Merge V8 5.1.281.59  DO NOT MERGE am: 85c91d5683
am: 5e33b08932  -s ours

Change-Id: I4f6c3b0a0153ef7001450eba906afecd0973fee3
diff --git a/AUTHORS b/AUTHORS
index 60b6c51..0618c69 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -40,6 +40,7 @@
 Andreas Anyuru <andreas.anyuru@gmail.com>
 Andrew Paprocki <andrew@ishiboo.com>
 Andrei Kashcha <anvaka@gmail.com>
+Anna Henningsen <addaleax@gmail.com>
 Bangfu Tao <bangfu.tao@samsung.com>
 Ben Noordhuis <info@bnoordhuis.nl>
 Benjamin Tan <demoneaux@gmail.com>
@@ -62,6 +63,7 @@
 Geoffrey Garside <ggarside@gmail.com>
 Han Choongwoo <cwhan.tunz@gmail.com>
 Hirofumi Mako <mkhrfm@gmail.com>
+Honggyu Kim <nexus226@gmail.com>
 Ioseb Dzmanashvili <ioseb.dzmanashvili@gmail.com>
 Isiah Meadows <impinball@gmail.com>
 Jan de Mooij <jandemooij@gmail.com>
@@ -90,6 +92,7 @@
 Milton Chiang <milton.chiang@mediatek.com>
 Myeong-bo Shim <m0609.shim@samsung.com>
 Nicolas Antonius Ernst Leopold Maria Kaiser <nikai@nikai.net>
+Oleksandr Chekhovskyi <oleksandr.chekhovskyi@gmail.com>
 Paolo Giarrusso <p.giarrusso@gmail.com>
 Patrick Gansterer <paroga@paroga.com>
 Peter Varga <pvarga@inf.u-szeged.hu>
diff --git a/Android.d8.mk b/Android.d8.mk
index fd2ff35..2dd0093 100644
--- a/Android.d8.mk
+++ b/Android.d8.mk
@@ -41,10 +41,18 @@
 
 LOCAL_CFLAGS := \
 	-DV8_I18N_SUPPORT \
+	-Wno-endif-labels \
+	-Wno-import \
+	-Wno-format \
 	-Wno-unused-parameter \
+	-Wno-sign-compare \
+	-Wno-missing-field-initializers \
 	-std=gnu++0x \
 	-O0
 
+# Bug: http://b/31101212  WAR LLVM bug until next Clang update
+LOCAL_CFLAGS_mips += -O2
+
 LOCAL_MODULE_TARGET_ARCH_WARN := $(V8_SUPPORTED_ARCH)
 
 include $(BUILD_EXECUTABLE)
diff --git a/Android.libv8.mk b/Android.libv8.mk
index 10d015e..7d10d33 100644
--- a/Android.libv8.mk
+++ b/Android.libv8.mk
@@ -90,6 +90,8 @@
 	-Wno-import \
 	-Wno-format \
 	-Wno-unused-parameter \
+	-Wno-sign-compare \
+	-Wno-missing-field-initializers \
 	-fno-exceptions \
 	-fvisibility=hidden \
 	-DENABLE_DEBUGGER_SUPPORT \
diff --git a/Android.v8common.mk b/Android.v8common.mk
index f921944..7f5232a 100644
--- a/Android.v8common.mk
+++ b/Android.v8common.mk
@@ -36,6 +36,7 @@
 	src/char-predicates.cc \
 	src/code-factory.cc \
 	src/codegen.cc \
+	src/code-stub-assembler.cc \
 	src/code-stubs.cc \
 	src/code-stubs-hydrogen.cc \
 	src/compilation-cache.cc \
@@ -51,11 +52,10 @@
 	src/compiler/bytecode-branch-analysis.cc \
 	src/compiler/bytecode-graph-builder.cc \
 	src/compiler.cc \
-	src/compiler/change-lowering.cc \
+	src/compiler/checkpoint-elimination.cc \
 	src/compiler/c-linkage.cc \
-	src/compiler/coalesced-live-ranges.cc \
+	src/compiler/code-assembler.cc \
 	src/compiler/code-generator.cc \
-	src/compiler/code-stub-assembler.cc \
 	src/compiler/common-node-cache.cc \
 	src/compiler/common-operator.cc \
 	src/compiler/common-operator-reducer.cc \
@@ -63,20 +63,18 @@
 	src/compiler/control-equivalence.cc \
 	src/compiler/control-flow-optimizer.cc \
 	src/compiler/dead-code-elimination.cc \
+	src/compiler/effect-control-linearizer.cc \
 	src/compiler/escape-analysis.cc \
 	src/compiler/escape-analysis-reducer.cc \
-	src/compiler/escape-analysis-reducer.h \
 	src/compiler/frame.cc \
 	src/compiler/frame-elider.cc \
 	src/compiler/frame-states.cc \
-	src/compiler/frame-states.h \
 	src/compiler/gap-resolver.cc \
 	src/compiler/graph.cc \
 	src/compiler/graph-reducer.cc \
 	src/compiler/graph-replay.cc \
 	src/compiler/graph-trimmer.cc \
 	src/compiler/graph-visualizer.cc \
-	src/compiler/greedy-allocator.cc \
 	src/compiler/instruction.cc \
 	src/compiler/instruction-scheduler.cc \
 	src/compiler/instruction-selector.cc \
@@ -104,6 +102,7 @@
 	src/compiler/loop-peeling.cc \
 	src/compiler/machine-operator.cc \
 	src/compiler/machine-operator-reducer.cc \
+	src/compiler/memory-optimizer.cc \
 	src/compiler/move-optimizer.cc \
 	src/compiler/node-cache.cc \
 	src/compiler/node.cc \
@@ -111,12 +110,14 @@
 	src/compiler/node-matchers.cc \
 	src/compiler/node-properties.cc \
 	src/compiler/opcodes.cc \
+	src/compiler/operation-typer.cc \
 	src/compiler/operator.cc \
 	src/compiler/operator-properties.cc \
 	src/compiler/osr.cc \
 	src/compiler/pipeline.cc \
 	src/compiler/pipeline-statistics.cc \
 	src/compiler/raw-machine-assembler.cc \
+	src/compiler/redundancy-elimination.cc \
 	src/compiler/register-allocator.cc \
 	src/compiler/register-allocator-verifier.cc \
 	src/compiler/representation-change.cc \
@@ -128,6 +129,7 @@
 	src/compiler/simplified-operator-reducer.cc \
 	src/compiler/source-position.cc \
 	src/compiler/state-values-utils.cc \
+	src/compiler/store-store-elimination.cc \
 	src/compiler/tail-call-optimization.cc \
 	src/compiler/type-hint-analyzer.cc \
 	src/compiler/type-hints.cc \
@@ -181,12 +183,14 @@
 	src/disassembler.cc \
 	src/diy-fp.cc \
 	src/dtoa.cc \
+	src/eh-frame.cc \
 	src/elements.cc \
 	src/elements-kind.cc \
 	src/execution.cc \
 	src/extensions/externalize-string-extension.cc \
 	src/extensions/free-buffer-extension.cc \
 	src/extensions/gc-extension.cc \
+	src/extensions/ignition-statistics-extension.cc \
 	src/extensions/statistics-extension.cc \
 	src/extensions/trigger-failure-extension.cc \
 	src/external-reference-table.cc \
@@ -230,8 +234,13 @@
 	src/interface-descriptors.cc \
 	src/interpreter/bytecode-array-builder.cc \
 	src/interpreter/bytecode-array-iterator.cc \
+	src/interpreter/bytecode-array-writer.cc \
+	src/interpreter/bytecode-dead-code-optimizer.cc \
 	src/interpreter/bytecode-generator.cc \
+	src/interpreter/bytecode-peephole-optimizer.cc \
+	src/interpreter/bytecode-pipeline.cc \
 	src/interpreter/bytecode-register-allocator.cc \
+	src/interpreter/bytecode-register-optimizer.cc \
 	src/interpreter/bytecodes.cc \
 	src/interpreter/constant-array-builder.cc \
 	src/interpreter/control-flow-builders.cc \
@@ -241,6 +250,8 @@
 	src/interpreter/interpreter-intrinsics.cc \
 	src/interpreter/source-position-table.cc \
 	src/isolate.cc \
+	src/json-parser.cc \
+	src/json-stringifier.cc \
 	src/keys.cc \
 	src/layout-descriptor.cc \
 	src/log.cc \
@@ -270,9 +281,10 @@
 	src/profiler/heap-profiler.cc \
 	src/profiler/heap-snapshot-generator.cc \
 	src/profiler/profile-generator.cc \
-	src/profiler/sampler.cc \
+	src/profiler/profiler-listener.cc \
 	src/profiler/sampling-heap-profiler.cc \
 	src/profiler/strings-storage.cc \
+	src/profiler/tick-sample.cc \
 	src/property.cc \
 	src/property-descriptor.cc \
 	src/regexp/interpreter-irregexp.cc \
@@ -300,13 +312,11 @@
 	src/runtime/runtime-i18n.cc \
 	src/runtime/runtime-internal.cc \
 	src/runtime/runtime-interpreter.cc \
-	src/runtime/runtime-json.cc \
 	src/runtime/runtime-literals.cc \
 	src/runtime/runtime-liveedit.cc \
 	src/runtime/runtime-maths.cc \
 	src/runtime/runtime-numbers.cc \
 	src/runtime/runtime-object.cc \
-	src/runtime/runtime-observe.cc \
 	src/runtime/runtime-operators.cc \
 	src/runtime/runtime-proxy.cc \
 	src/runtime/runtime-regexp.cc \
@@ -316,7 +326,6 @@
 	src/runtime/runtime-symbol.cc \
 	src/runtime/runtime-test.cc \
 	src/runtime/runtime-typedarray.cc \
-	src/runtime/runtime-uri.cc \
 	src/safepoint-table.cc \
 	src/snapshot/code-serializer.cc \
 	src/snapshot/deserializer.cc \
@@ -331,7 +340,6 @@
 	src/string-builder.cc \
 	src/string-stream.cc \
 	src/strtod.cc \
-	src/third_party/fdlibm/fdlibm.cc \
 	src/tracing/trace-event.cc \
 	src/transitions.cc \
 	src/type-cache.cc \
@@ -339,17 +347,23 @@
 	src/type-info.cc \
 	src/types.cc \
 	src/typing-asm.cc \
-	src/typing-reset.cc \
 	src/unicode.cc \
 	src/unicode-decoder.cc \
+	src/uri.cc \
 	src/utils.cc \
 	src/v8.cc \
 	src/v8threads.cc \
 	src/version.cc \
+	src/wasm/asm-types.cc \
 	src/wasm/asm-wasm-builder.cc \
 	src/wasm/ast-decoder.cc \
 	src/wasm/encoder.cc \
 	src/wasm/module-decoder.cc \
+	src/wasm/switch-logic.cc \
+	src/wasm/wasm-debug.cc \
+	src/wasm/wasm-external-refs.cc \
+	src/wasm/wasm-function-name-table.cc \
+	src/wasm/wasm-interpreter.cc \
 	src/wasm/wasm-js.cc \
 	src/wasm/wasm-module.cc \
 	src/wasm/wasm-opcodes.cc \
@@ -362,7 +376,9 @@
 	src/base/bits.cc \
 	src/base/cpu.cc \
 	src/base/division-by-constant.cc \
+	src/base/file-utils.cc \
 	src/base/functional.cc \
+	src/base/ieee754.cc \
 	src/base/logging.cc \
 	src/base/once.cc \
 	src/base/platform/condition-variable.cc \
@@ -377,6 +393,9 @@
 	src/libplatform/task-queue.cc \
 	src/libplatform/worker-thread.cc
 
+LOCAL_SRC_FILES += \
+	src/libsampler/v8-sampler.cc
+
 v8_local_src_files_arm := \
 	src/arm/assembler-arm.cc \
 	src/arm/builtins-arm.cc \
@@ -565,25 +584,21 @@
 	src/js/symbol.js \
 	src/js/array.js \
 	src/js/string.js \
-	src/js/uri.js \
 	src/js/math.js \
 	src/third_party/fdlibm/fdlibm.js \
 	src/js/regexp.js \
 	src/js/arraybuffer.js \
 	src/js/typedarray.js \
 	src/js/iterator-prototype.js \
-	src/js/generator.js \
-	src/js/object-observe.js \
 	src/js/collection.js \
 	src/js/weak-collection.js \
-	src/js/collection-iterator.js \
 	src/js/promise.js \
 	src/js/messages.js \
-	src/js/json.js \
 	src/js/array-iterator.js \
 	src/js/string-iterator.js \
 	src/js/templates.js \
 	src/js/spread.js \
+	src/js/proxy.js \
 	src/debug/mirrors.js \
 	src/debug/debug.js \
 	src/debug/liveedit.js \
@@ -592,14 +607,9 @@
 V8_LOCAL_JS_EXPERIMENTAL_LIBRARY_FILES := \
 	src/js/macros.py \
 	src/messages.h \
-	src/js/proxy.js \
-	src/js/generator.js \
 	src/js/harmony-atomics.js \
-	src/js/harmony-regexp-exec.js \
-	src/js/harmony-object-observe.js \
 	src/js/harmony-sharedarraybuffer.js \
 	src/js/harmony-simd.js \
-	src/js/harmony-species.js \
-	src/js/harmony-unicode-regexps.js \
 	src/js/harmony-string-padding.js \
-	src/js/promise-extra.js
+	src/js/promise-extra.js \
+	src/js/harmony-async-await.js
diff --git a/BUILD.gn b/BUILD.gn
index 28aca24..3121dce 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//build/config/android/config.gni")
 import("//build/config/arm.gni")
+import("//build/config/dcheck_always_on.gni")
 import("//build/config/mips.gni")
 import("//build/config/sanitizers/sanitizers.gni")
 
@@ -11,16 +12,49 @@
   import("//build/config/android/rules.gni")
 }
 
-# Because standalone V8 builds are not supported, assume this is part of a
-# Chromium build.
+import("gni/v8.gni")
+import("gni/isolate.gni")
 import("//build_overrides/v8.gni")
 
 import("snapshot_toolchain.gni")
 
 declare_args() {
-  # Enable the snapshot feature, for fast context creation.
-  # http://v8project.blogspot.com/2015/09/custom-startup-snapshots.html
-  v8_use_snapshot = true
+  # Sets -DVERIFY_HEAP.
+  v8_enable_verify_heap = false
+
+  # Enable compiler warnings when using V8_DEPRECATED apis.
+  v8_deprecation_warnings = false
+
+  # Enable compiler warnings when using V8_DEPRECATE_SOON apis.
+  v8_imminent_deprecation_warnings = false
+
+  # Sets -dENABLE_DISASSEMBLER.
+  v8_enable_disassembler = false
+
+  # Sets -dENABLE_GDB_JIT_INTERFACE.
+  v8_enable_gdbjit = false
+
+  # Sets -dENABLE_HANDLE_ZAPPING.
+  v8_enable_handle_zapping = is_debug
+
+  # Enable ECMAScript Internationalization API. Enabling this feature will
+  # add a dependency on the ICU library.
+  v8_enable_i18n_support = true
+
+  # Enable slow dchecks.
+  v8_enable_slow_dchecks = false
+
+  # Interpreted regexp engine exists as platform-independent alternative
+  # based where the regular expression is compiled to a bytecode.
+  v8_interpreted_regexp = false
+
+  # Sets -dOBJECT_PRINT.
+  v8_object_print = false
+
+  # With post mortem support enabled, metadata is embedded into libv8 that
+  # describes various parameters of the VM for use by debuggers. See
+  # tools/gen-postmortem-metadata.py for details.
+  v8_postmortem_support = false
 
   # Similar to vfp but on MIPS.
   v8_can_use_fpu_instructions = true
@@ -29,37 +63,8 @@
   v8_use_mips_abi_hardfloat = true
 }
 
-# TODO(jochen): These will need to be user-settable to support standalone V8
-# builds.
-v8_deprecation_warnings = false
-v8_enable_disassembler = false
-v8_enable_gdbjit = false
-v8_enable_handle_zapping = false
-v8_enable_i18n_support = true
-v8_enable_verify_heap = false
-v8_interpreted_regexp = false
-v8_object_print = false
-v8_postmortem_support = false
 v8_random_seed = "314159265"
-v8_toolset_for_d8 = "host"
-
-if (is_msan) {
-  # Running the V8-generated code on an ARM simulator is a powerful hack that
-  # allows the tool to see the memory accesses from JITted code. Without this
-  # flag, JS code causes false positive reports from MSan.
-  v8_target_arch = "arm64"
-} else {
-  v8_target_arch = target_cpu
-}
-
-if (v8_use_snapshot && v8_use_external_startup_data) {
-  snapshot_target = ":v8_external_snapshot"
-} else if (v8_use_snapshot) {
-  snapshot_target = ":v8_snapshot"
-} else {
-  assert(!v8_use_external_startup_data)
-  snapshot_target = ":v8_nosnapshot"
-}
+v8_toolset_for_shell = "host"
 
 ###############################################################################
 # Configurations
@@ -88,6 +93,11 @@
   include_dirs = [ "include" ]
 }
 
+# This config should be applied to code using the libsampler.
+config("libsampler_config") {
+  include_dirs = [ "include" ]
+}
+
 # This config should only be applied to code using V8 and not any V8 code
 # itself.
 config("external_config") {
@@ -98,6 +108,10 @@
     ]
   }
   include_dirs = [ "include" ]
+  libs = []
+  if (is_android && current_toolchain != host_toolchain) {
+    libs += [ "log" ]
+  }
 }
 
 # This config should only be applied to code that needs to be explicitly
@@ -113,31 +127,34 @@
 
   defines = []
 
-  if (v8_enable_disassembler == true) {
+  if (v8_enable_disassembler) {
     defines += [ "ENABLE_DISASSEMBLER" ]
   }
-  if (v8_enable_gdbjit == true) {
+  if (v8_enable_gdbjit) {
     defines += [ "ENABLE_GDB_JIT_INTERFACE" ]
   }
-  if (v8_object_print == true) {
+  if (v8_object_print) {
     defines += [ "OBJECT_PRINT" ]
   }
-  if (v8_enable_verify_heap == true) {
+  if (v8_enable_verify_heap) {
     defines += [ "VERIFY_HEAP" ]
   }
-  if (v8_interpreted_regexp == true) {
+  if (v8_interpreted_regexp) {
     defines += [ "V8_INTERPRETED_REGEXP" ]
   }
-  if (v8_deprecation_warnings == true) {
+  if (v8_deprecation_warnings) {
     defines += [ "V8_DEPRECATION_WARNINGS" ]
   }
-  if (v8_enable_i18n_support == true) {
+  if (v8_imminent_deprecation_warnings) {
+    defines += [ "V8_IMMINENT_DEPRECATION_WARNINGS" ]
+  }
+  if (v8_enable_i18n_support) {
     defines += [ "V8_I18N_SUPPORT" ]
   }
-  if (v8_enable_handle_zapping == true) {
+  if (v8_enable_handle_zapping) {
     defines += [ "ENABLE_HANDLE_ZAPPING" ]
   }
-  if (v8_use_external_startup_data == true) {
+  if (v8_use_external_startup_data) {
     defines += [ "V8_USE_EXTERNAL_STARTUP_DATA" ]
   }
 }
@@ -147,8 +164,9 @@
 
   defines = []
   cflags = []
+  ldflags = []
 
-  if (v8_target_arch == "arm") {
+  if (v8_target_cpu == "arm") {
     defines += [ "V8_TARGET_ARCH_ARM" ]
     if (arm_version == 7) {
       defines += [ "CAN_USE_ARMV7_INSTRUCTIONS" ]
@@ -167,6 +185,7 @@
         "CAN_USE_NEON",
       ]
     }
+
     # TODO(jochen): Add support for arm_test_noprobe.
 
     if (current_cpu != "arm") {
@@ -178,11 +197,12 @@
       }
     }
   }
-  if (v8_target_arch == "arm64") {
+  if (v8_target_cpu == "arm64") {
     defines += [ "V8_TARGET_ARCH_ARM64" ]
   }
+
   # TODO(jochen): Add support for mips.
-  if (v8_target_arch == "mipsel") {
+  if (v8_target_cpu == "mipsel") {
     defines += [ "V8_TARGET_ARCH_MIPS" ]
     if (v8_can_use_fpu_instructions) {
       defines += [ "CAN_USE_FPU_INSTRUCTIONS" ]
@@ -212,14 +232,17 @@
     } else if (mips_arch_variant == "r1") {
       defines += [ "FPU_MODE_FP32" ]
     }
+
     # TODO(jochen): Add support for mips_arch_variant rx and loongson.
   }
+
   # TODO(jochen): Add support for mips64.
-  if (v8_target_arch == "mips64el") {
+  if (v8_target_cpu == "mips64el") {
     defines += [ "V8_TARGET_ARCH_MIPS64" ]
     if (v8_can_use_fpu_instructions) {
       defines += [ "CAN_USE_FPU_INSTRUCTIONS" ]
     }
+
     # TODO(jochen): Add support for big endian host byteorder.
     defines += [ "V8_TARGET_ARCH_MIPS64_LE" ]
     if (v8_use_mips_abi_hardfloat) {
@@ -236,27 +259,33 @@
       defines += [ "_MIPS_ARCH_MIPS64R2" ]
     }
   }
-  if (v8_target_arch == "s390") {
+  if (v8_target_cpu == "s390" || v8_target_cpu == "s390x") {
     defines += [ "V8_TARGET_ARCH_S390" ]
-  } 
-  if (v8_target_arch == "s390x") {
-    defines += [
-      "V8_TARGET_ARCH_S390",
-      "V8_TARGET_ARCH_S390X",
-    ]
+    if (v8_target_cpu == "s390x") {
+      defines += [ "V8_TARGET_ARCH_S390X" ]
+    }
+    if (host_cpu == "x64" || host_cpu == "x86") {
+      defines += [ "V8_TARGET_ARCH_S390_LE_SIM" ]
+    }
   }
-  if (v8_target_arch == "x86") {
+  if (v8_target_cpu == "x86") {
     defines += [ "V8_TARGET_ARCH_IA32" ]
+    if (is_win) {
+      # Ensure no surprising artifacts from 80bit double math with x86.
+      cflags += [ "/arch:SSE2" ]
+    }
   }
-  if (v8_target_arch == "x64") {
+  if (v8_target_cpu == "x64") {
     defines += [ "V8_TARGET_ARCH_X64" ]
-  }
-     
-  if (is_win) {
-    defines += [ "WIN32" ]
-    # TODO(jochen): Support v8_enable_prof.
+    if (is_win) {
+      # Increase the initial stack size. The default is 1MB, this is 2MB. This
+      # applies only to executables and shared libraries produced by V8 since
+      # ldflags are not pushed to dependants.
+      ldflags += [ "/STACK:2097152" ]
+    }
   }
 
+  # TODO(jochen): Support v8_enable_prof on Windows.
   # TODO(jochen): Add support for compiling with simulators.
 
   if (is_debug) {
@@ -267,8 +296,13 @@
       "OBJECT_PRINT",
       "VERIFY_HEAP",
       "DEBUG",
-      "OPTIMIZED_DEBUG",
+      "TRACE_MAPS",
     ]
+    if (v8_enable_slow_dchecks) {
+      defines += [ "ENABLE_SLOW_DCHECKS" ]
+    }
+  } else if (dcheck_always_on) {
+    defines += [ "DEBUG" ]
   }
 }
 
@@ -297,21 +331,17 @@
     "src/js/symbol.js",
     "src/js/array.js",
     "src/js/string.js",
-    "src/js/uri.js",
     "src/js/math.js",
     "src/third_party/fdlibm/fdlibm.js",
     "src/js/regexp.js",
     "src/js/arraybuffer.js",
     "src/js/typedarray.js",
     "src/js/iterator-prototype.js",
-    "src/js/generator.js",
-    "src/js/object-observe.js",
     "src/js/collection.js",
     "src/js/weak-collection.js",
     "src/js/collection-iterator.js",
     "src/js/promise.js",
     "src/js/messages.js",
-    "src/js/json.js",
     "src/js/array-iterator.js",
     "src/js/string-iterator.js",
     "src/js/templates.js",
@@ -359,14 +389,10 @@
   sources = [
     "src/js/macros.py",
     "src/messages.h",
-    "src/js/generator.js",
+    "src/js/harmony-async-await.js",
     "src/js/harmony-atomics.js",
-    "src/js/harmony-regexp-exec.js",
-    "src/js/harmony-object-observe.js",
     "src/js/harmony-sharedarraybuffer.js",
     "src/js/harmony-simd.js",
-    "src/js/harmony-species.js",
-    "src/js/harmony-unicode-regexps.js",
     "src/js/harmony-string-padding.js",
     "src/js/promise-extra.js",
   ]
@@ -375,6 +401,13 @@
     "$target_gen_dir/experimental-libraries.cc",
   ]
 
+  if (v8_enable_i18n_support) {
+    sources += [
+      "src/js/icu-case-mapping.js",
+      "src/js/intl-extra.js",
+    ]
+  }
+
   args = [
            rebase_path("$target_gen_dir/experimental-libraries.cc",
                        root_build_dir),
@@ -479,8 +512,16 @@
       deps = [
         "//v8",
       ]
-      renaming_sources = v8_external_startup_data_renaming_sources
-      renaming_destinations = v8_external_startup_data_renaming_destinations
+      sources = [
+        "$root_out_dir/natives_blob.bin",
+      ]
+      renaming_sources = [ "$root_out_dir/snapshot_blob.bin" ]
+      if (current_cpu == "arm" || current_cpu == "x86" ||
+          current_cpu == "mipsel") {
+        renaming_destinations = [ "snapshot_blob_32.bin" ]
+      } else {
+        renaming_destinations = [ "snapshot_blob_64.bin" ]
+      }
       disable_compression = true
     }
   }
@@ -543,7 +584,7 @@
   visibility = [ ":*" ]  # Only targets in this file can depend on this.
 
   deps = [
-    ":mksnapshot($snapshot_toolchain)",
+    ":mksnapshot($v8_snapshot_toolchain)",
   ]
 
   script = "tools/run.py"
@@ -553,7 +594,7 @@
   ]
 
   args = [
-    "./" + rebase_path(get_label_info(":mksnapshot($snapshot_toolchain)",
+    "./" + rebase_path(get_label_info(":mksnapshot($v8_snapshot_toolchain)",
                                       "root_out_dir") + "/mksnapshot",
                        root_build_dir),
     "--startup_src",
@@ -580,7 +621,24 @@
 # Source Sets (aka static libraries)
 #
 
-source_set("v8_nosnapshot") {
+source_set("v8_maybe_snapshot") {
+  if (v8_use_snapshot && v8_use_external_startup_data) {
+    public_deps = [
+      ":v8_external_snapshot",
+    ]
+  } else if (v8_use_snapshot) {
+    public_deps = [
+      ":v8_snapshot",
+    ]
+  } else {
+    assert(!v8_use_external_startup_data)
+    public_deps = [
+      ":v8_nosnapshot",
+    ]
+  }
+}
+
+v8_source_set("v8_nosnapshot") {
   visibility = [ ":*" ]  # Only targets in this file can depend on this.
 
   deps = [
@@ -599,16 +657,10 @@
     "src/snapshot/snapshot-empty.cc",
   ]
 
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-  configs += [
-    ":internal_config",
-    ":features",
-    ":toolchain",
-  ]
+  configs = [ ":internal_config" ]
 }
 
-source_set("v8_snapshot") {
+v8_source_set("v8_snapshot") {
   # Only targets in this file and the top-level visibility target can
   # depend on this.
   visibility = [
@@ -637,17 +689,11 @@
     "$target_gen_dir/snapshot.cc",
   ]
 
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-  configs += [
-    ":internal_config",
-    ":features",
-    ":toolchain",
-  ]
+  configs = [ ":internal_config" ]
 }
 
 if (v8_use_external_startup_data) {
-  source_set("v8_external_snapshot") {
+  v8_source_set("v8_external_snapshot") {
     visibility = [ ":*" ]  # Only targets in this file can depend on this.
 
     deps = [
@@ -667,22 +713,15 @@
       "src/snapshot/snapshot-external.cc",
     ]
 
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    configs += [
-      ":internal_config",
-      ":features",
-      ":toolchain",
-    ]
+    configs = [ ":internal_config" ]
   }
 }
 
-source_set("v8_base") {
+v8_source_set("v8_base") {
   visibility = [ ":*" ]  # Only targets in this file can depend on this.
 
   sources = [
-    # TODO(fmeawad): This needs to be updated to support standalone V8 builds.
-    "../base/trace_event/common/trace_event_common.h",
+    "//base/trace_event/common/trace_event_common.h",
     "include/v8-debug.h",
     "include/v8-experimental.h",
     "include/v8-platform.h",
@@ -700,6 +739,7 @@
     "src/allocation-site-scopes.h",
     "src/allocation.cc",
     "src/allocation.h",
+    "src/api-arguments-inl.h",
     "src/api-arguments.cc",
     "src/api-arguments.h",
     "src/api-experimental.cc",
@@ -722,6 +762,7 @@
     "src/ast/ast-literal-reindexer.h",
     "src/ast/ast-numbering.cc",
     "src/ast/ast-numbering.h",
+    "src/ast/ast-type-bounds.h",
     "src/ast/ast-value-factory.cc",
     "src/ast/ast-value-factory.h",
     "src/ast/ast.cc",
@@ -736,7 +777,6 @@
     "src/ast/scopes.h",
     "src/ast/variables.cc",
     "src/ast/variables.h",
-    "src/atomic-utils.h",
     "src/background-parsing-task.cc",
     "src/background-parsing-task.h",
     "src/bailout-reason.cc",
@@ -761,8 +801,11 @@
     "src/char-predicates.cc",
     "src/char-predicates.h",
     "src/checks.h",
+    "src/code-events.h",
     "src/code-factory.cc",
     "src/code-factory.h",
+    "src/code-stub-assembler.cc",
+    "src/code-stub-assembler.h",
     "src/code-stubs-hydrogen.cc",
     "src/code-stubs.cc",
     "src/code-stubs.h",
@@ -796,15 +839,13 @@
     "src/compiler/bytecode-graph-builder.cc",
     "src/compiler/bytecode-graph-builder.h",
     "src/compiler/c-linkage.cc",
-    "src/compiler/change-lowering.cc",
-    "src/compiler/change-lowering.h",
-    "src/compiler/coalesced-live-ranges.cc",
-    "src/compiler/coalesced-live-ranges.h",
+    "src/compiler/checkpoint-elimination.cc",
+    "src/compiler/checkpoint-elimination.h",
+    "src/compiler/code-assembler.cc",
+    "src/compiler/code-assembler.h",
     "src/compiler/code-generator-impl.h",
     "src/compiler/code-generator.cc",
     "src/compiler/code-generator.h",
-    "src/compiler/code-stub-assembler.cc",
-    "src/compiler/code-stub-assembler.h",
     "src/compiler/common-node-cache.cc",
     "src/compiler/common-node-cache.h",
     "src/compiler/common-operator-reducer.cc",
@@ -820,6 +861,8 @@
     "src/compiler/dead-code-elimination.cc",
     "src/compiler/dead-code-elimination.h",
     "src/compiler/diamond.h",
+    "src/compiler/effect-control-linearizer.cc",
+    "src/compiler/effect-control-linearizer.h",
     "src/compiler/escape-analysis-reducer.cc",
     "src/compiler/escape-analysis-reducer.h",
     "src/compiler/escape-analysis.cc",
@@ -842,8 +885,6 @@
     "src/compiler/graph-visualizer.h",
     "src/compiler/graph.cc",
     "src/compiler/graph.h",
-    "src/compiler/greedy-allocator.cc",
-    "src/compiler/greedy-allocator.h",
     "src/compiler/instruction-codes.h",
     "src/compiler/instruction-scheduler.cc",
     "src/compiler/instruction-scheduler.h",
@@ -899,6 +940,8 @@
     "src/compiler/machine-operator-reducer.h",
     "src/compiler/machine-operator.cc",
     "src/compiler/machine-operator.h",
+    "src/compiler/memory-optimizer.cc",
+    "src/compiler/memory-optimizer.h",
     "src/compiler/move-optimizer.cc",
     "src/compiler/move-optimizer.h",
     "src/compiler/node-aux-data.h",
@@ -914,6 +957,8 @@
     "src/compiler/node.h",
     "src/compiler/opcodes.cc",
     "src/compiler/opcodes.h",
+    "src/compiler/operation-typer.cc",
+    "src/compiler/operation-typer.h",
     "src/compiler/operator-properties.cc",
     "src/compiler/operator-properties.h",
     "src/compiler/operator.cc",
@@ -926,6 +971,8 @@
     "src/compiler/pipeline.h",
     "src/compiler/raw-machine-assembler.cc",
     "src/compiler/raw-machine-assembler.h",
+    "src/compiler/redundancy-elimination.cc",
+    "src/compiler/redundancy-elimination.h",
     "src/compiler/register-allocator-verifier.cc",
     "src/compiler/register-allocator-verifier.h",
     "src/compiler/register-allocator.cc",
@@ -948,6 +995,8 @@
     "src/compiler/source-position.h",
     "src/compiler/state-values-utils.cc",
     "src/compiler/state-values-utils.h",
+    "src/compiler/store-store-elimination.cc",
+    "src/compiler/store-store-elimination.h",
     "src/compiler/tail-call-optimization.cc",
     "src/compiler/tail-call-optimization.h",
     "src/compiler/type-hint-analyzer.cc",
@@ -973,6 +1022,7 @@
     "src/conversions-inl.h",
     "src/conversions.cc",
     "src/conversions.h",
+    "src/counters-inl.h",
     "src/counters.cc",
     "src/counters.h",
     "src/crankshaft/compilation-phase.cc",
@@ -1063,6 +1113,8 @@
     "src/dtoa.cc",
     "src/dtoa.h",
     "src/effects.h",
+    "src/eh-frame.cc",
+    "src/eh-frame.h",
     "src/elements-kind.cc",
     "src/elements-kind.h",
     "src/elements.cc",
@@ -1075,6 +1127,8 @@
     "src/extensions/free-buffer-extension.h",
     "src/extensions/gc-extension.cc",
     "src/extensions/gc-extension.h",
+    "src/extensions/ignition-statistics-extension.cc",
+    "src/extensions/ignition-statistics-extension.h",
     "src/extensions/statistics-extension.cc",
     "src/extensions/statistics-extension.h",
     "src/extensions/trigger-failure-extension.cc",
@@ -1111,8 +1165,8 @@
     "src/handles-inl.h",
     "src/handles.cc",
     "src/handles.h",
-    "src/hashmap.h",
     "src/heap-symbols.h",
+    "src/heap/array-buffer-tracker-inl.h",
     "src/heap/array-buffer-tracker.cc",
     "src/heap/array-buffer-tracker.h",
     "src/heap/gc-idle-time-handler.cc",
@@ -1177,10 +1231,21 @@
     "src/interpreter/bytecode-array-builder.h",
     "src/interpreter/bytecode-array-iterator.cc",
     "src/interpreter/bytecode-array-iterator.h",
+    "src/interpreter/bytecode-array-writer.cc",
+    "src/interpreter/bytecode-array-writer.h",
+    "src/interpreter/bytecode-dead-code-optimizer.cc",
+    "src/interpreter/bytecode-dead-code-optimizer.h",
     "src/interpreter/bytecode-generator.cc",
     "src/interpreter/bytecode-generator.h",
+    "src/interpreter/bytecode-label.h",
+    "src/interpreter/bytecode-peephole-optimizer.cc",
+    "src/interpreter/bytecode-peephole-optimizer.h",
+    "src/interpreter/bytecode-pipeline.cc",
+    "src/interpreter/bytecode-pipeline.h",
     "src/interpreter/bytecode-register-allocator.cc",
     "src/interpreter/bytecode-register-allocator.h",
+    "src/interpreter/bytecode-register-optimizer.cc",
+    "src/interpreter/bytecode-register-optimizer.h",
     "src/interpreter/bytecode-traits.h",
     "src/interpreter/bytecodes.cc",
     "src/interpreter/bytecodes.h",
@@ -1201,7 +1266,9 @@
     "src/isolate-inl.h",
     "src/isolate.cc",
     "src/isolate.h",
+    "src/json-parser.cc",
     "src/json-parser.h",
+    "src/json-stringifier.cc",
     "src/json-stringifier.h",
     "src/keys.cc",
     "src/keys.h",
@@ -1275,12 +1342,14 @@
     "src/profiler/profile-generator-inl.h",
     "src/profiler/profile-generator.cc",
     "src/profiler/profile-generator.h",
-    "src/profiler/sampler.cc",
-    "src/profiler/sampler.h",
+    "src/profiler/profiler-listener.cc",
+    "src/profiler/profiler-listener.h",
     "src/profiler/sampling-heap-profiler.cc",
     "src/profiler/sampling-heap-profiler.h",
     "src/profiler/strings-storage.cc",
     "src/profiler/strings-storage.h",
+    "src/profiler/tick-sample.cc",
+    "src/profiler/tick-sample.h",
     "src/profiler/unbound-queue-inl.h",
     "src/profiler/unbound-queue.h",
     "src/property-descriptor.cc",
@@ -1326,13 +1395,11 @@
     "src/runtime/runtime-i18n.cc",
     "src/runtime/runtime-internal.cc",
     "src/runtime/runtime-interpreter.cc",
-    "src/runtime/runtime-json.cc",
     "src/runtime/runtime-literals.cc",
     "src/runtime/runtime-liveedit.cc",
     "src/runtime/runtime-maths.cc",
     "src/runtime/runtime-numbers.cc",
     "src/runtime/runtime-object.cc",
-    "src/runtime/runtime-observe.cc",
     "src/runtime/runtime-operators.cc",
     "src/runtime/runtime-proxy.cc",
     "src/runtime/runtime-regexp.cc",
@@ -1342,7 +1409,6 @@
     "src/runtime/runtime-symbol.cc",
     "src/runtime/runtime-test.cc",
     "src/runtime/runtime-typedarray.cc",
-    "src/runtime/runtime-uri.cc",
     "src/runtime/runtime-utils.h",
     "src/runtime/runtime.cc",
     "src/runtime/runtime.h",
@@ -1381,8 +1447,6 @@
     "src/string-stream.h",
     "src/strtod.cc",
     "src/strtod.h",
-    "src/third_party/fdlibm/fdlibm.cc",
-    "src/third_party/fdlibm/fdlibm.h",
     "src/tracing/trace-event.cc",
     "src/tracing/trace-event.h",
     "src/transitions-inl.h",
@@ -1399,8 +1463,6 @@
     "src/types.h",
     "src/typing-asm.cc",
     "src/typing-asm.h",
-    "src/typing-reset.cc",
-    "src/typing-reset.h",
     "src/unicode-cache-inl.h",
     "src/unicode-cache.h",
     "src/unicode-decoder.cc",
@@ -1408,6 +1470,8 @@
     "src/unicode-inl.h",
     "src/unicode.cc",
     "src/unicode.h",
+    "src/uri.cc",
+    "src/uri.h",
     "src/utils-inl.h",
     "src/utils.cc",
     "src/utils.h",
@@ -1420,6 +1484,8 @@
     "src/version.h",
     "src/vm-state-inl.h",
     "src/vm-state.h",
+    "src/wasm/asm-types.cc",
+    "src/wasm/asm-types.h",
     "src/wasm/asm-wasm-builder.cc",
     "src/wasm/asm-wasm-builder.h",
     "src/wasm/ast-decoder.cc",
@@ -1427,9 +1493,19 @@
     "src/wasm/decoder.h",
     "src/wasm/encoder.cc",
     "src/wasm/encoder.h",
+    "src/wasm/leb-helper.h",
     "src/wasm/module-decoder.cc",
     "src/wasm/module-decoder.h",
+    "src/wasm/switch-logic.cc",
+    "src/wasm/switch-logic.h",
+    "src/wasm/wasm-debug.cc",
+    "src/wasm/wasm-debug.h",
+    "src/wasm/wasm-external-refs.cc",
     "src/wasm/wasm-external-refs.h",
+    "src/wasm/wasm-function-name-table.cc",
+    "src/wasm/wasm-function-name-table.h",
+    "src/wasm/wasm-interpreter.cc",
+    "src/wasm/wasm-interpreter.h",
     "src/wasm/wasm-js.cc",
     "src/wasm/wasm-js.h",
     "src/wasm/wasm-macro-gen.h",
@@ -1445,7 +1521,7 @@
     "src/zone.h",
   ]
 
-  if (v8_target_arch == "x86") {
+  if (v8_target_cpu == "x86") {
     sources += [
       "src/compiler/ia32/code-generator-ia32.cc",
       "src/compiler/ia32/instruction-codes-ia32.h",
@@ -1483,7 +1559,7 @@
       "src/regexp/ia32/regexp-macro-assembler-ia32.cc",
       "src/regexp/ia32/regexp-macro-assembler-ia32.h",
     ]
-  } else if (v8_target_arch == "x64") {
+  } else if (v8_target_cpu == "x64") {
     sources += [
       "src/compiler/x64/code-generator-x64.cc",
       "src/compiler/x64/instruction-codes-x64.h",
@@ -1521,7 +1597,7 @@
       "src/x64/macro-assembler-x64.cc",
       "src/x64/macro-assembler-x64.h",
     ]
-  } else if (v8_target_arch == "arm") {
+  } else if (v8_target_cpu == "arm") {
     sources += [
       "src/arm/assembler-arm-inl.h",
       "src/arm/assembler-arm.cc",
@@ -1564,7 +1640,7 @@
       "src/regexp/arm/regexp-macro-assembler-arm.cc",
       "src/regexp/arm/regexp-macro-assembler-arm.h",
     ]
-  } else if (v8_target_arch == "arm64") {
+  } else if (v8_target_cpu == "arm64") {
     sources += [
       "src/arm64/assembler-arm64-inl.h",
       "src/arm64/assembler-arm64.cc",
@@ -1620,7 +1696,7 @@
       "src/regexp/arm64/regexp-macro-assembler-arm64.cc",
       "src/regexp/arm64/regexp-macro-assembler-arm64.h",
     ]
-  } else if (v8_target_arch == "mipsel") {
+  } else if (v8_target_cpu == "mipsel") {
     sources += [
       "src/compiler/mips/code-generator-mips.cc",
       "src/compiler/mips/instruction-codes-mips.h",
@@ -1662,12 +1738,12 @@
       "src/regexp/mips/regexp-macro-assembler-mips.cc",
       "src/regexp/mips/regexp-macro-assembler-mips.h",
     ]
-  } else if (v8_target_arch == "mips64el") {
+  } else if (v8_target_cpu == "mips64el") {
     sources += [
-      "compiler/mips64/code-generator-mips64.cc",
-      "compiler/mips64/instruction-codes-mips64.h",
-      "compiler/mips64/instruction-scheduler-mips64.cc",
-      "compiler/mips64/instruction-selector-mips64.cc",
+      "src/compiler/mips64/code-generator-mips64.cc",
+      "src/compiler/mips64/instruction-codes-mips64.h",
+      "src/compiler/mips64/instruction-scheduler-mips64.cc",
+      "src/compiler/mips64/instruction-selector-mips64.cc",
       "src/crankshaft/mips64/lithium-codegen-mips64.cc",
       "src/crankshaft/mips64/lithium-codegen-mips64.h",
       "src/crankshaft/mips64/lithium-gap-resolver-mips64.cc",
@@ -1704,7 +1780,7 @@
       "src/regexp/mips64/regexp-macro-assembler-mips64.cc",
       "src/regexp/mips64/regexp-macro-assembler-mips64.h",
     ]
-  } else if (v8_target_arch == "s390" || v8_target_arch == "s390x") {
+  } else if (v8_target_cpu == "s390" || v8_target_cpu == "s390x") {
     sources += [
       "src/compiler/s390/code-generator-s390.cc",
       "src/compiler/s390/instruction-codes-s390.h",
@@ -1748,22 +1824,12 @@
     ]
   }
 
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-  configs += [
-    ":internal_config",
-    ":features",
-    ":toolchain",
-  ]
-
-  if (!is_debug) {
-    configs -= [ "//build/config/compiler:default_optimization" ]
-    configs += [ "//build/config/compiler:optimize_max" ]
-  }
+  configs = [ ":internal_config" ]
 
   defines = []
   deps = [
     ":v8_libbase",
+    ":v8_libsampler",
   ]
 
   if (is_win) {
@@ -1776,9 +1842,6 @@
     if (is_win) {
       deps += [ "//third_party/icu:icudata" ]
     }
-
-    # TODO(jochen): Add support for icu_use_data_file_flag
-    defines += [ "ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE" ]
   } else {
     sources -= [
       "src/i18n.cc",
@@ -1792,13 +1855,14 @@
   }
 }
 
-source_set("v8_libbase") {
+v8_source_set("v8_libbase") {
   visibility = [ ":*" ]  # Only targets in this file can depend on this.
 
   sources = [
     "src/base/accounting-allocator.cc",
     "src/base/accounting-allocator.h",
     "src/base/adapters.h",
+    "src/base/atomic-utils.h",
     "src/base/atomicops.h",
     "src/base/atomicops_internals_arm64_gcc.h",
     "src/base/atomicops_internals_arm_gcc.h",
@@ -1819,9 +1883,15 @@
     "src/base/cpu.h",
     "src/base/division-by-constant.cc",
     "src/base/division-by-constant.h",
+    "src/base/file-utils.cc",
+    "src/base/file-utils.h",
     "src/base/flags.h",
+    "src/base/format-macros.h",
     "src/base/functional.cc",
     "src/base/functional.h",
+    "src/base/hashmap.h",
+    "src/base/ieee754.cc",
+    "src/base/ieee754.h",
     "src/base/iterator.h",
     "src/base/lazy-instance.h",
     "src/base/logging.cc",
@@ -1850,18 +1920,7 @@
     "src/base/utils/random-number-generator.h",
   ]
 
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-  configs += [
-    ":internal_config_base",
-    ":features",
-    ":toolchain",
-  ]
-
-  if (!is_debug) {
-    configs -= [ "//build/config/compiler:default_optimization" ]
-    configs += [ "//build/config/compiler:optimize_max" ]
-  }
+  configs = [ ":internal_config_base" ]
 
   defines = []
 
@@ -1910,7 +1969,7 @@
   # TODO(jochen): Add support for qnx, freebsd, openbsd, netbsd, and solaris.
 }
 
-source_set("v8_libplatform") {
+v8_source_set("v8_libplatform") {
   sources = [
     "include/libplatform/libplatform.h",
     "src/libplatform/default-platform.cc",
@@ -1921,25 +1980,31 @@
     "src/libplatform/worker-thread.h",
   ]
 
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-  configs += [
-    ":internal_config_base",
-    ":features",
-    ":toolchain",
-  ]
+  configs = [ ":internal_config_base" ]
 
-  if (!is_debug) {
-    configs -= [ "//build/config/compiler:default_optimization" ]
-    configs += [ "//build/config/compiler:optimize_max" ]
-  }
+  public_configs = [ ":libplatform_config" ]
 
   deps = [
     ":v8_libbase",
   ]
 }
 
-source_set("fuzzer_support") {
+v8_source_set("v8_libsampler") {
+  sources = [
+    "src/libsampler/v8-sampler.cc",
+    "src/libsampler/v8-sampler.h",
+  ]
+
+  configs = [ ":internal_config_base" ]
+
+  public_configs = [ ":libsampler_config" ]
+
+  deps = [
+    ":v8_libbase",
+  ]
+}
+
+v8_source_set("fuzzer_support") {
   visibility = [ ":*" ]  # Only targets in this file can depend on this.
 
   sources = [
@@ -1947,47 +2012,45 @@
     "test/fuzzer/fuzzer-support.h",
   ]
 
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-  configs += [
-    ":internal_config_base",
-    ":libplatform_config",
-    ":features",
-    ":toolchain",
-  ]
+  configs = [ ":internal_config_base" ]
 
   deps = [
-    ":v8_libplatform",
-    snapshot_target,
+    ":v8_maybe_snapshot",
   ]
+
+  public_deps = [
+    ":v8_libplatform",
+  ]
+}
+
+v8_source_set("simple_fuzzer") {
+  sources = [
+    "test/fuzzer/fuzzer.cc",
+  ]
+
+  configs = [ ":internal_config_base" ]
 }
 
 ###############################################################################
 # Executables
 #
 
-if (current_toolchain == snapshot_toolchain) {
-  executable("mksnapshot") {
+if (current_toolchain == v8_snapshot_toolchain) {
+  v8_executable("mksnapshot") {
     visibility = [ ":*" ]  # Only targets in this file can depend on this.
 
     sources = [
       "src/snapshot/mksnapshot.cc",
     ]
 
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    configs += [
-      ":internal_config",
-      ":libplatform_config",
-      ":features",
-      ":toolchain",
-    ]
+    configs = [ ":internal_config" ]
 
     deps = [
       ":v8_base",
       ":v8_libplatform",
       ":v8_nosnapshot",
       "//build/config/sanitizers:deps",
+      "//build/win:default_exe_manifest",
     ]
   }
 }
@@ -1996,87 +2059,227 @@
 # Public targets
 #
 
+want_v8_shell =
+    (current_toolchain == host_toolchain && v8_toolset_for_shell == "host") ||
+    (current_toolchain == v8_snapshot_toolchain &&
+     v8_toolset_for_shell == "host") ||
+    (current_toolchain != host_toolchain && v8_toolset_for_shell == "target")
+
+group("gn_all") {
+  testonly = true
+
+  deps = [
+    ":d8",
+    ":v8_hello_world",
+    ":v8_parser_shell",
+    ":v8_sample_process",
+    ":v8_simple_json_fuzzer",
+    ":v8_simple_parser_fuzzer",
+    ":v8_simple_regexp_fuzzer",
+    ":v8_simple_wasm_asmjs_fuzzer",
+    ":v8_simple_wasm_fuzzer",
+    "test:gn_all",
+    "tools:gn_all",
+  ]
+
+  if (want_v8_shell) {
+    deps += [ ":v8_shell" ]
+  }
+
+  if (v8_test_isolation_mode != "noop") {
+    deps += [ ":d8_run" ]
+  }
+}
+
 if (is_component_build) {
-  component("v8") {
+  v8_component("v8") {
     sources = [
       "src/v8dll-main.cc",
     ]
 
     public_deps = [
       ":v8_base",
-      snapshot_target,
+      ":v8_maybe_snapshot",
     ]
 
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    configs += [
-      ":internal_config",
-      ":features",
-      ":toolchain",
-    ]
+    configs = [ ":internal_config" ]
 
     public_configs = [ ":external_config" ]
-
-    libs = []
-    if (is_android && current_toolchain != host_toolchain) {
-      libs += [ "log" ]
-    }
   }
 } else {
   group("v8") {
     public_deps = [
       ":v8_base",
-      snapshot_target,
+      ":v8_maybe_snapshot",
     ]
     public_configs = [ ":external_config" ]
   }
 }
 
-if ((current_toolchain == host_toolchain && v8_toolset_for_d8 == "host") ||
-    (current_toolchain == snapshot_toolchain && v8_toolset_for_d8 == "host") ||
-    (current_toolchain != host_toolchain && v8_toolset_for_d8 == "target")) {
-  executable("d8") {
+v8_executable("d8") {
+  sources = [
+    "src/d8.cc",
+    "src/d8.h",
+  ]
+
+  configs = [
+    # Note: don't use :internal_config here because this target will get
+    # the :external_config applied to it by virtue of depending on :v8, and
+    # you can't have both applied to the same target.
+    ":internal_config_base",
+  ]
+
+  deps = [
+    ":d8_js2c",
+    ":v8",
+    ":v8_libplatform",
+    "//build/config/sanitizers:deps",
+    "//build/win:default_exe_manifest",
+  ]
+
+  # TODO(jochen): Add support for vtunejit.
+
+  if (is_posix) {
+    sources += [ "src/d8-posix.cc" ]
+  } else if (is_win) {
+    sources += [ "src/d8-windows.cc" ]
+  }
+
+  if (!is_component_build) {
+    sources += [ "$target_gen_dir/d8-js.cc" ]
+  }
+  if (v8_enable_i18n_support) {
+    deps += [ "//third_party/icu" ]
+  }
+}
+
+v8_isolate_run("d8") {
+  deps = [
+    ":d8",
+  ]
+
+  isolate = "//src/d8.isolate"
+}
+
+v8_executable("v8_hello_world") {
+  sources = [
+    "samples/hello-world.cc",
+  ]
+
+  configs = [
+    # Note: don't use :internal_config here because this target will get
+    # the :external_config applied to it by virtue of depending on :v8, and
+    # you can't have both applied to the same target.
+    ":internal_config_base",
+  ]
+
+  deps = [
+    ":v8",
+    ":v8_libplatform",
+    "//build/config/sanitizers:deps",
+    "//build/win:default_exe_manifest",
+  ]
+
+  if (v8_enable_i18n_support) {
+    deps += [ "//third_party/icu" ]
+  }
+}
+
+v8_executable("v8_sample_process") {
+  sources = [
+    "samples/process.cc",
+  ]
+
+  configs = [
+    # Note: don't use :internal_config here because this target will get
+    # the :external_config applied to it by virtue of depending on :v8, and
+    # you can't have both applied to the same target.
+    ":internal_config_base",
+  ]
+
+  deps = [
+    ":v8",
+    ":v8_libplatform",
+    "//build/config/sanitizers:deps",
+    "//build/win:default_exe_manifest",
+  ]
+
+  if (v8_enable_i18n_support) {
+    deps += [ "//third_party/icu" ]
+  }
+}
+
+v8_executable("v8_parser_shell") {
+  sources = [
+    "tools/parser-shell.cc",
+    "tools/shell-utils.h",
+  ]
+
+  configs = [
+    ":external_config",
+    ":internal_config_base",
+  ]
+
+  deps = [
+    ":v8_libplatform",
+    "//build/config/sanitizers:deps",
+    "//build/win:default_exe_manifest",
+  ]
+
+  if (is_component_build) {
+    # v8_parser_shell can't be built against a shared library, so we
+    # need to depend on the underlying static target in that case.
+    deps += [ ":v8_maybe_snapshot" ]
+  } else {
+    deps += [ ":v8" ]
+  }
+
+  if (v8_enable_i18n_support) {
+    deps += [ "//third_party/icu" ]
+  }
+}
+
+if (want_v8_shell) {
+  v8_executable("v8_shell") {
     sources = [
-      "src/d8.cc",
-      "src/d8.h",
+      "samples/shell.cc",
     ]
 
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    configs += [
+    configs = [
       # Note: don't use :internal_config here because this target will get
       # the :external_config applied to it by virtue of depending on :v8, and
       # you can't have both applied to the same target.
       ":internal_config_base",
-      ":features",
-      ":toolchain",
     ]
 
     deps = [
-      ":d8_js2c",
       ":v8",
       ":v8_libplatform",
       "//build/config/sanitizers:deps",
+      "//build/win:default_exe_manifest",
     ]
 
-    # TODO(jochen): Add support for vtunejit.
-
-    if (is_posix) {
-      sources += [ "src/d8-posix.cc" ]
-    } else if (is_win) {
-      sources += [ "src/d8-windows.cc" ]
-    }
-
-    if (!is_component_build) {
-      sources += [ "$target_gen_dir/d8-js.cc" ]
-    }
     if (v8_enable_i18n_support) {
       deps += [ "//third_party/icu" ]
     }
   }
 }
 
-source_set("json_fuzzer") {
+template("v8_fuzzer") {
+  name = target_name
+  forward_variables_from(invoker, "*")
+  v8_executable("v8_simple_" + name) {
+    deps = [
+      ":" + name,
+      ":simple_fuzzer",
+      "//build/win:default_exe_manifest",
+    ]
+
+    configs = [ ":external_config" ]
+  }
+}
+
+v8_source_set("json_fuzzer") {
   sources = [
     "test/fuzzer/json.cc",
   ]
@@ -2085,17 +2288,13 @@
     ":fuzzer_support",
   ]
 
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-  configs += [
-    ":internal_config",
-    ":libplatform_config",
-    ":features",
-    ":toolchain",
-  ]
+  configs = [ ":internal_config" ]
 }
 
-source_set("parser_fuzzer") {
+v8_fuzzer("json_fuzzer") {
+}
+
+v8_source_set("parser_fuzzer") {
   sources = [
     "test/fuzzer/parser.cc",
   ]
@@ -2104,17 +2303,13 @@
     ":fuzzer_support",
   ]
 
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-  configs += [
-    ":internal_config",
-    ":libplatform_config",
-    ":features",
-    ":toolchain",
-  ]
+  configs = [ ":internal_config" ]
 }
 
-source_set("regexp_fuzzer") {
+v8_fuzzer("parser_fuzzer") {
+}
+
+v8_source_set("regexp_fuzzer") {
   sources = [
     "test/fuzzer/regexp.cc",
   ]
@@ -2123,17 +2318,13 @@
     ":fuzzer_support",
   ]
 
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-  configs += [
-    ":internal_config",
-    ":libplatform_config",
-    ":features",
-    ":toolchain",
-  ]
+  configs = [ ":internal_config" ]
 }
 
-source_set("wasm_fuzzer") {
+v8_fuzzer("regexp_fuzzer") {
+}
+
+v8_source_set("wasm_fuzzer") {
   sources = [
     "test/fuzzer/wasm.cc",
   ]
@@ -2142,17 +2333,13 @@
     ":fuzzer_support",
   ]
 
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-  configs += [
-    ":internal_config",
-    ":libplatform_config",
-    ":features",
-    ":toolchain",
-  ]
+  configs = [ ":internal_config" ]
 }
 
-source_set("wasm_asmjs_fuzzer") {
+v8_fuzzer("wasm_fuzzer") {
+}
+
+v8_source_set("wasm_asmjs_fuzzer") {
   sources = [
     "test/fuzzer/wasm-asmjs.cc",
   ]
@@ -2161,12 +2348,8 @@
     ":fuzzer_support",
   ]
 
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
-  configs += [
-    ":internal_config",
-    ":libplatform_config",
-    ":features",
-    ":toolchain",
-  ]
+  configs = [ ":internal_config" ]
+}
+
+v8_fuzzer("wasm_asmjs_fuzzer") {
 }
diff --git a/ChangeLog b/ChangeLog
index dc97b80..2245195 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,2145 +1,3470 @@
-2016-04-06: Version 5.1.281
+2016-06-27: Version 5.3.332
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-05: Version 5.1.280
+2016-06-27: Version 5.3.331
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-05: Version 5.1.279
+2016-06-27: Version 5.3.330
 
-        Ship --harmony-regexp-exec (issue 4602).
+        [stubs] Implementing CodeStubAssembler::GetOwnProperty() (issue 4911).
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-05: Version 5.1.278
+2016-06-27: Version 5.3.329
 
-        [V8] Removed debugger V8::PromiseEvent (Chromium issue 526811).
+        Performance and stability improvements on all platforms.
 
-        [asm.js] Fix typing bug for non-literals in heap access (Chromium issue
-        599825).
 
-        Ensure CreateDataProperty works correctly on TypedArrays (Chromium issue
-        596394).
+2016-06-27: Version 5.3.328
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-05: Version 5.1.277
+2016-06-27: Version 5.3.327
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-05: Version 5.1.276
+2016-06-27: Version 5.3.326
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-05: Version 5.1.275
+2016-06-27: Version 5.3.325
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-05: Version 5.1.274
+2016-06-26: Version 5.3.324
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-05: Version 5.1.273
+2016-06-26: Version 5.3.323
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-05: Version 5.1.272
+2016-06-26: Version 5.3.322
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-05: Version 5.1.271
+2016-06-26: Version 5.3.321
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-04: Version 5.1.270
+2016-06-24: Version 5.3.320
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-04: Version 5.1.269
+2016-06-24: Version 5.3.319
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-04: Version 5.1.268
+2016-06-24: Version 5.3.318
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-04: Version 5.1.267
+2016-06-24: Version 5.3.317
+
+        Performance and stability improvements on all platforms.
+
 
-        [api] Restrict Template::Set to take templates or primitive values.
+2016-06-24: Version 5.3.316
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-04: Version 5.1.266
+2016-06-23: Version 5.3.315
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-04: Version 5.1.265
+2016-06-23: Version 5.3.314
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-04: Version 5.1.264
+2016-06-23: Version 5.3.313
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-04: Version 5.1.263
+2016-06-23: Version 5.3.312
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-04: Version 5.1.262
+2016-06-22: Version 5.3.311
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-04: Version 5.1.261
+2016-06-22: Version 5.3.310
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-04: Version 5.1.260
+2016-06-22: Version 5.3.309
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-04: Version 5.1.259
+2016-06-22: Version 5.3.308
+
+        Performance and stability improvements on all platforms.
+
 
-        Further ES2015 RegExp spec compliance fixes (issue 4602).
+2016-06-22: Version 5.3.307
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-03: Version 5.1.258
+2016-06-22: Version 5.3.306
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-02: Version 5.1.257
+2016-06-22: Version 5.3.305
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-02: Version 5.1.256
+2016-06-22: Version 5.3.304
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-02: Version 5.1.255
+2016-06-22: Version 5.3.303
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-01: Version 5.1.254
+2016-06-22: Version 5.3.302
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-01: Version 5.1.253
+2016-06-22: Version 5.3.301
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-01: Version 5.1.252
+2016-06-22: Version 5.3.300
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-01: Version 5.1.251
+2016-06-22: Version 5.3.299
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-01: Version 5.1.250
+2016-06-22: Version 5.3.298
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-22: Version 5.3.297
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-22: Version 5.3.296
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-22: Version 5.3.295
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-22: Version 5.3.294
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-22: Version 5.3.293
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-22: Version 5.3.292
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-21: Version 5.3.291
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-21: Version 5.3.290
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-21: Version 5.3.289
+
+        Reland: change most cases of variable redeclaration from TypeError to
+        SyntaxError (issue 4955).
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-21: Version 5.3.288
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-21: Version 5.3.287
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-21: Version 5.3.286
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-21: Version 5.3.285
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-21: Version 5.3.284
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-21: Version 5.3.283
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-21: Version 5.3.282
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-21: Version 5.3.281
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-21: Version 5.3.280
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.279
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.278
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.277
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.276
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.275
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.274
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.273
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.272
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.271
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.270
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.269
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.268
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.267
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.266
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.265
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.264
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.263
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.262
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.261
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.260
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.259
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.258
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-20: Version 5.3.257
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-17: Version 5.3.256
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-17: Version 5.3.255
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-17: Version 5.3.254
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-17: Version 5.3.253
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-17: Version 5.3.252
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-17: Version 5.3.251
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-17: Version 5.3.250
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-16: Version 5.3.249
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-16: Version 5.3.248
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-16: Version 5.3.247
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-16: Version 5.3.246
+
+        [es8] Unstage syntactic tail calls (issue 4915).
+
+        [ic] LoadICState cleanup (Chromium issue 576312).
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-16: Version 5.3.245
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-16: Version 5.3.244
+
+        [ic] Remove --new-load-global-ic switch (Chromium issue 576312).
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-16: Version 5.3.243
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-16: Version 5.3.242
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-16: Version 5.3.241
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-15: Version 5.3.240
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-15: Version 5.3.239
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-15: Version 5.3.238
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-15: Version 5.3.237
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-15: Version 5.3.236
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-15: Version 5.3.235
+
+        [ic] Enable new LoadGlobalIC machinery (Chromium issue 576312).
+
+        [ic] LoadGlobalIC is now able to cache PropertyCells in the feedback
+        vector (Chromium issue 576312).
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-15: Version 5.3.234
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-15: Version 5.3.233
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-15: Version 5.3.232
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-15: Version 5.3.231
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-15: Version 5.3.230
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-14: Version 5.3.229
+
+        [stubs] Ensure that StoreTransitionStub does not bailout after the
+        properties backing store is enlarged (Chromium issue 601420).
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-14: Version 5.3.228
+
+        [ic] Split LoadIC into LoadGlobalIC and LoadIC (Chromium issue 576312).
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-14: Version 5.3.227
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-14: Version 5.3.226
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-13: Version 5.3.225
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-13: Version 5.3.224
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-13: Version 5.3.223
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-13: Version 5.3.222
+
+        change most cases of variable redeclaration from TypeError to
+        SyntaxError (issue 4955).
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-13: Version 5.3.221
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-13: Version 5.3.220
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-13: Version 5.3.219
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-13: Version 5.3.218
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-13: Version 5.3.217
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-13: Version 5.3.216
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-12: Version 5.3.215
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-12: Version 5.3.214
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-10: Version 5.3.213
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-10: Version 5.3.212
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-10: Version 5.3.211
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-10: Version 5.3.210
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-10: Version 5.3.209
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-10: Version 5.3.208
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-10: Version 5.3.207
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-10: Version 5.3.206
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-10: Version 5.3.205
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-10: Version 5.3.204
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-10: Version 5.3.203
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-10: Version 5.3.202
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-10: Version 5.3.201
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-09: Version 5.3.200
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-09: Version 5.3.199
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-09: Version 5.3.198
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-09: Version 5.3.197
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-09: Version 5.3.196
+
+        [ic] [stubs] Remove InlineCacheState field from the code flags (Chromium
+        issue 618701).
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-09: Version 5.3.195
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-09: Version 5.3.194
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-09: Version 5.3.193
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-09: Version 5.3.192
+
+        [build] Use icu data file by default (Chromium issue 616033).
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-09: Version 5.3.191
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-09: Version 5.3.190
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-09: Version 5.3.189
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-09: Version 5.3.188
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.187
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.186
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.185
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.184
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.183
+
+        [build] Use sysroot for linux compilation with clang (Chromium issues
+        474921, 616032).
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.182
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.181
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.180
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.179
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.178
+
+        [icu] Support loading data file from default location (Chromium issue
+        616033).
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.177
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.176
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.175
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.174
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.173
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.172
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-08: Version 5.3.171
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.170
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.169
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.168
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.167
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.166
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.165
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.164
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.163
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.162
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.161
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.160
+
+        [runtime] Don't use ElementsTransitionAndStoreStub for transitions that
+        involve instance rewriting (issue 5009, Chromium issue 617524).
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.159
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.158
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.157
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.156
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.155
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-07: Version 5.3.154
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-06: Version 5.3.153
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-06: Version 5.3.152
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-06: Version 5.3.151
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-06: Version 5.3.150
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-06: Version 5.3.149
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-06: Version 5.3.148
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-06: Version 5.3.147
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-06: Version 5.3.146
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-06: Version 5.3.145
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-06: Version 5.3.144
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-06: Version 5.3.143
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-06: Version 5.3.142
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-06: Version 5.3.141
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-06: Version 5.3.140
+
+        [build] Use sysroot for linux compilation with clang (Chromium issues
+        474921, 616032).
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-05: Version 5.3.139
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-04: Version 5.3.138
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.137
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.136
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.135
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.134
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.133
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.132
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.131
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.130
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.129
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.128
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.127
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.126
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.125
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.124
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.123
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.122
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-03: Version 5.3.121
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-02: Version 5.3.120
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-02: Version 5.3.119
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-02: Version 5.3.118
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-02: Version 5.3.117
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-02: Version 5.3.116
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-02: Version 5.3.115
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-02: Version 5.3.114
+
+        [stubs] Extend HasProperty stub with dictionary-mode, string wrapper and
+        double-elements objects support (issue 2743).
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-02: Version 5.3.113
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-02: Version 5.3.112
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-02: Version 5.3.111
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-02: Version 5.3.110
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-02: Version 5.3.109
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-02: Version 5.3.108
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-02: Version 5.3.107
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-01: Version 5.3.106
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-01: Version 5.3.105
+
+        Extend HasProperty stub with dictionary-mode, string wrapper and double-
+        elements objects support (issue 2743).
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-01: Version 5.3.104
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-01: Version 5.3.103
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-01: Version 5.3.102
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-01: Version 5.3.101
+
+        [runtime] Ensure that all elements kind transitions are chained to the
+        root map (issue 5009).
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-01: Version 5.3.100
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-01: Version 5.3.99
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-01: Version 5.3.98
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-01: Version 5.3.97
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-01: Version 5.3.96
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-01: Version 5.3.95
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-01: Version 5.3.94
+
+        Performance and stability improvements on all platforms.
+
+
+2016-06-01: Version 5.3.93
+
+        Performance and stability improvements on all platforms.
+
+
+2016-05-31: Version 5.3.92
+
+        Performance and stability improvements on all platforms.
+
+
+2016-05-31: Version 5.3.91
+
+        Performance and stability improvements on all platforms.
+
+
+2016-05-31: Version 5.3.90
+
+        Performance and stability improvements on all platforms.
+
+
+2016-05-31: Version 5.3.89
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-01: Version 5.1.249
+2016-05-31: Version 5.3.88
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-01: Version 5.1.248
+2016-05-31: Version 5.3.87
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-01: Version 5.1.247
+2016-05-31: Version 5.3.86
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-01: Version 5.1.246
+2016-05-31: Version 5.3.85
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-01: Version 5.1.245
+2016-05-31: Version 5.3.84
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-01: Version 5.1.244
+2016-05-31: Version 5.3.83
 
         Performance and stability improvements on all platforms.
 
 
-2016-04-01: Version 5.1.243
+2016-05-30: Version 5.3.82
 
         Performance and stability improvements on all platforms.
 
 
+2016-05-30: Version 5.3.81
+
-2016-04-01: Version 5.1.242
+        [api] Remove deprectated memory allocation callback API (issue 4813).
 
         Performance and stability improvements on all platforms.
 
+
+2016-05-30: Version 5.3.80
 
-2016-04-01: Version 5.1.241
+        Performance and stability improvements on all platforms.
 
-        [GN] Define USE_EABI_HARDFLOAT=1 when arm_float_abi=="hard" (Chromium
-        issue 592660).
 
-        Ship --harmony-regexp-exec (issue 4602).
+2016-05-30: Version 5.3.79
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.240
+2016-05-30: Version 5.3.78
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.239
+2016-05-30: Version 5.3.77
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.238
+2016-05-30: Version 5.3.76
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.237
+2016-05-30: Version 5.3.75
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.236
+2016-05-30: Version 5.3.74
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.235
+2016-05-30: Version 5.3.73
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.234
+2016-05-30: Version 5.3.72
+
+        Performance and stability improvements on all platforms.
+
 
-        [arm/Linux] Don't rely on KUSER_HELPERS feature (Chromium issue 599051).
+2016-05-30: Version 5.3.71
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.233
+2016-05-30: Version 5.3.70
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.232
+2016-05-30: Version 5.3.69
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.231
+2016-05-30: Version 5.3.68
 
-        Turn scavenge_reclaim_unmodified_objects on by default (Chromium issue
-        4880).
+        Performance and stability improvements on all platforms.
+
+
+2016-05-29: Version 5.3.67
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.230
+2016-05-28: Version 5.3.66
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.229
+2016-05-28: Version 5.3.65
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.228
+2016-05-27: Version 5.3.64
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.227
+2016-05-27: Version 5.3.63
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.226
+2016-05-27: Version 5.3.62
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.225
+2016-05-27: Version 5.3.61
 
         Performance and stability improvements on all platforms.
 
+
+2016-05-27: Version 5.3.60
+
+        Performance and stability improvements on all platforms.
 
-2016-03-31: Version 5.1.224
 
-        Raise minimum Mac OS version to 10.7 (issue 4847).
+2016-05-27: Version 5.3.59
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-31: Version 5.1.223
+2016-05-27: Version 5.3.58
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-30: Version 5.1.222
+2016-05-27: Version 5.3.57
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-30: Version 5.1.221
+2016-05-26: Version 5.3.56
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-30: Version 5.1.220
+2016-05-26: Version 5.3.55
 
-        Stage --harmony-regexp-exec (issue 4602).
+        Performance and stability improvements on all platforms.
 
-        Add fast paths for native RegExps in ES2015 subclass-aware code (issue
-        4602).
 
-        [V8] Add FunctionMirror.prototype.contextDebugId method (Chromium issue
-        595206).
+2016-05-26: Version 5.3.54
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-30: Version 5.1.219
+2016-05-26: Version 5.3.53
 
-        Remove RegExp.prototype.source getter compat workaround (issue 4827,
-        Chromium issue 581577).
+        Performance and stability improvements on all platforms.
 
-        Check for proper types from error handling code (Chromium issue 596718).
 
-        Add ES2015 RegExp full subclassing semantics behind a flag (issue 4602).
+2016-05-25: Version 5.3.52
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-24: Version 5.1.218
+2016-05-25: Version 5.3.51
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-24: Version 5.1.217
+2016-05-25: Version 5.3.50
+
+        TypedArray: Make byteOffset, byteLength, and length configurable (issue
+        4902).
 
-        [esnext] implement String padding proposal.
+        Make %ThrowTypeError% function(s) strict (issue 4925).
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-24: Version 5.1.216
+2016-05-25: Version 5.3.49
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-24: Version 5.1.215
+2016-05-25: Version 5.3.48
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-24: Version 5.1.214
+2016-05-25: Version 5.3.47
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-23: Version 5.1.213
+2016-05-25: Version 5.3.46
+
+        Performance and stability improvements on all platforms.
+
 
-        Implement ES2015 labelled function declaration restrictions (Chromium
-        issue 595309).
+2016-05-25: Version 5.3.45
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-23: Version 5.1.212
+2016-05-25: Version 5.3.44
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-23: Version 5.1.211
+2016-05-25: Version 5.3.43
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-23: Version 5.1.210
+2016-05-25: Version 5.3.42
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-23: Version 5.1.209
+2016-05-25: Version 5.3.41
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-23: Version 5.1.208
+2016-05-25: Version 5.3.40
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-23: Version 5.1.207
+2016-05-25: Version 5.3.39
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-23: Version 5.1.206
+2016-05-24: Version 5.3.38
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-23: Version 5.1.205
+2016-05-24: Version 5.3.37
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-23: Version 5.1.204
+2016-05-24: Version 5.3.36
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-23: Version 5.1.203
+2016-05-24: Version 5.3.35
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-23: Version 5.1.202
+2016-05-24: Version 5.3.34
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-23: Version 5.1.201
+2016-05-24: Version 5.3.33
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-23: Version 5.1.200
+2016-05-24: Version 5.3.32
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-22: Version 5.1.199
+2016-05-24: Version 5.3.31
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-22: Version 5.1.198
+2016-05-24: Version 5.3.30
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-22: Version 5.1.197
+2016-05-24: Version 5.3.29
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-22: Version 5.1.196
+2016-05-24: Version 5.3.28
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-22: Version 5.1.195
+2016-05-24: Version 5.3.27
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-22: Version 5.1.194
+2016-05-24: Version 5.3.26
 
-        Fix match default behavior on strings for ES2015 semantics (issue 4602).
+        Performance and stability improvements on all platforms.
+
+
+2016-05-24: Version 5.3.25
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-22: Version 5.1.193
+2016-05-24: Version 5.3.24
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-22: Version 5.1.192
+2016-05-24: Version 5.3.23
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-22: Version 5.1.191
+2016-05-24: Version 5.3.22
 
-        [Interpreter] TurboFan implementation of intrinsics (issue 4822).
+        Performance and stability improvements on all platforms.
+
+
+2016-05-23: Version 5.3.21
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-22: Version 5.1.190
+2016-05-23: Version 5.3.20
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-21: Version 5.1.189
+2016-05-23: Version 5.3.19
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-21: Version 5.1.188
+2016-05-23: Version 5.3.18
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-21: Version 5.1.187
+2016-05-23: Version 5.3.17
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-21: Version 5.1.186
+2016-05-23: Version 5.3.16
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-21: Version 5.1.185
+2016-05-23: Version 5.3.15
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-21: Version 5.1.184
+2016-05-23: Version 5.3.14
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-21: Version 5.1.183
+2016-05-23: Version 5.3.13
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-21: Version 5.1.182
+2016-05-23: Version 5.3.12
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-21: Version 5.1.181
+2016-05-23: Version 5.3.11
+
+        Performance and stability improvements on all platforms.
+
 
-        Temporarily undeprecate ForceSet (Chromium issue 595601).
+2016-05-23: Version 5.3.10
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-21: Version 5.1.180
+2016-05-23: Version 5.3.9
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-20: Version 5.1.179
+2016-05-21: Version 5.3.8
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-20: Version 5.1.178
+2016-05-21: Version 5.3.7
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-20: Version 5.1.177
+2016-05-21: Version 5.3.6
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-19: Version 5.1.176
+2016-05-20: Version 5.3.5
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-18: Version 5.1.175
+2016-05-20: Version 5.3.4
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-18: Version 5.1.174
+2016-05-20: Version 5.3.3
+
+        Move case conversion with ICU to 'staged' (issues 4476, 4477).
 
         Performance and stability improvements on all platforms.
 
+
+2016-05-20: Version 5.3.2
+
+        Performance and stability improvements on all platforms.
 
-2016-03-18: Version 5.1.173
 
-        Parser: Make skipping HTML comments optional (Chromium issue 573887).
+2016-05-20: Version 5.3.1
 
-        [es7] implement exponentiation operator proposal (issue 3915).
+        Move case conversion with ICU to 'staged' (issues 4476, 4477).
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-18: Version 5.1.172
+2016-05-19: Version 5.2.371
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-18: Version 5.1.171
+2016-05-19: Version 5.2.370
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-18: Version 5.1.170
+2016-05-19: Version 5.2.369
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-18: Version 5.1.169
+2016-05-19: Version 5.2.368
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.168
+2016-05-18: Version 5.2.367
 
         Performance and stability improvements on all platforms.
 
+
+2016-05-18: Version 5.2.366
+
+        Performance and stability improvements on all platforms.
 
-2016-03-17: Version 5.1.167
 
-        Throw the right exceptions from setting elements in
-        Array.prototype.concat (Chromium issue 595319).
+2016-05-18: Version 5.2.365
 
         Performance and stability improvements on all platforms.
 
+
+2016-05-18: Version 5.2.364
+
+        Performance and stability improvements on all platforms.
 
-2016-03-17: Version 5.1.166
 
-        Throw exceptions from CreateDataProperty when should_throw (Chromium
-        issue 595319).
+2016-05-18: Version 5.2.363
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.165
+2016-05-18: Version 5.2.362
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.164
+2016-05-18: Version 5.2.361
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.163
+2016-05-18: Version 5.2.360
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.162
+2016-05-18: Version 5.2.359
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.161
+2016-05-18: Version 5.2.358
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.160
+2016-05-18: Version 5.2.357
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.159
+2016-05-18: Version 5.2.356
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.158
+2016-05-18: Version 5.2.355
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.157
+2016-05-18: Version 5.2.354
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.156
+2016-05-18: Version 5.2.353
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.155
+2016-05-18: Version 5.2.352
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.154
+2016-05-18: Version 5.2.351
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.153
+2016-05-18: Version 5.2.350
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.152
+2016-05-18: Version 5.2.349
 
         Performance and stability improvements on all platforms.
 
+
+2016-05-18: Version 5.2.348
+
+        Performance and stability improvements on all platforms.
 
-2016-03-17: Version 5.1.151
 
-        Move FastAccessorAssembler from RawMachineAssembler to CodeStubAssembler
-        (Chromium issue 508898).
+2016-05-17: Version 5.2.347
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.150
+2016-05-17: Version 5.2.346
+
+        Performance and stability improvements on all platforms.
+
 
-        [serializer] Add API to warm up startup snapshot with an additional
-        script (issue 4836).
+2016-05-17: Version 5.2.345
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.149
+2016-05-17: Version 5.2.344
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.148
+2016-05-17: Version 5.2.343
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-17: Version 5.1.147
+2016-05-17: Version 5.2.342
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-16: Version 5.1.146
+2016-05-17: Version 5.2.341
+
+        Performance and stability improvements on all platforms.
+
 
-        Ship ES2015 restrictions on function declaration locations (issue 4824).
+2016-05-17: Version 5.2.340
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-16: Version 5.1.145
+2016-05-17: Version 5.2.339
+
+        [wasm] remove extra nops in asm-wasm (issue 4203).
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-16: Version 5.1.144
+2016-05-17: Version 5.2.338
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-16: Version 5.1.143
+2016-05-17: Version 5.2.337
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-16: Version 5.1.142
+2016-05-17: Version 5.2.336
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-16: Version 5.1.141
+2016-05-17: Version 5.2.335
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-16: Version 5.1.140
+2016-05-17: Version 5.2.334
+
+        Performance and stability improvements on all platforms.
+
 
-        Put RegExp js code in strict mode (issue 4504).
+2016-05-17: Version 5.2.333
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-15: Version 5.1.139
+2016-05-17: Version 5.2.332
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-15: Version 5.1.138
+2016-05-16: Version 5.2.331
 
-        [builtins] Fix Array.prototype.concat bug (Chromium issue 594574).
+        Performance and stability improvements on all platforms.
+
+
+2016-05-16: Version 5.2.330
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-15: Version 5.1.137
+2016-05-16: Version 5.2.329
 
         Performance and stability improvements on all platforms.
 
+
+2016-05-16: Version 5.2.328
+
+        Add UseCounter for decimal with leading zero (issue 4973).
 
-2016-03-15: Version 5.1.136
+        [esnext] implement frontend changes for async/await proposal (issue
+        4483).
 
         Performance and stability improvements on all platforms.
 
+
+2016-05-16: Version 5.2.327
+
+        Performance and stability improvements on all platforms.
 
-2016-03-15: Version 5.1.135
 
-        Ship Array.prototype.values (issue 4247).
+2016-05-15: Version 5.2.326
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-15: Version 5.1.134
+2016-05-14: Version 5.2.325
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-15: Version 5.1.133
+2016-05-14: Version 5.2.324
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-15: Version 5.1.132
+2016-05-13: Version 5.2.323
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-15: Version 5.1.131
+2016-05-13: Version 5.2.322
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-15: Version 5.1.130
+2016-05-13: Version 5.2.321
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-15: Version 5.1.129
+2016-05-13: Version 5.2.320
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-15: Version 5.1.128
+2016-05-13: Version 5.2.319
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-14: Version 5.1.127
+2016-05-13: Version 5.2.318
 
         Performance and stability improvements on all platforms.
 
+
+2016-05-13: Version 5.2.317
+
+        Performance and stability improvements on all platforms.
 
-2016-03-14: Version 5.1.126
 
-        Remove --harmony-modules flag and let embedder decide when modules are
-        used (issue 1569, Chromium issue 594639).
+2016-05-13: Version 5.2.316
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-14: Version 5.1.125
+2016-05-13: Version 5.2.315
 
-        Make test262 test runner check for which exception is thrown (issue
-        4803).
+        Performance and stability improvements on all platforms.
+
+
+2016-05-13: Version 5.2.314
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-14: Version 5.1.124
+2016-05-13: Version 5.2.313
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-14: Version 5.1.123
+2016-05-13: Version 5.2.312
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-14: Version 5.1.122
+2016-05-13: Version 5.2.311
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-14: Version 5.1.121
+2016-05-13: Version 5.2.310
+
+        [api] Clarify expectations of ArrayBuffer::Allocator in API (Chromium
+        issue 611688).
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-14: Version 5.1.120
+2016-05-13: Version 5.2.309
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-14: Version 5.1.119
+2016-05-13: Version 5.2.308
 
         Performance and stability improvements on all platforms.
 
 
+2016-05-13: Version 5.2.307
+
-2016-03-13: Version 5.1.118
+        In parallel to the strict octal check that would reject `012` in strict
+        mode, this patch collects UseCounters for `089` in strict mode. The spec
+        says this should be an error, but this patch does not report it as such
+        (issue 4973).
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-11: Version 5.1.117
+2016-05-12: Version 5.2.306
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-11: Version 5.1.116
+2016-05-12: Version 5.2.305
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-11: Version 5.1.115
+2016-05-12: Version 5.2.304
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-11: Version 5.1.114
+2016-05-12: Version 5.2.303
 
-        [arm64] Fix i/d cache line size confusion typo (Chromium issue 593867).
+        Performance and stability improvements on all platforms.
+
+
+2016-05-12: Version 5.2.302
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-11: Version 5.1.113
+2016-05-12: Version 5.2.301
+
+        Performance and stability improvements on all platforms.
+
 
-        Fix expression positions for for-loops (issue 4690).
+2016-05-12: Version 5.2.300
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-11: Version 5.1.112
+2016-05-12: Version 5.2.299
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-11: Version 5.1.111
+2016-05-12: Version 5.2.298
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-10: Version 5.1.110
+2016-05-12: Version 5.2.297
 
-        Minor library function fixes for TypedArray spec compliance (issue
-        4785).
+        Performance and stability improvements on all platforms.
 
-        Check that Promise subclasses have callable resolve/reject (issue 4633).
+
+2016-05-12: Version 5.2.296
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-10: Version 5.1.109
+2016-05-12: Version 5.2.295
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-10: Version 5.1.108
+2016-05-11: Version 5.2.294
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-10: Version 5.1.107
+2016-05-11: Version 5.2.293
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-10: Version 5.1.106
+2016-05-11: Version 5.2.292
 
         Performance and stability improvements on all platforms.
 
+
+2016-05-11: Version 5.2.291
 
-2016-03-10: Version 5.1.105
+        Use ICU case conversion/transliterator for case conversion (issues 4476,
+        4477).
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-10: Version 5.1.104
+2016-05-11: Version 5.2.290
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-10: Version 5.1.103
+2016-05-11: Version 5.2.289
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-10: Version 5.1.102
+2016-05-11: Version 5.2.288
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-10: Version 5.1.101
+2016-05-11: Version 5.2.287
 
         Performance and stability improvements on all platforms.
 
+
+2016-05-11: Version 5.2.286
+
+        Performance and stability improvements on all platforms.
 
-2016-03-10: Version 5.1.100
 
-        [strong] Remove all remainders of strong mode (issue 3956).
+2016-05-11: Version 5.2.285
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-10: Version 5.1.99
+2016-05-11: Version 5.2.284
+
+        Performance and stability improvements on all platforms.
+
 
-        Marks the label associated with the runtime call in
-        CodeStubAssembler::Allocate as deferred (Chromium issue 593359).
+2016-05-10: Version 5.2.283
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-10: Version 5.1.98
+2016-05-10: Version 5.2.282
 
-        Implement iterator finalization in array destructuring (issue 3566).
+        Fix Map::AsArray to properly iterate over the backing store (issue
+        4946).
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-10: Version 5.1.97
+2016-05-10: Version 5.2.281
+
+        Remove LOG line checking from presubmit.
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-10: Version 5.1.96
+2016-05-10: Version 5.2.280
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-10: Version 5.1.95
+2016-05-10: Version 5.2.279
 
-        String.prototype[Symbol.iterator] does RequireObjectCoercible(this)
-        (issue 4348).
+        Performance and stability improvements on all platforms.
 
-        Stage restrictive declarations flag (issue 4824).
 
-        Expose Array.prototype.values behind a flag and stage it (issue 4247).
+2016-05-10: Version 5.2.278
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-09: Version 5.1.94
+2016-05-10: Version 5.2.277
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-09: Version 5.1.93
+2016-05-10: Version 5.2.276
 
-        Ensure appropriate bounds checking for Array subclass concat (Chromium
-        issue 592340).
+        Performance and stability improvements on all platforms.
+
+
+2016-05-10: Version 5.2.275
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-09: Version 5.1.92
+2016-05-10: Version 5.2.274
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-09: Version 5.1.91
+2016-05-10: Version 5.2.273
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-09: Version 5.1.90
+2016-05-10: Version 5.2.272
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-09: Version 5.1.89
+2016-05-10: Version 5.2.271
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-09: Version 5.1.88
+2016-05-10: Version 5.2.270
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-09: Version 5.1.87
+2016-05-10: Version 5.2.269
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-09: Version 5.1.86
+2016-05-10: Version 5.2.268
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-09: Version 5.1.85
+2016-05-10: Version 5.2.267
+
+        Various species micro-optimizations (Chromium issue 609739).
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-09: Version 5.1.84
+2016-05-09: Version 5.2.266
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-08: Version 5.1.83
+2016-05-09: Version 5.2.265
 
         Performance and stability improvements on all platforms.
 
 
+2016-05-09: Version 5.2.264
+
-2016-03-08: Version 5.1.82
+        Fix TypedArray Property optimizations (Chromium issue 593634).
 
         Performance and stability improvements on all platforms.
 
+
+2016-05-09: Version 5.2.263
 
-2016-03-08: Version 5.1.81
+        Performance and stability improvements on all platforms.
 
-        Optimize new TypedArray(typedArray) constructor (Chromium issue 592007).
 
-        Ensure the @@species protector is updated for accessors (issue 4093).
+2016-05-09: Version 5.2.262
 
-        Add UseCounters for various RegExp compatibility issues (Chromium issue
-        581577).
+        [V8] Add v8::Value::TypeOf to API (Chromium issue 595206).
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-08: Version 5.1.80
+2016-05-09: Version 5.2.261
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-08: Version 5.1.79
+2016-05-09: Version 5.2.260
 
         Performance and stability improvements on all platforms.
 
+
+2016-05-09: Version 5.2.259
 
-2016-03-08: Version 5.1.78
+        Expose IsConstructor to the C++ API (issue 4993).
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-08: Version 5.1.77
+2016-05-09: Version 5.2.258
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-08: Version 5.1.76
+2016-05-09: Version 5.2.257
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-08: Version 5.1.75
+2016-05-09: Version 5.2.256
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-08: Version 5.1.74
+2016-05-09: Version 5.2.255
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-08: Version 5.1.73
+2016-05-09: Version 5.2.254
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-08: Version 5.1.72
+2016-05-08: Version 5.2.253
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-08: Version 5.1.71
+2016-05-07: Version 5.2.252
+
+        fix Set::AsArray to not leave undefined holes in output array (issue
+        4946).
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-07: Version 5.1.70
+2016-05-06: Version 5.2.251
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-07: Version 5.1.69
+2016-05-06: Version 5.2.250
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-07: Version 5.1.68
+2016-05-06: Version 5.2.249
 
-        [key-accumulator] Starting to reimplement the key-accumulator (issue
-        4758, Chromium issue 545503).
+        Performance and stability improvements on all platforms.
+
+
+2016-05-06: Version 5.2.248
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-07: Version 5.1.67
+2016-05-06: Version 5.2.247
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-07: Version 5.1.66
+2016-05-06: Version 5.2.246
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-07: Version 5.1.65
+2016-05-06: Version 5.2.245
 
-        [key-accumulator] Starting to reimplement the key-accumulator (issue
-        4758, Chromium issue 545503).
+        Performance and stability improvements on all platforms.
+
+
+2016-05-06: Version 5.2.244
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-07: Version 5.1.64
+2016-05-06: Version 5.2.243
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-07: Version 5.1.63
+2016-05-04: Version 5.2.242
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-07: Version 5.1.62
+2016-05-04: Version 5.2.241
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-07: Version 5.1.61
+2016-05-04: Version 5.2.240
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-07: Version 5.1.60
+2016-05-04: Version 5.2.239
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-07: Version 5.1.59
+2016-05-04: Version 5.2.238
 
-        Use v8::kGCCallbackFlagCollectAllAvailableGarbage in
-        Heap::CollectAllAvailableGarbage (Chromium issue 591463).
+        Performance and stability improvements on all platforms.
+
 
-        [key-accumulator] Starting to reimplement the key-accumulator (issue
-        4758, Chromium issue 545503).
+2016-05-04: Version 5.2.237
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-07: Version 5.1.58
+2016-05-04: Version 5.2.236
 
-        [regexp] Fix off-by-one in CharacterRange::Negate (Chromium issue
-        592343).
+        S390: Add HasProperty code stub that tries simple lookups or jumps to
+        runtime otherwise (issue 2743).
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-07: Version 5.1.57
+2016-05-04: Version 5.2.235
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-07: Version 5.1.56
+2016-05-04: Version 5.2.234
 
-        Use v8::kGCCallbackFlagCollectAllAvailableGarbage in
-        Heap::CollectAllAvailableGarbage (Chromium issue 591463).
+        Make array __proto__ manipulations not disturb the species protector
+        (Chromium issue 606207).
+
+        Add v8::Object::GetOwnPropertyNames(context, filter) method (issue 3861,
+        Chromium issue 581495).
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-06: Version 5.1.55
+2016-05-04: Version 5.2.233
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-06: Version 5.1.54
+2016-05-04: Version 5.2.232
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-04: Version 5.1.53
+2016-05-04: Version 5.2.231
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-04: Version 5.1.52
+2016-05-04: Version 5.2.230
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-04: Version 5.1.51
+2016-05-04: Version 5.2.229
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-04: Version 5.1.50
+2016-05-04: Version 5.2.228
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-04: Version 5.1.49
+2016-05-04: Version 5.2.227
+
+        MIPS64: Fix [turbofan] Length and index2 are unsigned in
+        CheckedLoad/CheckedStore (Chromium issue 599717).
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-04: Version 5.1.48
+2016-05-04: Version 5.2.226
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-04: Version 5.1.47
+2016-05-04: Version 5.2.225
 
         Performance and stability improvements on all platforms.
 
+
+2016-05-04: Version 5.2.224
+
+        Performance and stability improvements on all platforms.
 
-2016-03-04: Version 5.1.46
 
-        Introduce v8::MicrotasksScope (Chromium issue 585949).
+2016-05-04: Version 5.2.223
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-04: Version 5.1.45
+2016-05-04: Version 5.2.222
+
+        Performance and stability improvements on all platforms.
+
+
+2016-05-04: Version 5.2.221
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-04: Version 5.1.44
+2016-05-04: Version 5.2.220
 
-        Use a different GCCallbackFlag for GCs triggered by
-        CollectAllAvailableGarbage (Chromium issue 591463).
+        [wasm] Fix for 608630: allow proxies as FFI (Chromium issue 608630).
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-04: Version 5.1.43
+2016-05-04: Version 5.2.219
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-04: Version 5.1.42
+2016-05-03: Version 5.2.218
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-04: Version 5.1.41
+2016-05-03: Version 5.2.217
 
         Performance and stability improvements on all platforms.
 
+
+2016-05-03: Version 5.2.216
+
+        [wasm] Disallow runtime calls in asm.js modules (Chromium issue 592352).
+
+        [API] remove (deprecated) hidden properties.
+
+        [wasm] Fix bug with empty input to Wasm.instantiateModuleFromAsm()
+        (Chromium issue 605488).
+
+        Add HasProperty code stub that tries simple lookups or jumps to runtime
+        otherwise (issue 2743).
 
-2016-03-04: Version 5.1.40
+        Fix ExternalTwobyteStringUtf16CharacterStream::PushBack(kEndOfInput)
+        (Chromium issue 607903).
 
         Performance and stability improvements on all platforms.
 
 
+2016-05-03: Version 5.2.215
+
-2016-03-04: Version 5.1.39
+        Performance and stability improvements on all platforms.
 
-        Ship ES2015 Function.name reform (issue 3699, Chromium issue 588803).
 
-        Introduce v8::MicrotasksScope (Chromium issue 585949).
+2016-05-03: Version 5.2.214
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-04: Version 5.1.38
+2016-05-03: Version 5.2.213
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-03: Version 5.1.37
+2016-05-03: Version 5.2.212
+
+        Performance and stability improvements on all platforms.
+
 
-        Restrict FunctionDeclarations in Statement position (issue 4647).
+2016-05-03: Version 5.2.211
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-03: Version 5.1.36
+2016-05-02: Version 5.2.210
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-03: Version 5.1.35
+2016-05-02: Version 5.2.209
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-03: Version 5.1.34
+2016-05-02: Version 5.2.208
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-03: Version 5.1.33
+2016-05-02: Version 5.2.207
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-03: Version 5.1.32
+2016-05-02: Version 5.2.206
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-03: Version 5.1.31
+2016-05-02: Version 5.2.205
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-03: Version 5.1.30
+2016-05-02: Version 5.2.204
 
-        Implement TypedArray(typedarray) constructor (issue 4726).
+        [debugger] Add JSProxy support in Runtime::GetInternalProperties
+        (Chromium issue 588705).
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-02: Version 5.1.29
+2016-05-02: Version 5.2.203
 
         Performance and stability improvements on all platforms.
 
+
+2016-05-02: Version 5.2.202
+
+        Performance and stability improvements on all platforms.
 
-2016-03-02: Version 5.1.28
 
-        [turbofan] Adds an Allocate macro to the CodeStubAssembler (Chromium
-        issue 588692).
+2016-05-02: Version 5.2.201
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-02: Version 5.1.27
+2016-05-02: Version 5.2.200
+
+        Performance and stability improvements on all platforms.
+
+
+2016-05-02: Version 5.2.199
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-02: Version 5.1.26
+2016-05-02: Version 5.2.198
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-02: Version 5.1.25
+2016-05-02: Version 5.2.197
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-02: Version 5.1.24
+2016-05-02: Version 5.2.196
 
-        Devtools: expose scopes source location to debugger (Chromium issue
-        327092).
+        Performance and stability improvements on all platforms.
+
 
-        CodeStubAssembler can generate code for builtins (issue 4614).
+2016-05-02: Version 5.2.195
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-01: Version 5.1.23
+2016-05-02: Version 5.2.194
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-01: Version 5.1.22
+2016-05-02: Version 5.2.193
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-01: Version 5.1.21
+2016-05-02: Version 5.2.192
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-01: Version 5.1.20
+2016-05-02: Version 5.2.191
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-01: Version 5.1.19
+2016-05-01: Version 5.2.190
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-01: Version 5.1.18
+2016-05-01: Version 5.2.189
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-01: Version 5.1.17
+2016-04-30: Version 5.2.188
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-01: Version 5.1.16
+2016-04-30: Version 5.2.187
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-01: Version 5.1.15
+2016-04-30: Version 5.2.186
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-01: Version 5.1.14
+2016-04-29: Version 5.2.185
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-01: Version 5.1.13
+2016-04-29: Version 5.2.184
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-01: Version 5.1.12
+2016-04-29: Version 5.2.183
 
         Performance and stability improvements on all platforms.
 
 
-2016-03-01: Version 5.1.11
+2016-04-29: Version 5.2.182
+
+        Performance and stability improvements on all platforms.
+
 
-        Make %TypedArray%.from spec-compliant (issue 4782).
+2016-04-29: Version 5.2.181
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-29: Version 5.1.10
+2016-04-29: Version 5.2.180
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-29: Version 5.1.9
+2016-04-29: Version 5.2.179
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-28: Version 5.1.8
+2016-04-29: Version 5.2.178
 
         Performance and stability improvements on all platforms.
 
+
+2016-04-29: Version 5.2.177
 
-2016-02-28: Version 5.1.7
+        Fix overflow issue in Zone::New (Chromium issue 606115).
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-28: Version 5.1.6
+2016-04-29: Version 5.2.176
 
         Performance and stability improvements on all platforms.
 
 
+2016-04-29: Version 5.2.175
+
+        [wasm] Binary 11: Bump module version to 0xB. [wasm] Binary 11: Swap the
+        order of section name / section length. [wasm] Binary 11: Shorter
+        section names. [wasm] Binary 11: Add a prefix for function type
+        declarations. [wasm] Binary 11: Function types encoded as pcount, p*,
+        rcount, r* [wasm] Fix numeric names for functions (Chromium issue
+        575167).
+
-2016-02-28: Version 5.1.5
+        [wasm] Binary 11: WASM AST is now postorder. [wasm] Binary 11: br_table
+        takes a value. [wasm] Binary 11: Add implicit blocks to if arms. [wasm]
+        Binary 11: Add arities to call, return, and breaks [wasm] Binary 11: Add
+        experimental version (Chromium issue 575167).
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-28: Version 5.1.4
+2016-04-29: Version 5.2.174
+
+        Add checks for detached ArrayBuffers to ArrayBuffer.prototype.slice
+        (issue 4964).
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-28: Version 5.1.3
+2016-04-28: Version 5.2.173
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-28: Version 5.1.2
+2016-04-28: Version 5.2.172
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-27: Version 5.1.1
+2016-04-28: Version 5.2.171
 
-        Fix strict mode function error message (issue 2198).
+        Ship for-in initializer deprecation (issue 4942).
 
-        Reland of Make Intl install properties more like how other builtins do
-        (patchset #1 id:1 of https://codereview.chromium.org/1733293003/ )
-        (issue 4778).
+        Performance and stability improvements on all platforms.
 
-        [turbofan] Bailout if LoadBuffer typing assumption doesn't hold
-        (Chromium issue 589792).
+
+2016-04-28: Version 5.2.170
+
+        Add GC request to libFuzzers in attempt to avoid parasitic coverage
+        (Chromium issue 584819).
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-26: Version 5.0.104
+2016-04-28: Version 5.2.169
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-26: Version 5.0.103
+2016-04-28: Version 5.2.168
+
+        Prevent unnecessary memory (de-)allocations in LiteralBuffer::CopyFrom
+        (issue 4947).
+
+        Performance and stability improvements on all platforms.
+
 
-        Make Intl install properties more like how other builtins do (issue
-        4778).
+2016-04-28: Version 5.2.167
 
         Performance and stability improvements on all platforms.
 
+
+2016-04-28: Version 5.2.166
+
+        Performance and stability improvements on all platforms.
 
-2016-02-26: Version 5.0.102
 
-        Make TypedArray.from and TypedArray.of writable and configurable (issue
-        4315).
+2016-04-28: Version 5.2.165
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-25: Version 5.0.101
+2016-04-28: Version 5.2.164
 
         Performance and stability improvements on all platforms.
 
+
+2016-04-27: Version 5.2.163
+
+        Performance and stability improvements on all platforms.
 
-2016-02-25: Version 5.0.100
 
-        Ship ES2015 iterator finalization (issue 3566).
+2016-04-27: Version 5.2.162
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-25: Version 5.0.99
+2016-04-27: Version 5.2.161
 
-        Introduce MicrotasksCompletedCallback (Chromium issue 585949).
+        [esnext] stage --harmony-string-padding (issue 4954).
+
+        Disallow generator declarations in certain locations (issue 4824).
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-25: Version 5.0.98
+2016-04-27: Version 5.2.160
 
         Performance and stability improvements on all platforms.
 
+
+2016-04-27: Version 5.2.159
 
-2016-02-25: Version 5.0.97
+        [api] Expose FunctionCallbackInfo::NewTarget (issue 4261).
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-25: Version 5.0.96
+2016-04-27: Version 5.2.158
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-25: Version 5.0.95
+2016-04-27: Version 5.2.157
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-25: Version 5.0.94
+2016-04-27: Version 5.2.156
+
+        [es8] Report proper syntax error for tail call expressions in for-in and
+        for-of bodies (issue 4915).
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-25: Version 5.0.93
+2016-04-27: Version 5.2.155
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-25: Version 5.0.92
+2016-04-27: Version 5.2.154
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-25: Version 5.0.91
+2016-04-27: Version 5.2.153
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-25: Version 5.0.90
+2016-04-27: Version 5.2.152
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-25: Version 5.0.89
+2016-04-27: Version 5.2.151
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-25: Version 5.0.88
+2016-04-26: Version 5.2.150
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-25: Version 5.0.87
+2016-04-26: Version 5.2.149
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-25: Version 5.0.86
+2016-04-26: Version 5.2.148
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-25: Version 5.0.85
+2016-04-26: Version 5.2.147
+
+        Do not penalize performance when --harmony-species is off (Chromium
+        issue 606207).
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-24: Version 5.0.84
+2016-04-26: Version 5.2.146
+
+        [es8] Initial set of changes to support syntactic tail calls (issue
+        4915).
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-24: Version 5.0.83
+2016-04-26: Version 5.2.145
 
         Performance and stability improvements on all platforms.
 
+
+2016-04-26: Version 5.2.144
 
-2016-02-24: Version 5.0.82
+        Performance and stability improvements on all platforms.
 
-        Ensure IteratorClose is called for errors in non-declaring assignments
-        (issue 4776).
 
-        Fix priority of exceptions being thrown from for-of loops (issue 4775).
+2016-04-26: Version 5.2.143
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-24: Version 5.0.81
+2016-04-26: Version 5.2.142
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-24: Version 5.0.80
+2016-04-26: Version 5.2.141
 
-        Encode interpreter::SourcePositionTable as variable-length ints (issue
-        4690).
+        Performance and stability improvements on all platforms.
+
 
-        Stage ES2015 iterator finalization (issue 3566).
+2016-04-26: Version 5.2.140
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-24: Version 5.0.79
+2016-04-26: Version 5.2.139
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-24: Version 5.0.78
+2016-04-26: Version 5.2.138
+
+        [es6] Fix tail call elimination in single-expression arrow functions
+        (issue 4698).
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-24: Version 5.0.77
+2016-04-26: Version 5.2.137
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-24: Version 5.0.76
+2016-04-25: Version 5.2.136
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-24: Version 5.0.75
+2016-04-25: Version 5.2.135
+
+        Widen --harmony-for-in flag to throw errors in PreParser (issue 4942).
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-24: Version 5.0.74
+2016-04-25: Version 5.2.134
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-23: Version 5.0.73
+2016-04-25: Version 5.2.133
 
-        Intl: Use private symbols to memoize bound functions (issue 3785).
+        Performance and stability improvements on all platforms.
 
-        Ensure Array.prototype.indexOf returns +0 rather than -0.
 
-        Ship ES2015 Symbol.species (issue 4093).
+2016-04-25: Version 5.2.132
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-23: Version 5.0.72
+2016-04-25: Version 5.2.131
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-23: Version 5.0.71
+2016-04-25: Version 5.2.130
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-23: Version 5.0.70
+2016-04-25: Version 5.2.129
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-23: Version 5.0.69
+2016-04-25: Version 5.2.128
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-23: Version 5.0.68
+2016-04-25: Version 5.2.127
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-23: Version 5.0.67
+2016-04-25: Version 5.2.126
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-23: Version 5.0.66
+2016-04-25: Version 5.2.125
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-22: Version 5.0.65
+2016-04-25: Version 5.2.124
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-22: Version 5.0.64
+2016-04-25: Version 5.2.123
 
-        ES2015 web compat workaround: RegExp.prototype.flags => "" (Chromium
-        issue 581577).
+        Performance and stability improvements on all platforms.
+
 
-        Remove the Proxy enumerate trap (issue 4768).
+2016-04-25: Version 5.2.122
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-22: Version 5.0.63
+2016-04-22: Version 5.2.121
 
         Performance and stability improvements on all platforms.
 
+
+2016-04-22: Version 5.2.120
+
+        Performance and stability improvements on all platforms.
 
-2016-02-22: Version 5.0.62
 
-        Remove Reflect.enumerate (issue 4768).
+2016-04-22: Version 5.2.119
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-22: Version 5.0.61
+2016-04-22: Version 5.2.118
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-22: Version 5.0.60
+2016-04-22: Version 5.2.117
+
+        [debugger] Hide scopes that originate from desugaring (Chromium issue
+        604458).
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-22: Version 5.0.59
+2016-04-22: Version 5.2.116
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-22: Version 5.0.58
+2016-04-22: Version 5.2.115
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-22: Version 5.0.57
+2016-04-21: Version 5.2.114
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-22: Version 5.0.56
+2016-04-21: Version 5.2.113
 
         Performance and stability improvements on all platforms.
 
+
+2016-04-21: Version 5.2.112
 
-2016-02-22: Version 5.0.55
+        [ic] Restore PROPERTY key tracking in keyed ICs (Chromium issue 594183).
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-22: Version 5.0.54
+2016-04-21: Version 5.2.111
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-21: Version 5.0.53
+2016-04-21: Version 5.2.110
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-21: Version 5.0.52
+2016-04-21: Version 5.2.109
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-21: Version 5.0.51
+2016-04-21: Version 5.2.108
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-21: Version 5.0.50
+2016-04-21: Version 5.2.107
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-21: Version 5.0.49
+2016-04-21: Version 5.2.106
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-21: Version 5.0.48
+2016-04-21: Version 5.2.105
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-20: Version 5.0.47
+2016-04-21: Version 5.2.104
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-20: Version 5.0.46
+2016-04-21: Version 5.2.103
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.45
+2016-04-21: Version 5.2.102
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.44
+2016-04-20: Version 5.2.101
 
-        Return undefined from RegExp.prototype.compile (Chromium issue 585775).
+        Performance and stability improvements on all platforms.
+
+
+2016-04-20: Version 5.2.100
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.43
+2016-04-20: Version 5.2.99
 
-        Disable --harmony-object-observe (Chromium issue 552100).
+        Performance and stability improvements on all platforms.
+
+
+2016-04-20: Version 5.2.98
 
         Performance and stability improvements on all platforms.
 
+
+2016-04-20: Version 5.2.97
+
+        Performance and stability improvements on all platforms.
 
-2016-02-19: Version 5.0.42
 
-        Introduce BeforeCallEnteredCallback (Chromium issue 585949).
+2016-04-20: Version 5.2.96
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.41
+2016-04-20: Version 5.2.95
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.40
+2016-04-20: Version 5.2.94
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.39
+2016-04-20: Version 5.2.93
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.38
+2016-04-20: Version 5.2.92
+
+        Performance and stability improvements on all platforms.
+
 
-        [wasm] Add support for import section (Chromium issue 575167).
+2016-04-20: Version 5.2.91
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.37
+2016-04-20: Version 5.2.90
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.36
+2016-04-20: Version 5.2.89
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.35
+2016-04-20: Version 5.2.88
+
+        [turbofan] Length and index2 are unsigned in CheckedLoad/CheckedStore
+        (Chromium issue 599717).
+
+        Prevent un-parsed LiteralFunction reaching the compiler (Chromium issue
+        604044).
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.34
+2016-04-20: Version 5.2.87
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.33
+2016-04-20: Version 5.2.86
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.32
+2016-04-19: Version 5.2.85
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.31
+2016-04-19: Version 5.2.84
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.30
+2016-04-19: Version 5.2.83
+
+        Performance and stability improvements on all platforms.
+
 
-        Mark old SetAccessCheckCallback as deprecated.
+2016-04-19: Version 5.2.82
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.29
+2016-04-19: Version 5.2.81
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.28
+2016-04-19: Version 5.2.80
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.27
+2016-04-19: Version 5.2.79
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-19: Version 5.0.26
+2016-04-19: Version 5.2.78
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-18: Version 5.0.25
+2016-04-19: Version 5.2.77
 
         Performance and stability improvements on all platforms.
 
+
+2016-04-19: Version 5.2.76
+
+        Performance and stability improvements on all platforms.
 
-2016-02-18: Version 5.0.24
 
-        Make Date.prototype.toGMTString an alias for Date.prototype.toUTCString
-        (issue 4708).
+2016-04-19: Version 5.2.75
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-18: Version 5.0.23
+2016-04-19: Version 5.2.74
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-18: Version 5.0.22
+2016-04-19: Version 5.2.73
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-18: Version 5.0.21
+2016-04-19: Version 5.2.72
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-18: Version 5.0.20
+2016-04-19: Version 5.2.71
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-18: Version 5.0.19
+2016-04-19: Version 5.2.70
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-18: Version 5.0.18
+2016-04-19: Version 5.2.69
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-18: Version 5.0.17
+2016-04-19: Version 5.2.68
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-18: Version 5.0.16
+2016-04-19: Version 5.2.67
 
-        [es6] Implement for-of iterator finalization (issue 2214).
+        Performance and stability improvements on all platforms.
+
+
+2016-04-19: Version 5.2.66
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-18: Version 5.0.15
+2016-04-18: Version 5.2.65
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-18: Version 5.0.14
+2016-04-18: Version 5.2.64
 
-        Use displayName in Error.stack rendering if present (issue 4761).
+        Performance and stability improvements on all platforms.
+
+
+2016-04-18: Version 5.2.63
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-18: Version 5.0.13
+2016-04-18: Version 5.2.62
 
         Performance and stability improvements on all platforms.
 
+
+2016-04-18: Version 5.2.61
 
-2016-02-18: Version 5.0.12
+        [Atomics] Remove Atomics code stubs; use TF ops (issue 4614).
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-18: Version 5.0.11
+2016-04-18: Version 5.2.60
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-17: Version 5.0.10
+2016-04-18: Version 5.2.59
+
+        Performance and stability improvements on all platforms.
+
 
-        [Atomics] Add dmb/dsb/isb instructions to ARM (issue 4614).
+2016-04-18: Version 5.2.58
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-17: Version 5.0.9
+2016-04-18: Version 5.2.57
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-17: Version 5.0.8
+2016-04-18: Version 5.2.56
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-17: Version 5.0.7
+2016-04-18: Version 5.2.55
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-17: Version 5.0.6
+2016-04-18: Version 5.2.54
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-17: Version 5.0.5
+2016-04-18: Version 5.2.53
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-17: Version 5.0.4
+2016-04-18: Version 5.2.52
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-17: Version 5.0.3
+2016-04-18: Version 5.2.51
 
         Performance and stability improvements on all platforms.
 
+
+2016-04-18: Version 5.2.50
 
-2016-02-17: Version 5.0.2
+        [Atomics] Remove Atomics code stubs; use TF ops (issue 4614).
 
         Performance and stability improvements on all platforms.
 
 
-2016-02-17: Version 5.0.1
+2016-04-18: Version 5.2.49
+
+        [api] Bring back finalizers on global handles.
 
         Performance and stability improvements on all platforms.
 
 
+2016-02-17: Sentinel
+
+        The ChangeLog file is no longer maintained on master. This
+        sentinel should stay on top of this list.
+
 2016-02-17: Version 4.10.253
 
         Performance and stability improvements on all platforms.
@@ -7268,12 +8593,6 @@
         Performance and stability improvements on all platforms.
 
 
-2015-05-17: Sentinel
-
-        The ChangeLog file is no longer maintained on bleeding_edge. This
-        sentinel should stay on top of this list.
-
-
 2015-05-17: Version 4.5.2
 
         Performance and stability improvements on all platforms.
diff --git a/DEPS b/DEPS
index 0559523..b3cf10a 100644
--- a/DEPS
+++ b/DEPS
@@ -7,14 +7,18 @@
 }
 
 deps = {
-  "v8/build/gyp":
-    Var("git_url") + "/external/gyp.git" + "@" + "4ec6c4e3a94bd04a6da2858163d40b2429b8aad1",
+  "v8/build":
+    Var("git_url") + "/chromium/src/build.git" + "@" + "87e063014aa0f343b15f5de495a28e5f8572bf8d",
+  "v8/tools/gyp":
+    Var("git_url") + "/external/gyp.git" + "@" + "35eafcd939515d51d19556c543f9cf97faf75ee6",
   "v8/third_party/icu":
-    Var("git_url") + "/chromium/deps/icu.git" + "@" + "c291cde264469b20ca969ce8832088acb21e0c48",
+    Var("git_url") + "/chromium/deps/icu.git" + "@" + "ffa4b6704cf5cc9fec9485731f24a05b2ba94bca",
   "v8/buildtools":
-    Var("git_url") + "/chromium/buildtools.git" + "@" + "80b5126f91be4eb359248d28696746ef09d5be67",
+    Var("git_url") + "/chromium/buildtools.git" + "@" + "56eaae134648135663c4aa1ed82278572b5f35ef",
   "v8/base/trace_event/common":
-    Var("git_url") + "/chromium/src/base/trace_event/common.git" + "@" + "c8c8665c2deaf1cc749d9f8e153256d4f67bf1b8",
+    Var("git_url") + "/chromium/src/base/trace_event/common.git" + "@" + "54b8455be9505c2cb0cf5c26bb86739c236471aa",
+  "v8/tools/mb":
+    Var('git_url') + '/chromium/src/tools/mb.git' + '@' + "62e2d060db3b06208f5d6558db03efd140ecd180",
   "v8/tools/swarming_client":
     Var('git_url') + '/external/swarming.client.git' + '@' + "df6e95e7669883c8fe9ef956c69a544154701a49",
   "v8/testing/gtest":
@@ -25,17 +29,17 @@
     Var("git_url") + "/v8/deps/third_party/benchmarks.git" + "@" + "05d7188267b4560491ff9155c5ee13e207ecd65f",
   "v8/test/mozilla/data":
     Var("git_url") + "/v8/deps/third_party/mozilla-tests.git" + "@" + "f6c578a10ea707b1a8ab0b88943fe5115ce2b9be",
-  "v8/test/simdjs/data": Var("git_url") + "/external/github.com/tc39/ecmascript_simd.git" + "@" + "c8ef63c728283debc25891123eb00482fee4b8cd",
+  "v8/test/simdjs/data": Var("git_url") + "/external/github.com/tc39/ecmascript_simd.git" + "@" + "baf493985cb9ea7cdbd0d68704860a8156de9556",
   "v8/test/test262/data":
-    Var("git_url") + "/external/github.com/tc39/test262.git" + "@" + "57d3e2216fa86ad63b6c0a54914ba9dcbff96003",
+    Var("git_url") + "/external/github.com/tc39/test262.git" + "@" + "88bc7fe7586f161201c5f14f55c9c489f82b1b67",
   "v8/tools/clang":
-    Var("git_url") + "/chromium/src/tools/clang.git" + "@" + "faee82e064e04e5cbf60cc7327e7a81d2a4557ad",
+    Var("git_url") + "/chromium/src/tools/clang.git" + "@" + "2ad431ac7823581e1f39c5b770704e1e1ca6cb32",
 }
 
 deps_os = {
   "android": {
     "v8/third_party/android_tools":
-      Var("git_url") + "/android_tools.git" + "@" + "adfd31794011488cd0fc716b53558b2d8a67af8b",
+      Var("git_url") + "/android_tools.git" + "@" + "5b5f2f60b78198eaef25d442ac60f823142a8a6e",
   },
   "win": {
     "v8/third_party/cygwin":
@@ -43,6 +47,8 @@
   }
 }
 
+recursedeps = [ 'v8/third_party/android_tools' ]
+
 include_rules = [
   # Everybody can use some things.
   "+include",
@@ -53,6 +59,7 @@
 # checkdeps.py shouldn't check for includes in these directories:
 skip_child_includes = [
   "build",
+  "gypfiles",
   "third_party",
 ]
 
@@ -65,7 +72,7 @@
     'pattern': '.',
     'action': [
         'python',
-        'v8/build/landmines.py',
+        'v8/gypfiles/landmines.py',
     ],
   },
   # Pull clang-format binaries using checked-in hashes.
@@ -187,10 +194,22 @@
     ],
   },
   {
+    # Downloads the current stable linux sysroot to build/linux/ if needed.
+    # This sysroot updates at about the same rate that the chrome build deps
+    # change.
+    'name': 'sysroot',
+    'pattern': '.',
+    'action': [
+        'python',
+        'v8/build/linux/sysroot_scripts/install-sysroot.py',
+        '--running-as-hook',
+    ],
+  },
+  {
     # Update the Windows toolchain if necessary.
     'name': 'win_toolchain',
     'pattern': '.',
-    'action': ['python', 'v8/build/vs_toolchain.py', 'update'],
+    'action': ['python', 'v8/gypfiles/vs_toolchain.py', 'update'],
   },
   # Pull binutils for linux, enabled debug fission for faster linking /
   # debugging when used with clang on Ubuntu Precise.
@@ -208,7 +227,7 @@
     # Note: This must run before the clang update.
     'name': 'gold_plugin',
     'pattern': '.',
-    'action': ['python', 'v8/build/download_gold_plugin.py'],
+    'action': ['python', 'v8/gypfiles/download_gold_plugin.py'],
   },
   {
     # Pull clang if needed or requested via GYP_DEFINES.
@@ -220,6 +239,6 @@
   {
     # A change to a .gyp, .gypi, or to GYP itself should run the generator.
     "pattern": ".",
-    "action": ["python", "v8/build/gyp_v8"],
+    "action": ["python", "v8/gypfiles/gyp_v8"],
   },
 ]
diff --git a/LICENSE.fdlibm b/LICENSE.fdlibm
new file mode 100644
index 0000000..b54cb52
--- /dev/null
+++ b/LICENSE.fdlibm
@@ -0,0 +1,6 @@
+Copyright (C) 1993-2004 by Sun Microsystems, Inc. All rights reserved.
+
+Developed at SunSoft, a Sun Microsystems, Inc. business.
+Permission to use, copy, modify, and distribute this
+software is freely granted, provided that this notice
+is preserved.
diff --git a/MODULE_LICENSE_BSD b/MODULE_LICENSE_BSD
deleted file mode 100644
index e69de29..0000000
--- a/MODULE_LICENSE_BSD
+++ /dev/null
diff --git a/Makefile b/Makefile
index a0c08a6..ffb5192 100644
--- a/Makefile
+++ b/Makefile
@@ -227,6 +227,11 @@
   GYPFLAGS += -Drelease_extra_cflags=-fno-omit-frame-pointer
 endif
 
+ifdef android_ndk_root
+  GYPFLAGS += -Dandroid_ndk_root=$(android_ndk_root)
+  export ANDROID_NDK_ROOT = $(android_ndk_root)
+endif
+
 # ----------------- available targets: --------------------
 # - "grokdump": rebuilds heap constants lists used by grokdump
 # - any arch listed in ARCHES (see below)
@@ -245,8 +250,9 @@
 
 # Architectures and modes to be compiled. Consider these to be internal
 # variables, don't override them (use the targets instead).
-ARCHES = ia32 x64 x32 arm arm64 mips mipsel mips64 mips64el x87 ppc ppc64 \
-		 s390 s390x
+ARCHES = ia32 x64 arm arm64 mips mipsel mips64 mips64el x87 ppc ppc64 s390 \
+         s390x
+ARCHES32 = ia32 arm mips mipsel x87 ppc s390
 DEFAULT_ARCHES = ia32 x64 arm
 MODES = release debug optdebug
 DEFAULT_MODES = release debug
@@ -256,10 +262,11 @@
 
 # List of files that trigger Makefile regeneration:
 GYPFILES = third_party/icu/icu.gypi third_party/icu/icu.gyp \
-	   build/shim_headers.gypi build/features.gypi build/standalone.gypi \
-	   build/toolchain.gypi build/all.gyp build/mac/asan.gyp \
+	   gypfiles/shim_headers.gypi gypfiles/features.gypi \
+           gypfiles/standalone.gypi \
+	   gypfiles/toolchain.gypi gypfiles/all.gyp gypfiles/mac/asan.gyp \
 	   test/cctest/cctest.gyp test/fuzzer/fuzzer.gyp \
-	   test/unittests/unittests.gyp tools/gyp/v8.gyp \
+	   test/unittests/unittests.gyp src/v8.gyp \
 	   tools/parser-shell.gyp testing/gmock.gyp testing/gtest.gyp \
 	   buildtools/third_party/libc++abi/libc++abi.gyp \
 	   buildtools/third_party/libc++/libc++.gyp samples/samples.gyp \
@@ -432,7 +439,7 @@
 	rm -rf $(OUTDIR)/native
 	find $(OUTDIR) -regex '.*\(host\|target\)\.native\.mk' -delete
 
-clean: $(addsuffix .clean, $(ARCHES) $(ANDROID_ARCHES) $(NACL_ARCHES)) native.clean gtags.clean
+clean: $(addsuffix .clean, $(ARCHES) $(ANDROID_ARCHES) $(NACL_ARCHES)) native.clean gtags.clean tags.clean
 
 # GYP file generation targets.
 OUT_MAKEFILES = $(addprefix $(OUTDIR)/Makefile.,$(BUILDS))
@@ -441,22 +448,28 @@
 	        cut -f 2 -d " " | cut -f 1 -d "-" ))
 	$(eval CXX_TARGET_ARCH:=$(subst aarch64,arm64,$(CXX_TARGET_ARCH)))
 	$(eval CXX_TARGET_ARCH:=$(subst x86_64,x64,$(CXX_TARGET_ARCH)))
+	$(eval CXX_TARGET_ARCH:=$(subst s390x,s390,$(CXX_TARGET_ARCH)))
+	$(eval CXX_TARGET_ARCH:=$(subst powerpc,ppc,$(CXX_TARGET_ARCH)))
+	$(eval CXX_TARGET_ARCH:=$(subst ppc64,ppc,$(CXX_TARGET_ARCH)))
+	$(eval CXX_TARGET_ARCH:=$(subst ppcle,ppc,$(CXX_TARGET_ARCH)))
 	$(eval V8_TARGET_ARCH:=$(subst .,,$(suffix $(basename $@))))
-	PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(shell pwd)/build:$(PYTHONPATH):$(shell pwd)/build/gyp/pylib:$(PYTHONPATH)" \
+	PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(shell pwd)/gypfiles:$(PYTHONPATH):$(shell pwd)/tools/gyp/pylib:$(PYTHONPATH)" \
 	GYP_GENERATORS=make \
-	build/gyp/gyp --generator-output="$(OUTDIR)" build/all.gyp \
-	              -Ibuild/standalone.gypi --depth=. \
+	tools/gyp/gyp --generator-output="$(OUTDIR)" gypfiles/all.gyp \
+	              -Igypfiles/standalone.gypi --depth=. \
 	              -Dv8_target_arch=$(V8_TARGET_ARCH) \
 	              $(if $(findstring $(CXX_TARGET_ARCH),$(V8_TARGET_ARCH)), \
-	              -Dtarget_arch=$(V8_TARGET_ARCH),) \
+	              -Dtarget_arch=$(V8_TARGET_ARCH), \
+	                  $(if $(shell echo $(ARCHES32) | grep $(V8_TARGET_ARCH)), \
+	                  -Dtarget_arch=ia32,)) \
 	              $(if $(findstring optdebug,$@),-Dv8_optimized_debug=1,) \
 	              -S$(suffix $(basename $@))$(suffix $@) $(GYPFLAGS)
 
 $(OUTDIR)/Makefile.native: $(GYPFILES) $(ENVFILE)
-	PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(shell pwd)/build:$(PYTHONPATH):$(shell pwd)/build/gyp/pylib:$(PYTHONPATH)" \
+	PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(shell pwd)/gypfiles:$(PYTHONPATH):$(shell pwd)/tools/gyp/pylib:$(PYTHONPATH)" \
 	GYP_GENERATORS=make \
-	build/gyp/gyp --generator-output="$(OUTDIR)" build/all.gyp \
-	              -Ibuild/standalone.gypi --depth=. -S.native $(GYPFLAGS)
+	tools/gyp/gyp --generator-output="$(OUTDIR)" gypfiles/all.gyp \
+	              -Igypfiles/standalone.gypi --depth=. -S.native $(GYPFLAGS)
 
 # Note that NACL_SDK_ROOT must be set to point to an appropriate
 # Native Client SDK before using this makefile. You can download
@@ -497,11 +510,21 @@
 
 # We need to manually set the stack limit here, to work around bugs in
 # gmake-3.81 and global-5.7.1 on recent 64-bit Linux systems.
-GPATH GRTAGS GSYMS GTAGS: gtags.files $(shell cat gtags.files 2> /dev/null)
+# Using $(wildcard ...) gracefully ignores non-existing files, so that stale
+# gtags.files after switching branches don't cause recipe failures.
+GPATH GRTAGS GSYMS GTAGS: gtags.files $(wildcard $(shell cat gtags.files 2> /dev/null))
 	@bash -c 'ulimit -s 10240 && GTAGSFORCECPP=yes gtags -i -q -f $<'
 
 gtags.clean:
 	rm -f gtags.files GPATH GRTAGS GSYMS GTAGS
 
+tags: gtags.files $(wildcard $(shell cat gtags.files 2> /dev/null))
+	@(ctags --version | grep 'Exuberant Ctags' >/dev/null) || \
+		(echo "Please install Exuberant Ctags (check 'ctags --version')" >&2; false)
+	ctags --fields=+l -L $<
+
+tags.clean:
+	rm -r tags
+
 dependencies builddeps:
 	$(error Use 'gclient sync' instead)
diff --git a/Makefile.android b/Makefile.android
index c49cb85..4171521 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -66,7 +66,7 @@
 $(ANDROID_MAKEFILES):
 	GYP_GENERATORS=make-android \
 	GYP_DEFINES="${DEFINES}" \
-	PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(shell pwd)/build:$(PYTHONPATH)" \
-	build/gyp/gyp --generator-output="${OUTDIR}" build/all.gyp \
-	              -Ibuild/standalone.gypi --depth=. \
+	PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(shell pwd)/gypfiles:$(PYTHONPATH)" \
+	tools/gyp/gyp --generator-output="${OUTDIR}" gypfiles/all.gyp \
+	              -Igypfiles/standalone.gypi --depth=. \
 	              -S$(suffix $(basename $@))$(suffix $@) ${GYPFLAGS}
diff --git a/Makefile.nacl b/Makefile.nacl
index 3459c42..5eaff47 100644
--- a/Makefile.nacl
+++ b/Makefile.nacl
@@ -91,7 +91,7 @@
 	CXX=${NACL_CXX} \
 	LINK=${NACL_LINK} \
 	PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(shell pwd)/build:$(PYTHONPATH)" \
-	build/gyp/gyp --generator-output="${OUTDIR}" build/all.gyp \
-	              -Ibuild/standalone.gypi --depth=. \
+	tools/gyp/gyp --generator-output="${OUTDIR}" gypfiles/all.gyp \
+	              -Igypfiles/standalone.gypi --depth=. \
 	              -S$(suffix $(basename $@))$(suffix $@) $(GYPFLAGS) \
                       -Dwno_array_bounds=-Wno-array-bounds
diff --git a/NOTICE b/NOTICE
deleted file mode 100644
index 678c73f..0000000
--- a/NOTICE
+++ /dev/null
@@ -1,33 +0,0 @@
-Copyright (c) 1994-2006 Sun Microsystems Inc.
-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.
-
-- Redistribution 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 Sun Microsystems or the names of 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.
-
-The original source code covered by the above license above has been
-modified significantly by Google Inc.
-Copyright 2006-2008 the V8 project authors. All rights reserved.
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index f8516af..5255ca1 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -223,6 +223,8 @@
       input_api, output_api, source_file_filter=None))
   results.extend(input_api.canned_checks.CheckPatchFormatted(
       input_api, output_api))
+  results.extend(input_api.canned_checks.CheckGenderNeutral(
+      input_api, output_api))
   results.extend(_V8PresubmitChecks(input_api, output_api))
   results.extend(_CheckUnwantedDependencies(input_api, output_api))
   results.extend(
@@ -242,32 +244,15 @@
   return input_api.environ.get('PRESUBMIT_TREE_CHECK') == 'skip'
 
 
-def _CheckChangeLogFlag(input_api, output_api, warn):
-  """Checks usage of LOG= flag in the commit message."""
-  results = []
-  if (input_api.change.BUG and input_api.change.BUG != 'none' and
-      not 'LOG' in input_api.change.tags):
-    text = ('An issue reference (BUG=) requires a change log flag (LOG=). '
-            'Use LOG=Y for including this commit message in the change log. '
-            'Use LOG=N or leave blank otherwise.')
-    if warn:
-      results.append(output_api.PresubmitPromptWarning(text))
-    else:
-      results.append(output_api.PresubmitError(text))
-  return results
-
-
 def CheckChangeOnUpload(input_api, output_api):
   results = []
   results.extend(_CommonChecks(input_api, output_api))
-  results.extend(_CheckChangeLogFlag(input_api, output_api, True))
   return results
 
 
 def CheckChangeOnCommit(input_api, output_api):
   results = []
   results.extend(_CommonChecks(input_api, output_api))
-  results.extend(_CheckChangeLogFlag(input_api, output_api, False))
   results.extend(input_api.canned_checks.CheckChangeHasDescription(
       input_api, output_api))
   if not _SkipTreeCheck(input_api, output_api):
diff --git a/V8_MERGE_REVISION b/V8_MERGE_REVISION
index 5278fb5..e855b52 100644
--- a/V8_MERGE_REVISION
+++ b/V8_MERGE_REVISION
@@ -1,2 +1,2 @@
-v8 5.1.281.59
-https://chromium.googlesource.com/v8/v8/+/5.1.281.59
+v8 5.3.332.45
+https://chromium.googlesource.com/v8/v8/+/5.3.332.45
diff --git a/WATCHLISTS b/WATCHLISTS
index 29b957b..bd07d31 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -44,7 +44,6 @@
     },
     'interpreter': {
       'filepath': 'src/interpreter/' \
-                  '|src/compiler/interpreter' \
                   '|src/compiler/bytecode' \
                   '|test/cctest/interpreter/' \
                   '|test/unittests/interpreter/',
@@ -60,6 +59,9 @@
     },
     'ia32': {
       'filepath': '/ia32/',
+    },
+    'merges': {
+      'filepath': '.',
     }
   },
 
@@ -91,5 +93,9 @@
     'ia32': [
       'v8-x87-ports@googlegroups.com',
     ],
+    'merges': [
+      # Only enabled on branches created with tools/release/create_release.py
+      'v8-merges@googlegroups.com',
+    ],
   },
 }
diff --git a/build/OWNERS b/build/OWNERS
index 0e56af3..122b6e6 100644
--- a/build/OWNERS
+++ b/build/OWNERS
@@ -1 +1,12 @@
-machenbach@chromium.org
+agrieve@chromium.org
+dpranke@chromium.org
+jbudorick@chromium.org
+jochen@chromium.org
+scottmg@chromium.org
+thakis@chromium.org
+brucedawson@chromium.org
+
+per-file mac_toolchain.py=erikchen@chromium.org
+per-file mac_toolchain.py=justincohen@chromium.org
+per-file package_mac_toolchain.py=erikchen@chromium.org
+per-file package_mac_toolchain.py=justincohen@chromium.org
diff --git a/build/all.gyp b/build/all.gyp
index feaf4fe..7520aab 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -1,49 +1,1364 @@
-# Copyright 2011 the V8 project authors. All rights reserved.
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
 {
+  'variables': {
+    # A hook that can be overridden in other repositories to add additional
+    # compilation targets to 'All'.
+    'app_targets%': [],
+    # For Android-specific targets.
+    'android_app_targets%': [],
+  },
+  'includes': [
+    '../third_party/openh264/openh264_args.gypi',
+  ],
   'targets': [
     {
       'target_name': 'All',
       'type': 'none',
+      'xcode_create_dependents_test_runner': 1,
       'dependencies': [
-        '../samples/samples.gyp:*',
-        '../src/d8.gyp:d8',
-        '../test/cctest/cctest.gyp:*',
-        '../test/fuzzer/fuzzer.gyp:*',
-        '../test/unittests/unittests.gyp:*',
+        '<@(app_targets)',
+        'some.gyp:*',
+        '../base/base.gyp:*',
+        '../components/components.gyp:*',
+        '../components/components_tests.gyp:*',
+        '../crypto/crypto.gyp:*',
+        '../net/net.gyp:*',
+        '../sdch/sdch.gyp:*',
+        '../sql/sql.gyp:*',
+        '../testing/gmock.gyp:*',
+        '../testing/gtest.gyp:*',
+        '../third_party/boringssl/boringssl.gyp:*',
+        '../third_party/icu/icu.gyp:*',
+        '../third_party/libxml/libxml.gyp:*',
+        '../third_party/sqlite/sqlite.gyp:*',
+        '../third_party/zlib/zlib.gyp:*',
+        '../ui/accessibility/accessibility.gyp:*',
+        '../ui/base/ui_base.gyp:*',
+        '../ui/display/display.gyp:display_unittests',
+        '../ui/snapshot/snapshot.gyp:*',
+        '../url/url.gyp:*',
       ],
       'conditions': [
-        ['component!="shared_library"', {
+        ['OS!="ios" and OS!="mac"', {
           'dependencies': [
-            '../tools/parser-shell.gyp:parser-shell',
+            '../ui/touch_selection/ui_touch_selection.gyp:*',
+          ],
+        }],
+        ['OS=="ios"', {
+          'dependencies': [
+            '../ios/ios.gyp:*',
+            # NOTE: This list of targets is present because
+            # mojo_base.gyp:mojo_base cannot be built on iOS, as
+            # javascript-related targets cause v8 to be built.
+            # TODO(crbug.com/605508): http://crrev.com/1832703002 introduced
+            # a dependency on //third_party/WebKit that cause build failures
+            # when using Xcode version of clang (loading clang plugin fails).
+            # '../mojo/mojo_base.gyp:mojo_common_lib',
+            # '../mojo/mojo_base.gyp:mojo_common_unittests',
+            # '../mojo/mojo_edk.gyp:mojo_system_impl',
+            # '../mojo/mojo_edk_tests.gyp:mojo_public_bindings_unittests',
+            # '../mojo/mojo_edk_tests.gyp:mojo_public_system_unittests',
+            # '../mojo/mojo_edk_tests.gyp:mojo_system_unittests',
+            # '../mojo/mojo_public.gyp:mojo_cpp_bindings',
+            # '../mojo/mojo_public.gyp:mojo_public_test_utils',
+            # '../mojo/mojo_public.gyp:mojo_system',
+            '../google_apis/google_apis.gyp:google_apis_unittests',
+            '../skia/skia_tests.gyp:skia_unittests',
+            '../ui/base/ui_base_tests.gyp:ui_base_unittests',
+            '../ui/gfx/gfx_tests.gyp:gfx_unittests',
+          ],
+        }, { # 'OS!="ios"
+          'dependencies': [
+            '../content/content.gyp:*',
+            '../device/bluetooth/bluetooth.gyp:*',
+            '../device/device_tests.gyp:*',
+          ],
+        }],
+        ['OS=="android"', {
+          'dependencies': [
+            '../content/content_shell_and_tests.gyp:content_shell_apk',
+            '<@(android_app_targets)',
+            'android_builder_tests',
+            '../third_party/catapult/telemetry/telemetry.gyp:*#host',
+            # TODO(nyquist) This should instead by a target for sync when all of
+            # the sync-related code for Android has been upstreamed.
+            # See http://crbug.com/159203
+            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_javalib',
+          ],
+          'conditions': [
+            ['chromecast==0', {
+              'dependencies': [
+                '../android_webview/android_webview.gyp:android_webview_apk',
+                '../android_webview/android_webview_shell.gyp:system_webview_shell_apk',
+                '../chrome/android/chrome_apk.gyp:chrome_public_apk',
+                '../chrome/android/chrome_apk.gyp:chrome_sync_shell_apk',
+              ],
+            }],
+            ['chromecast==0 and use_webview_internal_framework==0', {
+              'dependencies': [
+                '../android_webview/android_webview.gyp:system_webview_apk',
+              ],
+            }],
+            # TODO: Enable packed relocations for x64. See: b/20532404
+            ['target_arch != "x64"', {
+              'dependencies': [
+                '../third_party/android_platform/relocation_packer.gyp:android_relocation_packer_unittests#host',
+              ],
+            }],
+          ],
+        }, {
+          'dependencies': [
+            # TODO: This should build on Android and the target should move to the list above.
+            '../sync/sync.gyp:*',
+          ],
+          'conditions': [
+            ['OS!="ios"', {
+              'dependencies': [
+                '../content/content_shell_and_tests.gyp:*',
+              ],
+            }],
+          ],
+        }],
+        ['OS!="ios" and OS!="android" and chromecast==0', {
+          'dependencies': [
+            '../third_party/re2/re2.gyp:re2',
+            '../chrome/chrome.gyp:*',
+            '../cc/blink/cc_blink_tests.gyp:*',
+            '../cc/cc_tests.gyp:*',
+            '../device/usb/usb.gyp:*',
+            '../extensions/extensions.gyp:*',
+            '../extensions/extensions_tests.gyp:*',
+            '../gin/gin.gyp:*',
+            '../gpu/gpu.gyp:*',
+            '../gpu/tools/tools.gyp:*',
+            '../ipc/ipc.gyp:*',
+            '../ipc/mojo/ipc_mojo.gyp:*',
+            '../jingle/jingle.gyp:*',
+            '../media/cast/cast.gyp:*',
+            '../media/media.gyp:*',
+            '../media/midi/midi.gyp:*',
+            '../mojo/mojo.gyp:*',
+            '../mojo/mojo_base.gyp:*',
+            '../ppapi/ppapi.gyp:*',
+            '../ppapi/ppapi_internal.gyp:*',
+            '../ppapi/tools/ppapi_tools.gyp:*',
+            '../services/shell/shell.gyp:*',
+            '../skia/skia.gyp:*',
+            '../sync/tools/sync_tools.gyp:*',
+            '../third_party/catapult/telemetry/telemetry.gyp:*',
+            '../third_party/WebKit/public/all.gyp:*',
+            '../third_party/cacheinvalidation/cacheinvalidation.gyp:*',
+            '../third_party/codesighs/codesighs.gyp:*',
+            '../third_party/ffmpeg/ffmpeg.gyp:*',
+            '../third_party/iccjpeg/iccjpeg.gyp:*',
+            '../third_party/libpng/libpng.gyp:*',
+            '../third_party/libusb/libusb.gyp:*',
+            '../third_party/libwebp/libwebp.gyp:*',
+            '../third_party/libxslt/libxslt.gyp:*',
+            '../third_party/lzma_sdk/lzma_sdk.gyp:*',
+            '../third_party/mesa/mesa.gyp:*',
+            '../third_party/modp_b64/modp_b64.gyp:*',
+            '../third_party/ots/ots.gyp:*',
+            '../third_party/pdfium/samples/samples.gyp:*',
+            '../third_party/qcms/qcms.gyp:*',
+            '../tools/battor_agent/battor_agent.gyp:*',
+            '../tools/gn/gn.gyp:*',
+            '../tools/perf/clear_system_cache/clear_system_cache.gyp:*',
+            '../v8/src/v8.gyp:*',
+            '<(libjpeg_gyp_path):*',
+          ],
+        }],
+        ['OS=="win" or OS=="ios" or OS=="linux"', {
+          'dependencies': [
+            '../breakpad/breakpad.gyp:*',
+           ],
+        }],
+        ['OS=="mac"', {
+          'dependencies': [
+            '../sandbox/sandbox.gyp:*',
+            '../third_party/crashpad/crashpad/crashpad.gyp:*',
+            '../third_party/ocmock/ocmock.gyp:*',
+          ],
+          'conditions': [
+            ['enable_ipc_fuzzer==1', {
+              'dependencies': [
+                '../tools/ipc_fuzzer/ipc_fuzzer.gyp:*',
+              ],
+            }],
+          ],
+        }],
+        ['OS=="linux"', {
+          'dependencies': [
+            '../courgette/courgette.gyp:*',
+            '../sandbox/sandbox.gyp:*',
+          ],
+          'conditions': [
+            ['branding=="Chrome"', {
+              'dependencies': [
+                '../chrome/chrome.gyp:linux_packages_<(channel)',
+              ],
+            }],
+            ['enable_ipc_fuzzer==1', {
+              'dependencies': [
+                '../tools/ipc_fuzzer/ipc_fuzzer.gyp:*',
+              ],
+            }],
+            ['use_dbus==1', {
+              'dependencies': [
+                '../dbus/dbus.gyp:*',
+              ],
+            }],
+          ],
+        }],
+        ['chromecast==1', {
+          'dependencies': [
+            '../chromecast/chromecast.gyp:*',
+          ],
+        }],
+        ['use_x11==1', {
+          'dependencies': [
+            '../tools/xdisplaycheck/xdisplaycheck.gyp:*',
+          ],
+        }],
+        ['OS=="win"', {
+          'dependencies': [
+            '../chrome_elf/chrome_elf.gyp:*',
+            '../courgette/courgette.gyp:*',
+            '../rlz/rlz.gyp:*',
+            '../sandbox/sandbox.gyp:*',
+            '<(angle_path)/src/angle.gyp:*',
+            '../third_party/bspatch/bspatch.gyp:*',
+            '../tools/win/static_initializers/static_initializers.gyp:*',
+          ],
+        }],
+        ['toolkit_views==1', {
+          'dependencies': [
+            '../ui/views/controls/webview/webview.gyp:*',
+            '../ui/views/views.gyp:*',
+          ],
+        }],
+        ['use_aura==1', {
+          'dependencies': [
+            '../ash/ash.gyp:*',
+            '../ui/aura/aura.gyp:*',
+            '../ui/aura_extra/aura_extra.gyp:*',
+          ],
+        }],
+        ['remoting==1', {
+          'dependencies': [
+            '../remoting/remoting_all.gyp:remoting_all',
+          ],
+        }],
+        ['OS!="ios"', {
+          'dependencies': [
+            '../third_party/boringssl/boringssl_tests.gyp:*',
+          ],
+        }],
+        ['enable_app_list==1', {
+          'dependencies': [
+            '../ui/app_list/app_list.gyp:*',
+          ],
+        }],
+        ['OS!="android" and OS!="ios"', {
+          'dependencies': [
+            '../google_apis/gcm/gcm.gyp:*',
+          ],
+        }],
+        ['(chromeos==1 or OS=="linux" or OS=="win" or OS=="mac") and chromecast==0', {
+          'dependencies': [
+            '../extensions/shell/app_shell.gyp:*',
+          ],
+        }],
+        ['envoy==1', {
+          'dependencies': [
+            '../envoy/envoy.gyp:*',
+          ],
+        }],
+        ['use_openh264==1', {
+          'dependencies': [
+            '../third_party/openh264/openh264.gyp:*',
+          ],
+        }],
+        ['enable_basic_printing==1 or enable_print_preview==1', {
+          'dependencies': [
+            '../printing/printing.gyp:*',
+          ],
+        }],
+      ],
+    }, # target_name: All
+    {
+      'target_name': 'All_syzygy',
+      'type': 'none',
+      'conditions': [
+        ['OS=="win" and fastbuild==0 and target_arch=="ia32" and '
+            '(syzyasan==1 or syzygy_optimize==1)', {
+          'dependencies': [
+            '../chrome/installer/mini_installer_syzygy.gyp:*',
+          ],
+        }],
+      ],
+    }, # target_name: All_syzygy
+    {
+      # Note: Android uses android_builder_tests below.
+      # TODO: Consider merging that with this target.
+      'target_name': 'chromium_builder_tests',
+      'type': 'none',
+      'dependencies': [
+        '../base/base.gyp:base_unittests',
+        '../components/components_tests.gyp:components_unittests',
+        '../crypto/crypto.gyp:crypto_unittests',
+        '../net/net.gyp:net_unittests',
+        '../skia/skia_tests.gyp:skia_unittests',
+        '../sql/sql.gyp:sql_unittests',
+        '../sync/sync.gyp:sync_unit_tests',
+        '../ui/base/ui_base_tests.gyp:ui_base_unittests',
+        '../ui/display/display.gyp:display_unittests',
+        '../ui/gfx/gfx_tests.gyp:gfx_unittests',
+        '../url/url.gyp:url_unittests',
+      ],
+      'conditions': [
+        ['OS!="ios"', {
+          'dependencies': [
+            '../ui/gl/gl_tests.gyp:gl_unittests',
+            '../url/ipc/url_ipc.gyp:url_ipc_unittests',
+          ],
+        }],
+        ['OS!="ios" and OS!="mac"', {
+          'dependencies': [
+            '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
+          ],
+        }],
+        ['OS!="ios" and OS!="android"', {
+          'dependencies': [
+            '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
+            '../cc/cc_tests.gyp:cc_unittests',
+            '../content/content_shell_and_tests.gyp:content_browsertests',
+            '../content/content_shell_and_tests.gyp:content_shell',
+            '../content/content_shell_and_tests.gyp:content_unittests',
+            '../device/device_tests.gyp:device_unittests',
+            '../gin/gin.gyp:gin_unittests',
+            '../google_apis/google_apis.gyp:google_apis_unittests',
+            '../gpu/gles2_conform_support/gles2_conform_support.gyp:gles2_conform_support',
+            '../gpu/gpu.gyp:gpu_unittests',
+            '../ipc/ipc.gyp:ipc_tests',
+            '../ipc/mojo/ipc_mojo.gyp:ipc_mojo_unittests',
+            '../jingle/jingle.gyp:jingle_unittests',
+            '../media/cast/cast.gyp:cast_unittests',
+            '../media/media.gyp:media_unittests',
+            '../media/midi/midi.gyp:midi_unittests',
+            '../mojo/mojo.gyp:mojo',
+            '../ppapi/ppapi_internal.gyp:ppapi_unittests',
+            '../remoting/remoting.gyp:remoting_unittests',
+            '../third_party/catapult/telemetry/telemetry.gyp:*',
+            '../third_party/WebKit/public/all.gyp:all_blink',
+            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
+            '../third_party/leveldatabase/leveldatabase.gyp:env_chromium_unittests',
+            '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_unittests',
+            '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber_unittests',
+          ],
+        }],
+        ['OS!="ios" and OS!="android" and chromecast==0', {
+          'dependencies': [
+            '../chrome/chrome.gyp:browser_tests',
+            '../chrome/chrome.gyp:chromedriver_tests',
+            '../chrome/chrome.gyp:chromedriver_unittests',
+            '../chrome/chrome.gyp:interactive_ui_tests',
+            '../chrome/chrome.gyp:sync_integration_tests',
+            '../chrome/chrome.gyp:unit_tests',
+            '../extensions/extensions_tests.gyp:extensions_browsertests',
+            '../extensions/extensions_tests.gyp:extensions_unittests',
+          ],
+        }],
+        ['OS=="win"', {
+          'dependencies': [
+            '../chrome/chrome.gyp:installer_util_unittests',
+            '../chrome/chrome.gyp:setup_unittests',
+            # ../chrome/test/mini_installer requires mini_installer.
+            '../chrome/installer/mini_installer.gyp:mini_installer',
+            '../chrome_elf/chrome_elf.gyp:chrome_elf_unittests',
+            '../courgette/courgette.gyp:courgette_unittests',
+            '../sandbox/sandbox.gyp:sbox_integration_tests',
+            '../sandbox/sandbox.gyp:sbox_unittests',
+            '../sandbox/sandbox.gyp:sbox_validation_tests',
+          ],
+          'conditions': [
+            # remoting_host_installation uses lots of non-trivial GYP that tend
+            # to break because of differences between ninja and msbuild. Make
+            # sure this target is built by the builders on the main waterfall.
+            # See http://crbug.com/180600.
+            ['wix_exists == "True" and sas_dll_exists == "True"', {
+              'dependencies': [
+                '../remoting/remoting.gyp:remoting_host_installation',
+              ],
+            }],
+            ['syzyasan==1', {
+              'variables': {
+                # Disable incremental linking for all modules.
+                # 0: inherit, 1: disabled, 2: enabled.
+                'msvs_debug_link_incremental': '1',
+                'msvs_large_module_debug_link_mode': '1',
+                # Disable RTC. Syzygy explicitly doesn't support RTC
+                # instrumented binaries for now.
+                'win_debug_RuntimeChecks': '0',
+              },
+              'defines': [
+                # Disable iterator debugging (huge speed boost).
+                '_HAS_ITERATOR_DEBUGGING=0',
+              ],
+              'msvs_settings': {
+                'VCLinkerTool': {
+                  # Enable profile information (necessary for SyzyAsan
+                  # instrumentation). This is incompatible with incremental
+                  # linking.
+                  'Profile': 'true',
+                },
+              }
+            }],
+            ['component!="shared_library" or target_arch!="ia32"', {
+              'dependencies': [
+                '../chrome/installer/mini_installer.gyp:next_version_mini_installer',
+              ],
+            }],
+          ],
+        }],
+        ['chromeos==1', {
+          'dependencies': [
+            '../ui/chromeos/ui_chromeos.gyp:ui_chromeos_unittests',
+            '../ui/arc/arc.gyp:ui_arc_unittests',
+          ],
+        }],
+        ['OS=="linux"', {
+          'dependencies': [
+            '../sandbox/sandbox.gyp:sandbox_linux_unittests',
+          ],
+        }],
+        ['OS=="linux" and use_dbus==1', {
+          'dependencies': [
+            '../dbus/dbus.gyp:dbus_unittests',
+          ],
+        }],
+        ['OS=="mac"', {
+          'dependencies': [
+            '../ui/message_center/message_center.gyp:*',
           ],
         }],
         ['test_isolation_mode != "noop"', {
           'dependencies': [
-            '../test/bot_default.gyp:*',
-            '../test/benchmarks/benchmarks.gyp:*',
-            '../test/default.gyp:*',
-            '../test/ignition.gyp:*',
-            '../test/intl/intl.gyp:*',
-            '../test/message/message.gyp:*',
-            '../test/mjsunit/mjsunit.gyp:*',
-            '../test/mozilla/mozilla.gyp:*',
-            '../test/optimize_for_size.gyp:*',
-            '../test/perf.gyp:*',
-            '../test/preparser/preparser.gyp:*',
-            '../test/simdjs/simdjs.gyp:*',
-            '../test/test262/test262.gyp:*',
-            '../test/webkit/webkit.gyp:*',
-            '../tools/check-static-initializers.gyp:*',
-            '../tools/gcmole/run_gcmole.gyp:*',
-            '../tools/jsfunfuzz/jsfunfuzz.gyp:*',
-            '../tools/run-deopt-fuzzer.gyp:*',
-            '../tools/run-valgrind.gyp:*',
+            'chromium_swarm_tests',
           ],
         }],
+        ['OS!="android"', {
+          'dependencies': [
+            '../google_apis/gcm/gcm.gyp:gcm_unit_tests',
+          ],
+        }],
+        ['enable_basic_printing==1 or enable_print_preview==1', {
+          'dependencies': [
+            '../printing/printing.gyp:printing_unittests',
+          ],
+        }],
+        ['enable_app_list==1', {
+          'dependencies': [
+            '../ui/app_list/app_list.gyp:app_list_unittests',
+          ],
+        }],
+        ['enable_app_list==1 and use_aura==1', {
+          'dependencies': [
+            '../ui/app_list/presenter/app_list_presenter.gyp:app_list_presenter_unittests',
+          ],
+        }],
+        ['use_aura==1', {
+          'dependencies': [
+            '../ash/ash.gyp:ash_unittests',
+            '../ui/aura/aura.gyp:aura_unittests',
+            '../ui/compositor/compositor.gyp:compositor_unittests',
+          ],
+        }],
+        ['use_aura==1 and chromecast==0', {
+          'dependencies': [
+            '../ui/keyboard/keyboard.gyp:keyboard_unittests',
+            '../ui/views/views.gyp:views_unittests',
+          ],
+        }],
+        ['use_aura==1 or toolkit_views==1', {
+          'dependencies': [
+            '../ui/events/events_unittests.gyp:events_unittests',
+          ],
+        }],
+        ['disable_nacl==0', {
+          'dependencies': [
+            '../components/nacl.gyp:nacl_loader_unittests',
+          ],
+        }],
+        ['disable_nacl==0 and disable_nacl_untrusted==0 and enable_nacl_nonsfi_test==1', {
+          'dependencies': [
+            '../components/nacl.gyp:nacl_helper_nonsfi_unittests',
+          ],
+        }],
+      ],
+    }, # target_name: chromium_builder_tests
+  ],
+  'conditions': [
+    # TODO(GYP): make gn_migration.gypi work unconditionally.
+    ['OS=="mac" or OS=="win" or (OS=="android" and chromecast==0) or (OS=="linux" and target_arch=="x64" and chromecast==0)', {
+      'includes': [
+        'gn_migration.gypi',
+      ],
+    }],
+    ['OS!="ios"', {
+      'targets': [
+        {
+          'target_name': 'blink_tests',
+          'type': 'none',
+          'dependencies': [
+            '../third_party/WebKit/public/all.gyp:all_blink',
+          ],
+          'conditions': [
+            ['OS=="android"', {
+              'dependencies': [
+                '../content/content_shell_and_tests.gyp:content_shell_apk',
+                '../breakpad/breakpad.gyp:dump_syms#host',
+                '../breakpad/breakpad.gyp:minidump_stackwalk#host',
+                '../tools/imagediff/image_diff.gyp:image_diff#host',
+              ],
+            }, {  # OS!="android"
+              'dependencies': [
+                '../content/content_shell_and_tests.gyp:content_shell',
+                '../tools/imagediff/image_diff.gyp:image_diff',
+              ],
+            }],
+            ['OS=="win"', {
+              'dependencies': [
+                '../components/test_runner/test_runner.gyp:layout_test_helper',
+                '../content/content_shell_and_tests.gyp:content_shell_crash_service',
+              ],
+            }],
+            ['OS!="win" and OS!="android"', {
+              'dependencies': [
+                '../breakpad/breakpad.gyp:minidump_stackwalk',
+              ],
+            }],
+            ['OS=="mac"', {
+              'dependencies': [
+                '../components/test_runner/test_runner.gyp:layout_test_helper',
+                '../breakpad/breakpad.gyp:dump_syms#host',
+              ],
+            }],
+            ['OS=="linux"', {
+              'dependencies': [
+                '../breakpad/breakpad.gyp:dump_syms#host',
+              ],
+            }],
+          ],
+        }, # target_name: blink_tests
+      ],
+    }], # OS!=ios
+    ['OS!="ios" and OS!="android" and chromecast==0', {
+      'targets': [
+        {
+          'target_name': 'chromium_builder_nacl_win_integration',
+          'type': 'none',
+          'dependencies': [
+            'chromium_builder_tests',
+          ],
+        }, # target_name: chromium_builder_nacl_win_integration
+        {
+          'target_name': 'chromium_builder_perf',
+          'type': 'none',
+          'dependencies': [
+            '../cc/cc_tests.gyp:cc_perftests',
+            '../chrome/chrome.gyp:chrome',
+            '../chrome/chrome.gyp:load_library_perf_tests',
+            '../chrome/chrome.gyp:performance_browser_tests',
+            '../chrome/chrome.gyp:sync_performance_tests',
+            '../gpu/gpu.gyp:gpu_perftests',
+            '../media/media.gyp:media_perftests',
+            '../media/midi/midi.gyp:midi_unittests',
+            '../tools/perf/clear_system_cache/clear_system_cache.gyp:*',
+            '../third_party/catapult/telemetry/telemetry.gyp:*',
+          ],
+          'conditions': [
+            ['OS!="ios" and OS!="win"', {
+              'dependencies': [
+                '../breakpad/breakpad.gyp:minidump_stackwalk',
+              ],
+            }],
+            ['OS=="linux"', {
+              'dependencies': [
+                '../chrome/chrome.gyp:linux_symbols'
+              ],
+            }],
+            ['OS=="win"', {
+              'dependencies': [
+                '../chrome/installer/mini_installer.gyp:mini_installer',
+                '../gpu/gpu.gyp:angle_perftests',
+              ],
+            }],
+          ],
+        }, # target_name: chromium_builder_perf
+        {
+          'target_name': 'chromium_gpu_builder',
+          'type': 'none',
+          'dependencies': [
+            '../chrome/chrome.gyp:chrome',
+            '../chrome/chrome.gyp:performance_browser_tests',
+            '../content/content_shell_and_tests.gyp:content_browsertests',
+            '../gpu/gles2_conform_support/gles2_conform_test.gyp:gles2_conform_test',
+            '../gpu/khronos_glcts_support/khronos_glcts_test.gyp:khronos_glcts_test',
+            '../gpu/gpu.gyp:gl_tests',
+            '../gpu/gpu.gyp:angle_unittests',
+            '../gpu/gpu.gyp:gpu_unittests',
+            '../gpu/gpu.gyp:command_buffer_gles2_tests',
+            '../third_party/catapult/telemetry/telemetry.gyp:*',
+          ],
+          'conditions': [
+            ['OS!="ios" and OS!="win"', {
+              'dependencies': [
+                '../breakpad/breakpad.gyp:minidump_stackwalk',
+              ],
+            }],
+            ['OS=="linux"', {
+              'dependencies': [
+                '../chrome/chrome.gyp:linux_symbols'
+              ],
+            }],
+          ],
+        }, # target_name: chromium_gpu_builder
+        {
+          'target_name': 'chromium_gpu_debug_builder',
+          'type': 'none',
+          'dependencies': [
+            '../chrome/chrome.gyp:chrome',
+            '../content/content_shell_and_tests.gyp:content_browsertests',
+            '../gpu/gles2_conform_support/gles2_conform_test.gyp:gles2_conform_test',
+            '../gpu/khronos_glcts_support/khronos_glcts_test.gyp:khronos_glcts_test',
+            '../gpu/gpu.gyp:gl_tests',
+            '../gpu/gpu.gyp:angle_unittests',
+            '../gpu/gpu.gyp:gpu_unittests',
+            '../gpu/gpu.gyp:command_buffer_gles2_tests',
+            '../third_party/catapult/telemetry/telemetry.gyp:*',
+          ],
+          'conditions': [
+            ['OS!="ios" and OS!="win"', {
+              'dependencies': [
+                '../breakpad/breakpad.gyp:minidump_stackwalk',
+              ],
+            }],
+            ['OS=="linux"', {
+              'dependencies': [
+                '../chrome/chrome.gyp:linux_symbols'
+              ],
+            }],
+          ],
+        }, # target_name: chromium_gpu_debug_builder
+        {
+          # This target contains everything we need to run tests on the special
+          # device-equipped WebRTC bots. We have device-requiring tests in
+          # browser_tests and content_browsertests.
+          'target_name': 'chromium_builder_webrtc',
+          'type': 'none',
+          'dependencies': [
+            'chromium_builder_perf',
+            '../chrome/chrome.gyp:browser_tests',
+            '../content/content_shell_and_tests.gyp:content_browsertests',
+            '../content/content_shell_and_tests.gyp:content_unittests',
+            '../media/media.gyp:media_unittests',
+            '../media/midi/midi.gyp:midi_unittests',
+            '../third_party/webrtc/tools/tools.gyp:frame_analyzer',
+            '../third_party/webrtc/tools/tools.gyp:rgba_to_i420_converter',
+          ],
+          'conditions': [
+            ['remoting==1', {
+              'dependencies': [
+                '../remoting/remoting.gyp:*',
+              ],
+            }],
+          ],
+        },  # target_name: chromium_builder_webrtc
+        {
+          'target_name': 'chromium_builder_chromedriver',
+          'type': 'none',
+          'dependencies': [
+            '../chrome/chrome.gyp:chromedriver',
+            '../chrome/chrome.gyp:chromedriver_tests',
+            '../chrome/chrome.gyp:chromedriver_unittests',
+          ],
+        },  # target_name: chromium_builder_chromedriver
+        {
+          'target_name': 'chromium_builder_asan',
+          'type': 'none',
+          'dependencies': [
+            '../chrome/chrome.gyp:chrome',
+
+            # We refer to content_shell directly rather than blink_tests
+            # because we don't want the _unittests binaries.
+            '../content/content_shell_and_tests.gyp:content_shell',
+          ],
+          'conditions': [
+            ['OS!="win"', {
+              'dependencies': [
+                '../net/net.gyp:hpack_fuzz_wrapper',
+                '../net/net.gyp:dns_fuzz_stub',
+                '../skia/skia.gyp:filter_fuzz_stub',
+              ],
+            }],
+            ['enable_ipc_fuzzer==1 and component!="shared_library" and '
+                 '(OS=="linux" or OS=="win" or OS=="mac")', {
+              'dependencies': [
+                '../tools/ipc_fuzzer/ipc_fuzzer.gyp:*',
+              ],
+            }],
+            ['chromeos==0', {
+              'dependencies': [
+                '../v8/samples/samples.gyp:v8_shell#host',
+                '../third_party/pdfium/samples/samples.gyp:pdfium_test',
+              ],
+            }],
+            ['internal_filter_fuzzer==1', {
+              'dependencies': [
+                '../skia/tools/clusterfuzz-data/fuzzers/filter_fuzzer/filter_fuzzer.gyp:filter_fuzzer',
+              ],
+            }], # internal_filter_fuzzer
+            ['clang==1', {
+              'dependencies': [
+                'sanitizers/sanitizers.gyp:llvm-symbolizer',
+              ],
+            }],
+            ['OS=="win" and fastbuild==0 and target_arch=="ia32" and syzyasan==1', {
+              'dependencies': [
+                '../chrome/chrome_syzygy.gyp:chrome_dll_syzygy',
+                '../content/content_shell_and_tests.gyp:content_shell_syzyasan',
+              ],
+              'conditions': [
+                ['chrome_multiple_dll==1', {
+                  'dependencies': [
+                    '../chrome/chrome_syzygy.gyp:chrome_child_dll_syzygy',
+                  ],
+                }],
+              ],
+            }],
+          ],
+        },
+        {
+          'target_name': 'chromium_builder_nacl_sdk',
+          'type': 'none',
+          'dependencies': [
+            '../chrome/chrome.gyp:chrome',
+          ],
+          'conditions': [
+            ['OS=="win"', {
+              'dependencies': [
+                '../chrome/chrome.gyp:chrome_nacl_win64',
+              ]
+            }],
+          ],
+        },  #target_name: chromium_builder_nacl_sdk
+      ],  # targets
+    }], #OS!=ios and OS!=android
+    ['OS=="android"', {
+      'targets': [
+        {
+          # The current list of tests for android.  This is temporary
+          # until the full set supported.
+          #
+          # WARNING:
+          # Do not add targets here without communicating the implications
+          # on tryserver triggers and load.  Discuss with
+          # chrome-infrastructure-team please.
+          'target_name': 'android_builder_tests',
+          'type': 'none',
+          'dependencies': [
+            '../base/android/jni_generator/jni_generator.gyp:jni_generator_tests',
+            '../base/base.gyp:base_unittests',
+            '../breakpad/breakpad.gyp:breakpad_unittests_deps',
+            # Also compile the tools needed to deal with minidumps, they are
+            # needed to run minidump tests upstream.
+            '../breakpad/breakpad.gyp:dump_syms#host',
+            '../breakpad/breakpad.gyp:symupload#host',
+            '../breakpad/breakpad.gyp:minidump_dump#host',
+            '../breakpad/breakpad.gyp:minidump_stackwalk#host',
+            '../build/android/pylib/device/commands/commands.gyp:chromium_commands',
+            '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
+            '../cc/cc_tests.gyp:cc_perftests_apk',
+            '../cc/cc_tests.gyp:cc_unittests',
+            '../components/components_tests.gyp:components_unittests',
+            '../content/content_shell_and_tests.gyp:content_browsertests',
+            '../content/content_shell_and_tests.gyp:content_junit_tests',
+            '../content/content_shell_and_tests.gyp:chromium_linker_test_apk',
+            '../content/content_shell_and_tests.gyp:content_shell_test_apk',
+            '../content/content_shell_and_tests.gyp:content_unittests',
+            '../gpu/gpu.gyp:gl_tests',
+            '../gpu/gpu.gyp:gpu_perftests_apk',
+            '../gpu/gpu.gyp:gpu_unittests',
+            '../ipc/ipc.gyp:ipc_tests',
+            '../media/media.gyp:media_perftests_apk',
+            '../media/media.gyp:media_unittests',
+            '../media/midi/midi.gyp:midi_unittests_apk',
+            '../media/midi/midi.gyp:midi_unittests',
+            '../net/net.gyp:net_unittests',
+            '../sandbox/sandbox.gyp:sandbox_linux_unittests_deps',
+            '../skia/skia_tests.gyp:skia_unittests',
+            '../sql/sql.gyp:sql_unittests',
+            '../sync/sync.gyp:sync_unit_tests',
+            '../testing/android/junit/junit_test.gyp:junit_unit_tests',
+            '../third_party/leveldatabase/leveldatabase.gyp:env_chromium_unittests',
+            '../third_party/WebKit/public/all.gyp:*',
+            '../tools/android/android_tools.gyp:android_tools',
+            '../tools/android/android_tools.gyp:memconsumer',
+            '../tools/android/android_tools.gyp:push_apps_to_background',
+            '../tools/android/findbugs_plugin/findbugs_plugin.gyp:findbugs_plugin_test',
+            '../tools/cygprofile/cygprofile.gyp:cygprofile_unittests',
+            '../ui/android/ui_android.gyp:ui_android_unittests',
+            '../ui/base/ui_base_tests.gyp:ui_base_unittests',
+            '../ui/events/events_unittests.gyp:events_unittests',
+            '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
+            # Unit test bundles packaged as an apk.
+            '../base/base.gyp:base_unittests_apk',
+            '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests_apk',
+            '../cc/cc_tests.gyp:cc_unittests_apk',
+            '../components/components_tests.gyp:components_browsertests_apk',
+            '../components/components_tests.gyp:components_unittests_apk',
+            '../content/content_shell_and_tests.gyp:content_browsertests_apk',
+            '../content/content_shell_and_tests.gyp:content_unittests_apk',
+            '../gpu/gpu.gyp:command_buffer_gles2_tests_apk',
+            '../gpu/gpu.gyp:gl_tests_apk',
+            '../gpu/gpu.gyp:gpu_unittests_apk',
+            '../ipc/ipc.gyp:ipc_tests_apk',
+            '../media/media.gyp:media_unittests_apk',
+            '../media/media.gyp:video_decode_accelerator_unittest_apk',
+            '../media/midi/midi.gyp:midi_unittests_apk',
+            '../net/net.gyp:net_unittests_apk',
+            '../skia/skia_tests.gyp:skia_unittests_apk',
+            '../sql/sql.gyp:sql_unittests_apk',
+            '../sync/sync.gyp:sync_unit_tests_apk',
+            '../tools/android/heap_profiler/heap_profiler.gyp:heap_profiler_unittests_apk',
+            '../ui/android/ui_android.gyp:ui_android_unittests_apk',
+            '../ui/android/ui_android.gyp:ui_junit_tests',
+            '../ui/base/ui_base_tests.gyp:ui_base_unittests_apk',
+            '../ui/events/events_unittests.gyp:events_unittests_apk',
+            '../ui/gfx/gfx_tests.gyp:gfx_unittests_apk',
+            '../ui/gl/gl_tests.gyp:gl_unittests_apk',
+            '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests_apk',
+          ],
+          'conditions': [
+            ['chromecast==0', {
+              'dependencies': [
+                '../android_webview/android_webview.gyp:android_webview_unittests',
+                '../chrome/chrome.gyp:unit_tests',
+                # Unit test bundles packaged as an apk.
+                '../android_webview/android_webview.gyp:android_webview_test_apk',
+                '../android_webview/android_webview.gyp:android_webview_unittests_apk',
+                '../android_webview/android_webview_shell.gyp:system_webview_shell_layout_test_apk',
+                '../android_webview/android_webview_shell.gyp:system_webview_shell_page_cycler_apk',
+                '../chrome/android/chrome_apk.gyp:chrome_public_test_apk',
+                '../chrome/android/chrome_apk.gyp:chrome_sync_shell_test_apk',
+                '../chrome/chrome.gyp:chrome_junit_tests',
+                '../chrome/chrome.gyp:chromedriver_webview_shell_apk',
+                '../chrome/chrome.gyp:unit_tests_apk',
+                '../third_party/custom_tabs_client/custom_tabs_client.gyp:custom_tabs_client_example_apk',
+              ],
+            }],
+          ],
+        },
+        {
+          # WebRTC Chromium tests to run on Android.
+          'target_name': 'android_builder_chromium_webrtc',
+          'type': 'none',
+          'dependencies': [
+            '../build/android/pylib/device/commands/commands.gyp:chromium_commands',
+            '../content/content_shell_and_tests.gyp:content_browsertests',
+            '../tools/android/android_tools.gyp:android_tools',
+            '../tools/android/android_tools.gyp:memconsumer',
+            '../content/content_shell_and_tests.gyp:content_browsertests_apk',
+          ],
+        },  # target_name: android_builder_chromium_webrtc
+      ], # targets
+    }], # OS="android"
+    ['OS=="mac"', {
+      'targets': [
+        {
+          # Target to build everything plus the dmg.  We don't put the dmg
+          # in the All target because developers really don't need it.
+          'target_name': 'all_and_dmg',
+          'type': 'none',
+          'dependencies': [
+            'All',
+            '../chrome/chrome.gyp:build_app_dmg',
+          ],
+        },
+        # These targets are here so the build bots can use them to build
+        # subsets of a full tree for faster cycle times.
+        {
+          'target_name': 'chromium_builder_dbg',
+          'type': 'none',
+          'dependencies': [
+            '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
+            '../cc/cc_tests.gyp:cc_unittests',
+            '../chrome/chrome.gyp:browser_tests',
+            '../chrome/chrome.gyp:interactive_ui_tests',
+            '../chrome/chrome.gyp:sync_integration_tests',
+            '../chrome/chrome.gyp:unit_tests',
+            '../components/components_tests.gyp:components_unittests',
+            '../content/content_shell_and_tests.gyp:content_browsertests',
+            '../content/content_shell_and_tests.gyp:content_unittests',
+            '../device/device_tests.gyp:device_unittests',
+            '../google_apis/gcm/gcm.gyp:gcm_unit_tests',
+            '../gpu/gpu.gyp:gpu_unittests',
+            '../ipc/ipc.gyp:ipc_tests',
+            '../ipc/mojo/ipc_mojo.gyp:ipc_mojo_unittests',
+            '../jingle/jingle.gyp:jingle_unittests',
+            '../media/media.gyp:media_unittests',
+            '../media/midi/midi.gyp:midi_unittests',
+            '../ppapi/ppapi_internal.gyp:ppapi_unittests',
+            '../printing/printing.gyp:printing_unittests',
+            '../remoting/remoting.gyp:remoting_unittests',
+            '../rlz/rlz.gyp:*',
+            '../skia/skia_tests.gyp:skia_unittests',
+            '../sql/sql.gyp:sql_unittests',
+            '../sync/sync.gyp:sync_unit_tests',
+            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
+            '../third_party/leveldatabase/leveldatabase.gyp:env_chromium_unittests',
+            '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_unittests',
+            '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber_unittests',
+            '../tools/perf/clear_system_cache/clear_system_cache.gyp:*',
+            '../third_party/catapult/telemetry/telemetry.gyp:*',
+            '../ui/base/ui_base_tests.gyp:ui_base_unittests',
+            '../ui/gfx/gfx_tests.gyp:gfx_unittests',
+            '../ui/gl/gl_tests.gyp:gl_unittests',
+            '../url/url.gyp:url_unittests',
+          ],
+        },
+        {
+          'target_name': 'chromium_builder_rel',
+          'type': 'none',
+          'dependencies': [
+            '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
+            '../cc/cc_tests.gyp:cc_unittests',
+            '../chrome/chrome.gyp:browser_tests',
+            '../chrome/chrome.gyp:performance_browser_tests',
+            '../chrome/chrome.gyp:sync_integration_tests',
+            '../chrome/chrome.gyp:unit_tests',
+            '../components/components_tests.gyp:components_unittests',
+            '../content/content_shell_and_tests.gyp:content_browsertests',
+            '../content/content_shell_and_tests.gyp:content_unittests',
+            '../device/device_tests.gyp:device_unittests',
+            '../google_apis/gcm/gcm.gyp:gcm_unit_tests',
+            '../gpu/gpu.gyp:gpu_unittests',
+            '../ipc/ipc.gyp:ipc_tests',
+            '../ipc/mojo/ipc_mojo.gyp:ipc_mojo_unittests',
+            '../jingle/jingle.gyp:jingle_unittests',
+            '../media/media.gyp:media_unittests',
+            '../media/midi/midi.gyp:midi_unittests',
+            '../ppapi/ppapi_internal.gyp:ppapi_unittests',
+            '../printing/printing.gyp:printing_unittests',
+            '../remoting/remoting.gyp:remoting_unittests',
+            '../skia/skia_tests.gyp:skia_unittests',
+            '../sql/sql.gyp:sql_unittests',
+            '../sync/sync.gyp:sync_unit_tests',
+            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
+            '../third_party/leveldatabase/leveldatabase.gyp:env_chromium_unittests',
+            '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_unittests',
+            '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber_unittests',
+            '../tools/perf/clear_system_cache/clear_system_cache.gyp:*',
+            '../third_party/catapult/telemetry/telemetry.gyp:*',
+            '../ui/base/ui_base_tests.gyp:ui_base_unittests',
+            '../ui/gfx/gfx_tests.gyp:gfx_unittests',
+            '../ui/gl/gl_tests.gyp:gl_unittests',
+            '../url/url.gyp:url_unittests',
+          ],
+        },
+        {
+          'target_name': 'chromium_builder_dbg_tsan_mac',
+          'type': 'none',
+          'dependencies': [
+            '../base/base.gyp:base_unittests',
+            '../crypto/crypto.gyp:crypto_unittests',
+            '../ipc/ipc.gyp:ipc_tests',
+            '../jingle/jingle.gyp:jingle_unittests',
+            '../media/media.gyp:media_unittests',
+            '../media/midi/midi.gyp:midi_unittests',
+            '../net/net.gyp:net_unittests',
+            '../printing/printing.gyp:printing_unittests',
+            '../remoting/remoting.gyp:remoting_unittests',
+            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
+            '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_unittests',
+            '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber_unittests',
+            '../url/url.gyp:url_unittests',
+          ],
+        },
+     ],  # targets
+    }], # OS="mac"
+    ['OS=="win"', {
+      'targets': [
+        # These targets are here so the build bots can use them to build
+        # subsets of a full tree for faster cycle times.
+        {
+          'target_name': 'chromium_builder',
+          'type': 'none',
+          'dependencies': [
+            '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
+            '../cc/cc_tests.gyp:cc_unittests',
+            '../chrome/chrome.gyp:browser_tests',
+            '../chrome/chrome.gyp:gcapi_test',
+            '../chrome/chrome.gyp:installer_util_unittests',
+            '../chrome/chrome.gyp:interactive_ui_tests',
+            '../chrome/chrome.gyp:performance_browser_tests',
+            '../chrome/chrome.gyp:setup_unittests',
+            '../chrome/chrome.gyp:sync_integration_tests',
+            '../chrome/chrome.gyp:unit_tests',
+            '../components/components_tests.gyp:components_unittests',
+            '../content/content_shell_and_tests.gyp:content_browsertests',
+            '../content/content_shell_and_tests.gyp:content_unittests',
+            # ../chrome/test/mini_installer requires mini_installer.
+            '../chrome/installer/mini_installer.gyp:mini_installer',
+            '../courgette/courgette.gyp:courgette_unittests',
+            '../device/device_tests.gyp:device_unittests',
+            '../google_apis/gcm/gcm.gyp:gcm_unit_tests',
+            '../gpu/gpu.gyp:gpu_unittests',
+            '../ipc/ipc.gyp:ipc_tests',
+            '../ipc/mojo/ipc_mojo.gyp:ipc_mojo_unittests',
+            '../jingle/jingle.gyp:jingle_unittests',
+            '../media/media.gyp:media_unittests',
+            '../media/midi/midi.gyp:midi_unittests',
+            '../ppapi/ppapi_internal.gyp:ppapi_unittests',
+            '../printing/printing.gyp:printing_unittests',
+            '../remoting/remoting.gyp:remoting_unittests',
+            '../skia/skia_tests.gyp:skia_unittests',
+            '../sql/sql.gyp:sql_unittests',
+            '../sync/sync.gyp:sync_unit_tests',
+            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
+            '../third_party/leveldatabase/leveldatabase.gyp:env_chromium_unittests',
+            '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_unittests',
+            '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber_unittests',
+            '../tools/perf/clear_system_cache/clear_system_cache.gyp:*',
+            '../third_party/catapult/telemetry/telemetry.gyp:*',
+            '../ui/base/ui_base_tests.gyp:ui_base_unittests',
+            '../ui/events/events_unittests.gyp:events_unittests',
+            '../ui/gfx/gfx_tests.gyp:gfx_unittests',
+            '../ui/gl/gl_tests.gyp:gl_unittests',
+            '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
+            '../ui/views/views.gyp:views_unittests',
+            '../url/url.gyp:url_unittests',
+          ],
+        },
+        {
+          'target_name': 'chromium_builder_dbg_tsan_win',
+          'type': 'none',
+          'dependencies': [
+            '../base/base.gyp:base_unittests',
+            '../components/components_tests.gyp:components_unittests',
+            '../content/content_shell_and_tests.gyp:content_unittests',
+            '../crypto/crypto.gyp:crypto_unittests',
+            '../ipc/ipc.gyp:ipc_tests',
+            '../jingle/jingle.gyp:jingle_unittests',
+            '../media/media.gyp:media_unittests',
+            '../media/midi/midi.gyp:midi_unittests',
+            '../net/net.gyp:net_unittests',
+            '../printing/printing.gyp:printing_unittests',
+            '../remoting/remoting.gyp:remoting_unittests',
+            '../sql/sql.gyp:sql_unittests',
+            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
+            '../third_party/leveldatabase/leveldatabase.gyp:env_chromium_unittests',
+            '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_unittests',
+            '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber_unittests',
+            '../url/url.gyp:url_unittests',
+          ],
+        },
+        {
+          'target_name': 'chromium_builder_lkgr_drmemory_win',
+          'type': 'none',
+          'dependencies': [
+            '../components/test_runner/test_runner.gyp:layout_test_helper',
+            '../content/content_shell_and_tests.gyp:content_shell',
+            '../content/content_shell_and_tests.gyp:content_shell_crash_service',
+          ],
+        },
+        {
+          'target_name': 'chromium_builder_dbg_drmemory_win',
+          'type': 'none',
+          'dependencies': [
+            '../base/base.gyp:base_unittests',
+            '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
+            '../cc/cc_tests.gyp:cc_unittests',
+            '../chrome/chrome.gyp:browser_tests',
+            '../chrome/chrome.gyp:chrome_app_unittests',
+            '../chrome/chrome.gyp:chromedriver_unittests',
+            '../chrome/chrome.gyp:installer_util_unittests',
+            '../chrome/chrome.gyp:setup_unittests',
+            '../chrome/chrome.gyp:unit_tests',
+            '../chrome_elf/chrome_elf.gyp:chrome_elf_unittests',
+            '../components/components_tests.gyp:components_unittests',
+            '../components/test_runner/test_runner.gyp:layout_test_helper',
+            '../content/content_shell_and_tests.gyp:content_browsertests',
+            '../content/content_shell_and_tests.gyp:content_shell',
+            '../content/content_shell_and_tests.gyp:content_shell_crash_service',
+            '../content/content_shell_and_tests.gyp:content_unittests',
+            '../courgette/courgette.gyp:courgette_unittests',
+            '../crypto/crypto.gyp:crypto_unittests',
+            '../device/device_tests.gyp:device_unittests',
+            '../extensions/extensions_tests.gyp:extensions_browsertests',
+            '../extensions/extensions_tests.gyp:extensions_unittests',
+            '../gin/gin.gyp:gin_shell',
+            '../gin/gin.gyp:gin_unittests',
+            '../google_apis/gcm/gcm.gyp:gcm_unit_tests',
+            '../google_apis/google_apis.gyp:google_apis_unittests',
+            '../gpu/gpu.gyp:angle_unittests',
+            '../gpu/gpu.gyp:gpu_unittests',
+            '../ipc/ipc.gyp:ipc_tests',
+            '../ipc/mojo/ipc_mojo.gyp:ipc_mojo_unittests',
+            '../jingle/jingle.gyp:jingle_unittests',
+            '../media/cast/cast.gyp:cast_unittests',
+            '../media/media.gyp:media_unittests',
+            '../media/midi/midi.gyp:midi_unittests',
+            '../mojo/mojo.gyp:mojo',
+            '../net/net.gyp:net_unittests',
+            '../printing/printing.gyp:printing_unittests',
+            '../remoting/remoting.gyp:remoting_unittests',
+            '../skia/skia_tests.gyp:skia_unittests',
+            '../sql/sql.gyp:sql_unittests',
+            '../sync/sync.gyp:sync_unit_tests',
+            '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests',
+            '../third_party/leveldatabase/leveldatabase.gyp:env_chromium_unittests',
+            '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_unittests',
+            '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber_unittests',
+            '../third_party/WebKit/Source/platform/blink_platform_tests.gyp:blink_heap_unittests',
+            '../third_party/WebKit/Source/platform/blink_platform_tests.gyp:blink_platform_unittests',
+            '../ui/accessibility/accessibility.gyp:accessibility_unittests',
+            '../ui/aura/aura.gyp:aura_unittests',
+            '../ui/compositor/compositor.gyp:compositor_unittests',
+            '../ui/display/display.gyp:display_unittests',
+            '../ui/events/events_unittests.gyp:events_unittests',
+            '../ui/gfx/gfx_tests.gyp:gfx_unittests',
+            '../ui/gl/gl_tests.gyp:gl_unittests',
+            '../ui/keyboard/keyboard.gyp:keyboard_unittests',
+            '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
+            '../url/url.gyp:url_unittests',
+          ],
+        },
+      ],  # targets
+      'conditions': [
+        ['branding=="Chrome"', {
+          'targets': [
+            {
+              'target_name': 'chrome_official_builder_no_unittests',
+              'type': 'none',
+              'dependencies': [
+                '../chrome/chrome.gyp:gcapi_dll',
+                '../chrome/chrome.gyp:pack_policy_templates',
+                '../chrome/installer/mini_installer.gyp:mini_installer',
+                '../courgette/courgette.gyp:courgette',
+                '../courgette/courgette.gyp:courgette64',
+                '../remoting/remoting.gyp:remoting_webapp',
+                '../third_party/widevine/cdm/widevine_cdm.gyp:widevinecdmadapter',
+              ],
+              'conditions': [
+                ['component != "shared_library" and wix_exists == "True" and \
+                    sas_dll_exists == "True"', {
+                  'dependencies': [
+                    '../remoting/remoting.gyp:remoting_host_installation',
+                  ],
+                }], # component != "shared_library"
+              ]
+            }, {
+              'target_name': 'chrome_official_builder',
+              'type': 'none',
+              'dependencies': [
+                'chrome_official_builder_no_unittests',
+                '../base/base.gyp:base_unittests',
+                '../chrome/chrome.gyp:browser_tests',
+                '../chrome/chrome.gyp:sync_integration_tests',
+                '../ipc/ipc.gyp:ipc_tests',
+                '../media/media.gyp:media_unittests',
+                '../media/midi/midi.gyp:midi_unittests',
+                '../net/net.gyp:net_unittests',
+                '../printing/printing.gyp:printing_unittests',
+                '../sql/sql.gyp:sql_unittests',
+                '../sync/sync.gyp:sync_unit_tests',
+                '../ui/base/ui_base_tests.gyp:ui_base_unittests',
+                '../ui/gfx/gfx_tests.gyp:gfx_unittests',
+                '../ui/gl/gl_tests.gyp:gl_unittests',
+                '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
+                '../ui/views/views.gyp:views_unittests',
+                '../url/url.gyp:url_unittests',
+              ],
+            },
+          ], # targets
+        }], # branding=="Chrome"
+       ], # conditions
+    }], # OS="win"
+    ['chromeos==1', {
+      'targets': [
+        {
+          'target_name': 'chromiumos_preflight',
+          'type': 'none',
+          'dependencies': [
+            '../breakpad/breakpad.gyp:minidump_stackwalk',
+            '../chrome/chrome.gyp:chrome',
+            '../chrome/chrome.gyp:chromedriver',
+            '../media/media.gyp:media_unittests',
+            '../media/media.gyp:video_decode_accelerator_unittest',
+            '../media/media.gyp:video_encode_accelerator_unittest',
+            '../ppapi/ppapi_internal.gyp:ppapi_example_video_decode',
+            '../sandbox/sandbox.gyp:chrome_sandbox',
+            '../sandbox/sandbox.gyp:sandbox_linux_unittests',
+            '../third_party/catapult/telemetry/telemetry.gyp:bitmaptools#host',
+            '../third_party/mesa/mesa.gyp:osmesa',
+            '../tools/perf/clear_system_cache/clear_system_cache.gyp:clear_system_cache',
+          ],
+          'conditions': [
+            ['disable_nacl==0', {
+              'dependencies': [
+                '../components/nacl.gyp:nacl_helper',
+                '../native_client/src/trusted/service_runtime/linux/nacl_bootstrap.gyp:nacl_helper_bootstrap',
+              ],
+            }],
+          ],
+        },
+      ],  # targets
+    }], # "chromeos==1"
+    ['use_aura==1', {
+      'targets': [
+        {
+          'target_name': 'aura_builder',
+          'type': 'none',
+          'dependencies': [
+            '../ash/ash.gyp:ash_shell_with_content',
+            '../ash/ash.gyp:ash_unittests',
+            '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
+            '../cc/cc_tests.gyp:cc_unittests',
+            '../components/components_tests.gyp:components_unittests',
+            '../content/content_shell_and_tests.gyp:content_browsertests',
+            '../content/content_shell_and_tests.gyp:content_unittests',
+            '../device/device_tests.gyp:device_unittests',
+            '../google_apis/gcm/gcm.gyp:gcm_unit_tests',
+            '../ppapi/ppapi_internal.gyp:ppapi_unittests',
+            '../remoting/remoting.gyp:remoting_unittests',
+            '../skia/skia_tests.gyp:skia_unittests',
+            '../ui/aura/aura.gyp:*',
+            '../ui/aura_extra/aura_extra.gyp:*',
+            '../ui/base/ui_base_tests.gyp:ui_base_unittests',
+            '../ui/compositor/compositor.gyp:*',
+            '../ui/display/display.gyp:display_unittests',
+            '../ui/events/events.gyp:*',
+            '../ui/gfx/gfx_tests.gyp:gfx_unittests',
+            '../ui/gl/gl_tests.gyp:gl_unittests',
+            '../ui/keyboard/keyboard.gyp:*',
+            '../ui/snapshot/snapshot.gyp:snapshot_unittests',
+            '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests',
+            '../ui/wm/wm.gyp:*',
+            'blink_tests',
+          ],
+          'conditions': [
+            ['OS=="linux"', {
+              # Tests that currently only work on Linux.
+              'dependencies': [
+                '../base/base.gyp:base_unittests',
+                '../ipc/ipc.gyp:ipc_tests',
+                '../sql/sql.gyp:sql_unittests',
+                '../sync/sync.gyp:sync_unit_tests',
+              ],
+            }],
+            ['chromeos==1', {
+              'dependencies': [
+                '../chromeos/chromeos.gyp:chromeos_unittests',
+                '../ui/chromeos/ui_chromeos.gyp:ui_chromeos_unittests',
+              ],
+            }],
+            ['use_ozone==1', {
+              'dependencies': [
+                '../ui/ozone/ozone.gyp:*',
+                '../ui/ozone/demo/ozone_demos.gyp:*',
+              ],
+            }],
+            ['enable_app_list==1', {
+              'dependencies': [
+                '../ui/app_list/app_list.gyp:*',
+              ],
+            }],
+            ['chromecast==0', {
+              'dependencies': [
+                '../chrome/chrome.gyp:browser_tests',
+                '../chrome/chrome.gyp:chrome',
+                '../chrome/chrome.gyp:interactive_ui_tests',
+                '../chrome/chrome.gyp:unit_tests',
+                '../ui/message_center/message_center.gyp:*',
+                '../ui/views/examples/examples.gyp:views_examples_with_content_exe',
+                '../ui/views/views.gyp:views',
+                '../ui/views/views.gyp:views_unittests',
+              ],
+            }],
+          ],
+        },
+      ],  # targets
+    }], # "use_aura==1"
+    ['test_isolation_mode != "noop"', {
+      'targets': [
+        {
+          'target_name': 'chromium_swarm_tests',
+          'type': 'none',
+          'dependencies': [
+            '../base/base.gyp:base_unittests_run',
+            '../content/content_shell_and_tests.gyp:content_browsertests_run',
+            '../content/content_shell_and_tests.gyp:content_unittests_run',
+            '../net/net.gyp:net_unittests_run',
+          ],
+          'conditions': [
+            ['chromecast==0', {
+              'dependencies': [
+                '../chrome/chrome.gyp:browser_tests_run',
+                '../chrome/chrome.gyp:interactive_ui_tests_run',
+                '../chrome/chrome.gyp:sync_integration_tests_run',
+                '../chrome/chrome.gyp:unit_tests_run',
+              ],
+            }],
+          ],
+        }, # target_name: chromium_swarm_tests
+      ],
+    }],
+    ['archive_chromoting_tests==1', {
+      'targets': [
+        {
+          'target_name': 'chromoting_swarm_tests',
+          'type': 'none',
+          'dependencies': [
+            '../testing/chromoting/integration_tests.gyp:*',
+          ],
+        }, # target_name: chromoting_swarm_tests
       ]
-    }
-  ]
+    }],
+    ['archive_media_router_tests==1', {
+      'targets': [
+        {
+          'target_name': 'media_router_swarming_tests',
+          'type': 'none',
+          'dependencies': [
+            '../chrome/test/media_router/e2e_tests.gyp:media_router_e2e_tests_run',
+          ],
+        }, # target_name: media_router_swarming_tests
+        {
+          'target_name': 'media_router_swarming_perf_tests',
+          'type': 'none',
+          'dependencies': [
+            '../chrome/test/media_router/e2e_tests.gyp:media_router_perf_tests_run',
+          ],
+        }, # target_name: media_router_swarming_perf_tests
+      ]
+    }],
+    ['OS=="mac" and toolkit_views==1', {
+      'targets': [
+        {
+          'target_name': 'macviews_builder',
+          'type': 'none',
+          'dependencies': [
+            '../ui/views/examples/examples.gyp:views_examples_with_content_exe',
+            '../ui/views/views.gyp:views',
+            '../ui/views/views.gyp:views_unittests',
+          ],
+        },  # target_name: macviews_builder
+      ],  # targets
+    }],  # os=='mac' and toolkit_views==1
+  ],  # conditions
 }
diff --git a/build/args/bots/official.desktop/blimp-engine.gn b/build/args/bots/official.desktop/blimp-engine.gn
index 2554c37..0f9cc6d 100644
--- a/build/args/bots/official.desktop/blimp-engine.gn
+++ b/build/args/bots/official.desktop/blimp-engine.gn
@@ -3,5 +3,8 @@
 # Use release build to improve engine performance, especially WebP encoding.
 is_debug = false
 
+# Designate this as an official build to pick up breakpad symbols.
+is_official_build = true
+
 # Turn on DCHECK to find bugs.
 dcheck_always_on = true
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index f775123..98b4aa6 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -21,6 +21,10 @@
     extra_chrome_shared_library_configs = []
   }
 
+  if (!defined(default_android_ndk_root)) {
+    default_android_ndk_root = "//third_party/android_tools/ndk"
+  }
+
   if (!defined(default_android_sdk_root)) {
     default_android_sdk_root = "//third_party/android_tools/sdk"
     default_android_sdk_version = "23"
@@ -51,6 +55,8 @@
   }
 
   declare_args() {
+    android_ndk_root = default_android_ndk_root
+
     android_sdk_root = default_android_sdk_root
     android_sdk_version = default_android_sdk_version
     android_sdk_build_tools_version = default_android_sdk_build_tools_version
@@ -147,7 +153,6 @@
   android_sdk = "${android_sdk_root}/platforms/android-${android_sdk_version}"
 
   # Path to the Android NDK and SDK.
-  android_ndk_root = "//third_party/android_tools/ndk"
   android_ndk_include_dir = "$android_ndk_root/usr/include"
 
   android_sdk_tools = "${android_sdk_root}/tools"
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 5429f9f..267c920 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -501,14 +501,8 @@
       }
     } else if (current_cpu == "arm") {
       if (is_clang && !is_android && !is_nacl) {
-        cflags += [
-          "-target",
-          "arm-linux-gnueabihf",
-        ]
-        ldflags += [
-          "-target",
-          "arm-linux-gnueabihf",
-        ]
+        cflags += [ "--target=arm-linux-gnueabihf" ]
+        ldflags += [ "--target=arm-linux-gnueabihf" ]
       }
       if (!is_nacl) {
         cflags += [
@@ -530,14 +524,10 @@
       if (mips_arch_variant == "r6") {
         if (is_clang) {
           cflags += [
-            "-target",
-            "mipsel-linux-gnu",
+            "--target=mipsel-linux-gnu",
             "-march=mips32r6",
           ]
-          ldflags += [
-            "-target",
-            "mipsel-linux-gnu",
-          ]
+          ldflags += [ "--target=mipsel-linux-gnu" ]
         } else {
           cflags += [
             "-mips32r6",
@@ -554,26 +544,18 @@
         if (is_clang) {
           if (is_android) {
             cflags += [
-              "-target",
-              "mipsel-linux-android",
+              "--target=mipsel-linux-android",
               "-march=mipsel",
               "-mcpu=mips32r2",
             ]
-            ldflags += [
-              "-target",
-              "mipsel-linux-android",
-            ]
+            ldflags += [ "--target=mipsel-linux-android" ]
           } else {
             cflags += [
-              "-target",
-              "mipsel-linux-gnu",
+              "--target=mipsel-linux-gnu",
               "-march=mipsel",
               "-mcpu=mips32r2",
             ]
-            ldflags += [
-              "-target",
-              "mipsel-linux-gnu",
-            ]
+            ldflags += [ "--target=mipsel-linux-gnu" ]
           }
         } else {
           cflags += [
@@ -588,26 +570,18 @@
         if (is_clang) {
           if (is_android) {
             cflags += [
-              "-target",
-              "mipsel-linux-android",
+              "--target=mipsel-linux-android",
               "-march=mipsel",
               "-mcpu=mips32",
             ]
-            ldflags += [
-              "-target",
-              "mipsel-linux-android",
-            ]
+            ldflags += [ "--target=mipsel-linux-android" ]
           } else {
             cflags += [
-              "-target",
-              "mipsel-linux-gnu",
+              "--target=mipsel-linux-gnu",
               "-march=mipsel",
               "-mcpu=mips32",
             ]
-            ldflags += [
-              "-target",
-              "mipsel-linux-gnu",
-            ]
+            ldflags += [ "--target=mipsel-linux-gnu" ]
           }
         } else {
           cflags += [
diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni
index b628d26..0b4493e 100644
--- a/build/config/ios/rules.gni
+++ b/build/config/ios/rules.gni
@@ -176,9 +176,6 @@
     bundle_resources_dir = bundle_root_dir
     bundle_executable_dir = bundle_root_dir
     bundle_plugins_dir = "$bundle_root_dir/Plugins"
-    assert(
-        product_type != "",
-        "workaround to allow generation with version of gn that don't support product_type property for create_bundle target => remove once gn has rolled this change")
   }
 
   # TODO(crbug.com/297668):
diff --git a/build/config/win/msvs_dependencies.isolate b/build/config/win/msvs_dependencies.isolate
index ff92227..d33aec4 100644
--- a/build/config/win/msvs_dependencies.isolate
+++ b/build/config/win/msvs_dependencies.isolate
@@ -1,4 +1,3 @@
-# Copyright 2015 the V8 project authors. All rights reserved.
 # Copyright 2015 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
@@ -46,6 +45,8 @@
         'files': [
           '<(PRODUCT_DIR)/x64/msvcp140d.dll',
           '<(PRODUCT_DIR)/x64/vccorlib140d.dll',
+          '<(PRODUCT_DIR)/x64/vcruntime140d.dll',
+          '<(PRODUCT_DIR)/x64/ucrtbased.dll',
         ],
       },
     }],
@@ -54,6 +55,8 @@
         'files': [
           '<(PRODUCT_DIR)/x64/msvcp140.dll',
           '<(PRODUCT_DIR)/x64/vccorlib140.dll',
+          '<(PRODUCT_DIR)/x64/vcruntime140.dll',
+          '<(PRODUCT_DIR)/x64/ucrtbase.dll',
         ],
       },
     }],
@@ -62,6 +65,8 @@
         'files': [
           '<(PRODUCT_DIR)/msvcp140d.dll',
           '<(PRODUCT_DIR)/vccorlib140d.dll',
+          '<(PRODUCT_DIR)/vcruntime140d.dll',
+          '<(PRODUCT_DIR)/ucrtbased.dll',
         ],
       },
     }],
@@ -70,8 +75,105 @@
         'files': [
           '<(PRODUCT_DIR)/msvcp140.dll',
           '<(PRODUCT_DIR)/vccorlib140.dll',
+          '<(PRODUCT_DIR)/vcruntime140.dll',
+          '<(PRODUCT_DIR)/ucrtbase.dll',
+        ],
+      },
+    }],
+    ['OS=="win" and msvs_version==2015 and component=="shared_library" and target_arch=="ia32"', {
+      # 32-bit builds have an x64 directory which also needs Windows 10
+      # Universal C Runtime binaries copied over.
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-console-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-datetime-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-debug-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-errorhandling-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-file-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-file-l1-2-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-file-l2-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-handle-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-heap-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-interlocked-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-libraryloader-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-localization-l1-2-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-memory-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-namedpipe-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-processenvironment-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-processthreads-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-processthreads-l1-1-1.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-profile-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-rtlsupport-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-string-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-synch-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-synch-l1-2-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-sysinfo-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-timezone-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-core-util-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-crt-conio-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-crt-convert-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-crt-environment-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-crt-filesystem-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-crt-heap-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-crt-locale-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-crt-math-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-crt-multibyte-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-crt-private-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-crt-process-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-crt-runtime-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-crt-stdio-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-crt-string-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-crt-time-l1-1-0.dll',
+          '<(PRODUCT_DIR)/x64/api-ms-win-crt-utility-l1-1-0.dll',
+        ],
+      },
+    }],
+    ['OS=="win" and msvs_version==2015 and component=="shared_library"', {
+      # Windows 10 Universal C Runtime binaries.
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/api-ms-win-core-console-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-datetime-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-debug-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-errorhandling-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-file-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-file-l1-2-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-file-l2-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-handle-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-heap-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-interlocked-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-libraryloader-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-localization-l1-2-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-memory-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-namedpipe-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-processenvironment-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-processthreads-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-processthreads-l1-1-1.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-profile-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-rtlsupport-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-string-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-synch-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-synch-l1-2-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-sysinfo-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-timezone-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-core-util-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-crt-conio-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-crt-convert-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-crt-environment-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-crt-filesystem-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-crt-heap-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-crt-locale-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-crt-math-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-crt-multibyte-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-crt-private-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-crt-process-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-crt-runtime-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-crt-stdio-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-crt-string-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-crt-time-l1-1-0.dll',
+          '<(PRODUCT_DIR)/api-ms-win-crt-utility-l1-1-0.dll',
         ],
       },
     }],
   ],
-}
\ No newline at end of file
+}
diff --git a/build/download_gold_plugin.py b/build/download_gold_plugin.py
index b8131fd..d4fb48b 100755
--- a/build/download_gold_plugin.py
+++ b/build/download_gold_plugin.py
@@ -1,32 +1,21 @@
 #!/usr/bin/env python
-# Copyright 2015 the V8 project authors. All rights reserved.
 # Copyright 2015 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
 """Script to download LLVM gold plugin from google storage."""
 
+import find_depot_tools
 import json
 import os
-import re
-import platform
 import shutil
 import subprocess
 import sys
 import zipfile
 
-# Bail out on windows and cygwin.
-if "win" in platform.system().lower():
-  # Python 2.7.6 hangs at the second path.insert command on windows. Works
-  # with python 2.7.8.
-  print "Gold plugin download not supported on windows."
-  sys.exit(0)
-
 SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
 CHROME_SRC = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir))
-sys.path.insert(0, os.path.join(CHROME_SRC, 'tools'))
 
-import find_depot_tools
 
 DEPOT_PATH = find_depot_tools.add_depot_tools_to_path()
 GSUTIL_PATH = os.path.join(DEPOT_PATH, 'gsutil.py')
@@ -39,28 +28,7 @@
 
 CLANG_BUCKET = 'gs://chromium-browser-clang/Linux_x64'
 
-GOLD_PLUGIN_PATH = os.path.join(LLVM_BUILD_PATH, 'lib', 'LLVMgold.so')
-
-sys.path.insert(0, os.path.join(CHROME_SRC, 'tools', 'clang', 'scripts'))
-
-import update
-
 def main():
-  if not re.search(r'cfi_vptr=1', os.environ.get('GYP_DEFINES', '')):
-    # Bailout if this is not a cfi build.
-    print 'Skipping gold plugin download for non-cfi build.'
-    return 0
-  if (os.path.exists(GOLD_PLUGIN_PATH) and
-      update.ReadStampFile().strip() == update.PACKAGE_VERSION):
-    # Bailout if clang is up-to-date. This requires the script to be run before
-    # the clang update step! I.e. afterwards clang would always be up-to-date.
-    print 'Skipping gold plugin download. File present and clang up to date.'
-    return 0
-
-  # Make sure this works on empty checkouts (i.e. clang not downloaded yet).
-  if not os.path.exists(LLVM_BUILD_PATH):
-    os.makedirs(LLVM_BUILD_PATH)
-
   targz_name = 'llvmgold-%s.tgz' % CLANG_REVISION
   remote_path = '%s/%s' % (CLANG_BUCKET, targz_name)
 
diff --git a/build/get_landmines.py b/build/get_landmines.py
index 2bbf7a6..395c18f 100755
--- a/build/get_landmines.py
+++ b/build/get_landmines.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-# Copyright 2014 the V8 project authors. All rights reserved.
+# Copyright 2013 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
@@ -10,23 +10,77 @@
 
 import sys
 
+import landmine_utils
 
-def main():
+
+builder = landmine_utils.builder
+distributor = landmine_utils.distributor
+gyp_defines = landmine_utils.gyp_defines
+gyp_msvs_version = landmine_utils.gyp_msvs_version
+platform = landmine_utils.platform
+
+
+def print_landmines():
   """
   ALL LANDMINES ARE EMITTED FROM HERE.
   """
-  print 'Need to clobber after ICU52 roll.'
-  print 'Landmines test.'
-  print 'Activating MSVS 2013.'
-  print 'Revert activation of MSVS 2013.'
-  print 'Activating MSVS 2013 again.'
-  print 'Clobber after ICU roll.'
-  print 'Moar clobbering...'
-  print 'Remove build/android.gypi'
-  print 'Cleanup after windows ninja switch attempt.'
-  print 'Switching to pinned msvs toolchain.'
-  print 'Clobbering to hopefully resolve problem with mksnapshot'
-  print 'Clobber after ICU roll.'
+  # DO NOT add landmines as part of a regular CL. Landmines are a last-effort
+  # bandaid fix if a CL that got landed has a build dependency bug and all bots
+  # need to be cleaned up. If you're writing a new CL that causes build
+  # dependency problems, fix the dependency problems instead of adding a
+  # landmine.
+
+  if (distributor() == 'goma' and platform() == 'win32' and
+      builder() == 'ninja'):
+    print 'Need to clobber winja goma due to backend cwd cache fix.'
+  if platform() == 'android':
+    print 'Clobber: to handle new way of suppressing findbugs failures.'
+    print 'Clobber to fix gyp not rename package name (crbug.com/457038)'
+  if platform() == 'win' and builder() == 'ninja':
+    print 'Compile on cc_unittests fails due to symbols removed in r185063.'
+  if platform() == 'linux' and builder() == 'ninja':
+    print 'Builders switching from make to ninja will clobber on this.'
+  if platform() == 'mac':
+    print 'Switching from bundle to unbundled dylib (issue 14743002).'
+  if platform() in ('win', 'mac'):
+    print ('Improper dependency for create_nmf.py broke in r240802, '
+           'fixed in r240860.')
+  if (platform() == 'win' and builder() == 'ninja' and
+      gyp_msvs_version() == '2012' and
+      gyp_defines().get('target_arch') == 'x64' and
+      gyp_defines().get('dcheck_always_on') == '1'):
+    print "Switched win x64 trybots from VS2010 to VS2012."
+  if (platform() == 'win' and builder() == 'ninja' and
+      gyp_msvs_version().startswith('2013')):
+    print "Switch to VS2013"
+  if (platform() == 'win' and gyp_msvs_version().startswith('2015')):
+    print 'Switch to VS2015 Update 2'
+  print 'Need to clobber everything due to an IDL change in r154579 (blink)'
+  print 'Need to clobber everything due to gen file moves in r175513 (Blink)'
+  if (platform() != 'ios'):
+    print 'Clobber to get rid of obselete test plugin after r248358'
+    print 'Clobber to rebuild GN files for V8'
+  print 'Clobber to get rid of stale generated mojom.h files'
+  print 'Need to clobber everything due to build_nexe change in nacl r13424'
+  print '[chromium-dev] PSA: clobber build needed for IDR_INSPECTOR_* compil...'
+  print 'blink_resources.grd changed: crbug.com/400860'
+  print 'ninja dependency cycle: crbug.com/408192'
+  print 'Clobber to fix missing NaCl gyp dependencies (crbug.com/427427).'
+  print 'Another clobber for missing NaCl gyp deps (crbug.com/427427).'
+  print 'Clobber to fix GN not picking up increased ID range (crbug.com/444902)'
+  print 'Remove NaCl toolchains from the output dir (crbug.com/456902)'
+  if platform() == 'ios':
+    print 'Clobber iOS to workaround Xcode deps bug (crbug.com/485435)'
+  if platform() == 'win':
+    print 'Clobber to delete stale generated files (crbug.com/510086)'
+  if platform() == 'android' and gyp_defines().get('target_arch') == 'arm64':
+    print 'Clobber to support new location/infra for chrome_sync_shell_apk'
+  if platform() == 'mac':
+    print 'Clobber to get rid of evil libsqlite3.dylib (crbug.com/526208)'
+
+
+def main():
+  print_landmines()
   return 0
 
 
diff --git a/build/gyp_environment.py b/build/gyp_environment.py
index 7a4e622..199023a 100644
--- a/build/gyp_environment.py
+++ b/build/gyp_environment.py
@@ -1,54 +1,35 @@
-# Copyright 2015 the V8 project authors. All rights reserved.
+# Copyright 2014 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
 """
 Sets up various automatic gyp environment variables. These are used by
-gyp_v8 and landmines.py which run at different stages of runhooks. To
+gyp_chromium and landmines.py which run at different stages of runhooks. To
 make sure settings are consistent between them, all setup should happen here.
 """
 
+import gyp_helper
+import mac_toolchain
 import os
 import sys
 import vs_toolchain
 
-SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
-V8_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir))
-
-
-def apply_gyp_environment(file_path=None):
-  """
-  Reads in a *.gyp_env file and applies the valid keys to os.environ.
-  """
-  if not file_path or not os.path.exists(file_path):
-    return
-  file_contents = open(file_path).read()
-  try:
-    file_data = eval(file_contents, {'__builtins__': None}, None)
-  except SyntaxError, e:
-    e.filename = os.path.abspath(file_path)
-    raise
-  supported_vars = ( 'V8_GYP_FILE',
-                     'V8_GYP_SYNTAX_CHECK',
-                     'GYP_DEFINES',
-                     'GYP_GENERATOR_FLAGS',
-                     'GYP_GENERATOR_OUTPUT', )
-  for var in supported_vars:
-    val = file_data.get(var)
-    if val:
-      if var in os.environ:
-        print 'INFO: Environment value for "%s" overrides value in %s.' % (
-            var, os.path.abspath(file_path)
-        )
-      else:
-        os.environ[var] = val
-
-
-def set_environment():
+def SetEnvironment():
   """Sets defaults for GYP_* variables."""
+  gyp_helper.apply_chromium_gyp_env()
 
-  if 'SKIP_V8_GYP_ENV' not in os.environ:
-    # Update the environment based on v8.gyp_env
-    gyp_env_path = os.path.join(os.path.dirname(V8_ROOT), 'v8.gyp_env')
-    apply_gyp_environment(gyp_env_path)
-    vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs()
+  # Default to ninja on linux and windows, but only if no generator has
+  # explicitly been set.
+  # Also default to ninja on mac, but only when not building chrome/ios.
+  # . -f / --format has precedence over the env var, no need to check for it
+  # . set the env var only if it hasn't been set yet
+  # . chromium.gyp_env has been applied to os.environ at this point already
+  if sys.platform.startswith(('linux', 'win', 'freebsd')) and \
+      not os.environ.get('GYP_GENERATORS'):
+    os.environ['GYP_GENERATORS'] = 'ninja'
+  elif sys.platform == 'darwin' and not os.environ.get('GYP_GENERATORS') and \
+      not 'OS=ios' in os.environ.get('GYP_DEFINES', []):
+    os.environ['GYP_GENERATORS'] = 'ninja'
+
+  vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs()
+  mac_toolchain.SetToolchainEnvironment()
diff --git a/build/gyp_v8 b/build/gyp_v8
deleted file mode 100755
index 8813f2c..0000000
--- a/build/gyp_v8
+++ /dev/null
@@ -1,181 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2012 the V8 project authors. All rights reserved.
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-#       copyright notice, this list of conditions and the following
-#       disclaimer in the documentation and/or other materials provided
-#       with the distribution.
-#     * Neither the name of Google Inc. nor the names of its
-#       contributors may be used to endorse or promote products derived
-#       from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# This script is wrapper for V8 that adds some support for how GYP
-# is invoked by V8 beyond what can be done in the gclient hooks.
-
-import argparse
-import glob
-import gyp_environment
-import os
-import platform
-import shlex
-import subprocess
-import sys
-import vs_toolchain
-
-script_dir = os.path.dirname(os.path.realpath(__file__))
-v8_root = os.path.abspath(os.path.join(script_dir, os.pardir))
-
-sys.path.insert(0, os.path.join(v8_root, 'build', 'gyp', 'pylib'))
-import gyp
-
-# Add paths so that pymod_do_main(...) can import files.
-sys.path.insert(
-    1, os.path.abspath(os.path.join(v8_root, 'tools', 'generate_shim_headers')))
-
-
-def GetOutputDirectory():
-  """Returns the output directory that GYP will use."""
-
-  # Handle command line generator flags.
-  parser = argparse.ArgumentParser()
-  parser.add_argument('-G', dest='genflags', default=[], action='append')
-  genflags = parser.parse_known_args()[0].genflags
-
-  # Handle generator flags from the environment.
-  genflags += shlex.split(os.environ.get('GYP_GENERATOR_FLAGS', ''))
-
-  needle = 'output_dir='
-  for item in genflags:
-    if item.startswith(needle):
-      return item[len(needle):]
-
-  return 'out'
-
-
-def additional_include_files(args=[]):
-  """
-  Returns a list of additional (.gypi) files to include, without
-  duplicating ones that are already specified on the command line.
-  """
-  # Determine the include files specified on the command line.
-  # This doesn't cover all the different option formats you can use,
-  # but it's mainly intended to avoid duplicating flags on the automatic
-  # makefile regeneration which only uses this format.
-  specified_includes = set()
-  for arg in args:
-    if arg.startswith('-I') and len(arg) > 2:
-      specified_includes.add(os.path.realpath(arg[2:]))
-
-  result = []
-  def AddInclude(path):
-    if os.path.realpath(path) not in specified_includes:
-      result.append(path)
-
-  # Always include standalone.gypi
-  AddInclude(os.path.join(v8_root, 'build', 'standalone.gypi'))
-
-  # Optionally add supplemental .gypi files if present.
-  supplements = glob.glob(os.path.join(v8_root, '*', 'supplement.gypi'))
-  for supplement in supplements:
-    AddInclude(supplement)
-
-  return result
-
-
-def run_gyp(args):
-  rc = gyp.main(args)
-
-  vs2013_runtime_dll_dirs = vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs()
-  if vs2013_runtime_dll_dirs:
-    x64_runtime, x86_runtime = vs2013_runtime_dll_dirs
-    vs_toolchain.CopyVsRuntimeDlls(
-      os.path.join(v8_root, GetOutputDirectory()),
-      (x86_runtime, x64_runtime))
-
-  if rc != 0:
-    print 'Error running GYP'
-    sys.exit(rc)
-
-
-if __name__ == '__main__':
-  args = sys.argv[1:]
-
-  gyp_environment.set_environment()
-
-  # This could give false positives since it doesn't actually do real option
-  # parsing.  Oh well.
-  gyp_file_specified = False
-  for arg in args:
-    if arg.endswith('.gyp'):
-      gyp_file_specified = True
-      break
-
-  # If we didn't get a file, check an env var, and then fall back to
-  # assuming 'all.gyp' from the same directory as the script.
-  if not gyp_file_specified:
-    gyp_file = os.environ.get('V8_GYP_FILE')
-    if gyp_file:
-      # Note that V8_GYP_FILE values can't have backslashes as
-      # path separators even on Windows due to the use of shlex.split().
-      args.extend(shlex.split(gyp_file))
-    else:
-      args.append(os.path.join(script_dir, 'all.gyp'))
-
-  args.extend(['-I' + i for i in additional_include_files(args)])
-
-  # There shouldn't be a circular dependency relationship between .gyp files
-  args.append('--no-circular-check')
-
-  # Set the GYP DEPTH variable to the root of the V8 project.
-  args.append('--depth=' + os.path.relpath(v8_root))
-
-  # If V8_GYP_SYNTAX_CHECK is set to 1, it will invoke gyp with --check
-  # to enfore syntax checking.
-  syntax_check = os.environ.get('V8_GYP_SYNTAX_CHECK')
-  if syntax_check and int(syntax_check):
-    args.append('--check')
-
-  print 'Updating projects from gyp files...'
-  sys.stdout.flush()
-
-  # Generate for the architectures supported on the given platform.
-  gyp_args = list(args)
-  gyp_args.extend(['-D', 'gyp_output_dir=' + GetOutputDirectory()])
-  gyp_generators = os.environ.get('GYP_GENERATORS', '')
-  if platform.system() == 'Linux' and gyp_generators != 'ninja':
-    # Work around for crbug.com/331475.
-    for f in glob.glob(os.path.join(v8_root, 'out', 'Makefile.*')):
-      os.unlink(f)
-    # --generator-output defines where the Makefile goes.
-    gyp_args.append('--generator-output=out')
-    # -Goutput_dir defines where the build output goes, relative to the
-    # Makefile. Set it to . so that the build output doesn't end up in out/out.
-    gyp_args.append('-Goutput_dir=.')
-
-  gyp_defines = os.environ.get('GYP_DEFINES', '')
-
-  # Automatically turn on crosscompile support for platforms that need it.
-  if all(('ninja' in gyp_generators,
-          'OS=android' in gyp_defines,
-          'GYP_CROSSCOMPILE' not in os.environ)):
-    os.environ['GYP_CROSSCOMPILE'] = '1'
-
-  run_gyp(gyp_args)
diff --git a/build/has_valgrind.py b/build/has_valgrind.py
deleted file mode 100755
index 83a848d..0000000
--- a/build/has_valgrind.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2016 the V8 project authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import os
-
-BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-VALGRIND_DIR = os.path.join(BASE_DIR, 'third_party', 'valgrind')
-LINUX32_DIR = os.path.join(VALGRIND_DIR, 'linux_x86')
-LINUX64_DIR = os.path.join(VALGRIND_DIR, 'linux_x64')
-
-
-def DoMain(_):
-  """Hook to be called from gyp without starting a separate python
-  interpreter."""
-  return int(os.path.exists(LINUX32_DIR) and os.path.exists(LINUX64_DIR))
-
-
-if __name__ == '__main__':
-  print DoMain([])
diff --git a/build/isolate.gypi b/build/isolate.gypi
index 4cfbbfd..197e455 100644
--- a/build/isolate.gypi
+++ b/build/isolate.gypi
@@ -1,4 +1,3 @@
-# Copyright 2015 the V8 project authors. All rights reserved.
 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
@@ -48,9 +47,7 @@
         '<(DEPTH)/tools/swarming_client/isolate.py',
         '<(DEPTH)/tools/swarming_client/run_isolated.py',
       ],
-      'outputs': [
-        '<(PRODUCT_DIR)/<(RULE_INPUT_ROOT).isolated',
-      ],
+      'outputs': [],
       'action': [
         'python',
         '<(DEPTH)/tools/isolate_driver.py',
@@ -59,36 +56,67 @@
         '--isolate', '<(RULE_INPUT_PATH)',
 
         # Variables should use the -V FOO=<(FOO) form so frequent values,
-        # like '0' or '1', aren't stripped out by GYP. Run 'isolate.py help'
-        # for more details.
+        # like '0' or '1', aren't stripped out by GYP. Run 'isolate.py help' for
+        # more details.
 
         # Path variables are used to replace file paths when loading a .isolate
         # file
         '--path-variable', 'DEPTH', '<(DEPTH)',
-        '--path-variable', 'PRODUCT_DIR', '<(PRODUCT_DIR)',
+        '--path-variable', 'PRODUCT_DIR', '<(PRODUCT_DIR) ',
 
+        # Note: This list must match DefaultConfigVariables()
+        # in build/android/pylib/utils/isolator.py
         '--config-variable', 'CONFIGURATION_NAME=<(CONFIGURATION_NAME)',
         '--config-variable', 'OS=<(OS)',
         '--config-variable', 'asan=<(asan)',
-        '--config-variable', 'cfi_vptr=<(cfi_vptr)',
-        '--config-variable', 'gcmole=<(gcmole)',
-        '--config-variable', 'has_valgrind=<(has_valgrind)',
-        '--config-variable', 'icu_use_data_file_flag=0',
-        '--config-variable', 'msan=<(msan)',
-        '--config-variable', 'tsan=<(tsan)',
-        '--config-variable', 'coverage=<(coverage)',
-        '--config-variable', 'sanitizer_coverage=<(sanitizer_coverage)',
+        '--config-variable', 'branding=<(branding)',
+        '--config-variable', 'chromeos=<(chromeos)',
         '--config-variable', 'component=<(component)',
+        '--config-variable', 'disable_nacl=<(disable_nacl)',
+        '--config-variable', 'enable_pepper_cdms=<(enable_pepper_cdms)',
+        '--config-variable', 'enable_plugins=<(enable_plugins)',
+        '--config-variable', 'fastbuild=<(fastbuild)',
+        '--config-variable', 'icu_use_data_file_flag=<(icu_use_data_file_flag)',
+        # TODO(kbr): move this to chrome_tests.gypi:gles2_conform_tests_run
+        # once support for user-defined config variables is added.
+        '--config-variable',
+          'internal_gles2_conform_tests=<(internal_gles2_conform_tests)',
+        '--config-variable', 'kasko=<(kasko)',
+        '--config-variable', 'lsan=<(lsan)',
+        '--config-variable', 'msan=<(msan)',
         '--config-variable', 'target_arch=<(target_arch)',
+        '--config-variable', 'tsan=<(tsan)',
         '--config-variable', 'use_custom_libcxx=<(use_custom_libcxx)',
-        '--config-variable', 'v8_separate_ignition_snapshot=<(v8_separate_ignition_snapshot)',
+        '--config-variable', 'use_instrumented_libraries=<(use_instrumented_libraries)',
+        '--config-variable',
+        'use_prebuilt_instrumented_libraries=<(use_prebuilt_instrumented_libraries)',
+        '--config-variable', 'use_ozone=<(use_ozone)',
+        '--config-variable', 'use_x11=<(use_x11)',
         '--config-variable', 'v8_use_external_startup_data=<(v8_use_external_startup_data)',
-        '--config-variable', 'v8_use_snapshot=<(v8_use_snapshot)',
       ],
       'conditions': [
-        ['OS=="win"', {
+        # Note: When gyp merges lists, it appends them to the old value.
+        # Extra variables are replaced on the 'command' entry and on paths in
+        # the .isolate file but are not considered relative paths.
+        ['OS=="mac"', {
           'action': [
-            '--config-variable', 'msvs_version=2013',
+            '--extra-variable', 'mac_product_name=<(mac_product_name)',
+          ],
+        }],
+        ["test_isolation_mode == 'prepare'", {
+          'outputs': [
+            '<(PRODUCT_DIR)/<(RULE_INPUT_ROOT).isolated.gen.json',
+          ],
+        }, {
+          'outputs': [
+            '<(PRODUCT_DIR)/<(RULE_INPUT_ROOT).isolated',
+          ],
+        }],
+        ['OS=="win"', {
+          'includes': ['../build/util/version.gypi'],
+          'action': [
+            '--extra-variable', 'version_full=<(version_full)',
+            '--config-variable', 'msvs_version=<(MSVS_VERSION)',
           ],
         }, {
           'action': [
diff --git a/build/landmine_utils.py b/build/landmine_utils.py
index cb34991..6d18b6d 100644
--- a/build/landmine_utils.py
+++ b/build/landmine_utils.py
@@ -1,4 +1,4 @@
-# Copyright 2014 the V8 project authors. All rights reserved.
+# Copyright 2013 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
@@ -33,7 +33,7 @@
 
 @memoize()
 def IsLinux():
-  return sys.platform.startswith(('linux', 'freebsd'))
+  return sys.platform.startswith(('linux', 'freebsd', 'openbsd'))
 
 
 @memoize()
@@ -47,19 +47,16 @@
   return dict(arg.split('=', 1)
       for arg in shlex.split(os.environ.get('GYP_DEFINES', '')))
 
-
 @memoize()
 def gyp_generator_flags():
   """Parses and returns GYP_GENERATOR_FLAGS env var as a dictionary."""
   return dict(arg.split('=', 1)
       for arg in shlex.split(os.environ.get('GYP_GENERATOR_FLAGS', '')))
 
-
 @memoize()
 def gyp_msvs_version():
   return os.environ.get('GYP_MSVS_VERSION', '')
 
-
 @memoize()
 def distributor():
   """
@@ -110,14 +107,14 @@
   else:
     if platform() == 'android':
       # Good enough for now? Do any android bots use make?
-      return 'make'
+      return 'ninja'
     elif platform() == 'ios':
       return 'xcode'
     elif IsWindows():
-      return 'msvs'
+      return 'ninja'
     elif IsLinux():
-      return 'make'
+      return 'ninja'
     elif IsMac():
-      return 'xcode'
+      return 'ninja'
     else:
       assert False, 'Don\'t know what builder we\'re using!'
diff --git a/build/landmines.py b/build/landmines.py
index 97c6390..031c309 100755
--- a/build/landmines.py
+++ b/build/landmines.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-# Copyright 2014 the V8 project authors. All rights reserved.
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
@@ -19,19 +19,15 @@
 import logging
 import optparse
 import os
-import re
-import shutil
 import sys
 import subprocess
 import time
 
+import clobber
 import landmine_utils
 
 
-SRC_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
-
-
-def get_build_dir(build_tool, is_iphone=False):
+def get_build_dir(build_tool, src_dir, is_iphone=False):
   """
   Returns output directory absolute path dependent on build and targets.
   Examples:
@@ -43,7 +39,7 @@
   """
   ret = None
   if build_tool == 'xcode':
-    ret = os.path.join(SRC_DIR, 'xcodebuild')
+    ret = os.path.join(src_dir, 'xcodebuild')
   elif build_tool in ['make', 'ninja', 'ninja-ios']:  # TODO: Remove ninja-ios.
     if 'CHROMIUM_OUT_DIR' in os.environ:
       output_dir = os.environ.get('CHROMIUM_OUT_DIR').strip()
@@ -51,88 +47,22 @@
         raise Error('CHROMIUM_OUT_DIR environment variable is set but blank!')
     else:
       output_dir = landmine_utils.gyp_generator_flags().get('output_dir', 'out')
-    ret = os.path.join(SRC_DIR, output_dir)
-  elif build_tool in ['msvs', 'vs', 'ib']:
-    ret = os.path.join(SRC_DIR, 'build')
+    ret = os.path.join(src_dir, output_dir)
   else:
     raise NotImplementedError('Unexpected GYP_GENERATORS (%s)' % build_tool)
   return os.path.abspath(ret)
 
 
-def extract_gn_build_commands(build_ninja_file):
-  """Extracts from a build.ninja the commands to run GN.
-
-  The commands to run GN are the gn rule and build.ninja build step at the
-  top of the build.ninja file. We want to keep these when deleting GN builds
-  since we want to preserve the command-line flags to GN.
-
-  On error, returns the empty string."""
-  result = ""
-  with open(build_ninja_file, 'r') as f:
-    # Read until the second blank line. The first thing GN writes to the file
-    # is the "rule gn" and the second is the section for "build build.ninja",
-    # separated by blank lines.
-    num_blank_lines = 0
-    while num_blank_lines < 2:
-      line = f.readline()
-      if len(line) == 0:
-        return ''  # Unexpected EOF.
-      result += line
-      if line[0] == '\n':
-        num_blank_lines = num_blank_lines + 1
-  return result
-
-def delete_build_dir(build_dir):
-  # GN writes a build.ninja.d file. Note that not all GN builds have args.gn.
-  build_ninja_d_file = os.path.join(build_dir, 'build.ninja.d')
-  if not os.path.exists(build_ninja_d_file):
-    shutil.rmtree(build_dir)
-    return
-
-  # GN builds aren't automatically regenerated when you sync. To avoid
-  # messing with the GN workflow, erase everything but the args file, and
-  # write a dummy build.ninja file that will automatically rerun GN the next
-  # time Ninja is run.
-  build_ninja_file = os.path.join(build_dir, 'build.ninja')
-  build_commands = extract_gn_build_commands(build_ninja_file)
-
+def clobber_if_necessary(new_landmines, src_dir):
+  """Does the work of setting, planting, and triggering landmines."""
+  out_dir = get_build_dir(landmine_utils.builder(), src_dir)
+  landmines_path = os.path.normpath(os.path.join(src_dir, '.landmines'))
   try:
-    gn_args_file = os.path.join(build_dir, 'args.gn')
-    with open(gn_args_file, 'r') as f:
-      args_contents = f.read()
-  except IOError:
-    args_contents = ''
+    os.makedirs(out_dir)
+  except OSError as e:
+    if e.errno == errno.EEXIST:
+      pass
 
-  shutil.rmtree(build_dir)
-
-  # Put back the args file (if any).
-  os.mkdir(build_dir)
-  if args_contents != '':
-    with open(gn_args_file, 'w') as f:
-      f.write(args_contents)
-
-  # Write the build.ninja file sufficiently to regenerate itself.
-  with open(os.path.join(build_dir, 'build.ninja'), 'w') as f:
-    if build_commands != '':
-      f.write(build_commands)
-    else:
-      # Couldn't parse the build.ninja file, write a default thing.
-      f.write('''rule gn
-command = gn -q gen //out/%s/
-description = Regenerating ninja files
-
-build build.ninja: gn
-generator = 1
-depfile = build.ninja.d
-''' % (os.path.split(build_dir)[1]))
-
-  # Write a .d file for the build which references a nonexistant file. This
-  # will make Ninja always mark the build as dirty.
-  with open(build_ninja_d_file, 'w') as f:
-    f.write('build.ninja: nonexistant_file.gn\n')
-
-
-def needs_clobber(landmines_path, new_landmines):
   if os.path.exists(landmines_path):
     with open(landmines_path, 'r') as f:
       old_landmines = f.readlines()
@@ -143,50 +73,9 @@
           fromfiledate=old_date, tofiledate=time.ctime(), n=0)
       sys.stdout.write('Clobbering due to:\n')
       sys.stdout.writelines(diff)
-      return True
-  else:
-    sys.stdout.write('Clobbering due to missing landmines file.\n')
-    return True
-  return False
+      sys.stdout.flush()
 
-
-def clobber_if_necessary(new_landmines):
-  """Does the work of setting, planting, and triggering landmines."""
-  out_dir = get_build_dir(landmine_utils.builder())
-  landmines_path = os.path.normpath(os.path.join(out_dir, '..', '.landmines'))
-  try:
-    os.makedirs(out_dir)
-  except OSError as e:
-    if e.errno == errno.EEXIST:
-      pass
-
-  if needs_clobber(landmines_path, new_landmines):
-    # Clobber contents of build directory but not directory itself: some
-    # checkouts have the build directory mounted.
-    for f in os.listdir(out_dir):
-      path = os.path.join(out_dir, f)
-      if os.path.basename(out_dir) == 'build':
-        # Only delete build directories and files for MSVS builds as the folder
-        # shares some checked out files and directories.
-        if (os.path.isdir(path) and
-            re.search(r'(?:[Rr]elease)|(?:[Dd]ebug)', f)):
-          delete_build_dir(path)
-        elif (os.path.isfile(path) and
-              (path.endswith('.sln') or
-               path.endswith('.vcxproj') or
-               path.endswith('.vcxproj.user'))):
-          os.unlink(path)
-      else:
-        if os.path.isfile(path):
-          os.unlink(path)
-        elif os.path.isdir(path):
-          delete_build_dir(path)
-    if os.path.basename(out_dir) == 'xcodebuild':
-      # Xcodebuild puts an additional project file structure into build,
-      # while the output folder is xcodebuild.
-      project_dir = os.path.join(SRC_DIR, 'build', 'all.xcodeproj')
-      if os.path.exists(project_dir) and os.path.isdir(project_dir):
-        delete_build_dir(project_dir)
+      clobber.clobber(out_dir)
 
   # Save current set of landmines for next time.
   with open(landmines_path, 'w') as f:
@@ -194,14 +83,16 @@
 
 
 def process_options():
-  """Returns a list of landmine emitting scripts."""
+  """Returns an options object containing the configuration for this script."""
   parser = optparse.OptionParser()
   parser.add_option(
       '-s', '--landmine-scripts', action='append',
-      default=[os.path.join(SRC_DIR, 'build', 'get_landmines.py')],
       help='Path to the script which emits landmines to stdout. The target '
            'is passed to this script via option -t. Note that an extra '
            'script can be specified via an env var EXTRA_LANDMINES_SCRIPT.')
+  parser.add_option('-d', '--src-dir',
+      help='Path of the source root dir. Overrides the default location of the '
+           'source root dir when calculating the build directory.')
   parser.add_option('-v', '--verbose', action='store_true',
       default=('LANDMINES_VERBOSE' in os.environ),
       help=('Emit some extra debugging information (default off). This option '
@@ -216,27 +107,39 @@
   logging.basicConfig(
       level=logging.DEBUG if options.verbose else logging.ERROR)
 
+  if options.src_dir:
+    if not os.path.isdir(options.src_dir):
+      parser.error('Cannot find source root dir at %s' % options.src_dir)
+    logging.debug('Overriding source root dir. Using: %s', options.src_dir)
+  else:
+    options.src_dir = \
+        os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
+
+  if not options.landmine_scripts:
+    options.landmine_scripts = [os.path.join(options.src_dir, 'build',
+                                             'get_landmines.py')]
+
   extra_script = os.environ.get('EXTRA_LANDMINES_SCRIPT')
   if extra_script:
-    return options.landmine_scripts + [extra_script]
-  else:
-    return options.landmine_scripts
+    options.landmine_scripts += [extra_script]
+
+  return options
 
 
 def main():
-  landmine_scripts = process_options()
+  options = process_options()
 
   if landmine_utils.builder() in ('dump_dependency_json', 'eclipse'):
     return 0
 
-  gyp_environment.set_environment()
+  gyp_environment.SetEnvironment()
 
   landmines = []
-  for s in landmine_scripts:
+  for s in options.landmine_scripts:
     proc = subprocess.Popen([sys.executable, s], stdout=subprocess.PIPE)
     output, _ = proc.communicate()
     landmines.extend([('%s\n' % l.strip()) for l in output.splitlines()])
-  clobber_if_necessary(landmines)
+  clobber_if_necessary(landmines, options.src_dir)
 
   return 0
 
diff --git a/build/mac/asan.gyp b/build/mac/asan.gyp
index 3fc7f58..a66d118 100644
--- a/build/mac/asan.gyp
+++ b/build/mac/asan.gyp
@@ -1,4 +1,4 @@
-# Copyright 2015 the V8 project authors. All rights reserved.
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
@@ -6,7 +6,6 @@
    'targets': [
      {
        'target_name': 'asan_dynamic_runtime',
-       'toolsets': ['target', 'host'],
        'type': 'none',
        'variables': {
          # Every target is going to depend on asan_dynamic_runtime, so allow
@@ -14,17 +13,40 @@
          'prune_self_dependency': 1,
          # Path is relative to this GYP file.
          'asan_rtl_mask_path':
-             '../../third_party/llvm-build/Release+Asserts/lib/clang/*/lib/darwin',
+             '../../third_party/llvm-build/Release+Asserts/lib/clang/<!(python ../../tools/clang/scripts/update.py --print-clang-version)/lib/darwin',
          'asan_osx_dynamic':
              '<(asan_rtl_mask_path)/libclang_rt.asan_osx_dynamic.dylib',
+         'asan_iossim_dynamic':
+             '<(asan_rtl_mask_path)/libclang_rt.asan_iossim_dynamic.dylib',
        },
-       'copies': [
-         {
-           'destination': '<(PRODUCT_DIR)',
-           'files': [
-             '<!(/bin/ls <(asan_osx_dynamic))',
+       'conditions': [
+         ['OS=="mac"', {
+           'copies': [
+             {
+               'destination': '<(PRODUCT_DIR)',
+               'files': [
+                 '<!(/bin/ls <(asan_osx_dynamic))',
+               ],
+             },
            ],
-         },
+         }],
+         # ASan works with iOS simulator only, not bare-metal iOS.
+         ['OS=="ios" and target_arch=="ia32"', {
+           'toolsets': ['host', 'target'],
+           'copies': [
+             {
+               'destination': '<(PRODUCT_DIR)',
+               'target_conditions': [
+                 ['_toolset=="host"', {
+                   'files': [ '<!(/bin/ls <(asan_osx_dynamic))'],
+                 }],
+                 ['_toolset=="target"', {
+                   'files': [ '<!(/bin/ls <(asan_iossim_dynamic))'],
+                 }],
+               ],
+             },
+           ],
+         }],
        ],
      },
    ],
diff --git a/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn b/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn
index d29076f..9d519b7 100644
--- a/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn
+++ b/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn
@@ -9,7 +9,7 @@
 # Allows the source set to inject ldflags for targets that link to it.
 config("util_link_config") {
   if (is_mac) {
-    ldflags = [ "/usr/lib/libbsm.dylib" ]
+    libs = [ "bsm" ]
   }
 }
 
diff --git a/build/shim_headers.gypi b/build/shim_headers.gypi
index 940211c..56d8d3a 100644
--- a/build/shim_headers.gypi
+++ b/build/shim_headers.gypi
@@ -1,29 +1,6 @@
-# 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.
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
 
 # This file is meant to be included into a target to handle shim headers
 # in a consistent manner. To use this the following variables need to be
@@ -40,9 +17,19 @@
     '<(shim_headers_path)',
   ],
   'all_dependent_settings': {
+    # Repeating this with different numbers of plusses is unfortunately required
+    # to make sure that even if this include is inside nested conditions/etc, it
+    # still gets inserted at the beginning of the include_dirs list. See
+    # http://crbug.com/263818 for details.
     'include_dirs+++': [
       '<(shim_headers_path)',
     ],
+    'include_dirs++++': [
+      '<(shim_headers_path)',
+    ],
+    'include_dirs+++++': [
+      '<(shim_headers_path)',
+    ],
   },
   'actions': [
     {
@@ -67,7 +54,7 @@
                  '<@(generator_args)',
                  '--generate',
       ],
-      'message': 'Generating <(_target_name) shim headers.',
+      'message': 'Generating <(_target_name) shim headers',
     },
   ],
 }
diff --git a/build/standalone.gypi b/build/standalone.gypi
deleted file mode 100644
index 6c88409..0000000
--- a/build/standalone.gypi
+++ /dev/null
@@ -1,1395 +0,0 @@
-# Copyright 2012 the V8 project authors. All rights reserved.
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * 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.
-
-# Definitions to be used when building stand-alone V8 binaries.
-
-{
-  # We need to include toolchain.gypi here for third-party sources that don't
-  # directly include it themselves.
-  'includes': ['toolchain.gypi'],
-  'variables': {
-    'component%': 'static_library',
-    'clang_xcode%': 0,
-    # Track where uninitialized memory originates from. From fastest to
-    # slowest: 0 - no tracking, 1 - track only the initial allocation site, 2
-    # - track the chain of stores leading from allocation site to use site.
-    'msan_track_origins%': 2,
-    'visibility%': 'hidden',
-    'v8_enable_backtrace%': 0,
-    'v8_enable_i18n_support%': 1,
-    'v8_deprecation_warnings': 1,
-    'v8_imminent_deprecation_warnings': 1,
-    'msvs_multi_core_compile%': '1',
-    'mac_deployment_target%': '10.7',
-    'release_extra_cflags%': '',
-    'variables': {
-      'variables': {
-        'variables': {
-          'conditions': [
-            ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or \
-               OS=="netbsd" or OS=="mac" or OS=="qnx" or OS=="aix"', {
-              # This handles the Unix platforms we generally deal with.
-              # Anything else gets passed through, which probably won't work
-              # very well; such hosts should pass an explicit target_arch
-              # to gyp.
-              'host_arch%': '<!pymod_do_main(detect_v8_host_arch)',
-            }, {
-              # OS!="linux" and OS!="freebsd" and OS!="openbsd" and
-              # OS!="netbsd" and OS!="mac" and OS!="aix"
-              'host_arch%': 'ia32',
-            }],
-          ],
-        },
-        'host_arch%': '<(host_arch)',
-        'target_arch%': '<(host_arch)',
-        'base_dir%': '<!(cd <(DEPTH) && python -c "import os; print os.getcwd()")',
-
-        # Instrument for code coverage and use coverage wrapper to exclude some
-        # files. Uses gcov if clang=0 is set explicitly. Otherwise,
-        # sanitizer_coverage must be set too.
-        'coverage%': 0,
-      },
-      'base_dir%': '<(base_dir)',
-      'host_arch%': '<(host_arch)',
-      'target_arch%': '<(target_arch)',
-      'v8_target_arch%': '<(target_arch)',
-      'coverage%': '<(coverage)',
-      'asan%': 0,
-      'lsan%': 0,
-      'msan%': 0,
-      'tsan%': 0,
-      # Enable coverage gathering instrumentation in sanitizer tools. This flag
-      # also controls coverage granularity (1 for function-level, 2 for
-      # block-level, 3 for edge-level).
-      'sanitizer_coverage%': 0,
-      # Use libc++ (buildtools/third_party/libc++ and
-      # buildtools/third_party/libc++abi) instead of stdlibc++ as standard
-      # library. This is intended to be used for instrumented builds.
-      'use_custom_libcxx%': 0,
-
-      'clang_dir%': '<(base_dir)/third_party/llvm-build/Release+Asserts',
-
-      'use_lto%': 0,
-
-      # Control Flow Integrity for virtual calls and casts.
-      # See http://clang.llvm.org/docs/ControlFlowIntegrity.html
-      'cfi_vptr%': 0,
-      'cfi_diag%': 0,
-
-      'cfi_blacklist%': '<(base_dir)/tools/cfi/blacklist.txt',
-
-      # Set to 1 to enable fast builds.
-      # TODO(machenbach): Only configured for windows.
-      'fastbuild%': 0,
-
-      # goma settings.
-      # 1 to use goma.
-      # If no gomadir is set, it uses the default gomadir.
-      'use_goma%': 0,
-      'gomadir%': '',
-
-      # Check if valgrind directories are present.
-      'has_valgrind%': '<!pymod_do_main(has_valgrind)',
-
-      'test_isolation_mode%': 'noop',
-
-      'conditions': [
-        # Set default gomadir.
-        ['OS=="win"', {
-          'gomadir': 'c:\\goma\\goma-win',
-        }, {
-          'gomadir': '<!(/bin/echo -n ${HOME}/goma)',
-        }],
-        ['host_arch!="ppc" and host_arch!="ppc64" and host_arch!="ppc64le" and host_arch!="s390" and host_arch!="s390x"', {
-          'host_clang%': 1,
-        }, {
-          'host_clang%': 0,
-        }],
-        # linux_use_bundled_gold: whether to use the gold linker binary checked
-        # into third_party/binutils.  Force this off via GYP_DEFINES when you
-        # are using a custom toolchain and need to control -B in ldflags.
-        # Do not use 32-bit gold on 32-bit hosts as it runs out address space
-        # for component=static_library builds.
-        ['(OS=="linux" or OS=="android") and (target_arch=="x64" or target_arch=="arm" or (target_arch=="ia32" and host_arch=="x64"))', {
-          'linux_use_bundled_gold%': 1,
-        }, {
-          'linux_use_bundled_gold%': 0,
-        }],
-      ],
-    },
-    'base_dir%': '<(base_dir)',
-    'clang_dir%': '<(clang_dir)',
-    'host_arch%': '<(host_arch)',
-    'host_clang%': '<(host_clang)',
-    'target_arch%': '<(target_arch)',
-    'v8_target_arch%': '<(v8_target_arch)',
-    'werror%': '-Werror',
-    'use_goma%': '<(use_goma)',
-    'gomadir%': '<(gomadir)',
-    'asan%': '<(asan)',
-    'lsan%': '<(lsan)',
-    'msan%': '<(msan)',
-    'tsan%': '<(tsan)',
-    'sanitizer_coverage%': '<(sanitizer_coverage)',
-    'use_custom_libcxx%': '<(use_custom_libcxx)',
-    'linux_use_bundled_gold%': '<(linux_use_bundled_gold)',
-    'use_lto%': '<(use_lto)',
-    'cfi_vptr%': '<(cfi_vptr)',
-    'cfi_diag%': '<(cfi_diag)',
-    'cfi_blacklist%': '<(cfi_blacklist)',
-    'test_isolation_mode%': '<(test_isolation_mode)',
-    'fastbuild%': '<(fastbuild)',
-    'coverage%': '<(coverage)',
-    'has_valgrind%': '<(has_valgrind)',
-
-    # Add a simple extras solely for the purpose of the cctests
-    'v8_extra_library_files': ['../test/cctest/test-extra.js'],
-    'v8_experimental_extra_library_files': ['../test/cctest/test-experimental-extra.js'],
-
-    # .gyp files or targets should set v8_code to 1 if they build V8 specific
-    # code, as opposed to external code.  This variable is used to control such
-    # things as the set of warnings to enable, and whether warnings are treated
-    # as errors.
-    'v8_code%': 0,
-
-    # Speeds up Debug builds:
-    # 0 - Compiler optimizations off (debuggable) (default). This may
-    #     be 5x slower than Release (or worse).
-    # 1 - Turn on optimizations and disable slow DCHECKs, but leave
-    #     V8_ENABLE_CHECKS and most other assertions enabled.  This may cause
-    #     some v8 tests to fail in the Debug configuration.  This roughly
-    #     matches the performance of a Release build and can be used by
-    #     embedders that need to build their own code as debug but don't want
-    #     or need a debug version of V8. This should produce near-release
-    #     speeds.
-    'v8_optimized_debug%': 0,
-
-    # Use external files for startup data blobs:
-    # the JS builtins sources and the start snapshot.
-    # Embedders that don't use standalone.gypi will need to add
-    # their own default value.
-    'v8_use_external_startup_data%': 1,
-
-    # Use a separate ignition snapshot file in standalone builds.
-    'v8_separate_ignition_snapshot': 1,
-
-    # Relative path to icu.gyp from this file.
-    'icu_gyp_path': '../third_party/icu/icu.gyp',
-
-    'conditions': [
-      ['(v8_target_arch=="arm" and host_arch!="arm") or \
-        (v8_target_arch=="arm64" and host_arch!="arm64") or \
-        (v8_target_arch=="mipsel" and host_arch!="mipsel") or \
-        (v8_target_arch=="mips64el" and host_arch!="mips64el") or \
-        (v8_target_arch=="x64" and host_arch!="x64") or \
-        (OS=="android" or OS=="qnx")', {
-        'want_separate_host_toolset': 1,
-      }, {
-        'want_separate_host_toolset': 0,
-      }],
-      ['OS == "win"', {
-        'os_posix%': 0,
-      }, {
-        'os_posix%': 1,
-      }],
-      ['OS=="win" and use_goma==1', {
-        # goma doesn't support pch yet.
-        'chromium_win_pch': 0,
-        # goma doesn't support PDB yet.
-        'fastbuild%': 1,
-      }],
-      ['((v8_target_arch=="ia32" or v8_target_arch=="x64" or v8_target_arch=="x87") and \
-        (OS=="linux" or OS=="mac")) or (v8_target_arch=="ppc64" and OS=="linux")', {
-        'v8_enable_gdbjit%': 1,
-      }, {
-        'v8_enable_gdbjit%': 0,
-      }],
-      ['(OS=="linux" or OS=="mac") and (target_arch=="ia32" or target_arch=="x64") and \
-        (v8_target_arch!="x87" and v8_target_arch!="x32")', {
-        'clang%': 1,
-      }, {
-        'clang%': 0,
-      }],
-      ['asan==1 or lsan==1 or msan==1 or tsan==1', {
-        'clang%': 1,
-        'use_allocator%': 'none',
-      }],
-      ['asan==1 and OS=="linux"', {
-        'use_custom_libcxx%': 1,
-      }],
-      ['tsan==1', {
-        'use_custom_libcxx%': 1,
-      }],
-      ['msan==1', {
-        # Use a just-built, MSan-instrumented libc++ instead of the system-wide
-        # libstdc++. This is required to avoid false positive reports whenever
-        # the C++ standard library is used.
-        'use_custom_libcxx%': 1,
-      }],
-      ['cfi_vptr==1', {
-        'use_lto%': 1,
-      }],
-      ['OS=="android"', {
-        # Location of Android NDK.
-        'variables': {
-          'variables': {
-            # The Android toolchain needs to use the absolute path to the NDK
-            # because it is used at different levels in the GYP files.
-            'android_ndk_root%': '<(base_dir)/third_party/android_tools/ndk/',
-            'android_host_arch%': "<!(uname -m | sed -e 's/i[3456]86/x86/')",
-            'host_os%': "<!(uname -s | sed -e 's/Linux/linux/;s/Darwin/mac/')",
-          },
-
-          # Copy conditionally-set variables out one scope.
-          'android_ndk_root%': '<(android_ndk_root)',
-          'host_os%': '<(host_os)',
-
-          'conditions': [
-            ['target_arch == "ia32"', {
-              'android_toolchain%': '<(android_ndk_root)/toolchains/x86-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
-              'android_target_arch%': 'x86',
-              'android_target_platform%': '16',
-            }],
-            ['target_arch == "x64"', {
-              'android_toolchain%': '<(android_ndk_root)/toolchains/x86_64-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
-              'android_target_arch%': 'x86_64',
-              'android_target_platform%': '21',
-            }],
-            ['target_arch=="arm"', {
-              'android_toolchain%': '<(android_ndk_root)/toolchains/arm-linux-androideabi-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
-              'android_target_arch%': 'arm',
-              'android_target_platform%': '16',
-              'arm_version%': 7,
-            }],
-            ['target_arch == "arm64"', {
-              'android_toolchain%': '<(android_ndk_root)/toolchains/aarch64-linux-android-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
-              'android_target_arch%': 'arm64',
-              'android_target_platform%': '21',
-              'arm_version%': 'default',
-            }],
-            ['target_arch == "mipsel"', {
-              'android_toolchain%': '<(android_ndk_root)/toolchains/mipsel-linux-android-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
-              'android_target_arch%': 'mips',
-              'android_target_platform%': '16',
-            }],
-            ['target_arch == "mips64el"', {
-              'android_toolchain%': '<(android_ndk_root)/toolchains/mips64el-linux-android-4.9/prebuilt/<(host_os)-<(android_host_arch)/bin',
-              'android_target_arch%': 'mips64',
-              'android_target_platform%': '21',
-            }],
-          ],
-        },
-
-        # Copy conditionally-set variables out one scope.
-        'android_target_arch%': '<(android_target_arch)',
-        'android_target_platform%': '<(android_target_platform)',
-        'android_toolchain%': '<(android_toolchain)',
-        'arm_version%': '<(arm_version)',
-        'host_os%': '<(host_os)',
-
-        'conditions': [
-          ['android_ndk_root==""', {
-            'variables': {
-              'android_sysroot': '<(android_toolchain)/sysroot/',
-              'android_stl': '<(android_toolchain)/sources/cxx-stl/',
-            },
-            'conditions': [
-              ['target_arch=="x64"', {
-                'android_lib': '<(android_sysroot)/usr/lib64',
-              }, {
-                'android_lib': '<(android_sysroot)/usr/lib',
-              }],
-            ],
-            'android_libcpp_include': '<(android_stl)/llvm-libc++/libcxx/include',
-            'android_libcpp_abi_include': '<(android_stl)/llvm-libc++abi/libcxxabi/include',
-            'android_libcpp_libs': '<(android_stl)/llvm-libc++/libs',
-            'android_support_include': '<(android_toolchain)/sources/android/support/include',
-            'android_sysroot': '<(android_sysroot)',
-          }, {
-            'variables': {
-              'android_sysroot': '<(android_ndk_root)/platforms/android-<(android_target_platform)/arch-<(android_target_arch)',
-              'android_stl': '<(android_ndk_root)/sources/cxx-stl/',
-            },
-            'conditions': [
-              ['target_arch=="x64"', {
-                'android_lib': '<(android_sysroot)/usr/lib64',
-              }, {
-                'android_lib': '<(android_sysroot)/usr/lib',
-              }],
-            ],
-            'android_libcpp_include': '<(android_stl)/llvm-libc++/libcxx/include',
-            'android_libcpp_abi_include': '<(android_stl)/llvm-libc++abi/libcxxabi/include',
-            'android_libcpp_libs': '<(android_stl)/llvm-libc++/libs',
-            'android_support_include': '<(android_ndk_root)/sources/android/support/include',
-            'android_sysroot': '<(android_sysroot)',
-          }],
-        ],
-        'android_libcpp_library': 'c++_static',
-      }],  # OS=="android"
-      ['host_clang==1', {
-        'host_cc': '<(clang_dir)/bin/clang',
-        'host_cxx': '<(clang_dir)/bin/clang++',
-      }, {
-        'host_cc': '<!(which gcc)',
-        'host_cxx': '<!(which g++)',
-      }],
-    ],
-    # Default ARM variable settings.
-    'arm_version%': 'default',
-    'arm_fpu%': 'vfpv3',
-    'arm_float_abi%': 'default',
-    'arm_thumb': 'default',
-
-    # Default MIPS variable settings.
-    'mips_arch_variant%': 'r2',
-    # Possible values fp32, fp64, fpxx.
-    # fp32 - 32 32-bit FPU registers are available, doubles are placed in
-    #        register pairs.
-    # fp64 - 32 64-bit FPU registers are available.
-    # fpxx - compatibility mode, it chooses fp32 or fp64 depending on runtime
-    #        detection
-    'mips_fpu_mode%': 'fp32',
-
-    # Indicates if gcmole tools are downloaded by a hook.
-    'gcmole%': 0,
-  },
-  'target_defaults': {
-    'variables': {
-      'v8_code%': '<(v8_code)',
-      'conditions':[
-        ['OS=="android"', {
-          'host_os%': '<(host_os)',
-        }],
-      ],
-    },
-    'default_configuration': 'Debug',
-    'configurations': {
-      'DebugBaseCommon': {
-        'conditions': [
-          ['OS=="aix"', {
-            'cflags': [ '-g', '-Og', '-gxcoff' ],
-          }, {
-            'cflags': [ '-g', '-O0' ],
-          }],
-        ],
-      },
-      'Optdebug': {
-        'inherit_from': [ 'DebugBaseCommon', 'DebugBase1' ],
-      },
-      'Debug': {
-        # Xcode insists on this empty entry.
-      },
-      'Release': {
-        'cflags+': ['<@(release_extra_cflags)'],
-      },
-      'conditions': [
-        ['OS=="win"', {
-          'Optdebug_x64': {
-            'inherit_from': ['Optdebug'],
-          },
-          'Debug_x64': {
-            'inherit_from': ['Debug'],
-          },
-          'Release_x64': {
-            'inherit_from': ['Release'],
-          },
-        }],
-      ],
-    },
-    'conditions':[
-      ['clang==0', {
-        'cflags+': ['-Wno-sign-compare',],
-      }],
-      ['clang==1 or host_clang==1', {
-        # This is here so that all files get recompiled after a clang roll and
-        # when turning clang on or off.
-        # (defines are passed via the command line, and build systems rebuild
-        # things when their commandline changes). Nothing should ever read this
-        # define.
-        'defines': ['CR_CLANG_REVISION=<!(python <(DEPTH)/tools/clang/scripts/update.py --print-revision)'],
-        'conditions': [
-          ['host_clang==1', {
-            'target_conditions': [
-              ['_toolset=="host"', {
-                'cflags+': [
-                  '-Wno-format-pedantic',
-                 ],
-              }],
-           ],
-          }],
-          ['clang==1', {
-            'target_conditions': [
-              ['_toolset=="target"', {
-                'cflags+': [
-                  '-Wno-format-pedantic',
-                 ],
-              }],
-           ],
-          }],
-        ],
-      }],
-      ['fastbuild!=0', {
-        'conditions': [
-          ['OS=="win" and fastbuild==1', {
-            'msvs_settings': {
-              'VCLinkerTool': {
-                # This tells the linker to generate .pdbs, so that
-                # we can get meaningful stack traces.
-                'GenerateDebugInformation': 'true',
-              },
-              'VCCLCompilerTool': {
-                # No debug info to be generated by compiler.
-                'DebugInformationFormat': '0',
-              },
-            },
-          }],
-        ],
-      }],  # fastbuild!=0
-    ],
-    'target_conditions': [
-      ['v8_code == 0', {
-        'defines!': [
-          'DEBUG',
-        ],
-        'conditions': [
-          ['os_posix == 1 and OS != "mac"', {
-            # We don't want to get warnings from third-party code,
-            # so remove any existing warning-enabling flags like -Wall.
-            'cflags!': [
-              '-pedantic',
-              '-Wall',
-              '-Werror',
-              '-Wextra',
-              '-Wshorten-64-to-32',
-            ],
-            'cflags+': [
-              # Clang considers the `register` keyword as deprecated, but
-              # ICU uses it all over the place.
-              '-Wno-deprecated-register',
-              # ICU uses its own deprecated functions.
-              '-Wno-deprecated-declarations',
-              # ICU prefers `a && b || c` over `(a && b) || c`.
-              '-Wno-logical-op-parentheses',
-              # ICU has some `unsigned < 0` checks.
-              '-Wno-tautological-compare',
-              # uresdata.c has switch(RES_GET_TYPE(x)) code. The
-              # RES_GET_TYPE macro returns an UResType enum, but some switch
-              # statement contains case values that aren't part of that
-              # enum (e.g. URES_TABLE32 which is in UResInternalType). This
-              # is on purpose.
-              '-Wno-switch',
-            ],
-            'cflags_cc!': [
-              '-Wnon-virtual-dtor',
-            ],
-          }],
-          ['OS == "mac"', {
-            'xcode_settings': {
-              'GCC_TREAT_WARNINGS_AS_ERRORS': 'NO',    # -Werror
-            },
-          }],
-          ['OS == "win"', {
-            'msvs_settings': {
-              'VCCLCompilerTool': {
-                'WarnAsError': 'false',
-              },
-            },
-          }],
-        ],
-      }],
-    ],
-  },
-  'conditions': [
-    ['os_posix==1 and OS!="mac"', {
-      'target_defaults': {
-        'conditions': [
-          # Common options for AddressSanitizer, LeakSanitizer,
-          # ThreadSanitizer, MemorySanitizer and CFI builds.
-          ['asan==1 or lsan==1 or tsan==1 or msan==1 or cfi_vptr==1', {
-            'target_conditions': [
-              ['_toolset=="target"', {
-                'cflags': [
-                  '-fno-omit-frame-pointer',
-                  '-gline-tables-only',
-                ],
-                'cflags!': [
-                  '-fomit-frame-pointer',
-                ],
-              }],
-            ],
-          }],
-          ['asan==1', {
-            'target_conditions': [
-              ['_toolset=="target"', {
-                'cflags': [
-                  '-fsanitize=address',
-                ],
-                'ldflags': [
-                  '-fsanitize=address',
-                ],
-                'defines': [
-                  'ADDRESS_SANITIZER',
-                ],
-              }],
-            ],
-          }],
-          ['lsan==1', {
-            'target_conditions': [
-              ['_toolset=="target"', {
-                'cflags': [
-                  '-fsanitize=leak',
-                ],
-                'ldflags': [
-                  '-fsanitize=leak',
-                ],
-                'defines': [
-                  'LEAK_SANITIZER',
-                ],
-              }],
-            ],
-          }],
-          ['tsan==1', {
-            'target_conditions': [
-              ['_toolset=="target"', {
-                'cflags': [
-                  '-fsanitize=thread',
-                ],
-                'ldflags': [
-                  '-fsanitize=thread',
-                ],
-                'defines': [
-                  'THREAD_SANITIZER',
-                ],
-              }],
-            ],
-          }],
-          ['msan==1', {
-            'target_conditions': [
-              ['_toolset=="target"', {
-                'cflags': [
-                  '-fsanitize=memory',
-                  '-fsanitize-memory-track-origins=<(msan_track_origins)',
-                  '-fPIC',
-                ],
-                'ldflags': [
-                  '-fsanitize=memory',
-                  '-pie',
-                ],
-                'defines': [
-                  'MEMORY_SANITIZER',
-                ],
-              }],
-            ],
-          }],
-          ['use_custom_libcxx==1', {
-            'dependencies': [
-              '<(DEPTH)/buildtools/third_party/libc++/libc++.gyp:libcxx_proxy',
-            ],
-          }],
-          ['sanitizer_coverage!=0', {
-            'target_conditions': [
-              ['_toolset=="target"', {
-                'cflags': [
-                  '-fsanitize-coverage=<(sanitizer_coverage)',
-                ],
-                'defines': [
-                  'SANITIZER_COVERAGE',
-                ],
-              }],
-            ],
-          }],
-          ['linux_use_bundled_gold==1 and not (clang==0 and use_lto==1)', {
-            # Put our binutils, which contains gold in the search path. We pass
-            # the path to gold to the compiler. gyp leaves unspecified what the
-            # cwd is when running the compiler, so the normal gyp path-munging
-            # fails us. This hack gets the right path.
-            #
-            # Disabled when using GCC LTO because GCC also uses the -B search
-            # path at link time to find "as", and our bundled "as" can only
-            # target x86.
-            'ldflags': [
-              # Note, Chromium allows ia32 host arch as well, we limit this to
-              # x64 in v8.
-              '-B<(base_dir)/third_party/binutils/Linux_x64/Release/bin',
-            ],
-          }],
-        ],
-      },
-    }],
-    ['OS=="mac"', {
-      'target_defaults': {
-       'conditions': [
-          ['asan==1', {
-            'xcode_settings': {
-              # FIXME(machenbach): This is outdated compared to common.gypi.
-              'OTHER_CFLAGS+': [
-                '-fno-omit-frame-pointer',
-                '-gline-tables-only',
-                '-fsanitize=address',
-                '-w',  # http://crbug.com/162783
-              ],
-              'OTHER_CFLAGS!': [
-                '-fomit-frame-pointer',
-              ],
-              'defines': [
-                'ADDRESS_SANITIZER',
-              ],
-            },
-            'dependencies': [
-              '<(DEPTH)/build/mac/asan.gyp:asan_dynamic_runtime',
-            ],
-            'target_conditions': [
-              ['_type!="static_library"', {
-                'xcode_settings': {'OTHER_LDFLAGS': ['-fsanitize=address']},
-              }],
-            ],
-          }],
-          ['sanitizer_coverage!=0', {
-            'target_conditions': [
-              ['_toolset=="target"', {
-                'cflags': [
-                  '-fsanitize-coverage=<(sanitizer_coverage)',
-                ],
-                'defines': [
-                  'SANITIZER_COVERAGE',
-                ],
-              }],
-            ],
-          }],
-        ],
-      },  # target_defaults
-    }],  # OS=="mac"
-    ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
-       or OS=="netbsd" or OS=="aix"', {
-      'target_defaults': {
-        'cflags': [
-          '-Wall',
-          '<(werror)',
-          '-Wno-unused-parameter',
-          '-Wno-long-long',
-          '-pthread',
-          '-pedantic',
-          # Don't warn about the "struct foo f = {0};" initialization pattern.
-          '-Wno-missing-field-initializers',
-          '-Wno-gnu-zero-variadic-macro-arguments',
-        ],
-        'cflags_cc': [
-          '-Wnon-virtual-dtor',
-          '-fno-exceptions',
-          '-fno-rtti',
-          '-std=gnu++11',
-        ],
-        'ldflags': [ '-pthread', ],
-        'conditions': [
-          # Don't warn about TRACE_EVENT_* macros with zero arguments passed to
-          # ##__VA_ARGS__. C99 strict mode prohibits having zero variadic macro
-          # arguments in gcc.
-          [ 'clang==0', {
-            'cflags!' : [
-              '-pedantic' ,
-              # Don't warn about unrecognized command line option.
-              '-Wno-gnu-zero-variadic-macro-arguments',
-            ],
-          }],
-          [ 'clang==1 and (v8_target_arch=="x64" or v8_target_arch=="arm64" \
-            or v8_target_arch=="mips64el")', {
-            'cflags': [ '-Wshorten-64-to-32' ],
-          }],
-          [ 'host_arch=="ppc64" and OS!="aix"', {
-            'cflags': [ '-mminimal-toc' ],
-          }],
-          [ 'visibility=="hidden" and v8_enable_backtrace==0', {
-            'cflags': [ '-fvisibility=hidden' ],
-          }],
-          [ 'component=="shared_library"', {
-            'cflags': [ '-fPIC', ],
-          }],
-          [ 'clang==0 and coverage==1', {
-            'cflags': [ '-fprofile-arcs', '-ftest-coverage'],
-            'ldflags': [ '-fprofile-arcs'],
-          }],
-        ],
-      },
-    }],
-    # 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"
-    #  or OS=="netbsd"'
-    ['OS=="qnx"', {
-      'target_defaults': {
-        'cflags': [
-          '-Wall',
-          '<(werror)',
-          '-Wno-unused-parameter',
-          # Don't warn about the "struct foo f = {0};" initialization pattern.
-          '-Wno-missing-field-initializers',
-          '-Wno-gnu-zero-variadic-macro-arguments',
-        ],
-        'cflags_cc': [
-          '-Wnon-virtual-dtor',
-          '-fno-exceptions',
-          '-fno-rtti',
-          '-std=gnu++11',
-        ],
-        'conditions': [
-          [ 'visibility=="hidden"', {
-            'cflags': [ '-fvisibility=hidden' ],
-          }],
-          [ 'component=="shared_library"', {
-            'cflags': [ '-fPIC' ],
-          }],
-        ],
-        'target_conditions': [
-          [ '_toolset=="host" and host_os=="linux"', {
-            'cflags': [ '-pthread' ],
-            'ldflags': [ '-pthread' ],
-            'libraries': [ '-lrt' ],
-          }],
-          [ '_toolset=="target"', {
-            'cflags': [ '-Wno-psabi' ],
-            'libraries': [ '-lbacktrace', '-lsocket', '-lm' ],
-          }],
-        ],
-      },
-    }],  # OS=="qnx"
-    ['OS=="win"', {
-      'target_defaults': {
-        'defines': [
-          '_CRT_SECURE_NO_DEPRECATE',
-          '_CRT_NONSTDC_NO_DEPRECATE',
-          '_USING_V110_SDK71_',
-        ],
-        'conditions': [
-          ['component=="static_library"', {
-            'defines': [
-              '_HAS_EXCEPTIONS=0',
-            ],
-          }],
-        ],
-        'msvs_cygwin_dirs': ['<(DEPTH)/third_party/cygwin'],
-        'msvs_disabled_warnings': [
-          # C4091: 'typedef ': ignored on left of 'X' when no variable is
-          #                    declared.
-          # This happens in a number of Windows headers. Dumb.
-          4091,
-
-          # C4127: conditional expression is constant
-          # This warning can in theory catch dead code and other problems, but
-          # triggers in far too many desirable cases where the conditional
-          # expression is either set by macros or corresponds some legitimate
-          # compile-time constant expression (due to constant template args,
-          # conditionals comparing the sizes of different types, etc.).  Some of
-          # these can be worked around, but it's not worth it.
-          4127,
-
-          # C4351: new behavior: elements of array 'array' will be default
-          #        initialized
-          # This is a silly "warning" that basically just alerts you that the
-          # compiler is going to actually follow the language spec like it's
-          # supposed to, instead of not following it like old buggy versions
-          # did.  There's absolutely no reason to turn this on.
-          4351,
-
-          # C4355: 'this': used in base member initializer list
-          # It's commonly useful to pass |this| to objects in a class'
-          # initializer list.  While this warning can catch real bugs, most of
-          # the time the constructors in question don't attempt to call methods
-          # on the passed-in pointer (until later), and annotating every legit
-          # usage of this is simply more hassle than the warning is worth.
-          4355,
-
-          # C4503: 'identifier': decorated name length exceeded, name was
-          #        truncated
-          # This only means that some long error messages might have truncated
-          # identifiers in the presence of lots of templates.  It has no effect
-          # on program correctness and there's no real reason to waste time
-          # trying to prevent it.
-          4503,
-
-          # Warning C4589 says: "Constructor of abstract class ignores
-          # initializer for virtual base class." Disable this warning because it
-          # is flaky in VS 2015 RTM. It triggers on compiler generated
-          # copy-constructors in some cases.
-          4589,
-
-          # C4611: interaction between 'function' and C++ object destruction is
-          #        non-portable
-          # This warning is unavoidable when using e.g. setjmp/longjmp.  MSDN
-          # suggests using exceptions instead of setjmp/longjmp for C++, but
-          # Chromium code compiles without exception support.  We therefore have
-          # to use setjmp/longjmp for e.g. JPEG decode error handling, which
-          # means we have to turn off this warning (and be careful about how
-          # object destruction happens in such cases).
-          4611,
-
-          # TODO(jochen): These warnings are level 4. They will be slowly
-          # removed as code is fixed.
-          4100, # Unreferenced formal parameter
-          4121, # Alignment of a member was sensitive to packing
-          4244, # Conversion from 'type1' to 'type2', possible loss of data
-          4302, # Truncation from 'type 1' to 'type 2'
-          4309, # Truncation of constant value
-          4311, # Pointer truncation from 'type' to 'type'
-          4312, # Conversion from 'type1' to 'type2' of greater size
-          4505, # Unreferenced local function has been removed
-          4510, # Default constructor could not be generated
-          4512, # Assignment operator could not be generated
-          4610, # Object can never be instantiated
-          4800, # Forcing value to bool.
-          4838, # Narrowing conversion. Doesn't seem to be very useful.
-          4995, # 'X': name was marked as #pragma deprecated
-          4996, # 'X': was declared deprecated (for GetVersionEx).
-
-          # These are variable shadowing warnings that are new in VS2015. We
-          # should work through these at some point -- they may be removed from
-          # the RTM release in the /W4 set.
-          4456, 4457, 4458, 4459,
-        ],
-        'msvs_settings': {
-          'VCCLCompilerTool': {
-            'MinimalRebuild': 'false',
-            'BufferSecurityCheck': 'true',
-            'EnableFunctionLevelLinking': 'true',
-            'RuntimeTypeInfo': 'false',
-            'WarningLevel': '3',
-            'WarnAsError': 'true',
-            'DebugInformationFormat': '3',
-            'Detect64BitPortabilityProblems': 'false',
-            'conditions': [
-              [ 'msvs_multi_core_compile', {
-                'AdditionalOptions': ['/MP'],
-              }],
-              ['component=="shared_library"', {
-                'ExceptionHandling': '1',  # /EHsc
-              }, {
-                'ExceptionHandling': '0',
-              }],
-            ],
-          },
-          'VCLibrarianTool': {
-            'AdditionalOptions': ['/ignore:4221'],
-            'conditions': [
-              ['v8_target_arch=="x64"', {
-                'TargetMachine': '17',  # x64
-              }, {
-                'TargetMachine': '1',  # ia32
-              }],
-            ],
-          },
-          'VCLinkerTool': {
-            'AdditionalDependencies': [
-              'ws2_32.lib',
-            ],
-            'GenerateDebugInformation': 'true',
-            'MapFileName': '$(OutDir)\\$(TargetName).map',
-            'ImportLibrary': '$(OutDir)\\lib\\$(TargetName).lib',
-            'FixedBaseAddress': '1',
-            # LinkIncremental values:
-            #   0 == default
-            #   1 == /INCREMENTAL:NO
-            #   2 == /INCREMENTAL
-            'LinkIncremental': '1',
-            # SubSystem values:
-            #   0 == not set
-            #   1 == /SUBSYSTEM:CONSOLE
-            #   2 == /SUBSYSTEM:WINDOWS
-            'SubSystem': '1',
-
-            'conditions': [
-              ['v8_enable_i18n_support==1', {
-                'AdditionalDependencies': [
-                  'advapi32.lib',
-                ],
-              }],
-              ['v8_target_arch=="x64"', {
-                'MinimumRequiredVersion': '5.02',  # Server 2003.
-                'TargetMachine': '17',  # x64
-              }, {
-                'MinimumRequiredVersion': '5.01',  # XP.
-                'TargetMachine': '1',  # ia32
-              }],
-            ],
-          },
-        },
-      },
-    }],  # OS=="win"
-    ['OS=="mac"', {
-      'xcode_settings': {
-        'SDKROOT': 'macosx',
-        'SYMROOT': '<(DEPTH)/xcodebuild',
-      },
-      'target_defaults': {
-        'xcode_settings': {
-          'ALWAYS_SEARCH_USER_PATHS': 'NO',
-          'GCC_C_LANGUAGE_STANDARD': 'c99',         # -std=c99
-          'GCC_CW_ASM_SYNTAX': 'NO',                # No -fasm-blocks
-          'GCC_DYNAMIC_NO_PIC': 'NO',               # No -mdynamic-no-pic
-                                                    # (Equivalent to -fPIC)
-          'GCC_ENABLE_CPP_EXCEPTIONS': 'NO',        # -fno-exceptions
-          'GCC_ENABLE_CPP_RTTI': 'NO',              # -fno-rtti
-          'GCC_ENABLE_PASCAL_STRINGS': 'NO',        # No -mpascal-strings
-          # GCC_INLINES_ARE_PRIVATE_EXTERN maps to -fvisibility-inlines-hidden
-          'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES',
-          'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES',      # -fvisibility=hidden
-          'GCC_THREADSAFE_STATICS': 'NO',           # -fno-threadsafe-statics
-          'GCC_WARN_NON_VIRTUAL_DESTRUCTOR': 'YES', # -Wnon-virtual-dtor
-          # MACOSX_DEPLOYMENT_TARGET maps to -mmacosx-version-min
-          'MACOSX_DEPLOYMENT_TARGET': '<(mac_deployment_target)',
-          'PREBINDING': 'NO',                       # No -Wl,-prebind
-          'SYMROOT': '<(DEPTH)/xcodebuild',
-          'USE_HEADERMAP': 'NO',
-          'OTHER_CFLAGS': [
-            '-fno-strict-aliasing',
-          ],
-          'WARNING_CFLAGS': [
-            '-Wall',
-            '-Wendif-labels',
-            '-Wno-unused-parameter',
-            # Don't warn about the "struct foo f = {0};" initialization pattern.
-            '-Wno-missing-field-initializers',
-            '-Wno-gnu-zero-variadic-macro-arguments',
-          ],
-        },
-        'conditions': [
-          ['werror==""', {
-            'xcode_settings': {'GCC_TREAT_WARNINGS_AS_ERRORS': 'NO'},
-          }, {
-            'xcode_settings': {'GCC_TREAT_WARNINGS_AS_ERRORS': 'YES'},
-          }],
-          ['clang==1', {
-            'xcode_settings': {
-              'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
-              'CLANG_CXX_LANGUAGE_STANDARD': 'c++11',  # -std=c++11
-            },
-            'conditions': [
-              ['v8_target_arch=="x64" or v8_target_arch=="arm64" \
-                or v8_target_arch=="mips64el"', {
-                'xcode_settings': {'WARNING_CFLAGS': ['-Wshorten-64-to-32']},
-              }],
-            ],
-          }],
-        ],
-        'target_conditions': [
-          ['_type!="static_library"', {
-            'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-search_paths_first']},
-          }],
-        ],  # target_conditions
-      },  # target_defaults
-    }],  # OS=="mac"
-    ['OS=="android"', {
-      'target_defaults': {
-        'defines': [
-          'ANDROID',
-          'V8_ANDROID_LOG_STDOUT',
-        ],
-        'configurations': {
-          'Release': {
-            'cflags': [
-              '-fomit-frame-pointer',
-            ],
-          },  # Release
-        },  # configurations
-        'cflags': [ '-Wno-abi', '-Wall', '-W', '-Wno-unused-parameter'],
-        'cflags_cc': [ '-Wnon-virtual-dtor', '-fno-rtti', '-fno-exceptions',
-                       '-std=gnu++11' ],
-        'target_conditions': [
-          ['_toolset=="target"', {
-            'cflags!': [
-              '-pthread',  # Not supported by Android toolchain.
-            ],
-            'cflags': [
-              '-ffunction-sections',
-              '-funwind-tables',
-              '-fstack-protector',
-              '-fno-short-enums',
-              '-finline-limit=64',
-              '-Wa,--noexecstack',
-              '--sysroot=<(android_sysroot)',
-            ],
-            'cflags_cc': [
-              '-isystem<(android_libcpp_include)',
-              '-isystem<(android_libcpp_abi_include)',
-              '-isystem<(android_support_include)',
-            ],
-            'defines': [
-              'ANDROID',
-              #'__GNU_SOURCE=1',  # Necessary for clone()
-              'HAVE_OFF64_T',
-              'HAVE_SYS_UIO_H',
-              'ANDROID_BINSIZE_HACK', # Enable temporary hacks to reduce binsize.
-            ],
-            'ldflags!': [
-              '-pthread',  # Not supported by Android toolchain.
-            ],
-            'ldflags': [
-              '-Wl,--no-undefined',
-              '--sysroot=<(android_sysroot)',
-              '-nostdlib',
-            ],
-            'libraries!': [
-                '-lrt',  # librt is built into Bionic.
-                # Not supported by Android toolchain.
-                # Where do these come from?  Can't find references in
-                # any Chromium gyp or gypi file.  Maybe they come from
-                # gyp itself?
-                '-lpthread', '-lnss3', '-lnssutil3', '-lsmime3', '-lplds4', '-lplc4', '-lnspr4',
-              ],
-              'libraries': [
-                '-l<(android_libcpp_library)',
-                '-latomic',
-                # Manually link the libgcc.a that the cross compiler uses.
-                '<!(<(android_toolchain)/*-gcc -print-libgcc-file-name)',
-                '-lc',
-                '-ldl',
-                '-lm',
-            ],
-            'conditions': [
-              ['target_arch == "arm"', {
-                'ldflags': [
-                  # Enable identical code folding to reduce size.
-                  '-Wl,--icf=safe',
-                ],
-              }],
-              ['target_arch=="arm" and arm_version==7', {
-                'cflags': [
-                  '-march=armv7-a',
-                  '-mtune=cortex-a8',
-                  '-mfpu=vfp3',
-                ],
-                'ldflags': [
-                  '-L<(android_libcpp_libs)/armeabi-v7a',
-                ],
-              }],
-              ['target_arch=="arm" and arm_version < 7', {
-                'ldflags': [
-                  '-L<(android_libcpp_libs)/armeabi',
-                ],
-              }],
-              ['target_arch=="x64"', {
-                'ldflags': [
-                  '-L<(android_libcpp_libs)/x86_64',
-                ],
-              }],
-              ['target_arch=="arm64"', {
-                'ldflags': [
-                  '-L<(android_libcpp_libs)/arm64-v8a',
-                ],
-              }],
-              ['target_arch=="ia32" or target_arch=="x87"', {
-                # The x86 toolchain currently has problems with stack-protector.
-                'cflags!': [
-                  '-fstack-protector',
-                ],
-                'cflags': [
-                  '-fno-stack-protector',
-                ],
-                'ldflags': [
-                  '-L<(android_libcpp_libs)/x86',
-                ],
-              }],
-              ['target_arch=="mipsel"', {
-                # The mips toolchain currently has problems with stack-protector.
-                'cflags!': [
-                  '-fstack-protector',
-                  '-U__linux__'
-                ],
-                'cflags': [
-                  '-fno-stack-protector',
-                ],
-                'ldflags': [
-                  '-L<(android_libcpp_libs)/mips',
-                ],
-              }],
-              ['(target_arch=="arm" or target_arch=="arm64" or target_arch=="x64" or target_arch=="ia32") and component!="shared_library"', {
-                'cflags': [
-                  '-fPIE',
-                ],
-                'ldflags': [
-                  '-pie',
-                ],
-              }],
-            ],
-            'target_conditions': [
-              ['_type=="executable"', {
-                'conditions': [
-                  ['target_arch=="arm64" or target_arch=="x64"', {
-                    'ldflags': [
-                      '-Wl,-dynamic-linker,/system/bin/linker64',
-                    ],
-                  }, {
-                    'ldflags': [
-                      '-Wl,-dynamic-linker,/system/bin/linker',
-                    ],
-                  }]
-                ],
-                'ldflags': [
-                  '-Bdynamic',
-                  '-Wl,-z,nocopyreloc',
-                  # crtbegin_dynamic.o should be the last item in ldflags.
-                  '<(android_lib)/crtbegin_dynamic.o',
-                ],
-                'libraries': [
-                  # crtend_android.o needs to be the last item in libraries.
-                  # Do not add any libraries after this!
-                  '<(android_lib)/crtend_android.o',
-                ],
-              }],
-              ['_type=="shared_library"', {
-                'ldflags': [
-                  '-Wl,-shared,-Bsymbolic',
-                  '<(android_lib)/crtbegin_so.o',
-                ],
-              }],
-              ['_type=="static_library"', {
-                'ldflags': [
-                  # Don't export symbols from statically linked libraries.
-                  '-Wl,--exclude-libs=ALL',
-                ],
-              }],
-            ],
-          }],  # _toolset=="target"
-          # Settings for building host targets using the system toolchain.
-          ['_toolset=="host"', {
-            'cflags': [ '-pthread' ],
-            'ldflags': [ '-pthread' ],
-            'ldflags!': [
-              '-Wl,-z,noexecstack',
-              '-Wl,--gc-sections',
-              '-Wl,-O1',
-              '-Wl,--as-needed',
-            ],
-          }],
-        ],  # target_conditions
-      },  # target_defaults
-    }],  # OS=="android"
-    ['OS=="android" and clang==0', {
-      # Hardcode the compiler names in the Makefile so that
-      # it won't depend on the environment at make time.
-      'make_global_settings': [
-        ['CC', '<!(/bin/echo -n <(android_toolchain)/*-gcc)'],
-        ['CXX', '<!(/bin/echo -n <(android_toolchain)/*-g++)'],
-        ['CC.host', '<(host_cc)'],
-        ['CXX.host', '<(host_cxx)'],
-      ],
-    }],
-    ['clang!=1 and host_clang==1 and target_arch!="ia32" and target_arch!="x64"', {
-      'make_global_settings': [
-        ['CC.host', '<(clang_dir)/bin/clang'],
-        ['CXX.host', '<(clang_dir)/bin/clang++'],
-      ],
-    }],
-    ['clang==0 and host_clang==1 and target_arch!="ia32" and target_arch!="x64"', {
-      'target_conditions': [
-        ['_toolset=="host"', {
-          'cflags_cc': [ '-std=gnu++11', ],
-        }],
-      ],
-      'target_defaults': {
-        'target_conditions': [
-          ['_toolset=="host"', { 'cflags!': [ '-Wno-unused-local-typedefs' ]}],
-        ],
-      },
-    }],
-    ['clang==1 and "<(GENERATOR)"=="ninja"', {
-      # See http://crbug.com/110262
-      'target_defaults': {
-        'cflags': [ '-fcolor-diagnostics' ],
-        'xcode_settings': { 'OTHER_CFLAGS': [ '-fcolor-diagnostics' ] },
-      },
-    }],
-    ['clang==1 and ((OS!="mac" and OS!="ios") or clang_xcode==0) '
-        'and OS!="win" and "<(GENERATOR)"=="make"', {
-      'make_global_settings': [
-        ['CC', '<(clang_dir)/bin/clang'],
-        ['CXX', '<(clang_dir)/bin/clang++'],
-        ['CC.host', '$(CC)'],
-        ['CXX.host', '$(CXX)'],
-      ],
-    }],
-    ['clang==1 and ((OS!="mac" and OS!="ios") or clang_xcode==0) '
-        'and OS!="win" and "<(GENERATOR)"=="ninja"', {
-      'make_global_settings': [
-        ['CC', '<(clang_dir)/bin/clang'],
-        ['CXX', '<(clang_dir)/bin/clang++'],
-        ['CC.host', '$(CC)'],
-        ['CXX.host', '$(CXX)'],
-      ],
-    }],
-    ['clang==1 and OS=="win"', {
-      'make_global_settings': [
-        # On Windows, gyp's ninja generator only looks at CC.
-        ['CC', '<(clang_dir)/bin/clang-cl'],
-      ],
-    }],
-    ['OS=="linux" and target_arch=="arm" and host_arch!="arm" and clang==0 and "<(GENERATOR)"=="ninja"', {
-      # Set default ARM cross tools on linux.  These can be overridden
-      # using CC,CXX,CC.host and CXX.host environment variables.
-      'make_global_settings': [
-        ['CC', '<!(which arm-linux-gnueabihf-gcc)'],
-        ['CXX', '<!(which arm-linux-gnueabihf-g++)'],
-        ['CC.host', '<(host_cc)'],
-        ['CXX.host', '<(host_cxx)'],
-      ],
-    }],
-    # TODO(yyanagisawa): supports GENERATOR==make
-    #  make generator doesn't support CC_wrapper without CC
-    #  in make_global_settings yet.
-    ['use_goma==1 and ("<(GENERATOR)"=="ninja" or clang==1)', {
-      'conditions': [
-        ['coverage==1', {
-          # Wrap goma with coverage wrapper.
-          'make_global_settings': [
-            ['CC_wrapper', '<(base_dir)/build/coverage_wrapper.py <(gomadir)/gomacc'],
-            ['CXX_wrapper', '<(base_dir)/build/coverage_wrapper.py <(gomadir)/gomacc'],
-            ['CC.host_wrapper', '<(base_dir)/build/coverage_wrapper.py <(gomadir)/gomacc'],
-            ['CXX.host_wrapper', '<(base_dir)/build/coverage_wrapper.py <(gomadir)/gomacc'],
-          ],
-        }, {
-          # Use only goma wrapper.
-          'make_global_settings': [
-            ['CC_wrapper', '<(gomadir)/gomacc'],
-            ['CXX_wrapper', '<(gomadir)/gomacc'],
-            ['CC.host_wrapper', '<(gomadir)/gomacc'],
-            ['CXX.host_wrapper', '<(gomadir)/gomacc'],
-          ],
-        }],
-      ],
-    }, {
-      'conditions': [
-        ['coverage==1', {
-          # Use only coverage wrapper.
-          'make_global_settings': [
-            ['CC_wrapper', '<(base_dir)/build/coverage_wrapper.py'],
-            ['CXX_wrapper', '<(base_dir)/build/coverage_wrapper.py'],
-            ['CC.host_wrapper', '<(base_dir)/build/coverage_wrapper.py'],
-            ['CXX.host_wrapper', '<(base_dir)/build/coverage_wrapper.py'],
-          ],
-        }],
-      ],
-    }],
-    ['use_lto==1', {
-      'target_defaults': {
-        'target_conditions': [
-          ['_toolset=="target"', {
-            'cflags': [
-              '-flto',
-            ],
-          }],
-        ],
-      },
-    }],
-    ['use_lto==1 and clang==0', {
-      'target_defaults': {
-        'target_conditions': [
-          ['_toolset=="target"', {
-            'cflags': [
-              '-ffat-lto-objects',
-            ],
-          }],
-        ],
-      },
-    }],
-    ['use_lto==1 and clang==1', {
-      'target_defaults': {
-        'target_conditions': [
-          ['_toolset=="target"', {
-            'arflags': [
-              '--plugin', '<(clang_dir)/lib/LLVMgold.so',
-            ],
-            # Apply a lower optimization level with lto. Chromium does this
-            # for non-official builds only - a differentiation that doesn't
-            # exist in v8.
-            'ldflags': [
-              '-Wl,--plugin-opt,O1',
-            ],
-          }],
-        ],
-      },
-    }],
-    ['use_lto==1 and clang==0', {
-      'target_defaults': {
-        'target_conditions': [
-          ['_toolset=="target"', {
-            'ldflags': [
-              '-flto=32',
-            ],
-          }],
-        ],
-      },
-    }],
-    ['use_lto==1 and clang==1', {
-      'target_defaults': {
-        'target_conditions': [
-          ['_toolset=="target"', {
-            'ldflags': [
-              '-flto',
-            ],
-          }],
-        ],
-      },
-    }],
-    ['cfi_diag==1', {
-      'target_defaults': {
-        'target_conditions': [
-          ['_toolset=="target"', {
-            'cflags': [
-              '-fno-sanitize-trap=cfi',
-              '-fno-sanitize-recover=cfi',
-            ],
-            'cflags_cc!': [
-              '-fno-rtti',
-            ],
-            'cflags!': [
-              '-fno-rtti',
-            ],
-            'ldflags': [
-              '-fno-sanitize-trap=cfi',
-              '-fno-sanitize-recover=cfi',
-            ],
-          }],
-        ],
-      },
-    }],
-    ['cfi_vptr==1', {
-      'target_defaults': {
-        'target_conditions': [
-          ['_toolset=="target"', {
-            'cflags': [
-              '-fsanitize=cfi-vcall',
-              '-fsanitize=cfi-derived-cast',
-              '-fsanitize=cfi-unrelated-cast',
-              '-fsanitize-blacklist=<(cfi_blacklist)',
-            ],
-            'ldflags': [
-              '-fsanitize=cfi-vcall',
-              '-fsanitize=cfi-derived-cast',
-              '-fsanitize=cfi-unrelated-cast',
-            ],
-          }],
-        ],
-      },
-    }],
-  ],
-}
diff --git a/build/toolchain.gypi b/build/toolchain.gypi
deleted file mode 100644
index 6090898..0000000
--- a/build/toolchain.gypi
+++ /dev/null
@@ -1,1394 +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.
-
-# Shared definitions for all V8-related targets.
-
-{
-  'variables': {
-    'msvs_use_common_release': 0,
-    'clang%': 0,
-    'asan%': 0,
-    'lsan%': 0,
-    'msan%': 0,
-    'tsan%': 0,
-    'ubsan%': 0,
-    'ubsan_vptr%': 0,
-    'v8_target_arch%': '<(target_arch)',
-    'v8_host_byteorder%': '<!(python -c "import sys; print sys.byteorder")',
-    # Native Client builds currently use the V8 ARM JIT and
-    # arm/simulator-arm.cc to defer the significant effort required
-    # for NaCl JIT support. The nacl_target_arch variable provides
-    # the 'true' target arch for places in this file that need it.
-    # TODO(bradchen): get rid of nacl_target_arch when someday
-    # NaCl V8 builds stop using the ARM simulator
-    'nacl_target_arch%': 'none',     # must be set externally
-
-    # Setting 'v8_can_use_vfp32dregs' to 'true' will cause V8 to use the VFP
-    # registers d16-d31 in the generated code, both in the snapshot and for the
-    # ARM target. Leaving the default value of 'false' will avoid the use of
-    # these registers in the snapshot and use CPU feature probing when running
-    # on the target.
-    'v8_can_use_vfp32dregs%': 'false',
-    'arm_test_noprobe%': 'off',
-
-    # Similar to vfp but on MIPS.
-    'v8_can_use_fpu_instructions%': 'true',
-
-    # Similar to the ARM hard float ABI but on MIPS.
-    'v8_use_mips_abi_hardfloat%': 'true',
-
-    # Force disable libstdc++ debug mode.
-    'disable_glibcxx_debug%': 0,
-
-    'v8_enable_backtrace%': 0,
-
-    # Enable profiling support. Only required on Windows.
-    'v8_enable_prof%': 0,
-
-    # Some versions of GCC 4.5 seem to need -fno-strict-aliasing.
-    'v8_no_strict_aliasing%': 0,
-
-    # Chrome needs this definition unconditionally. For standalone V8 builds,
-    # it's handled in build/standalone.gypi.
-    'want_separate_host_toolset%': 1,
-
-    # Toolset the d8 binary should be compiled for. Possible values are 'host'
-    # and 'target'. If you want to run v8 tests, it needs to be set to 'target'.
-    # The setting is ignored if want_separate_host_toolset is 0.
-    'v8_toolset_for_d8%': 'target',
-
-    # Control usage of a separate ignition snapshot file.
-    'v8_separate_ignition_snapshot%': 0,
-
-    'host_os%': '<(OS)',
-    'werror%': '-Werror',
-    # For a shared library build, results in "libv8-<(soname_version).so".
-    'soname_version%': '',
-
-    # Allow to suppress the array bounds warning (default is no suppression).
-    'wno_array_bounds%': '',
-
-    # Override where to find binutils
-    'binutils_dir%': '',
-
-    'conditions': [
-      ['OS=="linux" and host_arch=="x64"', {
-        'binutils_dir%': 'third_party/binutils/Linux_x64/Release/bin',
-      }],
-      ['OS=="linux" and host_arch=="ia32"', {
-        'binutils_dir%': 'third_party/binutils/Linux_ia32/Release/bin',
-      }],
-
-      # linux_use_bundled_gold: whether to use the gold linker binary checked
-      # into third_party/binutils.  Force this off via GYP_DEFINES when you
-      # are using a custom toolchain and need to control -B in ldflags.
-      # Do not use 32-bit gold on 32-bit hosts as it runs out address space
-      # for component=static_library builds.
-      ['OS=="linux" and (target_arch=="x64" or target_arch=="arm")', {
-        'linux_use_bundled_gold%': 1,
-      }, {
-        'linux_use_bundled_gold%': 0,
-      }],
-      # linux_use_bundled_binutils: whether to use the binary binutils
-      # checked into third_party/binutils.  These are not multi-arch so cannot
-      # be used except on x86 and x86-64 (the only two architectures which
-      # are currently checke in).  Force this off via GYP_DEFINES when you
-      # are using a custom toolchain and need to control -B in cflags.
-      ['OS=="linux" and (target_arch=="ia32" or target_arch=="x64")', {
-        'linux_use_bundled_binutils%': 1,
-      }, {
-        'linux_use_bundled_binutils%': 0,
-      }],
-      # linux_use_gold_flags: whether to use build flags that rely on gold.
-      # On by default for x64 Linux.
-      ['OS=="linux" and target_arch=="x64"', {
-        'linux_use_gold_flags%': 1,
-      }, {
-        'linux_use_gold_flags%': 0,
-      }],
-    ],
-
-    # Link-Time Optimizations
-    'use_lto%': 0,
-  },
-  'conditions': [
-    ['host_arch=="ia32" or host_arch=="x64" or \
-      host_arch=="ppc" or host_arch=="ppc64" or \
-      host_arch=="s390" or host_arch=="s390x" or \
-      clang==1', {
-      'variables': {
-        'host_cxx_is_biarch%': 1,
-       },
-     }, {
-      'variables': {
-        'host_cxx_is_biarch%': 0,
-      },
-    }],
-    ['target_arch=="ia32" or target_arch=="x64" or target_arch=="x87" or \
-      target_arch=="ppc" or target_arch=="ppc64" or target_arch=="s390" or \
-      target_arch=="s390x" or clang==1', {
-      'variables': {
-        'target_cxx_is_biarch%': 1,
-       },
-     }, {
-      'variables': {
-        'target_cxx_is_biarch%': 0,
-      },
-    }],
-  ],
-  'target_defaults': {
-    'conditions': [
-      ['v8_target_arch=="arm"', {
-        'defines': [
-          'V8_TARGET_ARCH_ARM',
-        ],
-        'conditions': [
-          [ 'arm_version==7 or arm_version=="default"', {
-            'defines': [
-              'CAN_USE_ARMV7_INSTRUCTIONS',
-            ],
-          }],
-          [ 'arm_fpu=="vfpv3-d16" or arm_fpu=="default"', {
-            'defines': [
-              'CAN_USE_VFP3_INSTRUCTIONS',
-            ],
-          }],
-          [ 'arm_fpu=="vfpv3"', {
-            'defines': [
-              'CAN_USE_VFP3_INSTRUCTIONS',
-              'CAN_USE_VFP32DREGS',
-            ],
-          }],
-          [ 'arm_fpu=="neon"', {
-            'defines': [
-              'CAN_USE_VFP3_INSTRUCTIONS',
-              'CAN_USE_VFP32DREGS',
-              'CAN_USE_NEON',
-            ],
-          }],
-          [ 'arm_test_noprobe=="on"', {
-            'defines': [
-              'ARM_TEST_NO_FEATURE_PROBE',
-            ],
-          }],
-        ],
-        'target_conditions': [
-          ['_toolset=="host"', {
-            'conditions': [
-              ['v8_target_arch==host_arch', {
-                # Host built with an Arm CXX compiler.
-                'conditions': [
-                  [ 'arm_version==7', {
-                    'cflags': ['-march=armv7-a',],
-                  }],
-                  [ 'arm_version==7 or arm_version=="default"', {
-                    'conditions': [
-                      [ 'arm_fpu!="default"', {
-                        'cflags': ['-mfpu=<(arm_fpu)',],
-                      }],
-                    ],
-                  }],
-                  [ 'arm_float_abi!="default"', {
-                    'cflags': ['-mfloat-abi=<(arm_float_abi)',],
-                  }],
-                  [ 'arm_thumb==1', {
-                    'cflags': ['-mthumb',],
-                  }],
-                  [ 'arm_thumb==0', {
-                    'cflags': ['-marm',],
-                  }],
-                ],
-              }, {
-                # 'v8_target_arch!=host_arch'
-                # Host not built with an Arm CXX compiler (simulator build).
-                'conditions': [
-                  [ 'arm_float_abi=="hard"', {
-                    'defines': [
-                      'USE_EABI_HARDFLOAT=1',
-                    ],
-                  }],
-                  [ 'arm_float_abi=="softfp" or arm_float_abi=="default"', {
-                    'defines': [
-                      'USE_EABI_HARDFLOAT=0',
-                    ],
-                  }],
-                ],
-              }],
-            ],
-          }],  # _toolset=="host"
-          ['_toolset=="target"', {
-            'conditions': [
-              ['v8_target_arch==target_arch', {
-                # Target built with an Arm CXX compiler.
-                'conditions': [
-                  [ 'arm_version==7', {
-                    'cflags': ['-march=armv7-a',],
-                  }],
-                  [ 'arm_version==7 or arm_version=="default"', {
-                    'conditions': [
-                      [ 'arm_fpu!="default"', {
-                        'cflags': ['-mfpu=<(arm_fpu)',],
-                      }],
-                    ],
-                  }],
-                  [ 'arm_float_abi!="default"', {
-                    'cflags': ['-mfloat-abi=<(arm_float_abi)',],
-                  }],
-                  [ 'arm_thumb==1', {
-                    'cflags': ['-mthumb',],
-                  }],
-                  [ 'arm_thumb==0', {
-                    'cflags': ['-marm',],
-                  }],
-                ],
-              }, {
-                # 'v8_target_arch!=target_arch'
-                # Target not built with an Arm CXX compiler (simulator build).
-                'conditions': [
-                  [ 'arm_float_abi=="hard"', {
-                    'defines': [
-                      'USE_EABI_HARDFLOAT=1',
-                    ],
-                  }],
-                  [ 'arm_float_abi=="softfp" or arm_float_abi=="default"', {
-                    'defines': [
-                      'USE_EABI_HARDFLOAT=0',
-                    ],
-                  }],
-                ],
-              }],
-              # Disable GCC LTO for v8
-              # v8 is optimized for speed. Because GCC LTO merges flags at link
-              # time, we disable LTO to prevent any -O2 flags from taking
-              # precedence over v8's -Os flag. However, LLVM LTO does not work
-              # this way so we keep LTO enabled under LLVM.
-              ['clang==0 and use_lto==1', {
-                'cflags!': [
-                  '-flto',
-                  '-ffat-lto-objects',
-                ],
-              }],
-            ],
-          }],  # _toolset=="target"
-        ],
-      }],  # v8_target_arch=="arm"
-      ['v8_target_arch=="arm64"', {
-        'defines': [
-          'V8_TARGET_ARCH_ARM64',
-        ],
-      }],
-      ['v8_target_arch=="s390" or v8_target_arch=="s390x"', {
-        'defines': [
-          'V8_TARGET_ARCH_S390',
-        ],
-        'conditions': [
-          ['v8_target_arch=="s390x"', {
-            'defines': [
-              'V8_TARGET_ARCH_S390X',
-            ],
-          }],
-          ['v8_host_byteorder=="little"', {
-            'defines': [
-              'V8_TARGET_ARCH_S390_LE_SIM',
-            ],
-          }],
-          ],
-      }],  # s390
-      ['v8_target_arch=="ppc" or v8_target_arch=="ppc64"', {
-        'defines': [
-          'V8_TARGET_ARCH_PPC',
-        ],
-        'conditions': [
-          ['v8_target_arch=="ppc64"', {
-            'defines': [
-              'V8_TARGET_ARCH_PPC64',
-            ],
-          }],
-          ['v8_host_byteorder=="little"', {
-            'defines': [
-              'V8_TARGET_ARCH_PPC_LE',
-            ],
-          }],
-          ['v8_host_byteorder=="big"', {
-            'defines': [
-              'V8_TARGET_ARCH_PPC_BE',
-            ],
-            'conditions': [
-              ['OS=="aix"', {
-                # Work around AIX ceil, trunc and round oddities.
-                'cflags': [ '-mcpu=power5+ -mfprnd' ],
-              }],
-              ['OS=="aix"', {
-                # Work around AIX assembler popcntb bug.
-                'cflags': [ '-mno-popcntb' ],
-              }],
-            ],
-          }],
-        ],
-      }],  # ppc
-      ['v8_target_arch=="ia32"', {
-        'defines': [
-          'V8_TARGET_ARCH_IA32',
-        ],
-      }],  # v8_target_arch=="ia32"
-      ['v8_target_arch=="x87"', {
-        'defines': [
-          'V8_TARGET_ARCH_X87',
-        ],
-        'cflags': ['-march=i586'],
-      }],  # v8_target_arch=="x87"
-      ['(v8_target_arch=="mips" or v8_target_arch=="mipsel" \
-        or v8_target_arch=="mips64" or v8_target_arch=="mips64el") \
-         and v8_target_arch==target_arch', {
-        'target_conditions': [
-          ['_toolset=="target"', {
-            # Target built with a Mips CXX compiler.
-            'variables': {
-              'ldso_path%': '<!(/bin/echo -n $LDSO_PATH)',
-              'ld_r_path%': '<!(/bin/echo -n $LD_R_PATH)',
-            },
-            'conditions': [
-              ['ldso_path!=""', {
-                'ldflags': ['-Wl,--dynamic-linker=<(ldso_path)'],
-              }],
-              ['ld_r_path!=""', {
-                'ldflags': ['-Wl,--rpath=<(ld_r_path)'],
-              }],
-              [ 'clang==1', {
-                'cflags': ['-integrated-as'],
-              }],
-            ],
-          }],
-        ],
-      }],
-      ['v8_target_arch=="mips"', {
-        'defines': [
-          'V8_TARGET_ARCH_MIPS',
-        ],
-        'conditions': [
-          [ 'v8_can_use_fpu_instructions=="true"', {
-            'defines': [
-              'CAN_USE_FPU_INSTRUCTIONS',
-            ],
-          }],
-          [ 'v8_use_mips_abi_hardfloat=="true"', {
-            'defines': [
-              '__mips_hard_float=1',
-              'CAN_USE_FPU_INSTRUCTIONS',
-            ],
-          }, {
-            'defines': [
-              '__mips_soft_float=1'
-            ]
-          }],
-        ],
-        'target_conditions': [
-          ['_toolset=="target"', {
-            'conditions': [
-              ['v8_target_arch==target_arch', {
-                # Target built with a Mips CXX compiler.
-                'cflags': [
-                  '-EB',
-                  '-Wno-error=array-bounds',  # Workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56273
-                ],
-                'ldflags': ['-EB'],
-                'conditions': [
-                  [ 'v8_use_mips_abi_hardfloat=="true"', {
-                    'cflags': ['-mhard-float'],
-                    'ldflags': ['-mhard-float'],
-                  }, {
-                    'cflags': ['-msoft-float'],
-                    'ldflags': ['-msoft-float'],
-                  }],
-                  ['mips_arch_variant=="r6"', {
-                    'defines': [
-                      '_MIPS_ARCH_MIPS32R6',
-                      'FPU_MODE_FP64',
-                    ],
-                    'cflags!': ['-mfp32', '-mfpxx'],
-                    'conditions': [
-                      [ 'clang==0', {
-                        'cflags': ['-Wa,-mips32r6'],
-                      }],
-                    ],
-                    'cflags': ['-mips32r6'],
-                    'ldflags': ['-mips32r6'],
-                  }],
-                  ['mips_arch_variant=="r2"', {
-                    'conditions': [
-                      [ 'mips_fpu_mode=="fp64"', {
-                        'defines': [
-                          '_MIPS_ARCH_MIPS32R2',
-                          'FPU_MODE_FP64',
-                        ],
-                        'cflags': ['-mfp64'],
-                      }],
-                      ['mips_fpu_mode=="fpxx"', {
-                        'defines': [
-                          '_MIPS_ARCH_MIPS32R2',
-                          'FPU_MODE_FPXX',
-                        ],
-                        'cflags': ['-mfpxx'],
-                      }],
-                      ['mips_fpu_mode=="fp32"', {
-                        'defines': [
-                          '_MIPS_ARCH_MIPS32R2',
-                          'FPU_MODE_FP32',
-                        ],
-                        'cflags': ['-mfp32'],
-                      }],
-                      [ 'clang==0', {
-                        'cflags': ['-Wa,-mips32r2'],
-                      }],
-                    ],
-                    'cflags': ['-mips32r2'],
-                    'ldflags': ['-mips32r2'],
-                  }],
-                  ['mips_arch_variant=="r1"', {
-                    'defines': [
-                      'FPU_MODE_FP32',
-                    ],
-                    'cflags!': ['-mfp64', '-mfpxx'],
-                    'conditions': [
-                      [ 'clang==0', {
-                        'cflags': ['-Wa,-mips32'],
-                      }],
-                    ],
-                    'cflags': ['-mips32'],
-                    'ldflags': ['-mips32'],
-                  }],
-                  ['mips_arch_variant=="rx"', {
-                    'defines': [
-                      '_MIPS_ARCH_MIPS32RX',
-                      'FPU_MODE_FPXX',
-                    ],
-                    'cflags!': ['-mfp64', '-mfp32'],
-                    'conditions': [
-                      [ 'clang==0', {
-                        'cflags': ['-Wa,-mips32'],
-                      }],
-                    ],
-                    'cflags': ['-mips32', '-mfpxx'],
-                    'ldflags': ['-mips32'],
-                  }],
-                ],
-              }, {
-                # 'v8_target_arch!=target_arch'
-                # Target not built with an MIPS CXX compiler (simulator build).
-                'conditions': [
-                  ['mips_arch_variant=="r6"', {
-                    'defines': [
-                      '_MIPS_ARCH_MIPS32R6',
-                      'FPU_MODE_FP64',
-                    ],
-                  }],
-                  ['mips_arch_variant=="r2"', {
-                    'conditions': [
-                      [ 'mips_fpu_mode=="fp64"', {
-                        'defines': [
-                          '_MIPS_ARCH_MIPS32R2',
-                          'FPU_MODE_FP64',
-                        ],
-                      }],
-                      ['mips_fpu_mode=="fpxx"', {
-                        'defines': [
-                          '_MIPS_ARCH_MIPS32R2',
-                          'FPU_MODE_FPXX',
-                        ],
-                      }],
-                      ['mips_fpu_mode=="fp32"', {
-                        'defines': [
-                          '_MIPS_ARCH_MIPS32R2',
-                          'FPU_MODE_FP32',
-                        ],
-                      }],
-                    ],
-                  }],
-                  ['mips_arch_variant=="r1"', {
-                    'defines': [
-                      'FPU_MODE_FP32',
-                    ],
-                  }],
-                  ['mips_arch_variant=="rx"', {
-                    'defines': [
-                      '_MIPS_ARCH_MIPS32RX',
-                      'FPU_MODE_FPXX',
-                    ],
-                  }],
-                ],
-              }],
-            ],
-          }],  #_toolset=="target"
-          ['_toolset=="host"', {
-            'conditions': [
-              ['mips_arch_variant=="rx"', {
-                'defines': [
-                  '_MIPS_ARCH_MIPS32RX',
-                  'FPU_MODE_FPXX',
-                ],
-              }],
-              ['mips_arch_variant=="r6"', {
-                'defines': [
-                  '_MIPS_ARCH_MIPS32R6',
-                  'FPU_MODE_FP64',
-                ],
-              }],
-              ['mips_arch_variant=="r2"', {
-                'conditions': [
-                  ['mips_fpu_mode=="fp64"', {
-                    'defines': [
-                      '_MIPS_ARCH_MIPS32R2',
-                      'FPU_MODE_FP64',
-                    ],
-                  }],
-                  ['mips_fpu_mode=="fpxx"', {
-                    'defines': [
-                      '_MIPS_ARCH_MIPS32R2',
-                      'FPU_MODE_FPXX',
-                    ],
-                  }],
-                  ['mips_fpu_mode=="fp32"', {
-                    'defines': [
-                      '_MIPS_ARCH_MIPS32R2',
-                      'FPU_MODE_FP32'
-                    ],
-                  }],
-                ],
-              }],
-              ['mips_arch_variant=="r1"', {
-                'defines': ['FPU_MODE_FP32',],
-              }],
-            ]
-          }],  #_toolset=="host"
-        ],
-      }],  # v8_target_arch=="mips"
-      ['v8_target_arch=="mipsel"', {
-        'defines': [
-          'V8_TARGET_ARCH_MIPS',
-        ],
-        'conditions': [
-          [ 'v8_can_use_fpu_instructions=="true"', {
-            'defines': [
-              'CAN_USE_FPU_INSTRUCTIONS',
-            ],
-          }],
-          [ 'v8_use_mips_abi_hardfloat=="true"', {
-            'defines': [
-              '__mips_hard_float=1',
-              'CAN_USE_FPU_INSTRUCTIONS',
-            ],
-          }, {
-            'defines': [
-              '__mips_soft_float=1'
-            ],
-          }],
-        ],
-        'target_conditions': [
-          ['_toolset=="target"', {
-            'conditions': [
-              ['v8_target_arch==target_arch', {
-                # Target built with a Mips CXX compiler.
-                'cflags': [
-                  '-EL',
-                  '-Wno-error=array-bounds',  # Workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56273
-                ],
-                'ldflags': ['-EL'],
-                'conditions': [
-                  [ 'v8_use_mips_abi_hardfloat=="true"', {
-                    'cflags': ['-mhard-float'],
-                    'ldflags': ['-mhard-float'],
-                  }, {
-                    'cflags': ['-msoft-float'],
-                    'ldflags': ['-msoft-float'],
-                  }],
-                  ['mips_arch_variant=="r6"', {
-                    'defines': [
-                      '_MIPS_ARCH_MIPS32R6',
-                      'FPU_MODE_FP64',
-                    ],
-                    'cflags!': ['-mfp32', '-mfpxx'],
-                    'conditions': [
-                      [ 'clang==0', {
-                        'cflags': ['-Wa,-mips32r6'],
-                      }],
-                    ],
-                    'cflags': ['-mips32r6'],
-                    'ldflags': ['-mips32r6'],
-                  }],
-                  ['mips_arch_variant=="r2"', {
-                    'conditions': [
-                      [ 'mips_fpu_mode=="fp64"', {
-                        'defines': [
-                          '_MIPS_ARCH_MIPS32R2',
-                          'FPU_MODE_FP64',
-                        ],
-                        'cflags': ['-mfp64'],
-                      }],
-                      ['mips_fpu_mode=="fpxx"', {
-                        'defines': [
-                          '_MIPS_ARCH_MIPS32R2',
-                          'FPU_MODE_FPXX',
-                        ],
-                        'cflags': ['-mfpxx'],
-                      }],
-                      ['mips_fpu_mode=="fp32"', {
-                        'defines': [
-                          '_MIPS_ARCH_MIPS32R2',
-                          'FPU_MODE_FP32',
-                        ],
-                        'cflags': ['-mfp32'],
-                      }],
-                      [ 'clang==0', {
-                        'cflags': ['-Wa,-mips32r2'],
-                      }],
-                    ],
-                    'cflags': ['-mips32r2'],
-                    'ldflags': ['-mips32r2'],
-                  }],
-                  ['mips_arch_variant=="r1"', {
-                    'cflags!': ['-mfp64', '-mfpxx'],
-                    'conditions': [
-                      [ 'clang==0', {
-                        'cflags': ['-Wa,-mips32'],
-                      }],
-                    ],
-                    'cflags': ['-mips32'],
-                    'ldflags': ['-mips32'],
-                  }],
-                  ['mips_arch_variant=="rx"', {
-                    'defines': [
-                      '_MIPS_ARCH_MIPS32RX',
-                      'FPU_MODE_FPXX',
-                    ],
-                    'cflags!': ['-mfp64', '-mfp32'],
-                    'conditions': [
-                      [ 'clang==0', {
-                        'cflags': ['-Wa,-mips32'],
-                      }],
-                    ],
-                    'cflags': ['-mips32', '-mfpxx'],
-                    'ldflags': ['-mips32'],
-                  }],
-                  ['mips_arch_variant=="loongson"', {
-                    'defines': [
-                      '_MIPS_ARCH_LOONGSON',
-                      'FPU_MODE_FP32',
-                    ],
-                    'cflags!': ['-mfp64', '-mfpxx'],
-                    'conditions': [
-                      [ 'clang==0', {
-                        'cflags': ['-Wa,-mips3'],
-                      }],
-                    ],
-                    'cflags': ['-mips3', '-mfp32'],
-                  }],
-                ],
-              }, {
-                # 'v8_target_arch!=target_arch'
-                # Target not built with an MIPS CXX compiler (simulator build).
-                'conditions': [
-                  ['mips_arch_variant=="r6"', {
-                    'defines': [
-                      '_MIPS_ARCH_MIPS32R6',
-                      'FPU_MODE_FP64',
-                    ],
-                  }],
-                  ['mips_arch_variant=="r2"', {
-                    'conditions': [
-                      [ 'mips_fpu_mode=="fp64"', {
-                        'defines': [
-                          '_MIPS_ARCH_MIPS32R2',
-                          'FPU_MODE_FP64',
-                        ],
-                      }],
-                      ['mips_fpu_mode=="fpxx"', {
-                        'defines': [
-                          '_MIPS_ARCH_MIPS32R2',
-                          'FPU_MODE_FPXX',
-                        ],
-                      }],
-                      ['mips_fpu_mode=="fp32"', {
-                        'defines': [
-                          '_MIPS_ARCH_MIPS32R2',
-                          'FPU_MODE_FP32',
-                        ],
-                      }],
-                    ],
-                  }],
-                  ['mips_arch_variant=="r1"', {
-                    'defines': [
-                      'FPU_MODE_FP32',
-                    ],
-                  }],
-                  ['mips_arch_variant=="rx"', {
-                    'defines': [
-                      '_MIPS_ARCH_MIPS32RX',
-                      'FPU_MODE_FPXX',
-                    ],
-                  }],
-                  ['mips_arch_variant=="loongson"', {
-                    'defines': [
-                      '_MIPS_ARCH_LOONGSON',
-                      'FPU_MODE_FP32',
-                    ],
-                  }],
-                ],
-              }],
-            ],
-          }], #_toolset=="target
-          ['_toolset=="host"', {
-            'conditions': [
-              ['mips_arch_variant=="rx"', {
-                'defines': [
-                  '_MIPS_ARCH_MIPS32RX',
-                  'FPU_MODE_FPXX',
-                ],
-              }],
-              ['mips_arch_variant=="r6"', {
-                'defines': [
-                  '_MIPS_ARCH_MIPS32R6',
-                  'FPU_MODE_FP64',
-                ],
-              }],
-              ['mips_arch_variant=="r2"', {
-                'conditions': [
-                  ['mips_fpu_mode=="fp64"', {
-                    'defines': [
-                      '_MIPS_ARCH_MIPS32R2',
-                      'FPU_MODE_FP64',
-                    ],
-                  }],
-                  ['mips_fpu_mode=="fpxx"', {
-                    'defines': [
-                      '_MIPS_ARCH_MIPS32R2',
-                      'FPU_MODE_FPXX',
-                    ],
-                  }],
-                  ['mips_fpu_mode=="fp32"', {
-                    'defines': [
-                      '_MIPS_ARCH_MIPS32R2',
-                      'FPU_MODE_FP32'
-                    ],
-                  }],
-                ],
-              }],
-              ['mips_arch_variant=="r1"', {
-                'defines': ['FPU_MODE_FP32',],
-              }],
-              ['mips_arch_variant=="loongson"', {
-                'defines': [
-                  '_MIPS_ARCH_LOONGSON',
-                  'FPU_MODE_FP32',
-                ],
-              }],
-            ]
-          }],
-        ],
-      }],  # v8_target_arch=="mipsel"
-      ['v8_target_arch=="mips64el" or v8_target_arch=="mips64"', {
-        'defines': [
-          'V8_TARGET_ARCH_MIPS64',
-        ],
-        'conditions': [
-          [ 'v8_can_use_fpu_instructions=="true"', {
-            'defines': [
-              'CAN_USE_FPU_INSTRUCTIONS',
-            ],
-          }],
-          [ 'v8_host_byteorder=="little"', {
-            'defines': [
-              'V8_TARGET_ARCH_MIPS64_LE',
-            ],
-          }],
-          [ 'v8_host_byteorder=="big"', {
-            'defines': [
-              'V8_TARGET_ARCH_MIPS64_BE',
-            ],
-          }],
-          [ 'v8_use_mips_abi_hardfloat=="true"', {
-            'defines': [
-              '__mips_hard_float=1',
-              'CAN_USE_FPU_INSTRUCTIONS',
-            ],
-          }, {
-            'defines': [
-              '__mips_soft_float=1'
-            ],
-          }],
-         ],
-        'target_conditions': [
-          ['_toolset=="target"', {
-            'conditions': [
-              ['v8_target_arch==target_arch', {
-                'cflags': [
-                  '-Wno-error=array-bounds',  # Workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56273
-                ],
-                'conditions': [
-                  ['v8_target_arch=="mips64el"', {
-                    'cflags': ['-EL'],
-                    'ldflags': ['-EL'],
-                  }],
-                  ['v8_target_arch=="mips64"', {
-                    'cflags': ['-EB'],
-                    'ldflags': ['-EB'],
-                  }],
-                  [ 'v8_use_mips_abi_hardfloat=="true"', {
-                    'cflags': ['-mhard-float'],
-                    'ldflags': ['-mhard-float'],
-                  }, {
-                    'cflags': ['-msoft-float'],
-                    'ldflags': ['-msoft-float'],
-                  }],
-                  ['mips_arch_variant=="r6"', {
-                    'defines': ['_MIPS_ARCH_MIPS64R6',],
-                    'conditions': [
-                      [ 'clang==0', {
-                        'cflags': ['-Wa,-mips64r6'],
-                      }],
-                    ],
-                    'cflags': ['-mips64r6', '-mabi=64'],
-                    'ldflags': ['-mips64r6', '-mabi=64'],
-                  }],
-                  ['mips_arch_variant=="r2"', {
-                    'defines': ['_MIPS_ARCH_MIPS64R2',],
-                    'conditions': [
-                      [ 'clang==0', {
-                        'cflags': ['-Wa,-mips64r2'],
-                      }],
-                    ],
-                    'cflags': ['-mips64r2', '-mabi=64'],
-                    'ldflags': ['-mips64r2', '-mabi=64'],
-                  }],
-                ],
-              }, {
-                # 'v8_target_arch!=target_arch'
-                # Target not built with an MIPS CXX compiler (simulator build).
-                'conditions': [
-                  ['mips_arch_variant=="r6"', {
-                    'defines': ['_MIPS_ARCH_MIPS64R6',],
-                  }],
-                  ['mips_arch_variant=="r2"', {
-                    'defines': ['_MIPS_ARCH_MIPS64R2',],
-                  }],
-                ],
-              }],
-            ],
-          }],  #'_toolset=="target"
-          ['_toolset=="host"', {
-            'conditions': [
-              ['mips_arch_variant=="r6"', {
-                'defines': ['_MIPS_ARCH_MIPS64R6',],
-              }],
-              ['mips_arch_variant=="r2"', {
-                'defines': ['_MIPS_ARCH_MIPS64R2',],
-              }],
-            ],
-          }],  #'_toolset=="host"
-        ],
-      }],  # v8_target_arch=="mips64el"
-      ['v8_target_arch=="x64"', {
-        'defines': [
-          'V8_TARGET_ARCH_X64',
-        ],
-        'xcode_settings': {
-          'ARCHS': [ 'x86_64' ],
-        },
-        'msvs_settings': {
-          'VCLinkerTool': {
-            'StackReserveSize': '2097152',
-          },
-        },
-        'msvs_configuration_platform': 'x64',
-      }],  # v8_target_arch=="x64"
-      ['v8_target_arch=="x32"', {
-        'defines': [
-          # x32 port shares the source code with x64 port.
-          'V8_TARGET_ARCH_X64',
-          'V8_TARGET_ARCH_32_BIT',
-        ],
-        'cflags': [
-          '-mx32',
-          # Inhibit warning if long long type is used.
-          '-Wno-long-long',
-        ],
-        'ldflags': [
-          '-mx32',
-        ],
-      }],  # v8_target_arch=="x32"
-      ['linux_use_gold_flags==1', {
-        # Newer gccs and clangs support -fuse-ld, use the flag to force gold
-        # selection.
-        # gcc -- http://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Optimize-Options.html
-        'ldflags': [ '-fuse-ld=gold', ],
-      }],
-      ['linux_use_bundled_binutils==1', {
-        'cflags': [
-          '-B<!(cd <(DEPTH) && pwd -P)/<(binutils_dir)',
-        ],
-      }],
-      ['linux_use_bundled_gold==1', {
-        # Put our binutils, which contains gold in the search path. We pass
-        # the path to gold to the compiler. gyp leaves unspecified what the
-        # cwd is when running the compiler, so the normal gyp path-munging
-        # fails us. This hack gets the right path.
-        'ldflags': [
-          '-B<!(cd <(DEPTH) && pwd -P)/<(binutils_dir)',
-        ],
-      }],
-      ['OS=="win"', {
-        'defines': [
-          'WIN32',
-        ],
-        # 4351: VS 2005 and later are warning us that they've fixed a bug
-        #       present in VS 2003 and earlier.
-        'msvs_disabled_warnings': [4351],
-        'msvs_configuration_attributes': {
-          'OutputDirectory': '<(DEPTH)\\build\\$(ConfigurationName)',
-          'IntermediateDirectory': '$(OutDir)\\obj\\$(ProjectName)',
-          'CharacterSet': '1',
-        },
-      }],
-      ['OS=="win" and v8_target_arch=="ia32"', {
-        'msvs_settings': {
-          'VCCLCompilerTool': {
-            # Ensure no surprising artifacts from 80bit double math with x86.
-            'AdditionalOptions': ['/arch:SSE2'],
-          },
-        },
-      }],
-      ['OS=="win" and v8_enable_prof==1', {
-        'msvs_settings': {
-          'VCLinkerTool': {
-            'GenerateMapFile': 'true',
-          },
-        },
-      }],
-      ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
-         or OS=="netbsd" or OS=="mac" or OS=="android" or OS=="qnx") and \
-        v8_target_arch=="ia32"', {
-        'cflags': [
-          '-msse2',
-          '-mfpmath=sse',
-          '-mmmx',  # Allows mmintrin.h for MMX intrinsics.
-        ],
-      }],
-      ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
-         or OS=="netbsd" or OS=="mac" or OS=="android" or OS=="qnx") and \
-        (v8_target_arch=="arm" or v8_target_arch=="ia32" or \
-         v8_target_arch=="x87" or v8_target_arch=="mips" or \
-         v8_target_arch=="mipsel" or v8_target_arch=="ppc" or \
-         v8_target_arch=="s390")', {
-        'target_conditions': [
-          ['_toolset=="host"', {
-            'conditions': [
-              ['host_cxx_is_biarch==1', {
-                'conditions': [
-                  ['host_arch=="s390" or host_arch=="s390x"', {
-                    'cflags': [ '-m31' ],
-                    'ldflags': [ '-m31' ]
-                  },{
-                   'cflags': [ '-m32' ],
-                   'ldflags': [ '-m32' ]
-                  }],
-                ],
-              }],
-            ],
-            'xcode_settings': {
-              'ARCHS': [ 'i386' ],
-            },
-          }],
-          ['_toolset=="target"', {
-            'conditions': [
-              ['target_cxx_is_biarch==1 and nacl_target_arch!="nacl_x64"', {
-                'conditions': [
-                  ['host_arch=="s390" or host_arch=="s390x"', {
-                    'cflags': [ '-m31' ],
-                    'ldflags': [ '-m31' ]
-                  },{
-                   'cflags': [ '-m32' ],
-                   'ldflags': [ '-m32' ],
-                  }],
-                ],
-              }],
-            ],
-            'xcode_settings': {
-              'ARCHS': [ 'i386' ],
-            },
-          }],
-        ],
-      }],
-      ['(OS=="linux" or OS=="android") and \
-        (v8_target_arch=="x64" or v8_target_arch=="arm64" or \
-         v8_target_arch=="ppc64" or v8_target_arch=="s390x")', {
-        'target_conditions': [
-          ['_toolset=="host"', {
-            'conditions': [
-              ['host_cxx_is_biarch==1', {
-                'cflags': [ '-m64' ],
-                'ldflags': [ '-m64' ]
-              }],
-             ],
-           }],
-           ['_toolset=="target"', {
-             'conditions': [
-               ['target_cxx_is_biarch==1', {
-                 'cflags': [ '-m64' ],
-                 'ldflags': [ '-m64' ],
-               }],
-             ]
-           }],
-         ],
-      }],
-      ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
-         or OS=="netbsd" or OS=="qnx" or OS=="aix"', {
-        'conditions': [
-          [ 'v8_no_strict_aliasing==1', {
-            'cflags': [ '-fno-strict-aliasing' ],
-          }],
-        ],  # conditions
-      }],
-      ['OS=="solaris"', {
-        'defines': [ '__C99FEATURES__=1' ],  # isinf() etc.
-      }],
-      ['OS=="freebsd" or OS=="openbsd"', {
-        'cflags': [ '-I/usr/local/include' ],
-      }],
-      ['OS=="netbsd"', {
-        'cflags': [ '-I/usr/pkg/include' ],
-      }],
-      ['OS=="aix"', {
-        'defines': [
-          # Support for malloc(0)
-          '_LINUX_SOURCE_COMPAT=1',
-          '_ALL_SOURCE=1'],
-        'conditions': [
-          [ 'v8_target_arch=="ppc"', {
-            'ldflags': [ '-Wl,-bmaxdata:0x60000000/dsa' ],
-          }],
-          [ 'v8_target_arch=="ppc64"', {
-            'cflags': [ '-maix64' ],
-            'ldflags': [ '-maix64' ],
-          }],
-        ],
-      }],
-    ],  # conditions
-    'configurations': {
-      # Abstract configuration for v8_optimized_debug == 0.
-      'DebugBase0': {
-        'abstract': 1,
-        'msvs_settings': {
-          'VCCLCompilerTool': {
-            'Optimization': '0',
-            'conditions': [
-              ['component=="shared_library"', {
-                'RuntimeLibrary': '3',  # /MDd
-              }, {
-                'RuntimeLibrary': '1',  # /MTd
-              }],
-            ],
-          },
-          'VCLinkerTool': {
-            'LinkIncremental': '2',
-          },
-        },
-        'variables': {
-          'v8_enable_slow_dchecks%': 1,
-        },
-        'conditions': [
-          ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" or \
-            OS=="qnx" or OS=="aix"', {
-            'cflags!': [
-              '-O3',
-              '-O2',
-              '-O1',
-              '-Os',
-            ],
-            'cflags': [
-              '-fdata-sections',
-              '-ffunction-sections',
-            ],
-          }],
-          ['OS=="mac"', {
-            'xcode_settings': {
-               'GCC_OPTIMIZATION_LEVEL': '0',  # -O0
-            },
-          }],
-          ['v8_enable_slow_dchecks==1', {
-            'defines': [
-              'ENABLE_SLOW_DCHECKS',
-            ],
-          }],
-        ],
-      },  # DebugBase0
-      # Abstract configuration for v8_optimized_debug == 1.
-      'DebugBase1': {
-        'abstract': 1,
-        'msvs_settings': {
-          'VCCLCompilerTool': {
-            'Optimization': '2',
-            'InlineFunctionExpansion': '2',
-            'EnableIntrinsicFunctions': 'true',
-            'FavorSizeOrSpeed': '0',
-            'StringPooling': 'true',
-            'BasicRuntimeChecks': '0',
-            'conditions': [
-              ['component=="shared_library"', {
-                'RuntimeLibrary': '3',  #/MDd
-              }, {
-                'RuntimeLibrary': '1',  #/MTd
-              }],
-            ],
-          },
-          'VCLinkerTool': {
-            'LinkIncremental': '1',
-            'OptimizeReferences': '2',
-            'EnableCOMDATFolding': '2',
-          },
-        },
-        'variables': {
-          'v8_enable_slow_dchecks%': 0,
-        },
-        'conditions': [
-          ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" or \
-            OS=="qnx" or OS=="aix"', {
-            'cflags!': [
-              '-O0',
-              '-O1',
-              '-Os',
-            ],
-            'cflags': [
-              '-fdata-sections',
-              '-ffunction-sections',
-            ],
-            'conditions': [
-              # TODO(crbug.com/272548): Avoid -O3 in NaCl
-              # Don't use -O3 with sanitizers.
-              ['nacl_target_arch=="none" and asan==0 and msan==0 and lsan==0 \
-                and tsan==0 and ubsan==0 and ubsan_vptr==0', {
-                'cflags': ['-O3'],
-                'cflags!': ['-O2'],
-                }, {
-                'cflags': ['-O2'],
-                'cflags!': ['-O3'],
-              }],
-            ],
-          }],
-          ['OS=="mac"', {
-            'xcode_settings': {
-              'GCC_OPTIMIZATION_LEVEL': '3',  # -O3
-              'GCC_STRICT_ALIASING': 'YES',
-            },
-          }],
-          ['v8_enable_slow_dchecks==1', {
-            'defines': [
-              'ENABLE_SLOW_DCHECKS',
-            ],
-          }],
-        ],
-      },  # DebugBase1
-      # Common settings for the Debug configuration.
-      'DebugBaseCommon': {
-        'abstract': 1,
-        'defines': [
-          'ENABLE_DISASSEMBLER',
-          'V8_ENABLE_CHECKS',
-          'OBJECT_PRINT',
-          'VERIFY_HEAP',
-          'DEBUG',
-          'TRACE_MAPS'
-        ],
-        'conditions': [
-          ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" or \
-            OS=="qnx" or OS=="aix"', {
-            'cflags': [ '-Woverloaded-virtual', '<(wno_array_bounds)', ],
-          }],
-          ['OS=="linux" and v8_enable_backtrace==1', {
-            # Support for backtrace_symbols.
-            'ldflags': [ '-rdynamic' ],
-          }],
-          ['OS=="linux" and disable_glibcxx_debug==0', {
-            # Enable libstdc++ debugging facilities to help catch problems
-            # early, see http://crbug.com/65151 .
-            'defines': ['_GLIBCXX_DEBUG=1',],
-          }],
-          ['OS=="aix"', {
-            'ldflags': [ '-Wl,-bbigtoc' ],
-            'conditions': [
-              ['v8_target_arch=="ppc64"', {
-                'cflags': [ '-maix64 -mcmodel=large' ],
-              }],
-            ],
-          }],
-          ['OS=="android"', {
-            'variables': {
-              'android_full_debug%': 1,
-            },
-            'conditions': [
-              ['android_full_debug==0', {
-                # Disable full debug if we want a faster v8 in a debug build.
-                # TODO(2304): pass DISABLE_DEBUG_ASSERT instead of hiding DEBUG.
-                'defines!': [
-                  'DEBUG',
-                  'ENABLE_SLOW_DCHECKS',
-                ],
-              }],
-            ],
-          }],
-          # TODO(pcc): Re-enable in LTO builds once we've fixed the intermittent
-          # link failures (crbug.com/513074).
-          ['linux_use_gold_flags==1 and use_lto==0', {
-            'target_conditions': [
-              ['_toolset=="target"', {
-                'ldflags': [
-                  # Experimentation found that using four linking threads
-                  # saved ~20% of link time.
-                  # https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/281527606915bb36
-                  # Only apply this to the target linker, since the host
-                  # linker might not be gold, but isn't used much anyway.
-                  '-Wl,--threads',
-                  '-Wl,--thread-count=4',
-                ],
-              }],
-            ],
-          }],
-        ],
-      },  # DebugBaseCommon
-      'Debug': {
-        'inherit_from': ['DebugBaseCommon'],
-        'conditions': [
-          ['v8_optimized_debug==0', {
-            'inherit_from': ['DebugBase0'],
-          }, {
-            'inherit_from': ['DebugBase1'],
-          }],
-        ],
-      },  # Debug
-      'ReleaseBase': {
-        'abstract': 1,
-        'variables': {
-          'v8_enable_slow_dchecks%': 0,
-        },
-        'conditions': [
-          ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" \
-            or OS=="aix"', {
-            'cflags!': [
-              '-Os',
-            ],
-            'cflags': [
-              '-fdata-sections',
-              '-ffunction-sections',
-              '<(wno_array_bounds)',
-            ],
-            'conditions': [
-              # TODO(crbug.com/272548): Avoid -O3 in NaCl
-              # Don't use -O3 with sanitizers.
-              ['nacl_target_arch=="none" and asan==0 and msan==0 and lsan==0 \
-                and tsan==0 and ubsan==0 and ubsan_vptr==0', {
-                'cflags': ['-O3'],
-                'cflags!': ['-O2'],
-              }, {
-                'cflags': ['-O2'],
-                'cflags!': ['-O3'],
-              }],
-            ],
-          }],
-          ['OS=="android"', {
-            'cflags!': [
-              '-O3',
-              '-Os',
-            ],
-            'cflags': [
-              '-fdata-sections',
-              '-ffunction-sections',
-              '-O2',
-            ],
-          }],
-          ['OS=="mac"', {
-            'xcode_settings': {
-              'GCC_OPTIMIZATION_LEVEL': '3',  # -O3
-
-              # -fstrict-aliasing.  Mainline gcc
-              # enables this at -O2 and above,
-              # but Apple gcc does not unless it
-              # is specified explicitly.
-              'GCC_STRICT_ALIASING': 'YES',
-            },
-          }],  # OS=="mac"
-          ['OS=="win"', {
-            'msvs_settings': {
-              'VCCLCompilerTool': {
-                'Optimization': '2',
-                'InlineFunctionExpansion': '2',
-                'EnableIntrinsicFunctions': 'true',
-                'FavorSizeOrSpeed': '0',
-                'StringPooling': 'true',
-                'conditions': [
-                  ['component=="shared_library"', {
-                    'RuntimeLibrary': '2',  #/MD
-                  }, {
-                    'RuntimeLibrary': '0',  #/MT
-                  }],
-                ],
-              },
-              'VCLinkerTool': {
-                'LinkIncremental': '1',
-                'OptimizeReferences': '2',
-                'EnableCOMDATFolding': '2',
-              },
-            },
-          }],  # OS=="win"
-          ['v8_enable_slow_dchecks==1', {
-            'defines': [
-              'ENABLE_SLOW_DCHECKS',
-            ],
-          }],
-        ],  # conditions
-      },  # Release
-      'Release': {
-        'inherit_from': ['ReleaseBase'],
-      },  # Debug
-      'conditions': [
-        [ 'OS=="win"', {
-          # TODO(bradnelson): add a gyp mechanism to make this more graceful.
-          'Debug_x64': {
-            'inherit_from': ['DebugBaseCommon'],
-            'conditions': [
-              ['v8_optimized_debug==0', {
-                'inherit_from': ['DebugBase0'],
-              }, {
-                'inherit_from': ['DebugBase1'],
-              }],
-            ],
-          },
-          'Release_x64': {
-            'inherit_from': ['ReleaseBase'],
-          },
-        }],
-      ],
-    },  # configurations
-  },  # target_defaults
-}
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py
old mode 100644
new mode 100755
index 95fbcf4..ddff24a
--- a/build/vs_toolchain.py
+++ b/build/vs_toolchain.py
@@ -1,42 +1,44 @@
 #!/usr/bin/env python
-# Copyright 2015 the V8 project authors. All rights reserved.
 # Copyright 2014 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import glob
 import json
 import os
 import pipes
 import shutil
 import subprocess
 import sys
-import vs_toolchain
 
 
 script_dir = os.path.dirname(os.path.realpath(__file__))
 chrome_src = os.path.abspath(os.path.join(script_dir, os.pardir))
 SRC_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-sys.path.insert(1, os.path.join(chrome_src, 'tools'))
-sys.path.insert(0, os.path.join(chrome_src, 'build', 'gyp', 'pylib'))
+sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib'))
 json_data_file = os.path.join(script_dir, 'win_toolchain.json')
 
 
 import gyp
 
 
+# Use MSVS2015 as the default toolchain.
+CURRENT_DEFAULT_TOOLCHAIN_VERSION = '2015'
+
+
 def SetEnvironmentAndGetRuntimeDllDirs():
   """Sets up os.environ to use the depot_tools VS toolchain with gyp, and
   returns the location of the VS runtime DLLs so they can be copied into
   the output directory after gyp generation.
   """
-  vs2013_runtime_dll_dirs = None
+  vs_runtime_dll_dirs = None
   depot_tools_win_toolchain = \
       bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
   # When running on a non-Windows host, only do this if the SDK has explicitly
   # been downloaded before (in which case json_data_file will exist).
   if ((sys.platform in ('win32', 'cygwin') or os.path.exists(json_data_file))
       and depot_tools_win_toolchain):
-    if not os.path.exists(json_data_file):
+    if ShouldUpdateToolchain():
       Update()
     with open(json_data_file, 'r') as tempf:
       toolchain_data = json.load(tempf)
@@ -50,7 +52,7 @@
     # TODO(scottmg): The order unfortunately matters in these. They should be
     # split into separate keys for x86 and x64. (See CopyVsRuntimeDlls call
     # below). http://crbug.com/345992
-    vs2013_runtime_dll_dirs = toolchain_data['runtime_dirs']
+    vs_runtime_dll_dirs = toolchain_data['runtime_dirs']
 
     os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain
     os.environ['GYP_MSVS_VERSION'] = version
@@ -65,30 +67,102 @@
     os.environ['WINDOWSSDKDIR'] = win_sdk
     os.environ['WDK_DIR'] = wdk
     # Include the VS runtime in the PATH in case it's not machine-installed.
-    runtime_path = ';'.join(vs2013_runtime_dll_dirs)
-    os.environ['PATH'] = runtime_path + ';' + os.environ['PATH']
-  return vs2013_runtime_dll_dirs
+    runtime_path = os.path.pathsep.join(vs_runtime_dll_dirs)
+    os.environ['PATH'] = runtime_path + os.path.pathsep + os.environ['PATH']
+  elif sys.platform == 'win32' and not depot_tools_win_toolchain:
+    if not 'GYP_MSVS_OVERRIDE_PATH' in os.environ:
+      os.environ['GYP_MSVS_OVERRIDE_PATH'] = DetectVisualStudioPath()
+    if not 'GYP_MSVS_VERSION' in os.environ:
+      os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion()
+
+  return vs_runtime_dll_dirs
+
+
+def _RegistryGetValueUsingWinReg(key, value):
+  """Use the _winreg module to obtain the value of a registry key.
+
+  Args:
+    key: The registry key.
+    value: The particular registry value to read.
+  Return:
+    contents of the registry key's value, or None on failure.  Throws
+    ImportError if _winreg is unavailable.
+  """
+  import _winreg
+  try:
+    root, subkey = key.split('\\', 1)
+    assert root == 'HKLM'  # Only need HKLM for now.
+    with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, subkey) as hkey:
+      return _winreg.QueryValueEx(hkey, value)[0]
+  except WindowsError:
+    return None
+
+
+def _RegistryGetValue(key, value):
+  try:
+    return _RegistryGetValueUsingWinReg(key, value)
+  except ImportError:
+    raise Exception('The python library _winreg not found.')
+
+
+def GetVisualStudioVersion():
+  """Return GYP_MSVS_VERSION of Visual Studio.
+  """
+  return os.environ.get('GYP_MSVS_VERSION', CURRENT_DEFAULT_TOOLCHAIN_VERSION)
+
+
+def DetectVisualStudioPath():
+  """Return path to the GYP_MSVS_VERSION of Visual Studio.
+  """
+
+  # Note that this code is used from
+  # build/toolchain/win/setup_toolchain.py as well.
+  version_as_year = GetVisualStudioVersion()
+  year_to_version = {
+      '2013': '12.0',
+      '2015': '14.0',
+  }
+  if version_as_year not in year_to_version:
+    raise Exception(('Visual Studio version %s (from GYP_MSVS_VERSION)'
+                     ' not supported. Supported versions are: %s') % (
+                       version_as_year, ', '.join(year_to_version.keys())))
+  version = year_to_version[version_as_year]
+  keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version,
+          r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version]
+  for key in keys:
+    path = _RegistryGetValue(key, 'InstallDir')
+    if not path:
+      continue
+    path = os.path.normpath(os.path.join(path, '..', '..'))
+    return path
+
+  raise Exception(('Visual Studio Version %s (from GYP_MSVS_VERSION)'
+                   ' not found.') % (version_as_year))
 
 
 def _VersionNumber():
   """Gets the standard version number ('120', '140', etc.) based on
   GYP_MSVS_VERSION."""
-  if os.environ['GYP_MSVS_VERSION'] == '2013':
+  vs_version = GetVisualStudioVersion()
+  if vs_version == '2013':
     return '120'
-  elif os.environ['GYP_MSVS_VERSION'] == '2015':
+  elif vs_version == '2015':
     return '140'
   else:
     raise ValueError('Unexpected GYP_MSVS_VERSION')
 
 
-def _CopyRuntimeImpl(target, source):
-  """Copy |source| to |target| if it doesn't already exist or if it
-  needs to be updated.
+def _CopyRuntimeImpl(target, source, verbose=True):
+  """Copy |source| to |target| if it doesn't already exist or if it needs to be
+  updated (comparing last modified time as an approximate float match as for
+  some reason the values tend to differ by ~1e-07 despite being copies of the
+  same file... https://crbug.com/603603).
   """
   if (os.path.isdir(os.path.dirname(target)) and
       (not os.path.isfile(target) or
-      os.stat(target).st_mtime != os.stat(source).st_mtime)):
-    print 'Copying %s to %s...' % (source, target)
+       abs(os.stat(target).st_mtime - os.stat(source).st_mtime) >= 0.01)):
+    if verbose:
+      print 'Copying %s to %s...' % (source, target)
     if os.path.exists(target):
       os.unlink(target)
     shutil.copy2(source, target)
@@ -104,14 +178,49 @@
     _CopyRuntimeImpl(target, source)
 
 
-def _CopyRuntime2015(target_dir, source_dir, dll_pattern):
+def _CopyRuntime2015(target_dir, source_dir, dll_pattern, suffix):
   """Copy both the msvcp and vccorlib runtime DLLs, only if the target doesn't
   exist, but the target directory does exist."""
-  for file_part in ('msvcp', 'vccorlib'):
+  for file_part in ('msvcp', 'vccorlib', 'vcruntime'):
     dll = dll_pattern % file_part
     target = os.path.join(target_dir, dll)
     source = os.path.join(source_dir, dll)
     _CopyRuntimeImpl(target, source)
+  ucrt_src_dir = os.path.join(source_dir, 'api-ms-win-*.dll')
+  for ucrt_src_file in glob.glob(ucrt_src_dir):
+    file_part = os.path.basename(ucrt_src_file)
+    ucrt_dst_file = os.path.join(target_dir, file_part)
+    _CopyRuntimeImpl(ucrt_dst_file, ucrt_src_file, False)
+  _CopyRuntimeImpl(os.path.join(target_dir, 'ucrtbase' + suffix),
+                    os.path.join(source_dir, 'ucrtbase' + suffix))
+
+
+def _CopyRuntime(target_dir, source_dir, target_cpu, debug):
+  """Copy the VS runtime DLLs, only if the target doesn't exist, but the target
+  directory does exist. Handles VS 2013 and VS 2015."""
+  suffix = "d.dll" if debug else ".dll"
+  if GetVisualStudioVersion() == '2015':
+    _CopyRuntime2015(target_dir, source_dir, '%s140' + suffix, suffix)
+  else:
+    _CopyRuntime2013(target_dir, source_dir, 'msvc%s120' + suffix)
+
+  # Copy the PGO runtime library to the release directories.
+  if not debug and os.environ.get('GYP_MSVS_OVERRIDE_PATH'):
+    pgo_x86_runtime_dir = os.path.join(os.environ.get('GYP_MSVS_OVERRIDE_PATH'),
+                                        'VC', 'bin')
+    pgo_x64_runtime_dir = os.path.join(pgo_x86_runtime_dir, 'amd64')
+    pgo_runtime_dll = 'pgort' + _VersionNumber() + '.dll'
+    if target_cpu == "x86":
+      source_x86 = os.path.join(pgo_x86_runtime_dir, pgo_runtime_dll)
+      if os.path.exists(source_x86):
+        _CopyRuntimeImpl(os.path.join(target_dir, pgo_runtime_dll), source_x86)
+    elif target_cpu == "x64":
+      source_x64 = os.path.join(pgo_x64_runtime_dir, pgo_runtime_dll)
+      if os.path.exists(source_x64):
+        _CopyRuntimeImpl(os.path.join(target_dir, pgo_runtime_dll),
+                          source_x64)
+    else:
+      raise NotImplementedError("Unexpected target_cpu value:" + target_cpu)
 
 
 def CopyVsRuntimeDlls(output_dir, runtime_dirs):
@@ -121,6 +230,8 @@
 
   This needs to be run after gyp has been run so that the expected target
   output directories are already created.
+
+  This is used for the GYP build and gclient runhooks.
   """
   x86, x64 = runtime_dirs
   out_debug = os.path.join(output_dir, 'Debug')
@@ -134,35 +245,12 @@
     os.makedirs(out_debug_nacl64)
   if os.path.exists(out_release) and not os.path.exists(out_release_nacl64):
     os.makedirs(out_release_nacl64)
-  if os.environ.get('GYP_MSVS_VERSION') == '2015':
-    _CopyRuntime2015(out_debug,          x86, '%s140d.dll')
-    _CopyRuntime2015(out_release,        x86, '%s140.dll')
-    _CopyRuntime2015(out_debug_x64,      x64, '%s140d.dll')
-    _CopyRuntime2015(out_release_x64,    x64, '%s140.dll')
-    _CopyRuntime2015(out_debug_nacl64,   x64, '%s140d.dll')
-    _CopyRuntime2015(out_release_nacl64, x64, '%s140.dll')
-  else:
-    # VS2013 is the default.
-    _CopyRuntime2013(out_debug,          x86, 'msvc%s120d.dll')
-    _CopyRuntime2013(out_release,        x86, 'msvc%s120.dll')
-    _CopyRuntime2013(out_debug_x64,      x64, 'msvc%s120d.dll')
-    _CopyRuntime2013(out_release_x64,    x64, 'msvc%s120.dll')
-    _CopyRuntime2013(out_debug_nacl64,   x64, 'msvc%s120d.dll')
-    _CopyRuntime2013(out_release_nacl64, x64, 'msvc%s120.dll')
-
-  # Copy the PGO runtime library to the release directories.
-  if os.environ.get('GYP_MSVS_OVERRIDE_PATH'):
-    pgo_x86_runtime_dir = os.path.join(os.environ.get('GYP_MSVS_OVERRIDE_PATH'),
-                                       'VC', 'bin')
-    pgo_x64_runtime_dir = os.path.join(pgo_x86_runtime_dir, 'amd64')
-    pgo_runtime_dll = 'pgort' + _VersionNumber() + '.dll'
-    source_x86 = os.path.join(pgo_x86_runtime_dir, pgo_runtime_dll)
-    if os.path.exists(source_x86):
-      _CopyRuntimeImpl(os.path.join(out_release, pgo_runtime_dll), source_x86)
-    source_x64 = os.path.join(pgo_x64_runtime_dir, pgo_runtime_dll)
-    if os.path.exists(source_x64):
-      _CopyRuntimeImpl(os.path.join(out_release_x64, pgo_runtime_dll),
-                       source_x64)
+  _CopyRuntime(out_debug,          x86, "x86", debug=True)
+  _CopyRuntime(out_release,        x86, "x86", debug=False)
+  _CopyRuntime(out_debug_x64,      x64, "x64", debug=True)
+  _CopyRuntime(out_release_x64,    x64, "x64", debug=False)
+  _CopyRuntime(out_debug_nacl64,   x64, "x64", debug=True)
+  _CopyRuntime(out_release_nacl64, x64, "x64", debug=False)
 
 
 def CopyDlls(target_dir, configuration, target_cpu):
@@ -173,28 +261,45 @@
 
   The debug configuration gets both the debug and release DLLs; the
   release config only the latter.
+
+  This is used for the GN build.
   """
-  vs2013_runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs()
-  if not vs2013_runtime_dll_dirs:
+  vs_runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs()
+  if not vs_runtime_dll_dirs:
     return
 
-  x64_runtime, x86_runtime = vs2013_runtime_dll_dirs
+  x64_runtime, x86_runtime = vs_runtime_dll_dirs
   runtime_dir = x64_runtime if target_cpu == 'x64' else x86_runtime
-  _CopyRuntime2013(
-      target_dir, runtime_dir, 'msvc%s' + _VersionNumber() + '.dll')
+  _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=False)
   if configuration == 'Debug':
-    _CopyRuntime2013(
-        target_dir, runtime_dir, 'msvc%s' + _VersionNumber() + 'd.dll')
+    _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=True)
 
 
 def _GetDesiredVsToolchainHashes():
   """Load a list of SHA1s corresponding to the toolchains that we want installed
   to build with."""
-  if os.environ.get('GYP_MSVS_VERSION') == '2015':
-    return ['5a85cf1ce842f7cc96b9d17039a445a9dc9cf0dd']
+  if GetVisualStudioVersion() == '2015':
+    if bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN_PRERELEASE', '0'))):
+      # Update 3 pre-release, May 16th.
+      return ['283cc362f57dbe240e0d21f48ae45f9d834a425a']
+    else:
+      # Update 2.
+      return ['95ddda401ec5678f15eeed01d2bee08fcbc5ee97']
   else:
-    # Default to VS2013.
-    return ['9ff97c632ae1fee0c98bcd53e71770eb3a0d8deb']
+    return ['03a4e939cd325d6bc5216af41b92d02dda1366a6']
+
+
+def ShouldUpdateToolchain():
+  """Check if the toolchain should be upgraded."""
+  if not os.path.exists(json_data_file):
+    return True
+  with open(json_data_file, 'r') as tempf:
+    toolchain_data = json.load(tempf)
+  version = toolchain_data['version']
+  env_version = GetVisualStudioVersion()
+  # If there's a mismatch between the version set in the environment and the one
+  # in the json file then the toolchain should be updated.
+  return version != env_version
 
 
 def Update(force=False):
@@ -214,6 +319,9 @@
         depot_tools_win_toolchain):
     import find_depot_tools
     depot_tools_path = find_depot_tools.add_depot_tools_to_path()
+    # Necessary so that get_toolchain_if_necessary.py will put the VS toolkit
+    # in the correct directory.
+    os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion()
     get_toolchain_args = [
         sys.executable,
         os.path.join(depot_tools_path,
@@ -228,6 +336,12 @@
   return 0
 
 
+def NormalizePath(path):
+  while path.endswith("\\"):
+    path = path[:-1]
+  return path
+
+
 def GetToolchainDir():
   """Gets location information about the current toolchain (must have been
   previously updated by 'update'). This is used for the GN build."""
@@ -235,7 +349,7 @@
 
   # If WINDOWSSDKDIR is not set, search the default SDK path and set it.
   if not 'WINDOWSSDKDIR' in os.environ:
-    default_sdk_path = 'C:\\Program Files (x86)\\Windows Kits\\8.1'
+    default_sdk_path = 'C:\\Program Files (x86)\\Windows Kits\\10'
     if os.path.isdir(default_sdk_path):
       os.environ['WINDOWSSDKDIR'] = default_sdk_path
 
@@ -245,11 +359,11 @@
 wdk_dir = "%s"
 runtime_dirs = "%s"
 ''' % (
-      os.environ['GYP_MSVS_OVERRIDE_PATH'],
-      os.environ['WINDOWSSDKDIR'],
-      os.environ['GYP_MSVS_VERSION'],
-      os.environ.get('WDK_DIR', ''),
-      ';'.join(runtime_dll_dirs or ['None']))
+      NormalizePath(os.environ['GYP_MSVS_OVERRIDE_PATH']),
+      NormalizePath(os.environ['WINDOWSSDKDIR']),
+      GetVisualStudioVersion(),
+      NormalizePath(os.environ.get('WDK_DIR', '')),
+      os.path.pathsep.join(runtime_dll_dirs or ['None']))
 
 
 def main():
diff --git a/build_overrides/gtest.gni b/build_overrides/gtest.gni
new file mode 100644
index 0000000..5d22f01
--- /dev/null
+++ b/build_overrides/gtest.gni
@@ -0,0 +1,15 @@
+# Copyright 2016 The V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Exclude support for registering main function in multi-process tests.
+gtest_include_multiprocess = false
+
+# Exclude support for platform-specific operations across unit tests.
+gtest_include_platform_test = true
+
+# Exclude support for testing Objective C code on OS X and iOS.
+gtest_include_objc_support = true
+
+# Exclude support for flushing coverage files on iOS.
+gtest_include_ios_coverage = true
diff --git a/build_overrides/v8.gni b/build_overrides/v8.gni
new file mode 100644
index 0000000..5dcd672
--- /dev/null
+++ b/build_overrides/v8.gni
@@ -0,0 +1,26 @@
+# Copyright 2015 The V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/features.gni")
+import("//build/config/ui.gni")
+import("//build/config/v8_target_cpu.gni")
+import("//gni/v8.gni")
+
+if (is_android) {
+  import("//build/config/android/config.gni")
+}
+
+if (((v8_target_cpu == "x86" ||
+      v8_target_cpu == "x64" ||
+      v8_target_cpu=="x87") &&
+     (is_linux || is_mac)) ||
+    (v8_target_cpu == "ppc64" && is_linux)) {
+  v8_enable_gdbjit = true
+}
+
+v8_imminent_deprecation_warnings = true
+
+# Add simple extras solely for the purpose of the cctests.
+v8_extra_library_files = [ "//test/cctest/test-extra.js" ]
+v8_experimental_extra_library_files = [ "//test/cctest/test-experimental-extra.js" ]
diff --git a/gni/isolate.gni b/gni/isolate.gni
new file mode 100644
index 0000000..e6d166c
--- /dev/null
+++ b/gni/isolate.gni
@@ -0,0 +1,171 @@
+# Copyright 2016 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/sanitizers/sanitizers.gni")
+import("//third_party/icu/config.gni")
+import("v8.gni")
+
+declare_args() {
+  # Sets the test isolation mode (noop|prepare|check).
+  v8_test_isolation_mode = "noop"
+}
+
+template("v8_isolate_run") {
+  # Remember target name as within the action scope the target name will be
+  # different.
+  name = target_name
+  if (name != "" && invoker.isolate != "" && invoker.deps != [] &&
+      v8_test_isolation_mode != "noop") {
+    action(name + "_run") {
+      testonly = true
+
+      deps = invoker.deps
+
+      script = "//tools/isolate_driver.py"
+
+      sources = [
+        invoker.isolate,
+      ]
+
+      inputs = [
+        # Files that are known to be involved in this step.
+        "//tools/swarming_client/isolate.py",
+        "//tools/swarming_client/run_isolated.py",
+      ]
+
+      if (v8_test_isolation_mode == "prepare") {
+        outputs = [
+          "$root_out_dir/$name.isolated.gen.json",
+        ]
+      } else if (v8_test_isolation_mode == "check") {
+        outputs = [
+          "$root_out_dir/$name.isolated",
+          "$root_out_dir/$name.isolated.state",
+        ]
+      }
+
+      # Translate gn to gyp variables.
+      if (is_asan) {
+        asan = "1"
+      } else {
+        asan = "0"
+      }
+      if (is_msan) {
+        msan = "1"
+      } else {
+        msan = "0"
+      }
+      if (is_tsan) {
+        tsan = "1"
+      } else {
+        tsan = "0"
+      }
+      if (is_cfi) {
+        cfi_vptr = "1"
+      } else {
+        cfi_vptr = "0"
+      }
+      if (use_custom_libcxx) {
+        custom_libcxx = "1"
+      } else {
+        custom_libcxx = "0"
+      }
+      if (target_cpu == "x86") {
+        target_arch = "ia32"
+      } else {
+        target_arch = target_cpu
+      }
+      if (is_debug) {
+        configuration_name = "Debug"
+      } else {
+        configuration_name = "Release"
+      }
+      if (is_component_build) {
+        component = "shared_library"
+      } else {
+        component = "static_library"
+      }
+      if (icu_use_data_file) {
+        icu_use_data_file_flag = "1"
+      } else {
+        icu_use_data_file_flag = "0"
+      }
+      if (v8_use_external_startup_data) {
+        use_external_startup_data = "1"
+      } else {
+        use_external_startup_data = "0"
+      }
+      if (v8_use_snapshot) {
+        use_snapshot = "true"
+      } else {
+        use_snapshot = "false"
+      }
+
+      # Note, all paths will be rebased in isolate_driver.py to be relative to
+      # the isolate file.
+      args = [
+        v8_test_isolation_mode,
+        "--isolated",
+        rebase_path("$root_out_dir/$name.isolated", root_build_dir),
+        "--isolate",
+        rebase_path(invoker.isolate, root_build_dir),
+
+        # Path variables are used to replace file paths when loading a .isolate
+        # file
+        "--path-variable",
+        "DEPTH",
+        rebase_path("//", root_build_dir),
+        "--path-variable",
+        "PRODUCT_DIR",
+        rebase_path(root_out_dir, root_build_dir),
+
+        # TODO(machenbach): Set variables for remaining features.
+        "--config-variable",
+        "CONFIGURATION_NAME=$configuration_name",
+        "--config-variable",
+        "OS=$target_os",
+        "--config-variable",
+        "asan=$asan",
+        "--config-variable",
+        "cfi_vptr=$cfi_vptr",
+        "--config-variable",
+        "gcmole=0",
+        "--config-variable",
+        "has_valgrind=0",
+        "--config-variable",
+        "icu_use_data_file_flag=$icu_use_data_file_flag",
+        "--config-variable",
+        "msan=$msan",
+        "--config-variable",
+        "tsan=$tsan",
+        "--config-variable",
+        "coverage=0",
+        "--config-variable",
+        "sanitizer_coverage=0",
+        "--config-variable",
+        "component=$component",
+        "--config-variable",
+        "target_arch=$target_arch",
+        "--config-variable",
+        "use_custom_libcxx=$custom_libcxx",
+        "--config-variable",
+        "v8_use_external_startup_data=$use_external_startup_data",
+        "--config-variable",
+        "v8_use_snapshot=$use_snapshot",
+      ]
+
+      if (is_win) {
+        args += [
+          "--config-variable",
+          "msvs_version=2013",
+        ]
+      } else {
+        args += [
+          "--config-variable",
+          "msvs_version=0",
+        ]
+      }
+    }
+  }
+}
diff --git a/gni/v8.gni b/gni/v8.gni
new file mode 100644
index 0000000..24f6567
--- /dev/null
+++ b/gni/v8.gni
@@ -0,0 +1,79 @@
+# Copyright 2016 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/v8_target_cpu.gni")
+import("//build/config/sanitizers/sanitizers.gni")
+
+declare_args() {
+  # Turns on compiler optimizations in V8 in Debug build.
+  v8_optimized_debug = true
+
+  # Enable the snapshot feature, for fast context creation.
+  # http://v8project.blogspot.com/2015/09/custom-startup-snapshots.html
+  v8_use_snapshot = true
+
+  # Use external files for startup data blobs:
+  # the JS builtins sources and the start snapshot.
+  v8_use_external_startup_data = !is_ios
+}
+
+###############################################################################
+# Templates
+#
+
+# Points to // in v8 stand-alone or to //v8/ in chromium. We need absolute
+# paths for all configs in templates as they are shared in different
+# subdirectories.
+path_prefix = get_path_info("../", "abspath")
+
+# Common configs to remove or add in all v8 targets.
+remove_configs = [ "//build/config/compiler:chromium_code" ]
+add_configs = [
+  "//build/config/compiler:no_chromium_code",
+  path_prefix + ":features",
+  path_prefix + ":toolchain",
+]
+
+if (is_debug && !v8_optimized_debug) {
+  remove_configs += [ "//build/config/compiler:default_optimization" ]
+  add_configs += [ "//build/config/compiler:no_optimize" ]
+} else {
+  remove_configs += [ "//build/config/compiler:default_optimization" ]
+
+  # TODO(crbug.com/621335) Rework this so that we don't have the confusion
+  # between "optimize_speed" and "optimize_max".
+  if (is_posix && !is_android && !is_nacl && !using_sanitizer) {
+    add_configs += [ "//build/config/compiler:optimize_speed" ]
+  } else {
+    add_configs += [ "//build/config/compiler:optimize_max" ]
+  }
+}
+
+# All templates should be kept in sync.
+template("v8_source_set") {
+  source_set(target_name) {
+    forward_variables_from(invoker, "*", [ "configs" ])
+    configs += invoker.configs
+    configs -= remove_configs
+    configs += add_configs
+  }
+}
+
+template("v8_executable") {
+  executable(target_name) {
+    forward_variables_from(invoker, "*", [ "configs" ])
+    configs += invoker.configs
+    configs -= remove_configs
+    configs += add_configs
+  }
+}
+
+template("v8_component") {
+  component(target_name) {
+    forward_variables_from(invoker, "*", [ "configs" ])
+    configs += invoker.configs
+    configs -= remove_configs
+    configs += add_configs
+  }
+}
diff --git a/gypfiles/OWNERS b/gypfiles/OWNERS
new file mode 100644
index 0000000..0e56af3
--- /dev/null
+++ b/gypfiles/OWNERS
@@ -0,0 +1 @@
+machenbach@chromium.org
diff --git a/build/README.txt b/gypfiles/README.txt
similarity index 100%
rename from build/README.txt
rename to gypfiles/README.txt
diff --git a/gypfiles/all.gyp b/gypfiles/all.gyp
new file mode 100644
index 0000000..ff1bea4
--- /dev/null
+++ b/gypfiles/all.gyp
@@ -0,0 +1,54 @@
+# Copyright 2011 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'targets': [
+    {
+      'target_name': 'All',
+      'type': 'none',
+      'dependencies': [
+        '../src/d8.gyp:d8',
+      ],
+      'conditions': [
+        ['component!="shared_library"', {
+          'dependencies': [
+            '../tools/parser-shell.gyp:parser-shell',
+          ],
+        }],
+        # These items don't compile for Android on Mac.
+        ['host_os!="mac" or OS!="android"', {
+          'dependencies': [
+            '../samples/samples.gyp:*',
+            '../test/cctest/cctest.gyp:*',
+            '../test/fuzzer/fuzzer.gyp:*',
+            '../test/unittests/unittests.gyp:*',
+            ],
+        }],
+        ['test_isolation_mode != "noop"', {
+          'dependencies': [
+            '../test/bot_default.gyp:*',
+            '../test/benchmarks/benchmarks.gyp:*',
+            '../test/default.gyp:*',
+            '../test/ignition.gyp:*',
+            '../test/intl/intl.gyp:*',
+            '../test/message/message.gyp:*',
+            '../test/mjsunit/mjsunit.gyp:*',
+            '../test/mozilla/mozilla.gyp:*',
+            '../test/optimize_for_size.gyp:*',
+            '../test/perf.gyp:*',
+            '../test/preparser/preparser.gyp:*',
+            '../test/simdjs/simdjs.gyp:*',
+            '../test/test262/test262.gyp:*',
+            '../test/webkit/webkit.gyp:*',
+            '../tools/check-static-initializers.gyp:*',
+            '../tools/gcmole/run_gcmole.gyp:*',
+            '../tools/jsfunfuzz/jsfunfuzz.gyp:*',
+            '../tools/run-deopt-fuzzer.gyp:*',
+            '../tools/run-valgrind.gyp:*',
+          ],
+        }],
+      ]
+    }
+  ]
+}
diff --git a/gypfiles/config/win/msvs_dependencies.isolate b/gypfiles/config/win/msvs_dependencies.isolate
new file mode 100644
index 0000000..ff92227
--- /dev/null
+++ b/gypfiles/config/win/msvs_dependencies.isolate
@@ -0,0 +1,77 @@
+# Copyright 2015 the V8 project authors. All rights reserved.
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+  'conditions': [
+    # Copy the VS runtime DLLs into the isolate so that they
+    # don't have to be preinstalled on the target machine.
+    #
+    # VS2013 runtimes
+    ['OS=="win" and msvs_version==2013 and component=="shared_library" and CONFIGURATION_NAME=="Debug"', {
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/x64/msvcp120d.dll',
+          '<(PRODUCT_DIR)/x64/msvcr120d.dll',
+        ],
+      },
+    }],
+    ['OS=="win" and msvs_version==2013 and component=="shared_library" and CONFIGURATION_NAME=="Release"', {
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/x64/msvcp120.dll',
+          '<(PRODUCT_DIR)/x64/msvcr120.dll',
+        ],
+      },
+    }],
+    ['OS=="win" and msvs_version==2013 and component=="shared_library" and (CONFIGURATION_NAME=="Debug" or CONFIGURATION_NAME=="Debug_x64")', {
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/msvcp120d.dll',
+          '<(PRODUCT_DIR)/msvcr120d.dll',
+        ],
+      },
+    }],
+    ['OS=="win" and msvs_version==2013 and component=="shared_library" and (CONFIGURATION_NAME=="Release" or CONFIGURATION_NAME=="Release_x64")', {
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/msvcp120.dll',
+          '<(PRODUCT_DIR)/msvcr120.dll',
+        ],
+      },
+    }],
+    # VS2015 runtimes
+    ['OS=="win" and msvs_version==2015 and component=="shared_library" and CONFIGURATION_NAME=="Debug"', {
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/x64/msvcp140d.dll',
+          '<(PRODUCT_DIR)/x64/vccorlib140d.dll',
+        ],
+      },
+    }],
+    ['OS=="win" and msvs_version==2015 and component=="shared_library" and CONFIGURATION_NAME=="Release"', {
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/x64/msvcp140.dll',
+          '<(PRODUCT_DIR)/x64/vccorlib140.dll',
+        ],
+      },
+    }],
+    ['OS=="win" and msvs_version==2015 and component=="shared_library" and (CONFIGURATION_NAME=="Debug" or CONFIGURATION_NAME=="Debug_x64")', {
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/msvcp140d.dll',
+          '<(PRODUCT_DIR)/vccorlib140d.dll',
+        ],
+      },
+    }],
+    ['OS=="win" and msvs_version==2015 and component=="shared_library" and (CONFIGURATION_NAME=="Release" or CONFIGURATION_NAME=="Release_x64")', {
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/msvcp140.dll',
+          '<(PRODUCT_DIR)/vccorlib140.dll',
+        ],
+      },
+    }],
+  ],
+}
\ No newline at end of file
diff --git a/build/coverage_wrapper.py b/gypfiles/coverage_wrapper.py
similarity index 100%
rename from build/coverage_wrapper.py
rename to gypfiles/coverage_wrapper.py
diff --git a/build/detect_v8_host_arch.py b/gypfiles/detect_v8_host_arch.py
similarity index 100%
rename from build/detect_v8_host_arch.py
rename to gypfiles/detect_v8_host_arch.py
diff --git a/gypfiles/download_gold_plugin.py b/gypfiles/download_gold_plugin.py
new file mode 100755
index 0000000..b8131fd
--- /dev/null
+++ b/gypfiles/download_gold_plugin.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+# Copyright 2015 the V8 project authors. All rights reserved.
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Script to download LLVM gold plugin from google storage."""
+
+import json
+import os
+import re
+import platform
+import shutil
+import subprocess
+import sys
+import zipfile
+
+# Bail out on windows and cygwin.
+if "win" in platform.system().lower():
+  # Python 2.7.6 hangs at the second path.insert command on windows. Works
+  # with python 2.7.8.
+  print "Gold plugin download not supported on windows."
+  sys.exit(0)
+
+SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
+CHROME_SRC = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir))
+sys.path.insert(0, os.path.join(CHROME_SRC, 'tools'))
+
+import find_depot_tools
+
+DEPOT_PATH = find_depot_tools.add_depot_tools_to_path()
+GSUTIL_PATH = os.path.join(DEPOT_PATH, 'gsutil.py')
+
+LLVM_BUILD_PATH = os.path.join(CHROME_SRC, 'third_party', 'llvm-build',
+                               'Release+Asserts')
+CLANG_UPDATE_PY = os.path.join(CHROME_SRC, 'tools', 'clang', 'scripts',
+                               'update.py')
+CLANG_REVISION = os.popen(CLANG_UPDATE_PY + ' --print-revision').read().rstrip()
+
+CLANG_BUCKET = 'gs://chromium-browser-clang/Linux_x64'
+
+GOLD_PLUGIN_PATH = os.path.join(LLVM_BUILD_PATH, 'lib', 'LLVMgold.so')
+
+sys.path.insert(0, os.path.join(CHROME_SRC, 'tools', 'clang', 'scripts'))
+
+import update
+
+def main():
+  if not re.search(r'cfi_vptr=1', os.environ.get('GYP_DEFINES', '')):
+    # Bailout if this is not a cfi build.
+    print 'Skipping gold plugin download for non-cfi build.'
+    return 0
+  if (os.path.exists(GOLD_PLUGIN_PATH) and
+      update.ReadStampFile().strip() == update.PACKAGE_VERSION):
+    # Bailout if clang is up-to-date. This requires the script to be run before
+    # the clang update step! I.e. afterwards clang would always be up-to-date.
+    print 'Skipping gold plugin download. File present and clang up to date.'
+    return 0
+
+  # Make sure this works on empty checkouts (i.e. clang not downloaded yet).
+  if not os.path.exists(LLVM_BUILD_PATH):
+    os.makedirs(LLVM_BUILD_PATH)
+
+  targz_name = 'llvmgold-%s.tgz' % CLANG_REVISION
+  remote_path = '%s/%s' % (CLANG_BUCKET, targz_name)
+
+  os.chdir(LLVM_BUILD_PATH)
+
+  # TODO(pcc): Fix gsutil.py cp url file < /dev/null 2>&0
+  # (currently aborts with exit code 1,
+  # https://github.com/GoogleCloudPlatform/gsutil/issues/289) or change the
+  # stdin->stderr redirect in update.py to do something else (crbug.com/494442).
+  subprocess.check_call(['python', GSUTIL_PATH,
+                         'cp', remote_path, targz_name],
+                        stderr=open('/dev/null', 'w'))
+  subprocess.check_call(['tar', 'xzf', targz_name])
+  os.remove(targz_name)
+  return 0
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/build/features.gypi b/gypfiles/features.gypi
similarity index 100%
rename from build/features.gypi
rename to gypfiles/features.gypi
diff --git a/gypfiles/get_landmines.py b/gypfiles/get_landmines.py
new file mode 100755
index 0000000..9fcca4b
--- /dev/null
+++ b/gypfiles/get_landmines.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+# Copyright 2014 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+This file emits the list of reasons why a particular build needs to be clobbered
+(or a list of 'landmines').
+"""
+
+import sys
+
+
+def main():
+  """
+  ALL LANDMINES ARE EMITTED FROM HERE.
+  """
+  print 'Need to clobber after ICU52 roll.'
+  print 'Landmines test.'
+  print 'Activating MSVS 2013.'
+  print 'Revert activation of MSVS 2013.'
+  print 'Activating MSVS 2013 again.'
+  print 'Clobber after ICU roll.'
+  print 'Moar clobbering...'
+  print 'Remove build/android.gypi'
+  print 'Cleanup after windows ninja switch attempt.'
+  print 'Switching to pinned msvs toolchain.'
+  print 'Clobbering to hopefully resolve problem with mksnapshot'
+  print 'Clobber after ICU roll.'
+  print 'Clobber after Android NDK update.'
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/gypfiles/gyp_environment.py b/gypfiles/gyp_environment.py
new file mode 100644
index 0000000..76ae841
--- /dev/null
+++ b/gypfiles/gyp_environment.py
@@ -0,0 +1,60 @@
+# Copyright 2015 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Sets up various automatic gyp environment variables. These are used by
+gyp_v8 and landmines.py which run at different stages of runhooks. To
+make sure settings are consistent between them, all setup should happen here.
+"""
+
+import os
+import sys
+import vs_toolchain
+
+SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
+V8_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir))
+
+
+def apply_gyp_environment(file_path=None):
+  """
+  Reads in a *.gyp_env file and applies the valid keys to os.environ.
+  """
+  if not file_path or not os.path.exists(file_path):
+    return
+  file_contents = open(file_path).read()
+  try:
+    file_data = eval(file_contents, {'__builtins__': None}, None)
+  except SyntaxError, e:
+    e.filename = os.path.abspath(file_path)
+    raise
+  supported_vars = ( 'V8_GYP_FILE',
+                     'V8_GYP_SYNTAX_CHECK',
+                     'GYP_DEFINES',
+                     'GYP_GENERATORS',
+                     'GYP_GENERATOR_FLAGS',
+                     'GYP_GENERATOR_OUTPUT', )
+  for var in supported_vars:
+    val = file_data.get(var)
+    if val:
+      if var in os.environ:
+        print 'INFO: Environment value for "%s" overrides value in %s.' % (
+            var, os.path.abspath(file_path)
+        )
+      else:
+        os.environ[var] = val
+
+
+def set_environment():
+  """Sets defaults for GYP_* variables."""
+
+  if 'SKIP_V8_GYP_ENV' not in os.environ:
+    # Update the environment based on v8.gyp_env
+    gyp_env_path = os.path.join(os.path.dirname(V8_ROOT), 'v8.gyp_env')
+    apply_gyp_environment(gyp_env_path)
+
+    if not os.environ.get('GYP_GENERATORS'):
+      # Default to ninja on all platforms.
+      os.environ['GYP_GENERATORS'] = 'ninja'
+
+    vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs()
diff --git a/gypfiles/gyp_v8 b/gypfiles/gyp_v8
new file mode 100755
index 0000000..8be39d9
--- /dev/null
+++ b/gypfiles/gyp_v8
@@ -0,0 +1,185 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+#       copyright notice, this list of conditions and the following
+#       disclaimer in the documentation and/or other materials provided
+#       with the distribution.
+#     * Neither the name of Google Inc. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# This script is wrapper for V8 that adds some support for how GYP
+# is invoked by V8 beyond what can be done in the gclient hooks.
+
+import argparse
+import glob
+import gyp_environment
+import os
+import platform
+import shlex
+import subprocess
+import sys
+import vs_toolchain
+
+script_dir = os.path.dirname(os.path.realpath(__file__))
+v8_root = os.path.abspath(os.path.join(script_dir, os.pardir))
+
+sys.path.insert(0, os.path.join(v8_root, 'tools', 'gyp', 'pylib'))
+import gyp
+
+# Add paths so that pymod_do_main(...) can import files.
+sys.path.insert(
+    1, os.path.abspath(os.path.join(v8_root, 'tools', 'generate_shim_headers')))
+
+
+def GetOutputDirectory():
+  """Returns the output directory that GYP will use."""
+
+  # Handle command line generator flags.
+  parser = argparse.ArgumentParser()
+  parser.add_argument('-G', dest='genflags', default=[], action='append')
+  genflags = parser.parse_known_args()[0].genflags
+
+  # Handle generator flags from the environment.
+  genflags += shlex.split(os.environ.get('GYP_GENERATOR_FLAGS', ''))
+
+  needle = 'output_dir='
+  for item in genflags:
+    if item.startswith(needle):
+      return item[len(needle):]
+
+  return 'out'
+
+
+def additional_include_files(args=[]):
+  """
+  Returns a list of additional (.gypi) files to include, without
+  duplicating ones that are already specified on the command line.
+  """
+  # Determine the include files specified on the command line.
+  # This doesn't cover all the different option formats you can use,
+  # but it's mainly intended to avoid duplicating flags on the automatic
+  # makefile regeneration which only uses this format.
+  specified_includes = set()
+  for arg in args:
+    if arg.startswith('-I') and len(arg) > 2:
+      specified_includes.add(os.path.realpath(arg[2:]))
+
+  result = []
+  def AddInclude(path):
+    if os.path.realpath(path) not in specified_includes:
+      result.append(path)
+
+  # Always include standalone.gypi
+  AddInclude(os.path.join(v8_root, 'gypfiles', 'standalone.gypi'))
+
+  # Optionally add supplemental .gypi files if present.
+  supplements = glob.glob(os.path.join(v8_root, '*', 'supplement.gypi'))
+  for supplement in supplements:
+    AddInclude(supplement)
+
+  return result
+
+
+def run_gyp(args):
+  rc = gyp.main(args)
+
+  vs2013_runtime_dll_dirs = vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs()
+  if vs2013_runtime_dll_dirs:
+    x64_runtime, x86_runtime = vs2013_runtime_dll_dirs
+    vs_toolchain.CopyVsRuntimeDlls(
+      os.path.join(v8_root, GetOutputDirectory()),
+      (x86_runtime, x64_runtime))
+
+  if rc != 0:
+    print 'Error running GYP'
+    sys.exit(rc)
+
+
+if __name__ == '__main__':
+  args = sys.argv[1:]
+
+  if int(os.environ.get('GYP_CHROMIUM_NO_ACTION', 0)):
+    print 'Skipping gyp_v8 due to GYP_CHROMIUM_NO_ACTION env var.'
+    sys.exit(0)
+
+  gyp_environment.set_environment()
+
+  # This could give false positives since it doesn't actually do real option
+  # parsing.  Oh well.
+  gyp_file_specified = False
+  for arg in args:
+    if arg.endswith('.gyp'):
+      gyp_file_specified = True
+      break
+
+  # If we didn't get a file, check an env var, and then fall back to
+  # assuming 'all.gyp' from the same directory as the script.
+  if not gyp_file_specified:
+    gyp_file = os.environ.get('V8_GYP_FILE')
+    if gyp_file:
+      # Note that V8_GYP_FILE values can't have backslashes as
+      # path separators even on Windows due to the use of shlex.split().
+      args.extend(shlex.split(gyp_file))
+    else:
+      args.append(os.path.join(script_dir, 'all.gyp'))
+
+  args.extend(['-I' + i for i in additional_include_files(args)])
+
+  # There shouldn't be a circular dependency relationship between .gyp files
+  args.append('--no-circular-check')
+
+  # Set the GYP DEPTH variable to the root of the V8 project.
+  args.append('--depth=' + os.path.relpath(v8_root))
+
+  # If V8_GYP_SYNTAX_CHECK is set to 1, it will invoke gyp with --check
+  # to enfore syntax checking.
+  syntax_check = os.environ.get('V8_GYP_SYNTAX_CHECK')
+  if syntax_check and int(syntax_check):
+    args.append('--check')
+
+  print 'Updating projects from gyp files...'
+  sys.stdout.flush()
+
+  # Generate for the architectures supported on the given platform.
+  gyp_args = list(args)
+  gyp_args.extend(['-D', 'gyp_output_dir=' + GetOutputDirectory()])
+  gyp_generators = os.environ.get('GYP_GENERATORS', '')
+  if platform.system() == 'Linux' and gyp_generators != 'ninja':
+    # Work around for crbug.com/331475.
+    for f in glob.glob(os.path.join(v8_root, 'out', 'Makefile.*')):
+      os.unlink(f)
+    # --generator-output defines where the Makefile goes.
+    gyp_args.append('--generator-output=out')
+    # -Goutput_dir defines where the build output goes, relative to the
+    # Makefile. Set it to . so that the build output doesn't end up in out/out.
+    gyp_args.append('-Goutput_dir=.')
+
+  gyp_defines = os.environ.get('GYP_DEFINES', '')
+
+  # Automatically turn on crosscompile support for platforms that need it.
+  if all(('ninja' in gyp_generators,
+          'OS=android' in gyp_defines,
+          'GYP_CROSSCOMPILE' not in os.environ)):
+    os.environ['GYP_CROSSCOMPILE'] = '1'
+
+  run_gyp(gyp_args)
diff --git a/build/gyp_v8.py b/gypfiles/gyp_v8.py
similarity index 100%
rename from build/gyp_v8.py
rename to gypfiles/gyp_v8.py
diff --git a/gypfiles/isolate.gypi b/gypfiles/isolate.gypi
new file mode 100644
index 0000000..085ed5d
--- /dev/null
+++ b/gypfiles/isolate.gypi
@@ -0,0 +1,100 @@
+# Copyright 2015 the V8 project authors. All rights reserved.
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file is meant to be included into a target to provide a rule
+# to "build" .isolate files into a .isolated file.
+#
+# To use this, create a gyp target with the following form:
+# 'conditions': [
+#   ['test_isolation_mode != "noop"', {
+#     'targets': [
+#       {
+#         'target_name': 'foo_test_run',
+#         'type': 'none',
+#         'dependencies': [
+#           'foo_test',
+#         ],
+#         'includes': [
+#           '../gypfiles/isolate.gypi',
+#         ],
+#         'sources': [
+#           'foo_test.isolate',
+#         ],
+#       },
+#     ],
+#   }],
+# ],
+#
+# Note: foo_test.isolate is included and a source file. It is an inherent
+# property of the .isolate format. This permits to define GYP variables but is
+# a stricter format than GYP so isolate.py can read it.
+#
+# The generated .isolated file will be:
+#   <(PRODUCT_DIR)/foo_test.isolated
+#
+# See http://dev.chromium.org/developers/testing/isolated-testing/for-swes
+# for more information.
+
+{
+  'rules': [
+    {
+      'rule_name': 'isolate',
+      'extension': 'isolate',
+      'inputs': [
+        # Files that are known to be involved in this step.
+        '<(DEPTH)/tools/isolate_driver.py',
+        '<(DEPTH)/tools/swarming_client/isolate.py',
+        '<(DEPTH)/tools/swarming_client/run_isolated.py',
+      ],
+      'outputs': [
+        '<(PRODUCT_DIR)/<(RULE_INPUT_ROOT).isolated',
+      ],
+      'action': [
+        'python',
+        '<(DEPTH)/tools/isolate_driver.py',
+        '<(test_isolation_mode)',
+        '--isolated', '<(PRODUCT_DIR)/<(RULE_INPUT_ROOT).isolated',
+        '--isolate', '<(RULE_INPUT_PATH)',
+
+        # Variables should use the -V FOO=<(FOO) form so frequent values,
+        # like '0' or '1', aren't stripped out by GYP. Run 'isolate.py help'
+        # for more details.
+
+        # Path variables are used to replace file paths when loading a .isolate
+        # file
+        '--path-variable', 'DEPTH', '<(DEPTH)',
+        '--path-variable', 'PRODUCT_DIR', '<(PRODUCT_DIR)',
+
+        '--config-variable', 'CONFIGURATION_NAME=<(CONFIGURATION_NAME)',
+        '--config-variable', 'OS=<(OS)',
+        '--config-variable', 'asan=<(asan)',
+        '--config-variable', 'cfi_vptr=<(cfi_vptr)',
+        '--config-variable', 'gcmole=<(gcmole)',
+        '--config-variable', 'has_valgrind=<(has_valgrind)',
+        '--config-variable', 'icu_use_data_file_flag=<(icu_use_data_file_flag)',
+        '--config-variable', 'msan=<(msan)',
+        '--config-variable', 'tsan=<(tsan)',
+        '--config-variable', 'coverage=<(coverage)',
+        '--config-variable', 'sanitizer_coverage=<(sanitizer_coverage)',
+        '--config-variable', 'component=<(component)',
+        '--config-variable', 'target_arch=<(target_arch)',
+        '--config-variable', 'use_custom_libcxx=<(use_custom_libcxx)',
+        '--config-variable', 'v8_use_external_startup_data=<(v8_use_external_startup_data)',
+        '--config-variable', 'v8_use_snapshot=<(v8_use_snapshot)',
+      ],
+      'conditions': [
+        ['OS=="win"', {
+          'action': [
+            '--config-variable', 'msvs_version=2013',
+          ],
+        }, {
+          'action': [
+            '--config-variable', 'msvs_version=0',
+          ],
+        }],
+      ],
+    },
+  ],
+}
diff --git a/gypfiles/landmine_utils.py b/gypfiles/landmine_utils.py
new file mode 100644
index 0000000..cb34991
--- /dev/null
+++ b/gypfiles/landmine_utils.py
@@ -0,0 +1,123 @@
+# Copyright 2014 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+import functools
+import logging
+import os
+import shlex
+import sys
+
+
+def memoize(default=None):
+  """This decorator caches the return value of a parameterless pure function"""
+  def memoizer(func):
+    val = []
+    @functools.wraps(func)
+    def inner():
+      if not val:
+        ret = func()
+        val.append(ret if ret is not None else default)
+        if logging.getLogger().isEnabledFor(logging.INFO):
+          print '%s -> %r' % (func.__name__, val[0])
+      return val[0]
+    return inner
+  return memoizer
+
+
+@memoize()
+def IsWindows():
+  return sys.platform in ['win32', 'cygwin']
+
+
+@memoize()
+def IsLinux():
+  return sys.platform.startswith(('linux', 'freebsd'))
+
+
+@memoize()
+def IsMac():
+  return sys.platform == 'darwin'
+
+
+@memoize()
+def gyp_defines():
+  """Parses and returns GYP_DEFINES env var as a dictionary."""
+  return dict(arg.split('=', 1)
+      for arg in shlex.split(os.environ.get('GYP_DEFINES', '')))
+
+
+@memoize()
+def gyp_generator_flags():
+  """Parses and returns GYP_GENERATOR_FLAGS env var as a dictionary."""
+  return dict(arg.split('=', 1)
+      for arg in shlex.split(os.environ.get('GYP_GENERATOR_FLAGS', '')))
+
+
+@memoize()
+def gyp_msvs_version():
+  return os.environ.get('GYP_MSVS_VERSION', '')
+
+
+@memoize()
+def distributor():
+  """
+  Returns a string which is the distributed build engine in use (if any).
+  Possible values: 'goma', 'ib', ''
+  """
+  if 'goma' in gyp_defines():
+    return 'goma'
+  elif IsWindows():
+    if 'CHROME_HEADLESS' in os.environ:
+      return 'ib' # use (win and !goma and headless) as approximation of ib
+
+
+@memoize()
+def platform():
+  """
+  Returns a string representing the platform this build is targetted for.
+  Possible values: 'win', 'mac', 'linux', 'ios', 'android'
+  """
+  if 'OS' in gyp_defines():
+    if 'android' in gyp_defines()['OS']:
+      return 'android'
+    else:
+      return gyp_defines()['OS']
+  elif IsWindows():
+    return 'win'
+  elif IsLinux():
+    return 'linux'
+  else:
+    return 'mac'
+
+
+@memoize()
+def builder():
+  """
+  Returns a string representing the build engine (not compiler) to use.
+  Possible values: 'make', 'ninja', 'xcode', 'msvs', 'scons'
+  """
+  if 'GYP_GENERATORS' in os.environ:
+    # for simplicity, only support the first explicit generator
+    generator = os.environ['GYP_GENERATORS'].split(',')[0]
+    if generator.endswith('-android'):
+      return generator.split('-')[0]
+    elif generator.endswith('-ninja'):
+      return 'ninja'
+    else:
+      return generator
+  else:
+    if platform() == 'android':
+      # Good enough for now? Do any android bots use make?
+      return 'make'
+    elif platform() == 'ios':
+      return 'xcode'
+    elif IsWindows():
+      return 'msvs'
+    elif IsLinux():
+      return 'make'
+    elif IsMac():
+      return 'xcode'
+    else:
+      assert False, 'Don\'t know what builder we\'re using!'
diff --git a/gypfiles/landmines.py b/gypfiles/landmines.py
new file mode 100755
index 0000000..2a81c66
--- /dev/null
+++ b/gypfiles/landmines.py
@@ -0,0 +1,245 @@
+#!/usr/bin/env python
+# Copyright 2014 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+This script runs every build as the first hook (See DEPS). If it detects that
+the build should be clobbered, it will delete the contents of the build
+directory.
+
+A landmine is tripped when a builder checks out a different revision, and the
+diff between the new landmines and the old ones is non-null. At this point, the
+build is clobbered.
+"""
+
+import difflib
+import errno
+import gyp_environment
+import logging
+import optparse
+import os
+import re
+import shutil
+import sys
+import subprocess
+import time
+
+import landmine_utils
+
+
+SRC_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
+
+
+def get_build_dir(build_tool, is_iphone=False):
+  """
+  Returns output directory absolute path dependent on build and targets.
+  Examples:
+    r'c:\b\build\slave\win\build\src\out'
+    '/mnt/data/b/build/slave/linux/build/src/out'
+    '/b/build/slave/ios_rel_device/build/src/xcodebuild'
+
+  Keep this function in sync with tools/build/scripts/slave/compile.py
+  """
+  ret = None
+  if build_tool == 'xcode':
+    ret = os.path.join(SRC_DIR, 'xcodebuild')
+  elif build_tool in ['make', 'ninja', 'ninja-ios']:  # TODO: Remove ninja-ios.
+    if 'CHROMIUM_OUT_DIR' in os.environ:
+      output_dir = os.environ.get('CHROMIUM_OUT_DIR').strip()
+      if not output_dir:
+        raise Error('CHROMIUM_OUT_DIR environment variable is set but blank!')
+    else:
+      output_dir = landmine_utils.gyp_generator_flags().get('output_dir', 'out')
+    ret = os.path.join(SRC_DIR, output_dir)
+  elif build_tool in ['msvs', 'vs', 'ib']:
+    ret = os.path.join(SRC_DIR, 'build')
+  else:
+    raise NotImplementedError('Unexpected GYP_GENERATORS (%s)' % build_tool)
+  return os.path.abspath(ret)
+
+
+def extract_gn_build_commands(build_ninja_file):
+  """Extracts from a build.ninja the commands to run GN.
+
+  The commands to run GN are the gn rule and build.ninja build step at the
+  top of the build.ninja file. We want to keep these when deleting GN builds
+  since we want to preserve the command-line flags to GN.
+
+  On error, returns the empty string."""
+  result = ""
+  with open(build_ninja_file, 'r') as f:
+    # Read until the second blank line. The first thing GN writes to the file
+    # is the "rule gn" and the second is the section for "build build.ninja",
+    # separated by blank lines.
+    num_blank_lines = 0
+    while num_blank_lines < 2:
+      line = f.readline()
+      if len(line) == 0:
+        return ''  # Unexpected EOF.
+      result += line
+      if line[0] == '\n':
+        num_blank_lines = num_blank_lines + 1
+  return result
+
+def delete_build_dir(build_dir):
+  # GN writes a build.ninja.d file. Note that not all GN builds have args.gn.
+  build_ninja_d_file = os.path.join(build_dir, 'build.ninja.d')
+  if not os.path.exists(build_ninja_d_file):
+    shutil.rmtree(build_dir)
+    return
+
+  # GN builds aren't automatically regenerated when you sync. To avoid
+  # messing with the GN workflow, erase everything but the args file, and
+  # write a dummy build.ninja file that will automatically rerun GN the next
+  # time Ninja is run.
+  build_ninja_file = os.path.join(build_dir, 'build.ninja')
+  build_commands = extract_gn_build_commands(build_ninja_file)
+
+  try:
+    gn_args_file = os.path.join(build_dir, 'args.gn')
+    with open(gn_args_file, 'r') as f:
+      args_contents = f.read()
+  except IOError:
+    args_contents = ''
+
+  shutil.rmtree(build_dir)
+
+  # Put back the args file (if any).
+  os.mkdir(build_dir)
+  if args_contents != '':
+    with open(gn_args_file, 'w') as f:
+      f.write(args_contents)
+
+  # Write the build.ninja file sufficiently to regenerate itself.
+  with open(os.path.join(build_dir, 'build.ninja'), 'w') as f:
+    if build_commands != '':
+      f.write(build_commands)
+    else:
+      # Couldn't parse the build.ninja file, write a default thing.
+      f.write('''rule gn
+command = gn -q gen //out/%s/
+description = Regenerating ninja files
+
+build build.ninja: gn
+generator = 1
+depfile = build.ninja.d
+''' % (os.path.split(build_dir)[1]))
+
+  # Write a .d file for the build which references a nonexistant file. This
+  # will make Ninja always mark the build as dirty.
+  with open(build_ninja_d_file, 'w') as f:
+    f.write('build.ninja: nonexistant_file.gn\n')
+
+
+def needs_clobber(landmines_path, new_landmines):
+  if os.path.exists(landmines_path):
+    with open(landmines_path, 'r') as f:
+      old_landmines = f.readlines()
+    if old_landmines != new_landmines:
+      old_date = time.ctime(os.stat(landmines_path).st_ctime)
+      diff = difflib.unified_diff(old_landmines, new_landmines,
+          fromfile='old_landmines', tofile='new_landmines',
+          fromfiledate=old_date, tofiledate=time.ctime(), n=0)
+      sys.stdout.write('Clobbering due to:\n')
+      sys.stdout.writelines(diff)
+      return True
+  else:
+    sys.stdout.write('Clobbering due to missing landmines file.\n')
+    return True
+  return False
+
+
+def clobber_if_necessary(new_landmines):
+  """Does the work of setting, planting, and triggering landmines."""
+  out_dir = get_build_dir(landmine_utils.builder())
+  landmines_path = os.path.normpath(os.path.join(out_dir, '..', '.landmines'))
+  try:
+    os.makedirs(out_dir)
+  except OSError as e:
+    if e.errno == errno.EEXIST:
+      pass
+
+  if needs_clobber(landmines_path, new_landmines):
+    # Clobber contents of build directory but not directory itself: some
+    # checkouts have the build directory mounted.
+    for f in os.listdir(out_dir):
+      path = os.path.join(out_dir, f)
+      if os.path.basename(out_dir) == 'build':
+        # Only delete build directories and files for MSVS builds as the folder
+        # shares some checked out files and directories.
+        if (os.path.isdir(path) and
+            re.search(r'(?:[Rr]elease)|(?:[Dd]ebug)', f)):
+          delete_build_dir(path)
+        elif (os.path.isfile(path) and
+              (path.endswith('.sln') or
+               path.endswith('.vcxproj') or
+               path.endswith('.vcxproj.user'))):
+          os.unlink(path)
+      else:
+        if os.path.isfile(path):
+          os.unlink(path)
+        elif os.path.isdir(path):
+          delete_build_dir(path)
+    if os.path.basename(out_dir) == 'xcodebuild':
+      # Xcodebuild puts an additional project file structure into build,
+      # while the output folder is xcodebuild.
+      project_dir = os.path.join(SRC_DIR, 'build', 'all.xcodeproj')
+      if os.path.exists(project_dir) and os.path.isdir(project_dir):
+        delete_build_dir(project_dir)
+
+  # Save current set of landmines for next time.
+  with open(landmines_path, 'w') as f:
+    f.writelines(new_landmines)
+
+
+def process_options():
+  """Returns a list of landmine emitting scripts."""
+  parser = optparse.OptionParser()
+  parser.add_option(
+      '-s', '--landmine-scripts', action='append',
+      default=[os.path.join(SRC_DIR, 'gypfiles', 'get_landmines.py')],
+      help='Path to the script which emits landmines to stdout. The target '
+           'is passed to this script via option -t. Note that an extra '
+           'script can be specified via an env var EXTRA_LANDMINES_SCRIPT.')
+  parser.add_option('-v', '--verbose', action='store_true',
+      default=('LANDMINES_VERBOSE' in os.environ),
+      help=('Emit some extra debugging information (default off). This option '
+          'is also enabled by the presence of a LANDMINES_VERBOSE environment '
+          'variable.'))
+
+  options, args = parser.parse_args()
+
+  if args:
+    parser.error('Unknown arguments %s' % args)
+
+  logging.basicConfig(
+      level=logging.DEBUG if options.verbose else logging.ERROR)
+
+  extra_script = os.environ.get('EXTRA_LANDMINES_SCRIPT')
+  if extra_script:
+    return options.landmine_scripts + [extra_script]
+  else:
+    return options.landmine_scripts
+
+
+def main():
+  landmine_scripts = process_options()
+
+  if landmine_utils.builder() in ('dump_dependency_json', 'eclipse'):
+    return 0
+
+  gyp_environment.set_environment()
+
+  landmines = []
+  for s in landmine_scripts:
+    proc = subprocess.Popen([sys.executable, s], stdout=subprocess.PIPE)
+    output, _ = proc.communicate()
+    landmines.extend([('%s\n' % l.strip()) for l in output.splitlines()])
+  clobber_if_necessary(landmines)
+
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/gypfiles/mac/asan.gyp b/gypfiles/mac/asan.gyp
new file mode 100644
index 0000000..3fc7f58
--- /dev/null
+++ b/gypfiles/mac/asan.gyp
@@ -0,0 +1,31 @@
+# Copyright 2015 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+   'targets': [
+     {
+       'target_name': 'asan_dynamic_runtime',
+       'toolsets': ['target', 'host'],
+       'type': 'none',
+       'variables': {
+         # Every target is going to depend on asan_dynamic_runtime, so allow
+         # this one to depend on itself.
+         'prune_self_dependency': 1,
+         # Path is relative to this GYP file.
+         'asan_rtl_mask_path':
+             '../../third_party/llvm-build/Release+Asserts/lib/clang/*/lib/darwin',
+         'asan_osx_dynamic':
+             '<(asan_rtl_mask_path)/libclang_rt.asan_osx_dynamic.dylib',
+       },
+       'copies': [
+         {
+           'destination': '<(PRODUCT_DIR)',
+           'files': [
+             '<!(/bin/ls <(asan_osx_dynamic))',
+           ],
+         },
+       ],
+     },
+   ],
+}
diff --git a/gypfiles/set_clang_warning_flags.gypi b/gypfiles/set_clang_warning_flags.gypi
new file mode 100644
index 0000000..63d5f14
--- /dev/null
+++ b/gypfiles/set_clang_warning_flags.gypi
@@ -0,0 +1,59 @@
+# Copyright 2016 the V8 project authors. All rights reserved.
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file is meant to be included to set clang-specific compiler flags.
+# To use this the following variable can be defined:
+#   clang_warning_flags:       list: Compiler flags to pass to clang.
+#   clang_warning_flags_unset: list: Compiler flags to not pass to clang.
+#
+# Only use this in third-party code. In chromium_code, fix your code to not
+# warn instead!
+#
+# Note that the gypi file is included in target_defaults, so it does not need
+# to be explicitly included.
+#
+# Warning flags set by this will be used on all platforms. If you want to set
+# warning flags on only some platforms, you have to do so manually.
+#
+# To use this, create a gyp target with the following form:
+# {
+#   'target_name': 'my_target',
+#   'variables': {
+#     'clang_warning_flags': ['-Wno-awesome-warning'],
+#     'clang_warning_flags_unset': ['-Wpreviously-set-flag'],
+#   }
+# }
+
+{
+  'variables': {
+    'clang_warning_flags_unset%': [],  # Provide a default value.
+  },
+  'conditions': [
+    ['clang==1', {
+      # This uses >@ instead of @< to also see clang_warning_flags set in
+      # targets directly, not just the clang_warning_flags in target_defaults.
+      'cflags': [ '>@(clang_warning_flags)' ],
+      'cflags!': [ '>@(clang_warning_flags_unset)' ],
+      'xcode_settings': {
+        'WARNING_CFLAGS': ['>@(clang_warning_flags)'],
+        'WARNING_CFLAGS!': ['>@(clang_warning_flags_unset)'],
+      },
+      'msvs_settings': {
+        'VCCLCompilerTool': {
+          'AdditionalOptions': [ '>@(clang_warning_flags)' ],
+          'AdditionalOptions!': [ '>@(clang_warning_flags_unset)' ],
+        },
+      },
+    }],
+    ['clang==0 and host_clang==1', {
+      'target_conditions': [
+        ['_toolset=="host"', {
+          'cflags': [ '>@(clang_warning_flags)' ],
+          'cflags!': [ '>@(clang_warning_flags_unset)' ],
+        }],
+      ],
+    }],
+  ],
+}
diff --git a/gypfiles/shim_headers.gypi b/gypfiles/shim_headers.gypi
new file mode 100644
index 0000000..940211c
--- /dev/null
+++ b/gypfiles/shim_headers.gypi
@@ -0,0 +1,73 @@
+# 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 meant to be included into a target to handle shim headers
+# in a consistent manner. To use this the following variables need to be
+# defined:
+#   headers_root_path: string: path to directory containing headers
+#   header_filenames: list: list of header file names
+
+{
+  'variables': {
+    'shim_headers_path': '<(SHARED_INTERMEDIATE_DIR)/shim_headers/<(_target_name)/<(_toolset)',
+    'shim_generator_additional_args%': [],
+  },
+  'include_dirs++': [
+    '<(shim_headers_path)',
+  ],
+  'all_dependent_settings': {
+    'include_dirs+++': [
+      '<(shim_headers_path)',
+    ],
+  },
+  'actions': [
+    {
+      'variables': {
+        'generator_path': '<(DEPTH)/tools/generate_shim_headers/generate_shim_headers.py',
+        'generator_args': [
+          '--headers-root', '<(headers_root_path)',
+          '--output-directory', '<(shim_headers_path)',
+          '<@(shim_generator_additional_args)',
+          '<@(header_filenames)',
+        ],
+      },
+      'action_name': 'generate_<(_target_name)_shim_headers',
+      'inputs': [
+        '<(generator_path)',
+      ],
+      'outputs': [
+        '<!@pymod_do_main(generate_shim_headers <@(generator_args) --outputs)',
+      ],
+      'action': ['python',
+                 '<(generator_path)',
+                 '<@(generator_args)',
+                 '--generate',
+      ],
+      'message': 'Generating <(_target_name) shim headers.',
+    },
+  ],
+}
diff --git a/gypfiles/standalone.gypi b/gypfiles/standalone.gypi
new file mode 100644
index 0000000..c6c26fb
--- /dev/null
+++ b/gypfiles/standalone.gypi
@@ -0,0 +1,1485 @@
+# Copyright 2012 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * 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.
+
+# Definitions to be used when building stand-alone V8 binaries.
+
+{
+  # We need to include toolchain.gypi here for third-party sources that don't
+  # directly include it themselves.
+  'includes': ['toolchain.gypi'],
+  'variables': {
+    'component%': 'static_library',
+    'clang_xcode%': 0,
+    # Track where uninitialized memory originates from. From fastest to
+    # slowest: 0 - no tracking, 1 - track only the initial allocation site, 2
+    # - track the chain of stores leading from allocation site to use site.
+    'msan_track_origins%': 2,
+    'visibility%': 'hidden',
+    'v8_enable_backtrace%': 0,
+    'v8_enable_i18n_support%': 1,
+    'v8_deprecation_warnings': 1,
+    'v8_imminent_deprecation_warnings': 1,
+    'msvs_multi_core_compile%': '1',
+    'mac_deployment_target%': '10.7',
+    'release_extra_cflags%': '',
+    'variables': {
+      'variables': {
+        'variables': {
+          'variables': {
+            'conditions': [
+              ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or \
+                 OS=="netbsd" or OS=="mac" or OS=="qnx" or OS=="aix"', {
+                # This handles the Unix platforms we generally deal with.
+                # Anything else gets passed through, which probably won't work
+                # very well; such hosts should pass an explicit target_arch
+                # to gyp.
+                'host_arch%': '<!pymod_do_main(detect_v8_host_arch)',
+              }, {
+                # OS!="linux" and OS!="freebsd" and OS!="openbsd" and
+                # OS!="netbsd" and OS!="mac" and OS!="aix"
+                'host_arch%': 'ia32',
+              }],
+            ],
+          },
+          'host_arch%': '<(host_arch)',
+          'target_arch%': '<(host_arch)',
+
+          # By default we build against a stable sysroot image to avoid
+          # depending on the packages installed on the local machine. Set this
+          # to 0 to build against locally installed headers and libraries (e.g.
+          # if packaging for a linux distro)
+          'use_sysroot%': 1,
+        },
+        'host_arch%': '<(host_arch)',
+        'target_arch%': '<(target_arch)',
+        'use_sysroot%': '<(use_sysroot)',
+        'base_dir%': '<!(cd <(DEPTH) && python -c "import os; print os.getcwd()")',
+
+        # Instrument for code coverage and use coverage wrapper to exclude some
+        # files. Uses gcov if clang=0 is set explicitly. Otherwise,
+        # sanitizer_coverage must be set too.
+        'coverage%': 0,
+
+        # Default sysroot if no sysroot can be provided.
+        'sysroot%': '',
+
+        'conditions': [
+          # The system root for linux builds.
+          ['OS=="linux" and use_sysroot==1', {
+            'conditions': [
+              ['target_arch=="arm"', {
+                'sysroot%': '<!(cd <(DEPTH) && pwd -P)/build/linux/debian_wheezy_arm-sysroot',
+              }],
+              ['target_arch=="x64"', {
+                'sysroot%': '<!(cd <(DEPTH) && pwd -P)/build/linux/debian_wheezy_amd64-sysroot',
+              }],
+              ['target_arch=="ia32"', {
+                'sysroot%': '<!(cd <(DEPTH) && pwd -P)/build/linux/debian_wheezy_i386-sysroot',
+              }],
+              ['target_arch=="mipsel"', {
+                'sysroot%': '<!(cd <(DEPTH) && pwd -P)/build/linux/debian_wheezy_mips-sysroot',
+              }],
+            ],
+          }], # OS=="linux" and use_sysroot==1
+        ],
+      },
+      'base_dir%': '<(base_dir)',
+      'host_arch%': '<(host_arch)',
+      'target_arch%': '<(target_arch)',
+      'v8_target_arch%': '<(target_arch)',
+      'coverage%': '<(coverage)',
+      'sysroot%': '<(sysroot)',
+      'asan%': 0,
+      'lsan%': 0,
+      'msan%': 0,
+      'tsan%': 0,
+      # Enable coverage gathering instrumentation in sanitizer tools. This flag
+      # also controls coverage granularity (1 for function-level, 2 for
+      # block-level, 3 for edge-level).
+      'sanitizer_coverage%': 0,
+      # Use libc++ (buildtools/third_party/libc++ and
+      # buildtools/third_party/libc++abi) instead of stdlibc++ as standard
+      # library. This is intended to be used for instrumented builds.
+      'use_custom_libcxx%': 0,
+
+      'clang_dir%': '<(base_dir)/third_party/llvm-build/Release+Asserts',
+
+      'use_lto%': 0,
+
+      # Control Flow Integrity for virtual calls and casts.
+      # See http://clang.llvm.org/docs/ControlFlowIntegrity.html
+      'cfi_vptr%': 0,
+      'cfi_diag%': 0,
+
+      'cfi_blacklist%': '<(base_dir)/tools/cfi/blacklist.txt',
+
+      # Set to 1 to enable fast builds.
+      # TODO(machenbach): Only configured for windows.
+      'fastbuild%': 0,
+
+      # goma settings.
+      # 1 to use goma.
+      # If no gomadir is set, it uses the default gomadir.
+      'use_goma%': 0,
+      'gomadir%': '',
+
+      'test_isolation_mode%': 'noop',
+
+      # By default, use ICU data file (icudtl.dat).
+      'icu_use_data_file_flag%': 1,
+
+      'conditions': [
+        # Set default gomadir.
+        ['OS=="win"', {
+          'gomadir': 'c:\\goma\\goma-win',
+        }, {
+          'gomadir': '<!(/bin/echo -n ${HOME}/goma)',
+        }],
+        ['host_arch!="ppc" and host_arch!="ppc64" and host_arch!="ppc64le" and host_arch!="s390" and host_arch!="s390x"', {
+          'host_clang%': 1,
+        }, {
+          'host_clang%': 0,
+        }],
+        # linux_use_bundled_gold: whether to use the gold linker binary checked
+        # into third_party/binutils.  Force this off via GYP_DEFINES when you
+        # are using a custom toolchain and need to control -B in ldflags.
+        # Do not use 32-bit gold on 32-bit hosts as it runs out address space
+        # for component=static_library builds.
+        ['(OS=="linux" or OS=="android") and (target_arch=="x64" or target_arch=="arm" or (target_arch=="ia32" and host_arch=="x64"))', {
+          'linux_use_bundled_gold%': 1,
+        }, {
+          'linux_use_bundled_gold%': 0,
+        }],
+      ],
+    },
+    'base_dir%': '<(base_dir)',
+    'clang_dir%': '<(clang_dir)',
+    'host_arch%': '<(host_arch)',
+    'host_clang%': '<(host_clang)',
+    'target_arch%': '<(target_arch)',
+    'v8_target_arch%': '<(v8_target_arch)',
+    'werror%': '-Werror',
+    'use_goma%': '<(use_goma)',
+    'gomadir%': '<(gomadir)',
+    'asan%': '<(asan)',
+    'lsan%': '<(lsan)',
+    'msan%': '<(msan)',
+    'tsan%': '<(tsan)',
+    'sanitizer_coverage%': '<(sanitizer_coverage)',
+    'use_custom_libcxx%': '<(use_custom_libcxx)',
+    'linux_use_bundled_gold%': '<(linux_use_bundled_gold)',
+    'use_lto%': '<(use_lto)',
+    'cfi_vptr%': '<(cfi_vptr)',
+    'cfi_diag%': '<(cfi_diag)',
+    'cfi_blacklist%': '<(cfi_blacklist)',
+    'test_isolation_mode%': '<(test_isolation_mode)',
+    'fastbuild%': '<(fastbuild)',
+    'coverage%': '<(coverage)',
+    'sysroot%': '<(sysroot)',
+    'icu_use_data_file_flag%': '<(icu_use_data_file_flag)',
+
+    # Add a simple extras solely for the purpose of the cctests
+    'v8_extra_library_files': ['../test/cctest/test-extra.js'],
+    'v8_experimental_extra_library_files': ['../test/cctest/test-experimental-extra.js'],
+
+    # .gyp files or targets should set v8_code to 1 if they build V8 specific
+    # code, as opposed to external code.  This variable is used to control such
+    # things as the set of warnings to enable, and whether warnings are treated
+    # as errors.
+    'v8_code%': 0,
+
+    # Speeds up Debug builds:
+    # 0 - Compiler optimizations off (debuggable) (default). This may
+    #     be 5x slower than Release (or worse).
+    # 1 - Turn on optimizations and disable slow DCHECKs, but leave
+    #     V8_ENABLE_CHECKS and most other assertions enabled.  This may cause
+    #     some v8 tests to fail in the Debug configuration.  This roughly
+    #     matches the performance of a Release build and can be used by
+    #     embedders that need to build their own code as debug but don't want
+    #     or need a debug version of V8. This should produce near-release
+    #     speeds.
+    'v8_optimized_debug%': 0,
+
+    # Use external files for startup data blobs:
+    # the JS builtins sources and the start snapshot.
+    # Embedders that don't use standalone.gypi will need to add
+    # their own default value.
+    'v8_use_external_startup_data%': 1,
+
+    # Relative path to icu.gyp from this file.
+    'icu_gyp_path': '../third_party/icu/icu.gyp',
+
+    'conditions': [
+      ['(v8_target_arch=="arm" and host_arch!="arm") or \
+        (v8_target_arch=="arm64" and host_arch!="arm64") or \
+        (v8_target_arch=="mipsel" and host_arch!="mipsel") or \
+        (v8_target_arch=="mips64el" and host_arch!="mips64el") or \
+        (v8_target_arch=="x64" and host_arch!="x64") or \
+        (OS=="android" or OS=="qnx")', {
+        'want_separate_host_toolset': 1,
+      }, {
+        'want_separate_host_toolset': 0,
+      }],
+      ['OS == "win"', {
+        'os_posix%': 0,
+      }, {
+        'os_posix%': 1,
+      }],
+      ['OS=="win" and use_goma==1', {
+        # goma doesn't support pch yet.
+        'chromium_win_pch': 0,
+        # goma doesn't support PDB yet.
+        'fastbuild%': 1,
+      }],
+      ['((v8_target_arch=="ia32" or v8_target_arch=="x64" or v8_target_arch=="x87") and \
+        (OS=="linux" or OS=="mac")) or (v8_target_arch=="ppc64" and OS=="linux")', {
+        'v8_enable_gdbjit%': 1,
+      }, {
+        'v8_enable_gdbjit%': 0,
+      }],
+      ['(OS=="linux" or OS=="mac") and (target_arch=="ia32" or target_arch=="x64") and \
+        (v8_target_arch!="x87" and v8_target_arch!="x32")', {
+        'clang%': 1,
+      }, {
+        'clang%': 0,
+      }],
+      ['asan==1 or lsan==1 or msan==1 or tsan==1', {
+        'clang%': 1,
+        'use_allocator%': 'none',
+      }],
+      ['asan==1 and OS=="linux"', {
+        'use_custom_libcxx%': 1,
+      }],
+      ['tsan==1', {
+        'use_custom_libcxx%': 1,
+      }],
+      ['msan==1', {
+        # Use a just-built, MSan-instrumented libc++ instead of the system-wide
+        # libstdc++. This is required to avoid false positive reports whenever
+        # the C++ standard library is used.
+        'use_custom_libcxx%': 1,
+      }],
+      ['cfi_vptr==1', {
+        'use_lto%': 1,
+      }],
+      ['OS=="android"', {
+        # Location of Android NDK.
+        'variables': {
+          'variables': {
+            # The Android toolchain needs to use the absolute path to the NDK
+            # because it is used at different levels in the GYP files.
+            'android_ndk_root%': '<(base_dir)/third_party/android_tools/ndk/',
+            'android_host_arch%': "<!(uname -m | sed -e 's/i[3456]86/x86/')",
+            # Version of the NDK. Used to ensure full rebuilds on NDK rolls.
+            'android_ndk_version%': 'r11c',
+            'host_os%': "<!(uname -s | sed -e 's/Linux/linux/;s/Darwin/mac/')",
+            'os_folder_name%': "<!(uname -s | sed -e 's/Linux/linux/;s/Darwin/darwin/')",
+          },
+
+          # Copy conditionally-set variables out one scope.
+          'android_ndk_root%': '<(android_ndk_root)',
+          'android_ndk_version%': '<(android_ndk_version)',
+          'host_os%': '<(host_os)',
+          'os_folder_name%': '<(os_folder_name)',
+
+          'conditions': [
+            ['target_arch == "ia32"', {
+              'android_toolchain%': '<(android_ndk_root)/toolchains/x86-4.9/prebuilt/<(os_folder_name)-<(android_host_arch)/bin',
+              'android_target_arch%': 'x86',
+              'android_target_platform%': '16',
+              'arm_version%': 'default',
+            }],
+            ['target_arch == "x64"', {
+              'android_toolchain%': '<(android_ndk_root)/toolchains/x86_64-4.9/prebuilt/<(os_folder_name)-<(android_host_arch)/bin',
+              'android_target_arch%': 'x86_64',
+              'android_target_platform%': '21',
+              'arm_version%': 'default',
+            }],
+            ['target_arch=="arm"', {
+              'android_toolchain%': '<(android_ndk_root)/toolchains/arm-linux-androideabi-4.9/prebuilt/<(os_folder_name)-<(android_host_arch)/bin',
+              'android_target_arch%': 'arm',
+              'android_target_platform%': '16',
+              'arm_version%': 7,
+            }],
+            ['target_arch == "arm64"', {
+              'android_toolchain%': '<(android_ndk_root)/toolchains/aarch64-linux-android-4.9/prebuilt/<(os_folder_name)-<(android_host_arch)/bin',
+              'android_target_arch%': 'arm64',
+              'android_target_platform%': '21',
+              'arm_version%': 'default',
+            }],
+            ['target_arch == "mipsel"', {
+              'android_toolchain%': '<(android_ndk_root)/toolchains/mipsel-linux-android-4.9/prebuilt/<(os_folder_name)-<(android_host_arch)/bin',
+              'android_target_arch%': 'mips',
+              'android_target_platform%': '16',
+              'arm_version%': 'default',
+            }],
+            ['target_arch == "mips64el"', {
+              'android_toolchain%': '<(android_ndk_root)/toolchains/mips64el-linux-android-4.9/prebuilt/<(os_folder_name)-<(android_host_arch)/bin',
+              'android_target_arch%': 'mips64',
+              'android_target_platform%': '21',
+              'arm_version%': 'default',
+            }],
+          ],
+        },
+
+        # Copy conditionally-set variables out one scope.
+        'android_ndk_version%': '<(android_ndk_version)',
+        'android_target_arch%': '<(android_target_arch)',
+        'android_target_platform%': '<(android_target_platform)',
+        'android_toolchain%': '<(android_toolchain)',
+        'arm_version%': '<(arm_version)',
+        'host_os%': '<(host_os)',
+
+        'conditions': [
+          ['android_ndk_root==""', {
+            'variables': {
+              'android_sysroot': '<(android_toolchain)/sysroot/',
+              'android_stl': '<(android_toolchain)/sources/cxx-stl/',
+            },
+            'conditions': [
+              ['target_arch=="x64"', {
+                'android_lib': '<(android_sysroot)/usr/lib64',
+              }, {
+                'android_lib': '<(android_sysroot)/usr/lib',
+              }],
+            ],
+            'android_libcpp_include': '<(android_stl)/llvm-libc++/libcxx/include',
+            'android_libcpp_abi_include': '<(android_stl)/llvm-libc++abi/libcxxabi/include',
+            'android_libcpp_libs': '<(android_stl)/llvm-libc++/libs',
+            'android_support_include': '<(android_toolchain)/sources/android/support/include',
+            'android_sysroot': '<(android_sysroot)',
+          }, {
+            'variables': {
+              'android_sysroot': '<(android_ndk_root)/platforms/android-<(android_target_platform)/arch-<(android_target_arch)',
+              'android_stl': '<(android_ndk_root)/sources/cxx-stl/',
+            },
+            'conditions': [
+              ['target_arch=="x64"', {
+                'android_lib': '<(android_sysroot)/usr/lib64',
+              }, {
+                'android_lib': '<(android_sysroot)/usr/lib',
+              }],
+            ],
+            'android_libcpp_include': '<(android_stl)/llvm-libc++/libcxx/include',
+            'android_libcpp_abi_include': '<(android_stl)/llvm-libc++abi/libcxxabi/include',
+            'android_libcpp_libs': '<(android_stl)/llvm-libc++/libs',
+            'android_support_include': '<(android_ndk_root)/sources/android/support/include',
+            'android_sysroot': '<(android_sysroot)',
+          }],
+        ],
+        'android_libcpp_library': 'c++_static',
+      }],  # OS=="android"
+      ['host_clang==1', {
+        'conditions':[
+          ['OS=="android"', {
+            'host_ld': '<!(which ld)',
+            'host_ranlib': '<!(which ranlib)',
+          }],
+        ],
+        'host_cc': '<(clang_dir)/bin/clang',
+        'host_cxx': '<(clang_dir)/bin/clang++',
+      }, {
+        'host_cc': '<!(which gcc)',
+        'host_cxx': '<!(which g++)',
+      }],
+    ],
+    # Default ARM variable settings.
+    'arm_version%': 'default',
+    'arm_fpu%': 'vfpv3',
+    'arm_float_abi%': 'default',
+    'arm_thumb': 'default',
+
+    # Default MIPS variable settings.
+    'mips_arch_variant%': 'r2',
+    # Possible values fp32, fp64, fpxx.
+    # fp32 - 32 32-bit FPU registers are available, doubles are placed in
+    #        register pairs.
+    # fp64 - 32 64-bit FPU registers are available.
+    # fpxx - compatibility mode, it chooses fp32 or fp64 depending on runtime
+    #        detection
+    'mips_fpu_mode%': 'fp32',
+  },
+  'target_defaults': {
+    'variables': {
+      'v8_code%': '<(v8_code)',
+      'clang_warning_flags': [
+        # TODO(thakis): https://crbug.com/604888
+        '-Wno-undefined-var-template',
+      ],
+      'conditions':[
+        ['OS=="android"', {
+          'host_os%': '<(host_os)',
+        }],
+      ],
+    },
+    'includes': [ 'set_clang_warning_flags.gypi', ],
+    'default_configuration': 'Debug',
+    'configurations': {
+      'DebugBaseCommon': {
+        'conditions': [
+          ['OS=="aix"', {
+            'cflags': [ '-g', '-Og', '-gxcoff' ],
+          }, {
+            'cflags': [ '-g', '-O0' ],
+          }],
+        ],
+      },
+      'Optdebug': {
+        'inherit_from': [ 'DebugBaseCommon', 'DebugBase1' ],
+      },
+      'Debug': {
+        # Xcode insists on this empty entry.
+      },
+      'Release': {
+        'cflags+': ['<@(release_extra_cflags)'],
+      },
+      'conditions': [
+        ['OS=="win"', {
+          'Optdebug_x64': {
+            'inherit_from': ['Optdebug'],
+          },
+          'Debug_x64': {
+            'inherit_from': ['Debug'],
+          },
+          'Release_x64': {
+            'inherit_from': ['Release'],
+          },
+        }],
+      ],
+    },
+    'conditions':[
+      ['clang==0', {
+        'cflags+': ['-Wno-sign-compare',],
+      }],
+      ['clang==1 or host_clang==1', {
+        # This is here so that all files get recompiled after a clang roll and
+        # when turning clang on or off.
+        # (defines are passed via the command line, and build systems rebuild
+        # things when their commandline changes). Nothing should ever read this
+        # define.
+        'defines': ['CR_CLANG_REVISION=<!(python <(DEPTH)/tools/clang/scripts/update.py --print-revision)'],
+      }],
+      ['clang==1 and target_arch=="ia32"', {
+        'cflags': ['-mstack-alignment=16', '-mstackrealign'],
+      }],
+      ['fastbuild!=0', {
+        'conditions': [
+          ['OS=="win" and fastbuild==1', {
+            'msvs_settings': {
+              'VCLinkerTool': {
+                # This tells the linker to generate .pdbs, so that
+                # we can get meaningful stack traces.
+                'GenerateDebugInformation': 'true',
+              },
+              'VCCLCompilerTool': {
+                # No debug info to be generated by compiler.
+                'DebugInformationFormat': '0',
+              },
+            },
+          }],
+        ],
+      }],  # fastbuild!=0
+    ],
+    'target_conditions': [
+      ['v8_code == 0', {
+        'defines!': [
+          'DEBUG',
+        ],
+        'conditions': [
+          ['os_posix == 1 and OS != "mac"', {
+            # We don't want to get warnings from third-party code,
+            # so remove any existing warning-enabling flags like -Wall.
+            'cflags!': [
+              '-pedantic',
+              '-Wall',
+              '-Werror',
+              '-Wextra',
+              '-Wshorten-64-to-32',
+            ],
+            'cflags+': [
+              # Clang considers the `register` keyword as deprecated, but
+              # ICU uses it all over the place.
+              '-Wno-deprecated-register',
+              # ICU uses its own deprecated functions.
+              '-Wno-deprecated-declarations',
+              # ICU prefers `a && b || c` over `(a && b) || c`.
+              '-Wno-logical-op-parentheses',
+              # ICU has some `unsigned < 0` checks.
+              '-Wno-tautological-compare',
+              # uresdata.c has switch(RES_GET_TYPE(x)) code. The
+              # RES_GET_TYPE macro returns an UResType enum, but some switch
+              # statement contains case values that aren't part of that
+              # enum (e.g. URES_TABLE32 which is in UResInternalType). This
+              # is on purpose.
+              '-Wno-switch',
+            ],
+            'cflags_cc!': [
+              '-Wnon-virtual-dtor',
+            ],
+          }],
+          ['OS == "mac"', {
+            'xcode_settings': {
+              'GCC_TREAT_WARNINGS_AS_ERRORS': 'NO',    # -Werror
+            },
+          }],
+          ['OS == "win"', {
+            'msvs_settings': {
+              'VCCLCompilerTool': {
+                'WarnAsError': 'false',
+              },
+            },
+          }],
+        ],
+      }],
+    ],
+  },
+  'conditions': [
+    ['os_posix==1 and OS!="mac"', {
+      'target_defaults': {
+        'conditions': [
+          # Common options for AddressSanitizer, LeakSanitizer,
+          # ThreadSanitizer, MemorySanitizer and CFI builds.
+          ['asan==1 or lsan==1 or tsan==1 or msan==1 or cfi_vptr==1', {
+            'target_conditions': [
+              ['_toolset=="target"', {
+                'cflags': [
+                  '-fno-omit-frame-pointer',
+                  '-gline-tables-only',
+                ],
+                'cflags!': [
+                  '-fomit-frame-pointer',
+                ],
+              }],
+            ],
+          }],
+          ['asan==1', {
+            'target_conditions': [
+              ['_toolset=="target"', {
+                'cflags': [
+                  '-fsanitize=address',
+                ],
+                'ldflags': [
+                  '-fsanitize=address',
+                ],
+                'defines': [
+                  'ADDRESS_SANITIZER',
+                ],
+              }],
+            ],
+          }],
+          ['lsan==1', {
+            'target_conditions': [
+              ['_toolset=="target"', {
+                'cflags': [
+                  '-fsanitize=leak',
+                ],
+                'ldflags': [
+                  '-fsanitize=leak',
+                ],
+                'defines': [
+                  'LEAK_SANITIZER',
+                ],
+              }],
+            ],
+          }],
+          ['tsan==1', {
+            'target_conditions': [
+              ['_toolset=="target"', {
+                'cflags': [
+                  '-fsanitize=thread',
+                ],
+                'ldflags': [
+                  '-fsanitize=thread',
+                ],
+                'defines': [
+                  'THREAD_SANITIZER',
+                ],
+              }],
+            ],
+          }],
+          ['msan==1', {
+            'target_conditions': [
+              ['_toolset=="target"', {
+                'cflags': [
+                  '-fsanitize=memory',
+                  '-fsanitize-memory-track-origins=<(msan_track_origins)',
+                  '-fPIC',
+                ],
+                'ldflags': [
+                  '-fsanitize=memory',
+                  '-pie',
+                ],
+                'defines': [
+                  'MEMORY_SANITIZER',
+                ],
+              }],
+            ],
+          }],
+          ['use_custom_libcxx==1', {
+            'dependencies': [
+              '<(DEPTH)/buildtools/third_party/libc++/libc++.gyp:libcxx_proxy',
+            ],
+          }],
+          ['sanitizer_coverage!=0', {
+            'target_conditions': [
+              ['_toolset=="target"', {
+                'cflags': [
+                  '-fsanitize-coverage=<(sanitizer_coverage)',
+                ],
+                'defines': [
+                  'SANITIZER_COVERAGE',
+                ],
+              }],
+            ],
+          }],
+          ['linux_use_bundled_gold==1 and not (clang==0 and use_lto==1)', {
+            # Put our binutils, which contains gold in the search path. We pass
+            # the path to gold to the compiler. gyp leaves unspecified what the
+            # cwd is when running the compiler, so the normal gyp path-munging
+            # fails us. This hack gets the right path.
+            #
+            # Disabled when using GCC LTO because GCC also uses the -B search
+            # path at link time to find "as", and our bundled "as" can only
+            # target x86.
+            'ldflags': [
+              # Note, Chromium allows ia32 host arch as well, we limit this to
+              # x64 in v8.
+              '-B<(base_dir)/third_party/binutils/Linux_x64/Release/bin',
+            ],
+          }],
+          ['sysroot!="" and clang==1', {
+            'target_conditions': [
+              ['_toolset=="target"', {
+                'cflags': [
+                  '--sysroot=<(sysroot)',
+                ],
+                'ldflags': [
+                  '--sysroot=<(sysroot)',
+                  '<!(<(DEPTH)/build/linux/sysroot_ld_path.sh <(sysroot))',
+                ],
+              }]]
+          }],
+        ],
+      },
+    }],
+    ['OS=="mac"', {
+      'target_defaults': {
+       'conditions': [
+          ['asan==1', {
+            'xcode_settings': {
+              # FIXME(machenbach): This is outdated compared to common.gypi.
+              'OTHER_CFLAGS+': [
+                '-fno-omit-frame-pointer',
+                '-gline-tables-only',
+                '-fsanitize=address',
+                '-w',  # http://crbug.com/162783
+              ],
+              'OTHER_CFLAGS!': [
+                '-fomit-frame-pointer',
+              ],
+              'defines': [
+                'ADDRESS_SANITIZER',
+              ],
+            },
+            'dependencies': [
+              '<(DEPTH)/gypfiles/mac/asan.gyp:asan_dynamic_runtime',
+            ],
+            'target_conditions': [
+              ['_type!="static_library"', {
+                'xcode_settings': {'OTHER_LDFLAGS': ['-fsanitize=address']},
+              }],
+            ],
+          }],
+          ['sanitizer_coverage!=0', {
+            'target_conditions': [
+              ['_toolset=="target"', {
+                'cflags': [
+                  '-fsanitize-coverage=<(sanitizer_coverage)',
+                ],
+                'defines': [
+                  'SANITIZER_COVERAGE',
+                ],
+              }],
+            ],
+          }],
+        ],
+      },  # target_defaults
+    }],  # OS=="mac"
+    ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
+       or OS=="netbsd" or OS=="aix"', {
+      'target_defaults': {
+        'cflags': [
+          '-Wall',
+          '<(werror)',
+          '-Wno-unused-parameter',
+          '-pthread',
+          '-pedantic',
+          '-Wmissing-field-initializers',
+          '-Wno-gnu-zero-variadic-macro-arguments',
+        ],
+        'cflags_cc': [
+          '-Wnon-virtual-dtor',
+          '-fno-exceptions',
+          '-fno-rtti',
+          '-std=gnu++11',
+        ],
+        'ldflags': [ '-pthread', ],
+        'conditions': [
+          # Don't warn about TRACE_EVENT_* macros with zero arguments passed to
+          # ##__VA_ARGS__. C99 strict mode prohibits having zero variadic macro
+          # arguments in gcc.
+          [ 'clang==0', {
+            'cflags!' : [
+              '-pedantic' ,
+              # Don't warn about unrecognized command line option.
+              '-Wno-gnu-zero-variadic-macro-arguments',
+            ],
+          }],
+          [ 'clang==1 and (v8_target_arch=="x64" or v8_target_arch=="arm64" \
+            or v8_target_arch=="mips64el")', {
+            'cflags': [ '-Wshorten-64-to-32' ],
+          }],
+          [ 'host_arch=="ppc64" and OS!="aix"', {
+            'cflags': [ '-mminimal-toc' ],
+          }],
+          [ 'visibility=="hidden" and v8_enable_backtrace==0', {
+            'cflags': [ '-fvisibility=hidden' ],
+          }],
+          [ 'component=="shared_library"', {
+            'cflags': [ '-fPIC', ],
+          }],
+          [ 'clang==0 and coverage==1', {
+            'cflags': [ '-fprofile-arcs', '-ftest-coverage'],
+            'ldflags': [ '-fprofile-arcs'],
+          }],
+        ],
+      },
+    }],
+    # 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"
+    #  or OS=="netbsd"'
+    ['OS=="qnx"', {
+      'target_defaults': {
+        'cflags': [
+          '-Wall',
+          '<(werror)',
+          '-Wno-unused-parameter',
+          # Don't warn about the "struct foo f = {0};" initialization pattern.
+          '-Wno-missing-field-initializers',
+          '-Wno-gnu-zero-variadic-macro-arguments',
+        ],
+        'cflags_cc': [
+          '-Wnon-virtual-dtor',
+          '-fno-exceptions',
+          '-fno-rtti',
+          '-std=gnu++11',
+        ],
+        'conditions': [
+          [ 'visibility=="hidden"', {
+            'cflags': [ '-fvisibility=hidden' ],
+          }],
+          [ 'component=="shared_library"', {
+            'cflags': [ '-fPIC' ],
+          }],
+        ],
+        'target_conditions': [
+          [ '_toolset=="host" and host_os=="linux"', {
+            'cflags': [ '-pthread' ],
+            'ldflags': [ '-pthread' ],
+            'libraries': [ '-lrt' ],
+          }],
+          [ '_toolset=="target"', {
+            'cflags': [ '-Wno-psabi' ],
+            'libraries': [ '-lbacktrace', '-lsocket', '-lm' ],
+          }],
+        ],
+      },
+    }],  # OS=="qnx"
+    ['OS=="win"', {
+      'target_defaults': {
+        'defines': [
+          '_CRT_SECURE_NO_DEPRECATE',
+          '_CRT_NONSTDC_NO_DEPRECATE',
+          '_USING_V110_SDK71_',
+        ],
+        'conditions': [
+          ['component=="static_library"', {
+            'defines': [
+              '_HAS_EXCEPTIONS=0',
+            ],
+          }],
+        ],
+        'msvs_cygwin_dirs': ['<(DEPTH)/third_party/cygwin'],
+        'msvs_disabled_warnings': [
+          # C4091: 'typedef ': ignored on left of 'X' when no variable is
+          #                    declared.
+          # This happens in a number of Windows headers. Dumb.
+          4091,
+
+          # C4127: conditional expression is constant
+          # This warning can in theory catch dead code and other problems, but
+          # triggers in far too many desirable cases where the conditional
+          # expression is either set by macros or corresponds some legitimate
+          # compile-time constant expression (due to constant template args,
+          # conditionals comparing the sizes of different types, etc.).  Some of
+          # these can be worked around, but it's not worth it.
+          4127,
+
+          # C4351: new behavior: elements of array 'array' will be default
+          #        initialized
+          # This is a silly "warning" that basically just alerts you that the
+          # compiler is going to actually follow the language spec like it's
+          # supposed to, instead of not following it like old buggy versions
+          # did.  There's absolutely no reason to turn this on.
+          4351,
+
+          # C4355: 'this': used in base member initializer list
+          # It's commonly useful to pass |this| to objects in a class'
+          # initializer list.  While this warning can catch real bugs, most of
+          # the time the constructors in question don't attempt to call methods
+          # on the passed-in pointer (until later), and annotating every legit
+          # usage of this is simply more hassle than the warning is worth.
+          4355,
+
+          # C4503: 'identifier': decorated name length exceeded, name was
+          #        truncated
+          # This only means that some long error messages might have truncated
+          # identifiers in the presence of lots of templates.  It has no effect
+          # on program correctness and there's no real reason to waste time
+          # trying to prevent it.
+          4503,
+
+          # Warning C4589 says: "Constructor of abstract class ignores
+          # initializer for virtual base class." Disable this warning because it
+          # is flaky in VS 2015 RTM. It triggers on compiler generated
+          # copy-constructors in some cases.
+          4589,
+
+          # C4611: interaction between 'function' and C++ object destruction is
+          #        non-portable
+          # This warning is unavoidable when using e.g. setjmp/longjmp.  MSDN
+          # suggests using exceptions instead of setjmp/longjmp for C++, but
+          # Chromium code compiles without exception support.  We therefore have
+          # to use setjmp/longjmp for e.g. JPEG decode error handling, which
+          # means we have to turn off this warning (and be careful about how
+          # object destruction happens in such cases).
+          4611,
+
+          # TODO(jochen): These warnings are level 4. They will be slowly
+          # removed as code is fixed.
+          4100, # Unreferenced formal parameter
+          4121, # Alignment of a member was sensitive to packing
+          4244, # Conversion from 'type1' to 'type2', possible loss of data
+          4302, # Truncation from 'type 1' to 'type 2'
+          4309, # Truncation of constant value
+          4311, # Pointer truncation from 'type' to 'type'
+          4312, # Conversion from 'type1' to 'type2' of greater size
+          4505, # Unreferenced local function has been removed
+          4510, # Default constructor could not be generated
+          4512, # Assignment operator could not be generated
+          4610, # Object can never be instantiated
+          4800, # Forcing value to bool.
+          4838, # Narrowing conversion. Doesn't seem to be very useful.
+          4995, # 'X': name was marked as #pragma deprecated
+          4996, # 'X': was declared deprecated (for GetVersionEx).
+
+          # These are variable shadowing warnings that are new in VS2015. We
+          # should work through these at some point -- they may be removed from
+          # the RTM release in the /W4 set.
+          4456, 4457, 4458, 4459,
+        ],
+        'msvs_settings': {
+          'VCCLCompilerTool': {
+            'MinimalRebuild': 'false',
+            'BufferSecurityCheck': 'true',
+            'EnableFunctionLevelLinking': 'true',
+            'RuntimeTypeInfo': 'false',
+            'WarningLevel': '3',
+            'WarnAsError': 'true',
+            'DebugInformationFormat': '3',
+            'Detect64BitPortabilityProblems': 'false',
+            'conditions': [
+              [ 'msvs_multi_core_compile', {
+                'AdditionalOptions': ['/MP'],
+              }],
+              ['component=="shared_library"', {
+                'ExceptionHandling': '1',  # /EHsc
+              }, {
+                'ExceptionHandling': '0',
+              }],
+            ],
+          },
+          'VCLibrarianTool': {
+            'AdditionalOptions': ['/ignore:4221'],
+            'conditions': [
+              ['v8_target_arch=="x64"', {
+                'TargetMachine': '17',  # x64
+              }, {
+                'TargetMachine': '1',  # ia32
+              }],
+            ],
+          },
+          'VCLinkerTool': {
+            'AdditionalDependencies': [
+              'ws2_32.lib',
+            ],
+            'GenerateDebugInformation': 'true',
+            'MapFileName': '$(OutDir)\\$(TargetName).map',
+            'ImportLibrary': '$(OutDir)\\lib\\$(TargetName).lib',
+            'FixedBaseAddress': '1',
+            # LinkIncremental values:
+            #   0 == default
+            #   1 == /INCREMENTAL:NO
+            #   2 == /INCREMENTAL
+            'LinkIncremental': '1',
+            # SubSystem values:
+            #   0 == not set
+            #   1 == /SUBSYSTEM:CONSOLE
+            #   2 == /SUBSYSTEM:WINDOWS
+            'SubSystem': '1',
+
+            'conditions': [
+              ['v8_enable_i18n_support==1', {
+                'AdditionalDependencies': [
+                  'advapi32.lib',
+                ],
+              }],
+              ['v8_target_arch=="x64"', {
+                'MinimumRequiredVersion': '5.02',  # Server 2003.
+                'TargetMachine': '17',  # x64
+              }, {
+                'MinimumRequiredVersion': '5.01',  # XP.
+                'TargetMachine': '1',  # ia32
+              }],
+            ],
+          },
+          'conditions': [
+            ['clang==1', {
+              'VCCLCompilerTool': {
+                'AdditionalOptions': [
+                  # Don't warn about unused function parameters.
+                  # (This is also used on other platforms.)
+                  '-Wno-unused-parameter',
+                  # Don't warn about the "struct foo f = {0};" initialization
+                  # pattern.
+                  '-Wno-missing-field-initializers',
+
+                  # TODO(hans): Make this list shorter eventually, http://crbug.com/504657
+                  '-Qunused-arguments',  # http://crbug.com/504658
+                  '-Wno-microsoft-enum-value',  # http://crbug.com/505296
+                  '-Wno-unknown-pragmas',  # http://crbug.com/505314
+                  '-Wno-microsoft-cast',  # http://crbug.com/550065
+                ],
+              },
+            }],
+            ['clang==1 and MSVS_VERSION == "2013"', {
+              'VCCLCompilerTool': {
+                'AdditionalOptions': [
+                  '-fmsc-version=1800',
+                ],
+              },
+            }],
+            ['clang==1 and MSVS_VERSION == "2015"', {
+              'VCCLCompilerTool': {
+                'AdditionalOptions': [
+                  '-fmsc-version=1900',
+                ],
+              },
+            }],
+          ],
+        },
+      },
+    }],  # OS=="win"
+    ['OS=="mac"', {
+      'xcode_settings': {
+        'SDKROOT': 'macosx',
+        'SYMROOT': '<(DEPTH)/xcodebuild',
+      },
+      'target_defaults': {
+        'xcode_settings': {
+          'ALWAYS_SEARCH_USER_PATHS': 'NO',
+          'GCC_C_LANGUAGE_STANDARD': 'c99',         # -std=c99
+          'GCC_CW_ASM_SYNTAX': 'NO',                # No -fasm-blocks
+          'GCC_DYNAMIC_NO_PIC': 'NO',               # No -mdynamic-no-pic
+                                                    # (Equivalent to -fPIC)
+          'GCC_ENABLE_CPP_EXCEPTIONS': 'NO',        # -fno-exceptions
+          'GCC_ENABLE_CPP_RTTI': 'NO',              # -fno-rtti
+          'GCC_ENABLE_PASCAL_STRINGS': 'NO',        # No -mpascal-strings
+          # GCC_INLINES_ARE_PRIVATE_EXTERN maps to -fvisibility-inlines-hidden
+          'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES',
+          'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES',      # -fvisibility=hidden
+          'GCC_THREADSAFE_STATICS': 'NO',           # -fno-threadsafe-statics
+          'GCC_WARN_NON_VIRTUAL_DESTRUCTOR': 'YES', # -Wnon-virtual-dtor
+          # MACOSX_DEPLOYMENT_TARGET maps to -mmacosx-version-min
+          'MACOSX_DEPLOYMENT_TARGET': '<(mac_deployment_target)',
+          'PREBINDING': 'NO',                       # No -Wl,-prebind
+          'SYMROOT': '<(DEPTH)/xcodebuild',
+          'USE_HEADERMAP': 'NO',
+          'OTHER_CFLAGS': [
+            '-fno-strict-aliasing',
+          ],
+          'WARNING_CFLAGS': [
+            '-Wall',
+            '-Wendif-labels',
+            '-Wno-unused-parameter',
+            # Don't warn about the "struct foo f = {0};" initialization pattern.
+            '-Wno-missing-field-initializers',
+            '-Wno-gnu-zero-variadic-macro-arguments',
+          ],
+        },
+        'conditions': [
+          ['werror==""', {
+            'xcode_settings': {'GCC_TREAT_WARNINGS_AS_ERRORS': 'NO'},
+          }, {
+            'xcode_settings': {'GCC_TREAT_WARNINGS_AS_ERRORS': 'YES'},
+          }],
+          ['clang==1', {
+            'xcode_settings': {
+              'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
+              'CLANG_CXX_LANGUAGE_STANDARD': 'c++11',  # -std=c++11
+            },
+            'conditions': [
+              ['clang_xcode==0', {
+                'xcode_settings': {
+                  'CC': '<(clang_dir)/bin/clang',
+                  'LDPLUSPLUS': '<(clang_dir)/bin/clang++',
+                  'CLANG_CXX_LIBRARY': 'libc++'
+                },
+              }],
+              ['v8_target_arch=="x64" or v8_target_arch=="arm64" \
+                or v8_target_arch=="mips64el"', {
+                'xcode_settings': {'WARNING_CFLAGS': ['-Wshorten-64-to-32']},
+              }],
+            ],
+          }],
+        ],
+        'target_conditions': [
+          ['_type!="static_library"', {
+            'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-search_paths_first']},
+          }],
+        ],  # target_conditions
+      },  # target_defaults
+    }],  # OS=="mac"
+    ['OS=="android"', {
+      'target_defaults': {
+        'defines': [
+          'ANDROID',
+          'V8_ANDROID_LOG_STDOUT',
+        ],
+        'configurations': {
+          'Release': {
+            'cflags': [
+              '-fomit-frame-pointer',
+            ],
+          },  # Release
+        },  # configurations
+        'cflags': [ '-Wno-abi', '-Wall', '-W', '-Wno-unused-parameter'],
+        'cflags_cc': [ '-Wnon-virtual-dtor', '-fno-rtti', '-fno-exceptions',
+                       '-std=gnu++11' ],
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'cflags!': [
+              '-pthread',  # Not supported by Android toolchain.
+            ],
+            'cflags': [
+              '-ffunction-sections',
+              '-funwind-tables',
+              '-fstack-protector',
+              '-fno-short-enums',
+              '-finline-limit=64',
+              '-Wa,--noexecstack',
+              '--sysroot=<(android_sysroot)',
+            ],
+            'cflags_cc': [
+              '-isystem<(android_libcpp_include)',
+              '-isystem<(android_libcpp_abi_include)',
+              '-isystem<(android_support_include)',
+            ],
+            'defines': [
+              'ANDROID',
+              #'__GNU_SOURCE=1',  # Necessary for clone()
+              'HAVE_OFF64_T',
+              'HAVE_SYS_UIO_H',
+              'ANDROID_BINSIZE_HACK', # Enable temporary hacks to reduce binsize.
+              'ANDROID_NDK_VERSION=<(android_ndk_version)',
+            ],
+            'ldflags!': [
+              '-pthread',  # Not supported by Android toolchain.
+            ],
+            'ldflags': [
+              '-Wl,--no-undefined',
+              '--sysroot=<(android_sysroot)',
+              '-nostdlib',
+            ],
+            'libraries!': [
+                '-lrt',  # librt is built into Bionic.
+                # Not supported by Android toolchain.
+                # Where do these come from?  Can't find references in
+                # any Chromium gyp or gypi file.  Maybe they come from
+                # gyp itself?
+                '-lpthread', '-lnss3', '-lnssutil3', '-lsmime3', '-lplds4', '-lplc4', '-lnspr4',
+              ],
+              'libraries': [
+                '-l<(android_libcpp_library)',
+                '-latomic',
+                # Manually link the libgcc.a that the cross compiler uses.
+                '<!(<(android_toolchain)/*-gcc -print-libgcc-file-name)',
+                '-lc',
+                '-ldl',
+                '-lm',
+            ],
+            'conditions': [
+              ['target_arch == "arm"', {
+                'ldflags': [
+                  # Enable identical code folding to reduce size.
+                  '-Wl,--icf=safe',
+                ],
+              }],
+              ['target_arch=="arm" and arm_version==7', {
+                'cflags': [
+                  '-march=armv7-a',
+                  '-mtune=cortex-a8',
+                  '-mfpu=vfp3',
+                ],
+                'ldflags': [
+                  '-L<(android_libcpp_libs)/armeabi-v7a',
+                ],
+              }],
+              ['target_arch=="arm" and arm_version < 7', {
+                'ldflags': [
+                  '-L<(android_libcpp_libs)/armeabi',
+                ],
+              }],
+              ['target_arch=="x64"', {
+                'ldflags': [
+                  '-L<(android_libcpp_libs)/x86_64',
+                ],
+              }],
+              ['target_arch=="arm64"', {
+                'ldflags': [
+                  '-L<(android_libcpp_libs)/arm64-v8a',
+                ],
+              }],
+              ['target_arch=="ia32" or target_arch=="x87"', {
+                # The x86 toolchain currently has problems with stack-protector.
+                'cflags!': [
+                  '-fstack-protector',
+                ],
+                'cflags': [
+                  '-fno-stack-protector',
+                ],
+                'ldflags': [
+                  '-L<(android_libcpp_libs)/x86',
+                ],
+              }],
+              ['target_arch=="mipsel"', {
+                # The mips toolchain currently has problems with stack-protector.
+                'cflags!': [
+                  '-fstack-protector',
+                  '-U__linux__'
+                ],
+                'cflags': [
+                  '-fno-stack-protector',
+                ],
+                'ldflags': [
+                  '-L<(android_libcpp_libs)/mips',
+                ],
+              }],
+              ['(target_arch=="arm" or target_arch=="arm64" or target_arch=="x64" or target_arch=="ia32") and component!="shared_library"', {
+                'cflags': [
+                  '-fPIE',
+                ],
+                'ldflags': [
+                  '-pie',
+                ],
+              }],
+            ],
+            'target_conditions': [
+              ['_type=="executable"', {
+                'conditions': [
+                  ['target_arch=="arm64" or target_arch=="x64"', {
+                    'ldflags': [
+                      '-Wl,-dynamic-linker,/system/bin/linker64',
+                    ],
+                  }, {
+                    'ldflags': [
+                      '-Wl,-dynamic-linker,/system/bin/linker',
+                    ],
+                  }]
+                ],
+                'ldflags': [
+                  '-Bdynamic',
+                  '-Wl,-z,nocopyreloc',
+                  # crtbegin_dynamic.o should be the last item in ldflags.
+                  '<(android_lib)/crtbegin_dynamic.o',
+                ],
+                'libraries': [
+                  # crtend_android.o needs to be the last item in libraries.
+                  # Do not add any libraries after this!
+                  '<(android_lib)/crtend_android.o',
+                ],
+              }],
+              ['_type=="shared_library"', {
+                'ldflags': [
+                  '-Wl,-shared,-Bsymbolic',
+                  '<(android_lib)/crtbegin_so.o',
+                ],
+              }],
+              ['_type=="static_library"', {
+                'ldflags': [
+                  # Don't export symbols from statically linked libraries.
+                  '-Wl,--exclude-libs=ALL',
+                ],
+              }],
+            ],
+          }],  # _toolset=="target"
+          # Settings for building host targets using the system toolchain.
+          ['_toolset=="host"', {
+            'cflags': [ '-pthread' ],
+            'ldflags': [ '-pthread' ],
+            'ldflags!': [
+              '-Wl,-z,noexecstack',
+              '-Wl,--gc-sections',
+              '-Wl,-O1',
+              '-Wl,--as-needed',
+            ],
+          }],
+        ],  # target_conditions
+      },  # target_defaults
+    }],  # OS=="android"
+    ['OS=="android" and clang==0', {
+      # Hardcode the compiler names in the Makefile so that
+      # it won't depend on the environment at make time.
+      'make_global_settings': [
+        ['LD', '<!(/bin/echo -n <(android_toolchain)/../*/bin/ld)'],
+        ['RANLIB', '<!(/bin/echo -n <(android_toolchain)/../*/bin/ranlib)'],
+        ['CC', '<!(/bin/echo -n <(android_toolchain)/*-gcc)'],
+        ['CXX', '<!(/bin/echo -n <(android_toolchain)/*-g++)'],
+        ['LD.host', '<(host_ld)'],
+        ['RANLIB.host', '<(host_ranlib)'],
+        ['CC.host', '<(host_cc)'],
+        ['CXX.host', '<(host_cxx)'],
+      ],
+    }],
+    ['clang!=1 and host_clang==1 and target_arch!="ia32" and target_arch!="x64"', {
+      'make_global_settings': [
+        ['CC.host', '<(clang_dir)/bin/clang'],
+        ['CXX.host', '<(clang_dir)/bin/clang++'],
+      ],
+    }],
+    ['clang==0 and host_clang==1 and target_arch!="ia32" and target_arch!="x64"', {
+      'target_conditions': [
+        ['_toolset=="host"', {
+          'cflags_cc': [ '-std=gnu++11', ],
+        }],
+      ],
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="host"', { 'cflags!': [ '-Wno-unused-local-typedefs' ]}],
+        ],
+      },
+    }],
+    ['clang==1 and "<(GENERATOR)"=="ninja"', {
+      # See http://crbug.com/110262
+      'target_defaults': {
+        'cflags': [ '-fcolor-diagnostics' ],
+        'xcode_settings': { 'OTHER_CFLAGS': [ '-fcolor-diagnostics' ] },
+      },
+    }],
+    ['clang==1 and ((OS!="mac" and OS!="ios") or clang_xcode==0) '
+        'and OS!="win" and "<(GENERATOR)"=="make"', {
+      'make_global_settings': [
+        ['CC', '<(clang_dir)/bin/clang'],
+        ['CXX', '<(clang_dir)/bin/clang++'],
+        ['CC.host', '$(CC)'],
+        ['CXX.host', '$(CXX)'],
+      ],
+    }],
+    ['clang==1 and ((OS!="mac" and OS!="ios") or clang_xcode==0) '
+        'and OS!="win" and "<(GENERATOR)"=="ninja"', {
+      'make_global_settings': [
+        ['CC', '<(clang_dir)/bin/clang'],
+        ['CXX', '<(clang_dir)/bin/clang++'],
+        ['CC.host', '$(CC)'],
+        ['CXX.host', '$(CXX)'],
+      ],
+    }],
+    ['clang==1 and OS=="win"', {
+      'make_global_settings': [
+        # On Windows, gyp's ninja generator only looks at CC.
+        ['CC', '<(clang_dir)/bin/clang-cl'],
+      ],
+    }],
+    ['OS=="linux" and target_arch=="arm" and host_arch!="arm" and clang==0 and "<(GENERATOR)"=="ninja"', {
+      # Set default ARM cross tools on linux.  These can be overridden
+      # using CC,CXX,CC.host and CXX.host environment variables.
+      'make_global_settings': [
+        ['CC', '<!(which arm-linux-gnueabihf-gcc)'],
+        ['CXX', '<!(which arm-linux-gnueabihf-g++)'],
+        ['CC.host', '<(host_cc)'],
+        ['CXX.host', '<(host_cxx)'],
+      ],
+    }],
+    # TODO(yyanagisawa): supports GENERATOR==make
+    #  make generator doesn't support CC_wrapper without CC
+    #  in make_global_settings yet.
+    ['use_goma==1 and ("<(GENERATOR)"=="ninja" or clang==1)', {
+      'conditions': [
+        ['coverage==1', {
+          # Wrap goma with coverage wrapper.
+          'make_global_settings': [
+            ['CC_wrapper', '<(base_dir)/gypfiles/coverage_wrapper.py <(gomadir)/gomacc'],
+            ['CXX_wrapper', '<(base_dir)/gypfiles/coverage_wrapper.py <(gomadir)/gomacc'],
+            ['CC.host_wrapper', '<(base_dir)/gypfiles/coverage_wrapper.py <(gomadir)/gomacc'],
+            ['CXX.host_wrapper', '<(base_dir)/gypfiles/coverage_wrapper.py <(gomadir)/gomacc'],
+          ],
+        }, {
+          # Use only goma wrapper.
+          'make_global_settings': [
+            ['CC_wrapper', '<(gomadir)/gomacc'],
+            ['CXX_wrapper', '<(gomadir)/gomacc'],
+            ['CC.host_wrapper', '<(gomadir)/gomacc'],
+            ['CXX.host_wrapper', '<(gomadir)/gomacc'],
+          ],
+        }],
+      ],
+    }, {
+      'conditions': [
+        ['coverage==1', {
+          # Use only coverage wrapper.
+          'make_global_settings': [
+            ['CC_wrapper', '<(base_dir)/gypfiles/coverage_wrapper.py'],
+            ['CXX_wrapper', '<(base_dir)/gypfiles/coverage_wrapper.py'],
+            ['CC.host_wrapper', '<(base_dir)/gypfiles/coverage_wrapper.py'],
+            ['CXX.host_wrapper', '<(base_dir)/gypfiles/coverage_wrapper.py'],
+          ],
+        }],
+      ],
+    }],
+    ['use_lto==1', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'cflags': [
+              '-flto',
+            ],
+          }],
+        ],
+      },
+    }],
+    ['use_lto==1 and clang==0', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'cflags': [
+              '-ffat-lto-objects',
+            ],
+          }],
+        ],
+      },
+    }],
+    ['use_lto==1 and clang==1', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'arflags': [
+              '--plugin', '<(clang_dir)/lib/LLVMgold.so',
+            ],
+            # Apply a lower optimization level with lto. Chromium does this
+            # for non-official builds only - a differentiation that doesn't
+            # exist in v8.
+            'ldflags': [
+              '-Wl,--plugin-opt,O1',
+            ],
+          }],
+        ],
+      },
+    }],
+    ['use_lto==1 and clang==0', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'ldflags': [
+              '-flto=32',
+            ],
+          }],
+        ],
+      },
+    }],
+    ['use_lto==1 and clang==1', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'ldflags': [
+              '-flto',
+            ],
+          }],
+        ],
+      },
+    }],
+    ['cfi_diag==1', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'cflags': [
+              '-fno-sanitize-trap=cfi',
+              '-fno-sanitize-recover=cfi',
+            ],
+            'cflags_cc!': [
+              '-fno-rtti',
+            ],
+            'cflags!': [
+              '-fno-rtti',
+            ],
+            'ldflags': [
+              '-fno-sanitize-trap=cfi',
+              '-fno-sanitize-recover=cfi',
+            ],
+          }],
+        ],
+      },
+    }],
+    ['cfi_vptr==1', {
+      'target_defaults': {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'cflags': [
+              '-fsanitize=cfi-vcall',
+              '-fsanitize=cfi-derived-cast',
+              '-fsanitize=cfi-unrelated-cast',
+              '-fsanitize-blacklist=<(cfi_blacklist)',
+            ],
+            'ldflags': [
+              '-fsanitize=cfi-vcall',
+              '-fsanitize=cfi-derived-cast',
+              '-fsanitize=cfi-unrelated-cast',
+            ],
+          }],
+        ],
+      },
+    }],
+  ],
+}
diff --git a/gypfiles/toolchain.gypi b/gypfiles/toolchain.gypi
new file mode 100644
index 0000000..814d565
--- /dev/null
+++ b/gypfiles/toolchain.gypi
@@ -0,0 +1,1400 @@
+# 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.
+
+# Shared definitions for all V8-related targets.
+
+{
+  'variables': {
+    'msvs_use_common_release': 0,
+    'clang%': 0,
+    'asan%': 0,
+    'lsan%': 0,
+    'msan%': 0,
+    'tsan%': 0,
+    'ubsan%': 0,
+    'ubsan_vptr%': 0,
+    'has_valgrind%': 0,
+    'coverage%': 0,
+    'v8_target_arch%': '<(target_arch)',
+    'v8_host_byteorder%': '<!(python -c "import sys; print sys.byteorder")',
+    # Native Client builds currently use the V8 ARM JIT and
+    # arm/simulator-arm.cc to defer the significant effort required
+    # for NaCl JIT support. The nacl_target_arch variable provides
+    # the 'true' target arch for places in this file that need it.
+    # TODO(bradchen): get rid of nacl_target_arch when someday
+    # NaCl V8 builds stop using the ARM simulator
+    'nacl_target_arch%': 'none',     # must be set externally
+
+    # Setting 'v8_can_use_vfp32dregs' to 'true' will cause V8 to use the VFP
+    # registers d16-d31 in the generated code, both in the snapshot and for the
+    # ARM target. Leaving the default value of 'false' will avoid the use of
+    # these registers in the snapshot and use CPU feature probing when running
+    # on the target.
+    'v8_can_use_vfp32dregs%': 'false',
+    'arm_test_noprobe%': 'off',
+
+    # Similar to vfp but on MIPS.
+    'v8_can_use_fpu_instructions%': 'true',
+
+    # Similar to the ARM hard float ABI but on MIPS.
+    'v8_use_mips_abi_hardfloat%': 'true',
+
+    # Force disable libstdc++ debug mode.
+    'disable_glibcxx_debug%': 0,
+
+    'v8_enable_backtrace%': 0,
+
+    # Enable profiling support. Only required on Windows.
+    'v8_enable_prof%': 0,
+
+    # Some versions of GCC 4.5 seem to need -fno-strict-aliasing.
+    'v8_no_strict_aliasing%': 0,
+
+    # Chrome needs this definition unconditionally. For standalone V8 builds,
+    # it's handled in gypfiles/standalone.gypi.
+    'want_separate_host_toolset%': 1,
+
+    # Toolset the shell binary should be compiled for. Possible values are
+    # 'host' and 'target'.
+    # The setting is ignored if want_separate_host_toolset is 0.
+    'v8_toolset_for_shell%': 'target',
+
+    'host_os%': '<(OS)',
+    'werror%': '-Werror',
+    # For a shared library build, results in "libv8-<(soname_version).so".
+    'soname_version%': '',
+
+    # Allow to suppress the array bounds warning (default is no suppression).
+    'wno_array_bounds%': '',
+
+    # Override where to find binutils
+    'binutils_dir%': '',
+
+    'conditions': [
+      ['OS=="linux" and host_arch=="x64"', {
+        'binutils_dir%': 'third_party/binutils/Linux_x64/Release/bin',
+      }],
+      ['OS=="linux" and host_arch=="ia32"', {
+        'binutils_dir%': 'third_party/binutils/Linux_ia32/Release/bin',
+      }],
+
+      # linux_use_bundled_gold: whether to use the gold linker binary checked
+      # into third_party/binutils.  Force this off via GYP_DEFINES when you
+      # are using a custom toolchain and need to control -B in ldflags.
+      # Do not use 32-bit gold on 32-bit hosts as it runs out address space
+      # for component=static_library builds.
+      ['OS=="linux" and (target_arch=="x64" or target_arch=="arm")', {
+        'linux_use_bundled_gold%': 1,
+      }, {
+        'linux_use_bundled_gold%': 0,
+      }],
+      # linux_use_bundled_binutils: whether to use the binary binutils
+      # checked into third_party/binutils.  These are not multi-arch so cannot
+      # be used except on x86 and x86-64 (the only two architectures which
+      # are currently checke in).  Force this off via GYP_DEFINES when you
+      # are using a custom toolchain and need to control -B in cflags.
+      ['OS=="linux" and (target_arch=="ia32" or target_arch=="x64")', {
+        'linux_use_bundled_binutils%': 1,
+      }, {
+        'linux_use_bundled_binutils%': 0,
+      }],
+      # linux_use_gold_flags: whether to use build flags that rely on gold.
+      # On by default for x64 Linux.
+      ['OS=="linux" and target_arch=="x64"', {
+        'linux_use_gold_flags%': 1,
+      }, {
+        'linux_use_gold_flags%': 0,
+      }],
+    ],
+
+    # Link-Time Optimizations
+    'use_lto%': 0,
+
+    # Indicates if gcmole tools are downloaded by a hook.
+    'gcmole%': 0,
+  },
+  'conditions': [
+    ['host_arch=="ia32" or host_arch=="x64" or \
+      host_arch=="ppc" or host_arch=="ppc64" or \
+      host_arch=="s390" or host_arch=="s390x" or \
+      clang==1', {
+      'variables': {
+        'host_cxx_is_biarch%': 1,
+       },
+     }, {
+      'variables': {
+        'host_cxx_is_biarch%': 0,
+      },
+    }],
+    ['target_arch=="ia32" or target_arch=="x64" or target_arch=="x87" or \
+      target_arch=="ppc" or target_arch=="ppc64" or target_arch=="s390" or \
+      target_arch=="s390x" or clang==1', {
+      'variables': {
+        'target_cxx_is_biarch%': 1,
+       },
+     }, {
+      'variables': {
+        'target_cxx_is_biarch%': 0,
+      },
+    }],
+  ],
+  'target_defaults': {
+    'conditions': [
+      ['v8_target_arch=="arm"', {
+        'defines': [
+          'V8_TARGET_ARCH_ARM',
+        ],
+        'conditions': [
+          [ 'arm_version==7 or arm_version=="default"', {
+            'defines': [
+              'CAN_USE_ARMV7_INSTRUCTIONS',
+            ],
+          }],
+          [ 'arm_fpu=="vfpv3-d16" or arm_fpu=="default"', {
+            'defines': [
+              'CAN_USE_VFP3_INSTRUCTIONS',
+            ],
+          }],
+          [ 'arm_fpu=="vfpv3"', {
+            'defines': [
+              'CAN_USE_VFP3_INSTRUCTIONS',
+              'CAN_USE_VFP32DREGS',
+            ],
+          }],
+          [ 'arm_fpu=="neon"', {
+            'defines': [
+              'CAN_USE_VFP3_INSTRUCTIONS',
+              'CAN_USE_VFP32DREGS',
+              'CAN_USE_NEON',
+            ],
+          }],
+          [ 'arm_test_noprobe=="on"', {
+            'defines': [
+              'ARM_TEST_NO_FEATURE_PROBE',
+            ],
+          }],
+        ],
+        'target_conditions': [
+          ['_toolset=="host"', {
+            'conditions': [
+              ['v8_target_arch==host_arch', {
+                # Host built with an Arm CXX compiler.
+                'conditions': [
+                  [ 'arm_version==7', {
+                    'cflags': ['-march=armv7-a',],
+                  }],
+                  [ 'arm_version==7 or arm_version=="default"', {
+                    'conditions': [
+                      [ 'arm_fpu!="default"', {
+                        'cflags': ['-mfpu=<(arm_fpu)',],
+                      }],
+                    ],
+                  }],
+                  [ 'arm_float_abi!="default"', {
+                    'cflags': ['-mfloat-abi=<(arm_float_abi)',],
+                  }],
+                  [ 'arm_thumb==1', {
+                    'cflags': ['-mthumb',],
+                  }],
+                  [ 'arm_thumb==0', {
+                    'cflags': ['-marm',],
+                  }],
+                ],
+              }, {
+                # 'v8_target_arch!=host_arch'
+                # Host not built with an Arm CXX compiler (simulator build).
+                'conditions': [
+                  [ 'arm_float_abi=="hard"', {
+                    'defines': [
+                      'USE_EABI_HARDFLOAT=1',
+                    ],
+                  }],
+                  [ 'arm_float_abi=="softfp" or arm_float_abi=="default"', {
+                    'defines': [
+                      'USE_EABI_HARDFLOAT=0',
+                    ],
+                  }],
+                ],
+              }],
+            ],
+          }],  # _toolset=="host"
+          ['_toolset=="target"', {
+            'conditions': [
+              ['v8_target_arch==target_arch', {
+                # Target built with an Arm CXX compiler.
+                'conditions': [
+                  [ 'arm_version==7', {
+                    'cflags': ['-march=armv7-a',],
+                  }],
+                  [ 'arm_version==7 or arm_version=="default"', {
+                    'conditions': [
+                      [ 'arm_fpu!="default"', {
+                        'cflags': ['-mfpu=<(arm_fpu)',],
+                      }],
+                    ],
+                  }],
+                  [ 'arm_float_abi!="default"', {
+                    'cflags': ['-mfloat-abi=<(arm_float_abi)',],
+                  }],
+                  [ 'arm_thumb==1', {
+                    'cflags': ['-mthumb',],
+                  }],
+                  [ 'arm_thumb==0', {
+                    'cflags': ['-marm',],
+                  }],
+                ],
+              }, {
+                # 'v8_target_arch!=target_arch'
+                # Target not built with an Arm CXX compiler (simulator build).
+                'conditions': [
+                  [ 'arm_float_abi=="hard"', {
+                    'defines': [
+                      'USE_EABI_HARDFLOAT=1',
+                    ],
+                  }],
+                  [ 'arm_float_abi=="softfp" or arm_float_abi=="default"', {
+                    'defines': [
+                      'USE_EABI_HARDFLOAT=0',
+                    ],
+                  }],
+                ],
+              }],
+              # Disable GCC LTO for v8
+              # v8 is optimized for speed. Because GCC LTO merges flags at link
+              # time, we disable LTO to prevent any -O2 flags from taking
+              # precedence over v8's -Os flag. However, LLVM LTO does not work
+              # this way so we keep LTO enabled under LLVM.
+              ['clang==0 and use_lto==1', {
+                'cflags!': [
+                  '-flto',
+                  '-ffat-lto-objects',
+                ],
+              }],
+            ],
+          }],  # _toolset=="target"
+        ],
+      }],  # v8_target_arch=="arm"
+      ['v8_target_arch=="arm64"', {
+        'defines': [
+          'V8_TARGET_ARCH_ARM64',
+        ],
+      }],
+      ['v8_target_arch=="s390" or v8_target_arch=="s390x"', {
+        'defines': [
+          'V8_TARGET_ARCH_S390',
+        ],
+        'conditions': [
+          ['v8_target_arch=="s390x"', {
+            'defines': [
+              'V8_TARGET_ARCH_S390X',
+            ],
+          }],
+          ['v8_host_byteorder=="little"', {
+            'defines': [
+              'V8_TARGET_ARCH_S390_LE_SIM',
+            ],
+          }],
+          ],
+      }],  # s390
+      ['v8_target_arch=="ppc" or v8_target_arch=="ppc64"', {
+        'defines': [
+          'V8_TARGET_ARCH_PPC',
+        ],
+        'conditions': [
+          ['v8_target_arch=="ppc64"', {
+            'defines': [
+              'V8_TARGET_ARCH_PPC64',
+            ],
+          }],
+          ['v8_host_byteorder=="little"', {
+            'defines': [
+              'V8_TARGET_ARCH_PPC_LE',
+            ],
+          }],
+          ['v8_host_byteorder=="big"', {
+            'defines': [
+              'V8_TARGET_ARCH_PPC_BE',
+            ],
+            'conditions': [
+              ['OS=="aix"', {
+                # Work around AIX ceil, trunc and round oddities.
+                'cflags': [ '-mcpu=power5+ -mfprnd' ],
+              }],
+              ['OS=="aix"', {
+                # Work around AIX assembler popcntb bug.
+                'cflags': [ '-mno-popcntb' ],
+              }],
+            ],
+          }],
+        ],
+      }],  # ppc
+      ['v8_target_arch=="ia32"', {
+        'defines': [
+          'V8_TARGET_ARCH_IA32',
+        ],
+      }],  # v8_target_arch=="ia32"
+      ['v8_target_arch=="x87"', {
+        'defines': [
+          'V8_TARGET_ARCH_X87',
+        ],
+        'cflags': ['-march=i586'],
+      }],  # v8_target_arch=="x87"
+      ['(v8_target_arch=="mips" or v8_target_arch=="mipsel" \
+        or v8_target_arch=="mips64" or v8_target_arch=="mips64el") \
+         and v8_target_arch==target_arch', {
+        'target_conditions': [
+          ['_toolset=="target"', {
+            # Target built with a Mips CXX compiler.
+            'variables': {
+              'ldso_path%': '<!(/bin/echo -n $LDSO_PATH)',
+              'ld_r_path%': '<!(/bin/echo -n $LD_R_PATH)',
+            },
+            'conditions': [
+              ['ldso_path!=""', {
+                'ldflags': ['-Wl,--dynamic-linker=<(ldso_path)'],
+              }],
+              ['ld_r_path!=""', {
+                'ldflags': ['-Wl,--rpath=<(ld_r_path)'],
+              }],
+              [ 'clang==1', {
+                'cflags': ['-integrated-as'],
+              }],
+            ],
+          }],
+        ],
+      }],
+      ['v8_target_arch=="mips"', {
+        'defines': [
+          'V8_TARGET_ARCH_MIPS',
+        ],
+        'conditions': [
+          [ 'v8_can_use_fpu_instructions=="true"', {
+            'defines': [
+              'CAN_USE_FPU_INSTRUCTIONS',
+            ],
+          }],
+          [ 'v8_use_mips_abi_hardfloat=="true"', {
+            'defines': [
+              '__mips_hard_float=1',
+              'CAN_USE_FPU_INSTRUCTIONS',
+            ],
+          }, {
+            'defines': [
+              '__mips_soft_float=1'
+            ]
+          }],
+        ],
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'conditions': [
+              ['v8_target_arch==target_arch', {
+                # Target built with a Mips CXX compiler.
+                'cflags': [
+                  '-EB',
+                  '-Wno-error=array-bounds',  # Workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56273
+                ],
+                'ldflags': ['-EB'],
+                'conditions': [
+                  [ 'v8_use_mips_abi_hardfloat=="true"', {
+                    'cflags': ['-mhard-float'],
+                    'ldflags': ['-mhard-float'],
+                  }, {
+                    'cflags': ['-msoft-float'],
+                    'ldflags': ['-msoft-float'],
+                  }],
+                  ['mips_arch_variant=="r6"', {
+                    'defines': [
+                      '_MIPS_ARCH_MIPS32R6',
+                      'FPU_MODE_FP64',
+                    ],
+                    'cflags!': ['-mfp32', '-mfpxx'],
+                    'conditions': [
+                      [ 'clang==0', {
+                        'cflags': ['-Wa,-mips32r6'],
+                      }],
+                    ],
+                    'cflags': ['-mips32r6'],
+                    'ldflags': ['-mips32r6'],
+                  }],
+                  ['mips_arch_variant=="r2"', {
+                    'conditions': [
+                      [ 'mips_fpu_mode=="fp64"', {
+                        'defines': [
+                          '_MIPS_ARCH_MIPS32R2',
+                          'FPU_MODE_FP64',
+                        ],
+                        'cflags': ['-mfp64'],
+                      }],
+                      ['mips_fpu_mode=="fpxx"', {
+                        'defines': [
+                          '_MIPS_ARCH_MIPS32R2',
+                          'FPU_MODE_FPXX',
+                        ],
+                        'cflags': ['-mfpxx'],
+                      }],
+                      ['mips_fpu_mode=="fp32"', {
+                        'defines': [
+                          '_MIPS_ARCH_MIPS32R2',
+                          'FPU_MODE_FP32',
+                        ],
+                        'cflags': ['-mfp32'],
+                      }],
+                      [ 'clang==0', {
+                        'cflags': ['-Wa,-mips32r2'],
+                      }],
+                    ],
+                    'cflags': ['-mips32r2'],
+                    'ldflags': ['-mips32r2'],
+                  }],
+                  ['mips_arch_variant=="r1"', {
+                    'defines': [
+                      'FPU_MODE_FP32',
+                    ],
+                    'cflags!': ['-mfp64', '-mfpxx'],
+                    'conditions': [
+                      [ 'clang==0', {
+                        'cflags': ['-Wa,-mips32'],
+                      }],
+                    ],
+                    'cflags': ['-mips32'],
+                    'ldflags': ['-mips32'],
+                  }],
+                  ['mips_arch_variant=="rx"', {
+                    'defines': [
+                      '_MIPS_ARCH_MIPS32RX',
+                      'FPU_MODE_FPXX',
+                    ],
+                    'cflags!': ['-mfp64', '-mfp32'],
+                    'conditions': [
+                      [ 'clang==0', {
+                        'cflags': ['-Wa,-mips32'],
+                      }],
+                    ],
+                    'cflags': ['-mips32', '-mfpxx'],
+                    'ldflags': ['-mips32'],
+                  }],
+                ],
+              }, {
+                # 'v8_target_arch!=target_arch'
+                # Target not built with an MIPS CXX compiler (simulator build).
+                'conditions': [
+                  ['mips_arch_variant=="r6"', {
+                    'defines': [
+                      '_MIPS_ARCH_MIPS32R6',
+                      'FPU_MODE_FP64',
+                    ],
+                  }],
+                  ['mips_arch_variant=="r2"', {
+                    'conditions': [
+                      [ 'mips_fpu_mode=="fp64"', {
+                        'defines': [
+                          '_MIPS_ARCH_MIPS32R2',
+                          'FPU_MODE_FP64',
+                        ],
+                      }],
+                      ['mips_fpu_mode=="fpxx"', {
+                        'defines': [
+                          '_MIPS_ARCH_MIPS32R2',
+                          'FPU_MODE_FPXX',
+                        ],
+                      }],
+                      ['mips_fpu_mode=="fp32"', {
+                        'defines': [
+                          '_MIPS_ARCH_MIPS32R2',
+                          'FPU_MODE_FP32',
+                        ],
+                      }],
+                    ],
+                  }],
+                  ['mips_arch_variant=="r1"', {
+                    'defines': [
+                      'FPU_MODE_FP32',
+                    ],
+                  }],
+                  ['mips_arch_variant=="rx"', {
+                    'defines': [
+                      '_MIPS_ARCH_MIPS32RX',
+                      'FPU_MODE_FPXX',
+                    ],
+                  }],
+                ],
+              }],
+            ],
+          }],  #_toolset=="target"
+          ['_toolset=="host"', {
+            'conditions': [
+              ['mips_arch_variant=="rx"', {
+                'defines': [
+                  '_MIPS_ARCH_MIPS32RX',
+                  'FPU_MODE_FPXX',
+                ],
+              }],
+              ['mips_arch_variant=="r6"', {
+                'defines': [
+                  '_MIPS_ARCH_MIPS32R6',
+                  'FPU_MODE_FP64',
+                ],
+              }],
+              ['mips_arch_variant=="r2"', {
+                'conditions': [
+                  ['mips_fpu_mode=="fp64"', {
+                    'defines': [
+                      '_MIPS_ARCH_MIPS32R2',
+                      'FPU_MODE_FP64',
+                    ],
+                  }],
+                  ['mips_fpu_mode=="fpxx"', {
+                    'defines': [
+                      '_MIPS_ARCH_MIPS32R2',
+                      'FPU_MODE_FPXX',
+                    ],
+                  }],
+                  ['mips_fpu_mode=="fp32"', {
+                    'defines': [
+                      '_MIPS_ARCH_MIPS32R2',
+                      'FPU_MODE_FP32'
+                    ],
+                  }],
+                ],
+              }],
+              ['mips_arch_variant=="r1"', {
+                'defines': ['FPU_MODE_FP32',],
+              }],
+            ]
+          }],  #_toolset=="host"
+        ],
+      }],  # v8_target_arch=="mips"
+      ['v8_target_arch=="mipsel"', {
+        'defines': [
+          'V8_TARGET_ARCH_MIPS',
+        ],
+        'conditions': [
+          [ 'v8_can_use_fpu_instructions=="true"', {
+            'defines': [
+              'CAN_USE_FPU_INSTRUCTIONS',
+            ],
+          }],
+          [ 'v8_use_mips_abi_hardfloat=="true"', {
+            'defines': [
+              '__mips_hard_float=1',
+              'CAN_USE_FPU_INSTRUCTIONS',
+            ],
+          }, {
+            'defines': [
+              '__mips_soft_float=1'
+            ],
+          }],
+        ],
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'conditions': [
+              ['v8_target_arch==target_arch', {
+                # Target built with a Mips CXX compiler.
+                'cflags': [
+                  '-EL',
+                  '-Wno-error=array-bounds',  # Workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56273
+                ],
+                'ldflags': ['-EL'],
+                'conditions': [
+                  [ 'v8_use_mips_abi_hardfloat=="true"', {
+                    'cflags': ['-mhard-float'],
+                    'ldflags': ['-mhard-float'],
+                  }, {
+                    'cflags': ['-msoft-float'],
+                    'ldflags': ['-msoft-float'],
+                  }],
+                  ['mips_arch_variant=="r6"', {
+                    'defines': [
+                      '_MIPS_ARCH_MIPS32R6',
+                      'FPU_MODE_FP64',
+                    ],
+                    'cflags!': ['-mfp32', '-mfpxx'],
+                    'conditions': [
+                      [ 'clang==0', {
+                        'cflags': ['-Wa,-mips32r6'],
+                      }],
+                    ],
+                    'cflags': ['-mips32r6'],
+                    'ldflags': ['-mips32r6'],
+                  }],
+                  ['mips_arch_variant=="r2"', {
+                    'conditions': [
+                      [ 'mips_fpu_mode=="fp64"', {
+                        'defines': [
+                          '_MIPS_ARCH_MIPS32R2',
+                          'FPU_MODE_FP64',
+                        ],
+                        'cflags': ['-mfp64'],
+                      }],
+                      ['mips_fpu_mode=="fpxx"', {
+                        'defines': [
+                          '_MIPS_ARCH_MIPS32R2',
+                          'FPU_MODE_FPXX',
+                        ],
+                        'cflags': ['-mfpxx'],
+                      }],
+                      ['mips_fpu_mode=="fp32"', {
+                        'defines': [
+                          '_MIPS_ARCH_MIPS32R2',
+                          'FPU_MODE_FP32',
+                        ],
+                        'cflags': ['-mfp32'],
+                      }],
+                      [ 'clang==0', {
+                        'cflags': ['-Wa,-mips32r2'],
+                      }],
+                    ],
+                    'cflags': ['-mips32r2'],
+                    'ldflags': ['-mips32r2'],
+                  }],
+                  ['mips_arch_variant=="r1"', {
+                    'defines': [
+                      'FPU_MODE_FP32',
+                    ],
+                    'cflags!': ['-mfp64', '-mfpxx'],
+                    'conditions': [
+                      [ 'clang==0', {
+                        'cflags': ['-Wa,-mips32'],
+                      }],
+                    ],
+                    'cflags': ['-mips32'],
+                    'ldflags': ['-mips32'],
+                  }],
+                  ['mips_arch_variant=="rx"', {
+                    'defines': [
+                      '_MIPS_ARCH_MIPS32RX',
+                      'FPU_MODE_FPXX',
+                    ],
+                    'cflags!': ['-mfp64', '-mfp32'],
+                    'conditions': [
+                      [ 'clang==0', {
+                        'cflags': ['-Wa,-mips32'],
+                      }],
+                    ],
+                    'cflags': ['-mips32', '-mfpxx'],
+                    'ldflags': ['-mips32'],
+                  }],
+                  ['mips_arch_variant=="loongson"', {
+                    'defines': [
+                      '_MIPS_ARCH_LOONGSON',
+                      'FPU_MODE_FP32',
+                    ],
+                    'cflags!': ['-mfp64', '-mfpxx'],
+                    'conditions': [
+                      [ 'clang==0', {
+                        'cflags': ['-Wa,-mips3'],
+                      }],
+                    ],
+                    'cflags': ['-mips3', '-mfp32'],
+                  }],
+                ],
+              }, {
+                # 'v8_target_arch!=target_arch'
+                # Target not built with an MIPS CXX compiler (simulator build).
+                'conditions': [
+                  ['mips_arch_variant=="r6"', {
+                    'defines': [
+                      '_MIPS_ARCH_MIPS32R6',
+                      'FPU_MODE_FP64',
+                    ],
+                  }],
+                  ['mips_arch_variant=="r2"', {
+                    'conditions': [
+                      [ 'mips_fpu_mode=="fp64"', {
+                        'defines': [
+                          '_MIPS_ARCH_MIPS32R2',
+                          'FPU_MODE_FP64',
+                        ],
+                      }],
+                      ['mips_fpu_mode=="fpxx"', {
+                        'defines': [
+                          '_MIPS_ARCH_MIPS32R2',
+                          'FPU_MODE_FPXX',
+                        ],
+                      }],
+                      ['mips_fpu_mode=="fp32"', {
+                        'defines': [
+                          '_MIPS_ARCH_MIPS32R2',
+                          'FPU_MODE_FP32',
+                        ],
+                      }],
+                    ],
+                  }],
+                  ['mips_arch_variant=="r1"', {
+                    'defines': [
+                      'FPU_MODE_FP32',
+                    ],
+                  }],
+                  ['mips_arch_variant=="rx"', {
+                    'defines': [
+                      '_MIPS_ARCH_MIPS32RX',
+                      'FPU_MODE_FPXX',
+                    ],
+                  }],
+                  ['mips_arch_variant=="loongson"', {
+                    'defines': [
+                      '_MIPS_ARCH_LOONGSON',
+                      'FPU_MODE_FP32',
+                    ],
+                  }],
+                ],
+              }],
+            ],
+          }], #_toolset=="target
+          ['_toolset=="host"', {
+            'conditions': [
+              ['mips_arch_variant=="rx"', {
+                'defines': [
+                  '_MIPS_ARCH_MIPS32RX',
+                  'FPU_MODE_FPXX',
+                ],
+              }],
+              ['mips_arch_variant=="r6"', {
+                'defines': [
+                  '_MIPS_ARCH_MIPS32R6',
+                  'FPU_MODE_FP64',
+                ],
+              }],
+              ['mips_arch_variant=="r2"', {
+                'conditions': [
+                  ['mips_fpu_mode=="fp64"', {
+                    'defines': [
+                      '_MIPS_ARCH_MIPS32R2',
+                      'FPU_MODE_FP64',
+                    ],
+                  }],
+                  ['mips_fpu_mode=="fpxx"', {
+                    'defines': [
+                      '_MIPS_ARCH_MIPS32R2',
+                      'FPU_MODE_FPXX',
+                    ],
+                  }],
+                  ['mips_fpu_mode=="fp32"', {
+                    'defines': [
+                      '_MIPS_ARCH_MIPS32R2',
+                      'FPU_MODE_FP32'
+                    ],
+                  }],
+                ],
+              }],
+              ['mips_arch_variant=="r1"', {
+                'defines': ['FPU_MODE_FP32',],
+              }],
+              ['mips_arch_variant=="loongson"', {
+                'defines': [
+                  '_MIPS_ARCH_LOONGSON',
+                  'FPU_MODE_FP32',
+                ],
+              }],
+            ]
+          }],
+        ],
+      }],  # v8_target_arch=="mipsel"
+      ['v8_target_arch=="mips64el" or v8_target_arch=="mips64"', {
+        'defines': [
+          'V8_TARGET_ARCH_MIPS64',
+        ],
+        'conditions': [
+          [ 'v8_can_use_fpu_instructions=="true"', {
+            'defines': [
+              'CAN_USE_FPU_INSTRUCTIONS',
+            ],
+          }],
+          [ 'v8_host_byteorder=="little"', {
+            'defines': [
+              'V8_TARGET_ARCH_MIPS64_LE',
+            ],
+          }],
+          [ 'v8_host_byteorder=="big"', {
+            'defines': [
+              'V8_TARGET_ARCH_MIPS64_BE',
+            ],
+          }],
+          [ 'v8_use_mips_abi_hardfloat=="true"', {
+            'defines': [
+              '__mips_hard_float=1',
+              'CAN_USE_FPU_INSTRUCTIONS',
+            ],
+          }, {
+            'defines': [
+              '__mips_soft_float=1'
+            ],
+          }],
+         ],
+        'target_conditions': [
+          ['_toolset=="target"', {
+            'conditions': [
+              ['v8_target_arch==target_arch', {
+                'cflags': [
+                  '-Wno-error=array-bounds',  # Workaround https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56273
+                ],
+                'conditions': [
+                  ['v8_target_arch=="mips64el"', {
+                    'cflags': ['-EL'],
+                    'ldflags': ['-EL'],
+                  }],
+                  ['v8_target_arch=="mips64"', {
+                    'cflags': ['-EB'],
+                    'ldflags': ['-EB'],
+                  }],
+                  [ 'v8_use_mips_abi_hardfloat=="true"', {
+                    'cflags': ['-mhard-float'],
+                    'ldflags': ['-mhard-float'],
+                  }, {
+                    'cflags': ['-msoft-float'],
+                    'ldflags': ['-msoft-float'],
+                  }],
+                  ['mips_arch_variant=="r6"', {
+                    'defines': ['_MIPS_ARCH_MIPS64R6',],
+                    'conditions': [
+                      [ 'clang==0', {
+                        'cflags': ['-Wa,-mips64r6'],
+                      }],
+                    ],
+                    'cflags': ['-mips64r6', '-mabi=64'],
+                    'ldflags': ['-mips64r6', '-mabi=64'],
+                  }],
+                  ['mips_arch_variant=="r2"', {
+                    'defines': ['_MIPS_ARCH_MIPS64R2',],
+                    'conditions': [
+                      [ 'clang==0', {
+                        'cflags': ['-Wa,-mips64r2'],
+                      }],
+                    ],
+                    'cflags': ['-mips64r2', '-mabi=64'],
+                    'ldflags': ['-mips64r2', '-mabi=64'],
+                  }],
+                ],
+              }, {
+                # 'v8_target_arch!=target_arch'
+                # Target not built with an MIPS CXX compiler (simulator build).
+                'conditions': [
+                  ['mips_arch_variant=="r6"', {
+                    'defines': ['_MIPS_ARCH_MIPS64R6',],
+                  }],
+                  ['mips_arch_variant=="r2"', {
+                    'defines': ['_MIPS_ARCH_MIPS64R2',],
+                  }],
+                ],
+              }],
+            ],
+          }],  #'_toolset=="target"
+          ['_toolset=="host"', {
+            'conditions': [
+              ['mips_arch_variant=="r6"', {
+                'defines': ['_MIPS_ARCH_MIPS64R6',],
+              }],
+              ['mips_arch_variant=="r2"', {
+                'defines': ['_MIPS_ARCH_MIPS64R2',],
+              }],
+            ],
+          }],  #'_toolset=="host"
+        ],
+      }],  # v8_target_arch=="mips64el"
+      ['v8_target_arch=="x64"', {
+        'defines': [
+          'V8_TARGET_ARCH_X64',
+        ],
+        'xcode_settings': {
+          'ARCHS': [ 'x86_64' ],
+        },
+        'msvs_settings': {
+          'VCLinkerTool': {
+            'StackReserveSize': '2097152',
+          },
+        },
+        'msvs_configuration_platform': 'x64',
+      }],  # v8_target_arch=="x64"
+      ['v8_target_arch=="x32"', {
+        'defines': [
+          # x32 port shares the source code with x64 port.
+          'V8_TARGET_ARCH_X64',
+          'V8_TARGET_ARCH_32_BIT',
+        ],
+        'cflags': [
+          '-mx32',
+          # Inhibit warning if long long type is used.
+          '-Wno-long-long',
+        ],
+        'ldflags': [
+          '-mx32',
+        ],
+      }],  # v8_target_arch=="x32"
+      ['linux_use_gold_flags==1', {
+        # Newer gccs and clangs support -fuse-ld, use the flag to force gold
+        # selection.
+        # gcc -- http://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Optimize-Options.html
+        'ldflags': [ '-fuse-ld=gold', ],
+      }],
+      ['linux_use_bundled_binutils==1', {
+        'cflags': [
+          '-B<!(cd <(DEPTH) && pwd -P)/<(binutils_dir)',
+        ],
+      }],
+      ['linux_use_bundled_gold==1', {
+        # Put our binutils, which contains gold in the search path. We pass
+        # the path to gold to the compiler. gyp leaves unspecified what the
+        # cwd is when running the compiler, so the normal gyp path-munging
+        # fails us. This hack gets the right path.
+        'ldflags': [
+          '-B<!(cd <(DEPTH) && pwd -P)/<(binutils_dir)',
+        ],
+      }],
+      ['OS=="win"', {
+        'defines': [
+          'WIN32',
+        ],
+        # 4351: VS 2005 and later are warning us that they've fixed a bug
+        #       present in VS 2003 and earlier.
+        'msvs_disabled_warnings': [4351],
+        'msvs_configuration_attributes': {
+          'OutputDirectory': '<(DEPTH)\\build\\$(ConfigurationName)',
+          'IntermediateDirectory': '$(OutDir)\\obj\\$(ProjectName)',
+          'CharacterSet': '1',
+        },
+      }],
+      ['OS=="win" and v8_target_arch=="ia32"', {
+        'msvs_settings': {
+          'VCCLCompilerTool': {
+            # Ensure no surprising artifacts from 80bit double math with x86.
+            'AdditionalOptions': ['/arch:SSE2'],
+          },
+        },
+      }],
+      ['OS=="win" and v8_enable_prof==1', {
+        'msvs_settings': {
+          'VCLinkerTool': {
+            'GenerateMapFile': 'true',
+          },
+        },
+      }],
+      ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
+         or OS=="netbsd" or OS=="mac" or OS=="android" or OS=="qnx") and \
+        v8_target_arch=="ia32"', {
+        'cflags': [
+          '-msse2',
+          '-mfpmath=sse',
+          '-mmmx',  # Allows mmintrin.h for MMX intrinsics.
+        ],
+      }],
+      ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
+         or OS=="netbsd" or OS=="mac" or OS=="android" or OS=="qnx") and \
+        (v8_target_arch=="arm" or v8_target_arch=="ia32" or \
+         v8_target_arch=="x87" or v8_target_arch=="mips" or \
+         v8_target_arch=="mipsel" or v8_target_arch=="ppc" or \
+         v8_target_arch=="s390")', {
+        'target_conditions': [
+          ['_toolset=="host"', {
+            'conditions': [
+              ['host_cxx_is_biarch==1', {
+                'conditions': [
+                  ['host_arch=="s390" or host_arch=="s390x"', {
+                    'cflags': [ '-m31' ],
+                    'ldflags': [ '-m31' ]
+                  },{
+                   'cflags': [ '-m32' ],
+                   'ldflags': [ '-m32' ]
+                  }],
+                ],
+              }],
+            ],
+            'xcode_settings': {
+              'ARCHS': [ 'i386' ],
+            },
+          }],
+          ['_toolset=="target"', {
+            'conditions': [
+              ['target_cxx_is_biarch==1 and nacl_target_arch!="nacl_x64"', {
+                'conditions': [
+                  ['host_arch=="s390" or host_arch=="s390x"', {
+                    'cflags': [ '-m31' ],
+                    'ldflags': [ '-m31' ]
+                  },{
+                   'cflags': [ '-m32' ],
+                   'ldflags': [ '-m32' ],
+                  }],
+                ],
+              }],
+            ],
+            'xcode_settings': {
+              'ARCHS': [ 'i386' ],
+            },
+          }],
+        ],
+      }],
+      ['(OS=="linux" or OS=="android") and \
+        (v8_target_arch=="x64" or v8_target_arch=="arm64" or \
+         v8_target_arch=="ppc64" or v8_target_arch=="s390x")', {
+        'target_conditions': [
+          ['_toolset=="host"', {
+            'conditions': [
+              ['host_cxx_is_biarch==1', {
+                'cflags': [ '-m64' ],
+                'ldflags': [ '-m64' ]
+              }],
+             ],
+           }],
+           ['_toolset=="target"', {
+             'conditions': [
+               ['target_cxx_is_biarch==1', {
+                 'cflags': [ '-m64' ],
+                 'ldflags': [ '-m64' ],
+               }],
+             ]
+           }],
+         ],
+      }],
+      ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
+         or OS=="netbsd" or OS=="qnx" or OS=="aix"', {
+        'conditions': [
+          [ 'v8_no_strict_aliasing==1', {
+            'cflags': [ '-fno-strict-aliasing' ],
+          }],
+        ],  # conditions
+      }],
+      ['OS=="solaris"', {
+        'defines': [ '__C99FEATURES__=1' ],  # isinf() etc.
+      }],
+      ['OS=="freebsd" or OS=="openbsd"', {
+        'cflags': [ '-I/usr/local/include' ],
+      }],
+      ['OS=="netbsd"', {
+        'cflags': [ '-I/usr/pkg/include' ],
+      }],
+      ['OS=="aix"', {
+        'defines': [
+          # Support for malloc(0)
+          '_LINUX_SOURCE_COMPAT=1',
+          '__STDC_FORMAT_MACROS',
+          '_ALL_SOURCE=1'],
+        'conditions': [
+          [ 'v8_target_arch=="ppc"', {
+            'ldflags': [ '-Wl,-bmaxdata:0x60000000/dsa' ],
+          }],
+          [ 'v8_target_arch=="ppc64"', {
+            'cflags': [ '-maix64' ],
+            'ldflags': [ '-maix64 -Wl,-bbigtoc' ],
+          }],
+        ],
+      }],
+    ],  # conditions
+    'configurations': {
+      # Abstract configuration for v8_optimized_debug == 0.
+      'DebugBase0': {
+        'abstract': 1,
+        'msvs_settings': {
+          'VCCLCompilerTool': {
+            'Optimization': '0',
+            'conditions': [
+              ['component=="shared_library"', {
+                'RuntimeLibrary': '3',  # /MDd
+              }, {
+                'RuntimeLibrary': '1',  # /MTd
+              }],
+            ],
+          },
+          'VCLinkerTool': {
+            'LinkIncremental': '2',
+          },
+        },
+        'variables': {
+          'v8_enable_slow_dchecks%': 1,
+        },
+        'conditions': [
+          ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" or \
+            OS=="qnx" or OS=="aix"', {
+            'cflags!': [
+              '-O3',
+              '-O2',
+              '-O1',
+              '-Os',
+            ],
+            'cflags': [
+              '-fdata-sections',
+              '-ffunction-sections',
+            ],
+          }],
+          ['OS=="mac"', {
+            'xcode_settings': {
+               'GCC_OPTIMIZATION_LEVEL': '0',  # -O0
+            },
+          }],
+          ['v8_enable_slow_dchecks==1', {
+            'defines': [
+              'ENABLE_SLOW_DCHECKS',
+            ],
+          }],
+        ],
+      },  # DebugBase0
+      # Abstract configuration for v8_optimized_debug == 1.
+      'DebugBase1': {
+        'abstract': 1,
+        'msvs_settings': {
+          'VCCLCompilerTool': {
+            'Optimization': '2',
+            'InlineFunctionExpansion': '2',
+            'EnableIntrinsicFunctions': 'true',
+            'FavorSizeOrSpeed': '0',
+            'StringPooling': 'true',
+            'BasicRuntimeChecks': '0',
+            'conditions': [
+              ['component=="shared_library"', {
+                'RuntimeLibrary': '3',  #/MDd
+              }, {
+                'RuntimeLibrary': '1',  #/MTd
+              }],
+            ],
+          },
+          'VCLinkerTool': {
+            'LinkIncremental': '1',
+            'OptimizeReferences': '2',
+            'EnableCOMDATFolding': '2',
+          },
+        },
+        'variables': {
+          'v8_enable_slow_dchecks%': 0,
+        },
+        'conditions': [
+          ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" or \
+            OS=="qnx" or OS=="aix"', {
+            'cflags!': [
+              '-O0',
+              '-O1',
+              '-Os',
+            ],
+            'cflags': [
+              '-fdata-sections',
+              '-ffunction-sections',
+            ],
+            'conditions': [
+              # TODO(crbug.com/272548): Avoid -O3 in NaCl
+              # Don't use -O3 with sanitizers.
+              ['nacl_target_arch=="none" and asan==0 and msan==0 and lsan==0 \
+                and tsan==0 and ubsan==0 and ubsan_vptr==0', {
+                'cflags': ['-O3'],
+                'cflags!': ['-O2'],
+                }, {
+                'cflags': ['-O2'],
+                'cflags!': ['-O3'],
+              }],
+            ],
+          }],
+          ['OS=="mac"', {
+            'xcode_settings': {
+              'GCC_OPTIMIZATION_LEVEL': '3',  # -O3
+              'GCC_STRICT_ALIASING': 'YES',
+            },
+          }],
+          ['v8_enable_slow_dchecks==1', {
+            'defines': [
+              'ENABLE_SLOW_DCHECKS',
+            ],
+          }],
+        ],
+      },  # DebugBase1
+      # Common settings for the Debug configuration.
+      'DebugBaseCommon': {
+        'abstract': 1,
+        'defines': [
+          'ENABLE_DISASSEMBLER',
+          'V8_ENABLE_CHECKS',
+          'OBJECT_PRINT',
+          'VERIFY_HEAP',
+          'DEBUG',
+          'TRACE_MAPS'
+        ],
+        'conditions': [
+          ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" or \
+            OS=="qnx" or OS=="aix"', {
+            'cflags': [ '-Woverloaded-virtual', '<(wno_array_bounds)', ],
+          }],
+          ['OS=="linux" and v8_enable_backtrace==1', {
+            # Support for backtrace_symbols.
+            'ldflags': [ '-rdynamic' ],
+          }],
+          ['OS=="linux" and disable_glibcxx_debug==0', {
+            # Enable libstdc++ debugging facilities to help catch problems
+            # early, see http://crbug.com/65151 .
+            'defines': ['_GLIBCXX_DEBUG=1',],
+          }],
+          ['OS=="aix"', {
+            'ldflags': [ '-Wl,-bbigtoc' ],
+            'conditions': [
+              ['v8_target_arch=="ppc64"', {
+                'cflags': [ '-maix64 -mcmodel=large' ],
+              }],
+            ],
+          }],
+          ['OS=="android"', {
+            'variables': {
+              'android_full_debug%': 1,
+            },
+            'conditions': [
+              ['android_full_debug==0', {
+                # Disable full debug if we want a faster v8 in a debug build.
+                # TODO(2304): pass DISABLE_DEBUG_ASSERT instead of hiding DEBUG.
+                'defines!': [
+                  'DEBUG',
+                  'ENABLE_SLOW_DCHECKS',
+                ],
+              }],
+            ],
+          }],
+          # TODO(pcc): Re-enable in LTO builds once we've fixed the intermittent
+          # link failures (crbug.com/513074).
+          ['linux_use_gold_flags==1 and use_lto==0', {
+            'target_conditions': [
+              ['_toolset=="target"', {
+                'ldflags': [
+                  # Experimentation found that using four linking threads
+                  # saved ~20% of link time.
+                  # https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/281527606915bb36
+                  # Only apply this to the target linker, since the host
+                  # linker might not be gold, but isn't used much anyway.
+                  '-Wl,--threads',
+                  '-Wl,--thread-count=4',
+                ],
+              }],
+            ],
+          }],
+        ],
+      },  # DebugBaseCommon
+      'Debug': {
+        'inherit_from': ['DebugBaseCommon'],
+        'conditions': [
+          ['v8_optimized_debug==0', {
+            'inherit_from': ['DebugBase0'],
+          }, {
+            'inherit_from': ['DebugBase1'],
+          }],
+        ],
+      },  # Debug
+      'ReleaseBase': {
+        'abstract': 1,
+        'variables': {
+          'v8_enable_slow_dchecks%': 0,
+        },
+        'conditions': [
+          ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" \
+            or OS=="aix"', {
+            'cflags!': [
+              '-Os',
+            ],
+            'cflags': [
+              '-fdata-sections',
+              '-ffunction-sections',
+              '<(wno_array_bounds)',
+            ],
+            'conditions': [
+              # TODO(crbug.com/272548): Avoid -O3 in NaCl
+              # Don't use -O3 with sanitizers.
+              ['nacl_target_arch=="none" and asan==0 and msan==0 and lsan==0 \
+                and tsan==0 and ubsan==0 and ubsan_vptr==0', {
+                'cflags': ['-O3'],
+                'cflags!': ['-O2'],
+              }, {
+                'cflags': ['-O2'],
+                'cflags!': ['-O3'],
+              }],
+            ],
+          }],
+          ['OS=="android"', {
+            'cflags!': [
+              '-O3',
+              '-Os',
+            ],
+            'cflags': [
+              '-fdata-sections',
+              '-ffunction-sections',
+              '-O2',
+            ],
+          }],
+          ['OS=="mac"', {
+            'xcode_settings': {
+              'GCC_OPTIMIZATION_LEVEL': '3',  # -O3
+
+              # -fstrict-aliasing.  Mainline gcc
+              # enables this at -O2 and above,
+              # but Apple gcc does not unless it
+              # is specified explicitly.
+              'GCC_STRICT_ALIASING': 'YES',
+            },
+          }],  # OS=="mac"
+          ['OS=="win"', {
+            'msvs_settings': {
+              'VCCLCompilerTool': {
+                'Optimization': '2',
+                'InlineFunctionExpansion': '2',
+                'EnableIntrinsicFunctions': 'true',
+                'FavorSizeOrSpeed': '0',
+                'StringPooling': 'true',
+                'conditions': [
+                  ['component=="shared_library"', {
+                    'RuntimeLibrary': '2',  #/MD
+                  }, {
+                    'RuntimeLibrary': '0',  #/MT
+                  }],
+                ],
+              },
+              'VCLinkerTool': {
+                'LinkIncremental': '1',
+                'OptimizeReferences': '2',
+                'EnableCOMDATFolding': '2',
+              },
+            },
+          }],  # OS=="win"
+          ['v8_enable_slow_dchecks==1', {
+            'defines': [
+              'ENABLE_SLOW_DCHECKS',
+            ],
+          }],
+        ],  # conditions
+      },  # Release
+      'Release': {
+        'inherit_from': ['ReleaseBase'],
+      },  # Debug
+      'conditions': [
+        [ 'OS=="win"', {
+          # TODO(bradnelson): add a gyp mechanism to make this more graceful.
+          'Debug_x64': {
+            'inherit_from': ['DebugBaseCommon'],
+            'conditions': [
+              ['v8_optimized_debug==0', {
+                'inherit_from': ['DebugBase0'],
+              }, {
+                'inherit_from': ['DebugBase1'],
+              }],
+            ],
+          },
+          'Release_x64': {
+            'inherit_from': ['ReleaseBase'],
+          },
+        }],
+      ],
+    },  # configurations
+  },  # target_defaults
+}
diff --git a/gypfiles/vs_toolchain.py b/gypfiles/vs_toolchain.py
new file mode 100644
index 0000000..1693647
--- /dev/null
+++ b/gypfiles/vs_toolchain.py
@@ -0,0 +1,379 @@
+#!/usr/bin/env python
+# Copyright 2015 the V8 project authors. All rights reserved.
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import glob
+import json
+import os
+import pipes
+import shutil
+import subprocess
+import sys
+
+
+script_dir = os.path.dirname(os.path.realpath(__file__))
+chrome_src = os.path.abspath(os.path.join(script_dir, os.pardir))
+SRC_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+sys.path.insert(1, os.path.join(chrome_src, 'tools'))
+sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib'))
+json_data_file = os.path.join(script_dir, 'win_toolchain.json')
+
+
+import gyp
+
+
+# Use MSVS2013 as the default toolchain.
+CURRENT_DEFAULT_TOOLCHAIN_VERSION = '2013'
+
+
+def SetEnvironmentAndGetRuntimeDllDirs():
+  """Sets up os.environ to use the depot_tools VS toolchain with gyp, and
+  returns the location of the VS runtime DLLs so they can be copied into
+  the output directory after gyp generation.
+  """
+  vs_runtime_dll_dirs = None
+  depot_tools_win_toolchain = \
+      bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
+  # When running on a non-Windows host, only do this if the SDK has explicitly
+  # been downloaded before (in which case json_data_file will exist).
+  if ((sys.platform in ('win32', 'cygwin') or os.path.exists(json_data_file))
+      and depot_tools_win_toolchain):
+    if ShouldUpdateToolchain():
+      Update()
+    with open(json_data_file, 'r') as tempf:
+      toolchain_data = json.load(tempf)
+
+    toolchain = toolchain_data['path']
+    version = toolchain_data['version']
+    win_sdk = toolchain_data.get('win_sdk')
+    if not win_sdk:
+      win_sdk = toolchain_data['win8sdk']
+    wdk = toolchain_data['wdk']
+    # TODO(scottmg): The order unfortunately matters in these. They should be
+    # split into separate keys for x86 and x64. (See CopyVsRuntimeDlls call
+    # below). http://crbug.com/345992
+    vs_runtime_dll_dirs = toolchain_data['runtime_dirs']
+
+    os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain
+    os.environ['GYP_MSVS_VERSION'] = version
+    # We need to make sure windows_sdk_path is set to the automated
+    # toolchain values in GYP_DEFINES, but don't want to override any
+    # otheroptions.express
+    # values there.
+    gyp_defines_dict = gyp.NameValueListToDict(gyp.ShlexEnv('GYP_DEFINES'))
+    gyp_defines_dict['windows_sdk_path'] = win_sdk
+    os.environ['GYP_DEFINES'] = ' '.join('%s=%s' % (k, pipes.quote(str(v)))
+        for k, v in gyp_defines_dict.iteritems())
+    os.environ['WINDOWSSDKDIR'] = win_sdk
+    os.environ['WDK_DIR'] = wdk
+    # Include the VS runtime in the PATH in case it's not machine-installed.
+    runtime_path = os.path.pathsep.join(vs_runtime_dll_dirs)
+    os.environ['PATH'] = runtime_path + os.path.pathsep + os.environ['PATH']
+  elif sys.platform == 'win32' and not depot_tools_win_toolchain:
+    if not 'GYP_MSVS_OVERRIDE_PATH' in os.environ:
+      os.environ['GYP_MSVS_OVERRIDE_PATH'] = DetectVisualStudioPath()
+    if not 'GYP_MSVS_VERSION' in os.environ:
+      os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion()
+
+  return vs_runtime_dll_dirs
+
+
+def _RegistryGetValueUsingWinReg(key, value):
+  """Use the _winreg module to obtain the value of a registry key.
+
+  Args:
+    key: The registry key.
+    value: The particular registry value to read.
+  Return:
+    contents of the registry key's value, or None on failure.  Throws
+    ImportError if _winreg is unavailable.
+  """
+  import _winreg
+  try:
+    root, subkey = key.split('\\', 1)
+    assert root == 'HKLM'  # Only need HKLM for now.
+    with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, subkey) as hkey:
+      return _winreg.QueryValueEx(hkey, value)[0]
+  except WindowsError:
+    return None
+
+
+def _RegistryGetValue(key, value):
+  try:
+    return _RegistryGetValueUsingWinReg(key, value)
+  except ImportError:
+    raise Exception('The python library _winreg not found.')
+
+
+def GetVisualStudioVersion():
+  """Return GYP_MSVS_VERSION of Visual Studio.
+  """
+  return os.environ.get('GYP_MSVS_VERSION', CURRENT_DEFAULT_TOOLCHAIN_VERSION)
+
+
+def DetectVisualStudioPath():
+  """Return path to the GYP_MSVS_VERSION of Visual Studio.
+  """
+
+  # Note that this code is used from
+  # build/toolchain/win/setup_toolchain.py as well.
+  version_as_year = GetVisualStudioVersion()
+  year_to_version = {
+      '2013': '12.0',
+      '2015': '14.0',
+  }
+  if version_as_year not in year_to_version:
+    raise Exception(('Visual Studio version %s (from GYP_MSVS_VERSION)'
+                     ' not supported. Supported versions are: %s') % (
+                       version_as_year, ', '.join(year_to_version.keys())))
+  version = year_to_version[version_as_year]
+  keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version,
+          r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version]
+  for key in keys:
+    path = _RegistryGetValue(key, 'InstallDir')
+    if not path:
+      continue
+    path = os.path.normpath(os.path.join(path, '..', '..'))
+    return path
+
+  raise Exception(('Visual Studio Version %s (from GYP_MSVS_VERSION)'
+                   ' not found.') % (version_as_year))
+
+
+def _VersionNumber():
+  """Gets the standard version number ('120', '140', etc.) based on
+  GYP_MSVS_VERSION."""
+  vs_version = GetVisualStudioVersion()
+  if vs_version == '2013':
+    return '120'
+  elif vs_version == '2015':
+    return '140'
+  else:
+    raise ValueError('Unexpected GYP_MSVS_VERSION')
+
+
+def _CopyRuntimeImpl(target, source, verbose=True):
+  """Copy |source| to |target| if it doesn't already exist or if it
+  needs to be updated.
+  """
+  if (os.path.isdir(os.path.dirname(target)) and
+      (not os.path.isfile(target) or
+      os.stat(target).st_mtime != os.stat(source).st_mtime)):
+    if verbose:
+      print 'Copying %s to %s...' % (source, target)
+    if os.path.exists(target):
+      os.unlink(target)
+    shutil.copy2(source, target)
+
+
+def _CopyRuntime2013(target_dir, source_dir, dll_pattern):
+  """Copy both the msvcr and msvcp runtime DLLs, only if the target doesn't
+  exist, but the target directory does exist."""
+  for file_part in ('p', 'r'):
+    dll = dll_pattern % file_part
+    target = os.path.join(target_dir, dll)
+    source = os.path.join(source_dir, dll)
+    _CopyRuntimeImpl(target, source)
+
+
+def _CopyRuntime2015(target_dir, source_dir, dll_pattern, suffix):
+  """Copy both the msvcp and vccorlib runtime DLLs, only if the target doesn't
+  exist, but the target directory does exist."""
+  for file_part in ('msvcp', 'vccorlib', 'vcruntime'):
+    dll = dll_pattern % file_part
+    target = os.path.join(target_dir, dll)
+    source = os.path.join(source_dir, dll)
+    _CopyRuntimeImpl(target, source)
+  ucrt_src_dir = os.path.join(source_dir, 'api-ms-win-*.dll')
+  print 'Copying %s to %s...' % (ucrt_src_dir, target_dir)
+  for ucrt_src_file in glob.glob(ucrt_src_dir):
+    file_part = os.path.basename(ucrt_src_file)
+    ucrt_dst_file = os.path.join(target_dir, file_part)
+    _CopyRuntimeImpl(ucrt_dst_file, ucrt_src_file, False)
+  _CopyRuntimeImpl(os.path.join(target_dir, 'ucrtbase' + suffix),
+                    os.path.join(source_dir, 'ucrtbase' + suffix))
+
+
+def _CopyRuntime(target_dir, source_dir, target_cpu, debug):
+  """Copy the VS runtime DLLs, only if the target doesn't exist, but the target
+  directory does exist. Handles VS 2013 and VS 2015."""
+  suffix = "d.dll" if debug else ".dll"
+  if GetVisualStudioVersion() == '2015':
+    _CopyRuntime2015(target_dir, source_dir, '%s140' + suffix, suffix)
+  else:
+    _CopyRuntime2013(target_dir, source_dir, 'msvc%s120' + suffix)
+
+  # Copy the PGO runtime library to the release directories.
+  if not debug and os.environ.get('GYP_MSVS_OVERRIDE_PATH'):
+    pgo_x86_runtime_dir = os.path.join(os.environ.get('GYP_MSVS_OVERRIDE_PATH'),
+                                        'VC', 'bin')
+    pgo_x64_runtime_dir = os.path.join(pgo_x86_runtime_dir, 'amd64')
+    pgo_runtime_dll = 'pgort' + _VersionNumber() + '.dll'
+    if target_cpu == "x86":
+      source_x86 = os.path.join(pgo_x86_runtime_dir, pgo_runtime_dll)
+      if os.path.exists(source_x86):
+        _CopyRuntimeImpl(os.path.join(target_dir, pgo_runtime_dll), source_x86)
+    elif target_cpu == "x64":
+      source_x64 = os.path.join(pgo_x64_runtime_dir, pgo_runtime_dll)
+      if os.path.exists(source_x64):
+        _CopyRuntimeImpl(os.path.join(target_dir, pgo_runtime_dll),
+                          source_x64)
+    else:
+      raise NotImplementedError("Unexpected target_cpu value:" + target_cpu)
+
+
+def CopyVsRuntimeDlls(output_dir, runtime_dirs):
+  """Copies the VS runtime DLLs from the given |runtime_dirs| to the output
+  directory so that even if not system-installed, built binaries are likely to
+  be able to run.
+
+  This needs to be run after gyp has been run so that the expected target
+  output directories are already created.
+
+  This is used for the GYP build and gclient runhooks.
+  """
+  x86, x64 = runtime_dirs
+  out_debug = os.path.join(output_dir, 'Debug')
+  out_debug_nacl64 = os.path.join(output_dir, 'Debug', 'x64')
+  out_release = os.path.join(output_dir, 'Release')
+  out_release_nacl64 = os.path.join(output_dir, 'Release', 'x64')
+  out_debug_x64 = os.path.join(output_dir, 'Debug_x64')
+  out_release_x64 = os.path.join(output_dir, 'Release_x64')
+
+  if os.path.exists(out_debug) and not os.path.exists(out_debug_nacl64):
+    os.makedirs(out_debug_nacl64)
+  if os.path.exists(out_release) and not os.path.exists(out_release_nacl64):
+    os.makedirs(out_release_nacl64)
+  _CopyRuntime(out_debug,          x86, "x86", debug=True)
+  _CopyRuntime(out_release,        x86, "x86", debug=False)
+  _CopyRuntime(out_debug_x64,      x64, "x64", debug=True)
+  _CopyRuntime(out_release_x64,    x64, "x64", debug=False)
+  _CopyRuntime(out_debug_nacl64,   x64, "x64", debug=True)
+  _CopyRuntime(out_release_nacl64, x64, "x64", debug=False)
+
+
+def CopyDlls(target_dir, configuration, target_cpu):
+  """Copy the VS runtime DLLs into the requested directory as needed.
+
+  configuration is one of 'Debug' or 'Release'.
+  target_cpu is one of 'x86' or 'x64'.
+
+  The debug configuration gets both the debug and release DLLs; the
+  release config only the latter.
+
+  This is used for the GN build.
+  """
+  vs_runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs()
+  if not vs_runtime_dll_dirs:
+    return
+
+  x64_runtime, x86_runtime = vs_runtime_dll_dirs
+  runtime_dir = x64_runtime if target_cpu == 'x64' else x86_runtime
+  _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=False)
+  if configuration == 'Debug':
+    _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=True)
+
+
+def _GetDesiredVsToolchainHashes():
+  """Load a list of SHA1s corresponding to the toolchains that we want installed
+  to build with."""
+  if GetVisualStudioVersion() == '2015':
+    # Update 2.
+    return ['95ddda401ec5678f15eeed01d2bee08fcbc5ee97']
+  else:
+    return ['03a4e939cd325d6bc5216af41b92d02dda1366a6']
+
+
+def ShouldUpdateToolchain():
+  """Check if the toolchain should be upgraded."""
+  if not os.path.exists(json_data_file):
+    return True
+  with open(json_data_file, 'r') as tempf:
+    toolchain_data = json.load(tempf)
+  version = toolchain_data['version']
+  env_version = GetVisualStudioVersion()
+  # If there's a mismatch between the version set in the environment and the one
+  # in the json file then the toolchain should be updated.
+  return version != env_version
+
+
+def Update(force=False):
+  """Requests an update of the toolchain to the specific hashes we have at
+  this revision. The update outputs a .json of the various configuration
+  information required to pass to gyp which we use in |GetToolchainDir()|.
+  """
+  if force != False and force != '--force':
+    print >>sys.stderr, 'Unknown parameter "%s"' % force
+    return 1
+  if force == '--force' or os.path.exists(json_data_file):
+    force = True
+
+  depot_tools_win_toolchain = \
+      bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
+  if ((sys.platform in ('win32', 'cygwin') or force) and
+        depot_tools_win_toolchain):
+    import find_depot_tools
+    depot_tools_path = find_depot_tools.add_depot_tools_to_path()
+    # Necessary so that get_toolchain_if_necessary.py will put the VS toolkit
+    # in the correct directory.
+    os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion()
+    get_toolchain_args = [
+        sys.executable,
+        os.path.join(depot_tools_path,
+                    'win_toolchain',
+                    'get_toolchain_if_necessary.py'),
+        '--output-json', json_data_file,
+      ] + _GetDesiredVsToolchainHashes()
+    if force:
+      get_toolchain_args.append('--force')
+    subprocess.check_call(get_toolchain_args)
+
+  return 0
+
+
+def NormalizePath(path):
+  while path.endswith("\\"):
+    path = path[:-1]
+  return path
+
+
+def GetToolchainDir():
+  """Gets location information about the current toolchain (must have been
+  previously updated by 'update'). This is used for the GN build."""
+  runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs()
+
+  # If WINDOWSSDKDIR is not set, search the default SDK path and set it.
+  if not 'WINDOWSSDKDIR' in os.environ:
+    default_sdk_path = 'C:\\Program Files (x86)\\Windows Kits\\10'
+    if os.path.isdir(default_sdk_path):
+      os.environ['WINDOWSSDKDIR'] = default_sdk_path
+
+  print '''vs_path = "%s"
+sdk_path = "%s"
+vs_version = "%s"
+wdk_dir = "%s"
+runtime_dirs = "%s"
+''' % (
+      NormalizePath(os.environ['GYP_MSVS_OVERRIDE_PATH']),
+      NormalizePath(os.environ['WINDOWSSDKDIR']),
+      GetVisualStudioVersion(),
+      NormalizePath(os.environ.get('WDK_DIR', '')),
+      os.path.pathsep.join(runtime_dll_dirs or ['None']))
+
+
+def main():
+  commands = {
+      'update': Update,
+      'get_toolchain_dir': GetToolchainDir,
+      'copy_dlls': CopyDlls,
+  }
+  if len(sys.argv) < 2 or sys.argv[1] not in commands:
+    print >>sys.stderr, 'Expected one of: %s' % ', '.join(commands)
+    return 1
+  return commands[sys.argv[1]](*sys.argv[2:])
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/include/v8-debug.h b/include/v8-debug.h
index e41df29..6520cbe 100644
--- a/include/v8-debug.h
+++ b/include/v8-debug.h
@@ -125,6 +125,8 @@
      */
     virtual ClientData* GetClientData() const = 0;
 
+    virtual Isolate* GetIsolate() const = 0;
+
     virtual ~EventDetails() {}
   };
 
@@ -259,6 +261,11 @@
   V8_DEPRECATED("Use version with an Isolate",
                 static Local<Context> GetDebugContext());
 
+  /**
+   * While in the debug context, this method returns the top-most non-debug
+   * context, if it exists.
+   */
+  static MaybeLocal<Context> GetDebuggedContext(Isolate* isolate);
 
   /**
    * Enable/disable LiveEdit functionality for the given Isolate
diff --git a/include/v8-profiler.h b/include/v8-profiler.h
index 007ae2e..b2c1dc9 100644
--- a/include/v8-profiler.h
+++ b/include/v8-profiler.h
@@ -515,6 +515,11 @@
  */
 class V8_EXPORT HeapProfiler {
  public:
+  enum SamplingFlags {
+    kSamplingNoFlags = 0,
+    kSamplingForceGC = 1 << 0,
+  };
+
   /**
    * Callback function invoked for obtaining RetainedObjectInfo for
    * the given JavaScript wrapper object. It is prohibited to enter V8
@@ -640,7 +645,8 @@
    * Returns false if a sampling heap profiler is already running.
    */
   bool StartSamplingHeapProfiler(uint64_t sample_interval = 512 * 1024,
-                                 int stack_depth = 16);
+                                 int stack_depth = 16,
+                                 SamplingFlags flags = kSamplingNoFlags);
 
   /**
    * Stops the sampling heap profile and discards the current profile.
@@ -688,7 +694,6 @@
   HeapProfiler& operator=(const HeapProfiler&);
 };
 
-
 /**
  * Interface for providing information about embedder's objects
  * held by global handles. This information is reported in two ways:
@@ -703,7 +708,7 @@
  *     were not previously reported via AddObjectGroup.
  *
  * Thus, if an embedder wants to provide information about native
- * objects for heap snapshots, he can do it in a GC prologue
+ * objects for heap snapshots, it can do it in a GC prologue
  * handler, and / or by assigning wrapper class ids in the following way:
  *
  *  1. Bind a callback to class id by calling SetWrapperClassInfoProvider.
diff --git a/include/v8-util.h b/include/v8-util.h
index 73ec658..8133fdd 100644
--- a/include/v8-util.h
+++ b/include/v8-util.h
@@ -95,12 +95,12 @@
       MapType* map, const K& key, Local<V> value) {
     return NULL;
   }
-  static MapType* MapFromWeakCallbackData(
-          const WeakCallbackData<V, WeakCallbackDataType>& data) {
+  static MapType* MapFromWeakCallbackInfo(
+      const WeakCallbackInfo<WeakCallbackDataType>& data) {
     return NULL;
   }
-  static K KeyFromWeakCallbackData(
-      const WeakCallbackData<V, WeakCallbackDataType>& data) {
+  static K KeyFromWeakCallbackInfo(
+      const WeakCallbackInfo<WeakCallbackDataType>& data) {
     return K();
   }
   static void DisposeCallbackData(WeakCallbackDataType* data) { }
@@ -206,6 +206,17 @@
   }
 
   /**
+   * Call V8::RegisterExternallyReferencedObject with the map value for given
+   * key.
+   */
+  void RegisterExternallyReferencedObject(K& key) {
+    DCHECK(Contains(key));
+    V8::RegisterExternallyReferencedObject(
+        reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key))),
+        reinterpret_cast<internal::Isolate*>(GetIsolate()));
+  }
+
+  /**
    * Return value for key and remove it from the map.
    */
   Global<V> Remove(const K& key) {
@@ -402,11 +413,11 @@
 
  private:
   static void WeakCallback(
-      const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) {
+      const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
     if (Traits::kCallbackType != kNotWeak) {
       PersistentValueMap<K, V, Traits>* persistentValueMap =
-          Traits::MapFromWeakCallbackData(data);
-      K key = Traits::KeyFromWeakCallbackData(data);
+          Traits::MapFromWeakCallbackInfo(data);
+      K key = Traits::KeyFromWeakCallbackInfo(data);
       Traits::Dispose(data.GetIsolate(),
                       persistentValueMap->Remove(key).Pass(), key);
       Traits::DisposeCallbackData(data.GetParameter());
diff --git a/include/v8-version.h b/include/v8-version.h
index 545ec70..4cde6ff 100644
--- a/include/v8-version.h
+++ b/include/v8-version.h
@@ -9,9 +9,9 @@
 // NOTE these macros are used by some of the tool scripts and the build
 // system so their names cannot be changed without changing the scripts.
 #define V8_MAJOR_VERSION 5
-#define V8_MINOR_VERSION 1
-#define V8_BUILD_NUMBER 281
-#define V8_PATCH_LEVEL 59
+#define V8_MINOR_VERSION 3
+#define V8_BUILD_NUMBER 332
+#define V8_PATCH_LEVEL 45
 
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/include/v8.h b/include/v8.h
index 703a4f4..c62a1fd 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -457,32 +457,12 @@
 };
 
 
-template <class T, class P>
-class WeakCallbackData {
- public:
-  typedef void (*Callback)(const WeakCallbackData<T, P>& data);
-
-  WeakCallbackData(Isolate* isolate, P* parameter, Local<T> handle)
-      : isolate_(isolate), parameter_(parameter), handle_(handle) {}
-
-  V8_INLINE Isolate* GetIsolate() const { return isolate_; }
-  V8_INLINE P* GetParameter() const { return parameter_; }
-  V8_INLINE Local<T> GetValue() const { return handle_; }
-
- private:
-  Isolate* isolate_;
-  P* parameter_;
-  Local<T> handle_;
-};
-
-
-// TODO(dcarney): delete this with WeakCallbackData
-template <class T>
-using PhantomCallbackData = WeakCallbackInfo<T>;
-
-
-enum class WeakCallbackType { kParameter, kInternalFields };
-
+// kParameter will pass a void* parameter back to the callback, kInternalFields
+// will pass the first two internal fields back to the callback, kFinalizer
+// will pass a void* parameter back, but is invoked before the object is
+// actually collected, so it can be resurrected. In the last case, it is not
+// possible to request a second pass callback.
+enum class WeakCallbackType { kParameter, kInternalFields, kFinalizer };
 
 /**
  * An object reference that is independent of any handle scope.  Where
@@ -561,36 +541,19 @@
    *  critical form of resource management!
    */
   template <typename P>
-  V8_INLINE V8_DEPRECATED(
-      "use WeakCallbackInfo version",
-      void SetWeak(P* parameter,
-                   typename WeakCallbackData<T, P>::Callback callback));
-
-  template <typename S, typename P>
-  V8_INLINE V8_DEPRECATED(
-      "use WeakCallbackInfo version",
-      void SetWeak(P* parameter,
-                   typename WeakCallbackData<S, P>::Callback callback));
-
-  // Phantom persistents work like weak persistents, except that the pointer to
-  // the object being collected is not available in the finalization callback.
-  // This enables the garbage collector to collect the object and any objects
-  // it references transitively in one GC cycle. At the moment you can either
-  // specify a parameter for the callback or the location of two internal
-  // fields in the dying object.
-  template <typename P>
-  V8_INLINE V8_DEPRECATED(
-      "use SetWeak",
-      void SetPhantom(P* parameter,
-                      typename WeakCallbackInfo<P>::Callback callback,
-                      int internal_field_index1 = -1,
-                      int internal_field_index2 = -1));
-
-  template <typename P>
   V8_INLINE void SetWeak(P* parameter,
                          typename WeakCallbackInfo<P>::Callback callback,
                          WeakCallbackType type);
 
+  /**
+   * Turns this handle into a weak phantom handle without finalization callback.
+   * The handle will be reset automatically when the garbage collector detects
+   * that the object is no longer reachable.
+   * A related function Isolate::NumberOfPhantomHandleResetsSinceLastCall
+   * returns how many phantom handles were reset by the garbage collector.
+   */
+  V8_INLINE void SetWeak();
+
   template<typename P>
   V8_INLINE P* ClearWeak();
 
@@ -602,7 +565,7 @@
    * is alive. Only allowed when the embedder is asked to trace its heap by
    * EmbedderHeapTracer.
    */
-  V8_INLINE void RegisterExternalReference(Isolate* isolate);
+  V8_INLINE void RegisterExternalReference(Isolate* isolate) const;
 
   /**
    * Marks the reference to this object independent. Garbage collector is free
@@ -620,7 +583,9 @@
    * external dependencies. This mark is automatically cleared after each
    * garbage collection.
    */
-  V8_INLINE void MarkPartiallyDependent();
+  V8_INLINE V8_DEPRECATED(
+      "deprecated optimization, do not use partially dependent groups",
+      void MarkPartiallyDependent());
 
   /**
    * Marks the reference to this object as active. The scavenge garbage
@@ -1648,26 +1613,25 @@
 // A StateTag represents a possible state of the VM.
 enum StateTag { JS, GC, COMPILER, OTHER, EXTERNAL, IDLE };
 
-
 // A RegisterState represents the current state of registers used
 // by the sampling profiler API.
 struct RegisterState {
-  RegisterState() : pc(NULL), sp(NULL), fp(NULL) {}
+  RegisterState() : pc(nullptr), sp(nullptr), fp(nullptr) {}
   void* pc;  // Instruction pointer.
   void* sp;  // Stack pointer.
   void* fp;  // Frame pointer.
 };
 
-
 // The output structure filled up by GetStackSample API function.
 struct SampleInfo {
-  size_t frames_count;
-  StateTag vm_state;
+  size_t frames_count;            // Number of frames collected.
+  StateTag vm_state;              // Current VM state.
+  void* external_callback_entry;  // External callback address if VM is
+                                  // executing an external callback.
 };
 
-
 /**
- * A JSON Parser.
+ * A JSON Parser and Stringifier.
  */
 class V8_EXPORT JSON {
  public:
@@ -1678,10 +1642,24 @@
    * \param json_string The string to parse.
    * \return The corresponding value if successfully parsed.
    */
-  static V8_DEPRECATED("Use maybe version",
+  static V8_DEPRECATED("Use the maybe version taking context",
                        Local<Value> Parse(Local<String> json_string));
+  static V8_DEPRECATE_SOON("Use the maybe version taking context",
+                           MaybeLocal<Value> Parse(Isolate* isolate,
+                                                   Local<String> json_string));
   static V8_WARN_UNUSED_RESULT MaybeLocal<Value> Parse(
-      Isolate* isolate, Local<String> json_string);
+      Local<Context> context, Local<String> json_string);
+
+  /**
+   * Tries to stringify the JSON-serializable object |json_object| and returns
+   * it as string if successful.
+   *
+   * \param json_object The JSON-serializable object to stringify.
+   * \return The corresponding string if successfully stringified.
+   */
+  static V8_WARN_UNUSED_RESULT MaybeLocal<String> Stringify(
+      Local<Context> context, Local<Object> json_object,
+      Local<String> gap = Local<String>());
 };
 
 
@@ -2050,6 +2028,8 @@
 
   template <class T> V8_INLINE static Value* Cast(T* value);
 
+  Local<String> TypeOf(v8::Isolate*);
+
  private:
   V8_INLINE bool QuickIsUndefined() const;
   V8_INLINE bool QuickIsNull() const;
@@ -2640,6 +2620,33 @@
 };
 
 /**
+ * Property filter bits. They can be or'ed to build a composite filter.
+ */
+enum PropertyFilter {
+  ALL_PROPERTIES = 0,
+  ONLY_WRITABLE = 1,
+  ONLY_ENUMERABLE = 2,
+  ONLY_CONFIGURABLE = 4,
+  SKIP_STRINGS = 8,
+  SKIP_SYMBOLS = 16
+};
+
+/**
+ * Keys/Properties filter enums:
+ *
+ * KeyCollectionMode limits the range of collected properties. kOwnOnly limits
+ * the collected properties to the given Object only. kIncludesPrototypes will
+ * include all keys of the objects's prototype chain as well.
+ */
+enum class KeyCollectionMode { kOwnOnly, kIncludePrototypes };
+
+/**
+ * kIncludesIndices allows for integer indices to be collected, while
+ * kSkipIndices will exclude integer indicies from being collected.
+ */
+enum class IndexFilter { kIncludeIndices, kSkipIndices };
+
+/**
  * Integrity level for objects.
  */
 enum class IntegrityLevel { kFrozen, kSealed };
@@ -2788,6 +2795,9 @@
   V8_DEPRECATE_SOON("Use maybe version", Local<Array> GetPropertyNames());
   V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetPropertyNames(
       Local<Context> context);
+  V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetPropertyNames(
+      Local<Context> context, KeyCollectionMode mode,
+      PropertyFilter property_filter, IndexFilter index_filter);
 
   /**
    * This function has the same functionality as GetPropertyNames but
@@ -2799,6 +2809,15 @@
       Local<Context> context);
 
   /**
+   * Returns an array containing the names of the filtered properties
+   * of this object, including properties from prototype objects.  The
+   * array returned by this method contains the same values as would
+   * be enumerated by a for-in statement over this object.
+   */
+  V8_WARN_UNUSED_RESULT MaybeLocal<Array> GetOwnPropertyNames(
+      Local<Context> context, PropertyFilter filter);
+
+  /**
    * Get the prototype object.  This does not skip objects marked to
    * be skipped by __proto__ and it does not consult the security
    * handler.
@@ -2878,6 +2897,8 @@
   V8_DEPRECATED("Use maybe version", bool HasOwnProperty(Local<String> key));
   V8_WARN_UNUSED_RESULT Maybe<bool> HasOwnProperty(Local<Context> context,
                                                    Local<Name> key);
+  V8_WARN_UNUSED_RESULT Maybe<bool> HasOwnProperty(Local<Context> context,
+                                                   uint32_t index);
   V8_DEPRECATE_SOON("Use maybe version",
                     bool HasRealNamedProperty(Local<String> key));
   V8_WARN_UNUSED_RESULT Maybe<bool> HasRealNamedProperty(Local<Context> context,
@@ -2950,13 +2971,6 @@
    */
   int GetIdentityHash();
 
-  V8_DEPRECATED("Use v8::Object::SetPrivate instead.",
-                bool SetHiddenValue(Local<String> key, Local<Value> value));
-  V8_DEPRECATED("Use v8::Object::GetPrivate instead.",
-                Local<Value> GetHiddenValue(Local<String> key));
-  V8_DEPRECATED("Use v8::Object::DeletePrivate instead.",
-                bool DeleteHiddenValue(Local<String> key));
-
   /**
    * Clone this object with a fast but shallow copy.  Values will point
    * to the same values as the original object.
@@ -2977,6 +2991,11 @@
   bool IsCallable();
 
   /**
+   * True if this object is a constructor.
+   */
+  bool IsConstructor();
+
+  /**
    * Call an Object as a function if a callback is set by the
    * ObjectTemplate::SetCallAsFunctionHandler method.
    */
@@ -3177,12 +3196,13 @@
                           Local<Function> Callee() const);
   V8_INLINE Local<Object> This() const;
   V8_INLINE Local<Object> Holder() const;
+  V8_INLINE Local<Value> NewTarget() const;
   V8_INLINE bool IsConstructCall() const;
   V8_INLINE Local<Value> Data() const;
   V8_INLINE Isolate* GetIsolate() const;
   V8_INLINE ReturnValue<T> GetReturnValue() const;
   // This shouldn't be public, but the arm compiler needs it.
-  static const int kArgsLength = 7;
+  static const int kArgsLength = 8;
 
  protected:
   friend class internal::FunctionCallbackArguments;
@@ -3194,15 +3214,13 @@
   static const int kDataIndex = 4;
   static const int kCalleeIndex = 5;
   static const int kContextSaveIndex = 6;
+  static const int kNewTargetIndex = 7;
 
   V8_INLINE FunctionCallbackInfo(internal::Object** implicit_args,
-                   internal::Object** values,
-                   int length,
-                   bool is_construct_call);
+                                 internal::Object** values, int length);
   internal::Object** implicit_args_;
   internal::Object** values_;
   int length_;
-  int is_construct_call_;
 };
 
 
@@ -3241,6 +3259,7 @@
 
 typedef void (*FunctionCallback)(const FunctionCallbackInfo<Value>& info);
 
+enum class ConstructorBehavior { kThrow, kAllow };
 
 /**
  * A JavaScript function object (ECMA-262, 15.3).
@@ -3251,10 +3270,10 @@
    * Create a function in the current execution context
    * for a given FunctionCallback.
    */
-  static MaybeLocal<Function> New(Local<Context> context,
-                                  FunctionCallback callback,
-                                  Local<Value> data = Local<Value>(),
-                                  int length = 0);
+  static MaybeLocal<Function> New(
+      Local<Context> context, FunctionCallback callback,
+      Local<Value> data = Local<Value>(), int length = 0,
+      ConstructorBehavior behavior = ConstructorBehavior::kAllow);
   static V8_DEPRECATE_SOON(
       "Use maybe version",
       Local<Function> New(Isolate* isolate, FunctionCallback callback,
@@ -3456,10 +3475,20 @@
 class V8_EXPORT ArrayBuffer : public Object {
  public:
   /**
-   * Allocator that V8 uses to allocate |ArrayBuffer|'s memory.
+   * A thread-safe allocator that V8 uses to allocate |ArrayBuffer|'s memory.
    * The allocator is a global V8 setting. It has to be set via
    * Isolate::CreateParams.
    *
+   * Memory allocated through this allocator by V8 is accounted for as external
+   * memory by V8. Note that V8 keeps track of the memory for all internalized
+   * |ArrayBuffer|s. Responsibility for tracking external memory (using
+   * Isolate::AdjustAmountOfExternalAllocatedMemory) is handed over to the
+   * embedder upon externalization and taken over upon internalization (creating
+   * an internalized buffer from an existing buffer).
+   *
+   * Note that it is unsafe to call back into V8 from any of the allocator
+   * functions.
+   *
    * This API is experimental and may change significantly.
    */
   class V8_EXPORT Allocator { // NOLINT
@@ -4127,7 +4156,11 @@
  */
 class V8_EXPORT Template : public Data {
  public:
-  /** Adds a property to each instance created by this template.*/
+  /**
+   * Adds a property to each instance created by this template.
+   *
+   * The property must be defined either as a primitive value, or a template.
+   */
   void Set(Local<Name> name, Local<Data> value,
            PropertyAttribute attributes = None);
   V8_INLINE void Set(Isolate* isolate, const char* name, Local<Data> value);
@@ -4353,28 +4386,6 @@
 typedef bool (*AccessCheckCallback)(Local<Context> accessing_context,
                                     Local<Object> accessed_object,
                                     Local<Value> data);
-typedef bool (*DeprecatedAccessCheckCallback)(Local<Context> accessing_context,
-                                              Local<Object> accessed_object);
-
-/**
- * Returns true if cross-context access should be allowed to the named
- * property with the given key on the host object.
- */
-typedef bool (*NamedSecurityCallback)(Local<Object> host,
-                                      Local<Value> key,
-                                      AccessType type,
-                                      Local<Value> data);
-
-
-/**
- * Returns true if cross-context access should be allowed to the indexed
- * property with the given index on the host object.
- */
-typedef bool (*IndexedSecurityCallback)(Local<Object> host,
-                                        uint32_t index,
-                                        AccessType type,
-                                        Local<Value> data);
-
 
 /**
  * A FunctionTemplate is used to create functions at runtime. There
@@ -4477,7 +4488,11 @@
   static Local<FunctionTemplate> New(
       Isolate* isolate, FunctionCallback callback = 0,
       Local<Value> data = Local<Value>(),
-      Local<Signature> signature = Local<Signature>(), int length = 0);
+      Local<Signature> signature = Local<Signature>(), int length = 0,
+      ConstructorBehavior behavior = ConstructorBehavior::kAllow);
+
+  /** Get a template included in the snapshot by index. */
+  static Local<FunctionTemplate> FromSnapshot(Isolate* isolate, size_t index);
 
   /**
    * Creates a function template with a fast handler. If a fast handler is set,
@@ -4654,6 +4669,9 @@
       Local<FunctionTemplate> constructor = Local<FunctionTemplate>());
   static V8_DEPRECATED("Use isolate version", Local<ObjectTemplate> New());
 
+  /** Get a template included in the snapshot by index. */
+  static Local<ObjectTemplate> FromSnapshot(Isolate* isolate, size_t index);
+
   /** Creates a new instance of this template.*/
   V8_DEPRECATE_SOON("Use maybe version", Local<Object> NewInstance());
   V8_WARN_UNUSED_RESULT MaybeLocal<Object> NewInstance(Local<Context> context);
@@ -4784,16 +4802,18 @@
    */
   void SetAccessCheckCallback(AccessCheckCallback callback,
                               Local<Value> data = Local<Value>());
-  V8_DEPRECATED(
-      "Use SetAccessCheckCallback with new AccessCheckCallback signature.",
-      void SetAccessCheckCallback(DeprecatedAccessCheckCallback callback,
-                                  Local<Value> data = Local<Value>()));
 
-  V8_DEPRECATED(
-      "Use SetAccessCheckCallback instead",
-      void SetAccessCheckCallbacks(NamedSecurityCallback named_handler,
-                                   IndexedSecurityCallback indexed_handler,
-                                   Local<Value> data = Local<Value>()));
+  /**
+   * Like SetAccessCheckCallback but invokes an interceptor on failed access
+   * checks instead of looking up all-can-read properties. You can only use
+   * either this method or SetAccessCheckCallback, but not both at the same
+   * time.
+   */
+  void SetAccessCheckCallbackAndHandler(
+      AccessCheckCallback callback,
+      const NamedPropertyHandlerConfiguration& named_handler,
+      const IndexedPropertyHandlerConfiguration& indexed_handler,
+      Local<Value> data = Local<Value>());
 
   /**
    * Gets the number of internal fields for objects generated from
@@ -5038,10 +5058,6 @@
     kAllocationActionAll = kAllocationActionAllocate | kAllocationActionFree
   };
 
-typedef void (*MemoryAllocationCallback)(ObjectSpace space,
-                                         AllocationAction action,
-                                         int size);
-
 // --- Enter/Leave Script Callback ---
 typedef void (*BeforeCallEnteredCallback)(Isolate*);
 typedef void (*CallCompletedCallback)(Isolate*);
@@ -5121,6 +5137,11 @@
    */
   static int GetCurrentDepth(Isolate* isolate);
 
+  /**
+   * Returns true while microtasks are being executed.
+   */
+  static bool IsRunningMicrotasks(Isolate* isolate);
+
  private:
   internal::Isolate* const isolate_;
   bool run_;
@@ -5257,6 +5278,18 @@
   friend class Isolate;
 };
 
+class V8_EXPORT HeapCodeStatistics {
+ public:
+  HeapCodeStatistics();
+  size_t code_and_metadata_size() { return code_and_metadata_size_; }
+  size_t bytecode_and_metadata_size() { return bytecode_and_metadata_size_; }
+
+ private:
+  size_t code_and_metadata_size_;
+  size_t bytecode_and_metadata_size_;
+
+  friend class Isolate;
+};
 
 class RetainedObjectInfo;
 
@@ -5340,6 +5373,31 @@
 };
 
 /**
+ * Option flags passed to the SetRAILMode function.
+ * See documentation https://developers.google.com/web/tools/chrome-devtools/
+ * profile/evaluate-performance/rail
+ */
+enum RAILMode {
+  // Default performance mode: V8 will optimize for both latency and
+  // throughput in this mode.
+  PERFORMANCE_DEFAULT,
+  // Response performance mode: In this mode very low virtual machine latency
+  // is provided. V8 will try to avoid JavaScript execution interruptions.
+  // Throughput may be throttled.
+  PERFORMANCE_RESPONSE,
+  // Animation performance mode: In this mode low virtual machine latency is
+  // provided. V8 will try to avoid as many JavaScript execution interruptions
+  // as possible. Throughput may be throttled
+  PERFORMANCE_ANIMATION,
+  // Idle performance mode: The embedder is idle. V8 can complete deferred work
+  // in this mode.
+  PERFORMANCE_IDLE,
+  // Load performance mode: In this mode high throughput is provided. V8 may
+  // turn off latency optimizations.
+  PERFORMANCE_LOAD
+};
+
+/**
  * Option flags passed to the SetJitCodeEventHandler function.
  */
 enum JitCodeEventOptions {
@@ -5394,31 +5452,56 @@
  * trace through its heap and call PersistentBase::RegisterExternalReference on
  * each js object reachable from any of the given wrappers.
  *
- * Before the first call to the TraceWrappableFrom function v8 will call
- * TraceRoots. When the v8 garbage collection is finished, v8 will call
- * ClearTracingMarks.
+ * Before the first call to the TraceWrappersFrom function TracePrologue will be
+ * called. When the garbage collection cycle is finished, TraceEpilogue will be
+ * called.
  */
-class EmbedderHeapTracer {
+class V8_EXPORT EmbedderHeapTracer {
  public:
+  enum ForceCompletionAction { FORCE_COMPLETION, DO_NOT_FORCE_COMPLETION };
+  struct AdvanceTracingActions {
+    explicit AdvanceTracingActions(ForceCompletionAction force_completion_)
+        : force_completion(force_completion_) {}
+
+    ForceCompletionAction force_completion;
+  };
+  /**
+   * V8 will call this method with internal fields of found wrappers.
+   * Embedder is expected to store them in it's marking deque and trace
+   * reachable wrappers from them when asked by AdvanceTracing method.
+   */
+  virtual void RegisterV8References(
+      const std::vector<std::pair<void*, void*> >& internal_fields) = 0;
   /**
    * V8 will call this method at the beginning of the gc cycle.
    */
-  virtual void TraceRoots(Isolate* isolate) = 0;
-
+  virtual void TracePrologue() = 0;
   /**
-   * V8 will call this method with internal fields of a potential wrappers.
-   * Embedder is expected to trace its heap (synchronously) and call
-   * PersistentBase::RegisterExternalReference() on all wrappers reachable from
-   * any of the given wrappers.
+   * Embedder is expected to trace its heap starting from wrappers reported by
+   * RegisterV8References method, and call
+   * PersistentBase::RegisterExternalReference() on all reachable wrappers.
+   * Embedder is expected to stop tracing by the given deadline.
+   *
+   * Returns true if there is still work to do.
    */
-  virtual void TraceWrappableFrom(
-      Isolate* isolate,
-      const std::vector<std::pair<void*, void*> >& internal_fields) = 0;
+  virtual bool AdvanceTracing(double deadline_in_ms,
+                              AdvanceTracingActions actions) = 0;
   /**
    * V8 will call this method at the end of the gc cycle. Allocation is *not*
-   * allowed in the ClearTracingMarks.
+   * allowed in the TraceEpilogue.
    */
-  virtual void ClearTracingMarks(Isolate* isolate) = 0;
+  virtual void TraceEpilogue() = 0;
+
+  /**
+   * Let embedder know v8 entered final marking pause (no more incremental steps
+   * will follow).
+   */
+  virtual void EnterFinalPause() {}
+
+  /**
+   * Throw away all intermediate data and reset to the initial state.
+   */
+  virtual void AbortTracing() {}
 
  protected:
   virtual ~EmbedderHeapTracer() = default;
@@ -5439,20 +5522,21 @@
    */
   struct CreateParams {
     CreateParams()
-        : entry_hook(NULL),
-          code_event_handler(NULL),
-          snapshot_blob(NULL),
-          counter_lookup_callback(NULL),
-          create_histogram_callback(NULL),
-          add_histogram_sample_callback(NULL),
-          array_buffer_allocator(NULL) {}
+        : entry_hook(nullptr),
+          code_event_handler(nullptr),
+          snapshot_blob(nullptr),
+          counter_lookup_callback(nullptr),
+          create_histogram_callback(nullptr),
+          add_histogram_sample_callback(nullptr),
+          array_buffer_allocator(nullptr),
+          external_references(nullptr) {}
 
     /**
      * The optional entry_hook allows the host application to provide the
      * address of a function that's invoked on entry to every V8-generated
      * function.  Note that entry_hook is invoked at the very start of each
-     * generated function. Furthermore, if an  entry_hook is given, V8 will
-     * always run without a context snapshot.
+     * generated function. Furthermore, if an entry_hook is given, V8 will
+     * not use a snapshot, including custom snapshots.
      */
     FunctionEntryHook entry_hook;
 
@@ -5493,6 +5577,14 @@
      * store of ArrayBuffers.
      */
     ArrayBuffer::Allocator* array_buffer_allocator;
+
+    /**
+     * Specifies an optional nullptr-terminated array of raw addresses in the
+     * embedder that V8 can match against during serialization and use for
+     * deserialization. This array and its content must stay valid for the
+     * entire lifetime of the isolate.
+     */
+    intptr_t* external_references;
   };
 
 
@@ -5621,9 +5713,12 @@
     kLegacyFunctionDeclaration = 29,
     kRegExpPrototypeSourceGetter = 30,
     kRegExpPrototypeOldFlagGetter = 31,
+    kDecimalWithLeadingZeroInStrictMode = 32,
+    kLegacyDateParser = 33,
+    kDefineGetterOrSetterWouldThrow = 34,
 
-    // If you add new values here, you'll also need to update V8Initializer.cpp
-    // in Chromium.
+    // If you add new values here, you'll also need to update Chromium's:
+    // UseCounter.h, V8PerIsolateData.cpp, histograms.xml
     kUseCounterFeatureCount  // This enum value must be last.
   };
 
@@ -5765,6 +5860,15 @@
                                        size_t type_index);
 
   /**
+   * Get statistics about code and its metadata in the heap.
+   *
+   * \param object_statistics The HeapCodeStatistics object to fill in
+   *   statistics of code, bytecode and their metadata.
+   * \returns true on success.
+   */
+  bool GetHeapCodeAndMetadataStatistics(HeapCodeStatistics* object_statistics);
+
+  /**
    * Get a call stack sample from the isolate.
    * \param state Execution state.
    * \param frames Caller allocated buffer to store stack frames.
@@ -5796,6 +5900,12 @@
       AdjustAmountOfExternalAllocatedMemory(int64_t change_in_bytes);
 
   /**
+   * Returns the number of phantom handles without callbacks that were reset
+   * by the garbage collector since the last call to this function.
+   */
+  size_t NumberOfPhantomHandleResetsSinceLastCall();
+
+  /**
    * Returns heap profiler for this isolate. Will return NULL until the isolate
    * is initialized.
    */
@@ -6136,6 +6246,15 @@
   void IsolateInBackgroundNotification();
 
   /**
+   * Optional notification to tell V8 the current performance requirements
+   * of the embedder based on RAIL.
+   * V8 uses these notifications to guide heuristics.
+   * This is an unfinished experimental feature. Semantics and implementation
+   * may change frequently.
+   */
+  void SetRAILMode(RAILMode rail_mode);
+
+  /**
    * Allows the host application to provide the address of a function that is
    * notified each time code is added, moved or removed.
    *
@@ -6231,18 +6350,6 @@
       StackTrace::StackTraceOptions options = StackTrace::kOverview);
 
   /**
-   * Enables the host application to provide a mechanism to be notified
-   * and perform custom logging when V8 Allocates Executable Memory.
-   */
-  void AddMemoryAllocationCallback(MemoryAllocationCallback callback,
-                                   ObjectSpace space, AllocationAction action);
-
-  /**
-   * Removes callback that was installed by AddMemoryAllocationCallback.
-   */
-  void RemoveMemoryAllocationCallback(MemoryAllocationCallback callback);
-
-  /**
    * Iterates through all external resources referenced from current isolate
    * heap.  GC is not invoked prior to iterating, therefore there is no
    * guarantee that visited objects are still alive.
@@ -6271,6 +6378,12 @@
    */
   void VisitWeakHandles(PersistentHandleVisitor* visitor);
 
+  /**
+   * Check if this isolate is in use.
+   * True if at least one thread Enter'ed this isolate.
+   */
+  bool IsInUse();
+
  private:
   template <class K, class V, class Traits>
   friend class PersistentValueMapBase;
@@ -6477,23 +6590,6 @@
       void RemoveGCEpilogueCallback(GCCallback callback));
 
   /**
-   * Enables the host application to provide a mechanism to be notified
-   * and perform custom logging when V8 Allocates Executable Memory.
-   */
-  V8_INLINE static V8_DEPRECATED(
-      "Use isolate version",
-      void AddMemoryAllocationCallback(MemoryAllocationCallback callback,
-                                       ObjectSpace space,
-                                       AllocationAction action));
-
-  /**
-   * Removes callback that was installed by AddMemoryAllocationCallback.
-   */
-  V8_INLINE static V8_DEPRECATED(
-      "Use isolate version",
-      void RemoveMemoryAllocationCallback(MemoryAllocationCallback callback));
-
-  /**
    * Initializes V8. This function needs to be called before the first Isolate
    * is created. It always returns true.
    */
@@ -6613,7 +6709,24 @@
    * If V8 was compiled with the ICU data in an external file, the location
    * of the data file has to be provided.
    */
-  static bool InitializeICU(const char* icu_data_file = NULL);
+  V8_DEPRECATE_SOON(
+      "Use version with default location.",
+      static bool InitializeICU(const char* icu_data_file = nullptr));
+
+  /**
+   * Initialize the ICU library bundled with V8. The embedder should only
+   * invoke this method when using the bundled ICU. If V8 was compiled with
+   * the ICU data in an external file and when the default location of that
+   * file should be used, a path to the executable must be provided.
+   * Returns true on success.
+   *
+   * The default is a file called icudtl.dat side-by-side with the executable.
+   *
+   * Optionally, the location of the data file can be provided to override the
+   * default.
+   */
+  static bool InitializeICUDefaultLocation(const char* exec_path,
+                                           const char* icu_data_file = nullptr);
 
   /**
    * Initialize the external startup data. The embedder only needs to
@@ -6653,26 +6766,27 @@
                                                internal::Object** handle);
   static internal::Object** CopyPersistent(internal::Object** handle);
   static void DisposeGlobal(internal::Object** global_handle);
-  typedef WeakCallbackData<Value, void>::Callback WeakCallback;
-  static void RegisterExternallyReferencedObject(internal::Object** object,
-                                                 internal::Isolate* isolate);
-  static void MakeWeak(internal::Object** global_handle, void* data,
-                       WeakCallback weak_callback);
-  static void MakeWeak(internal::Object** global_handle, void* data,
+  static void MakeWeak(internal::Object** location, void* data,
                        WeakCallbackInfo<void>::Callback weak_callback,
                        WeakCallbackType type);
-  static void MakeWeak(internal::Object** global_handle, void* data,
+  static void MakeWeak(internal::Object** location, void* data,
                        // Must be 0 or -1.
                        int internal_field_index1,
                        // Must be 1 or -1.
                        int internal_field_index2,
                        WeakCallbackInfo<void>::Callback weak_callback);
-  static void* ClearWeak(internal::Object** global_handle);
+  static void MakeWeak(internal::Object*** location_addr);
+  static void* ClearWeak(internal::Object** location);
   static void Eternalize(Isolate* isolate,
                          Value* handle,
                          int* index);
   static Local<Value> GetEternal(Isolate* isolate, int index);
 
+  static void RegisterExternallyReferencedObject(internal::Object** object,
+                                                 internal::Isolate* isolate);
+  template <class K, class V, class T>
+  friend class PersistentValueMapBase;
+
   static void FromJustIsNothing();
   static void ToLocalEmpty();
   static void InternalFieldOutOfBounds(int index);
@@ -6689,6 +6803,60 @@
   friend class Context;
 };
 
+/**
+ * Helper class to create a snapshot data blob.
+ */
+class SnapshotCreator {
+ public:
+  enum class FunctionCodeHandling { kClear, kKeep };
+
+  /**
+   * Create and enter an isolate, and set it up for serialization.
+   * The isolate is either created from scratch or from an existing snapshot.
+   * The caller keeps ownership of the argument snapshot.
+   * \param existing_blob existing snapshot from which to create this one.
+   * \param external_references a null-terminated array of external references
+   *        that must be equivalent to CreateParams::external_references.
+   */
+  SnapshotCreator(intptr_t* external_references = nullptr,
+                  StartupData* existing_blob = nullptr);
+
+  ~SnapshotCreator();
+
+  /**
+   * \returns the isolate prepared by the snapshot creator.
+   */
+  Isolate* GetIsolate();
+
+  /**
+   * Add a context to be included in the snapshot blob.
+   * \returns the index of the context in the snapshot blob.
+   */
+  size_t AddContext(Local<Context> context);
+
+  /**
+   * Add a template to be included in the snapshot blob.
+   * \returns the index of the template in the snapshot blob.
+   */
+  size_t AddTemplate(Local<Template> template_obj);
+
+  /**
+   * Created a snapshot data blob.
+   * This must not be called from within a handle scope.
+   * \param function_code_handling whether to include compiled function code
+   *        in the snapshot.
+   * \returns { nullptr, 0 } on failure, and a startup snapshot on success. The
+   *        caller acquires ownership of the data array in the return value.
+   */
+  StartupData CreateBlob(FunctionCodeHandling function_code_handling);
+
+ private:
+  void* data_;
+
+  // Disallow copying and assigning.
+  SnapshotCreator(const SnapshotCreator&);
+  void operator=(const SnapshotCreator&);
+};
 
 /**
  * A simple Maybe type, representing an object which may or may not have a
@@ -6975,7 +7143,8 @@
   static Local<Context> New(
       Isolate* isolate, ExtensionConfiguration* extensions = NULL,
       Local<ObjectTemplate> global_template = Local<ObjectTemplate>(),
-      Local<Value> global_object = Local<Value>());
+      Local<Value> global_object = Local<Value>(),
+      size_t context_snapshot_index = 0);
 
   /**
    * Sets the security token for the context.  To access an object in
@@ -7330,7 +7499,7 @@
       1 * kApiPointerSize + kApiIntSize;
   static const int kStringResourceOffset = 3 * kApiPointerSize;
 
-  static const int kOddballKindOffset = 5 * kApiPointerSize;
+  static const int kOddballKindOffset = 5 * kApiPointerSize + sizeof(double);
   static const int kForeignAddressOffset = kApiPointerSize;
   static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
   static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
@@ -7342,13 +7511,12 @@
   static const int kExternalOneByteRepresentationTag = 0x06;
 
   static const int kIsolateEmbedderDataOffset = 0 * kApiPointerSize;
-  static const int kAmountOfExternalAllocatedMemoryOffset =
-      4 * kApiPointerSize;
-  static const int kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset =
-      kAmountOfExternalAllocatedMemoryOffset + kApiInt64Size;
-  static const int kIsolateRootsOffset =
-      kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset + kApiInt64Size +
-      kApiPointerSize;
+  static const int kExternalMemoryOffset = 4 * kApiPointerSize;
+  static const int kExternalMemoryLimitOffset =
+      kExternalMemoryOffset + kApiInt64Size;
+  static const int kIsolateRootsOffset = kExternalMemoryLimitOffset +
+                                         kApiInt64Size + kApiInt64Size +
+                                         kApiPointerSize + kApiPointerSize;
   static const int kUndefinedValueRootIndex = 4;
   static const int kTheHoleValueRootIndex = 5;
   static const int kNullValueRootIndex = 6;
@@ -7356,10 +7524,6 @@
   static const int kFalseValueRootIndex = 8;
   static const int kEmptyStringRootIndex = 9;
 
-  // The external allocation limit should be below 256 MB on all architectures
-  // to avoid that resource-constrained embedders run low on memory.
-  static const int kExternalAllocationLimit = 192 * 1024 * 1024;
-
   static const int kNodeClassIdOffset = 1 * kApiPointerSize;
   static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
   static const int kNodeStateMask = 0x7;
@@ -7370,7 +7534,8 @@
   static const int kNodeIsPartiallyDependentShift = 4;
   static const int kNodeIsActiveShift = 4;
 
-  static const int kJSObjectType = 0xb8;
+  static const int kJSObjectType = 0xb7;
+  static const int kJSApiObjectType = 0xb6;
   static const int kFirstNonstringType = 0x80;
   static const int kOddballType = 0x83;
   static const int kForeignType = 0x87;
@@ -7624,39 +7789,6 @@
 
 
 template <class T>
-template <typename S, typename P>
-void PersistentBase<T>::SetWeak(
-    P* parameter,
-    typename WeakCallbackData<S, P>::Callback callback) {
-  TYPE_CHECK(S, T);
-  typedef typename WeakCallbackData<Value, void>::Callback Callback;
-  V8::MakeWeak(reinterpret_cast<internal::Object**>(this->val_), parameter,
-               reinterpret_cast<Callback>(callback));
-}
-
-
-template <class T>
-template <typename P>
-void PersistentBase<T>::SetWeak(
-    P* parameter,
-    typename WeakCallbackData<T, P>::Callback callback) {
-  SetWeak<T, P>(parameter, callback);
-}
-
-
-template <class T>
-template <typename P>
-void PersistentBase<T>::SetPhantom(
-    P* parameter, typename WeakCallbackInfo<P>::Callback callback,
-    int internal_field_index1, int internal_field_index2) {
-  typedef typename WeakCallbackInfo<void>::Callback Callback;
-  V8::MakeWeak(reinterpret_cast<internal::Object**>(this->val_), parameter,
-               internal_field_index1, internal_field_index2,
-               reinterpret_cast<Callback>(callback));
-}
-
-
-template <class T>
 template <typename P>
 V8_INLINE void PersistentBase<T>::SetWeak(
     P* parameter, typename WeakCallbackInfo<P>::Callback callback,
@@ -7666,6 +7798,10 @@
                reinterpret_cast<Callback>(callback), type);
 }
 
+template <class T>
+void PersistentBase<T>::SetWeak() {
+  V8::MakeWeak(reinterpret_cast<internal::Object***>(&this->val_));
+}
 
 template <class T>
 template <typename P>
@@ -7675,7 +7811,7 @@
 }
 
 template <class T>
-void PersistentBase<T>::RegisterExternalReference(Isolate* isolate) {
+void PersistentBase<T>::RegisterExternalReference(Isolate* isolate) const {
   if (IsEmpty()) return;
   V8::RegisterExternallyReferencedObject(
       reinterpret_cast<internal::Object**>(this->val_),
@@ -7857,17 +7993,11 @@
   return value_[-1];
 }
 
-
-template<typename T>
+template <typename T>
 FunctionCallbackInfo<T>::FunctionCallbackInfo(internal::Object** implicit_args,
                                               internal::Object** values,
-                                              int length,
-                                              bool is_construct_call)
-    : implicit_args_(implicit_args),
-      values_(values),
-      length_(length),
-      is_construct_call_(is_construct_call) { }
-
+                                              int length)
+    : implicit_args_(implicit_args), values_(values), length_(length) {}
 
 template<typename T>
 Local<Value> FunctionCallbackInfo<T>::operator[](int i) const {
@@ -7895,8 +8025,13 @@
       &implicit_args_[kHolderIndex]));
 }
 
+template <typename T>
+Local<Value> FunctionCallbackInfo<T>::NewTarget() const {
+  return Local<Value>(
+      reinterpret_cast<Value*>(&implicit_args_[kNewTargetIndex]));
+}
 
-template<typename T>
+template <typename T>
 Local<Value> FunctionCallbackInfo<T>::Data() const {
   return Local<Value>(reinterpret_cast<Value*>(&implicit_args_[kDataIndex]));
 }
@@ -7916,7 +8051,7 @@
 
 template<typename T>
 bool FunctionCallbackInfo<T>::IsConstructCall() const {
-  return is_construct_call_ & 0x1;
+  return !NewTarget()->IsUndefined();
 }
 
 
@@ -8010,7 +8145,9 @@
   O* obj = *reinterpret_cast<O**>(this);
   // Fast path: If the object is a plain JSObject, which is the common case, we
   // know where to find the internal fields and can return the value directly.
-  if (I::GetInstanceType(obj) == I::kJSObjectType) {
+  auto instance_type = I::GetInstanceType(obj);
+  if (instance_type == I::kJSObjectType ||
+      instance_type == I::kJSApiObjectType) {
     int offset = I::kJSObjectHeaderSize + (internal::kApiPointerSize * index);
     O* value = I::ReadField<O*>(obj, offset);
     O** result = HandleScope::CreateHandle(reinterpret_cast<HO*>(obj), value);
@@ -8028,7 +8165,9 @@
   O* obj = *reinterpret_cast<O**>(this);
   // Fast path: If the object is a plain JSObject, which is the common case, we
   // know where to find the internal fields and can return the value directly.
-  if (V8_LIKELY(I::GetInstanceType(obj) == I::kJSObjectType)) {
+  auto instance_type = I::GetInstanceType(obj);
+  if (V8_LIKELY(instance_type == I::kJSObjectType ||
+                instance_type == I::kJSApiObjectType)) {
     int offset = I::kJSObjectHeaderSize + (internal::kApiPointerSize * index);
     return I::ReadField<void*>(obj, offset);
   }
@@ -8579,21 +8718,16 @@
 int64_t Isolate::AdjustAmountOfExternalAllocatedMemory(
     int64_t change_in_bytes) {
   typedef internal::Internals I;
-  int64_t* amount_of_external_allocated_memory =
-      reinterpret_cast<int64_t*>(reinterpret_cast<uint8_t*>(this) +
-                                 I::kAmountOfExternalAllocatedMemoryOffset);
-  int64_t* amount_of_external_allocated_memory_at_last_global_gc =
-      reinterpret_cast<int64_t*>(
-          reinterpret_cast<uint8_t*>(this) +
-          I::kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset);
-  int64_t amount = *amount_of_external_allocated_memory + change_in_bytes;
-  if (change_in_bytes > 0 &&
-      amount - *amount_of_external_allocated_memory_at_last_global_gc >
-          I::kExternalAllocationLimit) {
+  int64_t* external_memory = reinterpret_cast<int64_t*>(
+      reinterpret_cast<uint8_t*>(this) + I::kExternalMemoryOffset);
+  const int64_t external_memory_limit = *reinterpret_cast<int64_t*>(
+      reinterpret_cast<uint8_t*>(this) + I::kExternalMemoryLimitOffset);
+  const int64_t amount = *external_memory + change_in_bytes;
+  *external_memory = amount;
+  if (change_in_bytes > 0 && amount > external_memory_limit) {
     ReportExternalAllocationLimitReached();
   }
-  *amount_of_external_allocated_memory = amount;
-  return *amount_of_external_allocated_memory;
+  return *external_memory;
 }
 
 
@@ -8708,21 +8842,6 @@
       reinterpret_cast<v8::Isolate::GCCallback>(callback));
 }
 
-
-void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback,
-                                     ObjectSpace space,
-                                     AllocationAction action) {
-  Isolate* isolate = Isolate::GetCurrent();
-  isolate->AddMemoryAllocationCallback(callback, space, action);
-}
-
-
-void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) {
-  Isolate* isolate = Isolate::GetCurrent();
-  isolate->RemoveMemoryAllocationCallback(callback);
-}
-
-
 void V8::TerminateExecution(Isolate* isolate) { isolate->TerminateExecution(); }
 
 
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg
index 5f85111..4c42cf6 100644
--- a/infra/config/cq.cfg
+++ b/infra/config/cq.cfg
@@ -25,17 +25,33 @@
 
   try_job {
     buckets {
-      name: "tryserver.v8"
+      name: "master.tryserver.v8"
       builders { name: "v8_android_arm_compile_rel" }
-      builders { name: "v8_linux64_asan_rel" }
-      builders { name: "v8_linux64_avx2_rel" }
+      builders { name: "v8_linux64_asan_rel_ng" }
+      builders {
+        name: "v8_linux64_asan_rel_ng_triggered"
+        triggered_by: "v8_linux64_asan_rel_ng"
+      }
+      builders { name: "v8_linux64_avx2_rel_ng" }
+      builders {
+        name: "v8_linux64_avx2_rel_ng_triggered"
+        triggered_by: "v8_linux64_avx2_rel_ng"
+      }
       builders { name: "v8_linux64_rel_ng" }
       builders {
         name: "v8_linux64_rel_ng_triggered"
         triggered_by: "v8_linux64_rel_ng"
       }
-      builders { name: "v8_linux_arm64_rel" }
-      builders { name: "v8_linux_arm_rel" }
+      builders { name: "v8_linux_arm64_rel_ng" }
+      builders {
+        name: "v8_linux_arm64_rel_ng_triggered"
+        triggered_by: "v8_linux_arm64_rel_ng"
+      }
+      builders { name: "v8_linux_arm_rel_ng" }
+      builders {
+        name: "v8_linux_arm_rel_ng_triggered"
+        triggered_by: "v8_linux_arm_rel_ng"
+      }
       builders { name: "v8_linux_chromium_gn_rel" }
       builders { name: "v8_linux_dbg_ng" }
       builders {
@@ -45,13 +61,21 @@
       builders { name: "v8_linux_gcc_compile_rel" }
       builders { name: "v8_linux_mipsel_compile_rel" }
       builders { name: "v8_linux_mips64el_compile_rel" }
-      builders { name: "v8_linux_nodcheck_rel" }
+      builders { name: "v8_linux_nodcheck_rel_ng" }
+      builders {
+        name: "v8_linux_nodcheck_rel_ng_triggered"
+        triggered_by: "v8_linux_nodcheck_rel_ng"
+      }
       builders { name: "v8_linux_rel_ng" }
       builders {
         name: "v8_linux_rel_ng_triggered"
         triggered_by: "v8_linux_rel_ng"
       }
-      builders { name: "v8_mac_rel" }
+      builders { name: "v8_mac_rel_ng" }
+      builders {
+        name: "v8_mac_rel_ng_triggered"
+        triggered_by: "v8_mac_rel_ng"
+      }
       builders { name: "v8_presubmit" }
       builders { name: "v8_win64_rel_ng" }
       builders {
@@ -59,7 +83,11 @@
         triggered_by: "v8_win64_rel_ng"
       }
       builders { name: "v8_win_compile_dbg" }
-      builders { name: "v8_win_nosnap_shared_compile_rel" }
+      builders { name: "v8_win_nosnap_shared_rel_ng" }
+      builders {
+        name: "v8_win_nosnap_shared_rel_ng_triggered"
+        triggered_by: "v8_win_nosnap_shared_rel_ng"
+      }
       builders { name: "v8_win_rel_ng" }
       builders {
         name: "v8_win_rel_ng_triggered"
@@ -67,7 +95,7 @@
       }
       builders {
         name: "v8_linux_blink_rel"
-        experiment_percentage: 20
+        experiment_percentage: 100
       }
       builders {
         name: "v8_linux64_sanitizer_coverage_rel"
diff --git a/infra/mb/PRESUBMIT.py b/infra/mb/PRESUBMIT.py
new file mode 100644
index 0000000..39d15e8
--- /dev/null
+++ b/infra/mb/PRESUBMIT.py
@@ -0,0 +1,35 @@
+# Copyright 2016 the V8 project authors. All rights reserved.
+# Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS.  All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+
+def _CommonChecks(input_api, output_api):
+  results = []
+
+  # Validate the format of the mb_config.pyl file.
+  mb_script = input_api.os_path.join(input_api.PresubmitLocalPath(), '..',
+                                     '..', 'tools', 'mb', 'mb.py')
+  mb_config_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
+                                          'mb_config.pyl')
+  cmd = [input_api.python_executable, mb_script, 'validate', '--config-file',
+         mb_config_path]
+  kwargs = {'cwd': input_api.PresubmitLocalPath()}
+  results.extend(input_api.RunTests([
+      input_api.Command(name='mb_validate',
+                        cmd=cmd, kwargs=kwargs,
+                        message=output_api.PresubmitError)]))
+
+  return results
+
+
+def CheckChangeOnUpload(input_api, output_api):
+  return _CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+  return _CommonChecks(input_api, output_api)
diff --git a/infra/mb/mb_config.pyl b/infra/mb/mb_config.pyl
new file mode 100644
index 0000000..e290ccc
--- /dev/null
+++ b/infra/mb/mb_config.pyl
@@ -0,0 +1,619 @@
+# Copyright 2016 The V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  # This is a map of buildbot master names -> buildbot builder names ->
+  # config names (where each config name is a key in the 'configs' dict,
+  # below). MB uses this dict to look up which config to use for a given bot.
+  # Bots are ordered by appearance on waterfall.
+  'masters': {
+    'client.dart.fyi': {
+      'v8-linux-release': 'gyp_release_x86_disassembler',
+      'v8-win-release': 'gyp_release_x86_disassembler',
+      'v8-mac-release': 'gyp_release_x86_disassembler',
+    },
+    'client.dynamorio': {
+      'linux-v8-dr': 'gyp_release_x64',
+    },
+    'client.v8': {
+      # Linux.
+      'V8 Linux - builder': 'gyp_release_x86_gcmole',
+      'V8 Linux - debug builder': 'gyp_debug_x86',
+      'V8 Linux - nosnap builder': 'gyp_release_x86_no_snap',
+      'V8 Linux - nosnap debug builder': 'gyp_debug_x86_no_snap',
+      'V8 Linux - shared': 'gyp_release_x86_shared_verify_heap',
+      'V8 Linux - noi18n - debug': 'gyp_debug_x86_no_i18n',
+      # Linux64.
+      'V8 Linux64 - builder': 'gyp_release_x64',
+      'V8 Linux64 - debug builder': 'gyp_debug_x64_valgrind',
+      'V8 Linux64 - custom snapshot - debug builder': 'gyp_debug_x64_custom',
+      'V8 Linux64 - internal snapshot': 'gyp_release_x64_internal',
+      # Windows.
+      'V8 Win32 - builder': 'gyp_release_x86_minimal_symbols',
+      'V8 Win32 - debug builder': 'gyp_debug_x86_minimal_symbols',
+      'V8 Win32 - nosnap - shared':
+        'gyp_release_x86_no_snap_shared_minimal_symbols',
+      'V8 Win64': 'gyp_release_x64_minimal_symbols',
+      'V8 Win64 - debug': 'gyp_debug_x64_minimal_symbols',
+      'V8 Win64 - clang': 'gyp_release_x64_clang',
+      # Mac.
+      'V8 Mac': 'gyp_release_x86',
+      'V8 Mac - debug': 'gyp_debug_x86',
+      'V8 Mac64': 'gyp_release_x64',
+      'V8 Mac64 - debug': 'gyp_debug_x64',
+      'V8 Mac GC Stress': 'gyp_debug_x86',
+      'V8 Mac64 ASAN': 'gyp_release_x64_asan',
+      # Sanitizers.
+      'V8 Linux64 ASAN': 'gyp_release_x64_asan',
+      'V8 Linux64 TSAN': 'gyp_release_x64_tsan',
+      'V8 Linux - arm64 - sim - MSAN': 'gyp_release_simulate_arm64_msan',
+      # Clusterfuzz.
+      'V8 Linux64 ASAN no inline - release builder':
+          'gyp_release_x64_asan_symbolized_edge_verify_heap',
+      'V8 Linux64 ASAN - debug builder': 'gyp_debug_x64_asan_edge',
+      'V8 Linux64 ASAN arm64 - debug builder':
+          'gyp_debug_simulate_arm64_asan_edge',
+      'V8 Linux ASAN arm - debug builder':
+          'gyp_debug_simulate_arm_asan_edge',
+      'V8 Linux ASAN mipsel - debug builder':
+          'gyp_debug_simulate_mipsel_asan_edge',
+      # Misc.
+      'V8 Linux gcc 4.8': 'gyp_release_x86_gcc',
+      # FYI.
+      'V8 Linux - swarming staging': 'gn_release_x64',
+      # TODO(machenbach): Figure out if symbolized is still needed. The
+      # original config also specified -O1, which we dropped because chromium
+      # doesn't have it (anymore).
+      'V8 Linux64 - cfi': 'gyp_release_x64_cfi_symbolized',
+      'V8 Linux - vtunejit': 'gyp_debug_x86_vtunejit',
+      'V8 Linux64 - gcov coverage': 'gyp_release_x64_gcc_coverage',
+      'V8 Linux - predictable': 'gyp_release_x86_predictable',
+      'V8 Linux - full debug': 'gyp_full_debug_x86',
+      'V8 Linux - interpreted regexp': 'gyp_release_x86_interpreted_regexp',
+      'V8 Random Deopt Fuzzer - debug': 'gyp_debug_x86',
+    },
+
+    'client.v8.ports': {
+      # Arm.
+      'V8 Arm - builder': 'gyp_release_arm',
+      'V8 Arm - debug builder': 'gyp_debug_arm',
+      'V8 Android Arm - builder': 'gyp_release_android_arm',
+      'V8 Linux - arm - sim': 'gyp_release_simulate_arm',
+      'V8 Linux - arm - sim - debug': 'gyp_debug_simulate_arm',
+      # Arm64.
+      'V8 Android Arm64 - builder': 'gyp_release_android_arm64',
+      'V8 Linux - arm64 - sim': 'gyp_release_simulate_arm64',
+      'V8 Linux - arm64 - sim - debug': 'gyp_debug_simulate_arm64',
+      'V8 Linux - arm64 - sim - nosnap - debug':
+          'gyp_debug_simulate_arm64_no_snap',
+      'V8 Linux - arm64 - sim - gc stress': 'gyp_debug_simulate_arm64',
+      # Mips.
+      'V8 Mips - builder': 'gyp_release_mips_no_snap_no_i18n',
+      'V8 Linux - mipsel - sim - builder': 'gyp_release_simulate_mipsel',
+      'V8 Linux - mips64el - sim - builder': 'gyp_release_simulate_mips64el',
+      # PPC.
+      'V8 Linux - ppc - sim': 'gyp_release_simulate_ppc',
+      'V8 Linux - ppc64 - sim': 'gyp_release_simulate_ppc64',
+      # S390.
+      'V8 Linux - s390 - sim': 'gyp_release_simulate_s390',
+      'V8 Linux - s390x - sim': 'gyp_release_simulate_s390x',
+      # X87.
+      'V8 Linux - x87 - nosnap - debug builder':
+          'gyp_debug_simulate_x87_no_snap',
+    },
+    'client.v8.branches': {
+      'V8 Linux - beta branch': 'gyp_release_x86',
+      'V8 Linux - beta branch - debug': 'gyp_debug_x86',
+      'V8 Linux - stable branch': 'gyp_release_x86',
+      'V8 Linux - stable branch - debug': 'gyp_debug_x86',
+      'V8 Linux64 - beta branch': 'gyp_release_x64',
+      'V8 Linux64 - beta branch - debug': 'gyp_debug_x64',
+      'V8 Linux64 - stable branch': 'gyp_release_x64',
+      'V8 Linux64 - stable branch - debug': 'gyp_debug_x64',
+      'V8 arm - sim - beta branch': 'gyp_release_simulate_arm',
+      'V8 arm - sim - beta branch - debug': 'gyp_debug_simulate_arm',
+      'V8 arm - sim - stable branch': 'gyp_release_simulate_arm',
+      'V8 arm - sim - stable branch - debug': 'gyp_debug_simulate_arm',
+      'V8 mips64el - sim - beta branch': 'gyp_release_simulate_mips64el',
+      'V8 mips64el - sim - stable branch': 'gyp_release_simulate_mips64el',
+      'V8 mipsel - sim - beta branch': 'gyp_release_simulate_mipsel',
+      'V8 mipsel - sim - stable branch': 'gyp_release_simulate_mipsel',
+      'V8 ppc - sim - beta branch': 'gyp_release_simulate_ppc',
+      'V8 ppc - sim - stable branch': 'gyp_release_simulate_ppc',
+      'V8 ppc64 - sim - beta branch': 'gyp_release_simulate_ppc64',
+      'V8 ppc64 - sim - stable branch': 'gyp_release_simulate_ppc64',
+      'V8 s390 - sim - beta branch': 'gyp_release_simulate_s390',
+      'V8 s390 - sim - stable branch': 'gyp_release_simulate_s390',
+      'V8 s390x - sim - beta branch': 'gyp_release_simulate_s390x',
+      'V8 s390x - sim - stable branch': 'gyp_release_simulate_s390x',
+    },
+    'tryserver.v8': {
+      'v8_linux_rel_ng': 'gyp_release_x86_gcmole_trybot',
+      'v8_linux_avx2_dbg': 'gyp_debug_x86_trybot',
+      'v8_linux_nodcheck_rel_ng': 'gyp_release_x86_minimal_symbols',
+      'v8_linux_dbg_ng': 'gyp_debug_x86_trybot',
+      'v8_linux_noi18n_rel_ng': 'gyp_release_x86_no_i18n_trybot',
+      'v8_linux_gc_stress_dbg': 'gyp_debug_x86_trybot',
+      'v8_linux_nosnap_rel': 'gyp_release_x86_no_snap_trybot',
+      'v8_linux_nosnap_dbg': 'gyp_debug_x86_no_snap_trybot',
+      'v8_linux_gcc_compile_rel': 'gyp_release_x86_gcc_minimal_symbols',
+      'v8_linux_gcc_rel': 'gyp_release_x86_gcc_minimal_symbols',
+      'v8_linux64_rel_ng': 'gyp_release_x64_trybot',
+      'v8_linux64_avx2_rel_ng': 'gyp_release_x64_trybot',
+      'v8_linux64_avx2_dbg': 'gyp_debug_x64_trybot',
+      'v8_linux64_asan_rel_ng': 'gyp_release_x64_asan_minimal_symbols',
+      'v8_linux64_msan_rel': 'gyp_release_simulate_arm64_msan_minimal_symbols',
+      'v8_linux64_sanitizer_coverage_rel':
+          'gyp_release_x64_asan_minimal_symbols_coverage',
+      'v8_linux64_tsan_rel': 'gyp_release_x64_tsan_minimal_symbols',
+      'v8_win_dbg': 'gyp_debug_x86_trybot',
+      'v8_win_compile_dbg': 'gyp_debug_x86_trybot',
+      'v8_win_rel_ng': 'gyp_release_x86_trybot',
+      'v8_win_nosnap_shared_rel_ng':
+        'gyp_release_x86_no_snap_shared_minimal_symbols',
+      'v8_win64_dbg': 'gyp_debug_x64_minimal_symbols',
+      'v8_win64_rel_ng': 'gyp_release_x64_trybot',
+      'v8_mac_rel_ng': 'gyp_release_x86_trybot',
+      'v8_mac_dbg': 'gyp_debug_x86_trybot',
+      'v8_mac_gc_stress_dbg': 'gyp_debug_x86_trybot',
+      'v8_mac64_rel': 'gyp_release_x64_trybot',
+      'v8_mac64_dbg': 'gyp_debug_x64_minimal_symbols',
+      'v8_mac64_asan_rel': 'gyp_release_x64_asan',
+      'v8_linux_arm_rel_ng': 'gyp_release_simulate_arm_trybot',
+      'v8_linux_arm_dbg': 'gyp_debug_simulate_arm',
+      'v8_linux_arm_armv8a_rel': 'gyp_release_simulate_arm_trybot',
+      'v8_linux_arm_armv8a_dbg': 'gyp_debug_simulate_arm',
+      'v8_linux_arm64_rel_ng': 'gyp_release_simulate_arm64_trybot',
+      'v8_linux_arm64_dbg': 'gyp_debug_simulate_arm64',
+      'v8_linux_arm64_gc_stress_dbg': 'gyp_debug_simulate_arm64',
+      'v8_linux_mipsel_compile_rel': 'gyp_release_simulate_mipsel',
+      'v8_linux_mips64el_compile_rel': 'gyp_release_simulate_mips64el',
+      'v8_android_arm_compile_rel': 'gyp_release_android_arm',
+    },
+  },
+
+
+  # To ease readability, config values are ordered by:
+  # gyp/gn, release/debug, arch type, other values alphabetically.
+  'configs': {
+    # GN release configs for x64.
+    'gn_release_x64': [
+      'gn', 'release_bot', 'x64', 'swarming'],
+
+    # Gyp debug configs for arm.
+    'gyp_debug_arm': [
+      'gyp', 'debug_bot', 'arm', 'crosscompile', 'hard_float', 'swarming'],
+
+    # Gyp debug configs for simulators.
+    'gyp_debug_simulate_arm': [
+      'gyp', 'debug_bot', 'simulate_arm', 'swarming'],
+    'gyp_debug_simulate_arm_asan_edge': [
+      'gyp', 'debug_bot', 'simulate_arm', 'asan', 'edge'],
+    'gyp_debug_simulate_arm64': [
+      'gyp', 'debug_bot', 'simulate_arm64', 'swarming'],
+    'gyp_debug_simulate_arm64_asan_edge': [
+      'gyp', 'debug_bot', 'simulate_arm64', 'asan', 'lsan', 'edge'],
+    'gyp_debug_simulate_arm64_no_snap': [
+      'gyp', 'debug_bot', 'simulate_arm64', 'swarming', 'v8_snapshot_none'],
+    'gyp_debug_simulate_mipsel_asan_edge': [
+      'gyp', 'debug_bot', 'simulate_mipsel', 'asan', 'edge'],
+    'gyp_debug_simulate_x87_no_snap': [
+      'gyp', 'debug_bot', 'simulate_x87', 'v8_snapshot_none'],
+
+    # Gyp debug configs for x64.
+    'gyp_debug_x64': [
+      'gyp', 'debug_bot', 'x64', 'swarming'],
+    'gyp_debug_x64_asan_edge': [
+      'gyp', 'debug_bot', 'x64', 'asan', 'lsan', 'edge'],
+    'gyp_debug_x64_custom': [
+      'gyp', 'debug_bot', 'x64', 'swarming', 'v8_snapshot_custom'],
+    'gyp_debug_x64_minimal_symbols': [
+      'gyp', 'debug_bot', 'x64', 'minimal_symbols', 'swarming'],
+    'gyp_debug_x64_trybot': [
+      'gyp', 'debug_trybot', 'x64', 'swarming'],
+    'gyp_debug_x64_valgrind': [
+      'gyp', 'debug_bot', 'x64', 'swarming', 'valgrind'],
+
+    # Gyp debug configs for x86.
+    'gyp_debug_x86': [
+      'gyp', 'debug_bot', 'x86', 'swarming'],
+    'gyp_debug_x86_minimal_symbols': [
+      'gyp', 'debug_bot', 'x86', 'minimal_symbols', 'swarming'],
+    'gyp_debug_x86_trybot': [
+      'gyp', 'debug_trybot', 'x86', 'swarming'],
+    'gyp_debug_x86_no_i18n': [
+      'gyp', 'debug_bot', 'x86', 'v8_no_i18n'],
+    'gyp_debug_x86_no_snap': [
+      'gyp', 'debug_bot', 'x86', 'swarming', 'v8_snapshot_none'],
+    'gyp_debug_x86_no_snap_trybot': [
+      'gyp', 'debug_trybot', 'x86', 'swarming', 'v8_snapshot_none'],
+    'gyp_debug_x86_vtunejit': [
+      'gyp', 'debug_bot', 'x86', 'v8_enable_vtunejit'],
+    'gyp_full_debug_x86': [
+      'gyp', 'debug', 'x86', 'goma', 'static', 'v8_enable_slow_dchecks',
+      'v8_full_debug'],
+
+    # Gyp release configs for arm.
+    'gyp_release_arm': [
+      'gyp', 'release_bot', 'arm', 'crosscompile', 'hard_float', 'swarming'],
+    'gyp_release_android_arm': [
+      'gyp', 'release_bot', 'arm', 'android', 'crosscompile', 'swarming'],
+    'gyp_release_android_arm64': [
+      'gyp', 'release_bot', 'arm64', 'android', 'crosscompile', 'swarming'],
+
+    # Gyp release configs for mips.
+    'gyp_release_mips_no_snap_no_i18n': [
+      'gyp', 'release', 'mips', 'crosscompile', 'static', 'v8_no_i18n',
+      'v8_snapshot_none'],
+
+    # Gyp release configs for simulators.
+    'gyp_release_simulate_arm': [
+      'gyp', 'release_bot', 'simulate_arm', 'swarming'],
+    'gyp_release_simulate_arm_trybot': [
+      'gyp', 'release_trybot', 'simulate_arm', 'swarming'],
+    'gyp_release_simulate_arm64': [
+      'gyp', 'release_bot', 'simulate_arm64', 'swarming'],
+    'gyp_release_simulate_arm64_msan': [
+      'gyp', 'release_bot', 'simulate_arm64', 'msan', 'swarming'],
+    'gyp_release_simulate_arm64_msan_minimal_symbols': [
+      'gyp', 'release_bot', 'simulate_arm64', 'msan', 'minimal_symbols',
+      'swarming'],
+    'gyp_release_simulate_arm64_trybot': [
+      'gyp', 'release_trybot', 'simulate_arm64', 'swarming'],
+    'gyp_release_simulate_mipsel': [
+      'gyp', 'release_bot', 'simulate_mipsel', 'swarming'],
+    'gyp_release_simulate_mips64el': [
+      'gyp', 'release_bot', 'simulate_mips64el', 'swarming'],
+    'gyp_release_simulate_ppc': [
+      'gyp', 'release_bot', 'simulate_ppc', 'swarming'],
+    'gyp_release_simulate_ppc64': [
+      'gyp', 'release_bot', 'simulate_ppc64', 'swarming'],
+    'gyp_release_simulate_s390': [
+      'gyp', 'release_bot', 'simulate_s390', 'swarming'],
+    'gyp_release_simulate_s390x': [
+      'gyp', 'release_bot', 'simulate_s390x', 'swarming'],
+
+    # Gyp release configs for x64.
+    'gyp_release_x64': [
+      'gyp', 'release_bot', 'x64', 'swarming'],
+    'gyp_release_x64_asan': [
+      'gyp', 'release_bot', 'x64', 'asan', 'lsan', 'swarming'],
+    'gyp_release_x64_asan_minimal_symbols': [
+      'gyp', 'release_bot', 'x64', 'asan', 'lsan', 'minimal_symbols',
+      'swarming'],
+    'gyp_release_x64_asan_minimal_symbols_coverage': [
+      'gyp', 'release_bot', 'x64', 'asan', 'bb', 'coverage', 'lsan',
+      'minimal_symbols', 'swarming'],
+    'gyp_release_x64_asan_symbolized_edge_verify_heap': [
+      'gyp', 'release_bot', 'x64', 'asan', 'edge', 'lsan', 'symbolized',
+      'v8_verify_heap'],
+    'gyp_release_x64_cfi_symbolized': [
+      'gyp', 'release_bot', 'x64', 'cfi', 'swarming', 'symbolized'],
+    'gyp_release_x64_clang': [
+      'gyp', 'release_bot', 'x64', 'clang', 'swarming'],
+    'gyp_release_x64_gcc_coverage': [
+      'gyp', 'release_bot', 'x64', 'coverage', 'gcc'],
+    'gyp_release_x64_minimal_symbols': [
+      'gyp', 'release_bot', 'x64', 'minimal_symbols', 'swarming'],
+    'gyp_release_x64_tsan': [
+      'gyp', 'release_bot', 'x64', 'tsan', 'swarming'],
+    'gyp_release_x64_tsan_minimal_symbols': [
+      'gyp', 'release_bot', 'x64', 'tsan', 'minimal_symbols', 'swarming'],
+    'gyp_release_x64_internal': [
+      'gyp', 'release_bot', 'x64', 'swarming', 'v8_snapshot_internal'],
+    'gyp_release_x64_trybot': [
+      'gyp', 'release_trybot', 'x64', 'swarming'],
+
+    # Gyp release configs for x86.
+    'gyp_release_x86': [
+      'gyp', 'release_bot', 'x86', 'swarming'],
+    'gyp_release_x86_disassembler': [
+      'gyp', 'release_bot', 'x86', 'v8_enable_disassembler'],
+    'gyp_release_x86_gcc': [
+      'gyp', 'release_bot', 'x86', 'gcc'],
+    'gyp_release_x86_gcc_minimal_symbols': [
+      'gyp', 'release_bot', 'x86', 'gcc', 'minimal_symbols'],
+    'gyp_release_x86_interpreted_regexp': [
+      'gyp', 'release_bot', 'x86', 'v8_interpreted_regexp'],
+    'gyp_release_x86_gcmole': [
+      'gyp', 'release_bot', 'x86', 'gcmole', 'swarming'],
+    'gyp_release_x86_gcmole_trybot': [
+      'gyp', 'release_trybot', 'x86', 'gcmole', 'swarming'],
+    'gyp_release_x86_minimal_symbols': [
+      'gyp', 'release_bot', 'x86', 'minimal_symbols', 'swarming'],
+    'gyp_release_x86_no_i18n_trybot': [
+      'gyp', 'release_trybot', 'x86', 'swarming', 'v8_no_i18n'],
+    'gyp_release_x86_no_snap': [
+      'gyp', 'release_bot', 'x86', 'swarming', 'v8_snapshot_none'],
+    'gyp_release_x86_no_snap_shared_minimal_symbols': [
+      'gyp', 'release_bot', 'x86', 'minimal_symbols', 'shared', 'swarming',
+      'v8_snapshot_none'],
+    'gyp_release_x86_no_snap_trybot': [
+      'gyp', 'release_trybot', 'x86', 'swarming', 'v8_snapshot_none'],
+    'gyp_release_x86_predictable': [
+      'gyp', 'release_bot', 'x86', 'v8_enable_verify_predictable'],
+    'gyp_release_x86_shared_verify_heap': [
+      'gyp', 'release_bot', 'x86', 'shared', 'swarming', 'v8_verify_heap'],
+    'gyp_release_x86_trybot': [
+      'gyp', 'release_trybot', 'x86', 'swarming'],
+  },
+
+  'mixins': {
+    'android': {
+      'gn_args': 'target_os="android"',
+      'gyp_defines': 'OS=android',
+    },
+
+    'arm': {
+      'gn_args': 'target_cpu="arm"',
+      'gyp_defines': 'target_arch=arm',
+    },
+
+    'arm64': {
+      'gn_args': 'target_cpu="arm64"',
+      'gyp_defines': 'target_arch=arm64',
+    },
+
+    'asan': {
+      'gn_args': 'clang=true asan=true',
+      'gyp_defines': 'clang=1 asan=1',
+    },
+
+    'bb': {
+      'gn_args': 'sanitizer_coverage_flags="bb"',
+      'gyp_defines': 'sanitizer_coverage=bb',
+    },
+
+    'cfi': {
+      'gn_args': 'is_cfi=true use_cfi_diag=true',
+      'gyp_defines': 'cfi_vptr=1 cfi_diag=1',
+    },
+
+    'clang': {
+      'gn_args': 'clang=true',
+      'gyp_defines': 'clang=1',
+    },
+
+    'coverage': {
+      # TODO(machenbach): Add this to gn.
+      'gyp_defines': 'coverage=1',
+    },
+
+    'crosscompile': {
+      'gyp_crosscompile': True,
+    },
+
+    'dcheck_always_on': {
+      'gn_args': 'dcheck_always_on=true',
+      'gyp_defines': 'dcheck_always_on=1',
+    },
+
+    'debug': {
+      'gn_args': 'is_debug=true',
+    },
+
+    'debug_bot': {
+      'mixins': [
+        'debug', 'static', 'goma', 'v8_enable_slow_dchecks',
+        'v8_optimized_debug'],
+    },
+
+    'debug_trybot': {
+      'mixins': ['debug_bot', 'minimal_symbols'],
+    },
+
+    'edge': {
+      'gn_args': 'sanitizer_coverage_flags="edge"',
+      'gyp_defines': 'sanitizer_coverage=edge',
+    },
+
+    'gcc': {
+      'gn_args': 'clang=false',
+      'gyp_defines': 'clang=0',
+    },
+
+    'gcmole': {
+      # TODO(machenbach): Add this to gn.
+      'gn_args': 'gcmole=true',
+      'gyp_defines': 'gcmole=1',
+    },
+
+    'gn': {'type': 'gn'},
+
+    'goma': {
+      # The MB code will properly escape goma_dir if necessary in the GYP
+      # code path; the GN code path needs no escaping.
+      'gn_args': 'use_goma=true',
+      'gyp_defines': 'use_goma=1',
+    },
+
+    'gyp': {'type': 'gyp'},
+
+    'hard_float': {
+      'gn_args': 'arm_float_abi="hard"',
+      'gyp_defines': 'arm_float_abi=hard',
+    },
+
+    'lsan': {
+      'gn_args': 'lsan=true',
+      'gyp_defines': 'lsan=1',
+    },
+
+    'minimal_symbols': {
+      'gn_args': 'symbol_level=1',
+      'gyp_defines': 'fastbuild=1',
+    },
+
+    'mips': {
+      'gn_args': 'target_cpu="mips"',
+      'gyp_defines': 'target_arch=mips',
+    },
+
+    'msan': {
+      'gn_args': 'clang=true msan=true',
+      'gyp_defines': 'clang=1 msan=1',
+    },
+
+    'release': {
+      'gn_args': 'is_debug=false',
+    },
+
+    'release_bot': {
+      'mixins': ['release', 'static', 'goma'],
+    },
+
+    'release_trybot': {
+      'mixins': ['release_bot', 'minimal_symbols', 'dcheck_always_on'],
+    },
+
+    'shared': {
+      'gn_args': 'is_component_build=true',
+      'gyp_defines': 'component=shared_library',
+    },
+
+    'simulate_arm': {
+      'gn_args': 'target_cpu="ia32" v8_target_cpu="arm"',
+      'gyp_defines': 'target_arch=ia32 v8_target_arch=arm',
+    },
+
+    'simulate_arm64': {
+      'gn_args': 'target_cpu="x64" v8_target_cpu="arm64"',
+      'gyp_defines': 'target_arch=x64 v8_target_arch=arm64',
+    },
+
+    'simulate_mipsel': {
+      'gn_args': 'target_cpu="ia32" v8_target_cpu="mipsel"',
+      'gyp_defines': 'target_arch=ia32 v8_target_arch=mipsel',
+    },
+
+    'simulate_mips64el': {
+      'gn_args': 'target_cpu="x64" v8_target_cpu="mips64el"',
+      'gyp_defines': 'target_arch=x64 v8_target_arch=mips64el',
+    },
+
+    'simulate_ppc': {
+      'gn_args': 'target_cpu="ia32" v8_target_cpu="ppc"',
+      'gyp_defines': 'target_arch=ia32 v8_target_arch=ppc',
+    },
+
+    'simulate_ppc64': {
+      'gn_args': 'target_cpu="x64" v8_target_cpu="ppc64"',
+      'gyp_defines': 'target_arch=x64 v8_target_arch=ppc64',
+    },
+
+    'simulate_s390': {
+      'gn_args': 'target_cpu="ia32" v8_target_cpu="s390"',
+      'gyp_defines': 'target_arch=ia32 v8_target_arch=s390',
+    },
+
+    'simulate_s390x': {
+      'gn_args': 'target_cpu="x64" v8_target_cpu="s390x"',
+      'gyp_defines': 'target_arch=x64 v8_target_arch=s390x',
+    },
+
+    'simulate_x87': {
+      'gn_args': 'target_cpu="ia32" v8_target_cpu="x87"',
+      'gyp_defines': 'target_arch=ia32 v8_target_arch=x87',
+    },
+
+    'static': {
+      'gn_args': 'is_component_build=false',
+      'gyp_defines': 'component=static_library',
+    },
+
+    'swarming': {
+      'gn_args': 'v8_test_isolation_mode="prepare"',
+      'gyp_defines': 'test_isolation_mode=prepare',
+    },
+
+    # TODO(machenbach): Remove the symbolized config after the bots are  gone.
+    'symbolized': {
+      'gn_args': 'symbolized=true',
+      'gyp_defines':
+        'release_extra_cflags="-fno-inline-functions -fno-inline"',
+    },
+
+    'tsan': {
+      'gn_args': 'clang=true tsan=true',
+      'gyp_defines': 'clang=1 tsan=1',
+    },
+
+    'valgrind': {
+      # TODO(machenbach): Add this to gn.
+      'gn_args': 'has_valgrind=true',
+      'gyp_defines': 'has_valgrind=1',
+    },
+
+    'v8_no_i18n': {
+      'gn_args': 'v8_enable_i18n_support=false',
+      'gyp_defines': 'v8_enable_i18n_support=0',
+    },
+
+    'v8_enable_disassembler': {
+      'gn_args': 'v8_enable_disassembler=true',
+      'gyp_defines': 'v8_enable_disassembler=1',
+    },
+
+    'v8_enable_slow_dchecks': {
+      'gn_args': 'v8_enable_slow_dchecks=true',
+      'gyp_defines': 'v8_enable_slow_dchecks=1',
+    },
+
+    'v8_enable_verify_predictable': {
+      'gn_args': 'v8_enable_verify_predictable=true',
+      'gyp_defines': 'v8_enable_verify_predictable=1',
+    },
+
+    'v8_enable_vtunejit': {
+      'gn_args': 'v8_enable_vtunejit=true',
+      'gyp_defines': 'v8_enable_vtunejit=1',
+    },
+
+    'v8_full_debug': {
+      'gn_args': 'v8_optimized_debug=false',
+      'gyp_defines': 'v8_optimized_debug=0',
+    },
+
+    'v8_interpreted_regexp': {
+      'gn_args': 'v8_interpreted_regexp=true',
+      'gyp_defines': 'v8_interpreted_regexp=1',
+    },
+
+    'v8_optimized_debug': {
+      # This is the default in gn for debug.
+      'gyp_defines': 'v8_optimized_debug=1',
+    },
+
+    'v8_snapshot_custom': {
+      # TODO(machenbach): Add this to gn.
+      # Path needs to be relative to src/v8.gyp.
+      'gyp_defines': 'embed_script=../test/mjsunit/mjsunit.js',
+    },
+
+    'v8_snapshot_internal': {
+      'gn_args': 'v8_use_external_startup_data=false',
+      'gyp_defines': 'v8_use_external_startup_data=0',
+    },
+
+    'v8_snapshot_none': {
+      'gn_args': 'v8_use_snapshot=false',
+      'gyp_defines': 'v8_use_snapshot=false',
+    },
+
+    'v8_verify_heap': {
+      'gn_args': 'v8_enable_verify_heap=true',
+      'gyp_defines': 'v8_enable_verify_heap=1',
+    },
+
+    'x64': {
+      'gn_args': 'target_cpu="x64"',
+      'gyp_defines': 'target_arch=x64',
+    },
+
+    'x86': {
+      'gn_args': 'target_cpu="x86"',
+      'gyp_defines': 'target_arch=ia32',
+    },
+  },
+}
diff --git a/samples/hello-world.cc b/samples/hello-world.cc
index 3b952d8..902d8d5 100644
--- a/samples/hello-world.cc
+++ b/samples/hello-world.cc
@@ -24,7 +24,7 @@
 
 int main(int argc, char* argv[]) {
   // Initialize V8.
-  V8::InitializeICU();
+  V8::InitializeICUDefaultLocation(argv[0]);
   V8::InitializeExternalStartupData(argv[0]);
   Platform* platform = platform::CreateDefaultPlatform();
   V8::InitializePlatform(platform);
diff --git a/samples/process.cc b/samples/process.cc
index cfbd054..54c8376 100644
--- a/samples/process.cc
+++ b/samples/process.cc
@@ -687,7 +687,7 @@
 
 
 int main(int argc, char* argv[]) {
-  v8::V8::InitializeICU();
+  v8::V8::InitializeICUDefaultLocation(argv[0]);
   v8::V8::InitializeExternalStartupData(argv[0]);
   v8::Platform* platform = v8::platform::CreateDefaultPlatform();
   v8::V8::InitializePlatform(platform);
diff --git a/samples/samples.gyp b/samples/samples.gyp
index 7e0608b..e5e9ef0 100644
--- a/samples/samples.gyp
+++ b/samples/samples.gyp
@@ -29,13 +29,14 @@
   'variables': {
     'v8_code': 1,
     'v8_enable_i18n_support%': 1,
+    'v8_toolset_for_shell%': 'target',
   },
-  'includes': ['../build/toolchain.gypi', '../build/features.gypi'],
+  'includes': ['../gypfiles/toolchain.gypi', '../gypfiles/features.gypi'],
   'target_defaults': {
     'type': 'executable',
     'dependencies': [
-      '../tools/gyp/v8.gyp:v8',
-      '../tools/gyp/v8.gyp:v8_libplatform',
+      '../src/v8.gyp:v8',
+      '../src/v8.gyp:v8_libplatform',
     ],
     'include_dirs': [
       '..',
@@ -56,10 +57,15 @@
   },
   'targets': [
     {
-      'target_name': 'shell',
+      'target_name': 'v8_shell',
       'sources': [
         'shell.cc',
       ],
+      'conditions': [
+        [ 'want_separate_host_toolset==1', {
+          'toolsets': [ '<(v8_toolset_for_shell)', ],
+        }],
+      ],
     },
     {
       'target_name': 'hello-world',
diff --git a/samples/shell.cc b/samples/shell.cc
index b89ffdd..ad9b1ab 100644
--- a/samples/shell.cc
+++ b/samples/shell.cc
@@ -75,7 +75,7 @@
 
 
 int main(int argc, char* argv[]) {
-  v8::V8::InitializeICU();
+  v8::V8::InitializeICUDefaultLocation(argv[0]);
   v8::V8::InitializeExternalStartupData(argv[0]);
   v8::Platform* platform = v8::platform::CreateDefaultPlatform();
   v8::V8::InitializePlatform(platform);
diff --git a/snapshot_toolchain.gni b/snapshot_toolchain.gni
index 4932110..ccee7ff 100644
--- a/snapshot_toolchain.gni
+++ b/snapshot_toolchain.gni
@@ -25,22 +25,52 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-# The snapshot needs to be compiled for the host, but compiled with
-# a toolchain that matches the bit-width of the target.
+declare_args() {
+  # The snapshot needs to be compiled for the host, but compiled with
+  # a toolchain that matches the bit-width of the target.
+  v8_snapshot_toolchain = ""
+}
 
 # TODO(GYP): For now we only support 32-bit little-endian target builds from an
 # x64 Linux host. Eventually we need to support all of the host/target
 # configurations v8 runs on.
-if (host_cpu == "x64" && host_os == "linux") {
-  if (target_cpu == "arm" || target_cpu == "mipsel" || target_cpu == "x86") {
-    snapshot_toolchain = "//build/toolchain/linux:clang_x86"
-  } else if (target_cpu == "x64" || target_cpu == "arm64" || target_cpu == "mips64el") {
-    snapshot_toolchain = "//build/toolchain/linux:clang_x64"
+if (v8_snapshot_toolchain == "") {
+  if (host_cpu == "x64" && host_os == "linux") {
+    if (target_cpu == "arm" || target_cpu == "mipsel" || target_cpu == "x86") {
+      if (target_os == "android" || is_clang) {
+        v8_snapshot_toolchain = "//build/toolchain/linux:clang_x86"
+      } else if (target_os == "chromeos") {
+        # TODO(dpranke): crbug.com/608596: Remove this clause once the
+        # CrOS ebuilds are setting v8_snapshot_toolchain directly and
+        # we've cleaned up the sysroot settings in //build.
+        v8_snapshot_toolchain = "//build/toolchain/linux:clang_x86"
+      } else {
+        v8_snapshot_toolchain = "//build/toolchain/linux:x86"
+      }
+
+    } else if (target_cpu == "x64" || target_cpu == "arm64" ||
+               target_cpu == "mips64el") {
+      if (target_os == "android" || is_clang) {
+        v8_snapshot_toolchain = "//build/toolchain/linux:clang_x64"
+      } else if (target_os == "chromeos") {
+        # TODO(dpranke): crbug.com/608596: Remove this clause once the
+        # CrOS ebuilds are setting v8_snapshot_toolchain directly and
+        # we've cleaned up the sysroot settings in //build.
+        v8_snapshot_toolchain = "//build/toolchain/linux:clang_x64"
+      } else {
+        v8_snapshot_toolchain = "//build/toolchain/linux:x64"
+      }
+    } else {
+      assert(false, "Need environment for this arch: $target_cpu")
+    }
+  } else if (host_os == "mac" && target_os == "win") {
+    v8_snapshot_toolchain = "//build/toolchain/mac:clang_$target_cpu"
   } else {
-    assert(false, "Need environment for this arch: $target_cpu")
+    v8_snapshot_toolchain = default_toolchain
   }
-} else {
-  snapshot_toolchain = default_toolchain
 }
 
-
+# TODO(dpranke): snapshot_toolchain is provided for backwards compatibility
+# and should be removed once all callers are updated to refer to
+# v8_snapshot_toolchain directly.
+snapshot_toolchain = v8_snapshot_toolchain
diff --git a/src/DEPS b/src/DEPS
index 1bb616e..00c7f1f 100644
--- a/src/DEPS
+++ b/src/DEPS
@@ -3,7 +3,7 @@
   "+src",
   "-src/compiler",
   "+src/compiler/pipeline.h",
-  "+src/compiler/code-stub-assembler.h",
+  "+src/compiler/code-assembler.h",
   "+src/compiler/wasm-compiler.h",
   "-src/heap",
   "+src/heap/heap.h",
diff --git a/src/accessors.cc b/src/accessors.cc
index 374c0a2..74238eb 100644
--- a/src/accessors.cc
+++ b/src/accessors.cc
@@ -40,6 +40,11 @@
   Handle<Object> set = v8::FromCData(isolate, setter);
   info->set_getter(*get);
   info->set_setter(*set);
+  Address redirected = info->redirected_getter();
+  if (redirected != nullptr) {
+    Handle<Object> js_get = v8::FromCData(isolate, redirected);
+    info->set_js_getter(*js_get);
+  }
   return info;
 }
 
@@ -81,57 +86,11 @@
 }
 
 
-bool Accessors::IsJSArrayBufferViewFieldAccessor(Handle<Map> map,
-                                                 Handle<Name> name,
-                                                 int* object_offset) {
-  DCHECK(name->IsUniqueName());
-  Isolate* isolate = name->GetIsolate();
+namespace {
 
-  switch (map->instance_type()) {
-    case JS_TYPED_ARRAY_TYPE: {
-      if (!CheckForName(name, isolate->factory()->length_string(),
-                        JSTypedArray::kLengthOffset, object_offset) &&
-          !CheckForName(name, isolate->factory()->byte_length_string(),
-                        JSTypedArray::kByteLengthOffset, object_offset) &&
-          !CheckForName(name, isolate->factory()->byte_offset_string(),
-                        JSTypedArray::kByteOffsetOffset, object_offset)) {
-        return false;
-      }
-
-      if (map->is_dictionary_map()) return false;
-
-      // Check if the property is overridden on the instance.
-      DescriptorArray* descriptors = map->instance_descriptors();
-      int descriptor = descriptors->SearchWithCache(isolate, *name, *map);
-      if (descriptor != DescriptorArray::kNotFound) return false;
-
-      Handle<Object> proto = Handle<Object>(map->prototype(), isolate);
-      if (!proto->IsJSReceiver()) return false;
-
-      // Check if the property is defined in the prototype chain.
-      LookupIterator it(proto, name);
-      if (!it.IsFound()) return false;
-
-      Object* original_proto =
-          JSFunction::cast(map->GetConstructor())->prototype();
-
-      // Property is not configurable. It is enough to verify that
-      // the holder is the same.
-      return *it.GetHolder<Object>() == original_proto;
-    }
-    case JS_DATA_VIEW_TYPE:
-      return CheckForName(name, isolate->factory()->byte_length_string(),
-                          JSDataView::kByteLengthOffset, object_offset) ||
-             CheckForName(name, isolate->factory()->byte_offset_string(),
-                          JSDataView::kByteOffsetOffset, object_offset);
-    default:
-      return false;
-  }
-}
-
-MUST_USE_RESULT static MaybeHandle<Object> ReplaceAccessorWithDataProperty(
-    Isolate* isolate, Handle<JSObject> receiver, Handle<JSObject> holder,
-    Handle<Name> name, Handle<Object> value, bool observe) {
+MUST_USE_RESULT MaybeHandle<Object> ReplaceAccessorWithDataProperty(
+    Isolate* isolate, Handle<Object> receiver, Handle<JSObject> holder,
+    Handle<Name> name, Handle<Object> value) {
   LookupIterator it(receiver, name, holder,
                     LookupIterator::OWN_SKIP_INTERCEPTOR);
   // Skip any access checks we might hit. This accessor should never hit in a
@@ -140,37 +99,26 @@
     CHECK(it.HasAccess());
     it.Next();
   }
+  DCHECK(holder.is_identical_to(it.GetHolder<JSObject>()));
   CHECK_EQ(LookupIterator::ACCESSOR, it.state());
-
-  Handle<Object> old_value;
-  bool is_observed = observe && receiver->map()->is_observed();
-  if (is_observed) {
-    MaybeHandle<Object> maybe_old = Object::GetPropertyWithAccessor(&it);
-    if (!maybe_old.ToHandle(&old_value)) return maybe_old;
-  }
-
   it.ReconfigureDataProperty(value, it.property_attributes());
-
-  if (is_observed && !old_value->SameValue(*value)) {
-    return JSObject::EnqueueChangeRecord(receiver, "update", name, old_value);
-  }
-
   return value;
 }
 
+}  // namespace
+
 void Accessors::ReconfigureToDataProperty(
     v8::Local<v8::Name> key, v8::Local<v8::Value> val,
     const v8::PropertyCallbackInfo<void>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   HandleScope scope(isolate);
-  Handle<JSObject> receiver =
-      Handle<JSObject>::cast(Utils::OpenHandle(*info.This()));
+  Handle<Object> receiver = Utils::OpenHandle(*info.This());
   Handle<JSObject> holder =
       Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder()));
   Handle<Name> name = Utils::OpenHandle(*key);
   Handle<Object> value = Utils::OpenHandle(*val);
-  MaybeHandle<Object> result = ReplaceAccessorWithDataProperty(
-      isolate, receiver, holder, name, value, false);
+  MaybeHandle<Object> result =
+      ReplaceAccessorWithDataProperty(isolate, receiver, holder, name, value);
   if (result.is_null()) isolate->OptionalRescheduleException(false);
 }
 
@@ -221,7 +169,7 @@
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   HandleScope scope(isolate);
 
-  Handle<JSReceiver> object = Utils::OpenHandle(*info.This());
+  Handle<JSReceiver> object = Utils::OpenHandle(*info.Holder());
   Handle<JSArray> array = Handle<JSArray>::cast(object);
   Handle<Object> length_obj = Utils::OpenHandle(*val);
 
@@ -231,9 +179,7 @@
     return;
   }
 
-  if (JSArray::ObservableSetLength(array, length).is_null()) {
-    isolate->OptionalRescheduleException(false);
-  }
+  JSArray::SetLength(array, length);
 
   if (info.ShouldThrowOnError()) {
     uint32_t actual_new_len = 0;
@@ -305,7 +251,7 @@
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
   HandleScope scope(isolate);
-  Object* object = *Utils::OpenHandle(*info.This());
+  Object* object = *Utils::OpenHandle(*info.Holder());
   Object* res = Smi::FromInt(
       Script::cast(JSValue::cast(object)->value())->column_offset());
   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
@@ -332,7 +278,7 @@
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
   HandleScope scope(isolate);
-  Object* object = *Utils::OpenHandle(*info.This());
+  Object* object = *Utils::OpenHandle(*info.Holder());
   Object* id = Smi::FromInt(Script::cast(JSValue::cast(object)->value())->id());
   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(id, isolate)));
 }
@@ -357,7 +303,7 @@
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
   HandleScope scope(isolate);
-  Object* object = *Utils::OpenHandle(*info.This());
+  Object* object = *Utils::OpenHandle(*info.Holder());
   Object* source = Script::cast(JSValue::cast(object)->value())->name();
   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
 }
@@ -381,7 +327,7 @@
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
   HandleScope scope(isolate);
-  Object* object = *Utils::OpenHandle(*info.This());
+  Object* object = *Utils::OpenHandle(*info.Holder());
   Object* source = Script::cast(JSValue::cast(object)->value())->source();
   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(source, isolate)));
 }
@@ -405,7 +351,7 @@
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
   HandleScope scope(isolate);
-  Object* object = *Utils::OpenHandle(*info.This());
+  Object* object = *Utils::OpenHandle(*info.Holder());
   Object* res =
       Smi::FromInt(Script::cast(JSValue::cast(object)->value())->line_offset());
   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
@@ -432,7 +378,7 @@
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
   HandleScope scope(isolate);
-  Object* object = *Utils::OpenHandle(*info.This());
+  Object* object = *Utils::OpenHandle(*info.Holder());
   Object* res =
       Smi::FromInt(Script::cast(JSValue::cast(object)->value())->type());
   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
@@ -458,7 +404,7 @@
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
   HandleScope scope(isolate);
-  Object* object = *Utils::OpenHandle(*info.This());
+  Object* object = *Utils::OpenHandle(*info.Holder());
   Object* res = Smi::FromInt(
       Script::cast(JSValue::cast(object)->value())->compilation_type());
   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
@@ -484,7 +430,7 @@
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   HandleScope scope(isolate);
-  Handle<Object> object = Utils::OpenHandle(*info.This());
+  Handle<Object> object = Utils::OpenHandle(*info.Holder());
   Handle<Script> script(
       Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
   Script::InitLineEnds(script);
@@ -519,7 +465,7 @@
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
   HandleScope scope(isolate);
-  Object* object = *Utils::OpenHandle(*info.This());
+  Object* object = *Utils::OpenHandle(*info.Holder());
   Object* url = Script::cast(JSValue::cast(object)->value())->source_url();
   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
 }
@@ -543,7 +489,7 @@
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
   HandleScope scope(isolate);
-  Object* object = *Utils::OpenHandle(*info.This());
+  Object* object = *Utils::OpenHandle(*info.Holder());
   Object* url =
       Script::cast(JSValue::cast(object)->value())->source_mapping_url();
   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
@@ -567,7 +513,7 @@
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
   HandleScope scope(isolate);
-  Object* object = *Utils::OpenHandle(*info.This());
+  Object* object = *Utils::OpenHandle(*info.Holder());
   bool is_embedder_debug_script = Script::cast(JSValue::cast(object)->value())
                                       ->origin_options()
                                       .IsEmbedderDebugScript();
@@ -596,7 +542,7 @@
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   DisallowHeapAllocation no_allocation;
   HandleScope scope(isolate);
-  Object* object = *Utils::OpenHandle(*info.This());
+  Object* object = *Utils::OpenHandle(*info.Holder());
   Object* res = Script::cast(JSValue::cast(object)->value())->context_data();
   info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(res, isolate)));
 }
@@ -621,11 +567,11 @@
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   HandleScope scope(isolate);
-  Handle<Object> object = Utils::OpenHandle(*info.This());
+  Handle<Object> object = Utils::OpenHandle(*info.Holder());
   Handle<Script> script(
       Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
   Handle<Object> result = isolate->factory()->undefined_value();
-  if (!script->eval_from_shared()->IsUndefined()) {
+  if (!script->eval_from_shared()->IsUndefined(isolate)) {
     Handle<SharedFunctionInfo> eval_from_shared(
         SharedFunctionInfo::cast(script->eval_from_shared()));
     if (eval_from_shared->script()->IsScript()) {
@@ -657,16 +603,12 @@
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   HandleScope scope(isolate);
-  Handle<Object> object = Utils::OpenHandle(*info.This());
+  Handle<Object> object = Utils::OpenHandle(*info.Holder());
   Handle<Script> script(
       Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
   Handle<Object> result = isolate->factory()->undefined_value();
   if (script->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
-    Handle<Code> code(SharedFunctionInfo::cast(
-        script->eval_from_shared())->code());
-    result = Handle<Object>(Smi::FromInt(code->SourcePosition(
-                                script->eval_from_instructions_offset())),
-                            isolate);
+    result = Handle<Object>(Smi::FromInt(script->GetEvalPosition()), isolate);
   }
   info.GetReturnValue().Set(Utils::ToLocal(result));
 }
@@ -691,17 +633,19 @@
     const v8::PropertyCallbackInfo<v8::Value>& info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   HandleScope scope(isolate);
-  Handle<Object> object = Utils::OpenHandle(*info.This());
+  Handle<Object> object = Utils::OpenHandle(*info.Holder());
   Handle<Script> script(
       Script::cast(Handle<JSValue>::cast(object)->value()), isolate);
-  Handle<Object> result;
-  Handle<SharedFunctionInfo> shared(
-      SharedFunctionInfo::cast(script->eval_from_shared()));
-  // Find the name of the function calling eval.
-  if (!shared->name()->IsUndefined()) {
-    result = Handle<Object>(shared->name(), isolate);
-  } else {
-    result = Handle<Object>(shared->inferred_name(), isolate);
+  Handle<Object> result = isolate->factory()->undefined_value();
+  if (!script->eval_from_shared()->IsUndefined(isolate)) {
+    Handle<SharedFunctionInfo> shared(
+        SharedFunctionInfo::cast(script->eval_from_shared()));
+    // Find the name of the function calling eval.
+    if (!shared->name()->IsUndefined(isolate)) {
+      result = Handle<Object>(shared->name(), isolate);
+    } else {
+      result = Handle<Object>(shared->inferred_name(), isolate);
+    }
   }
   info.GetReturnValue().Set(Utils::ToLocal(result));
 }
@@ -732,24 +676,8 @@
 
 MUST_USE_RESULT static MaybeHandle<Object> SetFunctionPrototype(
     Isolate* isolate, Handle<JSFunction> function, Handle<Object> value) {
-  Handle<Object> old_value;
-  bool is_observed = function->map()->is_observed();
-  if (is_observed) {
-    if (function->has_prototype())
-      old_value = handle(function->prototype(), isolate);
-    else
-      old_value = isolate->factory()->NewFunctionPrototype(function);
-  }
-
   JSFunction::SetPrototype(function, value);
   DCHECK(function->prototype() == *value);
-
-  if (is_observed && !old_value->SameValue(*value)) {
-    MaybeHandle<Object> result = JSObject::EnqueueChangeRecord(
-        function, "update", isolate->factory()->prototype_string(), old_value);
-    if (result.is_null()) return MaybeHandle<Object>();
-  }
-
   return function;
 }
 
@@ -811,45 +739,19 @@
   HandleScope scope(isolate);
   Handle<JSFunction> function =
       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
-
-  int length = 0;
-  if (function->shared()->is_compiled()) {
-    length = function->shared()->length();
-  } else {
-    // If the function isn't compiled yet, the length is not computed
-    // correctly yet. Compile it now and return the right length.
-    if (Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) {
-      length = function->shared()->length();
-    }
-    if (isolate->has_pending_exception()) {
-      isolate->OptionalRescheduleException(false);
-    }
+  Handle<Object> result;
+  if (!JSFunction::GetLength(isolate, function).ToHandle(&result)) {
+    result = handle(Smi::FromInt(0), isolate);
+    isolate->OptionalRescheduleException(false);
   }
-  Handle<Object> result(Smi::FromInt(length), isolate);
+
   info.GetReturnValue().Set(Utils::ToLocal(result));
 }
 
-void Accessors::ObservedReconfigureToDataProperty(
-    v8::Local<v8::Name> key, v8::Local<v8::Value> val,
-    const v8::PropertyCallbackInfo<void>& info) {
-  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
-  HandleScope scope(isolate);
-  Handle<JSObject> receiver =
-      Handle<JSObject>::cast(Utils::OpenHandle(*info.This()));
-  Handle<JSObject> holder =
-      Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder()));
-  Handle<Name> name = Utils::OpenHandle(*key);
-  Handle<Object> value = Utils::OpenHandle(*val);
-  MaybeHandle<Object> result = ReplaceAccessorWithDataProperty(
-      isolate, receiver, holder, name, value, true);
-  if (result.is_null()) isolate->OptionalRescheduleException(false);
-}
-
-
 Handle<AccessorInfo> Accessors::FunctionLengthInfo(
       Isolate* isolate, PropertyAttributes attributes) {
   return MakeAccessor(isolate, isolate->factory()->length_string(),
-                      &FunctionLengthGetter, &ObservedReconfigureToDataProperty,
+                      &FunctionLengthGetter, &ReconfigureToDataProperty,
                       attributes);
 }
 
@@ -866,19 +768,14 @@
   HandleScope scope(isolate);
   Handle<JSFunction> function =
       Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder()));
-  Handle<Object> result;
-  if (function->shared()->name_should_print_as_anonymous()) {
-    result = isolate->factory()->anonymous_string();
-  } else {
-    result = handle(function->shared()->name(), isolate);
-  }
+  Handle<Object> result = JSFunction::GetName(isolate, function);
   info.GetReturnValue().Set(Utils::ToLocal(result));
 }
 
 Handle<AccessorInfo> Accessors::FunctionNameInfo(
       Isolate* isolate, PropertyAttributes attributes) {
   return MakeAccessor(isolate, isolate->factory()->name_string(),
-                      &FunctionNameGetter, &ObservedReconfigureToDataProperty,
+                      &FunctionNameGetter, &ReconfigureToDataProperty,
                       attributes);
 }
 
@@ -1155,6 +1052,65 @@
 
 
 //
+// Accessors::BoundFunctionLength
+//
+
+void Accessors::BoundFunctionLengthGetter(
+    v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
+  HandleScope scope(isolate);
+  Handle<JSBoundFunction> function =
+      Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder()));
+
+  Handle<Smi> target_length;
+  Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()),
+                            isolate);
+  if (!JSFunction::GetLength(isolate, target).ToHandle(&target_length)) {
+    target_length = handle(Smi::FromInt(0), isolate);
+    isolate->OptionalRescheduleException(false);
+    return;
+  }
+
+  int bound_length = function->bound_arguments()->length();
+  int length = Max(0, target_length->value() - bound_length);
+
+  Handle<Object> result(Smi::FromInt(length), isolate);
+  info.GetReturnValue().Set(Utils::ToLocal(result));
+}
+
+Handle<AccessorInfo> Accessors::BoundFunctionLengthInfo(
+    Isolate* isolate, PropertyAttributes attributes) {
+  return MakeAccessor(isolate, isolate->factory()->length_string(),
+                      &BoundFunctionLengthGetter, &ReconfigureToDataProperty,
+                      attributes);
+}
+
+//
+// Accessors::BoundFunctionName
+//
+
+void Accessors::BoundFunctionNameGetter(
+    v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
+  HandleScope scope(isolate);
+  Handle<JSBoundFunction> function =
+      Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder()));
+  Handle<Object> result;
+  if (!JSBoundFunction::GetName(isolate, function).ToHandle(&result)) {
+    isolate->OptionalRescheduleException(false);
+    return;
+  }
+  info.GetReturnValue().Set(Utils::ToLocal(result));
+}
+
+Handle<AccessorInfo> Accessors::BoundFunctionNameInfo(
+    Isolate* isolate, PropertyAttributes attributes) {
+  return MakeAccessor(isolate, isolate->factory()->name_string(),
+                      &BoundFunctionNameGetter, &ReconfigureToDataProperty,
+                      attributes);
+}
+
+//
 // Accessors::MakeModuleExport
 //
 
@@ -1176,7 +1132,7 @@
     return;
   }
   Object* value = context->get(slot);
-  if (value->IsTheHole()) {
+  if (value->IsTheHole(isolate)) {
     Handle<Name> name = v8::Utils::OpenHandle(*property);
 
     Handle<Object> exception = isolate->factory()->NewReferenceError(
diff --git a/src/accessors.h b/src/accessors.h
index 3fe550c..7863c5a 100644
--- a/src/accessors.h
+++ b/src/accessors.h
@@ -22,6 +22,8 @@
 #define ACCESSOR_INFO_LIST(V)     \
   V(ArgumentsIterator)            \
   V(ArrayLength)                  \
+  V(BoundFunctionLength)          \
+  V(BoundFunctionName)            \
   V(FunctionArguments)            \
   V(FunctionCaller)               \
   V(FunctionName)                 \
@@ -46,7 +48,6 @@
 
 #define ACCESSOR_SETTER_LIST(V)        \
   V(ReconfigureToDataProperty)         \
-  V(ObservedReconfigureToDataProperty) \
   V(ArrayLengthSetter)                 \
   V(FunctionPrototypeSetter)
 
@@ -94,14 +95,6 @@
   static bool IsJSObjectFieldAccessor(Handle<Map> map, Handle<Name> name,
                                       int* object_offset);
 
-  // Returns true for properties that are accessors to ArrayBufferView and
-  // derived classes fields. If true, *object_offset contains offset of
-  // object field. The caller still has to check whether the underlying
-  // buffer was neutered.
-  static bool IsJSArrayBufferViewFieldAccessor(Handle<Map> map,
-                                               Handle<Name> name,
-                                               int* object_offset);
-
   static Handle<AccessorInfo> MakeAccessor(
       Isolate* isolate,
       Handle<Name> name,
diff --git a/src/address-map.cc b/src/address-map.cc
index 86558e0..61292bf 100644
--- a/src/address-map.cc
+++ b/src/address-map.cc
@@ -13,7 +13,7 @@
 RootIndexMap::RootIndexMap(Isolate* isolate) {
   map_ = isolate->root_index_map();
   if (map_ != NULL) return;
-  map_ = new HashMap(HashMap::PointersMatch);
+  map_ = new base::HashMap(base::HashMap::PointersMatch);
   for (uint32_t i = 0; i < Heap::kStrongRootListLength; i++) {
     Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(i);
     Object* root = isolate->heap()->root(root_index);
@@ -22,7 +22,7 @@
     // not be referenced through the root list in the snapshot.
     if (isolate->heap()->RootCanBeTreatedAsConstant(root_index)) {
       HeapObject* heap_object = HeapObject::cast(root);
-      HashMap::Entry* entry = LookupEntry(map_, heap_object, false);
+      base::HashMap::Entry* entry = LookupEntry(map_, heap_object, false);
       if (entry != NULL) {
         // Some are initialized to a previous value in the root list.
         DCHECK_LT(GetValue(entry), i);
diff --git a/src/address-map.h b/src/address-map.h
index df32f89..ce21705 100644
--- a/src/address-map.h
+++ b/src/address-map.h
@@ -6,7 +6,7 @@
 #define V8_ADDRESS_MAP_H_
 
 #include "src/assert-scope.h"
-#include "src/hashmap.h"
+#include "src/base/hashmap.h"
 #include "src/objects.h"
 
 namespace v8 {
@@ -14,16 +14,17 @@
 
 class AddressMapBase {
  protected:
-  static void SetValue(HashMap::Entry* entry, uint32_t v) {
+  static void SetValue(base::HashMap::Entry* entry, uint32_t v) {
     entry->value = reinterpret_cast<void*>(v);
   }
 
-  static uint32_t GetValue(HashMap::Entry* entry) {
+  static uint32_t GetValue(base::HashMap::Entry* entry) {
     return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry->value));
   }
 
-  inline static HashMap::Entry* LookupEntry(HashMap* map, HeapObject* obj,
-                                            bool insert) {
+  inline static base::HashMap::Entry* LookupEntry(base::HashMap* map,
+                                                  HeapObject* obj,
+                                                  bool insert) {
     if (insert) {
       map->LookupOrInsert(Key(obj), Hash(obj));
     }
@@ -40,7 +41,6 @@
   }
 };
 
-
 class RootIndexMap : public AddressMapBase {
  public:
   explicit RootIndexMap(Isolate* isolate);
@@ -48,134 +48,166 @@
   static const int kInvalidRootIndex = -1;
 
   int Lookup(HeapObject* obj) {
-    HashMap::Entry* entry = LookupEntry(map_, obj, false);
+    base::HashMap::Entry* entry = LookupEntry(map_, obj, false);
     if (entry) return GetValue(entry);
     return kInvalidRootIndex;
   }
 
  private:
-  HashMap* map_;
+  base::HashMap* map_;
 
   DISALLOW_COPY_AND_ASSIGN(RootIndexMap);
 };
 
-
-class BackReference {
+class SerializerReference {
  public:
-  explicit BackReference(uint32_t bitfield) : bitfield_(bitfield) {}
+  SerializerReference() : bitfield_(Special(kInvalidValue)) {}
 
-  BackReference() : bitfield_(kInvalidValue) {}
-
-  static BackReference SourceReference() { return BackReference(kSourceValue); }
-
-  static BackReference GlobalProxyReference() {
-    return BackReference(kGlobalProxyValue);
+  static SerializerReference FromBitfield(uint32_t bitfield) {
+    return SerializerReference(bitfield);
   }
 
-  static BackReference LargeObjectReference(uint32_t index) {
-    return BackReference(SpaceBits::encode(LO_SPACE) |
-                         ChunkOffsetBits::encode(index));
-  }
-
-  static BackReference DummyReference() { return BackReference(kDummyValue); }
-
-  static BackReference Reference(AllocationSpace space, uint32_t chunk_index,
-                                 uint32_t chunk_offset) {
+  static SerializerReference BackReference(AllocationSpace space,
+                                           uint32_t chunk_index,
+                                           uint32_t chunk_offset) {
     DCHECK(IsAligned(chunk_offset, kObjectAlignment));
     DCHECK_NE(LO_SPACE, space);
-    return BackReference(
+    return SerializerReference(
         SpaceBits::encode(space) | ChunkIndexBits::encode(chunk_index) |
         ChunkOffsetBits::encode(chunk_offset >> kObjectAlignmentBits));
   }
 
-  bool is_valid() const { return bitfield_ != kInvalidValue; }
-  bool is_source() const { return bitfield_ == kSourceValue; }
-  bool is_global_proxy() const { return bitfield_ == kGlobalProxyValue; }
+  static SerializerReference LargeObjectReference(uint32_t index) {
+    return SerializerReference(SpaceBits::encode(LO_SPACE) |
+                               ValueIndexBits::encode(index));
+  }
+
+  static SerializerReference AttachedReference(uint32_t index) {
+    return SerializerReference(SpaceBits::encode(kAttachedReferenceSpace) |
+                               ValueIndexBits::encode(index));
+  }
+
+  static SerializerReference DummyReference() {
+    return SerializerReference(Special(kDummyValue));
+  }
+
+  bool is_valid() const { return bitfield_ != Special(kInvalidValue); }
+
+  bool is_back_reference() const {
+    return SpaceBits::decode(bitfield_) <= LAST_SPACE;
+  }
 
   AllocationSpace space() const {
-    DCHECK(is_valid());
-    return SpaceBits::decode(bitfield_);
+    DCHECK(is_back_reference());
+    return static_cast<AllocationSpace>(SpaceBits::decode(bitfield_));
   }
 
   uint32_t chunk_offset() const {
-    DCHECK(is_valid());
+    DCHECK(is_back_reference());
     return ChunkOffsetBits::decode(bitfield_) << kObjectAlignmentBits;
   }
 
   uint32_t large_object_index() const {
-    DCHECK(is_valid());
+    DCHECK(is_back_reference());
     DCHECK(chunk_index() == 0);
     return ChunkOffsetBits::decode(bitfield_);
   }
 
   uint32_t chunk_index() const {
-    DCHECK(is_valid());
+    DCHECK(is_back_reference());
     return ChunkIndexBits::decode(bitfield_);
   }
 
-  uint32_t reference() const {
-    DCHECK(is_valid());
+  uint32_t back_reference() const {
+    DCHECK(is_back_reference());
     return bitfield_ & (ChunkOffsetBits::kMask | ChunkIndexBits::kMask);
   }
 
-  uint32_t bitfield() const { return bitfield_; }
+  bool is_attached_reference() const {
+    return SpaceBits::decode(bitfield_) == kAttachedReferenceSpace;
+  }
+
+  int attached_reference_index() const {
+    DCHECK(is_attached_reference());
+    return ValueIndexBits::decode(bitfield_);
+  }
 
  private:
-  static const uint32_t kInvalidValue = 0xFFFFFFFF;
-  static const uint32_t kSourceValue = 0xFFFFFFFE;
-  static const uint32_t kGlobalProxyValue = 0xFFFFFFFD;
-  static const uint32_t kDummyValue = 0xFFFFFFFC;
+  explicit SerializerReference(uint32_t bitfield) : bitfield_(bitfield) {}
+
+  inline static uint32_t Special(int value) {
+    return SpaceBits::encode(kSpecialValueSpace) |
+           ValueIndexBits::encode(value);
+  }
+
+  // We use the 32-bit bitfield to encode either a back reference, a special
+  // value, or an attached reference index.
+  // Back reference:
+  //   [ Space index             ] [ Chunk index ] [ Chunk offset ]
+  //   [ LO_SPACE                ] [ large object index           ]
+  // Special value
+  //   [ kSpecialValueSpace      ] [ Special value index          ]
+  // Attached reference
+  //   [ kAttachedReferenceSpace ] [ Attached reference index     ]
+
   static const int kChunkOffsetSize = kPageSizeBits - kObjectAlignmentBits;
   static const int kChunkIndexSize = 32 - kChunkOffsetSize - kSpaceTagSize;
+  static const int kValueIndexSize = kChunkOffsetSize + kChunkIndexSize;
 
- public:
-  static const int kMaxChunkIndex = (1 << kChunkIndexSize) - 1;
+  static const int kSpecialValueSpace = LAST_SPACE + 1;
+  static const int kAttachedReferenceSpace = kSpecialValueSpace + 1;
+  STATIC_ASSERT(kAttachedReferenceSpace < (1 << kSpaceTagSize));
 
- private:
+  static const int kInvalidValue = 0;
+  static const int kDummyValue = 1;
+
+  // The chunk offset can also be used to encode the index of special values.
   class ChunkOffsetBits : public BitField<uint32_t, 0, kChunkOffsetSize> {};
   class ChunkIndexBits
       : public BitField<uint32_t, ChunkOffsetBits::kNext, kChunkIndexSize> {};
-  class SpaceBits
-      : public BitField<AllocationSpace, ChunkIndexBits::kNext, kSpaceTagSize> {
-  };
+  class ValueIndexBits : public BitField<uint32_t, 0, kValueIndexSize> {};
+  STATIC_ASSERT(ChunkIndexBits::kNext == ValueIndexBits::kNext);
+  class SpaceBits : public BitField<int, kValueIndexSize, kSpaceTagSize> {};
+  STATIC_ASSERT(SpaceBits::kNext == 32);
 
   uint32_t bitfield_;
-};
 
+  friend class SerializerReferenceMap;
+};
 
 // Mapping objects to their location after deserialization.
 // This is used during building, but not at runtime by V8.
-class BackReferenceMap : public AddressMapBase {
+class SerializerReferenceMap : public AddressMapBase {
  public:
-  BackReferenceMap()
-      : no_allocation_(), map_(new HashMap(HashMap::PointersMatch)) {}
+  SerializerReferenceMap()
+      : no_allocation_(),
+        map_(base::HashMap::PointersMatch),
+        attached_reference_index_(0) {}
 
-  ~BackReferenceMap() { delete map_; }
-
-  BackReference Lookup(HeapObject* obj) {
-    HashMap::Entry* entry = LookupEntry(map_, obj, false);
-    return entry ? BackReference(GetValue(entry)) : BackReference();
+  SerializerReference Lookup(HeapObject* obj) {
+    base::HashMap::Entry* entry = LookupEntry(&map_, obj, false);
+    return entry ? SerializerReference(GetValue(entry)) : SerializerReference();
   }
 
-  void Add(HeapObject* obj, BackReference b) {
+  void Add(HeapObject* obj, SerializerReference b) {
     DCHECK(b.is_valid());
-    DCHECK_NULL(LookupEntry(map_, obj, false));
-    HashMap::Entry* entry = LookupEntry(map_, obj, true);
-    SetValue(entry, b.bitfield());
+    DCHECK_NULL(LookupEntry(&map_, obj, false));
+    base::HashMap::Entry* entry = LookupEntry(&map_, obj, true);
+    SetValue(entry, b.bitfield_);
   }
 
-  void AddSourceString(String* string) {
-    Add(string, BackReference::SourceReference());
-  }
-
-  void AddGlobalProxy(HeapObject* global_proxy) {
-    Add(global_proxy, BackReference::GlobalProxyReference());
+  SerializerReference AddAttachedReference(HeapObject* attached_reference) {
+    SerializerReference reference =
+        SerializerReference::AttachedReference(attached_reference_index_++);
+    Add(attached_reference, reference);
+    return reference;
   }
 
  private:
   DisallowHeapAllocation no_allocation_;
-  HashMap* map_;
-  DISALLOW_COPY_AND_ASSIGN(BackReferenceMap);
+  base::HashMap map_;
+  int attached_reference_index_;
+  DISALLOW_COPY_AND_ASSIGN(SerializerReferenceMap);
 };
 
 }  // namespace internal
diff --git a/src/api-arguments-inl.h b/src/api-arguments-inl.h
new file mode 100644
index 0000000..89ac7de
--- /dev/null
+++ b/src/api-arguments-inl.h
@@ -0,0 +1,105 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/api-arguments.h"
+
+#include "src/tracing/trace-event.h"
+#include "src/vm-state-inl.h"
+
+namespace v8 {
+namespace internal {
+
+#define FOR_EACH_CALLBACK_TABLE_MAPPING_1_NAME(F)                  \
+  F(AccessorNameGetterCallback, "get", v8::Value, Object)          \
+  F(GenericNamedPropertyQueryCallback, "has", v8::Integer, Object) \
+  F(GenericNamedPropertyDeleterCallback, "delete", v8::Boolean, Object)
+
+#define WRITE_CALL_1_NAME(Function, type, ApiReturn, InternalReturn)          \
+  Handle<InternalReturn> PropertyCallbackArguments::Call(Function f,          \
+                                                         Handle<Name> name) { \
+    Isolate* isolate = this->isolate();                                       \
+    RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::Function);        \
+    VMState<EXTERNAL> state(isolate);                                         \
+    ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));              \
+    PropertyCallbackInfo<ApiReturn> info(begin());                            \
+    LOG(isolate,                                                              \
+        ApiNamedPropertyAccess("interceptor-named-" type, holder(), *name));  \
+    f(v8::Utils::ToLocal(name), info);                                        \
+    return GetReturnValue<InternalReturn>(isolate);                           \
+  }
+
+FOR_EACH_CALLBACK_TABLE_MAPPING_1_NAME(WRITE_CALL_1_NAME)
+
+#undef FOR_EACH_CALLBACK_TABLE_MAPPING_1_NAME
+#undef WRITE_CALL_1_NAME
+
+#define FOR_EACH_CALLBACK_TABLE_MAPPING_1_INDEX(F)            \
+  F(IndexedPropertyGetterCallback, "get", v8::Value, Object)  \
+  F(IndexedPropertyQueryCallback, "has", v8::Integer, Object) \
+  F(IndexedPropertyDeleterCallback, "delete", v8::Boolean, Object)
+
+#define WRITE_CALL_1_INDEX(Function, type, ApiReturn, InternalReturn)      \
+  Handle<InternalReturn> PropertyCallbackArguments::Call(Function f,       \
+                                                         uint32_t index) { \
+    Isolate* isolate = this->isolate();                                    \
+    RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::Function);     \
+    VMState<EXTERNAL> state(isolate);                                      \
+    ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));           \
+    PropertyCallbackInfo<ApiReturn> info(begin());                         \
+    LOG(isolate, ApiIndexedPropertyAccess("interceptor-indexed-" type,     \
+                                          holder(), index));               \
+    f(index, info);                                                        \
+    return GetReturnValue<InternalReturn>(isolate);                        \
+  }
+
+FOR_EACH_CALLBACK_TABLE_MAPPING_1_INDEX(WRITE_CALL_1_INDEX)
+
+#undef FOR_EACH_CALLBACK_TABLE_MAPPING_1_INDEX
+#undef WRITE_CALL_1_INDEX
+
+Handle<Object> PropertyCallbackArguments::Call(
+    GenericNamedPropertySetterCallback f, Handle<Name> name,
+    Handle<Object> value) {
+  Isolate* isolate = this->isolate();
+  RuntimeCallTimerScope timer(
+      isolate, &RuntimeCallStats::GenericNamedPropertySetterCallback);
+  VMState<EXTERNAL> state(isolate);
+  ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
+  PropertyCallbackInfo<v8::Value> info(begin());
+  LOG(isolate,
+      ApiNamedPropertyAccess("interceptor-named-set", holder(), *name));
+  f(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
+  return GetReturnValue<Object>(isolate);
+}
+
+Handle<Object> PropertyCallbackArguments::Call(IndexedPropertySetterCallback f,
+                                               uint32_t index,
+                                               Handle<Object> value) {
+  Isolate* isolate = this->isolate();
+  RuntimeCallTimerScope timer(isolate,
+                              &RuntimeCallStats::IndexedPropertySetterCallback);
+  VMState<EXTERNAL> state(isolate);
+  ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
+  PropertyCallbackInfo<v8::Value> info(begin());
+  LOG(isolate,
+      ApiIndexedPropertyAccess("interceptor-indexed-set", holder(), index));
+  f(index, v8::Utils::ToLocal(value), info);
+  return GetReturnValue<Object>(isolate);
+}
+
+void PropertyCallbackArguments::Call(AccessorNameSetterCallback f,
+                                     Handle<Name> name, Handle<Object> value) {
+  Isolate* isolate = this->isolate();
+  RuntimeCallTimerScope timer(isolate,
+                              &RuntimeCallStats::AccessorNameSetterCallback);
+  VMState<EXTERNAL> state(isolate);
+  ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
+  PropertyCallbackInfo<void> info(begin());
+  LOG(isolate,
+      ApiNamedPropertyAccess("interceptor-named-set", holder(), *name));
+  f(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/api-arguments.cc b/src/api-arguments.cc
index c4b698c..f8d6c8f 100644
--- a/src/api-arguments.cc
+++ b/src/api-arguments.cc
@@ -4,15 +4,18 @@
 
 #include "src/api-arguments.h"
 
+#include "src/tracing/trace-event.h"
+#include "src/vm-state-inl.h"
+
 namespace v8 {
 namespace internal {
 
 Handle<Object> FunctionCallbackArguments::Call(FunctionCallback f) {
   Isolate* isolate = this->isolate();
+  RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::FunctionCallback);
   VMState<EXTERNAL> state(isolate);
   ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
-  FunctionCallbackInfo<v8::Value> info(begin(), argv_, argc_,
-                                       is_construct_call_);
+  FunctionCallbackInfo<v8::Value> info(begin(), argv_, argc_);
   f(info);
   return GetReturnValue<Object>(isolate);
 }
@@ -20,6 +23,7 @@
 Handle<JSObject> PropertyCallbackArguments::Call(
     IndexedPropertyEnumeratorCallback f) {
   Isolate* isolate = this->isolate();
+  RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::PropertyCallback);
   VMState<EXTERNAL> state(isolate);
   ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
   PropertyCallbackInfo<v8::Array> info(begin());
diff --git a/src/api-arguments.h b/src/api-arguments.h
index 3bfe34d..0dfe618 100644
--- a/src/api-arguments.h
+++ b/src/api-arguments.h
@@ -7,8 +7,6 @@
 
 #include "src/api.h"
 #include "src/isolate.h"
-#include "src/tracing/trace-event.h"
-#include "src/vm-state-inl.h"
 
 namespace v8 {
 namespace internal {
@@ -58,7 +56,7 @@
   // Check the ReturnValue.
   Object** handle = &this->begin()[kReturnValueOffset];
   // Nothing was set, return empty handle as per previous behaviour.
-  if ((*handle)->IsTheHole()) return Handle<V>();
+  if ((*handle)->IsTheHole(isolate)) return Handle<V>();
   Handle<V> result = Handle<V>::cast(Handle<Object>(handle));
   result->VerifyApiCallResultType();
   return result;
@@ -108,84 +106,24 @@
  */
   Handle<JSObject> Call(IndexedPropertyEnumeratorCallback f);
 
-#define FOR_EACH_CALLBACK_TABLE_MAPPING_1_NAME(F)                  \
-  F(AccessorNameGetterCallback, "get", v8::Value, Object)          \
-  F(GenericNamedPropertyQueryCallback, "has", v8::Integer, Object) \
-  F(GenericNamedPropertyDeleterCallback, "delete", v8::Boolean, Object)
+  inline Handle<Object> Call(AccessorNameGetterCallback f, Handle<Name> name);
+  inline Handle<Object> Call(GenericNamedPropertyQueryCallback f,
+                             Handle<Name> name);
+  inline Handle<Object> Call(GenericNamedPropertyDeleterCallback f,
+                             Handle<Name> name);
 
-#define WRITE_CALL_1_NAME(Function, type, ApiReturn, InternalReturn)         \
-  Handle<InternalReturn> Call(Function f, Handle<Name> name) {               \
-    Isolate* isolate = this->isolate();                                      \
-    VMState<EXTERNAL> state(isolate);                                        \
-    ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));             \
-    PropertyCallbackInfo<ApiReturn> info(begin());                           \
-    LOG(isolate,                                                             \
-        ApiNamedPropertyAccess("interceptor-named-" type, holder(), *name)); \
-    f(v8::Utils::ToLocal(name), info);                                       \
-    return GetReturnValue<InternalReturn>(isolate);                          \
-  }
+  inline Handle<Object> Call(IndexedPropertyGetterCallback f, uint32_t index);
+  inline Handle<Object> Call(IndexedPropertyQueryCallback f, uint32_t index);
+  inline Handle<Object> Call(IndexedPropertyDeleterCallback f, uint32_t index);
 
-  FOR_EACH_CALLBACK_TABLE_MAPPING_1_NAME(WRITE_CALL_1_NAME)
+  inline Handle<Object> Call(GenericNamedPropertySetterCallback f,
+                             Handle<Name> name, Handle<Object> value);
 
-#undef FOR_EACH_CALLBACK_TABLE_MAPPING_1_NAME
-#undef WRITE_CALL_1_NAME
+  inline Handle<Object> Call(IndexedPropertySetterCallback f, uint32_t index,
+                             Handle<Object> value);
 
-#define FOR_EACH_CALLBACK_TABLE_MAPPING_1_INDEX(F)            \
-  F(IndexedPropertyGetterCallback, "get", v8::Value, Object)  \
-  F(IndexedPropertyQueryCallback, "has", v8::Integer, Object) \
-  F(IndexedPropertyDeleterCallback, "delete", v8::Boolean, Object)
-
-#define WRITE_CALL_1_INDEX(Function, type, ApiReturn, InternalReturn)  \
-  Handle<InternalReturn> Call(Function f, uint32_t index) {            \
-    Isolate* isolate = this->isolate();                                \
-    VMState<EXTERNAL> state(isolate);                                  \
-    ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));       \
-    PropertyCallbackInfo<ApiReturn> info(begin());                     \
-    LOG(isolate, ApiIndexedPropertyAccess("interceptor-indexed-" type, \
-                                          holder(), index));           \
-    f(index, info);                                                    \
-    return GetReturnValue<InternalReturn>(isolate);                    \
-  }
-
-  FOR_EACH_CALLBACK_TABLE_MAPPING_1_INDEX(WRITE_CALL_1_INDEX)
-
-#undef FOR_EACH_CALLBACK_TABLE_MAPPING_1_INDEX
-#undef WRITE_CALL_1_INDEX
-
-  Handle<Object> Call(GenericNamedPropertySetterCallback f, Handle<Name> name,
-                      Handle<Object> value) {
-    Isolate* isolate = this->isolate();
-    VMState<EXTERNAL> state(isolate);
-    ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
-    PropertyCallbackInfo<v8::Value> info(begin());
-    LOG(isolate,
-        ApiNamedPropertyAccess("interceptor-named-set", holder(), *name));
-    f(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
-    return GetReturnValue<Object>(isolate);
-  }
-
-  Handle<Object> Call(IndexedPropertySetterCallback f, uint32_t index,
-                      Handle<Object> value) {
-    Isolate* isolate = this->isolate();
-    VMState<EXTERNAL> state(isolate);
-    ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
-    PropertyCallbackInfo<v8::Value> info(begin());
-    LOG(isolate,
-        ApiIndexedPropertyAccess("interceptor-indexed-set", holder(), index));
-    f(index, v8::Utils::ToLocal(value), info);
-    return GetReturnValue<Object>(isolate);
-  }
-
-  void Call(AccessorNameSetterCallback f, Handle<Name> name,
-            Handle<Object> value) {
-    Isolate* isolate = this->isolate();
-    VMState<EXTERNAL> state(isolate);
-    ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
-    PropertyCallbackInfo<void> info(begin());
-    LOG(isolate,
-        ApiNamedPropertyAccess("interceptor-named-set", holder(), *name));
-    f(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
-  }
+  inline void Call(AccessorNameSetterCallback f, Handle<Name> name,
+                   Handle<Object> value);
 
  private:
   inline JSObject* holder() {
@@ -206,19 +144,19 @@
   static const int kIsolateIndex = T::kIsolateIndex;
   static const int kCalleeIndex = T::kCalleeIndex;
   static const int kContextSaveIndex = T::kContextSaveIndex;
+  static const int kNewTargetIndex = T::kNewTargetIndex;
 
   FunctionCallbackArguments(internal::Isolate* isolate, internal::Object* data,
                             internal::HeapObject* callee,
-                            internal::Object* holder, internal::Object** argv,
-                            int argc, bool is_construct_call)
-      : Super(isolate),
-        argv_(argv),
-        argc_(argc),
-        is_construct_call_(is_construct_call) {
+                            internal::Object* holder,
+                            internal::HeapObject* new_target,
+                            internal::Object** argv, int argc)
+      : Super(isolate), argv_(argv), argc_(argc) {
     Object** values = begin();
     values[T::kDataIndex] = data;
     values[T::kCalleeIndex] = callee;
     values[T::kHolderIndex] = holder;
+    values[T::kNewTargetIndex] = new_target;
     values[T::kContextSaveIndex] = isolate->heap()->the_hole_value();
     values[T::kIsolateIndex] = reinterpret_cast<internal::Object*>(isolate);
     // Here the hole is set as default value.
@@ -245,7 +183,6 @@
  private:
   internal::Object** argv_;
   int argc_;
-  bool is_construct_call_;
 };
 
 }  // namespace internal
diff --git a/src/api-natives.cc b/src/api-natives.cc
index adf4b6a..f09f42d 100644
--- a/src/api-natives.cc
+++ b/src/api-natives.cc
@@ -17,6 +17,7 @@
 
 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
                                         Handle<ObjectTemplateInfo> data,
+                                        Handle<JSReceiver> new_target,
                                         bool is_hidden_prototype);
 
 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
@@ -31,7 +32,7 @@
                                Handle<FunctionTemplateInfo>::cast(data), name);
   } else if (data->IsObjectTemplateInfo()) {
     return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data),
-                             false);
+                             Handle<JSReceiver>(), false);
   } else {
     return data;
   }
@@ -155,20 +156,25 @@
 // Returns parent function template or null.
 FunctionTemplateInfo* GetParent(FunctionTemplateInfo* data) {
   Object* parent = data->parent_template();
-  return parent->IsUndefined() ? nullptr : FunctionTemplateInfo::cast(parent);
+  return parent->IsUndefined(data->GetIsolate())
+             ? nullptr
+             : FunctionTemplateInfo::cast(parent);
 }
 
 // Starting from given object template's constructor walk up the inheritance
 // chain till a function template that has an instance template is found.
 ObjectTemplateInfo* GetParent(ObjectTemplateInfo* data) {
   Object* maybe_ctor = data->constructor();
-  if (maybe_ctor->IsUndefined()) return nullptr;
+  Isolate* isolate = data->GetIsolate();
+  if (maybe_ctor->IsUndefined(isolate)) return nullptr;
   FunctionTemplateInfo* ctor = FunctionTemplateInfo::cast(maybe_ctor);
   while (true) {
     ctor = GetParent(ctor);
     if (ctor == nullptr) return nullptr;
     Object* maybe_obj = ctor->instance_template();
-    if (!maybe_obj->IsUndefined()) return ObjectTemplateInfo::cast(maybe_obj);
+    if (!maybe_obj->IsUndefined(isolate)) {
+      return ObjectTemplateInfo::cast(maybe_obj);
+    }
   }
 }
 
@@ -184,9 +190,9 @@
   int max_number_of_properties = 0;
   TemplateInfoT* info = *data;
   while (info != nullptr) {
-    if (!info->property_accessors()->IsUndefined()) {
+    if (!info->property_accessors()->IsUndefined(isolate)) {
       Object* props = info->property_accessors();
-      if (!props->IsUndefined()) {
+      if (!props->IsUndefined(isolate)) {
         Handle<Object> props_handle(props, isolate);
         NeanderArray props_array(props_handle);
         max_number_of_properties += props_array.length();
@@ -204,7 +210,7 @@
     info = *data;
     while (info != nullptr) {
       // Accumulate accessors.
-      if (!info->property_accessors()->IsUndefined()) {
+      if (!info->property_accessors()->IsUndefined(isolate)) {
         Handle<Object> props(info->property_accessors(), isolate);
         valid_descriptors =
             AccessorInfo::AppendUnique(props, array, valid_descriptors);
@@ -220,7 +226,7 @@
   }
 
   auto property_list = handle(data->property_list(), isolate);
-  if (property_list->IsUndefined()) return obj;
+  if (property_list->IsUndefined(isolate)) return obj;
   // TODO(dcarney): just use a FixedArray here.
   NeanderArray properties(property_list);
   if (properties.length() == 0) return obj;
@@ -281,18 +287,32 @@
   Handle<Object> result =
       UnseededNumberDictionary::DeleteProperty(cache, entry);
   USE(result);
-  DCHECK(result->IsTrue());
+  DCHECK(result->IsTrue(isolate));
   auto new_cache = UnseededNumberDictionary::Shrink(cache, entry);
   isolate->native_context()->set_template_instantiations_cache(*new_cache);
 }
 
 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
                                         Handle<ObjectTemplateInfo> info,
+                                        Handle<JSReceiver> new_target,
                                         bool is_hidden_prototype) {
-  // Fast path.
-  Handle<JSObject> result;
+  Handle<JSFunction> constructor;
   uint32_t serial_number =
       static_cast<uint32_t>(Smi::cast(info->serial_number())->value());
+  if (!new_target.is_null()) {
+    if (new_target->IsJSFunction() &&
+        JSFunction::cast(*new_target)->shared()->function_data() ==
+            info->constructor() &&
+        JSFunction::cast(*new_target)->context()->native_context() ==
+            isolate->context()->native_context()) {
+      constructor = Handle<JSFunction>::cast(new_target);
+    } else {
+      // Disable caching for subclass instantiation.
+      serial_number = 0;
+    }
+  }
+  // Fast path.
+  Handle<JSObject> result;
   if (serial_number) {
     // Probe cache.
     auto cache = isolate->template_instantiations_cache();
@@ -305,20 +325,27 @@
   }
   // Enter a new scope.  Recursion could otherwise create a lot of handles.
   HandleScope scope(isolate);
-  auto constructor = handle(info->constructor(), isolate);
-  Handle<JSFunction> cons;
-  if (constructor->IsUndefined()) {
-    cons = isolate->object_function();
-  } else {
-    auto cons_templ = Handle<FunctionTemplateInfo>::cast(constructor);
-    ASSIGN_RETURN_ON_EXCEPTION(
-        isolate, cons, InstantiateFunction(isolate, cons_templ), JSFunction);
+
+  if (constructor.is_null()) {
+    Handle<Object> cons(info->constructor(), isolate);
+    if (cons->IsUndefined(isolate)) {
+      constructor = isolate->object_function();
+    } else {
+      auto cons_templ = Handle<FunctionTemplateInfo>::cast(cons);
+      ASSIGN_RETURN_ON_EXCEPTION(isolate, constructor,
+                                 InstantiateFunction(isolate, cons_templ),
+                                 JSObject);
+    }
+
+    if (new_target.is_null()) new_target = constructor;
   }
-  auto object = isolate->factory()->NewJSObject(cons);
+
+  Handle<JSObject> object;
+  ASSIGN_RETURN_ON_EXCEPTION(isolate, object,
+                             JSObject::New(constructor, new_target), JSObject);
   ASSIGN_RETURN_ON_EXCEPTION(
       isolate, result,
-      ConfigureInstance(isolate, object, info, is_hidden_prototype),
-      JSFunction);
+      ConfigureInstance(isolate, object, info, is_hidden_prototype), JSObject);
   // TODO(dcarney): is this necessary?
   JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject");
 
@@ -349,18 +376,18 @@
   Handle<JSObject> prototype;
   if (!data->remove_prototype()) {
     auto prototype_templ = handle(data->prototype_template(), isolate);
-    if (prototype_templ->IsUndefined()) {
+    if (prototype_templ->IsUndefined(isolate)) {
       prototype = isolate->factory()->NewJSObject(isolate->object_function());
     } else {
       ASSIGN_RETURN_ON_EXCEPTION(
           isolate, prototype,
           InstantiateObject(isolate,
                             Handle<ObjectTemplateInfo>::cast(prototype_templ),
-                            data->hidden_prototype()),
+                            Handle<JSReceiver>(), data->hidden_prototype()),
           JSFunction);
     }
     auto parent = handle(data->parent_template(), isolate);
-    if (!parent->IsUndefined()) {
+    if (!parent->IsUndefined(isolate)) {
       Handle<JSFunction> parent_instance;
       ASSIGN_RETURN_ON_EXCEPTION(
           isolate, parent_instance,
@@ -423,7 +450,7 @@
 void AddPropertyToPropertyList(Isolate* isolate, Handle<TemplateInfo> templ,
                                int length, Handle<Object>* data) {
   auto list = handle(templ->property_list(), isolate);
-  if (list->IsUndefined()) {
+  if (list->IsUndefined(isolate)) {
     list = NeanderArray(isolate).value();
     templ->set_property_list(*list);
   }
@@ -448,12 +475,11 @@
   return ::v8::internal::InstantiateFunction(isolate, data);
 }
 
-
 MaybeHandle<JSObject> ApiNatives::InstantiateObject(
-    Handle<ObjectTemplateInfo> data) {
+    Handle<ObjectTemplateInfo> data, Handle<JSReceiver> new_target) {
   Isolate* isolate = data->GetIsolate();
   InvokeScope invoke_scope(isolate);
-  return ::v8::internal::InstantiateObject(isolate, data, false);
+  return ::v8::internal::InstantiateObject(isolate, data, new_target, false);
 }
 
 
@@ -499,7 +525,7 @@
                                        Handle<TemplateInfo> info,
                                        Handle<AccessorInfo> property) {
   auto list = handle(info->property_accessors(), isolate);
-  if (list->IsUndefined()) {
+  if (list->IsUndefined(isolate)) {
     list = NeanderArray(isolate).value();
     info->set_property_accessors(*list);
   }
@@ -511,95 +537,77 @@
 Handle<JSFunction> ApiNatives::CreateApiFunction(
     Isolate* isolate, Handle<FunctionTemplateInfo> obj,
     Handle<Object> prototype, ApiInstanceType instance_type) {
-  Handle<Code> code;
-  if (obj->call_code()->IsCallHandlerInfo() &&
-      CallHandlerInfo::cast(obj->call_code())->fast_handler()->IsCode()) {
-    code = isolate->builtins()->HandleFastApiCall();
-  } else {
-    code = isolate->builtins()->HandleApiCall();
-  }
-  Handle<Code> construct_stub =
-      prototype.is_null() ? isolate->builtins()->ConstructedNonConstructable()
-                          : isolate->builtins()->JSConstructStubApi();
-
-  obj->set_instantiated(true);
-  Handle<JSFunction> result;
-  if (obj->remove_prototype()) {
-    result = isolate->factory()->NewFunctionWithoutPrototype(
-        isolate->factory()->empty_string(), code);
-  } else {
-    int internal_field_count = 0;
-    if (!obj->instance_template()->IsUndefined()) {
-      Handle<ObjectTemplateInfo> instance_template = Handle<ObjectTemplateInfo>(
-          ObjectTemplateInfo::cast(obj->instance_template()));
-      internal_field_count =
-          Smi::cast(instance_template->internal_field_count())->value();
-    }
-
-    // TODO(svenpanne) Kill ApiInstanceType and refactor things by generalizing
-    // JSObject::GetHeaderSize.
-    int instance_size = kPointerSize * internal_field_count;
-    InstanceType type;
-    switch (instance_type) {
-      case JavaScriptObjectType:
-        if (!obj->needs_access_check() &&
-            obj->named_property_handler()->IsUndefined() &&
-            obj->indexed_property_handler()->IsUndefined()) {
-          type = JS_OBJECT_TYPE;
-        } else {
-          type = JS_SPECIAL_API_OBJECT_TYPE;
-        }
-        instance_size += JSObject::kHeaderSize;
-        break;
-      case GlobalObjectType:
-        type = JS_GLOBAL_OBJECT_TYPE;
-        instance_size += JSGlobalObject::kSize;
-        break;
-      case GlobalProxyType:
-        type = JS_GLOBAL_PROXY_TYPE;
-        instance_size += JSGlobalProxy::kSize;
-        break;
-      default:
-        UNREACHABLE();
-        type = JS_OBJECT_TYPE;  // Keep the compiler happy.
-        break;
-    }
-
-    result = isolate->factory()->NewFunction(
-        isolate->factory()->empty_string(), code, prototype, type,
-        instance_size, obj->read_only_prototype(), true);
-  }
-
-  result->shared()->set_length(obj->length());
-  Handle<Object> class_name(obj->class_name(), isolate);
-  if (class_name->IsString()) {
-    result->shared()->set_instance_class_name(*class_name);
-    result->shared()->set_name(*class_name);
-  }
-  result->shared()->set_api_func_data(*obj);
-  result->shared()->set_construct_stub(*construct_stub);
-  result->shared()->DontAdaptArguments();
+  Handle<SharedFunctionInfo> shared =
+      FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(isolate, obj);
+  Handle<JSFunction> result =
+      isolate->factory()->NewFunctionFromSharedFunctionInfo(
+          shared, isolate->native_context());
 
   if (obj->remove_prototype()) {
+    result->set_map(*isolate->sloppy_function_without_prototype_map());
+    DCHECK(prototype.is_null());
     DCHECK(result->shared()->IsApiFunction());
     DCHECK(!result->has_initial_map());
     DCHECK(!result->has_prototype());
+    DCHECK(!result->IsConstructor());
     return result;
   }
 
-#ifdef DEBUG
-  LookupIterator it(handle(JSObject::cast(result->prototype())),
-                    isolate->factory()->constructor_string(),
-                    LookupIterator::OWN_SKIP_INTERCEPTOR);
-  MaybeHandle<Object> maybe_prop = Object::GetProperty(&it);
-  DCHECK(it.IsFound());
-  DCHECK(maybe_prop.ToHandleChecked().is_identical_to(result));
-#endif
-
   // Down from here is only valid for API functions that can be used as a
   // constructor (don't set the "remove prototype" flag).
 
-  Handle<Map> map(result->initial_map());
+  if (obj->read_only_prototype()) {
+    result->set_map(*isolate->sloppy_function_with_readonly_prototype_map());
+  }
+
+  if (prototype->IsTheHole(isolate)) {
+    prototype = isolate->factory()->NewFunctionPrototype(result);
+  } else {
+    JSObject::AddProperty(Handle<JSObject>::cast(prototype),
+                          isolate->factory()->constructor_string(), result,
+                          DONT_ENUM);
+  }
+
+  int internal_field_count = 0;
+  if (!obj->instance_template()->IsUndefined(isolate)) {
+    Handle<ObjectTemplateInfo> instance_template = Handle<ObjectTemplateInfo>(
+        ObjectTemplateInfo::cast(obj->instance_template()));
+    internal_field_count =
+        Smi::cast(instance_template->internal_field_count())->value();
+  }
+
+  // TODO(svenpanne) Kill ApiInstanceType and refactor things by generalizing
+  // JSObject::GetHeaderSize.
+  int instance_size = kPointerSize * internal_field_count;
+  InstanceType type;
+  switch (instance_type) {
+    case JavaScriptObjectType:
+      if (!obj->needs_access_check() &&
+          obj->named_property_handler()->IsUndefined(isolate) &&
+          obj->indexed_property_handler()->IsUndefined(isolate)) {
+        type = JS_API_OBJECT_TYPE;
+      } else {
+        type = JS_SPECIAL_API_OBJECT_TYPE;
+      }
+      instance_size += JSObject::kHeaderSize;
+      break;
+    case GlobalObjectType:
+      type = JS_GLOBAL_OBJECT_TYPE;
+      instance_size += JSGlobalObject::kSize;
+      break;
+    case GlobalProxyType:
+      type = JS_GLOBAL_PROXY_TYPE;
+      instance_size += JSGlobalProxy::kSize;
+      break;
+    default:
+      UNREACHABLE();
+      type = JS_OBJECT_TYPE;  // Keep the compiler happy.
+      break;
+  }
+
+  Handle<Map> map =
+      isolate->factory()->NewMap(type, instance_size, FAST_HOLEY_SMI_ELEMENTS);
+  JSFunction::SetInitialMap(result, map, Handle<JSObject>::cast(prototype));
 
   // Mark as undetectable if needed.
   if (obj->undetectable()) {
@@ -612,20 +620,19 @@
   }
 
   // Set interceptor information in the map.
-  if (!obj->named_property_handler()->IsUndefined()) {
+  if (!obj->named_property_handler()->IsUndefined(isolate)) {
     map->set_has_named_interceptor();
   }
-  if (!obj->indexed_property_handler()->IsUndefined()) {
+  if (!obj->indexed_property_handler()->IsUndefined(isolate)) {
     map->set_has_indexed_interceptor();
   }
 
   // Mark instance as callable in the map.
-  if (!obj->instance_call_handler()->IsUndefined()) {
+  if (!obj->instance_call_handler()->IsUndefined(isolate)) {
     map->set_is_callable();
     map->set_is_constructor(true);
   }
 
-  DCHECK(result->shared()->IsApiFunction());
   return result;
 }
 
diff --git a/src/api-natives.h b/src/api-natives.h
index 91f0b16..66901fe 100644
--- a/src/api-natives.h
+++ b/src/api-natives.h
@@ -23,7 +23,8 @@
       Handle<FunctionTemplateInfo> data);
 
   MUST_USE_RESULT static MaybeHandle<JSObject> InstantiateObject(
-      Handle<ObjectTemplateInfo> data);
+      Handle<ObjectTemplateInfo> data,
+      Handle<JSReceiver> new_target = Handle<JSReceiver>());
 
   enum ApiInstanceType {
     JavaScriptObjectType,
diff --git a/src/api.cc b/src/api.cc
index 853bd50..04d8cb3 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -15,6 +15,7 @@
 #include "include/v8-experimental.h"
 #include "include/v8-profiler.h"
 #include "include/v8-testing.h"
+#include "include/v8-util.h"
 #include "src/accessors.h"
 #include "src/api-experimental.h"
 #include "src/api-natives.h"
@@ -40,6 +41,7 @@
 #include "src/icu_util.h"
 #include "src/isolate-inl.h"
 #include "src/json-parser.h"
+#include "src/json-stringifier.h"
 #include "src/messages.h"
 #include "src/parsing/parser.h"
 #include "src/parsing/scanner-character-streams.h"
@@ -48,13 +50,13 @@
 #include "src/profiler/heap-profiler.h"
 #include "src/profiler/heap-snapshot-generator-inl.h"
 #include "src/profiler/profile-generator-inl.h"
-#include "src/profiler/sampler.h"
-#include "src/property.h"
+#include "src/profiler/tick-sample.h"
 #include "src/property-descriptor.h"
 #include "src/property-details.h"
+#include "src/property.h"
 #include "src/prototype.h"
-#include "src/runtime/runtime.h"
 #include "src/runtime-profiler.h"
+#include "src/runtime/runtime.h"
 #include "src/simulator.h"
 #include "src/snapshot/natives.h"
 #include "src/snapshot/snapshot.h"
@@ -66,57 +68,56 @@
 #include "src/version.h"
 #include "src/vm-state-inl.h"
 
-
 namespace v8 {
 
-#define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr))
-
+#define LOG_API(isolate, class_name, function_name)                       \
+  i::RuntimeCallTimerScope _runtime_timer(                                \
+      isolate, &i::RuntimeCallStats::API_##class_name##_##function_name); \
+  LOG(isolate, ApiEntryCall("v8::" #class_name "::" #function_name))
 
 #define ENTER_V8(isolate) i::VMState<v8::OTHER> __state__((isolate))
 
-
-#define PREPARE_FOR_EXECUTION_GENERIC(isolate, context, function_name, \
-                                      bailout_value, HandleScopeClass, \
-                                      do_callback)                     \
-  if (IsExecutionTerminatingCheck(isolate)) {                          \
-    return bailout_value;                                              \
-  }                                                                    \
-  HandleScopeClass handle_scope(isolate);                              \
-  CallDepthScope call_depth_scope(isolate, context, do_callback);      \
-  LOG_API(isolate, function_name);                                     \
-  ENTER_V8(isolate);                                                   \
+#define PREPARE_FOR_EXECUTION_GENERIC(isolate, context, class_name,  \
+                                      function_name, bailout_value,  \
+                                      HandleScopeClass, do_callback) \
+  if (IsExecutionTerminatingCheck(isolate)) {                        \
+    return bailout_value;                                            \
+  }                                                                  \
+  HandleScopeClass handle_scope(isolate);                            \
+  CallDepthScope call_depth_scope(isolate, context, do_callback);    \
+  LOG_API(isolate, class_name, function_name);                       \
+  ENTER_V8(isolate);                                                 \
   bool has_pending_exception = false
 
-
-#define PREPARE_FOR_EXECUTION_WITH_CONTEXT(                                  \
-    context, function_name, bailout_value, HandleScopeClass, do_callback)    \
-  auto isolate = context.IsEmpty()                                           \
-                     ? i::Isolate::Current()                                 \
-                     : reinterpret_cast<i::Isolate*>(context->GetIsolate()); \
-  PREPARE_FOR_EXECUTION_GENERIC(isolate, context, function_name,             \
+#define PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \
+                                           bailout_value, HandleScopeClass,    \
+                                           do_callback)                        \
+  auto isolate = context.IsEmpty()                                             \
+                     ? i::Isolate::Current()                                   \
+                     : reinterpret_cast<i::Isolate*>(context->GetIsolate());   \
+  PREPARE_FOR_EXECUTION_GENERIC(isolate, context, class_name, function_name,   \
                                 bailout_value, HandleScopeClass, do_callback);
 
+#define PREPARE_FOR_EXECUTION_WITH_ISOLATE(isolate, class_name, function_name, \
+                                           T)                                  \
+  PREPARE_FOR_EXECUTION_GENERIC(isolate, Local<Context>(), class_name,         \
+                                function_name, MaybeLocal<T>(),                \
+                                InternalEscapableScope, false);
 
-#define PREPARE_FOR_EXECUTION_WITH_ISOLATE(isolate, function_name, T)     \
-  PREPARE_FOR_EXECUTION_GENERIC(isolate, Local<Context>(), function_name, \
-                                MaybeLocal<T>(), InternalEscapableScope,  \
-                                false);
+#define PREPARE_FOR_EXECUTION(context, class_name, function_name, T)          \
+  PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name,      \
+                                     MaybeLocal<T>(), InternalEscapableScope, \
+                                     false)
 
+#define PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, class_name,              \
+                                            function_name, T)                 \
+  PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name,      \
+                                     MaybeLocal<T>(), InternalEscapableScope, \
+                                     true)
 
-#define PREPARE_FOR_EXECUTION(context, function_name, T)                      \
-  PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, function_name, MaybeLocal<T>(), \
-                                     InternalEscapableScope, false)
-
-
-#define PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, function_name, T)        \
-  PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, function_name, MaybeLocal<T>(), \
-                                     InternalEscapableScope, true)
-
-
-#define PREPARE_FOR_EXECUTION_PRIMITIVE(context, function_name, T)         \
-  PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, function_name, Nothing<T>(), \
-                                     i::HandleScope, false)
-
+#define PREPARE_FOR_EXECUTION_PRIMITIVE(context, class_name, function_name, T) \
+  PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name,       \
+                                     Nothing<T>(), i::HandleScope, false)
 
 #define EXCEPTION_BAILOUT_CHECK_SCOPED(isolate, value) \
   do {                                                 \
@@ -241,7 +242,7 @@
 
 // When V8 cannot allocated memory FatalProcessOutOfMemory is called.
 // The default fatal error handler is called and execution is stopped.
-void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
+void i::V8::FatalProcessOutOfMemory(const char* location, bool is_heap_oom) {
   i::Isolate* isolate = i::Isolate::Current();
   char last_few_messages[Heap::kTraceRingBufferSize + 1];
   char js_stacktrace[Heap::kStacktraceBufferSize + 1];
@@ -303,7 +304,9 @@
     PrintF("\n<--- Last few GCs --->\n%s\n", first_newline);
     PrintF("\n<--- JS stacktrace --->\n%s\n", js_stacktrace);
   }
-  Utils::ApiCheck(false, location, "Allocation failed - process out of memory");
+  Utils::ApiCheck(false, location, is_heap_oom
+                  ? "Allocation failed - JavaScript heap out of memory"
+                  : "Allocation failed - process out of memory");
   // If the fatal error handler returns, we stop execution.
   FATAL("API fatal error handler returned after process out of memory");
 }
@@ -381,91 +384,159 @@
   return true;
 }
 
-StartupData SerializeIsolateAndContext(
-    Isolate* isolate, Persistent<Context>* context,
-    i::Snapshot::Metadata metadata,
-    i::StartupSerializer::FunctionCodeHandling function_code_handling) {
-  if (context->IsEmpty()) return {NULL, 0};
+struct SnapshotCreatorData {
+  explicit SnapshotCreatorData(Isolate* isolate)
+      : isolate_(isolate),
+        contexts_(isolate),
+        templates_(isolate),
+        created_(false) {}
 
-  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  static SnapshotCreatorData* cast(void* data) {
+    return reinterpret_cast<SnapshotCreatorData*>(data);
+  }
+
+  ArrayBufferAllocator allocator_;
+  Isolate* isolate_;
+  PersistentValueVector<Context> contexts_;
+  PersistentValueVector<Template> templates_;
+  bool created_;
+};
+
+}  // namespace
+
+SnapshotCreator::SnapshotCreator(intptr_t* external_references,
+                                 StartupData* existing_snapshot) {
+  i::Isolate* internal_isolate = new i::Isolate(true);
+  Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate);
+  SnapshotCreatorData* data = new SnapshotCreatorData(isolate);
+  data->isolate_ = isolate;
+  internal_isolate->set_array_buffer_allocator(&data->allocator_);
+  internal_isolate->set_api_external_references(external_references);
+  isolate->Enter();
+  if (existing_snapshot) {
+    internal_isolate->set_snapshot_blob(existing_snapshot);
+    i::Snapshot::Initialize(internal_isolate);
+  } else {
+    internal_isolate->Init(nullptr);
+  }
+  data_ = data;
+}
+
+SnapshotCreator::~SnapshotCreator() {
+  SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
+  DCHECK(data->created_);
+  Isolate* isolate = data->isolate_;
+  isolate->Exit();
+  isolate->Dispose();
+  delete data;
+}
+
+Isolate* SnapshotCreator::GetIsolate() {
+  return SnapshotCreatorData::cast(data_)->isolate_;
+}
+
+size_t SnapshotCreator::AddContext(Local<Context> context) {
+  DCHECK(!context.IsEmpty());
+  SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
+  DCHECK(!data->created_);
+  Isolate* isolate = data->isolate_;
+  CHECK_EQ(isolate, context->GetIsolate());
+  size_t index = static_cast<int>(data->contexts_.Size());
+  data->contexts_.Append(context);
+  return index;
+}
+
+size_t SnapshotCreator::AddTemplate(Local<Template> template_obj) {
+  DCHECK(!template_obj.IsEmpty());
+  SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
+  DCHECK(!data->created_);
+  DCHECK_EQ(reinterpret_cast<i::Isolate*>(data->isolate_),
+            Utils::OpenHandle(*template_obj)->GetIsolate());
+  size_t index = static_cast<int>(data->templates_.Size());
+  data->templates_.Append(template_obj);
+  return index;
+}
+
+StartupData SnapshotCreator::CreateBlob(
+    SnapshotCreator::FunctionCodeHandling function_code_handling) {
+  SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(data->isolate_);
+  DCHECK(!data->created_);
+
+  {
+    int num_templates = static_cast<int>(data->templates_.Size());
+    i::HandleScope scope(isolate);
+    i::Handle<i::FixedArray> templates =
+        isolate->factory()->NewFixedArray(num_templates, i::TENURED);
+    for (int i = 0; i < num_templates; i++) {
+      templates->set(i, *v8::Utils::OpenHandle(*data->templates_.Get(i)));
+    }
+    isolate->heap()->SetSerializedTemplates(*templates);
+    data->templates_.Clear();
+  }
 
   // If we don't do this then we end up with a stray root pointing at the
   // context even after we have disposed of the context.
-  internal_isolate->heap()->CollectAllAvailableGarbage("mksnapshot");
+  isolate->heap()->CollectAllAvailableGarbage("mksnapshot");
+  isolate->heap()->CompactWeakFixedArrays();
 
-  // GC may have cleared weak cells, so compact any WeakFixedArrays
-  // found on the heap.
-  i::HeapIterator iterator(internal_isolate->heap(),
-                           i::HeapIterator::kFilterUnreachable);
-  for (i::HeapObject* o = iterator.next(); o != NULL; o = iterator.next()) {
-    if (o->IsPrototypeInfo()) {
-      i::Object* prototype_users = i::PrototypeInfo::cast(o)->prototype_users();
-      if (prototype_users->IsWeakFixedArray()) {
-        i::WeakFixedArray* array = i::WeakFixedArray::cast(prototype_users);
-        array->Compact<i::JSObject::PrototypeRegistryCompactionCallback>();
-      }
-    } else if (o->IsScript()) {
-      i::Object* shared_list = i::Script::cast(o)->shared_function_infos();
-      if (shared_list->IsWeakFixedArray()) {
-        i::WeakFixedArray* array = i::WeakFixedArray::cast(shared_list);
-        array->Compact<i::WeakFixedArray::NullCallback>();
-      }
-    }
+  i::DisallowHeapAllocation no_gc_from_here_on;
+
+  int num_contexts = static_cast<int>(data->contexts_.Size());
+  i::List<i::Object*> contexts(num_contexts);
+  for (int i = 0; i < num_contexts; i++) {
+    i::HandleScope scope(isolate);
+    i::Handle<i::Context> context =
+        v8::Utils::OpenHandle(*data->contexts_.Get(i));
+    contexts.Add(*context);
+  }
+  data->contexts_.Clear();
+
+  i::StartupSerializer startup_serializer(isolate, function_code_handling);
+  startup_serializer.SerializeStrongReferences();
+
+  // Serialize each context with a new partial serializer.
+  i::List<i::SnapshotData*> context_snapshots(num_contexts);
+  for (int i = 0; i < num_contexts; i++) {
+    i::PartialSerializer partial_serializer(isolate, &startup_serializer);
+    partial_serializer.Serialize(&contexts[i]);
+    context_snapshots.Add(new i::SnapshotData(&partial_serializer));
   }
 
-  i::Object* raw_context = *v8::Utils::OpenPersistent(*context);
-  context->Reset();
+  startup_serializer.SerializeWeakReferencesAndDeferred();
+  i::SnapshotData startup_snapshot(&startup_serializer);
+  StartupData result =
+      i::Snapshot::CreateSnapshotBlob(&startup_snapshot, &context_snapshots);
 
-  i::SnapshotByteSink snapshot_sink;
-  i::StartupSerializer ser(internal_isolate, &snapshot_sink,
-                           function_code_handling);
-  ser.SerializeStrongReferences();
-
-  i::SnapshotByteSink context_sink;
-  i::PartialSerializer context_ser(internal_isolate, &ser, &context_sink);
-  context_ser.Serialize(&raw_context);
-  ser.SerializeWeakReferencesAndDeferred();
-
-  return i::Snapshot::CreateSnapshotBlob(ser, context_ser, metadata);
+  // Delete heap-allocated context snapshot instances.
+  for (const auto& context_snapshot : context_snapshots) {
+    delete context_snapshot;
+  }
+  data->created_ = true;
+  return result;
 }
 
-}  // namespace
-
 StartupData V8::CreateSnapshotDataBlob(const char* embedded_source) {
   // Create a new isolate and a new context from scratch, optionally run
   // a script to embed, and serialize to create a snapshot blob.
-  StartupData result = {NULL, 0};
-
+  StartupData result = {nullptr, 0};
   base::ElapsedTimer timer;
   timer.Start();
-
-  ArrayBufferAllocator allocator;
-  i::Isolate* internal_isolate = new i::Isolate(true);
-  internal_isolate->set_array_buffer_allocator(&allocator);
-  Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate);
-
   {
-    Isolate::Scope isolate_scope(isolate);
-    internal_isolate->Init(NULL);
-    Persistent<Context> context;
+    SnapshotCreator snapshot_creator;
+    Isolate* isolate = snapshot_creator.GetIsolate();
     {
-      HandleScope handle_scope(isolate);
-      Local<Context> new_context = Context::New(isolate);
-      context.Reset(isolate, new_context);
+      HandleScope scope(isolate);
+      Local<Context> context = Context::New(isolate);
       if (embedded_source != NULL &&
-          !RunExtraCode(isolate, new_context, embedded_source, "<embedded>")) {
-        context.Reset();
+          !RunExtraCode(isolate, context, embedded_source, "<embedded>")) {
+        return result;
       }
+      snapshot_creator.AddContext(context);
     }
-
-    i::Snapshot::Metadata metadata;
-    metadata.set_embeds_script(embedded_source != NULL);
-
-    result = SerializeIsolateAndContext(
-        isolate, &context, metadata, i::StartupSerializer::CLEAR_FUNCTION_CODE);
-    DCHECK(context.IsEmpty());
+    result = snapshot_creator.CreateBlob(
+        SnapshotCreator::FunctionCodeHandling::kClear);
   }
-  isolate->Dispose();
 
   if (i::FLAG_profile_deserialization) {
     i::PrintF("Creating snapshot took %0.3f ms\n",
@@ -485,42 +556,28 @@
   //    compilation of executed functions.
   //  - Create a new context. This context will be unpolluted.
   //  - Serialize the isolate and the second context into a new snapshot blob.
-  StartupData result = {NULL, 0};
-
+  StartupData result = {nullptr, 0};
   base::ElapsedTimer timer;
   timer.Start();
-
-  ArrayBufferAllocator allocator;
-  i::Isolate* internal_isolate = new i::Isolate(true);
-  internal_isolate->set_array_buffer_allocator(&allocator);
-  internal_isolate->set_snapshot_blob(&cold_snapshot_blob);
-  Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate);
-
   {
-    Isolate::Scope isolate_scope(isolate);
-    i::Snapshot::Initialize(internal_isolate);
-    Persistent<Context> context;
-    bool success;
+    SnapshotCreator snapshot_creator(nullptr, &cold_snapshot_blob);
+    Isolate* isolate = snapshot_creator.GetIsolate();
+    {
+      HandleScope scope(isolate);
+      Local<Context> context = Context::New(isolate);
+      if (!RunExtraCode(isolate, context, warmup_source, "<warm-up>")) {
+        return result;
+      }
+    }
     {
       HandleScope handle_scope(isolate);
-      Local<Context> new_context = Context::New(isolate);
-      success = RunExtraCode(isolate, new_context, warmup_source, "<warm-up>");
-    }
-    if (success) {
-      HandleScope handle_scope(isolate);
       isolate->ContextDisposedNotification(false);
-      Local<Context> new_context = Context::New(isolate);
-      context.Reset(isolate, new_context);
+      Local<Context> context = Context::New(isolate);
+      snapshot_creator.AddContext(context);
     }
-
-    i::Snapshot::Metadata metadata;
-    metadata.set_embeds_script(i::Snapshot::EmbedsScript(internal_isolate));
-
-    result = SerializeIsolateAndContext(
-        isolate, &context, metadata, i::StartupSerializer::KEEP_FUNCTION_CODE);
-    DCHECK(context.IsEmpty());
+    result = snapshot_creator.CreateBlob(
+        SnapshotCreator::FunctionCodeHandling::kKeep);
   }
-  isolate->Dispose();
 
   if (i::FLAG_profile_deserialization) {
     i::PrintF("Warming up snapshot took %0.3f ms\n",
@@ -656,7 +713,7 @@
 
 
 i::Object** V8::GlobalizeReference(i::Isolate* isolate, i::Object** obj) {
-  LOG_API(isolate, "Persistent::New");
+  LOG_API(isolate, Persistent, New);
   i::Handle<i::Object> result = isolate->global_handles()->Create(*obj);
 #ifdef VERIFY_HEAP
   if (i::FLAG_verify_heap) {
@@ -682,13 +739,7 @@
   isolate->heap()->RegisterExternallyReferencedObject(object);
 }
 
-void V8::MakeWeak(i::Object** object, void* parameter,
-                  WeakCallback weak_callback) {
-  i::GlobalHandles::MakeWeak(object, parameter, weak_callback);
-}
-
-
-void V8::MakeWeak(i::Object** object, void* parameter,
+void V8::MakeWeak(i::Object** location, void* parameter,
                   int internal_field_index1, int internal_field_index2,
                   WeakCallbackInfo<void>::Callback weak_callback) {
   WeakCallbackType type = WeakCallbackType::kParameter;
@@ -703,24 +754,25 @@
     DCHECK_EQ(internal_field_index1, -1);
     DCHECK_EQ(internal_field_index2, -1);
   }
-  i::GlobalHandles::MakeWeak(object, parameter, weak_callback, type);
+  i::GlobalHandles::MakeWeak(location, parameter, weak_callback, type);
 }
 
-
-void V8::MakeWeak(i::Object** object, void* parameter,
+void V8::MakeWeak(i::Object** location, void* parameter,
                   WeakCallbackInfo<void>::Callback weak_callback,
                   WeakCallbackType type) {
-  i::GlobalHandles::MakeWeak(object, parameter, weak_callback, type);
+  i::GlobalHandles::MakeWeak(location, parameter, weak_callback, type);
 }
 
-
-void* V8::ClearWeak(i::Object** obj) {
-  return i::GlobalHandles::ClearWeakness(obj);
+void V8::MakeWeak(i::Object*** location_addr) {
+  i::GlobalHandles::MakeWeak(location_addr);
 }
 
+void* V8::ClearWeak(i::Object** location) {
+  return i::GlobalHandles::ClearWeakness(location);
+}
 
-void V8::DisposeGlobal(i::Object** obj) {
-  i::GlobalHandles::Destroy(obj);
+void V8::DisposeGlobal(i::Object** location) {
+  i::GlobalHandles::Destroy(location);
 }
 
 
@@ -815,9 +867,8 @@
 
 i::Object** EscapableHandleScope::Escape(i::Object** escape_value) {
   i::Heap* heap = reinterpret_cast<i::Isolate*>(GetIsolate())->heap();
-  Utils::ApiCheck(*escape_slot_ == heap->the_hole_value(),
-                  "EscapeableHandleScope::Escape",
-                  "Escape value set twice");
+  Utils::ApiCheck((*escape_slot_)->IsTheHole(heap->isolate()),
+                  "EscapeableHandleScope::Escape", "Escape value set twice");
   if (escape_value == NULL) {
     *escape_slot_ = heap->undefined_value();
     return NULL;
@@ -1028,13 +1079,13 @@
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
   auto value_obj = Utils::OpenHandle(*value);
+  CHECK(!value_obj->IsJSReceiver() || value_obj->IsTemplateInfo());
   if (value_obj->IsObjectTemplateInfo()) {
     templ->set_serial_number(i::Smi::FromInt(0));
     if (templ->IsFunctionTemplateInfo()) {
       i::Handle<i::FunctionTemplateInfo>::cast(templ)->set_do_not_cache(true);
     }
   }
-  // TODO(dcarney): split api to allow values of v8::Value or v8::TemplateInfo.
   i::ApiNatives::AddDataProperty(isolate, templ, Utils::OpenHandle(*name),
                                  value_obj,
                                  static_cast<i::PropertyAttributes>(attribute));
@@ -1078,7 +1129,7 @@
   ENTER_V8(i_isolate);
   i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template(),
                               i_isolate);
-  if (result->IsUndefined()) {
+  if (result->IsUndefined(i_isolate)) {
     // Do not cache prototype objects.
     result = Utils::OpenHandle(
         *ObjectTemplateNew(i_isolate, Local<FunctionTemplate>(), true));
@@ -1116,8 +1167,7 @@
   obj->set_do_not_cache(do_not_cache);
   int next_serial_number = 0;
   if (!do_not_cache) {
-    next_serial_number = isolate->next_serial_number() + 1;
-    isolate->set_next_serial_number(next_serial_number);
+    next_serial_number = isolate->heap()->GetNextTemplateSerialNumber();
   }
   obj->set_serial_number(i::Smi::FromInt(next_serial_number));
   if (callback != 0) {
@@ -1136,21 +1186,34 @@
 }
 
 
-Local<FunctionTemplate> FunctionTemplate::New(Isolate* isolate,
-                                              FunctionCallback callback,
-                                              v8::Local<Value> data,
-                                              v8::Local<Signature> signature,
-                                              int length) {
+Local<FunctionTemplate> FunctionTemplate::New(
+    Isolate* isolate, FunctionCallback callback, v8::Local<Value> data,
+    v8::Local<Signature> signature, int length, ConstructorBehavior behavior) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   // Changes to the environment cannot be captured in the snapshot. Expect no
   // function templates when the isolate is created for serialization.
-  DCHECK(!i_isolate->serializer_enabled());
-  LOG_API(i_isolate, "FunctionTemplate::New");
+  LOG_API(i_isolate, FunctionTemplate, New);
   ENTER_V8(i_isolate);
-  return FunctionTemplateNew(i_isolate, callback, nullptr, data, signature,
-                             length, false);
+  auto templ = FunctionTemplateNew(i_isolate, callback, nullptr, data,
+                                   signature, length, false);
+  if (behavior == ConstructorBehavior::kThrow) templ->RemovePrototype();
+  return templ;
 }
 
+Local<FunctionTemplate> FunctionTemplate::FromSnapshot(Isolate* isolate,
+                                                       size_t index) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  i::FixedArray* templates = i_isolate->heap()->serialized_templates();
+  int int_index = static_cast<int>(index);
+  if (int_index < templates->length()) {
+    i::Object* info = i_isolate->heap()->serialized_templates()->get(int_index);
+    if (info->IsFunctionTemplateInfo()) {
+      return Utils::ToLocal(i::Handle<i::FunctionTemplateInfo>(
+          i::FunctionTemplateInfo::cast(info)));
+    }
+  }
+  return Local<FunctionTemplate>();
+}
 
 Local<FunctionTemplate> FunctionTemplate::NewWithFastHandler(
     Isolate* isolate, FunctionCallback callback,
@@ -1158,7 +1221,7 @@
     v8::Local<Signature> signature, int length) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   DCHECK(!i_isolate->serializer_enabled());
-  LOG_API(i_isolate, "FunctionTemplate::NewWithFastHandler");
+  LOG_API(i_isolate, FunctionTemplate, NewWithFastHandler);
   ENTER_V8(i_isolate);
   return FunctionTemplateNew(i_isolate, callback, fast_handler, data, signature,
                              length, false);
@@ -1223,8 +1286,10 @@
   return obj;
 }
 
+namespace {
+
 template <typename Getter, typename Setter>
-static i::Handle<i::AccessorInfo> MakeAccessorInfo(
+i::Handle<i::AccessorInfo> MakeAccessorInfo(
     v8::Local<Name> name, Getter getter, Setter setter, v8::Local<Value> data,
     v8::AccessControl settings, v8::PropertyAttribute attributes,
     v8::Local<AccessorSignature> signature, bool is_special_data_property) {
@@ -1235,6 +1300,8 @@
     setter = reinterpret_cast<Setter>(&i::Accessors::ReconfigureToDataProperty);
   }
   SET_FIELD_WRAPPED(obj, set_setter, setter);
+  i::Address redirected = obj->redirected_getter();
+  if (redirected != nullptr) SET_FIELD_WRAPPED(obj, set_js_getter, redirected);
   if (data.IsEmpty()) {
     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
   }
@@ -1243,6 +1310,7 @@
   return SetAccessorInfoProperties(obj, name, settings, attributes, signature);
 }
 
+}  // namespace
 
 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
   i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this, true);
@@ -1253,7 +1321,7 @@
   }
   i::Isolate* isolate = handle->GetIsolate();
   ENTER_V8(isolate);
-  if (handle->instance_template()->IsUndefined()) {
+  if (handle->instance_template()->IsUndefined(isolate)) {
     Local<ObjectTemplate> templ =
         ObjectTemplate::New(isolate, ToApiHandle<FunctionTemplate>(handle));
     handle->set_instance_template(*Utils::OpenHandle(*templ));
@@ -1334,10 +1402,7 @@
 static Local<ObjectTemplate> ObjectTemplateNew(
     i::Isolate* isolate, v8::Local<FunctionTemplate> constructor,
     bool do_not_cache) {
-  // Changes to the environment cannot be captured in the snapshot. Expect no
-  // object templates when the isolate is created for serialization.
-  DCHECK(!isolate->serializer_enabled());
-  LOG_API(isolate, "ObjectTemplate::New");
+  LOG_API(isolate, ObjectTemplate, New);
   ENTER_V8(isolate);
   i::Handle<i::Struct> struct_obj =
       isolate->factory()->NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
@@ -1346,8 +1411,7 @@
   InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
   int next_serial_number = 0;
   if (!do_not_cache) {
-    next_serial_number = isolate->next_serial_number() + 1;
-    isolate->set_next_serial_number(next_serial_number);
+    next_serial_number = isolate->heap()->GetNextTemplateSerialNumber();
   }
   obj->set_serial_number(i::Smi::FromInt(next_serial_number));
   if (!constructor.IsEmpty())
@@ -1361,13 +1425,28 @@
   return ObjectTemplateNew(isolate, constructor, false);
 }
 
+Local<ObjectTemplate> ObjectTemplate::FromSnapshot(Isolate* isolate,
+                                                   size_t index) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  i::FixedArray* templates = i_isolate->heap()->serialized_templates();
+  int int_index = static_cast<int>(index);
+  if (int_index < templates->length()) {
+    i::Object* info = i_isolate->heap()->serialized_templates()->get(int_index);
+    if (info->IsObjectTemplateInfo()) {
+      return Utils::ToLocal(
+          i::Handle<i::ObjectTemplateInfo>(i::ObjectTemplateInfo::cast(info)));
+    }
+  }
+  return Local<ObjectTemplate>();
+}
+
 // Ensure that the object template has a constructor.  If no
 // constructor is available we create one.
 static i::Handle<i::FunctionTemplateInfo> EnsureConstructor(
     i::Isolate* isolate,
     ObjectTemplate* object_template) {
   i::Object* obj = Utils::OpenHandle(object_template)->constructor();
-  if (!obj ->IsUndefined()) {
+  if (!obj->IsUndefined(isolate)) {
     i::FunctionTemplateInfo* info = i::FunctionTemplateInfo::cast(obj);
     return i::Handle<i::FunctionTemplateInfo>(info, isolate);
   }
@@ -1456,20 +1535,12 @@
                       signature, i::FLAG_disable_old_api_accessors);
 }
 
-
 template <typename Getter, typename Setter, typename Query, typename Deleter,
           typename Enumerator>
-static void ObjectTemplateSetNamedPropertyHandler(ObjectTemplate* templ,
-                                                  Getter getter, Setter setter,
-                                                  Query query, Deleter remover,
-                                                  Enumerator enumerator,
-                                                  Local<Value> data,
-                                                  PropertyHandlerFlags flags) {
-  i::Isolate* isolate = Utils::OpenHandle(templ)->GetIsolate();
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  auto cons = EnsureConstructor(isolate, templ);
-  EnsureNotInstantiated(cons, "ObjectTemplateSetNamedPropertyHandler");
+static i::Handle<i::InterceptorInfo> CreateInterceptorInfo(
+    i::Isolate* isolate, Getter getter, Setter setter, Query query,
+    Deleter remover, Enumerator enumerator, Local<Value> data,
+    PropertyHandlerFlags flags) {
   auto obj = i::Handle<i::InterceptorInfo>::cast(
       isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE));
   obj->set_flags(0);
@@ -1491,6 +1562,24 @@
     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
   }
   obj->set_data(*Utils::OpenHandle(*data));
+  return obj;
+}
+
+template <typename Getter, typename Setter, typename Query, typename Deleter,
+          typename Enumerator>
+static void ObjectTemplateSetNamedPropertyHandler(ObjectTemplate* templ,
+                                                  Getter getter, Setter setter,
+                                                  Query query, Deleter remover,
+                                                  Enumerator enumerator,
+                                                  Local<Value> data,
+                                                  PropertyHandlerFlags flags) {
+  i::Isolate* isolate = Utils::OpenHandle(templ)->GetIsolate();
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
+  auto cons = EnsureConstructor(isolate, templ);
+  EnsureNotInstantiated(cons, "ObjectTemplateSetNamedPropertyHandler");
+  auto obj = CreateInterceptorInfo(isolate, getter, setter, query, remover,
+                                   enumerator, data, flags);
   cons->set_named_property_handler(*obj);
 }
 
@@ -1537,8 +1626,8 @@
       i::Handle<i::AccessCheckInfo>::cast(struct_info);
 
   SET_FIELD_WRAPPED(info, set_callback, callback);
-  SET_FIELD_WRAPPED(info, set_named_callback, nullptr);
-  SET_FIELD_WRAPPED(info, set_indexed_callback, nullptr);
+  info->set_named_interceptor(nullptr);
+  info->set_indexed_interceptor(nullptr);
 
   if (data.IsEmpty()) {
     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
@@ -1549,28 +1638,34 @@
   cons->set_needs_access_check(true);
 }
 
-void ObjectTemplate::SetAccessCheckCallback(
-    DeprecatedAccessCheckCallback callback, Local<Value> data) {
-  SetAccessCheckCallback(reinterpret_cast<AccessCheckCallback>(callback), data);
-}
-
-void ObjectTemplate::SetAccessCheckCallbacks(
-    NamedSecurityCallback named_callback,
-    IndexedSecurityCallback indexed_callback, Local<Value> data) {
+void ObjectTemplate::SetAccessCheckCallbackAndHandler(
+    AccessCheckCallback callback,
+    const NamedPropertyHandlerConfiguration& named_handler,
+    const IndexedPropertyHandlerConfiguration& indexed_handler,
+    Local<Value> data) {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
   auto cons = EnsureConstructor(isolate, this);
-  EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetAccessCheckCallbacks");
+  EnsureNotInstantiated(
+      cons, "v8::ObjectTemplate::SetAccessCheckCallbackWithHandler");
 
   i::Handle<i::Struct> struct_info =
       isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE);
   i::Handle<i::AccessCheckInfo> info =
       i::Handle<i::AccessCheckInfo>::cast(struct_info);
 
-  SET_FIELD_WRAPPED(info, set_callback, nullptr);
-  SET_FIELD_WRAPPED(info, set_named_callback, named_callback);
-  SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback);
+  SET_FIELD_WRAPPED(info, set_callback, callback);
+  auto named_interceptor = CreateInterceptorInfo(
+      isolate, named_handler.getter, named_handler.setter, named_handler.query,
+      named_handler.deleter, named_handler.enumerator, named_handler.data,
+      named_handler.flags);
+  info->set_named_interceptor(*named_interceptor);
+  auto indexed_interceptor = CreateInterceptorInfo(
+      isolate, indexed_handler.getter, indexed_handler.setter,
+      indexed_handler.query, indexed_handler.deleter,
+      indexed_handler.enumerator, indexed_handler.data, indexed_handler.flags);
+  info->set_indexed_interceptor(*indexed_interceptor);
 
   if (data.IsEmpty()) {
     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
@@ -1581,7 +1676,6 @@
   cons->set_needs_access_check(true);
 }
 
-
 void ObjectTemplate::SetHandler(
     const IndexedPropertyHandlerConfiguration& config) {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
@@ -1589,25 +1683,9 @@
   i::HandleScope scope(isolate);
   auto cons = EnsureConstructor(isolate, this);
   EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetHandler");
-  auto obj = i::Handle<i::InterceptorInfo>::cast(
-      isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE));
-  obj->set_flags(0);
-
-  if (config.getter != 0) SET_FIELD_WRAPPED(obj, set_getter, config.getter);
-  if (config.setter != 0) SET_FIELD_WRAPPED(obj, set_setter, config.setter);
-  if (config.query != 0) SET_FIELD_WRAPPED(obj, set_query, config.query);
-  if (config.deleter != 0) SET_FIELD_WRAPPED(obj, set_deleter, config.deleter);
-  if (config.enumerator != 0) {
-    SET_FIELD_WRAPPED(obj, set_enumerator, config.enumerator);
-  }
-  obj->set_all_can_read(static_cast<int>(config.flags) &
-                        static_cast<int>(PropertyHandlerFlags::kAllCanRead));
-
-  v8::Local<v8::Value> data = config.data;
-  if (data.IsEmpty()) {
-    data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
-  }
-  obj->set_data(*Utils::OpenHandle(*data));
+  auto obj = CreateInterceptorInfo(
+      isolate, config.getter, config.setter, config.query, config.deleter,
+      config.enumerator, config.data, config.flags);
   cons->set_indexed_property_handler(*obj);
 }
 
@@ -1715,7 +1793,7 @@
   i::Handle<i::HeapObject> obj =
       i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
   i::Isolate* isolate = obj->GetIsolate();
-  LOG_API(isolate, "v8::UnboundScript::GetId");
+  LOG_API(isolate, UnboundScript, GetId);
   i::HandleScope scope(isolate);
   i::Handle<i::SharedFunctionInfo> function_info(
       i::SharedFunctionInfo::cast(*obj));
@@ -1728,7 +1806,7 @@
   i::Handle<i::SharedFunctionInfo> obj =
       i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
   i::Isolate* isolate = obj->GetIsolate();
-  LOG_API(isolate, "UnboundScript::GetLineNumber");
+  LOG_API(isolate, UnboundScript, GetLineNumber);
   if (obj->script()->IsScript()) {
     i::Handle<i::Script> script(i::Script::cast(obj->script()));
     return i::Script::GetLineNumber(script, code_pos);
@@ -1742,7 +1820,7 @@
   i::Handle<i::SharedFunctionInfo> obj =
       i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
   i::Isolate* isolate = obj->GetIsolate();
-  LOG_API(isolate, "UnboundScript::GetName");
+  LOG_API(isolate, UnboundScript, GetName);
   if (obj->script()->IsScript()) {
     i::Object* name = i::Script::cast(obj->script())->name();
     return Utils::ToLocal(i::Handle<i::Object>(name, isolate));
@@ -1756,7 +1834,7 @@
   i::Handle<i::SharedFunctionInfo> obj =
       i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
   i::Isolate* isolate = obj->GetIsolate();
-  LOG_API(isolate, "UnboundScript::GetSourceURL");
+  LOG_API(isolate, UnboundScript, GetSourceURL);
   if (obj->script()->IsScript()) {
     i::Object* url = i::Script::cast(obj->script())->source_url();
     return Utils::ToLocal(i::Handle<i::Object>(url, isolate));
@@ -1770,7 +1848,7 @@
   i::Handle<i::SharedFunctionInfo> obj =
       i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
   i::Isolate* isolate = obj->GetIsolate();
-  LOG_API(isolate, "UnboundScript::GetSourceMappingURL");
+  LOG_API(isolate, UnboundScript, GetSourceMappingURL);
   if (obj->script()->IsScript()) {
     i::Object* url = i::Script::cast(obj->script())->source_mapping_url();
     return Utils::ToLocal(i::Handle<i::Object>(url, isolate));
@@ -1781,12 +1859,13 @@
 
 
 MaybeLocal<Value> Script::Run(Local<Context> context) {
-  PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, "v8::Script::Run()", Value)
+  PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, Script, Run, Value)
+  i::HistogramTimerScope execute_timer(isolate->counters()->execute(), true);
   i::AggregatingHistogramTimerScope timer(isolate->counters()->compile_lazy());
   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
   TRACE_EVENT0("v8", "V8.Execute");
   auto fun = i::Handle<i::JSFunction>::cast(Utils::OpenHandle(this));
-  i::Handle<i::Object> receiver(isolate->global_proxy(), isolate);
+  i::Handle<i::Object> receiver = isolate->global_proxy();
   Local<Value> result;
   has_pending_exception =
       !ToLocal<Value>(i::Execution::Call(isolate, fun, receiver, 0, NULL),
@@ -1817,8 +1896,8 @@
     Isolate* v8_isolate, Source* source, CompileOptions options,
     bool is_module) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
-  PREPARE_FOR_EXECUTION_WITH_ISOLATE(
-      isolate, "v8::ScriptCompiler::CompileUnbound()", UnboundScript);
+  PREPARE_FOR_EXECUTION_WITH_ISOLATE(isolate, ScriptCompiler, CompileUnbound,
+                                     UnboundScript);
 
   // Don't try to produce any kind of cache when the debugger is loaded.
   if (isolate->debug()->is_loaded() &&
@@ -1977,8 +2056,8 @@
     Local<Context> v8_context, Source* source, size_t arguments_count,
     Local<String> arguments[], size_t context_extension_count,
     Local<Object> context_extensions[]) {
-  PREPARE_FOR_EXECUTION(
-      v8_context, "v8::ScriptCompiler::CompileFunctionInContext()", Function);
+  PREPARE_FOR_EXECUTION(v8_context, ScriptCompiler, CompileFunctionInContext,
+                        Function);
   i::Handle<i::String> source_string;
   auto factory = isolate->factory();
   if (arguments_count) {
@@ -2032,6 +2111,8 @@
   }
 
   i::Handle<i::Object> name_obj;
+  int eval_scope_position = 0;
+  int eval_position = i::RelocInfo::kNoPosition;
   int line_offset = 0;
   int column_offset = 0;
   if (!source->resource_name.IsEmpty()) {
@@ -2044,11 +2125,13 @@
     column_offset = static_cast<int>(source->resource_column_offset->Value());
   }
   i::Handle<i::JSFunction> fun;
-  has_pending_exception = !i::Compiler::GetFunctionFromEval(
-                               source_string, outer_info, context, i::SLOPPY,
-                               i::ONLY_SINGLE_FUNCTION_LITERAL, line_offset,
-                               column_offset - scope_position, name_obj,
-                               source->resource_options).ToHandle(&fun);
+  has_pending_exception =
+      !i::Compiler::GetFunctionFromEval(
+           source_string, outer_info, context, i::SLOPPY,
+           i::ONLY_SINGLE_FUNCTION_LITERAL, eval_scope_position, eval_position,
+           line_offset, column_offset - scope_position, name_obj,
+           source->resource_options)
+           .ToHandle(&fun);
   if (has_pending_exception) {
     isolate->ReportPendingMessages();
   }
@@ -2088,7 +2171,7 @@
                                            StreamedSource* v8_source,
                                            Local<String> full_source_string,
                                            const ScriptOrigin& origin) {
-  PREPARE_FOR_EXECUTION(context, "v8::ScriptCompiler::Compile()", Script);
+  PREPARE_FOR_EXECUTION(context, ScriptCompiler, Compile, Script);
   i::StreamedSource* source = v8_source->impl();
   i::Handle<i::String> str = Utils::OpenHandle(*(full_source_string));
   i::Handle<i::Script> script = isolate->factory()->NewScript(str);
@@ -2251,7 +2334,7 @@
 
 
 bool v8::TryCatch::HasCaught() const {
-  return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
+  return !reinterpret_cast<i::Object*>(exception_)->IsTheHole(isolate_);
 }
 
 
@@ -2287,7 +2370,7 @@
   if (!HasCaught()) return v8::Local<Value>();
   i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
   if (!raw_obj->IsJSObject()) return v8::Local<Value>();
-  PREPARE_FOR_EXECUTION(context, "v8::TryCatch::StackTrace", Value);
+  PREPARE_FOR_EXECUTION(context, TryCatch, StackTrace, Value);
   i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj), isolate_);
   i::Handle<i::String> name = isolate->factory()->stack_string();
   Maybe<bool> maybe = i::JSReceiver::HasProperty(obj, name);
@@ -2310,8 +2393,8 @@
 
 v8::Local<v8::Message> v8::TryCatch::Message() const {
   i::Object* message = reinterpret_cast<i::Object*>(message_obj_);
-  DCHECK(message->IsJSMessageObject() || message->IsTheHole());
-  if (HasCaught() && !message->IsTheHole()) {
+  DCHECK(message->IsJSMessageObject() || message->IsTheHole(isolate_));
+  if (HasCaught() && !message->IsTheHole(isolate_)) {
     return v8::Utils::MessageToLocal(i::Handle<i::Object>(message, isolate_));
   } else {
     return v8::Local<v8::Message>();
@@ -2389,7 +2472,7 @@
 
 
 Maybe<int> Message::GetLineNumber(Local<Context> context) const {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Message::GetLineNumber()", int);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Message, GetLineNumber, int);
   i::Handle<i::JSFunction> fun = isolate->message_get_line_number();
   i::Handle<i::Object> undefined = isolate->factory()->undefined_value();
   i::Handle<i::Object> args[] = {Utils::OpenHandle(this)};
@@ -2421,8 +2504,7 @@
 
 
 Maybe<int> Message::GetStartColumn(Local<Context> context) const {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Message::GetStartColumn()",
-                                  int);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Message, GetStartColumn, int);
   i::Handle<i::JSFunction> fun = isolate->message_get_column_number();
   i::Handle<i::Object> undefined = isolate->factory()->undefined_value();
   i::Handle<i::Object> args[] = {Utils::OpenHandle(this)};
@@ -2444,7 +2526,7 @@
 
 Maybe<int> Message::GetEndColumn(Local<Context> context) const {
   auto self = Utils::OpenHandle(this);
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Message::GetEndColumn()", int);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Message, GetEndColumn, int);
   i::Handle<i::JSFunction> fun = isolate->message_get_column_number();
   i::Handle<i::Object> undefined = isolate->factory()->undefined_value();
   i::Handle<i::Object> args[] = {self};
@@ -2488,7 +2570,7 @@
 
 
 MaybeLocal<String> Message::GetSourceLine(Local<Context> context) const {
-  PREPARE_FOR_EXECUTION(context, "v8::Message::GetSourceLine()", String);
+  PREPARE_FOR_EXECUTION(context, Message, GetSourceLine, String);
   i::Handle<i::JSFunction> fun = isolate->message_get_source_line();
   i::Handle<i::Object> undefined = isolate->factory()->undefined_value();
   i::Handle<i::Object> args[] = {Utils::OpenHandle(this)};
@@ -2621,7 +2703,7 @@
   i::Handle<i::JSObject> self = Utils::OpenHandle(f);
   i::Handle<i::Object> obj =
       i::JSReceiver::GetProperty(isolate, self, propertyName).ToHandleChecked();
-  return obj->IsTrue();
+  return obj->IsTrue(isolate);
 }
 
 bool StackFrame::IsEval() const { return getBoolProperty(this, "isEval"); }
@@ -2656,7 +2738,7 @@
   }
   i::Handle<i::ObjectHashTable> table(
       i::ObjectHashTable::cast(weak_collection->table()));
-  if (!table->IsKey(*key)) {
+  if (!table->IsKey(isolate, *key)) {
     DCHECK(false);
     return;
   }
@@ -2676,12 +2758,12 @@
   }
   i::Handle<i::ObjectHashTable> table(
       i::ObjectHashTable::cast(weak_collection->table()));
-  if (!table->IsKey(*key)) {
+  if (!table->IsKey(isolate, *key)) {
     DCHECK(false);
     return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
   }
   i::Handle<i::Object> lookup(table->Lookup(key), isolate);
-  if (lookup->IsTheHole())
+  if (lookup->IsTheHole(isolate))
     return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
   return Utils::ToLocal(lookup);
 }
@@ -2699,12 +2781,12 @@
   }
   i::Handle<i::ObjectHashTable> table(
       i::ObjectHashTable::cast(weak_collection->table()));
-  if (!table->IsKey(*key)) {
+  if (!table->IsKey(isolate, *key)) {
     DCHECK(false);
     return false;
   }
   i::Handle<i::Object> lookup(table->Lookup(key), isolate);
-  return !lookup->IsTheHole();
+  return !lookup->IsTheHole(isolate);
 }
 
 
@@ -2720,7 +2802,7 @@
   }
   i::Handle<i::ObjectHashTable> table(
       i::ObjectHashTable::cast(weak_collection->table()));
-  if (!table->IsKey(*key)) {
+  if (!table->IsKey(isolate, *key)) {
     DCHECK(false);
     return false;
   }
@@ -2733,49 +2815,94 @@
 
 MaybeLocal<Value> JSON::Parse(Isolate* v8_isolate, Local<String> json_string) {
   auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
-  PREPARE_FOR_EXECUTION_WITH_ISOLATE(isolate, "JSON::Parse", Value);
+  PREPARE_FOR_EXECUTION_WITH_ISOLATE(isolate, JSON, Parse, Value);
   i::Handle<i::String> string = Utils::OpenHandle(*json_string);
   i::Handle<i::String> source = i::String::Flatten(string);
+  i::Handle<i::Object> undefined = isolate->factory()->undefined_value();
   auto maybe = source->IsSeqOneByteString()
-                   ? i::JsonParser<true>::Parse(source)
-                   : i::JsonParser<false>::Parse(source);
+                   ? i::JsonParser<true>::Parse(isolate, source, undefined)
+                   : i::JsonParser<false>::Parse(isolate, source, undefined);
   Local<Value> result;
   has_pending_exception = !ToLocal<Value>(maybe, &result);
   RETURN_ON_FAILED_EXECUTION(Value);
   RETURN_ESCAPED(result);
 }
 
-
-Local<Value> JSON::Parse(Local<String> json_string) {
-  auto isolate = reinterpret_cast<v8::Isolate*>(
-      Utils::OpenHandle(*json_string)->GetIsolate());
-  RETURN_TO_LOCAL_UNCHECKED(Parse(isolate, json_string), Value);
+MaybeLocal<Value> JSON::Parse(Local<Context> context,
+                              Local<String> json_string) {
+  PREPARE_FOR_EXECUTION(context, JSON, Parse, Value);
+  i::Handle<i::String> string = Utils::OpenHandle(*json_string);
+  i::Handle<i::String> source = i::String::Flatten(string);
+  i::Handle<i::Object> undefined = isolate->factory()->undefined_value();
+  auto maybe = source->IsSeqOneByteString()
+                   ? i::JsonParser<true>::Parse(isolate, source, undefined)
+                   : i::JsonParser<false>::Parse(isolate, source, undefined);
+  Local<Value> result;
+  has_pending_exception = !ToLocal<Value>(maybe, &result);
+  RETURN_ON_FAILED_EXECUTION(Value);
+  RETURN_ESCAPED(result);
 }
 
+Local<Value> JSON::Parse(Local<String> json_string) {
+  RETURN_TO_LOCAL_UNCHECKED(Parse(Local<Context>(), json_string), Value);
+}
+
+MaybeLocal<String> JSON::Stringify(Local<Context> context,
+                                   Local<Object> json_object,
+                                   Local<String> gap) {
+  PREPARE_FOR_EXECUTION(context, JSON, Stringify, String);
+  i::Handle<i::Object> object = Utils::OpenHandle(*json_object);
+  i::Handle<i::Object> replacer = isolate->factory()->undefined_value();
+  i::Handle<i::String> gap_string = gap.IsEmpty()
+                                        ? isolate->factory()->empty_string()
+                                        : Utils::OpenHandle(*gap);
+  i::Handle<i::Object> maybe;
+  has_pending_exception = !i::JsonStringifier(isolate)
+                               .Stringify(object, replacer, gap_string)
+                               .ToHandle(&maybe);
+  RETURN_ON_FAILED_EXECUTION(String);
+  Local<String> result;
+  has_pending_exception =
+      !ToLocal<String>(i::Object::ToString(isolate, maybe), &result);
+  RETURN_ON_FAILED_EXECUTION(String);
+  RETURN_ESCAPED(result);
+}
 
 // --- D a t a ---
 
 bool Value::FullIsUndefined() const {
-  bool result = Utils::OpenHandle(this)->IsUndefined();
+  i::Handle<i::Object> object = Utils::OpenHandle(this);
+  bool result = false;
+  if (!object->IsSmi()) {
+    result = object->IsUndefined(i::HeapObject::cast(*object)->GetIsolate());
+  }
   DCHECK_EQ(result, QuickIsUndefined());
   return result;
 }
 
 
 bool Value::FullIsNull() const {
-  bool result = Utils::OpenHandle(this)->IsNull();
+  i::Handle<i::Object> object = Utils::OpenHandle(this);
+  bool result = false;
+  if (!object->IsSmi()) {
+    result = object->IsNull(i::HeapObject::cast(*object)->GetIsolate());
+  }
   DCHECK_EQ(result, QuickIsNull());
   return result;
 }
 
 
 bool Value::IsTrue() const {
-  return Utils::OpenHandle(this)->IsTrue();
+  i::Handle<i::Object> object = Utils::OpenHandle(this);
+  if (object->IsSmi()) return false;
+  return object->IsTrue(i::HeapObject::cast(*object)->GetIsolate());
 }
 
 
 bool Value::IsFalse() const {
-  return Utils::OpenHandle(this)->IsFalse();
+  i::Handle<i::Object> object = Utils::OpenHandle(this);
+  if (object->IsSmi()) return false;
+  return object->IsFalse(i::HeapObject::cast(*object)->GetIsolate());
 }
 
 
@@ -2912,22 +3039,7 @@
 
 
 bool Value::IsNativeError() const {
-  i::Handle<i::Object> obj = Utils::OpenHandle(this);
-  if (!obj->IsJSObject()) return false;
-  i::Handle<i::JSObject> js_obj = i::Handle<i::JSObject>::cast(obj);
-  i::Isolate* isolate = js_obj->GetIsolate();
-  i::Handle<i::Object> constructor(js_obj->map()->GetConstructor(), isolate);
-  if (!constructor->IsJSFunction()) return false;
-  i::Handle<i::JSFunction> function =
-      i::Handle<i::JSFunction>::cast(constructor);
-  if (!function->shared()->native()) return false;
-  return function.is_identical_to(isolate->error_function()) ||
-         function.is_identical_to(isolate->eval_error_function()) ||
-         function.is_identical_to(isolate->range_error_function()) ||
-         function.is_identical_to(isolate->reference_error_function()) ||
-         function.is_identical_to(isolate->syntax_error_function()) ||
-         function.is_identical_to(isolate->type_error_function()) ||
-         function.is_identical_to(isolate->uri_error_function());
+  return Utils::OpenHandle(this)->IsJSError();
 }
 
 
@@ -2959,17 +3071,12 @@
   return Utils::OpenHandle(this)->IsJSSetIterator();
 }
 
-
-bool Value::IsPromise() const {
-  auto self = Utils::OpenHandle(this);
-  return i::Object::IsPromise(self);
-}
-
+bool Value::IsPromise() const { return Utils::OpenHandle(this)->IsJSPromise(); }
 
 MaybeLocal<String> Value::ToString(Local<Context> context) const {
   auto obj = Utils::OpenHandle(this);
   if (obj->IsString()) return ToApiHandle<String>(obj);
-  PREPARE_FOR_EXECUTION(context, "ToString", String);
+  PREPARE_FOR_EXECUTION(context, Object, ToString, String);
   Local<String> result;
   has_pending_exception =
       !ToLocal<String>(i::Object::ToString(isolate, obj), &result);
@@ -2986,7 +3093,7 @@
 MaybeLocal<String> Value::ToDetailString(Local<Context> context) const {
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   if (obj->IsString()) return ToApiHandle<String>(obj);
-  PREPARE_FOR_EXECUTION(context, "ToDetailString", String);
+  PREPARE_FOR_EXECUTION(context, Object, ToDetailString, String);
   Local<String> result;
   i::Handle<i::Object> args[] = {obj};
   has_pending_exception = !ToLocal<String>(
@@ -3008,7 +3115,7 @@
 MaybeLocal<Object> Value::ToObject(Local<Context> context) const {
   auto obj = Utils::OpenHandle(this);
   if (obj->IsJSReceiver()) return ToApiHandle<Object>(obj);
-  PREPARE_FOR_EXECUTION(context, "ToObject", Object);
+  PREPARE_FOR_EXECUTION(context, Object, ToObject, Object);
   Local<Object> result;
   has_pending_exception =
       !ToLocal<Object>(i::Object::ToObject(isolate, obj), &result);
@@ -3039,7 +3146,7 @@
 MaybeLocal<Number> Value::ToNumber(Local<Context> context) const {
   auto obj = Utils::OpenHandle(this);
   if (obj->IsNumber()) return ToApiHandle<Number>(obj);
-  PREPARE_FOR_EXECUTION(context, "ToNumber", Number);
+  PREPARE_FOR_EXECUTION(context, Object, ToNumber, Number);
   Local<Number> result;
   has_pending_exception = !ToLocal<Number>(i::Object::ToNumber(obj), &result);
   RETURN_ON_FAILED_EXECUTION(Number);
@@ -3055,7 +3162,7 @@
 MaybeLocal<Integer> Value::ToInteger(Local<Context> context) const {
   auto obj = Utils::OpenHandle(this);
   if (obj->IsSmi()) return ToApiHandle<Integer>(obj);
-  PREPARE_FOR_EXECUTION(context, "ToInteger", Integer);
+  PREPARE_FOR_EXECUTION(context, Object, ToInteger, Integer);
   Local<Integer> result;
   has_pending_exception =
       !ToLocal<Integer>(i::Object::ToInteger(isolate, obj), &result);
@@ -3073,7 +3180,7 @@
   auto obj = Utils::OpenHandle(this);
   if (obj->IsSmi()) return ToApiHandle<Int32>(obj);
   Local<Int32> result;
-  PREPARE_FOR_EXECUTION(context, "ToInt32", Int32);
+  PREPARE_FOR_EXECUTION(context, Object, ToInt32, Int32);
   has_pending_exception =
       !ToLocal<Int32>(i::Object::ToInt32(isolate, obj), &result);
   RETURN_ON_FAILED_EXECUTION(Int32);
@@ -3090,7 +3197,7 @@
   auto obj = Utils::OpenHandle(this);
   if (obj->IsSmi()) return ToApiHandle<Uint32>(obj);
   Local<Uint32> result;
-  PREPARE_FOR_EXECUTION(context, "ToUint32", Uint32);
+  PREPARE_FOR_EXECUTION(context, Object, ToUint32, Uint32);
   has_pending_exception =
       !ToLocal<Uint32>(i::Object::ToUint32(isolate, obj), &result);
   RETURN_ON_FAILED_EXECUTION(Uint32);
@@ -3105,62 +3212,55 @@
 
 void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
-  Utils::ApiCheck(isolate != NULL &&
-                  !isolate->IsDead(),
-                  "v8::internal::Internals::CheckInitialized()",
+  Utils::ApiCheck(isolate != NULL && !isolate->IsDead(),
+                  "v8::internal::Internals::CheckInitialized",
                   "Isolate is not initialized or V8 has died");
 }
 
 
 void External::CheckCast(v8::Value* that) {
-  Utils::ApiCheck(Utils::OpenHandle(that)->IsExternal(),
-                  "v8::External::Cast()",
+  Utils::ApiCheck(Utils::OpenHandle(that)->IsExternal(), "v8::External::Cast",
                   "Could not convert to external");
 }
 
 
 void v8::Object::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  Utils::ApiCheck(obj->IsJSReceiver(), "v8::Object::Cast()",
+  Utils::ApiCheck(obj->IsJSReceiver(), "v8::Object::Cast",
                   "Could not convert to object");
 }
 
 
 void v8::Function::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  Utils::ApiCheck(obj->IsCallable(), "v8::Function::Cast()",
+  Utils::ApiCheck(obj->IsCallable(), "v8::Function::Cast",
                   "Could not convert to function");
 }
 
 
 void v8::Boolean::CheckCast(v8::Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  Utils::ApiCheck(obj->IsBoolean(),
-                  "v8::Boolean::Cast()",
+  Utils::ApiCheck(obj->IsBoolean(), "v8::Boolean::Cast",
                   "Could not convert to boolean");
 }
 
 
 void v8::Name::CheckCast(v8::Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  Utils::ApiCheck(obj->IsName(),
-                  "v8::Name::Cast()",
-                  "Could not convert to name");
+  Utils::ApiCheck(obj->IsName(), "v8::Name::Cast", "Could not convert to name");
 }
 
 
 void v8::String::CheckCast(v8::Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  Utils::ApiCheck(obj->IsString(),
-                  "v8::String::Cast()",
+  Utils::ApiCheck(obj->IsString(), "v8::String::Cast",
                   "Could not convert to string");
 }
 
 
 void v8::Symbol::CheckCast(v8::Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  Utils::ApiCheck(obj->IsSymbol(),
-                  "v8::Symbol::Cast()",
+  Utils::ApiCheck(obj->IsSymbol(), "v8::Symbol::Cast",
                   "Could not convert to symbol");
 }
 
@@ -3175,62 +3275,56 @@
 
 void v8::Integer::CheckCast(v8::Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  Utils::ApiCheck(obj->IsNumber(),
-                  "v8::Integer::Cast()",
+  Utils::ApiCheck(obj->IsNumber(), "v8::Integer::Cast",
                   "Could not convert to number");
 }
 
 
 void v8::Int32::CheckCast(v8::Value* that) {
-  Utils::ApiCheck(that->IsInt32(), "v8::Int32::Cast()",
+  Utils::ApiCheck(that->IsInt32(), "v8::Int32::Cast",
                   "Could not convert to 32-bit signed integer");
 }
 
 
 void v8::Uint32::CheckCast(v8::Value* that) {
-  Utils::ApiCheck(that->IsUint32(), "v8::Uint32::Cast()",
+  Utils::ApiCheck(that->IsUint32(), "v8::Uint32::Cast",
                   "Could not convert to 32-bit unsigned integer");
 }
 
 
 void v8::Array::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  Utils::ApiCheck(obj->IsJSArray(),
-                  "v8::Array::Cast()",
+  Utils::ApiCheck(obj->IsJSArray(), "v8::Array::Cast",
                   "Could not convert to array");
 }
 
 
 void v8::Map::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  Utils::ApiCheck(obj->IsJSMap(), "v8::Map::Cast()",
-                  "Could not convert to Map");
+  Utils::ApiCheck(obj->IsJSMap(), "v8::Map::Cast", "Could not convert to Map");
 }
 
 
 void v8::Set::CheckCast(Value* that) {
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
-  Utils::ApiCheck(obj->IsJSSet(), "v8::Set::Cast()",
-                  "Could not convert to Set");
+  Utils::ApiCheck(obj->IsJSSet(), "v8_Set_Cast", "Could not convert to Set");
 }
 
 
 void v8::Promise::CheckCast(Value* that) {
-  Utils::ApiCheck(that->IsPromise(),
-                  "v8::Promise::Cast()",
+  Utils::ApiCheck(that->IsPromise(), "v8::Promise::Cast",
                   "Could not convert to promise");
 }
 
 
 void v8::Promise::Resolver::CheckCast(Value* that) {
-  Utils::ApiCheck(that->IsPromise(),
-                  "v8::Promise::Resolver::Cast()",
+  Utils::ApiCheck(that->IsPromise(), "v8::Promise::Resolver::Cast",
                   "Could not convert to promise resolver");
 }
 
 
 void v8::Proxy::CheckCast(Value* that) {
-  Utils::ApiCheck(that->IsProxy(), "v8::Proxy::Cast()",
+  Utils::ApiCheck(that->IsProxy(), "v8::Proxy::Cast",
                   "Could not convert to proxy");
 }
 
@@ -3367,7 +3461,7 @@
 Maybe<double> Value::NumberValue(Local<Context> context) const {
   auto obj = Utils::OpenHandle(this);
   if (obj->IsNumber()) return Just(obj->Number());
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "NumberValue", double);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, NumberValue, double);
   i::Handle<i::Object> num;
   has_pending_exception = !i::Object::ToNumber(obj).ToHandle(&num);
   RETURN_ON_FAILED_EXECUTION_PRIMITIVE(double);
@@ -3388,7 +3482,7 @@
   if (obj->IsNumber()) {
     return Just(NumberToInt64(*obj));
   }
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "IntegerValue", int64_t);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, IntegerValue, int64_t);
   i::Handle<i::Object> num;
   has_pending_exception = !i::Object::ToInteger(isolate, obj).ToHandle(&num);
   RETURN_ON_FAILED_EXECUTION_PRIMITIVE(int64_t);
@@ -3412,7 +3506,7 @@
 Maybe<int32_t> Value::Int32Value(Local<Context> context) const {
   auto obj = Utils::OpenHandle(this);
   if (obj->IsNumber()) return Just(NumberToInt32(*obj));
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Int32Value", int32_t);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, Int32Value, int32_t);
   i::Handle<i::Object> num;
   has_pending_exception = !i::Object::ToInt32(isolate, obj).ToHandle(&num);
   RETURN_ON_FAILED_EXECUTION_PRIMITIVE(int32_t);
@@ -3431,7 +3525,7 @@
 Maybe<uint32_t> Value::Uint32Value(Local<Context> context) const {
   auto obj = Utils::OpenHandle(this);
   if (obj->IsNumber()) return Just(NumberToUint32(*obj));
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Uint32Value", uint32_t);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, Uint32Value, uint32_t);
   i::Handle<i::Object> num;
   has_pending_exception = !i::Object::ToUint32(isolate, obj).ToHandle(&num);
   RETURN_ON_FAILED_EXECUTION_PRIMITIVE(uint32_t);
@@ -3453,7 +3547,7 @@
     if (i::Smi::cast(*self)->value() >= 0) return Utils::Uint32ToLocal(self);
     return Local<Uint32>();
   }
-  PREPARE_FOR_EXECUTION(context, "ToArrayIndex", Uint32);
+  PREPARE_FOR_EXECUTION(context, Object, ToArrayIndex, Uint32);
   i::Handle<i::Object> string_obj;
   has_pending_exception =
       !i::Object::ToString(isolate, self).ToHandle(&string_obj);
@@ -3519,10 +3613,16 @@
   return self->SameValue(*other);
 }
 
+Local<String> Value::TypeOf(v8::Isolate* external_isolate) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
+  ENTER_V8(isolate);
+  LOG_API(isolate, Value, TypeOf);
+  return Utils::ToLocal(i::Object::TypeOf(isolate, Utils::OpenHandle(this)));
+}
 
 Maybe<bool> v8::Object::Set(v8::Local<v8::Context> context,
                             v8::Local<Value> key, v8::Local<Value> value) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::Set()", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, Set, bool);
   auto self = Utils::OpenHandle(this);
   auto key_obj = Utils::OpenHandle(*key);
   auto value_obj = Utils::OpenHandle(*value);
@@ -3542,7 +3642,7 @@
 
 Maybe<bool> v8::Object::Set(v8::Local<v8::Context> context, uint32_t index,
                             v8::Local<Value> value) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::Set()", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, Set, bool);
   auto self = Utils::OpenHandle(this);
   auto value_obj = Utils::OpenHandle(*value);
   has_pending_exception = i::Object::SetElement(isolate, self, index, value_obj,
@@ -3561,8 +3661,7 @@
 Maybe<bool> v8::Object::CreateDataProperty(v8::Local<v8::Context> context,
                                            v8::Local<Name> key,
                                            v8::Local<Value> value) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::CreateDataProperty()",
-                                  bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, CreateDataProperty, bool);
   i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
   i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
@@ -3580,8 +3679,7 @@
 Maybe<bool> v8::Object::CreateDataProperty(v8::Local<v8::Context> context,
                                            uint32_t index,
                                            v8::Local<Value> value) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::CreateDataProperty()",
-                                  bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, CreateDataProperty, bool);
   i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
 
@@ -3598,8 +3696,7 @@
                                           v8::Local<Name> key,
                                           v8::Local<Value> value,
                                           v8::PropertyAttribute attributes) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::DefineOwnProperty()",
-                                  bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, DefineOwnProperty, bool);
   i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
   i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
@@ -3642,7 +3739,7 @@
 Maybe<bool> v8::Object::ForceSet(v8::Local<v8::Context> context,
                                  v8::Local<Value> key, v8::Local<Value> value,
                                  v8::PropertyAttribute attribs) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::ForceSet()", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, ForceSet, bool);
   auto self = i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
   auto key_obj = Utils::OpenHandle(*key);
   auto value_obj = Utils::OpenHandle(*value);
@@ -3658,9 +3755,8 @@
 bool v8::Object::ForceSet(v8::Local<Value> key, v8::Local<Value> value,
                           v8::PropertyAttribute attribs) {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  PREPARE_FOR_EXECUTION_GENERIC(isolate, Local<Context>(),
-                                "v8::Object::ForceSet", false, i::HandleScope,
-                                false);
+  PREPARE_FOR_EXECUTION_GENERIC(isolate, Local<Context>(), Object, ForceSet,
+                                false, i::HandleScope, false);
   i::Handle<i::JSObject> self =
       i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
@@ -3676,7 +3772,7 @@
 
 Maybe<bool> v8::Object::SetPrivate(Local<Context> context, Local<Private> key,
                                    Local<Value> value) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::SetPrivate()", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, SetPrivate, bool);
   auto self = Utils::OpenHandle(this);
   auto key_obj = Utils::OpenHandle(reinterpret_cast<Name*>(*key));
   auto value_obj = Utils::OpenHandle(*value);
@@ -3702,7 +3798,7 @@
 
 MaybeLocal<Value> v8::Object::Get(Local<v8::Context> context,
                                   Local<Value> key) {
-  PREPARE_FOR_EXECUTION(context, "v8::Object::Get()", Value);
+  PREPARE_FOR_EXECUTION(context, Object, Get, Value);
   auto self = Utils::OpenHandle(this);
   auto key_obj = Utils::OpenHandle(*key);
   i::Handle<i::Object> result;
@@ -3720,7 +3816,7 @@
 
 
 MaybeLocal<Value> v8::Object::Get(Local<Context> context, uint32_t index) {
-  PREPARE_FOR_EXECUTION(context, "v8::Object::Get()", Value);
+  PREPARE_FOR_EXECUTION(context, Object, Get, Value);
   auto self = Utils::OpenHandle(this);
   i::Handle<i::Object> result;
   has_pending_exception =
@@ -3744,8 +3840,8 @@
 
 Maybe<PropertyAttribute> v8::Object::GetPropertyAttributes(
     Local<Context> context, Local<Value> key) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(
-      context, "v8::Object::GetPropertyAttributes()", PropertyAttribute);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, GetPropertyAttributes,
+                                  PropertyAttribute);
   auto self = Utils::OpenHandle(this);
   auto key_obj = Utils::OpenHandle(*key);
   if (!key_obj->IsName()) {
@@ -3773,8 +3869,7 @@
 
 MaybeLocal<Value> v8::Object::GetOwnPropertyDescriptor(Local<Context> context,
                                                        Local<String> key) {
-  PREPARE_FOR_EXECUTION(context, "v8::Object::GetOwnPropertyDescriptor()",
-                        Value);
+  PREPARE_FOR_EXECUTION(context, Object, GetOwnPropertyDescriptor, Value);
   i::Handle<i::JSReceiver> obj = Utils::OpenHandle(this);
   i::Handle<i::String> key_name = Utils::OpenHandle(*key);
 
@@ -3806,7 +3901,7 @@
 
 Maybe<bool> v8::Object::SetPrototype(Local<Context> context,
                                      Local<Value> value) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::SetPrototype()", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, SetPrototype, bool);
   auto self = Utils::OpenHandle(this);
   auto value_obj = Utils::OpenHandle(*value);
   // We do not allow exceptions thrown while setting the prototype
@@ -3830,27 +3925,38 @@
     v8::Local<FunctionTemplate> tmpl) {
   auto isolate = Utils::OpenHandle(this)->GetIsolate();
   i::PrototypeIterator iter(isolate, *Utils::OpenHandle(this),
-                            i::PrototypeIterator::START_AT_RECEIVER);
+                            i::kStartAtReceiver);
   auto tmpl_info = *Utils::OpenHandle(*tmpl);
-  while (!tmpl_info->IsTemplateFor(iter.GetCurrent())) {
+  while (!tmpl_info->IsTemplateFor(iter.GetCurrent<i::JSObject>())) {
     iter.Advance();
-    if (iter.IsAtEnd()) {
-      return Local<Object>();
-    }
+    if (iter.IsAtEnd()) return Local<Object>();
+    if (!iter.GetCurrent()->IsJSObject()) return Local<Object>();
   }
   // IsTemplateFor() ensures that iter.GetCurrent() can't be a Proxy here.
   return Utils::ToLocal(i::handle(iter.GetCurrent<i::JSObject>(), isolate));
 }
 
-
 MaybeLocal<Array> v8::Object::GetPropertyNames(Local<Context> context) {
-  PREPARE_FOR_EXECUTION(context, "v8::Object::GetPropertyNames()", Array);
+  return GetPropertyNames(
+      context, v8::KeyCollectionMode::kIncludePrototypes,
+      static_cast<v8::PropertyFilter>(ONLY_ENUMERABLE | SKIP_SYMBOLS),
+      v8::IndexFilter::kIncludeIndices);
+}
+
+MaybeLocal<Array> v8::Object::GetPropertyNames(Local<Context> context,
+                                               KeyCollectionMode mode,
+                                               PropertyFilter property_filter,
+                                               IndexFilter index_filter) {
+  PREPARE_FOR_EXECUTION(context, Object, GetPropertyNames, Array);
   auto self = Utils::OpenHandle(this);
   i::Handle<i::FixedArray> value;
-  has_pending_exception =
-      !i::JSReceiver::GetKeys(self, i::INCLUDE_PROTOS, i::ENUMERABLE_STRINGS)
-           .ToHandle(&value);
+  i::KeyAccumulator accumulator(
+      isolate, static_cast<i::KeyCollectionMode>(mode),
+      static_cast<i::PropertyFilter>(property_filter));
+  accumulator.set_skip_indices(index_filter == IndexFilter::kSkipIndices);
+  has_pending_exception = accumulator.CollectKeys(self, self).IsNothing();
   RETURN_ON_FAILED_EXECUTION(Array);
+  value = accumulator.GetKeys(i::GetKeysConversion::kKeepNumbers);
   DCHECK(self->map()->EnumLength() == i::kInvalidEnumCacheSentinel ||
          self->map()->EnumLength() == 0 ||
          self->map()->instance_descriptors()->GetEnumCache() != *value);
@@ -3864,31 +3970,24 @@
   RETURN_TO_LOCAL_UNCHECKED(GetPropertyNames(context), Array);
 }
 
-
 MaybeLocal<Array> v8::Object::GetOwnPropertyNames(Local<Context> context) {
-  PREPARE_FOR_EXECUTION(context, "v8::Object::GetOwnPropertyNames()", Array);
-  auto self = Utils::OpenHandle(this);
-  i::Handle<i::FixedArray> value;
-  has_pending_exception =
-      !i::JSReceiver::GetKeys(self, i::OWN_ONLY, i::ENUMERABLE_STRINGS)
-           .ToHandle(&value);
-  RETURN_ON_FAILED_EXECUTION(Array);
-  DCHECK(self->map()->EnumLength() == i::kInvalidEnumCacheSentinel ||
-         self->map()->EnumLength() == 0 ||
-         self->map()->instance_descriptors()->GetEnumCache() != *value);
-  auto result = isolate->factory()->NewJSArrayWithElements(value);
-  RETURN_ESCAPED(Utils::ToLocal(result));
+  return GetOwnPropertyNames(
+      context, static_cast<v8::PropertyFilter>(ONLY_ENUMERABLE | SKIP_SYMBOLS));
 }
 
-
 Local<Array> v8::Object::GetOwnPropertyNames() {
   auto context = ContextFromHeapObject(Utils::OpenHandle(this));
   RETURN_TO_LOCAL_UNCHECKED(GetOwnPropertyNames(context), Array);
 }
 
+MaybeLocal<Array> v8::Object::GetOwnPropertyNames(Local<Context> context,
+                                                  PropertyFilter filter) {
+  return GetPropertyNames(context, KeyCollectionMode::kOwnOnly, filter,
+                          v8::IndexFilter::kIncludeIndices);
+}
 
 MaybeLocal<String> v8::Object::ObjectProtoToString(Local<Context> context) {
-  PREPARE_FOR_EXECUTION(context, "v8::Object::ObjectProtoToString", String);
+  PREPARE_FOR_EXECUTION(context, Object, ObjectProtoToString, String);
   auto obj = Utils::OpenHandle(this);
   Local<String> result;
   has_pending_exception =
@@ -3912,8 +4011,7 @@
 
 Maybe<bool> v8::Object::SetIntegrityLevel(Local<Context> context,
                                           IntegrityLevel level) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::SetIntegrityLevel()",
-                                  bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, SetIntegrityLevel, bool);
   auto self = Utils::OpenHandle(this);
   i::JSReceiver::IntegrityLevel i_level =
       level == IntegrityLevel::kFrozen ? i::FROZEN : i::SEALED;
@@ -3925,7 +4023,7 @@
 }
 
 Maybe<bool> v8::Object::Delete(Local<Context> context, Local<Value> key) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::Delete()", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, Delete, bool);
   auto self = Utils::OpenHandle(this);
   auto key_obj = Utils::OpenHandle(*key);
   Maybe<bool> result =
@@ -3949,7 +4047,7 @@
 
 
 Maybe<bool> v8::Object::Has(Local<Context> context, Local<Value> key) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::Get()", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, Get, bool);
   auto self = Utils::OpenHandle(this);
   auto key_obj = Utils::OpenHandle(*key);
   Maybe<bool> maybe = Nothing<bool>();
@@ -3982,8 +4080,7 @@
 
 
 Maybe<bool> v8::Object::Delete(Local<Context> context, uint32_t index) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::DeleteProperty()",
-                                  bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, DeleteProperty, bool);
   auto self = Utils::OpenHandle(this);
   Maybe<bool> result = i::JSReceiver::DeleteElement(self, index);
   has_pending_exception = result.IsNothing();
@@ -3999,7 +4096,7 @@
 
 
 Maybe<bool> v8::Object::Has(Local<Context> context, uint32_t index) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::Get()", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, Get, bool);
   auto self = Utils::OpenHandle(this);
   auto maybe = i::JSReceiver::HasElement(self, index);
   has_pending_exception = maybe.IsNothing();
@@ -4020,7 +4117,7 @@
                                      Setter setter, Data data,
                                      AccessControl settings,
                                      PropertyAttribute attributes) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::SetAccessor()", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, SetAccessor, bool);
   if (!Utils::OpenHandle(self)->IsJSObject()) return Just(false);
   i::Handle<i::JSObject> obj =
       i::Handle<i::JSObject>::cast(Utils::OpenHandle(self));
@@ -4033,7 +4130,7 @@
   has_pending_exception =
       !i::JSObject::SetAccessor(obj, info).ToHandle(&result);
   RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
-  if (result->IsUndefined()) return Nothing<bool>();
+  if (result->IsUndefined(obj->GetIsolate())) return Nothing<bool>();
   if (fast) {
     i::JSObject::MigrateSlowToFast(obj, 0, "APISetAccessor");
   }
@@ -4092,8 +4189,7 @@
 
 Maybe<bool> v8::Object::HasOwnProperty(Local<Context> context,
                                        Local<Name> key) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::HasOwnProperty()",
-                                  bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, HasOwnProperty, bool);
   auto self = Utils::OpenHandle(this);
   auto key_val = Utils::OpenHandle(*key);
   auto result = i::JSReceiver::HasOwnProperty(self, key_val);
@@ -4102,6 +4198,14 @@
   return result;
 }
 
+Maybe<bool> v8::Object::HasOwnProperty(Local<Context> context, uint32_t index) {
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, HasOwnProperty, bool);
+  auto self = Utils::OpenHandle(this);
+  auto result = i::JSReceiver::HasOwnProperty(self, index);
+  has_pending_exception = result.IsNothing();
+  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
+  return result;
+}
 
 bool v8::Object::HasOwnProperty(Local<String> key) {
   auto context = ContextFromHeapObject(Utils::OpenHandle(this));
@@ -4111,8 +4215,7 @@
 
 Maybe<bool> v8::Object::HasRealNamedProperty(Local<Context> context,
                                              Local<Name> key) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::HasRealNamedProperty()",
-                                  bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, HasRealNamedProperty, bool);
   auto self = Utils::OpenHandle(this);
   if (!self->IsJSObject()) return Just(false);
   auto key_val = Utils::OpenHandle(*key);
@@ -4132,8 +4235,8 @@
 
 Maybe<bool> v8::Object::HasRealIndexedProperty(Local<Context> context,
                                                uint32_t index) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context,
-                                  "v8::Object::HasRealIndexedProperty()", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, HasRealIndexedProperty,
+                                  bool);
   auto self = Utils::OpenHandle(this);
   if (!self->IsJSObject()) return Just(false);
   auto result = i::JSObject::HasRealElementProperty(
@@ -4152,8 +4255,8 @@
 
 Maybe<bool> v8::Object::HasRealNamedCallbackProperty(Local<Context> context,
                                                      Local<Name> key) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(
-      context, "v8::Object::HasRealNamedCallbackProperty()", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, HasRealNamedCallbackProperty,
+                                  bool);
   auto self = Utils::OpenHandle(this);
   if (!self->IsJSObject()) return Just(false);
   auto key_val = Utils::OpenHandle(*key);
@@ -4187,8 +4290,8 @@
 
 MaybeLocal<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
     Local<Context> context, Local<Name> key) {
-  PREPARE_FOR_EXECUTION(
-      context, "v8::Object::GetRealNamedPropertyInPrototypeChain()", Value);
+  PREPARE_FOR_EXECUTION(context, Object, GetRealNamedPropertyInPrototypeChain,
+                        Value);
   i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
   if (!self->IsJSObject()) return MaybeLocal<Value>();
   i::Handle<i::Name> key_obj = Utils::OpenHandle(*key);
@@ -4219,7 +4322,7 @@
 v8::Object::GetRealNamedPropertyAttributesInPrototypeChain(
     Local<Context> context, Local<Name> key) {
   PREPARE_FOR_EXECUTION_PRIMITIVE(
-      context, "v8::Object::GetRealNamedPropertyAttributesInPrototypeChain()",
+      context, Object, GetRealNamedPropertyAttributesInPrototypeChain,
       PropertyAttribute);
   i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
   if (!self->IsJSObject()) return Nothing<PropertyAttribute>();
@@ -4249,7 +4352,7 @@
 
 MaybeLocal<Value> v8::Object::GetRealNamedProperty(Local<Context> context,
                                                    Local<Name> key) {
-  PREPARE_FOR_EXECUTION(context, "v8::Object::GetRealNamedProperty()", Value);
+  PREPARE_FOR_EXECUTION(context, Object, GetRealNamedProperty, Value);
   auto self = Utils::OpenHandle(this);
   auto key_obj = Utils::OpenHandle(*key);
   i::LookupIterator it = i::LookupIterator::PropertyOrElement(
@@ -4272,8 +4375,7 @@
 Maybe<PropertyAttribute> v8::Object::GetRealNamedPropertyAttributes(
     Local<Context> context, Local<Name> key) {
   PREPARE_FOR_EXECUTION_PRIMITIVE(
-      context, "v8::Object::GetRealNamedPropertyAttributes()",
-      PropertyAttribute);
+      context, Object, GetRealNamedPropertyAttributes, PropertyAttribute);
   auto self = Utils::OpenHandle(this);
   auto key_obj = Utils::OpenHandle(*key);
   i::LookupIterator it = i::LookupIterator::PropertyOrElement(
@@ -4318,60 +4420,7 @@
   auto isolate = Utils::OpenHandle(this)->GetIsolate();
   i::HandleScope scope(isolate);
   auto self = Utils::OpenHandle(this);
-  return i::JSReceiver::GetOrCreateIdentityHash(self)->value();
-}
-
-
-bool v8::Object::SetHiddenValue(v8::Local<v8::String> key,
-                                v8::Local<v8::Value> value) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
-  if (!self->IsJSObject()) return false;
-  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
-  i::Handle<i::String> key_string =
-      isolate->factory()->InternalizeString(key_obj);
-  if (value.IsEmpty()) {
-    i::JSObject::DeleteHiddenProperty(i::Handle<i::JSObject>::cast(self),
-                                      key_string);
-    return true;
-  }
-  i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
-  i::Handle<i::Object> result = i::JSObject::SetHiddenProperty(
-      i::Handle<i::JSObject>::cast(self), key_string, value_obj);
-  return *result == *self;
-}
-
-
-v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Local<v8::String> key) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ENTER_V8(isolate);
-  i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
-  if (!self->IsJSObject()) return v8::Local<v8::Value>();
-  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
-  i::Handle<i::String> key_string =
-      isolate->factory()->InternalizeString(key_obj);
-  i::Handle<i::Object> result(
-      i::Handle<i::JSObject>::cast(self)->GetHiddenProperty(key_string),
-      isolate);
-  if (result->IsTheHole()) return v8::Local<v8::Value>();
-  return Utils::ToLocal(result);
-}
-
-
-bool v8::Object::DeleteHiddenValue(v8::Local<v8::String> key) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
-  i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
-  if (!self->IsJSObject()) return false;
-  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
-  i::Handle<i::String> key_string =
-      isolate->factory()->InternalizeString(key_obj);
-  i::JSObject::DeleteHiddenProperty(i::Handle<i::JSObject>::cast(self),
-                                    key_string);
-  return true;
+  return i::JSReceiver::GetOrCreateIdentityHash(isolate, self)->value();
 }
 
 
@@ -4380,12 +4429,16 @@
   return self->IsCallable();
 }
 
+bool v8::Object::IsConstructor() {
+  auto self = Utils::OpenHandle(this);
+  return self->IsConstructor();
+}
 
 MaybeLocal<Value> Object::CallAsFunction(Local<Context> context,
                                          Local<Value> recv, int argc,
                                          Local<Value> argv[]) {
-  PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, "v8::Object::CallAsFunction()",
-                                      Value);
+  PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, Object, CallAsFunction, Value);
+  i::HistogramTimerScope execute_timer(isolate->counters()->execute(), true);
   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
   TRACE_EVENT0("v8", "V8.Execute");
   auto self = Utils::OpenHandle(this);
@@ -4411,8 +4464,9 @@
 
 MaybeLocal<Value> Object::CallAsConstructor(Local<Context> context, int argc,
                                             Local<Value> argv[]) {
-  PREPARE_FOR_EXECUTION_WITH_CALLBACK(context,
-                                      "v8::Object::CallAsConstructor()", Value);
+  PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, Object, CallAsConstructor,
+                                      Value);
+  i::HistogramTimerScope execute_timer(isolate->counters()->execute(), true);
   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
   TRACE_EVENT0("v8", "V8.Execute");
   auto self = Utils::OpenHandle(this);
@@ -4433,22 +4487,23 @@
   RETURN_TO_LOCAL_UNCHECKED(CallAsConstructor(context, argc, argv_cast), Value);
 }
 
-
 MaybeLocal<Function> Function::New(Local<Context> context,
                                    FunctionCallback callback, Local<Value> data,
-                                   int length) {
+                                   int length, ConstructorBehavior behavior) {
   i::Isolate* isolate = Utils::OpenHandle(*context)->GetIsolate();
-  LOG_API(isolate, "Function::New");
+  LOG_API(isolate, Function, New);
   ENTER_V8(isolate);
-  return FunctionTemplateNew(isolate, callback, nullptr, data,
-                             Local<Signature>(), length, true)
-      ->GetFunction(context);
+  auto templ = FunctionTemplateNew(isolate, callback, nullptr, data,
+                                   Local<Signature>(), length, true);
+  if (behavior == ConstructorBehavior::kThrow) templ->RemovePrototype();
+  return templ->GetFunction(context);
 }
 
 
 Local<Function> Function::New(Isolate* v8_isolate, FunctionCallback callback,
                               Local<Value> data, int length) {
-  return Function::New(v8_isolate->GetCurrentContext(), callback, data, length)
+  return Function::New(v8_isolate->GetCurrentContext(), callback, data, length,
+                       ConstructorBehavior::kAllow)
       .FromMaybe(Local<Function>());
 }
 
@@ -4461,8 +4516,8 @@
 
 MaybeLocal<Object> Function::NewInstance(Local<Context> context, int argc,
                                          v8::Local<v8::Value> argv[]) const {
-  PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, "v8::Function::NewInstance()",
-                                      Object);
+  PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, Function, NewInstance, Object);
+  i::HistogramTimerScope execute_timer(isolate->counters()->execute(), true);
   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
   TRACE_EVENT0("v8", "V8.Execute");
   auto self = Utils::OpenHandle(this);
@@ -4486,7 +4541,8 @@
 MaybeLocal<v8::Value> Function::Call(Local<Context> context,
                                      v8::Local<v8::Value> recv, int argc,
                                      v8::Local<v8::Value> argv[]) {
-  PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, "v8::Function::Call()", Value);
+  PREPARE_FOR_EXECUTION_WITH_CALLBACK(context, Function, Call, Value);
+  i::HistogramTimerScope execute_timer(isolate->counters()->execute(), true);
   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
   TRACE_EVENT0("v8", "V8.Execute");
   auto self = Utils::OpenHandle(this);
@@ -4518,16 +4574,20 @@
 
 Local<Value> Function::GetName() const {
   auto self = Utils::OpenHandle(this);
+  i::Isolate* isolate = self->GetIsolate();
   if (self->IsJSBoundFunction()) {
     auto func = i::Handle<i::JSBoundFunction>::cast(self);
-    return Utils::ToLocal(handle(func->name(), func->GetIsolate()));
+    i::Handle<i::Object> name;
+    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, name,
+                                     i::JSBoundFunction::GetName(isolate, func),
+                                     Local<Value>());
+    return Utils::ToLocal(name);
   }
   if (self->IsJSFunction()) {
     auto func = i::Handle<i::JSFunction>::cast(self);
-    return Utils::ToLocal(handle(func->shared()->name(), func->GetIsolate()));
+    return Utils::ToLocal(handle(func->shared()->name(), isolate));
   }
-  return ToApiHandle<Primitive>(
-      self->GetIsolate()->factory()->undefined_value());
+  return ToApiHandle<Primitive>(isolate->factory()->undefined_value());
 }
 
 
@@ -5195,7 +5255,7 @@
                       int* nchars_ref,
                       int options) const {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  LOG_API(isolate, "String::WriteUtf8");
+  LOG_API(isolate, String, WriteUtf8);
   ENTER_V8(isolate);
   i::Handle<i::String> str = Utils::OpenHandle(this);
   if (options & HINT_MANY_WRITES_EXPECTED) {
@@ -5248,7 +5308,7 @@
                               int length,
                               int options) {
   i::Isolate* isolate = Utils::OpenHandle(string)->GetIsolate();
-  LOG_API(isolate, "String::Write");
+  LOG_API(isolate, String, Write);
   ENTER_V8(isolate);
   DCHECK(start >= 0 && length >= -1);
   i::Handle<i::String> str = Utils::OpenHandle(string);
@@ -5369,7 +5429,7 @@
 
 bool Boolean::Value() const {
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
-  return obj->IsTrue();
+  return obj->IsTrue(i::HeapObject::cast(*obj)->GetIsolate());
 }
 
 
@@ -5460,7 +5520,10 @@
 
 static void* ExternalValue(i::Object* obj) {
   // Obscure semantics for undefined, but somehow checked in our unit tests...
-  if (obj->IsUndefined()) return NULL;
+  if (!obj->IsSmi() &&
+      obj->IsUndefined(i::HeapObject::cast(obj)->GetIsolate())) {
+    return NULL;
+  }
   i::Object* foreign = i::JSObject::cast(obj)->GetInternalField(0);
   return i::Foreign::cast(foreign)->foreign_address();
 }
@@ -5530,11 +5593,17 @@
       object_count_(0),
       object_size_(0) {}
 
+HeapCodeStatistics::HeapCodeStatistics()
+    : code_and_metadata_size_(0), bytecode_and_metadata_size_(0) {}
 
 bool v8::V8::InitializeICU(const char* icu_data_file) {
   return i::InitializeICU(icu_data_file);
 }
 
+bool v8::V8::InitializeICUDefaultLocation(const char* exec_path,
+                                          const char* icu_data_file) {
+  return i::InitializeICUDefaultLocation(exec_path, icu_data_file);
+}
 
 void v8::V8::InitializeExternalStartupData(const char* directory_path) {
   i::InitializeExternalStartupData(directory_path);
@@ -5551,11 +5620,10 @@
   return i::Version::GetVersion();
 }
 
-
 static i::Handle<i::Context> CreateEnvironment(
     i::Isolate* isolate, v8::ExtensionConfiguration* extensions,
     v8::Local<ObjectTemplate> global_template,
-    v8::Local<Value> maybe_global_proxy) {
+    v8::Local<Value> maybe_global_proxy, size_t context_snapshot_index) {
   i::Handle<i::Context> env;
 
   // Enter V8 via an ENTER_V8 scope.
@@ -5582,7 +5650,7 @@
       // Migrate security handlers from global_template to
       // proxy_template.  Temporarily removing access check
       // information from the global template.
-      if (!global_constructor->access_check_info()->IsUndefined()) {
+      if (!global_constructor->access_check_info()->IsUndefined(isolate)) {
         proxy_constructor->set_access_check_info(
             global_constructor->access_check_info());
         proxy_constructor->set_needs_access_check(
@@ -5600,7 +5668,7 @@
     }
     // Create the environment.
     env = isolate->bootstrapper()->CreateEnvironment(
-        maybe_proxy, proxy_template, extensions);
+        maybe_proxy, proxy_template, extensions, context_snapshot_index);
 
     // Restore the access check info on the global template.
     if (!global_template.IsEmpty()) {
@@ -5620,14 +5688,16 @@
 Local<Context> v8::Context::New(v8::Isolate* external_isolate,
                                 v8::ExtensionConfiguration* extensions,
                                 v8::Local<ObjectTemplate> global_template,
-                                v8::Local<Value> global_object) {
+                                v8::Local<Value> global_object,
+                                size_t context_snapshot_index) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
-  LOG_API(isolate, "Context::New");
+  LOG_API(isolate, Context, New);
   i::HandleScope scope(isolate);
   ExtensionConfiguration no_extensions;
   if (extensions == NULL) extensions = &no_extensions;
   i::Handle<i::Context> env =
-      CreateEnvironment(isolate, extensions, global_template, global_object);
+      CreateEnvironment(isolate, extensions, global_template, global_object,
+                        context_snapshot_index);
   if (env.is_null()) {
     if (isolate->has_pending_exception()) {
       isolate->OptionalRescheduleException(true);
@@ -5707,7 +5777,8 @@
 
 bool Context::IsCodeGenerationFromStringsAllowed() {
   i::Handle<i::Context> context = Utils::OpenHandle(this);
-  return !context->allow_code_gen_from_strings()->IsFalse();
+  return !context->allow_code_gen_from_strings()->IsFalse(
+      context->GetIsolate());
 }
 
 
@@ -5725,7 +5796,7 @@
 
 
 MaybeLocal<v8::Object> ObjectTemplate::NewInstance(Local<Context> context) {
-  PREPARE_FOR_EXECUTION(context, "v8::ObjectTemplate::NewInstance()", Object);
+  PREPARE_FOR_EXECUTION(context, ObjectTemplate, NewInstance, Object);
   auto self = Utils::OpenHandle(this);
   Local<Object> result;
   has_pending_exception =
@@ -5742,8 +5813,7 @@
 
 
 MaybeLocal<v8::Function> FunctionTemplate::GetFunction(Local<Context> context) {
-  PREPARE_FOR_EXECUTION(context, "v8::FunctionTemplate::GetFunction()",
-                        Function);
+  PREPARE_FOR_EXECUTION(context, FunctionTemplate, GetFunction, Function);
   auto self = Utils::OpenHandle(this);
   Local<Function> result;
   has_pending_exception =
@@ -5762,14 +5832,14 @@
 bool FunctionTemplate::HasInstance(v8::Local<v8::Value> value) {
   auto self = Utils::OpenHandle(this);
   auto obj = Utils::OpenHandle(*value);
-  return self->IsTemplateFor(*obj);
+  return obj->IsJSObject() && self->IsTemplateFor(i::JSObject::cast(*obj));
 }
 
 
 Local<External> v8::External::New(Isolate* isolate, void* value) {
   STATIC_ASSERT(sizeof(value) == sizeof(i::Address));
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "External::New");
+  LOG_API(i_isolate, External, New);
   ENTER_V8(i_isolate);
   i::Handle<i::JSObject> external = i_isolate->factory()->NewExternal(value);
   return Utils::ExternalToLocal(external);
@@ -5837,42 +5907,42 @@
 
 STATIC_ASSERT(v8::String::kMaxLength == i::String::kMaxLength);
 
-
-template <typename Char>
-inline MaybeLocal<String> NewString(Isolate* v8_isolate, const char* location,
-                                    const char* env, const Char* data,
-                                    v8::NewStringType type, int length) {
-  i::Isolate* isolate = reinterpret_cast<internal::Isolate*>(v8_isolate);
-  if (length == 0) return String::Empty(v8_isolate);
-  // TODO(dcarney): throw a context free exception.
-  if (length > i::String::kMaxLength) return MaybeLocal<String>();
-  ENTER_V8(isolate);
-  LOG_API(isolate, env);
-  if (length < 0) length = StringLength(data);
-  i::Handle<i::String> result =
-      NewString(isolate->factory(), type, i::Vector<const Char>(data, length))
-          .ToHandleChecked();
-  return Utils::ToLocal(result);
-}
-
 }  // anonymous namespace
 
+// TODO(dcarney): throw a context free exception.
+#define NEW_STRING(isolate, class_name, function_name, Char, data, type,   \
+                   length)                                                 \
+  MaybeLocal<String> result;                                               \
+  if (length == 0) {                                                       \
+    result = String::Empty(isolate);                                       \
+  } else if (length > i::String::kMaxLength) {                             \
+    result = MaybeLocal<String>();                                         \
+  } else {                                                                 \
+    i::Isolate* i_isolate = reinterpret_cast<internal::Isolate*>(isolate); \
+    ENTER_V8(i_isolate);                                                   \
+    LOG_API(i_isolate, class_name, function_name);                         \
+    if (length < 0) length = StringLength(data);                           \
+    i::Handle<i::String> handle_result =                                   \
+        NewString(i_isolate->factory(), type,                              \
+                  i::Vector<const Char>(data, length))                     \
+            .ToHandleChecked();                                            \
+    result = Utils::ToLocal(handle_result);                                \
+  }
 
 Local<String> String::NewFromUtf8(Isolate* isolate,
                                   const char* data,
                                   NewStringType type,
                                   int length) {
-  RETURN_TO_LOCAL_UNCHECKED(
-      NewString(isolate, "v8::String::NewFromUtf8()", "String::NewFromUtf8",
-                data, static_cast<v8::NewStringType>(type), length),
-      String);
+  NEW_STRING(isolate, String, NewFromUtf8, char, data,
+             static_cast<v8::NewStringType>(type), length);
+  RETURN_TO_LOCAL_UNCHECKED(result, String);
 }
 
 
 MaybeLocal<String> String::NewFromUtf8(Isolate* isolate, const char* data,
                                        v8::NewStringType type, int length) {
-  return NewString(isolate, "v8::String::NewFromUtf8()", "String::NewFromUtf8",
-                   data, type, length);
+  NEW_STRING(isolate, String, NewFromUtf8, char, data, type, length);
+  return result;
 }
 
 
@@ -5880,18 +5950,16 @@
                                      const uint8_t* data,
                                      NewStringType type,
                                      int length) {
-  RETURN_TO_LOCAL_UNCHECKED(
-      NewString(isolate, "v8::String::NewFromOneByte()",
-                "String::NewFromOneByte", data,
-                static_cast<v8::NewStringType>(type), length),
-      String);
+  NEW_STRING(isolate, String, NewFromOneByte, uint8_t, data,
+             static_cast<v8::NewStringType>(type), length);
+  RETURN_TO_LOCAL_UNCHECKED(result, String);
 }
 
 
 MaybeLocal<String> String::NewFromOneByte(Isolate* isolate, const uint8_t* data,
                                           v8::NewStringType type, int length) {
-  return NewString(isolate, "v8::String::NewFromOneByte()",
-                   "String::NewFromOneByte", data, type, length);
+  NEW_STRING(isolate, String, NewFromOneByte, uint8_t, data, type, length);
+  return result;
 }
 
 
@@ -5899,19 +5967,17 @@
                                      const uint16_t* data,
                                      NewStringType type,
                                      int length) {
-  RETURN_TO_LOCAL_UNCHECKED(
-      NewString(isolate, "v8::String::NewFromTwoByte()",
-                "String::NewFromTwoByte", data,
-                static_cast<v8::NewStringType>(type), length),
-      String);
+  NEW_STRING(isolate, String, NewFromTwoByte, uint16_t, data,
+             static_cast<v8::NewStringType>(type), length);
+  RETURN_TO_LOCAL_UNCHECKED(result, String);
 }
 
 
 MaybeLocal<String> String::NewFromTwoByte(Isolate* isolate,
                                           const uint16_t* data,
                                           v8::NewStringType type, int length) {
-  return NewString(isolate, "v8::String::NewFromTwoByte()",
-                   "String::NewFromTwoByte", data, type, length);
+  NEW_STRING(isolate, String, NewFromTwoByte, uint16_t, data, type, length);
+  return result;
 }
 
 
@@ -5919,7 +5985,7 @@
   i::Handle<i::String> left_string = Utils::OpenHandle(*left);
   i::Isolate* isolate = left_string->GetIsolate();
   ENTER_V8(isolate);
-  LOG_API(isolate, "v8::String::Concat");
+  LOG_API(isolate, String, Concat);
   i::Handle<i::String> right_string = Utils::OpenHandle(*right);
   // If we are steering towards a range error, do not wait for the error to be
   // thrown, and return the null handle instead.
@@ -5941,7 +6007,7 @@
   }
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   ENTER_V8(i_isolate);
-  LOG_API(i_isolate, "String::NewExternalTwoByte");
+  LOG_API(i_isolate, String, NewExternalTwoByte);
   i::Handle<i::String> string = i_isolate->factory()
                                     ->NewExternalStringFromTwoByte(resource)
                                     .ToHandleChecked();
@@ -5965,7 +6031,7 @@
   }
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   ENTER_V8(i_isolate);
-  LOG_API(i_isolate, "String::NewExternalOneByte");
+  LOG_API(i_isolate, String, NewExternalOneByte);
   i::Handle<i::String> string = i_isolate->factory()
                                     ->NewExternalStringFromOneByte(resource)
                                     .ToHandleChecked();
@@ -6029,14 +6095,11 @@
 
 bool v8::String::CanMakeExternal() {
   i::Handle<i::String> obj = Utils::OpenHandle(this);
-  i::Isolate* isolate = obj->GetIsolate();
+  if (obj->IsExternalString()) return false;
 
   // Old space strings should be externalized.
-  if (!isolate->heap()->new_space()->Contains(*obj)) return true;
-  int size = obj->Size();  // Byte size of the original string.
-  if (size <= i::ExternalString::kShortSize) return false;
-  i::StringShape shape(*obj);
-  return !shape.IsExternal();
+  i::Isolate* isolate = obj->GetIsolate();
+  return !isolate->heap()->new_space()->Contains(*obj);
 }
 
 
@@ -6048,7 +6111,7 @@
 
 Local<v8::Object> v8::Object::New(Isolate* isolate) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "Object::New");
+  LOG_API(i_isolate, Object, New);
   ENTER_V8(i_isolate);
   i::Handle<i::JSObject> obj =
       i_isolate->factory()->NewJSObject(i_isolate->object_function());
@@ -6058,7 +6121,7 @@
 
 Local<v8::Value> v8::NumberObject::New(Isolate* isolate, double value) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "NumberObject::New");
+  LOG_API(i_isolate, NumberObject, New);
   ENTER_V8(i_isolate);
   i::Handle<i::Object> number = i_isolate->factory()->NewNumber(value);
   i::Handle<i::Object> obj =
@@ -6071,14 +6134,14 @@
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
   i::Isolate* isolate = jsvalue->GetIsolate();
-  LOG_API(isolate, "NumberObject::NumberValue");
+  LOG_API(isolate, NumberObject, NumberValue);
   return jsvalue->value()->Number();
 }
 
 
 Local<v8::Value> v8::BooleanObject::New(Isolate* isolate, bool value) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "BooleanObject::New");
+  LOG_API(i_isolate, BooleanObject, New);
   ENTER_V8(i_isolate);
   i::Handle<i::Object> boolean(value ? i_isolate->heap()->true_value()
                                      : i_isolate->heap()->false_value(),
@@ -6098,15 +6161,15 @@
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
   i::Isolate* isolate = jsvalue->GetIsolate();
-  LOG_API(isolate, "BooleanObject::BooleanValue");
-  return jsvalue->value()->IsTrue();
+  LOG_API(isolate, BooleanObject, BooleanValue);
+  return jsvalue->value()->IsTrue(isolate);
 }
 
 
 Local<v8::Value> v8::StringObject::New(Local<String> value) {
   i::Handle<i::String> string = Utils::OpenHandle(*value);
   i::Isolate* isolate = string->GetIsolate();
-  LOG_API(isolate, "StringObject::New");
+  LOG_API(isolate, StringObject, New);
   ENTER_V8(isolate);
   i::Handle<i::Object> obj =
       i::Object::ToObject(isolate, string).ToHandleChecked();
@@ -6118,7 +6181,7 @@
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
   i::Isolate* isolate = jsvalue->GetIsolate();
-  LOG_API(isolate, "StringObject::StringValue");
+  LOG_API(isolate, StringObject, StringValue);
   return Utils::ToLocal(
       i::Handle<i::String>(i::String::cast(jsvalue->value())));
 }
@@ -6126,7 +6189,7 @@
 
 Local<v8::Value> v8::SymbolObject::New(Isolate* isolate, Local<Symbol> value) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "SymbolObject::New");
+  LOG_API(i_isolate, SymbolObject, New);
   ENTER_V8(i_isolate);
   i::Handle<i::Object> obj = i::Object::ToObject(
       i_isolate, Utils::OpenHandle(*value)).ToHandleChecked();
@@ -6138,7 +6201,7 @@
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
   i::Isolate* isolate = jsvalue->GetIsolate();
-  LOG_API(isolate, "SymbolObject::SymbolValue");
+  LOG_API(isolate, SymbolObject, SymbolValue);
   return Utils::ToLocal(
       i::Handle<i::Symbol>(i::Symbol::cast(jsvalue->value())));
 }
@@ -6149,7 +6212,7 @@
     // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
     time = std::numeric_limits<double>::quiet_NaN();
   }
-  PREPARE_FOR_EXECUTION(context, "Date::New", Value);
+  PREPARE_FOR_EXECUTION(context, Date, New, Value);
   Local<Value> result;
   has_pending_exception = !ToLocal<Value>(
       i::JSDate::New(isolate->date_function(), isolate->date_function(), time),
@@ -6169,14 +6232,14 @@
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   i::Handle<i::JSDate> jsdate = i::Handle<i::JSDate>::cast(obj);
   i::Isolate* isolate = jsdate->GetIsolate();
-  LOG_API(isolate, "Date::NumberValue");
+  LOG_API(isolate, Date, NumberValue);
   return jsdate->value()->Number();
 }
 
 
 void v8::Date::DateTimeConfigurationChangeNotification(Isolate* isolate) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "Date::DateTimeConfigurationChangeNotification");
+  LOG_API(i_isolate, Date, DateTimeConfigurationChangeNotification);
   ENTER_V8(i_isolate);
   i_isolate->date_cache()->ResetDateCache();
   if (!i_isolate->eternal_handles()->Exists(
@@ -6196,7 +6259,7 @@
 
 MaybeLocal<v8::RegExp> v8::RegExp::New(Local<Context> context,
                                        Local<String> pattern, Flags flags) {
-  PREPARE_FOR_EXECUTION(context, "RegExp::New", RegExp);
+  PREPARE_FOR_EXECUTION(context, RegExp, New, RegExp);
   Local<v8::RegExp> result;
   has_pending_exception =
       !ToLocal<RegExp>(i::JSRegExp::New(Utils::OpenHandle(*pattern),
@@ -6241,7 +6304,7 @@
 
 Local<v8::Array> v8::Array::New(Isolate* isolate, int length) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "Array::New");
+  LOG_API(i_isolate, Array, New);
   ENTER_V8(i_isolate);
   int real_length = length > 0 ? length : 0;
   i::Handle<i::JSArray> obj = i_isolate->factory()->NewJSArray(real_length);
@@ -6265,7 +6328,7 @@
 
 MaybeLocal<Object> Array::CloneElementAt(Local<Context> context,
                                          uint32_t index) {
-  PREPARE_FOR_EXECUTION(context, "v8::Array::CloneElementAt()", Object);
+  PREPARE_FOR_EXECUTION(context, Array, CloneElementAt, Object);
   auto self = Utils::OpenHandle(this);
   if (!self->HasFastObjectElements()) return Local<Object>();
   i::FixedArray* elms = i::FixedArray::cast(self->elements());
@@ -6286,7 +6349,7 @@
 
 Local<v8::Map> v8::Map::New(Isolate* isolate) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "Map::New");
+  LOG_API(i_isolate, Map, New);
   ENTER_V8(i_isolate);
   i::Handle<i::JSMap> obj = i_isolate->factory()->NewJSMap();
   return Utils::ToLocal(obj);
@@ -6302,14 +6365,14 @@
 void Map::Clear() {
   auto self = Utils::OpenHandle(this);
   i::Isolate* isolate = self->GetIsolate();
-  LOG_API(isolate, "Map::Clear");
+  LOG_API(isolate, Map, Clear);
   ENTER_V8(isolate);
   i::JSMap::Clear(self);
 }
 
 
 MaybeLocal<Value> Map::Get(Local<Context> context, Local<Value> key) {
-  PREPARE_FOR_EXECUTION(context, "Map::Get", Value);
+  PREPARE_FOR_EXECUTION(context, Map, Get, Value);
   auto self = Utils::OpenHandle(this);
   Local<Value> result;
   i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
@@ -6324,7 +6387,7 @@
 
 MaybeLocal<Map> Map::Set(Local<Context> context, Local<Value> key,
                          Local<Value> value) {
-  PREPARE_FOR_EXECUTION(context, "Map::Set", Map);
+  PREPARE_FOR_EXECUTION(context, Map, Set, Map);
   auto self = Utils::OpenHandle(this);
   i::Handle<i::Object> result;
   i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key),
@@ -6338,7 +6401,7 @@
 
 
 Maybe<bool> Map::Has(Local<Context> context, Local<Value> key) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Map::Has", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Map, Has, bool);
   auto self = Utils::OpenHandle(this);
   i::Handle<i::Object> result;
   i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
@@ -6346,12 +6409,12 @@
                                               arraysize(argv), argv)
                                .ToHandle(&result);
   RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
-  return Just(result->IsTrue());
+  return Just(result->IsTrue(isolate));
 }
 
 
 Maybe<bool> Map::Delete(Local<Context> context, Local<Value> key) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Map::Delete", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Map, Delete, bool);
   auto self = Utils::OpenHandle(this);
   i::Handle<i::Object> result;
   i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
@@ -6359,7 +6422,7 @@
                                               self, arraysize(argv), argv)
                                .ToHandle(&result);
   RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
-  return Just(result->IsTrue());
+  return Just(result->IsTrue(isolate));
 }
 
 
@@ -6367,17 +6430,25 @@
   i::Handle<i::JSMap> obj = Utils::OpenHandle(this);
   i::Isolate* isolate = obj->GetIsolate();
   i::Factory* factory = isolate->factory();
-  LOG_API(isolate, "Map::AsArray");
+  LOG_API(isolate, Map, AsArray);
   ENTER_V8(isolate);
   i::Handle<i::OrderedHashMap> table(i::OrderedHashMap::cast(obj->table()));
-  int size = table->NumberOfElements();
-  int length = size * 2;
+  int length = table->NumberOfElements() * 2;
   i::Handle<i::FixedArray> result = factory->NewFixedArray(length);
-  for (int i = 0; i < size; ++i) {
-    if (table->KeyAt(i)->IsTheHole()) continue;
-    result->set(i * 2, table->KeyAt(i));
-    result->set(i * 2 + 1, table->ValueAt(i));
+  int result_index = 0;
+  {
+    i::DisallowHeapAllocation no_gc;
+    int capacity = table->UsedCapacity();
+    i::Oddball* the_hole = isolate->heap()->the_hole_value();
+    for (int i = 0; i < capacity; ++i) {
+      i::Object* key = table->KeyAt(i);
+      if (key == the_hole) continue;
+      result->set(result_index++, key);
+      result->set(result_index++, table->ValueAt(i));
+    }
   }
+  DCHECK_EQ(result_index, result->length());
+  DCHECK_EQ(result_index, length);
   i::Handle<i::JSArray> result_array =
       factory->NewJSArrayWithElements(result, i::FAST_ELEMENTS, length);
   return Utils::ToLocal(result_array);
@@ -6386,7 +6457,7 @@
 
 Local<v8::Set> v8::Set::New(Isolate* isolate) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "Set::New");
+  LOG_API(i_isolate, Set, New);
   ENTER_V8(i_isolate);
   i::Handle<i::JSSet> obj = i_isolate->factory()->NewJSSet();
   return Utils::ToLocal(obj);
@@ -6402,14 +6473,14 @@
 void Set::Clear() {
   auto self = Utils::OpenHandle(this);
   i::Isolate* isolate = self->GetIsolate();
-  LOG_API(isolate, "Set::Clear");
+  LOG_API(isolate, Set, Clear);
   ENTER_V8(isolate);
   i::JSSet::Clear(self);
 }
 
 
 MaybeLocal<Set> Set::Add(Local<Context> context, Local<Value> key) {
-  PREPARE_FOR_EXECUTION(context, "Set::Add", Set);
+  PREPARE_FOR_EXECUTION(context, Set, Add, Set);
   auto self = Utils::OpenHandle(this);
   i::Handle<i::Object> result;
   i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
@@ -6422,7 +6493,7 @@
 
 
 Maybe<bool> Set::Has(Local<Context> context, Local<Value> key) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Set::Has", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Set, Has, bool);
   auto self = Utils::OpenHandle(this);
   i::Handle<i::Object> result;
   i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
@@ -6430,12 +6501,12 @@
                                               arraysize(argv), argv)
                                .ToHandle(&result);
   RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
-  return Just(result->IsTrue());
+  return Just(result->IsTrue(isolate));
 }
 
 
 Maybe<bool> Set::Delete(Local<Context> context, Local<Value> key) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Set::Delete", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Set, Delete, bool);
   auto self = Utils::OpenHandle(this);
   i::Handle<i::Object> result;
   i::Handle<i::Object> argv[] = {Utils::OpenHandle(*key)};
@@ -6443,7 +6514,7 @@
                                               self, arraysize(argv), argv)
                                .ToHandle(&result);
   RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
-  return Just(result->IsTrue());
+  return Just(result->IsTrue(isolate));
 }
 
 
@@ -6451,17 +6522,24 @@
   i::Handle<i::JSSet> obj = Utils::OpenHandle(this);
   i::Isolate* isolate = obj->GetIsolate();
   i::Factory* factory = isolate->factory();
-  LOG_API(isolate, "Set::AsArray");
+  LOG_API(isolate, Set, AsArray);
   ENTER_V8(isolate);
   i::Handle<i::OrderedHashSet> table(i::OrderedHashSet::cast(obj->table()));
   int length = table->NumberOfElements();
   i::Handle<i::FixedArray> result = factory->NewFixedArray(length);
-  for (int i = 0; i < length; ++i) {
-    i::Object* key = table->KeyAt(i);
-    if (!key->IsTheHole()) {
-      result->set(i, key);
+  int result_index = 0;
+  {
+    i::DisallowHeapAllocation no_gc;
+    int capacity = table->UsedCapacity();
+    i::Oddball* the_hole = isolate->heap()->the_hole_value();
+    for (int i = 0; i < capacity; ++i) {
+      i::Object* key = table->KeyAt(i);
+      if (key == the_hole) continue;
+      result->set(result_index++, key);
     }
   }
+  DCHECK_EQ(result_index, result->length());
+  DCHECK_EQ(result_index, length);
   i::Handle<i::JSArray> result_array =
       factory->NewJSArrayWithElements(result, i::FAST_ELEMENTS, length);
   return Utils::ToLocal(result_array);
@@ -6469,7 +6547,7 @@
 
 
 MaybeLocal<Promise::Resolver> Promise::Resolver::New(Local<Context> context) {
-  PREPARE_FOR_EXECUTION(context, "Promise::Resolver::New", Resolver);
+  PREPARE_FOR_EXECUTION(context, Promise_Resolver, New, Resolver);
   i::Handle<i::Object> result;
   has_pending_exception =
       !i::Execution::Call(isolate, isolate->promise_create(),
@@ -6494,7 +6572,7 @@
 
 Maybe<bool> Promise::Resolver::Resolve(Local<Context> context,
                                        Local<Value> value) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Promise::Resolver::Resolve", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Promise_Resolver, Resolve, bool);
   auto self = Utils::OpenHandle(this);
   i::Handle<i::Object> argv[] = {self, Utils::OpenHandle(*value)};
   has_pending_exception =
@@ -6515,7 +6593,7 @@
 
 Maybe<bool> Promise::Resolver::Reject(Local<Context> context,
                                       Local<Value> value) {
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Promise::Resolver::Resolve", bool);
+  PREPARE_FOR_EXECUTION_PRIMITIVE(context, Promise_Resolver, Resolve, bool);
   auto self = Utils::OpenHandle(this);
   i::Handle<i::Object> argv[] = {self, Utils::OpenHandle(*value)};
   has_pending_exception =
@@ -6538,7 +6616,7 @@
 
 MaybeLocal<Promise> DoChain(Value* value, Local<Context> context,
                             Local<Function> handler) {
-  PREPARE_FOR_EXECUTION(context, "Promise::Chain", Promise);
+  PREPARE_FOR_EXECUTION(context, Promise, Chain, Promise);
   auto self = Utils::OpenHandle(value);
   i::Handle<i::Object> argv[] = {Utils::OpenHandle(*handler)};
   i::Handle<i::Object> result;
@@ -6566,7 +6644,7 @@
 
 MaybeLocal<Promise> Promise::Catch(Local<Context> context,
                                    Local<Function> handler) {
-  PREPARE_FOR_EXECUTION(context, "Promise::Catch", Promise);
+  PREPARE_FOR_EXECUTION(context, Promise, Catch, Promise);
   auto self = Utils::OpenHandle(this);
   i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
   i::Handle<i::Object> result;
@@ -6586,7 +6664,7 @@
 
 MaybeLocal<Promise> Promise::Then(Local<Context> context,
                                   Local<Function> handler) {
-  PREPARE_FOR_EXECUTION(context, "Promise::Then", Promise);
+  PREPARE_FOR_EXECUTION(context, Promise, Then, Promise);
   auto self = Utils::OpenHandle(this);
   i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
   i::Handle<i::Object> result;
@@ -6607,10 +6685,10 @@
 bool Promise::HasHandler() {
   i::Handle<i::JSReceiver> promise = Utils::OpenHandle(this);
   i::Isolate* isolate = promise->GetIsolate();
-  LOG_API(isolate, "Promise::HasRejectHandler");
+  LOG_API(isolate, Promise, HasRejectHandler);
   ENTER_V8(isolate);
   i::Handle<i::Symbol> key = isolate->factory()->promise_has_handler_symbol();
-  return i::JSReceiver::GetDataProperty(promise, key)->IsTrue();
+  return i::JSReceiver::GetDataProperty(promise, key)->IsTrue(isolate);
 }
 
 
@@ -6642,7 +6720,7 @@
 
 MaybeLocal<Proxy> Proxy::New(Local<Context> context, Local<Object> local_target,
                              Local<Object> local_handler) {
-  PREPARE_FOR_EXECUTION(context, "Proxy::New", Proxy);
+  PREPARE_FOR_EXECUTION(context, Proxy, New, Proxy);
   i::Handle<i::JSReceiver> target = Utils::OpenHandle(*local_target);
   i::Handle<i::JSReceiver> handler = Utils::OpenHandle(*local_handler);
   Local<Proxy> result;
@@ -6665,7 +6743,7 @@
 v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() {
   i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
   i::Isolate* isolate = self->GetIsolate();
-  Utils::ApiCheck(!self->is_external(), "v8::ArrayBuffer::Externalize",
+  Utils::ApiCheck(!self->is_external(), "v8_ArrayBuffer_Externalize",
                   "ArrayBuffer already externalized");
   self->set_is_external(true);
   isolate->heap()->UnregisterArrayBuffer(*self);
@@ -6692,7 +6770,7 @@
                   "Only externalized ArrayBuffers can be neutered");
   Utils::ApiCheck(obj->is_neuterable(), "v8::ArrayBuffer::Neuter",
                   "Only neuterable ArrayBuffers can be neutered");
-  LOG_API(obj->GetIsolate(), "v8::ArrayBuffer::Neuter()");
+  LOG_API(obj->GetIsolate(), ArrayBuffer, Neuter);
   ENTER_V8(isolate);
   obj->Neuter();
 }
@@ -6706,7 +6784,7 @@
 
 Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, size_t byte_length) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "v8::ArrayBuffer::New(size_t)");
+  LOG_API(i_isolate, ArrayBuffer, New);
   ENTER_V8(i_isolate);
   i::Handle<i::JSArrayBuffer> obj =
       i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kNotShared);
@@ -6721,7 +6799,7 @@
   // Embedders must guarantee that the external backing store is valid.
   CHECK(byte_length == 0 || data != NULL);
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "v8::ArrayBuffer::New(void*, size_t)");
+  LOG_API(i_isolate, ArrayBuffer, New);
   ENTER_V8(i_isolate);
   i::Handle<i::JSArrayBuffer> obj =
       i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kNotShared);
@@ -6794,49 +6872,45 @@
   return static_cast<size_t>(obj->length_value());
 }
 
-
-#define TYPED_ARRAY_NEW(Type, type, TYPE, ctype, size)                        \
-  Local<Type##Array> Type##Array::New(Local<ArrayBuffer> array_buffer,        \
-                                      size_t byte_offset, size_t length) {    \
-    i::Isolate* isolate = Utils::OpenHandle(*array_buffer)->GetIsolate();     \
-    LOG_API(isolate,                                                          \
-            "v8::" #Type "Array::New(Local<ArrayBuffer>, size_t, size_t)");   \
-    ENTER_V8(isolate);                                                        \
-    if (!Utils::ApiCheck(length <= static_cast<size_t>(i::Smi::kMaxValue),    \
-                         "v8::" #Type                                         \
-                         "Array::New(Local<ArrayBuffer>, size_t, size_t)",    \
-                         "length exceeds max allowed value")) {               \
-      return Local<Type##Array>();                                            \
-    }                                                                         \
-    i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);    \
-    i::Handle<i::JSTypedArray> obj = isolate->factory()->NewJSTypedArray(     \
-        i::kExternal##Type##Array, buffer, byte_offset, length);              \
-    return Utils::ToLocal##Type##Array(obj);                                  \
-  }                                                                           \
-  Local<Type##Array> Type##Array::New(                                        \
-      Local<SharedArrayBuffer> shared_array_buffer, size_t byte_offset,       \
-      size_t length) {                                                        \
-    CHECK(i::FLAG_harmony_sharedarraybuffer);                                 \
-    i::Isolate* isolate =                                                     \
-        Utils::OpenHandle(*shared_array_buffer)->GetIsolate();                \
-    LOG_API(isolate, "v8::" #Type                                             \
-                     "Array::New(Local<SharedArrayBuffer>, size_t, size_t)"); \
-    ENTER_V8(isolate);                                                        \
-    if (!Utils::ApiCheck(                                                     \
-            length <= static_cast<size_t>(i::Smi::kMaxValue),                 \
-            "v8::" #Type                                                      \
-            "Array::New(Local<SharedArrayBuffer>, size_t, size_t)",           \
-            "length exceeds max allowed value")) {                            \
-      return Local<Type##Array>();                                            \
-    }                                                                         \
-    i::Handle<i::JSArrayBuffer> buffer =                                      \
-        Utils::OpenHandle(*shared_array_buffer);                              \
-    i::Handle<i::JSTypedArray> obj = isolate->factory()->NewJSTypedArray(     \
-        i::kExternal##Type##Array, buffer, byte_offset, length);              \
-    return Utils::ToLocal##Type##Array(obj);                                  \
+#define TYPED_ARRAY_NEW(Type, type, TYPE, ctype, size)                     \
+  Local<Type##Array> Type##Array::New(Local<ArrayBuffer> array_buffer,     \
+                                      size_t byte_offset, size_t length) { \
+    i::Isolate* isolate = Utils::OpenHandle(*array_buffer)->GetIsolate();  \
+    LOG_API(isolate, Type##Array, New);                                    \
+    ENTER_V8(isolate);                                                     \
+    if (!Utils::ApiCheck(length <= static_cast<size_t>(i::Smi::kMaxValue), \
+                         "v8::" #Type                                      \
+                         "Array::New(Local<ArrayBuffer>, size_t, size_t)", \
+                         "length exceeds max allowed value")) {            \
+      return Local<Type##Array>();                                         \
+    }                                                                      \
+    i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer); \
+    i::Handle<i::JSTypedArray> obj = isolate->factory()->NewJSTypedArray(  \
+        i::kExternal##Type##Array, buffer, byte_offset, length);           \
+    return Utils::ToLocal##Type##Array(obj);                               \
+  }                                                                        \
+  Local<Type##Array> Type##Array::New(                                     \
+      Local<SharedArrayBuffer> shared_array_buffer, size_t byte_offset,    \
+      size_t length) {                                                     \
+    CHECK(i::FLAG_harmony_sharedarraybuffer);                              \
+    i::Isolate* isolate =                                                  \
+        Utils::OpenHandle(*shared_array_buffer)->GetIsolate();             \
+    LOG_API(isolate, Type##Array, New);                                    \
+    ENTER_V8(isolate);                                                     \
+    if (!Utils::ApiCheck(                                                  \
+            length <= static_cast<size_t>(i::Smi::kMaxValue),              \
+            "v8::" #Type                                                   \
+            "Array::New(Local<SharedArrayBuffer>, size_t, size_t)",        \
+            "length exceeds max allowed value")) {                         \
+      return Local<Type##Array>();                                         \
+    }                                                                      \
+    i::Handle<i::JSArrayBuffer> buffer =                                   \
+        Utils::OpenHandle(*shared_array_buffer);                           \
+    i::Handle<i::JSTypedArray> obj = isolate->factory()->NewJSTypedArray(  \
+        i::kExternal##Type##Array, buffer, byte_offset, length);           \
+    return Utils::ToLocal##Type##Array(obj);                               \
   }
 
-
 TYPED_ARRAYS(TYPED_ARRAY_NEW)
 #undef TYPED_ARRAY_NEW
 
@@ -6844,7 +6918,7 @@
                               size_t byte_offset, size_t byte_length) {
   i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
   i::Isolate* isolate = buffer->GetIsolate();
-  LOG_API(isolate, "v8::DataView::New(Local<ArrayBuffer>, size_t, size_t)");
+  LOG_API(isolate, DataView, New);
   ENTER_V8(isolate);
   i::Handle<i::JSDataView> obj =
       isolate->factory()->NewJSDataView(buffer, byte_offset, byte_length);
@@ -6857,8 +6931,7 @@
   CHECK(i::FLAG_harmony_sharedarraybuffer);
   i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*shared_array_buffer);
   i::Isolate* isolate = buffer->GetIsolate();
-  LOG_API(isolate,
-          "v8::DataView::New(Local<SharedArrayBuffer>, size_t, size_t)");
+  LOG_API(isolate, DataView, New);
   ENTER_V8(isolate);
   i::Handle<i::JSDataView> obj =
       isolate->factory()->NewJSDataView(buffer, byte_offset, byte_length);
@@ -6874,7 +6947,7 @@
 v8::SharedArrayBuffer::Contents v8::SharedArrayBuffer::Externalize() {
   i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this);
   i::Isolate* isolate = self->GetIsolate();
-  Utils::ApiCheck(!self->is_external(), "v8::SharedArrayBuffer::Externalize",
+  Utils::ApiCheck(!self->is_external(), "v8_SharedArrayBuffer_Externalize",
                   "SharedArrayBuffer already externalized");
   self->set_is_external(true);
   isolate->heap()->UnregisterArrayBuffer(*self);
@@ -6902,7 +6975,7 @@
                                                     size_t byte_length) {
   CHECK(i::FLAG_harmony_sharedarraybuffer);
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "v8::SharedArrayBuffer::New(size_t)");
+  LOG_API(i_isolate, SharedArrayBuffer, New);
   ENTER_V8(i_isolate);
   i::Handle<i::JSArrayBuffer> obj =
       i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kShared);
@@ -6919,7 +6992,7 @@
   // Embedders must guarantee that the external backing store is valid.
   CHECK(byte_length == 0 || data != NULL);
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "v8::SharedArrayBuffer::New(void*, size_t)");
+  LOG_API(i_isolate, SharedArrayBuffer, New);
   ENTER_V8(i_isolate);
   i::Handle<i::JSArrayBuffer> obj =
       i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kShared);
@@ -6932,7 +7005,7 @@
 
 Local<Symbol> v8::Symbol::New(Isolate* isolate, Local<String> name) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "Symbol::New()");
+  LOG_API(i_isolate, Symbol, New);
   ENTER_V8(i_isolate);
   i::Handle<i::Symbol> result = i_isolate->factory()->NewSymbol();
   if (!name.IsEmpty()) result->set_name(*Utils::OpenHandle(*name));
@@ -6951,7 +7024,7 @@
   i::Handle<i::Object> symbol =
       i::Object::GetPropertyOrElement(symbols, name).ToHandleChecked();
   if (!symbol->IsSymbol()) {
-    DCHECK(symbol->IsUndefined());
+    DCHECK(symbol->IsUndefined(isolate));
     if (private_symbol)
       symbol = isolate->factory()->NewPrivateSymbol();
     else
@@ -7005,7 +7078,7 @@
 
 Local<Private> v8::Private::New(Isolate* isolate, Local<String> name) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  LOG_API(i_isolate, "Private::New()");
+  LOG_API(i_isolate, Private, New);
   ENTER_V8(i_isolate);
   i::Handle<i::Symbol> symbol = i_isolate->factory()->NewPrivateSymbol();
   if (!name.IsEmpty()) symbol->set_name(*Utils::OpenHandle(*name));
@@ -7198,23 +7271,6 @@
   isolate->heap()->SetEmbedderHeapTracer(tracer);
 }
 
-void Isolate::AddMemoryAllocationCallback(MemoryAllocationCallback callback,
-                                          ObjectSpace space,
-                                          AllocationAction action) {
-  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
-  isolate->memory_allocator()->AddMemoryAllocationCallback(
-      callback, space, action);
-}
-
-
-void Isolate::RemoveMemoryAllocationCallback(
-    MemoryAllocationCallback callback) {
-  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
-  isolate->memory_allocator()->RemoveMemoryAllocationCallback(
-      callback);
-}
-
-
 void Isolate::TerminateExecution() {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
   isolate->stack_guard()->RequestTerminateExecution();
@@ -7297,18 +7353,12 @@
     v8_isolate->SetAddHistogramSampleFunction(
         params.add_histogram_sample_callback);
   }
+
+  isolate->set_api_external_references(params.external_references);
   SetResourceConstraints(isolate, params.constraints);
   // TODO(jochen): Once we got rid of Isolate::Current(), we can remove this.
   Isolate::Scope isolate_scope(v8_isolate);
   if (params.entry_hook || !i::Snapshot::Initialize(isolate)) {
-    // If the isolate has a function entry hook, it needs to re-build all its
-    // code stubs with entry hooks embedded, so don't deserialize a snapshot.
-    if (i::Snapshot::EmbedsScript(isolate)) {
-      // If the snapshot embeds a script, we cannot initialize the isolate
-      // without the snapshot as a fallback. This is unlikely to happen though.
-      V8_Fatal(__FILE__, __LINE__,
-               "Initializing isolate from custom startup snapshot failed");
-    }
     isolate->Init(NULL);
   }
   return v8_isolate;
@@ -7480,14 +7530,41 @@
   return true;
 }
 
+bool Isolate::GetHeapCodeAndMetadataStatistics(
+    HeapCodeStatistics* code_statistics) {
+  if (!code_statistics) return false;
+
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+  isolate->heap()->CollectCodeStatistics();
+
+  code_statistics->code_and_metadata_size_ = isolate->code_and_metadata_size();
+  code_statistics->bytecode_and_metadata_size_ =
+      isolate->bytecode_and_metadata_size();
+  return true;
+}
 
 void Isolate::GetStackSample(const RegisterState& state, void** frames,
                              size_t frames_limit, SampleInfo* sample_info) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
-  i::TickSample::GetStackSample(isolate, state, i::TickSample::kSkipCEntryFrame,
+#if defined(USE_SIMULATOR)
+  RegisterState regs;
+  regs.pc = state.pc;
+  regs.sp = state.sp;
+  regs.fp = state.fp;
+  i::SimulatorHelper::FillRegisters(isolate, &regs);
+#else
+  const RegisterState& regs = state;
+#endif
+  i::TickSample::GetStackSample(isolate, regs, i::TickSample::kSkipCEntryFrame,
                                 frames, frames_limit, sample_info);
 }
 
+size_t Isolate::NumberOfPhantomHandleResetsSinceLastCall() {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+  size_t result = isolate->global_handles()->NumberOfPhantomHandleResets();
+  isolate->global_handles()->ResetNumberOfPhantomHandleResets();
+  return result;
+}
 
 void Isolate::SetEventLogger(LogEventCallback that) {
   // Do not overwrite the event logger if we want to log explicitly.
@@ -7688,6 +7765,11 @@
                                                      Locker::IsLocked(this));
 }
 
+void Isolate::SetRAILMode(RAILMode rail_mode) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+  return isolate->SetRAILMode(rail_mode);
+}
+
 void Isolate::SetJitCodeEventHandler(JitCodeEventOptions options,
                                      JitCodeEventHandler event_handler) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
@@ -7706,9 +7788,10 @@
 
 void Isolate::GetCodeRange(void** start, size_t* length_in_bytes) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
-  if (isolate->code_range()->valid()) {
-    *start = isolate->code_range()->start();
-    *length_in_bytes = isolate->code_range()->size();
+  if (isolate->heap()->memory_allocator()->code_range()->valid()) {
+    *start = isolate->heap()->memory_allocator()->code_range()->start();
+    *length_in_bytes =
+        isolate->heap()->memory_allocator()->code_range()->size();
   } else {
     *start = NULL;
     *length_in_bytes = 0;
@@ -7755,7 +7838,7 @@
   i::HandleScope scope(isolate);
   NeanderArray listeners(isolate->factory()->message_listeners());
   for (int i = 0; i < listeners.length(); i++) {
-    if (listeners.get(i)->IsUndefined()) continue;  // skip deleted ones
+    if (listeners.get(i)->IsUndefined(isolate)) continue;  // skip deleted ones
 
     NeanderObject listener(i::JSObject::cast(listeners.get(i)));
     i::Handle<i::Foreign> callback_obj(i::Foreign::cast(listener.get(0)));
@@ -7787,6 +7870,12 @@
 }
 
 
+bool Isolate::IsInUse() {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+  return isolate->IsInUse();
+}
+
+
 class VisitorAdapter : public i::ObjectVisitor {
  public:
   explicit VisitorAdapter(PersistentHandleVisitor* visitor)
@@ -7874,6 +7963,10 @@
   return isolate->handle_scope_implementer()->GetMicrotasksScopeDepth();
 }
 
+bool MicrotasksScope::IsRunningMicrotasks(Isolate* v8Isolate) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8Isolate);
+  return isolate->IsRunningMicrotasks();
+}
 
 String::Utf8Value::Utf8Value(v8::Local<v8::Value> obj)
     : str_(NULL), length_(0) {
@@ -7918,11 +8011,10 @@
   i::DeleteArray(str_);
 }
 
-
 #define DEFINE_ERROR(NAME, name)                                         \
   Local<Value> Exception::NAME(v8::Local<v8::String> raw_message) {      \
     i::Isolate* isolate = i::Isolate::Current();                         \
-    LOG_API(isolate, #NAME);                                             \
+    LOG_API(isolate, NAME, New);                                         \
     ENTER_V8(isolate);                                                   \
     i::Object* error;                                                    \
     {                                                                    \
@@ -8038,7 +8130,7 @@
 MaybeLocal<Value> Debug::Call(Local<Context> context,
                               v8::Local<v8::Function> fun,
                               v8::Local<v8::Value> data) {
-  PREPARE_FOR_EXECUTION(context, "v8::Debug::Call()", Value);
+  PREPARE_FOR_EXECUTION(context, Debug, Call, Value);
   i::Handle<i::Object> data_obj;
   if (data.IsEmpty()) {
     data_obj = isolate->factory()->undefined_value();
@@ -8063,7 +8155,7 @@
 
 MaybeLocal<Value> Debug::GetMirror(Local<Context> context,
                                    v8::Local<v8::Value> obj) {
-  PREPARE_FOR_EXECUTION(context, "v8::Debug::GetMirror()", Value);
+  PREPARE_FOR_EXECUTION(context, Debug, GetMirror, Value);
   i::Debug* isolate_debug = isolate->debug();
   has_pending_exception = !isolate_debug->Load();
   RETURN_ON_FAILED_EXECUTION(Value);
@@ -8108,6 +8200,14 @@
   return GetDebugContext(reinterpret_cast<Isolate*>(i::Isolate::Current()));
 }
 
+MaybeLocal<Context> Debug::GetDebuggedContext(Isolate* isolate) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  ENTER_V8(i_isolate);
+  if (!i_isolate->debug()->in_debug_scope()) return MaybeLocal<Context>();
+  i::Handle<i::Object> calling = i_isolate->GetCallingNativeContext();
+  if (calling.is_null()) return MaybeLocal<Context>();
+  return Utils::ToLocal(i::Handle<i::Context>::cast(calling));
+}
 
 void Debug::SetLiveEditEnabled(Isolate* isolate, bool enable) {
   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
@@ -8234,9 +8334,8 @@
 
 void CpuProfile::Delete() {
   i::CpuProfile* profile = reinterpret_cast<i::CpuProfile*>(this);
-  i::Isolate* isolate = profile->top_down()->isolate();
-  i::CpuProfiler* profiler = isolate->cpu_profiler();
-  DCHECK(profiler != NULL);
+  i::CpuProfiler* profiler = profile->cpu_profiler();
+  DCHECK(profiler != nullptr);
   profiler->DeleteProfile(profile);
 }
 
@@ -8309,7 +8408,9 @@
 
 
 void CpuProfiler::SetIdle(bool is_idle) {
-  i::Isolate* isolate = reinterpret_cast<i::CpuProfiler*>(this)->isolate();
+  i::CpuProfiler* profiler = reinterpret_cast<i::CpuProfiler*>(this);
+  i::Isolate* isolate = profiler->isolate();
+  if (!isolate->is_profiling()) return;
   v8::StateTag state = isolate->current_vm_state();
   DCHECK(state == v8::EXTERNAL || state == v8::IDLE);
   if (isolate->js_entry_sp() != NULL) return;
@@ -8521,11 +8622,11 @@
   return heap_profiler->PushHeapObjectsStats(stream, timestamp_us);
 }
 
-
 bool HeapProfiler::StartSamplingHeapProfiler(uint64_t sample_interval,
-                                             int stack_depth) {
-  return reinterpret_cast<i::HeapProfiler*>(this)
-      ->StartSamplingHeapProfiler(sample_interval, stack_depth);
+                                             int stack_depth,
+                                             SamplingFlags flags) {
+  return reinterpret_cast<i::HeapProfiler*>(this)->StartSamplingHeapProfiler(
+      sample_interval, stack_depth, flags);
 }
 
 
@@ -8781,6 +8882,8 @@
     v8::AccessorNameGetterCallback getter) {
   // Leaving JavaScript.
   Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
+  RuntimeCallTimerScope timer(isolate,
+                              &RuntimeCallStats::AccessorGetterCallback);
   Address getter_address = reinterpret_cast<Address>(reinterpret_cast<intptr_t>(
       getter));
   VMState<EXTERNAL> state(isolate);
@@ -8792,6 +8895,8 @@
 void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
                             v8::FunctionCallback callback) {
   Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
+  RuntimeCallTimerScope timer(isolate,
+                              &RuntimeCallStats::InvokeFunctionCallback);
   Address callback_address =
       reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback));
   VMState<EXTERNAL> state(isolate);
diff --git a/src/api.h b/src/api.h
index cb2b5c3..a6f403d 100644
--- a/src/api.h
+++ b/src/api.h
@@ -281,7 +281,9 @@
 
   template<class From, class To>
   static inline Local<To> Convert(v8::internal::Handle<From> obj) {
-    DCHECK(obj.is_null() || !obj->IsTheHole());
+    DCHECK(obj.is_null() ||
+           (obj->IsSmi() ||
+            !obj->IsTheHole(i::HeapObject::cast(*obj)->GetIsolate())));
     return Local<To>(reinterpret_cast<To*>(obj.location()));
   }
 
diff --git a/src/arguments.h b/src/arguments.h
index 02090f9..53cea46 100644
--- a/src/arguments.h
+++ b/src/arguments.h
@@ -79,22 +79,29 @@
 #define CLOBBER_DOUBLE_REGISTERS()
 #endif
 
-#define RUNTIME_FUNCTION_RETURNS_TYPE(Type, Name)                          \
-  static INLINE(Type __RT_impl_##Name(Arguments args, Isolate* isolate));  \
-  Type Name(int args_length, Object** args_object, Isolate* isolate) {     \
-    CLOBBER_DOUBLE_REGISTERS();                                            \
-    Type value;                                                            \
-    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"), "V8." #Name);    \
-    Arguments args(args_length, args_object);                              \
-    if (FLAG_runtime_call_stats) {                                         \
-      RuntimeCallStats* stats = isolate->counters()->runtime_call_stats(); \
-      RuntimeCallTimerScope timer(isolate, &stats->Name);                  \
-      value = __RT_impl_##Name(args, isolate);                             \
-    } else {                                                               \
-      value = __RT_impl_##Name(args, isolate);                             \
-    }                                                                      \
-    return value;                                                          \
-  }                                                                        \
+// TODO(cbruni): add global flag to check whether any tracing events have been
+// enabled.
+#define RUNTIME_FUNCTION_RETURNS_TYPE(Type, Name)                             \
+  static INLINE(Type __RT_impl_##Name(Arguments args, Isolate* isolate));     \
+                                                                              \
+  V8_NOINLINE static Type Stats_##Name(int args_length, Object** args_object, \
+                                       Isolate* isolate) {                    \
+    RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::Name);            \
+    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"),                     \
+                 "V8.Runtime_" #Name);                                        \
+    Arguments args(args_length, args_object);                                 \
+    return __RT_impl_##Name(args, isolate);                                   \
+  }                                                                           \
+                                                                              \
+  Type Name(int args_length, Object** args_object, Isolate* isolate) {        \
+    CLOBBER_DOUBLE_REGISTERS();                                               \
+    if (FLAG_runtime_call_stats) {                                            \
+      return Stats_##Name(args_length, args_object, isolate);                 \
+    }                                                                         \
+    Arguments args(args_length, args_object);                                 \
+    return __RT_impl_##Name(args, isolate);                                   \
+  }                                                                           \
+                                                                              \
   static Type __RT_impl_##Name(Arguments args, Isolate* isolate)
 
 #define RUNTIME_FUNCTION(Name) RUNTIME_FUNCTION_RETURNS_TYPE(Object*, Name)
diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
index b0b22b6..52ebe32 100644
--- a/src/arm/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -71,11 +71,6 @@
   return Assembler::target_address_at(pc_, host_);
 }
 
-Address RelocInfo::wasm_memory_reference() {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  return Assembler::target_address_at(pc_, host_);
-}
-
 Address RelocInfo::target_address_address() {
   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
                               || rmode_ == EMBEDDED_OBJECT
@@ -118,19 +113,6 @@
   }
 }
 
-void RelocInfo::update_wasm_memory_reference(
-    Address old_base, Address new_base, size_t old_size, size_t new_size,
-    ICacheFlushMode icache_flush_mode) {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  DCHECK(old_base <= wasm_memory_reference() &&
-         wasm_memory_reference() < old_base + old_size);
-  Address updated_reference = new_base + (wasm_memory_reference() - old_base);
-  DCHECK(new_base <= updated_reference &&
-         updated_reference < new_base + new_size);
-  Assembler::set_target_address_at(isolate_, pc_, host_, updated_reference,
-                                   icache_flush_mode);
-}
-
 Object* RelocInfo::target_object() {
   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
   return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_));
@@ -276,7 +258,7 @@
   }
 }
 
-
+template <typename ObjectVisitor>
 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index 62516e8..9633a63 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -57,7 +57,7 @@
     answer |= 1u << ARMv8;
     // ARMv8 always features VFP and NEON.
     answer |= 1u << ARMv7 | 1u << VFP3 | 1u << NEON | 1u << VFP32DREGS;
-    answer |= 1u << SUDIV | 1u << MLS;
+    answer |= 1u << SUDIV;
   }
 #endif  // CAN_USE_ARMV8_INSTRUCTIONS
 #ifdef CAN_USE_ARMV7_INSTRUCTIONS
@@ -93,7 +93,7 @@
     supported_ |= 1u << ARMv8;
     // ARMv8 always features VFP and NEON.
     supported_ |= 1u << ARMv7 | 1u << VFP3 | 1u << NEON | 1u << VFP32DREGS;
-    supported_ |= 1u << SUDIV | 1u << MLS;
+    supported_ |= 1u << SUDIV;
     if (FLAG_enable_movw_movt) supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS;
   }
   if (FLAG_enable_armv7) {
@@ -104,7 +104,6 @@
     if (FLAG_enable_movw_movt) supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS;
     if (FLAG_enable_32dregs) supported_ |= 1u << VFP32DREGS;
   }
-  if (FLAG_enable_mls) supported_ |= 1u << MLS;
   if (FLAG_enable_unaligned_accesses) supported_ |= 1u << UNALIGNED_ACCESSES;
 
 #else  // __arm__
@@ -119,7 +118,6 @@
 
   if (FLAG_enable_neon && cpu.has_neon()) supported_ |= 1u << NEON;
   if (FLAG_enable_sudiv && cpu.has_idiva()) supported_ |= 1u << SUDIV;
-  if (FLAG_enable_mls && cpu.has_thumb2()) supported_ |= 1u << MLS;
 
   if (cpu.architecture() >= 7) {
     if (FLAG_enable_armv7) supported_ |= 1u << ARMv7;
@@ -141,15 +139,6 @@
   }
 
   if (FLAG_enable_32dregs && cpu.has_vfp3_d32()) supported_ |= 1u << VFP32DREGS;
-
-  if (cpu.implementer() == base::CPU::NVIDIA &&
-      cpu.variant() == base::CPU::NVIDIA_DENVER &&
-      cpu.part() <= base::CPU::NVIDIA_DENVER_V10) {
-    // TODO(jkummerow): This is turned off as an experiment to see if it
-    // affects crash rates. Keep an eye on crash reports and either remove
-    // coherent cache support permanently, or re-enable it!
-    // supported_ |= 1u << COHERENT_CACHE;
-  }
 #endif
 
   DCHECK(!IsSupported(VFP3) || IsSupported(ARMv7));
@@ -212,18 +201,13 @@
 
 void CpuFeatures::PrintFeatures() {
   printf(
-    "ARMv8=%d ARMv7=%d VFP3=%d VFP32DREGS=%d NEON=%d SUDIV=%d MLS=%d"
-    "UNALIGNED_ACCESSES=%d MOVW_MOVT_IMMEDIATE_LOADS=%d COHERENT_CACHE=%d",
-    CpuFeatures::IsSupported(ARMv8),
-    CpuFeatures::IsSupported(ARMv7),
-    CpuFeatures::IsSupported(VFP3),
-    CpuFeatures::IsSupported(VFP32DREGS),
-    CpuFeatures::IsSupported(NEON),
-    CpuFeatures::IsSupported(SUDIV),
-    CpuFeatures::IsSupported(MLS),
-    CpuFeatures::IsSupported(UNALIGNED_ACCESSES),
-    CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS),
-    CpuFeatures::IsSupported(COHERENT_CACHE));
+      "ARMv8=%d ARMv7=%d VFP3=%d VFP32DREGS=%d NEON=%d SUDIV=%d "
+      "UNALIGNED_ACCESSES=%d MOVW_MOVT_IMMEDIATE_LOADS=%d",
+      CpuFeatures::IsSupported(ARMv8), CpuFeatures::IsSupported(ARMv7),
+      CpuFeatures::IsSupported(VFP3), CpuFeatures::IsSupported(VFP32DREGS),
+      CpuFeatures::IsSupported(NEON), CpuFeatures::IsSupported(SUDIV),
+      CpuFeatures::IsSupported(UNALIGNED_ACCESSES),
+      CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS));
 #ifdef __arm__
   bool eabi_hardfloat = base::OS::ArmUsingHardFloat();
 #elif USE_EABI_HARDFLOAT
@@ -255,6 +239,31 @@
   return Assembler::is_constant_pool_load(pc_);
 }
 
+Address RelocInfo::wasm_memory_reference() {
+  DCHECK(IsWasmMemoryReference(rmode_));
+  return Assembler::target_address_at(pc_, host_);
+}
+
+uint32_t RelocInfo::wasm_memory_size_reference() {
+  DCHECK(IsWasmMemorySizeReference(rmode_));
+  return reinterpret_cast<uint32_t>(Assembler::target_address_at(pc_, host_));
+}
+
+Address RelocInfo::wasm_global_reference() {
+  DCHECK(IsWasmGlobalReference(rmode_));
+  return Assembler::target_address_at(pc_, host_);
+}
+
+void RelocInfo::unchecked_update_wasm_memory_reference(
+    Address address, ICacheFlushMode flush_mode) {
+  Assembler::set_target_address_at(isolate_, pc_, host_, address, flush_mode);
+}
+
+void RelocInfo::unchecked_update_wasm_memory_size(uint32_t size,
+                                                  ICacheFlushMode flush_mode) {
+  Assembler::set_target_address_at(isolate_, pc_, host_,
+                                   reinterpret_cast<Address>(size), flush_mode);
+}
 
 // -----------------------------------------------------------------------------
 // Implementation of Operand and MemOperand
@@ -463,17 +472,16 @@
     al | B26 | NegOffset | Register::kCode_fp * B16;
 const Instr kLdrStrInstrTypeMask = 0xffff0000;
 
-
 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
     : AssemblerBase(isolate, buffer, buffer_size),
       recorded_ast_id_(TypeFeedbackId::None()),
-      pending_32_bit_constants_(&pending_32_bit_constants_buffer_[0]),
-      pending_64_bit_constants_(&pending_64_bit_constants_buffer_[0]),
+      pending_32_bit_constants_(),
+      pending_64_bit_constants_(),
       constant_pool_builder_(kLdrMaxReachBits, kVldrMaxReachBits),
       positions_recorder_(this) {
+  pending_32_bit_constants_.reserve(kMinNumPendingConstants);
+  pending_64_bit_constants_.reserve(kMinNumPendingConstants);
   reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
-  num_pending_32_bit_constants_ = 0;
-  num_pending_64_bit_constants_ = 0;
   next_buffer_check_ = 0;
   const_pool_blocked_nesting_ = 0;
   no_const_pool_before_ = 0;
@@ -486,12 +494,6 @@
 
 Assembler::~Assembler() {
   DCHECK(const_pool_blocked_nesting_ == 0);
-  if (pending_32_bit_constants_ != &pending_32_bit_constants_buffer_[0]) {
-    delete[] pending_32_bit_constants_;
-  }
-  if (pending_64_bit_constants_ != &pending_64_bit_constants_buffer_[0]) {
-    delete[] pending_64_bit_constants_;
-  }
 }
 
 
@@ -504,8 +506,8 @@
     constant_pool_offset = EmitEmbeddedConstantPool();
   } else {
     CheckConstPool(true, false);
-    DCHECK(num_pending_32_bit_constants_ == 0);
-    DCHECK(num_pending_64_bit_constants_ == 0);
+    DCHECK(pending_32_bit_constants_.empty());
+    DCHECK(pending_64_bit_constants_.empty());
   }
   // Set up code descriptor.
   desc->buffer = buffer_;
@@ -515,6 +517,8 @@
   desc->constant_pool_size =
       (constant_pool_offset ? desc->instr_size - constant_pool_offset : 0);
   desc->origin = this;
+  desc->unwinding_info_size = 0;
+  desc->unwinding_info = nullptr;
 }
 
 
@@ -828,6 +832,19 @@
     // Load the position of the label relative to the generated code object
     // pointer in a register.
 
+    // The existing code must be a single 24-bit label chain link, followed by
+    // nops encoding the destination register. See mov_label_offset.
+
+    // Extract the destination register from the first nop instructions.
+    Register dst =
+        Register::from_code(Instruction::RmValue(instr_at(pos + kInstrSize)));
+    // In addition to the 24-bit label chain link, we expect to find one nop for
+    // ARMv7 and above, or two nops for ARMv6. See mov_label_offset.
+    DCHECK(IsNop(instr_at(pos + kInstrSize), dst.code()));
+    if (!CpuFeatures::IsSupported(ARMv7)) {
+      DCHECK(IsNop(instr_at(pos + 2 * kInstrSize), dst.code()));
+    }
+
     // Here are the instructions we need to emit:
     //   For ARMv7: target24 => target16_1:target16_0
     //      movw dst, #target16_0
@@ -837,10 +854,6 @@
     //      orr dst, dst, #target8_1 << 8
     //      orr dst, dst, #target8_2 << 16
 
-    // We extract the destination register from the emitted nop instruction.
-    Register dst = Register::from_code(
-        Instruction::RmValue(instr_at(pos + kInstrSize)));
-    DCHECK(IsNop(instr_at(pos + kInstrSize), dst.code()));
     uint32_t target24 = target_pos + (Code::kHeaderSize - kHeapObjectTag);
     DCHECK(is_uint24(target24));
     if (is_uint8(target24)) {
@@ -1367,7 +1380,6 @@
 
 
 void Assembler::bl(int branch_offset, Condition cond) {
-  positions_recorder()->WriteRecordedPositions();
   DCHECK((branch_offset & 3) == 0);
   int imm24 = branch_offset >> 2;
   CHECK(is_int24(imm24));
@@ -1376,7 +1388,6 @@
 
 
 void Assembler::blx(int branch_offset) {  // v5 and above
-  positions_recorder()->WriteRecordedPositions();
   DCHECK((branch_offset & 1) == 0);
   int h = ((branch_offset & 2) >> 1)*B24;
   int imm24 = branch_offset >> 2;
@@ -1386,14 +1397,12 @@
 
 
 void Assembler::blx(Register target, Condition cond) {  // v5 and above
-  positions_recorder()->WriteRecordedPositions();
   DCHECK(!target.is(pc));
   emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BLX | target.code());
 }
 
 
 void Assembler::bx(Register target, Condition cond) {  // v5 and above, plus v4t
-  positions_recorder()->WriteRecordedPositions();
   DCHECK(!target.is(pc));  // use of pc is actually allowed, but discouraged
   emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BX | target.code());
 }
@@ -1501,9 +1510,6 @@
 
 
 void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
-  if (dst.is(pc)) {
-    positions_recorder()->WriteRecordedPositions();
-  }
   // Don't allow nop instructions in the form mov rn, rn to be generated using
   // the mov instruction. They must be generated using nop(int/NopMarkerTypes)
   // or MarkCode(int/NopMarkerTypes) pseudo instructions.
@@ -1586,7 +1592,7 @@
 void Assembler::mls(Register dst, Register src1, Register src2, Register srcA,
                     Condition cond) {
   DCHECK(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc));
-  DCHECK(IsEnabled(MLS));
+  DCHECK(IsEnabled(ARMv7));
   emit(cond | B22 | B21 | dst.code()*B16 | srcA.code()*B12 |
        src2.code()*B8 | B7 | B4 | src1.code());
 }
@@ -1702,8 +1708,6 @@
                      int satpos,
                      const Operand& src,
                      Condition cond) {
-  // v6 and above.
-  DCHECK(CpuFeatures::IsSupported(ARMv7));
   DCHECK(!dst.is(pc) && !src.rm_.is(pc));
   DCHECK((satpos >= 0) && (satpos <= 31));
   DCHECK((src.shift_op_ == ASR) || (src.shift_op_ == LSL));
@@ -1994,9 +1998,6 @@
 
 // Load/Store instructions.
 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
-  if (dst.is(pc)) {
-    positions_recorder()->WriteRecordedPositions();
-  }
   addrmod2(cond | B26 | L, dst, src);
 }
 
@@ -2038,7 +2039,6 @@
 
 void Assembler::ldrd(Register dst1, Register dst2,
                      const MemOperand& src, Condition cond) {
-  DCHECK(IsEnabled(ARMv7));
   DCHECK(src.rm().is(no_reg));
   DCHECK(!dst1.is(lr));  // r14.
   DCHECK_EQ(0, dst1.code() % 2);
@@ -2053,10 +2053,56 @@
   DCHECK(!src1.is(lr));  // r14.
   DCHECK_EQ(0, src1.code() % 2);
   DCHECK_EQ(src1.code() + 1, src2.code());
-  DCHECK(IsEnabled(ARMv7));
   addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
 }
 
+// Load/Store exclusive instructions.
+void Assembler::ldrex(Register dst, Register src, Condition cond) {
+  // Instruction details available in ARM DDI 0406C.b, A8.8.75.
+  // cond(31-28) | 00011001(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0)
+  emit(cond | B24 | B23 | B20 | src.code() * B16 | dst.code() * B12 | 0xf9f);
+}
+
+void Assembler::strex(Register src1, Register src2, Register dst,
+                      Condition cond) {
+  // Instruction details available in ARM DDI 0406C.b, A8.8.212.
+  // cond(31-28) | 00011000(27-20) | Rn(19-16) | Rd(15-12) | 11111001(11-4) |
+  // Rt(3-0)
+  emit(cond | B24 | B23 | dst.code() * B16 | src1.code() * B12 | 0xf9 * B4 |
+       src2.code());
+}
+
+void Assembler::ldrexb(Register dst, Register src, Condition cond) {
+  // Instruction details available in ARM DDI 0406C.b, A8.8.76.
+  // cond(31-28) | 00011101(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0)
+  emit(cond | B24 | B23 | B22 | B20 | src.code() * B16 | dst.code() * B12 |
+       0xf9f);
+}
+
+void Assembler::strexb(Register src1, Register src2, Register dst,
+                       Condition cond) {
+  // Instruction details available in ARM DDI 0406C.b, A8.8.213.
+  // cond(31-28) | 00011100(27-20) | Rn(19-16) | Rd(15-12) | 11111001(11-4) |
+  // Rt(3-0)
+  emit(cond | B24 | B23 | B22 | dst.code() * B16 | src1.code() * B12 |
+       0xf9 * B4 | src2.code());
+}
+
+void Assembler::ldrexh(Register dst, Register src, Condition cond) {
+  // Instruction details available in ARM DDI 0406C.b, A8.8.78.
+  // cond(31-28) | 00011111(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0)
+  emit(cond | B24 | B23 | B22 | B21 | B20 | src.code() * B16 |
+       dst.code() * B12 | 0xf9f);
+}
+
+void Assembler::strexh(Register src1, Register src2, Register dst,
+                       Condition cond) {
+  // Instruction details available in ARM DDI 0406C.b, A8.8.215.
+  // cond(31-28) | 00011110(27-20) | Rn(19-16) | Rd(15-12) | 11111001(11-4) |
+  // Rt(3-0)
+  emit(cond | B24 | B23 | B22 | B21 | dst.code() * B16 | src1.code() * B12 |
+       0xf9 * B4 | src2.code());
+}
 
 // Preload instructions.
 void Assembler::pld(const MemOperand& address) {
@@ -3371,6 +3417,69 @@
        0x5 * B9 | B6);
 }
 
+void Assembler::vsel(Condition cond, const DwVfpRegister dst,
+                     const DwVfpRegister src1, const DwVfpRegister src2) {
+  // cond=kSpecialCondition(31-28) | 11100(27-23) | D(22) |
+  // vsel_cond=XX(21-20) | Vn(19-16) | Vd(15-12) | 101(11-9) | sz=1(8) | N(7) |
+  // 0(6) | M(5) | 0(4) | Vm(3-0)
+  DCHECK(CpuFeatures::IsSupported(ARMv8));
+  int vd, d;
+  dst.split_code(&vd, &d);
+  int vn, n;
+  src1.split_code(&vn, &n);
+  int vm, m;
+  src2.split_code(&vm, &m);
+  int sz = 1;
+
+  // VSEL has a special (restricted) condition encoding.
+  //   eq(0b0000)... -> 0b00
+  //   ge(0b1010)... -> 0b10
+  //   gt(0b1100)... -> 0b11
+  //   vs(0b0110)... -> 0b01
+  // No other conditions are supported.
+  int vsel_cond = (cond >> 30) & 0x3;
+  if ((cond != eq) && (cond != ge) && (cond != gt) && (cond != vs)) {
+    // We can implement some other conditions by swapping the inputs.
+    DCHECK((cond == ne) | (cond == lt) | (cond == le) | (cond == vc));
+    std::swap(vn, vm);
+    std::swap(n, m);
+  }
+
+  emit(kSpecialCondition | 0x1C * B23 | d * B22 | vsel_cond * B20 | vn * B16 |
+       vd * B12 | 0x5 * B9 | sz * B8 | n * B7 | m * B5 | vm);
+}
+
+void Assembler::vsel(Condition cond, const SwVfpRegister dst,
+                     const SwVfpRegister src1, const SwVfpRegister src2) {
+  // cond=kSpecialCondition(31-28) | 11100(27-23) | D(22) |
+  // vsel_cond=XX(21-20) | Vn(19-16) | Vd(15-12) | 101(11-9) | sz=0(8) | N(7) |
+  // 0(6) | M(5) | 0(4) | Vm(3-0)
+  DCHECK(CpuFeatures::IsSupported(ARMv8));
+  int vd, d;
+  dst.split_code(&vd, &d);
+  int vn, n;
+  src1.split_code(&vn, &n);
+  int vm, m;
+  src2.split_code(&vm, &m);
+  int sz = 0;
+
+  // VSEL has a special (restricted) condition encoding.
+  //   eq(0b0000)... -> 0b00
+  //   ge(0b1010)... -> 0b10
+  //   gt(0b1100)... -> 0b11
+  //   vs(0b0110)... -> 0b01
+  // No other conditions are supported.
+  int vsel_cond = (cond >> 30) & 0x3;
+  if ((cond != eq) && (cond != ge) && (cond != gt) && (cond != vs)) {
+    // We can implement some other conditions by swapping the inputs.
+    DCHECK((cond == ne) | (cond == lt) | (cond == le) | (cond == vc));
+    std::swap(vn, vm);
+    std::swap(n, m);
+  }
+
+  emit(kSpecialCondition | 0x1C * B23 | d * B22 | vsel_cond * B20 | vn * B16 |
+       vd * B12 | 0x5 * B9 | sz * B8 | n * B7 | m * B5 | vm);
+}
 
 void Assembler::vsqrt(const DwVfpRegister dst,
                       const DwVfpRegister src,
@@ -3745,8 +3854,8 @@
 void Assembler::db(uint8_t data) {
   // db is used to write raw data. The constant pool should be emitted or
   // blocked before using db.
-  DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0));
-  DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0));
+  DCHECK(is_const_pool_blocked() || pending_32_bit_constants_.empty());
+  DCHECK(is_const_pool_blocked() || pending_64_bit_constants_.empty());
   CheckBuffer();
   *reinterpret_cast<uint8_t*>(pc_) = data;
   pc_ += sizeof(uint8_t);
@@ -3756,8 +3865,8 @@
 void Assembler::dd(uint32_t data) {
   // dd is used to write raw data. The constant pool should be emitted or
   // blocked before using dd.
-  DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0));
-  DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0));
+  DCHECK(is_const_pool_blocked() || pending_32_bit_constants_.empty());
+  DCHECK(is_const_pool_blocked() || pending_64_bit_constants_.empty());
   CheckBuffer();
   *reinterpret_cast<uint32_t*>(pc_) = data;
   pc_ += sizeof(uint32_t);
@@ -3767,8 +3876,8 @@
 void Assembler::dq(uint64_t value) {
   // dq is used to write raw data. The constant pool should be emitted or
   // blocked before using dq.
-  DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0));
-  DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0));
+  DCHECK(is_const_pool_blocked() || pending_32_bit_constants_.empty());
+  DCHECK(is_const_pool_blocked() || pending_64_bit_constants_.empty());
   CheckBuffer();
   *reinterpret_cast<uint64_t*>(pc_) = value;
   pc_ += sizeof(uint64_t);
@@ -3811,21 +3920,12 @@
   if (FLAG_enable_embedded_constant_pool) {
     return constant_pool_builder_.AddEntry(position, value, sharing_ok);
   } else {
-    DCHECK(num_pending_32_bit_constants_ < kMaxNumPending32Constants);
-    if (num_pending_32_bit_constants_ == 0) {
+    DCHECK(pending_32_bit_constants_.size() < kMaxNumPending32Constants);
+    if (pending_32_bit_constants_.empty()) {
       first_const_pool_32_use_ = position;
-    } else if (num_pending_32_bit_constants_ == kMinNumPendingConstants &&
-               pending_32_bit_constants_ ==
-                   &pending_32_bit_constants_buffer_[0]) {
-      // Inline buffer is full, switch to dynamically allocated buffer.
-      pending_32_bit_constants_ =
-          new ConstantPoolEntry[kMaxNumPending32Constants];
-      std::copy(&pending_32_bit_constants_buffer_[0],
-                &pending_32_bit_constants_buffer_[kMinNumPendingConstants],
-                &pending_32_bit_constants_[0]);
     }
     ConstantPoolEntry entry(position, value, sharing_ok);
-    pending_32_bit_constants_[num_pending_32_bit_constants_++] = entry;
+    pending_32_bit_constants_.push_back(entry);
 
     // Make sure the constant pool is not emitted in place of the next
     // instruction for which we just recorded relocation info.
@@ -3840,21 +3940,12 @@
   if (FLAG_enable_embedded_constant_pool) {
     return constant_pool_builder_.AddEntry(position, value);
   } else {
-    DCHECK(num_pending_64_bit_constants_ < kMaxNumPending64Constants);
-    if (num_pending_64_bit_constants_ == 0) {
+    DCHECK(pending_64_bit_constants_.size() < kMaxNumPending64Constants);
+    if (pending_64_bit_constants_.empty()) {
       first_const_pool_64_use_ = position;
-    } else if (num_pending_64_bit_constants_ == kMinNumPendingConstants &&
-               pending_64_bit_constants_ ==
-                   &pending_64_bit_constants_buffer_[0]) {
-      // Inline buffer is full, switch to dynamically allocated buffer.
-      pending_64_bit_constants_ =
-          new ConstantPoolEntry[kMaxNumPending64Constants];
-      std::copy(&pending_64_bit_constants_buffer_[0],
-                &pending_64_bit_constants_buffer_[kMinNumPendingConstants],
-                &pending_64_bit_constants_[0]);
     }
     ConstantPoolEntry entry(position, value);
-    pending_64_bit_constants_[num_pending_64_bit_constants_++] = entry;
+    pending_64_bit_constants_.push_back(entry);
 
     // Make sure the constant pool is not emitted in place of the next
     // instruction for which we just recorded relocation info.
@@ -3867,8 +3958,8 @@
 void Assembler::BlockConstPoolFor(int instructions) {
   if (FLAG_enable_embedded_constant_pool) {
     // Should be a no-op if using an embedded constant pool.
-    DCHECK(num_pending_32_bit_constants_ == 0);
-    DCHECK(num_pending_64_bit_constants_ == 0);
+    DCHECK(pending_32_bit_constants_.empty());
+    DCHECK(pending_64_bit_constants_.empty());
     return;
   }
 
@@ -3877,11 +3968,11 @@
     // Max pool start (if we need a jump and an alignment).
 #ifdef DEBUG
     int start = pc_limit + kInstrSize + 2 * kPointerSize;
-    DCHECK((num_pending_32_bit_constants_ == 0) ||
+    DCHECK(pending_32_bit_constants_.empty() ||
            (start - first_const_pool_32_use_ +
-                num_pending_64_bit_constants_ * kDoubleSize <
+                pending_64_bit_constants_.size() * kDoubleSize <
             kMaxDistToIntPool));
-    DCHECK((num_pending_64_bit_constants_ == 0) ||
+    DCHECK(pending_64_bit_constants_.empty() ||
            (start - first_const_pool_64_use_ < kMaxDistToFPPool));
 #endif
     no_const_pool_before_ = pc_limit;
@@ -3896,8 +3987,8 @@
 void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
   if (FLAG_enable_embedded_constant_pool) {
     // Should be a no-op if using an embedded constant pool.
-    DCHECK(num_pending_32_bit_constants_ == 0);
-    DCHECK(num_pending_64_bit_constants_ == 0);
+    DCHECK(pending_32_bit_constants_.empty());
+    DCHECK(pending_64_bit_constants_.empty());
     return;
   }
 
@@ -3911,8 +4002,7 @@
   }
 
   // There is nothing to do if there are no pending constant pool entries.
-  if ((num_pending_32_bit_constants_ == 0) &&
-      (num_pending_64_bit_constants_ == 0)) {
+  if (pending_32_bit_constants_.empty() && pending_64_bit_constants_.empty()) {
     // Calculate the offset of the next check.
     next_buffer_check_ = pc_offset() + kCheckPoolInterval;
     return;
@@ -3924,9 +4014,9 @@
   int jump_instr = require_jump ? kInstrSize : 0;
   int size_up_to_marker = jump_instr + kInstrSize;
   int estimated_size_after_marker =
-      num_pending_32_bit_constants_ * kPointerSize;
-  bool has_int_values = (num_pending_32_bit_constants_ > 0);
-  bool has_fp_values = (num_pending_64_bit_constants_ > 0);
+      pending_32_bit_constants_.size() * kPointerSize;
+  bool has_int_values = !pending_32_bit_constants_.empty();
+  bool has_fp_values = !pending_64_bit_constants_.empty();
   bool require_64_bit_align = false;
   if (has_fp_values) {
     require_64_bit_align =
@@ -3935,7 +4025,8 @@
     if (require_64_bit_align) {
       estimated_size_after_marker += kInstrSize;
     }
-    estimated_size_after_marker += num_pending_64_bit_constants_ * kDoubleSize;
+    estimated_size_after_marker +=
+        pending_64_bit_constants_.size() * kDoubleSize;
   }
   int estimated_size = size_up_to_marker + estimated_size_after_marker;
 
@@ -3954,7 +4045,7 @@
       // The 64-bit constants are always emitted before the 32-bit constants, so
       // we can ignore the effect of the 32-bit constants on estimated_size.
       int dist64 = pc_offset() + estimated_size -
-                   num_pending_32_bit_constants_ * kPointerSize -
+                   pending_32_bit_constants_.size() * kPointerSize -
                    first_const_pool_64_use_;
       if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) ||
           (!require_jump && (dist64 >= kMaxDistToFPPool / 2))) {
@@ -3973,7 +4064,7 @@
 
   // Deduplicate constants.
   int size_after_marker = estimated_size_after_marker;
-  for (int i = 0; i < num_pending_64_bit_constants_; i++) {
+  for (int i = 0; i < pending_64_bit_constants_.size(); i++) {
     ConstantPoolEntry& entry = pending_64_bit_constants_[i];
     DCHECK(!entry.is_merged());
     for (int j = 0; j < i; j++) {
@@ -3986,7 +4077,7 @@
     }
   }
 
-  for (int i = 0; i < num_pending_32_bit_constants_; i++) {
+  for (int i = 0; i < pending_32_bit_constants_.size(); i++) {
     ConstantPoolEntry& entry = pending_32_bit_constants_[i];
     DCHECK(!entry.is_merged());
     if (!entry.sharing_ok()) continue;
@@ -4031,7 +4122,7 @@
 
     // Emit 64-bit constant pool entries first: their range is smaller than
     // 32-bit entries.
-    for (int i = 0; i < num_pending_64_bit_constants_; i++) {
+    for (int i = 0; i < pending_64_bit_constants_.size(); i++) {
       ConstantPoolEntry& entry = pending_64_bit_constants_[i];
 
       Instr instr = instr_at(entry.position());
@@ -4060,7 +4151,7 @@
     }
 
     // Emit 32-bit constant pool entries.
-    for (int i = 0; i < num_pending_32_bit_constants_; i++) {
+    for (int i = 0; i < pending_32_bit_constants_.size(); i++) {
       ConstantPoolEntry& entry = pending_32_bit_constants_[i];
       Instr instr = instr_at(entry.position());
 
@@ -4094,8 +4185,8 @@
       }
     }
 
-    num_pending_32_bit_constants_ = 0;
-    num_pending_64_bit_constants_ = 0;
+    pending_32_bit_constants_.clear();
+    pending_64_bit_constants_.clear();
     first_const_pool_32_use_ = -1;
     first_const_pool_64_use_ = -1;
 
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index 08ad64c..461d5b0 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -57,6 +57,12 @@
 #define ALLOCATABLE_GENERAL_REGISTERS(V) \
   V(r0)  V(r1)  V(r2)  V(r3)  V(r4)  V(r5)  V(r6)  V(r7)  V(r8)
 
+#define FLOAT_REGISTERS(V)                                \
+  V(s0)  V(s1)  V(s2)  V(s3)  V(s4)  V(s5)  V(s6)  V(s7)  \
+  V(s8)  V(s9)  V(s10) V(s11) V(s12) V(s13) V(s14) V(s15) \
+  V(s16) V(s17) V(s18) V(s19) V(s20) V(s21) V(s22) V(s23) \
+  V(s24) V(s25) V(s26) V(s27) V(s28) V(s29) V(s30) V(s31)
+
 #define DOUBLE_REGISTERS(V)                               \
   V(d0)  V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)  \
   V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d13) V(d14) V(d15) \
@@ -112,8 +118,6 @@
     Register r = {code};
     return r;
   }
-  const char* ToString();
-  bool IsAllocatable() const;
   bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
   bool is(Register reg) const { return reg_code == reg.reg_code; }
   int code() const {
@@ -141,9 +145,22 @@
 #undef DECLARE_REGISTER
 const Register no_reg = {Register::kCode_no_reg};
 
+static const bool kSimpleFPAliasing = false;
+
 // Single word VFP register.
 struct SwVfpRegister {
+  enum Code {
+#define REGISTER_CODE(R) kCode_##R,
+    FLOAT_REGISTERS(REGISTER_CODE)
+#undef REGISTER_CODE
+        kAfterLast,
+    kCode_no_reg = -1
+  };
+
+  static const int kMaxNumRegisters = Code::kAfterLast;
+
   static const int kSizeInBytes = 4;
+
   bool is_valid() const { return 0 <= reg_code && reg_code < 32; }
   bool is(SwVfpRegister reg) const { return reg_code == reg.reg_code; }
   int code() const {
@@ -154,6 +171,10 @@
     DCHECK(is_valid());
     return 1 << reg_code;
   }
+  static SwVfpRegister from_code(int code) {
+    SwVfpRegister r = {code};
+    return r;
+  }
   void split_code(int* vm, int* m) const {
     DCHECK(is_valid());
     *m = reg_code & 0x1;
@@ -163,9 +184,10 @@
   int reg_code;
 };
 
+typedef SwVfpRegister FloatRegister;
 
 // Double word VFP register.
-struct DoubleRegister {
+struct DwVfpRegister {
   enum Code {
 #define REGISTER_CODE(R) kCode_##R,
     DOUBLE_REGISTERS(REGISTER_CODE)
@@ -184,10 +206,8 @@
   //  d15: scratch register.
   static const int kSizeInBytes = 8;
 
-  const char* ToString();
-  bool IsAllocatable() const;
   bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
-  bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
+  bool is(DwVfpRegister reg) const { return reg_code == reg.reg_code; }
   int code() const {
     DCHECK(is_valid());
     return reg_code;
@@ -197,8 +217,8 @@
     return 1 << reg_code;
   }
 
-  static DoubleRegister from_code(int code) {
-    DoubleRegister r = {code};
+  static DwVfpRegister from_code(int code) {
+    DwVfpRegister r = {code};
     return r;
   }
   void split_code(int* vm, int* m) const {
@@ -211,7 +231,7 @@
 };
 
 
-typedef DoubleRegister DwVfpRegister;
+typedef DwVfpRegister DoubleRegister;
 
 
 // Double word VFP register d0-15.
@@ -975,6 +995,14 @@
             Register src2,
             const MemOperand& dst, Condition cond = al);
 
+  // Load/Store exclusive instructions
+  void ldrex(Register dst, Register src, Condition cond = al);
+  void strex(Register src1, Register src2, Register dst, Condition cond = al);
+  void ldrexb(Register dst, Register src, Condition cond = al);
+  void strexb(Register src1, Register src2, Register dst, Condition cond = al);
+  void ldrexh(Register dst, Register src, Condition cond = al);
+  void strexh(Register src1, Register src2, Register dst, Condition cond = al);
+
   // Preload instructions
   void pld(const MemOperand& address);
 
@@ -1225,6 +1253,17 @@
             const Condition cond = al);
   void vcmp(const SwVfpRegister src1, const float src2,
             const Condition cond = al);
+
+  // VSEL supports cond in {eq, ne, ge, lt, gt, le, vs, vc}.
+  void vsel(const Condition cond,
+            const DwVfpRegister dst,
+            const DwVfpRegister src1,
+            const DwVfpRegister src2);
+  void vsel(const Condition cond,
+            const SwVfpRegister dst,
+            const SwVfpRegister src1,
+            const SwVfpRegister src2);
+
   void vsqrt(const DwVfpRegister dst,
              const DwVfpRegister src,
              const Condition cond = al);
@@ -1290,6 +1329,10 @@
     vstm(db_w, sp, src, src, cond);
   }
 
+  void vpush(SwVfpRegister src, Condition cond = al) {
+    vstm(db_w, sp, src, src, cond);
+  }
+
   void vpop(DwVfpRegister dst, Condition cond = al) {
     vldm(ia_w, sp, dst, dst, cond);
   }
@@ -1357,7 +1400,7 @@
 
   // Record a deoptimization reason that can be used by a log or cpu profiler.
   // Use --trace-deopt to enable.
-  void RecordDeoptReason(const int reason, int raw_position);
+  void RecordDeoptReason(const int reason, int raw_position, int id);
 
   // Record the emission of a constant pool.
   //
@@ -1523,10 +1566,10 @@
       // Max pool start (if we need a jump and an alignment).
       int start = pc_offset() + kInstrSize + 2 * kPointerSize;
       // Check the constant pool hasn't been blocked for too long.
-      DCHECK((num_pending_32_bit_constants_ == 0) ||
-             (start + num_pending_64_bit_constants_ * kDoubleSize <
+      DCHECK(pending_32_bit_constants_.empty() ||
+             (start + pending_64_bit_constants_.size() * kDoubleSize <
               (first_const_pool_32_use_ + kMaxDistToIntPool)));
-      DCHECK((num_pending_64_bit_constants_ == 0) ||
+      DCHECK(pending_64_bit_constants_.empty() ||
              (start < (first_const_pool_64_use_ + kMaxDistToFPPool)));
 #endif
       // Two cases:
@@ -1593,14 +1636,8 @@
   // pending relocation entry per instruction.
 
   // The buffers of pending constant pool entries.
-  ConstantPoolEntry pending_32_bit_constants_buffer_[kMinNumPendingConstants];
-  ConstantPoolEntry pending_64_bit_constants_buffer_[kMinNumPendingConstants];
-  ConstantPoolEntry* pending_32_bit_constants_;
-  ConstantPoolEntry* pending_64_bit_constants_;
-  // Number of pending constant pool entries in the 32 bits buffer.
-  int num_pending_32_bit_constants_;
-  // Number of pending constant pool entries in the 64 bits buffer.
-  int num_pending_64_bit_constants_;
+  std::vector<ConstantPoolEntry> pending_32_bit_constants_;
+  std::vector<ConstantPoolEntry> pending_64_bit_constants_;
 
   ConstantPoolBuilder constant_pool_builder_;
 
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index 1fffcb6..365bc1e 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -16,10 +16,7 @@
 
 #define __ ACCESS_MASM(masm)
 
-
-void Builtins::Generate_Adaptor(MacroAssembler* masm,
-                                CFunctionId id,
-                                BuiltinExtraArguments extra_args) {
+void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
   // ----------- S t a t e -------------
   //  -- r0                 : number of arguments excluding receiver
   //  -- r1                 : target
@@ -38,23 +35,8 @@
   __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
 
   // Insert extra arguments.
-  int num_extra_args = 0;
-  switch (extra_args) {
-    case BuiltinExtraArguments::kTarget:
-      __ Push(r1);
-      ++num_extra_args;
-      break;
-    case BuiltinExtraArguments::kNewTarget:
-      __ Push(r3);
-      ++num_extra_args;
-      break;
-    case BuiltinExtraArguments::kTargetAndNewTarget:
-      __ Push(r1, r3);
-      num_extra_args += 2;
-      break;
-    case BuiltinExtraArguments::kNone:
-      break;
-  }
+  const int num_extra_args = 2;
+  __ Push(r1, r3);
 
   // JumpToExternalReference expects r0 to contain the number of arguments
   // including the receiver and the extra arguments.
@@ -140,6 +122,8 @@
 void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
   // ----------- S t a t e -------------
   //  -- r0                 : number of arguments
+  //  -- r1                 : function
+  //  -- cp                 : context
   //  -- lr                 : return address
   //  -- sp[(argc - n) * 8] : arg[n] (zero-based)
   //  -- sp[(argc + 1) * 8] : receiver
@@ -152,9 +136,9 @@
   DoubleRegister const reg = (kind == MathMaxMinKind::kMin) ? d2 : d1;
 
   // Load the accumulator with the default return value (either -Infinity or
-  // +Infinity), with the tagged value in r1 and the double value in d1.
-  __ LoadRoot(r1, root_index);
-  __ vldr(d1, FieldMemOperand(r1, HeapNumber::kValueOffset));
+  // +Infinity), with the tagged value in r5 and the double value in d1.
+  __ LoadRoot(r5, root_index);
+  __ vldr(d1, FieldMemOperand(r5, HeapNumber::kValueOffset));
 
   // Remember how many slots to drop (including the receiver).
   __ add(r4, r0, Operand(1));
@@ -170,33 +154,36 @@
     __ ldr(r2, MemOperand(sp, r0, LSL, kPointerSizeLog2));
 
     // Load the double value of the parameter into d2, maybe converting the
-    // parameter to a number first using the ToNumberStub if necessary.
+    // parameter to a number first using the ToNumber builtin if necessary.
     Label convert, convert_smi, convert_number, done_convert;
     __ bind(&convert);
     __ JumpIfSmi(r2, &convert_smi);
     __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
     __ JumpIfRoot(r3, Heap::kHeapNumberMapRootIndex, &convert_number);
     {
-      // Parameter is not a Number, use the ToNumberStub to convert it.
-      FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
+      // Parameter is not a Number, use the ToNumber builtin to convert it.
+      DCHECK(!FLAG_enable_embedded_constant_pool);
+      FrameScope scope(masm, StackFrame::MANUAL);
+      __ Push(lr, fp, cp, r1);
+      __ add(fp, sp, Operand(2 * kPointerSize));
       __ SmiTag(r0);
       __ SmiTag(r4);
-      __ Push(r0, r1, r4);
+      __ Push(r0, r4, r5);
       __ mov(r0, r2);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
       __ mov(r2, r0);
-      __ Pop(r0, r1, r4);
+      __ Pop(r0, r4, r5);
       {
         // Restore the double accumulator value (d1).
         Label done_restore;
-        __ SmiToDouble(d1, r1);
-        __ JumpIfSmi(r1, &done_restore);
-        __ vldr(d1, FieldMemOperand(r1, HeapNumber::kValueOffset));
+        __ SmiToDouble(d1, r5);
+        __ JumpIfSmi(r5, &done_restore);
+        __ vldr(d1, FieldMemOperand(r5, HeapNumber::kValueOffset));
         __ bind(&done_restore);
       }
       __ SmiUntag(r4);
       __ SmiUntag(r0);
+      __ Pop(lr, fp, cp, r1);
     }
     __ b(&convert);
     __ bind(&convert_number);
@@ -222,18 +209,18 @@
     // Result is on the right hand side.
     __ bind(&compare_swap);
     __ vmov(d1, d2);
-    __ mov(r1, r2);
+    __ mov(r5, r2);
     __ b(&loop);
 
     // At least one side is NaN, which means that the result will be NaN too.
     __ bind(&compare_nan);
-    __ LoadRoot(r1, Heap::kNanValueRootIndex);
-    __ vldr(d1, FieldMemOperand(r1, HeapNumber::kValueOffset));
+    __ LoadRoot(r5, Heap::kNanValueRootIndex);
+    __ vldr(d1, FieldMemOperand(r5, HeapNumber::kValueOffset));
     __ b(&loop);
   }
 
   __ bind(&done_loop);
-  __ mov(r0, r1);
+  __ mov(r0, r5);
   __ Drop(r4);
   __ Ret();
 }
@@ -259,8 +246,7 @@
   }
 
   // 2a. Convert the first argument to a number.
-  ToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
+  __ Jump(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
 
   // 2b. No arguments, return +0.
   __ bind(&no_arguments);
@@ -308,8 +294,7 @@
       FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
       __ Push(r1, r3);
       __ Move(r0, r2);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
       __ Move(r2, r0);
       __ Pop(r1, r3);
     }
@@ -604,16 +589,9 @@
     // r0: number of arguments
     // r1: constructor function
     // r3: new target
-    if (is_api_function) {
-      __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
-      Handle<Code> code =
-          masm->isolate()->builtins()->HandleApiCallConstruct();
-      __ Call(code, RelocInfo::CODE_TARGET);
-    } else {
-      ParameterCount actual(r0);
-      __ InvokeFunction(r1, r3, actual, CALL_FUNCTION,
-                        CheckDebugStepCallWrapper());
-    }
+    ParameterCount actual(r0);
+    __ InvokeFunction(r1, r3, actual, CALL_FUNCTION,
+                      CheckDebugStepCallWrapper());
 
     // Store offset of return address for deoptimizer.
     if (create_implicit_receiver && !is_api_function) {
@@ -704,6 +682,163 @@
   Generate_JSConstructStubHelper(masm, false, false, true);
 }
 
+// static
+void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r0 : the value to pass to the generator
+  //  -- r1 : the JSGeneratorObject to resume
+  //  -- r2 : the resume mode (tagged)
+  //  -- lr : return address
+  // -----------------------------------
+  __ AssertGeneratorObject(r1);
+
+  // Store input value into generator object.
+  __ str(r0, FieldMemOperand(r1, JSGeneratorObject::kInputOrDebugPosOffset));
+  __ RecordWriteField(r1, JSGeneratorObject::kInputOrDebugPosOffset, r0, r3,
+                      kLRHasNotBeenSaved, kDontSaveFPRegs);
+
+  // Store resume mode into generator object.
+  __ str(r2, FieldMemOperand(r1, JSGeneratorObject::kResumeModeOffset));
+
+  // Load suspended function and context.
+  __ ldr(cp, FieldMemOperand(r1, JSGeneratorObject::kContextOffset));
+  __ ldr(r4, FieldMemOperand(r1, JSGeneratorObject::kFunctionOffset));
+
+  // Flood function if we are stepping.
+  Label prepare_step_in_if_stepping, prepare_step_in_suspended_generator;
+  Label stepping_prepared;
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(masm->isolate());
+  STATIC_ASSERT(StepFrame > StepIn);
+  __ mov(ip, Operand(last_step_action));
+  __ ldrsb(ip, MemOperand(ip));
+  __ cmp(ip, Operand(StepIn));
+  __ b(ge, &prepare_step_in_if_stepping);
+
+  // Flood function if we need to continue stepping in the suspended generator.
+  ExternalReference debug_suspended_generator =
+      ExternalReference::debug_suspended_generator_address(masm->isolate());
+  __ mov(ip, Operand(debug_suspended_generator));
+  __ ldr(ip, MemOperand(ip));
+  __ cmp(ip, Operand(r1));
+  __ b(eq, &prepare_step_in_suspended_generator);
+  __ bind(&stepping_prepared);
+
+  // Push receiver.
+  __ ldr(ip, FieldMemOperand(r1, JSGeneratorObject::kReceiverOffset));
+  __ Push(ip);
+
+  // ----------- S t a t e -------------
+  //  -- r1    : the JSGeneratorObject to resume
+  //  -- r2    : the resume mode (tagged)
+  //  -- r4    : generator function
+  //  -- cp    : generator context
+  //  -- lr    : return address
+  //  -- sp[0] : generator receiver
+  // -----------------------------------
+
+  // Push holes for arguments to generator function. Since the parser forced
+  // context allocation for any variables in generators, the actual argument
+  // values have already been copied into the context and these dummy values
+  // will never be used.
+  __ ldr(r3, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+  __ ldr(r3,
+         FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
+  {
+    Label done_loop, loop;
+    __ bind(&loop);
+    __ sub(r3, r3, Operand(Smi::FromInt(1)), SetCC);
+    __ b(mi, &done_loop);
+    __ PushRoot(Heap::kTheHoleValueRootIndex);
+    __ b(&loop);
+    __ bind(&done_loop);
+  }
+
+  // Dispatch on the kind of generator object.
+  Label old_generator;
+  __ ldr(r3, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+  __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kFunctionDataOffset));
+  __ CompareObjectType(r3, r3, r3, BYTECODE_ARRAY_TYPE);
+  __ b(ne, &old_generator);
+
+  // New-style (ignition/turbofan) generator object
+  {
+    __ ldr(r0, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+    __ ldr(r0,
+         FieldMemOperand(r0, SharedFunctionInfo::kFormalParameterCountOffset));
+    __ SmiUntag(r0);
+    // We abuse new.target both to indicate that this is a resume call and to
+    // pass in the generator object.  In ordinary calls, new.target is always
+    // undefined because generator functions are non-constructable.
+    __ Move(r3, r1);
+    __ Move(r1, r4);
+    __ ldr(r5, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
+    __ Jump(r5);
+  }
+
+  // Old-style (full-codegen) generator object
+  __ bind(&old_generator);
+  {
+    // Enter a new JavaScript frame, and initialize its slots as they were when
+    // the generator was suspended.
+    DCHECK(!FLAG_enable_embedded_constant_pool);
+    FrameScope scope(masm, StackFrame::MANUAL);
+    __ Push(lr, fp);
+    __ Move(fp, sp);
+    __ Push(cp, r4);
+
+    // Restore the operand stack.
+    __ ldr(r0, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset));
+    __ ldr(r3, FieldMemOperand(r0, FixedArray::kLengthOffset));
+    __ add(r0, r0, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+    __ add(r3, r0, Operand(r3, LSL, kPointerSizeLog2 - 1));
+    {
+      Label done_loop, loop;
+      __ bind(&loop);
+      __ cmp(r0, r3);
+      __ b(eq, &done_loop);
+      __ ldr(ip, MemOperand(r0, kPointerSize, PostIndex));
+      __ Push(ip);
+      __ b(&loop);
+      __ bind(&done_loop);
+    }
+
+    // Reset operand stack so we don't leak.
+    __ LoadRoot(ip, Heap::kEmptyFixedArrayRootIndex);
+    __ str(ip, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset));
+
+    // Resume the generator function at the continuation.
+    __ ldr(r3, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+    __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset));
+    __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
+    __ ldr(r2, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset));
+    __ add(r3, r3, Operand(r2, ASR, 1));
+    __ mov(r2, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
+    __ str(r2, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset));
+    __ Move(r0, r1);  // Continuation expects generator object in r0.
+    __ Jump(r3);
+  }
+
+  __ bind(&prepare_step_in_if_stepping);
+  {
+    FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
+    __ Push(r1, r2, r4);
+    __ CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
+    __ Pop(r1, r2);
+    __ ldr(r4, FieldMemOperand(r1, JSGeneratorObject::kFunctionOffset));
+  }
+  __ b(&stepping_prepared);
+
+  __ bind(&prepare_step_in_suspended_generator);
+  {
+    FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
+    __ Push(r1, r2);
+    __ CallRuntime(Runtime::kDebugPrepareStepInSuspendedGenerator);
+    __ Pop(r1, r2);
+    __ ldr(r4, FieldMemOperand(r1, JSGeneratorObject::kFunctionOffset));
+  }
+  __ b(&stepping_prepared);
+}
 
 void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
   FrameScope scope(masm, StackFrame::INTERNAL);
@@ -832,6 +967,21 @@
   Generate_JSEntryTrampolineHelper(masm, true);
 }
 
+static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch) {
+  Register args_count = scratch;
+
+  // Get the arguments + receiver count.
+  __ ldr(args_count,
+         MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
+  __ ldr(args_count,
+         FieldMemOperand(args_count, BytecodeArray::kParameterSizeOffset));
+
+  // Leave the frame (also dropping the register file).
+  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+
+  // Drop receiver + arguments.
+  __ add(sp, sp, args_count, LeaveCC);
+}
 
 // Generate code for entering a JS function with the interpreter.
 // On entry to the function the receiver and arguments have been pushed on the
@@ -850,14 +1000,16 @@
 // The function builds an interpreter frame.  See InterpreterFrameConstants in
 // frames.h for its layout.
 void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
+  ProfileEntryHookStub::MaybeCallEntryHook(masm);
+
   // Open a frame scope to indicate that there is a frame on the stack.  The
   // MANUAL indicates that the scope shouldn't actually generate code to set up
   // the frame (that is done below).
   FrameScope frame_scope(masm, StackFrame::MANUAL);
   __ PushStandardFrame(r1);
 
-  // Get the bytecode array from the function object and load the pointer to the
-  // first entry into kInterpreterBytecodeRegister.
+  // Get the bytecode array from the function object (or from the DebugInfo if
+  // it is present) and load it into kInterpreterBytecodeArrayRegister.
   __ ldr(r0, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
   Register debug_info = kInterpreterBytecodeArrayRegister;
   DCHECK(!debug_info.is(r0));
@@ -869,8 +1021,12 @@
   __ ldr(kInterpreterBytecodeArrayRegister,
          FieldMemOperand(debug_info, DebugInfo::kAbstractCodeIndex), ne);
 
+  // Check function data field is actually a BytecodeArray object.
+  Label bytecode_array_not_present;
+  __ CompareRoot(kInterpreterBytecodeArrayRegister,
+                 Heap::kUndefinedValueRootIndex);
+  __ b(eq, &bytecode_array_not_present);
   if (FLAG_debug_code) {
-    // Check function data field is actually a BytecodeArray object.
     __ SmiTst(kInterpreterBytecodeArrayRegister);
     __ Assert(ne, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
     __ CompareObjectType(kInterpreterBytecodeArrayRegister, r0, no_reg,
@@ -878,8 +1034,12 @@
     __ Assert(eq, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
   }
 
-  // Push new.target, bytecode array and zero for bytecode array offset.
-  __ mov(r0, Operand(0));
+  // Load the initial bytecode offset.
+  __ mov(kInterpreterBytecodeOffsetRegister,
+         Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
+
+  // Push new.target, bytecode array and Smi tagged bytecode array offset.
+  __ SmiTag(r0, kInterpreterBytecodeOffsetRegister);
   __ Push(r3, kInterpreterBytecodeArrayRegister, r0);
 
   // Allocate the local and temporary register file on the stack.
@@ -911,18 +1071,8 @@
     __ b(&loop_header, ge);
   }
 
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's prologue:
-  //  - Call ProfileEntryHookStub when isolate has a function_entry_hook.
-  //  - Code aging of the BytecodeArray object.
-
-  // Load accumulator, register file, bytecode offset, dispatch table into
-  // registers.
+  // Load accumulator and dispatch table into registers.
   __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
-  __ add(kInterpreterRegisterFileRegister, fp,
-         Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
-  __ mov(kInterpreterBytecodeOffsetRegister,
-         Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
   __ mov(kInterpreterDispatchTableRegister,
          Operand(ExternalReference::interpreter_dispatch_table_address(
              masm->isolate())));
@@ -932,36 +1082,51 @@
                          kInterpreterBytecodeOffsetRegister));
   __ ldr(ip, MemOperand(kInterpreterDispatchTableRegister, r1, LSL,
                         kPointerSizeLog2));
-  // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
-  // and header removal.
-  __ add(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Call(ip);
+  masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
 
-  // Even though the first bytecode handler was called, we will never return.
-  __ Abort(kUnexpectedReturnFromBytecodeHandler);
+  // The return value is in r0.
+  LeaveInterpreterFrame(masm, r2);
+  __ Jump(lr);
+
+  // If the bytecode array is no longer present, then the underlying function
+  // has been switched to a different kind of code and we heal the closure by
+  // switching the code entry field over to the new code object as well.
+  __ bind(&bytecode_array_not_present);
+  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+  __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
+  __ ldr(r4, FieldMemOperand(r4, SharedFunctionInfo::kCodeOffset));
+  __ add(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ str(r4, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
+  __ RecordWriteCodeEntryField(r1, r4, r5);
+  __ Jump(r4);
 }
 
+void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) {
+  // Save the function and context for call to CompileBaseline.
+  __ ldr(r1, MemOperand(fp, StandardFrameConstants::kFunctionOffset));
+  __ ldr(kContextRegister,
+         MemOperand(fp, StandardFrameConstants::kContextOffset));
 
-void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's EmitReturnSequence.
-  //  - Supporting FLAG_trace for Runtime::TraceExit.
-  //  - Support profiler (specifically decrementing profiling_counter
-  //    appropriately and calling out to HandleInterrupts if necessary).
+  // Leave the frame before recompiling for baseline so that we don't count as
+  // an activation on the stack.
+  LeaveInterpreterFrame(masm, r2);
 
-  // The return value is in accumulator, which is already in r0.
+  {
+    FrameScope frame_scope(masm, StackFrame::INTERNAL);
+    // Push return value.
+    __ push(r0);
 
-  // Leave the frame (also dropping the register file).
-  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+    // Push function as argument and compile for baseline.
+    __ push(r1);
+    __ CallRuntime(Runtime::kCompileBaseline);
 
-  // Drop receiver + arguments and return.
-  __ ldr(ip, FieldMemOperand(kInterpreterBytecodeArrayRegister,
-                             BytecodeArray::kParameterSizeOffset));
-  __ add(sp, sp, ip, LeaveCC);
+    // Restore return value.
+    __ pop(r0);
+  }
   __ Jump(lr);
 }
 
-
 static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register index,
                                          Register limit, Register scratch) {
   Label loop_header, loop_check;
@@ -974,7 +1139,6 @@
   __ b(gt, &loop_header);
 }
 
-
 // static
 void Builtins::Generate_InterpreterPushArgsAndCallImpl(
     MacroAssembler* masm, TailCallMode tail_call_mode) {
@@ -1000,7 +1164,6 @@
           RelocInfo::CODE_TARGET);
 }
 
-
 // static
 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
   // ----------- S t a t e -------------
@@ -1025,25 +1188,24 @@
   __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
 }
 
+void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
+  // Set the return address to the correct point in the interpreter entry
+  // trampoline.
+  Smi* interpreter_entry_return_pc_offset(
+      masm->isolate()->heap()->interpreter_entry_return_pc_offset());
+  DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
+  __ Move(r2, masm->isolate()->builtins()->InterpreterEntryTrampoline());
+  __ add(lr, r2, Operand(interpreter_entry_return_pc_offset->value() +
+                         Code::kHeaderSize - kHeapObjectTag));
 
-static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
-  // Initialize register file register and dispatch table register.
-  __ add(kInterpreterRegisterFileRegister, fp,
-         Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
+  // Initialize the dispatch table register.
   __ mov(kInterpreterDispatchTableRegister,
          Operand(ExternalReference::interpreter_dispatch_table_address(
              masm->isolate())));
 
-  // Get the context from the frame.
-  __ ldr(kContextRegister,
-         MemOperand(kInterpreterRegisterFileRegister,
-                    InterpreterFrameConstants::kContextFromRegisterPointer));
-
   // Get the bytecode array pointer from the frame.
-  __ ldr(
-      kInterpreterBytecodeArrayRegister,
-      MemOperand(kInterpreterRegisterFileRegister,
-                 InterpreterFrameConstants::kBytecodeArrayFromRegisterPointer));
+  __ ldr(kInterpreterBytecodeArrayRegister,
+         MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
 
   if (FLAG_debug_code) {
     // Check function data field is actually a BytecodeArray object.
@@ -1056,9 +1218,7 @@
 
   // Get the target bytecode offset from the frame.
   __ ldr(kInterpreterBytecodeOffsetRegister,
-         MemOperand(
-             kInterpreterRegisterFileRegister,
-             InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
+         MemOperand(fp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
   __ SmiUntag(kInterpreterBytecodeOffsetRegister);
 
   // Dispatch to the target bytecode.
@@ -1066,63 +1226,185 @@
                          kInterpreterBytecodeOffsetRegister));
   __ ldr(ip, MemOperand(kInterpreterDispatchTableRegister, r1, LSL,
                         kPointerSizeLog2));
-  __ add(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ mov(pc, ip);
 }
 
-
-static void Generate_InterpreterNotifyDeoptimizedHelper(
-    MacroAssembler* masm, Deoptimizer::BailoutType type) {
-  // Enter an internal frame.
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Pass the deoptimization type to the runtime system.
-    __ mov(r1, Operand(Smi::FromInt(static_cast<int>(type))));
-    __ push(r1);
-    __ CallRuntime(Runtime::kNotifyDeoptimized);
-    // Tear down internal frame.
-  }
-
-  // Drop state (we don't use these for interpreter deopts) and and pop the
-  // accumulator value into the accumulator register.
-  __ Drop(1);
-  __ Pop(kInterpreterAccumulatorRegister);
-
-  // Enter the bytecode dispatch.
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-
-void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
-}
-
-
-void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
-}
-
-
-void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
-}
-
-void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
-  // Set the address of the interpreter entry trampoline as a return address.
-  // This simulates the initial call to bytecode handlers in interpreter entry
-  // trampoline. The return will never actually be taken, but our stack walker
-  // uses this address to determine whether a frame is interpreted.
-  __ Move(lr, masm->isolate()->builtins()->InterpreterEntryTrampoline());
-
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-
 void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r0 : argument count (preserved for callee)
+  //  -- r3 : new target (preserved for callee)
+  //  -- r1 : target function (preserved for callee)
+  // -----------------------------------
+  // First lookup code, maybe we don't need to compile!
+  Label gotta_call_runtime, gotta_call_runtime_no_stack;
+  Label maybe_call_runtime;
+  Label try_shared;
+  Label loop_top, loop_bottom;
+
+  Register argument_count = r0;
+  Register closure = r1;
+  Register new_target = r3;
+  __ push(argument_count);
+  __ push(new_target);
+  __ push(closure);
+
+  Register map = argument_count;
+  Register index = r2;
+  __ ldr(map, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ ldr(map,
+         FieldMemOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset));
+  __ ldr(index, FieldMemOperand(map, FixedArray::kLengthOffset));
+  __ cmp(index, Operand(Smi::FromInt(2)));
+  __ b(lt, &gotta_call_runtime);
+
+  // Find literals.
+  // r3  : native context
+  // r2  : length / index
+  // r0  : optimized code map
+  // stack[0] : new target
+  // stack[4] : closure
+  Register native_context = r3;
+  __ ldr(native_context, NativeContextMemOperand());
+
+  __ bind(&loop_top);
+  Register temp = r1;
+  Register array_pointer = r5;
+
+  // Does the native context match?
+  __ add(array_pointer, map, Operand::PointerOffsetFromSmiKey(index));
+  __ ldr(temp, FieldMemOperand(array_pointer,
+                               SharedFunctionInfo::kOffsetToPreviousContext));
+  __ ldr(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
+  __ cmp(temp, native_context);
+  __ b(ne, &loop_bottom);
+  // OSR id set to none?
+  __ ldr(temp, FieldMemOperand(array_pointer,
+                               SharedFunctionInfo::kOffsetToPreviousOsrAstId));
+  const int bailout_id = BailoutId::None().ToInt();
+  __ cmp(temp, Operand(Smi::FromInt(bailout_id)));
+  __ b(ne, &loop_bottom);
+
+  // Literals available?
+  Label got_literals, maybe_cleared_weakcell;
+  __ ldr(temp, FieldMemOperand(array_pointer,
+                               SharedFunctionInfo::kOffsetToPreviousLiterals));
+  // temp contains either a WeakCell pointing to the literals array or the
+  // literals array directly.
+  STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
+  __ ldr(r4, FieldMemOperand(temp, WeakCell::kValueOffset));
+  __ JumpIfSmi(r4, &maybe_cleared_weakcell);
+  // r4 is a pointer, therefore temp is a WeakCell pointing to a literals array.
+  __ ldr(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
+  __ jmp(&got_literals);
+
+  // r4 is a smi. If it's 0, then we are looking at a cleared WeakCell
+  // around the literals array, and we should visit the runtime. If it's > 0,
+  // then temp already contains the literals array.
+  __ bind(&maybe_cleared_weakcell);
+  __ cmp(r4, Operand(Smi::FromInt(0)));
+  __ b(eq, &gotta_call_runtime);
+
+  // Save the literals in the closure.
+  __ bind(&got_literals);
+  __ ldr(r4, MemOperand(sp, 0));
+  __ str(temp, FieldMemOperand(r4, JSFunction::kLiteralsOffset));
+  __ push(index);
+  __ RecordWriteField(r4, JSFunction::kLiteralsOffset, temp, index,
+                      kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  __ pop(index);
+
+  // Code available?
+  Register entry = r4;
+  __ ldr(entry,
+         FieldMemOperand(array_pointer,
+                         SharedFunctionInfo::kOffsetToPreviousCachedCode));
+  __ ldr(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &maybe_call_runtime);
+
+  // Found literals and code. Get them into the closure and return.
+  __ pop(closure);
+  // Store code entry in the closure.
+  __ add(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+
+  Label install_optimized_code_and_tailcall;
+  __ bind(&install_optimized_code_and_tailcall);
+  __ str(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
+  __ RecordWriteCodeEntryField(closure, entry, r5);
+
+  // Link the closure into the optimized function list.
+  // r4 : code entry
+  // r3 : native context
+  // r1 : closure
+  __ ldr(r5,
+         ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
+  __ str(r5, FieldMemOperand(closure, JSFunction::kNextFunctionLinkOffset));
+  __ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, r5, r0,
+                      kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  const int function_list_offset =
+      Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
+  __ str(closure,
+         ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
+  // Save closure before the write barrier.
+  __ mov(r5, closure);
+  __ RecordWriteContextSlot(native_context, function_list_offset, closure, r0,
+                            kLRHasNotBeenSaved, kDontSaveFPRegs);
+  __ mov(closure, r5);
+  __ pop(new_target);
+  __ pop(argument_count);
+  __ Jump(entry);
+
+  __ bind(&loop_bottom);
+  __ sub(index, index, Operand(Smi::FromInt(SharedFunctionInfo::kEntryLength)));
+  __ cmp(index, Operand(Smi::FromInt(1)));
+  __ b(gt, &loop_top);
+
+  // We found neither literals nor code.
+  __ jmp(&gotta_call_runtime);
+
+  __ bind(&maybe_call_runtime);
+  __ pop(closure);
+
+  // Last possibility. Check the context free optimized code map entry.
+  __ ldr(entry, FieldMemOperand(map, FixedArray::kHeaderSize +
+                                         SharedFunctionInfo::kSharedCodeIndex));
+  __ ldr(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &try_shared);
+
+  // Store code entry in the closure.
+  __ add(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ jmp(&install_optimized_code_and_tailcall);
+
+  __ bind(&try_shared);
+  __ pop(new_target);
+  __ pop(argument_count);
+  // Is the full code valid?
+  __ ldr(entry,
+         FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ ldr(entry, FieldMemOperand(entry, SharedFunctionInfo::kCodeOffset));
+  __ ldr(r5, FieldMemOperand(entry, Code::kFlagsOffset));
+  __ and_(r5, r5, Operand(Code::KindField::kMask));
+  __ mov(r5, Operand(r5, LSR, Code::KindField::kShift));
+  __ cmp(r5, Operand(Code::BUILTIN));
+  __ b(eq, &gotta_call_runtime_no_stack);
+  // Yes, install the full code.
+  __ add(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ str(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
+  __ RecordWriteCodeEntryField(closure, entry, r5);
+  __ Jump(entry);
+
+  __ bind(&gotta_call_runtime);
+  __ pop(closure);
+  __ pop(new_target);
+  __ pop(argument_count);
+  __ bind(&gotta_call_runtime_no_stack);
   GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
 }
 
+void Builtins::Generate_CompileBaseline(MacroAssembler* masm) {
+  GenerateTailCallToReturnedCode(masm, Runtime::kCompileBaseline);
+}
 
 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
   GenerateTailCallToReturnedCode(masm,
@@ -1252,14 +1534,17 @@
   __ SmiUntag(r6);
   // Switch on the state.
   Label with_tos_register, unknown_state;
-  __ cmp(r6, Operand(FullCodeGenerator::NO_REGISTERS));
+  __ cmp(r6,
+         Operand(static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS)));
   __ b(ne, &with_tos_register);
   __ add(sp, sp, Operand(1 * kPointerSize));  // Remove state.
   __ Ret();
 
   __ bind(&with_tos_register);
+  DCHECK_EQ(kInterpreterAccumulatorRegister.code(), r0.code());
   __ ldr(r0, MemOperand(sp, 1 * kPointerSize));
-  __ cmp(r6, Operand(FullCodeGenerator::TOS_REG));
+  __ cmp(r6,
+         Operand(static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER)));
   __ b(ne, &unknown_state);
   __ add(sp, sp, Operand(2 * kPointerSize));  // Remove state.
   __ Ret();
@@ -1431,6 +1716,9 @@
 void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
                                                int field_index) {
   // ----------- S t a t e -------------
+  //  -- r0    : number of arguments
+  //  -- r1    : function
+  //  -- cp    : context
   //  -- lr    : return address
   //  -- sp[0] : receiver
   // -----------------------------------
@@ -1440,7 +1728,7 @@
   {
     __ Pop(r0);
     __ JumpIfSmi(r0, &receiver_not_date);
-    __ CompareObjectType(r0, r1, r2, JS_DATE_TYPE);
+    __ CompareObjectType(r0, r2, r3, JS_DATE_TYPE);
     __ b(ne, &receiver_not_date);
   }
 
@@ -1470,29 +1758,14 @@
 
   // 3. Raise a TypeError if the receiver is not a date.
   __ bind(&receiver_not_date);
-  __ TailCallRuntime(Runtime::kThrowNotDateError);
-}
-
-// static
-void Builtins::Generate_FunctionHasInstance(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- r0    : argc
-  //  -- sp[0] : first argument (left-hand side)
-  //  -- sp[4] : receiver (right-hand side)
-  // -----------------------------------
-
   {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-    __ ldr(InstanceOfDescriptor::LeftRegister(),
-           MemOperand(fp, 2 * kPointerSize));  // Load left-hand side.
-    __ ldr(InstanceOfDescriptor::RightRegister(),
-           MemOperand(fp, 3 * kPointerSize));  // Load right-hand side.
-    InstanceOfStub stub(masm->isolate(), true);
-    __ CallStub(&stub);
+    FrameScope scope(masm, StackFrame::MANUAL);
+    __ Push(r0, lr, fp);
+    __ Move(fp, sp);
+    __ Push(cp, r1);
+    __ Push(Smi::FromInt(0));
+    __ CallRuntime(Runtime::kThrowNotDateError);
   }
-
-  // Pop the argument and the receiver.
-  __ Ret(2);
 }
 
 // static
@@ -2387,6 +2660,97 @@
           RelocInfo::CODE_TARGET);
 }
 
+// static
+void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r1 : requested object size (untagged)
+  //  -- lr : return address
+  // -----------------------------------
+  __ SmiTag(r1);
+  __ Push(r1);
+  __ Move(cp, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInNewSpace);
+}
+
+// static
+void Builtins::Generate_AllocateInOldSpace(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r1 : requested object size (untagged)
+  //  -- lr : return address
+  // -----------------------------------
+  __ SmiTag(r1);
+  __ Move(r2, Smi::FromInt(AllocateTargetSpace::encode(OLD_SPACE)));
+  __ Push(r1, r2);
+  __ Move(cp, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInTargetSpace);
+}
+
+// static
+void Builtins::Generate_StringToNumber(MacroAssembler* masm) {
+  // The StringToNumber stub takes one argument in r0.
+  __ AssertString(r0);
+
+  // Check if string has a cached array index.
+  Label runtime;
+  __ ldr(r2, FieldMemOperand(r0, String::kHashFieldOffset));
+  __ tst(r2, Operand(String::kContainsCachedArrayIndexMask));
+  __ b(ne, &runtime);
+  __ IndexFromHash(r2, r0);
+  __ Ret();
+
+  __ bind(&runtime);
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ Push(r0);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kStringToNumber);
+  }
+  __ Ret();
+}
+
+void Builtins::Generate_ToNumber(MacroAssembler* masm) {
+  // The ToNumber stub takes one argument in r0.
+  STATIC_ASSERT(kSmiTag == 0);
+  __ tst(r0, Operand(kSmiTagMask));
+  __ Ret(eq);
+
+  __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE);
+  // r0: receiver
+  // r1: receiver instance type
+  __ Ret(eq);
+
+  __ Jump(masm->isolate()->builtins()->NonNumberToNumber(),
+          RelocInfo::CODE_TARGET);
+}
+
+void Builtins::Generate_NonNumberToNumber(MacroAssembler* masm) {
+  // The NonNumberToNumber stub takes one argument in r0.
+  __ AssertNotNumber(r0);
+
+  __ CompareObjectType(r0, r1, r1, FIRST_NONSTRING_TYPE);
+  // r0: receiver
+  // r1: receiver instance type
+  __ Jump(masm->isolate()->builtins()->StringToNumber(), RelocInfo::CODE_TARGET,
+          lo);
+
+  Label not_oddball;
+  __ cmp(r1, Operand(ODDBALL_TYPE));
+  __ b(ne, &not_oddball);
+  __ ldr(r0, FieldMemOperand(r0, Oddball::kToNumberOffset));
+  __ Ret();
+  __ bind(&not_oddball);
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ Push(r0);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kToNumber);
+  }
+  __ Ret();
+}
 
 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
   // ----------- S t a t e -------------
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 31e3e95..0ef31d7 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -22,60 +22,15 @@
 namespace v8 {
 namespace internal {
 
+#define __ ACCESS_MASM(masm)
 
-static void InitializeArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  Address deopt_handler = Runtime::FunctionForId(
-      Runtime::kArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(r0, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-
-static void InitializeInternalArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  Address deopt_handler = Runtime::FunctionForId(
-      Runtime::kInternalArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(r0, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-
-void ArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 0);
-}
-
-
-void ArraySingleArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 1);
-}
-
-
-void ArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-void InternalArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0);
+void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
+  __ lsl(r5, r0, Operand(kPointerSizeLog2));
+  __ str(r1, MemOperand(sp, r5));
+  __ Push(r1);
+  __ Push(r2);
+  __ add(r0, r0, Operand(3));
+  __ TailCallRuntime(Runtime::kNewArray);
 }
 
 void FastArrayPushStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
@@ -83,20 +38,12 @@
   descriptor->Initialize(r0, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-void InternalArraySingleArgumentConstructorStub::InitializeDescriptor(
+void FastFunctionBindStub::InitializeDescriptor(
     CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1);
+  Address deopt_handler = Runtime::FunctionForId(Runtime::kFunctionBind)->entry;
+  descriptor->Initialize(r0, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-
-void InternalArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-#define __ ACCESS_MASM(masm)
-
 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
                                           Condition cond);
 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
@@ -953,7 +900,7 @@
   CEntryStub::GenerateAheadOfTime(isolate);
   StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
   StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
-  ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
+  CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate);
   CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
   CreateWeakCellStub::GenerateAheadOfTime(isolate);
   BinaryOpICStub::GenerateAheadOfTime(isolate);
@@ -1072,8 +1019,6 @@
   }
   // Result returned in r0, r1:r0 or r2:r1:r0 - do not destroy these registers!
 
-  __ VFPEnsureFPSCRState(r3);
-
   // Check result for exception sentinel.
   Label exception_returned;
   __ CompareRoot(r0, Heap::kExceptionRootIndex);
@@ -1183,7 +1128,6 @@
   __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
   // Set up the reserved register for 0.0.
   __ vmov(kDoubleRegZero, 0.0);
-  __ VFPEnsureFPSCRState(r4);
 
   // Get address of argv, see stm above.
   // r0: code entry
@@ -1333,126 +1277,6 @@
 }
 
 
-void InstanceOfStub::Generate(MacroAssembler* masm) {
-  Register const object = r1;              // Object (lhs).
-  Register const function = r0;            // Function (rhs).
-  Register const object_map = r2;          // Map of {object}.
-  Register const function_map = r3;        // Map of {function}.
-  Register const function_prototype = r4;  // Prototype of {function}.
-  Register const scratch = r5;
-
-  DCHECK(object.is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(function.is(InstanceOfDescriptor::RightRegister()));
-
-  // Check if {object} is a smi.
-  Label object_is_smi;
-  __ JumpIfSmi(object, &object_is_smi);
-
-  // Lookup the {function} and the {object} map in the global instanceof cache.
-  // Note: This is safe because we clear the global instanceof cache whenever
-  // we change the prototype of any object.
-  Label fast_case, slow_case;
-  __ ldr(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
-  __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
-  __ b(ne, &fast_case);
-  __ CompareRoot(object_map, Heap::kInstanceofCacheMapRootIndex);
-  __ b(ne, &fast_case);
-  __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
-  __ Ret();
-
-  // If {object} is a smi we can safely return false if {function} is a JS
-  // function, otherwise we have to miss to the runtime and throw an exception.
-  __ bind(&object_is_smi);
-  __ JumpIfSmi(function, &slow_case);
-  __ CompareObjectType(function, function_map, scratch, JS_FUNCTION_TYPE);
-  __ b(ne, &slow_case);
-  __ LoadRoot(r0, Heap::kFalseValueRootIndex);
-  __ Ret();
-
-  // Fast-case: The {function} must be a valid JSFunction.
-  __ bind(&fast_case);
-  __ JumpIfSmi(function, &slow_case);
-  __ CompareObjectType(function, function_map, scratch, JS_FUNCTION_TYPE);
-  __ b(ne, &slow_case);
-
-  // Go to the runtime if the function is not a constructor.
-  __ ldrb(scratch, FieldMemOperand(function_map, Map::kBitFieldOffset));
-  __ tst(scratch, Operand(1 << Map::kIsConstructor));
-  __ b(eq, &slow_case);
-
-  // Ensure that {function} has an instance prototype.
-  __ tst(scratch, Operand(1 << Map::kHasNonInstancePrototype));
-  __ b(ne, &slow_case);
-
-  // Get the "prototype" (or initial map) of the {function}.
-  __ ldr(function_prototype,
-         FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
-  __ AssertNotSmi(function_prototype);
-
-  // Resolve the prototype if the {function} has an initial map.  Afterwards the
-  // {function_prototype} will be either the JSReceiver prototype object or the
-  // hole value, which means that no instances of the {function} were created so
-  // far and hence we should return false.
-  Label function_prototype_valid;
-  __ CompareObjectType(function_prototype, scratch, scratch, MAP_TYPE);
-  __ b(ne, &function_prototype_valid);
-  __ ldr(function_prototype,
-         FieldMemOperand(function_prototype, Map::kPrototypeOffset));
-  __ bind(&function_prototype_valid);
-  __ AssertNotSmi(function_prototype);
-
-  // Update the global instanceof cache with the current {object} map and
-  // {function}.  The cached answer will be set when it is known below.
-  __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
-  __ StoreRoot(object_map, Heap::kInstanceofCacheMapRootIndex);
-
-  // Loop through the prototype chain looking for the {function} prototype.
-  // Assume true, and change to false if not found.
-  Register const object_instance_type = function_map;
-  Register const map_bit_field = function_map;
-  Register const null = scratch;
-  Register const result = r0;
-
-  Label done, loop, fast_runtime_fallback;
-  __ LoadRoot(result, Heap::kTrueValueRootIndex);
-  __ LoadRoot(null, Heap::kNullValueRootIndex);
-  __ bind(&loop);
-
-  // Check if the object needs to be access checked.
-  __ ldrb(map_bit_field, FieldMemOperand(object_map, Map::kBitFieldOffset));
-  __ tst(map_bit_field, Operand(1 << Map::kIsAccessCheckNeeded));
-  __ b(ne, &fast_runtime_fallback);
-  // Check if the current object is a Proxy.
-  __ CompareInstanceType(object_map, object_instance_type, JS_PROXY_TYPE);
-  __ b(eq, &fast_runtime_fallback);
-
-  __ ldr(object, FieldMemOperand(object_map, Map::kPrototypeOffset));
-  __ cmp(object, function_prototype);
-  __ b(eq, &done);
-  __ cmp(object, null);
-  __ ldr(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
-  __ b(ne, &loop);
-  __ LoadRoot(result, Heap::kFalseValueRootIndex);
-  __ bind(&done);
-  __ StoreRoot(result, Heap::kInstanceofCacheAnswerRootIndex);
-  __ Ret();
-
-  // Found Proxy or access check needed: Call the runtime
-  __ bind(&fast_runtime_fallback);
-  __ Push(object, function_prototype);
-  // Invalidate the instanceof cache.
-  __ Move(scratch, Smi::FromInt(0));
-  __ StoreRoot(scratch, Heap::kInstanceofCacheFunctionRootIndex);
-  __ TailCallRuntime(Runtime::kHasInPrototypeChain);
-
-  // Slow-case: Call the %InstanceOf runtime function.
-  __ bind(&slow_case);
-  __ Push(object, function);
-  __ TailCallRuntime(is_es6_instanceof() ? Runtime::kOrdinaryHasInstance
-                                         : Runtime::kInstanceOf);
-}
-
-
 void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
   Label miss;
   Register receiver = LoadDescriptor::ReceiverRegister();
@@ -1488,7 +1312,6 @@
                                           &miss,  // When not a string.
                                           &miss,  // When not a number.
                                           &miss,  // When index out of range.
-                                          STRING_INDEX_IS_ARRAY_INDEX,
                                           RECEIVER_IS_STRING);
   char_at_generator.GenerateFast(masm);
   __ Ret();
@@ -1932,6 +1755,7 @@
   // r2 : feedback vector
   // r3 : slot in feedback vector (Smi)
   Label initialize, done, miss, megamorphic, not_array_function;
+  Label done_initialize_count, done_increment_count;
 
   DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()),
             masm->isolate()->heap()->megamorphic_symbol());
@@ -1951,7 +1775,7 @@
   Register weak_value = r9;
   __ ldr(weak_value, FieldMemOperand(r5, WeakCell::kValueOffset));
   __ cmp(r1, weak_value);
-  __ b(eq, &done);
+  __ b(eq, &done_increment_count);
   __ CompareRoot(r5, Heap::kmegamorphic_symbolRootIndex);
   __ b(eq, &done);
   __ ldr(feedback_map, FieldMemOperand(r5, HeapObject::kMapOffset));
@@ -1974,7 +1798,7 @@
   __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r5);
   __ cmp(r1, r5);
   __ b(ne, &megamorphic);
-  __ jmp(&done);
+  __ jmp(&done_increment_count);
 
   __ bind(&miss);
 
@@ -2003,11 +1827,28 @@
   // slot.
   CreateAllocationSiteStub create_stub(masm->isolate());
   CallStubInRecordCallTarget(masm, &create_stub);
-  __ b(&done);
+  __ b(&done_initialize_count);
 
   __ bind(&not_array_function);
   CreateWeakCellStub weak_cell_stub(masm->isolate());
   CallStubInRecordCallTarget(masm, &weak_cell_stub);
+
+  __ bind(&done_initialize_count);
+  // Initialize the call counter.
+  __ Move(r5, Operand(Smi::FromInt(1)));
+  __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
+  __ str(r5, FieldMemOperand(r4, FixedArray::kHeaderSize + kPointerSize));
+  __ b(&done);
+
+  __ bind(&done_increment_count);
+
+  // Increment the call count for monomorphic function calls.
+  __ add(r5, r2, Operand::PointerOffsetFromSmiKey(r3));
+  __ add(r5, r5, Operand(FixedArray::kHeaderSize + kPointerSize));
+  __ ldr(r4, FieldMemOperand(r5, 0));
+  __ add(r4, r4, Operand(Smi::FromInt(1)));
+  __ str(r4, FieldMemOperand(r5, 0));
+
   __ bind(&done);
 }
 
@@ -2069,7 +1910,7 @@
   __ add(r2, r2, Operand::PointerOffsetFromSmiKey(r3));
   __ add(r2, r2, Operand(FixedArray::kHeaderSize + kPointerSize));
   __ ldr(r3, FieldMemOperand(r2, 0));
-  __ add(r3, r3, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+  __ add(r3, r3, Operand(Smi::FromInt(1)));
   __ str(r3, FieldMemOperand(r2, 0));
 
   __ mov(r2, r4);
@@ -2117,7 +1958,7 @@
   __ add(r2, r2, Operand::PointerOffsetFromSmiKey(r3));
   __ add(r2, r2, Operand(FixedArray::kHeaderSize + kPointerSize));
   __ ldr(r3, FieldMemOperand(r2, 0));
-  __ add(r3, r3, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+  __ add(r3, r3, Operand(Smi::FromInt(1)));
   __ str(r3, FieldMemOperand(r2, 0));
 
   __ bind(&call_function);
@@ -2188,7 +2029,7 @@
   __ b(ne, &miss);
 
   // Initialize the call counter.
-  __ Move(r5, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+  __ Move(r5, Operand(Smi::FromInt(1)));
   __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
   __ str(r5, FieldMemOperand(r4, FixedArray::kHeaderSize + kPointerSize));
 
@@ -2286,13 +2127,7 @@
     // index_ is consumed by runtime conversion function.
     __ Push(object_, index_);
   }
-  if (index_flags_ == STRING_INDEX_IS_NUMBER) {
-    __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero);
-  } else {
-    DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
-    // NumberToSmi discards numbers that are not exact integers.
-    __ CallRuntime(Runtime::kNumberToSmi);
-  }
+  __ CallRuntime(Runtime::kNumberToSmi);
   // Save the conversion result before the pop instructions below
   // have a chance to overwrite it.
   __ Move(index_, r0);
@@ -2622,67 +2457,13 @@
   // r3: from index (untagged)
   __ SmiTag(r3, r3);
   StringCharAtGenerator generator(r0, r3, r2, r0, &runtime, &runtime, &runtime,
-                                  STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING);
+                                  RECEIVER_IS_STRING);
   generator.GenerateFast(masm);
   __ Drop(3);
   __ Ret();
   generator.SkipSlow(masm, &runtime);
 }
 
-
-void ToNumberStub::Generate(MacroAssembler* masm) {
-  // The ToNumber stub takes one argument in r0.
-  STATIC_ASSERT(kSmiTag == 0);
-  __ tst(r0, Operand(kSmiTagMask));
-  __ Ret(eq);
-
-  __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE);
-  // r0: receiver
-  // r1: receiver instance type
-  __ Ret(eq);
-
-  NonNumberToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
-}
-
-void NonNumberToNumberStub::Generate(MacroAssembler* masm) {
-  // The NonNumberToNumber stub takes one argument in r0.
-  __ AssertNotNumber(r0);
-
-  __ CompareObjectType(r0, r1, r1, FIRST_NONSTRING_TYPE);
-  // r0: receiver
-  // r1: receiver instance type
-  StringToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub, lo);
-
-  Label not_oddball;
-  __ cmp(r1, Operand(ODDBALL_TYPE));
-  __ b(ne, &not_oddball);
-  __ ldr(r0, FieldMemOperand(r0, Oddball::kToNumberOffset));
-  __ Ret();
-  __ bind(&not_oddball);
-
-  __ Push(r0);  // Push argument.
-  __ TailCallRuntime(Runtime::kToNumber);
-}
-
-void StringToNumberStub::Generate(MacroAssembler* masm) {
-  // The StringToNumber stub takes one argument in r0.
-  __ AssertString(r0);
-
-  // Check if string has a cached array index.
-  Label runtime;
-  __ ldr(r2, FieldMemOperand(r0, String::kHashFieldOffset));
-  __ tst(r2, Operand(String::kContainsCachedArrayIndexMask));
-  __ b(ne, &runtime);
-  __ IndexFromHash(r2, r0);
-  __ Ret();
-
-  __ bind(&runtime);
-  __ Push(r0);  // Push argument.
-  __ TailCallRuntime(Runtime::kStringToNumber);
-}
-
 void ToStringStub::Generate(MacroAssembler* masm) {
   // The ToString stub takes one argument in r0.
   Label is_number;
@@ -2848,7 +2629,7 @@
   // Load r2 with the allocation site.  We stick an undefined dummy value here
   // and replace it with the real allocation site later when we instantiate this
   // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate().
-  __ Move(r2, handle(isolate()->heap()->undefined_value()));
+  __ Move(r2, isolate()->factory()->undefined_value());
 
   // Make sure that we actually patched the allocation site.
   if (FLAG_debug_code) {
@@ -3227,7 +3008,6 @@
   // GC safe. The RegExp backend also relies on this.
   __ str(lr, MemOperand(sp, 0));
   __ blx(ip);  // Call the C++ function.
-  __ VFPEnsureFPSCRState(r2);
   __ ldr(pc, MemOperand(sp, 0));
 }
 
@@ -3694,14 +3474,14 @@
 
 void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  LoadICStub stub(isolate(), state());
+  LoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate(), state());
+  KeyedLoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -3839,8 +3619,8 @@
   __ bind(&not_array);
   __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
   __ b(ne, &miss);
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::LOAD_IC, code_flags,
                                                receiver, name, feedback,
                                                receiver_map, scratch1, r9);
@@ -3984,8 +3764,8 @@
   __ bind(&not_array);
   __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
   __ b(ne, &miss);
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
   masm->isolate()->stub_cache()->GenerateProbe(
       masm, Code::STORE_IC, code_flags, receiver, key, feedback, receiver_map,
       scratch1, scratch2);
@@ -4331,19 +4111,13 @@
   }
 }
 
-
-void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
+void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
   ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
       isolate);
   ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
       isolate);
-  ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
-      isolate);
-}
-
-
-void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
-    Isolate* isolate) {
+  ArrayNArgumentsConstructorStub stub(isolate);
+  stub.GetCode();
   ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS };
   for (int i = 0; i < 2; i++) {
     // For internal arrays we only need a few things
@@ -4351,8 +4125,6 @@
     stubh1.GetCode();
     InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]);
     stubh2.GetCode();
-    InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]);
-    stubh3.GetCode();
   }
 }
 
@@ -4372,13 +4144,15 @@
     CreateArrayDispatchOneArgument(masm, mode);
 
     __ bind(&not_one_case);
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else if (argument_count() == NONE) {
     CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
   } else if (argument_count() == ONE) {
     CreateArrayDispatchOneArgument(masm, mode);
   } else if (argument_count() == MORE_THAN_ONE) {
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else {
     UNREACHABLE();
   }
@@ -4460,7 +4234,7 @@
   InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
   __ TailCallStub(&stub0, lo);
 
-  InternalArrayNArgumentsConstructorStub stubN(isolate(), kind);
+  ArrayNArgumentsConstructorStub stubN(isolate());
   __ TailCallStub(&stubN, hi);
 
   if (IsFastPackedElementsKind(kind)) {
@@ -4562,15 +4336,15 @@
   __ bind(&done_allocate);
 
   // Initialize the JSObject fields.
-  __ str(r2, MemOperand(r0, JSObject::kMapOffset));
+  __ str(r2, FieldMemOperand(r0, JSObject::kMapOffset));
   __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
-  __ str(r3, MemOperand(r0, JSObject::kPropertiesOffset));
-  __ str(r3, MemOperand(r0, JSObject::kElementsOffset));
+  __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset));
+  __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset));
   STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize);
-  __ add(r1, r0, Operand(JSObject::kHeaderSize));
+  __ add(r1, r0, Operand(JSObject::kHeaderSize - kHeapObjectTag));
 
   // ----------- S t a t e -------------
-  //  -- r0 : result (untagged)
+  //  -- r0 : result (tagged)
   //  -- r1 : result fields (untagged)
   //  -- r5 : result end (untagged)
   //  -- r2 : initial map
@@ -4588,10 +4362,6 @@
   {
     // Initialize all in-object fields with undefined.
     __ InitializeFieldsWithFiller(r1, r5, r6);
-
-    // Add the object tag to make the JSObject real.
-    STATIC_ASSERT(kHeapObjectTag == 1);
-    __ add(r0, r0, Operand(kHeapObjectTag));
     __ Ret();
   }
   __ bind(&slack_tracking);
@@ -4610,10 +4380,6 @@
     __ LoadRoot(r6, Heap::kOnePointerFillerMapRootIndex);
     __ InitializeFieldsWithFiller(r1, r5, r6);
 
-    // Add the object tag to make the JSObject real.
-    STATIC_ASSERT(kHeapObjectTag == 1);
-    __ add(r0, r0, Operand(kHeapObjectTag));
-
     // Check if we can finalize the instance size.
     STATIC_ASSERT(Map::kSlackTrackingCounterEnd == 1);
     __ tst(r3, Operand(Map::ConstructionCounter::kMask));
@@ -4640,10 +4406,10 @@
     __ CallRuntime(Runtime::kAllocateInNewSpace);
     __ Pop(r2);
   }
-  STATIC_ASSERT(kHeapObjectTag == 1);
-  __ sub(r0, r0, Operand(kHeapObjectTag));
   __ ldrb(r5, FieldMemOperand(r2, Map::kInstanceSizeOffset));
   __ add(r5, r0, Operand(r5, LSL, kPointerSizeLog2));
+  STATIC_ASSERT(kHeapObjectTag == 1);
+  __ sub(r5, r5, Operand(kHeapObjectTag));
   __ b(&done_allocate);
 
   // Fall back to %NewObject.
@@ -4662,20 +4428,20 @@
   // -----------------------------------
   __ AssertFunction(r1);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make r2 point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ mov(r2, fp);
-    __ b(&loop_entry);
-    __ bind(&loop);
+  // Make r2 point to the JavaScript frame.
+  __ mov(r2, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset));
-    __ bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ ldr(ip, MemOperand(r2, StandardFrameConstants::kFunctionOffset));
     __ cmp(ip, r1);
-    __ b(ne, &loop);
+    __ b(eq, &ok);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
   }
 
   // Check if we have rest parameters (only possible if we have an
@@ -4690,10 +4456,10 @@
   // specified by the function's internal formal parameter count.
   Label rest_parameters;
   __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
-  __ ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
-  __ ldr(r1,
-         FieldMemOperand(r1, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ sub(r0, r0, r1, SetCC);
+  __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
+  __ ldr(r3,
+         FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
+  __ sub(r0, r0, r3, SetCC);
   __ b(gt, &rest_parameters);
 
   // Return an empty rest parameter array.
@@ -4706,7 +4472,7 @@
 
     // Allocate an empty rest parameter array.
     Label allocate, done_allocate;
-    __ Allocate(JSArray::kSize, r0, r1, r2, &allocate, TAG_OBJECT);
+    __ Allocate(JSArray::kSize, r0, r1, r2, &allocate, NO_ALLOCATION_FLAGS);
     __ bind(&done_allocate);
 
     // Setup the rest parameter array in r0.
@@ -4740,15 +4506,16 @@
     // ----------- S t a t e -------------
     //  -- cp : context
     //  -- r0 : number of rest parameters (tagged)
+    //  -- r1 : function
     //  -- r2 : pointer to first rest parameters
     //  -- lr : return address
     // -----------------------------------
 
     // Allocate space for the rest parameter array plus the backing store.
     Label allocate, done_allocate;
-    __ mov(r1, Operand(JSArray::kSize + FixedArray::kHeaderSize));
-    __ add(r1, r1, Operand(r0, LSL, kPointerSizeLog2 - 1));
-    __ Allocate(r1, r3, r4, r5, &allocate, TAG_OBJECT);
+    __ mov(r6, Operand(JSArray::kSize + FixedArray::kHeaderSize));
+    __ add(r6, r6, Operand(r0, LSL, kPointerSizeLog2 - 1));
+    __ Allocate(r6, r3, r4, r5, &allocate, NO_ALLOCATION_FLAGS);
     __ bind(&done_allocate);
 
     // Setup the elements array in r3.
@@ -4780,17 +4547,25 @@
     __ mov(r0, r4);
     __ Ret();
 
-    // Fall back to %AllocateInNewSpace.
+    // Fall back to %AllocateInNewSpace (if not too big).
+    Label too_big_for_new_space;
     __ bind(&allocate);
+    __ cmp(r6, Operand(Page::kMaxRegularHeapObjectSize));
+    __ b(gt, &too_big_for_new_space);
     {
       FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
-      __ SmiTag(r1);
-      __ Push(r0, r2, r1);
+      __ SmiTag(r6);
+      __ Push(r0, r2, r6);
       __ CallRuntime(Runtime::kAllocateInNewSpace);
       __ mov(r3, r0);
       __ Pop(r0, r2);
     }
     __ jmp(&done_allocate);
+
+    // Fall back to %NewRestParameter.
+    __ bind(&too_big_for_new_space);
+    __ push(r1);
+    __ TailCallRuntime(Runtime::kNewRestParameter);
   }
 }
 
@@ -4804,23 +4579,40 @@
   // -----------------------------------
   __ AssertFunction(r1);
 
+  // Make r9 point to the JavaScript frame.
+  __ mov(r9, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
+    __ ldr(r9, MemOperand(r9, StandardFrameConstants::kCallerFPOffset));
+  }
+  if (FLAG_debug_code) {
+    Label ok;
+    __ ldr(ip, MemOperand(r9, StandardFrameConstants::kFunctionOffset));
+    __ cmp(ip, r1);
+    __ b(eq, &ok);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
+  }
+
   // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub.
   __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
   __ ldr(r2,
          FieldMemOperand(r2, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ add(r3, fp, Operand(r2, LSL, kPointerSizeLog2 - 1));
+  __ add(r3, r9, Operand(r2, LSL, kPointerSizeLog2 - 1));
   __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset));
 
   // r1 : function
   // r2 : number of parameters (tagged)
   // r3 : parameters pointer
+  // r9 : JavaScript frame pointer
   // Registers used over whole function:
   //  r5 : arguments count (tagged)
   //  r6 : mapped parameter count (tagged)
 
   // Check if the calling frame is an arguments adaptor frame.
   Label adaptor_frame, try_allocate, runtime;
-  __ ldr(r4, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+  __ ldr(r4, MemOperand(r9, StandardFrameConstants::kCallerFPOffset));
   __ ldr(r0, MemOperand(r4, CommonFrameConstants::kContextOrFrameTypeOffset));
   __ cmp(r0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
   __ b(eq, &adaptor_frame);
@@ -4863,7 +4655,7 @@
   __ add(r9, r9, Operand(JSSloppyArgumentsObject::kSize));
 
   // Do the allocation of all three objects in one go.
-  __ Allocate(r9, r0, r9, r4, &runtime, TAG_OBJECT);
+  __ Allocate(r9, r0, r9, r4, &runtime, NO_ALLOCATION_FLAGS);
 
   // r0 = address of new object(s) (tagged)
   // r2 = argument count (smi-tagged)
@@ -5009,20 +4801,20 @@
   // -----------------------------------
   __ AssertFunction(r1);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make r2 point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ mov(r2, fp);
-    __ b(&loop_entry);
-    __ bind(&loop);
+  // Make r2 point to the JavaScript frame.
+  __ mov(r2, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset));
-    __ bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ ldr(ip, MemOperand(r2, StandardFrameConstants::kFunctionOffset));
     __ cmp(ip, r1);
-    __ b(ne, &loop);
+    __ b(eq, &ok);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
   }
 
   // Check if we have an arguments adaptor frame below the function frame.
@@ -5032,9 +4824,9 @@
   __ cmp(ip, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
   __ b(eq, &arguments_adaptor);
   {
-    __ ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
+    __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
     __ ldr(r0, FieldMemOperand(
-                   r1, SharedFunctionInfo::kFormalParameterCountOffset));
+                   r4, SharedFunctionInfo::kFormalParameterCountOffset));
     __ add(r2, r2, Operand(r0, LSL, kPointerSizeLog2 - 1));
     __ add(r2, r2,
            Operand(StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize));
@@ -5052,15 +4844,16 @@
   // ----------- S t a t e -------------
   //  -- cp : context
   //  -- r0 : number of rest parameters (tagged)
+  //  -- r1 : function
   //  -- r2 : pointer to first rest parameters
   //  -- lr : return address
   // -----------------------------------
 
   // Allocate space for the strict arguments object plus the backing store.
   Label allocate, done_allocate;
-  __ mov(r1, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
-  __ add(r1, r1, Operand(r0, LSL, kPointerSizeLog2 - 1));
-  __ Allocate(r1, r3, r4, r5, &allocate, TAG_OBJECT);
+  __ mov(r6, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
+  __ add(r6, r6, Operand(r0, LSL, kPointerSizeLog2 - 1));
+  __ Allocate(r6, r3, r4, r5, &allocate, NO_ALLOCATION_FLAGS);
   __ bind(&done_allocate);
 
   // Setup the elements array in r3.
@@ -5092,44 +4885,25 @@
   __ mov(r0, r4);
   __ Ret();
 
-  // Fall back to %AllocateInNewSpace.
+  // Fall back to %AllocateInNewSpace (if not too big).
+  Label too_big_for_new_space;
   __ bind(&allocate);
+  __ cmp(r6, Operand(Page::kMaxRegularHeapObjectSize));
+  __ b(gt, &too_big_for_new_space);
   {
     FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
-    __ SmiTag(r1);
-    __ Push(r0, r2, r1);
+    __ SmiTag(r6);
+    __ Push(r0, r2, r6);
     __ CallRuntime(Runtime::kAllocateInNewSpace);
     __ mov(r3, r0);
     __ Pop(r0, r2);
   }
   __ b(&done_allocate);
-}
 
-
-void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
-  Register context = cp;
-  Register result = r0;
-  Register slot = r2;
-
-  // Go up the context chain to the script context.
-  for (int i = 0; i < depth(); ++i) {
-    __ ldr(result, ContextMemOperand(context, Context::PREVIOUS_INDEX));
-    context = result;
-  }
-
-  // Load the PropertyCell value at the specified slot.
-  __ add(result, context, Operand(slot, LSL, kPointerSizeLog2));
-  __ ldr(result, ContextMemOperand(result));
-  __ ldr(result, FieldMemOperand(result, PropertyCell::kValueOffset));
-
-  // If the result is not the_hole, return. Otherwise, handle in the runtime.
-  __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
-  __ Ret(ne);
-
-  // Fallback to runtime.
-  __ SmiTag(slot);
-  __ push(slot);
-  __ TailCallRuntime(Runtime::kLoadGlobalViaContext);
+  // Fall back to %NewStrictArguments.
+  __ bind(&too_big_for_new_space);
+  __ push(r1);
+  __ TailCallRuntime(Runtime::kNewStrictArguments);
 }
 
 
@@ -5423,7 +5197,11 @@
   STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
   STATIC_ASSERT(FCA::kIsolateIndex == 1);
   STATIC_ASSERT(FCA::kHolderIndex == 0);
-  STATIC_ASSERT(FCA::kArgsLength == 7);
+  STATIC_ASSERT(FCA::kNewTargetIndex == 7);
+  STATIC_ASSERT(FCA::kArgsLength == 8);
+
+  // new target
+  __ PushRoot(Heap::kUndefinedValueRootIndex);
 
   // context save
   __ push(context);
@@ -5457,7 +5235,7 @@
 
   // Allocate the v8::Arguments structure in the arguments' space since
   // it's not controlled by GC.
-  const int kApiStackSpace = 4;
+  const int kApiStackSpace = 3;
 
   FrameScope frame_scope(masm, StackFrame::MANUAL);
   __ EnterExitFrame(false, kApiStackSpace);
@@ -5474,9 +5252,6 @@
   // FunctionCallbackInfo::length_ = argc
   __ mov(ip, Operand(argc()));
   __ str(ip, MemOperand(r0, 2 * kPointerSize));
-  // FunctionCallbackInfo::is_construct_call_ = 0
-  __ mov(ip, Operand::Zero());
-  __ str(ip, MemOperand(r0, 3 * kPointerSize));
 
   ExternalReference thunk_ref =
       ExternalReference::invoke_function_callback(masm->isolate());
@@ -5493,8 +5268,8 @@
   }
   MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
   int stack_space = 0;
-  MemOperand is_construct_call_operand = MemOperand(sp, 4 * kPointerSize);
-  MemOperand* stack_space_operand = &is_construct_call_operand;
+  MemOperand length_operand = MemOperand(sp, 3 * kPointerSize);
+  MemOperand* stack_space_operand = &length_operand;
   stack_space = argc() + FCA::kArgsLength + 1;
   stack_space_operand = NULL;
 
@@ -5505,16 +5280,36 @@
 
 
 void CallApiGetterStub::Generate(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- sp[0]                        : name
-  //  -- sp[4 .. (4 + kArgsLength*4)] : v8::PropertyCallbackInfo::args_
-  //  -- ...
-  //  -- r2                           : api_function_address
-  // -----------------------------------
+  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
+  // name below the exit frame to make GC aware of them.
+  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
+  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
+  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
+  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
+  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
+  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
 
-  Register api_function_address = ApiGetterDescriptor::function_address();
-  DCHECK(api_function_address.is(r2));
+  Register receiver = ApiGetterDescriptor::ReceiverRegister();
+  Register holder = ApiGetterDescriptor::HolderRegister();
+  Register callback = ApiGetterDescriptor::CallbackRegister();
+  Register scratch = r4;
+  DCHECK(!AreAliased(receiver, holder, callback, scratch));
 
+  Register api_function_address = r2;
+
+  __ push(receiver);
+  // Push data from AccessorInfo.
+  __ ldr(scratch, FieldMemOperand(callback, AccessorInfo::kDataOffset));
+  __ push(scratch);
+  __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
+  __ Push(scratch, scratch);
+  __ mov(scratch, Operand(ExternalReference::isolate_address(isolate())));
+  __ Push(scratch, holder);
+  __ Push(Smi::FromInt(0));  // should_throw_on_error -> false
+  __ ldr(scratch, FieldMemOperand(callback, AccessorInfo::kNameOffset));
+  __ push(scratch);
   // v8::PropertyCallbackInfo::args_ array and name handle.
   const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
 
@@ -5534,6 +5329,10 @@
   ExternalReference thunk_ref =
       ExternalReference::invoke_accessor_getter_callback(isolate());
 
+  __ ldr(scratch, FieldMemOperand(callback, AccessorInfo::kJsGetterOffset));
+  __ ldr(api_function_address,
+         FieldMemOperand(scratch, Foreign::kForeignAddressOffset));
+
   // +3 is to skip prolog, return address and name handle.
   MemOperand return_value_operand(
       fp, (PropertyCallbackArguments::kReturnValueOffset + 3) * kPointerSize);
@@ -5541,7 +5340,6 @@
                            kStackUnwindSpace, NULL, return_value_operand, NULL);
 }
 
-
 #undef __
 
 }  // namespace internal
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 7e1a550..a7b38ff 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -16,68 +16,6 @@
 
 #define __ masm.
 
-
-#if defined(USE_SIMULATOR)
-byte* fast_exp_arm_machine_code = nullptr;
-double fast_exp_simulator(double x, Isolate* isolate) {
-  return Simulator::current(isolate)
-      ->CallFPReturnsDouble(fast_exp_arm_machine_code, x, 0);
-}
-#endif
-
-
-UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) {
-  size_t actual_size;
-  byte* buffer =
-      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
-  if (buffer == nullptr) return nullptr;
-  ExternalReference::InitializeMathExpData();
-
-  MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
-                      CodeObjectRequired::kNo);
-
-  {
-    DwVfpRegister input = d0;
-    DwVfpRegister result = d1;
-    DwVfpRegister double_scratch1 = d2;
-    DwVfpRegister double_scratch2 = d3;
-    Register temp1 = r4;
-    Register temp2 = r5;
-    Register temp3 = r6;
-
-    if (masm.use_eabi_hardfloat()) {
-      // Input value is in d0 anyway, nothing to do.
-    } else {
-      __ vmov(input, r0, r1);
-    }
-    __ Push(temp3, temp2, temp1);
-    MathExpGenerator::EmitMathExp(
-        &masm, input, result, double_scratch1, double_scratch2,
-        temp1, temp2, temp3);
-    __ Pop(temp3, temp2, temp1);
-    if (masm.use_eabi_hardfloat()) {
-      __ vmov(d0, result);
-    } else {
-      __ vmov(r0, r1, result);
-    }
-    __ Ret();
-  }
-
-  CodeDesc desc;
-  masm.GetCode(&desc);
-  DCHECK(!RelocInfo::RequiresRelocation(desc));
-
-  Assembler::FlushICache(isolate, buffer, actual_size);
-  base::OS::ProtectCode(buffer, actual_size);
-
-#if !defined(USE_SIMULATOR)
-  return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
-#else
-  fast_exp_arm_machine_code = buffer;
-  return &fast_exp_simulator;
-#endif
-}
-
 #if defined(V8_HOST_ARCH_ARM)
 MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
                                                 MemCopyUint8Function stub) {
@@ -450,6 +388,7 @@
   __ mov(lr, Operand(length, LSL, 2));
   __ add(lr, lr, Operand(FixedDoubleArray::kHeaderSize));
   __ Allocate(lr, array, elements, scratch2, &gc_required, DOUBLE_ALIGNMENT);
+  __ sub(array, array, Operand(kHeapObjectTag));
   // array: destination FixedDoubleArray, not tagged as heap object.
   __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
   // r4: source FixedArray.
@@ -594,11 +533,13 @@
   __ add(array_size, array_size, Operand(length, LSL, 1));
   __ Allocate(array_size, array, allocate_scratch, scratch, &gc_required,
               NO_ALLOCATION_FLAGS);
-  // array: destination FixedArray, not tagged as heap object
+  // array: destination FixedArray, tagged as heap object
   // Set destination FixedDoubleArray's length and map.
   __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
-  __ str(length, MemOperand(array, FixedDoubleArray::kLengthOffset));
-  __ str(scratch, MemOperand(array, HeapObject::kMapOffset));
+  __ str(length, FieldMemOperand(array, FixedDoubleArray::kLengthOffset));
+  __ str(scratch, FieldMemOperand(array, HeapObject::kMapOffset));
+
+  __ sub(array, array, Operand(kHeapObjectTag));
 
   // Prepare for conversion loop.
   Register src_elements = elements;
@@ -791,94 +732,6 @@
   __ bind(&done);
 }
 
-
-static MemOperand ExpConstant(int index, Register base) {
-  return MemOperand(base, index * kDoubleSize);
-}
-
-
-void MathExpGenerator::EmitMathExp(MacroAssembler* masm,
-                                   DwVfpRegister input,
-                                   DwVfpRegister result,
-                                   DwVfpRegister double_scratch1,
-                                   DwVfpRegister double_scratch2,
-                                   Register temp1,
-                                   Register temp2,
-                                   Register temp3) {
-  DCHECK(!input.is(result));
-  DCHECK(!input.is(double_scratch1));
-  DCHECK(!input.is(double_scratch2));
-  DCHECK(!result.is(double_scratch1));
-  DCHECK(!result.is(double_scratch2));
-  DCHECK(!double_scratch1.is(double_scratch2));
-  DCHECK(!temp1.is(temp2));
-  DCHECK(!temp1.is(temp3));
-  DCHECK(!temp2.is(temp3));
-  DCHECK(ExternalReference::math_exp_constants(0).address() != NULL);
-  DCHECK(!masm->serializer_enabled());  // External references not serializable.
-
-  Label zero, infinity, done;
-
-  __ mov(temp3, Operand(ExternalReference::math_exp_constants(0)));
-
-  __ vldr(double_scratch1, ExpConstant(0, temp3));
-  __ VFPCompareAndSetFlags(double_scratch1, input);
-  __ b(ge, &zero);
-
-  __ vldr(double_scratch2, ExpConstant(1, temp3));
-  __ VFPCompareAndSetFlags(input, double_scratch2);
-  __ b(ge, &infinity);
-
-  __ vldr(double_scratch1, ExpConstant(3, temp3));
-  __ vldr(result, ExpConstant(4, temp3));
-  __ vmul(double_scratch1, double_scratch1, input);
-  __ vadd(double_scratch1, double_scratch1, result);
-  __ VmovLow(temp2, double_scratch1);
-  __ vsub(double_scratch1, double_scratch1, result);
-  __ vldr(result, ExpConstant(6, temp3));
-  __ vldr(double_scratch2, ExpConstant(5, temp3));
-  __ vmul(double_scratch1, double_scratch1, double_scratch2);
-  __ vsub(double_scratch1, double_scratch1, input);
-  __ vsub(result, result, double_scratch1);
-  __ vmul(double_scratch2, double_scratch1, double_scratch1);
-  __ vmul(result, result, double_scratch2);
-  __ vldr(double_scratch2, ExpConstant(7, temp3));
-  __ vmul(result, result, double_scratch2);
-  __ vsub(result, result, double_scratch1);
-  // Mov 1 in double_scratch2 as math_exp_constants_array[8] == 1.
-  DCHECK(*reinterpret_cast<double*>
-         (ExternalReference::math_exp_constants(8).address()) == 1);
-  __ vmov(double_scratch2, 1);
-  __ vadd(result, result, double_scratch2);
-  __ mov(temp1, Operand(temp2, LSR, 11));
-  __ Ubfx(temp2, temp2, 0, 11);
-  __ add(temp1, temp1, Operand(0x3ff));
-
-  // Must not call ExpConstant() after overwriting temp3!
-  __ mov(temp3, Operand(ExternalReference::math_exp_log_table()));
-  __ add(temp3, temp3, Operand(temp2, LSL, 3));
-  __ ldm(ia, temp3, temp2.bit() | temp3.bit());
-  // The first word is loaded is the lower number register.
-  if (temp2.code() < temp3.code()) {
-    __ orr(temp1, temp3, Operand(temp1, LSL, 20));
-    __ vmov(double_scratch1, temp2, temp1);
-  } else {
-    __ orr(temp1, temp2, Operand(temp1, LSL, 20));
-    __ vmov(double_scratch1, temp3, temp1);
-  }
-  __ vmul(result, result, double_scratch1);
-  __ b(&done);
-
-  __ bind(&zero);
-  __ vmov(result, kDoubleRegZero);
-  __ b(&done);
-
-  __ bind(&infinity);
-  __ vldr(result, ExpConstant(2, temp3));
-
-  __ bind(&done);
-}
-
 #undef __
 
 #ifdef DEBUG
diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h
index 880825a..0086739 100644
--- a/src/arm/codegen-arm.h
+++ b/src/arm/codegen-arm.h
@@ -28,22 +28,6 @@
 };
 
 
-class MathExpGenerator : public AllStatic {
- public:
-  // Register input isn't modified. All other registers are clobbered.
-  static void EmitMathExp(MacroAssembler* masm,
-                          DwVfpRegister input,
-                          DwVfpRegister result,
-                          DwVfpRegister double_scratch1,
-                          DwVfpRegister double_scratch2,
-                          Register temp1,
-                          Register temp2,
-                          Register temp3);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MathExpGenerator);
-};
-
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/arm/deoptimizer-arm.cc b/src/arm/deoptimizer-arm.cc
index 2785b75..c569e66 100644
--- a/src/arm/deoptimizer-arm.cc
+++ b/src/arm/deoptimizer-arm.cc
@@ -66,15 +66,12 @@
     Address deopt_entry = GetDeoptimizationEntry(isolate, i, LAZY);
     // We need calls to have a predictable size in the unoptimized code, but
     // this is optimized code, so we don't have to have a predictable size.
-    int call_size_in_bytes =
-        MacroAssembler::CallSizeNotPredictableCodeSize(isolate,
-                                                       deopt_entry,
-                                                       RelocInfo::NONE32);
+    int call_size_in_bytes = MacroAssembler::CallDeoptimizerSize();
     int call_size_in_words = call_size_in_bytes / Assembler::kInstrSize;
     DCHECK(call_size_in_bytes % Assembler::kInstrSize == 0);
     DCHECK(call_size_in_bytes <= patch_size());
     CodePatcher patcher(isolate, call_address, call_size_in_words);
-    patcher.masm()->Call(deopt_entry, RelocInfo::NONE32);
+    patcher.masm()->CallDeoptimizer(deopt_entry);
     DCHECK(prev_call_address == NULL ||
            call_address >= prev_call_address + patch_size());
     DCHECK(call_address + patch_size() <= code->instruction_end());
@@ -189,8 +186,7 @@
   // Copy VFP registers to
   // double_registers_[DoubleRegister::kMaxNumAllocatableRegisters]
   int double_regs_offset = FrameDescription::double_registers_offset();
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
     int code = config->GetAllocatableDoubleCode(i);
     int dst_offset = code * kDoubleSize + double_regs_offset;
@@ -307,15 +303,50 @@
 void Deoptimizer::TableEntryGenerator::GeneratePrologue() {
   // Create a sequence of deoptimization entries.
   // Note that registers are still live when jumping to an entry.
-  Label done;
-  for (int i = 0; i < count(); i++) {
-    int start = masm()->pc_offset();
-    USE(start);
-    __ mov(ip, Operand(i));
-    __ b(&done);
-    DCHECK(masm()->pc_offset() - start == table_entry_size_);
+
+  // We need to be able to generate immediates up to kMaxNumberOfEntries. On
+  // ARMv7, we can use movw (with a maximum immediate of 0xffff). On ARMv6, we
+  // need two instructions.
+  STATIC_ASSERT((kMaxNumberOfEntries - 1) <= 0xffff);
+  if (CpuFeatures::IsSupported(ARMv7)) {
+    CpuFeatureScope scope(masm(), ARMv7);
+    Label done;
+    for (int i = 0; i < count(); i++) {
+      int start = masm()->pc_offset();
+      USE(start);
+      __ movw(ip, i);
+      __ b(&done);
+      DCHECK_EQ(table_entry_size_, masm()->pc_offset() - start);
+    }
+    __ bind(&done);
+  } else {
+    // We want to keep table_entry_size_ == 8 (since this is the common case),
+    // but we need two instructions to load most immediates over 0xff. To handle
+    // this, we set the low byte in the main table, and then set the high byte
+    // in a separate table if necessary.
+    Label high_fixes[256];
+    int high_fix_max = (count() - 1) >> 8;
+    DCHECK_GT(arraysize(high_fixes), high_fix_max);
+    for (int i = 0; i < count(); i++) {
+      int start = masm()->pc_offset();
+      USE(start);
+      __ mov(ip, Operand(i & 0xff));  // Set the low byte.
+      __ b(&high_fixes[i >> 8]);      // Jump to the secondary table.
+      DCHECK_EQ(table_entry_size_, masm()->pc_offset() - start);
+    }
+    // Generate the secondary table, to set the high byte.
+    for (int high = 1; high <= high_fix_max; high++) {
+      __ bind(&high_fixes[high]);
+      __ orr(ip, ip, Operand(high << 8));
+      // If this isn't the last entry, emit a branch to the end of the table.
+      // The last entry can just fall through.
+      if (high < high_fix_max) __ b(&high_fixes[0]);
+    }
+    // Bind high_fixes[0] last, for indices like 0x00**. This case requires no
+    // fix-up, so for (common) small tables we can jump here, then just fall
+    // through with no additional branch.
+    __ bind(&high_fixes[0]);
   }
-  __ bind(&done);
   __ push(ip);
 }
 
diff --git a/src/arm/disasm-arm.cc b/src/arm/disasm-arm.cc
index 287152a..1bb33fa 100644
--- a/src/arm/disasm-arm.cc
+++ b/src/arm/disasm-arm.cc
@@ -40,6 +40,7 @@
 namespace v8 {
 namespace internal {
 
+const auto GetRegConfig = RegisterConfiguration::Crankshaft;
 
 //------------------------------------------------------------------------------
 
@@ -755,7 +756,45 @@
           Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs");
         }
       } else {
-        Unknown(instr);  // not used by V8
+        if (instr->Bits(24, 23) == 3) {
+          if (instr->Bit(20) == 1) {
+            // ldrex
+            switch (instr->Bits(22, 21)) {
+              case 0:
+                Format(instr, "ldrex'cond 'rt, ['rn]");
+                break;
+              case 2:
+                Format(instr, "ldrexb'cond 'rt, ['rn]");
+                break;
+              case 3:
+                Format(instr, "ldrexh'cond 'rt, ['rn]");
+                break;
+              default:
+                UNREACHABLE();
+                break;
+            }
+          } else {
+            // strex
+            // The instruction is documented as strex rd, rt, [rn], but the
+            // "rt" register is using the rm bits.
+            switch (instr->Bits(22, 21)) {
+              case 0:
+                Format(instr, "strex'cond 'rd, 'rm, ['rn]");
+                break;
+              case 2:
+                Format(instr, "strexb'cond 'rd, 'rm, ['rn]");
+                break;
+              case 3:
+                Format(instr, "strexh'cond 'rd, 'rm, ['rn]");
+                break;
+              default:
+                UNREACHABLE();
+                break;
+            }
+          }
+        } else {
+          Unknown(instr);  // not used by V8
+        }
       }
     } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) {
       // ldrd, strd
@@ -1869,6 +1908,48 @@
         Unknown(instr);
       }
       break;
+    case 0x1C:
+      if ((instr->Bits(11, 9) == 0x5) && (instr->Bit(6) == 0) &&
+          (instr->Bit(4) == 0)) {
+        // VSEL* (floating-point)
+        bool dp_operation = (instr->SzValue() == 1);
+        switch (instr->Bits(21, 20)) {
+          case 0x0:
+            if (dp_operation) {
+              Format(instr, "vseleq.f64 'Dd, 'Dn, 'Dm");
+            } else {
+              Format(instr, "vseleq.f32 'Sd, 'Sn, 'Sm");
+            }
+            break;
+          case 0x1:
+            if (dp_operation) {
+              Format(instr, "vselvs.f64 'Dd, 'Dn, 'Dm");
+            } else {
+              Format(instr, "vselvs.f32 'Sd, 'Sn, 'Sm");
+            }
+            break;
+          case 0x2:
+            if (dp_operation) {
+              Format(instr, "vselge.f64 'Dd, 'Dn, 'Dm");
+            } else {
+              Format(instr, "vselge.f32 'Sd, 'Sn, 'Sm");
+            }
+            break;
+          case 0x3:
+            if (dp_operation) {
+              Format(instr, "vselgt.f64 'Dd, 'Dn, 'Dm");
+            } else {
+              Format(instr, "vselgt.f32 'Sd, 'Sn, 'Sm");
+            }
+            break;
+          default:
+            UNREACHABLE();  // Case analysis is exhaustive.
+            break;
+        }
+      } else {
+        Unknown(instr);
+      }
+      break;
     default:
       Unknown(instr);
       break;
@@ -1968,7 +2049,7 @@
 
 
 const char* NameConverter::NameOfAddress(byte* addr) const {
-  v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
+  v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
   return tmp_buffer_.start();
 }
 
@@ -1979,7 +2060,7 @@
 
 
 const char* NameConverter::NameOfCPURegister(int reg) const {
-  return v8::internal::Register::from_code(reg).ToString();
+  return v8::internal::GetRegConfig()->GetGeneralRegisterName(reg);
 }
 
 
@@ -2031,9 +2112,8 @@
     buffer[0] = '\0';
     byte* prev_pc = pc;
     pc += d.InstructionDecode(buffer, pc);
-    v8::internal::PrintF(
-        f, "%p    %08x      %s\n",
-        prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
+    v8::internal::PrintF(f, "%p    %08x      %s\n", static_cast<void*>(prev_pc),
+                         *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
   }
 }
 
diff --git a/src/arm/interface-descriptors-arm.cc b/src/arm/interface-descriptors-arm.cc
index b6cac76..fa0c040 100644
--- a/src/arm/interface-descriptors-arm.cc
+++ b/src/arm/interface-descriptors-arm.cc
@@ -13,6 +13,14 @@
 
 const Register CallInterfaceDescriptor::ContextRegister() { return cp; }
 
+void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
+    CallInterfaceDescriptorData* data, int register_parameter_count) {
+  const Register default_stub_registers[] = {r0, r1, r2, r3, r4};
+  CHECK_LE(static_cast<size_t>(register_parameter_count),
+           arraysize(default_stub_registers));
+  data->InitializePlatformSpecific(register_parameter_count,
+                                   default_stub_registers);
+}
 
 const Register LoadDescriptor::ReceiverRegister() { return r1; }
 const Register LoadDescriptor::NameRegister() { return r2; }
@@ -41,23 +49,15 @@
 const Register StoreTransitionDescriptor::MapRegister() { return r3; }
 
 
-const Register LoadGlobalViaContextDescriptor::SlotRegister() { return r2; }
-
-
 const Register StoreGlobalViaContextDescriptor::SlotRegister() { return r2; }
 const Register StoreGlobalViaContextDescriptor::ValueRegister() { return r0; }
 
 
-const Register InstanceOfDescriptor::LeftRegister() { return r1; }
-const Register InstanceOfDescriptor::RightRegister() { return r0; }
-
-
 const Register StringCompareDescriptor::LeftRegister() { return r1; }
 const Register StringCompareDescriptor::RightRegister() { return r0; }
 
-
-const Register ApiGetterDescriptor::function_address() { return r2; }
-
+const Register ApiGetterDescriptor::HolderRegister() { return r0; }
+const Register ApiGetterDescriptor::CallbackRegister() { return r3; }
 
 const Register MathPowTaggedDescriptor::exponent() { return r2; }
 
@@ -248,25 +248,27 @@
 SIMD128_TYPES(SIMD128_ALLOC_DESC)
 #undef SIMD128_ALLOC_DESC
 
-void AllocateInNewSpaceDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  Register registers[] = {r0};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-void ArrayConstructorConstantArgCountDescriptor::InitializePlatformSpecific(
+void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // register state
   // r0 -- number of arguments
   // r1 -- function
   // r2 -- allocation site with elements kind
-  Register registers[] = {r1, r2};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
+  Register registers[] = {r1, r2, r0};
+  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
+void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  // register state
+  // r0 -- number of arguments
+  // r1 -- function
+  // r2 -- allocation site with elements kind
+  Register registers[] = {r1, r2, r0};
+  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
+}
 
-void ArrayConstructorDescriptor::InitializePlatformSpecific(
+void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // stack param count needs (constructor pointer, and single argument)
   Register registers[] = {r1, r2, r0};
@@ -274,24 +276,7 @@
 }
 
 
-void InternalArrayConstructorConstantArgCountDescriptor::
-    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
-  // register state
-  // r0 -- number of arguments
-  // r1 -- constructor function
-  Register registers[] = {r1};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-void InternalArrayConstructorDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  // stack param count needs (constructor pointer, and single argument)
-  Register registers[] = {r1, r0};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-void FastArrayPushDescriptor::InitializePlatformSpecific(
+void VarArgFunctionDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // stack param count needs (arg count)
   Register registers[] = {r0};
@@ -318,6 +303,11 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
+void CountOpDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {r1};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
 
 void StringAddDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
@@ -398,9 +388,8 @@
 void InterpreterDispatchDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {
-      kInterpreterAccumulatorRegister, kInterpreterRegisterFileRegister,
-      kInterpreterBytecodeOffsetRegister, kInterpreterBytecodeArrayRegister,
-      kInterpreterDispatchTableRegister};
+      kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
+      kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
@@ -435,6 +424,16 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
+void ResumeGeneratorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {
+      r0,  // the value to pass to the generator
+      r1,  // the JSGeneratorObject to resume
+      r2   // the resume mode (tagged)
+  };
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 6af3d6c..4feadb7 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -89,17 +89,6 @@
 }
 
 
-int MacroAssembler::CallSizeNotPredictableCodeSize(Isolate* isolate,
-                                                   Address target,
-                                                   RelocInfo::Mode rmode,
-                                                   Condition cond) {
-  Instr mov_instr = cond | MOV | LeaveCC;
-  Operand mov_operand = Operand(reinterpret_cast<intptr_t>(target), rmode);
-  return kInstrSize +
-         mov_operand.instructions_required(NULL, mov_instr) * kInstrSize;
-}
-
-
 void MacroAssembler::Call(Address target,
                           RelocInfo::Mode rmode,
                           Condition cond,
@@ -131,12 +120,6 @@
   //  blx   ip
   //                      @ return address
 
-  // Statement positions are expected to be recorded when the target
-  // address is loaded. The mov method will automatically record
-  // positions when pc is the target, since this is not the case here
-  // we have to do it explicitly.
-  positions_recorder()->WriteRecordedPositions();
-
   mov(ip, Operand(reinterpret_cast<int32_t>(target), rmode));
   blx(ip, cond);
 
@@ -173,6 +156,40 @@
   Call(reinterpret_cast<Address>(code.location()), rmode, cond, mode);
 }
 
+void MacroAssembler::CallDeoptimizer(Address target) {
+  BlockConstPoolScope block_const_pool(this);
+
+  uintptr_t target_raw = reinterpret_cast<uintptr_t>(target);
+
+  // We use blx, like a call, but it does not return here. The link register is
+  // used by the deoptimizer to work out what called it.
+  if (CpuFeatures::IsSupported(ARMv7)) {
+    CpuFeatureScope scope(this, ARMv7);
+    movw(ip, target_raw & 0xffff);
+    movt(ip, (target_raw >> 16) & 0xffff);
+    blx(ip);
+  } else {
+    // We need to load a literal, but we can't use the usual constant pool
+    // because we call this from a patcher, and cannot afford the guard
+    // instruction and other administrative overhead.
+    ldr(ip, MemOperand(pc, (2 * kInstrSize) - kPcLoadDelta));
+    blx(ip);
+    dd(target_raw);
+  }
+}
+
+int MacroAssembler::CallDeoptimizerSize() {
+  // ARMv7+:
+  //    movw    ip, ...
+  //    movt    ip, ...
+  //    blx     ip              @ This never returns.
+  //
+  // ARMv6:
+  //    ldr     ip, =address
+  //    blx     ip              @ This never returns.
+  //    .word   address
+  return 3 * kInstrSize;
+}
 
 void MacroAssembler::Ret(Condition cond) {
   bx(lr, cond);
@@ -245,6 +262,11 @@
   }
 }
 
+void MacroAssembler::Move(SwVfpRegister dst, SwVfpRegister src) {
+  if (!dst.is(src)) {
+    vmov(dst, src);
+  }
+}
 
 void MacroAssembler::Move(DwVfpRegister dst, DwVfpRegister src) {
   if (!dst.is(src)) {
@@ -252,11 +274,10 @@
   }
 }
 
-
 void MacroAssembler::Mls(Register dst, Register src1, Register src2,
                          Register srcA, Condition cond) {
-  if (CpuFeatures::IsSupported(MLS)) {
-    CpuFeatureScope scope(this, MLS);
+  if (CpuFeatures::IsSupported(ARMv7)) {
+    CpuFeatureScope scope(this, ARMv7);
     mls(dst, src1, src2, srcA, cond);
   } else {
     DCHECK(!srcA.is(ip));
@@ -355,37 +376,6 @@
 }
 
 
-void MacroAssembler::Usat(Register dst, int satpos, const Operand& src,
-                          Condition cond) {
-  if (!CpuFeatures::IsSupported(ARMv7) || predictable_code_size()) {
-    DCHECK(!dst.is(pc) && !src.rm().is(pc));
-    DCHECK((satpos >= 0) && (satpos <= 31));
-
-    // These asserts are required to ensure compatibility with the ARMv7
-    // implementation.
-    DCHECK((src.shift_op() == ASR) || (src.shift_op() == LSL));
-    DCHECK(src.rs().is(no_reg));
-
-    Label done;
-    int satval = (1 << satpos) - 1;
-
-    if (cond != al) {
-      b(NegateCondition(cond), &done);  // Skip saturate if !condition.
-    }
-    if (!(src.is_reg() && dst.is(src.rm()))) {
-      mov(dst, src);
-    }
-    tst(dst, Operand(~satval));
-    b(eq, &done);
-    mov(dst, Operand::Zero(), LeaveCC, mi);  // 0 if negative.
-    mov(dst, Operand(satval), LeaveCC, pl);  // satval if positive.
-    bind(&done);
-  } else {
-    usat(dst, satpos, src, cond);
-  }
-}
-
-
 void MacroAssembler::Load(Register dst,
                           const MemOperand& src,
                           Representation r) {
@@ -872,8 +862,7 @@
   // Number of d-regs not known at snapshot time.
   DCHECK(!serializer_enabled());
   // General purpose registers are pushed last on the stack.
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   int doubles_size = config->num_allocatable_double_registers() * kDoubleSize;
   int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
   return MemOperand(sp, doubles_size + register_offset);
@@ -889,10 +878,8 @@
   // below doesn't support it yet.
   DCHECK((src.am() != PreIndex) && (src.am() != NegPreIndex));
 
-  // Generate two ldr instructions if ldrd is not available.
-  if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size() &&
-      (dst1.code() % 2 == 0) && (dst1.code() + 1 == dst2.code())) {
-    CpuFeatureScope scope(this, ARMv7);
+  // Generate two ldr instructions if ldrd is not applicable.
+  if ((dst1.code() % 2 == 0) && (dst1.code() + 1 == dst2.code())) {
     ldrd(dst1, dst2, src, cond);
   } else {
     if ((src.am() == Offset) || (src.am() == NegOffset)) {
@@ -930,10 +917,8 @@
   // below doesn't support it yet.
   DCHECK((dst.am() != PreIndex) && (dst.am() != NegPreIndex));
 
-  // Generate two str instructions if strd is not available.
-  if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size() &&
-      (src1.code() % 2 == 0) && (src1.code() + 1 == src2.code())) {
-    CpuFeatureScope scope(this, ARMv7);
+  // Generate two str instructions if strd is not applicable.
+  if ((src1.code() % 2 == 0) && (src1.code() + 1 == src2.code())) {
     strd(src1, src2, dst, cond);
   } else {
     MemOperand dst2(dst);
@@ -950,30 +935,12 @@
   }
 }
 
-
-void MacroAssembler::VFPEnsureFPSCRState(Register scratch) {
-  // If needed, restore wanted bits of FPSCR.
-  Label fpscr_done;
-  vmrs(scratch);
-  if (emit_debug_code()) {
-    Label rounding_mode_correct;
-    tst(scratch, Operand(kVFPRoundingModeMask));
-    b(eq, &rounding_mode_correct);
-    // Don't call Assert here, since Runtime_Abort could re-enter here.
-    stop("Default rounding mode not set");
-    bind(&rounding_mode_correct);
-  }
-  tst(scratch, Operand(kVFPDefaultNaNModeControlBit));
-  b(ne, &fpscr_done);
-  orr(scratch, scratch, Operand(kVFPDefaultNaNModeControlBit));
-  vmsr(scratch);
-  bind(&fpscr_done);
-}
-
-
 void MacroAssembler::VFPCanonicalizeNaN(const DwVfpRegister dst,
                                         const DwVfpRegister src,
                                         const Condition cond) {
+  // Subtracting 0.0 preserves all inputs except for signalling NaNs, which
+  // become quiet NaNs. We use vsub rather than vadd because vsub preserves -0.0
+  // inputs: -0.0 + 0.0 = 0.0, but -0.0 - 0.0 = -0.0.
   vsub(dst, src, kDoubleRegZero, cond);
 }
 
@@ -1290,9 +1257,8 @@
 
 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
   ldr(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  ldr(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset));
-  ldr(vector,
-      FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset));
+  ldr(vector, FieldMemOperand(vector, JSFunction::kLiteralsOffset));
+  ldr(vector, FieldMemOperand(vector, LiteralsArray::kFeedbackVectorOffset));
 }
 
 
@@ -1606,12 +1572,13 @@
                                              const ParameterCount& expected,
                                              const ParameterCount& actual) {
   Label skip_flooding;
-  ExternalReference step_in_enabled =
-      ExternalReference::debug_step_in_enabled_address(isolate());
-  mov(r4, Operand(step_in_enabled));
-  ldrb(r4, MemOperand(r4));
-  cmp(r4, Operand(0));
-  b(eq, &skip_flooding);
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(isolate());
+  STATIC_ASSERT(StepFrame > StepIn);
+  mov(r4, Operand(last_step_action));
+  ldrsb(r4, MemOperand(r4));
+  cmp(r4, Operand(StepIn));
+  b(lt, &skip_flooding);
   {
     FrameScope frame(this,
                      has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
@@ -2003,6 +1970,7 @@
                               Label* gc_required,
                               AllocationFlags flags) {
   DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -2090,26 +2058,29 @@
       shift += 8;
       Operand bits_operand(bits);
       DCHECK(bits_operand.instructions_required(this) == 1);
-      add(result_end, source, bits_operand, SetCC, cond);
+      add(result_end, source, bits_operand, LeaveCC, cond);
       source = result_end;
       cond = cc;
     }
   }
-  b(cs, gc_required);
+
   cmp(result_end, Operand(alloc_limit));
   b(hi, gc_required);
-  str(result_end, MemOperand(top_address));
 
-  // Tag object if requested.
-  if ((flags & TAG_OBJECT) != 0) {
-    add(result, result, Operand(kHeapObjectTag));
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    str(result_end, MemOperand(top_address));
   }
+
+  // Tag object.
+  add(result, result, Operand(kHeapObjectTag));
 }
 
 
 void MacroAssembler::Allocate(Register object_size, Register result,
                               Register result_end, Register scratch,
                               Label* gc_required, AllocationFlags flags) {
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -2185,7 +2156,7 @@
   } else {
     add(result_end, result, Operand(object_size), SetCC);
   }
-  b(cs, gc_required);
+
   cmp(result_end, Operand(alloc_limit));
   b(hi, gc_required);
 
@@ -2194,14 +2165,122 @@
     tst(result_end, Operand(kObjectAlignmentMask));
     Check(eq, kUnalignedAllocationInNewSpace);
   }
-  str(result_end, MemOperand(top_address));
-
-  // Tag object if requested.
-  if ((flags & TAG_OBJECT) != 0) {
-    add(result, result, Operand(kHeapObjectTag));
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    str(result_end, MemOperand(top_address));
   }
+
+  // Tag object.
+  add(result, result, Operand(kHeapObjectTag));
 }
 
+void MacroAssembler::FastAllocate(Register object_size, Register result,
+                                  Register result_end, Register scratch,
+                                  AllocationFlags flags) {
+  // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag
+  // is not specified. Other registers must not overlap.
+  DCHECK(!AreAliased(object_size, result, scratch, ip));
+  DCHECK(!AreAliased(result_end, result, scratch, ip));
+  DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end));
+
+  ExternalReference allocation_top =
+      AllocationUtils::GetAllocationTopReference(isolate(), flags);
+
+  Register top_address = scratch;
+  mov(top_address, Operand(allocation_top));
+  ldr(result, MemOperand(top_address));
+
+  if ((flags & DOUBLE_ALIGNMENT) != 0) {
+    // Align the next allocation. Storing the filler map without checking top is
+    // safe in new-space because the limit of the heap is aligned there.
+    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
+    and_(result_end, result, Operand(kDoubleAlignmentMask), SetCC);
+    Label aligned;
+    b(eq, &aligned);
+    mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
+    str(result_end, MemOperand(result, kDoubleSize / 2, PostIndex));
+    bind(&aligned);
+  }
+
+  // Calculate new top using result. Object size may be in words so a shift is
+  // required to get the number of bytes.
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    add(result_end, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC);
+  } else {
+    add(result_end, result, Operand(object_size), SetCC);
+  }
+
+  // Update allocation top. result temporarily holds the new top.
+  if (emit_debug_code()) {
+    tst(result_end, Operand(kObjectAlignmentMask));
+    Check(eq, kUnalignedAllocationInNewSpace);
+  }
+  // The top pointer is not updated for allocation folding dominators.
+  str(result_end, MemOperand(top_address));
+
+  add(result, result, Operand(kHeapObjectTag));
+}
+
+void MacroAssembler::FastAllocate(int object_size, Register result,
+                                  Register scratch1, Register scratch2,
+                                  AllocationFlags flags) {
+  DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
+  DCHECK(!AreAliased(result, scratch1, scratch2, ip));
+
+  // Make object size into bytes.
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    object_size *= kPointerSize;
+  }
+  DCHECK_EQ(0, object_size & kObjectAlignmentMask);
+
+  ExternalReference allocation_top =
+      AllocationUtils::GetAllocationTopReference(isolate(), flags);
+
+  // Set up allocation top address register.
+  Register top_address = scratch1;
+  Register result_end = scratch2;
+  mov(top_address, Operand(allocation_top));
+  ldr(result, MemOperand(top_address));
+
+  if ((flags & DOUBLE_ALIGNMENT) != 0) {
+    // Align the next allocation. Storing the filler map without checking top is
+    // safe in new-space because the limit of the heap is aligned there.
+    STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
+    and_(result_end, result, Operand(kDoubleAlignmentMask), SetCC);
+    Label aligned;
+    b(eq, &aligned);
+    mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
+    str(result_end, MemOperand(result, kDoubleSize / 2, PostIndex));
+    bind(&aligned);
+  }
+
+  // Calculate new top using result. Object size may be in words so a shift is
+  // required to get the number of bytes. We must preserve the ip register at
+  // this point, so we cannot just use add().
+  DCHECK(object_size > 0);
+  Register source = result;
+  Condition cond = al;
+  int shift = 0;
+  while (object_size != 0) {
+    if (((object_size >> shift) & 0x03) == 0) {
+      shift += 2;
+    } else {
+      int bits = object_size & (0xff << shift);
+      object_size -= bits;
+      shift += 8;
+      Operand bits_operand(bits);
+      DCHECK(bits_operand.instructions_required(this) == 1);
+      add(result_end, source, bits_operand, LeaveCC, cond);
+      source = result_end;
+      cond = cc;
+    }
+  }
+
+  // The top pointer is not updated for allocation folding dominators.
+  str(result_end, MemOperand(top_address));
+
+  add(result, result, Operand(kHeapObjectTag));
+}
 
 void MacroAssembler::AllocateTwoByteString(Register result,
                                            Register length,
@@ -2218,12 +2297,8 @@
   and_(scratch1, scratch1, Operand(~kObjectAlignmentMask));
 
   // Allocate two-byte string in new space.
-  Allocate(scratch1,
-           result,
-           scratch2,
-           scratch3,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(scratch1, result, scratch2, scratch3, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   InitializeNewString(result,
@@ -2247,12 +2322,8 @@
   and_(scratch1, scratch1, Operand(~kObjectAlignmentMask));
 
   // Allocate one-byte string in new space.
-  Allocate(scratch1,
-           result,
-           scratch2,
-           scratch3,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(scratch1, result, scratch2, scratch3, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   InitializeNewString(result, length, Heap::kOneByteStringMapRootIndex,
@@ -2266,7 +2337,7 @@
                                                Register scratch2,
                                                Label* gc_required) {
   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result,
                       length,
@@ -2280,12 +2351,8 @@
                                                Register scratch1,
                                                Register scratch2,
                                                Label* gc_required) {
-  Allocate(ConsString::kSize,
-           result,
-           scratch1,
-           scratch2,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result, length, Heap::kConsOneByteStringMapRootIndex,
                       scratch1, scratch2);
@@ -2298,7 +2365,7 @@
                                                  Register scratch2,
                                                  Label* gc_required) {
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result,
                       length,
@@ -2314,7 +2381,7 @@
                                                  Register scratch2,
                                                  Label* gc_required) {
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result, length, Heap::kSlicedOneByteStringMapRootIndex,
                       scratch1, scratch2);
@@ -2414,12 +2481,6 @@
            DONT_DO_SMI_CHECK);
 
   vldr(double_scratch, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
-  // Force a canonical NaN.
-  if (emit_debug_code()) {
-    vmrs(ip);
-    tst(ip, Operand(kVFPDefaultNaNModeControlBit));
-    Assert(ne, kDefaultNaNModeNotSet);
-  }
   VFPCanonicalizeNaN(double_scratch);
   b(&store);
 
@@ -3129,6 +3190,17 @@
   }
 }
 
+void MacroAssembler::AssertGeneratorObject(Register object) {
+  if (emit_debug_code()) {
+    STATIC_ASSERT(kSmiTag == 0);
+    tst(object, Operand(kSmiTagMask));
+    Check(ne, kOperandIsASmiAndNotAGeneratorObject);
+    push(object);
+    CompareObjectType(object, object, object, JS_GENERATOR_OBJECT_TYPE);
+    pop(object);
+    Check(eq, kOperandIsNotAGeneratorObject);
+  }
+}
 
 void MacroAssembler::AssertReceiver(Register object) {
   if (emit_debug_code()) {
@@ -3225,12 +3297,11 @@
                                         Register scratch2,
                                         Register heap_number_map,
                                         Label* gc_required,
-                                        TaggingMode tagging_mode,
                                         MutableMode mode) {
   // Allocate an object in the heap for the heap number and tag it as a heap
   // object.
   Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
-           tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS);
+           NO_ALLOCATION_FLAGS);
 
   Heap::RootListIndex map_index = mode == MUTABLE
       ? Heap::kMutableHeapNumberMapRootIndex
@@ -3238,11 +3309,7 @@
   AssertIsRoot(heap_number_map, map_index);
 
   // Store heap number map in the allocated object.
-  if (tagging_mode == TAG_RESULT) {
-    str(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
-  } else {
-    str(heap_number_map, MemOperand(result, HeapObject::kMapOffset));
-  }
+  str(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
 }
 
 
@@ -3267,7 +3334,8 @@
   DCHECK(!result.is(value));
 
   // Allocate JSValue in new space.
-  Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required, TAG_OBJECT);
+  Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Initialize the JSValue.
   LoadGlobalFunctionInitialMap(constructor, scratch1, scratch2);
@@ -3662,7 +3730,7 @@
 
 
 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) {
-  Usat(output_reg, 8, Operand(input_reg));
+  usat(output_reg, 8, Operand(input_reg));
 }
 
 
@@ -3770,7 +3838,7 @@
     Label* no_memento_found) {
   Label map_check;
   Label top_check;
-  ExternalReference new_space_allocation_top =
+  ExternalReference new_space_allocation_top_adr =
       ExternalReference::new_space_allocation_top_address(isolate());
   const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
   const int kMementoEndOffset = kMementoMapOffset + AllocationMemento::kSize;
@@ -3780,7 +3848,9 @@
   // If the object is in new space, we need to check whether it is on the same
   // page as the current top.
   add(scratch_reg, receiver_reg, Operand(kMementoEndOffset));
-  eor(scratch_reg, scratch_reg, Operand(new_space_allocation_top));
+  mov(ip, Operand(new_space_allocation_top_adr));
+  ldr(ip, MemOperand(ip));
+  eor(scratch_reg, scratch_reg, Operand(ip));
   tst(scratch_reg, Operand(~Page::kPageAlignmentMask));
   b(eq, &top_check);
   // The object is on a different page than allocation top. Bail out if the
@@ -3796,7 +3866,9 @@
   // we are below top.
   bind(&top_check);
   add(scratch_reg, receiver_reg, Operand(kMementoEndOffset));
-  cmp(scratch_reg, Operand(new_space_allocation_top));
+  mov(ip, Operand(new_space_allocation_top_adr));
+  ldr(ip, MemOperand(ip));
+  cmp(scratch_reg, ip);
   b(gt, no_memento_found);
   // Memento map check.
   bind(&map_check);
@@ -3818,8 +3890,7 @@
   if (reg5.is_valid()) regs |= reg5.bit();
   if (reg6.is_valid()) regs |= reg6.bit();
 
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
     int code = config->GetAllocatableGeneralCode(i);
     Register candidate = Register::from_code(code);
@@ -3917,6 +3988,10 @@
     Assembler::FlushICache(masm_.isolate(), address_, size_);
   }
 
+  // Check that we don't have any pending constant pools.
+  DCHECK(masm_.pending_32_bit_constants_.empty());
+  DCHECK(masm_.pending_64_bit_constants_.empty());
+
   // Check that the code was patched as expected.
   DCHECK(masm_.pc_ == address_ + size_);
   DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index f326304..16dcd47 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -19,8 +19,8 @@
 const Register kReturnRegister2 = {Register::kCode_r2};
 const Register kJSFunctionRegister = {Register::kCode_r1};
 const Register kContextRegister = {Register::kCode_r7};
+const Register kAllocateSizeRegister = {Register::kCode_r1};
 const Register kInterpreterAccumulatorRegister = {Register::kCode_r0};
-const Register kInterpreterRegisterFileRegister = {Register::kCode_r4};
 const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_r5};
 const Register kInterpreterBytecodeArrayRegister = {Register::kCode_r6};
 const Register kInterpreterDispatchTableRegister = {Register::kCode_r8};
@@ -101,10 +101,6 @@
   int CallStubSize(CodeStub* stub,
                    TypeFeedbackId ast_id = TypeFeedbackId::None(),
                    Condition cond = al);
-  static int CallSizeNotPredictableCodeSize(Isolate* isolate,
-                                            Address target,
-                                            RelocInfo::Mode rmode,
-                                            Condition cond = al);
 
   // Jump, Call, and Ret pseudo instructions implementing inter-working.
   void Jump(Register target, Condition cond = al);
@@ -114,17 +110,19 @@
   void Call(Address target, RelocInfo::Mode rmode,
             Condition cond = al,
             TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS);
+  void Call(Handle<Code> code, RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
+            TypeFeedbackId ast_id = TypeFeedbackId::None(), Condition cond = al,
+            TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS);
   int CallSize(Handle<Code> code,
                RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
                TypeFeedbackId ast_id = TypeFeedbackId::None(),
                Condition cond = al);
-  void Call(Handle<Code> code,
-            RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
-            TypeFeedbackId ast_id = TypeFeedbackId::None(),
-            Condition cond = al,
-            TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS);
   void Ret(Condition cond = al);
 
+  // Used for patching in calls to the deoptimizer.
+  void CallDeoptimizer(Address target);
+  static int CallDeoptimizerSize();
+
   // Emit code to discard a non-negative number of pointer-sized elements
   // from the stack, clobbering only the sp register.
   void Drop(int count, Condition cond = al);
@@ -157,8 +155,6 @@
            int width,
            Condition cond = al);
   void Bfc(Register dst, Register src, int lsb, int width, Condition cond = al);
-  void Usat(Register dst, int satpos, const Operand& src,
-            Condition cond = al);
 
   void Call(Label* target);
   void Push(Register src) { push(src); }
@@ -174,6 +170,7 @@
       mov(dst, src, sbit, cond);
     }
   }
+  void Move(SwVfpRegister dst, SwVfpRegister src);
   void Move(DwVfpRegister dst, DwVfpRegister src);
 
   void Load(Register dst, const MemOperand& src, Representation r);
@@ -489,15 +486,6 @@
             const MemOperand& dst,
             Condition cond = al);
 
-  // Ensure that FPSCR contains values needed by JavaScript.
-  // We need the NaNModeControlBit to be sure that operations like
-  // vadd and vsub generate the Canonical NaN (if a NaN must be generated).
-  // In VFP3 it will be always the Canonical NaN.
-  // In VFP2 it will be either the Canonical NaN or the negative version
-  // of the Canonical NaN. It doesn't matter if we have two values. The aim
-  // is to be sure to never generate the hole NaN.
-  void VFPEnsureFPSCRState(Register scratch);
-
   // If the value is a NaN, canonicalize the value else, do nothing.
   void VFPCanonicalizeNaN(const DwVfpRegister dst,
                           const DwVfpRegister src,
@@ -792,6 +780,15 @@
   void Allocate(Register object_size, Register result, Register result_end,
                 Register scratch, Label* gc_required, AllocationFlags flags);
 
+  // FastAllocate is right now only used for folded allocations. It just
+  // increments the top pointer without checking against limit. This can only
+  // be done if it was proved earlier that the allocation will succeed.
+  void FastAllocate(int object_size, Register result, Register scratch1,
+                    Register scratch2, AllocationFlags flags);
+
+  void FastAllocate(Register object_size, Register result, Register result_end,
+                    Register scratch, AllocationFlags flags);
+
   void AllocateTwoByteString(Register result,
                              Register length,
                              Register scratch1,
@@ -826,7 +823,6 @@
                           Register scratch2,
                           Register heap_number_map,
                           Label* gc_required,
-                          TaggingMode tagging_mode = TAG_RESULT,
                           MutableMode mode = IMMUTABLE);
   void AllocateHeapNumberWithValue(Register result,
                                    DwVfpRegister value,
@@ -1326,6 +1322,10 @@
   // enabled via --debug-code.
   void AssertBoundFunction(Register object);
 
+  // Abort execution if argument is not a JSGeneratorObject,
+  // enabled via --debug-code.
+  void AssertGeneratorObject(Register object);
+
   // Abort execution if argument is not a JSReceiver, enabled via --debug-code.
   void AssertReceiver(Register object);
 
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index 6c22a0a..afe31db 100644
--- a/src/arm/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -299,8 +299,11 @@
           if (strcmp(arg1, "all") == 0) {
             for (int i = 0; i < kNumRegisters; i++) {
               value = GetRegisterValue(i);
-              PrintF("%3s: 0x%08x %10d", Register::from_code(i).ToString(),
-                     value, value);
+              PrintF(
+                  "%3s: 0x%08x %10d",
+                  RegisterConfiguration::Crankshaft()->GetGeneralRegisterName(
+                      i),
+                  value, value);
               if ((argc == 3 && strcmp(arg2, "fp") == 0) &&
                   i < 8 &&
                   (i % 2) == 0) {
@@ -387,7 +390,7 @@
         end = cur + words;
 
         while (cur < end) {
-          PrintF("  0x%08x:  0x%08x %10d",
+          PrintF("  0x%08" V8PRIxPTR ":  0x%08x %10d",
                  reinterpret_cast<intptr_t>(cur), *cur, *cur);
           HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
           int value = *cur;
@@ -449,8 +452,8 @@
         while (cur < end) {
           prev = cur;
           cur += dasm.InstructionDecode(buffer, cur);
-          PrintF("  0x%08x  %s\n",
-                 reinterpret_cast<intptr_t>(prev), buffer.start());
+          PrintF("  0x%08" V8PRIxPTR "  %s\n", reinterpret_cast<intptr_t>(prev),
+                 buffer.start());
         }
       } else if (strcmp(cmd, "gdb") == 0) {
         PrintF("relinquishing control to gdb\n");
@@ -633,9 +636,7 @@
   last_debugger_input_ = input;
 }
 
-
-void Simulator::FlushICache(v8::internal::HashMap* i_cache,
-                            void* start_addr,
+void Simulator::FlushICache(base::HashMap* i_cache, void* start_addr,
                             size_t size) {
   intptr_t start = reinterpret_cast<intptr_t>(start_addr);
   int intra_line = (start & CachePage::kLineMask);
@@ -656,10 +657,8 @@
   }
 }
 
-
-CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
-  v8::internal::HashMap::Entry* entry =
-      i_cache->LookupOrInsert(page, ICacheHash(page));
+CachePage* Simulator::GetCachePage(base::HashMap* i_cache, void* page) {
+  base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page));
   if (entry->value == NULL) {
     CachePage* new_page = new CachePage();
     entry->value = new_page;
@@ -669,9 +668,7 @@
 
 
 // Flush from start up to and not including start + size.
-void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
-                             intptr_t start,
-                             int size) {
+void Simulator::FlushOnePage(base::HashMap* i_cache, intptr_t start, int size) {
   DCHECK(size <= CachePage::kPageSize);
   DCHECK(AllOnOnePage(start, size - 1));
   DCHECK((start & CachePage::kLineMask) == 0);
@@ -683,9 +680,7 @@
   memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
 }
 
-
-void Simulator::CheckICache(v8::internal::HashMap* i_cache,
-                            Instruction* instr) {
+void Simulator::CheckICache(base::HashMap* i_cache, Instruction* instr) {
   intptr_t address = reinterpret_cast<intptr_t>(instr);
   void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
   void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
@@ -718,7 +713,7 @@
 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
   i_cache_ = isolate_->simulator_i_cache();
   if (i_cache_ == NULL) {
-    i_cache_ = new v8::internal::HashMap(&ICacheMatch);
+    i_cache_ = new base::HashMap(&ICacheMatch);
     isolate_->set_simulator_i_cache(i_cache_);
   }
   Initialize(isolate);
@@ -850,10 +845,10 @@
 
 
 // static
-void Simulator::TearDown(HashMap* i_cache, Redirection* first) {
+void Simulator::TearDown(base::HashMap* i_cache, Redirection* first) {
   Redirection::DeleteChain(first);
   if (i_cache != nullptr) {
-    for (HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
+    for (base::HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
          entry = i_cache->Next(entry)) {
       delete static_cast<CachePage*>(entry->value);
     }
@@ -1271,7 +1266,7 @@
 
 // Unsupported instructions use Format to print an error and stop execution.
 void Simulator::Format(Instruction* instr, const char* format) {
-  PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
+  PrintF("Simulator found unsupported instruction:\n 0x%08" V8PRIxPTR ": %s\n",
          reinterpret_cast<intptr_t>(instr), format);
   UNIMPLEMENTED();
 }
@@ -1808,15 +1803,17 @@
           case ExternalReference::BUILTIN_FP_FP_CALL:
           case ExternalReference::BUILTIN_COMPARE_CALL:
             PrintF("Call to host function at %p with args %f, %f",
-                   FUNCTION_ADDR(generic_target), dval0, dval1);
+                   static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
+                   dval1);
             break;
           case ExternalReference::BUILTIN_FP_CALL:
             PrintF("Call to host function at %p with arg %f",
-                FUNCTION_ADDR(generic_target), dval0);
+                   static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0);
             break;
           case ExternalReference::BUILTIN_FP_INT_CALL:
             PrintF("Call to host function at %p with args %f, %d",
-                   FUNCTION_ADDR(generic_target), dval0, ival);
+                   static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
+                   ival);
             break;
           default:
             UNREACHABLE();
@@ -1942,7 +1939,8 @@
           PrintF(
               "Call to host triple returning runtime function %p "
               "args %08x, %08x, %08x, %08x, %08x",
-              FUNCTION_ADDR(target), arg1, arg2, arg3, arg4, arg5);
+              static_cast<void*>(FUNCTION_ADDR(target)), arg1, arg2, arg3, arg4,
+              arg5);
           if (!stack_aligned) {
             PrintF(" with unaligned stack %08x\n", get_register(sp));
           }
@@ -1953,7 +1951,8 @@
         // pass it to the target function.
         ObjectTriple result = target(arg1, arg2, arg3, arg4, arg5);
         if (::v8::internal::FLAG_trace_sim) {
-          PrintF("Returned { %p, %p, %p }\n", result.x, result.y, result.z);
+          PrintF("Returned { %p, %p, %p }\n", static_cast<void*>(result.x),
+                 static_cast<void*>(result.y), static_cast<void*>(result.z));
         }
         // Return is passed back in address pointed to by hidden first argument.
         ObjectTriple* sim_result = reinterpret_cast<ObjectTriple*>(arg0);
@@ -1969,13 +1968,8 @@
           PrintF(
               "Call to host function at %p "
               "args %08x, %08x, %08x, %08x, %08x, %08x",
-              FUNCTION_ADDR(target),
-              arg0,
-              arg1,
-              arg2,
-              arg3,
-              arg4,
-              arg5);
+              static_cast<void*>(FUNCTION_ADDR(target)), arg0, arg1, arg2, arg3,
+              arg4, arg5);
           if (!stack_aligned) {
             PrintF(" with unaligned stack %08x\n", get_register(sp));
           }
@@ -4028,6 +4022,45 @@
         UNIMPLEMENTED();
       }
       break;
+    case 0x1C:
+      if ((instr->Bits(11, 9) == 0x5) && (instr->Bit(6) == 0) &&
+          (instr->Bit(4) == 0)) {
+        // VSEL* (floating-point)
+        bool condition_holds;
+        switch (instr->Bits(21, 20)) {
+          case 0x0:  // VSELEQ
+            condition_holds = (z_flag_ == 1);
+            break;
+          case 0x1:  // VSELVS
+            condition_holds = (v_flag_ == 1);
+            break;
+          case 0x2:  // VSELGE
+            condition_holds = (n_flag_ == v_flag_);
+            break;
+          case 0x3:  // VSELGT
+            condition_holds = ((z_flag_ == 0) && (n_flag_ == v_flag_));
+            break;
+          default:
+            UNREACHABLE();  // Case analysis is exhaustive.
+            break;
+        }
+        if (instr->SzValue() == 0x1) {
+          int n = instr->VFPNRegValue(kDoublePrecision);
+          int m = instr->VFPMRegValue(kDoublePrecision);
+          int d = instr->VFPDRegValue(kDoublePrecision);
+          double result = get_double_from_d_register(condition_holds ? n : m);
+          set_d_register_from_double(d, result);
+        } else {
+          int n = instr->VFPNRegValue(kSinglePrecision);
+          int m = instr->VFPMRegValue(kSinglePrecision);
+          int d = instr->VFPDRegValue(kSinglePrecision);
+          float result = get_float_from_s_register(condition_holds ? n : m);
+          set_s_register_from_float(d, result);
+        }
+      } else {
+        UNIMPLEMENTED();
+      }
+      break;
     default:
       UNIMPLEMENTED();
       break;
@@ -4048,7 +4081,8 @@
     v8::internal::EmbeddedVector<char, 256> buffer;
     dasm.InstructionDecode(buffer,
                            reinterpret_cast<byte*>(instr));
-    PrintF("  0x%08x  %s\n", reinterpret_cast<intptr_t>(instr), buffer.start());
+    PrintF("  0x%08" V8PRIxPTR "  %s\n", reinterpret_cast<intptr_t>(instr),
+           buffer.start());
   }
   if (instr->ConditionField() == kSpecialCondition) {
     DecodeSpecialCondition(instr);
diff --git a/src/arm/simulator-arm.h b/src/arm/simulator-arm.h
index b3c8eb4..71b8e40 100644
--- a/src/arm/simulator-arm.h
+++ b/src/arm/simulator-arm.h
@@ -68,7 +68,7 @@
 
 #include "src/arm/constants-arm.h"
 #include "src/assembler.h"
-#include "src/hashmap.h"
+#include "src/base/hashmap.h"
 
 namespace v8 {
 namespace internal {
@@ -200,7 +200,7 @@
   // Call on program start.
   static void Initialize(Isolate* isolate);
 
-  static void TearDown(HashMap* i_cache, Redirection* first);
+  static void TearDown(base::HashMap* i_cache, Redirection* first);
 
   // V8 generally calls into generated JS code with 5 parameters and into
   // generated RegExp code with 7 parameters. This is a convenience function,
@@ -222,8 +222,7 @@
   char* last_debugger_input() { return last_debugger_input_; }
 
   // ICache checking.
-  static void FlushICache(v8::internal::HashMap* i_cache, void* start,
-                          size_t size);
+  static void FlushICache(base::HashMap* i_cache, void* start, size_t size);
 
   // Returns true if pc register contains one of the 'special_values' defined
   // below (bad_lr, end_sim_pc).
@@ -342,10 +341,9 @@
   void InstructionDecode(Instruction* instr);
 
   // ICache.
-  static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr);
-  static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
-                           int size);
-  static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);
+  static void CheckICache(base::HashMap* i_cache, Instruction* instr);
+  static void FlushOnePage(base::HashMap* i_cache, intptr_t start, int size);
+  static CachePage* GetCachePage(base::HashMap* i_cache, void* page);
 
   // Runtime call support.
   static void* RedirectExternalReference(
@@ -405,7 +403,7 @@
   char* last_debugger_input_;
 
   // Icache simulation
-  v8::internal::HashMap* i_cache_;
+  base::HashMap* i_cache_;
 
   // Registered breakpoints.
   Instruction* break_pc_;
diff --git a/src/arm64/assembler-arm64-inl.h b/src/arm64/assembler-arm64-inl.h
index 6191216..8e46771 100644
--- a/src/arm64/assembler-arm64-inl.h
+++ b/src/arm64/assembler-arm64-inl.h
@@ -41,19 +41,6 @@
   }
 }
 
-void RelocInfo::update_wasm_memory_reference(
-    Address old_base, Address new_base, size_t old_size, size_t new_size,
-    ICacheFlushMode icache_flush_mode) {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  DCHECK(old_base <= wasm_memory_reference() &&
-         wasm_memory_reference() < old_base + old_size);
-  Address updated_reference = new_base + (wasm_memory_reference() - old_base);
-  DCHECK(new_base <= updated_reference &&
-         updated_reference < new_base + new_size);
-  Assembler::set_target_address_at(isolate_, pc_, host_, updated_reference,
-                                   icache_flush_mode);
-}
-
 inline int CPURegister::code() const {
   DCHECK(IsValid());
   return reg_code;
@@ -705,11 +692,6 @@
   return Assembler::target_address_at(pc_, host_);
 }
 
-Address RelocInfo::wasm_memory_reference() {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  return Assembler::target_address_at(pc_, host_);
-}
-
 Address RelocInfo::target_address_address() {
   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
                               || rmode_ == EMBEDDED_OBJECT
@@ -868,7 +850,7 @@
   }
 }
 
-
+template <typename ObjectVisitor>
 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
diff --git a/src/arm64/assembler-arm64.cc b/src/arm64/assembler-arm64.cc
index 2471d5e..7fd5a79 100644
--- a/src/arm64/assembler-arm64.cc
+++ b/src/arm64/assembler-arm64.cc
@@ -51,26 +51,13 @@
   // Only use statically determined features for cross compile (snapshot).
   if (cross_compile) return;
 
-  // Probe for runtime features
-  base::CPU cpu;
-  if (cpu.implementer() == base::CPU::NVIDIA &&
-      cpu.variant() == base::CPU::NVIDIA_DENVER &&
-      cpu.part() <= base::CPU::NVIDIA_DENVER_V10) {
-    // TODO(jkummerow): This is turned off as an experiment to see if it
-    // affects crash rates. Keep an eye on crash reports and either remove
-    // coherent cache support permanently, or re-enable it!
-    // supported_ |= 1u << COHERENT_CACHE;
-  }
+  // We used to probe for coherent cache support, but on older CPUs it
+  // causes crashes (crbug.com/524337), and newer CPUs don't even have
+  // the feature any more.
 }
 
-
 void CpuFeatures::PrintTarget() { }
-
-
-void CpuFeatures::PrintFeatures() {
-  printf("COHERENT_CACHE=%d\n", CpuFeatures::IsSupported(COHERENT_CACHE));
-}
-
+void CpuFeatures::PrintFeatures() {}
 
 // -----------------------------------------------------------------------------
 // CPURegList utilities.
@@ -192,12 +179,35 @@
   return instr->IsLdrLiteralX();
 }
 
+Address RelocInfo::wasm_memory_reference() {
+  DCHECK(IsWasmMemoryReference(rmode_));
+  return Memory::Address_at(Assembler::target_pointer_address_at(pc_));
+}
+
+uint32_t RelocInfo::wasm_memory_size_reference() {
+  DCHECK(IsWasmMemorySizeReference(rmode_));
+  return Memory::uint32_at(Assembler::target_pointer_address_at(pc_));
+}
+
+Address RelocInfo::wasm_global_reference() {
+  DCHECK(IsWasmGlobalReference(rmode_));
+  return Memory::Address_at(Assembler::target_pointer_address_at(pc_));
+}
+
+void RelocInfo::unchecked_update_wasm_memory_reference(
+    Address address, ICacheFlushMode flush_mode) {
+  Assembler::set_target_address_at(isolate_, pc_, host_, address, flush_mode);
+}
+
+void RelocInfo::unchecked_update_wasm_memory_size(uint32_t size,
+                                                  ICacheFlushMode flush_mode) {
+  Memory::uint32_at(Assembler::target_pointer_address_at(pc_)) = size;
+}
 
 Register GetAllocatableRegisterThatIsNotOneOf(Register reg1, Register reg2,
                                               Register reg3, Register reg4) {
   CPURegList regs(reg1, reg2, reg3, reg4);
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
     int code = config->GetAllocatableDoubleCode(i);
     Register candidate = Register::from_code(code);
@@ -294,13 +304,11 @@
 // Constant Pool.
 void ConstPool::RecordEntry(intptr_t data,
                             RelocInfo::Mode mode) {
-  DCHECK(mode != RelocInfo::COMMENT &&
-         mode != RelocInfo::POSITION &&
+  DCHECK(mode != RelocInfo::COMMENT && mode != RelocInfo::POSITION &&
          mode != RelocInfo::STATEMENT_POSITION &&
-         mode != RelocInfo::CONST_POOL &&
-         mode != RelocInfo::VENEER_POOL &&
+         mode != RelocInfo::CONST_POOL && mode != RelocInfo::VENEER_POOL &&
          mode != RelocInfo::CODE_AGE_SEQUENCE &&
-         mode != RelocInfo::DEOPT_REASON);
+         mode != RelocInfo::DEOPT_REASON && mode != RelocInfo::DEOPT_ID);
   uint64_t raw_data = static_cast<uint64_t>(data);
   int offset = assm_->pc_offset();
   if (IsEmpty()) {
@@ -594,6 +602,8 @@
                          reloc_info_writer.pos());
     desc->origin = this;
     desc->constant_pool_size = 0;
+    desc->unwinding_info_size = 0;
+    desc->unwinding_info = nullptr;
   }
 }
 
@@ -962,14 +972,12 @@
 
 
 void Assembler::br(const Register& xn) {
-  positions_recorder()->WriteRecordedPositions();
   DCHECK(xn.Is64Bits());
   Emit(BR | Rn(xn));
 }
 
 
 void Assembler::blr(const Register& xn) {
-  positions_recorder()->WriteRecordedPositions();
   DCHECK(xn.Is64Bits());
   // The pattern 'blr xzr' is used as a guard to detect when execution falls
   // through the constant pool. It should not be emitted.
@@ -979,7 +987,6 @@
 
 
 void Assembler::ret(const Register& xn) {
-  positions_recorder()->WriteRecordedPositions();
   DCHECK(xn.Is64Bits());
   Emit(RET | Rn(xn));
 }
@@ -991,7 +998,6 @@
 
 
 void Assembler::b(Label* label) {
-  positions_recorder()->WriteRecordedPositions();
   b(LinkAndGetInstructionOffsetTo(label));
 }
 
@@ -1002,47 +1008,40 @@
 
 
 void Assembler::b(Label* label, Condition cond) {
-  positions_recorder()->WriteRecordedPositions();
   b(LinkAndGetInstructionOffsetTo(label), cond);
 }
 
 
 void Assembler::bl(int imm26) {
-  positions_recorder()->WriteRecordedPositions();
   Emit(BL | ImmUncondBranch(imm26));
 }
 
 
 void Assembler::bl(Label* label) {
-  positions_recorder()->WriteRecordedPositions();
   bl(LinkAndGetInstructionOffsetTo(label));
 }
 
 
 void Assembler::cbz(const Register& rt,
                     int imm19) {
-  positions_recorder()->WriteRecordedPositions();
   Emit(SF(rt) | CBZ | ImmCmpBranch(imm19) | Rt(rt));
 }
 
 
 void Assembler::cbz(const Register& rt,
                     Label* label) {
-  positions_recorder()->WriteRecordedPositions();
   cbz(rt, LinkAndGetInstructionOffsetTo(label));
 }
 
 
 void Assembler::cbnz(const Register& rt,
                      int imm19) {
-  positions_recorder()->WriteRecordedPositions();
   Emit(SF(rt) | CBNZ | ImmCmpBranch(imm19) | Rt(rt));
 }
 
 
 void Assembler::cbnz(const Register& rt,
                      Label* label) {
-  positions_recorder()->WriteRecordedPositions();
   cbnz(rt, LinkAndGetInstructionOffsetTo(label));
 }
 
@@ -1050,7 +1049,6 @@
 void Assembler::tbz(const Register& rt,
                     unsigned bit_pos,
                     int imm14) {
-  positions_recorder()->WriteRecordedPositions();
   DCHECK(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSizeInBits)));
   Emit(TBZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
 }
@@ -1059,7 +1057,6 @@
 void Assembler::tbz(const Register& rt,
                     unsigned bit_pos,
                     Label* label) {
-  positions_recorder()->WriteRecordedPositions();
   tbz(rt, bit_pos, LinkAndGetInstructionOffsetTo(label));
 }
 
@@ -1067,7 +1064,6 @@
 void Assembler::tbnz(const Register& rt,
                      unsigned bit_pos,
                      int imm14) {
-  positions_recorder()->WriteRecordedPositions();
   DCHECK(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSizeInBits)));
   Emit(TBNZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt));
 }
@@ -1076,7 +1072,6 @@
 void Assembler::tbnz(const Register& rt,
                      unsigned bit_pos,
                      Label* label) {
-  positions_recorder()->WriteRecordedPositions();
   tbnz(rt, bit_pos, LinkAndGetInstructionOffsetTo(label));
 }
 
@@ -1696,6 +1691,83 @@
   ldr_pcrel(rt, 0);
 }
 
+void Assembler::ldar(const Register& rt, const Register& rn) {
+  DCHECK(rn.Is64Bits());
+  LoadStoreAcquireReleaseOp op = rt.Is32Bits() ? LDAR_w : LDAR_x;
+  Emit(op | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt));
+}
+
+void Assembler::ldaxr(const Register& rt, const Register& rn) {
+  DCHECK(rn.Is64Bits());
+  LoadStoreAcquireReleaseOp op = rt.Is32Bits() ? LDAXR_w : LDAXR_x;
+  Emit(op | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt));
+}
+
+void Assembler::stlr(const Register& rt, const Register& rn) {
+  DCHECK(rn.Is64Bits());
+  LoadStoreAcquireReleaseOp op = rt.Is32Bits() ? STLR_w : STLR_x;
+  Emit(op | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt));
+}
+
+void Assembler::stlxr(const Register& rs, const Register& rt,
+                      const Register& rn) {
+  DCHECK(rs.Is32Bits());
+  DCHECK(rn.Is64Bits());
+  LoadStoreAcquireReleaseOp op = rt.Is32Bits() ? STLXR_w : STLXR_x;
+  Emit(op | Rs(rs) | Rt2(x31) | Rn(rn) | Rt(rt));
+}
+
+void Assembler::ldarb(const Register& rt, const Register& rn) {
+  DCHECK(rt.Is32Bits());
+  DCHECK(rn.Is64Bits());
+  Emit(LDAR_b | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt));
+}
+
+void Assembler::ldaxrb(const Register& rt, const Register& rn) {
+  DCHECK(rt.Is32Bits());
+  DCHECK(rn.Is64Bits());
+  Emit(LDAXR_b | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt));
+}
+
+void Assembler::stlrb(const Register& rt, const Register& rn) {
+  DCHECK(rt.Is32Bits());
+  DCHECK(rn.Is64Bits());
+  Emit(STLR_b | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt));
+}
+
+void Assembler::stlxrb(const Register& rs, const Register& rt,
+                       const Register& rn) {
+  DCHECK(rs.Is32Bits());
+  DCHECK(rt.Is32Bits());
+  DCHECK(rn.Is64Bits());
+  Emit(STLXR_b | Rs(rs) | Rt2(x31) | Rn(rn) | Rt(rt));
+}
+
+void Assembler::ldarh(const Register& rt, const Register& rn) {
+  DCHECK(rt.Is32Bits());
+  DCHECK(rn.Is64Bits());
+  Emit(LDAR_h | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt));
+}
+
+void Assembler::ldaxrh(const Register& rt, const Register& rn) {
+  DCHECK(rt.Is32Bits());
+  DCHECK(rn.Is64Bits());
+  Emit(LDAXR_h | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt));
+}
+
+void Assembler::stlrh(const Register& rt, const Register& rn) {
+  DCHECK(rt.Is32Bits());
+  DCHECK(rn.Is64Bits());
+  Emit(STLR_h | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt));
+}
+
+void Assembler::stlxrh(const Register& rs, const Register& rt,
+                       const Register& rn) {
+  DCHECK(rs.Is32Bits());
+  DCHECK(rt.Is32Bits());
+  DCHECK(rn.Is64Bits());
+  Emit(STLXR_h | Rs(rs) | Rt2(x31) | Rn(rn) | Rt(rt));
+}
 
 void Assembler::mov(const Register& rd, const Register& rm) {
   // Moves involving the stack pointer are encoded as add immediate with
@@ -2878,11 +2950,12 @@
        (rmode <= RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL)) ||
       (rmode == RelocInfo::INTERNAL_REFERENCE) ||
       (rmode == RelocInfo::CONST_POOL) || (rmode == RelocInfo::VENEER_POOL) ||
-      (rmode == RelocInfo::DEOPT_REASON) ||
+      (rmode == RelocInfo::DEOPT_REASON) || (rmode == RelocInfo::DEOPT_ID) ||
       (rmode == RelocInfo::GENERATOR_CONTINUATION)) {
     // Adjust code for new modes.
     DCHECK(RelocInfo::IsDebugBreakSlot(rmode) || RelocInfo::IsComment(rmode) ||
-           RelocInfo::IsDeoptReason(rmode) || RelocInfo::IsPosition(rmode) ||
+           RelocInfo::IsDeoptReason(rmode) || RelocInfo::IsDeoptId(rmode) ||
+           RelocInfo::IsPosition(rmode) ||
            RelocInfo::IsInternalReference(rmode) ||
            RelocInfo::IsConstPool(rmode) || RelocInfo::IsVeneerPool(rmode) ||
            RelocInfo::IsGeneratorContinuation(rmode));
diff --git a/src/arm64/assembler-arm64.h b/src/arm64/assembler-arm64.h
index 5460254..cc26278 100644
--- a/src/arm64/assembler-arm64.h
+++ b/src/arm64/assembler-arm64.h
@@ -40,6 +40,12 @@
   R(x8)  R(x9)  R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \
   R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) R(x24) R(x27)
 
+#define FLOAT_REGISTERS(V)                               \
+  V(s0)  V(s1)  V(s2)  V(s3)  V(s4)  V(s5)  V(s6)  V(s7)  \
+  V(s8)  V(s9)  V(s10) V(s11) V(s12) V(s13) V(s14) V(s15) \
+  V(s16) V(s17) V(s18) V(s19) V(s20) V(s21) V(s22) V(s23) \
+  V(s24) V(s25) V(s26) V(s27) V(s28) V(s29) V(s30) V(s31)
+
 #define DOUBLE_REGISTERS(R)                               \
   R(d0)  R(d1)  R(d2)  R(d3)  R(d4)  R(d5)  R(d6)  R(d7)  \
   R(d8)  R(d9)  R(d10) R(d11) R(d12) R(d13) R(d14) R(d15) \
@@ -148,8 +154,6 @@
     DCHECK(IsValidOrNone());
   }
 
-  const char* ToString();
-  bool IsAllocatable() const;
   bool IsValid() const {
     DCHECK(IsRegister() || IsNone());
     return IsValidRegister();
@@ -189,6 +193,7 @@
   // End of V8 compatibility section -----------------------
 };
 
+static const bool kSimpleFPAliasing = true;
 
 struct FPRegister : public CPURegister {
   enum Code {
@@ -224,8 +229,6 @@
     DCHECK(IsValidOrNone());
   }
 
-  const char* ToString();
-  bool IsAllocatable() const;
   bool IsValid() const {
     DCHECK(IsFPRegister() || IsNone());
     return IsValidFPRegister();
@@ -366,7 +369,7 @@
                         const CPURegister& reg7 = NoCPUReg,
                         const CPURegister& reg8 = NoCPUReg);
 
-
+typedef FPRegister FloatRegister;
 typedef FPRegister DoubleRegister;
 
 // TODO(arm64) Define SIMD registers.
@@ -929,7 +932,7 @@
 
   // Record a deoptimization reason that can be used by a log or cpu profiler.
   // Use --trace-deopt to enable.
-  void RecordDeoptReason(const int reason, int raw_position);
+  void RecordDeoptReason(const int reason, int raw_position, int id);
 
   int buffer_space() const;
 
@@ -1395,6 +1398,42 @@
   // Load literal to register.
   void ldr(const CPURegister& rt, const Immediate& imm);
 
+  // Load-acquire word.
+  void ldar(const Register& rt, const Register& rn);
+
+  // Load-acquire exclusive word.
+  void ldaxr(const Register& rt, const Register& rn);
+
+  // Store-release word.
+  void stlr(const Register& rt, const Register& rn);
+
+  // Store-release exclusive word.
+  void stlxr(const Register& rs, const Register& rt, const Register& rn);
+
+  // Load-acquire byte.
+  void ldarb(const Register& rt, const Register& rn);
+
+  // Load-acquire exclusive byte.
+  void ldaxrb(const Register& rt, const Register& rn);
+
+  // Store-release byte.
+  void stlrb(const Register& rt, const Register& rn);
+
+  // Store-release exclusive byte.
+  void stlxrb(const Register& rs, const Register& rt, const Register& rn);
+
+  // Load-acquire half-word.
+  void ldarh(const Register& rt, const Register& rn);
+
+  // Load-acquire exclusive half-word.
+  void ldaxrh(const Register& rt, const Register& rn);
+
+  // Store-release half-word.
+  void stlrh(const Register& rt, const Register& rn);
+
+  // Store-release exclusive half-word.
+  void stlxrh(const Register& rs, const Register& rt, const Register& rn);
+
   // Move instructions. The default shift of -1 indicates that the move
   // instruction will calculate an appropriate 16-bit immediate and left shift
   // that is equal to the 64-bit immediate argument. If an explicit left shift
@@ -1689,6 +1728,11 @@
     return rt2.code() << Rt2_offset;
   }
 
+  static Instr Rs(CPURegister rs) {
+    DCHECK(rs.code() != kSPRegInternalCode);
+    return rs.code() << Rs_offset;
+  }
+
   // These encoding functions allow the stack pointer to be encoded, and
   // disallow the zero register.
   static Instr RdSP(Register rd) {
diff --git a/src/arm64/builtins-arm64.cc b/src/arm64/builtins-arm64.cc
index 44bfc17..e16897a 100644
--- a/src/arm64/builtins-arm64.cc
+++ b/src/arm64/builtins-arm64.cc
@@ -32,10 +32,7 @@
   __ LoadNativeContextSlot(Context::INTERNAL_ARRAY_FUNCTION_INDEX, result);
 }
 
-
-void Builtins::Generate_Adaptor(MacroAssembler* masm,
-                                CFunctionId id,
-                                BuiltinExtraArguments extra_args) {
+void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
   // ----------- S t a t e -------------
   //  -- x0                 : number of arguments excluding receiver
   //  -- x1                 : target
@@ -54,23 +51,8 @@
   __ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset));
 
   // Insert extra arguments.
-  int num_extra_args = 0;
-  switch (extra_args) {
-    case BuiltinExtraArguments::kTarget:
-      __ Push(x1);
-      ++num_extra_args;
-      break;
-    case BuiltinExtraArguments::kNewTarget:
-      __ Push(x3);
-      ++num_extra_args;
-      break;
-    case BuiltinExtraArguments::kTargetAndNewTarget:
-      __ Push(x1, x3);
-      num_extra_args += 2;
-      break;
-    case BuiltinExtraArguments::kNone:
-      break;
-  }
+  const int num_extra_args = 2;
+  __ Push(x1, x3);
 
   // JumpToExternalReference expects x0 to contain the number of arguments
   // including the receiver and the extra arguments.
@@ -141,6 +123,8 @@
 void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
   // ----------- S t a t e -------------
   //  -- x0                 : number of arguments
+  //  -- x1                 : function
+  //  -- cp                 : context
   //  -- lr                 : return address
   //  -- sp[(argc - n) * 8] : arg[n] (zero-based)
   //  -- sp[(argc + 1) * 8] : receiver
@@ -152,9 +136,9 @@
                                      : Heap::kMinusInfinityValueRootIndex;
 
   // Load the accumulator with the default return value (either -Infinity or
-  // +Infinity), with the tagged value in x1 and the double value in d1.
-  __ LoadRoot(x1, root_index);
-  __ Ldr(d1, FieldMemOperand(x1, HeapNumber::kValueOffset));
+  // +Infinity), with the tagged value in x5 and the double value in d5.
+  __ LoadRoot(x5, root_index);
+  __ Ldr(d5, FieldMemOperand(x5, HeapNumber::kValueOffset));
 
   // Remember how many slots to drop (including the receiver).
   __ Add(x4, x0, 1);
@@ -170,31 +154,34 @@
     __ Peek(x2, Operand(x0, LSL, kPointerSizeLog2));
 
     // Load the double value of the parameter into d2, maybe converting the
-    // parameter to a number first using the ToNumberStub if necessary.
+    // parameter to a number first using the ToNumber builtin if necessary.
     Label convert_smi, convert_number, done_convert;
     __ JumpIfSmi(x2, &convert_smi);
     __ JumpIfHeapNumber(x2, &convert_number);
     {
-      // Parameter is not a Number, use the ToNumberStub to convert it.
-      FrameScope scope(masm, StackFrame::INTERNAL);
+      // Parameter is not a Number, use the ToNumber builtin to convert it.
+      FrameScope scope(masm, StackFrame::MANUAL);
+      __ Push(lr, fp);
+      __ Move(fp, jssp);
+      __ Push(cp, x1);
       __ SmiTag(x0);
       __ SmiTag(x4);
-      __ Push(x0, x1, x4);
+      __ Push(x0, x5, x4);
       __ Mov(x0, x2);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
       __ Mov(x2, x0);
-      __ Pop(x4, x1, x0);
+      __ Pop(x4, x5, x0);
       {
-        // Restore the double accumulator value (d1).
+        // Restore the double accumulator value (d5).
         Label done_restore;
-        __ SmiUntagToDouble(d1, x1, kSpeculativeUntag);
-        __ JumpIfSmi(x1, &done_restore);
-        __ Ldr(d1, FieldMemOperand(x1, HeapNumber::kValueOffset));
+        __ SmiUntagToDouble(d5, x5, kSpeculativeUntag);
+        __ JumpIfSmi(x5, &done_restore);
+        __ Ldr(d5, FieldMemOperand(x5, HeapNumber::kValueOffset));
         __ Bind(&done_restore);
       }
       __ SmiUntag(x4);
       __ SmiUntag(x0);
+      __ Pop(x1, cp, fp, lr);
     }
     __ AssertNumber(x2);
     __ JumpIfSmi(x2, &convert_smi);
@@ -209,22 +196,22 @@
 
     // We can use a single fmin/fmax for the operation itself, but we then need
     // to work out which HeapNumber (or smi) the result came from.
-    __ Fmov(x11, d1);
+    __ Fmov(x11, d5);
     if (kind == MathMaxMinKind::kMin) {
-      __ Fmin(d1, d1, d2);
+      __ Fmin(d5, d5, d2);
     } else {
       DCHECK(kind == MathMaxMinKind::kMax);
-      __ Fmax(d1, d1, d2);
+      __ Fmax(d5, d5, d2);
     }
-    __ Fmov(x10, d1);
+    __ Fmov(x10, d5);
     __ Cmp(x10, x11);
-    __ Csel(x1, x1, x2, eq);
+    __ Csel(x5, x5, x2, eq);
     __ B(&loop);
   }
 
   __ Bind(&done_loop);
-  __ Mov(x0, x1);
   __ Drop(x4);
+  __ Mov(x0, x5);
   __ Ret();
 }
 
@@ -250,8 +237,7 @@
   }
 
   // 2a. Convert first argument to number.
-  ToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
+  __ Jump(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
 
   // 2b. No arguments, return +0 (already in x0).
   __ Bind(&no_arguments);
@@ -299,8 +285,7 @@
       FrameScope scope(masm, StackFrame::INTERNAL);
       __ Push(x1, x3);
       __ Move(x0, x2);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
       __ Move(x2, x0);
       __ Pop(x3, x1);
     }
@@ -605,16 +590,9 @@
     // x0: number of arguments
     // x1: constructor function
     // x3: new target
-    if (is_api_function) {
-      __ Ldr(cp, FieldMemOperand(constructor, JSFunction::kContextOffset));
-      Handle<Code> code =
-          masm->isolate()->builtins()->HandleApiCallConstruct();
-      __ Call(code, RelocInfo::CODE_TARGET);
-    } else {
-      ParameterCount actual(argc);
-      __ InvokeFunction(constructor, new_target, actual, CALL_FUNCTION,
-                        CheckDebugStepCallWrapper());
-    }
+    ParameterCount actual(argc);
+    __ InvokeFunction(constructor, new_target, actual, CALL_FUNCTION,
+                      CheckDebugStepCallWrapper());
 
     // Store offset of return address for deoptimizer.
     if (create_implicit_receiver && !is_api_function) {
@@ -711,6 +689,154 @@
   __ CallRuntime(Runtime::kThrowConstructedNonConstructable);
 }
 
+// static
+void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- x0 : the value to pass to the generator
+  //  -- x1 : the JSGeneratorObject to resume
+  //  -- x2 : the resume mode (tagged)
+  //  -- lr : return address
+  // -----------------------------------
+  __ AssertGeneratorObject(x1);
+
+  // Store input value into generator object.
+  __ Str(x0, FieldMemOperand(x1, JSGeneratorObject::kInputOrDebugPosOffset));
+  __ RecordWriteField(x1, JSGeneratorObject::kInputOrDebugPosOffset, x0, x3,
+                      kLRHasNotBeenSaved, kDontSaveFPRegs);
+
+  // Store resume mode into generator object.
+  __ Str(x2, FieldMemOperand(x1, JSGeneratorObject::kResumeModeOffset));
+
+  // Load suspended function and context.
+  __ Ldr(cp, FieldMemOperand(x1, JSGeneratorObject::kContextOffset));
+  __ Ldr(x4, FieldMemOperand(x1, JSGeneratorObject::kFunctionOffset));
+
+  // Flood function if we are stepping.
+  Label prepare_step_in_if_stepping, prepare_step_in_suspended_generator;
+  Label stepping_prepared;
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(masm->isolate());
+  STATIC_ASSERT(StepFrame > StepIn);
+  __ Mov(x10, Operand(last_step_action));
+  __ Ldrsb(x10, MemOperand(x10));
+  __ CompareAndBranch(x10, Operand(StepIn), ge, &prepare_step_in_if_stepping);
+
+  // Flood function if we need to continue stepping in the suspended generator.
+  ExternalReference debug_suspended_generator =
+      ExternalReference::debug_suspended_generator_address(masm->isolate());
+  __ Mov(x10, Operand(debug_suspended_generator));
+  __ Ldr(x10, MemOperand(x10));
+  __ CompareAndBranch(x10, Operand(x1), eq,
+                      &prepare_step_in_suspended_generator);
+  __ Bind(&stepping_prepared);
+
+  // Push receiver.
+  __ Ldr(x5, FieldMemOperand(x1, JSGeneratorObject::kReceiverOffset));
+  __ Push(x5);
+
+  // ----------- S t a t e -------------
+  //  -- x1      : the JSGeneratorObject to resume
+  //  -- x2      : the resume mode (tagged)
+  //  -- x4      : generator function
+  //  -- cp      : generator context
+  //  -- lr      : return address
+  //  -- jssp[0] : generator receiver
+  // -----------------------------------
+
+  // Push holes for arguments to generator function. Since the parser forced
+  // context allocation for any variables in generators, the actual argument
+  // values have already been copied into the context and these dummy values
+  // will never be used.
+  __ Ldr(x10, FieldMemOperand(x4, JSFunction::kSharedFunctionInfoOffset));
+  __ Ldr(w10,
+         FieldMemOperand(x10, SharedFunctionInfo::kFormalParameterCountOffset));
+  __ LoadRoot(x11, Heap::kTheHoleValueRootIndex);
+  __ PushMultipleTimes(x11, w10);
+
+  // Dispatch on the kind of generator object.
+  Label old_generator;
+  __ Ldr(x3, FieldMemOperand(x4, JSFunction::kSharedFunctionInfoOffset));
+  __ Ldr(x3, FieldMemOperand(x3, SharedFunctionInfo::kFunctionDataOffset));
+  __ CompareObjectType(x3, x3, x3, BYTECODE_ARRAY_TYPE);
+  __ B(ne, &old_generator);
+
+  // New-style (ignition/turbofan) generator object
+  {
+    __ Ldr(x0, FieldMemOperand(x4, JSFunction::kSharedFunctionInfoOffset));
+    __ Ldr(w0,
+         FieldMemOperand(x0, SharedFunctionInfo::kFormalParameterCountOffset));
+    // We abuse new.target both to indicate that this is a resume call and to
+    // pass in the generator object.  In ordinary calls, new.target is always
+    // undefined because generator functions are non-constructable.
+    __ Move(x3, x1);
+    __ Move(x1, x4);
+    __ Ldr(x5, FieldMemOperand(x1, JSFunction::kCodeEntryOffset));
+    __ Jump(x5);
+  }
+
+  // Old-style (full-codegen) generator object
+  __ bind(&old_generator);
+  {
+    // Enter a new JavaScript frame, and initialize its slots as they were when
+    // the generator was suspended.
+    FrameScope scope(masm, StackFrame::MANUAL);
+    __ Push(lr, fp);
+    __ Move(fp, jssp);
+    __ Push(cp, x4);
+
+    // Restore the operand stack.
+    __ Ldr(x0, FieldMemOperand(x1, JSGeneratorObject::kOperandStackOffset));
+    __ Ldr(w3, UntagSmiFieldMemOperand(x0, FixedArray::kLengthOffset));
+    __ Add(x0, x0, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+    __ Add(x3, x0, Operand(x3, LSL, kPointerSizeLog2));
+    {
+      Label done_loop, loop;
+      __ Bind(&loop);
+      __ Cmp(x0, x3);
+      __ B(eq, &done_loop);
+      __ Ldr(x10, MemOperand(x0, kPointerSize, PostIndex));
+      __ Push(x10);
+      __ B(&loop);
+      __ Bind(&done_loop);
+    }
+
+    // Reset operand stack so we don't leak.
+    __ LoadRoot(x10, Heap::kEmptyFixedArrayRootIndex);
+    __ Str(x10, FieldMemOperand(x1, JSGeneratorObject::kOperandStackOffset));
+
+    // Resume the generator function at the continuation.
+    __ Ldr(x10, FieldMemOperand(x4, JSFunction::kSharedFunctionInfoOffset));
+    __ Ldr(x10, FieldMemOperand(x10, SharedFunctionInfo::kCodeOffset));
+    __ Add(x10, x10, Code::kHeaderSize - kHeapObjectTag);
+    __ Ldrsw(x11,
+        UntagSmiFieldMemOperand(x1, JSGeneratorObject::kContinuationOffset));
+    __ Add(x10, x10, x11);
+    __ Mov(x12, Smi::FromInt(JSGeneratorObject::kGeneratorExecuting));
+    __ Str(x12, FieldMemOperand(x1, JSGeneratorObject::kContinuationOffset));
+    __ Move(x0, x1);  // Continuation expects generator object in x0.
+    __ Br(x10);
+  }
+
+  __ Bind(&prepare_step_in_if_stepping);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ Push(x1, x2, x4);
+    __ CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
+    __ Pop(x2, x1);
+    __ Ldr(x4, FieldMemOperand(x1, JSGeneratorObject::kFunctionOffset));
+  }
+  __ B(&stepping_prepared);
+
+  __ Bind(&prepare_step_in_suspended_generator);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ Push(x1, x2);
+    __ CallRuntime(Runtime::kDebugPrepareStepInSuspendedGenerator);
+    __ Pop(x2, x1);
+    __ Ldr(x4, FieldMemOperand(x1, JSGeneratorObject::kFunctionOffset));
+  }
+  __ B(&stepping_prepared);
+}
 
 enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt };
 
@@ -844,6 +970,21 @@
   Generate_JSEntryTrampolineHelper(masm, true);
 }
 
+static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch) {
+  Register args_count = scratch;
+
+  // Get the arguments + receiver count.
+  __ ldr(args_count,
+         MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
+  __ Ldr(args_count.W(),
+         FieldMemOperand(args_count, BytecodeArray::kParameterSizeOffset));
+
+  // Leave the frame (also dropping the register file).
+  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+
+  // Drop receiver + arguments.
+  __ Drop(args_count, 1);
+}
 
 // Generate code for entering a JS function with the interpreter.
 // On entry to the function the receiver and arguments have been pushed on the
@@ -861,6 +1002,8 @@
 // The function builds an interpreter frame.  See InterpreterFrameConstants in
 // frames.h for its layout.
 void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
+  ProfileEntryHookStub::MaybeCallEntryHook(masm);
+
   // Open a frame scope to indicate that there is a frame on the stack.  The
   // MANUAL indicates that the scope shouldn't actually generate code to set up
   // the frame (that is done below).
@@ -868,8 +1011,8 @@
   __ Push(lr, fp, cp, x1);
   __ Add(fp, jssp, StandardFrameConstants::kFixedFrameSizeFromFp);
 
-  // Get the bytecode array from the function object and load the pointer to the
-  // first entry into kInterpreterBytecodeRegister.
+  // Get the bytecode array from the function object (or from the DebugInfo if
+  // it is present) and load it into kInterpreterBytecodeArrayRegister.
   __ Ldr(x0, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
   Register debug_info = kInterpreterBytecodeArrayRegister;
   Label load_debug_bytecode_array, bytecode_array_loaded;
@@ -881,8 +1024,12 @@
          FieldMemOperand(x0, SharedFunctionInfo::kFunctionDataOffset));
   __ Bind(&bytecode_array_loaded);
 
+  // Check function data field is actually a BytecodeArray object.
+  Label bytecode_array_not_present;
+  __ CompareRoot(kInterpreterBytecodeArrayRegister,
+                 Heap::kUndefinedValueRootIndex);
+  __ B(eq, &bytecode_array_not_present);
   if (FLAG_debug_code) {
-    // Check function data field is actually a BytecodeArray object.
     __ AssertNotSmi(kInterpreterBytecodeArrayRegister,
                     kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
     __ CompareObjectType(kInterpreterBytecodeArrayRegister, x0, x0,
@@ -890,8 +1037,12 @@
     __ Assert(eq, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
   }
 
-  // Push new.target, bytecode array and zero for bytecode array offset.
-  __ Mov(x0, Operand(0));
+  // Load the initial bytecode offset.
+  __ Mov(kInterpreterBytecodeOffsetRegister,
+         Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
+
+  // Push new.target, bytecode array and Smi tagged bytecode array offset.
+  __ SmiTag(x0, kInterpreterBytecodeOffsetRegister);
   __ Push(x3, kInterpreterBytecodeArrayRegister, x0);
 
   // Allocate the local and temporary register file on the stack.
@@ -921,18 +1072,8 @@
     __ Bind(&loop_header);
   }
 
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's prologue:
-  //  - Call ProfileEntryHookStub when isolate has a function_entry_hook.
-  //  - Code aging of the BytecodeArray object.
-
-  // Load accumulator, register file, bytecode offset, dispatch table into
-  // registers.
+  // Load accumulator and dispatch table into registers.
   __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
-  __ Add(kInterpreterRegisterFileRegister, fp,
-         Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
-  __ Mov(kInterpreterBytecodeOffsetRegister,
-         Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
   __ Mov(kInterpreterDispatchTableRegister,
          Operand(ExternalReference::interpreter_dispatch_table_address(
              masm->isolate())));
@@ -942,60 +1083,146 @@
                          kInterpreterBytecodeOffsetRegister));
   __ Mov(x1, Operand(x1, LSL, kPointerSizeLog2));
   __ Ldr(ip0, MemOperand(kInterpreterDispatchTableRegister, x1));
-  // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
-  // and header removal.
-  __ Add(ip0, ip0, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Call(ip0);
+  masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
 
-  // Even though the first bytecode handler was called, we will never return.
-  __ Abort(kUnexpectedReturnFromBytecodeHandler);
+  // The return value is in x0.
+  LeaveInterpreterFrame(masm, x2);
+  __ Ret();
 
   // Load debug copy of the bytecode array.
   __ Bind(&load_debug_bytecode_array);
   __ Ldr(kInterpreterBytecodeArrayRegister,
          FieldMemOperand(debug_info, DebugInfo::kAbstractCodeIndex));
   __ B(&bytecode_array_loaded);
+
+  // If the bytecode array is no longer present, then the underlying function
+  // has been switched to a different kind of code and we heal the closure by
+  // switching the code entry field over to the new code object as well.
+  __ Bind(&bytecode_array_not_present);
+  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+  __ Ldr(x7, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
+  __ Ldr(x7, FieldMemOperand(x7, SharedFunctionInfo::kCodeOffset));
+  __ Add(x7, x7, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ Str(x7, FieldMemOperand(x1, JSFunction::kCodeEntryOffset));
+  __ RecordWriteCodeEntryField(x1, x7, x5);
+  __ Jump(x7);
 }
 
+void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) {
+  // Save the function and context for call to CompileBaseline.
+  __ ldr(x1, MemOperand(fp, StandardFrameConstants::kFunctionOffset));
+  __ ldr(kContextRegister,
+         MemOperand(fp, StandardFrameConstants::kContextOffset));
 
-void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's EmitReturnSequence.
-  //  - Supporting FLAG_trace for Runtime::TraceExit.
-  //  - Support profiler (specifically decrementing profiling_counter
-  //    appropriately and calling out to HandleInterrupts if necessary).
+  // Leave the frame before recompiling for baseline so that we don't count as
+  // an activation on the stack.
+  LeaveInterpreterFrame(masm, x2);
 
-  // The return value is in accumulator, which is already in x0.
+  {
+    FrameScope frame_scope(masm, StackFrame::INTERNAL);
+    // Push return value.
+    __ push(x0);
 
-  // Leave the frame (also dropping the register file).
-  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+    // Push function as argument and compile for baseline.
+    __ push(x1);
+    __ CallRuntime(Runtime::kCompileBaseline);
 
-  // Drop receiver + arguments and return.
-  __ Ldr(w1, FieldMemOperand(kInterpreterBytecodeArrayRegister,
-                             BytecodeArray::kParameterSizeOffset));
-  __ Drop(x1, 1);
+    // Restore return value.
+    __ pop(x0);
+  }
   __ Ret();
 }
 
+// static
+void Builtins::Generate_InterpreterPushArgsAndCallImpl(
+    MacroAssembler* masm, TailCallMode tail_call_mode) {
+  // ----------- S t a t e -------------
+  //  -- x0 : the number of arguments (not including the receiver)
+  //  -- x2 : the address of the first argument to be pushed. Subsequent
+  //          arguments should be consecutive above this, in the same order as
+  //          they are to be pushed onto the stack.
+  //  -- x1 : the target to call (can be any Object).
+  // -----------------------------------
 
-static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
-  // Initialize register file register and dispatch table register.
-  __ Add(kInterpreterRegisterFileRegister, fp,
-         Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
+  // Find the address of the last argument.
+  __ add(x3, x0, Operand(1));  // Add one for receiver.
+  __ lsl(x3, x3, kPointerSizeLog2);
+  __ sub(x4, x2, x3);
+
+  // Push the arguments.
+  Label loop_header, loop_check;
+  __ Mov(x5, jssp);
+  __ Claim(x3, 1);
+  __ B(&loop_check);
+  __ Bind(&loop_header);
+  // TODO(rmcilroy): Push two at a time once we ensure we keep stack aligned.
+  __ Ldr(x3, MemOperand(x2, -kPointerSize, PostIndex));
+  __ Str(x3, MemOperand(x5, -kPointerSize, PreIndex));
+  __ Bind(&loop_check);
+  __ Cmp(x2, x4);
+  __ B(gt, &loop_header);
+
+  // Call the target.
+  __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny,
+                                            tail_call_mode),
+          RelocInfo::CODE_TARGET);
+}
+
+// static
+void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  // -- x0 : argument count (not including receiver)
+  // -- x3 : new target
+  // -- x1 : constructor to call
+  // -- x2 : address of the first argument
+  // -----------------------------------
+
+  // Find the address of the last argument.
+  __ add(x5, x0, Operand(1));  // Add one for receiver (to be constructed).
+  __ lsl(x5, x5, kPointerSizeLog2);
+
+  // Set stack pointer and where to stop.
+  __ Mov(x6, jssp);
+  __ Claim(x5, 1);
+  __ sub(x4, x6, x5);
+
+  // Push a slot for the receiver.
+  __ Str(xzr, MemOperand(x6, -kPointerSize, PreIndex));
+
+  Label loop_header, loop_check;
+  // Push the arguments.
+  __ B(&loop_check);
+  __ Bind(&loop_header);
+  // TODO(rmcilroy): Push two at a time once we ensure we keep stack aligned.
+  __ Ldr(x5, MemOperand(x2, -kPointerSize, PostIndex));
+  __ Str(x5, MemOperand(x6, -kPointerSize, PreIndex));
+  __ Bind(&loop_check);
+  __ Cmp(x6, x4);
+  __ B(gt, &loop_header);
+
+  // Call the constructor with x0, x1, and x3 unmodified.
+  __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
+}
+
+void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
+  // Set the return address to the correct point in the interpreter entry
+  // trampoline.
+  Smi* interpreter_entry_return_pc_offset(
+      masm->isolate()->heap()->interpreter_entry_return_pc_offset());
+  DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
+  __ LoadObject(x1, masm->isolate()->builtins()->InterpreterEntryTrampoline());
+  __ Add(lr, x1, Operand(interpreter_entry_return_pc_offset->value() +
+                         Code::kHeaderSize - kHeapObjectTag));
+
+  // Initialize the dispatch table register.
   __ Mov(kInterpreterDispatchTableRegister,
          Operand(ExternalReference::interpreter_dispatch_table_address(
              masm->isolate())));
 
-  // Get the context from the frame.
-  __ Ldr(kContextRegister,
-         MemOperand(kInterpreterRegisterFileRegister,
-                    InterpreterFrameConstants::kContextFromRegisterPointer));
-
   // Get the bytecode array pointer from the frame.
-  __ Ldr(
-      kInterpreterBytecodeArrayRegister,
-      MemOperand(kInterpreterRegisterFileRegister,
-                 InterpreterFrameConstants::kBytecodeArrayFromRegisterPointer));
+  __ Ldr(kInterpreterBytecodeArrayRegister,
+         MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
 
   if (FLAG_debug_code) {
     // Check function data field is actually a BytecodeArray object.
@@ -1008,9 +1235,7 @@
 
   // Get the target bytecode offset from the frame.
   __ Ldr(kInterpreterBytecodeOffsetRegister,
-         MemOperand(
-             kInterpreterRegisterFileRegister,
-             InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
+         MemOperand(fp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
   __ SmiUntag(kInterpreterBytecodeOffsetRegister);
 
   // Dispatch to the target bytecode.
@@ -1018,63 +1243,165 @@
                          kInterpreterBytecodeOffsetRegister));
   __ Mov(x1, Operand(x1, LSL, kPointerSizeLog2));
   __ Ldr(ip0, MemOperand(kInterpreterDispatchTableRegister, x1));
-  __ Add(ip0, ip0, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Jump(ip0);
 }
 
-
-static void Generate_InterpreterNotifyDeoptimizedHelper(
-    MacroAssembler* masm, Deoptimizer::BailoutType type) {
-  // Enter an internal frame.
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Pass the deoptimization type to the runtime system.
-    __ Mov(x1, Operand(Smi::FromInt(static_cast<int>(type))));
-    __ Push(x1);
-    __ CallRuntime(Runtime::kNotifyDeoptimized);
-    // Tear down internal frame.
-  }
-
-  // Drop state (we don't use these for interpreter deopts) and and pop the
-  // accumulator value into the accumulator register.
-  __ Drop(1);
-  __ Pop(kInterpreterAccumulatorRegister);
-
-  // Enter the bytecode dispatch.
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-
-void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
-}
-
-
-void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
-}
-
-
-void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
-}
-
-void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
-  // Set the address of the interpreter entry trampoline as a return address.
-  // This simulates the initial call to bytecode handlers in interpreter entry
-  // trampoline. The return will never actually be taken, but our stack walker
-  // uses this address to determine whether a frame is interpreted.
-  __ LoadObject(lr, masm->isolate()->builtins()->InterpreterEntryTrampoline());
-
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-
 void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- x0 : argument count (preserved for callee)
+  //  -- x3 : new target (preserved for callee)
+  //  -- x1 : target function (preserved for callee)
+  // -----------------------------------
+  // First lookup code, maybe we don't need to compile!
+  Label gotta_call_runtime;
+  Label maybe_call_runtime;
+  Label try_shared;
+  Label loop_top, loop_bottom;
+
+  Register closure = x1;
+  Register map = x13;
+  Register index = x2;
+  __ Ldr(map, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ Ldr(map,
+         FieldMemOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset));
+  __ Ldrsw(index, UntagSmiFieldMemOperand(map, FixedArray::kLengthOffset));
+  __ Cmp(index, Operand(2));
+  __ B(lt, &gotta_call_runtime);
+
+  // Find literals.
+  // x3  : native context
+  // x2  : length / index
+  // x13 : optimized code map
+  // stack[0] : new target
+  // stack[4] : closure
+  Register native_context = x4;
+  __ Ldr(native_context, NativeContextMemOperand());
+
+  __ Bind(&loop_top);
+  Register temp = x5;
+  Register array_pointer = x6;
+
+  // Does the native context match?
+  __ Add(array_pointer, map, Operand(index, LSL, kPointerSizeLog2));
+  __ Ldr(temp, FieldMemOperand(array_pointer,
+                               SharedFunctionInfo::kOffsetToPreviousContext));
+  __ Ldr(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
+  __ Cmp(temp, native_context);
+  __ B(ne, &loop_bottom);
+  // OSR id set to none?
+  __ Ldr(temp, FieldMemOperand(array_pointer,
+                               SharedFunctionInfo::kOffsetToPreviousOsrAstId));
+  const int bailout_id = BailoutId::None().ToInt();
+  __ Cmp(temp, Operand(Smi::FromInt(bailout_id)));
+  __ B(ne, &loop_bottom);
+
+  // Literals available?
+  Label got_literals, maybe_cleared_weakcell;
+  Register temp2 = x7;
+  __ Ldr(temp, FieldMemOperand(array_pointer,
+                               SharedFunctionInfo::kOffsetToPreviousLiterals));
+  // temp contains either a WeakCell pointing to the literals array or the
+  // literals array directly.
+  STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
+  __ Ldr(temp2, FieldMemOperand(temp, WeakCell::kValueOffset));
+  __ JumpIfSmi(temp2, &maybe_cleared_weakcell);
+  // temp2 is a pointer, therefore temp is a WeakCell pointing to a literals
+  // array.
+  __ Ldr(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
+  __ jmp(&got_literals);
+
+  // r4 is a smi. If it's 0, then we are looking at a cleared WeakCell
+  // around the literals array, and we should visit the runtime. If it's > 0,
+  // then temp already contains the literals array.
+  __ bind(&maybe_cleared_weakcell);
+  __ Cmp(temp2, Operand(Smi::FromInt(0)));
+  __ B(eq, &gotta_call_runtime);
+
+  // Save the literals in the closure.
+  __ bind(&got_literals);
+  __ Str(temp, FieldMemOperand(closure, JSFunction::kLiteralsOffset));
+  __ RecordWriteField(closure, JSFunction::kLiteralsOffset, temp, x7,
+                      kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+
+  // Code available?
+  Register entry = x7;
+  __ Ldr(entry,
+         FieldMemOperand(array_pointer,
+                         SharedFunctionInfo::kOffsetToPreviousCachedCode));
+  __ Ldr(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &maybe_call_runtime);
+
+  // Found literals and code. Get them into the closure and return.
+  __ Add(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+
+  Label install_optimized_code_and_tailcall;
+  __ Bind(&install_optimized_code_and_tailcall);
+  __ Str(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
+  __ RecordWriteCodeEntryField(closure, entry, x5);
+
+  // Link the closure into the optimized function list.
+  // x7 : code entry
+  // x4 : native context
+  // x1 : closure
+  __ Ldr(x8,
+         ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
+  __ Str(x8, FieldMemOperand(closure, JSFunction::kNextFunctionLinkOffset));
+  __ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, x8, x13,
+                      kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  const int function_list_offset =
+      Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
+  __ Str(closure,
+         ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
+  __ Mov(x5, closure);
+  __ RecordWriteContextSlot(native_context, function_list_offset, x5, x13,
+                            kLRHasNotBeenSaved, kDontSaveFPRegs);
+  __ Jump(entry);
+
+  __ Bind(&loop_bottom);
+  __ Sub(index, index, Operand(SharedFunctionInfo::kEntryLength));
+  __ Cmp(index, Operand(1));
+  __ B(gt, &loop_top);
+
+  // We found neither literals nor code.
+  __ B(&gotta_call_runtime);
+
+  __ Bind(&maybe_call_runtime);
+
+  // Last possibility. Check the context free optimized code map entry.
+  __ Ldr(entry, FieldMemOperand(map, FixedArray::kHeaderSize +
+                                         SharedFunctionInfo::kSharedCodeIndex));
+  __ Ldr(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &try_shared);
+
+  // Store code entry in the closure.
+  __ Add(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ B(&install_optimized_code_and_tailcall);
+
+  __ Bind(&try_shared);
+  // Is the full code valid?
+  __ Ldr(entry,
+         FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ Ldr(entry, FieldMemOperand(entry, SharedFunctionInfo::kCodeOffset));
+  __ Ldr(x5, FieldMemOperand(entry, Code::kFlagsOffset));
+  __ and_(x5, x5, Operand(Code::KindField::kMask));
+  __ Mov(x5, Operand(x5, LSR, Code::KindField::kShift));
+  __ Cmp(x5, Operand(Code::BUILTIN));
+  __ B(eq, &gotta_call_runtime);
+  // Yes, install the full code.
+  __ Add(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ Str(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
+  __ RecordWriteCodeEntryField(closure, entry, x5);
+  __ Jump(entry);
+
+  __ Bind(&gotta_call_runtime);
   GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
 }
 
+void Builtins::Generate_CompileBaseline(MacroAssembler* masm) {
+  GenerateTailCallToReturnedCode(masm, Runtime::kCompileBaseline);
+}
 
 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
   GenerateTailCallToReturnedCode(masm,
@@ -1225,15 +1552,19 @@
 
   // Switch on the state.
   Label with_tos_register, unknown_state;
-  __ CompareAndBranch(
-      state, FullCodeGenerator::NO_REGISTERS, ne, &with_tos_register);
+  __ CompareAndBranch(state,
+                      static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS),
+                      ne, &with_tos_register);
   __ Drop(1);  // Remove state.
   __ Ret();
 
   __ Bind(&with_tos_register);
   // Reload TOS register.
+  DCHECK_EQ(kInterpreterAccumulatorRegister.code(), x0.code());
   __ Peek(x0, kPointerSize);
-  __ CompareAndBranch(state, FullCodeGenerator::TOS_REG, ne, &unknown_state);
+  __ CompareAndBranch(state,
+                      static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER),
+                      ne, &unknown_state);
   __ Drop(2);  // Remove state and TOS.
   __ Ret();
 
@@ -1397,6 +1728,9 @@
 void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
                                                int field_index) {
   // ----------- S t a t e -------------
+  //  -- x0      : number of arguments
+  //  -- x1      : function
+  //  -- cp      : context
   //  -- lr      : return address
   //  -- jssp[0] : receiver
   // -----------------------------------
@@ -1407,7 +1741,7 @@
   {
     __ Pop(x0);
     __ JumpIfSmi(x0, &receiver_not_date);
-    __ JumpIfNotObjectType(x0, x1, x2, JS_DATE_TYPE, &receiver_not_date);
+    __ JumpIfNotObjectType(x0, x2, x3, JS_DATE_TYPE, &receiver_not_date);
   }
 
   // 2. Load the specified date field, falling back to the runtime as necessary.
@@ -1435,31 +1769,14 @@
 
   // 3. Raise a TypeError if the receiver is not a date.
   __ Bind(&receiver_not_date);
-  __ TailCallRuntime(Runtime::kThrowNotDateError);
-}
-
-// static
-void Builtins::Generate_FunctionHasInstance(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- x0      : argc
-  //  -- jssp[0] : first argument (left-hand side)
-  //  -- jssp[8] : receiver (right-hand side)
-  // -----------------------------------
-  ASM_LOCATION("Builtins::Generate_FunctionHasInstance");
-
   {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-    __ Ldr(InstanceOfDescriptor::LeftRegister(),
-           MemOperand(fp, 2 * kPointerSize));  // Load left-hand side.
-    __ Ldr(InstanceOfDescriptor::RightRegister(),
-           MemOperand(fp, 3 * kPointerSize));  // Load right-hand side.
-    InstanceOfStub stub(masm->isolate(), true);
-    __ CallStub(&stub);
+    FrameScope scope(masm, StackFrame::MANUAL);
+    __ Push(x0, lr, fp);
+    __ Move(fp, jssp);
+    __ Push(cp, x1);
+    __ Push(Smi::FromInt(0));
+    __ CallRuntime(Runtime::kThrowNotDateError);
   }
-
-  // Pop the argument and the receiver.
-  __ Drop(2);
-  __ Ret();
 }
 
 // static
@@ -2434,80 +2751,109 @@
           RelocInfo::CODE_TARGET);
 }
 
+// static
+void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) {
+  ASM_LOCATION("Builtins::Generate_AllocateInNewSpace");
+  // ----------- S t a t e -------------
+  //  -- x1 : requested object size (untagged)
+  //  -- lr : return address
+  // -----------------------------------
+  __ SmiTag(x1);
+  __ Push(x1);
+  __ Move(cp, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInNewSpace);
+}
 
 // static
-void Builtins::Generate_InterpreterPushArgsAndCallImpl(
-    MacroAssembler* masm, TailCallMode tail_call_mode) {
+void Builtins::Generate_AllocateInOldSpace(MacroAssembler* masm) {
+  ASM_LOCATION("Builtins::Generate_AllocateInOldSpace");
   // ----------- S t a t e -------------
-  //  -- x0 : the number of arguments (not including the receiver)
-  //  -- x2 : the address of the first argument to be pushed. Subsequent
-  //          arguments should be consecutive above this, in the same order as
-  //          they are to be pushed onto the stack.
-  //  -- x1 : the target to call (can be any Object).
+  //  -- x1 : requested object size (untagged)
+  //  -- lr : return address
   // -----------------------------------
+  __ SmiTag(x1);
+  __ Move(x2, Smi::FromInt(AllocateTargetSpace::encode(OLD_SPACE)));
+  __ Push(x1, x2);
+  __ Move(cp, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInTargetSpace);
+}
 
-  // Find the address of the last argument.
-  __ add(x3, x0, Operand(1));  // Add one for receiver.
-  __ lsl(x3, x3, kPointerSizeLog2);
-  __ sub(x4, x2, x3);
+// static
+void Builtins::Generate_StringToNumber(MacroAssembler* masm) {
+  // The StringToNumber stub takes one argument in x0.
+  __ AssertString(x0);
 
-  // Push the arguments.
-  Label loop_header, loop_check;
-  __ Mov(x5, jssp);
-  __ Claim(x3, 1);
-  __ B(&loop_check);
-  __ Bind(&loop_header);
-  // TODO(rmcilroy): Push two at a time once we ensure we keep stack aligned.
-  __ Ldr(x3, MemOperand(x2, -kPointerSize, PostIndex));
-  __ Str(x3, MemOperand(x5, -kPointerSize, PreIndex));
-  __ Bind(&loop_check);
-  __ Cmp(x2, x4);
-  __ B(gt, &loop_header);
+  // Check if string has a cached array index.
+  Label runtime;
+  __ Ldr(x2, FieldMemOperand(x0, String::kHashFieldOffset));
+  __ Tst(x2, Operand(String::kContainsCachedArrayIndexMask));
+  __ B(ne, &runtime);
+  __ IndexFromHash(x2, x0);
+  __ Ret();
 
-  // Call the target.
-  __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny,
-                                            tail_call_mode),
+  __ Bind(&runtime);
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ Push(x0);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kStringToNumber);
+  }
+  __ Ret();
+}
+
+// static
+void Builtins::Generate_ToNumber(MacroAssembler* masm) {
+  // The ToNumber stub takes one argument in x0.
+  Label not_smi;
+  __ JumpIfNotSmi(x0, &not_smi);
+  __ Ret();
+  __ Bind(&not_smi);
+
+  Label not_heap_number;
+  __ CompareObjectType(x0, x1, x1, HEAP_NUMBER_TYPE);
+  // x0: receiver
+  // x1: receiver instance type
+  __ B(ne, &not_heap_number);
+  __ Ret();
+  __ Bind(&not_heap_number);
+
+  __ Jump(masm->isolate()->builtins()->NonNumberToNumber(),
           RelocInfo::CODE_TARGET);
 }
 
-
 // static
-void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  // -- x0 : argument count (not including receiver)
-  // -- x3 : new target
-  // -- x1 : constructor to call
-  // -- x2 : address of the first argument
-  // -----------------------------------
+void Builtins::Generate_NonNumberToNumber(MacroAssembler* masm) {
+  // The NonNumberToNumber stub takes one argument in x0.
+  __ AssertNotNumber(x0);
 
-  // Find the address of the last argument.
-  __ add(x5, x0, Operand(1));  // Add one for receiver (to be constructed).
-  __ lsl(x5, x5, kPointerSizeLog2);
+  Label not_string;
+  __ CompareObjectType(x0, x1, x1, FIRST_NONSTRING_TYPE);
+  // x0: receiver
+  // x1: receiver instance type
+  __ B(hs, &not_string);
+  __ Jump(masm->isolate()->builtins()->StringToNumber(),
+          RelocInfo::CODE_TARGET);
+  __ Bind(&not_string);
 
-  // Set stack pointer and where to stop.
-  __ Mov(x6, jssp);
-  __ Claim(x5, 1);
-  __ sub(x4, x6, x5);
-
-  // Push a slot for the receiver.
-  __ Str(xzr, MemOperand(x6, -kPointerSize, PreIndex));
-
-  Label loop_header, loop_check;
-  // Push the arguments.
-  __ B(&loop_check);
-  __ Bind(&loop_header);
-  // TODO(rmcilroy): Push two at a time once we ensure we keep stack aligned.
-  __ Ldr(x5, MemOperand(x2, -kPointerSize, PostIndex));
-  __ Str(x5, MemOperand(x6, -kPointerSize, PreIndex));
-  __ Bind(&loop_check);
-  __ Cmp(x6, x4);
-  __ B(gt, &loop_header);
-
-  // Call the constructor with x0, x1, and x3 unmodified.
-  __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
+  Label not_oddball;
+  __ Cmp(x1, ODDBALL_TYPE);
+  __ B(ne, &not_oddball);
+  __ Ldr(x0, FieldMemOperand(x0, Oddball::kToNumberOffset));
+  __ Ret();
+  __ Bind(&not_oddball);
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ Push(x0);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kToNumber);
+  }
+  __ Ret();
 }
 
-
 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
   ASM_LOCATION("Builtins::Generate_ArgumentsAdaptorTrampoline");
   // ----------- S t a t e -------------
diff --git a/src/arm64/code-stubs-arm64.cc b/src/arm64/code-stubs-arm64.cc
index ee40535..6b03068 100644
--- a/src/arm64/code-stubs-arm64.cc
+++ b/src/arm64/code-stubs-arm64.cc
@@ -22,64 +22,15 @@
 namespace v8 {
 namespace internal {
 
+#define __ ACCESS_MASM(masm)
 
-static void InitializeArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  // cp: context
-  // x1: function
-  // x2: allocation site with elements kind
-  // x0: number of arguments to the constructor function
-  Address deopt_handler = Runtime::FunctionForId(
-      Runtime::kArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(x0, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-
-void ArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 0);
-}
-
-
-void ArraySingleArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 1);
-}
-
-
-void ArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-static void InitializeInternalArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  Address deopt_handler = Runtime::FunctionForId(
-      Runtime::kInternalArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(x0, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-
-void InternalArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0);
+void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
+  __ Mov(x5, Operand(x0, LSL, kPointerSizeLog2));
+  __ Str(x1, MemOperand(jssp, x5));
+  __ Push(x1);
+  __ Push(x2);
+  __ Add(x0, x0, Operand(3));
+  __ TailCallRuntime(Runtime::kNewArray);
 }
 
 void FastArrayPushStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
@@ -87,21 +38,12 @@
   descriptor->Initialize(x0, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-void InternalArraySingleArgumentConstructorStub::InitializeDescriptor(
+void FastFunctionBindStub::InitializeDescriptor(
     CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1);
+  Address deopt_handler = Runtime::FunctionForId(Runtime::kFunctionBind)->entry;
+  descriptor->Initialize(x0, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-
-void InternalArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-#define __ ACCESS_MASM(masm)
-
-
 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm,
                                                ExternalReference miss) {
   // Update the static counter each time a new code stub is generated.
@@ -997,7 +939,7 @@
   CEntryStub::GenerateAheadOfTime(isolate);
   StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
   StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
-  ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
+  CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate);
   CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
   CreateWeakCellStub::GenerateAheadOfTime(isolate);
   BinaryOpICStub::GenerateAheadOfTime(isolate);
@@ -1323,11 +1265,6 @@
   __ Mov(jssp, csp);
   __ SetStackPointer(jssp);
 
-  // Configure the FPCR. We don't restore it, so this is technically not allowed
-  // according to AAPCS64. However, we only set default-NaN mode and this will
-  // be harmless for most C code. Also, it works for ARM.
-  __ ConfigureFPCR();
-
   ProfileEntryHookStub::MaybeCallEntryHook(masm);
 
   // Set up the reserved register for 0.0.
@@ -1506,7 +1443,6 @@
                                           &miss,  // When not a string.
                                           &miss,  // When not a number.
                                           &miss,  // When index out of range.
-                                          STRING_INDEX_IS_ARRAY_INDEX,
                                           RECEIVER_IS_STRING);
   char_at_generator.GenerateFast(masm);
   __ Ret();
@@ -1520,123 +1456,6 @@
 }
 
 
-void InstanceOfStub::Generate(MacroAssembler* masm) {
-  Register const object = x1;              // Object (lhs).
-  Register const function = x0;            // Function (rhs).
-  Register const object_map = x2;          // Map of {object}.
-  Register const function_map = x3;        // Map of {function}.
-  Register const function_prototype = x4;  // Prototype of {function}.
-  Register const scratch = x5;
-
-  DCHECK(object.is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(function.is(InstanceOfDescriptor::RightRegister()));
-
-  // Check if {object} is a smi.
-  Label object_is_smi;
-  __ JumpIfSmi(object, &object_is_smi);
-
-  // Lookup the {function} and the {object} map in the global instanceof cache.
-  // Note: This is safe because we clear the global instanceof cache whenever
-  // we change the prototype of any object.
-  Label fast_case, slow_case;
-  __ Ldr(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
-  __ JumpIfNotRoot(function, Heap::kInstanceofCacheFunctionRootIndex,
-                   &fast_case);
-  __ JumpIfNotRoot(object_map, Heap::kInstanceofCacheMapRootIndex, &fast_case);
-  __ LoadRoot(x0, Heap::kInstanceofCacheAnswerRootIndex);
-  __ Ret();
-
-  // If {object} is a smi we can safely return false if {function} is a JS
-  // function, otherwise we have to miss to the runtime and throw an exception.
-  __ Bind(&object_is_smi);
-  __ JumpIfSmi(function, &slow_case);
-  __ JumpIfNotObjectType(function, function_map, scratch, JS_FUNCTION_TYPE,
-                         &slow_case);
-  __ LoadRoot(x0, Heap::kFalseValueRootIndex);
-  __ Ret();
-
-  // Fast-case: The {function} must be a valid JSFunction.
-  __ Bind(&fast_case);
-  __ JumpIfSmi(function, &slow_case);
-  __ JumpIfNotObjectType(function, function_map, scratch, JS_FUNCTION_TYPE,
-                         &slow_case);
-
-  // Go to the runtime if the function is not a constructor.
-  __ Ldrb(scratch, FieldMemOperand(function_map, Map::kBitFieldOffset));
-  __ Tbz(scratch, Map::kIsConstructor, &slow_case);
-
-  // Ensure that {function} has an instance prototype.
-  __ Tbnz(scratch, Map::kHasNonInstancePrototype, &slow_case);
-
-  // Get the "prototype" (or initial map) of the {function}.
-  __ Ldr(function_prototype,
-         FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
-  __ AssertNotSmi(function_prototype);
-
-  // Resolve the prototype if the {function} has an initial map.  Afterwards the
-  // {function_prototype} will be either the JSReceiver prototype object or the
-  // hole value, which means that no instances of the {function} were created so
-  // far and hence we should return false.
-  Label function_prototype_valid;
-  __ JumpIfNotObjectType(function_prototype, scratch, scratch, MAP_TYPE,
-                         &function_prototype_valid);
-  __ Ldr(function_prototype,
-         FieldMemOperand(function_prototype, Map::kPrototypeOffset));
-  __ Bind(&function_prototype_valid);
-  __ AssertNotSmi(function_prototype);
-
-  // Update the global instanceof cache with the current {object} map and
-  // {function}.  The cached answer will be set when it is known below.
-  __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
-  __ StoreRoot(object_map, Heap::kInstanceofCacheMapRootIndex);
-
-  // Loop through the prototype chain looking for the {function} prototype.
-  // Assume true, and change to false if not found.
-  Register const object_instance_type = function_map;
-  Register const map_bit_field = function_map;
-  Register const null = scratch;
-  Register const result = x0;
-
-  Label done, loop, fast_runtime_fallback;
-  __ LoadRoot(result, Heap::kTrueValueRootIndex);
-  __ LoadRoot(null, Heap::kNullValueRootIndex);
-  __ Bind(&loop);
-
-  // Check if the object needs to be access checked.
-  __ Ldrb(map_bit_field, FieldMemOperand(object_map, Map::kBitFieldOffset));
-  __ TestAndBranchIfAnySet(map_bit_field, 1 << Map::kIsAccessCheckNeeded,
-                           &fast_runtime_fallback);
-  // Check if the current object is a Proxy.
-  __ CompareInstanceType(object_map, object_instance_type, JS_PROXY_TYPE);
-  __ B(eq, &fast_runtime_fallback);
-
-  __ Ldr(object, FieldMemOperand(object_map, Map::kPrototypeOffset));
-  __ Cmp(object, function_prototype);
-  __ B(eq, &done);
-  __ Cmp(object, null);
-  __ Ldr(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
-  __ B(ne, &loop);
-  __ LoadRoot(result, Heap::kFalseValueRootIndex);
-  __ Bind(&done);
-  __ StoreRoot(result, Heap::kInstanceofCacheAnswerRootIndex);
-  __ Ret();
-
-  // Found Proxy or access check needed: Call the runtime
-  __ Bind(&fast_runtime_fallback);
-  __ Push(object, function_prototype);
-  // Invalidate the instanceof cache.
-  __ Move(scratch, Smi::FromInt(0));
-  __ StoreRoot(scratch, Heap::kInstanceofCacheFunctionRootIndex);
-  __ TailCallRuntime(Runtime::kHasInPrototypeChain);
-
-  // Slow-case: Call the %InstanceOf runtime function.
-  __ bind(&slow_case);
-  __ Push(object, function);
-  __ TailCallRuntime(is_es6_instanceof() ? Runtime::kOrdinaryHasInstance
-                                         : Runtime::kInstanceOf);
-}
-
-
 void RegExpExecStub::Generate(MacroAssembler* masm) {
 #ifdef V8_INTERPRETED_REGEXP
   __ TailCallRuntime(Runtime::kRegExpExec);
@@ -2155,6 +1974,7 @@
   //  feedback_vector : the feedback vector
   //  index :           slot in feedback vector (smi)
   Label initialize, done, miss, megamorphic, not_array_function;
+  Label done_initialize_count, done_increment_count;
 
   DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()),
             masm->isolate()->heap()->megamorphic_symbol());
@@ -2177,7 +1997,7 @@
   Label check_allocation_site;
   __ Ldr(feedback_value, FieldMemOperand(feedback, WeakCell::kValueOffset));
   __ Cmp(function, feedback_value);
-  __ B(eq, &done);
+  __ B(eq, &done_increment_count);
   __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
   __ B(eq, &done);
   __ Ldr(feedback_map, FieldMemOperand(feedback, HeapObject::kMapOffset));
@@ -2199,7 +2019,7 @@
   __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, scratch1);
   __ Cmp(function, scratch1);
   __ B(ne, &megamorphic);
-  __ B(&done);
+  __ B(&done_increment_count);
 
   __ Bind(&miss);
 
@@ -2230,12 +2050,32 @@
   CreateAllocationSiteStub create_stub(masm->isolate());
   CallStubInRecordCallTarget(masm, &create_stub, argc, function,
                              feedback_vector, index, new_target);
-  __ B(&done);
+  __ B(&done_initialize_count);
 
   __ Bind(&not_array_function);
   CreateWeakCellStub weak_cell_stub(masm->isolate());
   CallStubInRecordCallTarget(masm, &weak_cell_stub, argc, function,
                              feedback_vector, index, new_target);
+
+  __ bind(&done_initialize_count);
+  // Initialize the call counter.
+  __ Mov(scratch1, Operand(Smi::FromInt(1)));
+  __ Adds(scratch2, feedback_vector,
+          Operand::UntagSmiAndScale(index, kPointerSizeLog2));
+  __ Str(scratch1,
+         FieldMemOperand(scratch2, FixedArray::kHeaderSize + kPointerSize));
+  __ b(&done);
+
+  __ bind(&done_increment_count);
+
+  // Increment the call count for monomorphic function calls.
+  __ Add(scratch1, feedback_vector,
+         Operand::UntagSmiAndScale(index, kPointerSizeLog2));
+  __ Add(scratch1, scratch1, Operand(FixedArray::kHeaderSize + kPointerSize));
+  __ Ldr(scratch2, FieldMemOperand(scratch1, 0));
+  __ Add(scratch2, scratch2, Operand(Smi::FromInt(1)));
+  __ Str(scratch2, FieldMemOperand(scratch1, 0));
+
   __ Bind(&done);
 }
 
@@ -2308,7 +2148,7 @@
   __ Add(feedback_vector, feedback_vector,
          Operand(FixedArray::kHeaderSize + kPointerSize));
   __ Ldr(index, FieldMemOperand(feedback_vector, 0));
-  __ Add(index, index, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+  __ Add(index, index, Operand(Smi::FromInt(1)));
   __ Str(index, FieldMemOperand(feedback_vector, 0));
 
   // Set up arguments for the array constructor stub.
@@ -2368,7 +2208,7 @@
   __ Add(feedback_vector, feedback_vector,
          Operand(FixedArray::kHeaderSize + kPointerSize));
   __ Ldr(index, FieldMemOperand(feedback_vector, 0));
-  __ Add(index, index, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+  __ Add(index, index, Operand(Smi::FromInt(1)));
   __ Str(index, FieldMemOperand(feedback_vector, 0));
 
   __ Bind(&call_function);
@@ -2433,7 +2273,7 @@
   __ B(ne, &miss);
 
   // Initialize the call counter.
-  __ Mov(x5, Smi::FromInt(CallICNexus::kCallCountIncrement));
+  __ Mov(x5, Smi::FromInt(1));
   __ Adds(x4, feedback_vector,
           Operand::UntagSmiAndScale(index, kPointerSizeLog2));
   __ Str(x5, FieldMemOperand(x4, FixedArray::kHeaderSize + kPointerSize));
@@ -2527,13 +2367,7 @@
     // Save object_ on the stack and pass index_ as argument for runtime call.
     __ Push(object_, index_);
   }
-  if (index_flags_ == STRING_INDEX_IS_NUMBER) {
-    __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero);
-  } else {
-    DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
-    // NumberToSmi discards numbers that are not exact integers.
-    __ CallRuntime(Runtime::kNumberToSmi);
-  }
+  __ CallRuntime(Runtime::kNumberToSmi);
   // Save the conversion result before the pop instructions below
   // have a chance to overwrite it.
   __ Mov(index_, x0);
@@ -3219,74 +3053,13 @@
   __ SmiTag(from);
   StringCharAtGenerator generator(input_string, from, result_length, x0,
                                   &runtime, &runtime, &runtime,
-                                  STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING);
+                                  RECEIVER_IS_STRING);
   generator.GenerateFast(masm);
   __ Drop(3);
   __ Ret();
   generator.SkipSlow(masm, &runtime);
 }
 
-
-void ToNumberStub::Generate(MacroAssembler* masm) {
-  // The ToNumber stub takes one argument in x0.
-  Label not_smi;
-  __ JumpIfNotSmi(x0, &not_smi);
-  __ Ret();
-  __ Bind(&not_smi);
-
-  Label not_heap_number;
-  __ CompareObjectType(x0, x1, x1, HEAP_NUMBER_TYPE);
-  // x0: receiver
-  // x1: receiver instance type
-  __ B(ne, &not_heap_number);
-  __ Ret();
-  __ Bind(&not_heap_number);
-
-  NonNumberToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
-}
-
-void NonNumberToNumberStub::Generate(MacroAssembler* masm) {
-  // The NonNumberToNumber stub takes one argument in x0.
-  __ AssertNotNumber(x0);
-
-  Label not_string;
-  __ CompareObjectType(x0, x1, x1, FIRST_NONSTRING_TYPE);
-  // x0: receiver
-  // x1: receiver instance type
-  __ B(hs, &not_string);
-  StringToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
-  __ Bind(&not_string);
-
-  Label not_oddball;
-  __ Cmp(x1, ODDBALL_TYPE);
-  __ B(ne, &not_oddball);
-  __ Ldr(x0, FieldMemOperand(x0, Oddball::kToNumberOffset));
-  __ Ret();
-  __ Bind(&not_oddball);
-
-  __ Push(x0);  // Push argument.
-  __ TailCallRuntime(Runtime::kToNumber);
-}
-
-void StringToNumberStub::Generate(MacroAssembler* masm) {
-  // The StringToNumber stub takes one argument in x0.
-  __ AssertString(x0);
-
-  // Check if string has a cached array index.
-  Label runtime;
-  __ Ldr(x2, FieldMemOperand(x0, String::kHashFieldOffset));
-  __ Tst(x2, Operand(String::kContainsCachedArrayIndexMask));
-  __ B(ne, &runtime);
-  __ IndexFromHash(x2, x0);
-  __ Ret();
-
-  __ Bind(&runtime);
-  __ Push(x0);  // Push argument.
-  __ TailCallRuntime(Runtime::kStringToNumber);
-}
-
 void ToStringStub::Generate(MacroAssembler* masm) {
   // The ToString stub takes one argument in x0.
   Label is_number;
@@ -3669,14 +3442,14 @@
 
 void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  LoadICStub stub(isolate(), state());
+  LoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate(), state());
+  KeyedLoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -3815,8 +3588,8 @@
 
   __ Bind(&not_array);
   __ JumpIfNotRoot(feedback, Heap::kmegamorphic_symbolRootIndex, &miss);
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::LOAD_IC, code_flags,
                                                receiver, name, feedback,
                                                receiver_map, scratch1, x7);
@@ -3951,8 +3724,8 @@
 
   __ Bind(&not_array);
   __ JumpIfNotRoot(feedback, Heap::kmegamorphic_symbolRootIndex, &miss);
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, code_flags,
                                                receiver, key, feedback,
                                                receiver_map, scratch1, x8);
@@ -4576,19 +4349,13 @@
   }
 }
 
-
-void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
+void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
   ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
       isolate);
   ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
       isolate);
-  ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
-      isolate);
-}
-
-
-void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
-    Isolate* isolate) {
+  ArrayNArgumentsConstructorStub stub(isolate);
+  stub.GetCode();
   ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS };
   for (int i = 0; i < 2; i++) {
     // For internal arrays we only need a few things
@@ -4596,8 +4363,6 @@
     stubh1.GetCode();
     InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]);
     stubh2.GetCode();
-    InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]);
-    stubh3.GetCode();
   }
 }
 
@@ -4621,14 +4386,15 @@
 
     __ Bind(&n_case);
     // N arguments.
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
-
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else if (argument_count() == NONE) {
     CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
   } else if (argument_count() == ONE) {
     CreateArrayDispatchOneArgument(masm, mode);
   } else if (argument_count() == MORE_THAN_ONE) {
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else {
     UNREACHABLE();
   }
@@ -4743,7 +4509,7 @@
 
   __ Bind(&n_case);
   // N arguments.
-  InternalArrayNArgumentsConstructorStub stubN(isolate(), kind);
+  ArrayNArgumentsConstructorStub stubN(isolate());
   __ TailCallStub(&stubN);
 }
 
@@ -4829,17 +4595,18 @@
   __ Bind(&done_allocate);
 
   // Initialize the JSObject fields.
-  __ Mov(x1, x0);
   STATIC_ASSERT(JSObject::kMapOffset == 0 * kPointerSize);
-  __ Str(x2, MemOperand(x1, kPointerSize, PostIndex));
+  __ Str(x2, FieldMemOperand(x0, JSObject::kMapOffset));
   __ LoadRoot(x3, Heap::kEmptyFixedArrayRootIndex);
   STATIC_ASSERT(JSObject::kPropertiesOffset == 1 * kPointerSize);
   STATIC_ASSERT(JSObject::kElementsOffset == 2 * kPointerSize);
-  __ Stp(x3, x3, MemOperand(x1, 2 * kPointerSize, PostIndex));
+  __ Str(x3, FieldMemOperand(x0, JSObject::kPropertiesOffset));
+  __ Str(x3, FieldMemOperand(x0, JSObject::kElementsOffset));
   STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize);
+  __ Add(x1, x0, Operand(JSObject::kHeaderSize - kHeapObjectTag));
 
   // ----------- S t a t e -------------
-  //  -- x0 : result (untagged)
+  //  -- x0 : result (tagged)
   //  -- x1 : result fields (untagged)
   //  -- x5 : result end (untagged)
   //  -- x2 : initial map
@@ -4857,10 +4624,6 @@
   {
     // Initialize all in-object fields with undefined.
     __ InitializeFieldsWithFiller(x1, x5, x6);
-
-    // Add the object tag to make the JSObject real.
-    STATIC_ASSERT(kHeapObjectTag == 1);
-    __ Add(x0, x0, kHeapObjectTag);
     __ Ret();
   }
   __ Bind(&slack_tracking);
@@ -4879,10 +4642,6 @@
     __ LoadRoot(x6, Heap::kOnePointerFillerMapRootIndex);
     __ InitializeFieldsWithFiller(x1, x5, x6);
 
-    // Add the object tag to make the JSObject real.
-    STATIC_ASSERT(kHeapObjectTag == 1);
-    __ Add(x0, x0, kHeapObjectTag);
-
     // Check if we can finalize the instance size.
     Label finalize;
     STATIC_ASSERT(Map::kSlackTrackingCounterEnd == 1);
@@ -4912,10 +4671,10 @@
     __ CallRuntime(Runtime::kAllocateInNewSpace);
     __ Pop(x2);
   }
-  STATIC_ASSERT(kHeapObjectTag == 1);
-  __ Sub(x0, x0, kHeapObjectTag);
   __ Ldrb(x5, FieldMemOperand(x2, Map::kInstanceSizeOffset));
   __ Add(x5, x0, Operand(x5, LSL, kPointerSizeLog2));
+  STATIC_ASSERT(kHeapObjectTag == 1);
+  __ Sub(x5, x5, kHeapObjectTag);  // Subtract the tag from end.
   __ B(&done_allocate);
 
   // Fall back to %NewObject.
@@ -4934,20 +4693,20 @@
   // -----------------------------------
   __ AssertFunction(x1);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make x2 point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ Mov(x2, fp);
-    __ B(&loop_entry);
-    __ Bind(&loop);
+  // Make x2 point to the JavaScript frame.
+  __ Mov(x2, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ Ldr(x2, MemOperand(x2, StandardFrameConstants::kCallerFPOffset));
-    __ Bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ Ldr(x3, MemOperand(x2, StandardFrameConstants::kFunctionOffset));
     __ Cmp(x3, x1);
-    __ B(ne, &loop);
+    __ B(eq, &ok);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ Bind(&ok);
   }
 
   // Check if we have rest parameters (only possible if we have an
@@ -4963,10 +4722,10 @@
   Label rest_parameters;
   __ Ldrsw(x0, UntagSmiMemOperand(
                    x2, ArgumentsAdaptorFrameConstants::kLengthOffset));
-  __ Ldr(x1, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
+  __ Ldr(x3, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
   __ Ldrsw(
-      x1, FieldMemOperand(x1, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ Subs(x0, x0, x1);
+      x3, FieldMemOperand(x3, SharedFunctionInfo::kFormalParameterCountOffset));
+  __ Subs(x0, x0, x3);
   __ B(gt, &rest_parameters);
 
   // Return an empty rest parameter array.
@@ -4979,7 +4738,7 @@
 
     // Allocate an empty rest parameter array.
     Label allocate, done_allocate;
-    __ Allocate(JSArray::kSize, x0, x1, x2, &allocate, TAG_OBJECT);
+    __ Allocate(JSArray::kSize, x0, x1, x2, &allocate, NO_ALLOCATION_FLAGS);
     __ Bind(&done_allocate);
 
     // Setup the rest parameter array in x0.
@@ -5012,15 +4771,16 @@
     // ----------- S t a t e -------------
     //  -- cp : context
     //  -- x0 : number of rest parameters
+    //  -- x1 : function
     //  -- x2 : pointer to first rest parameters
     //  -- lr : return address
     // -----------------------------------
 
     // Allocate space for the rest parameter array plus the backing store.
     Label allocate, done_allocate;
-    __ Mov(x1, JSArray::kSize + FixedArray::kHeaderSize);
-    __ Add(x1, x1, Operand(x0, LSL, kPointerSizeLog2));
-    __ Allocate(x1, x3, x4, x5, &allocate, TAG_OBJECT);
+    __ Mov(x6, JSArray::kSize + FixedArray::kHeaderSize);
+    __ Add(x6, x6, Operand(x0, LSL, kPointerSizeLog2));
+    __ Allocate(x6, x3, x4, x5, &allocate, NO_ALLOCATION_FLAGS);
     __ Bind(&done_allocate);
 
     // Compute arguments.length in x6.
@@ -5055,19 +4815,27 @@
     STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
     __ Ret();
 
-    // Fall back to %AllocateInNewSpace.
+    // Fall back to %AllocateInNewSpace (if not too big).
+    Label too_big_for_new_space;
     __ Bind(&allocate);
+    __ Cmp(x6, Operand(Page::kMaxRegularHeapObjectSize));
+    __ B(gt, &too_big_for_new_space);
     {
       FrameScope scope(masm, StackFrame::INTERNAL);
       __ SmiTag(x0);
-      __ SmiTag(x1);
-      __ Push(x0, x2, x1);
+      __ SmiTag(x6);
+      __ Push(x0, x2, x6);
       __ CallRuntime(Runtime::kAllocateInNewSpace);
       __ Mov(x3, x0);
       __ Pop(x2, x0);
       __ SmiUntag(x0);
     }
     __ B(&done_allocate);
+
+    // Fall back to %NewRestParameter.
+    __ Bind(&too_big_for_new_space);
+    __ Push(x1);
+    __ TailCallRuntime(Runtime::kNewRestParameter);
   }
 }
 
@@ -5081,17 +4849,34 @@
   // -----------------------------------
   __ AssertFunction(x1);
 
+  // Make x6 point to the JavaScript frame.
+  __ Mov(x6, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
+    __ Ldr(x6, MemOperand(x6, StandardFrameConstants::kCallerFPOffset));
+  }
+  if (FLAG_debug_code) {
+    Label ok;
+    __ Ldr(x3, MemOperand(x6, StandardFrameConstants::kFunctionOffset));
+    __ Cmp(x3, x1);
+    __ B(eq, &ok);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ Bind(&ok);
+  }
+
   // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub.
   __ Ldr(x2, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
   __ Ldrsw(
       x2, FieldMemOperand(x2, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ Add(x3, fp, Operand(x2, LSL, kPointerSizeLog2));
+  __ Add(x3, x6, Operand(x2, LSL, kPointerSizeLog2));
   __ Add(x3, x3, Operand(StandardFrameConstants::kCallerSPOffset));
   __ SmiTag(x2);
 
   // x1 : function
   // x2 : number of parameters (tagged)
   // x3 : parameters pointer
+  // x6 : JavaScript frame pointer
   //
   // Returns pointer to result object in x0.
 
@@ -5109,7 +4894,7 @@
   Register caller_ctx = x12;
   Label runtime;
   Label adaptor_frame, try_allocate;
-  __ Ldr(caller_fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+  __ Ldr(caller_fp, MemOperand(x6, StandardFrameConstants::kCallerFPOffset));
   __ Ldr(
       caller_ctx,
       MemOperand(caller_fp, CommonFrameConstants::kContextOrFrameTypeOffset));
@@ -5180,7 +4965,7 @@
   // Do the allocation of all three objects in one go. Assign this to x0, as it
   // will be returned to the caller.
   Register alloc_obj = x0;
-  __ Allocate(size, alloc_obj, x11, x12, &runtime, TAG_OBJECT);
+  __ Allocate(size, alloc_obj, x11, x12, &runtime, NO_ALLOCATION_FLAGS);
 
   // Get the arguments boilerplate from the current (global) context.
 
@@ -5364,20 +5149,20 @@
   // -----------------------------------
   __ AssertFunction(x1);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make x2 point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ Mov(x2, fp);
-    __ B(&loop_entry);
-    __ Bind(&loop);
+  // Make x2 point to the JavaScript frame.
+  __ Mov(x2, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ Ldr(x2, MemOperand(x2, StandardFrameConstants::kCallerFPOffset));
-    __ Bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ Ldr(x3, MemOperand(x2, StandardFrameConstants::kFunctionOffset));
     __ Cmp(x3, x1);
-    __ B(ne, &loop);
+    __ B(eq, &ok);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ Bind(&ok);
   }
 
   // Check if we have an arguments adaptor frame below the function frame.
@@ -5387,9 +5172,9 @@
   __ Cmp(x4, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
   __ B(eq, &arguments_adaptor);
   {
-    __ Ldr(x1, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
+    __ Ldr(x4, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
     __ Ldrsw(x0, FieldMemOperand(
-                     x1, SharedFunctionInfo::kFormalParameterCountOffset));
+                     x4, SharedFunctionInfo::kFormalParameterCountOffset));
     __ Add(x2, x2, Operand(x0, LSL, kPointerSizeLog2));
     __ Add(x2, x2, StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize);
   }
@@ -5406,15 +5191,16 @@
   // ----------- S t a t e -------------
   //  -- cp : context
   //  -- x0 : number of rest parameters
+  //  -- x1 : function
   //  -- x2 : pointer to first rest parameters
   //  -- lr : return address
   // -----------------------------------
 
   // Allocate space for the strict arguments object plus the backing store.
   Label allocate, done_allocate;
-  __ Mov(x1, JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize);
-  __ Add(x1, x1, Operand(x0, LSL, kPointerSizeLog2));
-  __ Allocate(x1, x3, x4, x5, &allocate, TAG_OBJECT);
+  __ Mov(x6, JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize);
+  __ Add(x6, x6, Operand(x0, LSL, kPointerSizeLog2));
+  __ Allocate(x6, x3, x4, x5, &allocate, NO_ALLOCATION_FLAGS);
   __ Bind(&done_allocate);
 
   // Compute arguments.length in x6.
@@ -5449,48 +5235,27 @@
   STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
   __ Ret();
 
-  // Fall back to %AllocateInNewSpace.
+  // Fall back to %AllocateInNewSpace (if not too big).
+  Label too_big_for_new_space;
   __ Bind(&allocate);
+  __ Cmp(x6, Operand(Page::kMaxRegularHeapObjectSize));
+  __ B(gt, &too_big_for_new_space);
   {
     FrameScope scope(masm, StackFrame::INTERNAL);
     __ SmiTag(x0);
-    __ SmiTag(x1);
-    __ Push(x0, x2, x1);
+    __ SmiTag(x6);
+    __ Push(x0, x2, x6);
     __ CallRuntime(Runtime::kAllocateInNewSpace);
     __ Mov(x3, x0);
     __ Pop(x2, x0);
     __ SmiUntag(x0);
   }
   __ B(&done_allocate);
-}
 
-
-void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
-  Register context = cp;
-  Register result = x0;
-  Register slot = x2;
-  Label slow_case;
-
-  // Go up the context chain to the script context.
-  for (int i = 0; i < depth(); ++i) {
-    __ Ldr(result, ContextMemOperand(context, Context::PREVIOUS_INDEX));
-    context = result;
-  }
-
-  // Load the PropertyCell value at the specified slot.
-  __ Add(result, context, Operand(slot, LSL, kPointerSizeLog2));
-  __ Ldr(result, ContextMemOperand(result));
-  __ Ldr(result, FieldMemOperand(result, PropertyCell::kValueOffset));
-
-  // If the result is not the_hole, return. Otherwise, handle in the runtime.
-  __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &slow_case);
-  __ Ret();
-
-  // Fallback to runtime.
-  __ Bind(&slow_case);
-  __ SmiTag(slot);
-  __ Push(slot);
-  __ TailCallRuntime(Runtime::kLoadGlobalViaContext);
+  // Fall back to %NewStrictArguments.
+  __ Bind(&too_big_for_new_space);
+  __ Push(x1);
+  __ TailCallRuntime(Runtime::kNewStrictArguments);
 }
 
 
@@ -5807,9 +5572,15 @@
   STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
   STATIC_ASSERT(FCA::kIsolateIndex == 1);
   STATIC_ASSERT(FCA::kHolderIndex == 0);
-  STATIC_ASSERT(FCA::kArgsLength == 7);
+  STATIC_ASSERT(FCA::kNewTargetIndex == 7);
+  STATIC_ASSERT(FCA::kArgsLength == 8);
 
-  // FunctionCallbackArguments: context, callee and call data.
+  // FunctionCallbackArguments
+
+  // new target
+  __ PushRoot(Heap::kUndefinedValueRootIndex);
+
+  // context, callee and call data.
   __ Push(context, callee, call_data);
 
   if (!is_lazy()) {
@@ -5833,7 +5604,7 @@
 
   // Allocate the v8::Arguments structure in the arguments' space, since it's
   // not controlled by GC.
-  const int kApiStackSpace = 4;
+  const int kApiStackSpace = 3;
 
   // Allocate space for CallApiFunctionAndReturn can store some scratch
   // registeres on the stack.
@@ -5849,10 +5620,9 @@
   // FunctionCallbackInfo::implicit_args_ and FunctionCallbackInfo::values_
   __ Add(x10, args, Operand((FCA::kArgsLength - 1 + argc()) * kPointerSize));
   __ Stp(args, x10, MemOperand(x0, 0 * kPointerSize));
-  // FunctionCallbackInfo::length_ = argc and
-  // FunctionCallbackInfo::is_construct_call = 0
+  // FunctionCallbackInfo::length_ = argc
   __ Mov(x10, argc());
-  __ Stp(x10, xzr, MemOperand(x0, 2 * kPointerSize));
+  __ Str(x10, MemOperand(x0, 2 * kPointerSize));
 
   ExternalReference thunk_ref =
       ExternalReference::invoke_function_callback(masm->isolate());
@@ -5869,9 +5639,9 @@
   }
   MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
   int stack_space = 0;
-  MemOperand is_construct_call_operand =
-      MemOperand(masm->StackPointer(), 4 * kPointerSize);
-  MemOperand* stack_space_operand = &is_construct_call_operand;
+  MemOperand length_operand =
+      MemOperand(masm->StackPointer(), 3 * kPointerSize);
+  MemOperand* stack_space_operand = &length_operand;
   stack_space = argc() + FCA::kArgsLength + 1;
   stack_space_operand = NULL;
 
@@ -5883,15 +5653,34 @@
 
 
 void CallApiGetterStub::Generate(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- sp[0]                         : name
-  //  -- sp[8 .. (8 + kArgsLength*8)]  : v8::PropertyCallbackInfo::args_
-  //  -- ...
-  //  -- x2                            : api_function_address
-  // -----------------------------------
+  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
+  // name below the exit frame to make GC aware of them.
+  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
+  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
+  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
+  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
+  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
+  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
 
-  Register api_function_address = ApiGetterDescriptor::function_address();
-  DCHECK(api_function_address.is(x2));
+  Register receiver = ApiGetterDescriptor::ReceiverRegister();
+  Register holder = ApiGetterDescriptor::HolderRegister();
+  Register callback = ApiGetterDescriptor::CallbackRegister();
+  Register scratch = x4;
+  Register scratch2 = x5;
+  Register scratch3 = x6;
+  DCHECK(!AreAliased(receiver, holder, callback, scratch));
+
+  __ Push(receiver);
+
+  __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
+  __ Mov(scratch2, Operand(ExternalReference::isolate_address(isolate())));
+  __ Ldr(scratch3, FieldMemOperand(callback, AccessorInfo::kDataOffset));
+  __ Push(scratch3, scratch, scratch, scratch2, holder);
+  __ Push(Smi::FromInt(0));  // should_throw_on_error -> false
+  __ Ldr(scratch, FieldMemOperand(callback, AccessorInfo::kNameOffset));
+  __ Push(scratch);
 
   // v8::PropertyCallbackInfo::args_ array and name handle.
   const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
@@ -5918,6 +5707,11 @@
   ExternalReference thunk_ref =
       ExternalReference::invoke_accessor_getter_callback(isolate());
 
+  Register api_function_address = x2;
+  __ Ldr(scratch, FieldMemOperand(callback, AccessorInfo::kJsGetterOffset));
+  __ Ldr(api_function_address,
+         FieldMemOperand(scratch, Foreign::kForeignAddressOffset));
+
   const int spill_offset = 1 + kApiStackSpace;
   // +3 is to skip prolog, return address and name handle.
   MemOperand return_value_operand(
@@ -5927,7 +5721,6 @@
                            return_value_operand, NULL);
 }
 
-
 #undef __
 
 }  // namespace internal
diff --git a/src/arm64/codegen-arm64.cc b/src/arm64/codegen-arm64.cc
index c2073f1..edd2899 100644
--- a/src/arm64/codegen-arm64.cc
+++ b/src/arm64/codegen-arm64.cc
@@ -15,66 +15,6 @@
 
 #define __ ACCESS_MASM(masm)
 
-#if defined(USE_SIMULATOR)
-byte* fast_exp_arm64_machine_code = nullptr;
-double fast_exp_simulator(double x, Isolate* isolate) {
-  Simulator * simulator = Simulator::current(isolate);
-  Simulator::CallArgument args[] = {
-      Simulator::CallArgument(x),
-      Simulator::CallArgument::End()
-  };
-  return simulator->CallDouble(fast_exp_arm64_machine_code, args);
-}
-#endif
-
-
-UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) {
-  // Use the Math.exp implemetation in MathExpGenerator::EmitMathExp() to create
-  // an AAPCS64-compliant exp() function. This will be faster than the C
-  // library's exp() function, but probably less accurate.
-  size_t actual_size;
-  byte* buffer =
-      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
-  if (buffer == nullptr) return nullptr;
-
-  ExternalReference::InitializeMathExpData();
-  MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
-                      CodeObjectRequired::kNo);
-  masm.SetStackPointer(csp);
-
-  // The argument will be in d0 on entry.
-  DoubleRegister input = d0;
-  // Use other caller-saved registers for all other values.
-  DoubleRegister result = d1;
-  DoubleRegister double_temp1 = d2;
-  DoubleRegister double_temp2 = d3;
-  Register temp1 = x10;
-  Register temp2 = x11;
-  Register temp3 = x12;
-
-  MathExpGenerator::EmitMathExp(&masm, input, result,
-                                double_temp1, double_temp2,
-                                temp1, temp2, temp3);
-  // Move the result to the return register.
-  masm.Fmov(d0, result);
-  masm.Ret();
-
-  CodeDesc desc;
-  masm.GetCode(&desc);
-  DCHECK(!RelocInfo::RequiresRelocation(desc));
-
-  Assembler::FlushICache(isolate, buffer, actual_size);
-  base::OS::ProtectCode(buffer, actual_size);
-
-#if !defined(USE_SIMULATOR)
-  return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
-#else
-  fast_exp_arm64_machine_code = buffer;
-  return &fast_exp_simulator;
-#endif
-}
-
-
 UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
   return nullptr;
 }
@@ -175,8 +115,8 @@
   Register map_root = array_size;
   __ LoadRoot(map_root, Heap::kFixedDoubleArrayMapRootIndex);
   __ SmiTag(x11, length);
-  __ Str(x11, MemOperand(array, FixedDoubleArray::kLengthOffset));
-  __ Str(map_root, MemOperand(array, HeapObject::kMapOffset));
+  __ Str(x11, FieldMemOperand(array, FixedDoubleArray::kLengthOffset));
+  __ Str(map_root, FieldMemOperand(array, HeapObject::kMapOffset));
 
   __ Str(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
   __ RecordWriteField(receiver, HeapObject::kMapOffset, target_map, scratch,
@@ -184,18 +124,18 @@
                       OMIT_SMI_CHECK);
 
   // Replace receiver's backing store with newly created FixedDoubleArray.
-  __ Add(x10, array, kHeapObjectTag);
-  __ Str(x10, FieldMemOperand(receiver, JSObject::kElementsOffset));
-  __ RecordWriteField(receiver, JSObject::kElementsOffset, x10,
-                      scratch, kLRHasBeenSaved, kDontSaveFPRegs,
-                      EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+  __ Move(x10, array);
+  __ Str(array, FieldMemOperand(receiver, JSObject::kElementsOffset));
+  __ RecordWriteField(receiver, JSObject::kElementsOffset, x10, scratch,
+                      kLRHasBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
 
   // Prepare for conversion loop.
   Register src_elements = x10;
   Register dst_elements = x11;
   Register dst_end = x12;
   __ Add(src_elements, elements, FixedArray::kHeaderSize - kHeapObjectTag);
-  __ Add(dst_elements, array, FixedDoubleArray::kHeaderSize);
+  __ Add(dst_elements, array, FixedDoubleArray::kHeaderSize - kHeapObjectTag);
   __ Add(dst_end, dst_elements, Operand(length, LSL, kDoubleSizeLog2));
 
   FPRegister nan_d = d1;
@@ -282,8 +222,8 @@
   Register map_root = array_size;
   __ LoadRoot(map_root, Heap::kFixedArrayMapRootIndex);
   __ SmiTag(x11, length);
-  __ Str(x11, MemOperand(array, FixedDoubleArray::kLengthOffset));
-  __ Str(map_root, MemOperand(array, HeapObject::kMapOffset));
+  __ Str(x11, FieldMemOperand(array, FixedDoubleArray::kLengthOffset));
+  __ Str(map_root, FieldMemOperand(array, HeapObject::kMapOffset));
 
   // Prepare for conversion loop.
   Register src_elements = x10;
@@ -293,7 +233,7 @@
   __ LoadRoot(the_hole, Heap::kTheHoleValueRootIndex);
   __ Add(src_elements, elements,
          FixedDoubleArray::kHeaderSize - kHeapObjectTag);
-  __ Add(dst_elements, array, FixedArray::kHeaderSize);
+  __ Add(dst_elements, array, FixedArray::kHeaderSize - kHeapObjectTag);
   __ Add(dst_end, dst_elements, Operand(length, LSL, kPointerSizeLog2));
 
   // Allocating heap numbers in the loop below can fail and cause a jump to
@@ -307,8 +247,7 @@
   __ Cmp(dst_elements, dst_end);
   __ B(lt, &initialization_loop);
 
-  __ Add(dst_elements, array, FixedArray::kHeaderSize);
-  __ Add(array, array, kHeapObjectTag);
+  __ Add(dst_elements, array, FixedArray::kHeaderSize - kHeapObjectTag);
 
   Register heap_num_map = x15;
   __ LoadRoot(heap_num_map, Heap::kHeapNumberMapRootIndex);
@@ -511,127 +450,6 @@
   __ Bind(&done);
 }
 
-
-static MemOperand ExpConstant(Register base, int index) {
-  return MemOperand(base, index * kDoubleSize);
-}
-
-
-void MathExpGenerator::EmitMathExp(MacroAssembler* masm,
-                                   DoubleRegister input,
-                                   DoubleRegister result,
-                                   DoubleRegister double_temp1,
-                                   DoubleRegister double_temp2,
-                                   Register temp1,
-                                   Register temp2,
-                                   Register temp3) {
-  // TODO(jbramley): There are several instances where fnmsub could be used
-  // instead of fmul and fsub. Doing this changes the result, but since this is
-  // an estimation anyway, does it matter?
-
-  DCHECK(!AreAliased(input, result,
-                     double_temp1, double_temp2,
-                     temp1, temp2, temp3));
-  DCHECK(ExternalReference::math_exp_constants(0).address() != NULL);
-  DCHECK(!masm->serializer_enabled());  // External references not serializable.
-
-  Label done;
-  DoubleRegister double_temp3 = result;
-  Register constants = temp3;
-
-  // The algorithm used relies on some magic constants which are initialized in
-  // ExternalReference::InitializeMathExpData().
-
-  // Load the address of the start of the array.
-  __ Mov(constants, ExternalReference::math_exp_constants(0));
-
-  // We have to do a four-way split here:
-  //  - If input <= about -708.4, the output always rounds to zero.
-  //  - If input >= about 709.8, the output always rounds to +infinity.
-  //  - If the input is NaN, the output is NaN.
-  //  - Otherwise, the result needs to be calculated.
-  Label result_is_finite_non_zero;
-  // Assert that we can load offset 0 (the small input threshold) and offset 1
-  // (the large input threshold) with a single ldp.
-  DCHECK(kDRegSize == (ExpConstant(constants, 1).offset() -
-                              ExpConstant(constants, 0).offset()));
-  __ Ldp(double_temp1, double_temp2, ExpConstant(constants, 0));
-
-  __ Fcmp(input, double_temp1);
-  __ Fccmp(input, double_temp2, NoFlag, hi);
-  // At this point, the condition flags can be in one of five states:
-  //  NZCV
-  //  1000      -708.4 < input < 709.8    result = exp(input)
-  //  0110      input == 709.8            result = +infinity
-  //  0010      input > 709.8             result = +infinity
-  //  0011      input is NaN              result = input
-  //  0000      input <= -708.4           result = +0.0
-
-  // Continue the common case first. 'mi' tests N == 1.
-  __ B(&result_is_finite_non_zero, mi);
-
-  // TODO(jbramley): Consider adding a +infinity register for ARM64.
-  __ Ldr(double_temp2, ExpConstant(constants, 2));    // Synthesize +infinity.
-
-  // Select between +0.0 and +infinity. 'lo' tests C == 0.
-  __ Fcsel(result, fp_zero, double_temp2, lo);
-  // Select between {+0.0 or +infinity} and input. 'vc' tests V == 0.
-  __ Fcsel(result, result, input, vc);
-  __ B(&done);
-
-  // The rest is magic, as described in InitializeMathExpData().
-  __ Bind(&result_is_finite_non_zero);
-
-  // Assert that we can load offset 3 and offset 4 with a single ldp.
-  DCHECK(kDRegSize == (ExpConstant(constants, 4).offset() -
-                              ExpConstant(constants, 3).offset()));
-  __ Ldp(double_temp1, double_temp3, ExpConstant(constants, 3));
-  __ Fmadd(double_temp1, double_temp1, input, double_temp3);
-  __ Fmov(temp2.W(), double_temp1.S());
-  __ Fsub(double_temp1, double_temp1, double_temp3);
-
-  // Assert that we can load offset 5 and offset 6 with a single ldp.
-  DCHECK(kDRegSize == (ExpConstant(constants, 6).offset() -
-                              ExpConstant(constants, 5).offset()));
-  __ Ldp(double_temp2, double_temp3, ExpConstant(constants, 5));
-  // TODO(jbramley): Consider using Fnmsub here.
-  __ Fmul(double_temp1, double_temp1, double_temp2);
-  __ Fsub(double_temp1, double_temp1, input);
-
-  __ Fmul(double_temp2, double_temp1, double_temp1);
-  __ Fsub(double_temp3, double_temp3, double_temp1);
-  __ Fmul(double_temp3, double_temp3, double_temp2);
-
-  __ Mov(temp1.W(), Operand(temp2.W(), LSR, 11));
-
-  __ Ldr(double_temp2, ExpConstant(constants, 7));
-  // TODO(jbramley): Consider using Fnmsub here.
-  __ Fmul(double_temp3, double_temp3, double_temp2);
-  __ Fsub(double_temp3, double_temp3, double_temp1);
-
-  // The 8th constant is 1.0, so use an immediate move rather than a load.
-  // We can't generate a runtime assertion here as we would need to call Abort
-  // in the runtime and we don't have an Isolate when we generate this code.
-  __ Fmov(double_temp2, 1.0);
-  __ Fadd(double_temp3, double_temp3, double_temp2);
-
-  __ And(temp2, temp2, 0x7ff);
-  __ Add(temp1, temp1, 0x3ff);
-
-  // Do the final table lookup.
-  __ Mov(temp3, ExternalReference::math_exp_log_table());
-
-  __ Add(temp3, temp3, Operand(temp2, LSL, kDRegSizeLog2));
-  __ Ldp(temp2.W(), temp3.W(), MemOperand(temp3));
-  __ Orr(temp1.W(), temp3.W(), Operand(temp1.W(), LSL, 20));
-  __ Bfi(temp2, temp1, 32, 32);
-  __ Fmov(double_temp1, temp2);
-
-  __ Fmul(result, double_temp3, double_temp1);
-
-  __ Bind(&done);
-}
-
 #undef __
 
 }  // namespace internal
diff --git a/src/arm64/codegen-arm64.h b/src/arm64/codegen-arm64.h
index 573f6fe..b0490a8 100644
--- a/src/arm64/codegen-arm64.h
+++ b/src/arm64/codegen-arm64.h
@@ -27,22 +27,6 @@
   DISALLOW_COPY_AND_ASSIGN(StringCharLoadGenerator);
 };
 
-
-class MathExpGenerator : public AllStatic {
- public:
-  static void EmitMathExp(MacroAssembler* masm,
-                          DoubleRegister input,
-                          DoubleRegister result,
-                          DoubleRegister double_scratch1,
-                          DoubleRegister double_scratch2,
-                          Register temp1,
-                          Register temp2,
-                          Register temp3);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MathExpGenerator);
-};
-
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/arm64/constants-arm64.h b/src/arm64/constants-arm64.h
index 00b24e9..65b8b30 100644
--- a/src/arm64/constants-arm64.h
+++ b/src/arm64/constants-arm64.h
@@ -117,89 +117,89 @@
 const unsigned kFloatMantissaBits = 23;
 const unsigned kFloatExponentBits = 8;
 
-#define INSTRUCTION_FIELDS_LIST(V_)                                            \
-/* Register fields */                                                          \
-V_(Rd, 4, 0, Bits)                        /* Destination register.     */      \
-V_(Rn, 9, 5, Bits)                        /* First source register.    */      \
-V_(Rm, 20, 16, Bits)                      /* Second source register.   */      \
-V_(Ra, 14, 10, Bits)                      /* Third source register.    */      \
-V_(Rt, 4, 0, Bits)                        /* Load dest / store source. */      \
-V_(Rt2, 14, 10, Bits)                     /* Load second dest /        */      \
-                                         /* store second source.      */       \
-V_(PrefetchMode, 4, 0, Bits)                                                   \
-                                                                               \
-/* Common bits */                                                              \
-V_(SixtyFourBits, 31, 31, Bits)                                                \
-V_(FlagsUpdate, 29, 29, Bits)                                                  \
-                                                                               \
-/* PC relative addressing */                                                   \
-V_(ImmPCRelHi, 23, 5, SignedBits)                                              \
-V_(ImmPCRelLo, 30, 29, Bits)                                                   \
-                                                                               \
-/* Add/subtract/logical shift register */                                      \
-V_(ShiftDP, 23, 22, Bits)                                                      \
-V_(ImmDPShift, 15, 10, Bits)                                                   \
-                                                                               \
-/* Add/subtract immediate */                                                   \
-V_(ImmAddSub, 21, 10, Bits)                                                    \
-V_(ShiftAddSub, 23, 22, Bits)                                                  \
-                                                                               \
-/* Add/substract extend */                                                     \
-V_(ImmExtendShift, 12, 10, Bits)                                               \
-V_(ExtendMode, 15, 13, Bits)                                                   \
-                                                                               \
-/* Move wide */                                                                \
-V_(ImmMoveWide, 20, 5, Bits)                                                   \
-V_(ShiftMoveWide, 22, 21, Bits)                                                \
-                                                                               \
-/* Logical immediate, bitfield and extract */                                  \
-V_(BitN, 22, 22, Bits)                                                         \
-V_(ImmRotate, 21, 16, Bits)                                                    \
-V_(ImmSetBits, 15, 10, Bits)                                                   \
-V_(ImmR, 21, 16, Bits)                                                         \
-V_(ImmS, 15, 10, Bits)                                                         \
-                                                                               \
-/* Test and branch immediate */                                                \
-V_(ImmTestBranch, 18, 5, SignedBits)                                           \
-V_(ImmTestBranchBit40, 23, 19, Bits)                                           \
-V_(ImmTestBranchBit5, 31, 31, Bits)                                            \
-                                                                               \
-/* Conditionals */                                                             \
-V_(Condition, 15, 12, Bits)                                                    \
-V_(ConditionBranch, 3, 0, Bits)                                                \
-V_(Nzcv, 3, 0, Bits)                                                           \
-V_(ImmCondCmp, 20, 16, Bits)                                                   \
-V_(ImmCondBranch, 23, 5, SignedBits)                                           \
-                                                                               \
-/* Floating point */                                                           \
-V_(FPType, 23, 22, Bits)                                                       \
-V_(ImmFP, 20, 13, Bits)                                                        \
-V_(FPScale, 15, 10, Bits)                                                      \
-                                                                               \
-/* Load Store */                                                               \
-V_(ImmLS, 20, 12, SignedBits)                                                  \
-V_(ImmLSUnsigned, 21, 10, Bits)                                                \
-V_(ImmLSPair, 21, 15, SignedBits)                                              \
-V_(SizeLS, 31, 30, Bits)                                                       \
-V_(ImmShiftLS, 12, 12, Bits)                                                   \
-                                                                               \
-/* Other immediates */                                                         \
-V_(ImmUncondBranch, 25, 0, SignedBits)                                         \
-V_(ImmCmpBranch, 23, 5, SignedBits)                                            \
-V_(ImmLLiteral, 23, 5, SignedBits)                                             \
-V_(ImmException, 20, 5, Bits)                                                  \
-V_(ImmHint, 11, 5, Bits)                                                       \
-V_(ImmBarrierDomain, 11, 10, Bits)                                             \
-V_(ImmBarrierType, 9, 8, Bits)                                                 \
-                                                                               \
-/* System (MRS, MSR) */                                                        \
-V_(ImmSystemRegister, 19, 5, Bits)                                             \
-V_(SysO0, 19, 19, Bits)                                                        \
-V_(SysOp1, 18, 16, Bits)                                                       \
-V_(SysOp2, 7, 5, Bits)                                                         \
-V_(CRn, 15, 12, Bits)                                                          \
-V_(CRm, 11, 8, Bits)                                                           \
-
+#define INSTRUCTION_FIELDS_LIST(V_)                     \
+  /* Register fields */                                 \
+  V_(Rd, 4, 0, Bits)    /* Destination register.     */ \
+  V_(Rn, 9, 5, Bits)    /* First source register.    */ \
+  V_(Rm, 20, 16, Bits)  /* Second source register.   */ \
+  V_(Ra, 14, 10, Bits)  /* Third source register.    */ \
+  V_(Rt, 4, 0, Bits)    /* Load dest / store source. */ \
+  V_(Rt2, 14, 10, Bits) /* Load second dest /        */ \
+                        /* store second source.      */ \
+  V_(Rs, 20, 16, Bits)  /* Store-exclusive status */    \
+  V_(PrefetchMode, 4, 0, Bits)                          \
+                                                        \
+  /* Common bits */                                     \
+  V_(SixtyFourBits, 31, 31, Bits)                       \
+  V_(FlagsUpdate, 29, 29, Bits)                         \
+                                                        \
+  /* PC relative addressing */                          \
+  V_(ImmPCRelHi, 23, 5, SignedBits)                     \
+  V_(ImmPCRelLo, 30, 29, Bits)                          \
+                                                        \
+  /* Add/subtract/logical shift register */             \
+  V_(ShiftDP, 23, 22, Bits)                             \
+  V_(ImmDPShift, 15, 10, Bits)                          \
+                                                        \
+  /* Add/subtract immediate */                          \
+  V_(ImmAddSub, 21, 10, Bits)                           \
+  V_(ShiftAddSub, 23, 22, Bits)                         \
+                                                        \
+  /* Add/substract extend */                            \
+  V_(ImmExtendShift, 12, 10, Bits)                      \
+  V_(ExtendMode, 15, 13, Bits)                          \
+                                                        \
+  /* Move wide */                                       \
+  V_(ImmMoveWide, 20, 5, Bits)                          \
+  V_(ShiftMoveWide, 22, 21, Bits)                       \
+                                                        \
+  /* Logical immediate, bitfield and extract */         \
+  V_(BitN, 22, 22, Bits)                                \
+  V_(ImmRotate, 21, 16, Bits)                           \
+  V_(ImmSetBits, 15, 10, Bits)                          \
+  V_(ImmR, 21, 16, Bits)                                \
+  V_(ImmS, 15, 10, Bits)                                \
+                                                        \
+  /* Test and branch immediate */                       \
+  V_(ImmTestBranch, 18, 5, SignedBits)                  \
+  V_(ImmTestBranchBit40, 23, 19, Bits)                  \
+  V_(ImmTestBranchBit5, 31, 31, Bits)                   \
+                                                        \
+  /* Conditionals */                                    \
+  V_(Condition, 15, 12, Bits)                           \
+  V_(ConditionBranch, 3, 0, Bits)                       \
+  V_(Nzcv, 3, 0, Bits)                                  \
+  V_(ImmCondCmp, 20, 16, Bits)                          \
+  V_(ImmCondBranch, 23, 5, SignedBits)                  \
+                                                        \
+  /* Floating point */                                  \
+  V_(FPType, 23, 22, Bits)                              \
+  V_(ImmFP, 20, 13, Bits)                               \
+  V_(FPScale, 15, 10, Bits)                             \
+                                                        \
+  /* Load Store */                                      \
+  V_(ImmLS, 20, 12, SignedBits)                         \
+  V_(ImmLSUnsigned, 21, 10, Bits)                       \
+  V_(ImmLSPair, 21, 15, SignedBits)                     \
+  V_(SizeLS, 31, 30, Bits)                              \
+  V_(ImmShiftLS, 12, 12, Bits)                          \
+                                                        \
+  /* Other immediates */                                \
+  V_(ImmUncondBranch, 25, 0, SignedBits)                \
+  V_(ImmCmpBranch, 23, 5, SignedBits)                   \
+  V_(ImmLLiteral, 23, 5, SignedBits)                    \
+  V_(ImmException, 20, 5, Bits)                         \
+  V_(ImmHint, 11, 5, Bits)                              \
+  V_(ImmBarrierDomain, 11, 10, Bits)                    \
+  V_(ImmBarrierType, 9, 8, Bits)                        \
+                                                        \
+  /* System (MRS, MSR) */                               \
+  V_(ImmSystemRegister, 19, 5, Bits)                    \
+  V_(SysO0, 19, 19, Bits)                               \
+  V_(SysOp1, 18, 16, Bits)                              \
+  V_(SysOp2, 7, 5, Bits)                                \
+  V_(CRn, 15, 12, Bits)                                 \
+  V_(CRm, 11, 8, Bits)
 
 #define SYSTEM_REGISTER_FIELDS_LIST(V_, M_)                                    \
 /* NZCV */                                                                     \
@@ -857,6 +857,29 @@
   #undef LOAD_STORE_REGISTER_OFFSET
 };
 
+// Load/store acquire/release
+enum LoadStoreAcquireReleaseOp {
+  LoadStoreAcquireReleaseFixed = 0x08000000,
+  LoadStoreAcquireReleaseFMask = 0x3F000000,
+  LoadStoreAcquireReleaseMask = 0xCFC08000,
+  STLXR_b = LoadStoreAcquireReleaseFixed | 0x00008000,
+  LDAXR_b = LoadStoreAcquireReleaseFixed | 0x00408000,
+  STLR_b  = LoadStoreAcquireReleaseFixed | 0x00808000,
+  LDAR_b  = LoadStoreAcquireReleaseFixed | 0x00C08000,
+  STLXR_h = LoadStoreAcquireReleaseFixed | 0x40008000,
+  LDAXR_h = LoadStoreAcquireReleaseFixed | 0x40408000,
+  STLR_h  = LoadStoreAcquireReleaseFixed | 0x40808000,
+  LDAR_h  = LoadStoreAcquireReleaseFixed | 0x40C08000,
+  STLXR_w = LoadStoreAcquireReleaseFixed | 0x80008000,
+  LDAXR_w = LoadStoreAcquireReleaseFixed | 0x80408000,
+  STLR_w  = LoadStoreAcquireReleaseFixed | 0x80808000,
+  LDAR_w  = LoadStoreAcquireReleaseFixed | 0x80C08000,
+  STLXR_x = LoadStoreAcquireReleaseFixed | 0xC0008000,
+  LDAXR_x = LoadStoreAcquireReleaseFixed | 0xC0408000,
+  STLR_x  = LoadStoreAcquireReleaseFixed | 0xC0808000,
+  LDAR_x  = LoadStoreAcquireReleaseFixed | 0xC0C08000,
+};
+
 // Conditional compare.
 enum ConditionalCompareOp {
   ConditionalCompareMask = 0x60000000,
diff --git a/src/arm64/cpu-arm64.cc b/src/arm64/cpu-arm64.cc
index 712dbbd..7c1084f 100644
--- a/src/arm64/cpu-arm64.cc
+++ b/src/arm64/cpu-arm64.cc
@@ -58,14 +58,16 @@
   __asm__ __volatile__ (  // NOLINT
     // Clean every line of the D cache containing the target data.
     "0:                                \n\t"
-    // dc      : Data Cache maintenance
-    //    c    : Clean
-    //     va  : by (Virtual) Address
-    //       u : to the point of Unification
-    // The point of unification for a processor is the point by which the
-    // instruction and data caches are guaranteed to see the same copy of a
-    // memory location. See ARM DDI 0406B page B2-12 for more information.
-    "dc   cvau, %[dline]                \n\t"
+    // dc       : Data Cache maintenance
+    //    c     : Clean
+    //     i    : Invalidate
+    //      va  : by (Virtual) Address
+    //        c : to the point of Coherency
+    // See ARM DDI 0406B page B2-12 for more information.
+    // We would prefer to use "cvau" (clean to the point of unification) here
+    // but we use "civac" to work around Cortex-A53 errata 819472, 826319,
+    // 827319 and 824069.
+    "dc   civac, %[dline]               \n\t"
     "add  %[dline], %[dline], %[dsize]  \n\t"
     "cmp  %[dline], %[end]              \n\t"
     "b.lt 0b                            \n\t"
diff --git a/src/arm64/decoder-arm64-inl.h b/src/arm64/decoder-arm64-inl.h
index e00105e..2405f87 100644
--- a/src/arm64/decoder-arm64-inl.h
+++ b/src/arm64/decoder-arm64-inl.h
@@ -217,8 +217,15 @@
     if (instr->Bit(28) == 0) {
       if (instr->Bit(29) == 0) {
         if (instr->Bit(26) == 0) {
-          // TODO(all): VisitLoadStoreExclusive.
-          V::VisitUnimplemented(instr);
+          if (instr->Mask(0xA08000) == 0x800000 ||
+              instr->Mask(0xA00000) == 0xA00000) {
+            V::VisitUnallocated(instr);
+          } else if (instr->Mask(0x808000) == 0) {
+            // Load/Store exclusive without acquire/release are unimplemented.
+            V::VisitUnimplemented(instr);
+          } else {
+            V::VisitLoadStoreAcquireRelease(instr);
+          }
         } else {
           DecodeAdvSIMDLoadStore(instr);
         }
diff --git a/src/arm64/decoder-arm64.h b/src/arm64/decoder-arm64.h
index b1ef41f..a17b324 100644
--- a/src/arm64/decoder-arm64.h
+++ b/src/arm64/decoder-arm64.h
@@ -16,49 +16,50 @@
 
 // List macro containing all visitors needed by the decoder class.
 
-#define VISITOR_LIST(V)             \
-  V(PCRelAddressing)                \
-  V(AddSubImmediate)                \
-  V(LogicalImmediate)               \
-  V(MoveWideImmediate)              \
-  V(Bitfield)                       \
-  V(Extract)                        \
-  V(UnconditionalBranch)            \
-  V(UnconditionalBranchToRegister)  \
-  V(CompareBranch)                  \
-  V(TestBranch)                     \
-  V(ConditionalBranch)              \
-  V(System)                         \
-  V(Exception)                      \
-  V(LoadStorePairPostIndex)         \
-  V(LoadStorePairOffset)            \
-  V(LoadStorePairPreIndex)          \
-  V(LoadLiteral)                    \
-  V(LoadStoreUnscaledOffset)        \
-  V(LoadStorePostIndex)             \
-  V(LoadStorePreIndex)              \
-  V(LoadStoreRegisterOffset)        \
-  V(LoadStoreUnsignedOffset)        \
-  V(LogicalShifted)                 \
-  V(AddSubShifted)                  \
-  V(AddSubExtended)                 \
-  V(AddSubWithCarry)                \
-  V(ConditionalCompareRegister)     \
-  V(ConditionalCompareImmediate)    \
-  V(ConditionalSelect)              \
-  V(DataProcessing1Source)          \
-  V(DataProcessing2Source)          \
-  V(DataProcessing3Source)          \
-  V(FPCompare)                      \
-  V(FPConditionalCompare)           \
-  V(FPConditionalSelect)            \
-  V(FPImmediate)                    \
-  V(FPDataProcessing1Source)        \
-  V(FPDataProcessing2Source)        \
-  V(FPDataProcessing3Source)        \
-  V(FPIntegerConvert)               \
-  V(FPFixedPointConvert)            \
-  V(Unallocated)                    \
+#define VISITOR_LIST(V)            \
+  V(PCRelAddressing)               \
+  V(AddSubImmediate)               \
+  V(LogicalImmediate)              \
+  V(MoveWideImmediate)             \
+  V(Bitfield)                      \
+  V(Extract)                       \
+  V(UnconditionalBranch)           \
+  V(UnconditionalBranchToRegister) \
+  V(CompareBranch)                 \
+  V(TestBranch)                    \
+  V(ConditionalBranch)             \
+  V(System)                        \
+  V(Exception)                     \
+  V(LoadStorePairPostIndex)        \
+  V(LoadStorePairOffset)           \
+  V(LoadStorePairPreIndex)         \
+  V(LoadLiteral)                   \
+  V(LoadStoreUnscaledOffset)       \
+  V(LoadStorePostIndex)            \
+  V(LoadStorePreIndex)             \
+  V(LoadStoreRegisterOffset)       \
+  V(LoadStoreUnsignedOffset)       \
+  V(LoadStoreAcquireRelease)       \
+  V(LogicalShifted)                \
+  V(AddSubShifted)                 \
+  V(AddSubExtended)                \
+  V(AddSubWithCarry)               \
+  V(ConditionalCompareRegister)    \
+  V(ConditionalCompareImmediate)   \
+  V(ConditionalSelect)             \
+  V(DataProcessing1Source)         \
+  V(DataProcessing2Source)         \
+  V(DataProcessing3Source)         \
+  V(FPCompare)                     \
+  V(FPConditionalCompare)          \
+  V(FPConditionalSelect)           \
+  V(FPImmediate)                   \
+  V(FPDataProcessing1Source)       \
+  V(FPDataProcessing2Source)       \
+  V(FPDataProcessing3Source)       \
+  V(FPIntegerConvert)              \
+  V(FPFixedPointConvert)           \
+  V(Unallocated)                   \
   V(Unimplemented)
 
 // The Visitor interface. Disassembler and simulator (and other tools)
diff --git a/src/arm64/deoptimizer-arm64.cc b/src/arm64/deoptimizer-arm64.cc
index fe2a269..c1d04ac 100644
--- a/src/arm64/deoptimizer-arm64.cc
+++ b/src/arm64/deoptimizer-arm64.cc
@@ -97,8 +97,7 @@
   // Save all allocatable floating point registers.
   CPURegList saved_fp_registers(
       CPURegister::kFPRegister, kDRegSizeInBits,
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
-          ->allocatable_double_codes_mask());
+      RegisterConfiguration::Crankshaft()->allocatable_double_codes_mask());
   __ PushCPURegList(saved_fp_registers);
 
   // We save all the registers expcept jssp, sp and lr.
diff --git a/src/arm64/disasm-arm64.cc b/src/arm64/disasm-arm64.cc
index 00c3ec2..8e022b1 100644
--- a/src/arm64/disasm-arm64.cc
+++ b/src/arm64/disasm-arm64.cc
@@ -914,6 +914,34 @@
   Format(instr, mnemonic, form);
 }
 
+void DisassemblingDecoder::VisitLoadStoreAcquireRelease(Instruction *instr) {
+  const char *mnemonic = "unimplemented";
+  const char *form = "'Wt, ['Xn]";
+  const char *form_x = "'Xt, ['Xn]";
+  const char *form_stlx = "'Ws, 'Wt, ['Xn]";
+  const char *form_stlx_x = "'Ws, 'Xt, ['Xn]";
+
+  switch (instr->Mask(LoadStoreAcquireReleaseMask)) {
+    case LDAXR_b: mnemonic = "ldaxrb"; break;
+    case STLR_b:  mnemonic = "stlrb"; break;
+    case LDAR_b:  mnemonic = "ldarb"; break;
+    case LDAXR_h: mnemonic = "ldaxrh"; break;
+    case STLR_h:  mnemonic = "stlrh"; break;
+    case LDAR_h:  mnemonic = "ldarh"; break;
+    case LDAXR_w: mnemonic = "ldaxr"; break;
+    case STLR_w:  mnemonic = "stlr"; break;
+    case LDAR_w:  mnemonic = "ldar"; break;
+    case LDAXR_x: mnemonic = "ldaxr"; form = form_x; break;
+    case STLR_x:  mnemonic = "stlr"; form = form_x; break;
+    case LDAR_x:  mnemonic = "ldar"; form = form_x; break;
+    case STLXR_h: mnemonic = "stlxrh"; form = form_stlx; break;
+    case STLXR_b: mnemonic = "stlxrb"; form = form_stlx; break;
+    case STLXR_w: mnemonic = "stlxr"; form = form_stlx; break;
+    case STLXR_x: mnemonic = "stlxr"; form = form_stlx_x; break;
+    default: form = "(LoadStoreAcquireReleaseMask)";
+  }
+  Format(instr, mnemonic, form);
+}
 
 void DisassemblingDecoder::VisitFPCompare(Instruction* instr) {
   const char *mnemonic = "unimplemented";
@@ -1295,6 +1323,9 @@
       }
       break;
     }
+    case 's':
+      reg_num = instr->Rs();
+      break;
     default: UNREACHABLE();
   }
 
@@ -1719,7 +1750,7 @@
 
 
 const char* NameConverter::NameOfAddress(byte* addr) const {
-  v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
+  v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void *>(addr));
   return tmp_buffer_.start();
 }
 
@@ -1771,7 +1802,8 @@
   ~BufferDisassembler() { }
 
   virtual void ProcessOutput(v8::internal::Instruction* instr) {
-    v8::internal::SNPrintF(out_buffer_, "%s", GetOutput());
+    v8::internal::SNPrintF(out_buffer_, "%08" PRIx32 "       %s",
+                           instr->InstructionBits(), GetOutput());
   }
 
  private:
diff --git a/src/arm64/instrument-arm64.cc b/src/arm64/instrument-arm64.cc
index 7a8e2f4..dad89fe 100644
--- a/src/arm64/instrument-arm64.cc
+++ b/src/arm64/instrument-arm64.cc
@@ -429,6 +429,31 @@
   InstrumentLoadStore(instr);
 }
 
+void Instrument::VisitLoadStoreAcquireRelease(Instruction* instr) {
+  Update();
+  static Counter* load_counter = GetCounter("Load Acquire");
+  static Counter* store_counter = GetCounter("Store Release");
+
+  switch (instr->Mask(LoadStoreAcquireReleaseMask)) {
+    case LDAR_b:   // Fall-through.
+    case LDAR_h:   // Fall-through.
+    case LDAR_w:   // Fall-through.
+    case LDAR_x:   // Fall-through.
+    case LDAXR_b:  // Fall-through.
+    case LDAXR_h:  // Fall-through.
+    case LDAXR_w:  // Fall-through.
+    case LDAXR_x: load_counter->Increment(); break;
+    case STLR_b:   // Fall-through.
+    case STLR_h:   // Fall-through.
+    case STLR_w:   // Fall-through.
+    case STLR_x:   // Fall-through.
+    case STLXR_b:  // Fall-through.
+    case STLXR_h:  // Fall-through.
+    case STLXR_w:  // Fall-through.
+    case STLXR_x: store_counter->Increment(); break;
+    default: UNREACHABLE();
+  }
+}
 
 void Instrument::VisitLogicalShifted(Instruction* instr) {
   Update();
diff --git a/src/arm64/interface-descriptors-arm64.cc b/src/arm64/interface-descriptors-arm64.cc
index f307aeb..573d89e 100644
--- a/src/arm64/interface-descriptors-arm64.cc
+++ b/src/arm64/interface-descriptors-arm64.cc
@@ -13,6 +13,14 @@
 
 const Register CallInterfaceDescriptor::ContextRegister() { return cp; }
 
+void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
+    CallInterfaceDescriptorData* data, int register_parameter_count) {
+  const Register default_stub_registers[] = {x0, x1, x2, x3, x4};
+  CHECK_LE(static_cast<size_t>(register_parameter_count),
+           arraysize(default_stub_registers));
+  data->InitializePlatformSpecific(register_parameter_count,
+                                   default_stub_registers);
+}
 
 const Register LoadDescriptor::ReceiverRegister() { return x1; }
 const Register LoadDescriptor::NameRegister() { return x2; }
@@ -41,23 +49,15 @@
 const Register StoreTransitionDescriptor::MapRegister() { return x3; }
 
 
-const Register LoadGlobalViaContextDescriptor::SlotRegister() { return x2; }
-
-
 const Register StoreGlobalViaContextDescriptor::SlotRegister() { return x2; }
 const Register StoreGlobalViaContextDescriptor::ValueRegister() { return x0; }
 
 
-const Register InstanceOfDescriptor::LeftRegister() { return x1; }
-const Register InstanceOfDescriptor::RightRegister() { return x0; }
-
-
 const Register StringCompareDescriptor::LeftRegister() { return x1; }
 const Register StringCompareDescriptor::RightRegister() { return x0; }
 
-
-const Register ApiGetterDescriptor::function_address() { return x2; }
-
+const Register ApiGetterDescriptor::HolderRegister() { return x0; }
+const Register ApiGetterDescriptor::CallbackRegister() { return x3; }
 
 const Register MathPowTaggedDescriptor::exponent() { return x11; }
 
@@ -273,48 +273,34 @@
 SIMD128_TYPES(SIMD128_ALLOC_DESC)
 #undef SIMD128_ALLOC_DESC
 
-void AllocateInNewSpaceDescriptor::InitializePlatformSpecific(
+void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
-  Register registers[] = {x0};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-void ArrayConstructorConstantArgCountDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
+  // register state
   // x1: function
   // x2: allocation site with elements kind
   // x0: number of arguments to the constructor function
-  Register registers[] = {x1, x2};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
+  Register registers[] = {x1, x2, x0};
+  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
+void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  // register state
+  // x0: number of arguments
+  // x1: function
+  // x2: allocation site with elements kind
+  Register registers[] = {x1, x2, x0};
+  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
+}
 
-void ArrayConstructorDescriptor::InitializePlatformSpecific(
+void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // stack param count needs (constructor pointer, and single argument)
   Register registers[] = {x1, x2, x0};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
-
-void InternalArrayConstructorConstantArgCountDescriptor::
-    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
-  // x1: constructor function
-  // x0: number of arguments to the constructor function
-  Register registers[] = {x1};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-void InternalArrayConstructorDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  // stack param count needs (constructor pointer, and single argument)
-  Register registers[] = {x1, x0};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-void FastArrayPushDescriptor::InitializePlatformSpecific(
+void VarArgFunctionDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // stack param count needs (arg count)
   Register registers[] = {x0};
@@ -348,6 +334,11 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
+void CountOpDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {x1};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
 
 void StringAddDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
@@ -430,9 +421,8 @@
 void InterpreterDispatchDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {
-      kInterpreterAccumulatorRegister, kInterpreterRegisterFileRegister,
-      kInterpreterBytecodeOffsetRegister, kInterpreterBytecodeArrayRegister,
-      kInterpreterDispatchTableRegister};
+      kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
+      kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
@@ -467,6 +457,15 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
+void ResumeGeneratorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {
+      x0,  // the value to pass to the generator
+      x1,  // the JSGeneratorObject to resume
+      x2   // the resume mode (tagged)
+  };
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
 
 }  // namespace internal
 }  // namespace v8
diff --git a/src/arm64/macro-assembler-arm64-inl.h b/src/arm64/macro-assembler-arm64-inl.h
index 60418ad..f19d690 100644
--- a/src/arm64/macro-assembler-arm64-inl.h
+++ b/src/arm64/macro-assembler-arm64-inl.h
@@ -309,6 +309,22 @@
 LSPAIR_MACRO_LIST(DEFINE_FUNCTION)
 #undef DEFINE_FUNCTION
 
+#define DECLARE_FUNCTION(FN, OP)                                    \
+  void MacroAssembler::FN(const Register& rt, const Register& rn) { \
+    DCHECK(allow_macro_instructions_);                              \
+    OP(rt, rn);                                                     \
+  }
+LDA_STL_MACRO_LIST(DECLARE_FUNCTION)
+#undef DECLARE_FUNCTION
+
+#define DECLARE_FUNCTION(FN, OP)                                  \
+  void MacroAssembler::FN(const Register& rs, const Register& rt, \
+                          const Register& rn) {                   \
+    DCHECK(allow_macro_instructions_);                            \
+    OP(rs, rt, rn);                                               \
+  }
+STLX_MACRO_LIST(DECLARE_FUNCTION)
+#undef DECLARE_FUNCTION
 
 void MacroAssembler::Asr(const Register& rd,
                          const Register& rn,
diff --git a/src/arm64/macro-assembler-arm64.cc b/src/arm64/macro-assembler-arm64.cc
index 12ddd81..83b33b7 100644
--- a/src/arm64/macro-assembler-arm64.cc
+++ b/src/arm64/macro-assembler-arm64.cc
@@ -1373,10 +1373,6 @@
       Mrs(fpcr, FPCR);
     }
 
-    // Settings overridden by ConfiugreFPCR():
-    //   - Assert that default-NaN mode is set.
-    Tbz(fpcr, DN_offset, &unexpected_mode);
-
     // Settings left to their default values:
     //   - Assert that flush-to-zero is not set.
     Tbnz(fpcr, FZ_offset, &unexpected_mode);
@@ -1393,31 +1389,13 @@
 }
 
 
-void MacroAssembler::ConfigureFPCR() {
-  UseScratchRegisterScope temps(this);
-  Register fpcr = temps.AcquireX();
-  Mrs(fpcr, FPCR);
-
-  // If necessary, enable default-NaN mode. The default values of the other FPCR
-  // options should be suitable, and AssertFPCRState will verify that.
-  Label no_write_required;
-  Tbnz(fpcr, DN_offset, &no_write_required);
-
-  Orr(fpcr, fpcr, DN_mask);
-  Msr(FPCR, fpcr);
-
-  Bind(&no_write_required);
-  AssertFPCRState(fpcr);
-}
-
-
 void MacroAssembler::CanonicalizeNaN(const FPRegister& dst,
                                      const FPRegister& src) {
   AssertFPCRState();
 
-  // With DN=1 and RMode=FPTieEven, subtracting 0.0 preserves all inputs except
-  // for NaNs, which become the default NaN. We use fsub rather than fadd
-  // because sub preserves -0.0 inputs: -0.0 + 0.0 = 0.0, but -0.0 - 0.0 = -0.0.
+  // Subtracting 0.0 preserves all inputs except for signalling NaNs, which
+  // become quiet NaNs. We use fsub rather than fadd because fsub preserves -0.0
+  // inputs: -0.0 + 0.0 = 0.0, but -0.0 - 0.0 = -0.0.
   Fsub(dst, src, fp_zero);
 }
 
@@ -1558,7 +1536,7 @@
                                                      Label* no_memento_found) {
   Label map_check;
   Label top_check;
-  ExternalReference new_space_allocation_top =
+  ExternalReference new_space_allocation_top_adr =
       ExternalReference::new_space_allocation_top_address(isolate());
   const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
   const int kMementoEndOffset = kMementoMapOffset + AllocationMemento::kSize;
@@ -1568,7 +1546,9 @@
   Add(scratch1, receiver, kMementoEndOffset);
   // If the object is in new space, we need to check whether it is on the same
   // page as the current top.
-  Eor(scratch2, scratch1, new_space_allocation_top);
+  Mov(scratch2, new_space_allocation_top_adr);
+  Ldr(scratch2, MemOperand(scratch2));
+  Eor(scratch2, scratch1, scratch2);
   Tst(scratch2, ~Page::kPageAlignmentMask);
   B(eq, &top_check);
   // The object is on a different page than allocation top. Bail out if the
@@ -1582,7 +1562,9 @@
   // If top is on the same page as the current object, we need to check whether
   // we are below top.
   bind(&top_check);
-  Cmp(scratch1, new_space_allocation_top);
+  Mov(scratch2, new_space_allocation_top_adr);
+  Ldr(scratch2, MemOperand(scratch2));
+  Cmp(scratch1, scratch2);
   B(gt, no_memento_found);
   // Memento map check.
   bind(&map_check);
@@ -1659,6 +1641,17 @@
   }
 }
 
+void MacroAssembler::AssertGeneratorObject(Register object) {
+  if (emit_debug_code()) {
+    AssertNotSmi(object, kOperandIsASmiAndNotAGeneratorObject);
+
+    UseScratchRegisterScope temps(this);
+    Register temp = temps.AcquireX();
+
+    CompareObjectType(object, temp, temp, JS_GENERATOR_OBJECT_TYPE);
+    Check(eq, kOperandIsNotAGeneratorObject);
+  }
+}
 
 void MacroAssembler::AssertReceiver(Register object) {
   if (emit_debug_code()) {
@@ -1978,9 +1971,6 @@
   Label start_call;
   Bind(&start_call);
 #endif
-  // Statement positions are expected to be recorded when the target
-  // address is loaded.
-  positions_recorder()->WriteRecordedPositions();
 
   // Addresses always have 64 bits, so we shouldn't encounter NONE32.
   DCHECK(rmode != RelocInfo::NONE32);
@@ -2503,11 +2493,12 @@
                                              const ParameterCount& expected,
                                              const ParameterCount& actual) {
   Label skip_flooding;
-  ExternalReference step_in_enabled =
-      ExternalReference::debug_step_in_enabled_address(isolate());
-  Mov(x4, Operand(step_in_enabled));
-  ldrb(x4, MemOperand(x4));
-  CompareAndBranch(x4, Operand(0), eq, &skip_flooding);
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(isolate());
+  STATIC_ASSERT(StepFrame > StepIn);
+  Mov(x4, Operand(last_step_action));
+  Ldrsb(x4, MemOperand(x4));
+  CompareAndBranch(x4, Operand(StepIn), lt, &skip_flooding);
   {
     FrameScope frame(this,
                      has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
@@ -2768,9 +2759,8 @@
 
 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
   Ldr(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  Ldr(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset));
-  Ldr(vector,
-      FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset));
+  Ldr(vector, FieldMemOperand(vector, JSFunction::kLiteralsOffset));
+  Ldr(vector, FieldMemOperand(vector, LiteralsArray::kFeedbackVectorOffset));
 }
 
 
@@ -3041,6 +3031,7 @@
                               Label* gc_required,
                               AllocationFlags flags) {
   DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -3101,14 +3092,16 @@
 
   // Calculate new top and bail out if new space is exhausted.
   Adds(result_end, result, object_size);
-  Ccmp(result_end, alloc_limit, CFlag, cc);
+  Ccmp(result_end, alloc_limit, NoFlag, cc);
   B(hi, gc_required);
-  Str(result_end, MemOperand(top_address));
 
-  // Tag the object if requested.
-  if ((flags & TAG_OBJECT) != 0) {
-    ObjectTag(result, result);
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    Str(result_end, MemOperand(top_address));
   }
+
+  // Tag the object.
+  ObjectTag(result, result);
 }
 
 
@@ -3181,16 +3174,88 @@
     Check(eq, kUnalignedAllocationInNewSpace);
   }
 
-  Ccmp(result_end, alloc_limit, CFlag, cc);
+  Ccmp(result_end, alloc_limit, NoFlag, cc);
   B(hi, gc_required);
-  Str(result_end, MemOperand(top_address));
 
-  // Tag the object if requested.
-  if ((flags & TAG_OBJECT) != 0) {
-    ObjectTag(result, result);
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    Str(result_end, MemOperand(top_address));
   }
+
+  // Tag the object.
+  ObjectTag(result, result);
 }
 
+void MacroAssembler::FastAllocate(int object_size, Register result,
+                                  Register scratch1, Register scratch2,
+                                  AllocationFlags flags) {
+  DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
+
+  DCHECK(!AreAliased(result, scratch1, scratch2));
+  DCHECK(result.Is64Bits() && scratch1.Is64Bits() && scratch2.Is64Bits());
+
+  // Make object size into bytes.
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    object_size *= kPointerSize;
+  }
+  DCHECK(0 == (object_size & kObjectAlignmentMask));
+
+  ExternalReference heap_allocation_top =
+      AllocationUtils::GetAllocationTopReference(isolate(), flags);
+
+  // Set up allocation top address and allocation limit registers.
+  Register top_address = scratch1;
+  Register result_end = scratch2;
+  Mov(top_address, Operand(heap_allocation_top));
+  Ldr(result, MemOperand(top_address));
+
+  // We can ignore DOUBLE_ALIGNMENT flags here because doubles and pointers have
+  // the same alignment on ARM64.
+  STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
+
+  // Calculate new top and write it back.
+  Adds(result_end, result, object_size);
+  Str(result_end, MemOperand(top_address));
+
+  ObjectTag(result, result);
+}
+
+void MacroAssembler::FastAllocate(Register object_size, Register result,
+                                  Register result_end, Register scratch,
+                                  AllocationFlags flags) {
+  // |object_size| and |result_end| may overlap, other registers must not.
+  DCHECK(!AreAliased(object_size, result, scratch));
+  DCHECK(!AreAliased(result_end, result, scratch));
+  DCHECK(object_size.Is64Bits() && result.Is64Bits() && scratch.Is64Bits() &&
+         result_end.Is64Bits());
+
+  ExternalReference heap_allocation_top =
+      AllocationUtils::GetAllocationTopReference(isolate(), flags);
+
+  // Set up allocation top address and allocation limit registers.
+  Register top_address = scratch;
+  Mov(top_address, heap_allocation_top);
+  Ldr(result, MemOperand(top_address));
+
+  // We can ignore DOUBLE_ALIGNMENT flags here because doubles and pointers have
+  // the same alignment on ARM64.
+  STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
+
+  // Calculate new top and write it back.
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    Adds(result_end, result, Operand(object_size, LSL, kPointerSizeLog2));
+  } else {
+    Adds(result_end, result, object_size);
+  }
+  Str(result_end, MemOperand(top_address));
+
+  if (emit_debug_code()) {
+    Tst(result_end, kObjectAlignmentMask);
+    Check(eq, kUnalignedAllocationInNewSpace);
+  }
+
+  ObjectTag(result, result);
+}
 
 void MacroAssembler::AllocateTwoByteString(Register result,
                                            Register length,
@@ -3207,12 +3272,8 @@
   Bic(scratch1, scratch1, kObjectAlignmentMask);
 
   // Allocate two-byte string in new space.
-  Allocate(scratch1,
-           result,
-           scratch2,
-           scratch3,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(scratch1, result, scratch2, scratch3, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   InitializeNewString(result,
@@ -3236,12 +3297,8 @@
   Bic(scratch1, scratch1, kObjectAlignmentMask);
 
   // Allocate one-byte string in new space.
-  Allocate(scratch1,
-           result,
-           scratch2,
-           scratch3,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(scratch1, result, scratch2, scratch3, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   InitializeNewString(result, length, Heap::kOneByteStringMapRootIndex,
@@ -3255,7 +3312,7 @@
                                                Register scratch2,
                                                Label* gc_required) {
   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result,
                       length,
@@ -3269,12 +3326,8 @@
                                                Register scratch1,
                                                Register scratch2,
                                                Label* gc_required) {
-  Allocate(ConsString::kSize,
-           result,
-           scratch1,
-           scratch2,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result, length, Heap::kConsOneByteStringMapRootIndex,
                       scratch1, scratch2);
@@ -3288,7 +3341,7 @@
                                                  Label* gc_required) {
   DCHECK(!AreAliased(result, length, scratch1, scratch2));
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result,
                       length,
@@ -3305,7 +3358,7 @@
                                                  Label* gc_required) {
   DCHECK(!AreAliased(result, length, scratch1, scratch2));
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result, length, Heap::kSlicedOneByteStringMapRootIndex,
                       scratch1, scratch2);
@@ -3359,14 +3412,14 @@
   if (value.IsSameSizeAndType(heap_number_map)) {
     STATIC_ASSERT(HeapObject::kMapOffset + kPointerSize ==
                   HeapNumber::kValueOffset);
-    Stp(heap_number_map, value, MemOperand(result, HeapObject::kMapOffset));
+    Stp(heap_number_map, value,
+        FieldMemOperand(result, HeapObject::kMapOffset));
   } else {
-    Str(heap_number_map, MemOperand(result, HeapObject::kMapOffset));
+    Str(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
     if (value.IsValid()) {
-      Str(value, MemOperand(result, HeapNumber::kValueOffset));
+      Str(value, FieldMemOperand(result, HeapNumber::kValueOffset));
     }
   }
-  ObjectTag(result, result);
 }
 
 
@@ -3390,7 +3443,8 @@
   DCHECK(!result.is(value));
 
   // Allocate JSValue in new space.
-  Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required, TAG_OBJECT);
+  Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Initialize the JSValue.
   LoadGlobalFunctionInitialMap(constructor, scratch1, scratch2);
@@ -4075,16 +4129,14 @@
   PushSafepointRegisters();
   PushCPURegList(CPURegList(
       CPURegister::kFPRegister, kDRegSizeInBits,
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
-          ->allocatable_double_codes_mask()));
+      RegisterConfiguration::Crankshaft()->allocatable_double_codes_mask()));
 }
 
 
 void MacroAssembler::PopSafepointRegistersAndDoubles() {
   PopCPURegList(CPURegList(
       CPURegister::kFPRegister, kDRegSizeInBits,
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
-          ->allocatable_double_codes_mask()));
+      RegisterConfiguration::Crankshaft()->allocatable_double_codes_mask()));
   PopSafepointRegisters();
 }
 
diff --git a/src/arm64/macro-assembler-arm64.h b/src/arm64/macro-assembler-arm64.h
index 4b6b3c0..246d574 100644
--- a/src/arm64/macro-assembler-arm64.h
+++ b/src/arm64/macro-assembler-arm64.h
@@ -21,12 +21,15 @@
   #define ASM_UNIMPLEMENTED_BREAK(message)                                   \
   __ Debug(message, __LINE__,                                                \
            FLAG_ignore_asm_unimplemented_break ? NO_PARAM : BREAK)
-  #define ASM_LOCATION(message)                                              \
-  __ Debug("LOCATION: " message, __LINE__, NO_PARAM)
+#if DEBUG
+#define ASM_LOCATION(message) __ Debug("LOCATION: " message, __LINE__, NO_PARAM)
 #else
-  #define ASM_UNIMPLEMENTED(message)
-  #define ASM_UNIMPLEMENTED_BREAK(message)
-  #define ASM_LOCATION(message)
+#define ASM_LOCATION(message)
+#endif
+#else
+#define ASM_UNIMPLEMENTED(message)
+#define ASM_UNIMPLEMENTED_BREAK(message)
+#define ASM_LOCATION(message)
 #endif
 
 
@@ -39,8 +42,8 @@
 #define kReturnRegister2 x2
 #define kJSFunctionRegister x1
 #define kContextRegister cp
+#define kAllocateSizeRegister x1
 #define kInterpreterAccumulatorRegister x0
-#define kInterpreterRegisterFileRegister x18
 #define kInterpreterBytecodeOffsetRegister x19
 #define kInterpreterBytecodeArrayRegister x20
 #define kInterpreterDispatchTableRegister x21
@@ -65,6 +68,21 @@
   V(Stp, CPURegister&, rt, rt2, StorePairOpFor(rt, rt2)) \
   V(Ldpsw, CPURegister&, rt, rt2, LDPSW_x)
 
+#define LDA_STL_MACRO_LIST(V) \
+  V(Ldarb, ldarb)             \
+  V(Ldarh, ldarh)             \
+  V(Ldar, ldar)               \
+  V(Ldaxrb, ldaxrb)           \
+  V(Ldaxrh, ldaxrh)           \
+  V(Ldaxr, ldaxr)             \
+  V(Stlrb, stlrb)             \
+  V(Stlrh, stlrh)             \
+  V(Stlr, stlr)
+
+#define STLX_MACRO_LIST(V) \
+  V(Stlxrb, stlxrb)        \
+  V(Stlxrh, stlxrh)        \
+  V(Stlxr, stlxr)
 
 // ----------------------------------------------------------------------------
 // Static helper functions
@@ -292,6 +310,17 @@
   void LoadStorePairMacro(const CPURegister& rt, const CPURegister& rt2,
                           const MemOperand& addr, LoadStorePairOp op);
 
+// Load-acquire/store-release macros.
+#define DECLARE_FUNCTION(FN, OP) \
+  inline void FN(const Register& rt, const Register& rn);
+  LDA_STL_MACRO_LIST(DECLARE_FUNCTION)
+#undef DECLARE_FUNCTION
+
+#define DECLARE_FUNCTION(FN, OP) \
+  inline void FN(const Register& rs, const Register& rt, const Register& rn);
+  STLX_MACRO_LIST(DECLARE_FUNCTION)
+#undef DECLARE_FUNCTION
+
   // V8-specific load/store helpers.
   void Load(const Register& rt, const MemOperand& addr, Representation r);
   void Store(const Register& rt, const MemOperand& addr, Representation r);
@@ -865,7 +894,6 @@
   inline void InitializeRootRegister();
 
   void AssertFPCRState(Register fpcr = NoReg);
-  void ConfigureFPCR();
   void CanonicalizeNaN(const FPRegister& dst, const FPRegister& src);
   void CanonicalizeNaN(const FPRegister& reg) {
     CanonicalizeNaN(reg, reg);
@@ -970,6 +998,10 @@
   // Abort execution if argument is not a JSFunction, enabled via --debug-code.
   void AssertFunction(Register object);
 
+  // Abort execution if argument is not a JSGeneratorObject,
+  // enabled via --debug-code.
+  void AssertGeneratorObject(Register object);
+
   // Abort execution if argument is not a JSBoundFunction,
   // enabled via --debug-code.
   void AssertBoundFunction(Register object);
@@ -1306,7 +1338,6 @@
   //
   // If the new space is exhausted control continues at the gc_required label.
   // In this case, the result and scratch registers may still be clobbered.
-  // If flags includes TAG_OBJECT, the result is tagged as as a heap object.
   void Allocate(Register object_size, Register result, Register result_end,
                 Register scratch, Label* gc_required, AllocationFlags flags);
 
@@ -1317,6 +1348,15 @@
                 Label* gc_required,
                 AllocationFlags flags);
 
+  // FastAllocate is right now only used for folded allocations. It just
+  // increments the top pointer without checking against limit. This can only
+  // be done if it was proved earlier that the allocation will succeed.
+  void FastAllocate(Register object_size, Register result, Register result_end,
+                    Register scratch, AllocationFlags flags);
+
+  void FastAllocate(int object_size, Register result, Register scratch1,
+                    Register scratch2, AllocationFlags flags);
+
   void AllocateTwoByteString(Register result,
                              Register length,
                              Register scratch1,
diff --git a/src/arm64/simulator-arm64.cc b/src/arm64/simulator-arm64.cc
index 81dbdf8..aa10eb2 100644
--- a/src/arm64/simulator-arm64.cc
+++ b/src/arm64/simulator-arm64.cc
@@ -524,7 +524,7 @@
 
 
 // static
-void Simulator::TearDown(HashMap* i_cache, Redirection* first) {
+void Simulator::TearDown(base::HashMap* i_cache, Redirection* first) {
   Redirection::DeleteChain(first);
 }
 
@@ -609,7 +609,8 @@
                xreg(4), xreg(5), xreg(6), xreg(7));
       ObjectPair result = target(xreg(0), xreg(1), xreg(2), xreg(3),
                                  xreg(4), xreg(5), xreg(6), xreg(7));
-      TraceSim("Returned: {%p, %p}\n", result.x, result.y);
+      TraceSim("Returned: {%p, %p}\n", static_cast<void*>(result.x),
+               static_cast<void*>(result.y));
 #ifdef DEBUG
       CorruptAllCallerSavedCPURegisters();
 #endif
@@ -639,7 +640,8 @@
       ObjectTriple* sim_result = reinterpret_cast<ObjectTriple*>(xreg(8));
       ObjectTriple result = target(xreg(0), xreg(1), xreg(2), xreg(3), xreg(4),
                                    xreg(5), xreg(6), xreg(7));
-      TraceSim("Returned: {%p, %p, %p}\n", result.x, result.y, result.z);
+      TraceSim("Returned: {%p, %p, %p}\n", static_cast<void*>(result.x),
+               static_cast<void*>(result.y), static_cast<void*>(result.z));
 #ifdef DEBUG
       CorruptAllCallerSavedCPURegisters();
 #endif
@@ -1900,6 +1902,9 @@
   }
 }
 
+void Simulator::VisitLoadStoreAcquireRelease(Instruction* instr) {
+  // TODO(binji)
+}
 
 void Simulator::CheckMemoryAccess(uintptr_t address, uintptr_t stack) {
   if ((address >= stack_limit_) && (address < stack)) {
diff --git a/src/arm64/simulator-arm64.h b/src/arm64/simulator-arm64.h
index 724c767..cc2dcc2 100644
--- a/src/arm64/simulator-arm64.h
+++ b/src/arm64/simulator-arm64.h
@@ -14,6 +14,7 @@
 #include "src/arm64/disasm-arm64.h"
 #include "src/arm64/instrument-arm64.h"
 #include "src/assembler.h"
+#include "src/base/compiler-specific.h"
 #include "src/globals.h"
 #include "src/utils.h"
 
@@ -150,8 +151,7 @@
 
 class Simulator : public DecoderVisitor {
  public:
-  static void FlushICache(v8::internal::HashMap* i_cache, void* start,
-                          size_t size) {
+  static void FlushICache(base::HashMap* i_cache, void* start, size_t size) {
     USE(i_cache);
     USE(start);
     USE(size);
@@ -167,7 +167,7 @@
 
   static void Initialize(Isolate* isolate);
 
-  static void TearDown(HashMap* i_cache, Redirection* first);
+  static void TearDown(base::HashMap* i_cache, Redirection* first);
 
   static Simulator* current(v8::internal::Isolate* isolate);
 
@@ -794,7 +794,7 @@
   // Output stream.
   FILE* stream_;
   PrintDisassembler* print_disasm_;
-  void PRINTF_METHOD_CHECKING TraceSim(const char* format, ...);
+  void PRINTF_FORMAT(2, 3) TraceSim(const char* format, ...);
 
   // Instrumentation.
   Instrument* instrument_;
diff --git a/src/assembler.cc b/src/assembler.cc
index a912bb6..c7e819a 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -39,6 +39,7 @@
 #include "src/api.h"
 #include "src/base/cpu.h"
 #include "src/base/functional.h"
+#include "src/base/ieee754.h"
 #include "src/base/lazy-instance.h"
 #include "src/base/platform/platform.h"
 #include "src/base/utils/random-number-generator.h"
@@ -53,7 +54,6 @@
 #include "src/ic/stub-cache.h"
 #include "src/interpreter/interpreter.h"
 #include "src/ostreams.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/regexp/jsregexp.h"
 #include "src/regexp/regexp-macro-assembler.h"
 #include "src/regexp/regexp-stack.h"
@@ -114,39 +114,6 @@
 namespace internal {
 
 // -----------------------------------------------------------------------------
-// Common register code.
-
-const char* Register::ToString() {
-  // This is the mapping of allocation indices to registers.
-  DCHECK(reg_code >= 0 && reg_code < kNumRegisters);
-  return RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
-      ->GetGeneralRegisterName(reg_code);
-}
-
-
-bool Register::IsAllocatable() const {
-  return ((1 << reg_code) &
-          RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
-              ->allocatable_general_codes_mask()) != 0;
-}
-
-
-const char* DoubleRegister::ToString() {
-  // This is the mapping of allocation indices to registers.
-  DCHECK(reg_code >= 0 && reg_code < kMaxNumRegisters);
-  return RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
-      ->GetDoubleRegisterName(reg_code);
-}
-
-
-bool DoubleRegister::IsAllocatable() const {
-  return ((1 << reg_code) &
-          RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
-              ->allocatable_double_codes_mask()) != 0;
-}
-
-
-// -----------------------------------------------------------------------------
 // Common double constants.
 
 struct DoubleConstant BASE_EMBEDDED {
@@ -162,11 +129,6 @@
 
 const char* const RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
 
-static bool math_exp_data_initialized = false;
-static base::Mutex* math_exp_data_mutex = NULL;
-static double* math_exp_constants_array = NULL;
-static double* math_exp_log_table_array = NULL;
-
 // -----------------------------------------------------------------------------
 // Implementation of AssemblerBase
 
@@ -201,7 +163,6 @@
 
 void AssemblerBase::FlushICache(Isolate* isolate, void* start, size_t size) {
   if (size == 0) return;
-  if (CpuFeatures::IsSupported(COHERENT_CACHE)) return;
 
 #if defined(USE_SIMULATOR)
   Simulator::FlushICache(isolate->simulator_i_cache(), start, size);
@@ -362,6 +323,49 @@
 const int kStatementPositionTag = 2;
 const int kDeoptReasonTag = 3;
 
+void RelocInfo::update_wasm_memory_reference(
+    Address old_base, Address new_base, uint32_t old_size, uint32_t new_size,
+    ICacheFlushMode icache_flush_mode) {
+  DCHECK(IsWasmMemoryReference(rmode_) || IsWasmMemorySizeReference(rmode_));
+  if (IsWasmMemoryReference(rmode_)) {
+    Address updated_reference;
+    DCHECK(old_size == 0 || Memory::IsAddressInRange(
+                                old_base, wasm_memory_reference(), old_size));
+    updated_reference = new_base + (wasm_memory_reference() - old_base);
+    DCHECK(new_size == 0 ||
+           Memory::IsAddressInRange(new_base, updated_reference, new_size));
+    unchecked_update_wasm_memory_reference(updated_reference,
+                                           icache_flush_mode);
+  } else if (IsWasmMemorySizeReference(rmode_)) {
+    uint32_t updated_size_reference;
+    DCHECK(old_size == 0 || wasm_memory_size_reference() <= old_size);
+    updated_size_reference =
+        new_size + (wasm_memory_size_reference() - old_size);
+    DCHECK(updated_size_reference <= new_size);
+    unchecked_update_wasm_memory_size(updated_size_reference,
+                                      icache_flush_mode);
+  } else {
+    UNREACHABLE();
+  }
+  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
+    Assembler::FlushICache(isolate_, pc_, sizeof(int64_t));
+  }
+}
+
+void RelocInfo::update_wasm_global_reference(
+    Address old_base, Address new_base, ICacheFlushMode icache_flush_mode) {
+  DCHECK(IsWasmGlobalReference(rmode_));
+  Address updated_reference;
+  DCHECK(reinterpret_cast<uintptr_t>(old_base) <=
+         reinterpret_cast<uintptr_t>(wasm_global_reference()));
+  updated_reference = new_base + (wasm_global_reference() - old_base);
+  DCHECK(reinterpret_cast<uintptr_t>(new_base) <=
+         reinterpret_cast<uintptr_t>(updated_reference));
+  unchecked_update_wasm_memory_reference(updated_reference, icache_flush_mode);
+  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
+    Assembler::FlushICache(isolate_, pc_, sizeof(int32_t));
+  }
+}
 
 uint32_t RelocInfoWriter::WriteLongPCJump(uint32_t pc_delta) {
   // Return if the pc_delta can fit in kSmallPCDeltaBits bits.
@@ -514,7 +518,8 @@
     if (RelocInfo::IsComment(rmode)) {
       WriteData(rinfo->data());
     } else if (RelocInfo::IsConstPool(rmode) ||
-               RelocInfo::IsVeneerPool(rmode)) {
+               RelocInfo::IsVeneerPool(rmode) ||
+               RelocInfo::IsDeoptId(rmode)) {
       WriteIntData(static_cast<int>(rinfo->data()));
     }
   }
@@ -705,7 +710,8 @@
             Advance(kIntSize);
           }
         } else if (RelocInfo::IsConstPool(rmode) ||
-                   RelocInfo::IsVeneerPool(rmode)) {
+                   RelocInfo::IsVeneerPool(rmode) ||
+                   RelocInfo::IsDeoptId(rmode)) {
           if (SetMode(rmode)) {
             AdvanceReadInt();
             return;
@@ -828,6 +834,8 @@
       return "encoded internal reference";
     case DEOPT_REASON:
       return "deopt reason";
+    case DEOPT_ID:
+      return "deopt index";
     case CONST_POOL:
       return "constant pool";
     case VENEER_POOL:
@@ -846,6 +854,10 @@
       return "generator continuation";
     case WASM_MEMORY_REFERENCE:
       return "wasm memory reference";
+    case WASM_MEMORY_SIZE_REFERENCE:
+      return "wasm memory size reference";
+    case WASM_GLOBAL_REFERENCE:
+      return "wasm global value reference";
     case NUMBER_OF_MODES:
     case PC_JUMP:
       UNREACHABLE();
@@ -933,6 +945,7 @@
     case STATEMENT_POSITION:
     case EXTERNAL_REFERENCE:
     case DEOPT_REASON:
+    case DEOPT_ID:
     case CONST_POOL:
     case VENEER_POOL:
     case DEBUG_BREAK_SLOT_AT_POSITION:
@@ -941,6 +954,8 @@
     case DEBUG_BREAK_SLOT_AT_TAIL_CALL:
     case GENERATOR_CONTINUATION:
     case WASM_MEMORY_REFERENCE:
+    case WASM_MEMORY_SIZE_REFERENCE:
+    case WASM_GLOBAL_REFERENCE:
     case NONE32:
     case NONE64:
       break;
@@ -980,61 +995,6 @@
   double_constants.negative_infinity = -V8_INFINITY;
   double_constants.uint32_bias =
     static_cast<double>(static_cast<uint32_t>(0xFFFFFFFF)) + 1;
-
-  math_exp_data_mutex = new base::Mutex();
-}
-
-
-void ExternalReference::InitializeMathExpData() {
-  // Early return?
-  if (math_exp_data_initialized) return;
-
-  base::LockGuard<base::Mutex> lock_guard(math_exp_data_mutex);
-  if (!math_exp_data_initialized) {
-    // If this is changed, generated code must be adapted too.
-    const int kTableSizeBits = 11;
-    const int kTableSize = 1 << kTableSizeBits;
-    const double kTableSizeDouble = static_cast<double>(kTableSize);
-
-    math_exp_constants_array = new double[9];
-    // Input values smaller than this always return 0.
-    math_exp_constants_array[0] = -708.39641853226408;
-    // Input values larger than this always return +Infinity.
-    math_exp_constants_array[1] = 709.78271289338397;
-    math_exp_constants_array[2] = V8_INFINITY;
-    // The rest is black magic. Do not attempt to understand it. It is
-    // loosely based on the "expd" function published at:
-    // http://herumi.blogspot.com/2011/08/fast-double-precision-exponential.html
-    const double constant3 = (1 << kTableSizeBits) / std::log(2.0);
-    math_exp_constants_array[3] = constant3;
-    math_exp_constants_array[4] =
-        static_cast<double>(static_cast<int64_t>(3) << 51);
-    math_exp_constants_array[5] = 1 / constant3;
-    math_exp_constants_array[6] = 3.0000000027955394;
-    math_exp_constants_array[7] = 0.16666666685227835;
-    math_exp_constants_array[8] = 1;
-
-    math_exp_log_table_array = new double[kTableSize];
-    for (int i = 0; i < kTableSize; i++) {
-      double value = std::pow(2, i / kTableSizeDouble);
-      uint64_t bits = bit_cast<uint64_t, double>(value);
-      bits &= (static_cast<uint64_t>(1) << 52) - 1;
-      double mantissa = bit_cast<double, uint64_t>(bits);
-      math_exp_log_table_array[i] = mantissa;
-    }
-
-    math_exp_data_initialized = true;
-  }
-}
-
-
-void ExternalReference::TearDownMathExpData() {
-  delete[] math_exp_constants_array;
-  math_exp_constants_array = NULL;
-  delete[] math_exp_log_table_array;
-  math_exp_log_table_array = NULL;
-  delete math_exp_data_mutex;
-  math_exp_data_mutex = NULL;
 }
 
 
@@ -1072,6 +1032,12 @@
   return ExternalReference(isolate->interpreter()->dispatch_table_address());
 }
 
+ExternalReference ExternalReference::interpreter_dispatch_counters(
+    Isolate* isolate) {
+  return ExternalReference(
+      isolate->interpreter()->bytecode_dispatch_counters_table());
+}
+
 ExternalReference::ExternalReference(StatsCounter* counter)
   : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}
 
@@ -1255,64 +1221,47 @@
       Redirect(isolate, FUNCTION_ADDR(wasm::uint64_mod_wrapper)));
 }
 
-static void f64_acos_wrapper(double* param) { *param = std::acos(*param); }
+ExternalReference ExternalReference::wasm_word32_ctz(Isolate* isolate) {
+  return ExternalReference(
+      Redirect(isolate, FUNCTION_ADDR(wasm::word32_ctz_wrapper)));
+}
+
+ExternalReference ExternalReference::wasm_word64_ctz(Isolate* isolate) {
+  return ExternalReference(
+      Redirect(isolate, FUNCTION_ADDR(wasm::word64_ctz_wrapper)));
+}
+
+ExternalReference ExternalReference::wasm_word32_popcnt(Isolate* isolate) {
+  return ExternalReference(
+      Redirect(isolate, FUNCTION_ADDR(wasm::word32_popcnt_wrapper)));
+}
+
+ExternalReference ExternalReference::wasm_word64_popcnt(Isolate* isolate) {
+  return ExternalReference(
+      Redirect(isolate, FUNCTION_ADDR(wasm::word64_popcnt_wrapper)));
+}
+
+static void f64_acos_wrapper(double* param) {
+  WriteDoubleValue(param, std::acos(ReadDoubleValue(param)));
+}
 
 ExternalReference ExternalReference::f64_acos_wrapper_function(
     Isolate* isolate) {
   return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_acos_wrapper)));
 }
 
-static void f64_asin_wrapper(double* param) { *param = std::asin(*param); }
+static void f64_asin_wrapper(double* param) {
+  WriteDoubleValue(param, std::asin(ReadDoubleValue(param)));
+}
 
 ExternalReference ExternalReference::f64_asin_wrapper_function(
     Isolate* isolate) {
   return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_asin_wrapper)));
 }
 
-static void f64_atan_wrapper(double* param) { *param = std::atan(*param); }
-
-ExternalReference ExternalReference::f64_atan_wrapper_function(
-    Isolate* isolate) {
-  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_atan_wrapper)));
-}
-
-static void f64_cos_wrapper(double* param) { *param = std::cos(*param); }
-
-ExternalReference ExternalReference::f64_cos_wrapper_function(
-    Isolate* isolate) {
-  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_cos_wrapper)));
-}
-
-static void f64_sin_wrapper(double* param) { *param = std::sin(*param); }
-
-ExternalReference ExternalReference::f64_sin_wrapper_function(
-    Isolate* isolate) {
-  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_sin_wrapper)));
-}
-
-static void f64_tan_wrapper(double* param) { *param = std::tan(*param); }
-
-ExternalReference ExternalReference::f64_tan_wrapper_function(
-    Isolate* isolate) {
-  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_tan_wrapper)));
-}
-
-static void f64_exp_wrapper(double* param) { *param = std::exp(*param); }
-
-ExternalReference ExternalReference::f64_exp_wrapper_function(
-    Isolate* isolate) {
-  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_exp_wrapper)));
-}
-
-static void f64_log_wrapper(double* param) { *param = std::log(*param); }
-
-ExternalReference ExternalReference::f64_log_wrapper_function(
-    Isolate* isolate) {
-  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_log_wrapper)));
-}
-
 static void f64_pow_wrapper(double* param0, double* param1) {
-  *param0 = power_double_double(*param0, *param1);
+  WriteDoubleValue(param0, power_double_double(ReadDoubleValue(param0),
+                                               ReadDoubleValue(param1)));
 }
 
 ExternalReference ExternalReference::f64_pow_wrapper_function(
@@ -1320,32 +1269,9 @@
   return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_pow_wrapper)));
 }
 
-static void f64_atan2_wrapper(double* param0, double* param1) {
-  double x = *param0;
-  double y = *param1;
-  // TODO(bradnelson): Find a good place to put this to share
-  // with the same code in src/runtime/runtime-math.cc
-  static const double kPiDividedBy4 = 0.78539816339744830962;
-  if (std::isinf(x) && std::isinf(y)) {
-    // Make sure that the result in case of two infinite arguments
-    // is a multiple of Pi / 4. The sign of the result is determined
-    // by the first argument (x) and the sign of the second argument
-    // determines the multiplier: one or three.
-    int multiplier = (x < 0) ? -1 : 1;
-    if (y < 0) multiplier *= 3;
-    *param0 = multiplier * kPiDividedBy4;
-  } else {
-    *param0 = std::atan2(x, y);
-  }
-}
-
-ExternalReference ExternalReference::f64_atan2_wrapper_function(
-    Isolate* isolate) {
-  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(f64_atan2_wrapper)));
-}
-
 static void f64_mod_wrapper(double* param0, double* param1) {
-  *param0 = modulo(*param0, *param1);
+  WriteDoubleValue(param0,
+                   modulo(ReadDoubleValue(param0), ReadDoubleValue(param1)));
 }
 
 ExternalReference ExternalReference::f64_mod_wrapper_function(
@@ -1500,7 +1426,7 @@
 
 
 ExternalReference ExternalReference::is_profiling_address(Isolate* isolate) {
-  return ExternalReference(isolate->cpu_profiler()->is_profiling_address());
+  return ExternalReference(isolate->is_profiling_address());
 }
 
 
@@ -1590,28 +1516,70 @@
 
 #endif  // V8_INTERPRETED_REGEXP
 
-
-ExternalReference ExternalReference::math_log_double_function(
-    Isolate* isolate) {
-  typedef double (*d2d)(double x);
-  return ExternalReference(Redirect(isolate,
-                                    FUNCTION_ADDR(static_cast<d2d>(std::log)),
-                                    BUILTIN_FP_CALL));
-}
-
-
-ExternalReference ExternalReference::math_exp_constants(int constant_index) {
-  DCHECK(math_exp_data_initialized);
+ExternalReference ExternalReference::ieee754_atan_function(Isolate* isolate) {
   return ExternalReference(
-      reinterpret_cast<void*>(math_exp_constants_array + constant_index));
+      Redirect(isolate, FUNCTION_ADDR(base::ieee754::atan), BUILTIN_FP_CALL));
 }
 
-
-ExternalReference ExternalReference::math_exp_log_table() {
-  DCHECK(math_exp_data_initialized);
-  return ExternalReference(reinterpret_cast<void*>(math_exp_log_table_array));
+ExternalReference ExternalReference::ieee754_atan2_function(Isolate* isolate) {
+  return ExternalReference(Redirect(
+      isolate, FUNCTION_ADDR(base::ieee754::atan2), BUILTIN_FP_FP_CALL));
 }
 
+ExternalReference ExternalReference::ieee754_atanh_function(Isolate* isolate) {
+  return ExternalReference(Redirect(
+      isolate, FUNCTION_ADDR(base::ieee754::atanh), BUILTIN_FP_FP_CALL));
+}
+
+ExternalReference ExternalReference::ieee754_cbrt_function(Isolate* isolate) {
+  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(base::ieee754::cbrt),
+                                    BUILTIN_FP_FP_CALL));
+}
+
+ExternalReference ExternalReference::ieee754_cos_function(Isolate* isolate) {
+  return ExternalReference(
+      Redirect(isolate, FUNCTION_ADDR(base::ieee754::cos), BUILTIN_FP_CALL));
+}
+
+ExternalReference ExternalReference::ieee754_exp_function(Isolate* isolate) {
+  return ExternalReference(
+      Redirect(isolate, FUNCTION_ADDR(base::ieee754::exp), BUILTIN_FP_CALL));
+}
+
+ExternalReference ExternalReference::ieee754_expm1_function(Isolate* isolate) {
+  return ExternalReference(Redirect(
+      isolate, FUNCTION_ADDR(base::ieee754::expm1), BUILTIN_FP_FP_CALL));
+}
+
+ExternalReference ExternalReference::ieee754_log_function(Isolate* isolate) {
+  return ExternalReference(
+      Redirect(isolate, FUNCTION_ADDR(base::ieee754::log), BUILTIN_FP_CALL));
+}
+
+ExternalReference ExternalReference::ieee754_log1p_function(Isolate* isolate) {
+  return ExternalReference(
+      Redirect(isolate, FUNCTION_ADDR(base::ieee754::log1p), BUILTIN_FP_CALL));
+}
+
+ExternalReference ExternalReference::ieee754_log10_function(Isolate* isolate) {
+  return ExternalReference(
+      Redirect(isolate, FUNCTION_ADDR(base::ieee754::log10), BUILTIN_FP_CALL));
+}
+
+ExternalReference ExternalReference::ieee754_log2_function(Isolate* isolate) {
+  return ExternalReference(
+      Redirect(isolate, FUNCTION_ADDR(base::ieee754::log2), BUILTIN_FP_CALL));
+}
+
+ExternalReference ExternalReference::ieee754_sin_function(Isolate* isolate) {
+  return ExternalReference(
+      Redirect(isolate, FUNCTION_ADDR(base::ieee754::sin), BUILTIN_FP_CALL));
+}
+
+ExternalReference ExternalReference::ieee754_tan_function(Isolate* isolate) {
+  return ExternalReference(
+      Redirect(isolate, FUNCTION_ADDR(base::ieee754::tan), BUILTIN_FP_CALL));
+}
 
 ExternalReference ExternalReference::page_flags(Page* page) {
   return ExternalReference(reinterpret_cast<Address>(page) +
@@ -1735,12 +1703,15 @@
                                     BUILTIN_FP_FP_CALL));
 }
 
-
-ExternalReference ExternalReference::debug_step_in_enabled_address(
+ExternalReference ExternalReference::debug_last_step_action_address(
     Isolate* isolate) {
-  return ExternalReference(isolate->debug()->step_in_enabled_address());
+  return ExternalReference(isolate->debug()->last_step_action_address());
 }
 
+ExternalReference ExternalReference::debug_suspended_generator_address(
+    Isolate* isolate) {
+  return ExternalReference(isolate->debug()->suspended_generator_address());
+}
 
 ExternalReference ExternalReference::fixed_typed_array_base_data_offset() {
   return ExternalReference(reinterpret_cast<void*>(
@@ -1773,49 +1744,44 @@
 void AssemblerPositionsRecorder::RecordPosition(int pos) {
   DCHECK(pos != RelocInfo::kNoPosition);
   DCHECK(pos >= 0);
-  state_.current_position = pos;
+  current_position_ = pos;
   LOG_CODE_EVENT(assembler_->isolate(),
                  CodeLinePosInfoAddPositionEvent(jit_handler_data_,
                                                  assembler_->pc_offset(),
                                                  pos));
+  WriteRecordedPositions();
 }
 
 void AssemblerPositionsRecorder::RecordStatementPosition(int pos) {
   DCHECK(pos != RelocInfo::kNoPosition);
   DCHECK(pos >= 0);
-  state_.current_statement_position = pos;
+  current_statement_position_ = pos;
   LOG_CODE_EVENT(assembler_->isolate(),
                  CodeLinePosInfoAddStatementPositionEvent(
                      jit_handler_data_,
                      assembler_->pc_offset(),
                      pos));
+  RecordPosition(pos);
 }
 
-bool AssemblerPositionsRecorder::WriteRecordedPositions() {
-  bool written = false;
-
+void AssemblerPositionsRecorder::WriteRecordedPositions() {
   // Write the statement position if it is different from what was written last
   // time.
-  if (state_.current_statement_position != state_.written_statement_position) {
+  if (current_statement_position_ != written_statement_position_) {
     EnsureSpace ensure_space(assembler_);
     assembler_->RecordRelocInfo(RelocInfo::STATEMENT_POSITION,
-                                state_.current_statement_position);
-    state_.written_position = state_.current_statement_position;
-    state_.written_statement_position = state_.current_statement_position;
-    written = true;
+                                current_statement_position_);
+    written_position_ = current_statement_position_;
+    written_statement_position_ = current_statement_position_;
   }
 
   // Write the position if it is different from what was written last time and
   // also different from the statement position that was just written.
-  if (state_.current_position != state_.written_position) {
+  if (current_position_ != written_position_) {
     EnsureSpace ensure_space(assembler_);
-    assembler_->RecordRelocInfo(RelocInfo::POSITION, state_.current_position);
-    state_.written_position = state_.current_position;
-    written = true;
+    assembler_->RecordRelocInfo(RelocInfo::POSITION, current_position_);
+    written_position_ = current_position_;
   }
-
-  // Return whether something was written.
-  return written;
 }
 
 
@@ -2023,12 +1989,12 @@
 
 // Platform specific but identical code for all the platforms.
 
-
-void Assembler::RecordDeoptReason(const int reason, int raw_position) {
-  if (FLAG_trace_deopt || isolate()->cpu_profiler()->is_profiling()) {
+void Assembler::RecordDeoptReason(const int reason, int raw_position, int id) {
+  if (FLAG_trace_deopt || isolate()->is_profiling()) {
     EnsureSpace ensure_space(this);
     RecordRelocInfo(RelocInfo::POSITION, raw_position);
     RecordRelocInfo(RelocInfo::DEOPT_REASON, reason);
+    RecordRelocInfo(RelocInfo::DEOPT_ID, id);
   }
 }
 
diff --git a/src/assembler.h b/src/assembler.h
index 192d16b..0c2b7e8 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -39,6 +39,7 @@
 #include "src/builtins.h"
 #include "src/isolate.h"
 #include "src/log.h"
+#include "src/register-configuration.h"
 #include "src/runtime/runtime.h"
 
 namespace v8 {
@@ -384,9 +385,11 @@
     CODE_TARGET_WITH_ID,
     DEBUGGER_STATEMENT,  // Code target for the debugger statement.
     EMBEDDED_OBJECT,
-    CELL,
     // To relocate pointers into the wasm memory embedded in wasm code
     WASM_MEMORY_REFERENCE,
+    WASM_GLOBAL_REFERENCE,
+    WASM_MEMORY_SIZE_REFERENCE,
+    CELL,
 
     // Everything after runtime_entry (inclusive) is not GC'ed.
     RUNTIME_ENTRY,
@@ -415,6 +418,7 @@
     VENEER_POOL,
 
     DEOPT_REASON,  // Deoptimization reason index.
+    DEOPT_ID,      // Deoptimization inlining id.
 
     // This is not an actual reloc mode, but used to encode a long pc jump that
     // cannot be encoded as part of another record.
@@ -430,7 +434,7 @@
     FIRST_REAL_RELOC_MODE = CODE_TARGET,
     LAST_REAL_RELOC_MODE = VENEER_POOL,
     LAST_CODE_ENUM = DEBUGGER_STATEMENT,
-    LAST_GCED_ENUM = WASM_MEMORY_REFERENCE,
+    LAST_GCED_ENUM = WASM_MEMORY_SIZE_REFERENCE,
     FIRST_SHAREABLE_RELOC_MODE = CELL,
   };
 
@@ -446,8 +450,7 @@
   }
 
   static inline bool IsRealRelocMode(Mode mode) {
-    return mode >= FIRST_REAL_RELOC_MODE &&
-        mode <= LAST_REAL_RELOC_MODE;
+    return mode >= FIRST_REAL_RELOC_MODE && mode <= LAST_REAL_RELOC_MODE;
   }
   static inline bool IsCodeTarget(Mode mode) {
     return mode <= LAST_CODE_ENUM;
@@ -475,6 +478,9 @@
   static inline bool IsDeoptReason(Mode mode) {
     return mode == DEOPT_REASON;
   }
+  static inline bool IsDeoptId(Mode mode) {
+    return mode == DEOPT_ID;
+  }
   static inline bool IsPosition(Mode mode) {
     return mode == POSITION || mode == STATEMENT_POSITION;
   }
@@ -521,6 +527,12 @@
   static inline bool IsWasmMemoryReference(Mode mode) {
     return mode == WASM_MEMORY_REFERENCE;
   }
+  static inline bool IsWasmMemorySizeReference(Mode mode) {
+    return mode == WASM_MEMORY_SIZE_REFERENCE;
+  }
+  static inline bool IsWasmGlobalReference(Mode mode) {
+    return mode == WASM_GLOBAL_REFERENCE;
+  }
   static inline int ModeMask(Mode mode) { return 1 << mode; }
 
   // Accessors
@@ -547,44 +559,44 @@
   // constant pool, otherwise the pointer is embedded in the instruction stream.
   bool IsInConstantPool();
 
+  Address wasm_memory_reference();
+  Address wasm_global_reference();
+  uint32_t wasm_memory_size_reference();
+  void update_wasm_memory_reference(
+      Address old_base, Address new_base, uint32_t old_size, uint32_t new_size,
+      ICacheFlushMode icache_flush_mode = SKIP_ICACHE_FLUSH);
+  void update_wasm_global_reference(
+      Address old_base, Address new_base,
+      ICacheFlushMode icache_flush_mode = SKIP_ICACHE_FLUSH);
+
   // this relocation applies to;
   // can only be called if IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
   INLINE(Address target_address());
-  INLINE(void set_target_address(Address target,
-                                 WriteBarrierMode write_barrier_mode =
-                                     UPDATE_WRITE_BARRIER,
-                                 ICacheFlushMode icache_flush_mode =
-                                     FLUSH_ICACHE_IF_NEEDED));
+  INLINE(void set_target_address(
+      Address target,
+      WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER,
+      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
   INLINE(Object* target_object());
   INLINE(Handle<Object> target_object_handle(Assembler* origin));
-  INLINE(void set_target_object(Object* target,
-                                WriteBarrierMode write_barrier_mode =
-                                    UPDATE_WRITE_BARRIER,
-                                ICacheFlushMode icache_flush_mode =
-                                    FLUSH_ICACHE_IF_NEEDED));
+  INLINE(void set_target_object(
+      Object* target,
+      WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER,
+      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
   INLINE(Address target_runtime_entry(Assembler* origin));
-  INLINE(void set_target_runtime_entry(Address target,
-                                       WriteBarrierMode write_barrier_mode =
-                                           UPDATE_WRITE_BARRIER,
-                                       ICacheFlushMode icache_flush_mode =
-                                           FLUSH_ICACHE_IF_NEEDED));
+  INLINE(void set_target_runtime_entry(
+      Address target,
+      WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER,
+      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
   INLINE(Cell* target_cell());
   INLINE(Handle<Cell> target_cell_handle());
-  INLINE(void set_target_cell(Cell* cell,
-                              WriteBarrierMode write_barrier_mode =
-                                  UPDATE_WRITE_BARRIER,
-                              ICacheFlushMode icache_flush_mode =
-                                  FLUSH_ICACHE_IF_NEEDED));
+  INLINE(void set_target_cell(
+      Cell* cell, WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER,
+      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
   INLINE(Handle<Object> code_age_stub_handle(Assembler* origin));
   INLINE(Code* code_age_stub());
-  INLINE(void set_code_age_stub(Code* stub,
-                                ICacheFlushMode icache_flush_mode =
-                                    FLUSH_ICACHE_IF_NEEDED));
+  INLINE(void set_code_age_stub(
+      Code* stub, ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
 
-  INLINE(Address wasm_memory_reference());
-  INLINE(void update_wasm_memory_reference(
-      Address old_base, Address new_base, size_t old_size, size_t new_size,
-      ICacheFlushMode icache_flush_mode = SKIP_ICACHE_FLUSH));
   // Returns the address of the constant pool entry where the target address
   // is held.  This should only be called if IsInConstantPool returns true.
   INLINE(Address constant_pool_entry_address());
@@ -631,6 +643,8 @@
   INLINE(void WipeOut());
 
   template<typename StaticVisitor> inline void Visit(Heap* heap);
+
+  template <typename ObjectVisitor>
   inline void Visit(Isolate* isolate, ObjectVisitor* v);
 
   // Check whether this debug break slot has been patched with a call to the
@@ -662,6 +676,11 @@
   static const int kApplyMask;  // Modes affected by apply.  Depends on arch.
 
  private:
+  void unchecked_update_wasm_memory_reference(Address address,
+                                              ICacheFlushMode flush_mode);
+  void unchecked_update_wasm_memory_size(uint32_t size,
+                                         ICacheFlushMode flush_mode);
+
   Isolate* isolate_;
   // On ARM, note that pc_ is the address of the constant pool entry
   // to be relocated and not the address of the instruction
@@ -877,8 +896,6 @@
   };
 
   static void SetUp();
-  static void InitializeMathExpData();
-  static void TearDownMathExpData();
 
   typedef void* ExternalReferenceRedirector(Isolate* isolate, void* original,
                                             Type type);
@@ -909,6 +926,7 @@
   // ExternalReferenceTable in serialize.cc manually.
 
   static ExternalReference interpreter_dispatch_table_address(Isolate* isolate);
+  static ExternalReference interpreter_dispatch_counters(Isolate* isolate);
 
   static ExternalReference incremental_marking_record_write_function(
       Isolate* isolate);
@@ -948,16 +966,13 @@
   static ExternalReference wasm_int64_mod(Isolate* isolate);
   static ExternalReference wasm_uint64_div(Isolate* isolate);
   static ExternalReference wasm_uint64_mod(Isolate* isolate);
+  static ExternalReference wasm_word32_ctz(Isolate* isolate);
+  static ExternalReference wasm_word64_ctz(Isolate* isolate);
+  static ExternalReference wasm_word32_popcnt(Isolate* isolate);
+  static ExternalReference wasm_word64_popcnt(Isolate* isolate);
 
   static ExternalReference f64_acos_wrapper_function(Isolate* isolate);
   static ExternalReference f64_asin_wrapper_function(Isolate* isolate);
-  static ExternalReference f64_atan_wrapper_function(Isolate* isolate);
-  static ExternalReference f64_cos_wrapper_function(Isolate* isolate);
-  static ExternalReference f64_sin_wrapper_function(Isolate* isolate);
-  static ExternalReference f64_tan_wrapper_function(Isolate* isolate);
-  static ExternalReference f64_exp_wrapper_function(Isolate* isolate);
-  static ExternalReference f64_log_wrapper_function(Isolate* isolate);
-  static ExternalReference f64_atan2_wrapper_function(Isolate* isolate);
   static ExternalReference f64_pow_wrapper_function(Isolate* isolate);
   static ExternalReference f64_mod_wrapper_function(Isolate* isolate);
 
@@ -1019,10 +1034,20 @@
   static ExternalReference address_of_the_hole_nan();
   static ExternalReference address_of_uint32_bias();
 
-  static ExternalReference math_log_double_function(Isolate* isolate);
-
-  static ExternalReference math_exp_constants(int constant_index);
-  static ExternalReference math_exp_log_table();
+  // IEEE 754 functions.
+  static ExternalReference ieee754_atan_function(Isolate* isolate);
+  static ExternalReference ieee754_atan2_function(Isolate* isolate);
+  static ExternalReference ieee754_atanh_function(Isolate* isolate);
+  static ExternalReference ieee754_cbrt_function(Isolate* isolate);
+  static ExternalReference ieee754_cos_function(Isolate* isolate);
+  static ExternalReference ieee754_exp_function(Isolate* isolate);
+  static ExternalReference ieee754_expm1_function(Isolate* isolate);
+  static ExternalReference ieee754_log_function(Isolate* isolate);
+  static ExternalReference ieee754_log1p_function(Isolate* isolate);
+  static ExternalReference ieee754_log10_function(Isolate* isolate);
+  static ExternalReference ieee754_log2_function(Isolate* isolate);
+  static ExternalReference ieee754_sin_function(Isolate* isolate);
+  static ExternalReference ieee754_tan_function(Isolate* isolate);
 
   static ExternalReference page_flags(Page* page);
 
@@ -1047,8 +1072,11 @@
 
   Address address() const { return reinterpret_cast<Address>(address_); }
 
-  // Used to check if single stepping is enabled in generated code.
-  static ExternalReference debug_step_in_enabled_address(Isolate* isolate);
+  // Used to read out the last step action of the debugger.
+  static ExternalReference debug_last_step_action_address(Isolate* isolate);
+
+  // Used to check for suspended generator, used for stepping across await call.
+  static ExternalReference debug_suspended_generator_address(Isolate* isolate);
 
 #ifndef V8_INTERPRETED_REGEXP
   // C functions called from RegExp generated code.
@@ -1111,23 +1139,14 @@
 // -----------------------------------------------------------------------------
 // Position recording support
 
-struct PositionState {
-  PositionState() : current_position(RelocInfo::kNoPosition),
-                    written_position(RelocInfo::kNoPosition),
-                    current_statement_position(RelocInfo::kNoPosition),
-                    written_statement_position(RelocInfo::kNoPosition) {}
-
-  int current_position;
-  int written_position;
-
-  int current_statement_position;
-  int written_statement_position;
-};
-
 class AssemblerPositionsRecorder : public PositionsRecorder {
  public:
   explicit AssemblerPositionsRecorder(Assembler* assembler)
-      : assembler_(assembler) {}
+      : assembler_(assembler),
+        current_position_(RelocInfo::kNoPosition),
+        written_position_(RelocInfo::kNoPosition),
+        current_statement_position_(RelocInfo::kNoPosition),
+        written_statement_position_(RelocInfo::kNoPosition) {}
 
   // Set current position to pos.
   void RecordPosition(int pos);
@@ -1135,18 +1154,17 @@
   // Set current statement position to pos.
   void RecordStatementPosition(int pos);
 
-  // Write recorded positions to relocation information.
-  bool WriteRecordedPositions();
-
-  int current_position() const { return state_.current_position; }
-
-  int current_statement_position() const {
-    return state_.current_statement_position;
-  }
-
  private:
+  // Write recorded positions to relocation information.
+  void WriteRecordedPositions();
+
   Assembler* assembler_;
-  PositionState state_;
+
+  int current_position_;
+  int written_position_;
+
+  int current_statement_position_;
+  int written_statement_position_;
 
   DISALLOW_COPY_AND_ASSIGN(AssemblerPositionsRecorder);
 };
diff --git a/src/ast/ast-expression-rewriter.cc b/src/ast/ast-expression-rewriter.cc
index edee91d..b39f7f1 100644
--- a/src/ast/ast-expression-rewriter.cc
+++ b/src/ast/ast-expression-rewriter.cc
@@ -169,12 +169,10 @@
 
 
 void AstExpressionRewriter::VisitForOfStatement(ForOfStatement* node) {
-  AST_REWRITE_PROPERTY(Expression, node, each);
   AST_REWRITE_PROPERTY(Expression, node, assign_iterator);
   AST_REWRITE_PROPERTY(Expression, node, next_result);
   AST_REWRITE_PROPERTY(Expression, node, result_done);
   AST_REWRITE_PROPERTY(Expression, node, assign_each);
-  AST_REWRITE_PROPERTY(Expression, node, subject);
   AST_REWRITE_PROPERTY(Statement, node, body);
 }
 
diff --git a/src/ast/ast-expression-visitor.cc b/src/ast/ast-expression-visitor.cc
index dbf4ea4..7536d90 100644
--- a/src/ast/ast-expression-visitor.cc
+++ b/src/ast/ast-expression-visitor.cc
@@ -13,397 +13,153 @@
 namespace v8 {
 namespace internal {
 
-
-#define RECURSE(call)               \
-  do {                              \
-    DCHECK(!HasStackOverflow());    \
-    call;                           \
-    if (HasStackOverflow()) return; \
-  } while (false)
-
-
-#define RECURSE_EXPRESSION(call)    \
-  do {                              \
-    DCHECK(!HasStackOverflow());    \
-    ++depth_;                       \
-    call;                           \
-    --depth_;                       \
-    if (HasStackOverflow()) return; \
-  } while (false)
-
-
 AstExpressionVisitor::AstExpressionVisitor(Isolate* isolate, Expression* root)
-    : root_(root), depth_(0) {
-  InitializeAstVisitor(isolate);
-}
-
+    : AstTraversalVisitor(isolate), root_(root) {}
 
 AstExpressionVisitor::AstExpressionVisitor(uintptr_t stack_limit,
                                            Expression* root)
-    : root_(root), depth_(0) {
-  InitializeAstVisitor(stack_limit);
-}
+    : AstTraversalVisitor(stack_limit), root_(root) {}
 
-
-void AstExpressionVisitor::Run() { RECURSE(Visit(root_)); }
-
-
-void AstExpressionVisitor::VisitVariableDeclaration(VariableDeclaration* decl) {
-}
-
-
-void AstExpressionVisitor::VisitFunctionDeclaration(FunctionDeclaration* decl) {
-  RECURSE(Visit(decl->fun()));
-}
-
-
-void AstExpressionVisitor::VisitImportDeclaration(ImportDeclaration* decl) {}
-
-
-void AstExpressionVisitor::VisitExportDeclaration(ExportDeclaration* decl) {}
-
-
-void AstExpressionVisitor::VisitStatements(ZoneList<Statement*>* stmts) {
-  for (int i = 0; i < stmts->length(); ++i) {
-    Statement* stmt = stmts->at(i);
-    RECURSE(Visit(stmt));
-    if (stmt->IsJump()) break;
-  }
-}
-
-
-void AstExpressionVisitor::VisitBlock(Block* stmt) {
-  RECURSE(VisitStatements(stmt->statements()));
-}
-
-
-void AstExpressionVisitor::VisitExpressionStatement(ExpressionStatement* stmt) {
-  RECURSE(Visit(stmt->expression()));
-}
-
-
-void AstExpressionVisitor::VisitEmptyStatement(EmptyStatement* stmt) {}
-
-
-void AstExpressionVisitor::VisitSloppyBlockFunctionStatement(
-    SloppyBlockFunctionStatement* stmt) {
-  RECURSE(Visit(stmt->statement()));
-}
-
-
-void AstExpressionVisitor::VisitIfStatement(IfStatement* stmt) {
-  RECURSE(Visit(stmt->condition()));
-  RECURSE(Visit(stmt->then_statement()));
-  RECURSE(Visit(stmt->else_statement()));
-}
-
-
-void AstExpressionVisitor::VisitContinueStatement(ContinueStatement* stmt) {}
-
-
-void AstExpressionVisitor::VisitBreakStatement(BreakStatement* stmt) {}
-
-
-void AstExpressionVisitor::VisitReturnStatement(ReturnStatement* stmt) {
-  RECURSE(Visit(stmt->expression()));
-}
-
-
-void AstExpressionVisitor::VisitWithStatement(WithStatement* stmt) {
-  RECURSE(stmt->expression());
-  RECURSE(stmt->statement());
-}
-
-
-void AstExpressionVisitor::VisitSwitchStatement(SwitchStatement* stmt) {
-  RECURSE(Visit(stmt->tag()));
-
-  ZoneList<CaseClause*>* clauses = stmt->cases();
-
-  for (int i = 0; i < clauses->length(); ++i) {
-    CaseClause* clause = clauses->at(i);
-    if (!clause->is_default()) {
-      Expression* label = clause->label();
-      RECURSE(Visit(label));
-    }
-    ZoneList<Statement*>* stmts = clause->statements();
-    RECURSE(VisitStatements(stmts));
-  }
-}
-
-
-void AstExpressionVisitor::VisitCaseClause(CaseClause* clause) {
-  UNREACHABLE();
-}
-
-
-void AstExpressionVisitor::VisitDoWhileStatement(DoWhileStatement* stmt) {
-  RECURSE(Visit(stmt->body()));
-  RECURSE(Visit(stmt->cond()));
-}
-
-
-void AstExpressionVisitor::VisitWhileStatement(WhileStatement* stmt) {
-  RECURSE(Visit(stmt->cond()));
-  RECURSE(Visit(stmt->body()));
-}
-
-
-void AstExpressionVisitor::VisitForStatement(ForStatement* stmt) {
-  if (stmt->init() != NULL) {
-    RECURSE(Visit(stmt->init()));
-  }
-  if (stmt->cond() != NULL) {
-    RECURSE(Visit(stmt->cond()));
-  }
-  if (stmt->next() != NULL) {
-    RECURSE(Visit(stmt->next()));
-  }
-  RECURSE(Visit(stmt->body()));
-}
-
-
-void AstExpressionVisitor::VisitForInStatement(ForInStatement* stmt) {
-  RECURSE(Visit(stmt->enumerable()));
-  RECURSE(Visit(stmt->body()));
-}
-
-
-void AstExpressionVisitor::VisitForOfStatement(ForOfStatement* stmt) {
-  RECURSE(Visit(stmt->iterable()));
-  RECURSE(Visit(stmt->each()));
-  RECURSE(Visit(stmt->assign_iterator()));
-  RECURSE(Visit(stmt->next_result()));
-  RECURSE(Visit(stmt->result_done()));
-  RECURSE(Visit(stmt->assign_each()));
-  RECURSE(Visit(stmt->body()));
-}
-
-
-void AstExpressionVisitor::VisitTryCatchStatement(TryCatchStatement* stmt) {
-  RECURSE(Visit(stmt->try_block()));
-  RECURSE(Visit(stmt->catch_block()));
-}
-
-
-void AstExpressionVisitor::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
-  RECURSE(Visit(stmt->try_block()));
-  RECURSE(Visit(stmt->finally_block()));
-}
-
-
-void AstExpressionVisitor::VisitDebuggerStatement(DebuggerStatement* stmt) {}
-
+void AstExpressionVisitor::Run() { Visit(root_); }
 
 void AstExpressionVisitor::VisitFunctionLiteral(FunctionLiteral* expr) {
-  Scope* scope = expr->scope();
   VisitExpression(expr);
-  RECURSE_EXPRESSION(VisitDeclarations(scope->declarations()));
-  RECURSE_EXPRESSION(VisitStatements(expr->body()));
+  AstTraversalVisitor::VisitFunctionLiteral(expr);
 }
 
-
 void AstExpressionVisitor::VisitNativeFunctionLiteral(
-    NativeFunctionLiteral* expr) {}
-
+    NativeFunctionLiteral* expr) {
+  AstTraversalVisitor::VisitNativeFunctionLiteral(expr);
+}
 
 void AstExpressionVisitor::VisitDoExpression(DoExpression* expr) {
   VisitExpression(expr);
-  RECURSE(VisitBlock(expr->block()));
-  RECURSE(VisitVariableProxy(expr->result()));
+  AstTraversalVisitor::VisitDoExpression(expr);
 }
 
-
 void AstExpressionVisitor::VisitConditional(Conditional* expr) {
   VisitExpression(expr);
-  RECURSE_EXPRESSION(Visit(expr->condition()));
-  RECURSE_EXPRESSION(Visit(expr->then_expression()));
-  RECURSE_EXPRESSION(Visit(expr->else_expression()));
+  AstTraversalVisitor::VisitConditional(expr);
 }
 
-
 void AstExpressionVisitor::VisitVariableProxy(VariableProxy* expr) {
   VisitExpression(expr);
+  AstTraversalVisitor::VisitVariableProxy(expr);
 }
 
-
 void AstExpressionVisitor::VisitLiteral(Literal* expr) {
   VisitExpression(expr);
+  AstTraversalVisitor::VisitLiteral(expr);
 }
 
-
 void AstExpressionVisitor::VisitRegExpLiteral(RegExpLiteral* expr) {
   VisitExpression(expr);
+  AstTraversalVisitor::VisitRegExpLiteral(expr);
 }
 
-
 void AstExpressionVisitor::VisitObjectLiteral(ObjectLiteral* expr) {
   VisitExpression(expr);
-  ZoneList<ObjectLiteralProperty*>* props = expr->properties();
-  for (int i = 0; i < props->length(); ++i) {
-    ObjectLiteralProperty* prop = props->at(i);
-    if (!prop->key()->IsLiteral()) {
-      RECURSE_EXPRESSION(Visit(prop->key()));
-    }
-    RECURSE_EXPRESSION(Visit(prop->value()));
-  }
+  AstTraversalVisitor::VisitObjectLiteral(expr);
 }
 
-
 void AstExpressionVisitor::VisitArrayLiteral(ArrayLiteral* expr) {
   VisitExpression(expr);
-  ZoneList<Expression*>* values = expr->values();
-  for (int i = 0; i < values->length(); ++i) {
-    Expression* value = values->at(i);
-    RECURSE_EXPRESSION(Visit(value));
-  }
+  AstTraversalVisitor::VisitArrayLiteral(expr);
 }
 
-
 void AstExpressionVisitor::VisitAssignment(Assignment* expr) {
   VisitExpression(expr);
-  RECURSE_EXPRESSION(Visit(expr->target()));
-  RECURSE_EXPRESSION(Visit(expr->value()));
+  AstTraversalVisitor::VisitAssignment(expr);
 }
 
-
 void AstExpressionVisitor::VisitYield(Yield* expr) {
   VisitExpression(expr);
-  RECURSE_EXPRESSION(Visit(expr->generator_object()));
-  RECURSE_EXPRESSION(Visit(expr->expression()));
+  AstTraversalVisitor::VisitYield(expr);
 }
 
-
 void AstExpressionVisitor::VisitThrow(Throw* expr) {
   VisitExpression(expr);
-  RECURSE_EXPRESSION(Visit(expr->exception()));
+  AstTraversalVisitor::VisitThrow(expr);
 }
 
-
 void AstExpressionVisitor::VisitProperty(Property* expr) {
   VisitExpression(expr);
-  RECURSE_EXPRESSION(Visit(expr->obj()));
-  RECURSE_EXPRESSION(Visit(expr->key()));
+  AstTraversalVisitor::VisitProperty(expr);
 }
 
-
 void AstExpressionVisitor::VisitCall(Call* expr) {
   VisitExpression(expr);
-  RECURSE_EXPRESSION(Visit(expr->expression()));
-  ZoneList<Expression*>* args = expr->arguments();
-  for (int i = 0; i < args->length(); ++i) {
-    Expression* arg = args->at(i);
-    RECURSE_EXPRESSION(Visit(arg));
-  }
+  AstTraversalVisitor::VisitCall(expr);
 }
 
-
 void AstExpressionVisitor::VisitCallNew(CallNew* expr) {
   VisitExpression(expr);
-  RECURSE_EXPRESSION(Visit(expr->expression()));
-  ZoneList<Expression*>* args = expr->arguments();
-  for (int i = 0; i < args->length(); ++i) {
-    Expression* arg = args->at(i);
-    RECURSE_EXPRESSION(Visit(arg));
-  }
+  AstTraversalVisitor::VisitCallNew(expr);
 }
 
-
 void AstExpressionVisitor::VisitCallRuntime(CallRuntime* expr) {
   VisitExpression(expr);
-  ZoneList<Expression*>* args = expr->arguments();
-  for (int i = 0; i < args->length(); ++i) {
-    Expression* arg = args->at(i);
-    RECURSE_EXPRESSION(Visit(arg));
-  }
+  AstTraversalVisitor::VisitCallRuntime(expr);
 }
 
-
 void AstExpressionVisitor::VisitUnaryOperation(UnaryOperation* expr) {
   VisitExpression(expr);
-  RECURSE_EXPRESSION(Visit(expr->expression()));
+  AstTraversalVisitor::VisitUnaryOperation(expr);
 }
 
-
 void AstExpressionVisitor::VisitCountOperation(CountOperation* expr) {
   VisitExpression(expr);
-  RECURSE_EXPRESSION(Visit(expr->expression()));
+  AstTraversalVisitor::VisitCountOperation(expr);
 }
 
-
 void AstExpressionVisitor::VisitBinaryOperation(BinaryOperation* expr) {
   VisitExpression(expr);
-  RECURSE_EXPRESSION(Visit(expr->left()));
-  RECURSE_EXPRESSION(Visit(expr->right()));
+  AstTraversalVisitor::VisitBinaryOperation(expr);
 }
 
-
 void AstExpressionVisitor::VisitCompareOperation(CompareOperation* expr) {
   VisitExpression(expr);
-  RECURSE_EXPRESSION(Visit(expr->left()));
-  RECURSE_EXPRESSION(Visit(expr->right()));
+  AstTraversalVisitor::VisitCompareOperation(expr);
 }
 
-
 void AstExpressionVisitor::VisitThisFunction(ThisFunction* expr) {
   VisitExpression(expr);
+  AstTraversalVisitor::VisitThisFunction(expr);
 }
 
-
-void AstExpressionVisitor::VisitDeclarations(ZoneList<Declaration*>* decls) {
-  for (int i = 0; i < decls->length(); ++i) {
-    Declaration* decl = decls->at(i);
-    RECURSE(Visit(decl));
-  }
-}
-
-
 void AstExpressionVisitor::VisitClassLiteral(ClassLiteral* expr) {
   VisitExpression(expr);
-  if (expr->extends() != nullptr) {
-    RECURSE_EXPRESSION(Visit(expr->extends()));
-  }
-  RECURSE_EXPRESSION(Visit(expr->constructor()));
-  ZoneList<ObjectLiteralProperty*>* props = expr->properties();
-  for (int i = 0; i < props->length(); ++i) {
-    ObjectLiteralProperty* prop = props->at(i);
-    if (!prop->key()->IsLiteral()) {
-      RECURSE_EXPRESSION(Visit(prop->key()));
-    }
-    RECURSE_EXPRESSION(Visit(prop->value()));
-  }
+  AstTraversalVisitor::VisitClassLiteral(expr);
 }
 
-
 void AstExpressionVisitor::VisitSpread(Spread* expr) {
   VisitExpression(expr);
-  RECURSE_EXPRESSION(Visit(expr->expression()));
+  AstTraversalVisitor::VisitSpread(expr);
 }
 
-
-void AstExpressionVisitor::VisitEmptyParentheses(EmptyParentheses* expr) {}
-
-
 void AstExpressionVisitor::VisitSuperPropertyReference(
     SuperPropertyReference* expr) {
   VisitExpression(expr);
-  RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var()));
-  RECURSE_EXPRESSION(Visit(expr->home_object()));
+  AstTraversalVisitor::VisitSuperPropertyReference(expr);
 }
 
-
 void AstExpressionVisitor::VisitSuperCallReference(SuperCallReference* expr) {
   VisitExpression(expr);
-  RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var()));
-  RECURSE_EXPRESSION(VisitVariableProxy(expr->new_target_var()));
-  RECURSE_EXPRESSION(VisitVariableProxy(expr->this_function_var()));
+  AstTraversalVisitor::VisitSuperCallReference(expr);
 }
 
+void AstExpressionVisitor::VisitCaseClause(CaseClause* expr) {
+  AstTraversalVisitor::VisitCaseClause(expr);
+}
+
+void AstExpressionVisitor::VisitEmptyParentheses(EmptyParentheses* expr) {
+  AstTraversalVisitor::VisitEmptyParentheses(expr);
+}
 
 void AstExpressionVisitor::VisitRewritableExpression(
     RewritableExpression* expr) {
   VisitExpression(expr);
-  RECURSE(Visit(expr->expression()));
+  AstTraversalVisitor::VisitRewritableExpression(expr);
 }
 
 
diff --git a/src/ast/ast-expression-visitor.h b/src/ast/ast-expression-visitor.h
index 545a45c..3f7b9f7 100644
--- a/src/ast/ast-expression-visitor.h
+++ b/src/ast/ast-expression-visitor.h
@@ -17,7 +17,7 @@
 // A Visitor over a CompilationInfo's AST that invokes
 // VisitExpression on each expression node.
 
-class AstExpressionVisitor : public AstVisitor {
+class AstExpressionVisitor : public AstTraversalVisitor {
  public:
   AstExpressionVisitor(Isolate* isolate, Expression* root);
   AstExpressionVisitor(uintptr_t stack_limit, Expression* root);
@@ -25,20 +25,13 @@
 
  protected:
   virtual void VisitExpression(Expression* expression) = 0;
-  int depth() { return depth_; }
 
  private:
-  void VisitDeclarations(ZoneList<Declaration*>* d) override;
-  void VisitStatements(ZoneList<Statement*>* s) override;
-
-  DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
-
 #define DECLARE_VISIT(type) void Visit##type(type* node) override;
-  AST_NODE_LIST(DECLARE_VISIT)
+  EXPRESSION_NODE_LIST(DECLARE_VISIT)
 #undef DECLARE_VISIT
 
   Expression* root_;
-  int depth_;
 
   DISALLOW_COPY_AND_ASSIGN(AstExpressionVisitor);
 };
diff --git a/src/ast/ast-numbering.cc b/src/ast/ast-numbering.cc
index f54333f..dd6ce4a 100644
--- a/src/ast/ast-numbering.cc
+++ b/src/ast/ast-numbering.cc
@@ -17,6 +17,7 @@
         isolate_(isolate),
         zone_(zone),
         next_id_(BailoutId::FirstUsable().ToInt()),
+        yield_count_(0),
         properties_(zone),
         slot_cache_(zone),
         dont_optimize_reason_(kNoReason) {
@@ -31,8 +32,6 @@
   AST_NODE_LIST(DEFINE_VISIT)
 #undef DEFINE_VISIT
 
-  bool Finish(FunctionLiteral* node);
-
   void VisitVariableProxyReference(VariableProxy* node);
   void VisitPropertyReference(Property* node);
   void VisitReference(Expression* expr);
@@ -76,6 +75,7 @@
   Isolate* isolate_;
   Zone* zone_;
   int next_id_;
+  int yield_count_;
   AstProperties properties_;
   // The slot cache allows us to reuse certain feedback vector slots.
   FeedbackVectorSlotCache slot_cache_;
@@ -217,8 +217,9 @@
 
 
 void AstNumberingVisitor::VisitYield(Yield* node) {
+  node->set_yield_id(yield_count_);
+  yield_count_++;
   IncrementNodeCount();
-  DisableOptimization(kYield);
   ReserveFeedbackSlots(node);
   node->set_base_id(ReserveIdRange(Yield::num_ids()));
   Visit(node->generator_object());
@@ -284,8 +285,10 @@
   IncrementNodeCount();
   DisableSelfOptimization();
   node->set_base_id(ReserveIdRange(DoWhileStatement::num_ids()));
+  node->set_first_yield_id(yield_count_);
   Visit(node->body());
   Visit(node->cond());
+  node->set_yield_count(yield_count_ - node->first_yield_id());
 }
 
 
@@ -293,14 +296,16 @@
   IncrementNodeCount();
   DisableSelfOptimization();
   node->set_base_id(ReserveIdRange(WhileStatement::num_ids()));
+  node->set_first_yield_id(yield_count_);
   Visit(node->cond());
   Visit(node->body());
+  node->set_yield_count(yield_count_ - node->first_yield_id());
 }
 
 
 void AstNumberingVisitor::VisitTryCatchStatement(TryCatchStatement* node) {
   IncrementNodeCount();
-  DisableOptimization(kTryCatchStatement);
+  DisableCrankshaft(kTryCatchStatement);
   Visit(node->try_block());
   Visit(node->catch_block());
 }
@@ -308,7 +313,7 @@
 
 void AstNumberingVisitor::VisitTryFinallyStatement(TryFinallyStatement* node) {
   IncrementNodeCount();
-  DisableOptimization(kTryFinallyStatement);
+  DisableCrankshaft(kTryFinallyStatement);
   Visit(node->try_block());
   Visit(node->finally_block());
 }
@@ -377,9 +382,11 @@
   IncrementNodeCount();
   DisableSelfOptimization();
   node->set_base_id(ReserveIdRange(ForInStatement::num_ids()));
+  Visit(node->enumerable());  // Not part of loop.
+  node->set_first_yield_id(yield_count_);
   Visit(node->each());
-  Visit(node->enumerable());
   Visit(node->body());
+  node->set_yield_count(yield_count_ - node->first_yield_id());
   ReserveFeedbackSlots(node);
 }
 
@@ -388,11 +395,13 @@
   IncrementNodeCount();
   DisableCrankshaft(kForOfStatement);
   node->set_base_id(ReserveIdRange(ForOfStatement::num_ids()));
-  Visit(node->assign_iterator());
+  Visit(node->assign_iterator());  // Not part of loop.
+  node->set_first_yield_id(yield_count_);
   Visit(node->next_result());
   Visit(node->result_done());
   Visit(node->assign_each());
   Visit(node->body());
+  node->set_yield_count(yield_count_ - node->first_yield_id());
   ReserveFeedbackSlots(node);
 }
 
@@ -440,10 +449,12 @@
   IncrementNodeCount();
   DisableSelfOptimization();
   node->set_base_id(ReserveIdRange(ForStatement::num_ids()));
-  if (node->init() != NULL) Visit(node->init());
+  if (node->init() != NULL) Visit(node->init());  // Not part of loop.
+  node->set_first_yield_id(yield_count_);
   if (node->cond() != NULL) Visit(node->cond());
   if (node->next() != NULL) Visit(node->next());
   Visit(node->body());
+  node->set_yield_count(yield_count_ - node->first_yield_id());
 }
 
 
@@ -554,13 +565,6 @@
 }
 
 
-bool AstNumberingVisitor::Finish(FunctionLiteral* node) {
-  node->set_ast_properties(&properties_);
-  node->set_dont_optimize_reason(dont_optimize_reason());
-  return !HasStackOverflow();
-}
-
-
 bool AstNumberingVisitor::Renumber(FunctionLiteral* node) {
   Scope* scope = node->scope();
   if (scope->new_target_var()) DisableCrankshaft(kSuperReference);
@@ -574,10 +578,20 @@
     DisableCrankshaft(kRestParameter);
   }
 
+  if (IsGeneratorFunction(node->kind()) || IsAsyncFunction(node->kind())) {
+    // TODO(neis): We may want to allow Turbofan optimization here if
+    // --turbo-from-bytecode is set and we know that Ignition is used.
+    // Unfortunately we can't express that here.
+    DisableOptimization(kGenerator);
+  }
+
   VisitDeclarations(scope->declarations());
   VisitStatements(node->body());
 
-  return Finish(node);
+  node->set_ast_properties(&properties_);
+  node->set_dont_optimize_reason(dont_optimize_reason());
+  node->set_yield_count(yield_count_);
+  return !HasStackOverflow();
 }
 
 
diff --git a/src/ast/ast-numbering.h b/src/ast/ast-numbering.h
index 0ac1ef2..a1d3137 100644
--- a/src/ast/ast-numbering.h
+++ b/src/ast/ast-numbering.h
@@ -14,11 +14,27 @@
 class Zone;
 
 namespace AstNumbering {
-// Assign type feedback IDs and bailout IDs to an AST node tree.
-//
+// Assign type feedback IDs, bailout IDs, and generator yield IDs to an AST node
+// tree.
 bool Renumber(Isolate* isolate, Zone* zone, FunctionLiteral* function);
 }
 
+// Some details on yield IDs
+// -------------------------
+//
+// In order to assist Ignition in generating bytecode for a generator function,
+// we assign a unique number (the yield ID) to each Yield node in its AST. We
+// also annotate loops with the number of yields they contain (loop.yield_count)
+// and the smallest ID of those (loop.first_yield_id), and we annotate the
+// function itself with the number of yields it contains (function.yield_count).
+//
+// The way in which we choose the IDs is simply by enumerating the Yield nodes.
+// Ignition relies on the following properties:
+// - For each loop l and each yield y of l:
+//     l.first_yield_id  <=  y.yield_id  <  l.first_yield_id + l.yield_count
+// - For the generator function f itself and each yield y of f:
+//                    0  <=  y.yield_id  <  f.yield_count
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/ast/ast-type-bounds.h b/src/ast/ast-type-bounds.h
new file mode 100644
index 0000000..ec26fdf
--- /dev/null
+++ b/src/ast/ast-type-bounds.h
@@ -0,0 +1,40 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// A container to associate type bounds with AST Expression nodes.
+
+#ifndef V8_AST_AST_TYPE_BOUNDS_H_
+#define V8_AST_AST_TYPE_BOUNDS_H_
+
+#include "src/types.h"
+#include "src/zone-containers.h"
+
+namespace v8 {
+namespace internal {
+
+class Expression;
+
+class AstTypeBounds {
+ public:
+  explicit AstTypeBounds(Zone* zone) : bounds_map_(zone) {}
+  ~AstTypeBounds() {}
+
+  Bounds get(Expression* expression) const {
+    ZoneMap<Expression*, Bounds>::const_iterator i =
+        bounds_map_.find(expression);
+    return (i != bounds_map_.end()) ? i->second : Bounds::Unbounded();
+  }
+
+  void set(Expression* expression, Bounds bounds) {
+    bounds_map_[expression] = bounds;
+  }
+
+ private:
+  ZoneMap<Expression*, Bounds> bounds_map_;
+};
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_AST_AST_TYPE_BOUNDS_H_
diff --git a/src/ast/ast-value-factory.cc b/src/ast/ast-value-factory.cc
index 189d4cc..92322a0 100644
--- a/src/ast/ast-value-factory.cc
+++ b/src/ast/ast-value-factory.cc
@@ -360,7 +360,7 @@
   // against the AstRawStrings which are in the string_table_. We should not
   // return this AstRawString.
   AstRawString key(is_one_byte, literal_bytes, hash);
-  HashMap::Entry* entry = string_table_.LookupOrInsert(&key, hash);
+  base::HashMap::Entry* entry = string_table_.LookupOrInsert(&key, hash);
   if (entry->value == NULL) {
     // Copy literal contents for later comparison.
     int length = literal_bytes.length();
diff --git a/src/ast/ast-value-factory.h b/src/ast/ast-value-factory.h
index 8b3f0ed..b0019a5 100644
--- a/src/ast/ast-value-factory.h
+++ b/src/ast/ast-value-factory.h
@@ -29,7 +29,7 @@
 #define V8_AST_AST_VALUE_FACTORY_H_
 
 #include "src/api.h"
-#include "src/hashmap.h"
+#include "src/base/hashmap.h"
 #include "src/utils.h"
 
 // AstString, AstValue and AstValueFactory are for storing strings and values
@@ -242,6 +242,8 @@
 #define STRING_CONSTANTS(F)                     \
   F(anonymous_function, "(anonymous function)") \
   F(arguments, "arguments")                     \
+  F(async, "async")                             \
+  F(await, "await")                             \
   F(constructor, "constructor")                 \
   F(default, "default")                         \
   F(done, "done")                               \
@@ -263,7 +265,6 @@
   F(next, "next")                               \
   F(proto, "__proto__")                         \
   F(prototype, "prototype")                     \
-  F(rest_parameter, ".rest_parameter")          \
   F(return, "return")                           \
   F(set_space, "set ")                          \
   F(this, "this")                               \
@@ -350,7 +351,7 @@
   static bool AstRawStringCompare(void* a, void* b);
 
   // All strings are copied here, one after another (no NULLs inbetween).
-  HashMap string_table_;
+  base::HashMap string_table_;
   // For keeping track of all AstValues and AstRawStrings we've created (so that
   // they can be internalized later).
   List<AstValue*> values_;
diff --git a/src/ast/ast.cc b/src/ast/ast.cc
index e8b6269..4ad4585 100644
--- a/src/ast/ast.cc
+++ b/src/ast/ast.cc
@@ -8,14 +8,14 @@
 
 #include "src/ast/prettyprinter.h"
 #include "src/ast/scopes.h"
+#include "src/base/hashmap.h"
 #include "src/builtins.h"
 #include "src/code-stubs.h"
 #include "src/contexts.h"
 #include "src/conversions.h"
-#include "src/hashmap.h"
 #include "src/parsing/parser.h"
-#include "src/property.h"
 #include "src/property-details.h"
+#include "src/property.h"
 #include "src/string-stream.h"
 #include "src/type-info.h"
 
@@ -59,12 +59,19 @@
 
 
 bool Expression::IsNullLiteral() const {
-  return IsLiteral() && AsLiteral()->value()->IsNull();
+  if (!IsLiteral()) return false;
+  Handle<Object> value = AsLiteral()->value();
+  return !value->IsSmi() &&
+         value->IsNull(HeapObject::cast(*value)->GetIsolate());
 }
 
 bool Expression::IsUndefinedLiteral() const {
-  if (IsLiteral() && AsLiteral()->value()->IsUndefined()) {
-    return true;
+  if (IsLiteral()) {
+    Handle<Object> value = AsLiteral()->value();
+    if (!value->IsSmi() &&
+        value->IsUndefined(HeapObject::cast(*value)->GetIsolate())) {
+      return true;
+    }
   }
 
   const VariableProxy* var_proxy = AsVariableProxy();
@@ -120,17 +127,17 @@
   if (UsesVariableFeedbackSlot()) {
     // VariableProxies that point to the same Variable within a function can
     // make their loads from the same IC slot.
-    if (var()->IsUnallocated()) {
+    if (var()->IsUnallocated() || var()->mode() == DYNAMIC_GLOBAL) {
       ZoneHashMap::Entry* entry = cache->Get(var());
       if (entry != NULL) {
         variable_feedback_slot_ = FeedbackVectorSlot(
             static_cast<int>(reinterpret_cast<intptr_t>(entry->value)));
         return;
       }
-    }
-    variable_feedback_slot_ = spec->AddLoadICSlot();
-    if (var()->IsUnallocated()) {
+      variable_feedback_slot_ = spec->AddLoadGlobalICSlot(var()->name());
       cache->Put(var(), variable_feedback_slot_);
+    } else {
+      variable_feedback_slot_ = spec->AddLoadICSlot();
     }
   }
 }
@@ -387,7 +394,7 @@
     if (property->is_computed_name()) continue;
     if (property->kind() == ObjectLiteral::Property::PROTOTYPE) continue;
     Literal* literal = property->key()->AsLiteral();
-    DCHECK(!literal->value()->IsNull());
+    DCHECK(!literal->IsNullLiteral());
 
     // If there is an existing entry do not emit a store unless the previous
     // entry was also an accessor.
@@ -457,11 +464,11 @@
     // (value->IsNumber()).
     // TODO(verwaest): Remove once we can store them inline.
     if (FLAG_track_double_fields &&
-        (value->IsNumber() || value->IsUninitialized())) {
+        (value->IsNumber() || value->IsUninitialized(isolate))) {
       may_store_doubles_ = true;
     }
 
-    is_simple = is_simple && !value->IsUninitialized();
+    is_simple = is_simple && !value->IsUninitialized(isolate);
 
     // Keep track of the number of elements in the object literal and
     // the largest element index.  If the largest element index is
@@ -524,12 +531,12 @@
     // New handle scope here, needs to be after BuildContants().
     HandleScope scope(isolate);
     Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate);
-    if (boilerplate_value->IsTheHole()) {
+    if (boilerplate_value->IsTheHole(isolate)) {
       is_holey = true;
       continue;
     }
 
-    if (boilerplate_value->IsUninitialized()) {
+    if (boilerplate_value->IsUninitialized(isolate)) {
       boilerplate_value = handle(Smi::FromInt(0), isolate);
       is_simple = false;
     }
@@ -813,6 +820,309 @@
   }
 }
 
+// ----------------------------------------------------------------------------
+// Implementation of AstTraversalVisitor
+
+#define RECURSE(call)               \
+  do {                              \
+    DCHECK(!HasStackOverflow());    \
+    call;                           \
+    if (HasStackOverflow()) return; \
+  } while (false)
+
+#define RECURSE_EXPRESSION(call)    \
+  do {                              \
+    DCHECK(!HasStackOverflow());    \
+    ++depth_;                       \
+    call;                           \
+    --depth_;                       \
+    if (HasStackOverflow()) return; \
+  } while (false)
+
+AstTraversalVisitor::AstTraversalVisitor(Isolate* isolate) : depth_(0) {
+  InitializeAstVisitor(isolate);
+}
+
+AstTraversalVisitor::AstTraversalVisitor(uintptr_t stack_limit) : depth_(0) {
+  InitializeAstVisitor(stack_limit);
+}
+
+void AstTraversalVisitor::VisitDeclarations(ZoneList<Declaration*>* decls) {
+  for (int i = 0; i < decls->length(); ++i) {
+    Declaration* decl = decls->at(i);
+    RECURSE(Visit(decl));
+  }
+}
+
+void AstTraversalVisitor::VisitStatements(ZoneList<Statement*>* stmts) {
+  for (int i = 0; i < stmts->length(); ++i) {
+    Statement* stmt = stmts->at(i);
+    RECURSE(Visit(stmt));
+    if (stmt->IsJump()) break;
+  }
+}
+
+void AstTraversalVisitor::VisitVariableDeclaration(VariableDeclaration* decl) {}
+
+void AstTraversalVisitor::VisitFunctionDeclaration(FunctionDeclaration* decl) {
+  RECURSE(Visit(decl->fun()));
+}
+
+void AstTraversalVisitor::VisitImportDeclaration(ImportDeclaration* decl) {}
+
+void AstTraversalVisitor::VisitExportDeclaration(ExportDeclaration* decl) {}
+
+void AstTraversalVisitor::VisitBlock(Block* stmt) {
+  RECURSE(VisitStatements(stmt->statements()));
+}
+
+void AstTraversalVisitor::VisitExpressionStatement(ExpressionStatement* stmt) {
+  RECURSE(Visit(stmt->expression()));
+}
+
+void AstTraversalVisitor::VisitEmptyStatement(EmptyStatement* stmt) {}
+
+void AstTraversalVisitor::VisitSloppyBlockFunctionStatement(
+    SloppyBlockFunctionStatement* stmt) {
+  RECURSE(Visit(stmt->statement()));
+}
+
+void AstTraversalVisitor::VisitIfStatement(IfStatement* stmt) {
+  RECURSE(Visit(stmt->condition()));
+  RECURSE(Visit(stmt->then_statement()));
+  RECURSE(Visit(stmt->else_statement()));
+}
+
+void AstTraversalVisitor::VisitContinueStatement(ContinueStatement* stmt) {}
+
+void AstTraversalVisitor::VisitBreakStatement(BreakStatement* stmt) {}
+
+void AstTraversalVisitor::VisitReturnStatement(ReturnStatement* stmt) {
+  RECURSE(Visit(stmt->expression()));
+}
+
+void AstTraversalVisitor::VisitWithStatement(WithStatement* stmt) {
+  RECURSE(stmt->expression());
+  RECURSE(stmt->statement());
+}
+
+void AstTraversalVisitor::VisitSwitchStatement(SwitchStatement* stmt) {
+  RECURSE(Visit(stmt->tag()));
+
+  ZoneList<CaseClause*>* clauses = stmt->cases();
+
+  for (int i = 0; i < clauses->length(); ++i) {
+    CaseClause* clause = clauses->at(i);
+    if (!clause->is_default()) {
+      Expression* label = clause->label();
+      RECURSE(Visit(label));
+    }
+    ZoneList<Statement*>* stmts = clause->statements();
+    RECURSE(VisitStatements(stmts));
+  }
+}
+
+void AstTraversalVisitor::VisitCaseClause(CaseClause* clause) { UNREACHABLE(); }
+
+void AstTraversalVisitor::VisitDoWhileStatement(DoWhileStatement* stmt) {
+  RECURSE(Visit(stmt->body()));
+  RECURSE(Visit(stmt->cond()));
+}
+
+void AstTraversalVisitor::VisitWhileStatement(WhileStatement* stmt) {
+  RECURSE(Visit(stmt->cond()));
+  RECURSE(Visit(stmt->body()));
+}
+
+void AstTraversalVisitor::VisitForStatement(ForStatement* stmt) {
+  if (stmt->init() != NULL) {
+    RECURSE(Visit(stmt->init()));
+  }
+  if (stmt->cond() != NULL) {
+    RECURSE(Visit(stmt->cond()));
+  }
+  if (stmt->next() != NULL) {
+    RECURSE(Visit(stmt->next()));
+  }
+  RECURSE(Visit(stmt->body()));
+}
+
+void AstTraversalVisitor::VisitForInStatement(ForInStatement* stmt) {
+  RECURSE(Visit(stmt->enumerable()));
+  RECURSE(Visit(stmt->body()));
+}
+
+void AstTraversalVisitor::VisitForOfStatement(ForOfStatement* stmt) {
+  RECURSE(Visit(stmt->assign_iterator()));
+  RECURSE(Visit(stmt->next_result()));
+  RECURSE(Visit(stmt->result_done()));
+  RECURSE(Visit(stmt->assign_each()));
+  RECURSE(Visit(stmt->body()));
+}
+
+void AstTraversalVisitor::VisitTryCatchStatement(TryCatchStatement* stmt) {
+  RECURSE(Visit(stmt->try_block()));
+  RECURSE(Visit(stmt->catch_block()));
+}
+
+void AstTraversalVisitor::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
+  RECURSE(Visit(stmt->try_block()));
+  RECURSE(Visit(stmt->finally_block()));
+}
+
+void AstTraversalVisitor::VisitDebuggerStatement(DebuggerStatement* stmt) {}
+
+void AstTraversalVisitor::VisitFunctionLiteral(FunctionLiteral* expr) {
+  Scope* scope = expr->scope();
+  RECURSE_EXPRESSION(VisitDeclarations(scope->declarations()));
+  RECURSE_EXPRESSION(VisitStatements(expr->body()));
+}
+
+void AstTraversalVisitor::VisitNativeFunctionLiteral(
+    NativeFunctionLiteral* expr) {}
+
+void AstTraversalVisitor::VisitDoExpression(DoExpression* expr) {
+  RECURSE(VisitBlock(expr->block()));
+  RECURSE(VisitVariableProxy(expr->result()));
+}
+
+void AstTraversalVisitor::VisitConditional(Conditional* expr) {
+  RECURSE_EXPRESSION(Visit(expr->condition()));
+  RECURSE_EXPRESSION(Visit(expr->then_expression()));
+  RECURSE_EXPRESSION(Visit(expr->else_expression()));
+}
+
+void AstTraversalVisitor::VisitVariableProxy(VariableProxy* expr) {}
+
+void AstTraversalVisitor::VisitLiteral(Literal* expr) {}
+
+void AstTraversalVisitor::VisitRegExpLiteral(RegExpLiteral* expr) {}
+
+void AstTraversalVisitor::VisitObjectLiteral(ObjectLiteral* expr) {
+  ZoneList<ObjectLiteralProperty*>* props = expr->properties();
+  for (int i = 0; i < props->length(); ++i) {
+    ObjectLiteralProperty* prop = props->at(i);
+    if (!prop->key()->IsLiteral()) {
+      RECURSE_EXPRESSION(Visit(prop->key()));
+    }
+    RECURSE_EXPRESSION(Visit(prop->value()));
+  }
+}
+
+void AstTraversalVisitor::VisitArrayLiteral(ArrayLiteral* expr) {
+  ZoneList<Expression*>* values = expr->values();
+  for (int i = 0; i < values->length(); ++i) {
+    Expression* value = values->at(i);
+    RECURSE_EXPRESSION(Visit(value));
+  }
+}
+
+void AstTraversalVisitor::VisitAssignment(Assignment* expr) {
+  RECURSE_EXPRESSION(Visit(expr->target()));
+  RECURSE_EXPRESSION(Visit(expr->value()));
+}
+
+void AstTraversalVisitor::VisitYield(Yield* expr) {
+  RECURSE_EXPRESSION(Visit(expr->generator_object()));
+  RECURSE_EXPRESSION(Visit(expr->expression()));
+}
+
+void AstTraversalVisitor::VisitThrow(Throw* expr) {
+  RECURSE_EXPRESSION(Visit(expr->exception()));
+}
+
+void AstTraversalVisitor::VisitProperty(Property* expr) {
+  RECURSE_EXPRESSION(Visit(expr->obj()));
+  RECURSE_EXPRESSION(Visit(expr->key()));
+}
+
+void AstTraversalVisitor::VisitCall(Call* expr) {
+  RECURSE_EXPRESSION(Visit(expr->expression()));
+  ZoneList<Expression*>* args = expr->arguments();
+  for (int i = 0; i < args->length(); ++i) {
+    Expression* arg = args->at(i);
+    RECURSE_EXPRESSION(Visit(arg));
+  }
+}
+
+void AstTraversalVisitor::VisitCallNew(CallNew* expr) {
+  RECURSE_EXPRESSION(Visit(expr->expression()));
+  ZoneList<Expression*>* args = expr->arguments();
+  for (int i = 0; i < args->length(); ++i) {
+    Expression* arg = args->at(i);
+    RECURSE_EXPRESSION(Visit(arg));
+  }
+}
+
+void AstTraversalVisitor::VisitCallRuntime(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  for (int i = 0; i < args->length(); ++i) {
+    Expression* arg = args->at(i);
+    RECURSE_EXPRESSION(Visit(arg));
+  }
+}
+
+void AstTraversalVisitor::VisitUnaryOperation(UnaryOperation* expr) {
+  RECURSE_EXPRESSION(Visit(expr->expression()));
+}
+
+void AstTraversalVisitor::VisitCountOperation(CountOperation* expr) {
+  RECURSE_EXPRESSION(Visit(expr->expression()));
+}
+
+void AstTraversalVisitor::VisitBinaryOperation(BinaryOperation* expr) {
+  RECURSE_EXPRESSION(Visit(expr->left()));
+  RECURSE_EXPRESSION(Visit(expr->right()));
+}
+
+void AstTraversalVisitor::VisitCompareOperation(CompareOperation* expr) {
+  RECURSE_EXPRESSION(Visit(expr->left()));
+  RECURSE_EXPRESSION(Visit(expr->right()));
+}
+
+void AstTraversalVisitor::VisitThisFunction(ThisFunction* expr) {}
+
+void AstTraversalVisitor::VisitClassLiteral(ClassLiteral* expr) {
+  if (expr->extends() != nullptr) {
+    RECURSE_EXPRESSION(Visit(expr->extends()));
+  }
+  RECURSE_EXPRESSION(Visit(expr->constructor()));
+  ZoneList<ObjectLiteralProperty*>* props = expr->properties();
+  for (int i = 0; i < props->length(); ++i) {
+    ObjectLiteralProperty* prop = props->at(i);
+    if (!prop->key()->IsLiteral()) {
+      RECURSE_EXPRESSION(Visit(prop->key()));
+    }
+    RECURSE_EXPRESSION(Visit(prop->value()));
+  }
+}
+
+void AstTraversalVisitor::VisitSpread(Spread* expr) {
+  RECURSE_EXPRESSION(Visit(expr->expression()));
+}
+
+void AstTraversalVisitor::VisitEmptyParentheses(EmptyParentheses* expr) {}
+
+void AstTraversalVisitor::VisitSuperPropertyReference(
+    SuperPropertyReference* expr) {
+  RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var()));
+  RECURSE_EXPRESSION(Visit(expr->home_object()));
+}
+
+void AstTraversalVisitor::VisitSuperCallReference(SuperCallReference* expr) {
+  RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var()));
+  RECURSE_EXPRESSION(VisitVariableProxy(expr->new_target_var()));
+  RECURSE_EXPRESSION(VisitVariableProxy(expr->this_function_var()));
+}
+
+void AstTraversalVisitor::VisitRewritableExpression(
+    RewritableExpression* expr) {
+  RECURSE(Visit(expr->expression()));
+}
+
+#undef RECURSE_EXPRESSION
+#undef RECURSE
+
 CaseClause::CaseClause(Zone* zone, Expression* label,
                        ZoneList<Statement*>* statements, int pos)
     : Expression(zone, pos),
diff --git a/src/ast/ast.h b/src/ast/ast.h
index 52bac8e..5ae90f8 100644
--- a/src/ast/ast.h
+++ b/src/ast/ast.h
@@ -130,7 +130,8 @@
  public:
   explicit FeedbackVectorSlotCache(Zone* zone)
       : zone_(zone),
-        hash_map_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity,
+        hash_map_(base::HashMap::PointersMatch,
+                  ZoneHashMap::kDefaultHashMapCapacity,
                   ZoneAllocationPolicy(zone)) {}
 
   void Put(Variable* variable, FeedbackVectorSlot slot) {
@@ -337,10 +338,6 @@
   // True iff the expression is a valid target for an assignment.
   bool IsValidReferenceExpressionOrThis() const;
 
-  // Expression type bounds
-  Bounds bounds() const { return bounds_; }
-  void set_bounds(Bounds bounds) { bounds_ = bounds; }
-
   // Type feedback information for assignments and properties.
   virtual bool IsMonomorphic() {
     UNREACHABLE();
@@ -374,7 +371,6 @@
   Expression(Zone* zone, int pos)
       : AstNode(pos),
         base_id_(BailoutId::None().ToInt()),
-        bounds_(Bounds::Unbounded()),
         bit_field_(0) {}
   static int parent_num_ids() { return 0; }
   void set_to_boolean_types(uint16_t types) {
@@ -390,7 +386,6 @@
   int local_id(int n) const { return base_id() + parent_num_ids() + n; }
 
   int base_id_;
-  Bounds bounds_;
   class ToBooleanTypesField : public BitField16<uint16_t, 0, 9> {};
   uint16_t bit_field_;
   // Ends with 16-bit field; deriving classes in turn begin with
@@ -598,7 +593,7 @@
   ImportDeclaration(Zone* zone, VariableProxy* proxy,
                     const AstRawString* import_name,
                     const AstRawString* module_specifier, Scope* scope, int pos)
-      : Declaration(zone, proxy, IMPORT, scope, pos),
+      : Declaration(zone, proxy, CONST, scope, pos),
         import_name_(import_name),
         module_specifier_(module_specifier) {}
 
@@ -647,6 +642,13 @@
   Statement* body() const { return body_; }
   void set_body(Statement* s) { body_ = s; }
 
+  int yield_count() const { return yield_count_; }
+  int first_yield_id() const { return first_yield_id_; }
+  void set_yield_count(int yield_count) { yield_count_ = yield_count; }
+  void set_first_yield_id(int first_yield_id) {
+    first_yield_id_ = first_yield_id;
+  }
+
   static int num_ids() { return parent_num_ids() + 1; }
   BailoutId OsrEntryId() const { return BailoutId(local_id(0)); }
   virtual BailoutId ContinueId() const = 0;
@@ -658,7 +660,9 @@
  protected:
   IterationStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
       : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
-        body_(NULL) {}
+        body_(NULL),
+        yield_count_(0),
+        first_yield_id_(0) {}
   static int parent_num_ids() { return BreakableStatement::num_ids(); }
   void Initialize(Statement* body) { body_ = body; }
 
@@ -667,6 +671,8 @@
 
   Statement* body_;
   Label continue_target_;
+  int yield_count_;
+  int first_yield_id_;
 };
 
 
@@ -779,17 +785,7 @@
     ITERATE      // for (each of subject) body;
   };
 
-  void Initialize(Expression* each, Expression* subject, Statement* body) {
-    IterationStatement::Initialize(body);
-    each_ = each;
-    subject_ = subject;
-  }
-
-  Expression* each() const { return each_; }
-  Expression* subject() const { return subject_; }
-
-  void set_each(Expression* e) { each_ = e; }
-  void set_subject(Expression* e) { subject_ = e; }
+  using IterationStatement::Initialize;
 
   static const char* VisitModeString(VisitMode mode) {
     return mode == ITERATE ? "for-of" : "for-in";
@@ -797,11 +793,7 @@
 
  protected:
   ForEachStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
-      : IterationStatement(zone, labels, pos), each_(NULL), subject_(NULL) {}
-
- private:
-  Expression* each_;
-  Expression* subject_;
+      : IterationStatement(zone, labels, pos) {}
 };
 
 
@@ -809,10 +801,22 @@
  public:
   DECLARE_NODE_TYPE(ForInStatement)
 
+  void Initialize(Expression* each, Expression* subject, Statement* body) {
+    ForEachStatement::Initialize(body);
+    each_ = each;
+    subject_ = subject;
+  }
+
   Expression* enumerable() const {
     return subject();
   }
 
+  Expression* each() const { return each_; }
+  Expression* subject() const { return subject_; }
+
+  void set_each(Expression* e) { each_ = e; }
+  void set_subject(Expression* e) { subject_ = e; }
+
   // Type feedback information.
   void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec,
                                  FeedbackVectorSlotCache* cache) override;
@@ -838,12 +842,17 @@
 
  protected:
   ForInStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
-      : ForEachStatement(zone, labels, pos), for_in_type_(SLOW_FOR_IN) {}
+      : ForEachStatement(zone, labels, pos),
+        each_(nullptr),
+        subject_(nullptr),
+        for_in_type_(SLOW_FOR_IN) {}
   static int parent_num_ids() { return ForEachStatement::num_ids(); }
 
  private:
   int local_id(int n) const { return base_id() + parent_num_ids() + n; }
 
+  Expression* each_;
+  Expression* subject_;
   ForInType for_in_type_;
   FeedbackVectorSlot each_slot_;
   FeedbackVectorSlot for_in_feedback_slot_;
@@ -854,15 +863,10 @@
  public:
   DECLARE_NODE_TYPE(ForOfStatement)
 
-  void Initialize(Expression* each,
-                  Expression* subject,
-                  Statement* body,
-                  Variable* iterator,
-                  Expression* assign_iterator,
-                  Expression* next_result,
-                  Expression* result_done,
-                  Expression* assign_each) {
-    ForEachStatement::Initialize(each, subject, body);
+  void Initialize(Statement* body, Variable* iterator,
+                  Expression* assign_iterator, Expression* next_result,
+                  Expression* result_done, Expression* assign_each) {
+    ForEachStatement::Initialize(body);
     iterator_ = iterator;
     assign_iterator_ = assign_iterator;
     next_result_ = next_result;
@@ -870,10 +874,6 @@
     assign_each_ = assign_each;
   }
 
-  Expression* iterable() const {
-    return subject();
-  }
-
   Variable* iterator() const {
     return iterator_;
   }
@@ -1502,9 +1502,10 @@
   };
 
   struct Accessors: public ZoneObject {
-    Accessors() : getter(NULL), setter(NULL) {}
+    Accessors() : getter(NULL), setter(NULL), bailout_id(BailoutId::None()) {}
     ObjectLiteralProperty* getter;
     ObjectLiteralProperty* setter;
+    BailoutId bailout_id;
   };
 
   BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); }
@@ -1552,13 +1553,14 @@
 
 
 // A map from property names to getter/setter pairs allocated in the zone.
-class AccessorTable : public TemplateHashMap<Literal, ObjectLiteral::Accessors,
-                                             ZoneAllocationPolicy> {
+class AccessorTable
+    : public base::TemplateHashMap<Literal, ObjectLiteral::Accessors,
+                                   ZoneAllocationPolicy> {
  public:
   explicit AccessorTable(Zone* zone)
-      : TemplateHashMap<Literal, ObjectLiteral::Accessors,
-                        ZoneAllocationPolicy>(Literal::Match,
-                                              ZoneAllocationPolicy(zone)),
+      : base::TemplateHashMap<Literal, ObjectLiteral::Accessors,
+                              ZoneAllocationPolicy>(Literal::Match,
+                                                    ZoneAllocationPolicy(zone)),
         zone_(zone) {}
 
   Iterator lookup(Literal* literal) {
@@ -2005,6 +2007,9 @@
   void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec,
                                  FeedbackVectorSlotCache* cache) override {
     callnew_feedback_slot_ = spec->AddGeneralSlot();
+    // Construct calls have two slots, one right after the other.
+    // The second slot stores the call count for monomorphic calls.
+    spec->AddGeneralSlot();
   }
 
   FeedbackVectorSlot CallNewFeedbackSlot() {
@@ -2526,20 +2531,24 @@
 
   Expression* generator_object() const { return generator_object_; }
   Expression* expression() const { return expression_; }
+  int yield_id() const { return yield_id_; }
 
   void set_generator_object(Expression* e) { generator_object_ = e; }
   void set_expression(Expression* e) { expression_ = e; }
+  void set_yield_id(int yield_id) { yield_id_ = yield_id; }
 
  protected:
   Yield(Zone* zone, Expression* generator_object, Expression* expression,
         int pos)
       : Expression(zone, pos),
         generator_object_(generator_object),
-        expression_(expression) {}
+        expression_(expression),
+        yield_id_(-1) {}
 
  private:
   Expression* generator_object_;
   Expression* expression_;
+  int yield_id_;
 };
 
 
@@ -2584,12 +2593,12 @@
   int start_position() const;
   int end_position() const;
   int SourceSize() const { return end_position() - start_position(); }
-  bool is_declaration() const { return IsDeclaration::decode(bitfield_); }
+  bool is_declaration() const { return function_type() == kDeclaration; }
   bool is_named_expression() const {
-    return IsNamedExpression::decode(bitfield_);
+    return function_type() == kNamedExpression;
   }
   bool is_anonymous_expression() const {
-    return IsAnonymousExpression::decode(bitfield_);
+    return function_type() == kAnonymousExpression;
   }
   LanguageMode language_mode() const;
 
@@ -2666,6 +2675,9 @@
     bitfield_ = ShouldBeUsedOnceHint::update(bitfield_, true);
   }
 
+  FunctionType function_type() const {
+    return FunctionTypeBits::decode(bitfield_);
+  }
   FunctionKind kind() const { return FunctionKindBits::decode(bitfield_); }
 
   int ast_node_count() { return ast_properties_.node_count(); }
@@ -2686,6 +2698,9 @@
     return is_anonymous_expression();
   }
 
+  int yield_count() { return yield_count_; }
+  void set_yield_count(int yield_count) { yield_count_ = yield_count; }
+
  protected:
   FunctionLiteral(Zone* zone, const AstString* name,
                   AstValueFactory* ast_value_factory, Scope* scope,
@@ -2705,12 +2720,10 @@
         materialized_literal_count_(materialized_literal_count),
         expected_property_count_(expected_property_count),
         parameter_count_(parameter_count),
-        function_token_position_(RelocInfo::kNoPosition) {
+        function_token_position_(RelocInfo::kNoPosition),
+        yield_count_(0) {
     bitfield_ =
-        IsDeclaration::encode(function_type == kDeclaration) |
-        IsNamedExpression::encode(function_type == kNamedExpression) |
-        IsAnonymousExpression::encode(function_type == kAnonymousExpression) |
-        Pretenure::encode(false) |
+        FunctionTypeBits::encode(function_type) | Pretenure::encode(false) |
         HasDuplicateParameters::encode(has_duplicate_parameters ==
                                        kHasDuplicateParameters) |
         IsFunction::encode(is_function) |
@@ -2720,15 +2733,13 @@
   }
 
  private:
-  class IsDeclaration : public BitField16<bool, 0, 1> {};
-  class IsNamedExpression : public BitField16<bool, 1, 1> {};
-  class IsAnonymousExpression : public BitField16<bool, 2, 1> {};
-  class Pretenure : public BitField16<bool, 3, 1> {};
-  class HasDuplicateParameters : public BitField16<bool, 4, 1> {};
-  class IsFunction : public BitField16<bool, 5, 1> {};
-  class ShouldEagerCompile : public BitField16<bool, 6, 1> {};
-  class ShouldBeUsedOnceHint : public BitField16<bool, 7, 1> {};
-  class FunctionKindBits : public BitField16<FunctionKind, 8, 8> {};
+  class FunctionTypeBits : public BitField16<FunctionType, 0, 2> {};
+  class Pretenure : public BitField16<bool, 2, 1> {};
+  class HasDuplicateParameters : public BitField16<bool, 3, 1> {};
+  class IsFunction : public BitField16<bool, 4, 1> {};
+  class ShouldEagerCompile : public BitField16<bool, 5, 1> {};
+  class ShouldBeUsedOnceHint : public BitField16<bool, 6, 1> {};
+  class FunctionKindBits : public BitField16<FunctionKind, 7, 9> {};
 
   // Start with 16-bit field, which should get packed together
   // with Expression's trailing 16-bit field.
@@ -2746,6 +2757,7 @@
   int expected_property_count_;
   int parameter_count_;
   int function_token_position_;
+  int yield_count_;
 };
 
 
@@ -3041,6 +3053,36 @@
 
 
 // ----------------------------------------------------------------------------
+// Traversing visitor
+// - fully traverses the entire AST.
+
+class AstTraversalVisitor : public AstVisitor {
+ public:
+  explicit AstTraversalVisitor(Isolate* isolate);
+  explicit AstTraversalVisitor(uintptr_t stack_limit);
+  virtual ~AstTraversalVisitor() {}
+
+  // Iteration left-to-right.
+  void VisitDeclarations(ZoneList<Declaration*>* declarations) override;
+  void VisitStatements(ZoneList<Statement*>* statements) override;
+
+// Individual nodes
+#define DECLARE_VISIT(type) void Visit##type(type* node) override;
+  AST_NODE_LIST(DECLARE_VISIT)
+#undef DECLARE_VISIT
+
+ protected:
+  int depth() { return depth_; }
+
+ private:
+  DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
+
+  int depth_;
+
+  DISALLOW_COPY_AND_ASSIGN(AstTraversalVisitor);
+};
+
+// ----------------------------------------------------------------------------
 // AstNode factory
 
 class AstNodeFactory final BASE_EMBEDDED {
diff --git a/src/ast/prettyprinter.cc b/src/ast/prettyprinter.cc
index 2a79049..d1673c3 100644
--- a/src/ast/prettyprinter.cc
+++ b/src/ast/prettyprinter.cc
@@ -14,6 +14,7 @@
 namespace internal {
 
 CallPrinter::CallPrinter(Isolate* isolate, bool is_builtin) {
+  isolate_ = isolate;
   output_ = NULL;
   size_ = 0;
   pos_ = 0;
@@ -192,10 +193,11 @@
 
 
 void CallPrinter::VisitForOfStatement(ForOfStatement* node) {
-  Find(node->each());
   Find(node->assign_iterator());
-  Find(node->body());
   Find(node->next_result());
+  Find(node->result_done());
+  Find(node->assign_each());
+  Find(node->body());
 }
 
 
@@ -439,13 +441,13 @@
     if (quote) Print("\"");
     Print("%s", String::cast(object)->ToCString().get());
     if (quote) Print("\"");
-  } else if (object->IsNull()) {
+  } else if (object->IsNull(isolate_)) {
     Print("null");
-  } else if (object->IsTrue()) {
+  } else if (object->IsTrue(isolate_)) {
     Print("true");
-  } else if (object->IsFalse()) {
+  } else if (object->IsFalse(isolate_)) {
     Print("false");
-  } else if (object->IsUndefined()) {
+  } else if (object->IsUndefined(isolate_)) {
     Print("undefined");
   } else if (object->IsNumber()) {
     Print("%g", object->Number());
@@ -478,6 +480,7 @@
 
 
 PrettyPrinter::PrettyPrinter(Isolate* isolate) {
+  isolate_ = isolate;
   output_ = NULL;
   size_ = 0;
   pos_ = 0;
@@ -675,11 +678,37 @@
 
 
 void PrettyPrinter::VisitForOfStatement(ForOfStatement* node) {
+  // TODO(adamk): ForOf is largely desugared as part of parsing,
+  // so it's hard to display useful stuff here. Should likely
+  // either bite the bullet and display less or try harder
+  // to preserve more.
   PrintLabels(node->labels());
-  Print("for (");
-  Visit(node->each());
-  Print(" of ");
-  Visit(node->iterable());
+  // The <each> is embedded inside a do-expression by the time we get here.
+  Print("for (<each> of ");
+  if (node->assign_iterator()->IsAssignment() &&
+      node->assign_iterator()->AsAssignment()->value()->IsCall() &&
+      node->assign_iterator()
+          ->AsAssignment()
+          ->value()
+          ->AsCall()
+          ->expression()
+          ->IsProperty() &&
+      node->assign_iterator()
+          ->AsAssignment()
+          ->value()
+          ->AsCall()
+          ->expression()
+          ->IsProperty()) {
+    Visit(node->assign_iterator()
+              ->AsAssignment()
+              ->value()
+              ->AsCall()
+              ->expression()
+              ->AsProperty()
+              ->obj());
+  } else {
+    Print("<iterable>");
+  }
   Print(") ");
   Visit(node->body());
 }
@@ -1040,13 +1069,13 @@
       Print("%c", string->Get(i));
     }
     if (quote) Print("\"");
-  } else if (object->IsNull()) {
+  } else if (object->IsNull(isolate_)) {
     Print("null");
-  } else if (object->IsTrue()) {
+  } else if (object->IsTrue(isolate_)) {
     Print("true");
-  } else if (object->IsFalse()) {
+  } else if (object->IsFalse(isolate_)) {
     Print("false");
-  } else if (object->IsUndefined()) {
+  } else if (object->IsUndefined(isolate_)) {
     Print("undefined");
   } else if (object->IsNumber()) {
     Print("%g", object->Number());
@@ -1055,7 +1084,8 @@
     if (object->IsJSFunction()) {
       Print("JS-Function");
     } else if (object->IsJSArray()) {
-      Print("JS-array[%u]", JSArray::cast(object)->length());
+      Print("JS-array[%u]",
+            Smi::cast(JSArray::cast(object)->length())->value());
     } else if (object->IsJSObject()) {
       Print("JS-Object");
     } else {
@@ -1064,7 +1094,7 @@
   } else if (object->IsFixedArray()) {
     Print("FixedArray");
   } else {
-    Print("<unknown literal %p>", object);
+    Print("<unknown literal %p>", static_cast<void*>(object));
   }
 }
 
@@ -1145,7 +1175,7 @@
   for (int i = 0; i < indent_; i++) {
     Print(". ");
   }
-  Print(txt);
+  Print("%s", txt);
 }
 
 
@@ -1191,6 +1221,10 @@
 const char* AstPrinter::PrintProgram(FunctionLiteral* program) {
   Init();
   { IndentedScope indent(this, "FUNC", program->position());
+    PrintIndented("KIND");
+    Print(" %d\n", program->kind());
+    PrintIndented("YIELD COUNT");
+    Print(" %d\n", program->yield_count());
     PrintLiteralIndented("NAME", program->name(), true);
     PrintLiteralIndented("INFERRED NAME", program->inferred_name(), true);
     PrintParameters(program->scope());
@@ -1359,6 +1393,8 @@
 
 void AstPrinter::VisitDoWhileStatement(DoWhileStatement* node) {
   IndentedScope indent(this, "DO", node->position());
+  PrintIndented("YIELD COUNT");
+  Print(" %d\n", node->yield_count());
   PrintLabelsIndented(node->labels());
   PrintIndentedVisit("BODY", node->body());
   PrintIndentedVisit("COND", node->cond());
@@ -1367,6 +1403,8 @@
 
 void AstPrinter::VisitWhileStatement(WhileStatement* node) {
   IndentedScope indent(this, "WHILE", node->position());
+  PrintIndented("YIELD COUNT");
+  Print(" %d\n", node->yield_count());
   PrintLabelsIndented(node->labels());
   PrintIndentedVisit("COND", node->cond());
   PrintIndentedVisit("BODY", node->body());
@@ -1375,6 +1413,8 @@
 
 void AstPrinter::VisitForStatement(ForStatement* node) {
   IndentedScope indent(this, "FOR", node->position());
+  PrintIndented("YIELD COUNT");
+  Print(" %d\n", node->yield_count());
   PrintLabelsIndented(node->labels());
   if (node->init()) PrintIndentedVisit("INIT", node->init());
   if (node->cond()) PrintIndentedVisit("COND", node->cond());
@@ -1385,6 +1425,8 @@
 
 void AstPrinter::VisitForInStatement(ForInStatement* node) {
   IndentedScope indent(this, "FOR IN", node->position());
+  PrintIndented("YIELD COUNT");
+  Print(" %d\n", node->yield_count());
   PrintIndentedVisit("FOR", node->each());
   PrintIndentedVisit("IN", node->enumerable());
   PrintIndentedVisit("BODY", node->body());
@@ -1393,13 +1435,13 @@
 
 void AstPrinter::VisitForOfStatement(ForOfStatement* node) {
   IndentedScope indent(this, "FOR OF", node->position());
-  PrintIndentedVisit("FOR", node->each());
-  PrintIndentedVisit("OF", node->iterable());
-  PrintIndentedVisit("BODY", node->body());
+  PrintIndented("YIELD COUNT");
+  Print(" %d\n", node->yield_count());
   PrintIndentedVisit("INIT", node->assign_iterator());
   PrintIndentedVisit("NEXT", node->next_result());
-  PrintIndentedVisit("EACH", node->assign_each());
   PrintIndentedVisit("DONE", node->result_done());
+  PrintIndentedVisit("EACH", node->assign_each());
+  PrintIndentedVisit("BODY", node->body());
 }
 
 
@@ -1522,7 +1564,7 @@
   if (node->flags() & RegExp::kSticky) buf[i++] = 'y';
   buf[i] = '\0';
   PrintIndented("FLAGS ");
-  Print(buf.start());
+  Print("%s", buf.start());
   Print("\n");
 }
 
@@ -1594,7 +1636,9 @@
 
 
 void AstPrinter::VisitYield(Yield* node) {
-  IndentedScope indent(this, "YIELD", node->position());
+  EmbeddedVector<char, 128> buf;
+  SNPrintF(buf, "YIELD id %d", node->yield_id());
+  IndentedScope indent(this, buf.start(), node->position());
   Visit(node->expression());
 }
 
diff --git a/src/ast/prettyprinter.h b/src/ast/prettyprinter.h
index 0186203..bb36c2b 100644
--- a/src/ast/prettyprinter.h
+++ b/src/ast/prettyprinter.h
@@ -7,6 +7,7 @@
 
 #include "src/allocation.h"
 #include "src/ast/ast.h"
+#include "src/base/compiler-specific.h"
 
 namespace v8 {
 namespace internal {
@@ -20,7 +21,7 @@
   // string. The result string is alive as long as the CallPrinter is alive.
   const char* Print(FunctionLiteral* program, int position);
 
-  void Print(const char* format, ...);
+  void PRINTF_FORMAT(2, 3) Print(const char* format, ...);
 
   void Find(AstNode* node, bool print = false);
 
@@ -31,6 +32,7 @@
 
  private:
   void Init();
+  Isolate* isolate_;
   char* output_;  // output string buffer
   int size_;      // output_ size
   int pos_;       // current printing position
@@ -62,7 +64,7 @@
   const char* PrintExpression(FunctionLiteral* program);
   const char* PrintProgram(FunctionLiteral* program);
 
-  void Print(const char* format, ...);
+  void PRINTF_FORMAT(2, 3) Print(const char* format, ...);
 
   // Print a node to stdout.
   static void PrintOut(Isolate* isolate, AstNode* node);
@@ -73,6 +75,7 @@
 #undef DECLARE_VISIT
 
  private:
+  Isolate* isolate_;
   char* output_;  // output string buffer
   int size_;  // output_ size
   int pos_;  // current printing position
diff --git a/src/ast/scopeinfo.cc b/src/ast/scopeinfo.cc
index 4ffc020..10315aa 100644
--- a/src/ast/scopeinfo.cc
+++ b/src/ast/scopeinfo.cc
@@ -438,16 +438,13 @@
   return ContextLocalMaybeAssignedFlag::decode(value);
 }
 
-
-bool ScopeInfo::LocalIsSynthetic(int var) {
-  DCHECK(0 <= var && var < LocalCount());
+bool ScopeInfo::VariableIsSynthetic(String* name) {
   // There's currently no flag stored on the ScopeInfo to indicate that a
   // variable is a compiler-introduced temporary. However, to avoid conflict
   // with user declarations, the current temporaries like .generator_object and
   // .result start with a dot, so we can use that as a flag. It's a hack!
-  Handle<String> name(LocalName(var));
-  return (name->length() > 0 && name->Get(0) == '.') ||
-         name->Equals(*GetIsolate()->factory()->this_string());
+  return name->length() == 0 || name->Get(0) == '.' ||
+         name->Equals(name->GetHeap()->this_string());
 }
 
 
diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc
index 5d4b809..77c5d62 100644
--- a/src/ast/scopes.cc
+++ b/src/ast/scopes.cc
@@ -175,7 +175,10 @@
   asm_module_ = false;
   asm_function_ = outer_scope != NULL && outer_scope->asm_module_;
   // Inherit the language mode from the parent scope.
-  language_mode_ = outer_scope != NULL ? outer_scope->language_mode_ : SLOPPY;
+  language_mode_ =
+      is_module_scope()
+          ? STRICT
+          : (outer_scope != NULL ? outer_scope->language_mode_ : SLOPPY);
   outer_scope_calls_sloppy_eval_ = false;
   inner_scope_calls_eval_ = false;
   scope_nonlinear_ = false;
@@ -193,6 +196,7 @@
   scope_info_ = scope_info;
   start_position_ = RelocInfo::kNoPosition;
   end_position_ = RelocInfo::kNoPosition;
+  is_hidden_ = false;
   if (!scope_info.is_null()) {
     scope_calls_eval_ = scope_info->CallsEval();
     language_mode_ = scope_info->language_mode();
@@ -287,6 +291,7 @@
                                : FLAG_print_scopes) {
     scope->Print();
   }
+  scope->CheckScopePositions();
 #endif
 
   info->set_scope(scope);
@@ -553,17 +558,24 @@
   return var;
 }
 
-
-bool Scope::RemoveTemporary(Variable* var) {
+int Scope::RemoveTemporary(Variable* var) {
+  DCHECK_NOT_NULL(var);
+  // Temporaries are only placed in ClosureScopes.
+  DCHECK_EQ(ClosureScope(), this);
+  DCHECK_EQ(var->scope()->ClosureScope(), var->scope());
+  // If the temporary is not here, return quickly.
+  if (var->scope() != this) return -1;
   // Most likely (always?) any temporary variable we want to remove
   // was just added before, so we search backwards.
   for (int i = temps_.length(); i-- > 0;) {
     if (temps_[i] == var) {
-      temps_.Remove(i);
-      return true;
+      // Don't shrink temps_, as callers of this method expect
+      // the returned indices to be unique per-scope.
+      temps_[i] = nullptr;
+      return i;
     }
   }
-  return false;
+  return -1;
 }
 
 
@@ -630,6 +642,7 @@
   // context as a whole has forced context allocation.
   for (int i = 0; i < temps_.length(); i++) {
     Variable* var = temps_[i];
+    if (var == nullptr) continue;
     if (var->is_used()) {
       if (var->IsContextSlot()) {
         DCHECK(has_forced_context_allocation());
@@ -808,21 +821,6 @@
 }
 
 
-void Scope::ReportMessage(int start_position, int end_position,
-                          MessageTemplate::Template message,
-                          const AstRawString* arg) {
-  // Propagate the error to the topmost scope targeted by this scope analysis
-  // phase.
-  Scope* top = this;
-  while (!top->is_script_scope() && !top->outer_scope()->already_resolved()) {
-    top = top->outer_scope();
-  }
-
-  top->pending_error_handler_.ReportMessageAt(start_position, end_position,
-                                              message, arg, kReferenceError);
-}
-
-
 #ifdef DEBUG
 static const char* Header(ScopeType scope_type, FunctionKind function_kind,
                           bool is_declaration_scope) {
@@ -830,7 +828,10 @@
     case EVAL_SCOPE: return "eval";
     // TODO(adamk): Should we print concise method scopes specially?
     case FUNCTION_SCOPE:
-      return IsArrowFunction(function_kind) ? "arrow" : "function";
+      if (IsGeneratorFunction(function_kind)) return "function*";
+      if (IsAsyncFunction(function_kind)) return "async function";
+      if (IsArrowFunction(function_kind)) return "arrow";
+      return "function";
     case MODULE_SCOPE: return "module";
     case SCRIPT_SCOPE: return "global";
     case CATCH_SCOPE: return "catch";
@@ -953,6 +954,8 @@
   if (is_strict(language_mode())) {
     Indent(n1, "// strict mode scope\n");
   }
+  if (asm_module_) Indent(n1, "// scope is an asm module\n");
+  if (asm_function_) Indent(n1, "// scope is an asm function\n");
   if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
   if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
   if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n");
@@ -979,9 +982,15 @@
   }
 
   if (temps_.length() > 0) {
-    Indent(n1, "// temporary vars:\n");
+    bool printed_header = false;
     for (int i = 0; i < temps_.length(); i++) {
-      PrintVar(n1, temps_[i]);
+      if (temps_[i] != nullptr) {
+        if (!printed_header) {
+          printed_header = true;
+          Indent(n1, "// temporary vars:\n");
+        }
+        PrintVar(n1, temps_[i]);
+      }
     }
   }
 
@@ -1007,6 +1016,16 @@
 
   Indent(n0, "}\n");
 }
+
+void Scope::CheckScopePositions() {
+  // A scope is allowed to have invalid positions if it is hidden and has no
+  // inner scopes
+  if (!is_hidden() && inner_scopes_.length() == 0) {
+    CHECK_NE(RelocInfo::kNoPosition, start_position());
+    CHECK_NE(RelocInfo::kNoPosition, end_position());
+  }
+  for (Scope* scope : inner_scopes_) scope->CheckScopePositions();
+}
 #endif  // DEBUG
 
 
@@ -1083,12 +1102,15 @@
     if (var != NULL && proxy->is_assigned()) var->set_maybe_assigned();
     *binding_kind = DYNAMIC_LOOKUP;
     return NULL;
-  } else if (calls_sloppy_eval() && !is_script_scope() &&
-             name_can_be_shadowed) {
+  } else if (calls_sloppy_eval() && is_declaration_scope() &&
+             !is_script_scope() && name_can_be_shadowed) {
     // A variable binding may have been found in an outer scope, but the current
     // scope makes a sloppy 'eval' call, so the found variable may not be
     // the correct one (the 'eval' may introduce a binding with the same name).
     // In that case, change the lookup result to reflect this situation.
+    // Only scopes that can host var bindings (declaration scopes) need be
+    // considered here (this excludes block and catch scopes), and variable
+    // lookups at script scope are always dynamic.
     if (*binding_kind == BOUND) {
       *binding_kind = BOUND_EVAL_SHADOWED;
     } else if (*binding_kind == UNBOUND) {
@@ -1398,6 +1420,7 @@
 void Scope::AllocateNonParameterLocalsAndDeclaredGlobals(Isolate* isolate) {
   // All variables that have no rewrite yet are non-parameter locals.
   for (int i = 0; i < temps_.length(); i++) {
+    if (temps_[i] == nullptr) continue;
     AllocateNonParameterLocal(isolate, temps_[i]);
   }
 
diff --git a/src/ast/scopes.h b/src/ast/scopes.h
index dae70c0..e420cfe 100644
--- a/src/ast/scopes.h
+++ b/src/ast/scopes.h
@@ -6,7 +6,7 @@
 #define V8_AST_SCOPES_H_
 
 #include "src/ast/ast.h"
-#include "src/hashmap.h"
+#include "src/base/hashmap.h"
 #include "src/pending-compilation-error-handler.h"
 #include "src/zone.h"
 
@@ -209,12 +209,18 @@
 
   // Remove a temporary variable. This is for adjusting the scope of
   // temporaries used when desugaring parameter initializers.
-  bool RemoveTemporary(Variable* var);
+  // Returns the index at which it was found in this scope, or -1 if
+  // it was not found.
+  int RemoveTemporary(Variable* var);
 
   // Adds a temporary variable in this scope's TemporaryScope. This is for
   // adjusting the scope of temporaries used when desugaring parameter
   // initializers.
-  void AddTemporary(Variable* var) { temps_.Add(var, zone()); }
+  void AddTemporary(Variable* var) {
+    // Temporaries are only placed in ClosureScopes.
+    DCHECK_EQ(ClosureScope(), this);
+    temps_.Add(var, zone());
+  }
 
   // Adds the specific declaration node to the list of declarations in
   // this scope. The declarations are processed as part of entering
@@ -243,6 +249,7 @@
 
   // Set the language mode flag (unless disabled by a global flag).
   void SetLanguageMode(LanguageMode language_mode) {
+    DCHECK(!is_module_scope() || is_strict(language_mode));
     language_mode_ = language_mode;
   }
 
@@ -295,6 +302,10 @@
     end_position_ = statement_pos;
   }
 
+  // Scopes created for desugaring are hidden. I.e. not visible to the debugger.
+  bool is_hidden() const { return is_hidden_; }
+  void set_is_hidden() { is_hidden_ = true; }
+
   // In some cases we want to force context allocation for a whole scope.
   void ForceContextAllocation() {
     DCHECK(!already_resolved());
@@ -564,16 +575,14 @@
     return &sloppy_block_function_map_;
   }
 
-  // Error handling.
-  void ReportMessage(int start_position, int end_position,
-                     MessageTemplate::Template message,
-                     const AstRawString* arg);
-
   // ---------------------------------------------------------------------------
   // Debugging.
 
 #ifdef DEBUG
   void Print(int n = 0);  // n = indentation; n < 0 => don't print recursively
+
+  // Check that the scope has positions assigned.
+  void CheckScopePositions();
 #endif
 
   // ---------------------------------------------------------------------------
@@ -597,7 +606,9 @@
   // variables may be implicitly 'declared' by being used (possibly in
   // an inner scope) with no intervening with statements or eval calls.
   VariableMap variables_;
-  // Compiler-allocated (user-invisible) temporaries.
+  // Compiler-allocated (user-invisible) temporaries. Due to the implementation
+  // of RemoveTemporary(), may contain nulls, which must be skipped-over during
+  // allocation and printing.
   ZoneList<Variable*> temps_;
   // Parameter list in source order.
   ZoneList<Variable*> params_;
@@ -645,6 +656,7 @@
   // Source positions.
   int start_position_;
   int end_position_;
+  bool is_hidden_;
 
   // Computed via PropagateScopeInfo.
   bool outer_scope_calls_sloppy_eval_;
diff --git a/src/ast/variables.cc b/src/ast/variables.cc
index 7b9a5d2..9048f79 100644
--- a/src/ast/variables.cc
+++ b/src/ast/variables.cc
@@ -19,7 +19,6 @@
     case CONST_LEGACY: return "CONST_LEGACY";
     case LET: return "LET";
     case CONST: return "CONST";
-    case IMPORT: return "IMPORT";
     case DYNAMIC: return "DYNAMIC";
     case DYNAMIC_GLOBAL: return "DYNAMIC_GLOBAL";
     case DYNAMIC_LOCAL: return "DYNAMIC_LOCAL";
@@ -41,7 +40,6 @@
       index_(-1),
       initializer_position_(RelocInfo::kNoPosition),
       local_if_not_shadowed_(NULL),
-      is_from_eval_(false),
       force_context_allocation_(false),
       is_used_(false),
       initialization_flag_(initialization_flag),
diff --git a/src/ast/variables.h b/src/ast/variables.h
index b8bb07e..7d54bc0 100644
--- a/src/ast/variables.h
+++ b/src/ast/variables.h
@@ -119,21 +119,8 @@
     index_ = index;
   }
 
-  void SetFromEval() { is_from_eval_ = true; }
-
   static int CompareIndex(Variable* const* v, Variable* const* w);
 
-  PropertyAttributes DeclarationPropertyAttributes() const {
-    int property_attributes = NONE;
-    if (IsImmutableVariableMode(mode_)) {
-      property_attributes |= READ_ONLY;
-    }
-    if (is_from_eval_) {
-      property_attributes |= EVAL_DECLARED;
-    }
-    return static_cast<PropertyAttributes>(property_attributes);
-  }
-
  private:
   Scope* scope_;
   const AstRawString* name_;
@@ -149,9 +136,6 @@
   // binding scope (exclusive).
   Variable* local_if_not_shadowed_;
 
-  // True if this variable is introduced by a sloppy eval
-  bool is_from_eval_;
-
   // Usage info.
   bool force_context_allocation_;  // set by variable resolver
   bool is_used_;
diff --git a/src/atomic-utils.h b/src/atomic-utils.h
deleted file mode 100644
index 34e1cb0..0000000
--- a/src/atomic-utils.h
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_ATOMIC_UTILS_H_
-#define V8_ATOMIC_UTILS_H_
-
-#include <limits.h>
-
-#include "src/base/atomicops.h"
-#include "src/base/macros.h"
-
-namespace v8 {
-namespace internal {
-
-template <class T>
-class AtomicNumber {
- public:
-  AtomicNumber() : value_(0) {}
-  explicit AtomicNumber(T initial) : value_(initial) {}
-
-  // Returns the newly set value.
-  V8_INLINE T Increment(T increment) {
-    return static_cast<T>(base::Barrier_AtomicIncrement(
-        &value_, static_cast<base::AtomicWord>(increment)));
-  }
-
-  V8_INLINE T Value() { return static_cast<T>(base::Acquire_Load(&value_)); }
-
-  V8_INLINE void SetValue(T new_value) {
-    base::Release_Store(&value_, static_cast<base::AtomicWord>(new_value));
-  }
-
-  V8_INLINE T operator=(T value) {
-    SetValue(value);
-    return value;
-  }
-
- private:
-  STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
-
-  base::AtomicWord value_;
-};
-
-
-// Flag using T atomically. Also accepts void* as T.
-template <typename T>
-class AtomicValue {
- public:
-  AtomicValue() : value_(0) {}
-
-  explicit AtomicValue(T initial)
-      : value_(cast_helper<T>::to_storage_type(initial)) {}
-
-  V8_INLINE T Value() {
-    return cast_helper<T>::to_return_type(base::Acquire_Load(&value_));
-  }
-
-  V8_INLINE bool TrySetValue(T old_value, T new_value) {
-    return base::Release_CompareAndSwap(
-               &value_, cast_helper<T>::to_storage_type(old_value),
-               cast_helper<T>::to_storage_type(new_value)) ==
-           cast_helper<T>::to_storage_type(old_value);
-  }
-
-  V8_INLINE void SetValue(T new_value) {
-    base::Release_Store(&value_, cast_helper<T>::to_storage_type(new_value));
-  }
-
- private:
-  STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
-
-  template <typename S>
-  struct cast_helper {
-    static base::AtomicWord to_storage_type(S value) {
-      return static_cast<base::AtomicWord>(value);
-    }
-    static S to_return_type(base::AtomicWord value) {
-      return static_cast<S>(value);
-    }
-  };
-
-  template <typename S>
-  struct cast_helper<S*> {
-    static base::AtomicWord to_storage_type(S* value) {
-      return reinterpret_cast<base::AtomicWord>(value);
-    }
-    static S* to_return_type(base::AtomicWord value) {
-      return reinterpret_cast<S*>(value);
-    }
-  };
-
-  base::AtomicWord value_;
-};
-
-
-// See utils.h for EnumSet. Storage is always base::AtomicWord.
-// Requirements on E:
-// - No explicit values.
-// - E::kLastValue defined to be the last actually used value.
-//
-// Example:
-// enum E { kA, kB, kC, kLastValue = kC };
-template <class E>
-class AtomicEnumSet {
- public:
-  explicit AtomicEnumSet(base::AtomicWord bits = 0) : bits_(bits) {}
-
-  bool IsEmpty() const { return ToIntegral() == 0; }
-
-  bool Contains(E element) const { return (ToIntegral() & Mask(element)) != 0; }
-  bool ContainsAnyOf(const AtomicEnumSet& set) const {
-    return (ToIntegral() & set.ToIntegral()) != 0;
-  }
-
-  void RemoveAll() { base::Release_Store(&bits_, 0); }
-
-  bool operator==(const AtomicEnumSet& set) const {
-    return ToIntegral() == set.ToIntegral();
-  }
-
-  bool operator!=(const AtomicEnumSet& set) const {
-    return ToIntegral() != set.ToIntegral();
-  }
-
-  AtomicEnumSet<E> operator|(const AtomicEnumSet& set) const {
-    return AtomicEnumSet<E>(ToIntegral() | set.ToIntegral());
-  }
-
-// The following operations modify the underlying storage.
-
-#define ATOMIC_SET_WRITE(OP, NEW_VAL)                                     \
-  do {                                                                    \
-    base::AtomicWord old;                                                 \
-    do {                                                                  \
-      old = base::Acquire_Load(&bits_);                                   \
-    } while (base::Release_CompareAndSwap(&bits_, old, old OP NEW_VAL) != \
-             old);                                                        \
-  } while (false)
-
-  void Add(E element) { ATOMIC_SET_WRITE(|, Mask(element)); }
-
-  void Add(const AtomicEnumSet& set) { ATOMIC_SET_WRITE(|, set.ToIntegral()); }
-
-  void Remove(E element) { ATOMIC_SET_WRITE(&, ~Mask(element)); }
-
-  void Remove(const AtomicEnumSet& set) {
-    ATOMIC_SET_WRITE(&, ~set.ToIntegral());
-  }
-
-  void Intersect(const AtomicEnumSet& set) {
-    ATOMIC_SET_WRITE(&, set.ToIntegral());
-  }
-
-#undef ATOMIC_SET_OP
-
- private:
-  // Check whether there's enough storage to hold E.
-  STATIC_ASSERT(E::kLastValue < (sizeof(base::AtomicWord) * CHAR_BIT));
-
-  V8_INLINE base::AtomicWord ToIntegral() const {
-    return base::Acquire_Load(&bits_);
-  }
-
-  V8_INLINE base::AtomicWord Mask(E element) const {
-    return static_cast<base::AtomicWord>(1) << element;
-  }
-
-  base::AtomicWord bits_;
-};
-
-}  // namespace internal
-}  // namespace v8
-
-#endif  // #define V8_ATOMIC_UTILS_H_
diff --git a/src/bailout-reason.h b/src/bailout-reason.h
index 92929cf..e47a93c 100644
--- a/src/bailout-reason.h
+++ b/src/bailout-reason.h
@@ -18,7 +18,6 @@
   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,                              \
@@ -62,8 +61,8 @@
   V(kEmitLoadRegisterUnsupportedDoubleImmediate,                               \
     "EmitLoadRegister: Unsupported double immediate")                          \
   V(kEval, "eval")                                                             \
-  V(kExpectedAlignmentMarker, "Expected alignment marker")                     \
   V(kExpectedAllocationSite, "Expected allocation site")                       \
+  V(kExpectedBooleanValue, "Expected boolean value")                           \
   V(kExpectedFunctionObject, "Expected function object in register")           \
   V(kExpectedHeapNumber, "Expected HeapNumber")                                \
   V(kExpectedNativeContext, "Expected native context")                         \
@@ -79,17 +78,15 @@
   V(kForInStatementWithNonLocalEachVariable,                                   \
     "ForInStatement with non-local each variable")                             \
   V(kForOfStatement, "ForOfStatement")                                         \
-  V(kFrameIsExpectedToBeAligned, "Frame is expected to be aligned")            \
   V(kFunctionBeingDebugged, "Function is being debugged")                      \
   V(kFunctionCallsEval, "Function calls eval")                                 \
   V(kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry,                      \
     "The function_data field should be a BytecodeArray on interpreter entry")  \
   V(kGeneratedCodeIsTooLarge, "Generated code is too large")                   \
-  V(kGeneratorFailedToResume, "Generator failed to resume")                    \
-  V(kGeneratorResumeMethod, "Generator resume method is being called")         \
   V(kGenerator, "Generator")                                                   \
   V(kGlobalFunctionsMustHaveInitialMap,                                        \
     "Global functions must have initial map")                                  \
+  V(kGraphBuildingFailed, "Optimized graph construction failed")               \
   V(kHeapNumberMapRegisterClobbered, "HeapNumberMap register clobbered")       \
   V(kHydrogenFilter, "Optimization disabled by filter")                        \
   V(kImportDeclaration, "Import declaration")                                  \
@@ -102,15 +99,22 @@
   V(kInteger32ToSmiFieldWritingToNonSmiLocation,                               \
     "Integer32ToSmiField writing to non-smi location")                         \
   V(kInvalidBytecode, "Invalid bytecode")                                      \
-  V(kInvalidCaptureReferenced, "Invalid capture referenced")                   \
   V(kInvalidElementsKindForInternalArrayOrInternalPackedArray,                 \
     "Invalid ElementsKind for InternalArray or InternalPackedArray")           \
+  V(kInvalidFrameForFastNewRestArgumentsStub,                                  \
+    "Invalid frame for FastNewRestArgumentsStub")                              \
+  V(kInvalidFrameForFastNewSloppyArgumentsStub,                                \
+    "Invalid frame for FastNewSloppyArgumentsStub")                            \
+  V(kInvalidFrameForFastNewStrictArgumentsStub,                                \
+    "Invalid frame for FastNewStrictArgumentsStub")                            \
   V(kInvalidFullCodegenState, "invalid full-codegen state")                    \
   V(kInvalidHandleScopeLevel, "Invalid HandleScope level")                     \
+  V(kInvalidJumpTableIndex, "Invalid jump table index")                        \
   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(kInvalidRegisterFileInGenerator, "invalid register file in generator")     \
   V(kJSGlobalObjectNativeContextShouldBeANativeContext,                        \
     "JSGlobalObject::native_context should be a native context")               \
   V(kJSGlobalProxyContextShouldNotBeNull,                                      \
@@ -118,7 +122,6 @@
   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(kLiveEdit, "LiveEdit")                                                     \
   V(kLookupVariableInCountOperation, "Lookup variable in count operation")     \
   V(kMapBecameDeprecated, "Map became deprecated")                             \
@@ -143,13 +146,15 @@
   V(kOperandIsASmiAndNotABoundFunction,                                        \
     "Operand is a smi and not a bound function")                               \
   V(kOperandIsASmiAndNotAFunction, "Operand is a smi and not a function")      \
+  V(kOperandIsASmiAndNotAGeneratorObject,                                      \
+    "Operand is a smi and not a generator object")                             \
   V(kOperandIsASmiAndNotAName, "Operand is a smi and not a name")              \
   V(kOperandIsASmiAndNotAReceiver, "Operand is a smi and not a receiver")      \
   V(kOperandIsASmiAndNotAString, "Operand is a smi and not a string")          \
   V(kOperandIsASmi, "Operand is a smi")                                        \
-  V(kOperandIsNotADate, "Operand is not a date")                               \
   V(kOperandIsNotABoundFunction, "Operand is not a bound function")            \
   V(kOperandIsNotAFunction, "Operand is not a function")                       \
+  V(kOperandIsNotAGeneratorObject, "Operand is not a generator object")        \
   V(kOperandIsNotAName, "Operand is not a name")                               \
   V(kOperandIsNotANumber, "Operand is not a number")                           \
   V(kOperandIsNotAReceiver, "Operand is not a receiver")                       \
@@ -159,7 +164,8 @@
   V(kOperandNotANumber, "Operand not a number")                                \
   V(kObjectTagged, "The object is tagged")                                     \
   V(kObjectNotTagged, "The object is not tagged")                              \
-  V(kOptimizationDisabled, "Optimization is disabled")                         \
+  V(kOptimizationDisabled, "Optimization disabled")                            \
+  V(kOptimizationDisabledForTest, "Optimization disabled for test")            \
   V(kOptimizedTooManyTimes, "Optimized too many times")                        \
   V(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister,                   \
     "Out of virtual registers while trying to allocate temp register")         \
@@ -185,8 +191,6 @@
   V(kTailCall, "Tail call")                                                    \
   V(kTheCurrentStackPointerIsBelowCsp,                                         \
     "The current stack pointer is below csp")                                  \
-  V(kTheSourceAndDestinationAreTheSame,                                        \
-    "The source and destination are the same")                                 \
   V(kTheStackWasCorruptedByMacroAssemblerCall,                                 \
     "The stack was corrupted by MacroAssembler::Call()")                       \
   V(kTooManyParametersLocals, "Too many parameters/locals")                    \
@@ -228,8 +232,6 @@
   V(kUnexpectedLevelAfterReturnFromApiCall,                                    \
     "Unexpected level after return from api call")                             \
   V(kUnexpectedNegativeValue, "Unexpected negative value")                     \
-  V(kUnexpectedNumberOfPreAllocatedPropertyFields,                             \
-    "Unexpected number of pre-allocated property fields")                      \
   V(kUnexpectedFunctionIDForInvokeIntrinsic,                                   \
     "Unexpected runtime function id for the InvokeIntrinsic bytecode")         \
   V(kUnexpectedFPCRMode, "Unexpected FPCR mode.")                              \
@@ -252,8 +254,6 @@
   V(kUnsupportedPhiUseOfArguments, "Unsupported phi use of arguments")         \
   V(kUnsupportedPhiUseOfConstVariable,                                         \
     "Unsupported phi use of const or let variable")                            \
-  V(kUnexpectedReturnFromBytecodeHandler,                                      \
-    "Unexpectedly returned from a bytecode handler")                           \
   V(kUnexpectedReturnFromThrow, "Unexpectedly returned from a throw")          \
   V(kUnsupportedSwitchStatement, "Unsupported switch statement")               \
   V(kUnsupportedTaggedImmediate, "Unsupported tagged immediate")               \
@@ -267,8 +267,7 @@
   V(kWrongArgumentCountForInvokeIntrinsic,                                     \
     "Wrong number of arguments for intrinsic")                                 \
   V(kShouldNotDirectlyEnterOsrFunction,                                        \
-    "Should not directly enter OSR-compiled function")                         \
-  V(kYield, "Yield")
+    "Should not directly enter OSR-compiled function")
 
 #define ERROR_MESSAGES_CONSTANTS(C, T) C,
 enum BailoutReason {
diff --git a/src/base.isolate b/src/base.isolate
index b51de01..592e4f6 100644
--- a/src/base.isolate
+++ b/src/base.isolate
@@ -4,7 +4,7 @@
 {
   'includes': [
     '../third_party/icu/icu.isolate',
-    '../build/config/win/msvs_dependencies.isolate',
+    '../gypfiles/config/win/msvs_dependencies.isolate',
   ],
   'conditions': [
     ['use_custom_libcxx==1', {
@@ -22,13 +22,6 @@
         ],
       },
     }],
-    ['v8_use_snapshot=="true" and v8_use_external_startup_data==1 and v8_separate_ignition_snapshot==1', {
-      'variables': {
-        'files': [
-          '<(PRODUCT_DIR)/snapshot_blob_ignition.bin',
-        ],
-      },
-    }],
     ['OS=="linux" and component=="shared_library" and target_arch=="ia32"', {
       'variables': {
         'files': [
diff --git a/src/base/atomic-utils.h b/src/base/atomic-utils.h
new file mode 100644
index 0000000..ac90fd9
--- /dev/null
+++ b/src/base/atomic-utils.h
@@ -0,0 +1,175 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_ATOMIC_UTILS_H_
+#define V8_ATOMIC_UTILS_H_
+
+#include <limits.h>
+
+#include "src/base/atomicops.h"
+#include "src/base/macros.h"
+
+namespace v8 {
+namespace base {
+
+template <class T>
+class AtomicNumber {
+ public:
+  AtomicNumber() : value_(0) {}
+  explicit AtomicNumber(T initial) : value_(initial) {}
+
+  // Returns the newly set value.
+  V8_INLINE T Increment(T increment) {
+    return static_cast<T>(base::Barrier_AtomicIncrement(
+        &value_, static_cast<base::AtomicWord>(increment)));
+  }
+
+  V8_INLINE T Value() { return static_cast<T>(base::Acquire_Load(&value_)); }
+
+  V8_INLINE void SetValue(T new_value) {
+    base::Release_Store(&value_, static_cast<base::AtomicWord>(new_value));
+  }
+
+  V8_INLINE T operator=(T value) {
+    SetValue(value);
+    return value;
+  }
+
+ private:
+  STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
+
+  base::AtomicWord value_;
+};
+
+
+// Flag using T atomically. Also accepts void* as T.
+template <typename T>
+class AtomicValue {
+ public:
+  AtomicValue() : value_(0) {}
+
+  explicit AtomicValue(T initial)
+      : value_(cast_helper<T>::to_storage_type(initial)) {}
+
+  V8_INLINE T Value() {
+    return cast_helper<T>::to_return_type(base::Acquire_Load(&value_));
+  }
+
+  V8_INLINE bool TrySetValue(T old_value, T new_value) {
+    return base::Release_CompareAndSwap(
+               &value_, cast_helper<T>::to_storage_type(old_value),
+               cast_helper<T>::to_storage_type(new_value)) ==
+           cast_helper<T>::to_storage_type(old_value);
+  }
+
+  V8_INLINE void SetValue(T new_value) {
+    base::Release_Store(&value_, cast_helper<T>::to_storage_type(new_value));
+  }
+
+ private:
+  STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
+
+  template <typename S>
+  struct cast_helper {
+    static base::AtomicWord to_storage_type(S value) {
+      return static_cast<base::AtomicWord>(value);
+    }
+    static S to_return_type(base::AtomicWord value) {
+      return static_cast<S>(value);
+    }
+  };
+
+  template <typename S>
+  struct cast_helper<S*> {
+    static base::AtomicWord to_storage_type(S* value) {
+      return reinterpret_cast<base::AtomicWord>(value);
+    }
+    static S* to_return_type(base::AtomicWord value) {
+      return reinterpret_cast<S*>(value);
+    }
+  };
+
+  base::AtomicWord value_;
+};
+
+
+// See utils.h for EnumSet. Storage is always base::AtomicWord.
+// Requirements on E:
+// - No explicit values.
+// - E::kLastValue defined to be the last actually used value.
+//
+// Example:
+// enum E { kA, kB, kC, kLastValue = kC };
+template <class E>
+class AtomicEnumSet {
+ public:
+  explicit AtomicEnumSet(base::AtomicWord bits = 0) : bits_(bits) {}
+
+  bool IsEmpty() const { return ToIntegral() == 0; }
+
+  bool Contains(E element) const { return (ToIntegral() & Mask(element)) != 0; }
+  bool ContainsAnyOf(const AtomicEnumSet& set) const {
+    return (ToIntegral() & set.ToIntegral()) != 0;
+  }
+
+  void RemoveAll() { base::Release_Store(&bits_, 0); }
+
+  bool operator==(const AtomicEnumSet& set) const {
+    return ToIntegral() == set.ToIntegral();
+  }
+
+  bool operator!=(const AtomicEnumSet& set) const {
+    return ToIntegral() != set.ToIntegral();
+  }
+
+  AtomicEnumSet<E> operator|(const AtomicEnumSet& set) const {
+    return AtomicEnumSet<E>(ToIntegral() | set.ToIntegral());
+  }
+
+// The following operations modify the underlying storage.
+
+#define ATOMIC_SET_WRITE(OP, NEW_VAL)                                     \
+  do {                                                                    \
+    base::AtomicWord old;                                                 \
+    do {                                                                  \
+      old = base::Acquire_Load(&bits_);                                   \
+    } while (base::Release_CompareAndSwap(&bits_, old, old OP NEW_VAL) != \
+             old);                                                        \
+  } while (false)
+
+  void Add(E element) { ATOMIC_SET_WRITE(|, Mask(element)); }
+
+  void Add(const AtomicEnumSet& set) { ATOMIC_SET_WRITE(|, set.ToIntegral()); }
+
+  void Remove(E element) { ATOMIC_SET_WRITE(&, ~Mask(element)); }
+
+  void Remove(const AtomicEnumSet& set) {
+    ATOMIC_SET_WRITE(&, ~set.ToIntegral());
+  }
+
+  void Intersect(const AtomicEnumSet& set) {
+    ATOMIC_SET_WRITE(&, set.ToIntegral());
+  }
+
+#undef ATOMIC_SET_OP
+
+ private:
+  // Check whether there's enough storage to hold E.
+  STATIC_ASSERT(E::kLastValue < (sizeof(base::AtomicWord) * CHAR_BIT));
+
+  V8_INLINE base::AtomicWord ToIntegral() const {
+    return base::Acquire_Load(&bits_);
+  }
+
+  V8_INLINE base::AtomicWord Mask(E element) const {
+    return static_cast<base::AtomicWord>(1) << element;
+  }
+
+  base::AtomicWord bits_;
+};
+
+}  // namespace base
+}  // namespace v8
+
+#endif  // #define V8_ATOMIC_UTILS_H_
diff --git a/src/base/atomicops_internals_mips64_gcc.h b/src/base/atomicops_internals_mips64_gcc.h
index 85b4e46..cf2e194 100644
--- a/src/base/atomicops_internals_mips64_gcc.h
+++ b/src/base/atomicops_internals_mips64_gcc.h
@@ -91,18 +91,19 @@
                                           Atomic32 increment) {
   Atomic32 temp, temp2;
 
-  __asm__ __volatile__(".set push\n"
-                       ".set noreorder\n"
-                       "1:\n"
-                       "ll %0, %2\n"  // temp = *ptr
-                       "addu %1, %0, %3\n"  // temp2 = temp + increment
-                       "sc %1, %2\n"  // *ptr = temp2 (with atomic check)
-                       "beqz %1, 1b\n"  // start again on atomic error
-                       "addu %1, %0, %3\n"  // temp2 = temp + increment
-                       ".set pop\n"
-                       : "=&r" (temp), "=&r" (temp2), "=m" (*ptr)
-                       : "Ir" (increment), "m" (*ptr)
-                       : "memory");
+  __asm__ __volatile__(
+      ".set push\n"
+      ".set noreorder\n"
+      "1:\n"
+      "ll %0, %2\n"        // temp = *ptr
+      "addu %1, %0, %3\n"  // temp2 = temp + increment
+      "sc %1, %2\n"        // *ptr = temp2 (with atomic check)
+      "beqz %1, 1b\n"      // start again on atomic error
+      "addu %1, %0, %3\n"  // temp2 = temp + increment
+      ".set pop\n"
+      : "=&r"(temp), "=&r"(temp2), "=ZC"(*ptr)
+      : "Ir"(increment), "m"(*ptr)
+      : "memory");
   // temp2 now holds the final value.
   return temp2;
 }
@@ -228,18 +229,19 @@
                                           Atomic64 increment) {
   Atomic64 temp, temp2;
 
-  __asm__ __volatile__(".set push\n"
-                       ".set noreorder\n"
-                       "1:\n"
-                       "lld %0, %2\n"  // temp = *ptr
-                       "daddu %1, %0, %3\n"  // temp2 = temp + increment
-                       "scd %1, %2\n"  // *ptr = temp2 (with atomic check)
-                       "beqz %1, 1b\n"  // start again on atomic error
-                       "daddu %1, %0, %3\n"  // temp2 = temp + increment
-                       ".set pop\n"
-                       : "=&r" (temp), "=&r" (temp2), "=m" (*ptr)
-                       : "Ir" (increment), "m" (*ptr)
-                       : "memory");
+  __asm__ __volatile__(
+      ".set push\n"
+      ".set noreorder\n"
+      "1:\n"
+      "lld %0, %2\n"        // temp = *ptr
+      "daddu %1, %0, %3\n"  // temp2 = temp + increment
+      "scd %1, %2\n"        // *ptr = temp2 (with atomic check)
+      "beqz %1, 1b\n"       // start again on atomic error
+      "daddu %1, %0, %3\n"  // temp2 = temp + increment
+      ".set pop\n"
+      : "=&r"(temp), "=&r"(temp2), "=ZC"(*ptr)
+      : "Ir"(increment), "m"(*ptr)
+      : "memory");
   // temp2 now holds the final value.
   return temp2;
 }
diff --git a/src/base/bits.cc b/src/base/bits.cc
index 74d747f..9b949cc 100644
--- a/src/base/bits.cc
+++ b/src/base/bits.cc
@@ -7,6 +7,7 @@
 #include <limits>
 
 #include "src/base/logging.h"
+#include "src/base/safe_math.h"
 
 namespace v8 {
 namespace base {
@@ -48,6 +49,35 @@
   return lhs % rhs;
 }
 
+
+int64_t FromCheckedNumeric(const internal::CheckedNumeric<int64_t> value) {
+  if (value.IsValid())
+    return value.ValueUnsafe();
+
+  // We could return max/min but we don't really expose what the maximum delta
+  // is. Instead, return max/(-max), which is something that clients can reason
+  // about.
+  // TODO(rvargas) crbug.com/332611: don't use internal values.
+  int64_t limit = std::numeric_limits<int64_t>::max();
+  if (value.validity() == internal::RANGE_UNDERFLOW)
+    limit = -limit;
+  return value.ValueOrDefault(limit);
+}
+
+
+int64_t SignedSaturatedAdd64(int64_t lhs, int64_t rhs) {
+  internal::CheckedNumeric<int64_t> rv(lhs);
+  rv += rhs;
+  return FromCheckedNumeric(rv);
+}
+
+
+int64_t SignedSaturatedSub64(int64_t lhs, int64_t rhs) {
+  internal::CheckedNumeric<int64_t> rv(lhs);
+  rv -= rhs;
+  return FromCheckedNumeric(rv);
+}
+
 }  // namespace bits
 }  // namespace base
 }  // namespace v8
diff --git a/src/base/bits.h b/src/base/bits.h
index 0e76624..1bb3a0f 100644
--- a/src/base/bits.h
+++ b/src/base/bits.h
@@ -16,6 +16,12 @@
 
 namespace v8 {
 namespace base {
+
+namespace internal {
+template <typename T>
+class CheckedNumeric;
+}
+
 namespace bits {
 
 // CountPopulation32(value) returns the number of bits set in |value|.
@@ -105,7 +111,6 @@
   return result;
 }
 
-
 // CountTrailingZeros32(value) returns the number of zero bits preceding the
 // least significant 1 bit in |value| if |value| is non-zero, otherwise it
 // returns 32.
@@ -141,6 +146,14 @@
 #endif
 }
 
+// Overloaded versions of CountTrailingZeros32/64.
+inline unsigned CountTrailingZeros(uint32_t value) {
+  return CountTrailingZeros32(value);
+}
+
+inline unsigned CountTrailingZeros(uint64_t value) {
+  return CountTrailingZeros64(value);
+}
 
 // Returns true iff |value| is a power of 2.
 inline bool IsPowerOfTwo32(uint32_t value) {
@@ -296,6 +309,21 @@
   return rhs ? lhs % rhs : 0u;
 }
 
+
+// Clamp |value| on overflow and underflow conditions.
+int64_t FromCheckedNumeric(const internal::CheckedNumeric<int64_t> value);
+
+
+// SignedSaturatedAdd64(lhs, rhs) adds |lhs| and |rhs|,
+// checks and returns the result.
+int64_t SignedSaturatedAdd64(int64_t lhs, int64_t rhs);
+
+
+// SignedSaturatedSub64(lhs, rhs) substracts |lhs| by |rhs|,
+// checks and returns the result.
+int64_t SignedSaturatedSub64(int64_t lhs, int64_t rhs);
+
+
 }  // namespace bits
 }  // namespace base
 }  // namespace v8
diff --git a/src/base/compiler-specific.h b/src/base/compiler-specific.h
index ffd5a44..822893f 100644
--- a/src/base/compiler-specific.h
+++ b/src/base/compiler-specific.h
@@ -26,6 +26,17 @@
 #define WARN_UNUSED_RESULT /* NOT SUPPORTED */
 #endif
 
+// Tell the compiler a function is using a printf-style format string.
+// |format_param| is the one-based index of the format string parameter;
+// |dots_param| is the one-based index of the "..." parameter.
+// For v*printf functions (which take a va_list), pass 0 for dots_param.
+// (This is undocumented but matches what the system C headers do.)
+#if defined(__GNUC__)
+#define PRINTF_FORMAT(format_param, dots_param) \
+  __attribute__((format(printf, format_param, dots_param)))
+#else
+#define PRINTF_FORMAT(format_param, dots_param)
+#endif
 
 // The C++ standard requires that static const members have an out-of-class
 // definition (in a single compilation unit), but MSVC chokes on this (when
diff --git a/src/base/cpu.cc b/src/base/cpu.cc
index 12a3881..16eb7c9 100644
--- a/src/base/cpu.cc
+++ b/src/base/cpu.cc
@@ -338,7 +338,8 @@
       has_vfp_(false),
       has_vfp3_(false),
       has_vfp3_d32_(false),
-      is_fp64_mode_(false) {
+      is_fp64_mode_(false),
+      has_non_stop_time_stamp_counter_(false) {
   memcpy(vendor_, "Unknown", 8);
 #if V8_OS_NACL
 // Portable host shouldn't do feature detection.
@@ -419,6 +420,13 @@
     has_sahf_ = (cpu_info[2] & 0x00000001) != 0;
   }
 
+  // Check if CPU has non stoppable time stamp counter.
+  const int parameter_containing_non_stop_time_stamp_counter = 0x80000007;
+  if (num_ext_ids >= parameter_containing_non_stop_time_stamp_counter) {
+    __cpuid(cpu_info, parameter_containing_non_stop_time_stamp_counter);
+    has_non_stop_time_stamp_counter_ = (cpu_info[3] & (1 << 8)) != 0;
+  }
+
 #elif V8_HOST_ARCH_ARM
 
 #if V8_OS_LINUX
diff --git a/src/base/cpu.h b/src/base/cpu.h
index 3778d27..19d4102 100644
--- a/src/base/cpu.h
+++ b/src/base/cpu.h
@@ -97,6 +97,9 @@
   bool has_lzcnt() const { return has_lzcnt_; }
   bool has_popcnt() const { return has_popcnt_; }
   bool is_atom() const { return is_atom_; }
+  bool has_non_stop_time_stamp_counter() const {
+    return has_non_stop_time_stamp_counter_;
+  }
 
   // arm features
   bool has_idiva() const { return has_idiva_; }
@@ -148,6 +151,7 @@
   bool has_vfp3_;
   bool has_vfp3_d32_;
   bool is_fp64_mode_;
+  bool has_non_stop_time_stamp_counter_;
 };
 
 }  // namespace base
diff --git a/src/base/file-utils.cc b/src/base/file-utils.cc
new file mode 100644
index 0000000..2262df9
--- /dev/null
+++ b/src/base/file-utils.cc
@@ -0,0 +1,36 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/base/file-utils.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "src/base/platform/platform.h"
+
+namespace v8 {
+namespace internal {
+
+char* RelativePath(char** buffer, const char* exec_path, const char* name) {
+  DCHECK(exec_path);
+  int path_separator = static_cast<int>(strlen(exec_path)) - 1;
+  while (path_separator >= 0 &&
+         !base::OS::isDirectorySeparator(exec_path[path_separator])) {
+    path_separator--;
+  }
+  if (path_separator >= 0) {
+    int name_length = static_cast<int>(strlen(name));
+    *buffer =
+        reinterpret_cast<char*>(calloc(path_separator + name_length + 2, 1));
+    *buffer[0] = '\0';
+    strncat(*buffer, exec_path, path_separator + 1);
+    strncat(*buffer, name, name_length);
+  } else {
+    *buffer = strdup(name);
+  }
+  return *buffer;
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/base/file-utils.h b/src/base/file-utils.h
new file mode 100644
index 0000000..ce9e9a1
--- /dev/null
+++ b/src/base/file-utils.h
@@ -0,0 +1,18 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_FILE_UTILS_H_
+#define V8_FILE_UTILS_H_
+
+namespace v8 {
+namespace internal {
+
+// Helper functions to manipulate file paths.
+
+char* RelativePath(char** buffer, const char* exec_path, const char* name);
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_FILE_UTILS_H_
diff --git a/src/base/format-macros.h b/src/base/format-macros.h
new file mode 100644
index 0000000..5f5fe5d
--- /dev/null
+++ b/src/base/format-macros.h
@@ -0,0 +1,97 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_FORMAT_MACROS_H_
+#define BASE_FORMAT_MACROS_H_
+
+// This file defines the format macros for some integer types.
+
+// To print a 64-bit value in a portable way:
+//   int64_t value;
+//   printf("xyz:%" PRId64, value);
+// The "d" in the macro corresponds to %d; you can also use PRIu64 etc.
+//
+// For wide strings, prepend "Wide" to the macro:
+//   int64_t value;
+//   StringPrintf(L"xyz: %" WidePRId64, value);
+//
+// To print a size_t value in a portable way:
+//   size_t size;
+//   printf("xyz: %" PRIuS, size);
+// The "u" in the macro corresponds to %u, and S is for "size".
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "src/base/build_config.h"
+
+#if defined(V8_OS_POSIX) && (defined(_INTTYPES_H) || defined(_INTTYPES_H_)) && \
+    !defined(PRId64)
+#error "inttypes.h has already been included before this header file, but "
+#error "without __STDC_FORMAT_MACROS defined."
+#endif
+
+#if defined(V8_OS_POSIX) && !defined(__STDC_FORMAT_MACROS)
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include <inttypes.h>
+
+#if defined(V8_OS_POSIX)
+
+// GCC will concatenate wide and narrow strings correctly, so nothing needs to
+// be done here.
+#define WidePRId64 PRId64
+#define WidePRIu64 PRIu64
+#define WidePRIx64 PRIx64
+
+#if !defined(PRIuS)
+#define PRIuS "zu"
+#endif
+
+// The size of NSInteger and NSUInteger varies between 32-bit and 64-bit
+// architectures and Apple does not provides standard format macros and
+// recommends casting. This has many drawbacks, so instead define macros
+// for formatting those types.
+#if defined(V8_OS_MACOSX)
+#if defined(V8_HOST_ARCH_64_BIT)
+#if !defined(PRIdNS)
+#define PRIdNS "ld"
+#endif
+#if !defined(PRIuNS)
+#define PRIuNS "lu"
+#endif
+#if !defined(PRIxNS)
+#define PRIxNS "lx"
+#endif
+#else  // defined(V8_HOST_ARCH_64_BIT)
+#if !defined(PRIdNS)
+#define PRIdNS "d"
+#endif
+#if !defined(PRIuNS)
+#define PRIuNS "u"
+#endif
+#if !defined(PRIxNS)
+#define PRIxNS "x"
+#endif
+#endif
+#endif  // defined(V8_OS_MACOSX)
+
+#else  // V8_OS_WIN
+
+#if !defined(PRId64) || !defined(PRIu64) || !defined(PRIx64)
+#error "inttypes.h provided by win toolchain should define these."
+#endif
+
+#define WidePRId64 L"I64d"
+#define WidePRIu64 L"I64u"
+#define WidePRIx64 L"I64x"
+
+#if !defined(PRIuS)
+#define PRIuS "Iu"
+#endif
+
+#endif
+
+#endif  // BASE_FORMAT_MACROS_H_
diff --git a/src/base/hashmap.h b/src/base/hashmap.h
new file mode 100644
index 0000000..efb5dc8
--- /dev/null
+++ b/src/base/hashmap.h
@@ -0,0 +1,352 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// The reason we write our own hash map instead of using unordered_map in STL,
+// is that STL containers use a mutex pool on debug build, which will lead to
+// deadlock when we are using async signal handler.
+
+#ifndef V8_BASE_HASHMAP_H_
+#define V8_BASE_HASHMAP_H_
+
+#include <stdlib.h>
+
+#include "src/base/bits.h"
+#include "src/base/logging.h"
+
+namespace v8 {
+namespace base {
+
+class DefaultAllocationPolicy {
+ public:
+  V8_INLINE void* New(size_t size) { return malloc(size); }
+  V8_INLINE static void Delete(void* p) { free(p); }
+};
+
+template <class AllocationPolicy>
+class TemplateHashMapImpl {
+ public:
+  typedef bool (*MatchFun)(void* key1, void* key2);
+
+  // The default capacity.  This is used by the call sites which want
+  // to pass in a non-default AllocationPolicy but want to use the
+  // default value of capacity specified by the implementation.
+  static const uint32_t kDefaultHashMapCapacity = 8;
+
+  // initial_capacity is the size of the initial hash map;
+  // it must be a power of 2 (and thus must not be 0).
+  TemplateHashMapImpl(MatchFun match,
+                      uint32_t capacity = kDefaultHashMapCapacity,
+                      AllocationPolicy allocator = AllocationPolicy());
+
+  ~TemplateHashMapImpl();
+
+  // HashMap entries are (key, value, hash) triplets.
+  // Some clients may not need to use the value slot
+  // (e.g. implementers of sets, where the key is the value).
+  struct Entry {
+    void* key;
+    void* value;
+    uint32_t hash;  // The full hash value for key
+    int order;      // If you never remove entries this is the insertion order.
+  };
+
+  // If an entry with matching key is found, returns that entry.
+  // Otherwise, NULL is returned.
+  Entry* Lookup(void* key, uint32_t hash) const;
+
+  // If an entry with matching key is found, returns that entry.
+  // If no matching entry is found, a new entry is inserted with
+  // corresponding key, key hash, and NULL value.
+  Entry* LookupOrInsert(void* key, uint32_t hash,
+                        AllocationPolicy allocator = AllocationPolicy());
+
+  // Removes the entry with matching key.
+  // It returns the value of the deleted entry
+  // or null if there is no value for such key.
+  void* Remove(void* key, uint32_t hash);
+
+  // Empties the hash map (occupancy() == 0).
+  void Clear();
+
+  // The number of (non-empty) entries in the table.
+  uint32_t occupancy() const { return occupancy_; }
+
+  // The capacity of the table. The implementation
+  // makes sure that occupancy is at most 80% of
+  // the table capacity.
+  uint32_t capacity() const { return capacity_; }
+
+  // Iteration
+  //
+  // for (Entry* p = map.Start(); p != NULL; p = map.Next(p)) {
+  //   ...
+  // }
+  //
+  // If entries are inserted during iteration, the effect of
+  // calling Next() is undefined.
+  Entry* Start() const;
+  Entry* Next(Entry* p) const;
+
+  // Some match functions defined for convenience.
+  static bool PointersMatch(void* key1, void* key2) { return key1 == key2; }
+
+ private:
+  MatchFun match_;
+  Entry* map_;
+  uint32_t capacity_;
+  uint32_t occupancy_;
+
+  Entry* map_end() const { return map_ + capacity_; }
+  Entry* Probe(void* key, uint32_t hash) const;
+  void Initialize(uint32_t capacity, AllocationPolicy allocator);
+  void Resize(AllocationPolicy allocator);
+};
+
+typedef TemplateHashMapImpl<DefaultAllocationPolicy> HashMap;
+
+template <class AllocationPolicy>
+TemplateHashMapImpl<AllocationPolicy>::TemplateHashMapImpl(
+    MatchFun match, uint32_t initial_capacity, AllocationPolicy allocator) {
+  match_ = match;
+  Initialize(initial_capacity, allocator);
+}
+
+template <class AllocationPolicy>
+TemplateHashMapImpl<AllocationPolicy>::~TemplateHashMapImpl() {
+  AllocationPolicy::Delete(map_);
+}
+
+template <class AllocationPolicy>
+typename TemplateHashMapImpl<AllocationPolicy>::Entry*
+TemplateHashMapImpl<AllocationPolicy>::Lookup(void* key, uint32_t hash) const {
+  Entry* p = Probe(key, hash);
+  return p->key != NULL ? p : NULL;
+}
+
+template <class AllocationPolicy>
+typename TemplateHashMapImpl<AllocationPolicy>::Entry*
+TemplateHashMapImpl<AllocationPolicy>::LookupOrInsert(
+    void* key, uint32_t hash, AllocationPolicy allocator) {
+  // Find a matching entry.
+  Entry* p = Probe(key, hash);
+  if (p->key != NULL) {
+    return p;
+  }
+
+  // No entry found; insert one.
+  p->key = key;
+  p->value = NULL;
+  p->hash = hash;
+  p->order = occupancy_;
+  occupancy_++;
+
+  // Grow the map if we reached >= 80% occupancy.
+  if (occupancy_ + occupancy_ / 4 >= capacity_) {
+    Resize(allocator);
+    p = Probe(key, hash);
+  }
+
+  return p;
+}
+
+template <class AllocationPolicy>
+void* TemplateHashMapImpl<AllocationPolicy>::Remove(void* key, uint32_t hash) {
+  // Lookup the entry for the key to remove.
+  Entry* p = Probe(key, hash);
+  if (p->key == NULL) {
+    // Key not found nothing to remove.
+    return NULL;
+  }
+
+  void* value = p->value;
+  // To remove an entry we need to ensure that it does not create an empty
+  // entry that will cause the search for another entry to stop too soon. If all
+  // the entries between the entry to remove and the next empty slot have their
+  // initial position inside this interval, clearing the entry to remove will
+  // not break the search. If, while searching for the next empty entry, an
+  // entry is encountered which does not have its initial position between the
+  // entry to remove and the position looked at, then this entry can be moved to
+  // the place of the entry to remove without breaking the search for it. The
+  // entry made vacant by this move is now the entry to remove and the process
+  // starts over.
+  // Algorithm from http://en.wikipedia.org/wiki/Open_addressing.
+
+  // This guarantees loop termination as there is at least one empty entry so
+  // eventually the removed entry will have an empty entry after it.
+  DCHECK(occupancy_ < capacity_);
+
+  // p is the candidate entry to clear. q is used to scan forwards.
+  Entry* q = p;  // Start at the entry to remove.
+  while (true) {
+    // Move q to the next entry.
+    q = q + 1;
+    if (q == map_end()) {
+      q = map_;
+    }
+
+    // All entries between p and q have their initial position between p and q
+    // and the entry p can be cleared without breaking the search for these
+    // entries.
+    if (q->key == NULL) {
+      break;
+    }
+
+    // Find the initial position for the entry at position q.
+    Entry* r = map_ + (q->hash & (capacity_ - 1));
+
+    // If the entry at position q has its initial position outside the range
+    // between p and q it can be moved forward to position p and will still be
+    // found. There is now a new candidate entry for clearing.
+    if ((q > p && (r <= p || r > q)) || (q < p && (r <= p && r > q))) {
+      *p = *q;
+      p = q;
+    }
+  }
+
+  // Clear the entry which is allowed to en emptied.
+  p->key = NULL;
+  occupancy_--;
+  return value;
+}
+
+template <class AllocationPolicy>
+void TemplateHashMapImpl<AllocationPolicy>::Clear() {
+  // Mark all entries as empty.
+  const Entry* end = map_end();
+  for (Entry* p = map_; p < end; p++) {
+    p->key = NULL;
+  }
+  occupancy_ = 0;
+}
+
+template <class AllocationPolicy>
+typename TemplateHashMapImpl<AllocationPolicy>::Entry*
+TemplateHashMapImpl<AllocationPolicy>::Start() const {
+  return Next(map_ - 1);
+}
+
+template <class AllocationPolicy>
+typename TemplateHashMapImpl<AllocationPolicy>::Entry*
+TemplateHashMapImpl<AllocationPolicy>::Next(Entry* p) const {
+  const Entry* end = map_end();
+  DCHECK(map_ - 1 <= p && p < end);
+  for (p++; p < end; p++) {
+    if (p->key != NULL) {
+      return p;
+    }
+  }
+  return NULL;
+}
+
+template <class AllocationPolicy>
+typename TemplateHashMapImpl<AllocationPolicy>::Entry*
+TemplateHashMapImpl<AllocationPolicy>::Probe(void* key, uint32_t hash) const {
+  DCHECK(key != NULL);
+
+  DCHECK(base::bits::IsPowerOfTwo32(capacity_));
+  Entry* p = map_ + (hash & (capacity_ - 1));
+  const Entry* end = map_end();
+  DCHECK(map_ <= p && p < end);
+
+  DCHECK(occupancy_ < capacity_);  // Guarantees loop termination.
+  while (p->key != NULL && (hash != p->hash || !match_(key, p->key))) {
+    p++;
+    if (p >= end) {
+      p = map_;
+    }
+  }
+
+  return p;
+}
+
+template <class AllocationPolicy>
+void TemplateHashMapImpl<AllocationPolicy>::Initialize(
+    uint32_t capacity, AllocationPolicy allocator) {
+  DCHECK(base::bits::IsPowerOfTwo32(capacity));
+  map_ = reinterpret_cast<Entry*>(allocator.New(capacity * sizeof(Entry)));
+  if (map_ == NULL) {
+    FATAL("Out of memory: HashMap::Initialize");
+    return;
+  }
+  capacity_ = capacity;
+  Clear();
+}
+
+template <class AllocationPolicy>
+void TemplateHashMapImpl<AllocationPolicy>::Resize(AllocationPolicy allocator) {
+  Entry* map = map_;
+  uint32_t n = occupancy_;
+
+  // Allocate larger map.
+  Initialize(capacity_ * 2, allocator);
+
+  // Rehash all current entries.
+  for (Entry* p = map; n > 0; p++) {
+    if (p->key != NULL) {
+      Entry* entry = LookupOrInsert(p->key, p->hash, allocator);
+      entry->value = p->value;
+      entry->order = p->order;
+      n--;
+    }
+  }
+
+  // Delete old map.
+  AllocationPolicy::Delete(map);
+}
+
+// A hash map for pointer keys and values with an STL-like interface.
+template <class Key, class Value, class AllocationPolicy>
+class TemplateHashMap : private TemplateHashMapImpl<AllocationPolicy> {
+ public:
+  STATIC_ASSERT(sizeof(Key*) == sizeof(void*));    // NOLINT
+  STATIC_ASSERT(sizeof(Value*) == sizeof(void*));  // NOLINT
+  struct value_type {
+    Key* first;
+    Value* second;
+  };
+
+  class Iterator {
+   public:
+    Iterator& operator++() {
+      entry_ = map_->Next(entry_);
+      return *this;
+    }
+
+    value_type* operator->() { return reinterpret_cast<value_type*>(entry_); }
+    bool operator!=(const Iterator& other) { return entry_ != other.entry_; }
+
+   private:
+    Iterator(const TemplateHashMapImpl<AllocationPolicy>* map,
+             typename TemplateHashMapImpl<AllocationPolicy>::Entry* entry)
+        : map_(map), entry_(entry) {}
+
+    const TemplateHashMapImpl<AllocationPolicy>* map_;
+    typename TemplateHashMapImpl<AllocationPolicy>::Entry* entry_;
+
+    friend class TemplateHashMap;
+  };
+
+  TemplateHashMap(
+      typename TemplateHashMapImpl<AllocationPolicy>::MatchFun match,
+      AllocationPolicy allocator = AllocationPolicy())
+      : TemplateHashMapImpl<AllocationPolicy>(
+            match,
+            TemplateHashMapImpl<AllocationPolicy>::kDefaultHashMapCapacity,
+            allocator) {}
+
+  Iterator begin() const { return Iterator(this, this->Start()); }
+  Iterator end() const { return Iterator(this, NULL); }
+  Iterator find(Key* key, bool insert = false,
+                AllocationPolicy allocator = AllocationPolicy()) {
+    if (insert) {
+      return Iterator(this, this->LookupOrInsert(key, key->Hash(), allocator));
+    }
+    return Iterator(this, this->Lookup(key, key->Hash()));
+  }
+};
+
+}  // namespace base
+}  // namespace v8
+
+#endif  // V8_BASE_HASHMAP_H_
diff --git a/src/base/ieee754.cc b/src/base/ieee754.cc
new file mode 100644
index 0000000..b7178ca
--- /dev/null
+++ b/src/base/ieee754.cc
@@ -0,0 +1,2313 @@
+// The following is adapted from fdlibm (http://www.netlib.org/fdlibm).
+//
+// ====================================================
+// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+//
+// Developed at SunSoft, a Sun Microsystems, Inc. business.
+// Permission to use, copy, modify, and distribute this
+// software is freely granted, provided that this notice
+// is preserved.
+// ====================================================
+//
+// The original source code covered by the above license above has been
+// modified significantly by Google Inc.
+// Copyright 2016 the V8 project authors. All rights reserved.
+
+#include "src/base/ieee754.h"
+
+#include <cmath>
+#include <limits>
+
+#include "src/base/build_config.h"
+#include "src/base/macros.h"
+
+namespace v8 {
+namespace base {
+namespace ieee754 {
+
+namespace {
+
+/* Disable "potential divide by 0" warning in Visual Studio compiler. */
+
+#if V8_CC_MSVC
+
+#pragma warning(disable : 4723)
+
+#endif
+
+/*
+ * The original fdlibm code used statements like:
+ *  n0 = ((*(int*)&one)>>29)^1;   * index of high word *
+ *  ix0 = *(n0+(int*)&x);     * high word of x *
+ *  ix1 = *((1-n0)+(int*)&x);   * low word of x *
+ * to dig two 32 bit words out of the 64 bit IEEE floating point
+ * value.  That is non-ANSI, and, moreover, the gcc instruction
+ * scheduler gets it wrong.  We instead use the following macros.
+ * Unlike the original code, we determine the endianness at compile
+ * time, not at run time; I don't see much benefit to selecting
+ * endianness at run time.
+ */
+
+/*
+ * A union which permits us to convert between a double and two 32 bit
+ * ints.
+ */
+
+#if V8_TARGET_LITTLE_ENDIAN
+
+typedef union {
+  double value;
+  struct {
+    uint32_t lsw;
+    uint32_t msw;
+  } parts;
+  struct {
+    uint64_t w;
+  } xparts;
+} ieee_double_shape_type;
+
+#else
+
+typedef union {
+  double value;
+  struct {
+    uint32_t msw;
+    uint32_t lsw;
+  } parts;
+  struct {
+    uint64_t w;
+  } xparts;
+} ieee_double_shape_type;
+
+#endif
+
+/* Get two 32 bit ints from a double.  */
+
+#define EXTRACT_WORDS(ix0, ix1, d) \
+  do {                             \
+    ieee_double_shape_type ew_u;   \
+    ew_u.value = (d);              \
+    (ix0) = ew_u.parts.msw;        \
+    (ix1) = ew_u.parts.lsw;        \
+  } while (0)
+
+/* Get a 64-bit int from a double. */
+#define EXTRACT_WORD64(ix, d)    \
+  do {                           \
+    ieee_double_shape_type ew_u; \
+    ew_u.value = (d);            \
+    (ix) = ew_u.xparts.w;        \
+  } while (0)
+
+/* Get the more significant 32 bit int from a double.  */
+
+#define GET_HIGH_WORD(i, d)      \
+  do {                           \
+    ieee_double_shape_type gh_u; \
+    gh_u.value = (d);            \
+    (i) = gh_u.parts.msw;        \
+  } while (0)
+
+/* Get the less significant 32 bit int from a double.  */
+
+#define GET_LOW_WORD(i, d)       \
+  do {                           \
+    ieee_double_shape_type gl_u; \
+    gl_u.value = (d);            \
+    (i) = gl_u.parts.lsw;        \
+  } while (0)
+
+/* Set a double from two 32 bit ints.  */
+
+#define INSERT_WORDS(d, ix0, ix1) \
+  do {                            \
+    ieee_double_shape_type iw_u;  \
+    iw_u.parts.msw = (ix0);       \
+    iw_u.parts.lsw = (ix1);       \
+    (d) = iw_u.value;             \
+  } while (0)
+
+/* Set a double from a 64-bit int. */
+#define INSERT_WORD64(d, ix)     \
+  do {                           \
+    ieee_double_shape_type iw_u; \
+    iw_u.xparts.w = (ix);        \
+    (d) = iw_u.value;            \
+  } while (0)
+
+/* Set the more significant 32 bits of a double from an int.  */
+
+#define SET_HIGH_WORD(d, v)      \
+  do {                           \
+    ieee_double_shape_type sh_u; \
+    sh_u.value = (d);            \
+    sh_u.parts.msw = (v);        \
+    (d) = sh_u.value;            \
+  } while (0)
+
+/* Set the less significant 32 bits of a double from an int.  */
+
+#define SET_LOW_WORD(d, v)       \
+  do {                           \
+    ieee_double_shape_type sl_u; \
+    sl_u.value = (d);            \
+    sl_u.parts.lsw = (v);        \
+    (d) = sl_u.value;            \
+  } while (0)
+
+/* Support macro. */
+
+#define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval))
+
+int32_t __ieee754_rem_pio2(double x, double *y) WARN_UNUSED_RESULT;
+double __kernel_cos(double x, double y) WARN_UNUSED_RESULT;
+int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec,
+                      const int32_t *ipio2) WARN_UNUSED_RESULT;
+double __kernel_sin(double x, double y, int iy) WARN_UNUSED_RESULT;
+
+/* __ieee754_rem_pio2(x,y)
+ *
+ * return the remainder of x rem pi/2 in y[0]+y[1]
+ * use __kernel_rem_pio2()
+ */
+int32_t __ieee754_rem_pio2(double x, double *y) {
+  /*
+   * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
+   */
+  static const int32_t two_over_pi[] = {
+      0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C,
+      0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649,
+      0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, 0xA73EE8, 0x8235F5, 0x2EBB44,
+      0x84E99C, 0x7026B4, 0x5F7E41, 0x3991D6, 0x398353, 0x39F49C, 0x845F8B,
+      0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D,
+      0x367ECF, 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
+      0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, 0x560330,
+      0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 0x91615E, 0xE61B08,
+      0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA,
+      0x73A8C9, 0x60E27B, 0xC08C6B,
+  };
+
+  static const int32_t npio2_hw[] = {
+      0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
+      0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
+      0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
+      0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C,
+      0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB,
+      0x404858EB, 0x404921FB,
+  };
+
+  /*
+   * invpio2:  53 bits of 2/pi
+   * pio2_1:   first  33 bit of pi/2
+   * pio2_1t:  pi/2 - pio2_1
+   * pio2_2:   second 33 bit of pi/2
+   * pio2_2t:  pi/2 - (pio2_1+pio2_2)
+   * pio2_3:   third  33 bit of pi/2
+   * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
+   */
+
+  static const double
+      zero = 0.00000000000000000000e+00,    /* 0x00000000, 0x00000000 */
+      half = 5.00000000000000000000e-01,    /* 0x3FE00000, 0x00000000 */
+      two24 = 1.67772160000000000000e+07,   /* 0x41700000, 0x00000000 */
+      invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
+      pio2_1 = 1.57079632673412561417e+00,  /* 0x3FF921FB, 0x54400000 */
+      pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
+      pio2_2 = 6.07710050630396597660e-11,  /* 0x3DD0B461, 0x1A600000 */
+      pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
+      pio2_3 = 2.02226624871116645580e-21,  /* 0x3BA3198A, 0x2E000000 */
+      pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
+
+  double z, w, t, r, fn;
+  double tx[3];
+  int32_t e0, i, j, nx, n, ix, hx;
+  uint32_t low;
+
+  z = 0;
+  GET_HIGH_WORD(hx, x); /* high word of x */
+  ix = hx & 0x7fffffff;
+  if (ix <= 0x3fe921fb) { /* |x| ~<= pi/4 , no need for reduction */
+    y[0] = x;
+    y[1] = 0;
+    return 0;
+  }
+  if (ix < 0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */
+    if (hx > 0) {
+      z = x - pio2_1;
+      if (ix != 0x3ff921fb) { /* 33+53 bit pi is good enough */
+        y[0] = z - pio2_1t;
+        y[1] = (z - y[0]) - pio2_1t;
+      } else { /* near pi/2, use 33+33+53 bit pi */
+        z -= pio2_2;
+        y[0] = z - pio2_2t;
+        y[1] = (z - y[0]) - pio2_2t;
+      }
+      return 1;
+    } else { /* negative x */
+      z = x + pio2_1;
+      if (ix != 0x3ff921fb) { /* 33+53 bit pi is good enough */
+        y[0] = z + pio2_1t;
+        y[1] = (z - y[0]) + pio2_1t;
+      } else { /* near pi/2, use 33+33+53 bit pi */
+        z += pio2_2;
+        y[0] = z + pio2_2t;
+        y[1] = (z - y[0]) + pio2_2t;
+      }
+      return -1;
+    }
+  }
+  if (ix <= 0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */
+    t = fabs(x);
+    n = static_cast<int32_t>(t * invpio2 + half);
+    fn = static_cast<double>(n);
+    r = t - fn * pio2_1;
+    w = fn * pio2_1t; /* 1st round good to 85 bit */
+    if (n < 32 && ix != npio2_hw[n - 1]) {
+      y[0] = r - w; /* quick check no cancellation */
+    } else {
+      uint32_t high;
+      j = ix >> 20;
+      y[0] = r - w;
+      GET_HIGH_WORD(high, y[0]);
+      i = j - ((high >> 20) & 0x7ff);
+      if (i > 16) { /* 2nd iteration needed, good to 118 */
+        t = r;
+        w = fn * pio2_2;
+        r = t - w;
+        w = fn * pio2_2t - ((t - r) - w);
+        y[0] = r - w;
+        GET_HIGH_WORD(high, y[0]);
+        i = j - ((high >> 20) & 0x7ff);
+        if (i > 49) { /* 3rd iteration need, 151 bits acc */
+          t = r;      /* will cover all possible cases */
+          w = fn * pio2_3;
+          r = t - w;
+          w = fn * pio2_3t - ((t - r) - w);
+          y[0] = r - w;
+        }
+      }
+    }
+    y[1] = (r - y[0]) - w;
+    if (hx < 0) {
+      y[0] = -y[0];
+      y[1] = -y[1];
+      return -n;
+    } else {
+      return n;
+    }
+  }
+  /*
+   * all other (large) arguments
+   */
+  if (ix >= 0x7ff00000) { /* x is inf or NaN */
+    y[0] = y[1] = x - x;
+    return 0;
+  }
+  /* set z = scalbn(|x|,ilogb(x)-23) */
+  GET_LOW_WORD(low, x);
+  SET_LOW_WORD(z, low);
+  e0 = (ix >> 20) - 1046; /* e0 = ilogb(z)-23; */
+  SET_HIGH_WORD(z, ix - static_cast<int32_t>(e0 << 20));
+  for (i = 0; i < 2; i++) {
+    tx[i] = static_cast<double>(static_cast<int32_t>(z));
+    z = (z - tx[i]) * two24;
+  }
+  tx[2] = z;
+  nx = 3;
+  while (tx[nx - 1] == zero) nx--; /* skip zero term */
+  n = __kernel_rem_pio2(tx, y, e0, nx, 2, two_over_pi);
+  if (hx < 0) {
+    y[0] = -y[0];
+    y[1] = -y[1];
+    return -n;
+  }
+  return n;
+}
+
+/* __kernel_cos( x,  y )
+ * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ *
+ * Algorithm
+ *      1. Since cos(-x) = cos(x), we need only to consider positive x.
+ *      2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0.
+ *      3. cos(x) is approximated by a polynomial of degree 14 on
+ *         [0,pi/4]
+ *                                       4            14
+ *              cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
+ *         where the remez error is
+ *
+ *      |              2     4     6     8     10    12     14 |     -58
+ *      |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x  +C6*x  )| <= 2
+ *      |                                                      |
+ *
+ *                     4     6     8     10    12     14
+ *      4. let r = C1*x +C2*x +C3*x +C4*x +C5*x  +C6*x  , then
+ *             cos(x) = 1 - x*x/2 + r
+ *         since cos(x+y) ~ cos(x) - sin(x)*y
+ *                        ~ cos(x) - x*y,
+ *         a correction term is necessary in cos(x) and hence
+ *              cos(x+y) = 1 - (x*x/2 - (r - x*y))
+ *         For better accuracy when x > 0.3, let qx = |x|/4 with
+ *         the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125.
+ *         Then
+ *              cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)).
+ *         Note that 1-qx and (x*x/2-qx) is EXACT here, and the
+ *         magnitude of the latter is at least a quarter of x*x/2,
+ *         thus, reducing the rounding error in the subtraction.
+ */
+V8_INLINE double __kernel_cos(double x, double y) {
+  static const double
+      one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+      C1 = 4.16666666666666019037e-02,  /* 0x3FA55555, 0x5555554C */
+      C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
+      C3 = 2.48015872894767294178e-05,  /* 0x3EFA01A0, 0x19CB1590 */
+      C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
+      C5 = 2.08757232129817482790e-09,  /* 0x3E21EE9E, 0xBDB4B1C4 */
+      C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
+
+  double a, iz, z, r, qx;
+  int32_t ix;
+  GET_HIGH_WORD(ix, x);
+  ix &= 0x7fffffff;                           /* ix = |x|'s high word*/
+  if (ix < 0x3e400000) {                      /* if x < 2**27 */
+    if (static_cast<int>(x) == 0) return one; /* generate inexact */
+  }
+  z = x * x;
+  r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6)))));
+  if (ix < 0x3FD33333) { /* if |x| < 0.3 */
+    return one - (0.5 * z - (z * r - x * y));
+  } else {
+    if (ix > 0x3fe90000) { /* x > 0.78125 */
+      qx = 0.28125;
+    } else {
+      INSERT_WORDS(qx, ix - 0x00200000, 0); /* x/4 */
+    }
+    iz = 0.5 * z - qx;
+    a = one - qx;
+    return a - (iz - (z * r - x * y));
+  }
+}
+
+/* __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
+ * double x[],y[]; int e0,nx,prec; int ipio2[];
+ *
+ * __kernel_rem_pio2 return the last three digits of N with
+ *              y = x - N*pi/2
+ * so that |y| < pi/2.
+ *
+ * The method is to compute the integer (mod 8) and fraction parts of
+ * (2/pi)*x without doing the full multiplication. In general we
+ * skip the part of the product that are known to be a huge integer (
+ * more accurately, = 0 mod 8 ). Thus the number of operations are
+ * independent of the exponent of the input.
+ *
+ * (2/pi) is represented by an array of 24-bit integers in ipio2[].
+ *
+ * Input parameters:
+ *      x[]     The input value (must be positive) is broken into nx
+ *              pieces of 24-bit integers in double precision format.
+ *              x[i] will be the i-th 24 bit of x. The scaled exponent
+ *              of x[0] is given in input parameter e0 (i.e., x[0]*2^e0
+ *              match x's up to 24 bits.
+ *
+ *              Example of breaking a double positive z into x[0]+x[1]+x[2]:
+ *                      e0 = ilogb(z)-23
+ *                      z  = scalbn(z,-e0)
+ *              for i = 0,1,2
+ *                      x[i] = floor(z)
+ *                      z    = (z-x[i])*2**24
+ *
+ *
+ *      y[]     output result in an array of double precision numbers.
+ *              The dimension of y[] is:
+ *                      24-bit  precision       1
+ *                      53-bit  precision       2
+ *                      64-bit  precision       2
+ *                      113-bit precision       3
+ *              The actual value is the sum of them. Thus for 113-bit
+ *              precison, one may have to do something like:
+ *
+ *              long double t,w,r_head, r_tail;
+ *              t = (long double)y[2] + (long double)y[1];
+ *              w = (long double)y[0];
+ *              r_head = t+w;
+ *              r_tail = w - (r_head - t);
+ *
+ *      e0      The exponent of x[0]
+ *
+ *      nx      dimension of x[]
+ *
+ *      prec    an integer indicating the precision:
+ *                      0       24  bits (single)
+ *                      1       53  bits (double)
+ *                      2       64  bits (extended)
+ *                      3       113 bits (quad)
+ *
+ *      ipio2[]
+ *              integer array, contains the (24*i)-th to (24*i+23)-th
+ *              bit of 2/pi after binary point. The corresponding
+ *              floating value is
+ *
+ *                      ipio2[i] * 2^(-24(i+1)).
+ *
+ * External function:
+ *      double scalbn(), floor();
+ *
+ *
+ * Here is the description of some local variables:
+ *
+ *      jk      jk+1 is the initial number of terms of ipio2[] needed
+ *              in the computation. The recommended value is 2,3,4,
+ *              6 for single, double, extended,and quad.
+ *
+ *      jz      local integer variable indicating the number of
+ *              terms of ipio2[] used.
+ *
+ *      jx      nx - 1
+ *
+ *      jv      index for pointing to the suitable ipio2[] for the
+ *              computation. In general, we want
+ *                      ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
+ *              is an integer. Thus
+ *                      e0-3-24*jv >= 0 or (e0-3)/24 >= jv
+ *              Hence jv = max(0,(e0-3)/24).
+ *
+ *      jp      jp+1 is the number of terms in PIo2[] needed, jp = jk.
+ *
+ *      q[]     double array with integral value, representing the
+ *              24-bits chunk of the product of x and 2/pi.
+ *
+ *      q0      the corresponding exponent of q[0]. Note that the
+ *              exponent for q[i] would be q0-24*i.
+ *
+ *      PIo2[]  double precision array, obtained by cutting pi/2
+ *              into 24 bits chunks.
+ *
+ *      f[]     ipio2[] in floating point
+ *
+ *      iq[]    integer array by breaking up q[] in 24-bits chunk.
+ *
+ *      fq[]    final product of x*(2/pi) in fq[0],..,fq[jk]
+ *
+ *      ih      integer. If >0 it indicates q[] is >= 0.5, hence
+ *              it also indicates the *sign* of the result.
+ *
+ */
+int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec,
+                      const int32_t *ipio2) {
+  /* Constants:
+   * The hexadecimal values are the intended ones for the following
+   * constants. The decimal values may be used, provided that the
+   * compiler will convert from decimal to binary accurately enough
+   * to produce the hexadecimal values shown.
+   */
+  static const int init_jk[] = {2, 3, 4, 6}; /* initial value for jk */
+
+  static const double PIo2[] = {
+      1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
+      7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
+      5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
+      3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */
+      1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */
+      1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */
+      2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */
+      2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
+  };
+
+  static const double
+      zero = 0.0,
+      one = 1.0,
+      two24 = 1.67772160000000000000e+07,  /* 0x41700000, 0x00000000 */
+      twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */
+
+  int32_t jz, jx, jv, jp, jk, carry, n, iq[20], i, j, k, m, q0, ih;
+  double z, fw, f[20], fq[20], q[20];
+
+  /* initialize jk*/
+  jk = init_jk[prec];
+  jp = jk;
+
+  /* determine jx,jv,q0, note that 3>q0 */
+  jx = nx - 1;
+  jv = (e0 - 3) / 24;
+  if (jv < 0) jv = 0;
+  q0 = e0 - 24 * (jv + 1);
+
+  /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
+  j = jv - jx;
+  m = jx + jk;
+  for (i = 0; i <= m; i++, j++) {
+    f[i] = (j < 0) ? zero : static_cast<double>(ipio2[j]);
+  }
+
+  /* compute q[0],q[1],...q[jk] */
+  for (i = 0; i <= jk; i++) {
+    for (j = 0, fw = 0.0; j <= jx; j++) fw += x[j] * f[jx + i - j];
+    q[i] = fw;
+  }
+
+  jz = jk;
+recompute:
+  /* distill q[] into iq[] reversingly */
+  for (i = 0, j = jz, z = q[jz]; j > 0; i++, j--) {
+    fw = static_cast<double>(static_cast<int32_t>(twon24 * z));
+    iq[i] = static_cast<int32_t>(z - two24 * fw);
+    z = q[j - 1] + fw;
+  }
+
+  /* compute n */
+  z = scalbn(z, q0);           /* actual value of z */
+  z -= 8.0 * floor(z * 0.125); /* trim off integer >= 8 */
+  n = static_cast<int32_t>(z);
+  z -= static_cast<double>(n);
+  ih = 0;
+  if (q0 > 0) { /* need iq[jz-1] to determine n */
+    i = (iq[jz - 1] >> (24 - q0));
+    n += i;
+    iq[jz - 1] -= i << (24 - q0);
+    ih = iq[jz - 1] >> (23 - q0);
+  } else if (q0 == 0) {
+    ih = iq[jz - 1] >> 23;
+  } else if (z >= 0.5) {
+    ih = 2;
+  }
+
+  if (ih > 0) { /* q > 0.5 */
+    n += 1;
+    carry = 0;
+    for (i = 0; i < jz; i++) { /* compute 1-q */
+      j = iq[i];
+      if (carry == 0) {
+        if (j != 0) {
+          carry = 1;
+          iq[i] = 0x1000000 - j;
+        }
+      } else {
+        iq[i] = 0xffffff - j;
+      }
+    }
+    if (q0 > 0) { /* rare case: chance is 1 in 12 */
+      switch (q0) {
+        case 1:
+          iq[jz - 1] &= 0x7fffff;
+          break;
+        case 2:
+          iq[jz - 1] &= 0x3fffff;
+          break;
+      }
+    }
+    if (ih == 2) {
+      z = one - z;
+      if (carry != 0) z -= scalbn(one, q0);
+    }
+  }
+
+  /* check if recomputation is needed */
+  if (z == zero) {
+    j = 0;
+    for (i = jz - 1; i >= jk; i--) j |= iq[i];
+    if (j == 0) { /* need recomputation */
+      for (k = 1; jk >= k && iq[jk - k] == 0; k++) {
+        /* k = no. of terms needed */
+      }
+
+      for (i = jz + 1; i <= jz + k; i++) { /* add q[jz+1] to q[jz+k] */
+        f[jx + i] = ipio2[jv + i];
+        for (j = 0, fw = 0.0; j <= jx; j++) fw += x[j] * f[jx + i - j];
+        q[i] = fw;
+      }
+      jz += k;
+      goto recompute;
+    }
+  }
+
+  /* chop off zero terms */
+  if (z == 0.0) {
+    jz -= 1;
+    q0 -= 24;
+    while (iq[jz] == 0) {
+      jz--;
+      q0 -= 24;
+    }
+  } else { /* break z into 24-bit if necessary */
+    z = scalbn(z, -q0);
+    if (z >= two24) {
+      fw = static_cast<double>(static_cast<int32_t>(twon24 * z));
+      iq[jz] = z - two24 * fw;
+      jz += 1;
+      q0 += 24;
+      iq[jz] = fw;
+    } else {
+      iq[jz] = z;
+    }
+  }
+
+  /* convert integer "bit" chunk to floating-point value */
+  fw = scalbn(one, q0);
+  for (i = jz; i >= 0; i--) {
+    q[i] = fw * iq[i];
+    fw *= twon24;
+  }
+
+  /* compute PIo2[0,...,jp]*q[jz,...,0] */
+  for (i = jz; i >= 0; i--) {
+    for (fw = 0.0, k = 0; k <= jp && k <= jz - i; k++) fw += PIo2[k] * q[i + k];
+    fq[jz - i] = fw;
+  }
+
+  /* compress fq[] into y[] */
+  switch (prec) {
+    case 0:
+      fw = 0.0;
+      for (i = jz; i >= 0; i--) fw += fq[i];
+      y[0] = (ih == 0) ? fw : -fw;
+      break;
+    case 1:
+    case 2:
+      fw = 0.0;
+      for (i = jz; i >= 0; i--) fw += fq[i];
+      y[0] = (ih == 0) ? fw : -fw;
+      fw = fq[0] - fw;
+      for (i = 1; i <= jz; i++) fw += fq[i];
+      y[1] = (ih == 0) ? fw : -fw;
+      break;
+    case 3: /* painful */
+      for (i = jz; i > 0; i--) {
+        fw = fq[i - 1] + fq[i];
+        fq[i] += fq[i - 1] - fw;
+        fq[i - 1] = fw;
+      }
+      for (i = jz; i > 1; i--) {
+        fw = fq[i - 1] + fq[i];
+        fq[i] += fq[i - 1] - fw;
+        fq[i - 1] = fw;
+      }
+      for (fw = 0.0, i = jz; i >= 2; i--) fw += fq[i];
+      if (ih == 0) {
+        y[0] = fq[0];
+        y[1] = fq[1];
+        y[2] = fw;
+      } else {
+        y[0] = -fq[0];
+        y[1] = -fq[1];
+        y[2] = -fw;
+      }
+  }
+  return n & 7;
+}
+
+/* __kernel_sin( x, y, iy)
+ * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ * Input iy indicates whether y is 0. (if iy=0, y assume to be 0).
+ *
+ * Algorithm
+ *      1. Since sin(-x) = -sin(x), we need only to consider positive x.
+ *      2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0.
+ *      3. sin(x) is approximated by a polynomial of degree 13 on
+ *         [0,pi/4]
+ *                               3            13
+ *              sin(x) ~ x + S1*x + ... + S6*x
+ *         where
+ *
+ *      |sin(x)         2     4     6     8     10     12  |     -58
+ *      |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x  +S6*x   )| <= 2
+ *      |  x                                               |
+ *
+ *      4. sin(x+y) = sin(x) + sin'(x')*y
+ *                  ~ sin(x) + (1-x*x/2)*y
+ *         For better accuracy, let
+ *                   3      2      2      2      2
+ *              r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
+ *         then                   3    2
+ *              sin(x) = x + (S1*x + (x *(r-y/2)+y))
+ */
+V8_INLINE double __kernel_sin(double x, double y, int iy) {
+  static const double
+      half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+      S1 = -1.66666666666666324348e-01,  /* 0xBFC55555, 0x55555549 */
+      S2 = 8.33333333332248946124e-03,   /* 0x3F811111, 0x1110F8A6 */
+      S3 = -1.98412698298579493134e-04,  /* 0xBF2A01A0, 0x19C161D5 */
+      S4 = 2.75573137070700676789e-06,   /* 0x3EC71DE3, 0x57B1FE7D */
+      S5 = -2.50507602534068634195e-08,  /* 0xBE5AE5E6, 0x8A2B9CEB */
+      S6 = 1.58969099521155010221e-10;   /* 0x3DE5D93A, 0x5ACFD57C */
+
+  double z, r, v;
+  int32_t ix;
+  GET_HIGH_WORD(ix, x);
+  ix &= 0x7fffffff;      /* high word of x */
+  if (ix < 0x3e400000) { /* |x| < 2**-27 */
+    if (static_cast<int>(x) == 0) return x;
+  } /* generate inexact */
+  z = x * x;
+  v = z * x;
+  r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6)));
+  if (iy == 0) {
+    return x + v * (S1 + z * r);
+  } else {
+    return x - ((z * (half * y - v * r) - y) - v * S1);
+  }
+}
+
+/* __kernel_tan( x, y, k )
+ * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854
+ * Input x is assumed to be bounded by ~pi/4 in magnitude.
+ * Input y is the tail of x.
+ * Input k indicates whether tan (if k=1) or
+ * -1/tan (if k= -1) is returned.
+ *
+ * Algorithm
+ *      1. Since tan(-x) = -tan(x), we need only to consider positive x.
+ *      2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0.
+ *      3. tan(x) is approximated by a odd polynomial of degree 27 on
+ *         [0,0.67434]
+ *                               3             27
+ *              tan(x) ~ x + T1*x + ... + T13*x
+ *         where
+ *
+ *              |tan(x)         2     4            26   |     -59.2
+ *              |----- - (1+T1*x +T2*x +.... +T13*x    )| <= 2
+ *              |  x                                    |
+ *
+ *         Note: tan(x+y) = tan(x) + tan'(x)*y
+ *                        ~ tan(x) + (1+x*x)*y
+ *         Therefore, for better accuracy in computing tan(x+y), let
+ *                   3      2      2       2       2
+ *              r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
+ *         then
+ *                                  3    2
+ *              tan(x+y) = x + (T1*x + (x *(r+y)+y))
+ *
+ *      4. For x in [0.67434,pi/4],  let y = pi/4 - x, then
+ *              tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
+ *                     = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
+ */
+double __kernel_tan(double x, double y, int iy) {
+  static const double xxx[] = {
+      3.33333333333334091986e-01,             /* 3FD55555, 55555563 */
+      1.33333333333201242699e-01,             /* 3FC11111, 1110FE7A */
+      5.39682539762260521377e-02,             /* 3FABA1BA, 1BB341FE */
+      2.18694882948595424599e-02,             /* 3F9664F4, 8406D637 */
+      8.86323982359930005737e-03,             /* 3F8226E3, E96E8493 */
+      3.59207910759131235356e-03,             /* 3F6D6D22, C9560328 */
+      1.45620945432529025516e-03,             /* 3F57DBC8, FEE08315 */
+      5.88041240820264096874e-04,             /* 3F4344D8, F2F26501 */
+      2.46463134818469906812e-04,             /* 3F3026F7, 1A8D1068 */
+      7.81794442939557092300e-05,             /* 3F147E88, A03792A6 */
+      7.14072491382608190305e-05,             /* 3F12B80F, 32F0A7E9 */
+      -1.85586374855275456654e-05,            /* BEF375CB, DB605373 */
+      2.59073051863633712884e-05,             /* 3EFB2A70, 74BF7AD4 */
+      /* one */ 1.00000000000000000000e+00,   /* 3FF00000, 00000000 */
+      /* pio4 */ 7.85398163397448278999e-01,  /* 3FE921FB, 54442D18 */
+      /* pio4lo */ 3.06161699786838301793e-17 /* 3C81A626, 33145C07 */
+  };
+#define one xxx[13]
+#define pio4 xxx[14]
+#define pio4lo xxx[15]
+#define T xxx
+
+  double z, r, v, w, s;
+  int32_t ix, hx;
+
+  GET_HIGH_WORD(hx, x);             /* high word of x */
+  ix = hx & 0x7fffffff;             /* high word of |x| */
+  if (ix < 0x3e300000) {            /* x < 2**-28 */
+    if (static_cast<int>(x) == 0) { /* generate inexact */
+      uint32_t low;
+      GET_LOW_WORD(low, x);
+      if (((ix | low) | (iy + 1)) == 0) {
+        return one / fabs(x);
+      } else {
+        if (iy == 1) {
+          return x;
+        } else { /* compute -1 / (x+y) carefully */
+          double a, t;
+
+          z = w = x + y;
+          SET_LOW_WORD(z, 0);
+          v = y - (z - x);
+          t = a = -one / w;
+          SET_LOW_WORD(t, 0);
+          s = one + t * z;
+          return t + a * (s + t * v);
+        }
+      }
+    }
+  }
+  if (ix >= 0x3FE59428) { /* |x| >= 0.6744 */
+    if (hx < 0) {
+      x = -x;
+      y = -y;
+    }
+    z = pio4 - x;
+    w = pio4lo - y;
+    x = z + w;
+    y = 0.0;
+  }
+  z = x * x;
+  w = z * z;
+  /*
+   * Break x^5*(T[1]+x^2*T[2]+...) into
+   * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
+   * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
+   */
+  r = T[1] + w * (T[3] + w * (T[5] + w * (T[7] + w * (T[9] + w * T[11]))));
+  v = z *
+      (T[2] + w * (T[4] + w * (T[6] + w * (T[8] + w * (T[10] + w * T[12])))));
+  s = z * x;
+  r = y + z * (s * (r + v) + y);
+  r += T[0] * s;
+  w = x + r;
+  if (ix >= 0x3FE59428) {
+    v = iy;
+    return (1 - ((hx >> 30) & 2)) * (v - 2.0 * (x - (w * w / (w + v) - r)));
+  }
+  if (iy == 1) {
+    return w;
+  } else {
+    /*
+     * if allow error up to 2 ulp, simply return
+     * -1.0 / (x+r) here
+     */
+    /* compute -1.0 / (x+r) accurately */
+    double a, t;
+    z = w;
+    SET_LOW_WORD(z, 0);
+    v = r - (z - x);  /* z+v = r+x */
+    t = a = -1.0 / w; /* a = -1.0/w */
+    SET_LOW_WORD(t, 0);
+    s = 1.0 + t * z;
+    return t + a * (s + t * v);
+  }
+
+#undef one
+#undef pio4
+#undef pio4lo
+#undef T
+}
+
+}  // namespace
+
+/* atan(x)
+ * Method
+ *   1. Reduce x to positive by atan(x) = -atan(-x).
+ *   2. According to the integer k=4t+0.25 chopped, t=x, the argument
+ *      is further reduced to one of the following intervals and the
+ *      arctangent of t is evaluated by the corresponding formula:
+ *
+ *      [0,7/16]      atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...)
+ *      [7/16,11/16]  atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) )
+ *      [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) )
+ *      [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) )
+ *      [39/16,INF]   atan(x) = atan(INF) + atan( -1/t )
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+double atan(double x) {
+  static const double atanhi[] = {
+      4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
+      7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */
+      9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */
+      1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */
+  };
+
+  static const double atanlo[] = {
+      2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */
+      3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */
+      1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */
+      6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */
+  };
+
+  static const double aT[] = {
+      3.33333333333329318027e-01,  /* 0x3FD55555, 0x5555550D */
+      -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */
+      1.42857142725034663711e-01,  /* 0x3FC24924, 0x920083FF */
+      -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */
+      9.09088713343650656196e-02,  /* 0x3FB745CD, 0xC54C206E */
+      -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */
+      6.66107313738753120669e-02,  /* 0x3FB10D66, 0xA0D03D51 */
+      -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */
+      4.97687799461593236017e-02,  /* 0x3FA97B4B, 0x24760DEB */
+      -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */
+      1.62858201153657823623e-02,  /* 0x3F90AD3A, 0xE322DA11 */
+  };
+
+  static const double one = 1.0, huge = 1.0e300;
+
+  double w, s1, s2, z;
+  int32_t ix, hx, id;
+
+  GET_HIGH_WORD(hx, x);
+  ix = hx & 0x7fffffff;
+  if (ix >= 0x44100000) { /* if |x| >= 2^66 */
+    uint32_t low;
+    GET_LOW_WORD(low, x);
+    if (ix > 0x7ff00000 || (ix == 0x7ff00000 && (low != 0)))
+      return x + x; /* NaN */
+    if (hx > 0)
+      return atanhi[3] + *(volatile double *)&atanlo[3];
+    else
+      return -atanhi[3] - *(volatile double *)&atanlo[3];
+  }
+  if (ix < 0x3fdc0000) {            /* |x| < 0.4375 */
+    if (ix < 0x3e400000) {          /* |x| < 2^-27 */
+      if (huge + x > one) return x; /* raise inexact */
+    }
+    id = -1;
+  } else {
+    x = fabs(x);
+    if (ix < 0x3ff30000) {   /* |x| < 1.1875 */
+      if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */
+        id = 0;
+        x = (2.0 * x - one) / (2.0 + x);
+      } else { /* 11/16<=|x|< 19/16 */
+        id = 1;
+        x = (x - one) / (x + one);
+      }
+    } else {
+      if (ix < 0x40038000) { /* |x| < 2.4375 */
+        id = 2;
+        x = (x - 1.5) / (one + 1.5 * x);
+      } else { /* 2.4375 <= |x| < 2^66 */
+        id = 3;
+        x = -1.0 / x;
+      }
+    }
+  }
+  /* end of argument reduction */
+  z = x * x;
+  w = z * z;
+  /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
+  s1 = z * (aT[0] +
+            w * (aT[2] + w * (aT[4] + w * (aT[6] + w * (aT[8] + w * aT[10])))));
+  s2 = w * (aT[1] + w * (aT[3] + w * (aT[5] + w * (aT[7] + w * aT[9]))));
+  if (id < 0) {
+    return x - x * (s1 + s2);
+  } else {
+    z = atanhi[id] - ((x * (s1 + s2) - atanlo[id]) - x);
+    return (hx < 0) ? -z : z;
+  }
+}
+
+/* atan2(y,x)
+ * Method :
+ *  1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
+ *  2. Reduce x to positive by (if x and y are unexceptional):
+ *    ARG (x+iy) = arctan(y/x)       ... if x > 0,
+ *    ARG (x+iy) = pi - arctan[y/(-x)]   ... if x < 0,
+ *
+ * Special cases:
+ *
+ *  ATAN2((anything), NaN ) is NaN;
+ *  ATAN2(NAN , (anything) ) is NaN;
+ *  ATAN2(+-0, +(anything but NaN)) is +-0  ;
+ *  ATAN2(+-0, -(anything but NaN)) is +-pi ;
+ *  ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2;
+ *  ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;
+ *  ATAN2(+-(anything but INF and NaN), -INF) is +-pi;
+ *  ATAN2(+-INF,+INF ) is +-pi/4 ;
+ *  ATAN2(+-INF,-INF ) is +-3pi/4;
+ *  ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+double atan2(double y, double x) {
+  static volatile double tiny = 1.0e-300;
+  static const double
+      zero = 0.0,
+      pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */
+      pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */
+      pi = 3.1415926535897931160E+00;     /* 0x400921FB, 0x54442D18 */
+  static volatile double pi_lo =
+      1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
+
+  double z;
+  int32_t k, m, hx, hy, ix, iy;
+  uint32_t lx, ly;
+
+  EXTRACT_WORDS(hx, lx, x);
+  ix = hx & 0x7fffffff;
+  EXTRACT_WORDS(hy, ly, y);
+  iy = hy & 0x7fffffff;
+  if (((ix | ((lx | -static_cast<int32_t>(lx)) >> 31)) > 0x7ff00000) ||
+      ((iy | ((ly | -static_cast<int32_t>(ly)) >> 31)) > 0x7ff00000)) {
+    return x + y; /* x or y is NaN */
+  }
+  if (((hx - 0x3ff00000) | lx) == 0) return atan(y); /* x=1.0 */
+  m = ((hy >> 31) & 1) | ((hx >> 30) & 2);           /* 2*sign(x)+sign(y) */
+
+  /* when y = 0 */
+  if ((iy | ly) == 0) {
+    switch (m) {
+      case 0:
+      case 1:
+        return y; /* atan(+-0,+anything)=+-0 */
+      case 2:
+        return pi + tiny; /* atan(+0,-anything) = pi */
+      case 3:
+        return -pi - tiny; /* atan(-0,-anything) =-pi */
+    }
+  }
+  /* when x = 0 */
+  if ((ix | lx) == 0) return (hy < 0) ? -pi_o_2 - tiny : pi_o_2 + tiny;
+
+  /* when x is INF */
+  if (ix == 0x7ff00000) {
+    if (iy == 0x7ff00000) {
+      switch (m) {
+        case 0:
+          return pi_o_4 + tiny; /* atan(+INF,+INF) */
+        case 1:
+          return -pi_o_4 - tiny; /* atan(-INF,+INF) */
+        case 2:
+          return 3.0 * pi_o_4 + tiny; /*atan(+INF,-INF)*/
+        case 3:
+          return -3.0 * pi_o_4 - tiny; /*atan(-INF,-INF)*/
+      }
+    } else {
+      switch (m) {
+        case 0:
+          return zero; /* atan(+...,+INF) */
+        case 1:
+          return -zero; /* atan(-...,+INF) */
+        case 2:
+          return pi + tiny; /* atan(+...,-INF) */
+        case 3:
+          return -pi - tiny; /* atan(-...,-INF) */
+      }
+    }
+  }
+  /* when y is INF */
+  if (iy == 0x7ff00000) return (hy < 0) ? -pi_o_2 - tiny : pi_o_2 + tiny;
+
+  /* compute y/x */
+  k = (iy - ix) >> 20;
+  if (k > 60) { /* |y/x| >  2**60 */
+    z = pi_o_2 + 0.5 * pi_lo;
+    m &= 1;
+  } else if (hx < 0 && k < -60) {
+    z = 0.0; /* 0 > |y|/x > -2**-60 */
+  } else {
+    z = atan(fabs(y / x)); /* safe to do y/x */
+  }
+  switch (m) {
+    case 0:
+      return z; /* atan(+,+) */
+    case 1:
+      return -z; /* atan(-,+) */
+    case 2:
+      return pi - (z - pi_lo); /* atan(+,-) */
+    default:                   /* case 3 */
+      return (z - pi_lo) - pi; /* atan(-,-) */
+  }
+}
+
+/* cos(x)
+ * Return cosine function of x.
+ *
+ * kernel function:
+ *      __kernel_sin            ... sine function on [-pi/4,pi/4]
+ *      __kernel_cos            ... cosine function on [-pi/4,pi/4]
+ *      __ieee754_rem_pio2      ... argument reduction routine
+ *
+ * Method.
+ *      Let S,C and T denote the sin, cos and tan respectively on
+ *      [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ *      in [-pi/4 , +pi/4], and let n = k mod 4.
+ *      We have
+ *
+ *          n        sin(x)      cos(x)        tan(x)
+ *     ----------------------------------------------------------
+ *          0          S           C             T
+ *          1          C          -S            -1/T
+ *          2         -S          -C             T
+ *          3         -C           S            -1/T
+ *     ----------------------------------------------------------
+ *
+ * Special cases:
+ *      Let trig be any of sin, cos, or tan.
+ *      trig(+-INF)  is NaN, with signals;
+ *      trig(NaN)    is that NaN;
+ *
+ * Accuracy:
+ *      TRIG(x) returns trig(x) nearly rounded
+ */
+double cos(double x) {
+  double y[2], z = 0.0;
+  int32_t n, ix;
+
+  /* High word of x. */
+  GET_HIGH_WORD(ix, x);
+
+  /* |x| ~< pi/4 */
+  ix &= 0x7fffffff;
+  if (ix <= 0x3fe921fb) {
+    return __kernel_cos(x, z);
+  } else if (ix >= 0x7ff00000) {
+    /* cos(Inf or NaN) is NaN */
+    return x - x;
+  } else {
+    /* argument reduction needed */
+    n = __ieee754_rem_pio2(x, y);
+    switch (n & 3) {
+      case 0:
+        return __kernel_cos(y[0], y[1]);
+      case 1:
+        return -__kernel_sin(y[0], y[1], 1);
+      case 2:
+        return -__kernel_cos(y[0], y[1]);
+      default:
+        return __kernel_sin(y[0], y[1], 1);
+    }
+  }
+}
+
+/* exp(x)
+ * Returns the exponential of x.
+ *
+ * Method
+ *   1. Argument reduction:
+ *      Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
+ *      Given x, find r and integer k such that
+ *
+ *               x = k*ln2 + r,  |r| <= 0.5*ln2.
+ *
+ *      Here r will be represented as r = hi-lo for better
+ *      accuracy.
+ *
+ *   2. Approximation of exp(r) by a special rational function on
+ *      the interval [0,0.34658]:
+ *      Write
+ *          R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
+ *      We use a special Remes algorithm on [0,0.34658] to generate
+ *      a polynomial of degree 5 to approximate R. The maximum error
+ *      of this polynomial approximation is bounded by 2**-59. In
+ *      other words,
+ *          R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
+ *      (where z=r*r, and the values of P1 to P5 are listed below)
+ *      and
+ *          |                  5          |     -59
+ *          | 2.0+P1*z+...+P5*z   -  R(z) | <= 2
+ *          |                             |
+ *      The computation of exp(r) thus becomes
+ *                             2*r
+ *              exp(r) = 1 + -------
+ *                            R - r
+ *                                 r*R1(r)
+ *                     = 1 + r + ----------- (for better accuracy)
+ *                                2 - R1(r)
+ *      where
+ *                               2       4             10
+ *              R1(r) = r - (P1*r  + P2*r  + ... + P5*r   ).
+ *
+ *   3. Scale back to obtain exp(x):
+ *      From step 1, we have
+ *         exp(x) = 2^k * exp(r)
+ *
+ * Special cases:
+ *      exp(INF) is INF, exp(NaN) is NaN;
+ *      exp(-INF) is 0, and
+ *      for finite argument, only exp(0)=1 is exact.
+ *
+ * Accuracy:
+ *      according to an error analysis, the error is always less than
+ *      1 ulp (unit in the last place).
+ *
+ * Misc. info.
+ *      For IEEE double
+ *          if x >  7.09782712893383973096e+02 then exp(x) overflow
+ *          if x < -7.45133219101941108420e+02 then exp(x) underflow
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+double exp(double x) {
+  static const double
+      one = 1.0,
+      halF[2] = {0.5, -0.5},
+      o_threshold = 7.09782712893383973096e+02,  /* 0x40862E42, 0xFEFA39EF */
+      u_threshold = -7.45133219101941108420e+02, /* 0xc0874910, 0xD52D3051 */
+      ln2HI[2] = {6.93147180369123816490e-01,    /* 0x3fe62e42, 0xfee00000 */
+                  -6.93147180369123816490e-01},  /* 0xbfe62e42, 0xfee00000 */
+      ln2LO[2] = {1.90821492927058770002e-10,    /* 0x3dea39ef, 0x35793c76 */
+                  -1.90821492927058770002e-10},  /* 0xbdea39ef, 0x35793c76 */
+      invln2 = 1.44269504088896338700e+00,       /* 0x3ff71547, 0x652b82fe */
+      P1 = 1.66666666666666019037e-01,           /* 0x3FC55555, 0x5555553E */
+      P2 = -2.77777777770155933842e-03,          /* 0xBF66C16C, 0x16BEBD93 */
+      P3 = 6.61375632143793436117e-05,           /* 0x3F11566A, 0xAF25DE2C */
+      P4 = -1.65339022054652515390e-06,          /* 0xBEBBBD41, 0xC5D26BF1 */
+      P5 = 4.13813679705723846039e-08,           /* 0x3E663769, 0x72BEA4D0 */
+      E = 2.718281828459045;                     /* 0x4005bf0a, 0x8b145769 */
+
+  static volatile double
+      huge = 1.0e+300,
+      twom1000 = 9.33263618503218878990e-302, /* 2**-1000=0x01700000,0*/
+      two1023 = 8.988465674311579539e307;     /* 0x1p1023 */
+
+  double y, hi = 0.0, lo = 0.0, c, t, twopk;
+  int32_t k = 0, xsb;
+  uint32_t hx;
+
+  GET_HIGH_WORD(hx, x);
+  xsb = (hx >> 31) & 1; /* sign bit of x */
+  hx &= 0x7fffffff;     /* high word of |x| */
+
+  /* filter out non-finite argument */
+  if (hx >= 0x40862E42) { /* if |x|>=709.78... */
+    if (hx >= 0x7ff00000) {
+      uint32_t lx;
+      GET_LOW_WORD(lx, x);
+      if (((hx & 0xfffff) | lx) != 0)
+        return x + x; /* NaN */
+      else
+        return (xsb == 0) ? x : 0.0; /* exp(+-inf)={inf,0} */
+    }
+    if (x > o_threshold) return huge * huge;         /* overflow */
+    if (x < u_threshold) return twom1000 * twom1000; /* underflow */
+  }
+
+  /* argument reduction */
+  if (hx > 0x3fd62e42) {   /* if  |x| > 0.5 ln2 */
+    if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
+      /* TODO(rtoy): We special case exp(1) here to return the correct
+       * value of E, as the computation below would get the last bit
+       * wrong. We should probably fix the algorithm instead.
+       */
+      if (x == 1.0) return E;
+      hi = x - ln2HI[xsb];
+      lo = ln2LO[xsb];
+      k = 1 - xsb - xsb;
+    } else {
+      k = static_cast<int>(invln2 * x + halF[xsb]);
+      t = k;
+      hi = x - t * ln2HI[0]; /* t*ln2HI is exact here */
+      lo = t * ln2LO[0];
+    }
+    STRICT_ASSIGN(double, x, hi - lo);
+  } else if (hx < 0x3e300000) {         /* when |x|<2**-28 */
+    if (huge + x > one) return one + x; /* trigger inexact */
+  } else {
+    k = 0;
+  }
+
+  /* x is now in primary range */
+  t = x * x;
+  if (k >= -1021) {
+    INSERT_WORDS(twopk, 0x3ff00000 + (k << 20), 0);
+  } else {
+    INSERT_WORDS(twopk, 0x3ff00000 + ((k + 1000) << 20), 0);
+  }
+  c = x - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
+  if (k == 0) {
+    return one - ((x * c) / (c - 2.0) - x);
+  } else {
+    y = one - ((lo - (x * c) / (2.0 - c)) - hi);
+  }
+  if (k >= -1021) {
+    if (k == 1024) return y * 2.0 * two1023;
+    return y * twopk;
+  } else {
+    return y * twopk * twom1000;
+  }
+}
+
+/*
+ * Method :
+ *    1.Reduced x to positive by atanh(-x) = -atanh(x)
+ *    2.For x>=0.5
+ *              1              2x                          x
+ *  atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
+ *              2             1 - x                      1 - x
+ *
+ *   For x<0.5
+ *  atanh(x) = 0.5*log1p(2x+2x*x/(1-x))
+ *
+ * Special cases:
+ *  atanh(x) is NaN if |x| > 1 with signal;
+ *  atanh(NaN) is that NaN with no signal;
+ *  atanh(+-1) is +-INF with signal.
+ *
+ */
+double atanh(double x) {
+  static const double one = 1.0, huge = 1e300;
+  static const double zero = 0.0;
+
+  double t;
+  int32_t hx, ix;
+  uint32_t lx;
+  EXTRACT_WORDS(hx, lx, x);
+  ix = hx & 0x7fffffff;
+  if ((ix | ((lx | -static_cast<int32_t>(lx)) >> 31)) > 0x3ff00000) /* |x|>1 */
+    return (x - x) / (x - x);
+  if (ix == 0x3ff00000) return x / zero;
+  if (ix < 0x3e300000 && (huge + x) > zero) return x; /* x<2**-28 */
+  SET_HIGH_WORD(x, ix);
+  if (ix < 0x3fe00000) { /* x < 0.5 */
+    t = x + x;
+    t = 0.5 * log1p(t + t * x / (one - x));
+  } else {
+    t = 0.5 * log1p((x + x) / (one - x));
+  }
+  if (hx >= 0)
+    return t;
+  else
+    return -t;
+}
+
+/* log(x)
+ * Return the logrithm of x
+ *
+ * Method :
+ *   1. Argument Reduction: find k and f such that
+ *     x = 2^k * (1+f),
+ *     where  sqrt(2)/2 < 1+f < sqrt(2) .
+ *
+ *   2. Approximation of log(1+f).
+ *  Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+ *     = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ *         = 2s + s*R
+ *      We use a special Reme algorithm on [0,0.1716] to generate
+ *  a polynomial of degree 14 to approximate R The maximum error
+ *  of this polynomial approximation is bounded by 2**-58.45. In
+ *  other words,
+ *            2      4      6      8      10      12      14
+ *      R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s  +Lg6*s  +Lg7*s
+ *    (the values of Lg1 to Lg7 are listed in the program)
+ *  and
+ *      |      2          14          |     -58.45
+ *      | Lg1*s +...+Lg7*s    -  R(z) | <= 2
+ *      |                             |
+ *  Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ *  In order to guarantee error in log below 1ulp, we compute log
+ *  by
+ *    log(1+f) = f - s*(f - R)  (if f is not too large)
+ *    log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
+ *
+ *  3. Finally,  log(x) = k*ln2 + log(1+f).
+ *          = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ *     Here ln2 is split into two floating point number:
+ *      ln2_hi + ln2_lo,
+ *     where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ *  log(x) is NaN with signal if x < 0 (including -INF) ;
+ *  log(+INF) is +INF; log(0) is -INF with signal;
+ *  log(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ *  according to an error analysis, the error is always less than
+ *  1 ulp (unit in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+double log(double x) {
+  static const double                      /* -- */
+      ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
+      ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
+      two54 = 1.80143985094819840000e+16,  /* 43500000 00000000 */
+      Lg1 = 6.666666666666735130e-01,      /* 3FE55555 55555593 */
+      Lg2 = 3.999999999940941908e-01,      /* 3FD99999 9997FA04 */
+      Lg3 = 2.857142874366239149e-01,      /* 3FD24924 94229359 */
+      Lg4 = 2.222219843214978396e-01,      /* 3FCC71C5 1D8E78AF */
+      Lg5 = 1.818357216161805012e-01,      /* 3FC74664 96CB03DE */
+      Lg6 = 1.531383769920937332e-01,      /* 3FC39A09 D078C69F */
+      Lg7 = 1.479819860511658591e-01;      /* 3FC2F112 DF3E5244 */
+
+  static const double zero = 0.0;
+  static volatile double vzero = 0.0;
+
+  double hfsq, f, s, z, R, w, t1, t2, dk;
+  int32_t k, hx, i, j;
+  uint32_t lx;
+
+  EXTRACT_WORDS(hx, lx, x);
+
+  k = 0;
+  if (hx < 0x00100000) { /* x < 2**-1022  */
+    if (((hx & 0x7fffffff) | lx) == 0)
+      return -two54 / vzero;           /* log(+-0)=-inf */
+    if (hx < 0) return (x - x) / zero; /* log(-#) = NaN */
+    k -= 54;
+    x *= two54; /* subnormal number, scale up x */
+    GET_HIGH_WORD(hx, x);
+  }
+  if (hx >= 0x7ff00000) return x + x;
+  k += (hx >> 20) - 1023;
+  hx &= 0x000fffff;
+  i = (hx + 0x95f64) & 0x100000;
+  SET_HIGH_WORD(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */
+  k += (i >> 20);
+  f = x - 1.0;
+  if ((0x000fffff & (2 + hx)) < 3) { /* -2**-20 <= f < 2**-20 */
+    if (f == zero) {
+      if (k == 0) {
+        return zero;
+      } else {
+        dk = static_cast<double>(k);
+        return dk * ln2_hi + dk * ln2_lo;
+      }
+    }
+    R = f * f * (0.5 - 0.33333333333333333 * f);
+    if (k == 0) {
+      return f - R;
+    } else {
+      dk = static_cast<double>(k);
+      return dk * ln2_hi - ((R - dk * ln2_lo) - f);
+    }
+  }
+  s = f / (2.0 + f);
+  dk = static_cast<double>(k);
+  z = s * s;
+  i = hx - 0x6147a;
+  w = z * z;
+  j = 0x6b851 - hx;
+  t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
+  t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
+  i |= j;
+  R = t2 + t1;
+  if (i > 0) {
+    hfsq = 0.5 * f * f;
+    if (k == 0)
+      return f - (hfsq - s * (hfsq + R));
+    else
+      return dk * ln2_hi - ((hfsq - (s * (hfsq + R) + dk * ln2_lo)) - f);
+  } else {
+    if (k == 0)
+      return f - s * (f - R);
+    else
+      return dk * ln2_hi - ((s * (f - R) - dk * ln2_lo) - f);
+  }
+}
+
+/* double log1p(double x)
+ *
+ * Method :
+ *   1. Argument Reduction: find k and f such that
+ *      1+x = 2^k * (1+f),
+ *     where  sqrt(2)/2 < 1+f < sqrt(2) .
+ *
+ *      Note. If k=0, then f=x is exact. However, if k!=0, then f
+ *  may not be representable exactly. In that case, a correction
+ *  term is need. Let u=1+x rounded. Let c = (1+x)-u, then
+ *  log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u),
+ *  and add back the correction term c/u.
+ *  (Note: when x > 2**53, one can simply return log(x))
+ *
+ *   2. Approximation of log1p(f).
+ *  Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+ *     = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ *         = 2s + s*R
+ *      We use a special Reme algorithm on [0,0.1716] to generate
+ *  a polynomial of degree 14 to approximate R The maximum error
+ *  of this polynomial approximation is bounded by 2**-58.45. In
+ *  other words,
+ *            2      4      6      8      10      12      14
+ *      R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s  +Lp6*s  +Lp7*s
+ *    (the values of Lp1 to Lp7 are listed in the program)
+ *  and
+ *      |      2          14          |     -58.45
+ *      | Lp1*s +...+Lp7*s    -  R(z) | <= 2
+ *      |                             |
+ *  Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ *  In order to guarantee error in log below 1ulp, we compute log
+ *  by
+ *    log1p(f) = f - (hfsq - s*(hfsq+R)).
+ *
+ *  3. Finally, log1p(x) = k*ln2 + log1p(f).
+ *           = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ *     Here ln2 is split into two floating point number:
+ *      ln2_hi + ln2_lo,
+ *     where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ *  log1p(x) is NaN with signal if x < -1 (including -INF) ;
+ *  log1p(+INF) is +INF; log1p(-1) is -INF with signal;
+ *  log1p(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ *  according to an error analysis, the error is always less than
+ *  1 ulp (unit in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ *
+ * Note: Assuming log() return accurate answer, the following
+ *   algorithm can be used to compute log1p(x) to within a few ULP:
+ *
+ *    u = 1+x;
+ *    if(u==1.0) return x ; else
+ *         return log(u)*(x/(u-1.0));
+ *
+ *   See HP-15C Advanced Functions Handbook, p.193.
+ */
+double log1p(double x) {
+  static const double                      /* -- */
+      ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
+      ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
+      two54 = 1.80143985094819840000e+16,  /* 43500000 00000000 */
+      Lp1 = 6.666666666666735130e-01,      /* 3FE55555 55555593 */
+      Lp2 = 3.999999999940941908e-01,      /* 3FD99999 9997FA04 */
+      Lp3 = 2.857142874366239149e-01,      /* 3FD24924 94229359 */
+      Lp4 = 2.222219843214978396e-01,      /* 3FCC71C5 1D8E78AF */
+      Lp5 = 1.818357216161805012e-01,      /* 3FC74664 96CB03DE */
+      Lp6 = 1.531383769920937332e-01,      /* 3FC39A09 D078C69F */
+      Lp7 = 1.479819860511658591e-01;      /* 3FC2F112 DF3E5244 */
+
+  static const double zero = 0.0;
+  static volatile double vzero = 0.0;
+
+  double hfsq, f, c, s, z, R, u;
+  int32_t k, hx, hu, ax;
+
+  GET_HIGH_WORD(hx, x);
+  ax = hx & 0x7fffffff;
+
+  k = 1;
+  if (hx < 0x3FDA827A) {    /* 1+x < sqrt(2)+ */
+    if (ax >= 0x3ff00000) { /* x <= -1.0 */
+      if (x == -1.0)
+        return -two54 / vzero; /* log1p(-1)=+inf */
+      else
+        return (x - x) / (x - x); /* log1p(x<-1)=NaN */
+    }
+    if (ax < 0x3e200000) {    /* |x| < 2**-29 */
+      if (two54 + x > zero    /* raise inexact */
+          && ax < 0x3c900000) /* |x| < 2**-54 */
+        return x;
+      else
+        return x - x * x * 0.5;
+    }
+    if (hx > 0 || hx <= static_cast<int32_t>(0xbfd2bec4)) {
+      k = 0;
+      f = x;
+      hu = 1;
+    } /* sqrt(2)/2- <= 1+x < sqrt(2)+ */
+  }
+  if (hx >= 0x7ff00000) return x + x;
+  if (k != 0) {
+    if (hx < 0x43400000) {
+      STRICT_ASSIGN(double, u, 1.0 + x);
+      GET_HIGH_WORD(hu, u);
+      k = (hu >> 20) - 1023;
+      c = (k > 0) ? 1.0 - (u - x) : x - (u - 1.0); /* correction term */
+      c /= u;
+    } else {
+      u = x;
+      GET_HIGH_WORD(hu, u);
+      k = (hu >> 20) - 1023;
+      c = 0;
+    }
+    hu &= 0x000fffff;
+    /*
+     * The approximation to sqrt(2) used in thresholds is not
+     * critical.  However, the ones used above must give less
+     * strict bounds than the one here so that the k==0 case is
+     * never reached from here, since here we have committed to
+     * using the correction term but don't use it if k==0.
+     */
+    if (hu < 0x6a09e) {                  /* u ~< sqrt(2) */
+      SET_HIGH_WORD(u, hu | 0x3ff00000); /* normalize u */
+    } else {
+      k += 1;
+      SET_HIGH_WORD(u, hu | 0x3fe00000); /* normalize u/2 */
+      hu = (0x00100000 - hu) >> 2;
+    }
+    f = u - 1.0;
+  }
+  hfsq = 0.5 * f * f;
+  if (hu == 0) { /* |f| < 2**-20 */
+    if (f == zero) {
+      if (k == 0) {
+        return zero;
+      } else {
+        c += k * ln2_lo;
+        return k * ln2_hi + c;
+      }
+    }
+    R = hfsq * (1.0 - 0.66666666666666666 * f);
+    if (k == 0)
+      return f - R;
+    else
+      return k * ln2_hi - ((R - (k * ln2_lo + c)) - f);
+  }
+  s = f / (2.0 + f);
+  z = s * s;
+  R = z * (Lp1 +
+           z * (Lp2 + z * (Lp3 + z * (Lp4 + z * (Lp5 + z * (Lp6 + z * Lp7))))));
+  if (k == 0)
+    return f - (hfsq - s * (hfsq + R));
+  else
+    return k * ln2_hi - ((hfsq - (s * (hfsq + R) + (k * ln2_lo + c))) - f);
+}
+
+/*
+ * k_log1p(f):
+ * Return log(1+f) - f for 1+f in ~[sqrt(2)/2, sqrt(2)].
+ *
+ * The following describes the overall strategy for computing
+ * logarithms in base e.  The argument reduction and adding the final
+ * term of the polynomial are done by the caller for increased accuracy
+ * when different bases are used.
+ *
+ * Method :
+ *   1. Argument Reduction: find k and f such that
+ *         x = 2^k * (1+f),
+ *         where  sqrt(2)/2 < 1+f < sqrt(2) .
+ *
+ *   2. Approximation of log(1+f).
+ *      Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+ *            = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ *            = 2s + s*R
+ *      We use a special Reme algorithm on [0,0.1716] to generate
+ *      a polynomial of degree 14 to approximate R The maximum error
+ *      of this polynomial approximation is bounded by 2**-58.45. In
+ *      other words,
+ *          2      4      6      8      10      12      14
+ *          R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s  +Lg6*s  +Lg7*s
+ *      (the values of Lg1 to Lg7 are listed in the program)
+ *      and
+ *          |      2          14          |     -58.45
+ *          | Lg1*s +...+Lg7*s    -  R(z) | <= 2
+ *          |                             |
+ *      Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
+ *      In order to guarantee error in log below 1ulp, we compute log
+ *      by
+ *          log(1+f) = f - s*(f - R)            (if f is not too large)
+ *          log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy)
+ *
+ *   3. Finally,  log(x) = k*ln2 + log(1+f).
+ *          = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
+ *      Here ln2 is split into two floating point number:
+ *          ln2_hi + ln2_lo,
+ *      where n*ln2_hi is always exact for |n| < 2000.
+ *
+ * Special cases:
+ *      log(x) is NaN with signal if x < 0 (including -INF) ;
+ *      log(+INF) is +INF; log(0) is -INF with signal;
+ *      log(NaN) is that NaN with no signal.
+ *
+ * Accuracy:
+ *      according to an error analysis, the error is always less than
+ *      1 ulp (unit in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+
+static const double Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */
+    Lg2 = 3.999999999940941908e-01,                 /* 3FD99999 9997FA04 */
+    Lg3 = 2.857142874366239149e-01,                 /* 3FD24924 94229359 */
+    Lg4 = 2.222219843214978396e-01,                 /* 3FCC71C5 1D8E78AF */
+    Lg5 = 1.818357216161805012e-01,                 /* 3FC74664 96CB03DE */
+    Lg6 = 1.531383769920937332e-01,                 /* 3FC39A09 D078C69F */
+    Lg7 = 1.479819860511658591e-01;                 /* 3FC2F112 DF3E5244 */
+
+/*
+ * We always inline k_log1p(), since doing so produces a
+ * substantial performance improvement (~40% on amd64).
+ */
+static inline double k_log1p(double f) {
+  double hfsq, s, z, R, w, t1, t2;
+
+  s = f / (2.0 + f);
+  z = s * s;
+  w = z * z;
+  t1 = w * (Lg2 + w * (Lg4 + w * Lg6));
+  t2 = z * (Lg1 + w * (Lg3 + w * (Lg5 + w * Lg7)));
+  R = t2 + t1;
+  hfsq = 0.5 * f * f;
+  return s * (hfsq + R);
+}
+
+/*
+ * Return the base 2 logarithm of x.  See e_log.c and k_log.h for most
+ * comments.
+ *
+ * This reduces x to {k, 1+f} exactly as in e_log.c, then calls the kernel,
+ * then does the combining and scaling steps
+ *    log2(x) = (f - 0.5*f*f + k_log1p(f)) / ln2 + k
+ * in not-quite-routine extra precision.
+ */
+double log2(double x) {
+  static const double
+      two54 = 1.80143985094819840000e+16,   /* 0x43500000, 0x00000000 */
+      ivln2hi = 1.44269504072144627571e+00, /* 0x3ff71547, 0x65200000 */
+      ivln2lo = 1.67517131648865118353e-10; /* 0x3de705fc, 0x2eefa200 */
+
+  static const double zero = 0.0;
+  static volatile double vzero = 0.0;
+
+  double f, hfsq, hi, lo, r, val_hi, val_lo, w, y;
+  int32_t i, k, hx;
+  uint32_t lx;
+
+  EXTRACT_WORDS(hx, lx, x);
+
+  k = 0;
+  if (hx < 0x00100000) { /* x < 2**-1022  */
+    if (((hx & 0x7fffffff) | lx) == 0)
+      return -two54 / vzero;           /* log(+-0)=-inf */
+    if (hx < 0) return (x - x) / zero; /* log(-#) = NaN */
+    k -= 54;
+    x *= two54; /* subnormal number, scale up x */
+    GET_HIGH_WORD(hx, x);
+  }
+  if (hx >= 0x7ff00000) return x + x;
+  if (hx == 0x3ff00000 && lx == 0) return zero; /* log(1) = +0 */
+  k += (hx >> 20) - 1023;
+  hx &= 0x000fffff;
+  i = (hx + 0x95f64) & 0x100000;
+  SET_HIGH_WORD(x, hx | (i ^ 0x3ff00000)); /* normalize x or x/2 */
+  k += (i >> 20);
+  y = static_cast<double>(k);
+  f = x - 1.0;
+  hfsq = 0.5 * f * f;
+  r = k_log1p(f);
+
+  /*
+   * f-hfsq must (for args near 1) be evaluated in extra precision
+   * to avoid a large cancellation when x is near sqrt(2) or 1/sqrt(2).
+   * This is fairly efficient since f-hfsq only depends on f, so can
+   * be evaluated in parallel with R.  Not combining hfsq with R also
+   * keeps R small (though not as small as a true `lo' term would be),
+   * so that extra precision is not needed for terms involving R.
+   *
+   * Compiler bugs involving extra precision used to break Dekker's
+   * theorem for spitting f-hfsq as hi+lo, unless double_t was used
+   * or the multi-precision calculations were avoided when double_t
+   * has extra precision.  These problems are now automatically
+   * avoided as a side effect of the optimization of combining the
+   * Dekker splitting step with the clear-low-bits step.
+   *
+   * y must (for args near sqrt(2) and 1/sqrt(2)) be added in extra
+   * precision to avoid a very large cancellation when x is very near
+   * these values.  Unlike the above cancellations, this problem is
+   * specific to base 2.  It is strange that adding +-1 is so much
+   * harder than adding +-ln2 or +-log10_2.
+   *
+   * This uses Dekker's theorem to normalize y+val_hi, so the
+   * compiler bugs are back in some configurations, sigh.  And I
+   * don't want to used double_t to avoid them, since that gives a
+   * pessimization and the support for avoiding the pessimization
+   * is not yet available.
+   *
+   * The multi-precision calculations for the multiplications are
+   * routine.
+   */
+  hi = f - hfsq;
+  SET_LOW_WORD(hi, 0);
+  lo = (f - hi) - hfsq + r;
+  val_hi = hi * ivln2hi;
+  val_lo = (lo + hi) * ivln2lo + lo * ivln2hi;
+
+  /* spadd(val_hi, val_lo, y), except for not using double_t: */
+  w = y + val_hi;
+  val_lo += (y - w) + val_hi;
+  val_hi = w;
+
+  return val_lo + val_hi;
+}
+
+/*
+ * Return the base 10 logarithm of x
+ *
+ * Method :
+ *      Let log10_2hi = leading 40 bits of log10(2) and
+ *          log10_2lo = log10(2) - log10_2hi,
+ *          ivln10   = 1/log(10) rounded.
+ *      Then
+ *              n = ilogb(x),
+ *              if(n<0)  n = n+1;
+ *              x = scalbn(x,-n);
+ *              log10(x) := n*log10_2hi + (n*log10_2lo + ivln10*log(x))
+ *
+ *  Note 1:
+ *     To guarantee log10(10**n)=n, where 10**n is normal, the rounding
+ *     mode must set to Round-to-Nearest.
+ *  Note 2:
+ *      [1/log(10)] rounded to 53 bits has error .198 ulps;
+ *      log10 is monotonic at all binary break points.
+ *
+ *  Special cases:
+ *      log10(x) is NaN if x < 0;
+ *      log10(+INF) is +INF; log10(0) is -INF;
+ *      log10(NaN) is that NaN;
+ *      log10(10**N) = N  for N=0,1,...,22.
+ */
+double log10(double x) {
+  static const double
+      two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+      ivln10 = 4.34294481903251816668e-01,
+      log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
+      log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */
+
+  static const double zero = 0.0;
+  static volatile double vzero = 0.0;
+
+  double y;
+  int32_t i, k, hx;
+  uint32_t lx;
+
+  EXTRACT_WORDS(hx, lx, x);
+
+  k = 0;
+  if (hx < 0x00100000) { /* x < 2**-1022  */
+    if (((hx & 0x7fffffff) | lx) == 0)
+      return -two54 / vzero;           /* log(+-0)=-inf */
+    if (hx < 0) return (x - x) / zero; /* log(-#) = NaN */
+    k -= 54;
+    x *= two54; /* subnormal number, scale up x */
+    GET_HIGH_WORD(hx, x);
+    GET_LOW_WORD(lx, x);
+  }
+  if (hx >= 0x7ff00000) return x + x;
+  if (hx == 0x3ff00000 && lx == 0) return zero; /* log(1) = +0 */
+  k += (hx >> 20) - 1023;
+
+  i = (k & 0x80000000) >> 31;
+  hx = (hx & 0x000fffff) | ((0x3ff - i) << 20);
+  y = k + i;
+  SET_HIGH_WORD(x, hx);
+  SET_LOW_WORD(x, lx);
+
+  double z = y * log10_2lo + ivln10 * log(x);
+  return z + y * log10_2hi;
+}
+
+/* expm1(x)
+ * Returns exp(x)-1, the exponential of x minus 1.
+ *
+ * Method
+ *   1. Argument reduction:
+ *  Given x, find r and integer k such that
+ *
+ *               x = k*ln2 + r,  |r| <= 0.5*ln2 ~ 0.34658
+ *
+ *      Here a correction term c will be computed to compensate
+ *  the error in r when rounded to a floating-point number.
+ *
+ *   2. Approximating expm1(r) by a special rational function on
+ *  the interval [0,0.34658]:
+ *  Since
+ *      r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ...
+ *  we define R1(r*r) by
+ *      r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r)
+ *  That is,
+ *      R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r)
+ *         = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r))
+ *         = 1 - r^2/60 + r^4/2520 - r^6/100800 + ...
+ *      We use a special Reme algorithm on [0,0.347] to generate
+ *   a polynomial of degree 5 in r*r to approximate R1. The
+ *  maximum error of this polynomial approximation is bounded
+ *  by 2**-61. In other words,
+ *      R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5
+ *  where   Q1  =  -1.6666666666666567384E-2,
+ *     Q2  =   3.9682539681370365873E-4,
+ *     Q3  =  -9.9206344733435987357E-6,
+ *     Q4  =   2.5051361420808517002E-7,
+ *     Q5  =  -6.2843505682382617102E-9;
+ *    z   =  r*r,
+ *  with error bounded by
+ *      |                  5           |     -61
+ *      | 1.0+Q1*z+...+Q5*z   -  R1(z) | <= 2
+ *      |                              |
+ *
+ *  expm1(r) = exp(r)-1 is then computed by the following
+ *   specific way which minimize the accumulation rounding error:
+ *             2     3
+ *            r     r    [ 3 - (R1 + R1*r/2)  ]
+ *        expm1(r) = r + --- + --- * [--------------------]
+ *                  2     2    [ 6 - r*(3 - R1*r/2) ]
+ *
+ *  To compensate the error in the argument reduction, we use
+ *    expm1(r+c) = expm1(r) + c + expm1(r)*c
+ *         ~ expm1(r) + c + r*c
+ *  Thus c+r*c will be added in as the correction terms for
+ *  expm1(r+c). Now rearrange the term to avoid optimization
+ *   screw up:
+ *            (      2                                    2 )
+ *            ({  ( r    [ R1 -  (3 - R1*r/2) ]  )  }    r  )
+ *   expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- )
+ *                  ({  ( 2    [ 6 - r*(3 - R1*r/2) ]  )  }    2  )
+ *                      (                                             )
+ *
+ *       = r - E
+ *   3. Scale back to obtain expm1(x):
+ *  From step 1, we have
+ *     expm1(x) = either 2^k*[expm1(r)+1] - 1
+ *        = or     2^k*[expm1(r) + (1-2^-k)]
+ *   4. Implementation notes:
+ *  (A). To save one multiplication, we scale the coefficient Qi
+ *       to Qi*2^i, and replace z by (x^2)/2.
+ *  (B). To achieve maximum accuracy, we compute expm1(x) by
+ *    (i)   if x < -56*ln2, return -1.0, (raise inexact if x!=inf)
+ *    (ii)  if k=0, return r-E
+ *    (iii) if k=-1, return 0.5*(r-E)-0.5
+ *        (iv)  if k=1 if r < -0.25, return 2*((r+0.5)- E)
+ *                  else       return  1.0+2.0*(r-E);
+ *    (v)   if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1)
+ *    (vi)  if k <= 20, return 2^k((1-2^-k)-(E-r)), else
+ *    (vii) return 2^k(1-((E+2^-k)-r))
+ *
+ * Special cases:
+ *  expm1(INF) is INF, expm1(NaN) is NaN;
+ *  expm1(-INF) is -1, and
+ *  for finite argument, only expm1(0)=0 is exact.
+ *
+ * Accuracy:
+ *  according to an error analysis, the error is always less than
+ *  1 ulp (unit in the last place).
+ *
+ * Misc. info.
+ *  For IEEE double
+ *      if x >  7.09782712893383973096e+02 then expm1(x) overflow
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following
+ * constants. The decimal values may be used, provided that the
+ * compiler will convert from decimal to binary accurately enough
+ * to produce the hexadecimal values shown.
+ */
+double expm1(double x) {
+  static const double
+      one = 1.0,
+      tiny = 1.0e-300,
+      o_threshold = 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */
+      ln2_hi = 6.93147180369123816490e-01,      /* 0x3fe62e42, 0xfee00000 */
+      ln2_lo = 1.90821492927058770002e-10,      /* 0x3dea39ef, 0x35793c76 */
+      invln2 = 1.44269504088896338700e+00,      /* 0x3ff71547, 0x652b82fe */
+      /* Scaled Q's: Qn_here = 2**n * Qn_above, for R(2*z) where z = hxs =
+         x*x/2: */
+      Q1 = -3.33333333333331316428e-02, /* BFA11111 111110F4 */
+      Q2 = 1.58730158725481460165e-03,  /* 3F5A01A0 19FE5585 */
+      Q3 = -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */
+      Q4 = 4.00821782732936239552e-06,  /* 3ED0CFCA 86E65239 */
+      Q5 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */
+
+  static volatile double huge = 1.0e+300;
+
+  double y, hi, lo, c, t, e, hxs, hfx, r1, twopk;
+  int32_t k, xsb;
+  uint32_t hx;
+
+  GET_HIGH_WORD(hx, x);
+  xsb = hx & 0x80000000; /* sign bit of x */
+  hx &= 0x7fffffff;      /* high word of |x| */
+
+  /* filter out huge and non-finite argument */
+  if (hx >= 0x4043687A) {   /* if |x|>=56*ln2 */
+    if (hx >= 0x40862E42) { /* if |x|>=709.78... */
+      if (hx >= 0x7ff00000) {
+        uint32_t low;
+        GET_LOW_WORD(low, x);
+        if (((hx & 0xfffff) | low) != 0)
+          return x + x; /* NaN */
+        else
+          return (xsb == 0) ? x : -1.0; /* exp(+-inf)={inf,-1} */
+      }
+      if (x > o_threshold) return huge * huge; /* overflow */
+    }
+    if (xsb != 0) {        /* x < -56*ln2, return -1.0 with inexact */
+      if (x + tiny < 0.0)  /* raise inexact */
+        return tiny - one; /* return -1 */
+    }
+  }
+
+  /* argument reduction */
+  if (hx > 0x3fd62e42) {   /* if  |x| > 0.5 ln2 */
+    if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
+      if (xsb == 0) {
+        hi = x - ln2_hi;
+        lo = ln2_lo;
+        k = 1;
+      } else {
+        hi = x + ln2_hi;
+        lo = -ln2_lo;
+        k = -1;
+      }
+    } else {
+      k = invln2 * x + ((xsb == 0) ? 0.5 : -0.5);
+      t = k;
+      hi = x - t * ln2_hi; /* t*ln2_hi is exact here */
+      lo = t * ln2_lo;
+    }
+    STRICT_ASSIGN(double, x, hi - lo);
+    c = (hi - x) - lo;
+  } else if (hx < 0x3c900000) { /* when |x|<2**-54, return x */
+    t = huge + x;               /* return x with inexact flags when x!=0 */
+    return x - (t - (huge + x));
+  } else {
+    k = 0;
+  }
+
+  /* x is now in primary range */
+  hfx = 0.5 * x;
+  hxs = x * hfx;
+  r1 = one + hxs * (Q1 + hxs * (Q2 + hxs * (Q3 + hxs * (Q4 + hxs * Q5))));
+  t = 3.0 - r1 * hfx;
+  e = hxs * ((r1 - t) / (6.0 - x * t));
+  if (k == 0) {
+    return x - (x * e - hxs); /* c is 0 */
+  } else {
+    INSERT_WORDS(twopk, 0x3ff00000 + (k << 20), 0); /* 2^k */
+    e = (x * (e - c) - c);
+    e -= hxs;
+    if (k == -1) return 0.5 * (x - e) - 0.5;
+    if (k == 1) {
+      if (x < -0.25)
+        return -2.0 * (e - (x + 0.5));
+      else
+        return one + 2.0 * (x - e);
+    }
+    if (k <= -2 || k > 56) { /* suffice to return exp(x)-1 */
+      y = one - (e - x);
+      // TODO(mvstanton): is this replacement for the hex float
+      // sufficient?
+      // if (k == 1024) y = y*2.0*0x1p1023;
+      if (k == 1024)
+        y = y * 2.0 * 8.98846567431158e+307;
+      else
+        y = y * twopk;
+      return y - one;
+    }
+    t = one;
+    if (k < 20) {
+      SET_HIGH_WORD(t, 0x3ff00000 - (0x200000 >> k)); /* t=1-2^-k */
+      y = t - (e - x);
+      y = y * twopk;
+    } else {
+      SET_HIGH_WORD(t, ((0x3ff - k) << 20)); /* 2^-k */
+      y = x - (e + t);
+      y += one;
+      y = y * twopk;
+    }
+  }
+  return y;
+}
+
+double cbrt(double x) {
+  static const uint32_t
+      B1 = 715094163, /* B1 = (1023-1023/3-0.03306235651)*2**20 */
+      B2 = 696219795; /* B2 = (1023-1023/3-54/3-0.03306235651)*2**20 */
+
+  /* |1/cbrt(x) - p(x)| < 2**-23.5 (~[-7.93e-8, 7.929e-8]). */
+  static const double P0 = 1.87595182427177009643, /* 0x3ffe03e6, 0x0f61e692 */
+      P1 = -1.88497979543377169875,                /* 0xbffe28e0, 0x92f02420 */
+      P2 = 1.621429720105354466140,                /* 0x3ff9f160, 0x4a49d6c2 */
+      P3 = -0.758397934778766047437,               /* 0xbfe844cb, 0xbee751d9 */
+      P4 = 0.145996192886612446982;                /* 0x3fc2b000, 0xd4e4edd7 */
+
+  int32_t hx;
+  union {
+    double value;
+    uint64_t bits;
+  } u;
+  double r, s, t = 0.0, w;
+  uint32_t sign;
+  uint32_t high, low;
+
+  EXTRACT_WORDS(hx, low, x);
+  sign = hx & 0x80000000; /* sign= sign(x) */
+  hx ^= sign;
+  if (hx >= 0x7ff00000) return (x + x); /* cbrt(NaN,INF) is itself */
+
+  /*
+   * Rough cbrt to 5 bits:
+   *    cbrt(2**e*(1+m) ~= 2**(e/3)*(1+(e%3+m)/3)
+   * where e is integral and >= 0, m is real and in [0, 1), and "/" and
+   * "%" are integer division and modulus with rounding towards minus
+   * infinity.  The RHS is always >= the LHS and has a maximum relative
+   * error of about 1 in 16.  Adding a bias of -0.03306235651 to the
+   * (e%3+m)/3 term reduces the error to about 1 in 32. With the IEEE
+   * floating point representation, for finite positive normal values,
+   * ordinary integer divison of the value in bits magically gives
+   * almost exactly the RHS of the above provided we first subtract the
+   * exponent bias (1023 for doubles) and later add it back.  We do the
+   * subtraction virtually to keep e >= 0 so that ordinary integer
+   * division rounds towards minus infinity; this is also efficient.
+   */
+  if (hx < 0x00100000) {             /* zero or subnormal? */
+    if ((hx | low) == 0) return (x); /* cbrt(0) is itself */
+    SET_HIGH_WORD(t, 0x43500000);    /* set t= 2**54 */
+    t *= x;
+    GET_HIGH_WORD(high, t);
+    INSERT_WORDS(t, sign | ((high & 0x7fffffff) / 3 + B2), 0);
+  } else {
+    INSERT_WORDS(t, sign | (hx / 3 + B1), 0);
+  }
+
+  /*
+   * New cbrt to 23 bits:
+   *    cbrt(x) = t*cbrt(x/t**3) ~= t*P(t**3/x)
+   * where P(r) is a polynomial of degree 4 that approximates 1/cbrt(r)
+   * to within 2**-23.5 when |r - 1| < 1/10.  The rough approximation
+   * has produced t such than |t/cbrt(x) - 1| ~< 1/32, and cubing this
+   * gives us bounds for r = t**3/x.
+   *
+   * Try to optimize for parallel evaluation as in k_tanf.c.
+   */
+  r = (t * t) * (t / x);
+  t = t * ((P0 + r * (P1 + r * P2)) + ((r * r) * r) * (P3 + r * P4));
+
+  /*
+   * Round t away from zero to 23 bits (sloppily except for ensuring that
+   * the result is larger in magnitude than cbrt(x) but not much more than
+   * 2 23-bit ulps larger).  With rounding towards zero, the error bound
+   * would be ~5/6 instead of ~4/6.  With a maximum error of 2 23-bit ulps
+   * in the rounded t, the infinite-precision error in the Newton
+   * approximation barely affects third digit in the final error
+   * 0.667; the error in the rounded t can be up to about 3 23-bit ulps
+   * before the final error is larger than 0.667 ulps.
+   */
+  u.value = t;
+  u.bits = (u.bits + 0x80000000) & 0xffffffffc0000000ULL;
+  t = u.value;
+
+  /* one step Newton iteration to 53 bits with error < 0.667 ulps */
+  s = t * t;             /* t*t is exact */
+  r = x / s;             /* error <= 0.5 ulps; |r| < |t| */
+  w = t + t;             /* t+t is exact */
+  r = (r - t) / (w + r); /* r-t is exact; w+r ~= 3*t */
+  t = t + t * r;         /* error <= 0.5 + 0.5/3 + epsilon */
+
+  return (t);
+}
+
+/* sin(x)
+ * Return sine function of x.
+ *
+ * kernel function:
+ *      __kernel_sin            ... sine function on [-pi/4,pi/4]
+ *      __kernel_cos            ... cose function on [-pi/4,pi/4]
+ *      __ieee754_rem_pio2      ... argument reduction routine
+ *
+ * Method.
+ *      Let S,C and T denote the sin, cos and tan respectively on
+ *      [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ *      in [-pi/4 , +pi/4], and let n = k mod 4.
+ *      We have
+ *
+ *          n        sin(x)      cos(x)        tan(x)
+ *     ----------------------------------------------------------
+ *          0          S           C             T
+ *          1          C          -S            -1/T
+ *          2         -S          -C             T
+ *          3         -C           S            -1/T
+ *     ----------------------------------------------------------
+ *
+ * Special cases:
+ *      Let trig be any of sin, cos, or tan.
+ *      trig(+-INF)  is NaN, with signals;
+ *      trig(NaN)    is that NaN;
+ *
+ * Accuracy:
+ *      TRIG(x) returns trig(x) nearly rounded
+ */
+double sin(double x) {
+  double y[2], z = 0.0;
+  int32_t n, ix;
+
+  /* High word of x. */
+  GET_HIGH_WORD(ix, x);
+
+  /* |x| ~< pi/4 */
+  ix &= 0x7fffffff;
+  if (ix <= 0x3fe921fb) {
+    return __kernel_sin(x, z, 0);
+  } else if (ix >= 0x7ff00000) {
+    /* sin(Inf or NaN) is NaN */
+    return x - x;
+  } else {
+    /* argument reduction needed */
+    n = __ieee754_rem_pio2(x, y);
+    switch (n & 3) {
+      case 0:
+        return __kernel_sin(y[0], y[1], 1);
+      case 1:
+        return __kernel_cos(y[0], y[1]);
+      case 2:
+        return -__kernel_sin(y[0], y[1], 1);
+      default:
+        return -__kernel_cos(y[0], y[1]);
+    }
+  }
+}
+
+/* tan(x)
+ * Return tangent function of x.
+ *
+ * kernel function:
+ *      __kernel_tan            ... tangent function on [-pi/4,pi/4]
+ *      __ieee754_rem_pio2      ... argument reduction routine
+ *
+ * Method.
+ *      Let S,C and T denote the sin, cos and tan respectively on
+ *      [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2
+ *      in [-pi/4 , +pi/4], and let n = k mod 4.
+ *      We have
+ *
+ *          n        sin(x)      cos(x)        tan(x)
+ *     ----------------------------------------------------------
+ *          0          S           C             T
+ *          1          C          -S            -1/T
+ *          2         -S          -C             T
+ *          3         -C           S            -1/T
+ *     ----------------------------------------------------------
+ *
+ * Special cases:
+ *      Let trig be any of sin, cos, or tan.
+ *      trig(+-INF)  is NaN, with signals;
+ *      trig(NaN)    is that NaN;
+ *
+ * Accuracy:
+ *      TRIG(x) returns trig(x) nearly rounded
+ */
+double tan(double x) {
+  double y[2], z = 0.0;
+  int32_t n, ix;
+
+  /* High word of x. */
+  GET_HIGH_WORD(ix, x);
+
+  /* |x| ~< pi/4 */
+  ix &= 0x7fffffff;
+  if (ix <= 0x3fe921fb) {
+    return __kernel_tan(x, z, 1);
+  } else if (ix >= 0x7ff00000) {
+    /* tan(Inf or NaN) is NaN */
+    return x - x; /* NaN */
+  } else {
+    /* argument reduction needed */
+    n = __ieee754_rem_pio2(x, y);
+    /* 1 -> n even, -1 -> n odd */
+    return __kernel_tan(y[0], y[1], 1 - ((n & 1) << 1));
+  }
+}
+
+}  // namespace ieee754
+}  // namespace base
+}  // namespace v8
diff --git a/src/base/ieee754.h b/src/base/ieee754.h
new file mode 100644
index 0000000..cf33580
--- /dev/null
+++ b/src/base/ieee754.h
@@ -0,0 +1,57 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_BASE_IEEE754_H_
+#define V8_BASE_IEEE754_H_
+
+namespace v8 {
+namespace base {
+namespace ieee754 {
+
+// Returns the principal value of the arc tangent of |x|; that is the value
+// whose tangent is |x|.
+double atan(double x);
+
+// Returns the principal value of the arc tangent of |y/x|, using the signs of
+// the two arguments to determine the quadrant of the result.
+double atan2(double y, double x);
+
+// Returns the cosine of |x|, where |x| is given in radians.
+double cos(double x);
+
+// Returns the base-e exponential of |x|.
+double exp(double x);
+
+double atanh(double x);
+
+// Returns the natural logarithm of |x|.
+double log(double x);
+
+// Returns a value equivalent to |log(1+x)|, but computed in a way that is
+// accurate even if the value of |x| is near zero.
+double log1p(double x);
+
+// Returns the base 2 logarithm of |x|.
+double log2(double x);
+
+// Returns the base 10 logarithm of |x|.
+double log10(double x);
+
+// Returns the cube root of |x|.
+double cbrt(double x);
+
+// Returns exp(x)-1, the exponential of |x| minus 1.
+double expm1(double x);
+
+// Returns the sine of |x|, where |x| is given in radians.
+double sin(double x);
+
+// Returns the tangent of |x|, where |x| is given in radians.
+double tan(double x);
+
+}  // namespace ieee754
+}  // namespace base
+}  // namespace v8
+
+#endif  // V8_BASE_IEEE754_H_
diff --git a/src/base/logging.h b/src/base/logging.h
index 15322f6..45bc3c4 100644
--- a/src/base/logging.h
+++ b/src/base/logging.h
@@ -10,9 +10,10 @@
 #include <string>
 
 #include "src/base/build_config.h"
+#include "src/base/compiler-specific.h"
 
-extern "C" V8_NORETURN void V8_Fatal(const char* file, int line,
-                                     const char* format, ...);
+extern "C" PRINTF_FORMAT(3, 4) V8_NORETURN
+    void V8_Fatal(const char* file, int line, const char* format, ...);
 
 extern "C" void V8_RuntimeError(const char* file, int line,
                                 const char* message);
diff --git a/src/base/macros.h b/src/base/macros.h
index 3f09b2b..382c30b 100644
--- a/src/base/macros.h
+++ b/src/base/macros.h
@@ -5,13 +5,8 @@
 #ifndef V8_BASE_MACROS_H_
 #define V8_BASE_MACROS_H_
 
-#include <stddef.h>
-#include <stdint.h>
-
-#include <cstring>
-
-#include "src/base/build_config.h"
 #include "src/base/compiler-specific.h"
+#include "src/base/format-macros.h"
 #include "src/base/logging.h"
 
 
@@ -274,23 +269,27 @@
 #define V8PRIdPTR V8_PTR_PREFIX "d"
 #define V8PRIuPTR V8_PTR_PREFIX "u"
 
+// ptrdiff_t is 't' according to the standard, but MSVC uses 'I'.
+#if V8_CC_MSVC
+#define V8PRIxPTRDIFF "Ix"
+#define V8PRIdPTRDIFF "Id"
+#define V8PRIuPTRDIFF "Iu"
+#else
+#define V8PRIxPTRDIFF "tx"
+#define V8PRIdPTRDIFF "td"
+#define V8PRIuPTRDIFF "tu"
+#endif
+
 // Fix for Mac OS X defining uintptr_t as "unsigned long":
 #if V8_OS_MACOSX
 #undef V8PRIxPTR
 #define V8PRIxPTR "lx"
+#undef V8PRIdPTR
+#define V8PRIdPTR "ld"
 #undef V8PRIuPTR
 #define V8PRIuPTR "lxu"
 #endif
 
-// GCC on S390 31-bit expands 'size_t' to 'long unsigned int'
-// instead of 'int', resulting in compilation errors with %d.
-// The printf format specifier needs to be %zd instead.
-#if V8_HOST_ARCH_S390 && !V8_HOST_ARCH_64_BIT
-#define V8_SIZET_PREFIX "z"
-#else
-#define V8_SIZET_PREFIX ""
-#endif
-
 // The following macro works on both 32 and 64-bit platforms.
 // Usage: instead of writing 0x1234567890123456
 //      write V8_2PART_UINT64_C(0x12345678,90123456);
diff --git a/src/base/platform/condition-variable.cc b/src/base/platform/condition-variable.cc
index fcd6cf7..19c33f8 100644
--- a/src/base/platform/condition-variable.cc
+++ b/src/base/platform/condition-variable.cc
@@ -36,6 +36,19 @@
 
 
 ConditionVariable::~ConditionVariable() {
+#if defined(V8_OS_MACOSX)
+  // This hack is necessary to avoid a fatal pthreads subsystem bug in the
+  // Darwin kernel. http://crbug.com/517681.
+  {
+    Mutex lock;
+    LockGuard<Mutex> l(&lock);
+    struct timespec ts;
+    ts.tv_sec = 0;
+    ts.tv_nsec = 1;
+    pthread_cond_timedwait_relative_np(&native_handle_, &lock.native_handle(),
+                                       &ts);
+  }
+#endif
   int result = pthread_cond_destroy(&native_handle_);
   DCHECK_EQ(0, result);
   USE(result);
diff --git a/src/base/platform/platform-macos.cc b/src/base/platform/platform-macos.cc
index 419281f..ecd440c 100644
--- a/src/base/platform/platform-macos.cc
+++ b/src/base/platform/platform-macos.cc
@@ -86,10 +86,10 @@
     char* code_ptr = getsectdatafromheader(header, SEG_TEXT, SECT_TEXT, &size);
 #endif
     if (code_ptr == NULL) continue;
-    const uintptr_t slide = _dyld_get_image_vmaddr_slide(i);
+    const intptr_t slide = _dyld_get_image_vmaddr_slide(i);
     const uintptr_t start = reinterpret_cast<uintptr_t>(code_ptr) + slide;
-    result.push_back(
-        SharedLibraryAddress(_dyld_get_image_name(i), start, start + size));
+    result.push_back(SharedLibraryAddress(_dyld_get_image_name(i), start,
+                                          start + size, slide));
   }
   return result;
 }
diff --git a/src/base/platform/platform.h b/src/base/platform/platform.h
index 5b2dbc9..9464fb1 100644
--- a/src/base/platform/platform.h
+++ b/src/base/platform/platform.h
@@ -26,6 +26,7 @@
 #include <vector>
 
 #include "src/base/build_config.h"
+#include "src/base/compiler-specific.h"
 #include "src/base/platform/mutex.h"
 #include "src/base/platform/semaphore.h"
 
@@ -154,18 +155,19 @@
   // Print output to console. This is mostly used for debugging output.
   // On platforms that has standard terminal output, the output
   // should go to stdout.
-  static void Print(const char* format, ...);
-  static void VPrint(const char* format, va_list args);
+  static PRINTF_FORMAT(1, 2) void Print(const char* format, ...);
+  static PRINTF_FORMAT(1, 0) void VPrint(const char* format, va_list args);
 
   // Print output to a file. This is mostly used for debugging output.
-  static void FPrint(FILE* out, const char* format, ...);
-  static void VFPrint(FILE* out, const char* format, va_list args);
+  static PRINTF_FORMAT(2, 3) void FPrint(FILE* out, const char* format, ...);
+  static PRINTF_FORMAT(2, 0) void VFPrint(FILE* out, const char* format,
+                                          va_list args);
 
   // Print error output to console. This is mostly used for error message
   // output. On platforms that has standard terminal output, the output
   // should go to stderr.
-  static void PrintError(const char* format, ...);
-  static void VPrintError(const char* format, va_list args);
+  static PRINTF_FORMAT(1, 2) void PrintError(const char* format, ...);
+  static PRINTF_FORMAT(1, 0) void VPrintError(const char* format, va_list args);
 
   // Allocate/Free memory used by JS heap. Pages are readable/writable, but
   // they are not guaranteed to be executable unless 'executable' is true.
@@ -222,11 +224,10 @@
 
   // Safe formatting print. Ensures that str is always null-terminated.
   // Returns the number of chars written, or -1 if output was truncated.
-  static int SNPrintF(char* str, int length, const char* format, ...);
-  static int VSNPrintF(char* str,
-                       int length,
-                       const char* format,
-                       va_list args);
+  static PRINTF_FORMAT(3, 4) int SNPrintF(char* str, int length,
+                                          const char* format, ...);
+  static PRINTF_FORMAT(3, 0) int VSNPrintF(char* str, int length,
+                                           const char* format, va_list args);
 
   static char* StrChr(char* str, int c);
   static void StrNCpy(char* dest, int length, const char* src, size_t n);
@@ -234,13 +235,20 @@
   // Support for the profiler.  Can do nothing, in which case ticks
   // occuring in shared libraries will not be properly accounted for.
   struct SharedLibraryAddress {
-    SharedLibraryAddress(
-        const std::string& library_path, uintptr_t start, uintptr_t end)
-        : library_path(library_path), start(start), end(end) {}
+    SharedLibraryAddress(const std::string& library_path, uintptr_t start,
+                         uintptr_t end)
+        : library_path(library_path), start(start), end(end), aslr_slide(0) {}
+    SharedLibraryAddress(const std::string& library_path, uintptr_t start,
+                         uintptr_t end, intptr_t aslr_slide)
+        : library_path(library_path),
+          start(start),
+          end(end),
+          aslr_slide(aslr_slide) {}
 
     std::string library_path;
     uintptr_t start;
     uintptr_t end;
+    intptr_t aslr_slide;
   };
 
   static std::vector<SharedLibraryAddress> GetSharedLibraryAddresses();
diff --git a/src/base/platform/semaphore.cc b/src/base/platform/semaphore.cc
index 284474e..7bf5986 100644
--- a/src/base/platform/semaphore.cc
+++ b/src/base/platform/semaphore.cc
@@ -34,7 +34,6 @@
   USE(result);
 }
 
-
 void Semaphore::Signal() {
   kern_return_t result = semaphore_signal(native_handle_);
   DCHECK_EQ(KERN_SUCCESS, result);
@@ -74,11 +73,20 @@
 #elif V8_OS_POSIX
 
 Semaphore::Semaphore(int count) {
-  DCHECK(count >= 0);
-#if V8_LIBC_GLIBC
-  // sem_init in glibc prior to 2.1 does not zero out semaphores.
-  memset(&native_handle_, 0, sizeof(native_handle_));
+  // The sem_init() does not check for alignment of the native handle.
+  // Unaligned native handle can later cause a failure in semaphore signal.
+  // Check the alignment here to catch the failure earlier.
+  // Context: crbug.com/605349.
+#if V8_OS_AIX
+  // On aix sem_t is of type int
+  const uintptr_t kSemaphoreAlignmentMask = sizeof(int) - 1;
+#else
+  const uintptr_t kSemaphoreAlignmentMask = sizeof(void*) - 1;
 #endif
+  CHECK_EQ(
+      0, reinterpret_cast<uintptr_t>(&native_handle_) &
+      kSemaphoreAlignmentMask);
+  DCHECK(count >= 0);
   int result = sem_init(&native_handle_, 0, count);
   DCHECK_EQ(0, result);
   USE(result);
@@ -91,9 +99,11 @@
   USE(result);
 }
 
-
 void Semaphore::Signal() {
   int result = sem_post(&native_handle_);
+  // This check may fail with <libc-2.21, which we use on the try bots, if the
+  // semaphore is destroyed while sem_post is still executed. A work around is
+  // to extend the lifetime of the semaphore.
   CHECK_EQ(0, result);
 }
 
@@ -162,7 +172,6 @@
   USE(result);
 }
 
-
 void Semaphore::Signal() {
   LONG dummy;
   BOOL result = ReleaseSemaphore(native_handle_, 1, &dummy);
diff --git a/src/base/platform/time.cc b/src/base/platform/time.cc
index 6d5e538..786ef2e 100644
--- a/src/base/platform/time.cc
+++ b/src/base/platform/time.cc
@@ -10,7 +10,9 @@
 #include <unistd.h>
 #endif
 #if V8_OS_MACOSX
+#include <mach/mach.h>
 #include <mach/mach_time.h>
+#include <pthread.h>
 #endif
 
 #include <cstring>
@@ -25,6 +27,90 @@
 #include "src/base/logging.h"
 #include "src/base/platform/platform.h"
 
+namespace {
+
+#if V8_OS_MACOSX
+int64_t ComputeThreadTicks() {
+  mach_msg_type_number_t thread_info_count = THREAD_BASIC_INFO_COUNT;
+  thread_basic_info_data_t thread_info_data;
+  kern_return_t kr = thread_info(
+      pthread_mach_thread_np(pthread_self()),
+      THREAD_BASIC_INFO,
+      reinterpret_cast<thread_info_t>(&thread_info_data),
+      &thread_info_count);
+  CHECK(kr == KERN_SUCCESS);
+
+  v8::base::CheckedNumeric<int64_t> absolute_micros(
+      thread_info_data.user_time.seconds +
+      thread_info_data.system_time.seconds);
+  absolute_micros *= v8::base::Time::kMicrosecondsPerSecond;
+  absolute_micros += (thread_info_data.user_time.microseconds +
+                      thread_info_data.system_time.microseconds);
+  return absolute_micros.ValueOrDie();
+}
+#elif V8_OS_POSIX
+// Helper function to get results from clock_gettime() and convert to a
+// microsecond timebase. Minimum requirement is MONOTONIC_CLOCK to be supported
+// on the system. FreeBSD 6 has CLOCK_MONOTONIC but defines
+// _POSIX_MONOTONIC_CLOCK to -1.
+V8_INLINE int64_t ClockNow(clockid_t clk_id) {
+#if (defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0) || \
+  defined(V8_OS_BSD) || defined(V8_OS_ANDROID)
+// On AIX clock_gettime for CLOCK_THREAD_CPUTIME_ID outputs time with
+// resolution of 10ms. thread_cputime API provides the time in ns
+#if defined(V8_OS_AIX)
+  thread_cputime_t tc;
+  if (clk_id == CLOCK_THREAD_CPUTIME_ID) {
+    if (thread_cputime(-1, &tc) != 0) {
+      UNREACHABLE();
+      return 0;
+    }
+  }
+#endif
+  struct timespec ts;
+  if (clock_gettime(clk_id, &ts) != 0) {
+    UNREACHABLE();
+    return 0;
+  }
+  v8::base::internal::CheckedNumeric<int64_t> result(ts.tv_sec);
+  result *= v8::base::Time::kMicrosecondsPerSecond;
+#if defined(V8_OS_AIX)
+  if (clk_id == CLOCK_THREAD_CPUTIME_ID) {
+    result += (tc.stime / v8::base::Time::kNanosecondsPerMicrosecond);
+  } else {
+    result += (ts.tv_nsec / v8::base::Time::kNanosecondsPerMicrosecond);
+  }
+#else
+  result += (ts.tv_nsec / v8::base::Time::kNanosecondsPerMicrosecond);
+#endif
+  return result.ValueOrDie();
+#else  // Monotonic clock not supported.
+  return 0;
+#endif
+}
+#elif V8_OS_WIN
+V8_INLINE bool IsQPCReliable() {
+  v8::base::CPU cpu;
+  // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is unreliable.
+  return strcmp(cpu.vendor(), "AuthenticAMD") == 0 && cpu.family() == 15;
+}
+
+// Returns the current value of the performance counter.
+V8_INLINE uint64_t QPCNowRaw() {
+  LARGE_INTEGER perf_counter_now = {};
+  // According to the MSDN documentation for QueryPerformanceCounter(), this
+  // will never fail on systems that run XP or later.
+  // https://msdn.microsoft.com/library/windows/desktop/ms644904.aspx
+  BOOL result = ::QueryPerformanceCounter(&perf_counter_now);
+  DCHECK(result);
+  USE(result);
+  return perf_counter_now.QuadPart;
+}
+#endif  // V8_OS_MACOSX
+
+
+}  // namespace
+
 namespace v8 {
 namespace base {
 
@@ -409,15 +495,12 @@
   virtual ~HighResolutionTickClock() {}
 
   int64_t Now() override {
-    LARGE_INTEGER now;
-    BOOL result = QueryPerformanceCounter(&now);
-    DCHECK(result);
-    USE(result);
+    uint64_t now = QPCNowRaw();
 
     // Intentionally calculate microseconds in a round about manner to avoid
     // overflow and precision issues. Think twice before simplifying!
-    int64_t whole_seconds = now.QuadPart / ticks_per_second_;
-    int64_t leftover_ticks = now.QuadPart % ticks_per_second_;
+    int64_t whole_seconds = now / ticks_per_second_;
+    int64_t leftover_ticks = now % ticks_per_second_;
     int64_t ticks = (whole_seconds * Time::kMicrosecondsPerSecond) +
         ((leftover_ticks * Time::kMicrosecondsPerSecond) / ticks_per_second_);
 
@@ -482,10 +565,8 @@
       return tick_clock.Pointer();
     }
 
-    // On Athlon X2 CPUs (e.g. model 15) the QueryPerformanceCounter
-    // is unreliable, fallback to the low-resolution tick clock.
-    CPU cpu;
-    if (strcmp(cpu.vendor(), "AuthenticAMD") == 0 && cpu.family() == 15) {
+    // If QPC not reliable, fallback to low-resolution tick clock.
+    if (IsQPCReliable()) {
       return tick_clock.Pointer();
     }
 
@@ -541,12 +622,7 @@
 #elif V8_OS_SOLARIS
   ticks = (gethrtime() / Time::kNanosecondsPerMicrosecond);
 #elif V8_OS_POSIX
-  struct timespec ts;
-  int result = clock_gettime(CLOCK_MONOTONIC, &ts);
-  DCHECK_EQ(0, result);
-  USE(result);
-  ticks = (ts.tv_sec * Time::kMicrosecondsPerSecond +
-           ts.tv_nsec / Time::kNanosecondsPerMicrosecond);
+  ticks = ClockNow(CLOCK_MONOTONIC);
 #endif  // V8_OS_MACOSX
   // Make sure we never return 0 here.
   return TimeTicks(ticks + 1);
@@ -560,5 +636,125 @@
 
 #endif  // V8_OS_WIN
 
+
+// TODO(lpy): For windows ThreadTicks implementation,
+// see http://crbug.com/v8/5000
+bool ThreadTicks::IsSupported() {
+#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
+    defined(V8_OS_MACOSX) || defined(V8_OS_ANDROID)
+    return true;
+#else
+    return false;
+#endif
+}
+
+
+ThreadTicks ThreadTicks::Now() {
+#if V8_OS_MACOSX
+  return ThreadTicks(ComputeThreadTicks());
+#elif(defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
+  defined(V8_OS_ANDROID)
+  return ThreadTicks(ClockNow(CLOCK_THREAD_CPUTIME_ID));
+#elif V8_OS_WIN
+  return ThreadTicks::GetForThread(::GetCurrentThread());
+#else
+  UNREACHABLE();
+  return ThreadTicks();
+#endif
+}
+
+
+#if V8_OS_WIN
+ThreadTicks ThreadTicks::GetForThread(const HANDLE& thread_handle) {
+  DCHECK(IsSupported());
+
+  // Get the number of TSC ticks used by the current thread.
+  ULONG64 thread_cycle_time = 0;
+  ::QueryThreadCycleTime(thread_handle, &thread_cycle_time);
+
+  // Get the frequency of the TSC.
+  double tsc_ticks_per_second = TSCTicksPerSecond();
+  if (tsc_ticks_per_second == 0)
+    return ThreadTicks();
+
+  // Return the CPU time of the current thread.
+  double thread_time_seconds = thread_cycle_time / tsc_ticks_per_second;
+  return ThreadTicks(
+      static_cast<int64_t>(thread_time_seconds * Time::kMicrosecondsPerSecond));
+}
+
+// static
+bool ThreadTicks::IsSupportedWin() {
+  static bool is_supported = base::CPU().has_non_stop_time_stamp_counter() &&
+                             !IsQPCReliable();
+  return is_supported;
+}
+
+// static
+void ThreadTicks::WaitUntilInitializedWin() {
+  while (TSCTicksPerSecond() == 0)
+    ::Sleep(10);
+}
+
+double ThreadTicks::TSCTicksPerSecond() {
+  DCHECK(IsSupported());
+
+  // The value returned by QueryPerformanceFrequency() cannot be used as the TSC
+  // frequency, because there is no guarantee that the TSC frequency is equal to
+  // the performance counter frequency.
+
+  // The TSC frequency is cached in a static variable because it takes some time
+  // to compute it.
+  static double tsc_ticks_per_second = 0;
+  if (tsc_ticks_per_second != 0)
+    return tsc_ticks_per_second;
+
+  // Increase the thread priority to reduces the chances of having a context
+  // switch during a reading of the TSC and the performance counter.
+  int previous_priority = ::GetThreadPriority(::GetCurrentThread());
+  ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
+
+  // The first time that this function is called, make an initial reading of the
+  // TSC and the performance counter.
+  static const uint64_t tsc_initial = __rdtsc();
+  static const uint64_t perf_counter_initial = QPCNowRaw();
+
+  // Make a another reading of the TSC and the performance counter every time
+  // that this function is called.
+  uint64_t tsc_now = __rdtsc();
+  uint64_t perf_counter_now = QPCNowRaw();
+
+  // Reset the thread priority.
+  ::SetThreadPriority(::GetCurrentThread(), previous_priority);
+
+  // Make sure that at least 50 ms elapsed between the 2 readings. The first
+  // time that this function is called, we don't expect this to be the case.
+  // Note: The longer the elapsed time between the 2 readings is, the more
+  //   accurate the computed TSC frequency will be. The 50 ms value was
+  //   chosen because local benchmarks show that it allows us to get a
+  //   stddev of less than 1 tick/us between multiple runs.
+  // Note: According to the MSDN documentation for QueryPerformanceFrequency(),
+  //   this will never fail on systems that run XP or later.
+  //   https://msdn.microsoft.com/library/windows/desktop/ms644905.aspx
+  LARGE_INTEGER perf_counter_frequency = {};
+  ::QueryPerformanceFrequency(&perf_counter_frequency);
+  DCHECK_GE(perf_counter_now, perf_counter_initial);
+  uint64_t perf_counter_ticks = perf_counter_now - perf_counter_initial;
+  double elapsed_time_seconds =
+      perf_counter_ticks / static_cast<double>(perf_counter_frequency.QuadPart);
+
+  const double kMinimumEvaluationPeriodSeconds = 0.05;
+  if (elapsed_time_seconds < kMinimumEvaluationPeriodSeconds)
+    return 0;
+
+  // Compute the frequency of the TSC.
+  DCHECK_GE(tsc_now, tsc_initial);
+  uint64_t tsc_ticks = tsc_now - tsc_initial;
+  tsc_ticks_per_second = tsc_ticks / elapsed_time_seconds;
+
+  return tsc_ticks_per_second;
+}
+#endif  // V8_OS_WIN
+
 }  // namespace base
 }  // namespace v8
diff --git a/src/base/platform/time.h b/src/base/platform/time.h
index c8140ef..be62014 100644
--- a/src/base/platform/time.h
+++ b/src/base/platform/time.h
@@ -9,7 +9,12 @@
 #include <iosfwd>
 #include <limits>
 
+#include "src/base/bits.h"
 #include "src/base/macros.h"
+#include "src/base/safe_math.h"
+#if V8_OS_WIN
+#include "src/base/win32-headers.h"
+#endif
 
 // Forward declarations.
 extern "C" {
@@ -23,8 +28,14 @@
 namespace base {
 
 class Time;
+class TimeDelta;
 class TimeTicks;
 
+namespace time_internal {
+template<class TimeClass>
+class TimeBase;
+}
+
 // -----------------------------------------------------------------------------
 // TimeDelta
 //
@@ -143,6 +154,7 @@
   }
 
  private:
+  template<class TimeClass> friend class time_internal::TimeBase;
   // Constructs a delta given the duration in microseconds. This is private
   // to avoid confusion by callers with an integer constructor. Use
   // FromSeconds, FromMilliseconds, etc. instead.
@@ -153,34 +165,122 @@
 };
 
 
+namespace time_internal {
+
+// TimeBase--------------------------------------------------------------------
+
+// Provides value storage and comparison/math operations common to all time
+// classes. Each subclass provides for strong type-checking to ensure
+// semantically meaningful comparison/math of time values from the same clock
+// source or timeline.
+template<class TimeClass>
+class TimeBase {
+ public:
+  static const int64_t kHoursPerDay = 24;
+  static const int64_t kMillisecondsPerSecond = 1000;
+  static const int64_t kMillisecondsPerDay =
+      kMillisecondsPerSecond * 60 * 60 * kHoursPerDay;
+  static const int64_t kMicrosecondsPerMillisecond = 1000;
+  static const int64_t kMicrosecondsPerSecond =
+      kMicrosecondsPerMillisecond * kMillisecondsPerSecond;
+  static const int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60;
+  static const int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60;
+  static const int64_t kMicrosecondsPerDay =
+      kMicrosecondsPerHour * kHoursPerDay;
+  static const int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7;
+  static const int64_t kNanosecondsPerMicrosecond = 1000;
+  static const int64_t kNanosecondsPerSecond =
+      kNanosecondsPerMicrosecond * kMicrosecondsPerSecond;
+
+  // Returns true if this object has not been initialized.
+  //
+  // Warning: Be careful when writing code that performs math on time values,
+  // since it's possible to produce a valid "zero" result that should not be
+  // interpreted as a "null" value.
+  bool IsNull() const {
+    return us_ == 0;
+  }
+
+  // Returns true if this object represents the maximum time.
+  bool IsMax() const { return us_ == std::numeric_limits<int64_t>::max(); }
+
+  // For serializing only. Use FromInternalValue() to reconstitute. Please don't
+  // use this and do arithmetic on it, as it is more error prone than using the
+  // provided operators.
+  int64_t ToInternalValue() const { return us_; }
+
+  TimeClass& operator=(TimeClass other) {
+    us_ = other.us_;
+    return *(static_cast<TimeClass*>(this));
+  }
+
+  // Compute the difference between two times.
+  TimeDelta operator-(TimeClass other) const {
+    return TimeDelta::FromMicroseconds(us_ - other.us_);
+  }
+
+  // Return a new time modified by some delta.
+  TimeClass operator+(TimeDelta delta) const {
+    return TimeClass(bits::SignedSaturatedAdd64(delta.delta_, us_));
+  }
+  TimeClass operator-(TimeDelta delta) const {
+    return TimeClass(-bits::SignedSaturatedSub64(delta.delta_, us_));
+  }
+
+  // Modify by some time delta.
+  TimeClass& operator+=(TimeDelta delta) {
+    return static_cast<TimeClass&>(*this = (*this + delta));
+  }
+  TimeClass& operator-=(TimeDelta delta) {
+    return static_cast<TimeClass&>(*this = (*this - delta));
+  }
+
+  // Comparison operators
+  bool operator==(TimeClass other) const {
+    return us_ == other.us_;
+  }
+  bool operator!=(TimeClass other) const {
+    return us_ != other.us_;
+  }
+  bool operator<(TimeClass other) const {
+    return us_ < other.us_;
+  }
+  bool operator<=(TimeClass other) const {
+    return us_ <= other.us_;
+  }
+  bool operator>(TimeClass other) const {
+    return us_ > other.us_;
+  }
+  bool operator>=(TimeClass other) const {
+    return us_ >= other.us_;
+  }
+
+  // Converts an integer value representing TimeClass to a class. This is used
+  // when deserializing a |TimeClass| structure, using a value known to be
+  // compatible. It is not provided as a constructor because the integer type
+  // may be unclear from the perspective of a caller.
+  static TimeClass FromInternalValue(int64_t us) { return TimeClass(us); }
+
+ protected:
+  explicit TimeBase(int64_t us) : us_(us) {}
+
+  // Time value in a microsecond timebase.
+  int64_t us_;
+};
+
+}  // namespace time_internal
+
+
 // -----------------------------------------------------------------------------
 // Time
 //
 // This class represents an absolute point in time, internally represented as
 // microseconds (s/1,000,000) since 00:00:00 UTC, January 1, 1970.
 
-class Time final {
+class Time final : public time_internal::TimeBase<Time> {
  public:
-  static const int64_t kMillisecondsPerSecond = 1000;
-  static const int64_t kMicrosecondsPerMillisecond = 1000;
-  static const int64_t kMicrosecondsPerSecond = kMicrosecondsPerMillisecond *
-                                                kMillisecondsPerSecond;
-  static const int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60;
-  static const int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60;
-  static const int64_t kMicrosecondsPerDay = kMicrosecondsPerHour * 24;
-  static const int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7;
-  static const int64_t kNanosecondsPerMicrosecond = 1000;
-  static const int64_t kNanosecondsPerSecond = kNanosecondsPerMicrosecond *
-                                               kMicrosecondsPerSecond;
-
   // Contains the NULL time. Use Time::Now() to get the current time.
-  Time() : us_(0) {}
-
-  // Returns true if the time object has not been initialized.
-  bool IsNull() const { return us_ == 0; }
-
-  // Returns true if the time object is the maximum time.
-  bool IsMax() const { return us_ == std::numeric_limits<int64_t>::max(); }
+  Time() : TimeBase(0) {}
 
   // Returns the current time. Watch out, the system might adjust its clock
   // in which case time will actually go backwards. We don't guarantee that
@@ -200,15 +300,6 @@
   // with which we might compare it.
   static Time Max() { return Time(std::numeric_limits<int64_t>::max()); }
 
-  // Converts to/from internal values. The meaning of the "internal value" is
-  // completely up to the implementation, so it should be treated as opaque.
-  static Time FromInternalValue(int64_t value) {
-    return Time(value);
-  }
-  int64_t ToInternalValue() const {
-    return us_;
-  }
-
   // Converts to/from POSIX time specs.
   static Time FromTimespec(struct timespec ts);
   struct timespec ToTimespec() const;
@@ -226,59 +317,9 @@
   static Time FromJsTime(double ms_since_epoch);
   double ToJsTime() const;
 
-  Time& operator=(const Time& other) {
-    us_ = other.us_;
-    return *this;
-  }
-
-  // Compute the difference between two times.
-  TimeDelta operator-(const Time& other) const {
-    return TimeDelta::FromMicroseconds(us_ - other.us_);
-  }
-
-  // Modify by some time delta.
-  Time& operator+=(const TimeDelta& delta) {
-    us_ += delta.InMicroseconds();
-    return *this;
-  }
-  Time& operator-=(const TimeDelta& delta) {
-    us_ -= delta.InMicroseconds();
-    return *this;
-  }
-
-  // Return a new time modified by some delta.
-  Time operator+(const TimeDelta& delta) const {
-    return Time(us_ + delta.InMicroseconds());
-  }
-  Time operator-(const TimeDelta& delta) const {
-    return Time(us_ - delta.InMicroseconds());
-  }
-
-  // Comparison operators
-  bool operator==(const Time& other) const {
-    return us_ == other.us_;
-  }
-  bool operator!=(const Time& other) const {
-    return us_ != other.us_;
-  }
-  bool operator<(const Time& other) const {
-    return us_ < other.us_;
-  }
-  bool operator<=(const Time& other) const {
-    return us_ <= other.us_;
-  }
-  bool operator>(const Time& other) const {
-    return us_ > other.us_;
-  }
-  bool operator>=(const Time& other) const {
-    return us_ >= other.us_;
-  }
-
  private:
-  explicit Time(int64_t us) : us_(us) {}
-
-  // Time in microseconds in UTC.
-  int64_t us_;
+  friend class time_internal::TimeBase<Time>;
+  explicit Time(int64_t us) : TimeBase(us) {}
 };
 
 std::ostream& operator<<(std::ostream&, const Time&);
@@ -298,9 +339,9 @@
 // Time::Now() may actually decrease or jump).  But note that TimeTicks may
 // "stand still", for example if the computer suspended.
 
-class TimeTicks final {
+class TimeTicks final : public time_internal::TimeBase<TimeTicks> {
  public:
-  TimeTicks() : ticks_(0) {}
+  TimeTicks() : TimeBase(0) {}
 
   // Platform-dependent tick count representing "right now."
   // The resolution of this clock is ~1-15ms.  Resolution varies depending
@@ -318,79 +359,68 @@
   // Returns true if the high-resolution clock is working on this system.
   static bool IsHighResolutionClockWorking();
 
-  // Returns true if this object has not been initialized.
-  bool IsNull() const { return ticks_ == 0; }
-
-  // Converts to/from internal values. The meaning of the "internal value" is
-  // completely up to the implementation, so it should be treated as opaque.
-  static TimeTicks FromInternalValue(int64_t value) {
-    return TimeTicks(value);
-  }
-  int64_t ToInternalValue() const {
-    return ticks_;
-  }
-
-  TimeTicks& operator=(const TimeTicks other) {
-    ticks_ = other.ticks_;
-    return *this;
-  }
-
-  // Compute the difference between two times.
-  TimeDelta operator-(const TimeTicks other) const {
-    return TimeDelta::FromMicroseconds(ticks_ - other.ticks_);
-  }
-
-  // Modify by some time delta.
-  TimeTicks& operator+=(const TimeDelta& delta) {
-    ticks_ += delta.InMicroseconds();
-    return *this;
-  }
-  TimeTicks& operator-=(const TimeDelta& delta) {
-    ticks_ -= delta.InMicroseconds();
-    return *this;
-  }
-
-  // Return a new TimeTicks modified by some delta.
-  TimeTicks operator+(const TimeDelta& delta) const {
-    return TimeTicks(ticks_ + delta.InMicroseconds());
-  }
-  TimeTicks operator-(const TimeDelta& delta) const {
-    return TimeTicks(ticks_ - delta.InMicroseconds());
-  }
-
-  // Comparison operators
-  bool operator==(const TimeTicks& other) const {
-    return ticks_ == other.ticks_;
-  }
-  bool operator!=(const TimeTicks& other) const {
-    return ticks_ != other.ticks_;
-  }
-  bool operator<(const TimeTicks& other) const {
-    return ticks_ < other.ticks_;
-  }
-  bool operator<=(const TimeTicks& other) const {
-    return ticks_ <= other.ticks_;
-  }
-  bool operator>(const TimeTicks& other) const {
-    return ticks_ > other.ticks_;
-  }
-  bool operator>=(const TimeTicks& other) const {
-    return ticks_ >= other.ticks_;
-  }
-
  private:
-  // Please use Now() to create a new object. This is for internal use
-  // and testing. Ticks is in microseconds.
-  explicit TimeTicks(int64_t ticks) : ticks_(ticks) {}
+  friend class time_internal::TimeBase<TimeTicks>;
 
-  // Tick count in microseconds.
-  int64_t ticks_;
+  // Please use Now() to create a new object. This is for internal use
+  // and testing. Ticks are in microseconds.
+  explicit TimeTicks(int64_t ticks) : TimeBase(ticks) {}
 };
 
 inline TimeTicks operator+(const TimeDelta& delta, const TimeTicks& ticks) {
   return ticks + delta;
 }
 
+
+// ThreadTicks ----------------------------------------------------------------
+
+// Represents a clock, specific to a particular thread, than runs only while the
+// thread is running.
+class ThreadTicks final : public time_internal::TimeBase<ThreadTicks> {
+ public:
+  ThreadTicks() : TimeBase(0) {}
+
+  // Returns true if ThreadTicks::Now() is supported on this system.
+  static bool IsSupported();
+
+  // Waits until the initialization is completed. Needs to be guarded with a
+  // call to IsSupported().
+  static void WaitUntilInitialized() {
+#if V8_OS_WIN
+    WaitUntilInitializedWin();
+#endif
+  }
+
+  // Returns thread-specific CPU-time on systems that support this feature.
+  // Needs to be guarded with a call to IsSupported(). Use this timer
+  // to (approximately) measure how much time the calling thread spent doing
+  // actual work vs. being de-scheduled. May return bogus results if the thread
+  // migrates to another CPU between two calls. Returns an empty ThreadTicks
+  // object until the initialization is completed. If a clock reading is
+  // absolutely needed, call WaitUntilInitialized() before this method.
+  static ThreadTicks Now();
+
+#if V8_OS_WIN
+  // Similar to Now() above except this returns thread-specific CPU time for an
+  // arbitrary thread. All comments for Now() method above apply apply to this
+  // method as well.
+  static ThreadTicks GetForThread(const HANDLE& thread_handle);
+#endif
+
+ private:
+  // Please use Now() or GetForThread() to create a new object. This is for
+  // internal use and testing. Ticks are in microseconds.
+  explicit ThreadTicks(int64_t ticks) : TimeBase(ticks) {}
+
+#if V8_OS_WIN
+  // Returns the frequency of the TSC in ticks per second, or 0 if it hasn't
+  // been measured yet. Needs to be guarded with a call to IsSupported().
+  static double TSCTicksPerSecond();
+  static bool IsSupportedWin();
+  static void WaitUntilInitializedWin();
+#endif
+};
+
 }  // namespace base
 }  // namespace v8
 
diff --git a/src/base/utils/random-number-generator.cc b/src/base/utils/random-number-generator.cc
index ff42840..3a6f2c6 100644
--- a/src/base/utils/random-number-generator.cc
+++ b/src/base/utils/random-number-generator.cc
@@ -124,10 +124,10 @@
 
 
 void RandomNumberGenerator::SetSeed(int64_t seed) {
-  if (seed == 0) seed = 1;
   initial_seed_ = seed;
   state0_ = MurmurHash3(bit_cast<uint64_t>(seed));
-  state1_ = MurmurHash3(state0_);
+  state1_ = MurmurHash3(~state0_);
+  CHECK(state0_ != 0 || state1_ != 0);
 }
 
 
diff --git a/src/base/win32-headers.h b/src/base/win32-headers.h
index 20ec8e0..b61ce71 100644
--- a/src/base/win32-headers.h
+++ b/src/base/win32-headers.h
@@ -27,10 +27,10 @@
 #ifndef NOMCX
 #define NOMCX
 #endif
-// Require Windows XP or higher (this is required for the RtlCaptureContext
-// function to be present).
+// Require Windows Vista or higher (this is required for the
+// QueryThreadCycleTime function to be present).
 #ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x501
+#define _WIN32_WINNT 0x0600
 #endif
 
 #include <windows.h>
diff --git a/src/bignum.cc b/src/bignum.cc
index e7c6747..e2a9c4e 100644
--- a/src/bignum.cc
+++ b/src/bignum.cc
@@ -539,13 +539,6 @@
 }
 
 
-static char HexCharOfValue(int value) {
-  DCHECK(0 <= value && value <= 16);
-  if (value < 10) return value + '0';
-  return value - 10 + 'A';
-}
-
-
 bool Bignum::ToHexString(char* buffer, int buffer_size) const {
   DCHECK(IsClamped());
   // Each bigit must be printable as separate hex-character.
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index f67065d..0be96ea 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -6,10 +6,12 @@
 
 #include "src/accessors.h"
 #include "src/api-natives.h"
+#include "src/base/ieee754.h"
 #include "src/code-stubs.h"
 #include "src/extensions/externalize-string-extension.h"
 #include "src/extensions/free-buffer-extension.h"
 #include "src/extensions/gc-extension.h"
+#include "src/extensions/ignition-statistics-extension.h"
 #include "src/extensions/statistics-extension.h"
 #include "src/extensions/trigger-failure-extension.h"
 #include "src/heap/heap.h"
@@ -30,17 +32,15 @@
 Handle<String> Bootstrapper::SourceLookup(int index) {
   DCHECK(0 <= index && index < Source::GetBuiltinsCount());
   Heap* heap = isolate_->heap();
-  if (Source::GetSourceCache(heap)->get(index)->IsUndefined()) {
+  if (Source::GetSourceCache(heap)->get(index)->IsUndefined(isolate_)) {
     // We can use external strings for the natives.
     Vector<const char> source = Source::GetScriptSource(index);
     NativesExternalStringResource* resource =
         new NativesExternalStringResource(source.start(), source.length());
-    // We do not expect this to throw an exception. Change this if it does.
-    Handle<String> source_code = isolate_->factory()
-                                     ->NewExternalStringFromOneByte(resource)
-                                     .ToHandleChecked();
+    Handle<ExternalOneByteString> source_code =
+        isolate_->factory()->NewNativeSourceString(resource);
     // Mark this external string with a special map.
-    source_code->set_map(isolate_->heap()->native_source_string_map());
+    DCHECK(source_code->is_short());
     Source::GetSourceCache(heap)->set(index, *source_code);
   }
   Handle<Object> cached_source(Source::GetSourceCache(heap)->get(index),
@@ -73,7 +73,7 @@
 v8::Extension* Bootstrapper::externalize_string_extension_ = NULL;
 v8::Extension* Bootstrapper::statistics_extension_ = NULL;
 v8::Extension* Bootstrapper::trigger_failure_extension_ = NULL;
-
+v8::Extension* Bootstrapper::ignition_statistics_extension_ = NULL;
 
 void Bootstrapper::InitializeOncePerProcess() {
   free_buffer_extension_ = new FreeBufferExtension;
@@ -86,6 +86,8 @@
   v8::RegisterExtension(statistics_extension_);
   trigger_failure_extension_ = new TriggerFailureExtension;
   v8::RegisterExtension(trigger_failure_extension_);
+  ignition_statistics_extension_ = new IgnitionStatisticsExtension;
+  v8::RegisterExtension(ignition_statistics_extension_);
 }
 
 
@@ -100,15 +102,18 @@
   statistics_extension_ = NULL;
   delete trigger_failure_extension_;
   trigger_failure_extension_ = NULL;
+  delete ignition_statistics_extension_;
+  ignition_statistics_extension_ = NULL;
 }
 
 
 void DeleteNativeSources(Object* maybe_array) {
   if (maybe_array->IsFixedArray()) {
     FixedArray* array = FixedArray::cast(maybe_array);
+    Isolate* isolate = array->GetIsolate();
     for (int i = 0; i < array->length(); i++) {
       Object* natives_source = array->get(i);
-      if (!natives_source->IsUndefined()) {
+      if (!natives_source->IsUndefined(isolate)) {
         const NativesExternalStringResource* resource =
             reinterpret_cast<const NativesExternalStringResource*>(
                 ExternalOneByteString::cast(natives_source)->resource());
@@ -134,7 +139,7 @@
  public:
   Genesis(Isolate* isolate, MaybeHandle<JSGlobalProxy> maybe_global_proxy,
           v8::Local<v8::ObjectTemplate> global_proxy_template,
-          v8::ExtensionConfiguration* extensions,
+          v8::ExtensionConfiguration* extensions, size_t context_snapshot_index,
           GlobalContextType context_type);
   ~Genesis() { }
 
@@ -157,11 +162,12 @@
   Handle<JSFunction> GetThrowTypeErrorIntrinsic(Builtins::Name builtin_name);
 
   void CreateStrictModeFunctionMaps(Handle<JSFunction> empty);
-  void CreateIteratorMaps();
+  void CreateIteratorMaps(Handle<JSFunction> empty);
+  void CreateAsyncFunctionMaps(Handle<JSFunction> empty);
   void CreateJSProxyMaps();
 
   // Make the "arguments" and "caller" properties throw a TypeError on access.
-  void AddRestrictedFunctionProperties(Handle<Map> map);
+  void AddRestrictedFunctionProperties(Handle<JSFunction> empty);
 
   // Creates the global objects using the global proxy and the template passed
   // in through the API.  We call this regardless of whether we are building a
@@ -200,6 +206,7 @@
   HARMONY_STAGED(DECLARE_FEATURE_INITIALIZATION)
   HARMONY_SHIPPING(DECLARE_FEATURE_INITIALIZATION)
   DECLARE_FEATURE_INITIALIZATION(promise_extra, "")
+  DECLARE_FEATURE_INITIALIZATION(intl_extra, "")
 #undef DECLARE_FEATURE_INITIALIZATION
 
   Handle<JSFunction> InstallArrayBuffer(Handle<JSObject> target,
@@ -230,7 +237,7 @@
     void set_state(RegisteredExtension* extension,
                    ExtensionTraversalState state);
    private:
-    HashMap map_;
+    base::HashMap map_;
     DISALLOW_COPY_AND_ASSIGN(ExtensionStates);
   };
 
@@ -318,13 +325,13 @@
 Handle<Context> Bootstrapper::CreateEnvironment(
     MaybeHandle<JSGlobalProxy> maybe_global_proxy,
     v8::Local<v8::ObjectTemplate> global_proxy_template,
-    v8::ExtensionConfiguration* extensions, GlobalContextType context_type) {
+    v8::ExtensionConfiguration* extensions, size_t context_snapshot_index,
+    GlobalContextType context_type) {
   HandleScope scope(isolate_);
   Genesis genesis(isolate_, maybe_global_proxy, global_proxy_template,
-                  extensions, context_type);
+                  extensions, context_snapshot_index, context_type);
   Handle<Context> env = genesis.result();
-  if (env.is_null() ||
-      (context_type != THIN_CONTEXT && !InstallExtensions(env, extensions))) {
+  if (env.is_null() || !InstallExtensions(env, extensions)) {
     return Handle<Context>();
   }
   return scope.CloseAndEscape(env);
@@ -354,7 +361,6 @@
   }
 }
 
-
 namespace {
 
 void InstallFunction(Handle<JSObject> target, Handle<Name> property_name,
@@ -367,34 +373,38 @@
   function->shared()->set_native(true);
 }
 
-
-static void InstallFunction(Handle<JSObject> target,
-                            Handle<JSFunction> function, Handle<Name> name,
-                            PropertyAttributes attributes = DONT_ENUM) {
+void InstallFunction(Handle<JSObject> target, Handle<JSFunction> function,
+                     Handle<Name> name,
+                     PropertyAttributes attributes = DONT_ENUM) {
   Handle<String> name_string = Name::ToFunctionName(name).ToHandleChecked();
   InstallFunction(target, name, function, name_string, attributes);
 }
 
+Handle<JSFunction> InstallGetter(Handle<JSObject> target,
+                                 Handle<Name> property_name,
+                                 Handle<JSFunction> getter,
+                                 PropertyAttributes attributes = DONT_ENUM) {
+  Handle<Object> setter = target->GetIsolate()->factory()->undefined_value();
+  JSObject::DefineAccessor(target, property_name, getter, setter, attributes)
+      .Check();
+  return getter;
+}
 
-static Handle<JSFunction> CreateFunction(Isolate* isolate, Handle<String> name,
-                                         InstanceType type, int instance_size,
-                                         MaybeHandle<JSObject> maybe_prototype,
-                                         Builtins::Name call,
-                                         bool strict_function_map = false) {
+Handle<JSFunction> CreateFunction(Isolate* isolate, Handle<String> name,
+                                  InstanceType type, int instance_size,
+                                  MaybeHandle<JSObject> maybe_prototype,
+                                  Builtins::Name call,
+                                  bool strict_function_map = false) {
   Factory* factory = isolate->factory();
   Handle<Code> call_code(isolate->builtins()->builtin(call));
   Handle<JSObject> prototype;
-  static const bool kReadOnlyPrototype = false;
-  static const bool kInstallConstructor = false;
   return maybe_prototype.ToHandle(&prototype)
              ? factory->NewFunction(name, call_code, prototype, type,
-                                    instance_size, kReadOnlyPrototype,
-                                    kInstallConstructor, strict_function_map)
+                                    instance_size, strict_function_map)
              : factory->NewFunctionWithoutPrototype(name, call_code,
                                                     strict_function_map);
 }
 
-
 Handle<JSFunction> InstallFunction(Handle<JSObject> target, Handle<Name> name,
                                    InstanceType type, int instance_size,
                                    MaybeHandle<JSObject> maybe_prototype,
@@ -409,7 +419,6 @@
   return function;
 }
 
-
 Handle<JSFunction> InstallFunction(Handle<JSObject> target, const char* name,
                                    InstanceType type, int instance_size,
                                    MaybeHandle<JSObject> maybe_prototype,
@@ -422,8 +431,61 @@
                          strict_function_map);
 }
 
-}  // namespace
+Handle<JSFunction> SimpleCreateFunction(Isolate* isolate, Handle<String> name,
+                                        Builtins::Name call, int len,
+                                        bool adapt) {
+  Handle<JSFunction> fun =
+      CreateFunction(isolate, name, JS_OBJECT_TYPE, JSObject::kHeaderSize,
+                     MaybeHandle<JSObject>(), call);
+  if (adapt) {
+    fun->shared()->set_internal_formal_parameter_count(len);
+  } else {
+    fun->shared()->DontAdaptArguments();
+  }
+  fun->shared()->set_length(len);
+  return fun;
+}
 
+Handle<JSFunction> SimpleInstallFunction(Handle<JSObject> base,
+                                         Handle<String> name,
+                                         Builtins::Name call, int len,
+                                         bool adapt) {
+  Handle<JSFunction> fun =
+      SimpleCreateFunction(base->GetIsolate(), name, call, len, adapt);
+  InstallFunction(base, fun, name, DONT_ENUM);
+  return fun;
+}
+
+Handle<JSFunction> SimpleInstallFunction(Handle<JSObject> base,
+                                         const char* name, Builtins::Name call,
+                                         int len, bool adapt) {
+  Factory* const factory = base->GetIsolate()->factory();
+  return SimpleInstallFunction(base, factory->InternalizeUtf8String(name), call,
+                               len, adapt);
+}
+
+Handle<JSFunction> SimpleInstallGetter(Handle<JSObject> base,
+                                       Handle<String> name, Builtins::Name call,
+                                       bool adapt) {
+  Isolate* const isolate = base->GetIsolate();
+  Handle<String> fun_name =
+      Name::ToFunctionName(name, isolate->factory()->get_string())
+          .ToHandleChecked();
+  Handle<JSFunction> fun =
+      SimpleCreateFunction(isolate, fun_name, call, 0, adapt);
+  InstallGetter(base, name, fun);
+  return fun;
+}
+
+Handle<JSFunction> SimpleInstallGetter(Handle<JSObject> base,
+                                       Handle<String> name, Builtins::Name call,
+                                       bool adapt, BuiltinFunctionId id) {
+  Handle<JSFunction> fun = SimpleInstallGetter(base, name, call, adapt);
+  fun->shared()->set_builtin_function_id(id);
+  return fun;
+}
+
+}  // namespace
 
 void Genesis::SetFunctionInstanceDescriptor(Handle<Map> map,
                                             FunctionMode function_mode) {
@@ -435,6 +497,7 @@
   PropertyAttributes roc_attribs =
       static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
 
+  STATIC_ASSERT(JSFunction::kLengthDescriptorIndex == 0);
   Handle<AccessorInfo> length =
       Accessors::FunctionLengthInfo(isolate(), roc_attribs);
   {  // Add length.
@@ -442,6 +505,8 @@
                                  length, roc_attribs);
     map->AppendDescriptor(&d);
   }
+
+  STATIC_ASSERT(JSFunction::kNameDescriptorIndex == 1);
   Handle<AccessorInfo> name =
       Accessors::FunctionNameInfo(isolate(), ro_attribs);
   {  // Add name.
@@ -577,9 +642,6 @@
   Map::SetPrototype(sloppy_function_without_prototype_map, empty_function);
   Map::SetPrototype(sloppy_function_map_writable_prototype_, empty_function);
 
-  // ES6 draft 03-17-2015, section 8.2.2 step 12
-  AddRestrictedFunctionProperties(empty_function_map);
-
   return empty_function;
 }
 
@@ -599,17 +661,20 @@
   DCHECK(function_mode == FUNCTION_WITH_WRITEABLE_PROTOTYPE ||
          function_mode == FUNCTION_WITH_READONLY_PROTOTYPE ||
          function_mode == FUNCTION_WITHOUT_PROTOTYPE);
+  STATIC_ASSERT(JSFunction::kLengthDescriptorIndex == 0);
   {  // Add length.
     Handle<AccessorInfo> length =
         Accessors::FunctionLengthInfo(isolate(), roc_attribs);
-    AccessorConstantDescriptor d(Handle<Name>(Name::cast(length->name())),
-                                 length, roc_attribs);
+    AccessorConstantDescriptor d(handle(Name::cast(length->name())), length,
+                                 roc_attribs);
     map->AppendDescriptor(&d);
   }
+
+  STATIC_ASSERT(JSFunction::kNameDescriptorIndex == 1);
   {  // Add name.
     Handle<AccessorInfo> name =
         Accessors::FunctionNameInfo(isolate(), roc_attribs);
-    AccessorConstantDescriptor d(Handle<Name>(Name::cast(name->name())), name,
+    AccessorConstantDescriptor d(handle(Name::cast(name->name())), name,
                                  roc_attribs);
     map->AppendDescriptor(&d);
   }
@@ -634,7 +699,7 @@
       factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("ThrowTypeError"));
   Handle<Code> code(isolate()->builtins()->builtin(builtin_name));
   Handle<JSFunction> function =
-      factory()->NewFunctionWithoutPrototype(name, code);
+      factory()->NewFunctionWithoutPrototype(name, code, true);
   function->shared()->DontAdaptArguments();
 
   // %ThrowTypeError% must not have a name property.
@@ -707,24 +772,49 @@
   // This map is installed in MakeFunctionInstancePrototypeWritable.
   strict_function_map_writable_prototype_ =
       CreateStrictFunctionMap(FUNCTION_WITH_WRITEABLE_PROTOTYPE, empty);
+
+  // Now that the strict mode function map is available, set up the
+  // restricted "arguments" and "caller" getters.
+  AddRestrictedFunctionProperties(empty);
 }
 
-
-void Genesis::CreateIteratorMaps() {
+void Genesis::CreateIteratorMaps(Handle<JSFunction> empty) {
   // Create iterator-related meta-objects.
   Handle<JSObject> iterator_prototype =
       factory()->NewJSObject(isolate()->object_function(), TENURED);
   Handle<JSObject> generator_object_prototype =
       factory()->NewJSObject(isolate()->object_function(), TENURED);
+  native_context()->set_initial_generator_prototype(
+      *generator_object_prototype);
+  SetObjectPrototype(generator_object_prototype, iterator_prototype);
   Handle<JSObject> generator_function_prototype =
       factory()->NewJSObject(isolate()->object_function(), TENURED);
-  SetObjectPrototype(generator_object_prototype, iterator_prototype);
+  SetObjectPrototype(generator_function_prototype, empty);
 
+  JSObject::AddProperty(
+      generator_function_prototype, factory()->to_string_tag_symbol(),
+      factory()->NewStringFromAsciiChecked("GeneratorFunction"),
+      static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
   JSObject::AddProperty(generator_function_prototype,
-                        factory()->InternalizeUtf8String("prototype"),
+                        factory()->prototype_string(),
                         generator_object_prototype,
                         static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
 
+  JSObject::AddProperty(generator_object_prototype,
+                        factory()->constructor_string(),
+                        generator_function_prototype,
+                        static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
+  JSObject::AddProperty(generator_object_prototype,
+                        factory()->to_string_tag_symbol(),
+                        factory()->NewStringFromAsciiChecked("Generator"),
+                        static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
+  SimpleInstallFunction(generator_object_prototype, "next",
+                        Builtins::kGeneratorPrototypeNext, 1, true);
+  SimpleInstallFunction(generator_object_prototype, "return",
+                        Builtins::kGeneratorPrototypeReturn, 1, true);
+  SimpleInstallFunction(generator_object_prototype, "throw",
+                        Builtins::kGeneratorPrototypeThrow, 1, true);
+
   // Create maps for generator functions and their prototypes.  Store those
   // maps in the native context. The "prototype" property descriptor is
   // writable, non-enumerable, and non-configurable (as per ES6 draft
@@ -754,6 +844,32 @@
       *generator_object_prototype_map);
 }
 
+void Genesis::CreateAsyncFunctionMaps(Handle<JSFunction> empty) {
+  // %AsyncFunctionPrototype% intrinsic
+  Handle<JSObject> async_function_prototype =
+      factory()->NewJSObject(isolate()->object_function(), TENURED);
+  SetObjectPrototype(async_function_prototype, empty);
+
+  JSObject::AddProperty(async_function_prototype,
+                        factory()->to_string_tag_symbol(),
+                        factory()->NewStringFromAsciiChecked("AsyncFunction"),
+                        static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
+
+  Handle<Map> strict_function_map(
+      native_context()->strict_function_without_prototype_map());
+  Handle<Map> sloppy_async_function_map =
+      Map::Copy(strict_function_map, "SloppyAsyncFunction");
+  sloppy_async_function_map->set_is_constructor(false);
+  Map::SetPrototype(sloppy_async_function_map, async_function_prototype);
+  native_context()->set_sloppy_async_function_map(*sloppy_async_function_map);
+
+  Handle<Map> strict_async_function_map =
+      Map::Copy(strict_function_map, "StrictAsyncFunction");
+  strict_async_function_map->set_is_constructor(false);
+  Map::SetPrototype(strict_async_function_map, async_function_prototype);
+  native_context()->set_strict_async_function_map(*strict_async_function_map);
+}
+
 void Genesis::CreateJSProxyMaps() {
   // Allocate the different maps for all Proxy types.
   // Next to the default proxy, we need maps indicating callable and
@@ -789,14 +905,14 @@
   descriptors->Replace(idx, &descriptor);
 }
 
-
-void Genesis::AddRestrictedFunctionProperties(Handle<Map> map) {
+void Genesis::AddRestrictedFunctionProperties(Handle<JSFunction> empty) {
   PropertyAttributes rw_attribs = static_cast<PropertyAttributes>(DONT_ENUM);
   Handle<JSFunction> thrower = GetRestrictedFunctionPropertiesThrower();
   Handle<AccessorPair> accessors = factory()->NewAccessorPair();
   accessors->set_getter(*thrower);
   accessors->set_setter(*thrower);
 
+  Handle<Map> map(empty->map());
   ReplaceAccessors(map, factory()->arguments_string(), rw_attribs, accessors);
   ReplaceAccessors(map, factory()->caller_string(), rw_attribs, accessors);
 }
@@ -804,14 +920,15 @@
 
 static void AddToWeakNativeContextList(Context* context) {
   DCHECK(context->IsNativeContext());
-  Heap* heap = context->GetIsolate()->heap();
+  Isolate* isolate = context->GetIsolate();
+  Heap* heap = isolate->heap();
 #ifdef DEBUG
   { // NOLINT
-    DCHECK(context->get(Context::NEXT_CONTEXT_LINK)->IsUndefined());
+    DCHECK(context->next_context_link()->IsUndefined(isolate));
     // Check that context is not in the list yet.
     for (Object* current = heap->native_contexts_list();
-         !current->IsUndefined();
-         current = Context::cast(current)->get(Context::NEXT_CONTEXT_LINK)) {
+         !current->IsUndefined(isolate);
+         current = Context::cast(current)->next_context_link()) {
       DCHECK(current != context);
     }
   }
@@ -885,7 +1002,7 @@
             FunctionTemplateInfo::cast(data->constructor()));
     Handle<Object> proto_template(global_constructor->prototype_template(),
                                   isolate());
-    if (!proto_template->IsUndefined()) {
+    if (!proto_template->IsUndefined(isolate())) {
       js_global_object_template =
           Handle<ObjectTemplateInfo>::cast(proto_template);
     }
@@ -955,7 +1072,9 @@
   global_proxy->set_native_context(*native_context());
   // If we deserialized the context, the global proxy is already
   // correctly set up. Otherwise it's undefined.
-  DCHECK(native_context()->get(Context::GLOBAL_PROXY_INDEX)->IsUndefined() ||
+  DCHECK(native_context()
+             ->get(Context::GLOBAL_PROXY_INDEX)
+             ->IsUndefined(isolate()) ||
          native_context()->global_proxy() == *global_proxy);
   native_context()->set_global_proxy(*global_proxy);
 }
@@ -971,45 +1090,6 @@
   TransferIndexedProperties(global_object_from_snapshot, global_object);
 }
 
-
-static Handle<JSFunction> SimpleCreateFunction(Isolate* isolate,
-                                               Handle<String> name,
-                                               Builtins::Name call, int len,
-                                               bool adapt) {
-  Handle<JSFunction> fun =
-      CreateFunction(isolate, name, JS_OBJECT_TYPE, JSObject::kHeaderSize,
-                     MaybeHandle<JSObject>(), call);
-  if (adapt) {
-    fun->shared()->set_internal_formal_parameter_count(len);
-  } else {
-    fun->shared()->DontAdaptArguments();
-  }
-  fun->shared()->set_length(len);
-  return fun;
-}
-
-
-static Handle<JSFunction> SimpleInstallFunction(Handle<JSObject> base,
-                                                Handle<String> name,
-                                                Builtins::Name call, int len,
-                                                bool adapt) {
-  Handle<JSFunction> fun =
-      SimpleCreateFunction(base->GetIsolate(), name, call, len, adapt);
-  InstallFunction(base, fun, name, DONT_ENUM);
-  return fun;
-}
-
-
-static Handle<JSFunction> SimpleInstallFunction(Handle<JSObject> base,
-                                                const char* name,
-                                                Builtins::Name call, int len,
-                                                bool adapt) {
-  Factory* const factory = base->GetIsolate()->factory();
-  return SimpleInstallFunction(base, factory->InternalizeUtf8String(name), call,
-                               len, adapt);
-}
-
-
 static void InstallWithIntrinsicDefaultProto(Isolate* isolate,
                                              Handle<JSFunction> function,
                                              int context_index) {
@@ -1049,40 +1129,74 @@
     Handle<JSFunction> object_function = isolate->object_function();
     JSObject::AddProperty(global_object, object_name, object_function,
                           DONT_ENUM);
+
     SimpleInstallFunction(object_function, factory->assign_string(),
                           Builtins::kObjectAssign, 2, false);
     SimpleInstallFunction(object_function, factory->create_string(),
                           Builtins::kObjectCreate, 2, false);
-    Handle<JSFunction> object_freeze = SimpleInstallFunction(
-        object_function, "freeze", Builtins::kObjectFreeze, 1, false);
-    native_context()->set_object_freeze(*object_freeze);
     SimpleInstallFunction(object_function, "getOwnPropertyDescriptor",
                           Builtins::kObjectGetOwnPropertyDescriptor, 2, false);
     SimpleInstallFunction(object_function, "getOwnPropertyNames",
                           Builtins::kObjectGetOwnPropertyNames, 1, false);
     SimpleInstallFunction(object_function, "getOwnPropertySymbols",
                           Builtins::kObjectGetOwnPropertySymbols, 1, false);
-    SimpleInstallFunction(object_function, "is", Builtins::kObjectIs, 2, true);
-    Handle<JSFunction> object_is_extensible =
-        SimpleInstallFunction(object_function, "isExtensible",
-                              Builtins::kObjectIsExtensible, 1, false);
+    SimpleInstallFunction(object_function, "is",
+                          Builtins::kObjectIs, 2, true);
+    SimpleInstallFunction(object_function, "preventExtensions",
+                          Builtins::kObjectPreventExtensions, 1, false);
+    SimpleInstallFunction(object_function, "seal",
+                          Builtins::kObjectSeal, 1, false);
+
+    Handle<JSFunction> object_define_properties = SimpleInstallFunction(
+        object_function, "defineProperties",
+        Builtins::kObjectDefineProperties, 2, true);
+    native_context()->set_object_define_properties(*object_define_properties);
+
+    Handle<JSFunction> object_define_property = SimpleInstallFunction(
+        object_function, factory->defineProperty_string(),
+        Builtins::kObjectDefineProperty, 3, true);
+    native_context()->set_object_define_property(*object_define_property);
+
+    Handle<JSFunction> object_freeze = SimpleInstallFunction(
+        object_function, "freeze", Builtins::kObjectFreeze, 1, false);
+    native_context()->set_object_freeze(*object_freeze);
+
+    Handle<JSFunction> object_get_prototype_of = SimpleInstallFunction(
+        object_function, "getPrototypeOf", Builtins::kObjectGetPrototypeOf,
+        1, false);
+    native_context()->set_object_get_prototype_of(*object_get_prototype_of);
+
+    Handle<JSFunction> object_is_extensible = SimpleInstallFunction(
+        object_function, "isExtensible", Builtins::kObjectIsExtensible,
+        1, false);
     native_context()->set_object_is_extensible(*object_is_extensible);
+
     Handle<JSFunction> object_is_frozen = SimpleInstallFunction(
         object_function, "isFrozen", Builtins::kObjectIsFrozen, 1, false);
     native_context()->set_object_is_frozen(*object_is_frozen);
+
     Handle<JSFunction> object_is_sealed = SimpleInstallFunction(
         object_function, "isSealed", Builtins::kObjectIsSealed, 1, false);
     native_context()->set_object_is_sealed(*object_is_sealed);
+
     Handle<JSFunction> object_keys = SimpleInstallFunction(
         object_function, "keys", Builtins::kObjectKeys, 1, false);
     native_context()->set_object_keys(*object_keys);
-    SimpleInstallFunction(object_function, "preventExtensions",
-                          Builtins::kObjectPreventExtensions, 1, false);
-    SimpleInstallFunction(object_function, "seal", Builtins::kObjectSeal, 1,
-                          false);
 
+    SimpleInstallFunction(isolate->initial_object_prototype(),
+                          "__defineGetter__", Builtins::kObjectDefineGetter, 2,
+                          true);
+    SimpleInstallFunction(isolate->initial_object_prototype(),
+                          "__defineSetter__", Builtins::kObjectDefineSetter, 2,
+                          true);
     SimpleInstallFunction(isolate->initial_object_prototype(), "hasOwnProperty",
                           Builtins::kObjectHasOwnProperty, 1, true);
+    SimpleInstallFunction(isolate->initial_object_prototype(),
+                          "__lookupGetter__", Builtins::kObjectLookupGetter, 1,
+                          true);
+    SimpleInstallFunction(isolate->initial_object_prototype(),
+                          "__lookupSetter__", Builtins::kObjectLookupSetter, 1,
+                          true);
   }
 
   Handle<JSObject> global(native_context()->global_object());
@@ -1104,8 +1218,15 @@
     // Setup the methods on the %FunctionPrototype%.
     SimpleInstallFunction(prototype, factory->apply_string(),
                           Builtins::kFunctionPrototypeApply, 2, false);
-    SimpleInstallFunction(prototype, factory->bind_string(),
-                          Builtins::kFunctionPrototypeBind, 1, false);
+
+    FastFunctionBindStub bind_stub(isolate);
+    Handle<JSFunction> bind_function = factory->NewFunctionWithoutPrototype(
+        factory->bind_string(), bind_stub.GetCode(), false);
+    bind_function->shared()->DontAdaptArguments();
+    bind_function->shared()->set_length(1);
+    InstallFunction(prototype, bind_function, factory->bind_string(),
+                    DONT_ENUM);
+
     SimpleInstallFunction(prototype, factory->call_string(),
                           Builtins::kFunctionPrototypeCall, 1, false);
     SimpleInstallFunction(prototype, factory->toString_string(),
@@ -1115,7 +1236,7 @@
     Handle<JSFunction> has_instance = InstallFunction(
         prototype, factory->has_instance_symbol(), JS_OBJECT_TYPE,
         JSObject::kHeaderSize, MaybeHandle<JSObject>(),
-        Builtins::kFunctionHasInstance,
+        Builtins::kFunctionPrototypeHasInstance,
         static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY));
 
     // Set the expected parameters for @@hasInstance to 1; required by builtin.
@@ -1124,9 +1245,6 @@
     // Set the length for the function to satisfy ECMA-262.
     has_instance->shared()->set_length(1);
 
-    // Install in the native context
-    native_context()->set_ordinary_has_instance(*has_instance);
-
     // Install the "constructor" property on the %FunctionPrototype%.
     JSObject::AddProperty(prototype, factory->constructor_string(),
                           function_fun, DONT_ENUM);
@@ -1251,7 +1369,33 @@
 
     // Install the String.fromCharCode function.
     SimpleInstallFunction(string_fun, "fromCharCode",
-                          Builtins::kStringFromCharCode, 1, false);
+                          Builtins::kStringFromCharCode, 1, true);
+
+    // Install the String.fromCodePoint function.
+    SimpleInstallFunction(string_fun, "fromCodePoint",
+                          Builtins::kStringFromCodePoint, 1, false);
+
+    // Create the %StringPrototype%
+    Handle<JSValue> prototype =
+        Handle<JSValue>::cast(factory->NewJSObject(string_fun, TENURED));
+    prototype->set_value(isolate->heap()->empty_string());
+    Accessors::FunctionSetPrototype(string_fun, prototype).Assert();
+
+    // Install the "constructor" property on the {prototype}.
+    JSObject::AddProperty(prototype, factory->constructor_string(), string_fun,
+                          DONT_ENUM);
+
+    // Install the String.prototype methods.
+    SimpleInstallFunction(prototype, "charAt", Builtins::kStringPrototypeCharAt,
+                          1, true);
+    SimpleInstallFunction(prototype, "charCodeAt",
+                          Builtins::kStringPrototypeCharCodeAt, 1, true);
+    SimpleInstallFunction(prototype, "trim", Builtins::kStringPrototypeTrim, 0,
+                          false);
+    SimpleInstallFunction(prototype, "trimLeft",
+                          Builtins::kStringPrototypeTrimLeft, 0, false);
+    SimpleInstallFunction(prototype, "trimRight",
+                          Builtins::kStringPrototypeTrimRight, 0, false);
   }
 
   {
@@ -1381,6 +1525,8 @@
                           0, true);
     SimpleInstallFunction(prototype, "setYear", Builtins::kDatePrototypeSetYear,
                           1, false);
+    SimpleInstallFunction(prototype, "toJSON", Builtins::kDatePrototypeToJson,
+                          1, false);
 
     // Install i18n fallback functions.
     SimpleInstallFunction(prototype, "toLocaleString",
@@ -1439,7 +1585,7 @@
 
   {  // -- E r r o r
     Handle<JSFunction> error_fun = InstallFunction(
-        global, "Error", JS_OBJECT_TYPE, JSObject::kHeaderSize,
+        global, "Error", JS_ERROR_TYPE, JSObject::kHeaderSize,
         isolate->initial_object_prototype(), Builtins::kIllegal);
     InstallWithIntrinsicDefaultProto(isolate, error_fun,
                                      Context::ERROR_FUNCTION_INDEX);
@@ -1447,7 +1593,7 @@
 
   {  // -- E v a l E r r o r
     Handle<JSFunction> eval_error_fun = InstallFunction(
-        global, "EvalError", JS_OBJECT_TYPE, JSObject::kHeaderSize,
+        global, "EvalError", JS_ERROR_TYPE, JSObject::kHeaderSize,
         isolate->initial_object_prototype(), Builtins::kIllegal);
     InstallWithIntrinsicDefaultProto(isolate, eval_error_fun,
                                      Context::EVAL_ERROR_FUNCTION_INDEX);
@@ -1455,7 +1601,7 @@
 
   {  // -- R a n g e E r r o r
     Handle<JSFunction> range_error_fun = InstallFunction(
-        global, "RangeError", JS_OBJECT_TYPE, JSObject::kHeaderSize,
+        global, "RangeError", JS_ERROR_TYPE, JSObject::kHeaderSize,
         isolate->initial_object_prototype(), Builtins::kIllegal);
     InstallWithIntrinsicDefaultProto(isolate, range_error_fun,
                                      Context::RANGE_ERROR_FUNCTION_INDEX);
@@ -1463,7 +1609,7 @@
 
   {  // -- R e f e r e n c e E r r o r
     Handle<JSFunction> reference_error_fun = InstallFunction(
-        global, "ReferenceError", JS_OBJECT_TYPE, JSObject::kHeaderSize,
+        global, "ReferenceError", JS_ERROR_TYPE, JSObject::kHeaderSize,
         isolate->initial_object_prototype(), Builtins::kIllegal);
     InstallWithIntrinsicDefaultProto(isolate, reference_error_fun,
                                      Context::REFERENCE_ERROR_FUNCTION_INDEX);
@@ -1471,7 +1617,7 @@
 
   {  // -- S y n t a x E r r o r
     Handle<JSFunction> syntax_error_fun = InstallFunction(
-        global, "SyntaxError", JS_OBJECT_TYPE, JSObject::kHeaderSize,
+        global, "SyntaxError", JS_ERROR_TYPE, JSObject::kHeaderSize,
         isolate->initial_object_prototype(), Builtins::kIllegal);
     InstallWithIntrinsicDefaultProto(isolate, syntax_error_fun,
                                      Context::SYNTAX_ERROR_FUNCTION_INDEX);
@@ -1479,7 +1625,7 @@
 
   {  // -- T y p e E r r o r
     Handle<JSFunction> type_error_fun = InstallFunction(
-        global, "TypeError", JS_OBJECT_TYPE, JSObject::kHeaderSize,
+        global, "TypeError", JS_ERROR_TYPE, JSObject::kHeaderSize,
         isolate->initial_object_prototype(), Builtins::kIllegal);
     InstallWithIntrinsicDefaultProto(isolate, type_error_fun,
                                      Context::TYPE_ERROR_FUNCTION_INDEX);
@@ -1487,7 +1633,7 @@
 
   {  // -- U R I E r r o r
     Handle<JSFunction> uri_error_fun = InstallFunction(
-        global, "URIError", JS_OBJECT_TYPE, JSObject::kHeaderSize,
+        global, "URIError", JS_ERROR_TYPE, JSObject::kHeaderSize,
         isolate->initial_object_prototype(), Builtins::kIllegal);
     InstallWithIntrinsicDefaultProto(isolate, uri_error_fun,
                                      Context::URI_ERROR_FUNCTION_INDEX);
@@ -1497,17 +1643,21 @@
   Handle<FixedArray> embedder_data = factory->NewFixedArray(3);
   native_context()->set_embedder_data(*embedder_data);
 
-  if (context_type == THIN_CONTEXT) return;
-
   {  // -- J S O N
     Handle<String> name = factory->InternalizeUtf8String("JSON");
     Handle<JSFunction> cons = factory->NewFunction(name);
     JSFunction::SetInstancePrototype(cons,
         Handle<Object>(native_context()->initial_object_prototype(), isolate));
-    cons->shared()->set_instance_class_name(*name);
     Handle<JSObject> json_object = factory->NewJSObject(cons, TENURED);
     DCHECK(json_object->IsJSObject());
     JSObject::AddProperty(global, name, json_object, DONT_ENUM);
+    SimpleInstallFunction(json_object, "parse", Builtins::kJsonParse, 2, false);
+    SimpleInstallFunction(json_object, "stringify", Builtins::kJsonStringify, 3,
+                          true);
+    JSObject::AddProperty(
+        json_object, factory->to_string_tag_symbol(),
+        factory->NewStringFromAsciiChecked("JSON"),
+        static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
   }
 
   {  // -- M a t h
@@ -1516,27 +1666,64 @@
     JSFunction::SetInstancePrototype(
         cons,
         Handle<Object>(native_context()->initial_object_prototype(), isolate));
-    cons->shared()->set_instance_class_name(*name);
     Handle<JSObject> math = factory->NewJSObject(cons, TENURED);
     DCHECK(math->IsJSObject());
     JSObject::AddProperty(global, name, math, DONT_ENUM);
     SimpleInstallFunction(math, "acos", Builtins::kMathAcos, 1, true);
     SimpleInstallFunction(math, "asin", Builtins::kMathAsin, 1, true);
     SimpleInstallFunction(math, "atan", Builtins::kMathAtan, 1, true);
+    SimpleInstallFunction(math, "atan2", Builtins::kMathAtan2, 2, true);
+    SimpleInstallFunction(math, "atanh", Builtins::kMathAtanh, 1, true);
     SimpleInstallFunction(math, "ceil", Builtins::kMathCeil, 1, true);
+    SimpleInstallFunction(math, "cbrt", Builtins::kMathCbrt, 1, true);
+    SimpleInstallFunction(math, "expm1", Builtins::kMathExpm1, 1, true);
     SimpleInstallFunction(math, "clz32", Builtins::kMathClz32, 1, true);
+    SimpleInstallFunction(math, "cos", Builtins::kMathCos, 1, true);
+    Handle<JSFunction> math_exp =
+        SimpleInstallFunction(math, "exp", Builtins::kMathExp, 1, true);
+    native_context()->set_math_exp(*math_exp);
     Handle<JSFunction> math_floor =
         SimpleInstallFunction(math, "floor", Builtins::kMathFloor, 1, true);
     native_context()->set_math_floor(*math_floor);
     SimpleInstallFunction(math, "fround", Builtins::kMathFround, 1, true);
     SimpleInstallFunction(math, "imul", Builtins::kMathImul, 2, true);
+    Handle<JSFunction> math_log =
+        SimpleInstallFunction(math, "log", Builtins::kMathLog, 1, true);
+    native_context()->set_math_log(*math_log);
+    SimpleInstallFunction(math, "log1p", Builtins::kMathLog1p, 1, true);
+    SimpleInstallFunction(math, "log2", Builtins::kMathLog2, 1, true);
+    SimpleInstallFunction(math, "log10", Builtins::kMathLog10, 1, true);
     SimpleInstallFunction(math, "max", Builtins::kMathMax, 2, false);
     SimpleInstallFunction(math, "min", Builtins::kMathMin, 2, false);
     SimpleInstallFunction(math, "round", Builtins::kMathRound, 1, true);
+    SimpleInstallFunction(math, "sin", Builtins::kMathSin, 1, true);
     Handle<JSFunction> math_sqrt =
         SimpleInstallFunction(math, "sqrt", Builtins::kMathSqrt, 1, true);
     native_context()->set_math_sqrt(*math_sqrt);
+    SimpleInstallFunction(math, "tan", Builtins::kMathTan, 1, true);
     SimpleInstallFunction(math, "trunc", Builtins::kMathTrunc, 1, true);
+
+    // Install math constants.
+    double const kE = base::ieee754::exp(1.0);
+    JSObject::AddProperty(
+        math, factory->NewStringFromAsciiChecked("E"), factory->NewNumber(kE),
+        static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY));
+    JSObject::AddProperty(
+        math, factory->NewStringFromAsciiChecked("LN10"),
+        factory->NewNumber(base::ieee754::log(10.0)),
+        static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY));
+    JSObject::AddProperty(
+        math, factory->NewStringFromAsciiChecked("LN2"),
+        factory->NewNumber(base::ieee754::log(2.0)),
+        static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY));
+    JSObject::AddProperty(
+        math, factory->NewStringFromAsciiChecked("LOG10E"),
+        factory->NewNumber(base::ieee754::log10(kE)),
+        static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY));
+    JSObject::AddProperty(
+        math, factory->NewStringFromAsciiChecked("LOG2E"),
+        factory->NewNumber(base::ieee754::log2(kE)),
+        static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY));
   }
 
   {  // -- A r r a y B u f f e r
@@ -1546,6 +1733,36 @@
                                      Context::ARRAY_BUFFER_FUN_INDEX);
   }
 
+  {  // -- T y p e d A r r a y
+    Handle<JSObject> prototype =
+        factory->NewJSObject(isolate->object_function(), TENURED);
+    native_context()->set_typed_array_prototype(*prototype);
+
+    Handle<JSFunction> typed_array_fun =
+        CreateFunction(isolate, factory->InternalizeUtf8String("TypedArray"),
+                       JS_TYPED_ARRAY_TYPE, JSTypedArray::kSize, prototype,
+                       Builtins::kIllegal);
+
+    // Install the "constructor" property on the {prototype}.
+    JSObject::AddProperty(prototype, factory->constructor_string(),
+                          typed_array_fun, DONT_ENUM);
+    native_context()->set_typed_array_function(*typed_array_fun);
+
+    // Install the "buffer", "byteOffset", "byteLength" and "length"
+    // getters on the {prototype}.
+    SimpleInstallGetter(prototype, factory->buffer_string(),
+                        Builtins::kTypedArrayPrototypeBuffer, false);
+    SimpleInstallGetter(prototype, factory->byte_length_string(),
+                        Builtins::kTypedArrayPrototypeByteLength, true,
+                        kTypedArrayByteLength);
+    SimpleInstallGetter(prototype, factory->byte_offset_string(),
+                        Builtins::kTypedArrayPrototypeByteOffset, true,
+                        kTypedArrayByteOffset);
+    SimpleInstallGetter(prototype, factory->length_string(),
+                        Builtins::kTypedArrayPrototypeLength, true,
+                        kTypedArrayLength);
+  }
+
   {  // -- T y p e d A r r a y s
 #define INSTALL_TYPED_ARRAY(Type, type, TYPE, ctype, size)             \
   {                                                                    \
@@ -1556,17 +1773,43 @@
   }
     TYPED_ARRAYS(INSTALL_TYPED_ARRAY)
 #undef INSTALL_TYPED_ARRAY
+  }
 
-    Handle<JSFunction> data_view_fun = InstallFunction(
-        global, "DataView", JS_DATA_VIEW_TYPE,
-        JSDataView::kSizeWithInternalFields,
-        isolate->initial_object_prototype(), Builtins::kDataViewConstructor);
+  {  // -- D a t a V i e w
+    Handle<JSObject> prototype =
+        factory->NewJSObject(isolate->object_function(), TENURED);
+    Handle<JSFunction> data_view_fun =
+        InstallFunction(global, "DataView", JS_DATA_VIEW_TYPE,
+                        JSDataView::kSizeWithInternalFields, prototype,
+                        Builtins::kDataViewConstructor);
     InstallWithIntrinsicDefaultProto(isolate, data_view_fun,
                                      Context::DATA_VIEW_FUN_INDEX);
     data_view_fun->shared()->set_construct_stub(
         *isolate->builtins()->DataViewConstructor_ConstructStub());
     data_view_fun->shared()->set_length(3);
     data_view_fun->shared()->DontAdaptArguments();
+
+    // Install the @@toStringTag property on the {prototype}.
+    JSObject::AddProperty(
+        prototype, factory->to_string_tag_symbol(),
+        factory->NewStringFromAsciiChecked("DataView"),
+        static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
+
+    // Install the "constructor" property on the {prototype}.
+    JSObject::AddProperty(prototype, factory->constructor_string(),
+                          data_view_fun, DONT_ENUM);
+
+    // Install the "buffer", "byteOffset" and "byteLength" getters
+    // on the {prototype}.
+    SimpleInstallGetter(prototype, factory->buffer_string(),
+                        Builtins::kDataViewPrototypeGetBuffer, false,
+                        kDataViewBuffer);
+    SimpleInstallGetter(prototype, factory->byte_length_string(),
+                        Builtins::kDataViewPrototypeGetByteLength, false,
+                        kDataViewByteLength);
+    SimpleInstallGetter(prototype, factory->byte_offset_string(),
+                        Builtins::kDataViewPrototypeGetByteOffset, false,
+                        kDataViewByteOffset);
   }
 
   {  // -- M a p
@@ -1702,18 +1945,21 @@
         static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
     Map::EnsureDescriptorSlack(map, 2);
 
+    Handle<AccessorInfo> bound_length =
+        Accessors::BoundFunctionLengthInfo(isolate, roc_attribs);
     {  // length
-      DataDescriptor d(factory->length_string(), JSBoundFunction::kLengthIndex,
-                       roc_attribs, Representation::Tagged());
+      AccessorConstantDescriptor d(factory->length_string(), bound_length,
+                                   roc_attribs);
       map->AppendDescriptor(&d);
     }
-    {  // name
-      DataDescriptor d(factory->name_string(), JSBoundFunction::kNameIndex,
-                       roc_attribs, Representation::Tagged());
+    Handle<AccessorInfo> bound_name =
+        Accessors::BoundFunctionNameInfo(isolate, roc_attribs);
+    {  // length
+      AccessorConstantDescriptor d(factory->name_string(), bound_name,
+                                   roc_attribs);
       map->AppendDescriptor(&d);
     }
-
-    map->SetInObjectProperties(2);
+    map->SetInObjectProperties(0);
     native_context()->set_bound_function_without_constructor_map(*map);
 
     map = Map::Copy(map, "IsConstructor");
@@ -1732,7 +1978,7 @@
     function->shared()->set_instance_class_name(*arguments_string);
 
     Handle<Map> map = factory->NewMap(
-        JS_OBJECT_TYPE, JSSloppyArgumentsObject::kSize, FAST_ELEMENTS);
+        JS_ARGUMENTS_TYPE, JSSloppyArgumentsObject::kSize, FAST_ELEMENTS);
     // Create the descriptor array for the arguments object.
     Map::EnsureDescriptorSlack(map, 2);
 
@@ -1792,7 +2038,7 @@
 
     // Create the map. Allocate one in-object field for length.
     Handle<Map> map = factory->NewMap(
-        JS_OBJECT_TYPE, JSStrictArgumentsObject::kSize, FAST_ELEMENTS);
+        JS_ARGUMENTS_TYPE, JSStrictArgumentsObject::kSize, FAST_ELEMENTS);
     // Create the descriptor array for the arguments object.
     Map::EnsureDescriptorSlack(map, 3);
 
@@ -1862,13 +2108,20 @@
   }
 }  // NOLINT(readability/fn_size)
 
-
 void Genesis::InstallTypedArray(const char* name, ElementsKind elements_kind,
                                 Handle<JSFunction>* fun) {
   Handle<JSObject> global = Handle<JSObject>(native_context()->global_object());
-  Handle<JSFunction> result = InstallFunction(
-      global, name, JS_TYPED_ARRAY_TYPE, JSTypedArray::kSize,
-      isolate()->initial_object_prototype(), Builtins::kIllegal);
+
+  Handle<JSObject> typed_array_prototype =
+      Handle<JSObject>(isolate()->typed_array_prototype());
+  Handle<JSFunction> typed_array_function =
+      Handle<JSFunction>(isolate()->typed_array_function());
+
+  Handle<JSObject> prototype =
+      factory()->NewJSObject(isolate()->object_function(), TENURED);
+  Handle<JSFunction> result =
+      InstallFunction(global, name, JS_TYPED_ARRAY_TYPE, JSTypedArray::kSize,
+                      prototype, Builtins::kIllegal);
 
   Handle<Map> initial_map = isolate()->factory()->NewMap(
       JS_TYPED_ARRAY_TYPE,
@@ -1876,6 +2129,14 @@
       elements_kind);
   JSFunction::SetInitialMap(result, initial_map,
                             handle(initial_map->prototype(), isolate()));
+
+  CHECK(JSObject::SetPrototype(result, typed_array_function, false,
+                               Object::DONT_THROW)
+            .FromJust());
+
+  CHECK(JSObject::SetPrototype(prototype, typed_array_prototype, false,
+                               Object::DONT_THROW)
+            .FromJust());
   *fun = result;
 }
 
@@ -1887,6 +2148,7 @@
   HARMONY_STAGED(FEATURE_INITIALIZE_GLOBAL)
   HARMONY_SHIPPING(FEATURE_INITIALIZE_GLOBAL)
   FEATURE_INITIALIZE_GLOBAL(promise_extra, "")
+  FEATURE_INITIALIZE_GLOBAL(intl_extra, "")
 #undef FEATURE_INITIALIZE_GLOBAL
 }
 
@@ -2098,8 +2360,6 @@
       JSObject::AddProperty(global, natives_key, utils, DONT_ENUM);
       break;
     }
-    case THIN_CONTEXT:
-      break;
   }
 
   // The utils object can be removed for cases that reach this point.
@@ -2169,6 +2429,13 @@
         isolate, generator_function_function,
         Context::GENERATOR_FUNCTION_FUNCTION_INDEX);
 
+    SetObjectPrototype(generator_function_function,
+                       isolate->function_function());
+    JSObject::AddProperty(
+        generator_function_prototype, factory->constructor_string(),
+        generator_function_function,
+        static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
+
     native_context->sloppy_generator_function_map()->SetConstructor(
         *generator_function_function);
     native_context->strict_generator_function_map()->SetConstructor(
@@ -2341,6 +2608,49 @@
           script_is_embedder_debug_script, attribs);
       script_map->AppendDescriptor(&d);
     }
+
+    {
+      // TODO(mvstanton): Remove this when MathSinh, MathCosh and MathTanh are
+      // no longer implemented in fdlibm.js.
+      SimpleInstallFunction(container, "MathExpm1", Builtins::kMathExpm1, 1,
+                            true);
+    }
+
+    {
+      PrototypeIterator iter(native_context->sloppy_async_function_map());
+      Handle<JSObject> async_function_prototype(iter.GetCurrent<JSObject>());
+
+      static const bool kUseStrictFunctionMap = true;
+      Handle<JSFunction> async_function_constructor = InstallFunction(
+          container, "AsyncFunction", JS_FUNCTION_TYPE, JSFunction::kSize,
+          async_function_prototype, Builtins::kAsyncFunctionConstructor,
+          kUseStrictFunctionMap);
+      async_function_constructor->set_prototype_or_initial_map(
+          native_context->sloppy_async_function_map());
+      async_function_constructor->shared()->DontAdaptArguments();
+      async_function_constructor->shared()->set_construct_stub(
+          *isolate->builtins()->AsyncFunctionConstructor());
+      async_function_constructor->shared()->set_length(1);
+      InstallWithIntrinsicDefaultProto(isolate, async_function_constructor,
+                                       Context::ASYNC_FUNCTION_FUNCTION_INDEX);
+
+      JSObject::AddProperty(
+          async_function_prototype, factory->constructor_string(),
+          async_function_constructor,
+          static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
+
+      JSFunction::SetPrototype(async_function_constructor,
+                               async_function_prototype);
+
+      Handle<JSFunction> async_function_next =
+          SimpleInstallFunction(container, "AsyncFunctionNext",
+                                Builtins::kGeneratorPrototypeNext, 1, true);
+      Handle<JSFunction> async_function_throw =
+          SimpleInstallFunction(container, "AsyncFunctionThrow",
+                                Builtins::kGeneratorPrototypeThrow, 1, true);
+      async_function_next->shared()->set_native(false);
+      async_function_throw->shared()->set_native(false);
+    }
   }
 }
 
@@ -2357,7 +2667,7 @@
                           isolate->factory()->ToBoolean(FLAG), NONE); \
   }
 
-  INITIALIZE_FLAG(FLAG_harmony_species)
+  INITIALIZE_FLAG(FLAG_intl_extra)
 
 #undef INITIALIZE_FLAG
 }
@@ -2366,24 +2676,24 @@
 #define EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(id) \
   void Genesis::InitializeGlobal_##id() {}
 
-EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_sloppy)
-EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_sloppy_function)
-EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_sloppy_let)
-EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_object_observe)
-EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_unicode_regexps)
 EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_do_expressions)
-EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_iterator_close)
-EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_regexp_exec)
+EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_for_in)
 EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_regexp_lookbehind)
+EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_regexp_named_captures)
 EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_regexp_property)
-EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_function_name)
 EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_function_sent)
 EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(promise_extra)
+EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(intl_extra)
+EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_explicit_tailcalls)
 EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_tailcalls)
-EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_instanceof)
 EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_restrictive_declarations)
 EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_exponentiation_operator)
 EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_string_padding)
+#ifdef V8_I18N_SUPPORT
+EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(icu_case_mapping)
+#endif
+EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_async_await)
+EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_restrictive_generators)
 
 void InstallPublicSymbol(Factory* factory, Handle<Context> native_context,
                          const char* name, Handle<Symbol> value) {
@@ -2399,26 +2709,30 @@
 }
 
 
-void Genesis::InitializeGlobal_harmony_regexp_subclass() {
-  if (!FLAG_harmony_regexp_subclass) return;
-  InstallPublicSymbol(factory(), native_context(), "match",
-                      factory()->match_symbol());
-  InstallPublicSymbol(factory(), native_context(), "replace",
-                      factory()->replace_symbol());
-  InstallPublicSymbol(factory(), native_context(), "search",
-                      factory()->search_symbol());
-  InstallPublicSymbol(factory(), native_context(), "split",
-                      factory()->split_symbol());
-}
-
-
 void Genesis::InitializeGlobal_harmony_sharedarraybuffer() {
   if (!FLAG_harmony_sharedarraybuffer) return;
 
   Handle<JSGlobalObject> global(native_context()->global_object());
+  Isolate* isolate = global->GetIsolate();
+  Factory* factory = isolate->factory();
+
   Handle<JSFunction> shared_array_buffer_fun =
       InstallArrayBuffer(global, "SharedArrayBuffer");
   native_context()->set_shared_array_buffer_fun(*shared_array_buffer_fun);
+
+  Handle<String> name = factory->InternalizeUtf8String("Atomics");
+  Handle<JSFunction> cons = factory->NewFunction(name);
+  JSFunction::SetInstancePrototype(
+      cons,
+      Handle<Object>(native_context()->initial_object_prototype(), isolate));
+  Handle<JSObject> atomics_object = factory->NewJSObject(cons, TENURED);
+  DCHECK(atomics_object->IsJSObject());
+  JSObject::AddProperty(global, name, atomics_object, DONT_ENUM);
+
+  SimpleInstallFunction(atomics_object, factory->InternalizeUtf8String("load"),
+                        Builtins::kAtomicsLoad, 2, true);
+  SimpleInstallFunction(atomics_object, factory->InternalizeUtf8String("store"),
+                        Builtins::kAtomicsStore, 3, true);
 }
 
 
@@ -2533,13 +2847,6 @@
 }
 
 
-void Genesis::InitializeGlobal_harmony_species() {
-  if (!FLAG_harmony_species) return;
-  InstallPublicSymbol(factory(), native_context(), "species",
-                      factory()->species_symbol());
-}
-
-
 Handle<JSFunction> Genesis::InstallInternalArray(Handle<JSObject> target,
                                                  const char* name,
                                                  ElementsKind elements_kind) {
@@ -2606,9 +2913,6 @@
   DCHECK_EQ(builtin_index, Natives::GetIndex("runtime"));
   if (!Bootstrapper::CompileBuiltin(isolate(), builtin_index++)) return false;
 
-  // A thin context is ready at this point.
-  if (context_type == THIN_CONTEXT) return true;
-
   {
     // Builtin function for OpaqueReference -- a JSValue-based object,
     // that keeps its field isolated from JavaScript code. It may store
@@ -2657,6 +2961,14 @@
   native_context()->set_object_function_prototype_map(
       HeapObject::cast(object_function->initial_map()->prototype())->map());
 
+  // Set up the map for Object.create(null) instances.
+  Handle<Map> object_with_null_prototype_map =
+      Map::CopyInitialMap(handle(object_function->initial_map(), isolate()));
+  Map::SetPrototype(object_with_null_prototype_map,
+                    isolate()->factory()->null_value());
+  native_context()->set_object_with_null_prototype_map(
+      *object_with_null_prototype_map);
+
   // Store the map for the %StringPrototype% after the natives has been compiled
   // and the String function has been set up.
   Handle<JSFunction> string_function(native_context()->string_function());
@@ -2665,11 +2977,38 @@
   native_context()->set_string_function_prototype_map(
       HeapObject::cast(string_function->initial_map()->prototype())->map());
 
+  Handle<JSGlobalObject> global_object =
+      handle(native_context()->global_object());
+
+  // Install Global.decodeURI.
+  SimpleInstallFunction(global_object, "decodeURI", Builtins::kGlobalDecodeURI,
+                        1, false);
+
+  // Install Global.decodeURIComponent.
+  SimpleInstallFunction(global_object, "decodeURIComponent",
+                        Builtins::kGlobalDecodeURIComponent, 1, false);
+
+  // Install Global.encodeURI.
+  SimpleInstallFunction(global_object, "encodeURI", Builtins::kGlobalEncodeURI,
+                        1, false);
+
+  // Install Global.encodeURIComponent.
+  SimpleInstallFunction(global_object, "encodeURIComponent",
+                        Builtins::kGlobalEncodeURIComponent, 1, false);
+
+  // Install Global.escape.
+  SimpleInstallFunction(global_object, "escape", Builtins::kGlobalEscape, 1,
+                        false);
+
+  // Install Global.unescape.
+  SimpleInstallFunction(global_object, "unescape", Builtins::kGlobalUnescape, 1,
+                        false);
+
   // Install Global.eval.
   {
-    Handle<JSFunction> eval = SimpleInstallFunction(
-        handle(native_context()->global_object()), factory()->eval_string(),
-        Builtins::kGlobalEval, 1, false);
+    Handle<JSFunction> eval =
+        SimpleInstallFunction(global_object, factory()->eval_string(),
+                              Builtins::kGlobalEval, 1, false);
     native_context()->set_global_eval_fun(*eval);
   }
 
@@ -2712,8 +3051,7 @@
   {
     Handle<String> key = factory()->Promise_string();
     Handle<JSFunction> function = Handle<JSFunction>::cast(
-        JSReceiver::GetProperty(handle(native_context()->global_object()), key)
-            .ToHandleChecked());
+        JSReceiver::GetProperty(global_object, key).ToHandleChecked());
     JSFunction::EnsureHasInitialMap(function);
     function->initial_map()->set_instance_type(JS_PROMISE_TYPE);
     function->shared()->set_construct_stub(
@@ -2724,37 +3062,6 @@
 
   InstallBuiltinFunctionIds();
 
-  // Also install builtin function ids to some generator object methods. These
-  // three methods use the three resume operations (Runtime_GeneratorNext,
-  // Runtime_GeneratorReturn, Runtime_GeneratorThrow) respectively. Those
-  // operations are not supported by Crankshaft, TurboFan, nor Ignition.
-  {
-    Handle<JSObject> generator_object_prototype(JSObject::cast(
-        native_context()->generator_object_prototype_map()->prototype()));
-
-    {  // GeneratorObject.prototype.next
-      Handle<String> key = factory()->next_string();
-      Handle<JSFunction> function = Handle<JSFunction>::cast(
-          JSReceiver::GetProperty(generator_object_prototype, key)
-              .ToHandleChecked());
-      function->shared()->set_builtin_function_id(kGeneratorObjectNext);
-    }
-    {  // GeneratorObject.prototype.return
-      Handle<String> key = factory()->NewStringFromAsciiChecked("return");
-      Handle<JSFunction> function = Handle<JSFunction>::cast(
-          JSReceiver::GetProperty(generator_object_prototype, key)
-              .ToHandleChecked());
-      function->shared()->set_builtin_function_id(kGeneratorObjectReturn);
-    }
-    {  // GeneratorObject.prototype.throw
-      Handle<String> key = factory()->throw_string();
-      Handle<JSFunction> function = Handle<JSFunction>::cast(
-          JSReceiver::GetProperty(generator_object_prototype, key)
-              .ToHandleChecked());
-      function->shared()->set_builtin_function_id(kGeneratorObjectThrow);
-    }
-  }
-
   // Create a map for accessor property descriptors (a variant of JSObject
   // that predefines four properties get, set, configurable and enumerable).
   {
@@ -2935,33 +3242,22 @@
 
 
 bool Genesis::InstallExperimentalNatives() {
-  static const char* harmony_iterator_close_natives[] = {nullptr};
-  static const char* harmony_sloppy_natives[] = {nullptr};
-  static const char* harmony_sloppy_function_natives[] = {nullptr};
-  static const char* harmony_sloppy_let_natives[] = {nullptr};
-  static const char* harmony_species_natives[] = {"native harmony-species.js",
-                                                  nullptr};
+  static const char* harmony_explicit_tailcalls_natives[] = {nullptr};
   static const char* harmony_tailcalls_natives[] = {nullptr};
-  static const char* harmony_unicode_regexps_natives[] = {
-      "native harmony-unicode-regexps.js", nullptr};
-  static const char* harmony_object_observe_natives[] = {
-      "native harmony-object-observe.js", nullptr};
   static const char* harmony_sharedarraybuffer_natives[] = {
       "native harmony-sharedarraybuffer.js", "native harmony-atomics.js", NULL};
   static const char* harmony_simd_natives[] = {"native harmony-simd.js",
                                                nullptr};
   static const char* harmony_do_expressions_natives[] = {nullptr};
-  static const char* harmony_regexp_exec_natives[] = {
-      "native harmony-regexp-exec.js", nullptr};
-  static const char* harmony_regexp_subclass_natives[] = {nullptr};
+  static const char* harmony_for_in_natives[] = {nullptr};
   static const char* harmony_regexp_lookbehind_natives[] = {nullptr};
-  static const char* harmony_instanceof_natives[] = {nullptr};
   static const char* harmony_restrictive_declarations_natives[] = {nullptr};
+  static const char* harmony_regexp_named_captures_natives[] = {nullptr};
   static const char* harmony_regexp_property_natives[] = {nullptr};
-  static const char* harmony_function_name_natives[] = {nullptr};
   static const char* harmony_function_sent_natives[] = {nullptr};
   static const char* promise_extra_natives[] = {"native promise-extra.js",
                                                 nullptr};
+  static const char* intl_extra_natives[] = {"native intl-extra.js", nullptr};
   static const char* harmony_object_values_entries_natives[] = {nullptr};
   static const char* harmony_object_own_property_descriptors_natives[] = {
       nullptr};
@@ -2969,6 +3265,13 @@
   static const char* harmony_exponentiation_operator_natives[] = {nullptr};
   static const char* harmony_string_padding_natives[] = {
       "native harmony-string-padding.js", nullptr};
+#ifdef V8_I18N_SUPPORT
+  static const char* icu_case_mapping_natives[] = {"native icu-case-mapping.js",
+                                                   nullptr};
+#endif
+  static const char* harmony_async_await_natives[] = {
+      "native harmony-async-await.js", nullptr};
+  static const char* harmony_restrictive_generators_natives[] = {nullptr};
 
   for (int i = ExperimentalNatives::GetDebuggerCount();
        i < ExperimentalNatives::GetBuiltinsCount(); i++) {
@@ -2987,6 +3290,7 @@
     HARMONY_INPROGRESS(INSTALL_EXPERIMENTAL_NATIVES);
     HARMONY_STAGED(INSTALL_EXPERIMENTAL_NATIVES);
     HARMONY_SHIPPING(INSTALL_EXPERIMENTAL_NATIVES);
+    INSTALL_EXPERIMENTAL_NATIVES(intl_extra, "");
     INSTALL_EXPERIMENTAL_NATIVES(promise_extra, "");
 #undef INSTALL_EXPERIMENTAL_NATIVES
   }
@@ -3154,12 +3458,12 @@
   return v8::internal::ComputePointerHash(extension);
 }
 
-
-Genesis::ExtensionStates::ExtensionStates() : map_(HashMap::PointersMatch, 8) {}
+Genesis::ExtensionStates::ExtensionStates()
+    : map_(base::HashMap::PointersMatch, 8) {}
 
 Genesis::ExtensionTraversalState Genesis::ExtensionStates::get_state(
     RegisteredExtension* extension) {
-  i::HashMap::Entry* entry = map_.Lookup(extension, Hash(extension));
+  base::HashMap::Entry* entry = map_.Lookup(extension, Hash(extension));
   if (entry == NULL) {
     return UNVISITED;
   }
@@ -3179,17 +3483,20 @@
   Isolate* isolate = native_context->GetIsolate();
   ExtensionStates extension_states;  // All extensions have state UNVISITED.
   return InstallAutoExtensions(isolate, &extension_states) &&
-      (!FLAG_expose_free_buffer ||
-       InstallExtension(isolate, "v8/free-buffer", &extension_states)) &&
-      (!FLAG_expose_gc ||
-       InstallExtension(isolate, "v8/gc", &extension_states)) &&
-      (!FLAG_expose_externalize_string ||
-       InstallExtension(isolate, "v8/externalize", &extension_states)) &&
-      (!FLAG_track_gc_object_stats ||
-       InstallExtension(isolate, "v8/statistics", &extension_states)) &&
-      (!FLAG_expose_trigger_failure ||
-       InstallExtension(isolate, "v8/trigger-failure", &extension_states)) &&
-      InstallRequestedExtensions(isolate, extensions, &extension_states);
+         (!FLAG_expose_free_buffer ||
+          InstallExtension(isolate, "v8/free-buffer", &extension_states)) &&
+         (!FLAG_expose_gc ||
+          InstallExtension(isolate, "v8/gc", &extension_states)) &&
+         (!FLAG_expose_externalize_string ||
+          InstallExtension(isolate, "v8/externalize", &extension_states)) &&
+         (!FLAG_track_gc_object_stats ||
+          InstallExtension(isolate, "v8/statistics", &extension_states)) &&
+         (!FLAG_expose_trigger_failure ||
+          InstallExtension(isolate, "v8/trigger-failure", &extension_states)) &&
+         (!(FLAG_ignition && FLAG_trace_ignition_dispatches) ||
+          InstallExtension(isolate, "v8/ignition-statistics",
+                           &extension_states)) &&
+         InstallRequestedExtensions(isolate, extensions, &extension_states);
 }
 
 
@@ -3293,7 +3600,7 @@
     // Configure the global object.
     Handle<FunctionTemplateInfo> proxy_constructor(
         FunctionTemplateInfo::cast(global_proxy_data->constructor()));
-    if (!proxy_constructor->prototype_template()->IsUndefined()) {
+    if (!proxy_constructor->prototype_template()->IsUndefined(isolate())) {
       Handle<ObjectTemplateInfo> global_object_data(
           ObjectTemplateInfo::cast(proxy_constructor->prototype_template()));
       if (!ConfigureApiObject(global_object, global_object_data)) return false;
@@ -3389,7 +3696,7 @@
     int capacity = properties->Capacity();
     for (int i = 0; i < capacity; i++) {
       Object* raw_key(properties->KeyAt(i));
-      if (properties->IsKey(raw_key)) {
+      if (properties->IsKey(isolate(), raw_key)) {
         DCHECK(raw_key->IsName());
         // If the property is already there we skip it.
         Handle<Name> key(Name::cast(raw_key));
@@ -3400,7 +3707,7 @@
         DCHECK(properties->ValueAt(i)->IsPropertyCell());
         Handle<PropertyCell> cell(PropertyCell::cast(properties->ValueAt(i)));
         Handle<Object> value(cell->value(), isolate());
-        if (value->IsTheHole()) continue;
+        if (value->IsTheHole(isolate())) continue;
         PropertyDetails details = cell->property_details();
         DCHECK_EQ(kData, details.kind());
         JSObject::AddProperty(to, key, value, details.attributes());
@@ -3412,7 +3719,7 @@
     int capacity = properties->Capacity();
     for (int i = 0; i < capacity; i++) {
       Object* raw_key(properties->KeyAt(i));
-      if (properties->IsKey(raw_key)) {
+      if (properties->IsKey(isolate(), raw_key)) {
         DCHECK(raw_key->IsName());
         // If the property is already there we skip it.
         Handle<Name> key(Name::cast(raw_key));
@@ -3423,7 +3730,7 @@
         Handle<Object> value = Handle<Object>(properties->ValueAt(i),
                                               isolate());
         DCHECK(!value->IsCell());
-        DCHECK(!value->IsTheHole());
+        DCHECK(!value->IsTheHole(isolate()));
         PropertyDetails details = properties->DetailsAt(i);
         DCHECK_EQ(kData, details.kind());
         JSObject::AddProperty(to, key, value, details.attributes());
@@ -3500,7 +3807,7 @@
                  MaybeHandle<JSGlobalProxy> maybe_global_proxy,
                  v8::Local<v8::ObjectTemplate> global_proxy_template,
                  v8::ExtensionConfiguration* extensions,
-                 GlobalContextType context_type)
+                 size_t context_snapshot_index, GlobalContextType context_type)
     : isolate_(isolate), active_(isolate->bootstrapper()) {
   NoTrackDoubleFieldsForSerializerScope disable_scope(isolate);
   result_ = Handle<Context>::null();
@@ -3529,7 +3836,8 @@
   // a snapshot. Otherwise we have to build the context from scratch.
   // Also create a context from scratch to expose natives, if required by flag.
   if (!isolate->initialized_from_snapshot() ||
-      !Snapshot::NewContextFromSnapshot(isolate, global_proxy)
+      !Snapshot::NewContextFromSnapshot(isolate, global_proxy,
+                                        context_snapshot_index)
            .ToHandle(&native_context_)) {
     native_context_ = Handle<Context>();
   }
@@ -3559,7 +3867,8 @@
     CreateRoots();
     Handle<JSFunction> empty_function = CreateEmptyFunction(isolate);
     CreateStrictModeFunctionMaps(empty_function);
-    CreateIteratorMaps();
+    CreateIteratorMaps(empty_function);
+    CreateAsyncFunctionMaps(empty_function);
     Handle<JSGlobalObject> global_object =
         CreateNewGlobals(global_proxy_template, global_proxy);
     HookUpGlobalProxy(global_object, global_proxy);
@@ -3570,10 +3879,9 @@
 
     MakeFunctionInstancePrototypeWritable();
 
-    if (context_type != THIN_CONTEXT) {
-      if (!InstallExtraNatives()) return;
-      if (!ConfigureGlobalObjects(global_proxy_template)) return;
-    }
+    if (!InstallExtraNatives()) return;
+    if (!ConfigureGlobalObjects(global_proxy_template)) return;
+
     isolate->counters()->contexts_created_from_scratch()->Increment();
     // Re-initialize the counter because it got incremented during snapshot
     // creation.
diff --git a/src/bootstrapper.h b/src/bootstrapper.h
index d1bf201..66a3d8a 100644
--- a/src/bootstrapper.h
+++ b/src/bootstrapper.h
@@ -61,7 +61,7 @@
   DISALLOW_COPY_AND_ASSIGN(SourceCodeCache);
 };
 
-enum GlobalContextType { FULL_CONTEXT, THIN_CONTEXT, DEBUG_CONTEXT };
+enum GlobalContextType { FULL_CONTEXT, DEBUG_CONTEXT };
 
 // The Boostrapper is the public interface for creating a JavaScript global
 // context.
@@ -79,7 +79,7 @@
   Handle<Context> CreateEnvironment(
       MaybeHandle<JSGlobalProxy> maybe_global_proxy,
       v8::Local<v8::ObjectTemplate> global_object_template,
-      v8::ExtensionConfiguration* extensions,
+      v8::ExtensionConfiguration* extensions, size_t context_snapshot_index,
       GlobalContextType context_type = FULL_CONTEXT);
 
   // Detach the environment from its outer global object.
@@ -136,6 +136,7 @@
   static v8::Extension* externalize_string_extension_;
   static v8::Extension* statistics_extension_;
   static v8::Extension* trigger_failure_extension_;
+  static v8::Extension* ignition_statistics_extension_;
 
   DISALLOW_COPY_AND_ASSIGN(Bootstrapper);
 };
diff --git a/src/builtins.cc b/src/builtins.cc
index 9c3ff59..24abb72 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -4,13 +4,14 @@
 
 #include "src/builtins.h"
 
-#include "src/api.h"
 #include "src/api-arguments.h"
 #include "src/api-natives.h"
+#include "src/api.h"
+#include "src/base/ieee754.h"
 #include "src/base/once.h"
 #include "src/bootstrapper.h"
 #include "src/code-factory.h"
-#include "src/compiler/code-stub-assembler.h"
+#include "src/code-stub-assembler.h"
 #include "src/dateparser-inl.h"
 #include "src/elements.h"
 #include "src/frames-inl.h"
@@ -18,11 +19,13 @@
 #include "src/ic/handler-compiler.h"
 #include "src/ic/ic.h"
 #include "src/isolate-inl.h"
+#include "src/json-parser.h"
+#include "src/json-stringifier.h"
 #include "src/messages.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/property-descriptor.h"
 #include "src/prototype.h"
 #include "src/string-builder.h"
+#include "src/uri.h"
 #include "src/vm-state-inl.h"
 
 namespace v8 {
@@ -31,7 +34,6 @@
 namespace {
 
 // Arguments object passed to C++ builtins.
-template <BuiltinExtraArguments extra_args>
 class BuiltinArguments : public Arguments {
  public:
   BuiltinArguments(int length, Object** arguments)
@@ -41,12 +43,12 @@
   }
 
   Object*& operator[] (int index) {
-    DCHECK(index < length());
+    DCHECK_LT(index, length());
     return Arguments::operator[](index);
   }
 
   template <class S> Handle<S> at(int index) {
-    DCHECK(index < length());
+    DCHECK_LT(index, length());
     return Arguments::at<S>(index);
   }
 
@@ -62,70 +64,19 @@
   }
 
   template <class S>
-  Handle<S> target();
-  Handle<HeapObject> new_target();
+  Handle<S> target() {
+    return Arguments::at<S>(Arguments::length() - 2);
+  }
+  Handle<HeapObject> new_target() {
+    return Arguments::at<HeapObject>(Arguments::length() - 1);
+  }
 
   // Gets the total number of arguments including the receiver (but
   // excluding extra arguments).
-  int length() const;
+  int length() const { return Arguments::length() - 2; }
 };
 
 
-// Specialize BuiltinArguments for the extra arguments.
-
-template <>
-int BuiltinArguments<BuiltinExtraArguments::kNone>::length() const {
-  return Arguments::length();
-}
-
-template <>
-int BuiltinArguments<BuiltinExtraArguments::kTarget>::length() const {
-  return Arguments::length() - 1;
-}
-
-template <>
-template <class S>
-Handle<S> BuiltinArguments<BuiltinExtraArguments::kTarget>::target() {
-  return Arguments::at<S>(Arguments::length() - 1);
-}
-
-template <>
-int BuiltinArguments<BuiltinExtraArguments::kNewTarget>::length() const {
-  return Arguments::length() - 1;
-}
-
-template <>
-Handle<HeapObject>
-BuiltinArguments<BuiltinExtraArguments::kNewTarget>::new_target() {
-  return Arguments::at<HeapObject>(Arguments::length() - 1);
-}
-
-template <>
-int BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::length()
-    const {
-  return Arguments::length() - 2;
-}
-
-template <>
-template <class S>
-Handle<S>
-BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::target() {
-  return Arguments::at<S>(Arguments::length() - 2);
-}
-
-template <>
-Handle<HeapObject>
-BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::new_target() {
-  return Arguments::at<HeapObject>(Arguments::length() - 1);
-}
-
-
-#define DEF_ARG_TYPE(name, spec) \
-  typedef BuiltinArguments<BuiltinExtraArguments::spec> name##ArgumentsType;
-BUILTIN_LIST_C(DEF_ARG_TYPE)
-#undef DEF_ARG_TYPE
-
-
 // ----------------------------------------------------------------------------
 // Support macro for defining builtins in C++.
 // ----------------------------------------------------------------------------
@@ -138,33 +89,35 @@
 //
 // In the body of the builtin function the arguments can be accessed
 // through the BuiltinArguments object args.
-
-#define BUILTIN(name)                                                          \
-  MUST_USE_RESULT static Object* Builtin_Impl_##name(name##ArgumentsType args, \
-                                                     Isolate* isolate);        \
-  MUST_USE_RESULT static Object* Builtin_##name(                               \
-      int args_length, Object** args_object, Isolate* isolate) {               \
-    Object* value;                                                             \
-    isolate->counters()->runtime_calls()->Increment();                         \
-    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"),                      \
-                 "V8.Builtin_" #name);                                         \
-    name##ArgumentsType args(args_length, args_object);                        \
-    if (FLAG_runtime_call_stats) {                                             \
-      RuntimeCallStats* stats = isolate->counters()->runtime_call_stats();     \
-      RuntimeCallTimerScope timer(isolate, &stats->Builtin_##name);            \
-      value = Builtin_Impl_##name(args, isolate);                              \
-    } else {                                                                   \
-      value = Builtin_Impl_##name(args, isolate);                              \
-    }                                                                          \
-    return value;                                                              \
-  }                                                                            \
-                                                                               \
-  MUST_USE_RESULT static Object* Builtin_Impl_##name(name##ArgumentsType args, \
+// TODO(cbruni): add global flag to check whether any tracing events have been
+// enabled.
+#define BUILTIN(name)                                                        \
+  MUST_USE_RESULT static Object* Builtin_Impl_##name(BuiltinArguments args,  \
+                                                     Isolate* isolate);      \
+                                                                             \
+  V8_NOINLINE static Object* Builtin_Impl_Stats_##name(                      \
+      int args_length, Object** args_object, Isolate* isolate) {             \
+    BuiltinArguments args(args_length, args_object);                         \
+    RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::Builtin_##name); \
+    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"),                    \
+                 "V8.Builtin_" #name);                                       \
+    return Builtin_Impl_##name(args, isolate);                               \
+  }                                                                          \
+                                                                             \
+  MUST_USE_RESULT static Object* Builtin_##name(                             \
+      int args_length, Object** args_object, Isolate* isolate) {             \
+    if (FLAG_runtime_call_stats) {                                           \
+      return Builtin_Impl_Stats_##name(args_length, args_object, isolate);   \
+    }                                                                        \
+    BuiltinArguments args(args_length, args_object);                         \
+    return Builtin_Impl_##name(args, isolate);                               \
+  }                                                                          \
+                                                                             \
+  MUST_USE_RESULT static Object* Builtin_Impl_##name(BuiltinArguments args,  \
                                                      Isolate* isolate)
 
 // ----------------------------------------------------------------------------
 
-
 #define CHECK_RECEIVER(Type, name, method)                                  \
   if (!args.receiver()->Is##Type()) {                                       \
     THROW_NEW_ERROR_RETURN_FAILURE(                                         \
@@ -175,8 +128,22 @@
   }                                                                         \
   Handle<Type> name = Handle<Type>::cast(args.receiver())
 
+// Throws a TypeError for {method} if the receiver is not coercible to Object,
+// or converts the receiver to a String otherwise and assigns it to a new var
+// with the given {name}.
+#define TO_THIS_STRING(name, method)                                          \
+  if (args.receiver()->IsNull(isolate) ||                                     \
+      args.receiver()->IsUndefined(isolate)) {                                \
+    THROW_NEW_ERROR_RETURN_FAILURE(                                           \
+        isolate,                                                              \
+        NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,               \
+                     isolate->factory()->NewStringFromAsciiChecked(method))); \
+  }                                                                           \
+  Handle<String> name;                                                        \
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(                                         \
+      isolate, name, Object::ToString(isolate, args.receiver()))
 
-inline bool ClampedToInteger(Object* object, int* out) {
+inline bool ClampedToInteger(Isolate* isolate, Object* object, int* out) {
   // This is an extended version of ECMA-262 7.1.11 handling signed values
   // Try to convert object to a number and clamp values to [kMinInt, kMaxInt]
   if (object->IsSmi()) {
@@ -194,11 +161,11 @@
       *out = static_cast<int>(value);
     }
     return true;
-  } else if (object->IsUndefined() || object->IsNull()) {
+  } else if (object->IsUndefined(isolate) || object->IsNull(isolate)) {
     *out = 0;
     return true;
   } else if (object->IsBoolean()) {
-    *out = object->IsTrue();
+    *out = object->IsTrue(isolate);
     return true;
   }
   return false;
@@ -207,9 +174,14 @@
 
 inline bool GetSloppyArgumentsLength(Isolate* isolate, Handle<JSObject> object,
                                      int* out) {
-  Map* arguments_map = isolate->native_context()->sloppy_arguments_map();
-  if (object->map() != arguments_map) return false;
-  DCHECK(object->HasFastElements());
+  Context* context = *isolate->native_context();
+  Map* map = object->map();
+  if (map != context->sloppy_arguments_map() &&
+      map != context->strict_arguments_map() &&
+      map != context->fast_aliased_arguments_map()) {
+    return false;
+  }
+  DCHECK(object->HasFastElements() || object->HasFastArgumentsElements());
   Object* len_obj = object->InObjectPropertyAt(JSArgumentsObject::kLengthIndex);
   if (!len_obj->IsSmi()) return false;
   *out = Max(0, Smi::cast(len_obj)->value());
@@ -249,8 +221,7 @@
 
 inline bool HasOnlySimpleElements(Isolate* isolate, JSReceiver* receiver) {
   DisallowHeapAllocation no_gc;
-  PrototypeIterator iter(isolate, receiver,
-                         PrototypeIterator::START_AT_RECEIVER);
+  PrototypeIterator iter(isolate, receiver, kStartAtReceiver);
   for (; !iter.IsAtEnd(); iter.Advance()) {
     if (iter.GetCurrent()->IsJSProxy()) return false;
     JSObject* current = iter.GetCurrent<JSObject>();
@@ -263,13 +234,12 @@
 MUST_USE_RESULT
 inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate,
                                                   Handle<Object> receiver,
-                                                  Arguments* args,
+                                                  BuiltinArguments* args,
                                                   int first_added_arg) {
   if (!receiver->IsJSArray()) return false;
   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
   ElementsKind origin_kind = array->GetElementsKind();
   if (IsDictionaryElementsKind(origin_kind)) return false;
-  if (array->map()->is_observed()) return false;
   if (!array->map()->is_extensible()) return false;
   if (args == nullptr) return true;
 
@@ -311,25 +281,18 @@
   return true;
 }
 
-
-MUST_USE_RESULT static Object* CallJsIntrinsic(
-    Isolate* isolate, Handle<JSFunction> function,
-    BuiltinArguments<BuiltinExtraArguments::kNone> args) {
+MUST_USE_RESULT static Object* CallJsIntrinsic(Isolate* isolate,
+                                               Handle<JSFunction> function,
+                                               BuiltinArguments args) {
   HandleScope handleScope(isolate);
   int argc = args.length() - 1;
   ScopedVector<Handle<Object> > argv(argc);
   for (int i = 0; i < argc; ++i) {
     argv[i] = args.at<Object>(i + 1);
   }
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      Execution::Call(isolate,
-                      function,
-                      args.receiver(),
-                      argc,
-                      argv.start()));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(
+      isolate,
+      Execution::Call(isolate, function, args.receiver(), argc, argv.start()));
 }
 
 
@@ -344,11 +307,43 @@
 
 BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); }
 
-void Builtins::Generate_ObjectHasOwnProperty(
-    compiler::CodeStubAssembler* assembler) {
+void Builtins::Generate_ArrayIsArray(CodeStubAssembler* assembler) {
   typedef compiler::Node Node;
-  typedef compiler::CodeStubAssembler::Label Label;
-  typedef compiler::CodeStubAssembler::Variable Variable;
+  typedef CodeStubAssembler::Label Label;
+
+  Node* object = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+
+  Label call_runtime(assembler), return_true(assembler),
+      return_false(assembler);
+
+  assembler->GotoIf(assembler->WordIsSmi(object), &return_false);
+  Node* instance_type = assembler->LoadInstanceType(object);
+
+  assembler->GotoIf(assembler->Word32Equal(
+                        instance_type, assembler->Int32Constant(JS_ARRAY_TYPE)),
+                    &return_true);
+
+  // TODO(verwaest): Handle proxies in-place.
+  assembler->Branch(assembler->Word32Equal(
+                        instance_type, assembler->Int32Constant(JS_PROXY_TYPE)),
+                    &call_runtime, &return_false);
+
+  assembler->Bind(&return_true);
+  assembler->Return(assembler->BooleanConstant(true));
+
+  assembler->Bind(&return_false);
+  assembler->Return(assembler->BooleanConstant(false));
+
+  assembler->Bind(&call_runtime);
+  assembler->Return(
+      assembler->CallRuntime(Runtime::kArrayIsArray, context, object));
+}
+
+void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) {
+  typedef compiler::Node Node;
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
 
   Node* object = assembler->Parameter(0);
   Node* key = assembler->Parameter(1);
@@ -368,153 +363,17 @@
 
   Variable var_index(assembler, MachineRepresentation::kWord32);
 
-  Label if_keyissmi(assembler), if_keyisnotsmi(assembler),
-      keyisindex(assembler);
-  assembler->Branch(assembler->WordIsSmi(key), &if_keyissmi, &if_keyisnotsmi);
-  assembler->Bind(&if_keyissmi);
-  {
-    // Negative smi keys are named properties. Handle in the runtime.
-    Label if_keyispositive(assembler);
-    assembler->Branch(assembler->WordIsPositiveSmi(key), &if_keyispositive,
-                      &call_runtime);
-    assembler->Bind(&if_keyispositive);
+  Label keyisindex(assembler), if_iskeyunique(assembler);
+  assembler->TryToName(key, &keyisindex, &var_index, &if_iskeyunique,
+                       &call_runtime);
 
-    var_index.Bind(assembler->SmiUntag(key));
-    assembler->Goto(&keyisindex);
-  }
-
-  assembler->Bind(&if_keyisnotsmi);
-
-  Node* key_instance_type = assembler->LoadInstanceType(key);
-  Label if_iskeyunique(assembler), if_iskeynotsymbol(assembler);
-  assembler->Branch(
-      assembler->Word32Equal(key_instance_type,
-                             assembler->Int32Constant(SYMBOL_TYPE)),
-      &if_iskeyunique, &if_iskeynotsymbol);
-  assembler->Bind(&if_iskeynotsymbol);
-  {
-    Label if_iskeyinternalized(assembler);
-    Node* bits = assembler->WordAnd(
-        key_instance_type,
-        assembler->Int32Constant(kIsNotStringMask | kIsNotInternalizedMask));
-    assembler->Branch(
-        assembler->Word32Equal(
-            bits, assembler->Int32Constant(kStringTag | kInternalizedTag)),
-        &if_iskeyinternalized, &call_runtime);
-    assembler->Bind(&if_iskeyinternalized);
-
-    // Check whether the key is an array index passed in as string. Handle
-    // uniform with smi keys if so.
-    // TODO(verwaest): Also support non-internalized strings.
-    Node* hash = assembler->LoadNameHash(key);
-    Node* bit = assembler->Word32And(
-        hash, assembler->Int32Constant(internal::Name::kIsNotArrayIndexMask));
-    Label if_isarrayindex(assembler);
-    assembler->Branch(assembler->Word32Equal(bit, assembler->Int32Constant(0)),
-                      &if_isarrayindex, &if_iskeyunique);
-    assembler->Bind(&if_isarrayindex);
-    var_index.Bind(
-        assembler->BitFieldDecode<internal::Name::ArrayIndexValueBits>(hash));
-    assembler->Goto(&keyisindex);
-  }
   assembler->Bind(&if_iskeyunique);
-
-  {
-    Label if_objectissimple(assembler);
-    assembler->Branch(assembler->Int32LessThanOrEqual(
-                          instance_type,
-                          assembler->Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)),
-                      &call_runtime, &if_objectissimple);
-    assembler->Bind(&if_objectissimple);
-  }
-
-  // TODO(verwaest): Perform a dictonary lookup on slow-mode receivers.
-  Node* bit_field3 = assembler->LoadMapBitField3(map);
-  Node* bit = assembler->BitFieldDecode<Map::DictionaryMap>(bit_field3);
-  Label if_isfastmap(assembler);
-  assembler->Branch(assembler->Word32Equal(bit, assembler->Int32Constant(0)),
-                    &if_isfastmap, &call_runtime);
-  assembler->Bind(&if_isfastmap);
-  Node* nof =
-      assembler->BitFieldDecode<Map::NumberOfOwnDescriptorsBits>(bit_field3);
-  // Bail out to the runtime for large numbers of own descriptors. The stub only
-  // does linear search, which becomes too expensive in that case.
-  {
-    static const int32_t kMaxLinear = 256;
-    Label above_max(assembler), below_max(assembler);
-    assembler->Branch(assembler->Int32LessThanOrEqual(
-                          nof, assembler->Int32Constant(kMaxLinear)),
-                      &below_max, &call_runtime);
-    assembler->Bind(&below_max);
-  }
-  Node* descriptors = assembler->LoadMapDescriptors(map);
-
-  Variable var_descriptor(assembler, MachineRepresentation::kWord32);
-  Label loop(assembler, &var_descriptor);
-  var_descriptor.Bind(assembler->Int32Constant(0));
-  assembler->Goto(&loop);
-  assembler->Bind(&loop);
-  {
-    Node* index = var_descriptor.value();
-    Node* offset = assembler->Int32Constant(DescriptorArray::ToKeyIndex(0));
-    Node* factor = assembler->Int32Constant(DescriptorArray::kDescriptorSize);
-    Label if_notdone(assembler);
-    assembler->Branch(assembler->Word32Equal(index, nof), &return_false,
-                      &if_notdone);
-    assembler->Bind(&if_notdone);
-    {
-      Node* array_index =
-          assembler->Int32Add(offset, assembler->Int32Mul(index, factor));
-      Node* current =
-          assembler->LoadFixedArrayElementInt32Index(descriptors, array_index);
-      Label if_unequal(assembler);
-      assembler->Branch(assembler->WordEqual(current, key), &return_true,
-                        &if_unequal);
-      assembler->Bind(&if_unequal);
-
-      var_descriptor.Bind(
-          assembler->Int32Add(index, assembler->Int32Constant(1)));
-      assembler->Goto(&loop);
-    }
-  }
+  assembler->TryHasOwnProperty(object, map, instance_type, key, &return_true,
+                               &return_false, &call_runtime);
 
   assembler->Bind(&keyisindex);
-  {
-    Label if_objectissimple(assembler);
-    assembler->Branch(assembler->Int32LessThanOrEqual(
-                          instance_type, assembler->Int32Constant(
-                                             LAST_CUSTOM_ELEMENTS_RECEIVER)),
-                      &call_runtime, &if_objectissimple);
-    assembler->Bind(&if_objectissimple);
-  }
-
-  Node* index = var_index.value();
-  Node* bit_field2 = assembler->LoadMapBitField2(map);
-  Node* elements_kind =
-      assembler->BitFieldDecode<Map::ElementsKindBits>(bit_field2);
-
-  // TODO(verwaest): Support other elements kinds as well.
-  Label if_isobjectorsmi(assembler);
-  assembler->Branch(
-      assembler->Int32LessThanOrEqual(
-          elements_kind, assembler->Int32Constant(FAST_HOLEY_ELEMENTS)),
-      &if_isobjectorsmi, &call_runtime);
-  assembler->Bind(&if_isobjectorsmi);
-  {
-    Node* elements = assembler->LoadElements(object);
-    Node* length = assembler->LoadFixedArrayBaseLength(elements);
-
-    Label if_iskeyinrange(assembler);
-    assembler->Branch(
-        assembler->Int32LessThan(index, assembler->SmiToWord32(length)),
-        &if_iskeyinrange, &return_false);
-
-    assembler->Bind(&if_iskeyinrange);
-    Node* element = assembler->LoadFixedArrayElementInt32Index(elements, index);
-    Node* the_hole = assembler->LoadRoot(Heap::kTheHoleValueRootIndex);
-    assembler->Branch(assembler->WordEqual(element, the_hole), &return_false,
-                      &return_true);
-  }
+  assembler->TryLookupElement(object, map, instance_type, var_index.value(),
+                              &return_true, &return_false, &call_runtime);
 
   assembler->Bind(&return_true);
   assembler->Return(assembler->BooleanConstant(true));
@@ -529,8 +388,7 @@
 
 namespace {
 
-Object* DoArrayPush(Isolate* isolate,
-                    BuiltinArguments<BuiltinExtraArguments::kNone> args) {
+Object* DoArrayPush(Isolate* isolate, BuiltinArguments args) {
   HandleScope scope(isolate);
   Handle<Object> receiver = args.receiver();
   if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1)) {
@@ -564,8 +422,8 @@
   DCHECK_EQ(2, args.length());
   Arguments* incoming = reinterpret_cast<Arguments*>(args[0]);
   // Rewrap the arguments as builtins arguments.
-  BuiltinArguments<BuiltinExtraArguments::kNone> caller_args(
-      incoming->length() + 1, incoming->arguments() + 1);
+  BuiltinArguments caller_args(incoming->length() + 3,
+                               incoming->arguments() + 1);
   return DoArrayPush(isolate, caller_args);
 }
 
@@ -577,7 +435,6 @@
   }
 
   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
-  DCHECK(!array->map()->is_observed());
 
   uint32_t len = static_cast<uint32_t>(Smi::cast(array->length())->value());
   if (len == 0) return isolate->heap()->undefined_value();
@@ -610,7 +467,6 @@
     return CallJsIntrinsic(isolate, isolate->array_shift(), args);
   }
   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
-  DCHECK(!array->map()->is_observed());
 
   int len = Smi::cast(array->length())->value();
   if (len == 0) return heap->undefined_value();
@@ -631,7 +487,6 @@
     return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
   }
   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
-  DCHECK(!array->map()->is_observed());
   int to_add = args.length() - 1;
   if (to_add == 0) return array->length();
 
@@ -670,10 +525,11 @@
   } else if (receiver->IsJSObject() &&
              GetSloppyArgumentsLength(isolate, Handle<JSObject>::cast(receiver),
                                       &len)) {
-    DCHECK_EQ(FAST_ELEMENTS, JSObject::cast(*receiver)->GetElementsKind());
-    // Array.prototype.slice(arguments, ...) is quite a common idiom
+    // Array.prototype.slice.call(arguments, ...) is quite a common idiom
     // (notably more than 50% of invocations in Web apps).
     // Treat it in C++ as well.
+    DCHECK(JSObject::cast(*receiver)->HasFastElements() ||
+           JSObject::cast(*receiver)->HasFastArgumentsElements());
   } else {
     AllowHeapAllocation allow_allocation;
     return CallJsIntrinsic(isolate, isolate->array_slice(), args);
@@ -687,16 +543,16 @@
   relative_end = len;
   if (argument_count > 0) {
     DisallowHeapAllocation no_gc;
-    if (!ClampedToInteger(args[1], &relative_start)) {
+    if (!ClampedToInteger(isolate, args[1], &relative_start)) {
       AllowHeapAllocation allow_allocation;
       return CallJsIntrinsic(isolate, isolate->array_slice(), args);
     }
     if (argument_count > 1) {
       Object* end_arg = args[2];
       // slice handles the end_arg specially
-      if (end_arg->IsUndefined()) {
+      if (end_arg->IsUndefined(isolate)) {
         relative_end = len;
-      } else if (!ClampedToInteger(end_arg, &relative_end)) {
+      } else if (!ClampedToInteger(isolate, end_arg, &relative_end)) {
         AllowHeapAllocation allow_allocation;
         return CallJsIntrinsic(isolate, isolate->array_slice(), args);
       }
@@ -729,13 +585,12 @@
     return CallJsIntrinsic(isolate, isolate->array_splice(), args);
   }
   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
-  DCHECK(!array->map()->is_observed());
 
   int argument_count = args.length() - 1;
   int relative_start = 0;
   if (argument_count > 0) {
     DisallowHeapAllocation no_gc;
-    if (!ClampedToInteger(args[1], &relative_start)) {
+    if (!ClampedToInteger(isolate, args[1], &relative_start)) {
       AllowHeapAllocation allow_allocation;
       return CallJsIntrinsic(isolate, isolate->array_splice(), args);
     }
@@ -757,7 +612,7 @@
     int delete_count = 0;
     DisallowHeapAllocation no_gc;
     if (argument_count > 1) {
-      if (!ClampedToInteger(args[2], &delete_count)) {
+      if (!ClampedToInteger(isolate, args[2], &delete_count)) {
         AllowHeapAllocation allow_allocation;
         return CallJsIntrinsic(isolate, isolate->array_splice(), args);
       }
@@ -910,7 +765,7 @@
     FOR_WITH_HANDLE_SCOPE(
         isolate_, uint32_t, i = 0, i, i < current_length, i++, {
           Handle<Object> element(current_storage->get(i), isolate_);
-          if (!element->IsTheHole()) {
+          if (!element->IsTheHole(isolate_)) {
             // The object holding this backing store has just been allocated, so
             // it cannot yet be used as a prototype.
             Handle<SeededNumberDictionary> new_storage =
@@ -956,6 +811,7 @@
 
 
 uint32_t EstimateElementCount(Handle<JSArray> array) {
+  DisallowHeapAllocation no_gc;
   uint32_t length = static_cast<uint32_t>(array->length()->Number());
   int element_count = 0;
   switch (array->GetElementsKind()) {
@@ -967,9 +823,10 @@
       // a 32-bit signed integer.
       DCHECK(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
       int fast_length = static_cast<int>(length);
-      Handle<FixedArray> elements(FixedArray::cast(array->elements()));
+      Isolate* isolate = array->GetIsolate();
+      FixedArray* elements = FixedArray::cast(array->elements());
       for (int i = 0; i < fast_length; i++) {
-        if (!elements->get(i)->IsTheHole()) element_count++;
+        if (!elements->get(i)->IsTheHole(isolate)) element_count++;
       }
       break;
     }
@@ -983,20 +840,20 @@
         DCHECK(FixedArray::cast(array->elements())->length() == 0);
         break;
       }
-      Handle<FixedDoubleArray> elements(
-          FixedDoubleArray::cast(array->elements()));
+      FixedDoubleArray* elements = FixedDoubleArray::cast(array->elements());
       for (int i = 0; i < fast_length; i++) {
         if (!elements->is_the_hole(i)) element_count++;
       }
       break;
     }
     case DICTIONARY_ELEMENTS: {
-      Handle<SeededNumberDictionary> dictionary(
-          SeededNumberDictionary::cast(array->elements()));
+      SeededNumberDictionary* dictionary =
+          SeededNumberDictionary::cast(array->elements());
+      Isolate* isolate = dictionary->GetIsolate();
       int capacity = dictionary->Capacity();
       for (int i = 0; i < capacity; i++) {
-        Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
-        if (dictionary->IsKey(*key)) {
+        Object* key = dictionary->KeyAt(i);
+        if (dictionary->IsKey(isolate, key)) {
           element_count++;
         }
       }
@@ -1045,7 +902,7 @@
       uint32_t length = static_cast<uint32_t>(elements->length());
       if (range < length) length = range;
       for (uint32_t i = 0; i < length; i++) {
-        if (!elements->get(i)->IsTheHole()) {
+        if (!elements->get(i)->IsTheHole(isolate)) {
           indices->Add(i);
         }
       }
@@ -1073,13 +930,9 @@
       SeededNumberDictionary* dict =
           SeededNumberDictionary::cast(object->elements());
       uint32_t capacity = dict->Capacity();
-      Heap* heap = isolate->heap();
-      Object* undefined = heap->undefined_value();
-      Object* the_hole = heap->the_hole_value();
       FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, j = 0, j, j < capacity, j++, {
         Object* k = dict->KeyAt(j);
-        if (k == undefined) continue;
-        if (k == the_hole) continue;
+        if (!dict->IsKey(isolate, k)) continue;
         DCHECK(k->IsNumber());
         uint32_t index = static_cast<uint32_t>(k->Number());
         if (index < range) {
@@ -1188,12 +1041,8 @@
     length = static_cast<uint32_t>(array->length()->Number());
   } else {
     Handle<Object> val;
-    Handle<Object> key = isolate->factory()->length_string();
     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-        isolate, val, Runtime::GetObjectProperty(isolate, receiver, key),
-        false);
-    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val,
-                                     Object::ToLength(isolate, val), false);
+        isolate, val, Object::GetLengthFromArrayLike(isolate, receiver), false);
     // TODO(caitp): Support larger element indexes (up to 2^53-1).
     if (!val->ToUint32(&length)) {
       length = 0;
@@ -1219,7 +1068,7 @@
       DCHECK(fast_length <= elements->length());
       FOR_WITH_HANDLE_SCOPE(isolate, int, j = 0, j, j < fast_length, j++, {
         Handle<Object> element_value(elements->get(j), isolate);
-        if (!element_value->IsTheHole()) {
+        if (!element_value->IsTheHole(isolate)) {
           if (!visitor->visit(j, element_value)) return false;
         } else {
           Maybe<bool> maybe = JSReceiver::HasElement(array, j);
@@ -1323,28 +1172,22 @@
   return true;
 }
 
-
-bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) {
-  Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
-  Maybe<bool> maybe = JSReceiver::HasProperty(obj, key);
-  return maybe.FromMaybe(false);
-}
-
-
 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) {
   HandleScope handle_scope(isolate);
   if (!obj->IsJSReceiver()) return Just(false);
-  Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
-  Handle<Object> value;
-  MaybeHandle<Object> maybeValue =
-      i::Runtime::GetObjectProperty(isolate, obj, key);
-  if (!maybeValue.ToHandle(&value)) return Nothing<bool>();
-  if (!value->IsUndefined()) return Just(value->BooleanValue());
+  if (!isolate->IsIsConcatSpreadableLookupChainIntact()) {
+    // Slow path if @@isConcatSpreadable has been used.
+    Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
+    Handle<Object> value;
+    MaybeHandle<Object> maybeValue =
+        i::Runtime::GetObjectProperty(isolate, obj, key);
+    if (!maybeValue.ToHandle(&value)) return Nothing<bool>();
+    if (!value->IsUndefined(isolate)) return Just(value->BooleanValue());
+  }
   return Object::IsArray(obj);
 }
 
-
-Object* Slow_ArrayConcat(Arguments* args, Handle<Object> species,
+Object* Slow_ArrayConcat(BuiltinArguments* args, Handle<Object> species,
                          Isolate* isolate) {
   int argument_count = args->length();
 
@@ -1527,8 +1370,25 @@
   }
 }
 
+bool IsSimpleArray(Isolate* isolate, Handle<JSArray> obj) {
+  DisallowHeapAllocation no_gc;
+  Map* map = obj->map();
+  // If there is only the 'length' property we are fine.
+  if (map->prototype() ==
+          isolate->native_context()->initial_array_prototype() &&
+      map->NumberOfOwnDescriptors() == 1) {
+    return true;
+  }
+  // TODO(cbruni): slower lookup for array subclasses and support slow
+  // @@IsConcatSpreadable lookup.
+  return false;
+}
 
-MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) {
+MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate,
+                                      BuiltinArguments* args) {
+  if (!isolate->IsIsConcatSpreadableLookupChainIntact()) {
+    return MaybeHandle<JSArray>();
+  }
   // We shouldn't overflow when adding another len.
   const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
   STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
@@ -1544,14 +1404,15 @@
     for (int i = 0; i < n_arguments; i++) {
       Object* arg = (*args)[i];
       if (!arg->IsJSArray()) return MaybeHandle<JSArray>();
-      if (!JSObject::cast(arg)->HasFastElements()) {
-        return MaybeHandle<JSArray>();
-      }
       if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) {
         return MaybeHandle<JSArray>();
       }
+      // TODO(cbruni): support fast concatenation of DICTIONARY_ELEMENTS.
+      if (!JSObject::cast(arg)->HasFastElements()) {
+        return MaybeHandle<JSArray>();
+      }
       Handle<JSArray> array(JSArray::cast(arg), isolate);
-      if (HasConcatSpreadableModifier(isolate, array)) {
+      if (!IsSimpleArray(isolate, array)) {
         return MaybeHandle<JSArray>();
       }
       // The Array length is guaranted to be <= kHalfOfMaxInt thus we won't
@@ -1561,14 +1422,14 @@
       // Throw an Error if we overflow the FixedArray limits
       if (FixedDoubleArray::kMaxLength < result_len ||
           FixedArray::kMaxLength < result_len) {
-        AllowHeapAllocation allow_gc;
+        AllowHeapAllocation gc;
         THROW_NEW_ERROR(isolate,
                         NewRangeError(MessageTemplate::kInvalidArrayLength),
                         JSArray);
       }
     }
   }
-  return ElementsAccessor::Concat(isolate, args, n_arguments);
+  return ElementsAccessor::Concat(isolate, args, n_arguments, result_len);
 }
 
 }  // namespace
@@ -1580,7 +1441,7 @@
 
   Handle<Object> receiver = args.receiver();
   // TODO(bmeurer): Do we really care about the exact exception message here?
-  if (receiver->IsNull() || receiver->IsUndefined()) {
+  if (receiver->IsNull(isolate) || receiver->IsUndefined(isolate)) {
     THROW_NEW_ERROR_RETURN_FAILURE(
         isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
                               isolate->factory()->NewStringFromAsciiChecked(
@@ -1616,16 +1477,6 @@
 }
 
 
-// ES6 22.1.2.2 Array.isArray
-BUILTIN(ArrayIsArray) {
-  HandleScope scope(isolate);
-  DCHECK_EQ(2, args.length());
-  Handle<Object> object = args.at<Object>(1);
-  Maybe<bool> result = Object::IsArray(object);
-  MAYBE_RETURN(result, isolate->heap()->exception());
-  return *isolate->factory()->ToBoolean(result.FromJust());
-}
-
 namespace {
 
 MUST_USE_RESULT Maybe<bool> FastAssign(Handle<JSReceiver> to,
@@ -1637,6 +1488,14 @@
                 String::cast(*next_source)->length() == 0);
   }
 
+  // If the target is deprecated, the object will be updated on first store. If
+  // the source for that store equals the target, this will invalidate the
+  // cached representation of the source. Preventively upgrade the target.
+  // Do this on each iteration since any property load could cause deprecation.
+  if (to->map()->is_deprecated()) {
+    JSObject::MigrateInstance(Handle<JSObject>::cast(to));
+  }
+
   Isolate* isolate = to->GetIsolate();
   Handle<Map> map(JSReceiver::cast(*next_source)->map(), isolate);
 
@@ -1727,8 +1586,9 @@
     // 4b ii. Let keys be ? from.[[OwnPropertyKeys]]().
     Handle<FixedArray> keys;
     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-        isolate, keys,
-        JSReceiver::GetKeys(from, OWN_ONLY, ALL_PROPERTIES, KEEP_NUMBERS));
+        isolate, keys, KeyAccumulator::GetKeys(
+                           from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
+                           GetKeysConversion::kKeepNumbers));
     // 4c. Repeat for each element nextKey of keys in List order,
     for (int j = 0; j < keys->length(); ++j) {
       Handle<Object> next_key(keys->get(j), isolate);
@@ -1758,10 +1618,12 @@
 
 
 // ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
+// TODO(verwaest): Support the common cases with precached map directly in
+// an Object.create stub.
 BUILTIN(ObjectCreate) {
   HandleScope scope(isolate);
   Handle<Object> prototype = args.atOrUndefined(isolate, 1);
-  if (!prototype->IsNull() && !prototype->IsJSReceiver()) {
+  if (!prototype->IsNull(isolate) && !prototype->IsJSReceiver()) {
     THROW_NEW_ERROR_RETURN_FAILURE(
         isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
   }
@@ -1773,7 +1635,26 @@
   Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
                   isolate);
   if (map->prototype() != *prototype) {
-    map = Map::TransitionToPrototype(map, prototype, FAST_PROTOTYPE);
+    if (prototype->IsNull(isolate)) {
+      map = isolate->object_with_null_prototype_map();
+    } else if (prototype->IsJSObject()) {
+      Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
+      if (!js_prototype->map()->is_prototype_map()) {
+        JSObject::OptimizeAsPrototype(js_prototype, FAST_PROTOTYPE);
+      }
+      Handle<PrototypeInfo> info =
+          Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
+      // TODO(verwaest): Use inobject slack tracking for this map.
+      if (info->HasObjectCreateMap()) {
+        map = handle(info->ObjectCreateMap(), isolate);
+      } else {
+        map = Map::CopyInitialMap(map);
+        Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
+        PrototypeInfo::SetObjectCreateMap(info, map);
+      }
+    } else {
+      map = Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE);
+    }
   }
 
   // Actually allocate the object.
@@ -1781,7 +1662,7 @@
 
   // Define the properties if properties was specified and is not undefined.
   Handle<Object> properties = args.atOrUndefined(isolate, 2);
-  if (!properties->IsUndefined()) {
+  if (!properties->IsUndefined(isolate)) {
     RETURN_FAILURE_ON_EXCEPTION(
         isolate, JSReceiver::DefineProperties(isolate, object, properties));
   }
@@ -1789,6 +1670,156 @@
   return *object;
 }
 
+// ES6 section 19.1.2.3 Object.defineProperties
+BUILTIN(ObjectDefineProperties) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(3, args.length());
+  Handle<Object> target = args.at<Object>(1);
+  Handle<Object> properties = args.at<Object>(2);
+
+  RETURN_RESULT_OR_FAILURE(
+      isolate, JSReceiver::DefineProperties(isolate, target, properties));
+}
+
+// ES6 section 19.1.2.4 Object.defineProperty
+BUILTIN(ObjectDefineProperty) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(4, args.length());
+  Handle<Object> target = args.at<Object>(1);
+  Handle<Object> key = args.at<Object>(2);
+  Handle<Object> attributes = args.at<Object>(3);
+
+  return JSReceiver::DefineProperty(isolate, target, key, attributes);
+}
+
+namespace {
+
+template <AccessorComponent which_accessor>
+Object* ObjectDefineAccessor(Isolate* isolate, Handle<Object> object,
+                             Handle<Object> name, Handle<Object> accessor) {
+  // 1. Let O be ? ToObject(this value).
+  Handle<JSReceiver> receiver;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
+                                     Object::ConvertReceiver(isolate, object));
+  // 2. If IsCallable(getter) is false, throw a TypeError exception.
+  if (!accessor->IsCallable()) {
+    MessageTemplate::Template message =
+        which_accessor == ACCESSOR_GETTER
+            ? MessageTemplate::kObjectGetterExpectingFunction
+            : MessageTemplate::kObjectSetterExpectingFunction;
+    THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(message));
+  }
+  // 3. Let desc be PropertyDescriptor{[[Get]]: getter, [[Enumerable]]: true,
+  //                                   [[Configurable]]: true}.
+  PropertyDescriptor desc;
+  if (which_accessor == ACCESSOR_GETTER) {
+    desc.set_get(accessor);
+  } else {
+    DCHECK(which_accessor == ACCESSOR_SETTER);
+    desc.set_set(accessor);
+  }
+  desc.set_enumerable(true);
+  desc.set_configurable(true);
+  // 4. Let key be ? ToPropertyKey(P).
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
+                                     Object::ToPropertyKey(isolate, name));
+  // 5. Perform ? DefinePropertyOrThrow(O, key, desc).
+  // To preserve legacy behavior, we ignore errors silently rather than
+  // throwing an exception.
+  Maybe<bool> success = JSReceiver::DefineOwnProperty(
+      isolate, receiver, name, &desc, Object::DONT_THROW);
+  MAYBE_RETURN(success, isolate->heap()->exception());
+  if (!success.FromJust()) {
+    isolate->CountUsage(v8::Isolate::kDefineGetterOrSetterWouldThrow);
+  }
+  // 6. Return undefined.
+  return isolate->heap()->undefined_value();
+}
+
+Object* ObjectLookupAccessor(Isolate* isolate, Handle<Object> object,
+                             Handle<Object> key, AccessorComponent component) {
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, object,
+                                     Object::ConvertReceiver(isolate, object));
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
+                                     Object::ToPropertyKey(isolate, key));
+  bool success = false;
+  LookupIterator it = LookupIterator::PropertyOrElement(
+      isolate, object, key, &success,
+      LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
+  DCHECK(success);
+
+  for (; it.IsFound(); it.Next()) {
+    switch (it.state()) {
+      case LookupIterator::INTERCEPTOR:
+      case LookupIterator::NOT_FOUND:
+      case LookupIterator::TRANSITION:
+        UNREACHABLE();
+
+      case LookupIterator::ACCESS_CHECK:
+        if (it.HasAccess()) continue;
+        isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
+        RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
+        return isolate->heap()->undefined_value();
+
+      case LookupIterator::JSPROXY:
+        return isolate->heap()->undefined_value();
+
+      case LookupIterator::INTEGER_INDEXED_EXOTIC:
+        return isolate->heap()->undefined_value();
+      case LookupIterator::DATA:
+        continue;
+      case LookupIterator::ACCESSOR: {
+        Handle<Object> maybe_pair = it.GetAccessors();
+        if (maybe_pair->IsAccessorPair()) {
+          return *AccessorPair::GetComponent(
+              Handle<AccessorPair>::cast(maybe_pair), component);
+        }
+      }
+    }
+  }
+
+  return isolate->heap()->undefined_value();
+}
+
+}  // namespace
+
+// ES6 B.2.2.2 a.k.a.
+// https://tc39.github.io/ecma262/#sec-object.prototype.__defineGetter__
+BUILTIN(ObjectDefineGetter) {
+  HandleScope scope(isolate);
+  Handle<Object> object = args.at<Object>(0);  // Receiver.
+  Handle<Object> name = args.at<Object>(1);
+  Handle<Object> getter = args.at<Object>(2);
+  return ObjectDefineAccessor<ACCESSOR_GETTER>(isolate, object, name, getter);
+}
+
+// ES6 B.2.2.3 a.k.a.
+// https://tc39.github.io/ecma262/#sec-object.prototype.__defineSetter__
+BUILTIN(ObjectDefineSetter) {
+  HandleScope scope(isolate);
+  Handle<Object> object = args.at<Object>(0);  // Receiver.
+  Handle<Object> name = args.at<Object>(1);
+  Handle<Object> setter = args.at<Object>(2);
+  return ObjectDefineAccessor<ACCESSOR_SETTER>(isolate, object, name, setter);
+}
+
+// ES6 B.2.2.4 a.k.a.
+// https://tc39.github.io/ecma262/#sec-object.prototype.__lookupGetter__
+BUILTIN(ObjectLookupGetter) {
+  HandleScope scope(isolate);
+  Handle<Object> object = args.at<Object>(0);
+  Handle<Object> name = args.at<Object>(1);
+  return ObjectLookupAccessor(isolate, object, name, ACCESSOR_GETTER);
+}
+
+// ES6 B.2.2.5 a.k.a.
+// https://tc39.github.io/ecma262/#sec-object.prototype.__lookupSetter__
+BUILTIN(ObjectLookupSetter) {
+  HandleScope scope(isolate);
+  Handle<Object> object = args.at<Object>(0);
+  Handle<Object> name = args.at<Object>(1);
+  return ObjectLookupAccessor(isolate, object, name, ACCESSOR_SETTER);
+}
 
 // ES6 section 19.1.2.5 Object.freeze ( O )
 BUILTIN(ObjectFreeze) {
@@ -1803,6 +1834,20 @@
 }
 
 
+// ES section 19.1.2.9 Object.getPrototypeOf ( O )
+BUILTIN(ObjectGetPrototypeOf) {
+  HandleScope scope(isolate);
+  Handle<Object> object = args.atOrUndefined(isolate, 1);
+
+  Handle<JSReceiver> receiver;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, receiver, Object::ToObject(isolate, object));
+
+  RETURN_RESULT_OR_FAILURE(isolate,
+                           JSReceiver::GetPrototype(isolate, receiver));
+}
+
+
 // ES6 section 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
 BUILTIN(ObjectGetOwnPropertyDescriptor) {
   HandleScope scope(isolate);
@@ -1829,8 +1874,7 @@
 
 namespace {
 
-Object* GetOwnPropertyKeys(Isolate* isolate,
-                           BuiltinArguments<BuiltinExtraArguments::kNone> args,
+Object* GetOwnPropertyKeys(Isolate* isolate, BuiltinArguments args,
                            PropertyFilter filter) {
   HandleScope scope(isolate);
   Handle<Object> object = args.atOrUndefined(isolate, 1);
@@ -1840,7 +1884,8 @@
   Handle<FixedArray> keys;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
       isolate, keys,
-      JSReceiver::GetKeys(receiver, OWN_ONLY, filter, CONVERT_TO_STRING));
+      KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly, filter,
+                              GetKeysConversion::kConvertToString));
   return *isolate->factory()->NewJSArrayWithElements(keys);
 }
 
@@ -1936,8 +1981,9 @@
   } else {
     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
         isolate, keys,
-        JSReceiver::GetKeys(receiver, OWN_ONLY, ENUMERABLE_STRINGS,
-                            CONVERT_TO_STRING));
+        KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
+                                ENUMERABLE_STRINGS,
+                                GetKeysConversion::kConvertToString));
   }
   return *isolate->factory()->NewJSArrayWithElements(keys, FAST_ELEMENTS);
 }
@@ -1979,8 +2025,9 @@
 
   Handle<FixedArray> keys;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, keys, JSReceiver::GetKeys(receiver, OWN_ONLY, ALL_PROPERTIES,
-                                         CONVERT_TO_STRING));
+      isolate, keys, KeyAccumulator::GetKeys(
+                         receiver, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
+                         GetKeysConversion::kConvertToString));
 
   Handle<JSObject> descriptors =
       isolate->factory()->NewJSObject(isolate->object_function());
@@ -2031,12 +2078,78 @@
   return *object;
 }
 
+// ES6 section 18.2.6.2 decodeURI (encodedURI)
+BUILTIN(GlobalDecodeURI) {
+  HandleScope scope(isolate);
+  Handle<String> encoded_uri;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, encoded_uri,
+      Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
+
+  RETURN_RESULT_OR_FAILURE(isolate, Uri::DecodeUri(isolate, encoded_uri));
+}
+
+// ES6 section 18.2.6.3 decodeURIComponent (encodedURIComponent)
+BUILTIN(GlobalDecodeURIComponent) {
+  HandleScope scope(isolate);
+  Handle<String> encoded_uri_component;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, encoded_uri_component,
+      Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
+
+  RETURN_RESULT_OR_FAILURE(
+      isolate, Uri::DecodeUriComponent(isolate, encoded_uri_component));
+}
+
+// ES6 section 18.2.6.4 encodeURI (uri)
+BUILTIN(GlobalEncodeURI) {
+  HandleScope scope(isolate);
+  Handle<String> uri;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, uri, Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
+
+  RETURN_RESULT_OR_FAILURE(isolate, Uri::EncodeUri(isolate, uri));
+}
+
+// ES6 section 18.2.6.5 encodeURIComponenet (uriComponent)
+BUILTIN(GlobalEncodeURIComponent) {
+  HandleScope scope(isolate);
+  Handle<String> uri_component;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, uri_component,
+      Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
+
+  RETURN_RESULT_OR_FAILURE(isolate,
+                           Uri::EncodeUriComponent(isolate, uri_component));
+}
+
+// ES6 section B.2.1.1 escape (string)
+BUILTIN(GlobalEscape) {
+  HandleScope scope(isolate);
+  Handle<String> string;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, string,
+      Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
+
+  RETURN_RESULT_OR_FAILURE(isolate, Uri::Escape(isolate, string));
+}
+
+// ES6 section B.2.1.2 unescape (string)
+BUILTIN(GlobalUnescape) {
+  HandleScope scope(isolate);
+  Handle<String> string;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, string,
+      Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
+
+  RETURN_RESULT_OR_FAILURE(isolate, Uri::Unescape(isolate, string));
+}
 
 namespace {
 
 bool CodeGenerationFromStringsAllowed(Isolate* isolate,
                                       Handle<Context> context) {
-  DCHECK(context->allow_code_gen_from_strings()->IsFalse());
+  DCHECK(context->allow_code_gen_from_strings()->IsFalse(isolate));
   // Check with callback if set.
   AllowCodeGenerationFromStringsCallback callback =
       isolate->allow_code_gen_callback();
@@ -2059,7 +2172,7 @@
 
   // Check if native context allows code generation from
   // strings. Throw an exception if it doesn't.
-  if (native_context->allow_code_gen_from_strings()->IsFalse() &&
+  if (native_context->allow_code_gen_from_strings()->IsFalse(isolate) &&
       !CodeGenerationFromStringsAllowed(isolate, native_context)) {
     Handle<Object> error_message =
         native_context->ErrorMessageForCodeGenerationFromStrings();
@@ -2069,11 +2182,12 @@
   }
 
   // Compile source string in the native context.
-  Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared(),
-                                        isolate);
+  int eval_scope_position = 0;
+  int eval_position = RelocInfo::kNoPosition;
+  Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared());
   return Compiler::GetFunctionFromEval(source, outer_info, native_context,
-                                       SLOPPY, restriction,
-                                       RelocInfo::kNoPosition);
+                                       SLOPPY, restriction, eval_scope_position,
+                                       eval_position);
 }
 
 }  // namespace
@@ -2091,13 +2205,36 @@
       isolate, function,
       CompileString(handle(target->native_context(), isolate),
                     Handle<String>::cast(x), NO_PARSE_RESTRICTION));
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
+  RETURN_RESULT_OR_FAILURE(
+      isolate,
       Execution::Call(isolate, function, target_global_proxy, 0, nullptr));
-  return *result;
 }
 
+// ES6 section 24.3.1 JSON.parse.
+BUILTIN(JsonParse) {
+  HandleScope scope(isolate);
+  Handle<Object> source = args.atOrUndefined(isolate, 1);
+  Handle<Object> reviver = args.atOrUndefined(isolate, 2);
+  Handle<String> string;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string,
+                                     Object::ToString(isolate, source));
+  string = String::Flatten(string);
+  RETURN_RESULT_OR_FAILURE(
+      isolate, string->IsSeqOneByteString()
+                   ? JsonParser<true>::Parse(isolate, string, reviver)
+                   : JsonParser<false>::Parse(isolate, string, reviver));
+}
+
+// ES6 section 24.3.2 JSON.stringify.
+BUILTIN(JsonStringify) {
+  HandleScope scope(isolate);
+  JsonStringifier stringifier(isolate);
+  Handle<Object> object = args.atOrUndefined(isolate, 1);
+  Handle<Object> replacer = args.atOrUndefined(isolate, 2);
+  Handle<Object> indent = args.atOrUndefined(isolate, 3);
+  RETURN_RESULT_OR_FAILURE(isolate,
+                           stringifier.Stringify(object, replacer, indent));
+}
 
 // -----------------------------------------------------------------------------
 // ES6 section 20.2.2 Function Properties of the Math Object
@@ -2122,25 +2259,52 @@
   return *isolate->factory()->NewHeapNumber(std::asin(x->Number()));
 }
 
-
 // ES6 section 20.2.2.6 Math.atan ( x )
-BUILTIN(MathAtan) {
-  HandleScope scope(isolate);
-  DCHECK_EQ(2, args.length());
-  Handle<Object> x = args.at<Object>(1);
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
-  return *isolate->factory()->NewHeapNumber(std::atan(x->Number()));
+void Builtins::Generate_MathAtan(CodeStubAssembler* assembler) {
+  using compiler::Node;
+
+  Node* x = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+  Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+  Node* value = assembler->Float64Atan(x_value);
+  Node* result = assembler->ChangeFloat64ToTagged(value);
+  assembler->Return(result);
+}
+
+// ES6 section 20.2.2.8 Math.atan2 ( y, x )
+void Builtins::Generate_MathAtan2(CodeStubAssembler* assembler) {
+  using compiler::Node;
+
+  Node* y = assembler->Parameter(1);
+  Node* x = assembler->Parameter(2);
+  Node* context = assembler->Parameter(5);
+  Node* y_value = assembler->TruncateTaggedToFloat64(context, y);
+  Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+  Node* value = assembler->Float64Atan2(y_value, x_value);
+  Node* result = assembler->ChangeFloat64ToTagged(value);
+  assembler->Return(result);
+}
+
+// ES6 section 20.2.2.7 Math.atanh ( x )
+void Builtins::Generate_MathAtanh(CodeStubAssembler* assembler) {
+  using compiler::Node;
+
+  Node* x = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+  Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+  Node* value = assembler->Float64Atanh(x_value);
+  Node* result = assembler->ChangeFloat64ToTagged(value);
+  assembler->Return(result);
 }
 
 namespace {
 
 void Generate_MathRoundingOperation(
-    compiler::CodeStubAssembler* assembler,
-    compiler::Node* (compiler::CodeStubAssembler::*float64op)(
-        compiler::Node*)) {
-  typedef compiler::CodeStubAssembler::Label Label;
+    CodeStubAssembler* assembler,
+    compiler::Node* (CodeStubAssembler::*float64op)(compiler::Node*)) {
+  typedef CodeStubAssembler::Label Label;
   typedef compiler::Node Node;
-  typedef compiler::CodeStubAssembler::Variable Variable;
+  typedef CodeStubAssembler::Variable Variable;
 
   Node* context = assembler->Parameter(4);
 
@@ -2197,16 +2361,27 @@
 }  // namespace
 
 // ES6 section 20.2.2.10 Math.ceil ( x )
-void Builtins::Generate_MathCeil(compiler::CodeStubAssembler* assembler) {
-  Generate_MathRoundingOperation(assembler,
-                                 &compiler::CodeStubAssembler::Float64Ceil);
+void Builtins::Generate_MathCeil(CodeStubAssembler* assembler) {
+  Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Ceil);
+}
+
+// ES6 section 20.2.2.9 Math.cbrt ( x )
+void Builtins::Generate_MathCbrt(CodeStubAssembler* assembler) {
+  using compiler::Node;
+
+  Node* x = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+  Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+  Node* value = assembler->Float64Cbrt(x_value);
+  Node* result = assembler->ChangeFloat64ToTagged(value);
+  assembler->Return(result);
 }
 
 // ES6 section 20.2.2.11 Math.clz32 ( x )
-void Builtins::Generate_MathClz32(compiler::CodeStubAssembler* assembler) {
-  typedef compiler::CodeStubAssembler::Label Label;
+void Builtins::Generate_MathClz32(CodeStubAssembler* assembler) {
+  typedef CodeStubAssembler::Label Label;
   typedef compiler::Node Node;
-  typedef compiler::CodeStubAssembler::Variable Variable;
+  typedef CodeStubAssembler::Variable Variable;
 
   Node* context = assembler->Parameter(4);
 
@@ -2270,10 +2445,33 @@
   }
 }
 
+// ES6 section 20.2.2.12 Math.cos ( x )
+void Builtins::Generate_MathCos(CodeStubAssembler* assembler) {
+  using compiler::Node;
+
+  Node* x = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+  Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+  Node* value = assembler->Float64Cos(x_value);
+  Node* result = assembler->ChangeFloat64ToTagged(value);
+  assembler->Return(result);
+}
+
+// ES6 section 20.2.2.14 Math.exp ( x )
+void Builtins::Generate_MathExp(CodeStubAssembler* assembler) {
+  using compiler::Node;
+
+  Node* x = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+  Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+  Node* value = assembler->Float64Exp(x_value);
+  Node* result = assembler->ChangeFloat64ToTagged(value);
+  assembler->Return(result);
+}
+
 // ES6 section 20.2.2.16 Math.floor ( x )
-void Builtins::Generate_MathFloor(compiler::CodeStubAssembler* assembler) {
-  Generate_MathRoundingOperation(assembler,
-                                 &compiler::CodeStubAssembler::Float64Floor);
+void Builtins::Generate_MathFloor(CodeStubAssembler* assembler) {
+  Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Floor);
 }
 
 // ES6 section 20.2.2.17 Math.fround ( x )
@@ -2298,14 +2496,85 @@
   return *isolate->factory()->NewNumberFromInt(product);
 }
 
+// ES6 section 20.2.2.20 Math.log ( x )
+void Builtins::Generate_MathLog(CodeStubAssembler* assembler) {
+  using compiler::Node;
+
+  Node* x = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+  Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+  Node* value = assembler->Float64Log(x_value);
+  Node* result = assembler->ChangeFloat64ToTagged(value);
+  assembler->Return(result);
+}
+
+// ES6 section 20.2.2.21 Math.log1p ( x )
+void Builtins::Generate_MathLog1p(CodeStubAssembler* assembler) {
+  using compiler::Node;
+
+  Node* x = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+  Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+  Node* value = assembler->Float64Log1p(x_value);
+  Node* result = assembler->ChangeFloat64ToTagged(value);
+  assembler->Return(result);
+}
+
+// ES6 section 20.2.2.23 Math.log2 ( x )
+void Builtins::Generate_MathLog2(CodeStubAssembler* assembler) {
+  using compiler::Node;
+
+  Node* x = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+  Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+  Node* value = assembler->Float64Log2(x_value);
+  Node* result = assembler->ChangeFloat64ToTagged(value);
+  assembler->Return(result);
+}
+
+// ES6 section 20.2.2.22 Math.log10 ( x )
+void Builtins::Generate_MathLog10(CodeStubAssembler* assembler) {
+  using compiler::Node;
+
+  Node* x = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+  Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+  Node* value = assembler->Float64Log10(x_value);
+  Node* result = assembler->ChangeFloat64ToTagged(value);
+  assembler->Return(result);
+}
+
+// ES6 section 20.2.2.15 Math.expm1 ( x )
+void Builtins::Generate_MathExpm1(CodeStubAssembler* assembler) {
+  using compiler::Node;
+
+  Node* x = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+  Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+  Node* value = assembler->Float64Expm1(x_value);
+  Node* result = assembler->ChangeFloat64ToTagged(value);
+  assembler->Return(result);
+}
+
 // ES6 section 20.2.2.28 Math.round ( x )
-void Builtins::Generate_MathRound(compiler::CodeStubAssembler* assembler) {
-  Generate_MathRoundingOperation(assembler,
-                                 &compiler::CodeStubAssembler::Float64Round);
+void Builtins::Generate_MathRound(CodeStubAssembler* assembler) {
+  Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Round);
+}
+
+// ES6 section 20.2.2.30 Math.sin ( x )
+void Builtins::Generate_MathSin(CodeStubAssembler* assembler) {
+  using compiler::Node;
+
+  Node* x = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+  Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+  Node* value = assembler->Float64Sin(x_value);
+  Node* result = assembler->ChangeFloat64ToTagged(value);
+  assembler->Return(result);
 }
 
 // ES6 section 20.2.2.32 Math.sqrt ( x )
-void Builtins::Generate_MathSqrt(compiler::CodeStubAssembler* assembler) {
+void Builtins::Generate_MathSqrt(CodeStubAssembler* assembler) {
   using compiler::Node;
 
   Node* x = assembler->Parameter(1);
@@ -2316,16 +2585,146 @@
   assembler->Return(result);
 }
 
+// ES6 section 20.2.2.33 Math.tan ( x )
+void Builtins::Generate_MathTan(CodeStubAssembler* assembler) {
+  using compiler::Node;
+
+  Node* x = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+  Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+  Node* value = assembler->Float64Tan(x_value);
+  Node* result = assembler->ChangeFloat64ToTagged(value);
+  assembler->Return(result);
+}
+
 // ES6 section 20.2.2.35 Math.trunc ( x )
-void Builtins::Generate_MathTrunc(compiler::CodeStubAssembler* assembler) {
-  Generate_MathRoundingOperation(assembler,
-                                 &compiler::CodeStubAssembler::Float64Trunc);
+void Builtins::Generate_MathTrunc(CodeStubAssembler* assembler) {
+  Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Trunc);
+}
+
+// -----------------------------------------------------------------------------
+// ES6 section 19.2 Function Objects
+
+// ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] ( V )
+void Builtins::Generate_FunctionPrototypeHasInstance(
+    CodeStubAssembler* assembler) {
+  using compiler::Node;
+
+  Node* f = assembler->Parameter(0);
+  Node* v = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+  Node* result = assembler->OrdinaryHasInstance(context, f, v);
+  assembler->Return(result);
+}
+
+// -----------------------------------------------------------------------------
+// ES6 section 25.3 Generator Objects
+
+namespace {
+
+void Generate_GeneratorPrototypeResume(
+    CodeStubAssembler* assembler, JSGeneratorObject::ResumeMode resume_mode,
+    char const* const method_name) {
+  typedef CodeStubAssembler::Label Label;
+  typedef compiler::Node Node;
+
+  Node* receiver = assembler->Parameter(0);
+  Node* value = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+  Node* closed = assembler->SmiConstant(
+      Smi::FromInt(JSGeneratorObject::kGeneratorClosed));
+
+  // Check if the {receiver} is actually a JSGeneratorObject.
+  Label if_receiverisincompatible(assembler, Label::kDeferred);
+  assembler->GotoIf(assembler->WordIsSmi(receiver), &if_receiverisincompatible);
+  Node* receiver_instance_type = assembler->LoadInstanceType(receiver);
+  assembler->GotoUnless(assembler->Word32Equal(
+                            receiver_instance_type,
+                            assembler->Int32Constant(JS_GENERATOR_OBJECT_TYPE)),
+                        &if_receiverisincompatible);
+
+  // Check if the {receiver} is running or already closed.
+  Node* receiver_continuation = assembler->LoadObjectField(
+      receiver, JSGeneratorObject::kContinuationOffset);
+  Label if_receiverisclosed(assembler, Label::kDeferred),
+      if_receiverisrunning(assembler, Label::kDeferred);
+  assembler->GotoIf(assembler->SmiEqual(receiver_continuation, closed),
+                    &if_receiverisclosed);
+  DCHECK_LT(JSGeneratorObject::kGeneratorExecuting,
+            JSGeneratorObject::kGeneratorClosed);
+  assembler->GotoIf(assembler->SmiLessThan(receiver_continuation, closed),
+                    &if_receiverisrunning);
+
+  // Resume the {receiver} using our trampoline.
+  Node* result = assembler->CallStub(
+      CodeFactory::ResumeGenerator(assembler->isolate()), context, value,
+      receiver, assembler->SmiConstant(Smi::FromInt(resume_mode)));
+  assembler->Return(result);
+
+  assembler->Bind(&if_receiverisincompatible);
+  {
+    // The {receiver} is not a valid JSGeneratorObject.
+    Node* result = assembler->CallRuntime(
+        Runtime::kThrowIncompatibleMethodReceiver, context,
+        assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
+            method_name, TENURED)),
+        receiver);
+    assembler->Return(result);  // Never reached.
+  }
+
+  assembler->Bind(&if_receiverisclosed);
+  {
+    // The {receiver} is closed already.
+    Node* result = nullptr;
+    switch (resume_mode) {
+      case JSGeneratorObject::kNext:
+        result = assembler->CallRuntime(Runtime::kCreateIterResultObject,
+                                        context, assembler->UndefinedConstant(),
+                                        assembler->BooleanConstant(true));
+        break;
+      case JSGeneratorObject::kReturn:
+        result =
+            assembler->CallRuntime(Runtime::kCreateIterResultObject, context,
+                                   value, assembler->BooleanConstant(true));
+        break;
+      case JSGeneratorObject::kThrow:
+        result = assembler->CallRuntime(Runtime::kThrow, context, value);
+        break;
+    }
+    assembler->Return(result);
+  }
+
+  assembler->Bind(&if_receiverisrunning);
+  {
+    Node* result =
+        assembler->CallRuntime(Runtime::kThrowGeneratorRunning, context);
+    assembler->Return(result);  // Never reached.
+  }
+}
+
+}  // namespace
+
+// ES6 section 25.3.1.2 Generator.prototype.next ( value )
+void Builtins::Generate_GeneratorPrototypeNext(CodeStubAssembler* assembler) {
+  Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kNext,
+                                    "[Generator].prototype.next");
+}
+
+// ES6 section 25.3.1.3 Generator.prototype.return ( value )
+void Builtins::Generate_GeneratorPrototypeReturn(CodeStubAssembler* assembler) {
+  Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kReturn,
+                                    "[Generator].prototype.return");
+}
+
+// ES6 section 25.3.1.4 Generator.prototype.throw ( exception )
+void Builtins::Generate_GeneratorPrototypeThrow(CodeStubAssembler* assembler) {
+  Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kThrow,
+                                    "[Generator].prototype.throw");
 }
 
 // -----------------------------------------------------------------------------
 // ES6 section 26.1 The Reflect Object
 
-
 // ES6 section 26.1.3 Reflect.defineProperty
 BUILTIN(ReflectDefineProperty) {
   HandleScope scope(isolate);
@@ -2401,12 +2800,9 @@
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
                                      Object::ToName(isolate, key));
 
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, Object::GetPropertyOrElement(
-                           receiver, name, Handle<JSReceiver>::cast(target)));
-
-  return *result;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, Object::GetPropertyOrElement(receiver, name,
+                                            Handle<JSReceiver>::cast(target)));
 }
 
 
@@ -2449,11 +2845,9 @@
                               isolate->factory()->NewStringFromAsciiChecked(
                                   "Reflect.getPrototypeOf")));
   }
-  Handle<Object> prototype;
   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(target);
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, prototype, JSReceiver::GetPrototype(isolate, receiver));
-  return *prototype;
+  RETURN_RESULT_OR_FAILURE(isolate,
+                           JSReceiver::GetPrototype(isolate, receiver));
 }
 
 
@@ -2518,8 +2912,9 @@
   Handle<FixedArray> keys;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
       isolate, keys,
-      JSReceiver::GetKeys(Handle<JSReceiver>::cast(target), OWN_ONLY,
-                          ALL_PROPERTIES, CONVERT_TO_STRING));
+      KeyAccumulator::GetKeys(Handle<JSReceiver>::cast(target),
+                              KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
+                              GetKeysConversion::kConvertToString));
   return *isolate->factory()->NewJSArrayWithElements(keys);
 }
 
@@ -2586,7 +2981,7 @@
                                   "Reflect.setPrototypeOf")));
   }
 
-  if (!proto->IsJSReceiver() && !proto->IsNull()) {
+  if (!proto->IsJSReceiver() && !proto->IsNull(isolate)) {
     THROW_NEW_ERROR_RETURN_FAILURE(
         isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
   }
@@ -2694,7 +3089,7 @@
 
   // 4. Let numberOffset be ? ToNumber(byteOffset).
   Handle<Object> number_offset;
-  if (byte_offset->IsUndefined()) {
+  if (byte_offset->IsUndefined(isolate)) {
     // We intentionally violate the specification at this point to allow
     // for new DataView(buffer) invocations to be equivalent to the full
     // new DataView(buffer, 0) invocation.
@@ -2729,7 +3124,7 @@
   }
 
   Handle<Object> view_byte_length;
-  if (byte_length->IsUndefined()) {
+  if (byte_length->IsUndefined(isolate)) {
     // 10. If byteLength is undefined, then
     //       a. Let viewByteLength be bufferByteLength - offset.
     view_byte_length =
@@ -2771,6 +3166,119 @@
   return *result;
 }
 
+// ES6 section 24.2.4.1 get DataView.prototype.buffer
+BUILTIN(DataViewPrototypeGetBuffer) {
+  HandleScope scope(isolate);
+  CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.buffer");
+  return data_view->buffer();
+}
+
+// ES6 section 24.2.4.2 get DataView.prototype.byteLength
+BUILTIN(DataViewPrototypeGetByteLength) {
+  HandleScope scope(isolate);
+  CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.byteLength");
+  // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError
+  // here if the JSArrayBuffer of the {data_view} was neutered.
+  return data_view->byte_length();
+}
+
+// ES6 section 24.2.4.3 get DataView.prototype.byteOffset
+BUILTIN(DataViewPrototypeGetByteOffset) {
+  HandleScope scope(isolate);
+  CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.byteOffset");
+  // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError
+  // here if the JSArrayBuffer of the {data_view} was neutered.
+  return data_view->byte_offset();
+}
+
+// -----------------------------------------------------------------------------
+// ES6 section 22.2 TypedArray Objects
+
+// ES6 section 22.2.3.1 get %TypedArray%.prototype.buffer
+BUILTIN(TypedArrayPrototypeBuffer) {
+  HandleScope scope(isolate);
+  CHECK_RECEIVER(JSTypedArray, typed_array, "get TypedArray.prototype.buffer");
+  return *typed_array->GetBuffer();
+}
+
+namespace {
+
+void Generate_TypedArrayProtoypeGetter(CodeStubAssembler* assembler,
+                                       const char* method_name,
+                                       int object_offset) {
+  typedef CodeStubAssembler::Label Label;
+  typedef compiler::Node Node;
+
+  Node* receiver = assembler->Parameter(0);
+  Node* context = assembler->Parameter(3);
+
+  // Check if the {receiver} is actually a JSTypedArray.
+  Label if_receiverisincompatible(assembler, Label::kDeferred);
+  assembler->GotoIf(assembler->WordIsSmi(receiver), &if_receiverisincompatible);
+  Node* receiver_instance_type = assembler->LoadInstanceType(receiver);
+  assembler->GotoUnless(
+      assembler->Word32Equal(receiver_instance_type,
+                             assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)),
+      &if_receiverisincompatible);
+
+  // Check if the {receiver}'s JSArrayBuffer was neutered.
+  Node* receiver_buffer =
+      assembler->LoadObjectField(receiver, JSTypedArray::kBufferOffset);
+  Node* receiver_buffer_bit_field = assembler->LoadObjectField(
+      receiver_buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32());
+  Label if_receiverisneutered(assembler, Label::kDeferred);
+  assembler->GotoUnless(
+      assembler->Word32Equal(
+          assembler->Word32And(
+              receiver_buffer_bit_field,
+              assembler->Int32Constant(JSArrayBuffer::WasNeutered::kMask)),
+          assembler->Int32Constant(0)),
+      &if_receiverisneutered);
+  assembler->Return(assembler->LoadObjectField(receiver, object_offset));
+
+  assembler->Bind(&if_receiverisneutered);
+  {
+    // The {receiver}s buffer was neutered, default to zero.
+    assembler->Return(assembler->SmiConstant(0));
+  }
+
+  assembler->Bind(&if_receiverisincompatible);
+  {
+    // The {receiver} is not a valid JSGeneratorObject.
+    Node* result = assembler->CallRuntime(
+        Runtime::kThrowIncompatibleMethodReceiver, context,
+        assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
+            method_name, TENURED)),
+        receiver);
+    assembler->Return(result);  // Never reached.
+  }
+}
+
+}  // namespace
+
+// ES6 section 22.2.3.2 get %TypedArray%.prototype.byteLength
+void Builtins::Generate_TypedArrayPrototypeByteLength(
+    CodeStubAssembler* assembler) {
+  Generate_TypedArrayProtoypeGetter(assembler,
+                                    "get TypedArray.prototype.byteLength",
+                                    JSTypedArray::kByteLengthOffset);
+}
+
+// ES6 section 22.2.3.3 get %TypedArray%.prototype.byteOffset
+void Builtins::Generate_TypedArrayPrototypeByteOffset(
+    CodeStubAssembler* assembler) {
+  Generate_TypedArrayProtoypeGetter(assembler,
+                                    "get TypedArray.prototype.byteOffset",
+                                    JSTypedArray::kByteOffsetOffset);
+}
+
+// ES6 section 22.2.3.18 get %TypedArray%.prototype.length
+void Builtins::Generate_TypedArrayPrototypeLength(
+    CodeStubAssembler* assembler) {
+  Generate_TypedArrayProtoypeGetter(assembler,
+                                    "get TypedArray.prototype.length",
+                                    JSTypedArray::kLengthOffset);
+}
 
 // -----------------------------------------------------------------------------
 // ES6 section 20.3 Date Objects
@@ -2889,11 +3397,9 @@
   String::FlatContent str_content = str->GetFlatContent();
   bool result;
   if (str_content.IsOneByte()) {
-    result = DateParser::Parse(str_content.ToOneByteVector(), *tmp,
-                               isolate->unicode_cache());
+    result = DateParser::Parse(isolate, str_content.ToOneByteVector(), *tmp);
   } else {
-    result = DateParser::Parse(str_content.ToUC16Vector(), *tmp,
-                               isolate->unicode_cache());
+    result = DateParser::Parse(isolate, str_content.ToUC16Vector(), *tmp);
   }
   if (!result) return std::numeric_limits<double>::quiet_NaN();
   double const day = MakeDay(tmp->get(0)->Number(), tmp->get(1)->Number(),
@@ -2901,7 +3407,7 @@
   double const time = MakeTime(tmp->get(3)->Number(), tmp->get(4)->Number(),
                                tmp->get(5)->Number(), tmp->get(6)->Number());
   double date = MakeDate(day, time);
-  if (tmp->get(7)->IsNull()) {
+  if (tmp->get(7)->IsNull(isolate)) {
     if (!std::isnan(date)) {
       date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date));
     }
@@ -2971,13 +3477,9 @@
   HandleScope scope(isolate);
   double const time_val = JSDate::CurrentTimeValue(isolate);
   char buffer[128];
-  Vector<char> str(buffer, arraysize(buffer));
-  ToDateString(time_val, str, isolate->date_cache());
-  Handle<String> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
-  return *result;
+  ToDateString(time_val, ArrayVector(buffer), isolate->date_cache());
+  RETURN_RESULT_OR_FAILURE(
+      isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
 }
 
 
@@ -3059,10 +3561,7 @@
       time_val = std::numeric_limits<double>::quiet_NaN();
     }
   }
-  Handle<JSDate> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     JSDate::New(target, new_target, time_val));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, JSDate::New(target, new_target, time_val));
 }
 
 
@@ -3555,13 +4054,10 @@
   HandleScope scope(isolate);
   CHECK_RECEIVER(JSDate, date, "Date.prototype.toDateString");
   char buffer[128];
-  Vector<char> str(buffer, arraysize(buffer));
-  ToDateString(date->value()->Number(), str, isolate->date_cache(), kDateOnly);
-  Handle<String> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
-  return *result;
+  ToDateString(date->value()->Number(), ArrayVector(buffer),
+               isolate->date_cache(), kDateOnly);
+  RETURN_RESULT_OR_FAILURE(
+      isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
 }
 
 
@@ -3579,18 +4075,17 @@
   isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
                                        &hour, &min, &sec, &ms);
   char buffer[128];
-  Vector<char> str(buffer, arraysize(buffer));
   if (year >= 0 && year <= 9999) {
-    SNPrintF(str, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, month + 1, day,
-             hour, min, sec, ms);
+    SNPrintF(ArrayVector(buffer), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", year,
+             month + 1, day, hour, min, sec, ms);
   } else if (year < 0) {
-    SNPrintF(str, "-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", -year, month + 1, day,
-             hour, min, sec, ms);
+    SNPrintF(ArrayVector(buffer), "-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", -year,
+             month + 1, day, hour, min, sec, ms);
   } else {
-    SNPrintF(str, "+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, month + 1, day,
-             hour, min, sec, ms);
+    SNPrintF(ArrayVector(buffer), "+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", year,
+             month + 1, day, hour, min, sec, ms);
   }
-  return *isolate->factory()->NewStringFromAsciiChecked(str.start());
+  return *isolate->factory()->NewStringFromAsciiChecked(buffer);
 }
 
 
@@ -3599,13 +4094,10 @@
   HandleScope scope(isolate);
   CHECK_RECEIVER(JSDate, date, "Date.prototype.toString");
   char buffer[128];
-  Vector<char> str(buffer, arraysize(buffer));
-  ToDateString(date->value()->Number(), str, isolate->date_cache());
-  Handle<String> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
-  return *result;
+  ToDateString(date->value()->Number(), ArrayVector(buffer),
+               isolate->date_cache());
+  RETURN_RESULT_OR_FAILURE(
+      isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
 }
 
 
@@ -3614,13 +4106,10 @@
   HandleScope scope(isolate);
   CHECK_RECEIVER(JSDate, date, "Date.prototype.toTimeString");
   char buffer[128];
-  Vector<char> str(buffer, arraysize(buffer));
-  ToDateString(date->value()->Number(), str, isolate->date_cache(), kTimeOnly);
-  Handle<String> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
-  return *result;
+  ToDateString(date->value()->Number(), ArrayVector(buffer),
+               isolate->date_cache(), kTimeOnly);
+  RETURN_RESULT_OR_FAILURE(
+      isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
 }
 
 
@@ -3633,14 +4122,14 @@
     return *isolate->factory()->NewStringFromAsciiChecked("Invalid Date");
   }
   char buffer[128];
-  Vector<char> str(buffer, arraysize(buffer));
   int64_t time_ms = static_cast<int64_t>(time_val);
   int year, month, day, weekday, hour, min, sec, ms;
   isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
                                        &hour, &min, &sec, &ms);
-  SNPrintF(str, "%s, %02d %s %4d %02d:%02d:%02d GMT", kShortWeekDays[weekday],
-           day, kShortMonths[month], year, hour, min, sec);
-  return *isolate->factory()->NewStringFromAsciiChecked(str.start());
+  SNPrintF(ArrayVector(buffer), "%s, %02d %s %4d %02d:%02d:%02d GMT",
+           kShortWeekDays[weekday], day, kShortMonths[month], year, hour, min,
+           sec);
+  return *isolate->factory()->NewStringFromAsciiChecked(buffer);
 }
 
 
@@ -3658,10 +4147,7 @@
   DCHECK_EQ(2, args.length());
   CHECK_RECEIVER(JSReceiver, receiver, "Date.prototype [ @@toPrimitive ]");
   Handle<Object> hint = args.at<Object>(1);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     JSDate::ToPrimitive(receiver, hint));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, JSDate::ToPrimitive(receiver, hint));
 }
 
 
@@ -3705,6 +4191,33 @@
   return SetLocalDateValue(date, time_val);
 }
 
+// ES6 section 20.3.4.37 Date.prototype.toJSON ( key )
+BUILTIN(DatePrototypeToJson) {
+  HandleScope scope(isolate);
+  Handle<Object> receiver = args.atOrUndefined(isolate, 0);
+  Handle<JSReceiver> receiver_obj;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_obj,
+                                     Object::ToObject(isolate, receiver));
+  Handle<Object> primitive;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, primitive,
+      Object::ToPrimitive(receiver_obj, ToPrimitiveHint::kNumber));
+  if (primitive->IsNumber() && !std::isfinite(primitive->Number())) {
+    return isolate->heap()->null_value();
+  } else {
+    Handle<String> name =
+        isolate->factory()->NewStringFromAsciiChecked("toISOString");
+    Handle<Object> function;
+    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, function,
+                                       Object::GetProperty(receiver_obj, name));
+    if (!function->IsCallable()) {
+      THROW_NEW_ERROR_RETURN_FAILURE(
+          isolate, NewTypeError(MessageTemplate::kCalledNonCallable, name));
+    }
+    RETURN_RESULT_OR_FAILURE(
+        isolate, Execution::Call(isolate, function, receiver_obj, 0, NULL));
+  }
+}
 
 // static
 void Builtins::Generate_DatePrototypeGetDate(MacroAssembler* masm) {
@@ -3817,10 +4330,9 @@
 namespace {
 
 // ES6 section 19.2.1.1.1 CreateDynamicFunction
-MaybeHandle<JSFunction> CreateDynamicFunction(
-    Isolate* isolate,
-    BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget> args,
-    const char* token) {
+MaybeHandle<JSFunction> CreateDynamicFunction(Isolate* isolate,
+                                              BuiltinArguments args,
+                                              const char* token) {
   // Compute number of arguments, ignoring the receiver.
   DCHECK_LE(1, args.length());
   int const argc = args.length() - 1;
@@ -3906,7 +4418,7 @@
   // function has wrong initial map. To fix that we create a new
   // function object with correct initial map.
   Handle<Object> unchecked_new_target = args.new_target();
-  if (!unchecked_new_target->IsUndefined() &&
+  if (!unchecked_new_target->IsUndefined(isolate) &&
       !unchecked_new_target.is_identical_to(target)) {
     Handle<JSReceiver> new_target =
         Handle<JSReceiver>::cast(unchecked_new_target);
@@ -3938,9 +4450,9 @@
   return *result;
 }
 
+namespace {
 
-// ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args )
-BUILTIN(FunctionPrototypeBind) {
+Object* DoFunctionBind(Isolate* isolate, BuiltinArguments args) {
   HandleScope scope(isolate);
   DCHECK_LE(1, args.length());
   if (!args.receiver()->IsCallable()) {
@@ -3963,45 +4475,82 @@
       isolate, function,
       isolate->factory()->NewJSBoundFunction(target, this_arg, argv));
 
-  // TODO(bmeurer): Optimize the rest for the common cases where {target} is
-  // a function with some initial map or even a bound function.
+  LookupIterator length_lookup(target, isolate->factory()->length_string(),
+                               target, LookupIterator::OWN);
   // Setup the "length" property based on the "length" of the {target}.
-  Handle<Object> length(Smi::FromInt(0), isolate);
-  Maybe<bool> target_has_length =
-      JSReceiver::HasOwnProperty(target, isolate->factory()->length_string());
-  if (!target_has_length.IsJust()) {
-    return isolate->heap()->exception();
-  } else if (target_has_length.FromJust()) {
-    Handle<Object> target_length;
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-        isolate, target_length,
-        JSReceiver::GetProperty(target, isolate->factory()->length_string()));
-    if (target_length->IsNumber()) {
-      length = isolate->factory()->NewNumber(std::max(
-          0.0, DoubleToInteger(target_length->Number()) - argv.length()));
+  // If the targets length is the default JSFunction accessor, we can keep the
+  // accessor that's installed by default on the JSBoundFunction. It lazily
+  // computes the value from the underlying internal length.
+  if (!target->IsJSFunction() ||
+      length_lookup.state() != LookupIterator::ACCESSOR ||
+      !length_lookup.GetAccessors()->IsAccessorInfo()) {
+    Handle<Object> length(Smi::FromInt(0), isolate);
+    Maybe<PropertyAttributes> attributes =
+        JSReceiver::GetPropertyAttributes(&length_lookup);
+    if (!attributes.IsJust()) return isolate->heap()->exception();
+    if (attributes.FromJust() != ABSENT) {
+      Handle<Object> target_length;
+      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_length,
+                                         Object::GetProperty(&length_lookup));
+      if (target_length->IsNumber()) {
+        length = isolate->factory()->NewNumber(std::max(
+            0.0, DoubleToInteger(target_length->Number()) - argv.length()));
+      }
     }
+    LookupIterator it(function, isolate->factory()->length_string(), function);
+    DCHECK_EQ(LookupIterator::ACCESSOR, it.state());
+    RETURN_FAILURE_ON_EXCEPTION(isolate,
+                                JSObject::DefineOwnPropertyIgnoreAttributes(
+                                    &it, length, it.property_attributes()));
   }
-  function->set_length(*length);
 
   // Setup the "name" property based on the "name" of the {target}.
-  Handle<Object> target_name;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, target_name,
-      JSReceiver::GetProperty(target, isolate->factory()->name_string()));
-  Handle<String> name;
-  if (!target_name->IsString()) {
-    name = isolate->factory()->bound__string();
-  } else {
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-        isolate, name, Name::ToFunctionName(Handle<String>::cast(target_name)));
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-        isolate, name, isolate->factory()->NewConsString(
-                           isolate->factory()->bound__string(), name));
+  // If the targets name is the default JSFunction accessor, we can keep the
+  // accessor that's installed by default on the JSBoundFunction. It lazily
+  // computes the value from the underlying internal name.
+  LookupIterator name_lookup(target, isolate->factory()->name_string(), target,
+                             LookupIterator::OWN);
+  if (!target->IsJSFunction() ||
+      name_lookup.state() != LookupIterator::ACCESSOR ||
+      !name_lookup.GetAccessors()->IsAccessorInfo()) {
+    Handle<Object> target_name;
+    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_name,
+                                       Object::GetProperty(&name_lookup));
+    Handle<String> name;
+    if (target_name->IsString()) {
+      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+          isolate, name,
+          Name::ToFunctionName(Handle<String>::cast(target_name)));
+      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+          isolate, name, isolate->factory()->NewConsString(
+                             isolate->factory()->bound__string(), name));
+    } else {
+      name = isolate->factory()->bound__string();
+    }
+    LookupIterator it(function, isolate->factory()->name_string());
+    DCHECK_EQ(LookupIterator::ACCESSOR, it.state());
+    RETURN_FAILURE_ON_EXCEPTION(isolate,
+                                JSObject::DefineOwnPropertyIgnoreAttributes(
+                                    &it, name, it.property_attributes()));
   }
-  function->set_name(*name);
   return *function;
 }
 
+}  // namespace
+
+// ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args )
+BUILTIN(FunctionPrototypeBind) { return DoFunctionBind(isolate, args); }
+
+// TODO(verwaest): This is a temporary helper until the FastFunctionBind stub
+// can tailcall to the builtin directly.
+RUNTIME_FUNCTION(Runtime_FunctionBind) {
+  DCHECK_EQ(2, args.length());
+  Arguments* incoming = reinterpret_cast<Arguments*>(args[0]);
+  // Rewrap the arguments as builtins arguments.
+  BuiltinArguments caller_args(incoming->length() + 3,
+                               incoming->arguments() + 1);
+  return DoFunctionBind(isolate, caller_args);
+}
 
 // ES6 section 19.2.3.5 Function.prototype.toString ( )
 BUILTIN(FunctionPrototypeToString) {
@@ -4022,19 +4571,31 @@
 // ES6 section 25.2.1.1 GeneratorFunction (p1, p2, ... , pn, body)
 BUILTIN(GeneratorFunctionConstructor) {
   HandleScope scope(isolate);
-  Handle<JSFunction> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, CreateDynamicFunction(isolate, args, "function*"));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate,
+                           CreateDynamicFunction(isolate, args, "function*"));
 }
 
+BUILTIN(AsyncFunctionConstructor) {
+  HandleScope scope(isolate);
+  Handle<JSFunction> func;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, func, CreateDynamicFunction(isolate, args, "async function"));
+
+  // Do not lazily compute eval position for AsyncFunction, as they may not be
+  // determined after the function is resumed.
+  Handle<Script> script = handle(Script::cast(func->shared()->script()));
+  int position = script->GetEvalPosition();
+  USE(position);
+
+  return *func;
+}
 
 // ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Call]] case.
 BUILTIN(SymbolConstructor) {
   HandleScope scope(isolate);
   Handle<Symbol> result = isolate->factory()->NewSymbol();
   Handle<Object> description = args.atOrUndefined(isolate, 1);
-  if (!description->IsUndefined()) {
+  if (!description->IsUndefined(isolate)) {
     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, description,
                                        Object::ToString(isolate, description));
     result->set_name(*description);
@@ -4056,78 +4617,501 @@
 BUILTIN(ObjectProtoToString) {
   HandleScope scope(isolate);
   Handle<Object> object = args.at<Object>(0);
-  Handle<String> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, Object::ObjectProtoToString(isolate, object));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate,
+                           Object::ObjectProtoToString(isolate, object));
 }
 
 // -----------------------------------------------------------------------------
 // ES6 section 21.1 String Objects
 
-namespace {
+// ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits )
+void Builtins::Generate_StringFromCharCode(CodeStubAssembler* assembler) {
+  typedef CodeStubAssembler::Label Label;
+  typedef compiler::Node Node;
+  typedef CodeStubAssembler::Variable Variable;
 
-bool ToUint16(Handle<Object> value, uint16_t* result) {
-  if (value->IsNumber() || Object::ToNumber(value).ToHandle(&value)) {
-    *result = DoubleToUint32(value->Number());
-    return true;
+  Node* code = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+
+  // Check if we have exactly one argument (plus the implicit receiver), i.e.
+  // if the parent frame is not an arguments adaptor frame.
+  Label if_oneargument(assembler), if_notoneargument(assembler);
+  Node* parent_frame_pointer = assembler->LoadParentFramePointer();
+  Node* parent_frame_type =
+      assembler->Load(MachineType::Pointer(), parent_frame_pointer,
+                      assembler->IntPtrConstant(
+                          CommonFrameConstants::kContextOrFrameTypeOffset));
+  assembler->Branch(
+      assembler->WordEqual(
+          parent_frame_type,
+          assembler->SmiConstant(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))),
+      &if_notoneargument, &if_oneargument);
+
+  assembler->Bind(&if_oneargument);
+  {
+    // Single argument case, perform fast single character string cache lookup
+    // for one-byte code units, or fall back to creating a single character
+    // string on the fly otherwise.
+    Node* code32 = assembler->TruncateTaggedToWord32(context, code);
+    Node* code16 = assembler->Word32And(
+        code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
+    Node* result = assembler->StringFromCharCode(code16);
+    assembler->Return(result);
   }
-  return false;
+
+  assembler->Bind(&if_notoneargument);
+  {
+    // Determine the resulting string length.
+    Node* parent_frame_length =
+        assembler->Load(MachineType::Pointer(), parent_frame_pointer,
+                        assembler->IntPtrConstant(
+                            ArgumentsAdaptorFrameConstants::kLengthOffset));
+    Node* length = assembler->SmiToWord(parent_frame_length);
+
+    // Assume that the resulting string contains only one-byte characters.
+    Node* result = assembler->AllocateSeqOneByteString(context, length);
+
+    // Truncate all input parameters and append them to the resulting string.
+    Variable var_offset(assembler, MachineType::PointerRepresentation());
+    Label loop(assembler, &var_offset), done_loop(assembler);
+    var_offset.Bind(assembler->IntPtrConstant(0));
+    assembler->Goto(&loop);
+    assembler->Bind(&loop);
+    {
+      // Load the current {offset}.
+      Node* offset = var_offset.value();
+
+      // Check if we're done with the string.
+      assembler->GotoIf(assembler->WordEqual(offset, length), &done_loop);
+
+      // Load the next code point and truncate it to a 16-bit value.
+      Node* code = assembler->Load(
+          MachineType::AnyTagged(), parent_frame_pointer,
+          assembler->IntPtrAdd(
+              assembler->WordShl(assembler->IntPtrSub(length, offset),
+                                 assembler->IntPtrConstant(kPointerSizeLog2)),
+              assembler->IntPtrConstant(
+                  CommonFrameConstants::kFixedFrameSizeAboveFp -
+                  kPointerSize)));
+      Node* code32 = assembler->TruncateTaggedToWord32(context, code);
+      Node* code16 = assembler->Word32And(
+          code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
+
+      // Check if {code16} fits into a one-byte string.
+      Label if_codeisonebyte(assembler), if_codeistwobyte(assembler);
+      assembler->Branch(
+          assembler->Int32LessThanOrEqual(
+              code16, assembler->Int32Constant(String::kMaxOneByteCharCode)),
+          &if_codeisonebyte, &if_codeistwobyte);
+
+      assembler->Bind(&if_codeisonebyte);
+      {
+        // The {code16} fits into the SeqOneByteString {result}.
+        assembler->StoreNoWriteBarrier(
+            MachineRepresentation::kWord8, result,
+            assembler->IntPtrAdd(
+                assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
+                                          kHeapObjectTag),
+                offset),
+            code16);
+        var_offset.Bind(
+            assembler->IntPtrAdd(offset, assembler->IntPtrConstant(1)));
+        assembler->Goto(&loop);
+      }
+
+      assembler->Bind(&if_codeistwobyte);
+      {
+        // Allocate a SeqTwoByteString to hold the resulting string.
+        Node* cresult = assembler->AllocateSeqTwoByteString(context, length);
+
+        // Copy all characters that were previously written to the
+        // SeqOneByteString in {result} over to the new {cresult}.
+        Variable var_coffset(assembler, MachineType::PointerRepresentation());
+        Label cloop(assembler, &var_coffset), done_cloop(assembler);
+        var_coffset.Bind(assembler->IntPtrConstant(0));
+        assembler->Goto(&cloop);
+        assembler->Bind(&cloop);
+        {
+          Node* coffset = var_coffset.value();
+          assembler->GotoIf(assembler->WordEqual(coffset, offset), &done_cloop);
+          Node* ccode = assembler->Load(
+              MachineType::Uint8(), result,
+              assembler->IntPtrAdd(
+                  assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
+                                            kHeapObjectTag),
+                  coffset));
+          assembler->StoreNoWriteBarrier(
+              MachineRepresentation::kWord16, cresult,
+              assembler->IntPtrAdd(
+                  assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
+                                            kHeapObjectTag),
+                  assembler->WordShl(coffset, 1)),
+              ccode);
+          var_coffset.Bind(
+              assembler->IntPtrAdd(coffset, assembler->IntPtrConstant(1)));
+          assembler->Goto(&cloop);
+        }
+
+        // Write the pending {code16} to {offset}.
+        assembler->Bind(&done_cloop);
+        assembler->StoreNoWriteBarrier(
+            MachineRepresentation::kWord16, cresult,
+            assembler->IntPtrAdd(
+                assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
+                                          kHeapObjectTag),
+                assembler->WordShl(offset, 1)),
+            code16);
+
+        // Copy the remaining parameters to the SeqTwoByteString {cresult}.
+        Label floop(assembler, &var_offset), done_floop(assembler);
+        assembler->Goto(&floop);
+        assembler->Bind(&floop);
+        {
+          // Compute the next {offset}.
+          Node* offset = assembler->IntPtrAdd(var_offset.value(),
+                                              assembler->IntPtrConstant(1));
+
+          // Check if we're done with the string.
+          assembler->GotoIf(assembler->WordEqual(offset, length), &done_floop);
+
+          // Load the next code point and truncate it to a 16-bit value.
+          Node* code = assembler->Load(
+              MachineType::AnyTagged(), parent_frame_pointer,
+              assembler->IntPtrAdd(
+                  assembler->WordShl(
+                      assembler->IntPtrSub(length, offset),
+                      assembler->IntPtrConstant(kPointerSizeLog2)),
+                  assembler->IntPtrConstant(
+                      CommonFrameConstants::kFixedFrameSizeAboveFp -
+                      kPointerSize)));
+          Node* code32 = assembler->TruncateTaggedToWord32(context, code);
+          Node* code16 = assembler->Word32And(
+              code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
+
+          // Store the truncated {code} point at the next offset.
+          assembler->StoreNoWriteBarrier(
+              MachineRepresentation::kWord16, cresult,
+              assembler->IntPtrAdd(
+                  assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
+                                            kHeapObjectTag),
+                  assembler->WordShl(offset, 1)),
+              code16);
+          var_offset.Bind(offset);
+          assembler->Goto(&floop);
+        }
+
+        // Return the SeqTwoByteString.
+        assembler->Bind(&done_floop);
+        assembler->Return(cresult);
+      }
+    }
+
+    assembler->Bind(&done_loop);
+    assembler->Return(result);
+  }
+}
+
+namespace {  // for String.fromCodePoint
+
+bool IsValidCodePoint(Isolate* isolate, Handle<Object> value) {
+  if (!value->IsNumber() && !Object::ToNumber(value).ToHandle(&value)) {
+    return false;
+  }
+
+  if (Object::ToInteger(isolate, value).ToHandleChecked()->Number() !=
+      value->Number()) {
+    return false;
+  }
+
+  if (value->Number() < 0 || value->Number() > 0x10FFFF) {
+    return false;
+  }
+
+  return true;
+}
+
+uc32 NextCodePoint(Isolate* isolate, BuiltinArguments args, int index) {
+  Handle<Object> value = args.at<Object>(1 + index);
+  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, value, Object::ToNumber(value), -1);
+  if (!IsValidCodePoint(isolate, value)) {
+    isolate->Throw(*isolate->factory()->NewRangeError(
+        MessageTemplate::kInvalidCodePoint, value));
+    return -1;
+  }
+  return DoubleToUint32(value->Number());
 }
 
 }  // namespace
 
-// ES6 21.1.2.1 String.fromCharCode ( ...codeUnits )
-BUILTIN(StringFromCharCode) {
+// ES6 section 21.1.2.2 String.fromCodePoint ( ...codePoints )
+BUILTIN(StringFromCodePoint) {
   HandleScope scope(isolate);
-  // Check resulting string length.
-  int index = 0;
-  Handle<String> result;
   int const length = args.length() - 1;
   if (length == 0) return isolate->heap()->empty_string();
   DCHECK_LT(0, length);
-  // Load the first character code.
-  uint16_t code;
-  if (!ToUint16(args.at<Object>(1), &code)) return isolate->heap()->exception();
-  // Assume that the resulting String contains only one byte characters.
-  if (code <= String::kMaxOneByteCharCodeU) {
-    // Check for single one-byte character fast case.
-    if (length == 1) {
-      return *isolate->factory()->LookupSingleCharacterStringFromCode(code);
+
+  // Optimistically assume that the resulting String contains only one byte
+  // characters.
+  List<uint8_t> one_byte_buffer(length);
+  uc32 code = 0;
+  int index;
+  for (index = 0; index < length; index++) {
+    code = NextCodePoint(isolate, args, index);
+    if (code < 0) {
+      return isolate->heap()->exception();
     }
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-        isolate, result, isolate->factory()->NewRawOneByteString(length));
-    do {
-      Handle<SeqOneByteString>::cast(result)->Set(index, code);
-      if (++index == length) break;
-      if (!ToUint16(args.at<Object>(1 + index), &code)) {
-        return isolate->heap()->exception();
-      }
-    } while (code <= String::kMaxOneByteCharCodeU);
+    if (code > String::kMaxOneByteCharCode) {
+      break;
+    }
+    one_byte_buffer.Add(code);
   }
-  // Check if all characters fit into the one byte range.
-  if (index < length) {
-    // Fallback to two byte string.
-    Handle<String> new_result;
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-        isolate, new_result, isolate->factory()->NewRawTwoByteString(length));
-    for (int new_index = 0; new_index < index; ++new_index) {
-      uint16_t new_code =
-          Handle<SeqOneByteString>::cast(result)->Get(new_index);
-      Handle<SeqTwoByteString>::cast(new_result)->Set(new_index, new_code);
-    }
-    while (true) {
-      Handle<SeqTwoByteString>::cast(new_result)->Set(index, code);
-      if (++index == length) break;
-      if (!ToUint16(args.at<Object>(1 + index), &code)) {
-        return isolate->heap()->exception();
-      }
-    }
-    result = new_result;
+
+  if (index == length) {
+    RETURN_RESULT_OR_FAILURE(isolate, isolate->factory()->NewStringFromOneByte(
+                                          one_byte_buffer.ToConstVector()));
   }
+
+  List<uc16> two_byte_buffer(length - index);
+
+  while (true) {
+    if (code <= unibrow::Utf16::kMaxNonSurrogateCharCode) {
+      two_byte_buffer.Add(code);
+    } else {
+      two_byte_buffer.Add(unibrow::Utf16::LeadSurrogate(code));
+      two_byte_buffer.Add(unibrow::Utf16::TrailSurrogate(code));
+    }
+
+    if (++index == length) {
+      break;
+    }
+    code = NextCodePoint(isolate, args, index);
+    if (code < 0) {
+      return isolate->heap()->exception();
+    }
+  }
+
+  Handle<SeqTwoByteString> result;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, result,
+      isolate->factory()->NewRawTwoByteString(one_byte_buffer.length() +
+                                              two_byte_buffer.length()));
+
+  CopyChars(result->GetChars(), one_byte_buffer.ToConstVector().start(),
+            one_byte_buffer.length());
+  CopyChars(result->GetChars() + one_byte_buffer.length(),
+            two_byte_buffer.ToConstVector().start(), two_byte_buffer.length());
+
   return *result;
 }
 
+// ES6 section 21.1.3.1 String.prototype.charAt ( pos )
+void Builtins::Generate_StringPrototypeCharAt(CodeStubAssembler* assembler) {
+  typedef CodeStubAssembler::Label Label;
+  typedef compiler::Node Node;
+  typedef CodeStubAssembler::Variable Variable;
+
+  Node* receiver = assembler->Parameter(0);
+  Node* position = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+
+  // Check that {receiver} is coercible to Object and convert it to a String.
+  receiver =
+      assembler->ToThisString(context, receiver, "String.prototype.charAt");
+
+  // Convert the {position} to a Smi and check that it's in bounds of the
+  // {receiver}.
+  // TODO(bmeurer): Find an abstraction for this!
+  {
+    // Check if the {position} is already a Smi.
+    Variable var_position(assembler, MachineRepresentation::kTagged);
+    var_position.Bind(position);
+    Label if_positionissmi(assembler),
+        if_positionisnotsmi(assembler, Label::kDeferred);
+    assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi,
+                      &if_positionisnotsmi);
+    assembler->Bind(&if_positionisnotsmi);
+    {
+      // Convert the {position} to an Integer via the ToIntegerStub.
+      Callable callable = CodeFactory::ToInteger(assembler->isolate());
+      Node* index = assembler->CallStub(callable, context, position);
+
+      // Check if the resulting {index} is now a Smi.
+      Label if_indexissmi(assembler, Label::kDeferred),
+          if_indexisnotsmi(assembler, Label::kDeferred);
+      assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi,
+                        &if_indexisnotsmi);
+
+      assembler->Bind(&if_indexissmi);
+      {
+        var_position.Bind(index);
+        assembler->Goto(&if_positionissmi);
+      }
+
+      assembler->Bind(&if_indexisnotsmi);
+      {
+        // The ToIntegerStub canonicalizes everything in Smi range to Smi
+        // representation, so any HeapNumber returned is not in Smi range.
+        // The only exception here is -0.0, which we treat as 0.
+        Node* index_value = assembler->LoadHeapNumberValue(index);
+        Label if_indexiszero(assembler, Label::kDeferred),
+            if_indexisnotzero(assembler, Label::kDeferred);
+        assembler->Branch(assembler->Float64Equal(
+                              index_value, assembler->Float64Constant(0.0)),
+                          &if_indexiszero, &if_indexisnotzero);
+
+        assembler->Bind(&if_indexiszero);
+        {
+          var_position.Bind(assembler->SmiConstant(Smi::FromInt(0)));
+          assembler->Goto(&if_positionissmi);
+        }
+
+        assembler->Bind(&if_indexisnotzero);
+        {
+          // The {index} is some other integral Number, that is definitely
+          // neither -0.0 nor in Smi range.
+          assembler->Return(assembler->EmptyStringConstant());
+        }
+      }
+    }
+    assembler->Bind(&if_positionissmi);
+    position = var_position.value();
+
+    // Determine the actual length of the {receiver} String.
+    Node* receiver_length =
+        assembler->LoadObjectField(receiver, String::kLengthOffset);
+
+    // Return "" if the Smi {position} is outside the bounds of the {receiver}.
+    Label if_positioninbounds(assembler),
+        if_positionnotinbounds(assembler, Label::kDeferred);
+    assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length),
+                      &if_positionnotinbounds, &if_positioninbounds);
+    assembler->Bind(&if_positionnotinbounds);
+    assembler->Return(assembler->EmptyStringConstant());
+    assembler->Bind(&if_positioninbounds);
+  }
+
+  // Load the character code at the {position} from the {receiver}.
+  Node* code = assembler->StringCharCodeAt(receiver, position);
+
+  // And return the single character string with only that {code}.
+  Node* result = assembler->StringFromCharCode(code);
+  assembler->Return(result);
+}
+
+// ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos )
+void Builtins::Generate_StringPrototypeCharCodeAt(
+    CodeStubAssembler* assembler) {
+  typedef CodeStubAssembler::Label Label;
+  typedef compiler::Node Node;
+  typedef CodeStubAssembler::Variable Variable;
+
+  Node* receiver = assembler->Parameter(0);
+  Node* position = assembler->Parameter(1);
+  Node* context = assembler->Parameter(4);
+
+  // Check that {receiver} is coercible to Object and convert it to a String.
+  receiver =
+      assembler->ToThisString(context, receiver, "String.prototype.charCodeAt");
+
+  // Convert the {position} to a Smi and check that it's in bounds of the
+  // {receiver}.
+  // TODO(bmeurer): Find an abstraction for this!
+  {
+    // Check if the {position} is already a Smi.
+    Variable var_position(assembler, MachineRepresentation::kTagged);
+    var_position.Bind(position);
+    Label if_positionissmi(assembler),
+        if_positionisnotsmi(assembler, Label::kDeferred);
+    assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi,
+                      &if_positionisnotsmi);
+    assembler->Bind(&if_positionisnotsmi);
+    {
+      // Convert the {position} to an Integer via the ToIntegerStub.
+      Callable callable = CodeFactory::ToInteger(assembler->isolate());
+      Node* index = assembler->CallStub(callable, context, position);
+
+      // Check if the resulting {index} is now a Smi.
+      Label if_indexissmi(assembler, Label::kDeferred),
+          if_indexisnotsmi(assembler, Label::kDeferred);
+      assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi,
+                        &if_indexisnotsmi);
+
+      assembler->Bind(&if_indexissmi);
+      {
+        var_position.Bind(index);
+        assembler->Goto(&if_positionissmi);
+      }
+
+      assembler->Bind(&if_indexisnotsmi);
+      {
+        // The ToIntegerStub canonicalizes everything in Smi range to Smi
+        // representation, so any HeapNumber returned is not in Smi range.
+        // The only exception here is -0.0, which we treat as 0.
+        Node* index_value = assembler->LoadHeapNumberValue(index);
+        Label if_indexiszero(assembler, Label::kDeferred),
+            if_indexisnotzero(assembler, Label::kDeferred);
+        assembler->Branch(assembler->Float64Equal(
+                              index_value, assembler->Float64Constant(0.0)),
+                          &if_indexiszero, &if_indexisnotzero);
+
+        assembler->Bind(&if_indexiszero);
+        {
+          var_position.Bind(assembler->SmiConstant(Smi::FromInt(0)));
+          assembler->Goto(&if_positionissmi);
+        }
+
+        assembler->Bind(&if_indexisnotzero);
+        {
+          // The {index} is some other integral Number, that is definitely
+          // neither -0.0 nor in Smi range.
+          assembler->Return(assembler->NaNConstant());
+        }
+      }
+    }
+    assembler->Bind(&if_positionissmi);
+    position = var_position.value();
+
+    // Determine the actual length of the {receiver} String.
+    Node* receiver_length =
+        assembler->LoadObjectField(receiver, String::kLengthOffset);
+
+    // Return NaN if the Smi {position} is outside the bounds of the {receiver}.
+    Label if_positioninbounds(assembler),
+        if_positionnotinbounds(assembler, Label::kDeferred);
+    assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length),
+                      &if_positionnotinbounds, &if_positioninbounds);
+    assembler->Bind(&if_positionnotinbounds);
+    assembler->Return(assembler->NaNConstant());
+    assembler->Bind(&if_positioninbounds);
+  }
+
+  // Load the character at the {position} from the {receiver}.
+  Node* value = assembler->StringCharCodeAt(receiver, position);
+  Node* result = assembler->SmiFromWord32(value);
+  assembler->Return(result);
+}
+
+// ES6 section 21.1.3.25 String.prototype.trim ()
+BUILTIN(StringPrototypeTrim) {
+  HandleScope scope(isolate);
+  TO_THIS_STRING(string, "String.prototype.trim");
+  return *String::Trim(string, String::kTrim);
+}
+
+// Non-standard WebKit extension
+BUILTIN(StringPrototypeTrimLeft) {
+  HandleScope scope(isolate);
+  TO_THIS_STRING(string, "String.prototype.trimLeft");
+  return *String::Trim(string, String::kTrimLeft);
+}
+
+// Non-standard WebKit extension
+BUILTIN(StringPrototypeTrimRight) {
+  HandleScope scope(isolate);
+  TO_THIS_STRING(string, "String.prototype.trimRight");
+  return *String::Trim(string, String::kTrimRight);
+}
+
 // -----------------------------------------------------------------------------
 // ES6 section 21.1 ArrayBuffer Objects
 
@@ -4205,10 +5189,7 @@
   DCHECK(isolate->proxy_function()->IsConstructor());
   Handle<Object> target = args.atOrUndefined(isolate, 1);
   Handle<Object> handler = args.atOrUndefined(isolate, 2);
-  Handle<JSProxy> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     JSProxy::New(isolate, target, handler));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, JSProxy::New(isolate, target, handler));
 }
 
 
@@ -4237,23 +5218,38 @@
 
 namespace {
 
+// Returns the holder JSObject if the function can legally be called with this
+// receiver.  Returns nullptr if the call is illegal.
+// TODO(dcarney): CallOptimization duplicates this logic, merge.
+JSObject* GetCompatibleReceiver(Isolate* isolate, FunctionTemplateInfo* info,
+                                JSObject* receiver) {
+  Object* recv_type = info->signature();
+  // No signature, return holder.
+  if (!recv_type->IsFunctionTemplateInfo()) return receiver;
+  FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type);
+
+  // Check the receiver. Fast path for receivers with no hidden prototypes.
+  if (signature->IsTemplateFor(receiver)) return receiver;
+  if (!receiver->map()->has_hidden_prototype()) return nullptr;
+  for (PrototypeIterator iter(isolate, receiver, kStartAtPrototype,
+                              PrototypeIterator::END_AT_NON_HIDDEN);
+       !iter.IsAtEnd(); iter.Advance()) {
+    JSObject* current = iter.GetCurrent<JSObject>();
+    if (signature->IsTemplateFor(current)) return current;
+  }
+  return nullptr;
+}
+
 template <bool is_construct>
 MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(
-    Isolate* isolate, BuiltinArguments<BuiltinExtraArguments::kTarget> args) {
-  HandleScope scope(isolate);
-  Handle<HeapObject> function = args.target<HeapObject>();
-  Handle<JSReceiver> receiver;
-
-  DCHECK(function->IsFunctionTemplateInfo() ||
-         Handle<JSFunction>::cast(function)->shared()->IsApiFunction());
-
-  Handle<FunctionTemplateInfo> fun_data =
-      function->IsFunctionTemplateInfo()
-          ? Handle<FunctionTemplateInfo>::cast(function)
-          : handle(JSFunction::cast(*function)->shared()->get_api_func_data());
+    Isolate* isolate, Handle<HeapObject> function,
+    Handle<HeapObject> new_target, Handle<FunctionTemplateInfo> fun_data,
+    Handle<Object> receiver, BuiltinArguments args) {
+  Handle<JSObject> js_receiver;
+  JSObject* raw_holder;
   if (is_construct) {
-    DCHECK(args.receiver()->IsTheHole());
-    if (fun_data->instance_template()->IsUndefined()) {
+    DCHECK(args.receiver()->IsTheHole(isolate));
+    if (fun_data->instance_template()->IsUndefined(isolate)) {
       v8::Local<ObjectTemplate> templ =
           ObjectTemplate::New(reinterpret_cast<v8::Isolate*>(isolate),
                               ToApiHandle<v8::FunctionTemplate>(fun_data));
@@ -4261,36 +5257,44 @@
     }
     Handle<ObjectTemplateInfo> instance_template(
         ObjectTemplateInfo::cast(fun_data->instance_template()), isolate);
-    ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
-                               ApiNatives::InstantiateObject(instance_template),
-                               Object);
-    args[0] = *receiver;
-    DCHECK_EQ(*receiver, *args.receiver());
-  } else {
-    DCHECK(args.receiver()->IsJSReceiver());
-    receiver = args.at<JSReceiver>(0);
-  }
+    ASSIGN_RETURN_ON_EXCEPTION(
+        isolate, js_receiver,
+        ApiNatives::InstantiateObject(instance_template,
+                                      Handle<JSReceiver>::cast(new_target)),
+        Object);
+    args[0] = *js_receiver;
+    DCHECK_EQ(*js_receiver, *args.receiver());
 
-  if (!is_construct && !fun_data->accept_any_receiver()) {
-    if (receiver->IsJSObject() && receiver->IsAccessCheckNeeded()) {
-      Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver);
-      if (!isolate->MayAccess(handle(isolate->context()), js_receiver)) {
-        isolate->ReportFailedAccessCheck(js_receiver);
-        RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
-      }
+    raw_holder = *js_receiver;
+  } else {
+    DCHECK(receiver->IsJSReceiver());
+
+    if (!receiver->IsJSObject()) {
+      // This function cannot be called with the given receiver.  Abort!
+      THROW_NEW_ERROR(
+          isolate, NewTypeError(MessageTemplate::kIllegalInvocation), Object);
+    }
+
+    js_receiver = Handle<JSObject>::cast(receiver);
+
+    if (!fun_data->accept_any_receiver() &&
+        js_receiver->IsAccessCheckNeeded() &&
+        !isolate->MayAccess(handle(isolate->context()), js_receiver)) {
+      isolate->ReportFailedAccessCheck(js_receiver);
+      RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
+    }
+
+    raw_holder = GetCompatibleReceiver(isolate, *fun_data, *js_receiver);
+
+    if (raw_holder == nullptr) {
+      // This function cannot be called with the given receiver.  Abort!
+      THROW_NEW_ERROR(
+          isolate, NewTypeError(MessageTemplate::kIllegalInvocation), Object);
     }
   }
 
-  Object* raw_holder = fun_data->GetCompatibleReceiver(isolate, *receiver);
-
-  if (raw_holder->IsNull()) {
-    // This function cannot be called with the given receiver.  Abort!
-    THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kIllegalInvocation),
-                    Object);
-  }
-
   Object* raw_call_data = fun_data->call_code();
-  if (!raw_call_data->IsUndefined()) {
+  if (!raw_call_data->IsUndefined(isolate)) {
     DCHECK(raw_call_data->IsCallHandlerInfo());
     CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
     Object* callback_obj = call_data->callback();
@@ -4298,27 +5302,25 @@
         v8::ToCData<v8::FunctionCallback>(callback_obj);
     Object* data_obj = call_data->data();
 
-    LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver())));
-    DCHECK(raw_holder->IsJSObject());
+    LOG(isolate, ApiObjectAccess("call", JSObject::cast(*js_receiver)));
 
-    FunctionCallbackArguments custom(isolate,
-                                     data_obj,
-                                     *function,
-                                     raw_holder,
-                                     &args[0] - 1,
-                                     args.length() - 1,
-                                     is_construct);
+    FunctionCallbackArguments custom(isolate, data_obj, *function, raw_holder,
+                                     *new_target, &args[0] - 1,
+                                     args.length() - 1);
 
     Handle<Object> result = custom.Call(callback);
-    if (result.is_null()) result = isolate->factory()->undefined_value();
 
     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
-    if (!is_construct || result->IsJSObject()) {
-      return scope.CloseAndEscape(result);
+    if (result.is_null()) {
+      if (is_construct) return js_receiver;
+      return isolate->factory()->undefined_value();
     }
+    // Rebox the result.
+    result->VerifyApiCallResultType();
+    if (!is_construct || result->IsJSObject()) return handle(*result, isolate);
   }
 
-  return scope.CloseAndEscape(receiver);
+  return js_receiver;
 }
 
 }  // namespace
@@ -4326,21 +5328,23 @@
 
 BUILTIN(HandleApiCall) {
   HandleScope scope(isolate);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     HandleApiCallHelper<false>(isolate, args));
-  return *result;
+  Handle<JSFunction> function = args.target<JSFunction>();
+  Handle<Object> receiver = args.receiver();
+  Handle<HeapObject> new_target = args.new_target();
+  Handle<FunctionTemplateInfo> fun_data(function->shared()->get_api_func_data(),
+                                        isolate);
+  if (new_target->IsJSReceiver()) {
+    RETURN_RESULT_OR_FAILURE(
+        isolate, HandleApiCallHelper<true>(isolate, function, new_target,
+                                           fun_data, receiver, args));
+  } else {
+    RETURN_RESULT_OR_FAILURE(
+        isolate, HandleApiCallHelper<false>(isolate, function, new_target,
+                                            fun_data, receiver, args));
+  }
 }
 
 
-BUILTIN(HandleApiCallConstruct) {
-  HandleScope scope(isolate);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     HandleApiCallHelper<true>(isolate, args));
-  return *result;
-}
-
 Handle<Code> Builtins::CallFunction(ConvertReceiverMode mode,
                                     TailCallMode tail_call_mode) {
   switch (tail_call_mode) {
@@ -4421,13 +5425,10 @@
 
 namespace {
 
-class RelocatableArguments
-    : public BuiltinArguments<BuiltinExtraArguments::kTarget>,
-      public Relocatable {
+class RelocatableArguments : public BuiltinArguments, public Relocatable {
  public:
   RelocatableArguments(Isolate* isolate, int length, Object** arguments)
-      : BuiltinArguments<BuiltinExtraArguments::kTarget>(length, arguments),
-        Relocatable(isolate) {}
+      : BuiltinArguments(length, arguments), Relocatable(isolate) {}
 
   virtual inline void IterateInstance(ObjectVisitor* v) {
     if (length() == 0) return;
@@ -4440,46 +5441,54 @@
 
 }  // namespace
 
-MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<HeapObject> function,
+MaybeHandle<Object> Builtins::InvokeApiFunction(Isolate* isolate,
+                                                Handle<HeapObject> function,
                                                 Handle<Object> receiver,
                                                 int argc,
                                                 Handle<Object> args[]) {
-  Isolate* isolate = function->GetIsolate();
+  DCHECK(function->IsFunctionTemplateInfo() ||
+         (function->IsJSFunction() &&
+          JSFunction::cast(*function)->shared()->IsApiFunction()));
+
   // Do proper receiver conversion for non-strict mode api functions.
   if (!receiver->IsJSReceiver()) {
-    DCHECK(function->IsFunctionTemplateInfo() || function->IsJSFunction());
     if (function->IsFunctionTemplateInfo() ||
         is_sloppy(JSFunction::cast(*function)->shared()->language_mode())) {
-      if (receiver->IsUndefined() || receiver->IsNull()) {
-        receiver = handle(isolate->global_proxy(), isolate);
-      } else {
-        ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
-                                   Object::ToObject(isolate, receiver), Object);
-      }
+      ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
+                                 Object::ConvertReceiver(isolate, receiver),
+                                 Object);
     }
   }
-  // Construct BuiltinArguments object: function, arguments reversed, receiver.
+
+  Handle<FunctionTemplateInfo> fun_data =
+      function->IsFunctionTemplateInfo()
+          ? Handle<FunctionTemplateInfo>::cast(function)
+          : handle(JSFunction::cast(*function)->shared()->get_api_func_data(),
+                   isolate);
+  Handle<HeapObject> new_target = isolate->factory()->undefined_value();
+  // Construct BuiltinArguments object:
+  // new target, function, arguments reversed, receiver.
   const int kBufferSize = 32;
   Object* small_argv[kBufferSize];
   Object** argv;
-  if (argc + 2 <= kBufferSize) {
+  if (argc + 3 <= kBufferSize) {
     argv = small_argv;
   } else {
-    argv = new Object* [argc + 2];
+    argv = new Object*[argc + 3];
   }
-  argv[argc + 1] = *receiver;
+  argv[argc + 2] = *receiver;
   for (int i = 0; i < argc; ++i) {
-    argv[argc - i] = *args[i];
+    argv[argc - i + 1] = *args[i];
   }
-  argv[0] = *function;
+  argv[1] = *function;
+  argv[0] = *new_target;
   MaybeHandle<Object> result;
   {
-    RelocatableArguments arguments(isolate, argc + 2, &argv[argc + 1]);
-    result = HandleApiCallHelper<false>(isolate, arguments);
+    RelocatableArguments arguments(isolate, argc + 3, &argv[argc] + 2);
+    result = HandleApiCallHelper<false>(isolate, function, new_target, fun_data,
+                                        receiver, arguments);
   }
-  if (argv != small_argv) {
-    delete[] argv;
-  }
+  if (argv != small_argv) delete[] argv;
   return result;
 }
 
@@ -4488,13 +5497,24 @@
 // API. The object can be called as either a constructor (using new) or just as
 // a function (without new).
 MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
-    Isolate* isolate, bool is_construct_call,
-    BuiltinArguments<BuiltinExtraArguments::kNone> args) {
+    Isolate* isolate, bool is_construct_call, BuiltinArguments args) {
   Handle<Object> receiver = args.receiver();
 
   // Get the object called.
   JSObject* obj = JSObject::cast(*receiver);
 
+  // Set the new target.
+  HeapObject* new_target;
+  if (is_construct_call) {
+    // TODO(adamk): This should be passed through in args instead of
+    // being patched in here. We need to set a non-undefined value
+    // for v8::FunctionCallbackInfo::IsConstructCall() to get the
+    // right answer.
+    new_target = obj;
+  } else {
+    new_target = isolate->heap()->undefined_value();
+  }
+
   // Get the invocation callback from the function descriptor that was
   // used to create the called object.
   DCHECK(obj->map()->is_callable());
@@ -4503,7 +5523,7 @@
   CHECK(constructor->shared()->IsApiFunction());
   Object* handler =
       constructor->shared()->get_api_func_data()->instance_call_handler();
-  DCHECK(!handler->IsUndefined());
+  DCHECK(!handler->IsUndefined(isolate));
   // TODO(ishell): remove this debugging code.
   CHECK(handler->IsCallHandlerInfo());
   CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
@@ -4517,13 +5537,9 @@
     HandleScope scope(isolate);
     LOG(isolate, ApiObjectAccess("call non-function", obj));
 
-    FunctionCallbackArguments custom(isolate,
-                                     call_data->data(),
-                                     constructor,
-                                     obj,
-                                     &args[0] - 1,
-                                     args.length() - 1,
-                                     is_construct_call);
+    FunctionCallbackArguments custom(isolate, call_data->data(), constructor,
+                                     obj, new_target, &args[0] - 1,
+                                     args.length() - 1);
     Handle<Object> result_handle = custom.Call(callback);
     if (result_handle.is_null()) {
       result = isolate->heap()->undefined_value();
@@ -4550,118 +5566,122 @@
   return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
 }
 
+namespace {
 
-static void Generate_LoadIC_Miss(MacroAssembler* masm) {
-  LoadIC::GenerateMiss(masm);
+void Generate_LoadIC_Miss(CodeStubAssembler* assembler) {
+  typedef compiler::Node Node;
+
+  Node* receiver = assembler->Parameter(0);
+  Node* name = assembler->Parameter(1);
+  Node* slot = assembler->Parameter(2);
+  Node* vector = assembler->Parameter(3);
+  Node* context = assembler->Parameter(4);
+
+  assembler->TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name,
+                             slot, vector);
 }
 
+void Generate_LoadGlobalIC_Miss(CodeStubAssembler* assembler) {
+  typedef compiler::Node Node;
 
-static void Generate_LoadIC_Normal(MacroAssembler* masm) {
+  Node* slot = assembler->Parameter(0);
+  Node* vector = assembler->Parameter(1);
+  Node* context = assembler->Parameter(2);
+
+  assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Miss, context, slot,
+                             vector);
+}
+
+void Generate_LoadIC_Normal(MacroAssembler* masm) {
   LoadIC::GenerateNormal(masm);
 }
 
-
-static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
+void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
   NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
 }
 
+void Generate_LoadIC_Slow(CodeStubAssembler* assembler) {
+  typedef compiler::Node Node;
 
-static void Generate_LoadIC_Slow(MacroAssembler* masm) {
-  LoadIC::GenerateRuntimeGetProperty(masm);
+  Node* receiver = assembler->Parameter(0);
+  Node* name = assembler->Parameter(1);
+  // Node* slot = assembler->Parameter(2);
+  // Node* vector = assembler->Parameter(3);
+  Node* context = assembler->Parameter(4);
+
+  assembler->TailCallRuntime(Runtime::kGetProperty, context, receiver, name);
 }
 
+void Generate_LoadGlobalIC_Slow(CodeStubAssembler* assembler) {
+  typedef compiler::Node Node;
 
-static void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
+  Node* slot = assembler->Parameter(0);
+  Node* vector = assembler->Parameter(1);
+  Node* context = assembler->Parameter(2);
+
+  assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Slow, context, slot,
+                             vector);
+}
+
+void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
   KeyedLoadIC::GenerateRuntimeGetProperty(masm);
 }
 
-
-static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
+void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
   KeyedLoadIC::GenerateMiss(masm);
 }
 
-
-static void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
+void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
   KeyedLoadIC::GenerateMegamorphic(masm);
 }
 
-
-static void Generate_StoreIC_Miss(MacroAssembler* masm) {
+void Generate_StoreIC_Miss(MacroAssembler* masm) {
   StoreIC::GenerateMiss(masm);
 }
 
-
-static void Generate_StoreIC_Normal(MacroAssembler* masm) {
+void Generate_StoreIC_Normal(MacroAssembler* masm) {
   StoreIC::GenerateNormal(masm);
 }
 
-
-static void Generate_StoreIC_Slow(MacroAssembler* masm) {
+void Generate_StoreIC_Slow(MacroAssembler* masm) {
   NamedStoreHandlerCompiler::GenerateSlow(masm);
 }
 
-
-static void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
+void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
   ElementHandlerCompiler::GenerateStoreSlow(masm);
 }
 
-
-static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
+void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
   NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
 }
 
-
-static void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
+void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
   KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY);
 }
 
-
-static void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
+void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
   KeyedStoreIC::GenerateMegamorphic(masm, STRICT);
 }
 
-
-static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
+void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
   KeyedStoreIC::GenerateMiss(masm);
 }
 
-
-static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
-  KeyedStoreIC::GenerateInitialize(masm);
-}
-
-
-static void Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler* masm) {
-  KeyedStoreIC::GenerateInitialize(masm);
-}
-
-
-static void Generate_KeyedStoreIC_PreMonomorphic(MacroAssembler* masm) {
-  KeyedStoreIC::GeneratePreMonomorphic(masm);
-}
-
-
-static void Generate_KeyedStoreIC_PreMonomorphic_Strict(MacroAssembler* masm) {
-  KeyedStoreIC::GeneratePreMonomorphic(masm);
-}
-
-
-static void Generate_Return_DebugBreak(MacroAssembler* masm) {
+void Generate_Return_DebugBreak(MacroAssembler* masm) {
   DebugCodegen::GenerateDebugBreakStub(masm,
                                        DebugCodegen::SAVE_RESULT_REGISTER);
 }
 
-
-static void Generate_Slot_DebugBreak(MacroAssembler* masm) {
+void Generate_Slot_DebugBreak(MacroAssembler* masm) {
   DebugCodegen::GenerateDebugBreakStub(masm,
                                        DebugCodegen::IGNORE_RESULT_REGISTER);
 }
 
-
-static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
+void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
   DebugCodegen::GenerateFrameDropperLiveEdit(masm);
 }
 
+}  // namespace
 
 Builtins::Builtins() : initialized_(false) {
   memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
@@ -4672,8 +5692,7 @@
 Builtins::~Builtins() {
 }
 
-
-#define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
+#define DEF_ENUM_C(name) FUNCTION_ADDR(Builtin_##name),
 Address const Builtins::c_functions_[cfunction_count] = {
   BUILTIN_LIST_C(DEF_ENUM_C)
 };
@@ -4687,7 +5706,6 @@
   const char* s_name;  // name is only used for generating log information.
   int name;
   Code::Flags flags;
-  BuiltinExtraArguments extra_args;
   int argc;
 };
 
@@ -4732,13 +5750,13 @@
   MacroAssembler masm(isolate, u.buffer, sizeof(u.buffer),
                       CodeObjectRequired::kYes);
   // Generate the code/adaptor.
-  typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
+  typedef void (*Generator)(MacroAssembler*, int);
   Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
   // We pass all arguments to the generator, but it may not use all of
   // them.  This works because the first arguments are on top of the
   // stack.
   DCHECK(!masm.has_frame());
-  g(&masm, builtin_desc->name, builtin_desc->extra_args);
+  g(&masm, builtin_desc->name);
   // Move the code into the object heap.
   CodeDesc desc;
   masm.GetCode(&desc);
@@ -4746,14 +5764,33 @@
   return isolate->factory()->NewCode(desc, flags, masm.CodeObject());
 }
 
-Handle<Code> CodeStubAssemblerBuilder(Isolate* isolate,
-                                      BuiltinDesc const* builtin_desc) {
+// Builder for builtins implemented in TurboFan with JS linkage.
+Handle<Code> CodeStubAssemblerBuilderJS(Isolate* isolate,
+                                        BuiltinDesc const* builtin_desc) {
   Zone zone(isolate->allocator());
-  compiler::CodeStubAssembler assembler(isolate, &zone, builtin_desc->argc,
-                                        builtin_desc->flags,
-                                        builtin_desc->s_name);
+  CodeStubAssembler assembler(isolate, &zone, builtin_desc->argc,
+                              builtin_desc->flags, builtin_desc->s_name);
   // Generate the code/adaptor.
-  typedef void (*Generator)(compiler::CodeStubAssembler*);
+  typedef void (*Generator)(CodeStubAssembler*);
+  Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
+  g(&assembler);
+  return assembler.GenerateCode();
+}
+
+// Builder for builtins implemented in TurboFan with CallStub linkage.
+Handle<Code> CodeStubAssemblerBuilderCS(Isolate* isolate,
+                                        BuiltinDesc const* builtin_desc) {
+  Zone zone(isolate->allocator());
+  // The interface descriptor with given key must be initialized at this point
+  // and this construction just queries the details from the descriptors table.
+  CallInterfaceDescriptor descriptor(
+      isolate, static_cast<CallDescriptors::Key>(builtin_desc->argc));
+  // Ensure descriptor is already initialized.
+  DCHECK_NOT_NULL(descriptor.GetFunctionType());
+  CodeStubAssembler assembler(isolate, &zone, descriptor, builtin_desc->flags,
+                              builtin_desc->s_name);
+  // Generate the code/adaptor.
+  typedef void (*Generator)(CodeStubAssembler*);
   Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
   g(&assembler);
   return assembler.GenerateCode();
@@ -4773,41 +5810,46 @@
   functions[builtin_count].s_name = nullptr;
   functions[builtin_count].name = builtin_count;
   functions[builtin_count].flags = static_cast<Code::Flags>(0);
-  functions[builtin_count].extra_args = BuiltinExtraArguments::kNone;
   functions[builtin_count].argc = 0;
 
-#define DEF_FUNCTION_PTR_C(aname, aextra_args)                \
-  functions->builder = &MacroAssemblerBuilder;                \
-  functions->generator = FUNCTION_ADDR(Generate_Adaptor);     \
-  functions->c_code = FUNCTION_ADDR(Builtin_##aname);         \
-  functions->s_name = #aname;                                 \
-  functions->name = c_##aname;                                \
-  functions->flags = Code::ComputeFlags(Code::BUILTIN);       \
-  functions->extra_args = BuiltinExtraArguments::aextra_args; \
-  functions->argc = 0;                                        \
+#define DEF_FUNCTION_PTR_C(aname)                         \
+  functions->builder = &MacroAssemblerBuilder;            \
+  functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
+  functions->c_code = FUNCTION_ADDR(Builtin_##aname);     \
+  functions->s_name = #aname;                             \
+  functions->name = c_##aname;                            \
+  functions->flags = Code::ComputeFlags(Code::BUILTIN);   \
+  functions->argc = 0;                                    \
   ++functions;
 
-#define DEF_FUNCTION_PTR_A(aname, kind, state, extra)              \
-  functions->builder = &MacroAssemblerBuilder;                     \
-  functions->generator = FUNCTION_ADDR(Generate_##aname);          \
-  functions->c_code = NULL;                                        \
-  functions->s_name = #aname;                                      \
-  functions->name = k##aname;                                      \
-  functions->flags = Code::ComputeFlags(Code::kind, state, extra); \
-  functions->extra_args = BuiltinExtraArguments::kNone;            \
-  functions->argc = 0;                                             \
+#define DEF_FUNCTION_PTR_A(aname, kind, extra)              \
+  functions->builder = &MacroAssemblerBuilder;              \
+  functions->generator = FUNCTION_ADDR(Generate_##aname);   \
+  functions->c_code = NULL;                                 \
+  functions->s_name = #aname;                               \
+  functions->name = k##aname;                               \
+  functions->flags = Code::ComputeFlags(Code::kind, extra); \
+  functions->argc = 0;                                      \
   ++functions;
 
-#define DEF_FUNCTION_PTR_T(aname, aargc)                                 \
-  functions->builder = &CodeStubAssemblerBuilder;                        \
-  functions->generator = FUNCTION_ADDR(Generate_##aname);                \
-  functions->c_code = NULL;                                              \
-  functions->s_name = #aname;                                            \
-  functions->name = k##aname;                                            \
-  functions->flags =                                                     \
-      Code::ComputeFlags(Code::BUILTIN, UNINITIALIZED, kNoExtraICState); \
-  functions->extra_args = BuiltinExtraArguments::kNone;                  \
-  functions->argc = aargc;                                               \
+#define DEF_FUNCTION_PTR_T(aname, aargc)                  \
+  functions->builder = &CodeStubAssemblerBuilderJS;       \
+  functions->generator = FUNCTION_ADDR(Generate_##aname); \
+  functions->c_code = NULL;                               \
+  functions->s_name = #aname;                             \
+  functions->name = k##aname;                             \
+  functions->flags = Code::ComputeFlags(Code::BUILTIN);   \
+  functions->argc = aargc;                                \
+  ++functions;
+
+#define DEF_FUNCTION_PTR_S(aname, kind, extra, interface_descriptor) \
+  functions->builder = &CodeStubAssemblerBuilderCS;                  \
+  functions->generator = FUNCTION_ADDR(Generate_##aname);            \
+  functions->c_code = NULL;                                          \
+  functions->s_name = #aname;                                        \
+  functions->name = k##aname;                                        \
+  functions->flags = Code::ComputeFlags(Code::kind, extra);          \
+  functions->argc = CallDescriptors::interface_descriptor;           \
   ++functions;
 
 #define DEF_FUNCTION_PTR_H(aname, kind)                     \
@@ -4817,20 +5859,21 @@
   functions->s_name = #aname;                               \
   functions->name = k##aname;                               \
   functions->flags = Code::ComputeHandlerFlags(Code::kind); \
-  functions->extra_args = BuiltinExtraArguments::kNone;     \
   functions->argc = 0;                                      \
   ++functions;
 
   BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
   BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
   BUILTIN_LIST_T(DEF_FUNCTION_PTR_T)
+  BUILTIN_LIST_S(DEF_FUNCTION_PTR_S)
   BUILTIN_LIST_H(DEF_FUNCTION_PTR_H)
   BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
 
 #undef DEF_FUNCTION_PTR_C
 #undef DEF_FUNCTION_PTR_A
-#undef DEF_FUNCTION_PTR_H
 #undef DEF_FUNCTION_PTR_T
+#undef DEF_FUNCTION_PTR_S
+#undef DEF_FUNCTION_PTR_H
 }
 
 
@@ -4840,6 +5883,11 @@
   // Create a scope for the handles in the builtins.
   HandleScope scope(isolate);
 
+#define INITIALIZE_CALL_DESCRIPTOR(name, kind, extra, interface_descriptor) \
+  { interface_descriptor##Descriptor descriptor(isolate); }
+  BUILTIN_LIST_S(INITIALIZE_CALL_DESCRIPTOR)
+#undef INITIALIZE_CALL_DESCRIPTOR
+
   const BuiltinDesc* functions = builtin_function_table.functions();
 
   // Traverse the list of builtins and generate an adaptor in a
@@ -4849,8 +5897,8 @@
       Handle<Code> code = (*functions[i].builder)(isolate, functions + i);
       // Log the event and add the code to the builtins array.
       PROFILE(isolate,
-              CodeCreateEvent(Logger::BUILTIN_TAG, AbstractCode::cast(*code),
-                              functions[i].s_name));
+              CodeCreateEvent(CodeEventListener::BUILTIN_TAG,
+                              AbstractCode::cast(*code), functions[i].s_name));
       builtins_[i] = *code;
       code->set_builtin_index(i);
 #ifdef ENABLE_DISASSEMBLER
@@ -4907,24 +5955,263 @@
   masm->TailCallRuntime(Runtime::kStackGuard);
 }
 
+namespace {
 
-#define DEFINE_BUILTIN_ACCESSOR_C(name, ignore)               \
-Handle<Code> Builtins::name() {                               \
-  Code** code_address =                                       \
-      reinterpret_cast<Code**>(builtin_address(k##name));     \
-  return Handle<Code>(code_address);                          \
+void ValidateSharedTypedArray(CodeStubAssembler* a, compiler::Node* tagged,
+                              compiler::Node* context,
+                              compiler::Node** out_instance_type,
+                              compiler::Node** out_backing_store) {
+  using namespace compiler;
+  CodeStubAssembler::Label is_smi(a), not_smi(a), is_typed_array(a),
+      not_typed_array(a), is_shared(a), not_shared(a), is_float_or_clamped(a),
+      not_float_or_clamped(a), invalid(a);
+
+  // Fail if it is not a heap object.
+  a->Branch(a->WordIsSmi(tagged), &is_smi, &not_smi);
+  a->Bind(&is_smi);
+  a->Goto(&invalid);
+
+  // Fail if the array's instance type is not JSTypedArray.
+  a->Bind(&not_smi);
+  a->Branch(a->WordEqual(a->LoadInstanceType(tagged),
+                         a->Int32Constant(JS_TYPED_ARRAY_TYPE)),
+            &is_typed_array, &not_typed_array);
+  a->Bind(&not_typed_array);
+  a->Goto(&invalid);
+
+  // Fail if the array's JSArrayBuffer is not shared.
+  a->Bind(&is_typed_array);
+  Node* array_buffer = a->LoadObjectField(tagged, JSTypedArray::kBufferOffset);
+  Node* is_buffer_shared = a->BitFieldDecode<JSArrayBuffer::IsShared>(
+      a->LoadObjectField(array_buffer, JSArrayBuffer::kBitFieldSlot));
+  a->Branch(is_buffer_shared, &is_shared, &not_shared);
+  a->Bind(&not_shared);
+  a->Goto(&invalid);
+
+  // Fail if the array's element type is float32, float64 or clamped.
+  a->Bind(&is_shared);
+  Node* elements_instance_type = a->LoadInstanceType(
+      a->LoadObjectField(tagged, JSObject::kElementsOffset));
+  STATIC_ASSERT(FIXED_INT8_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
+  STATIC_ASSERT(FIXED_INT16_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
+  STATIC_ASSERT(FIXED_INT32_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
+  STATIC_ASSERT(FIXED_UINT8_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
+  STATIC_ASSERT(FIXED_UINT16_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
+  STATIC_ASSERT(FIXED_UINT32_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
+  a->Branch(a->Int32LessThan(elements_instance_type,
+                             a->Int32Constant(FIXED_FLOAT32_ARRAY_TYPE)),
+            &not_float_or_clamped, &is_float_or_clamped);
+  a->Bind(&is_float_or_clamped);
+  a->Goto(&invalid);
+
+  a->Bind(&invalid);
+  a->CallRuntime(Runtime::kThrowNotIntegerSharedTypedArrayError, context,
+                 tagged);
+  a->Return(a->UndefinedConstant());
+
+  a->Bind(&not_float_or_clamped);
+  *out_instance_type = elements_instance_type;
+
+  Node* backing_store =
+      a->LoadObjectField(array_buffer, JSArrayBuffer::kBackingStoreOffset);
+  Node* byte_offset = a->ChangeUint32ToWord(a->TruncateTaggedToWord32(
+      context,
+      a->LoadObjectField(tagged, JSArrayBufferView::kByteOffsetOffset)));
+  *out_backing_store = a->IntPtrAdd(backing_store, byte_offset);
 }
-#define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \
-Handle<Code> Builtins::name() {                             \
-  Code** code_address =                                     \
-      reinterpret_cast<Code**>(builtin_address(k##name));   \
-  return Handle<Code>(code_address);                        \
+
+// https://tc39.github.io/ecmascript_sharedmem/shmem.html#Atomics.ValidateAtomicAccess
+compiler::Node* ConvertTaggedAtomicIndexToWord32(CodeStubAssembler* a,
+                                                 compiler::Node* tagged,
+                                                 compiler::Node* context) {
+  using namespace compiler;
+  CodeStubAssembler::Variable var_result(a, MachineRepresentation::kWord32);
+
+  Callable to_number = CodeFactory::ToNumber(a->isolate());
+  Node* number_index = a->CallStub(to_number, context, tagged);
+  CodeStubAssembler::Label done(a, &var_result);
+
+  CodeStubAssembler::Label if_numberissmi(a), if_numberisnotsmi(a);
+  a->Branch(a->WordIsSmi(number_index), &if_numberissmi, &if_numberisnotsmi);
+
+  a->Bind(&if_numberissmi);
+  {
+    var_result.Bind(a->SmiToWord32(number_index));
+    a->Goto(&done);
+  }
+
+  a->Bind(&if_numberisnotsmi);
+  {
+    Node* number_index_value = a->LoadHeapNumberValue(number_index);
+    Node* access_index = a->TruncateFloat64ToWord32(number_index_value);
+    Node* test_index = a->ChangeInt32ToFloat64(access_index);
+
+    CodeStubAssembler::Label if_indexesareequal(a), if_indexesarenotequal(a);
+    a->Branch(a->Float64Equal(number_index_value, test_index),
+              &if_indexesareequal, &if_indexesarenotequal);
+
+    a->Bind(&if_indexesareequal);
+    {
+      var_result.Bind(access_index);
+      a->Goto(&done);
+    }
+
+    a->Bind(&if_indexesarenotequal);
+    a->Return(
+        a->CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context));
+  }
+
+  a->Bind(&done);
+  return var_result.value();
 }
+
+void ValidateAtomicIndex(CodeStubAssembler* a, compiler::Node* index_word,
+                         compiler::Node* array_length_word,
+                         compiler::Node* context) {
+  using namespace compiler;
+  // Check if the index is in bounds. If not, throw RangeError.
+  CodeStubAssembler::Label if_inbounds(a), if_notinbounds(a);
+  a->Branch(
+      a->WordOr(a->Int32LessThan(index_word, a->Int32Constant(0)),
+                a->Int32GreaterThanOrEqual(index_word, array_length_word)),
+      &if_notinbounds, &if_inbounds);
+  a->Bind(&if_notinbounds);
+  a->Return(
+      a->CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context));
+  a->Bind(&if_inbounds);
+}
+
+}  // anonymous namespace
+
+void Builtins::Generate_AtomicsLoad(CodeStubAssembler* a) {
+  using namespace compiler;
+  Node* array = a->Parameter(1);
+  Node* index = a->Parameter(2);
+  Node* context = a->Parameter(3 + 2);
+
+  Node* instance_type;
+  Node* backing_store;
+  ValidateSharedTypedArray(a, array, context, &instance_type, &backing_store);
+
+  Node* index_word32 = ConvertTaggedAtomicIndexToWord32(a, index, context);
+  Node* array_length_word32 = a->TruncateTaggedToWord32(
+      context, a->LoadObjectField(array, JSTypedArray::kLengthOffset));
+  ValidateAtomicIndex(a, index_word32, array_length_word32, context);
+  Node* index_word = a->ChangeUint32ToWord(index_word32);
+
+  CodeStubAssembler::Label i8(a), u8(a), i16(a), u16(a), i32(a), u32(a),
+      other(a);
+  int32_t case_values[] = {
+      FIXED_INT8_ARRAY_TYPE,   FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
+      FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
+  };
+  CodeStubAssembler::Label* case_labels[] = {
+      &i8, &u8, &i16, &u16, &i32, &u32,
+  };
+  a->Switch(instance_type, &other, case_values, case_labels,
+            arraysize(case_labels));
+
+  a->Bind(&i8);
+  a->Return(
+      a->SmiTag(a->AtomicLoad(MachineType::Int8(), backing_store, index_word)));
+
+  a->Bind(&u8);
+  a->Return(a->SmiTag(
+      a->AtomicLoad(MachineType::Uint8(), backing_store, index_word)));
+
+  a->Bind(&i16);
+  a->Return(a->SmiTag(a->AtomicLoad(MachineType::Int16(), backing_store,
+                                    a->WordShl(index_word, 1))));
+
+  a->Bind(&u16);
+  a->Return(a->SmiTag(a->AtomicLoad(MachineType::Uint16(), backing_store,
+                                    a->WordShl(index_word, 1))));
+
+  a->Bind(&i32);
+  a->Return(a->ChangeInt32ToTagged(a->AtomicLoad(
+      MachineType::Int32(), backing_store, a->WordShl(index_word, 2))));
+
+  a->Bind(&u32);
+  a->Return(a->ChangeUint32ToTagged(a->AtomicLoad(
+      MachineType::Uint32(), backing_store, a->WordShl(index_word, 2))));
+
+  // This shouldn't happen, we've already validated the type.
+  a->Bind(&other);
+  a->Return(a->Int32Constant(0));
+}
+
+void Builtins::Generate_AtomicsStore(CodeStubAssembler* a) {
+  using namespace compiler;
+  Node* array = a->Parameter(1);
+  Node* index = a->Parameter(2);
+  Node* value = a->Parameter(3);
+  Node* context = a->Parameter(4 + 2);
+
+  Node* instance_type;
+  Node* backing_store;
+  ValidateSharedTypedArray(a, array, context, &instance_type, &backing_store);
+
+  Node* index_word32 = ConvertTaggedAtomicIndexToWord32(a, index, context);
+  Node* array_length_word32 = a->TruncateTaggedToWord32(
+      context, a->LoadObjectField(array, JSTypedArray::kLengthOffset));
+  ValidateAtomicIndex(a, index_word32, array_length_word32, context);
+  Node* index_word = a->ChangeUint32ToWord(index_word32);
+
+  Callable to_integer = CodeFactory::ToInteger(a->isolate());
+  Node* value_integer = a->CallStub(to_integer, context, value);
+  Node* value_word32 = a->TruncateTaggedToWord32(context, value_integer);
+
+  CodeStubAssembler::Label u8(a), u16(a), u32(a), other(a);
+  int32_t case_values[] = {
+      FIXED_INT8_ARRAY_TYPE,   FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
+      FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
+  };
+  CodeStubAssembler::Label* case_labels[] = {
+      &u8, &u8, &u16, &u16, &u32, &u32,
+  };
+  a->Switch(instance_type, &other, case_values, case_labels,
+            arraysize(case_labels));
+
+  a->Bind(&u8);
+  a->AtomicStore(MachineRepresentation::kWord8, backing_store, index_word,
+                 value_word32);
+  a->Return(value_integer);
+
+  a->Bind(&u16);
+  a->SmiTag(a->AtomicStore(MachineRepresentation::kWord16, backing_store,
+                           a->WordShl(index_word, 1), value_word32));
+  a->Return(value_integer);
+
+  a->Bind(&u32);
+  a->AtomicStore(MachineRepresentation::kWord32, backing_store,
+                 a->WordShl(index_word, 2), value_word32);
+  a->Return(value_integer);
+
+  // This shouldn't happen, we've already validated the type.
+  a->Bind(&other);
+  a->Return(a->Int32Constant(0));
+}
+
+#define DEFINE_BUILTIN_ACCESSOR_C(name)                                       \
+  Handle<Code> Builtins::name() {                                             \
+    Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
+    return Handle<Code>(code_address);                                        \
+  }
+#define DEFINE_BUILTIN_ACCESSOR_A(name, kind, extra)                          \
+  Handle<Code> Builtins::name() {                                             \
+    Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
+    return Handle<Code>(code_address);                                        \
+  }
 #define DEFINE_BUILTIN_ACCESSOR_T(name, argc)                                 \
   Handle<Code> Builtins::name() {                                             \
     Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
     return Handle<Code>(code_address);                                        \
   }
+#define DEFINE_BUILTIN_ACCESSOR_S(name, kind, extra, interface_descriptor)    \
+  Handle<Code> Builtins::name() {                                             \
+    Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
+    return Handle<Code>(code_address);                                        \
+  }
 #define DEFINE_BUILTIN_ACCESSOR_H(name, kind)               \
 Handle<Code> Builtins::name() {                             \
   Code** code_address =                                     \
@@ -4934,11 +6221,13 @@
 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T)
+BUILTIN_LIST_S(DEFINE_BUILTIN_ACCESSOR_S)
 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
 #undef DEFINE_BUILTIN_ACCESSOR_C
 #undef DEFINE_BUILTIN_ACCESSOR_A
 #undef DEFINE_BUILTIN_ACCESSOR_T
+#undef DEFINE_BUILTIN_ACCESSOR_S
 #undef DEFINE_BUILTIN_ACCESSOR_H
 
 }  // namespace internal
diff --git a/src/builtins.h b/src/builtins.h
index 221d06f..cbce375 100644
--- a/src/builtins.h
+++ b/src/builtins.h
@@ -1,3 +1,4 @@
+
 // Copyright 2011 the V8 project authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
@@ -11,26 +12,9 @@
 namespace v8 {
 namespace internal {
 
-namespace compiler {
-
 // Forward declarations.
 class CodeStubAssembler;
 
-}  // namespace compiler
-
-// Specifies extra arguments required by a C++ builtin.
-enum class BuiltinExtraArguments : uint8_t {
-  kNone = 0u,
-  kTarget = 1u << 0,
-  kNewTarget = 1u << 1,
-  kTargetAndNewTarget = kTarget | kNewTarget
-};
-
-inline bool operator&(BuiltinExtraArguments lhs, BuiltinExtraArguments rhs) {
-  return static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs);
-}
-
-
 #define CODE_AGE_LIST_WITH_ARG(V, A)     \
   V(Quadragenarian, A)                   \
   V(Quinquagenarian, A)                  \
@@ -50,276 +34,317 @@
   V(NoAge)                                         \
   CODE_AGE_LIST_WITH_ARG(CODE_AGE_LIST_IGNORE_ARG, V)
 
-#define DECLARE_CODE_AGE_BUILTIN(C, V)             \
-  V(Make##C##CodeYoungAgainOddMarking, BUILTIN,    \
-    UNINITIALIZED, kNoExtraICState)                \
-  V(Make##C##CodeYoungAgainEvenMarking, BUILTIN,   \
-    UNINITIALIZED, kNoExtraICState)
-
+#define DECLARE_CODE_AGE_BUILTIN(C, V)                           \
+  V(Make##C##CodeYoungAgainOddMarking, BUILTIN, kNoExtraICState) \
+  V(Make##C##CodeYoungAgainEvenMarking, BUILTIN, kNoExtraICState)
 
 // Define list of builtins implemented in C++.
-#define BUILTIN_LIST_C(V)                                      \
-  V(Illegal, kNone)                                            \
-                                                               \
-  V(EmptyFunction, kNone)                                      \
-                                                               \
-  V(ArrayConcat, kNone)                                        \
-  V(ArrayIsArray, kNone)                                       \
-  V(ArrayPop, kNone)                                           \
-  V(ArrayPush, kNone)                                          \
-  V(ArrayShift, kNone)                                         \
-  V(ArraySlice, kNone)                                         \
-  V(ArraySplice, kNone)                                        \
-  V(ArrayUnshift, kNone)                                       \
-                                                               \
-  V(ArrayBufferConstructor, kTarget)                           \
-  V(ArrayBufferConstructor_ConstructStub, kTargetAndNewTarget) \
-  V(ArrayBufferIsView, kNone)                                  \
-                                                               \
-  V(BooleanConstructor, kNone)                                 \
-  V(BooleanConstructor_ConstructStub, kTargetAndNewTarget)     \
-  V(BooleanPrototypeToString, kNone)                           \
-  V(BooleanPrototypeValueOf, kNone)                            \
-                                                               \
-  V(DataViewConstructor, kNone)                                \
-  V(DataViewConstructor_ConstructStub, kTargetAndNewTarget)    \
-                                                               \
-  V(DateConstructor, kNone)                                    \
-  V(DateConstructor_ConstructStub, kTargetAndNewTarget)        \
-  V(DateNow, kNone)                                            \
-  V(DateParse, kNone)                                          \
-  V(DateUTC, kNone)                                            \
-  V(DatePrototypeSetDate, kNone)                               \
-  V(DatePrototypeSetFullYear, kNone)                           \
-  V(DatePrototypeSetHours, kNone)                              \
-  V(DatePrototypeSetMilliseconds, kNone)                       \
-  V(DatePrototypeSetMinutes, kNone)                            \
-  V(DatePrototypeSetMonth, kNone)                              \
-  V(DatePrototypeSetSeconds, kNone)                            \
-  V(DatePrototypeSetTime, kNone)                               \
-  V(DatePrototypeSetUTCDate, kNone)                            \
-  V(DatePrototypeSetUTCFullYear, kNone)                        \
-  V(DatePrototypeSetUTCHours, kNone)                           \
-  V(DatePrototypeSetUTCMilliseconds, kNone)                    \
-  V(DatePrototypeSetUTCMinutes, kNone)                         \
-  V(DatePrototypeSetUTCMonth, kNone)                           \
-  V(DatePrototypeSetUTCSeconds, kNone)                         \
-  V(DatePrototypeToDateString, kNone)                          \
-  V(DatePrototypeToISOString, kNone)                           \
-  V(DatePrototypeToPrimitive, kNone)                           \
-  V(DatePrototypeToUTCString, kNone)                           \
-  V(DatePrototypeToString, kNone)                              \
-  V(DatePrototypeToTimeString, kNone)                          \
-  V(DatePrototypeValueOf, kNone)                               \
-  V(DatePrototypeGetYear, kNone)                               \
-  V(DatePrototypeSetYear, kNone)                               \
-                                                               \
-  V(FunctionConstructor, kTargetAndNewTarget)                  \
-  V(FunctionPrototypeBind, kNone)                              \
-  V(FunctionPrototypeToString, kNone)                          \
-                                                               \
-  V(GeneratorFunctionConstructor, kTargetAndNewTarget)         \
-                                                               \
-  V(GlobalEval, kTarget)                                       \
-                                                               \
-  V(MathAcos, kNone)                                           \
-  V(MathAsin, kNone)                                           \
-  V(MathAtan, kNone)                                           \
-  V(MathFround, kNone)                                         \
-  V(MathImul, kNone)                                           \
-                                                               \
-  V(ObjectAssign, kNone)                                       \
-  V(ObjectCreate, kNone)                                       \
-  V(ObjectFreeze, kNone)                                       \
-  V(ObjectGetOwnPropertyDescriptor, kNone)                     \
-  V(ObjectGetOwnPropertyNames, kNone)                          \
-  V(ObjectGetOwnPropertySymbols, kNone)                        \
-  V(ObjectIs, kNone)                                           \
-  V(ObjectIsExtensible, kNone)                                 \
-  V(ObjectIsFrozen, kNone)                                     \
-  V(ObjectIsSealed, kNone)                                     \
-  V(ObjectKeys, kNone)                                         \
-  V(ObjectValues, kNone)                                       \
-  V(ObjectEntries, kNone)                                      \
-  V(ObjectGetOwnPropertyDescriptors, kNone)                    \
-  V(ObjectPreventExtensions, kNone)                            \
-  V(ObjectSeal, kNone)                                         \
-  V(ObjectProtoToString, kNone)                                \
-                                                               \
-  V(ProxyConstructor, kNone)                                   \
-  V(ProxyConstructor_ConstructStub, kTarget)                   \
-                                                               \
-  V(ReflectDefineProperty, kNone)                              \
-  V(ReflectDeleteProperty, kNone)                              \
-  V(ReflectGet, kNone)                                         \
-  V(ReflectGetOwnPropertyDescriptor, kNone)                    \
-  V(ReflectGetPrototypeOf, kNone)                              \
-  V(ReflectHas, kNone)                                         \
-  V(ReflectIsExtensible, kNone)                                \
-  V(ReflectOwnKeys, kNone)                                     \
-  V(ReflectPreventExtensions, kNone)                           \
-  V(ReflectSet, kNone)                                         \
-  V(ReflectSetPrototypeOf, kNone)                              \
-                                                               \
-  V(StringFromCharCode, kNone)                                 \
-                                                               \
-  V(SymbolConstructor, kNone)                                  \
-  V(SymbolConstructor_ConstructStub, kTarget)                  \
-                                                               \
-  V(HandleApiCall, kTarget)                                    \
-  V(HandleApiCallConstruct, kTarget)                           \
-  V(HandleApiCallAsFunction, kNone)                            \
-  V(HandleApiCallAsConstructor, kNone)                         \
-                                                               \
-  V(RestrictedFunctionPropertiesThrower, kNone)                \
-  V(RestrictedStrictArgumentsPropertiesThrower, kNone)
+#define BUILTIN_LIST_C(V)                 \
+  V(Illegal)                              \
+                                          \
+  V(EmptyFunction)                        \
+                                          \
+  V(ArrayConcat)                          \
+  V(ArrayPop)                             \
+  V(ArrayPush)                            \
+  V(ArrayShift)                           \
+  V(ArraySlice)                           \
+  V(ArraySplice)                          \
+  V(ArrayUnshift)                         \
+                                          \
+  V(ArrayBufferConstructor)               \
+  V(ArrayBufferConstructor_ConstructStub) \
+  V(ArrayBufferIsView)                    \
+                                          \
+  V(BooleanConstructor)                   \
+  V(BooleanConstructor_ConstructStub)     \
+  V(BooleanPrototypeToString)             \
+  V(BooleanPrototypeValueOf)              \
+                                          \
+  V(DataViewConstructor)                  \
+  V(DataViewConstructor_ConstructStub)    \
+  V(DataViewPrototypeGetBuffer)           \
+  V(DataViewPrototypeGetByteLength)       \
+  V(DataViewPrototypeGetByteOffset)       \
+                                          \
+  V(DateConstructor)                      \
+  V(DateConstructor_ConstructStub)        \
+  V(DateNow)                              \
+  V(DateParse)                            \
+  V(DateUTC)                              \
+  V(DatePrototypeSetDate)                 \
+  V(DatePrototypeSetFullYear)             \
+  V(DatePrototypeSetHours)                \
+  V(DatePrototypeSetMilliseconds)         \
+  V(DatePrototypeSetMinutes)              \
+  V(DatePrototypeSetMonth)                \
+  V(DatePrototypeSetSeconds)              \
+  V(DatePrototypeSetTime)                 \
+  V(DatePrototypeSetUTCDate)              \
+  V(DatePrototypeSetUTCFullYear)          \
+  V(DatePrototypeSetUTCHours)             \
+  V(DatePrototypeSetUTCMilliseconds)      \
+  V(DatePrototypeSetUTCMinutes)           \
+  V(DatePrototypeSetUTCMonth)             \
+  V(DatePrototypeSetUTCSeconds)           \
+  V(DatePrototypeToDateString)            \
+  V(DatePrototypeToISOString)             \
+  V(DatePrototypeToPrimitive)             \
+  V(DatePrototypeToUTCString)             \
+  V(DatePrototypeToString)                \
+  V(DatePrototypeToTimeString)            \
+  V(DatePrototypeValueOf)                 \
+  V(DatePrototypeGetYear)                 \
+  V(DatePrototypeSetYear)                 \
+  V(DatePrototypeToJson)                  \
+                                          \
+  V(FunctionConstructor)                  \
+  V(FunctionPrototypeBind)                \
+  V(FunctionPrototypeToString)            \
+                                          \
+  V(GeneratorFunctionConstructor)         \
+  V(AsyncFunctionConstructor)             \
+                                          \
+  V(GlobalDecodeURI)                      \
+  V(GlobalDecodeURIComponent)             \
+  V(GlobalEncodeURI)                      \
+  V(GlobalEncodeURIComponent)             \
+  V(GlobalEscape)                         \
+  V(GlobalUnescape)                       \
+                                          \
+  V(GlobalEval)                           \
+                                          \
+  V(JsonParse)                            \
+  V(JsonStringify)                        \
+                                          \
+  V(MathAcos)                             \
+  V(MathAsin)                             \
+  V(MathFround)                           \
+  V(MathImul)                             \
+                                          \
+  V(ObjectAssign)                         \
+  V(ObjectCreate)                         \
+  V(ObjectDefineGetter)                   \
+  V(ObjectDefineProperties)               \
+  V(ObjectDefineProperty)                 \
+  V(ObjectDefineSetter)                   \
+  V(ObjectEntries)                        \
+  V(ObjectFreeze)                         \
+  V(ObjectGetOwnPropertyDescriptor)       \
+  V(ObjectGetOwnPropertyDescriptors)      \
+  V(ObjectGetOwnPropertyNames)            \
+  V(ObjectGetOwnPropertySymbols)          \
+  V(ObjectGetPrototypeOf)                 \
+  V(ObjectIs)                             \
+  V(ObjectIsExtensible)                   \
+  V(ObjectIsFrozen)                       \
+  V(ObjectIsSealed)                       \
+  V(ObjectKeys)                           \
+  V(ObjectLookupGetter)                   \
+  V(ObjectLookupSetter)                   \
+  V(ObjectPreventExtensions)              \
+  V(ObjectProtoToString)                  \
+  V(ObjectSeal)                           \
+  V(ObjectValues)                         \
+                                          \
+  V(ProxyConstructor)                     \
+  V(ProxyConstructor_ConstructStub)       \
+                                          \
+  V(ReflectDefineProperty)                \
+  V(ReflectDeleteProperty)                \
+  V(ReflectGet)                           \
+  V(ReflectGetOwnPropertyDescriptor)      \
+  V(ReflectGetPrototypeOf)                \
+  V(ReflectHas)                           \
+  V(ReflectIsExtensible)                  \
+  V(ReflectOwnKeys)                       \
+  V(ReflectPreventExtensions)             \
+  V(ReflectSet)                           \
+  V(ReflectSetPrototypeOf)                \
+                                          \
+  V(StringFromCodePoint)                  \
+                                          \
+  V(StringPrototypeTrim)                  \
+  V(StringPrototypeTrimLeft)              \
+  V(StringPrototypeTrimRight)             \
+                                          \
+  V(SymbolConstructor)                    \
+  V(SymbolConstructor_ConstructStub)      \
+                                          \
+  V(TypedArrayPrototypeBuffer)            \
+                                          \
+  V(HandleApiCall)                        \
+  V(HandleApiCallAsFunction)              \
+  V(HandleApiCallAsConstructor)           \
+                                          \
+  V(RestrictedFunctionPropertiesThrower)  \
+  V(RestrictedStrictArgumentsPropertiesThrower)
 
 // Define list of builtins implemented in assembly.
-#define BUILTIN_LIST_A(V)                                                      \
-  V(ArgumentsAdaptorTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState)       \
-                                                                               \
-  V(ConstructedNonConstructable, BUILTIN, UNINITIALIZED, kNoExtraICState)      \
-                                                                               \
-  V(CallFunction_ReceiverIsNullOrUndefined, BUILTIN, UNINITIALIZED,            \
-    kNoExtraICState)                                                           \
-  V(CallFunction_ReceiverIsNotNullOrUndefined, BUILTIN, UNINITIALIZED,         \
-    kNoExtraICState)                                                           \
-  V(CallFunction_ReceiverIsAny, BUILTIN, UNINITIALIZED, kNoExtraICState)       \
-  V(TailCallFunction_ReceiverIsNullOrUndefined, BUILTIN, UNINITIALIZED,        \
-    kNoExtraICState)                                                           \
-  V(TailCallFunction_ReceiverIsNotNullOrUndefined, BUILTIN, UNINITIALIZED,     \
-    kNoExtraICState)                                                           \
-  V(TailCallFunction_ReceiverIsAny, BUILTIN, UNINITIALIZED, kNoExtraICState)   \
-  V(CallBoundFunction, BUILTIN, UNINITIALIZED, kNoExtraICState)                \
-  V(TailCallBoundFunction, BUILTIN, UNINITIALIZED, kNoExtraICState)            \
-  V(Call_ReceiverIsNullOrUndefined, BUILTIN, UNINITIALIZED, kNoExtraICState)   \
-  V(Call_ReceiverIsNotNullOrUndefined, BUILTIN, UNINITIALIZED,                 \
-    kNoExtraICState)                                                           \
-  V(Call_ReceiverIsAny, BUILTIN, UNINITIALIZED, kNoExtraICState)               \
-  V(TailCall_ReceiverIsNullOrUndefined, BUILTIN, UNINITIALIZED,                \
-    kNoExtraICState)                                                           \
-  V(TailCall_ReceiverIsNotNullOrUndefined, BUILTIN, UNINITIALIZED,             \
-    kNoExtraICState)                                                           \
-  V(TailCall_ReceiverIsAny, BUILTIN, UNINITIALIZED, kNoExtraICState)           \
-                                                                               \
-  V(ConstructFunction, BUILTIN, UNINITIALIZED, kNoExtraICState)                \
-  V(ConstructBoundFunction, BUILTIN, UNINITIALIZED, kNoExtraICState)           \
-  V(ConstructProxy, BUILTIN, UNINITIALIZED, kNoExtraICState)                   \
-  V(Construct, BUILTIN, UNINITIALIZED, kNoExtraICState)                        \
-                                                                               \
-  V(Apply, BUILTIN, UNINITIALIZED, kNoExtraICState)                            \
-                                                                               \
-  V(HandleFastApiCall, BUILTIN, UNINITIALIZED, kNoExtraICState)                \
-                                                                               \
-  V(InOptimizationQueue, BUILTIN, UNINITIALIZED, kNoExtraICState)              \
-  V(JSConstructStubGeneric, BUILTIN, UNINITIALIZED, kNoExtraICState)           \
-  V(JSBuiltinsConstructStub, BUILTIN, UNINITIALIZED, kNoExtraICState)          \
-  V(JSBuiltinsConstructStubForDerived, BUILTIN, UNINITIALIZED,                 \
-    kNoExtraICState)                                                           \
-  V(JSConstructStubApi, BUILTIN, UNINITIALIZED, kNoExtraICState)               \
-  V(JSEntryTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState)                \
-  V(JSConstructEntryTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState)       \
-  V(CompileLazy, BUILTIN, UNINITIALIZED, kNoExtraICState)                      \
-  V(CompileOptimized, BUILTIN, UNINITIALIZED, kNoExtraICState)                 \
-  V(CompileOptimizedConcurrent, BUILTIN, UNINITIALIZED, kNoExtraICState)       \
-  V(NotifyDeoptimized, BUILTIN, UNINITIALIZED, kNoExtraICState)                \
-  V(NotifySoftDeoptimized, BUILTIN, UNINITIALIZED, kNoExtraICState)            \
-  V(NotifyLazyDeoptimized, BUILTIN, UNINITIALIZED, kNoExtraICState)            \
-  V(NotifyStubFailure, BUILTIN, UNINITIALIZED, kNoExtraICState)                \
-  V(NotifyStubFailureSaveDoubles, BUILTIN, UNINITIALIZED, kNoExtraICState)     \
-                                                                               \
-  V(InterpreterEntryTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState)       \
-  V(InterpreterExitTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState)        \
-  V(InterpreterPushArgsAndCall, BUILTIN, UNINITIALIZED, kNoExtraICState)       \
-  V(InterpreterPushArgsAndTailCall, BUILTIN, UNINITIALIZED, kNoExtraICState)   \
-  V(InterpreterPushArgsAndConstruct, BUILTIN, UNINITIALIZED, kNoExtraICState)  \
-  V(InterpreterNotifyDeoptimized, BUILTIN, UNINITIALIZED, kNoExtraICState)     \
-  V(InterpreterNotifySoftDeoptimized, BUILTIN, UNINITIALIZED, kNoExtraICState) \
-  V(InterpreterNotifyLazyDeoptimized, BUILTIN, UNINITIALIZED, kNoExtraICState) \
-  V(InterpreterEnterBytecodeDispatch, BUILTIN, UNINITIALIZED, kNoExtraICState) \
-                                                                               \
-  V(LoadIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState)                      \
-  V(KeyedLoadIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState)                 \
-  V(StoreIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState)                     \
-  V(KeyedStoreIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState)                \
-  V(LoadIC_Getter_ForDeopt, LOAD_IC, MONOMORPHIC, kNoExtraICState)             \
-  V(KeyedLoadIC_Megamorphic, KEYED_LOAD_IC, MEGAMORPHIC, kNoExtraICState)      \
-                                                                               \
-  V(StoreIC_Setter_ForDeopt, STORE_IC, MONOMORPHIC,                            \
-    StoreICState::kStrictModeState)                                            \
-                                                                               \
-  V(KeyedStoreIC_Initialize, KEYED_STORE_IC, UNINITIALIZED, kNoExtraICState)   \
-  V(KeyedStoreIC_PreMonomorphic, KEYED_STORE_IC, PREMONOMORPHIC,               \
-    kNoExtraICState)                                                           \
-  V(KeyedStoreIC_Megamorphic, KEYED_STORE_IC, MEGAMORPHIC, kNoExtraICState)    \
-                                                                               \
-  V(KeyedStoreIC_Initialize_Strict, KEYED_STORE_IC, UNINITIALIZED,             \
-    StoreICState::kStrictModeState)                                            \
-  V(KeyedStoreIC_PreMonomorphic_Strict, KEYED_STORE_IC, PREMONOMORPHIC,        \
-    StoreICState::kStrictModeState)                                            \
-  V(KeyedStoreIC_Megamorphic_Strict, KEYED_STORE_IC, MEGAMORPHIC,              \
-    StoreICState::kStrictModeState)                                            \
-                                                                               \
-  V(DatePrototypeGetDate, BUILTIN, UNINITIALIZED, kNoExtraICState)             \
-  V(DatePrototypeGetDay, BUILTIN, UNINITIALIZED, kNoExtraICState)              \
-  V(DatePrototypeGetFullYear, BUILTIN, UNINITIALIZED, kNoExtraICState)         \
-  V(DatePrototypeGetHours, BUILTIN, UNINITIALIZED, kNoExtraICState)            \
-  V(DatePrototypeGetMilliseconds, BUILTIN, UNINITIALIZED, kNoExtraICState)     \
-  V(DatePrototypeGetMinutes, BUILTIN, UNINITIALIZED, kNoExtraICState)          \
-  V(DatePrototypeGetMonth, BUILTIN, UNINITIALIZED, kNoExtraICState)            \
-  V(DatePrototypeGetSeconds, BUILTIN, UNINITIALIZED, kNoExtraICState)          \
-  V(DatePrototypeGetTime, BUILTIN, UNINITIALIZED, kNoExtraICState)             \
-  V(DatePrototypeGetTimezoneOffset, BUILTIN, UNINITIALIZED, kNoExtraICState)   \
-  V(DatePrototypeGetUTCDate, BUILTIN, UNINITIALIZED, kNoExtraICState)          \
-  V(DatePrototypeGetUTCDay, BUILTIN, UNINITIALIZED, kNoExtraICState)           \
-  V(DatePrototypeGetUTCFullYear, BUILTIN, UNINITIALIZED, kNoExtraICState)      \
-  V(DatePrototypeGetUTCHours, BUILTIN, UNINITIALIZED, kNoExtraICState)         \
-  V(DatePrototypeGetUTCMilliseconds, BUILTIN, UNINITIALIZED, kNoExtraICState)  \
-  V(DatePrototypeGetUTCMinutes, BUILTIN, UNINITIALIZED, kNoExtraICState)       \
-  V(DatePrototypeGetUTCMonth, BUILTIN, UNINITIALIZED, kNoExtraICState)         \
-  V(DatePrototypeGetUTCSeconds, BUILTIN, UNINITIALIZED, kNoExtraICState)       \
-                                                                               \
-  V(FunctionHasInstance, BUILTIN, UNINITIALIZED, kNoExtraICState)              \
-  V(FunctionPrototypeApply, BUILTIN, UNINITIALIZED, kNoExtraICState)           \
-  V(FunctionPrototypeCall, BUILTIN, UNINITIALIZED, kNoExtraICState)            \
-                                                                               \
-  V(ReflectApply, BUILTIN, UNINITIALIZED, kNoExtraICState)                     \
-  V(ReflectConstruct, BUILTIN, UNINITIALIZED, kNoExtraICState)                 \
-                                                                               \
-  V(InternalArrayCode, BUILTIN, UNINITIALIZED, kNoExtraICState)                \
-  V(ArrayCode, BUILTIN, UNINITIALIZED, kNoExtraICState)                        \
-                                                                               \
-  V(MathMax, BUILTIN, UNINITIALIZED, kNoExtraICState)                          \
-  V(MathMin, BUILTIN, UNINITIALIZED, kNoExtraICState)                          \
-                                                                               \
-  V(NumberConstructor, BUILTIN, UNINITIALIZED, kNoExtraICState)                \
-  V(NumberConstructor_ConstructStub, BUILTIN, UNINITIALIZED, kNoExtraICState)  \
-                                                                               \
-  V(StringConstructor, BUILTIN, UNINITIALIZED, kNoExtraICState)                \
-  V(StringConstructor_ConstructStub, BUILTIN, UNINITIALIZED, kNoExtraICState)  \
-                                                                               \
-  V(OnStackReplacement, BUILTIN, UNINITIALIZED, kNoExtraICState)               \
-  V(InterruptCheck, BUILTIN, UNINITIALIZED, kNoExtraICState)                   \
-  V(StackCheck, BUILTIN, UNINITIALIZED, kNoExtraICState)                       \
-                                                                               \
-  V(MarkCodeAsToBeExecutedOnce, BUILTIN, UNINITIALIZED, kNoExtraICState)       \
-  V(MarkCodeAsExecutedOnce, BUILTIN, UNINITIALIZED, kNoExtraICState)           \
-  V(MarkCodeAsExecutedTwice, BUILTIN, UNINITIALIZED, kNoExtraICState)          \
+#define BUILTIN_LIST_A(V)                                                    \
+  V(AllocateInNewSpace, BUILTIN, kNoExtraICState)                            \
+  V(AllocateInOldSpace, BUILTIN, kNoExtraICState)                            \
+                                                                             \
+  V(ArgumentsAdaptorTrampoline, BUILTIN, kNoExtraICState)                    \
+                                                                             \
+  V(ConstructedNonConstructable, BUILTIN, kNoExtraICState)                   \
+                                                                             \
+  V(CallFunction_ReceiverIsNullOrUndefined, BUILTIN, kNoExtraICState)        \
+  V(CallFunction_ReceiverIsNotNullOrUndefined, BUILTIN, kNoExtraICState)     \
+  V(CallFunction_ReceiverIsAny, BUILTIN, kNoExtraICState)                    \
+  V(TailCallFunction_ReceiverIsNullOrUndefined, BUILTIN, kNoExtraICState)    \
+  V(TailCallFunction_ReceiverIsNotNullOrUndefined, BUILTIN, kNoExtraICState) \
+  V(TailCallFunction_ReceiverIsAny, BUILTIN, kNoExtraICState)                \
+  V(CallBoundFunction, BUILTIN, kNoExtraICState)                             \
+  V(TailCallBoundFunction, BUILTIN, kNoExtraICState)                         \
+  V(Call_ReceiverIsNullOrUndefined, BUILTIN, kNoExtraICState)                \
+  V(Call_ReceiverIsNotNullOrUndefined, BUILTIN, kNoExtraICState)             \
+  V(Call_ReceiverIsAny, BUILTIN, kNoExtraICState)                            \
+  V(TailCall_ReceiverIsNullOrUndefined, BUILTIN, kNoExtraICState)            \
+  V(TailCall_ReceiverIsNotNullOrUndefined, BUILTIN, kNoExtraICState)         \
+  V(TailCall_ReceiverIsAny, BUILTIN, kNoExtraICState)                        \
+                                                                             \
+  V(ConstructFunction, BUILTIN, kNoExtraICState)                             \
+  V(ConstructBoundFunction, BUILTIN, kNoExtraICState)                        \
+  V(ConstructProxy, BUILTIN, kNoExtraICState)                                \
+  V(Construct, BUILTIN, kNoExtraICState)                                     \
+                                                                             \
+  V(StringToNumber, BUILTIN, kNoExtraICState)                                \
+  V(NonNumberToNumber, BUILTIN, kNoExtraICState)                             \
+  V(ToNumber, BUILTIN, kNoExtraICState)                                      \
+                                                                             \
+  V(Apply, BUILTIN, kNoExtraICState)                                         \
+                                                                             \
+  V(HandleFastApiCall, BUILTIN, kNoExtraICState)                             \
+                                                                             \
+  V(InOptimizationQueue, BUILTIN, kNoExtraICState)                           \
+  V(JSConstructStubGeneric, BUILTIN, kNoExtraICState)                        \
+  V(JSBuiltinsConstructStub, BUILTIN, kNoExtraICState)                       \
+  V(JSBuiltinsConstructStubForDerived, BUILTIN, kNoExtraICState)             \
+  V(JSConstructStubApi, BUILTIN, kNoExtraICState)                            \
+  V(JSEntryTrampoline, BUILTIN, kNoExtraICState)                             \
+  V(JSConstructEntryTrampoline, BUILTIN, kNoExtraICState)                    \
+  V(ResumeGeneratorTrampoline, BUILTIN, kNoExtraICState)                     \
+  V(CompileLazy, BUILTIN, kNoExtraICState)                                   \
+  V(CompileBaseline, BUILTIN, kNoExtraICState)                               \
+  V(CompileOptimized, BUILTIN, kNoExtraICState)                              \
+  V(CompileOptimizedConcurrent, BUILTIN, kNoExtraICState)                    \
+  V(NotifyDeoptimized, BUILTIN, kNoExtraICState)                             \
+  V(NotifySoftDeoptimized, BUILTIN, kNoExtraICState)                         \
+  V(NotifyLazyDeoptimized, BUILTIN, kNoExtraICState)                         \
+  V(NotifyStubFailure, BUILTIN, kNoExtraICState)                             \
+  V(NotifyStubFailureSaveDoubles, BUILTIN, kNoExtraICState)                  \
+                                                                             \
+  V(InterpreterEntryTrampoline, BUILTIN, kNoExtraICState)                    \
+  V(InterpreterMarkBaselineOnReturn, BUILTIN, kNoExtraICState)               \
+  V(InterpreterPushArgsAndCall, BUILTIN, kNoExtraICState)                    \
+  V(InterpreterPushArgsAndTailCall, BUILTIN, kNoExtraICState)                \
+  V(InterpreterPushArgsAndConstruct, BUILTIN, kNoExtraICState)               \
+  V(InterpreterEnterBytecodeDispatch, BUILTIN, kNoExtraICState)              \
+                                                                             \
+  V(KeyedLoadIC_Miss, BUILTIN, kNoExtraICState)                              \
+  V(StoreIC_Miss, BUILTIN, kNoExtraICState)                                  \
+  V(KeyedStoreIC_Miss, BUILTIN, kNoExtraICState)                             \
+  V(LoadIC_Getter_ForDeopt, LOAD_IC, kNoExtraICState)                        \
+  V(KeyedLoadIC_Megamorphic, KEYED_LOAD_IC, kNoExtraICState)                 \
+                                                                             \
+  V(StoreIC_Setter_ForDeopt, STORE_IC, StoreICState::kStrictModeState)       \
+                                                                             \
+  V(KeyedStoreIC_Megamorphic, KEYED_STORE_IC, kNoExtraICState)               \
+  V(KeyedStoreIC_Megamorphic_Strict, KEYED_STORE_IC,                         \
+    StoreICState::kStrictModeState)                                          \
+                                                                             \
+  V(DatePrototypeGetDate, BUILTIN, kNoExtraICState)                          \
+  V(DatePrototypeGetDay, BUILTIN, kNoExtraICState)                           \
+  V(DatePrototypeGetFullYear, BUILTIN, kNoExtraICState)                      \
+  V(DatePrototypeGetHours, BUILTIN, kNoExtraICState)                         \
+  V(DatePrototypeGetMilliseconds, BUILTIN, kNoExtraICState)                  \
+  V(DatePrototypeGetMinutes, BUILTIN, kNoExtraICState)                       \
+  V(DatePrototypeGetMonth, BUILTIN, kNoExtraICState)                         \
+  V(DatePrototypeGetSeconds, BUILTIN, kNoExtraICState)                       \
+  V(DatePrototypeGetTime, BUILTIN, kNoExtraICState)                          \
+  V(DatePrototypeGetTimezoneOffset, BUILTIN, kNoExtraICState)                \
+  V(DatePrototypeGetUTCDate, BUILTIN, kNoExtraICState)                       \
+  V(DatePrototypeGetUTCDay, BUILTIN, kNoExtraICState)                        \
+  V(DatePrototypeGetUTCFullYear, BUILTIN, kNoExtraICState)                   \
+  V(DatePrototypeGetUTCHours, BUILTIN, kNoExtraICState)                      \
+  V(DatePrototypeGetUTCMilliseconds, BUILTIN, kNoExtraICState)               \
+  V(DatePrototypeGetUTCMinutes, BUILTIN, kNoExtraICState)                    \
+  V(DatePrototypeGetUTCMonth, BUILTIN, kNoExtraICState)                      \
+  V(DatePrototypeGetUTCSeconds, BUILTIN, kNoExtraICState)                    \
+                                                                             \
+  V(FunctionPrototypeApply, BUILTIN, kNoExtraICState)                        \
+  V(FunctionPrototypeCall, BUILTIN, kNoExtraICState)                         \
+                                                                             \
+  V(ReflectApply, BUILTIN, kNoExtraICState)                                  \
+  V(ReflectConstruct, BUILTIN, kNoExtraICState)                              \
+                                                                             \
+  V(InternalArrayCode, BUILTIN, kNoExtraICState)                             \
+  V(ArrayCode, BUILTIN, kNoExtraICState)                                     \
+                                                                             \
+  V(MathMax, BUILTIN, kNoExtraICState)                                       \
+  V(MathMin, BUILTIN, kNoExtraICState)                                       \
+                                                                             \
+  V(NumberConstructor, BUILTIN, kNoExtraICState)                             \
+  V(NumberConstructor_ConstructStub, BUILTIN, kNoExtraICState)               \
+                                                                             \
+  V(StringConstructor, BUILTIN, kNoExtraICState)                             \
+  V(StringConstructor_ConstructStub, BUILTIN, kNoExtraICState)               \
+                                                                             \
+  V(OnStackReplacement, BUILTIN, kNoExtraICState)                            \
+  V(InterruptCheck, BUILTIN, kNoExtraICState)                                \
+  V(StackCheck, BUILTIN, kNoExtraICState)                                    \
+                                                                             \
+  V(MarkCodeAsToBeExecutedOnce, BUILTIN, kNoExtraICState)                    \
+  V(MarkCodeAsExecutedOnce, BUILTIN, kNoExtraICState)                        \
+  V(MarkCodeAsExecutedTwice, BUILTIN, kNoExtraICState)                       \
   CODE_AGE_LIST_WITH_ARG(DECLARE_CODE_AGE_BUILTIN, V)
 
 // Define list of builtins implemented in TurboFan (with JS linkage).
-#define BUILTIN_LIST_T(V) \
-  V(MathCeil, 2)          \
-  V(MathClz32, 2)         \
-  V(MathFloor, 2)         \
-  V(MathRound, 2)         \
-  V(MathSqrt, 2)          \
-  V(MathTrunc, 2)         \
-  V(ObjectHasOwnProperty, 2)
+#define BUILTIN_LIST_T(V)             \
+  V(FunctionPrototypeHasInstance, 2)  \
+  V(GeneratorPrototypeNext, 2)        \
+  V(GeneratorPrototypeReturn, 2)      \
+  V(GeneratorPrototypeThrow, 2)       \
+  V(MathAtan, 2)                      \
+  V(MathAtan2, 3)                     \
+  V(MathAtanh, 2)                     \
+  V(MathCeil, 2)                      \
+  V(MathCbrt, 2)                      \
+  V(MathExpm1, 2)                     \
+  V(MathClz32, 2)                     \
+  V(MathCos, 2)                       \
+  V(MathExp, 2)                       \
+  V(MathFloor, 2)                     \
+  V(MathLog, 2)                       \
+  V(MathLog1p, 2)                     \
+  V(MathLog2, 2)                      \
+  V(MathLog10, 2)                     \
+  V(MathRound, 2)                     \
+  V(MathSin, 2)                       \
+  V(MathTan, 2)                       \
+  V(MathSqrt, 2)                      \
+  V(MathTrunc, 2)                     \
+  V(ObjectHasOwnProperty, 2)          \
+  V(ArrayIsArray, 2)                  \
+  V(StringFromCharCode, 2)            \
+  V(StringPrototypeCharAt, 2)         \
+  V(StringPrototypeCharCodeAt, 2)     \
+  V(TypedArrayPrototypeByteLength, 1) \
+  V(TypedArrayPrototypeByteOffset, 1) \
+  V(TypedArrayPrototypeLength, 1)     \
+  V(AtomicsLoad, 3)                   \
+  V(AtomicsStore, 4)
+
+// Define list of builtins implemented in TurboFan (with CallStub linkage).
+#define BUILTIN_LIST_S(V)                                                   \
+  V(LoadGlobalIC_Miss, BUILTIN, kNoExtraICState, LoadGlobalWithVector)      \
+  V(LoadGlobalIC_Slow, HANDLER, Code::LOAD_GLOBAL_IC, LoadGlobalWithVector) \
+  V(LoadIC_Miss, BUILTIN, kNoExtraICState, LoadWithVector)                  \
+  V(LoadIC_Slow, HANDLER, Code::LOAD_IC, LoadWithVector)
 
 // Define list of builtin handlers implemented in assembly.
 #define BUILTIN_LIST_H(V)                    \
-  V(LoadIC_Slow,             LOAD_IC)        \
   V(KeyedLoadIC_Slow,        KEYED_LOAD_IC)  \
   V(StoreIC_Slow,            STORE_IC)       \
   V(KeyedStoreIC_Slow,       KEYED_STORE_IC) \
@@ -327,11 +352,10 @@
   V(StoreIC_Normal,          STORE_IC)
 
 // Define list of builtins used by the debugger implemented in assembly.
-#define BUILTIN_LIST_DEBUG_A(V)                                 \
-  V(Return_DebugBreak, BUILTIN, DEBUG_STUB, kNoExtraICState)    \
-  V(Slot_DebugBreak, BUILTIN, DEBUG_STUB, kNoExtraICState)      \
-  V(FrameDropper_LiveEdit, BUILTIN, DEBUG_STUB, kNoExtraICState)
-
+#define BUILTIN_LIST_DEBUG_A(V)                  \
+  V(Return_DebugBreak, BUILTIN, kNoExtraICState) \
+  V(Slot_DebugBreak, BUILTIN, kNoExtraICState)   \
+  V(FrameDropper_LiveEdit, BUILTIN, kNoExtraICState)
 
 class BuiltinFunctionTable;
 class ObjectVisitor;
@@ -353,40 +377,45 @@
   const char* Lookup(byte* pc);
 
   enum Name {
-#define DEF_ENUM_C(name, ignore) k##name,
-#define DEF_ENUM_A(name, kind, state, extra) k##name,
+#define DEF_ENUM_C(name) k##name,
+#define DEF_ENUM_A(name, kind, extra) k##name,
 #define DEF_ENUM_T(name, argc) k##name,
+#define DEF_ENUM_S(name, kind, extra, interface_descriptor) k##name,
 #define DEF_ENUM_H(name, kind) k##name,
     BUILTIN_LIST_C(DEF_ENUM_C) BUILTIN_LIST_A(DEF_ENUM_A)
-        BUILTIN_LIST_T(DEF_ENUM_T) BUILTIN_LIST_H(DEF_ENUM_H)
-            BUILTIN_LIST_DEBUG_A(DEF_ENUM_A)
+        BUILTIN_LIST_T(DEF_ENUM_T) BUILTIN_LIST_S(DEF_ENUM_S)
+            BUILTIN_LIST_H(DEF_ENUM_H) BUILTIN_LIST_DEBUG_A(DEF_ENUM_A)
 #undef DEF_ENUM_C
 #undef DEF_ENUM_A
 #undef DEF_ENUM_T
+#undef DEF_ENUM_S
 #undef DEF_ENUM_H
                 builtin_count
   };
 
   enum CFunctionId {
-#define DEF_ENUM_C(name, ignore) c_##name,
+#define DEF_ENUM_C(name) c_##name,
     BUILTIN_LIST_C(DEF_ENUM_C)
 #undef DEF_ENUM_C
     cfunction_count
   };
 
-#define DECLARE_BUILTIN_ACCESSOR_C(name, ignore) Handle<Code> name();
-#define DECLARE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \
-  Handle<Code> name();
+#define DECLARE_BUILTIN_ACCESSOR_C(name) Handle<Code> name();
+#define DECLARE_BUILTIN_ACCESSOR_A(name, kind, extra) Handle<Code> name();
 #define DECLARE_BUILTIN_ACCESSOR_T(name, argc) Handle<Code> name();
+#define DECLARE_BUILTIN_ACCESSOR_S(name, kind, extra, interface_descriptor) \
+  Handle<Code> name();
 #define DECLARE_BUILTIN_ACCESSOR_H(name, kind) Handle<Code> name();
   BUILTIN_LIST_C(DECLARE_BUILTIN_ACCESSOR_C)
   BUILTIN_LIST_A(DECLARE_BUILTIN_ACCESSOR_A)
   BUILTIN_LIST_T(DECLARE_BUILTIN_ACCESSOR_T)
+  BUILTIN_LIST_S(DECLARE_BUILTIN_ACCESSOR_S)
   BUILTIN_LIST_H(DECLARE_BUILTIN_ACCESSOR_H)
   BUILTIN_LIST_DEBUG_A(DECLARE_BUILTIN_ACCESSOR_A)
 #undef DECLARE_BUILTIN_ACCESSOR_C
 #undef DECLARE_BUILTIN_ACCESSOR_A
 #undef DECLARE_BUILTIN_ACCESSOR_T
+#undef DECLARE_BUILTIN_ACCESSOR_S
 #undef DECLARE_BUILTIN_ACCESSOR_H
 
   // Convenience wrappers.
@@ -421,8 +450,8 @@
   bool is_initialized() const { return initialized_; }
 
   MUST_USE_RESULT static MaybeHandle<Object> InvokeApiFunction(
-      Handle<HeapObject> function, Handle<Object> receiver, int argc,
-      Handle<Object> args[]);
+      Isolate* isolate, Handle<HeapObject> function, Handle<Object> receiver,
+      int argc, Handle<Object> args[]);
 
  private:
   Builtins();
@@ -436,11 +465,12 @@
   Object* builtins_[builtin_count];
   const char* names_[builtin_count];
 
-  static void Generate_Adaptor(MacroAssembler* masm,
-                               CFunctionId id,
-                               BuiltinExtraArguments extra_args);
+  static void Generate_Adaptor(MacroAssembler* masm, CFunctionId id);
+  static void Generate_AllocateInNewSpace(MacroAssembler* masm);
+  static void Generate_AllocateInOldSpace(MacroAssembler* masm);
   static void Generate_ConstructedNonConstructable(MacroAssembler* masm);
   static void Generate_CompileLazy(MacroAssembler* masm);
+  static void Generate_CompileBaseline(MacroAssembler* masm);
   static void Generate_InOptimizationQueue(MacroAssembler* masm);
   static void Generate_CompileOptimized(MacroAssembler* masm);
   static void Generate_CompileOptimizedConcurrent(MacroAssembler* masm);
@@ -450,12 +480,16 @@
   static void Generate_JSConstructStubApi(MacroAssembler* masm);
   static void Generate_JSEntryTrampoline(MacroAssembler* masm);
   static void Generate_JSConstructEntryTrampoline(MacroAssembler* masm);
+  static void Generate_ResumeGeneratorTrampoline(MacroAssembler* masm);
   static void Generate_NotifyDeoptimized(MacroAssembler* masm);
   static void Generate_NotifySoftDeoptimized(MacroAssembler* masm);
   static void Generate_NotifyLazyDeoptimized(MacroAssembler* masm);
   static void Generate_NotifyStubFailure(MacroAssembler* masm);
   static void Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm);
   static void Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm);
+  static void Generate_StringToNumber(MacroAssembler* masm);
+  static void Generate_NonNumberToNumber(MacroAssembler* masm);
+  static void Generate_ToNumber(MacroAssembler* masm);
 
   static void Generate_Apply(MacroAssembler* masm);
 
@@ -578,7 +612,6 @@
   // ES6 section 20.3.4.19 Date.prototype.getUTCSeconds ( )
   static void Generate_DatePrototypeGetUTCSeconds(MacroAssembler* masm);
 
-  static void Generate_FunctionHasInstance(MacroAssembler* masm);
   static void Generate_FunctionPrototypeApply(MacroAssembler* masm);
   static void Generate_FunctionPrototypeCall(MacroAssembler* masm);
 
@@ -588,12 +621,34 @@
   static void Generate_InternalArrayCode(MacroAssembler* masm);
   static void Generate_ArrayCode(MacroAssembler* masm);
 
+  // ES6 section 20.2.2.6 Math.atan ( x )
+  static void Generate_MathAtan(CodeStubAssembler* assembler);
+  // ES6 section 20.2.2.8 Math.atan2 ( y, x )
+  static void Generate_MathAtan2(CodeStubAssembler* assembler);
+  // ES6 section 20.2.2.7 Math.atanh ( x )
+  static void Generate_MathAtanh(CodeStubAssembler* assembler);
   // ES6 section 20.2.2.10 Math.ceil ( x )
-  static void Generate_MathCeil(compiler::CodeStubAssembler* assembler);
+  static void Generate_MathCeil(CodeStubAssembler* assembler);
+  // ES6 section 20.2.2.9 Math.ceil ( x )
+  static void Generate_MathCbrt(CodeStubAssembler* assembler);
+  // ES6 section 20.2.2.15 Math.expm1 ( x )
+  static void Generate_MathExpm1(CodeStubAssembler* assembler);
   // ES6 section 20.2.2.11 Math.clz32 ( x )
-  static void Generate_MathClz32(compiler::CodeStubAssembler* assembler);
+  static void Generate_MathClz32(CodeStubAssembler* assembler);
+  // ES6 section 20.2.2.12 Math.cos ( x )
+  static void Generate_MathCos(CodeStubAssembler* assembler);
+  // ES6 section 20.2.2.14 Math.exp ( x )
+  static void Generate_MathExp(CodeStubAssembler* assembler);
   // ES6 section 20.2.2.16 Math.floor ( x )
-  static void Generate_MathFloor(compiler::CodeStubAssembler* assembler);
+  static void Generate_MathFloor(CodeStubAssembler* assembler);
+  // ES6 section 20.2.2.20 Math.log ( x )
+  static void Generate_MathLog(CodeStubAssembler* assembler);
+  // ES6 section 20.2.2.21 Math.log ( x )
+  static void Generate_MathLog1p(CodeStubAssembler* assembler);
+
+  static void Generate_MathLog2(CodeStubAssembler* assembler);
+  static void Generate_MathLog10(CodeStubAssembler* assembler);
+
   enum class MathMaxMinKind { kMax, kMin };
   static void Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind);
   // ES6 section 20.2.2.24 Math.max ( value1, value2 , ...values )
@@ -605,29 +660,64 @@
     Generate_MathMaxMin(masm, MathMaxMinKind::kMin);
   }
   // ES6 section 20.2.2.28 Math.round ( x )
-  static void Generate_MathRound(compiler::CodeStubAssembler* assembler);
+  static void Generate_MathRound(CodeStubAssembler* assembler);
+  // ES6 section 20.2.2.20 Math.sin ( x )
+  static void Generate_MathSin(CodeStubAssembler* assembler);
   // ES6 section 20.2.2.32 Math.sqrt ( x )
-  static void Generate_MathSqrt(compiler::CodeStubAssembler* assembler);
+  static void Generate_MathSqrt(CodeStubAssembler* assembler);
+  // ES6 section 20.2.2.33 Math.sin ( x )
+  static void Generate_MathTan(CodeStubAssembler* assembler);
   // ES6 section 20.2.2.35 Math.trunc ( x )
-  static void Generate_MathTrunc(compiler::CodeStubAssembler* assembler);
+  static void Generate_MathTrunc(CodeStubAssembler* assembler);
 
   // ES6 section 20.1.1.1 Number ( [ value ] ) for the [[Call]] case.
   static void Generate_NumberConstructor(MacroAssembler* masm);
   // ES6 section 20.1.1.1 Number ( [ value ] ) for the [[Construct]] case.
   static void Generate_NumberConstructor_ConstructStub(MacroAssembler* masm);
 
+  // ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] ( V )
+  static void Generate_FunctionPrototypeHasInstance(
+      CodeStubAssembler* assembler);
+
+  // ES6 section 25.3.1.2 Generator.prototype.next ( value )
+  static void Generate_GeneratorPrototypeNext(CodeStubAssembler* assembler);
+  // ES6 section 25.3.1.3 Generator.prototype.return ( value )
+  static void Generate_GeneratorPrototypeReturn(CodeStubAssembler* assembler);
+  // ES6 section 25.3.1.4 Generator.prototype.throw ( exception )
+  static void Generate_GeneratorPrototypeThrow(CodeStubAssembler* assembler);
+
   // ES6 section 19.1.3.2 Object.prototype.hasOwnProperty
-  static void Generate_ObjectHasOwnProperty(
-      compiler::CodeStubAssembler* assembler);
+  static void Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler);
+
+  // ES6 section 22.1.2.2 Array.isArray
+  static void Generate_ArrayIsArray(CodeStubAssembler* assembler);
+
+  // ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits )
+  static void Generate_StringFromCharCode(CodeStubAssembler* assembler);
+  // ES6 section 21.1.3.1 String.prototype.charAt ( pos )
+  static void Generate_StringPrototypeCharAt(CodeStubAssembler* assembler);
+  // ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos )
+  static void Generate_StringPrototypeCharCodeAt(CodeStubAssembler* assembler);
 
   static void Generate_StringConstructor(MacroAssembler* masm);
   static void Generate_StringConstructor_ConstructStub(MacroAssembler* masm);
+
+  // ES6 section 22.2.3.2 get %TypedArray%.prototype.byteLength
+  static void Generate_TypedArrayPrototypeByteLength(
+      CodeStubAssembler* assembler);
+  // ES6 section 22.2.3.3 get %TypedArray%.prototype.byteOffset
+  static void Generate_TypedArrayPrototypeByteOffset(
+      CodeStubAssembler* assembler);
+  // ES6 section 22.2.3.18 get %TypedArray%.prototype.length
+  static void Generate_TypedArrayPrototypeLength(CodeStubAssembler* assembler);
+
   static void Generate_OnStackReplacement(MacroAssembler* masm);
   static void Generate_InterruptCheck(MacroAssembler* masm);
   static void Generate_StackCheck(MacroAssembler* masm);
 
   static void Generate_InterpreterEntryTrampoline(MacroAssembler* masm);
-  static void Generate_InterpreterExitTrampoline(MacroAssembler* masm);
+  static void Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm);
+  static void Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm);
   static void Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
     return Generate_InterpreterPushArgsAndCallImpl(masm,
                                                    TailCallMode::kDisallow);
@@ -638,10 +728,6 @@
   static void Generate_InterpreterPushArgsAndCallImpl(
       MacroAssembler* masm, TailCallMode tail_call_mode);
   static void Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm);
-  static void Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm);
-  static void Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm);
-  static void Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm);
-  static void Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm);
 
 #define DECLARE_CODE_AGE_BUILTIN_GENERATOR(C)                \
   static void Generate_Make##C##CodeYoungAgainEvenMarking(   \
@@ -655,6 +741,9 @@
   static void Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm);
   static void Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm);
 
+  static void Generate_AtomicsLoad(CodeStubAssembler* assembler);
+  static void Generate_AtomicsStore(CodeStubAssembler* assembler);
+
   static void InitBuiltinFunctionTable();
 
   bool initialized_;
diff --git a/src/cancelable-task.cc b/src/cancelable-task.cc
index d231bb7..defbb44 100644
--- a/src/cancelable-task.cc
+++ b/src/cancelable-task.cc
@@ -14,7 +14,6 @@
 Cancelable::Cancelable(CancelableTaskManager* parent)
     : parent_(parent), status_(kWaiting), id_(0), cancel_counter_(0) {
   id_ = parent->Register(this);
-  CHECK(id_ != 0);
 }
 
 
@@ -27,49 +26,35 @@
   }
 }
 
-
-static bool ComparePointers(void* ptr1, void* ptr2) { return ptr1 == ptr2; }
-
-
-CancelableTaskManager::CancelableTaskManager()
-    : task_id_counter_(0), cancelable_tasks_(ComparePointers) {}
-
+CancelableTaskManager::CancelableTaskManager() : task_id_counter_(0) {}
 
 uint32_t CancelableTaskManager::Register(Cancelable* task) {
   base::LockGuard<base::Mutex> guard(&mutex_);
   uint32_t id = ++task_id_counter_;
   // The loop below is just used when task_id_counter_ overflows.
-  while ((id == 0) || (cancelable_tasks_.Lookup(reinterpret_cast<void*>(id),
-                                                id) != nullptr)) {
-    ++id;
-  }
-  HashMap::Entry* entry =
-      cancelable_tasks_.LookupOrInsert(reinterpret_cast<void*>(id), id);
-  entry->value = task;
+  while (cancelable_tasks_.count(id) > 0) ++id;
+  cancelable_tasks_[id] = task;
   return id;
 }
 
 
 void CancelableTaskManager::RemoveFinishedTask(uint32_t id) {
   base::LockGuard<base::Mutex> guard(&mutex_);
-  void* removed = cancelable_tasks_.Remove(reinterpret_cast<void*>(id), id);
+  size_t removed = cancelable_tasks_.erase(id);
   USE(removed);
-  DCHECK(removed != nullptr);
+  DCHECK_NE(0, removed);
   cancelable_tasks_barrier_.NotifyOne();
 }
 
 
 bool CancelableTaskManager::TryAbort(uint32_t id) {
   base::LockGuard<base::Mutex> guard(&mutex_);
-  HashMap::Entry* entry =
-      cancelable_tasks_.Lookup(reinterpret_cast<void*>(id), id);
-  if (entry != nullptr) {
-    Cancelable* value = reinterpret_cast<Cancelable*>(entry->value);
+  auto entry = cancelable_tasks_.find(id);
+  if (entry != cancelable_tasks_.end()) {
+    Cancelable* value = entry->second;
     if (value->Cancel()) {
       // Cannot call RemoveFinishedTask here because of recursive locking.
-      void* removed = cancelable_tasks_.Remove(reinterpret_cast<void*>(id), id);
-      USE(removed);
-      DCHECK(removed != nullptr);
+      cancelable_tasks_.erase(entry);
       cancelable_tasks_barrier_.NotifyOne();
       return true;
     }
@@ -85,27 +70,19 @@
   // started.
   base::LockGuard<base::Mutex> guard(&mutex_);
 
-  // HashMap does not support removing while iterating, hence keep a set of
-  // entries that are to be removed.
-  std::set<uint32_t> to_remove;
-
-  // Cancelable tasks could potentially register new tasks, requiring a loop
-  // here.
-  while (cancelable_tasks_.occupancy() > 0) {
-    for (HashMap::Entry* p = cancelable_tasks_.Start(); p != nullptr;
-         p = cancelable_tasks_.Next(p)) {
-      if (reinterpret_cast<Cancelable*>(p->value)->Cancel()) {
-        to_remove.insert(reinterpret_cast<Cancelable*>(p->value)->id());
+  // Cancelable tasks could be running or could potentially register new
+  // tasks, requiring a loop here.
+  while (!cancelable_tasks_.empty()) {
+    for (auto it = cancelable_tasks_.begin(); it != cancelable_tasks_.end();) {
+      auto current = it;
+      // We need to get to the next element before erasing the current.
+      ++it;
+      if (current->second->Cancel()) {
+        cancelable_tasks_.erase(current);
       }
     }
-    // Remove tasks that were successfully canceled.
-    for (auto id : to_remove) {
-      cancelable_tasks_.Remove(reinterpret_cast<void*>(id), id);
-    }
-    to_remove.clear();
-
-    // Finally, wait for already running background tasks.
-    if (cancelable_tasks_.occupancy() > 0) {
+    // Wait for already running background tasks.
+    if (!cancelable_tasks_.empty()) {
       cancelable_tasks_barrier_.Wait(&mutex_);
     }
   }
diff --git a/src/cancelable-task.h b/src/cancelable-task.h
index a8387fc..b1d62aa 100644
--- a/src/cancelable-task.h
+++ b/src/cancelable-task.h
@@ -5,11 +5,12 @@
 #ifndef V8_CANCELABLE_TASK_H_
 #define V8_CANCELABLE_TASK_H_
 
+#include <map>
+
 #include "include/v8-platform.h"
-#include "src/atomic-utils.h"
+#include "src/base/atomic-utils.h"
 #include "src/base/macros.h"
 #include "src/base/platform/condition-variable.h"
-#include "src/hashmap.h"
 
 namespace v8 {
 namespace internal {
@@ -51,7 +52,7 @@
   uint32_t task_id_counter_;
 
   // A set of cancelable tasks that are currently registered.
-  HashMap cancelable_tasks_;
+  std::map<uint32_t, Cancelable*> cancelable_tasks_;
 
   // Mutex and condition variable enabling concurrent register and removing, as
   // well as waiting for background tasks on {CancelAndWait}.
@@ -104,13 +105,13 @@
   }
 
   CancelableTaskManager* parent_;
-  AtomicValue<Status> status_;
+  base::AtomicValue<Status> status_;
   uint32_t id_;
 
   // The counter is incremented for failing tries to cancel a task. This can be
   // used by the task itself as an indication how often external entities tried
   // to abort it.
-  AtomicNumber<intptr_t> cancel_counter_;
+  base::AtomicNumber<intptr_t> cancel_counter_;
 
   friend class CancelableTaskManager;
 
diff --git a/src/code-events.h b/src/code-events.h
new file mode 100644
index 0000000..9ae1cae
--- /dev/null
+++ b/src/code-events.h
@@ -0,0 +1,183 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_CODE_EVENTS_H_
+#define V8_CODE_EVENTS_H_
+
+#include <unordered_set>
+
+#include "src/globals.h"
+
+namespace v8 {
+namespace internal {
+
+class AbstractCode;
+class Name;
+class SharedFunctionInfo;
+class String;
+
+#define LOG_EVENTS_AND_TAGS_LIST(V)                                      \
+  V(CODE_CREATION_EVENT, "code-creation")                                \
+  V(CODE_DISABLE_OPT_EVENT, "code-disable-optimization")                 \
+  V(CODE_MOVE_EVENT, "code-move")                                        \
+  V(CODE_DELETE_EVENT, "code-delete")                                    \
+  V(CODE_MOVING_GC, "code-moving-gc")                                    \
+  V(SHARED_FUNC_MOVE_EVENT, "sfi-move")                                  \
+  V(SNAPSHOT_CODE_NAME_EVENT, "snapshot-code-name")                      \
+  V(TICK_EVENT, "tick")                                                  \
+  V(REPEAT_META_EVENT, "repeat")                                         \
+  V(BUILTIN_TAG, "Builtin")                                              \
+  V(CALL_DEBUG_BREAK_TAG, "CallDebugBreak")                              \
+  V(CALL_DEBUG_PREPARE_STEP_IN_TAG, "CallDebugPrepareStepIn")            \
+  V(CALL_INITIALIZE_TAG, "CallInitialize")                               \
+  V(CALL_MEGAMORPHIC_TAG, "CallMegamorphic")                             \
+  V(CALL_MISS_TAG, "CallMiss")                                           \
+  V(CALL_NORMAL_TAG, "CallNormal")                                       \
+  V(LOAD_INITIALIZE_TAG, "LoadInitialize")                               \
+  V(LOAD_MEGAMORPHIC_TAG, "LoadMegamorphic")                             \
+  V(STORE_INITIALIZE_TAG, "StoreInitialize")                             \
+  V(STORE_GENERIC_TAG, "StoreGeneric")                                   \
+  V(STORE_MEGAMORPHIC_TAG, "StoreMegamorphic")                           \
+  V(KEYED_CALL_DEBUG_BREAK_TAG, "KeyedCallDebugBreak")                   \
+  V(KEYED_CALL_DEBUG_PREPARE_STEP_IN_TAG, "KeyedCallDebugPrepareStepIn") \
+  V(KEYED_CALL_INITIALIZE_TAG, "KeyedCallInitialize")                    \
+  V(KEYED_CALL_MEGAMORPHIC_TAG, "KeyedCallMegamorphic")                  \
+  V(KEYED_CALL_MISS_TAG, "KeyedCallMiss")                                \
+  V(KEYED_CALL_NORMAL_TAG, "KeyedCallNormal")                            \
+  V(CALLBACK_TAG, "Callback")                                            \
+  V(EVAL_TAG, "Eval")                                                    \
+  V(FUNCTION_TAG, "Function")                                            \
+  V(HANDLER_TAG, "Handler")                                              \
+  V(BYTECODE_HANDLER_TAG, "BytecodeHandler")                             \
+  V(KEYED_LOAD_IC_TAG, "KeyedLoadIC")                                    \
+  V(KEYED_LOAD_POLYMORPHIC_IC_TAG, "KeyedLoadPolymorphicIC")             \
+  V(KEYED_EXTERNAL_ARRAY_LOAD_IC_TAG, "KeyedExternalArrayLoadIC")        \
+  V(KEYED_STORE_IC_TAG, "KeyedStoreIC")                                  \
+  V(KEYED_STORE_POLYMORPHIC_IC_TAG, "KeyedStorePolymorphicIC")           \
+  V(KEYED_EXTERNAL_ARRAY_STORE_IC_TAG, "KeyedExternalArrayStoreIC")      \
+  V(LAZY_COMPILE_TAG, "LazyCompile")                                     \
+  V(CALL_IC_TAG, "CallIC")                                               \
+  V(LOAD_IC_TAG, "LoadIC")                                               \
+  V(LOAD_GLOBAL_IC_TAG, "LoadGlobalIC")                                  \
+  V(LOAD_POLYMORPHIC_IC_TAG, "LoadPolymorphicIC")                        \
+  V(REG_EXP_TAG, "RegExp")                                               \
+  V(SCRIPT_TAG, "Script")                                                \
+  V(STORE_IC_TAG, "StoreIC")                                             \
+  V(STORE_POLYMORPHIC_IC_TAG, "StorePolymorphicIC")                      \
+  V(STUB_TAG, "Stub")                                                    \
+  V(NATIVE_FUNCTION_TAG, "Function")                                     \
+  V(NATIVE_LAZY_COMPILE_TAG, "LazyCompile")                              \
+  V(NATIVE_SCRIPT_TAG, "Script")
+// Note that 'NATIVE_' cases for functions and scripts are mapped onto
+// original tags when writing to the log.
+
+#define PROFILE(the_isolate, Call) (the_isolate)->code_event_dispatcher()->Call;
+
+class CodeEventListener {
+ public:
+#define DECLARE_ENUM(enum_item, _) enum_item,
+  enum LogEventsAndTags {
+    LOG_EVENTS_AND_TAGS_LIST(DECLARE_ENUM) NUMBER_OF_LOG_EVENTS
+  };
+#undef DECLARE_ENUM
+
+  virtual ~CodeEventListener() {}
+
+  virtual void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
+                               const char* comment) = 0;
+  virtual void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
+                               Name* name) = 0;
+  virtual void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
+                               SharedFunctionInfo* shared, Name* name) = 0;
+  virtual void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
+                               SharedFunctionInfo* shared, Name* source,
+                               int line, int column) = 0;
+  virtual void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
+                               int args_count) = 0;
+  virtual void CallbackEvent(Name* name, Address entry_point) = 0;
+  virtual void GetterCallbackEvent(Name* name, Address entry_point) = 0;
+  virtual void SetterCallbackEvent(Name* name, Address entry_point) = 0;
+  virtual void RegExpCodeCreateEvent(AbstractCode* code, String* source) = 0;
+  virtual void CodeMoveEvent(AbstractCode* from, Address to) = 0;
+  virtual void SharedFunctionInfoMoveEvent(Address from, Address to) = 0;
+  virtual void CodeMovingGCEvent() = 0;
+  virtual void CodeDisableOptEvent(AbstractCode* code,
+                                   SharedFunctionInfo* shared) = 0;
+  virtual void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta) = 0;
+};
+
+class CodeEventDispatcher {
+ public:
+  using LogEventsAndTags = CodeEventListener::LogEventsAndTags;
+
+  CodeEventDispatcher() {}
+
+  bool AddListener(CodeEventListener* listener) {
+    return listeners_.insert(listener).second;
+  }
+  void RemoveListener(CodeEventListener* listener) {
+    listeners_.erase(listener);
+  }
+
+#define CODE_EVENT_DISPATCH(code) \
+  for (auto it = listeners_.begin(); it != listeners_.end(); ++it) (*it)->code
+
+  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
+                       const char* comment) {
+    CODE_EVENT_DISPATCH(CodeCreateEvent(tag, code, comment));
+  }
+  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code, Name* name) {
+    CODE_EVENT_DISPATCH(CodeCreateEvent(tag, code, name));
+  }
+  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
+                       SharedFunctionInfo* shared, Name* name) {
+    CODE_EVENT_DISPATCH(CodeCreateEvent(tag, code, shared, name));
+  }
+  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
+                       SharedFunctionInfo* shared, Name* source, int line,
+                       int column) {
+    CODE_EVENT_DISPATCH(
+        CodeCreateEvent(tag, code, shared, source, line, column));
+  }
+  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
+                       int args_count) {
+    CODE_EVENT_DISPATCH(CodeCreateEvent(tag, code, args_count));
+  }
+  void CallbackEvent(Name* name, Address entry_point) {
+    CODE_EVENT_DISPATCH(CallbackEvent(name, entry_point));
+  }
+  void GetterCallbackEvent(Name* name, Address entry_point) {
+    CODE_EVENT_DISPATCH(GetterCallbackEvent(name, entry_point));
+  }
+  void SetterCallbackEvent(Name* name, Address entry_point) {
+    CODE_EVENT_DISPATCH(SetterCallbackEvent(name, entry_point));
+  }
+  void RegExpCodeCreateEvent(AbstractCode* code, String* source) {
+    CODE_EVENT_DISPATCH(RegExpCodeCreateEvent(code, source));
+  }
+  void CodeMoveEvent(AbstractCode* from, Address to) {
+    CODE_EVENT_DISPATCH(CodeMoveEvent(from, to));
+  }
+  void SharedFunctionInfoMoveEvent(Address from, Address to) {
+    CODE_EVENT_DISPATCH(SharedFunctionInfoMoveEvent(from, to));
+  }
+  void CodeMovingGCEvent() { CODE_EVENT_DISPATCH(CodeMovingGCEvent()); }
+  void CodeDisableOptEvent(AbstractCode* code, SharedFunctionInfo* shared) {
+    CODE_EVENT_DISPATCH(CodeDisableOptEvent(code, shared));
+  }
+  void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta) {
+    CODE_EVENT_DISPATCH(CodeDeoptEvent(code, pc, fp_to_sp_delta));
+  }
+#undef CODE_EVENT_DISPATCH
+
+ private:
+  std::unordered_set<CodeEventListener*> listeners_;
+
+  DISALLOW_COPY_AND_ASSIGN(CodeEventDispatcher);
+};
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_CODE_EVENTS_H_
diff --git a/src/code-factory.cc b/src/code-factory.cc
index fbfdd5f..944f780 100644
--- a/src/code-factory.cc
+++ b/src/code-factory.cc
@@ -12,40 +12,53 @@
 
 
 // static
-Callable CodeFactory::LoadIC(Isolate* isolate, TypeofMode typeof_mode) {
-  return Callable(LoadIC::initialize_stub(
-                      isolate, LoadICState(typeof_mode).GetExtraICState()),
-                  LoadDescriptor(isolate));
+Callable CodeFactory::LoadIC(Isolate* isolate) {
+  if (FLAG_tf_load_ic_stub) {
+    LoadICTrampolineTFStub stub(isolate);
+    return Callable(stub.GetCode(), LoadDescriptor(isolate));
+  }
+  LoadICTrampolineStub stub(isolate);
+  return Callable(stub.GetCode(), LoadDescriptor(isolate));
 }
 
+// static
+Callable CodeFactory::ApiGetter(Isolate* isolate) {
+  CallApiGetterStub stub(isolate);
+  return Callable(stub.GetCode(), ApiGetterDescriptor(isolate));
+}
 
 // static
-Callable CodeFactory::LoadICInOptimizedCode(
-    Isolate* isolate, TypeofMode typeof_mode,
-    InlineCacheState initialization_state) {
-  auto code = LoadIC::initialize_stub_in_optimized_code(
-      isolate, LoadICState(typeof_mode).GetExtraICState(),
-      initialization_state);
+Callable CodeFactory::LoadICInOptimizedCode(Isolate* isolate) {
+  auto code = LoadIC::initialize_stub_in_optimized_code(isolate);
   return Callable(code, LoadWithVectorDescriptor(isolate));
 }
 
+// static
+Callable CodeFactory::LoadGlobalIC(Isolate* isolate, TypeofMode typeof_mode) {
+  LoadGlobalICTrampolineStub stub(isolate, LoadGlobalICState(typeof_mode));
+  return Callable(stub.GetCode(), LoadGlobalDescriptor(isolate));
+}
+
+// static
+Callable CodeFactory::LoadGlobalICInOptimizedCode(Isolate* isolate,
+                                                  TypeofMode typeof_mode) {
+  auto code = LoadGlobalIC::initialize_stub_in_optimized_code(
+      isolate, LoadGlobalICState(typeof_mode).GetExtraICState());
+  return Callable(code, LoadGlobalWithVectorDescriptor(isolate));
+}
 
 // static
 Callable CodeFactory::KeyedLoadIC(Isolate* isolate) {
-  return Callable(KeyedLoadIC::initialize_stub(isolate, kNoExtraICState),
-                  LoadDescriptor(isolate));
+  KeyedLoadICTrampolineStub stub(isolate);
+  return Callable(stub.GetCode(), LoadDescriptor(isolate));
 }
 
 
 // static
-Callable CodeFactory::KeyedLoadICInOptimizedCode(
-    Isolate* isolate, InlineCacheState initialization_state) {
-  auto code = KeyedLoadIC::initialize_stub_in_optimized_code(
-      isolate, initialization_state, kNoExtraICState);
-  if (initialization_state != MEGAMORPHIC) {
-    return Callable(code, LoadWithVectorDescriptor(isolate));
-  }
-  return Callable(code, LoadDescriptor(isolate));
+Callable CodeFactory::KeyedLoadICInOptimizedCode(Isolate* isolate) {
+  auto code =
+      KeyedLoadIC::initialize_stub_in_optimized_code(isolate, kNoExtraICState);
+  return Callable(code, LoadWithVectorDescriptor(isolate));
 }
 
 
@@ -53,8 +66,8 @@
 Callable CodeFactory::CallIC(Isolate* isolate, int argc,
                              ConvertReceiverMode mode,
                              TailCallMode tail_call_mode) {
-  return Callable(CallIC::initialize_stub(isolate, argc, mode, tail_call_mode),
-                  CallFunctionWithFeedbackDescriptor(isolate));
+  CallICTrampolineStub stub(isolate, CallICState(argc, mode, tail_call_mode));
+  return Callable(stub.GetCode(), CallFunctionWithFeedbackDescriptor(isolate));
 }
 
 
@@ -70,44 +83,36 @@
 
 // static
 Callable CodeFactory::StoreIC(Isolate* isolate, LanguageMode language_mode) {
-  return Callable(
-      StoreIC::initialize_stub(isolate, language_mode, UNINITIALIZED),
-      VectorStoreICTrampolineDescriptor(isolate));
+  VectorStoreICTrampolineStub stub(isolate, StoreICState(language_mode));
+  return Callable(stub.GetCode(), VectorStoreICTrampolineDescriptor(isolate));
 }
 
 
 // static
-Callable CodeFactory::StoreICInOptimizedCode(
-    Isolate* isolate, LanguageMode language_mode,
-    InlineCacheState initialization_state) {
-  CallInterfaceDescriptor descriptor = initialization_state != MEGAMORPHIC
-                                           ? VectorStoreICDescriptor(isolate)
-                                           : StoreDescriptor(isolate);
-  return Callable(StoreIC::initialize_stub_in_optimized_code(
-                      isolate, language_mode, initialization_state),
-                  descriptor);
+Callable CodeFactory::StoreICInOptimizedCode(Isolate* isolate,
+                                             LanguageMode language_mode) {
+  CallInterfaceDescriptor descriptor = VectorStoreICDescriptor(isolate);
+  return Callable(
+      StoreIC::initialize_stub_in_optimized_code(isolate, language_mode),
+      descriptor);
 }
 
 
 // static
 Callable CodeFactory::KeyedStoreIC(Isolate* isolate,
                                    LanguageMode language_mode) {
-  return Callable(
-      KeyedStoreIC::initialize_stub(isolate, language_mode, UNINITIALIZED),
-      VectorStoreICTrampolineDescriptor(isolate));
+  VectorKeyedStoreICTrampolineStub stub(isolate, StoreICState(language_mode));
+  return Callable(stub.GetCode(), VectorStoreICTrampolineDescriptor(isolate));
 }
 
 
 // static
-Callable CodeFactory::KeyedStoreICInOptimizedCode(
-    Isolate* isolate, LanguageMode language_mode,
-    InlineCacheState initialization_state) {
-  CallInterfaceDescriptor descriptor = initialization_state != MEGAMORPHIC
-                                           ? VectorStoreICDescriptor(isolate)
-                                           : StoreDescriptor(isolate);
-  return Callable(KeyedStoreIC::initialize_stub_in_optimized_code(
-                      isolate, language_mode, initialization_state),
-                  descriptor);
+Callable CodeFactory::KeyedStoreICInOptimizedCode(Isolate* isolate,
+                                                  LanguageMode language_mode) {
+  CallInterfaceDescriptor descriptor = VectorStoreICDescriptor(isolate);
+  return Callable(
+      KeyedStoreIC::initialize_stub_in_optimized_code(isolate, language_mode),
+      descriptor);
 }
 
 
@@ -141,21 +146,21 @@
 
 // static
 Callable CodeFactory::ToNumber(Isolate* isolate) {
-  ToNumberStub stub(isolate);
-  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
+  return Callable(isolate->builtins()->ToNumber(),
+                  TypeConversionDescriptor(isolate));
 }
 
 
 // static
 Callable CodeFactory::NonNumberToNumber(Isolate* isolate) {
-  NonNumberToNumberStub stub(isolate);
-  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
+  return Callable(isolate->builtins()->NonNumberToNumber(),
+                  TypeConversionDescriptor(isolate));
 }
 
 // static
 Callable CodeFactory::StringToNumber(Isolate* isolate) {
-  StringToNumberStub stub(isolate);
-  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
+  return Callable(isolate->builtins()->StringToNumber(),
+                  TypeConversionDescriptor(isolate));
 }
 
 // static
@@ -225,6 +230,42 @@
 }
 
 // static
+Callable CodeFactory::Multiply(Isolate* isolate) {
+  MultiplyStub stub(isolate);
+  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
+}
+
+// static
+Callable CodeFactory::Divide(Isolate* isolate) {
+  DivideStub stub(isolate);
+  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
+}
+
+// static
+Callable CodeFactory::Modulus(Isolate* isolate) {
+  ModulusStub stub(isolate);
+  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
+}
+
+// static
+Callable CodeFactory::ShiftRight(Isolate* isolate) {
+  ShiftRightStub stub(isolate);
+  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
+}
+
+// static
+Callable CodeFactory::ShiftRightLogical(Isolate* isolate) {
+  ShiftRightLogicalStub stub(isolate);
+  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
+}
+
+// static
+Callable CodeFactory::ShiftLeft(Isolate* isolate) {
+  ShiftLeftStub stub(isolate);
+  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
+}
+
+// static
 Callable CodeFactory::BitwiseAnd(Isolate* isolate) {
   BitwiseAndStub stub(isolate);
   return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
@@ -243,6 +284,18 @@
 }
 
 // static
+Callable CodeFactory::Inc(Isolate* isolate) {
+  IncStub stub(isolate);
+  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
+}
+
+// static
+Callable CodeFactory::Dec(Isolate* isolate) {
+  DecStub stub(isolate);
+  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
+}
+
+// static
 Callable CodeFactory::LessThan(Isolate* isolate) {
   LessThanStub stub(isolate);
   return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
@@ -365,9 +418,9 @@
 
 
 // static
-Callable CodeFactory::StoreInterceptor(Isolate* isolate) {
-  StoreInterceptorStub stub(isolate);
-  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
+Callable CodeFactory::ResumeGenerator(Isolate* isolate) {
+  return Callable(isolate->builtins()->ResumeGeneratorTrampoline(),
+                  ResumeGeneratorDescriptor(isolate));
 }
 
 // static
@@ -423,22 +476,25 @@
 
 
 // static
-Callable CodeFactory::FastNewRestParameter(Isolate* isolate) {
-  FastNewRestParameterStub stub(isolate);
+Callable CodeFactory::FastNewRestParameter(Isolate* isolate,
+                                           bool skip_stub_frame) {
+  FastNewRestParameterStub stub(isolate, skip_stub_frame);
   return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
 }
 
 
 // static
-Callable CodeFactory::FastNewSloppyArguments(Isolate* isolate) {
-  FastNewSloppyArgumentsStub stub(isolate);
+Callable CodeFactory::FastNewSloppyArguments(Isolate* isolate,
+                                             bool skip_stub_frame) {
+  FastNewSloppyArgumentsStub stub(isolate, skip_stub_frame);
   return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
 }
 
 
 // static
-Callable CodeFactory::FastNewStrictArguments(Isolate* isolate) {
-  FastNewStrictArgumentsStub stub(isolate);
+Callable CodeFactory::FastNewStrictArguments(Isolate* isolate,
+                                             bool skip_stub_frame) {
+  FastNewStrictArgumentsStub stub(isolate, skip_stub_frame);
   return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
 }
 
@@ -449,13 +505,6 @@
   return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
 }
 
-
-// static
-Callable CodeFactory::AllocateMutableHeapNumber(Isolate* isolate) {
-  AllocateMutableHeapNumberStub stub(isolate);
-  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
-}
-
 #define SIMD128_ALLOC(TYPE, Type, type, lane_count, lane_type)          \
   Callable CodeFactory::Allocate##Type(Isolate* isolate) {              \
     Allocate##Type##Stub stub(isolate);                                 \
@@ -465,13 +514,6 @@
 #undef SIMD128_ALLOC
 
 // static
-Callable CodeFactory::AllocateInNewSpace(Isolate* isolate) {
-  AllocateInNewSpaceStub stub(isolate);
-  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
-}
-
-
-// static
 Callable CodeFactory::ArgumentAdaptor(Isolate* isolate) {
   return Callable(isolate->builtins()->ArgumentsAdaptorTrampoline(),
                   ArgumentAdaptorDescriptor(isolate));
@@ -506,6 +548,17 @@
                   ConstructTrampolineDescriptor(isolate));
 }
 
+// static
+Callable CodeFactory::HasProperty(Isolate* isolate) {
+  HasPropertyStub stub(isolate);
+  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
+}
+
+// static
+Callable CodeFactory::MathPow(Isolate* isolate) {
+  MathPowStub stub(isolate, MathPowStub::ON_STACK);
+  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
+}
 
 // static
 Callable CodeFactory::InterpreterPushArgsAndCall(Isolate* isolate,
diff --git a/src/code-factory.h b/src/code-factory.h
index deb125f..7fb7bc5 100644
--- a/src/code-factory.h
+++ b/src/code-factory.h
@@ -32,13 +32,13 @@
 class CodeFactory final {
  public:
   // Initial states for ICs.
-  static Callable LoadIC(Isolate* isolate, TypeofMode typeof_mode);
-  static Callable LoadICInOptimizedCode(Isolate* isolate,
-                                        TypeofMode typeof_mode,
-                                        InlineCacheState initialization_state);
+  static Callable LoadIC(Isolate* isolate);
+  static Callable LoadICInOptimizedCode(Isolate* isolate);
+  static Callable LoadGlobalIC(Isolate* isolate, TypeofMode typeof_mode);
+  static Callable LoadGlobalICInOptimizedCode(Isolate* isolate,
+                                              TypeofMode typeof_mode);
   static Callable KeyedLoadIC(Isolate* isolate);
-  static Callable KeyedLoadICInOptimizedCode(
-      Isolate* isolate, InlineCacheState initialization_state);
+  static Callable KeyedLoadICInOptimizedCode(Isolate* isolate);
   static Callable CallIC(Isolate* isolate, int argc,
                          ConvertReceiverMode mode = ConvertReceiverMode::kAny,
                          TailCallMode tail_call_mode = TailCallMode::kDisallow);
@@ -47,20 +47,20 @@
       ConvertReceiverMode mode = ConvertReceiverMode::kAny,
       TailCallMode tail_call_mode = TailCallMode::kDisallow);
   static Callable StoreIC(Isolate* isolate, LanguageMode mode);
-  static Callable StoreICInOptimizedCode(Isolate* isolate, LanguageMode mode,
-                                         InlineCacheState initialization_state);
+  static Callable StoreICInOptimizedCode(Isolate* isolate, LanguageMode mode);
   static Callable KeyedStoreIC(Isolate* isolate, LanguageMode mode);
-  static Callable KeyedStoreICInOptimizedCode(
-      Isolate* isolate, LanguageMode mode,
-      InlineCacheState initialization_state);
+  static Callable KeyedStoreICInOptimizedCode(Isolate* isolate,
+                                              LanguageMode mode);
 
-  static Callable StoreInterceptor(Isolate* isolate);
+  static Callable ResumeGenerator(Isolate* isolate);
 
   static Callable CompareIC(Isolate* isolate, Token::Value op);
   static Callable CompareNilIC(Isolate* isolate, NilValue nil_value);
 
   static Callable BinaryOpIC(Isolate* isolate, Token::Value op);
 
+  static Callable ApiGetter(Isolate* isolate);
+
   // Code stubs. Add methods here as needed to reduce dependency on
   // code-stubs.h.
   static Callable InstanceOf(Isolate* isolate);
@@ -82,9 +82,17 @@
 
   static Callable Add(Isolate* isolate);
   static Callable Subtract(Isolate* isolate);
+  static Callable Multiply(Isolate* isolate);
+  static Callable Divide(Isolate* isolate);
+  static Callable Modulus(Isolate* isolate);
+  static Callable ShiftRight(Isolate* isolate);
+  static Callable ShiftRightLogical(Isolate* isolate);
+  static Callable ShiftLeft(Isolate* isolate);
   static Callable BitwiseAnd(Isolate* isolate);
   static Callable BitwiseOr(Isolate* isolate);
   static Callable BitwiseXor(Isolate* isolate);
+  static Callable Inc(Isolate* isolate);
+  static Callable Dec(Isolate* isolate);
   static Callable LessThan(Isolate* isolate);
   static Callable LessThanOrEqual(Isolate* isolate);
   static Callable GreaterThan(Isolate* isolate);
@@ -115,17 +123,18 @@
   static Callable FastNewClosure(Isolate* isolate, LanguageMode language_mode,
                                  FunctionKind kind);
   static Callable FastNewObject(Isolate* isolate);
-  static Callable FastNewRestParameter(Isolate* isolate);
-  static Callable FastNewSloppyArguments(Isolate* isolate);
-  static Callable FastNewStrictArguments(Isolate* isolate);
+  static Callable FastNewRestParameter(Isolate* isolate,
+                                       bool skip_stub_frame = false);
+  static Callable FastNewSloppyArguments(Isolate* isolate,
+                                         bool skip_stub_frame = false);
+  static Callable FastNewStrictArguments(Isolate* isolate,
+                                         bool skip_stub_frame = false);
 
   static Callable AllocateHeapNumber(Isolate* isolate);
-  static Callable AllocateMutableHeapNumber(Isolate* isolate);
 #define SIMD128_ALLOC(TYPE, Type, type, lane_count, lane_type) \
   static Callable Allocate##Type(Isolate* isolate);
   SIMD128_TYPES(SIMD128_ALLOC)
 #undef SIMD128_ALLOC
-  static Callable AllocateInNewSpace(Isolate* isolate);
 
   static Callable ArgumentAdaptor(Isolate* isolate);
   static Callable Call(Isolate* isolate,
@@ -135,6 +144,9 @@
       Isolate* isolate, ConvertReceiverMode mode = ConvertReceiverMode::kAny);
   static Callable Construct(Isolate* isolate);
   static Callable ConstructFunction(Isolate* isolate);
+  static Callable HasProperty(Isolate* isolate);
+
+  static Callable MathPow(Isolate* isolate);
 
   static Callable InterpreterPushArgsAndCall(Isolate* isolate,
                                              TailCallMode tail_call_mode);
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
new file mode 100644
index 0000000..dca2167
--- /dev/null
+++ b/src/code-stub-assembler.cc
@@ -0,0 +1,2677 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/code-stub-assembler.h"
+#include "src/code-factory.h"
+#include "src/frames-inl.h"
+#include "src/frames.h"
+#include "src/ic/stub-cache.h"
+
+namespace v8 {
+namespace internal {
+
+using compiler::Node;
+
+CodeStubAssembler::CodeStubAssembler(Isolate* isolate, Zone* zone,
+                                     const CallInterfaceDescriptor& descriptor,
+                                     Code::Flags flags, const char* name,
+                                     size_t result_size)
+    : compiler::CodeAssembler(isolate, zone, descriptor, flags, name,
+                              result_size) {}
+
+CodeStubAssembler::CodeStubAssembler(Isolate* isolate, Zone* zone,
+                                     int parameter_count, Code::Flags flags,
+                                     const char* name)
+    : compiler::CodeAssembler(isolate, zone, parameter_count, flags, name) {}
+
+void CodeStubAssembler::Assert(Node* condition) {
+#if defined(DEBUG)
+  Label ok(this);
+  Comment("[ Assert");
+  GotoIf(condition, &ok);
+  DebugBreak();
+  Goto(&ok);
+  Bind(&ok);
+  Comment("] Assert");
+#endif
+}
+
+Node* CodeStubAssembler::BooleanMapConstant() {
+  return HeapConstant(isolate()->factory()->boolean_map());
+}
+
+Node* CodeStubAssembler::EmptyStringConstant() {
+  return LoadRoot(Heap::kempty_stringRootIndex);
+}
+
+Node* CodeStubAssembler::HeapNumberMapConstant() {
+  return HeapConstant(isolate()->factory()->heap_number_map());
+}
+
+Node* CodeStubAssembler::NoContextConstant() {
+  return SmiConstant(Smi::FromInt(0));
+}
+
+Node* CodeStubAssembler::NullConstant() {
+  return LoadRoot(Heap::kNullValueRootIndex);
+}
+
+Node* CodeStubAssembler::UndefinedConstant() {
+  return LoadRoot(Heap::kUndefinedValueRootIndex);
+}
+
+Node* CodeStubAssembler::TheHoleConstant() {
+  return LoadRoot(Heap::kTheHoleValueRootIndex);
+}
+
+Node* CodeStubAssembler::HashSeed() {
+  return SmiToWord32(LoadRoot(Heap::kHashSeedRootIndex));
+}
+
+Node* CodeStubAssembler::StaleRegisterConstant() {
+  return LoadRoot(Heap::kStaleRegisterRootIndex);
+}
+
+Node* CodeStubAssembler::Float64Round(Node* x) {
+  Node* one = Float64Constant(1.0);
+  Node* one_half = Float64Constant(0.5);
+
+  Variable var_x(this, MachineRepresentation::kFloat64);
+  Label return_x(this);
+
+  // Round up {x} towards Infinity.
+  var_x.Bind(Float64Ceil(x));
+
+  GotoIf(Float64LessThanOrEqual(Float64Sub(var_x.value(), one_half), x),
+         &return_x);
+  var_x.Bind(Float64Sub(var_x.value(), one));
+  Goto(&return_x);
+
+  Bind(&return_x);
+  return var_x.value();
+}
+
+Node* CodeStubAssembler::Float64Ceil(Node* x) {
+  if (IsFloat64RoundUpSupported()) {
+    return Float64RoundUp(x);
+  }
+
+  Node* one = Float64Constant(1.0);
+  Node* zero = Float64Constant(0.0);
+  Node* two_52 = Float64Constant(4503599627370496.0E0);
+  Node* minus_two_52 = Float64Constant(-4503599627370496.0E0);
+
+  Variable var_x(this, MachineRepresentation::kFloat64);
+  Label return_x(this), return_minus_x(this);
+  var_x.Bind(x);
+
+  // Check if {x} is greater than zero.
+  Label if_xgreaterthanzero(this), if_xnotgreaterthanzero(this);
+  Branch(Float64GreaterThan(x, zero), &if_xgreaterthanzero,
+         &if_xnotgreaterthanzero);
+
+  Bind(&if_xgreaterthanzero);
+  {
+    // Just return {x} unless it's in the range ]0,2^52[.
+    GotoIf(Float64GreaterThanOrEqual(x, two_52), &return_x);
+
+    // Round positive {x} towards Infinity.
+    var_x.Bind(Float64Sub(Float64Add(two_52, x), two_52));
+    GotoUnless(Float64LessThan(var_x.value(), x), &return_x);
+    var_x.Bind(Float64Add(var_x.value(), one));
+    Goto(&return_x);
+  }
+
+  Bind(&if_xnotgreaterthanzero);
+  {
+    // Just return {x} unless it's in the range ]-2^52,0[
+    GotoIf(Float64LessThanOrEqual(x, minus_two_52), &return_x);
+    GotoUnless(Float64LessThan(x, zero), &return_x);
+
+    // Round negated {x} towards Infinity and return the result negated.
+    Node* minus_x = Float64Neg(x);
+    var_x.Bind(Float64Sub(Float64Add(two_52, minus_x), two_52));
+    GotoUnless(Float64GreaterThan(var_x.value(), minus_x), &return_minus_x);
+    var_x.Bind(Float64Sub(var_x.value(), one));
+    Goto(&return_minus_x);
+  }
+
+  Bind(&return_minus_x);
+  var_x.Bind(Float64Neg(var_x.value()));
+  Goto(&return_x);
+
+  Bind(&return_x);
+  return var_x.value();
+}
+
+Node* CodeStubAssembler::Float64Floor(Node* x) {
+  if (IsFloat64RoundDownSupported()) {
+    return Float64RoundDown(x);
+  }
+
+  Node* one = Float64Constant(1.0);
+  Node* zero = Float64Constant(0.0);
+  Node* two_52 = Float64Constant(4503599627370496.0E0);
+  Node* minus_two_52 = Float64Constant(-4503599627370496.0E0);
+
+  Variable var_x(this, MachineRepresentation::kFloat64);
+  Label return_x(this), return_minus_x(this);
+  var_x.Bind(x);
+
+  // Check if {x} is greater than zero.
+  Label if_xgreaterthanzero(this), if_xnotgreaterthanzero(this);
+  Branch(Float64GreaterThan(x, zero), &if_xgreaterthanzero,
+         &if_xnotgreaterthanzero);
+
+  Bind(&if_xgreaterthanzero);
+  {
+    // Just return {x} unless it's in the range ]0,2^52[.
+    GotoIf(Float64GreaterThanOrEqual(x, two_52), &return_x);
+
+    // Round positive {x} towards -Infinity.
+    var_x.Bind(Float64Sub(Float64Add(two_52, x), two_52));
+    GotoUnless(Float64GreaterThan(var_x.value(), x), &return_x);
+    var_x.Bind(Float64Sub(var_x.value(), one));
+    Goto(&return_x);
+  }
+
+  Bind(&if_xnotgreaterthanzero);
+  {
+    // Just return {x} unless it's in the range ]-2^52,0[
+    GotoIf(Float64LessThanOrEqual(x, minus_two_52), &return_x);
+    GotoUnless(Float64LessThan(x, zero), &return_x);
+
+    // Round negated {x} towards -Infinity and return the result negated.
+    Node* minus_x = Float64Neg(x);
+    var_x.Bind(Float64Sub(Float64Add(two_52, minus_x), two_52));
+    GotoUnless(Float64LessThan(var_x.value(), minus_x), &return_minus_x);
+    var_x.Bind(Float64Add(var_x.value(), one));
+    Goto(&return_minus_x);
+  }
+
+  Bind(&return_minus_x);
+  var_x.Bind(Float64Neg(var_x.value()));
+  Goto(&return_x);
+
+  Bind(&return_x);
+  return var_x.value();
+}
+
+Node* CodeStubAssembler::Float64Trunc(Node* x) {
+  if (IsFloat64RoundTruncateSupported()) {
+    return Float64RoundTruncate(x);
+  }
+
+  Node* one = Float64Constant(1.0);
+  Node* zero = Float64Constant(0.0);
+  Node* two_52 = Float64Constant(4503599627370496.0E0);
+  Node* minus_two_52 = Float64Constant(-4503599627370496.0E0);
+
+  Variable var_x(this, MachineRepresentation::kFloat64);
+  Label return_x(this), return_minus_x(this);
+  var_x.Bind(x);
+
+  // Check if {x} is greater than 0.
+  Label if_xgreaterthanzero(this), if_xnotgreaterthanzero(this);
+  Branch(Float64GreaterThan(x, zero), &if_xgreaterthanzero,
+         &if_xnotgreaterthanzero);
+
+  Bind(&if_xgreaterthanzero);
+  {
+    if (IsFloat64RoundDownSupported()) {
+      var_x.Bind(Float64RoundDown(x));
+    } else {
+      // Just return {x} unless it's in the range ]0,2^52[.
+      GotoIf(Float64GreaterThanOrEqual(x, two_52), &return_x);
+
+      // Round positive {x} towards -Infinity.
+      var_x.Bind(Float64Sub(Float64Add(two_52, x), two_52));
+      GotoUnless(Float64GreaterThan(var_x.value(), x), &return_x);
+      var_x.Bind(Float64Sub(var_x.value(), one));
+    }
+    Goto(&return_x);
+  }
+
+  Bind(&if_xnotgreaterthanzero);
+  {
+    if (IsFloat64RoundUpSupported()) {
+      var_x.Bind(Float64RoundUp(x));
+      Goto(&return_x);
+    } else {
+      // Just return {x} unless its in the range ]-2^52,0[.
+      GotoIf(Float64LessThanOrEqual(x, minus_two_52), &return_x);
+      GotoUnless(Float64LessThan(x, zero), &return_x);
+
+      // Round negated {x} towards -Infinity and return result negated.
+      Node* minus_x = Float64Neg(x);
+      var_x.Bind(Float64Sub(Float64Add(two_52, minus_x), two_52));
+      GotoUnless(Float64GreaterThan(var_x.value(), minus_x), &return_minus_x);
+      var_x.Bind(Float64Sub(var_x.value(), one));
+      Goto(&return_minus_x);
+    }
+  }
+
+  Bind(&return_minus_x);
+  var_x.Bind(Float64Neg(var_x.value()));
+  Goto(&return_x);
+
+  Bind(&return_x);
+  return var_x.value();
+}
+
+Node* CodeStubAssembler::SmiFromWord32(Node* value) {
+  value = ChangeInt32ToIntPtr(value);
+  return WordShl(value, SmiShiftBitsConstant());
+}
+
+Node* CodeStubAssembler::SmiTag(Node* value) {
+  int32_t constant_value;
+  if (ToInt32Constant(value, constant_value) && Smi::IsValid(constant_value)) {
+    return SmiConstant(Smi::FromInt(constant_value));
+  }
+  return WordShl(value, SmiShiftBitsConstant());
+}
+
+Node* CodeStubAssembler::SmiUntag(Node* value) {
+  return WordSar(value, SmiShiftBitsConstant());
+}
+
+Node* CodeStubAssembler::SmiToWord32(Node* value) {
+  Node* result = WordSar(value, SmiShiftBitsConstant());
+  if (Is64()) {
+    result = TruncateInt64ToInt32(result);
+  }
+  return result;
+}
+
+Node* CodeStubAssembler::SmiToFloat64(Node* value) {
+  return ChangeInt32ToFloat64(SmiToWord32(value));
+}
+
+Node* CodeStubAssembler::SmiAdd(Node* a, Node* b) { return IntPtrAdd(a, b); }
+
+Node* CodeStubAssembler::SmiAddWithOverflow(Node* a, Node* b) {
+  return IntPtrAddWithOverflow(a, b);
+}
+
+Node* CodeStubAssembler::SmiSub(Node* a, Node* b) { return IntPtrSub(a, b); }
+
+Node* CodeStubAssembler::SmiSubWithOverflow(Node* a, Node* b) {
+  return IntPtrSubWithOverflow(a, b);
+}
+
+Node* CodeStubAssembler::SmiEqual(Node* a, Node* b) { return WordEqual(a, b); }
+
+Node* CodeStubAssembler::SmiAboveOrEqual(Node* a, Node* b) {
+  return UintPtrGreaterThanOrEqual(a, b);
+}
+
+Node* CodeStubAssembler::SmiLessThan(Node* a, Node* b) {
+  return IntPtrLessThan(a, b);
+}
+
+Node* CodeStubAssembler::SmiLessThanOrEqual(Node* a, Node* b) {
+  return IntPtrLessThanOrEqual(a, b);
+}
+
+Node* CodeStubAssembler::SmiMin(Node* a, Node* b) {
+  // TODO(bmeurer): Consider using Select once available.
+  Variable min(this, MachineRepresentation::kTagged);
+  Label if_a(this), if_b(this), join(this);
+  BranchIfSmiLessThan(a, b, &if_a, &if_b);
+  Bind(&if_a);
+  min.Bind(a);
+  Goto(&join);
+  Bind(&if_b);
+  min.Bind(b);
+  Goto(&join);
+  Bind(&join);
+  return min.value();
+}
+
+Node* CodeStubAssembler::WordIsSmi(Node* a) {
+  return WordEqual(WordAnd(a, IntPtrConstant(kSmiTagMask)), IntPtrConstant(0));
+}
+
+Node* CodeStubAssembler::WordIsPositiveSmi(Node* a) {
+  return WordEqual(WordAnd(a, IntPtrConstant(kSmiTagMask | kSmiSignMask)),
+                   IntPtrConstant(0));
+}
+
+Node* CodeStubAssembler::AllocateRawUnaligned(Node* size_in_bytes,
+                                              AllocationFlags flags,
+                                              Node* top_address,
+                                              Node* limit_address) {
+  Node* top = Load(MachineType::Pointer(), top_address);
+  Node* limit = Load(MachineType::Pointer(), limit_address);
+
+  // If there's not enough space, call the runtime.
+  Variable result(this, MachineRepresentation::kTagged);
+  Label runtime_call(this, Label::kDeferred), no_runtime_call(this);
+  Label merge_runtime(this, &result);
+
+  Node* new_top = IntPtrAdd(top, size_in_bytes);
+  Branch(UintPtrGreaterThanOrEqual(new_top, limit), &runtime_call,
+         &no_runtime_call);
+
+  Bind(&runtime_call);
+  // AllocateInTargetSpace does not use the context.
+  Node* context = SmiConstant(Smi::FromInt(0));
+
+  Node* runtime_result;
+  if (flags & kPretenured) {
+    Node* runtime_flags = SmiConstant(
+        Smi::FromInt(AllocateDoubleAlignFlag::encode(false) |
+                     AllocateTargetSpace::encode(AllocationSpace::OLD_SPACE)));
+    runtime_result = CallRuntime(Runtime::kAllocateInTargetSpace, context,
+                                 SmiTag(size_in_bytes), runtime_flags);
+  } else {
+    runtime_result = CallRuntime(Runtime::kAllocateInNewSpace, context,
+                                 SmiTag(size_in_bytes));
+  }
+  result.Bind(runtime_result);
+  Goto(&merge_runtime);
+
+  // When there is enough space, return `top' and bump it up.
+  Bind(&no_runtime_call);
+  Node* no_runtime_result = top;
+  StoreNoWriteBarrier(MachineType::PointerRepresentation(), top_address,
+                      new_top);
+  no_runtime_result = BitcastWordToTagged(
+      IntPtrAdd(no_runtime_result, IntPtrConstant(kHeapObjectTag)));
+  result.Bind(no_runtime_result);
+  Goto(&merge_runtime);
+
+  Bind(&merge_runtime);
+  return result.value();
+}
+
+Node* CodeStubAssembler::AllocateRawAligned(Node* size_in_bytes,
+                                            AllocationFlags flags,
+                                            Node* top_address,
+                                            Node* limit_address) {
+  Node* top = Load(MachineType::Pointer(), top_address);
+  Node* limit = Load(MachineType::Pointer(), limit_address);
+  Variable adjusted_size(this, MachineType::PointerRepresentation());
+  adjusted_size.Bind(size_in_bytes);
+  if (flags & kDoubleAlignment) {
+    // TODO(epertoso): Simd128 alignment.
+    Label aligned(this), not_aligned(this), merge(this, &adjusted_size);
+    Branch(WordAnd(top, IntPtrConstant(kDoubleAlignmentMask)), &not_aligned,
+           &aligned);
+
+    Bind(&not_aligned);
+    Node* not_aligned_size =
+        IntPtrAdd(size_in_bytes, IntPtrConstant(kPointerSize));
+    adjusted_size.Bind(not_aligned_size);
+    Goto(&merge);
+
+    Bind(&aligned);
+    Goto(&merge);
+
+    Bind(&merge);
+  }
+
+  Variable address(this, MachineRepresentation::kTagged);
+  address.Bind(AllocateRawUnaligned(adjusted_size.value(), kNone, top, limit));
+
+  Label needs_filler(this), doesnt_need_filler(this),
+      merge_address(this, &address);
+  Branch(IntPtrEqual(adjusted_size.value(), size_in_bytes), &doesnt_need_filler,
+         &needs_filler);
+
+  Bind(&needs_filler);
+  // Store a filler and increase the address by kPointerSize.
+  // TODO(epertoso): this code assumes that we only align to kDoubleSize. Change
+  // it when Simd128 alignment is supported.
+  StoreNoWriteBarrier(MachineType::PointerRepresentation(), top,
+                      LoadRoot(Heap::kOnePointerFillerMapRootIndex));
+  address.Bind(BitcastWordToTagged(
+      IntPtrAdd(address.value(), IntPtrConstant(kPointerSize))));
+  Goto(&merge_address);
+
+  Bind(&doesnt_need_filler);
+  Goto(&merge_address);
+
+  Bind(&merge_address);
+  // Update the top.
+  StoreNoWriteBarrier(MachineType::PointerRepresentation(), top_address,
+                      IntPtrAdd(top, adjusted_size.value()));
+  return address.value();
+}
+
+Node* CodeStubAssembler::Allocate(Node* size_in_bytes, AllocationFlags flags) {
+  bool const new_space = !(flags & kPretenured);
+  Node* top_address = ExternalConstant(
+      new_space
+          ? ExternalReference::new_space_allocation_top_address(isolate())
+          : ExternalReference::old_space_allocation_top_address(isolate()));
+  Node* limit_address = ExternalConstant(
+      new_space
+          ? ExternalReference::new_space_allocation_limit_address(isolate())
+          : ExternalReference::old_space_allocation_limit_address(isolate()));
+
+#ifdef V8_HOST_ARCH_32_BIT
+  if (flags & kDoubleAlignment) {
+    return AllocateRawAligned(size_in_bytes, flags, top_address, limit_address);
+  }
+#endif
+
+  return AllocateRawUnaligned(size_in_bytes, flags, top_address, limit_address);
+}
+
+Node* CodeStubAssembler::Allocate(int size_in_bytes, AllocationFlags flags) {
+  return CodeStubAssembler::Allocate(IntPtrConstant(size_in_bytes), flags);
+}
+
+Node* CodeStubAssembler::InnerAllocate(Node* previous, Node* offset) {
+  return BitcastWordToTagged(IntPtrAdd(previous, offset));
+}
+
+Node* CodeStubAssembler::InnerAllocate(Node* previous, int offset) {
+  return InnerAllocate(previous, IntPtrConstant(offset));
+}
+
+compiler::Node* CodeStubAssembler::LoadFromFrame(int offset, MachineType rep) {
+  Node* frame_pointer = LoadFramePointer();
+  return Load(rep, frame_pointer, IntPtrConstant(offset));
+}
+
+compiler::Node* CodeStubAssembler::LoadFromParentFrame(int offset,
+                                                       MachineType rep) {
+  Node* frame_pointer = LoadParentFramePointer();
+  return Load(rep, frame_pointer, IntPtrConstant(offset));
+}
+
+Node* CodeStubAssembler::LoadBufferObject(Node* buffer, int offset,
+                                          MachineType rep) {
+  return Load(rep, buffer, IntPtrConstant(offset));
+}
+
+Node* CodeStubAssembler::LoadObjectField(Node* object, int offset,
+                                         MachineType rep) {
+  return Load(rep, object, IntPtrConstant(offset - kHeapObjectTag));
+}
+
+Node* CodeStubAssembler::LoadObjectField(Node* object, Node* offset,
+                                         MachineType rep) {
+  return Load(rep, object, IntPtrSub(offset, IntPtrConstant(kHeapObjectTag)));
+}
+
+Node* CodeStubAssembler::LoadHeapNumberValue(Node* object) {
+  return LoadObjectField(object, HeapNumber::kValueOffset,
+                         MachineType::Float64());
+}
+
+Node* CodeStubAssembler::LoadMap(Node* object) {
+  return LoadObjectField(object, HeapObject::kMapOffset);
+}
+
+Node* CodeStubAssembler::LoadInstanceType(Node* object) {
+  return LoadMapInstanceType(LoadMap(object));
+}
+
+void CodeStubAssembler::AssertInstanceType(Node* object,
+                                           InstanceType instance_type) {
+  Assert(Word32Equal(LoadInstanceType(object), Int32Constant(instance_type)));
+}
+
+Node* CodeStubAssembler::LoadProperties(Node* object) {
+  return LoadObjectField(object, JSObject::kPropertiesOffset);
+}
+
+Node* CodeStubAssembler::LoadElements(Node* object) {
+  return LoadObjectField(object, JSObject::kElementsOffset);
+}
+
+Node* CodeStubAssembler::LoadFixedArrayBaseLength(Node* array) {
+  return LoadObjectField(array, FixedArrayBase::kLengthOffset);
+}
+
+Node* CodeStubAssembler::LoadMapBitField(Node* map) {
+  return LoadObjectField(map, Map::kBitFieldOffset, MachineType::Uint8());
+}
+
+Node* CodeStubAssembler::LoadMapBitField2(Node* map) {
+  return LoadObjectField(map, Map::kBitField2Offset, MachineType::Uint8());
+}
+
+Node* CodeStubAssembler::LoadMapBitField3(Node* map) {
+  return LoadObjectField(map, Map::kBitField3Offset, MachineType::Uint32());
+}
+
+Node* CodeStubAssembler::LoadMapInstanceType(Node* map) {
+  return LoadObjectField(map, Map::kInstanceTypeOffset, MachineType::Uint8());
+}
+
+Node* CodeStubAssembler::LoadMapDescriptors(Node* map) {
+  return LoadObjectField(map, Map::kDescriptorsOffset);
+}
+
+Node* CodeStubAssembler::LoadMapPrototype(Node* map) {
+  return LoadObjectField(map, Map::kPrototypeOffset);
+}
+
+Node* CodeStubAssembler::LoadMapInstanceSize(Node* map) {
+  return LoadObjectField(map, Map::kInstanceSizeOffset, MachineType::Uint8());
+}
+
+Node* CodeStubAssembler::LoadMapInobjectProperties(Node* map) {
+  // See Map::GetInObjectProperties() for details.
+  STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
+  Assert(Int32GreaterThanOrEqual(LoadMapInstanceType(map),
+                                 Int32Constant(FIRST_JS_OBJECT_TYPE)));
+  return LoadObjectField(
+      map, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset,
+      MachineType::Uint8());
+}
+
+Node* CodeStubAssembler::LoadNameHashField(Node* name) {
+  return LoadObjectField(name, Name::kHashFieldOffset, MachineType::Uint32());
+}
+
+Node* CodeStubAssembler::LoadNameHash(Node* name, Label* if_hash_not_computed) {
+  Node* hash_field = LoadNameHashField(name);
+  if (if_hash_not_computed != nullptr) {
+    GotoIf(WordEqual(
+               Word32And(hash_field, Int32Constant(Name::kHashNotComputedMask)),
+               Int32Constant(0)),
+           if_hash_not_computed);
+  }
+  return Word32Shr(hash_field, Int32Constant(Name::kHashShift));
+}
+
+Node* CodeStubAssembler::LoadStringLength(Node* object) {
+  return LoadObjectField(object, String::kLengthOffset);
+}
+
+Node* CodeStubAssembler::LoadJSValueValue(Node* object) {
+  return LoadObjectField(object, JSValue::kValueOffset);
+}
+
+Node* CodeStubAssembler::LoadWeakCellValue(Node* weak_cell, Label* if_cleared) {
+  Node* value = LoadObjectField(weak_cell, WeakCell::kValueOffset);
+  if (if_cleared != nullptr) {
+    GotoIf(WordEqual(value, IntPtrConstant(0)), if_cleared);
+  }
+  return value;
+}
+
+Node* CodeStubAssembler::AllocateUninitializedFixedArray(Node* length) {
+  Node* header_size = IntPtrConstant(FixedArray::kHeaderSize);
+  Node* data_size = WordShl(length, IntPtrConstant(kPointerSizeLog2));
+  Node* total_size = IntPtrAdd(data_size, header_size);
+
+  Node* result = Allocate(total_size, kNone);
+  StoreMapNoWriteBarrier(result, LoadRoot(Heap::kFixedArrayMapRootIndex));
+  StoreObjectFieldNoWriteBarrier(result, FixedArray::kLengthOffset,
+      SmiTag(length));
+
+  return result;
+}
+
+Node* CodeStubAssembler::LoadFixedArrayElement(Node* object, Node* index_node,
+                                               int additional_offset,
+                                               ParameterMode parameter_mode) {
+  int32_t header_size =
+      FixedArray::kHeaderSize + additional_offset - kHeapObjectTag;
+  Node* offset = ElementOffsetFromIndex(index_node, FAST_HOLEY_ELEMENTS,
+                                        parameter_mode, header_size);
+  return Load(MachineType::AnyTagged(), object, offset);
+}
+
+Node* CodeStubAssembler::LoadFixedDoubleArrayElement(
+    Node* object, Node* index_node, MachineType machine_type,
+    int additional_offset, ParameterMode parameter_mode) {
+  int32_t header_size =
+      FixedDoubleArray::kHeaderSize + additional_offset - kHeapObjectTag;
+  Node* offset = ElementOffsetFromIndex(index_node, FAST_HOLEY_DOUBLE_ELEMENTS,
+                                        parameter_mode, header_size);
+  return Load(machine_type, object, offset);
+}
+
+Node* CodeStubAssembler::LoadNativeContext(Node* context) {
+  return LoadFixedArrayElement(context,
+                               Int32Constant(Context::NATIVE_CONTEXT_INDEX));
+}
+
+Node* CodeStubAssembler::LoadJSArrayElementsMap(ElementsKind kind,
+                                                Node* native_context) {
+  return LoadFixedArrayElement(native_context,
+                               Int32Constant(Context::ArrayMapIndex(kind)));
+}
+
+Node* CodeStubAssembler::StoreHeapNumberValue(Node* object, Node* value) {
+  return StoreNoWriteBarrier(
+      MachineRepresentation::kFloat64, object,
+      IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag), value);
+}
+
+Node* CodeStubAssembler::StoreObjectField(
+    Node* object, int offset, Node* value) {
+  return Store(MachineRepresentation::kTagged, object,
+               IntPtrConstant(offset - kHeapObjectTag), value);
+}
+
+Node* CodeStubAssembler::StoreObjectFieldNoWriteBarrier(
+    Node* object, int offset, Node* value, MachineRepresentation rep) {
+  return StoreNoWriteBarrier(rep, object,
+                             IntPtrConstant(offset - kHeapObjectTag), value);
+}
+
+Node* CodeStubAssembler::StoreMapNoWriteBarrier(Node* object, Node* map) {
+  return StoreNoWriteBarrier(
+      MachineRepresentation::kTagged, object,
+      IntPtrConstant(HeapNumber::kMapOffset - kHeapObjectTag), map);
+}
+
+Node* CodeStubAssembler::StoreFixedArrayElement(Node* object, Node* index_node,
+                                                Node* value,
+                                                WriteBarrierMode barrier_mode,
+                                                ParameterMode parameter_mode) {
+  DCHECK(barrier_mode == SKIP_WRITE_BARRIER ||
+         barrier_mode == UPDATE_WRITE_BARRIER);
+  Node* offset =
+      ElementOffsetFromIndex(index_node, FAST_HOLEY_ELEMENTS, parameter_mode,
+                             FixedArray::kHeaderSize - kHeapObjectTag);
+  MachineRepresentation rep = MachineRepresentation::kTagged;
+  if (barrier_mode == SKIP_WRITE_BARRIER) {
+    return StoreNoWriteBarrier(rep, object, offset, value);
+  } else {
+    return Store(rep, object, offset, value);
+  }
+}
+
+Node* CodeStubAssembler::StoreFixedDoubleArrayElement(
+    Node* object, Node* index_node, Node* value, ParameterMode parameter_mode) {
+  Node* offset =
+      ElementOffsetFromIndex(index_node, FAST_DOUBLE_ELEMENTS, parameter_mode,
+                             FixedArray::kHeaderSize - kHeapObjectTag);
+  MachineRepresentation rep = MachineRepresentation::kFloat64;
+  return StoreNoWriteBarrier(rep, object, offset, value);
+}
+
+Node* CodeStubAssembler::AllocateHeapNumber() {
+  Node* result = Allocate(HeapNumber::kSize, kNone);
+  StoreMapNoWriteBarrier(result, HeapNumberMapConstant());
+  return result;
+}
+
+Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value) {
+  Node* result = AllocateHeapNumber();
+  StoreHeapNumberValue(result, value);
+  return result;
+}
+
+Node* CodeStubAssembler::AllocateSeqOneByteString(int length) {
+  Node* result = Allocate(SeqOneByteString::SizeFor(length));
+  StoreMapNoWriteBarrier(result, LoadRoot(Heap::kOneByteStringMapRootIndex));
+  StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset,
+                                 SmiConstant(Smi::FromInt(length)));
+  StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldOffset,
+                                 IntPtrConstant(String::kEmptyHashField),
+                                 MachineRepresentation::kWord32);
+  return result;
+}
+
+Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length) {
+  Variable var_result(this, MachineRepresentation::kTagged);
+
+  // Compute the SeqOneByteString size and check if it fits into new space.
+  Label if_sizeissmall(this), if_notsizeissmall(this, Label::kDeferred),
+      if_join(this);
+  Node* size = WordAnd(
+      IntPtrAdd(
+          IntPtrAdd(length, IntPtrConstant(SeqOneByteString::kHeaderSize)),
+          IntPtrConstant(kObjectAlignmentMask)),
+      IntPtrConstant(~kObjectAlignmentMask));
+  Branch(IntPtrLessThanOrEqual(size,
+                               IntPtrConstant(Page::kMaxRegularHeapObjectSize)),
+         &if_sizeissmall, &if_notsizeissmall);
+
+  Bind(&if_sizeissmall);
+  {
+    // Just allocate the SeqOneByteString in new space.
+    Node* result = Allocate(size);
+    StoreMapNoWriteBarrier(result, LoadRoot(Heap::kOneByteStringMapRootIndex));
+    StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset,
+                                   SmiFromWord(length));
+    StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldOffset,
+                                   IntPtrConstant(String::kEmptyHashField),
+                                   MachineRepresentation::kWord32);
+    var_result.Bind(result);
+    Goto(&if_join);
+  }
+
+  Bind(&if_notsizeissmall);
+  {
+    // We might need to allocate in large object space, go to the runtime.
+    Node* result = CallRuntime(Runtime::kAllocateSeqOneByteString, context,
+                               SmiFromWord(length));
+    var_result.Bind(result);
+    Goto(&if_join);
+  }
+
+  Bind(&if_join);
+  return var_result.value();
+}
+
+Node* CodeStubAssembler::AllocateSeqTwoByteString(int length) {
+  Node* result = Allocate(SeqTwoByteString::SizeFor(length));
+  StoreMapNoWriteBarrier(result, LoadRoot(Heap::kStringMapRootIndex));
+  StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset,
+                                 SmiConstant(Smi::FromInt(length)));
+  StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldOffset,
+                                 IntPtrConstant(String::kEmptyHashField),
+                                 MachineRepresentation::kWord32);
+  return result;
+}
+
+Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length) {
+  Variable var_result(this, MachineRepresentation::kTagged);
+
+  // Compute the SeqTwoByteString size and check if it fits into new space.
+  Label if_sizeissmall(this), if_notsizeissmall(this, Label::kDeferred),
+      if_join(this);
+  Node* size = WordAnd(
+      IntPtrAdd(IntPtrAdd(WordShl(length, 1),
+                          IntPtrConstant(SeqTwoByteString::kHeaderSize)),
+                IntPtrConstant(kObjectAlignmentMask)),
+      IntPtrConstant(~kObjectAlignmentMask));
+  Branch(IntPtrLessThanOrEqual(size,
+                               IntPtrConstant(Page::kMaxRegularHeapObjectSize)),
+         &if_sizeissmall, &if_notsizeissmall);
+
+  Bind(&if_sizeissmall);
+  {
+    // Just allocate the SeqTwoByteString in new space.
+    Node* result = Allocate(size);
+    StoreMapNoWriteBarrier(result, LoadRoot(Heap::kStringMapRootIndex));
+    StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset,
+                                   SmiFromWord(length));
+    StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldOffset,
+                                   IntPtrConstant(String::kEmptyHashField),
+                                   MachineRepresentation::kWord32);
+    var_result.Bind(result);
+    Goto(&if_join);
+  }
+
+  Bind(&if_notsizeissmall);
+  {
+    // We might need to allocate in large object space, go to the runtime.
+    Node* result = CallRuntime(Runtime::kAllocateSeqTwoByteString, context,
+                               SmiFromWord(length));
+    var_result.Bind(result);
+    Goto(&if_join);
+  }
+
+  Bind(&if_join);
+  return var_result.value();
+}
+
+Node* CodeStubAssembler::AllocateJSArray(ElementsKind kind, Node* array_map,
+                                         Node* capacity_node, Node* length_node,
+                                         compiler::Node* allocation_site,
+                                         ParameterMode mode) {
+  bool is_double = IsFastDoubleElementsKind(kind);
+  int base_size = JSArray::kSize + FixedArray::kHeaderSize;
+  int elements_offset = JSArray::kSize;
+
+  Comment("begin allocation of JSArray");
+
+  if (allocation_site != nullptr) {
+    base_size += AllocationMemento::kSize;
+    elements_offset += AllocationMemento::kSize;
+  }
+
+  int32_t capacity;
+  bool constant_capacity = ToInt32Constant(capacity_node, capacity);
+  Node* total_size =
+      ElementOffsetFromIndex(capacity_node, kind, mode, base_size);
+
+  // Allocate both array and elements object, and initialize the JSArray.
+  Heap* heap = isolate()->heap();
+  Node* array = Allocate(total_size);
+  StoreMapNoWriteBarrier(array, array_map);
+  Node* empty_properties =
+      HeapConstant(Handle<HeapObject>(heap->empty_fixed_array()));
+  StoreObjectFieldNoWriteBarrier(array, JSArray::kPropertiesOffset,
+                                 empty_properties);
+  StoreObjectFieldNoWriteBarrier(
+      array, JSArray::kLengthOffset,
+      mode == SMI_PARAMETERS ? length_node : SmiTag(length_node));
+
+  if (allocation_site != nullptr) {
+    InitializeAllocationMemento(array, JSArray::kSize, allocation_site);
+  }
+
+  // Setup elements object.
+  Node* elements = InnerAllocate(array, elements_offset);
+  StoreObjectFieldNoWriteBarrier(array, JSArray::kElementsOffset, elements);
+  Handle<Map> elements_map(is_double ? heap->fixed_double_array_map()
+                                     : heap->fixed_array_map());
+  StoreMapNoWriteBarrier(elements, HeapConstant(elements_map));
+  StoreObjectFieldNoWriteBarrier(
+      elements, FixedArray::kLengthOffset,
+      mode == SMI_PARAMETERS ? capacity_node : SmiTag(capacity_node));
+
+  int const first_element_offset = FixedArray::kHeaderSize - kHeapObjectTag;
+  Node* hole = HeapConstant(Handle<HeapObject>(heap->the_hole_value()));
+  Node* double_hole =
+      Is64() ? Int64Constant(kHoleNanInt64) : Int32Constant(kHoleNanLower32);
+  DCHECK_EQ(kHoleNanLower32, kHoleNanUpper32);
+  if (constant_capacity && capacity <= kElementLoopUnrollThreshold) {
+    for (int i = 0; i < capacity; ++i) {
+      if (is_double) {
+        Node* offset = ElementOffsetFromIndex(Int32Constant(i), kind, mode,
+                                              first_element_offset);
+        // Don't use doubles to store the hole double, since manipulating the
+        // signaling NaN used for the hole in C++, e.g. with bit_cast, will
+        // change its value on ia32 (the x87 stack is used to return values
+        // and stores to the stack silently clear the signalling bit).
+        //
+        // TODO(danno): When we have a Float32/Float64 wrapper class that
+        // preserves double bits during manipulation, remove this code/change
+        // this to an indexed Float64 store.
+        if (Is64()) {
+          StoreNoWriteBarrier(MachineRepresentation::kWord64, elements, offset,
+                              double_hole);
+        } else {
+          StoreNoWriteBarrier(MachineRepresentation::kWord32, elements, offset,
+                              double_hole);
+          offset = ElementOffsetFromIndex(Int32Constant(i), kind, mode,
+                                          first_element_offset + kPointerSize);
+          StoreNoWriteBarrier(MachineRepresentation::kWord32, elements, offset,
+                              double_hole);
+        }
+      } else {
+        StoreFixedArrayElement(elements, Int32Constant(i), hole,
+                               SKIP_WRITE_BARRIER);
+      }
+    }
+  } else {
+    Variable current(this, MachineRepresentation::kTagged);
+    Label test(this);
+    Label decrement(this, &current);
+    Label done(this);
+    Node* limit = IntPtrAdd(elements, IntPtrConstant(first_element_offset));
+    current.Bind(
+        IntPtrAdd(limit, ElementOffsetFromIndex(capacity_node, kind, mode, 0)));
+
+    Branch(WordEqual(current.value(), limit), &done, &decrement);
+
+    Bind(&decrement);
+    current.Bind(IntPtrSub(
+        current.value(),
+        Int32Constant(IsFastDoubleElementsKind(kind) ? kDoubleSize
+                                                     : kPointerSize)));
+    if (is_double) {
+      // Don't use doubles to store the hole double, since manipulating the
+      // signaling NaN used for the hole in C++, e.g. with bit_cast, will
+      // change its value on ia32 (the x87 stack is used to return values
+      // and stores to the stack silently clear the signalling bit).
+      //
+      // TODO(danno): When we have a Float32/Float64 wrapper class that
+      // preserves double bits during manipulation, remove this code/change
+      // this to an indexed Float64 store.
+      if (Is64()) {
+        StoreNoWriteBarrier(MachineRepresentation::kWord64, current.value(),
+                            double_hole);
+      } else {
+        StoreNoWriteBarrier(MachineRepresentation::kWord32, current.value(),
+                            double_hole);
+        StoreNoWriteBarrier(
+            MachineRepresentation::kWord32,
+            IntPtrAdd(current.value(), Int32Constant(kPointerSize)),
+            double_hole);
+      }
+    } else {
+      StoreNoWriteBarrier(MachineRepresentation::kTagged, current.value(),
+                          hole);
+    }
+    Node* compare = WordNotEqual(current.value(), limit);
+    Branch(compare, &decrement, &done);
+
+    Bind(&done);
+  }
+
+  return array;
+}
+
+void CodeStubAssembler::InitializeAllocationMemento(
+    compiler::Node* base_allocation, int base_allocation_size,
+    compiler::Node* allocation_site) {
+  StoreObjectFieldNoWriteBarrier(
+      base_allocation, AllocationMemento::kMapOffset + base_allocation_size,
+      HeapConstant(Handle<Map>(isolate()->heap()->allocation_memento_map())));
+  StoreObjectFieldNoWriteBarrier(
+      base_allocation,
+      AllocationMemento::kAllocationSiteOffset + base_allocation_size,
+      allocation_site);
+  if (FLAG_allocation_site_pretenuring) {
+    Node* count = LoadObjectField(allocation_site,
+                                  AllocationSite::kPretenureCreateCountOffset);
+    Node* incremented_count = IntPtrAdd(count, SmiConstant(Smi::FromInt(1)));
+    StoreObjectFieldNoWriteBarrier(allocation_site,
+                                   AllocationSite::kPretenureCreateCountOffset,
+                                   incremented_count);
+  }
+}
+
+Node* CodeStubAssembler::TruncateTaggedToFloat64(Node* context, Node* value) {
+  // We might need to loop once due to ToNumber conversion.
+  Variable var_value(this, MachineRepresentation::kTagged),
+      var_result(this, MachineRepresentation::kFloat64);
+  Label loop(this, &var_value), done_loop(this, &var_result);
+  var_value.Bind(value);
+  Goto(&loop);
+  Bind(&loop);
+  {
+    // Load the current {value}.
+    value = var_value.value();
+
+    // Check if the {value} is a Smi or a HeapObject.
+    Label if_valueissmi(this), if_valueisnotsmi(this);
+    Branch(WordIsSmi(value), &if_valueissmi, &if_valueisnotsmi);
+
+    Bind(&if_valueissmi);
+    {
+      // Convert the Smi {value}.
+      var_result.Bind(SmiToFloat64(value));
+      Goto(&done_loop);
+    }
+
+    Bind(&if_valueisnotsmi);
+    {
+      // Check if {value} is a HeapNumber.
+      Label if_valueisheapnumber(this),
+          if_valueisnotheapnumber(this, Label::kDeferred);
+      Branch(WordEqual(LoadMap(value), HeapNumberMapConstant()),
+             &if_valueisheapnumber, &if_valueisnotheapnumber);
+
+      Bind(&if_valueisheapnumber);
+      {
+        // Load the floating point value.
+        var_result.Bind(LoadHeapNumberValue(value));
+        Goto(&done_loop);
+      }
+
+      Bind(&if_valueisnotheapnumber);
+      {
+        // Convert the {value} to a Number first.
+        Callable callable = CodeFactory::NonNumberToNumber(isolate());
+        var_value.Bind(CallStub(callable, context, value));
+        Goto(&loop);
+      }
+    }
+  }
+  Bind(&done_loop);
+  return var_result.value();
+}
+
+Node* CodeStubAssembler::TruncateTaggedToWord32(Node* context, Node* value) {
+  // We might need to loop once due to ToNumber conversion.
+  Variable var_value(this, MachineRepresentation::kTagged),
+      var_result(this, MachineRepresentation::kWord32);
+  Label loop(this, &var_value), done_loop(this, &var_result);
+  var_value.Bind(value);
+  Goto(&loop);
+  Bind(&loop);
+  {
+    // Load the current {value}.
+    value = var_value.value();
+
+    // Check if the {value} is a Smi or a HeapObject.
+    Label if_valueissmi(this), if_valueisnotsmi(this);
+    Branch(WordIsSmi(value), &if_valueissmi, &if_valueisnotsmi);
+
+    Bind(&if_valueissmi);
+    {
+      // Convert the Smi {value}.
+      var_result.Bind(SmiToWord32(value));
+      Goto(&done_loop);
+    }
+
+    Bind(&if_valueisnotsmi);
+    {
+      // Check if {value} is a HeapNumber.
+      Label if_valueisheapnumber(this),
+          if_valueisnotheapnumber(this, Label::kDeferred);
+      Branch(WordEqual(LoadMap(value), HeapNumberMapConstant()),
+             &if_valueisheapnumber, &if_valueisnotheapnumber);
+
+      Bind(&if_valueisheapnumber);
+      {
+        // Truncate the floating point value.
+        var_result.Bind(TruncateHeapNumberValueToWord32(value));
+        Goto(&done_loop);
+      }
+
+      Bind(&if_valueisnotheapnumber);
+      {
+        // Convert the {value} to a Number first.
+        Callable callable = CodeFactory::NonNumberToNumber(isolate());
+        var_value.Bind(CallStub(callable, context, value));
+        Goto(&loop);
+      }
+    }
+  }
+  Bind(&done_loop);
+  return var_result.value();
+}
+
+Node* CodeStubAssembler::TruncateHeapNumberValueToWord32(Node* object) {
+  Node* value = LoadHeapNumberValue(object);
+  return TruncateFloat64ToWord32(value);
+}
+
+Node* CodeStubAssembler::ChangeFloat64ToTagged(Node* value) {
+  Node* value32 = RoundFloat64ToInt32(value);
+  Node* value64 = ChangeInt32ToFloat64(value32);
+
+  Label if_valueisint32(this), if_valueisheapnumber(this), if_join(this);
+
+  Label if_valueisequal(this), if_valueisnotequal(this);
+  Branch(Float64Equal(value, value64), &if_valueisequal, &if_valueisnotequal);
+  Bind(&if_valueisequal);
+  {
+    GotoUnless(Word32Equal(value32, Int32Constant(0)), &if_valueisint32);
+    BranchIfInt32LessThan(Float64ExtractHighWord32(value), Int32Constant(0),
+                          &if_valueisheapnumber, &if_valueisint32);
+  }
+  Bind(&if_valueisnotequal);
+  Goto(&if_valueisheapnumber);
+
+  Variable var_result(this, MachineRepresentation::kTagged);
+  Bind(&if_valueisint32);
+  {
+    if (Is64()) {
+      Node* result = SmiTag(ChangeInt32ToInt64(value32));
+      var_result.Bind(result);
+      Goto(&if_join);
+    } else {
+      Node* pair = Int32AddWithOverflow(value32, value32);
+      Node* overflow = Projection(1, pair);
+      Label if_overflow(this, Label::kDeferred), if_notoverflow(this);
+      Branch(overflow, &if_overflow, &if_notoverflow);
+      Bind(&if_overflow);
+      Goto(&if_valueisheapnumber);
+      Bind(&if_notoverflow);
+      {
+        Node* result = Projection(0, pair);
+        var_result.Bind(result);
+        Goto(&if_join);
+      }
+    }
+  }
+  Bind(&if_valueisheapnumber);
+  {
+    Node* result = AllocateHeapNumberWithValue(value);
+    var_result.Bind(result);
+    Goto(&if_join);
+  }
+  Bind(&if_join);
+  return var_result.value();
+}
+
+Node* CodeStubAssembler::ChangeInt32ToTagged(Node* value) {
+  if (Is64()) {
+    return SmiTag(ChangeInt32ToInt64(value));
+  }
+  Variable var_result(this, MachineRepresentation::kTagged);
+  Node* pair = Int32AddWithOverflow(value, value);
+  Node* overflow = Projection(1, pair);
+  Label if_overflow(this, Label::kDeferred), if_notoverflow(this),
+      if_join(this);
+  Branch(overflow, &if_overflow, &if_notoverflow);
+  Bind(&if_overflow);
+  {
+    Node* value64 = ChangeInt32ToFloat64(value);
+    Node* result = AllocateHeapNumberWithValue(value64);
+    var_result.Bind(result);
+  }
+  Goto(&if_join);
+  Bind(&if_notoverflow);
+  {
+    Node* result = Projection(0, pair);
+    var_result.Bind(result);
+  }
+  Goto(&if_join);
+  Bind(&if_join);
+  return var_result.value();
+}
+
+Node* CodeStubAssembler::ChangeUint32ToTagged(Node* value) {
+  Label if_overflow(this, Label::kDeferred), if_not_overflow(this),
+      if_join(this);
+  Variable var_result(this, MachineRepresentation::kTagged);
+  // If {value} > 2^31 - 1, we need to store it in a HeapNumber.
+  Branch(Int32LessThan(value, Int32Constant(0)), &if_overflow,
+         &if_not_overflow);
+  Bind(&if_not_overflow);
+  {
+    if (Is64()) {
+      var_result.Bind(SmiTag(ChangeUint32ToUint64(value)));
+    } else {
+      // If tagging {value} results in an overflow, we need to use a HeapNumber
+      // to represent it.
+      Node* pair = Int32AddWithOverflow(value, value);
+      Node* overflow = Projection(1, pair);
+      GotoIf(overflow, &if_overflow);
+
+      Node* result = Projection(0, pair);
+      var_result.Bind(result);
+    }
+  }
+  Goto(&if_join);
+
+  Bind(&if_overflow);
+  {
+    Node* float64_value = ChangeUint32ToFloat64(value);
+    var_result.Bind(AllocateHeapNumberWithValue(float64_value));
+  }
+  Goto(&if_join);
+
+  Bind(&if_join);
+  return var_result.value();
+}
+
+Node* CodeStubAssembler::ToThisString(Node* context, Node* value,
+                                      char const* method_name) {
+  Variable var_value(this, MachineRepresentation::kTagged);
+  var_value.Bind(value);
+
+  // Check if the {value} is a Smi or a HeapObject.
+  Label if_valueissmi(this, Label::kDeferred), if_valueisnotsmi(this),
+      if_valueisstring(this);
+  Branch(WordIsSmi(value), &if_valueissmi, &if_valueisnotsmi);
+  Bind(&if_valueisnotsmi);
+  {
+    // Load the instance type of the {value}.
+    Node* value_instance_type = LoadInstanceType(value);
+
+    // Check if the {value} is already String.
+    Label if_valueisnotstring(this, Label::kDeferred);
+    Branch(
+        Int32LessThan(value_instance_type, Int32Constant(FIRST_NONSTRING_TYPE)),
+        &if_valueisstring, &if_valueisnotstring);
+    Bind(&if_valueisnotstring);
+    {
+      // Check if the {value} is null.
+      Label if_valueisnullorundefined(this, Label::kDeferred),
+          if_valueisnotnullorundefined(this, Label::kDeferred),
+          if_valueisnotnull(this, Label::kDeferred);
+      Branch(WordEqual(value, NullConstant()), &if_valueisnullorundefined,
+             &if_valueisnotnull);
+      Bind(&if_valueisnotnull);
+      {
+        // Check if the {value} is undefined.
+        Branch(WordEqual(value, UndefinedConstant()),
+               &if_valueisnullorundefined, &if_valueisnotnullorundefined);
+        Bind(&if_valueisnotnullorundefined);
+        {
+          // Convert the {value} to a String.
+          Callable callable = CodeFactory::ToString(isolate());
+          var_value.Bind(CallStub(callable, context, value));
+          Goto(&if_valueisstring);
+        }
+      }
+
+      Bind(&if_valueisnullorundefined);
+      {
+        // The {value} is either null or undefined.
+        CallRuntime(Runtime::kThrowCalledOnNullOrUndefined, context,
+                    HeapConstant(factory()->NewStringFromAsciiChecked(
+                        method_name, TENURED)));
+        Goto(&if_valueisstring);  // Never reached.
+      }
+    }
+  }
+  Bind(&if_valueissmi);
+  {
+    // The {value} is a Smi, convert it to a String.
+    Callable callable = CodeFactory::NumberToString(isolate());
+    var_value.Bind(CallStub(callable, context, value));
+    Goto(&if_valueisstring);
+  }
+  Bind(&if_valueisstring);
+  return var_value.value();
+}
+
+Node* CodeStubAssembler::StringCharCodeAt(Node* string, Node* index) {
+  // Translate the {index} into a Word.
+  index = SmiToWord(index);
+
+  // We may need to loop in case of cons or sliced strings.
+  Variable var_index(this, MachineType::PointerRepresentation());
+  Variable var_result(this, MachineRepresentation::kWord32);
+  Variable var_string(this, MachineRepresentation::kTagged);
+  Variable* loop_vars[] = {&var_index, &var_string};
+  Label done_loop(this, &var_result), loop(this, 2, loop_vars);
+  var_string.Bind(string);
+  var_index.Bind(index);
+  Goto(&loop);
+  Bind(&loop);
+  {
+    // Load the current {index}.
+    index = var_index.value();
+
+    // Load the current {string}.
+    string = var_string.value();
+
+    // Load the instance type of the {string}.
+    Node* string_instance_type = LoadInstanceType(string);
+
+    // Check if the {string} is a SeqString.
+    Label if_stringissequential(this), if_stringisnotsequential(this);
+    Branch(Word32Equal(Word32And(string_instance_type,
+                                 Int32Constant(kStringRepresentationMask)),
+                       Int32Constant(kSeqStringTag)),
+           &if_stringissequential, &if_stringisnotsequential);
+
+    Bind(&if_stringissequential);
+    {
+      // Check if the {string} is a TwoByteSeqString or a OneByteSeqString.
+      Label if_stringistwobyte(this), if_stringisonebyte(this);
+      Branch(Word32Equal(Word32And(string_instance_type,
+                                   Int32Constant(kStringEncodingMask)),
+                         Int32Constant(kTwoByteStringTag)),
+             &if_stringistwobyte, &if_stringisonebyte);
+
+      Bind(&if_stringisonebyte);
+      {
+        var_result.Bind(
+            Load(MachineType::Uint8(), string,
+                 IntPtrAdd(index, IntPtrConstant(SeqOneByteString::kHeaderSize -
+                                                 kHeapObjectTag))));
+        Goto(&done_loop);
+      }
+
+      Bind(&if_stringistwobyte);
+      {
+        var_result.Bind(
+            Load(MachineType::Uint16(), string,
+                 IntPtrAdd(WordShl(index, IntPtrConstant(1)),
+                           IntPtrConstant(SeqTwoByteString::kHeaderSize -
+                                          kHeapObjectTag))));
+        Goto(&done_loop);
+      }
+    }
+
+    Bind(&if_stringisnotsequential);
+    {
+      // Check if the {string} is a ConsString.
+      Label if_stringiscons(this), if_stringisnotcons(this);
+      Branch(Word32Equal(Word32And(string_instance_type,
+                                   Int32Constant(kStringRepresentationMask)),
+                         Int32Constant(kConsStringTag)),
+             &if_stringiscons, &if_stringisnotcons);
+
+      Bind(&if_stringiscons);
+      {
+        // Check whether the right hand side is the empty string (i.e. if
+        // this is really a flat string in a cons string). If that is not
+        // the case we flatten the string first.
+        Label if_rhsisempty(this), if_rhsisnotempty(this, Label::kDeferred);
+        Node* rhs = LoadObjectField(string, ConsString::kSecondOffset);
+        Branch(WordEqual(rhs, EmptyStringConstant()), &if_rhsisempty,
+               &if_rhsisnotempty);
+
+        Bind(&if_rhsisempty);
+        {
+          // Just operate on the left hand side of the {string}.
+          var_string.Bind(LoadObjectField(string, ConsString::kFirstOffset));
+          Goto(&loop);
+        }
+
+        Bind(&if_rhsisnotempty);
+        {
+          // Flatten the {string} and lookup in the resulting string.
+          var_string.Bind(CallRuntime(Runtime::kFlattenString,
+                                      NoContextConstant(), string));
+          Goto(&loop);
+        }
+      }
+
+      Bind(&if_stringisnotcons);
+      {
+        // Check if the {string} is an ExternalString.
+        Label if_stringisexternal(this), if_stringisnotexternal(this);
+        Branch(Word32Equal(Word32And(string_instance_type,
+                                     Int32Constant(kStringRepresentationMask)),
+                           Int32Constant(kExternalStringTag)),
+               &if_stringisexternal, &if_stringisnotexternal);
+
+        Bind(&if_stringisexternal);
+        {
+          // Check if the {string} is a short external string.
+          Label if_stringisshort(this),
+              if_stringisnotshort(this, Label::kDeferred);
+          Branch(Word32Equal(Word32And(string_instance_type,
+                                       Int32Constant(kShortExternalStringMask)),
+                             Int32Constant(0)),
+                 &if_stringisshort, &if_stringisnotshort);
+
+          Bind(&if_stringisshort);
+          {
+            // Load the actual resource data from the {string}.
+            Node* string_resource_data =
+                LoadObjectField(string, ExternalString::kResourceDataOffset,
+                                MachineType::Pointer());
+
+            // Check if the {string} is a TwoByteExternalString or a
+            // OneByteExternalString.
+            Label if_stringistwobyte(this), if_stringisonebyte(this);
+            Branch(Word32Equal(Word32And(string_instance_type,
+                                         Int32Constant(kStringEncodingMask)),
+                               Int32Constant(kTwoByteStringTag)),
+                   &if_stringistwobyte, &if_stringisonebyte);
+
+            Bind(&if_stringisonebyte);
+            {
+              var_result.Bind(
+                  Load(MachineType::Uint8(), string_resource_data, index));
+              Goto(&done_loop);
+            }
+
+            Bind(&if_stringistwobyte);
+            {
+              var_result.Bind(Load(MachineType::Uint16(), string_resource_data,
+                                   WordShl(index, IntPtrConstant(1))));
+              Goto(&done_loop);
+            }
+          }
+
+          Bind(&if_stringisnotshort);
+          {
+            // The {string} might be compressed, call the runtime.
+            var_result.Bind(SmiToWord32(
+                CallRuntime(Runtime::kExternalStringGetChar,
+                            NoContextConstant(), string, SmiTag(index))));
+            Goto(&done_loop);
+          }
+        }
+
+        Bind(&if_stringisnotexternal);
+        {
+          // The {string} is a SlicedString, continue with its parent.
+          Node* string_offset =
+              SmiToWord(LoadObjectField(string, SlicedString::kOffsetOffset));
+          Node* string_parent =
+              LoadObjectField(string, SlicedString::kParentOffset);
+          var_index.Bind(IntPtrAdd(index, string_offset));
+          var_string.Bind(string_parent);
+          Goto(&loop);
+        }
+      }
+    }
+  }
+
+  Bind(&done_loop);
+  return var_result.value();
+}
+
+Node* CodeStubAssembler::StringFromCharCode(Node* code) {
+  Variable var_result(this, MachineRepresentation::kTagged);
+
+  // Check if the {code} is a one-byte char code.
+  Label if_codeisonebyte(this), if_codeistwobyte(this, Label::kDeferred),
+      if_done(this);
+  Branch(Int32LessThanOrEqual(code, Int32Constant(String::kMaxOneByteCharCode)),
+         &if_codeisonebyte, &if_codeistwobyte);
+  Bind(&if_codeisonebyte);
+  {
+    // Load the isolate wide single character string cache.
+    Node* cache = LoadRoot(Heap::kSingleCharacterStringCacheRootIndex);
+
+    // Check if we have an entry for the {code} in the single character string
+    // cache already.
+    Label if_entryisundefined(this, Label::kDeferred),
+        if_entryisnotundefined(this);
+    Node* entry = LoadFixedArrayElement(cache, code);
+    Branch(WordEqual(entry, UndefinedConstant()), &if_entryisundefined,
+           &if_entryisnotundefined);
+
+    Bind(&if_entryisundefined);
+    {
+      // Allocate a new SeqOneByteString for {code} and store it in the {cache}.
+      Node* result = AllocateSeqOneByteString(1);
+      StoreNoWriteBarrier(
+          MachineRepresentation::kWord8, result,
+          IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag), code);
+      StoreFixedArrayElement(cache, code, result);
+      var_result.Bind(result);
+      Goto(&if_done);
+    }
+
+    Bind(&if_entryisnotundefined);
+    {
+      // Return the entry from the {cache}.
+      var_result.Bind(entry);
+      Goto(&if_done);
+    }
+  }
+
+  Bind(&if_codeistwobyte);
+  {
+    // Allocate a new SeqTwoByteString for {code}.
+    Node* result = AllocateSeqTwoByteString(1);
+    StoreNoWriteBarrier(
+        MachineRepresentation::kWord16, result,
+        IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), code);
+    var_result.Bind(result);
+    Goto(&if_done);
+  }
+
+  Bind(&if_done);
+  return var_result.value();
+}
+
+Node* CodeStubAssembler::BitFieldDecode(Node* word32, uint32_t shift,
+                                        uint32_t mask) {
+  return Word32Shr(Word32And(word32, Int32Constant(mask)),
+                   Int32Constant(shift));
+}
+
+void CodeStubAssembler::SetCounter(StatsCounter* counter, int value) {
+  if (FLAG_native_code_counters && counter->Enabled()) {
+    Node* counter_address = ExternalConstant(ExternalReference(counter));
+    StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address,
+                        Int32Constant(value));
+  }
+}
+
+void CodeStubAssembler::IncrementCounter(StatsCounter* counter, int delta) {
+  DCHECK(delta > 0);
+  if (FLAG_native_code_counters && counter->Enabled()) {
+    Node* counter_address = ExternalConstant(ExternalReference(counter));
+    Node* value = Load(MachineType::Int32(), counter_address);
+    value = Int32Add(value, Int32Constant(delta));
+    StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address, value);
+  }
+}
+
+void CodeStubAssembler::DecrementCounter(StatsCounter* counter, int delta) {
+  DCHECK(delta > 0);
+  if (FLAG_native_code_counters && counter->Enabled()) {
+    Node* counter_address = ExternalConstant(ExternalReference(counter));
+    Node* value = Load(MachineType::Int32(), counter_address);
+    value = Int32Sub(value, Int32Constant(delta));
+    StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address, value);
+  }
+}
+
+void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex,
+                                  Variable* var_index, Label* if_keyisunique,
+                                  Label* if_bailout) {
+  DCHECK_EQ(MachineRepresentation::kWord32, var_index->rep());
+  Comment("TryToName");
+
+  Label if_keyissmi(this), if_keyisnotsmi(this);
+  Branch(WordIsSmi(key), &if_keyissmi, &if_keyisnotsmi);
+  Bind(&if_keyissmi);
+  {
+    // Negative smi keys are named properties. Handle in the runtime.
+    GotoUnless(WordIsPositiveSmi(key), if_bailout);
+
+    var_index->Bind(SmiToWord32(key));
+    Goto(if_keyisindex);
+  }
+
+  Bind(&if_keyisnotsmi);
+
+  Node* key_instance_type = LoadInstanceType(key);
+  // Symbols are unique.
+  GotoIf(Word32Equal(key_instance_type, Int32Constant(SYMBOL_TYPE)),
+         if_keyisunique);
+
+  Label if_keyisinternalized(this);
+  Node* bits =
+      WordAnd(key_instance_type,
+              Int32Constant(kIsNotStringMask | kIsNotInternalizedMask));
+  Branch(Word32Equal(bits, Int32Constant(kStringTag | kInternalizedTag)),
+         &if_keyisinternalized, if_bailout);
+  Bind(&if_keyisinternalized);
+
+  // Check whether the key is an array index passed in as string. Handle
+  // uniform with smi keys if so.
+  // TODO(verwaest): Also support non-internalized strings.
+  Node* hash = LoadNameHashField(key);
+  Node* bit = Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask));
+  GotoIf(Word32NotEqual(bit, Int32Constant(0)), if_keyisunique);
+  // Key is an index. Check if it is small enough to be encoded in the
+  // hash_field. Handle too big array index in runtime.
+  bit = Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask));
+  GotoIf(Word32NotEqual(bit, Int32Constant(0)), if_bailout);
+  var_index->Bind(BitFieldDecode<Name::ArrayIndexValueBits>(hash));
+  Goto(if_keyisindex);
+}
+
+template <typename Dictionary>
+Node* CodeStubAssembler::EntryToIndex(Node* entry, int field_index) {
+  Node* entry_index = Int32Mul(entry, Int32Constant(Dictionary::kEntrySize));
+  return Int32Add(entry_index,
+                  Int32Constant(Dictionary::kElementsStartIndex + field_index));
+}
+
+template <typename Dictionary>
+void CodeStubAssembler::NameDictionaryLookup(Node* dictionary,
+                                             Node* unique_name, Label* if_found,
+                                             Variable* var_name_index,
+                                             Label* if_not_found,
+                                             int inlined_probes) {
+  DCHECK_EQ(MachineRepresentation::kWord32, var_name_index->rep());
+  Comment("NameDictionaryLookup");
+
+  Node* capacity = SmiToWord32(LoadFixedArrayElement(
+      dictionary, Int32Constant(Dictionary::kCapacityIndex)));
+  Node* mask = Int32Sub(capacity, Int32Constant(1));
+  Node* hash = LoadNameHash(unique_name);
+
+  // See Dictionary::FirstProbe().
+  Node* count = Int32Constant(0);
+  Node* entry = Word32And(hash, mask);
+
+  for (int i = 0; i < inlined_probes; i++) {
+    Node* index = EntryToIndex<Dictionary>(entry);
+    var_name_index->Bind(index);
+
+    Node* current = LoadFixedArrayElement(dictionary, index);
+    GotoIf(WordEqual(current, unique_name), if_found);
+
+    // See Dictionary::NextProbe().
+    count = Int32Constant(i + 1);
+    entry = Word32And(Int32Add(entry, count), mask);
+  }
+
+  Node* undefined = UndefinedConstant();
+
+  Variable var_count(this, MachineRepresentation::kWord32);
+  Variable var_entry(this, MachineRepresentation::kWord32);
+  Variable* loop_vars[] = {&var_count, &var_entry, var_name_index};
+  Label loop(this, 3, loop_vars);
+  var_count.Bind(count);
+  var_entry.Bind(entry);
+  Goto(&loop);
+  Bind(&loop);
+  {
+    Node* count = var_count.value();
+    Node* entry = var_entry.value();
+
+    Node* index = EntryToIndex<Dictionary>(entry);
+    var_name_index->Bind(index);
+
+    Node* current = LoadFixedArrayElement(dictionary, index);
+    GotoIf(WordEqual(current, undefined), if_not_found);
+    GotoIf(WordEqual(current, unique_name), if_found);
+
+    // See Dictionary::NextProbe().
+    count = Int32Add(count, Int32Constant(1));
+    entry = Word32And(Int32Add(entry, count), mask);
+
+    var_count.Bind(count);
+    var_entry.Bind(entry);
+    Goto(&loop);
+  }
+}
+
+// Instantiate template methods to workaround GCC compilation issue.
+template void CodeStubAssembler::NameDictionaryLookup<NameDictionary>(
+    Node*, Node*, Label*, Variable*, Label*, int);
+template void CodeStubAssembler::NameDictionaryLookup<GlobalDictionary>(
+    Node*, Node*, Label*, Variable*, Label*, int);
+
+Node* CodeStubAssembler::ComputeIntegerHash(Node* key, Node* seed) {
+  // See v8::internal::ComputeIntegerHash()
+  Node* hash = key;
+  hash = Word32Xor(hash, seed);
+  hash = Int32Add(Word32Xor(hash, Int32Constant(0xffffffff)),
+                  Word32Shl(hash, Int32Constant(15)));
+  hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(12)));
+  hash = Int32Add(hash, Word32Shl(hash, Int32Constant(2)));
+  hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(4)));
+  hash = Int32Mul(hash, Int32Constant(2057));
+  hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(16)));
+  return Word32And(hash, Int32Constant(0x3fffffff));
+}
+
+template <typename Dictionary>
+void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, Node* key,
+                                               Label* if_found,
+                                               Variable* var_entry,
+                                               Label* if_not_found) {
+  DCHECK_EQ(MachineRepresentation::kWord32, var_entry->rep());
+  Comment("NumberDictionaryLookup");
+
+  Node* capacity = SmiToWord32(LoadFixedArrayElement(
+      dictionary, Int32Constant(Dictionary::kCapacityIndex)));
+  Node* mask = Int32Sub(capacity, Int32Constant(1));
+
+  Node* seed;
+  if (Dictionary::ShapeT::UsesSeed) {
+    seed = HashSeed();
+  } else {
+    seed = Int32Constant(kZeroHashSeed);
+  }
+  Node* hash = ComputeIntegerHash(key, seed);
+  Node* key_as_float64 = ChangeUint32ToFloat64(key);
+
+  // See Dictionary::FirstProbe().
+  Node* count = Int32Constant(0);
+  Node* entry = Word32And(hash, mask);
+
+  Node* undefined = UndefinedConstant();
+  Node* the_hole = TheHoleConstant();
+
+  Variable var_count(this, MachineRepresentation::kWord32);
+  Variable* loop_vars[] = {&var_count, var_entry};
+  Label loop(this, 2, loop_vars);
+  var_count.Bind(count);
+  var_entry->Bind(entry);
+  Goto(&loop);
+  Bind(&loop);
+  {
+    Node* count = var_count.value();
+    Node* entry = var_entry->value();
+
+    Node* index = EntryToIndex<Dictionary>(entry);
+    Node* current = LoadFixedArrayElement(dictionary, index);
+    GotoIf(WordEqual(current, undefined), if_not_found);
+    Label next_probe(this);
+    {
+      Label if_currentissmi(this), if_currentisnotsmi(this);
+      Branch(WordIsSmi(current), &if_currentissmi, &if_currentisnotsmi);
+      Bind(&if_currentissmi);
+      {
+        Node* current_value = SmiToWord32(current);
+        Branch(Word32Equal(current_value, key), if_found, &next_probe);
+      }
+      Bind(&if_currentisnotsmi);
+      {
+        GotoIf(WordEqual(current, the_hole), &next_probe);
+        // Current must be the Number.
+        Node* current_value = LoadHeapNumberValue(current);
+        Branch(Float64Equal(current_value, key_as_float64), if_found,
+               &next_probe);
+      }
+    }
+
+    Bind(&next_probe);
+    // See Dictionary::NextProbe().
+    count = Int32Add(count, Int32Constant(1));
+    entry = Word32And(Int32Add(entry, count), mask);
+
+    var_count.Bind(count);
+    var_entry->Bind(entry);
+    Goto(&loop);
+  }
+}
+
+void CodeStubAssembler::TryLookupProperty(
+    Node* object, Node* map, Node* instance_type, Node* unique_name,
+    Label* if_found_fast, Label* if_found_dict, Label* if_found_global,
+    Variable* var_meta_storage, Variable* var_name_index, Label* if_not_found,
+    Label* if_bailout) {
+  DCHECK_EQ(MachineRepresentation::kTagged, var_meta_storage->rep());
+  DCHECK_EQ(MachineRepresentation::kWord32, var_name_index->rep());
+
+  Label if_objectisspecial(this);
+  STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE);
+  GotoIf(Int32LessThanOrEqual(instance_type,
+                              Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)),
+         &if_objectisspecial);
+
+  Node* bit_field = LoadMapBitField(map);
+  Node* mask = Int32Constant(1 << Map::kHasNamedInterceptor |
+                             1 << Map::kIsAccessCheckNeeded);
+  Assert(Word32Equal(Word32And(bit_field, mask), Int32Constant(0)));
+
+  Node* bit_field3 = LoadMapBitField3(map);
+  Node* bit = BitFieldDecode<Map::DictionaryMap>(bit_field3);
+  Label if_isfastmap(this), if_isslowmap(this);
+  Branch(Word32Equal(bit, Int32Constant(0)), &if_isfastmap, &if_isslowmap);
+  Bind(&if_isfastmap);
+  {
+    Comment("DescriptorArrayLookup");
+    Node* nof = BitFieldDecode<Map::NumberOfOwnDescriptorsBits>(bit_field3);
+    // Bail out to the runtime for large numbers of own descriptors. The stub
+    // only does linear search, which becomes too expensive in that case.
+    {
+      static const int32_t kMaxLinear = 210;
+      GotoIf(Int32GreaterThan(nof, Int32Constant(kMaxLinear)), if_bailout);
+    }
+    Node* descriptors = LoadMapDescriptors(map);
+    var_meta_storage->Bind(descriptors);
+
+    Variable var_descriptor(this, MachineRepresentation::kWord32);
+    Label loop(this, &var_descriptor);
+    var_descriptor.Bind(Int32Constant(0));
+    Goto(&loop);
+    Bind(&loop);
+    {
+      Node* index = var_descriptor.value();
+      Node* name_offset = Int32Constant(DescriptorArray::ToKeyIndex(0));
+      Node* factor = Int32Constant(DescriptorArray::kDescriptorSize);
+      GotoIf(Word32Equal(index, nof), if_not_found);
+
+      Node* name_index = Int32Add(name_offset, Int32Mul(index, factor));
+      Node* name = LoadFixedArrayElement(descriptors, name_index);
+
+      var_name_index->Bind(name_index);
+      GotoIf(WordEqual(name, unique_name), if_found_fast);
+
+      var_descriptor.Bind(Int32Add(index, Int32Constant(1)));
+      Goto(&loop);
+    }
+  }
+  Bind(&if_isslowmap);
+  {
+    Node* dictionary = LoadProperties(object);
+    var_meta_storage->Bind(dictionary);
+
+    NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found_dict,
+                                         var_name_index, if_not_found);
+  }
+  Bind(&if_objectisspecial);
+  {
+    // Handle global object here and other special objects in runtime.
+    GotoUnless(Word32Equal(instance_type, Int32Constant(JS_GLOBAL_OBJECT_TYPE)),
+               if_bailout);
+
+    // Handle interceptors and access checks in runtime.
+    Node* bit_field = LoadMapBitField(map);
+    Node* mask = Int32Constant(1 << Map::kHasNamedInterceptor |
+                               1 << Map::kIsAccessCheckNeeded);
+    GotoIf(Word32NotEqual(Word32And(bit_field, mask), Int32Constant(0)),
+           if_bailout);
+
+    Node* dictionary = LoadProperties(object);
+    var_meta_storage->Bind(dictionary);
+
+    NameDictionaryLookup<GlobalDictionary>(
+        dictionary, unique_name, if_found_global, var_name_index, if_not_found);
+  }
+}
+
+void CodeStubAssembler::TryHasOwnProperty(compiler::Node* object,
+                                          compiler::Node* map,
+                                          compiler::Node* instance_type,
+                                          compiler::Node* unique_name,
+                                          Label* if_found, Label* if_not_found,
+                                          Label* if_bailout) {
+  Comment("TryHasOwnProperty");
+  Variable var_meta_storage(this, MachineRepresentation::kTagged);
+  Variable var_name_index(this, MachineRepresentation::kWord32);
+
+  Label if_found_global(this);
+  TryLookupProperty(object, map, instance_type, unique_name, if_found, if_found,
+                    &if_found_global, &var_meta_storage, &var_name_index,
+                    if_not_found, if_bailout);
+  Bind(&if_found_global);
+  {
+    Variable var_value(this, MachineRepresentation::kTagged);
+    Variable var_details(this, MachineRepresentation::kWord32);
+    // Check if the property cell is not deleted.
+    LoadPropertyFromGlobalDictionary(var_meta_storage.value(),
+                                     var_name_index.value(), &var_value,
+                                     &var_details, if_not_found);
+    Goto(if_found);
+  }
+}
+
+void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map,
+                                                   Node* descriptors,
+                                                   Node* name_index,
+                                                   Variable* var_details,
+                                                   Variable* var_value) {
+  DCHECK_EQ(MachineRepresentation::kWord32, var_details->rep());
+  DCHECK_EQ(MachineRepresentation::kTagged, var_value->rep());
+  Comment("[ LoadPropertyFromFastObject");
+
+  const int name_to_details_offset =
+      (DescriptorArray::kDescriptorDetails - DescriptorArray::kDescriptorKey) *
+      kPointerSize;
+  const int name_to_value_offset =
+      (DescriptorArray::kDescriptorValue - DescriptorArray::kDescriptorKey) *
+      kPointerSize;
+
+  Node* details = SmiToWord32(
+      LoadFixedArrayElement(descriptors, name_index, name_to_details_offset));
+  var_details->Bind(details);
+
+  Node* location = BitFieldDecode<PropertyDetails::LocationField>(details);
+
+  Label if_in_field(this), if_in_descriptor(this), done(this);
+  Branch(Word32Equal(location, Int32Constant(kField)), &if_in_field,
+         &if_in_descriptor);
+  Bind(&if_in_field);
+  {
+    Node* field_index =
+        BitFieldDecode<PropertyDetails::FieldIndexField>(details);
+    Node* representation =
+        BitFieldDecode<PropertyDetails::RepresentationField>(details);
+
+    Node* inobject_properties = LoadMapInobjectProperties(map);
+
+    Label if_inobject(this), if_backing_store(this);
+    Variable var_double_value(this, MachineRepresentation::kFloat64);
+    Label rebox_double(this, &var_double_value);
+    BranchIfInt32LessThan(field_index, inobject_properties, &if_inobject,
+                          &if_backing_store);
+    Bind(&if_inobject);
+    {
+      Comment("if_inobject");
+      Node* field_offset = ChangeInt32ToIntPtr(
+          Int32Mul(Int32Sub(LoadMapInstanceSize(map),
+                            Int32Sub(inobject_properties, field_index)),
+                   Int32Constant(kPointerSize)));
+
+      Label if_double(this), if_tagged(this);
+      BranchIfWord32NotEqual(representation,
+                             Int32Constant(Representation::kDouble), &if_tagged,
+                             &if_double);
+      Bind(&if_tagged);
+      {
+        var_value->Bind(LoadObjectField(object, field_offset));
+        Goto(&done);
+      }
+      Bind(&if_double);
+      {
+        if (FLAG_unbox_double_fields) {
+          var_double_value.Bind(
+              LoadObjectField(object, field_offset, MachineType::Float64()));
+        } else {
+          Node* mutable_heap_number = LoadObjectField(object, field_offset);
+          var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number));
+        }
+        Goto(&rebox_double);
+      }
+    }
+    Bind(&if_backing_store);
+    {
+      Comment("if_backing_store");
+      Node* properties = LoadProperties(object);
+      field_index = Int32Sub(field_index, inobject_properties);
+      Node* value = LoadFixedArrayElement(properties, field_index);
+
+      Label if_double(this), if_tagged(this);
+      BranchIfWord32NotEqual(representation,
+                             Int32Constant(Representation::kDouble), &if_tagged,
+                             &if_double);
+      Bind(&if_tagged);
+      {
+        var_value->Bind(value);
+        Goto(&done);
+      }
+      Bind(&if_double);
+      {
+        var_double_value.Bind(LoadHeapNumberValue(value));
+        Goto(&rebox_double);
+      }
+    }
+    Bind(&rebox_double);
+    {
+      Comment("rebox_double");
+      Node* heap_number = AllocateHeapNumber();
+      StoreHeapNumberValue(heap_number, var_double_value.value());
+      var_value->Bind(heap_number);
+      Goto(&done);
+    }
+  }
+  Bind(&if_in_descriptor);
+  {
+    Node* value =
+        LoadFixedArrayElement(descriptors, name_index, name_to_value_offset);
+    var_value->Bind(value);
+    Goto(&done);
+  }
+  Bind(&done);
+
+  Comment("] LoadPropertyFromFastObject");
+}
+
+void CodeStubAssembler::LoadPropertyFromNameDictionary(Node* dictionary,
+                                                       Node* name_index,
+                                                       Variable* var_details,
+                                                       Variable* var_value) {
+  Comment("LoadPropertyFromNameDictionary");
+
+  const int name_to_details_offset =
+      (NameDictionary::kEntryDetailsIndex - NameDictionary::kEntryKeyIndex) *
+      kPointerSize;
+  const int name_to_value_offset =
+      (NameDictionary::kEntryValueIndex - NameDictionary::kEntryKeyIndex) *
+      kPointerSize;
+
+  Node* details = SmiToWord32(
+      LoadFixedArrayElement(dictionary, name_index, name_to_details_offset));
+
+  var_details->Bind(details);
+  var_value->Bind(
+      LoadFixedArrayElement(dictionary, name_index, name_to_value_offset));
+
+  Comment("] LoadPropertyFromNameDictionary");
+}
+
+void CodeStubAssembler::LoadPropertyFromGlobalDictionary(Node* dictionary,
+                                                         Node* name_index,
+                                                         Variable* var_details,
+                                                         Variable* var_value,
+                                                         Label* if_deleted) {
+  Comment("[ LoadPropertyFromGlobalDictionary");
+
+  const int name_to_value_offset =
+      (GlobalDictionary::kEntryValueIndex - GlobalDictionary::kEntryKeyIndex) *
+      kPointerSize;
+
+  Node* property_cell =
+      LoadFixedArrayElement(dictionary, name_index, name_to_value_offset);
+
+  Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset);
+  GotoIf(WordEqual(value, TheHoleConstant()), if_deleted);
+
+  var_value->Bind(value);
+
+  Node* details =
+      SmiToWord32(LoadObjectField(property_cell, PropertyCell::kDetailsOffset));
+  var_details->Bind(details);
+
+  Comment("] LoadPropertyFromGlobalDictionary");
+}
+
+void CodeStubAssembler::TryGetOwnProperty(
+    Node* context, Node* receiver, Node* object, Node* map, Node* instance_type,
+    Node* unique_name, Label* if_found_value, Variable* var_value,
+    Label* if_not_found, Label* if_bailout) {
+  DCHECK_EQ(MachineRepresentation::kTagged, var_value->rep());
+  Comment("TryGetOwnProperty");
+
+  Variable var_meta_storage(this, MachineRepresentation::kTagged);
+  Variable var_entry(this, MachineRepresentation::kWord32);
+
+  Label if_found_fast(this), if_found_dict(this), if_found_global(this);
+
+  Variable var_details(this, MachineRepresentation::kWord32);
+  Variable* vars[] = {var_value, &var_details};
+  Label if_found(this, 2, vars);
+
+  TryLookupProperty(object, map, instance_type, unique_name, &if_found_fast,
+                    &if_found_dict, &if_found_global, &var_meta_storage,
+                    &var_entry, if_not_found, if_bailout);
+  Bind(&if_found_fast);
+  {
+    Node* descriptors = var_meta_storage.value();
+    Node* name_index = var_entry.value();
+
+    LoadPropertyFromFastObject(object, map, descriptors, name_index,
+                               &var_details, var_value);
+    Goto(&if_found);
+  }
+  Bind(&if_found_dict);
+  {
+    Node* dictionary = var_meta_storage.value();
+    Node* entry = var_entry.value();
+    LoadPropertyFromNameDictionary(dictionary, entry, &var_details, var_value);
+    Goto(&if_found);
+  }
+  Bind(&if_found_global);
+  {
+    Node* dictionary = var_meta_storage.value();
+    Node* entry = var_entry.value();
+
+    LoadPropertyFromGlobalDictionary(dictionary, entry, &var_details, var_value,
+                                     if_not_found);
+    Goto(&if_found);
+  }
+  // Here we have details and value which could be an accessor.
+  Bind(&if_found);
+  {
+    Node* details = var_details.value();
+    Node* kind = BitFieldDecode<PropertyDetails::KindField>(details);
+
+    Label if_accessor(this);
+    Branch(Word32Equal(kind, Int32Constant(kData)), if_found_value,
+           &if_accessor);
+    Bind(&if_accessor);
+    {
+      Node* accessor_pair = var_value->value();
+      GotoIf(Word32Equal(LoadInstanceType(accessor_pair),
+                         Int32Constant(ACCESSOR_INFO_TYPE)),
+             if_bailout);
+      AssertInstanceType(accessor_pair, ACCESSOR_PAIR_TYPE);
+      Node* getter =
+          LoadObjectField(accessor_pair, AccessorPair::kGetterOffset);
+      Node* getter_map = LoadMap(getter);
+      Node* instance_type = LoadMapInstanceType(getter_map);
+      // FunctionTemplateInfo getters are not supported yet.
+      GotoIf(Word32Equal(instance_type,
+                         Int32Constant(FUNCTION_TEMPLATE_INFO_TYPE)),
+             if_bailout);
+
+      // Return undefined if the {getter} is not callable.
+      var_value->Bind(UndefinedConstant());
+      GotoIf(Word32Equal(Word32And(LoadMapBitField(getter_map),
+                                   Int32Constant(1 << Map::kIsCallable)),
+                         Int32Constant(0)),
+             if_found_value);
+
+      // Call the accessor.
+      Callable callable = CodeFactory::Call(isolate());
+      Node* result = CallJS(callable, context, getter, receiver);
+      var_value->Bind(result);
+      Goto(if_found_value);
+    }
+  }
+}
+
+void CodeStubAssembler::TryLookupElement(Node* object, Node* map,
+                                         Node* instance_type, Node* index,
+                                         Label* if_found, Label* if_not_found,
+                                         Label* if_bailout) {
+  // Handle special objects in runtime.
+  GotoIf(Int32LessThanOrEqual(instance_type,
+                              Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)),
+         if_bailout);
+
+  Node* bit_field2 = LoadMapBitField2(map);
+  Node* elements_kind = BitFieldDecode<Map::ElementsKindBits>(bit_field2);
+
+  // TODO(verwaest): Support other elements kinds as well.
+  Label if_isobjectorsmi(this), if_isdouble(this), if_isdictionary(this),
+      if_isfaststringwrapper(this), if_isslowstringwrapper(this);
+  // clang-format off
+  int32_t values[] = {
+      // Handled by {if_isobjectorsmi}.
+      FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS,
+          FAST_HOLEY_ELEMENTS,
+      // Handled by {if_isdouble}.
+      FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS,
+      // Handled by {if_isdictionary}.
+      DICTIONARY_ELEMENTS,
+      // Handled by {if_isfaststringwrapper}.
+      FAST_STRING_WRAPPER_ELEMENTS,
+      // Handled by {if_isslowstringwrapper}.
+      SLOW_STRING_WRAPPER_ELEMENTS,
+      // Handled by {if_not_found}.
+      NO_ELEMENTS,
+  };
+  Label* labels[] = {
+      &if_isobjectorsmi, &if_isobjectorsmi, &if_isobjectorsmi,
+          &if_isobjectorsmi,
+      &if_isdouble, &if_isdouble,
+      &if_isdictionary,
+      &if_isfaststringwrapper,
+      &if_isslowstringwrapper,
+      if_not_found,
+  };
+  // clang-format on
+  STATIC_ASSERT(arraysize(values) == arraysize(labels));
+  Switch(elements_kind, if_bailout, values, labels, arraysize(values));
+
+  Bind(&if_isobjectorsmi);
+  {
+    Node* elements = LoadElements(object);
+    Node* length = LoadFixedArrayBaseLength(elements);
+
+    GotoIf(Int32GreaterThanOrEqual(index, SmiToWord32(length)), if_not_found);
+
+    Node* element = LoadFixedArrayElement(elements, index);
+    Node* the_hole = TheHoleConstant();
+    Branch(WordEqual(element, the_hole), if_not_found, if_found);
+  }
+  Bind(&if_isdouble);
+  {
+    Node* elements = LoadElements(object);
+    Node* length = LoadFixedArrayBaseLength(elements);
+
+    GotoIf(Int32GreaterThanOrEqual(index, SmiToWord32(length)), if_not_found);
+
+    if (kPointerSize == kDoubleSize) {
+      Node* element =
+          LoadFixedDoubleArrayElement(elements, index, MachineType::Uint64());
+      Node* the_hole = Int64Constant(kHoleNanInt64);
+      Branch(Word64Equal(element, the_hole), if_not_found, if_found);
+    } else {
+      Node* element_upper =
+          LoadFixedDoubleArrayElement(elements, index, MachineType::Uint32(),
+                                      kIeeeDoubleExponentWordOffset);
+      Branch(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)),
+             if_not_found, if_found);
+    }
+  }
+  Bind(&if_isdictionary);
+  {
+    Variable var_entry(this, MachineRepresentation::kWord32);
+    Node* elements = LoadElements(object);
+    NumberDictionaryLookup<SeededNumberDictionary>(elements, index, if_found,
+                                                   &var_entry, if_not_found);
+  }
+  Bind(&if_isfaststringwrapper);
+  {
+    AssertInstanceType(object, JS_VALUE_TYPE);
+    Node* string = LoadJSValueValue(object);
+    Assert(Int32LessThan(LoadInstanceType(string),
+                         Int32Constant(FIRST_NONSTRING_TYPE)));
+    Node* length = LoadStringLength(string);
+    GotoIf(Int32LessThan(index, SmiToWord32(length)), if_found);
+    Goto(&if_isobjectorsmi);
+  }
+  Bind(&if_isslowstringwrapper);
+  {
+    AssertInstanceType(object, JS_VALUE_TYPE);
+    Node* string = LoadJSValueValue(object);
+    Assert(Int32LessThan(LoadInstanceType(string),
+                         Int32Constant(FIRST_NONSTRING_TYPE)));
+    Node* length = LoadStringLength(string);
+    GotoIf(Int32LessThan(index, SmiToWord32(length)), if_found);
+    Goto(&if_isdictionary);
+  }
+}
+
+// Instantiate template methods to workaround GCC compilation issue.
+template void CodeStubAssembler::NumberDictionaryLookup<SeededNumberDictionary>(
+    Node*, Node*, Label*, Variable*, Label*);
+template void CodeStubAssembler::NumberDictionaryLookup<
+    UnseededNumberDictionary>(Node*, Node*, Label*, Variable*, Label*);
+
+Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
+                                             Node* object) {
+  Variable var_result(this, MachineRepresentation::kTagged);
+  Label return_false(this), return_true(this),
+      return_runtime(this, Label::kDeferred), return_result(this);
+
+  // Goto runtime if {object} is a Smi.
+  GotoIf(WordIsSmi(object), &return_runtime);
+
+  // Load map of {object}.
+  Node* object_map = LoadMap(object);
+
+  // Lookup the {callable} and {object} map in the global instanceof cache.
+  // Note: This is safe because we clear the global instanceof cache whenever
+  // we change the prototype of any object.
+  Node* instanceof_cache_function =
+      LoadRoot(Heap::kInstanceofCacheFunctionRootIndex);
+  Node* instanceof_cache_map = LoadRoot(Heap::kInstanceofCacheMapRootIndex);
+  {
+    Label instanceof_cache_miss(this);
+    GotoUnless(WordEqual(instanceof_cache_function, callable),
+               &instanceof_cache_miss);
+    GotoUnless(WordEqual(instanceof_cache_map, object_map),
+               &instanceof_cache_miss);
+    var_result.Bind(LoadRoot(Heap::kInstanceofCacheAnswerRootIndex));
+    Goto(&return_result);
+    Bind(&instanceof_cache_miss);
+  }
+
+  // Goto runtime if {callable} is a Smi.
+  GotoIf(WordIsSmi(callable), &return_runtime);
+
+  // Load map of {callable}.
+  Node* callable_map = LoadMap(callable);
+
+  // Goto runtime if {callable} is not a JSFunction.
+  Node* callable_instance_type = LoadMapInstanceType(callable_map);
+  GotoUnless(
+      Word32Equal(callable_instance_type, Int32Constant(JS_FUNCTION_TYPE)),
+      &return_runtime);
+
+  // Goto runtime if {callable} is not a constructor or has
+  // a non-instance "prototype".
+  Node* callable_bitfield = LoadMapBitField(callable_map);
+  GotoUnless(
+      Word32Equal(Word32And(callable_bitfield,
+                            Int32Constant((1 << Map::kHasNonInstancePrototype) |
+                                          (1 << Map::kIsConstructor))),
+                  Int32Constant(1 << Map::kIsConstructor)),
+      &return_runtime);
+
+  // Get the "prototype" (or initial map) of the {callable}.
+  Node* callable_prototype =
+      LoadObjectField(callable, JSFunction::kPrototypeOrInitialMapOffset);
+  {
+    Variable var_callable_prototype(this, MachineRepresentation::kTagged);
+    Label callable_prototype_valid(this);
+    var_callable_prototype.Bind(callable_prototype);
+
+    // Resolve the "prototype" if the {callable} has an initial map.  Afterwards
+    // the {callable_prototype} will be either the JSReceiver prototype object
+    // or the hole value, which means that no instances of the {callable} were
+    // created so far and hence we should return false.
+    Node* callable_prototype_instance_type =
+        LoadInstanceType(callable_prototype);
+    GotoUnless(
+        Word32Equal(callable_prototype_instance_type, Int32Constant(MAP_TYPE)),
+        &callable_prototype_valid);
+    var_callable_prototype.Bind(
+        LoadObjectField(callable_prototype, Map::kPrototypeOffset));
+    Goto(&callable_prototype_valid);
+    Bind(&callable_prototype_valid);
+    callable_prototype = var_callable_prototype.value();
+  }
+
+  // Update the global instanceof cache with the current {object} map and
+  // {callable}.  The cached answer will be set when it is known below.
+  StoreRoot(Heap::kInstanceofCacheFunctionRootIndex, callable);
+  StoreRoot(Heap::kInstanceofCacheMapRootIndex, object_map);
+
+  // Loop through the prototype chain looking for the {callable} prototype.
+  Variable var_object_map(this, MachineRepresentation::kTagged);
+  var_object_map.Bind(object_map);
+  Label loop(this, &var_object_map);
+  Goto(&loop);
+  Bind(&loop);
+  {
+    Node* object_map = var_object_map.value();
+
+    // Check if the current {object} needs to be access checked.
+    Node* object_bitfield = LoadMapBitField(object_map);
+    GotoUnless(
+        Word32Equal(Word32And(object_bitfield,
+                              Int32Constant(1 << Map::kIsAccessCheckNeeded)),
+                    Int32Constant(0)),
+        &return_runtime);
+
+    // Check if the current {object} is a proxy.
+    Node* object_instance_type = LoadMapInstanceType(object_map);
+    GotoIf(Word32Equal(object_instance_type, Int32Constant(JS_PROXY_TYPE)),
+           &return_runtime);
+
+    // Check the current {object} prototype.
+    Node* object_prototype = LoadMapPrototype(object_map);
+    GotoIf(WordEqual(object_prototype, NullConstant()), &return_false);
+    GotoIf(WordEqual(object_prototype, callable_prototype), &return_true);
+
+    // Continue with the prototype.
+    var_object_map.Bind(LoadMap(object_prototype));
+    Goto(&loop);
+  }
+
+  Bind(&return_true);
+  StoreRoot(Heap::kInstanceofCacheAnswerRootIndex, BooleanConstant(true));
+  var_result.Bind(BooleanConstant(true));
+  Goto(&return_result);
+
+  Bind(&return_false);
+  StoreRoot(Heap::kInstanceofCacheAnswerRootIndex, BooleanConstant(false));
+  var_result.Bind(BooleanConstant(false));
+  Goto(&return_result);
+
+  Bind(&return_runtime);
+  {
+    // Invalidate the global instanceof cache.
+    StoreRoot(Heap::kInstanceofCacheFunctionRootIndex, SmiConstant(0));
+    // Fallback to the runtime implementation.
+    var_result.Bind(
+        CallRuntime(Runtime::kOrdinaryHasInstance, context, callable, object));
+  }
+  Goto(&return_result);
+
+  Bind(&return_result);
+  return var_result.value();
+}
+
+compiler::Node* CodeStubAssembler::ElementOffsetFromIndex(Node* index_node,
+                                                          ElementsKind kind,
+                                                          ParameterMode mode,
+                                                          int base_size) {
+  bool is_double = IsFastDoubleElementsKind(kind);
+  int element_size_shift = is_double ? kDoubleSizeLog2 : kPointerSizeLog2;
+  int element_size = 1 << element_size_shift;
+  int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize;
+  int32_t index = 0;
+  bool constant_index = false;
+  if (mode == SMI_PARAMETERS) {
+    element_size_shift -= kSmiShiftBits;
+    intptr_t temp = 0;
+    constant_index = ToIntPtrConstant(index_node, temp);
+    index = temp >> kSmiShiftBits;
+  } else {
+    constant_index = ToInt32Constant(index_node, index);
+  }
+  if (constant_index) {
+    return IntPtrConstant(base_size + element_size * index);
+  }
+  if (Is64() && mode == INTEGER_PARAMETERS) {
+    index_node = ChangeInt32ToInt64(index_node);
+  }
+  if (base_size == 0) {
+    return (element_size_shift >= 0)
+               ? WordShl(index_node, IntPtrConstant(element_size_shift))
+               : WordShr(index_node, IntPtrConstant(-element_size_shift));
+  }
+  return IntPtrAdd(
+      IntPtrConstant(base_size),
+      (element_size_shift >= 0)
+          ? WordShl(index_node, IntPtrConstant(element_size_shift))
+          : WordShr(index_node, IntPtrConstant(-element_size_shift)));
+}
+
+compiler::Node* CodeStubAssembler::LoadTypeFeedbackVectorForStub() {
+  Node* function =
+      LoadFromParentFrame(JavaScriptFrameConstants::kFunctionOffset);
+  Node* literals = LoadObjectField(function, JSFunction::kLiteralsOffset);
+  return LoadObjectField(literals, LiteralsArray::kFeedbackVectorOffset);
+}
+
+compiler::Node* CodeStubAssembler::LoadReceiverMap(compiler::Node* receiver) {
+  Variable var_receiver_map(this, MachineRepresentation::kTagged);
+  // TODO(ishell): defer blocks when it works.
+  Label load_smi_map(this /*, Label::kDeferred*/), load_receiver_map(this),
+      if_result(this);
+
+  Branch(WordIsSmi(receiver), &load_smi_map, &load_receiver_map);
+  Bind(&load_smi_map);
+  {
+    var_receiver_map.Bind(LoadRoot(Heap::kHeapNumberMapRootIndex));
+    Goto(&if_result);
+  }
+  Bind(&load_receiver_map);
+  {
+    var_receiver_map.Bind(LoadMap(receiver));
+    Goto(&if_result);
+  }
+  Bind(&if_result);
+  return var_receiver_map.value();
+}
+
+compiler::Node* CodeStubAssembler::TryMonomorphicCase(
+    const LoadICParameters* p, compiler::Node* receiver_map, Label* if_handler,
+    Variable* var_handler, Label* if_miss) {
+  DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
+
+  // TODO(ishell): add helper class that hides offset computations for a series
+  // of loads.
+  int32_t header_size = FixedArray::kHeaderSize - kHeapObjectTag;
+  Node* offset = ElementOffsetFromIndex(p->slot, FAST_HOLEY_ELEMENTS,
+                                        SMI_PARAMETERS, header_size);
+  Node* feedback = Load(MachineType::AnyTagged(), p->vector, offset);
+
+  // Try to quickly handle the monomorphic case without knowing for sure
+  // if we have a weak cell in feedback. We do know it's safe to look
+  // at WeakCell::kValueOffset.
+  GotoUnless(WordEqual(receiver_map, LoadWeakCellValue(feedback)), if_miss);
+
+  Node* handler = Load(MachineType::AnyTagged(), p->vector,
+                       IntPtrAdd(offset, IntPtrConstant(kPointerSize)));
+
+  var_handler->Bind(handler);
+  Goto(if_handler);
+  return feedback;
+}
+
+void CodeStubAssembler::HandlePolymorphicCase(
+    const LoadICParameters* p, compiler::Node* receiver_map,
+    compiler::Node* feedback, Label* if_handler, Variable* var_handler,
+    Label* if_miss, int unroll_count) {
+  DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
+
+  // Iterate {feedback} array.
+  const int kEntrySize = 2;
+
+  for (int i = 0; i < unroll_count; i++) {
+    Label next_entry(this);
+    Node* cached_map = LoadWeakCellValue(
+        LoadFixedArrayElement(feedback, Int32Constant(i * kEntrySize)));
+    GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry);
+
+    // Found, now call handler.
+    Node* handler =
+        LoadFixedArrayElement(feedback, Int32Constant(i * kEntrySize + 1));
+    var_handler->Bind(handler);
+    Goto(if_handler);
+
+    Bind(&next_entry);
+  }
+  Node* length = SmiToWord32(LoadFixedArrayBaseLength(feedback));
+
+  // Loop from {unroll_count}*kEntrySize to {length}.
+  Variable var_index(this, MachineRepresentation::kWord32);
+  Label loop(this, &var_index);
+  var_index.Bind(Int32Constant(unroll_count * kEntrySize));
+  Goto(&loop);
+  Bind(&loop);
+  {
+    Node* index = var_index.value();
+    GotoIf(Int32GreaterThanOrEqual(index, length), if_miss);
+
+    Node* cached_map =
+        LoadWeakCellValue(LoadFixedArrayElement(feedback, index));
+
+    Label next_entry(this);
+    GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry);
+
+    // Found, now call handler.
+    Node* handler = LoadFixedArrayElement(feedback, index, kPointerSize);
+    var_handler->Bind(handler);
+    Goto(if_handler);
+
+    Bind(&next_entry);
+    var_index.Bind(Int32Add(index, Int32Constant(kEntrySize)));
+    Goto(&loop);
+  }
+}
+
+compiler::Node* CodeStubAssembler::StubCachePrimaryOffset(compiler::Node* name,
+                                                          Code::Flags flags,
+                                                          compiler::Node* map) {
+  // See v8::internal::StubCache::PrimaryOffset().
+  STATIC_ASSERT(StubCache::kCacheIndexShift == Name::kHashShift);
+  // Compute the hash of the name (use entire hash field).
+  Node* hash_field = LoadNameHashField(name);
+  Assert(WordEqual(
+      Word32And(hash_field, Int32Constant(Name::kHashNotComputedMask)),
+      Int32Constant(0)));
+
+  // Using only the low bits in 64-bit mode is unlikely to increase the
+  // risk of collision even if the heap is spread over an area larger than
+  // 4Gb (and not at all if it isn't).
+  Node* hash = Int32Add(hash_field, map);
+  // We always set the in_loop bit to zero when generating the lookup code
+  // so do it here too so the hash codes match.
+  uint32_t iflags =
+      (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
+  // Base the offset on a simple combination of name, flags, and map.
+  hash = Word32Xor(hash, Int32Constant(iflags));
+  uint32_t mask = (StubCache::kPrimaryTableSize - 1)
+                  << StubCache::kCacheIndexShift;
+  return Word32And(hash, Int32Constant(mask));
+}
+
+compiler::Node* CodeStubAssembler::StubCacheSecondaryOffset(
+    compiler::Node* name, Code::Flags flags, compiler::Node* seed) {
+  // See v8::internal::StubCache::SecondaryOffset().
+
+  // Use the seed from the primary cache in the secondary cache.
+  Node* hash = Int32Sub(seed, name);
+  // We always set the in_loop bit to zero when generating the lookup code
+  // so do it here too so the hash codes match.
+  uint32_t iflags =
+      (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
+  hash = Int32Add(hash, Int32Constant(iflags));
+  int32_t mask = (StubCache::kSecondaryTableSize - 1)
+                 << StubCache::kCacheIndexShift;
+  return Word32And(hash, Int32Constant(mask));
+}
+
+enum CodeStubAssembler::StubCacheTable : int {
+  kPrimary = static_cast<int>(StubCache::kPrimary),
+  kSecondary = static_cast<int>(StubCache::kSecondary)
+};
+
+void CodeStubAssembler::TryProbeStubCacheTable(
+    StubCache* stub_cache, StubCacheTable table_id,
+    compiler::Node* entry_offset, compiler::Node* name, Code::Flags flags,
+    compiler::Node* map, Label* if_handler, Variable* var_handler,
+    Label* if_miss) {
+  StubCache::Table table = static_cast<StubCache::Table>(table_id);
+#ifdef DEBUG
+  if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
+    Goto(if_miss);
+    return;
+  } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
+    Goto(if_miss);
+    return;
+  }
+#endif
+  // The {table_offset} holds the entry offset times four (due to masking
+  // and shifting optimizations).
+  const int kMultiplier = sizeof(StubCache::Entry) >> Name::kHashShift;
+  entry_offset = Int32Mul(entry_offset, Int32Constant(kMultiplier));
+
+  // Check that the key in the entry matches the name.
+  Node* key_base =
+      ExternalConstant(ExternalReference(stub_cache->key_reference(table)));
+  Node* entry_key = Load(MachineType::Pointer(), key_base, entry_offset);
+  GotoIf(WordNotEqual(name, entry_key), if_miss);
+
+  // Get the map entry from the cache.
+  DCHECK_EQ(kPointerSize * 2, stub_cache->map_reference(table).address() -
+                                  stub_cache->key_reference(table).address());
+  Node* entry_map =
+      Load(MachineType::Pointer(), key_base,
+           Int32Add(entry_offset, Int32Constant(kPointerSize * 2)));
+  GotoIf(WordNotEqual(map, entry_map), if_miss);
+
+  // Check that the flags match what we're looking for.
+  DCHECK_EQ(kPointerSize, stub_cache->value_reference(table).address() -
+                              stub_cache->key_reference(table).address());
+  Node* code = Load(MachineType::Pointer(), key_base,
+                    Int32Add(entry_offset, Int32Constant(kPointerSize)));
+
+  Node* code_flags =
+      LoadObjectField(code, Code::kFlagsOffset, MachineType::Uint32());
+  GotoIf(Word32NotEqual(Int32Constant(flags),
+                        Word32And(code_flags,
+                                  Int32Constant(~Code::kFlagsNotUsedInLookup))),
+         if_miss);
+
+  // We found the handler.
+  var_handler->Bind(code);
+  Goto(if_handler);
+}
+
+void CodeStubAssembler::TryProbeStubCache(
+    StubCache* stub_cache, Code::Flags flags, compiler::Node* receiver,
+    compiler::Node* name, Label* if_handler, Variable* var_handler,
+    Label* if_miss) {
+  Label try_secondary(this), miss(this);
+
+  Counters* counters = isolate()->counters();
+  IncrementCounter(counters->megamorphic_stub_cache_probes(), 1);
+
+  // Check that the {receiver} isn't a smi.
+  GotoIf(WordIsSmi(receiver), &miss);
+
+  Node* receiver_map = LoadMap(receiver);
+
+  // Probe the primary table.
+  Node* primary_offset = StubCachePrimaryOffset(name, flags, receiver_map);
+  TryProbeStubCacheTable(stub_cache, kPrimary, primary_offset, name, flags,
+                         receiver_map, if_handler, var_handler, &try_secondary);
+
+  Bind(&try_secondary);
+  {
+    // Probe the secondary table.
+    Node* secondary_offset =
+        StubCacheSecondaryOffset(name, flags, primary_offset);
+    TryProbeStubCacheTable(stub_cache, kSecondary, secondary_offset, name,
+                           flags, receiver_map, if_handler, var_handler, &miss);
+  }
+
+  Bind(&miss);
+  {
+    IncrementCounter(counters->megamorphic_stub_cache_misses(), 1);
+    Goto(if_miss);
+  }
+}
+
+void CodeStubAssembler::LoadIC(const LoadICParameters* p) {
+  Variable var_handler(this, MachineRepresentation::kTagged);
+  // TODO(ishell): defer blocks when it works.
+  Label if_handler(this, &var_handler), try_polymorphic(this),
+      try_megamorphic(this /*, Label::kDeferred*/),
+      miss(this /*, Label::kDeferred*/);
+
+  Node* receiver_map = LoadReceiverMap(p->receiver);
+
+  // Check monomorphic case.
+  Node* feedback = TryMonomorphicCase(p, receiver_map, &if_handler,
+                                      &var_handler, &try_polymorphic);
+  Bind(&if_handler);
+  {
+    LoadWithVectorDescriptor descriptor(isolate());
+    TailCallStub(descriptor, var_handler.value(), p->context, p->receiver,
+                 p->name, p->slot, p->vector);
+  }
+
+  Bind(&try_polymorphic);
+  {
+    // Check polymorphic case.
+    GotoUnless(
+        WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)),
+        &try_megamorphic);
+    HandlePolymorphicCase(p, receiver_map, feedback, &if_handler, &var_handler,
+                          &miss, 2);
+  }
+
+  Bind(&try_megamorphic);
+  {
+    // Check megamorphic case.
+    GotoUnless(
+        WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)),
+        &miss);
+
+    Code::Flags code_flags =
+        Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
+
+    TryProbeStubCache(isolate()->stub_cache(), code_flags, p->receiver, p->name,
+                      &if_handler, &var_handler, &miss);
+  }
+  Bind(&miss);
+  {
+    TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name,
+                    p->slot, p->vector);
+  }
+}
+
+void CodeStubAssembler::LoadGlobalIC(const LoadICParameters* p) {
+  Label try_handler(this), miss(this);
+  Node* weak_cell =
+      LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS);
+  AssertInstanceType(weak_cell, WEAK_CELL_TYPE);
+
+  // Load value or try handler case if the {weak_cell} is cleared.
+  Node* property_cell = LoadWeakCellValue(weak_cell, &try_handler);
+  AssertInstanceType(property_cell, PROPERTY_CELL_TYPE);
+
+  Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset);
+  GotoIf(WordEqual(value, TheHoleConstant()), &miss);
+  Return(value);
+
+  Bind(&try_handler);
+  {
+    Node* handler =
+        LoadFixedArrayElement(p->vector, p->slot, kPointerSize, SMI_PARAMETERS);
+    GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)),
+           &miss);
+
+    // In this case {handler} must be a Code object.
+    AssertInstanceType(handler, CODE_TYPE);
+    LoadWithVectorDescriptor descriptor(isolate());
+    Node* native_context = LoadNativeContext(p->context);
+    Node* receiver = LoadFixedArrayElement(
+        native_context, Int32Constant(Context::EXTENSION_INDEX));
+    Node* fake_name = IntPtrConstant(0);
+    TailCallStub(descriptor, handler, p->context, receiver, fake_name, p->slot,
+                 p->vector);
+  }
+  Bind(&miss);
+  {
+    TailCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, p->slot,
+                    p->vector);
+  }
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/code-stub-assembler.h b/src/code-stub-assembler.h
new file mode 100644
index 0000000..f10e3ad
--- /dev/null
+++ b/src/code-stub-assembler.h
@@ -0,0 +1,444 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_CODE_STUB_ASSEMBLER_H_
+#define V8_CODE_STUB_ASSEMBLER_H_
+
+#include "src/compiler/code-assembler.h"
+#include "src/objects.h"
+
+namespace v8 {
+namespace internal {
+
+class CallInterfaceDescriptor;
+class StatsCounter;
+class StubCache;
+
+// Provides JavaScript-specific "macro-assembler" functionality on top of the
+// CodeAssembler. By factoring the JavaScript-isms out of the CodeAssembler,
+// it's possible to add JavaScript-specific useful CodeAssembler "macros"
+// without modifying files in the compiler directory (and requiring a review
+// from a compiler directory OWNER).
+class CodeStubAssembler : public compiler::CodeAssembler {
+ public:
+  // Create with CallStub linkage.
+  // |result_size| specifies the number of results returned by the stub.
+  // TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
+  CodeStubAssembler(Isolate* isolate, Zone* zone,
+                    const CallInterfaceDescriptor& descriptor,
+                    Code::Flags flags, const char* name,
+                    size_t result_size = 1);
+
+  // Create with JSCall linkage.
+  CodeStubAssembler(Isolate* isolate, Zone* zone, int parameter_count,
+                    Code::Flags flags, const char* name);
+
+  enum ParameterMode { INTEGER_PARAMETERS, SMI_PARAMETERS };
+
+  compiler::Node* BooleanMapConstant();
+  compiler::Node* EmptyStringConstant();
+  compiler::Node* HeapNumberMapConstant();
+  compiler::Node* NoContextConstant();
+  compiler::Node* NullConstant();
+  compiler::Node* UndefinedConstant();
+  compiler::Node* TheHoleConstant();
+  compiler::Node* HashSeed();
+  compiler::Node* StaleRegisterConstant();
+
+  // Float64 operations.
+  compiler::Node* Float64Ceil(compiler::Node* x);
+  compiler::Node* Float64Floor(compiler::Node* x);
+  compiler::Node* Float64Round(compiler::Node* x);
+  compiler::Node* Float64Trunc(compiler::Node* x);
+
+  // Tag a Word as a Smi value.
+  compiler::Node* SmiTag(compiler::Node* value);
+  // Untag a Smi value as a Word.
+  compiler::Node* SmiUntag(compiler::Node* value);
+
+  // Smi conversions.
+  compiler::Node* SmiToFloat64(compiler::Node* value);
+  compiler::Node* SmiFromWord(compiler::Node* value) { return SmiTag(value); }
+  compiler::Node* SmiFromWord32(compiler::Node* value);
+  compiler::Node* SmiToWord(compiler::Node* value) { return SmiUntag(value); }
+  compiler::Node* SmiToWord32(compiler::Node* value);
+
+  // Smi operations.
+  compiler::Node* SmiAdd(compiler::Node* a, compiler::Node* b);
+  compiler::Node* SmiAddWithOverflow(compiler::Node* a, compiler::Node* b);
+  compiler::Node* SmiSub(compiler::Node* a, compiler::Node* b);
+  compiler::Node* SmiSubWithOverflow(compiler::Node* a, compiler::Node* b);
+  compiler::Node* SmiEqual(compiler::Node* a, compiler::Node* b);
+  compiler::Node* SmiAboveOrEqual(compiler::Node* a, compiler::Node* b);
+  compiler::Node* SmiLessThan(compiler::Node* a, compiler::Node* b);
+  compiler::Node* SmiLessThanOrEqual(compiler::Node* a, compiler::Node* b);
+  compiler::Node* SmiMin(compiler::Node* a, compiler::Node* b);
+
+  // Allocate an object of the given size.
+  compiler::Node* Allocate(compiler::Node* size, AllocationFlags flags = kNone);
+  compiler::Node* Allocate(int size, AllocationFlags flags = kNone);
+  compiler::Node* InnerAllocate(compiler::Node* previous, int offset);
+  compiler::Node* InnerAllocate(compiler::Node* previous,
+                                compiler::Node* offset);
+
+  void Assert(compiler::Node* condition);
+
+  // Check a value for smi-ness
+  compiler::Node* WordIsSmi(compiler::Node* a);
+  // Check that the value is a positive smi.
+  compiler::Node* WordIsPositiveSmi(compiler::Node* a);
+
+  void BranchIfSmiLessThan(compiler::Node* a, compiler::Node* b, Label* if_true,
+                           Label* if_false) {
+    BranchIf(SmiLessThan(a, b), if_true, if_false);
+  }
+
+  void BranchIfSmiLessThanOrEqual(compiler::Node* a, compiler::Node* b,
+                                  Label* if_true, Label* if_false) {
+    BranchIf(SmiLessThanOrEqual(a, b), if_true, if_false);
+  }
+
+  void BranchIfFloat64IsNaN(compiler::Node* value, Label* if_true,
+                            Label* if_false) {
+    BranchIfFloat64Equal(value, value, if_false, if_true);
+  }
+
+  // Load value from current frame by given offset in bytes.
+  compiler::Node* LoadFromFrame(int offset,
+                                MachineType rep = MachineType::AnyTagged());
+  // Load value from current parent frame by given offset in bytes.
+  compiler::Node* LoadFromParentFrame(
+      int offset, MachineType rep = MachineType::AnyTagged());
+
+  // Load an object pointer from a buffer that isn't in the heap.
+  compiler::Node* LoadBufferObject(compiler::Node* buffer, int offset,
+                                   MachineType rep = MachineType::AnyTagged());
+  // Load a field from an object on the heap.
+  compiler::Node* LoadObjectField(compiler::Node* object, int offset,
+                                  MachineType rep = MachineType::AnyTagged());
+  compiler::Node* LoadObjectField(compiler::Node* object,
+                                  compiler::Node* offset,
+                                  MachineType rep = MachineType::AnyTagged());
+
+  // Load the floating point value of a HeapNumber.
+  compiler::Node* LoadHeapNumberValue(compiler::Node* object);
+  // Load the Map of an HeapObject.
+  compiler::Node* LoadMap(compiler::Node* object);
+  // Load the instance type of an HeapObject.
+  compiler::Node* LoadInstanceType(compiler::Node* object);
+  // Checks that given heap object has given instance type.
+  void AssertInstanceType(compiler::Node* object, InstanceType instance_type);
+  // Load the properties backing store of a JSObject.
+  compiler::Node* LoadProperties(compiler::Node* object);
+  // Load the elements backing store of a JSObject.
+  compiler::Node* LoadElements(compiler::Node* object);
+  // Load the length of a fixed array base instance.
+  compiler::Node* LoadFixedArrayBaseLength(compiler::Node* array);
+  // Load the bit field of a Map.
+  compiler::Node* LoadMapBitField(compiler::Node* map);
+  // Load bit field 2 of a map.
+  compiler::Node* LoadMapBitField2(compiler::Node* map);
+  // Load bit field 3 of a map.
+  compiler::Node* LoadMapBitField3(compiler::Node* map);
+  // Load the instance type of a map.
+  compiler::Node* LoadMapInstanceType(compiler::Node* map);
+  // Load the instance descriptors of a map.
+  compiler::Node* LoadMapDescriptors(compiler::Node* map);
+  // Load the prototype of a map.
+  compiler::Node* LoadMapPrototype(compiler::Node* map);
+  // Load the instance size of a Map.
+  compiler::Node* LoadMapInstanceSize(compiler::Node* map);
+  // Load the inobject properties count of a Map (valid only for JSObjects).
+  compiler::Node* LoadMapInobjectProperties(compiler::Node* map);
+
+  // Load the hash field of a name.
+  compiler::Node* LoadNameHashField(compiler::Node* name);
+  // Load the hash value of a name. If {if_hash_not_computed} label
+  // is specified then it also checks if hash is actually computed.
+  compiler::Node* LoadNameHash(compiler::Node* name,
+                               Label* if_hash_not_computed = nullptr);
+
+  // Load length field of a String object.
+  compiler::Node* LoadStringLength(compiler::Node* object);
+  // Load value field of a JSValue object.
+  compiler::Node* LoadJSValueValue(compiler::Node* object);
+  // Load value field of a WeakCell object.
+  compiler::Node* LoadWeakCellValue(compiler::Node* weak_cell,
+                                    Label* if_cleared = nullptr);
+
+  compiler::Node* AllocateUninitializedFixedArray(compiler::Node* length);
+
+  // Load an array element from a FixedArray.
+  compiler::Node* LoadFixedArrayElement(
+      compiler::Node* object, compiler::Node* int32_index,
+      int additional_offset = 0,
+      ParameterMode parameter_mode = INTEGER_PARAMETERS);
+  // Load an array element from a FixedDoubleArray.
+  compiler::Node* LoadFixedDoubleArrayElement(
+      compiler::Node* object, compiler::Node* int32_index,
+      MachineType machine_type, int additional_offset = 0,
+      ParameterMode parameter_mode = INTEGER_PARAMETERS);
+
+  // Context manipulation
+  compiler::Node* LoadNativeContext(compiler::Node* context);
+
+  compiler::Node* LoadJSArrayElementsMap(ElementsKind kind,
+                                         compiler::Node* native_context);
+
+  // Store the floating point value of a HeapNumber.
+  compiler::Node* StoreHeapNumberValue(compiler::Node* object,
+                                       compiler::Node* value);
+  // Store a field to an object on the heap.
+  compiler::Node* StoreObjectField(
+      compiler::Node* object, int offset, compiler::Node* value);
+  compiler::Node* StoreObjectFieldNoWriteBarrier(
+      compiler::Node* object, int offset, compiler::Node* value,
+      MachineRepresentation rep = MachineRepresentation::kTagged);
+  // Store the Map of an HeapObject.
+  compiler::Node* StoreMapNoWriteBarrier(compiler::Node* object,
+                                         compiler::Node* map);
+  // Store an array element to a FixedArray.
+  compiler::Node* StoreFixedArrayElement(
+      compiler::Node* object, compiler::Node* index, compiler::Node* value,
+      WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
+      ParameterMode parameter_mode = INTEGER_PARAMETERS);
+
+  compiler::Node* StoreFixedDoubleArrayElement(
+      compiler::Node* object, compiler::Node* index, compiler::Node* value,
+      ParameterMode parameter_mode = INTEGER_PARAMETERS);
+
+  // Allocate a HeapNumber without initializing its value.
+  compiler::Node* AllocateHeapNumber();
+  // Allocate a HeapNumber with a specific value.
+  compiler::Node* AllocateHeapNumberWithValue(compiler::Node* value);
+  // Allocate a SeqOneByteString with the given length.
+  compiler::Node* AllocateSeqOneByteString(int length);
+  compiler::Node* AllocateSeqOneByteString(compiler::Node* context,
+                                           compiler::Node* length);
+  // Allocate a SeqTwoByteString with the given length.
+  compiler::Node* AllocateSeqTwoByteString(int length);
+  compiler::Node* AllocateSeqTwoByteString(compiler::Node* context,
+                                           compiler::Node* length);
+  // Allocated an JSArray
+  compiler::Node* AllocateJSArray(ElementsKind kind, compiler::Node* array_map,
+                                  compiler::Node* capacity,
+                                  compiler::Node* length,
+                                  compiler::Node* allocation_site = nullptr,
+                                  ParameterMode mode = INTEGER_PARAMETERS);
+
+  // Allocation site manipulation
+  void InitializeAllocationMemento(compiler::Node* base_allocation,
+                                   int base_allocation_size,
+                                   compiler::Node* allocation_site);
+
+  compiler::Node* TruncateTaggedToFloat64(compiler::Node* context,
+                                          compiler::Node* value);
+  compiler::Node* TruncateTaggedToWord32(compiler::Node* context,
+                                         compiler::Node* value);
+  // Truncate the floating point value of a HeapNumber to an Int32.
+  compiler::Node* TruncateHeapNumberValueToWord32(compiler::Node* object);
+
+  // Conversions.
+  compiler::Node* ChangeFloat64ToTagged(compiler::Node* value);
+  compiler::Node* ChangeInt32ToTagged(compiler::Node* value);
+  compiler::Node* ChangeUint32ToTagged(compiler::Node* value);
+
+  // Type conversions.
+  // Throws a TypeError for {method_name} if {value} is not coercible to Object,
+  // or returns the {value} converted to a String otherwise.
+  compiler::Node* ToThisString(compiler::Node* context, compiler::Node* value,
+                               char const* method_name);
+
+  // String helpers.
+  // Load a character from a String (might flatten a ConsString).
+  compiler::Node* StringCharCodeAt(compiler::Node* string,
+                                   compiler::Node* smi_index);
+  // Return the single character string with only {code}.
+  compiler::Node* StringFromCharCode(compiler::Node* code);
+
+  // Returns a node that is true if the given bit is set in |word32|.
+  template <typename T>
+  compiler::Node* BitFieldDecode(compiler::Node* word32) {
+    return BitFieldDecode(word32, T::kShift, T::kMask);
+  }
+
+  compiler::Node* BitFieldDecode(compiler::Node* word32, uint32_t shift,
+                                 uint32_t mask);
+
+  void SetCounter(StatsCounter* counter, int value);
+  void IncrementCounter(StatsCounter* counter, int delta);
+  void DecrementCounter(StatsCounter* counter, int delta);
+
+  // Various building blocks for stubs doing property lookups.
+  void TryToName(compiler::Node* key, Label* if_keyisindex, Variable* var_index,
+                 Label* if_keyisunique, Label* if_bailout);
+
+  // Calculates array index for given dictionary entry and entry field.
+  // See Dictionary::EntryToIndex().
+  template <typename Dictionary>
+  compiler::Node* EntryToIndex(compiler::Node* entry, int field_index);
+  template <typename Dictionary>
+  compiler::Node* EntryToIndex(compiler::Node* entry) {
+    return EntryToIndex<Dictionary>(entry, Dictionary::kEntryKeyIndex);
+  }
+
+  // Looks up an entry in a NameDictionaryBase successor. If the entry is found
+  // control goes to {if_found} and {var_name_index} contains an index of the
+  // key field of the entry found. If the key is not found control goes to
+  // {if_not_found}.
+  static const int kInlinedDictionaryProbes = 4;
+  template <typename Dictionary>
+  void NameDictionaryLookup(compiler::Node* dictionary,
+                            compiler::Node* unique_name, Label* if_found,
+                            Variable* var_name_index, Label* if_not_found,
+                            int inlined_probes = kInlinedDictionaryProbes);
+
+  compiler::Node* ComputeIntegerHash(compiler::Node* key, compiler::Node* seed);
+
+  template <typename Dictionary>
+  void NumberDictionaryLookup(compiler::Node* dictionary, compiler::Node* key,
+                              Label* if_found, Variable* var_entry,
+                              Label* if_not_found);
+
+  // Tries to check if {object} has own {unique_name} property.
+  void TryHasOwnProperty(compiler::Node* object, compiler::Node* map,
+                         compiler::Node* instance_type,
+                         compiler::Node* unique_name, Label* if_found,
+                         Label* if_not_found, Label* if_bailout);
+
+  // Tries to get {object}'s own {unique_name} property value. If the property
+  // is an accessor then it also calls a getter. If the property is a double
+  // field it re-wraps value in an immutable heap number.
+  void TryGetOwnProperty(compiler::Node* context, compiler::Node* receiver,
+                         compiler::Node* object, compiler::Node* map,
+                         compiler::Node* instance_type,
+                         compiler::Node* unique_name, Label* if_found,
+                         Variable* var_value, Label* if_not_found,
+                         Label* if_bailout);
+
+  void LoadPropertyFromFastObject(compiler::Node* object, compiler::Node* map,
+                                  compiler::Node* descriptors,
+                                  compiler::Node* name_index,
+                                  Variable* var_details, Variable* var_value);
+
+  void LoadPropertyFromNameDictionary(compiler::Node* dictionary,
+                                      compiler::Node* entry,
+                                      Variable* var_details,
+                                      Variable* var_value);
+
+  void LoadPropertyFromGlobalDictionary(compiler::Node* dictionary,
+                                        compiler::Node* entry,
+                                        Variable* var_details,
+                                        Variable* var_value, Label* if_deleted);
+
+  // Generic property lookup generator. If the {object} is fast and
+  // {unique_name} property is found then the control goes to {if_found_fast}
+  // label and {var_meta_storage} and {var_name_index} will contain
+  // DescriptorArray and an index of the descriptor's name respectively.
+  // If the {object} is slow or global then the control goes to {if_found_dict}
+  // or {if_found_global} and the {var_meta_storage} and {var_name_index} will
+  // contain a dictionary and an index of the key field of the found entry.
+  // If property is not found or given lookup is not supported then
+  // the control goes to {if_not_found} or {if_bailout} respectively.
+  //
+  // Note: this code does not check if the global dictionary points to deleted
+  // entry! This has to be done by the caller.
+  void TryLookupProperty(compiler::Node* object, compiler::Node* map,
+                         compiler::Node* instance_type,
+                         compiler::Node* unique_name, Label* if_found_fast,
+                         Label* if_found_dict, Label* if_found_global,
+                         Variable* var_meta_storage, Variable* var_name_index,
+                         Label* if_not_found, Label* if_bailout);
+
+  void TryLookupElement(compiler::Node* object, compiler::Node* map,
+                        compiler::Node* instance_type, compiler::Node* index,
+                        Label* if_found, Label* if_not_found,
+                        Label* if_bailout);
+
+  // Instanceof helpers.
+  // ES6 section 7.3.19 OrdinaryHasInstance (C, O)
+  compiler::Node* OrdinaryHasInstance(compiler::Node* context,
+                                      compiler::Node* callable,
+                                      compiler::Node* object);
+
+  // LoadIC helpers.
+  struct LoadICParameters {
+    LoadICParameters(compiler::Node* context, compiler::Node* receiver,
+                     compiler::Node* name, compiler::Node* slot,
+                     compiler::Node* vector)
+        : context(context),
+          receiver(receiver),
+          name(name),
+          slot(slot),
+          vector(vector) {}
+
+    compiler::Node* context;
+    compiler::Node* receiver;
+    compiler::Node* name;
+    compiler::Node* slot;
+    compiler::Node* vector;
+  };
+
+  // Load type feedback vector from the stub caller's frame.
+  compiler::Node* LoadTypeFeedbackVectorForStub();
+
+  compiler::Node* LoadReceiverMap(compiler::Node* receiver);
+
+  // Checks monomorphic case. Returns {feedback} entry of the vector.
+  compiler::Node* TryMonomorphicCase(const LoadICParameters* p,
+                                     compiler::Node* receiver_map,
+                                     Label* if_handler, Variable* var_handler,
+                                     Label* if_miss);
+  void HandlePolymorphicCase(const LoadICParameters* p,
+                             compiler::Node* receiver_map,
+                             compiler::Node* feedback, Label* if_handler,
+                             Variable* var_handler, Label* if_miss,
+                             int unroll_count);
+
+  compiler::Node* StubCachePrimaryOffset(compiler::Node* name,
+                                         Code::Flags flags,
+                                         compiler::Node* map);
+
+  compiler::Node* StubCacheSecondaryOffset(compiler::Node* name,
+                                           Code::Flags flags,
+                                           compiler::Node* seed);
+
+  // This enum is used here as a replacement for StubCache::Table to avoid
+  // including stub cache header.
+  enum StubCacheTable : int;
+
+  void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id,
+                              compiler::Node* entry_offset,
+                              compiler::Node* name, Code::Flags flags,
+                              compiler::Node* map, Label* if_handler,
+                              Variable* var_handler, Label* if_miss);
+
+  void TryProbeStubCache(StubCache* stub_cache, Code::Flags flags,
+                         compiler::Node* receiver, compiler::Node* name,
+                         Label* if_handler, Variable* var_handler,
+                         Label* if_miss);
+
+  void LoadIC(const LoadICParameters* p);
+  void LoadGlobalIC(const LoadICParameters* p);
+
+ private:
+  compiler::Node* ElementOffsetFromIndex(compiler::Node* index,
+                                         ElementsKind kind, ParameterMode mode,
+                                         int base_size = 0);
+
+  compiler::Node* AllocateRawAligned(compiler::Node* size_in_bytes,
+                                     AllocationFlags flags,
+                                     compiler::Node* top_address,
+                                     compiler::Node* limit_address);
+  compiler::Node* AllocateRawUnaligned(compiler::Node* size_in_bytes,
+                                       AllocationFlags flags,
+                                       compiler::Node* top_adddress,
+                                       compiler::Node* limit_address);
+
+  static const int kElementLoopUnrollThreshold = 8;
+};
+
+}  // namespace internal
+}  // namespace v8
+#endif  // V8_CODE_STUB_ASSEMBLER_H_
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 1d2fb81..650e538 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -81,50 +81,14 @@
   HValue* BuildPushElement(HValue* object, HValue* argc,
                            HValue* argument_elements, ElementsKind kind);
 
-  enum ArgumentClass {
-    NONE,
-    SINGLE,
-    MULTIPLE
-  };
-
   HValue* UnmappedCase(HValue* elements, HValue* key, HValue* value);
   HValue* EmitKeyedSloppyArguments(HValue* receiver, HValue* key,
                                    HValue* value);
 
-  HValue* BuildArrayConstructor(ElementsKind kind,
-                                AllocationSiteOverrideMode override_mode,
-                                ArgumentClass argument_class);
-  HValue* BuildInternalArrayConstructor(ElementsKind kind,
-                                        ArgumentClass argument_class);
-
-  // BuildCheckAndInstallOptimizedCode emits code to install the optimized
-  // function found in the optimized code map at map_index in js_function, if
-  // the function at map_index matches the given native_context. Builder is
-  // left in the "Then()" state after the install.
-  void BuildCheckAndInstallOptimizedCode(HValue* js_function,
-                                         HValue* native_context,
-                                         IfBuilder* builder,
-                                         HValue* optimized_map,
-                                         HValue* map_index);
-  void BuildInstallOptimizedCode(HValue* js_function, HValue* native_context,
-                                 HValue* code_object, HValue* literals);
-  void BuildInstallCode(HValue* js_function, HValue* shared_info);
-
-  HInstruction* LoadFromOptimizedCodeMap(HValue* optimized_map,
-                                         HValue* iterator,
-                                         int field_offset);
-  void BuildInstallFromOptimizedCodeMap(HValue* js_function,
-                                        HValue* shared_info,
-                                        HValue* native_context);
-
   HValue* BuildToString(HValue* input, bool convert);
   HValue* BuildToPrimitive(HValue* input, HValue* input_map);
 
  private:
-  HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder);
-  HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder,
-                                          ElementsKind kind);
-
   base::SmartArrayPointer<HParameter*> parameters_;
   HValue* arguments_length_;
   CompilationInfo* info_;
@@ -298,8 +262,8 @@
     timer.Start();
   }
   Zone zone(isolate->allocator());
-  CompilationInfo info(CodeStub::MajorName(stub->MajorKey()), isolate, &zone,
-                       stub->GetCodeFlags());
+  CompilationInfo info(CStrVector(CodeStub::MajorName(stub->MajorKey())),
+                       isolate, &zone, stub->GetCodeFlags());
   // Parameter count is number of stack parameters.
   int parameter_count = descriptor.GetStackParameterCount();
   if (descriptor.function_mode() == NOT_JS_FUNCTION_STUB_MODE) {
@@ -463,7 +427,7 @@
         JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
     HValue* result =
         Add<HAllocate>(Add<HConstant>(result_size), HType::JSObject(),
-                       NOT_TENURED, JS_REGEXP_TYPE);
+                       NOT_TENURED, JS_REGEXP_TYPE, graph()->GetConstant0());
     Add<HStoreNamedField>(
         result, HObjectAccess::ForMap(),
         Add<HLoadNamedField>(boilerplate, nullptr, HObjectAccess::ForMap()));
@@ -503,9 +467,14 @@
   HValue* closure = GetParameter(0);
   HValue* literal_index = GetParameter(1);
 
+  // TODO(turbofan): This codestub has regressed to need a frame on ia32 at some
+  // point and wasn't caught since it wasn't built in the snapshot. We should
+  // probably just replace with a TurboFan stub rather than fixing it.
+#if !(V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87)
   // This stub is very performance sensitive, the generated code must be tuned
   // so that it doesn't build and eager frame.
   info()->MarkMustNotHaveEagerFrame();
+#endif
 
   HValue* literals_array = Add<HLoadNamedField>(
       closure, nullptr, HObjectAccess::ForLiteralsPointer());
@@ -570,87 +539,15 @@
 
 
 template <>
-HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
-  HValue* undefined = graph()->GetConstantUndefined();
-  HValue* closure = GetParameter(0);
-  HValue* literal_index = GetParameter(1);
-
-  HValue* literals_array = Add<HLoadNamedField>(
-      closure, nullptr, HObjectAccess::ForLiteralsPointer());
-
-  HInstruction* allocation_site = Add<HLoadKeyed>(
-      literals_array, literal_index, nullptr, nullptr, FAST_ELEMENTS,
-      NEVER_RETURN_HOLE, LiteralsArray::kOffsetToFirstLiteral - kHeapObjectTag);
-
-  IfBuilder checker(this);
-  checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site,
-                                                    undefined);
-  checker.And();
-
-  HObjectAccess access = HObjectAccess::ForAllocationSiteOffset(
-      AllocationSite::kTransitionInfoOffset);
-  HInstruction* boilerplate =
-      Add<HLoadNamedField>(allocation_site, nullptr, access);
-
-  int length = casted_stub()->length();
-  if (length == 0) {
-    // Empty objects have some slack added to them.
-    length = JSObject::kInitialGlobalObjectUnusedPropertiesCount;
-  }
-  int size = JSObject::kHeaderSize + length * kPointerSize;
-  int object_size = size;
-  if (FLAG_allocation_site_pretenuring) {
-    size += AllocationMemento::kSize;
-  }
-
-  HValue* boilerplate_map =
-      Add<HLoadNamedField>(boilerplate, nullptr, HObjectAccess::ForMap());
-  HValue* boilerplate_size = Add<HLoadNamedField>(
-      boilerplate_map, nullptr, HObjectAccess::ForMapInstanceSize());
-  HValue* size_in_words = Add<HConstant>(object_size >> kPointerSizeLog2);
-  checker.If<HCompareNumericAndBranch>(boilerplate_size,
-                                       size_in_words, Token::EQ);
-  checker.Then();
-
-  HValue* size_in_bytes = Add<HConstant>(size);
-
-  HInstruction* object = Add<HAllocate>(size_in_bytes, HType::JSObject(),
-      NOT_TENURED, JS_OBJECT_TYPE);
-
-  for (int i = 0; i < object_size; i += kPointerSize) {
-    HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(i);
-    Add<HStoreNamedField>(object, access,
-                          Add<HLoadNamedField>(boilerplate, nullptr, access));
-  }
-
-  DCHECK(FLAG_allocation_site_pretenuring || (size == object_size));
-  if (FLAG_allocation_site_pretenuring) {
-    BuildCreateAllocationMemento(
-        object, Add<HConstant>(object_size), allocation_site);
-  }
-
-  environment()->Push(object);
-  checker.ElseDeopt(Deoptimizer::kUninitializedBoilerplateInFastClone);
-  checker.End();
-
-  return environment()->Pop();
-}
-
-
-Handle<Code> FastCloneShallowObjectStub::GenerateCode() {
-  return DoGenerateCode(this);
-}
-
-
-template <>
 HValue* CodeStubGraphBuilder<CreateAllocationSiteStub>::BuildCodeStub() {
   // This stub is performance sensitive, the generated code must be tuned
   // so that it doesn't build an eager frame.
   info()->MarkMustNotHaveEagerFrame();
 
   HValue* size = Add<HConstant>(AllocationSite::kSize);
-  HInstruction* object = Add<HAllocate>(size, HType::JSObject(), TENURED,
-      JS_OBJECT_TYPE);
+  HInstruction* object =
+      Add<HAllocate>(size, HType::JSObject(), TENURED, JS_OBJECT_TYPE,
+                     graph()->GetConstant0());
 
   // Store the map
   Handle<Map> allocation_site_map = isolate()->factory()->allocation_site_map();
@@ -728,7 +625,8 @@
 
   HValue* size = Add<HConstant>(WeakCell::kSize);
   HInstruction* object =
-      Add<HAllocate>(size, HType::JSObject(), TENURED, JS_OBJECT_TYPE);
+      Add<HAllocate>(size, HType::JSObject(), TENURED, JS_OBJECT_TYPE,
+                     graph()->GetConstant0());
 
   Handle<Map> weak_cell_map = isolate()->factory()->weak_cell_map();
   AddStoreMapConstant(object, weak_cell_map);
@@ -801,7 +699,7 @@
         can_store.IfNot<HCompareMap>(argument,
                                      isolate()->factory()->heap_number_map());
       }
-      can_store.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
+      can_store.ThenDeopt(Deoptimizer::kFastPathFailed);
       can_store.End();
     }
     builder.EndBody();
@@ -852,19 +750,7 @@
     IfBuilder check(this);
     check.If<HCompareNumericAndBranch>(
         bits, Add<HConstant>(1 << Map::kIsExtensible), Token::NE);
-    check.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
-    check.End();
-  }
-
-  // Disallow pushing onto observed objects.
-  {
-    HValue* bit_field =
-        Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField());
-    HValue* mask = Add<HConstant>(1 << Map::kIsObserved);
-    HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field, mask);
-    IfBuilder check(this);
-    check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ);
-    check.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
+    check.ThenDeopt(Deoptimizer::kFastPathFailed);
     check.End();
   }
 
@@ -877,7 +763,7 @@
     HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field3, mask);
     IfBuilder check(this);
     check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ);
-    check.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
+    check.ThenDeopt(Deoptimizer::kFastPathFailed);
     check.End();
   }
 
@@ -895,7 +781,7 @@
     HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, details, mask);
     IfBuilder readonly(this);
     readonly.If<HCompareNumericAndBranch>(bit, mask, Token::EQ);
-    readonly.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
+    readonly.ThenDeopt(Deoptimizer::kFastPathFailed);
     readonly.End();
   }
 
@@ -923,14 +809,14 @@
     check_instance_type.If<HCompareNumericAndBranch>(
         instance_type, Add<HConstant>(LAST_CUSTOM_ELEMENTS_RECEIVER),
         Token::LTE);
-    check_instance_type.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
+    check_instance_type.ThenDeopt(Deoptimizer::kFastPathFailed);
     check_instance_type.End();
 
     HValue* elements = Add<HLoadNamedField>(
         prototype, nullptr, HObjectAccess::ForElementsPointer());
     IfBuilder no_elements(this);
     no_elements.IfNot<HCompareObjectEqAndBranch>(elements, empty);
-    no_elements.ThenDeopt(Deoptimizer::kFastArrayPushFailed);
+    no_elements.ThenDeopt(Deoptimizer::kFastPathFailed);
     no_elements.End();
 
     environment()->Push(prototype_map);
@@ -980,7 +866,7 @@
                                               FAST_HOLEY_DOUBLE_ELEMENTS);
         environment()->Push(new_length);
       }
-      has_double_elements.ElseDeopt(Deoptimizer::kFastArrayPushFailed);
+      has_double_elements.ElseDeopt(Deoptimizer::kFastPathFailed);
       has_double_elements.End();
     }
     has_object_elements.End();
@@ -993,6 +879,191 @@
 Handle<Code> FastArrayPushStub::GenerateCode() { return DoGenerateCode(this); }
 
 template <>
+HValue* CodeStubGraphBuilder<FastFunctionBindStub>::BuildCodeStub() {
+  // TODO(verwaest): Fix deoptimizer messages.
+  HValue* argc = GetArgumentsLength();
+  HInstruction* argument_elements = Add<HArgumentsElements>(false, false);
+  HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc,
+                                                 graph()->GetConstantMinus1());
+  BuildCheckHeapObject(object);
+  HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
+  Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_FUNCTION);
+
+  // Disallow binding of slow-mode functions. We need to figure out whether the
+  // length and name property are in the original state.
+  {
+    HValue* bit_field3 =
+        Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3());
+    HValue* mask = Add<HConstant>(static_cast<int>(Map::DictionaryMap::kMask));
+    HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field3, mask);
+    IfBuilder check(this);
+    check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ);
+    check.ThenDeopt(Deoptimizer::kFastPathFailed);
+    check.End();
+  }
+
+  // Check whether the length and name properties are still present as
+  // AccessorInfo objects. In that case, their value can be recomputed even if
+  // the actual value on the object changes.
+  {
+    HValue* descriptors =
+        Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapDescriptors());
+
+    HValue* descriptors_length = Add<HLoadNamedField>(
+        descriptors, nullptr, HObjectAccess::ForFixedArrayLength());
+    IfBuilder range(this);
+    range.If<HCompareNumericAndBranch>(descriptors_length,
+                                       graph()->GetConstant1(), Token::LTE);
+    range.ThenDeopt(Deoptimizer::kFastPathFailed);
+    range.End();
+
+    // Verify .length.
+    const int length_index = JSFunction::kLengthDescriptorIndex;
+    HValue* maybe_length = Add<HLoadKeyed>(
+        descriptors, Add<HConstant>(DescriptorArray::ToKeyIndex(length_index)),
+        nullptr, nullptr, FAST_ELEMENTS);
+    Unique<Name> length_string = Unique<Name>::CreateUninitialized(
+        isolate()->factory()->length_string());
+    Add<HCheckValue>(maybe_length, length_string, false);
+
+    HValue* maybe_length_accessor = Add<HLoadKeyed>(
+        descriptors,
+        Add<HConstant>(DescriptorArray::ToValueIndex(length_index)), nullptr,
+        nullptr, FAST_ELEMENTS);
+    BuildCheckHeapObject(maybe_length_accessor);
+    Add<HCheckMaps>(maybe_length_accessor,
+                    isolate()->factory()->accessor_info_map());
+
+    // Verify .name.
+    const int name_index = JSFunction::kNameDescriptorIndex;
+    HValue* maybe_name = Add<HLoadKeyed>(
+        descriptors, Add<HConstant>(DescriptorArray::ToKeyIndex(name_index)),
+        nullptr, nullptr, FAST_ELEMENTS);
+    Unique<Name> name_string =
+        Unique<Name>::CreateUninitialized(isolate()->factory()->name_string());
+    Add<HCheckValue>(maybe_name, name_string, false);
+
+    HValue* maybe_name_accessor = Add<HLoadKeyed>(
+        descriptors, Add<HConstant>(DescriptorArray::ToValueIndex(name_index)),
+        nullptr, nullptr, FAST_ELEMENTS);
+    BuildCheckHeapObject(maybe_name_accessor);
+    Add<HCheckMaps>(maybe_name_accessor,
+                    isolate()->factory()->accessor_info_map());
+  }
+
+  // Choose the right bound function map based on whether the target is
+  // constructable.
+  {
+    HValue* bit_field =
+        Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField());
+    HValue* mask = Add<HConstant>(static_cast<int>(1 << Map::kIsConstructor));
+    HValue* bits = AddUncasted<HBitwise>(Token::BIT_AND, bit_field, mask);
+
+    HValue* native_context = BuildGetNativeContext();
+    IfBuilder is_constructor(this);
+    is_constructor.If<HCompareNumericAndBranch>(bits, mask, Token::EQ);
+    is_constructor.Then();
+    {
+      HValue* map = Add<HLoadNamedField>(
+          native_context, nullptr,
+          HObjectAccess::ForContextSlot(
+              Context::BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX));
+      environment()->Push(map);
+    }
+    is_constructor.Else();
+    {
+      HValue* map = Add<HLoadNamedField>(
+          native_context, nullptr,
+          HObjectAccess::ForContextSlot(
+              Context::BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX));
+      environment()->Push(map);
+    }
+    is_constructor.End();
+  }
+  HValue* bound_function_map = environment()->Pop();
+
+  // Verify that __proto__ matches that of a the target bound function.
+  {
+    HValue* prototype =
+        Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForPrototype());
+    HValue* expected_prototype = Add<HLoadNamedField>(
+        bound_function_map, nullptr, HObjectAccess::ForPrototype());
+    IfBuilder equal_prototype(this);
+    equal_prototype.IfNot<HCompareObjectEqAndBranch>(prototype,
+                                                     expected_prototype);
+    equal_prototype.ThenDeopt(Deoptimizer::kFastPathFailed);
+    equal_prototype.End();
+  }
+
+  // Allocate the arguments array.
+  IfBuilder empty_args(this);
+  empty_args.If<HCompareNumericAndBranch>(argc, graph()->GetConstant1(),
+                                          Token::LTE);
+  empty_args.Then();
+  { environment()->Push(Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex)); }
+  empty_args.Else();
+  {
+    HValue* elements_length = AddUncasted<HSub>(argc, graph()->GetConstant1());
+    HValue* elements =
+        BuildAllocateAndInitializeArray(FAST_ELEMENTS, elements_length);
+
+    LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
+    HValue* start = graph()->GetConstant1();
+    HValue* key = builder.BeginBody(start, argc, Token::LT);
+    {
+      HValue* argument = Add<HAccessArgumentsAt>(argument_elements, argc, key);
+      HValue* index = AddUncasted<HSub>(key, graph()->GetConstant1());
+      AddElementAccess(elements, index, argument, elements, nullptr,
+                       FAST_ELEMENTS, STORE);
+    }
+    builder.EndBody();
+    environment()->Push(elements);
+  }
+  empty_args.End();
+  HValue* elements = environment()->Pop();
+
+  // Find the 'this' to bind.
+  IfBuilder no_receiver(this);
+  no_receiver.If<HCompareNumericAndBranch>(argc, graph()->GetConstant0(),
+                                           Token::EQ);
+  no_receiver.Then();
+  { environment()->Push(Add<HLoadRoot>(Heap::kUndefinedValueRootIndex)); }
+  no_receiver.Else();
+  {
+    environment()->Push(Add<HAccessArgumentsAt>(argument_elements, argc,
+                                                graph()->GetConstant0()));
+  }
+  no_receiver.End();
+  HValue* receiver = environment()->Pop();
+
+  // Allocate the resulting bound function.
+  HValue* size = Add<HConstant>(JSBoundFunction::kSize);
+  HValue* bound_function =
+      Add<HAllocate>(size, HType::JSObject(), NOT_TENURED,
+                     JS_BOUND_FUNCTION_TYPE, graph()->GetConstant0());
+  Add<HStoreNamedField>(bound_function, HObjectAccess::ForMap(),
+                        bound_function_map);
+  HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
+  Add<HStoreNamedField>(bound_function, HObjectAccess::ForPropertiesPointer(),
+                        empty_fixed_array);
+  Add<HStoreNamedField>(bound_function, HObjectAccess::ForElementsPointer(),
+                        empty_fixed_array);
+  Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundTargetFunction(),
+                        object);
+
+  Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundThis(),
+                        receiver);
+  Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundArguments(),
+                        elements);
+
+  return bound_function;
+}
+
+Handle<Code> FastFunctionBindStub::GenerateCode() {
+  return DoGenerateCode(this);
+}
+
+template <>
 HValue* CodeStubGraphBuilder<GrowArrayElementsStub>::BuildCodeStub() {
   ElementsKind kind = casted_stub()->elements_kind();
   if (IsFastDoubleElementsKind(kind)) {
@@ -1075,18 +1146,6 @@
 
 
 template <>
-HValue* CodeStubGraphBuilder<ArrayBufferViewLoadFieldStub>::BuildCodeStub() {
-  return BuildArrayBufferViewFieldAccessor(GetParameter(0), nullptr,
-                                           casted_stub()->index());
-}
-
-
-Handle<Code> ArrayBufferViewLoadFieldStub::GenerateCode() {
-  return DoGenerateCode(this);
-}
-
-
-template <>
 HValue* CodeStubGraphBuilder<LoadConstantStub>::BuildCodeStub() {
   HValue* map = AddLoadMap(GetParameter(0), NULL);
   HObjectAccess descriptors_access = HObjectAccess::ForObservableJSObjectOffset(
@@ -1272,7 +1331,7 @@
         // TODO(hpayer): Allocation site pretenuring support.
         HInstruction* heap_number =
             Add<HAllocate>(heap_number_size, HType::HeapObject(), NOT_TENURED,
-                           MUTABLE_HEAP_NUMBER_TYPE);
+                           MUTABLE_HEAP_NUMBER_TYPE, graph()->GetConstant0());
         AddStoreMapConstant(heap_number,
                             isolate()->factory()->mutable_heap_number_map());
         Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
@@ -1309,8 +1368,21 @@
 template <>
 HValue* CodeStubGraphBuilder<StoreTransitionStub>::BuildCodeStub() {
   HValue* object = GetParameter(StoreTransitionHelper::ReceiverIndex());
+  HValue* value = GetParameter(StoreTransitionHelper::ValueIndex());
+  StoreTransitionStub::StoreMode store_mode = casted_stub()->store_mode();
 
-  switch (casted_stub()->store_mode()) {
+  if (store_mode != StoreTransitionStub::StoreMapOnly) {
+    value = GetParameter(StoreTransitionHelper::ValueIndex());
+    Representation representation = casted_stub()->representation();
+    if (representation.IsDouble()) {
+      // In case we are storing a double, assure that the value is a double
+      // before manipulating the properties backing store. Otherwise the actual
+      // store may deopt, leaving the backing store in an overallocated state.
+      value = AddUncasted<HForceRepresentation>(value, representation);
+    }
+  }
+
+  switch (store_mode) {
     case StoreTransitionStub::ExtendStorageAndStoreMapAndValue: {
       HValue* properties = Add<HLoadNamedField>(
           object, nullptr, HObjectAccess::ForPropertiesPointer());
@@ -1338,9 +1410,8 @@
     // Fall through.
     case StoreTransitionStub::StoreMapAndValue:
       // Store the new value into the "extended" object.
-      BuildStoreNamedField(
-          object, GetParameter(StoreTransitionHelper::ValueIndex()),
-          casted_stub()->index(), casted_stub()->representation(), true);
+      BuildStoreNamedField(object, value, casted_stub()->index(),
+                           casted_stub()->representation(), true);
     // Fall through.
 
     case StoreTransitionStub::StoreMapOnly:
@@ -1349,7 +1420,7 @@
                             GetParameter(StoreTransitionHelper::MapIndex()));
       break;
   }
-  return GetParameter(StoreTransitionHelper::ValueIndex());
+  return value;
 }
 
 
@@ -1378,15 +1449,61 @@
 
 template <>
 HValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
+  ElementsKind const from_kind = casted_stub()->from_kind();
+  ElementsKind const to_kind = casted_stub()->to_kind();
+  HValue* const object = GetParameter(0);
+  HValue* const map = GetParameter(1);
+
+  // The {object} is known to be a JSObject (otherwise it wouldn't have elements
+  // anyways).
+  object->set_type(HType::JSObject());
+
   info()->MarkAsSavesCallerDoubles();
 
-  BuildTransitionElementsKind(GetParameter(0),
-                              GetParameter(1),
-                              casted_stub()->from_kind(),
-                              casted_stub()->to_kind(),
-                              casted_stub()->is_js_array());
+  DCHECK_IMPLIES(IsFastHoleyElementsKind(from_kind),
+                 IsFastHoleyElementsKind(to_kind));
 
-  return GetParameter(0);
+  if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) {
+    Add<HTrapAllocationMemento>(object);
+  }
+
+  if (!IsSimpleMapChangeTransition(from_kind, to_kind)) {
+    HInstruction* elements = AddLoadElements(object);
+
+    IfBuilder if_objecthaselements(this);
+    if_objecthaselements.IfNot<HCompareObjectEqAndBranch>(
+        elements, Add<HConstant>(isolate()->factory()->empty_fixed_array()));
+    if_objecthaselements.Then();
+    {
+      // Determine the elements capacity.
+      HInstruction* elements_length = AddLoadFixedArrayLength(elements);
+
+      // Determine the effective (array) length.
+      IfBuilder if_objectisarray(this);
+      if_objectisarray.If<HHasInstanceTypeAndBranch>(object, JS_ARRAY_TYPE);
+      if_objectisarray.Then();
+      {
+        // The {object} is a JSArray, load the special "length" property.
+        Push(Add<HLoadNamedField>(object, nullptr,
+                                  HObjectAccess::ForArrayLength(from_kind)));
+      }
+      if_objectisarray.Else();
+      {
+        // The {object} is some other JSObject.
+        Push(elements_length);
+      }
+      if_objectisarray.End();
+      HValue* length = Pop();
+
+      BuildGrowElementsCapacity(object, elements, from_kind, to_kind, length,
+                                elements_length);
+    }
+    if_objecthaselements.End();
+  }
+
+  Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
+
+  return object;
 }
 
 
@@ -1394,211 +1511,6 @@
   return DoGenerateCode(this);
 }
 
-
-template <>
-HValue* CodeStubGraphBuilder<AllocateInNewSpaceStub>::BuildCodeStub() {
-  HValue* result = Add<HAllocate>(GetParameter(0), HType::Tagged(), NOT_TENURED,
-                                  JS_OBJECT_TYPE);
-  return result;
-}
-
-
-Handle<Code> AllocateInNewSpaceStub::GenerateCode() {
-  return DoGenerateCode(this);
-}
-
-
-HValue* CodeStubGraphBuilderBase::BuildArrayConstructor(
-    ElementsKind kind,
-    AllocationSiteOverrideMode override_mode,
-    ArgumentClass argument_class) {
-  HValue* constructor = GetParameter(ArrayConstructorStubBase::kConstructor);
-  HValue* alloc_site = GetParameter(ArrayConstructorStubBase::kAllocationSite);
-  JSArrayBuilder array_builder(this, kind, alloc_site, constructor,
-                               override_mode);
-  HValue* result = NULL;
-  switch (argument_class) {
-    case NONE:
-      // This stub is very performance sensitive, the generated code must be
-      // tuned so that it doesn't build and eager frame.
-      info()->MarkMustNotHaveEagerFrame();
-      result = array_builder.AllocateEmptyArray();
-      break;
-    case SINGLE:
-      result = BuildArraySingleArgumentConstructor(&array_builder);
-      break;
-    case MULTIPLE:
-      result = BuildArrayNArgumentsConstructor(&array_builder, kind);
-      break;
-  }
-
-  return result;
-}
-
-
-HValue* CodeStubGraphBuilderBase::BuildInternalArrayConstructor(
-    ElementsKind kind, ArgumentClass argument_class) {
-  HValue* constructor = GetParameter(
-      InternalArrayConstructorStubBase::kConstructor);
-  JSArrayBuilder array_builder(this, kind, constructor);
-
-  HValue* result = NULL;
-  switch (argument_class) {
-    case NONE:
-      // This stub is very performance sensitive, the generated code must be
-      // tuned so that it doesn't build and eager frame.
-      info()->MarkMustNotHaveEagerFrame();
-      result = array_builder.AllocateEmptyArray();
-      break;
-    case SINGLE:
-      result = BuildArraySingleArgumentConstructor(&array_builder);
-      break;
-    case MULTIPLE:
-      result = BuildArrayNArgumentsConstructor(&array_builder, kind);
-      break;
-  }
-  return result;
-}
-
-
-HValue* CodeStubGraphBuilderBase::BuildArraySingleArgumentConstructor(
-    JSArrayBuilder* array_builder) {
-  // Smi check and range check on the input arg.
-  HValue* constant_one = graph()->GetConstant1();
-  HValue* constant_zero = graph()->GetConstant0();
-
-  HInstruction* elements = Add<HArgumentsElements>(false);
-  HInstruction* argument = Add<HAccessArgumentsAt>(
-      elements, constant_one, constant_zero);
-
-  return BuildAllocateArrayFromLength(array_builder, argument);
-}
-
-
-HValue* CodeStubGraphBuilderBase::BuildArrayNArgumentsConstructor(
-    JSArrayBuilder* array_builder, ElementsKind kind) {
-  // Insert a bounds check because the number of arguments might exceed
-  // the kInitialMaxFastElementArray limit. This cannot happen for code
-  // that was parsed, but calling via Array.apply(thisArg, [...]) might
-  // trigger it.
-  HValue* length = GetArgumentsLength();
-  HConstant* max_alloc_length =
-      Add<HConstant>(JSArray::kInitialMaxFastElementArray);
-  HValue* checked_length = Add<HBoundsCheck>(length, max_alloc_length);
-
-  // We need to fill with the hole if it's a smi array in the multi-argument
-  // case because we might have to bail out while copying arguments into
-  // the array because they aren't compatible with a smi array.
-  // If it's a double array, no problem, and if it's fast then no
-  // problem either because doubles are boxed.
-  //
-  // TODO(mvstanton): consider an instruction to memset fill the array
-  // with zero in this case instead.
-  JSArrayBuilder::FillMode fill_mode = IsFastSmiElementsKind(kind)
-      ? JSArrayBuilder::FILL_WITH_HOLE
-      : JSArrayBuilder::DONT_FILL_WITH_HOLE;
-  HValue* new_object = array_builder->AllocateArray(checked_length,
-                                                    max_alloc_length,
-                                                    checked_length,
-                                                    fill_mode);
-  HValue* elements = array_builder->GetElementsLocation();
-  DCHECK(elements != NULL);
-
-  // Now populate the elements correctly.
-  LoopBuilder builder(this,
-                      context(),
-                      LoopBuilder::kPostIncrement);
-  HValue* start = graph()->GetConstant0();
-  HValue* key = builder.BeginBody(start, checked_length, Token::LT);
-  HInstruction* argument_elements = Add<HArgumentsElements>(false);
-  HInstruction* argument = Add<HAccessArgumentsAt>(
-      argument_elements, checked_length, key);
-
-  Add<HStoreKeyed>(elements, key, argument, nullptr, kind);
-  builder.EndBody();
-  return new_object;
-}
-
-
-template <>
-HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() {
-  ElementsKind kind = casted_stub()->elements_kind();
-  AllocationSiteOverrideMode override_mode = casted_stub()->override_mode();
-  return BuildArrayConstructor(kind, override_mode, NONE);
-}
-
-
-Handle<Code> ArrayNoArgumentConstructorStub::GenerateCode() {
-  return DoGenerateCode(this);
-}
-
-
-template <>
-HValue* CodeStubGraphBuilder<ArraySingleArgumentConstructorStub>::
-    BuildCodeStub() {
-  ElementsKind kind = casted_stub()->elements_kind();
-  AllocationSiteOverrideMode override_mode = casted_stub()->override_mode();
-  return BuildArrayConstructor(kind, override_mode, SINGLE);
-}
-
-
-Handle<Code> ArraySingleArgumentConstructorStub::GenerateCode() {
-  return DoGenerateCode(this);
-}
-
-
-template <>
-HValue* CodeStubGraphBuilder<ArrayNArgumentsConstructorStub>::BuildCodeStub() {
-  ElementsKind kind = casted_stub()->elements_kind();
-  AllocationSiteOverrideMode override_mode = casted_stub()->override_mode();
-  return BuildArrayConstructor(kind, override_mode, MULTIPLE);
-}
-
-
-Handle<Code> ArrayNArgumentsConstructorStub::GenerateCode() {
-  return DoGenerateCode(this);
-}
-
-
-template <>
-HValue* CodeStubGraphBuilder<InternalArrayNoArgumentConstructorStub>::
-    BuildCodeStub() {
-  ElementsKind kind = casted_stub()->elements_kind();
-  return BuildInternalArrayConstructor(kind, NONE);
-}
-
-
-Handle<Code> InternalArrayNoArgumentConstructorStub::GenerateCode() {
-  return DoGenerateCode(this);
-}
-
-
-template <>
-HValue* CodeStubGraphBuilder<InternalArraySingleArgumentConstructorStub>::
-    BuildCodeStub() {
-  ElementsKind kind = casted_stub()->elements_kind();
-  return BuildInternalArrayConstructor(kind, SINGLE);
-}
-
-
-Handle<Code> InternalArraySingleArgumentConstructorStub::GenerateCode() {
-  return DoGenerateCode(this);
-}
-
-
-template <>
-HValue* CodeStubGraphBuilder<InternalArrayNArgumentsConstructorStub>::
-    BuildCodeStub() {
-  ElementsKind kind = casted_stub()->elements_kind();
-  return BuildInternalArrayConstructor(kind, MULTIPLE);
-}
-
-
-Handle<Code> InternalArrayNArgumentsConstructorStub::GenerateCode() {
-  return DoGenerateCode(this);
-}
-
-
 template <>
 HValue* CodeStubGraphBuilder<BinaryOpICStub>::BuildCodeInitializedStub() {
   BinaryOpICState state = casted_stub()->state();
@@ -1746,9 +1658,9 @@
       // Convert the primitive to a string value.
       ToStringStub stub(isolate());
       HValue* values[] = {context(), Pop()};
-      Push(AddUncasted<HCallWithDescriptor>(
-          Add<HConstant>(stub.GetCode()), 0, stub.GetCallInterfaceDescriptor(),
-          Vector<HValue*>(values, arraysize(values))));
+      Push(AddUncasted<HCallWithDescriptor>(Add<HConstant>(stub.GetCode()), 0,
+                                            stub.GetCallInterfaceDescriptor(),
+                                            ArrayVector(values)));
     }
     if_inputisstring.End();
   }
@@ -2013,188 +1925,14 @@
 Handle<Code> ToObjectStub::GenerateCode() { return DoGenerateCode(this); }
 
 
-void CodeStubGraphBuilderBase::BuildCheckAndInstallOptimizedCode(
-    HValue* js_function,
-    HValue* native_context,
-    IfBuilder* builder,
-    HValue* optimized_map,
-    HValue* map_index) {
-  HValue* osr_ast_id_none = Add<HConstant>(BailoutId::None().ToInt());
-  HValue* context_slot = LoadFromOptimizedCodeMap(
-      optimized_map, map_index, SharedFunctionInfo::kContextOffset);
-  context_slot = Add<HLoadNamedField>(context_slot, nullptr,
-                                      HObjectAccess::ForWeakCellValue());
-  HValue* osr_ast_slot = LoadFromOptimizedCodeMap(
-      optimized_map, map_index, SharedFunctionInfo::kOsrAstIdOffset);
-  HValue* code_object = LoadFromOptimizedCodeMap(
-      optimized_map, map_index, SharedFunctionInfo::kCachedCodeOffset);
-  code_object = Add<HLoadNamedField>(code_object, nullptr,
-                                     HObjectAccess::ForWeakCellValue());
-  builder->If<HCompareObjectEqAndBranch>(native_context,
-                                         context_slot);
-  builder->AndIf<HCompareObjectEqAndBranch>(osr_ast_slot, osr_ast_id_none);
-  builder->And();
-  builder->IfNot<HCompareObjectEqAndBranch>(code_object,
-                                            graph()->GetConstant0());
-  builder->Then();
-  HValue* literals = LoadFromOptimizedCodeMap(optimized_map,
-      map_index, SharedFunctionInfo::kLiteralsOffset);
-  literals = Add<HLoadNamedField>(literals, nullptr,
-                                  HObjectAccess::ForWeakCellValue());
-  IfBuilder maybe_deopt(this);
-  maybe_deopt.If<HCompareObjectEqAndBranch>(literals, graph()->GetConstant0());
-  maybe_deopt.ThenDeopt(Deoptimizer::kLiteralsWereDisposed);
-  maybe_deopt.End();
-
-  BuildInstallOptimizedCode(js_function, native_context, code_object, literals);
-
-  // The builder continues in the "then" after this function.
-}
-
-
-void CodeStubGraphBuilderBase::BuildInstallOptimizedCode(HValue* js_function,
-                                                         HValue* native_context,
-                                                         HValue* code_object,
-                                                         HValue* literals) {
-  Counters* counters = isolate()->counters();
-  AddIncrementCounter(counters->fast_new_closure_install_optimized());
-
-  // TODO(fschneider): Idea: store proper code pointers in the optimized code
-  // map and either unmangle them on marking or do nothing as the whole map is
-  // discarded on major GC anyway.
-  Add<HStoreCodeEntry>(js_function, code_object);
-  Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(),
-                        literals);
-
-  // Now link a function into a list of optimized functions.
-  HValue* optimized_functions_list = Add<HLoadNamedField>(
-      native_context, nullptr,
-      HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST));
-  Add<HStoreNamedField>(js_function,
-                        HObjectAccess::ForNextFunctionLinkPointer(),
-                        optimized_functions_list);
-
-  // This store is the only one that should have a write barrier.
-  Add<HStoreNamedField>(native_context,
-           HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST),
-           js_function);
-}
-
-
-void CodeStubGraphBuilderBase::BuildInstallCode(HValue* js_function,
-                                                HValue* shared_info) {
-  Add<HStoreNamedField>(js_function,
-                        HObjectAccess::ForNextFunctionLinkPointer(),
-                        graph()->GetConstantUndefined());
-  HValue* code_object = Add<HLoadNamedField>(shared_info, nullptr,
-                                             HObjectAccess::ForCodeOffset());
-  Add<HStoreCodeEntry>(js_function, code_object);
-}
-
-
-HInstruction* CodeStubGraphBuilderBase::LoadFromOptimizedCodeMap(
-    HValue* optimized_map,
-    HValue* iterator,
-    int field_offset) {
-  // By making sure to express these loads in the form [<hvalue> + constant]
-  // the keyed load can be hoisted.
-  DCHECK(field_offset >= 0 && field_offset < SharedFunctionInfo::kEntryLength);
-  HValue* field_slot = iterator;
-  if (field_offset > 0) {
-    HValue* field_offset_value = Add<HConstant>(field_offset);
-    field_slot = AddUncasted<HAdd>(iterator, field_offset_value);
-  }
-  HInstruction* field_entry = Add<HLoadKeyed>(optimized_map, field_slot,
-                                              nullptr, nullptr, FAST_ELEMENTS);
-  return field_entry;
-}
-
-
-void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap(
-    HValue* js_function,
-    HValue* shared_info,
-    HValue* native_context) {
-  Counters* counters = isolate()->counters();
-  Factory* factory = isolate()->factory();
-  IfBuilder is_optimized(this);
-  HInstruction* optimized_map = Add<HLoadNamedField>(
-      shared_info, nullptr, HObjectAccess::ForOptimizedCodeMap());
-  HValue* null_constant = Add<HConstant>(0);
-  is_optimized.If<HCompareObjectEqAndBranch>(optimized_map, null_constant);
-  is_optimized.Then();
-  {
-    BuildInstallCode(js_function, shared_info);
-  }
-  is_optimized.Else();
-  {
-    AddIncrementCounter(counters->fast_new_closure_try_optimized());
-    // The {optimized_map} points to fixed array of 4-element entries:
-    //   (native context, optimized code, literals, ast-id).
-    // Iterate through the {optimized_map} backwards. After the loop, if no
-    // matching optimized code was found, install unoptimized code.
-    //   for(i = map.length() - SharedFunctionInfo::kEntryLength;
-    //       i >= SharedFunctionInfo::kEntriesStart;
-    //       i -= SharedFunctionInfo::kEntryLength) { ... }
-    HValue* first_entry_index =
-        Add<HConstant>(SharedFunctionInfo::kEntriesStart);
-    HValue* shared_function_entry_length =
-        Add<HConstant>(SharedFunctionInfo::kEntryLength);
-    LoopBuilder loop_builder(this, context(), LoopBuilder::kPostDecrement,
-                             shared_function_entry_length);
-    HValue* array_length = Add<HLoadNamedField>(
-        optimized_map, nullptr, HObjectAccess::ForFixedArrayLength());
-    HValue* start_pos =
-        AddUncasted<HSub>(array_length, shared_function_entry_length);
-    HValue* slot_iterator =
-        loop_builder.BeginBody(start_pos, first_entry_index, Token::GTE);
-    {
-      IfBuilder done_check(this);
-      BuildCheckAndInstallOptimizedCode(js_function, native_context,
-                                        &done_check, optimized_map,
-                                        slot_iterator);
-      // Fall out of the loop
-      loop_builder.Break();
-    }
-    loop_builder.EndBody();
-
-    // If {slot_iterator} is less than the first entry index, then we failed to
-    // find a context-dependent code and try context-independent code next.
-    IfBuilder no_optimized_code_check(this);
-    no_optimized_code_check.If<HCompareNumericAndBranch>(
-        slot_iterator, first_entry_index, Token::LT);
-    no_optimized_code_check.Then();
-    {
-      IfBuilder shared_code_check(this);
-      HValue* shared_code =
-          Add<HLoadNamedField>(optimized_map, nullptr,
-                               HObjectAccess::ForOptimizedCodeMapSharedCode());
-      shared_code = Add<HLoadNamedField>(shared_code, nullptr,
-                                         HObjectAccess::ForWeakCellValue());
-      shared_code_check.IfNot<HCompareObjectEqAndBranch>(
-          shared_code, graph()->GetConstant0());
-      shared_code_check.Then();
-      {
-        // Store the context-independent optimized code.
-        HValue* literals = Add<HConstant>(factory->empty_fixed_array());
-        BuildInstallOptimizedCode(js_function, native_context, shared_code,
-                                  literals);
-      }
-      shared_code_check.Else();
-      {
-        // Store the unoptimized code.
-        BuildInstallCode(js_function, shared_info);
-      }
-    }
-  }
-}
-
-
 template<>
 HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() {
   Counters* counters = isolate()->counters();
   Factory* factory = isolate()->factory();
   HInstruction* empty_fixed_array =
       Add<HConstant>(factory->empty_fixed_array());
+  HInstruction* empty_literals_array =
+      Add<HConstant>(factory->empty_literals_array());
   HValue* shared_info = GetParameter(0);
 
   AddIncrementCounter(counters->fast_new_closure_total());
@@ -2202,7 +1940,8 @@
   // Create a new closure from the given function info in new space
   HValue* size = Add<HConstant>(JSFunction::kSize);
   HInstruction* js_function =
-      Add<HAllocate>(size, HType::JSObject(), NOT_TENURED, JS_FUNCTION_TYPE);
+      Add<HAllocate>(size, HType::JSObject(), NOT_TENURED, JS_FUNCTION_TYPE,
+                     graph()->GetConstant0());
 
   int map_index = Context::FunctionMapIndex(casted_stub()->language_mode(),
                                             casted_stub()->kind());
@@ -2220,7 +1959,7 @@
   Add<HStoreNamedField>(js_function, HObjectAccess::ForElementsPointer(),
                         empty_fixed_array);
   Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(),
-                        empty_fixed_array);
+                        empty_literals_array);
   Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(),
                         graph()->GetConstantHole());
   Add<HStoreNamedField>(
@@ -2228,10 +1967,13 @@
   Add<HStoreNamedField>(js_function, HObjectAccess::ForFunctionContextPointer(),
                         context());
 
-  // Initialize the code pointer in the function to be the one found in the
-  // shared function info object. But first check if there is an optimized
-  // version for our context.
-  BuildInstallFromOptimizedCodeMap(js_function, shared_info, native_context);
+  Handle<Code> lazy_builtin(
+      isolate()->builtins()->builtin(Builtins::kCompileLazy));
+  HConstant* lazy = Add<HConstant>(lazy_builtin);
+  Add<HStoreCodeEntry>(js_function, lazy);
+  Add<HStoreNamedField>(js_function,
+                        HObjectAccess::ForNextFunctionLinkPointer(),
+                        graph()->GetConstantUndefined());
 
   return js_function;
 }
@@ -2252,7 +1994,8 @@
   // Allocate the context in new space.
   HAllocate* function_context = Add<HAllocate>(
       Add<HConstant>(length * kPointerSize + FixedArray::kHeaderSize),
-      HType::HeapObject(), NOT_TENURED, FIXED_ARRAY_TYPE);
+      HType::HeapObject(), NOT_TENURED, FIXED_ARRAY_TYPE,
+      graph()->GetConstant0());
 
   // Set up the object header.
   AddStoreMapConstant(function_context,
@@ -2323,7 +2066,12 @@
   HValue* index = GetParameter(RegExpConstructResultStub::kIndex);
   HValue* input = GetParameter(RegExpConstructResultStub::kInput);
 
+  // TODO(turbofan): This codestub has regressed to need a frame on ia32 at some
+  // point and wasn't caught since it wasn't built in the snapshot. We should
+  // probably just replace with a TurboFan stub rather than fixing it.
+#if !(V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87)
   info()->MarkMustNotHaveEagerFrame();
+#endif
 
   return BuildRegExpConstructResult(length, index, input);
 }
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index 60b350c..ae3adb7 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -8,14 +8,13 @@
 
 #include "src/bootstrapper.h"
 #include "src/code-factory.h"
-#include "src/compiler/code-stub-assembler.h"
+#include "src/code-stub-assembler.h"
 #include "src/factory.h"
 #include "src/gdb-jit.h"
 #include "src/ic/handler-compiler.h"
 #include "src/ic/ic.h"
 #include "src/macro-assembler.h"
 #include "src/parsing/parser.h"
-#include "src/profiler/cpu-profiler.h"
 
 namespace v8 {
 namespace internal {
@@ -83,8 +82,8 @@
   std::ostringstream os;
   os << *this;
   PROFILE(isolate(),
-          CodeCreateEvent(Logger::STUB_TAG, AbstractCode::cast(*code),
-                          os.str().c_str()));
+          CodeCreateEvent(CodeEventListener::STUB_TAG,
+                          AbstractCode::cast(*code), os.str().c_str()));
   Counters* counters = isolate()->counters();
   counters->total_stubs_code_size()->Increment(code->instruction_size());
 #ifdef DEBUG
@@ -99,8 +98,7 @@
 
 
 Code::Flags CodeStub::GetCodeFlags() const {
-  return Code::ComputeFlags(GetCodeKind(), GetICState(), GetExtraICState(),
-                            GetStubType());
+  return Code::ComputeFlags(GetCodeKind(), GetExtraICState());
 }
 
 
@@ -135,11 +133,7 @@
   CodeDesc desc;
   masm.GetCode(&desc);
   // Copy the generated code into a heap object.
-  Code::Flags flags = Code::ComputeFlags(
-      GetCodeKind(),
-      GetICState(),
-      GetExtraICState(),
-      GetStubType());
+  Code::Flags flags = Code::ComputeFlags(GetCodeKind(), GetExtraICState());
   Handle<Code> new_object = factory->NewCode(
       desc, flags, masm.CodeObject(), NeedsImmovableCode());
   return new_object;
@@ -377,45 +371,6 @@
 }
 
 
-void CompareICStub::AddToSpecialCache(Handle<Code> new_object) {
-  DCHECK(*known_map_ != NULL);
-  Isolate* isolate = new_object->GetIsolate();
-  Factory* factory = isolate->factory();
-  return Map::UpdateCodeCache(known_map_,
-                              strict() ?
-                                  factory->strict_compare_ic_string() :
-                                  factory->compare_ic_string(),
-                              new_object);
-}
-
-
-bool CompareICStub::FindCodeInSpecialCache(Code** code_out) {
-  Factory* factory = isolate()->factory();
-  Code::Flags flags = Code::ComputeFlags(
-      GetCodeKind(),
-      UNINITIALIZED);
-  Handle<Object> probe(
-      known_map_->FindInCodeCache(
-        strict() ?
-            *factory->strict_compare_ic_string() :
-            *factory->compare_ic_string(),
-        flags),
-      isolate());
-  if (probe->IsCode()) {
-    *code_out = Code::cast(*probe);
-#ifdef DEBUG
-    CompareICStub decode((*code_out)->stub_key(), isolate());
-    DCHECK(op() == decode.op());
-    DCHECK(left() == decode.left());
-    DCHECK(right() == decode.right());
-    DCHECK(state() == decode.state());
-#endif
-    return true;
-  }
-  return false;
-}
-
-
 void CompareICStub::Generate(MacroAssembler* masm) {
   switch (state()) {
     case CompareICState::UNINITIALIZED:
@@ -452,41 +407,81 @@
   }
 }
 
-
 Handle<Code> TurboFanCodeStub::GenerateCode() {
   const char* name = CodeStub::MajorName(MajorKey());
   Zone zone(isolate()->allocator());
   CallInterfaceDescriptor descriptor(GetCallInterfaceDescriptor());
-  compiler::CodeStubAssembler assembler(isolate(), &zone, descriptor,
-                                        GetCodeFlags(), name);
+  CodeStubAssembler assembler(isolate(), &zone, descriptor, GetCodeFlags(),
+                              name);
   GenerateAssembly(&assembler);
   return assembler.GenerateCode();
 }
 
+void LoadICTrampolineTFStub::GenerateAssembly(
+    CodeStubAssembler* assembler) const {
+  typedef compiler::Node Node;
+
+  Node* receiver = assembler->Parameter(0);
+  Node* name = assembler->Parameter(1);
+  Node* slot = assembler->Parameter(2);
+  Node* context = assembler->Parameter(3);
+  Node* vector = assembler->LoadTypeFeedbackVectorForStub();
+
+  CodeStubAssembler::LoadICParameters p(context, receiver, name, slot, vector);
+  assembler->LoadIC(&p);
+}
+
+void LoadICTFStub::GenerateAssembly(CodeStubAssembler* assembler) const {
+  typedef compiler::Node Node;
+
+  Node* receiver = assembler->Parameter(0);
+  Node* name = assembler->Parameter(1);
+  Node* slot = assembler->Parameter(2);
+  Node* vector = assembler->Parameter(3);
+  Node* context = assembler->Parameter(4);
+
+  CodeStubAssembler::LoadICParameters p(context, receiver, name, slot, vector);
+  assembler->LoadIC(&p);
+}
+
+void LoadGlobalICTrampolineStub::GenerateAssembly(
+    CodeStubAssembler* assembler) const {
+  typedef compiler::Node Node;
+
+  Node* slot = assembler->Parameter(0);
+  Node* context = assembler->Parameter(1);
+  Node* vector = assembler->LoadTypeFeedbackVectorForStub();
+
+  CodeStubAssembler::LoadICParameters p(context, nullptr, nullptr, slot,
+                                        vector);
+  assembler->LoadGlobalIC(&p);
+}
+
+void LoadGlobalICStub::GenerateAssembly(CodeStubAssembler* assembler) const {
+  typedef compiler::Node Node;
+
+  Node* slot = assembler->Parameter(0);
+  Node* vector = assembler->Parameter(1);
+  Node* context = assembler->Parameter(2);
+
+  CodeStubAssembler::LoadICParameters p(context, nullptr, nullptr, slot,
+                                        vector);
+  assembler->LoadGlobalIC(&p);
+}
+
 void AllocateHeapNumberStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
+    CodeStubAssembler* assembler) const {
   typedef compiler::Node Node;
 
   Node* result = assembler->AllocateHeapNumber();
   assembler->Return(result);
 }
 
-void AllocateMutableHeapNumberStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
-  typedef compiler::Node Node;
-
-  Node* result = assembler->Allocate(HeapNumber::kSize);
-  assembler->StoreMapNoWriteBarrier(
-      result,
-      assembler->HeapConstant(isolate()->factory()->mutable_heap_number_map()));
-  assembler->Return(result);
-}
-
 #define SIMD128_GEN_ASM(TYPE, Type, type, lane_count, lane_type)            \
-  void Allocate##Type##Stub::GenerateAssembly(                              \
-      compiler::CodeStubAssembler* assembler) const {                       \
-    compiler::Node* result = assembler->Allocate(                           \
-        Simd128Value::kSize, compiler::CodeStubAssembler::kNone);           \
+  void Allocate##Type##Stub::GenerateAssembly(CodeStubAssembler* assembler) \
+      const {                                                               \
+    compiler::Node* result =                                                \
+        assembler->Allocate(Simd128Value::kSize, CodeStubAssembler::kNone); \
     compiler::Node* map_offset =                                            \
         assembler->IntPtrConstant(HeapObject::kMapOffset - kHeapObjectTag); \
     compiler::Node* map = assembler->IntPtrAdd(result, map_offset);         \
@@ -498,8 +493,7 @@
 SIMD128_TYPES(SIMD128_GEN_ASM)
 #undef SIMD128_GEN_ASM
 
-void StringLengthStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
+void StringLengthStub::GenerateAssembly(CodeStubAssembler* assembler) const {
   compiler::Node* value = assembler->Parameter(0);
   compiler::Node* string =
       assembler->LoadObjectField(value, JSValue::kValueOffset);
@@ -508,12 +502,13 @@
   assembler->Return(result);
 }
 
-void AddStub::GenerateAssembly(compiler::CodeStubAssembler* assembler) const {
-  typedef compiler::CodeStubAssembler::Label Label;
+// static
+compiler::Node* AddStub::Generate(CodeStubAssembler* assembler,
+                                  compiler::Node* left, compiler::Node* right,
+                                  compiler::Node* context) {
+  typedef CodeStubAssembler::Label Label;
   typedef compiler::Node Node;
-  typedef compiler::CodeStubAssembler::Variable Variable;
-
-  Node* context = assembler->Parameter(2);
+  typedef CodeStubAssembler::Variable Variable;
 
   // Shared entry for floating point addition.
   Label do_fadd(assembler);
@@ -523,11 +518,14 @@
   // We might need to loop several times due to ToPrimitive, ToString and/or
   // ToNumber conversions.
   Variable var_lhs(assembler, MachineRepresentation::kTagged),
-      var_rhs(assembler, MachineRepresentation::kTagged);
+      var_rhs(assembler, MachineRepresentation::kTagged),
+      var_result(assembler, MachineRepresentation::kTagged);
   Variable* loop_vars[2] = {&var_lhs, &var_rhs};
-  Label loop(assembler, 2, loop_vars);
-  var_lhs.Bind(assembler->Parameter(0));
-  var_rhs.Bind(assembler->Parameter(1));
+  Label loop(assembler, 2, loop_vars), end(assembler),
+      string_add_convert_left(assembler, Label::kDeferred),
+      string_add_convert_right(assembler, Label::kDeferred);
+  var_lhs.Bind(left);
+  var_rhs.Bind(right);
   assembler->Goto(&loop);
   assembler->Bind(&loop);
   {
@@ -564,7 +562,8 @@
         }
 
         assembler->Bind(&if_notoverflow);
-        assembler->Return(assembler->Projection(0, pair));
+        var_result.Bind(assembler->Projection(0, pair));
+        assembler->Goto(&end);
       }
 
       assembler->Bind(&if_rhsisnotsmi);
@@ -601,11 +600,9 @@
 
           assembler->Bind(&if_rhsisstring);
           {
-            // Convert {lhs}, which is a Smi, to a String and concatenate the
-            // resulting string with the String {rhs}.
-            Callable callable = CodeFactory::StringAdd(
-                assembler->isolate(), STRING_ADD_CONVERT_LEFT, NOT_TENURED);
-            assembler->TailCallStub(callable, context, lhs, rhs);
+            var_lhs.Bind(lhs);
+            var_rhs.Bind(rhs);
+            assembler->Goto(&string_add_convert_left);
           }
 
           assembler->Bind(&if_rhsisnotstring);
@@ -655,11 +652,9 @@
 
       assembler->Bind(&if_lhsisstring);
       {
-        // Convert {rhs} to a String (using the sequence of ToPrimitive with
-        // no hint followed by ToString) and concatenate the strings.
-        Callable callable = CodeFactory::StringAdd(
-            assembler->isolate(), STRING_ADD_CONVERT_RIGHT, NOT_TENURED);
-        assembler->TailCallStub(callable, context, lhs, rhs);
+        var_lhs.Bind(lhs);
+        var_rhs.Bind(rhs);
+        assembler->Goto(&string_add_convert_right);
       }
 
       assembler->Bind(&if_lhsisnotstring);
@@ -733,11 +728,9 @@
 
           assembler->Bind(&if_rhsisstring);
           {
-            // Convert {lhs} to a String (using the sequence of ToPrimitive with
-            // no hint followed by ToString) and concatenate the strings.
-            Callable callable = CodeFactory::StringAdd(
-                assembler->isolate(), STRING_ADD_CONVERT_LEFT, NOT_TENURED);
-            assembler->TailCallStub(callable, context, lhs, rhs);
+            var_lhs.Bind(lhs);
+            var_rhs.Bind(rhs);
+            assembler->Goto(&string_add_convert_left);
           }
 
           assembler->Bind(&if_rhsisnotstring);
@@ -853,6 +846,27 @@
       }
     }
   }
+  assembler->Bind(&string_add_convert_left);
+  {
+    // Convert {lhs}, which is a Smi, to a String and concatenate the
+    // resulting string with the String {rhs}.
+    Callable callable = CodeFactory::StringAdd(
+        assembler->isolate(), STRING_ADD_CONVERT_LEFT, NOT_TENURED);
+    var_result.Bind(assembler->CallStub(callable, context, var_lhs.value(),
+                                        var_rhs.value()));
+    assembler->Goto(&end);
+  }
+
+  assembler->Bind(&string_add_convert_right);
+  {
+    // Convert {lhs}, which is a Smi, to a String and concatenate the
+    // resulting string with the String {rhs}.
+    Callable callable = CodeFactory::StringAdd(
+        assembler->isolate(), STRING_ADD_CONVERT_RIGHT, NOT_TENURED);
+    var_result.Bind(assembler->CallStub(callable, context, var_lhs.value(),
+                                        var_rhs.value()));
+    assembler->Goto(&end);
+  }
 
   assembler->Bind(&do_fadd);
   {
@@ -860,31 +874,36 @@
     Node* rhs_value = var_fadd_rhs.value();
     Node* value = assembler->Float64Add(lhs_value, rhs_value);
     Node* result = assembler->ChangeFloat64ToTagged(value);
-    assembler->Return(result);
+    var_result.Bind(result);
+    assembler->Goto(&end);
   }
+  assembler->Bind(&end);
+  return var_result.value();
 }
 
-void SubtractStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
-  typedef compiler::CodeStubAssembler::Label Label;
+// static
+compiler::Node* SubtractStub::Generate(CodeStubAssembler* assembler,
+                                       compiler::Node* left,
+                                       compiler::Node* right,
+                                       compiler::Node* context) {
+  typedef CodeStubAssembler::Label Label;
   typedef compiler::Node Node;
-  typedef compiler::CodeStubAssembler::Variable Variable;
-
-  Node* context = assembler->Parameter(2);
+  typedef CodeStubAssembler::Variable Variable;
 
   // Shared entry for floating point subtraction.
-  Label do_fsub(assembler);
+  Label do_fsub(assembler), end(assembler);
   Variable var_fsub_lhs(assembler, MachineRepresentation::kFloat64),
       var_fsub_rhs(assembler, MachineRepresentation::kFloat64);
 
   // We might need to loop several times due to ToPrimitive and/or ToNumber
   // conversions.
   Variable var_lhs(assembler, MachineRepresentation::kTagged),
-      var_rhs(assembler, MachineRepresentation::kTagged);
+      var_rhs(assembler, MachineRepresentation::kTagged),
+      var_result(assembler, MachineRepresentation::kTagged);
   Variable* loop_vars[2] = {&var_lhs, &var_rhs};
   Label loop(assembler, 2, loop_vars);
-  var_lhs.Bind(assembler->Parameter(0));
-  var_rhs.Bind(assembler->Parameter(1));
+  var_lhs.Bind(left);
+  var_rhs.Bind(right);
   assembler->Goto(&loop);
   assembler->Bind(&loop);
   {
@@ -922,7 +941,8 @@
         }
 
         assembler->Bind(&if_notoverflow);
-        assembler->Return(assembler->Projection(0, pair));
+        var_result.Bind(assembler->Projection(0, pair));
+        assembler->Goto(&end);
       }
 
       assembler->Bind(&if_rhsisnotsmi);
@@ -948,7 +968,8 @@
         assembler->Bind(&if_rhsisnotnumber);
         {
           // Convert the {rhs} to a Number first.
-          Callable callable = CodeFactory::NonNumberToNumber(isolate());
+          Callable callable =
+              CodeFactory::NonNumberToNumber(assembler->isolate());
           var_rhs.Bind(assembler->CallStub(callable, context, rhs));
           assembler->Goto(&loop);
         }
@@ -1004,7 +1025,8 @@
           assembler->Bind(&if_rhsisnotnumber);
           {
             // Convert the {rhs} to a Number first.
-            Callable callable = CodeFactory::NonNumberToNumber(isolate());
+            Callable callable =
+                CodeFactory::NonNumberToNumber(assembler->isolate());
             var_rhs.Bind(assembler->CallStub(callable, context, rhs));
             assembler->Goto(&loop);
           }
@@ -1014,7 +1036,8 @@
       assembler->Bind(&if_lhsisnotnumber);
       {
         // Convert the {lhs} to a Number first.
-        Callable callable = CodeFactory::NonNumberToNumber(isolate());
+        Callable callable =
+            CodeFactory::NonNumberToNumber(assembler->isolate());
         var_lhs.Bind(assembler->CallStub(callable, context, lhs));
         assembler->Goto(&loop);
       }
@@ -1026,51 +1049,843 @@
     Node* lhs_value = var_fsub_lhs.value();
     Node* rhs_value = var_fsub_rhs.value();
     Node* value = assembler->Float64Sub(lhs_value, rhs_value);
+    var_result.Bind(assembler->ChangeFloat64ToTagged(value));
+    assembler->Goto(&end);
+  }
+  assembler->Bind(&end);
+  return var_result.value();
+}
+
+// static
+compiler::Node* MultiplyStub::Generate(CodeStubAssembler* assembler,
+                                       compiler::Node* left,
+                                       compiler::Node* right,
+                                       compiler::Node* context) {
+  using compiler::Node;
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
+
+  // Shared entry point for floating point multiplication.
+  Label do_fmul(assembler);
+  Variable var_lhs_float64(assembler, MachineRepresentation::kFloat64),
+      var_rhs_float64(assembler, MachineRepresentation::kFloat64);
+
+  Node* number_map = assembler->HeapNumberMapConstant();
+
+  // We might need to loop one or two times due to ToNumber conversions.
+  Variable var_lhs(assembler, MachineRepresentation::kTagged),
+      var_rhs(assembler, MachineRepresentation::kTagged);
+  Variable* loop_variables[] = {&var_lhs, &var_rhs};
+  Label loop(assembler, 2, loop_variables);
+  var_lhs.Bind(left);
+  var_rhs.Bind(right);
+  assembler->Goto(&loop);
+  assembler->Bind(&loop);
+  {
+    Node* lhs = var_lhs.value();
+    Node* rhs = var_rhs.value();
+
+    Label lhs_is_smi(assembler), lhs_is_not_smi(assembler);
+    assembler->Branch(assembler->WordIsSmi(lhs), &lhs_is_smi, &lhs_is_not_smi);
+
+    assembler->Bind(&lhs_is_smi);
+    {
+      Label rhs_is_smi(assembler), rhs_is_not_smi(assembler);
+      assembler->Branch(assembler->WordIsSmi(rhs), &rhs_is_smi,
+                        &rhs_is_not_smi);
+
+      assembler->Bind(&rhs_is_smi);
+      {
+        // Both {lhs} and {rhs} are Smis. Convert them to double and multiply.
+        // TODO(epertoso): use SmiMulWithOverflow once available.
+        var_lhs_float64.Bind(assembler->SmiToFloat64(lhs));
+        var_rhs_float64.Bind(assembler->SmiToFloat64(rhs));
+        assembler->Goto(&do_fmul);
+      }
+
+      assembler->Bind(&rhs_is_not_smi);
+      {
+        Node* rhs_map = assembler->LoadMap(rhs);
+
+        // Check if {rhs} is a HeapNumber.
+        Label rhs_is_number(assembler),
+            rhs_is_not_number(assembler, Label::kDeferred);
+        assembler->Branch(assembler->WordEqual(rhs_map, number_map),
+                          &rhs_is_number, &rhs_is_not_number);
+
+        assembler->Bind(&rhs_is_number);
+        {
+          // Convert {lhs} to a double and multiply it with the value of {rhs}.
+          var_lhs_float64.Bind(assembler->SmiToFloat64(lhs));
+          var_rhs_float64.Bind(assembler->LoadHeapNumberValue(rhs));
+          assembler->Goto(&do_fmul);
+        }
+
+        assembler->Bind(&rhs_is_not_number);
+        {
+          // Multiplication is commutative, swap {lhs} with {rhs} and loop.
+          var_lhs.Bind(rhs);
+          var_rhs.Bind(lhs);
+          assembler->Goto(&loop);
+        }
+      }
+    }
+
+    assembler->Bind(&lhs_is_not_smi);
+    {
+      Node* lhs_map = assembler->LoadMap(lhs);
+
+      // Check if {lhs} is a HeapNumber.
+      Label lhs_is_number(assembler),
+          lhs_is_not_number(assembler, Label::kDeferred);
+      assembler->Branch(assembler->WordEqual(lhs_map, number_map),
+                        &lhs_is_number, &lhs_is_not_number);
+
+      assembler->Bind(&lhs_is_number);
+      {
+        // Check if {rhs} is a Smi.
+        Label rhs_is_smi(assembler), rhs_is_not_smi(assembler);
+        assembler->Branch(assembler->WordIsSmi(rhs), &rhs_is_smi,
+                          &rhs_is_not_smi);
+
+        assembler->Bind(&rhs_is_smi);
+        {
+          // Convert {rhs} to a double and multiply it with the value of {lhs}.
+          var_lhs_float64.Bind(assembler->LoadHeapNumberValue(lhs));
+          var_rhs_float64.Bind(assembler->SmiToFloat64(rhs));
+          assembler->Goto(&do_fmul);
+        }
+
+        assembler->Bind(&rhs_is_not_smi);
+        {
+          Node* rhs_map = assembler->LoadMap(rhs);
+
+          // Check if {rhs} is a HeapNumber.
+          Label rhs_is_number(assembler),
+              rhs_is_not_number(assembler, Label::kDeferred);
+          assembler->Branch(assembler->WordEqual(rhs_map, number_map),
+                            &rhs_is_number, &rhs_is_not_number);
+
+          assembler->Bind(&rhs_is_number);
+          {
+            // Both {lhs} and {rhs} are HeapNumbers. Load their values and
+            // multiply them.
+            var_lhs_float64.Bind(assembler->LoadHeapNumberValue(lhs));
+            var_rhs_float64.Bind(assembler->LoadHeapNumberValue(rhs));
+            assembler->Goto(&do_fmul);
+          }
+
+          assembler->Bind(&rhs_is_not_number);
+          {
+            // Multiplication is commutative, swap {lhs} with {rhs} and loop.
+            var_lhs.Bind(rhs);
+            var_rhs.Bind(lhs);
+            assembler->Goto(&loop);
+          }
+        }
+      }
+
+      assembler->Bind(&lhs_is_not_number);
+      {
+        // Convert {lhs} to a Number and loop.
+        Callable callable =
+            CodeFactory::NonNumberToNumber(assembler->isolate());
+        var_lhs.Bind(assembler->CallStub(callable, context, lhs));
+        assembler->Goto(&loop);
+      }
+    }
+  }
+
+  assembler->Bind(&do_fmul);
+  {
+    Node* value =
+        assembler->Float64Mul(var_lhs_float64.value(), var_rhs_float64.value());
     Node* result = assembler->ChangeFloat64ToTagged(value);
-    assembler->Return(result);
+    return result;
   }
 }
 
-void BitwiseAndStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
+// static
+compiler::Node* DivideStub::Generate(CodeStubAssembler* assembler,
+                                     compiler::Node* left,
+                                     compiler::Node* right,
+                                     compiler::Node* context) {
+  using compiler::Node;
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
+
+  // Shared entry point for floating point division.
+  Label do_fdiv(assembler), end(assembler);
+  Variable var_dividend_float64(assembler, MachineRepresentation::kFloat64),
+      var_divisor_float64(assembler, MachineRepresentation::kFloat64);
+
+  Node* number_map = assembler->HeapNumberMapConstant();
+
+  // We might need to loop one or two times due to ToNumber conversions.
+  Variable var_dividend(assembler, MachineRepresentation::kTagged),
+      var_divisor(assembler, MachineRepresentation::kTagged),
+      var_result(assembler, MachineRepresentation::kTagged);
+  Variable* loop_variables[] = {&var_dividend, &var_divisor};
+  Label loop(assembler, 2, loop_variables);
+  var_dividend.Bind(left);
+  var_divisor.Bind(right);
+  assembler->Goto(&loop);
+  assembler->Bind(&loop);
+  {
+    Node* dividend = var_dividend.value();
+    Node* divisor = var_divisor.value();
+
+    Label dividend_is_smi(assembler), dividend_is_not_smi(assembler);
+    assembler->Branch(assembler->WordIsSmi(dividend), &dividend_is_smi,
+                      &dividend_is_not_smi);
+
+    assembler->Bind(&dividend_is_smi);
+    {
+      Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
+      assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
+                        &divisor_is_not_smi);
+
+      assembler->Bind(&divisor_is_smi);
+      {
+        Label bailout(assembler);
+
+        // Do floating point division if {divisor} is zero.
+        assembler->GotoIf(
+            assembler->WordEqual(divisor, assembler->IntPtrConstant(0)),
+            &bailout);
+
+        // Do floating point division {dividend} is zero and {divisor} is
+        // negative.
+        Label dividend_is_zero(assembler), dividend_is_not_zero(assembler);
+        assembler->Branch(
+            assembler->WordEqual(dividend, assembler->IntPtrConstant(0)),
+            &dividend_is_zero, &dividend_is_not_zero);
+
+        assembler->Bind(&dividend_is_zero);
+        {
+          assembler->GotoIf(
+              assembler->IntPtrLessThan(divisor, assembler->IntPtrConstant(0)),
+              &bailout);
+          assembler->Goto(&dividend_is_not_zero);
+        }
+        assembler->Bind(&dividend_is_not_zero);
+
+        Node* untagged_divisor = assembler->SmiUntag(divisor);
+        Node* untagged_dividend = assembler->SmiUntag(dividend);
+
+        // Do floating point division if {dividend} is kMinInt (or kMinInt - 1
+        // if the Smi size is 31) and {divisor} is -1.
+        Label divisor_is_minus_one(assembler),
+            divisor_is_not_minus_one(assembler);
+        assembler->Branch(assembler->Word32Equal(untagged_divisor,
+                                                 assembler->Int32Constant(-1)),
+                          &divisor_is_minus_one, &divisor_is_not_minus_one);
+
+        assembler->Bind(&divisor_is_minus_one);
+        {
+          assembler->GotoIf(
+              assembler->Word32Equal(
+                  untagged_dividend,
+                  assembler->Int32Constant(
+                      kSmiValueSize == 32 ? kMinInt : (kMinInt >> 1))),
+              &bailout);
+          assembler->Goto(&divisor_is_not_minus_one);
+        }
+        assembler->Bind(&divisor_is_not_minus_one);
+
+        // TODO(epertoso): consider adding a machine instruction that returns
+        // both the result and the remainder.
+        Node* untagged_result =
+            assembler->Int32Div(untagged_dividend, untagged_divisor);
+        Node* truncated =
+            assembler->IntPtrMul(untagged_result, untagged_divisor);
+        // Do floating point division if the remainder is not 0.
+        assembler->GotoIf(
+            assembler->Word32NotEqual(untagged_dividend, truncated), &bailout);
+        var_result.Bind(assembler->SmiTag(untagged_result));
+        assembler->Goto(&end);
+
+        // Bailout: convert {dividend} and {divisor} to double and do double
+        // division.
+        assembler->Bind(&bailout);
+        {
+          var_dividend_float64.Bind(assembler->SmiToFloat64(dividend));
+          var_divisor_float64.Bind(assembler->SmiToFloat64(divisor));
+          assembler->Goto(&do_fdiv);
+        }
+      }
+
+      assembler->Bind(&divisor_is_not_smi);
+      {
+        Node* divisor_map = assembler->LoadMap(divisor);
+
+        // Check if {divisor} is a HeapNumber.
+        Label divisor_is_number(assembler),
+            divisor_is_not_number(assembler, Label::kDeferred);
+        assembler->Branch(assembler->WordEqual(divisor_map, number_map),
+                          &divisor_is_number, &divisor_is_not_number);
+
+        assembler->Bind(&divisor_is_number);
+        {
+          // Convert {dividend} to a double and divide it with the value of
+          // {divisor}.
+          var_dividend_float64.Bind(assembler->SmiToFloat64(dividend));
+          var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
+          assembler->Goto(&do_fdiv);
+        }
+
+        assembler->Bind(&divisor_is_not_number);
+        {
+          // Convert {divisor} to a number and loop.
+          Callable callable =
+              CodeFactory::NonNumberToNumber(assembler->isolate());
+          var_divisor.Bind(assembler->CallStub(callable, context, divisor));
+          assembler->Goto(&loop);
+        }
+      }
+    }
+
+    assembler->Bind(&dividend_is_not_smi);
+    {
+      Node* dividend_map = assembler->LoadMap(dividend);
+
+      // Check if {dividend} is a HeapNumber.
+      Label dividend_is_number(assembler),
+          dividend_is_not_number(assembler, Label::kDeferred);
+      assembler->Branch(assembler->WordEqual(dividend_map, number_map),
+                        &dividend_is_number, &dividend_is_not_number);
+
+      assembler->Bind(&dividend_is_number);
+      {
+        // Check if {divisor} is a Smi.
+        Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
+        assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
+                          &divisor_is_not_smi);
+
+        assembler->Bind(&divisor_is_smi);
+        {
+          // Convert {divisor} to a double and use it for a floating point
+          // division.
+          var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
+          var_divisor_float64.Bind(assembler->SmiToFloat64(divisor));
+          assembler->Goto(&do_fdiv);
+        }
+
+        assembler->Bind(&divisor_is_not_smi);
+        {
+          Node* divisor_map = assembler->LoadMap(divisor);
+
+          // Check if {divisor} is a HeapNumber.
+          Label divisor_is_number(assembler),
+              divisor_is_not_number(assembler, Label::kDeferred);
+          assembler->Branch(assembler->WordEqual(divisor_map, number_map),
+                            &divisor_is_number, &divisor_is_not_number);
+
+          assembler->Bind(&divisor_is_number);
+          {
+            // Both {dividend} and {divisor} are HeapNumbers. Load their values
+            // and divide them.
+            var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
+            var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
+            assembler->Goto(&do_fdiv);
+          }
+
+          assembler->Bind(&divisor_is_not_number);
+          {
+            // Convert {divisor} to a number and loop.
+            Callable callable =
+                CodeFactory::NonNumberToNumber(assembler->isolate());
+            var_divisor.Bind(assembler->CallStub(callable, context, divisor));
+            assembler->Goto(&loop);
+          }
+        }
+      }
+
+      assembler->Bind(&dividend_is_not_number);
+      {
+        // Convert {dividend} to a Number and loop.
+        Callable callable =
+            CodeFactory::NonNumberToNumber(assembler->isolate());
+        var_dividend.Bind(assembler->CallStub(callable, context, dividend));
+        assembler->Goto(&loop);
+      }
+    }
+  }
+
+  assembler->Bind(&do_fdiv);
+  {
+    Node* value = assembler->Float64Div(var_dividend_float64.value(),
+                                        var_divisor_float64.value());
+    var_result.Bind(assembler->ChangeFloat64ToTagged(value));
+    assembler->Goto(&end);
+  }
+  assembler->Bind(&end);
+  return var_result.value();
+}
+
+// static
+compiler::Node* ModulusStub::Generate(CodeStubAssembler* assembler,
+                                      compiler::Node* left,
+                                      compiler::Node* right,
+                                      compiler::Node* context) {
+  using compiler::Node;
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
+
+  // Shared entry point for floating point modulus.
+  Label do_fmod(assembler);
+  Variable var_dividend_float64(assembler, MachineRepresentation::kFloat64),
+      var_divisor_float64(assembler, MachineRepresentation::kFloat64);
+
+  Node* number_map = assembler->HeapNumberMapConstant();
+
+  // We might need to loop one or two times due to ToNumber conversions.
+  Variable var_dividend(assembler, MachineRepresentation::kTagged),
+      var_divisor(assembler, MachineRepresentation::kTagged);
+  Variable* loop_variables[] = {&var_dividend, &var_divisor};
+  Label loop(assembler, 2, loop_variables);
+  var_dividend.Bind(left);
+  var_divisor.Bind(right);
+  assembler->Goto(&loop);
+  assembler->Bind(&loop);
+  {
+    Node* dividend = var_dividend.value();
+    Node* divisor = var_divisor.value();
+
+    Label dividend_is_smi(assembler), dividend_is_not_smi(assembler);
+    assembler->Branch(assembler->WordIsSmi(dividend), &dividend_is_smi,
+                      &dividend_is_not_smi);
+
+    assembler->Bind(&dividend_is_smi);
+    {
+      Label dividend_is_not_zero(assembler);
+      Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
+      assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
+                        &divisor_is_not_smi);
+
+      assembler->Bind(&divisor_is_smi);
+      {
+        var_dividend_float64.Bind(assembler->SmiToFloat64(dividend));
+        var_divisor_float64.Bind(assembler->SmiToFloat64(divisor));
+        assembler->Goto(&do_fmod);
+      }
+
+      assembler->Bind(&divisor_is_not_smi);
+      {
+        Node* divisor_map = assembler->LoadMap(divisor);
+
+        // Check if {divisor} is a HeapNumber.
+        Label divisor_is_number(assembler),
+            divisor_is_not_number(assembler, Label::kDeferred);
+        assembler->Branch(assembler->WordEqual(divisor_map, number_map),
+                          &divisor_is_number, &divisor_is_not_number);
+
+        assembler->Bind(&divisor_is_number);
+        {
+          // Convert {dividend} to a double and compute its modulus with the
+          // value of {dividend}.
+          var_dividend_float64.Bind(assembler->SmiToFloat64(dividend));
+          var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
+          assembler->Goto(&do_fmod);
+        }
+
+        assembler->Bind(&divisor_is_not_number);
+        {
+          // Convert {divisor} to a number and loop.
+          Callable callable =
+              CodeFactory::NonNumberToNumber(assembler->isolate());
+          var_divisor.Bind(assembler->CallStub(callable, context, divisor));
+          assembler->Goto(&loop);
+        }
+      }
+    }
+
+    assembler->Bind(&dividend_is_not_smi);
+    {
+      Node* dividend_map = assembler->LoadMap(dividend);
+
+      // Check if {dividend} is a HeapNumber.
+      Label dividend_is_number(assembler),
+          dividend_is_not_number(assembler, Label::kDeferred);
+      assembler->Branch(assembler->WordEqual(dividend_map, number_map),
+                        &dividend_is_number, &dividend_is_not_number);
+
+      assembler->Bind(&dividend_is_number);
+      {
+        // Check if {divisor} is a Smi.
+        Label divisor_is_smi(assembler), divisor_is_not_smi(assembler);
+        assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi,
+                          &divisor_is_not_smi);
+
+        assembler->Bind(&divisor_is_smi);
+        {
+          // Convert {divisor} to a double and compute {dividend}'s modulus with
+          // it.
+          var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
+          var_divisor_float64.Bind(assembler->SmiToFloat64(divisor));
+          assembler->Goto(&do_fmod);
+        }
+
+        assembler->Bind(&divisor_is_not_smi);
+        {
+          Node* divisor_map = assembler->LoadMap(divisor);
+
+          // Check if {divisor} is a HeapNumber.
+          Label divisor_is_number(assembler),
+              divisor_is_not_number(assembler, Label::kDeferred);
+          assembler->Branch(assembler->WordEqual(divisor_map, number_map),
+                            &divisor_is_number, &divisor_is_not_number);
+
+          assembler->Bind(&divisor_is_number);
+          {
+            // Both {dividend} and {divisor} are HeapNumbers. Load their values
+            // and compute their modulus.
+            var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend));
+            var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor));
+            assembler->Goto(&do_fmod);
+          }
+
+          assembler->Bind(&divisor_is_not_number);
+          {
+            // Convert {divisor} to a number and loop.
+            Callable callable =
+                CodeFactory::NonNumberToNumber(assembler->isolate());
+            var_divisor.Bind(assembler->CallStub(callable, context, divisor));
+            assembler->Goto(&loop);
+          }
+        }
+      }
+
+      assembler->Bind(&dividend_is_not_number);
+      {
+        // Convert {dividend} to a Number and loop.
+        Callable callable =
+            CodeFactory::NonNumberToNumber(assembler->isolate());
+        var_dividend.Bind(assembler->CallStub(callable, context, dividend));
+        assembler->Goto(&loop);
+      }
+    }
+  }
+
+  assembler->Bind(&do_fmod);
+  {
+    Node* value = assembler->Float64Mod(var_dividend_float64.value(),
+                                        var_divisor_float64.value());
+    Node* result = assembler->ChangeFloat64ToTagged(value);
+    return result;
+  }
+}
+
+// static
+compiler::Node* ShiftLeftStub::Generate(CodeStubAssembler* assembler,
+                                        compiler::Node* left,
+                                        compiler::Node* right,
+                                        compiler::Node* context) {
   using compiler::Node;
 
-  Node* lhs = assembler->Parameter(0);
-  Node* rhs = assembler->Parameter(1);
-  Node* context = assembler->Parameter(2);
-  Node* lhs_value = assembler->TruncateTaggedToWord32(context, lhs);
-  Node* rhs_value = assembler->TruncateTaggedToWord32(context, rhs);
+  Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
+  Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
+  Node* shift_count =
+      assembler->Word32And(rhs_value, assembler->Int32Constant(0x1f));
+  Node* value = assembler->Word32Shl(lhs_value, shift_count);
+  Node* result = assembler->ChangeInt32ToTagged(value);
+  return result;
+}
+
+// static
+compiler::Node* ShiftRightStub::Generate(CodeStubAssembler* assembler,
+                                         compiler::Node* left,
+                                         compiler::Node* right,
+                                         compiler::Node* context) {
+  using compiler::Node;
+
+  Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
+  Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
+  Node* shift_count =
+      assembler->Word32And(rhs_value, assembler->Int32Constant(0x1f));
+  Node* value = assembler->Word32Sar(lhs_value, shift_count);
+  Node* result = assembler->ChangeInt32ToTagged(value);
+  return result;
+}
+
+// static
+compiler::Node* ShiftRightLogicalStub::Generate(CodeStubAssembler* assembler,
+                                                compiler::Node* left,
+                                                compiler::Node* right,
+                                                compiler::Node* context) {
+  using compiler::Node;
+
+  Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
+  Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
+  Node* shift_count =
+      assembler->Word32And(rhs_value, assembler->Int32Constant(0x1f));
+  Node* value = assembler->Word32Shr(lhs_value, shift_count);
+  Node* result = assembler->ChangeUint32ToTagged(value);
+  return result;
+}
+
+// static
+compiler::Node* BitwiseAndStub::Generate(CodeStubAssembler* assembler,
+                                         compiler::Node* left,
+                                         compiler::Node* right,
+                                         compiler::Node* context) {
+  using compiler::Node;
+
+  Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
+  Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
   Node* value = assembler->Word32And(lhs_value, rhs_value);
   Node* result = assembler->ChangeInt32ToTagged(value);
-  assembler->Return(result);
+  return result;
 }
 
-void BitwiseOrStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
+// static
+compiler::Node* BitwiseOrStub::Generate(CodeStubAssembler* assembler,
+                                        compiler::Node* left,
+                                        compiler::Node* right,
+                                        compiler::Node* context) {
   using compiler::Node;
 
-  Node* lhs = assembler->Parameter(0);
-  Node* rhs = assembler->Parameter(1);
-  Node* context = assembler->Parameter(2);
-  Node* lhs_value = assembler->TruncateTaggedToWord32(context, lhs);
-  Node* rhs_value = assembler->TruncateTaggedToWord32(context, rhs);
+  Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
+  Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
   Node* value = assembler->Word32Or(lhs_value, rhs_value);
   Node* result = assembler->ChangeInt32ToTagged(value);
-  assembler->Return(result);
+  return result;
 }
 
-void BitwiseXorStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
+// static
+compiler::Node* BitwiseXorStub::Generate(CodeStubAssembler* assembler,
+                                         compiler::Node* left,
+                                         compiler::Node* right,
+                                         compiler::Node* context) {
   using compiler::Node;
 
-  Node* lhs = assembler->Parameter(0);
-  Node* rhs = assembler->Parameter(1);
-  Node* context = assembler->Parameter(2);
-  Node* lhs_value = assembler->TruncateTaggedToWord32(context, lhs);
-  Node* rhs_value = assembler->TruncateTaggedToWord32(context, rhs);
+  Node* lhs_value = assembler->TruncateTaggedToWord32(context, left);
+  Node* rhs_value = assembler->TruncateTaggedToWord32(context, right);
   Node* value = assembler->Word32Xor(lhs_value, rhs_value);
   Node* result = assembler->ChangeInt32ToTagged(value);
-  assembler->Return(result);
+  return result;
+}
+
+// static
+compiler::Node* IncStub::Generate(CodeStubAssembler* assembler,
+                                  compiler::Node* value,
+                                  compiler::Node* context) {
+  typedef CodeStubAssembler::Label Label;
+  typedef compiler::Node Node;
+  typedef CodeStubAssembler::Variable Variable;
+
+  // Shared entry for floating point increment.
+  Label do_finc(assembler), end(assembler);
+  Variable var_finc_value(assembler, MachineRepresentation::kFloat64);
+
+  // We might need to try again due to ToNumber conversion.
+  Variable value_var(assembler, MachineRepresentation::kTagged);
+  Variable result_var(assembler, MachineRepresentation::kTagged);
+  Label start(assembler, &value_var);
+  value_var.Bind(value);
+  assembler->Goto(&start);
+  assembler->Bind(&start);
+  {
+    value = value_var.value();
+
+    Label if_issmi(assembler), if_isnotsmi(assembler);
+    assembler->Branch(assembler->WordIsSmi(value), &if_issmi, &if_isnotsmi);
+
+    assembler->Bind(&if_issmi);
+    {
+      // Try fast Smi addition first.
+      Node* one = assembler->SmiConstant(Smi::FromInt(1));
+      Node* pair = assembler->SmiAddWithOverflow(value, one);
+      Node* overflow = assembler->Projection(1, pair);
+
+      // Check if the Smi additon overflowed.
+      Label if_overflow(assembler), if_notoverflow(assembler);
+      assembler->Branch(overflow, &if_overflow, &if_notoverflow);
+
+      assembler->Bind(&if_notoverflow);
+      result_var.Bind(assembler->Projection(0, pair));
+      assembler->Goto(&end);
+
+      assembler->Bind(&if_overflow);
+      {
+        var_finc_value.Bind(assembler->SmiToFloat64(value));
+        assembler->Goto(&do_finc);
+      }
+    }
+
+    assembler->Bind(&if_isnotsmi);
+    {
+      // Check if the value is a HeapNumber.
+      Label if_valueisnumber(assembler),
+          if_valuenotnumber(assembler, Label::kDeferred);
+      Node* value_map = assembler->LoadMap(value);
+      Node* number_map = assembler->HeapNumberMapConstant();
+      assembler->Branch(assembler->WordEqual(value_map, number_map),
+                        &if_valueisnumber, &if_valuenotnumber);
+
+      assembler->Bind(&if_valueisnumber);
+      {
+        // Load the HeapNumber value.
+        var_finc_value.Bind(assembler->LoadHeapNumberValue(value));
+        assembler->Goto(&do_finc);
+      }
+
+      assembler->Bind(&if_valuenotnumber);
+      {
+        // Convert to a Number first and try again.
+        Callable callable =
+            CodeFactory::NonNumberToNumber(assembler->isolate());
+        value_var.Bind(assembler->CallStub(callable, context, value));
+        assembler->Goto(&start);
+      }
+    }
+  }
+
+  assembler->Bind(&do_finc);
+  {
+    Node* finc_value = var_finc_value.value();
+    Node* one = assembler->Float64Constant(1.0);
+    Node* finc_result = assembler->Float64Add(finc_value, one);
+    result_var.Bind(assembler->ChangeFloat64ToTagged(finc_result));
+    assembler->Goto(&end);
+  }
+
+  assembler->Bind(&end);
+  return result_var.value();
+}
+
+// static
+compiler::Node* DecStub::Generate(CodeStubAssembler* assembler,
+                                  compiler::Node* value,
+                                  compiler::Node* context) {
+  typedef CodeStubAssembler::Label Label;
+  typedef compiler::Node Node;
+  typedef CodeStubAssembler::Variable Variable;
+
+  // Shared entry for floating point decrement.
+  Label do_fdec(assembler), end(assembler);
+  Variable var_fdec_value(assembler, MachineRepresentation::kFloat64);
+
+  // We might need to try again due to ToNumber conversion.
+  Variable value_var(assembler, MachineRepresentation::kTagged);
+  Variable result_var(assembler, MachineRepresentation::kTagged);
+  Label start(assembler, &value_var);
+  value_var.Bind(value);
+  assembler->Goto(&start);
+  assembler->Bind(&start);
+  {
+    value = value_var.value();
+
+    Label if_issmi(assembler), if_isnotsmi(assembler);
+    assembler->Branch(assembler->WordIsSmi(value), &if_issmi, &if_isnotsmi);
+
+    assembler->Bind(&if_issmi);
+    {
+      // Try fast Smi subtraction first.
+      Node* one = assembler->SmiConstant(Smi::FromInt(1));
+      Node* pair = assembler->SmiSubWithOverflow(value, one);
+      Node* overflow = assembler->Projection(1, pair);
+
+      // Check if the Smi subtraction overflowed.
+      Label if_overflow(assembler), if_notoverflow(assembler);
+      assembler->Branch(overflow, &if_overflow, &if_notoverflow);
+
+      assembler->Bind(&if_notoverflow);
+      result_var.Bind(assembler->Projection(0, pair));
+      assembler->Goto(&end);
+
+      assembler->Bind(&if_overflow);
+      {
+        var_fdec_value.Bind(assembler->SmiToFloat64(value));
+        assembler->Goto(&do_fdec);
+      }
+    }
+
+    assembler->Bind(&if_isnotsmi);
+    {
+      // Check if the value is a HeapNumber.
+      Label if_valueisnumber(assembler),
+          if_valuenotnumber(assembler, Label::kDeferred);
+      Node* value_map = assembler->LoadMap(value);
+      Node* number_map = assembler->HeapNumberMapConstant();
+      assembler->Branch(assembler->WordEqual(value_map, number_map),
+                        &if_valueisnumber, &if_valuenotnumber);
+
+      assembler->Bind(&if_valueisnumber);
+      {
+        // Load the HeapNumber value.
+        var_fdec_value.Bind(assembler->LoadHeapNumberValue(value));
+        assembler->Goto(&do_fdec);
+      }
+
+      assembler->Bind(&if_valuenotnumber);
+      {
+        // Convert to a Number first and try again.
+        Callable callable =
+            CodeFactory::NonNumberToNumber(assembler->isolate());
+        value_var.Bind(assembler->CallStub(callable, context, value));
+        assembler->Goto(&start);
+      }
+    }
+  }
+
+  assembler->Bind(&do_fdec);
+  {
+    Node* fdec_value = var_fdec_value.value();
+    Node* one = assembler->Float64Constant(1.0);
+    Node* fdec_result = assembler->Float64Sub(fdec_value, one);
+    result_var.Bind(assembler->ChangeFloat64ToTagged(fdec_result));
+    assembler->Goto(&end);
+  }
+
+  assembler->Bind(&end);
+  return result_var.value();
+}
+
+// static
+compiler::Node* InstanceOfStub::Generate(CodeStubAssembler* assembler,
+                                         compiler::Node* object,
+                                         compiler::Node* callable,
+                                         compiler::Node* context) {
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
+
+  Label return_runtime(assembler, Label::kDeferred), end(assembler);
+  Variable result(assembler, MachineRepresentation::kTagged);
+
+  // Check if no one installed @@hasInstance somewhere.
+  assembler->GotoUnless(
+      assembler->WordEqual(
+          assembler->LoadObjectField(
+              assembler->LoadRoot(Heap::kHasInstanceProtectorRootIndex),
+              PropertyCell::kValueOffset),
+          assembler->SmiConstant(Smi::FromInt(Isolate::kArrayProtectorValid))),
+      &return_runtime);
+
+  // Check if {callable} is a valid receiver.
+  assembler->GotoIf(assembler->WordIsSmi(callable), &return_runtime);
+  assembler->GotoIf(
+      assembler->Word32Equal(
+          assembler->Word32And(
+              assembler->LoadMapBitField(assembler->LoadMap(callable)),
+              assembler->Int32Constant(1 << Map::kIsCallable)),
+          assembler->Int32Constant(0)),
+      &return_runtime);
+
+  // Use the inline OrdinaryHasInstance directly.
+  result.Bind(assembler->OrdinaryHasInstance(context, callable, object));
+  assembler->Goto(&end);
+
+  // TODO(bmeurer): Use GetPropertyStub here once available.
+  assembler->Bind(&return_runtime);
+  {
+    result.Bind(assembler->CallRuntime(Runtime::kInstanceOf, context, object,
+                                       callable));
+    assembler->Goto(&end);
+  }
+
+  assembler->Bind(&end);
+  return result.value();
 }
 
 namespace {
@@ -1082,15 +1897,15 @@
   kGreaterThanOrEqual
 };
 
-void GenerateAbstractRelationalComparison(
-    compiler::CodeStubAssembler* assembler, RelationalComparisonMode mode) {
-  typedef compiler::CodeStubAssembler::Label Label;
+compiler::Node* GenerateAbstractRelationalComparison(
+    CodeStubAssembler* assembler, RelationalComparisonMode mode,
+    compiler::Node* lhs, compiler::Node* rhs, compiler::Node* context) {
+  typedef CodeStubAssembler::Label Label;
   typedef compiler::Node Node;
-  typedef compiler::CodeStubAssembler::Variable Variable;
+  typedef CodeStubAssembler::Variable Variable;
 
-  Node* context = assembler->Parameter(2);
-
-  Label return_true(assembler), return_false(assembler);
+  Label return_true(assembler), return_false(assembler), end(assembler);
+  Variable result(assembler, MachineRepresentation::kTagged);
 
   // Shared entry for floating point comparison.
   Label do_fcmp(assembler);
@@ -1103,14 +1918,14 @@
       var_rhs(assembler, MachineRepresentation::kTagged);
   Variable* loop_vars[2] = {&var_lhs, &var_rhs};
   Label loop(assembler, 2, loop_vars);
-  var_lhs.Bind(assembler->Parameter(0));
-  var_rhs.Bind(assembler->Parameter(1));
+  var_lhs.Bind(lhs);
+  var_rhs.Bind(rhs);
   assembler->Goto(&loop);
   assembler->Bind(&loop);
   {
     // Load the current {lhs} and {rhs} values.
-    Node* lhs = var_lhs.value();
-    Node* rhs = var_rhs.value();
+    lhs = var_lhs.value();
+    rhs = var_rhs.value();
 
     // Check if the {lhs} is a Smi or a HeapObject.
     Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler);
@@ -1283,7 +2098,7 @@
             Node* rhs_instance_type = assembler->LoadMapInstanceType(rhs_map);
 
             // Check if {rhs} is also a String.
-            Label if_rhsisstring(assembler),
+            Label if_rhsisstring(assembler, Label::kDeferred),
                 if_rhsisnotstring(assembler, Label::kDeferred);
             assembler->Branch(assembler->Int32LessThan(
                                   rhs_instance_type, assembler->Int32Constant(
@@ -1295,24 +2110,29 @@
               // Both {lhs} and {rhs} are strings.
               switch (mode) {
                 case kLessThan:
-                  assembler->TailCallStub(
+                  result.Bind(assembler->CallStub(
                       CodeFactory::StringLessThan(assembler->isolate()),
-                      context, lhs, rhs);
+                      context, lhs, rhs));
+                  assembler->Goto(&end);
                   break;
                 case kLessThanOrEqual:
-                  assembler->TailCallStub(
+                  result.Bind(assembler->CallStub(
                       CodeFactory::StringLessThanOrEqual(assembler->isolate()),
-                      context, lhs, rhs);
+                      context, lhs, rhs));
+                  assembler->Goto(&end);
                   break;
                 case kGreaterThan:
-                  assembler->TailCallStub(
+                  result.Bind(assembler->CallStub(
                       CodeFactory::StringGreaterThan(assembler->isolate()),
-                      context, lhs, rhs);
+                      context, lhs, rhs));
+                  assembler->Goto(&end);
                   break;
                 case kGreaterThanOrEqual:
-                  assembler->TailCallStub(CodeFactory::StringGreaterThanOrEqual(
+                  result.Bind(
+                      assembler->CallStub(CodeFactory::StringGreaterThanOrEqual(
                                               assembler->isolate()),
-                                          context, lhs, rhs);
+                                          context, lhs, rhs));
+                  assembler->Goto(&end);
                   break;
               }
             }
@@ -1417,25 +2237,33 @@
   }
 
   assembler->Bind(&return_true);
-  assembler->Return(assembler->BooleanConstant(true));
+  {
+    result.Bind(assembler->BooleanConstant(true));
+    assembler->Goto(&end);
+  }
 
   assembler->Bind(&return_false);
-  assembler->Return(assembler->BooleanConstant(false));
+  {
+    result.Bind(assembler->BooleanConstant(false));
+    assembler->Goto(&end);
+  }
+
+  assembler->Bind(&end);
+  return result.value();
 }
 
 enum ResultMode { kDontNegateResult, kNegateResult };
 
-void GenerateEqual_Same(compiler::CodeStubAssembler* assembler,
-                        compiler::Node* value,
-                        compiler::CodeStubAssembler::Label* if_equal,
-                        compiler::CodeStubAssembler::Label* if_notequal) {
+void GenerateEqual_Same(CodeStubAssembler* assembler, compiler::Node* value,
+                        CodeStubAssembler::Label* if_equal,
+                        CodeStubAssembler::Label* if_notequal) {
   // In case of abstract or strict equality checks, we need additional checks
   // for NaN values because they are not considered equal, even if both the
   // left and the right hand side reference exactly the same value.
   // TODO(bmeurer): This seems to violate the SIMD.js specification, but it
   // seems to be what is tested in the current SIMD.js testsuite.
 
-  typedef compiler::CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Label Label;
   typedef compiler::Node Node;
 
   // Check if {value} is a Smi or a HeapObject.
@@ -1472,11 +2300,10 @@
 }
 
 void GenerateEqual_Simd128Value_HeapObject(
-    compiler::CodeStubAssembler* assembler, compiler::Node* lhs,
-    compiler::Node* lhs_map, compiler::Node* rhs, compiler::Node* rhs_map,
-    compiler::CodeStubAssembler::Label* if_equal,
-    compiler::CodeStubAssembler::Label* if_notequal) {
-  typedef compiler::CodeStubAssembler::Label Label;
+    CodeStubAssembler* assembler, compiler::Node* lhs, compiler::Node* lhs_map,
+    compiler::Node* rhs, compiler::Node* rhs_map,
+    CodeStubAssembler::Label* if_equal, CodeStubAssembler::Label* if_notequal) {
+  typedef CodeStubAssembler::Label Label;
   typedef compiler::Node Node;
 
   // Check if {lhs} and {rhs} have the same map.
@@ -1551,18 +2378,20 @@
 }
 
 // ES6 section 7.2.12 Abstract Equality Comparison
-void GenerateEqual(compiler::CodeStubAssembler* assembler, ResultMode mode) {
+compiler::Node* GenerateEqual(CodeStubAssembler* assembler, ResultMode mode,
+                              compiler::Node* lhs, compiler::Node* rhs,
+                              compiler::Node* context) {
   // This is a slightly optimized version of Object::Equals represented as
   // scheduled TurboFan graph utilizing the CodeStubAssembler. Whenever you
   // change something functionality wise in here, remember to update the
   // Object::Equals method as well.
-  typedef compiler::CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Label Label;
   typedef compiler::Node Node;
-  typedef compiler::CodeStubAssembler::Variable Variable;
+  typedef CodeStubAssembler::Variable Variable;
 
-  Node* context = assembler->Parameter(2);
-
-  Label if_equal(assembler), if_notequal(assembler);
+  Label if_equal(assembler), if_notequal(assembler),
+      do_rhsstringtonumber(assembler, Label::kDeferred), end(assembler);
+  Variable result(assembler, MachineRepresentation::kTagged);
 
   // Shared entry for floating point comparison.
   Label do_fcmp(assembler);
@@ -1575,14 +2404,14 @@
       var_rhs(assembler, MachineRepresentation::kTagged);
   Variable* loop_vars[2] = {&var_lhs, &var_rhs};
   Label loop(assembler, 2, loop_vars);
-  var_lhs.Bind(assembler->Parameter(0));
-  var_rhs.Bind(assembler->Parameter(1));
+  var_lhs.Bind(lhs);
+  var_rhs.Bind(rhs);
   assembler->Goto(&loop);
   assembler->Bind(&loop);
   {
     // Load the current {lhs} and {rhs} values.
-    Node* lhs = var_lhs.value();
-    Node* rhs = var_rhs.value();
+    lhs = var_lhs.value();
+    rhs = var_rhs.value();
 
     // Check if {lhs} and {rhs} refer to the same object.
     Label if_same(assembler), if_notsame(assembler);
@@ -1610,6 +2439,8 @@
                           &if_rhsisnotsmi);
 
         assembler->Bind(&if_rhsissmi);
+        // We have already checked for {lhs} and {rhs} being the same value, so
+        // if both are Smis when we get here they must not be equal.
         assembler->Goto(&if_notequal);
 
         assembler->Bind(&if_rhsisnotsmi);
@@ -1619,8 +2450,7 @@
 
           // Check if {rhs} is a HeapNumber.
           Node* number_map = assembler->HeapNumberMapConstant();
-          Label if_rhsisnumber(assembler),
-              if_rhsisnotnumber(assembler, Label::kDeferred);
+          Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler);
           assembler->Branch(assembler->WordEqual(rhs_map, number_map),
                             &if_rhsisnumber, &if_rhsisnotnumber);
 
@@ -1640,7 +2470,7 @@
 
             // Check if the {rhs} is a String.
             Label if_rhsisstring(assembler, Label::kDeferred),
-                if_rhsisnotstring(assembler, Label::kDeferred);
+                if_rhsisnotstring(assembler);
             assembler->Branch(assembler->Int32LessThan(
                                   rhs_instance_type, assembler->Int32Constant(
                                                          FIRST_NONSTRING_TYPE)),
@@ -1648,19 +2478,17 @@
 
             assembler->Bind(&if_rhsisstring);
             {
-              // Convert the {rhs} to a Number.
-              Callable callable =
-                  CodeFactory::StringToNumber(assembler->isolate());
-              var_rhs.Bind(assembler->CallStub(callable, context, rhs));
-              assembler->Goto(&loop);
+              // The {rhs} is a String and the {lhs} is a Smi; we need
+              // to convert the {rhs} to a Number and compare the output to
+              // the Number on the {lhs}.
+              assembler->Goto(&do_rhsstringtonumber);
             }
 
             assembler->Bind(&if_rhsisnotstring);
             {
               // Check if the {rhs} is a Boolean.
               Node* boolean_map = assembler->BooleanMapConstant();
-              Label if_rhsisboolean(assembler, Label::kDeferred),
-                  if_rhsisnotboolean(assembler, Label::kDeferred);
+              Label if_rhsisboolean(assembler), if_rhsisnotboolean(assembler);
               assembler->Branch(assembler->WordEqual(rhs_map, boolean_map),
                                 &if_rhsisboolean, &if_rhsisnotboolean);
 
@@ -1677,7 +2505,7 @@
                 // Check if the {rhs} is a Receiver.
                 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
                 Label if_rhsisreceiver(assembler, Label::kDeferred),
-                    if_rhsisnotreceiver(assembler, Label::kDeferred);
+                    if_rhsisnotreceiver(assembler);
                 assembler->Branch(
                     assembler->Int32LessThanOrEqual(
                         assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE),
@@ -1761,8 +2589,8 @@
           assembler->Bind(&if_lhsisstring);
           {
             // Check if {rhs} is also a String.
-            Label if_rhsisstring(assembler),
-                if_rhsisnotstring(assembler, Label::kDeferred);
+            Label if_rhsisstring(assembler, Label::kDeferred),
+                if_rhsisnotstring(assembler);
             assembler->Branch(assembler->Int32LessThan(
                                   rhs_instance_type, assembler->Int32Constant(
                                                          FIRST_NONSTRING_TYPE)),
@@ -1776,7 +2604,8 @@
                   (mode == kDontNegateResult)
                       ? CodeFactory::StringEqual(assembler->isolate())
                       : CodeFactory::StringNotEqual(assembler->isolate());
-              assembler->TailCallStub(callable, context, lhs, rhs);
+              result.Bind(assembler->CallStub(callable, context, lhs, rhs));
+              assembler->Goto(&end);
             }
 
             assembler->Bind(&if_rhsisnotstring);
@@ -1794,8 +2623,7 @@
           assembler->Bind(&if_lhsisnumber);
           {
             // Check if {rhs} is also a HeapNumber.
-            Label if_rhsisnumber(assembler),
-                if_rhsisnotnumber(assembler, Label::kDeferred);
+            Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler);
             assembler->Branch(
                 assembler->Word32Equal(lhs_instance_type, rhs_instance_type),
                 &if_rhsisnumber, &if_rhsisnotnumber);
@@ -1825,16 +2653,13 @@
                 // The {rhs} is a String and the {lhs} is a HeapNumber; we need
                 // to convert the {rhs} to a Number and compare the output to
                 // the Number on the {lhs}.
-                Callable callable =
-                    CodeFactory::StringToNumber(assembler->isolate());
-                var_rhs.Bind(assembler->CallStub(callable, context, rhs));
-                assembler->Goto(&loop);
+                assembler->Goto(&do_rhsstringtonumber);
               }
 
               assembler->Bind(&if_rhsisnotstring);
               {
                 // Check if the {rhs} is a JSReceiver.
-                Label if_rhsisreceiver(assembler, Label::kDeferred),
+                Label if_rhsisreceiver(assembler),
                     if_rhsisnotreceiver(assembler);
                 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
                 assembler->Branch(
@@ -1926,8 +2751,7 @@
           assembler->Bind(&if_lhsissymbol);
           {
             // Check if the {rhs} is a JSReceiver.
-            Label if_rhsisreceiver(assembler, Label::kDeferred),
-                if_rhsisnotreceiver(assembler);
+            Label if_rhsisreceiver(assembler), if_rhsisnotreceiver(assembler);
             STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
             assembler->Branch(
                 assembler->Int32LessThanOrEqual(
@@ -1974,8 +2798,7 @@
             assembler->Bind(&if_rhsisnotsimd128value);
             {
               // Check if the {rhs} is a JSReceiver.
-              Label if_rhsisreceiver(assembler, Label::kDeferred),
-                  if_rhsisnotreceiver(assembler);
+              Label if_rhsisreceiver(assembler), if_rhsisnotreceiver(assembler);
               STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
               assembler->Branch(
                   assembler->Int32LessThanOrEqual(
@@ -2060,6 +2883,13 @@
         }
       }
     }
+
+    assembler->Bind(&do_rhsstringtonumber);
+    {
+      Callable callable = CodeFactory::StringToNumber(assembler->isolate());
+      var_rhs.Bind(assembler->CallStub(callable, context, rhs));
+      assembler->Goto(&loop);
+    }
   }
 
   assembler->Bind(&do_fcmp);
@@ -2073,14 +2903,25 @@
   }
 
   assembler->Bind(&if_equal);
-  assembler->Return(assembler->BooleanConstant(mode == kDontNegateResult));
+  {
+    result.Bind(assembler->BooleanConstant(mode == kDontNegateResult));
+    assembler->Goto(&end);
+  }
 
   assembler->Bind(&if_notequal);
-  assembler->Return(assembler->BooleanConstant(mode == kNegateResult));
+  {
+    result.Bind(assembler->BooleanConstant(mode == kNegateResult));
+    assembler->Goto(&end);
+  }
+
+  assembler->Bind(&end);
+  return result.value();
 }
 
-void GenerateStrictEqual(compiler::CodeStubAssembler* assembler,
-                         ResultMode mode) {
+compiler::Node* GenerateStrictEqual(CodeStubAssembler* assembler,
+                                    ResultMode mode, compiler::Node* lhs,
+                                    compiler::Node* rhs,
+                                    compiler::Node* context) {
   // Here's pseudo-code for the algorithm below in case of kDontNegateResult
   // mode; for kNegateResult mode we properly negate the result.
   //
@@ -2129,14 +2970,12 @@
   //   }
   // }
 
-  typedef compiler::CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
   typedef compiler::Node Node;
 
-  Node* lhs = assembler->Parameter(0);
-  Node* rhs = assembler->Parameter(1);
-  Node* context = assembler->Parameter(2);
-
-  Label if_equal(assembler), if_notequal(assembler);
+  Label if_equal(assembler), if_notequal(assembler), end(assembler);
+  Variable result(assembler, MachineRepresentation::kTagged);
 
   // Check if {lhs} and {rhs} refer to the same object.
   Label if_same(assembler), if_notsame(assembler);
@@ -2241,7 +3080,8 @@
             Node* rhs_instance_type = assembler->LoadInstanceType(rhs);
 
             // Check if {rhs} is also a String.
-            Label if_rhsisstring(assembler), if_rhsisnotstring(assembler);
+            Label if_rhsisstring(assembler, Label::kDeferred),
+                if_rhsisnotstring(assembler);
             assembler->Branch(assembler->Int32LessThan(
                                   rhs_instance_type, assembler->Int32Constant(
                                                          FIRST_NONSTRING_TYPE)),
@@ -2253,7 +3093,8 @@
                   (mode == kDontNegateResult)
                       ? CodeFactory::StringEqual(assembler->isolate())
                       : CodeFactory::StringNotEqual(assembler->isolate());
-              assembler->TailCallStub(callable, context, lhs, rhs);
+              result.Bind(assembler->CallStub(callable, context, lhs, rhs));
+              assembler->Goto(&end);
             }
 
             assembler->Bind(&if_rhsisnotstring);
@@ -2330,17 +3171,26 @@
   }
 
   assembler->Bind(&if_equal);
-  assembler->Return(assembler->BooleanConstant(mode == kDontNegateResult));
+  {
+    result.Bind(assembler->BooleanConstant(mode == kDontNegateResult));
+    assembler->Goto(&end);
+  }
 
   assembler->Bind(&if_notequal);
-  assembler->Return(assembler->BooleanConstant(mode == kNegateResult));
+  {
+    result.Bind(assembler->BooleanConstant(mode == kNegateResult));
+    assembler->Goto(&end);
+  }
+
+  assembler->Bind(&end);
+  return result.value();
 }
 
-void GenerateStringRelationalComparison(compiler::CodeStubAssembler* assembler,
+void GenerateStringRelationalComparison(CodeStubAssembler* assembler,
                                         RelationalComparisonMode mode) {
-  typedef compiler::CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Label Label;
   typedef compiler::Node Node;
-  typedef compiler::CodeStubAssembler::Variable Variable;
+  typedef CodeStubAssembler::Variable Variable;
 
   Node* lhs = assembler->Parameter(0);
   Node* rhs = assembler->Parameter(1);
@@ -2519,8 +3369,7 @@
   }
 }
 
-void GenerateStringEqual(compiler::CodeStubAssembler* assembler,
-                         ResultMode mode) {
+void GenerateStringEqual(CodeStubAssembler* assembler, ResultMode mode) {
   // Here's pseudo-code for the algorithm below in case of kDontNegateResult
   // mode; for kNegateResult mode we properly negate the result.
   //
@@ -2537,9 +3386,9 @@
   // }
   // return %StringEqual(lhs, rhs);
 
-  typedef compiler::CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Label Label;
   typedef compiler::Node Node;
-  typedef compiler::CodeStubAssembler::Variable Variable;
+  typedef CodeStubAssembler::Variable Variable;
 
   Node* lhs = assembler->Parameter(0);
   Node* rhs = assembler->Parameter(1);
@@ -2698,80 +3547,118 @@
 
 }  // namespace
 
-void LessThanStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
-  GenerateAbstractRelationalComparison(assembler, kLessThan);
+void LoadApiGetterStub::GenerateAssembly(CodeStubAssembler* assembler) const {
+  typedef compiler::Node Node;
+  Node* context = assembler->Parameter(3);
+  Node* receiver = assembler->Parameter(0);
+  // For now we only support receiver_is_holder.
+  DCHECK(receiver_is_holder());
+  Node* holder = receiver;
+  Node* map = assembler->LoadMap(receiver);
+  Node* descriptors = assembler->LoadMapDescriptors(map);
+  Node* offset =
+      assembler->Int32Constant(DescriptorArray::ToValueIndex(index()));
+  Node* callback = assembler->LoadFixedArrayElement(descriptors, offset);
+  assembler->TailCallStub(CodeFactory::ApiGetter(isolate()), context, receiver,
+                          holder, callback);
 }
 
-void LessThanOrEqualStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
-  GenerateAbstractRelationalComparison(assembler, kLessThanOrEqual);
+// static
+compiler::Node* LessThanStub::Generate(CodeStubAssembler* assembler,
+                                       compiler::Node* lhs, compiler::Node* rhs,
+                                       compiler::Node* context) {
+  return GenerateAbstractRelationalComparison(assembler, kLessThan, lhs, rhs,
+                                              context);
 }
 
-void GreaterThanStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
-  GenerateAbstractRelationalComparison(assembler, kGreaterThan);
+// static
+compiler::Node* LessThanOrEqualStub::Generate(CodeStubAssembler* assembler,
+                                              compiler::Node* lhs,
+                                              compiler::Node* rhs,
+                                              compiler::Node* context) {
+  return GenerateAbstractRelationalComparison(assembler, kLessThanOrEqual, lhs,
+                                              rhs, context);
 }
 
-void GreaterThanOrEqualStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
-  GenerateAbstractRelationalComparison(assembler, kGreaterThanOrEqual);
+// static
+compiler::Node* GreaterThanStub::Generate(CodeStubAssembler* assembler,
+                                          compiler::Node* lhs,
+                                          compiler::Node* rhs,
+                                          compiler::Node* context) {
+  return GenerateAbstractRelationalComparison(assembler, kGreaterThan, lhs, rhs,
+                                              context);
 }
 
-void EqualStub::GenerateAssembly(compiler::CodeStubAssembler* assembler) const {
-  GenerateEqual(assembler, kDontNegateResult);
+// static
+compiler::Node* GreaterThanOrEqualStub::Generate(CodeStubAssembler* assembler,
+                                                 compiler::Node* lhs,
+                                                 compiler::Node* rhs,
+                                                 compiler::Node* context) {
+  return GenerateAbstractRelationalComparison(assembler, kGreaterThanOrEqual,
+                                              lhs, rhs, context);
 }
 
-void NotEqualStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
-  GenerateEqual(assembler, kNegateResult);
+// static
+compiler::Node* EqualStub::Generate(CodeStubAssembler* assembler,
+                                    compiler::Node* lhs, compiler::Node* rhs,
+                                    compiler::Node* context) {
+  return GenerateEqual(assembler, kDontNegateResult, lhs, rhs, context);
 }
 
-void StrictEqualStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
-  GenerateStrictEqual(assembler, kDontNegateResult);
+// static
+compiler::Node* NotEqualStub::Generate(CodeStubAssembler* assembler,
+                                       compiler::Node* lhs, compiler::Node* rhs,
+                                       compiler::Node* context) {
+  return GenerateEqual(assembler, kNegateResult, lhs, rhs, context);
 }
 
-void StrictNotEqualStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
-  GenerateStrictEqual(assembler, kNegateResult);
+// static
+compiler::Node* StrictEqualStub::Generate(CodeStubAssembler* assembler,
+                                          compiler::Node* lhs,
+                                          compiler::Node* rhs,
+                                          compiler::Node* context) {
+  return GenerateStrictEqual(assembler, kDontNegateResult, lhs, rhs, context);
 }
 
-void StringEqualStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
+// static
+compiler::Node* StrictNotEqualStub::Generate(CodeStubAssembler* assembler,
+                                             compiler::Node* lhs,
+                                             compiler::Node* rhs,
+                                             compiler::Node* context) {
+  return GenerateStrictEqual(assembler, kNegateResult, lhs, rhs, context);
+}
+
+void StringEqualStub::GenerateAssembly(CodeStubAssembler* assembler) const {
   GenerateStringEqual(assembler, kDontNegateResult);
 }
 
-void StringNotEqualStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
+void StringNotEqualStub::GenerateAssembly(CodeStubAssembler* assembler) const {
   GenerateStringEqual(assembler, kNegateResult);
 }
 
-void StringLessThanStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
+void StringLessThanStub::GenerateAssembly(CodeStubAssembler* assembler) const {
   GenerateStringRelationalComparison(assembler, kLessThan);
 }
 
 void StringLessThanOrEqualStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
+    CodeStubAssembler* assembler) const {
   GenerateStringRelationalComparison(assembler, kLessThanOrEqual);
 }
 
 void StringGreaterThanStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
+    CodeStubAssembler* assembler) const {
   GenerateStringRelationalComparison(assembler, kGreaterThan);
 }
 
 void StringGreaterThanOrEqualStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
+    CodeStubAssembler* assembler) const {
   GenerateStringRelationalComparison(assembler, kGreaterThanOrEqual);
 }
 
-void ToLengthStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
-  typedef compiler::CodeStubAssembler::Label Label;
+void ToLengthStub::GenerateAssembly(CodeStubAssembler* assembler) const {
+  typedef CodeStubAssembler::Label Label;
   typedef compiler::Node Node;
-  typedef compiler::CodeStubAssembler::Variable Variable;
+  typedef CodeStubAssembler::Variable Variable;
 
   Node* context = assembler->Parameter(1);
 
@@ -2844,13 +3731,17 @@
   }
 }
 
-void ToBooleanStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
+// static
+compiler::Node* ToBooleanStub::Generate(CodeStubAssembler* assembler,
+                                        compiler::Node* value,
+                                        compiler::Node* context) {
   typedef compiler::Node Node;
-  typedef compiler::CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
 
-  Node* value = assembler->Parameter(0);
-  Label if_valueissmi(assembler), if_valueisnotsmi(assembler);
+  Variable result(assembler, MachineRepresentation::kTagged);
+  Label if_valueissmi(assembler), if_valueisnotsmi(assembler),
+      return_true(assembler), return_false(assembler), end(assembler);
 
   // Check if {value} is a Smi or a HeapObject.
   assembler->Branch(assembler->WordIsSmi(value), &if_valueissmi,
@@ -2859,21 +3750,15 @@
   assembler->Bind(&if_valueissmi);
   {
     // The {value} is a Smi, only need to check against zero.
-    Label if_valueiszero(assembler), if_valueisnotzero(assembler);
     assembler->Branch(assembler->SmiEqual(value, assembler->SmiConstant(0)),
-                      &if_valueiszero, &if_valueisnotzero);
-
-    assembler->Bind(&if_valueiszero);
-    assembler->Return(assembler->BooleanConstant(false));
-
-    assembler->Bind(&if_valueisnotzero);
-    assembler->Return(assembler->BooleanConstant(true));
+                      &return_false, &return_true);
   }
 
   assembler->Bind(&if_valueisnotsmi);
   {
-    Label if_valueisstring(assembler), if_valueisheapnumber(assembler),
-        if_valueisoddball(assembler), if_valueisother(assembler);
+    Label if_valueisstring(assembler), if_valueisnotstring(assembler),
+        if_valueisheapnumber(assembler), if_valueisoddball(assembler),
+        if_valueisother(assembler);
 
     // The {value} is a HeapObject, load its map.
     Node* value_map = assembler->LoadMap(value);
@@ -2885,24 +3770,20 @@
 
     // Dispatch based on the instance type; we distinguish all String instance
     // types, the HeapNumber type and the Oddball type.
-    size_t const kNumCases = FIRST_NONSTRING_TYPE + 2;
+    assembler->Branch(assembler->Int32LessThan(
+                          value_instance_type,
+                          assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
+                      &if_valueisstring, &if_valueisnotstring);
+    assembler->Bind(&if_valueisnotstring);
+    size_t const kNumCases = 2;
     Label* case_labels[kNumCases];
     int32_t case_values[kNumCases];
-    for (int32_t i = 0; i < FIRST_NONSTRING_TYPE; ++i) {
-      case_labels[i] = new Label(assembler);
-      case_values[i] = i;
-    }
-    case_labels[FIRST_NONSTRING_TYPE + 0] = &if_valueisheapnumber;
-    case_values[FIRST_NONSTRING_TYPE + 0] = HEAP_NUMBER_TYPE;
-    case_labels[FIRST_NONSTRING_TYPE + 1] = &if_valueisoddball;
-    case_values[FIRST_NONSTRING_TYPE + 1] = ODDBALL_TYPE;
+    case_labels[0] = &if_valueisheapnumber;
+    case_values[0] = HEAP_NUMBER_TYPE;
+    case_labels[1] = &if_valueisoddball;
+    case_values[1] = ODDBALL_TYPE;
     assembler->Switch(value_instance_type, &if_valueisother, case_values,
                       case_labels, arraysize(case_values));
-    for (int32_t i = 0; i < FIRST_NONSTRING_TYPE; ++i) {
-      assembler->Bind(case_labels[i]);
-      assembler->Goto(&if_valueisstring);
-      delete case_labels[i];
-    }
 
     assembler->Bind(&if_valueisstring);
     {
@@ -2911,16 +3792,9 @@
           assembler->LoadObjectField(value, String::kLengthOffset);
 
       // Check if the {value} is the empty string.
-      Label if_valueisempty(assembler), if_valueisnotempty(assembler);
       assembler->Branch(
           assembler->SmiEqual(value_length, assembler->SmiConstant(0)),
-          &if_valueisempty, &if_valueisnotempty);
-
-      assembler->Bind(&if_valueisempty);
-      assembler->Return(assembler->BooleanConstant(false));
-
-      assembler->Bind(&if_valueisnotempty);
-      assembler->Return(assembler->BooleanConstant(true));
+          &return_false, &return_true);
     }
 
     assembler->Bind(&if_valueisheapnumber);
@@ -2929,25 +3803,15 @@
           MachineType::Float64(), value,
           assembler->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag));
 
-      Label if_valueispositive(assembler), if_valueisnotpositive(assembler),
-          if_valueisnegative(assembler), if_valueisnanorzero(assembler);
+      Label if_valueisnotpositive(assembler);
       assembler->Branch(assembler->Float64LessThan(
                             assembler->Float64Constant(0.0), value_value),
-                        &if_valueispositive, &if_valueisnotpositive);
-
-      assembler->Bind(&if_valueispositive);
-      assembler->Return(assembler->BooleanConstant(true));
+                        &return_true, &if_valueisnotpositive);
 
       assembler->Bind(&if_valueisnotpositive);
       assembler->Branch(assembler->Float64LessThan(
                             value_value, assembler->Float64Constant(0.0)),
-                        &if_valueisnegative, &if_valueisnanorzero);
-
-      assembler->Bind(&if_valueisnegative);
-      assembler->Return(assembler->BooleanConstant(true));
-
-      assembler->Bind(&if_valueisnanorzero);
-      assembler->Return(assembler->BooleanConstant(false));
+                        &return_true, &return_false);
     }
 
     assembler->Bind(&if_valueisoddball);
@@ -2955,7 +3819,8 @@
       // The {value} is an Oddball, and every Oddball knows its boolean value.
       Node* value_toboolean =
           assembler->LoadObjectField(value, Oddball::kToBooleanOffset);
-      assembler->Return(value_toboolean);
+      result.Bind(value_toboolean);
+      assembler->Goto(&end);
     }
 
     assembler->Bind(&if_valueisother);
@@ -2968,26 +3833,32 @@
           assembler->Int32Constant(1 << Map::kIsUndetectable));
 
       // Check if the {value} is undetectable.
-      Label if_valueisundetectable(assembler),
-          if_valueisnotundetectable(assembler);
       assembler->Branch(assembler->Word32Equal(value_map_undetectable,
                                                assembler->Int32Constant(0)),
-                        &if_valueisnotundetectable, &if_valueisundetectable);
-
-      assembler->Bind(&if_valueisundetectable);
-      assembler->Return(assembler->BooleanConstant(false));
-
-      assembler->Bind(&if_valueisnotundetectable);
-      assembler->Return(assembler->BooleanConstant(true));
+                        &return_true, &return_false);
     }
   }
+
+  assembler->Bind(&return_false);
+  {
+    result.Bind(assembler->BooleanConstant(false));
+    assembler->Goto(&end);
+  }
+
+  assembler->Bind(&return_true);
+  {
+    result.Bind(assembler->BooleanConstant(true));
+    assembler->Goto(&end);
+  }
+
+  assembler->Bind(&end);
+  return result.value();
 }
 
-void ToIntegerStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
-  typedef compiler::CodeStubAssembler::Label Label;
+void ToIntegerStub::GenerateAssembly(CodeStubAssembler* assembler) const {
+  typedef CodeStubAssembler::Label Label;
   typedef compiler::Node Node;
-  typedef compiler::CodeStubAssembler::Variable Variable;
+  typedef CodeStubAssembler::Variable Variable;
 
   Node* context = assembler->Parameter(1);
 
@@ -3046,7 +3917,7 @@
 }
 
 void StoreInterceptorStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
+    CodeStubAssembler* assembler) const {
   typedef compiler::Node Node;
   Node* receiver = assembler->Parameter(0);
   Node* name = assembler->Parameter(1);
@@ -3057,9 +3928,9 @@
 }
 
 void LoadIndexedInterceptorStub::GenerateAssembly(
-    compiler::CodeStubAssembler* assembler) const {
+    CodeStubAssembler* assembler) const {
   typedef compiler::Node Node;
-  typedef compiler::CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Label Label;
   Node* receiver = assembler->Parameter(0);
   Node* key = assembler->Parameter(1);
   Node* slot = assembler->Parameter(2);
@@ -3078,6 +3949,133 @@
                              slot, vector);
 }
 
+// static
+bool FastCloneShallowObjectStub::IsSupported(ObjectLiteral* expr) {
+  // FastCloneShallowObjectStub doesn't copy elements, and object literals don't
+  // support copy-on-write (COW) elements for now.
+  // TODO(mvstanton): make object literals support COW elements.
+  return expr->fast_elements() && expr->has_shallow_properties() &&
+         expr->properties_count() <= kMaximumClonedProperties;
+}
+
+// static
+int FastCloneShallowObjectStub::PropertiesCount(int literal_length) {
+  // This heuristic of setting empty literals to have
+  // kInitialGlobalObjectUnusedPropertiesCount must remain in-sync with the
+  // runtime.
+  // TODO(verwaest): Unify this with the heuristic in the runtime.
+  return literal_length == 0
+             ? JSObject::kInitialGlobalObjectUnusedPropertiesCount
+             : literal_length;
+}
+
+// static
+compiler::Node* FastCloneShallowObjectStub::GenerateFastPath(
+    CodeStubAssembler* assembler, compiler::CodeAssembler::Label* call_runtime,
+    compiler::Node* closure, compiler::Node* literals_index,
+    compiler::Node* properties_count) {
+  typedef compiler::Node Node;
+  typedef compiler::CodeAssembler::Label Label;
+  typedef compiler::CodeAssembler::Variable Variable;
+
+  Node* undefined = assembler->UndefinedConstant();
+  Node* literals_array =
+      assembler->LoadObjectField(closure, JSFunction::kLiteralsOffset);
+  Node* allocation_site = assembler->LoadFixedArrayElement(
+      literals_array, literals_index,
+      LiteralsArray::kFirstLiteralIndex * kPointerSize,
+      CodeStubAssembler::SMI_PARAMETERS);
+  assembler->GotoIf(assembler->WordEqual(allocation_site, undefined),
+                    call_runtime);
+
+  // Calculate the object and allocation size based on the properties count.
+  Node* object_size = assembler->IntPtrAdd(
+      assembler->WordShl(properties_count, kPointerSizeLog2),
+      assembler->IntPtrConstant(JSObject::kHeaderSize));
+  Node* allocation_size = object_size;
+  if (FLAG_allocation_site_pretenuring) {
+    allocation_size = assembler->IntPtrAdd(
+        object_size, assembler->IntPtrConstant(AllocationMemento::kSize));
+  }
+  Node* boilerplate = assembler->LoadObjectField(
+      allocation_site, AllocationSite::kTransitionInfoOffset);
+  Node* boilerplate_map = assembler->LoadMap(boilerplate);
+  Node* instance_size = assembler->LoadMapInstanceSize(boilerplate_map);
+  Node* size_in_words = assembler->WordShr(object_size, kPointerSizeLog2);
+  assembler->GotoUnless(assembler->Word32Equal(instance_size, size_in_words),
+                        call_runtime);
+
+  Node* copy = assembler->Allocate(allocation_size);
+
+  // Copy boilerplate elements.
+  Variable offset(assembler, MachineType::PointerRepresentation());
+  offset.Bind(assembler->IntPtrConstant(-kHeapObjectTag));
+  Node* end_offset = assembler->IntPtrAdd(object_size, offset.value());
+  Label loop_body(assembler, &offset), loop_check(assembler, &offset);
+  // We should always have an object size greater than zero.
+  assembler->Goto(&loop_body);
+  assembler->Bind(&loop_body);
+  {
+    // The Allocate above guarantees that the copy lies in new space. This
+    // allows us to skip write barriers. This is necessary since we may also be
+    // copying unboxed doubles.
+    Node* field =
+        assembler->Load(MachineType::IntPtr(), boilerplate, offset.value());
+    assembler->StoreNoWriteBarrier(MachineType::PointerRepresentation(), copy,
+                                   offset.value(), field);
+    assembler->Goto(&loop_check);
+  }
+  assembler->Bind(&loop_check);
+  {
+    offset.Bind(assembler->IntPtrAdd(offset.value(),
+                                     assembler->IntPtrConstant(kPointerSize)));
+    assembler->GotoUnless(
+        assembler->IntPtrGreaterThanOrEqual(offset.value(), end_offset),
+        &loop_body);
+  }
+
+  if (FLAG_allocation_site_pretenuring) {
+    Node* memento = assembler->InnerAllocate(copy, object_size);
+    assembler->StoreObjectFieldNoWriteBarrier(
+        memento, HeapObject::kMapOffset,
+        assembler->LoadRoot(Heap::kAllocationMementoMapRootIndex));
+    assembler->StoreObjectFieldNoWriteBarrier(
+        memento, AllocationMemento::kAllocationSiteOffset, allocation_site);
+    Node* memento_create_count = assembler->LoadObjectField(
+        allocation_site, AllocationSite::kPretenureCreateCountOffset);
+    memento_create_count = assembler->SmiAdd(
+        memento_create_count, assembler->SmiConstant(Smi::FromInt(1)));
+    assembler->StoreObjectFieldNoWriteBarrier(
+        allocation_site, AllocationSite::kPretenureCreateCountOffset,
+        memento_create_count);
+  }
+
+  // TODO(verwaest): Allocate and fill in double boxes.
+  return copy;
+}
+
+void FastCloneShallowObjectStub::GenerateAssembly(
+    CodeStubAssembler* assembler) const {
+  typedef CodeStubAssembler::Label Label;
+  typedef compiler::Node Node;
+  Label call_runtime(assembler);
+  Node* closure = assembler->Parameter(0);
+  Node* literals_index = assembler->Parameter(1);
+
+  Node* properties_count =
+      assembler->IntPtrConstant(PropertiesCount(this->length()));
+  Node* copy = GenerateFastPath(assembler, &call_runtime, closure,
+                                literals_index, properties_count);
+  assembler->Return(copy);
+
+  assembler->Bind(&call_runtime);
+  Node* constant_properties = assembler->Parameter(2);
+  Node* flags = assembler->Parameter(3);
+  Node* context = assembler->Parameter(4);
+  assembler->TailCallRuntime(Runtime::kCreateObjectLiteral, context, closure,
+                             literals_index, constant_properties, flags);
+}
+
 template<class StateType>
 void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
   // Note: Although a no-op transition is semantically OK, it is hinting at a
@@ -3191,11 +4189,7 @@
   return VectorStoreTransitionDescriptor(isolate());
 }
 
-
-void FastNewClosureStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
-  descriptor->Initialize(Runtime::FunctionForId(Runtime::kNewClosure)->entry);
-}
-
+void FastNewClosureStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {}
 
 void FastNewContextStub::InitializeDescriptor(CodeStubDescriptor* d) {}
 
@@ -3224,14 +4218,6 @@
 }
 
 
-void FastCloneShallowObjectStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  FastCloneShallowObjectDescriptor call_descriptor(isolate());
-  descriptor->Initialize(
-      Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry);
-}
-
-
 void CreateAllocationSiteStub::InitializeDescriptor(CodeStubDescriptor* d) {}
 
 
@@ -3259,11 +4245,6 @@
 }
 
 
-void AllocateMutableHeapNumberStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  descriptor->Initialize();
-}
-
 #define SIMD128_INIT_DESC(TYPE, Type, type, lane_count, lane_type) \
   void Allocate##Type##Stub::InitializeDescriptor(                 \
       CodeStubDescriptor* descriptor) {                            \
@@ -3273,11 +4254,6 @@
 SIMD128_TYPES(SIMD128_INIT_DESC)
 #undef SIMD128_INIT_DESC
 
-void AllocateInNewSpaceStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  descriptor->Initialize();
-}
-
 void ToBooleanICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
   descriptor->Initialize(FUNCTION_ADDR(Runtime_ToBooleanIC_Miss));
   descriptor->SetMissHandler(ExternalReference(
@@ -3316,6 +4292,138 @@
   stub.GetCode();
 }
 
+// static
+compiler::Node* HasPropertyStub::Generate(CodeStubAssembler* assembler,
+                                          compiler::Node* key,
+                                          compiler::Node* object,
+                                          compiler::Node* context) {
+  typedef compiler::Node Node;
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
+
+  Label call_runtime(assembler, Label::kDeferred), return_true(assembler),
+      return_false(assembler), end(assembler);
+
+  // Ensure object is JSReceiver, otherwise call runtime to throw error.
+  Label if_objectisnotsmi(assembler);
+  assembler->Branch(assembler->WordIsSmi(object), &call_runtime,
+                    &if_objectisnotsmi);
+  assembler->Bind(&if_objectisnotsmi);
+
+  Node* map = assembler->LoadMap(object);
+  Node* instance_type = assembler->LoadMapInstanceType(map);
+  {
+    Label if_objectisreceiver(assembler);
+    STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
+    assembler->Branch(
+        assembler->Int32GreaterThanOrEqual(
+            instance_type, assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE)),
+        &if_objectisreceiver, &call_runtime);
+    assembler->Bind(&if_objectisreceiver);
+  }
+
+  Variable var_index(assembler, MachineRepresentation::kWord32);
+
+  Label keyisindex(assembler), if_iskeyunique(assembler);
+  assembler->TryToName(key, &keyisindex, &var_index, &if_iskeyunique,
+                       &call_runtime);
+
+  assembler->Bind(&if_iskeyunique);
+  {
+    Variable var_object(assembler, MachineRepresentation::kTagged);
+    Variable var_map(assembler, MachineRepresentation::kTagged);
+    Variable var_instance_type(assembler, MachineRepresentation::kWord8);
+
+    Variable* merged_variables[] = {&var_object, &var_map, &var_instance_type};
+    Label loop(assembler, arraysize(merged_variables), merged_variables);
+    var_object.Bind(object);
+    var_map.Bind(map);
+    var_instance_type.Bind(instance_type);
+    assembler->Goto(&loop);
+    assembler->Bind(&loop);
+    {
+      Label next_proto(assembler);
+      assembler->TryHasOwnProperty(var_object.value(), var_map.value(),
+                                   var_instance_type.value(), key, &return_true,
+                                   &next_proto, &call_runtime);
+      assembler->Bind(&next_proto);
+
+      Node* proto = assembler->LoadMapPrototype(var_map.value());
+
+      Label if_not_null(assembler);
+      assembler->Branch(assembler->WordEqual(proto, assembler->NullConstant()),
+                        &return_false, &if_not_null);
+      assembler->Bind(&if_not_null);
+
+      Node* map = assembler->LoadMap(proto);
+      Node* instance_type = assembler->LoadMapInstanceType(map);
+
+      var_object.Bind(proto);
+      var_map.Bind(map);
+      var_instance_type.Bind(instance_type);
+      assembler->Goto(&loop);
+    }
+  }
+  assembler->Bind(&keyisindex);
+  {
+    Variable var_object(assembler, MachineRepresentation::kTagged);
+    Variable var_map(assembler, MachineRepresentation::kTagged);
+    Variable var_instance_type(assembler, MachineRepresentation::kWord8);
+
+    Variable* merged_variables[] = {&var_object, &var_map, &var_instance_type};
+    Label loop(assembler, arraysize(merged_variables), merged_variables);
+    var_object.Bind(object);
+    var_map.Bind(map);
+    var_instance_type.Bind(instance_type);
+    assembler->Goto(&loop);
+    assembler->Bind(&loop);
+    {
+      Label next_proto(assembler);
+      assembler->TryLookupElement(var_object.value(), var_map.value(),
+                                  var_instance_type.value(), var_index.value(),
+                                  &return_true, &next_proto, &call_runtime);
+      assembler->Bind(&next_proto);
+
+      Node* proto = assembler->LoadMapPrototype(var_map.value());
+
+      Label if_not_null(assembler);
+      assembler->Branch(assembler->WordEqual(proto, assembler->NullConstant()),
+                        &return_false, &if_not_null);
+      assembler->Bind(&if_not_null);
+
+      Node* map = assembler->LoadMap(proto);
+      Node* instance_type = assembler->LoadMapInstanceType(map);
+
+      var_object.Bind(proto);
+      var_map.Bind(map);
+      var_instance_type.Bind(instance_type);
+      assembler->Goto(&loop);
+    }
+  }
+
+  Variable result(assembler, MachineRepresentation::kTagged);
+  assembler->Bind(&return_true);
+  {
+    result.Bind(assembler->BooleanConstant(true));
+    assembler->Goto(&end);
+  }
+
+  assembler->Bind(&return_false);
+  {
+    result.Bind(assembler->BooleanConstant(false));
+    assembler->Goto(&end);
+  }
+
+  assembler->Bind(&call_runtime);
+  {
+    result.Bind(
+        assembler->CallRuntime(Runtime::kHasProperty, context, key, object));
+    assembler->Goto(&end);
+  }
+
+  assembler->Bind(&end);
+  return result.value();
+}
 
 void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) {
   CreateAllocationSiteStub stub(isolate);
@@ -3370,20 +4478,10 @@
 }
 
 
-std::ostream& ArrayConstructorStubBase::BasePrintName(
-    std::ostream& os,  // NOLINT
-    const char* name) const {
-  os << name << "_" << ElementsKindToString(elements_kind());
-  if (override_mode() == DISABLE_ALLOCATION_SITES) {
-    os << "_DISABLE_ALLOCATION_SITES";
-  }
-  return os;
-}
-
 bool ToBooleanICStub::UpdateStatus(Handle<Object> object) {
   Types new_types = types();
   Types old_types = new_types;
-  bool to_boolean_value = new_types.UpdateStatus(object);
+  bool to_boolean_value = new_types.UpdateStatus(isolate(), object);
   TraceTransition(old_types, new_types);
   set_sub_minor_key(TypesBits::update(sub_minor_key(), new_types.ToIntegral()));
   return to_boolean_value;
@@ -3409,14 +4507,15 @@
   return os << ")";
 }
 
-bool ToBooleanICStub::Types::UpdateStatus(Handle<Object> object) {
-  if (object->IsUndefined()) {
+bool ToBooleanICStub::Types::UpdateStatus(Isolate* isolate,
+                                          Handle<Object> object) {
+  if (object->IsUndefined(isolate)) {
     Add(UNDEFINED);
     return false;
   } else if (object->IsBoolean()) {
     Add(BOOLEAN);
-    return object->IsTrue();
-  } else if (object->IsNull()) {
+    return object->IsTrue(isolate);
+  } else if (object->IsNull(isolate)) {
     Add(NULL_TYPE);
     return false;
   } else if (object->IsSmi()) {
@@ -3472,11 +4571,133 @@
   entry_hook(function, stack_pointer);
 }
 
+void ArrayNoArgumentConstructorStub::GenerateAssembly(
+    CodeStubAssembler* assembler) const {
+  typedef compiler::Node Node;
+  Node* native_context = assembler->LoadObjectField(
+      assembler->Parameter(
+          ArrayNoArgumentConstructorDescriptor::kFunctionIndex),
+      JSFunction::kContextOffset);
+  bool track_allocation_site =
+      AllocationSite::GetMode(elements_kind()) == TRACK_ALLOCATION_SITE &&
+      override_mode() != DISABLE_ALLOCATION_SITES;
+  Node* allocation_site =
+      track_allocation_site
+          ? assembler->Parameter(
+                ArrayNoArgumentConstructorDescriptor::kAllocationSiteIndex)
+          : nullptr;
+  Node* array_map =
+      assembler->LoadJSArrayElementsMap(elements_kind(), native_context);
+  Node* array = assembler->AllocateJSArray(
+      elements_kind(), array_map,
+      assembler->IntPtrConstant(JSArray::kPreallocatedArrayElements),
+      assembler->IntPtrConstant(0), allocation_site);
+  assembler->Return(array);
+}
+
+void InternalArrayNoArgumentConstructorStub::GenerateAssembly(
+    CodeStubAssembler* assembler) const {
+  typedef compiler::Node Node;
+  Node* array_map = assembler->LoadObjectField(
+      assembler->Parameter(
+          ArrayNoArgumentConstructorDescriptor::kFunctionIndex),
+      JSFunction::kPrototypeOrInitialMapOffset);
+  Node* array = assembler->AllocateJSArray(
+      elements_kind(), array_map,
+      assembler->IntPtrConstant(JSArray::kPreallocatedArrayElements),
+      assembler->IntPtrConstant(0), nullptr);
+  assembler->Return(array);
+}
+
+namespace {
+
+void SingleArgumentConstructorCommon(CodeStubAssembler* assembler,
+                                     ElementsKind elements_kind,
+                                     compiler::Node* array_map,
+                                     compiler::Node* allocation_site,
+                                     AllocationSiteMode mode) {
+  typedef compiler::Node Node;
+  typedef CodeStubAssembler::Label Label;
+
+  Label ok(assembler);
+  Label smi_size(assembler);
+  Label small_smi_size(assembler);
+  Label call_runtime(assembler, Label::kDeferred);
+
+  Node* size = assembler->Parameter(
+      ArraySingleArgumentConstructorDescriptor::kArraySizeSmiParameterIndex);
+  assembler->Branch(assembler->WordIsSmi(size), &smi_size, &call_runtime);
+
+  assembler->Bind(&smi_size);
+  int element_size =
+      IsFastDoubleElementsKind(elements_kind) ? kDoubleSize : kPointerSize;
+  int max_fast_elements =
+      (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize -
+       JSArray::kSize - AllocationMemento::kSize) /
+      element_size;
+  assembler->Branch(
+      assembler->SmiAboveOrEqual(
+          size, assembler->SmiConstant(Smi::FromInt(max_fast_elements))),
+      &call_runtime, &small_smi_size);
+
+  assembler->Bind(&small_smi_size);
+  {
+    Node* array = assembler->AllocateJSArray(
+        elements_kind, array_map, size, size,
+        mode == DONT_TRACK_ALLOCATION_SITE ? nullptr : allocation_site,
+        CodeStubAssembler::SMI_PARAMETERS);
+    assembler->Return(array);
+  }
+
+  assembler->Bind(&call_runtime);
+  {
+    Node* context = assembler->Parameter(
+        ArraySingleArgumentConstructorDescriptor::kContextIndex);
+    Node* function = assembler->Parameter(
+        ArraySingleArgumentConstructorDescriptor::kFunctionIndex);
+    Node* array_size = assembler->Parameter(
+        ArraySingleArgumentConstructorDescriptor::kArraySizeSmiParameterIndex);
+    Node* allocation_site = assembler->Parameter(
+        ArraySingleArgumentConstructorDescriptor::kAllocationSiteIndex);
+    assembler->TailCallRuntime(Runtime::kNewArray, context, function,
+                               array_size, function, allocation_site);
+  }
+}
+}  // namespace
+
+void ArraySingleArgumentConstructorStub::GenerateAssembly(
+    CodeStubAssembler* assembler) const {
+  typedef compiler::Node Node;
+  Node* function = assembler->Parameter(
+      ArraySingleArgumentConstructorDescriptor::kFunctionIndex);
+  Node* native_context =
+      assembler->LoadObjectField(function, JSFunction::kContextOffset);
+  Node* array_map =
+      assembler->LoadJSArrayElementsMap(elements_kind(), native_context);
+  AllocationSiteMode mode = override_mode() == DISABLE_ALLOCATION_SITES
+                                ? DONT_TRACK_ALLOCATION_SITE
+                                : AllocationSite::GetMode(elements_kind());
+  Node* allocation_site = assembler->Parameter(
+      ArrayNoArgumentConstructorDescriptor::kAllocationSiteIndex);
+  SingleArgumentConstructorCommon(assembler, elements_kind(), array_map,
+                                  allocation_site, mode);
+}
+
+void InternalArraySingleArgumentConstructorStub::GenerateAssembly(
+    CodeStubAssembler* assembler) const {
+  typedef compiler::Node Node;
+  Node* function = assembler->Parameter(
+      ArraySingleArgumentConstructorDescriptor::kFunctionIndex);
+  Node* array_map = assembler->LoadObjectField(
+      function, JSFunction::kPrototypeOrInitialMapOffset);
+  SingleArgumentConstructorCommon(assembler, elements_kind(), array_map,
+                                  assembler->UndefinedConstant(),
+                                  DONT_TRACK_ALLOCATION_SITE);
+}
 
 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
     : PlatformCodeStub(isolate) {
   minor_key_ = ArgumentCountBits::encode(ANY);
-  ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
 }
 
 
@@ -3492,15 +4713,10 @@
   } else {
     UNREACHABLE();
   }
-  ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
 }
 
-
-InternalArrayConstructorStub::InternalArrayConstructorStub(
-    Isolate* isolate) : PlatformCodeStub(isolate) {
-  InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
-}
-
+InternalArrayConstructorStub::InternalArrayConstructorStub(Isolate* isolate)
+    : PlatformCodeStub(isolate) {}
 
 Representation RepresentationFromType(Type* type) {
   if (type->Is(Type::UntaggedIntegral())) {
diff --git a/src/code-stubs.h b/src/code-stubs.h
index ace4aae..85b0883 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -7,8 +7,8 @@
 
 #include "src/allocation.h"
 #include "src/assembler.h"
+#include "src/code-stub-assembler.h"
 #include "src/codegen.h"
-#include "src/compiler/code-stub-assembler.h"
 #include "src/globals.h"
 #include "src/ic/ic-state.h"
 #include "src/interface-descriptors.h"
@@ -31,11 +31,11 @@
   V(CompareIC)                              \
   V(DoubleToI)                              \
   V(FunctionPrototype)                      \
-  V(InstanceOf)                             \
   V(InternalArrayConstructor)               \
   V(JSEntry)                                \
   V(KeyedLoadICTrampoline)                  \
   V(LoadICTrampoline)                       \
+  V(LoadGlobalICTrampoline)                 \
   V(CallICTrampoline)                       \
   V(LoadIndexedString)                      \
   V(MathPow)                                \
@@ -46,9 +46,6 @@
   V(StoreElement)                           \
   V(StubFailureTrampoline)                  \
   V(SubString)                              \
-  V(ToNumber)                               \
-  V(NonNumberToNumber)                      \
-  V(StringToNumber)                         \
   V(ToString)                               \
   V(ToName)                                 \
   V(ToObject)                               \
@@ -57,10 +54,6 @@
   V(VectorStoreIC)                          \
   V(VectorKeyedStoreIC)                     \
   /* HydrogenCodeStubs */                   \
-  V(AllocateInNewSpace)                     \
-  V(ArrayNArgumentsConstructor)             \
-  V(ArrayNoArgumentConstructor)             \
-  V(ArraySingleArgumentConstructor)         \
   V(BinaryOpIC)                             \
   V(BinaryOpWithAllocationSite)             \
   V(CreateAllocationSite)                   \
@@ -69,7 +62,7 @@
   V(FastArrayPush)                          \
   V(FastCloneRegExp)                        \
   V(FastCloneShallowArray)                  \
-  V(FastCloneShallowObject)                 \
+  V(FastFunctionBind)                       \
   V(FastNewClosure)                         \
   V(FastNewContext)                         \
   V(FastNewObject)                          \
@@ -77,11 +70,7 @@
   V(FastNewSloppyArguments)                 \
   V(FastNewStrictArguments)                 \
   V(GrowArrayElements)                      \
-  V(InternalArrayNArgumentsConstructor)     \
-  V(InternalArrayNoArgumentConstructor)     \
-  V(InternalArraySingleArgumentConstructor) \
   V(KeyedLoadGeneric)                       \
-  V(LoadGlobalViaContext)                   \
   V(LoadScriptContextField)                 \
   V(LoadDictionaryElement)                  \
   V(NameDictionaryLookup)                   \
@@ -96,9 +85,9 @@
   V(TransitionElementsKind)                 \
   V(KeyedLoadIC)                            \
   V(LoadIC)                                 \
+  V(LoadGlobalIC)                           \
   /* TurboFanCodeStubs */                   \
   V(AllocateHeapNumber)                     \
-  V(AllocateMutableHeapNumber)              \
   V(AllocateFloat32x4)                      \
   V(AllocateInt32x4)                        \
   V(AllocateUint32x4)                       \
@@ -109,12 +98,27 @@
   V(AllocateInt8x16)                        \
   V(AllocateUint8x16)                       \
   V(AllocateBool8x16)                       \
+  V(ArrayNoArgumentConstructor)             \
+  V(ArraySingleArgumentConstructor)         \
+  V(ArrayNArgumentsConstructor)             \
   V(StringLength)                           \
   V(Add)                                    \
   V(Subtract)                               \
+  V(Multiply)                               \
+  V(Divide)                                 \
+  V(Modulus)                                \
+  V(ShiftRight)                             \
+  V(ShiftRightLogical)                      \
+  V(ShiftLeft)                              \
   V(BitwiseAnd)                             \
   V(BitwiseOr)                              \
   V(BitwiseXor)                             \
+  V(Inc)                                    \
+  V(InternalArrayNoArgumentConstructor)     \
+  V(InternalArraySingleArgumentConstructor) \
+  V(Dec)                                    \
+  V(FastCloneShallowObject)                 \
+  V(InstanceOf)                             \
   V(LessThan)                               \
   V(LessThanOrEqual)                        \
   V(GreaterThan)                            \
@@ -132,17 +136,20 @@
   V(ToBoolean)                              \
   V(ToInteger)                              \
   V(ToLength)                               \
+  V(HasProperty)                            \
+  V(LoadICTrampolineTF)                     \
+  V(LoadICTF)                               \
   /* IC Handler stubs */                    \
-  V(ArrayBufferViewLoadField)               \
+  V(KeyedLoadSloppyArguments)               \
+  V(KeyedStoreSloppyArguments)              \
+  V(LoadApiGetter)                          \
   V(LoadConstant)                           \
   V(LoadFastElement)                        \
   V(LoadField)                              \
   V(LoadIndexedInterceptor)                 \
-  V(KeyedLoadSloppyArguments)               \
-  V(KeyedStoreSloppyArguments)              \
   V(StoreField)                             \
-  V(StoreInterceptor)                       \
   V(StoreGlobal)                            \
+  V(StoreInterceptor)                       \
   V(StoreTransition)
 
 // List of code stubs only used on ARM 32 bits platforms.
@@ -282,9 +289,7 @@
   // BinaryOpStub needs to override this.
   virtual Code::Kind GetCodeKind() const;
 
-  virtual InlineCacheState GetICState() const { return UNINITIALIZED; }
   virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
-  virtual Code::StubType GetStubType() const { return Code::NORMAL; }
 
   Code::Flags GetCodeFlags() const;
 
@@ -390,10 +395,32 @@
   Handle<Code> GenerateCode() override;                               \
   DEFINE_CODE_STUB(NAME, SUPER)
 
-#define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER)                  \
- public:                                                        \
-  void GenerateAssembly(compiler::CodeStubAssembler* assembler) \
-      const override;                                           \
+#define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER)                        \
+ public:                                                              \
+  void GenerateAssembly(CodeStubAssembler* assembler) const override; \
+  DEFINE_CODE_STUB(NAME, SUPER)
+
+#define DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(NAME, SUPER)                       \
+ public:                                                                       \
+  static compiler::Node* Generate(CodeStubAssembler* assembler,                \
+                                  compiler::Node* left, compiler::Node* right, \
+                                  compiler::Node* context);                    \
+  void GenerateAssembly(CodeStubAssembler* assembler) const override {         \
+    assembler->Return(Generate(assembler, assembler->Parameter(0),             \
+                               assembler->Parameter(1),                        \
+                               assembler->Parameter(2)));                      \
+  }                                                                            \
+  DEFINE_CODE_STUB(NAME, SUPER)
+
+#define DEFINE_TURBOFAN_UNARY_OP_CODE_STUB(NAME, SUPER)                \
+ public:                                                               \
+  static compiler::Node* Generate(CodeStubAssembler* assembler,        \
+                                  compiler::Node* value,               \
+                                  compiler::Node* context);            \
+  void GenerateAssembly(CodeStubAssembler* assembler) const override { \
+    assembler->Return(Generate(assembler, assembler->Parameter(0),     \
+                               assembler->Parameter(1)));              \
+  }                                                                    \
   DEFINE_CODE_STUB(NAME, SUPER)
 
 #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
@@ -407,6 +434,12 @@
     return NAME##Descriptor(isolate());                                 \
   }
 
+#define DEFINE_ON_STACK_CALL_INTERFACE_DESCRIPTOR(PARAMETER_COUNT)         \
+ public:                                                                   \
+  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {    \
+    return OnStackArgsDescriptorBase::ForArgs(isolate(), PARAMETER_COUNT); \
+  }
+
 // There are some code stubs we just can't describe right now with a
 // CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
 // An attempt to retrieve a descriptor will fail.
@@ -579,13 +612,10 @@
     return GetCallInterfaceDescriptor().GetStackParameterCount();
   }
 
-  Code::StubType GetStubType() const override { return Code::FAST; }
-
  protected:
   explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {}
 
-  virtual void GenerateAssembly(
-      compiler::CodeStubAssembler* assembler) const = 0;
+  virtual void GenerateAssembly(CodeStubAssembler* assembler) const = 0;
 
  private:
   DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub);
@@ -666,7 +696,6 @@
   explicit StringLengthStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
 
   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
-  InlineCacheState GetICState() const override { return MONOMORPHIC; }
   ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
@@ -678,7 +707,7 @@
   explicit AddStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
-  DEFINE_TURBOFAN_CODE_STUB(Add, TurboFanCodeStub);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(Add, TurboFanCodeStub);
 };
 
 class SubtractStub final : public TurboFanCodeStub {
@@ -686,7 +715,56 @@
   explicit SubtractStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
-  DEFINE_TURBOFAN_CODE_STUB(Subtract, TurboFanCodeStub);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(Subtract, TurboFanCodeStub);
+};
+
+class MultiplyStub final : public TurboFanCodeStub {
+ public:
+  explicit MultiplyStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(Multiply, TurboFanCodeStub);
+};
+
+class DivideStub final : public TurboFanCodeStub {
+ public:
+  explicit DivideStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(Divide, TurboFanCodeStub);
+};
+
+class ModulusStub final : public TurboFanCodeStub {
+ public:
+  explicit ModulusStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(Modulus, TurboFanCodeStub);
+};
+
+class ShiftRightStub final : public TurboFanCodeStub {
+ public:
+  explicit ShiftRightStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(ShiftRight, TurboFanCodeStub);
+};
+
+class ShiftRightLogicalStub final : public TurboFanCodeStub {
+ public:
+  explicit ShiftRightLogicalStub(Isolate* isolate)
+      : TurboFanCodeStub(isolate) {}
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(ShiftRightLogical, TurboFanCodeStub);
+};
+
+class ShiftLeftStub final : public TurboFanCodeStub {
+ public:
+  explicit ShiftLeftStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(ShiftLeft, TurboFanCodeStub);
 };
 
 class BitwiseAndStub final : public TurboFanCodeStub {
@@ -694,7 +772,7 @@
   explicit BitwiseAndStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
-  DEFINE_TURBOFAN_CODE_STUB(BitwiseAnd, TurboFanCodeStub);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(BitwiseAnd, TurboFanCodeStub);
 };
 
 class BitwiseOrStub final : public TurboFanCodeStub {
@@ -702,7 +780,7 @@
   explicit BitwiseOrStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
-  DEFINE_TURBOFAN_CODE_STUB(BitwiseOr, TurboFanCodeStub);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(BitwiseOr, TurboFanCodeStub);
 };
 
 class BitwiseXorStub final : public TurboFanCodeStub {
@@ -710,7 +788,32 @@
   explicit BitwiseXorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
-  DEFINE_TURBOFAN_CODE_STUB(BitwiseXor, TurboFanCodeStub);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(BitwiseXor, TurboFanCodeStub);
+};
+
+class IncStub final : public TurboFanCodeStub {
+ public:
+  explicit IncStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(CountOp);
+  DEFINE_TURBOFAN_UNARY_OP_CODE_STUB(Inc, TurboFanCodeStub);
+};
+
+class DecStub final : public TurboFanCodeStub {
+ public:
+  explicit DecStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(CountOp);
+  DEFINE_TURBOFAN_UNARY_OP_CODE_STUB(Dec, TurboFanCodeStub);
+};
+
+class InstanceOfStub final : public TurboFanCodeStub {
+ public:
+  explicit InstanceOfStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
+
+ private:
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(InstanceOf, TurboFanCodeStub);
 };
 
 class LessThanStub final : public TurboFanCodeStub {
@@ -718,7 +821,7 @@
   explicit LessThanStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
-  DEFINE_TURBOFAN_CODE_STUB(LessThan, TurboFanCodeStub);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(LessThan, TurboFanCodeStub);
 };
 
 class LessThanOrEqualStub final : public TurboFanCodeStub {
@@ -726,7 +829,7 @@
   explicit LessThanOrEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
-  DEFINE_TURBOFAN_CODE_STUB(LessThanOrEqual, TurboFanCodeStub);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(LessThanOrEqual, TurboFanCodeStub);
 };
 
 class GreaterThanStub final : public TurboFanCodeStub {
@@ -734,7 +837,7 @@
   explicit GreaterThanStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
-  DEFINE_TURBOFAN_CODE_STUB(GreaterThan, TurboFanCodeStub);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(GreaterThan, TurboFanCodeStub);
 };
 
 class GreaterThanOrEqualStub final : public TurboFanCodeStub {
@@ -743,7 +846,7 @@
       : TurboFanCodeStub(isolate) {}
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
-  DEFINE_TURBOFAN_CODE_STUB(GreaterThanOrEqual, TurboFanCodeStub);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(GreaterThanOrEqual, TurboFanCodeStub);
 };
 
 class EqualStub final : public TurboFanCodeStub {
@@ -751,7 +854,7 @@
   explicit EqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
-  DEFINE_TURBOFAN_CODE_STUB(Equal, TurboFanCodeStub);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(Equal, TurboFanCodeStub);
 };
 
 class NotEqualStub final : public TurboFanCodeStub {
@@ -759,7 +862,7 @@
   explicit NotEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
-  DEFINE_TURBOFAN_CODE_STUB(NotEqual, TurboFanCodeStub);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(NotEqual, TurboFanCodeStub);
 };
 
 class StrictEqualStub final : public TurboFanCodeStub {
@@ -767,7 +870,7 @@
   explicit StrictEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
-  DEFINE_TURBOFAN_CODE_STUB(StrictEqual, TurboFanCodeStub);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(StrictEqual, TurboFanCodeStub);
 };
 
 class StrictNotEqualStub final : public TurboFanCodeStub {
@@ -775,7 +878,7 @@
   explicit StrictNotEqualStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(Compare);
-  DEFINE_TURBOFAN_CODE_STUB(StrictNotEqual, TurboFanCodeStub);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(StrictNotEqual, TurboFanCodeStub);
 };
 
 class StringEqualStub final : public TurboFanCodeStub {
@@ -834,7 +937,7 @@
   explicit ToBooleanStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(TypeConversion);
-  DEFINE_TURBOFAN_CODE_STUB(ToBoolean, TurboFanCodeStub);
+  DEFINE_TURBOFAN_UNARY_OP_CODE_STUB(ToBoolean, TurboFanCodeStub);
 };
 
 class ToIntegerStub final : public TurboFanCodeStub {
@@ -857,9 +960,10 @@
  public:
   explicit StoreInterceptorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
 
-  void GenerateAssembly(compiler::CodeStubAssembler* assember) const override;
+  void GenerateAssembly(CodeStubAssembler* assember) const override;
 
   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
+  ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
   DEFINE_CODE_STUB(StoreInterceptor, TurboFanCodeStub);
@@ -871,11 +975,21 @@
       : TurboFanCodeStub(isolate) {}
 
   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
+  ExtraICState GetExtraICState() const override { return Code::KEYED_LOAD_IC; }
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
   DEFINE_TURBOFAN_CODE_STUB(LoadIndexedInterceptor, TurboFanCodeStub);
 };
 
+// ES6 section 12.10.3 "in" operator evaluation.
+class HasPropertyStub : public TurboFanCodeStub {
+ public:
+  explicit HasPropertyStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(HasProperty);
+  DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(HasProperty, TurboFanCodeStub);
+};
+
 enum StringAddFlags {
   // Omit both parameter checks.
   STRING_ADD_CHECK_NONE = 0,
@@ -942,7 +1056,7 @@
  private:
   STATIC_ASSERT(LANGUAGE_END == 3);
   class LanguageModeBits : public BitField<LanguageMode, 0, 2> {};
-  class FunctionKindBits : public BitField<FunctionKind, 2, 8> {};
+  class FunctionKindBits : public BitField<FunctionKind, 2, 9> {};
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
   DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
@@ -986,11 +1100,19 @@
 // of the strict arguments object materialization code.
 class FastNewRestParameterStub final : public PlatformCodeStub {
  public:
-  explicit FastNewRestParameterStub(Isolate* isolate)
-      : PlatformCodeStub(isolate) {}
+  explicit FastNewRestParameterStub(Isolate* isolate,
+                                    bool skip_stub_frame = false)
+      : PlatformCodeStub(isolate) {
+    minor_key_ = SkipStubFrameBits::encode(skip_stub_frame);
+  }
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewRestParameter);
   DEFINE_PLATFORM_CODE_STUB(FastNewRestParameter, PlatformCodeStub);
+
+  int skip_stub_frame() const { return SkipStubFrameBits::decode(minor_key_); }
+
+ private:
+  class SkipStubFrameBits : public BitField<bool, 0, 1> {};
 };
 
 
@@ -999,11 +1121,19 @@
 // and easy as the current handwritten version.
 class FastNewSloppyArgumentsStub final : public PlatformCodeStub {
  public:
-  explicit FastNewSloppyArgumentsStub(Isolate* isolate)
-      : PlatformCodeStub(isolate) {}
+  explicit FastNewSloppyArgumentsStub(Isolate* isolate,
+                                      bool skip_stub_frame = false)
+      : PlatformCodeStub(isolate) {
+    minor_key_ = SkipStubFrameBits::encode(skip_stub_frame);
+  }
+
+  int skip_stub_frame() const { return SkipStubFrameBits::decode(minor_key_); }
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewSloppyArguments);
   DEFINE_PLATFORM_CODE_STUB(FastNewSloppyArguments, PlatformCodeStub);
+
+ private:
+  class SkipStubFrameBits : public BitField<bool, 0, 1> {};
 };
 
 
@@ -1012,11 +1142,19 @@
 // and easy as the current handwritten version.
 class FastNewStrictArgumentsStub final : public PlatformCodeStub {
  public:
-  explicit FastNewStrictArgumentsStub(Isolate* isolate)
-      : PlatformCodeStub(isolate) {}
+  explicit FastNewStrictArgumentsStub(Isolate* isolate,
+                                      bool skip_stub_frame = false)
+      : PlatformCodeStub(isolate) {
+    minor_key_ = SkipStubFrameBits::encode(skip_stub_frame);
+  }
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewStrictArguments);
   DEFINE_PLATFORM_CODE_STUB(FastNewStrictArguments, PlatformCodeStub);
+
+  int skip_stub_frame() const { return SkipStubFrameBits::decode(minor_key_); }
+
+ private:
+  class SkipStubFrameBits : public BitField<bool, 0, 1> {};
 };
 
 
@@ -1049,26 +1187,33 @@
   DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowArray, HydrogenCodeStub);
 };
 
-
-class FastCloneShallowObjectStub : public HydrogenCodeStub {
+class FastCloneShallowObjectStub : public TurboFanCodeStub {
  public:
   // Maximum number of properties in copied object.
   static const int kMaximumClonedProperties = 6;
 
   FastCloneShallowObjectStub(Isolate* isolate, int length)
-      : HydrogenCodeStub(isolate) {
+      : TurboFanCodeStub(isolate) {
     DCHECK_GE(length, 0);
     DCHECK_LE(length, kMaximumClonedProperties);
-    set_sub_minor_key(LengthBits::encode(length));
+    minor_key_ = LengthBits::encode(LengthBits::encode(length));
   }
 
-  int length() const { return LengthBits::decode(sub_minor_key()); }
+  static compiler::Node* GenerateFastPath(
+      CodeStubAssembler* assembler,
+      compiler::CodeAssembler::Label* call_runtime, compiler::Node* closure,
+      compiler::Node* literals_index, compiler::Node* properties_count);
+
+  static bool IsSupported(ObjectLiteral* expr);
+  static int PropertiesCount(int literal_length);
+
+  int length() const { return LengthBits::decode(minor_key_); }
 
  private:
   class LengthBits : public BitField<int, 0, 4> {};
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowObject);
-  DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowObject, HydrogenCodeStub);
+  DEFINE_TURBOFAN_CODE_STUB(FastCloneShallowObject, TurboFanCodeStub);
 };
 
 
@@ -1122,29 +1267,19 @@
   explicit FastArrayPushStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
 
  private:
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(FastArrayPush);
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(VarArgFunction);
   DEFINE_HYDROGEN_CODE_STUB(FastArrayPush, HydrogenCodeStub);
 };
 
-class InstanceOfStub final : public PlatformCodeStub {
+class FastFunctionBindStub : public HydrogenCodeStub {
  public:
-  explicit InstanceOfStub(Isolate* isolate, bool es6_instanceof = false)
-      : PlatformCodeStub(isolate) {
-    minor_key_ = IsES6InstanceOfBits::encode(es6_instanceof);
-  }
-
-  bool is_es6_instanceof() const {
-    return IsES6InstanceOfBits::decode(minor_key_);
-  }
+  explicit FastFunctionBindStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
 
  private:
-  class IsES6InstanceOfBits : public BitField<bool, 0, 1> {};
-
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(InstanceOf);
-  DEFINE_PLATFORM_CODE_STUB(InstanceOf, PlatformCodeStub);
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(VarArgFunction);
+  DEFINE_HYDROGEN_CODE_STUB(FastFunctionBind, HydrogenCodeStub);
 };
 
-
 enum AllocationSiteOverrideMode {
   DONT_OVERRIDE,
   DISABLE_ALLOCATION_SITES,
@@ -1172,7 +1307,7 @@
 
   class ArgumentCountBits : public BitField<ArgumentCountKey, 0, 2> {};
 
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNArgumentsConstructor);
   DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub);
 };
 
@@ -1184,7 +1319,7 @@
  private:
   void GenerateCase(MacroAssembler* masm, ElementsKind kind);
 
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNArgumentsConstructor);
   DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
 };
 
@@ -1199,13 +1334,17 @@
   }
 
   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
-    if (exponent_type() == TAGGED) {
+    if (exponent_type() == ON_STACK) {
+      return OnStackArgsDescriptorBase::ForArgs(isolate(), 2);
+    } else if (exponent_type() == TAGGED) {
       return MathPowTaggedDescriptor(isolate());
     } else if (exponent_type() == INTEGER) {
       return MathPowIntegerDescriptor(isolate());
+    } else {
+      // A CallInterfaceDescriptor doesn't specify double registers (yet).
+      DCHECK_EQ(DOUBLE, exponent_type());
+      return ContextOnlyDescriptor(isolate());
     }
-    // A CallInterfaceDescriptor doesn't specify double registers (yet).
-    return ContextOnlyDescriptor(isolate());
   }
 
  private:
@@ -1228,8 +1367,6 @@
 
   Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
 
-  InlineCacheState GetICState() const override { return GENERIC; }
-
   ExtraICState GetExtraICState() const final {
     return static_cast<ExtraICState>(minor_key_);
   }
@@ -1239,9 +1376,7 @@
   ConvertReceiverMode convert_mode() const { return state().convert_mode(); }
   TailCallMode tail_call_mode() const { return state().tail_call_mode(); }
 
-  CallICState state() const {
-    return CallICState(static_cast<ExtraICState>(minor_key_));
-  }
+  CallICState state() const { return CallICState(GetExtraICState()); }
 
   // Code generation helpers.
   void GenerateMiss(MacroAssembler* masm);
@@ -1280,7 +1415,6 @@
       : PlatformCodeStub(isolate) {}
 
   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
-  Code::StubType GetStubType() const override { return Code::FAST; }
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
   DEFINE_PLATFORM_CODE_STUB(LoadIndexedString, PlatformCodeStub);
@@ -1291,7 +1425,6 @@
  public:
   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
   ExtraICState GetExtraICState() const override { return kind(); }
-  InlineCacheState GetICState() const override { return MONOMORPHIC; }
 
   void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
 
@@ -1320,7 +1453,6 @@
 
  protected:
   Code::Kind kind() const override { return Code::LOAD_IC; }
-  Code::StubType GetStubType() const override { return Code::FAST; }
 
  private:
   class LoadFieldByIndexBits : public BitField<int, 0, 13> {};
@@ -1329,32 +1461,6 @@
 };
 
 
-class ArrayBufferViewLoadFieldStub : public HandlerStub {
- public:
-  ArrayBufferViewLoadFieldStub(Isolate* isolate, FieldIndex index)
-      : HandlerStub(isolate) {
-    int property_index_key = index.GetFieldAccessStubKey();
-    set_sub_minor_key(
-        ArrayBufferViewLoadFieldByIndexBits::encode(property_index_key));
-  }
-
-  FieldIndex index() const {
-    int property_index_key =
-        ArrayBufferViewLoadFieldByIndexBits::decode(sub_minor_key());
-    return FieldIndex::FromFieldAccessStubKey(property_index_key);
-  }
-
- protected:
-  Code::Kind kind() const override { return Code::LOAD_IC; }
-  Code::StubType GetStubType() const override { return Code::FAST; }
-
- private:
-  class ArrayBufferViewLoadFieldByIndexBits : public BitField<int, 0, 13> {};
-
-  DEFINE_HANDLER_CODE_STUB(ArrayBufferViewLoadField, HandlerStub);
-};
-
-
 class KeyedLoadSloppyArgumentsStub : public HandlerStub {
  public:
   explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
@@ -1362,7 +1468,6 @@
 
  protected:
   Code::Kind kind() const override { return Code::KEYED_LOAD_IC; }
-  Code::StubType GetStubType() const override { return Code::FAST; }
 
  private:
   DEFINE_HANDLER_CODE_STUB(KeyedLoadSloppyArguments, HandlerStub);
@@ -1381,7 +1486,6 @@
 
  protected:
   Code::Kind kind() const override { return Code::KEYED_STORE_IC; }
-  Code::StubType GetStubType() const override { return Code::FAST; }
 
  private:
   DEFINE_HANDLER_CODE_STUB(KeyedStoreSloppyArguments, HandlerStub);
@@ -1401,7 +1505,6 @@
 
  protected:
   Code::Kind kind() const override { return Code::LOAD_IC; }
-  Code::StubType GetStubType() const override { return Code::FAST; }
 
  private:
   class ConstantIndexBits : public BitField<int, 0, kSubMinorKeyBits> {};
@@ -1409,6 +1512,32 @@
   DEFINE_HANDLER_CODE_STUB(LoadConstant, HandlerStub);
 };
 
+class LoadApiGetterStub : public TurboFanCodeStub {
+ public:
+  LoadApiGetterStub(Isolate* isolate, bool receiver_is_holder, int index)
+      : TurboFanCodeStub(isolate) {
+    // If that's not true, we need to ensure that the receiver is actually a
+    // JSReceiver. http://crbug.com/609134
+    DCHECK(receiver_is_holder);
+    minor_key_ = IndexBits::encode(index) |
+                 ReceiverIsHolderBits::encode(receiver_is_holder);
+  }
+
+  Code::Kind GetCodeKind() const override { return Code::HANDLER; }
+  ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
+
+  int index() const { return IndexBits::decode(minor_key_); }
+  bool receiver_is_holder() const {
+    return ReceiverIsHolderBits::decode(minor_key_);
+  }
+
+ private:
+  class ReceiverIsHolderBits : public BitField<bool, 0, 1> {};
+  class IndexBits : public BitField<int, 1, kDescriptorIndexBitCount> {};
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
+  DEFINE_TURBOFAN_CODE_STUB(LoadApiGetter, TurboFanCodeStub);
+};
 
 class StoreFieldStub : public HandlerStub {
  public:
@@ -1433,7 +1562,6 @@
 
  protected:
   Code::Kind kind() const override { return Code::STORE_IC; }
-  Code::StubType GetStubType() const override { return Code::FAST; }
 
  private:
   class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
@@ -1543,7 +1671,6 @@
 
  protected:
   Code::Kind kind() const override { return Code::STORE_IC; }
-  Code::StubType GetStubType() const override { return Code::FAST; }
 
  private:
   class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
@@ -1619,26 +1746,6 @@
 };
 
 
-class LoadGlobalViaContextStub final : public PlatformCodeStub {
- public:
-  static const int kMaximumDepth = 15;
-
-  LoadGlobalViaContextStub(Isolate* isolate, int depth)
-      : PlatformCodeStub(isolate) {
-    minor_key_ = DepthBits::encode(depth);
-  }
-
-  int depth() const { return DepthBits::decode(minor_key_); }
-
- private:
-  class DepthBits : public BitField<int, 0, 4> {};
-  STATIC_ASSERT(DepthBits::kMax == kMaximumDepth);
-
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobalViaContext);
-  DEFINE_PLATFORM_CODE_STUB(LoadGlobalViaContext, PlatformCodeStub);
-};
-
-
 class StoreGlobalViaContextStub final : public PlatformCodeStub {
  public:
   static const int kMaximumDepth = 15;
@@ -1737,8 +1844,6 @@
 
   Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
 
-  InlineCacheState GetICState() const final { return state().GetICState(); }
-
   ExtraICState GetExtraICState() const final {
     return static_cast<ExtraICState>(sub_minor_key());
   }
@@ -1782,8 +1887,6 @@
 
   Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
 
-  InlineCacheState GetICState() const override { return state().GetICState(); }
-
   ExtraICState GetExtraICState() const override {
     return static_cast<ExtraICState>(minor_key_);
   }
@@ -1792,7 +1895,7 @@
 
  private:
   BinaryOpICState state() const {
-    return BinaryOpICState(isolate(), static_cast<ExtraICState>(minor_key_));
+    return BinaryOpICState(isolate(), GetExtraICState());
   }
 
   static void GenerateAheadOfTime(Isolate* isolate,
@@ -1861,14 +1964,19 @@
                 CompareICState::State right, CompareICState::State state)
       : PlatformCodeStub(isolate) {
     DCHECK(Token::IsCompareOp(op));
+    DCHECK(OpBits::is_valid(op - Token::EQ));
     minor_key_ = OpBits::encode(op - Token::EQ) |
                  LeftStateBits::encode(left) | RightStateBits::encode(right) |
                  StateBits::encode(state);
   }
+  CompareICStub(Isolate* isolate, ExtraICState extra_ic_state)
+      : PlatformCodeStub(isolate) {
+    minor_key_ = extra_ic_state;
+  }
 
   void set_known_map(Handle<Map> map) { known_map_ = map; }
 
-  InlineCacheState GetICState() const override;
+  InlineCacheState GetICState() const;
 
   Token::Value op() const {
     return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
@@ -1899,8 +2007,9 @@
   bool strict() const { return op() == Token::EQ_STRICT; }
   Condition GetCondition() const;
 
-  void AddToSpecialCache(Handle<Code> new_object) override;
-  bool FindCodeInSpecialCache(Code** code_out) override;
+  // Although we don't cache anything in the special cache we have to define
+  // this predicate to avoid appearance of code stubs with embedded maps in
+  // the global stub cache.
   bool UseSpecialCache() override {
     return state() == CompareICState::KNOWN_RECEIVER;
   }
@@ -1984,7 +2093,7 @@
  public:
   explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
 
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
+  DEFINE_ON_STACK_CALL_INTERFACE_DESCRIPTOR(4);
   DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
 };
 
@@ -2014,17 +2123,6 @@
 };
 
 
-enum StringIndexFlags {
-  // Accepts smis or heap numbers.
-  STRING_INDEX_IS_NUMBER,
-
-  // Accepts smis or heap numbers that are valid array indices
-  // (ECMA-262 15.4). Invalid indices are reported as being out of
-  // range.
-  STRING_INDEX_IS_ARRAY_INDEX
-};
-
-
 enum ReceiverCheckMode {
   // We don't know anything about the receiver.
   RECEIVER_IS_UNKNOWN,
@@ -2058,7 +2156,6 @@
   StringCharCodeAtGenerator(Register object, Register index, Register result,
                             Label* receiver_not_string, Label* index_not_number,
                             Label* index_out_of_range,
-                            StringIndexFlags index_flags,
                             ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
       : object_(object),
         index_(index),
@@ -2066,7 +2163,6 @@
         receiver_not_string_(receiver_not_string),
         index_not_number_(index_not_number),
         index_out_of_range_(index_out_of_range),
-        index_flags_(index_flags),
         check_mode_(check_mode) {
     DCHECK(!result_.is(object_));
     DCHECK(!result_.is(index_));
@@ -2098,7 +2194,6 @@
   Label* index_not_number_;
   Label* index_out_of_range_;
 
-  StringIndexFlags index_flags_;
   ReceiverCheckMode check_mode_;
 
   Label call_runtime_;
@@ -2162,11 +2257,10 @@
   StringCharAtGenerator(Register object, Register index, Register scratch,
                         Register result, Label* receiver_not_string,
                         Label* index_not_number, Label* index_out_of_range,
-                        StringIndexFlags index_flags,
                         ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
       : char_code_at_generator_(object, index, scratch, receiver_not_string,
                                 index_not_number, index_out_of_range,
-                                index_flags, check_mode),
+                                check_mode),
         char_from_code_generator_(scratch, result) {}
 
   // Generates the fast case code. On the fallthrough path |result|
@@ -2201,64 +2295,72 @@
 
 class LoadDictionaryElementStub : public HydrogenCodeStub {
  public:
-  explicit LoadDictionaryElementStub(Isolate* isolate, const LoadICState& state)
-      : HydrogenCodeStub(isolate) {
-    minor_key_ = state.GetExtraICState();
-  }
+  explicit LoadDictionaryElementStub(Isolate* isolate)
+      : HydrogenCodeStub(isolate) {}
 
-  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
-    return LoadWithVectorDescriptor(isolate());
-  }
-
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
   DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
 };
 
 
 class KeyedLoadGenericStub : public HydrogenCodeStub {
  public:
-  explicit KeyedLoadGenericStub(Isolate* isolate, const LoadICState& state)
-      : HydrogenCodeStub(isolate) {
-    minor_key_ = state.GetExtraICState();
-  }
+  explicit KeyedLoadGenericStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
 
   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
-  InlineCacheState GetICState() const override { return GENERIC; }
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
-
   DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub);
 };
 
 
 class LoadICTrampolineStub : public PlatformCodeStub {
  public:
-  LoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
-      : PlatformCodeStub(isolate) {
-    minor_key_ = state.GetExtraICState();
-  }
+  explicit LoadICTrampolineStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
 
   Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
 
-  InlineCacheState GetICState() const final { return GENERIC; }
-
-  ExtraICState GetExtraICState() const final {
-    return static_cast<ExtraICState>(minor_key_);
-  }
-
- protected:
-  LoadICState state() const {
-    return LoadICState(static_cast<ExtraICState>(minor_key_));
-  }
-
   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
   DEFINE_PLATFORM_CODE_STUB(LoadICTrampoline, PlatformCodeStub);
 };
 
+class LoadICTrampolineTFStub : public TurboFanCodeStub {
+ public:
+  explicit LoadICTrampolineTFStub(Isolate* isolate)
+      : TurboFanCodeStub(isolate) {}
+
+  void GenerateAssembly(CodeStubAssembler* assembler) const override;
+
+  Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
+  DEFINE_CODE_STUB(LoadICTrampolineTF, TurboFanCodeStub);
+};
+
+class LoadGlobalICTrampolineStub : public TurboFanCodeStub {
+ public:
+  explicit LoadGlobalICTrampolineStub(Isolate* isolate,
+                                      const LoadGlobalICState& state)
+      : TurboFanCodeStub(isolate) {
+    minor_key_ = state.GetExtraICState();
+  }
+
+  void GenerateAssembly(CodeStubAssembler* assembler) const override;
+
+  Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; }
+
+  ExtraICState GetExtraICState() const final {
+    return static_cast<ExtraICState>(minor_key_);
+  }
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobal);
+  DEFINE_CODE_STUB(LoadGlobalICTrampoline, TurboFanCodeStub);
+};
 
 class KeyedLoadICTrampolineStub : public LoadICTrampolineStub {
  public:
-  explicit KeyedLoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
-      : LoadICTrampolineStub(isolate, state) {}
+  explicit KeyedLoadICTrampolineStub(Isolate* isolate)
+      : LoadICTrampolineStub(isolate) {}
 
   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
 
@@ -2275,8 +2377,6 @@
 
   Code::Kind GetCodeKind() const override { return Code::STORE_IC; }
 
-  InlineCacheState GetICState() const final { return GENERIC; }
-
   ExtraICState GetExtraICState() const final {
     return static_cast<ExtraICState>(minor_key_);
   }
@@ -2313,8 +2413,6 @@
 
   Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
 
-  InlineCacheState GetICState() const final { return GENERIC; }
-
   ExtraICState GetExtraICState() const final {
     return static_cast<ExtraICState>(minor_key_);
   }
@@ -2331,18 +2429,11 @@
 
 class LoadICStub : public PlatformCodeStub {
  public:
-  explicit LoadICStub(Isolate* isolate, const LoadICState& state)
-      : PlatformCodeStub(isolate) {
-    minor_key_ = state.GetExtraICState();
-  }
+  explicit LoadICStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
 
   void GenerateForTrampoline(MacroAssembler* masm);
 
   Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
-  InlineCacheState GetICState() const final { return GENERIC; }
-  ExtraICState GetExtraICState() const final {
-    return static_cast<ExtraICState>(minor_key_);
-  }
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
   DEFINE_PLATFORM_CODE_STUB(LoadIC, PlatformCodeStub);
@@ -2351,21 +2442,44 @@
   void GenerateImpl(MacroAssembler* masm, bool in_frame);
 };
 
+class LoadICTFStub : public TurboFanCodeStub {
+ public:
+  explicit LoadICTFStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
+
+  void GenerateAssembly(CodeStubAssembler* assembler) const override;
+
+  Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
+  DEFINE_CODE_STUB(LoadICTF, TurboFanCodeStub);
+};
+
+class LoadGlobalICStub : public TurboFanCodeStub {
+ public:
+  explicit LoadGlobalICStub(Isolate* isolate, const LoadGlobalICState& state)
+      : TurboFanCodeStub(isolate) {
+    minor_key_ = state.GetExtraICState();
+  }
+
+  void GenerateAssembly(CodeStubAssembler* assembler) const override;
+
+  Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; }
+
+  ExtraICState GetExtraICState() const final {
+    return static_cast<ExtraICState>(minor_key_);
+  }
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobalWithVector);
+  DEFINE_CODE_STUB(LoadGlobalIC, TurboFanCodeStub);
+};
 
 class KeyedLoadICStub : public PlatformCodeStub {
  public:
-  explicit KeyedLoadICStub(Isolate* isolate, const LoadICState& state)
-      : PlatformCodeStub(isolate) {
-    minor_key_ = state.GetExtraICState();
-  }
+  explicit KeyedLoadICStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
 
   void GenerateForTrampoline(MacroAssembler* masm);
 
   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
-  InlineCacheState GetICState() const final { return GENERIC; }
-  ExtraICState GetExtraICState() const final {
-    return static_cast<ExtraICState>(minor_key_);
-  }
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
   DEFINE_PLATFORM_CODE_STUB(KeyedLoadIC, PlatformCodeStub);
@@ -2385,7 +2499,7 @@
   void GenerateForTrampoline(MacroAssembler* masm);
 
   Code::Kind GetCodeKind() const final { return Code::STORE_IC; }
-  InlineCacheState GetICState() const final { return GENERIC; }
+
   ExtraICState GetExtraICState() const final {
     return static_cast<ExtraICState>(minor_key_);
   }
@@ -2408,7 +2522,7 @@
   void GenerateForTrampoline(MacroAssembler* masm);
 
   Code::Kind GetCodeKind() const final { return Code::KEYED_STORE_IC; }
-  InlineCacheState GetICState() const final { return GENERIC; }
+
   ExtraICState GetExtraICState() const final {
     return static_cast<ExtraICState>(minor_key_);
   }
@@ -2492,13 +2606,11 @@
 
  private:
   static const int kContextIndexBits = 9;
-  static const int kSlotIndexBits = 13;
+  static const int kSlotIndexBits = 12;
   class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {};
   class SlotIndexBits
       : public BitField<int, kContextIndexBits, kSlotIndexBits> {};
 
-  Code::StubType GetStubType() const override { return Code::FAST; }
-
   DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, HandlerStub);
 };
 
@@ -2599,13 +2711,11 @@
 
 class TransitionElementsKindStub : public HydrogenCodeStub {
  public:
-  TransitionElementsKindStub(Isolate* isolate,
-                             ElementsKind from_kind,
-                             ElementsKind to_kind,
-                             bool is_js_array) : HydrogenCodeStub(isolate) {
+  TransitionElementsKindStub(Isolate* isolate, ElementsKind from_kind,
+                             ElementsKind to_kind)
+      : HydrogenCodeStub(isolate) {
     set_sub_minor_key(FromKindBits::encode(from_kind) |
-                      ToKindBits::encode(to_kind) |
-                      IsJSArrayBits::encode(is_js_array));
+                      ToKindBits::encode(to_kind));
   }
 
   ElementsKind from_kind() const {
@@ -2614,12 +2724,9 @@
 
   ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
 
-  bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
-
  private:
   class FromKindBits: public BitField<ElementsKind, 8, 8> {};
   class ToKindBits: public BitField<ElementsKind, 0, 8> {};
-  class IsJSArrayBits: public BitField<bool, 16, 1> {};
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
   DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub);
@@ -2631,24 +2738,12 @@
       : TurboFanCodeStub(isolate) {}
 
   void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
-  void GenerateAssembly(compiler::CodeStubAssembler* assembler) const override;
+  void GenerateAssembly(CodeStubAssembler* assembler) const override;
 
   DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber);
   DEFINE_CODE_STUB(AllocateHeapNumber, TurboFanCodeStub);
 };
 
-class AllocateMutableHeapNumberStub : public TurboFanCodeStub {
- public:
-  explicit AllocateMutableHeapNumberStub(Isolate* isolate)
-      : TurboFanCodeStub(isolate) {}
-
-  void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
-  void GenerateAssembly(compiler::CodeStubAssembler* assembler) const override;
-
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateMutableHeapNumber);
-  DEFINE_CODE_STUB(AllocateMutableHeapNumber, TurboFanCodeStub);
-};
-
 #define SIMD128_ALLOC_STUB(TYPE, Type, type, lane_count, lane_type)     \
   class Allocate##Type##Stub : public TurboFanCodeStub {                \
    public:                                                              \
@@ -2656,8 +2751,7 @@
         : TurboFanCodeStub(isolate) {}                                  \
                                                                         \
     void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \
-    void GenerateAssembly(                                              \
-        compiler::CodeStubAssembler* assembler) const override;         \
+    void GenerateAssembly(CodeStubAssembler* assembler) const override; \
                                                                         \
     DEFINE_CALL_INTERFACE_DESCRIPTOR(Allocate##Type);                   \
     DEFINE_CODE_STUB(Allocate##Type, TurboFanCodeStub);                 \
@@ -2665,23 +2759,11 @@
 SIMD128_TYPES(SIMD128_ALLOC_STUB)
 #undef SIMD128_ALLOC_STUB
 
-class AllocateInNewSpaceStub final : public HydrogenCodeStub {
- public:
-  explicit AllocateInNewSpaceStub(Isolate* isolate)
-      : HydrogenCodeStub(isolate) {}
-
- private:
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateInNewSpace);
-  DEFINE_HYDROGEN_CODE_STUB(AllocateInNewSpace, HydrogenCodeStub);
-};
-
-
-class ArrayConstructorStubBase : public HydrogenCodeStub {
- public:
-  ArrayConstructorStubBase(Isolate* isolate,
-                           ElementsKind kind,
-                           AllocationSiteOverrideMode override_mode)
-      : HydrogenCodeStub(isolate) {
+class CommonArrayConstructorStub : public TurboFanCodeStub {
+ protected:
+  CommonArrayConstructorStub(Isolate* isolate, ElementsKind kind,
+                             AllocationSiteOverrideMode override_mode)
+      : TurboFanCodeStub(isolate) {
     // It only makes sense to override local allocation site behavior
     // if there is a difference between the global allocation site policy
     // for an ElementsKind and the desired usage of the stub.
@@ -2691,6 +2773,14 @@
                       AllocationSiteOverrideModeBits::encode(override_mode));
   }
 
+  void set_sub_minor_key(uint32_t key) { minor_key_ = key; }
+
+  uint32_t sub_minor_key() const { return minor_key_; }
+
+  CommonArrayConstructorStub(uint32_t key, Isolate* isolate)
+      : TurboFanCodeStub(key, isolate) {}
+
+ public:
   ElementsKind elements_kind() const {
     return ElementsKindBits::decode(sub_minor_key());
   }
@@ -2701,147 +2791,95 @@
 
   static void GenerateStubsAheadOfTime(Isolate* isolate);
 
-  // Parameters accessed via CodeStubGraphBuilder::GetParameter()
-  static const int kConstructor = 0;
-  static const int kAllocationSite = 1;
-
- protected:
-  std::ostream& BasePrintName(std::ostream& os,
-                              const char* name) const;  // NOLINT
-
  private:
   // Ensure data fits within available bits.
   STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
 
-  class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
-  class AllocationSiteOverrideModeBits: public
-      BitField<AllocationSiteOverrideMode, 8, 1> {};  // NOLINT
-
-  DEFINE_CODE_STUB_BASE(ArrayConstructorStubBase, HydrogenCodeStub);
+  class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
+  class AllocationSiteOverrideModeBits
+      : public BitField<AllocationSiteOverrideMode, 8, 1> {};  // NOLINT
 };
 
-
-class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
+class ArrayNoArgumentConstructorStub : public CommonArrayConstructorStub {
  public:
   ArrayNoArgumentConstructorStub(
-      Isolate* isolate,
-      ElementsKind kind,
+      Isolate* isolate, ElementsKind kind,
       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
-      : ArrayConstructorStubBase(isolate, kind, override_mode) {
-  }
+      : CommonArrayConstructorStub(isolate, kind, override_mode) {}
 
  private:
   void PrintName(std::ostream& os) const override {  // NOLINT
-    BasePrintName(os, "ArrayNoArgumentConstructorStub");
+    os << "ArrayNoArgumentConstructorStub";
   }
 
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructorConstantArgCount);
-  DEFINE_HYDROGEN_CODE_STUB(ArrayNoArgumentConstructor,
-                            ArrayConstructorStubBase);
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor);
+  DEFINE_TURBOFAN_CODE_STUB(ArrayNoArgumentConstructor,
+                            CommonArrayConstructorStub);
 };
 
+class InternalArrayNoArgumentConstructorStub
+    : public CommonArrayConstructorStub {
+ public:
+  InternalArrayNoArgumentConstructorStub(Isolate* isolate, ElementsKind kind)
+      : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {}
 
-class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
+ private:
+  void PrintName(std::ostream& os) const override {  // NOLINT
+    os << "InternalArrayNoArgumentConstructorStub";
+  }
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor);
+  DEFINE_TURBOFAN_CODE_STUB(InternalArrayNoArgumentConstructor,
+                            CommonArrayConstructorStub);
+};
+
+class ArraySingleArgumentConstructorStub : public CommonArrayConstructorStub {
  public:
   ArraySingleArgumentConstructorStub(
-      Isolate* isolate,
-      ElementsKind kind,
+      Isolate* isolate, ElementsKind kind,
       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
-      : ArrayConstructorStubBase(isolate, kind, override_mode) {
-  }
+      : CommonArrayConstructorStub(isolate, kind, override_mode) {}
 
  private:
   void PrintName(std::ostream& os) const override {  // NOLINT
-    BasePrintName(os, "ArraySingleArgumentConstructorStub");
+    os << "ArraySingleArgumentConstructorStub";
   }
 
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
-  DEFINE_HYDROGEN_CODE_STUB(ArraySingleArgumentConstructor,
-                            ArrayConstructorStubBase);
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor);
+  DEFINE_TURBOFAN_CODE_STUB(ArraySingleArgumentConstructor,
+                            CommonArrayConstructorStub);
 };
 
-
-class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
- public:
-  ArrayNArgumentsConstructorStub(
-      Isolate* isolate,
-      ElementsKind kind,
-      AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
-      : ArrayConstructorStubBase(isolate, kind, override_mode) {
-  }
-
- private:
-  void PrintName(std::ostream& os) const override {  // NOLINT
-    BasePrintName(os, "ArrayNArgumentsConstructorStub");
-  }
-
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
-  DEFINE_HYDROGEN_CODE_STUB(ArrayNArgumentsConstructor,
-                            ArrayConstructorStubBase);
-};
-
-
-class InternalArrayConstructorStubBase : public HydrogenCodeStub {
- public:
-  InternalArrayConstructorStubBase(Isolate* isolate, ElementsKind kind)
-      : HydrogenCodeStub(isolate) {
-    set_sub_minor_key(ElementsKindBits::encode(kind));
-  }
-
-  static void GenerateStubsAheadOfTime(Isolate* isolate);
-
-  // Parameters accessed via CodeStubGraphBuilder::GetParameter()
-  static const int kConstructor = 0;
-
-  ElementsKind elements_kind() const {
-    return ElementsKindBits::decode(sub_minor_key());
-  }
-
- private:
-  class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
-
-  DEFINE_CODE_STUB_BASE(InternalArrayConstructorStubBase, HydrogenCodeStub);
-};
-
-
-class InternalArrayNoArgumentConstructorStub : public
-    InternalArrayConstructorStubBase {
- public:
-  InternalArrayNoArgumentConstructorStub(Isolate* isolate,
-                                         ElementsKind kind)
-      : InternalArrayConstructorStubBase(isolate, kind) { }
-
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructorConstantArgCount);
-  DEFINE_HYDROGEN_CODE_STUB(InternalArrayNoArgumentConstructor,
-                            InternalArrayConstructorStubBase);
-};
-
-
-class InternalArraySingleArgumentConstructorStub : public
-    InternalArrayConstructorStubBase {
+class InternalArraySingleArgumentConstructorStub
+    : public CommonArrayConstructorStub {
  public:
   InternalArraySingleArgumentConstructorStub(Isolate* isolate,
                                              ElementsKind kind)
-      : InternalArrayConstructorStubBase(isolate, kind) { }
+      : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {}
 
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
-  DEFINE_HYDROGEN_CODE_STUB(InternalArraySingleArgumentConstructor,
-                            InternalArrayConstructorStubBase);
+ private:
+  void PrintName(std::ostream& os) const override {  // NOLINT
+    os << "InternalArraySingleArgumentConstructorStub";
+  }
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor);
+  DEFINE_TURBOFAN_CODE_STUB(InternalArraySingleArgumentConstructor,
+                            CommonArrayConstructorStub);
 };
 
-
-class InternalArrayNArgumentsConstructorStub : public
-    InternalArrayConstructorStubBase {
+class ArrayNArgumentsConstructorStub : public PlatformCodeStub {
  public:
-  InternalArrayNArgumentsConstructorStub(Isolate* isolate, ElementsKind kind)
-      : InternalArrayConstructorStubBase(isolate, kind) { }
+  explicit ArrayNArgumentsConstructorStub(Isolate* isolate)
+      : PlatformCodeStub(isolate) {}
 
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
-  DEFINE_HYDROGEN_CODE_STUB(InternalArrayNArgumentsConstructor,
-                            InternalArrayConstructorStubBase);
+  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
+    return ArrayNArgumentsConstructorDescriptor(isolate());
+  }
+
+ private:
+  DEFINE_PLATFORM_CODE_STUB(ArrayNArgumentsConstructor, PlatformCodeStub);
 };
 
-
 class StoreElementStub : public PlatformCodeStub {
  public:
   StoreElementStub(Isolate* isolate, ElementsKind elements_kind,
@@ -2894,7 +2932,7 @@
     Types() : EnumSet<Type, uint16_t>(0) {}
     explicit Types(uint16_t bits) : EnumSet<Type, uint16_t>(bits) {}
 
-    bool UpdateStatus(Handle<Object> object);
+    bool UpdateStatus(Isolate* isolate, Handle<Object> object);
     bool NeedsMap() const;
     bool CanBeUndetectable() const {
       return Contains(ToBooleanICStub::SPEC_OBJECT);
@@ -2923,7 +2961,7 @@
 
   ExtraICState GetExtraICState() const override { return types().ToIntegral(); }
 
-  InlineCacheState GetICState() const override {
+  InlineCacheState GetICState() const {
     if (types().IsEmpty()) {
       return ::v8::internal::UNINITIALIZED;
     } else {
@@ -3040,37 +3078,10 @@
  public:
   explicit SubStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
 
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
+  DEFINE_ON_STACK_CALL_INTERFACE_DESCRIPTOR(3);
   DEFINE_PLATFORM_CODE_STUB(SubString, PlatformCodeStub);
 };
 
-
-class ToNumberStub final : public PlatformCodeStub {
- public:
-  explicit ToNumberStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
-
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(TypeConversion);
-  DEFINE_PLATFORM_CODE_STUB(ToNumber, PlatformCodeStub);
-};
-
-class NonNumberToNumberStub final : public PlatformCodeStub {
- public:
-  explicit NonNumberToNumberStub(Isolate* isolate)
-      : PlatformCodeStub(isolate) {}
-
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(TypeConversion);
-  DEFINE_PLATFORM_CODE_STUB(NonNumberToNumber, PlatformCodeStub);
-};
-
-class StringToNumberStub final : public PlatformCodeStub {
- public:
-  explicit StringToNumberStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
-
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(TypeConversion);
-  DEFINE_PLATFORM_CODE_STUB(StringToNumber, PlatformCodeStub);
-};
-
-
 class ToStringStub final : public PlatformCodeStub {
  public:
   explicit ToStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
@@ -3079,7 +3090,6 @@
   DEFINE_PLATFORM_CODE_STUB(ToString, PlatformCodeStub);
 };
 
-
 class ToNameStub final : public PlatformCodeStub {
  public:
   explicit ToNameStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
diff --git a/src/codegen.cc b/src/codegen.cc
index 692fa64..4597ae2 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -12,7 +12,6 @@
 #include "src/compiler.h"
 #include "src/debug/debug.h"
 #include "src/parsing/parser.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/runtime/runtime.h"
 
 namespace v8 {
@@ -61,7 +60,6 @@
   }
 
 UNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction)
-UNARY_MATH_FUNCTION(exp, CreateExpFunction)
 
 #undef UNARY_MATH_FUNCTION
 
@@ -147,11 +145,12 @@
 void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
 #ifdef ENABLE_DISASSEMBLER
   AllowDeferredHandleDereference allow_deference_for_print_code;
-  bool print_code = info->isolate()->bootstrapper()->IsActive()
-      ? FLAG_print_builtin_code
-      : (FLAG_print_code ||
-         (info->IsStub() && FLAG_print_code_stubs) ||
-         (info->IsOptimizing() && FLAG_print_opt_code));
+  Isolate* isolate = info->isolate();
+  bool print_code =
+      isolate->bootstrapper()->IsActive()
+          ? FLAG_print_builtin_code
+          : (FLAG_print_code || (info->IsStub() && FLAG_print_code_stubs) ||
+             (info->IsOptimizing() && FLAG_print_opt_code));
   if (print_code) {
     base::SmartArrayPointer<char> debug_name = info->GetDebugName();
     CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer());
@@ -162,16 +161,16 @@
         info->parse_info() && (code->kind() == Code::OPTIMIZED_FUNCTION ||
                                code->kind() == Code::FUNCTION);
     if (print_source) {
-      FunctionLiteral* literal = info->literal();
+      Handle<SharedFunctionInfo> shared = info->shared_info();
       Handle<Script> script = info->script();
-      if (!script->IsUndefined() && !script->source()->IsUndefined()) {
+      if (!script->IsUndefined(isolate) &&
+          !script->source()->IsUndefined(isolate)) {
         os << "--- Raw source ---\n";
         StringCharacterStream stream(String::cast(script->source()),
-                                     literal->start_position());
+                                     shared->start_position());
         // fun->end_position() points to the last character in the stream. We
         // need to compensate by adding one to calculate the length.
-        int source_len =
-            literal->end_position() - literal->start_position() + 1;
+        int source_len = shared->end_position() - shared->start_position() + 1;
         for (int i = 0; i < source_len; i++) {
           if (stream.HasMore()) {
             os << AsReversiblyEscapedUC16(stream.GetNext());
@@ -191,8 +190,8 @@
       os << "--- Code ---\n";
     }
     if (print_source) {
-      FunctionLiteral* literal = info->literal();
-      os << "source_position = " << literal->start_position() << "\n";
+      Handle<SharedFunctionInfo> shared = info->shared_info();
+      os << "source_position = " << shared->start_position() << "\n";
     }
     code->Disassemble(debug_name.get(), os);
     os << "--- End code ---\n";
diff --git a/src/codegen.h b/src/codegen.h
index f941696..82962ad 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -93,16 +93,13 @@
 // generated code both in runtime and compiled code.
 typedef double (*UnaryMathFunctionWithIsolate)(double x, Isolate* isolate);
 
-UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate);
 UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate);
 
 
 double modulo(double x, double y);
 
 // Custom implementation of math functions.
-double fast_exp(double input, Isolate* isolate);
 double fast_sqrt(double input, Isolate* isolate);
-void lazily_initialize_fast_exp(Isolate* isolate);
 void lazily_initialize_fast_sqrt(Isolate* isolate);
 
 
diff --git a/src/compilation-cache.cc b/src/compilation-cache.cc
index aca8cee..53e2190 100644
--- a/src/compilation-cache.cc
+++ b/src/compilation-cache.cc
@@ -41,7 +41,7 @@
 Handle<CompilationCacheTable> CompilationSubCache::GetTable(int generation) {
   DCHECK(generation < generations_);
   Handle<CompilationCacheTable> result;
-  if (tables_[generation]->IsUndefined()) {
+  if (tables_[generation]->IsUndefined(isolate())) {
     result = CompilationCacheTable::New(isolate(), kInitialCacheSize);
     tables_[generation] = *result;
   } else {
@@ -56,7 +56,7 @@
 void CompilationSubCache::Age() {
   // Don't directly age single-generation caches.
   if (generations_ == 1) {
-    if (tables_[0] != isolate()->heap()->undefined_value()) {
+    if (!tables_[0]->IsUndefined(isolate())) {
       CompilationCacheTable::cast(tables_[0])->Age();
     }
     return;
@@ -121,7 +121,7 @@
   // If the script name isn't set, the boilerplate script should have
   // an undefined name to have the same origin.
   if (name.is_null()) {
-    return script->name()->IsUndefined();
+    return script->name()->IsUndefined(isolate());
   }
   // Do the fast bailout checks first.
   if (line_offset != script->line_offset()) return false;
diff --git a/src/compilation-cache.h b/src/compilation-cache.h
index 2295f4c..973673c 100644
--- a/src/compilation-cache.h
+++ b/src/compilation-cache.h
@@ -210,7 +210,7 @@
   explicit CompilationCache(Isolate* isolate);
   ~CompilationCache();
 
-  HashMap* EagerOptimizingSet();
+  base::HashMap* EagerOptimizingSet();
 
   // The number of sub caches covering the different types to cache.
   static const int kSubCacheCount = 4;
diff --git a/src/compilation-statistics.cc b/src/compilation-statistics.cc
index ed568cb..d4ca39d 100644
--- a/src/compilation-statistics.cc
+++ b/src/compilation-statistics.cc
@@ -54,8 +54,7 @@
   }
 }
 
-
-static void WriteLine(std::ostream& os, const char* name,
+static void WriteLine(std::ostream& os, bool machine_format, const char* name,
                       const CompilationStatistics::BasicStats& stats,
                       const CompilationStatistics::BasicStats& total_stats) {
   const size_t kBufferSize = 128;
@@ -66,18 +65,24 @@
   double size_percent =
       static_cast<double>(stats.total_allocated_bytes_ * 100) /
       static_cast<double>(total_stats.total_allocated_bytes_);
-  base::OS::SNPrintF(buffer, kBufferSize,
-                     "%28s %10.3f (%5.1f%%)  "
-                     "%10u (%5.1f%%) %10u %10u",
-                     name, ms, percent, stats.total_allocated_bytes_,
-                     size_percent, stats.max_allocated_bytes_,
-                     stats.absolute_max_allocated_bytes_);
+  if (machine_format) {
+    base::OS::SNPrintF(buffer, kBufferSize,
+                       "\"%s_time\"=%.3f\n\"%s_space\"=%" PRIuS, name, ms, name,
+                       stats.total_allocated_bytes_);
+    os << buffer;
+  } else {
+    base::OS::SNPrintF(buffer, kBufferSize, "%28s %10.3f (%5.1f%%)  %10" PRIuS
+                                            " (%5.1f%%) %10" PRIuS " %10" PRIuS,
+                       name, ms, percent, stats.total_allocated_bytes_,
+                       size_percent, stats.max_allocated_bytes_,
+                       stats.absolute_max_allocated_bytes_);
 
-  os << buffer;
-  if (stats.function_name_.size() > 0) {
-    os << "   " << stats.function_name_.c_str();
+    os << buffer;
+    if (stats.function_name_.size() > 0) {
+      os << "   " << stats.function_name_.c_str();
+    }
+    os << std::endl;
   }
-  os << std::endl;
 }
 
 
@@ -102,10 +107,10 @@
         "--------------------------------------------------------\n";
 }
 
-
-std::ostream& operator<<(std::ostream& os, const CompilationStatistics& s) {
+std::ostream& operator<<(std::ostream& os, const AsPrintableStatistics& ps) {
   // phase_kind_map_ and phase_map_ don't get mutated, so store a bunch of
   // pointers into them.
+  const CompilationStatistics& s = ps.s;
 
   typedef std::vector<CompilationStatistics::PhaseKindMap::const_iterator>
       SortedPhaseKinds;
@@ -122,22 +127,27 @@
     sorted_phases[it->second.insert_order_] = it;
   }
 
-  WriteHeader(os);
+  if (!ps.machine_output) WriteHeader(os);
   for (auto phase_kind_it : sorted_phase_kinds) {
     const auto& phase_kind_name = phase_kind_it->first;
-    for (auto phase_it : sorted_phases) {
-      const auto& phase_stats = phase_it->second;
-      if (phase_stats.phase_kind_name_ != phase_kind_name) continue;
-      const auto& phase_name = phase_it->first;
-      WriteLine(os, phase_name.c_str(), phase_stats, s.total_stats_);
+    if (!ps.machine_output) {
+      for (auto phase_it : sorted_phases) {
+        const auto& phase_stats = phase_it->second;
+        if (phase_stats.phase_kind_name_ != phase_kind_name) continue;
+        const auto& phase_name = phase_it->first;
+        WriteLine(os, ps.machine_output, phase_name.c_str(), phase_stats,
+                  s.total_stats_);
+      }
+      WritePhaseKindBreak(os);
     }
-    WritePhaseKindBreak(os);
     const auto& phase_kind_stats = phase_kind_it->second;
-    WriteLine(os, phase_kind_name.c_str(), phase_kind_stats, s.total_stats_);
+    WriteLine(os, ps.machine_output, phase_kind_name.c_str(), phase_kind_stats,
+              s.total_stats_);
     os << std::endl;
   }
-  WriteFullLine(os);
-  WriteLine(os, "totals", s.total_stats_, s.total_stats_);
+
+  if (!ps.machine_output) WriteFullLine(os);
+  WriteLine(os, ps.machine_output, "totals", s.total_stats_, s.total_stats_);
 
   return os;
 }
diff --git a/src/compilation-statistics.h b/src/compilation-statistics.h
index 6219180..ceffc2e 100644
--- a/src/compilation-statistics.h
+++ b/src/compilation-statistics.h
@@ -15,6 +15,12 @@
 namespace internal {
 
 class CompilationInfo;
+class CompilationStatistics;
+
+struct AsPrintableStatistics {
+  const CompilationStatistics& s;
+  const bool machine_output;
+};
 
 class CompilationStatistics final : public Malloced {
  public:
@@ -65,7 +71,7 @@
   };
 
   friend std::ostream& operator<<(std::ostream& os,
-                                  const CompilationStatistics& s);
+                                  const AsPrintableStatistics& s);
 
   typedef OrderedStats PhaseKindStats;
   typedef std::map<std::string, PhaseKindStats> PhaseKindMap;
@@ -78,7 +84,7 @@
   DISALLOW_COPY_AND_ASSIGN(CompilationStatistics);
 };
 
-std::ostream& operator<<(std::ostream& os, const CompilationStatistics& s);
+std::ostream& operator<<(std::ostream& os, const AsPrintableStatistics& s);
 
 }  // namespace internal
 }  // namespace v8
diff --git a/src/compiler.cc b/src/compiler.cc
index 8bb5332..2a0eda0 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -15,13 +15,11 @@
 #include "src/compilation-cache.h"
 #include "src/compiler/pipeline.h"
 #include "src/crankshaft/hydrogen.h"
-#include "src/crankshaft/lithium.h"
-#include "src/crankshaft/typing.h"
 #include "src/debug/debug.h"
 #include "src/debug/liveedit.h"
 #include "src/deoptimizer.h"
+#include "src/frames-inl.h"
 #include "src/full-codegen/full-codegen.h"
-#include "src/gdb-jit.h"
 #include "src/interpreter/interpreter.h"
 #include "src/isolate-inl.h"
 #include "src/log-inl.h"
@@ -29,9 +27,9 @@
 #include "src/parsing/parser.h"
 #include "src/parsing/rewriter.h"
 #include "src/parsing/scanner-character-streams.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/runtime-profiler.h"
 #include "src/snapshot/code-serializer.h"
+#include "src/typing-asm.h"
 #include "src/vm-state-inl.h"
 
 namespace v8 {
@@ -52,15 +50,10 @@
 
 
 PARSE_INFO_GETTER(Handle<Script>, script)
-PARSE_INFO_GETTER(bool, is_eval)
-PARSE_INFO_GETTER(bool, is_native)
-PARSE_INFO_GETTER(bool, is_module)
 PARSE_INFO_GETTER(FunctionLiteral*, literal)
-PARSE_INFO_GETTER_WITH_DEFAULT(LanguageMode, language_mode, STRICT)
-PARSE_INFO_GETTER_WITH_DEFAULT(Handle<JSFunction>, closure,
-                               Handle<JSFunction>::null())
 PARSE_INFO_GETTER_WITH_DEFAULT(Scope*, scope, nullptr)
-PARSE_INFO_GETTER(Handle<Context>, context)
+PARSE_INFO_GETTER_WITH_DEFAULT(Handle<Context>, context,
+                               Handle<Context>::null())
 PARSE_INFO_GETTER(Handle<SharedFunctionInfo>, shared_info)
 
 #undef PARSE_INFO_GETTER
@@ -80,26 +73,17 @@
   CompilationInfo* info_;
 };
 
-// Exactly like a CompilationInfo, except being allocated via {new} and it also
-// creates and enters a Zone on construction and deallocates it on destruction.
-class CompilationInfoWithZone : public CompilationInfo {
- public:
-  explicit CompilationInfoWithZone(Handle<JSFunction> function)
-      : CompilationInfo(new ParseInfo(&zone_, function)),
-        zone_(function->GetIsolate()->allocator()) {}
-
-  // Virtual destructor because a CompilationInfoWithZone has to exit the
-  // zone scope and get rid of dependent maps even when the destructor is
-  // called when cast as a CompilationInfo.
-  virtual ~CompilationInfoWithZone() {
-    DisableFutureOptimization();
-    dependencies()->Rollback();
-    delete parse_info_;
-    parse_info_ = nullptr;
+// Helper that times a scoped region and records the elapsed time.
+struct ScopedTimer {
+  explicit ScopedTimer(base::TimeDelta* location) : location_(location) {
+    DCHECK(location_ != NULL);
+    timer_.Start();
   }
 
- private:
-  Zone zone_;
+  ~ScopedTimer() { *location_ += timer_.Elapsed(); }
+
+  base::ElapsedTimer timer_;
+  base::TimeDelta* location_;
 };
 
 // ----------------------------------------------------------------------------
@@ -109,25 +93,12 @@
   return parse_info_ && !parse_info_->shared_info().is_null();
 }
 
+CompilationInfo::CompilationInfo(ParseInfo* parse_info,
+                                 Handle<JSFunction> closure)
+    : CompilationInfo(parse_info, {}, Code::ComputeFlags(Code::FUNCTION), BASE,
+                      parse_info->isolate(), parse_info->zone()) {
+  closure_ = closure;
 
-bool CompilationInfo::has_context() const {
-  return parse_info_ && !parse_info_->context().is_null();
-}
-
-
-bool CompilationInfo::has_literal() const {
-  return parse_info_ && parse_info_->literal() != nullptr;
-}
-
-
-bool CompilationInfo::has_scope() const {
-  return parse_info_ && parse_info_->scope() != nullptr;
-}
-
-
-CompilationInfo::CompilationInfo(ParseInfo* parse_info)
-    : CompilationInfo(parse_info, nullptr, Code::ComputeFlags(Code::FUNCTION),
-                      BASE, parse_info->isolate(), parse_info->zone()) {
   // Compiling for the snapshot typically results in different code than
   // compiling later on. This means that code recompiled with deoptimization
   // support won't be "equivalent" (as defined by SharedFunctionInfo::
@@ -140,19 +111,15 @@
   if (FLAG_turbo_inlining) MarkAsInliningEnabled();
   if (FLAG_turbo_source_positions) MarkAsSourcePositionsEnabled();
   if (FLAG_turbo_splitting) MarkAsSplittingEnabled();
-  if (FLAG_turbo_types) MarkAsTypingEnabled();
-
-  if (has_shared_info()) {
-    if (shared_info()->never_compiled()) MarkAsFirstCompile();
-  }
 }
 
-
-CompilationInfo::CompilationInfo(const char* debug_name, Isolate* isolate,
-                                 Zone* zone, Code::Flags code_flags)
+CompilationInfo::CompilationInfo(Vector<const char> debug_name,
+                                 Isolate* isolate, Zone* zone,
+                                 Code::Flags code_flags)
     : CompilationInfo(nullptr, debug_name, code_flags, STUB, isolate, zone) {}
 
-CompilationInfo::CompilationInfo(ParseInfo* parse_info, const char* debug_name,
+CompilationInfo::CompilationInfo(ParseInfo* parse_info,
+                                 Vector<const char> debug_name,
                                  Code::Flags code_flags, Mode mode,
                                  Isolate* isolate, Zone* zone)
     : parse_info_(parse_info),
@@ -167,27 +134,21 @@
       bailout_reason_(kNoReason),
       prologue_offset_(Code::kPrologueOffsetNotSet),
       track_positions_(FLAG_hydrogen_track_positions ||
-                       isolate->cpu_profiler()->is_profiling()),
-      opt_count_(has_shared_info() ? shared_info()->opt_count() : 0),
+                       isolate->is_profiling()),
       parameter_count_(0),
       optimization_id_(-1),
       osr_expr_stack_height_(0),
       debug_name_(debug_name) {}
 
-
 CompilationInfo::~CompilationInfo() {
   DisableFutureOptimization();
+  dependencies()->Rollback();
   delete deferred_handles_;
-#ifdef DEBUG
-  // Check that no dependent maps have been added or added dependent maps have
-  // been rolled back or committed.
-  DCHECK(dependencies()->IsEmpty());
-#endif  // DEBUG
 }
 
 
 int CompilationInfo::num_parameters() const {
-  return has_scope() ? scope()->num_parameters() : parameter_count_;
+  return !IsStub() ? scope()->num_parameters() : parameter_count_;
 }
 
 
@@ -199,11 +160,6 @@
 bool CompilationInfo::is_this_defined() const { return !IsStub(); }
 
 
-int CompilationInfo::num_heap_slots() const {
-  return has_scope() ? scope()->num_heap_slots() : 0;
-}
-
-
 // Primitive functions are unlikely to be picked up by the stack-walking
 // profiler, so they trigger their own optimization when they're called
 // for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time.
@@ -212,7 +168,7 @@
          !(literal()->flags() & AstProperties::kDontSelfOptimize) &&
          !literal()->dont_optimize() &&
          literal()->scope()->AllowsLazyCompilation() &&
-         (!has_shared_info() || !shared_info()->optimization_disabled());
+         !shared_info()->optimization_disabled();
 }
 
 
@@ -221,59 +177,6 @@
 }
 
 
-int CompilationInfo::TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
-                                          SourcePosition position,
-                                          int parent_id) {
-  DCHECK(track_positions_);
-
-  int inline_id = static_cast<int>(inlined_function_infos_.size());
-  InlinedFunctionInfo info(parent_id, position, UnboundScript::kNoScriptId,
-      shared->start_position());
-  if (!shared->script()->IsUndefined()) {
-    Handle<Script> script(Script::cast(shared->script()));
-    info.script_id = script->id();
-
-    if (FLAG_hydrogen_track_positions && !script->source()->IsUndefined()) {
-      CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
-      OFStream os(tracing_scope.file());
-      os << "--- FUNCTION SOURCE (" << shared->DebugName()->ToCString().get()
-         << ") id{" << optimization_id() << "," << inline_id << "} ---\n";
-      {
-        DisallowHeapAllocation no_allocation;
-        int start = shared->start_position();
-        int len = shared->end_position() - start;
-        String::SubStringRange source(String::cast(script->source()), start,
-                                      len);
-        for (const auto& c : source) {
-          os << AsReversiblyEscapedUC16(c);
-        }
-      }
-
-      os << "\n--- END ---\n";
-    }
-  }
-
-  inlined_function_infos_.push_back(info);
-
-  if (FLAG_hydrogen_track_positions && inline_id != 0) {
-    CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
-    OFStream os(tracing_scope.file());
-    os << "INLINE (" << shared->DebugName()->ToCString().get() << ") id{"
-       << optimization_id() << "," << inline_id << "} AS " << inline_id
-       << " AT " << position << std::endl;
-  }
-
-  return inline_id;
-}
-
-
-void CompilationInfo::LogDeoptCallPosition(int pc_offset, int inlining_id) {
-  if (!track_positions_ || IsStub()) return;
-  DCHECK_LT(static_cast<size_t>(inlining_id), inlined_function_infos_.size());
-  inlined_function_infos_.at(inlining_id).deopt_pc_offsets.push_back(pc_offset);
-}
-
-
 base::SmartArrayPointer<char> CompilationInfo::GetDebugName() const {
   if (parse_info() && parse_info()->literal()) {
     AllowHandleDereference allow_deref;
@@ -282,10 +185,11 @@
   if (parse_info() && !parse_info()->shared_info().is_null()) {
     return parse_info()->shared_info()->DebugName()->ToCString();
   }
-  const char* str = debug_name_ ? debug_name_ : "unknown";
-  size_t len = strlen(str) + 1;
-  base::SmartArrayPointer<char> name(new char[len]);
-  memcpy(name.get(), str, len);
+  Vector<const char> name_vec = debug_name_;
+  if (name_vec.is_empty()) name_vec = ArrayVector("unknown");
+  base::SmartArrayPointer<char> name(new char[name_vec.length() + 1]);
+  memcpy(name.get(), name_vec.start(), name_vec.length());
+  name[name_vec.length()] = '\0';
   return name;
 }
 
@@ -295,6 +199,9 @@
     case Code::BYTECODE_HANDLER:
     case Code::HANDLER:
     case Code::BUILTIN:
+#define CASE_KIND(kind) case Code::kind:
+      IC_KIND_LIST(CASE_KIND)
+#undef CASE_KIND
       return StackFrame::STUB;
     case Code::WASM_FUNCTION:
       return StackFrame::WASM;
@@ -308,8 +215,15 @@
   }
 }
 
+int CompilationInfo::GetDeclareGlobalsFlags() const {
+  DCHECK(DeclareGlobalsLanguageMode::is_valid(parse_info()->language_mode()));
+  return DeclareGlobalsEvalFlag::encode(parse_info()->is_eval()) |
+         DeclareGlobalsNativeFlag::encode(parse_info()->is_native()) |
+         DeclareGlobalsLanguageMode::encode(parse_info()->language_mode());
+}
+
 bool CompilationInfo::ExpectsJSReceiverAsReceiver() {
-  return is_sloppy(language_mode()) && !is_native();
+  return is_sloppy(parse_info()->language_mode()) && !parse_info()->is_native();
 }
 
 #if DEBUG
@@ -320,250 +234,47 @@
 #endif
 
 // ----------------------------------------------------------------------------
-// Implementation of OptimizedCompileJob
+// Implementation of CompilationJob
 
-class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder {
- public:
-  explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info)
-      : HOptimizedGraphBuilder(info) {
-  }
-
-#define DEF_VISIT(type)                                      \
-  void Visit##type(type* node) override {                    \
-    SourcePosition old_position = SourcePosition::Unknown(); \
-    if (node->position() != RelocInfo::kNoPosition) {        \
-      old_position = source_position();                      \
-      SetSourcePosition(node->position());                   \
-    }                                                        \
-    HOptimizedGraphBuilder::Visit##type(node);               \
-    if (!old_position.IsUnknown()) {                         \
-      set_source_position(old_position);                     \
-    }                                                        \
-  }
-  EXPRESSION_NODE_LIST(DEF_VISIT)
-#undef DEF_VISIT
-
-#define DEF_VISIT(type)                                      \
-  void Visit##type(type* node) override {                    \
-    SourcePosition old_position = SourcePosition::Unknown(); \
-    if (node->position() != RelocInfo::kNoPosition) {        \
-      old_position = source_position();                      \
-      SetSourcePosition(node->position());                   \
-    }                                                        \
-    HOptimizedGraphBuilder::Visit##type(node);               \
-    if (!old_position.IsUnknown()) {                         \
-      set_source_position(old_position);                     \
-    }                                                        \
-  }
-  STATEMENT_NODE_LIST(DEF_VISIT)
-#undef DEF_VISIT
-
-#define DEF_VISIT(type)                        \
-  void Visit##type(type* node) override {      \
-    HOptimizedGraphBuilder::Visit##type(node); \
-  }
-  DECLARATION_NODE_LIST(DEF_VISIT)
-#undef DEF_VISIT
-};
-
-
-OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() {
+CompilationJob::Status CompilationJob::CreateGraph() {
+  DisallowJavascriptExecution no_js(isolate());
   DCHECK(info()->IsOptimizing());
 
-  // Do not use Crankshaft/TurboFan if we need to be able to set break points.
-  if (info()->shared_info()->HasDebugInfo()) {
-    return AbortOptimization(kFunctionBeingDebugged);
-  }
-
-  // Resuming a suspended frame is not supported by Crankshaft/TurboFan.
-  if (info()->shared_info()->HasBuiltinFunctionId() &&
-      (info()->shared_info()->builtin_function_id() == kGeneratorObjectNext ||
-       info()->shared_info()->builtin_function_id() == kGeneratorObjectReturn ||
-       info()->shared_info()->builtin_function_id() == kGeneratorObjectThrow)) {
-    return AbortOptimization(kGeneratorResumeMethod);
-  }
-
-  // Limit the number of times we try to optimize functions.
-  const int kMaxOptCount =
-      FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
-  if (info()->opt_count() > kMaxOptCount) {
-    return AbortOptimization(kOptimizedTooManyTimes);
-  }
-
-  // Check the whitelist for Crankshaft.
-  if (!info()->shared_info()->PassesFilter(FLAG_hydrogen_filter)) {
-    return AbortOptimization(kHydrogenFilter);
-  }
-
-  // Optimization requires a version of fullcode with deoptimization support.
-  // Recompile the unoptimized version of the code if the current version
-  // doesn't have deoptimization support already.
-  // Otherwise, if we are gathering compilation time and space statistics
-  // for hydrogen, gather baseline statistics for a fullcode compilation.
-  bool should_recompile = !info()->shared_info()->has_deoptimization_support();
-  if (should_recompile || FLAG_hydrogen_stats) {
-    base::ElapsedTimer timer;
-    if (FLAG_hydrogen_stats) {
-      timer.Start();
-    }
-    if (!Compiler::EnsureDeoptimizationSupport(info())) {
-      return SetLastStatus(FAILED);
-    }
-    if (FLAG_hydrogen_stats) {
-      isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed());
-    }
-  }
-
-  DCHECK(info()->shared_info()->has_deoptimization_support());
-  DCHECK(!info()->is_first_compile());
-
-  bool optimization_disabled = info()->shared_info()->optimization_disabled();
-  bool dont_crankshaft = info()->shared_info()->dont_crankshaft();
-
-  // Check the enabling conditions for Turbofan.
-  // 1. "use asm" code.
-  bool is_turbofanable_asm = FLAG_turbo_asm &&
-                             info()->shared_info()->asm_function() &&
-                             !optimization_disabled;
-
-  // 2. Fallback for features unsupported by Crankshaft.
-  bool is_unsupported_by_crankshaft_but_turbofanable =
-      dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 &&
-      !optimization_disabled;
-
-  // 3. Explicitly enabled by the command-line filter.
-  bool passes_turbo_filter =
-      info()->shared_info()->PassesFilter(FLAG_turbo_filter);
-
-  // If this is OSR request, OSR must be enabled by Turbofan.
-  bool passes_osr_test = FLAG_turbo_osr || !info()->is_osr();
-
-  if ((is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable ||
-       passes_turbo_filter) &&
-      passes_osr_test) {
-    // Use TurboFan for the compilation.
-    if (FLAG_trace_opt) {
-      OFStream os(stdout);
-      os << "[compiling method " << Brief(*info()->closure())
-         << " using TurboFan";
-      if (info()->is_osr()) os << " OSR";
-      os << "]" << std::endl;
-    }
-
-    if (info()->shared_info()->asm_function()) {
-      if (info()->osr_frame()) info()->MarkAsFrameSpecializing();
-      info()->MarkAsFunctionContextSpecializing();
-    } else {
-      if (!FLAG_always_opt) {
-        info()->MarkAsBailoutOnUninitialized();
-      }
-      if (FLAG_native_context_specialization) {
-        info()->MarkAsNativeContextSpecializing();
-        info()->MarkAsTypingEnabled();
-      }
-    }
-    if (!info()->shared_info()->asm_function() ||
-        FLAG_turbo_asm_deoptimization) {
-      info()->MarkAsDeoptimizationEnabled();
-    }
-
-    Timer t(this, &time_taken_to_create_graph_);
-    compiler::Pipeline pipeline(info());
-    pipeline.GenerateCode();
-    if (!info()->code().is_null()) {
-      return SetLastStatus(SUCCEEDED);
-    }
-  }
-
-  if (!isolate()->use_crankshaft() || dont_crankshaft) {
-    // Crankshaft is entirely disabled.
-    return SetLastStatus(FAILED);
-  }
-
-  Scope* scope = info()->scope();
-  if (LUnallocated::TooManyParameters(scope->num_parameters())) {
-    // Crankshaft would require too many Lithium operands.
-    return AbortOptimization(kTooManyParameters);
-  }
-
-  if (info()->is_osr() &&
-      LUnallocated::TooManyParametersOrStackSlots(scope->num_parameters(),
-                                                  scope->num_stack_slots())) {
-    // Crankshaft would require too many Lithium operands.
-    return AbortOptimization(kTooManyParametersLocals);
-  }
-
   if (FLAG_trace_opt) {
     OFStream os(stdout);
-    os << "[compiling method " << Brief(*info()->closure())
-       << " using Crankshaft";
+    os << "[compiling method " << Brief(*info()->closure()) << " using "
+       << compiler_name_;
     if (info()->is_osr()) os << " OSR";
     os << "]" << std::endl;
   }
 
-  if (FLAG_trace_hydrogen) {
-    isolate()->GetHTracer()->TraceCompilation(info());
-  }
-
-  // Type-check the function.
-  AstTyper(info()->isolate(), info()->zone(), info()->closure(),
-           info()->scope(), info()->osr_ast_id(), info()->literal())
-      .Run();
-
-  // Optimization could have been disabled by the parser. Note that this check
-  // is only needed because the Hydrogen graph builder is missing some bailouts.
-  if (info()->shared_info()->optimization_disabled()) {
-    return AbortOptimization(
-        info()->shared_info()->disable_optimization_reason());
-  }
-
-  HOptimizedGraphBuilder* graph_builder =
-      (info()->is_tracking_positions() || FLAG_trace_ic)
-          ? new (info()->zone()) HOptimizedGraphBuilderWithPositions(info())
-          : new (info()->zone()) HOptimizedGraphBuilder(info());
-
-  Timer t(this, &time_taken_to_create_graph_);
-  graph_ = graph_builder->CreateGraph();
-
-  if (isolate()->has_pending_exception()) {
-    return SetLastStatus(FAILED);
-  }
-
-  if (graph_ == NULL) return SetLastStatus(BAILED_OUT);
-
-  if (info()->dependencies()->HasAborted()) {
-    // Dependency has changed during graph creation. Let's try again later.
-    return RetryOptimization(kBailedOutDueToDependencyChange);
-  }
-
-  return SetLastStatus(SUCCEEDED);
+  // Delegate to the underlying implementation.
+  DCHECK_EQ(SUCCEEDED, last_status());
+  ScopedTimer t(&time_taken_to_create_graph_);
+  return SetLastStatus(CreateGraphImpl());
 }
 
-
-OptimizedCompileJob::Status OptimizedCompileJob::OptimizeGraph() {
+CompilationJob::Status CompilationJob::OptimizeGraph() {
   DisallowHeapAllocation no_allocation;
   DisallowHandleAllocation no_handles;
   DisallowHandleDereference no_deref;
   DisallowCodeDependencyChange no_dependency_change;
 
-  DCHECK(last_status() == SUCCEEDED);
-  // TODO(turbofan): Currently everything is done in the first phase.
-  if (!info()->code().is_null()) {
-    return last_status();
-  }
+  // Delegate to the underlying implementation.
+  DCHECK_EQ(SUCCEEDED, last_status());
+  ScopedTimer t(&time_taken_to_optimize_);
+  return SetLastStatus(OptimizeGraphImpl());
+}
 
-  Timer t(this, &time_taken_to_optimize_);
-  DCHECK(graph_ != NULL);
-  BailoutReason bailout_reason = kNoReason;
+CompilationJob::Status CompilationJob::GenerateCode() {
+  DisallowCodeDependencyChange no_dependency_change;
+  DisallowJavascriptExecution no_js(isolate());
+  DCHECK(!info()->dependencies()->HasAborted());
 
-  if (graph_->Optimize(&bailout_reason)) {
-    chunk_ = LChunk::NewChunk(graph_);
-    if (chunk_ != NULL) return SetLastStatus(SUCCEEDED);
-  } else if (bailout_reason != kNoReason) {
-    info_->AbortOptimization(bailout_reason);
-  }
-
-  return SetLastStatus(BAILED_OUT);
+  // Delegate to the underlying implementation.
+  DCHECK_EQ(SUCCEEDED, last_status());
+  ScopedTimer t(&time_taken_to_codegen_);
+  return SetLastStatus(GenerateCodeImpl());
 }
 
 
@@ -578,8 +289,9 @@
   heap->AddWeakObjectToCodeDependency(object, dep);
 }
 
+}  // namespace
 
-void RegisterWeakObjectsInOptimizedCode(Handle<Code> code) {
+void CompilationJob::RegisterWeakObjectsInOptimizedCode(Handle<Code> code) {
   // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies.
   Isolate* const isolate = code->GetIsolate();
   DCHECK(code->is_optimized_code());
@@ -619,53 +331,7 @@
   code->set_can_have_weak_objects(true);
 }
 
-}  // namespace
-
-
-OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() {
-  DCHECK(last_status() == SUCCEEDED);
-  // TODO(turbofan): Currently everything is done in the first phase.
-  if (!info()->code().is_null()) {
-    info()->dependencies()->Commit(info()->code());
-    if (info()->is_deoptimization_enabled()) {
-      info()->parse_info()->context()->native_context()->AddOptimizedCode(
-          *info()->code());
-      RegisterWeakObjectsInOptimizedCode(info()->code());
-    }
-    RecordOptimizationStats();
-    return last_status();
-  }
-
-  DCHECK(!info()->dependencies()->HasAborted());
-  DisallowCodeDependencyChange no_dependency_change;
-  DisallowJavascriptExecution no_js(isolate());
-  {  // Scope for timer.
-    Timer timer(this, &time_taken_to_codegen_);
-    DCHECK(chunk_ != NULL);
-    DCHECK(graph_ != NULL);
-    // Deferred handles reference objects that were accessible during
-    // graph creation.  To make sure that we don't encounter inconsistencies
-    // between graph creation and code generation, we disallow accessing
-    // objects through deferred handles during the latter, with exceptions.
-    DisallowDeferredHandleDereference no_deferred_handle_deref;
-    Handle<Code> optimized_code = chunk_->Codegen();
-    if (optimized_code.is_null()) {
-      if (info()->bailout_reason() == kNoReason) {
-        return AbortOptimization(kCodeGenerationFailed);
-      }
-      return SetLastStatus(BAILED_OUT);
-    }
-    RegisterWeakObjectsInOptimizedCode(optimized_code);
-    info()->SetCode(optimized_code);
-  }
-  RecordOptimizationStats();
-  // Add to the weak list of optimized code objects.
-  info()->context()->native_context()->AddOptimizedCode(*info()->code());
-  return SetLastStatus(SUCCEEDED);
-}
-
-
-void OptimizedCompileJob::RecordOptimizationStats() {
+void CompilationJob::RecordOptimizationStats() {
   Handle<JSFunction> function = info()->closure();
   if (!function->IsOptimized()) {
     // Concurrent recompilation and OSR may race.  Increment only once.
@@ -706,47 +372,25 @@
 
 namespace {
 
-// Sets the expected number of properties based on estimate from compiler.
-void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
-                                          int estimate) {
-  // If no properties are added in the constructor, they are more likely
-  // to be added later.
-  if (estimate == 0) estimate = 2;
-
-  // TODO(yangguo): check whether those heuristics are still up-to-date.
-  // We do not shrink objects that go into a snapshot (yet), so we adjust
-  // the estimate conservatively.
-  if (shared->GetIsolate()->serializer_enabled()) {
-    estimate += 2;
-  } else {
-    // Inobject slack tracking will reclaim redundant inobject space later,
-    // so we can afford to adjust the estimate generously.
-    estimate += 8;
-  }
-
-  shared->set_expected_nof_properties(estimate);
+bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) {
+  return shared->is_toplevel() && shared->script()->IsScript() &&
+         Script::cast(shared->script())->compilation_type() ==
+             Script::COMPILATION_TYPE_EVAL;
 }
 
-void MaybeDisableOptimization(Handle<SharedFunctionInfo> shared_info,
-                              BailoutReason bailout_reason) {
-  if (bailout_reason != kNoReason) {
-    shared_info->DisableOptimization(bailout_reason);
-  }
-}
-
-void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
-                               CompilationInfo* info,
-                               Handle<SharedFunctionInfo> shared) {
-  // SharedFunctionInfo is passed separately, because if CompilationInfo
-  // was created using Script object, it will not have it.
-
+void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
+                               CompilationInfo* info) {
   // Log the code generation. If source information is available include
   // script name and line number. Check explicitly whether logging is
   // enabled as finding the line number is not free.
   if (info->isolate()->logger()->is_logging_code_events() ||
-      info->isolate()->cpu_profiler()->is_profiling()) {
+      info->isolate()->is_profiling()) {
+    Handle<SharedFunctionInfo> shared = info->shared_info();
     Handle<Script> script = info->parse_info()->script();
-    Handle<AbstractCode> abstract_code = info->abstract_code();
+    Handle<AbstractCode> abstract_code =
+        info->has_bytecode_array()
+            ? Handle<AbstractCode>::cast(info->bytecode_array())
+            : Handle<AbstractCode>::cast(info->code());
     if (abstract_code.is_identical_to(
             info->isolate()->builtins()->CompileLazy())) {
       return;
@@ -757,57 +401,52 @@
     String* script_name = script->name()->IsString()
                               ? String::cast(script->name())
                               : info->isolate()->heap()->empty_string();
-    Logger::LogEventsAndTags log_tag = Logger::ToNativeByScript(tag, *script);
+    CodeEventListener::LogEventsAndTags log_tag =
+        Logger::ToNativeByScript(tag, *script);
     PROFILE(info->isolate(),
-            CodeCreateEvent(log_tag, *abstract_code, *shared, info, script_name,
+            CodeCreateEvent(log_tag, *abstract_code, *shared, script_name,
                             line_num, column_num));
   }
 }
 
-void EnsureFeedbackVector(CompilationInfo* info) {
-  if (!info->has_shared_info()) return;
+void EnsureFeedbackMetadata(CompilationInfo* info) {
+  DCHECK(info->has_shared_info());
 
-  // If no type feedback vector exists, we create one now. At this point the
+  // If no type feedback metadata exists, we create it now. At this point the
   // AstNumbering pass has already run. Note the snapshot can contain outdated
   // vectors for a different configuration, hence we also recreate a new vector
   // when the function is not compiled (i.e. no code was serialized).
-  if (info->shared_info()->feedback_vector()->is_empty() ||
+
+  // TODO(mvstanton): reintroduce is_empty() predicate to feedback_metadata().
+  if (info->shared_info()->feedback_metadata()->length() == 0 ||
       !info->shared_info()->is_compiled()) {
     Handle<TypeFeedbackMetadata> feedback_metadata = TypeFeedbackMetadata::New(
         info->isolate(), info->literal()->feedback_vector_spec());
-    Handle<TypeFeedbackVector> feedback_vector =
-        TypeFeedbackVector::New(info->isolate(), feedback_metadata);
-    info->shared_info()->set_feedback_vector(*feedback_vector);
+    info->shared_info()->set_feedback_metadata(*feedback_metadata);
   }
 
   // It's very important that recompiles do not alter the structure of the type
   // feedback vector. Verify that the structure fits the function literal.
-  CHECK(!info->shared_info()->feedback_vector()->metadata()->SpecDiffersFrom(
+  CHECK(!info->shared_info()->feedback_metadata()->SpecDiffersFrom(
       info->literal()->feedback_vector_spec()));
 }
 
-bool CompileUnoptimizedCode(CompilationInfo* info) {
-  DCHECK(AllowCompilation::IsAllowed(info->isolate()));
-  if (!Compiler::Analyze(info->parse_info()) ||
-      !(EnsureFeedbackVector(info), FullCodeGenerator::MakeCode(info))) {
-    Isolate* isolate = info->isolate();
-    if (!isolate->has_pending_exception()) isolate->StackOverflow();
-    return false;
-  }
-  return true;
-}
-
 bool UseIgnition(CompilationInfo* info) {
-  // TODO(4681): Generator functions are not yet supported.
-  if (info->shared_info()->is_generator()) {
+  DCHECK(info->has_shared_info());
+
+  // When requesting debug code as a replacement for existing code, we provide
+  // the same kind as the existing code (to prevent implicit tier-change).
+  if (info->is_debug() && info->shared_info()->is_compiled()) {
+    return info->shared_info()->HasBytecodeArray();
+  }
+
+  // For generator or async functions we might avoid Ignition wholesale.
+  if (info->shared_info()->is_resumable() && !FLAG_ignition_generators) {
     return false;
   }
 
-  // TODO(4681): Resuming a suspended frame is not supported.
-  if (info->shared_info()->HasBuiltinFunctionId() &&
-      (info->shared_info()->builtin_function_id() == kGeneratorObjectNext ||
-       info->shared_info()->builtin_function_id() == kGeneratorObjectReturn ||
-       info->shared_info()->builtin_function_id() == kGeneratorObjectThrow)) {
+  // Since we can't OSR from Ignition, skip Ignition for asm.js functions.
+  if (info->shared_info()->asm_function()) {
     return false;
   }
 
@@ -822,26 +461,26 @@
 }
 
 int CodeAndMetadataSize(CompilationInfo* info) {
-  int size = 0;
   if (info->has_bytecode_array()) {
-    Handle<BytecodeArray> bytecode_array = info->bytecode_array();
-    size += bytecode_array->BytecodeArraySize();
-    size += bytecode_array->constant_pool()->Size();
-    size += bytecode_array->handler_table()->Size();
-    size += bytecode_array->source_position_table()->Size();
-  } else {
-    Handle<Code> code = info->code();
-    size += code->CodeSize();
-    size += code->relocation_info()->Size();
-    size += code->deoptimization_data()->Size();
-    size += code->handler_table()->Size();
+    return info->bytecode_array()->SizeIncludingMetadata();
   }
-  return size;
+  return info->code()->SizeIncludingMetadata();
 }
 
-bool GenerateBaselineCode(CompilationInfo* info) {
+bool GenerateUnoptimizedCode(CompilationInfo* info) {
   bool success;
-  EnsureFeedbackVector(info);
+  EnsureFeedbackMetadata(info);
+  if (FLAG_validate_asm && info->scope()->asm_module()) {
+    AsmTyper typer(info->isolate(), info->zone(), *(info->script()),
+                   info->literal());
+    if (FLAG_enable_simd_asmjs) {
+      typer.set_allow_simd(true);
+    }
+    if (!typer.Validate()) {
+      DCHECK(!info->isolate()->has_pending_exception());
+      PrintF("Validation of asm.js module failed: %s", typer.error_message());
+    }
+  }
   if (FLAG_ignition && UseIgnition(info)) {
     success = interpreter::Interpreter::MakeBytecode(info);
   } else {
@@ -850,15 +489,17 @@
   if (success) {
     Isolate* isolate = info->isolate();
     Counters* counters = isolate->counters();
+    // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually.
     counters->total_baseline_code_size()->Increment(CodeAndMetadataSize(info));
     counters->total_baseline_compile_count()->Increment(1);
   }
   return success;
 }
 
-bool CompileBaselineCode(CompilationInfo* info) {
+bool CompileUnoptimizedCode(CompilationInfo* info) {
   DCHECK(AllowCompilation::IsAllowed(info->isolate()));
-  if (!Compiler::Analyze(info->parse_info()) || !GenerateBaselineCode(info)) {
+  if (!Compiler::Analyze(info->parse_info()) ||
+      !GenerateUnoptimizedCode(info)) {
     Isolate* isolate = info->isolate();
     if (!isolate->has_pending_exception()) isolate->StackOverflow();
     return false;
@@ -866,44 +507,51 @@
   return true;
 }
 
-void InstallBaselineCompilationResult(CompilationInfo* info,
-                                      Handle<SharedFunctionInfo> shared,
-                                      Handle<ScopeInfo> scope_info) {
+void InstallSharedScopeInfo(CompilationInfo* info,
+                            Handle<SharedFunctionInfo> shared) {
+  Handle<ScopeInfo> scope_info =
+      ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
+  shared->set_scope_info(*scope_info);
+}
+
+void InstallSharedCompilationResult(CompilationInfo* info,
+                                    Handle<SharedFunctionInfo> shared) {
+  // TODO(mstarzinger): Compiling for debug code might be used to reveal inner
+  // functions via {FindSharedFunctionInfoInScript}, in which case we end up
+  // regenerating existing bytecode. Fix this!
+  if (info->is_debug() && info->has_bytecode_array()) {
+    shared->ClearBytecodeArray();
+  }
   // Assert that we are not overwriting (possibly patched) debug code.
-  DCHECK(!shared->HasDebugCode());
+  DCHECK(!shared->HasDebugInfo());
   DCHECK(!info->code().is_null());
   shared->ReplaceCode(*info->code());
-  shared->set_scope_info(*scope_info);
   if (info->has_bytecode_array()) {
     DCHECK(!shared->HasBytecodeArray());  // Only compiled once.
     shared->set_bytecode_array(*info->bytecode_array());
   }
 }
 
-MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCodeCommon(
-    CompilationInfo* info) {
+MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(CompilationInfo* info) {
   VMState<COMPILER> state(info->isolate());
   PostponeInterruptsScope postpone(info->isolate());
 
   // Parse and update CompilationInfo with the results.
   if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>();
   Handle<SharedFunctionInfo> shared = info->shared_info();
-  FunctionLiteral* lit = info->literal();
-  DCHECK_EQ(shared->language_mode(), lit->language_mode());
-  SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
-  MaybeDisableOptimization(shared, lit->dont_optimize_reason());
+  DCHECK_EQ(shared->language_mode(), info->literal()->language_mode());
 
   // Compile either unoptimized code or bytecode for the interpreter.
-  if (!CompileBaselineCode(info)) return MaybeHandle<Code>();
-  RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
+  if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>();
 
-  // Update the shared function info with the scope info. Allocating the
-  // ScopeInfo object may cause a GC.
-  Handle<ScopeInfo> scope_info =
-      ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
+  // Update the shared function info with the scope info.
+  InstallSharedScopeInfo(info, shared);
 
   // Install compilation result on the shared function info
-  InstallBaselineCompilationResult(info, shared, scope_info);
+  InstallSharedCompilationResult(info, shared);
+
+  // Record the function compilation event.
+  RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
 
   return info->code();
 }
@@ -964,7 +612,9 @@
   if (!shared_info.is_null()) {
     FunctionLiteral* lit = parse_info->literal();
     shared_info->set_ast_node_count(lit->ast_node_count());
-    MaybeDisableOptimization(shared_info, lit->dont_optimize_reason());
+    if (lit->dont_optimize_reason() != kNoReason) {
+      shared_info->DisableOptimization(lit->dont_optimize_reason());
+    }
     shared_info->set_dont_crankshaft(
         shared_info->dont_crankshaft() ||
         (lit->flags() & AstProperties::kDontCrankshaft));
@@ -972,21 +622,47 @@
   return true;
 }
 
-bool GetOptimizedCodeNow(CompilationInfo* info) {
-  Isolate* isolate = info->isolate();
-  CanonicalHandleScope canonical(isolate);
-  TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
-  TRACE_EVENT0("v8", "V8.OptimizeCode");
+bool UseTurboFan(Handle<SharedFunctionInfo> shared) {
+  bool optimization_disabled = shared->optimization_disabled();
+  bool dont_crankshaft = shared->dont_crankshaft();
 
-  if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
+  // Check the enabling conditions for Turbofan.
+  // 1. "use asm" code.
+  bool is_turbofanable_asm =
+      FLAG_turbo_asm && shared->asm_function() && !optimization_disabled;
+
+  // 2. Fallback for features unsupported by Crankshaft.
+  bool is_unsupported_by_crankshaft_but_turbofanable =
+      dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 &&
+      !optimization_disabled;
+
+  // 3. Explicitly enabled by the command-line filter.
+  bool passes_turbo_filter = shared->PassesFilter(FLAG_turbo_filter);
+
+  return is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable ||
+         passes_turbo_filter;
+}
+
+bool GetOptimizedCodeNow(CompilationJob* job) {
+  CompilationInfo* info = job->info();
+  Isolate* isolate = info->isolate();
+
+  // Parsing is not required when optimizing from existing bytecode.
+  if (!info->is_optimizing_from_bytecode()) {
+    if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
+    EnsureFeedbackMetadata(info);
+  }
+
+  JSFunction::EnsureLiterals(info->closure());
 
   TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
+  RuntimeCallTimerScope runtimeTimer(isolate,
+                                     &RuntimeCallStats::RecompileSynchronous);
   TRACE_EVENT0("v8", "V8.RecompileSynchronous");
 
-  OptimizedCompileJob job(info);
-  if (job.CreateGraph() != OptimizedCompileJob::SUCCEEDED ||
-      job.OptimizeGraph() != OptimizedCompileJob::SUCCEEDED ||
-      job.GenerateCode() != OptimizedCompileJob::SUCCEEDED) {
+  if (job->CreateGraph() != CompilationJob::SUCCEEDED ||
+      job->OptimizeGraph() != CompilationJob::SUCCEEDED ||
+      job->GenerateCode() != CompilationJob::SUCCEEDED) {
     if (FLAG_trace_opt) {
       PrintF("[aborted optimizing ");
       info->closure()->ShortPrint();
@@ -996,18 +672,16 @@
   }
 
   // Success!
+  job->RecordOptimizationStats();
   DCHECK(!isolate->has_pending_exception());
   InsertCodeIntoOptimizedCodeMap(info);
-  RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info,
-                            info->shared_info());
+  RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
   return true;
 }
 
-bool GetOptimizedCodeLater(CompilationInfo* info) {
+bool GetOptimizedCodeLater(CompilationJob* job) {
+  CompilationInfo* info = job->info();
   Isolate* isolate = info->isolate();
-  CanonicalHandleScope canonical(isolate);
-  TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
-  TRACE_EVENT0("v8", "V8.OptimizeCode");
 
   if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
     if (FLAG_trace_concurrent_recompilation) {
@@ -1018,55 +692,44 @@
     return false;
   }
 
+  // All handles below this point will be allocated in a deferred handle scope
+  // that is detached and handed off to the background thread when we return.
   CompilationHandleScope handle_scope(info);
-  if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
+
+  // Parsing is not required when optimizing from existing bytecode.
+  if (!info->is_optimizing_from_bytecode()) {
+    if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
+    EnsureFeedbackMetadata(info);
+  }
+
+  JSFunction::EnsureLiterals(info->closure());
 
   // Reopen handles in the new CompilationHandleScope.
   info->ReopenHandlesInNewHandleScope();
   info->parse_info()->ReopenHandlesInNewHandleScope();
 
   TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
+  RuntimeCallTimerScope runtimeTimer(info->isolate(),
+                                     &RuntimeCallStats::RecompileSynchronous);
   TRACE_EVENT0("v8", "V8.RecompileSynchronous");
 
-  OptimizedCompileJob* job = new (info->zone()) OptimizedCompileJob(info);
-  OptimizedCompileJob::Status status = job->CreateGraph();
-  if (status != OptimizedCompileJob::SUCCEEDED) return false;
+  if (job->CreateGraph() != CompilationJob::SUCCEEDED) return false;
   isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
 
   if (FLAG_trace_concurrent_recompilation) {
     PrintF("  ** Queued ");
     info->closure()->ShortPrint();
-    if (info->is_osr()) {
-      PrintF(" for concurrent OSR at %d.\n", info->osr_ast_id().ToInt());
-    } else {
-      PrintF(" for concurrent optimization.\n");
-    }
+    PrintF(" for concurrent optimization.\n");
   }
   return true;
 }
 
-MaybeHandle<Code> GetUnoptimizedCode(Handle<JSFunction> function) {
-  DCHECK(!function->GetIsolate()->has_pending_exception());
-  DCHECK(!function->is_compiled());
-  if (function->shared()->is_compiled()) {
-    return Handle<Code>(function->shared()->code());
-  }
-
-  CompilationInfoWithZone info(function);
-  Handle<Code> result;
-  ASSIGN_RETURN_ON_EXCEPTION(info.isolate(), result,
-                             GetUnoptimizedCodeCommon(&info),
-                             Code);
-  return result;
-}
-
 MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
                                    Compiler::ConcurrencyMode mode,
                                    BailoutId osr_ast_id = BailoutId::None(),
                                    JavaScriptFrame* osr_frame = nullptr) {
   Isolate* isolate = function->GetIsolate();
   Handle<SharedFunctionInfo> shared(function->shared(), isolate);
-  if (shared->HasDebugInfo()) return MaybeHandle<Code>();
 
   Handle<Code> cached_code;
   if (GetCodeFromOptimizedCodeMap(function, osr_ast_id)
@@ -1082,82 +745,256 @@
     return cached_code;
   }
 
-  DCHECK(AllowCompilation::IsAllowed(isolate));
-
+  // Reset profiler ticks, function is no longer considered hot.
   if (shared->is_compiled()) {
     shared->code()->set_profiler_ticks(0);
   }
 
-  // TODO(mstarzinger): We cannot properly deserialize a scope chain containing
-  // an eval scope and hence would fail at parsing the eval source again.
-  if (shared->disable_optimization_reason() == kEval) {
-    return MaybeHandle<Code>();
-  }
-
-  // TODO(mstarzinger): We cannot properly deserialize a scope chain for the
-  // builtin context, hence Genesis::InstallExperimentalNatives would fail.
-  if (shared->is_toplevel() && isolate->bootstrapper()->IsActive()) {
-    return MaybeHandle<Code>();
-  }
-
-  base::SmartPointer<CompilationInfo> info(
-      new CompilationInfoWithZone(function));
   VMState<COMPILER> state(isolate);
   DCHECK(!isolate->has_pending_exception());
   PostponeInterruptsScope postpone(isolate);
+  bool use_turbofan = UseTurboFan(shared);
+  base::SmartPointer<CompilationJob> job(
+      use_turbofan ? compiler::Pipeline::NewCompilationJob(function)
+                   : new HCompilationJob(function));
+  CompilationInfo* info = job->info();
+  ParseInfo* parse_info = info->parse_info();
 
-  info->SetOptimizingForOsr(osr_ast_id);
+  info->SetOptimizingForOsr(osr_ast_id, osr_frame);
+
+  // Do not use Crankshaft/TurboFan if we need to be able to set break points.
+  if (info->shared_info()->HasDebugInfo()) {
+    info->AbortOptimization(kFunctionBeingDebugged);
+    return MaybeHandle<Code>();
+  }
+
+  // Limit the number of times we try to optimize functions.
+  const int kMaxOptCount =
+      FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
+  if (info->shared_info()->opt_count() > kMaxOptCount) {
+    info->AbortOptimization(kOptimizedTooManyTimes);
+    return MaybeHandle<Code>();
+  }
+
+  CanonicalHandleScope canonical(isolate);
+  TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
+  RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::OptimizeCode);
+  TRACE_EVENT0("v8", "V8.OptimizeCode");
+
+  // TurboFan can optimize directly from existing bytecode.
+  if (FLAG_turbo_from_bytecode && use_turbofan &&
+      info->shared_info()->HasBytecodeArray()) {
+    info->MarkAsOptimizeFromBytecode();
+  }
+
+  if (IsEvalToplevel(shared)) {
+    parse_info->set_eval();
+    if (function->context()->IsNativeContext()) parse_info->set_global();
+    parse_info->set_toplevel();
+    parse_info->set_allow_lazy_parsing(false);
+    parse_info->set_lazy(false);
+  }
 
   if (mode == Compiler::CONCURRENT) {
-    if (GetOptimizedCodeLater(info.get())) {
-      info.Detach();  // The background recompile job owns this now.
+    if (GetOptimizedCodeLater(job.get())) {
+      job.Detach();   // The background recompile job owns this now.
       return isolate->builtins()->InOptimizationQueue();
     }
   } else {
-    info->set_osr_frame(osr_frame);
-    if (GetOptimizedCodeNow(info.get())) return info->code();
+    if (GetOptimizedCodeNow(job.get())) return info->code();
   }
 
   if (isolate->has_pending_exception()) isolate->clear_pending_exception();
   return MaybeHandle<Code>();
 }
 
+class InterpreterActivationsFinder : public ThreadVisitor,
+                                     public OptimizedFunctionVisitor {
+ public:
+  explicit InterpreterActivationsFinder(SharedFunctionInfo* shared)
+      : shared_(shared), has_activations_(false) {}
+
+  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
+    Address* activation_pc_address = nullptr;
+    JavaScriptFrameIterator it(isolate, top);
+    for (; !it.done(); it.Advance()) {
+      JavaScriptFrame* frame = it.frame();
+      if (!frame->is_interpreted()) continue;
+      if (frame->function()->shared() == shared_) {
+        has_activations_ = true;
+        activation_pc_address = frame->pc_address();
+      }
+    }
+
+    if (activation_pc_address) {
+      activation_pc_addresses_.push_back(activation_pc_address);
+    }
+  }
+
+  void VisitFunction(JSFunction* function) {
+    if (function->Inlines(shared_)) has_activations_ = true;
+  }
+
+  void EnterContext(Context* context) {}
+  void LeaveContext(Context* context) {}
+
+  bool MarkActivationsForBaselineOnReturn(Isolate* isolate) {
+    if (activation_pc_addresses_.empty()) return false;
+
+    for (Address* activation_pc_address : activation_pc_addresses_) {
+      DCHECK(isolate->inner_pointer_to_code_cache()
+                 ->GetCacheEntry(*activation_pc_address)
+                 ->code->is_interpreter_trampoline_builtin());
+      *activation_pc_address =
+          isolate->builtins()->InterpreterMarkBaselineOnReturn()->entry();
+    }
+    return true;
+  }
+
+  bool has_activations() { return has_activations_; }
+
+ private:
+  SharedFunctionInfo* shared_;
+  bool has_activations_;
+  std::vector<Address*> activation_pc_addresses_;
+};
+
+bool HasInterpreterActivations(
+    Isolate* isolate, InterpreterActivationsFinder* activations_finder) {
+  activations_finder->VisitThread(isolate, isolate->thread_local_top());
+  isolate->thread_manager()->IterateArchivedThreads(activations_finder);
+  if (FLAG_turbo_from_bytecode) {
+    // If we are able to optimize functions directly from bytecode, then there
+    // might be optimized functions that rely on bytecode being around. We need
+    // to prevent switching the given function to baseline code in those cases.
+    Deoptimizer::VisitAllOptimizedFunctions(isolate, activations_finder);
+  }
+  return activations_finder->has_activations();
+}
+
+MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) {
+  Isolate* isolate = function->GetIsolate();
+  VMState<COMPILER> state(isolate);
+  PostponeInterruptsScope postpone(isolate);
+  Zone zone(isolate->allocator());
+  ParseInfo parse_info(&zone, function);
+  CompilationInfo info(&parse_info, function);
+
+  // Reset profiler ticks, function is no longer considered hot.
+  if (function->shared()->HasBytecodeArray()) {
+    function->shared()->set_profiler_ticks(0);
+  }
+
+  // Nothing left to do if the function already has baseline code.
+  if (function->shared()->code()->kind() == Code::FUNCTION) {
+    return Handle<Code>(function->shared()->code());
+  }
+
+  // We do not switch to baseline code when the debugger might have created a
+  // copy of the bytecode with break slots to be able to set break points.
+  if (function->shared()->HasDebugInfo()) {
+    return MaybeHandle<Code>();
+  }
+
+  // TODO(4280): For now we do not switch generators or async functions to
+  // baseline code because there might be suspended activations stored in
+  // generator objects on the heap. We could eventually go directly to
+  // TurboFan in this case.
+  if (function->shared()->is_resumable()) {
+    return MaybeHandle<Code>();
+  }
+
+  // TODO(4280): For now we disable switching to baseline code in the presence
+  // of interpreter activations of the given function. The reasons are:
+  //  1) The debugger assumes each function is either full-code or bytecode.
+  //  2) The underlying bytecode is cleared below, breaking stack unwinding.
+  InterpreterActivationsFinder activations_finder(function->shared());
+  if (HasInterpreterActivations(isolate, &activations_finder)) {
+    if (FLAG_trace_opt) {
+      OFStream os(stdout);
+      os << "[unable to switch " << Brief(*function) << " due to activations]"
+         << std::endl;
+    }
+
+    if (activations_finder.MarkActivationsForBaselineOnReturn(isolate)) {
+      if (FLAG_trace_opt) {
+        OFStream os(stdout);
+        os << "[marking " << Brief(function->shared())
+           << " for baseline recompilation on return]" << std::endl;
+      }
+    }
+
+    return MaybeHandle<Code>();
+  }
+
+  if (FLAG_trace_opt) {
+    OFStream os(stdout);
+    os << "[switching method " << Brief(*function) << " to baseline code]"
+       << std::endl;
+  }
+
+  // Parse and update CompilationInfo with the results.
+  if (!Parser::ParseStatic(info.parse_info())) return MaybeHandle<Code>();
+  Handle<SharedFunctionInfo> shared = info.shared_info();
+  DCHECK_EQ(shared->language_mode(), info.literal()->language_mode());
+
+  // Compile baseline code using the full code generator.
+  if (!Compiler::Analyze(info.parse_info()) ||
+      !FullCodeGenerator::MakeCode(&info)) {
+    if (!isolate->has_pending_exception()) isolate->StackOverflow();
+    return MaybeHandle<Code>();
+  }
+
+  // TODO(4280): For now we play it safe and remove the bytecode array when we
+  // switch to baseline code. We might consider keeping around the bytecode so
+  // that it can be used as the "source of truth" eventually.
+  shared->ClearBytecodeArray();
+
+  // Update the shared function info with the scope info.
+  InstallSharedScopeInfo(&info, shared);
+
+  // Install compilation result on the shared function info
+  InstallSharedCompilationResult(&info, shared);
+
+  // Record the function compilation event.
+  RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, &info);
+
+  return info.code();
+}
+
 MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) {
   Isolate* isolate = function->GetIsolate();
   DCHECK(!isolate->has_pending_exception());
   DCHECK(!function->is_compiled());
   TimerEventScope<TimerEventCompileCode> compile_timer(isolate);
+  RuntimeCallTimerScope runtimeTimer(isolate,
+                                     &RuntimeCallStats::CompileCodeLazy);
   TRACE_EVENT0("v8", "V8.CompileCode");
   AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy());
-  // If the debugger is active, do not compile with turbofan unless we can
-  // deopt from turbofan code.
-  if (FLAG_turbo_asm && function->shared()->asm_function() &&
-      (FLAG_turbo_asm_deoptimization || !isolate->debug()->is_active()) &&
-      !FLAG_turbo_osr) {
-    CompilationInfoWithZone info(function);
 
-    VMState<COMPILER> state(isolate);
-    PostponeInterruptsScope postpone(isolate);
-
-    info.SetOptimizing();
-
-    if (GetOptimizedCodeNow(&info)) {
+  if (FLAG_turbo_cache_shared_code) {
+    Handle<Code> cached_code;
+    if (GetCodeFromOptimizedCodeMap(function, BailoutId::None())
+            .ToHandle(&cached_code)) {
+      if (FLAG_trace_opt) {
+        PrintF("[found optimized code for ");
+        function->ShortPrint();
+        PrintF(" during unoptimized compile]\n");
+      }
       DCHECK(function->shared()->is_compiled());
-      return info.code();
+      return cached_code;
     }
-    // We have failed compilation. If there was an exception clear it so that
-    // we can compile unoptimized code.
-    if (isolate->has_pending_exception()) isolate->clear_pending_exception();
   }
 
   if (function->shared()->is_compiled()) {
     return Handle<Code>(function->shared()->code());
   }
 
-  CompilationInfoWithZone info(function);
+  Zone zone(isolate->allocator());
+  ParseInfo parse_info(&zone, function);
+  CompilationInfo info(&parse_info, function);
   Handle<Code> result;
-  ASSIGN_RETURN_ON_EXCEPTION(isolate, result, GetUnoptimizedCodeCommon(&info),
-                             Code);
+  ASSIGN_RETURN_ON_EXCEPTION(isolate, result, GetUnoptimizedCode(&info), Code);
 
   if (FLAG_always_opt) {
     Handle<Code> opt_code;
@@ -1171,59 +1008,6 @@
 }
 
 
-bool CompileEvalForDebugging(Handle<JSFunction> function,
-                             Handle<SharedFunctionInfo> shared) {
-  Handle<Script> script(Script::cast(shared->script()));
-  Handle<Context> context(function->context());
-
-  Zone zone(function->GetIsolate()->allocator());
-  ParseInfo parse_info(&zone, script);
-  CompilationInfo info(&parse_info);
-  Isolate* isolate = info.isolate();
-
-  parse_info.set_eval();
-  parse_info.set_context(context);
-  if (context->IsNativeContext()) parse_info.set_global();
-  parse_info.set_toplevel();
-  parse_info.set_allow_lazy_parsing(false);
-  parse_info.set_language_mode(shared->language_mode());
-  parse_info.set_parse_restriction(NO_PARSE_RESTRICTION);
-  info.MarkAsDebug();
-
-  VMState<COMPILER> state(info.isolate());
-
-  if (!Parser::ParseStatic(&parse_info)) {
-    isolate->clear_pending_exception();
-    return false;
-  }
-
-  FunctionLiteral* lit = parse_info.literal();
-  LiveEditFunctionTracker live_edit_tracker(isolate, lit);
-
-  if (!CompileUnoptimizedCode(&info)) {
-    isolate->clear_pending_exception();
-    return false;
-  }
-  shared->ReplaceCode(*info.code());
-  return true;
-}
-
-
-bool CompileForDebugging(CompilationInfo* info) {
-  info->MarkAsDebug();
-  if (GetUnoptimizedCodeCommon(info).is_null()) {
-    info->isolate()->clear_pending_exception();
-    return false;
-  }
-  return true;
-}
-
-inline bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) {
-  return shared->is_toplevel() && shared->script()->IsScript() &&
-         Script::cast(shared->script())->compilation_type() ==
-             Script::COMPILATION_TYPE_EVAL;
-}
-
 Handle<SharedFunctionInfo> NewSharedFunctionInfoForLiteral(
     Isolate* isolate, FunctionLiteral* literal, Handle<Script> script) {
   Handle<Code> code = isolate->builtins()->CompileLazy();
@@ -1239,6 +1023,7 @@
 Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
   Isolate* isolate = info->isolate();
   TimerEventScope<TimerEventCompileCode> timer(isolate);
+  RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::CompileCode);
   TRACE_EVENT0("v8", "V8.CompileCode");
   PostponeInterruptsScope postpone(isolate);
   DCHECK(!isolate->native_context().is_null());
@@ -1294,61 +1079,55 @@
 
     DCHECK(!info->is_debug() || !parse_info->allow_lazy_parsing());
 
-    info->MarkAsFirstCompile();
-
     FunctionLiteral* lit = parse_info->literal();
-    LiveEditFunctionTracker live_edit_tracker(isolate, lit);
 
     // Measure how long it takes to do the compilation; only take the
     // rest of the function into account to avoid overlap with the
     // parsing statistics.
-    HistogramTimer* rate = info->is_eval()
-          ? info->isolate()->counters()->compile_eval()
-          : info->isolate()->counters()->compile();
+    RuntimeCallTimerScope runtimeTimer(
+        isolate, parse_info->is_eval() ? &RuntimeCallStats::CompileEval
+                                       : &RuntimeCallStats::Compile);
+    HistogramTimer* rate = parse_info->is_eval()
+                               ? info->isolate()->counters()->compile_eval()
+                               : info->isolate()->counters()->compile();
     HistogramTimerScope timer(rate);
-    TRACE_EVENT0("v8", info->is_eval() ? "V8.CompileEval" : "V8.Compile");
+    TRACE_EVENT0("v8", parse_info->is_eval() ? "V8.CompileEval" : "V8.Compile");
 
     // Allocate a shared function info object.
     DCHECK_EQ(RelocInfo::kNoPosition, lit->function_token_position());
     result = NewSharedFunctionInfoForLiteral(isolate, lit, script);
     result->set_is_toplevel(true);
-    if (info->is_eval()) {
+    if (parse_info->is_eval()) {
       // Eval scripts cannot be (re-)compiled without context.
       result->set_allows_lazy_compilation_without_context(false);
     }
     parse_info->set_shared_info(result);
 
     // Compile the code.
-    if (!CompileBaselineCode(info)) {
+    if (!CompileUnoptimizedCode(info)) {
       return Handle<SharedFunctionInfo>::null();
     }
 
+    // Update the shared function info with the scope info.
+    InstallSharedScopeInfo(info, result);
+
     // Install compilation result on the shared function info
-    Handle<ScopeInfo> scope_info =
-        ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
-    InstallBaselineCompilationResult(info, result, scope_info);
+    InstallSharedCompilationResult(info, result);
 
     Handle<String> script_name =
         script->name()->IsString()
             ? Handle<String>(String::cast(script->name()))
             : isolate->factory()->empty_string();
-    Logger::LogEventsAndTags log_tag = info->is_eval()
-        ? Logger::EVAL_TAG
-        : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script);
+    CodeEventListener::LogEventsAndTags log_tag =
+        parse_info->is_eval()
+            ? CodeEventListener::EVAL_TAG
+            : Logger::ToNativeByScript(CodeEventListener::SCRIPT_TAG, *script);
 
-    PROFILE(isolate, CodeCreateEvent(log_tag, *info->abstract_code(), *result,
-                                     info, *script_name));
-
-    // Hint to the runtime system used when allocating space for initial
-    // property space by setting the expected number of properties for
-    // the instances of the function.
-    SetExpectedNofPropertiesFromEstimate(result,
-                                         lit->expected_property_count());
+    PROFILE(isolate, CodeCreateEvent(log_tag, result->abstract_code(), *result,
+                                     *script_name));
 
     if (!script.is_null())
       script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
-
-    live_edit_tracker.RecordFunctionInfo(result, lit, info->zone());
   }
 
   return result;
@@ -1370,90 +1149,211 @@
 
 bool Compiler::ParseAndAnalyze(ParseInfo* info) {
   if (!Parser::ParseStatic(info)) return false;
-  return Compiler::Analyze(info);
+  if (!Compiler::Analyze(info)) return false;
+  DCHECK_NOT_NULL(info->literal());
+  DCHECK_NOT_NULL(info->scope());
+  return true;
 }
 
 bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
   if (function->is_compiled()) return true;
-  MaybeHandle<Code> maybe_code = GetLazyCode(function);
+  Isolate* isolate = function->GetIsolate();
+  DCHECK(AllowCompilation::IsAllowed(isolate));
+
+  // Start a compilation.
   Handle<Code> code;
-  if (!maybe_code.ToHandle(&code)) {
+  if (!GetLazyCode(function).ToHandle(&code)) {
     if (flag == CLEAR_EXCEPTION) {
-      function->GetIsolate()->clear_pending_exception();
+      isolate->clear_pending_exception();
     }
     return false;
   }
-  DCHECK(code->IsJavaScriptCode());
+
+  // Install code on closure.
   function->ReplaceCode(*code);
+  JSFunction::EnsureLiterals(function);
+
+  // Check postconditions on success.
+  DCHECK(!isolate->has_pending_exception());
+  DCHECK(function->shared()->is_compiled());
+  DCHECK(function->is_compiled());
+  return true;
+}
+
+bool Compiler::CompileBaseline(Handle<JSFunction> function) {
+  Isolate* isolate = function->GetIsolate();
+  DCHECK(AllowCompilation::IsAllowed(isolate));
+
+  // Start a compilation.
+  Handle<Code> code;
+  if (!GetBaselineCode(function).ToHandle(&code)) {
+    // Baseline generation failed, get unoptimized code.
+    DCHECK(function->shared()->is_compiled());
+    code = handle(function->shared()->code());
+    isolate->clear_pending_exception();
+  }
+
+  // Install code on closure.
+  function->ReplaceCode(*code);
+  JSFunction::EnsureLiterals(function);
+
+  // Check postconditions on success.
+  DCHECK(!isolate->has_pending_exception());
+  DCHECK(function->shared()->is_compiled());
   DCHECK(function->is_compiled());
   return true;
 }
 
 bool Compiler::CompileOptimized(Handle<JSFunction> function,
                                 ConcurrencyMode mode) {
+  if (function->IsOptimized()) return true;
+  Isolate* isolate = function->GetIsolate();
+  DCHECK(AllowCompilation::IsAllowed(isolate));
+
+  // Start a compilation.
   Handle<Code> code;
-  if (GetOptimizedCode(function, mode).ToHandle(&code)) {
-    // Optimization succeeded, return optimized code.
-    function->ReplaceCode(*code);
-  } else {
+  if (!GetOptimizedCode(function, mode).ToHandle(&code)) {
     // Optimization failed, get unoptimized code.
-    Isolate* isolate = function->GetIsolate();
-    if (isolate->has_pending_exception()) {  // Possible stack overflow.
-      return false;
-    }
-    code = Handle<Code>(function->shared()->code(), isolate);
-    if (code->kind() != Code::FUNCTION &&
-        code->kind() != Code::OPTIMIZED_FUNCTION) {
-      if (!GetUnoptimizedCode(function).ToHandle(&code)) {
+    DCHECK(!isolate->has_pending_exception());
+    if (function->shared()->is_compiled()) {
+      code = handle(function->shared()->code(), isolate);
+    } else {
+      Zone zone(isolate->allocator());
+      ParseInfo parse_info(&zone, function);
+      CompilationInfo info(&parse_info, function);
+      if (!GetUnoptimizedCode(&info).ToHandle(&code)) {
         return false;
       }
     }
-    function->ReplaceCode(*code);
   }
 
-  DCHECK(function->code()->kind() == Code::FUNCTION ||
-         function->code()->kind() == Code::OPTIMIZED_FUNCTION ||
-         (function->code()->is_interpreter_entry_trampoline() &&
-          function->shared()->HasBytecodeArray()) ||
-         function->IsInOptimizationQueue());
+  // Install code on closure.
+  function->ReplaceCode(*code);
+  JSFunction::EnsureLiterals(function);
+
+  // Check postconditions on success.
+  DCHECK(!isolate->has_pending_exception());
+  DCHECK(function->shared()->is_compiled());
+  DCHECK(function->is_compiled());
   return true;
 }
 
 bool Compiler::CompileDebugCode(Handle<JSFunction> function) {
-  Handle<SharedFunctionInfo> shared(function->shared());
-  if (IsEvalToplevel(shared)) {
-    return CompileEvalForDebugging(function, shared);
-  } else {
-    CompilationInfoWithZone info(function);
-    return CompileForDebugging(&info);
+  Isolate* isolate = function->GetIsolate();
+  DCHECK(AllowCompilation::IsAllowed(isolate));
+
+  // Start a compilation.
+  Zone zone(isolate->allocator());
+  ParseInfo parse_info(&zone, function);
+  CompilationInfo info(&parse_info, Handle<JSFunction>::null());
+  if (IsEvalToplevel(handle(function->shared()))) {
+    parse_info.set_eval();
+    if (function->context()->IsNativeContext()) parse_info.set_global();
+    parse_info.set_toplevel();
+    parse_info.set_allow_lazy_parsing(false);
+    parse_info.set_lazy(false);
   }
+  info.MarkAsDebug();
+  if (GetUnoptimizedCode(&info).is_null()) {
+    isolate->clear_pending_exception();
+    return false;
+  }
+
+  // Check postconditions on success.
+  DCHECK(!isolate->has_pending_exception());
+  DCHECK(function->shared()->is_compiled());
+  DCHECK(function->shared()->HasDebugCode());
+  return true;
 }
 
 bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) {
+  Isolate* isolate = shared->GetIsolate();
+  DCHECK(AllowCompilation::IsAllowed(isolate));
+
+  // Start a compilation.
+  Zone zone(isolate->allocator());
+  ParseInfo parse_info(&zone, shared);
+  CompilationInfo info(&parse_info, Handle<JSFunction>::null());
   DCHECK(shared->allows_lazy_compilation_without_context());
   DCHECK(!IsEvalToplevel(shared));
-  Zone zone(shared->GetIsolate()->allocator());
-  ParseInfo parse_info(&zone, shared);
-  CompilationInfo info(&parse_info);
-  return CompileForDebugging(&info);
+  info.MarkAsDebug();
+  if (GetUnoptimizedCode(&info).is_null()) {
+    isolate->clear_pending_exception();
+    return false;
+  }
+
+  // Check postconditions on success.
+  DCHECK(!isolate->has_pending_exception());
+  DCHECK(shared->is_compiled());
+  DCHECK(shared->HasDebugCode());
+  return true;
+}
+
+MaybeHandle<JSArray> Compiler::CompileForLiveEdit(Handle<Script> script) {
+  Isolate* isolate = script->GetIsolate();
+  DCHECK(AllowCompilation::IsAllowed(isolate));
+
+  // In order to ensure that live edit function info collection finds the newly
+  // generated shared function infos, clear the script's list temporarily
+  // and restore it at the end of this method.
+  Handle<Object> old_function_infos(script->shared_function_infos(), isolate);
+  script->set_shared_function_infos(Smi::FromInt(0));
+
+  // Start a compilation.
+  Zone zone(isolate->allocator());
+  ParseInfo parse_info(&zone, script);
+  CompilationInfo info(&parse_info, Handle<JSFunction>::null());
+  parse_info.set_global();
+  info.MarkAsDebug();
+
+  // TODO(635): support extensions.
+  const bool compilation_succeeded = !CompileToplevel(&info).is_null();
+  Handle<JSArray> infos;
+  if (compilation_succeeded) {
+    // Check postconditions on success.
+    DCHECK(!isolate->has_pending_exception());
+    infos = LiveEditFunctionTracker::Collect(parse_info.literal(), script,
+                                             &zone, isolate);
+  }
+
+  // Restore the original function info list in order to remain side-effect
+  // free as much as possible, since some code expects the old shared function
+  // infos to stick around.
+  script->set_shared_function_infos(*old_function_infos);
+
+  return infos;
 }
 
 // TODO(turbofan): In the future, unoptimized code with deopt support could
 // be generated lazily once deopt is triggered.
 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
   DCHECK_NOT_NULL(info->literal());
-  DCHECK(info->has_scope());
+  DCHECK_NOT_NULL(info->scope());
   Handle<SharedFunctionInfo> shared = info->shared_info();
   if (!shared->has_deoptimization_support()) {
-    // TODO(titzer): just reuse the ParseInfo for the unoptimized compile.
-    CompilationInfoWithZone unoptimized(info->closure());
-    // Note that we use the same AST that we will use for generating the
-    // optimized code.
-    ParseInfo* parse_info = unoptimized.parse_info();
-    parse_info->set_literal(info->literal());
-    parse_info->set_scope(info->scope());
-    parse_info->set_context(info->context());
+    Zone zone(info->isolate()->allocator());
+    CompilationInfo unoptimized(info->parse_info(), info->closure());
     unoptimized.EnableDeoptimizationSupport();
+
+    // TODO(4280): For now we do not switch generators or async functions to
+    // baseline code because there might be suspended activations stored in
+    // generator objects on the heap. We could eventually go directly to
+    // TurboFan in this case.
+    if (shared->is_resumable()) return false;
+
+    // TODO(4280): For now we disable switching to baseline code in the presence
+    // of interpreter activations of the given function. The reasons are:
+    //  1) The debugger assumes each function is either full-code or bytecode.
+    //  2) The underlying bytecode is cleared below, breaking stack unwinding.
+    // The expensive check for activations only needs to be done when the given
+    // function has bytecode, otherwise we can be sure there are no activations.
+    if (shared->HasBytecodeArray()) {
+      InterpreterActivationsFinder activations_finder(*shared);
+      if (HasInterpreterActivations(info->isolate(), &activations_finder)) {
+        return false;
+      }
+    }
+
     // If the current code has reloc info for serialization, also include
     // reloc info for serialization for the new code, so that deopt support
     // can be added without losing IC state.
@@ -1461,51 +1361,36 @@
         shared->code()->has_reloc_info_for_serialization()) {
       unoptimized.PrepareForSerializing();
     }
-    EnsureFeedbackVector(&unoptimized);
+    EnsureFeedbackMetadata(&unoptimized);
     if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;
 
-    shared->EnableDeoptimizationSupport(*unoptimized.code());
-
-    info->MarkAsCompiled();
+    // TODO(4280): For now we play it safe and remove the bytecode array when we
+    // switch to baseline code. We might consider keeping around the bytecode so
+    // that it can be used as the "source of truth" eventually.
+    shared->ClearBytecodeArray();
 
     // The scope info might not have been set if a lazily compiled
     // function is inlined before being called for the first time.
     if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) {
-      Handle<ScopeInfo> target_scope_info =
-          ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
-      shared->set_scope_info(*target_scope_info);
+      InstallSharedScopeInfo(info, shared);
     }
 
+    // Install compilation result on the shared function info
+    shared->EnableDeoptimizationSupport(*unoptimized.code());
+
     // The existing unoptimized code was replaced with the new one.
-    RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
+    RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,
+                              &unoptimized);
   }
   return true;
 }
 
-void Compiler::CompileForLiveEdit(Handle<Script> script) {
-  // TODO(635): support extensions.
-  Zone zone(script->GetIsolate()->allocator());
-  ParseInfo parse_info(&zone, script);
-  CompilationInfo info(&parse_info);
-  PostponeInterruptsScope postpone(info.isolate());
-  VMState<COMPILER> state(info.isolate());
-
-  // Get rid of old list of shared function infos.
-  info.MarkAsFirstCompile();
-  info.MarkAsDebug();
-  info.parse_info()->set_global();
-  if (!Parser::ParseStatic(info.parse_info())) return;
-
-  LiveEditFunctionTracker tracker(info.isolate(), parse_info.literal());
-  if (!CompileUnoptimizedCode(&info)) return;
-  tracker.RecordRootFunctionInfo(info.code());
-}
-
 MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
     Handle<String> source, Handle<SharedFunctionInfo> outer_info,
     Handle<Context> context, LanguageMode language_mode,
-    ParseRestriction restriction, int line_offset, int column_offset,
-    Handle<Object> script_name, ScriptOriginOptions options) {
+    ParseRestriction restriction, int eval_scope_position, int eval_position,
+    int line_offset, int column_offset, Handle<Object> script_name,
+    ScriptOriginOptions options) {
   Isolate* isolate = source->GetIsolate();
   int source_length = source->length();
   isolate->counters()->total_eval_size()->Increment(source_length);
@@ -1514,7 +1399,7 @@
   CompilationCache* compilation_cache = isolate->compilation_cache();
   MaybeHandle<SharedFunctionInfo> maybe_shared_info =
       compilation_cache->LookupEval(source, outer_info, context, language_mode,
-                                    line_offset);
+                                    eval_scope_position);
   Handle<SharedFunctionInfo> shared_info;
 
   Handle<Script> script;
@@ -1526,33 +1411,28 @@
       script->set_column_offset(column_offset);
     }
     script->set_origin_options(options);
+    script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
+    Script::SetEvalOrigin(script, outer_info, eval_position);
+
     Zone zone(isolate->allocator());
     ParseInfo parse_info(&zone, script);
-    CompilationInfo info(&parse_info);
+    CompilationInfo info(&parse_info, Handle<JSFunction>::null());
     parse_info.set_eval();
     if (context->IsNativeContext()) parse_info.set_global();
     parse_info.set_language_mode(language_mode);
     parse_info.set_parse_restriction(restriction);
     parse_info.set_context(context);
 
-    Debug::RecordEvalCaller(script);
-
     shared_info = CompileToplevel(&info);
 
     if (shared_info.is_null()) {
       return MaybeHandle<JSFunction>();
     } else {
-      // Explicitly disable optimization for eval code. We're not yet prepared
-      // to handle eval-code in the optimizing compiler.
-      if (restriction != ONLY_SINGLE_FUNCTION_LITERAL) {
-        shared_info->DisableOptimization(kEval);
-      }
-
       // If caller is strict mode, the result must be in strict mode as well.
       DCHECK(is_sloppy(language_mode) ||
              is_strict(shared_info->language_mode()));
       compilation_cache->PutEval(source, outer_info, context, shared_info,
-                                 line_offset);
+                                 eval_scope_position);
     }
   }
 
@@ -1609,6 +1489,8 @@
         !isolate->debug()->is_loaded()) {
       // Then check cached code provided by embedder.
       HistogramTimerScope timer(isolate->counters()->compile_deserialize());
+      RuntimeCallTimerScope runtimeTimer(isolate,
+                                         &RuntimeCallStats::CompileDeserialize);
       TRACE_EVENT0("v8", "V8.CompileDeserialize");
       Handle<SharedFunctionInfo> result;
       if (CodeSerializer::Deserialize(isolate, *cached_data, source)
@@ -1627,8 +1509,10 @@
     timer.Start();
   }
 
-  if (!maybe_result.ToHandle(&result)) {
-    // No cache entry found. Compile the script.
+  if (!maybe_result.ToHandle(&result) ||
+      (FLAG_serialize_toplevel &&
+       compile_options == ScriptCompiler::kProduceCodeCache)) {
+    // No cache entry found, or embedder wants a code cache. Compile the script.
 
     // Create a script object describing the script to be compiled.
     Handle<Script> script = isolate->factory()->NewScript(source);
@@ -1652,7 +1536,7 @@
     // Compile the function and add it to the cache.
     Zone zone(isolate->allocator());
     ParseInfo parse_info(&zone, script);
-    CompilationInfo info(&parse_info);
+    CompilationInfo info(&parse_info, Handle<JSFunction>::null());
     if (is_module) {
       parse_info.set_module();
     } else {
@@ -1670,7 +1554,7 @@
     }
 
     parse_info.set_language_mode(
-        static_cast<LanguageMode>(info.language_mode() | language_mode));
+        static_cast<LanguageMode>(parse_info.language_mode() | language_mode));
     result = CompileToplevel(&info);
     if (extension == NULL && !result.is_null()) {
       compilation_cache->PutScript(source, context, language_mode, result);
@@ -1678,6 +1562,8 @@
           compile_options == ScriptCompiler::kProduceCodeCache) {
         HistogramTimerScope histogram_timer(
             isolate->counters()->compile_serialize());
+        RuntimeCallTimerScope runtimeTimer(isolate,
+                                           &RuntimeCallStats::CompileSerialize);
         TRACE_EVENT0("v8", "V8.CompileSerialize");
         *cached_data = CodeSerializer::Serialize(isolate, result, source);
         if (FLAG_profile_deserialization) {
@@ -1709,7 +1595,7 @@
   parse_info->set_language_mode(
       static_cast<LanguageMode>(parse_info->language_mode() | language_mode));
 
-  CompilationInfo compile_info(parse_info);
+  CompilationInfo compile_info(parse_info, Handle<JSFunction>::null());
 
   // The source was parsed lazily, so compiling for debugging is not possible.
   DCHECK(!compile_info.is_debug());
@@ -1726,7 +1612,9 @@
   // Precondition: code has been parsed and scopes have been analyzed.
   Isolate* isolate = outer_info->isolate();
   MaybeHandle<SharedFunctionInfo> maybe_existing;
-  if (outer_info->is_first_compile()) {
+
+  // Find any previously allocated shared function info for the given literal.
+  if (outer_info->shared_info()->never_compiled()) {
     // On the first compile, there are no existing shared function info for
     // inner functions yet, so do not try to find them. All bets are off for
     // live edit though.
@@ -1735,6 +1623,7 @@
   } else {
     maybe_existing = script->FindSharedFunctionInfo(literal);
   }
+
   // We found an existing shared function info. If it's already compiled,
   // don't worry about compiling it, and simply return it. If it's not yet
   // compiled, continue to decide whether to eagerly compile.
@@ -1742,6 +1631,7 @@
   // unless we already have code with debut break slots.
   Handle<SharedFunctionInfo> existing;
   if (maybe_existing.ToHandle(&existing) && existing->is_compiled()) {
+    DCHECK(!existing->is_toplevel());
     if (!outer_info->is_debug() || existing->HasDebugCode()) {
       return existing;
     }
@@ -1752,20 +1642,23 @@
   if (!maybe_existing.ToHandle(&result)) {
     result = NewSharedFunctionInfoForLiteral(isolate, literal, script);
     result->set_is_toplevel(false);
+
+    // If the outer function has been compiled before, we cannot be sure that
+    // shared function info for this function literal has been created for the
+    // first time. It may have already been compiled previously.
+    result->set_never_compiled(outer_info->shared_info()->never_compiled());
   }
 
   Zone zone(isolate->allocator());
   ParseInfo parse_info(&zone, script);
-  CompilationInfo info(&parse_info);
+  CompilationInfo info(&parse_info, Handle<JSFunction>::null());
   parse_info.set_literal(literal);
   parse_info.set_shared_info(result);
   parse_info.set_scope(literal->scope());
   parse_info.set_language_mode(literal->scope()->language_mode());
   if (outer_info->will_serialize()) info.PrepareForSerializing();
-  if (outer_info->is_first_compile()) info.MarkAsFirstCompile();
   if (outer_info->is_debug()) info.MarkAsDebug();
 
-  LiveEditFunctionTracker live_edit_tracker(isolate, literal);
   // Determine if the function can be lazily compiled. This is necessary to
   // allow some of our builtin JS files to be lazily compiled. These
   // builtins cannot be handled lazily by the parser, since we have to know
@@ -1775,13 +1668,7 @@
   // aggressive about lazy compilation, because it might trigger compilation
   // of functions without an outer context when setting a breakpoint through
   // Debug::FindSharedFunctionInfoInScript.
-  bool allow_lazy_without_ctx = literal->AllowsLazyCompilationWithoutContext();
-  // Compile eagerly for live edit. When compiling debug code, eagerly compile
-  // unless we can lazily compile without the context.
-  bool allow_lazy = literal->AllowsLazyCompilation() &&
-                    !LiveEditFunctionTracker::IsActive(isolate) &&
-                    (!info.is_debug() || allow_lazy_without_ctx);
-
+  bool allow_lazy = literal->AllowsLazyCompilation() && !info.is_debug();
   bool lazy = FLAG_lazy && allow_lazy && !literal->should_eager_compile();
 
   // Consider compiling eagerly when targeting the code cache.
@@ -1793,40 +1680,28 @@
 
   // Generate code
   TimerEventScope<TimerEventCompileCode> timer(isolate);
+  RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::CompileCode);
   TRACE_EVENT0("v8", "V8.CompileCode");
   if (lazy) {
     info.SetCode(isolate->builtins()->CompileLazy());
-  } else if (Renumber(info.parse_info()) && GenerateBaselineCode(&info)) {
+  } else if (Renumber(info.parse_info()) && GenerateUnoptimizedCode(&info)) {
     // Code generation will ensure that the feedback vector is present and
     // appropriately sized.
     DCHECK(!info.code().is_null());
-    Handle<ScopeInfo> scope_info =
-        ScopeInfo::Create(info.isolate(), info.zone(), info.scope());
     if (literal->should_eager_compile() &&
         literal->should_be_used_once_hint()) {
       info.code()->MarkToBeExecutedOnce(isolate);
     }
+    // Update the shared function info with the scope info.
+    InstallSharedScopeInfo(&info, result);
     // Install compilation result on the shared function info.
-    InstallBaselineCompilationResult(&info, result, scope_info);
+    InstallSharedCompilationResult(&info, result);
   } else {
     return Handle<SharedFunctionInfo>::null();
   }
 
   if (maybe_existing.is_null()) {
-    // If the outer function has been compiled before, we cannot be sure that
-    // shared function info for this function literal has been created for the
-    // first time. It may have already been compiled previously.
-    result->set_never_compiled(outer_info->is_first_compile() && lazy);
-
-    RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
-    result->set_allows_lazy_compilation(literal->AllowsLazyCompilation());
-    result->set_allows_lazy_compilation_without_context(allow_lazy_without_ctx);
-
-    // Set the expected number of properties for instances and return
-    // the resulting function.
-    SetExpectedNofPropertiesFromEstimate(result,
-                                         literal->expected_property_count());
-    live_edit_tracker.RecordFunctionInfo(result, literal, info.zone());
+    RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, &info);
   }
 
   return result;
@@ -1847,14 +1722,13 @@
   Handle<JSFunction> fun = Handle<JSFunction>::cast(Utils::OpenHandle(
       *fun_template->GetFunction(v8_isolate->GetCurrentContext())
            .ToLocalChecked()));
-  const int literals = fun->NumberOfLiterals();
   Handle<Code> code = Handle<Code>(fun->shared()->code());
   Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
   Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo(
-      name, literals, FunctionKind::kNormalFunction, code,
+      name, fun->shared()->num_literals(), FunctionKind::kNormalFunction, code,
       Handle<ScopeInfo>(fun->shared()->scope_info()));
   shared->set_construct_stub(*construct_stub);
-  shared->set_feedback_vector(fun->shared()->feedback_vector());
+  shared->set_feedback_metadata(fun->shared()->feedback_metadata());
 
   // Copy the function data to the shared function info.
   shared->set_function_data(fun->shared()->function_data());
@@ -1872,14 +1746,16 @@
   return GetOptimizedCode(function, NOT_CONCURRENT, osr_ast_id, osr_frame);
 }
 
-void Compiler::FinalizeOptimizedCompileJob(OptimizedCompileJob* job) {
-  // Take ownership of compilation info.  Deleting compilation info
-  // also tears down the zone and the recompile job.
-  base::SmartPointer<CompilationInfo> info(job->info());
+void Compiler::FinalizeCompilationJob(CompilationJob* raw_job) {
+  // Take ownership of compilation job.  Deleting job also tears down the zone.
+  base::SmartPointer<CompilationJob> job(raw_job);
+  CompilationInfo* info = job->info();
   Isolate* isolate = info->isolate();
 
   VMState<COMPILER> state(isolate);
   TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
+  RuntimeCallTimerScope runtimeTimer(isolate,
+                                     &RuntimeCallStats::RecompileSynchronous);
   TRACE_EVENT0("v8", "V8.RecompileSynchronous");
 
   Handle<SharedFunctionInfo> shared = info->shared_info();
@@ -1892,16 +1768,17 @@
   //    Except when OSR already disabled optimization for some reason.
   // 3) The code may have already been invalidated due to dependency change.
   // 4) Code generation may have failed.
-  if (job->last_status() == OptimizedCompileJob::SUCCEEDED) {
+  if (job->last_status() == CompilationJob::SUCCEEDED) {
     if (shared->optimization_disabled()) {
       job->RetryOptimization(kOptimizationDisabled);
     } else if (info->dependencies()->HasAborted()) {
       job->RetryOptimization(kBailedOutDueToDependencyChange);
-    } else if (job->GenerateCode() == OptimizedCompileJob::SUCCEEDED) {
-      RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info.get(), shared);
+    } else if (job->GenerateCode() == CompilationJob::SUCCEEDED) {
+      job->RecordOptimizationStats();
+      RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
       if (shared->SearchOptimizedCodeMap(info->context()->native_context(),
                                          info->osr_ast_id()).code == nullptr) {
-        InsertCodeIntoOptimizedCodeMap(info.get());
+        InsertCodeIntoOptimizedCodeMap(info);
       }
       if (FLAG_trace_opt) {
         PrintF("[completed optimizing ");
@@ -1913,7 +1790,7 @@
     }
   }
 
-  DCHECK(job->last_status() != OptimizedCompileJob::SUCCEEDED);
+  DCHECK(job->last_status() != CompilationJob::SUCCEEDED);
   if (FLAG_trace_opt) {
     PrintF("[aborted optimizing ");
     info->closure()->ShortPrint();
@@ -1940,21 +1817,11 @@
   }
 
   if (cached.literals != nullptr) {
+    DCHECK(shared->is_compiled());
     function->set_literals(cached.literals);
-  } else {
-    Isolate* isolate = function->GetIsolate();
-    int number_of_literals = shared->num_literals();
-    Handle<LiteralsArray> literals =
-        LiteralsArray::New(isolate, handle(shared->feedback_vector()),
-                           number_of_literals, pretenure);
-    function->set_literals(*literals);
-
-    // Cache context-specific literals.
-    MaybeHandle<Code> code;
-    if (cached.code != nullptr) code = handle(cached.code);
-    Handle<Context> native_context(function->context()->native_context());
-    SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code,
-                                              literals, BailoutId::None());
+  } else if (shared->is_compiled()) {
+    // TODO(mvstanton): pass pretenure flag to EnsureLiterals.
+    JSFunction::EnsureLiterals(function);
   }
 }
 
diff --git a/src/compiler.h b/src/compiler.h
index fa04399..e0ebd45 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -17,8 +17,8 @@
 
 // Forward declarations.
 class CompilationInfo;
+class CompilationJob;
 class JavaScriptFrame;
-class OptimizedCompileJob;
 class ParseInfo;
 class ScriptData;
 
@@ -44,13 +44,14 @@
   // given function holds (except for live-edit, which compiles the world).
 
   static bool Compile(Handle<JSFunction> function, ClearExceptionFlag flag);
+  static bool CompileBaseline(Handle<JSFunction> function);
   static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode);
   static bool CompileDebugCode(Handle<JSFunction> function);
   static bool CompileDebugCode(Handle<SharedFunctionInfo> shared);
-  static void CompileForLiveEdit(Handle<Script> script);
+  static MaybeHandle<JSArray> CompileForLiveEdit(Handle<Script> script);
 
-  // Generate and install code from previously queued optimization job.
-  static void FinalizeOptimizedCompileJob(OptimizedCompileJob* job);
+  // Generate and install code from previously queued compilation job.
+  static void FinalizeCompilationJob(CompilationJob* job);
 
   // Give the compiler a chance to perform low-latency initialization tasks of
   // the given {function} on its instantiation. Note that only the runtime will
@@ -77,7 +78,8 @@
   MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
       Handle<String> source, Handle<SharedFunctionInfo> outer_info,
       Handle<Context> context, LanguageMode language_mode,
-      ParseRestriction restriction, int line_offset, int column_offset = 0,
+      ParseRestriction restriction, int eval_scope_position, int eval_position,
+      int line_offset = 0, int column_offset = 0,
       Handle<Object> script_name = Handle<Object>(),
       ScriptOriginOptions options = ScriptOriginOptions());
 
@@ -118,26 +120,10 @@
       JavaScriptFrame* osr_frame);
 };
 
-struct InlinedFunctionInfo {
-  InlinedFunctionInfo(int parent_id, SourcePosition inline_position,
-                      int script_id, int start_position)
-      : parent_id(parent_id),
-        inline_position(inline_position),
-        script_id(script_id),
-        start_position(start_position) {}
-  int parent_id;
-  SourcePosition inline_position;
-  int script_id;
-  int start_position;
-  std::vector<size_t> deopt_pc_offsets;
-
-  static const int kNoParentId = -1;
-};
-
 
 // CompilationInfo encapsulates some information known at compile time.  It
 // is constructed based on the resources available at compile-time.
-class CompilationInfo {
+class CompilationInfo final {
  public:
   // Various configuration flags for a compilation, as well as some properties
   // of the compiled code produced by a compilation.
@@ -154,19 +140,19 @@
     kFrameSpecializing = 1 << 9,
     kNativeContextSpecializing = 1 << 10,
     kInliningEnabled = 1 << 11,
-    kTypingEnabled = 1 << 12,
-    kDisableFutureOptimization = 1 << 13,
-    kSplittingEnabled = 1 << 14,
-    kDeoptimizationEnabled = 1 << 16,
-    kSourcePositionsEnabled = 1 << 17,
-    kFirstCompile = 1 << 18,
-    kBailoutOnUninitialized = 1 << 19,
+    kDisableFutureOptimization = 1 << 12,
+    kSplittingEnabled = 1 << 13,
+    kDeoptimizationEnabled = 1 << 14,
+    kSourcePositionsEnabled = 1 << 15,
+    kBailoutOnUninitialized = 1 << 16,
+    kOptimizeFromBytecode = 1 << 17,
+    kTypeFeedbackEnabled = 1 << 18,
   };
 
-  explicit CompilationInfo(ParseInfo* parse_info);
-  CompilationInfo(const char* debug_name, Isolate* isolate, Zone* zone,
+  CompilationInfo(ParseInfo* parse_info, Handle<JSFunction> closure);
+  CompilationInfo(Vector<const char> debug_name, Isolate* isolate, Zone* zone,
                   Code::Flags code_flags = Code::ComputeFlags(Code::STUB));
-  virtual ~CompilationInfo();
+  ~CompilationInfo();
 
   ParseInfo* parse_info() const { return parse_info_; }
 
@@ -174,19 +160,11 @@
   // TODO(titzer): inline and delete accessors of ParseInfo
   // -----------------------------------------------------------
   Handle<Script> script() const;
-  bool is_eval() const;
-  bool is_native() const;
-  bool is_module() const;
-  LanguageMode language_mode() const;
-  Handle<JSFunction> closure() const;
   FunctionLiteral* literal() const;
   Scope* scope() const;
   Handle<Context> context() const;
   Handle<SharedFunctionInfo> shared_info() const;
   bool has_shared_info() const;
-  bool has_context() const;
-  bool has_literal() const;
-  bool has_scope() const;
   // -----------------------------------------------------------
 
   Isolate* isolate() const {
@@ -194,14 +172,14 @@
   }
   Zone* zone() { return zone_; }
   bool is_osr() const { return !osr_ast_id_.IsNone(); }
+  Handle<JSFunction> closure() const { return closure_; }
   Handle<Code> code() const { return code_; }
   Code::Flags code_flags() const { return code_flags_; }
   BailoutId osr_ast_id() const { return osr_ast_id_; }
-  int opt_count() const { return opt_count_; }
+  JavaScriptFrame* osr_frame() const { return osr_frame_; }
   int num_parameters() const;
   int num_parameters_including_this() const;
   bool is_this_defined() const;
-  int num_heap_slots() const;
 
   void set_parameter_count(int parameter_count) {
     DCHECK(IsStub());
@@ -211,11 +189,6 @@
   bool has_bytecode_array() const { return !bytecode_array_.is_null(); }
   Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; }
 
-  Handle<AbstractCode> abstract_code() const {
-    return has_bytecode_array() ? Handle<AbstractCode>::cast(bytecode_array())
-                                : Handle<AbstractCode>::cast(code());
-  }
-
   bool is_tracking_positions() const { return track_positions_; }
 
   bool is_calling() const {
@@ -284,6 +257,12 @@
     return GetFlag(kDeoptimizationEnabled);
   }
 
+  void MarkAsTypeFeedbackEnabled() { SetFlag(kTypeFeedbackEnabled); }
+
+  bool is_type_feedback_enabled() const {
+    return GetFlag(kTypeFeedbackEnabled);
+  }
+
   void MarkAsSourcePositionsEnabled() { SetFlag(kSourcePositionsEnabled); }
 
   bool is_source_positions_enabled() const {
@@ -294,26 +273,22 @@
 
   bool is_inlining_enabled() const { return GetFlag(kInliningEnabled); }
 
-  void MarkAsTypingEnabled() { SetFlag(kTypingEnabled); }
-
-  bool is_typing_enabled() const { return GetFlag(kTypingEnabled); }
-
   void MarkAsSplittingEnabled() { SetFlag(kSplittingEnabled); }
 
   bool is_splitting_enabled() const { return GetFlag(kSplittingEnabled); }
 
-  void MarkAsFirstCompile() { SetFlag(kFirstCompile); }
-
-  void MarkAsCompiled() { SetFlag(kFirstCompile, false); }
-
-  bool is_first_compile() const { return GetFlag(kFirstCompile); }
-
   void MarkAsBailoutOnUninitialized() { SetFlag(kBailoutOnUninitialized); }
 
   bool is_bailout_on_uninitialized() const {
     return GetFlag(kBailoutOnUninitialized);
   }
 
+  void MarkAsOptimizeFromBytecode() { SetFlag(kOptimizeFromBytecode); }
+
+  bool is_optimizing_from_bytecode() const {
+    return GetFlag(kOptimizeFromBytecode);
+  }
+
   bool GeneratePreagedPrologue() const {
     // Generate a pre-aged prologue if we are optimizing for size, which
     // will make code flushing more aggressive. Only apply to Code::FUNCTION,
@@ -357,9 +332,10 @@
     code_flags_ =
         Code::KindField::update(code_flags_, Code::OPTIMIZED_FUNCTION);
   }
-  void SetOptimizingForOsr(BailoutId osr_ast_id) {
+  void SetOptimizingForOsr(BailoutId osr_ast_id, JavaScriptFrame* osr_frame) {
     SetOptimizing();
     osr_ast_id_ = osr_ast_id;
+    osr_frame_ = osr_frame;
   }
 
   // Deoptimization support.
@@ -383,7 +359,7 @@
   }
 
   void ReopenHandlesInNewHandleScope() {
-    // Empty for now but will be needed once fields move from ParseInfo.
+    closure_ = Handle<JSFunction>(*closure_);
   }
 
   void AbortOptimization(BailoutReason reason) {
@@ -410,23 +386,8 @@
     prologue_offset_ = prologue_offset;
   }
 
-  int start_position_for(uint32_t inlining_id) {
-    return inlined_function_infos_.at(inlining_id).start_position;
-  }
-  const std::vector<InlinedFunctionInfo>& inlined_function_infos() {
-    return inlined_function_infos_;
-  }
-
-  void LogDeoptCallPosition(int pc_offset, int inlining_id);
-  int TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
-                           SourcePosition position, int pareint_id);
-
   CompilationDependencies* dependencies() { return &dependencies_; }
 
-  bool HasSameOsrEntry(Handle<JSFunction> function, BailoutId osr_ast_id) {
-    return osr_ast_id_ == osr_ast_id && function.is_identical_to(closure());
-  }
-
   int optimization_id() const { return optimization_id_; }
 
   int osr_expr_stack_height() { return osr_expr_stack_height_; }
@@ -434,8 +395,6 @@
     DCHECK(height >= 0);
     osr_expr_stack_height_ = height;
   }
-  JavaScriptFrame* osr_frame() const { return osr_frame_; }
-  void set_osr_frame(JavaScriptFrame* osr_frame) { osr_frame_ = osr_frame; }
 
 #if DEBUG
   void PrintAstForTesting();
@@ -474,6 +433,8 @@
 
   StackFrame::Type GetOutputStackFrameType() const;
 
+  int GetDeclareGlobalsFlags() const;
+
  protected:
   ParseInfo* parse_info_;
 
@@ -505,7 +466,7 @@
     STUB
   };
 
-  CompilationInfo(ParseInfo* parse_info, const char* debug_name,
+  CompilationInfo(ParseInfo* parse_info, Vector<const char> debug_name,
                   Code::Flags code_flags, Mode mode, Isolate* isolate,
                   Zone* zone);
 
@@ -527,6 +488,8 @@
 
   Code::Flags code_flags_;
 
+  Handle<JSFunction> closure_;
+
   // The compiled code.
   Handle<Code> code_;
 
@@ -552,15 +515,10 @@
 
   int prologue_offset_;
 
-  std::vector<InlinedFunctionInfo> inlined_function_infos_;
   bool track_positions_;
 
   InlinedFunctionList inlined_functions_;
 
-  // A copy of shared_info()->opt_count() to avoid handle deref
-  // during graph optimization.
-  int opt_count_;
-
   // Number of parameters used for compilation of stubs that require arguments.
   int parameter_count_;
 
@@ -571,29 +529,30 @@
   // The current OSR frame for specialization or {nullptr}.
   JavaScriptFrame* osr_frame_ = nullptr;
 
-  const char* debug_name_;
+  Vector<const char> debug_name_;
 
   DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
 };
 
-
-class HGraph;
-class LChunk;
-
-// A helper class that calls the three compilation phases in
-// Crankshaft and keeps track of its state.  The three phases
-// CreateGraph, OptimizeGraph and GenerateAndInstallCode can either
-// fail, bail-out to the full code generator or succeed.  Apart from
-// their return value, the status of the phase last run can be checked
-// using last_status().
-class OptimizedCompileJob: public ZoneObject {
+// A base class for compilation jobs intended to run concurrent to the main
+// thread. The job is split into three phases which are called in sequence on
+// different threads and with different limitations:
+//  1) CreateGraph:   Runs on main thread. No major limitations.
+//  2) OptimizeGraph: Runs concurrently. No heap allocation or handle derefs.
+//  3) GenerateCode:  Runs on main thread. No dependency changes.
+//
+// Each of the three phases can either fail or succeed. Apart from their return
+// value, the status of the phase last run can be checked using {last_status()}
+// as well. When failing we distinguish between the following levels:
+//  a) AbortOptimization: Persistent failure, disable future optimization.
+//  b) RetryOptimzation: Transient failure, try again next time.
+class CompilationJob {
  public:
-  explicit OptimizedCompileJob(CompilationInfo* info)
-      : info_(info), graph_(NULL), chunk_(NULL), last_status_(FAILED) {}
+  explicit CompilationJob(CompilationInfo* info, const char* compiler_name)
+      : info_(info), compiler_name_(compiler_name), last_status_(SUCCEEDED) {}
+  virtual ~CompilationJob() {}
 
-  enum Status {
-    FAILED, BAILED_OUT, SUCCEEDED
-  };
+  enum Status { FAILED, SUCCEEDED };
 
   MUST_USE_RESULT Status CreateGraph();
   MUST_USE_RESULT Status OptimizeGraph();
@@ -605,44 +564,36 @@
 
   Status RetryOptimization(BailoutReason reason) {
     info_->RetryOptimization(reason);
-    return SetLastStatus(BAILED_OUT);
+    return SetLastStatus(FAILED);
   }
 
   Status AbortOptimization(BailoutReason reason) {
     info_->AbortOptimization(reason);
-    return SetLastStatus(BAILED_OUT);
+    return SetLastStatus(FAILED);
   }
 
+  void RecordOptimizationStats();
+
+ protected:
+  void RegisterWeakObjectsInOptimizedCode(Handle<Code> code);
+
+  // Overridden by the actual implementation.
+  virtual Status CreateGraphImpl() = 0;
+  virtual Status OptimizeGraphImpl() = 0;
+  virtual Status GenerateCodeImpl() = 0;
+
  private:
   CompilationInfo* info_;
-  HGraph* graph_;
-  LChunk* chunk_;
   base::TimeDelta time_taken_to_create_graph_;
   base::TimeDelta time_taken_to_optimize_;
   base::TimeDelta time_taken_to_codegen_;
+  const char* compiler_name_;
   Status last_status_;
 
   MUST_USE_RESULT Status SetLastStatus(Status status) {
     last_status_ = status;
     return last_status_;
   }
-  void RecordOptimizationStats();
-
-  struct Timer {
-    Timer(OptimizedCompileJob* job, base::TimeDelta* location)
-        : job_(job), location_(location) {
-      DCHECK(location_ != NULL);
-      timer_.Start();
-    }
-
-    ~Timer() {
-      *location_ += timer_.Elapsed();
-    }
-
-    OptimizedCompileJob* job_;
-    base::ElapsedTimer timer_;
-    base::TimeDelta* location_;
-  };
 };
 
 }  // namespace internal
diff --git a/src/compiler/OWNERS b/src/compiler/OWNERS
index 1257e23..02de4ed 100644
--- a/src/compiler/OWNERS
+++ b/src/compiler/OWNERS
@@ -1,6 +1,7 @@
 set noparent
 
 bmeurer@chromium.org
+epertoso@chromium.org
 jarin@chromium.org
 mstarzinger@chromium.org
 mtrofin@chromium.org
diff --git a/src/compiler/access-builder.cc b/src/compiler/access-builder.cc
index 722bbf0..0eac109 100644
--- a/src/compiler/access-builder.cc
+++ b/src/compiler/access-builder.cc
@@ -16,36 +16,39 @@
 
 // static
 FieldAccess AccessBuilder::ForMap() {
-  FieldAccess access = {kTaggedBase, HeapObject::kMapOffset,
-                        MaybeHandle<Name>(), Type::Any(),
-                        MachineType::AnyTagged()};
+  FieldAccess access = {
+      kTaggedBase, HeapObject::kMapOffset,   MaybeHandle<Name>(),
+      Type::Any(), MachineType::AnyTagged(), kMapWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForHeapNumberValue() {
-  FieldAccess access = {kTaggedBase, HeapNumber::kValueOffset,
-                        MaybeHandle<Name>(), TypeCache().Get().kFloat64,
-                        MachineType::Float64()};
+  FieldAccess access = {kTaggedBase,
+                        HeapNumber::kValueOffset,
+                        MaybeHandle<Name>(),
+                        TypeCache::Get().kFloat64,
+                        MachineType::Float64(),
+                        kNoWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForJSObjectProperties() {
-  FieldAccess access = {kTaggedBase, JSObject::kPropertiesOffset,
-                        MaybeHandle<Name>(), Type::Internal(),
-                        MachineType::AnyTagged()};
+  FieldAccess access = {
+      kTaggedBase,      JSObject::kPropertiesOffset, MaybeHandle<Name>(),
+      Type::Internal(), MachineType::AnyTagged(),    kPointerWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForJSObjectElements() {
-  FieldAccess access = {kTaggedBase, JSObject::kElementsOffset,
-                        MaybeHandle<Name>(), Type::Internal(),
-                        MachineType::AnyTagged()};
+  FieldAccess access = {
+      kTaggedBase,      JSObject::kElementsOffset, MaybeHandle<Name>(),
+      Type::Internal(), MachineType::AnyTagged(),  kPointerWriteBarrier};
   return access;
 }
 
@@ -54,39 +57,149 @@
 FieldAccess AccessBuilder::ForJSObjectInObjectProperty(Handle<Map> map,
                                                        int index) {
   int const offset = map->GetInObjectPropertyOffset(index);
-  FieldAccess access = {kTaggedBase, offset, MaybeHandle<Name>(),
-                        Type::Tagged(), MachineType::AnyTagged()};
+  FieldAccess access = {kTaggedBase,
+                        offset,
+                        MaybeHandle<Name>(),
+                        Type::Tagged(),
+                        MachineType::AnyTagged(),
+                        kFullWriteBarrier};
   return access;
 }
 
 
 // static
+FieldAccess AccessBuilder::ForJSFunctionPrototypeOrInitialMap() {
+  FieldAccess access = {kTaggedBase,
+                        JSFunction::kPrototypeOrInitialMapOffset,
+                        MaybeHandle<Name>(),
+                        Type::Any(),
+                        MachineType::AnyTagged(),
+                        kFullWriteBarrier};
+  return access;
+}
+
+// static
 FieldAccess AccessBuilder::ForJSFunctionContext() {
-  FieldAccess access = {kTaggedBase, JSFunction::kContextOffset,
-                        MaybeHandle<Name>(), Type::Internal(),
-                        MachineType::AnyTagged()};
+  FieldAccess access = {
+      kTaggedBase,      JSFunction::kContextOffset, MaybeHandle<Name>(),
+      Type::Internal(), MachineType::AnyTagged(),   kPointerWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForJSFunctionSharedFunctionInfo() {
-  FieldAccess access = {kTaggedBase, JSFunction::kSharedFunctionInfoOffset,
-                        Handle<Name>(), Type::Any(), MachineType::AnyTagged()};
+  FieldAccess access = {kTaggedBase,
+                        JSFunction::kSharedFunctionInfoOffset,
+                        Handle<Name>(),
+                        Type::Any(),
+                        MachineType::AnyTagged(),
+                        kPointerWriteBarrier};
   return access;
 }
 
+// static
+FieldAccess AccessBuilder::ForJSFunctionLiterals() {
+  FieldAccess access = {
+      kTaggedBase,      JSFunction::kLiteralsOffset, Handle<Name>(),
+      Type::Internal(), MachineType::AnyTagged(),    kPointerWriteBarrier};
+  return access;
+}
+
+// static
+FieldAccess AccessBuilder::ForJSFunctionCodeEntry() {
+  FieldAccess access = {kTaggedBase,
+                        JSFunction::kCodeEntryOffset,
+                        Handle<Name>(),
+                        Type::UntaggedPointer(),
+                        MachineType::Pointer(),
+                        kNoWriteBarrier};
+  return access;
+}
+
+// static
+FieldAccess AccessBuilder::ForJSFunctionNextFunctionLink() {
+  FieldAccess access = {kTaggedBase,
+                        JSFunction::kNextFunctionLinkOffset,
+                        Handle<Name>(),
+                        Type::Any(),
+                        MachineType::AnyTagged(),
+                        kPointerWriteBarrier};
+  return access;
+}
+
+// static
+FieldAccess AccessBuilder::ForJSGeneratorObjectContext() {
+  FieldAccess access = {kTaggedBase,
+                        JSGeneratorObject::kContextOffset,
+                        Handle<Name>(),
+                        Type::Internal(),
+                        MachineType::AnyTagged(),
+                        kPointerWriteBarrier};
+  return access;
+}
+
+// static
+FieldAccess AccessBuilder::ForJSGeneratorObjectContinuation() {
+  TypeCache const& type_cache = TypeCache::Get();
+  FieldAccess access = {kTaggedBase,
+                        JSGeneratorObject::kContinuationOffset,
+                        Handle<Name>(),
+                        type_cache.kSmi,
+                        MachineType::AnyTagged(),
+                        kNoWriteBarrier};
+  return access;
+}
+
+// static
+FieldAccess AccessBuilder::ForJSGeneratorObjectInputOrDebugPos() {
+  FieldAccess access = {kTaggedBase,
+                        JSGeneratorObject::kInputOrDebugPosOffset,
+                        Handle<Name>(),
+                        Type::Any(),
+                        MachineType::AnyTagged(),
+                        kFullWriteBarrier};
+  return access;
+}
+
+// static
+FieldAccess AccessBuilder::ForJSGeneratorObjectOperandStack() {
+  FieldAccess access = {kTaggedBase,
+                        JSGeneratorObject::kOperandStackOffset,
+                        Handle<Name>(),
+                        Type::Internal(),
+                        MachineType::AnyTagged(),
+                        kPointerWriteBarrier};
+  return access;
+}
+
+// static
+FieldAccess AccessBuilder::ForJSGeneratorObjectResumeMode() {
+  TypeCache const& type_cache = TypeCache::Get();
+  FieldAccess access = {kTaggedBase,
+                        JSGeneratorObject::kResumeModeOffset,
+                        Handle<Name>(),
+                        type_cache.kSmi,
+                        MachineType::AnyTagged(),
+                        kNoWriteBarrier};
+  return access;
+}
 
 // static
 FieldAccess AccessBuilder::ForJSArrayLength(ElementsKind elements_kind) {
   TypeCache const& type_cache = TypeCache::Get();
-  FieldAccess access = {kTaggedBase, JSArray::kLengthOffset, Handle<Name>(),
+  FieldAccess access = {kTaggedBase,
+                        JSArray::kLengthOffset,
+                        Handle<Name>(),
                         type_cache.kJSArrayLengthType,
-                        MachineType::AnyTagged()};
+                        MachineType::AnyTagged(),
+                        kFullWriteBarrier};
   if (IsFastDoubleElementsKind(elements_kind)) {
     access.type = type_cache.kFixedDoubleArrayLengthType;
+    access.write_barrier_kind = kNoWriteBarrier;
   } else if (IsFastElementsKind(elements_kind)) {
     access.type = type_cache.kFixedArrayLengthType;
+    access.write_barrier_kind = kNoWriteBarrier;
   }
   return access;
 }
@@ -94,190 +207,236 @@
 
 // static
 FieldAccess AccessBuilder::ForJSArrayBufferBackingStore() {
-  FieldAccess access = {kTaggedBase, JSArrayBuffer::kBackingStoreOffset,
-                        MaybeHandle<Name>(), Type::UntaggedPointer(),
-                        MachineType::Pointer()};
+  FieldAccess access = {kTaggedBase,
+                        JSArrayBuffer::kBackingStoreOffset,
+                        MaybeHandle<Name>(),
+                        Type::UntaggedPointer(),
+                        MachineType::Pointer(),
+                        kNoWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForJSArrayBufferBitField() {
-  FieldAccess access = {kTaggedBase, JSArrayBuffer::kBitFieldOffset,
+  FieldAccess access = {kTaggedBase,         JSArrayBuffer::kBitFieldOffset,
                         MaybeHandle<Name>(), TypeCache::Get().kInt8,
-                        MachineType::Int8()};
+                        MachineType::Int8(), kNoWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForJSArrayBufferViewBuffer() {
-  FieldAccess access = {kTaggedBase, JSArrayBufferView::kBufferOffset,
-                        MaybeHandle<Name>(), Type::TaggedPointer(),
-                        MachineType::AnyTagged()};
+  FieldAccess access = {kTaggedBase,
+                        JSArrayBufferView::kBufferOffset,
+                        MaybeHandle<Name>(),
+                        Type::TaggedPointer(),
+                        MachineType::AnyTagged(),
+                        kPointerWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForJSDateField(JSDate::FieldIndex index) {
-  FieldAccess access = {
-      kTaggedBase, JSDate::kValueOffset + index * kPointerSize,
-      MaybeHandle<Name>(), Type::Number(), MachineType::AnyTagged()};
+  FieldAccess access = {kTaggedBase,
+                        JSDate::kValueOffset + index * kPointerSize,
+                        MaybeHandle<Name>(),
+                        Type::Number(),
+                        MachineType::AnyTagged(),
+                        kFullWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForJSIteratorResultDone() {
-  FieldAccess access = {kTaggedBase, JSIteratorResult::kDoneOffset,
-                        MaybeHandle<Name>(), Type::Any(),
-                        MachineType::AnyTagged()};
+  FieldAccess access = {
+      kTaggedBase, JSIteratorResult::kDoneOffset, MaybeHandle<Name>(),
+      Type::Any(), MachineType::AnyTagged(),      kFullWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForJSIteratorResultValue() {
-  FieldAccess access = {kTaggedBase, JSIteratorResult::kValueOffset,
-                        MaybeHandle<Name>(), Type::Any(),
-                        MachineType::AnyTagged()};
+  FieldAccess access = {
+      kTaggedBase, JSIteratorResult::kValueOffset, MaybeHandle<Name>(),
+      Type::Any(), MachineType::AnyTagged(),       kFullWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForJSRegExpFlags() {
-  FieldAccess access = {kTaggedBase, JSRegExp::kFlagsOffset,
-                        MaybeHandle<Name>(), Type::Tagged(),
-                        MachineType::AnyTagged()};
+  FieldAccess access = {
+      kTaggedBase,    JSRegExp::kFlagsOffset,   MaybeHandle<Name>(),
+      Type::Tagged(), MachineType::AnyTagged(), kFullWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForJSRegExpSource() {
-  FieldAccess access = {kTaggedBase, JSRegExp::kSourceOffset,
-                        MaybeHandle<Name>(), Type::Tagged(),
-                        MachineType::AnyTagged()};
+  FieldAccess access = {
+      kTaggedBase,    JSRegExp::kSourceOffset,  MaybeHandle<Name>(),
+      Type::Tagged(), MachineType::AnyTagged(), kFullWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForFixedArrayLength() {
-  FieldAccess access = {
-      kTaggedBase, FixedArray::kLengthOffset, MaybeHandle<Name>(),
-      TypeCache::Get().kFixedArrayLengthType, MachineType::AnyTagged()};
+  FieldAccess access = {kTaggedBase,
+                        FixedArray::kLengthOffset,
+                        MaybeHandle<Name>(),
+                        TypeCache::Get().kFixedArrayLengthType,
+                        MachineType::AnyTagged(),
+                        kNoWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForDescriptorArrayEnumCache() {
-  FieldAccess access = {kTaggedBase, DescriptorArray::kEnumCacheOffset,
-                        Handle<Name>(), Type::TaggedPointer(),
-                        MachineType::AnyTagged()};
+  FieldAccess access = {kTaggedBase,
+                        DescriptorArray::kEnumCacheOffset,
+                        Handle<Name>(),
+                        Type::TaggedPointer(),
+                        MachineType::AnyTagged(),
+                        kPointerWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForDescriptorArrayEnumCacheBridgeCache() {
-  FieldAccess access = {
-      kTaggedBase, DescriptorArray::kEnumCacheBridgeCacheOffset, Handle<Name>(),
-      Type::TaggedPointer(), MachineType::AnyTagged()};
+  FieldAccess access = {kTaggedBase,
+                        DescriptorArray::kEnumCacheBridgeCacheOffset,
+                        Handle<Name>(),
+                        Type::TaggedPointer(),
+                        MachineType::AnyTagged(),
+                        kPointerWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForMapBitField() {
-  FieldAccess access = {kTaggedBase, Map::kBitFieldOffset, Handle<Name>(),
-                        TypeCache::Get().kUint8, MachineType::Uint8()};
+  FieldAccess access = {kTaggedBase,          Map::kBitFieldOffset,
+                        Handle<Name>(),       TypeCache::Get().kUint8,
+                        MachineType::Uint8(), kNoWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForMapBitField3() {
-  FieldAccess access = {kTaggedBase, Map::kBitField3Offset, Handle<Name>(),
-                        TypeCache::Get().kInt32, MachineType::Int32()};
+  FieldAccess access = {kTaggedBase,          Map::kBitField3Offset,
+                        Handle<Name>(),       TypeCache::Get().kInt32,
+                        MachineType::Int32(), kNoWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForMapDescriptors() {
-  FieldAccess access = {kTaggedBase, Map::kDescriptorsOffset, Handle<Name>(),
-                        Type::TaggedPointer(), MachineType::AnyTagged()};
+  FieldAccess access = {
+      kTaggedBase,           Map::kDescriptorsOffset,  Handle<Name>(),
+      Type::TaggedPointer(), MachineType::AnyTagged(), kPointerWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForMapInstanceType() {
-  FieldAccess access = {kTaggedBase, Map::kInstanceTypeOffset, Handle<Name>(),
-                        TypeCache::Get().kUint8, MachineType::Uint8()};
+  FieldAccess access = {kTaggedBase,          Map::kInstanceTypeOffset,
+                        Handle<Name>(),       TypeCache::Get().kUint8,
+                        MachineType::Uint8(), kNoWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForMapPrototype() {
-  FieldAccess access = {kTaggedBase, Map::kPrototypeOffset, Handle<Name>(),
-                        Type::TaggedPointer(), MachineType::AnyTagged()};
+  FieldAccess access = {
+      kTaggedBase,           Map::kPrototypeOffset,    Handle<Name>(),
+      Type::TaggedPointer(), MachineType::AnyTagged(), kPointerWriteBarrier};
   return access;
 }
 
 
 // static
+FieldAccess AccessBuilder::ForNameHashField() {
+  FieldAccess access = {kTaggedBase,           Name::kHashFieldOffset,
+                        Handle<Name>(),        Type::Internal(),
+                        MachineType::Uint32(), kNoWriteBarrier};
+  return access;
+}
+
+// static
 FieldAccess AccessBuilder::ForStringLength() {
-  FieldAccess access = {kTaggedBase, String::kLengthOffset, Handle<Name>(),
+  FieldAccess access = {kTaggedBase,
+                        String::kLengthOffset,
+                        Handle<Name>(),
                         TypeCache::Get().kStringLengthType,
-                        MachineType::AnyTagged()};
+                        MachineType::AnyTagged(),
+                        kNoWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForJSGlobalObjectGlobalProxy() {
-  FieldAccess access = {kTaggedBase, JSGlobalObject::kGlobalProxyOffset,
-                        Handle<Name>(), Type::Receiver(),
-                        MachineType::AnyTagged()};
+  FieldAccess access = {kTaggedBase,
+                        JSGlobalObject::kGlobalProxyOffset,
+                        Handle<Name>(),
+                        Type::Receiver(),
+                        MachineType::AnyTagged(),
+                        kPointerWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForJSGlobalObjectNativeContext() {
-  FieldAccess access = {kTaggedBase, JSGlobalObject::kNativeContextOffset,
-                        Handle<Name>(), Type::Internal(),
-                        MachineType::AnyTagged()};
+  FieldAccess access = {kTaggedBase,
+                        JSGlobalObject::kNativeContextOffset,
+                        Handle<Name>(),
+                        Type::Internal(),
+                        MachineType::AnyTagged(),
+                        kPointerWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForValue() {
-  FieldAccess access = {kTaggedBase, JSValue::kValueOffset, Handle<Name>(),
-                        Type::Any(), MachineType::AnyTagged()};
+  FieldAccess access = {
+      kTaggedBase, JSValue::kValueOffset,    Handle<Name>(),
+      Type::Any(), MachineType::AnyTagged(), kFullWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForArgumentsLength() {
-  FieldAccess access = {kTaggedBase, JSArgumentsObject::kLengthOffset,
-                        Handle<Name>(), Type::Any(), MachineType::AnyTagged()};
+  FieldAccess access = {
+      kTaggedBase, JSArgumentsObject::kLengthOffset, Handle<Name>(),
+      Type::Any(), MachineType::AnyTagged(),         kFullWriteBarrier};
   return access;
 }
 
 
 // static
 FieldAccess AccessBuilder::ForArgumentsCallee() {
-  FieldAccess access = {kTaggedBase, JSSloppyArgumentsObject::kCalleeOffset,
-                        Handle<Name>(), Type::Any(), MachineType::AnyTagged()};
+  FieldAccess access = {kTaggedBase,
+                        JSSloppyArgumentsObject::kCalleeOffset,
+                        Handle<Name>(),
+                        Type::Any(),
+                        MachineType::AnyTagged(),
+                        kPointerWriteBarrier};
   return access;
 }
 
@@ -285,8 +444,12 @@
 // static
 FieldAccess AccessBuilder::ForFixedArraySlot(size_t index) {
   int offset = FixedArray::OffsetOfElementAt(static_cast<int>(index));
-  FieldAccess access = {kTaggedBase, offset, Handle<Name>(), Type::Any(),
-                        MachineType::AnyTagged()};
+  FieldAccess access = {kTaggedBase,
+                        offset,
+                        Handle<Name>(),
+                        Type::Any(),
+                        MachineType::AnyTagged(),
+                        kFullWriteBarrier};
   return access;
 }
 
@@ -296,8 +459,12 @@
   int offset = Context::kHeaderSize + static_cast<int>(index) * kPointerSize;
   DCHECK_EQ(offset,
             Context::SlotOffset(static_cast<int>(index)) + kHeapObjectTag);
-  FieldAccess access = {kTaggedBase, offset, Handle<Name>(), Type::Any(),
-                        MachineType::AnyTagged()};
+  FieldAccess access = {kTaggedBase,
+                        offset,
+                        Handle<Name>(),
+                        Type::Any(),
+                        MachineType::AnyTagged(),
+                        kFullWriteBarrier};
   return access;
 }
 
@@ -310,24 +477,16 @@
 
 // static
 FieldAccess AccessBuilder::ForPropertyCellValue(Type* type) {
-  FieldAccess access = {kTaggedBase, PropertyCell::kValueOffset, Handle<Name>(),
-                        type, MachineType::AnyTagged()};
+  FieldAccess access = {
+      kTaggedBase, PropertyCell::kValueOffset, Handle<Name>(),
+      type,        MachineType::AnyTagged(),   kFullWriteBarrier};
   return access;
 }
 
-
-// static
-FieldAccess AccessBuilder::ForSharedFunctionInfoTypeFeedbackVector() {
-  FieldAccess access = {kTaggedBase, SharedFunctionInfo::kFeedbackVectorOffset,
-                        Handle<Name>(), Type::Any(), MachineType::AnyTagged()};
-  return access;
-}
-
-
 // static
 ElementAccess AccessBuilder::ForFixedArrayElement() {
   ElementAccess access = {kTaggedBase, FixedArray::kHeaderSize, Type::Tagged(),
-                          MachineType::AnyTagged()};
+                          MachineType::AnyTagged(), kFullWriteBarrier};
   return access;
 }
 
@@ -335,7 +494,8 @@
 // static
 ElementAccess AccessBuilder::ForFixedDoubleArrayElement() {
   ElementAccess access = {kTaggedBase, FixedDoubleArray::kHeaderSize,
-                          TypeCache::Get().kFloat64, MachineType::Float64()};
+                          TypeCache::Get().kFloat64, MachineType::Float64(),
+                          kNoWriteBarrier};
   return access;
 }
 
@@ -348,56 +508,49 @@
   switch (type) {
     case kExternalInt8Array: {
       ElementAccess access = {taggedness, header_size, Type::Signed32(),
-                              MachineType::Int8()};
+                              MachineType::Int8(), kNoWriteBarrier};
       return access;
     }
     case kExternalUint8Array:
     case kExternalUint8ClampedArray: {
       ElementAccess access = {taggedness, header_size, Type::Unsigned32(),
-                              MachineType::Uint8()};
+                              MachineType::Uint8(), kNoWriteBarrier};
       return access;
     }
     case kExternalInt16Array: {
       ElementAccess access = {taggedness, header_size, Type::Signed32(),
-                              MachineType::Int16()};
+                              MachineType::Int16(), kNoWriteBarrier};
       return access;
     }
     case kExternalUint16Array: {
       ElementAccess access = {taggedness, header_size, Type::Unsigned32(),
-                              MachineType::Uint16()};
+                              MachineType::Uint16(), kNoWriteBarrier};
       return access;
     }
     case kExternalInt32Array: {
       ElementAccess access = {taggedness, header_size, Type::Signed32(),
-                              MachineType::Int32()};
+                              MachineType::Int32(), kNoWriteBarrier};
       return access;
     }
     case kExternalUint32Array: {
       ElementAccess access = {taggedness, header_size, Type::Unsigned32(),
-                              MachineType::Uint32()};
+                              MachineType::Uint32(), kNoWriteBarrier};
       return access;
     }
     case kExternalFloat32Array: {
       ElementAccess access = {taggedness, header_size, Type::Number(),
-                              MachineType::Float32()};
+                              MachineType::Float32(), kNoWriteBarrier};
       return access;
     }
     case kExternalFloat64Array: {
       ElementAccess access = {taggedness, header_size, Type::Number(),
-                              MachineType::Float64()};
+                              MachineType::Float64(), kNoWriteBarrier};
       return access;
     }
   }
   UNREACHABLE();
-  ElementAccess access = {kUntaggedBase, 0, Type::None(), MachineType::None()};
-  return access;
-}
-
-
-// static
-FieldAccess AccessBuilder::ForStatsCounter() {
-  FieldAccess access = {kUntaggedBase, 0, MaybeHandle<Name>(),
-                        TypeCache::Get().kInt32, MachineType::Int32()};
+  ElementAccess access = {kUntaggedBase, 0, Type::None(), MachineType::None(),
+                          kNoWriteBarrier};
   return access;
 }
 
diff --git a/src/compiler/access-builder.h b/src/compiler/access-builder.h
index 8375d37..8345225 100644
--- a/src/compiler/access-builder.h
+++ b/src/compiler/access-builder.h
@@ -34,12 +34,39 @@
   // Provides access to JSObject inobject property fields.
   static FieldAccess ForJSObjectInObjectProperty(Handle<Map> map, int index);
 
+  // Provides access to JSFunction::prototype_or_initial_map() field.
+  static FieldAccess ForJSFunctionPrototypeOrInitialMap();
+
   // Provides access to JSFunction::context() field.
   static FieldAccess ForJSFunctionContext();
 
   // Provides access to JSFunction::shared() field.
   static FieldAccess ForJSFunctionSharedFunctionInfo();
 
+  // Provides access to JSFunction::literals() field.
+  static FieldAccess ForJSFunctionLiterals();
+
+  // Provides access to JSFunction::code() field.
+  static FieldAccess ForJSFunctionCodeEntry();
+
+  // Provides access to JSFunction::next_function_link() field.
+  static FieldAccess ForJSFunctionNextFunctionLink();
+
+  // Provides access to JSGeneratorObject::context() field.
+  static FieldAccess ForJSGeneratorObjectContext();
+
+  // Provides access to JSGeneratorObject::continuation() field.
+  static FieldAccess ForJSGeneratorObjectContinuation();
+
+  // Provides access to JSGeneratorObject::input_or_debug_pos() field.
+  static FieldAccess ForJSGeneratorObjectInputOrDebugPos();
+
+  // Provides access to JSGeneratorObject::operand_stack() field.
+  static FieldAccess ForJSGeneratorObjectOperandStack();
+
+  // Provides access to JSGeneratorObject::resume_mode() field.
+  static FieldAccess ForJSGeneratorObjectResumeMode();
+
   // Provides access to JSArray::length() field.
   static FieldAccess ForJSArrayLength(ElementsKind elements_kind);
 
@@ -91,6 +118,9 @@
   // Provides access to Map::prototype() field.
   static FieldAccess ForMapPrototype();
 
+  // Provides access to Name::hash_field() field.
+  static FieldAccess ForNameHashField();
+
   // Provides access to String::length() field.
   static FieldAccess ForStringLength();
 
@@ -117,9 +147,6 @@
   static FieldAccess ForPropertyCellValue();
   static FieldAccess ForPropertyCellValue(Type* type);
 
-  // Provides access to SharedFunctionInfo::feedback_vector() field.
-  static FieldAccess ForSharedFunctionInfoTypeFeedbackVector();
-
   // Provides access to FixedArray elements.
   static ElementAccess ForFixedArrayElement();
 
@@ -130,12 +157,6 @@
   static ElementAccess ForTypedArrayElement(ExternalArrayType type,
                                             bool is_external);
 
-  // ===========================================================================
-  // Access to global per-isolate variables (based on external reference).
-
-  // Provides access to the backing store of a StatsCounter.
-  static FieldAccess ForStatsCounter();
-
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(AccessBuilder);
 };
diff --git a/src/compiler/access-info.cc b/src/compiler/access-info.cc
index 4a2a857..768b985 100644
--- a/src/compiler/access-info.cc
+++ b/src/compiler/access-info.cc
@@ -9,7 +9,7 @@
 #include "src/compiler/access-info.h"
 #include "src/field-index-inl.h"
 #include "src/field-type.h"
-#include "src/objects-inl.h"  // TODO(mstarzinger): Temporary cycle breaker!
+#include "src/objects-inl.h"
 #include "src/type-cache.h"
 
 namespace v8 {
@@ -75,10 +75,9 @@
 // static
 PropertyAccessInfo PropertyAccessInfo::DataField(
     Type* receiver_type, FieldIndex field_index, Type* field_type,
-    FieldCheck field_check, MaybeHandle<JSObject> holder,
-    MaybeHandle<Map> transition_map) {
-  return PropertyAccessInfo(holder, transition_map, field_index, field_check,
-                            field_type, receiver_type);
+    MaybeHandle<JSObject> holder, MaybeHandle<Map> transition_map) {
+  return PropertyAccessInfo(holder, transition_map, field_index, field_type,
+                            receiver_type);
 }
 
 
@@ -114,21 +113,17 @@
       holder_(holder),
       field_type_(Type::Any()) {}
 
-
 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder,
                                        MaybeHandle<Map> transition_map,
-                                       FieldIndex field_index,
-                                       FieldCheck field_check, Type* field_type,
+                                       FieldIndex field_index, Type* field_type,
                                        Type* receiver_type)
     : kind_(kDataField),
       receiver_type_(receiver_type),
       transition_map_(transition_map),
       holder_(holder),
       field_index_(field_index),
-      field_check_(field_check),
       field_type_(field_type) {}
 
-
 AccessInfoFactory::AccessInfoFactory(CompilationDependencies* dependencies,
                                      Handle<Context> native_context, Zone* zone)
     : dependencies_(dependencies),
@@ -192,12 +187,12 @@
   MapTransitionList transitions(maps.length());
   for (Handle<Map> map : maps) {
     if (Map::TryUpdate(map).ToHandle(&map)) {
-      Handle<Map> transition_target =
-          Map::FindTransitionedMap(map, &possible_transition_targets);
-      if (transition_target.is_null()) {
+      Map* transition_target =
+          map->FindElementsKindTransitionedMap(&possible_transition_targets);
+      if (transition_target == nullptr) {
         receiver_maps.Add(map);
       } else {
-        transitions.push_back(std::make_pair(map, transition_target));
+        transitions.push_back(std::make_pair(map, handle(transition_target)));
       }
     }
   }
@@ -299,8 +294,7 @@
           DCHECK(field_type->Is(Type::TaggedPointer()));
         }
         *access_info = PropertyAccessInfo::DataField(
-            Type::Class(receiver_map, zone()), field_index, field_type,
-            FieldCheck::kNone, holder);
+            Type::Class(receiver_map, zone()), field_index, field_type, holder);
         return true;
       } else {
         // TODO(bmeurer): Add support for accessors.
@@ -327,7 +321,7 @@
               .ToHandle(&constructor)) {
         map = handle(constructor->initial_map(), isolate());
         DCHECK(map->prototype()->IsJSObject());
-      } else if (map->prototype()->IsNull()) {
+      } else if (map->prototype()->IsNull(isolate())) {
         // Store to property not found on the receiver or any prototype, we need
         // to transition to a new data property.
         // Implemented according to ES6 section 9.1.9 [[Set]] (P, V, Receiver)
@@ -404,26 +398,6 @@
                                                  field_index, field_type);
     return true;
   }
-  // Check for special JSArrayBufferView field accessors.
-  if (Accessors::IsJSArrayBufferViewFieldAccessor(map, name, &offset)) {
-    FieldIndex field_index = FieldIndex::ForInObjectOffset(offset);
-    Type* field_type = Type::Tagged();
-    if (Name::Equals(factory()->byte_length_string(), name) ||
-        Name::Equals(factory()->byte_offset_string(), name)) {
-      // The JSArrayBufferView::byte_length and JSArrayBufferView::byte_offset
-      // properties are always numbers in the range [0, kMaxSafeInteger].
-      field_type = type_cache_.kPositiveSafeInteger;
-    } else if (map->IsJSTypedArrayMap()) {
-      DCHECK(Name::Equals(factory()->length_string(), name));
-      // The JSTypedArray::length property is always a number in the range
-      // [0, kMaxSafeInteger].
-      field_type = type_cache_.kPositiveSafeInteger;
-    }
-    *access_info = PropertyAccessInfo::DataField(
-        Type::Class(map, zone()), field_index, field_type,
-        FieldCheck::kJSArrayBufferViewBufferNotNeutered);
-    return true;
-  }
   return false;
 }
 
@@ -471,9 +445,9 @@
       DCHECK(field_type->Is(Type::TaggedPointer()));
     }
     dependencies()->AssumeMapNotDeprecated(transition_map);
-    *access_info = PropertyAccessInfo::DataField(
-        Type::Class(map, zone()), field_index, field_type, FieldCheck::kNone,
-        holder, transition_map);
+    *access_info =
+        PropertyAccessInfo::DataField(Type::Class(map, zone()), field_index,
+                                      field_type, holder, transition_map);
     return true;
   }
   return false;
diff --git a/src/compiler/access-info.h b/src/compiler/access-info.h
index cae1191..1556e0e 100644
--- a/src/compiler/access-info.h
+++ b/src/compiler/access-info.h
@@ -53,16 +53,6 @@
 };
 
 
-// Additional checks that need to be perform for data field accesses.
-enum class FieldCheck : uint8_t {
-  // No additional checking needed.
-  kNone,
-  // Check that the [[ViewedArrayBuffer]] of {JSArrayBufferView}s
-  // was not neutered.
-  kJSArrayBufferViewBufferNotNeutered,
-};
-
-
 // This class encapsulates all information required to access a certain
 // object property, either on the object itself or on the prototype chain.
 class PropertyAccessInfo final {
@@ -76,7 +66,6 @@
                                          MaybeHandle<JSObject> holder);
   static PropertyAccessInfo DataField(
       Type* receiver_type, FieldIndex field_index, Type* field_type,
-      FieldCheck field_check = FieldCheck::kNone,
       MaybeHandle<JSObject> holder = MaybeHandle<JSObject>(),
       MaybeHandle<Map> transition_map = MaybeHandle<Map>());
 
@@ -92,7 +81,6 @@
   MaybeHandle<JSObject> holder() const { return holder_; }
   MaybeHandle<Map> transition_map() const { return transition_map_; }
   Handle<Object> constant() const { return constant_; }
-  FieldCheck field_check() const { return field_check_; }
   FieldIndex field_index() const { return field_index_; }
   Type* field_type() const { return field_type_; }
   Type* receiver_type() const { return receiver_type_; }
@@ -103,8 +91,7 @@
                      Type* receiver_type);
   PropertyAccessInfo(MaybeHandle<JSObject> holder,
                      MaybeHandle<Map> transition_map, FieldIndex field_index,
-                     FieldCheck field_check, Type* field_type,
-                     Type* receiver_type);
+                     Type* field_type, Type* receiver_type);
 
   Kind kind_;
   Type* receiver_type_;
@@ -112,7 +99,6 @@
   MaybeHandle<Map> transition_map_;
   MaybeHandle<JSObject> holder_;
   FieldIndex field_index_;
-  FieldCheck field_check_;
   Type* field_type_;
 };
 
diff --git a/src/compiler/arm/code-generator-arm.cc b/src/compiler/arm/code-generator-arm.cc
index a0b5022..e1cf2a6 100644
--- a/src/compiler/arm/code-generator-arm.cc
+++ b/src/compiler/arm/code-generator-arm.cc
@@ -27,30 +27,6 @@
   ArmOperandConverter(CodeGenerator* gen, Instruction* instr)
       : InstructionOperandConverter(gen, instr) {}
 
-  SwVfpRegister OutputFloat32Register(size_t index = 0) {
-    return ToFloat32Register(instr_->OutputAt(index));
-  }
-
-  SwVfpRegister InputFloat32Register(size_t index) {
-    return ToFloat32Register(instr_->InputAt(index));
-  }
-
-  SwVfpRegister ToFloat32Register(InstructionOperand* op) {
-    return ToFloat64Register(op).low();
-  }
-
-  LowDwVfpRegister OutputFloat64Register(size_t index = 0) {
-    return ToFloat64Register(instr_->OutputAt(index));
-  }
-
-  LowDwVfpRegister InputFloat64Register(size_t index) {
-    return ToFloat64Register(instr_->InputAt(index));
-  }
-
-  LowDwVfpRegister ToFloat64Register(InstructionOperand* op) {
-    return LowDwVfpRegister::from_code(ToDoubleRegister(op).code());
-  }
-
   SBit OutputSBit() const {
     switch (instr_->flags_mode()) {
       case kFlags_branch:
@@ -125,13 +101,16 @@
       case kMode_Operand2_R:
       case kMode_Operand2_R_ASR_I:
       case kMode_Operand2_R_ASR_R:
-      case kMode_Operand2_R_LSL_I:
       case kMode_Operand2_R_LSL_R:
       case kMode_Operand2_R_LSR_I:
       case kMode_Operand2_R_LSR_R:
       case kMode_Operand2_R_ROR_I:
       case kMode_Operand2_R_ROR_R:
         break;
+      case kMode_Operand2_R_LSL_I:
+        *first_index += 3;
+        return MemOperand(InputRegister(index + 0), InputRegister(index + 1),
+                          LSL, InputInt32(index + 2));
       case kMode_Offset_RI:
         *first_index += 2;
         return MemOperand(InputRegister(index + 0), InputInt32(index + 1));
@@ -149,7 +128,7 @@
 
   MemOperand ToMemOperand(InstructionOperand* op) const {
     DCHECK_NOT_NULL(op);
-    DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
+    DCHECK(op->IsStackSlot() || op->IsFPStackSlot());
     return SlotToMemOperand(AllocatedOperand::cast(op)->index());
   }
 
@@ -162,9 +141,9 @@
 
 namespace {
 
-class OutOfLineLoadFloat32 final : public OutOfLineCode {
+class OutOfLineLoadFloat final : public OutOfLineCode {
  public:
-  OutOfLineLoadFloat32(CodeGenerator* gen, SwVfpRegister result)
+  OutOfLineLoadFloat(CodeGenerator* gen, SwVfpRegister result)
       : OutOfLineCode(gen), result_(result) {}
 
   void Generate() final {
@@ -177,10 +156,9 @@
   SwVfpRegister const result_;
 };
 
-
-class OutOfLineLoadFloat64 final : public OutOfLineCode {
+class OutOfLineLoadDouble final : public OutOfLineCode {
  public:
-  OutOfLineLoadFloat64(CodeGenerator* gen, DwVfpRegister result)
+  OutOfLineLoadDouble(CodeGenerator* gen, DwVfpRegister result)
       : OutOfLineCode(gen), result_(result) {}
 
   void Generate() final {
@@ -218,7 +196,8 @@
         value_(value),
         scratch0_(scratch0),
         scratch1_(scratch1),
-        mode_(mode) {}
+        mode_(mode),
+        must_save_lr_(!gen->frame_access_state()->has_frame()) {}
 
   OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t index,
                        Register value, Register scratch0, Register scratch1,
@@ -326,24 +305,22 @@
 
 }  // namespace
 
-
-#define ASSEMBLE_CHECKED_LOAD_FLOAT(width)                           \
-  do {                                                               \
-    auto result = i.OutputFloat##width##Register();                  \
-    auto offset = i.InputRegister(0);                                \
-    if (instr->InputAt(1)->IsRegister()) {                           \
-      __ cmp(offset, i.InputRegister(1));                            \
-    } else {                                                         \
-      __ cmp(offset, i.InputImmediate(1));                           \
-    }                                                                \
-    auto ool = new (zone()) OutOfLineLoadFloat##width(this, result); \
-    __ b(hs, ool->entry());                                          \
-    __ vldr(result, i.InputOffset(2));                               \
-    __ bind(ool->exit());                                            \
-    DCHECK_EQ(LeaveCC, i.OutputSBit());                              \
+#define ASSEMBLE_CHECKED_LOAD_FP(Type)                         \
+  do {                                                         \
+    auto result = i.Output##Type##Register();                  \
+    auto offset = i.InputRegister(0);                          \
+    if (instr->InputAt(1)->IsRegister()) {                     \
+      __ cmp(offset, i.InputRegister(1));                      \
+    } else {                                                   \
+      __ cmp(offset, i.InputImmediate(1));                     \
+    }                                                          \
+    auto ool = new (zone()) OutOfLineLoad##Type(this, result); \
+    __ b(hs, ool->entry());                                    \
+    __ vldr(result, i.InputOffset(2));                         \
+    __ bind(ool->exit());                                      \
+    DCHECK_EQ(LeaveCC, i.OutputSBit());                        \
   } while (0)
 
-
 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr)                \
   do {                                                          \
     auto result = i.OutputRegister();                           \
@@ -360,21 +337,19 @@
     DCHECK_EQ(LeaveCC, i.OutputSBit());                         \
   } while (0)
 
-
-#define ASSEMBLE_CHECKED_STORE_FLOAT(width)        \
-  do {                                             \
-    auto offset = i.InputRegister(0);              \
-    if (instr->InputAt(1)->IsRegister()) {         \
-      __ cmp(offset, i.InputRegister(1));          \
-    } else {                                       \
-      __ cmp(offset, i.InputImmediate(1));         \
-    }                                              \
-    auto value = i.InputFloat##width##Register(2); \
-    __ vstr(value, i.InputOffset(3), lo);          \
-    DCHECK_EQ(LeaveCC, i.OutputSBit());            \
+#define ASSEMBLE_CHECKED_STORE_FP(Type)      \
+  do {                                       \
+    auto offset = i.InputRegister(0);        \
+    if (instr->InputAt(1)->IsRegister()) {   \
+      __ cmp(offset, i.InputRegister(1));    \
+    } else {                                 \
+      __ cmp(offset, i.InputImmediate(1));   \
+    }                                        \
+    auto value = i.Input##Type##Register(2); \
+    __ vstr(value, i.InputOffset(3), lo);    \
+    DCHECK_EQ(LeaveCC, i.OutputSBit());      \
   } while (0)
 
-
 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \
   do {                                            \
     auto offset = i.InputRegister(0);             \
@@ -388,12 +363,54 @@
     DCHECK_EQ(LeaveCC, i.OutputSBit());           \
   } while (0)
 
+#define ASSEMBLE_ATOMIC_LOAD_INTEGER(asm_instr)                       \
+  do {                                                                \
+    __ asm_instr(i.OutputRegister(),                                  \
+                 MemOperand(i.InputRegister(0), i.InputRegister(1))); \
+    __ dmb(ISH);                                                      \
+  } while (0)
+
+#define ASSEMBLE_ATOMIC_STORE_INTEGER(asm_instr)                      \
+  do {                                                                \
+    __ dmb(ISH);                                                      \
+    __ asm_instr(i.InputRegister(2),                                  \
+                 MemOperand(i.InputRegister(0), i.InputRegister(1))); \
+    __ dmb(ISH);                                                      \
+  } while (0)
+
+#define ASSEMBLE_IEEE754_BINOP(name)                                           \
+  do {                                                                         \
+    /* TODO(bmeurer): We should really get rid of this special instruction, */ \
+    /* and generate a CallAddress instruction instead. */                      \
+    FrameScope scope(masm(), StackFrame::MANUAL);                              \
+    __ PrepareCallCFunction(0, 2, kScratchReg);                                \
+    __ MovToFloatParameters(i.InputDoubleRegister(0),                          \
+                            i.InputDoubleRegister(1));                         \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()),  \
+                     0, 2);                                                    \
+    /* Move the result in the double result register. */                       \
+    __ MovFromFloatResult(i.OutputDoubleRegister());                           \
+    DCHECK_EQ(LeaveCC, i.OutputSBit());                                        \
+  } while (0)
+
+#define ASSEMBLE_IEEE754_UNOP(name)                                            \
+  do {                                                                         \
+    /* TODO(bmeurer): We should really get rid of this special instruction, */ \
+    /* and generate a CallAddress instruction instead. */                      \
+    FrameScope scope(masm(), StackFrame::MANUAL);                              \
+    __ PrepareCallCFunction(0, 1, kScratchReg);                                \
+    __ MovToFloatParameter(i.InputDoubleRegister(0));                          \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()),  \
+                     0, 1);                                                    \
+    /* Move the result in the double result register. */                       \
+    __ MovFromFloatResult(i.OutputDoubleRegister());                           \
+    DCHECK_EQ(LeaveCC, i.OutputSBit());                                        \
+  } while (0)
+
 void CodeGenerator::AssembleDeconstructFrame() {
   __ LeaveFrame(StackFrame::MANUAL);
 }
 
-void CodeGenerator::AssembleSetupStackPointer() {}
-
 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
   int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
   if (sp_slot_delta > 0) {
@@ -445,7 +462,8 @@
 }
 
 // Assembles an instruction after register allocation, producing machine code.
-void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
+CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
+    Instruction* instr) {
   ArmOperandConverter i(this, instr);
 
   __ MaybeCheckConstPool();
@@ -488,6 +506,14 @@
       frame_access_state()->ClearSPDelta();
       break;
     }
+    case kArchTailCallAddress: {
+      int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
+      AssembleDeconstructActivationRecord(stack_param_delta);
+      CHECK(!instr->InputAt(0)->IsImmediate());
+      __ Jump(i.InputRegister(0));
+      frame_access_state()->ClearSPDelta();
+      break;
+    }
     case kArchCallJSFunction: {
       EnsureSpaceForLazyDeopt();
       Register func = i.InputRegister(0);
@@ -561,6 +587,14 @@
       AssembleArchTableSwitch(instr);
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
+    case kArchDebugBreak:
+      __ stop("kArchDebugBreak");
+      break;
+    case kArchComment: {
+      Address comment_string = i.InputExternalReference(0).address();
+      __ RecordComment(reinterpret_cast<const char*>(comment_string));
+      break;
+    }
     case kArchNop:
     case kArchThrowTerminator:
       // don't emit code for nops.
@@ -571,7 +605,9 @@
           BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
       Deoptimizer::BailoutType bailout_type =
           Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
-      AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      CodeGenResult result =
+          AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      if (result != kSuccess) return result;
       break;
     }
     case kArchRet:
@@ -594,7 +630,7 @@
       }
       break;
     case kArchTruncateDoubleToI:
-      __ TruncateDoubleToI(i.OutputRegister(), i.InputFloat64Register(0));
+      __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArchStoreWithWriteBarrier: {
@@ -638,6 +674,45 @@
       __ add(i.OutputRegister(0), base, Operand(offset.offset()));
       break;
     }
+    case kIeee754Float64Atan:
+      ASSEMBLE_IEEE754_UNOP(atan);
+      break;
+    case kIeee754Float64Atan2:
+      ASSEMBLE_IEEE754_BINOP(atan2);
+      break;
+    case kIeee754Float64Cbrt:
+      ASSEMBLE_IEEE754_UNOP(cbrt);
+      break;
+    case kIeee754Float64Cos:
+      ASSEMBLE_IEEE754_UNOP(cos);
+      break;
+    case kIeee754Float64Exp:
+      ASSEMBLE_IEEE754_UNOP(exp);
+      break;
+    case kIeee754Float64Expm1:
+      ASSEMBLE_IEEE754_UNOP(expm1);
+      break;
+    case kIeee754Float64Atanh:
+      ASSEMBLE_IEEE754_UNOP(atanh);
+      break;
+    case kIeee754Float64Log:
+      ASSEMBLE_IEEE754_UNOP(log);
+      break;
+    case kIeee754Float64Log1p:
+      ASSEMBLE_IEEE754_UNOP(log1p);
+      break;
+    case kIeee754Float64Log2:
+      ASSEMBLE_IEEE754_UNOP(log2);
+      break;
+    case kIeee754Float64Log10:
+      ASSEMBLE_IEEE754_UNOP(log10);
+      break;
+    case kIeee754Float64Sin:
+      ASSEMBLE_IEEE754_UNOP(sin);
+      break;
+    case kIeee754Float64Tan:
+      ASSEMBLE_IEEE754_UNOP(tan);
+      break;
     case kArmAdd:
       __ add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1),
              i.OutputSBit());
@@ -659,7 +734,7 @@
              i.InputRegister(2), i.OutputSBit());
       break;
     case kArmMls: {
-      CpuFeatureScope scope(masm(), MLS);
+      CpuFeatureScope scope(masm(), ARMv7);
       __ mls(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
              i.InputRegister(2));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
@@ -856,96 +931,96 @@
       }
       break;
     case kArmVcmpF32:
-      if (instr->InputAt(1)->IsDoubleRegister()) {
-        __ VFPCompareAndSetFlags(i.InputFloat32Register(0),
-                                 i.InputFloat32Register(1));
+      if (instr->InputAt(1)->IsFPRegister()) {
+        __ VFPCompareAndSetFlags(i.InputFloatRegister(0),
+                                 i.InputFloatRegister(1));
       } else {
         DCHECK(instr->InputAt(1)->IsImmediate());
         // 0.0 is the only immediate supported by vcmp instructions.
         DCHECK(i.InputFloat32(1) == 0.0f);
-        __ VFPCompareAndSetFlags(i.InputFloat32Register(0), i.InputFloat32(1));
+        __ VFPCompareAndSetFlags(i.InputFloatRegister(0), i.InputFloat32(1));
       }
       DCHECK_EQ(SetCC, i.OutputSBit());
       break;
     case kArmVaddF32:
-      __ vadd(i.OutputFloat32Register(), i.InputFloat32Register(0),
-              i.InputFloat32Register(1));
+      __ vadd(i.OutputFloatRegister(), i.InputFloatRegister(0),
+              i.InputFloatRegister(1));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmVsubF32:
-      __ vsub(i.OutputFloat32Register(), i.InputFloat32Register(0),
-              i.InputFloat32Register(1));
+      __ vsub(i.OutputFloatRegister(), i.InputFloatRegister(0),
+              i.InputFloatRegister(1));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmVmulF32:
-      __ vmul(i.OutputFloat32Register(), i.InputFloat32Register(0),
-              i.InputFloat32Register(1));
+      __ vmul(i.OutputFloatRegister(), i.InputFloatRegister(0),
+              i.InputFloatRegister(1));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmVmlaF32:
-      __ vmla(i.OutputFloat32Register(), i.InputFloat32Register(1),
-              i.InputFloat32Register(2));
+      __ vmla(i.OutputFloatRegister(), i.InputFloatRegister(1),
+              i.InputFloatRegister(2));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmVmlsF32:
-      __ vmls(i.OutputFloat32Register(), i.InputFloat32Register(1),
-              i.InputFloat32Register(2));
+      __ vmls(i.OutputFloatRegister(), i.InputFloatRegister(1),
+              i.InputFloatRegister(2));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmVdivF32:
-      __ vdiv(i.OutputFloat32Register(), i.InputFloat32Register(0),
-              i.InputFloat32Register(1));
+      __ vdiv(i.OutputFloatRegister(), i.InputFloatRegister(0),
+              i.InputFloatRegister(1));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmVsqrtF32:
-      __ vsqrt(i.OutputFloat32Register(), i.InputFloat32Register(0));
+      __ vsqrt(i.OutputFloatRegister(), i.InputFloatRegister(0));
       break;
     case kArmVabsF32:
-      __ vabs(i.OutputFloat32Register(), i.InputFloat32Register(0));
+      __ vabs(i.OutputFloatRegister(), i.InputFloatRegister(0));
       break;
     case kArmVnegF32:
-      __ vneg(i.OutputFloat32Register(), i.InputFloat32Register(0));
+      __ vneg(i.OutputFloatRegister(), i.InputFloatRegister(0));
       break;
     case kArmVcmpF64:
-      if (instr->InputAt(1)->IsDoubleRegister()) {
-        __ VFPCompareAndSetFlags(i.InputFloat64Register(0),
-                                 i.InputFloat64Register(1));
+      if (instr->InputAt(1)->IsFPRegister()) {
+        __ VFPCompareAndSetFlags(i.InputDoubleRegister(0),
+                                 i.InputDoubleRegister(1));
       } else {
         DCHECK(instr->InputAt(1)->IsImmediate());
         // 0.0 is the only immediate supported by vcmp instructions.
         DCHECK(i.InputDouble(1) == 0.0);
-        __ VFPCompareAndSetFlags(i.InputFloat64Register(0), i.InputDouble(1));
+        __ VFPCompareAndSetFlags(i.InputDoubleRegister(0), i.InputDouble(1));
       }
       DCHECK_EQ(SetCC, i.OutputSBit());
       break;
     case kArmVaddF64:
-      __ vadd(i.OutputFloat64Register(), i.InputFloat64Register(0),
-              i.InputFloat64Register(1));
+      __ vadd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
+              i.InputDoubleRegister(1));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmVsubF64:
-      __ vsub(i.OutputFloat64Register(), i.InputFloat64Register(0),
-              i.InputFloat64Register(1));
+      __ vsub(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
+              i.InputDoubleRegister(1));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmVmulF64:
-      __ vmul(i.OutputFloat64Register(), i.InputFloat64Register(0),
-              i.InputFloat64Register(1));
+      __ vmul(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
+              i.InputDoubleRegister(1));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmVmlaF64:
-      __ vmla(i.OutputFloat64Register(), i.InputFloat64Register(1),
-              i.InputFloat64Register(2));
+      __ vmla(i.OutputDoubleRegister(), i.InputDoubleRegister(1),
+              i.InputDoubleRegister(2));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmVmlsF64:
-      __ vmls(i.OutputFloat64Register(), i.InputFloat64Register(1),
-              i.InputFloat64Register(2));
+      __ vmls(i.OutputDoubleRegister(), i.InputDoubleRegister(1),
+              i.InputDoubleRegister(2));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmVdivF64:
-      __ vdiv(i.OutputFloat64Register(), i.InputFloat64Register(0),
-              i.InputFloat64Register(1));
+      __ vdiv(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
+              i.InputDoubleRegister(1));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmVmodF64: {
@@ -953,136 +1028,143 @@
       // and generate a CallAddress instruction instead.
       FrameScope scope(masm(), StackFrame::MANUAL);
       __ PrepareCallCFunction(0, 2, kScratchReg);
-      __ MovToFloatParameters(i.InputFloat64Register(0),
-                              i.InputFloat64Register(1));
+      __ MovToFloatParameters(i.InputDoubleRegister(0),
+                              i.InputDoubleRegister(1));
       __ CallCFunction(ExternalReference::mod_two_doubles_operation(isolate()),
                        0, 2);
       // Move the result in the double result register.
-      __ MovFromFloatResult(i.OutputFloat64Register());
+      __ MovFromFloatResult(i.OutputDoubleRegister());
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     }
     case kArmVsqrtF64:
-      __ vsqrt(i.OutputFloat64Register(), i.InputFloat64Register(0));
+      __ vsqrt(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
       break;
     case kArmVabsF64:
-      __ vabs(i.OutputFloat64Register(), i.InputFloat64Register(0));
+      __ vabs(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
       break;
     case kArmVnegF64:
-      __ vneg(i.OutputFloat64Register(), i.InputFloat64Register(0));
+      __ vneg(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
       break;
     case kArmVrintmF32:
-      __ vrintm(i.OutputFloat32Register(), i.InputFloat32Register(0));
+      __ vrintm(i.OutputFloatRegister(), i.InputFloatRegister(0));
       break;
     case kArmVrintmF64:
-      __ vrintm(i.OutputFloat64Register(), i.InputFloat64Register(0));
+      __ vrintm(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
       break;
     case kArmVrintpF32:
-      __ vrintp(i.OutputFloat32Register(), i.InputFloat32Register(0));
+      __ vrintp(i.OutputFloatRegister(), i.InputFloatRegister(0));
       break;
     case kArmVrintpF64:
-      __ vrintp(i.OutputFloat64Register(), i.InputFloat64Register(0));
+      __ vrintp(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
       break;
     case kArmVrintzF32:
-      __ vrintz(i.OutputFloat32Register(), i.InputFloat32Register(0));
+      __ vrintz(i.OutputFloatRegister(), i.InputFloatRegister(0));
       break;
     case kArmVrintzF64:
-      __ vrintz(i.OutputFloat64Register(), i.InputFloat64Register(0));
+      __ vrintz(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
       break;
     case kArmVrintaF64:
-      __ vrinta(i.OutputFloat64Register(), i.InputFloat64Register(0));
+      __ vrinta(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
       break;
     case kArmVrintnF32:
-      __ vrintn(i.OutputFloat32Register(), i.InputFloat32Register(0));
+      __ vrintn(i.OutputFloatRegister(), i.InputFloatRegister(0));
       break;
     case kArmVrintnF64:
-      __ vrintn(i.OutputFloat64Register(), i.InputFloat64Register(0));
+      __ vrintn(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
       break;
     case kArmVcvtF32F64: {
-      __ vcvt_f32_f64(i.OutputFloat32Register(), i.InputFloat64Register(0));
+      __ vcvt_f32_f64(i.OutputFloatRegister(), i.InputDoubleRegister(0));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     }
     case kArmVcvtF64F32: {
-      __ vcvt_f64_f32(i.OutputFloat64Register(), i.InputFloat32Register(0));
+      __ vcvt_f64_f32(i.OutputDoubleRegister(), i.InputFloatRegister(0));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     }
     case kArmVcvtF32S32: {
       SwVfpRegister scratch = kScratchDoubleReg.low();
       __ vmov(scratch, i.InputRegister(0));
-      __ vcvt_f32_s32(i.OutputFloat32Register(), scratch);
+      __ vcvt_f32_s32(i.OutputFloatRegister(), scratch);
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     }
     case kArmVcvtF32U32: {
       SwVfpRegister scratch = kScratchDoubleReg.low();
       __ vmov(scratch, i.InputRegister(0));
-      __ vcvt_f32_u32(i.OutputFloat32Register(), scratch);
+      __ vcvt_f32_u32(i.OutputFloatRegister(), scratch);
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     }
     case kArmVcvtF64S32: {
       SwVfpRegister scratch = kScratchDoubleReg.low();
       __ vmov(scratch, i.InputRegister(0));
-      __ vcvt_f64_s32(i.OutputFloat64Register(), scratch);
+      __ vcvt_f64_s32(i.OutputDoubleRegister(), scratch);
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     }
     case kArmVcvtF64U32: {
       SwVfpRegister scratch = kScratchDoubleReg.low();
       __ vmov(scratch, i.InputRegister(0));
-      __ vcvt_f64_u32(i.OutputFloat64Register(), scratch);
+      __ vcvt_f64_u32(i.OutputDoubleRegister(), scratch);
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     }
     case kArmVcvtS32F32: {
       SwVfpRegister scratch = kScratchDoubleReg.low();
-      __ vcvt_s32_f32(scratch, i.InputFloat32Register(0));
+      __ vcvt_s32_f32(scratch, i.InputFloatRegister(0));
       __ vmov(i.OutputRegister(), scratch);
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     }
     case kArmVcvtU32F32: {
       SwVfpRegister scratch = kScratchDoubleReg.low();
-      __ vcvt_u32_f32(scratch, i.InputFloat32Register(0));
+      __ vcvt_u32_f32(scratch, i.InputFloatRegister(0));
       __ vmov(i.OutputRegister(), scratch);
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     }
     case kArmVcvtS32F64: {
       SwVfpRegister scratch = kScratchDoubleReg.low();
-      __ vcvt_s32_f64(scratch, i.InputFloat64Register(0));
+      __ vcvt_s32_f64(scratch, i.InputDoubleRegister(0));
       __ vmov(i.OutputRegister(), scratch);
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     }
     case kArmVcvtU32F64: {
       SwVfpRegister scratch = kScratchDoubleReg.low();
-      __ vcvt_u32_f64(scratch, i.InputFloat64Register(0));
+      __ vcvt_u32_f64(scratch, i.InputDoubleRegister(0));
       __ vmov(i.OutputRegister(), scratch);
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     }
+    case kArmVmovU32F32:
+      __ vmov(i.OutputRegister(), i.InputFloatRegister(0));
+      DCHECK_EQ(LeaveCC, i.OutputSBit());
+      break;
+    case kArmVmovF32U32:
+      __ vmov(i.OutputFloatRegister(), i.InputRegister(0));
+      DCHECK_EQ(LeaveCC, i.OutputSBit());
+      break;
     case kArmVmovLowU32F64:
-      __ VmovLow(i.OutputRegister(), i.InputFloat64Register(0));
+      __ VmovLow(i.OutputRegister(), i.InputDoubleRegister(0));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmVmovLowF64U32:
-      __ VmovLow(i.OutputFloat64Register(), i.InputRegister(1));
+      __ VmovLow(i.OutputDoubleRegister(), i.InputRegister(1));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmVmovHighU32F64:
-      __ VmovHigh(i.OutputRegister(), i.InputFloat64Register(0));
+      __ VmovHigh(i.OutputRegister(), i.InputDoubleRegister(0));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmVmovHighF64U32:
-      __ VmovHigh(i.OutputFloat64Register(), i.InputRegister(1));
+      __ VmovHigh(i.OutputDoubleRegister(), i.InputRegister(1));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmVmovF64U32U32:
-      __ vmov(i.OutputFloat64Register(), i.InputRegister(0),
-              i.InputRegister(1));
+      __ vmov(i.OutputDoubleRegister(), i.InputRegister(0), i.InputRegister(1));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     case kArmLdrb:
@@ -1093,63 +1175,101 @@
       __ ldrsb(i.OutputRegister(), i.InputOffset());
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
-    case kArmStrb: {
-      size_t index = 0;
-      MemOperand operand = i.InputOffset(&index);
-      __ strb(i.InputRegister(index), operand);
+    case kArmStrb:
+      __ strb(i.InputRegister(0), i.InputOffset(1));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
-    }
     case kArmLdrh:
       __ ldrh(i.OutputRegister(), i.InputOffset());
       break;
     case kArmLdrsh:
       __ ldrsh(i.OutputRegister(), i.InputOffset());
       break;
-    case kArmStrh: {
-      size_t index = 0;
-      MemOperand operand = i.InputOffset(&index);
-      __ strh(i.InputRegister(index), operand);
+    case kArmStrh:
+      __ strh(i.InputRegister(0), i.InputOffset(1));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
-    }
     case kArmLdr:
       __ ldr(i.OutputRegister(), i.InputOffset());
       break;
-    case kArmStr: {
-      size_t index = 0;
-      MemOperand operand = i.InputOffset(&index);
-      __ str(i.InputRegister(index), operand);
+    case kArmStr:
+      __ str(i.InputRegister(0), i.InputOffset(1));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
-    }
     case kArmVldrF32: {
-      __ vldr(i.OutputFloat32Register(), i.InputOffset());
+      __ vldr(i.OutputFloatRegister(), i.InputOffset());
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     }
-    case kArmVstrF32: {
-      size_t index = 0;
-      MemOperand operand = i.InputOffset(&index);
-      __ vstr(i.InputFloat32Register(index), operand);
+    case kArmVstrF32:
+      __ vstr(i.InputFloatRegister(0), i.InputOffset(1));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
-    }
     case kArmVldrF64:
-      __ vldr(i.OutputFloat64Register(), i.InputOffset());
+      __ vldr(i.OutputDoubleRegister(), i.InputOffset());
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
-    case kArmVstrF64: {
-      size_t index = 0;
-      MemOperand operand = i.InputOffset(&index);
-      __ vstr(i.InputFloat64Register(index), operand);
+    case kArmVstrF64:
+      __ vstr(i.InputDoubleRegister(0), i.InputOffset(1));
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
+    case kArmFloat32Max: {
+      CpuFeatureScope scope(masm(), ARMv8);
+      // (b < a) ? a : b
+      SwVfpRegister a = i.InputFloatRegister(0);
+      SwVfpRegister b = i.InputFloatRegister(1);
+      SwVfpRegister result = i.OutputFloatRegister();
+      __ VFPCompareAndSetFlags(a, b);
+      __ vsel(gt, result, a, b);
+      break;
+    }
+    case kArmFloat32Min: {
+      CpuFeatureScope scope(masm(), ARMv8);
+      // (a < b) ? a : b
+      SwVfpRegister a = i.InputFloatRegister(0);
+      SwVfpRegister b = i.InputFloatRegister(1);
+      SwVfpRegister result = i.OutputFloatRegister();
+      __ VFPCompareAndSetFlags(b, a);
+      __ vsel(gt, result, a, b);
+      break;
+    }
+    case kArmFloat64Max: {
+      CpuFeatureScope scope(masm(), ARMv8);
+      // (b < a) ? a : b
+      DwVfpRegister a = i.InputDoubleRegister(0);
+      DwVfpRegister b = i.InputDoubleRegister(1);
+      DwVfpRegister result = i.OutputDoubleRegister();
+      __ VFPCompareAndSetFlags(a, b);
+      __ vsel(gt, result, a, b);
+      break;
+    }
+    case kArmFloat64Min: {
+      CpuFeatureScope scope(masm(), ARMv8);
+      // (a < b) ? a : b
+      DwVfpRegister a = i.InputDoubleRegister(0);
+      DwVfpRegister b = i.InputDoubleRegister(1);
+      DwVfpRegister result = i.OutputDoubleRegister();
+      __ VFPCompareAndSetFlags(b, a);
+      __ vsel(gt, result, a, b);
+      break;
+    }
+    case kArmFloat64SilenceNaN: {
+      DwVfpRegister value = i.InputDoubleRegister(0);
+      DwVfpRegister result = i.OutputDoubleRegister();
+      __ VFPCanonicalizeNaN(result, value);
+      break;
     }
     case kArmPush:
-      if (instr->InputAt(0)->IsDoubleRegister()) {
-        __ vpush(i.InputDoubleRegister(0));
-        frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
+      if (instr->InputAt(0)->IsFPRegister()) {
+        LocationOperand* op = LocationOperand::cast(instr->InputAt(0));
+        if (op->representation() == MachineRepresentation::kFloat64) {
+          __ vpush(i.InputDoubleRegister(0));
+          frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
+        } else {
+          DCHECK_EQ(MachineRepresentation::kFloat32, op->representation());
+          __ vpush(i.InputFloatRegister(0));
+          frame_access_state()->IncreaseSPDelta(1);
+        }
       } else {
         __ push(i.InputRegister(0));
         frame_access_state()->IncreaseSPDelta(1);
@@ -1178,10 +1298,10 @@
       ASSEMBLE_CHECKED_LOAD_INTEGER(ldr);
       break;
     case kCheckedLoadFloat32:
-      ASSEMBLE_CHECKED_LOAD_FLOAT(32);
+      ASSEMBLE_CHECKED_LOAD_FP(Float);
       break;
     case kCheckedLoadFloat64:
-      ASSEMBLE_CHECKED_LOAD_FLOAT(64);
+      ASSEMBLE_CHECKED_LOAD_FP(Double);
       break;
     case kCheckedStoreWord8:
       ASSEMBLE_CHECKED_STORE_INTEGER(strb);
@@ -1193,16 +1313,43 @@
       ASSEMBLE_CHECKED_STORE_INTEGER(str);
       break;
     case kCheckedStoreFloat32:
-      ASSEMBLE_CHECKED_STORE_FLOAT(32);
+      ASSEMBLE_CHECKED_STORE_FP(Float);
       break;
     case kCheckedStoreFloat64:
-      ASSEMBLE_CHECKED_STORE_FLOAT(64);
+      ASSEMBLE_CHECKED_STORE_FP(Double);
       break;
     case kCheckedLoadWord64:
     case kCheckedStoreWord64:
       UNREACHABLE();  // currently unsupported checked int64 load/store.
       break;
+
+    case kAtomicLoadInt8:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(ldrsb);
+      break;
+    case kAtomicLoadUint8:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(ldrb);
+      break;
+    case kAtomicLoadInt16:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(ldrsh);
+      break;
+    case kAtomicLoadUint16:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(ldrh);
+      break;
+    case kAtomicLoadWord32:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(ldr);
+      break;
+
+    case kAtomicStoreWord8:
+      ASSEMBLE_ATOMIC_STORE_INTEGER(strb);
+      break;
+    case kAtomicStoreWord16:
+      ASSEMBLE_ATOMIC_STORE_INTEGER(strh);
+      break;
+    case kAtomicStoreWord32:
+      ASSEMBLE_ATOMIC_STORE_INTEGER(str);
+      break;
   }
+  return kSuccess;
 }  // NOLINT(readability/fn_size)
 
 
@@ -1263,20 +1410,47 @@
   }
 }
 
-
-void CodeGenerator::AssembleDeoptimizerCall(
+CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
     int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
   Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
       isolate(), deoptimization_id, bailout_type);
   // TODO(turbofan): We should be able to generate better code by sharing the
   // actual final call site and just bl'ing to it here, similar to what we do
   // in the lithium backend.
+  if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
   __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
   __ CheckConstPool(false, false);
+  return kSuccess;
 }
 
+void CodeGenerator::FinishFrame(Frame* frame) {
+  CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
 
-void CodeGenerator::AssemblePrologue() {
+  const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
+  if (saves_fp != 0) {
+    frame->AlignSavedCalleeRegisterSlots();
+  }
+
+  if (saves_fp != 0) {
+    // Save callee-saved FP registers.
+    STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32);
+    uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
+    uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
+    DCHECK_EQ((last - first + 1), base::bits::CountPopulation32(saves_fp));
+    frame->AllocateSavedCalleeRegisterSlots((last - first + 1) *
+                                            (kDoubleSize / kPointerSize));
+  }
+  const RegList saves = FLAG_enable_embedded_constant_pool
+                            ? (descriptor->CalleeSavedRegisters() & ~pp.bit())
+                            : descriptor->CalleeSavedRegisters();
+  if (saves != 0) {
+    // Save callee-saved registers.
+    frame->AllocateSavedCalleeRegisterSlots(
+        base::bits::CountPopulation32(saves));
+  }
+}
+
+void CodeGenerator::AssembleConstructFrame() {
   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
   if (frame_access_state()->has_frame()) {
     if (descriptor->IsCFunctionCall()) {
@@ -1295,7 +1469,8 @@
     }
   }
 
-  int stack_shrink_slots = frame()->GetSpillSlotCount();
+  int shrink_slots = frame()->GetSpillSlotCount();
+
   if (info()->is_osr()) {
     // TurboFan OSR-compiled functions cannot be entered directly.
     __ Abort(kShouldNotDirectlyEnterOsrFunction);
@@ -1306,15 +1481,12 @@
     // remaining stack slots.
     if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
     osr_pc_offset_ = __ pc_offset();
-    stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
+    shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
   }
 
   const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
-  if (saves_fp != 0) {
-    stack_shrink_slots += frame()->AlignSavedCalleeRegisterSlots();
-  }
-  if (stack_shrink_slots > 0) {
-    __ sub(sp, sp, Operand(stack_shrink_slots * kPointerSize));
+  if (shrink_slots > 0) {
+    __ sub(sp, sp, Operand(shrink_slots * kPointerSize));
   }
 
   if (saves_fp != 0) {
@@ -1325,8 +1497,6 @@
     DCHECK_EQ((last - first + 1), base::bits::CountPopulation32(saves_fp));
     __ vstm(db_w, sp, DwVfpRegister::from_code(first),
             DwVfpRegister::from_code(last));
-    frame()->AllocateSavedCalleeRegisterSlots((last - first + 1) *
-                                              (kDoubleSize / kPointerSize));
   }
   const RegList saves = FLAG_enable_embedded_constant_pool
                             ? (descriptor->CalleeSavedRegisters() & ~pp.bit())
@@ -1334,8 +1504,6 @@
   if (saves != 0) {
     // Save callee-saved registers.
     __ stm(db_w, sp, saves);
-    frame()->AllocateSavedCalleeRegisterSlots(
-        base::bits::CountPopulation32(saves));
   }
 }
 
@@ -1408,7 +1576,13 @@
           destination->IsRegister() ? g.ToRegister(destination) : kScratchReg;
       switch (src.type()) {
         case Constant::kInt32:
-          __ mov(dst, Operand(src.ToInt32()));
+          if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
+              src.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE ||
+              src.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) {
+            __ mov(dst, Operand(src.ToInt32(), src.rmode()));
+          } else {
+            __ mov(dst, Operand(src.ToInt32()));
+          }
           break;
         case Constant::kInt64:
           UNREACHABLE();
@@ -1443,42 +1617,69 @@
       }
       if (destination->IsStackSlot()) __ str(dst, g.ToMemOperand(destination));
     } else if (src.type() == Constant::kFloat32) {
-      if (destination->IsDoubleStackSlot()) {
+      if (destination->IsFPStackSlot()) {
         MemOperand dst = g.ToMemOperand(destination);
         __ mov(ip, Operand(bit_cast<int32_t>(src.ToFloat32())));
         __ str(ip, dst);
       } else {
-        SwVfpRegister dst = g.ToFloat32Register(destination);
+        SwVfpRegister dst = g.ToFloatRegister(destination);
         __ vmov(dst, src.ToFloat32());
       }
     } else {
       DCHECK_EQ(Constant::kFloat64, src.type());
-      DwVfpRegister dst = destination->IsDoubleRegister()
-                              ? g.ToFloat64Register(destination)
+      DwVfpRegister dst = destination->IsFPRegister()
+                              ? g.ToDoubleRegister(destination)
                               : kScratchDoubleReg;
       __ vmov(dst, src.ToFloat64(), kScratchReg);
-      if (destination->IsDoubleStackSlot()) {
+      if (destination->IsFPStackSlot()) {
         __ vstr(dst, g.ToMemOperand(destination));
       }
     }
-  } else if (source->IsDoubleRegister()) {
-    DwVfpRegister src = g.ToDoubleRegister(source);
-    if (destination->IsDoubleRegister()) {
-      DwVfpRegister dst = g.ToDoubleRegister(destination);
-      __ Move(dst, src);
+  } else if (source->IsFPRegister()) {
+    MachineRepresentation rep = LocationOperand::cast(source)->representation();
+    if (rep == MachineRepresentation::kFloat64) {
+      DwVfpRegister src = g.ToDoubleRegister(source);
+      if (destination->IsFPRegister()) {
+        DwVfpRegister dst = g.ToDoubleRegister(destination);
+        __ Move(dst, src);
+      } else {
+        DCHECK(destination->IsFPStackSlot());
+        __ vstr(src, g.ToMemOperand(destination));
+      }
     } else {
-      DCHECK(destination->IsDoubleStackSlot());
-      __ vstr(src, g.ToMemOperand(destination));
+      DCHECK_EQ(MachineRepresentation::kFloat32, rep);
+      SwVfpRegister src = g.ToFloatRegister(source);
+      if (destination->IsFPRegister()) {
+        SwVfpRegister dst = g.ToFloatRegister(destination);
+        __ Move(dst, src);
+      } else {
+        DCHECK(destination->IsFPStackSlot());
+        __ vstr(src, g.ToMemOperand(destination));
+      }
     }
-  } else if (source->IsDoubleStackSlot()) {
-    DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
+  } else if (source->IsFPStackSlot()) {
     MemOperand src = g.ToMemOperand(source);
-    if (destination->IsDoubleRegister()) {
-      __ vldr(g.ToDoubleRegister(destination), src);
+    MachineRepresentation rep =
+        LocationOperand::cast(destination)->representation();
+    if (destination->IsFPRegister()) {
+      if (rep == MachineRepresentation::kFloat64) {
+        __ vldr(g.ToDoubleRegister(destination), src);
+      } else {
+        DCHECK_EQ(MachineRepresentation::kFloat32, rep);
+        __ vldr(g.ToFloatRegister(destination), src);
+      }
     } else {
-      DwVfpRegister temp = kScratchDoubleReg;
-      __ vldr(temp, src);
-      __ vstr(temp, g.ToMemOperand(destination));
+      DCHECK(destination->IsFPStackSlot());
+      if (rep == MachineRepresentation::kFloat64) {
+        DwVfpRegister temp = kScratchDoubleReg;
+        __ vldr(temp, src);
+        __ vstr(temp, g.ToMemOperand(destination));
+      } else {
+        DCHECK_EQ(MachineRepresentation::kFloat32, rep);
+        SwVfpRegister temp = kScratchDoubleReg.low();
+        __ vldr(temp, src);
+        __ vstr(temp, g.ToMemOperand(destination));
+      }
     }
   } else {
     UNREACHABLE();
@@ -1517,35 +1718,62 @@
     __ vldr(temp_1, dst);
     __ str(temp_0, dst);
     __ vstr(temp_1, src);
-  } else if (source->IsDoubleRegister()) {
-    DwVfpRegister temp = kScratchDoubleReg;
-    DwVfpRegister src = g.ToDoubleRegister(source);
-    if (destination->IsDoubleRegister()) {
-      DwVfpRegister dst = g.ToDoubleRegister(destination);
-      __ Move(temp, src);
-      __ Move(src, dst);
-      __ Move(dst, temp);
+  } else if (source->IsFPRegister()) {
+    MachineRepresentation rep = LocationOperand::cast(source)->representation();
+    LowDwVfpRegister temp = kScratchDoubleReg;
+    if (rep == MachineRepresentation::kFloat64) {
+      DwVfpRegister src = g.ToDoubleRegister(source);
+      if (destination->IsFPRegister()) {
+        DwVfpRegister dst = g.ToDoubleRegister(destination);
+        __ Move(temp, src);
+        __ Move(src, dst);
+        __ Move(dst, temp);
+      } else {
+        DCHECK(destination->IsFPStackSlot());
+        MemOperand dst = g.ToMemOperand(destination);
+        __ Move(temp, src);
+        __ vldr(src, dst);
+        __ vstr(temp, dst);
+      }
     } else {
-      DCHECK(destination->IsDoubleStackSlot());
-      MemOperand dst = g.ToMemOperand(destination);
-      __ Move(temp, src);
-      __ vldr(src, dst);
-      __ vstr(temp, dst);
+      DCHECK_EQ(MachineRepresentation::kFloat32, rep);
+      SwVfpRegister src = g.ToFloatRegister(source);
+      if (destination->IsFPRegister()) {
+        SwVfpRegister dst = g.ToFloatRegister(destination);
+        __ Move(temp.low(), src);
+        __ Move(src, dst);
+        __ Move(dst, temp.low());
+      } else {
+        DCHECK(destination->IsFPStackSlot());
+        MemOperand dst = g.ToMemOperand(destination);
+        __ Move(temp.low(), src);
+        __ vldr(src, dst);
+        __ vstr(temp.low(), dst);
+      }
     }
-  } else if (source->IsDoubleStackSlot()) {
-    DCHECK(destination->IsDoubleStackSlot());
+  } else if (source->IsFPStackSlot()) {
+    DCHECK(destination->IsFPStackSlot());
     Register temp_0 = kScratchReg;
-    DwVfpRegister temp_1 = kScratchDoubleReg;
+    LowDwVfpRegister temp_1 = kScratchDoubleReg;
     MemOperand src0 = g.ToMemOperand(source);
-    MemOperand src1(src0.rn(), src0.offset() + kPointerSize);
     MemOperand dst0 = g.ToMemOperand(destination);
-    MemOperand dst1(dst0.rn(), dst0.offset() + kPointerSize);
-    __ vldr(temp_1, dst0);  // Save destination in temp_1.
-    __ ldr(temp_0, src0);   // Then use temp_0 to copy source to destination.
-    __ str(temp_0, dst0);
-    __ ldr(temp_0, src1);
-    __ str(temp_0, dst1);
-    __ vstr(temp_1, src0);
+    MachineRepresentation rep = LocationOperand::cast(source)->representation();
+    if (rep == MachineRepresentation::kFloat64) {
+      MemOperand src1(src0.rn(), src0.offset() + kPointerSize);
+      MemOperand dst1(dst0.rn(), dst0.offset() + kPointerSize);
+      __ vldr(temp_1, dst0);  // Save destination in temp_1.
+      __ ldr(temp_0, src0);   // Then use temp_0 to copy source to destination.
+      __ str(temp_0, dst0);
+      __ ldr(temp_0, src1);
+      __ str(temp_0, dst1);
+      __ vstr(temp_1, src0);
+    } else {
+      DCHECK_EQ(MachineRepresentation::kFloat32, rep);
+      __ vldr(temp_1.low(), dst0);  // Save destination in temp_1.
+      __ ldr(temp_0, src0);  // Then use temp_0 to copy source to destination.
+      __ str(temp_0, dst0);
+      __ vstr(temp_1.low(), src0);
+    }
   } else {
     // No other combinations are possible.
     UNREACHABLE();
@@ -1559,11 +1787,6 @@
 }
 
 
-void CodeGenerator::AddNopForSmiCodeInlining() {
-  // On 32-bit ARM we do not insert nops for inlined Smi code.
-}
-
-
 void CodeGenerator::EnsureSpaceForLazyDeopt() {
   if (!info()->ShouldEnsureSpaceForLazyDeopt()) {
     return;
diff --git a/src/compiler/arm/instruction-codes-arm.h b/src/compiler/arm/instruction-codes-arm.h
index 5e6f5c9..bc3336f 100644
--- a/src/compiler/arm/instruction-codes-arm.h
+++ b/src/compiler/arm/instruction-codes-arm.h
@@ -92,6 +92,8 @@
   V(ArmVcvtU32F32)                 \
   V(ArmVcvtS32F64)                 \
   V(ArmVcvtU32F64)                 \
+  V(ArmVmovU32F32)                 \
+  V(ArmVmovF32U32)                 \
   V(ArmVmovLowU32F64)              \
   V(ArmVmovLowF64U32)              \
   V(ArmVmovHighU32F64)             \
@@ -101,6 +103,11 @@
   V(ArmVstrF32)                    \
   V(ArmVldrF64)                    \
   V(ArmVstrF64)                    \
+  V(ArmFloat32Max)                 \
+  V(ArmFloat32Min)                 \
+  V(ArmFloat64Max)                 \
+  V(ArmFloat64Min)                 \
+  V(ArmFloat64SilenceNaN)          \
   V(ArmLdrb)                       \
   V(ArmLdrsb)                      \
   V(ArmStrb)                       \
diff --git a/src/compiler/arm/instruction-scheduler-arm.cc b/src/compiler/arm/instruction-scheduler-arm.cc
index 466765e..065fe52 100644
--- a/src/compiler/arm/instruction-scheduler-arm.cc
+++ b/src/compiler/arm/instruction-scheduler-arm.cc
@@ -94,11 +94,18 @@
     case kArmVcvtU32F32:
     case kArmVcvtS32F64:
     case kArmVcvtU32F64:
+    case kArmVmovU32F32:
+    case kArmVmovF32U32:
     case kArmVmovLowU32F64:
     case kArmVmovLowF64U32:
     case kArmVmovHighU32F64:
     case kArmVmovHighF64U32:
     case kArmVmovF64U32U32:
+    case kArmFloat64Max:
+    case kArmFloat64Min:
+    case kArmFloat32Max:
+    case kArmFloat32Min:
+    case kArmFloat64SilenceNaN:
       return kNoOpcodeFlags;
 
     case kArmVldrF32:
diff --git a/src/compiler/arm/instruction-selector-arm.cc b/src/compiler/arm/instruction-selector-arm.cc
index 76d9e3c..e21e63f 100644
--- a/src/compiler/arm/instruction-selector-arm.cc
+++ b/src/compiler/arm/instruction-selector-arm.cc
@@ -115,6 +115,24 @@
   return false;
 }
 
+template <IrOpcode::Value kOpcode, int kImmMin, int kImmMax,
+          AddressingMode kImmMode>
+bool TryMatchShiftImmediate(InstructionSelector* selector,
+                            InstructionCode* opcode_return, Node* node,
+                            InstructionOperand* value_return,
+                            InstructionOperand* shift_return) {
+  ArmOperandGenerator g(selector);
+  if (node->opcode() == kOpcode) {
+    Int32BinopMatcher m(node);
+    if (m.right().IsInRange(kImmMin, kImmMax)) {
+      *opcode_return |= AddressingModeField::encode(kImmMode);
+      *value_return = g.UseRegister(m.left().node());
+      *shift_return = g.UseImmediate(m.right().node());
+      return true;
+    }
+  }
+  return false;
+}
 
 bool TryMatchROR(InstructionSelector* selector, InstructionCode* opcode_return,
                  Node* node, InstructionOperand* value_return,
@@ -142,6 +160,14 @@
                                                value_return, shift_return);
 }
 
+bool TryMatchLSLImmediate(InstructionSelector* selector,
+                          InstructionCode* opcode_return, Node* node,
+                          InstructionOperand* value_return,
+                          InstructionOperand* shift_return) {
+  return TryMatchShiftImmediate<IrOpcode::kWord32Shl, 0, 31,
+                                kMode_Operand2_R_LSL_I>(
+      selector, opcode_return, node, value_return, shift_return);
+}
 
 bool TryMatchLSR(InstructionSelector* selector, InstructionCode* opcode_return,
                  Node* node, InstructionOperand* value_return,
@@ -226,7 +252,14 @@
     inputs[input_count++] = g.Label(cont->false_block());
   }
 
-  outputs[output_count++] = g.DefineAsRegister(node);
+  if (cont->IsDeoptimize()) {
+    // If we can deoptimize as a result of the binop, we need to make sure that
+    // the deopt inputs are not overwritten by the binop result. One way
+    // to achieve that is to declare the output register as same-as-first.
+    outputs[output_count++] = g.DefineSameAsFirst(node);
+  } else {
+    outputs[output_count++] = g.DefineAsRegister(node);
+  }
   if (cont->IsSet()) {
     outputs[output_count++] = g.DefineAsRegister(cont->result());
   }
@@ -294,13 +327,14 @@
   InstructionOperand right_operand = g.UseRegister(m.right().node());
   EmitDiv(selector, div_opcode, f64i32_opcode, i32f64_opcode, div_operand,
           left_operand, right_operand);
-  if (selector->IsSupported(MLS)) {
+  if (selector->IsSupported(ARMv7)) {
     selector->Emit(kArmMls, result_operand, div_operand, right_operand,
                    left_operand);
   } else {
     InstructionOperand mul_operand = g.TempRegister();
     selector->Emit(kArmMul, mul_operand, div_operand, right_operand);
-    selector->Emit(kArmSub, result_operand, left_operand, mul_operand);
+    selector->Emit(kArmSub | AddressingModeField::encode(kMode_Operand2_R),
+                   result_operand, left_operand, mul_operand);
   }
 }
 
@@ -312,8 +346,11 @@
   ArmOperandGenerator g(this);
   Node* base = node->InputAt(0);
   Node* index = node->InputAt(1);
+  InstructionOperand inputs[3];
+  size_t input_count = 0;
+  InstructionOperand outputs[1];
 
-  ArchOpcode opcode = kArchNop;
+  InstructionCode opcode = kArchNop;
   switch (load_rep.representation()) {
     case MachineRepresentation::kFloat32:
       opcode = kArmVldrF32;
@@ -339,13 +376,24 @@
       return;
   }
 
+  outputs[0] = g.DefineAsRegister(node);
+  inputs[0] = g.UseRegister(base);
+
   if (g.CanBeImmediate(index, opcode)) {
-    Emit(opcode | AddressingModeField::encode(kMode_Offset_RI),
-         g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
+    input_count = 2;
+    inputs[1] = g.UseImmediate(index);
+    opcode |= AddressingModeField::encode(kMode_Offset_RI);
+  } else if ((opcode == kArmLdr) &&
+             TryMatchLSLImmediate(this, &opcode, index, &inputs[1],
+                                  &inputs[2])) {
+    input_count = 3;
   } else {
-    Emit(opcode | AddressingModeField::encode(kMode_Offset_RR),
-         g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
+    input_count = 2;
+    inputs[1] = g.UseRegister(index);
+    opcode |= AddressingModeField::encode(kMode_Offset_RR);
   }
+
+  Emit(opcode, arraysize(outputs), outputs, input_count, inputs);
 }
 
 
@@ -397,7 +445,10 @@
     code |= MiscField::encode(static_cast<int>(record_write_mode));
     Emit(code, 0, nullptr, input_count, inputs, temp_count, temps);
   } else {
-    ArchOpcode opcode = kArchNop;
+    InstructionOperand inputs[4];
+    size_t input_count = 0;
+
+    InstructionCode opcode = kArchNop;
     switch (rep) {
       case MachineRepresentation::kFloat32:
         opcode = kArmVstrF32;
@@ -423,13 +474,23 @@
         return;
     }
 
+    inputs[0] = g.UseRegister(value);
+    inputs[1] = g.UseRegister(base);
+
     if (g.CanBeImmediate(index, opcode)) {
-      Emit(opcode | AddressingModeField::encode(kMode_Offset_RI), g.NoOutput(),
-           g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value));
+      input_count = 3;
+      inputs[2] = g.UseImmediate(index);
+      opcode |= AddressingModeField::encode(kMode_Offset_RI);
+    } else if ((opcode == kArmStr) &&
+               TryMatchLSLImmediate(this, &opcode, index, &inputs[2],
+                                    &inputs[3])) {
+      input_count = 4;
     } else {
-      Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), g.NoOutput(),
-           g.UseRegister(base), g.UseRegister(index), g.UseRegister(value));
+      input_count = 3;
+      inputs[2] = g.UseRegister(index);
+      opcode |= AddressingModeField::encode(kMode_Offset_RR);
     }
+    Emit(opcode, 0, nullptr, input_count, inputs);
   }
 }
 
@@ -1022,7 +1083,7 @@
 void InstructionSelector::VisitInt32Sub(Node* node) {
   ArmOperandGenerator g(this);
   Int32BinopMatcher m(node);
-  if (IsSupported(MLS) && m.right().IsInt32Mul() &&
+  if (IsSupported(ARMv7) && m.right().IsInt32Mul() &&
       CanCover(node, m.right().node())) {
     Int32BinopMatcher mright(m.right().node());
     Emit(kArmMls, g.DefineAsRegister(node), g.UseRegister(mright.left().node()),
@@ -1142,31 +1203,22 @@
   VisitRR(this, kArmVcvtF32F64, node);
 }
 
-
-void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
-  switch (TruncationModeOf(node->op())) {
-    case TruncationMode::kJavaScript:
-      return VisitRR(this, kArchTruncateDoubleToI, node);
-    case TruncationMode::kRoundToZero:
-      return VisitRR(this, kArmVcvtS32F64, node);
-  }
-  UNREACHABLE();
+void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
+  VisitRR(this, kArchTruncateDoubleToI, node);
 }
 
+void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
+  VisitRR(this, kArmVcvtS32F64, node);
+}
 
 void InstructionSelector::VisitBitcastFloat32ToInt32(Node* node) {
-  VisitRR(this, kArmVmovLowU32F64, node);
+  VisitRR(this, kArmVmovU32F32, node);
 }
 
-
 void InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) {
-  ArmOperandGenerator g(this);
-  Emit(kArmVmovLowF64U32, g.DefineAsRegister(node),
-       ImmediateOperand(ImmediateOperand::INLINE, 0),
-       g.UseRegister(node->InputAt(0)));
+  VisitRR(this, kArmVmovF32U32, node);
 }
 
-
 void InstructionSelector::VisitFloat32Add(Node* node) {
   ArmOperandGenerator g(this);
   Float32BinopMatcher m(node);
@@ -1208,6 +1260,35 @@
   VisitRRR(this, kArmVaddF64, node);
 }
 
+namespace {
+void VisitFloat32SubHelper(InstructionSelector* selector, Node* node) {
+  ArmOperandGenerator g(selector);
+  Float32BinopMatcher m(node);
+  if (m.right().IsFloat32Mul() && selector->CanCover(node, m.right().node())) {
+    Float32BinopMatcher mright(m.right().node());
+    selector->Emit(kArmVmlsF32, g.DefineSameAsFirst(node),
+                   g.UseRegister(m.left().node()),
+                   g.UseRegister(mright.left().node()),
+                   g.UseRegister(mright.right().node()));
+    return;
+  }
+  VisitRRR(selector, kArmVsubF32, node);
+}
+
+void VisitFloat64SubHelper(InstructionSelector* selector, Node* node) {
+  ArmOperandGenerator g(selector);
+  Float64BinopMatcher m(node);
+  if (m.right().IsFloat64Mul() && selector->CanCover(node, m.right().node())) {
+    Float64BinopMatcher mright(m.right().node());
+    selector->Emit(kArmVmlsF64, g.DefineSameAsFirst(node),
+                   g.UseRegister(m.left().node()),
+                   g.UseRegister(mright.left().node()),
+                   g.UseRegister(mright.right().node()));
+    return;
+  }
+  VisitRRR(selector, kArmVsubF64, node);
+}
+}  // namespace
 
 void InstructionSelector::VisitFloat32Sub(Node* node) {
   ArmOperandGenerator g(this);
@@ -1217,16 +1298,12 @@
          g.UseRegister(m.right().node()));
     return;
   }
-  if (m.right().IsFloat32Mul() && CanCover(node, m.right().node())) {
-    Float32BinopMatcher mright(m.right().node());
-    Emit(kArmVmlsF32, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
-         g.UseRegister(mright.left().node()),
-         g.UseRegister(mright.right().node()));
-    return;
-  }
-  VisitRRR(this, kArmVsubF32, node);
+  VisitFloat32SubHelper(this, node);
 }
 
+void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
+  VisitFloat32SubHelper(this, node);
+}
 
 void InstructionSelector::VisitFloat64Sub(Node* node) {
   ArmOperandGenerator g(this);
@@ -1248,16 +1325,12 @@
          g.UseRegister(m.right().node()));
     return;
   }
-  if (m.right().IsFloat64Mul() && CanCover(node, m.right().node())) {
-    Float64BinopMatcher mright(m.right().node());
-    Emit(kArmVmlsF64, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
-         g.UseRegister(mright.left().node()),
-         g.UseRegister(mright.right().node()));
-    return;
-  }
-  VisitRRR(this, kArmVsubF64, node);
+  VisitFloat64SubHelper(this, node);
 }
 
+void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
+  VisitFloat64SubHelper(this, node);
+}
 
 void InstructionSelector::VisitFloat32Mul(Node* node) {
   VisitRRR(this, kArmVmulF32, node);
@@ -1285,18 +1358,29 @@
        g.UseFixed(node->InputAt(1), d1))->MarkAsCall();
 }
 
+void InstructionSelector::VisitFloat32Max(Node* node) {
+  DCHECK(IsSupported(ARMv8));
+  VisitRRR(this, kArmFloat32Max, node);
+}
 
-void InstructionSelector::VisitFloat32Max(Node* node) { UNREACHABLE(); }
+void InstructionSelector::VisitFloat64Max(Node* node) {
+  DCHECK(IsSupported(ARMv8));
+  VisitRRR(this, kArmFloat64Max, node);
+}
 
+void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
+  VisitRR(this, kArmFloat64SilenceNaN, node);
+}
 
-void InstructionSelector::VisitFloat64Max(Node* node) { UNREACHABLE(); }
+void InstructionSelector::VisitFloat32Min(Node* node) {
+  DCHECK(IsSupported(ARMv8));
+  VisitRRR(this, kArmFloat32Min, node);
+}
 
-
-void InstructionSelector::VisitFloat32Min(Node* node) { UNREACHABLE(); }
-
-
-void InstructionSelector::VisitFloat64Min(Node* node) { UNREACHABLE(); }
-
+void InstructionSelector::VisitFloat64Min(Node* node) {
+  DCHECK(IsSupported(ARMv8));
+  VisitRRR(this, kArmFloat64Min, node);
+}
 
 void InstructionSelector::VisitFloat32Abs(Node* node) {
   VisitRR(this, kArmVabsF32, node);
@@ -1307,7 +1391,6 @@
   VisitRR(this, kArmVabsF64, node);
 }
 
-
 void InstructionSelector::VisitFloat32Sqrt(Node* node) {
   VisitRR(this, kArmVsqrtF32, node);
 }
@@ -1362,6 +1445,28 @@
   VisitRR(this, kArmVrintnF64, node);
 }
 
+void InstructionSelector::VisitFloat32Neg(Node* node) {
+  VisitRR(this, kArmVnegF32, node);
+}
+
+void InstructionSelector::VisitFloat64Neg(Node* node) {
+  VisitRR(this, kArmVnegF64, node);
+}
+
+void InstructionSelector::VisitFloat64Ieee754Binop(Node* node,
+                                                   InstructionCode opcode) {
+  ArmOperandGenerator g(this);
+  Emit(opcode, g.DefineAsFixed(node, d0), g.UseFixed(node->InputAt(0), d0),
+       g.UseFixed(node->InputAt(1), d1))
+      ->MarkAsCall();
+}
+
+void InstructionSelector::VisitFloat64Ieee754Unop(Node* node,
+                                                  InstructionCode opcode) {
+  ArmOperandGenerator g(this);
+  Emit(opcode, g.DefineAsFixed(node, d0), g.UseFixed(node->InputAt(0), d0))
+      ->MarkAsCall();
+}
 
 void InstructionSelector::EmitPrepareArguments(
     ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
@@ -1807,13 +1912,72 @@
        g.UseRegister(right));
 }
 
+void InstructionSelector::VisitAtomicLoad(Node* node) {
+  LoadRepresentation load_rep = LoadRepresentationOf(node->op());
+  ArmOperandGenerator g(this);
+  Node* base = node->InputAt(0);
+  Node* index = node->InputAt(1);
+  ArchOpcode opcode = kArchNop;
+  switch (load_rep.representation()) {
+    case MachineRepresentation::kWord8:
+      opcode = load_rep.IsSigned() ? kAtomicLoadInt8 : kAtomicLoadUint8;
+      break;
+    case MachineRepresentation::kWord16:
+      opcode = load_rep.IsSigned() ? kAtomicLoadInt16 : kAtomicLoadUint16;
+      break;
+    case MachineRepresentation::kWord32:
+      opcode = kAtomicLoadWord32;
+      break;
+    default:
+      UNREACHABLE();
+      return;
+  }
+  Emit(opcode | AddressingModeField::encode(kMode_Offset_RR),
+       g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
+}
+
+void InstructionSelector::VisitAtomicStore(Node* node) {
+  MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
+  ArmOperandGenerator g(this);
+  Node* base = node->InputAt(0);
+  Node* index = node->InputAt(1);
+  Node* value = node->InputAt(2);
+  ArchOpcode opcode = kArchNop;
+  switch (rep) {
+    case MachineRepresentation::kWord8:
+      opcode = kAtomicStoreWord8;
+      break;
+    case MachineRepresentation::kWord16:
+      opcode = kAtomicStoreWord16;
+      break;
+    case MachineRepresentation::kWord32:
+      opcode = kAtomicStoreWord32;
+      break;
+    default:
+      UNREACHABLE();
+      return;
+  }
+
+  AddressingMode addressing_mode = kMode_Offset_RR;
+  InstructionOperand inputs[4];
+  size_t input_count = 0;
+  inputs[input_count++] = g.UseUniqueRegister(base);
+  inputs[input_count++] = g.UseUniqueRegister(index);
+  inputs[input_count++] = g.UseUniqueRegister(value);
+  InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
+  Emit(code, 0, nullptr, input_count, inputs);
+}
 
 // static
 MachineOperatorBuilder::Flags
 InstructionSelector::SupportedMachineOperatorFlags() {
-  MachineOperatorBuilder::Flags flags =
-      MachineOperatorBuilder::kInt32DivIsSafe |
-      MachineOperatorBuilder::kUint32DivIsSafe;
+  MachineOperatorBuilder::Flags flags;
+  if (CpuFeatures::IsSupported(SUDIV)) {
+    // The sdiv and udiv instructions correctly return 0 if the divisor is 0,
+    // but the fall-back implementation does not.
+    flags |= MachineOperatorBuilder::kInt32DivIsSafe |
+             MachineOperatorBuilder::kUint32DivIsSafe;
+  }
   if (CpuFeatures::IsSupported(ARMv7)) {
     flags |= MachineOperatorBuilder::kWord32ReverseBits;
   }
@@ -1826,11 +1990,24 @@
              MachineOperatorBuilder::kFloat64RoundTruncate |
              MachineOperatorBuilder::kFloat64RoundTiesAway |
              MachineOperatorBuilder::kFloat32RoundTiesEven |
-             MachineOperatorBuilder::kFloat64RoundTiesEven;
+             MachineOperatorBuilder::kFloat64RoundTiesEven |
+             MachineOperatorBuilder::kFloat32Min |
+             MachineOperatorBuilder::kFloat32Max |
+             MachineOperatorBuilder::kFloat64Min |
+             MachineOperatorBuilder::kFloat64Max |
+             MachineOperatorBuilder::kFloat32Neg |
+             MachineOperatorBuilder::kFloat64Neg;
   }
   return flags;
 }
 
+// static
+MachineOperatorBuilder::AlignmentRequirements
+InstructionSelector::AlignmentRequirements() {
+  return MachineOperatorBuilder::AlignmentRequirements::
+      FullUnalignedAccessSupport();
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/src/compiler/arm64/code-generator-arm64.cc b/src/compiler/arm64/code-generator-arm64.cc
index 456e7e7..479af7a 100644
--- a/src/compiler/arm64/code-generator-arm64.cc
+++ b/src/compiler/arm64/code-generator-arm64.cc
@@ -33,6 +33,24 @@
     return InputDoubleRegister(index);
   }
 
+  CPURegister InputFloat32OrZeroRegister(size_t index) {
+    if (instr_->InputAt(index)->IsImmediate()) {
+      DCHECK(bit_cast<int32_t>(InputFloat32(index)) == 0);
+      return wzr;
+    }
+    DCHECK(instr_->InputAt(index)->IsFPRegister());
+    return InputDoubleRegister(index).S();
+  }
+
+  CPURegister InputFloat64OrZeroRegister(size_t index) {
+    if (instr_->InputAt(index)->IsImmediate()) {
+      DCHECK(bit_cast<int64_t>(InputDouble(index)) == 0);
+      return xzr;
+    }
+    DCHECK(instr_->InputAt(index)->IsDoubleRegister());
+    return InputDoubleRegister(index);
+  }
+
   size_t OutputCount() { return instr_->OutputCount(); }
 
   DoubleRegister OutputFloat32Register() { return OutputDoubleRegister().S(); }
@@ -141,7 +159,6 @@
     const size_t index = *first_index;
     switch (AddressingModeField::decode(instr_->opcode())) {
       case kMode_None:
-      case kMode_Operand2_R_LSL_I:
       case kMode_Operand2_R_LSR_I:
       case kMode_Operand2_R_ASR_I:
       case kMode_Operand2_R_ROR_I:
@@ -150,6 +167,10 @@
       case kMode_Operand2_R_SXTB:
       case kMode_Operand2_R_SXTH:
         break;
+      case kMode_Operand2_R_LSL_I:
+        *first_index += 3;
+        return MemOperand(InputRegister(index + 0), InputRegister(index + 1),
+                          LSL, InputInt32(index + 2));
       case kMode_MRI:
         *first_index += 2;
         return MemOperand(InputRegister(index + 0), InputInt32(index + 1));
@@ -183,9 +204,19 @@
     Constant constant = ToConstant(operand);
     switch (constant.type()) {
       case Constant::kInt32:
-        return Operand(constant.ToInt32());
+        if (constant.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) {
+          return Operand(constant.ToInt32(), constant.rmode());
+        } else {
+          return Operand(constant.ToInt32());
+        }
       case Constant::kInt64:
-        return Operand(constant.ToInt64());
+        if (constant.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
+            constant.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE) {
+          return Operand(constant.ToInt64(), constant.rmode());
+        } else {
+          DCHECK(constant.rmode() != RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
+          return Operand(constant.ToInt64());
+        }
       case Constant::kFloat32:
         return Operand(
             isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED));
@@ -206,7 +237,7 @@
 
   MemOperand ToMemOperand(InstructionOperand* op, MacroAssembler* masm) const {
     DCHECK_NOT_NULL(op);
-    DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
+    DCHECK(op->IsStackSlot() || op->IsFPStackSlot());
     return SlotToMemOperand(AllocatedOperand::cast(op)->index(), masm);
   }
 
@@ -370,6 +401,17 @@
 
 }  // namespace
 
+#define ASSEMBLE_BOUNDS_CHECK(offset, length, out_of_bounds)   \
+  do {                                                         \
+    if (length.IsImmediate() &&                                \
+        base::bits::IsPowerOfTwo64(length.ImmediateValue())) { \
+      __ Tst(offset, ~(length.ImmediateValue() - 1));          \
+      __ B(ne, out_of_bounds);                                 \
+    } else {                                                   \
+      __ Cmp(offset, length);                                  \
+      __ B(hs, out_of_bounds);                                 \
+    }                                                          \
+  } while (0)
 
 #define ASSEMBLE_CHECKED_LOAD_FLOAT(width)                         \
   do {                                                             \
@@ -377,84 +419,72 @@
     auto buffer = i.InputRegister(0);                              \
     auto offset = i.InputRegister32(1);                            \
     auto length = i.InputOperand32(2);                             \
-    __ Cmp(offset, length);                                        \
     auto ool = new (zone()) OutOfLineLoadNaN##width(this, result); \
-    __ B(hs, ool->entry());                                        \
+    ASSEMBLE_BOUNDS_CHECK(offset, length, ool->entry());           \
     __ Ldr(result, MemOperand(buffer, offset, UXTW));              \
     __ Bind(ool->exit());                                          \
   } while (0)
 
-
 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr)             \
   do {                                                       \
     auto result = i.OutputRegister32();                      \
     auto buffer = i.InputRegister(0);                        \
     auto offset = i.InputRegister32(1);                      \
     auto length = i.InputOperand32(2);                       \
-    __ Cmp(offset, length);                                  \
     auto ool = new (zone()) OutOfLineLoadZero(this, result); \
-    __ B(hs, ool->entry());                                  \
+    ASSEMBLE_BOUNDS_CHECK(offset, length, ool->entry());     \
     __ asm_instr(result, MemOperand(buffer, offset, UXTW));  \
     __ Bind(ool->exit());                                    \
   } while (0)
 
-
 #define ASSEMBLE_CHECKED_LOAD_INTEGER_64(asm_instr)          \
   do {                                                       \
     auto result = i.OutputRegister();                        \
     auto buffer = i.InputRegister(0);                        \
     auto offset = i.InputRegister32(1);                      \
     auto length = i.InputOperand32(2);                       \
-    __ Cmp(offset, length);                                  \
     auto ool = new (zone()) OutOfLineLoadZero(this, result); \
-    __ B(hs, ool->entry());                                  \
+    ASSEMBLE_BOUNDS_CHECK(offset, length, ool->entry());     \
     __ asm_instr(result, MemOperand(buffer, offset, UXTW));  \
     __ Bind(ool->exit());                                    \
   } while (0)
 
-
-#define ASSEMBLE_CHECKED_STORE_FLOAT(width)          \
-  do {                                               \
-    auto buffer = i.InputRegister(0);                \
-    auto offset = i.InputRegister32(1);              \
-    auto length = i.InputOperand32(2);               \
-    auto value = i.InputFloat##width##Register(3);   \
-    __ Cmp(offset, length);                          \
-    Label done;                                      \
-    __ B(hs, &done);                                 \
-    __ Str(value, MemOperand(buffer, offset, UXTW)); \
-    __ Bind(&done);                                  \
+#define ASSEMBLE_CHECKED_STORE_FLOAT(width)              \
+  do {                                                   \
+    auto buffer = i.InputRegister(0);                    \
+    auto offset = i.InputRegister32(1);                  \
+    auto length = i.InputOperand32(2);                   \
+    auto value = i.InputFloat##width##OrZeroRegister(3); \
+    Label done;                                          \
+    ASSEMBLE_BOUNDS_CHECK(offset, length, &done);        \
+    __ Str(value, MemOperand(buffer, offset, UXTW));     \
+    __ Bind(&done);                                      \
   } while (0)
 
-
 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr)          \
   do {                                                     \
     auto buffer = i.InputRegister(0);                      \
     auto offset = i.InputRegister32(1);                    \
     auto length = i.InputOperand32(2);                     \
-    auto value = i.InputRegister32(3);                     \
-    __ Cmp(offset, length);                                \
+    auto value = i.InputOrZeroRegister32(3);               \
     Label done;                                            \
-    __ B(hs, &done);                                       \
+    ASSEMBLE_BOUNDS_CHECK(offset, length, &done);          \
     __ asm_instr(value, MemOperand(buffer, offset, UXTW)); \
     __ Bind(&done);                                        \
   } while (0)
 
-
 #define ASSEMBLE_CHECKED_STORE_INTEGER_64(asm_instr)       \
   do {                                                     \
     auto buffer = i.InputRegister(0);                      \
     auto offset = i.InputRegister32(1);                    \
     auto length = i.InputOperand32(2);                     \
-    auto value = i.InputRegister(3);                       \
-    __ Cmp(offset, length);                                \
+    auto value = i.InputOrZeroRegister64(3);               \
     Label done;                                            \
-    __ B(hs, &done);                                       \
+    ASSEMBLE_BOUNDS_CHECK(offset, length, &done);          \
     __ asm_instr(value, MemOperand(buffer, offset, UXTW)); \
     __ Bind(&done);                                        \
   } while (0)
 
-
 #define ASSEMBLE_SHIFT(asm_instr, width)                                    \
   do {                                                                      \
     if (instr->InputAt(1)->IsRegister()) {                                  \
@@ -468,6 +498,35 @@
     }                                                                       \
   } while (0)
 
+#define ASSEMBLE_ATOMIC_LOAD_INTEGER(asm_instr)                       \
+  do {                                                                \
+    __ asm_instr(i.OutputRegister(),                                  \
+                 MemOperand(i.InputRegister(0), i.InputRegister(1))); \
+    __ Dmb(InnerShareable, BarrierAll);                               \
+  } while (0)
+
+#define ASSEMBLE_ATOMIC_STORE_INTEGER(asm_instr)                      \
+  do {                                                                \
+    __ Dmb(InnerShareable, BarrierAll);                               \
+    __ asm_instr(i.InputRegister(2),                                  \
+                 MemOperand(i.InputRegister(0), i.InputRegister(1))); \
+    __ Dmb(InnerShareable, BarrierAll);                               \
+  } while (0)
+
+#define ASSEMBLE_IEEE754_BINOP(name)                                          \
+  do {                                                                        \
+    FrameScope scope(masm(), StackFrame::MANUAL);                             \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \
+                     0, 2);                                                   \
+  } while (0)
+
+#define ASSEMBLE_IEEE754_UNOP(name)                                           \
+  do {                                                                        \
+    FrameScope scope(masm(), StackFrame::MANUAL);                             \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \
+                     0, 1);                                                   \
+  } while (0)
+
 void CodeGenerator::AssembleDeconstructFrame() {
   const CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
   if (descriptor->IsCFunctionCall() || descriptor->UseNativeStack()) {
@@ -526,7 +585,8 @@
 }
 
 // Assembles an instruction after register allocation, producing machine code.
-void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
+CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
+    Instruction* instr) {
   Arm64OperandConverter i(this, instr);
   InstructionCode opcode = instr->opcode();
   ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode);
@@ -577,6 +637,14 @@
       frame_access_state()->ClearSPDelta();
       break;
     }
+    case kArchTailCallAddress: {
+      int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
+      AssembleDeconstructActivationRecord(stack_param_delta);
+      CHECK(!instr->InputAt(0)->IsImmediate());
+      __ Jump(i.InputRegister(0));
+      frame_access_state()->ClearSPDelta();
+      break;
+    }
     case kArchCallJSFunction: {
       EnsureSpaceForLazyDeopt();
       Register func = i.InputRegister(0);
@@ -661,6 +729,14 @@
     case kArchLookupSwitch:
       AssembleArchLookupSwitch(instr);
       break;
+    case kArchDebugBreak:
+      __ Debug("kArchDebugBreak", 0, BREAK);
+      break;
+    case kArchComment: {
+      Address comment_string = i.InputExternalReference(0).address();
+      __ RecordComment(reinterpret_cast<const char*>(comment_string));
+      break;
+    }
     case kArchNop:
     case kArchThrowTerminator:
       // don't emit code for nops.
@@ -670,7 +746,9 @@
           BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
       Deoptimizer::BailoutType bailout_type =
           Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
-      AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      CodeGenResult result =
+          AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      if (result != kSuccess) return result;
       break;
     }
     case kArchRet:
@@ -729,6 +807,45 @@
       __ Add(i.OutputRegister(0), base, Operand(offset.offset()));
       break;
     }
+    case kIeee754Float64Atan:
+      ASSEMBLE_IEEE754_UNOP(atan);
+      break;
+    case kIeee754Float64Atan2:
+      ASSEMBLE_IEEE754_BINOP(atan2);
+      break;
+    case kIeee754Float64Cos:
+      ASSEMBLE_IEEE754_UNOP(cos);
+      break;
+    case kIeee754Float64Cbrt:
+      ASSEMBLE_IEEE754_UNOP(cbrt);
+      break;
+    case kIeee754Float64Exp:
+      ASSEMBLE_IEEE754_UNOP(exp);
+      break;
+    case kIeee754Float64Expm1:
+      ASSEMBLE_IEEE754_UNOP(expm1);
+      break;
+    case kIeee754Float64Atanh:
+      ASSEMBLE_IEEE754_UNOP(atanh);
+      break;
+    case kIeee754Float64Log:
+      ASSEMBLE_IEEE754_UNOP(log);
+      break;
+    case kIeee754Float64Log1p:
+      ASSEMBLE_IEEE754_UNOP(log1p);
+      break;
+    case kIeee754Float64Log2:
+      ASSEMBLE_IEEE754_UNOP(log2);
+      break;
+    case kIeee754Float64Log10:
+      ASSEMBLE_IEEE754_UNOP(log10);
+      break;
+    case kIeee754Float64Sin:
+      ASSEMBLE_IEEE754_UNOP(sin);
+      break;
+    case kIeee754Float64Tan:
+      ASSEMBLE_IEEE754_UNOP(tan);
+      break;
     case kArm64Float32RoundDown:
       __ Frintm(i.OutputFloat32Register(), i.InputFloat32Register(0));
       break;
@@ -983,6 +1100,7 @@
       // Pseudo instructions turned into tbz/tbnz in AssembleArchBranch.
       break;
     case kArm64CompareAndBranch32:
+    case kArm64CompareAndBranch:
       // Pseudo instruction turned into cbz/cbnz in AssembleArchBranch.
       break;
     case kArm64ClaimCSP: {
@@ -1038,7 +1156,7 @@
       Register prev = __ StackPointer();
       __ SetStackPointer(arch_opcode == kArm64PokeCSP ? csp : jssp);
       Operand operand(i.InputInt32(1) * kPointerSize);
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ Poke(i.InputFloat64Register(0), operand);
       } else {
         __ Poke(i.InputRegister(0), operand);
@@ -1048,7 +1166,7 @@
     }
     case kArm64PokePair: {
       int slot = i.InputInt32(2) - 1;
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ PokePair(i.InputFloat64Register(1), i.InputFloat64Register(0),
                     slot * kPointerSize);
       } else {
@@ -1088,7 +1206,7 @@
       __ Tst(i.InputRegister32(0), i.InputOperand32(1));
       break;
     case kArm64Float32Cmp:
-      if (instr->InputAt(1)->IsDoubleRegister()) {
+      if (instr->InputAt(1)->IsFPRegister()) {
         __ Fcmp(i.InputFloat32Register(0), i.InputFloat32Register(1));
       } else {
         DCHECK(instr->InputAt(1)->IsImmediate());
@@ -1128,11 +1246,14 @@
     case kArm64Float32Abs:
       __ Fabs(i.OutputFloat32Register(), i.InputFloat32Register(0));
       break;
+    case kArm64Float32Neg:
+      __ Fneg(i.OutputFloat32Register(), i.InputFloat32Register(0));
+      break;
     case kArm64Float32Sqrt:
       __ Fsqrt(i.OutputFloat32Register(), i.InputFloat32Register(0));
       break;
     case kArm64Float64Cmp:
-      if (instr->InputAt(1)->IsDoubleRegister()) {
+      if (instr->InputAt(1)->IsFPRegister()) {
         __ Fcmp(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
       } else {
         DCHECK(instr->InputAt(1)->IsImmediate());
@@ -1305,6 +1426,9 @@
     case kArm64Float64MoveU64:
       __ Fmov(i.OutputFloat64Register(), i.InputRegister(0));
       break;
+    case kArm64Float64SilenceNaN:
+      __ CanonicalizeNaN(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
+      break;
     case kArm64U64MoveFloat64:
       __ Fmov(i.OutputRegister(), i.InputDoubleRegister(0));
       break;
@@ -1315,7 +1439,7 @@
       __ Ldrsb(i.OutputRegister(), i.MemoryOperand());
       break;
     case kArm64Strb:
-      __ Strb(i.InputRegister(2), i.MemoryOperand());
+      __ Strb(i.InputOrZeroRegister64(0), i.MemoryOperand(1));
       break;
     case kArm64Ldrh:
       __ Ldrh(i.OutputRegister(), i.MemoryOperand());
@@ -1324,31 +1448,31 @@
       __ Ldrsh(i.OutputRegister(), i.MemoryOperand());
       break;
     case kArm64Strh:
-      __ Strh(i.InputRegister(2), i.MemoryOperand());
+      __ Strh(i.InputOrZeroRegister64(0), i.MemoryOperand(1));
       break;
     case kArm64LdrW:
       __ Ldr(i.OutputRegister32(), i.MemoryOperand());
       break;
     case kArm64StrW:
-      __ Str(i.InputRegister32(2), i.MemoryOperand());
+      __ Str(i.InputOrZeroRegister32(0), i.MemoryOperand(1));
       break;
     case kArm64Ldr:
       __ Ldr(i.OutputRegister(), i.MemoryOperand());
       break;
     case kArm64Str:
-      __ Str(i.InputRegister(2), i.MemoryOperand());
+      __ Str(i.InputOrZeroRegister64(0), i.MemoryOperand(1));
       break;
     case kArm64LdrS:
       __ Ldr(i.OutputDoubleRegister().S(), i.MemoryOperand());
       break;
     case kArm64StrS:
-      __ Str(i.InputDoubleRegister(2).S(), i.MemoryOperand());
+      __ Str(i.InputFloat32OrZeroRegister(0), i.MemoryOperand(1));
       break;
     case kArm64LdrD:
       __ Ldr(i.OutputDoubleRegister(), i.MemoryOperand());
       break;
     case kArm64StrD:
-      __ Str(i.InputDoubleRegister(2), i.MemoryOperand());
+      __ Str(i.InputFloat64OrZeroRegister(0), i.MemoryOperand(1));
       break;
     case kCheckedLoadInt8:
       ASSEMBLE_CHECKED_LOAD_INTEGER(Ldrsb);
@@ -1392,7 +1516,37 @@
     case kCheckedStoreFloat64:
       ASSEMBLE_CHECKED_STORE_FLOAT(64);
       break;
+    case kAtomicLoadInt8:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(Ldrsb);
+      break;
+    case kAtomicLoadUint8:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(Ldrb);
+      break;
+    case kAtomicLoadInt16:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(Ldrsh);
+      break;
+    case kAtomicLoadUint16:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(Ldrh);
+      break;
+    case kAtomicLoadWord32:
+      __ Ldr(i.OutputRegister32(),
+             MemOperand(i.InputRegister(0), i.InputRegister(1)));
+      __ Dmb(InnerShareable, BarrierAll);
+      break;
+    case kAtomicStoreWord8:
+      ASSEMBLE_ATOMIC_STORE_INTEGER(Strb);
+      break;
+    case kAtomicStoreWord16:
+      ASSEMBLE_ATOMIC_STORE_INTEGER(Strh);
+      break;
+    case kAtomicStoreWord32:
+      __ Dmb(InnerShareable, BarrierAll);
+      __ Str(i.InputRegister32(2),
+             MemOperand(i.InputRegister(0), i.InputRegister(1)));
+      __ Dmb(InnerShareable, BarrierAll);
+      break;
   }
+  return kSuccess;
 }  // NOLINT(readability/fn_size)
 
 
@@ -1415,6 +1569,17 @@
       default:
         UNREACHABLE();
     }
+  } else if (opcode == kArm64CompareAndBranch) {
+    switch (condition) {
+      case kEqual:
+        __ Cbz(i.InputRegister64(0), tlabel);
+        break;
+      case kNotEqual:
+        __ Cbnz(i.InputRegister64(0), tlabel);
+        break;
+      default:
+        UNREACHABLE();
+    }
   } else if (opcode == kArm64TestAndBranch32) {
     switch (condition) {
       case kEqual:
@@ -1495,30 +1660,49 @@
   __ EndBlockPools();
 }
 
-
-void CodeGenerator::AssembleDeoptimizerCall(
+CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
     int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
   Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
       isolate(), deoptimization_id, bailout_type);
+  if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
   __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
+  return kSuccess;
 }
 
-void CodeGenerator::AssembleSetupStackPointer() {
-  const CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
+void CodeGenerator::FinishFrame(Frame* frame) {
+  frame->AlignFrame(16);
+  CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
+
   if (descriptor->UseNativeStack() || descriptor->IsCFunctionCall()) {
     __ SetStackPointer(csp);
   } else {
     __ SetStackPointer(jssp);
   }
+
+  // Save FP registers.
+  CPURegList saves_fp = CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
+                                   descriptor->CalleeSavedFPRegisters());
+  int saved_count = saves_fp.Count();
+  if (saved_count != 0) {
+    DCHECK(saves_fp.list() == CPURegList::GetCalleeSavedFP().list());
+    frame->AllocateSavedCalleeRegisterSlots(saved_count *
+                                            (kDoubleSize / kPointerSize));
+  }
+
+  CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
+                                descriptor->CalleeSavedRegisters());
+  saved_count = saves.Count();
+  if (saved_count != 0) {
+    frame->AllocateSavedCalleeRegisterSlots(saved_count);
+  }
 }
 
-void CodeGenerator::AssemblePrologue() {
+void CodeGenerator::AssembleConstructFrame() {
   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
   if (descriptor->UseNativeStack()) {
     __ AssertCspAligned();
   }
 
-  int stack_shrink_slots = frame()->GetSpillSlotCount();
   if (frame_access_state()->has_frame()) {
     if (descriptor->IsJSFunctionCall()) {
       DCHECK(!descriptor->UseNativeStack());
@@ -1527,7 +1711,7 @@
       if (descriptor->IsCFunctionCall()) {
         __ Push(lr, fp);
         __ Mov(fp, masm_.StackPointer());
-        __ Claim(stack_shrink_slots);
+        __ Claim(frame()->GetSpillSlotCount());
       } else {
         __ StubPrologue(info()->GetOutputStackFrameType(),
                         frame()->GetTotalFrameSlotCount());
@@ -1535,6 +1719,8 @@
     }
   }
 
+  int shrink_slots = frame()->GetSpillSlotCount();
+
   if (info()->is_osr()) {
     // TurboFan OSR-compiled functions cannot be entered directly.
     __ Abort(kShouldNotDirectlyEnterOsrFunction);
@@ -1545,11 +1731,11 @@
     // remaining stack slots.
     if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
     osr_pc_offset_ = __ pc_offset();
-    stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
+    shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
   }
 
   if (descriptor->IsJSFunctionCall()) {
-    __ Claim(stack_shrink_slots);
+    __ Claim(shrink_slots);
   }
 
   // Save FP registers.
@@ -1559,8 +1745,6 @@
   if (saved_count != 0) {
     DCHECK(saves_fp.list() == CPURegList::GetCalleeSavedFP().list());
     __ PushCPURegList(saves_fp);
-    frame()->AllocateSavedCalleeRegisterSlots(saved_count *
-                                              (kDoubleSize / kPointerSize));
   }
   // Save registers.
   // TODO(palfia): TF save list is not in sync with
@@ -1571,7 +1755,6 @@
   saved_count = saves.Count();
   if (saved_count != 0) {
     __ PushCPURegList(saves);
-    frame()->AllocateSavedCalleeRegisterSlots(saved_count);
   }
 }
 
@@ -1668,11 +1851,11 @@
         __ Str(dst, g.ToMemOperand(destination, masm()));
       }
     } else if (src.type() == Constant::kFloat32) {
-      if (destination->IsDoubleRegister()) {
+      if (destination->IsFPRegister()) {
         FPRegister dst = g.ToDoubleRegister(destination).S();
         __ Fmov(dst, src.ToFloat32());
       } else {
-        DCHECK(destination->IsDoubleStackSlot());
+        DCHECK(destination->IsFPStackSlot());
         UseScratchRegisterScope scope(masm());
         FPRegister temp = scope.AcquireS();
         __ Fmov(temp, src.ToFloat32());
@@ -1680,30 +1863,30 @@
       }
     } else {
       DCHECK_EQ(Constant::kFloat64, src.type());
-      if (destination->IsDoubleRegister()) {
+      if (destination->IsFPRegister()) {
         FPRegister dst = g.ToDoubleRegister(destination);
         __ Fmov(dst, src.ToFloat64());
       } else {
-        DCHECK(destination->IsDoubleStackSlot());
+        DCHECK(destination->IsFPStackSlot());
         UseScratchRegisterScope scope(masm());
         FPRegister temp = scope.AcquireD();
         __ Fmov(temp, src.ToFloat64());
         __ Str(temp, g.ToMemOperand(destination, masm()));
       }
     }
-  } else if (source->IsDoubleRegister()) {
+  } else if (source->IsFPRegister()) {
     FPRegister src = g.ToDoubleRegister(source);
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       FPRegister dst = g.ToDoubleRegister(destination);
       __ Fmov(dst, src);
     } else {
-      DCHECK(destination->IsDoubleStackSlot());
+      DCHECK(destination->IsFPStackSlot());
       __ Str(src, g.ToMemOperand(destination, masm()));
     }
-  } else if (source->IsDoubleStackSlot()) {
-    DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
+  } else if (source->IsFPStackSlot()) {
+    DCHECK(destination->IsFPRegister() || destination->IsFPStackSlot());
     MemOperand src = g.ToMemOperand(source, masm());
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       __ Ldr(g.ToDoubleRegister(destination), src);
     } else {
       UseScratchRegisterScope scope(masm());
@@ -1739,7 +1922,7 @@
       __ Ldr(src, dst);
       __ Str(temp, dst);
     }
-  } else if (source->IsStackSlot() || source->IsDoubleStackSlot()) {
+  } else if (source->IsStackSlot() || source->IsFPStackSlot()) {
     UseScratchRegisterScope scope(masm());
     DoubleRegister temp_0 = scope.AcquireD();
     DoubleRegister temp_1 = scope.AcquireD();
@@ -1749,17 +1932,17 @@
     __ Ldr(temp_1, dst);
     __ Str(temp_0, dst);
     __ Str(temp_1, src);
-  } else if (source->IsDoubleRegister()) {
+  } else if (source->IsFPRegister()) {
     UseScratchRegisterScope scope(masm());
     FPRegister temp = scope.AcquireD();
     FPRegister src = g.ToDoubleRegister(source);
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       FPRegister dst = g.ToDoubleRegister(destination);
       __ Fmov(temp, src);
       __ Fmov(src, dst);
       __ Fmov(dst, temp);
     } else {
-      DCHECK(destination->IsDoubleStackSlot());
+      DCHECK(destination->IsFPStackSlot());
       MemOperand dst = g.ToMemOperand(destination, masm());
       __ Fmov(temp, src);
       __ Ldr(src, dst);
@@ -1778,9 +1961,6 @@
 }
 
 
-void CodeGenerator::AddNopForSmiCodeInlining() { __ movz(xzr, 0); }
-
-
 void CodeGenerator::EnsureSpaceForLazyDeopt() {
   if (!info()->ShouldEnsureSpaceForLazyDeopt()) {
     return;
diff --git a/src/compiler/arm64/instruction-codes-arm64.h b/src/compiler/arm64/instruction-codes-arm64.h
index f03c2fb..2b5fe33 100644
--- a/src/compiler/arm64/instruction-codes-arm64.h
+++ b/src/compiler/arm64/instruction-codes-arm64.h
@@ -78,6 +78,7 @@
   V(Arm64TestAndBranch32)          \
   V(Arm64TestAndBranch)            \
   V(Arm64CompareAndBranch32)       \
+  V(Arm64CompareAndBranch)         \
   V(Arm64ClaimCSP)                 \
   V(Arm64ClaimJSSP)                \
   V(Arm64PokeCSP)                  \
@@ -91,6 +92,7 @@
   V(Arm64Float32Max)               \
   V(Arm64Float32Min)               \
   V(Arm64Float32Abs)               \
+  V(Arm64Float32Neg)               \
   V(Arm64Float32Sqrt)              \
   V(Arm64Float32RoundDown)         \
   V(Arm64Float64Cmp)               \
@@ -112,6 +114,7 @@
   V(Arm64Float64RoundTruncate)     \
   V(Arm64Float32RoundTiesEven)     \
   V(Arm64Float64RoundTiesEven)     \
+  V(Arm64Float64SilenceNaN)        \
   V(Arm64Float32ToFloat64)         \
   V(Arm64Float64ToFloat32)         \
   V(Arm64Float32ToInt32)           \
diff --git a/src/compiler/arm64/instruction-scheduler-arm64.cc b/src/compiler/arm64/instruction-scheduler-arm64.cc
index ca37299..f3797c2 100644
--- a/src/compiler/arm64/instruction-scheduler-arm64.cc
+++ b/src/compiler/arm64/instruction-scheduler-arm64.cc
@@ -85,6 +85,7 @@
     case kArm64Float32Max:
     case kArm64Float32Min:
     case kArm64Float32Abs:
+    case kArm64Float32Neg:
     case kArm64Float32Sqrt:
     case kArm64Float32RoundDown:
     case kArm64Float64Cmp:
@@ -130,11 +131,13 @@
     case kArm64Float64InsertHighWord32:
     case kArm64Float64MoveU64:
     case kArm64U64MoveFloat64:
+    case kArm64Float64SilenceNaN:
       return kNoOpcodeFlags;
 
     case kArm64TestAndBranch32:
     case kArm64TestAndBranch:
     case kArm64CompareAndBranch32:
+    case kArm64CompareAndBranch:
       return kIsBlockTerminator;
 
     case kArm64LdrS:
@@ -176,23 +179,46 @@
   // Basic latency modeling for arm64 instructions. They have been determined
   // in an empirical way.
   switch (instr->arch_opcode()) {
-    case kArm64Float32ToFloat64:
-    case kArm64Float64ToFloat32:
-    case kArm64Float64ToInt32:
-    case kArm64Float64ToUint32:
-    case kArm64Int32ToFloat64:
-    case kArm64Uint32ToFloat64:
-      return 3;
+    case kArm64Add:
+    case kArm64Add32:
+    case kArm64And:
+    case kArm64And32:
+    case kArm64Bic:
+    case kArm64Bic32:
+    case kArm64Cmn:
+    case kArm64Cmn32:
+    case kArm64Cmp:
+    case kArm64Cmp32:
+    case kArm64Eon:
+    case kArm64Eon32:
+    case kArm64Eor:
+    case kArm64Eor32:
+    case kArm64Not:
+    case kArm64Not32:
+    case kArm64Or:
+    case kArm64Or32:
+    case kArm64Orn:
+    case kArm64Orn32:
+    case kArm64Sub:
+    case kArm64Sub32:
+    case kArm64Tst:
+    case kArm64Tst32:
+      if (instr->addressing_mode() != kMode_None) {
+        return 3;
+      } else {
+        return 1;
+      }
 
-    case kArm64Float64Add:
-    case kArm64Float64Sub:
-      return 2;
-
-    case kArm64Float64Mul:
-      return 3;
-
-    case kArm64Float64Div:
-      return 6;
+    case kArm64Clz:
+    case kArm64Clz32:
+    case kArm64Sbfx32:
+    case kArm64Sxtb32:
+    case kArm64Sxth32:
+    case kArm64Sxtw:
+    case kArm64Ubfiz32:
+    case kArm64Ubfx:
+    case kArm64Ubfx32:
+      return 1;
 
     case kArm64Lsl:
     case kArm64Lsl32:
@@ -202,7 +228,17 @@
     case kArm64Asr32:
     case kArm64Ror:
     case kArm64Ror32:
-      return 3;
+      return 1;
+
+    case kArm64Ldr:
+    case kArm64LdrD:
+    case kArm64LdrS:
+    case kArm64LdrW:
+    case kArm64Ldrb:
+    case kArm64Ldrh:
+    case kArm64Ldrsb:
+    case kArm64Ldrsh:
+      return 11;
 
     case kCheckedLoadInt8:
     case kCheckedLoadUint8:
@@ -212,18 +248,95 @@
     case kCheckedLoadWord64:
     case kCheckedLoadFloat32:
     case kCheckedLoadFloat64:
-    case kArm64LdrS:
-    case kArm64LdrD:
-    case kArm64Ldrb:
-    case kArm64Ldrsb:
-    case kArm64Ldrh:
-    case kArm64Ldrsh:
-    case kArm64LdrW:
-    case kArm64Ldr:
+      return 5;
+
+    case kArm64Str:
+    case kArm64StrD:
+    case kArm64StrS:
+    case kArm64StrW:
+    case kArm64Strb:
+    case kArm64Strh:
+      return 1;
+
+    case kCheckedStoreWord8:
+    case kCheckedStoreWord16:
+    case kCheckedStoreWord32:
+    case kCheckedStoreWord64:
+    case kCheckedStoreFloat32:
+    case kCheckedStoreFloat64:
+      return 1;
+
+    case kArm64Madd32:
+    case kArm64Mneg32:
+    case kArm64Msub32:
+    case kArm64Mul32:
+      return 3;
+
+    case kArm64Madd:
+    case kArm64Mneg:
+    case kArm64Msub:
+    case kArm64Mul:
+      return 5;
+
+    case kArm64Idiv32:
+    case kArm64Udiv32:
+      return 12;
+
+    case kArm64Idiv:
+    case kArm64Udiv:
+      return 20;
+
+    case kArm64Float32Add:
+    case kArm64Float32Sub:
+    case kArm64Float64Add:
+    case kArm64Float64Sub:
+      return 5;
+
+    case kArm64Float32Abs:
+    case kArm64Float32Cmp:
+    case kArm64Float32Neg:
+    case kArm64Float64Abs:
+    case kArm64Float64Cmp:
+    case kArm64Float64Neg:
+      return 3;
+
+    case kArm64Float32Div:
+    case kArm64Float32Sqrt:
+      return 12;
+
+    case kArm64Float64Div:
+    case kArm64Float64Sqrt:
+      return 19;
+
+    case kArm64Float32RoundDown:
+    case kArm64Float32RoundTiesEven:
+    case kArm64Float32RoundTruncate:
+    case kArm64Float32RoundUp:
+    case kArm64Float64RoundDown:
+    case kArm64Float64RoundTiesAway:
+    case kArm64Float64RoundTiesEven:
+    case kArm64Float64RoundTruncate:
+    case kArm64Float64RoundUp:
+      return 5;
+
+    case kArm64Float32ToFloat64:
+    case kArm64Float64ToFloat32:
+    case kArm64Float64ToInt32:
+    case kArm64Float64ToUint32:
+    case kArm64Float32ToInt64:
+    case kArm64Float64ToInt64:
+    case kArm64Float32ToUint64:
+    case kArm64Float64ToUint64:
+    case kArm64Int32ToFloat64:
+    case kArm64Int64ToFloat32:
+    case kArm64Int64ToFloat64:
+    case kArm64Uint32ToFloat64:
+    case kArm64Uint64ToFloat32:
+    case kArm64Uint64ToFloat64:
       return 5;
 
     default:
-      return 1;
+      return 2;
   }
 }
 
diff --git a/src/compiler/arm64/instruction-selector-arm64.cc b/src/compiler/arm64/instruction-selector-arm64.cc
index d90deae..637acac 100644
--- a/src/compiler/arm64/instruction-selector-arm64.cc
+++ b/src/compiler/arm64/instruction-selector-arm64.cc
@@ -40,7 +40,9 @@
   // Use the zero register if the node has the immediate value zero, otherwise
   // assign a register.
   InstructionOperand UseRegisterOrImmediateZero(Node* node) {
-    if (IsIntegerConstant(node) && (GetIntegerConstantValue(node) == 0)) {
+    if ((IsIntegerConstant(node) && (GetIntegerConstantValue(node) == 0)) ||
+        (IsFloatConstant(node) &&
+         (bit_cast<int64_t>(GetFloatConstantValue(node)) == V8_INT64_C(0)))) {
       return UseImmediate(node);
     }
     return UseRegister(node);
@@ -68,6 +70,19 @@
     return OpParameter<int64_t>(node);
   }
 
+  bool IsFloatConstant(Node* node) {
+    return (node->opcode() == IrOpcode::kFloat32Constant) ||
+           (node->opcode() == IrOpcode::kFloat64Constant);
+  }
+
+  double GetFloatConstantValue(Node* node) {
+    if (node->opcode() == IrOpcode::kFloat32Constant) {
+      return OpParameter<float>(node);
+    }
+    DCHECK_EQ(IrOpcode::kFloat64Constant, node->opcode());
+    return OpParameter<double>(node);
+  }
+
   bool CanBeImmediate(Node* node, ImmediateMode mode) {
     return IsIntegerConstant(node) &&
            CanBeImmediate(GetIntegerConstantValue(node), mode);
@@ -106,6 +121,13 @@
     return false;
   }
 
+  bool CanBeLoadStoreShiftImmediate(Node* node, MachineRepresentation rep) {
+    // TODO(arm64): Load and Store on 128 bit Q registers is not supported yet.
+    DCHECK_NE(MachineRepresentation::kSimd128, rep);
+    return IsIntegerConstant(node) &&
+           (GetIntegerConstantValue(node) == ElementSizeLog2Of(rep));
+  }
+
  private:
   bool IsLoadStoreImmediate(int64_t value, LSDataSize size) {
     return Assembler::IsImmLSScaled(value, size) ||
@@ -211,6 +233,94 @@
   return false;
 }
 
+bool TryMatchLoadStoreShift(Arm64OperandGenerator* g,
+                            InstructionSelector* selector,
+                            MachineRepresentation rep, Node* node, Node* index,
+                            InstructionOperand* index_op,
+                            InstructionOperand* shift_immediate_op) {
+  if (!selector->CanCover(node, index)) return false;
+  if (index->InputCount() != 2) return false;
+  Node* left = index->InputAt(0);
+  Node* right = index->InputAt(1);
+  switch (index->opcode()) {
+    case IrOpcode::kWord32Shl:
+    case IrOpcode::kWord64Shl:
+      if (!g->CanBeLoadStoreShiftImmediate(right, rep)) {
+        return false;
+      }
+      *index_op = g->UseRegister(left);
+      *shift_immediate_op = g->UseImmediate(right);
+      return true;
+    default:
+      return false;
+  }
+}
+
+// Bitfields describing binary operator properties:
+// CanCommuteField is true if we can switch the two operands, potentially
+// requiring commuting the flags continuation condition.
+typedef BitField8<bool, 1, 1> CanCommuteField;
+// MustCommuteCondField is true when we need to commute the flags continuation
+// condition in order to switch the operands.
+typedef BitField8<bool, 2, 1> MustCommuteCondField;
+// IsComparisonField is true when the operation is a comparison and has no other
+// result other than the condition.
+typedef BitField8<bool, 3, 1> IsComparisonField;
+// IsAddSubField is true when an instruction is encoded as ADD or SUB.
+typedef BitField8<bool, 4, 1> IsAddSubField;
+
+// Get properties of a binary operator.
+uint8_t GetBinopProperties(InstructionCode opcode) {
+  uint8_t result = 0;
+  switch (opcode) {
+    case kArm64Cmp32:
+    case kArm64Cmp:
+      // We can commute CMP by switching the inputs and commuting
+      // the flags continuation.
+      result = CanCommuteField::update(result, true);
+      result = MustCommuteCondField::update(result, true);
+      result = IsComparisonField::update(result, true);
+      // The CMP and CMN instructions are encoded as SUB or ADD
+      // with zero output register, and therefore support the same
+      // operand modes.
+      result = IsAddSubField::update(result, true);
+      break;
+    case kArm64Cmn32:
+    case kArm64Cmn:
+      result = CanCommuteField::update(result, true);
+      result = IsComparisonField::update(result, true);
+      result = IsAddSubField::update(result, true);
+      break;
+    case kArm64Add32:
+    case kArm64Add:
+      result = CanCommuteField::update(result, true);
+      result = IsAddSubField::update(result, true);
+      break;
+    case kArm64Sub32:
+    case kArm64Sub:
+      result = IsAddSubField::update(result, true);
+      break;
+    case kArm64Tst32:
+    case kArm64Tst:
+      result = CanCommuteField::update(result, true);
+      result = IsComparisonField::update(result, true);
+      break;
+    case kArm64And32:
+    case kArm64And:
+    case kArm64Or32:
+    case kArm64Or:
+    case kArm64Eor32:
+    case kArm64Eor:
+      result = CanCommuteField::update(result, true);
+      break;
+    default:
+      UNREACHABLE();
+      return 0;
+  }
+  DCHECK_IMPLIES(MustCommuteCondField::decode(result),
+                 CanCommuteField::decode(result));
+  return result;
+}
 
 // Shared routine for multiple binary operations.
 template <typename Matcher>
@@ -218,30 +328,24 @@
                 InstructionCode opcode, ImmediateMode operand_mode,
                 FlagsContinuation* cont) {
   Arm64OperandGenerator g(selector);
-  Matcher m(node);
   InstructionOperand inputs[5];
   size_t input_count = 0;
   InstructionOperand outputs[2];
   size_t output_count = 0;
-  bool is_cmp = (opcode == kArm64Cmp32) || (opcode == kArm64Cmn32);
 
-  // We can commute cmp by switching the inputs and commuting the flags
-  // continuation.
-  bool can_commute = m.HasProperty(Operator::kCommutative) || is_cmp;
+  Node* left_node = node->InputAt(0);
+  Node* right_node = node->InputAt(1);
 
-  // The cmp and cmn instructions are encoded as sub or add with zero output
-  // register, and therefore support the same operand modes.
-  bool is_add_sub = m.IsInt32Add() || m.IsInt64Add() || m.IsInt32Sub() ||
-                    m.IsInt64Sub() || is_cmp;
-
-  Node* left_node = m.left().node();
-  Node* right_node = m.right().node();
+  uint8_t properties = GetBinopProperties(opcode);
+  bool can_commute = CanCommuteField::decode(properties);
+  bool must_commute_cond = MustCommuteCondField::decode(properties);
+  bool is_add_sub = IsAddSubField::decode(properties);
 
   if (g.CanBeImmediate(right_node, operand_mode)) {
     inputs[input_count++] = g.UseRegister(left_node);
     inputs[input_count++] = g.UseImmediate(right_node);
-  } else if (is_cmp && g.CanBeImmediate(left_node, operand_mode)) {
-    cont->Commute();
+  } else if (can_commute && g.CanBeImmediate(left_node, operand_mode)) {
+    if (must_commute_cond) cont->Commute();
     inputs[input_count++] = g.UseRegister(right_node);
     inputs[input_count++] = g.UseImmediate(left_node);
   } else if (is_add_sub &&
@@ -251,7 +355,7 @@
   } else if (is_add_sub && can_commute &&
              TryMatchAnyExtend(&g, selector, node, right_node, left_node,
                                &inputs[0], &inputs[1], &opcode)) {
-    if (is_cmp) cont->Commute();
+    if (must_commute_cond) cont->Commute();
     input_count += 2;
   } else if (TryMatchAnyShift(selector, node, right_node, &opcode,
                               !is_add_sub)) {
@@ -261,7 +365,7 @@
     inputs[input_count++] = g.UseImmediate(m_shift.right().node());
   } else if (can_commute && TryMatchAnyShift(selector, node, left_node, &opcode,
                                              !is_add_sub)) {
-    if (is_cmp) cont->Commute();
+    if (must_commute_cond) cont->Commute();
     Matcher m_shift(left_node);
     inputs[input_count++] = g.UseRegisterOrImmediateZero(right_node);
     inputs[input_count++] = g.UseRegister(m_shift.left().node());
@@ -276,7 +380,7 @@
     inputs[input_count++] = g.Label(cont->false_block());
   }
 
-  if (!is_cmp) {
+  if (!IsComparisonField::decode(properties)) {
     outputs[output_count++] = g.DefineAsRegister(node);
   }
 
@@ -285,7 +389,7 @@
   }
 
   DCHECK_NE(0u, input_count);
-  DCHECK((output_count != 0) || is_cmp);
+  DCHECK((output_count != 0) || IsComparisonField::decode(properties));
   DCHECK_GE(arraysize(inputs), input_count);
   DCHECK_GE(arraysize(outputs), output_count);
 
@@ -344,12 +448,16 @@
 
 void InstructionSelector::VisitLoad(Node* node) {
   LoadRepresentation load_rep = LoadRepresentationOf(node->op());
+  MachineRepresentation rep = load_rep.representation();
   Arm64OperandGenerator g(this);
   Node* base = node->InputAt(0);
   Node* index = node->InputAt(1);
-  ArchOpcode opcode = kArchNop;
+  InstructionCode opcode = kArchNop;
   ImmediateMode immediate_mode = kNoImmediate;
-  switch (load_rep.representation()) {
+  InstructionOperand inputs[3];
+  size_t input_count = 0;
+  InstructionOperand outputs[1];
+  switch (rep) {
     case MachineRepresentation::kFloat32:
       opcode = kArm64LdrS;
       immediate_mode = kLoadStoreImm32;
@@ -381,13 +489,25 @@
       UNREACHABLE();
       return;
   }
+
+  outputs[0] = g.DefineAsRegister(node);
+  inputs[0] = g.UseRegister(base);
+
   if (g.CanBeImmediate(index, immediate_mode)) {
-    Emit(opcode | AddressingModeField::encode(kMode_MRI),
-         g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
+    input_count = 2;
+    inputs[1] = g.UseImmediate(index);
+    opcode |= AddressingModeField::encode(kMode_MRI);
+  } else if (TryMatchLoadStoreShift(&g, this, rep, node, index, &inputs[1],
+                                    &inputs[2])) {
+    input_count = 3;
+    opcode |= AddressingModeField::encode(kMode_Operand2_R_LSL_I);
   } else {
-    Emit(opcode | AddressingModeField::encode(kMode_MRR),
-         g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
+    input_count = 2;
+    inputs[1] = g.UseRegister(index);
+    opcode |= AddressingModeField::encode(kMode_MRR);
   }
+
+  Emit(opcode, arraysize(outputs), outputs, input_count, inputs);
 }
 
 
@@ -441,7 +561,9 @@
     code |= MiscField::encode(static_cast<int>(record_write_mode));
     Emit(code, 0, nullptr, input_count, inputs, temp_count, temps);
   } else {
-    ArchOpcode opcode = kArchNop;
+    InstructionOperand inputs[4];
+    size_t input_count = 0;
+    InstructionCode opcode = kArchNop;
     ImmediateMode immediate_mode = kNoImmediate;
     switch (rep) {
       case MachineRepresentation::kFloat32:
@@ -475,13 +597,25 @@
         UNREACHABLE();
         return;
     }
+
+    inputs[0] = g.UseRegisterOrImmediateZero(value);
+    inputs[1] = g.UseRegister(base);
+
     if (g.CanBeImmediate(index, immediate_mode)) {
-      Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
-           g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value));
+      input_count = 3;
+      inputs[2] = g.UseImmediate(index);
+      opcode |= AddressingModeField::encode(kMode_MRI);
+    } else if (TryMatchLoadStoreShift(&g, this, rep, node, index, &inputs[2],
+                                      &inputs[3])) {
+      input_count = 4;
+      opcode |= AddressingModeField::encode(kMode_Operand2_R_LSL_I);
     } else {
-      Emit(opcode | AddressingModeField::encode(kMode_MRR), g.NoOutput(),
-           g.UseRegister(base), g.UseRegister(index), g.UseRegister(value));
+      input_count = 3;
+      inputs[2] = g.UseRegister(index);
+      opcode |= AddressingModeField::encode(kMode_MRR);
     }
+
+    Emit(opcode, 0, nullptr, input_count, inputs);
   }
 }
 
@@ -519,6 +653,17 @@
       UNREACHABLE();
       return;
   }
+  // If the length is a constant power of two, allow the code generator to
+  // pick a more efficient bounds check sequence by passing the length as an
+  // immediate.
+  if (length->opcode() == IrOpcode::kInt32Constant) {
+    Int32Matcher m(length);
+    if (m.IsPowerOf2()) {
+      Emit(opcode, g.DefineAsRegister(node), g.UseRegister(buffer),
+           g.UseRegister(offset), g.UseImmediate(length));
+      return;
+    }
+  }
   Emit(opcode, g.DefineAsRegister(node), g.UseRegister(buffer),
        g.UseRegister(offset), g.UseOperand(length, kArithmeticImm));
 }
@@ -558,8 +703,20 @@
       UNREACHABLE();
       return;
   }
+  // If the length is a constant power of two, allow the code generator to
+  // pick a more efficient bounds check sequence by passing the length as an
+  // immediate.
+  if (length->opcode() == IrOpcode::kInt32Constant) {
+    Int32Matcher m(length);
+    if (m.IsPowerOf2()) {
+      Emit(opcode, g.NoOutput(), g.UseRegister(buffer), g.UseRegister(offset),
+           g.UseImmediate(length), g.UseRegisterOrImmediateZero(value));
+      return;
+    }
+  }
   Emit(opcode, g.NoOutput(), g.UseRegister(buffer), g.UseRegister(offset),
-       g.UseOperand(length, kArithmeticImm), g.UseRegister(value));
+       g.UseOperand(length, kArithmeticImm),
+       g.UseRegisterOrImmediateZero(value));
 }
 
 
@@ -1396,6 +1553,20 @@
       Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
       return;
     }
+    case IrOpcode::kLoad: {
+      // As for the operations above, a 32-bit load will implicitly clear the
+      // top 32 bits of the destination register.
+      LoadRepresentation load_rep = LoadRepresentationOf(value->op());
+      switch (load_rep.representation()) {
+        case MachineRepresentation::kWord8:
+        case MachineRepresentation::kWord16:
+        case MachineRepresentation::kWord32:
+          Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
+          return;
+        default:
+          break;
+      }
+    }
     default:
       break;
   }
@@ -1407,15 +1578,12 @@
   VisitRR(this, kArm64Float64ToFloat32, node);
 }
 
+void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
+  VisitRR(this, kArchTruncateDoubleToI, node);
+}
 
-void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
-  switch (TruncationModeOf(node->op())) {
-    case TruncationMode::kJavaScript:
-      return VisitRR(this, kArchTruncateDoubleToI, node);
-    case TruncationMode::kRoundToZero:
-      return VisitRR(this, kArm64Float64ToInt32, node);
-  }
-  UNREACHABLE();
+void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
+  VisitRR(this, kArm64Float64ToInt32, node);
 }
 
 
@@ -1491,6 +1659,9 @@
   VisitRRR(this, kArm64Float32Sub, node);
 }
 
+void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
+  VisitRRR(this, kArm64Float32Sub, node);
+}
 
 void InstructionSelector::VisitFloat64Sub(Node* node) {
   Arm64OperandGenerator g(this);
@@ -1515,6 +1686,9 @@
   VisitRRR(this, kArm64Float64Sub, node);
 }
 
+void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
+  VisitRRR(this, kArm64Float64Sub, node);
+}
 
 void InstructionSelector::VisitFloat32Mul(Node* node) {
   VisitRRR(this, kArm64Float32Mul, node);
@@ -1573,7 +1747,6 @@
   VisitRR(this, kArm64Float64Abs, node);
 }
 
-
 void InstructionSelector::VisitFloat32Sqrt(Node* node) {
   VisitRR(this, kArm64Float32Sqrt, node);
 }
@@ -1628,6 +1801,28 @@
   VisitRR(this, kArm64Float64RoundTiesEven, node);
 }
 
+void InstructionSelector::VisitFloat32Neg(Node* node) {
+  VisitRR(this, kArm64Float32Neg, node);
+}
+
+void InstructionSelector::VisitFloat64Neg(Node* node) {
+  VisitRR(this, kArm64Float64Neg, node);
+}
+
+void InstructionSelector::VisitFloat64Ieee754Binop(Node* node,
+                                                   InstructionCode opcode) {
+  Arm64OperandGenerator g(this);
+  Emit(opcode, g.DefineAsFixed(node, d0), g.UseFixed(node->InputAt(0), d0),
+       g.UseFixed(node->InputAt(1), d1))
+      ->MarkAsCall();
+}
+
+void InstructionSelector::VisitFloat64Ieee754Unop(Node* node,
+                                                  InstructionCode opcode) {
+  Arm64OperandGenerator g(this);
+  Emit(opcode, g.DefineAsFixed(node, d0), g.UseFixed(node->InputAt(0), d0))
+      ->MarkAsCall();
+}
 
 void InstructionSelector::EmitPrepareArguments(
     ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
@@ -1761,6 +1956,23 @@
   VisitWordTest(selector, node, kArm64Tst, cont);
 }
 
+template <typename Matcher, ArchOpcode kOpcode>
+bool TryEmitTestAndBranch(InstructionSelector* selector, Node* node,
+                          FlagsContinuation* cont) {
+  Arm64OperandGenerator g(selector);
+  Matcher m(node);
+  if (cont->IsBranch() && m.right().HasValue() &&
+      (base::bits::CountPopulation(m.right().Value()) == 1)) {
+    // If the mask has only one bit set, we can use tbz/tbnz.
+    DCHECK((cont->condition() == kEqual) || (cont->condition() == kNotEqual));
+    selector->Emit(
+        cont->Encode(kOpcode), g.NoOutput(), g.UseRegister(m.left().node()),
+        g.TempImmediate(base::bits::CountTrailingZeros(m.right().Value())),
+        g.Label(cont->true_block()), g.Label(cont->false_block()));
+    return true;
+  }
+  return false;
+}
 
 // Shared routine for multiple float32 compare operations.
 void VisitFloat32Compare(InstructionSelector* selector, Node* node,
@@ -1805,6 +2017,8 @@
   while (selector->CanCover(user, value)) {
     switch (value->opcode()) {
       case IrOpcode::kWord32Equal: {
+        // Combine with comparisons against 0 by simply inverting the
+        // continuation.
         Int32BinopMatcher m(value);
         if (m.right().Is(0)) {
           user = value;
@@ -1827,10 +2041,33 @@
       case IrOpcode::kUint32LessThanOrEqual:
         cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
         return VisitWord32Compare(selector, value, cont);
-      case IrOpcode::kWord64Equal:
+      case IrOpcode::kWord64Equal: {
         cont->OverwriteAndNegateIfEqual(kEqual);
+        Int64BinopMatcher m(value);
+        if (m.right().Is(0)) {
+          Node* const left = m.left().node();
+          if (selector->CanCover(value, left) &&
+              left->opcode() == IrOpcode::kWord64And) {
+            // Attempt to merge the Word64Equal(Word64And(x, y), 0) comparison
+            // into a tbz/tbnz instruction.
+            if (TryEmitTestAndBranch<Uint64BinopMatcher, kArm64TestAndBranch>(
+                    selector, left, cont)) {
+              return;
+            }
+            return VisitWordCompare(selector, left, kArm64Tst, cont, true,
+                                    kLogical64Imm);
+          }
+          // Merge the Word64Equal(x, 0) comparison into a cbz instruction.
+          if (cont->IsBranch()) {
+            selector->Emit(cont->Encode(kArm64CompareAndBranch), g.NoOutput(),
+                           g.UseRegister(left), g.Label(cont->true_block()),
+                           g.Label(cont->false_block()));
+            return;
+          }
+        }
         return VisitWordCompare(selector, value, kArm64Cmp, cont, false,
                                 kArithmeticImm);
+      }
       case IrOpcode::kInt64LessThan:
         cont->OverwriteAndNegateIfEqual(kSignedLessThan);
         return VisitWordCompare(selector, value, kArm64Cmp, cont, false,
@@ -1905,42 +2142,20 @@
                                 kArithmeticImm);
       case IrOpcode::kInt32Sub:
         return VisitWord32Compare(selector, value, cont);
-      case IrOpcode::kWord32And: {
-        Int32BinopMatcher m(value);
-        if (cont->IsBranch() && m.right().HasValue() &&
-            (base::bits::CountPopulation32(m.right().Value()) == 1)) {
-          // If the mask has only one bit set, we can use tbz/tbnz.
-          DCHECK((cont->condition() == kEqual) ||
-                 (cont->condition() == kNotEqual));
-          selector->Emit(
-              cont->Encode(kArm64TestAndBranch32), g.NoOutput(),
-              g.UseRegister(m.left().node()),
-              g.TempImmediate(
-                  base::bits::CountTrailingZeros32(m.right().Value())),
-              g.Label(cont->true_block()), g.Label(cont->false_block()));
+      case IrOpcode::kWord32And:
+        if (TryEmitTestAndBranch<Uint32BinopMatcher, kArm64TestAndBranch32>(
+                selector, value, cont)) {
           return;
         }
         return VisitWordCompare(selector, value, kArm64Tst32, cont, true,
                                 kLogical32Imm);
-      }
-      case IrOpcode::kWord64And: {
-        Int64BinopMatcher m(value);
-        if (cont->IsBranch() && m.right().HasValue() &&
-            (base::bits::CountPopulation64(m.right().Value()) == 1)) {
-          // If the mask has only one bit set, we can use tbz/tbnz.
-          DCHECK((cont->condition() == kEqual) ||
-                 (cont->condition() == kNotEqual));
-          selector->Emit(
-              cont->Encode(kArm64TestAndBranch), g.NoOutput(),
-              g.UseRegister(m.left().node()),
-              g.TempImmediate(
-                  base::bits::CountTrailingZeros64(m.right().Value())),
-              g.Label(cont->true_block()), g.Label(cont->false_block()));
+      case IrOpcode::kWord64And:
+        if (TryEmitTestAndBranch<Uint64BinopMatcher, kArm64TestAndBranch>(
+                selector, value, cont)) {
           return;
         }
         return VisitWordCompare(selector, value, kArm64Tst, cont, true,
                                 kLogical64Imm);
-      }
       default:
         break;
     }
@@ -2246,6 +2461,65 @@
        g.UseRegister(left), g.UseRegister(right));
 }
 
+void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
+  VisitRR(this, kArm64Float64SilenceNaN, node);
+}
+
+void InstructionSelector::VisitAtomicLoad(Node* node) {
+  LoadRepresentation load_rep = LoadRepresentationOf(node->op());
+  Arm64OperandGenerator g(this);
+  Node* base = node->InputAt(0);
+  Node* index = node->InputAt(1);
+  ArchOpcode opcode = kArchNop;
+  switch (load_rep.representation()) {
+    case MachineRepresentation::kWord8:
+      opcode = load_rep.IsSigned() ? kAtomicLoadInt8 : kAtomicLoadUint8;
+      break;
+    case MachineRepresentation::kWord16:
+      opcode = load_rep.IsSigned() ? kAtomicLoadInt16 : kAtomicLoadUint16;
+      break;
+    case MachineRepresentation::kWord32:
+      opcode = kAtomicLoadWord32;
+      break;
+    default:
+      UNREACHABLE();
+      return;
+  }
+  Emit(opcode | AddressingModeField::encode(kMode_MRR),
+       g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
+}
+
+void InstructionSelector::VisitAtomicStore(Node* node) {
+  MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
+  Arm64OperandGenerator g(this);
+  Node* base = node->InputAt(0);
+  Node* index = node->InputAt(1);
+  Node* value = node->InputAt(2);
+  ArchOpcode opcode = kArchNop;
+  switch (rep) {
+    case MachineRepresentation::kWord8:
+      opcode = kAtomicStoreWord8;
+      break;
+    case MachineRepresentation::kWord16:
+      opcode = kAtomicStoreWord16;
+      break;
+    case MachineRepresentation::kWord32:
+      opcode = kAtomicStoreWord32;
+      break;
+    default:
+      UNREACHABLE();
+      return;
+  }
+
+  AddressingMode addressing_mode = kMode_MRR;
+  InstructionOperand inputs[3];
+  size_t input_count = 0;
+  inputs[input_count++] = g.UseUniqueRegister(base);
+  inputs[input_count++] = g.UseUniqueRegister(index);
+  inputs[input_count++] = g.UseUniqueRegister(value);
+  InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
+  Emit(code, 0, nullptr, input_count, inputs);
+}
 
 // static
 MachineOperatorBuilder::Flags
@@ -2267,7 +2541,16 @@
          MachineOperatorBuilder::kInt32DivIsSafe |
          MachineOperatorBuilder::kUint32DivIsSafe |
          MachineOperatorBuilder::kWord32ReverseBits |
-         MachineOperatorBuilder::kWord64ReverseBits;
+         MachineOperatorBuilder::kWord64ReverseBits |
+         MachineOperatorBuilder::kFloat32Neg |
+         MachineOperatorBuilder::kFloat64Neg;
+}
+
+// static
+MachineOperatorBuilder::AlignmentRequirements
+InstructionSelector::AlignmentRequirements() {
+  return MachineOperatorBuilder::AlignmentRequirements::
+      FullUnalignedAccessSupport();
 }
 
 }  // namespace compiler
diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc
index 89bb619..d8d60f3 100644
--- a/src/compiler/ast-graph-builder.cc
+++ b/src/compiler/ast-graph-builder.cc
@@ -281,9 +281,9 @@
     return NewPathToken(TokenDispenserForFinally::kFallThroughToken);
   }
   Node* NewPathDispatchCondition(Node* t1, Node* t2) {
-    // TODO(mstarzinger): This should be machine()->WordEqual(), but our Phi
-    // nodes all have kRepTagged|kTypeAny, which causes representation mismatch.
-    return owner_->NewNode(owner_->javascript()->StrictEqual(), t1, t2);
+    return owner_->NewNode(
+        owner_->javascript()->StrictEqual(CompareOperationHints::Any()), t1,
+        t2);
   }
 
  private:
@@ -416,8 +416,15 @@
   FrameStateBeforeAndAfter(AstGraphBuilder* builder, BailoutId id_before)
       : builder_(builder), frame_state_before_(nullptr) {
     frame_state_before_ = id_before == BailoutId::None()
-                              ? builder_->jsgraph()->EmptyFrameState()
+                              ? builder_->GetEmptyFrameState()
                               : builder_->environment()->Checkpoint(id_before);
+    if (id_before != BailoutId::None()) {
+      // Create an explicit checkpoint node for before the operation.
+      Node* node = builder_->NewNode(builder_->common()->Checkpoint());
+      DCHECK_EQ(IrOpcode::kDead,
+                NodeProperties::GetFrameStateInput(node, 0)->opcode());
+      NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_before_);
+    }
   }
 
   void AddToNode(
@@ -435,7 +442,7 @@
 
       Node* frame_state_after =
           id_after == BailoutId::None()
-              ? builder_->jsgraph()->EmptyFrameState()
+              ? builder_->GetEmptyFrameState()
               : builder_->environment()->Checkpoint(id_after, combine,
                                                     node_has_exception);
 
@@ -444,6 +451,7 @@
 
     if (count >= 2) {
       // Add the frame state for before the operation.
+      // TODO(mstarzinger): Get rid of frame state input before!
       DCHECK_EQ(IrOpcode::kDead,
                 NodeProperties::GetFrameStateInput(node, 1)->opcode());
       NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_);
@@ -492,6 +500,12 @@
     // Contexts nested in the native context have a canonical empty function as
     // their closure, not the anonymous closure containing the global code.
     return BuildLoadNativeContextField(Context::CLOSURE_INDEX);
+  } else if (closure_scope->is_eval_scope()) {
+    // Contexts nested inside eval code have the same closure as the context
+    // calling eval, not the anonymous closure containing the eval code.
+    const Operator* op =
+        javascript()->LoadContext(0, Context::CLOSURE_INDEX, false);
+    return NewNode(op, current_context());
   } else {
     DCHECK(closure_scope->is_function_scope());
     return GetFunctionClosure();
@@ -533,6 +547,18 @@
   return new_target_.get();
 }
 
+Node* AstGraphBuilder::GetEmptyFrameState() {
+  if (!empty_frame_state_.is_set()) {
+    const Operator* op = common()->FrameState(
+        BailoutId::None(), OutputFrameStateCombine::Ignore(), nullptr);
+    Node* node = graph()->NewNode(
+        op, jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(),
+        jsgraph()->EmptyStateValues(), jsgraph()->NoContextConstant(),
+        jsgraph()->UndefinedConstant(), graph()->start());
+    empty_frame_state_.set(node);
+  }
+  return empty_frame_state_.get();
+}
 
 bool AstGraphBuilder::CreateGraph(bool stack_check) {
   Scope* scope = info()->scope();
@@ -568,7 +594,7 @@
   }
 
   // Build local context only if there are context allocated variables.
-  if (info()->num_heap_slots() > 0) {
+  if (scope->num_heap_slots() > 0) {
     // Push a new inner context scope for the current activation.
     Node* inner_context = BuildLocalActivationContext(GetFunctionContext());
     ContextScope top_context(this, scope, inner_context);
@@ -869,7 +895,7 @@
                                                OutputFrameStateCombine combine,
                                                bool owner_has_exception) {
   if (!builder()->info()->is_deoptimization_enabled()) {
-    return builder()->jsgraph()->EmptyFrameState();
+    return builder()->GetEmptyFrameState();
   }
 
   UpdateStateValues(&parameters_node_, 0, parameters_count());
@@ -1083,17 +1109,14 @@
 void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
   Variable* variable = decl->proxy()->var();
   VariableMode mode = decl->mode();
-  bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
+  bool hole_init = mode == CONST || mode == LET;
   switch (variable->location()) {
     case VariableLocation::GLOBAL:
-    case VariableLocation::UNALLOCATED: {
-      Handle<Oddball> value = variable->binding_needs_init()
-                                  ? isolate()->factory()->the_hole_value()
-                                  : isolate()->factory()->undefined_value();
+    case VariableLocation::UNALLOCATED:
+      DCHECK(!variable->binding_needs_init());
       globals()->push_back(variable->name());
-      globals()->push_back(value);
+      globals()->push_back(isolate()->factory()->undefined_value());
       break;
-    }
     case VariableLocation::PARAMETER:
     case VariableLocation::LOCAL:
       if (hole_init) {
@@ -1108,8 +1131,14 @@
         NewNode(op, current_context(), value);
       }
       break;
-    case VariableLocation::LOOKUP:
-      UNIMPLEMENTED();
+    case VariableLocation::LOOKUP: {
+      DCHECK(!hole_init);
+      Node* name = jsgraph()->Constant(variable->name());
+      const Operator* op = javascript()->CallRuntime(Runtime::kDeclareEvalVar);
+      Node* store = NewNode(op, name);
+      PrepareFrameState(store, decl->proxy()->id());
+      break;
+    }
   }
 }
 
@@ -1141,8 +1170,16 @@
       NewNode(op, current_context(), value);
       break;
     }
-    case VariableLocation::LOOKUP:
-      UNIMPLEMENTED();
+    case VariableLocation::LOOKUP: {
+      VisitForValue(decl->fun());
+      Node* value = environment()->Pop();
+      Node* name = jsgraph()->Constant(variable->name());
+      const Operator* op =
+          javascript()->CallRuntime(Runtime::kDeclareEvalFunction);
+      Node* store = NewNode(op, name, value);
+      PrepareFrameState(store, decl->proxy()->id());
+      break;
+    }
   }
 }
 
@@ -1262,7 +1299,15 @@
     VisitForValue(clause->label());
     Node* label = environment()->Pop();
     Node* tag = environment()->Top();
-    const Operator* op = javascript()->StrictEqual();
+
+    CompareOperationHints hints;
+    if (!type_hint_analysis_ ||
+        !type_hint_analysis_->GetCompareOperationHints(clause->CompareId(),
+                                                       &hints)) {
+      hints = CompareOperationHints::Any();
+    }
+
+    const Operator* op = javascript()->StrictEqual(hints);
     Node* condition = NewNode(op, tag, label);
     compare_switch.BeginLabel(i, condition);
 
@@ -1338,10 +1383,12 @@
   for_block.BeginBlock();
   // Check for null or undefined before entering loop.
   Node* is_null_cond =
-      NewNode(javascript()->StrictEqual(), object, jsgraph()->NullConstant());
+      NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), object,
+              jsgraph()->NullConstant());
   for_block.BreakWhen(is_null_cond, BranchHint::kFalse);
-  Node* is_undefined_cond = NewNode(javascript()->StrictEqual(), object,
-                                    jsgraph()->UndefinedConstant());
+  Node* is_undefined_cond =
+      NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), object,
+              jsgraph()->UndefinedConstant());
   for_block.BreakWhen(is_undefined_cond, BranchHint::kFalse);
   {
     // Convert object to jsobject.
@@ -1384,8 +1431,9 @@
       PrepareFrameState(value, stmt->FilterId(),
                         OutputFrameStateCombine::Push());
       IfBuilder test_value(this);
-      Node* test_value_cond = NewNode(javascript()->StrictEqual(), value,
-                                      jsgraph()->UndefinedConstant());
+      Node* test_value_cond =
+          NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
+                  value, jsgraph()->UndefinedConstant());
       test_value.If(test_value_cond, BranchHint::kFalse);
       test_value.Then();
       test_value.Else();
@@ -1398,10 +1446,10 @@
         VisitIterationBody(stmt, &for_loop);
       }
       test_value.End();
-      index = environment()->Peek(0);
       for_loop.EndBody();
 
       // Increment counter and continue.
+      index = environment()->Peek(0);
       index = NewNode(javascript()->ForInStep(), index);
       environment()->Poke(0, index);
     }
@@ -1575,12 +1623,12 @@
   environment()->Push(literal);
 
   // Load the "prototype" from the constructor.
-  FrameStateBeforeAndAfter states(this, expr->CreateLiteralId());
+  PrepareEagerCheckpoint(expr->CreateLiteralId());
   Handle<Name> name = isolate()->factory()->prototype_string();
   VectorSlotPair pair = CreateVectorSlotPair(expr->PrototypeSlot());
   Node* prototype = BuildNamedLoad(literal, name, pair);
-  states.AddToNode(prototype, expr->PrototypeId(),
-                   OutputFrameStateCombine::Push());
+  PrepareFrameState(prototype, expr->PrototypeId(),
+                    OutputFrameStateCombine::Push());
   environment()->Push(prototype);
 
   // Create nodes to store method values into the literal.
@@ -1620,7 +1668,8 @@
             jsgraph()->Constant(property->NeedsSetFunctionName());
         const Operator* op =
             javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
-        NewNode(op, receiver, key, value, attr, set_function_name);
+        Node* call = NewNode(op, receiver, key, value, attr, set_function_name);
+        PrepareFrameState(call, BailoutId::None());
         break;
       }
       case ObjectLiteral::Property::GETTER: {
@@ -1640,22 +1689,20 @@
     }
   }
 
-  // Set both the prototype and constructor to have fast properties.
+  // Set the constructor to have fast properties.
   prototype = environment()->Pop();
   literal = environment()->Pop();
-  const Operator* op =
-      javascript()->CallRuntime(Runtime::kFinalizeClassDefinition);
-  literal = NewNode(op, literal, prototype);
+  const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties);
+  literal = NewNode(op, literal);
 
   // Assign to class variable.
   if (expr->class_variable_proxy() != nullptr) {
     Variable* var = expr->class_variable_proxy()->var();
-    FrameStateBeforeAndAfter states(this, BailoutId::None());
     VectorSlotPair feedback = CreateVectorSlotPair(
         expr->NeedsProxySlot() ? expr->ProxySlot()
                                : FeedbackVectorSlot::Invalid());
     BuildVariableAssignment(var, literal, Token::INIT, feedback,
-                            BailoutId::None(), states);
+                            BailoutId::None());
   }
   ast_context()->ProduceValue(literal);
 }
@@ -1689,8 +1736,8 @@
 
 void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
   VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot());
-  FrameStateBeforeAndAfter states(this, BeforeId(expr));
-  Node* value = BuildVariableLoad(expr->var(), expr->id(), states, pair,
+  PrepareEagerCheckpoint(BeforeId(expr));
+  Node* value = BuildVariableLoad(expr->var(), expr->id(), pair,
                                   ast_context()->GetStateCombine());
   ast_context()->ProduceValue(value);
 }
@@ -1750,15 +1797,15 @@
         if (key->value()->IsInternalizedString()) {
           if (property->emit_store()) {
             VisitForValue(property->value());
-            FrameStateBeforeAndAfter states(this, property->value()->id());
+            PrepareEagerCheckpoint(property->value()->id());
             Node* value = environment()->Pop();
             Node* literal = environment()->Top();
             Handle<Name> name = key->AsPropertyName();
             VectorSlotPair feedback =
                 CreateVectorSlotPair(property->GetSlot(0));
             Node* store = BuildNamedStore(literal, name, value, feedback);
-            states.AddToNode(store, key->id(),
-                             OutputFrameStateCombine::Ignore());
+            PrepareFrameState(store, key->id(),
+                              OutputFrameStateCombine::Ignore());
             BuildSetHomeObject(value, literal, property, 1);
           } else {
             VisitForEffect(property->value());
@@ -1797,12 +1844,16 @@
       }
       case ObjectLiteral::Property::GETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->getter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->getter = property;
         }
         break;
       case ObjectLiteral::Property::SETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->setter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->setter = property;
         }
         break;
     }
@@ -1823,8 +1874,7 @@
     const Operator* op =
         javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked);
     Node* call = NewNode(op, literal, name, getter, setter, attr);
-    // This should not lazy deopt on a new literal.
-    PrepareFrameState(call, BailoutId::None());
+    PrepareFrameState(call, it->second->bailout_id);
   }
 
   // Object literals have two parts. The "static" part on the left contains no
@@ -1870,7 +1920,8 @@
             jsgraph()->Constant(property->NeedsSetFunctionName());
         const Operator* op =
             javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
-        NewNode(op, receiver, key, value, attr, set_function_name);
+        Node* call = NewNode(op, receiver, key, value, attr, set_function_name);
+        PrepareFrameState(call, expr->GetIdForPropertySet(property_index));
         break;
       }
       case ObjectLiteral::Property::PROTOTYPE:
@@ -1935,14 +1986,14 @@
 
     VisitForValue(subexpr);
     {
-      FrameStateBeforeAndAfter states(this, subexpr->id());
+      PrepareEagerCheckpoint(subexpr->id());
       VectorSlotPair pair = CreateVectorSlotPair(expr->LiteralFeedbackSlot());
       Node* value = environment()->Pop();
       Node* index = jsgraph()->Constant(array_index);
       Node* literal = environment()->Top();
       Node* store = BuildKeyedStore(literal, index, value, pair);
-      states.AddToNode(store, expr->GetIdForElement(array_index),
-                       OutputFrameStateCombine::Ignore());
+      PrepareFrameState(store, expr->GetIdForElement(array_index),
+                        OutputFrameStateCombine::Ignore());
     }
   }
 
@@ -1985,49 +2036,49 @@
     case VARIABLE: {
       Variable* var = expr->AsVariableProxy()->var();
       environment()->Push(value);
-      FrameStateBeforeAndAfter states(this, bailout_id_before);
+      PrepareEagerCheckpoint(bailout_id_before);
       value = environment()->Pop();
       BuildVariableAssignment(var, value, Token::ASSIGN, feedback,
-                              bailout_id_after, states);
+                              bailout_id_after);
       break;
     }
     case NAMED_PROPERTY: {
       environment()->Push(value);
       VisitForValue(property->obj());
-      FrameStateBeforeAndAfter states(this, property->obj()->id());
+      PrepareEagerCheckpoint(property->obj()->id());
       Node* object = environment()->Pop();
       value = environment()->Pop();
       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
       Node* store = BuildNamedStore(object, name, value, feedback);
-      states.AddToNode(store, bailout_id_after,
-                       OutputFrameStateCombine::Ignore());
+      PrepareFrameState(store, bailout_id_after,
+                        OutputFrameStateCombine::Ignore());
       break;
     }
     case KEYED_PROPERTY: {
       environment()->Push(value);
       VisitForValue(property->obj());
       VisitForValue(property->key());
-      FrameStateBeforeAndAfter states(this, property->key()->id());
+      PrepareEagerCheckpoint(property->key()->id());
       Node* key = environment()->Pop();
       Node* object = environment()->Pop();
       value = environment()->Pop();
       Node* store = BuildKeyedStore(object, key, value, feedback);
-      states.AddToNode(store, bailout_id_after,
-                       OutputFrameStateCombine::Ignore());
+      PrepareFrameState(store, bailout_id_after,
+                        OutputFrameStateCombine::Ignore());
       break;
     }
     case NAMED_SUPER_PROPERTY: {
       environment()->Push(value);
       VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
       VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
-      FrameStateBeforeAndAfter states(this, property->obj()->id());
+      PrepareEagerCheckpoint(property->obj()->id());
       Node* home_object = environment()->Pop();
       Node* receiver = environment()->Pop();
       value = environment()->Pop();
       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
       Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
-      states.AddToNode(store, bailout_id_after,
-                       OutputFrameStateCombine::Ignore());
+      PrepareFrameState(store, bailout_id_after,
+                        OutputFrameStateCombine::Ignore());
       break;
     }
     case KEYED_SUPER_PROPERTY: {
@@ -2035,14 +2086,14 @@
       VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
       VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
       VisitForValue(property->key());
-      FrameStateBeforeAndAfter states(this, property->key()->id());
+      PrepareEagerCheckpoint(property->key()->id());
       Node* key = environment()->Pop();
       Node* home_object = environment()->Pop();
       Node* receiver = environment()->Pop();
       value = environment()->Pop();
       Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
-      states.AddToNode(store, bailout_id_after,
-                       OutputFrameStateCombine::Ignore());
+      PrepareFrameState(store, bailout_id_after,
+                        OutputFrameStateCombine::Ignore());
       break;
     }
   }
@@ -2096,10 +2147,9 @@
         VariableProxy* proxy = expr->target()->AsVariableProxy();
         VectorSlotPair pair =
             CreateVectorSlotPair(proxy->VariableFeedbackSlot());
-        FrameStateBeforeAndAfter states(this, BeforeId(proxy));
-        old_value =
-            BuildVariableLoad(proxy->var(), expr->target()->id(), states, pair,
-                              OutputFrameStateCombine::Push());
+        PrepareEagerCheckpoint(BeforeId(proxy));
+        old_value = BuildVariableLoad(proxy->var(), expr->target()->id(), pair,
+                                      OutputFrameStateCombine::Push());
         break;
       }
       case NAMED_PROPERTY: {
@@ -2107,10 +2157,10 @@
         Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
         VectorSlotPair pair =
             CreateVectorSlotPair(property->PropertyFeedbackSlot());
-        FrameStateBeforeAndAfter states(this, property->obj()->id());
+        PrepareEagerCheckpoint(property->obj()->id());
         old_value = BuildNamedLoad(object, name, pair);
-        states.AddToNode(old_value, property->LoadId(),
-                         OutputFrameStateCombine::Push());
+        PrepareFrameState(old_value, property->LoadId(),
+                          OutputFrameStateCombine::Push());
         break;
       }
       case KEYED_PROPERTY: {
@@ -2118,10 +2168,10 @@
         Node* object = environment()->Peek(1);
         VectorSlotPair pair =
             CreateVectorSlotPair(property->PropertyFeedbackSlot());
-        FrameStateBeforeAndAfter states(this, property->key()->id());
+        PrepareEagerCheckpoint(property->key()->id());
         old_value = BuildKeyedLoad(object, key, pair);
-        states.AddToNode(old_value, property->LoadId(),
-                         OutputFrameStateCombine::Push());
+        PrepareFrameState(old_value, property->LoadId(),
+                          OutputFrameStateCombine::Push());
         break;
       }
       case NAMED_SUPER_PROPERTY: {
@@ -2130,10 +2180,10 @@
         Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
         VectorSlotPair pair =
             CreateVectorSlotPair(property->PropertyFeedbackSlot());
-        FrameStateBeforeAndAfter states(this, property->obj()->id());
+        PrepareEagerCheckpoint(property->obj()->id());
         old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
-        states.AddToNode(old_value, property->LoadId(),
-                         OutputFrameStateCombine::Push());
+        PrepareFrameState(old_value, property->LoadId(),
+                          OutputFrameStateCombine::Push());
         break;
       }
       case KEYED_SUPER_PROPERTY: {
@@ -2142,10 +2192,10 @@
         Node* receiver = environment()->Peek(2);
         VectorSlotPair pair =
             CreateVectorSlotPair(property->PropertyFeedbackSlot());
-        FrameStateBeforeAndAfter states(this, property->key()->id());
+        PrepareEagerCheckpoint(property->key()->id());
         old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
-        states.AddToNode(old_value, property->LoadId(),
-                         OutputFrameStateCombine::Push());
+        PrepareFrameState(old_value, property->LoadId(),
+                          OutputFrameStateCombine::Push());
         break;
       }
     }
@@ -2173,31 +2223,29 @@
     }
   }
 
-  FrameStateBeforeAndAfter store_states(this, before_store_id);
   // Store the value.
+  PrepareEagerCheckpoint(before_store_id);
   Node* value = environment()->Pop();
   VectorSlotPair feedback = CreateVectorSlotPair(expr->AssignmentSlot());
   switch (assign_type) {
     case VARIABLE: {
       Variable* variable = expr->target()->AsVariableProxy()->var();
       BuildVariableAssignment(variable, value, expr->op(), feedback, expr->id(),
-                              store_states, ast_context()->GetStateCombine());
+                              ast_context()->GetStateCombine());
       break;
     }
     case NAMED_PROPERTY: {
       Node* object = environment()->Pop();
       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
       Node* store = BuildNamedStore(object, name, value, feedback);
-      store_states.AddToNode(store, expr->id(),
-                             ast_context()->GetStateCombine());
+      PrepareFrameState(store, expr->id(), ast_context()->GetStateCombine());
       break;
     }
     case KEYED_PROPERTY: {
       Node* key = environment()->Pop();
       Node* object = environment()->Pop();
       Node* store = BuildKeyedStore(object, key, value, feedback);
-      store_states.AddToNode(store, expr->id(),
-                             ast_context()->GetStateCombine());
+      PrepareFrameState(store, expr->id(), ast_context()->GetStateCombine());
       break;
     }
     case NAMED_SUPER_PROPERTY: {
@@ -2205,8 +2253,7 @@
       Node* receiver = environment()->Pop();
       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
       Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
-      store_states.AddToNode(store, expr->id(),
-                             ast_context()->GetStateCombine());
+      PrepareFrameState(store, expr->id(), ast_context()->GetStateCombine());
       break;
     }
     case KEYED_SUPER_PROPERTY: {
@@ -2214,8 +2261,7 @@
       Node* home_object = environment()->Pop();
       Node* receiver = environment()->Pop();
       Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
-      store_states.AddToNode(store, expr->id(),
-                             ast_context()->GetStateCombine());
+      PrepareFrameState(store, expr->id(), ast_context()->GetStateCombine());
       break;
     }
   }
@@ -2225,7 +2271,7 @@
 
 
 void AstGraphBuilder::VisitYield(Yield* expr) {
-  // TODO(turbofan): Implement yield here.
+  // Generator functions are supported only by going through Ignition first.
   SetStackOverflow();
   ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
 }
@@ -2249,44 +2295,44 @@
       break;
     case NAMED_PROPERTY: {
       VisitForValue(expr->obj());
-      FrameStateBeforeAndAfter states(this, expr->obj()->id());
+      PrepareEagerCheckpoint(expr->obj()->id());
       Node* object = environment()->Pop();
       Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
       value = BuildNamedLoad(object, name, pair);
-      states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
+      PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
       break;
     }
     case KEYED_PROPERTY: {
       VisitForValue(expr->obj());
       VisitForValue(expr->key());
-      FrameStateBeforeAndAfter states(this, expr->key()->id());
+      PrepareEagerCheckpoint(expr->key()->id());
       Node* key = environment()->Pop();
       Node* object = environment()->Pop();
       value = BuildKeyedLoad(object, key, pair);
-      states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
+      PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
       break;
     }
     case NAMED_SUPER_PROPERTY: {
       VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
       VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
-      FrameStateBeforeAndAfter states(this, expr->obj()->id());
+      PrepareEagerCheckpoint(expr->obj()->id());
       Node* home_object = environment()->Pop();
       Node* receiver = environment()->Pop();
       Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
       value = BuildNamedSuperLoad(receiver, home_object, name, pair);
-      states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
+      PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
       break;
     }
     case KEYED_SUPER_PROPERTY: {
       VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
       VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
       VisitForValue(expr->key());
-      FrameStateBeforeAndAfter states(this, expr->key()->id());
+      PrepareEagerCheckpoint(expr->key()->id());
       Node* key = environment()->Pop();
       Node* home_object = environment()->Pop();
       Node* receiver = environment()->Pop();
       value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
-      states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
+      PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
       break;
     }
   }
@@ -2308,10 +2354,9 @@
     case Call::GLOBAL_CALL: {
       VariableProxy* proxy = callee->AsVariableProxy();
       VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
-      FrameStateBeforeAndAfter states(this, BeforeId(proxy));
-      callee_value =
-          BuildVariableLoad(proxy->var(), expr->expression()->id(), states,
-                            pair, OutputFrameStateCombine::Push());
+      PrepareEagerCheckpoint(BeforeId(proxy));
+      callee_value = BuildVariableLoad(proxy->var(), expr->expression()->id(),
+                                       pair, OutputFrameStateCombine::Push());
       receiver_hint = ConvertReceiverMode::kNullOrUndefined;
       receiver_value = jsgraph()->UndefinedConstant();
       break;
@@ -2334,12 +2379,12 @@
       VectorSlotPair feedback =
           CreateVectorSlotPair(property->PropertyFeedbackSlot());
       VisitForValue(property->obj());
-      FrameStateBeforeAndAfter states(this, property->obj()->id());
+      PrepareEagerCheckpoint(property->obj()->id());
       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
       Node* object = environment()->Top();
       callee_value = BuildNamedLoad(object, name, feedback);
-      states.AddToNode(callee_value, property->LoadId(),
-                       OutputFrameStateCombine::Push());
+      PrepareFrameState(callee_value, property->LoadId(),
+                        OutputFrameStateCombine::Push());
       // Note that a property call requires the receiver to be wrapped into
       // an object for sloppy callees. However the receiver is guaranteed
       // not to be null or undefined at this point.
@@ -2353,12 +2398,12 @@
           CreateVectorSlotPair(property->PropertyFeedbackSlot());
       VisitForValue(property->obj());
       VisitForValue(property->key());
-      FrameStateBeforeAndAfter states(this, property->key()->id());
+      PrepareEagerCheckpoint(property->key()->id());
       Node* key = environment()->Pop();
       Node* object = environment()->Top();
       callee_value = BuildKeyedLoad(object, key, feedback);
-      states.AddToNode(callee_value, property->LoadId(),
-                       OutputFrameStateCombine::Push());
+      PrepareFrameState(callee_value, property->LoadId(),
+                        OutputFrameStateCombine::Push());
       // Note that a property call requires the receiver to be wrapped into
       // an object for sloppy callees. However the receiver is guaranteed
       // not to be null or undefined at this point.
@@ -2375,10 +2420,10 @@
       Node* home = environment()->Peek(1);
       Node* object = environment()->Top();
       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
-      FrameStateBeforeAndAfter states(this, property->obj()->id());
+      PrepareEagerCheckpoint(property->obj()->id());
       callee_value = BuildNamedSuperLoad(object, home, name, VectorSlotPair());
-      states.AddToNode(callee_value, property->LoadId(),
-                       OutputFrameStateCombine::Push());
+      PrepareFrameState(callee_value, property->LoadId(),
+                        OutputFrameStateCombine::Push());
       // Note that a property call requires the receiver to be wrapped into
       // an object for sloppy callees. Since the receiver is not the target of
       // the load, it could very well be null or undefined at this point.
@@ -2398,10 +2443,10 @@
       Node* key = environment()->Pop();
       Node* home = environment()->Pop();
       Node* object = environment()->Pop();
-      FrameStateBeforeAndAfter states(this, property->key()->id());
+      PrepareEagerCheckpoint(property->key()->id());
       callee_value = BuildKeyedSuperLoad(object, home, key, VectorSlotPair());
-      states.AddToNode(callee_value, property->LoadId(),
-                       OutputFrameStateCombine::Push());
+      PrepareFrameState(callee_value, property->LoadId(),
+                        OutputFrameStateCombine::Push());
       // Note that a property call requires the receiver to be wrapped into
       // an object for sloppy callees. Since the receiver is not the target of
       // the load, it could very well be null or undefined at this point.
@@ -2456,11 +2501,13 @@
     // provide a fully resolved callee to patch into the environment.
     Node* function = GetFunctionClosure();
     Node* language = jsgraph()->Constant(language_mode());
-    Node* position = jsgraph()->Constant(current_scope()->start_position());
+    Node* eval_scope_position =
+        jsgraph()->Constant(current_scope()->start_position());
+    Node* eval_position = jsgraph()->Constant(expr->position());
     const Operator* op =
         javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval);
-    Node* new_callee =
-        NewNode(op, callee, source, function, language, position);
+    Node* new_callee = NewNode(op, callee, source, function, language,
+                               eval_scope_position, eval_position);
     PrepareFrameState(new_callee, expr->EvalId(),
                       OutputFrameStateCombine::PokeAt(arg_count + 1));
 
@@ -2472,10 +2519,10 @@
   VectorSlotPair feedback = CreateVectorSlotPair(expr->CallFeedbackICSlot());
   const Operator* call = javascript()->CallFunction(
       args->length() + 2, feedback, receiver_hint, expr->tail_call_mode());
-  FrameStateBeforeAndAfter states(this, expr->CallId());
+  PrepareEagerCheckpoint(expr->CallId());
   Node* value = ProcessArguments(call, args->length() + 2);
   environment()->Push(value->InputAt(0));  // The callee passed to the call.
-  states.AddToNode(value, expr->ReturnId(), OutputFrameStateCombine::Push());
+  PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
   environment()->Drop(1);
   ast_context()->ProduceValue(value);
 }
@@ -2503,9 +2550,9 @@
   // Create node to perform the super call.
   const Operator* call =
       javascript()->CallConstruct(args->length() + 2, VectorSlotPair());
-  FrameStateBeforeAndAfter states(this, super->new_target_var()->id());
+  PrepareEagerCheckpoint(super->new_target_var()->id());
   Node* value = ProcessArguments(call, args->length() + 2);
-  states.AddToNode(value, expr->ReturnId(), OutputFrameStateCombine::Push());
+  PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
   ast_context()->ProduceValue(value);
 }
 
@@ -2519,8 +2566,8 @@
 
   // The baseline compiler doesn't push the new.target, so we need to record
   // the frame state before the push.
-  FrameStateBeforeAndAfter states(
-      this, args->is_empty() ? expr->expression()->id() : args->last()->id());
+  PrepareEagerCheckpoint(args->is_empty() ? expr->expression()->id()
+                                          : args->last()->id());
 
   // The new target is the same as the callee.
   environment()->Push(environment()->Peek(args->length()));
@@ -2530,7 +2577,7 @@
   const Operator* call =
       javascript()->CallConstruct(args->length() + 2, feedback);
   Node* value = ProcessArguments(call, args->length() + 2);
-  states.AddToNode(value, expr->ReturnId(), OutputFrameStateCombine::Push());
+  PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
   ast_context()->ProduceValue(value);
 }
 
@@ -2550,9 +2597,9 @@
 
   // Create node to perform the JS runtime call.
   const Operator* call = javascript()->CallFunction(args->length() + 2);
-  FrameStateBeforeAndAfter states(this, expr->CallId());
+  PrepareEagerCheckpoint(expr->CallId());
   Node* value = ProcessArguments(call, args->length() + 2);
-  states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
+  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
   ast_context()->ProduceValue(value);
 }
 
@@ -2571,9 +2618,9 @@
   // Create node to perform the runtime call.
   Runtime::FunctionId functionId = expr->function()->function_id;
   const Operator* call = javascript()->CallRuntime(functionId, args->length());
-  FrameStateBeforeAndAfter states(this, expr->CallId());
+  PrepareEagerCheckpoint(expr->CallId());
   Node* value = ProcessArguments(call, args->length());
-  states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
+  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
   ast_context()->ProduceValue(value);
 }
 
@@ -2614,52 +2661,51 @@
     case VARIABLE: {
       VariableProxy* proxy = expr->expression()->AsVariableProxy();
       VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
-      FrameStateBeforeAndAfter states(this, BeforeId(proxy));
-      old_value =
-          BuildVariableLoad(proxy->var(), expr->expression()->id(), states,
-                            pair, OutputFrameStateCombine::Push());
+      PrepareEagerCheckpoint(BeforeId(proxy));
+      old_value = BuildVariableLoad(proxy->var(), expr->expression()->id(),
+                                    pair, OutputFrameStateCombine::Push());
       stack_depth = 0;
       break;
     }
     case NAMED_PROPERTY: {
       VisitForValue(property->obj());
-      FrameStateBeforeAndAfter states(this, property->obj()->id());
+      PrepareEagerCheckpoint(property->obj()->id());
       Node* object = environment()->Top();
       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
       VectorSlotPair pair =
           CreateVectorSlotPair(property->PropertyFeedbackSlot());
       old_value = BuildNamedLoad(object, name, pair);
-      states.AddToNode(old_value, property->LoadId(),
-                       OutputFrameStateCombine::Push());
+      PrepareFrameState(old_value, property->LoadId(),
+                        OutputFrameStateCombine::Push());
       stack_depth = 1;
       break;
     }
     case KEYED_PROPERTY: {
       VisitForValue(property->obj());
       VisitForValue(property->key());
-      FrameStateBeforeAndAfter states(this, property->key()->id());
+      PrepareEagerCheckpoint(property->key()->id());
       Node* key = environment()->Top();
       Node* object = environment()->Peek(1);
       VectorSlotPair pair =
           CreateVectorSlotPair(property->PropertyFeedbackSlot());
       old_value = BuildKeyedLoad(object, key, pair);
-      states.AddToNode(old_value, property->LoadId(),
-                       OutputFrameStateCombine::Push());
+      PrepareFrameState(old_value, property->LoadId(),
+                        OutputFrameStateCombine::Push());
       stack_depth = 2;
       break;
     }
     case NAMED_SUPER_PROPERTY: {
       VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
       VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
-      FrameStateBeforeAndAfter states(this, property->obj()->id());
+      PrepareEagerCheckpoint(property->obj()->id());
       Node* home_object = environment()->Top();
       Node* receiver = environment()->Peek(1);
       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
       VectorSlotPair pair =
           CreateVectorSlotPair(property->PropertyFeedbackSlot());
       old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
-      states.AddToNode(old_value, property->LoadId(),
-                       OutputFrameStateCombine::Push());
+      PrepareFrameState(old_value, property->LoadId(),
+                        OutputFrameStateCombine::Push());
       stack_depth = 2;
       break;
     }
@@ -2667,15 +2713,15 @@
       VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
       VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
       VisitForValue(property->key());
-      FrameStateBeforeAndAfter states(this, property->obj()->id());
+      PrepareEagerCheckpoint(property->obj()->id());
       Node* key = environment()->Top();
       Node* home_object = environment()->Peek(1);
       Node* receiver = environment()->Peek(2);
       VectorSlotPair pair =
           CreateVectorSlotPair(property->PropertyFeedbackSlot());
       old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
-      states.AddToNode(old_value, property->LoadId(),
-                       OutputFrameStateCombine::Push());
+      PrepareFrameState(old_value, property->LoadId(),
+                        OutputFrameStateCombine::Push());
       stack_depth = 3;
       break;
     }
@@ -2688,7 +2734,7 @@
 
   // Create a proper eager frame state for the stores.
   environment()->Push(old_value);
-  FrameStateBeforeAndAfter store_states(this, expr->ToNumberId());
+  FrameStateBeforeAndAfter binop_states(this, expr->ToNumberId());
   old_value = environment()->Pop();
 
   // Save result for postfix expressions at correct stack depth.
@@ -2701,16 +2747,12 @@
   }
 
   // Create node to perform +1/-1 operation.
-  Node* value;
-  {
-    // TODO(bmeurer): Cleanup this feedback/bailout mess!
-    FrameStateBeforeAndAfter states(this, BailoutId::None());
-    value = BuildBinaryOp(old_value, jsgraph()->OneConstant(),
-                          expr->binary_op(), expr->CountBinOpFeedbackId());
-    // This should never deoptimize because we have converted to number before.
-    states.AddToNode(value, BailoutId::None(),
-                     OutputFrameStateCombine::Ignore());
-  }
+  // TODO(bmeurer): Cleanup this feedback/bailout mess!
+  Node* value = BuildBinaryOp(old_value, jsgraph()->OneConstant(),
+                              expr->binary_op(), expr->CountBinOpFeedbackId());
+  // This should never deoptimize because we have converted to number before.
+  binop_states.AddToNode(value, BailoutId::None(),
+                         OutputFrameStateCombine::Ignore());
 
   // Store the value.
   VectorSlotPair feedback = CreateVectorSlotPair(expr->CountSlot());
@@ -2719,7 +2761,7 @@
       Variable* variable = expr->expression()->AsVariableProxy()->var();
       environment()->Push(value);
       BuildVariableAssignment(variable, value, expr->op(), feedback,
-                              expr->AssignmentId(), store_states);
+                              expr->AssignmentId());
       environment()->Pop();
       break;
     }
@@ -2728,8 +2770,8 @@
       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
       Node* store = BuildNamedStore(object, name, value, feedback);
       environment()->Push(value);
-      store_states.AddToNode(store, expr->AssignmentId(),
-                             OutputFrameStateCombine::Ignore());
+      PrepareFrameState(store, expr->AssignmentId(),
+                        OutputFrameStateCombine::Ignore());
       environment()->Pop();
       break;
     }
@@ -2738,8 +2780,8 @@
       Node* object = environment()->Pop();
       Node* store = BuildKeyedStore(object, key, value, feedback);
       environment()->Push(value);
-      store_states.AddToNode(store, expr->AssignmentId(),
-                             OutputFrameStateCombine::Ignore());
+      PrepareFrameState(store, expr->AssignmentId(),
+                        OutputFrameStateCombine::Ignore());
       environment()->Pop();
       break;
     }
@@ -2749,8 +2791,8 @@
       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
       Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
       environment()->Push(value);
-      store_states.AddToNode(store, expr->AssignmentId(),
-                             OutputFrameStateCombine::Ignore());
+      PrepareFrameState(store, expr->AssignmentId(),
+                        OutputFrameStateCombine::Ignore());
       environment()->Pop();
       break;
     }
@@ -2760,8 +2802,8 @@
       Node* receiver = environment()->Pop();
       Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
       environment()->Push(value);
-      store_states.AddToNode(store, expr->AssignmentId(),
-                             OutputFrameStateCombine::Ignore());
+      PrepareFrameState(store, expr->AssignmentId(),
+                        OutputFrameStateCombine::Ignore());
       environment()->Pop();
       break;
     }
@@ -2801,19 +2843,19 @@
   const Operator* op = nullptr;
   switch (expr->op()) {
     case Token::EQ:
-      op = javascript()->Equal();
+      op = javascript()->Equal(CompareOperationHints::Any());
       break;
     case Token::EQ_STRICT:
-      op = javascript()->StrictEqual();
+      op = javascript()->StrictEqual(CompareOperationHints::Any());
       break;
     default:
       UNREACHABLE();
   }
   VisitForValue(sub_expr);
-  FrameStateBeforeAndAfter states(this, sub_expr->id());
+  PrepareEagerCheckpoint(sub_expr->id());
   Node* value_to_compare = environment()->Pop();
   Node* value = NewNode(op, value_to_compare, nil_value);
-  states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
+  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
   return ast_context()->ProduceValue(value);
 }
 
@@ -2821,11 +2863,11 @@
                                                 Expression* sub_expr,
                                                 Handle<String> check) {
   VisitTypeofExpression(sub_expr);
-  FrameStateBeforeAndAfter states(this, sub_expr->id());
+  PrepareEagerCheckpoint(sub_expr->id());
   Node* typeof_arg = NewNode(javascript()->TypeOf(), environment()->Pop());
-  Node* value = NewNode(javascript()->StrictEqual(), typeof_arg,
-                        jsgraph()->Constant(check));
-  states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
+  Node* value = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
+                        typeof_arg, jsgraph()->Constant(check));
+  PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
   return ast_context()->ProduceValue(value);
 }
 
@@ -2846,34 +2888,40 @@
     return VisitLiteralCompareNil(expr, sub_expr, jsgraph()->NullConstant());
   }
 
+  CompareOperationHints hints;
+  if (!type_hint_analysis_ ||
+      !type_hint_analysis_->GetCompareOperationHints(
+          expr->CompareOperationFeedbackId(), &hints)) {
+    hints = CompareOperationHints::Any();
+  }
+
   const Operator* op;
   switch (expr->op()) {
     case Token::EQ:
-      op = javascript()->Equal();
+      op = javascript()->Equal(hints);
       break;
     case Token::NE:
-      op = javascript()->NotEqual();
+      op = javascript()->NotEqual(hints);
       break;
     case Token::EQ_STRICT:
-      op = javascript()->StrictEqual();
+      op = javascript()->StrictEqual(hints);
       break;
     case Token::NE_STRICT:
-      op = javascript()->StrictNotEqual();
+      op = javascript()->StrictNotEqual(hints);
       break;
     case Token::LT:
-      op = javascript()->LessThan();
+      op = javascript()->LessThan(hints);
       break;
     case Token::GT:
-      op = javascript()->GreaterThan();
+      op = javascript()->GreaterThan(hints);
       break;
     case Token::LTE:
-      op = javascript()->LessThanOrEqual();
+      op = javascript()->LessThanOrEqual(hints);
       break;
     case Token::GTE:
-      op = javascript()->GreaterThanOrEqual();
+      op = javascript()->GreaterThanOrEqual(hints);
       break;
     case Token::INSTANCEOF:
-      DCHECK(!FLAG_harmony_instanceof);
       op = javascript()->InstanceOf();
       break;
     case Token::IN:
@@ -2939,9 +2987,7 @@
   Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
       static_cast<int>(globals()->size()), TENURED);
   for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
-  int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
-                      DeclareGlobalsNativeFlag::encode(info()->is_native()) |
-                      DeclareGlobalsLanguageMode::encode(language_mode());
+  int encoded_flags = info()->GetDeclareGlobalsFlags();
   Node* flags = jsgraph()->Constant(encoded_flags);
   Node* pairs = jsgraph()->Constant(data);
   const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals);
@@ -3014,9 +3060,9 @@
     // perform a non-contextual load in case the operand is a variable proxy.
     VariableProxy* proxy = expr->AsVariableProxy();
     VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
-    FrameStateBeforeAndAfter states(this, BeforeId(proxy));
+    PrepareEagerCheckpoint(BeforeId(proxy));
     Node* load =
-        BuildVariableLoad(proxy->var(), expr->id(), states, pair,
+        BuildVariableLoad(proxy->var(), expr->id(), pair,
                           OutputFrameStateCombine::Push(), INSIDE_TYPEOF);
     environment()->Push(load);
   } else {
@@ -3084,7 +3130,7 @@
 
 VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(
     FeedbackVectorSlot slot) const {
-  return VectorSlotPair(handle(info()->shared_info()->feedback_vector()), slot);
+  return VectorSlotPair(handle(info()->closure()->feedback_vector()), slot);
 }
 
 
@@ -3183,7 +3229,7 @@
 
 
 Node* AstGraphBuilder::BuildLocalFunctionContext(Scope* scope) {
-  DCHECK(scope->is_function_scope());
+  DCHECK(scope->is_function_scope() || scope->is_eval_scope());
 
   // Allocate a new local context.
   int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
@@ -3235,9 +3281,8 @@
   // Assign the object to the {arguments} variable. This should never lazy
   // deopt, so it is fine to send invalid bailout id.
   DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
-  FrameStateBeforeAndAfter states(this, BailoutId::None());
   BuildVariableAssignment(arguments, object, Token::ASSIGN, VectorSlotPair(),
-                          BailoutId::None(), states);
+                          BailoutId::None());
   return object;
 }
 
@@ -3254,9 +3299,8 @@
   // Assign the object to the {rest} variable. This should never lazy
   // deopt, so it is fine to send invalid bailout id.
   DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
-  FrameStateBeforeAndAfter states(this, BailoutId::None());
   BuildVariableAssignment(rest, object, Token::ASSIGN, VectorSlotPair(),
-                          BailoutId::None(), states);
+                          BailoutId::None());
   return object;
 }
 
@@ -3269,9 +3313,8 @@
 
   // Assign the object to the {.this_function} variable. This should never lazy
   // deopt, so it is fine to send invalid bailout id.
-  FrameStateBeforeAndAfter states(this, BailoutId::None());
   BuildVariableAssignment(this_function_var, this_function, Token::INIT,
-                          VectorSlotPair(), BailoutId::None(), states);
+                          VectorSlotPair(), BailoutId::None());
   return this_function;
 }
 
@@ -3284,29 +3327,19 @@
 
   // Assign the object to the {new.target} variable. This should never lazy
   // deopt, so it is fine to send invalid bailout id.
-  FrameStateBeforeAndAfter states(this, BailoutId::None());
   BuildVariableAssignment(new_target_var, object, Token::INIT, VectorSlotPair(),
-                          BailoutId::None(), states);
+                          BailoutId::None());
   return object;
 }
 
 
-Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole,
-                                            Node* not_hole) {
-  Node* the_hole = jsgraph()->TheHoleConstant();
-  Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
-  return NewNode(
-      common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
-      check, for_hole, not_hole);
-}
-
-
 Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable,
                                                Node* not_hole,
                                                BailoutId bailout_id) {
   IfBuilder hole_check(this);
   Node* the_hole = jsgraph()->TheHoleConstant();
-  Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
+  Node* check = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
+                        value, the_hole);
   hole_check.If(check);
   hole_check.Then();
   Node* error = BuildThrowReferenceError(variable, bailout_id);
@@ -3323,7 +3356,8 @@
                                                BailoutId bailout_id) {
   IfBuilder hole_check(this);
   Node* the_hole = jsgraph()->TheHoleConstant();
-  Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
+  Node* check = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
+                        value, the_hole);
   hole_check.If(check);
   hole_check.Then();
   environment()->Push(for_hole);
@@ -3340,7 +3374,8 @@
   IfBuilder prototype_check(this);
   Node* prototype_string =
       jsgraph()->Constant(isolate()->factory()->prototype_string());
-  Node* check = NewNode(javascript()->StrictEqual(), name, prototype_string);
+  Node* check = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
+                        name, prototype_string);
   prototype_check.If(check);
   prototype_check.Then();
   Node* error = BuildThrowStaticPrototypeError(bailout_id);
@@ -3354,7 +3389,6 @@
 
 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
                                          BailoutId bailout_id,
-                                         FrameStateBeforeAndAfter& states,
                                          const VectorSlotPair& feedback,
                                          OutputFrameStateCombine combine,
                                          TypeofMode typeof_mode) {
@@ -3367,22 +3401,14 @@
       Handle<Name> name = variable->name();
       if (Node* node = TryLoadGlobalConstant(name)) return node;
       Node* value = BuildGlobalLoad(name, feedback, typeof_mode);
-      states.AddToNode(value, bailout_id, combine);
+      PrepareFrameState(value, bailout_id, combine);
       return value;
     }
     case VariableLocation::PARAMETER:
     case VariableLocation::LOCAL: {
       // Local var, const, or let variable.
       Node* value = environment()->Lookup(variable);
-      if (mode == CONST_LEGACY) {
-        // Perform check for uninitialized legacy const variables.
-        if (value->op() == the_hole->op()) {
-          value = jsgraph()->UndefinedConstant();
-        } else if (value->opcode() == IrOpcode::kPhi) {
-          Node* undefined = jsgraph()->UndefinedConstant();
-          value = BuildHoleCheckSilent(value, undefined, value);
-        }
-      } else if (mode == LET || mode == CONST) {
+      if (mode == LET || mode == CONST) {
         // Perform check for uninitialized let/const variables.
         if (value->op() == the_hole->op()) {
           value = BuildThrowReferenceError(variable, bailout_id);
@@ -3402,11 +3428,7 @@
       // TODO(titzer): initialization checks are redundant for already
       // initialized immutable context loads, but only specialization knows.
       // Maybe specializer should be a parameter to the graph builder?
-      if (mode == CONST_LEGACY) {
-        // Perform check for uninitialized legacy const variables.
-        Node* undefined = jsgraph()->UndefinedConstant();
-        value = BuildHoleCheckSilent(value, undefined, value);
-      } else if (mode == LET || mode == CONST) {
+      if (mode == LET || mode == CONST) {
         // Perform check for uninitialized let/const variables.
         value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
       }
@@ -3415,13 +3437,12 @@
     case VariableLocation::LOOKUP: {
       // Dynamic lookup of context variable (anywhere in the chain).
       Handle<String> name = variable->name();
-      if (Node* node =
-              TryLoadDynamicVariable(variable, name, bailout_id, states,
-                                     feedback, combine, typeof_mode)) {
+      if (Node* node = TryLoadDynamicVariable(variable, name, bailout_id,
+                                              feedback, combine, typeof_mode)) {
         return node;
       }
       Node* value = BuildDynamicLoad(name, typeof_mode);
-      states.AddToNode(value, bailout_id, combine);
+      PrepareFrameState(value, bailout_id, combine);
       return value;
     }
   }
@@ -3464,11 +3485,10 @@
   return nullptr;
 }
 
-
 Node* AstGraphBuilder::BuildVariableAssignment(
     Variable* variable, Node* value, Token::Value op,
     const VectorSlotPair& feedback, BailoutId bailout_id,
-    FrameStateBeforeAndAfter& states, OutputFrameStateCombine combine) {
+    OutputFrameStateCombine combine) {
   Node* the_hole = jsgraph()->TheHoleConstant();
   VariableMode mode = variable->mode();
   switch (variable->location()) {
@@ -3477,19 +3497,13 @@
       // Global var, const, or let variable.
       Handle<Name> name = variable->name();
       Node* store = BuildGlobalStore(name, value, feedback);
-      states.AddToNode(store, bailout_id, combine);
+      PrepareFrameState(store, bailout_id, combine);
       return store;
     }
     case VariableLocation::PARAMETER:
     case VariableLocation::LOCAL:
       // Local var, const, or let variable.
-      if (mode == CONST_LEGACY && op == Token::INIT) {
-        // Perform an initialization check for legacy const variables.
-        Node* current = environment()->Lookup(variable);
-        if (current->op() != the_hole->op()) {
-          value = BuildHoleCheckSilent(current, value, current);
-        }
-      } else if (mode == CONST_LEGACY && op != Token::INIT) {
+      if (mode == CONST_LEGACY && op != Token::INIT) {
         // Non-initializing assignment to legacy const is
         // - exception in strict mode.
         // - ignored in sloppy mode.
@@ -3534,13 +3548,7 @@
     case VariableLocation::CONTEXT: {
       // Context variable (potentially up the context chain).
       int depth = current_scope()->ContextChainLength(variable->scope());
-      if (mode == CONST_LEGACY && op == Token::INIT) {
-        // Perform an initialization check for legacy const variables.
-        const Operator* op =
-            javascript()->LoadContext(depth, variable->index(), false);
-        Node* current = NewNode(op, current_context());
-        value = BuildHoleCheckSilent(current, value, current);
-      } else if (mode == CONST_LEGACY && op != Token::INIT) {
+      if (mode == CONST_LEGACY && op != Token::INIT) {
         // Non-initializing assignment to legacy const is
         // - exception in strict mode.
         // - ignored in sloppy mode.
@@ -3578,8 +3586,6 @@
     case VariableLocation::LOOKUP: {
       // Dynamic lookup of context variable (anywhere in the chain).
       Handle<Name> name = variable->name();
-      // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for
-      // initializations of const declarations.
       Node* store = BuildDynamicStore(name, value);
       PrepareFrameState(store, bailout_id, combine);
       return store;
@@ -3751,11 +3757,11 @@
   Expression* expr = property->value();
   if (!FunctionLiteral::NeedsHomeObject(expr)) return value;
   Handle<Name> name = isolate()->factory()->home_object_symbol();
-  FrameStateBeforeAndAfter states(this, BailoutId::None());
   VectorSlotPair feedback =
       CreateVectorSlotPair(property->GetSlot(slot_number));
   Node* store = BuildNamedStore(value, name, home_object, feedback);
-  states.AddToNode(store, BailoutId::None(), OutputFrameStateCombine::Ignore());
+  PrepareFrameState(store, BailoutId::None(),
+                    OutputFrameStateCombine::Ignore());
   return store;
 }
 
@@ -3892,11 +3898,12 @@
   return nullptr;
 }
 
-
-Node* AstGraphBuilder::TryLoadDynamicVariable(
-    Variable* variable, Handle<String> name, BailoutId bailout_id,
-    FrameStateBeforeAndAfter& states, const VectorSlotPair& feedback,
-    OutputFrameStateCombine combine, TypeofMode typeof_mode) {
+Node* AstGraphBuilder::TryLoadDynamicVariable(Variable* variable,
+                                              Handle<String> name,
+                                              BailoutId bailout_id,
+                                              const VectorSlotPair& feedback,
+                                              OutputFrameStateCombine combine,
+                                              TypeofMode typeof_mode) {
   VariableMode mode = variable->mode();
 
   if (mode == DYNAMIC_GLOBAL) {
@@ -3918,8 +3925,9 @@
       Node* load = NewNode(
           javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
           current_context());
-      Node* check = NewNode(javascript()->StrictEqual(), load,
-                            jsgraph()->TheHoleConstant());
+      Node* check =
+          NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), load,
+                  jsgraph()->TheHoleConstant());
       fast_block.BreakUnless(check, BranchHint::kTrue);
     }
 
@@ -3929,7 +3937,7 @@
     } else {
       // Perform global slot load.
       Node* fast = BuildGlobalLoad(name, feedback, typeof_mode);
-      states.AddToNode(fast, bailout_id, combine);
+      PrepareFrameState(fast, bailout_id, combine);
       environment()->Push(fast);
     }
     slow_block.Break();
@@ -3938,7 +3946,7 @@
 
     // Slow case, because variable potentially shadowed. Perform dynamic lookup.
     Node* slow = BuildDynamicLoad(name, typeof_mode);
-    states.AddToNode(slow, bailout_id, combine);
+    PrepareFrameState(slow, bailout_id, combine);
     environment()->Push(slow);
     slow_block.EndBlock();
 
@@ -3964,16 +3972,17 @@
       Node* load = NewNode(
           javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
           current_context());
-      Node* check = NewNode(javascript()->StrictEqual(), load,
-                            jsgraph()->TheHoleConstant());
+      Node* check =
+          NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), load,
+                  jsgraph()->TheHoleConstant());
       fast_block.BreakUnless(check, BranchHint::kTrue);
     }
 
     // Fast case, because variable is not shadowed. Perform context slot load.
     Variable* local = variable->local_if_not_shadowed();
     DCHECK(local->location() == VariableLocation::CONTEXT);  // Must be context.
-    Node* fast = BuildVariableLoad(local, bailout_id, states, feedback, combine,
-                                   typeof_mode);
+    Node* fast =
+        BuildVariableLoad(local, bailout_id, feedback, combine, typeof_mode);
     environment()->Push(fast);
     slow_block.Break();
     environment()->Pop();
@@ -3981,7 +3990,7 @@
 
     // Slow case, because variable potentially shadowed. Perform dynamic lookup.
     Node* slow = BuildDynamicLoad(name, typeof_mode);
-    states.AddToNode(slow, bailout_id, combine);
+    PrepareFrameState(slow, bailout_id, combine);
     environment()->Push(slow);
     slow_block.EndBlock();
 
@@ -4064,6 +4073,20 @@
   }
 }
 
+void AstGraphBuilder::PrepareEagerCheckpoint(BailoutId ast_id) {
+  if (environment()->GetEffectDependency()->opcode() == IrOpcode::kCheckpoint) {
+    // We skip preparing a checkpoint if there already is one the current effect
+    // dependency. This is just an optimization and not need for correctness.
+    return;
+  }
+  if (ast_id != BailoutId::None()) {
+    Node* node = NewNode(common()->Checkpoint());
+    DCHECK_EQ(IrOpcode::kDead,
+              NodeProperties::GetFrameStateInput(node, 0)->opcode());
+    NodeProperties::ReplaceFrameStateInput(node, 0,
+                                           environment()->Checkpoint(ast_id));
+  }
+}
 
 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop(
     IterationStatement* stmt) {
@@ -4309,7 +4332,6 @@
 }
 
 
-// TODO(mstarzinger): Revisit this once we have proper effect states.
 Node* AstGraphBuilder::NewEffectPhi(int count, Node* input, Node* control) {
   const Operator* phi_op = common()->EffectPhi(count);
   Node** buffer = EnsureInputBufferSize(count + 1);
diff --git a/src/compiler/ast-graph-builder.h b/src/compiler/ast-graph-builder.h
index e206db0..8346a51 100644
--- a/src/compiler/ast-graph-builder.h
+++ b/src/compiler/ast-graph-builder.h
@@ -15,7 +15,7 @@
 
 // Forward declarations.
 class BitVector;
-
+class CompilationInfo;
 
 namespace compiler {
 
@@ -106,6 +106,9 @@
   // Optimization to cache loaded feedback vector.
   SetOncePointer<Node> feedback_vector_;
 
+  // Optimization to cache empty frame state.
+  SetOncePointer<Node> empty_frame_state_;
+
   // Control nodes that exit the function body.
   ZoneVector<Node*> exit_controls_;
 
@@ -167,6 +170,9 @@
   // Get or create the node that represents the incoming new target value.
   Node* GetNewTarget();
 
+  // Get or create the node that represents the empty frame state.
+  Node* GetEmptyFrameState();
+
   // Node creation helpers.
   Node* NewNode(const Operator* op, bool incomplete = false) {
     return MakeNode(op, 0, static_cast<Node**>(nullptr), incomplete);
@@ -225,11 +231,18 @@
   // Helper to indicate a node exits the function body.
   void UpdateControlDependencyToLeaveFunction(Node* exit);
 
-  // Builds deoptimization for a given node.
+  // Prepare information for lazy deoptimization. This information is attached
+  // to the given node and the output value produced by the node is combined.
+  // Conceptually this frame state is "after" a given operation.
   void PrepareFrameState(Node* node, BailoutId ast_id,
                          OutputFrameStateCombine framestate_combine =
                              OutputFrameStateCombine::Ignore());
 
+  // Prepare information for eager deoptimization. This information is carried
+  // by dedicated {Checkpoint} nodes that are wired into the effect chain.
+  // Conceptually this frame state is "before" a given operation.
+  void PrepareEagerCheckpoint(BailoutId ast_id);
+
   BitVector* GetVariablesAssignedInLoop(IterationStatement* stmt);
 
   // Check if the given statement is an OSR entry.
@@ -277,13 +290,11 @@
   Node* BuildVariableAssignment(Variable* variable, Node* value,
                                 Token::Value op, const VectorSlotPair& slot,
                                 BailoutId bailout_id,
-                                FrameStateBeforeAndAfter& states,
                                 OutputFrameStateCombine framestate_combine =
                                     OutputFrameStateCombine::Ignore());
   Node* BuildVariableDelete(Variable* variable, BailoutId bailout_id,
                             OutputFrameStateCombine framestate_combine);
   Node* BuildVariableLoad(Variable* variable, BailoutId bailout_id,
-                          FrameStateBeforeAndAfter& states,
                           const VectorSlotPair& feedback,
                           OutputFrameStateCombine framestate_combine,
                           TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
@@ -341,7 +352,6 @@
   Node* BuildThrowUnsupportedSuperError(BailoutId bailout_id);
 
   // Builders for dynamic hole-checks at runtime.
-  Node* BuildHoleCheckSilent(Node* value, Node* for_hole, Node* not_hole);
   Node* BuildHoleCheckThenThrow(Node* value, Variable* var, Node* not_hole,
                                 BailoutId bailout_id);
   Node* BuildHoleCheckElseThrow(Node* value, Variable* var, Node* for_hole,
@@ -375,7 +385,6 @@
   // to resolve to a global slot or context slot (inferred from scope chain).
   Node* TryLoadDynamicVariable(Variable* variable, Handle<String> name,
                                BailoutId bailout_id,
-                               FrameStateBeforeAndAfter& states,
                                const VectorSlotPair& feedback,
                                OutputFrameStateCombine combine,
                                TypeofMode typeof_mode);
diff --git a/src/compiler/ast-loop-assignment-analyzer.cc b/src/compiler/ast-loop-assignment-analyzer.cc
index ac96399..334c597 100644
--- a/src/compiler/ast-loop-assignment-analyzer.cc
+++ b/src/compiler/ast-loop-assignment-analyzer.cc
@@ -265,8 +265,9 @@
 void ALAA::VisitForOfStatement(ForOfStatement* loop) {
   Visit(loop->assign_iterator());
   Enter(loop);
+  Visit(loop->next_result());
+  Visit(loop->result_done());
   Visit(loop->assign_each());
-  Visit(loop->subject());
   Visit(loop->body());
   Exit(loop);
 }
diff --git a/src/compiler/ast-loop-assignment-analyzer.h b/src/compiler/ast-loop-assignment-analyzer.h
index 1696911..a4a4609 100644
--- a/src/compiler/ast-loop-assignment-analyzer.h
+++ b/src/compiler/ast-loop-assignment-analyzer.h
@@ -12,8 +12,9 @@
 namespace v8 {
 namespace internal {
 
-class Variable;
+class CompilationInfo;
 class Scope;
+class Variable;
 
 namespace compiler {
 
diff --git a/src/compiler/branch-elimination.cc b/src/compiler/branch-elimination.cc
index 427612c..236fbca 100644
--- a/src/compiler/branch-elimination.cc
+++ b/src/compiler/branch-elimination.cc
@@ -99,17 +99,17 @@
   if (condition_value.IsJust()) {
     // If we know the condition we can discard the branch.
     if (condition_is_true == condition_value.FromJust()) {
-      // We don't to update the conditions here, because we're replacing with
-      // the {control} node that already contains the right information.
-      return Replace(control);
+      // We don't update the conditions here, because we're replacing {node}
+      // with the {control} node that already contains the right information.
+      ReplaceWithValue(node, dead(), effect, control);
     } else {
       control = graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
                                  frame_state, effect, control);
       // TODO(bmeurer): This should be on the AdvancedReducer somehow.
       NodeProperties::MergeControlToEnd(graph(), common(), control);
       Revisit(graph()->end());
-      return Replace(dead());
     }
+    return Replace(dead());
   }
   return UpdateConditions(
       node, conditions->AddCondition(zone_, condition, condition_is_true));
diff --git a/src/compiler/bytecode-graph-builder.cc b/src/compiler/bytecode-graph-builder.cc
index 2249cbc..79d8ff2 100644
--- a/src/compiler/bytecode-graph-builder.cc
+++ b/src/compiler/bytecode-graph-builder.cc
@@ -109,6 +109,11 @@
         id_before, OutputFrameStateCombine::Ignore());
     id_after_ = BailoutId(id_before.ToInt() +
                           builder->bytecode_iterator().current_bytecode_size());
+    // Create an explicit checkpoint node for before the operation.
+    Node* node = builder_->NewNode(builder_->common()->Checkpoint());
+    DCHECK_EQ(IrOpcode::kDead,
+              NodeProperties::GetFrameStateInput(node, 0)->opcode());
+    NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_before_);
   }
 
   ~FrameStateBeforeAndAfter() {
@@ -136,6 +141,7 @@
 
     if (count >= 2) {
       // Add the frame state for before the operation.
+      // TODO(mstarzinger): Get rid of frame state input before!
       DCHECK_EQ(IrOpcode::kDead,
                 NodeProperties::GetFrameStateInput(node, 1)->opcode());
       NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_);
@@ -355,9 +361,6 @@
 
 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate(
     Node** state_values, int offset, int count) {
-  if (!builder()->deoptimization_enabled_) {
-    return false;
-  }
   if (*state_values == nullptr) {
     return true;
   }
@@ -385,10 +388,6 @@
 
 Node* BytecodeGraphBuilder::Environment::Checkpoint(
     BailoutId bailout_id, OutputFrameStateCombine combine) {
-  if (!builder()->deoptimization_enabled_) {
-    return builder()->jsgraph()->EmptyFrameState();
-  }
-
   // TODO(rmcilroy): Consider using StateValuesCache for some state values.
   UpdateStateValues(&parameters_state_values_, 0, parameter_count());
   UpdateStateValues(&registers_state_values_, register_base(),
@@ -423,7 +422,6 @@
 
 bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate(
     int output_poke_offset, int output_poke_count) {
-  if (!builder()->deoptimization_enabled_) return true;
   // Poke offset is relative to the top of the stack (i.e., the accumulator).
   int output_poke_start = accumulator_base() - output_poke_offset;
   int output_poke_end = output_poke_start + output_poke_count;
@@ -444,12 +442,11 @@
       bytecode_array_(handle(info->shared_info()->bytecode_array())),
       exception_handler_table_(
           handle(HandlerTable::cast(bytecode_array()->handler_table()))),
-      feedback_vector_(handle(info->shared_info()->feedback_vector())),
+      feedback_vector_(handle(info->closure()->feedback_vector())),
       frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
           FrameStateType::kInterpretedFunction,
           bytecode_array()->parameter_count(),
           bytecode_array()->register_count(), info->shared_info())),
-      deoptimization_enabled_(info->is_deoptimization_enabled()),
       merge_environments_(local_zone),
       exception_handlers_(local_zone),
       current_exception_handler_(0),
@@ -586,6 +583,11 @@
   environment()->BindAccumulator(node);
 }
 
+void BytecodeGraphBuilder::VisitLdrUndefined() {
+  Node* node = jsgraph()->UndefinedConstant();
+  environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), node);
+}
+
 void BytecodeGraphBuilder::VisitLdaNull() {
   Node* node = jsgraph()->NullConstant();
   environment()->BindAccumulator(node);
@@ -623,25 +625,33 @@
   environment()->BindRegister(bytecode_iterator().GetRegisterOperand(1), value);
 }
 
-void BytecodeGraphBuilder::BuildLoadGlobal(
-    TypeofMode typeof_mode) {
-  FrameStateBeforeAndAfter states(this);
-  Handle<Name> name =
-      Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
+Node* BytecodeGraphBuilder::BuildLoadGlobal(TypeofMode typeof_mode) {
   VectorSlotPair feedback =
-      CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1));
-
+      CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(0));
+  DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC,
+            feedback_vector()->GetKind(feedback.slot()));
+  Handle<Name> name(feedback_vector()->GetName(feedback.slot()));
   const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
-  Node* node = NewNode(op, GetFunctionClosure());
-  environment()->BindAccumulator(node, &states);
+  return NewNode(op, GetFunctionClosure());
 }
 
 void BytecodeGraphBuilder::VisitLdaGlobal() {
-  BuildLoadGlobal(TypeofMode::NOT_INSIDE_TYPEOF);
+  FrameStateBeforeAndAfter states(this);
+  Node* node = BuildLoadGlobal(TypeofMode::NOT_INSIDE_TYPEOF);
+  environment()->BindAccumulator(node, &states);
+}
+
+void BytecodeGraphBuilder::VisitLdrGlobal() {
+  FrameStateBeforeAndAfter states(this);
+  Node* node = BuildLoadGlobal(TypeofMode::NOT_INSIDE_TYPEOF);
+  environment()->BindRegister(bytecode_iterator().GetRegisterOperand(1), node,
+                              &states);
 }
 
 void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeof() {
-  BuildLoadGlobal(TypeofMode::INSIDE_TYPEOF);
+  FrameStateBeforeAndAfter states(this);
+  Node* node = BuildLoadGlobal(TypeofMode::INSIDE_TYPEOF);
+  environment()->BindAccumulator(node, &states);
 }
 
 void BytecodeGraphBuilder::BuildStoreGlobal(LanguageMode language_mode) {
@@ -665,7 +675,7 @@
   BuildStoreGlobal(LanguageMode::STRICT);
 }
 
-void BytecodeGraphBuilder::VisitLdaContextSlot() {
+Node* BytecodeGraphBuilder::BuildLoadContextSlot() {
   // TODO(mythria): LoadContextSlots are unrolled by the required depth when
   // generating bytecode. Hence the value of depth is always 0. Update this
   // code, when the implementation changes.
@@ -676,10 +686,19 @@
       0, bytecode_iterator().GetIndexOperand(1), false);
   Node* context =
       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
-  Node* node = NewNode(op, context);
+  return NewNode(op, context);
+}
+
+void BytecodeGraphBuilder::VisitLdaContextSlot() {
+  Node* node = BuildLoadContextSlot();
   environment()->BindAccumulator(node);
 }
 
+void BytecodeGraphBuilder::VisitLdrContextSlot() {
+  Node* node = BuildLoadContextSlot();
+  environment()->BindRegister(bytecode_iterator().GetRegisterOperand(2), node);
+}
+
 void BytecodeGraphBuilder::VisitStaContextSlot() {
   // TODO(mythria): LoadContextSlots are unrolled by the required depth when
   // generating bytecode. Hence the value of depth is always 0. Update this
@@ -732,8 +751,7 @@
   BuildStaLookupSlot(LanguageMode::STRICT);
 }
 
-void BytecodeGraphBuilder::BuildNamedLoad() {
-  FrameStateBeforeAndAfter states(this);
+Node* BytecodeGraphBuilder::BuildNamedLoad() {
   Node* object =
       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
   Handle<Name> name =
@@ -742,14 +760,23 @@
       CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
 
   const Operator* op = javascript()->LoadNamed(name, feedback);
-  Node* node = NewNode(op, object, GetFunctionClosure());
+  return NewNode(op, object, GetFunctionClosure());
+}
+
+void BytecodeGraphBuilder::VisitLdaNamedProperty() {
+  FrameStateBeforeAndAfter states(this);
+  Node* node = BuildNamedLoad();
   environment()->BindAccumulator(node, &states);
 }
 
-void BytecodeGraphBuilder::VisitLoadIC() { BuildNamedLoad(); }
-
-void BytecodeGraphBuilder::BuildKeyedLoad() {
+void BytecodeGraphBuilder::VisitLdrNamedProperty() {
   FrameStateBeforeAndAfter states(this);
+  Node* node = BuildNamedLoad();
+  environment()->BindRegister(bytecode_iterator().GetRegisterOperand(3), node,
+                              &states);
+}
+
+Node* BytecodeGraphBuilder::BuildKeyedLoad() {
   Node* key = environment()->LookupAccumulator();
   Node* object =
       environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
@@ -757,11 +784,21 @@
       CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1));
 
   const Operator* op = javascript()->LoadProperty(feedback);
-  Node* node = NewNode(op, object, key, GetFunctionClosure());
+  return NewNode(op, object, key, GetFunctionClosure());
+}
+
+void BytecodeGraphBuilder::VisitLdaKeyedProperty() {
+  FrameStateBeforeAndAfter states(this);
+  Node* node = BuildKeyedLoad();
   environment()->BindAccumulator(node, &states);
 }
 
-void BytecodeGraphBuilder::VisitKeyedLoadIC() { BuildKeyedLoad(); }
+void BytecodeGraphBuilder::VisitLdrKeyedProperty() {
+  FrameStateBeforeAndAfter states(this);
+  Node* node = BuildKeyedLoad();
+  environment()->BindRegister(bytecode_iterator().GetRegisterOperand(2), node,
+                              &states);
+}
 
 void BytecodeGraphBuilder::BuildNamedStore(LanguageMode language_mode) {
   FrameStateBeforeAndAfter states(this);
@@ -778,11 +815,11 @@
   environment()->RecordAfterState(node, &states);
 }
 
-void BytecodeGraphBuilder::VisitStoreICSloppy() {
+void BytecodeGraphBuilder::VisitStaNamedPropertySloppy() {
   BuildNamedStore(LanguageMode::SLOPPY);
 }
 
-void BytecodeGraphBuilder::VisitStoreICStrict() {
+void BytecodeGraphBuilder::VisitStaNamedPropertyStrict() {
   BuildNamedStore(LanguageMode::STRICT);
 }
 
@@ -801,11 +838,11 @@
   environment()->RecordAfterState(node, &states);
 }
 
-void BytecodeGraphBuilder::VisitKeyedStoreICSloppy() {
+void BytecodeGraphBuilder::VisitStaKeyedPropertySloppy() {
   BuildKeyedStore(LanguageMode::SLOPPY);
 }
 
-void BytecodeGraphBuilder::VisitKeyedStoreICStrict() {
+void BytecodeGraphBuilder::VisitStaKeyedPropertyStrict() {
   BuildKeyedStore(LanguageMode::STRICT);
 }
 
@@ -882,7 +919,9 @@
   Handle<FixedArray> constant_properties = Handle<FixedArray>::cast(
       bytecode_iterator().GetConstantForIndexOperand(0));
   int literal_index = bytecode_iterator().GetIndexOperand(1);
-  int literal_flags = bytecode_iterator().GetFlagOperand(2);
+  int bytecode_flags = bytecode_iterator().GetFlagOperand(2);
+  int literal_flags =
+      interpreter::CreateObjectLiteralFlags::FlagsBits::decode(bytecode_flags);
   // TODO(mstarzinger): Thread through number of properties.
   int number_of_properties = constant_properties->length() / 2;
   const Operator* op = javascript()->CreateLiteralObject(
@@ -963,8 +1002,7 @@
 
 void BytecodeGraphBuilder::VisitCallRuntime() {
   FrameStateBeforeAndAfter states(this);
-  Runtime::FunctionId functionId = static_cast<Runtime::FunctionId>(
-      bytecode_iterator().GetRuntimeIdOperand(0));
+  Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0);
   interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
   size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
 
@@ -976,8 +1014,7 @@
 
 void BytecodeGraphBuilder::VisitCallRuntimeForPair() {
   FrameStateBeforeAndAfter states(this);
-  Runtime::FunctionId functionId = static_cast<Runtime::FunctionId>(
-      bytecode_iterator().GetRuntimeIdOperand(0));
+  Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0);
   interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
   size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
   interpreter::Register first_return =
@@ -991,8 +1028,7 @@
 
 void BytecodeGraphBuilder::VisitInvokeIntrinsic() {
   FrameStateBeforeAndAfter states(this);
-  Runtime::FunctionId functionId = static_cast<Runtime::FunctionId>(
-      bytecode_iterator().GetRuntimeIdOperand(0));
+  Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0);
   interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
   size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
 
@@ -1121,9 +1157,11 @@
 
 void BytecodeGraphBuilder::VisitInc() {
   FrameStateBeforeAndAfter states(this);
-  const Operator* js_op = javascript()->Add(BinaryOperationHints::Any());
+  // Note: Use subtract -1 here instead of add 1 to ensure we always convert to
+  // a number, not a string.
+  const Operator* js_op = javascript()->Subtract(BinaryOperationHints::Any());
   Node* node = NewNode(js_op, environment()->LookupAccumulator(),
-                       jsgraph()->OneConstant());
+                       jsgraph()->Constant(-1.0));
   environment()->BindAccumulator(node, &states);
 }
 
@@ -1136,6 +1174,13 @@
 }
 
 void BytecodeGraphBuilder::VisitLogicalNot() {
+  Node* value = environment()->LookupAccumulator();
+  Node* node = NewNode(common()->Select(MachineRepresentation::kTagged), value,
+                       jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
+  environment()->BindAccumulator(node);
+}
+
+void BytecodeGraphBuilder::VisitToBooleanLogicalNot() {
   Node* value = NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
                         environment()->LookupAccumulator());
   Node* node = NewNode(common()->Select(MachineRepresentation::kTagged), value,
@@ -1177,31 +1222,38 @@
 }
 
 void BytecodeGraphBuilder::VisitTestEqual() {
-  BuildCompareOp(javascript()->Equal());
+  CompareOperationHints hints = CompareOperationHints::Any();
+  BuildCompareOp(javascript()->Equal(hints));
 }
 
 void BytecodeGraphBuilder::VisitTestNotEqual() {
-  BuildCompareOp(javascript()->NotEqual());
+  CompareOperationHints hints = CompareOperationHints::Any();
+  BuildCompareOp(javascript()->NotEqual(hints));
 }
 
 void BytecodeGraphBuilder::VisitTestEqualStrict() {
-  BuildCompareOp(javascript()->StrictEqual());
+  CompareOperationHints hints = CompareOperationHints::Any();
+  BuildCompareOp(javascript()->StrictEqual(hints));
 }
 
 void BytecodeGraphBuilder::VisitTestLessThan() {
-  BuildCompareOp(javascript()->LessThan());
+  CompareOperationHints hints = CompareOperationHints::Any();
+  BuildCompareOp(javascript()->LessThan(hints));
 }
 
 void BytecodeGraphBuilder::VisitTestGreaterThan() {
-  BuildCompareOp(javascript()->GreaterThan());
+  CompareOperationHints hints = CompareOperationHints::Any();
+  BuildCompareOp(javascript()->GreaterThan(hints));
 }
 
 void BytecodeGraphBuilder::VisitTestLessThanOrEqual() {
-  BuildCompareOp(javascript()->LessThanOrEqual());
+  CompareOperationHints hints = CompareOperationHints::Any();
+  BuildCompareOp(javascript()->LessThanOrEqual(hints));
 }
 
 void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual() {
-  BuildCompareOp(javascript()->GreaterThanOrEqual());
+  CompareOperationHints hints = CompareOperationHints::Any();
+  BuildCompareOp(javascript()->GreaterThanOrEqual(hints));
 }
 
 void BytecodeGraphBuilder::VisitTestIn() {
@@ -1209,7 +1261,6 @@
 }
 
 void BytecodeGraphBuilder::VisitTestInstanceOf() {
-  DCHECK(!FLAG_harmony_instanceof);
   BuildCompareOp(javascript()->InstanceOf());
 }
 
@@ -1362,6 +1413,51 @@
   environment()->BindAccumulator(index, &states);
 }
 
+void BytecodeGraphBuilder::VisitSuspendGenerator() {
+  Node* state = environment()->LookupAccumulator();
+  Node* generator = environment()->LookupRegister(
+      bytecode_iterator().GetRegisterOperand(0));
+  // The offsets used by the bytecode iterator are relative to a different base
+  // than what is used in the interpreter, hence the addition.
+  Node* offset =
+      jsgraph()->Constant(bytecode_iterator().current_offset() +
+                          (BytecodeArray::kHeaderSize - kHeapObjectTag));
+
+  int register_count = environment()->register_count();
+  int value_input_count = 3 + register_count;
+
+  Node** value_inputs = local_zone()->NewArray<Node*>(value_input_count);
+  value_inputs[0] = generator;
+  value_inputs[1] = state;
+  value_inputs[2] = offset;
+  for (int i = 0; i < register_count; ++i) {
+    value_inputs[3 + i] =
+        environment()->LookupRegister(interpreter::Register(i));
+  }
+
+  MakeNode(javascript()->GeneratorStore(register_count), value_input_count,
+           value_inputs, false);
+}
+
+void BytecodeGraphBuilder::VisitResumeGenerator() {
+  FrameStateBeforeAndAfter states(this);
+
+  Node* generator = environment()->LookupRegister(
+      bytecode_iterator().GetRegisterOperand(0));
+
+  // Bijection between registers and array indices must match that used in
+  // InterpreterAssembler::ExportRegisterFile.
+  for (int i = 0; i < environment()->register_count(); ++i) {
+    Node* value = NewNode(javascript()->GeneratorRestoreRegister(i), generator);
+    environment()->BindRegister(interpreter::Register(i), value);
+  }
+
+  Node* state =
+      NewNode(javascript()->GeneratorRestoreContinuation(), generator);
+
+  environment()->BindAccumulator(state, &states);
+}
+
 void BytecodeGraphBuilder::VisitWide() {
   // Consumed by the BytecodeArrayIterator.
   UNREACHABLE();
@@ -1373,10 +1469,12 @@
 }
 
 void BytecodeGraphBuilder::VisitIllegal() {
-  // Never present in valid bytecode.
+  // Not emitted in valid bytecode.
   UNREACHABLE();
 }
 
+void BytecodeGraphBuilder::VisitNop() {}
+
 void BytecodeGraphBuilder::SwitchToMergeEnvironment(int current_offset) {
   if (merge_environments_[current_offset] != nullptr) {
     if (environment() != nullptr) {
@@ -1431,7 +1529,8 @@
 void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) {
   Node* accumulator = environment()->LookupAccumulator();
   Node* condition =
-      NewNode(javascript()->StrictEqual(), accumulator, comperand);
+      NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
+              accumulator, comperand);
   BuildConditionalJump(condition);
 }
 
@@ -1440,14 +1539,17 @@
   Node* accumulator = environment()->LookupAccumulator();
   Node* to_boolean =
       NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator);
-  Node* condition = NewNode(javascript()->StrictEqual(), to_boolean, comperand);
+  Node* condition =
+      NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
+              to_boolean, comperand);
   BuildConditionalJump(condition);
 }
 
 void BytecodeGraphBuilder::BuildJumpIfNotHole() {
   Node* accumulator = environment()->LookupAccumulator();
-  Node* condition = NewNode(javascript()->StrictEqual(), accumulator,
-                            jsgraph()->TheHoleConstant());
+  Node* condition =
+      NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
+              accumulator, jsgraph()->TheHoleConstant());
   Node* node =
       NewNode(common()->Select(MachineRepresentation::kTagged), condition,
               jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
diff --git a/src/compiler/bytecode-graph-builder.h b/src/compiler/bytecode-graph-builder.h
index c842c24..66cd96e 100644
--- a/src/compiler/bytecode-graph-builder.h
+++ b/src/compiler/bytecode-graph-builder.h
@@ -112,11 +112,12 @@
 
   void BuildCreateLiteral(const Operator* op);
   void BuildCreateArguments(CreateArgumentsType type);
-  void BuildLoadGlobal(TypeofMode typeof_mode);
+  Node* BuildLoadContextSlot();
+  Node* BuildLoadGlobal(TypeofMode typeof_mode);
   void BuildStoreGlobal(LanguageMode language_mode);
-  void BuildNamedLoad();
-  void BuildKeyedLoad();
+  Node* BuildNamedLoad();
   void BuildNamedStore(LanguageMode language_mode);
+  Node* BuildKeyedLoad();
   void BuildKeyedStore(LanguageMode language_mode);
   void BuildLdaLookupSlot(TypeofMode typeof_mode);
   void BuildStaLookupSlot(LanguageMode language_mode);
@@ -218,10 +219,6 @@
   const BytecodeBranchAnalysis* branch_analysis_;
   Environment* environment_;
 
-  // Indicates whether deoptimization support is enabled for this compilation
-  // and whether valid frame states need to be attached to deoptimizing nodes.
-  bool deoptimization_enabled_;
-
   // Merge environments are snapshots of the environment at points where the
   // control flow merges. This models a forward data flow propagation of all
   // values from all predecessors of the merge in question.
diff --git a/src/compiler/change-lowering.cc b/src/compiler/change-lowering.cc
deleted file mode 100644
index 907b36a..0000000
--- a/src/compiler/change-lowering.cc
+++ /dev/null
@@ -1,713 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/compiler/change-lowering.h"
-
-#include "src/address-map.h"
-#include "src/code-factory.h"
-#include "src/compiler/js-graph.h"
-#include "src/compiler/linkage.h"
-#include "src/compiler/machine-operator.h"
-#include "src/compiler/node-properties.h"
-#include "src/compiler/operator-properties.h"
-#include "src/compiler/simplified-operator.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-ChangeLowering::~ChangeLowering() {}
-
-
-Reduction ChangeLowering::Reduce(Node* node) {
-  Node* control = graph()->start();
-  switch (node->opcode()) {
-    case IrOpcode::kChangeBitToBool:
-      return ChangeBitToBool(node->InputAt(0), control);
-    case IrOpcode::kChangeBoolToBit:
-      return ChangeBoolToBit(node->InputAt(0));
-    case IrOpcode::kChangeFloat64ToTagged:
-      return ChangeFloat64ToTagged(node->InputAt(0), control);
-    case IrOpcode::kChangeInt32ToTagged:
-      return ChangeInt32ToTagged(node->InputAt(0), control);
-    case IrOpcode::kChangeTaggedToFloat64:
-      return ChangeTaggedToFloat64(node->InputAt(0), control);
-    case IrOpcode::kChangeTaggedToInt32:
-      return ChangeTaggedToUI32(node->InputAt(0), control, kSigned);
-    case IrOpcode::kChangeTaggedToUint32:
-      return ChangeTaggedToUI32(node->InputAt(0), control, kUnsigned);
-    case IrOpcode::kChangeUint32ToTagged:
-      return ChangeUint32ToTagged(node->InputAt(0), control);
-    case IrOpcode::kLoadField:
-      return LoadField(node);
-    case IrOpcode::kStoreField:
-      return StoreField(node);
-    case IrOpcode::kLoadElement:
-      return LoadElement(node);
-    case IrOpcode::kStoreElement:
-      return StoreElement(node);
-    case IrOpcode::kAllocate:
-      return Allocate(node);
-    case IrOpcode::kObjectIsReceiver:
-      return ObjectIsReceiver(node);
-    case IrOpcode::kObjectIsSmi:
-      return ObjectIsSmi(node);
-    case IrOpcode::kObjectIsNumber:
-      return ObjectIsNumber(node);
-    case IrOpcode::kObjectIsUndetectable:
-      return ObjectIsUndetectable(node);
-    default:
-      return NoChange();
-  }
-  UNREACHABLE();
-  return NoChange();
-}
-
-
-Node* ChangeLowering::HeapNumberValueIndexConstant() {
-  return jsgraph()->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag);
-}
-
-
-Node* ChangeLowering::SmiMaxValueConstant() {
-  return jsgraph()->Int32Constant(Smi::kMaxValue);
-}
-
-
-Node* ChangeLowering::SmiShiftBitsConstant() {
-  return jsgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize);
-}
-
-
-Node* ChangeLowering::AllocateHeapNumberWithValue(Node* value, Node* control) {
-  // The AllocateHeapNumberStub does not use the context, so we can safely pass
-  // in Smi zero here.
-  Callable callable = CodeFactory::AllocateHeapNumber(isolate());
-  Node* target = jsgraph()->HeapConstant(callable.code());
-  Node* context = jsgraph()->NoContextConstant();
-  Node* effect = graph()->NewNode(common()->BeginRegion(), graph()->start());
-  if (!allocate_heap_number_operator_.is_set()) {
-    CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
-        isolate(), jsgraph()->zone(), callable.descriptor(), 0,
-        CallDescriptor::kNoFlags, Operator::kNoThrow);
-    allocate_heap_number_operator_.set(common()->Call(descriptor));
-  }
-  Node* heap_number = graph()->NewNode(allocate_heap_number_operator_.get(),
-                                       target, context, effect, control);
-  Node* store = graph()->NewNode(
-      machine()->Store(StoreRepresentation(MachineRepresentation::kFloat64,
-                                           kNoWriteBarrier)),
-      heap_number, HeapNumberValueIndexConstant(), value, heap_number, control);
-  return graph()->NewNode(common()->FinishRegion(), heap_number, store);
-}
-
-
-Node* ChangeLowering::ChangeInt32ToFloat64(Node* value) {
-  return graph()->NewNode(machine()->ChangeInt32ToFloat64(), value);
-}
-
-
-Node* ChangeLowering::ChangeInt32ToSmi(Node* value) {
-  if (machine()->Is64()) {
-    value = graph()->NewNode(machine()->ChangeInt32ToInt64(), value);
-  }
-  return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant());
-}
-
-
-Node* ChangeLowering::ChangeSmiToFloat64(Node* value) {
-  return ChangeInt32ToFloat64(ChangeSmiToInt32(value));
-}
-
-
-Node* ChangeLowering::ChangeSmiToInt32(Node* value) {
-  value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant());
-  if (machine()->Is64()) {
-    value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value);
-  }
-  return value;
-}
-
-
-Node* ChangeLowering::ChangeUint32ToFloat64(Node* value) {
-  return graph()->NewNode(machine()->ChangeUint32ToFloat64(), value);
-}
-
-
-Node* ChangeLowering::ChangeUint32ToSmi(Node* value) {
-  if (machine()->Is64()) {
-    value = graph()->NewNode(machine()->ChangeUint32ToUint64(), value);
-  }
-  return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant());
-}
-
-
-Node* ChangeLowering::LoadHeapNumberValue(Node* value, Node* control) {
-  return graph()->NewNode(machine()->Load(MachineType::Float64()), value,
-                          HeapNumberValueIndexConstant(), graph()->start(),
-                          control);
-}
-
-
-Node* ChangeLowering::TestNotSmi(Node* value) {
-  STATIC_ASSERT(kSmiTag == 0);
-  STATIC_ASSERT(kSmiTagMask == 1);
-  return graph()->NewNode(machine()->WordAnd(), value,
-                          jsgraph()->IntPtrConstant(kSmiTagMask));
-}
-
-
-Reduction ChangeLowering::ChangeBitToBool(Node* value, Node* control) {
-  return Replace(
-      graph()->NewNode(common()->Select(MachineRepresentation::kTagged), value,
-                       jsgraph()->TrueConstant(), jsgraph()->FalseConstant()));
-}
-
-
-Reduction ChangeLowering::ChangeBoolToBit(Node* value) {
-  return Replace(graph()->NewNode(machine()->WordEqual(), value,
-                                  jsgraph()->TrueConstant()));
-}
-
-
-Reduction ChangeLowering::ChangeFloat64ToTagged(Node* value, Node* control) {
-  Type* const value_type = NodeProperties::GetType(value);
-  Node* const value32 = graph()->NewNode(
-      machine()->TruncateFloat64ToInt32(TruncationMode::kRoundToZero), value);
-  // TODO(bmeurer): This fast case must be disabled until we kill the asm.js
-  // support in the generic JavaScript pipeline, because LoadBuffer is lying
-  // about its result.
-  // if (value_type->Is(Type::Signed32())) {
-  //   return ChangeInt32ToTagged(value32, control);
-  // }
-  Node* check_same = graph()->NewNode(
-      machine()->Float64Equal(), value,
-      graph()->NewNode(machine()->ChangeInt32ToFloat64(), value32));
-  Node* branch_same = graph()->NewNode(common()->Branch(), check_same, control);
-
-  Node* if_smi = graph()->NewNode(common()->IfTrue(), branch_same);
-  Node* vsmi;
-  Node* if_box = graph()->NewNode(common()->IfFalse(), branch_same);
-  Node* vbox;
-
-  // We only need to check for -0 if the {value} can potentially contain -0.
-  if (value_type->Maybe(Type::MinusZero())) {
-    Node* check_zero = graph()->NewNode(machine()->Word32Equal(), value32,
-                                        jsgraph()->Int32Constant(0));
-    Node* branch_zero = graph()->NewNode(common()->Branch(BranchHint::kFalse),
-                                         check_zero, if_smi);
-
-    Node* if_zero = graph()->NewNode(common()->IfTrue(), branch_zero);
-    Node* if_notzero = graph()->NewNode(common()->IfFalse(), branch_zero);
-
-    // In case of 0, we need to check the high bits for the IEEE -0 pattern.
-    Node* check_negative = graph()->NewNode(
-        machine()->Int32LessThan(),
-        graph()->NewNode(machine()->Float64ExtractHighWord32(), value),
-        jsgraph()->Int32Constant(0));
-    Node* branch_negative = graph()->NewNode(
-        common()->Branch(BranchHint::kFalse), check_negative, if_zero);
-
-    Node* if_negative = graph()->NewNode(common()->IfTrue(), branch_negative);
-    Node* if_notnegative =
-        graph()->NewNode(common()->IfFalse(), branch_negative);
-
-    // We need to create a box for negative 0.
-    if_smi = graph()->NewNode(common()->Merge(2), if_notzero, if_notnegative);
-    if_box = graph()->NewNode(common()->Merge(2), if_box, if_negative);
-  }
-
-  // On 64-bit machines we can just wrap the 32-bit integer in a smi, for 32-bit
-  // machines we need to deal with potential overflow and fallback to boxing.
-  if (machine()->Is64() || value_type->Is(Type::SignedSmall())) {
-    vsmi = ChangeInt32ToSmi(value32);
-  } else {
-    Node* smi_tag =
-        graph()->NewNode(machine()->Int32AddWithOverflow(), value32, value32);
-
-    Node* check_ovf = graph()->NewNode(common()->Projection(1), smi_tag);
-    Node* branch_ovf = graph()->NewNode(common()->Branch(BranchHint::kFalse),
-                                        check_ovf, if_smi);
-
-    Node* if_ovf = graph()->NewNode(common()->IfTrue(), branch_ovf);
-    if_box = graph()->NewNode(common()->Merge(2), if_ovf, if_box);
-
-    if_smi = graph()->NewNode(common()->IfFalse(), branch_ovf);
-    vsmi = graph()->NewNode(common()->Projection(0), smi_tag);
-  }
-
-  // Allocate the box for the {value}.
-  vbox = AllocateHeapNumberWithValue(value, if_box);
-
-  control = graph()->NewNode(common()->Merge(2), if_smi, if_box);
-  value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
-                           vsmi, vbox, control);
-  return Replace(value);
-}
-
-
-Reduction ChangeLowering::ChangeInt32ToTagged(Node* value, Node* control) {
-  if (machine()->Is64() ||
-      NodeProperties::GetType(value)->Is(Type::SignedSmall())) {
-    return Replace(ChangeInt32ToSmi(value));
-  }
-
-  Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value);
-
-  Node* ovf = graph()->NewNode(common()->Projection(1), add);
-  Node* branch =
-      graph()->NewNode(common()->Branch(BranchHint::kFalse), ovf, control);
-
-  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-  Node* vtrue =
-      AllocateHeapNumberWithValue(ChangeInt32ToFloat64(value), if_true);
-
-  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
-  Node* vfalse = graph()->NewNode(common()->Projection(0), add);
-
-  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
-  Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
-                               vtrue, vfalse, merge);
-
-  return Replace(phi);
-}
-
-
-Reduction ChangeLowering::ChangeTaggedToUI32(Node* value, Node* control,
-                                             Signedness signedness) {
-  if (NodeProperties::GetType(value)->Is(Type::TaggedSigned())) {
-    return Replace(ChangeSmiToInt32(value));
-  }
-
-  const Operator* op = (signedness == kSigned)
-                           ? machine()->ChangeFloat64ToInt32()
-                           : machine()->ChangeFloat64ToUint32();
-
-  if (NodeProperties::GetType(value)->Is(Type::TaggedPointer())) {
-    return Replace(graph()->NewNode(op, LoadHeapNumberValue(value, control)));
-  }
-
-  Node* check = TestNotSmi(value);
-  Node* branch =
-      graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
-
-  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-  Node* vtrue = graph()->NewNode(op, LoadHeapNumberValue(value, if_true));
-
-  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
-  Node* vfalse = ChangeSmiToInt32(value);
-
-  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
-  Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
-                               vtrue, vfalse, merge);
-
-  return Replace(phi);
-}
-
-
-namespace {
-
-bool CanCover(Node* value, IrOpcode::Value opcode) {
-  if (value->opcode() != opcode) return false;
-  bool first = true;
-  for (Edge const edge : value->use_edges()) {
-    if (NodeProperties::IsControlEdge(edge)) continue;
-    if (NodeProperties::IsEffectEdge(edge)) continue;
-    DCHECK(NodeProperties::IsValueEdge(edge));
-    if (!first) return false;
-    first = false;
-  }
-  return true;
-}
-
-}  // namespace
-
-
-Reduction ChangeLowering::ChangeTaggedToFloat64(Node* value, Node* control) {
-  if (CanCover(value, IrOpcode::kJSToNumber)) {
-    // ChangeTaggedToFloat64(JSToNumber(x)) =>
-    //   if IsSmi(x) then ChangeSmiToFloat64(x)
-    //   else let y = JSToNumber(x) in
-    //     if IsSmi(y) then ChangeSmiToFloat64(y)
-    //     else LoadHeapNumberValue(y)
-    Node* const object = NodeProperties::GetValueInput(value, 0);
-    Node* const context = NodeProperties::GetContextInput(value);
-    Node* const frame_state = NodeProperties::GetFrameStateInput(value, 0);
-    Node* const effect = NodeProperties::GetEffectInput(value);
-    Node* const control = NodeProperties::GetControlInput(value);
-
-    const Operator* merge_op = common()->Merge(2);
-    const Operator* ephi_op = common()->EffectPhi(2);
-    const Operator* phi_op = common()->Phi(MachineRepresentation::kFloat64, 2);
-
-    Node* check1 = TestNotSmi(object);
-    Node* branch1 =
-        graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, control);
-
-    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
-    Node* vtrue1 = graph()->NewNode(value->op(), object, context, frame_state,
-                                    effect, if_true1);
-    Node* etrue1 = vtrue1;
-
-    Node* check2 = TestNotSmi(vtrue1);
-    Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_true1);
-
-    Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
-    Node* vtrue2 = LoadHeapNumberValue(vtrue1, if_true2);
-
-    Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
-    Node* vfalse2 = ChangeSmiToFloat64(vtrue1);
-
-    if_true1 = graph()->NewNode(merge_op, if_true2, if_false2);
-    vtrue1 = graph()->NewNode(phi_op, vtrue2, vfalse2, if_true1);
-
-    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
-    Node* vfalse1 = ChangeSmiToFloat64(object);
-    Node* efalse1 = effect;
-
-    Node* merge1 = graph()->NewNode(merge_op, if_true1, if_false1);
-    Node* ephi1 = graph()->NewNode(ephi_op, etrue1, efalse1, merge1);
-    Node* phi1 = graph()->NewNode(phi_op, vtrue1, vfalse1, merge1);
-
-    // Wire the new diamond into the graph, {JSToNumber} can still throw.
-    NodeProperties::ReplaceUses(value, phi1, ephi1, etrue1, etrue1);
-
-    // TODO(mstarzinger): This iteration cuts out the IfSuccess projection from
-    // the node and places it inside the diamond. Come up with a helper method!
-    for (Node* use : etrue1->uses()) {
-      if (use->opcode() == IrOpcode::kIfSuccess) {
-        use->ReplaceUses(merge1);
-        NodeProperties::ReplaceControlInput(branch2, use);
-      }
-    }
-
-    return Replace(phi1);
-  }
-
-  Node* check = TestNotSmi(value);
-  Node* branch =
-      graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
-
-  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-  Node* vtrue = LoadHeapNumberValue(value, if_true);
-
-  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
-  Node* vfalse = ChangeSmiToFloat64(value);
-
-  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
-  Node* phi = graph()->NewNode(
-      common()->Phi(MachineRepresentation::kFloat64, 2), vtrue, vfalse, merge);
-
-  return Replace(phi);
-}
-
-
-Reduction ChangeLowering::ChangeUint32ToTagged(Node* value, Node* control) {
-  if (NodeProperties::GetType(value)->Is(Type::UnsignedSmall())) {
-    return Replace(ChangeUint32ToSmi(value));
-  }
-
-  Node* check = graph()->NewNode(machine()->Uint32LessThanOrEqual(), value,
-                                 SmiMaxValueConstant());
-  Node* branch =
-      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
-
-  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-  Node* vtrue = ChangeUint32ToSmi(value);
-
-  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
-  Node* vfalse =
-      AllocateHeapNumberWithValue(ChangeUint32ToFloat64(value), if_false);
-
-  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
-  Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
-                               vtrue, vfalse, merge);
-
-  return Replace(phi);
-}
-
-
-namespace {
-
-WriteBarrierKind ComputeWriteBarrierKind(BaseTaggedness base_is_tagged,
-                                         MachineRepresentation representation,
-                                         Type* field_type, Type* input_type) {
-  if (field_type->Is(Type::TaggedSigned()) ||
-      input_type->Is(Type::TaggedSigned())) {
-    // Write barriers are only for writes of heap objects.
-    return kNoWriteBarrier;
-  }
-  if (input_type->Is(Type::BooleanOrNullOrUndefined())) {
-    // Write barriers are not necessary when storing true, false, null or
-    // undefined, because these special oddballs are always in the root set.
-    return kNoWriteBarrier;
-  }
-  if (base_is_tagged == kTaggedBase &&
-      representation == MachineRepresentation::kTagged) {
-    if (input_type->IsConstant() &&
-        input_type->AsConstant()->Value()->IsHeapObject()) {
-      Handle<HeapObject> input =
-          Handle<HeapObject>::cast(input_type->AsConstant()->Value());
-      if (input->IsMap()) {
-        // Write barriers for storing maps are cheaper.
-        return kMapWriteBarrier;
-      }
-      Isolate* const isolate = input->GetIsolate();
-      RootIndexMap root_index_map(isolate);
-      int root_index = root_index_map.Lookup(*input);
-      if (root_index != RootIndexMap::kInvalidRootIndex &&
-          isolate->heap()->RootIsImmortalImmovable(root_index)) {
-        // Write barriers are unnecessary for immortal immovable roots.
-        return kNoWriteBarrier;
-      }
-    }
-    if (field_type->Is(Type::TaggedPointer()) ||
-        input_type->Is(Type::TaggedPointer())) {
-      // Write barriers for heap objects don't need a Smi check.
-      return kPointerWriteBarrier;
-    }
-    // Write barriers are only for writes into heap objects (i.e. tagged base).
-    return kFullWriteBarrier;
-  }
-  return kNoWriteBarrier;
-}
-
-
-WriteBarrierKind ComputeWriteBarrierKind(BaseTaggedness base_is_tagged,
-                                         MachineRepresentation representation,
-                                         int field_offset, Type* field_type,
-                                         Type* input_type) {
-  if (base_is_tagged == kTaggedBase && field_offset == HeapObject::kMapOffset) {
-    // Write barriers for storing maps are cheaper.
-    return kMapWriteBarrier;
-  }
-  return ComputeWriteBarrierKind(base_is_tagged, representation, field_type,
-                                 input_type);
-}
-
-}  // namespace
-
-
-Reduction ChangeLowering::LoadField(Node* node) {
-  const FieldAccess& access = FieldAccessOf(node->op());
-  Node* offset = jsgraph()->IntPtrConstant(access.offset - access.tag());
-  node->InsertInput(graph()->zone(), 1, offset);
-  NodeProperties::ChangeOp(node, machine()->Load(access.machine_type));
-  return Changed(node);
-}
-
-
-Reduction ChangeLowering::StoreField(Node* node) {
-  const FieldAccess& access = FieldAccessOf(node->op());
-  Type* type = NodeProperties::GetType(node->InputAt(1));
-  WriteBarrierKind kind = ComputeWriteBarrierKind(
-      access.base_is_tagged, access.machine_type.representation(),
-      access.offset, access.type, type);
-  Node* offset = jsgraph()->IntPtrConstant(access.offset - access.tag());
-  node->InsertInput(graph()->zone(), 1, offset);
-  NodeProperties::ChangeOp(node,
-                           machine()->Store(StoreRepresentation(
-                               access.machine_type.representation(), kind)));
-  return Changed(node);
-}
-
-
-Node* ChangeLowering::ComputeIndex(const ElementAccess& access,
-                                   Node* const key) {
-  Node* index = key;
-  const int element_size_shift =
-      ElementSizeLog2Of(access.machine_type.representation());
-  if (element_size_shift) {
-    index = graph()->NewNode(machine()->Word32Shl(), index,
-                             jsgraph()->Int32Constant(element_size_shift));
-  }
-  const int fixed_offset = access.header_size - access.tag();
-  if (fixed_offset) {
-    index = graph()->NewNode(machine()->Int32Add(), index,
-                             jsgraph()->Int32Constant(fixed_offset));
-  }
-  if (machine()->Is64()) {
-    // TODO(turbofan): This is probably only correct for typed arrays, and only
-    // if the typed arrays are at most 2GiB in size, which happens to match
-    // exactly our current situation.
-    index = graph()->NewNode(machine()->ChangeUint32ToUint64(), index);
-  }
-  return index;
-}
-
-
-Reduction ChangeLowering::LoadElement(Node* node) {
-  const ElementAccess& access = ElementAccessOf(node->op());
-  node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1)));
-  NodeProperties::ChangeOp(node, machine()->Load(access.machine_type));
-  return Changed(node);
-}
-
-
-Reduction ChangeLowering::StoreElement(Node* node) {
-  const ElementAccess& access = ElementAccessOf(node->op());
-  Type* type = NodeProperties::GetType(node->InputAt(2));
-  node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1)));
-  NodeProperties::ChangeOp(
-      node, machine()->Store(StoreRepresentation(
-                access.machine_type.representation(),
-                ComputeWriteBarrierKind(access.base_is_tagged,
-                                        access.machine_type.representation(),
-                                        access.type, type))));
-  return Changed(node);
-}
-
-
-Reduction ChangeLowering::Allocate(Node* node) {
-  PretenureFlag pretenure = OpParameter<PretenureFlag>(node->op());
-  if (pretenure == NOT_TENURED) {
-    Callable callable = CodeFactory::AllocateInNewSpace(isolate());
-    Node* target = jsgraph()->HeapConstant(callable.code());
-    CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
-        isolate(), jsgraph()->zone(), callable.descriptor(), 0,
-        CallDescriptor::kNoFlags, Operator::kNoThrow);
-    const Operator* op = common()->Call(descriptor);
-    node->InsertInput(graph()->zone(), 0, target);
-    node->InsertInput(graph()->zone(), 2, jsgraph()->NoContextConstant());
-    NodeProperties::ChangeOp(node, op);
-  } else {
-    DCHECK_EQ(TENURED, pretenure);
-    AllocationSpace space = OLD_SPACE;
-    Runtime::FunctionId f = Runtime::kAllocateInTargetSpace;
-    Operator::Properties props = node->op()->properties();
-    CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
-        jsgraph()->zone(), f, 2, props, CallDescriptor::kNeedsFrameState);
-    ExternalReference ref(f, jsgraph()->isolate());
-    int32_t flags = AllocateTargetSpace::encode(space);
-    node->InsertInput(graph()->zone(), 0, jsgraph()->CEntryStubConstant(1));
-    node->InsertInput(graph()->zone(), 2, jsgraph()->SmiConstant(flags));
-    node->InsertInput(graph()->zone(), 3, jsgraph()->ExternalConstant(ref));
-    node->InsertInput(graph()->zone(), 4, jsgraph()->Int32Constant(2));
-    node->InsertInput(graph()->zone(), 5, jsgraph()->NoContextConstant());
-    NodeProperties::ChangeOp(node, common()->Call(desc));
-  }
-  return Changed(node);
-}
-
-Node* ChangeLowering::IsSmi(Node* value) {
-  return graph()->NewNode(
-      machine()->WordEqual(),
-      graph()->NewNode(machine()->WordAnd(), value,
-                       jsgraph()->IntPtrConstant(kSmiTagMask)),
-      jsgraph()->IntPtrConstant(kSmiTag));
-}
-
-Node* ChangeLowering::LoadHeapObjectMap(Node* object, Node* control) {
-  return graph()->NewNode(
-      machine()->Load(MachineType::AnyTagged()), object,
-      jsgraph()->IntPtrConstant(HeapObject::kMapOffset - kHeapObjectTag),
-      graph()->start(), control);
-}
-
-Node* ChangeLowering::LoadMapBitField(Node* map) {
-  return graph()->NewNode(
-      machine()->Load(MachineType::Uint8()), map,
-      jsgraph()->IntPtrConstant(Map::kBitFieldOffset - kHeapObjectTag),
-      graph()->start(), graph()->start());
-}
-
-Node* ChangeLowering::LoadMapInstanceType(Node* map) {
-  return graph()->NewNode(
-      machine()->Load(MachineType::Uint8()), map,
-      jsgraph()->IntPtrConstant(Map::kInstanceTypeOffset - kHeapObjectTag),
-      graph()->start(), graph()->start());
-}
-
-Reduction ChangeLowering::ObjectIsNumber(Node* node) {
-  Node* input = NodeProperties::GetValueInput(node, 0);
-  // TODO(bmeurer): Optimize somewhat based on input type.
-  Node* check = IsSmi(input);
-  Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start());
-  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-  Node* vtrue = jsgraph()->Int32Constant(1);
-  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
-  Node* vfalse = graph()->NewNode(
-      machine()->WordEqual(), LoadHeapObjectMap(input, if_false),
-      jsgraph()->HeapConstant(isolate()->factory()->heap_number_map()));
-  Node* control = graph()->NewNode(common()->Merge(2), if_true, if_false);
-  node->ReplaceInput(0, vtrue);
-  node->AppendInput(graph()->zone(), vfalse);
-  node->AppendInput(graph()->zone(), control);
-  NodeProperties::ChangeOp(node, common()->Phi(MachineRepresentation::kBit, 2));
-  return Changed(node);
-}
-
-Reduction ChangeLowering::ObjectIsReceiver(Node* node) {
-  Node* input = NodeProperties::GetValueInput(node, 0);
-  // TODO(bmeurer): Optimize somewhat based on input type.
-  STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
-  Node* check = IsSmi(input);
-  Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start());
-  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-  Node* vtrue = jsgraph()->Int32Constant(0);
-  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
-  Node* vfalse =
-      graph()->NewNode(machine()->Uint32LessThanOrEqual(),
-                       jsgraph()->Uint32Constant(FIRST_JS_RECEIVER_TYPE),
-                       LoadMapInstanceType(LoadHeapObjectMap(input, if_false)));
-  Node* control = graph()->NewNode(common()->Merge(2), if_true, if_false);
-  node->ReplaceInput(0, vtrue);
-  node->AppendInput(graph()->zone(), vfalse);
-  node->AppendInput(graph()->zone(), control);
-  NodeProperties::ChangeOp(node, common()->Phi(MachineRepresentation::kBit, 2));
-  return Changed(node);
-}
-
-Reduction ChangeLowering::ObjectIsUndetectable(Node* node) {
-  Node* input = NodeProperties::GetValueInput(node, 0);
-  // TODO(bmeurer): Optimize somewhat based on input type.
-  Node* check = IsSmi(input);
-  Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start());
-  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-  Node* vtrue = jsgraph()->Int32Constant(0);
-  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
-  Node* vfalse = graph()->NewNode(
-      machine()->Word32Equal(),
-      graph()->NewNode(
-          machine()->Word32Equal(),
-          graph()->NewNode(machine()->Word32And(),
-                           jsgraph()->Uint32Constant(1 << Map::kIsUndetectable),
-                           LoadMapBitField(LoadHeapObjectMap(input, if_false))),
-          jsgraph()->Int32Constant(0)),
-      jsgraph()->Int32Constant(0));
-  Node* control = graph()->NewNode(common()->Merge(2), if_true, if_false);
-  node->ReplaceInput(0, vtrue);
-  node->AppendInput(graph()->zone(), vfalse);
-  node->AppendInput(graph()->zone(), control);
-  NodeProperties::ChangeOp(node, common()->Phi(MachineRepresentation::kBit, 2));
-  return Changed(node);
-}
-
-Reduction ChangeLowering::ObjectIsSmi(Node* node) {
-  node->ReplaceInput(0,
-                     graph()->NewNode(machine()->WordAnd(), node->InputAt(0),
-                                      jsgraph()->IntPtrConstant(kSmiTagMask)));
-  node->AppendInput(graph()->zone(), jsgraph()->IntPtrConstant(kSmiTag));
-  NodeProperties::ChangeOp(node, machine()->WordEqual());
-  return Changed(node);
-}
-
-Isolate* ChangeLowering::isolate() const { return jsgraph()->isolate(); }
-
-
-Graph* ChangeLowering::graph() const { return jsgraph()->graph(); }
-
-
-CommonOperatorBuilder* ChangeLowering::common() const {
-  return jsgraph()->common();
-}
-
-
-MachineOperatorBuilder* ChangeLowering::machine() const {
-  return jsgraph()->machine();
-}
-
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
diff --git a/src/compiler/change-lowering.h b/src/compiler/change-lowering.h
deleted file mode 100644
index 7e5078b..0000000
--- a/src/compiler/change-lowering.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_COMPILER_CHANGE_LOWERING_H_
-#define V8_COMPILER_CHANGE_LOWERING_H_
-
-#include "src/compiler/graph-reducer.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-// Forward declarations.
-class CommonOperatorBuilder;
-struct ElementAccess;
-class JSGraph;
-class Linkage;
-class MachineOperatorBuilder;
-class Operator;
-
-class ChangeLowering final : public Reducer {
- public:
-  explicit ChangeLowering(JSGraph* jsgraph) : jsgraph_(jsgraph) {}
-  ~ChangeLowering() final;
-
-  Reduction Reduce(Node* node) final;
-
- private:
-  Node* HeapNumberValueIndexConstant();
-  Node* SmiMaxValueConstant();
-  Node* SmiShiftBitsConstant();
-
-  Node* AllocateHeapNumberWithValue(Node* value, Node* control);
-  Node* ChangeInt32ToFloat64(Node* value);
-  Node* ChangeInt32ToSmi(Node* value);
-  Node* ChangeSmiToFloat64(Node* value);
-  Node* ChangeSmiToInt32(Node* value);
-  Node* ChangeUint32ToFloat64(Node* value);
-  Node* ChangeUint32ToSmi(Node* value);
-  Node* LoadHeapNumberValue(Node* value, Node* control);
-  Node* TestNotSmi(Node* value);
-
-  Reduction ChangeBitToBool(Node* value, Node* control);
-  Reduction ChangeBoolToBit(Node* value);
-  Reduction ChangeFloat64ToTagged(Node* value, Node* control);
-  Reduction ChangeInt32ToTagged(Node* value, Node* control);
-  Reduction ChangeTaggedToFloat64(Node* value, Node* control);
-  Reduction ChangeTaggedToUI32(Node* value, Node* control,
-                               Signedness signedness);
-  Reduction ChangeUint32ToTagged(Node* value, Node* control);
-
-  Reduction LoadField(Node* node);
-  Reduction StoreField(Node* node);
-  Reduction LoadElement(Node* node);
-  Reduction StoreElement(Node* node);
-  Reduction Allocate(Node* node);
-
-  Node* IsSmi(Node* value);
-  Node* LoadHeapObjectMap(Node* object, Node* control);
-  Node* LoadMapBitField(Node* map);
-  Node* LoadMapInstanceType(Node* map);
-
-  Reduction ObjectIsNumber(Node* node);
-  Reduction ObjectIsReceiver(Node* node);
-  Reduction ObjectIsSmi(Node* node);
-  Reduction ObjectIsUndetectable(Node* node);
-
-  Node* ComputeIndex(const ElementAccess& access, Node* const key);
-  Graph* graph() const;
-  Isolate* isolate() const;
-  JSGraph* jsgraph() const { return jsgraph_; }
-  CommonOperatorBuilder* common() const;
-  MachineOperatorBuilder* machine() const;
-
-  JSGraph* const jsgraph_;
-  SetOncePointer<const Operator> allocate_heap_number_operator_;
-};
-
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
-
-#endif  // V8_COMPILER_CHANGE_LOWERING_H_
diff --git a/src/compiler/checkpoint-elimination.cc b/src/compiler/checkpoint-elimination.cc
new file mode 100644
index 0000000..d81e109
--- /dev/null
+++ b/src/compiler/checkpoint-elimination.cc
@@ -0,0 +1,43 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/checkpoint-elimination.h"
+
+#include "src/compiler/node-properties.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+CheckpointElimination::CheckpointElimination(Editor* editor)
+    : AdvancedReducer(editor) {}
+
+namespace {
+
+// The given checkpoint is redundant if it is effect-wise dominated by another
+// checkpoint and there is no observable write in between. For now we consider
+// a linear effect chain only instead of true effect-wise dominance.
+bool IsRedundantCheckpoint(Node* node) {
+  Node* effect = NodeProperties::GetEffectInput(node);
+  while (effect->op()->HasProperty(Operator::kNoWrite) &&
+         effect->op()->EffectInputCount() == 1) {
+    if (effect->opcode() == IrOpcode::kCheckpoint) return true;
+    effect = NodeProperties::GetEffectInput(effect);
+  }
+  return false;
+}
+
+}  // namespace
+
+Reduction CheckpointElimination::Reduce(Node* node) {
+  if (node->opcode() != IrOpcode::kCheckpoint) return NoChange();
+  if (IsRedundantCheckpoint(node)) {
+    return Replace(NodeProperties::GetEffectInput(node));
+  }
+  return NoChange();
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/src/compiler/checkpoint-elimination.h b/src/compiler/checkpoint-elimination.h
new file mode 100644
index 0000000..4d6aada
--- /dev/null
+++ b/src/compiler/checkpoint-elimination.h
@@ -0,0 +1,27 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_CHECKPOINT_ELIMINATION_H_
+#define V8_COMPILER_CHECKPOINT_ELIMINATION_H_
+
+#include "src/compiler/graph-reducer.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+// Performs elimination of redundant checkpoints within the graph.
+class CheckpointElimination final : public AdvancedReducer {
+ public:
+  explicit CheckpointElimination(Editor* editor);
+  ~CheckpointElimination() final {}
+
+  Reduction Reduce(Node* node) final;
+};
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_COMPILER_CHECKPOINT_ELIMINATION_H_
diff --git a/src/compiler/coalesced-live-ranges.cc b/src/compiler/coalesced-live-ranges.cc
deleted file mode 100644
index 4ac3e21..0000000
--- a/src/compiler/coalesced-live-ranges.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/compiler/coalesced-live-ranges.h"
-#include "src/compiler/greedy-allocator.h"
-#include "src/compiler/register-allocator.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-
-LiveRangeConflictIterator::LiveRangeConflictIterator(const LiveRange* range,
-                                                     IntervalStore* storage)
-    : query_(range->first_interval()),
-      pos_(storage->end()),
-      intervals_(storage) {
-  MovePosAndQueryToFirstConflict();
-}
-
-
-LiveRange* LiveRangeConflictIterator::Current() const {
-  if (IsFinished()) return nullptr;
-  return pos_->range_;
-}
-
-
-void LiveRangeConflictIterator::MovePosToFirstConflictForQuery() {
-  DCHECK_NOT_NULL(query_);
-  auto end = intervals_->end();
-  LifetimePosition q_start = query_->start();
-  LifetimePosition q_end = query_->end();
-
-  if (intervals_->empty() || intervals_->rbegin()->end_ <= q_start ||
-      intervals_->begin()->start_ >= q_end) {
-    pos_ = end;
-    return;
-  }
-
-  pos_ = intervals_->upper_bound(AsAllocatedInterval(q_start));
-  // pos is either at the end (no start strictly greater than q_start) or
-  // at some position with the aforementioned property. In either case, the
-  // allocated interval before this one may intersect our query:
-  // either because, although it starts before this query's start, it ends
-  // after; or because it starts exactly at the query start. So unless we're
-  // right at the beginning of the storage - meaning the first allocated
-  // interval is also starting after this query's start - see what's behind.
-  if (pos_ != intervals_->begin()) {
-    --pos_;
-    if (!QueryIntersectsAllocatedInterval()) {
-      // The interval behind wasn't intersecting, so move back.
-      ++pos_;
-    }
-  }
-  if (pos_ == end || !QueryIntersectsAllocatedInterval()) {
-    pos_ = end;
-  }
-}
-
-
-void LiveRangeConflictIterator::MovePosAndQueryToFirstConflict() {
-  auto end = intervals_->end();
-  for (; query_ != nullptr; query_ = query_->next()) {
-    MovePosToFirstConflictForQuery();
-    if (pos_ != end) {
-      DCHECK(QueryIntersectsAllocatedInterval());
-      return;
-    }
-  }
-
-  Invalidate();
-}
-
-
-void LiveRangeConflictIterator::IncrementPosAndSkipOverRepetitions() {
-  auto end = intervals_->end();
-  DCHECK(pos_ != end);
-  LiveRange* current_conflict = Current();
-  while (pos_ != end && pos_->range_ == current_conflict) {
-    ++pos_;
-  }
-}
-
-
-LiveRange* LiveRangeConflictIterator::InternalGetNext(bool clean_behind) {
-  if (IsFinished()) return nullptr;
-
-  LiveRange* to_clear = Current();
-  IncrementPosAndSkipOverRepetitions();
-  // At this point, pos_ is either at the end, or on an interval that doesn't
-  // correspond to the same range as to_clear. This interval may not even be
-  // a conflict.
-  if (clean_behind) {
-    // Since we parked pos_ on an iterator that won't be affected by removal,
-    // we can safely delete to_clear's intervals.
-    for (auto interval = to_clear->first_interval(); interval != nullptr;
-         interval = interval->next()) {
-      AllocatedInterval erase_key(interval->start(), interval->end(), nullptr);
-      intervals_->erase(erase_key);
-    }
-  }
-  // We may have parked pos_ at the end, or on a non-conflict. In that case,
-  // move to the next query and reinitialize pos and query. This may invalidate
-  // the iterator, if no more conflicts are available.
-  if (!QueryIntersectsAllocatedInterval()) {
-    query_ = query_->next();
-    MovePosAndQueryToFirstConflict();
-  }
-  return Current();
-}
-
-
-LiveRangeConflictIterator CoalescedLiveRanges::GetConflicts(
-    const LiveRange* range) {
-  return LiveRangeConflictIterator(range, &intervals());
-}
-
-
-void CoalescedLiveRanges::AllocateRange(LiveRange* range) {
-  for (auto interval = range->first_interval(); interval != nullptr;
-       interval = interval->next()) {
-    AllocatedInterval to_insert(interval->start(), interval->end(), range);
-    intervals().insert(to_insert);
-  }
-}
-
-
-bool CoalescedLiveRanges::VerifyAllocationsAreValidForTesting() const {
-  LifetimePosition last_end = LifetimePosition::GapFromInstructionIndex(0);
-  for (auto i : intervals_) {
-    if (i.start_ < last_end) {
-      return false;
-    }
-    last_end = i.end_;
-  }
-  return true;
-}
-
-
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
diff --git a/src/compiler/coalesced-live-ranges.h b/src/compiler/coalesced-live-ranges.h
deleted file mode 100644
index 54bbce2..0000000
--- a/src/compiler/coalesced-live-ranges.h
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_COALESCED_LIVE_RANGES_H_
-#define V8_COALESCED_LIVE_RANGES_H_
-
-#include "src/compiler/register-allocator.h"
-#include "src/zone-containers.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-
-// Implementation detail for CoalescedLiveRanges.
-struct AllocatedInterval {
-  AllocatedInterval(LifetimePosition start, LifetimePosition end,
-                    LiveRange* range)
-      : start_(start), end_(end), range_(range) {}
-
-  LifetimePosition start_;
-  LifetimePosition end_;
-  LiveRange* range_;
-  bool operator<(const AllocatedInterval& other) const {
-    return start_ < other.start_;
-  }
-  bool operator>(const AllocatedInterval& other) const {
-    return start_ > other.start_;
-  }
-};
-typedef ZoneSet<AllocatedInterval> IntervalStore;
-
-
-// An iterator over conflicts of a live range, obtained from CoalescedLiveRanges
-// The design supports two main scenarios (see GreedyAllocator):
-// (1) observing each conflicting range, without mutating the allocations, and
-// (2) observing each conflicting range, and then moving to the next, after
-// removing the current conflict.
-class LiveRangeConflictIterator {
- public:
-  // Current conflict. nullptr if no conflicts, or if we reached the end of
-  // conflicts.
-  LiveRange* Current() const;
-
-  // Get the next conflict. Caller should handle non-consecutive repetitions of
-  // the same range.
-  LiveRange* GetNext() { return InternalGetNext(false); }
-
-  // Get the next conflict, after evicting the current one. Caller may expect
-  // to never observe the same live range more than once.
-  LiveRange* RemoveCurrentAndGetNext() { return InternalGetNext(true); }
-
- private:
-  friend class CoalescedLiveRanges;
-
-  typedef IntervalStore::const_iterator interval_iterator;
-  LiveRangeConflictIterator(const LiveRange* range, IntervalStore* store);
-
-  // Move the store iterator to  first interval intersecting query. Since the
-  // intervals are sorted, subsequent intervals intersecting query follow. May
-  // leave the store iterator at "end", meaning that the current query does not
-  // have an intersection.
-  void MovePosToFirstConflictForQuery();
-
-  // Move both query and store iterator to the first intersection, if any. If
-  // none, then it invalidates the iterator (IsFinished() == true)
-  void MovePosAndQueryToFirstConflict();
-
-  // Increment pos and skip over intervals belonging to the same range we
-  // started with (i.e. Current() before the call). It is possible that range
-  // will be seen again, but not consecutively.
-  void IncrementPosAndSkipOverRepetitions();
-
-  // Common implementation used by both GetNext as well as
-  // ClearCurrentAndGetNext.
-  LiveRange* InternalGetNext(bool clean_behind);
-
-  bool IsFinished() const { return query_ == nullptr; }
-
-  static AllocatedInterval AsAllocatedInterval(LifetimePosition pos) {
-    return AllocatedInterval(pos, LifetimePosition::Invalid(), nullptr);
-  }
-
-  // Intersection utilities.
-  static bool Intersects(LifetimePosition a_start, LifetimePosition a_end,
-                         LifetimePosition b_start, LifetimePosition b_end) {
-    return a_start < b_end && b_start < a_end;
-  }
-
-  bool QueryIntersectsAllocatedInterval() const {
-    DCHECK_NOT_NULL(query_);
-    return pos_ != intervals_->end() &&
-           Intersects(query_->start(), query_->end(), pos_->start_, pos_->end_);
-  }
-
-  void Invalidate() {
-    query_ = nullptr;
-    pos_ = intervals_->end();
-  }
-
-  const UseInterval* query_;
-  interval_iterator pos_;
-  IntervalStore* intervals_;
-};
-
-// Collection of live ranges allocated to the same register.
-// It supports efficiently finding all conflicts for a given, non-allocated
-// range. See AllocatedInterval.
-// Allocated live ranges do not intersect. At most, individual use intervals
-// touch. We store, for a live range, an AllocatedInterval corresponding to each
-// of that range's UseIntervals. We keep the list of AllocatedIntervals sorted
-// by starts. Then, given the non-intersecting property, we know that
-// consecutive AllocatedIntervals have the property that the "smaller"'s end is
-// less or equal to the "larger"'s start.
-// This allows for quick (logarithmic complexity) identification of the first
-// AllocatedInterval to conflict with a given LiveRange, and then for efficient
-// traversal of conflicts.
-class CoalescedLiveRanges : public ZoneObject {
- public:
-  explicit CoalescedLiveRanges(Zone* zone) : intervals_(zone) {}
-  void clear() { intervals_.clear(); }
-
-  bool empty() const { return intervals_.empty(); }
-
-  // Iterate over each live range conflicting with the provided one.
-  // The same live range may be observed multiple, but non-consecutive times.
-  LiveRangeConflictIterator GetConflicts(const LiveRange* range);
-
-
-  // Allocates a range with a pre-calculated candidate weight.
-  void AllocateRange(LiveRange* range);
-
-  // Unit testing API, verifying that allocated intervals do not overlap.
-  bool VerifyAllocationsAreValidForTesting() const;
-
- private:
-  static const float kAllocatedRangeMultiplier;
-
-  IntervalStore& intervals() { return intervals_; }
-  const IntervalStore& intervals() const { return intervals_; }
-
-  // Augment the weight of a range that is about to be allocated.
-  static void UpdateWeightAtAllocation(LiveRange* range);
-
-  // Reduce the weight of a range that has lost allocation.
-  static void UpdateWeightAtEviction(LiveRange* range);
-
-
-  IntervalStore intervals_;
-  DISALLOW_COPY_AND_ASSIGN(CoalescedLiveRanges);
-};
-
-
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
-#endif  // V8_COALESCED_LIVE_RANGES_H_
diff --git a/src/compiler/code-assembler.cc b/src/compiler/code-assembler.cc
new file mode 100644
index 0000000..e598c09
--- /dev/null
+++ b/src/compiler/code-assembler.cc
@@ -0,0 +1,857 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/code-assembler.h"
+
+#include <ostream>
+
+#include "src/code-factory.h"
+#include "src/compiler/graph.h"
+#include "src/compiler/instruction-selector.h"
+#include "src/compiler/linkage.h"
+#include "src/compiler/node-matchers.h"
+#include "src/compiler/pipeline.h"
+#include "src/compiler/raw-machine-assembler.h"
+#include "src/compiler/schedule.h"
+#include "src/frames.h"
+#include "src/interface-descriptors.h"
+#include "src/interpreter/bytecodes.h"
+#include "src/machine-type.h"
+#include "src/macro-assembler.h"
+#include "src/utils.h"
+#include "src/zone.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone,
+                             const CallInterfaceDescriptor& descriptor,
+                             Code::Flags flags, const char* name,
+                             size_t result_size)
+    : CodeAssembler(
+          isolate, zone,
+          Linkage::GetStubCallDescriptor(
+              isolate, zone, descriptor, descriptor.GetStackParameterCount(),
+              CallDescriptor::kNoFlags, Operator::kNoProperties,
+              MachineType::AnyTagged(), result_size),
+          flags, name) {}
+
+CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone, int parameter_count,
+                             Code::Flags flags, const char* name)
+    : CodeAssembler(isolate, zone,
+                    Linkage::GetJSCallDescriptor(zone, false, parameter_count,
+                                                 CallDescriptor::kNoFlags),
+                    flags, name) {}
+
+CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone,
+                             CallDescriptor* call_descriptor, Code::Flags flags,
+                             const char* name)
+    : raw_assembler_(new RawMachineAssembler(
+          isolate, new (zone) Graph(zone), call_descriptor,
+          MachineType::PointerRepresentation(),
+          InstructionSelector::SupportedMachineOperatorFlags())),
+      flags_(flags),
+      name_(name),
+      code_generated_(false),
+      variables_(zone) {}
+
+CodeAssembler::~CodeAssembler() {}
+
+void CodeAssembler::CallPrologue() {}
+
+void CodeAssembler::CallEpilogue() {}
+
+Handle<Code> CodeAssembler::GenerateCode() {
+  DCHECK(!code_generated_);
+
+  Schedule* schedule = raw_assembler_->Export();
+  Handle<Code> code = Pipeline::GenerateCodeForCodeStub(
+      isolate(), raw_assembler_->call_descriptor(), graph(), schedule, flags_,
+      name_);
+
+  code_generated_ = true;
+  return code;
+}
+
+bool CodeAssembler::Is64() const { return raw_assembler_->machine()->Is64(); }
+
+bool CodeAssembler::IsFloat64RoundUpSupported() const {
+  return raw_assembler_->machine()->Float64RoundUp().IsSupported();
+}
+
+bool CodeAssembler::IsFloat64RoundDownSupported() const {
+  return raw_assembler_->machine()->Float64RoundDown().IsSupported();
+}
+
+bool CodeAssembler::IsFloat64RoundTruncateSupported() const {
+  return raw_assembler_->machine()->Float64RoundTruncate().IsSupported();
+}
+
+Node* CodeAssembler::Int32Constant(int32_t value) {
+  return raw_assembler_->Int32Constant(value);
+}
+
+Node* CodeAssembler::Int64Constant(int64_t value) {
+  return raw_assembler_->Int64Constant(value);
+}
+
+Node* CodeAssembler::IntPtrConstant(intptr_t value) {
+  return raw_assembler_->IntPtrConstant(value);
+}
+
+Node* CodeAssembler::NumberConstant(double value) {
+  return raw_assembler_->NumberConstant(value);
+}
+
+Node* CodeAssembler::SmiConstant(Smi* value) {
+  return IntPtrConstant(bit_cast<intptr_t>(value));
+}
+
+Node* CodeAssembler::HeapConstant(Handle<HeapObject> object) {
+  return raw_assembler_->HeapConstant(object);
+}
+
+Node* CodeAssembler::BooleanConstant(bool value) {
+  return raw_assembler_->BooleanConstant(value);
+}
+
+Node* CodeAssembler::ExternalConstant(ExternalReference address) {
+  return raw_assembler_->ExternalConstant(address);
+}
+
+Node* CodeAssembler::Float64Constant(double value) {
+  return raw_assembler_->Float64Constant(value);
+}
+
+Node* CodeAssembler::NaNConstant() {
+  return LoadRoot(Heap::kNanValueRootIndex);
+}
+
+bool CodeAssembler::ToInt32Constant(Node* node, int32_t& out_value) {
+  Int64Matcher m(node);
+  if (m.HasValue() &&
+      m.IsInRange(std::numeric_limits<int32_t>::min(),
+                  std::numeric_limits<int32_t>::max())) {
+    out_value = static_cast<int32_t>(m.Value());
+    return true;
+  }
+
+  return false;
+}
+
+bool CodeAssembler::ToInt64Constant(Node* node, int64_t& out_value) {
+  Int64Matcher m(node);
+  if (m.HasValue()) out_value = m.Value();
+  return m.HasValue();
+}
+
+bool CodeAssembler::ToIntPtrConstant(Node* node, intptr_t& out_value) {
+  IntPtrMatcher m(node);
+  if (m.HasValue()) out_value = m.Value();
+  return m.HasValue();
+}
+
+Node* CodeAssembler::Parameter(int value) {
+  return raw_assembler_->Parameter(value);
+}
+
+void CodeAssembler::Return(Node* value) {
+  return raw_assembler_->Return(value);
+}
+
+void CodeAssembler::DebugBreak() { raw_assembler_->DebugBreak(); }
+
+void CodeAssembler::Comment(const char* format, ...) {
+  if (!FLAG_code_comments) return;
+  char buffer[4 * KB];
+  StringBuilder builder(buffer, arraysize(buffer));
+  va_list arguments;
+  va_start(arguments, format);
+  builder.AddFormattedList(format, arguments);
+  va_end(arguments);
+
+  // Copy the string before recording it in the assembler to avoid
+  // issues when the stack allocated buffer goes out of scope.
+  const int prefix_len = 2;
+  int length = builder.position() + 1;
+  char* copy = reinterpret_cast<char*>(malloc(length + prefix_len));
+  MemCopy(copy + prefix_len, builder.Finalize(), length);
+  copy[0] = ';';
+  copy[1] = ' ';
+  raw_assembler_->Comment(copy);
+}
+
+void CodeAssembler::Bind(CodeAssembler::Label* label) { return label->Bind(); }
+
+Node* CodeAssembler::LoadFramePointer() {
+  return raw_assembler_->LoadFramePointer();
+}
+
+Node* CodeAssembler::LoadParentFramePointer() {
+  return raw_assembler_->LoadParentFramePointer();
+}
+
+Node* CodeAssembler::LoadStackPointer() {
+  return raw_assembler_->LoadStackPointer();
+}
+
+Node* CodeAssembler::SmiShiftBitsConstant() {
+  return IntPtrConstant(kSmiShiftSize + kSmiTagSize);
+}
+
+#define DEFINE_CODE_ASSEMBLER_BINARY_OP(name)   \
+  Node* CodeAssembler::name(Node* a, Node* b) { \
+    return raw_assembler_->name(a, b);          \
+  }
+CODE_ASSEMBLER_BINARY_OP_LIST(DEFINE_CODE_ASSEMBLER_BINARY_OP)
+#undef DEFINE_CODE_ASSEMBLER_BINARY_OP
+
+Node* CodeAssembler::WordShl(Node* value, int shift) {
+  return raw_assembler_->WordShl(value, IntPtrConstant(shift));
+}
+
+Node* CodeAssembler::WordShr(Node* value, int shift) {
+  return raw_assembler_->WordShr(value, IntPtrConstant(shift));
+}
+
+Node* CodeAssembler::ChangeUint32ToWord(Node* value) {
+  if (raw_assembler_->machine()->Is64()) {
+    value = raw_assembler_->ChangeUint32ToUint64(value);
+  }
+  return value;
+}
+
+Node* CodeAssembler::ChangeInt32ToIntPtr(Node* value) {
+  if (raw_assembler_->machine()->Is64()) {
+    value = raw_assembler_->ChangeInt32ToInt64(value);
+  }
+  return value;
+}
+
+#define DEFINE_CODE_ASSEMBLER_UNARY_OP(name) \
+  Node* CodeAssembler::name(Node* a) { return raw_assembler_->name(a); }
+CODE_ASSEMBLER_UNARY_OP_LIST(DEFINE_CODE_ASSEMBLER_UNARY_OP)
+#undef DEFINE_CODE_ASSEMBLER_UNARY_OP
+
+Node* CodeAssembler::Load(MachineType rep, Node* base) {
+  return raw_assembler_->Load(rep, base);
+}
+
+Node* CodeAssembler::Load(MachineType rep, Node* base, Node* index) {
+  return raw_assembler_->Load(rep, base, index);
+}
+
+Node* CodeAssembler::AtomicLoad(MachineType rep, Node* base, Node* index) {
+  return raw_assembler_->AtomicLoad(rep, base, index);
+}
+
+Node* CodeAssembler::LoadRoot(Heap::RootListIndex root_index) {
+  if (isolate()->heap()->RootCanBeTreatedAsConstant(root_index)) {
+    Handle<Object> root = isolate()->heap()->root_handle(root_index);
+    if (root->IsSmi()) {
+      return SmiConstant(Smi::cast(*root));
+    } else {
+      return HeapConstant(Handle<HeapObject>::cast(root));
+    }
+  }
+
+  Node* roots_array_start =
+      ExternalConstant(ExternalReference::roots_array_start(isolate()));
+  return Load(MachineType::AnyTagged(), roots_array_start,
+              IntPtrConstant(root_index * kPointerSize));
+}
+
+Node* CodeAssembler::Store(MachineRepresentation rep, Node* base, Node* value) {
+  return raw_assembler_->Store(rep, base, value, kFullWriteBarrier);
+}
+
+Node* CodeAssembler::Store(MachineRepresentation rep, Node* base, Node* index,
+                           Node* value) {
+  return raw_assembler_->Store(rep, base, index, value, kFullWriteBarrier);
+}
+
+Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
+                                         Node* value) {
+  return raw_assembler_->Store(rep, base, value, kNoWriteBarrier);
+}
+
+Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
+                                         Node* index, Node* value) {
+  return raw_assembler_->Store(rep, base, index, value, kNoWriteBarrier);
+}
+
+Node* CodeAssembler::AtomicStore(MachineRepresentation rep, Node* base,
+                                 Node* index, Node* value) {
+  return raw_assembler_->AtomicStore(rep, base, index, value);
+}
+
+Node* CodeAssembler::StoreRoot(Heap::RootListIndex root_index, Node* value) {
+  DCHECK(Heap::RootCanBeWrittenAfterInitialization(root_index));
+  Node* roots_array_start =
+      ExternalConstant(ExternalReference::roots_array_start(isolate()));
+  return StoreNoWriteBarrier(MachineRepresentation::kTagged, roots_array_start,
+                             IntPtrConstant(root_index * kPointerSize), value);
+}
+
+Node* CodeAssembler::Projection(int index, Node* value) {
+  return raw_assembler_->Projection(index, value);
+}
+
+void CodeAssembler::BranchIf(Node* condition, Label* if_true, Label* if_false) {
+  Label if_condition_is_true(this), if_condition_is_false(this);
+  Branch(condition, &if_condition_is_true, &if_condition_is_false);
+  Bind(&if_condition_is_true);
+  Goto(if_true);
+  Bind(&if_condition_is_false);
+  Goto(if_false);
+}
+
+Node* CodeAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
+                           Node** args) {
+  CallPrologue();
+  Node* return_value = raw_assembler_->CallN(descriptor, code_target, args);
+  CallEpilogue();
+  return return_value;
+}
+
+Node* CodeAssembler::TailCallN(CallDescriptor* descriptor, Node* code_target,
+                               Node** args) {
+  return raw_assembler_->TailCallN(descriptor, code_target, args);
+}
+
+Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id,
+                                 Node* context) {
+  CallPrologue();
+  Node* return_value = raw_assembler_->CallRuntime0(function_id, context);
+  CallEpilogue();
+  return return_value;
+}
+
+Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
+                                 Node* arg1) {
+  CallPrologue();
+  Node* return_value = raw_assembler_->CallRuntime1(function_id, arg1, context);
+  CallEpilogue();
+  return return_value;
+}
+
+Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
+                                 Node* arg1, Node* arg2) {
+  CallPrologue();
+  Node* return_value =
+      raw_assembler_->CallRuntime2(function_id, arg1, arg2, context);
+  CallEpilogue();
+  return return_value;
+}
+
+Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
+                                 Node* arg1, Node* arg2, Node* arg3) {
+  CallPrologue();
+  Node* return_value =
+      raw_assembler_->CallRuntime3(function_id, arg1, arg2, arg3, context);
+  CallEpilogue();
+  return return_value;
+}
+
+Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
+                                 Node* arg1, Node* arg2, Node* arg3,
+                                 Node* arg4) {
+  CallPrologue();
+  Node* return_value = raw_assembler_->CallRuntime4(function_id, arg1, arg2,
+                                                    arg3, arg4, context);
+  CallEpilogue();
+  return return_value;
+}
+
+Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
+                                     Node* context) {
+  return raw_assembler_->TailCallRuntime0(function_id, context);
+}
+
+Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
+                                     Node* context, Node* arg1) {
+  return raw_assembler_->TailCallRuntime1(function_id, arg1, context);
+}
+
+Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
+                                     Node* context, Node* arg1, Node* arg2) {
+  return raw_assembler_->TailCallRuntime2(function_id, arg1, arg2, context);
+}
+
+Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
+                                     Node* context, Node* arg1, Node* arg2,
+                                     Node* arg3) {
+  return raw_assembler_->TailCallRuntime3(function_id, arg1, arg2, arg3,
+                                          context);
+}
+
+Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
+                                     Node* context, Node* arg1, Node* arg2,
+                                     Node* arg3, Node* arg4) {
+  return raw_assembler_->TailCallRuntime4(function_id, arg1, arg2, arg3, arg4,
+                                          context);
+}
+
+Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
+                              Node* arg1, size_t result_size) {
+  Node* target = HeapConstant(callable.code());
+  return CallStub(callable.descriptor(), target, context, arg1, result_size);
+}
+
+Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
+                              Node* arg1, Node* arg2, size_t result_size) {
+  Node* target = HeapConstant(callable.code());
+  return CallStub(callable.descriptor(), target, context, arg1, arg2,
+                  result_size);
+}
+
+Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
+                              Node* arg1, Node* arg2, Node* arg3,
+                              size_t result_size) {
+  Node* target = HeapConstant(callable.code());
+  return CallStub(callable.descriptor(), target, context, arg1, arg2, arg3,
+                  result_size);
+}
+
+Node* CodeAssembler::CallStubN(Callable const& callable, Node** args,
+                               size_t result_size) {
+  Node* target = HeapConstant(callable.code());
+  return CallStubN(callable.descriptor(), target, args, result_size);
+}
+
+Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
+                              Node* target, Node* context, Node* arg1,
+                              size_t result_size) {
+  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
+      isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
+      CallDescriptor::kNoFlags, Operator::kNoProperties,
+      MachineType::AnyTagged(), result_size);
+
+  Node** args = zone()->NewArray<Node*>(2);
+  args[0] = arg1;
+  args[1] = context;
+
+  return CallN(call_descriptor, target, args);
+}
+
+Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
+                              Node* target, Node* context, Node* arg1,
+                              Node* arg2, size_t result_size) {
+  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
+      isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
+      CallDescriptor::kNoFlags, Operator::kNoProperties,
+      MachineType::AnyTagged(), result_size);
+
+  Node** args = zone()->NewArray<Node*>(3);
+  args[0] = arg1;
+  args[1] = arg2;
+  args[2] = context;
+
+  return CallN(call_descriptor, target, args);
+}
+
+Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
+                              Node* target, Node* context, Node* arg1,
+                              Node* arg2, Node* arg3, size_t result_size) {
+  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
+      isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
+      CallDescriptor::kNoFlags, Operator::kNoProperties,
+      MachineType::AnyTagged(), result_size);
+
+  Node** args = zone()->NewArray<Node*>(4);
+  args[0] = arg1;
+  args[1] = arg2;
+  args[2] = arg3;
+  args[3] = context;
+
+  return CallN(call_descriptor, target, args);
+}
+
+Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
+                              Node* target, Node* context, Node* arg1,
+                              Node* arg2, Node* arg3, Node* arg4,
+                              size_t result_size) {
+  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
+      isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
+      CallDescriptor::kNoFlags, Operator::kNoProperties,
+      MachineType::AnyTagged(), result_size);
+
+  Node** args = zone()->NewArray<Node*>(5);
+  args[0] = arg1;
+  args[1] = arg2;
+  args[2] = arg3;
+  args[3] = arg4;
+  args[4] = context;
+
+  return CallN(call_descriptor, target, args);
+}
+
+Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
+                              Node* target, Node* context, Node* arg1,
+                              Node* arg2, Node* arg3, Node* arg4, Node* arg5,
+                              size_t result_size) {
+  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
+      isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
+      CallDescriptor::kNoFlags, Operator::kNoProperties,
+      MachineType::AnyTagged(), result_size);
+
+  Node** args = zone()->NewArray<Node*>(6);
+  args[0] = arg1;
+  args[1] = arg2;
+  args[2] = arg3;
+  args[3] = arg4;
+  args[4] = arg5;
+  args[5] = context;
+
+  return CallN(call_descriptor, target, args);
+}
+
+Node* CodeAssembler::CallStubN(const CallInterfaceDescriptor& descriptor,
+                               Node* target, Node** args, size_t result_size) {
+  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
+      isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
+      CallDescriptor::kNoFlags, Operator::kNoProperties,
+      MachineType::AnyTagged(), result_size);
+
+  return CallN(call_descriptor, target, args);
+}
+
+Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
+                                  Node* arg1, Node* arg2, size_t result_size) {
+  Node* target = HeapConstant(callable.code());
+  return TailCallStub(callable.descriptor(), target, context, arg1, arg2,
+                      result_size);
+}
+
+Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
+                                  Node* arg1, Node* arg2, Node* arg3,
+                                  size_t result_size) {
+  Node* target = HeapConstant(callable.code());
+  return TailCallStub(callable.descriptor(), target, context, arg1, arg2, arg3,
+                      result_size);
+}
+
+Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
+                                  Node* target, Node* context, Node* arg1,
+                                  Node* arg2, size_t result_size) {
+  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
+      isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
+      CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
+      MachineType::AnyTagged(), result_size);
+
+  Node** args = zone()->NewArray<Node*>(3);
+  args[0] = arg1;
+  args[1] = arg2;
+  args[2] = context;
+
+  return raw_assembler_->TailCallN(call_descriptor, target, args);
+}
+
+Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
+                                  Node* target, Node* context, Node* arg1,
+                                  Node* arg2, Node* arg3, size_t result_size) {
+  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
+      isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
+      CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
+      MachineType::AnyTagged(), result_size);
+
+  Node** args = zone()->NewArray<Node*>(4);
+  args[0] = arg1;
+  args[1] = arg2;
+  args[2] = arg3;
+  args[3] = context;
+
+  return raw_assembler_->TailCallN(call_descriptor, target, args);
+}
+
+Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
+                                  Node* target, Node* context, Node* arg1,
+                                  Node* arg2, Node* arg3, Node* arg4,
+                                  size_t result_size) {
+  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
+      isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
+      CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
+      MachineType::AnyTagged(), result_size);
+
+  Node** args = zone()->NewArray<Node*>(5);
+  args[0] = arg1;
+  args[1] = arg2;
+  args[2] = arg3;
+  args[3] = arg4;
+  args[4] = context;
+
+  return raw_assembler_->TailCallN(call_descriptor, target, args);
+}
+
+Node* CodeAssembler::TailCallBytecodeDispatch(
+    const CallInterfaceDescriptor& interface_descriptor,
+    Node* code_target_address, Node** args) {
+  CallDescriptor* descriptor = Linkage::GetBytecodeDispatchCallDescriptor(
+      isolate(), zone(), interface_descriptor,
+      interface_descriptor.GetStackParameterCount());
+  return raw_assembler_->TailCallN(descriptor, code_target_address, args);
+}
+
+Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
+                            Node* function, Node* receiver,
+                            size_t result_size) {
+  const int argc = 0;
+  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
+      isolate(), zone(), callable.descriptor(), argc + 1,
+      CallDescriptor::kNoFlags, Operator::kNoProperties,
+      MachineType::AnyTagged(), result_size);
+  Node* target = HeapConstant(callable.code());
+
+  Node** args = zone()->NewArray<Node*>(argc + 4);
+  args[0] = function;
+  args[1] = Int32Constant(argc);
+  args[2] = receiver;
+  args[3] = context;
+
+  return CallN(call_descriptor, target, args);
+}
+
+Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
+                            Node* function, Node* receiver, Node* arg1,
+                            size_t result_size) {
+  const int argc = 1;
+  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
+      isolate(), zone(), callable.descriptor(), argc + 1,
+      CallDescriptor::kNoFlags, Operator::kNoProperties,
+      MachineType::AnyTagged(), result_size);
+  Node* target = HeapConstant(callable.code());
+
+  Node** args = zone()->NewArray<Node*>(argc + 4);
+  args[0] = function;
+  args[1] = Int32Constant(argc);
+  args[2] = receiver;
+  args[3] = arg1;
+  args[4] = context;
+
+  return CallN(call_descriptor, target, args);
+}
+
+Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
+                            Node* function, Node* receiver, Node* arg1,
+                            Node* arg2, size_t result_size) {
+  const int argc = 2;
+  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
+      isolate(), zone(), callable.descriptor(), argc + 1,
+      CallDescriptor::kNoFlags, Operator::kNoProperties,
+      MachineType::AnyTagged(), result_size);
+  Node* target = HeapConstant(callable.code());
+
+  Node** args = zone()->NewArray<Node*>(argc + 4);
+  args[0] = function;
+  args[1] = Int32Constant(argc);
+  args[2] = receiver;
+  args[3] = arg1;
+  args[4] = arg2;
+  args[5] = context;
+
+  return CallN(call_descriptor, target, args);
+}
+
+void CodeAssembler::Goto(CodeAssembler::Label* label) {
+  label->MergeVariables();
+  raw_assembler_->Goto(label->label_);
+}
+
+void CodeAssembler::GotoIf(Node* condition, Label* true_label) {
+  Label false_label(this);
+  Branch(condition, true_label, &false_label);
+  Bind(&false_label);
+}
+
+void CodeAssembler::GotoUnless(Node* condition, Label* false_label) {
+  Label true_label(this);
+  Branch(condition, &true_label, false_label);
+  Bind(&true_label);
+}
+
+void CodeAssembler::Branch(Node* condition, CodeAssembler::Label* true_label,
+                           CodeAssembler::Label* false_label) {
+  true_label->MergeVariables();
+  false_label->MergeVariables();
+  return raw_assembler_->Branch(condition, true_label->label_,
+                                false_label->label_);
+}
+
+void CodeAssembler::Switch(Node* index, Label* default_label,
+                           int32_t* case_values, Label** case_labels,
+                           size_t case_count) {
+  RawMachineLabel** labels =
+      new (zone()->New(sizeof(RawMachineLabel*) * case_count))
+          RawMachineLabel*[case_count];
+  for (size_t i = 0; i < case_count; ++i) {
+    labels[i] = case_labels[i]->label_;
+    case_labels[i]->MergeVariables();
+    default_label->MergeVariables();
+  }
+  return raw_assembler_->Switch(index, default_label->label_, case_values,
+                                labels, case_count);
+}
+
+// RawMachineAssembler delegate helpers:
+Isolate* CodeAssembler::isolate() const { return raw_assembler_->isolate(); }
+
+Factory* CodeAssembler::factory() const { return isolate()->factory(); }
+
+Graph* CodeAssembler::graph() const { return raw_assembler_->graph(); }
+
+Zone* CodeAssembler::zone() const { return raw_assembler_->zone(); }
+
+// The core implementation of Variable is stored through an indirection so
+// that it can outlive the often block-scoped Variable declarations. This is
+// needed to ensure that variable binding and merging through phis can
+// properly be verified.
+class CodeAssembler::Variable::Impl : public ZoneObject {
+ public:
+  explicit Impl(MachineRepresentation rep) : value_(nullptr), rep_(rep) {}
+  Node* value_;
+  MachineRepresentation rep_;
+};
+
+CodeAssembler::Variable::Variable(CodeAssembler* assembler,
+                                  MachineRepresentation rep)
+    : impl_(new (assembler->zone()) Impl(rep)), assembler_(assembler) {
+  assembler->variables_.insert(impl_);
+}
+
+CodeAssembler::Variable::~Variable() { assembler_->variables_.erase(impl_); }
+
+void CodeAssembler::Variable::Bind(Node* value) { impl_->value_ = value; }
+
+Node* CodeAssembler::Variable::value() const {
+  DCHECK_NOT_NULL(impl_->value_);
+  return impl_->value_;
+}
+
+MachineRepresentation CodeAssembler::Variable::rep() const {
+  return impl_->rep_;
+}
+
+bool CodeAssembler::Variable::IsBound() const {
+  return impl_->value_ != nullptr;
+}
+
+CodeAssembler::Label::Label(CodeAssembler* assembler, int merged_value_count,
+                            CodeAssembler::Variable** merged_variables,
+                            CodeAssembler::Label::Type type)
+    : bound_(false), merge_count_(0), assembler_(assembler), label_(nullptr) {
+  void* buffer = assembler->zone()->New(sizeof(RawMachineLabel));
+  label_ = new (buffer)
+      RawMachineLabel(type == kDeferred ? RawMachineLabel::kDeferred
+                                        : RawMachineLabel::kNonDeferred);
+  for (int i = 0; i < merged_value_count; ++i) {
+    variable_phis_[merged_variables[i]->impl_] = nullptr;
+  }
+}
+
+void CodeAssembler::Label::MergeVariables() {
+  ++merge_count_;
+  for (auto var : assembler_->variables_) {
+    size_t count = 0;
+    Node* node = var->value_;
+    if (node != nullptr) {
+      auto i = variable_merges_.find(var);
+      if (i != variable_merges_.end()) {
+        i->second.push_back(node);
+        count = i->second.size();
+      } else {
+        count = 1;
+        variable_merges_[var] = std::vector<Node*>(1, node);
+      }
+    }
+    // If the following asserts, then you've jumped to a label without a bound
+    // variable along that path that expects to merge its value into a phi.
+    DCHECK(variable_phis_.find(var) == variable_phis_.end() ||
+           count == merge_count_);
+    USE(count);
+
+    // If the label is already bound, we already know the set of variables to
+    // merge and phi nodes have already been created.
+    if (bound_) {
+      auto phi = variable_phis_.find(var);
+      if (phi != variable_phis_.end()) {
+        DCHECK_NOT_NULL(phi->second);
+        assembler_->raw_assembler_->AppendPhiInput(phi->second, node);
+      } else {
+        auto i = variable_merges_.find(var);
+        if (i != variable_merges_.end()) {
+          // If the following assert fires, then you've declared a variable that
+          // has the same bound value along all paths up until the point you
+          // bound this label, but then later merged a path with a new value for
+          // the variable after the label bind (it's not possible to add phis to
+          // the bound label after the fact, just make sure to list the variable
+          // in the label's constructor's list of merged variables).
+          DCHECK(find_if(i->second.begin(), i->second.end(),
+                         [node](Node* e) -> bool { return node != e; }) ==
+                 i->second.end());
+        }
+      }
+    }
+  }
+}
+
+void CodeAssembler::Label::Bind() {
+  DCHECK(!bound_);
+  assembler_->raw_assembler_->Bind(label_);
+
+  // Make sure that all variables that have changed along any path up to this
+  // point are marked as merge variables.
+  for (auto var : assembler_->variables_) {
+    Node* shared_value = nullptr;
+    auto i = variable_merges_.find(var);
+    if (i != variable_merges_.end()) {
+      for (auto value : i->second) {
+        DCHECK(value != nullptr);
+        if (value != shared_value) {
+          if (shared_value == nullptr) {
+            shared_value = value;
+          } else {
+            variable_phis_[var] = nullptr;
+          }
+        }
+      }
+    }
+  }
+
+  for (auto var : variable_phis_) {
+    CodeAssembler::Variable::Impl* var_impl = var.first;
+    auto i = variable_merges_.find(var_impl);
+    // If the following assert fires, then a variable that has been marked as
+    // being merged at the label--either by explicitly marking it so in the
+    // label constructor or by having seen different bound values at branches
+    // into the label--doesn't have a bound value along all of the paths that
+    // have been merged into the label up to this point.
+    DCHECK(i != variable_merges_.end() && i->second.size() == merge_count_);
+    Node* phi = assembler_->raw_assembler_->Phi(
+        var.first->rep_, static_cast<int>(merge_count_), &(i->second[0]));
+    variable_phis_[var_impl] = phi;
+  }
+
+  // Bind all variables to a merge phi, the common value along all paths or
+  // null.
+  for (auto var : assembler_->variables_) {
+    auto i = variable_phis_.find(var);
+    if (i != variable_phis_.end()) {
+      var->value_ = i->second;
+    } else {
+      auto j = variable_merges_.find(var);
+      if (j != variable_merges_.end() && j->second.size() == merge_count_) {
+        var->value_ = j->second.back();
+      } else {
+        var->value_ = nullptr;
+      }
+    }
+  }
+
+  bound_ = true;
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/src/compiler/code-assembler.h b/src/compiler/code-assembler.h
new file mode 100644
index 0000000..c33605c
--- /dev/null
+++ b/src/compiler/code-assembler.h
@@ -0,0 +1,438 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_CODE_ASSEMBLER_H_
+#define V8_COMPILER_CODE_ASSEMBLER_H_
+
+#include <map>
+
+// Clients of this interface shouldn't depend on lots of compiler internals.
+// Do not include anything from src/compiler here!
+#include "src/allocation.h"
+#include "src/builtins.h"
+#include "src/heap/heap.h"
+#include "src/machine-type.h"
+#include "src/runtime/runtime.h"
+#include "src/zone-containers.h"
+
+namespace v8 {
+namespace internal {
+
+class Callable;
+class CallInterfaceDescriptor;
+class Isolate;
+class Factory;
+class Zone;
+
+namespace compiler {
+
+class CallDescriptor;
+class Graph;
+class Node;
+class Operator;
+class RawMachineAssembler;
+class RawMachineLabel;
+class Schedule;
+
+#define CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V) \
+  V(Float32Equal)                                \
+  V(Float32LessThan)                             \
+  V(Float32LessThanOrEqual)                      \
+  V(Float32GreaterThan)                          \
+  V(Float32GreaterThanOrEqual)                   \
+  V(Float64Equal)                                \
+  V(Float64LessThan)                             \
+  V(Float64LessThanOrEqual)                      \
+  V(Float64GreaterThan)                          \
+  V(Float64GreaterThanOrEqual)                   \
+  V(Int32GreaterThan)                            \
+  V(Int32GreaterThanOrEqual)                     \
+  V(Int32LessThan)                               \
+  V(Int32LessThanOrEqual)                        \
+  V(IntPtrLessThan)                              \
+  V(IntPtrLessThanOrEqual)                       \
+  V(IntPtrGreaterThan)                           \
+  V(IntPtrGreaterThanOrEqual)                    \
+  V(IntPtrEqual)                                 \
+  V(Uint32LessThan)                              \
+  V(UintPtrLessThan)                             \
+  V(UintPtrGreaterThanOrEqual)                   \
+  V(WordEqual)                                   \
+  V(WordNotEqual)                                \
+  V(Word32Equal)                                 \
+  V(Word32NotEqual)                              \
+  V(Word64Equal)                                 \
+  V(Word64NotEqual)
+
+#define CODE_ASSEMBLER_BINARY_OP_LIST(V)   \
+  CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V) \
+  V(Float64Add)                            \
+  V(Float64Sub)                            \
+  V(Float64Mul)                            \
+  V(Float64Div)                            \
+  V(Float64Mod)                            \
+  V(Float64Atan2)                          \
+  V(Float64InsertLowWord32)                \
+  V(Float64InsertHighWord32)               \
+  V(IntPtrAdd)                             \
+  V(IntPtrAddWithOverflow)                 \
+  V(IntPtrSub)                             \
+  V(IntPtrSubWithOverflow)                 \
+  V(IntPtrMul)                             \
+  V(Int32Add)                              \
+  V(Int32AddWithOverflow)                  \
+  V(Int32Sub)                              \
+  V(Int32Mul)                              \
+  V(Int32Div)                              \
+  V(WordOr)                                \
+  V(WordAnd)                               \
+  V(WordXor)                               \
+  V(WordShl)                               \
+  V(WordShr)                               \
+  V(WordSar)                               \
+  V(WordRor)                               \
+  V(Word32Or)                              \
+  V(Word32And)                             \
+  V(Word32Xor)                             \
+  V(Word32Shl)                             \
+  V(Word32Shr)                             \
+  V(Word32Sar)                             \
+  V(Word32Ror)                             \
+  V(Word64Or)                              \
+  V(Word64And)                             \
+  V(Word64Xor)                             \
+  V(Word64Shr)                             \
+  V(Word64Sar)                             \
+  V(Word64Ror)
+
+#define CODE_ASSEMBLER_UNARY_OP_LIST(V) \
+  V(Float64Atan)                        \
+  V(Float64Atanh)                       \
+  V(Float64Cos)                         \
+  V(Float64Exp)                         \
+  V(Float64Expm1)                       \
+  V(Float64Log)                         \
+  V(Float64Log1p)                       \
+  V(Float64Log2)                        \
+  V(Float64Log10)                       \
+  V(Float64Cbrt)                        \
+  V(Float64Neg)                         \
+  V(Float64Sin)                         \
+  V(Float64Sqrt)                        \
+  V(Float64Tan)                         \
+  V(Float64ExtractLowWord32)            \
+  V(Float64ExtractHighWord32)           \
+  V(BitcastWordToTagged)                \
+  V(TruncateFloat64ToWord32)            \
+  V(TruncateInt64ToInt32)               \
+  V(ChangeFloat64ToUint32)              \
+  V(ChangeInt32ToFloat64)               \
+  V(ChangeInt32ToInt64)                 \
+  V(ChangeUint32ToFloat64)              \
+  V(ChangeUint32ToUint64)               \
+  V(RoundFloat64ToInt32)                \
+  V(Float64RoundDown)                   \
+  V(Float64RoundUp)                     \
+  V(Float64RoundTruncate)               \
+  V(Word32Clz)
+
+// A "public" interface used by components outside of compiler directory to
+// create code objects with TurboFan's backend. This class is mostly a thin shim
+// around the RawMachineAssembler, and its primary job is to ensure that the
+// innards of the RawMachineAssembler and other compiler implementation details
+// don't leak outside of the the compiler directory..
+//
+// V8 components that need to generate low-level code using this interface
+// should include this header--and this header only--from the compiler directory
+// (this is actually enforced). Since all interesting data structures are
+// forward declared, it's not possible for clients to peek inside the compiler
+// internals.
+//
+// In addition to providing isolation between TurboFan and code generation
+// clients, CodeAssembler also provides an abstraction for creating variables
+// and enhanced Label functionality to merge variable values along paths where
+// they have differing values, including loops.
+class CodeAssembler {
+ public:
+  // Create with CallStub linkage.
+  // |result_size| specifies the number of results returned by the stub.
+  // TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
+  CodeAssembler(Isolate* isolate, Zone* zone,
+                const CallInterfaceDescriptor& descriptor, Code::Flags flags,
+                const char* name, size_t result_size = 1);
+
+  // Create with JSCall linkage.
+  CodeAssembler(Isolate* isolate, Zone* zone, int parameter_count,
+                Code::Flags flags, const char* name);
+
+  virtual ~CodeAssembler();
+
+  Handle<Code> GenerateCode();
+
+  bool Is64() const;
+  bool IsFloat64RoundUpSupported() const;
+  bool IsFloat64RoundDownSupported() const;
+  bool IsFloat64RoundTruncateSupported() const;
+
+  class Label;
+  class Variable {
+   public:
+    explicit Variable(CodeAssembler* assembler, MachineRepresentation rep);
+    ~Variable();
+    void Bind(Node* value);
+    Node* value() const;
+    MachineRepresentation rep() const;
+    bool IsBound() const;
+
+   private:
+    friend class CodeAssembler;
+    class Impl;
+    Impl* impl_;
+    CodeAssembler* assembler_;
+  };
+
+  enum AllocationFlag : uint8_t {
+    kNone = 0,
+    kDoubleAlignment = 1,
+    kPretenured = 1 << 1
+  };
+
+  typedef base::Flags<AllocationFlag> AllocationFlags;
+
+  // ===========================================================================
+  // Base Assembler
+  // ===========================================================================
+
+  // Constants.
+  Node* Int32Constant(int32_t value);
+  Node* Int64Constant(int64_t value);
+  Node* IntPtrConstant(intptr_t value);
+  Node* NumberConstant(double value);
+  Node* SmiConstant(Smi* value);
+  Node* HeapConstant(Handle<HeapObject> object);
+  Node* BooleanConstant(bool value);
+  Node* ExternalConstant(ExternalReference address);
+  Node* Float64Constant(double value);
+  Node* NaNConstant();
+
+  bool ToInt32Constant(Node* node, int32_t& out_value);
+  bool ToInt64Constant(Node* node, int64_t& out_value);
+  bool ToIntPtrConstant(Node* node, intptr_t& out_value);
+
+  Node* Parameter(int value);
+  void Return(Node* value);
+
+  void DebugBreak();
+  void Comment(const char* format, ...);
+
+  void Bind(Label* label);
+  void Goto(Label* label);
+  void GotoIf(Node* condition, Label* true_label);
+  void GotoUnless(Node* condition, Label* false_label);
+  void Branch(Node* condition, Label* true_label, Label* false_label);
+
+  void Switch(Node* index, Label* default_label, int32_t* case_values,
+              Label** case_labels, size_t case_count);
+
+  // Access to the frame pointer
+  Node* LoadFramePointer();
+  Node* LoadParentFramePointer();
+
+  // Access to the stack pointer
+  Node* LoadStackPointer();
+
+  // Load raw memory location.
+  Node* Load(MachineType rep, Node* base);
+  Node* Load(MachineType rep, Node* base, Node* index);
+  Node* AtomicLoad(MachineType rep, Node* base, Node* index);
+
+  // Load a value from the root array.
+  Node* LoadRoot(Heap::RootListIndex root_index);
+
+  // Store value to raw memory location.
+  Node* Store(MachineRepresentation rep, Node* base, Node* value);
+  Node* Store(MachineRepresentation rep, Node* base, Node* index, Node* value);
+  Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* value);
+  Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* index,
+                            Node* value);
+  Node* AtomicStore(MachineRepresentation rep, Node* base, Node* index,
+                    Node* value);
+
+  // Store a value to the root array.
+  Node* StoreRoot(Heap::RootListIndex root_index, Node* value);
+
+// Basic arithmetic operations.
+#define DECLARE_CODE_ASSEMBLER_BINARY_OP(name) Node* name(Node* a, Node* b);
+  CODE_ASSEMBLER_BINARY_OP_LIST(DECLARE_CODE_ASSEMBLER_BINARY_OP)
+#undef DECLARE_CODE_ASSEMBLER_BINARY_OP
+
+  Node* WordShl(Node* value, int shift);
+  Node* WordShr(Node* value, int shift);
+
+// Unary
+#define DECLARE_CODE_ASSEMBLER_UNARY_OP(name) Node* name(Node* a);
+  CODE_ASSEMBLER_UNARY_OP_LIST(DECLARE_CODE_ASSEMBLER_UNARY_OP)
+#undef DECLARE_CODE_ASSEMBLER_UNARY_OP
+
+  // No-op on 32-bit, otherwise zero extend.
+  Node* ChangeUint32ToWord(Node* value);
+  // No-op on 32-bit, otherwise sign extend.
+  Node* ChangeInt32ToIntPtr(Node* value);
+
+  // Projections
+  Node* Projection(int index, Node* value);
+
+  // Calls
+  Node* CallRuntime(Runtime::FunctionId function_id, Node* context);
+  Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1);
+  Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1,
+                    Node* arg2);
+  Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1,
+                    Node* arg2, Node* arg3);
+  Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1,
+                    Node* arg2, Node* arg3, Node* arg4);
+  Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1,
+                    Node* arg2, Node* arg3, Node* arg4, Node* arg5);
+
+  Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context);
+  Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
+                        Node* arg1);
+  Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
+                        Node* arg1, Node* arg2);
+  Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
+                        Node* arg1, Node* arg2, Node* arg3);
+  Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
+                        Node* arg1, Node* arg2, Node* arg3, Node* arg4);
+
+  Node* CallStub(Callable const& callable, Node* context, Node* arg1,
+                 size_t result_size = 1);
+  Node* CallStub(Callable const& callable, Node* context, Node* arg1,
+                 Node* arg2, size_t result_size = 1);
+  Node* CallStub(Callable const& callable, Node* context, Node* arg1,
+                 Node* arg2, Node* arg3, size_t result_size = 1);
+  Node* CallStubN(Callable const& callable, Node** args,
+                  size_t result_size = 1);
+
+  Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
+                 Node* context, Node* arg1, size_t result_size = 1);
+  Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
+                 Node* context, Node* arg1, Node* arg2, size_t result_size = 1);
+  Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
+                 Node* context, Node* arg1, Node* arg2, Node* arg3,
+                 size_t result_size = 1);
+  Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
+                 Node* context, Node* arg1, Node* arg2, Node* arg3, Node* arg4,
+                 size_t result_size = 1);
+  Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
+                 Node* context, Node* arg1, Node* arg2, Node* arg3, Node* arg4,
+                 Node* arg5, size_t result_size = 1);
+  Node* CallStubN(const CallInterfaceDescriptor& descriptor, Node* target,
+                  Node** args, size_t result_size = 1);
+
+  Node* TailCallStub(Callable const& callable, Node* context, Node* arg1,
+                     Node* arg2, size_t result_size = 1);
+  Node* TailCallStub(Callable const& callable, Node* context, Node* arg1,
+                     Node* arg2, Node* arg3, size_t result_size = 1);
+  Node* TailCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
+                     Node* context, Node* arg1, Node* arg2,
+                     size_t result_size = 1);
+  Node* TailCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
+                     Node* context, Node* arg1, Node* arg2, Node* arg3,
+                     size_t result_size = 1);
+  Node* TailCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
+                     Node* context, Node* arg1, Node* arg2, Node* arg3,
+                     Node* arg4, size_t result_size = 1);
+
+  Node* TailCallBytecodeDispatch(const CallInterfaceDescriptor& descriptor,
+                                 Node* code_target_address, Node** args);
+
+  Node* CallJS(Callable const& callable, Node* context, Node* function,
+               Node* receiver, size_t result_size = 1);
+  Node* CallJS(Callable const& callable, Node* context, Node* function,
+               Node* receiver, Node* arg1, size_t result_size = 1);
+  Node* CallJS(Callable const& callable, Node* context, Node* function,
+               Node* receiver, Node* arg1, Node* arg2, size_t result_size = 1);
+
+  // Branching helpers.
+  void BranchIf(Node* condition, Label* if_true, Label* if_false);
+
+#define BRANCH_HELPER(name)                                                \
+  void BranchIf##name(Node* a, Node* b, Label* if_true, Label* if_false) { \
+    BranchIf(name(a, b), if_true, if_false);                               \
+  }
+  CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(BRANCH_HELPER)
+#undef BRANCH_HELPER
+
+  // Helpers which delegate to RawMachineAssembler.
+  Factory* factory() const;
+  Isolate* isolate() const;
+  Zone* zone() const;
+
+ protected:
+  // Protected helpers which delegate to RawMachineAssembler.
+  Graph* graph() const;
+
+  Node* SmiShiftBitsConstant();
+
+  // Enables subclasses to perform operations before and after a call.
+  virtual void CallPrologue();
+  virtual void CallEpilogue();
+
+ private:
+  CodeAssembler(Isolate* isolate, Zone* zone, CallDescriptor* call_descriptor,
+                Code::Flags flags, const char* name);
+
+  Node* CallN(CallDescriptor* descriptor, Node* code_target, Node** args);
+  Node* TailCallN(CallDescriptor* descriptor, Node* code_target, Node** args);
+
+  base::SmartPointer<RawMachineAssembler> raw_assembler_;
+  Code::Flags flags_;
+  const char* name_;
+  bool code_generated_;
+  ZoneSet<Variable::Impl*> variables_;
+
+  DISALLOW_COPY_AND_ASSIGN(CodeAssembler);
+};
+
+DEFINE_OPERATORS_FOR_FLAGS(CodeAssembler::AllocationFlags);
+
+class CodeAssembler::Label {
+ public:
+  enum Type { kDeferred, kNonDeferred };
+
+  explicit Label(
+      CodeAssembler* assembler,
+      CodeAssembler::Label::Type type = CodeAssembler::Label::kNonDeferred)
+      : CodeAssembler::Label(assembler, 0, nullptr, type) {}
+  Label(CodeAssembler* assembler, CodeAssembler::Variable* merged_variable,
+        CodeAssembler::Label::Type type = CodeAssembler::Label::kNonDeferred)
+      : CodeAssembler::Label(assembler, 1, &merged_variable, type) {}
+  Label(CodeAssembler* assembler, int merged_variable_count,
+        CodeAssembler::Variable** merged_variables,
+        CodeAssembler::Label::Type type = CodeAssembler::Label::kNonDeferred);
+  ~Label() {}
+
+ private:
+  friend class CodeAssembler;
+
+  void Bind();
+  void MergeVariables();
+
+  bool bound_;
+  size_t merge_count_;
+  CodeAssembler* assembler_;
+  RawMachineLabel* label_;
+  // Map of variables that need to be merged to their phi nodes (or placeholders
+  // for those phis).
+  std::map<Variable::Impl*, Node*> variable_phis_;
+  // Map of variables to the list of value nodes that have been added from each
+  // merge path in their order of merging.
+  std::map<Variable::Impl*, std::vector<Node*>> variable_merges_;
+};
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_COMPILER_CODE_ASSEMBLER_H_
diff --git a/src/compiler/code-generator-impl.h b/src/compiler/code-generator-impl.h
index 7de32c5..4e09a27 100644
--- a/src/compiler/code-generator-impl.h
+++ b/src/compiler/code-generator-impl.h
@@ -31,6 +31,10 @@
     return ToRegister(instr_->InputAt(index));
   }
 
+  FloatRegister InputFloatRegister(size_t index) {
+    return ToFloatRegister(instr_->InputAt(index));
+  }
+
   DoubleRegister InputDoubleRegister(size_t index) {
     return ToDoubleRegister(instr_->InputAt(index));
   }
@@ -43,6 +47,10 @@
     return ToConstant(instr_->InputAt(index)).ToInt32();
   }
 
+  uint32_t InputUint32(size_t index) {
+    return bit_cast<uint32_t>(InputInt32(index));
+  }
+
   int64_t InputInt64(size_t index) {
     return ToConstant(instr_->InputAt(index)).ToInt64();
   }
@@ -85,6 +93,10 @@
     return ToRegister(instr_->TempAt(index));
   }
 
+  FloatRegister OutputFloatRegister() {
+    return ToFloatRegister(instr_->Output());
+  }
+
   DoubleRegister OutputDoubleRegister() {
     return ToDoubleRegister(instr_->Output());
   }
@@ -107,6 +119,10 @@
     return LocationOperand::cast(op)->GetDoubleRegister();
   }
 
+  FloatRegister ToFloatRegister(InstructionOperand* op) {
+    return LocationOperand::cast(op)->GetFloatRegister();
+  }
+
   Constant ToConstant(InstructionOperand* op) {
     if (op->IsImmediate()) {
       return gen_->code()->GetImmediate(ImmediateOperand::cast(op));
@@ -127,7 +143,7 @@
     return ToConstant(op).ToHeapObject();
   }
 
-  Frame* frame() const { return gen_->frame(); }
+  const Frame* frame() const { return gen_->frame(); }
   FrameAccessState* frame_access_state() const {
     return gen_->frame_access_state();
   }
@@ -163,7 +179,7 @@
 
   Label* entry() { return &entry_; }
   Label* exit() { return &exit_; }
-  Frame* frame() const { return frame_; }
+  const Frame* frame() const { return frame_; }
   Isolate* isolate() const { return masm()->isolate(); }
   MacroAssembler* masm() const { return masm_; }
   OutOfLineCode* next() const { return next_; }
@@ -171,7 +187,7 @@
  private:
   Label entry_;
   Label exit_;
-  Frame* const frame_;
+  const Frame* const frame_;
   MacroAssembler* const masm_;
   OutOfLineCode* const next_;
 };
diff --git a/src/compiler/code-generator.cc b/src/compiler/code-generator.cc
index 086da56..f388659 100644
--- a/src/compiler/code-generator.cc
+++ b/src/compiler/code-generator.cc
@@ -33,7 +33,7 @@
 
 CodeGenerator::CodeGenerator(Frame* frame, Linkage* linkage,
                              InstructionSequence* code, CompilationInfo* info)
-    : frame_access_state_(new (code->zone()) FrameAccessState(frame)),
+    : frame_access_state_(nullptr),
       linkage_(linkage),
       code_(code),
       info_(info),
@@ -56,6 +56,12 @@
   for (int i = 0; i < code->InstructionBlockCount(); ++i) {
     new (&labels_[i]) Label;
   }
+  CreateFrameAccessState(frame);
+}
+
+void CodeGenerator::CreateFrameAccessState(Frame* frame) {
+  FinishFrame(frame);
+  frame_access_state_ = new (code()->zone()) FrameAccessState(frame);
 }
 
 Handle<Code> CodeGenerator::GenerateCode() {
@@ -96,9 +102,6 @@
     }
   }
 
-  // Finish the Frame
-  frame()->AlignFrame(kFrameAlignmentInBytes);
-  AssembleSetupStackPointer();
   // Assemble all non-deferred blocks, followed by deferred ones.
   for (int deferred = 0; deferred < 2; ++deferred) {
     for (const InstructionBlock* block : code()->instruction_blocks()) {
@@ -143,7 +146,7 @@
 
       masm()->bind(GetLabel(current_block_));
       if (block->must_construct_frame()) {
-        AssemblePrologue();
+        AssembleConstructFrame();
         // We need to setup the root register after we assemble the prologue, to
         // avoid clobbering callee saved registers in case of C linkage and
         // using the roots.
@@ -153,12 +156,14 @@
         }
       }
 
+      CodeGenResult result;
       if (FLAG_enable_embedded_constant_pool && !block->needs_frame()) {
         ConstantPoolUnavailableScope constant_pool_unavailable(masm());
-        AssembleBlock(block);
+        result = AssembleBlock(block);
       } else {
-        AssembleBlock(block);
+        result = AssembleBlock(block);
       }
+      if (result != kSuccess) return Handle<Code>();
     }
   }
 
@@ -274,8 +279,7 @@
 bool CodeGenerator::IsMaterializableFromFrame(Handle<HeapObject> object,
                                               int* slot_return) {
   if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) {
-    if (info()->has_context() && object.is_identical_to(info()->context()) &&
-        !info()->is_osr()) {
+    if (object.is_identical_to(info()->context()) && !info()->is_osr()) {
       *slot_return = Frame::kContextSlot;
       return true;
     } else if (object.is_identical_to(info()->closure())) {
@@ -302,15 +306,18 @@
   return false;
 }
 
-void CodeGenerator::AssembleBlock(const InstructionBlock* block) {
+CodeGenerator::CodeGenResult CodeGenerator::AssembleBlock(
+    const InstructionBlock* block) {
   for (int i = block->code_start(); i < block->code_end(); ++i) {
     Instruction* instr = code()->InstructionAt(i);
-    AssembleInstruction(instr, block);
+    CodeGenResult result = AssembleInstruction(instr, block);
+    if (result != kSuccess) return result;
   }
+  return kSuccess;
 }
 
-void CodeGenerator::AssembleInstruction(Instruction* instr,
-                                        const InstructionBlock* block) {
+CodeGenerator::CodeGenResult CodeGenerator::AssembleInstruction(
+    Instruction* instr, const InstructionBlock* block) {
   AssembleGaps(instr);
   DCHECK_IMPLIES(
       block->must_deconstruct_frame(),
@@ -321,7 +328,8 @@
   }
   AssembleSourcePosition(instr);
   // Assemble architecture-specific code for the instruction.
-  AssembleArchInstruction(instr);
+  CodeGenResult result = AssembleArchInstruction(instr);
+  if (result != kSuccess) return result;
 
   FlagsMode mode = FlagsModeField::decode(instr->opcode());
   FlagsCondition condition = FlagsConditionField::decode(instr->opcode());
@@ -337,7 +345,7 @@
         if (!IsNextInAssemblyOrder(true_rpo)) {
           AssembleArchJump(true_rpo);
         }
-        return;
+        return kSuccess;
       }
       if (IsNextInAssemblyOrder(true_rpo)) {
         // true block is next, can fall through if condition negated.
@@ -379,6 +387,7 @@
       break;
     }
   }
+  return kSuccess;
 }
 
 
@@ -390,10 +399,10 @@
   if (source_position.IsUnknown()) return;
   int code_pos = source_position.raw();
   masm()->positions_recorder()->RecordPosition(code_pos);
-  masm()->positions_recorder()->WriteRecordedPositions();
   if (FLAG_code_comments) {
-    Vector<char> buffer = Vector<char>::New(256);
     CompilationInfo* info = this->info();
+    if (!info->parse_info()) return;
+    Vector<char> buffer = Vector<char>::New(256);
     int ln = Script::GetLineNumber(info->script(), code_pos);
     int cn = Script::GetColumnNumber(info->script(), code_pos);
     if (info->script()->name()->IsString()) {
@@ -498,10 +507,6 @@
     handlers_.push_back({caught, GetLabel(handler_rpo), masm()->pc_offset()});
   }
 
-  if (flags & CallDescriptor::kNeedsNopAfterCall) {
-    AddNopForSmiCodeInlining();
-  }
-
   if (needs_frame_state) {
     MarkLazyDeoptSite();
     // If the frame state is present, it starts at argument 1 (just after the
@@ -528,7 +533,7 @@
     // by calls.)
     for (size_t i = 0; i < descriptor->GetSize(); i++) {
       InstructionOperand* op = instr->InputAt(frame_state_offset + 1 + i);
-      CHECK(op->IsStackSlot() || op->IsDoubleStackSlot() || op->IsImmediate());
+      CHECK(op->IsStackSlot() || op->IsFPStackSlot() || op->IsImmediate());
     }
 #endif
     safepoints()->RecordLazyDeoptimizationIndex(deopt_state_id);
@@ -710,9 +715,13 @@
     } else {
       CHECK(false);
     }
-  } else if (op->IsDoubleStackSlot()) {
-    DCHECK(IsFloatingPoint(type.representation()));
-    translation->StoreDoubleStackSlot(LocationOperand::cast(op)->index());
+  } else if (op->IsFPStackSlot()) {
+    if (type.representation() == MachineRepresentation::kFloat64) {
+      translation->StoreDoubleStackSlot(LocationOperand::cast(op)->index());
+    } else {
+      DCHECK_EQ(MachineRepresentation::kFloat32, type.representation());
+      translation->StoreFloatStackSlot(LocationOperand::cast(op)->index());
+    }
   } else if (op->IsRegister()) {
     InstructionOperandConverter converter(this, instr);
     if (type.representation() == MachineRepresentation::kBit) {
@@ -728,10 +737,14 @@
     } else {
       CHECK(false);
     }
-  } else if (op->IsDoubleRegister()) {
-    DCHECK(IsFloatingPoint(type.representation()));
+  } else if (op->IsFPRegister()) {
     InstructionOperandConverter converter(this, instr);
-    translation->StoreDoubleRegister(converter.ToDoubleRegister(op));
+    if (type.representation() == MachineRepresentation::kFloat64) {
+      translation->StoreDoubleRegister(converter.ToDoubleRegister(op));
+    } else {
+      DCHECK_EQ(MachineRepresentation::kFloat32, type.representation());
+      translation->StoreFloatRegister(converter.ToFloatRegister(op));
+    }
   } else if (op->IsImmediate()) {
     InstructionOperandConverter converter(this, instr);
     Constant constant = converter.ToConstant(op);
diff --git a/src/compiler/code-generator.h b/src/compiler/code-generator.h
index b82181c..5f35e8a 100644
--- a/src/compiler/code-generator.h
+++ b/src/compiler/code-generator.h
@@ -54,7 +54,7 @@
 
   InstructionSequence* code() const { return code_; }
   FrameAccessState* frame_access_state() const { return frame_access_state_; }
-  Frame* frame() const { return frame_access_state_->frame(); }
+  const Frame* frame() const { return frame_access_state_->frame(); }
   Isolate* isolate() const { return info_->isolate(); }
   Linkage* linkage() const { return linkage_; }
 
@@ -67,6 +67,12 @@
   Zone* zone() const { return code()->zone(); }
   CompilationInfo* info() const { return info_; }
 
+  // Create the FrameAccessState object. The Frame is immutable from here on.
+  void CreateFrameAccessState(Frame* frame);
+
+  // Architecture - specific frame finalization.
+  void FinishFrame(Frame* frame);
+
   // Checks if {block} will appear directly after {current_block_} when
   // assembling code, in which case, a fall-through can be used.
   bool IsNextInAssemblyOrder(RpoNumber block) const;
@@ -84,11 +90,14 @@
   bool IsMaterializableFromRoot(Handle<HeapObject> object,
                                 Heap::RootListIndex* index_return);
 
+  enum CodeGenResult { kSuccess, kTooManyDeoptimizationBailouts };
+
   // Assemble instructions for the specified block.
-  void AssembleBlock(const InstructionBlock* block);
+  CodeGenResult AssembleBlock(const InstructionBlock* block);
 
   // Assemble code for the specified instruction.
-  void AssembleInstruction(Instruction* instr, const InstructionBlock* block);
+  CodeGenResult AssembleInstruction(Instruction* instr,
+                                    const InstructionBlock* block);
   void AssembleSourcePosition(Instruction* instr);
   void AssembleGaps(Instruction* instr);
 
@@ -96,21 +105,19 @@
   // ============= Architecture-specific code generation methods. ==============
   // ===========================================================================
 
-  void AssembleArchInstruction(Instruction* instr);
+  CodeGenResult AssembleArchInstruction(Instruction* instr);
   void AssembleArchJump(RpoNumber target);
   void AssembleArchBranch(Instruction* instr, BranchInfo* branch);
   void AssembleArchBoolean(Instruction* instr, FlagsCondition condition);
   void AssembleArchLookupSwitch(Instruction* instr);
   void AssembleArchTableSwitch(Instruction* instr);
 
-  void AssembleDeoptimizerCall(int deoptimization_id,
-                               Deoptimizer::BailoutType bailout_type);
+  CodeGenResult AssembleDeoptimizerCall(int deoptimization_id,
+                                        Deoptimizer::BailoutType bailout_type);
 
   // Generates an architecture-specific, descriptor-specific prologue
   // to set up a stack frame.
-  void AssemblePrologue();
-
-  void AssembleSetupStackPointer();
+  void AssembleConstructFrame();
 
   // Generates an architecture-specific, descriptor-specific return sequence
   // to tear down a stack frame.
@@ -174,7 +181,6 @@
                                              Translation* translation);
   void AddTranslationForOperand(Translation* translation, Instruction* instr,
                                 InstructionOperand* op, MachineType type);
-  void AddNopForSmiCodeInlining();
   void EnsureSpaceForLazyDeopt();
   void MarkLazyDeoptSite();
 
diff --git a/src/compiler/code-stub-assembler.cc b/src/compiler/code-stub-assembler.cc
deleted file mode 100644
index bbb4d63..0000000
--- a/src/compiler/code-stub-assembler.cc
+++ /dev/null
@@ -1,1353 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/compiler/code-stub-assembler.h"
-
-#include <ostream>
-
-#include "src/code-factory.h"
-#include "src/compiler/graph.h"
-#include "src/compiler/instruction-selector.h"
-#include "src/compiler/linkage.h"
-#include "src/compiler/pipeline.h"
-#include "src/compiler/raw-machine-assembler.h"
-#include "src/compiler/schedule.h"
-#include "src/frames.h"
-#include "src/interface-descriptors.h"
-#include "src/interpreter/bytecodes.h"
-#include "src/machine-type.h"
-#include "src/macro-assembler.h"
-#include "src/zone.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-CodeStubAssembler::CodeStubAssembler(Isolate* isolate, Zone* zone,
-                                     const CallInterfaceDescriptor& descriptor,
-                                     Code::Flags flags, const char* name,
-                                     size_t result_size)
-    : CodeStubAssembler(
-          isolate, zone,
-          Linkage::GetStubCallDescriptor(
-              isolate, zone, descriptor, descriptor.GetStackParameterCount(),
-              CallDescriptor::kNoFlags, Operator::kNoProperties,
-              MachineType::AnyTagged(), result_size),
-          flags, name) {}
-
-CodeStubAssembler::CodeStubAssembler(Isolate* isolate, Zone* zone,
-                                     int parameter_count, Code::Flags flags,
-                                     const char* name)
-    : CodeStubAssembler(isolate, zone, Linkage::GetJSCallDescriptor(
-                                           zone, false, parameter_count,
-                                           CallDescriptor::kNoFlags),
-                        flags, name) {}
-
-CodeStubAssembler::CodeStubAssembler(Isolate* isolate, Zone* zone,
-                                     CallDescriptor* call_descriptor,
-                                     Code::Flags flags, const char* name)
-    : raw_assembler_(new RawMachineAssembler(
-          isolate, new (zone) Graph(zone), call_descriptor,
-          MachineType::PointerRepresentation(),
-          InstructionSelector::SupportedMachineOperatorFlags())),
-      flags_(flags),
-      name_(name),
-      code_generated_(false),
-      variables_(zone) {}
-
-CodeStubAssembler::~CodeStubAssembler() {}
-
-void CodeStubAssembler::CallPrologue() {}
-
-void CodeStubAssembler::CallEpilogue() {}
-
-Handle<Code> CodeStubAssembler::GenerateCode() {
-  DCHECK(!code_generated_);
-
-  Schedule* schedule = raw_assembler_->Export();
-  Handle<Code> code = Pipeline::GenerateCodeForCodeStub(
-      isolate(), raw_assembler_->call_descriptor(), graph(), schedule, flags_,
-      name_);
-
-  code_generated_ = true;
-  return code;
-}
-
-
-Node* CodeStubAssembler::Int32Constant(int value) {
-  return raw_assembler_->Int32Constant(value);
-}
-
-
-Node* CodeStubAssembler::IntPtrConstant(intptr_t value) {
-  return raw_assembler_->IntPtrConstant(value);
-}
-
-
-Node* CodeStubAssembler::NumberConstant(double value) {
-  return raw_assembler_->NumberConstant(value);
-}
-
-Node* CodeStubAssembler::SmiConstant(Smi* value) {
-  return IntPtrConstant(bit_cast<intptr_t>(value));
-}
-
-Node* CodeStubAssembler::HeapConstant(Handle<HeapObject> object) {
-  return raw_assembler_->HeapConstant(object);
-}
-
-
-Node* CodeStubAssembler::BooleanConstant(bool value) {
-  return raw_assembler_->BooleanConstant(value);
-}
-
-Node* CodeStubAssembler::ExternalConstant(ExternalReference address) {
-  return raw_assembler_->ExternalConstant(address);
-}
-
-Node* CodeStubAssembler::Float64Constant(double value) {
-  return raw_assembler_->Float64Constant(value);
-}
-
-Node* CodeStubAssembler::BooleanMapConstant() {
-  return HeapConstant(isolate()->factory()->boolean_map());
-}
-
-Node* CodeStubAssembler::HeapNumberMapConstant() {
-  return HeapConstant(isolate()->factory()->heap_number_map());
-}
-
-Node* CodeStubAssembler::NullConstant() {
-  return LoadRoot(Heap::kNullValueRootIndex);
-}
-
-Node* CodeStubAssembler::UndefinedConstant() {
-  return LoadRoot(Heap::kUndefinedValueRootIndex);
-}
-
-Node* CodeStubAssembler::Parameter(int value) {
-  return raw_assembler_->Parameter(value);
-}
-
-void CodeStubAssembler::Return(Node* value) {
-  return raw_assembler_->Return(value);
-}
-
-void CodeStubAssembler::Bind(CodeStubAssembler::Label* label) {
-  return label->Bind();
-}
-
-Node* CodeStubAssembler::LoadFramePointer() {
-  return raw_assembler_->LoadFramePointer();
-}
-
-Node* CodeStubAssembler::LoadParentFramePointer() {
-  return raw_assembler_->LoadParentFramePointer();
-}
-
-Node* CodeStubAssembler::LoadStackPointer() {
-  return raw_assembler_->LoadStackPointer();
-}
-
-Node* CodeStubAssembler::SmiShiftBitsConstant() {
-  return IntPtrConstant(kSmiShiftSize + kSmiTagSize);
-}
-
-Node* CodeStubAssembler::Float64Round(Node* x) {
-  Node* one = Float64Constant(1.0);
-  Node* one_half = Float64Constant(0.5);
-
-  Variable var_x(this, MachineRepresentation::kFloat64);
-  Label return_x(this);
-
-  // Round up {x} towards Infinity.
-  var_x.Bind(Float64Ceil(x));
-
-  GotoIf(Float64LessThanOrEqual(Float64Sub(var_x.value(), one_half), x),
-         &return_x);
-  var_x.Bind(Float64Sub(var_x.value(), one));
-  Goto(&return_x);
-
-  Bind(&return_x);
-  return var_x.value();
-}
-
-Node* CodeStubAssembler::Float64Ceil(Node* x) {
-  if (raw_assembler_->machine()->Float64RoundUp().IsSupported()) {
-    return raw_assembler_->Float64RoundUp(x);
-  }
-
-  Node* one = Float64Constant(1.0);
-  Node* zero = Float64Constant(0.0);
-  Node* two_52 = Float64Constant(4503599627370496.0E0);
-  Node* minus_two_52 = Float64Constant(-4503599627370496.0E0);
-
-  Variable var_x(this, MachineRepresentation::kFloat64);
-  Label return_x(this), return_minus_x(this);
-  var_x.Bind(x);
-
-  // Check if {x} is greater than zero.
-  Label if_xgreaterthanzero(this), if_xnotgreaterthanzero(this);
-  Branch(Float64GreaterThan(x, zero), &if_xgreaterthanzero,
-         &if_xnotgreaterthanzero);
-
-  Bind(&if_xgreaterthanzero);
-  {
-    // Just return {x} unless it's in the range ]0,2^52[.
-    GotoIf(Float64GreaterThanOrEqual(x, two_52), &return_x);
-
-    // Round positive {x} towards Infinity.
-    var_x.Bind(Float64Sub(Float64Add(two_52, x), two_52));
-    GotoUnless(Float64LessThan(var_x.value(), x), &return_x);
-    var_x.Bind(Float64Add(var_x.value(), one));
-    Goto(&return_x);
-  }
-
-  Bind(&if_xnotgreaterthanzero);
-  {
-    // Just return {x} unless it's in the range ]-2^52,0[
-    GotoIf(Float64LessThanOrEqual(x, minus_two_52), &return_x);
-    GotoUnless(Float64LessThan(x, zero), &return_x);
-
-    // Round negated {x} towards Infinity and return the result negated.
-    Node* minus_x = Float64Neg(x);
-    var_x.Bind(Float64Sub(Float64Add(two_52, minus_x), two_52));
-    GotoUnless(Float64GreaterThan(var_x.value(), minus_x), &return_minus_x);
-    var_x.Bind(Float64Sub(var_x.value(), one));
-    Goto(&return_minus_x);
-  }
-
-  Bind(&return_minus_x);
-  var_x.Bind(Float64Neg(var_x.value()));
-  Goto(&return_x);
-
-  Bind(&return_x);
-  return var_x.value();
-}
-
-Node* CodeStubAssembler::Float64Floor(Node* x) {
-  if (raw_assembler_->machine()->Float64RoundDown().IsSupported()) {
-    return raw_assembler_->Float64RoundDown(x);
-  }
-
-  Node* one = Float64Constant(1.0);
-  Node* zero = Float64Constant(0.0);
-  Node* two_52 = Float64Constant(4503599627370496.0E0);
-  Node* minus_two_52 = Float64Constant(-4503599627370496.0E0);
-
-  Variable var_x(this, MachineRepresentation::kFloat64);
-  Label return_x(this), return_minus_x(this);
-  var_x.Bind(x);
-
-  // Check if {x} is greater than zero.
-  Label if_xgreaterthanzero(this), if_xnotgreaterthanzero(this);
-  Branch(Float64GreaterThan(x, zero), &if_xgreaterthanzero,
-         &if_xnotgreaterthanzero);
-
-  Bind(&if_xgreaterthanzero);
-  {
-    // Just return {x} unless it's in the range ]0,2^52[.
-    GotoIf(Float64GreaterThanOrEqual(x, two_52), &return_x);
-
-    // Round positive {x} towards -Infinity.
-    var_x.Bind(Float64Sub(Float64Add(two_52, x), two_52));
-    GotoUnless(Float64GreaterThan(var_x.value(), x), &return_x);
-    var_x.Bind(Float64Sub(var_x.value(), one));
-    Goto(&return_x);
-  }
-
-  Bind(&if_xnotgreaterthanzero);
-  {
-    // Just return {x} unless it's in the range ]-2^52,0[
-    GotoIf(Float64LessThanOrEqual(x, minus_two_52), &return_x);
-    GotoUnless(Float64LessThan(x, zero), &return_x);
-
-    // Round negated {x} towards -Infinity and return the result negated.
-    Node* minus_x = Float64Neg(x);
-    var_x.Bind(Float64Sub(Float64Add(two_52, minus_x), two_52));
-    GotoUnless(Float64LessThan(var_x.value(), minus_x), &return_minus_x);
-    var_x.Bind(Float64Add(var_x.value(), one));
-    Goto(&return_minus_x);
-  }
-
-  Bind(&return_minus_x);
-  var_x.Bind(Float64Neg(var_x.value()));
-  Goto(&return_x);
-
-  Bind(&return_x);
-  return var_x.value();
-}
-
-Node* CodeStubAssembler::Float64Trunc(Node* x) {
-  if (raw_assembler_->machine()->Float64RoundTruncate().IsSupported()) {
-    return raw_assembler_->Float64RoundTruncate(x);
-  }
-
-  Node* one = Float64Constant(1.0);
-  Node* zero = Float64Constant(0.0);
-  Node* two_52 = Float64Constant(4503599627370496.0E0);
-  Node* minus_two_52 = Float64Constant(-4503599627370496.0E0);
-
-  Variable var_x(this, MachineRepresentation::kFloat64);
-  Label return_x(this), return_minus_x(this);
-  var_x.Bind(x);
-
-  // Check if {x} is greater than 0.
-  Label if_xgreaterthanzero(this), if_xnotgreaterthanzero(this);
-  Branch(Float64GreaterThan(x, zero), &if_xgreaterthanzero,
-         &if_xnotgreaterthanzero);
-
-  Bind(&if_xgreaterthanzero);
-  {
-    if (raw_assembler_->machine()->Float64RoundDown().IsSupported()) {
-      var_x.Bind(raw_assembler_->Float64RoundDown(x));
-    } else {
-      // Just return {x} unless it's in the range ]0,2^52[.
-      GotoIf(Float64GreaterThanOrEqual(x, two_52), &return_x);
-
-      // Round positive {x} towards -Infinity.
-      var_x.Bind(Float64Sub(Float64Add(two_52, x), two_52));
-      GotoUnless(Float64GreaterThan(var_x.value(), x), &return_x);
-      var_x.Bind(Float64Sub(var_x.value(), one));
-    }
-    Goto(&return_x);
-  }
-
-  Bind(&if_xnotgreaterthanzero);
-  {
-    if (raw_assembler_->machine()->Float64RoundUp().IsSupported()) {
-      var_x.Bind(raw_assembler_->Float64RoundUp(x));
-      Goto(&return_x);
-    } else {
-      // Just return {x} unless its in the range ]-2^52,0[.
-      GotoIf(Float64LessThanOrEqual(x, minus_two_52), &return_x);
-      GotoUnless(Float64LessThan(x, zero), &return_x);
-
-      // Round negated {x} towards -Infinity and return result negated.
-      Node* minus_x = Float64Neg(x);
-      var_x.Bind(Float64Sub(Float64Add(two_52, minus_x), two_52));
-      GotoUnless(Float64GreaterThan(var_x.value(), minus_x), &return_minus_x);
-      var_x.Bind(Float64Sub(var_x.value(), one));
-      Goto(&return_minus_x);
-    }
-  }
-
-  Bind(&return_minus_x);
-  var_x.Bind(Float64Neg(var_x.value()));
-  Goto(&return_x);
-
-  Bind(&return_x);
-  return var_x.value();
-}
-
-Node* CodeStubAssembler::SmiTag(Node* value) {
-  return raw_assembler_->WordShl(value, SmiShiftBitsConstant());
-}
-
-Node* CodeStubAssembler::SmiUntag(Node* value) {
-  return raw_assembler_->WordSar(value, SmiShiftBitsConstant());
-}
-
-Node* CodeStubAssembler::SmiToWord32(Node* value) {
-  Node* result = raw_assembler_->WordSar(value, SmiShiftBitsConstant());
-  if (raw_assembler_->machine()->Is64()) {
-    result = raw_assembler_->TruncateInt64ToInt32(result);
-  }
-  return result;
-}
-
-Node* CodeStubAssembler::SmiToFloat64(Node* value) {
-  return ChangeInt32ToFloat64(SmiUntag(value));
-}
-
-Node* CodeStubAssembler::SmiAdd(Node* a, Node* b) { return IntPtrAdd(a, b); }
-
-Node* CodeStubAssembler::SmiAddWithOverflow(Node* a, Node* b) {
-  return IntPtrAddWithOverflow(a, b);
-}
-
-Node* CodeStubAssembler::SmiSub(Node* a, Node* b) { return IntPtrSub(a, b); }
-
-Node* CodeStubAssembler::SmiSubWithOverflow(Node* a, Node* b) {
-  return IntPtrSubWithOverflow(a, b);
-}
-
-Node* CodeStubAssembler::SmiEqual(Node* a, Node* b) { return WordEqual(a, b); }
-
-Node* CodeStubAssembler::SmiLessThan(Node* a, Node* b) {
-  return IntPtrLessThan(a, b);
-}
-
-Node* CodeStubAssembler::SmiLessThanOrEqual(Node* a, Node* b) {
-  return IntPtrLessThanOrEqual(a, b);
-}
-
-Node* CodeStubAssembler::SmiMin(Node* a, Node* b) {
-  // TODO(bmeurer): Consider using Select once available.
-  Variable min(this, MachineRepresentation::kTagged);
-  Label if_a(this), if_b(this), join(this);
-  BranchIfSmiLessThan(a, b, &if_a, &if_b);
-  Bind(&if_a);
-  min.Bind(a);
-  Goto(&join);
-  Bind(&if_b);
-  min.Bind(b);
-  Goto(&join);
-  Bind(&join);
-  return min.value();
-}
-
-#define DEFINE_CODE_STUB_ASSEMBER_BINARY_OP(name)   \
-  Node* CodeStubAssembler::name(Node* a, Node* b) { \
-    return raw_assembler_->name(a, b);              \
-  }
-CODE_STUB_ASSEMBLER_BINARY_OP_LIST(DEFINE_CODE_STUB_ASSEMBER_BINARY_OP)
-#undef DEFINE_CODE_STUB_ASSEMBER_BINARY_OP
-
-Node* CodeStubAssembler::WordShl(Node* value, int shift) {
-  return raw_assembler_->WordShl(value, IntPtrConstant(shift));
-}
-
-#define DEFINE_CODE_STUB_ASSEMBER_UNARY_OP(name) \
-  Node* CodeStubAssembler::name(Node* a) { return raw_assembler_->name(a); }
-CODE_STUB_ASSEMBLER_UNARY_OP_LIST(DEFINE_CODE_STUB_ASSEMBER_UNARY_OP)
-#undef DEFINE_CODE_STUB_ASSEMBER_UNARY_OP
-
-Node* CodeStubAssembler::WordIsSmi(Node* a) {
-  return WordEqual(raw_assembler_->WordAnd(a, IntPtrConstant(kSmiTagMask)),
-                   IntPtrConstant(0));
-}
-
-Node* CodeStubAssembler::WordIsPositiveSmi(Node* a) {
-  return WordEqual(
-      raw_assembler_->WordAnd(a, IntPtrConstant(kSmiTagMask | kSmiSignMask)),
-      IntPtrConstant(0));
-}
-
-Node* CodeStubAssembler::LoadBufferObject(Node* buffer, int offset,
-                                          MachineType rep) {
-  return raw_assembler_->Load(rep, buffer, IntPtrConstant(offset));
-}
-
-Node* CodeStubAssembler::LoadObjectField(Node* object, int offset,
-                                         MachineType rep) {
-  return raw_assembler_->Load(rep, object,
-                              IntPtrConstant(offset - kHeapObjectTag));
-}
-
-Node* CodeStubAssembler::LoadHeapNumberValue(Node* object) {
-  return Load(MachineType::Float64(), object,
-              IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag));
-}
-
-Node* CodeStubAssembler::StoreHeapNumberValue(Node* object, Node* value) {
-  return StoreNoWriteBarrier(
-      MachineRepresentation::kFloat64, object,
-      IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag), value);
-}
-
-Node* CodeStubAssembler::TruncateHeapNumberValueToWord32(Node* object) {
-  Node* value = LoadHeapNumberValue(object);
-  return raw_assembler_->TruncateFloat64ToInt32(TruncationMode::kJavaScript,
-                                                value);
-}
-
-Node* CodeStubAssembler::LoadMapBitField(Node* map) {
-  return Load(MachineType::Uint8(), map,
-              IntPtrConstant(Map::kBitFieldOffset - kHeapObjectTag));
-}
-
-Node* CodeStubAssembler::LoadMapBitField2(Node* map) {
-  return Load(MachineType::Uint8(), map,
-              IntPtrConstant(Map::kBitField2Offset - kHeapObjectTag));
-}
-
-Node* CodeStubAssembler::LoadMapBitField3(Node* map) {
-  return Load(MachineType::Uint32(), map,
-              IntPtrConstant(Map::kBitField3Offset - kHeapObjectTag));
-}
-
-Node* CodeStubAssembler::LoadMapInstanceType(Node* map) {
-  return Load(MachineType::Uint8(), map,
-              IntPtrConstant(Map::kInstanceTypeOffset - kHeapObjectTag));
-}
-
-Node* CodeStubAssembler::LoadMapDescriptors(Node* map) {
-  return LoadObjectField(map, Map::kDescriptorsOffset);
-}
-
-Node* CodeStubAssembler::LoadNameHash(Node* name) {
-  return Load(MachineType::Uint32(), name,
-              IntPtrConstant(Name::kHashFieldOffset - kHeapObjectTag));
-}
-
-Node* CodeStubAssembler::LoadFixedArrayElementInt32Index(
-    Node* object, Node* int32_index, int additional_offset) {
-  Node* header_size = IntPtrConstant(additional_offset +
-                                     FixedArray::kHeaderSize - kHeapObjectTag);
-  Node* scaled_index = WordShl(int32_index, IntPtrConstant(kPointerSizeLog2));
-  Node* offset = IntPtrAdd(scaled_index, header_size);
-  return Load(MachineType::AnyTagged(), object, offset);
-}
-
-Node* CodeStubAssembler::LoadFixedArrayElementSmiIndex(Node* object,
-                                                       Node* smi_index,
-                                                       int additional_offset) {
-  int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize;
-  Node* header_size = IntPtrConstant(additional_offset +
-                                     FixedArray::kHeaderSize - kHeapObjectTag);
-  Node* scaled_index =
-      (kSmiShiftBits > kPointerSizeLog2)
-          ? WordSar(smi_index, IntPtrConstant(kSmiShiftBits - kPointerSizeLog2))
-          : WordShl(smi_index,
-                    IntPtrConstant(kPointerSizeLog2 - kSmiShiftBits));
-  Node* offset = IntPtrAdd(scaled_index, header_size);
-  return Load(MachineType::AnyTagged(), object, offset);
-}
-
-Node* CodeStubAssembler::LoadFixedArrayElementConstantIndex(Node* object,
-                                                            int index) {
-  Node* offset = IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag +
-                                index * kPointerSize);
-  return raw_assembler_->Load(MachineType::AnyTagged(), object, offset);
-}
-
-Node* CodeStubAssembler::StoreFixedArrayElementNoWriteBarrier(Node* object,
-                                                              Node* index,
-                                                              Node* value) {
-  Node* offset =
-      IntPtrAdd(WordShl(index, IntPtrConstant(kPointerSizeLog2)),
-                IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag));
-  return StoreNoWriteBarrier(MachineRepresentation::kTagged, object, offset,
-                             value);
-}
-
-Node* CodeStubAssembler::LoadRoot(Heap::RootListIndex root_index) {
-  if (isolate()->heap()->RootCanBeTreatedAsConstant(root_index)) {
-    Handle<Object> root = isolate()->heap()->root_handle(root_index);
-    if (root->IsSmi()) {
-      return SmiConstant(Smi::cast(*root));
-    } else {
-      return HeapConstant(Handle<HeapObject>::cast(root));
-    }
-  }
-
-  compiler::Node* roots_array_start =
-      ExternalConstant(ExternalReference::roots_array_start(isolate()));
-  USE(roots_array_start);
-
-  // TODO(danno): Implement thee root-access case where the root is not constant
-  // and must be loaded from the root array.
-  UNIMPLEMENTED();
-  return nullptr;
-}
-
-Node* CodeStubAssembler::AllocateRawUnaligned(Node* size_in_bytes,
-                                              AllocationFlags flags,
-                                              Node* top_address,
-                                              Node* limit_address) {
-  Node* top = Load(MachineType::Pointer(), top_address);
-  Node* limit = Load(MachineType::Pointer(), limit_address);
-
-  // If there's not enough space, call the runtime.
-  RawMachineLabel runtime_call(RawMachineLabel::kDeferred), no_runtime_call,
-      merge_runtime;
-  raw_assembler_->Branch(
-      raw_assembler_->IntPtrLessThan(IntPtrSub(limit, top), size_in_bytes),
-      &runtime_call, &no_runtime_call);
-
-  raw_assembler_->Bind(&runtime_call);
-  // AllocateInTargetSpace does not use the context.
-  Node* context = IntPtrConstant(0);
-  Node* runtime_flags = SmiTag(Int32Constant(
-      AllocateDoubleAlignFlag::encode(false) |
-      AllocateTargetSpace::encode(flags & kPretenured
-                                      ? AllocationSpace::OLD_SPACE
-                                      : AllocationSpace::NEW_SPACE)));
-  Node* runtime_result = CallRuntime(Runtime::kAllocateInTargetSpace, context,
-                                     SmiTag(size_in_bytes), runtime_flags);
-  raw_assembler_->Goto(&merge_runtime);
-
-  // When there is enough space, return `top' and bump it up.
-  raw_assembler_->Bind(&no_runtime_call);
-  Node* no_runtime_result = top;
-  StoreNoWriteBarrier(MachineType::PointerRepresentation(), top_address,
-                      IntPtrAdd(top, size_in_bytes));
-  no_runtime_result =
-      IntPtrAdd(no_runtime_result, IntPtrConstant(kHeapObjectTag));
-  raw_assembler_->Goto(&merge_runtime);
-
-  raw_assembler_->Bind(&merge_runtime);
-  return raw_assembler_->Phi(MachineType::PointerRepresentation(),
-                             runtime_result, no_runtime_result);
-}
-
-Node* CodeStubAssembler::AllocateRawAligned(Node* size_in_bytes,
-                                            AllocationFlags flags,
-                                            Node* top_address,
-                                            Node* limit_address) {
-  Node* top = Load(MachineType::Pointer(), top_address);
-  Node* limit = Load(MachineType::Pointer(), limit_address);
-  Node* adjusted_size = size_in_bytes;
-  if (flags & kDoubleAlignment) {
-    // TODO(epertoso): Simd128 alignment.
-    RawMachineLabel aligned, not_aligned, merge;
-    raw_assembler_->Branch(WordAnd(top, IntPtrConstant(kDoubleAlignmentMask)),
-                           &not_aligned, &aligned);
-
-    raw_assembler_->Bind(&not_aligned);
-    Node* not_aligned_size =
-        IntPtrAdd(size_in_bytes, IntPtrConstant(kPointerSize));
-    raw_assembler_->Goto(&merge);
-
-    raw_assembler_->Bind(&aligned);
-    raw_assembler_->Goto(&merge);
-
-    raw_assembler_->Bind(&merge);
-    adjusted_size = raw_assembler_->Phi(MachineType::PointerRepresentation(),
-                                        not_aligned_size, adjusted_size);
-  }
-
-  Node* address = AllocateRawUnaligned(adjusted_size, kNone, top, limit);
-
-  RawMachineLabel needs_filler, doesnt_need_filler, merge_address;
-  raw_assembler_->Branch(
-      raw_assembler_->IntPtrEqual(adjusted_size, size_in_bytes),
-      &doesnt_need_filler, &needs_filler);
-
-  raw_assembler_->Bind(&needs_filler);
-  // Store a filler and increase the address by kPointerSize.
-  // TODO(epertoso): this code assumes that we only align to kDoubleSize. Change
-  // it when Simd128 alignment is supported.
-  StoreNoWriteBarrier(MachineType::PointerRepresentation(), top,
-                      LoadRoot(Heap::kOnePointerFillerMapRootIndex));
-  Node* address_with_filler = IntPtrAdd(address, IntPtrConstant(kPointerSize));
-  raw_assembler_->Goto(&merge_address);
-
-  raw_assembler_->Bind(&doesnt_need_filler);
-  Node* address_without_filler = address;
-  raw_assembler_->Goto(&merge_address);
-
-  raw_assembler_->Bind(&merge_address);
-  address = raw_assembler_->Phi(MachineType::PointerRepresentation(),
-                                address_with_filler, address_without_filler);
-  // Update the top.
-  StoreNoWriteBarrier(MachineType::PointerRepresentation(), top_address,
-                      IntPtrAdd(top, adjusted_size));
-  return address;
-}
-
-Node* CodeStubAssembler::Allocate(int size_in_bytes, AllocationFlags flags) {
-  bool const new_space = !(flags & kPretenured);
-  Node* top_address = ExternalConstant(
-      new_space
-          ? ExternalReference::new_space_allocation_top_address(isolate())
-          : ExternalReference::old_space_allocation_top_address(isolate()));
-  Node* limit_address = ExternalConstant(
-      new_space
-          ? ExternalReference::new_space_allocation_limit_address(isolate())
-          : ExternalReference::old_space_allocation_limit_address(isolate()));
-
-#ifdef V8_HOST_ARCH_32_BIT
-  if (flags & kDoubleAlignment) {
-    return AllocateRawAligned(IntPtrConstant(size_in_bytes), flags, top_address,
-                              limit_address);
-  }
-#endif
-
-  return AllocateRawUnaligned(IntPtrConstant(size_in_bytes), flags, top_address,
-                              limit_address);
-}
-
-Node* CodeStubAssembler::AllocateHeapNumber() {
-  Node* result = Allocate(HeapNumber::kSize, kNone);
-  StoreMapNoWriteBarrier(result, HeapNumberMapConstant());
-  return result;
-}
-
-Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value) {
-  Node* result = AllocateHeapNumber();
-  StoreHeapNumberValue(result, value);
-  return result;
-}
-
-Node* CodeStubAssembler::Load(MachineType rep, Node* base) {
-  return raw_assembler_->Load(rep, base);
-}
-
-Node* CodeStubAssembler::Load(MachineType rep, Node* base, Node* index) {
-  return raw_assembler_->Load(rep, base, index);
-}
-
-Node* CodeStubAssembler::Store(MachineRepresentation rep, Node* base,
-                               Node* value) {
-  return raw_assembler_->Store(rep, base, value, kFullWriteBarrier);
-}
-
-Node* CodeStubAssembler::Store(MachineRepresentation rep, Node* base,
-                               Node* index, Node* value) {
-  return raw_assembler_->Store(rep, base, index, value, kFullWriteBarrier);
-}
-
-Node* CodeStubAssembler::StoreNoWriteBarrier(MachineRepresentation rep,
-                                             Node* base, Node* value) {
-  return raw_assembler_->Store(rep, base, value, kNoWriteBarrier);
-}
-
-Node* CodeStubAssembler::StoreNoWriteBarrier(MachineRepresentation rep,
-                                             Node* base, Node* index,
-                                             Node* value) {
-  return raw_assembler_->Store(rep, base, index, value, kNoWriteBarrier);
-}
-
-Node* CodeStubAssembler::Projection(int index, Node* value) {
-  return raw_assembler_->Projection(index, value);
-}
-
-Node* CodeStubAssembler::LoadMap(Node* object) {
-  return LoadObjectField(object, HeapObject::kMapOffset);
-}
-
-Node* CodeStubAssembler::StoreMapNoWriteBarrier(Node* object, Node* map) {
-  return StoreNoWriteBarrier(
-      MachineRepresentation::kTagged, object,
-      IntPtrConstant(HeapNumber::kMapOffset - kHeapObjectTag), map);
-}
-
-Node* CodeStubAssembler::LoadInstanceType(Node* object) {
-  return LoadMapInstanceType(LoadMap(object));
-}
-
-Node* CodeStubAssembler::LoadElements(Node* object) {
-  return LoadObjectField(object, JSObject::kElementsOffset);
-}
-
-Node* CodeStubAssembler::LoadFixedArrayBaseLength(Node* array) {
-  return LoadObjectField(array, FixedArrayBase::kLengthOffset);
-}
-
-Node* CodeStubAssembler::BitFieldDecode(Node* word32, uint32_t shift,
-                                        uint32_t mask) {
-  return raw_assembler_->Word32Shr(
-      raw_assembler_->Word32And(word32, raw_assembler_->Int32Constant(mask)),
-      raw_assembler_->Int32Constant(shift));
-}
-
-Node* CodeStubAssembler::ChangeFloat64ToTagged(Node* value) {
-  Node* value32 = raw_assembler_->TruncateFloat64ToInt32(
-      TruncationMode::kRoundToZero, value);
-  Node* value64 = ChangeInt32ToFloat64(value32);
-
-  Label if_valueisint32(this), if_valueisheapnumber(this), if_join(this);
-
-  Label if_valueisequal(this), if_valueisnotequal(this);
-  Branch(Float64Equal(value, value64), &if_valueisequal, &if_valueisnotequal);
-  Bind(&if_valueisequal);
-  {
-    Label if_valueiszero(this), if_valueisnotzero(this);
-    Branch(Float64Equal(value, Float64Constant(0.0)), &if_valueiszero,
-           &if_valueisnotzero);
-
-    Bind(&if_valueiszero);
-    BranchIfInt32LessThan(raw_assembler_->Float64ExtractHighWord32(value),
-                          Int32Constant(0), &if_valueisheapnumber,
-                          &if_valueisint32);
-
-    Bind(&if_valueisnotzero);
-    Goto(&if_valueisint32);
-  }
-  Bind(&if_valueisnotequal);
-  Goto(&if_valueisheapnumber);
-
-  Variable var_result(this, MachineRepresentation::kTagged);
-  Bind(&if_valueisint32);
-  {
-    if (raw_assembler_->machine()->Is64()) {
-      Node* result = SmiTag(ChangeInt32ToInt64(value32));
-      var_result.Bind(result);
-      Goto(&if_join);
-    } else {
-      Node* pair = Int32AddWithOverflow(value32, value32);
-      Node* overflow = Projection(1, pair);
-      Label if_overflow(this, Label::kDeferred), if_notoverflow(this);
-      Branch(overflow, &if_overflow, &if_notoverflow);
-      Bind(&if_overflow);
-      Goto(&if_valueisheapnumber);
-      Bind(&if_notoverflow);
-      {
-        Node* result = Projection(0, pair);
-        var_result.Bind(result);
-        Goto(&if_join);
-      }
-    }
-  }
-  Bind(&if_valueisheapnumber);
-  {
-    Node* result = AllocateHeapNumberWithValue(value);
-    var_result.Bind(result);
-    Goto(&if_join);
-  }
-  Bind(&if_join);
-  return var_result.value();
-}
-
-Node* CodeStubAssembler::ChangeInt32ToTagged(Node* value) {
-  if (raw_assembler_->machine()->Is64()) {
-    return SmiTag(ChangeInt32ToInt64(value));
-  }
-  Variable var_result(this, MachineRepresentation::kTagged);
-  Node* pair = Int32AddWithOverflow(value, value);
-  Node* overflow = Projection(1, pair);
-  Label if_overflow(this, Label::kDeferred), if_notoverflow(this),
-      if_join(this);
-  Branch(overflow, &if_overflow, &if_notoverflow);
-  Bind(&if_overflow);
-  {
-    Node* value64 = ChangeInt32ToFloat64(value);
-    Node* result = AllocateHeapNumberWithValue(value64);
-    var_result.Bind(result);
-  }
-  Goto(&if_join);
-  Bind(&if_notoverflow);
-  {
-    Node* result = Projection(0, pair);
-    var_result.Bind(result);
-  }
-  Goto(&if_join);
-  Bind(&if_join);
-  return var_result.value();
-}
-
-Node* CodeStubAssembler::TruncateTaggedToFloat64(Node* context, Node* value) {
-  // We might need to loop once due to ToNumber conversion.
-  Variable var_value(this, MachineRepresentation::kTagged),
-      var_result(this, MachineRepresentation::kFloat64);
-  Label loop(this, &var_value), done_loop(this, &var_result);
-  var_value.Bind(value);
-  Goto(&loop);
-  Bind(&loop);
-  {
-    // Load the current {value}.
-    value = var_value.value();
-
-    // Check if the {value} is a Smi or a HeapObject.
-    Label if_valueissmi(this), if_valueisnotsmi(this);
-    Branch(WordIsSmi(value), &if_valueissmi, &if_valueisnotsmi);
-
-    Bind(&if_valueissmi);
-    {
-      // Convert the Smi {value}.
-      var_result.Bind(SmiToFloat64(value));
-      Goto(&done_loop);
-    }
-
-    Bind(&if_valueisnotsmi);
-    {
-      // Check if {value} is a HeapNumber.
-      Label if_valueisheapnumber(this),
-          if_valueisnotheapnumber(this, Label::kDeferred);
-      Branch(WordEqual(LoadMap(value), HeapNumberMapConstant()),
-             &if_valueisheapnumber, &if_valueisnotheapnumber);
-
-      Bind(&if_valueisheapnumber);
-      {
-        // Load the floating point value.
-        var_result.Bind(LoadHeapNumberValue(value));
-        Goto(&done_loop);
-      }
-
-      Bind(&if_valueisnotheapnumber);
-      {
-        // Convert the {value} to a Number first.
-        Callable callable = CodeFactory::NonNumberToNumber(isolate());
-        var_value.Bind(CallStub(callable, context, value));
-        Goto(&loop);
-      }
-    }
-  }
-  Bind(&done_loop);
-  return var_result.value();
-}
-
-Node* CodeStubAssembler::TruncateTaggedToWord32(Node* context, Node* value) {
-  // We might need to loop once due to ToNumber conversion.
-  Variable var_value(this, MachineRepresentation::kTagged),
-      var_result(this, MachineRepresentation::kWord32);
-  Label loop(this, &var_value), done_loop(this, &var_result);
-  var_value.Bind(value);
-  Goto(&loop);
-  Bind(&loop);
-  {
-    // Load the current {value}.
-    value = var_value.value();
-
-    // Check if the {value} is a Smi or a HeapObject.
-    Label if_valueissmi(this), if_valueisnotsmi(this);
-    Branch(WordIsSmi(value), &if_valueissmi, &if_valueisnotsmi);
-
-    Bind(&if_valueissmi);
-    {
-      // Convert the Smi {value}.
-      var_result.Bind(SmiToWord32(value));
-      Goto(&done_loop);
-    }
-
-    Bind(&if_valueisnotsmi);
-    {
-      // Check if {value} is a HeapNumber.
-      Label if_valueisheapnumber(this),
-          if_valueisnotheapnumber(this, Label::kDeferred);
-      Branch(WordEqual(LoadMap(value), HeapNumberMapConstant()),
-             &if_valueisheapnumber, &if_valueisnotheapnumber);
-
-      Bind(&if_valueisheapnumber);
-      {
-        // Truncate the floating point value.
-        var_result.Bind(TruncateHeapNumberValueToWord32(value));
-        Goto(&done_loop);
-      }
-
-      Bind(&if_valueisnotheapnumber);
-      {
-        // Convert the {value} to a Number first.
-        Callable callable = CodeFactory::NonNumberToNumber(isolate());
-        var_value.Bind(CallStub(callable, context, value));
-        Goto(&loop);
-      }
-    }
-  }
-  Bind(&done_loop);
-  return var_result.value();
-}
-
-void CodeStubAssembler::BranchIf(Node* condition, Label* if_true,
-                                 Label* if_false) {
-  Label if_condition_is_true(this), if_condition_is_false(this);
-  Branch(condition, &if_condition_is_true, &if_condition_is_false);
-  Bind(&if_condition_is_true);
-  Goto(if_true);
-  Bind(&if_condition_is_false);
-  Goto(if_false);
-}
-
-Node* CodeStubAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
-                               Node** args) {
-  CallPrologue();
-  Node* return_value = raw_assembler_->CallN(descriptor, code_target, args);
-  CallEpilogue();
-  return return_value;
-}
-
-
-Node* CodeStubAssembler::TailCallN(CallDescriptor* descriptor,
-                                   Node* code_target, Node** args) {
-  return raw_assembler_->TailCallN(descriptor, code_target, args);
-}
-
-Node* CodeStubAssembler::CallRuntime(Runtime::FunctionId function_id,
-                                     Node* context) {
-  CallPrologue();
-  Node* return_value = raw_assembler_->CallRuntime0(function_id, context);
-  CallEpilogue();
-  return return_value;
-}
-
-Node* CodeStubAssembler::CallRuntime(Runtime::FunctionId function_id,
-                                     Node* context, Node* arg1) {
-  CallPrologue();
-  Node* return_value = raw_assembler_->CallRuntime1(function_id, arg1, context);
-  CallEpilogue();
-  return return_value;
-}
-
-Node* CodeStubAssembler::CallRuntime(Runtime::FunctionId function_id,
-                                     Node* context, Node* arg1, Node* arg2) {
-  CallPrologue();
-  Node* return_value =
-      raw_assembler_->CallRuntime2(function_id, arg1, arg2, context);
-  CallEpilogue();
-  return return_value;
-}
-
-Node* CodeStubAssembler::CallRuntime(Runtime::FunctionId function_id,
-                                     Node* context, Node* arg1, Node* arg2,
-                                     Node* arg3) {
-  CallPrologue();
-  Node* return_value =
-      raw_assembler_->CallRuntime3(function_id, arg1, arg2, arg3, context);
-  CallEpilogue();
-  return return_value;
-}
-
-Node* CodeStubAssembler::CallRuntime(Runtime::FunctionId function_id,
-                                     Node* context, Node* arg1, Node* arg2,
-                                     Node* arg3, Node* arg4) {
-  CallPrologue();
-  Node* return_value = raw_assembler_->CallRuntime4(function_id, arg1, arg2,
-                                                    arg3, arg4, context);
-  CallEpilogue();
-  return return_value;
-}
-
-Node* CodeStubAssembler::TailCallRuntime(Runtime::FunctionId function_id,
-                                         Node* context) {
-  return raw_assembler_->TailCallRuntime0(function_id, context);
-}
-
-Node* CodeStubAssembler::TailCallRuntime(Runtime::FunctionId function_id,
-                                         Node* context, Node* arg1) {
-  return raw_assembler_->TailCallRuntime1(function_id, arg1, context);
-}
-
-Node* CodeStubAssembler::TailCallRuntime(Runtime::FunctionId function_id,
-                                         Node* context, Node* arg1,
-                                         Node* arg2) {
-  return raw_assembler_->TailCallRuntime2(function_id, arg1, arg2, context);
-}
-
-Node* CodeStubAssembler::TailCallRuntime(Runtime::FunctionId function_id,
-                                         Node* context, Node* arg1, Node* arg2,
-                                         Node* arg3) {
-  return raw_assembler_->TailCallRuntime3(function_id, arg1, arg2, arg3,
-                                          context);
-}
-
-Node* CodeStubAssembler::TailCallRuntime(Runtime::FunctionId function_id,
-                                         Node* context, Node* arg1, Node* arg2,
-                                         Node* arg3, Node* arg4) {
-  return raw_assembler_->TailCallRuntime4(function_id, arg1, arg2, arg3, arg4,
-                                          context);
-}
-
-Node* CodeStubAssembler::CallStub(Callable const& callable, Node* context,
-                                  Node* arg1, size_t result_size) {
-  Node* target = HeapConstant(callable.code());
-  return CallStub(callable.descriptor(), target, context, arg1, result_size);
-}
-
-Node* CodeStubAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
-                                  Node* target, Node* context, Node* arg1,
-                                  size_t result_size) {
-  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
-      isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
-      CallDescriptor::kNoFlags, Operator::kNoProperties,
-      MachineType::AnyTagged(), result_size);
-
-  Node** args = zone()->NewArray<Node*>(2);
-  args[0] = arg1;
-  args[1] = context;
-
-  return CallN(call_descriptor, target, args);
-}
-
-Node* CodeStubAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
-                                  Node* target, Node* context, Node* arg1,
-                                  Node* arg2, size_t result_size) {
-  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
-      isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
-      CallDescriptor::kNoFlags, Operator::kNoProperties,
-      MachineType::AnyTagged(), result_size);
-
-  Node** args = zone()->NewArray<Node*>(3);
-  args[0] = arg1;
-  args[1] = arg2;
-  args[2] = context;
-
-  return CallN(call_descriptor, target, args);
-}
-
-Node* CodeStubAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
-                                  Node* target, Node* context, Node* arg1,
-                                  Node* arg2, Node* arg3, size_t result_size) {
-  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
-      isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
-      CallDescriptor::kNoFlags, Operator::kNoProperties,
-      MachineType::AnyTagged(), result_size);
-
-  Node** args = zone()->NewArray<Node*>(4);
-  args[0] = arg1;
-  args[1] = arg2;
-  args[2] = arg3;
-  args[3] = context;
-
-  return CallN(call_descriptor, target, args);
-}
-
-Node* CodeStubAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
-                                  Node* target, Node* context, Node* arg1,
-                                  Node* arg2, Node* arg3, Node* arg4,
-                                  size_t result_size) {
-  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
-      isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
-      CallDescriptor::kNoFlags, Operator::kNoProperties,
-      MachineType::AnyTagged(), result_size);
-
-  Node** args = zone()->NewArray<Node*>(5);
-  args[0] = arg1;
-  args[1] = arg2;
-  args[2] = arg3;
-  args[3] = arg4;
-  args[4] = context;
-
-  return CallN(call_descriptor, target, args);
-}
-
-Node* CodeStubAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
-                                  Node* target, Node* context, Node* arg1,
-                                  Node* arg2, Node* arg3, Node* arg4,
-                                  Node* arg5, size_t result_size) {
-  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
-      isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
-      CallDescriptor::kNoFlags, Operator::kNoProperties,
-      MachineType::AnyTagged(), result_size);
-
-  Node** args = zone()->NewArray<Node*>(6);
-  args[0] = arg1;
-  args[1] = arg2;
-  args[2] = arg3;
-  args[3] = arg4;
-  args[4] = arg5;
-  args[5] = context;
-
-  return CallN(call_descriptor, target, args);
-}
-
-Node* CodeStubAssembler::TailCallStub(Callable const& callable, Node* context,
-                                      Node* arg1, Node* arg2,
-                                      size_t result_size) {
-  Node* target = HeapConstant(callable.code());
-  return TailCallStub(callable.descriptor(), target, context, arg1, arg2,
-                      result_size);
-}
-
-Node* CodeStubAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
-                                      Node* target, Node* context, Node* arg1,
-                                      Node* arg2, size_t result_size) {
-  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
-      isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
-      CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
-      MachineType::AnyTagged(), result_size);
-
-  Node** args = zone()->NewArray<Node*>(3);
-  args[0] = arg1;
-  args[1] = arg2;
-  args[2] = context;
-
-  return raw_assembler_->TailCallN(call_descriptor, target, args);
-}
-
-Node* CodeStubAssembler::TailCall(
-    const CallInterfaceDescriptor& interface_descriptor, Node* code_target,
-    Node** args, size_t result_size) {
-  CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
-      isolate(), zone(), interface_descriptor,
-      interface_descriptor.GetStackParameterCount(),
-      CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
-      MachineType::AnyTagged(), result_size);
-  return raw_assembler_->TailCallN(descriptor, code_target, args);
-}
-
-void CodeStubAssembler::Goto(CodeStubAssembler::Label* label) {
-  label->MergeVariables();
-  raw_assembler_->Goto(label->label_);
-}
-
-void CodeStubAssembler::GotoIf(Node* condition, Label* true_label) {
-  Label false_label(this);
-  Branch(condition, true_label, &false_label);
-  Bind(&false_label);
-}
-
-void CodeStubAssembler::GotoUnless(Node* condition, Label* false_label) {
-  Label true_label(this);
-  Branch(condition, &true_label, false_label);
-  Bind(&true_label);
-}
-
-void CodeStubAssembler::Branch(Node* condition,
-                               CodeStubAssembler::Label* true_label,
-                               CodeStubAssembler::Label* false_label) {
-  true_label->MergeVariables();
-  false_label->MergeVariables();
-  return raw_assembler_->Branch(condition, true_label->label_,
-                                false_label->label_);
-}
-
-void CodeStubAssembler::Switch(Node* index, Label* default_label,
-                               int32_t* case_values, Label** case_labels,
-                               size_t case_count) {
-  RawMachineLabel** labels =
-      new (zone()->New(sizeof(RawMachineLabel*) * case_count))
-          RawMachineLabel*[case_count];
-  for (size_t i = 0; i < case_count; ++i) {
-    labels[i] = case_labels[i]->label_;
-    case_labels[i]->MergeVariables();
-    default_label->MergeVariables();
-  }
-  return raw_assembler_->Switch(index, default_label->label_, case_values,
-                                labels, case_count);
-}
-
-// RawMachineAssembler delegate helpers:
-Isolate* CodeStubAssembler::isolate() const {
-  return raw_assembler_->isolate();
-}
-
-Factory* CodeStubAssembler::factory() const { return isolate()->factory(); }
-
-Graph* CodeStubAssembler::graph() const { return raw_assembler_->graph(); }
-
-Zone* CodeStubAssembler::zone() const { return raw_assembler_->zone(); }
-
-// The core implementation of Variable is stored through an indirection so
-// that it can outlive the often block-scoped Variable declarations. This is
-// needed to ensure that variable binding and merging through phis can
-// properly be verified.
-class CodeStubAssembler::Variable::Impl : public ZoneObject {
- public:
-  explicit Impl(MachineRepresentation rep) : value_(nullptr), rep_(rep) {}
-  Node* value_;
-  MachineRepresentation rep_;
-};
-
-CodeStubAssembler::Variable::Variable(CodeStubAssembler* assembler,
-                                      MachineRepresentation rep)
-    : impl_(new (assembler->zone()) Impl(rep)) {
-  assembler->variables_.push_back(impl_);
-}
-
-void CodeStubAssembler::Variable::Bind(Node* value) { impl_->value_ = value; }
-
-Node* CodeStubAssembler::Variable::value() const {
-  DCHECK_NOT_NULL(impl_->value_);
-  return impl_->value_;
-}
-
-MachineRepresentation CodeStubAssembler::Variable::rep() const {
-  return impl_->rep_;
-}
-
-bool CodeStubAssembler::Variable::IsBound() const {
-  return impl_->value_ != nullptr;
-}
-
-CodeStubAssembler::Label::Label(CodeStubAssembler* assembler,
-                                int merged_value_count,
-                                CodeStubAssembler::Variable** merged_variables,
-                                CodeStubAssembler::Label::Type type)
-    : bound_(false), merge_count_(0), assembler_(assembler), label_(nullptr) {
-  void* buffer = assembler->zone()->New(sizeof(RawMachineLabel));
-  label_ = new (buffer)
-      RawMachineLabel(type == kDeferred ? RawMachineLabel::kDeferred
-                                        : RawMachineLabel::kNonDeferred);
-  for (int i = 0; i < merged_value_count; ++i) {
-    variable_phis_[merged_variables[i]->impl_] = nullptr;
-  }
-}
-
-void CodeStubAssembler::Label::MergeVariables() {
-  ++merge_count_;
-  for (auto var : assembler_->variables_) {
-    size_t count = 0;
-    Node* node = var->value_;
-    if (node != nullptr) {
-      auto i = variable_merges_.find(var);
-      if (i != variable_merges_.end()) {
-        i->second.push_back(node);
-        count = i->second.size();
-      } else {
-        count = 1;
-        variable_merges_[var] = std::vector<Node*>(1, node);
-      }
-    }
-    // If the following asserts, then you've jumped to a label without a bound
-    // variable along that path that expects to merge its value into a phi.
-    DCHECK(variable_phis_.find(var) == variable_phis_.end() ||
-           count == merge_count_);
-    USE(count);
-
-    // If the label is already bound, we already know the set of variables to
-    // merge and phi nodes have already been created.
-    if (bound_) {
-      auto phi = variable_phis_.find(var);
-      if (phi != variable_phis_.end()) {
-        DCHECK_NOT_NULL(phi->second);
-        assembler_->raw_assembler_->AppendPhiInput(phi->second, node);
-      } else {
-        auto i = variable_merges_.find(var);
-        if (i != variable_merges_.end()) {
-          // If the following assert fires, then you've declared a variable that
-          // has the same bound value along all paths up until the point you
-          // bound this label, but then later merged a path with a new value for
-          // the variable after the label bind (it's not possible to add phis to
-          // the bound label after the fact, just make sure to list the variable
-          // in the label's constructor's list of merged variables).
-          DCHECK(find_if(i->second.begin(), i->second.end(),
-                         [node](Node* e) -> bool { return node != e; }) ==
-                 i->second.end());
-        }
-      }
-    }
-  }
-}
-
-void CodeStubAssembler::Label::Bind() {
-  DCHECK(!bound_);
-  assembler_->raw_assembler_->Bind(label_);
-
-  // Make sure that all variables that have changed along any path up to this
-  // point are marked as merge variables.
-  for (auto var : assembler_->variables_) {
-    Node* shared_value = nullptr;
-    auto i = variable_merges_.find(var);
-    if (i != variable_merges_.end()) {
-      for (auto value : i->second) {
-        DCHECK(value != nullptr);
-        if (value != shared_value) {
-          if (shared_value == nullptr) {
-            shared_value = value;
-          } else {
-            variable_phis_[var] = nullptr;
-          }
-        }
-      }
-    }
-  }
-
-  for (auto var : variable_phis_) {
-    CodeStubAssembler::Variable::Impl* var_impl = var.first;
-    auto i = variable_merges_.find(var_impl);
-    // If the following assert fires, then a variable that has been marked as
-    // being merged at the label--either by explicitly marking it so in the
-    // label constructor or by having seen different bound values at branches
-    // into the label--doesn't have a bound value along all of the paths that
-    // have been merged into the label up to this point.
-    DCHECK(i != variable_merges_.end() && i->second.size() == merge_count_);
-    Node* phi = assembler_->raw_assembler_->Phi(
-        var.first->rep_, static_cast<int>(merge_count_), &(i->second[0]));
-    variable_phis_[var_impl] = phi;
-  }
-
-  // Bind all variables to a merge phi, the common value along all paths or
-  // null.
-  for (auto var : assembler_->variables_) {
-    auto i = variable_phis_.find(var);
-    if (i != variable_phis_.end()) {
-      var->value_ = i->second;
-    } else {
-      auto j = variable_merges_.find(var);
-      if (j != variable_merges_.end() && j->second.size() == merge_count_) {
-        var->value_ = j->second.back();
-      } else {
-        var->value_ = nullptr;
-      }
-    }
-  }
-
-  bound_ = true;
-}
-
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
diff --git a/src/compiler/code-stub-assembler.h b/src/compiler/code-stub-assembler.h
deleted file mode 100644
index 9fcb890..0000000
--- a/src/compiler/code-stub-assembler.h
+++ /dev/null
@@ -1,475 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_COMPILER_CODE_STUB_ASSEMBLER_H_
-#define V8_COMPILER_CODE_STUB_ASSEMBLER_H_
-
-#include <map>
-
-// Clients of this interface shouldn't depend on lots of compiler internals.
-// Do not include anything from src/compiler here!
-#include "src/allocation.h"
-#include "src/builtins.h"
-#include "src/heap/heap.h"
-#include "src/machine-type.h"
-#include "src/runtime/runtime.h"
-#include "src/zone-containers.h"
-
-namespace v8 {
-namespace internal {
-
-class Callable;
-class CallInterfaceDescriptor;
-class Isolate;
-class Factory;
-class Zone;
-
-namespace compiler {
-
-class CallDescriptor;
-class Graph;
-class Node;
-class Operator;
-class RawMachineAssembler;
-class RawMachineLabel;
-class Schedule;
-
-#define CODE_STUB_ASSEMBLER_COMPARE_BINARY_OP_LIST(V) \
-  V(Float32Equal)                                     \
-  V(Float32LessThan)                                  \
-  V(Float32LessThanOrEqual)                           \
-  V(Float32GreaterThan)                               \
-  V(Float32GreaterThanOrEqual)                        \
-  V(Float64Equal)                                     \
-  V(Float64LessThan)                                  \
-  V(Float64LessThanOrEqual)                           \
-  V(Float64GreaterThan)                               \
-  V(Float64GreaterThanOrEqual)                        \
-  V(Int32GreaterThan)                                 \
-  V(Int32GreaterThanOrEqual)                          \
-  V(Int32LessThan)                                    \
-  V(Int32LessThanOrEqual)                             \
-  V(IntPtrLessThan)                                   \
-  V(IntPtrLessThanOrEqual)                            \
-  V(Uint32LessThan)                                   \
-  V(UintPtrGreaterThanOrEqual)                        \
-  V(WordEqual)                                        \
-  V(WordNotEqual)                                     \
-  V(Word32Equal)                                      \
-  V(Word32NotEqual)                                   \
-  V(Word64Equal)                                      \
-  V(Word64NotEqual)
-
-#define CODE_STUB_ASSEMBLER_BINARY_OP_LIST(V)   \
-  CODE_STUB_ASSEMBLER_COMPARE_BINARY_OP_LIST(V) \
-  V(Float64Add)                                 \
-  V(Float64Sub)                                 \
-  V(Float64InsertLowWord32)                     \
-  V(Float64InsertHighWord32)                    \
-  V(IntPtrAdd)                                  \
-  V(IntPtrAddWithOverflow)                      \
-  V(IntPtrSub)                                  \
-  V(IntPtrSubWithOverflow)                      \
-  V(Int32Add)                                   \
-  V(Int32AddWithOverflow)                       \
-  V(Int32Sub)                                   \
-  V(Int32Mul)                                   \
-  V(WordOr)                                     \
-  V(WordAnd)                                    \
-  V(WordXor)                                    \
-  V(WordShl)                                    \
-  V(WordShr)                                    \
-  V(WordSar)                                    \
-  V(WordRor)                                    \
-  V(Word32Or)                                   \
-  V(Word32And)                                  \
-  V(Word32Xor)                                  \
-  V(Word32Shl)                                  \
-  V(Word32Shr)                                  \
-  V(Word32Sar)                                  \
-  V(Word32Ror)                                  \
-  V(Word64Or)                                   \
-  V(Word64And)                                  \
-  V(Word64Xor)                                  \
-  V(Word64Shr)                                  \
-  V(Word64Sar)                                  \
-  V(Word64Ror)
-
-#define CODE_STUB_ASSEMBLER_UNARY_OP_LIST(V) \
-  V(Float64Neg)                              \
-  V(Float64Sqrt)                             \
-  V(ChangeFloat64ToUint32)                   \
-  V(ChangeInt32ToFloat64)                    \
-  V(ChangeInt32ToInt64)                      \
-  V(ChangeUint32ToFloat64)                   \
-  V(ChangeUint32ToUint64)                    \
-  V(Word32Clz)
-
-class CodeStubAssembler {
- public:
-  // Create with CallStub linkage.
-  // |result_size| specifies the number of results returned by the stub.
-  // TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
-  CodeStubAssembler(Isolate* isolate, Zone* zone,
-                    const CallInterfaceDescriptor& descriptor,
-                    Code::Flags flags, const char* name,
-                    size_t result_size = 1);
-
-  // Create with JSCall linkage.
-  CodeStubAssembler(Isolate* isolate, Zone* zone, int parameter_count,
-                    Code::Flags flags, const char* name);
-
-  virtual ~CodeStubAssembler();
-
-  Handle<Code> GenerateCode();
-
-  class Label;
-  class Variable {
-   public:
-    explicit Variable(CodeStubAssembler* assembler, MachineRepresentation rep);
-    void Bind(Node* value);
-    Node* value() const;
-    MachineRepresentation rep() const;
-    bool IsBound() const;
-
-   private:
-    friend class CodeStubAssembler;
-    class Impl;
-    Impl* impl_;
-  };
-
-  enum AllocationFlag : uint8_t {
-    kNone = 0,
-    kDoubleAlignment = 1,
-    kPretenured = 1 << 1
-  };
-
-  typedef base::Flags<AllocationFlag> AllocationFlags;
-
-  // ===========================================================================
-  // Base Assembler
-  // ===========================================================================
-
-  // Constants.
-  Node* Int32Constant(int value);
-  Node* IntPtrConstant(intptr_t value);
-  Node* NumberConstant(double value);
-  Node* SmiConstant(Smi* value);
-  Node* HeapConstant(Handle<HeapObject> object);
-  Node* BooleanConstant(bool value);
-  Node* ExternalConstant(ExternalReference address);
-  Node* Float64Constant(double value);
-  Node* BooleanMapConstant();
-  Node* HeapNumberMapConstant();
-  Node* NullConstant();
-  Node* UndefinedConstant();
-
-  Node* Parameter(int value);
-  void Return(Node* value);
-
-  void Bind(Label* label);
-  void Goto(Label* label);
-  void GotoIf(Node* condition, Label* true_label);
-  void GotoUnless(Node* condition, Label* false_label);
-  void Branch(Node* condition, Label* true_label, Label* false_label);
-
-  void Switch(Node* index, Label* default_label, int32_t* case_values,
-              Label** case_labels, size_t case_count);
-
-  // Access to the frame pointer
-  Node* LoadFramePointer();
-  Node* LoadParentFramePointer();
-
-  // Access to the stack pointer
-  Node* LoadStackPointer();
-
-  // Load raw memory location.
-  Node* Load(MachineType rep, Node* base);
-  Node* Load(MachineType rep, Node* base, Node* index);
-
-  // Store value to raw memory location.
-  Node* Store(MachineRepresentation rep, Node* base, Node* value);
-  Node* Store(MachineRepresentation rep, Node* base, Node* index, Node* value);
-  Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* value);
-  Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* index,
-                            Node* value);
-
-// Basic arithmetic operations.
-#define DECLARE_CODE_STUB_ASSEMBER_BINARY_OP(name) Node* name(Node* a, Node* b);
-  CODE_STUB_ASSEMBLER_BINARY_OP_LIST(DECLARE_CODE_STUB_ASSEMBER_BINARY_OP)
-#undef DECLARE_CODE_STUB_ASSEMBER_BINARY_OP
-
-  Node* WordShl(Node* value, int shift);
-
-// Unary
-#define DECLARE_CODE_STUB_ASSEMBER_UNARY_OP(name) Node* name(Node* a);
-  CODE_STUB_ASSEMBLER_UNARY_OP_LIST(DECLARE_CODE_STUB_ASSEMBER_UNARY_OP)
-#undef DECLARE_CODE_STUB_ASSEMBER_UNARY_OP
-
-  // Projections
-  Node* Projection(int index, Node* value);
-
-  // Calls
-  Node* CallRuntime(Runtime::FunctionId function_id, Node* context);
-  Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1);
-  Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1,
-                    Node* arg2);
-  Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1,
-                    Node* arg2, Node* arg3);
-  Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1,
-                    Node* arg2, Node* arg3, Node* arg4);
-  Node* CallRuntime(Runtime::FunctionId function_id, Node* context, Node* arg1,
-                    Node* arg2, Node* arg3, Node* arg4, Node* arg5);
-
-  Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context);
-  Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
-                        Node* arg1);
-  Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
-                        Node* arg1, Node* arg2);
-  Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
-                        Node* arg1, Node* arg2, Node* arg3);
-  Node* TailCallRuntime(Runtime::FunctionId function_id, Node* context,
-                        Node* arg1, Node* arg2, Node* arg3, Node* arg4);
-
-  Node* CallStub(Callable const& callable, Node* context, Node* arg1,
-                 size_t result_size = 1);
-
-  Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
-                 Node* context, Node* arg1, size_t result_size = 1);
-  Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
-                 Node* context, Node* arg1, Node* arg2, size_t result_size = 1);
-  Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
-                 Node* context, Node* arg1, Node* arg2, Node* arg3,
-                 size_t result_size = 1);
-  Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
-                 Node* context, Node* arg1, Node* arg2, Node* arg3, Node* arg4,
-                 size_t result_size = 1);
-  Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
-                 Node* context, Node* arg1, Node* arg2, Node* arg3, Node* arg4,
-                 Node* arg5, size_t result_size = 1);
-
-  Node* TailCallStub(Callable const& callable, Node* context, Node* arg1,
-                     Node* arg2, size_t result_size = 1);
-
-  Node* TailCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
-                     Node* context, Node* arg1, Node* arg2,
-                     size_t result_size = 1);
-
-  Node* TailCall(const CallInterfaceDescriptor& descriptor, Node* target,
-                 Node** args, size_t result_size = 1);
-
-  // ===========================================================================
-  // Macros
-  // ===========================================================================
-
-  // Float64 operations.
-  Node* Float64Ceil(Node* x);
-  Node* Float64Floor(Node* x);
-  Node* Float64Round(Node* x);
-  Node* Float64Trunc(Node* x);
-
-  // Tag a Word as a Smi value.
-  Node* SmiTag(Node* value);
-  // Untag a Smi value as a Word.
-  Node* SmiUntag(Node* value);
-
-  // Smi conversions.
-  Node* SmiToFloat64(Node* value);
-  Node* SmiToWord32(Node* value);
-
-  // Smi operations.
-  Node* SmiAdd(Node* a, Node* b);
-  Node* SmiAddWithOverflow(Node* a, Node* b);
-  Node* SmiSub(Node* a, Node* b);
-  Node* SmiSubWithOverflow(Node* a, Node* b);
-  Node* SmiEqual(Node* a, Node* b);
-  Node* SmiLessThan(Node* a, Node* b);
-  Node* SmiLessThanOrEqual(Node* a, Node* b);
-  Node* SmiMin(Node* a, Node* b);
-
-  // Load a value from the root array.
-  Node* LoadRoot(Heap::RootListIndex root_index);
-
-  // Check a value for smi-ness
-  Node* WordIsSmi(Node* a);
-
-  // Check that the value is a positive smi.
-  Node* WordIsPositiveSmi(Node* a);
-
-  // Load an object pointer from a buffer that isn't in the heap.
-  Node* LoadBufferObject(Node* buffer, int offset,
-                         MachineType rep = MachineType::AnyTagged());
-  // Load a field from an object on the heap.
-  Node* LoadObjectField(Node* object, int offset,
-                        MachineType rep = MachineType::AnyTagged());
-  // Load the floating point value of a HeapNumber.
-  Node* LoadHeapNumberValue(Node* object);
-  // Store the floating point value of a HeapNumber.
-  Node* StoreHeapNumberValue(Node* object, Node* value);
-  // Truncate the floating point value of a HeapNumber to an Int32.
-  Node* TruncateHeapNumberValueToWord32(Node* object);
-  // Load the bit field of a Map.
-  Node* LoadMapBitField(Node* map);
-  // Load bit field 2 of a map.
-  Node* LoadMapBitField2(Node* map);
-  // Load bit field 3 of a map.
-  Node* LoadMapBitField3(Node* map);
-  // Load the instance type of a map.
-  Node* LoadMapInstanceType(Node* map);
-  // Load the instance descriptors of a map.
-  Node* LoadMapDescriptors(Node* map);
-
-  // Load the hash field of a name.
-  Node* LoadNameHash(Node* name);
-
-  // Load an array element from a FixedArray.
-  Node* LoadFixedArrayElementInt32Index(Node* object, Node* int32_index,
-                                        int additional_offset = 0);
-  Node* LoadFixedArrayElementSmiIndex(Node* object, Node* smi_index,
-                                      int additional_offset = 0);
-  Node* LoadFixedArrayElementConstantIndex(Node* object, int index);
-
-  // Allocate an object of the given size.
-  Node* Allocate(int size, AllocationFlags flags = kNone);
-  // Allocate a HeapNumber without initializing its value.
-  Node* AllocateHeapNumber();
-  // Allocate a HeapNumber with a specific value.
-  Node* AllocateHeapNumberWithValue(Node* value);
-
-  // Store an array element to a FixedArray.
-  Node* StoreFixedArrayElementNoWriteBarrier(Node* object, Node* index,
-                                             Node* value);
-  // Load the Map of an HeapObject.
-  Node* LoadMap(Node* object);
-  // Store the Map of an HeapObject.
-  Node* StoreMapNoWriteBarrier(Node* object, Node* map);
-  // Load the instance type of an HeapObject.
-  Node* LoadInstanceType(Node* object);
-
-  // Load the elements backing store of a JSObject.
-  Node* LoadElements(Node* object);
-  // Load the length of a fixed array base instance.
-  Node* LoadFixedArrayBaseLength(Node* array);
-
-  // Returns a node that is true if the given bit is set in |word32|.
-  template <typename T>
-  Node* BitFieldDecode(Node* word32) {
-    return BitFieldDecode(word32, T::kShift, T::kMask);
-  }
-
-  Node* BitFieldDecode(Node* word32, uint32_t shift, uint32_t mask);
-
-  // Conversions.
-  Node* ChangeFloat64ToTagged(Node* value);
-  Node* ChangeInt32ToTagged(Node* value);
-  Node* TruncateTaggedToFloat64(Node* context, Node* value);
-  Node* TruncateTaggedToWord32(Node* context, Node* value);
-
-  // Branching helpers.
-  // TODO(danno): Can we be more cleverish wrt. edge-split?
-  void BranchIf(Node* condition, Label* if_true, Label* if_false);
-
-#define BRANCH_HELPER(name)                                                \
-  void BranchIf##name(Node* a, Node* b, Label* if_true, Label* if_false) { \
-    BranchIf(name(a, b), if_true, if_false);                               \
-  }
-  CODE_STUB_ASSEMBLER_COMPARE_BINARY_OP_LIST(BRANCH_HELPER)
-#undef BRANCH_HELPER
-
-  void BranchIfSmiLessThan(Node* a, Node* b, Label* if_true, Label* if_false) {
-    BranchIf(SmiLessThan(a, b), if_true, if_false);
-  }
-
-  void BranchIfSmiLessThanOrEqual(Node* a, Node* b, Label* if_true,
-                                  Label* if_false) {
-    BranchIf(SmiLessThanOrEqual(a, b), if_true, if_false);
-  }
-
-  void BranchIfFloat64IsNaN(Node* value, Label* if_true, Label* if_false) {
-    BranchIfFloat64Equal(value, value, if_false, if_true);
-  }
-
-  // Helpers which delegate to RawMachineAssembler.
-  Factory* factory() const;
-  Isolate* isolate() const;
-  Zone* zone() const;
-
- protected:
-  // Protected helpers which delegate to RawMachineAssembler.
-  Graph* graph() const;
-
-  // Enables subclasses to perform operations before and after a call.
-  virtual void CallPrologue();
-  virtual void CallEpilogue();
-
- private:
-  friend class CodeStubAssemblerTester;
-
-  CodeStubAssembler(Isolate* isolate, Zone* zone,
-                    CallDescriptor* call_descriptor, Code::Flags flags,
-                    const char* name);
-
-  Node* CallN(CallDescriptor* descriptor, Node* code_target, Node** args);
-  Node* TailCallN(CallDescriptor* descriptor, Node* code_target, Node** args);
-
-  Node* SmiShiftBitsConstant();
-
-  Node* AllocateRawAligned(Node* size_in_bytes, AllocationFlags flags,
-                           Node* top_address, Node* limit_address);
-  Node* AllocateRawUnaligned(Node* size_in_bytes, AllocationFlags flags,
-                             Node* top_adddress, Node* limit_address);
-
-  base::SmartPointer<RawMachineAssembler> raw_assembler_;
-  Code::Flags flags_;
-  const char* name_;
-  bool code_generated_;
-  ZoneVector<Variable::Impl*> variables_;
-
-  DISALLOW_COPY_AND_ASSIGN(CodeStubAssembler);
-};
-
-DEFINE_OPERATORS_FOR_FLAGS(CodeStubAssembler::AllocationFlags);
-
-class CodeStubAssembler::Label {
- public:
-  enum Type { kDeferred, kNonDeferred };
-
-  explicit Label(CodeStubAssembler* assembler,
-                 CodeStubAssembler::Label::Type type =
-                     CodeStubAssembler::Label::kNonDeferred)
-      : CodeStubAssembler::Label(assembler, 0, nullptr, type) {}
-  Label(CodeStubAssembler* assembler,
-        CodeStubAssembler::Variable* merged_variable,
-        CodeStubAssembler::Label::Type type =
-            CodeStubAssembler::Label::kNonDeferred)
-      : CodeStubAssembler::Label(assembler, 1, &merged_variable, type) {}
-  Label(CodeStubAssembler* assembler, int merged_variable_count,
-        CodeStubAssembler::Variable** merged_variables,
-        CodeStubAssembler::Label::Type type =
-            CodeStubAssembler::Label::kNonDeferred);
-  ~Label() {}
-
- private:
-  friend class CodeStubAssembler;
-
-  void Bind();
-  void MergeVariables();
-
-  bool bound_;
-  size_t merge_count_;
-  CodeStubAssembler* assembler_;
-  RawMachineLabel* label_;
-  // Map of variables that need to be merged to their phi nodes (or placeholders
-  // for those phis).
-  std::map<Variable::Impl*, Node*> variable_phis_;
-  // Map of variables to the list of value nodes that have been added from each
-  // merge path in their order of merging.
-  std::map<Variable::Impl*, std::vector<Node*>> variable_merges_;
-};
-
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
-
-#endif  // V8_COMPILER_CODE_STUB_ASSEMBLER_H_
diff --git a/src/compiler/common-node-cache.cc b/src/compiler/common-node-cache.cc
index a0ae6e8..fa4ca34 100644
--- a/src/compiler/common-node-cache.cc
+++ b/src/compiler/common-node-cache.cc
@@ -17,7 +17,7 @@
 
 
 Node** CommonNodeCache::FindHeapConstant(Handle<HeapObject> value) {
-  return heap_constants_.Find(zone(), bit_cast<intptr_t>(value.location()));
+  return heap_constants_.Find(zone(), bit_cast<intptr_t>(value.address()));
 }
 
 
@@ -29,6 +29,8 @@
   external_constants_.GetCachedNodes(nodes);
   number_constants_.GetCachedNodes(nodes);
   heap_constants_.GetCachedNodes(nodes);
+  relocatable_int32_constants_.GetCachedNodes(nodes);
+  relocatable_int64_constants_.GetCachedNodes(nodes);
 }
 
 }  // namespace compiler
diff --git a/src/compiler/common-node-cache.h b/src/compiler/common-node-cache.h
index 720bc15..1f07703 100644
--- a/src/compiler/common-node-cache.h
+++ b/src/compiler/common-node-cache.h
@@ -52,6 +52,16 @@
 
   Node** FindHeapConstant(Handle<HeapObject> value);
 
+  Node** FindRelocatableInt32Constant(int32_t value, RelocInfoMode rmode) {
+    return relocatable_int32_constants_.Find(zone(),
+                                             std::make_pair(value, rmode));
+  }
+
+  Node** FindRelocatableInt64Constant(int64_t value, RelocInfoMode rmode) {
+    return relocatable_int64_constants_.Find(zone(),
+                                             std::make_pair(value, rmode));
+  }
+
   // Return all nodes from the cache.
   void GetCachedNodes(ZoneVector<Node*>* nodes);
 
@@ -65,6 +75,8 @@
   IntPtrNodeCache external_constants_;
   Int64NodeCache number_constants_;
   IntPtrNodeCache heap_constants_;
+  RelocInt32NodeCache relocatable_int32_constants_;
+  RelocInt64NodeCache relocatable_int64_constants_;
   Zone* const zone_;
 
   DISALLOW_COPY_AND_ASSIGN(CommonNodeCache);
diff --git a/src/compiler/common-operator-reducer.cc b/src/compiler/common-operator-reducer.cc
index 22e16a2..5c3d3d7 100644
--- a/src/compiler/common-operator-reducer.cc
+++ b/src/compiler/common-operator-reducer.cc
@@ -19,18 +19,12 @@
 
 namespace {
 
-enum class Decision { kUnknown, kTrue, kFalse };
-
 Decision DecideCondition(Node* const cond) {
   switch (cond->opcode()) {
     case IrOpcode::kInt32Constant: {
       Int32Matcher mcond(cond);
       return mcond.Value() ? Decision::kTrue : Decision::kFalse;
     }
-    case IrOpcode::kInt64Constant: {
-      Int64Matcher mcond(cond);
-      return mcond.Value() ? Decision::kTrue : Decision::kFalse;
-    }
     case IrOpcode::kHeapConstant: {
       HeapObjectMatcher mcond(cond);
       return mcond.Value()->BooleanValue() ? Decision::kTrue : Decision::kFalse;
@@ -70,8 +64,6 @@
       return ReduceReturn(node);
     case IrOpcode::kSelect:
       return ReduceSelect(node);
-    case IrOpcode::kGuard:
-      return ReduceGuard(node);
     default:
       break;
   }
@@ -148,13 +140,14 @@
   Decision const decision = DecideCondition(condition);
   if (decision == Decision::kUnknown) return NoChange();
   if (condition_is_true == (decision == Decision::kTrue)) {
-    return Replace(control);
+    ReplaceWithValue(node, dead(), effect, control);
+  } else {
+    control = graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
+                               frame_state, effect, control);
+    // TODO(bmeurer): This should be on the AdvancedReducer somehow.
+    NodeProperties::MergeControlToEnd(graph(), common(), control);
+    Revisit(graph()->end());
   }
-  control = graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kEager),
-                             frame_state, effect, control);
-  // TODO(bmeurer): This should be on the AdvancedReducer somehow.
-  NodeProperties::MergeControlToEnd(graph(), common(), control);
-  Revisit(graph()->end());
   return Replace(dead());
 }
 
@@ -396,16 +389,6 @@
 }
 
 
-Reduction CommonOperatorReducer::ReduceGuard(Node* node) {
-  DCHECK_EQ(IrOpcode::kGuard, node->opcode());
-  Node* const input = NodeProperties::GetValueInput(node, 0);
-  Type* const input_type = NodeProperties::GetTypeOrAny(input);
-  Type* const guard_type = OpParameter<Type*>(node);
-  if (input_type->Is(guard_type)) return Replace(input);
-  return NoChange();
-}
-
-
 Reduction CommonOperatorReducer::Change(Node* node, Operator const* op,
                                         Node* a) {
   node->ReplaceInput(0, a);
diff --git a/src/compiler/common-operator-reducer.h b/src/compiler/common-operator-reducer.h
index 49d9f1d..b7aeeb7 100644
--- a/src/compiler/common-operator-reducer.h
+++ b/src/compiler/common-operator-reducer.h
@@ -36,7 +36,6 @@
   Reduction ReducePhi(Node* node);
   Reduction ReduceReturn(Node* node);
   Reduction ReduceSelect(Node* node);
-  Reduction ReduceGuard(Node* node);
 
   Reduction Change(Node* node, Operator const* op, Node* a);
   Reduction Change(Node* node, Operator const* op, Node* a, Node* b);
diff --git a/src/compiler/common-operator.cc b/src/compiler/common-operator.cc
index 3bb1b34..4f5ead8 100644
--- a/src/compiler/common-operator.cc
+++ b/src/compiler/common-operator.cc
@@ -98,6 +98,11 @@
   return OpParameter<SelectParameters>(op);
 }
 
+CallDescriptor const* CallDescriptorOf(const Operator* const op) {
+  DCHECK(op->opcode() == IrOpcode::kCall ||
+         op->opcode() == IrOpcode::kTailCall);
+  return OpParameter<CallDescriptor const*>(op);
+}
 
 size_t ProjectionIndexOf(const Operator* const op) {
   DCHECK_EQ(IrOpcode::kProjection, op->opcode());
@@ -142,10 +147,64 @@
   return os;
 }
 
+bool operator==(RelocatablePtrConstantInfo const& lhs,
+                RelocatablePtrConstantInfo const& rhs) {
+  return lhs.rmode() == rhs.rmode() && lhs.value() == rhs.value() &&
+         lhs.type() == rhs.type();
+}
+
+bool operator!=(RelocatablePtrConstantInfo const& lhs,
+                RelocatablePtrConstantInfo const& rhs) {
+  return !(lhs == rhs);
+}
+
+size_t hash_value(RelocatablePtrConstantInfo const& p) {
+  return base::hash_combine(p.value(), p.rmode(), p.type());
+}
+
+std::ostream& operator<<(std::ostream& os,
+                         RelocatablePtrConstantInfo const& p) {
+  return os << p.value() << "|" << p.rmode() << "|" << p.type();
+}
+
+size_t hash_value(RegionObservability observability) {
+  return static_cast<size_t>(observability);
+}
+
+std::ostream& operator<<(std::ostream& os, RegionObservability observability) {
+  switch (observability) {
+    case RegionObservability::kObservable:
+      return os << "observable";
+    case RegionObservability::kNotObservable:
+      return os << "not-observable";
+  }
+  UNREACHABLE();
+  return os;
+}
+
+RegionObservability RegionObservabilityOf(Operator const* op) {
+  DCHECK_EQ(IrOpcode::kBeginRegion, op->opcode());
+  return OpParameter<RegionObservability>(op);
+}
+
+std::ostream& operator<<(std::ostream& os,
+                         const ZoneVector<MachineType>* types) {
+  // Print all the MachineTypes, separated by commas.
+  bool first = true;
+  for (MachineType elem : *types) {
+    if (!first) {
+      os << ", ";
+    }
+    first = false;
+    os << elem;
+  }
+  return os;
+}
+
 #define CACHED_OP_LIST(V)                                    \
   V(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1)             \
-  V(DeoptimizeIf, Operator::kFoldable, 2, 1, 1, 0, 0, 1)     \
-  V(DeoptimizeUnless, Operator::kFoldable, 2, 1, 1, 0, 0, 1) \
+  V(DeoptimizeIf, Operator::kFoldable, 2, 1, 1, 0, 1, 1)     \
+  V(DeoptimizeUnless, Operator::kFoldable, 2, 1, 1, 0, 1, 1) \
   V(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1)            \
   V(IfFalse, Operator::kKontrol, 0, 0, 1, 0, 0, 1)           \
   V(IfSuccess, Operator::kKontrol, 0, 0, 1, 0, 0, 1)         \
@@ -154,8 +213,8 @@
   V(Terminate, Operator::kKontrol, 0, 1, 1, 0, 0, 1)         \
   V(OsrNormalEntry, Operator::kFoldable, 0, 1, 1, 0, 1, 1)   \
   V(OsrLoopEntry, Operator::kFoldable, 0, 1, 1, 0, 1, 1)     \
-  V(BeginRegion, Operator::kNoThrow, 0, 1, 0, 0, 1, 0)       \
-  V(FinishRegion, Operator::kNoThrow, 1, 1, 0, 1, 1, 0)
+  V(Checkpoint, Operator::kKontrol, 0, 1, 1, 0, 1, 0)        \
+  V(FinishRegion, Operator::kKontrol, 1, 1, 0, 1, 1, 0)
 
 #define CACHED_RETURN_LIST(V) \
   V(1)                        \
@@ -334,6 +393,20 @@
   CACHED_EFFECT_PHI_LIST(CACHED_EFFECT_PHI)
 #undef CACHED_EFFECT_PHI
 
+  template <RegionObservability kRegionObservability>
+  struct BeginRegionOperator final : public Operator1<RegionObservability> {
+    BeginRegionOperator()
+        : Operator1<RegionObservability>(                  // --
+              IrOpcode::kBeginRegion, Operator::kKontrol,  // opcode
+              "BeginRegion",                               // name
+              0, 1, 0, 0, 1, 0,                            // counts
+              kRegionObservability) {}                     // parameter
+  };
+  BeginRegionOperator<RegionObservability::kObservable>
+      kBeginRegionObservableOperator;
+  BeginRegionOperator<RegionObservability::kNotObservable>
+      kBeginRegionNotObservableOperator;
+
   template <size_t kInputCount>
   struct LoopOperator final : public Operator {
     LoopOperator()
@@ -396,7 +469,7 @@
               IrOpcode::kProjection,  // opcode
               Operator::kPure,        // flags
               "Projection",           // name
-              1, 0, 0, 1, 0, 0,       // counts,
+              1, 0, 1, 1, 0, 0,       // counts,
               kIndex) {}              // parameter
   };
 #define CACHED_PROJECTION(index) \
@@ -668,6 +741,23 @@
       value);                                         // parameter
 }
 
+const Operator* CommonOperatorBuilder::RelocatableInt32Constant(
+    int32_t value, RelocInfo::Mode rmode) {
+  return new (zone()) Operator1<RelocatablePtrConstantInfo>(  // --
+      IrOpcode::kRelocatableInt32Constant, Operator::kPure,   // opcode
+      "RelocatableInt32Constant",                             // name
+      0, 0, 0, 1, 0, 0,                                       // counts
+      RelocatablePtrConstantInfo(value, rmode));              // parameter
+}
+
+const Operator* CommonOperatorBuilder::RelocatableInt64Constant(
+    int64_t value, RelocInfo::Mode rmode) {
+  return new (zone()) Operator1<RelocatablePtrConstantInfo>(  // --
+      IrOpcode::kRelocatableInt64Constant, Operator::kPure,   // opcode
+      "RelocatableInt64Constant",                             // name
+      0, 0, 0, 1, 0, 0,                                       // counts
+      RelocatablePtrConstantInfo(value, rmode));              // parameter
+}
 
 const Operator* CommonOperatorBuilder::Select(MachineRepresentation rep,
                                               BranchHint hint) {
@@ -716,25 +806,18 @@
       0, effect_input_count, 1, 0, 1, 0);     // counts
 }
 
-
-const Operator* CommonOperatorBuilder::Guard(Type* type) {
-  return new (zone()) Operator1<Type*>(      // --
-      IrOpcode::kGuard, Operator::kKontrol,  // opcode
-      "Guard",                               // name
-      1, 0, 1, 1, 0, 0,                      // counts
-      type);                                 // parameter
+const Operator* CommonOperatorBuilder::BeginRegion(
+    RegionObservability region_observability) {
+  switch (region_observability) {
+    case RegionObservability::kObservable:
+      return &cache_.kBeginRegionObservableOperator;
+    case RegionObservability::kNotObservable:
+      return &cache_.kBeginRegionNotObservableOperator;
+  }
+  UNREACHABLE();
+  return nullptr;
 }
 
-
-const Operator* CommonOperatorBuilder::EffectSet(int arguments) {
-  DCHECK(arguments > 1);                      // Disallow empty/singleton sets.
-  return new (zone()) Operator(               // --
-      IrOpcode::kEffectSet, Operator::kPure,  // opcode
-      "EffectSet",                            // name
-      0, arguments, 0, 0, 1, 0);              // counts
-}
-
-
 const Operator* CommonOperatorBuilder::StateValues(int arguments) {
   switch (arguments) {
 #define CACHED_STATE_VALUES(arguments) \
@@ -832,12 +915,12 @@
       break;
   }
   // Uncached.
-  return new (zone()) Operator1<size_t>(         // --
-      IrOpcode::kProjection,                     // opcode
-      Operator::kFoldable | Operator::kNoThrow,  // flags
-      "Projection",                              // name
-      1, 0, 0, 1, 0, 0,                          // counts
-      index);                                    // parameter
+  return new (zone()) Operator1<size_t>(  // --
+      IrOpcode::kProjection,              // opcode
+      Operator::kPure,                    // flags
+      "Projection",                       // name
+      1, 0, 1, 1, 0, 0,                   // counts
+      index);                             // parameter
 }
 
 
diff --git a/src/compiler/common-operator.h b/src/compiler/common-operator.h
index 7c59f47..77d53de 100644
--- a/src/compiler/common-operator.h
+++ b/src/compiler/common-operator.h
@@ -5,17 +5,13 @@
 #ifndef V8_COMPILER_COMMON_OPERATOR_H_
 #define V8_COMPILER_COMMON_OPERATOR_H_
 
+#include "src/assembler.h"
 #include "src/compiler/frame-states.h"
 #include "src/machine-type.h"
 #include "src/zone-containers.h"
 
 namespace v8 {
 namespace internal {
-
-// Forward declarations.
-class ExternalReference;
-class Type;
-
 namespace compiler {
 
 // Forward declarations.
@@ -88,6 +84,7 @@
 
 SelectParameters const& SelectParametersOf(const Operator* const);
 
+CallDescriptor const* CallDescriptorOf(const Operator* const);
 
 size_t ProjectionIndexOf(const Operator* const);
 
@@ -114,6 +111,47 @@
 int ParameterIndexOf(const Operator* const);
 const ParameterInfo& ParameterInfoOf(const Operator* const);
 
+class RelocatablePtrConstantInfo final {
+ public:
+  enum Type { kInt32, kInt64 };
+
+  RelocatablePtrConstantInfo(int32_t value, RelocInfo::Mode rmode)
+      : value_(value), rmode_(rmode), type_(kInt32) {}
+  RelocatablePtrConstantInfo(int64_t value, RelocInfo::Mode rmode)
+      : value_(value), rmode_(rmode), type_(kInt64) {}
+
+  intptr_t value() const { return value_; }
+  RelocInfo::Mode rmode() const { return rmode_; }
+  Type type() const { return type_; }
+
+ private:
+  intptr_t value_;
+  RelocInfo::Mode rmode_;
+  Type type_;
+};
+
+bool operator==(RelocatablePtrConstantInfo const& lhs,
+                RelocatablePtrConstantInfo const& rhs);
+bool operator!=(RelocatablePtrConstantInfo const& lhs,
+                RelocatablePtrConstantInfo const& rhs);
+
+std::ostream& operator<<(std::ostream&, RelocatablePtrConstantInfo const&);
+
+size_t hash_value(RelocatablePtrConstantInfo const& p);
+
+// Used to mark a region (as identified by BeginRegion/FinishRegion) as either
+// JavaScript-observable or not (i.e. allocations are not JavaScript observable
+// themselves, but transitioning stores are).
+enum class RegionObservability : uint8_t { kObservable, kNotObservable };
+
+size_t hash_value(RegionObservability);
+
+std::ostream& operator<<(std::ostream&, RegionObservability);
+
+RegionObservability RegionObservabilityOf(Operator const*) WARN_UNUSED_RESULT;
+
+std::ostream& operator<<(std::ostream& os,
+                         const ZoneVector<MachineType>* types);
 
 // Interface for building common operators that can be used at any level of IR,
 // including JavaScript, mid-level, and low-level.
@@ -155,13 +193,17 @@
   const Operator* NumberConstant(volatile double);
   const Operator* HeapConstant(const Handle<HeapObject>&);
 
+  const Operator* RelocatableInt32Constant(int32_t value,
+                                           RelocInfo::Mode rmode);
+  const Operator* RelocatableInt64Constant(int64_t value,
+                                           RelocInfo::Mode rmode);
+
   const Operator* Select(MachineRepresentation, BranchHint = BranchHint::kNone);
   const Operator* Phi(MachineRepresentation representation,
                       int value_input_count);
   const Operator* EffectPhi(int effect_input_count);
-  const Operator* EffectSet(int arguments);
-  const Operator* Guard(Type* type);
-  const Operator* BeginRegion();
+  const Operator* Checkpoint();
+  const Operator* BeginRegion(RegionObservability);
   const Operator* FinishRegion();
   const Operator* StateValues(int arguments);
   const Operator* ObjectState(int pointer_slots, int id);
diff --git a/src/compiler/effect-control-linearizer.cc b/src/compiler/effect-control-linearizer.cc
new file mode 100644
index 0000000..b7f6b12
--- /dev/null
+++ b/src/compiler/effect-control-linearizer.cc
@@ -0,0 +1,1670 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/effect-control-linearizer.h"
+
+#include "src/code-factory.h"
+#include "src/compiler/access-builder.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/linkage.h"
+#include "src/compiler/node-properties.h"
+#include "src/compiler/node.h"
+#include "src/compiler/schedule.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+EffectControlLinearizer::EffectControlLinearizer(JSGraph* js_graph,
+                                                 Schedule* schedule,
+                                                 Zone* temp_zone)
+    : js_graph_(js_graph), schedule_(schedule), temp_zone_(temp_zone) {}
+
+Graph* EffectControlLinearizer::graph() const { return js_graph_->graph(); }
+CommonOperatorBuilder* EffectControlLinearizer::common() const {
+  return js_graph_->common();
+}
+SimplifiedOperatorBuilder* EffectControlLinearizer::simplified() const {
+  return js_graph_->simplified();
+}
+MachineOperatorBuilder* EffectControlLinearizer::machine() const {
+  return js_graph_->machine();
+}
+
+namespace {
+
+struct BlockEffectControlData {
+  Node* current_effect = nullptr;  // New effect.
+  Node* current_control = nullptr;  // New control.
+  Node* current_frame_state = nullptr;  // New frame state.
+};
+
+// Effect phis that need to be updated after the first pass.
+struct PendingEffectPhi {
+  Node* effect_phi;
+  BasicBlock* block;
+
+  PendingEffectPhi(Node* effect_phi, BasicBlock* block)
+      : effect_phi(effect_phi), block(block) {}
+};
+
+void UpdateEffectPhi(Node* node, BasicBlock* block,
+                     ZoneVector<BlockEffectControlData>* block_effects) {
+  // Update all inputs to an effect phi with the effects from the given
+  // block->effect map.
+  DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode());
+  DCHECK_EQ(node->op()->EffectInputCount(), block->PredecessorCount());
+  for (int i = 0; i < node->op()->EffectInputCount(); i++) {
+    Node* input = node->InputAt(i);
+    BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
+    Node* input_effect =
+        (*block_effects)[predecessor->rpo_number()].current_effect;
+    if (input != input_effect) {
+      node->ReplaceInput(i, input_effect);
+    }
+  }
+}
+
+void UpdateBlockControl(BasicBlock* block,
+                        ZoneVector<BlockEffectControlData>* block_effects) {
+  Node* control = block->NodeAt(0);
+  DCHECK(NodeProperties::IsControl(control));
+
+  // Do not rewire the end node.
+  if (control->opcode() == IrOpcode::kEnd) return;
+
+  // Update all inputs to the given control node with the correct control.
+  DCHECK_EQ(control->op()->ControlInputCount(), block->PredecessorCount());
+  for (int i = 0; i < control->op()->ControlInputCount(); i++) {
+    Node* input = NodeProperties::GetControlInput(control, i);
+    BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
+    Node* input_control =
+        (*block_effects)[predecessor->rpo_number()].current_control;
+    if (input != input_control) {
+      NodeProperties::ReplaceControlInput(control, input_control, i);
+    }
+  }
+}
+
+bool HasIncomingBackEdges(BasicBlock* block) {
+  for (BasicBlock* pred : block->predecessors()) {
+    if (pred->rpo_number() >= block->rpo_number()) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void RemoveRegionNode(Node* node) {
+  DCHECK(IrOpcode::kFinishRegion == node->opcode() ||
+         IrOpcode::kBeginRegion == node->opcode());
+  // Update the value/context uses to the value input of the finish node and
+  // the effect uses to the effect input.
+  for (Edge edge : node->use_edges()) {
+    DCHECK(!edge.from()->IsDead());
+    if (NodeProperties::IsEffectEdge(edge)) {
+      edge.UpdateTo(NodeProperties::GetEffectInput(node));
+    } else {
+      DCHECK(!NodeProperties::IsControlEdge(edge));
+      DCHECK(!NodeProperties::IsFrameStateEdge(edge));
+      edge.UpdateTo(node->InputAt(0));
+    }
+  }
+  node->Kill();
+}
+
+}  // namespace
+
+void EffectControlLinearizer::Run() {
+  ZoneVector<BlockEffectControlData> block_effects(temp_zone());
+  ZoneVector<PendingEffectPhi> pending_effect_phis(temp_zone());
+  ZoneVector<BasicBlock*> pending_block_controls(temp_zone());
+  block_effects.resize(schedule()->RpoBlockCount());
+  NodeVector inputs_buffer(temp_zone());
+
+  for (BasicBlock* block : *(schedule()->rpo_order())) {
+    size_t instr = 0;
+
+    // The control node should be the first.
+    Node* control = block->NodeAt(instr);
+    DCHECK(NodeProperties::IsControl(control));
+    // Update the control inputs.
+    if (HasIncomingBackEdges(block)) {
+      // If there are back edges, we need to update later because we have not
+      // computed the control yet. This should only happen for loops.
+      DCHECK_EQ(IrOpcode::kLoop, control->opcode());
+      pending_block_controls.push_back(block);
+    } else {
+      // If there are no back edges, we can update now.
+      UpdateBlockControl(block, &block_effects);
+    }
+    instr++;
+
+    // Iterate over the phis and update the effect phis.
+    Node* effect = nullptr;
+    Node* terminate = nullptr;
+    for (; instr < block->NodeCount(); instr++) {
+      Node* node = block->NodeAt(instr);
+      // Only go through the phis and effect phis.
+      if (node->opcode() == IrOpcode::kEffectPhi) {
+        // There should be at most one effect phi in a block.
+        DCHECK_NULL(effect);
+        // IfException blocks should not have effect phis.
+        DCHECK_NE(IrOpcode::kIfException, control->opcode());
+        effect = node;
+
+        // Make sure we update the inputs to the incoming blocks' effects.
+        if (HasIncomingBackEdges(block)) {
+          // In case of loops, we do not update the effect phi immediately
+          // because the back predecessor has not been handled yet. We just
+          // record the effect phi for later processing.
+          pending_effect_phis.push_back(PendingEffectPhi(node, block));
+        } else {
+          UpdateEffectPhi(node, block, &block_effects);
+        }
+      } else if (node->opcode() == IrOpcode::kPhi) {
+        // Just skip phis.
+      } else if (node->opcode() == IrOpcode::kTerminate) {
+        DCHECK(terminate == nullptr);
+        terminate = node;
+      } else {
+        break;
+      }
+    }
+
+    if (effect == nullptr) {
+      // There was no effect phi.
+      DCHECK(!HasIncomingBackEdges(block));
+      if (block == schedule()->start()) {
+        // Start block => effect is start.
+        DCHECK_EQ(graph()->start(), control);
+        effect = graph()->start();
+      } else if (control->opcode() == IrOpcode::kEnd) {
+        // End block is just a dummy, no effect needed.
+        DCHECK_EQ(BasicBlock::kNone, block->control());
+        DCHECK_EQ(1u, block->size());
+        effect = nullptr;
+      } else {
+        // If all the predecessors have the same effect, we can use it
+        // as our current effect.
+        int rpo_number = block->PredecessorAt(0)->rpo_number();
+        effect = block_effects[rpo_number].current_effect;
+        for (size_t i = 1; i < block->PredecessorCount(); i++) {
+          int rpo_number = block->PredecessorAt(i)->rpo_number();
+          if (block_effects[rpo_number].current_effect != effect) {
+            effect = nullptr;
+            break;
+          }
+        }
+        if (effect == nullptr) {
+          DCHECK_NE(IrOpcode::kIfException, control->opcode());
+          // The input blocks do not have the same effect. We have
+          // to create an effect phi node.
+          inputs_buffer.clear();
+          inputs_buffer.resize(block->PredecessorCount(), graph()->start());
+          inputs_buffer.push_back(control);
+          effect = graph()->NewNode(
+              common()->EffectPhi(static_cast<int>(block->PredecessorCount())),
+              static_cast<int>(inputs_buffer.size()), &(inputs_buffer.front()));
+          // Let us update the effect phi node later.
+          pending_effect_phis.push_back(PendingEffectPhi(effect, block));
+        } else if (control->opcode() == IrOpcode::kIfException) {
+          // The IfException is connected into the effect chain, so we need
+          // to update the effect here.
+          NodeProperties::ReplaceEffectInput(control, effect);
+          effect = control;
+        }
+      }
+    }
+
+    // Fixup the Terminate node.
+    if (terminate != nullptr) {
+      NodeProperties::ReplaceEffectInput(terminate, effect);
+    }
+
+    // The frame state at block entry is determined by the frame states leaving
+    // all predecessors. In case there is no frame state dominating this block,
+    // we can rely on a checkpoint being present before the next deoptimization.
+    // TODO(mstarzinger): Eventually we will need to go hunt for a frame state
+    // once deoptimizing nodes roam freely through the schedule.
+    Node* frame_state = nullptr;
+    if (block != schedule()->start()) {
+      // If all the predecessors have the same effect, we can use it
+      // as our current effect.
+      int rpo_number = block->PredecessorAt(0)->rpo_number();
+      frame_state = block_effects[rpo_number].current_frame_state;
+      for (size_t i = 1; i < block->PredecessorCount(); i++) {
+        int rpo_number = block->PredecessorAt(i)->rpo_number();
+        if (block_effects[rpo_number].current_frame_state != frame_state) {
+          frame_state = nullptr;
+          break;
+        }
+      }
+    }
+
+    // Process the ordinary instructions.
+    for (; instr < block->NodeCount(); instr++) {
+      Node* node = block->NodeAt(instr);
+      ProcessNode(node, &frame_state, &effect, &control);
+    }
+
+    switch (block->control()) {
+      case BasicBlock::kGoto:
+      case BasicBlock::kNone:
+        break;
+
+      case BasicBlock::kCall:
+      case BasicBlock::kTailCall:
+      case BasicBlock::kBranch:
+      case BasicBlock::kSwitch:
+      case BasicBlock::kReturn:
+      case BasicBlock::kDeoptimize:
+      case BasicBlock::kThrow:
+        ProcessNode(block->control_input(), &frame_state, &effect, &control);
+        break;
+    }
+
+    // Store the effect for later use.
+    block_effects[block->rpo_number()].current_effect = effect;
+    block_effects[block->rpo_number()].current_control = control;
+    block_effects[block->rpo_number()].current_frame_state = frame_state;
+  }
+
+  // Update the incoming edges of the effect phis that could not be processed
+  // during the first pass (because they could have incoming back edges).
+  for (const PendingEffectPhi& pending_effect_phi : pending_effect_phis) {
+    UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block,
+                    &block_effects);
+  }
+  for (BasicBlock* pending_block_control : pending_block_controls) {
+    UpdateBlockControl(pending_block_control, &block_effects);
+  }
+}
+
+namespace {
+
+void TryScheduleCallIfSuccess(Node* node, Node** control) {
+  // Schedule the call's IfSuccess node if there is no exception use.
+  if (!NodeProperties::IsExceptionalCall(node)) {
+    for (Edge edge : node->use_edges()) {
+      if (NodeProperties::IsControlEdge(edge) &&
+          edge.from()->opcode() == IrOpcode::kIfSuccess) {
+        *control = edge.from();
+      }
+    }
+  }
+}
+
+}  // namespace
+
+void EffectControlLinearizer::ProcessNode(Node* node, Node** frame_state,
+                                          Node** effect, Node** control) {
+  // If the node needs to be wired into the effect/control chain, do this
+  // here. Pass current frame state for lowering to eager deoptimization.
+  if (TryWireInStateEffect(node, *frame_state, effect, control)) {
+    return;
+  }
+
+  // If the node has a visible effect, then there must be a checkpoint in the
+  // effect chain before we are allowed to place another eager deoptimization
+  // point. We zap the frame state to ensure this invariant is maintained.
+  if (region_observability_ == RegionObservability::kObservable &&
+      !node->op()->HasProperty(Operator::kNoWrite)) {
+    *frame_state = nullptr;
+  }
+
+  // Remove the end markers of 'atomic' allocation region because the
+  // region should be wired-in now.
+  if (node->opcode() == IrOpcode::kFinishRegion) {
+    // Reset the current region observability.
+    region_observability_ = RegionObservability::kObservable;
+    // Update the value uses to the value input of the finish node and
+    // the effect uses to the effect input.
+    return RemoveRegionNode(node);
+  }
+  if (node->opcode() == IrOpcode::kBeginRegion) {
+    // Determine the observability for this region and use that for all
+    // nodes inside the region (i.e. ignore the absence of kNoWrite on
+    // StoreField and other operators).
+    DCHECK_NE(RegionObservability::kNotObservable, region_observability_);
+    region_observability_ = RegionObservabilityOf(node->op());
+    // Update the value uses to the value input of the finish node and
+    // the effect uses to the effect input.
+    return RemoveRegionNode(node);
+  }
+
+  // Special treatment for checkpoint nodes.
+  if (node->opcode() == IrOpcode::kCheckpoint) {
+    // Unlink the check point; effect uses will be updated to the incoming
+    // effect that is passed. The frame state is preserved for lowering.
+    DCHECK_EQ(RegionObservability::kObservable, region_observability_);
+    *frame_state = NodeProperties::GetFrameStateInput(node, 0);
+    node->TrimInputCount(0);
+    return;
+  }
+
+  if (node->opcode() == IrOpcode::kIfSuccess) {
+    // We always schedule IfSuccess with its call, so skip it here.
+    DCHECK_EQ(IrOpcode::kCall, node->InputAt(0)->opcode());
+    // The IfSuccess node should not belong to an exceptional call node
+    // because such IfSuccess nodes should only start a basic block (and
+    // basic block start nodes are not handled in the ProcessNode method).
+    DCHECK(!NodeProperties::IsExceptionalCall(node->InputAt(0)));
+    return;
+  }
+
+  // If the node takes an effect, replace with the current one.
+  if (node->op()->EffectInputCount() > 0) {
+    DCHECK_EQ(1, node->op()->EffectInputCount());
+    Node* input_effect = NodeProperties::GetEffectInput(node);
+
+    if (input_effect != *effect) {
+      NodeProperties::ReplaceEffectInput(node, *effect);
+    }
+
+    // If the node produces an effect, update our current effect. (However,
+    // ignore new effect chains started with ValueEffect.)
+    if (node->op()->EffectOutputCount() > 0) {
+      DCHECK_EQ(1, node->op()->EffectOutputCount());
+      *effect = node;
+    }
+  } else {
+    // New effect chain is only started with a Start or ValueEffect node.
+    DCHECK(node->op()->EffectOutputCount() == 0 ||
+           node->opcode() == IrOpcode::kStart);
+  }
+
+  // Rewire control inputs.
+  for (int i = 0; i < node->op()->ControlInputCount(); i++) {
+    NodeProperties::ReplaceControlInput(node, *control, i);
+  }
+  // Update the current control and wire IfSuccess right after calls.
+  if (node->op()->ControlOutputCount() > 0) {
+    *control = node;
+    if (node->opcode() == IrOpcode::kCall) {
+      // Schedule the call's IfSuccess node (if there is no exception use).
+      TryScheduleCallIfSuccess(node, control);
+    }
+  }
+}
+
+bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
+                                                   Node* frame_state,
+                                                   Node** effect,
+                                                   Node** control) {
+  ValueEffectControl state(nullptr, nullptr, nullptr);
+  switch (node->opcode()) {
+    case IrOpcode::kTypeGuard:
+      state = LowerTypeGuard(node, *effect, *control);
+      break;
+    case IrOpcode::kChangeBitToTagged:
+      state = LowerChangeBitToTagged(node, *effect, *control);
+      break;
+    case IrOpcode::kChangeInt31ToTaggedSigned:
+      state = LowerChangeInt31ToTaggedSigned(node, *effect, *control);
+      break;
+    case IrOpcode::kChangeInt32ToTagged:
+      state = LowerChangeInt32ToTagged(node, *effect, *control);
+      break;
+    case IrOpcode::kChangeUint32ToTagged:
+      state = LowerChangeUint32ToTagged(node, *effect, *control);
+      break;
+    case IrOpcode::kChangeFloat64ToTagged:
+      state = LowerChangeFloat64ToTagged(node, *effect, *control);
+      break;
+    case IrOpcode::kChangeTaggedSignedToInt32:
+      state = LowerChangeTaggedSignedToInt32(node, *effect, *control);
+      break;
+    case IrOpcode::kChangeTaggedToBit:
+      state = LowerChangeTaggedToBit(node, *effect, *control);
+      break;
+    case IrOpcode::kChangeTaggedToInt32:
+      state = LowerChangeTaggedToInt32(node, *effect, *control);
+      break;
+    case IrOpcode::kChangeTaggedToUint32:
+      state = LowerChangeTaggedToUint32(node, *effect, *control);
+      break;
+    case IrOpcode::kChangeTaggedToFloat64:
+      state = LowerChangeTaggedToFloat64(node, *effect, *control);
+      break;
+    case IrOpcode::kTruncateTaggedToFloat64:
+      state = LowerTruncateTaggedToFloat64(node, *effect, *control);
+      break;
+    case IrOpcode::kCheckBounds:
+      state = LowerCheckBounds(node, frame_state, *effect, *control);
+      break;
+    case IrOpcode::kCheckTaggedPointer:
+      state = LowerCheckTaggedPointer(node, frame_state, *effect, *control);
+      break;
+    case IrOpcode::kCheckTaggedSigned:
+      state = LowerCheckTaggedSigned(node, frame_state, *effect, *control);
+      break;
+    case IrOpcode::kCheckedInt32Add:
+      state = LowerCheckedInt32Add(node, frame_state, *effect, *control);
+      break;
+    case IrOpcode::kCheckedInt32Sub:
+      state = LowerCheckedInt32Sub(node, frame_state, *effect, *control);
+      break;
+    case IrOpcode::kCheckedUint32ToInt32:
+      state = LowerCheckedUint32ToInt32(node, frame_state, *effect, *control);
+      break;
+    case IrOpcode::kCheckedFloat64ToInt32:
+      state = LowerCheckedFloat64ToInt32(node, frame_state, *effect, *control);
+      break;
+    case IrOpcode::kCheckedTaggedToInt32:
+      state = LowerCheckedTaggedToInt32(node, frame_state, *effect, *control);
+      break;
+    case IrOpcode::kCheckedTaggedToFloat64:
+      state = LowerCheckedTaggedToFloat64(node, frame_state, *effect, *control);
+      break;
+    case IrOpcode::kTruncateTaggedToWord32:
+      state = LowerTruncateTaggedToWord32(node, *effect, *control);
+      break;
+    case IrOpcode::kObjectIsCallable:
+      state = LowerObjectIsCallable(node, *effect, *control);
+      break;
+    case IrOpcode::kObjectIsNumber:
+      state = LowerObjectIsNumber(node, *effect, *control);
+      break;
+    case IrOpcode::kObjectIsReceiver:
+      state = LowerObjectIsReceiver(node, *effect, *control);
+      break;
+    case IrOpcode::kObjectIsSmi:
+      state = LowerObjectIsSmi(node, *effect, *control);
+      break;
+    case IrOpcode::kObjectIsString:
+      state = LowerObjectIsString(node, *effect, *control);
+      break;
+    case IrOpcode::kObjectIsUndetectable:
+      state = LowerObjectIsUndetectable(node, *effect, *control);
+      break;
+    case IrOpcode::kStringFromCharCode:
+      state = LowerStringFromCharCode(node, *effect, *control);
+      break;
+    case IrOpcode::kCheckFloat64Hole:
+      state = LowerCheckFloat64Hole(node, frame_state, *effect, *control);
+      break;
+    case IrOpcode::kCheckTaggedHole:
+      state = LowerCheckTaggedHole(node, frame_state, *effect, *control);
+      break;
+    case IrOpcode::kPlainPrimitiveToNumber:
+      state = LowerPlainPrimitiveToNumber(node, *effect, *control);
+      break;
+    case IrOpcode::kPlainPrimitiveToWord32:
+      state = LowerPlainPrimitiveToWord32(node, *effect, *control);
+      break;
+    case IrOpcode::kPlainPrimitiveToFloat64:
+      state = LowerPlainPrimitiveToFloat64(node, *effect, *control);
+      break;
+    default:
+      return false;
+  }
+  NodeProperties::ReplaceUses(node, state.value, state.effect, state.control);
+  *effect = state.effect;
+  *control = state.control;
+  return true;
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerTypeGuard(Node* node, Node* effect,
+                                        Node* control) {
+  Node* value = node->InputAt(0);
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node, Node* effect,
+                                                    Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* value32 = graph()->NewNode(machine()->RoundFloat64ToInt32(), value);
+  Node* check_same = graph()->NewNode(
+      machine()->Float64Equal(), value,
+      graph()->NewNode(machine()->ChangeInt32ToFloat64(), value32));
+  Node* branch_same = graph()->NewNode(common()->Branch(), check_same, control);
+
+  Node* if_smi = graph()->NewNode(common()->IfTrue(), branch_same);
+  Node* vsmi;
+  Node* if_box = graph()->NewNode(common()->IfFalse(), branch_same);
+
+  // Check if {value} is -0.
+  Node* check_zero = graph()->NewNode(machine()->Word32Equal(), value32,
+                                      jsgraph()->Int32Constant(0));
+  Node* branch_zero = graph()->NewNode(common()->Branch(BranchHint::kFalse),
+                                       check_zero, if_smi);
+
+  Node* if_zero = graph()->NewNode(common()->IfTrue(), branch_zero);
+  Node* if_notzero = graph()->NewNode(common()->IfFalse(), branch_zero);
+
+  // In case of 0, we need to check the high bits for the IEEE -0 pattern.
+  Node* check_negative = graph()->NewNode(
+      machine()->Int32LessThan(),
+      graph()->NewNode(machine()->Float64ExtractHighWord32(), value),
+      jsgraph()->Int32Constant(0));
+  Node* branch_negative = graph()->NewNode(common()->Branch(BranchHint::kFalse),
+                                           check_negative, if_zero);
+
+  Node* if_negative = graph()->NewNode(common()->IfTrue(), branch_negative);
+  Node* if_notnegative = graph()->NewNode(common()->IfFalse(), branch_negative);
+
+  // We need to create a box for negative 0.
+  if_smi = graph()->NewNode(common()->Merge(2), if_notzero, if_notnegative);
+  if_box = graph()->NewNode(common()->Merge(2), if_box, if_negative);
+
+  // On 64-bit machines we can just wrap the 32-bit integer in a smi, for 32-bit
+  // machines we need to deal with potential overflow and fallback to boxing.
+  if (machine()->Is64()) {
+    vsmi = ChangeInt32ToSmi(value32);
+  } else {
+    Node* smi_tag = graph()->NewNode(machine()->Int32AddWithOverflow(), value32,
+                                     value32, if_smi);
+
+    Node* check_ovf =
+        graph()->NewNode(common()->Projection(1), smi_tag, if_smi);
+    Node* branch_ovf = graph()->NewNode(common()->Branch(BranchHint::kFalse),
+                                        check_ovf, if_smi);
+
+    Node* if_ovf = graph()->NewNode(common()->IfTrue(), branch_ovf);
+    if_box = graph()->NewNode(common()->Merge(2), if_ovf, if_box);
+
+    if_smi = graph()->NewNode(common()->IfFalse(), branch_ovf);
+    vsmi = graph()->NewNode(common()->Projection(0), smi_tag, if_smi);
+  }
+
+  // Allocate the box for the {value}.
+  ValueEffectControl box = AllocateHeapNumberWithValue(value, effect, if_box);
+
+  control = graph()->NewNode(common()->Merge(2), if_smi, box.control);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
+                           vsmi, box.value, control);
+  effect =
+      graph()->NewNode(common()->EffectPhi(2), effect, box.effect, control);
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerChangeBitToTagged(Node* node, Node* effect,
+                                                Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* branch = graph()->NewNode(common()->Branch(), value, control);
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* vtrue = jsgraph()->TrueConstant();
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Node* vfalse = jsgraph()->FalseConstant();
+
+  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
+                           vtrue, vfalse, control);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerChangeInt31ToTaggedSigned(Node* node,
+                                                        Node* effect,
+                                                        Node* control) {
+  Node* value = node->InputAt(0);
+  value = ChangeInt32ToSmi(value);
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node, Node* effect,
+                                                  Node* control) {
+  Node* value = node->InputAt(0);
+
+  if (machine()->Is64()) {
+    return ValueEffectControl(ChangeInt32ToSmi(value), effect, control);
+  }
+
+  Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value,
+                               control);
+
+  Node* ovf = graph()->NewNode(common()->Projection(1), add, control);
+  Node* branch =
+      graph()->NewNode(common()->Branch(BranchHint::kFalse), ovf, control);
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  ValueEffectControl alloc =
+      AllocateHeapNumberWithValue(ChangeInt32ToFloat64(value), effect, if_true);
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Node* vfalse = graph()->NewNode(common()->Projection(0), add, if_false);
+
+  Node* merge = graph()->NewNode(common()->Merge(2), alloc.control, if_false);
+  Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
+                               alloc.value, vfalse, merge);
+  Node* ephi =
+      graph()->NewNode(common()->EffectPhi(2), alloc.effect, effect, merge);
+
+  return ValueEffectControl(phi, ephi, merge);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerChangeUint32ToTagged(Node* node, Node* effect,
+                                                   Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* check = graph()->NewNode(machine()->Uint32LessThanOrEqual(), value,
+                                 SmiMaxValueConstant());
+  Node* branch =
+      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* vtrue = ChangeUint32ToSmi(value);
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  ValueEffectControl alloc = AllocateHeapNumberWithValue(
+      ChangeUint32ToFloat64(value), effect, if_false);
+
+  Node* merge = graph()->NewNode(common()->Merge(2), if_true, alloc.control);
+  Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
+                               vtrue, alloc.value, merge);
+  Node* ephi =
+      graph()->NewNode(common()->EffectPhi(2), effect, alloc.effect, merge);
+
+  return ValueEffectControl(phi, ephi, merge);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerChangeTaggedSignedToInt32(Node* node,
+                                                        Node* effect,
+                                                        Node* control) {
+  Node* value = node->InputAt(0);
+  value = ChangeSmiToInt32(value);
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerChangeTaggedToBit(Node* node, Node* effect,
+                                                Node* control) {
+  Node* value = node->InputAt(0);
+  value = graph()->NewNode(machine()->WordEqual(), value,
+                           jsgraph()->TrueConstant());
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node, Node* effect,
+                                                  Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* check = ObjectIsSmi(value);
+  Node* branch =
+      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* etrue = effect;
+  Node* vtrue = ChangeSmiToInt32(value);
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Node* efalse = effect;
+  Node* vfalse;
+  {
+    STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
+    vfalse = efalse = graph()->NewNode(
+        simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
+        efalse, if_false);
+    vfalse = graph()->NewNode(machine()->ChangeFloat64ToInt32(), vfalse);
+  }
+
+  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
+                           vtrue, vfalse, control);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerChangeTaggedToUint32(Node* node, Node* effect,
+                                                   Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* check = ObjectIsSmi(value);
+  Node* branch =
+      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* etrue = effect;
+  Node* vtrue = ChangeSmiToInt32(value);
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Node* efalse = effect;
+  Node* vfalse;
+  {
+    STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
+    vfalse = efalse = graph()->NewNode(
+        simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
+        efalse, if_false);
+    vfalse = graph()->NewNode(machine()->ChangeFloat64ToUint32(), vfalse);
+  }
+
+  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
+                           vtrue, vfalse, control);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerChangeTaggedToFloat64(Node* node, Node* effect,
+                                                    Node* control) {
+  return LowerTruncateTaggedToFloat64(node, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerTruncateTaggedToFloat64(Node* node, Node* effect,
+                                                      Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* check = ObjectIsSmi(value);
+  Node* branch =
+      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* etrue = effect;
+  Node* vtrue;
+  {
+    vtrue = ChangeSmiToInt32(value);
+    vtrue = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue);
+  }
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Node* efalse = effect;
+  Node* vfalse;
+  {
+    STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
+    vfalse = efalse = graph()->NewNode(
+        simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
+        efalse, if_false);
+  }
+
+  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+                           vtrue, vfalse, control);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerCheckBounds(Node* node, Node* frame_state,
+                                          Node* effect, Node* control) {
+  Node* index = node->InputAt(0);
+  Node* limit = node->InputAt(1);
+
+  Node* check = graph()->NewNode(machine()->Uint32LessThan(), index, limit);
+  control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check,
+                                      frame_state, effect, control);
+
+  // Make sure the lowered node does not appear in any use lists.
+  node->TrimInputCount(0);
+
+  return ValueEffectControl(index, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerCheckTaggedPointer(Node* node, Node* frame_state,
+                                                 Node* effect, Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* check = ObjectIsSmi(value);
+  control = effect = graph()->NewNode(common()->DeoptimizeIf(), check,
+                                      frame_state, effect, control);
+
+  // Make sure the lowered node does not appear in any use lists.
+  node->TrimInputCount(0);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerCheckTaggedSigned(Node* node, Node* frame_state,
+                                                Node* effect, Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* check = ObjectIsSmi(value);
+  control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check,
+                                      frame_state, effect, control);
+
+  // Make sure the lowered node does not appear in any use lists.
+  node->TrimInputCount(0);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerCheckedInt32Add(Node* node, Node* frame_state,
+                                              Node* effect, Node* control) {
+  Node* lhs = node->InputAt(0);
+  Node* rhs = node->InputAt(1);
+
+  Node* value =
+      graph()->NewNode(machine()->Int32AddWithOverflow(), lhs, rhs, control);
+
+  Node* check = graph()->NewNode(common()->Projection(1), value, control);
+  control = effect = graph()->NewNode(common()->DeoptimizeIf(), check,
+                                      frame_state, effect, control);
+
+  value = graph()->NewNode(common()->Projection(0), value, control);
+
+  // Make sure the lowered node does not appear in any use lists.
+  node->TrimInputCount(0);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerCheckedInt32Sub(Node* node, Node* frame_state,
+                                              Node* effect, Node* control) {
+  Node* lhs = node->InputAt(0);
+  Node* rhs = node->InputAt(1);
+
+  Node* value =
+      graph()->NewNode(machine()->Int32SubWithOverflow(), lhs, rhs, control);
+
+  Node* check = graph()->NewNode(common()->Projection(1), value, control);
+  control = effect = graph()->NewNode(common()->DeoptimizeIf(), check,
+                                      frame_state, effect, control);
+
+  value = graph()->NewNode(common()->Projection(0), value, control);
+
+  // Make sure the lowered node does not appear in any use lists.
+  node->TrimInputCount(0);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node,
+                                                   Node* frame_state,
+                                                   Node* effect,
+                                                   Node* control) {
+  Node* value = node->InputAt(0);
+  Node* max_int = jsgraph()->Int32Constant(std::numeric_limits<int32_t>::max());
+  Node* is_safe =
+      graph()->NewNode(machine()->Uint32LessThanOrEqual(), value, max_int);
+  control = effect = graph()->NewNode(common()->DeoptimizeUnless(), is_safe,
+                                      frame_state, effect, control);
+
+  // Make sure the lowered node does not appear in any use lists.
+  node->TrimInputCount(0);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::BuildCheckedFloat64ToInt32(Node* value,
+                                                    Node* frame_state,
+                                                    Node* effect,
+                                                    Node* control) {
+  Node* value32 = graph()->NewNode(machine()->RoundFloat64ToInt32(), value);
+  Node* check_same = graph()->NewNode(
+      machine()->Float64Equal(), value,
+      graph()->NewNode(machine()->ChangeInt32ToFloat64(), value32));
+  control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check_same,
+                                      frame_state, effect, control);
+
+  // Check if {value} is -0.
+  Node* check_zero = graph()->NewNode(machine()->Word32Equal(), value32,
+                                      jsgraph()->Int32Constant(0));
+  Node* branch_zero = graph()->NewNode(common()->Branch(BranchHint::kFalse),
+                                       check_zero, control);
+
+  Node* if_zero = graph()->NewNode(common()->IfTrue(), branch_zero);
+  Node* if_notzero = graph()->NewNode(common()->IfFalse(), branch_zero);
+
+  // In case of 0, we need to check the high bits for the IEEE -0 pattern.
+  Node* check_negative = graph()->NewNode(
+      machine()->Int32LessThan(),
+      graph()->NewNode(machine()->Float64ExtractHighWord32(), value),
+      jsgraph()->Int32Constant(0));
+
+  Node* deopt_minus_zero = graph()->NewNode(
+      common()->DeoptimizeIf(), check_negative, frame_state, effect, if_zero);
+
+  Node* merge =
+      graph()->NewNode(common()->Merge(2), deopt_minus_zero, if_notzero);
+
+  effect =
+      graph()->NewNode(common()->EffectPhi(2), deopt_minus_zero, effect, merge);
+
+  return ValueEffectControl(value32, effect, merge);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node,
+                                                    Node* frame_state,
+                                                    Node* effect,
+                                                    Node* control) {
+  Node* value = node->InputAt(0);
+
+  // Make sure the lowered node does not appear in any use lists.
+  node->TrimInputCount(0);
+
+  return BuildCheckedFloat64ToInt32(value, frame_state, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node,
+                                                   Node* frame_state,
+                                                   Node* effect,
+                                                   Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* check = ObjectIsSmi(value);
+  Node* branch =
+      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
+
+  // In the Smi case, just convert to int32.
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* etrue = effect;
+  Node* vtrue = ChangeSmiToInt32(value);
+
+  // In the non-Smi case, check the heap numberness, load the number and convert
+  // to int32.
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Node* efalse = effect;
+  Node* vfalse;
+  {
+    Node* value_map = efalse =
+        graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
+                         value, efalse, if_false);
+    Node* check = graph()->NewNode(machine()->WordEqual(), value_map,
+                                   jsgraph()->HeapNumberMapConstant());
+    if_false = efalse = graph()->NewNode(common()->DeoptimizeUnless(), check,
+                                         frame_state, efalse, if_false);
+    vfalse = efalse = graph()->NewNode(
+        simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
+        efalse, if_false);
+    ValueEffectControl state =
+        BuildCheckedFloat64ToInt32(vfalse, frame_state, efalse, if_false);
+    if_false = state.control;
+    efalse = state.effect;
+    vfalse = state.value;
+  }
+
+  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
+                           vtrue, vfalse, control);
+
+  // Make sure the lowered node does not appear in any use lists.
+  node->TrimInputCount(0);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64(
+    Node* value, Node* frame_state, Node* effect, Node* control) {
+  Node* value_map = effect = graph()->NewNode(
+      simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control);
+  Node* check_number = graph()->NewNode(machine()->WordEqual(), value_map,
+                                        jsgraph()->HeapNumberMapConstant());
+
+  Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
+                                  check_number, control);
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* etrue = effect;
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  // For oddballs also contain the numeric value, let us just check that
+  // we have an oddball here.
+  Node* efalse = effect;
+  Node* instance_type = efalse = graph()->NewNode(
+      simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map,
+      efalse, if_false);
+  Node* check_oddball =
+      graph()->NewNode(machine()->Word32Equal(), instance_type,
+                       jsgraph()->Int32Constant(ODDBALL_TYPE));
+  if_false = efalse =
+      graph()->NewNode(common()->DeoptimizeUnless(), check_oddball, frame_state,
+                       efalse, if_false);
+  STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
+
+  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+
+  Node* result = effect = graph()->NewNode(
+      simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
+      effect, control);
+  return ValueEffectControl(result, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node,
+                                                     Node* frame_state,
+                                                     Node* effect,
+                                                     Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* check = ObjectIsSmi(value);
+  Node* branch =
+      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
+
+  // In the Smi case, just convert to int32 and then float64.
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* etrue = effect;
+  Node* vtrue = ChangeSmiToInt32(value);
+  vtrue = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue);
+
+  // Otherwise, check heap numberness and load the number.
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  ValueEffectControl number_state = BuildCheckedHeapNumberOrOddballToFloat64(
+      value, frame_state, effect, if_false);
+
+  Node* merge =
+      graph()->NewNode(common()->Merge(2), if_true, number_state.control);
+  Node* effect_phi = graph()->NewNode(common()->EffectPhi(2), etrue,
+                                      number_state.effect, merge);
+  Node* result =
+      graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), vtrue,
+                       number_state.value, merge);
+
+  // Make sure the lowered node does not appear in any use lists.
+  node->TrimInputCount(0);
+
+  return ValueEffectControl(result, effect_phi, merge);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node, Node* effect,
+                                                     Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* check = ObjectIsSmi(value);
+  Node* branch =
+      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* etrue = effect;
+  Node* vtrue = ChangeSmiToInt32(value);
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Node* efalse = effect;
+  Node* vfalse;
+  {
+    STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
+    vfalse = efalse = graph()->NewNode(
+        simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
+        efalse, if_false);
+    vfalse = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse);
+  }
+
+  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
+                           vtrue, vfalse, control);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerObjectIsCallable(Node* node, Node* effect,
+                                               Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* check = ObjectIsSmi(value);
+  Node* branch =
+      graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* etrue = effect;
+  Node* vtrue = jsgraph()->Int32Constant(0);
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Node* efalse = effect;
+  Node* vfalse;
+  {
+    Node* value_map = efalse =
+        graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
+                         value, efalse, if_false);
+    Node* value_bit_field = efalse = graph()->NewNode(
+        simplified()->LoadField(AccessBuilder::ForMapBitField()), value_map,
+        efalse, if_false);
+    vfalse = graph()->NewNode(
+        machine()->Word32Equal(),
+        jsgraph()->Int32Constant(1 << Map::kIsCallable),
+        graph()->NewNode(
+            machine()->Word32And(), value_bit_field,
+            jsgraph()->Int32Constant((1 << Map::kIsCallable) |
+                                     (1 << Map::kIsUndetectable))));
+  }
+
+  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue,
+                           vfalse, control);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerObjectIsNumber(Node* node, Node* effect,
+                                             Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* check = ObjectIsSmi(value);
+  Node* branch = graph()->NewNode(common()->Branch(), check, control);
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* etrue = effect;
+  Node* vtrue = jsgraph()->Int32Constant(1);
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Node* efalse = effect;
+  Node* vfalse;
+  {
+    Node* value_map = efalse =
+        graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
+                         value, efalse, if_false);
+    vfalse = graph()->NewNode(machine()->WordEqual(), value_map,
+                              jsgraph()->HeapNumberMapConstant());
+  }
+
+  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue,
+                           vfalse, control);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerObjectIsReceiver(Node* node, Node* effect,
+                                               Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* check = ObjectIsSmi(value);
+  Node* branch =
+      graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* etrue = effect;
+  Node* vtrue = jsgraph()->Int32Constant(0);
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Node* efalse = effect;
+  Node* vfalse;
+  {
+    STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
+    Node* value_map = efalse =
+        graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
+                         value, efalse, if_false);
+    Node* value_instance_type = efalse = graph()->NewNode(
+        simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map,
+        efalse, if_false);
+    vfalse = graph()->NewNode(machine()->Uint32LessThanOrEqual(),
+                              jsgraph()->Uint32Constant(FIRST_JS_RECEIVER_TYPE),
+                              value_instance_type);
+  }
+
+  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue,
+                           vfalse, control);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerObjectIsSmi(Node* node, Node* effect,
+                                          Node* control) {
+  Node* value = node->InputAt(0);
+  value = ObjectIsSmi(value);
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerObjectIsString(Node* node, Node* effect,
+                                             Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* check = ObjectIsSmi(value);
+  Node* branch =
+      graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* etrue = effect;
+  Node* vtrue = jsgraph()->Int32Constant(0);
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Node* efalse = effect;
+  Node* vfalse;
+  {
+    Node* value_map = efalse =
+        graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
+                         value, efalse, if_false);
+    Node* value_instance_type = efalse = graph()->NewNode(
+        simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map,
+        efalse, if_false);
+    vfalse = graph()->NewNode(machine()->Uint32LessThan(), value_instance_type,
+                              jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE));
+  }
+
+  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue,
+                           vfalse, control);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerObjectIsUndetectable(Node* node, Node* effect,
+                                                   Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* check = ObjectIsSmi(value);
+  Node* branch =
+      graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* etrue = effect;
+  Node* vtrue = jsgraph()->Int32Constant(0);
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Node* efalse = effect;
+  Node* vfalse;
+  {
+    Node* value_map = efalse =
+        graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
+                         value, efalse, if_false);
+    Node* value_bit_field = efalse = graph()->NewNode(
+        simplified()->LoadField(AccessBuilder::ForMapBitField()), value_map,
+        efalse, if_false);
+    vfalse = graph()->NewNode(
+        machine()->Word32Equal(),
+        graph()->NewNode(
+            machine()->Word32Equal(), jsgraph()->Int32Constant(0),
+            graph()->NewNode(
+                machine()->Word32And(), value_bit_field,
+                jsgraph()->Int32Constant(1 << Map::kIsUndetectable))),
+        jsgraph()->Int32Constant(0));
+  }
+
+  control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+  effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kBit, 2), vtrue,
+                           vfalse, control);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerStringFromCharCode(Node* node, Node* effect,
+                                                 Node* control) {
+  Node* value = node->InputAt(0);
+
+  // Compute the character code.
+  Node* code =
+      graph()->NewNode(machine()->Word32And(), value,
+                       jsgraph()->Int32Constant(String::kMaxUtf16CodeUnit));
+
+  // Check if the {code} is a one-byte char code.
+  Node* check0 =
+      graph()->NewNode(machine()->Int32LessThanOrEqual(), code,
+                       jsgraph()->Int32Constant(String::kMaxOneByteCharCode));
+  Node* branch0 =
+      graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
+
+  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
+  Node* etrue0 = effect;
+  Node* vtrue0;
+  {
+    // Load the isolate wide single character string cache.
+    Node* cache =
+        jsgraph()->HeapConstant(factory()->single_character_string_cache());
+
+    // Compute the {cache} index for {code}.
+    Node* index =
+        machine()->Is32() ? code : graph()->NewNode(
+                                       machine()->ChangeUint32ToUint64(), code);
+
+    // Check if we have an entry for the {code} in the single character string
+    // cache already.
+    Node* entry = etrue0 = graph()->NewNode(
+        simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), cache,
+        index, etrue0, if_true0);
+
+    Node* check1 = graph()->NewNode(machine()->WordEqual(), entry,
+                                    jsgraph()->UndefinedConstant());
+    Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
+                                     check1, if_true0);
+
+    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+    Node* etrue1 = etrue0;
+    Node* vtrue1;
+    {
+      // Allocate a new SeqOneByteString for {code}.
+      vtrue1 = etrue1 = graph()->NewNode(
+          simplified()->Allocate(NOT_TENURED),
+          jsgraph()->Int32Constant(SeqOneByteString::SizeFor(1)), etrue1,
+          if_true1);
+      etrue1 = graph()->NewNode(
+          simplified()->StoreField(AccessBuilder::ForMap()), vtrue1,
+          jsgraph()->HeapConstant(factory()->one_byte_string_map()), etrue1,
+          if_true1);
+      etrue1 = graph()->NewNode(
+          simplified()->StoreField(AccessBuilder::ForNameHashField()), vtrue1,
+          jsgraph()->IntPtrConstant(Name::kEmptyHashField), etrue1, if_true1);
+      etrue1 = graph()->NewNode(
+          simplified()->StoreField(AccessBuilder::ForStringLength()), vtrue1,
+          jsgraph()->SmiConstant(1), etrue1, if_true1);
+      etrue1 = graph()->NewNode(
+          machine()->Store(StoreRepresentation(MachineRepresentation::kWord8,
+                                               kNoWriteBarrier)),
+          vtrue1, jsgraph()->IntPtrConstant(SeqOneByteString::kHeaderSize -
+                                            kHeapObjectTag),
+          code, etrue1, if_true1);
+
+      // Remember it in the {cache}.
+      etrue1 = graph()->NewNode(
+          simplified()->StoreElement(AccessBuilder::ForFixedArrayElement()),
+          cache, index, vtrue1, etrue1, if_true1);
+    }
+
+    // Use the {entry} from the {cache}.
+    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+    Node* efalse1 = etrue0;
+    Node* vfalse1 = entry;
+
+    if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+    etrue0 =
+        graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0);
+    vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
+                              vtrue1, vfalse1, if_true0);
+  }
+
+  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
+  Node* efalse0 = effect;
+  Node* vfalse0;
+  {
+    // Allocate a new SeqTwoByteString for {code}.
+    vfalse0 = efalse0 =
+        graph()->NewNode(simplified()->Allocate(NOT_TENURED),
+                         jsgraph()->Int32Constant(SeqTwoByteString::SizeFor(1)),
+                         efalse0, if_false0);
+    efalse0 = graph()->NewNode(
+        simplified()->StoreField(AccessBuilder::ForMap()), vfalse0,
+        jsgraph()->HeapConstant(factory()->string_map()), efalse0, if_false0);
+    efalse0 = graph()->NewNode(
+        simplified()->StoreField(AccessBuilder::ForNameHashField()), vfalse0,
+        jsgraph()->IntPtrConstant(Name::kEmptyHashField), efalse0, if_false0);
+    efalse0 = graph()->NewNode(
+        simplified()->StoreField(AccessBuilder::ForStringLength()), vfalse0,
+        jsgraph()->SmiConstant(1), efalse0, if_false0);
+    efalse0 = graph()->NewNode(
+        machine()->Store(StoreRepresentation(MachineRepresentation::kWord16,
+                                             kNoWriteBarrier)),
+        vfalse0, jsgraph()->IntPtrConstant(SeqTwoByteString::kHeaderSize -
+                                           kHeapObjectTag),
+        code, efalse0, if_false0);
+  }
+
+  control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
+  effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
+                           vtrue0, vfalse0, control);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerCheckFloat64Hole(Node* node, Node* frame_state,
+                                               Node* effect, Node* control) {
+  // If we reach this point w/o eliminating the {node} that's marked
+  // with allow-return-hole, we cannot do anything, so just deoptimize
+  // in case of the hole NaN (similar to Crankshaft).
+  Node* value = node->InputAt(0);
+  Node* check = graph()->NewNode(
+      machine()->Word32Equal(),
+      graph()->NewNode(machine()->Float64ExtractHighWord32(), value),
+      jsgraph()->Int32Constant(kHoleNanUpper32));
+  control = effect = graph()->NewNode(common()->DeoptimizeIf(), check,
+                                      frame_state, effect, control);
+
+  // Make sure the lowered node does not appear in any use lists.
+  node->TrimInputCount(0);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerCheckTaggedHole(Node* node, Node* frame_state,
+                                              Node* effect, Node* control) {
+  CheckTaggedHoleMode mode = CheckTaggedHoleModeOf(node->op());
+  Node* value = node->InputAt(0);
+  Node* check = graph()->NewNode(machine()->WordEqual(), value,
+                                 jsgraph()->TheHoleConstant());
+  switch (mode) {
+    case CheckTaggedHoleMode::kConvertHoleToUndefined:
+      value = graph()->NewNode(
+          common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
+          check, jsgraph()->UndefinedConstant(), value);
+      break;
+    case CheckTaggedHoleMode::kNeverReturnHole:
+      control = effect = graph()->NewNode(common()->DeoptimizeIf(), check,
+                                          frame_state, effect, control);
+      break;
+  }
+
+  // Make sure the lowered node does not appear in any use lists.
+  node->TrimInputCount(0);
+
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::AllocateHeapNumberWithValue(Node* value, Node* effect,
+                                                     Node* control) {
+  Node* result = effect = graph()->NewNode(
+      simplified()->Allocate(NOT_TENURED),
+      jsgraph()->Int32Constant(HeapNumber::kSize), effect, control);
+  effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
+                            result, jsgraph()->HeapNumberMapConstant(), effect,
+                            control);
+  effect = graph()->NewNode(
+      simplified()->StoreField(AccessBuilder::ForHeapNumberValue()), result,
+      value, effect, control);
+  return ValueEffectControl(result, effect, control);
+}
+
+Node* EffectControlLinearizer::ChangeInt32ToSmi(Node* value) {
+  if (machine()->Is64()) {
+    value = graph()->NewNode(machine()->ChangeInt32ToInt64(), value);
+  }
+  return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant());
+}
+
+Node* EffectControlLinearizer::ChangeUint32ToSmi(Node* value) {
+  if (machine()->Is64()) {
+    value = graph()->NewNode(machine()->ChangeUint32ToUint64(), value);
+  }
+  return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant());
+}
+
+Node* EffectControlLinearizer::ChangeInt32ToFloat64(Node* value) {
+  return graph()->NewNode(machine()->ChangeInt32ToFloat64(), value);
+}
+
+Node* EffectControlLinearizer::ChangeUint32ToFloat64(Node* value) {
+  return graph()->NewNode(machine()->ChangeUint32ToFloat64(), value);
+}
+
+Node* EffectControlLinearizer::ChangeSmiToInt32(Node* value) {
+  value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant());
+  if (machine()->Is64()) {
+    value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value);
+  }
+  return value;
+}
+Node* EffectControlLinearizer::ObjectIsSmi(Node* value) {
+  return graph()->NewNode(
+      machine()->WordEqual(),
+      graph()->NewNode(machine()->WordAnd(), value,
+                       jsgraph()->IntPtrConstant(kSmiTagMask)),
+      jsgraph()->IntPtrConstant(kSmiTag));
+}
+
+Node* EffectControlLinearizer::SmiMaxValueConstant() {
+  return jsgraph()->Int32Constant(Smi::kMaxValue);
+}
+
+Node* EffectControlLinearizer::SmiShiftBitsConstant() {
+  return jsgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerPlainPrimitiveToNumber(Node* node, Node* effect,
+                                                     Node* control) {
+  Node* value = node->InputAt(0);
+  Node* result = effect =
+      graph()->NewNode(ToNumberOperator(), jsgraph()->ToNumberBuiltinConstant(),
+                       value, jsgraph()->NoContextConstant(), effect, control);
+  return ValueEffectControl(result, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerPlainPrimitiveToWord32(Node* node, Node* effect,
+                                                     Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* check0 = ObjectIsSmi(value);
+  Node* branch0 =
+      graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
+
+  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
+  Node* etrue0 = effect;
+  Node* vtrue0 = ChangeSmiToInt32(value);
+
+  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
+  Node* efalse0 = effect;
+  Node* vfalse0;
+  {
+    vfalse0 = efalse0 = graph()->NewNode(
+        ToNumberOperator(), jsgraph()->ToNumberBuiltinConstant(), value,
+        jsgraph()->NoContextConstant(), efalse0, if_false0);
+
+    Node* check1 = ObjectIsSmi(vfalse0);
+    Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
+
+    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+    Node* etrue1 = efalse0;
+    Node* vtrue1 = ChangeSmiToInt32(vfalse0);
+
+    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+    Node* efalse1 = efalse0;
+    Node* vfalse1;
+    {
+      vfalse1 = efalse1 = graph()->NewNode(
+          simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
+          efalse1, if_false1);
+      vfalse1 = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse1);
+    }
+
+    if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+    efalse0 =
+        graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
+    vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
+                               vtrue1, vfalse1, if_false0);
+  }
+
+  control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
+  effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
+                           vtrue0, vfalse0, control);
+  return ValueEffectControl(value, effect, control);
+}
+
+EffectControlLinearizer::ValueEffectControl
+EffectControlLinearizer::LowerPlainPrimitiveToFloat64(Node* node, Node* effect,
+                                                      Node* control) {
+  Node* value = node->InputAt(0);
+
+  Node* check0 = ObjectIsSmi(value);
+  Node* branch0 =
+      graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
+
+  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
+  Node* etrue0 = effect;
+  Node* vtrue0;
+  {
+    vtrue0 = ChangeSmiToInt32(value);
+    vtrue0 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue0);
+  }
+
+  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
+  Node* efalse0 = effect;
+  Node* vfalse0;
+  {
+    vfalse0 = efalse0 = graph()->NewNode(
+        ToNumberOperator(), jsgraph()->ToNumberBuiltinConstant(), value,
+        jsgraph()->NoContextConstant(), efalse0, if_false0);
+
+    Node* check1 = ObjectIsSmi(vfalse0);
+    Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
+
+    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+    Node* etrue1 = efalse0;
+    Node* vtrue1;
+    {
+      vtrue1 = ChangeSmiToInt32(vfalse0);
+      vtrue1 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue1);
+    }
+
+    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+    Node* efalse1 = efalse0;
+    Node* vfalse1;
+    {
+      vfalse1 = efalse1 = graph()->NewNode(
+          simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
+          efalse1, if_false1);
+    }
+
+    if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+    efalse0 =
+        graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
+    vfalse0 =
+        graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+                         vtrue1, vfalse1, if_false0);
+  }
+
+  control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
+  effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+                           vtrue0, vfalse0, control);
+  return ValueEffectControl(value, effect, control);
+}
+
+Factory* EffectControlLinearizer::factory() const {
+  return isolate()->factory();
+}
+
+Isolate* EffectControlLinearizer::isolate() const {
+  return jsgraph()->isolate();
+}
+
+Operator const* EffectControlLinearizer::ToNumberOperator() {
+  if (!to_number_operator_.is_set()) {
+    Callable callable = CodeFactory::ToNumber(isolate());
+    CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
+    CallDescriptor* desc = Linkage::GetStubCallDescriptor(
+        isolate(), graph()->zone(), callable.descriptor(), 0, flags,
+        Operator::kNoThrow);
+    to_number_operator_.set(common()->Call(desc));
+  }
+  return to_number_operator_.get();
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/src/compiler/effect-control-linearizer.h b/src/compiler/effect-control-linearizer.h
new file mode 100644
index 0000000..280b4b7
--- /dev/null
+++ b/src/compiler/effect-control-linearizer.h
@@ -0,0 +1,156 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_EFFECT_CONTROL_LINEARIZER_H_
+#define V8_COMPILER_EFFECT_CONTROL_LINEARIZER_H_
+
+#include "src/compiler/common-operator.h"
+#include "src/compiler/node.h"
+#include "src/compiler/simplified-operator.h"
+
+namespace v8 {
+namespace internal {
+
+class Zone;
+
+namespace compiler {
+
+class CommonOperatorBuilder;
+class SimplifiedOperatorBuilder;
+class MachineOperatorBuilder;
+class JSGraph;
+class Graph;
+class Schedule;
+
+class EffectControlLinearizer {
+ public:
+  EffectControlLinearizer(JSGraph* graph, Schedule* schedule, Zone* temp_zone);
+
+  void Run();
+
+ private:
+  void ProcessNode(Node* node, Node** frame_state, Node** effect,
+                   Node** control);
+
+  struct ValueEffectControl {
+    Node* value;
+    Node* effect;
+    Node* control;
+    ValueEffectControl(Node* value, Node* effect, Node* control)
+        : value(value), effect(effect), control(control) {}
+  };
+
+  bool TryWireInStateEffect(Node* node, Node* frame_state, Node** effect,
+                            Node** control);
+  ValueEffectControl LowerTypeGuard(Node* node, Node* effect, Node* control);
+  ValueEffectControl LowerChangeBitToTagged(Node* node, Node* effect,
+                                            Node* control);
+  ValueEffectControl LowerChangeInt31ToTaggedSigned(Node* node, Node* effect,
+                                                    Node* control);
+  ValueEffectControl LowerChangeInt32ToTagged(Node* node, Node* effect,
+                                              Node* control);
+  ValueEffectControl LowerChangeUint32ToTagged(Node* node, Node* effect,
+                                               Node* control);
+  ValueEffectControl LowerChangeFloat64ToTagged(Node* node, Node* effect,
+                                                Node* control);
+  ValueEffectControl LowerChangeTaggedSignedToInt32(Node* node, Node* effect,
+                                                    Node* control);
+  ValueEffectControl LowerChangeTaggedToBit(Node* node, Node* effect,
+                                            Node* control);
+  ValueEffectControl LowerChangeTaggedToInt32(Node* node, Node* effect,
+                                              Node* control);
+  ValueEffectControl LowerChangeTaggedToUint32(Node* node, Node* effect,
+                                               Node* control);
+  ValueEffectControl LowerCheckBounds(Node* node, Node* frame_state,
+                                      Node* effect, Node* control);
+  ValueEffectControl LowerCheckTaggedPointer(Node* node, Node* frame_state,
+                                             Node* effect, Node* control);
+  ValueEffectControl LowerCheckTaggedSigned(Node* node, Node* frame_state,
+                                            Node* effect, Node* control);
+  ValueEffectControl LowerCheckedInt32Add(Node* node, Node* frame_state,
+                                          Node* effect, Node* control);
+  ValueEffectControl LowerCheckedInt32Sub(Node* node, Node* frame_state,
+                                          Node* effect, Node* control);
+  ValueEffectControl LowerCheckedUint32ToInt32(Node* node, Node* frame_state,
+                                               Node* effect, Node* control);
+  ValueEffectControl LowerCheckedFloat64ToInt32(Node* node, Node* frame_state,
+                                                Node* effect, Node* control);
+  ValueEffectControl LowerCheckedTaggedToInt32(Node* node, Node* frame_state,
+                                               Node* effect, Node* control);
+  ValueEffectControl LowerCheckedTaggedToFloat64(Node* node, Node* frame_state,
+                                                 Node* effect, Node* control);
+  ValueEffectControl LowerChangeTaggedToFloat64(Node* node, Node* effect,
+                                                Node* control);
+  ValueEffectControl LowerTruncateTaggedToFloat64(Node* node, Node* effect,
+                                                  Node* control);
+  ValueEffectControl LowerTruncateTaggedToWord32(Node* node, Node* effect,
+                                                 Node* control);
+  ValueEffectControl LowerObjectIsCallable(Node* node, Node* effect,
+                                           Node* control);
+  ValueEffectControl LowerObjectIsNumber(Node* node, Node* effect,
+                                         Node* control);
+  ValueEffectControl LowerObjectIsReceiver(Node* node, Node* effect,
+                                           Node* control);
+  ValueEffectControl LowerObjectIsSmi(Node* node, Node* effect, Node* control);
+  ValueEffectControl LowerObjectIsString(Node* node, Node* effect,
+                                         Node* control);
+  ValueEffectControl LowerObjectIsUndetectable(Node* node, Node* effect,
+                                               Node* control);
+  ValueEffectControl LowerStringFromCharCode(Node* node, Node* effect,
+                                             Node* control);
+  ValueEffectControl LowerCheckFloat64Hole(Node* node, Node* frame_state,
+                                           Node* effect, Node* control);
+  ValueEffectControl LowerCheckTaggedHole(Node* node, Node* frame_state,
+                                          Node* effect, Node* control);
+  ValueEffectControl LowerPlainPrimitiveToNumber(Node* node, Node* effect,
+                                                 Node* control);
+  ValueEffectControl LowerPlainPrimitiveToWord32(Node* node, Node* effect,
+                                                 Node* control);
+  ValueEffectControl LowerPlainPrimitiveToFloat64(Node* node, Node* effect,
+                                                  Node* control);
+
+  ValueEffectControl AllocateHeapNumberWithValue(Node* node, Node* effect,
+                                                 Node* control);
+  ValueEffectControl BuildCheckedFloat64ToInt32(Node* value, Node* frame_state,
+                                                Node* effect, Node* control);
+  ValueEffectControl BuildCheckedHeapNumberOrOddballToFloat64(Node* value,
+                                                              Node* frame_state,
+                                                              Node* effect,
+                                                              Node* control);
+
+  Node* ChangeInt32ToSmi(Node* value);
+  Node* ChangeUint32ToSmi(Node* value);
+  Node* ChangeInt32ToFloat64(Node* value);
+  Node* ChangeUint32ToFloat64(Node* value);
+  Node* ChangeSmiToInt32(Node* value);
+  Node* ObjectIsSmi(Node* value);
+
+  Node* SmiMaxValueConstant();
+  Node* SmiShiftBitsConstant();
+
+  Factory* factory() const;
+  Isolate* isolate() const;
+  JSGraph* jsgraph() const { return js_graph_; }
+  Graph* graph() const;
+  Schedule* schedule() const { return schedule_; }
+  Zone* temp_zone() const { return temp_zone_; }
+  CommonOperatorBuilder* common() const;
+  SimplifiedOperatorBuilder* simplified() const;
+  MachineOperatorBuilder* machine() const;
+
+  Operator const* ToNumberOperator();
+
+  JSGraph* js_graph_;
+  Schedule* schedule_;
+  Zone* temp_zone_;
+  RegionObservability region_observability_ = RegionObservability::kObservable;
+
+  SetOncePointer<Operator const> to_number_operator_;
+};
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_COMPILER_EFFECT_CONTROL_LINEARIZER_H_
diff --git a/src/compiler/escape-analysis-reducer.cc b/src/compiler/escape-analysis-reducer.cc
index 313b639..8402366 100644
--- a/src/compiler/escape-analysis-reducer.cc
+++ b/src/compiler/escape-analysis-reducer.cc
@@ -4,6 +4,7 @@
 
 #include "src/compiler/escape-analysis-reducer.h"
 
+#include "src/compiler/all-nodes.h"
 #include "src/compiler/js-graph.h"
 #include "src/counters.h"
 
@@ -28,8 +29,7 @@
       escape_analysis_(escape_analysis),
       zone_(zone),
       fully_reduced_(static_cast<int>(jsgraph->graph()->NodeCount() * 2), zone),
-      exists_virtual_allocate_(true) {}
-
+      exists_virtual_allocate_(escape_analysis->ExistsVirtualAllocate()) {}
 
 Reduction EscapeAnalysisReducer::Reduce(Node* node) {
   if (node->id() < static_cast<NodeId>(fully_reduced_.length()) &&
@@ -105,7 +105,7 @@
     fully_reduced_.Add(node->id());
   }
   if (Node* rep = escape_analysis()->GetReplacement(node)) {
-    counters()->turbo_escape_loads_replaced()->Increment();
+    isolate()->counters()->turbo_escape_loads_replaced()->Increment();
     TRACE("Replaced #%d (%s) with #%d (%s)\n", node->id(),
           node->op()->mnemonic(), rep->id(), rep->op()->mnemonic());
     ReplaceWithValue(node, rep);
@@ -138,7 +138,7 @@
   }
   if (escape_analysis()->IsVirtual(node)) {
     RelaxEffectsAndControls(node);
-    counters()->turbo_escape_allocs_replaced()->Increment();
+    isolate()->counters()->turbo_escape_allocs_replaced()->Increment();
     TRACE("Removed allocate #%d from effect chain\n", node->id());
     return Changed(node);
   }
@@ -328,40 +328,19 @@
 }
 
 
-Counters* EscapeAnalysisReducer::counters() const {
-  return jsgraph_->isolate()->counters();
-}
-
-
-class EscapeAnalysisVerifier final : public AdvancedReducer {
- public:
-  EscapeAnalysisVerifier(Editor* editor, EscapeAnalysis* escape_analysis)
-      : AdvancedReducer(editor), escape_analysis_(escape_analysis) {}
-
-  Reduction Reduce(Node* node) final {
-    switch (node->opcode()) {
-      case IrOpcode::kAllocate:
-        CHECK(!escape_analysis_->IsVirtual(node));
-        break;
-      default:
-        break;
-    }
-    return NoChange();
-  }
-
- private:
-  EscapeAnalysis* escape_analysis_;
-};
-
 void EscapeAnalysisReducer::VerifyReplacement() const {
 #ifdef DEBUG
-  GraphReducer graph_reducer(zone(), jsgraph()->graph());
-  EscapeAnalysisVerifier verifier(&graph_reducer, escape_analysis());
-  graph_reducer.AddReducer(&verifier);
-  graph_reducer.ReduceGraph();
+  AllNodes all(zone(), jsgraph()->graph());
+  for (Node* node : all.live) {
+    if (node->opcode() == IrOpcode::kAllocate) {
+      CHECK(!escape_analysis_->IsVirtual(node));
+    }
+  }
 #endif  // DEBUG
 }
 
+Isolate* EscapeAnalysisReducer::isolate() const { return jsgraph_->isolate(); }
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/src/compiler/escape-analysis-reducer.h b/src/compiler/escape-analysis-reducer.h
index 12487b1..ad67479 100644
--- a/src/compiler/escape-analysis-reducer.h
+++ b/src/compiler/escape-analysis-reducer.h
@@ -9,29 +9,22 @@
 #include "src/compiler/escape-analysis.h"
 #include "src/compiler/graph-reducer.h"
 
-
 namespace v8 {
 namespace internal {
-
-// Forward declarations.
-class Counters;
-
-
 namespace compiler {
 
 // Forward declarations.
 class JSGraph;
 
-
 class EscapeAnalysisReducer final : public AdvancedReducer {
  public:
   EscapeAnalysisReducer(Editor* editor, JSGraph* jsgraph,
                         EscapeAnalysis* escape_analysis, Zone* zone);
 
   Reduction Reduce(Node* node) final;
-  void SetExistsVirtualAllocate(bool exists) {
-    exists_virtual_allocate_ = exists;
-  }
+
+  // Verifies that all virtual allocation nodes have been dealt with. Run it
+  // after this reducer has been applied. Has no effect in release mode.
   void VerifyReplacement() const;
 
  private:
@@ -50,12 +43,12 @@
   JSGraph* jsgraph() const { return jsgraph_; }
   EscapeAnalysis* escape_analysis() const { return escape_analysis_; }
   Zone* zone() const { return zone_; }
-  Counters* counters() const;
+  Isolate* isolate() const;
 
   JSGraph* const jsgraph_;
   EscapeAnalysis* escape_analysis_;
   Zone* const zone_;
-  // _visited marks nodes we already processed (allocs, loads, stores)
+  // This bit vector marks nodes we already processed (allocs, loads, stores)
   // and nodes that do not need a visit from ReduceDeoptState etc.
   BitVector fully_reduced_;
   bool exists_virtual_allocate_;
diff --git a/src/compiler/escape-analysis.cc b/src/compiler/escape-analysis.cc
index b1a12b2..9409a27 100644
--- a/src/compiler/escape-analysis.cc
+++ b/src/compiler/escape-analysis.cc
@@ -24,7 +24,7 @@
 namespace internal {
 namespace compiler {
 
-using Alias = EscapeStatusAnalysis::Alias;
+typedef NodeId Alias;
 
 #ifdef DEBUG
 #define TRACE(...)                                    \
@@ -35,6 +35,90 @@
 #define TRACE(...)
 #endif
 
+// EscapeStatusAnalysis determines for each allocation whether it escapes.
+class EscapeStatusAnalysis : public ZoneObject {
+ public:
+  enum Status {
+    kUnknown = 0u,
+    kTracked = 1u << 0,
+    kEscaped = 1u << 1,
+    kOnStack = 1u << 2,
+    kVisited = 1u << 3,
+    // A node is dangling, if it is a load of some kind, and does not have
+    // an effect successor.
+    kDanglingComputed = 1u << 4,
+    kDangling = 1u << 5,
+    // A node is is an effect branch point, if it has more than 2 non-dangling
+    // effect successors.
+    kBranchPointComputed = 1u << 6,
+    kBranchPoint = 1u << 7,
+    kInQueue = 1u << 8
+  };
+  typedef base::Flags<Status, uint16_t> StatusFlags;
+
+  void RunStatusAnalysis();
+
+  bool IsVirtual(Node* node);
+  bool IsEscaped(Node* node);
+  bool IsAllocation(Node* node);
+
+  bool IsInQueue(NodeId id);
+  void SetInQueue(NodeId id, bool on_stack);
+
+  void DebugPrint();
+
+  EscapeStatusAnalysis(EscapeAnalysis* object_analysis, Graph* graph,
+                       Zone* zone);
+  void EnqueueForStatusAnalysis(Node* node);
+  bool SetEscaped(Node* node);
+  bool IsEffectBranchPoint(Node* node);
+  bool IsDanglingEffectNode(Node* node);
+  void ResizeStatusVector();
+  size_t GetStatusVectorSize();
+  bool IsVirtual(NodeId id);
+
+  Graph* graph() const { return graph_; }
+  void AssignAliases();
+  Alias GetAlias(NodeId id) const { return aliases_[id]; }
+  const ZoneVector<Alias>& GetAliasMap() const { return aliases_; }
+  Alias AliasCount() const { return next_free_alias_; }
+  static const Alias kNotReachable;
+  static const Alias kUntrackable;
+
+  bool IsNotReachable(Node* node);
+
+ private:
+  void Process(Node* node);
+  void ProcessAllocate(Node* node);
+  void ProcessFinishRegion(Node* node);
+  void ProcessStoreField(Node* node);
+  void ProcessStoreElement(Node* node);
+  bool CheckUsesForEscape(Node* node, bool phi_escaping = false) {
+    return CheckUsesForEscape(node, node, phi_escaping);
+  }
+  bool CheckUsesForEscape(Node* node, Node* rep, bool phi_escaping = false);
+  void RevisitUses(Node* node);
+  void RevisitInputs(Node* node);
+
+  Alias NextAlias() { return next_free_alias_++; }
+
+  bool HasEntry(Node* node);
+
+  bool IsAllocationPhi(Node* node);
+
+  ZoneVector<Node*> stack_;
+  EscapeAnalysis* object_analysis_;
+  Graph* const graph_;
+  ZoneVector<StatusFlags> status_;
+  Alias next_free_alias_;
+  ZoneVector<Node*> status_stack_;
+  ZoneVector<Alias> aliases_;
+
+  DISALLOW_COPY_AND_ASSIGN(EscapeStatusAnalysis);
+};
+
+DEFINE_OPERATORS_FOR_FLAGS(EscapeStatusAnalysis::StatusFlags)
+
 const Alias EscapeStatusAnalysis::kNotReachable =
     std::numeric_limits<Alias>::max();
 const Alias EscapeStatusAnalysis::kUntrackable =
@@ -475,14 +559,11 @@
     : stack_(zone),
       object_analysis_(object_analysis),
       graph_(graph),
-      zone_(zone),
       status_(zone),
       next_free_alias_(0),
       status_stack_(zone),
       aliases_(zone) {}
 
-EscapeStatusAnalysis::~EscapeStatusAnalysis() {}
-
 bool EscapeStatusAnalysis::HasEntry(Node* node) {
   return status_[node->id()] & (kTracked | kEscaped);
 }
@@ -712,6 +793,13 @@
         }
         break;
       case IrOpcode::kSelect:
+      case IrOpcode::kTypeGuard:
+      // TODO(mstarzinger): The following list of operators will eventually be
+      // handled by the EscapeAnalysisReducer (similar to ObjectIsSmi).
+      case IrOpcode::kObjectIsCallable:
+      case IrOpcode::kObjectIsNumber:
+      case IrOpcode::kObjectIsString:
+      case IrOpcode::kObjectIsUndetectable:
         if (SetEscaped(rep)) {
           TRACE("Setting #%d (%s) to escaped because of use by #%d (%s)\n",
                 rep->id(), rep->op()->mnemonic(), use->id(),
@@ -721,7 +809,8 @@
         break;
       default:
         if (use->op()->EffectInputCount() == 0 &&
-            uses->op()->EffectInputCount() > 0) {
+            uses->op()->EffectInputCount() > 0 &&
+            !IrOpcode::IsJsOpcode(use->opcode())) {
           TRACE("Encountered unaccounted use by #%d (%s)\n", use->id(),
                 use->op()->mnemonic());
           UNREACHABLE();
@@ -759,8 +848,10 @@
 
 EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common,
                                Zone* zone)
-    : status_analysis_(this, graph, zone),
+    : zone_(zone),
+      slot_not_analyzed_(graph->NewNode(common->NumberConstant(0x1c0debad))),
       common_(common),
+      status_analysis_(new (zone) EscapeStatusAnalysis(this, graph, zone)),
       virtual_states_(zone),
       replacements_(zone),
       cache_(nullptr) {}
@@ -769,13 +860,13 @@
 
 void EscapeAnalysis::Run() {
   replacements_.resize(graph()->NodeCount());
-  status_analysis_.AssignAliases();
-  if (status_analysis_.AliasCount() > 0) {
+  status_analysis_->AssignAliases();
+  if (status_analysis_->AliasCount() > 0) {
     cache_ = new (zone()) MergeCache(zone());
     replacements_.resize(graph()->NodeCount());
-    status_analysis_.ResizeStatusVector();
+    status_analysis_->ResizeStatusVector();
     RunObjectAnalysis();
-    status_analysis_.RunStatusAnalysis();
+    status_analysis_->RunStatusAnalysis();
   }
 }
 
@@ -853,11 +944,11 @@
   while (!queue.empty()) {
     Node* node = queue.back();
     queue.pop_back();
-    status_analysis_.SetInQueue(node->id(), false);
+    status_analysis_->SetInQueue(node->id(), false);
     if (Process(node)) {
       for (Edge edge : node->use_edges()) {
         Node* use = edge.from();
-        if (IsNotReachable(use)) {
+        if (status_analysis_->IsNotReachable(use)) {
           continue;
         }
         if (NodeProperties::IsEffectEdge(edge)) {
@@ -865,14 +956,14 @@
           // We need DFS do avoid some duplication of VirtualStates and
           // VirtualObjects, and we want to delay phis to improve performance.
           if (use->opcode() == IrOpcode::kEffectPhi) {
-            if (!status_analysis_.IsInQueue(use->id())) {
+            if (!status_analysis_->IsInQueue(use->id())) {
               queue.push_front(use);
             }
           } else if ((use->opcode() != IrOpcode::kLoadField &&
                       use->opcode() != IrOpcode::kLoadElement) ||
-                     !IsDanglingEffectNode(use)) {
-            if (!status_analysis_.IsInQueue(use->id())) {
-              status_analysis_.SetInQueue(use->id(), true);
+                     !status_analysis_->IsDanglingEffectNode(use)) {
+            if (!status_analysis_->IsInQueue(use->id())) {
+              status_analysis_->SetInQueue(use->id(), true);
               queue.push_back(use);
             }
           } else {
@@ -1008,8 +1099,8 @@
           if (!obj->AllFieldsClear()) {
             obj = CopyForModificationAt(obj, state, node);
             obj->ClearAllFields();
-            TRACE("Cleared all fields of @%d:#%d\n", GetAlias(obj->id()),
-                  obj->id());
+            TRACE("Cleared all fields of @%d:#%d\n",
+                  status_analysis_->GetAlias(obj->id()), obj->id());
           }
         }
         break;
@@ -1035,7 +1126,7 @@
                                                      Node* node) {
   if (obj->NeedCopyForModification()) {
     state = CopyForModificationAt(state, node);
-    return state->Copy(obj, GetAlias(obj->id()));
+    return state->Copy(obj, status_analysis_->GetAlias(obj->id()));
   }
   return obj;
 }
@@ -1045,7 +1136,8 @@
 #ifdef DEBUG
   if (node->opcode() != IrOpcode::kLoadField &&
       node->opcode() != IrOpcode::kLoadElement &&
-      node->opcode() != IrOpcode::kLoad && IsDanglingEffectNode(node)) {
+      node->opcode() != IrOpcode::kLoad &&
+      status_analysis_->IsDanglingEffectNode(node)) {
     PrintF("Dangeling effect node: #%d (%s)\n", node->id(),
            node->op()->mnemonic());
     UNREACHABLE();
@@ -1062,7 +1154,7 @@
           static_cast<void*>(virtual_states_[effect->id()]),
           effect->op()->mnemonic(), effect->id(), node->op()->mnemonic(),
           node->id());
-    if (IsEffectBranchPoint(effect) ||
+    if (status_analysis_->IsEffectBranchPoint(effect) ||
         OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
       virtual_states_[node->id()]->SetCopyRequired();
       TRACE(", effect input %s#%d is branch point", effect->op()->mnemonic(),
@@ -1075,7 +1167,7 @@
 void EscapeAnalysis::ProcessStart(Node* node) {
   DCHECK_EQ(node->opcode(), IrOpcode::kStart);
   virtual_states_[node->id()] =
-      new (zone()) VirtualState(node, zone(), AliasCount());
+      new (zone()) VirtualState(node, zone(), status_analysis_->AliasCount());
 }
 
 bool EscapeAnalysis::ProcessEffectPhi(Node* node) {
@@ -1084,7 +1176,8 @@
 
   VirtualState* mergeState = virtual_states_[node->id()];
   if (!mergeState) {
-    mergeState = new (zone()) VirtualState(node, zone(), AliasCount());
+    mergeState =
+        new (zone()) VirtualState(node, zone(), status_analysis_->AliasCount());
     virtual_states_[node->id()] = mergeState;
     changed = true;
     TRACE("Effect Phi #%d got new virtual state %p.\n", node->id(),
@@ -1102,7 +1195,8 @@
     if (state) {
       cache_->states().push_back(state);
       if (state == mergeState) {
-        mergeState = new (zone()) VirtualState(node, zone(), AliasCount());
+        mergeState = new (zone())
+            VirtualState(node, zone(), status_analysis_->AliasCount());
         virtual_states_[node->id()] = mergeState;
         changed = true;
       }
@@ -1122,7 +1216,7 @@
   TRACE("Merge %s the node.\n", changed ? "changed" : "did not change");
 
   if (changed) {
-    status_analysis_.ResizeStatusVector();
+    status_analysis_->ResizeStatusVector();
   }
   return changed;
 }
@@ -1131,7 +1225,7 @@
   DCHECK_EQ(node->opcode(), IrOpcode::kAllocate);
   ForwardVirtualState(node);
   VirtualState* state = virtual_states_[node->id()];
-  Alias alias = GetAlias(node->id());
+  Alias alias = status_analysis_->GetAlias(node->id());
 
   // Check if we have already processed this node.
   if (state->VirtualObjectFromAlias(alias)) {
@@ -1163,19 +1257,16 @@
   Node* allocation = NodeProperties::GetValueInput(node, 0);
   if (allocation->opcode() == IrOpcode::kAllocate) {
     VirtualState* state = virtual_states_[node->id()];
-    VirtualObject* obj = state->VirtualObjectFromAlias(GetAlias(node->id()));
+    VirtualObject* obj =
+        state->VirtualObjectFromAlias(status_analysis_->GetAlias(node->id()));
     DCHECK_NOT_NULL(obj);
     obj->SetInitialized();
   }
 }
 
-Node* EscapeAnalysis::replacement(NodeId id) {
-  if (id >= replacements_.size()) return nullptr;
-  return replacements_[id];
-}
-
 Node* EscapeAnalysis::replacement(Node* node) {
-  return replacement(node->id());
+  if (node->id() >= replacements_.size()) return nullptr;
+  return replacements_[node->id()];
 }
 
 bool EscapeAnalysis::SetReplacement(Node* node, Node* rep) {
@@ -1206,41 +1297,25 @@
 }
 
 Node* EscapeAnalysis::GetReplacement(Node* node) {
-  return GetReplacement(node->id());
-}
-
-Node* EscapeAnalysis::GetReplacement(NodeId id) {
-  Node* node = nullptr;
-  while (replacement(id)) {
-    node = replacement(id);
-    id = node->id();
+  Node* result = nullptr;
+  while (replacement(node)) {
+    node = result = replacement(node);
   }
-  return node;
+  return result;
 }
 
 bool EscapeAnalysis::IsVirtual(Node* node) {
-  if (node->id() >= status_analysis_.GetStatusVectorSize()) {
+  if (node->id() >= status_analysis_->GetStatusVectorSize()) {
     return false;
   }
-  return status_analysis_.IsVirtual(node);
+  return status_analysis_->IsVirtual(node);
 }
 
 bool EscapeAnalysis::IsEscaped(Node* node) {
-  if (node->id() >= status_analysis_.GetStatusVectorSize()) {
+  if (node->id() >= status_analysis_->GetStatusVectorSize()) {
     return false;
   }
-  return status_analysis_.IsEscaped(node);
-}
-
-bool EscapeAnalysis::SetEscaped(Node* node) {
-  return status_analysis_.SetEscaped(node);
-}
-
-VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) {
-  if (VirtualState* states = virtual_states_[at->id()]) {
-    return states->VirtualObjectFromAlias(GetAlias(id));
-  }
-  return nullptr;
+  return status_analysis_->IsEscaped(node);
 }
 
 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) {
@@ -1253,11 +1328,24 @@
   return false;
 }
 
-int EscapeAnalysis::OffsetFromAccess(Node* node) {
-  DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0);
-  return OpParameter<FieldAccess>(node).offset / kPointerSize;
+namespace {
+
+int OffsetForFieldAccess(Node* node) {
+  FieldAccess access = FieldAccessOf(node->op());
+  DCHECK_EQ(access.offset % kPointerSize, 0);
+  return access.offset / kPointerSize;
 }
 
+int OffsetForElementAccess(Node* node, int index) {
+  ElementAccess access = ElementAccessOf(node->op());
+  DCHECK_GE(ElementSizeLog2Of(access.machine_type.representation()),
+            kPointerSizeLog2);
+  DCHECK_EQ(access.header_size % kPointerSize, 0);
+  return access.header_size / kPointerSize + index;
+}
+
+}  // namespace
+
 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* load,
                                         VirtualState* state) {
   TRACE("Load #%d from phi #%d", load->id(), from->id());
@@ -1269,7 +1357,7 @@
   }
 
   cache_->LoadVirtualObjectsForFieldsFrom(state,
-                                          status_analysis_.GetAliasMap());
+                                          status_analysis_->GetAliasMap());
   if (cache_->objects().size() == cache_->fields().size()) {
     cache_->GetFields(offset);
     if (cache_->fields().size() == cache_->objects().size()) {
@@ -1280,7 +1368,7 @@
         Node* phi = graph()->NewNode(
             common()->Phi(MachineRepresentation::kTagged, value_input_count),
             value_input_count + 1, &cache_->fields().front());
-        status_analysis_.ResizeStatusVector();
+        status_analysis_->ResizeStatusVector();
         SetReplacement(load, phi);
         TRACE(" got phi created.\n");
       } else {
@@ -1300,11 +1388,9 @@
   Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
   VirtualState* state = virtual_states_[node->id()];
   if (VirtualObject* object = GetVirtualObject(state, from)) {
-    int offset = OffsetFromAccess(node);
-    if (!object->IsTracked() ||
-        static_cast<size_t>(offset) >= object->field_count()) {
-      return;
-    }
+    if (!object->IsTracked()) return;
+    int offset = OffsetForFieldAccess(node);
+    if (static_cast<size_t>(offset) >= object->field_count()) return;
     Node* value = object->GetField(offset);
     if (value) {
       value = ResolveReplacement(value);
@@ -1312,8 +1398,8 @@
     // Record that the load has this alias.
     UpdateReplacement(state, node, value);
   } else if (from->opcode() == IrOpcode::kPhi &&
-             OpParameter<FieldAccess>(node).offset % kPointerSize == 0) {
-    int offset = OffsetFromAccess(node);
+             FieldAccessOf(node->op()).offset % kPointerSize == 0) {
+    int offset = OffsetForFieldAccess(node);
     // Only binary phis are supported for now.
     ProcessLoadFromPhi(offset, from, node, state);
   } else {
@@ -1332,19 +1418,11 @@
          index_node->opcode() != IrOpcode::kInt64Constant &&
          index_node->opcode() != IrOpcode::kFloat32Constant &&
          index_node->opcode() != IrOpcode::kFloat64Constant);
-  ElementAccess access = OpParameter<ElementAccess>(node);
   if (index.HasValue()) {
-    int offset = index.Value() + access.header_size / kPointerSize;
     if (VirtualObject* object = GetVirtualObject(state, from)) {
-      CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()),
-               kPointerSizeLog2);
-      CHECK_EQ(access.header_size % kPointerSize, 0);
-
-      if (!object->IsTracked() ||
-          static_cast<size_t>(offset) >= object->field_count()) {
-        return;
-      }
-
+      if (!object->IsTracked()) return;
+      int offset = OffsetForElementAccess(node, index.Value());
+      if (static_cast<size_t>(offset) >= object->field_count()) return;
       Node* value = object->GetField(offset);
       if (value) {
         value = ResolveReplacement(value);
@@ -1352,15 +1430,14 @@
       // Record that the load has this alias.
       UpdateReplacement(state, node, value);
     } else if (from->opcode() == IrOpcode::kPhi) {
-      ElementAccess access = OpParameter<ElementAccess>(node);
-      int offset = index.Value() + access.header_size / kPointerSize;
+      int offset = OffsetForElementAccess(node, index.Value());
       ProcessLoadFromPhi(offset, from, node, state);
     } else {
       UpdateReplacement(state, node, nullptr);
     }
   } else {
     // We have a load from a non-const index, cannot eliminate object.
-    if (SetEscaped(from)) {
+    if (status_analysis_->SetEscaped(from)) {
       TRACE(
           "Setting #%d (%s) to escaped because load element #%d from non-const "
           "index #%d (%s)\n",
@@ -1375,14 +1452,23 @@
   ForwardVirtualState(node);
   Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
   VirtualState* state = virtual_states_[node->id()];
-  VirtualObject* obj = GetVirtualObject(state, to);
-  int offset = OffsetFromAccess(node);
-  if (obj && obj->IsTracked() &&
-      static_cast<size_t>(offset) < obj->field_count()) {
+  if (VirtualObject* object = GetVirtualObject(state, to)) {
+    if (!object->IsTracked()) return;
+    int offset = OffsetForFieldAccess(node);
+    if (static_cast<size_t>(offset) >= object->field_count()) return;
     Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 1));
-    if (obj->GetField(offset) != val) {
-      obj = CopyForModificationAt(obj, state, node);
-      obj->SetField(offset, val);
+    // TODO(mstarzinger): The following is a workaround to not track the code
+    // entry field in virtual JSFunction objects. We only ever store the inner
+    // pointer into the compile lazy stub in this field and the deoptimizer has
+    // this assumption hard-coded in {TranslatedState::MaterializeAt} as well.
+    if (val->opcode() == IrOpcode::kInt32Constant ||
+        val->opcode() == IrOpcode::kInt64Constant) {
+      DCHECK_EQ(JSFunction::kCodeEntryOffset, FieldAccessOf(node->op()).offset);
+      val = slot_not_analyzed_;
+    }
+    if (object->GetField(offset) != val) {
+      object = CopyForModificationAt(object, state, node);
+      object->SetField(offset, val);
     }
   }
 }
@@ -1397,37 +1483,34 @@
          index_node->opcode() != IrOpcode::kInt64Constant &&
          index_node->opcode() != IrOpcode::kFloat32Constant &&
          index_node->opcode() != IrOpcode::kFloat64Constant);
-  ElementAccess access = OpParameter<ElementAccess>(node);
   VirtualState* state = virtual_states_[node->id()];
-  VirtualObject* obj = GetVirtualObject(state, to);
   if (index.HasValue()) {
-    int offset = index.Value() + access.header_size / kPointerSize;
-    if (obj && obj->IsTracked() &&
-        static_cast<size_t>(offset) < obj->field_count()) {
-      CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()),
-               kPointerSizeLog2);
-      CHECK_EQ(access.header_size % kPointerSize, 0);
+    if (VirtualObject* object = GetVirtualObject(state, to)) {
+      if (!object->IsTracked()) return;
+      int offset = OffsetForElementAccess(node, index.Value());
+      if (static_cast<size_t>(offset) >= object->field_count()) return;
       Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 2));
-      if (obj->GetField(offset) != val) {
-        obj = CopyForModificationAt(obj, state, node);
-        obj->SetField(offset, val);
+      if (object->GetField(offset) != val) {
+        object = CopyForModificationAt(object, state, node);
+        object->SetField(offset, val);
       }
     }
   } else {
     // We have a store to a non-const index, cannot eliminate object.
-    if (SetEscaped(to)) {
+    if (status_analysis_->SetEscaped(to)) {
       TRACE(
           "Setting #%d (%s) to escaped because store element #%d to non-const "
           "index #%d (%s)\n",
           to->id(), to->op()->mnemonic(), node->id(), index_node->id(),
           index_node->op()->mnemonic());
     }
-    if (obj && obj->IsTracked()) {
-      if (!obj->AllFieldsClear()) {
-        obj = CopyForModificationAt(obj, state, node);
-        obj->ClearAllFields();
-        TRACE("Cleared all fields of @%d:#%d\n", GetAlias(obj->id()),
-              obj->id());
+    if (VirtualObject* object = GetVirtualObject(state, to)) {
+      if (!object->IsTracked()) return;
+      if (!object->AllFieldsClear()) {
+        object = CopyForModificationAt(object, state, node);
+        object->ClearAllFields();
+        TRACE("Cleared all fields of @%d:#%d\n",
+              status_analysis_->GetAlias(object->id()), object->id());
       }
     }
   }
@@ -1475,21 +1558,17 @@
   return nullptr;
 }
 
-void EscapeAnalysis::DebugPrintObject(VirtualObject* object, Alias alias) {
-  PrintF("  Alias @%d: Object #%d with %zu fields\n", alias, object->id(),
-         object->field_count());
-  for (size_t i = 0; i < object->field_count(); ++i) {
-    if (Node* f = object->GetField(i)) {
-      PrintF("    Field %zu = #%d (%s)\n", i, f->id(), f->op()->mnemonic());
-    }
-  }
-}
-
 void EscapeAnalysis::DebugPrintState(VirtualState* state) {
   PrintF("Dumping virtual state %p\n", static_cast<void*>(state));
-  for (Alias alias = 0; alias < AliasCount(); ++alias) {
+  for (Alias alias = 0; alias < status_analysis_->AliasCount(); ++alias) {
     if (VirtualObject* object = state->VirtualObjectFromAlias(alias)) {
-      DebugPrintObject(object, alias);
+      PrintF("  Alias @%d: Object #%d with %zu fields\n", alias, object->id(),
+             object->field_count());
+      for (size_t i = 0; i < object->field_count(); ++i) {
+        if (Node* f = object->GetField(i)) {
+          PrintF("    Field %zu = #%d (%s)\n", i, f->id(), f->op()->mnemonic());
+        }
+      }
     }
   }
 }
@@ -1511,17 +1590,17 @@
 
 VirtualObject* EscapeAnalysis::GetVirtualObject(VirtualState* state,
                                                 Node* node) {
-  if (node->id() >= status_analysis_.GetAliasMap().size()) return nullptr;
-  Alias alias = GetAlias(node->id());
+  if (node->id() >= status_analysis_->GetAliasMap().size()) return nullptr;
+  Alias alias = status_analysis_->GetAlias(node->id());
   if (alias >= state->size()) return nullptr;
   return state->VirtualObjectFromAlias(alias);
 }
 
 bool EscapeAnalysis::ExistsVirtualAllocate() {
-  for (size_t id = 0; id < status_analysis_.GetAliasMap().size(); ++id) {
-    Alias alias = GetAlias(static_cast<NodeId>(id));
+  for (size_t id = 0; id < status_analysis_->GetAliasMap().size(); ++id) {
+    Alias alias = status_analysis_->GetAlias(static_cast<NodeId>(id));
     if (alias < EscapeStatusAnalysis::kUntrackable) {
-      if (status_analysis_.IsVirtual(static_cast<int>(id))) {
+      if (status_analysis_->IsVirtual(static_cast<int>(id))) {
         return true;
       }
     }
@@ -1529,6 +1608,8 @@
   return false;
 }
 
+Graph* EscapeAnalysis::graph() const { return status_analysis_->graph(); }
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/src/compiler/escape-analysis.h b/src/compiler/escape-analysis.h
index c3f236d..839e54c 100644
--- a/src/compiler/escape-analysis.h
+++ b/src/compiler/escape-analysis.h
@@ -5,7 +5,6 @@
 #ifndef V8_COMPILER_ESCAPE_ANALYSIS_H_
 #define V8_COMPILER_ESCAPE_ANALYSIS_H_
 
-#include "src/base/flags.h"
 #include "src/compiler/graph.h"
 
 namespace v8 {
@@ -14,107 +13,15 @@
 
 // Forward declarations.
 class CommonOperatorBuilder;
-class EscapeAnalysis;
+class EscapeStatusAnalysis;
+class MergeCache;
 class VirtualState;
 class VirtualObject;
 
-// EscapeStatusAnalysis determines for each allocation whether it escapes.
-class EscapeStatusAnalysis {
- public:
-  typedef NodeId Alias;
-  ~EscapeStatusAnalysis();
-
-  enum Status {
-    kUnknown = 0u,
-    kTracked = 1u << 0,
-    kEscaped = 1u << 1,
-    kOnStack = 1u << 2,
-    kVisited = 1u << 3,
-    // A node is dangling, if it is a load of some kind, and does not have
-    // an effect successor.
-    kDanglingComputed = 1u << 4,
-    kDangling = 1u << 5,
-    // A node is is an effect branch point, if it has more than 2 non-dangling
-    // effect successors.
-    kBranchPointComputed = 1u << 6,
-    kBranchPoint = 1u << 7,
-    kInQueue = 1u << 8
-  };
-  typedef base::Flags<Status, uint16_t> StatusFlags;
-
-  void RunStatusAnalysis();
-
-  bool IsVirtual(Node* node);
-  bool IsEscaped(Node* node);
-  bool IsAllocation(Node* node);
-
-  bool IsInQueue(NodeId id);
-  void SetInQueue(NodeId id, bool on_stack);
-
-  void DebugPrint();
-
-  EscapeStatusAnalysis(EscapeAnalysis* object_analysis, Graph* graph,
-                       Zone* zone);
-  void EnqueueForStatusAnalysis(Node* node);
-  bool SetEscaped(Node* node);
-  bool IsEffectBranchPoint(Node* node);
-  bool IsDanglingEffectNode(Node* node);
-  void ResizeStatusVector();
-  size_t GetStatusVectorSize();
-  bool IsVirtual(NodeId id);
-
-  Graph* graph() const { return graph_; }
-  Zone* zone() const { return zone_; }
-  void AssignAliases();
-  Alias GetAlias(NodeId id) const { return aliases_[id]; }
-  const ZoneVector<Alias>& GetAliasMap() const { return aliases_; }
-  Alias AliasCount() const { return next_free_alias_; }
-  static const Alias kNotReachable;
-  static const Alias kUntrackable;
-
-  bool IsNotReachable(Node* node);
-
- private:
-  void Process(Node* node);
-  void ProcessAllocate(Node* node);
-  void ProcessFinishRegion(Node* node);
-  void ProcessStoreField(Node* node);
-  void ProcessStoreElement(Node* node);
-  bool CheckUsesForEscape(Node* node, bool phi_escaping = false) {
-    return CheckUsesForEscape(node, node, phi_escaping);
-  }
-  bool CheckUsesForEscape(Node* node, Node* rep, bool phi_escaping = false);
-  void RevisitUses(Node* node);
-  void RevisitInputs(Node* node);
-
-  Alias NextAlias() { return next_free_alias_++; }
-
-  bool HasEntry(Node* node);
-
-  bool IsAllocationPhi(Node* node);
-
-  ZoneVector<Node*> stack_;
-  EscapeAnalysis* object_analysis_;
-  Graph* const graph_;
-  Zone* const zone_;
-  ZoneVector<StatusFlags> status_;
-  Alias next_free_alias_;
-  ZoneVector<Node*> status_stack_;
-  ZoneVector<Alias> aliases_;
-
-  DISALLOW_COPY_AND_ASSIGN(EscapeStatusAnalysis);
-};
-
-DEFINE_OPERATORS_FOR_FLAGS(EscapeStatusAnalysis::StatusFlags)
-
-// Forward Declaration.
-class MergeCache;
-
 // EscapeObjectAnalysis simulates stores to determine values of loads if
 // an object is virtual and eliminated.
 class EscapeAnalysis {
  public:
-  using Alias = EscapeStatusAnalysis::Alias;
   EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, Zone* zone);
   ~EscapeAnalysis();
 
@@ -144,17 +51,12 @@
                           VirtualState* states);
 
   void ForwardVirtualState(Node* node);
-  int OffsetFromAccess(Node* node);
   VirtualState* CopyForModificationAt(VirtualState* state, Node* node);
   VirtualObject* CopyForModificationAt(VirtualObject* obj, VirtualState* state,
                                        Node* node);
-  VirtualObject* GetVirtualObject(Node* at, NodeId id);
 
-  bool SetEscaped(Node* node);
-  Node* replacement(NodeId id);
   Node* replacement(Node* node);
   Node* ResolveReplacement(Node* node);
-  Node* GetReplacement(NodeId id);
   bool SetReplacement(Node* node, Node* rep);
   bool UpdateReplacement(VirtualState* state, Node* node, Node* rep);
 
@@ -162,25 +64,15 @@
 
   void DebugPrint();
   void DebugPrintState(VirtualState* state);
-  void DebugPrintObject(VirtualObject* state, Alias id);
 
-  Graph* graph() const { return status_analysis_.graph(); }
-  Zone* zone() const { return status_analysis_.zone(); }
+  Graph* graph() const;
+  Zone* zone() const { return zone_; }
   CommonOperatorBuilder* common() const { return common_; }
-  bool IsEffectBranchPoint(Node* node) {
-    return status_analysis_.IsEffectBranchPoint(node);
-  }
-  bool IsDanglingEffectNode(Node* node) {
-    return status_analysis_.IsDanglingEffectNode(node);
-  }
-  bool IsNotReachable(Node* node) {
-    return status_analysis_.IsNotReachable(node);
-  }
-  Alias GetAlias(NodeId id) const { return status_analysis_.GetAlias(id); }
-  Alias AliasCount() const { return status_analysis_.AliasCount(); }
 
-  EscapeStatusAnalysis status_analysis_;
+  Zone* const zone_;
+  Node* const slot_not_analyzed_;
   CommonOperatorBuilder* const common_;
+  EscapeStatusAnalysis* status_analysis_;
   ZoneVector<VirtualState*> virtual_states_;
   ZoneVector<Node*> replacements_;
   MergeCache* cache_;
diff --git a/src/compiler/frame.cc b/src/compiler/frame.cc
index 3d93e15..e0284c8 100644
--- a/src/compiler/frame.cc
+++ b/src/compiler/frame.cc
@@ -12,15 +12,13 @@
 namespace internal {
 namespace compiler {
 
-Frame::Frame(int fixed_frame_size_in_slots, const CallDescriptor* descriptor)
+Frame::Frame(int fixed_frame_size_in_slots)
     : frame_slot_count_(fixed_frame_size_in_slots),
-      callee_saved_slot_count_(0),
       spill_slot_count_(0),
       allocated_registers_(nullptr),
       allocated_double_registers_(nullptr) {}
 
 int Frame::AlignFrame(int alignment) {
-  DCHECK_EQ(0, callee_saved_slot_count_);
   int alignment_slots = alignment / kPointerSize;
   int delta = alignment_slots - (frame_slot_count_ & (alignment_slots - 1));
   if (delta != alignment_slots) {
diff --git a/src/compiler/frame.h b/src/compiler/frame.h
index d413d3e..de2ae1a 100644
--- a/src/compiler/frame.h
+++ b/src/compiler/frame.h
@@ -78,14 +78,10 @@
 //
 class Frame : public ZoneObject {
  public:
-  explicit Frame(int fixed_frame_size_in_slots,
-                 const CallDescriptor* descriptor);
+  explicit Frame(int fixed_frame_size_in_slots);
 
   inline int GetTotalFrameSlotCount() const { return frame_slot_count_; }
 
-  inline int GetSavedCalleeRegisterSlotCount() const {
-    return callee_saved_slot_count_;
-  }
   inline int GetSpillSlotCount() const { return spill_slot_count_; }
 
   void SetAllocatedRegisters(BitVector* regs) {
@@ -102,23 +98,20 @@
     return !allocated_double_registers_->IsEmpty();
   }
 
-  int AlignSavedCalleeRegisterSlots(int alignment = kDoubleSize) {
-    DCHECK_EQ(0, callee_saved_slot_count_);
+  void AlignSavedCalleeRegisterSlots(int alignment = kDoubleSize) {
     int alignment_slots = alignment / kPointerSize;
     int delta = alignment_slots - (frame_slot_count_ & (alignment_slots - 1));
     if (delta != alignment_slots) {
       frame_slot_count_ += delta;
     }
-    return delta;
+    spill_slot_count_ += delta;
   }
 
   void AllocateSavedCalleeRegisterSlots(int count) {
     frame_slot_count_ += count;
-    callee_saved_slot_count_ += count;
   }
 
   int AllocateSpillSlot(int width) {
-    DCHECK_EQ(0, callee_saved_slot_count_);
     int frame_slot_count_before = frame_slot_count_;
     int slot = AllocateAlignedFrameSlot(width);
     spill_slot_count_ += (frame_slot_count_ - frame_slot_count_before);
@@ -128,7 +121,6 @@
   int AlignFrame(int alignment = kDoubleSize);
 
   int ReserveSpillSlots(size_t slot_count) {
-    DCHECK_EQ(0, callee_saved_slot_count_);
     DCHECK_EQ(0, spill_slot_count_);
     spill_slot_count_ += static_cast<int>(slot_count);
     frame_slot_count_ += static_cast<int>(slot_count);
@@ -152,7 +144,6 @@
 
  private:
   int frame_slot_count_;
-  int callee_saved_slot_count_;
   int spill_slot_count_;
   BitVector* allocated_registers_;
   BitVector* allocated_double_registers_;
@@ -191,13 +182,13 @@
 // current function's frame.
 class FrameAccessState : public ZoneObject {
  public:
-  explicit FrameAccessState(Frame* const frame)
+  explicit FrameAccessState(const Frame* const frame)
       : frame_(frame),
         access_frame_with_fp_(false),
         sp_delta_(0),
         has_frame_(false) {}
 
-  Frame* frame() const { return frame_; }
+  const Frame* frame() const { return frame_; }
   void MarkHasFrame(bool state);
 
   int sp_delta() const { return sp_delta_; }
@@ -229,7 +220,7 @@
   FrameOffset GetFrameOffset(int spill_slot) const;
 
  private:
-  Frame* const frame_;
+  const Frame* const frame_;
   bool access_frame_with_fp_;
   int sp_delta_;
   bool has_frame_;
diff --git a/src/compiler/gap-resolver.cc b/src/compiler/gap-resolver.cc
index 35e91fa..7c39700 100644
--- a/src/compiler/gap-resolver.cc
+++ b/src/compiler/gap-resolver.cc
@@ -75,7 +75,7 @@
   // This move's source may have changed due to swaps to resolve cycles and so
   // it may now be the last move in the cycle.  If so remove it.
   InstructionOperand source = move->source();
-  if (source.EqualsCanonicalized(destination)) {
+  if (source.InterferesWith(destination)) {
     move->Eliminate();
     return;
   }
@@ -94,7 +94,7 @@
 
   DCHECK((*blocker)->IsPending());
   // Ensure source is a register or both are stack slots, to limit swap cases.
-  if (source.IsStackSlot() || source.IsDoubleStackSlot()) {
+  if (source.IsStackSlot() || source.IsFPStackSlot()) {
     std::swap(source, destination);
   }
   assembler_->AssembleSwap(&source, &destination);
diff --git a/src/compiler/graph-reducer.cc b/src/compiler/graph-reducer.cc
index 6f583d6..2ef1ba1 100644
--- a/src/compiler/graph-reducer.cc
+++ b/src/compiler/graph-reducer.cc
@@ -222,7 +222,11 @@
         edge.UpdateTo(dead_);
         Revisit(user);
       } else {
-        UNREACHABLE();
+        DCHECK_NOT_NULL(control);
+        edge.UpdateTo(control);
+        Revisit(user);
+        // TODO(jarin) Check that the node cannot throw (otherwise, it
+        // would have to be connected via IfSuccess/IfException).
       }
     } else if (NodeProperties::IsEffectEdge(edge)) {
       DCHECK_NOT_NULL(effect);
diff --git a/src/compiler/graph-reducer.h b/src/compiler/graph-reducer.h
index 683c345..2ac60a6 100644
--- a/src/compiler/graph-reducer.h
+++ b/src/compiler/graph-reducer.h
@@ -74,8 +74,7 @@
     virtual void Revisit(Node* node) = 0;
     // Replace value uses of {node} with {value} and effect uses of {node} with
     // {effect}. If {effect == nullptr}, then use the effect input to {node}.
-    // All
-    // control uses will be relaxed assuming {node} cannot throw.
+    // All control uses will be relaxed assuming {node} cannot throw.
     virtual void ReplaceWithValue(Node* node, Node* value, Node* effect,
                                   Node* control) = 0;
   };
diff --git a/src/compiler/graph-visualizer.cc b/src/compiler/graph-visualizer.cc
index 301e390..2e39764 100644
--- a/src/compiler/graph-visualizer.cc
+++ b/src/compiler/graph-visualizer.cc
@@ -25,9 +25,8 @@
 namespace internal {
 namespace compiler {
 
-
-FILE* OpenVisualizerLogFile(CompilationInfo* info, const char* phase,
-                            const char* suffix, const char* mode) {
+base::SmartArrayPointer<const char> GetVisualizerLogFileName(
+    CompilationInfo* info, const char* phase, const char* suffix) {
   EmbeddedVector<char, 256> filename(0);
   base::SmartArrayPointer<char> debug_name = info->GetDebugName();
   if (strlen(debug_name.get()) > 0) {
@@ -37,16 +36,40 @@
   } else {
     SNPrintF(filename, "turbo-none-%s", phase);
   }
+  EmbeddedVector<char, 256> source_file(0);
+  bool source_available = false;
+  if (FLAG_trace_file_names && info->parse_info()) {
+    Object* source_name = info->script()->name();
+    if (source_name->IsString()) {
+      String* str = String::cast(source_name);
+      if (str->length() > 0) {
+        SNPrintF(source_file, "%s", str->ToCString().get());
+        std::replace(source_file.start(),
+                     source_file.start() + source_file.length(), '/', '_');
+        source_available = true;
+      }
+    }
+  }
   std::replace(filename.start(), filename.start() + filename.length(), ' ',
                '_');
 
   EmbeddedVector<char, 256> full_filename;
-  if (phase == nullptr) {
+  if (phase == nullptr && !source_available) {
     SNPrintF(full_filename, "%s.%s", filename.start(), suffix);
-  } else {
+  } else if (phase != nullptr && !source_available) {
     SNPrintF(full_filename, "%s-%s.%s", filename.start(), phase, suffix);
+  } else if (phase == nullptr && source_available) {
+    SNPrintF(full_filename, "%s_%s.%s", filename.start(), source_file.start(),
+             suffix);
+  } else {
+    SNPrintF(full_filename, "%s_%s-%s.%s", filename.start(),
+             source_file.start(), phase, suffix);
   }
-  return base::OS::FOpen(full_filename.start(), mode);
+
+  char* buffer = new char[full_filename.length() + 1];
+  memcpy(buffer, full_filename.start(), full_filename.length());
+  buffer[full_filename.length()] = '\0';
+  return base::SmartArrayPointer<const char>(buffer);
 }
 
 
@@ -491,9 +514,8 @@
       for (int j = instruction_block->first_instruction_index();
            j <= instruction_block->last_instruction_index(); j++) {
         PrintIndent();
-        PrintableInstruction printable = {
-            RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN),
-            instructions->InstructionAt(j)};
+        PrintableInstruction printable = {RegisterConfiguration::Turbofan(),
+                                          instructions->InstructionAt(j)};
         os_ << j << " " << printable << " <|@\n";
       }
     }
@@ -536,13 +558,17 @@
     os_ << vreg << ":" << range->relative_id() << " " << type;
     if (range->HasRegisterAssigned()) {
       AllocatedOperand op = AllocatedOperand::cast(range->GetAssignedOperand());
-      if (op.IsDoubleRegister()) {
-        DoubleRegister assigned_reg = op.GetDoubleRegister();
-        os_ << " \"" << assigned_reg.ToString() << "\"";
+      const auto config = RegisterConfiguration::Turbofan();
+      if (op.IsRegister()) {
+        os_ << " \"" << config->GetGeneralRegisterName(op.register_code())
+            << "\"";
+      } else if (op.IsDoubleRegister()) {
+        os_ << " \"" << config->GetDoubleRegisterName(op.register_code())
+            << "\"";
       } else {
-        DCHECK(op.IsRegister());
-        Register assigned_reg = op.GetRegister();
-        os_ << " \"" << assigned_reg.ToString() << "\"";
+        DCHECK(op.IsFloatRegister());
+        os_ << " \"" << config->GetFloatRegisterName(op.register_code())
+            << "\"";
       }
     } else if (range->spilled()) {
       const TopLevelLiveRange* top = range->TopLevel();
@@ -555,7 +581,7 @@
             << "\"";
       } else {
         index = AllocatedOperand::cast(top->GetSpillOperand())->index();
-        if (top->kind() == DOUBLE_REGISTERS) {
+        if (top->kind() == FP_REGISTERS) {
           os_ << " \"double_stack:" << index << "\"";
         } else if (top->kind() == GENERAL_REGISTERS) {
           os_ << " \"stack:" << index << "\"";
@@ -615,6 +641,20 @@
 std::ostream& operator<<(std::ostream& os, const AsRPO& ar) {
   base::AccountingAllocator allocator;
   Zone local_zone(&allocator);
+
+  // Do a post-order depth-first search on the RPO graph. For every node,
+  // print:
+  //
+  //   - the node id
+  //   - the operator mnemonic
+  //   - in square brackets its parameter (if present)
+  //   - in parentheses the list of argument ids and their mnemonics
+  //   - the node type (if it is typed)
+
+  // Post-order guarantees that all inputs of a node will be printed before
+  // the node itself, if there are no cycles. Any cycles are broken
+  // arbitrarily.
+
   ZoneVector<byte> state(ar.graph.NodeCount(), kUnvisited, &local_zone);
   ZoneStack<Node*> stack(&local_zone);
 
@@ -635,12 +675,20 @@
       state[n->id()] = kVisited;
       stack.pop();
       os << "#" << n->id() << ":" << *n->op() << "(";
+      // Print the inputs.
       int j = 0;
       for (Node* const i : n->inputs()) {
         if (j++ > 0) os << ", ";
         os << "#" << SafeId(i) << ":" << SafeMnemonic(i);
       }
-      os << ")" << std::endl;
+      os << ")";
+      // Print the node type, if any.
+      if (NodeProperties::IsTyped(n)) {
+        os << "  [Type: ";
+        NodeProperties::GetType(n)->PrintTo(os);
+        os << "]";
+      }
+      os << std::endl;
     }
   }
   return os;
diff --git a/src/compiler/graph-visualizer.h b/src/compiler/graph-visualizer.h
index 1a971a5..85b0cf7 100644
--- a/src/compiler/graph-visualizer.h
+++ b/src/compiler/graph-visualizer.h
@@ -8,6 +8,8 @@
 #include <stdio.h>
 #include <iosfwd>
 
+#include "src/base/smart-pointers.h"
+
 namespace v8 {
 namespace internal {
 
@@ -21,8 +23,8 @@
 class Schedule;
 class SourcePositionTable;
 
-FILE* OpenVisualizerLogFile(CompilationInfo* info, const char* phase,
-                            const char* suffix, const char* mode);
+base::SmartArrayPointer<const char> GetVisualizerLogFileName(
+    CompilationInfo* info, const char* phase, const char* suffix);
 
 struct AsJSON {
   AsJSON(const Graph& g, SourcePositionTable* p) : graph(g), positions(p) {}
diff --git a/src/compiler/graph.h b/src/compiler/graph.h
index 958a15d..a694a0b 100644
--- a/src/compiler/graph.h
+++ b/src/compiler/graph.h
@@ -28,11 +28,30 @@
 // out-of-line data associated with each node.
 typedef uint32_t NodeId;
 
-
-class Graph : public ZoneObject {
+class Graph final : public ZoneObject {
  public:
   explicit Graph(Zone* zone);
 
+  // Scope used when creating a subgraph for inlining. Automatically preserves
+  // the original start and end nodes of the graph, and resets them when you
+  // leave the scope.
+  class SubgraphScope final {
+   public:
+    explicit SubgraphScope(Graph* graph)
+        : graph_(graph), start_(graph->start()), end_(graph->end()) {}
+    ~SubgraphScope() {
+      graph_->SetStart(start_);
+      graph_->SetEnd(end_);
+    }
+
+   private:
+    Graph* const graph_;
+    Node* const start_;
+    Node* const end_;
+
+    DISALLOW_COPY_AND_ASSIGN(SubgraphScope);
+  };
+
   // Base implementation used by all factory methods.
   Node* NewNodeUnchecked(const Operator* op, int input_count,
                          Node* const* inputs, bool incomplete = false);
diff --git a/src/compiler/greedy-allocator.cc b/src/compiler/greedy-allocator.cc
deleted file mode 100644
index 683b75d..0000000
--- a/src/compiler/greedy-allocator.cc
+++ /dev/null
@@ -1,629 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/compiler/greedy-allocator.h"
-#include "src/compiler/register-allocator.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-
-#define TRACE(...)                             \
-  do {                                         \
-    if (FLAG_trace_alloc) PrintF(__VA_ARGS__); \
-  } while (false)
-
-
-const float GreedyAllocator::kAllocatedRangeMultiplier = 10.0;
-
-
-namespace {
-
-void UpdateOperands(LiveRange* range, RegisterAllocationData* data) {
-  int reg_id = range->assigned_register();
-  range->SetUseHints(reg_id);
-  if (range->IsTopLevel() && range->TopLevel()->is_phi()) {
-    data->GetPhiMapValueFor(range->TopLevel())->set_assigned_register(reg_id);
-  }
-}
-
-
-void UnsetOperands(LiveRange* range, RegisterAllocationData* data) {
-  range->UnsetUseHints();
-  if (range->IsTopLevel() && range->TopLevel()->is_phi()) {
-    data->GetPhiMapValueFor(range->TopLevel())->UnsetAssignedRegister();
-  }
-}
-
-
-LiveRange* Split(LiveRange* range, RegisterAllocationData* data,
-                 LifetimePosition pos) {
-  DCHECK(range->Start() < pos && pos < range->End());
-  DCHECK(pos.IsStart() || pos.IsGapPosition() ||
-         (data->code()
-              ->GetInstructionBlock(pos.ToInstructionIndex())
-              ->last_instruction_index() != pos.ToInstructionIndex()));
-  LiveRange* result = range->SplitAt(pos, data->allocation_zone());
-  return result;
-}
-
-
-}  // namespace
-
-
-AllocationCandidate AllocationScheduler::GetNext() {
-  DCHECK(!queue_.empty());
-  AllocationCandidate ret = queue_.top();
-  queue_.pop();
-  return ret;
-}
-
-
-void AllocationScheduler::Schedule(LiveRange* range) {
-  TRACE("Scheduling live range %d:%d.\n", range->TopLevel()->vreg(),
-        range->relative_id());
-  queue_.push(AllocationCandidate(range));
-}
-
-
-void AllocationScheduler::Schedule(LiveRangeGroup* group) {
-  queue_.push(AllocationCandidate(group));
-}
-
-GreedyAllocator::GreedyAllocator(RegisterAllocationData* data,
-                                 RegisterKind kind, Zone* local_zone)
-    : RegisterAllocator(data, kind),
-      local_zone_(local_zone),
-      allocations_(local_zone),
-      scheduler_(local_zone),
-      groups_(local_zone) {}
-
-
-void GreedyAllocator::AssignRangeToRegister(int reg_id, LiveRange* range) {
-  TRACE("Assigning register %s to live range %d:%d\n", RegisterName(reg_id),
-        range->TopLevel()->vreg(), range->relative_id());
-
-  DCHECK(!range->HasRegisterAssigned());
-
-  AllocateRegisterToRange(reg_id, range);
-
-  TRACE("Assigning %s to range %d%d.\n", RegisterName(reg_id),
-        range->TopLevel()->vreg(), range->relative_id());
-  range->set_assigned_register(reg_id);
-  UpdateOperands(range, data());
-}
-
-
-void GreedyAllocator::PreallocateFixedRanges() {
-  allocations_.resize(num_registers());
-  for (int i = 0; i < num_registers(); i++) {
-    allocations_[i] = new (local_zone()) CoalescedLiveRanges(local_zone());
-  }
-
-  for (LiveRange* fixed_range : GetFixedRegisters()) {
-    if (fixed_range != nullptr) {
-      DCHECK_EQ(mode(), fixed_range->kind());
-      DCHECK(fixed_range->TopLevel()->IsFixed());
-
-      int reg_nr = fixed_range->assigned_register();
-      EnsureValidRangeWeight(fixed_range);
-      AllocateRegisterToRange(reg_nr, fixed_range);
-    }
-  }
-}
-
-
-void GreedyAllocator::GroupLiveRanges() {
-  CoalescedLiveRanges grouper(local_zone());
-  for (TopLevelLiveRange* range : data()->live_ranges()) {
-    grouper.clear();
-    // Skip splinters, because we do not want to optimize for them, and moves
-    // due to assigning them to different registers occur in deferred blocks.
-    if (!CanProcessRange(range) || range->IsSplinter() || !range->is_phi()) {
-      continue;
-    }
-
-    // A phi can't be a memory operand, so it couldn't have been split.
-    DCHECK(!range->spilled());
-
-    // Maybe this phi range is itself an input to another phi which was already
-    // processed.
-    LiveRangeGroup* latest_grp = range->group() != nullptr
-                                     ? range->group()
-                                     : new (local_zone())
-                                           LiveRangeGroup(local_zone());
-
-    // Populate the grouper.
-    if (range->group() == nullptr) {
-      grouper.AllocateRange(range);
-    } else {
-      for (LiveRange* member : range->group()->ranges()) {
-        grouper.AllocateRange(member);
-      }
-    }
-    for (int j : data()->GetPhiMapValueFor(range)->phi()->operands()) {
-      // skip output also in input, which may happen for loops.
-      if (j == range->vreg()) continue;
-
-      TopLevelLiveRange* other_top = data()->live_ranges()[j];
-
-      if (other_top->IsSplinter()) continue;
-      // If the other was a memory operand, it might have been split.
-      // So get the unsplit part.
-      LiveRange* other =
-          other_top->next() == nullptr ? other_top : other_top->next();
-
-      if (other->spilled()) continue;
-
-      LiveRangeGroup* other_group = other->group();
-      if (other_group != nullptr) {
-        bool can_merge = true;
-        for (LiveRange* member : other_group->ranges()) {
-          if (grouper.GetConflicts(member).Current() != nullptr) {
-            can_merge = false;
-            break;
-          }
-        }
-        // If each member doesn't conflict with the current group, then since
-        // the members don't conflict with eachother either, we can merge them.
-        if (can_merge) {
-          latest_grp->ranges().insert(latest_grp->ranges().end(),
-                                      other_group->ranges().begin(),
-                                      other_group->ranges().end());
-          for (LiveRange* member : other_group->ranges()) {
-            grouper.AllocateRange(member);
-            member->set_group(latest_grp);
-          }
-          // Clear the other range, so we avoid scheduling it.
-          other_group->ranges().clear();
-        }
-      } else if (grouper.GetConflicts(other).Current() == nullptr) {
-        grouper.AllocateRange(other);
-        latest_grp->ranges().push_back(other);
-        other->set_group(latest_grp);
-      }
-    }
-
-    if (latest_grp->ranges().size() > 0 && range->group() == nullptr) {
-      latest_grp->ranges().push_back(range);
-      DCHECK(latest_grp->ranges().size() > 1);
-      groups().push_back(latest_grp);
-      range->set_group(latest_grp);
-    }
-  }
-}
-
-
-void GreedyAllocator::ScheduleAllocationCandidates() {
-  for (LiveRangeGroup* group : groups()) {
-    if (group->ranges().size() > 0) {
-      // We shouldn't have added single-range groups.
-      DCHECK(group->ranges().size() != 1);
-      scheduler().Schedule(group);
-    }
-  }
-  for (LiveRange* range : data()->live_ranges()) {
-    if (CanProcessRange(range)) {
-      for (LiveRange* child = range; child != nullptr; child = child->next()) {
-        if (!child->spilled() && child->group() == nullptr) {
-          scheduler().Schedule(child);
-        }
-      }
-    }
-  }
-}
-
-
-void GreedyAllocator::TryAllocateCandidate(
-    const AllocationCandidate& candidate) {
-  if (candidate.is_group()) {
-    TryAllocateGroup(candidate.group());
-  } else {
-    TryAllocateLiveRange(candidate.live_range());
-  }
-}
-
-
-void GreedyAllocator::TryAllocateGroup(LiveRangeGroup* group) {
-  float group_weight = 0.0;
-  for (LiveRange* member : group->ranges()) {
-    EnsureValidRangeWeight(member);
-    group_weight = Max(group_weight, member->weight());
-  }
-
-  float eviction_weight = group_weight;
-  int eviction_reg = -1;
-  int free_reg = -1;
-  for (int i = 0; i < num_allocatable_registers(); ++i) {
-    int reg = allocatable_register_code(i);
-    float weight = GetMaximumConflictingWeight(reg, group, group_weight);
-    if (weight == LiveRange::kInvalidWeight) {
-      free_reg = reg;
-      break;
-    }
-    if (weight < eviction_weight) {
-      eviction_weight = weight;
-      eviction_reg = reg;
-    }
-  }
-  if (eviction_reg < 0 && free_reg < 0) {
-    for (LiveRange* member : group->ranges()) {
-      scheduler().Schedule(member);
-    }
-    return;
-  }
-  if (free_reg < 0) {
-    DCHECK(eviction_reg >= 0);
-    for (LiveRange* member : group->ranges()) {
-      EvictAndRescheduleConflicts(eviction_reg, member);
-    }
-    free_reg = eviction_reg;
-  }
-
-  DCHECK(free_reg >= 0);
-  for (LiveRange* member : group->ranges()) {
-    AssignRangeToRegister(free_reg, member);
-  }
-}
-
-
-void GreedyAllocator::TryAllocateLiveRange(LiveRange* range) {
-  // TODO(mtrofin): once we introduce groups, we'll want to first try and
-  // allocate at the preferred register.
-  TRACE("Attempting to allocate live range %d:%d.\n", range->TopLevel()->vreg(),
-        range->relative_id());
-  int free_reg = -1;
-  int evictable_reg = -1;
-  int hinted_reg = -1;
-
-  EnsureValidRangeWeight(range);
-  float competing_weight = range->weight();
-  DCHECK(competing_weight != LiveRange::kInvalidWeight);
-
-  // Can we allocate at the hinted register?
-  if (range->FirstHintPosition(&hinted_reg) != nullptr) {
-    DCHECK(hinted_reg >= 0);
-    float max_conflict_weight =
-        GetMaximumConflictingWeight(hinted_reg, range, competing_weight);
-    if (max_conflict_weight == LiveRange::kInvalidWeight) {
-      free_reg = hinted_reg;
-    } else if (max_conflict_weight < range->weight()) {
-      evictable_reg = hinted_reg;
-    }
-  }
-
-  if (free_reg < 0 && evictable_reg < 0) {
-    // There was no hinted reg, or we cannot allocate there.
-    float smallest_weight = LiveRange::kMaxWeight;
-
-    // Seek either the first free register, or, from the set of registers
-    // where the maximum conflict is lower than the candidate's weight, the one
-    // with the smallest such weight.
-    for (int i = 0; i < num_allocatable_registers(); i++) {
-      int reg = allocatable_register_code(i);
-      // Skip unnecessarily re-visiting the hinted register, if any.
-      if (reg == hinted_reg) continue;
-      float max_conflict_weight =
-          GetMaximumConflictingWeight(reg, range, competing_weight);
-      if (max_conflict_weight == LiveRange::kInvalidWeight) {
-        free_reg = reg;
-        break;
-      }
-      if (max_conflict_weight < range->weight() &&
-          max_conflict_weight < smallest_weight) {
-        smallest_weight = max_conflict_weight;
-        evictable_reg = reg;
-      }
-    }
-  }
-
-  // We have a free register, so we use it.
-  if (free_reg >= 0) {
-    TRACE("Found free register %s for live range %d:%d.\n",
-          RegisterName(free_reg), range->TopLevel()->vreg(),
-          range->relative_id());
-    AssignRangeToRegister(free_reg, range);
-    return;
-  }
-
-  // We found a register to perform evictions, so we evict and allocate our
-  // candidate.
-  if (evictable_reg >= 0) {
-    TRACE("Found evictable register %s for live range %d:%d.\n",
-          RegisterName(free_reg), range->TopLevel()->vreg(),
-          range->relative_id());
-    EvictAndRescheduleConflicts(evictable_reg, range);
-    AssignRangeToRegister(evictable_reg, range);
-    return;
-  }
-
-  // The range needs to be split or spilled.
-  SplitOrSpillBlockedRange(range);
-}
-
-
-void GreedyAllocator::EvictAndRescheduleConflicts(unsigned reg_id,
-                                                  const LiveRange* range) {
-  auto conflicts = current_allocations(reg_id)->GetConflicts(range);
-  for (LiveRange* conflict = conflicts.Current(); conflict != nullptr;
-       conflict = conflicts.RemoveCurrentAndGetNext()) {
-    DCHECK(conflict->HasRegisterAssigned());
-    CHECK(!conflict->TopLevel()->IsFixed());
-    conflict->UnsetAssignedRegister();
-    UnsetOperands(conflict, data());
-    UpdateWeightAtEviction(conflict);
-    scheduler().Schedule(conflict);
-    TRACE("Evicted range %d%d.\n", conflict->TopLevel()->vreg(),
-          conflict->relative_id());
-  }
-}
-
-
-void GreedyAllocator::AllocateRegisters() {
-  CHECK(scheduler().empty());
-  CHECK(allocations_.empty());
-
-  TRACE("Begin allocating function %s with the Greedy Allocator\n",
-        data()->debug_name());
-
-  SplitAndSpillRangesDefinedByMemoryOperand(true);
-  GroupLiveRanges();
-  ScheduleAllocationCandidates();
-  PreallocateFixedRanges();
-  while (!scheduler().empty()) {
-    AllocationCandidate candidate = scheduler().GetNext();
-    TryAllocateCandidate(candidate);
-  }
-
-  for (size_t i = 0; i < allocations_.size(); ++i) {
-    if (!allocations_[i]->empty()) {
-      data()->MarkAllocated(mode(), static_cast<int>(i));
-    }
-  }
-  allocations_.clear();
-
-  TryReuseSpillRangesForGroups();
-
-  TRACE("End allocating function %s with the Greedy Allocator\n",
-        data()->debug_name());
-}
-
-
-void GreedyAllocator::TryReuseSpillRangesForGroups() {
-  for (TopLevelLiveRange* top : data()->live_ranges()) {
-    if (!CanProcessRange(top) || !top->is_phi() || top->group() == nullptr) {
-      continue;
-    }
-
-    SpillRange* spill_range = nullptr;
-    for (LiveRange* member : top->group()->ranges()) {
-      if (!member->TopLevel()->HasSpillRange()) continue;
-      SpillRange* member_range = member->TopLevel()->GetSpillRange();
-      if (spill_range == nullptr) {
-        spill_range = member_range;
-      } else {
-        // This may not always succeed, because we group non-conflicting ranges
-        // that may have been splintered, and the splinters may cause conflicts
-        // in the spill ranges.
-        // TODO(mtrofin): should the splinters own their own spill ranges?
-        spill_range->TryMerge(member_range);
-      }
-    }
-  }
-}
-
-
-float GreedyAllocator::GetMaximumConflictingWeight(
-    unsigned reg_id, const LiveRange* range, float competing_weight) const {
-  float ret = LiveRange::kInvalidWeight;
-
-  auto conflicts = current_allocations(reg_id)->GetConflicts(range);
-  for (LiveRange* conflict = conflicts.Current(); conflict != nullptr;
-       conflict = conflicts.GetNext()) {
-    DCHECK_NE(conflict->weight(), LiveRange::kInvalidWeight);
-    if (competing_weight <= conflict->weight()) return LiveRange::kMaxWeight;
-    ret = Max(ret, conflict->weight());
-    DCHECK(ret < LiveRange::kMaxWeight);
-  }
-
-  return ret;
-}
-
-
-float GreedyAllocator::GetMaximumConflictingWeight(unsigned reg_id,
-                                                   const LiveRangeGroup* group,
-                                                   float group_weight) const {
-  float ret = LiveRange::kInvalidWeight;
-
-  for (LiveRange* member : group->ranges()) {
-    float member_conflict_weight =
-        GetMaximumConflictingWeight(reg_id, member, group_weight);
-    if (member_conflict_weight == LiveRange::kMaxWeight) {
-      return LiveRange::kMaxWeight;
-    }
-    if (member_conflict_weight > group_weight) return LiveRange::kMaxWeight;
-    ret = Max(member_conflict_weight, ret);
-  }
-
-  return ret;
-}
-
-
-void GreedyAllocator::EnsureValidRangeWeight(LiveRange* range) {
-  // The live range weight will be invalidated when ranges are created or split.
-  // Otherwise, it is consistently updated when the range is allocated or
-  // unallocated.
-  if (range->weight() != LiveRange::kInvalidWeight) return;
-
-  if (range->TopLevel()->IsFixed()) {
-    range->set_weight(LiveRange::kMaxWeight);
-    return;
-  }
-  if (!IsProgressPossible(range)) {
-    range->set_weight(LiveRange::kMaxWeight);
-    return;
-  }
-
-  float use_count = 0.0;
-  for (auto pos = range->first_pos(); pos != nullptr; pos = pos->next()) {
-    ++use_count;
-  }
-  range->set_weight(use_count / static_cast<float>(range->GetSize()));
-}
-
-
-void GreedyAllocator::SpillRangeAsLastResort(LiveRange* range) {
-  LifetimePosition start = range->Start();
-  CHECK(range->CanBeSpilled(start));
-
-  DCHECK(range->NextRegisterPosition(start) == nullptr);
-  Spill(range);
-}
-
-
-LiveRange* GreedyAllocator::GetRemainderAfterSplittingAroundFirstCall(
-    LiveRange* range) {
-  LiveRange* ret = range;
-  for (UseInterval* interval = range->first_interval(); interval != nullptr;
-       interval = interval->next()) {
-    LifetimePosition start = interval->start();
-    LifetimePosition end = interval->end();
-    // If the interval starts at instruction end, then the first instruction
-    // in the interval is the next one.
-    int first_full_instruction = (start.IsGapPosition() || start.IsStart())
-                                     ? start.ToInstructionIndex()
-                                     : start.ToInstructionIndex() + 1;
-    // If the interval ends in a gap or at instruction start, then the last
-    // instruction is the previous one.
-    int last_full_instruction = (end.IsGapPosition() || end.IsStart())
-                                    ? end.ToInstructionIndex() - 1
-                                    : end.ToInstructionIndex();
-
-    for (int instruction_index = first_full_instruction;
-         instruction_index <= last_full_instruction; ++instruction_index) {
-      if (!code()->InstructionAt(instruction_index)->IsCall()) continue;
-
-      LifetimePosition before =
-          GetSplitPositionForInstruction(range, instruction_index);
-      LiveRange* second_part =
-          before.IsValid() ? Split(range, data(), before) : range;
-
-      if (range != second_part) scheduler().Schedule(range);
-
-      LifetimePosition after =
-          FindSplitPositionAfterCall(second_part, instruction_index);
-
-      if (after.IsValid()) {
-        ret = Split(second_part, data(), after);
-      } else {
-        ret = nullptr;
-      }
-      Spill(second_part);
-      return ret;
-    }
-  }
-  return ret;
-}
-
-
-bool GreedyAllocator::TrySplitAroundCalls(LiveRange* range) {
-  bool modified = false;
-
-  while (range != nullptr) {
-    LiveRange* remainder = GetRemainderAfterSplittingAroundFirstCall(range);
-    // If we performed no modification, we're done.
-    if (remainder == range) {
-      break;
-    }
-    // We performed a modification.
-    modified = true;
-    range = remainder;
-  }
-  // If we have a remainder and we made modifications, it means the remainder
-  // has no calls and we should schedule it for further processing. If we made
-  // no modifications, we will just return false, because we want the algorithm
-  // to make progress by trying some other heuristic.
-  if (modified && range != nullptr) {
-    DCHECK(!range->spilled());
-    DCHECK(!range->HasRegisterAssigned());
-    scheduler().Schedule(range);
-  }
-  return modified;
-}
-
-
-LifetimePosition GreedyAllocator::FindSplitPositionAfterCall(
-    const LiveRange* range, int call_index) {
-  LifetimePosition after_call =
-      Max(range->Start(),
-          LifetimePosition::GapFromInstructionIndex(call_index + 1));
-  UsePosition* next_use = range->NextRegisterPosition(after_call);
-  if (!next_use) return LifetimePosition::Invalid();
-
-  LifetimePosition split_pos = FindOptimalSplitPos(after_call, next_use->pos());
-  split_pos =
-      GetSplitPositionForInstruction(range, split_pos.ToInstructionIndex());
-  return split_pos;
-}
-
-
-LifetimePosition GreedyAllocator::FindSplitPositionBeforeLoops(
-    LiveRange* range) {
-  LifetimePosition end = range->End();
-  if (end.ToInstructionIndex() >= code()->LastInstructionIndex()) {
-    end =
-        LifetimePosition::GapFromInstructionIndex(end.ToInstructionIndex() - 1);
-  }
-  LifetimePosition pos = FindOptimalSplitPos(range->Start(), end);
-  pos = GetSplitPositionForInstruction(range, pos.ToInstructionIndex());
-  return pos;
-}
-
-
-void GreedyAllocator::SplitOrSpillBlockedRange(LiveRange* range) {
-  if (TrySplitAroundCalls(range)) return;
-
-  LifetimePosition pos = FindSplitPositionBeforeLoops(range);
-
-  if (!pos.IsValid()) pos = GetLastResortSplitPosition(range);
-  if (pos.IsValid()) {
-    LiveRange* tail = Split(range, data(), pos);
-    DCHECK(tail != range);
-    scheduler().Schedule(tail);
-    scheduler().Schedule(range);
-    return;
-  }
-  SpillRangeAsLastResort(range);
-}
-
-
-// Basic heuristic for advancing the algorithm, if any other splitting heuristic
-// failed.
-LifetimePosition GreedyAllocator::GetLastResortSplitPosition(
-    const LiveRange* range) {
-  LifetimePosition previous = range->Start();
-  for (UsePosition *pos = range->NextRegisterPosition(previous); pos != nullptr;
-       previous = previous.NextFullStart(),
-                   pos = range->NextRegisterPosition(previous)) {
-    LifetimePosition optimal = FindOptimalSplitPos(previous, pos->pos());
-    LifetimePosition before =
-        GetSplitPositionForInstruction(range, optimal.ToInstructionIndex());
-    if (before.IsValid()) return before;
-    LifetimePosition after = GetSplitPositionForInstruction(
-        range, pos->pos().ToInstructionIndex() + 1);
-    if (after.IsValid()) return after;
-  }
-  return LifetimePosition::Invalid();
-}
-
-
-bool GreedyAllocator::IsProgressPossible(const LiveRange* range) {
-  return range->CanBeSpilled(range->Start()) ||
-         GetLastResortSplitPosition(range).IsValid();
-}
-
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
diff --git a/src/compiler/greedy-allocator.h b/src/compiler/greedy-allocator.h
deleted file mode 100644
index b61ba42..0000000
--- a/src/compiler/greedy-allocator.h
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_GREEDY_ALLOCATOR_H_
-#define V8_GREEDY_ALLOCATOR_H_
-
-#include "src/compiler/coalesced-live-ranges.h"
-#include "src/compiler/register-allocator.h"
-#include "src/zone-containers.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-
-// The object of allocation scheduling. At minimum, this is a LiveRange, but
-// we may extend this to groups of LiveRanges. It has to be comparable.
-class AllocationCandidate {
- public:
-  explicit AllocationCandidate(LiveRange* range)
-      : is_group_(false), size_(range->GetSize()) {
-    candidate_.range_ = range;
-  }
-
-  explicit AllocationCandidate(LiveRangeGroup* ranges)
-      : is_group_(true), size_(CalculateGroupSize(ranges)) {
-    candidate_.group_ = ranges;
-  }
-
-  // Strict ordering operators
-  bool operator<(const AllocationCandidate& other) const {
-    return size() < other.size();
-  }
-
-  bool operator>(const AllocationCandidate& other) const {
-    return size() > other.size();
-  }
-
-  bool is_group() const { return is_group_; }
-  LiveRange* live_range() const { return candidate_.range_; }
-  LiveRangeGroup* group() const { return candidate_.group_; }
-
- private:
-  unsigned CalculateGroupSize(LiveRangeGroup* group) {
-    unsigned ret = 0;
-    for (LiveRange* range : group->ranges()) {
-      ret += range->GetSize();
-    }
-    return ret;
-  }
-
-  unsigned size() const { return size_; }
-  bool is_group_;
-  unsigned size_;
-  union {
-    LiveRange* range_;
-    LiveRangeGroup* group_;
-  } candidate_;
-};
-
-
-// Schedule processing (allocating) of AllocationCandidates.
-class AllocationScheduler final : ZoneObject {
- public:
-  explicit AllocationScheduler(Zone* zone) : queue_(zone) {}
-  void Schedule(LiveRange* range);
-  void Schedule(LiveRangeGroup* group);
-  AllocationCandidate GetNext();
-  bool empty() const { return queue_.empty(); }
-
- private:
-  typedef ZonePriorityQueue<AllocationCandidate> ScheduleQueue;
-  ScheduleQueue queue_;
-
-  DISALLOW_COPY_AND_ASSIGN(AllocationScheduler);
-};
-
-
-// A variant of the LLVM Greedy Register Allocator. See
-// http://blog.llvm.org/2011/09/greedy-register-allocation-in-llvm-30.html
-class GreedyAllocator final : public RegisterAllocator {
- public:
-  explicit GreedyAllocator(RegisterAllocationData* data, RegisterKind kind,
-                           Zone* local_zone);
-
-  void AllocateRegisters();
-
- private:
-  static const float kAllocatedRangeMultiplier;
-
-  static void UpdateWeightAtAllocation(LiveRange* range) {
-    DCHECK_NE(range->weight(), LiveRange::kInvalidWeight);
-    range->set_weight(range->weight() * kAllocatedRangeMultiplier);
-  }
-
-
-  static void UpdateWeightAtEviction(LiveRange* range) {
-    DCHECK_NE(range->weight(), LiveRange::kInvalidWeight);
-    range->set_weight(range->weight() / kAllocatedRangeMultiplier);
-  }
-
-  AllocationScheduler& scheduler() { return scheduler_; }
-  CoalescedLiveRanges* current_allocations(unsigned i) {
-    return allocations_[i];
-  }
-
-  CoalescedLiveRanges* current_allocations(unsigned i) const {
-    return allocations_[i];
-  }
-
-  Zone* local_zone() const { return local_zone_; }
-  ZoneVector<LiveRangeGroup*>& groups() { return groups_; }
-  const ZoneVector<LiveRangeGroup*>& groups() const { return groups_; }
-
-  // Insert fixed ranges.
-  void PreallocateFixedRanges();
-
-  void GroupLiveRanges();
-
-  // Schedule unassigned live ranges for allocation.
-  void ScheduleAllocationCandidates();
-
-  void AllocateRegisterToRange(unsigned reg_id, LiveRange* range) {
-    UpdateWeightAtAllocation(range);
-    current_allocations(reg_id)->AllocateRange(range);
-  }
-  // Evict and reschedule conflicts of a given range, at a given register.
-  void EvictAndRescheduleConflicts(unsigned reg_id, const LiveRange* range);
-
-  void TryAllocateCandidate(const AllocationCandidate& candidate);
-  void TryAllocateLiveRange(LiveRange* range);
-  void TryAllocateGroup(LiveRangeGroup* group);
-
-  // Calculate the weight of a candidate for allocation.
-  void EnsureValidRangeWeight(LiveRange* range);
-
-  // Calculate the new weight of a range that is about to be allocated.
-  float GetAllocatedRangeWeight(float candidate_weight);
-
-  // Returns kInvalidWeight if there are no conflicts, or the largest weight of
-  // a range conflicting with the given range, at the given register.
-  float GetMaximumConflictingWeight(unsigned reg_id, const LiveRange* range,
-                                    float competing_weight) const;
-
-  // Returns kInvalidWeight if there are no conflicts, or the largest weight of
-  // a range conflicting with the given range, at the given register.
-  float GetMaximumConflictingWeight(unsigned reg_id,
-                                    const LiveRangeGroup* group,
-                                    float group_weight) const;
-
-  // This is the extension point for splitting heuristics.
-  void SplitOrSpillBlockedRange(LiveRange* range);
-
-  // Find a good position where to fill, after a range was spilled after a call.
-  LifetimePosition FindSplitPositionAfterCall(const LiveRange* range,
-                                              int call_index);
-  // Split a range around all calls it passes over. Returns true if any changes
-  // were made, or false if no calls were found.
-  bool TrySplitAroundCalls(LiveRange* range);
-
-  // Find a split position at the outmost loop.
-  LifetimePosition FindSplitPositionBeforeLoops(LiveRange* range);
-
-  // Finds the first call instruction in the path of this range. Splits before
-  // and requeues that segment (if any), spills the section over the call, and
-  // returns the section after the call. The return is:
-  // - same range, if no call was found
-  // - nullptr, if the range finished at the call and there's no "after the
-  //   call" portion.
-  // - the portion after the call.
-  LiveRange* GetRemainderAfterSplittingAroundFirstCall(LiveRange* range);
-
-  // While we attempt to merge spill ranges later on in the allocation pipeline,
-  // we want to ensure group elements get merged. Waiting until later may hinder
-  // merge-ability, since the pipeline merger (being naive) may create conflicts
-  // between spill ranges of group members.
-  void TryReuseSpillRangesForGroups();
-
-  LifetimePosition GetLastResortSplitPosition(const LiveRange* range);
-
-  bool IsProgressPossible(const LiveRange* range);
-
-  // Necessary heuristic: spill when all else failed.
-  void SpillRangeAsLastResort(LiveRange* range);
-
-  void AssignRangeToRegister(int reg_id, LiveRange* range);
-
-  Zone* local_zone_;
-  ZoneVector<CoalescedLiveRanges*> allocations_;
-  AllocationScheduler scheduler_;
-  ZoneVector<LiveRangeGroup*> groups_;
-
-  DISALLOW_COPY_AND_ASSIGN(GreedyAllocator);
-};
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
-#endif  // V8_GREEDY_ALLOCATOR_H_
diff --git a/src/compiler/ia32/code-generator-ia32.cc b/src/compiler/ia32/code-generator-ia32.cc
index ee05ad0..6df22f6 100644
--- a/src/compiler/ia32/code-generator-ia32.cc
+++ b/src/compiler/ia32/code-generator-ia32.cc
@@ -44,11 +44,11 @@
     if (op->IsRegister()) {
       DCHECK(extra == 0);
       return Operand(ToRegister(op));
-    } else if (op->IsDoubleRegister()) {
+    } else if (op->IsFPRegister()) {
       DCHECK(extra == 0);
       return Operand(ToDoubleRegister(op));
     }
-    DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
+    DCHECK(op->IsStackSlot() || op->IsFPStackSlot());
     return SlotToOperand(AllocatedOperand::cast(op)->index(), extra);
   }
 
@@ -59,12 +59,19 @@
   }
 
   Operand HighOperand(InstructionOperand* op) {
-    DCHECK(op->IsDoubleStackSlot());
+    DCHECK(op->IsFPStackSlot());
     return ToOperand(op, kPointerSize);
   }
 
   Immediate ToImmediate(InstructionOperand* operand) {
     Constant constant = ToConstant(operand);
+    if (constant.type() == Constant::kInt32 &&
+        (constant.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
+         constant.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE ||
+         constant.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE)) {
+      return Immediate(reinterpret_cast<Address>(constant.ToInt32()),
+                       constant.rmode());
+    }
     switch (constant.type()) {
       case Constant::kInt32:
         return Immediate(constant.ToInt32());
@@ -113,8 +120,8 @@
       }
       case kMode_MRI: {
         Register base = InputRegister(NextOffset(offset));
-        int32_t disp = InputInt32(NextOffset(offset));
-        return Operand(base, disp);
+        Constant ctant = ToConstant(instr_->InputAt(NextOffset(offset)));
+        return Operand(base, ctant.ToInt32(), ctant.rmode());
       }
       case kMode_MR1:
       case kMode_MR2:
@@ -133,8 +140,8 @@
         Register base = InputRegister(NextOffset(offset));
         Register index = InputRegister(NextOffset(offset));
         ScaleFactor scale = ScaleFor(kMode_MR1I, mode);
-        int32_t disp = InputInt32(NextOffset(offset));
-        return Operand(base, index, scale, disp);
+        Constant ctant = ToConstant(instr_->InputAt(NextOffset(offset)));
+        return Operand(base, index, scale, ctant.ToInt32(), ctant.rmode());
       }
       case kMode_M1:
       case kMode_M2:
@@ -151,12 +158,12 @@
       case kMode_M8I: {
         Register index = InputRegister(NextOffset(offset));
         ScaleFactor scale = ScaleFor(kMode_M1I, mode);
-        int32_t disp = InputInt32(NextOffset(offset));
-        return Operand(index, scale, disp);
+        Constant ctant = ToConstant(instr_->InputAt(NextOffset(offset)));
+        return Operand(index, scale, ctant.ToInt32(), ctant.rmode());
       }
       case kMode_MI: {
-        int32_t disp = InputInt32(NextOffset(offset));
-        return Operand(Immediate(disp));
+        Constant ctant = ToConstant(instr_->InputAt(NextOffset(offset)));
+        return Operand(ctant.ToInt32(), ctant.rmode());
       }
       case kMode_None:
         UNREACHABLE();
@@ -357,13 +364,42 @@
     }                                                                 \
   } while (0)
 
+#define ASSEMBLE_IEEE754_BINOP(name)                                          \
+  do {                                                                        \
+    /* Pass two doubles as arguments on the stack. */                         \
+    __ PrepareCallCFunction(4, eax);                                          \
+    __ movsd(Operand(esp, 0 * kDoubleSize), i.InputDoubleRegister(0));        \
+    __ movsd(Operand(esp, 1 * kDoubleSize), i.InputDoubleRegister(1));        \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \
+                     4);                                                      \
+    /* Return value is in st(0) on ia32. */                                   \
+    /* Store it into the result register. */                                  \
+    __ sub(esp, Immediate(kDoubleSize));                                      \
+    __ fstp_d(Operand(esp, 0));                                               \
+    __ movsd(i.OutputDoubleRegister(), Operand(esp, 0));                      \
+    __ add(esp, Immediate(kDoubleSize));                                      \
+  } while (false)
+
+#define ASSEMBLE_IEEE754_UNOP(name)                                           \
+  do {                                                                        \
+    /* Pass one double as argument on the stack. */                           \
+    __ PrepareCallCFunction(2, eax);                                          \
+    __ movsd(Operand(esp, 0 * kDoubleSize), i.InputDoubleRegister(0));        \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \
+                     2);                                                      \
+    /* Return value is in st(0) on ia32. */                                   \
+    /* Store it into the result register. */                                  \
+    __ sub(esp, Immediate(kDoubleSize));                                      \
+    __ fstp_d(Operand(esp, 0));                                               \
+    __ movsd(i.OutputDoubleRegister(), Operand(esp, 0));                      \
+    __ add(esp, Immediate(kDoubleSize));                                      \
+  } while (false)
+
 void CodeGenerator::AssembleDeconstructFrame() {
   __ mov(esp, ebp);
   __ pop(ebp);
 }
 
-void CodeGenerator::AssembleSetupStackPointer() {}
-
 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
   int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
   if (sp_slot_delta > 0) {
@@ -424,7 +460,8 @@
 }
 
 // Assembles an instruction after register allocation, producing machine code.
-void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
+CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
+    Instruction* instr) {
   IA32OperandConverter i(this, instr);
   InstructionCode opcode = instr->opcode();
   ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode);
@@ -462,6 +499,15 @@
       frame_access_state()->ClearSPDelta();
       break;
     }
+    case kArchTailCallAddress: {
+      int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
+      AssembleDeconstructActivationRecord(stack_param_delta);
+      CHECK(!HasImmediateInput(instr, 0));
+      Register reg = i.InputRegister(0);
+      __ jmp(reg);
+      frame_access_state()->ClearSPDelta();
+      break;
+    }
     case kArchCallJSFunction: {
       EnsureSpaceForLazyDeopt();
       Register func = i.InputRegister(0);
@@ -525,6 +571,14 @@
     case kArchTableSwitch:
       AssembleArchTableSwitch(instr);
       break;
+    case kArchComment: {
+      Address comment_string = i.InputExternalReference(0).address();
+      __ RecordComment(reinterpret_cast<const char*>(comment_string));
+      break;
+    }
+    case kArchDebugBreak:
+      __ int3();
+      break;
     case kArchNop:
     case kArchThrowTerminator:
       // don't emit code for nops.
@@ -534,7 +588,9 @@
           BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
       Deoptimizer::BailoutType bailout_type =
           Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
-      AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      CodeGenResult result =
+          AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      if (result != kSuccess) return result;
       break;
     }
     case kArchRet:
@@ -593,6 +649,45 @@
       __ lea(i.OutputRegister(), Operand(base, offset.offset()));
       break;
     }
+    case kIeee754Float64Atan:
+      ASSEMBLE_IEEE754_UNOP(atan);
+      break;
+    case kIeee754Float64Atan2:
+      ASSEMBLE_IEEE754_BINOP(atan2);
+      break;
+    case kIeee754Float64Cbrt:
+      ASSEMBLE_IEEE754_UNOP(cbrt);
+      break;
+    case kIeee754Float64Cos:
+      ASSEMBLE_IEEE754_UNOP(cos);
+      break;
+    case kIeee754Float64Expm1:
+      ASSEMBLE_IEEE754_UNOP(expm1);
+      break;
+    case kIeee754Float64Exp:
+      ASSEMBLE_IEEE754_UNOP(exp);
+      break;
+    case kIeee754Float64Atanh:
+      ASSEMBLE_IEEE754_UNOP(atanh);
+      break;
+    case kIeee754Float64Log:
+      ASSEMBLE_IEEE754_UNOP(log);
+      break;
+    case kIeee754Float64Log1p:
+      ASSEMBLE_IEEE754_UNOP(log1p);
+      break;
+    case kIeee754Float64Log2:
+      ASSEMBLE_IEEE754_UNOP(log2);
+      break;
+    case kIeee754Float64Log10:
+      ASSEMBLE_IEEE754_UNOP(log10);
+      break;
+    case kIeee754Float64Sin:
+      ASSEMBLE_IEEE754_UNOP(sin);
+      break;
+    case kIeee754Float64Tan:
+      ASSEMBLE_IEEE754_UNOP(tan);
+      break;
     case kIA32Add:
       if (HasImmediateInput(instr, 1)) {
         __ add(i.InputOperand(0), i.InputImmediate(1));
@@ -965,14 +1060,14 @@
       __ LoadUint32(i.OutputDoubleRegister(), i.InputOperand(0));
       break;
     case kSSEFloat64ExtractLowWord32:
-      if (instr->InputAt(0)->IsDoubleStackSlot()) {
+      if (instr->InputAt(0)->IsFPStackSlot()) {
         __ mov(i.OutputRegister(), i.InputOperand(0));
       } else {
         __ movd(i.OutputRegister(), i.InputDoubleRegister(0));
       }
       break;
     case kSSEFloat64ExtractHighWord32:
-      if (instr->InputAt(0)->IsDoubleStackSlot()) {
+      if (instr->InputAt(0)->IsFPStackSlot()) {
         __ mov(i.OutputRegister(), i.InputOperand(0, kDoubleSize / 2));
       } else {
         __ Pextrd(i.OutputRegister(), i.InputDoubleRegister(0), 1);
@@ -1097,6 +1192,10 @@
       __ vxorpd(i.OutputDoubleRegister(), kScratchDoubleReg, i.InputOperand(0));
       break;
     }
+    case kSSEFloat64SilenceNaN:
+      __ xorpd(kScratchDoubleReg, kScratchDoubleReg);
+      __ subsd(i.InputDoubleRegister(0), kScratchDoubleReg);
+      break;
     case kIA32Movsxbl:
       __ movsx_b(i.OutputRegister(), i.MemoryOperand());
       break;
@@ -1161,7 +1260,7 @@
       }
       break;
     case kIA32BitcastFI:
-      if (instr->InputAt(0)->IsDoubleStackSlot()) {
+      if (instr->InputAt(0)->IsFPStackSlot()) {
         __ mov(i.OutputRegister(), i.InputOperand(0));
       } else {
         __ movd(i.OutputRegister(), i.InputDoubleRegister(0));
@@ -1210,10 +1309,10 @@
       break;
     }
     case kIA32PushFloat32:
-      if (instr->InputAt(0)->IsDoubleRegister()) {
-        __ sub(esp, Immediate(kDoubleSize));
+      if (instr->InputAt(0)->IsFPRegister()) {
+        __ sub(esp, Immediate(kFloatSize));
         __ movss(Operand(esp, 0), i.InputDoubleRegister(0));
-        frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
+        frame_access_state()->IncreaseSPDelta(kFloatSize / kPointerSize);
       } else if (HasImmediateInput(instr, 0)) {
         __ Move(kScratchDoubleReg, i.InputDouble(0));
         __ sub(esp, Immediate(kDoubleSize));
@@ -1227,7 +1326,7 @@
       }
       break;
     case kIA32PushFloat64:
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ sub(esp, Immediate(kDoubleSize));
         __ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
@@ -1244,10 +1343,10 @@
       }
       break;
     case kIA32Push:
-      if (instr->InputAt(0)->IsDoubleRegister()) {
-        __ sub(esp, Immediate(kDoubleSize));
+      if (instr->InputAt(0)->IsFPRegister()) {
+        __ sub(esp, Immediate(kFloatSize));
         __ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
-        frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
+        frame_access_state()->IncreaseSPDelta(kFloatSize / kPointerSize);
       } else if (HasImmediateInput(instr, 0)) {
         __ push(i.InputImmediate(0));
         frame_access_state()->IncreaseSPDelta(1);
@@ -1265,6 +1364,24 @@
       }
       break;
     }
+    case kIA32Xchgb: {
+      size_t index = 0;
+      Operand operand = i.MemoryOperand(&index);
+      __ xchg_b(i.InputRegister(index), operand);
+      break;
+    }
+    case kIA32Xchgw: {
+      size_t index = 0;
+      Operand operand = i.MemoryOperand(&index);
+      __ xchg_w(i.InputRegister(index), operand);
+      break;
+    }
+    case kIA32Xchgl: {
+      size_t index = 0;
+      Operand operand = i.MemoryOperand(&index);
+      __ xchg(i.InputRegister(index), operand);
+      break;
+    }
     case kCheckedLoadInt8:
       ASSEMBLE_CHECKED_LOAD_INTEGER(movsx_b);
       break;
@@ -1311,7 +1428,18 @@
     case kCheckedStoreWord64:
       UNREACHABLE();  // currently unsupported checked int64 load/store.
       break;
+    case kAtomicLoadInt8:
+    case kAtomicLoadUint8:
+    case kAtomicLoadInt16:
+    case kAtomicLoadUint16:
+    case kAtomicLoadWord32:
+    case kAtomicStoreWord8:
+    case kAtomicStoreWord16:
+    case kAtomicStoreWord32:
+      UNREACHABLE();  // Won't be generated by instruction selector.
+      break;
   }
+  return kSuccess;
 }  // NOLINT(readability/fn_size)
 
 
@@ -1485,12 +1613,13 @@
   __ jmp(Operand::JumpTable(input, times_4, table));
 }
 
-
-void CodeGenerator::AssembleDeoptimizerCall(
+CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
     int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
   Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
       isolate(), deoptimization_id, bailout_type);
+  if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
   __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
+  return kSuccess;
 }
 
 
@@ -1621,8 +1750,21 @@
 //                                            | RET | args |  caller frame |
 //                                            ^ esp                        ^ ebp
 
+void CodeGenerator::FinishFrame(Frame* frame) {
+  CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
+  const RegList saves = descriptor->CalleeSavedRegisters();
+  if (saves != 0) {  // Save callee-saved registers.
+    DCHECK(!info()->is_osr());
+    int pushed = 0;
+    for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
+      if (!((1 << i) & saves)) continue;
+      ++pushed;
+    }
+    frame->AllocateSavedCalleeRegisterSlots(pushed);
+  }
+}
 
-void CodeGenerator::AssemblePrologue() {
+void CodeGenerator::AssembleConstructFrame() {
   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
   if (frame_access_state()->has_frame()) {
     if (descriptor->IsCFunctionCall()) {
@@ -1634,7 +1776,9 @@
       __ StubPrologue(info()->GetOutputStackFrameType());
     }
   }
-  int stack_shrink_slots = frame()->GetSpillSlotCount();
+
+  int shrink_slots = frame()->GetSpillSlotCount();
+
   if (info()->is_osr()) {
     // TurboFan OSR-compiled functions cannot be entered directly.
     __ Abort(kShouldNotDirectlyEnterOsrFunction);
@@ -1645,12 +1789,12 @@
     // remaining stack slots.
     if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
     osr_pc_offset_ = __ pc_offset();
-    stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
+    shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
   }
 
   const RegList saves = descriptor->CalleeSavedRegisters();
-  if (stack_shrink_slots > 0) {
-    __ sub(esp, Immediate(stack_shrink_slots * kPointerSize));
+  if (shrink_slots > 0) {
+    __ sub(esp, Immediate(shrink_slots * kPointerSize));
   }
 
   if (saves != 0) {  // Save callee-saved registers.
@@ -1661,7 +1805,6 @@
       __ push(Register::from_code(i));
       ++pushed;
     }
-    frame()->AllocateSavedCalleeRegisterSlots(pushed);
   }
 }
 
@@ -1756,11 +1899,11 @@
     } else if (src_constant.type() == Constant::kFloat32) {
       // TODO(turbofan): Can we do better here?
       uint32_t src = bit_cast<uint32_t>(src_constant.ToFloat32());
-      if (destination->IsDoubleRegister()) {
+      if (destination->IsFPRegister()) {
         XMMRegister dst = g.ToDoubleRegister(destination);
         __ Move(dst, src);
       } else {
-        DCHECK(destination->IsDoubleStackSlot());
+        DCHECK(destination->IsFPStackSlot());
         Operand dst = g.ToOperand(destination);
         __ Move(dst, Immediate(src));
       }
@@ -1769,31 +1912,31 @@
       uint64_t src = bit_cast<uint64_t>(src_constant.ToFloat64());
       uint32_t lower = static_cast<uint32_t>(src);
       uint32_t upper = static_cast<uint32_t>(src >> 32);
-      if (destination->IsDoubleRegister()) {
+      if (destination->IsFPRegister()) {
         XMMRegister dst = g.ToDoubleRegister(destination);
         __ Move(dst, src);
       } else {
-        DCHECK(destination->IsDoubleStackSlot());
+        DCHECK(destination->IsFPStackSlot());
         Operand dst0 = g.ToOperand(destination);
         Operand dst1 = g.HighOperand(destination);
         __ Move(dst0, Immediate(lower));
         __ Move(dst1, Immediate(upper));
       }
     }
-  } else if (source->IsDoubleRegister()) {
+  } else if (source->IsFPRegister()) {
     XMMRegister src = g.ToDoubleRegister(source);
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       XMMRegister dst = g.ToDoubleRegister(destination);
       __ movaps(dst, src);
     } else {
-      DCHECK(destination->IsDoubleStackSlot());
+      DCHECK(destination->IsFPStackSlot());
       Operand dst = g.ToOperand(destination);
       __ movsd(dst, src);
     }
-  } else if (source->IsDoubleStackSlot()) {
-    DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
+  } else if (source->IsFPStackSlot()) {
+    DCHECK(destination->IsFPRegister() || destination->IsFPStackSlot());
     Operand src = g.ToOperand(source);
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       XMMRegister dst = g.ToDoubleRegister(destination);
       __ movsd(dst, src);
     } else {
@@ -1841,21 +1984,21 @@
     frame_access_state()->IncreaseSPDelta(-1);
     Operand src2 = g.ToOperand(source);
     __ pop(src2);
-  } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) {
+  } else if (source->IsFPRegister() && destination->IsFPRegister()) {
     // XMM register-register swap.
     XMMRegister src = g.ToDoubleRegister(source);
     XMMRegister dst = g.ToDoubleRegister(destination);
     __ movaps(kScratchDoubleReg, src);
     __ movaps(src, dst);
     __ movaps(dst, kScratchDoubleReg);
-  } else if (source->IsDoubleRegister() && destination->IsDoubleStackSlot()) {
+  } else if (source->IsFPRegister() && destination->IsFPStackSlot()) {
     // XMM register-memory swap.
     XMMRegister reg = g.ToDoubleRegister(source);
     Operand other = g.ToOperand(destination);
     __ movsd(kScratchDoubleReg, other);
     __ movsd(other, reg);
     __ movaps(reg, kScratchDoubleReg);
-  } else if (source->IsDoubleStackSlot() && destination->IsDoubleStackSlot()) {
+  } else if (source->IsFPStackSlot() && destination->IsFPStackSlot()) {
     // Double-width memory-to-memory.
     Operand src0 = g.ToOperand(source);
     Operand src1 = g.HighOperand(source);
@@ -1881,9 +2024,6 @@
 }
 
 
-void CodeGenerator::AddNopForSmiCodeInlining() { __ nop(); }
-
-
 void CodeGenerator::EnsureSpaceForLazyDeopt() {
   if (!info()->ShouldEnsureSpaceForLazyDeopt()) {
     return;
diff --git a/src/compiler/ia32/instruction-codes-ia32.h b/src/compiler/ia32/instruction-codes-ia32.h
index 3cf2094..09d4615 100644
--- a/src/compiler/ia32/instruction-codes-ia32.h
+++ b/src/compiler/ia32/instruction-codes-ia32.h
@@ -81,6 +81,7 @@
   V(SSEFloat64InsertLowWord32)     \
   V(SSEFloat64InsertHighWord32)    \
   V(SSEFloat64LoadLowWord32)       \
+  V(SSEFloat64SilenceNaN)          \
   V(AVXFloat32Add)                 \
   V(AVXFloat32Sub)                 \
   V(AVXFloat32Mul)                 \
@@ -113,7 +114,10 @@
   V(IA32PushFloat32)               \
   V(IA32PushFloat64)               \
   V(IA32Poke)                      \
-  V(IA32StackCheck)
+  V(IA32StackCheck)                \
+  V(IA32Xchgb)                     \
+  V(IA32Xchgw)                     \
+  V(IA32Xchgl)
 
 // Addressing modes represent the "shape" of inputs to an instruction.
 // Many instructions support multiple addressing modes. Addressing modes
diff --git a/src/compiler/ia32/instruction-scheduler-ia32.cc b/src/compiler/ia32/instruction-scheduler-ia32.cc
index 803fdf6..f19c328 100644
--- a/src/compiler/ia32/instruction-scheduler-ia32.cc
+++ b/src/compiler/ia32/instruction-scheduler-ia32.cc
@@ -84,6 +84,7 @@
     case kSSEFloat64InsertLowWord32:
     case kSSEFloat64InsertHighWord32:
     case kSSEFloat64LoadLowWord32:
+    case kSSEFloat64SilenceNaN:
     case kAVXFloat32Add:
     case kAVXFloat32Sub:
     case kAVXFloat32Mul:
@@ -127,6 +128,11 @@
     case kIA32Poke:
       return kHasSideEffect;
 
+    case kIA32Xchgb:
+    case kIA32Xchgw:
+    case kIA32Xchgl:
+      return kIsLoadOperation | kHasSideEffect;
+
 #define CASE(Name) case k##Name:
     COMMON_ARCH_OPCODE_LIST(CASE)
 #undef CASE
diff --git a/src/compiler/ia32/instruction-selector-ia32.cc b/src/compiler/ia32/instruction-selector-ia32.cc
index 5c4acce..3ffdd30 100644
--- a/src/compiler/ia32/instruction-selector-ia32.cc
+++ b/src/compiler/ia32/instruction-selector-ia32.cc
@@ -27,11 +27,15 @@
     return DefineAsRegister(node);
   }
 
-  bool CanBeMemoryOperand(InstructionCode opcode, Node* node, Node* input) {
+  bool CanBeMemoryOperand(InstructionCode opcode, Node* node, Node* input,
+                          int effect_level) {
     if (input->opcode() != IrOpcode::kLoad ||
         !selector()->CanCover(node, input)) {
       return false;
     }
+    if (effect_level != selector()->GetEffectLevel(input)) {
+      return false;
+    }
     MachineRepresentation rep =
         LoadRepresentationOf(input->op()).representation();
     switch (opcode) {
@@ -56,13 +60,20 @@
       case IrOpcode::kInt32Constant:
       case IrOpcode::kNumberConstant:
       case IrOpcode::kExternalConstant:
+      case IrOpcode::kRelocatableInt32Constant:
+      case IrOpcode::kRelocatableInt64Constant:
         return true;
       case IrOpcode::kHeapConstant: {
+// TODO(bmeurer): We must not dereference handles concurrently. If we
+// really have to this here, then we need to find a way to put this
+// information on the HeapConstant node already.
+#if 0
         // Constants in new space cannot be used as immediates in V8 because
         // the GC does not scan code objects when collecting the new generation.
         Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node);
         Isolate* isolate = value->GetIsolate();
         return !isolate->heap()->InNewSpace(*value);
+#endif
       }
       default:
         return false;
@@ -870,15 +881,12 @@
   VisitRO(this, node, kSSEFloat64ToFloat32);
 }
 
+void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
+  VisitRR(this, node, kArchTruncateDoubleToI);
+}
 
-void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
-  switch (TruncationModeOf(node->op())) {
-    case TruncationMode::kJavaScript:
-      return VisitRR(this, node, kArchTruncateDoubleToI);
-    case TruncationMode::kRoundToZero:
-      return VisitRO(this, node, kSSEFloat64ToInt32);
-  }
-  UNREACHABLE();
+void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
+  VisitRO(this, node, kSSEFloat64ToInt32);
 }
 
 
@@ -915,6 +923,9 @@
   VisitRROFloat(this, node, kAVXFloat32Sub, kSSEFloat32Sub);
 }
 
+void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
+  VisitRROFloat(this, node, kAVXFloat32Sub, kSSEFloat32Sub);
+}
 
 void InstructionSelector::VisitFloat64Sub(Node* node) {
   IA32OperandGenerator g(this);
@@ -939,6 +950,9 @@
   VisitRROFloat(this, node, kAVXFloat64Sub, kSSEFloat64Sub);
 }
 
+void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
+  VisitRROFloat(this, node, kAVXFloat64Sub, kSSEFloat64Sub);
+}
 
 void InstructionSelector::VisitFloat32Mul(Node* node) {
   VisitRROFloat(this, node, kAVXFloat32Mul, kSSEFloat32Mul);
@@ -1000,7 +1014,6 @@
   VisitFloatUnop(this, node, node->InputAt(0), kAVXFloat64Abs, kSSEFloat64Abs);
 }
 
-
 void InstructionSelector::VisitFloat32Sqrt(Node* node) {
   VisitRO(this, node, kSSEFloat32Sqrt);
 }
@@ -1055,6 +1068,24 @@
   VisitRR(this, node, kSSEFloat64Round | MiscField::encode(kRoundToNearest));
 }
 
+void InstructionSelector::VisitFloat32Neg(Node* node) { UNREACHABLE(); }
+
+void InstructionSelector::VisitFloat64Neg(Node* node) { UNREACHABLE(); }
+
+void InstructionSelector::VisitFloat64Ieee754Binop(Node* node,
+                                                   InstructionCode opcode) {
+  IA32OperandGenerator g(this);
+  Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(node->InputAt(0)),
+       g.UseRegister(node->InputAt(1)))
+      ->MarkAsCall();
+}
+
+void InstructionSelector::VisitFloat64Ieee754Unop(Node* node,
+                                                  InstructionCode opcode) {
+  IA32OperandGenerator g(this);
+  Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(node->InputAt(0)))
+      ->MarkAsCall();
+}
 
 void InstructionSelector::EmitPrepareArguments(
     ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
@@ -1089,7 +1120,7 @@
           g.CanBeImmediate(input.node())
               ? g.UseImmediate(input.node())
               : IsSupported(ATOM) ||
-                        sequence()->IsFloat(GetVirtualRegister(input.node()))
+                        sequence()->IsFP(GetVirtualRegister(input.node()))
                     ? g.UseRegister(input.node())
                     : g.Use(input.node());
       if (input.type() == MachineType::Float32()) {
@@ -1225,18 +1256,24 @@
 
   InstructionCode narrowed_opcode = TryNarrowOpcodeSize(opcode, left, right);
 
+  int effect_level = selector->GetEffectLevel(node);
+  if (cont->IsBranch()) {
+    effect_level = selector->GetEffectLevel(
+        cont->true_block()->PredecessorAt(0)->control_input());
+  }
+
   // If one of the two inputs is an immediate, make sure it's on the right, or
   // if one of the two inputs is a memory operand, make sure it's on the left.
   if ((!g.CanBeImmediate(right) && g.CanBeImmediate(left)) ||
-      (g.CanBeMemoryOperand(narrowed_opcode, node, right) &&
-       !g.CanBeMemoryOperand(narrowed_opcode, node, left))) {
+      (g.CanBeMemoryOperand(narrowed_opcode, node, right, effect_level) &&
+       !g.CanBeMemoryOperand(narrowed_opcode, node, left, effect_level))) {
     if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
     std::swap(left, right);
   }
 
   // Match immediates on right side of comparison.
   if (g.CanBeImmediate(right)) {
-    if (g.CanBeMemoryOperand(opcode, node, left)) {
+    if (g.CanBeMemoryOperand(opcode, node, left, effect_level)) {
       // TODO(epertoso): we should use `narrowed_opcode' here once we match
       // immediates too.
       return VisitCompareWithMemoryOperand(selector, opcode, left,
@@ -1247,7 +1284,7 @@
   }
 
   // Match memory operands on left side of comparison.
-  if (g.CanBeMemoryOperand(narrowed_opcode, node, left)) {
+  if (g.CanBeMemoryOperand(narrowed_opcode, node, left, effect_level)) {
     bool needs_byte_register =
         narrowed_opcode == kIA32Test8 || narrowed_opcode == kIA32Cmp8;
     return VisitCompareWithMemoryOperand(
@@ -1563,6 +1600,58 @@
        g.UseRegister(left), g.Use(right));
 }
 
+void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
+  IA32OperandGenerator g(this);
+  Emit(kSSEFloat64SilenceNaN, g.DefineSameAsFirst(node),
+       g.UseRegister(node->InputAt(0)));
+}
+
+void InstructionSelector::VisitAtomicLoad(Node* node) {
+  LoadRepresentation load_rep = LoadRepresentationOf(node->op());
+  DCHECK(load_rep.representation() == MachineRepresentation::kWord8 ||
+         load_rep.representation() == MachineRepresentation::kWord16 ||
+         load_rep.representation() == MachineRepresentation::kWord32);
+  USE(load_rep);
+  VisitLoad(node);
+}
+
+void InstructionSelector::VisitAtomicStore(Node* node) {
+  IA32OperandGenerator g(this);
+  Node* base = node->InputAt(0);
+  Node* index = node->InputAt(1);
+  Node* value = node->InputAt(2);
+
+  MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
+  ArchOpcode opcode = kArchNop;
+  switch (rep) {
+    case MachineRepresentation::kWord8:
+      opcode = kIA32Xchgb;
+      break;
+    case MachineRepresentation::kWord16:
+      opcode = kIA32Xchgw;
+      break;
+    case MachineRepresentation::kWord32:
+      opcode = kIA32Xchgl;
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+  AddressingMode addressing_mode;
+  InstructionOperand inputs[4];
+  size_t input_count = 0;
+  inputs[input_count++] = g.UseUniqueRegister(base);
+  if (g.CanBeImmediate(index)) {
+    inputs[input_count++] = g.UseImmediate(index);
+    addressing_mode = kMode_MRI;
+  } else {
+    inputs[input_count++] = g.UseUniqueRegister(index);
+    addressing_mode = kMode_MR1;
+  }
+  inputs[input_count++] = g.UseUniqueRegister(value);
+  InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
+  Emit(code, 0, nullptr, input_count, inputs);
+}
 
 // static
 MachineOperatorBuilder::Flags
@@ -1590,6 +1679,13 @@
   return flags;
 }
 
+// static
+MachineOperatorBuilder::AlignmentRequirements
+InstructionSelector::AlignmentRequirements() {
+  return MachineOperatorBuilder::AlignmentRequirements::
+      FullUnalignedAccessSupport();
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/src/compiler/instruction-codes.h b/src/compiler/instruction-codes.h
index b005083..0b3132f 100644
--- a/src/compiler/instruction-codes.h
+++ b/src/compiler/instruction-codes.h
@@ -48,6 +48,7 @@
   V(ArchCallJSFunction)                   \
   V(ArchTailCallJSFunctionFromJSFunction) \
   V(ArchTailCallJSFunction)               \
+  V(ArchTailCallAddress)                  \
   V(ArchPrepareCallCFunction)             \
   V(ArchCallCFunction)                    \
   V(ArchPrepareTailCall)                  \
@@ -55,6 +56,8 @@
   V(ArchLookupSwitch)                     \
   V(ArchTableSwitch)                      \
   V(ArchNop)                              \
+  V(ArchDebugBreak)                       \
+  V(ArchComment)                          \
   V(ArchThrowTerminator)                  \
   V(ArchDeoptimize)                       \
   V(ArchRet)                              \
@@ -77,7 +80,28 @@
   V(CheckedStoreWord64)                   \
   V(CheckedStoreFloat32)                  \
   V(CheckedStoreFloat64)                  \
-  V(ArchStackSlot)
+  V(ArchStackSlot)                        \
+  V(AtomicLoadInt8)                       \
+  V(AtomicLoadUint8)                      \
+  V(AtomicLoadInt16)                      \
+  V(AtomicLoadUint16)                     \
+  V(AtomicLoadWord32)                     \
+  V(AtomicStoreWord8)                     \
+  V(AtomicStoreWord16)                    \
+  V(AtomicStoreWord32)                    \
+  V(Ieee754Float64Atan)                   \
+  V(Ieee754Float64Atan2)                  \
+  V(Ieee754Float64Atanh)                  \
+  V(Ieee754Float64Cbrt)                   \
+  V(Ieee754Float64Cos)                    \
+  V(Ieee754Float64Exp)                    \
+  V(Ieee754Float64Expm1)                  \
+  V(Ieee754Float64Log)                    \
+  V(Ieee754Float64Log1p)                  \
+  V(Ieee754Float64Log10)                  \
+  V(Ieee754Float64Log2)                   \
+  V(Ieee754Float64Sin)                    \
+  V(Ieee754Float64Tan)
 
 #define ARCH_OPCODE_LIST(V)  \
   COMMON_ARCH_OPCODE_LIST(V) \
diff --git a/src/compiler/instruction-scheduler.cc b/src/compiler/instruction-scheduler.cc
index b612cd1..3ef7c08 100644
--- a/src/compiler/instruction-scheduler.cc
+++ b/src/compiler/instruction-scheduler.cc
@@ -82,7 +82,8 @@
       graph_(zone),
       last_side_effect_instr_(nullptr),
       pending_loads_(zone),
-      last_live_in_reg_marker_(nullptr) {
+      last_live_in_reg_marker_(nullptr),
+      last_deopt_(nullptr) {
 }
 
 
@@ -91,6 +92,7 @@
   DCHECK(last_side_effect_instr_ == nullptr);
   DCHECK(pending_loads_.empty());
   DCHECK(last_live_in_reg_marker_ == nullptr);
+  DCHECK(last_deopt_ == nullptr);
   sequence()->StartBlock(rpo);
 }
 
@@ -106,6 +108,7 @@
   last_side_effect_instr_ = nullptr;
   pending_loads_.clear();
   last_live_in_reg_marker_ = nullptr;
+  last_deopt_ = nullptr;
 }
 
 
@@ -128,6 +131,12 @@
       last_live_in_reg_marker_->AddSuccessor(new_node);
     }
 
+    // Make sure that new instructions are not scheduled before the last
+    // deoptimization point.
+    if (last_deopt_ != nullptr) {
+      last_deopt_->AddSuccessor(new_node);
+    }
+
     // Instructions with side effects and memory operations can't be
     // reordered with respect to each other.
     if (HasSideEffect(instr)) {
@@ -146,6 +155,13 @@
         last_side_effect_instr_->AddSuccessor(new_node);
       }
       pending_loads_.push_back(new_node);
+    } else if (instr->IsDeoptimizeCall()) {
+      // Ensure that deopts are not reordered with respect to side-effect
+      // instructions.
+      if (last_side_effect_instr_ != nullptr) {
+        last_side_effect_instr_->AddSuccessor(new_node);
+      }
+      last_deopt_ = new_node;
     }
 
     // Look for operand dependencies.
@@ -206,6 +222,21 @@
     case kArchParentFramePointer:
     case kArchTruncateDoubleToI:
     case kArchStackSlot:
+    case kArchDebugBreak:
+    case kArchComment:
+    case kIeee754Float64Atan:
+    case kIeee754Float64Atan2:
+    case kIeee754Float64Atanh:
+    case kIeee754Float64Cbrt:
+    case kIeee754Float64Cos:
+    case kIeee754Float64Exp:
+    case kIeee754Float64Expm1:
+    case kIeee754Float64Log:
+    case kIeee754Float64Log1p:
+    case kIeee754Float64Log10:
+    case kIeee754Float64Log2:
+    case kIeee754Float64Sin:
+    case kIeee754Float64Tan:
       return kNoOpcodeFlags;
 
     case kArchStackPointer:
@@ -224,6 +255,7 @@
     case kArchTailCallCodeObject:
     case kArchTailCallJSFunctionFromJSFunction:
     case kArchTailCallJSFunction:
+    case kArchTailCallAddress:
       return kHasSideEffect | kIsBlockTerminator;
 
     case kArchDeoptimize:
@@ -253,6 +285,18 @@
     case kArchStoreWithWriteBarrier:
       return kHasSideEffect;
 
+    case kAtomicLoadInt8:
+    case kAtomicLoadUint8:
+    case kAtomicLoadInt16:
+    case kAtomicLoadUint16:
+    case kAtomicLoadWord32:
+      return kIsLoadOperation;
+
+    case kAtomicStoreWord8:
+    case kAtomicStoreWord16:
+    case kAtomicStoreWord32:
+      return kHasSideEffect;
+
 #define CASE(Name) case k##Name:
     TARGET_ARCH_OPCODE_LIST(CASE)
 #undef CASE
diff --git a/src/compiler/instruction-scheduler.h b/src/compiler/instruction-scheduler.h
index 104c0b9..4f5b0f7 100644
--- a/src/compiler/instruction-scheduler.h
+++ b/src/compiler/instruction-scheduler.h
@@ -177,10 +177,12 @@
   // Identify nops used as a definition point for live-in registers at
   // function entry.
   bool IsFixedRegisterParameter(const Instruction* instr) const {
-    return (instr->arch_opcode() == kArchNop) &&
-      (instr->OutputCount() == 1) &&
-      (instr->OutputAt(0)->IsUnallocated()) &&
-      UnallocatedOperand::cast(instr->OutputAt(0))->HasFixedRegisterPolicy();
+    return (instr->arch_opcode() == kArchNop) && (instr->OutputCount() == 1) &&
+           (instr->OutputAt(0)->IsUnallocated()) &&
+           (UnallocatedOperand::cast(instr->OutputAt(0))
+                ->HasFixedRegisterPolicy() ||
+            UnallocatedOperand::cast(instr->OutputAt(0))
+                ->HasFixedFPRegisterPolicy());
   }
 
   void ComputeTotalLatencies();
@@ -209,6 +211,9 @@
   // All these nops are chained together and added as a predecessor of every
   // other instructions in the basic block.
   ScheduleGraphNode* last_live_in_reg_marker_;
+
+  // Last deoptimization instruction encountered while building the graph.
+  ScheduleGraphNode* last_deopt_;
 };
 
 }  // namespace compiler
diff --git a/src/compiler/instruction-selector-impl.h b/src/compiler/instruction-selector-impl.h
index e750aed..be24e2d 100644
--- a/src/compiler/instruction-selector-impl.h
+++ b/src/compiler/instruction-selector-impl.h
@@ -54,9 +54,10 @@
                                            reg.code(), GetVReg(node)));
   }
 
-  InstructionOperand DefineAsFixed(Node* node, DoubleRegister reg) {
+  template <typename FPRegType>
+  InstructionOperand DefineAsFixed(Node* node, FPRegType reg) {
     return Define(node,
-                  UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
+                  UnallocatedOperand(UnallocatedOperand::FIXED_FP_REGISTER,
                                      reg.code(), GetVReg(node)));
   }
 
@@ -122,10 +123,10 @@
                                         reg.code(), GetVReg(node)));
   }
 
-  InstructionOperand UseFixed(Node* node, DoubleRegister reg) {
-    return Use(node,
-               UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
-                                  reg.code(), GetVReg(node)));
+  template <typename FPRegType>
+  InstructionOperand UseFixed(Node* node, FPRegType reg) {
+    return Use(node, UnallocatedOperand(UnallocatedOperand::FIXED_FP_REGISTER,
+                                        reg.code(), GetVReg(node)));
   }
 
   InstructionOperand UseExplicit(LinkageLocation location) {
@@ -211,10 +212,14 @@
         return Constant(OpParameter<int64_t>(node));
       case IrOpcode::kFloat32Constant:
         return Constant(OpParameter<float>(node));
+      case IrOpcode::kRelocatableInt32Constant:
+      case IrOpcode::kRelocatableInt64Constant:
+        return Constant(OpParameter<RelocatablePtrConstantInfo>(node));
       case IrOpcode::kFloat64Constant:
       case IrOpcode::kNumberConstant:
         return Constant(OpParameter<double>(node));
       case IrOpcode::kExternalConstant:
+      case IrOpcode::kComment:
         return Constant(OpParameter<ExternalReference>(node));
       case IrOpcode::kHeapConstant:
         return Constant(OpParameter<Handle<HeapObject>>(node));
@@ -271,7 +276,7 @@
     }
     // a fixed register.
     if (IsFloatingPoint(rep)) {
-      return UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
+      return UnallocatedOperand(UnallocatedOperand::FIXED_FP_REGISTER,
                                 location.AsRegister(), virtual_register);
     }
     return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc
index d172ed1..558aff3 100644
--- a/src/compiler/instruction-selector.cc
+++ b/src/compiler/instruction-selector.cc
@@ -87,7 +87,6 @@
 #endif
 }
 
-
 void InstructionSelector::StartBlock(RpoNumber rpo) {
   if (FLAG_turbo_instruction_scheduling &&
       InstructionScheduler::SchedulerSupported()) {
@@ -714,6 +713,12 @@
     SetEffectLevel(node, effect_level);
   }
 
+  // We visit the control first, then the nodes in the block, so the block's
+  // control input should be on the same effect level as the last node.
+  if (block->control_input() != nullptr) {
+    SetEffectLevel(block->control_input(), effect_level);
+  }
+
   // Generate code for the block control "top down", but schedule the code
   // "bottom up".
   VisitControl(block);
@@ -859,8 +864,6 @@
       return MarkAsReference(node), VisitIfException(node);
     case IrOpcode::kFinishRegion:
       return MarkAsReference(node), VisitFinishRegion(node);
-    case IrOpcode::kGuard:
-      return MarkAsReference(node), VisitGuard(node);
     case IrOpcode::kParameter: {
       MachineType type =
           linkage()->GetParameterType(ParameterIndexOf(node->op()));
@@ -879,6 +882,8 @@
     case IrOpcode::kInt32Constant:
     case IrOpcode::kInt64Constant:
     case IrOpcode::kExternalConstant:
+    case IrOpcode::kRelocatableInt32Constant:
+    case IrOpcode::kRelocatableInt64Constant:
       return VisitConstant(node);
     case IrOpcode::kFloat32Constant:
       return MarkAsFloat32(node), VisitConstant(node);
@@ -901,6 +906,12 @@
     case IrOpcode::kStateValues:
     case IrOpcode::kObjectState:
       return;
+    case IrOpcode::kDebugBreak:
+      VisitDebugBreak(node);
+      return;
+    case IrOpcode::kComment:
+      VisitComment(node);
+      return;
     case IrOpcode::kLoad: {
       LoadRepresentation type = LoadRepresentationOf(node->op());
       MarkAsRepresentation(type.representation(), node);
@@ -1012,6 +1023,8 @@
       return VisitUint64LessThanOrEqual(node);
     case IrOpcode::kUint64Mod:
       return MarkAsWord64(node), VisitUint64Mod(node);
+    case IrOpcode::kBitcastWordToTagged:
+      return MarkAsReference(node), VisitBitcastWordToTagged(node);
     case IrOpcode::kChangeFloat32ToFloat64:
       return MarkAsFloat64(node), VisitChangeFloat32ToFloat64(node);
     case IrOpcode::kChangeInt32ToFloat64:
@@ -1022,6 +1035,13 @@
       return MarkAsWord32(node), VisitChangeFloat64ToInt32(node);
     case IrOpcode::kChangeFloat64ToUint32:
       return MarkAsWord32(node), VisitChangeFloat64ToUint32(node);
+    case IrOpcode::kFloat64SilenceNaN:
+      MarkAsFloat64(node);
+      if (CanProduceSignalingNaN(node->InputAt(0))) {
+        return VisitFloat64SilenceNaN(node);
+      } else {
+        return EmitIdentity(node);
+      }
     case IrOpcode::kTruncateFloat64ToUint32:
       return MarkAsWord32(node), VisitTruncateFloat64ToUint32(node);
     case IrOpcode::kTruncateFloat32ToInt32:
@@ -1042,10 +1062,12 @@
       return MarkAsWord64(node), VisitChangeUint32ToUint64(node);
     case IrOpcode::kTruncateFloat64ToFloat32:
       return MarkAsFloat32(node), VisitTruncateFloat64ToFloat32(node);
-    case IrOpcode::kTruncateFloat64ToInt32:
-      return MarkAsWord32(node), VisitTruncateFloat64ToInt32(node);
+    case IrOpcode::kTruncateFloat64ToWord32:
+      return MarkAsWord32(node), VisitTruncateFloat64ToWord32(node);
     case IrOpcode::kTruncateInt64ToInt32:
       return MarkAsWord32(node), VisitTruncateInt64ToInt32(node);
+    case IrOpcode::kRoundFloat64ToInt32:
+      return MarkAsWord32(node), VisitRoundFloat64ToInt32(node);
     case IrOpcode::kRoundInt64ToFloat32:
       return MarkAsFloat32(node), VisitRoundInt64ToFloat32(node);
     case IrOpcode::kRoundInt32ToFloat32:
@@ -1070,6 +1092,10 @@
       return MarkAsFloat32(node), VisitFloat32Add(node);
     case IrOpcode::kFloat32Sub:
       return MarkAsFloat32(node), VisitFloat32Sub(node);
+    case IrOpcode::kFloat32SubPreserveNan:
+      return MarkAsFloat32(node), VisitFloat32SubPreserveNan(node);
+    case IrOpcode::kFloat32Neg:
+      return MarkAsFloat32(node), VisitFloat32Neg(node);
     case IrOpcode::kFloat32Mul:
       return MarkAsFloat32(node), VisitFloat32Mul(node);
     case IrOpcode::kFloat32Div:
@@ -1092,6 +1118,10 @@
       return MarkAsFloat64(node), VisitFloat64Add(node);
     case IrOpcode::kFloat64Sub:
       return MarkAsFloat64(node), VisitFloat64Sub(node);
+    case IrOpcode::kFloat64SubPreserveNan:
+      return MarkAsFloat64(node), VisitFloat64SubPreserveNan(node);
+    case IrOpcode::kFloat64Neg:
+      return MarkAsFloat64(node), VisitFloat64Neg(node);
     case IrOpcode::kFloat64Mul:
       return MarkAsFloat64(node), VisitFloat64Mul(node);
     case IrOpcode::kFloat64Div:
@@ -1104,8 +1134,34 @@
       return MarkAsFloat64(node), VisitFloat64Max(node);
     case IrOpcode::kFloat64Abs:
       return MarkAsFloat64(node), VisitFloat64Abs(node);
+    case IrOpcode::kFloat64Atan:
+      return MarkAsFloat64(node), VisitFloat64Atan(node);
+    case IrOpcode::kFloat64Atan2:
+      return MarkAsFloat64(node), VisitFloat64Atan2(node);
+    case IrOpcode::kFloat64Atanh:
+      return MarkAsFloat64(node), VisitFloat64Atanh(node);
+    case IrOpcode::kFloat64Cbrt:
+      return MarkAsFloat64(node), VisitFloat64Cbrt(node);
+    case IrOpcode::kFloat64Cos:
+      return MarkAsFloat64(node), VisitFloat64Cos(node);
+    case IrOpcode::kFloat64Exp:
+      return MarkAsFloat64(node), VisitFloat64Exp(node);
+    case IrOpcode::kFloat64Expm1:
+      return MarkAsFloat64(node), VisitFloat64Expm1(node);
+    case IrOpcode::kFloat64Log:
+      return MarkAsFloat64(node), VisitFloat64Log(node);
+    case IrOpcode::kFloat64Log1p:
+      return MarkAsFloat64(node), VisitFloat64Log1p(node);
+    case IrOpcode::kFloat64Log10:
+      return MarkAsFloat64(node), VisitFloat64Log10(node);
+    case IrOpcode::kFloat64Log2:
+      return MarkAsFloat64(node), VisitFloat64Log2(node);
+    case IrOpcode::kFloat64Sin:
+      return MarkAsFloat64(node), VisitFloat64Sin(node);
     case IrOpcode::kFloat64Sqrt:
       return MarkAsFloat64(node), VisitFloat64Sqrt(node);
+    case IrOpcode::kFloat64Tan:
+      return MarkAsFloat64(node), VisitFloat64Tan(node);
     case IrOpcode::kFloat64Equal:
       return VisitFloat64Equal(node);
     case IrOpcode::kFloat64LessThan:
@@ -1178,6 +1234,13 @@
       MarkAsWord32(NodeProperties::FindProjection(node, 0));
       MarkAsWord32(NodeProperties::FindProjection(node, 1));
       return VisitWord32PairSar(node);
+    case IrOpcode::kAtomicLoad: {
+      LoadRepresentation type = LoadRepresentationOf(node->op());
+      MarkAsRepresentation(type.representation(), node);
+      return VisitAtomicLoad(node);
+    }
+    case IrOpcode::kAtomicStore:
+      return VisitAtomicStore(node);
     default:
       V8_Fatal(__FILE__, __LINE__, "Unexpected operator #%d:%s @ node #%d",
                node->opcode(), node->op()->mnemonic(), node->id());
@@ -1202,6 +1265,58 @@
   Emit(kArchParentFramePointer, g.DefineAsRegister(node));
 }
 
+void InstructionSelector::VisitFloat64Atan(Node* node) {
+  VisitFloat64Ieee754Unop(node, kIeee754Float64Atan);
+}
+
+void InstructionSelector::VisitFloat64Atan2(Node* node) {
+  VisitFloat64Ieee754Binop(node, kIeee754Float64Atan2);
+}
+
+void InstructionSelector::VisitFloat64Atanh(Node* node) {
+  VisitFloat64Ieee754Unop(node, kIeee754Float64Atanh);
+}
+
+void InstructionSelector::VisitFloat64Cbrt(Node* node) {
+  VisitFloat64Ieee754Unop(node, kIeee754Float64Cbrt);
+}
+
+void InstructionSelector::VisitFloat64Cos(Node* node) {
+  VisitFloat64Ieee754Unop(node, kIeee754Float64Cos);
+}
+
+void InstructionSelector::VisitFloat64Exp(Node* node) {
+  VisitFloat64Ieee754Unop(node, kIeee754Float64Exp);
+}
+
+void InstructionSelector::VisitFloat64Expm1(Node* node) {
+  VisitFloat64Ieee754Unop(node, kIeee754Float64Expm1);
+}
+
+void InstructionSelector::VisitFloat64Log(Node* node) {
+  VisitFloat64Ieee754Unop(node, kIeee754Float64Log);
+}
+
+void InstructionSelector::VisitFloat64Log1p(Node* node) {
+  VisitFloat64Ieee754Unop(node, kIeee754Float64Log1p);
+}
+
+void InstructionSelector::VisitFloat64Log2(Node* node) {
+  VisitFloat64Ieee754Unop(node, kIeee754Float64Log2);
+}
+
+void InstructionSelector::VisitFloat64Log10(Node* node) {
+  VisitFloat64Ieee754Unop(node, kIeee754Float64Log10);
+}
+
+void InstructionSelector::VisitFloat64Sin(Node* node) {
+  VisitFloat64Ieee754Unop(node, kIeee754Float64Sin);
+}
+
+void InstructionSelector::VisitFloat64Tan(Node* node) {
+  VisitFloat64Ieee754Unop(node, kIeee754Float64Tan);
+}
+
 void InstructionSelector::EmitTableSwitch(const SwitchInfo& sw,
                                           InstructionOperand& index_operand) {
   OperandGenerator g(this);
@@ -1246,6 +1361,10 @@
        sequence()->AddImmediate(Constant(slot)), 0, nullptr);
 }
 
+void InstructionSelector::VisitBitcastWordToTagged(Node* node) {
+  EmitIdentity(node);
+}
+
 // 32 bit targets do not implement the following instructions.
 #if V8_TARGET_ARCH_32_BIT
 
@@ -1415,19 +1534,7 @@
 void InstructionSelector::VisitWord32PairSar(Node* node) { UNIMPLEMENTED(); }
 #endif  // V8_TARGET_ARCH_64_BIT
 
-void InstructionSelector::VisitFinishRegion(Node* node) {
-  OperandGenerator g(this);
-  Node* value = node->InputAt(0);
-  Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
-}
-
-
-void InstructionSelector::VisitGuard(Node* node) {
-  OperandGenerator g(this);
-  Node* value = node->InputAt(0);
-  Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
-}
-
+void InstructionSelector::VisitFinishRegion(Node* node) { EmitIdentity(node); }
 
 void InstructionSelector::VisitParameter(Node* node) {
   OperandGenerator g(this);
@@ -1449,7 +1556,7 @@
   OperandGenerator g(this);
   Node* call = node->InputAt(1);
   DCHECK_EQ(IrOpcode::kCall, call->opcode());
-  const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(call);
+  const CallDescriptor* descriptor = CallDescriptorOf(call->op());
   Emit(kArchNop,
        g.DefineAsLocation(node, descriptor->GetReturnLocation(0),
                           descriptor->GetReturnType(0).representation()));
@@ -1521,7 +1628,7 @@
 
 void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
   OperandGenerator g(this);
-  const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
+  const CallDescriptor* descriptor = CallDescriptorOf(node->op());
 
   FrameStateDescriptor* frame_state_descriptor = nullptr;
   if (descriptor->NeedsFrameState()) {
@@ -1589,10 +1696,8 @@
 
 void InstructionSelector::VisitTailCall(Node* node) {
   OperandGenerator g(this);
-  CallDescriptor const* descriptor = OpParameter<CallDescriptor const*>(node);
+  CallDescriptor const* descriptor = CallDescriptorOf(node->op());
   DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls);
-  DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite);
-  DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall);
 
   // TODO(turbofan): Relax restriction for stack parameters.
 
@@ -1635,6 +1740,9 @@
         case CallDescriptor::kCallJSFunction:
           opcode = kArchTailCallJSFunction;
           break;
+        case CallDescriptor::kCallAddress:
+          opcode = kArchTailCallAddress;
+          break;
         default:
           UNREACHABLE();
           return;
@@ -1752,6 +1860,12 @@
               nullptr);
 }
 
+void InstructionSelector::EmitIdentity(Node* node) {
+  OperandGenerator g(this);
+  Node* value = node->InputAt(0);
+  Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
+}
+
 void InstructionSelector::VisitDeoptimize(DeoptimizeKind kind, Node* value) {
   InstructionCode opcode = kArchDeoptimize;
   switch (kind) {
@@ -1771,6 +1885,26 @@
   Emit(kArchThrowTerminator, g.NoOutput());
 }
 
+void InstructionSelector::VisitDebugBreak(Node* node) {
+  OperandGenerator g(this);
+  Emit(kArchDebugBreak, g.NoOutput());
+}
+
+void InstructionSelector::VisitComment(Node* node) {
+  OperandGenerator g(this);
+  InstructionOperand operand(g.UseImmediate(node));
+  Emit(kArchComment, 0, nullptr, 1, &operand);
+}
+
+bool InstructionSelector::CanProduceSignalingNaN(Node* node) {
+  // TODO(jarin) Improve the heuristic here.
+  if (node->opcode() == IrOpcode::kFloat64Add ||
+      node->opcode() == IrOpcode::kFloat64Sub ||
+      node->opcode() == IrOpcode::kFloat64Mul) {
+    return false;
+  }
+  return true;
+}
 
 FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor(
     Node* state) {
diff --git a/src/compiler/instruction-selector.h b/src/compiler/instruction-selector.h
index 9c1cd4c..8ac8e7b 100644
--- a/src/compiler/instruction-selector.h
+++ b/src/compiler/instruction-selector.h
@@ -139,6 +139,8 @@
   // TODO(sigurds) This should take a CpuFeatures argument.
   static MachineOperatorBuilder::Flags SupportedMachineOperatorFlags();
 
+  static MachineOperatorBuilder::AlignmentRequirements AlignmentRequirements();
+
   // ===========================================================================
   // ============ Architecture-independent graph covering methods. =============
   // ===========================================================================
@@ -242,12 +244,15 @@
   // Visit the node and generate code, if any.
   void VisitNode(Node* node);
 
+  // Visit the node and generate code for IEEE 754 functions.
+  void VisitFloat64Ieee754Binop(Node*, InstructionCode code);
+  void VisitFloat64Ieee754Unop(Node*, InstructionCode code);
+
 #define DECLARE_GENERATOR(x) void Visit##x(Node* node);
   MACHINE_OP_LIST(DECLARE_GENERATOR)
 #undef DECLARE_GENERATOR
 
   void VisitFinishRegion(Node* node);
-  void VisitGuard(Node* node);
   void VisitParameter(Node* node);
   void VisitIfException(Node* node);
   void VisitOsrValue(Node* node);
@@ -268,6 +273,9 @@
   void EmitPrepareArguments(ZoneVector<compiler::PushParameter>* arguments,
                             const CallDescriptor* descriptor, Node* node);
 
+  void EmitIdentity(Node* node);
+  bool CanProduceSignalingNaN(Node* node);
+
   // ===========================================================================
 
   Schedule* schedule() const { return schedule_; }
diff --git a/src/compiler/instruction.cc b/src/compiler/instruction.cc
index c757557..1ef42d6 100644
--- a/src/compiler/instruction.cc
+++ b/src/compiler/instruction.cc
@@ -12,6 +12,7 @@
 namespace internal {
 namespace compiler {
 
+const auto GetRegConfig = RegisterConfiguration::Turbofan;
 
 FlagsCondition CommuteFlagsCondition(FlagsCondition condition) {
   switch (condition) {
@@ -59,6 +60,16 @@
   return condition;
 }
 
+bool InstructionOperand::InterferesWith(const InstructionOperand& that) const {
+  if (!IsFPRegister() || !that.IsFPRegister() || kSimpleFPAliasing)
+    return EqualsCanonicalized(that);
+  // Both operands are fp registers and aliasing is non-simple.
+  const LocationOperand& loc1 = *LocationOperand::cast(this);
+  const LocationOperand& loc2 = LocationOperand::cast(that);
+  return GetRegConfig()->AreAliases(loc1.representation(), loc1.register_code(),
+                                    loc2.representation(),
+                                    loc2.register_code());
+}
 
 void InstructionOperand::Print(const RegisterConfiguration* config) const {
   OFStream os(stdout);
@@ -68,13 +79,7 @@
   os << wrapper << std::endl;
 }
 
-
-void InstructionOperand::Print() const {
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
-  Print(config);
-}
-
+void InstructionOperand::Print() const { Print(GetRegConfig()); }
 
 std::ostream& operator<<(std::ostream& os,
                          const PrintableInstructionOperand& printable) {
@@ -95,7 +100,7 @@
                     << conf->GetGeneralRegisterName(
                            unalloc->fixed_register_index())
                     << ")";
-        case UnallocatedOperand::FIXED_DOUBLE_REGISTER:
+        case UnallocatedOperand::FIXED_FP_REGISTER:
           return os << "(="
                     << conf->GetDoubleRegisterName(
                            unalloc->fixed_register_index())
@@ -126,14 +131,21 @@
     case InstructionOperand::ALLOCATED: {
       LocationOperand allocated = LocationOperand::cast(op);
       if (op.IsStackSlot()) {
-        os << "[stack:" << LocationOperand::cast(op).index();
-      } else if (op.IsDoubleStackSlot()) {
-        os << "[double_stack:" << LocationOperand::cast(op).index();
+        os << "[stack:" << allocated.index();
+      } else if (op.IsFPStackSlot()) {
+        os << "[fp_stack:" << allocated.index();
       } else if (op.IsRegister()) {
-        os << "[" << LocationOperand::cast(op).GetRegister().ToString() << "|R";
+        os << "["
+           << GetRegConfig()->GetGeneralRegisterName(allocated.register_code())
+           << "|R";
+      } else if (op.IsDoubleRegister()) {
+        os << "["
+           << GetRegConfig()->GetDoubleRegisterName(allocated.register_code())
+           << "|R";
       } else {
-        DCHECK(op.IsDoubleRegister());
-        os << "[" << LocationOperand::cast(op).GetDoubleRegister().ToString()
+        DCHECK(op.IsFloatRegister());
+        os << "["
+           << GetRegConfig()->GetFloatRegisterName(allocated.register_code())
            << "|R";
       }
       if (allocated.IsExplicit()) {
@@ -180,7 +192,6 @@
   return os;
 }
 
-
 void MoveOperands::Print(const RegisterConfiguration* config) const {
   OFStream os(stdout);
   PrintableInstructionOperand wrapper;
@@ -191,13 +202,7 @@
   os << wrapper << std::endl;
 }
 
-
-void MoveOperands::Print() const {
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
-  Print(config);
-}
-
+void MoveOperands::Print() const { Print(GetRegConfig()); }
 
 std::ostream& operator<<(std::ostream& os,
                          const PrintableMoveOperands& printable) {
@@ -246,22 +251,23 @@
                                  int index)
     : LocationOperand(EXPLICIT, kind, rep, index) {
   DCHECK_IMPLIES(kind == REGISTER && !IsFloatingPoint(rep),
-                 Register::from_code(index).IsAllocatable());
-  DCHECK_IMPLIES(kind == REGISTER && IsFloatingPoint(rep),
-                 DoubleRegister::from_code(index).IsAllocatable());
+                 GetRegConfig()->IsAllocatableGeneralCode(index));
+  DCHECK_IMPLIES(kind == REGISTER && rep == MachineRepresentation::kFloat32,
+                 GetRegConfig()->IsAllocatableFloatCode(index));
+  DCHECK_IMPLIES(kind == REGISTER && (rep == MachineRepresentation::kFloat64),
+                 GetRegConfig()->IsAllocatableDoubleCode(index));
 }
 
-
 Instruction::Instruction(InstructionCode opcode)
     : opcode_(opcode),
       bit_field_(OutputCountField::encode(0) | InputCountField::encode(0) |
                  TempCountField::encode(0) | IsCallField::encode(false)),
-      reference_map_(nullptr) {
+      reference_map_(nullptr),
+      block_(nullptr) {
   parallel_moves_[0] = nullptr;
   parallel_moves_[1] = nullptr;
 }
 
-
 Instruction::Instruction(InstructionCode opcode, size_t output_count,
                          InstructionOperand* outputs, size_t input_count,
                          InstructionOperand* inputs, size_t temp_count,
@@ -271,7 +277,8 @@
                  InputCountField::encode(input_count) |
                  TempCountField::encode(temp_count) |
                  IsCallField::encode(false)),
-      reference_map_(nullptr) {
+      reference_map_(nullptr),
+      block_(nullptr) {
   parallel_moves_[0] = nullptr;
   parallel_moves_[1] = nullptr;
   size_t offset = 0;
@@ -309,13 +316,7 @@
   os << wrapper << std::endl;
 }
 
-
-void Instruction::Print() const {
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
-  Print(config);
-}
-
+void Instruction::Print() const { Print(GetRegConfig()); }
 
 std::ostream& operator<<(std::ostream& os,
                          const PrintableParallelMove& printable) {
@@ -335,7 +336,7 @@
 void ReferenceMap::RecordReference(const AllocatedOperand& op) {
   // Do not record arguments as pointers.
   if (op.IsStackSlot() && LocationOperand::cast(op).index() < 0) return;
-  DCHECK(!op.IsDoubleRegister() && !op.IsDoubleStackSlot());
+  DCHECK(!op.IsFPRegister() && !op.IsFPStackSlot());
   reference_operands_.push_back(op);
 }
 
@@ -343,9 +344,7 @@
 std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm) {
   os << "{";
   bool first = true;
-  PrintableInstructionOperand poi = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN),
-      InstructionOperand()};
+  PrintableInstructionOperand poi = {GetRegConfig(), InstructionOperand()};
   for (const InstructionOperand& op : pm.reference_operands_) {
     if (!first) {
       os << ";";
@@ -504,6 +503,27 @@
 
 Constant::Constant(int32_t v) : type_(kInt32), value_(v) {}
 
+Constant::Constant(RelocatablePtrConstantInfo info) {
+  if (info.type() == RelocatablePtrConstantInfo::kInt32) {
+    type_ = kInt32;
+  } else if (info.type() == RelocatablePtrConstantInfo::kInt64) {
+    type_ = kInt64;
+  } else {
+    UNREACHABLE();
+  }
+  value_ = info.value();
+  rmode_ = info.rmode();
+}
+
+Handle<HeapObject> Constant::ToHeapObject() const {
+  DCHECK_EQ(kHeapObject, type());
+  Handle<HeapObject> value(
+      bit_cast<HeapObject**>(static_cast<intptr_t>(value_)));
+  if (value->IsConsString()) {
+    value = String::Flatten(Handle<String>::cast(value), TENURED);
+  }
+  return value;
+}
 
 std::ostream& operator<<(std::ostream& os, const Constant& constant) {
   switch (constant.type()) {
@@ -603,7 +623,6 @@
   return instr_block;
 }
 
-
 InstructionBlocks* InstructionSequence::InstructionBlocksFor(
     Zone* zone, const Schedule* schedule) {
   InstructionBlocks* blocks = zone->NewArray<InstructionBlocks>(1);
@@ -620,7 +639,7 @@
   return blocks;
 }
 
-void InstructionSequence::ValidateEdgeSplitForm() {
+void InstructionSequence::ValidateEdgeSplitForm() const {
   // Validate blocks are in edge-split form: no block with multiple successors
   // has an edge to a block (== a successor) with more than one predecessors.
   for (const InstructionBlock* block : instruction_blocks()) {
@@ -635,7 +654,7 @@
   }
 }
 
-void InstructionSequence::ValidateDeferredBlockExitPaths() {
+void InstructionSequence::ValidateDeferredBlockExitPaths() const {
   // A deferred block with more than one successor must have all its successors
   // deferred.
   for (const InstructionBlock* block : instruction_blocks()) {
@@ -646,7 +665,21 @@
   }
 }
 
-void InstructionSequence::ValidateSSA() {
+void InstructionSequence::ValidateDeferredBlockEntryPaths() const {
+  // If a deferred block has multiple predecessors, they have to
+  // all be deferred. Otherwise, we can run into a situation where a range
+  // that spills only in deferred blocks inserts its spill in the block, but
+  // other ranges need moves inserted by ResolveControlFlow in the predecessors,
+  // which may clobber the register of this range.
+  for (const InstructionBlock* block : instruction_blocks()) {
+    if (!block->IsDeferred() || block->PredecessorCount() <= 1) continue;
+    for (RpoNumber predecessor_id : block->predecessors()) {
+      CHECK(InstructionBlockAt(predecessor_id)->IsDeferred());
+    }
+  }
+}
+
+void InstructionSequence::ValidateSSA() const {
   // TODO(mtrofin): We could use a local zone here instead.
   BitVector definitions(VirtualRegisterCount(), zone());
   for (const Instruction* instruction : *this) {
@@ -675,7 +708,6 @@
   }
 }
 
-
 InstructionSequence::InstructionSequence(Isolate* isolate,
                                          Zone* instruction_zone,
                                          InstructionBlocks* instruction_blocks)
@@ -683,7 +715,6 @@
       zone_(instruction_zone),
       instruction_blocks_(instruction_blocks),
       source_positions_(zone()),
-      block_starts_(zone()),
       constants_(ConstantMap::key_compare(),
                  ConstantMap::allocator_type(zone())),
       immediates_(zone()),
@@ -691,10 +722,8 @@
       next_virtual_register_(0),
       reference_maps_(zone()),
       representations_(zone()),
-      deoptimization_entries_(zone()) {
-  block_starts_.reserve(instruction_blocks_->size());
-}
-
+      deoptimization_entries_(zone()),
+      current_block_(nullptr) {}
 
 int InstructionSequence::NextVirtualRegister() {
   int virtual_register = next_virtual_register_++;
@@ -710,28 +739,31 @@
 
 
 void InstructionSequence::StartBlock(RpoNumber rpo) {
-  DCHECK(block_starts_.size() == rpo.ToSize());
-  InstructionBlock* block = InstructionBlockAt(rpo);
+  DCHECK_NULL(current_block_);
+  current_block_ = InstructionBlockAt(rpo);
   int code_start = static_cast<int>(instructions_.size());
-  block->set_code_start(code_start);
-  block_starts_.push_back(code_start);
+  current_block_->set_code_start(code_start);
 }
 
 
 void InstructionSequence::EndBlock(RpoNumber rpo) {
   int end = static_cast<int>(instructions_.size());
-  InstructionBlock* block = InstructionBlockAt(rpo);
-  if (block->code_start() == end) {  // Empty block.  Insert a nop.
+  DCHECK_EQ(current_block_->rpo_number(), rpo);
+  if (current_block_->code_start() == end) {  // Empty block.  Insert a nop.
     AddInstruction(Instruction::New(zone(), kArchNop));
     end = static_cast<int>(instructions_.size());
   }
-  DCHECK(block->code_start() >= 0 && block->code_start() < end);
-  block->set_code_end(end);
+  DCHECK(current_block_->code_start() >= 0 &&
+         current_block_->code_start() < end);
+  current_block_->set_code_end(end);
+  current_block_ = nullptr;
 }
 
 
 int InstructionSequence::AddInstruction(Instruction* instr) {
+  DCHECK_NOT_NULL(current_block_);
   int index = static_cast<int>(instructions_.size());
+  instr->set_block(current_block_);
   instructions_.push_back(instr);
   if (instr->NeedsReferenceMap()) {
     DCHECK(instr->reference_map() == nullptr);
@@ -746,18 +778,7 @@
 
 InstructionBlock* InstructionSequence::GetInstructionBlock(
     int instruction_index) const {
-  DCHECK(instruction_blocks_->size() == block_starts_.size());
-  auto begin = block_starts_.begin();
-  auto end = std::lower_bound(begin, block_starts_.end(), instruction_index);
-  // Post condition of std::lower_bound:
-  DCHECK(end == block_starts_.end() || *end >= instruction_index);
-  if (end == block_starts_.end() || *end > instruction_index) --end;
-  DCHECK(*end <= instruction_index);
-  size_t index = std::distance(begin, end);
-  InstructionBlock* block = instruction_blocks_->at(index);
-  DCHECK(block->code_start() <= instruction_index &&
-         instruction_index < block->code_end());
-  return block;
+  return instructions()[instruction_index]->block();
 }
 
 
@@ -858,12 +879,7 @@
   os << wrapper << std::endl;
 }
 
-
-void InstructionSequence::Print() const {
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
-  Print(config);
-}
+void InstructionSequence::Print() const { Print(GetRegConfig()); }
 
 void InstructionSequence::PrintBlock(const RegisterConfiguration* config,
                                      int block_id) const {
@@ -917,9 +933,7 @@
 }
 
 void InstructionSequence::PrintBlock(int block_id) const {
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
-  PrintBlock(config, block_id);
+  PrintBlock(GetRegConfig(), block_id);
 }
 
 FrameStateDescriptor::FrameStateDescriptor(
diff --git a/src/compiler/instruction.h b/src/compiler/instruction.h
index a1fe494..7130c3d 100644
--- a/src/compiler/instruction.h
+++ b/src/compiler/instruction.h
@@ -66,9 +66,13 @@
 
   inline bool IsAnyRegister() const;
   inline bool IsRegister() const;
+  inline bool IsFPRegister() const;
+  inline bool IsFloatRegister() const;
   inline bool IsDoubleRegister() const;
   inline bool IsSimd128Register() const;
   inline bool IsStackSlot() const;
+  inline bool IsFPStackSlot() const;
+  inline bool IsFloatStackSlot() const;
   inline bool IsDoubleStackSlot() const;
   inline bool IsSimd128StackSlot() const;
 
@@ -99,6 +103,8 @@
     return this->GetCanonicalizedValue() < that.GetCanonicalizedValue();
   }
 
+  bool InterferesWith(const InstructionOperand& that) const;
+
   void Print(const RegisterConfiguration* config) const;
   void Print() const;
 
@@ -151,7 +157,7 @@
     NONE,
     ANY,
     FIXED_REGISTER,
-    FIXED_DOUBLE_REGISTER,
+    FIXED_FP_REGISTER,
     MUST_HAVE_REGISTER,
     MUST_HAVE_SLOT,
     SAME_AS_FIRST_INPUT
@@ -188,7 +194,7 @@
 
   UnallocatedOperand(ExtendedPolicy policy, int index, int virtual_register)
       : UnallocatedOperand(virtual_register) {
-    DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER);
+    DCHECK(policy == FIXED_REGISTER || policy == FIXED_FP_REGISTER);
     value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
     value_ |= ExtendedPolicyField::encode(policy);
     value_ |= LifetimeField::encode(USED_AT_END);
@@ -216,7 +222,7 @@
   bool HasFixedPolicy() const {
     return basic_policy() == FIXED_SLOT ||
            extended_policy() == FIXED_REGISTER ||
-           extended_policy() == FIXED_DOUBLE_REGISTER;
+           extended_policy() == FIXED_FP_REGISTER;
   }
   bool HasRegisterPolicy() const {
     return basic_policy() == EXTENDED_POLICY &&
@@ -235,9 +241,9 @@
     return basic_policy() == EXTENDED_POLICY &&
            extended_policy() == FIXED_REGISTER;
   }
-  bool HasFixedDoubleRegisterPolicy() const {
+  bool HasFixedFPRegisterPolicy() const {
     return basic_policy() == EXTENDED_POLICY &&
-           extended_policy() == FIXED_DOUBLE_REGISTER;
+           extended_policy() == FIXED_FP_REGISTER;
   }
   bool HasSecondaryStorage() const {
     return basic_policy() == EXTENDED_POLICY &&
@@ -268,9 +274,9 @@
                             FixedSlotIndexField::kShift);
   }
 
-  // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER.
+  // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_FP_REGISTER.
   int fixed_register_index() const {
-    DCHECK(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy());
+    DCHECK(HasFixedRegisterPolicy() || HasFixedFPRegisterPolicy());
     return FixedRegisterField::decode(value_);
   }
 
@@ -413,26 +419,36 @@
   }
 
   int index() const {
-    DCHECK(IsStackSlot() || IsDoubleStackSlot() || IsSimd128StackSlot());
+    DCHECK(IsStackSlot() || IsFPStackSlot());
+    return static_cast<int64_t>(value_) >> IndexField::kShift;
+  }
+
+  int register_code() const {
+    DCHECK(IsRegister() || IsFPRegister());
     return static_cast<int64_t>(value_) >> IndexField::kShift;
   }
 
   Register GetRegister() const {
     DCHECK(IsRegister());
-    return Register::from_code(static_cast<int64_t>(value_) >>
-                               IndexField::kShift);
+    return Register::from_code(register_code());
+  }
+
+  FloatRegister GetFloatRegister() const {
+    DCHECK(IsFloatRegister());
+    return FloatRegister::from_code(register_code());
   }
 
   DoubleRegister GetDoubleRegister() const {
-    DCHECK(IsDoubleRegister());
-    return DoubleRegister::from_code(static_cast<int64_t>(value_) >>
-                                     IndexField::kShift);
+    // On platforms where FloatRegister, DoubleRegister, and Simd128Register
+    // are all the same type, it's convenient to treat everything as a
+    // DoubleRegister, so be lax about type checking here.
+    DCHECK(IsFPRegister());
+    return DoubleRegister::from_code(register_code());
   }
 
   Simd128Register GetSimd128Register() const {
     DCHECK(IsSimd128Register());
-    return Simd128Register::from_code(static_cast<int64_t>(value_) >>
-                                      IndexField::kShift);
+    return Simd128Register::from_code(register_code());
   }
 
   LocationKind location_kind() const {
@@ -526,11 +542,23 @@
          !IsFloatingPoint(LocationOperand::cast(this)->representation());
 }
 
-bool InstructionOperand::IsDoubleRegister() const {
+bool InstructionOperand::IsFPRegister() const {
   return IsAnyRegister() &&
          IsFloatingPoint(LocationOperand::cast(this)->representation());
 }
 
+bool InstructionOperand::IsFloatRegister() const {
+  return IsAnyRegister() &&
+         LocationOperand::cast(this)->representation() ==
+             MachineRepresentation::kFloat32;
+}
+
+bool InstructionOperand::IsDoubleRegister() const {
+  return IsAnyRegister() &&
+         LocationOperand::cast(this)->representation() ==
+             MachineRepresentation::kFloat64;
+}
+
 bool InstructionOperand::IsSimd128Register() const {
   return IsAnyRegister() &&
          LocationOperand::cast(this)->representation() ==
@@ -544,13 +572,29 @@
          !IsFloatingPoint(LocationOperand::cast(this)->representation());
 }
 
-bool InstructionOperand::IsDoubleStackSlot() const {
+bool InstructionOperand::IsFPStackSlot() const {
   return (IsAllocated() || IsExplicit()) &&
          LocationOperand::cast(this)->location_kind() ==
              LocationOperand::STACK_SLOT &&
          IsFloatingPoint(LocationOperand::cast(this)->representation());
 }
 
+bool InstructionOperand::IsFloatStackSlot() const {
+  return (IsAllocated() || IsExplicit()) &&
+         LocationOperand::cast(this)->location_kind() ==
+             LocationOperand::STACK_SLOT &&
+         LocationOperand::cast(this)->representation() ==
+             MachineRepresentation::kFloat32;
+}
+
+bool InstructionOperand::IsDoubleStackSlot() const {
+  return (IsAllocated() || IsExplicit()) &&
+         LocationOperand::cast(this)->location_kind() ==
+             LocationOperand::STACK_SLOT &&
+         LocationOperand::cast(this)->representation() ==
+             MachineRepresentation::kFloat64;
+}
+
 bool InstructionOperand::IsSimd128StackSlot() const {
   return (IsAllocated() || IsExplicit()) &&
          LocationOperand::cast(this)->location_kind() ==
@@ -561,20 +605,25 @@
 
 uint64_t InstructionOperand::GetCanonicalizedValue() const {
   if (IsAllocated() || IsExplicit()) {
-    // TODO(dcarney): put machine type last and mask.
-    MachineRepresentation canonicalized_representation =
-        IsFloatingPoint(LocationOperand::cast(this)->representation())
-            ? MachineRepresentation::kFloat64
-            : MachineRepresentation::kNone;
+    MachineRepresentation rep = LocationOperand::cast(this)->representation();
+    MachineRepresentation canonical = MachineRepresentation::kNone;
+    if (IsFloatingPoint(rep)) {
+      if (kSimpleFPAliasing) {
+        // Archs with simple aliasing can treat all FP operands the same.
+        canonical = MachineRepresentation::kFloat64;
+      } else {
+        // We need to distinguish FP operands of different reps when FP
+        // aliasing is not simple (e.g. ARM).
+        canonical = rep;
+      }
+    }
     return InstructionOperand::KindField::update(
-        LocationOperand::RepresentationField::update(
-            this->value_, canonicalized_representation),
+        LocationOperand::RepresentationField::update(this->value_, canonical),
         LocationOperand::EXPLICIT);
   }
   return this->value_;
 }
 
-
 // Required for maps that don't care about machine type.
 struct CompareOperandModuloType {
   bool operator()(const InstructionOperand& a,
@@ -609,9 +658,9 @@
   }
   void SetPending() { destination_ = InstructionOperand(); }
 
-  // True if this move a move into the given destination operand.
-  bool Blocks(const InstructionOperand& operand) const {
-    return !IsEliminated() && source().EqualsCanonicalized(operand);
+  // True if this move is a move into the given destination operand.
+  bool Blocks(const InstructionOperand& destination) const {
+    return !IsEliminated() && source().InterferesWith(destination);
   }
 
   // A move is redundant if it's been eliminated or if its source and
@@ -715,6 +764,8 @@
 
 std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm);
 
+class InstructionBlock;
+
 class Instruction final {
  public:
   size_t OutputCount() const { return OutputCountField::decode(bit_field_); }
@@ -826,7 +877,8 @@
     return arch_opcode() == ArchOpcode::kArchTailCallCodeObject ||
            arch_opcode() == ArchOpcode::kArchTailCallCodeObjectFromJSFunction ||
            arch_opcode() == ArchOpcode::kArchTailCallJSFunction ||
-           arch_opcode() == ArchOpcode::kArchTailCallJSFunctionFromJSFunction;
+           arch_opcode() == ArchOpcode::kArchTailCallJSFunctionFromJSFunction ||
+           arch_opcode() == ArchOpcode::kArchTailCallAddress;
   }
   bool IsThrow() const {
     return arch_opcode() == ArchOpcode::kArchThrowTerminator;
@@ -859,6 +911,15 @@
   ParallelMove* const* parallel_moves() const { return &parallel_moves_[0]; }
   ParallelMove** parallel_moves() { return &parallel_moves_[0]; }
 
+  // The block_id may be invalidated in JumpThreading. It is only important for
+  // register allocation, to avoid searching for blocks from instruction
+  // indexes.
+  InstructionBlock* block() const { return block_; }
+  void set_block(InstructionBlock* block) {
+    DCHECK_NOT_NULL(block);
+    block_ = block;
+  }
+
   void Print(const RegisterConfiguration* config) const;
   void Print() const;
 
@@ -879,6 +940,7 @@
   uint32_t bit_field_;
   ParallelMove* parallel_moves_[2];
   ReferenceMap* reference_map_;
+  InstructionBlock* block_;
   InstructionOperand operands_[1];
 
   DISALLOW_COPY_AND_ASSIGN(Instruction);
@@ -950,9 +1012,12 @@
   explicit Constant(Handle<HeapObject> obj)
       : type_(kHeapObject), value_(bit_cast<intptr_t>(obj)) {}
   explicit Constant(RpoNumber rpo) : type_(kRpoNumber), value_(rpo.ToInt()) {}
+  explicit Constant(RelocatablePtrConstantInfo info);
 
   Type type() const { return type_; }
 
+  RelocInfo::Mode rmode() const { return rmode_; }
+
   int32_t ToInt32() const {
     DCHECK(type() == kInt32 || type() == kInt64);
     const int32_t value = static_cast<int32_t>(value_);
@@ -987,14 +1052,16 @@
     return RpoNumber::FromInt(static_cast<int>(value_));
   }
 
-  Handle<HeapObject> ToHeapObject() const {
-    DCHECK_EQ(kHeapObject, type());
-    return bit_cast<Handle<HeapObject> >(static_cast<intptr_t>(value_));
-  }
+  Handle<HeapObject> ToHeapObject() const;
 
  private:
   Type type_;
   int64_t value_;
+#if V8_TARGET_ARCH_32_BIT
+  RelocInfo::Mode rmode_ = RelocInfo::NONE32;
+#else
+  RelocInfo::Mode rmode_ = RelocInfo::NONE64;
+#endif
 };
 
 
@@ -1268,9 +1335,17 @@
     return GetRepresentation(virtual_register) ==
            MachineRepresentation::kTagged;
   }
-  bool IsFloat(int virtual_register) const {
+  bool IsFP(int virtual_register) const {
     return IsFloatingPoint(GetRepresentation(virtual_register));
   }
+  bool IsFloat(int virtual_register) const {
+    return GetRepresentation(virtual_register) ==
+           MachineRepresentation::kFloat32;
+  }
+  bool IsDouble(int virtual_register) const {
+    return GetRepresentation(virtual_register) ==
+           MachineRepresentation::kFloat64;
+  }
 
   Instruction* GetBlockStart(RpoNumber rpo) const;
 
@@ -1316,7 +1391,8 @@
   Immediates& immediates() { return immediates_; }
 
   ImmediateOperand AddImmediate(const Constant& constant) {
-    if (constant.type() == Constant::kInt32) {
+    if (constant.type() == Constant::kInt32 &&
+        RelocInfo::IsNone(constant.rmode())) {
       return ImmediateOperand(ImmediateOperand::INLINE, constant.ToInt32());
     }
     int index = static_cast<int>(immediates_.size());
@@ -1374,9 +1450,10 @@
   void PrintBlock(const RegisterConfiguration* config, int block_id) const;
   void PrintBlock(int block_id) const;
 
-  void ValidateEdgeSplitForm();
-  void ValidateDeferredBlockExitPaths();
-  void ValidateSSA();
+  void ValidateEdgeSplitForm() const;
+  void ValidateDeferredBlockExitPaths() const;
+  void ValidateDeferredBlockEntryPaths() const;
+  void ValidateSSA() const;
 
  private:
   friend std::ostream& operator<<(std::ostream& os,
@@ -1388,7 +1465,6 @@
   Zone* const zone_;
   InstructionBlocks* const instruction_blocks_;
   SourcePositionMap source_positions_;
-  IntVector block_starts_;
   ConstantMap constants_;
   Immediates immediates_;
   InstructionDeque instructions_;
@@ -1397,6 +1473,9 @@
   ZoneVector<MachineRepresentation> representations_;
   DeoptimizationVector deoptimization_entries_;
 
+  // Used at construction time
+  InstructionBlock* current_block_;
+
   DISALLOW_COPY_AND_ASSIGN(InstructionSequence);
 };
 
diff --git a/src/compiler/int64-lowering.cc b/src/compiler/int64-lowering.cc
index 8824a03..68d3772 100644
--- a/src/compiler/int64-lowering.cc
+++ b/src/compiler/int64-lowering.cc
@@ -32,6 +32,8 @@
       signature_(signature),
       placeholder_(graph->NewNode(common->Parameter(-2, "placeholder"),
                                   graph->start())) {
+  DCHECK_NOT_NULL(graph);
+  DCHECK_NOT_NULL(graph->end());
   replacements_ = zone->NewArray<Replacement>(graph->NodeCount());
   memset(replacements_, 0, sizeof(Replacement) * graph->NodeCount());
 }
@@ -79,8 +81,10 @@
   return result;
 }
 
-static int GetParameterCountAfterLowering(
+int Int64Lowering::GetParameterCountAfterLowering(
     Signature<MachineRepresentation>* signature) {
+  // GetParameterIndexAfterLowering(parameter_count) returns the parameter count
+  // after lowering.
   return GetParameterIndexAfterLowering(
       signature, static_cast<int>(signature->parameter_count()));
 }
@@ -96,6 +100,27 @@
   return result;
 }
 
+void Int64Lowering::GetIndexNodes(Node* index, Node*& index_low,
+                                  Node*& index_high) {
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+  index_low = index;
+  index_high = graph()->NewNode(machine()->Int32Add(), index,
+                                graph()->NewNode(common()->Int32Constant(4)));
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  index_low = graph()->NewNode(machine()->Int32Add(), index,
+                               graph()->NewNode(common()->Int32Constant(4)));
+  index_high = index;
+#endif
+}
+
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+const int Int64Lowering::kLowerWordOffset = 0;
+const int Int64Lowering::kHigherWordOffset = 4;
+#elif defined(V8_TARGET_BIG_ENDIAN)
+const int Int64Lowering::kLowerWordOffset = 4;
+const int Int64Lowering::kHigherWordOffset = 0;
+#endif
+
 void Int64Lowering::LowerNode(Node* node) {
   switch (node->opcode()) {
     case IrOpcode::kInt64Constant: {
@@ -113,10 +138,9 @@
       if (load_rep.representation() == MachineRepresentation::kWord64) {
         Node* base = node->InputAt(0);
         Node* index = node->InputAt(1);
-        Node* index_high =
-            graph()->NewNode(machine()->Int32Add(), index,
-                             graph()->NewNode(common()->Int32Constant(4)));
-
+        Node* index_low;
+        Node* index_high;
+        GetIndexNodes(index, index_low, index_high);
         const Operator* load_op = machine()->Load(MachineType::Int32());
         Node* high_node;
         if (node->InputCount() > 2) {
@@ -130,6 +154,7 @@
         } else {
           high_node = graph()->NewNode(load_op, base, index_high);
         }
+        node->ReplaceInput(1, index_low);
         NodeProperties::ChangeOp(node, load_op);
         ReplaceNode(node, node, high_node);
       } else {
@@ -148,10 +173,9 @@
 
         Node* base = node->InputAt(0);
         Node* index = node->InputAt(1);
-        Node* index_high =
-            graph()->NewNode(machine()->Int32Add(), index,
-                             graph()->NewNode(common()->Int32Constant(4)));
-
+        Node* index_low;
+        Node* index_high;
+        GetIndexNodes(index, index_low, index_high);
         Node* value = node->InputAt(2);
         DCHECK(HasReplacementLow(value));
         DCHECK(HasReplacementHigh(value));
@@ -173,11 +197,14 @@
                                        GetReplacementHigh(value));
         }
 
+        node->ReplaceInput(1, index_low);
         node->ReplaceInput(2, GetReplacementLow(value));
         NodeProperties::ChangeOp(node, store_op);
         ReplaceNode(node, node, high_node);
       } else {
-        DefaultLowering(node);
+        if (HasReplacementLow(node->InputAt(2))) {
+          node->ReplaceInput(2, GetReplacementLow(node->InputAt(2)));
+        }
       }
       break;
     }
@@ -223,7 +250,9 @@
       break;
     }
     case IrOpcode::kCall: {
-      CallDescriptor* descriptor = OpParameter<CallDescriptor*>(node);
+      // TODO(turbofan): Make WASM code const-correct wrt. CallDescriptor.
+      CallDescriptor* descriptor =
+          const_cast<CallDescriptor*>(CallDescriptorOf(node->op()));
       if (DefaultLowering(node) ||
           (descriptor->ReturnCount() == 1 &&
            descriptor->GetReturnType(0) == MachineType::Int64())) {
@@ -235,8 +264,10 @@
       if (descriptor->ReturnCount() == 1 &&
           descriptor->GetReturnType(0) == MachineType::Int64()) {
         // We access the additional return values through projections.
-        Node* low_node = graph()->NewNode(common()->Projection(0), node);
-        Node* high_node = graph()->NewNode(common()->Projection(1), node);
+        Node* low_node =
+            graph()->NewNode(common()->Projection(0), node, graph()->start());
+        Node* high_node =
+            graph()->NewNode(common()->Projection(1), node, graph()->start());
         ReplaceNode(node, low_node, high_node);
       }
       break;
@@ -262,9 +293,6 @@
       node->NullAllInputs();
       break;
     }
-    // todo(ahaas): I added a list of missing instructions here to make merging
-    // easier when I do them one by one.
-    // kExprI64Add:
     case IrOpcode::kInt64Add: {
       DCHECK(node->InputCount() == 2);
 
@@ -278,13 +306,13 @@
 
       NodeProperties::ChangeOp(node, machine()->Int32PairAdd());
       // We access the additional return values through projections.
-      Node* low_node = graph()->NewNode(common()->Projection(0), node);
-      Node* high_node = graph()->NewNode(common()->Projection(1), node);
+      Node* low_node =
+          graph()->NewNode(common()->Projection(0), node, graph()->start());
+      Node* high_node =
+          graph()->NewNode(common()->Projection(1), node, graph()->start());
       ReplaceNode(node, low_node, high_node);
       break;
     }
-
-    // kExprI64Sub:
     case IrOpcode::kInt64Sub: {
       DCHECK(node->InputCount() == 2);
 
@@ -298,12 +326,13 @@
 
       NodeProperties::ChangeOp(node, machine()->Int32PairSub());
       // We access the additional return values through projections.
-      Node* low_node = graph()->NewNode(common()->Projection(0), node);
-      Node* high_node = graph()->NewNode(common()->Projection(1), node);
+      Node* low_node =
+          graph()->NewNode(common()->Projection(0), node, graph()->start());
+      Node* high_node =
+          graph()->NewNode(common()->Projection(1), node, graph()->start());
       ReplaceNode(node, low_node, high_node);
       break;
     }
-    // kExprI64Mul:
     case IrOpcode::kInt64Mul: {
       DCHECK(node->InputCount() == 2);
 
@@ -317,16 +346,13 @@
 
       NodeProperties::ChangeOp(node, machine()->Int32PairMul());
       // We access the additional return values through projections.
-      Node* low_node = graph()->NewNode(common()->Projection(0), node);
-      Node* high_node = graph()->NewNode(common()->Projection(1), node);
+      Node* low_node =
+          graph()->NewNode(common()->Projection(0), node, graph()->start());
+      Node* high_node =
+          graph()->NewNode(common()->Projection(1), node, graph()->start());
       ReplaceNode(node, low_node, high_node);
       break;
     }
-    // kExprI64DivS:
-    // kExprI64DivU:
-    // kExprI64RemS:
-    // kExprI64RemU:
-    // kExprI64Ior:
     case IrOpcode::kWord64Or: {
       DCHECK(node->InputCount() == 2);
       Node* left = node->InputAt(0);
@@ -341,8 +367,6 @@
       ReplaceNode(node, low_node, high_node);
       break;
     }
-
-    // kExprI64Xor:
     case IrOpcode::kWord64Xor: {
       DCHECK(node->InputCount() == 2);
       Node* left = node->InputAt(0);
@@ -357,7 +381,6 @@
       ReplaceNode(node, low_node, high_node);
       break;
     }
-    // kExprI64Shl:
     case IrOpcode::kWord64Shl: {
       // TODO(turbofan): if the shift count >= 32, then we can set the low word
       // of the output to 0 and just calculate the high word.
@@ -375,12 +398,13 @@
 
       NodeProperties::ChangeOp(node, machine()->Word32PairShl());
       // We access the additional return values through projections.
-      Node* low_node = graph()->NewNode(common()->Projection(0), node);
-      Node* high_node = graph()->NewNode(common()->Projection(1), node);
+      Node* low_node =
+          graph()->NewNode(common()->Projection(0), node, graph()->start());
+      Node* high_node =
+          graph()->NewNode(common()->Projection(1), node, graph()->start());
       ReplaceNode(node, low_node, high_node);
       break;
     }
-    // kExprI64ShrU:
     case IrOpcode::kWord64Shr: {
       // TODO(turbofan): if the shift count >= 32, then we can set the low word
       // of the output to 0 and just calculate the high word.
@@ -398,12 +422,13 @@
 
       NodeProperties::ChangeOp(node, machine()->Word32PairShr());
       // We access the additional return values through projections.
-      Node* low_node = graph()->NewNode(common()->Projection(0), node);
-      Node* high_node = graph()->NewNode(common()->Projection(1), node);
+      Node* low_node =
+          graph()->NewNode(common()->Projection(0), node, graph()->start());
+      Node* high_node =
+          graph()->NewNode(common()->Projection(1), node, graph()->start());
       ReplaceNode(node, low_node, high_node);
       break;
     }
-    // kExprI64ShrS:
     case IrOpcode::kWord64Sar: {
       // TODO(turbofan): if the shift count >= 32, then we can set the low word
       // of the output to 0 and just calculate the high word.
@@ -421,12 +446,13 @@
 
       NodeProperties::ChangeOp(node, machine()->Word32PairSar());
       // We access the additional return values through projections.
-      Node* low_node = graph()->NewNode(common()->Projection(0), node);
-      Node* high_node = graph()->NewNode(common()->Projection(1), node);
+      Node* low_node =
+          graph()->NewNode(common()->Projection(0), node, graph()->start());
+      Node* high_node =
+          graph()->NewNode(common()->Projection(1), node, graph()->start());
       ReplaceNode(node, low_node, high_node);
       break;
     }
-    // kExprI64Eq:
     case IrOpcode::kWord64Equal: {
       DCHECK(node->InputCount() == 2);
       Node* left = node->InputAt(0);
@@ -446,7 +472,6 @@
       ReplaceNode(node, replacement, nullptr);
       break;
     }
-    // kExprI64LtS:
     case IrOpcode::kInt64LessThan: {
       LowerComparison(node, machine()->Int32LessThan(),
                       machine()->Uint32LessThan());
@@ -467,8 +492,6 @@
                       machine()->Uint32LessThanOrEqual());
       break;
     }
-
-    // kExprI64SConvertI32:
     case IrOpcode::kChangeInt32ToInt64: {
       DCHECK(node->InputCount() == 1);
       Node* input = node->InputAt(0);
@@ -483,7 +506,6 @@
       node->NullAllInputs();
       break;
     }
-    // kExprI64UConvertI32: {
     case IrOpcode::kChangeUint32ToUint64: {
       DCHECK(node->InputCount() == 1);
       Node* input = node->InputAt(0);
@@ -494,7 +516,6 @@
       node->NullAllInputs();
       break;
     }
-    // kExprF64ReinterpretI64:
     case IrOpcode::kBitcastInt64ToFloat64: {
       DCHECK(node->InputCount() == 1);
       Node* input = node->InputAt(0);
@@ -505,14 +526,16 @@
           machine()->Store(
               StoreRepresentation(MachineRepresentation::kWord32,
                                   WriteBarrierKind::kNoWriteBarrier)),
-          stack_slot, graph()->NewNode(common()->Int32Constant(4)),
+          stack_slot,
+          graph()->NewNode(common()->Int32Constant(kHigherWordOffset)),
           GetReplacementHigh(input), graph()->start(), graph()->start());
 
       Node* store_low_word = graph()->NewNode(
           machine()->Store(
               StoreRepresentation(MachineRepresentation::kWord32,
                                   WriteBarrierKind::kNoWriteBarrier)),
-          stack_slot, graph()->NewNode(common()->Int32Constant(0)),
+          stack_slot,
+          graph()->NewNode(common()->Int32Constant(kLowerWordOffset)),
           GetReplacementLow(input), store_high_word, graph()->start());
 
       Node* load =
@@ -523,7 +546,6 @@
       ReplaceNode(node, load, nullptr);
       break;
     }
-    // kExprI64ReinterpretF64:
     case IrOpcode::kBitcastFloat64ToInt64: {
       DCHECK(node->InputCount() == 1);
       Node* input = node->InputAt(0);
@@ -539,15 +561,15 @@
           stack_slot, graph()->NewNode(common()->Int32Constant(0)), input,
           graph()->start(), graph()->start());
 
-      Node* high_node =
-          graph()->NewNode(machine()->Load(MachineType::Int32()), stack_slot,
-                           graph()->NewNode(common()->Int32Constant(4)), store,
-                           graph()->start());
+      Node* high_node = graph()->NewNode(
+          machine()->Load(MachineType::Int32()), stack_slot,
+          graph()->NewNode(common()->Int32Constant(kHigherWordOffset)), store,
+          graph()->start());
 
-      Node* low_node =
-          graph()->NewNode(machine()->Load(MachineType::Int32()), stack_slot,
-                           graph()->NewNode(common()->Int32Constant(0)), store,
-                           graph()->start());
+      Node* low_node = graph()->NewNode(
+          machine()->Load(MachineType::Int32()), stack_slot,
+          graph()->NewNode(common()->Int32Constant(kLowerWordOffset)), store,
+          graph()->start());
       ReplaceNode(node, low_node, high_node);
       break;
     }
@@ -659,7 +681,6 @@
       }
       break;
     }
-    // kExprI64Clz:
     case IrOpcode::kWord64Clz: {
       DCHECK(node->InputCount() == 1);
       Node* input = node->InputAt(0);
@@ -678,7 +699,6 @@
       ReplaceNode(node, low_node, graph()->NewNode(common()->Int32Constant(0)));
       break;
     }
-    // kExprI64Ctz:
     case IrOpcode::kWord64Ctz: {
       DCHECK(node->InputCount() == 1);
       DCHECK(machine()->Word32Ctz().IsSupported());
@@ -698,7 +718,6 @@
       ReplaceNode(node, low_node, graph()->NewNode(common()->Int32Constant(0)));
       break;
     }
-    // kExprI64Popcnt:
     case IrOpcode::kWord64Popcnt: {
       DCHECK(node->InputCount() == 1);
       Node* input = node->InputAt(0);
diff --git a/src/compiler/int64-lowering.h b/src/compiler/int64-lowering.h
index 7f6ef9a..4ec4e82 100644
--- a/src/compiler/int64-lowering.h
+++ b/src/compiler/int64-lowering.h
@@ -23,6 +23,12 @@
 
   void LowerGraph();
 
+  static int GetParameterCountAfterLowering(
+      Signature<MachineRepresentation>* signature);
+
+  static const int kLowerWordOffset;
+  static const int kHigherWordOffset;
+
  private:
   enum class State : uint8_t { kUnvisited, kOnStack, kVisited };
 
@@ -51,6 +57,7 @@
   bool HasReplacementHigh(Node* node);
   Node* GetReplacementHigh(Node* node);
   void PreparePhiReplacement(Node* phi);
+  void GetIndexNodes(Node* index, Node*& index_low, Node*& index_high);
 
   struct NodeState {
     Node* node;
diff --git a/src/compiler/js-builtin-reducer.cc b/src/compiler/js-builtin-reducer.cc
index 41f9c30..81d6392 100644
--- a/src/compiler/js-builtin-reducer.cc
+++ b/src/compiler/js-builtin-reducer.cc
@@ -91,16 +91,211 @@
       jsgraph_(jsgraph),
       type_cache_(TypeCache::Get()) {}
 
-// ECMA-262, section 15.8.2.11.
+// ES6 section 20.2.2.1 Math.abs ( x )
+Reduction JSBuiltinReducer::ReduceMathAbs(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.abs(a:plain-primitive) -> NumberAbs(ToNumber(a))
+    Node* input = ToNumber(r.GetJSCallInput(0));
+    Node* value = graph()->NewNode(simplified()->NumberAbs(), input);
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.6 Math.atan ( x )
+Reduction JSBuiltinReducer::ReduceMathAtan(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.atan(a:plain-primitive) -> NumberAtan(ToNumber(a))
+    Node* input = ToNumber(r.GetJSCallInput(0));
+    Node* value = graph()->NewNode(simplified()->NumberAtan(), input);
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.8 Math.atan2 ( y, x )
+Reduction JSBuiltinReducer::ReduceMathAtan2(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchTwo(Type::PlainPrimitive(), Type::PlainPrimitive())) {
+    // Math.atan2(a:plain-primitive,
+    //            b:plain-primitive) -> NumberAtan2(ToNumber(a),
+    //                                              ToNumber(b))
+    Node* left = ToNumber(r.left());
+    Node* right = ToNumber(r.right());
+    Node* value = graph()->NewNode(simplified()->NumberAtan2(), left, right);
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.7 Math.atanh ( x )
+Reduction JSBuiltinReducer::ReduceMathAtanh(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::Number())) {
+    // Math.atanh(a:number) -> NumberAtanh(a)
+    Node* value = graph()->NewNode(simplified()->NumberAtanh(), r.left());
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.10 Math.ceil ( x )
+Reduction JSBuiltinReducer::ReduceMathCeil(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.ceil(a:plain-primitive) -> NumberCeil(ToNumber(a))
+    Node* input = ToNumber(r.GetJSCallInput(0));
+    Node* value = graph()->NewNode(simplified()->NumberCeil(), input);
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.11 Math.clz32 ( x )
+Reduction JSBuiltinReducer::ReduceMathClz32(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.clz32(a:plain-primitive) -> NumberClz32(ToUint32(a))
+    Node* input = ToUint32(r.GetJSCallInput(0));
+    Node* value = graph()->NewNode(simplified()->NumberClz32(), input);
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.12 Math.cos ( x )
+Reduction JSBuiltinReducer::ReduceMathCos(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.cos(a:plain-primitive) -> NumberCos(ToNumber(a))
+    Node* input = ToNumber(r.GetJSCallInput(0));
+    Node* value = graph()->NewNode(simplified()->NumberCos(), input);
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.14 Math.exp ( x )
+Reduction JSBuiltinReducer::ReduceMathExp(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.exp(a:plain-primitive) -> NumberExp(ToNumber(a))
+    Node* input = ToNumber(r.GetJSCallInput(0));
+    Node* value = graph()->NewNode(simplified()->NumberExp(), input);
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.15 Math.expm1 ( x )
+Reduction JSBuiltinReducer::ReduceMathExpm1(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::Number())) {
+    // Math.expm1(a:number) -> NumberExpm1(a)
+    Node* value = graph()->NewNode(simplified()->NumberExpm1(), r.left());
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.16 Math.floor ( x )
+Reduction JSBuiltinReducer::ReduceMathFloor(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.floor(a:plain-primitive) -> NumberFloor(ToNumber(a))
+    Node* input = ToNumber(r.GetJSCallInput(0));
+    Node* value = graph()->NewNode(simplified()->NumberFloor(), input);
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.17 Math.fround ( x )
+Reduction JSBuiltinReducer::ReduceMathFround(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.fround(a:plain-primitive) -> NumberFround(ToNumber(a))
+    Node* input = ToNumber(r.GetJSCallInput(0));
+    Node* value = graph()->NewNode(simplified()->NumberFround(), input);
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.19 Math.imul ( x, y )
+Reduction JSBuiltinReducer::ReduceMathImul(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchTwo(Type::PlainPrimitive(), Type::PlainPrimitive())) {
+    // Math.imul(a:plain-primitive,
+    //           b:plain-primitive) -> NumberImul(ToUint32(a),
+    //                                            ToUint32(b))
+    Node* left = ToUint32(r.left());
+    Node* right = ToUint32(r.right());
+    Node* value = graph()->NewNode(simplified()->NumberImul(), left, right);
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.20 Math.log ( x )
+Reduction JSBuiltinReducer::ReduceMathLog(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.log(a:plain-primitive) -> NumberLog(ToNumber(a))
+    Node* input = ToNumber(r.GetJSCallInput(0));
+    Node* value = graph()->NewNode(simplified()->NumberLog(), input);
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.21 Math.log1p ( x )
+Reduction JSBuiltinReducer::ReduceMathLog1p(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.log1p(a:plain-primitive) -> NumberLog1p(ToNumber(a))
+    Node* input = ToNumber(r.GetJSCallInput(0));
+    Node* value = graph()->NewNode(simplified()->NumberLog1p(), input);
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.22 Math.log10 ( x )
+Reduction JSBuiltinReducer::ReduceMathLog10(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::Number())) {
+    // Math.log10(a:number) -> NumberLog10(a)
+    Node* value = graph()->NewNode(simplified()->NumberLog10(), r.left());
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.23 Math.log2 ( x )
+Reduction JSBuiltinReducer::ReduceMathLog2(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::Number())) {
+    // Math.log2(a:number) -> NumberLog(a)
+    Node* value = graph()->NewNode(simplified()->NumberLog2(), r.left());
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.24 Math.max ( value1, value2, ...values )
 Reduction JSBuiltinReducer::ReduceMathMax(Node* node) {
   JSCallReduction r(node);
   if (r.InputsMatchZero()) {
     // Math.max() -> -Infinity
     return Replace(jsgraph()->Constant(-V8_INFINITY));
   }
-  if (r.InputsMatchOne(Type::Number())) {
-    // Math.max(a:number) -> a
-    return Replace(r.left());
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.max(a:plain-primitive) -> ToNumber(a)
+    Node* value = ToNumber(r.GetJSCallInput(0));
+    return Replace(value);
   }
   if (r.InputsMatchAll(Type::Integral32())) {
     // Math.max(a:int32, b:int32, ...)
@@ -117,67 +312,28 @@
   return NoChange();
 }
 
-// ES6 section 20.2.2.19 Math.imul ( x, y )
-Reduction JSBuiltinReducer::ReduceMathImul(Node* node) {
+// ES6 section 20.2.2.25 Math.min ( value1, value2, ...values )
+Reduction JSBuiltinReducer::ReduceMathMin(Node* node) {
   JSCallReduction r(node);
-  if (r.InputsMatchTwo(Type::Number(), Type::Number())) {
-    // Math.imul(a:number, b:number) -> NumberImul(NumberToUint32(a),
-    //                                             NumberToUint32(b))
-    Node* a = graph()->NewNode(simplified()->NumberToUint32(), r.left());
-    Node* b = graph()->NewNode(simplified()->NumberToUint32(), r.right());
-    Node* value = graph()->NewNode(simplified()->NumberImul(), a, b);
+  if (r.InputsMatchZero()) {
+    // Math.min() -> Infinity
+    return Replace(jsgraph()->Constant(V8_INFINITY));
+  }
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.min(a:plain-primitive) -> ToNumber(a)
+    Node* value = ToNumber(r.GetJSCallInput(0));
     return Replace(value);
   }
-  return NoChange();
-}
-
-// ES6 section 20.2.2.10 Math.ceil ( x )
-Reduction JSBuiltinReducer::ReduceMathCeil(Node* node) {
-  JSCallReduction r(node);
-  if (r.InputsMatchOne(Type::Number())) {
-    // Math.ceil(a:number) -> NumberCeil(a)
-    Node* value = graph()->NewNode(simplified()->NumberCeil(), r.left());
-    return Replace(value);
-  }
-  return NoChange();
-}
-
-// ES6 section 20.2.2.11 Math.clz32 ( x )
-Reduction JSBuiltinReducer::ReduceMathClz32(Node* node) {
-  JSCallReduction r(node);
-  if (r.InputsMatchOne(Type::Unsigned32())) {
-    // Math.clz32(a:unsigned32) -> NumberClz32(a)
-    Node* value = graph()->NewNode(simplified()->NumberClz32(), r.left());
-    return Replace(value);
-  }
-  if (r.InputsMatchOne(Type::Number())) {
-    // Math.clz32(a:number) -> NumberClz32(NumberToUint32(a))
-    Node* value = graph()->NewNode(
-        simplified()->NumberClz32(),
-        graph()->NewNode(simplified()->NumberToUint32(), r.left()));
-    return Replace(value);
-  }
-  return NoChange();
-}
-
-// ES6 draft 08-24-14, section 20.2.2.16.
-Reduction JSBuiltinReducer::ReduceMathFloor(Node* node) {
-  JSCallReduction r(node);
-  if (r.InputsMatchOne(Type::Number())) {
-    // Math.floor(a:number) -> NumberFloor(a)
-    Node* value = graph()->NewNode(simplified()->NumberFloor(), r.left());
-    return Replace(value);
-  }
-  return NoChange();
-}
-
-// ES6 draft 08-24-14, section 20.2.2.17.
-Reduction JSBuiltinReducer::ReduceMathFround(Node* node) {
-  JSCallReduction r(node);
-  if (r.InputsMatchOne(Type::Number())) {
-    // Math.fround(a:number) -> TruncateFloat64ToFloat32(a)
-    Node* value =
-        graph()->NewNode(machine()->TruncateFloat64ToFloat32(), r.left());
+  if (r.InputsMatchAll(Type::Integral32())) {
+    // Math.min(a:int32, b:int32, ...)
+    Node* value = r.GetJSCallInput(0);
+    for (int i = 1; i < r.GetJSCallArity(); i++) {
+      Node* const input = r.GetJSCallInput(i);
+      value = graph()->NewNode(
+          common()->Select(MachineRepresentation::kNone),
+          graph()->NewNode(simplified()->NumberLessThan(), input, value), input,
+          value);
+    }
     return Replace(value);
   }
   return NoChange();
@@ -186,9 +342,33 @@
 // ES6 section 20.2.2.28 Math.round ( x )
 Reduction JSBuiltinReducer::ReduceMathRound(Node* node) {
   JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.round(a:plain-primitive) -> NumberRound(ToNumber(a))
+    Node* input = ToNumber(r.GetJSCallInput(0));
+    Node* value = graph()->NewNode(simplified()->NumberRound(), input);
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.9 Math.cbrt ( x )
+Reduction JSBuiltinReducer::ReduceMathCbrt(Node* node) {
+  JSCallReduction r(node);
   if (r.InputsMatchOne(Type::Number())) {
-    // Math.round(a:number) -> NumberRound(a)
-    Node* value = graph()->NewNode(simplified()->NumberRound(), r.left());
+    // Math.cbrt(a:number) -> NumberCbrt(a)
+    Node* value = graph()->NewNode(simplified()->NumberCbrt(), r.left());
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.30 Math.sin ( x )
+Reduction JSBuiltinReducer::ReduceMathSin(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.sin(a:plain-primitive) -> NumberSin(ToNumber(a))
+    Node* input = ToNumber(r.GetJSCallInput(0));
+    Node* value = graph()->NewNode(simplified()->NumberSin(), input);
     return Replace(value);
   }
   return NoChange();
@@ -197,9 +377,22 @@
 // ES6 section 20.2.2.32 Math.sqrt ( x )
 Reduction JSBuiltinReducer::ReduceMathSqrt(Node* node) {
   JSCallReduction r(node);
-  if (r.InputsMatchOne(Type::Number())) {
-    // Math.sqrt(a:number) -> Float64Sqrt(a)
-    Node* value = graph()->NewNode(machine()->Float64Sqrt(), r.left());
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.sqrt(a:plain-primitive) -> NumberSqrt(ToNumber(a))
+    Node* input = ToNumber(r.GetJSCallInput(0));
+    Node* value = graph()->NewNode(simplified()->NumberSqrt(), input);
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 20.2.2.33 Math.tan ( x )
+Reduction JSBuiltinReducer::ReduceMathTan(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.tan(a:plain-primitive) -> NumberTan(ToNumber(a))
+    Node* input = ToNumber(r.GetJSCallInput(0));
+    Node* value = graph()->NewNode(simplified()->NumberTan(), input);
     return Replace(value);
   }
   return NoChange();
@@ -208,9 +401,22 @@
 // ES6 section 20.2.2.35 Math.trunc ( x )
 Reduction JSBuiltinReducer::ReduceMathTrunc(Node* node) {
   JSCallReduction r(node);
-  if (r.InputsMatchOne(Type::Number())) {
-    // Math.trunc(a:number) -> NumberTrunc(a)
-    Node* value = graph()->NewNode(simplified()->NumberTrunc(), r.left());
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // Math.trunc(a:plain-primitive) -> NumberTrunc(ToNumber(a))
+    Node* input = ToNumber(r.GetJSCallInput(0));
+    Node* value = graph()->NewNode(simplified()->NumberTrunc(), input);
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+// ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits )
+Reduction JSBuiltinReducer::ReduceStringFromCharCode(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchOne(Type::PlainPrimitive())) {
+    // String.fromCharCode(a:plain-primitive) -> StringFromCharCode(a)
+    Node* input = ToNumber(r.GetJSCallInput(0));
+    Node* value = graph()->NewNode(simplified()->StringFromCharCode(), input);
     return Replace(value);
   }
   return NoChange();
@@ -223,11 +429,17 @@
   // Dispatch according to the BuiltinFunctionId if present.
   if (!r.HasBuiltinFunctionId()) return NoChange();
   switch (r.GetBuiltinFunctionId()) {
-    case kMathMax:
-      reduction = ReduceMathMax(node);
+    case kMathAbs:
+      reduction = ReduceMathAbs(node);
       break;
-    case kMathImul:
-      reduction = ReduceMathImul(node);
+    case kMathAtan:
+      reduction = ReduceMathAtan(node);
+      break;
+    case kMathAtan2:
+      reduction = ReduceMathAtan2(node);
+      break;
+    case kMathAtanh:
+      reduction = ReduceMathAtanh(node);
       break;
     case kMathClz32:
       reduction = ReduceMathClz32(node);
@@ -235,21 +447,63 @@
     case kMathCeil:
       reduction = ReduceMathCeil(node);
       break;
+    case kMathCos:
+      reduction = ReduceMathCos(node);
+      break;
+    case kMathExp:
+      reduction = ReduceMathExp(node);
+      break;
+    case kMathExpm1:
+      reduction = ReduceMathExpm1(node);
+      break;
     case kMathFloor:
       reduction = ReduceMathFloor(node);
       break;
     case kMathFround:
       reduction = ReduceMathFround(node);
       break;
+    case kMathImul:
+      reduction = ReduceMathImul(node);
+      break;
+    case kMathLog:
+      reduction = ReduceMathLog(node);
+      break;
+    case kMathLog1p:
+      reduction = ReduceMathLog1p(node);
+      break;
+    case kMathLog10:
+      reduction = ReduceMathLog10(node);
+      break;
+    case kMathLog2:
+      reduction = ReduceMathLog2(node);
+      break;
+    case kMathMax:
+      reduction = ReduceMathMax(node);
+      break;
+    case kMathMin:
+      reduction = ReduceMathMin(node);
+      break;
+    case kMathCbrt:
+      reduction = ReduceMathCbrt(node);
+      break;
     case kMathRound:
       reduction = ReduceMathRound(node);
       break;
+    case kMathSin:
+      reduction = ReduceMathSin(node);
+      break;
     case kMathSqrt:
       reduction = ReduceMathSqrt(node);
       break;
+    case kMathTan:
+      reduction = ReduceMathTan(node);
+      break;
     case kMathTrunc:
       reduction = ReduceMathTrunc(node);
       break;
+    case kStringFromCharCode:
+      reduction = ReduceStringFromCharCode(node);
+      break;
     default:
       break;
   }
@@ -261,6 +515,18 @@
   return reduction;
 }
 
+Node* JSBuiltinReducer::ToNumber(Node* input) {
+  Type* input_type = NodeProperties::GetType(input);
+  if (input_type->Is(Type::Number())) return input;
+  return graph()->NewNode(simplified()->PlainPrimitiveToNumber(), input);
+}
+
+Node* JSBuiltinReducer::ToUint32(Node* input) {
+  input = ToNumber(input);
+  Type* input_type = NodeProperties::GetType(input);
+  if (input_type->Is(Type::Unsigned32())) return input;
+  return graph()->NewNode(simplified()->NumberToUint32(), input);
+}
 
 Graph* JSBuiltinReducer::graph() const { return jsgraph()->graph(); }
 
@@ -273,11 +539,6 @@
 }
 
 
-MachineOperatorBuilder* JSBuiltinReducer::machine() const {
-  return jsgraph()->machine();
-}
-
-
 SimplifiedOperatorBuilder* JSBuiltinReducer::simplified() const {
   return jsgraph()->simplified();
 }
diff --git a/src/compiler/js-builtin-reducer.h b/src/compiler/js-builtin-reducer.h
index dfeb409..c915792 100644
--- a/src/compiler/js-builtin-reducer.h
+++ b/src/compiler/js-builtin-reducer.h
@@ -18,7 +18,6 @@
 // Forward declarations.
 class CommonOperatorBuilder;
 class JSGraph;
-class MachineOperatorBuilder;
 class SimplifiedOperatorBuilder;
 
 
@@ -30,22 +29,39 @@
   Reduction Reduce(Node* node) final;
 
  private:
-  Reduction ReduceFunctionCall(Node* node);
-  Reduction ReduceMathMax(Node* node);
-  Reduction ReduceMathImul(Node* node);
+  Reduction ReduceMathAbs(Node* node);
+  Reduction ReduceMathAtan(Node* node);
+  Reduction ReduceMathAtan2(Node* node);
+  Reduction ReduceMathAtanh(Node* node);
   Reduction ReduceMathCeil(Node* node);
   Reduction ReduceMathClz32(Node* node);
+  Reduction ReduceMathCos(Node* node);
+  Reduction ReduceMathExp(Node* node);
   Reduction ReduceMathFloor(Node* node);
   Reduction ReduceMathFround(Node* node);
+  Reduction ReduceMathImul(Node* node);
+  Reduction ReduceMathLog(Node* node);
+  Reduction ReduceMathLog1p(Node* node);
+  Reduction ReduceMathLog10(Node* node);
+  Reduction ReduceMathLog2(Node* node);
+  Reduction ReduceMathMax(Node* node);
+  Reduction ReduceMathMin(Node* node);
+  Reduction ReduceMathCbrt(Node* node);
+  Reduction ReduceMathExpm1(Node* node);
   Reduction ReduceMathRound(Node* node);
+  Reduction ReduceMathSin(Node* node);
   Reduction ReduceMathSqrt(Node* node);
+  Reduction ReduceMathTan(Node* node);
   Reduction ReduceMathTrunc(Node* node);
+  Reduction ReduceStringFromCharCode(Node* node);
+
+  Node* ToNumber(Node* value);
+  Node* ToUint32(Node* value);
 
   Graph* graph() const;
   JSGraph* jsgraph() const { return jsgraph_; }
   Isolate* isolate() const;
   CommonOperatorBuilder* common() const;
-  MachineOperatorBuilder* machine() const;
   SimplifiedOperatorBuilder* simplified() const;
 
   JSGraph* const jsgraph_;
diff --git a/src/compiler/js-call-reducer.cc b/src/compiler/js-call-reducer.cc
index 892dcc7..f4b0d7b 100644
--- a/src/compiler/js-call-reducer.cc
+++ b/src/compiler/js-call-reducer.cc
@@ -71,7 +71,6 @@
   size_t const arity = p.arity() - 2;
   NodeProperties::ReplaceValueInput(node, target, 0);
   NodeProperties::ReplaceValueInput(node, target, 1);
-  NodeProperties::RemoveFrameStateInput(node, 1);
   // TODO(bmeurer): We might need to propagate the tail call mode to
   // the JSCreateArray operator, because an Array call in tail call
   // position must always properly consume the parent stack frame.
@@ -89,7 +88,6 @@
   DCHECK_LE(2u, p.arity());
   Node* value = (p.arity() == 2) ? jsgraph()->ZeroConstant()
                                  : NodeProperties::GetValueInput(node, 2);
-  NodeProperties::RemoveFrameStateInput(node, 1);
   NodeProperties::ReplaceValueInputs(node, value);
   NodeProperties::ChangeOp(node, javascript()->ToNumber());
   return Changed(node);
@@ -220,9 +218,9 @@
   CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
   Node* target = NodeProperties::GetValueInput(node, 0);
   Node* context = NodeProperties::GetContextInput(node);
-  Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
   Node* control = NodeProperties::GetControlInput(node);
   Node* effect = NodeProperties::GetEffectInput(node);
+  Node* frame_state = NodeProperties::FindFrameStateBefore(node);
 
   // Try to specialize JSCallFunction {node}s with constant {target}s.
   HeapObjectMatcher m(target);
@@ -233,7 +231,6 @@
 
       // Raise a TypeError if the {target} is a "classConstructor".
       if (IsClassConstructor(shared->kind())) {
-        NodeProperties::RemoveFrameStateInput(node, 0);
         NodeProperties::ReplaceValueInputs(node, target);
         NodeProperties::ChangeOp(
             node, javascript()->CallRuntime(
@@ -272,7 +269,7 @@
                                          isolate());
       CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
       ConvertReceiverMode const convert_mode =
-          (bound_this->IsNull() || bound_this->IsUndefined())
+          (bound_this->IsNull(isolate()) || bound_this->IsUndefined(isolate()))
               ? ConvertReceiverMode::kNullOrUndefined
               : ConvertReceiverMode::kNotNullOrUndefined;
       size_t arity = p.arity();
@@ -326,11 +323,11 @@
     }
 
     // Check that the {target} is still the {array_function}.
-    Node* check = effect =
-        graph()->NewNode(javascript()->StrictEqual(), target, array_function,
-                         context, effect, control);
-    control = graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
-                               effect, control);
+    Node* check = graph()->NewNode(
+        javascript()->StrictEqual(CompareOperationHints::Any()), target,
+        array_function, context);
+    control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check,
+                                        frame_state, effect, control);
 
     // Turn the {node} into a {JSCreateArray} call.
     NodeProperties::ReplaceValueInput(node, array_function, 0);
@@ -344,11 +341,11 @@
           jsgraph()->Constant(handle(cell->value(), isolate()));
 
       // Check that the {target} is still the {target_function}.
-      Node* check = effect =
-          graph()->NewNode(javascript()->StrictEqual(), target, target_function,
-                           context, effect, control);
-      control = graph()->NewNode(common()->DeoptimizeUnless(), check,
-                                 frame_state, effect, control);
+      Node* check = graph()->NewNode(
+          javascript()->StrictEqual(CompareOperationHints::Any()), target,
+          target_function, context);
+      control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check,
+                                          frame_state, effect, control);
 
       // Specialize the JSCallFunction node to the {target_function}.
       NodeProperties::ReplaceValueInput(node, target_function, 0);
@@ -372,9 +369,9 @@
   Node* target = NodeProperties::GetValueInput(node, 0);
   Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
   Node* context = NodeProperties::GetContextInput(node);
-  Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
   Node* effect = NodeProperties::GetEffectInput(node);
   Node* control = NodeProperties::GetControlInput(node);
+  Node* frame_state = NodeProperties::FindFrameStateBefore(node);
 
   // Try to specialize JSCallConstruct {node}s with constant {target}s.
   HeapObjectMatcher m(target);
@@ -384,11 +381,6 @@
 
       // Raise a TypeError if the {target} is not a constructor.
       if (!function->IsConstructor()) {
-        // Drop the lazy bailout location and use the eager bailout point for
-        // the runtime function (actually as lazy bailout point). It doesn't
-        // really matter which bailout location we use since we never really
-        // go back after throwing the exception.
-        NodeProperties::RemoveFrameStateInput(node, 0);
         NodeProperties::ReplaceValueInputs(node, target);
         NodeProperties::ChangeOp(
             node, javascript()->CallRuntime(Runtime::kThrowCalledNonCallable));
@@ -408,7 +400,6 @@
         }
 
         // Turn the {node} into a {JSCreateArray} call.
-        NodeProperties::RemoveFrameStateInput(node, 1);
         for (int i = arity; i > 0; --i) {
           NodeProperties::ReplaceValueInput(
               node, NodeProperties::GetValueInput(node, i), i + 1);
@@ -454,16 +445,15 @@
     }
 
     // Check that the {target} is still the {array_function}.
-    Node* check = effect =
-        graph()->NewNode(javascript()->StrictEqual(), target, array_function,
-                         context, effect, control);
-    control = graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
-                               effect, control);
+    Node* check = graph()->NewNode(
+        javascript()->StrictEqual(CompareOperationHints::Any()), target,
+        array_function, context);
+    control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check,
+                                        frame_state, effect, control);
 
     // Turn the {node} into a {JSCreateArray} call.
     NodeProperties::ReplaceEffectInput(node, effect);
     NodeProperties::ReplaceControlInput(node, control);
-    NodeProperties::RemoveFrameStateInput(node, 1);
     for (int i = arity; i > 0; --i) {
       NodeProperties::ReplaceValueInput(
           node, NodeProperties::GetValueInput(node, i), i + 1);
@@ -478,11 +468,11 @@
           jsgraph()->Constant(handle(cell->value(), isolate()));
 
       // Check that the {target} is still the {target_function}.
-      Node* check = effect =
-          graph()->NewNode(javascript()->StrictEqual(), target, target_function,
-                           context, effect, control);
-      control = graph()->NewNode(common()->DeoptimizeUnless(), check,
-                                 frame_state, effect, control);
+      Node* check = graph()->NewNode(
+          javascript()->StrictEqual(CompareOperationHints::Any()), target,
+          target_function, context);
+      control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check,
+                                          frame_state, effect, control);
 
       // Specialize the JSCallConstruct node to the {target_function}.
       NodeProperties::ReplaceValueInput(node, target_function, 0);
diff --git a/src/compiler/js-context-specialization.cc b/src/compiler/js-context-specialization.cc
index 4d9d1d9..e02fc49 100644
--- a/src/compiler/js-context-specialization.cc
+++ b/src/compiler/js-context-specialization.cc
@@ -70,7 +70,7 @@
   // before the function to which it belongs has initialized the slot.
   // We must be conservative and check if the value in the slot is currently the
   // hole or undefined. If it is neither of these, then it must be initialized.
-  if (value->IsUndefined() || value->IsTheHole()) {
+  if (value->IsUndefined(isolate()) || value->IsTheHole(isolate())) {
     return NoChange();
   }
 
diff --git a/src/compiler/js-create-lowering.cc b/src/compiler/js-create-lowering.cc
index 2003363..0f829d4 100644
--- a/src/compiler/js-create-lowering.cc
+++ b/src/compiler/js-create-lowering.cc
@@ -37,7 +37,8 @@
 
   // Primitive allocation of static size.
   void Allocate(int size, PretenureFlag pretenure = NOT_TENURED) {
-    effect_ = graph()->NewNode(common()->BeginRegion(), effect_);
+    effect_ = graph()->NewNode(
+        common()->BeginRegion(RegionObservability::kNotObservable), effect_);
     allocation_ =
         graph()->NewNode(simplified()->Allocate(pretenure),
                          jsgraph()->Constant(size), effect_, control_);
@@ -201,6 +202,8 @@
       return ReduceJSCreateArguments(node);
     case IrOpcode::kJSCreateArray:
       return ReduceJSCreateArray(node);
+    case IrOpcode::kJSCreateClosure:
+      return ReduceJSCreateClosure(node);
     case IrOpcode::kJSCreateIterResultObject:
       return ReduceJSCreateIterResultObject(node);
     case IrOpcode::kJSCreateLiteralArray:
@@ -278,6 +281,7 @@
   CreateArgumentsType type = CreateArgumentsTypeOf(node->op());
   Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0);
   Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
+  Node* const control = graph()->start();
   FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
 
   // Use the ArgumentsAccessStub for materializing both mapped and unmapped
@@ -291,23 +295,24 @@
             shared_info->has_duplicate_parameters()) {
           return NoChange();
         }
-        // TODO(bmeurer): Actually we don't need a frame state here.
         Callable callable = CodeFactory::FastNewSloppyArguments(isolate());
+        Operator::Properties properties = node->op()->properties();
         CallDescriptor* desc = Linkage::GetStubCallDescriptor(
             isolate(), graph()->zone(), callable.descriptor(), 0,
-            CallDescriptor::kNeedsFrameState);
+            CallDescriptor::kNoFlags, properties);
         const Operator* new_op = common()->Call(desc);
         Node* stub_code = jsgraph()->HeapConstant(callable.code());
         node->InsertInput(graph()->zone(), 0, stub_code);
+        node->RemoveInput(3);  // Remove the frame state.
         NodeProperties::ChangeOp(node, new_op);
         return Changed(node);
       }
       case CreateArgumentsType::kUnmappedArguments: {
-        // TODO(bmeurer): Actually we don't need a frame state here.
         Callable callable = CodeFactory::FastNewStrictArguments(isolate());
+        Operator::Properties properties = node->op()->properties();
         CallDescriptor* desc = Linkage::GetStubCallDescriptor(
             isolate(), graph()->zone(), callable.descriptor(), 0,
-            CallDescriptor::kNeedsFrameState);
+            CallDescriptor::kNeedsFrameState, properties);
         const Operator* new_op = common()->Call(desc);
         Node* stub_code = jsgraph()->HeapConstant(callable.code());
         node->InsertInput(graph()->zone(), 0, stub_code);
@@ -315,11 +320,11 @@
         return Changed(node);
       }
       case CreateArgumentsType::kRestParameter: {
-        // TODO(bmeurer): Actually we don't need a frame state here.
         Callable callable = CodeFactory::FastNewRestParameter(isolate());
+        Operator::Properties properties = node->op()->properties();
         CallDescriptor* desc = Linkage::GetStubCallDescriptor(
             isolate(), graph()->zone(), callable.descriptor(), 0,
-            CallDescriptor::kNeedsFrameState);
+            CallDescriptor::kNeedsFrameState, properties);
         const Operator* new_op = common()->Call(desc);
         Node* stub_code = jsgraph()->HeapConstant(callable.code());
         node->InsertInput(graph()->zone(), 0, stub_code);
@@ -335,7 +340,6 @@
       Handle<SharedFunctionInfo> shared;
       if (!state_info.shared_info().ToHandle(&shared)) return NoChange();
       Node* const callee = NodeProperties::GetValueInput(node, 0);
-      Node* const control = NodeProperties::GetControlInput(node);
       Node* const context = NodeProperties::GetContextInput(node);
       Node* effect = NodeProperties::GetEffectInput(node);
       // TODO(mstarzinger): Duplicate parameters are not handled yet.
@@ -376,7 +380,6 @@
     } else if (type == CreateArgumentsType::kUnmappedArguments) {
       // Use inline allocation for all unmapped arguments objects within inlined
       // (i.e. non-outermost) frames, independent of the object size.
-      Node* const control = NodeProperties::GetControlInput(node);
       Node* const context = NodeProperties::GetContextInput(node);
       Node* effect = NodeProperties::GetEffectInput(node);
       // Choose the correct frame state and frame state info depending on
@@ -414,7 +417,6 @@
       int start_index = shared->internal_formal_parameter_count();
       // Use inline allocation for all unmapped arguments objects within inlined
       // (i.e. non-outermost) frames, independent of the object size.
-      Node* const control = NodeProperties::GetControlInput(node);
       Node* const context = NodeProperties::GetContextInput(node);
       Node* effect = NodeProperties::GetEffectInput(node);
       // Choose the correct frame state and frame state info depending on
@@ -471,6 +473,9 @@
   PretenureFlag pretenure = site->GetPretenureMode();
   ElementsKind elements_kind = site->GetElementsKind();
   DCHECK(IsFastElementsKind(elements_kind));
+  if (NodeProperties::GetType(length)->Max() > 0) {
+    elements_kind = GetHoleyElementsKind(elements_kind);
+  }
   dependencies()->AssumeTenuringDecision(site);
   dependencies()->AssumeTransitionStable(site);
 
@@ -540,6 +545,47 @@
   return NoChange();
 }
 
+Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
+  DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode());
+  CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
+  Handle<SharedFunctionInfo> shared = p.shared_info();
+
+  Node* effect = NodeProperties::GetEffectInput(node);
+  Node* control = NodeProperties::GetControlInput(node);
+  Node* context = NodeProperties::GetContextInput(node);
+  Node* native_context = effect = graph()->NewNode(
+      javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
+      context, context, effect);
+  int function_map_index =
+      Context::FunctionMapIndex(shared->language_mode(), shared->kind());
+  Node* function_map = effect =
+      graph()->NewNode(javascript()->LoadContext(0, function_map_index, true),
+                       native_context, native_context, effect);
+  // Note that it is only safe to embed the raw entry point of the compile
+  // lazy stub into the code, because that stub is immortal and immovable.
+  Node* compile_entry = jsgraph()->IntPtrConstant(reinterpret_cast<intptr_t>(
+      jsgraph()->isolate()->builtins()->CompileLazy()->entry()));
+  Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant();
+  Node* empty_literals_array = jsgraph()->EmptyLiteralsArrayConstant();
+  Node* the_hole = jsgraph()->TheHoleConstant();
+  Node* undefined = jsgraph()->UndefinedConstant();
+  AllocationBuilder a(jsgraph(), effect, control);
+  STATIC_ASSERT(JSFunction::kSize == 9 * kPointerSize);
+  a.Allocate(JSFunction::kSize, p.pretenure());
+  a.Store(AccessBuilder::ForMap(), function_map);
+  a.Store(AccessBuilder::ForJSObjectProperties(), empty_fixed_array);
+  a.Store(AccessBuilder::ForJSObjectElements(), empty_fixed_array);
+  a.Store(AccessBuilder::ForJSFunctionLiterals(), empty_literals_array);
+  a.Store(AccessBuilder::ForJSFunctionPrototypeOrInitialMap(), the_hole);
+  a.Store(AccessBuilder::ForJSFunctionSharedFunctionInfo(), shared);
+  a.Store(AccessBuilder::ForJSFunctionContext(), context);
+  a.Store(AccessBuilder::ForJSFunctionCodeEntry(), compile_entry);
+  a.Store(AccessBuilder::ForJSFunctionNextFunctionLink(), undefined);
+  RelaxControls(node);
+  a.FinishAndChange(node);
+  return Changed(node);
+}
+
 Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) {
   DCHECK_EQ(IrOpcode::kJSCreateIterResultObject, node->opcode());
   Node* value = NodeProperties::GetValueInput(node, 0);
@@ -886,8 +932,9 @@
     Handle<Name> property_name(
         boilerplate_map->instance_descriptors()->GetKey(i), isolate());
     FieldIndex index = FieldIndex::ForDescriptor(*boilerplate_map, i);
-    FieldAccess access = {kTaggedBase, index.offset(), property_name,
-                          Type::Tagged(), MachineType::AnyTagged()};
+    FieldAccess access = {
+        kTaggedBase,    index.offset(),           property_name,
+        Type::Tagged(), MachineType::AnyTagged(), kFullWriteBarrier};
     Node* value;
     if (boilerplate->IsUnboxedDoubleField(index)) {
       access.machine_type = MachineType::Float64();
@@ -905,21 +952,25 @@
         site_context->ExitScope(current_site, boilerplate_object);
       } else if (property_details.representation().IsDouble()) {
         // Allocate a mutable HeapNumber box and store the value into it.
-        Callable callable = CodeFactory::AllocateMutableHeapNumber(isolate());
-        CallDescriptor* desc = Linkage::GetStubCallDescriptor(
-            isolate(), jsgraph()->zone(), callable.descriptor(), 0,
-            CallDescriptor::kNoFlags, Operator::kNoThrow);
+        effect = graph()->NewNode(
+            common()->BeginRegion(RegionObservability::kNotObservable), effect);
         value = effect = graph()->NewNode(
-            common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
-            jsgraph()->NoContextConstant(), effect, control);
+            simplified()->Allocate(NOT_TENURED),
+            jsgraph()->Constant(HeapNumber::kSize), effect, control);
+        effect = graph()->NewNode(
+            simplified()->StoreField(AccessBuilder::ForMap()), value,
+            jsgraph()->HeapConstant(factory()->mutable_heap_number_map()),
+            effect, control);
         effect = graph()->NewNode(
             simplified()->StoreField(AccessBuilder::ForHeapNumberValue()),
             value, jsgraph()->Constant(
                        Handle<HeapNumber>::cast(boilerplate_value)->value()),
             effect, control);
+        value = effect =
+            graph()->NewNode(common()->FinishRegion(), value, effect);
       } else if (property_details.representation().IsSmi()) {
         // Ensure that value is stored as smi.
-        value = boilerplate_value->IsUninitialized()
+        value = boilerplate_value->IsUninitialized(isolate())
                     ? jsgraph()->ZeroConstant()
                     : jsgraph()->Constant(boilerplate_value);
       } else {
diff --git a/src/compiler/js-create-lowering.h b/src/compiler/js-create-lowering.h
index 52e7ec2..57b28af 100644
--- a/src/compiler/js-create-lowering.h
+++ b/src/compiler/js-create-lowering.h
@@ -45,6 +45,7 @@
   Reduction ReduceJSCreate(Node* node);
   Reduction ReduceJSCreateArguments(Node* node);
   Reduction ReduceJSCreateArray(Node* node);
+  Reduction ReduceJSCreateClosure(Node* node);
   Reduction ReduceJSCreateIterResultObject(Node* node);
   Reduction ReduceJSCreateLiteral(Node* node);
   Reduction ReduceJSCreateFunctionContext(Node* node);
diff --git a/src/compiler/js-generic-lowering.cc b/src/compiler/js-generic-lowering.cc
index 1f12579..47a82d2 100644
--- a/src/compiler/js-generic-lowering.cc
+++ b/src/compiler/js-generic-lowering.cc
@@ -28,10 +28,7 @@
                    : CallDescriptor::kNoFlags;
 }
 
-
-JSGenericLowering::JSGenericLowering(bool is_typing_enabled, JSGraph* jsgraph)
-    : is_typing_enabled_(is_typing_enabled), jsgraph_(jsgraph) {}
-
+JSGenericLowering::JSGenericLowering(JSGraph* jsgraph) : jsgraph_(jsgraph) {}
 
 JSGenericLowering::~JSGenericLowering() {}
 
@@ -44,40 +41,12 @@
       break;
     JS_OP_LIST(DECLARE_CASE)
 #undef DECLARE_CASE
-    case IrOpcode::kBranch:
-    case IrOpcode::kDeoptimizeIf:
-    case IrOpcode::kDeoptimizeUnless:
-      // TODO(mstarzinger): If typing is enabled then simplified lowering will
-      // have inserted the correct ChangeBoolToBit, otherwise we need to perform
-      // poor-man's representation inference here and insert manual change.
-      if (!is_typing_enabled_) {
-        Node* condition = node->InputAt(0);
-        Node* test = graph()->NewNode(machine()->WordEqual(), condition,
-                                      jsgraph()->TrueConstant());
-        node->ReplaceInput(0, test);
-      }
-      // Fall-through.
     default:
       // Nothing to see.
       return NoChange();
   }
   return Changed(node);
 }
-
-#define REPLACE_BINARY_OP_IC_CALL(Op, token)                                \
-  void JSGenericLowering::Lower##Op(Node* node) {                           \
-    CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);           \
-    ReplaceWithStubCall(node, CodeFactory::BinaryOpIC(isolate(), token),    \
-                        CallDescriptor::kPatchableCallSiteWithNop | flags); \
-  }
-REPLACE_BINARY_OP_IC_CALL(JSShiftLeft, Token::SHL)
-REPLACE_BINARY_OP_IC_CALL(JSShiftRight, Token::SAR)
-REPLACE_BINARY_OP_IC_CALL(JSShiftRightLogical, Token::SHR)
-REPLACE_BINARY_OP_IC_CALL(JSMultiply, Token::MUL)
-REPLACE_BINARY_OP_IC_CALL(JSDivide, Token::DIV)
-REPLACE_BINARY_OP_IC_CALL(JSModulus, Token::MOD)
-#undef REPLACE_BINARY_OP_IC_CALL
-
 #define REPLACE_RUNTIME_CALL(op, fun)             \
   void JSGenericLowering::Lower##op(Node* node) { \
     ReplaceWithRuntimeCall(node, fun);            \
@@ -95,18 +64,22 @@
   }
 REPLACE_STUB_CALL(Add)
 REPLACE_STUB_CALL(Subtract)
+REPLACE_STUB_CALL(Multiply)
+REPLACE_STUB_CALL(Divide)
+REPLACE_STUB_CALL(Modulus)
 REPLACE_STUB_CALL(BitwiseAnd)
 REPLACE_STUB_CALL(BitwiseOr)
 REPLACE_STUB_CALL(BitwiseXor)
+REPLACE_STUB_CALL(ShiftLeft)
+REPLACE_STUB_CALL(ShiftRight)
+REPLACE_STUB_CALL(ShiftRightLogical)
 REPLACE_STUB_CALL(LessThan)
 REPLACE_STUB_CALL(LessThanOrEqual)
 REPLACE_STUB_CALL(GreaterThan)
 REPLACE_STUB_CALL(GreaterThanOrEqual)
+REPLACE_STUB_CALL(HasProperty)
 REPLACE_STUB_CALL(Equal)
 REPLACE_STUB_CALL(NotEqual)
-REPLACE_STUB_CALL(StrictEqual)
-REPLACE_STUB_CALL(StrictNotEqual)
-REPLACE_STUB_CALL(ToBoolean)
 REPLACE_STUB_CALL(ToInteger)
 REPLACE_STUB_CALL(ToLength)
 REPLACE_STUB_CALL(ToNumber)
@@ -117,7 +90,12 @@
 
 void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
                                             CallDescriptor::Flags flags) {
-  Operator::Properties properties = node->op()->properties();
+  ReplaceWithStubCall(node, callable, flags, node->op()->properties());
+}
+
+void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
+                                            CallDescriptor::Flags flags,
+                                            Operator::Properties properties) {
   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
       isolate(), zone(), callable.descriptor(), 0, flags, properties);
   Node* stub_code = jsgraph()->HeapConstant(callable.code());
@@ -143,11 +121,32 @@
   NodeProperties::ChangeOp(node, common()->Call(desc));
 }
 
+void JSGenericLowering::LowerJSStrictEqual(Node* node) {
+  Callable callable = CodeFactory::StrictEqual(isolate());
+  node->AppendInput(zone(), graph()->start());
+  ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags,
+                      Operator::kEliminatable);
+}
+
+void JSGenericLowering::LowerJSStrictNotEqual(Node* node) {
+  Callable callable = CodeFactory::StrictNotEqual(isolate());
+  node->AppendInput(zone(), graph()->start());
+  ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags,
+                      Operator::kEliminatable);
+}
+
+void JSGenericLowering::LowerJSToBoolean(Node* node) {
+  Callable callable = CodeFactory::ToBoolean(isolate());
+  node->AppendInput(zone(), graph()->start());
+  ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
+                      Operator::kEliminatable);
+}
 
 void JSGenericLowering::LowerJSTypeOf(Node* node) {
-  CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
   Callable callable = CodeFactory::Typeof(isolate());
-  ReplaceWithStubCall(node, callable, flags);
+  node->AppendInput(zone(), graph()->start());
+  ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
+                      Operator::kEliminatable);
 }
 
 
@@ -157,17 +156,15 @@
   Node* control = NodeProperties::GetControlInput(node);
   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
   const PropertyAccess& p = PropertyAccessOf(node->op());
-  Callable callable =
-      CodeFactory::KeyedLoadICInOptimizedCode(isolate(), UNINITIALIZED);
+  Callable callable = CodeFactory::KeyedLoadICInOptimizedCode(isolate());
   // Load the type feedback vector from the closure.
-  Node* shared_info = effect = graph()->NewNode(
+  Node* literals = effect = graph()->NewNode(
       machine()->Load(MachineType::AnyTagged()), closure,
-      jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
-                                kHeapObjectTag),
+      jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
       effect, control);
   Node* vector = effect = graph()->NewNode(
-      machine()->Load(MachineType::AnyTagged()), shared_info,
-      jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
+      machine()->Load(MachineType::AnyTagged()), literals,
+      jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
                                 kHeapObjectTag),
       effect, control);
   node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
@@ -183,17 +180,15 @@
   Node* control = NodeProperties::GetControlInput(node);
   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
   NamedAccess const& p = NamedAccessOf(node->op());
-  Callable callable = CodeFactory::LoadICInOptimizedCode(
-      isolate(), NOT_INSIDE_TYPEOF, UNINITIALIZED);
+  Callable callable = CodeFactory::LoadICInOptimizedCode(isolate());
   // Load the type feedback vector from the closure.
-  Node* shared_info = effect = graph()->NewNode(
+  Node* literals = effect = graph()->NewNode(
       machine()->Load(MachineType::AnyTagged()), closure,
-      jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
-                                kHeapObjectTag),
+      jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
       effect, control);
   Node* vector = effect = graph()->NewNode(
-      machine()->Load(MachineType::AnyTagged()), shared_info,
-      jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
+      machine()->Load(MachineType::AnyTagged()), literals,
+      jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
                                 kHeapObjectTag),
       effect, control);
   node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
@@ -206,39 +201,25 @@
 
 void JSGenericLowering::LowerJSLoadGlobal(Node* node) {
   Node* closure = NodeProperties::GetValueInput(node, 0);
-  Node* context = NodeProperties::GetContextInput(node);
   Node* effect = NodeProperties::GetEffectInput(node);
   Node* control = NodeProperties::GetControlInput(node);
   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
   const LoadGlobalParameters& p = LoadGlobalParametersOf(node->op());
-  Callable callable = CodeFactory::LoadICInOptimizedCode(
-      isolate(), p.typeof_mode(), UNINITIALIZED);
+  Callable callable =
+      CodeFactory::LoadGlobalICInOptimizedCode(isolate(), p.typeof_mode());
   // Load the type feedback vector from the closure.
-  Node* shared_info = effect = graph()->NewNode(
+  Node* literals = effect = graph()->NewNode(
       machine()->Load(MachineType::AnyTagged()), closure,
-      jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
-                                kHeapObjectTag),
+      jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
       effect, control);
   Node* vector = effect = graph()->NewNode(
-      machine()->Load(MachineType::AnyTagged()), shared_info,
-      jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
+      machine()->Load(MachineType::AnyTagged()), literals,
+      jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
                                 kHeapObjectTag),
       effect, control);
-  // Load global object from the context.
-  Node* native_context = effect =
-      graph()->NewNode(machine()->Load(MachineType::AnyTagged()), context,
-                       jsgraph()->IntPtrConstant(
-                           Context::SlotOffset(Context::NATIVE_CONTEXT_INDEX)),
-                       effect, control);
-  Node* global = effect = graph()->NewNode(
-      machine()->Load(MachineType::AnyTagged()), native_context,
-      jsgraph()->IntPtrConstant(Context::SlotOffset(Context::EXTENSION_INDEX)),
-      effect, control);
-  node->InsertInput(zone(), 0, global);
-  node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
-  node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
-  node->ReplaceInput(3, vector);
-  node->ReplaceInput(6, effect);
+  node->InsertInput(zone(), 0, jsgraph()->SmiConstant(p.feedback().index()));
+  node->ReplaceInput(1, vector);
+  node->ReplaceInput(4, effect);
   ReplaceWithStubCall(node, callable, flags);
 }
 
@@ -250,17 +231,16 @@
   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
   PropertyAccess const& p = PropertyAccessOf(node->op());
   LanguageMode language_mode = p.language_mode();
-  Callable callable = CodeFactory::KeyedStoreICInOptimizedCode(
-      isolate(), language_mode, UNINITIALIZED);
+  Callable callable =
+      CodeFactory::KeyedStoreICInOptimizedCode(isolate(), language_mode);
   // Load the type feedback vector from the closure.
-  Node* shared_info = effect = graph()->NewNode(
+  Node* literals = effect = graph()->NewNode(
       machine()->Load(MachineType::AnyTagged()), closure,
-      jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
-                                kHeapObjectTag),
+      jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
       effect, control);
   Node* vector = effect = graph()->NewNode(
-      machine()->Load(MachineType::AnyTagged()), shared_info,
-      jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
+      machine()->Load(MachineType::AnyTagged()), literals,
+      jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
                                 kHeapObjectTag),
       effect, control);
   node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.feedback().index()));
@@ -276,17 +256,16 @@
   Node* control = NodeProperties::GetControlInput(node);
   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
   NamedAccess const& p = NamedAccessOf(node->op());
-  Callable callable = CodeFactory::StoreICInOptimizedCode(
-      isolate(), p.language_mode(), UNINITIALIZED);
+  Callable callable =
+      CodeFactory::StoreICInOptimizedCode(isolate(), p.language_mode());
   // Load the type feedback vector from the closure.
-  Node* shared_info = effect = graph()->NewNode(
+  Node* literals = effect = graph()->NewNode(
       machine()->Load(MachineType::AnyTagged()), closure,
-      jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
-                                kHeapObjectTag),
+      jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
       effect, control);
   Node* vector = effect = graph()->NewNode(
-      machine()->Load(MachineType::AnyTagged()), shared_info,
-      jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
+      machine()->Load(MachineType::AnyTagged()), literals,
+      jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
                                 kHeapObjectTag),
       effect, control);
   node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
@@ -304,17 +283,16 @@
   Node* control = NodeProperties::GetControlInput(node);
   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
   const StoreGlobalParameters& p = StoreGlobalParametersOf(node->op());
-  Callable callable = CodeFactory::StoreICInOptimizedCode(
-      isolate(), p.language_mode(), UNINITIALIZED);
+  Callable callable =
+      CodeFactory::StoreICInOptimizedCode(isolate(), p.language_mode());
   // Load the type feedback vector from the closure.
-  Node* shared_info = effect = graph()->NewNode(
+  Node* literals = effect = graph()->NewNode(
       machine()->Load(MachineType::AnyTagged()), closure,
-      jsgraph()->IntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
-                                kHeapObjectTag),
+      jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
       effect, control);
   Node* vector = effect = graph()->NewNode(
-      machine()->Load(MachineType::AnyTagged()), shared_info,
-      jsgraph()->IntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
+      machine()->Load(MachineType::AnyTagged()), literals,
+      jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
                                 kHeapObjectTag),
       effect, control);
   // Load global object from the context.
@@ -344,11 +322,6 @@
 }
 
 
-void JSGenericLowering::LowerJSHasProperty(Node* node) {
-  ReplaceWithRuntimeCall(node, Runtime::kHasProperty);
-}
-
-
 void JSGenericLowering::LowerJSInstanceOf(Node* node) {
   CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
   Callable callable = CodeFactory::InstanceOf(isolate());
@@ -447,7 +420,8 @@
           CallDescriptor::kNeedsFrameState);
       node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
       node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site));
-      node->InsertInput(graph()->zone(), 3, jsgraph()->UndefinedConstant());
+      node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(0));
+      node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
       NodeProperties::ChangeOp(node, common()->Call(desc));
     } else if (arity == 1) {
       // TODO(bmeurer): Optimize for the 0 length non-holey case?
@@ -462,8 +436,7 @@
       node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
       NodeProperties::ChangeOp(node, common()->Call(desc));
     } else {
-      ArrayNArgumentsConstructorStub stub(isolate(), elements_kind,
-                                          override_mode);
+      ArrayNArgumentsConstructorStub stub(isolate());
       CallDescriptor* desc = Linkage::GetStubCallDescriptor(
           isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(),
           arity + 1, CallDescriptor::kNeedsFrameState);
@@ -491,9 +464,8 @@
   Handle<SharedFunctionInfo> const shared_info = p.shared_info();
   node->InsertInput(zone(), 0, jsgraph()->HeapConstant(shared_info));
 
-  // Use the FastNewClosureStub that allocates in new space only for nested
-  // functions that don't need literals cloning.
-  if (p.pretenure() == NOT_TENURED && shared_info->num_literals() == 0) {
+  // Use the FastNewClosureStub only for functions allocated in new space.
+  if (p.pretenure() == NOT_TENURED) {
     Callable callable = CodeFactory::FastNewClosure(
         isolate(), shared_info->language_mode(), shared_info->kind());
     ReplaceWithStubCall(node, callable, flags);
@@ -685,9 +657,17 @@
   NodeProperties::ChangeOp(node, machine()->Store(representation));
 }
 
+void JSGenericLowering::LowerJSGeneratorStore(Node* node) {
+  UNREACHABLE();  // Eliminated in typed lowering.
+}
 
-void JSGenericLowering::LowerJSYield(Node* node) { UNIMPLEMENTED(); }
+void JSGenericLowering::LowerJSGeneratorRestoreContinuation(Node* node) {
+  UNREACHABLE();  // Eliminated in typed lowering.
+}
 
+void JSGenericLowering::LowerJSGeneratorRestoreRegister(Node* node) {
+  UNREACHABLE();  // Eliminated in typed lowering.
+}
 
 void JSGenericLowering::LowerJSStackCheck(Node* node) {
   Node* effect = NodeProperties::GetEffectInput(node);
diff --git a/src/compiler/js-generic-lowering.h b/src/compiler/js-generic-lowering.h
index 5ee759b..38ee431 100644
--- a/src/compiler/js-generic-lowering.h
+++ b/src/compiler/js-generic-lowering.h
@@ -24,7 +24,7 @@
 // Lowers JS-level operators to runtime and IC calls in the "generic" case.
 class JSGenericLowering final : public Reducer {
  public:
-  JSGenericLowering(bool is_typing_enabled, JSGraph* jsgraph);
+  explicit JSGenericLowering(JSGraph* jsgraph);
   ~JSGenericLowering() final;
 
   Reduction Reduce(Node* node) final;
@@ -37,6 +37,8 @@
 
   // Helpers to replace existing nodes with a generic call.
   void ReplaceWithStubCall(Node* node, Callable c, CallDescriptor::Flags flags);
+  void ReplaceWithStubCall(Node* node, Callable c, CallDescriptor::Flags flags,
+                           Operator::Properties properties);
   void ReplaceWithRuntimeCall(Node* node, Runtime::FunctionId f, int args = -1);
 
   Zone* zone() const;
@@ -47,7 +49,6 @@
   MachineOperatorBuilder* machine() const;
 
  private:
-  bool const is_typing_enabled_;
   JSGraph* const jsgraph_;
 };
 
diff --git a/src/compiler/js-global-object-specialization.cc b/src/compiler/js-global-object-specialization.cc
index d8c9f17..31407e8 100644
--- a/src/compiler/js-global-object-specialization.cc
+++ b/src/compiler/js-global-object-specialization.cc
@@ -12,7 +12,7 @@
 #include "src/compiler/node-properties.h"
 #include "src/compiler/simplified-operator.h"
 #include "src/lookup.h"
-#include "src/objects-inl.h"  // TODO(mstarzinger): Temporary cycle breaker!
+#include "src/objects-inl.h"
 #include "src/type-cache.h"
 
 namespace v8 {
@@ -74,6 +74,7 @@
   // properties of the global object here (represented as PropertyCell).
   LookupIterator it(global_object, name, LookupIterator::OWN);
   if (it.state() != LookupIterator::DATA) return NoChange();
+  if (!it.GetHolder<JSObject>()->IsJSGlobalObject()) return NoChange();
   Handle<PropertyCell> property_cell = it.GetPropertyCell();
   PropertyDetails property_details = property_cell->property_details();
   Handle<Object> property_cell_value(property_cell->value(), isolate());
@@ -130,9 +131,9 @@
   DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode());
   Handle<Name> name = StoreGlobalParametersOf(node->op()).name();
   Node* value = NodeProperties::GetValueInput(node, 0);
-  Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
   Node* effect = NodeProperties::GetEffectInput(node);
   Node* control = NodeProperties::GetControlInput(node);
+  Node* frame_state = NodeProperties::FindFrameStateBefore(node);
 
   // Retrieve the global object from the given {node}.
   Handle<JSGlobalObject> global_object;
@@ -154,6 +155,7 @@
   // properties of the global object here (represented as PropertyCell).
   LookupIterator it(global_object, name, LookupIterator::OWN);
   if (it.state() != LookupIterator::DATA) return NoChange();
+  if (!it.GetHolder<JSObject>()->IsJSGlobalObject()) return NoChange();
   Handle<PropertyCell> property_cell = it.GetPropertyCell();
   PropertyDetails property_details = property_cell->property_details();
   Handle<Object> property_cell_value(property_cell->value(), isolate());
@@ -171,8 +173,8 @@
       Node* check =
           graph()->NewNode(simplified()->ReferenceEqual(Type::Tagged()), value,
                            jsgraph()->Constant(property_cell_value));
-      control = graph()->NewNode(common()->DeoptimizeUnless(), check,
-                                 frame_state, effect, control);
+      control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check,
+                                          frame_state, effect, control);
       break;
     }
     case PropertyCellType::kConstantType: {
@@ -183,8 +185,8 @@
       Type* property_cell_value_type = Type::TaggedSigned();
       if (property_cell_value->IsHeapObject()) {
         // Deoptimize if the {value} is a Smi.
-        control = graph()->NewNode(common()->DeoptimizeIf(), check, frame_state,
-                                   effect, control);
+        control = effect = graph()->NewNode(common()->DeoptimizeIf(), check,
+                                            frame_state, effect, control);
 
         // Load the {value} map check against the {property_cell} map.
         Node* value_map = effect =
@@ -197,8 +199,8 @@
             jsgraph()->HeapConstant(property_cell_value_map));
         property_cell_value_type = Type::TaggedPointer();
       }
-      control = graph()->NewNode(common()->DeoptimizeUnless(), check,
-                                 frame_state, effect, control);
+      control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check,
+                                          frame_state, effect, control);
       effect = graph()->NewNode(
           simplified()->StoreField(
               AccessBuilder::ForPropertyCellValue(property_cell_value_type)),
diff --git a/src/compiler/js-graph.cc b/src/compiler/js-graph.cc
index 98ca7aa..3f20daa 100644
--- a/src/compiler/js-graph.cc
+++ b/src/compiler/js-graph.cc
@@ -14,6 +14,20 @@
 #define CACHED(name, expr) \
   cached_nodes_[name] ? cached_nodes_[name] : (cached_nodes_[name] = (expr))
 
+Node* JSGraph::AllocateInNewSpaceStubConstant() {
+  return CACHED(kAllocateInNewSpaceStubConstant,
+                HeapConstant(isolate()->builtins()->AllocateInNewSpace()));
+}
+
+Node* JSGraph::AllocateInOldSpaceStubConstant() {
+  return CACHED(kAllocateInOldSpaceStubConstant,
+                HeapConstant(isolate()->builtins()->AllocateInOldSpace()));
+}
+
+Node* JSGraph::ToNumberBuiltinConstant() {
+  return CACHED(kToNumberBuiltinConstant,
+                HeapConstant(isolate()->builtins()->ToNumber()));
+}
 
 Node* JSGraph::CEntryStubConstant(int result_size) {
   if (result_size == 1) {
@@ -29,11 +43,26 @@
                 HeapConstant(factory()->empty_fixed_array()));
 }
 
+Node* JSGraph::EmptyLiteralsArrayConstant() {
+  return CACHED(kEmptyLiteralsArrayConstant,
+                HeapConstant(factory()->empty_literals_array()));
+}
+
+Node* JSGraph::HeapNumberMapConstant() {
+  return CACHED(kHeapNumberMapConstant,
+                HeapConstant(factory()->heap_number_map()));
+}
+
 Node* JSGraph::OptimizedOutConstant() {
   return CACHED(kOptimizedOutConstant,
                 HeapConstant(factory()->optimized_out()));
 }
 
+Node* JSGraph::StaleRegisterConstant() {
+  return CACHED(kStaleRegisterConstant,
+                HeapConstant(factory()->stale_register()));
+}
+
 Node* JSGraph::UndefinedConstant() {
   return CACHED(kUndefinedConstant, HeapConstant(factory()->undefined_value()));
 }
@@ -76,9 +105,6 @@
 
 
 Node* JSGraph::HeapConstant(Handle<HeapObject> value) {
-  if (value->IsConsString()) {
-    value = String::Flatten(Handle<String>::cast(value), TENURED);
-  }
   Node** loc = cache_.FindHeapConstant(value);
   if (*loc == nullptr) {
     *loc = graph()->NewNode(common()->HeapConstant(value));
@@ -92,15 +118,15 @@
   // canonicalized node can be used.
   if (value->IsNumber()) {
     return Constant(value->Number());
-  } else if (value->IsUndefined()) {
+  } else if (value->IsUndefined(isolate())) {
     return UndefinedConstant();
-  } else if (value->IsTrue()) {
+  } else if (value->IsTrue(isolate())) {
     return TrueConstant();
-  } else if (value->IsFalse()) {
+  } else if (value->IsFalse(isolate())) {
     return FalseConstant();
-  } else if (value->IsNull()) {
+  } else if (value->IsNull(isolate())) {
     return NullConstant();
-  } else if (value->IsTheHole()) {
+  } else if (value->IsTheHole(isolate())) {
     return TheHoleConstant();
   } else {
     return HeapConstant(Handle<HeapObject>::cast(value));
@@ -139,6 +165,30 @@
   return *loc;
 }
 
+Node* JSGraph::RelocatableInt32Constant(int32_t value, RelocInfo::Mode rmode) {
+  Node** loc = cache_.FindRelocatableInt32Constant(
+      value, static_cast<RelocInfoMode>(rmode));
+  if (*loc == nullptr) {
+    *loc = graph()->NewNode(common()->RelocatableInt32Constant(value, rmode));
+  }
+  return *loc;
+}
+
+Node* JSGraph::RelocatableInt64Constant(int64_t value, RelocInfo::Mode rmode) {
+  Node** loc = cache_.FindRelocatableInt64Constant(
+      value, static_cast<RelocInfoMode>(rmode));
+  if (*loc == nullptr) {
+    *loc = graph()->NewNode(common()->RelocatableInt64Constant(value, rmode));
+  }
+  return *loc;
+}
+
+Node* JSGraph::RelocatableIntPtrConstant(intptr_t value,
+                                         RelocInfo::Mode rmode) {
+  return kPointerSize == 8
+             ? RelocatableInt64Constant(value, rmode)
+             : RelocatableInt32Constant(static_cast<int>(value), rmode);
+}
 
 Node* JSGraph::NumberConstant(double value) {
   Node** loc = cache_.FindNumberConstant(value);
@@ -180,22 +230,10 @@
   return ExternalConstant(ExternalReference(function_id, isolate()));
 }
 
-
-Node* JSGraph::EmptyFrameState() {
-  Node* empty_frame_state = cached_nodes_[kEmptyFrameState];
-  if (!empty_frame_state || empty_frame_state->IsDead()) {
-    Node* state_values = graph()->NewNode(common()->StateValues(0));
-    empty_frame_state = graph()->NewNode(
-        common()->FrameState(BailoutId::None(),
-                             OutputFrameStateCombine::Ignore(), nullptr),
-        state_values, state_values, state_values, NoContextConstant(),
-        UndefinedConstant(), graph()->start());
-    cached_nodes_[kEmptyFrameState] = empty_frame_state;
-  }
-  return empty_frame_state;
+Node* JSGraph::EmptyStateValues() {
+  return CACHED(kEmptyStateValues, graph()->NewNode(common()->StateValues(0)));
 }
 
-
 Node* JSGraph::Dead() {
   return CACHED(kDead, graph()->NewNode(common()->Dead()));
 }
diff --git a/src/compiler/js-graph.h b/src/compiler/js-graph.h
index 06e8030..fe5545a 100644
--- a/src/compiler/js-graph.h
+++ b/src/compiler/js-graph.h
@@ -39,9 +39,15 @@
   }
 
   // Canonicalized global constants.
+  Node* AllocateInNewSpaceStubConstant();
+  Node* AllocateInOldSpaceStubConstant();
+  Node* ToNumberBuiltinConstant();
   Node* CEntryStubConstant(int result_size);
   Node* EmptyFixedArrayConstant();
+  Node* EmptyLiteralsArrayConstant();
+  Node* HeapNumberMapConstant();
   Node* OptimizedOutConstant();
+  Node* StaleRegisterConstant();
   Node* UndefinedConstant();
   Node* TheHoleConstant();
   Node* TrueConstant();
@@ -96,6 +102,10 @@
     return IntPtrConstant(bit_cast<intptr_t>(value));
   }
 
+  Node* RelocatableInt32Constant(int32_t value, RelocInfo::Mode rmode);
+  Node* RelocatableInt64Constant(int64_t value, RelocInfo::Mode rmode);
+  Node* RelocatableIntPtrConstant(intptr_t value, RelocInfo::Mode rmode);
+
   // Creates a Float32Constant node, usually canonicalized.
   Node* Float32Constant(float value);
 
@@ -115,9 +125,9 @@
   // stubs and runtime functions that do not require a context.
   Node* NoContextConstant() { return ZeroConstant(); }
 
-  // Creates an empty frame states for cases where we know that a function
-  // cannot deopt.
-  Node* EmptyFrameState();
+  // Creates an empty StateValues node, used when we don't have any concrete
+  // values for a certain part of the frame state.
+  Node* EmptyStateValues();
 
   // Create a control node that serves as dependency for dead nodes.
   Node* Dead();
@@ -135,9 +145,15 @@
 
  private:
   enum CachedNode {
+    kAllocateInNewSpaceStubConstant,
+    kAllocateInOldSpaceStubConstant,
+    kToNumberBuiltinConstant,
     kCEntryStubConstant,
     kEmptyFixedArrayConstant,
+    kEmptyLiteralsArrayConstant,
+    kHeapNumberMapConstant,
     kOptimizedOutConstant,
+    kStaleRegisterConstant,
     kUndefinedConstant,
     kTheHoleConstant,
     kTrueConstant,
@@ -146,7 +162,7 @@
     kZeroConstant,
     kOneConstant,
     kNaNConstant,
-    kEmptyFrameState,
+    kEmptyStateValues,
     kDead,
     kNumCachedNodes  // Must remain last.
   };
diff --git a/src/compiler/js-inlining-heuristic.cc b/src/compiler/js-inlining-heuristic.cc
index 0e0508b..0118b92 100644
--- a/src/compiler/js-inlining-heuristic.cc
+++ b/src/compiler/js-inlining-heuristic.cc
@@ -75,13 +75,24 @@
 
   // Gather feedback on how often this call site has been hit before.
   int calls = -1;  // Same default as CallICNexus::ExtractCallCount.
-  // TODO(turbofan): We also want call counts for constructor calls.
   if (node->opcode() == IrOpcode::kJSCallFunction) {
     CallFunctionParameters p = CallFunctionParametersOf(node->op());
     if (p.feedback().IsValid()) {
       CallICNexus nexus(p.feedback().vector(), p.feedback().slot());
       calls = nexus.ExtractCallCount();
     }
+  } else {
+    DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode());
+    CallConstructParameters p = CallConstructParametersOf(node->op());
+    if (p.feedback().IsValid()) {
+      int const extra_index =
+          p.feedback().vector()->GetIndex(p.feedback().slot()) + 1;
+      Handle<Object> feedback_extra(p.feedback().vector()->get(extra_index),
+                                    function->GetIsolate());
+      if (feedback_extra->IsSmi()) {
+        calls = Handle<Smi>::cast(feedback_extra)->value();
+      }
+    }
   }
 
   // ---------------------------------------------------------------------------
diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc
index e3254bd..0664105 100644
--- a/src/compiler/js-inlining.cc
+++ b/src/compiler/js-inlining.cc
@@ -4,18 +4,19 @@
 
 #include "src/compiler/js-inlining.h"
 
-#include "src/ast/ast.h"
 #include "src/ast/ast-numbering.h"
+#include "src/ast/ast.h"
 #include "src/ast/scopes.h"
 #include "src/compiler.h"
-#include "src/compiler/all-nodes.h"
 #include "src/compiler/ast-graph-builder.h"
+#include "src/compiler/ast-loop-assignment-analyzer.h"
 #include "src/compiler/common-operator.h"
 #include "src/compiler/graph-reducer.h"
 #include "src/compiler/js-operator.h"
 #include "src/compiler/node-matchers.h"
 #include "src/compiler/node-properties.h"
 #include "src/compiler/operator-properties.h"
+#include "src/compiler/type-hint-analyzer.h"
 #include "src/isolate-inl.h"
 #include "src/parsing/parser.h"
 #include "src/parsing/rewriter.h"
@@ -54,12 +55,8 @@
     return call_->InputAt(formal_arguments() + 1);
   }
 
-  Node* frame_state_before() {
-    return NodeProperties::GetFrameStateInput(call_, 1);
-  }
-
-  Node* frame_state_after() {
-    // Both, {JSCallFunction} and {JSCallConstruct}, have frame state after.
+  Node* frame_state() {
+    // Both, {JSCallFunction} and {JSCallConstruct}, have frame state.
     return NodeProperties::GetFrameStateInput(call_, 0);
   }
 
@@ -75,63 +72,6 @@
 };
 
 
-class CopyVisitor {
- public:
-  CopyVisitor(Graph* source_graph, Graph* target_graph, Zone* temp_zone)
-      : sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, "Sentinel", 0, 0,
-                     0, 0, 0, 0),
-        sentinel_(target_graph->NewNode(&sentinel_op_)),
-        copies_(source_graph->NodeCount(), sentinel_, temp_zone),
-        source_graph_(source_graph),
-        target_graph_(target_graph),
-        temp_zone_(temp_zone) {}
-
-  Node* GetCopy(Node* orig) { return copies_[orig->id()]; }
-
-  void CopyGraph() {
-    NodeVector inputs(temp_zone_);
-    // TODO(bmeurer): AllNodes should be turned into something like
-    // Graph::CollectNodesReachableFromEnd() and the gray set stuff should be
-    // removed since it's only needed by the visualizer.
-    AllNodes all(temp_zone_, source_graph_);
-    // Copy all nodes reachable from end.
-    for (Node* orig : all.live) {
-      Node* copy = GetCopy(orig);
-      if (copy != sentinel_) {
-        // Mapping already exists.
-        continue;
-      }
-      // Copy the node.
-      inputs.clear();
-      for (Node* input : orig->inputs()) inputs.push_back(copies_[input->id()]);
-      copy = target_graph_->NewNode(orig->op(), orig->InputCount(),
-                                    inputs.empty() ? nullptr : &inputs[0]);
-      copies_[orig->id()] = copy;
-    }
-    // For missing inputs.
-    for (Node* orig : all.live) {
-      Node* copy = copies_[orig->id()];
-      for (int i = 0; i < copy->InputCount(); ++i) {
-        Node* input = copy->InputAt(i);
-        if (input == sentinel_) {
-          copy->ReplaceInput(i, GetCopy(orig->InputAt(i)));
-        }
-      }
-    }
-  }
-
-  const NodeVector& copies() const { return copies_; }
-
- private:
-  Operator const sentinel_op_;
-  Node* const sentinel_;
-  NodeVector copies_;
-  Graph* const source_graph_;
-  Graph* const target_graph_;
-  Zone* const temp_zone_;
-};
-
-
 Reduction JSInliner::InlineCall(Node* call, Node* new_target, Node* context,
                                 Node* frame_state, Node* start, Node* end) {
   // The scheduler is smart enough to place our code; we just ensure {control}
@@ -390,7 +330,7 @@
   // TODO(turbofan): TranslatedState::GetAdaptedArguments() currently relies on
   // not inlining recursive functions. We might want to relax that at some
   // point.
-  for (Node* frame_state = call.frame_state_after();
+  for (Node* frame_state = call.frame_state();
        frame_state->opcode() == IrOpcode::kFrameState;
        frame_state = frame_state->InputAt(kFrameStateOuterStateInput)) {
     FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state);
@@ -414,8 +354,9 @@
 
   Zone zone(info_->isolate()->allocator());
   ParseInfo parse_info(&zone, function);
-  CompilationInfo info(&parse_info);
+  CompilationInfo info(&parse_info, function);
   if (info_->is_deoptimization_enabled()) info.MarkAsDeoptimizationEnabled();
+  if (info_->is_type_feedback_enabled()) info.MarkAsTypeFeedbackEnabled();
 
   if (!Compiler::ParseAndAnalyze(info.parse_info())) {
     TRACE("Not inlining %s into %s because parsing failed\n",
@@ -433,6 +374,7 @@
           info_->shared_info()->DebugName()->ToCString().get());
     return NoChange();
   }
+
   // Remember that we inlined this function. This needs to be called right
   // after we ensure deoptimization support so that the code flusher
   // does not remove the code with the deoptimization support.
@@ -446,59 +388,75 @@
         shared_info->DebugName()->ToCString().get(),
         info_->shared_info()->DebugName()->ToCString().get());
 
-  // TODO(mstarzinger): We could use the temporary zone for the graph because
-  // nodes are copied. This however leads to Zone-Types being allocated in the
-  // wrong zone and makes the engine explode at high speeds. Explosion bad!
-  Graph graph(jsgraph_->zone());
-  JSGraph jsgraph(info.isolate(), &graph, jsgraph_->common(),
-                  jsgraph_->javascript(), jsgraph_->simplified(),
-                  jsgraph_->machine());
-  AstGraphBuilder graph_builder(local_zone_, &info, &jsgraph);
-  graph_builder.CreateGraph(false);
+  // If function was lazily compiled, it's literals array may not yet be set up.
+  JSFunction::EnsureLiterals(function);
 
-  CopyVisitor visitor(&graph, jsgraph_->graph(), &zone);
-  visitor.CopyGraph();
+  // Create the subgraph for the inlinee.
+  Node* start;
+  Node* end;
+  {
+    // Run the loop assignment analyzer on the inlinee.
+    AstLoopAssignmentAnalyzer loop_assignment_analyzer(&zone, &info);
+    LoopAssignmentAnalysis* loop_assignment =
+        loop_assignment_analyzer.Analyze();
 
-  Node* start = visitor.GetCopy(graph.start());
-  Node* end = visitor.GetCopy(graph.end());
-  Node* frame_state = call.frame_state_after();
-  Node* new_target = jsgraph_->UndefinedConstant();
+    // Run the type hint analyzer on the inlinee.
+    TypeHintAnalyzer type_hint_analyzer(&zone);
+    TypeHintAnalysis* type_hint_analysis =
+        type_hint_analyzer.Analyze(handle(shared_info->code(), info.isolate()));
 
-  // Insert nodes around the call that model the behavior required for a
-  // constructor dispatch (allocate implicit receiver and check return value).
-  // This models the behavior usually accomplished by our {JSConstructStub}.
-  // Note that the context has to be the callers context (input to call node).
-  Node* receiver = jsgraph_->UndefinedConstant();  // Implicit receiver.
-  if (node->opcode() == IrOpcode::kJSCallConstruct &&
-      NeedsImplicitReceiver(shared_info)) {
-    Node* effect = NodeProperties::GetEffectInput(node);
-    Node* context = NodeProperties::GetContextInput(node);
-    Node* create = jsgraph_->graph()->NewNode(
-        jsgraph_->javascript()->Create(), call.target(), call.new_target(),
-        context, call.frame_state_before(), effect);
-    NodeProperties::ReplaceEffectInput(node, create);
-    // Insert a check of the return value to determine whether the return value
-    // or the implicit receiver should be selected as a result of the call.
-    Node* check = jsgraph_->graph()->NewNode(
-        jsgraph_->javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1),
-        node, context, node, start);
-    Node* select = jsgraph_->graph()->NewNode(
-        jsgraph_->common()->Select(MachineRepresentation::kTagged), check, node,
-        create);
-    NodeProperties::ReplaceUses(node, select, check, node, node);
-    NodeProperties::ReplaceValueInput(select, node, 1);
-    NodeProperties::ReplaceValueInput(check, node, 0);
-    NodeProperties::ReplaceEffectInput(check, node);
-    receiver = create;  // The implicit receiver.
+    // Run the AstGraphBuilder to create the subgraph.
+    Graph::SubgraphScope scope(graph());
+    AstGraphBuilder graph_builder(&zone, &info, jsgraph(), loop_assignment,
+                                  type_hint_analysis);
+    graph_builder.CreateGraph(false);
+
+    // Extract the inlinee start/end nodes.
+    start = graph()->start();
+    end = graph()->end();
   }
 
-  // Swizzle the inputs of the {JSCallConstruct} node to look like inputs to a
-  // normal {JSCallFunction} node so that the rest of the inlining machinery
-  // behaves as if we were dealing with a regular function invocation.
+  Node* frame_state = call.frame_state();
+  Node* new_target = jsgraph_->UndefinedConstant();
+
+  // Inline {JSCallConstruct} requires some additional magic.
   if (node->opcode() == IrOpcode::kJSCallConstruct) {
+    // Insert nodes around the call that model the behavior required for a
+    // constructor dispatch (allocate implicit receiver and check return value).
+    // This models the behavior usually accomplished by our {JSConstructStub}.
+    // Note that the context has to be the callers context (input to call node).
+    Node* receiver = jsgraph_->UndefinedConstant();  // Implicit receiver.
+    if (NeedsImplicitReceiver(shared_info)) {
+      Node* frame_state_before = NodeProperties::FindFrameStateBefore(node);
+      Node* effect = NodeProperties::GetEffectInput(node);
+      Node* context = NodeProperties::GetContextInput(node);
+      Node* create = jsgraph_->graph()->NewNode(
+          jsgraph_->javascript()->Create(), call.target(), call.new_target(),
+          context, frame_state_before, effect);
+      NodeProperties::ReplaceEffectInput(node, create);
+      // Insert a check of the return value to determine whether the return
+      // value
+      // or the implicit receiver should be selected as a result of the call.
+      Node* check = jsgraph_->graph()->NewNode(
+          jsgraph_->javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1),
+          node, context, node, start);
+      Node* select = jsgraph_->graph()->NewNode(
+          jsgraph_->common()->Select(MachineRepresentation::kTagged), check,
+          node, create);
+      NodeProperties::ReplaceUses(node, select, check, node, node);
+      NodeProperties::ReplaceValueInput(select, node, 1);
+      NodeProperties::ReplaceValueInput(check, node, 0);
+      NodeProperties::ReplaceEffectInput(check, node);
+      receiver = create;  // The implicit receiver.
+    }
+
+    // Swizzle the inputs of the {JSCallConstruct} node to look like inputs to a
+    // normal {JSCallFunction} node so that the rest of the inlining machinery
+    // behaves as if we were dealing with a regular function invocation.
     new_target = call.new_target();  // Retrieve new target value input.
     node->RemoveInput(call.formal_arguments() + 1);  // Drop new target.
     node->InsertInput(jsgraph_->graph()->zone(), 1, receiver);
+
     // Insert a construct stub frame into the chain of frame states. This will
     // reconstruct the proper frame when deoptimizing within the constructor.
     frame_state = CreateArtificialFrameState(
@@ -519,12 +477,13 @@
   // in that frame state tho, as the conversion of the receiver can be repeated
   // any number of times, it's not observable.
   if (node->opcode() == IrOpcode::kJSCallFunction &&
-      is_sloppy(info.language_mode()) && !shared_info->native()) {
+      is_sloppy(parse_info.language_mode()) && !shared_info->native()) {
     const CallFunctionParameters& p = CallFunctionParametersOf(node->op());
+    Node* frame_state_before = NodeProperties::FindFrameStateBefore(node);
     Node* effect = NodeProperties::GetEffectInput(node);
     Node* convert = jsgraph_->graph()->NewNode(
         jsgraph_->javascript()->ConvertReceiver(p.convert_mode()),
-        call.receiver(), context, call.frame_state_before(), effect, start);
+        call.receiver(), context, frame_state_before, effect, start);
     NodeProperties::ReplaceValueInput(node, convert, 1);
     NodeProperties::ReplaceEffectInput(node, convert);
   }
@@ -558,6 +517,8 @@
   return InlineCall(node, new_target, context, frame_state, start, end);
 }
 
+Graph* JSInliner::graph() const { return jsgraph()->graph(); }
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/src/compiler/js-inlining.h b/src/compiler/js-inlining.h
index d0ab7c0..88cbf89 100644
--- a/src/compiler/js-inlining.h
+++ b/src/compiler/js-inlining.h
@@ -36,9 +36,12 @@
   Reduction ReduceJSCall(Node* node, Handle<JSFunction> function);
 
  private:
-  Zone* local_zone_;
+  Graph* graph() const;
+  JSGraph* jsgraph() const { return jsgraph_; }
+
+  Zone* const local_zone_;
   CompilationInfo* info_;
-  JSGraph* jsgraph_;
+  JSGraph* const jsgraph_;
 
   Node* CreateArtificialFrameState(Node* node, Node* outer_frame_state,
                                    int parameter_count,
diff --git a/src/compiler/js-intrinsic-lowering.cc b/src/compiler/js-intrinsic-lowering.cc
index 034ee6f..8d24013 100644
--- a/src/compiler/js-intrinsic-lowering.cc
+++ b/src/compiler/js-intrinsic-lowering.cc
@@ -30,8 +30,6 @@
       Runtime::FunctionForId(CallRuntimeParametersOf(node->op()).id());
   if (f->intrinsic_type != Runtime::IntrinsicType::INLINE) return NoChange();
   switch (f->function_id) {
-    case Runtime::kInlineConstructDouble:
-      return ReduceConstructDouble(node);
     case Runtime::kInlineCreateIterResultObject:
       return ReduceCreateIterResultObject(node);
     case Runtime::kInlineDeoptimizeNow:
@@ -40,6 +38,12 @@
       return ReduceDoubleHi(node);
     case Runtime::kInlineDoubleLo:
       return ReduceDoubleLo(node);
+    case Runtime::kInlineGeneratorClose:
+      return ReduceGeneratorClose(node);
+    case Runtime::kInlineGeneratorGetInputOrDebugPos:
+      return ReduceGeneratorGetInputOrDebugPos(node);
+    case Runtime::kInlineGeneratorGetResumeMode:
+      return ReduceGeneratorGetResumeMode(node);
     case Runtime::kInlineIsArray:
       return ReduceIsInstanceType(node, JS_ARRAY_TYPE);
     case Runtime::kInlineIsTypedArray:
@@ -86,8 +90,6 @@
       return ReduceNewObject(node);
     case Runtime::kInlineGetSuperConstructor:
       return ReduceGetSuperConstructor(node);
-    case Runtime::kInlineGetOrdinaryHasInstance:
-      return ReduceGetOrdinaryHasInstance(node);
     default:
       break;
   }
@@ -105,19 +107,6 @@
 }
 
 
-Reduction JSIntrinsicLowering::ReduceConstructDouble(Node* node) {
-  Node* high = NodeProperties::GetValueInput(node, 0);
-  Node* low = NodeProperties::GetValueInput(node, 1);
-  Node* value =
-      graph()->NewNode(machine()->Float64InsertHighWord32(),
-                       graph()->NewNode(machine()->Float64InsertLowWord32(),
-                                        jsgraph()->Constant(0), low),
-                       high);
-  ReplaceWithValue(node, value);
-  return Replace(value);
-}
-
-
 Reduction JSIntrinsicLowering::ReduceDeoptimizeNow(Node* node) {
   if (mode() != kDeoptimizationEnabled) return NoChange();
   Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0);
@@ -139,7 +128,7 @@
 
 Reduction JSIntrinsicLowering::ReduceDoubleHi(Node* node) {
   // Tell the compiler to assume number input.
-  Node* renamed = graph()->NewNode(common()->Guard(Type::Number()),
+  Node* renamed = graph()->NewNode(simplified()->TypeGuard(Type::Number()),
                                    node->InputAt(0), graph()->start());
   node->ReplaceInput(0, renamed);
   return Change(node, machine()->Float64ExtractHighWord32());
@@ -148,12 +137,45 @@
 
 Reduction JSIntrinsicLowering::ReduceDoubleLo(Node* node) {
   // Tell the compiler to assume number input.
-  Node* renamed = graph()->NewNode(common()->Guard(Type::Number()),
+  Node* renamed = graph()->NewNode(simplified()->TypeGuard(Type::Number()),
                                    node->InputAt(0), graph()->start());
   node->ReplaceInput(0, renamed);
   return Change(node, machine()->Float64ExtractLowWord32());
 }
 
+Reduction JSIntrinsicLowering::ReduceGeneratorClose(Node* node) {
+  Node* const generator = NodeProperties::GetValueInput(node, 0);
+  Node* const effect = NodeProperties::GetEffectInput(node);
+  Node* const control = NodeProperties::GetControlInput(node);
+  Node* const closed = jsgraph()->Constant(JSGeneratorObject::kGeneratorClosed);
+  Node* const undefined = jsgraph()->UndefinedConstant();
+  Operator const* const op = simplified()->StoreField(
+      AccessBuilder::ForJSGeneratorObjectContinuation());
+
+  ReplaceWithValue(node, undefined, node);
+  NodeProperties::RemoveType(node);
+  return Change(node, op, generator, closed, effect, control);
+}
+
+Reduction JSIntrinsicLowering::ReduceGeneratorGetInputOrDebugPos(Node* node) {
+  Node* const generator = NodeProperties::GetValueInput(node, 0);
+  Node* const effect = NodeProperties::GetEffectInput(node);
+  Node* const control = NodeProperties::GetControlInput(node);
+  Operator const* const op = simplified()->LoadField(
+      AccessBuilder::ForJSGeneratorObjectInputOrDebugPos());
+
+  return Change(node, op, generator, effect, control);
+}
+
+Reduction JSIntrinsicLowering::ReduceGeneratorGetResumeMode(Node* node) {
+  Node* const generator = NodeProperties::GetValueInput(node, 0);
+  Node* const effect = NodeProperties::GetEffectInput(node);
+  Node* const control = NodeProperties::GetControlInput(node);
+  Operator const* const op =
+      simplified()->LoadField(AccessBuilder::ForJSGeneratorObjectResumeMode());
+
+  return Change(node, op, generator, effect, control);
+}
 
 Reduction JSIntrinsicLowering::ReduceIsInstanceType(
     Node* node, InstanceType instance_type) {
@@ -397,15 +419,7 @@
 }
 
 Reduction JSIntrinsicLowering::ReduceNewObject(Node* node) {
-  Node* constructor = NodeProperties::GetValueInput(node, 0);
-  Node* new_target = NodeProperties::GetValueInput(node, 1);
-  Node* context = NodeProperties::GetContextInput(node);
-  Node* effect = NodeProperties::GetEffectInput(node);
-  Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
-  Node* value = graph()->NewNode(javascript()->Create(), constructor,
-                                 new_target, context, frame_state, effect);
-  ReplaceWithValue(node, value, value);
-  return Replace(value);
+  return Change(node, CodeFactory::FastNewObject(isolate()), 0);
 }
 
 Reduction JSIntrinsicLowering::ReduceGetSuperConstructor(Node* node) {
@@ -419,17 +433,6 @@
                 active_function_map, effect, control);
 }
 
-Reduction JSIntrinsicLowering::ReduceGetOrdinaryHasInstance(Node* node) {
-  Node* effect = NodeProperties::GetEffectInput(node);
-  Node* context = NodeProperties::GetContextInput(node);
-  Node* native_context = effect = graph()->NewNode(
-      javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
-      context, context, effect);
-  return Change(node, javascript()->LoadContext(
-                          0, Context::ORDINARY_HAS_INSTANCE_INDEX, true),
-                native_context, context, effect);
-}
-
 Reduction JSIntrinsicLowering::Change(Node* node, const Operator* op, Node* a,
                                       Node* b) {
   RelaxControls(node);
@@ -466,12 +469,6 @@
 }
 
 
-Reduction JSIntrinsicLowering::ChangeToUndefined(Node* node, Node* effect) {
-  ReplaceWithValue(node, jsgraph()->UndefinedConstant(), effect);
-  return Changed(node);
-}
-
-
 Reduction JSIntrinsicLowering::Change(Node* node, Callable const& callable,
                                       int stack_parameter_count) {
   CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
diff --git a/src/compiler/js-intrinsic-lowering.h b/src/compiler/js-intrinsic-lowering.h
index a43ed01..f4b8695 100644
--- a/src/compiler/js-intrinsic-lowering.h
+++ b/src/compiler/js-intrinsic-lowering.h
@@ -37,11 +37,13 @@
   Reduction Reduce(Node* node) final;
 
  private:
-  Reduction ReduceConstructDouble(Node* node);
   Reduction ReduceCreateIterResultObject(Node* node);
   Reduction ReduceDeoptimizeNow(Node* node);
   Reduction ReduceDoubleHi(Node* node);
   Reduction ReduceDoubleLo(Node* node);
+  Reduction ReduceGeneratorClose(Node* node);
+  Reduction ReduceGeneratorGetInputOrDebugPos(Node* node);
+  Reduction ReduceGeneratorGetResumeMode(Node* node);
   Reduction ReduceIsInstanceType(Node* node, InstanceType instance_type);
   Reduction ReduceIsJSReceiver(Node* node);
   Reduction ReduceIsSmi(Node* node);
@@ -63,14 +65,12 @@
   Reduction ReduceCall(Node* node);
   Reduction ReduceNewObject(Node* node);
   Reduction ReduceGetSuperConstructor(Node* node);
-  Reduction ReduceGetOrdinaryHasInstance(Node* node);
 
   Reduction Change(Node* node, const Operator* op);
   Reduction Change(Node* node, const Operator* op, Node* a, Node* b);
   Reduction Change(Node* node, const Operator* op, Node* a, Node* b, Node* c);
   Reduction Change(Node* node, const Operator* op, Node* a, Node* b, Node* c,
                    Node* d);
-  Reduction ChangeToUndefined(Node* node, Node* effect = nullptr);
   Reduction Change(Node* node, Callable const& callable,
                    int stack_parameter_count);
 
diff --git a/src/compiler/js-native-context-specialization.cc b/src/compiler/js-native-context-specialization.cc
index d1353d2..81d4cd0 100644
--- a/src/compiler/js-native-context-specialization.cc
+++ b/src/compiler/js-native-context-specialization.cc
@@ -15,7 +15,6 @@
 #include "src/compiler/node-matchers.h"
 #include "src/field-index-inl.h"
 #include "src/isolate-inl.h"
-#include "src/objects-inl.h"  // TODO(mstarzinger): Temporary cycle breaker!
 #include "src/type-cache.h"
 #include "src/type-feedback-vector.h"
 
@@ -79,9 +78,9 @@
          node->opcode() == IrOpcode::kJSLoadProperty ||
          node->opcode() == IrOpcode::kJSStoreProperty);
   Node* receiver = NodeProperties::GetValueInput(node, 0);
-  Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
   Node* effect = NodeProperties::GetEffectInput(node);
   Node* control = NodeProperties::GetControlInput(node);
+  Node* frame_state = NodeProperties::FindFrameStateBefore(node);
 
   // Not much we can do if deoptimization support is disabled.
   if (!(flags() & kDeoptimizationEnabled)) return NoChange();
@@ -112,8 +111,8 @@
   if (index != nullptr) {
     Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Name()),
                                    index, jsgraph()->HeapConstant(name));
-    control = graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
-                               effect, control);
+    control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check,
+                                        frame_state, effect, control);
   }
 
   // Check if {receiver} may be a number.
@@ -126,17 +125,17 @@
   }
 
   // Ensure that {receiver} is a heap object.
-  Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
   Node* receiverissmi_control = nullptr;
   Node* receiverissmi_effect = effect;
   if (receiverissmi_possible) {
+    Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
     Node* branch = graph()->NewNode(common()->Branch(), check, control);
     control = graph()->NewNode(common()->IfFalse(), branch);
     receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch);
     receiverissmi_effect = effect;
   } else {
-    control = graph()->NewNode(common()->DeoptimizeIf(), check, frame_state,
-                               effect, control);
+    receiver = effect = graph()->NewNode(simplified()->CheckTaggedPointer(),
+                                         receiver, effect, control);
   }
 
   // Load the {receiver} map. The resulting effect is the dominating effect for
@@ -157,15 +156,9 @@
     // Perform map check on {receiver}.
     Type* receiver_type = access_info.receiver_type();
     if (receiver_type->Is(Type::String())) {
-      // Emit an instance type check for strings.
-      Node* receiver_instance_type = this_effect = graph()->NewNode(
-          simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
-          receiver_map, this_effect, fallthrough_control);
-      Node* check =
-          graph()->NewNode(machine()->Uint32LessThan(), receiver_instance_type,
-                           jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE));
+      Node* check = graph()->NewNode(simplified()->ObjectIsString(), receiver);
       if (j == access_infos.size() - 1) {
-        this_control =
+        this_control = this_effect =
             graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
                              this_effect, fallthrough_control);
         fallthrough_control = nullptr;
@@ -188,10 +181,11 @@
             graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()),
                              receiver_map, jsgraph()->Constant(map));
         if (--num_classes == 0 && j == access_infos.size() - 1) {
-          this_controls.push_back(
+          Node* deoptimize =
               graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
-                               this_effect, fallthrough_control));
-          this_effects.push_back(this_effect);
+                               this_effect, fallthrough_control);
+          this_controls.push_back(deoptimize);
+          this_effects.push_back(deoptimize);
           fallthrough_control = nullptr;
         } else {
           Node* branch =
@@ -243,38 +237,14 @@
       if (access_mode == AccessMode::kStore) {
         Node* check = graph()->NewNode(
             simplified()->ReferenceEqual(Type::Tagged()), value, this_value);
-        this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
-                                        frame_state, this_effect, this_control);
+        this_control = this_effect =
+            graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
+                             this_effect, this_control);
       }
     } else {
       DCHECK(access_info.IsDataField());
       FieldIndex const field_index = access_info.field_index();
-      FieldCheck const field_check = access_info.field_check();
       Type* const field_type = access_info.field_type();
-      switch (field_check) {
-        case FieldCheck::kNone:
-          break;
-        case FieldCheck::kJSArrayBufferViewBufferNotNeutered: {
-          Node* this_buffer = this_effect =
-              graph()->NewNode(simplified()->LoadField(
-                                   AccessBuilder::ForJSArrayBufferViewBuffer()),
-                               this_receiver, this_effect, this_control);
-          Node* this_buffer_bit_field = this_effect =
-              graph()->NewNode(simplified()->LoadField(
-                                   AccessBuilder::ForJSArrayBufferBitField()),
-                               this_buffer, this_effect, this_control);
-          Node* check = graph()->NewNode(
-              machine()->Word32Equal(),
-              graph()->NewNode(machine()->Word32And(), this_buffer_bit_field,
-                               jsgraph()->Int32Constant(
-                                   1 << JSArrayBuffer::WasNeutered::kShift)),
-              jsgraph()->Int32Constant(0));
-          this_control =
-              graph()->NewNode(common()->DeoptimizeIf(), check, frame_state,
-                               this_effect, this_control);
-          break;
-        }
-      }
       if (access_mode == AccessMode::kLoad &&
           access_info.holder().ToHandle(&holder)) {
         this_receiver = jsgraph()->Constant(holder);
@@ -285,10 +255,16 @@
             simplified()->LoadField(AccessBuilder::ForJSObjectProperties()),
             this_storage, this_effect, this_control);
       }
-      FieldAccess field_access = {kTaggedBase, field_index.offset(), name,
-                                  field_type, MachineType::AnyTagged()};
+      FieldAccess field_access = {
+          kTaggedBase, field_index.offset(),     name,
+          field_type,  MachineType::AnyTagged(), kFullWriteBarrier};
       if (access_mode == AccessMode::kLoad) {
         if (field_type->Is(Type::UntaggedFloat64())) {
+          // TODO(turbofan): We remove the representation axis from the type to
+          // avoid uninhabited representation types. This is a workaround until
+          // the {PropertyAccessInfo} is using {MachineRepresentation} instead.
+          field_access.type = Type::Union(
+              field_type, Type::Representation(Type::Number(), zone()), zone());
           if (!field_index.is_inobject() || field_index.is_hidden_field() ||
               !FLAG_unbox_double_fields) {
             this_storage = this_effect =
@@ -305,31 +281,39 @@
       } else {
         DCHECK_EQ(AccessMode::kStore, access_mode);
         if (field_type->Is(Type::UntaggedFloat64())) {
+          // TODO(turbofan): We remove the representation axis from the type to
+          // avoid uninhabited representation types. This is a workaround until
+          // the {PropertyAccessInfo} is using {MachineRepresentation} instead.
+          field_access.type = Type::Union(
+              field_type, Type::Representation(Type::Number(), zone()), zone());
           Node* check =
               graph()->NewNode(simplified()->ObjectIsNumber(), this_value);
-          this_control =
+          this_control = this_effect =
               graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
                                this_effect, this_control);
-          this_value = graph()->NewNode(common()->Guard(Type::Number()),
+          this_value = graph()->NewNode(simplified()->TypeGuard(Type::Number()),
                                         this_value, this_control);
 
           if (!field_index.is_inobject() || field_index.is_hidden_field() ||
               !FLAG_unbox_double_fields) {
             if (access_info.HasTransitionMap()) {
               // Allocate a MutableHeapNumber for the new property.
-              Callable callable =
-                  CodeFactory::AllocateMutableHeapNumber(isolate());
-              CallDescriptor* desc = Linkage::GetStubCallDescriptor(
-                  isolate(), jsgraph()->zone(), callable.descriptor(), 0,
-                  CallDescriptor::kNoFlags, Operator::kNoThrow);
-              Node* this_box = this_effect = graph()->NewNode(
-                  common()->Call(desc),
-                  jsgraph()->HeapConstant(callable.code()),
-                  jsgraph()->NoContextConstant(), this_effect, this_control);
+              this_effect = graph()->NewNode(
+                  common()->BeginRegion(RegionObservability::kNotObservable),
+                  this_effect);
+              Node* this_box = this_effect =
+                  graph()->NewNode(simplified()->Allocate(NOT_TENURED),
+                                   jsgraph()->Constant(HeapNumber::kSize),
+                                   this_effect, this_control);
+              this_effect = graph()->NewNode(
+                  simplified()->StoreField(AccessBuilder::ForMap()), this_box,
+                  jsgraph()->HeapConstant(factory()->mutable_heap_number_map()),
+                  this_effect, this_control);
               this_effect = graph()->NewNode(
                   simplified()->StoreField(AccessBuilder::ForHeapNumberValue()),
                   this_box, this_value, this_effect, this_control);
-              this_value = this_box;
+              this_value = this_effect = graph()->NewNode(
+                  common()->FinishRegion(), this_box, this_effect);
 
               field_access.type = Type::TaggedPointer();
             } else {
@@ -346,18 +330,12 @@
             field_access.machine_type = MachineType::Float64();
           }
         } else if (field_type->Is(Type::TaggedSigned())) {
-          Node* check =
-              graph()->NewNode(simplified()->ObjectIsSmi(), this_value);
-          this_control =
-              graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
+          this_value = this_effect =
+              graph()->NewNode(simplified()->CheckTaggedSigned(), this_value,
                                this_effect, this_control);
-          this_value = graph()->NewNode(common()->Guard(type_cache_.kSmi),
-                                        this_value, this_control);
         } else if (field_type->Is(Type::TaggedPointer())) {
-          Node* check =
-              graph()->NewNode(simplified()->ObjectIsSmi(), this_value);
-          this_control =
-              graph()->NewNode(common()->DeoptimizeIf(), check, frame_state,
+          this_value = this_effect =
+              graph()->NewNode(simplified()->CheckTaggedPointer(), this_value,
                                this_effect, this_control);
           if (field_type->NumClasses() == 1) {
             // Emit a map check for the value.
@@ -367,7 +345,7 @@
             Node* check = graph()->NewNode(
                 simplified()->ReferenceEqual(Type::Internal()), this_value_map,
                 jsgraph()->Constant(field_type->Classes().Current()));
-            this_control =
+            this_control = this_effect =
                 graph()->NewNode(common()->DeoptimizeUnless(), check,
                                  frame_state, this_effect, this_control);
           } else {
@@ -378,7 +356,9 @@
         }
         Handle<Map> transition_map;
         if (access_info.transition_map().ToHandle(&transition_map)) {
-          this_effect = graph()->NewNode(common()->BeginRegion(), this_effect);
+          this_effect = graph()->NewNode(
+              common()->BeginRegion(RegionObservability::kObservable),
+              this_effect);
           this_effect = graph()->NewNode(
               simplified()->StoreField(AccessBuilder::ForMap()), this_receiver,
               jsgraph()->Constant(transition_map), this_effect, this_control);
@@ -431,25 +411,29 @@
     AccessMode access_mode, LanguageMode language_mode) {
   DCHECK(node->opcode() == IrOpcode::kJSLoadNamed ||
          node->opcode() == IrOpcode::kJSStoreNamed);
+  Node* const receiver = NodeProperties::GetValueInput(node, 0);
+  Node* const effect = NodeProperties::GetEffectInput(node);
 
   // Check if the {nexus} reports type feedback for the IC.
   if (nexus.IsUninitialized()) {
     if ((flags() & kDeoptimizationEnabled) &&
         (flags() & kBailoutOnUninitialized)) {
-      // TODO(turbofan): Implement all eager bailout points correctly in
-      // the graph builder.
-      Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
-      if (!OpParameter<FrameStateInfo>(frame_state).bailout_id().IsNone()) {
-        return ReduceSoftDeoptimize(node);
-      }
+      return ReduceSoftDeoptimize(node);
     }
     return NoChange();
   }
 
   // Extract receiver maps from the IC using the {nexus}.
   MapHandleList receiver_maps;
-  if (nexus.ExtractMaps(&receiver_maps) == 0) return NoChange();
-  DCHECK_LT(0, receiver_maps.length());
+  if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) {
+    return NoChange();
+  } else if (receiver_maps.length() == 0) {
+    if ((flags() & kDeoptimizationEnabled) &&
+        (flags() & kBailoutOnUninitialized)) {
+      return ReduceSoftDeoptimize(node);
+    }
+    return NoChange();
+  }
 
   // Try to lower the named access based on the {receiver_maps}.
   return ReduceNamedAccess(node, value, receiver_maps, name, access_mode,
@@ -460,8 +444,33 @@
 Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
   DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
   NamedAccess const& p = NamedAccessOf(node->op());
+  Node* const receiver = NodeProperties::GetValueInput(node, 0);
   Node* const value = jsgraph()->Dead();
 
+  // Check if we have a constant receiver.
+  HeapObjectMatcher m(receiver);
+  if (m.HasValue()) {
+    // Optimize "prototype" property of functions.
+    if (m.Value()->IsJSFunction() &&
+        p.name().is_identical_to(factory()->prototype_string())) {
+      Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value());
+      if (function->has_initial_map()) {
+        // We need to add a code dependency on the initial map of the
+        // {function} in order to be notified about changes to the
+        // "prototype" of {function}, so it doesn't make sense to
+        // continue unless deoptimization is enabled.
+        if (flags() & kDeoptimizationEnabled) {
+          Handle<Map> initial_map(function->initial_map(), isolate());
+          dependencies()->AssumeInitialMapCantChange(initial_map);
+          Handle<Object> prototype(initial_map->prototype(), isolate());
+          Node* value = jsgraph()->Constant(prototype);
+          ReplaceWithValue(node, value);
+          return Replace(value);
+        }
+      }
+    }
+  }
+
   // Extract receiver maps from the LOAD_IC using the LoadICNexus.
   if (!p.feedback().IsValid()) return NoChange();
   LoadICNexus nexus(p.feedback().vector(), p.feedback().slot());
@@ -495,9 +504,9 @@
          node->opcode() == IrOpcode::kJSStoreProperty);
   Node* receiver = NodeProperties::GetValueInput(node, 0);
   Node* context = NodeProperties::GetContextInput(node);
-  Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
   Node* effect = NodeProperties::GetEffectInput(node);
   Node* control = NodeProperties::GetControlInput(node);
+  Node* frame_state = NodeProperties::FindFrameStateBefore(node);
 
   // Not much we can do if deoptimization support is disabled.
   if (!(flags() & kDeoptimizationEnabled)) return NoChange();
@@ -528,9 +537,8 @@
   ZoneVector<Node*> controls(zone());
 
   // Ensure that {receiver} is a heap object.
-  Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
-  control = graph()->NewNode(common()->DeoptimizeIf(), check, frame_state,
-                             effect, control);
+  receiver = effect = graph()->NewNode(simplified()->CheckTaggedPointer(),
+                                       receiver, effect, control);
 
   // Load the {receiver} map. The resulting effect is the dominating effect for
   // all (polymorphic) branches.
@@ -570,17 +578,19 @@
           // TODO(turbofan): This is ugly as hell! We should probably introduce
           // macro-ish operators for property access that encapsulate this whole
           // mess.
-          this_controls.push_back(graph()->NewNode(common()->DeoptimizeUnless(),
-                                                   check, frame_state, effect,
-                                                   fallthrough_control));
+          Node* deoptimize =
+              graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
+                               effect, fallthrough_control);
+          this_controls.push_back(deoptimize);
+          this_effects.push_back(deoptimize);
           fallthrough_control = nullptr;
         } else {
           Node* branch =
               graph()->NewNode(common()->Branch(), check, fallthrough_control);
           this_controls.push_back(graph()->NewNode(common()->IfTrue(), branch));
+          this_effects.push_back(effect);
           fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
         }
-        this_effects.push_back(effect);
         if (!map->IsJSArrayMap()) receiver_is_jsarray = false;
       }
 
@@ -597,7 +607,7 @@
             simplified()->ReferenceEqual(Type::Any()), receiver_map,
             jsgraph()->HeapConstant(transition_source));
         if (--num_transitions == 0 && j == access_infos.size() - 1) {
-          transition_control =
+          transition_control = transition_effect =
               graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
                                transition_effect, fallthrough_control);
           fallthrough_control = nullptr;
@@ -620,8 +630,7 @@
           // Instance migration, let the stub deal with the {receiver}.
           TransitionElementsKindStub stub(isolate(),
                                           transition_source->elements_kind(),
-                                          transition_target->elements_kind(),
-                                          transition_source->IsJSArrayMap());
+                                          transition_target->elements_kind());
           CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
               isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 0,
               CallDescriptor::kNeedsFrameState, node->op()->properties());
@@ -630,6 +639,7 @@
               receiver, jsgraph()->HeapConstant(transition_target), context,
               frame_state, transition_effect, transition_control);
         }
+
         this_controls.push_back(transition_control);
         this_effects.push_back(transition_effect);
       }
@@ -648,6 +658,14 @@
             graph()->NewNode(common()->EffectPhi(this_control_count),
                              this_control_count + 1, &this_effects.front());
       }
+
+      // TODO(turbofan): The effect/control linearization will not find a
+      // FrameState after the StoreField or Call that is generated for the
+      // elements kind transition above. This is because those operators
+      // don't have the kNoWrite flag on it, even though they are not
+      // observable by JavaScript.
+      this_effect = graph()->NewNode(common()->Checkpoint(), frame_state,
+                                     this_effect, this_control);
     }
 
     // Certain stores need a prototype chain check because shape changes
@@ -658,28 +676,6 @@
       AssumePrototypesStable(receiver_type, native_context, holder);
     }
 
-    // Check that the {index} is actually a Number.
-    if (!NumberMatcher(this_index).HasValue()) {
-      Node* check =
-          graph()->NewNode(simplified()->ObjectIsNumber(), this_index);
-      this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
-                                      frame_state, this_effect, this_control);
-      this_index = graph()->NewNode(common()->Guard(Type::Number()), this_index,
-                                    this_control);
-    }
-
-    // Convert the {index} to an unsigned32 value and check if the result is
-    // equal to the original {index}.
-    if (!NumberMatcher(this_index).IsInRange(0.0, kMaxUInt32)) {
-      Node* this_index32 =
-          graph()->NewNode(simplified()->NumberToUint32(), this_index);
-      Node* check = graph()->NewNode(simplified()->NumberEqual(), this_index32,
-                                     this_index);
-      this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
-                                      frame_state, this_effect, this_control);
-      this_index = this_index32;
-    }
-
     // TODO(bmeurer): We currently specialize based on elements kind. We should
     // also be able to properly support strings and other JSObjects here.
     ElementsKind elements_kind = access_info.elements_kind();
@@ -698,8 +694,9 @@
       Node* check = graph()->NewNode(
           simplified()->ReferenceEqual(Type::Any()), this_elements_map,
           jsgraph()->HeapConstant(factory()->fixed_array_map()));
-      this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
-                                      frame_state, this_effect, this_control);
+      this_control = this_effect =
+          graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
+                           this_effect, this_control);
     }
 
     // Load the length of the {receiver}.
@@ -714,10 +711,9 @@
                   this_elements, this_effect, this_control);
 
     // Check that the {index} is in the valid range for the {receiver}.
-    Node* check = graph()->NewNode(simplified()->NumberLessThan(), this_index,
-                                   this_length);
-    this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
-                                    frame_state, this_effect, this_control);
+    this_index = this_effect =
+        graph()->NewNode(simplified()->CheckBounds(), this_index, this_length,
+                         this_effect, this_control);
 
     // Compute the element access.
     Type* element_type = Type::Any();
@@ -729,7 +725,8 @@
       element_type = type_cache_.kSmi;
     }
     ElementAccess element_access = {kTaggedBase, FixedArray::kHeaderSize,
-                                    element_type, element_machine_type};
+                                    element_type, element_machine_type,
+                                    kFullWriteBarrier};
 
     // Access the actual element.
     // TODO(bmeurer): Refactor this into separate methods or even a separate
@@ -753,45 +750,26 @@
       if (elements_kind == FAST_HOLEY_ELEMENTS ||
           elements_kind == FAST_HOLEY_SMI_ELEMENTS) {
         // Perform the hole check on the result.
-        Node* check =
-            graph()->NewNode(simplified()->ReferenceEqual(element_access.type),
-                             this_value, jsgraph()->TheHoleConstant());
+        CheckTaggedHoleMode mode = CheckTaggedHoleMode::kNeverReturnHole;
         // Check if we are allowed to turn the hole into undefined.
         Type* initial_holey_array_type = Type::Class(
             handle(isolate()->get_initial_js_array_map(elements_kind)),
             graph()->zone());
         if (receiver_type->NowIs(initial_holey_array_type) &&
             isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
-          Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse),
-                                          check, this_control);
-          Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-          Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
           // Add a code dependency on the array protector cell.
           AssumePrototypesStable(receiver_type, native_context,
                                  isolate()->initial_object_prototype());
           dependencies()->AssumePropertyCell(factory()->array_protector());
           // Turn the hole into undefined.
-          this_control =
-              graph()->NewNode(common()->Merge(2), if_true, if_false);
-          this_value = graph()->NewNode(
-              common()->Phi(MachineRepresentation::kTagged, 2),
-              jsgraph()->UndefinedConstant(), this_value, this_control);
-          element_type =
-              Type::Union(element_type, Type::Undefined(), graph()->zone());
-        } else {
-          // Deoptimize in case of the hole.
-          this_control =
-              graph()->NewNode(common()->DeoptimizeIf(), check, frame_state,
-                               this_effect, this_control);
+          mode = CheckTaggedHoleMode::kConvertHoleToUndefined;
         }
-        // Rename the result to represent the actual type (not polluted by the
-        // hole).
-        this_value = graph()->NewNode(common()->Guard(element_type), this_value,
-                                      this_control);
+        this_value = this_effect =
+            graph()->NewNode(simplified()->CheckTaggedHole(mode), this_value,
+                             this_effect, this_control);
       } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) {
         // Perform the hole check on the result.
-        Node* check =
-            graph()->NewNode(simplified()->NumberIsHoleNaN(), this_value);
+        CheckFloat64HoleMode mode = CheckFloat64HoleMode::kNeverReturnHole;
         // Check if we are allowed to return the hole directly.
         Type* initial_holey_array_type = Type::Class(
             handle(isolate()->get_initial_js_array_map(elements_kind)),
@@ -802,33 +780,32 @@
           AssumePrototypesStable(receiver_type, native_context,
                                  isolate()->initial_object_prototype());
           dependencies()->AssumePropertyCell(factory()->array_protector());
-          // Turn the hole into undefined.
-          this_value = graph()->NewNode(
-              common()->Select(MachineRepresentation::kTagged,
-                               BranchHint::kFalse),
-              check, jsgraph()->UndefinedConstant(), this_value);
-        } else {
-          // Deoptimize in case of the hole.
-          this_control =
-              graph()->NewNode(common()->DeoptimizeIf(), check, frame_state,
-                               this_effect, this_control);
+          // Return the signaling NaN hole directly if all uses are truncating.
+          mode = CheckFloat64HoleMode::kAllowReturnHole;
         }
+        this_value = this_effect =
+            graph()->NewNode(simplified()->CheckFloat64Hole(mode), this_value,
+                             this_effect, this_control);
       }
     } else {
       DCHECK_EQ(AccessMode::kStore, access_mode);
       if (IsFastSmiElementsKind(elements_kind)) {
-        Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), this_value);
-        this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
-                                        frame_state, this_effect, this_control);
-        this_value = graph()->NewNode(common()->Guard(type_cache_.kSmi),
-                                      this_value, this_control);
+        this_value = this_effect =
+            graph()->NewNode(simplified()->CheckTaggedSigned(), this_value,
+                             this_effect, this_control);
       } else if (IsFastDoubleElementsKind(elements_kind)) {
         Node* check =
             graph()->NewNode(simplified()->ObjectIsNumber(), this_value);
-        this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
-                                        frame_state, this_effect, this_control);
-        this_value = graph()->NewNode(common()->Guard(Type::Number()),
+        this_control = this_effect =
+            graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
+                             this_effect, this_control);
+        this_value = graph()->NewNode(simplified()->TypeGuard(Type::Number()),
                                       this_value, this_control);
+        // Make sure we do not store signalling NaNs into holey double arrays.
+        if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) {
+          this_value =
+              graph()->NewNode(simplified()->NumberSilenceNaN(), this_value);
+        }
       }
       this_effect = graph()->NewNode(simplified()->StoreElement(element_access),
                                      this_elements, this_index, this_value,
@@ -873,25 +850,29 @@
     KeyedAccessStoreMode store_mode) {
   DCHECK(node->opcode() == IrOpcode::kJSLoadProperty ||
          node->opcode() == IrOpcode::kJSStoreProperty);
+  Node* const receiver = NodeProperties::GetValueInput(node, 0);
+  Node* const effect = NodeProperties::GetEffectInput(node);
 
   // Check if the {nexus} reports type feedback for the IC.
   if (nexus.IsUninitialized()) {
     if ((flags() & kDeoptimizationEnabled) &&
         (flags() & kBailoutOnUninitialized)) {
-      // TODO(turbofan): Implement all eager bailout points correctly in
-      // the graph builder.
-      Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
-      if (!OpParameter<FrameStateInfo>(frame_state).bailout_id().IsNone()) {
-        return ReduceSoftDeoptimize(node);
-      }
+      return ReduceSoftDeoptimize(node);
     }
     return NoChange();
   }
 
   // Extract receiver maps from the {nexus}.
   MapHandleList receiver_maps;
-  if (nexus.ExtractMaps(&receiver_maps) == 0) return NoChange();
-  DCHECK_LT(0, receiver_maps.length());
+  if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) {
+    return NoChange();
+  } else if (receiver_maps.length() == 0) {
+    if ((flags() & kDeoptimizationEnabled) &&
+        (flags() & kBailoutOnUninitialized)) {
+      return ReduceSoftDeoptimize(node);
+    }
+    return NoChange();
+  }
 
   // Optimize access for constant {index}.
   HeapObjectMatcher mindex(index);
@@ -928,9 +909,9 @@
 
 
 Reduction JSNativeContextSpecialization::ReduceSoftDeoptimize(Node* node) {
-  Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
   Node* effect = NodeProperties::GetEffectInput(node);
   Node* control = NodeProperties::GetControlInput(node);
+  Node* frame_state = NodeProperties::FindFrameStateBefore(node);
   Node* deoptimize =
       graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kSoft), frame_state,
                        effect, control);
@@ -995,6 +976,84 @@
   }
 }
 
+bool JSNativeContextSpecialization::ExtractReceiverMaps(
+    Node* receiver, Node* effect, FeedbackNexus const& nexus,
+    MapHandleList* receiver_maps) {
+  DCHECK_EQ(0, receiver_maps->length());
+  // See if we can infer a concrete type for the {receiver}.
+  Handle<Map> receiver_map;
+  if (InferReceiverMap(receiver, effect).ToHandle(&receiver_map)) {
+    // We can assume that the {receiver} still has the infered {receiver_map}.
+    receiver_maps->Add(receiver_map);
+    return true;
+  }
+  // Try to extract some maps from the {nexus}.
+  if (nexus.ExtractMaps(receiver_maps) != 0) {
+    // Try to filter impossible candidates based on infered root map.
+    if (InferReceiverRootMap(receiver).ToHandle(&receiver_map)) {
+      for (int i = receiver_maps->length(); --i >= 0;) {
+        if (receiver_maps->at(i)->FindRootMap() != *receiver_map) {
+          receiver_maps->Remove(i);
+        }
+      }
+    }
+    return true;
+  }
+  return false;
+}
+
+MaybeHandle<Map> JSNativeContextSpecialization::InferReceiverMap(Node* receiver,
+                                                                 Node* effect) {
+  NodeMatcher m(receiver);
+  if (m.IsJSCreate()) {
+    HeapObjectMatcher mtarget(m.InputAt(0));
+    HeapObjectMatcher mnewtarget(m.InputAt(1));
+    if (mtarget.HasValue() && mnewtarget.HasValue()) {
+      Handle<JSFunction> constructor =
+          Handle<JSFunction>::cast(mtarget.Value());
+      if (constructor->has_initial_map()) {
+        Handle<Map> initial_map(constructor->initial_map(), isolate());
+        if (initial_map->constructor_or_backpointer() == *mnewtarget.Value()) {
+          // Walk up the {effect} chain to see if the {receiver} is the
+          // dominating effect and there's no other observable write in
+          // between.
+          while (true) {
+            if (receiver == effect) return initial_map;
+            if (!effect->op()->HasProperty(Operator::kNoWrite) ||
+                effect->op()->EffectInputCount() != 1) {
+              break;
+            }
+            effect = NodeProperties::GetEffectInput(effect);
+          }
+        }
+      }
+    }
+  }
+  return MaybeHandle<Map>();
+}
+
+MaybeHandle<Map> JSNativeContextSpecialization::InferReceiverRootMap(
+    Node* receiver) {
+  HeapObjectMatcher m(receiver);
+  if (m.HasValue()) {
+    return handle(m.Value()->map()->FindRootMap(), isolate());
+  } else if (m.IsJSCreate()) {
+    HeapObjectMatcher mtarget(m.InputAt(0));
+    HeapObjectMatcher mnewtarget(m.InputAt(1));
+    if (mtarget.HasValue() && mnewtarget.HasValue()) {
+      Handle<JSFunction> constructor =
+          Handle<JSFunction>::cast(mtarget.Value());
+      if (constructor->has_initial_map()) {
+        Handle<Map> initial_map(constructor->initial_map(), isolate());
+        if (initial_map->constructor_or_backpointer() == *mnewtarget.Value()) {
+          DCHECK_EQ(*initial_map, initial_map->FindRootMap());
+          return initial_map;
+        }
+      }
+    }
+  }
+  return MaybeHandle<Map>();
+}
 
 MaybeHandle<Context> JSNativeContextSpecialization::GetNativeContext(
     Node* node) {
diff --git a/src/compiler/js-native-context-specialization.h b/src/compiler/js-native-context-specialization.h
index 5562c6e..7d43bfb 100644
--- a/src/compiler/js-native-context-specialization.h
+++ b/src/compiler/js-native-context-specialization.h
@@ -85,6 +85,20 @@
                               Handle<Context> native_context,
                               Handle<JSObject> holder);
 
+  // Extract receiver maps from {nexus} and filter based on {receiver} if
+  // possible.
+  bool ExtractReceiverMaps(Node* receiver, Node* effect,
+                           FeedbackNexus const& nexus,
+                           MapHandleList* receiver_maps);
+
+  // Try to infer a map for the given {receiver} at the current {effect}.
+  // If a map is returned then you can be sure that the {receiver} definitely
+  // has the returned map at this point in the program (identified by {effect}).
+  MaybeHandle<Map> InferReceiverMap(Node* receiver, Node* effect);
+  // Try to infer a root map for the {receiver} independent of the current
+  // program location.
+  MaybeHandle<Map> InferReceiverRootMap(Node* receiver);
+
   // Retrieve the native context from the given {node} if known.
   MaybeHandle<Context> GetNativeContext(Node* node);
 
diff --git a/src/compiler/js-operator.cc b/src/compiler/js-operator.cc
index 98e090b..89c0eee 100644
--- a/src/compiler/js-operator.cc
+++ b/src/compiler/js-operator.cc
@@ -9,8 +9,8 @@
 #include "src/base/lazy-instance.h"
 #include "src/compiler/opcodes.h"
 #include "src/compiler/operator.h"
-#include "src/objects-inl.h"  // TODO(mstarzinger): Temporary cycle breaker!
-#include "src/type-feedback-vector-inl.h"
+#include "src/handles-inl.h"
+#include "src/type-feedback-vector.h"
 
 namespace v8 {
 namespace internal {
@@ -376,35 +376,54 @@
   return OpParameter<CreateLiteralParameters>(op);
 }
 
-#define CACHED_OP_LIST(V)                                  \
-  V(Equal, Operator::kNoProperties, 2, 1)                  \
-  V(NotEqual, Operator::kNoProperties, 2, 1)               \
-  V(StrictEqual, Operator::kNoThrow, 2, 1)                 \
-  V(StrictNotEqual, Operator::kNoThrow, 2, 1)              \
-  V(LessThan, Operator::kNoProperties, 2, 1)               \
-  V(GreaterThan, Operator::kNoProperties, 2, 1)            \
-  V(LessThanOrEqual, Operator::kNoProperties, 2, 1)        \
-  V(GreaterThanOrEqual, Operator::kNoProperties, 2, 1)     \
-  V(ToInteger, Operator::kNoProperties, 1, 1)              \
-  V(ToLength, Operator::kNoProperties, 1, 1)               \
-  V(ToName, Operator::kNoProperties, 1, 1)                 \
-  V(ToNumber, Operator::kNoProperties, 1, 1)               \
-  V(ToObject, Operator::kNoProperties, 1, 1)               \
-  V(ToString, Operator::kNoProperties, 1, 1)               \
-  V(Yield, Operator::kNoProperties, 1, 1)                  \
-  V(Create, Operator::kEliminatable, 2, 1)                 \
-  V(CreateIterResultObject, Operator::kEliminatable, 2, 1) \
-  V(HasProperty, Operator::kNoProperties, 2, 1)            \
-  V(TypeOf, Operator::kEliminatable, 1, 1)                 \
-  V(InstanceOf, Operator::kNoProperties, 2, 1)             \
-  V(ForInDone, Operator::kPure, 2, 1)                      \
-  V(ForInNext, Operator::kNoProperties, 4, 1)              \
-  V(ForInPrepare, Operator::kNoProperties, 1, 3)           \
-  V(ForInStep, Operator::kPure, 1, 1)                      \
-  V(LoadMessage, Operator::kNoThrow, 0, 1)                 \
-  V(StoreMessage, Operator::kNoThrow, 1, 0)                \
-  V(StackCheck, Operator::kNoProperties, 0, 0)             \
-  V(CreateWithContext, Operator::kNoProperties, 2, 1)      \
+const BinaryOperationHints& BinaryOperationHintsOf(const Operator* op) {
+  DCHECK(op->opcode() == IrOpcode::kJSBitwiseOr ||
+         op->opcode() == IrOpcode::kJSBitwiseXor ||
+         op->opcode() == IrOpcode::kJSBitwiseAnd ||
+         op->opcode() == IrOpcode::kJSShiftLeft ||
+         op->opcode() == IrOpcode::kJSShiftRight ||
+         op->opcode() == IrOpcode::kJSShiftRightLogical ||
+         op->opcode() == IrOpcode::kJSAdd ||
+         op->opcode() == IrOpcode::kJSSubtract ||
+         op->opcode() == IrOpcode::kJSMultiply ||
+         op->opcode() == IrOpcode::kJSDivide ||
+         op->opcode() == IrOpcode::kJSModulus);
+  return OpParameter<BinaryOperationHints>(op);
+}
+
+const CompareOperationHints& CompareOperationHintsOf(const Operator* op) {
+  DCHECK(op->opcode() == IrOpcode::kJSEqual ||
+         op->opcode() == IrOpcode::kJSNotEqual ||
+         op->opcode() == IrOpcode::kJSStrictEqual ||
+         op->opcode() == IrOpcode::kJSStrictNotEqual ||
+         op->opcode() == IrOpcode::kJSLessThan ||
+         op->opcode() == IrOpcode::kJSGreaterThan ||
+         op->opcode() == IrOpcode::kJSLessThanOrEqual ||
+         op->opcode() == IrOpcode::kJSGreaterThanOrEqual);
+  return OpParameter<CompareOperationHints>(op);
+}
+
+#define CACHED_OP_LIST(V)                                   \
+  V(ToInteger, Operator::kNoProperties, 1, 1)               \
+  V(ToLength, Operator::kNoProperties, 1, 1)                \
+  V(ToName, Operator::kNoProperties, 1, 1)                  \
+  V(ToNumber, Operator::kNoProperties, 1, 1)                \
+  V(ToObject, Operator::kFoldable, 1, 1)                    \
+  V(ToString, Operator::kNoProperties, 1, 1)                \
+  V(Create, Operator::kEliminatable, 2, 1)                  \
+  V(CreateIterResultObject, Operator::kEliminatable, 2, 1)  \
+  V(HasProperty, Operator::kNoProperties, 2, 1)             \
+  V(TypeOf, Operator::kPure, 1, 1)                          \
+  V(InstanceOf, Operator::kNoProperties, 2, 1)              \
+  V(ForInDone, Operator::kPure, 2, 1)                       \
+  V(ForInNext, Operator::kNoProperties, 4, 1)               \
+  V(ForInPrepare, Operator::kNoProperties, 1, 3)            \
+  V(ForInStep, Operator::kPure, 1, 1)                       \
+  V(LoadMessage, Operator::kNoThrow, 0, 1)                  \
+  V(StoreMessage, Operator::kNoThrow, 1, 0)                 \
+  V(GeneratorRestoreContinuation, Operator::kNoThrow, 1, 1) \
+  V(StackCheck, Operator::kNoProperties, 0, 0)              \
+  V(CreateWithContext, Operator::kNoProperties, 2, 1)       \
   V(CreateModuleContext, Operator::kNoProperties, 2, 1)
 
 struct JSOperatorGlobalCache final {
@@ -538,14 +557,87 @@
       hints);                                           // parameter
 }
 
+const Operator* JSOperatorBuilder::Equal(CompareOperationHints hints) {
+  // TODO(turbofan): Cache most important versions of this operator.
+  return new (zone()) Operator1<CompareOperationHints>(  //--
+      IrOpcode::kJSEqual, Operator::kNoProperties,       // opcode
+      "JSEqual",                                         // name
+      2, 1, 1, 1, 1, 2,                                  // inputs/outputs
+      hints);                                            // parameter
+}
+
+const Operator* JSOperatorBuilder::NotEqual(CompareOperationHints hints) {
+  // TODO(turbofan): Cache most important versions of this operator.
+  return new (zone()) Operator1<CompareOperationHints>(  //--
+      IrOpcode::kJSNotEqual, Operator::kNoProperties,    // opcode
+      "JSNotEqual",                                      // name
+      2, 1, 1, 1, 1, 2,                                  // inputs/outputs
+      hints);                                            // parameter
+}
+
+const Operator* JSOperatorBuilder::StrictEqual(CompareOperationHints hints) {
+  // TODO(turbofan): Cache most important versions of this operator.
+  return new (zone()) Operator1<CompareOperationHints>(  //--
+      IrOpcode::kJSStrictEqual, Operator::kPure,         // opcode
+      "JSStrictEqual",                                   // name
+      2, 0, 0, 1, 0, 0,                                  // inputs/outputs
+      hints);                                            // parameter
+}
+
+const Operator* JSOperatorBuilder::StrictNotEqual(CompareOperationHints hints) {
+  // TODO(turbofan): Cache most important versions of this operator.
+  return new (zone()) Operator1<CompareOperationHints>(  //--
+      IrOpcode::kJSStrictNotEqual, Operator::kPure,      // opcode
+      "JSStrictNotEqual",                                // name
+      2, 0, 0, 1, 0, 0,                                  // inputs/outputs
+      hints);                                            // parameter
+}
+
+const Operator* JSOperatorBuilder::LessThan(CompareOperationHints hints) {
+  // TODO(turbofan): Cache most important versions of this operator.
+  return new (zone()) Operator1<CompareOperationHints>(  //--
+      IrOpcode::kJSLessThan, Operator::kNoProperties,    // opcode
+      "JSLessThan",                                      // name
+      2, 1, 1, 1, 1, 2,                                  // inputs/outputs
+      hints);                                            // parameter
+}
+
+const Operator* JSOperatorBuilder::GreaterThan(CompareOperationHints hints) {
+  // TODO(turbofan): Cache most important versions of this operator.
+  return new (zone()) Operator1<CompareOperationHints>(   //--
+      IrOpcode::kJSGreaterThan, Operator::kNoProperties,  // opcode
+      "JSGreaterThan",                                    // name
+      2, 1, 1, 1, 1, 2,                                   // inputs/outputs
+      hints);                                             // parameter
+}
+
+const Operator* JSOperatorBuilder::LessThanOrEqual(
+    CompareOperationHints hints) {
+  // TODO(turbofan): Cache most important versions of this operator.
+  return new (zone()) Operator1<CompareOperationHints>(       //--
+      IrOpcode::kJSLessThanOrEqual, Operator::kNoProperties,  // opcode
+      "JSLessThanOrEqual",                                    // name
+      2, 1, 1, 1, 1, 2,                                       // inputs/outputs
+      hints);                                                 // parameter
+}
+
+const Operator* JSOperatorBuilder::GreaterThanOrEqual(
+    CompareOperationHints hints) {
+  // TODO(turbofan): Cache most important versions of this operator.
+  return new (zone()) Operator1<CompareOperationHints>(          //--
+      IrOpcode::kJSGreaterThanOrEqual, Operator::kNoProperties,  // opcode
+      "JSGreaterThanOrEqual",                                    // name
+      2, 1, 1, 1, 1, 2,  // inputs/outputs
+      hints);            // parameter
+}
 
 const Operator* JSOperatorBuilder::ToBoolean(ToBooleanHints hints) {
   // TODO(turbofan): Cache most important versions of this operator.
-  return new (zone()) Operator1<ToBooleanHints>(        //--
-      IrOpcode::kJSToBoolean, Operator::kEliminatable,  // opcode
-      "JSToBoolean",                                    // name
-      1, 1, 0, 1, 1, 0,                                 // inputs/outputs
-      hints);                                           // parameter
+  return new (zone()) Operator1<ToBooleanHints>(  //--
+      IrOpcode::kJSToBoolean, Operator::kPure,    // opcode
+      "JSToBoolean",                              // name
+      1, 0, 0, 1, 0, 0,                           // inputs/outputs
+      hints);                                     // parameter
 }
 
 const Operator* JSOperatorBuilder::CallFunction(
@@ -626,6 +718,21 @@
       access);                                             // parameter
 }
 
+const Operator* JSOperatorBuilder::GeneratorStore(int register_count) {
+  return new (zone()) Operator1<int>(                   // --
+      IrOpcode::kJSGeneratorStore, Operator::kNoThrow,  // opcode
+      "JSGeneratorStore",                               // name
+      3 + register_count, 1, 1, 0, 1, 0,                // counts
+      register_count);                                  // parameter
+}
+
+const Operator* JSOperatorBuilder::GeneratorRestoreRegister(int index) {
+  return new (zone()) Operator1<int>(                             // --
+      IrOpcode::kJSGeneratorRestoreRegister, Operator::kNoThrow,  // opcode
+      "JSGeneratorRestoreRegister",                               // name
+      1, 1, 1, 1, 1, 0,                                           // counts
+      index);                                                     // parameter
+}
 
 const Operator* JSOperatorBuilder::StoreNamed(LanguageMode language_mode,
                                               Handle<Name> name,
@@ -707,11 +814,11 @@
 
 
 const Operator* JSOperatorBuilder::CreateArguments(CreateArgumentsType type) {
-  return new (zone()) Operator1<CreateArgumentsType>(    // --
-      IrOpcode::kJSCreateArguments, Operator::kNoThrow,  // opcode
-      "JSCreateArguments",                               // name
-      1, 1, 1, 1, 1, 0,                                  // counts
-      type);                                             // parameter
+  return new (zone()) Operator1<CreateArgumentsType>(         // --
+      IrOpcode::kJSCreateArguments, Operator::kEliminatable,  // opcode
+      "JSCreateArguments",                                    // name
+      1, 1, 0, 1, 1, 0,                                       // counts
+      type);                                                  // parameter
 }
 
 
diff --git a/src/compiler/js-operator.h b/src/compiler/js-operator.h
index eb323c9..8390cbd 100644
--- a/src/compiler/js-operator.h
+++ b/src/compiler/js-operator.h
@@ -344,7 +344,6 @@
 
 const CreateClosureParameters& CreateClosureParametersOf(const Operator* op);
 
-
 // Defines shared information for the literal that should be created. This is
 // used as parameter by JSCreateLiteralArray, JSCreateLiteralObject and
 // JSCreateLiteralRegExp operators.
@@ -375,6 +374,9 @@
 
 const CreateLiteralParameters& CreateLiteralParametersOf(const Operator* op);
 
+const BinaryOperationHints& BinaryOperationHintsOf(const Operator* op);
+
+const CompareOperationHints& CompareOperationHintsOf(const Operator* op);
 
 // Interface for building JavaScript-level operators, e.g. directly from the
 // AST. Most operators have no parameters, thus can be globally shared for all
@@ -383,14 +385,14 @@
  public:
   explicit JSOperatorBuilder(Zone* zone);
 
-  const Operator* Equal();
-  const Operator* NotEqual();
-  const Operator* StrictEqual();
-  const Operator* StrictNotEqual();
-  const Operator* LessThan();
-  const Operator* GreaterThan();
-  const Operator* LessThanOrEqual();
-  const Operator* GreaterThanOrEqual();
+  const Operator* Equal(CompareOperationHints hints);
+  const Operator* NotEqual(CompareOperationHints hints);
+  const Operator* StrictEqual(CompareOperationHints hints);
+  const Operator* StrictNotEqual(CompareOperationHints hints);
+  const Operator* LessThan(CompareOperationHints hints);
+  const Operator* GreaterThan(CompareOperationHints hints);
+  const Operator* LessThanOrEqual(CompareOperationHints hints);
+  const Operator* GreaterThanOrEqual(CompareOperationHints hints);
   const Operator* BitwiseOr(BinaryOperationHints hints);
   const Operator* BitwiseXor(BinaryOperationHints hints);
   const Operator* BitwiseAnd(BinaryOperationHints hints);
@@ -410,7 +412,6 @@
   const Operator* ToNumber();
   const Operator* ToObject();
   const Operator* ToString();
-  const Operator* Yield();
 
   const Operator* Create();
   const Operator* CreateArguments(CreateArgumentsType type);
@@ -471,6 +472,13 @@
   const Operator* LoadMessage();
   const Operator* StoreMessage();
 
+  // Used to implement Ignition's SuspendGenerator bytecode.
+  const Operator* GeneratorStore(int register_count);
+
+  // Used to implement Ignition's ResumeGenerator bytecode.
+  const Operator* GeneratorRestoreContinuation();
+  const Operator* GeneratorRestoreRegister(int index);
+
   const Operator* StackCheck();
 
   const Operator* CreateFunctionContext(int slot_count);
diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc
index 7e1a0dc..fcfe134 100644
--- a/src/compiler/js-typed-lowering.cc
+++ b/src/compiler/js-typed-lowering.cc
@@ -27,6 +27,41 @@
   JSBinopReduction(JSTypedLowering* lowering, Node* node)
       : lowering_(lowering), node_(node) {}
 
+  BinaryOperationHints::Hint GetNumberBinaryOperationFeedback() {
+    if (!(lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) ||
+        !(lowering_->flags() & JSTypedLowering::kTypeFeedbackEnabled)) {
+      return BinaryOperationHints::kAny;
+    }
+    DCHECK_NE(0, node_->op()->ControlOutputCount());
+    DCHECK_EQ(1, node_->op()->EffectOutputCount());
+    DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node_->op()));
+    BinaryOperationHints hints = BinaryOperationHintsOf(node_->op());
+    BinaryOperationHints::Hint combined = hints.combined();
+    if (combined == BinaryOperationHints::kSignedSmall ||
+        combined == BinaryOperationHints::kSigned32 ||
+        combined == BinaryOperationHints::kNumberOrUndefined) {
+      return combined;
+    }
+    return BinaryOperationHints::kAny;
+  }
+
+  CompareOperationHints::Hint GetNumberCompareOperationFeedback() {
+    if (!(lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) ||
+        !(lowering_->flags() & JSTypedLowering::kTypeFeedbackEnabled)) {
+      return CompareOperationHints::kAny;
+    }
+    DCHECK_NE(0, node_->op()->ControlOutputCount());
+    DCHECK_EQ(1, node_->op()->EffectOutputCount());
+    DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node_->op()));
+    CompareOperationHints hints = CompareOperationHintsOf(node_->op());
+    CompareOperationHints::Hint combined = hints.combined();
+    if (combined == CompareOperationHints::kSignedSmall ||
+        combined == CompareOperationHints::kNumber) {
+      return combined;
+    }
+    return CompareOperationHints::kAny;
+  }
+
   void ConvertInputsToNumber(Node* frame_state) {
     // To convert the inputs to numbers, we have to provide frame states
     // for lazy bailouts in the ToNumber conversions.
@@ -107,29 +142,50 @@
     return lowering_->Changed(node_);
   }
 
-  Reduction ChangeToStringComparisonOperator(const Operator* op,
-                                             bool invert = false) {
-    if (node_->op()->ControlInputCount() > 0) {
-      lowering_->RelaxControls(node_);
-    }
-    // String comparison operators need effect and control inputs, so copy them
-    // over.
-    Node* effect = NodeProperties::GetEffectInput(node_);
-    Node* control = NodeProperties::GetControlInput(node_);
-    node_->ReplaceInput(2, effect);
-    node_->ReplaceInput(3, control);
+  Reduction ChangeToSpeculativeOperator(const Operator* op, Type* upper_bound) {
+    DCHECK_EQ(1, op->EffectInputCount());
+    DCHECK_EQ(1, op->EffectOutputCount());
+    DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
+    DCHECK_EQ(1, op->ControlInputCount());
+    DCHECK_EQ(0, op->ControlOutputCount());
+    DCHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op));
+    DCHECK_EQ(2, op->ValueInputCount());
 
-    node_->TrimInputCount(4);
+    DCHECK_EQ(1, node_->op()->EffectInputCount());
+    DCHECK_EQ(1, node_->op()->EffectOutputCount());
+    DCHECK_EQ(1, node_->op()->ControlInputCount());
+    DCHECK_LT(1, node_->op()->ControlOutputCount());
+    DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node_->op()));
+    DCHECK_EQ(2, node_->op()->ValueInputCount());
+
+    // Reconnect the control output to bypass the IfSuccess node and
+    // possibly disconnect from the IfException node.
+    for (Edge edge : node_->use_edges()) {
+      Node* const user = edge.from();
+      DCHECK(!user->IsDead());
+      if (NodeProperties::IsControlEdge(edge)) {
+        if (user->opcode() == IrOpcode::kIfSuccess) {
+          user->ReplaceUses(NodeProperties::GetControlInput(node_));
+          user->Kill();
+        } else {
+          DCHECK_EQ(user->opcode(), IrOpcode::kIfException);
+          edge.UpdateTo(jsgraph()->Dead());
+        }
+      }
+    }
+
+    // Remove both bailout frame states and the context.
+    node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_) + 1);
+    node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_));
+    node_->RemoveInput(NodeProperties::FirstContextIndex(node_));
+
     NodeProperties::ChangeOp(node_, op);
 
-    if (invert) {
-      // Insert a boolean-not to invert the value.
-      Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
-      node_->ReplaceUses(value);
-      // Note: ReplaceUses() smashes all uses, so smash it back here.
-      value->ReplaceInput(0, node_);
-      return lowering_->Replace(value);
-    }
+    // Update the type to number.
+    Type* node_type = NodeProperties::GetType(node_);
+    NodeProperties::SetType(node_,
+                            Type::Intersect(node_type, upper_bound, zone()));
+
     return lowering_->Changed(node_);
   }
 
@@ -247,17 +303,19 @@
     // Avoid inserting too many eager ToNumber() operations.
     Reduction const reduction = lowering_->ReduceJSToNumberInput(node);
     if (reduction.Changed()) return reduction.replacement();
-    // TODO(jarin) Use PlainPrimitiveToNumber once we have it.
-    return graph()->NewNode(
-        javascript()->ToNumber(), node, jsgraph()->NoContextConstant(),
-        jsgraph()->EmptyFrameState(), graph()->start(), graph()->start());
+    if (NodeProperties::GetType(node)->Is(Type::Number())) {
+      return node;
+    }
+    return graph()->NewNode(simplified()->PlainPrimitiveToNumber(), node);
   }
 
   Node* ConvertSingleInputToNumber(Node* node, Node* frame_state) {
     DCHECK(!NodeProperties::GetType(node)->Is(Type::PlainPrimitive()));
     Node* const n = graph()->NewNode(javascript()->ToNumber(), node, context(),
                                      frame_state, effect(), control());
-    NodeProperties::ReplaceUses(node_, node_, node_, n, n);
+    Node* const if_success = graph()->NewNode(common()->IfSuccess(), n);
+    NodeProperties::ReplaceControlInput(node_, if_success);
+    NodeProperties::ReplaceUses(node_, node_, node_, node_, n);
     update_effect(n);
     return n;
   }
@@ -361,8 +419,25 @@
   if (flags() & kDisableBinaryOpReduction) return NoChange();
 
   JSBinopReduction r(this, node);
+
+  BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
+  if (feedback == BinaryOperationHints::kNumberOrUndefined &&
+      r.BothInputsAre(Type::PlainPrimitive()) &&
+      r.NeitherInputCanBe(Type::StringOrReceiver())) {
+    // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
+    Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
+    r.ConvertInputsToNumber(frame_state);
+    return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
+  }
+  if (feedback != BinaryOperationHints::kAny) {
+    // Lower to the optimistic number binop.
+    return r.ChangeToSpeculativeOperator(
+        simplified()->SpeculativeNumberAdd(feedback), Type::Number());
+  }
   if (r.BothInputsAre(Type::Number())) {
     // JSAdd(x:number, y:number) => NumberAdd(x, y)
+    Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
+    r.ConvertInputsToNumber(frame_state);
     return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
   }
   if (r.NeitherInputCanBe(Type::StringOrReceiver())) {
@@ -371,10 +446,17 @@
     r.ConvertInputsToNumber(frame_state);
     return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
   }
-  if (r.BothInputsAre(Type::String())) {
-    // JSAdd(x:string, y:string) => CallStub[StringAdd](x, y)
+  if (r.OneInputIs(Type::String())) {
+    StringAddFlags flags = STRING_ADD_CHECK_NONE;
+    if (!r.LeftInputIs(Type::String())) {
+      flags = STRING_ADD_CONVERT_LEFT;
+    } else if (!r.RightInputIs(Type::String())) {
+      flags = STRING_ADD_CONVERT_RIGHT;
+    }
+    // JSAdd(x:string, y) => CallStub[StringAdd](x, y)
+    // JSAdd(x, y:string) => CallStub[StringAdd](x, y)
     Callable const callable =
-        CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);
+        CodeFactory::StringAdd(isolate(), flags, NOT_TENURED);
     CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
         isolate(), graph()->zone(), callable.descriptor(), 0,
         CallDescriptor::kNeedsFrameState, node->op()->properties());
@@ -391,31 +473,69 @@
 
 Reduction JSTypedLowering::ReduceJSModulus(Node* node) {
   if (flags() & kDisableBinaryOpReduction) return NoChange();
-
   JSBinopReduction r(this, node);
   if (r.BothInputsAre(Type::Number())) {
     // JSModulus(x:number, x:number) => NumberModulus(x, y)
     return r.ChangeToPureOperator(simplified()->NumberModulus(),
                                   Type::Number());
   }
+  BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
+  if (feedback != BinaryOperationHints::kAny) {
+    return r.ChangeToSpeculativeOperator(
+        simplified()->SpeculativeNumberModulus(feedback), Type::Number());
+  }
   return NoChange();
 }
 
-
-Reduction JSTypedLowering::ReduceNumberBinop(Node* node,
-                                             const Operator* numberOp) {
+Reduction JSTypedLowering::ReduceJSSubtract(Node* node) {
   if (flags() & kDisableBinaryOpReduction) return NoChange();
-
   JSBinopReduction r(this, node);
-  if (numberOp == simplified()->NumberModulus()) {
-    if (r.BothInputsAre(Type::Number())) {
-      return r.ChangeToPureOperator(numberOp, Type::Number());
-    }
-    return NoChange();
+  BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
+  if (feedback == BinaryOperationHints::kNumberOrUndefined &&
+      r.BothInputsAre(Type::PlainPrimitive())) {
+    // JSSubtract(x:plain-primitive, y:plain-primitive)
+    //   => NumberSubtract(ToNumber(x), ToNumber(y))
+    Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
+    r.ConvertInputsToNumber(frame_state);
+    return r.ChangeToPureOperator(simplified()->NumberSubtract(),
+                                  Type::Number());
+  }
+  if (feedback != BinaryOperationHints::kAny) {
+    // Lower to the optimistic number binop.
+    return r.ChangeToSpeculativeOperator(
+        simplified()->SpeculativeNumberSubtract(feedback), Type::Number());
   }
   Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
   r.ConvertInputsToNumber(frame_state);
-  return r.ChangeToPureOperator(numberOp, Type::Number());
+  return r.ChangeToPureOperator(simplified()->NumberSubtract(), Type::Number());
+}
+
+Reduction JSTypedLowering::ReduceJSMultiply(Node* node) {
+  if (flags() & kDisableBinaryOpReduction) return NoChange();
+  JSBinopReduction r(this, node);
+
+  BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
+  if (feedback != BinaryOperationHints::kAny) {
+    return r.ChangeToSpeculativeOperator(
+        simplified()->SpeculativeNumberMultiply(feedback), Type::Number());
+  }
+
+  Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
+  r.ConvertInputsToNumber(frame_state);
+  return r.ChangeToPureOperator(simplified()->NumberMultiply(), Type::Number());
+}
+
+Reduction JSTypedLowering::ReduceJSDivide(Node* node) {
+  if (flags() & kDisableBinaryOpReduction) return NoChange();
+  JSBinopReduction r(this, node);
+  BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
+  if (feedback != BinaryOperationHints::kAny) {
+    return r.ChangeToSpeculativeOperator(
+        simplified()->SpeculativeNumberDivide(feedback), Type::Number());
+  }
+  Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
+  r.ConvertInputsToNumber(frame_state);
+  return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number());
 }
 
 
@@ -468,10 +588,13 @@
       default:
         return NoChange();
     }
-    r.ChangeToStringComparisonOperator(stringOp);
+    r.ChangeToPureOperator(stringOp);
     return Changed(node);
   }
-  if (r.OneInputCannotBe(Type::StringOrReceiver())) {
+
+  CompareOperationHints::Hint hint = r.GetNumberCompareOperationFeedback();
+  if (hint != CompareOperationHints::kAny ||
+      r.OneInputCannotBe(Type::StringOrReceiver())) {
     const Operator* less_than;
     const Operator* less_than_or_equal;
     if (r.BothInputsAre(Type::Unsigned32())) {
@@ -480,6 +603,9 @@
     } else if (r.BothInputsAre(Type::Signed32())) {
       less_than = machine()->Int32LessThan();
       less_than_or_equal = machine()->Int32LessThanOrEqual();
+    } else if (hint != CompareOperationHints::kAny) {
+      less_than = simplified()->SpeculativeNumberLessThan(hint);
+      less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint);
     } else {
       // TODO(turbofan): mixed signed/unsigned int32 comparisons.
       Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
@@ -506,24 +632,71 @@
       default:
         return NoChange();
     }
-    return r.ChangeToPureOperator(comparison);
+    if (comparison->EffectInputCount() > 0) {
+      return r.ChangeToSpeculativeOperator(comparison, Type::Boolean());
+    } else {
+      return r.ChangeToPureOperator(comparison);
+    }
   }
   // TODO(turbofan): relax/remove effects of this operator in other cases.
   return NoChange();  // Keep a generic comparison.
 }
 
+Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) {
+  HeapObjectBinopMatcher m(node);
+  if (m.left().IsJSTypeOf() && m.right().HasValue() &&
+      m.right().Value()->IsString()) {
+    Node* replacement;
+    Node* input = m.left().InputAt(0);
+    Handle<String> value = Handle<String>::cast(m.right().Value());
+    if (String::Equals(value, factory()->boolean_string())) {
+      replacement = graph()->NewNode(
+          common()->Select(MachineRepresentation::kTagged),
+          graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), input,
+                           jsgraph()->TrueConstant()),
+          jsgraph()->TrueConstant(),
+          graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), input,
+                           jsgraph()->FalseConstant()));
+    } else if (String::Equals(value, factory()->function_string())) {
+      replacement = graph()->NewNode(simplified()->ObjectIsCallable(), input);
+    } else if (String::Equals(value, factory()->number_string())) {
+      replacement = graph()->NewNode(simplified()->ObjectIsNumber(), input);
+    } else if (String::Equals(value, factory()->string_string())) {
+      replacement = graph()->NewNode(simplified()->ObjectIsString(), input);
+    } else if (String::Equals(value, factory()->undefined_string())) {
+      replacement = graph()->NewNode(
+          common()->Select(MachineRepresentation::kTagged),
+          graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), input,
+                           jsgraph()->NullConstant()),
+          jsgraph()->FalseConstant(),
+          graph()->NewNode(simplified()->ObjectIsUndetectable(), input));
+    } else {
+      return NoChange();
+    }
+    if (invert) {
+      replacement = graph()->NewNode(simplified()->BooleanNot(), replacement);
+    }
+    return Replace(replacement);
+  }
+  return NoChange();
+}
 
 Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) {
   if (flags() & kDisableBinaryOpReduction) return NoChange();
 
+  Reduction const reduction = ReduceJSEqualTypeOf(node, invert);
+  if (reduction.Changed()) {
+    ReplaceWithValue(node, reduction.replacement());
+    return reduction;
+  }
+
   JSBinopReduction r(this, node);
 
   if (r.BothInputsAre(Type::Number())) {
     return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
   }
   if (r.BothInputsAre(Type::String())) {
-    return r.ChangeToStringComparisonOperator(simplified()->StringEqual(),
-                                              invert);
+    return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
   }
   if (r.BothInputsAre(Type::Boolean())) {
     return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Boolean()),
@@ -564,15 +737,20 @@
       return Replace(replacement);
     }
   }
-  if (r.OneInputCannotBe(Type::NumberOrString())) {
-    // For values with canonical representation (i.e. not string nor number) an
-    // empty type intersection means the values cannot be strictly equal.
+  if (r.OneInputCannotBe(Type::NumberOrSimdOrString())) {
+    // For values with canonical representation (i.e. neither String, nor
+    // Simd128Value nor Number) an empty type intersection means the values
+    // cannot be strictly equal.
     if (!r.left_type()->Maybe(r.right_type())) {
       Node* replacement = jsgraph()->BooleanConstant(invert);
       ReplaceWithValue(node, replacement);
       return Replace(replacement);
     }
   }
+  Reduction const reduction = ReduceJSEqualTypeOf(node, invert);
+  if (reduction.Changed()) {
+    return reduction;
+  }
   if (r.OneInputIs(the_hole_type_)) {
     return r.ChangeToPureOperator(simplified()->ReferenceEqual(the_hole_type_),
                                   invert);
@@ -602,8 +780,7 @@
                                   invert);
   }
   if (r.BothInputsAre(Type::String())) {
-    return r.ChangeToStringComparisonOperator(simplified()->StringEqual(),
-                                              invert);
+    return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
   }
   if (r.BothInputsAre(Type::Number())) {
     return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
@@ -616,10 +793,8 @@
 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
   Node* const input = node->InputAt(0);
   Type* const input_type = NodeProperties::GetType(input);
-  Node* const effect = NodeProperties::GetEffectInput(node);
   if (input_type->Is(Type::Boolean())) {
     // JSToBoolean(x:boolean) => x
-    ReplaceWithValue(node, input, effect);
     return Replace(input);
   } else if (input_type->Is(Type::OrderedNumber())) {
     // JSToBoolean(x:ordered-number) => BooleanNot(NumberEqual(x,#0))
@@ -633,11 +808,10 @@
     // JSToBoolean(x:string) => NumberLessThan(#0,x.length)
     FieldAccess const access = AccessBuilder::ForStringLength();
     Node* length = graph()->NewNode(simplified()->LoadField(access), input,
-                                    effect, graph()->start());
+                                    graph()->start(), graph()->start());
     ReplaceWithValue(node, node, length);
     node->ReplaceInput(0, jsgraph()->ZeroConstant());
     node->ReplaceInput(1, length);
-    node->TrimInputCount(2);
     NodeProperties::ChangeOp(node, simplified()->NumberLessThan());
     return Changed(node);
   }
@@ -691,27 +865,6 @@
 }
 
 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
-  if (input->opcode() == IrOpcode::kJSToNumber) {
-    // Recursively try to reduce the input first.
-    Reduction result = ReduceJSToNumber(input);
-    if (result.Changed()) return result;
-    return Changed(input);  // JSToNumber(JSToNumber(x)) => JSToNumber(x)
-  }
-  // Check for ToNumber truncation of signaling NaN to undefined mapping.
-  if (input->opcode() == IrOpcode::kSelect) {
-    Node* check = NodeProperties::GetValueInput(input, 0);
-    Node* vtrue = NodeProperties::GetValueInput(input, 1);
-    Type* vtrue_type = NodeProperties::GetType(vtrue);
-    Node* vfalse = NodeProperties::GetValueInput(input, 2);
-    Type* vfalse_type = NodeProperties::GetType(vfalse);
-    if (vtrue_type->Is(Type::Undefined()) && vfalse_type->Is(Type::Number())) {
-      if (check->opcode() == IrOpcode::kNumberIsHoleNaN &&
-          check->InputAt(0) == vfalse) {
-        // JSToNumber(Select(NumberIsHoleNaN(x), y:undefined, x:number)) => x
-        return Replace(vfalse);
-      }
-    }
-  }
   // Try constant-folding of JSToNumber with constant inputs.
   Type* input_type = NodeProperties::GetType(input);
   if (input_type->IsConstant()) {
@@ -758,21 +911,10 @@
   }
   Type* const input_type = NodeProperties::GetType(input);
   if (input_type->Is(Type::PlainPrimitive())) {
-    if (NodeProperties::GetContextInput(node) !=
-            jsgraph()->NoContextConstant() ||
-        NodeProperties::GetEffectInput(node) != graph()->start() ||
-        NodeProperties::GetControlInput(node) != graph()->start()) {
-      // JSToNumber(x:plain-primitive,context,effect,control)
-      //   => JSToNumber(x,no-context,start,start)
-      RelaxEffectsAndControls(node);
-      NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
-      NodeProperties::ReplaceControlInput(node, graph()->start());
-      NodeProperties::ReplaceEffectInput(node, graph()->start());
-      DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
-      NodeProperties::ReplaceFrameStateInput(node, 0,
-                                             jsgraph()->EmptyFrameState());
-      return Changed(node);
-    }
+    RelaxEffectsAndControls(node);
+    node->TrimInputCount(1);
+    NodeProperties::ChangeOp(node, simplified()->PlainPrimitiveToNumber());
+    return Changed(node);
   }
   return NoChange();
 }
@@ -914,27 +1056,6 @@
     ReplaceWithValue(node, value, effect);
     return Replace(value);
   }
-  // Optimize "prototype" property of functions.
-  if (name.is_identical_to(factory()->prototype_string()) &&
-      receiver_type->IsConstant() &&
-      receiver_type->AsConstant()->Value()->IsJSFunction()) {
-    // TODO(turbofan): This lowering might not kick in if we ever lower
-    // the C++ accessor for "prototype" in an earlier optimization pass.
-    Handle<JSFunction> function =
-        Handle<JSFunction>::cast(receiver_type->AsConstant()->Value());
-    if (function->has_initial_map()) {
-      // We need to add a code dependency on the initial map of the {function}
-      // in order to be notified about changes to the "prototype" of {function},
-      // so it doesn't make sense to continue unless deoptimization is enabled.
-      if (!(flags() & kDeoptimizationEnabled)) return NoChange();
-      Handle<Map> initial_map(function->initial_map(), isolate());
-      dependencies()->AssumeInitialMapCantChange(initial_map);
-      Node* value =
-          jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
-      ReplaceWithValue(node, value);
-      return Replace(value);
-    }
-  }
   return NoChange();
 }
 
@@ -1018,7 +1139,7 @@
             value = number_reduction.replacement();
           } else {
             Node* frame_state_for_to_number =
-                NodeProperties::GetFrameStateInput(node, 1);
+                NodeProperties::FindFrameStateBefore(node);
             value = effect =
                 graph()->NewNode(javascript()->ToNumber(), value, context,
                                  frame_state_for_to_number, effect, control);
@@ -1065,10 +1186,7 @@
   Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0);
 
   // If deoptimization is disabled, we cannot optimize.
-  if (!(flags() & kDeoptimizationEnabled) ||
-      (flags() & kDisableBinaryOpReduction)) {
-    return NoChange();
-  }
+  if (!(flags() & kDeoptimizationEnabled)) return NoChange();
 
   // If we are in a try block, don't optimize since the runtime call
   // in the proxy case can throw.
@@ -1087,29 +1205,31 @@
       Handle<JSFunction>::cast(r.right_type()->AsConstant()->Value());
   Handle<SharedFunctionInfo> shared(function->shared(), isolate());
 
-  if (!function->IsConstructor() ||
-      function->map()->has_non_instance_prototype()) {
+  // Make sure the prototype of {function} is the %FunctionPrototype%, and it
+  // already has a meaningful initial map (i.e. we constructed at least one
+  // instance using the constructor {function}).
+  if (function->map()->prototype() != function->native_context()->closure() ||
+      function->map()->has_non_instance_prototype() ||
+      !function->has_initial_map()) {
     return NoChange();
   }
 
-  JSFunction::EnsureHasInitialMap(function);
-  DCHECK(function->has_initial_map());
+  // We can only use the fast case if @@hasInstance was not used so far.
+  if (!isolate()->IsHasInstanceLookupChainIntact()) return NoChange();
+  dependencies()->AssumePropertyCell(factory()->has_instance_protector());
+
   Handle<Map> initial_map(function->initial_map(), isolate());
-  this->dependencies()->AssumeInitialMapCantChange(initial_map);
+  dependencies()->AssumeInitialMapCantChange(initial_map);
   Node* prototype =
       jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
 
-  Node* if_is_smi = nullptr;
-  Node* e_is_smi = nullptr;
   // If the left hand side is an object, no smi check is needed.
-  if (r.left_type()->Maybe(Type::TaggedSigned())) {
-    Node* is_smi = graph()->NewNode(simplified()->ObjectIsSmi(), r.left());
-    Node* branch_is_smi =
-        graph()->NewNode(common()->Branch(BranchHint::kFalse), is_smi, control);
-    if_is_smi = graph()->NewNode(common()->IfTrue(), branch_is_smi);
-    e_is_smi = effect;
-    control = graph()->NewNode(common()->IfFalse(), branch_is_smi);
-  }
+  Node* is_smi = graph()->NewNode(simplified()->ObjectIsSmi(), r.left());
+  Node* branch_is_smi =
+      graph()->NewNode(common()->Branch(BranchHint::kFalse), is_smi, control);
+  Node* if_is_smi = graph()->NewNode(common()->IfTrue(), branch_is_smi);
+  Node* e_is_smi = effect;
+  control = graph()->NewNode(common()->IfFalse(), branch_is_smi);
 
   Node* object_map = effect =
       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
@@ -1175,6 +1295,17 @@
       simplified()->LoadField(AccessBuilder::ForMapPrototype()),
       loop_object_map, loop_effect, control);
 
+  // If not, check if object prototype is the null prototype.
+  Node* null_proto =
+      graph()->NewNode(simplified()->ReferenceEqual(r.right_type()),
+                       object_prototype, jsgraph()->NullConstant());
+  Node* branch_null_proto = graph()->NewNode(
+      common()->Branch(BranchHint::kFalse), null_proto, control);
+  Node* if_null_proto = graph()->NewNode(common()->IfTrue(), branch_null_proto);
+  Node* e_null_proto = effect;
+
+  control = graph()->NewNode(common()->IfFalse(), branch_null_proto);
+
   // Check if object prototype is equal to function prototype.
   Node* eq_proto =
       graph()->NewNode(simplified()->ReferenceEqual(r.right_type()),
@@ -1186,16 +1317,6 @@
 
   control = graph()->NewNode(common()->IfFalse(), branch_eq_proto);
 
-  // If not, check if object prototype is the null prototype.
-  Node* null_proto =
-      graph()->NewNode(simplified()->ReferenceEqual(r.right_type()),
-                       object_prototype, jsgraph()->NullConstant());
-  Node* branch_null_proto = graph()->NewNode(
-      common()->Branch(BranchHint::kFalse), null_proto, control);
-  Node* if_null_proto = graph()->NewNode(common()->IfTrue(), branch_null_proto);
-  Node* e_null_proto = effect;
-
-  control = graph()->NewNode(common()->IfFalse(), branch_null_proto);
   Node* load_object_map = effect =
       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
                        object_prototype, effect, control);
@@ -1215,14 +1336,12 @@
       bool_result_runtime_has_in_proto_chain_case, jsgraph()->TrueConstant(),
       jsgraph()->FalseConstant(), control);
 
-  if (if_is_smi != nullptr) {
-    DCHECK_NOT_NULL(e_is_smi);
-    control = graph()->NewNode(common()->Merge(2), if_is_smi, control);
-    effect =
-        graph()->NewNode(common()->EffectPhi(2), e_is_smi, effect, control);
-    result = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
-                              jsgraph()->FalseConstant(), result, control);
-  }
+  DCHECK_NOT_NULL(e_is_smi);
+  control = graph()->NewNode(common()->Merge(2), if_is_smi, control);
+  effect =
+      graph()->NewNode(common()->EffectPhi(2), e_is_smi, effect, control);
+  result = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
+                            jsgraph()->FalseConstant(), result, control);
 
   ReplaceWithValue(node, result, effect, control);
   return Changed(result);
@@ -1383,9 +1502,6 @@
         Handle<JSFunction>::cast(target_type->AsConstant()->Value());
     Handle<SharedFunctionInfo> shared(function->shared(), isolate());
 
-    // Remove the eager bailout frame state.
-    NodeProperties::RemoveFrameStateInput(node, 1);
-
     // Patch {node} to an indirect call via the {function}s construct stub.
     Callable callable(handle(shared->construct_stub(), isolate()),
                       ConstructStubDescriptor(isolate()));
@@ -1405,9 +1521,6 @@
 
   // Check if {target} is a JSFunction.
   if (target_type->Is(Type::Function())) {
-    // Remove the eager bailout frame state.
-    NodeProperties::RemoveFrameStateInput(node, 1);
-
     // Patch {node} to an indirect call via the ConstructFunction builtin.
     Callable callable = CodeFactory::ConstructFunction(isolate());
     node->RemoveInput(arity + 1);
@@ -1436,9 +1549,9 @@
   Type* target_type = NodeProperties::GetType(target);
   Node* receiver = NodeProperties::GetValueInput(node, 1);
   Type* receiver_type = NodeProperties::GetType(receiver);
-  Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
   Node* effect = NodeProperties::GetEffectInput(node);
   Node* control = NodeProperties::GetControlInput(node);
+  Node* frame_state = NodeProperties::FindFrameStateBefore(node);
 
   // Try to infer receiver {convert_mode} from {receiver} type.
   if (receiver_type->Is(Type::NullOrUndefined())) {
@@ -1476,9 +1589,6 @@
     // Update the effect dependency for the {node}.
     NodeProperties::ReplaceEffectInput(node, effect);
 
-    // Remove the eager bailout frame state.
-    NodeProperties::RemoveFrameStateInput(node, 1);
-
     // Compute flags for the call.
     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
     if (p.tail_call_mode() == TailCallMode::kAllow) {
@@ -1516,9 +1626,6 @@
 
   // Check if {target} is a JSFunction.
   if (target_type->Is(Type::Function())) {
-    // Remove the eager bailout frame state.
-    NodeProperties::RemoveFrameStateInput(node, 1);
-
     // Compute flags for the call.
     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
     if (p.tail_call_mode() == TailCallMode::kAllow) {
@@ -1626,6 +1733,84 @@
   return Changed(node);
 }
 
+Reduction JSTypedLowering::ReduceJSGeneratorStore(Node* node) {
+  DCHECK_EQ(IrOpcode::kJSGeneratorStore, node->opcode());
+  Node* generator = NodeProperties::GetValueInput(node, 0);
+  Node* continuation = NodeProperties::GetValueInput(node, 1);
+  Node* offset = NodeProperties::GetValueInput(node, 2);
+  Node* context = NodeProperties::GetContextInput(node);
+  Node* effect = NodeProperties::GetEffectInput(node);
+  Node* control = NodeProperties::GetControlInput(node);
+  int register_count = OpParameter<int>(node);
+
+  FieldAccess array_field = AccessBuilder::ForJSGeneratorObjectOperandStack();
+  FieldAccess context_field = AccessBuilder::ForJSGeneratorObjectContext();
+  FieldAccess continuation_field =
+      AccessBuilder::ForJSGeneratorObjectContinuation();
+  FieldAccess input_or_debug_pos_field =
+      AccessBuilder::ForJSGeneratorObjectInputOrDebugPos();
+
+  Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field),
+                                          generator, effect, control);
+
+  for (int i = 0; i < register_count; ++i) {
+    Node* value = NodeProperties::GetValueInput(node, 3 + i);
+    effect = graph()->NewNode(
+        simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)), array,
+        value, effect, control);
+  }
+
+  effect = graph()->NewNode(simplified()->StoreField(context_field), generator,
+                            context, effect, control);
+  effect = graph()->NewNode(simplified()->StoreField(continuation_field),
+                            generator, continuation, effect, control);
+  effect = graph()->NewNode(simplified()->StoreField(input_or_debug_pos_field),
+                            generator, offset, effect, control);
+
+  ReplaceWithValue(node, effect, effect, control);
+  return Changed(effect);
+}
+
+Reduction JSTypedLowering::ReduceJSGeneratorRestoreContinuation(Node* node) {
+  DCHECK_EQ(IrOpcode::kJSGeneratorRestoreContinuation, node->opcode());
+  Node* generator = NodeProperties::GetValueInput(node, 0);
+  Node* effect = NodeProperties::GetEffectInput(node);
+  Node* control = NodeProperties::GetControlInput(node);
+
+  FieldAccess continuation_field =
+      AccessBuilder::ForJSGeneratorObjectContinuation();
+
+  Node* continuation = effect = graph()->NewNode(
+      simplified()->LoadField(continuation_field), generator, effect, control);
+  Node* executing = jsgraph()->Constant(JSGeneratorObject::kGeneratorExecuting);
+  effect = graph()->NewNode(simplified()->StoreField(continuation_field),
+                            generator, executing, effect, control);
+
+  ReplaceWithValue(node, continuation, effect, control);
+  return Changed(continuation);
+}
+
+Reduction JSTypedLowering::ReduceJSGeneratorRestoreRegister(Node* node) {
+  DCHECK_EQ(IrOpcode::kJSGeneratorRestoreRegister, node->opcode());
+  Node* generator = NodeProperties::GetValueInput(node, 0);
+  Node* effect = NodeProperties::GetEffectInput(node);
+  Node* control = NodeProperties::GetControlInput(node);
+  int index = OpParameter<int>(node);
+
+  FieldAccess array_field = AccessBuilder::ForJSGeneratorObjectOperandStack();
+  FieldAccess element_field = AccessBuilder::ForFixedArraySlot(index);
+
+  Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field),
+                                          generator, effect, control);
+  Node* element = effect = graph()->NewNode(
+      simplified()->LoadField(element_field), array, effect, control);
+  Node* stale = jsgraph()->StaleRegisterConstant();
+  effect = graph()->NewNode(simplified()->StoreField(element_field), array,
+                            stale, effect, control);
+
+  ReplaceWithValue(node, element, effect, control);
+  return Changed(element);
+}
 
 Reduction JSTypedLowering::ReduceSelect(Node* node) {
   DCHECK_EQ(IrOpcode::kSelect, node->opcode());
@@ -1662,31 +1847,38 @@
   // result value and can simply replace the node if it's eliminable.
   if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) &&
       node->op()->HasProperty(Operator::kEliminatable)) {
+    // We can only constant-fold nodes here, that are known to not cause any
+    // side-effect, may it be a JavaScript observable side-effect or a possible
+    // eager deoptimization exit (i.e. {node} has an operator that doesn't have
+    // the Operator::kNoDeopt property).
     Type* upper = NodeProperties::GetType(node);
-    if (upper->IsConstant()) {
-      Node* replacement = jsgraph()->Constant(upper->AsConstant()->Value());
-      ReplaceWithValue(node, replacement);
-      return Changed(replacement);
-    } else if (upper->Is(Type::MinusZero())) {
-      Node* replacement = jsgraph()->Constant(factory()->minus_zero_value());
-      ReplaceWithValue(node, replacement);
-      return Changed(replacement);
-    } else if (upper->Is(Type::NaN())) {
-      Node* replacement = jsgraph()->NaNConstant();
-      ReplaceWithValue(node, replacement);
-      return Changed(replacement);
-    } else if (upper->Is(Type::Null())) {
-      Node* replacement = jsgraph()->NullConstant();
-      ReplaceWithValue(node, replacement);
-      return Changed(replacement);
-    } else if (upper->Is(Type::PlainNumber()) && upper->Min() == upper->Max()) {
-      Node* replacement = jsgraph()->Constant(upper->Min());
-      ReplaceWithValue(node, replacement);
-      return Changed(replacement);
-    } else if (upper->Is(Type::Undefined())) {
-      Node* replacement = jsgraph()->UndefinedConstant();
-      ReplaceWithValue(node, replacement);
-      return Changed(replacement);
+    if (upper->IsInhabited()) {
+      if (upper->IsConstant()) {
+        Node* replacement = jsgraph()->Constant(upper->AsConstant()->Value());
+        ReplaceWithValue(node, replacement);
+        return Changed(replacement);
+      } else if (upper->Is(Type::MinusZero())) {
+        Node* replacement = jsgraph()->Constant(factory()->minus_zero_value());
+        ReplaceWithValue(node, replacement);
+        return Changed(replacement);
+      } else if (upper->Is(Type::NaN())) {
+        Node* replacement = jsgraph()->NaNConstant();
+        ReplaceWithValue(node, replacement);
+        return Changed(replacement);
+      } else if (upper->Is(Type::Null())) {
+        Node* replacement = jsgraph()->NullConstant();
+        ReplaceWithValue(node, replacement);
+        return Changed(replacement);
+      } else if (upper->Is(Type::PlainNumber()) &&
+                 upper->Min() == upper->Max()) {
+        Node* replacement = jsgraph()->Constant(upper->Min());
+        ReplaceWithValue(node, replacement);
+        return Changed(replacement);
+      } else if (upper->Is(Type::Undefined())) {
+        Node* replacement = jsgraph()->UndefinedConstant();
+        ReplaceWithValue(node, replacement);
+        return Changed(replacement);
+      }
     }
   }
   switch (node->opcode()) {
@@ -1719,11 +1911,11 @@
     case IrOpcode::kJSAdd:
       return ReduceJSAdd(node);
     case IrOpcode::kJSSubtract:
-      return ReduceNumberBinop(node, simplified()->NumberSubtract());
+      return ReduceJSSubtract(node);
     case IrOpcode::kJSMultiply:
-      return ReduceNumberBinop(node, simplified()->NumberMultiply());
+      return ReduceJSMultiply(node);
     case IrOpcode::kJSDivide:
-      return ReduceNumberBinop(node, simplified()->NumberDivide());
+      return ReduceJSDivide(node);
     case IrOpcode::kJSModulus:
       return ReduceJSModulus(node);
     case IrOpcode::kJSToBoolean:
@@ -1762,6 +1954,12 @@
       return ReduceJSForInNext(node);
     case IrOpcode::kJSForInStep:
       return ReduceJSForInStep(node);
+    case IrOpcode::kJSGeneratorStore:
+      return ReduceJSGeneratorStore(node);
+    case IrOpcode::kJSGeneratorRestoreContinuation:
+      return ReduceJSGeneratorRestoreContinuation(node);
+    case IrOpcode::kJSGeneratorRestoreRegister:
+      return ReduceJSGeneratorRestoreRegister(node);
     case IrOpcode::kSelect:
       return ReduceSelect(node);
     default:
@@ -1777,6 +1975,14 @@
                           jsgraph()->Int32Constant(rhs));
 }
 
+Node* JSTypedLowering::EmptyFrameState() {
+  return graph()->NewNode(
+      common()->FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(),
+                           nullptr),
+      jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(),
+      jsgraph()->EmptyStateValues(), jsgraph()->NoContextConstant(),
+      jsgraph()->UndefinedConstant(), graph()->start());
+}
 
 Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); }
 
diff --git a/src/compiler/js-typed-lowering.h b/src/compiler/js-typed-lowering.h
index 1517871..a370b7a 100644
--- a/src/compiler/js-typed-lowering.h
+++ b/src/compiler/js-typed-lowering.h
@@ -36,6 +36,7 @@
     kNoFlags = 0u,
     kDeoptimizationEnabled = 1u << 0,
     kDisableBinaryOpReduction = 1u << 1,
+    kTypeFeedbackEnabled = 1u << 2,
   };
   typedef base::Flags<Flag> Flags;
 
@@ -59,6 +60,7 @@
   Reduction ReduceJSInstanceOf(Node* node);
   Reduction ReduceJSLoadContext(Node* node);
   Reduction ReduceJSStoreContext(Node* node);
+  Reduction ReduceJSEqualTypeOf(Node* node, bool invert);
   Reduction ReduceJSEqual(Node* node, bool invert);
   Reduction ReduceJSStrictEqual(Node* node, bool invert);
   Reduction ReduceJSToBoolean(Node* node);
@@ -75,14 +77,20 @@
   Reduction ReduceJSForInDone(Node* node);
   Reduction ReduceJSForInNext(Node* node);
   Reduction ReduceJSForInStep(Node* node);
+  Reduction ReduceJSGeneratorStore(Node* node);
+  Reduction ReduceJSGeneratorRestoreContinuation(Node* node);
+  Reduction ReduceJSGeneratorRestoreRegister(Node* node);
   Reduction ReduceSelect(Node* node);
-  Reduction ReduceNumberBinop(Node* node, const Operator* numberOp);
+  Reduction ReduceJSSubtract(Node* node);
+  Reduction ReduceJSDivide(Node* node);
   Reduction ReduceInt32Binop(Node* node, const Operator* intOp);
   Reduction ReduceUI32Shift(Node* node, Signedness left_signedness,
                             const Operator* shift_op);
 
   Node* Word32Shl(Node* const lhs, int32_t const rhs);
 
+  Node* EmptyFrameState();
+
   Factory* factory() const;
   Graph* graph() const;
   JSGraph* jsgraph() const { return jsgraph_; }
diff --git a/src/compiler/linkage.cc b/src/compiler/linkage.cc
index 105bd35..c3b68d6 100644
--- a/src/compiler/linkage.cc
+++ b/src/compiler/linkage.cc
@@ -88,7 +88,7 @@
 
 bool CallDescriptor::CanTailCall(const Node* node,
                                  int* stack_param_delta) const {
-  CallDescriptor const* other = OpParameter<CallDescriptor const*>(node);
+  CallDescriptor const* other = CallDescriptorOf(node->op());
   size_t current_input = 0;
   size_t other_input = 0;
   *stack_param_delta = 0;
@@ -112,19 +112,12 @@
     ++current_input;
     ++other_input;
   }
-  return HasSameReturnLocationsAs(OpParameter<CallDescriptor const*>(node));
+  return HasSameReturnLocationsAs(CallDescriptorOf(node->op()));
 }
 
 
 CallDescriptor* Linkage::ComputeIncoming(Zone* zone, CompilationInfo* info) {
   DCHECK(!info->IsStub());
-  if (info->has_literal()) {
-    // If we already have the function literal, use the number of parameters
-    // plus the receiver.
-    return GetJSCallDescriptor(zone, info->is_osr(),
-                               1 + info->literal()->parameter_count(),
-                               CallDescriptor::kNoFlags);
-  }
   if (!info->closure().is_null()) {
     // If we are compiling a JS function, use a JS call descriptor,
     // plus the receiver.
@@ -138,19 +131,19 @@
 
 
 // static
-int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
+bool Linkage::NeedsFrameStateInput(Runtime::FunctionId function) {
   // Most runtime functions need a FrameState. A few chosen ones that we know
   // not to call into arbitrary JavaScript, not to throw, and not to deoptimize
   // are blacklisted here and can be called without a FrameState.
   switch (function) {
+    case Runtime::kAbort:
     case Runtime::kAllocateInTargetSpace:
     case Runtime::kCreateIterResultObject:
-    case Runtime::kDefineDataPropertyInLiteral:
     case Runtime::kDefineGetterPropertyUnchecked:  // TODO(jarin): Is it safe?
     case Runtime::kDefineSetterPropertyUnchecked:  // TODO(jarin): Is it safe?
-    case Runtime::kFinalizeClassDefinition:        // TODO(conradw): Is it safe?
     case Runtime::kForInDone:
     case Runtime::kForInStep:
+    case Runtime::kGeneratorGetContinuation:
     case Runtime::kGetSuperConstructor:
     case Runtime::kIsFunction:
     case Runtime::kNewClosure:
@@ -166,14 +159,18 @@
     case Runtime::kStringLessThanOrEqual:
     case Runtime::kStringGreaterThan:
     case Runtime::kStringGreaterThanOrEqual:
+    case Runtime::kToFastProperties:  // TODO(conradw): Is it safe?
     case Runtime::kTraceEnter:
     case Runtime::kTraceExit:
-      return 0;
+      return false;
+    case Runtime::kInlineCall:
+    case Runtime::kInlineDeoptimizeNow:
     case Runtime::kInlineGetPrototype:
     case Runtime::kInlineNewObject:
     case Runtime::kInlineRegExpConstructResult:
     case Runtime::kInlineRegExpExec:
     case Runtime::kInlineSubString:
+    case Runtime::kInlineThrowNotDateError:
     case Runtime::kInlineToInteger:
     case Runtime::kInlineToLength:
     case Runtime::kInlineToName:
@@ -183,11 +180,7 @@
     case Runtime::kInlineToPrimitive_Number:
     case Runtime::kInlineToPrimitive_String:
     case Runtime::kInlineToString:
-      return 1;
-    case Runtime::kInlineCall:
-    case Runtime::kInlineDeoptimizeNow:
-    case Runtime::kInlineThrowNotDateError:
-      return 2;
+      return true;
     default:
       break;
   }
@@ -195,9 +188,9 @@
   // Most inlined runtime functions (except the ones listed above) can be called
   // without a FrameState or will be lowered by JSIntrinsicLowering internally.
   const Runtime::Function* const f = Runtime::FunctionForId(function);
-  if (f->intrinsic_type == Runtime::IntrinsicType::INLINE) return 0;
+  if (f->intrinsic_type == Runtime::IntrinsicType::INLINE) return false;
 
-  return 1;
+  return true;
 }
 
 
@@ -260,7 +253,7 @@
   locations.AddParam(regloc(kContextRegister));
   types.AddParam(MachineType::AnyTagged());
 
-  if (Linkage::FrameStateInputCount(function_id) == 0) {
+  if (!Linkage::NeedsFrameStateInput(function_id)) {
     flags = static_cast<CallDescriptor::Flags>(
         flags & ~CallDescriptor::kNeedsFrameState);
   }
@@ -411,6 +404,78 @@
       descriptor.DebugName(isolate));
 }
 
+// static
+CallDescriptor* Linkage::GetAllocateCallDescriptor(Zone* zone) {
+  LocationSignature::Builder locations(zone, 1, 1);
+  MachineSignature::Builder types(zone, 1, 1);
+
+  locations.AddParam(regloc(kAllocateSizeRegister));
+  types.AddParam(MachineType::Int32());
+
+  locations.AddReturn(regloc(kReturnRegister0));
+  types.AddReturn(MachineType::AnyTagged());
+
+  // The target for allocate calls is a code object.
+  MachineType target_type = MachineType::AnyTagged();
+  LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
+  return new (zone) CallDescriptor(     // --
+      CallDescriptor::kCallCodeObject,  // kind
+      target_type,                      // target MachineType
+      target_loc,                       // target location
+      types.Build(),                    // machine_sig
+      locations.Build(),                // location_sig
+      0,                                // stack_parameter_count
+      Operator::kNoThrow,               // properties
+      kNoCalleeSaved,                   // callee-saved registers
+      kNoCalleeSaved,                   // callee-saved fp
+      CallDescriptor::kCanUseRoots,     // flags
+      "Allocate");
+}
+
+// static
+CallDescriptor* Linkage::GetBytecodeDispatchCallDescriptor(
+    Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,
+    int stack_parameter_count) {
+  const int register_parameter_count = descriptor.GetRegisterParameterCount();
+  const int parameter_count = register_parameter_count + stack_parameter_count;
+
+  LocationSignature::Builder locations(zone, 0, parameter_count);
+  MachineSignature::Builder types(zone, 0, parameter_count);
+
+  // Add parameters in registers and on the stack.
+  for (int i = 0; i < parameter_count; i++) {
+    if (i < register_parameter_count) {
+      // The first parameters go in registers.
+      Register reg = descriptor.GetRegisterParameter(i);
+      Representation rep =
+          RepresentationFromType(descriptor.GetParameterType(i));
+      locations.AddParam(regloc(reg));
+      types.AddParam(reptyp(rep));
+    } else {
+      // The rest of the parameters go on the stack.
+      int stack_slot = i - register_parameter_count - stack_parameter_count;
+      locations.AddParam(LinkageLocation::ForCallerFrameSlot(stack_slot));
+      types.AddParam(MachineType::AnyTagged());
+    }
+  }
+
+  // The target for interpreter dispatches is a code entry address.
+  MachineType target_type = MachineType::Pointer();
+  LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
+  return new (zone) CallDescriptor(            // --
+      CallDescriptor::kCallAddress,            // kind
+      target_type,                             // target MachineType
+      target_loc,                              // target location
+      types.Build(),                           // machine_sig
+      locations.Build(),                       // location_sig
+      stack_parameter_count,                   // stack_parameter_count
+      Operator::kNoProperties,                 // properties
+      kNoCalleeSaved,                          // callee-saved registers
+      kNoCalleeSaved,                          // callee-saved fp
+      CallDescriptor::kCanUseRoots |           // flags
+          CallDescriptor::kSupportsTailCalls,  // flags
+      descriptor.DebugName(isolate));
+}
 
 LinkageLocation Linkage::GetOsrValueLocation(int index) const {
   CHECK(incoming_->IsJSFunctionCall());
diff --git a/src/compiler/linkage.h b/src/compiler/linkage.h
index a0434f8..8596327 100644
--- a/src/compiler/linkage.h
+++ b/src/compiler/linkage.h
@@ -152,20 +152,19 @@
   enum Flag {
     kNoFlags = 0u,
     kNeedsFrameState = 1u << 0,
-    kPatchableCallSite = 1u << 1,
-    kNeedsNopAfterCall = 1u << 2,
-    kHasExceptionHandler = 1u << 3,
-    kHasLocalCatchHandler = 1u << 4,
-    kSupportsTailCalls = 1u << 5,
-    kCanUseRoots = 1u << 6,
+    kHasExceptionHandler = 1u << 1,
+    kHasLocalCatchHandler = 1u << 2,
+    kSupportsTailCalls = 1u << 3,
+    kCanUseRoots = 1u << 4,
     // (arm64 only) native stack should be used for arguments.
-    kUseNativeStack = 1u << 7,
+    kUseNativeStack = 1u << 5,
     // (arm64 only) call instruction has to restore JSSP or CSP.
-    kRestoreJSSP = 1u << 8,
-    kRestoreCSP = 1u << 9,
+    kRestoreJSSP = 1u << 6,
+    kRestoreCSP = 1u << 7,
     // Causes the code generator to initialize the root register.
-    kInitializeRootRegister = 1u << 10,
-    kPatchableCallSiteWithNop = kPatchableCallSite | kNeedsNopAfterCall
+    kInitializeRootRegister = 1u << 8,
+    // Does not ever try to allocate space on our heap.
+    kNoAllocate = 1u << 9
   };
   typedef base::Flags<Flag> Flags;
 
@@ -304,10 +303,11 @@
 // representing the architecture-specific location. The following call node
 // layouts are supported (where {n} is the number of value inputs):
 //
-//                  #0          #1     #2     #3     [...]             #n
-// Call[CodeStub]   code,       arg 1, arg 2, arg 3, [...],            context
-// Call[JSFunction] function,   rcvr,  arg 1, arg 2, [...], new, #arg, context
-// Call[Runtime]    CEntryStub, arg 1, arg 2, arg 3, [...], fun, #arg, context
+//                        #0          #1     #2     [...]             #n
+// Call[CodeStub]         code,       arg 1, arg 2, [...],            context
+// Call[JSFunction]       function,   rcvr,  arg 1, [...], new, #arg, context
+// Call[Runtime]          CEntryStub, arg 1, arg 2, [...], fun, #arg, context
+// Call[BytecodeDispatch] address,    arg 1, arg 2, [...]
 class Linkage : public ZoneObject {
  public:
   explicit Linkage(CallDescriptor* incoming) : incoming_(incoming) {}
@@ -332,6 +332,11 @@
       MachineType return_type = MachineType::AnyTagged(),
       size_t return_count = 1);
 
+  static CallDescriptor* GetAllocateCallDescriptor(Zone* zone);
+  static CallDescriptor* GetBytecodeDispatchCallDescriptor(
+      Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,
+      int stack_parameter_count);
+
   // Creates a call descriptor for simplified C calls that is appropriate
   // for the host platform. This simplified calling convention only supports
   // integers and pointers of one word size each, i.e. no floating point,
@@ -363,7 +368,7 @@
   bool ParameterHasSecondaryLocation(int index) const;
   LinkageLocation GetParameterSecondaryLocation(int index) const;
 
-  static int FrameStateInputCount(Runtime::FunctionId function);
+  static bool NeedsFrameStateInput(Runtime::FunctionId function);
 
   // Get the location where an incoming OSR value is stored.
   LinkageLocation GetOsrValueLocation(int index) const;
diff --git a/src/compiler/load-elimination.cc b/src/compiler/load-elimination.cc
index e19368d..a451cfc 100644
--- a/src/compiler/load-elimination.cc
+++ b/src/compiler/load-elimination.cc
@@ -4,7 +4,6 @@
 
 #include "src/compiler/load-elimination.h"
 
-#include "src/compiler/common-operator.h"
 #include "src/compiler/graph.h"
 #include "src/compiler/node-properties.h"
 #include "src/compiler/simplified-operator.h"
@@ -34,8 +33,9 @@
        effect = NodeProperties::GetEffectInput(effect)) {
     switch (effect->opcode()) {
       case IrOpcode::kLoadField: {
+        FieldAccess const effect_access = FieldAccessOf(effect->op());
         if (object == NodeProperties::GetValueInput(effect, 0) &&
-            access == FieldAccessOf(effect->op())) {
+            access == effect_access && effect_access.type->Is(access.type)) {
           Node* const value = effect;
           ReplaceWithValue(node, value);
           return Replace(value);
@@ -56,8 +56,8 @@
               return Replace(value);
             } else {
               Node* renamed = graph()->NewNode(
-                  common()->Guard(Type::Intersect(stored_value_type, load_type,
-                                                  graph()->zone())),
+                  simplified()->TypeGuard(Type::Intersect(
+                      stored_value_type, load_type, graph()->zone())),
                   value, NodeProperties::GetControlInput(node));
               ReplaceWithValue(node, renamed);
               return Replace(renamed);
diff --git a/src/compiler/load-elimination.h b/src/compiler/load-elimination.h
index 92c6dd0..4a1323b 100644
--- a/src/compiler/load-elimination.h
+++ b/src/compiler/load-elimination.h
@@ -11,25 +11,26 @@
 namespace internal {
 namespace compiler {
 
-class CommonOperatorBuilder;
 class Graph;
+class SimplifiedOperatorBuilder;
 
 class LoadElimination final : public AdvancedReducer {
  public:
   explicit LoadElimination(Editor* editor, Graph* graph,
-                           CommonOperatorBuilder* common)
-      : AdvancedReducer(editor), graph_(graph), common_(common) {}
+                           SimplifiedOperatorBuilder* simplified)
+      : AdvancedReducer(editor), graph_(graph), simplified_(simplified) {}
   ~LoadElimination() final;
 
   Reduction Reduce(Node* node) final;
 
  private:
-  CommonOperatorBuilder* common() const { return common_; }
-  Graph* graph() { return graph_; }
+  SimplifiedOperatorBuilder* simplified() const { return simplified_; }
+  Graph* graph() const { return graph_; }
 
   Reduction ReduceLoadField(Node* node);
-  Graph* graph_;
-  CommonOperatorBuilder* common_;
+
+  Graph* const graph_;
+  SimplifiedOperatorBuilder* const simplified_;
 };
 
 }  // namespace compiler
diff --git a/src/compiler/machine-operator-reducer.cc b/src/compiler/machine-operator-reducer.cc
index 19ea062..b566f48 100644
--- a/src/compiler/machine-operator-reducer.cc
+++ b/src/compiler/machine-operator-reducer.cc
@@ -6,6 +6,7 @@
 
 #include "src/base/bits.h"
 #include "src/base/division-by-constant.h"
+#include "src/base/ieee754.h"
 #include "src/codegen.h"
 #include "src/compiler/diamond.h"
 #include "src/compiler/graph.h"
@@ -152,14 +153,8 @@
     }
     case IrOpcode::kWord32Shl:
       return ReduceWord32Shl(node);
-    case IrOpcode::kWord32Shr: {
-      Uint32BinopMatcher m(node);
-      if (m.right().Is(0)) return Replace(m.left().node());  // x >>> 0 => x
-      if (m.IsFoldable()) {                                  // K >>> K => K
-        return ReplaceInt32(m.left().Value() >> m.right().Value());
-      }
-      return ReduceWord32Shifts(node);
-    }
+    case IrOpcode::kWord32Shr:
+      return ReduceWord32Shr(node);
     case IrOpcode::kWord32Sar:
       return ReduceWord32Sar(node);
     case IrOpcode::kWord32Ror: {
@@ -239,18 +234,6 @@
       if (m.IsFoldable()) {  // K < K => K
         return ReplaceBool(m.left().Value() < m.right().Value());
       }
-      if (m.left().IsInt32Sub() && m.right().Is(0)) {  // x - y < 0 => x < y
-        Int32BinopMatcher msub(m.left().node());
-        node->ReplaceInput(0, msub.left().node());
-        node->ReplaceInput(1, msub.right().node());
-        return Changed(node);
-      }
-      if (m.left().Is(0) && m.right().IsInt32Sub()) {  // 0 < x - y => y < x
-        Int32BinopMatcher msub(m.right().node());
-        node->ReplaceInput(0, msub.right().node());
-        node->ReplaceInput(1, msub.left().node());
-        return Changed(node);
-      }
       if (m.LeftEqualsRight()) return ReplaceBool(false);  // x < x => false
       break;
     }
@@ -259,18 +242,6 @@
       if (m.IsFoldable()) {  // K <= K => K
         return ReplaceBool(m.left().Value() <= m.right().Value());
       }
-      if (m.left().IsInt32Sub() && m.right().Is(0)) {  // x - y <= 0 => x <= y
-        Int32BinopMatcher msub(m.left().node());
-        node->ReplaceInput(0, msub.left().node());
-        node->ReplaceInput(1, msub.right().node());
-        return Changed(node);
-      }
-      if (m.left().Is(0) && m.right().IsInt32Sub()) {  // 0 <= x - y => y <= x
-        Int32BinopMatcher msub(m.right().node());
-        node->ReplaceInput(0, msub.right().node());
-        node->ReplaceInput(1, msub.left().node());
-        return Changed(node);
-      }
       if (m.LeftEqualsRight()) return ReplaceBool(true);  // x <= x => true
       break;
     }
@@ -382,6 +353,80 @@
       }
       break;
     }
+    case IrOpcode::kFloat64Atan: {
+      Float64Matcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceFloat64(base::ieee754::atan(m.Value()));
+      break;
+    }
+    case IrOpcode::kFloat64Atan2: {
+      Float64BinopMatcher m(node);
+      if (m.right().IsNaN()) {
+        return Replace(m.right().node());
+      }
+      if (m.left().IsNaN()) {
+        return Replace(m.left().node());
+      }
+      if (m.IsFoldable()) {
+        return ReplaceFloat64(
+            base::ieee754::atan2(m.left().Value(), m.right().Value()));
+      }
+      break;
+    }
+    case IrOpcode::kFloat64Atanh: {
+      Float64Matcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceFloat64(base::ieee754::atanh(m.Value()));
+      break;
+    }
+    case IrOpcode::kFloat64Cos: {
+      Float64Matcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceFloat64(base::ieee754::cos(m.Value()));
+      break;
+    }
+    case IrOpcode::kFloat64Exp: {
+      Float64Matcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceFloat64(base::ieee754::exp(m.Value()));
+      break;
+    }
+    case IrOpcode::kFloat64Expm1: {
+      Float64Matcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceFloat64(base::ieee754::expm1(m.Value()));
+      break;
+    }
+    case IrOpcode::kFloat64Log: {
+      Float64Matcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceFloat64(base::ieee754::log(m.Value()));
+      break;
+    }
+    case IrOpcode::kFloat64Log1p: {
+      Float64Matcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceFloat64(base::ieee754::log1p(m.Value()));
+      break;
+    }
+    case IrOpcode::kFloat64Log2: {
+      Float64Matcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceFloat64(base::ieee754::log2(m.Value()));
+      break;
+    }
+    case IrOpcode::kFloat64Log10: {
+      Float64Matcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceFloat64(base::ieee754::log10(m.Value()));
+      break;
+    }
+    case IrOpcode::kFloat64Cbrt: {
+      Float64Matcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceFloat64(base::ieee754::cbrt(m.Value()));
+      break;
+    }
+    case IrOpcode::kFloat64Sin: {
+      Float64Matcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceFloat64(base::ieee754::sin(m.Value()));
+      break;
+    }
+    case IrOpcode::kFloat64Tan: {
+      Float64Matcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceFloat64(base::ieee754::tan(m.Value()));
+      break;
+    }
     case IrOpcode::kChangeFloat32ToFloat64: {
       Float32Matcher m(node->InputAt(0));
       if (m.HasValue()) return ReplaceFloat64(m.Value());
@@ -419,8 +464,12 @@
       if (m.HasValue()) return ReplaceInt64(static_cast<uint64_t>(m.Value()));
       break;
     }
-    case IrOpcode::kTruncateFloat64ToInt32:
-      return ReduceTruncateFloat64ToInt32(node);
+    case IrOpcode::kTruncateFloat64ToWord32: {
+      Float64Matcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
+      if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
+      return NoChange();
+    }
     case IrOpcode::kTruncateInt64ToInt32: {
       Int64Matcher m(node->InputAt(0));
       if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
@@ -433,11 +482,18 @@
       if (m.IsChangeFloat32ToFloat64()) return Replace(m.node()->InputAt(0));
       break;
     }
+    case IrOpcode::kRoundFloat64ToInt32: {
+      Float64Matcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
+      if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
+      break;
+    }
     case IrOpcode::kFloat64InsertLowWord32:
       return ReduceFloat64InsertLowWord32(node);
     case IrOpcode::kFloat64InsertHighWord32:
       return ReduceFloat64InsertHighWord32(node);
     case IrOpcode::kStore:
+    case IrOpcode::kCheckedStore:
       return ReduceStore(node);
     case IrOpcode::kFloat64Equal:
     case IrOpcode::kFloat64LessThan:
@@ -645,41 +701,20 @@
 }
 
 
-Reduction MachineOperatorReducer::ReduceTruncateFloat64ToInt32(Node* node) {
-  Float64Matcher m(node->InputAt(0));
-  if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
-  if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
-  if (m.IsPhi()) {
-    Node* const phi = m.node();
-    DCHECK_EQ(MachineRepresentation::kFloat64, PhiRepresentationOf(phi->op()));
-    if (phi->OwnedBy(node)) {
-      // TruncateFloat64ToInt32[mode](Phi[Float64](x1,...,xn))
-      //   => Phi[Int32](TruncateFloat64ToInt32[mode](x1),
-      //                 ...,
-      //                 TruncateFloat64ToInt32[mode](xn))
-      const int value_input_count = phi->InputCount() - 1;
-      for (int i = 0; i < value_input_count; ++i) {
-        Node* input = graph()->NewNode(node->op(), phi->InputAt(i));
-        // TODO(bmeurer): Reschedule input for reduction once we have Revisit()
-        // instead of recursing into ReduceTruncateFloat64ToInt32() here.
-        Reduction reduction = ReduceTruncateFloat64ToInt32(input);
-        if (reduction.Changed()) input = reduction.replacement();
-        phi->ReplaceInput(i, input);
-      }
-      NodeProperties::ChangeOp(
-          phi,
-          common()->Phi(MachineRepresentation::kWord32, value_input_count));
-      return Replace(phi);
-    }
-  }
-  return NoChange();
-}
-
-
 Reduction MachineOperatorReducer::ReduceStore(Node* node) {
-  MachineRepresentation const rep =
-      StoreRepresentationOf(node->op()).representation();
-  Node* const value = node->InputAt(2);
+  NodeMatcher nm(node);
+  MachineRepresentation rep;
+  int value_input;
+  if (nm.IsCheckedStore()) {
+    rep = CheckedStoreRepresentationOf(node->op());
+    value_input = 3;
+  } else {
+    rep = StoreRepresentationOf(node->op()).representation();
+    value_input = 2;
+  }
+
+  Node* const value = node->InputAt(value_input);
+
   switch (value->opcode()) {
     case IrOpcode::kWord32And: {
       Uint32BinopMatcher m(value);
@@ -687,7 +722,7 @@
                                     (m.right().Value() & 0xff) == 0xff) ||
                                    (rep == MachineRepresentation::kWord16 &&
                                     (m.right().Value() & 0xffff) == 0xffff))) {
-        node->ReplaceInput(2, m.left().node());
+        node->ReplaceInput(value_input, m.left().node());
         return Changed(node);
       }
       break;
@@ -700,7 +735,7 @@
                                       m.right().IsInRange(1, 16)))) {
         Int32BinopMatcher mleft(m.left().node());
         if (mleft.right().Is(m.right().Value())) {
-          node->ReplaceInput(2, mleft.left().node());
+          node->ReplaceInput(value_input, mleft.left().node());
           return Changed(node);
         }
       }
@@ -795,6 +830,25 @@
   return ReduceWord32Shifts(node);
 }
 
+Reduction MachineOperatorReducer::ReduceWord32Shr(Node* node) {
+  Uint32BinopMatcher m(node);
+  if (m.right().Is(0)) return Replace(m.left().node());  // x >>> 0 => x
+  if (m.IsFoldable()) {                                  // K >>> K => K
+    return ReplaceInt32(m.left().Value() >> m.right().Value());
+  }
+  if (m.left().IsWord32And() && m.right().HasValue()) {
+    Uint32BinopMatcher mleft(m.left().node());
+    if (mleft.right().HasValue()) {
+      uint32_t shift = m.right().Value() & 0x1f;
+      uint32_t mask = mleft.right().Value();
+      if ((mask >> shift) == 0) {
+        // (m >>> s) == 0 implies ((x & m) >>> s) == 0
+        return ReplaceInt32(0);
+      }
+    }
+  }
+  return ReduceWord32Shifts(node);
+}
 
 Reduction MachineOperatorReducer::ReduceWord32Sar(Node* node) {
   Int32BinopMatcher m(node);
diff --git a/src/compiler/machine-operator-reducer.h b/src/compiler/machine-operator-reducer.h
index 7f8ff1a..e44521e 100644
--- a/src/compiler/machine-operator-reducer.h
+++ b/src/compiler/machine-operator-reducer.h
@@ -70,11 +70,11 @@
   Reduction ReduceUint32Div(Node* node);
   Reduction ReduceInt32Mod(Node* node);
   Reduction ReduceUint32Mod(Node* node);
-  Reduction ReduceTruncateFloat64ToInt32(Node* node);
   Reduction ReduceStore(Node* node);
   Reduction ReduceProjection(size_t index, Node* node);
   Reduction ReduceWord32Shifts(Node* node);
   Reduction ReduceWord32Shl(Node* node);
+  Reduction ReduceWord32Shr(Node* node);
   Reduction ReduceWord32Sar(Node* node);
   Reduction ReduceWord32And(Node* node);
   Reduction ReduceWord32Or(Node* node);
diff --git a/src/compiler/machine-operator.cc b/src/compiler/machine-operator.cc
index 6a506d2..3662d0a 100644
--- a/src/compiler/machine-operator.cc
+++ b/src/compiler/machine-operator.cc
@@ -12,40 +12,6 @@
 namespace internal {
 namespace compiler {
 
-std::ostream& operator<<(std::ostream& os, TruncationMode mode) {
-  switch (mode) {
-    case TruncationMode::kJavaScript:
-      return os << "JavaScript";
-    case TruncationMode::kRoundToZero:
-      return os << "RoundToZero";
-  }
-  UNREACHABLE();
-  return os;
-}
-
-
-TruncationMode TruncationModeOf(Operator const* op) {
-  DCHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, op->opcode());
-  return OpParameter<TruncationMode>(op);
-}
-
-
-std::ostream& operator<<(std::ostream& os, WriteBarrierKind kind) {
-  switch (kind) {
-    case kNoWriteBarrier:
-      return os << "NoWriteBarrier";
-    case kMapWriteBarrier:
-      return os << "MapWriteBarrier";
-    case kPointerWriteBarrier:
-      return os << "PointerWriteBarrier";
-    case kFullWriteBarrier:
-      return os << "FullWriteBarrier";
-  }
-  UNREACHABLE();
-  return os;
-}
-
-
 bool operator==(StoreRepresentation lhs, StoreRepresentation rhs) {
   return lhs.representation() == rhs.representation() &&
          lhs.write_barrier_kind() == rhs.write_barrier_kind();
@@ -69,7 +35,8 @@
 
 
 LoadRepresentation LoadRepresentationOf(Operator const* op) {
-  DCHECK_EQ(IrOpcode::kLoad, op->opcode());
+  DCHECK(IrOpcode::kLoad == op->opcode() ||
+         IrOpcode::kAtomicLoad == op->opcode());
   return OpParameter<LoadRepresentation>(op);
 }
 
@@ -96,6 +63,11 @@
   return OpParameter<MachineRepresentation>(op);
 }
 
+MachineRepresentation AtomicStoreRepresentationOf(Operator const* op) {
+  DCHECK_EQ(IrOpcode::kAtomicStore, op->opcode());
+  return OpParameter<MachineRepresentation>(op);
+}
+
 #define PURE_OP_LIST(V)                                                       \
   V(Word32And, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)      \
   V(Word32Or, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
@@ -116,10 +88,7 @@
   V(Word64Clz, Operator::kNoProperties, 1, 0, 1)                              \
   V(Word64Equal, Operator::kCommutative, 2, 0, 1)                             \
   V(Int32Add, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
-  V(Int32AddWithOverflow, Operator::kAssociative | Operator::kCommutative, 2, \
-    0, 2)                                                                     \
   V(Int32Sub, Operator::kNoProperties, 2, 0, 1)                               \
-  V(Int32SubWithOverflow, Operator::kNoProperties, 2, 0, 2)                   \
   V(Int32Mul, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
   V(Int32MulHigh, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)   \
   V(Int32Div, Operator::kNoProperties, 2, 1, 1)                               \
@@ -132,10 +101,7 @@
   V(Uint32Mod, Operator::kNoProperties, 2, 1, 1)                              \
   V(Uint32MulHigh, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)  \
   V(Int64Add, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
-  V(Int64AddWithOverflow, Operator::kAssociative | Operator::kCommutative, 2, \
-    0, 2)                                                                     \
   V(Int64Sub, Operator::kNoProperties, 2, 0, 1)                               \
-  V(Int64SubWithOverflow, Operator::kNoProperties, 2, 0, 2)                   \
   V(Int64Mul, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
   V(Int64Div, Operator::kNoProperties, 2, 1, 1)                               \
   V(Int64Mod, Operator::kNoProperties, 2, 1, 1)                               \
@@ -145,6 +111,8 @@
   V(Uint64Mod, Operator::kNoProperties, 2, 1, 1)                              \
   V(Uint64LessThan, Operator::kNoProperties, 2, 0, 1)                         \
   V(Uint64LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                  \
+  V(BitcastWordToTagged, Operator::kNoProperties, 1, 0, 1)                    \
+  V(TruncateFloat64ToWord32, Operator::kNoProperties, 1, 0, 1)                \
   V(ChangeFloat32ToFloat64, Operator::kNoProperties, 1, 0, 1)                 \
   V(ChangeFloat64ToInt32, Operator::kNoProperties, 1, 0, 1)                   \
   V(ChangeFloat64ToUint32, Operator::kNoProperties, 1, 0, 1)                  \
@@ -156,6 +124,8 @@
   V(TryTruncateFloat32ToUint64, Operator::kNoProperties, 1, 0, 2)             \
   V(TryTruncateFloat64ToUint64, Operator::kNoProperties, 1, 0, 2)             \
   V(ChangeInt32ToFloat64, Operator::kNoProperties, 1, 0, 1)                   \
+  V(Float64SilenceNaN, Operator::kNoProperties, 1, 0, 1)                      \
+  V(RoundFloat64ToInt32, Operator::kNoProperties, 1, 0, 1)                    \
   V(RoundInt32ToFloat32, Operator::kNoProperties, 1, 0, 1)                    \
   V(RoundInt64ToFloat32, Operator::kNoProperties, 1, 0, 1)                    \
   V(RoundInt64ToFloat64, Operator::kNoProperties, 1, 0, 1)                    \
@@ -174,16 +144,31 @@
   V(Float32Abs, Operator::kNoProperties, 1, 0, 1)                             \
   V(Float32Add, Operator::kCommutative, 2, 0, 1)                              \
   V(Float32Sub, Operator::kNoProperties, 2, 0, 1)                             \
+  V(Float32SubPreserveNan, Operator::kNoProperties, 2, 0, 1)                  \
   V(Float32Mul, Operator::kCommutative, 2, 0, 1)                              \
   V(Float32Div, Operator::kNoProperties, 2, 0, 1)                             \
   V(Float32Sqrt, Operator::kNoProperties, 1, 0, 1)                            \
   V(Float64Abs, Operator::kNoProperties, 1, 0, 1)                             \
+  V(Float64Atan, Operator::kNoProperties, 1, 0, 1)                            \
+  V(Float64Atan2, Operator::kNoProperties, 2, 0, 1)                           \
+  V(Float64Atanh, Operator::kNoProperties, 1, 0, 1)                           \
+  V(Float64Cbrt, Operator::kNoProperties, 1, 0, 1)                            \
+  V(Float64Cos, Operator::kNoProperties, 1, 0, 1)                             \
+  V(Float64Exp, Operator::kNoProperties, 1, 0, 1)                             \
+  V(Float64Expm1, Operator::kNoProperties, 1, 0, 1)                           \
+  V(Float64Log, Operator::kNoProperties, 1, 0, 1)                             \
+  V(Float64Log1p, Operator::kNoProperties, 1, 0, 1)                           \
+  V(Float64Log2, Operator::kNoProperties, 1, 0, 1)                            \
+  V(Float64Log10, Operator::kNoProperties, 1, 0, 1)                           \
   V(Float64Add, Operator::kCommutative, 2, 0, 1)                              \
   V(Float64Sub, Operator::kNoProperties, 2, 0, 1)                             \
+  V(Float64SubPreserveNan, Operator::kNoProperties, 2, 0, 1)                  \
   V(Float64Mul, Operator::kCommutative, 2, 0, 1)                              \
   V(Float64Div, Operator::kNoProperties, 2, 0, 1)                             \
   V(Float64Mod, Operator::kNoProperties, 2, 0, 1)                             \
+  V(Float64Sin, Operator::kNoProperties, 1, 0, 1)                             \
   V(Float64Sqrt, Operator::kNoProperties, 1, 0, 1)                            \
+  V(Float64Tan, Operator::kNoProperties, 1, 0, 1)                             \
   V(Float32Equal, Operator::kCommutative, 2, 0, 1)                            \
   V(Float32LessThan, Operator::kNoProperties, 2, 0, 1)                        \
   V(Float32LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                 \
@@ -202,7 +187,179 @@
   V(Int32PairMul, Operator::kNoProperties, 4, 0, 2)                           \
   V(Word32PairShl, Operator::kNoProperties, 3, 0, 2)                          \
   V(Word32PairShr, Operator::kNoProperties, 3, 0, 2)                          \
-  V(Word32PairSar, Operator::kNoProperties, 3, 0, 2)
+  V(Word32PairSar, Operator::kNoProperties, 3, 0, 2)                          \
+  V(CreateFloat32x4, Operator::kNoProperties, 4, 0, 1)                        \
+  V(Float32x4ExtractLane, Operator::kNoProperties, 2, 0, 1)                   \
+  V(Float32x4ReplaceLane, Operator::kNoProperties, 3, 0, 1)                   \
+  V(Float32x4Abs, Operator::kNoProperties, 1, 0, 1)                           \
+  V(Float32x4Neg, Operator::kNoProperties, 1, 0, 1)                           \
+  V(Float32x4Sqrt, Operator::kNoProperties, 1, 0, 1)                          \
+  V(Float32x4RecipApprox, Operator::kNoProperties, 1, 0, 1)                   \
+  V(Float32x4RecipSqrtApprox, Operator::kNoProperties, 1, 0, 1)               \
+  V(Float32x4Add, Operator::kCommutative, 2, 0, 1)                            \
+  V(Float32x4Sub, Operator::kNoProperties, 2, 0, 1)                           \
+  V(Float32x4Mul, Operator::kCommutative, 2, 0, 1)                            \
+  V(Float32x4Div, Operator::kNoProperties, 2, 0, 1)                           \
+  V(Float32x4Min, Operator::kCommutative, 2, 0, 1)                            \
+  V(Float32x4Max, Operator::kCommutative, 2, 0, 1)                            \
+  V(Float32x4MinNum, Operator::kCommutative, 2, 0, 1)                         \
+  V(Float32x4MaxNum, Operator::kCommutative, 2, 0, 1)                         \
+  V(Float32x4Equal, Operator::kCommutative, 2, 0, 1)                          \
+  V(Float32x4NotEqual, Operator::kCommutative, 2, 0, 1)                       \
+  V(Float32x4LessThan, Operator::kNoProperties, 2, 0, 1)                      \
+  V(Float32x4LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)               \
+  V(Float32x4GreaterThan, Operator::kNoProperties, 2, 0, 1)                   \
+  V(Float32x4GreaterThanOrEqual, Operator::kNoProperties, 2, 0, 1)            \
+  V(Float32x4Select, Operator::kNoProperties, 3, 0, 1)                        \
+  V(Float32x4Swizzle, Operator::kNoProperties, 5, 0, 1)                       \
+  V(Float32x4Shuffle, Operator::kNoProperties, 6, 0, 1)                       \
+  V(Float32x4FromInt32x4, Operator::kNoProperties, 1, 0, 1)                   \
+  V(Float32x4FromUint32x4, Operator::kNoProperties, 1, 0, 1)                  \
+  V(CreateInt32x4, Operator::kNoProperties, 4, 0, 1)                          \
+  V(Int32x4ExtractLane, Operator::kNoProperties, 2, 0, 1)                     \
+  V(Int32x4ReplaceLane, Operator::kNoProperties, 3, 0, 1)                     \
+  V(Int32x4Neg, Operator::kNoProperties, 1, 0, 1)                             \
+  V(Int32x4Add, Operator::kCommutative, 2, 0, 1)                              \
+  V(Int32x4Sub, Operator::kNoProperties, 2, 0, 1)                             \
+  V(Int32x4Mul, Operator::kCommutative, 2, 0, 1)                              \
+  V(Int32x4Min, Operator::kCommutative, 2, 0, 1)                              \
+  V(Int32x4Max, Operator::kCommutative, 2, 0, 1)                              \
+  V(Int32x4ShiftLeftByScalar, Operator::kNoProperties, 2, 0, 1)               \
+  V(Int32x4ShiftRightByScalar, Operator::kNoProperties, 2, 0, 1)              \
+  V(Int32x4Equal, Operator::kCommutative, 2, 0, 1)                            \
+  V(Int32x4NotEqual, Operator::kCommutative, 2, 0, 1)                         \
+  V(Int32x4LessThan, Operator::kNoProperties, 2, 0, 1)                        \
+  V(Int32x4LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                 \
+  V(Int32x4GreaterThan, Operator::kNoProperties, 2, 0, 1)                     \
+  V(Int32x4GreaterThanOrEqual, Operator::kNoProperties, 2, 0, 1)              \
+  V(Int32x4Select, Operator::kNoProperties, 3, 0, 1)                          \
+  V(Int32x4Swizzle, Operator::kNoProperties, 5, 0, 1)                         \
+  V(Int32x4Shuffle, Operator::kNoProperties, 6, 0, 1)                         \
+  V(Int32x4FromFloat32x4, Operator::kNoProperties, 1, 0, 1)                   \
+  V(Uint32x4Min, Operator::kCommutative, 2, 0, 1)                             \
+  V(Uint32x4Max, Operator::kCommutative, 2, 0, 1)                             \
+  V(Uint32x4ShiftLeftByScalar, Operator::kNoProperties, 2, 0, 1)              \
+  V(Uint32x4ShiftRightByScalar, Operator::kNoProperties, 2, 0, 1)             \
+  V(Uint32x4LessThan, Operator::kNoProperties, 2, 0, 1)                       \
+  V(Uint32x4LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                \
+  V(Uint32x4GreaterThan, Operator::kNoProperties, 2, 0, 1)                    \
+  V(Uint32x4GreaterThanOrEqual, Operator::kNoProperties, 2, 0, 1)             \
+  V(Uint32x4FromFloat32x4, Operator::kNoProperties, 1, 0, 1)                  \
+  V(CreateBool32x4, Operator::kNoProperties, 4, 0, 1)                         \
+  V(Bool32x4ExtractLane, Operator::kNoProperties, 2, 0, 1)                    \
+  V(Bool32x4ReplaceLane, Operator::kNoProperties, 3, 0, 1)                    \
+  V(Bool32x4And, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)    \
+  V(Bool32x4Or, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)     \
+  V(Bool32x4Xor, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)    \
+  V(Bool32x4Not, Operator::kNoProperties, 1, 0, 1)                            \
+  V(Bool32x4AnyTrue, Operator::kNoProperties, 1, 0, 1)                        \
+  V(Bool32x4AllTrue, Operator::kNoProperties, 1, 0, 1)                        \
+  V(Bool32x4Swizzle, Operator::kNoProperties, 5, 0, 1)                        \
+  V(Bool32x4Shuffle, Operator::kNoProperties, 6, 0, 1)                        \
+  V(Bool32x4Equal, Operator::kCommutative, 2, 0, 1)                           \
+  V(Bool32x4NotEqual, Operator::kCommutative, 2, 0, 1)                        \
+  V(CreateInt16x8, Operator::kNoProperties, 8, 0, 1)                          \
+  V(Int16x8ExtractLane, Operator::kNoProperties, 2, 0, 1)                     \
+  V(Int16x8ReplaceLane, Operator::kNoProperties, 3, 0, 1)                     \
+  V(Int16x8Neg, Operator::kNoProperties, 1, 0, 1)                             \
+  V(Int16x8Add, Operator::kCommutative, 2, 0, 1)                              \
+  V(Int16x8AddSaturate, Operator::kCommutative, 2, 0, 1)                      \
+  V(Int16x8Sub, Operator::kNoProperties, 2, 0, 1)                             \
+  V(Int16x8SubSaturate, Operator::kNoProperties, 2, 0, 1)                     \
+  V(Int16x8Mul, Operator::kCommutative, 2, 0, 1)                              \
+  V(Int16x8Min, Operator::kCommutative, 2, 0, 1)                              \
+  V(Int16x8Max, Operator::kCommutative, 2, 0, 1)                              \
+  V(Int16x8ShiftLeftByScalar, Operator::kNoProperties, 2, 0, 1)               \
+  V(Int16x8ShiftRightByScalar, Operator::kNoProperties, 2, 0, 1)              \
+  V(Int16x8Equal, Operator::kCommutative, 2, 0, 1)                            \
+  V(Int16x8NotEqual, Operator::kCommutative, 2, 0, 1)                         \
+  V(Int16x8LessThan, Operator::kNoProperties, 2, 0, 1)                        \
+  V(Int16x8LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                 \
+  V(Int16x8GreaterThan, Operator::kNoProperties, 2, 0, 1)                     \
+  V(Int16x8GreaterThanOrEqual, Operator::kNoProperties, 2, 0, 1)              \
+  V(Int16x8Select, Operator::kNoProperties, 3, 0, 1)                          \
+  V(Int16x8Swizzle, Operator::kNoProperties, 9, 0, 1)                         \
+  V(Int16x8Shuffle, Operator::kNoProperties, 10, 0, 1)                        \
+  V(Uint16x8AddSaturate, Operator::kCommutative, 2, 0, 1)                     \
+  V(Uint16x8SubSaturate, Operator::kNoProperties, 2, 0, 1)                    \
+  V(Uint16x8Min, Operator::kCommutative, 2, 0, 1)                             \
+  V(Uint16x8Max, Operator::kCommutative, 2, 0, 1)                             \
+  V(Uint16x8ShiftLeftByScalar, Operator::kNoProperties, 2, 0, 1)              \
+  V(Uint16x8ShiftRightByScalar, Operator::kNoProperties, 2, 0, 1)             \
+  V(Uint16x8LessThan, Operator::kNoProperties, 2, 0, 1)                       \
+  V(Uint16x8LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                \
+  V(Uint16x8GreaterThan, Operator::kNoProperties, 2, 0, 1)                    \
+  V(Uint16x8GreaterThanOrEqual, Operator::kNoProperties, 2, 0, 1)             \
+  V(CreateBool16x8, Operator::kNoProperties, 8, 0, 1)                         \
+  V(Bool16x8ExtractLane, Operator::kNoProperties, 2, 0, 1)                    \
+  V(Bool16x8ReplaceLane, Operator::kNoProperties, 3, 0, 1)                    \
+  V(Bool16x8And, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)    \
+  V(Bool16x8Or, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)     \
+  V(Bool16x8Xor, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)    \
+  V(Bool16x8Not, Operator::kNoProperties, 1, 0, 1)                            \
+  V(Bool16x8AnyTrue, Operator::kNoProperties, 1, 0, 1)                        \
+  V(Bool16x8AllTrue, Operator::kNoProperties, 1, 0, 1)                        \
+  V(Bool16x8Swizzle, Operator::kNoProperties, 9, 0, 1)                        \
+  V(Bool16x8Shuffle, Operator::kNoProperties, 10, 0, 1)                       \
+  V(Bool16x8Equal, Operator::kCommutative, 2, 0, 1)                           \
+  V(Bool16x8NotEqual, Operator::kCommutative, 2, 0, 1)                        \
+  V(CreateInt8x16, Operator::kNoProperties, 16, 0, 1)                         \
+  V(Int8x16ExtractLane, Operator::kNoProperties, 2, 0, 1)                     \
+  V(Int8x16ReplaceLane, Operator::kNoProperties, 3, 0, 1)                     \
+  V(Int8x16Neg, Operator::kNoProperties, 1, 0, 1)                             \
+  V(Int8x16Add, Operator::kCommutative, 2, 0, 1)                              \
+  V(Int8x16AddSaturate, Operator::kCommutative, 2, 0, 1)                      \
+  V(Int8x16Sub, Operator::kNoProperties, 2, 0, 1)                             \
+  V(Int8x16SubSaturate, Operator::kNoProperties, 2, 0, 1)                     \
+  V(Int8x16Mul, Operator::kCommutative, 2, 0, 1)                              \
+  V(Int8x16Min, Operator::kCommutative, 2, 0, 1)                              \
+  V(Int8x16Max, Operator::kCommutative, 2, 0, 1)                              \
+  V(Int8x16ShiftLeftByScalar, Operator::kNoProperties, 2, 0, 1)               \
+  V(Int8x16ShiftRightByScalar, Operator::kNoProperties, 2, 0, 1)              \
+  V(Int8x16Equal, Operator::kCommutative, 2, 0, 1)                            \
+  V(Int8x16NotEqual, Operator::kCommutative, 2, 0, 1)                         \
+  V(Int8x16LessThan, Operator::kNoProperties, 2, 0, 1)                        \
+  V(Int8x16LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                 \
+  V(Int8x16GreaterThan, Operator::kNoProperties, 2, 0, 1)                     \
+  V(Int8x16GreaterThanOrEqual, Operator::kNoProperties, 2, 0, 1)              \
+  V(Int8x16Select, Operator::kNoProperties, 3, 0, 1)                          \
+  V(Int8x16Swizzle, Operator::kNoProperties, 17, 0, 1)                        \
+  V(Int8x16Shuffle, Operator::kNoProperties, 18, 0, 1)                        \
+  V(Uint8x16AddSaturate, Operator::kCommutative, 2, 0, 1)                     \
+  V(Uint8x16SubSaturate, Operator::kNoProperties, 2, 0, 1)                    \
+  V(Uint8x16Min, Operator::kCommutative, 2, 0, 1)                             \
+  V(Uint8x16Max, Operator::kCommutative, 2, 0, 1)                             \
+  V(Uint8x16ShiftLeftByScalar, Operator::kNoProperties, 2, 0, 1)              \
+  V(Uint8x16ShiftRightByScalar, Operator::kNoProperties, 2, 0, 1)             \
+  V(Uint8x16LessThan, Operator::kNoProperties, 2, 0, 1)                       \
+  V(Uint8x16LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                \
+  V(Uint8x16GreaterThan, Operator::kNoProperties, 2, 0, 1)                    \
+  V(Uint8x16GreaterThanOrEqual, Operator::kNoProperties, 2, 0, 1)             \
+  V(CreateBool8x16, Operator::kNoProperties, 16, 0, 1)                        \
+  V(Bool8x16ExtractLane, Operator::kNoProperties, 2, 0, 1)                    \
+  V(Bool8x16ReplaceLane, Operator::kNoProperties, 3, 0, 1)                    \
+  V(Bool8x16And, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)    \
+  V(Bool8x16Or, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)     \
+  V(Bool8x16Xor, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)    \
+  V(Bool8x16Not, Operator::kNoProperties, 1, 0, 1)                            \
+  V(Bool8x16AnyTrue, Operator::kNoProperties, 1, 0, 1)                        \
+  V(Bool8x16AllTrue, Operator::kNoProperties, 1, 0, 1)                        \
+  V(Bool8x16Swizzle, Operator::kNoProperties, 17, 0, 1)                       \
+  V(Bool8x16Shuffle, Operator::kNoProperties, 18, 0, 1)                       \
+  V(Bool8x16Equal, Operator::kCommutative, 2, 0, 1)                           \
+  V(Bool8x16NotEqual, Operator::kCommutative, 2, 0, 1)                        \
+  V(Simd128Load, Operator::kNoProperties, 2, 0, 1)                            \
+  V(Simd128Load1, Operator::kNoProperties, 2, 0, 1)                           \
+  V(Simd128Load2, Operator::kNoProperties, 2, 0, 1)                           \
+  V(Simd128Load3, Operator::kNoProperties, 2, 0, 1)                           \
+  V(Simd128Store, Operator::kNoProperties, 3, 0, 1)                           \
+  V(Simd128Store1, Operator::kNoProperties, 3, 0, 1)                          \
+  V(Simd128Store2, Operator::kNoProperties, 3, 0, 1)                          \
+  V(Simd128Store3, Operator::kNoProperties, 3, 0, 1)                          \
+  V(Simd128And, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)     \
+  V(Simd128Or, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)      \
+  V(Simd128Xor, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)     \
+  V(Simd128Not, Operator::kNoProperties, 1, 0, 1)
 
 #define PURE_OPTIONAL_OP_LIST(V)                            \
   V(Word32Ctz, Operator::kNoProperties, 1, 0, 1)            \
@@ -223,7 +380,15 @@
   V(Float64RoundTruncate, Operator::kNoProperties, 1, 0, 1) \
   V(Float64RoundTiesAway, Operator::kNoProperties, 1, 0, 1) \
   V(Float32RoundTiesEven, Operator::kNoProperties, 1, 0, 1) \
-  V(Float64RoundTiesEven, Operator::kNoProperties, 1, 0, 1)
+  V(Float64RoundTiesEven, Operator::kNoProperties, 1, 0, 1) \
+  V(Float32Neg, Operator::kNoProperties, 1, 0, 1)           \
+  V(Float64Neg, Operator::kNoProperties, 1, 0, 1)
+
+#define OVERFLOW_OP_LIST(V)                                                \
+  V(Int32AddWithOverflow, Operator::kAssociative | Operator::kCommutative) \
+  V(Int32SubWithOverflow, Operator::kNoProperties)                         \
+  V(Int64AddWithOverflow, Operator::kAssociative | Operator::kCommutative) \
+  V(Int64SubWithOverflow, Operator::kNoProperties)
 
 #define MACHINE_TYPE_LIST(V) \
   V(Float32)                 \
@@ -250,6 +415,19 @@
   V(kWord64)                           \
   V(kTagged)
 
+#define ATOMIC_TYPE_LIST(V) \
+  V(Int8)                   \
+  V(Uint8)                  \
+  V(Int16)                  \
+  V(Uint16)                 \
+  V(Int32)                  \
+  V(Uint32)
+
+#define ATOMIC_REPRESENTATION_LIST(V) \
+  V(kWord8)                           \
+  V(kWord16)                          \
+  V(kWord32)
+
 struct MachineOperatorGlobalCache {
 #define PURE(Name, properties, value_input_count, control_input_count,         \
              output_count)                                                     \
@@ -264,46 +442,47 @@
   PURE_OPTIONAL_OP_LIST(PURE)
 #undef PURE
 
-  template <TruncationMode kMode>
-  struct TruncateFloat64ToInt32Operator final
-      : public Operator1<TruncationMode> {
-    TruncateFloat64ToInt32Operator()
-        : Operator1<TruncationMode>(IrOpcode::kTruncateFloat64ToInt32,
-                                    Operator::kPure, "TruncateFloat64ToInt32",
-                                    1, 0, 0, 1, 0, 0, kMode) {}
-  };
-  TruncateFloat64ToInt32Operator<TruncationMode::kJavaScript>
-      kTruncateFloat64ToInt32JavaScript;
-  TruncateFloat64ToInt32Operator<TruncationMode::kRoundToZero>
-      kTruncateFloat64ToInt32RoundToZero;
+#define OVERFLOW_OP(Name, properties)                                        \
+  struct Name##Operator final : public Operator {                            \
+    Name##Operator()                                                         \
+        : Operator(IrOpcode::k##Name,                                        \
+                   Operator::kEliminatable | Operator::kNoRead | properties, \
+                   #Name, 2, 0, 1, 2, 0, 0) {}                               \
+  };                                                                         \
+  Name##Operator k##Name;
+  OVERFLOW_OP_LIST(OVERFLOW_OP)
+#undef OVERFLOW_OP
 
-#define LOAD(Type)                                                             \
-  struct Load##Type##Operator final : public Operator1<LoadRepresentation> {   \
-    Load##Type##Operator()                                                     \
-        : Operator1<LoadRepresentation>(                                       \
-              IrOpcode::kLoad, Operator::kNoThrow | Operator::kNoWrite,        \
-              "Load", 2, 1, 1, 1, 1, 0, MachineType::Type()) {}                \
-  };                                                                           \
-  struct CheckedLoad##Type##Operator final                                     \
-      : public Operator1<CheckedLoadRepresentation> {                          \
-    CheckedLoad##Type##Operator()                                              \
-        : Operator1<CheckedLoadRepresentation>(                                \
-              IrOpcode::kCheckedLoad, Operator::kNoThrow | Operator::kNoWrite, \
-              "CheckedLoad", 3, 1, 1, 1, 1, 0, MachineType::Type()) {}         \
-  };                                                                           \
-  Load##Type##Operator kLoad##Type;                                            \
+#define LOAD(Type)                                                           \
+  struct Load##Type##Operator final : public Operator1<LoadRepresentation> { \
+    Load##Type##Operator()                                                   \
+        : Operator1<LoadRepresentation>(                                     \
+              IrOpcode::kLoad,                                               \
+              Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite,  \
+              "Load", 2, 1, 1, 1, 1, 0, MachineType::Type()) {}              \
+  };                                                                         \
+  struct CheckedLoad##Type##Operator final                                   \
+      : public Operator1<CheckedLoadRepresentation> {                        \
+    CheckedLoad##Type##Operator()                                            \
+        : Operator1<CheckedLoadRepresentation>(                              \
+              IrOpcode::kCheckedLoad,                                        \
+              Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite,  \
+              "CheckedLoad", 3, 1, 1, 1, 1, 0, MachineType::Type()) {}       \
+  };                                                                         \
+  Load##Type##Operator kLoad##Type;                                          \
   CheckedLoad##Type##Operator kCheckedLoad##Type;
   MACHINE_TYPE_LIST(LOAD)
 #undef LOAD
 
-#define STACKSLOT(Type)                                                       \
-  struct StackSlot##Type##Operator final                                      \
-      : public Operator1<MachineRepresentation> {                             \
-    StackSlot##Type##Operator()                                               \
-        : Operator1<MachineRepresentation>(                                   \
-              IrOpcode::kStackSlot, Operator::kNoThrow, "StackSlot", 0, 0, 0, \
-              1, 0, 0, MachineType::Type().representation()) {}               \
-  };                                                                          \
+#define STACKSLOT(Type)                                                      \
+  struct StackSlot##Type##Operator final                                     \
+      : public Operator1<MachineRepresentation> {                            \
+    StackSlot##Type##Operator()                                              \
+        : Operator1<MachineRepresentation>(                                  \
+              IrOpcode::kStackSlot, Operator::kNoDeopt | Operator::kNoThrow, \
+              "StackSlot", 0, 0, 0, 1, 0, 0,                                 \
+              MachineType::Type().representation()) {}                       \
+  };                                                                         \
   StackSlot##Type##Operator kStackSlot##Type;
   MACHINE_TYPE_LIST(STACKSLOT)
 #undef STACKSLOT
@@ -312,7 +491,8 @@
   struct Store##Type##Operator : public Operator1<StoreRepresentation> {       \
     explicit Store##Type##Operator(WriteBarrierKind write_barrier_kind)        \
         : Operator1<StoreRepresentation>(                                      \
-              IrOpcode::kStore, Operator::kNoRead | Operator::kNoThrow,        \
+              IrOpcode::kStore,                                                \
+              Operator::kNoDeopt | Operator::kNoRead | Operator::kNoThrow,     \
               "Store", 3, 1, 1, 0, 1, 0,                                       \
               StoreRepresentation(MachineRepresentation::Type,                 \
                                   write_barrier_kind)) {}                      \
@@ -341,7 +521,8 @@
       : public Operator1<CheckedStoreRepresentation> {                         \
     CheckedStore##Type##Operator()                                             \
         : Operator1<CheckedStoreRepresentation>(                               \
-              IrOpcode::kCheckedStore, Operator::kNoRead | Operator::kNoThrow, \
+              IrOpcode::kCheckedStore,                                         \
+              Operator::kNoDeopt | Operator::kNoRead | Operator::kNoThrow,     \
               "CheckedStore", 4, 1, 1, 0, 1, 0, MachineRepresentation::Type) { \
     }                                                                          \
   };                                                                           \
@@ -353,17 +534,58 @@
   CheckedStore##Type##Operator kCheckedStore##Type;
   MACHINE_REPRESENTATION_LIST(STORE)
 #undef STORE
+
+#define ATOMIC_LOAD(Type)                                                   \
+  struct AtomicLoad##Type##Operator final                                   \
+      : public Operator1<LoadRepresentation> {                              \
+    AtomicLoad##Type##Operator()                                            \
+        : Operator1<LoadRepresentation>(                                    \
+              IrOpcode::kAtomicLoad,                                        \
+              Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite, \
+              "AtomicLoad", 2, 1, 1, 1, 1, 0, MachineType::Type()) {}       \
+  };                                                                        \
+  AtomicLoad##Type##Operator kAtomicLoad##Type;
+  ATOMIC_TYPE_LIST(ATOMIC_LOAD)
+#undef ATOMIC_LOAD
+
+#define ATOMIC_STORE(Type)                                                     \
+  struct AtomicStore##Type##Operator                                           \
+      : public Operator1<MachineRepresentation> {                              \
+    AtomicStore##Type##Operator()                                              \
+        : Operator1<MachineRepresentation>(                                    \
+              IrOpcode::kAtomicStore,                                          \
+              Operator::kNoDeopt | Operator::kNoRead | Operator::kNoThrow,     \
+              "AtomicStore", 3, 1, 1, 0, 1, 0, MachineRepresentation::Type) {} \
+  };                                                                           \
+  AtomicStore##Type##Operator kAtomicStore##Type;
+  ATOMIC_REPRESENTATION_LIST(ATOMIC_STORE)
+#undef STORE
+
+  struct DebugBreakOperator : public Operator {
+    DebugBreakOperator()
+        : Operator(IrOpcode::kDebugBreak, Operator::kNoThrow, "DebugBreak", 0,
+                   0, 0, 0, 0, 0) {}
+  };
+  DebugBreakOperator kDebugBreak;
 };
 
+struct CommentOperator : public Operator1<const char*> {
+  explicit CommentOperator(const char* msg)
+      : Operator1<const char*>(IrOpcode::kComment, Operator::kNoThrow,
+                               "Comment", 0, 0, 0, 0, 0, 0, msg) {}
+};
 
 static base::LazyInstance<MachineOperatorGlobalCache>::type kCache =
     LAZY_INSTANCE_INITIALIZER;
 
-
-MachineOperatorBuilder::MachineOperatorBuilder(Zone* zone,
-                                               MachineRepresentation word,
-                                               Flags flags)
-    : cache_(kCache.Get()), word_(word), flags_(flags) {
+MachineOperatorBuilder::MachineOperatorBuilder(
+    Zone* zone, MachineRepresentation word, Flags flags,
+    AlignmentRequirements alignmentRequirements)
+    : zone_(zone),
+      cache_(kCache.Get()),
+      word_(word),
+      flags_(flags),
+      alignment_requirements_(alignmentRequirements) {
   DCHECK(word == MachineRepresentation::kWord32 ||
          word == MachineRepresentation::kWord64);
 }
@@ -383,19 +605,10 @@
 PURE_OPTIONAL_OP_LIST(PURE)
 #undef PURE
 
-
-const Operator* MachineOperatorBuilder::TruncateFloat64ToInt32(
-    TruncationMode mode) {
-  switch (mode) {
-    case TruncationMode::kJavaScript:
-      return &cache_.kTruncateFloat64ToInt32JavaScript;
-    case TruncationMode::kRoundToZero:
-      return &cache_.kTruncateFloat64ToInt32RoundToZero;
-  }
-  UNREACHABLE();
-  return nullptr;
-}
-
+#define OVERFLOW_OP(Name, properties) \
+  const Operator* MachineOperatorBuilder::Name() { return &cache_.k##Name; }
+OVERFLOW_OP_LIST(OVERFLOW_OP)
+#undef OVERFLOW_OP
 
 const Operator* MachineOperatorBuilder::Load(LoadRepresentation rep) {
 #define LOAD(Type)                  \
@@ -444,6 +657,13 @@
   return nullptr;
 }
 
+const Operator* MachineOperatorBuilder::DebugBreak() {
+  return &cache_.kDebugBreak;
+}
+
+const Operator* MachineOperatorBuilder::Comment(const char* msg) {
+  return new (zone_) CommentOperator(msg);
+}
 
 const Operator* MachineOperatorBuilder::CheckedLoad(
     CheckedLoadRepresentation rep) {
@@ -487,6 +707,29 @@
 const Operator* MachineOperatorBuilder::Word64CtzPlaceholder() {
   return &cache_.kWord64Ctz;
 }
+
+const Operator* MachineOperatorBuilder::AtomicLoad(LoadRepresentation rep) {
+#define LOAD(Type)                    \
+  if (rep == MachineType::Type()) {   \
+    return &cache_.kAtomicLoad##Type; \
+  }
+  ATOMIC_TYPE_LIST(LOAD)
+#undef LOAD
+  UNREACHABLE();
+  return nullptr;
+}
+
+const Operator* MachineOperatorBuilder::AtomicStore(MachineRepresentation rep) {
+#define STORE(kRep)                         \
+  if (rep == MachineRepresentation::kRep) { \
+    return &cache_.kAtomicStore##kRep;      \
+  }
+  ATOMIC_REPRESENTATION_LIST(STORE)
+#undef STORE
+  UNREACHABLE();
+  return nullptr;
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/src/compiler/machine-operator.h b/src/compiler/machine-operator.h
index 68e393a..7c443f4 100644
--- a/src/compiler/machine-operator.h
+++ b/src/compiler/machine-operator.h
@@ -33,32 +33,6 @@
 };
 
 
-// Supported float64 to int32 truncation modes.
-enum class TruncationMode : uint8_t {
-  kJavaScript,  // ES6 section 7.1.5
-  kRoundToZero  // Round towards zero. Implementation defined for NaN and ovf.
-};
-
-V8_INLINE size_t hash_value(TruncationMode mode) {
-  return static_cast<uint8_t>(mode);
-}
-
-std::ostream& operator<<(std::ostream&, TruncationMode);
-
-TruncationMode TruncationModeOf(Operator const*);
-
-
-// Supported write barrier modes.
-enum WriteBarrierKind {
-  kNoWriteBarrier,
-  kMapWriteBarrier,
-  kPointerWriteBarrier,
-  kFullWriteBarrier
-};
-
-std::ostream& operator<<(std::ostream& os, WriteBarrierKind);
-
-
 // A Load needs a MachineType.
 typedef MachineType LoadRepresentation;
 
@@ -104,6 +78,8 @@
 
 MachineRepresentation StackSlotRepresentationOf(Operator const* op);
 
+MachineRepresentation AtomicStoreRepresentationOf(Operator const* op);
+
 // Interface for building machine-level operators. These operators are
 // machine-level but machine-independent and thus define a language suitable
 // for generating code to run on architectures such as ia32, x64, arm, etc.
@@ -137,20 +113,89 @@
     kWord64Popcnt = 1u << 19,
     kWord32ReverseBits = 1u << 20,
     kWord64ReverseBits = 1u << 21,
-    kAllOptionalOps = kFloat32Max | kFloat32Min | kFloat64Max | kFloat64Min |
-                      kFloat32RoundDown | kFloat64RoundDown | kFloat32RoundUp |
-                      kFloat64RoundUp | kFloat32RoundTruncate |
-                      kFloat64RoundTruncate | kFloat64RoundTiesAway |
-                      kFloat32RoundTiesEven | kFloat64RoundTiesEven |
-                      kWord32Ctz | kWord64Ctz | kWord32Popcnt | kWord64Popcnt |
-                      kWord32ReverseBits | kWord64ReverseBits
+    kFloat32Neg = 1u << 22,
+    kFloat64Neg = 1u << 23,
+    kAllOptionalOps =
+        kFloat32Max | kFloat32Min | kFloat64Max | kFloat64Min |
+        kFloat32RoundDown | kFloat64RoundDown | kFloat32RoundUp |
+        kFloat64RoundUp | kFloat32RoundTruncate | kFloat64RoundTruncate |
+        kFloat64RoundTiesAway | kFloat32RoundTiesEven | kFloat64RoundTiesEven |
+        kWord32Ctz | kWord64Ctz | kWord32Popcnt | kWord64Popcnt |
+        kWord32ReverseBits | kWord64ReverseBits | kFloat32Neg | kFloat64Neg
   };
   typedef base::Flags<Flag, unsigned> Flags;
 
+  class AlignmentRequirements {
+   public:
+    enum UnalignedAccessSupport { kNoSupport, kSomeSupport, kFullSupport };
+
+    bool IsUnalignedLoadSupported(const MachineType& machineType,
+                                  uint8_t alignment) const {
+      return IsUnalignedSupported(unalignedLoadSupportedTypes_, machineType,
+                                  alignment);
+    }
+
+    bool IsUnalignedStoreSupported(const MachineType& machineType,
+                                   uint8_t alignment) const {
+      return IsUnalignedSupported(unalignedStoreSupportedTypes_, machineType,
+                                  alignment);
+    }
+
+    static AlignmentRequirements FullUnalignedAccessSupport() {
+      return AlignmentRequirements(kFullSupport);
+    }
+    static AlignmentRequirements NoUnalignedAccessSupport() {
+      return AlignmentRequirements(kNoSupport);
+    }
+    static AlignmentRequirements SomeUnalignedAccessSupport(
+        const Vector<MachineType>& unalignedLoadSupportedTypes,
+        const Vector<MachineType>& unalignedStoreSupportedTypes) {
+      return AlignmentRequirements(kSomeSupport, unalignedLoadSupportedTypes,
+                                   unalignedStoreSupportedTypes);
+    }
+
+   private:
+    explicit AlignmentRequirements(
+        AlignmentRequirements::UnalignedAccessSupport unalignedAccessSupport,
+        Vector<MachineType> unalignedLoadSupportedTypes =
+            Vector<MachineType>(NULL, 0),
+        Vector<MachineType> unalignedStoreSupportedTypes =
+            Vector<MachineType>(NULL, 0))
+        : unalignedSupport_(unalignedAccessSupport),
+          unalignedLoadSupportedTypes_(unalignedLoadSupportedTypes),
+          unalignedStoreSupportedTypes_(unalignedStoreSupportedTypes) {}
+
+    bool IsUnalignedSupported(const Vector<MachineType>& supported,
+                              const MachineType& machineType,
+                              uint8_t alignment) const {
+      if (unalignedSupport_ == kFullSupport) {
+        return true;
+      } else if (unalignedSupport_ == kNoSupport) {
+        return false;
+      } else {
+        for (MachineType m : supported) {
+          if (m == machineType) {
+            return true;
+          }
+        }
+        return false;
+      }
+    }
+
+    const AlignmentRequirements::UnalignedAccessSupport unalignedSupport_;
+    const Vector<MachineType> unalignedLoadSupportedTypes_;
+    const Vector<MachineType> unalignedStoreSupportedTypes_;
+  };
+
   explicit MachineOperatorBuilder(
       Zone* zone,
       MachineRepresentation word = MachineType::PointerRepresentation(),
-      Flags supportedOperators = kNoFlags);
+      Flags supportedOperators = kNoFlags,
+      AlignmentRequirements alignmentRequirements =
+          AlignmentRequirements::NoUnalignedAccessSupport());
+
+  const Operator* Comment(const char* msg);
+  const Operator* DebugBreak();
 
   const Operator* Word32And();
   const Operator* Word32Or();
@@ -220,6 +265,12 @@
   const Operator* Uint64LessThanOrEqual();
   const Operator* Uint64Mod();
 
+  // This operator reinterprets the bits of a word as tagged pointer.
+  const Operator* BitcastWordToTagged();
+
+  // JavaScript float64 to int32/uint32 truncation.
+  const Operator* TruncateFloat64ToWord32();
+
   // These operators change the representation of numbers while preserving the
   // value of the number. Narrowing operators assume the input is representable
   // in the target type and are *not* defined for other inputs.
@@ -243,8 +294,8 @@
   // These operators truncate or round numbers, both changing the representation
   // of the number and mapping multiple input values onto the same output value.
   const Operator* TruncateFloat64ToFloat32();
-  const Operator* TruncateFloat64ToInt32(TruncationMode);
   const Operator* TruncateInt64ToInt32();
+  const Operator* RoundFloat64ToInt32();
   const Operator* RoundInt32ToFloat32();
   const Operator* RoundInt64ToFloat32();
   const Operator* RoundInt64ToFloat64();
@@ -263,6 +314,7 @@
   // (single-precision).
   const Operator* Float32Add();
   const Operator* Float32Sub();
+  const Operator* Float32SubPreserveNan();
   const Operator* Float32Mul();
   const Operator* Float32Div();
   const Operator* Float32Sqrt();
@@ -271,6 +323,7 @@
   // (double-precision).
   const Operator* Float64Add();
   const Operator* Float64Sub();
+  const Operator* Float64SubPreserveNan();
   const Operator* Float64Mul();
   const Operator* Float64Div();
   const Operator* Float64Mod();
@@ -311,12 +364,226 @@
   const OptionalOperator Float32RoundTiesEven();
   const OptionalOperator Float64RoundTiesEven();
 
+  // Floating point neg.
+  const OptionalOperator Float32Neg();
+  const OptionalOperator Float64Neg();
+
+  // Floating point trigonometric functions (double-precision).
+  const Operator* Float64Atan();
+  const Operator* Float64Atan2();
+  const Operator* Float64Atanh();
+
+  // Floating point trigonometric functions (double-precision).
+  const Operator* Float64Cos();
+  const Operator* Float64Sin();
+  const Operator* Float64Tan();
+
+  // Floating point exponential functions (double-precision).
+  const Operator* Float64Exp();
+
+  // Floating point logarithm (double-precision).
+  const Operator* Float64Log();
+  const Operator* Float64Log1p();
+  const Operator* Float64Log2();
+  const Operator* Float64Log10();
+
+  const Operator* Float64Cbrt();
+  const Operator* Float64Expm1();
+
   // Floating point bit representation.
   const Operator* Float64ExtractLowWord32();
   const Operator* Float64ExtractHighWord32();
   const Operator* Float64InsertLowWord32();
   const Operator* Float64InsertHighWord32();
 
+  // Change signalling NaN to quiet NaN.
+  // Identity for any input that is not signalling NaN.
+  const Operator* Float64SilenceNaN();
+
+  // SIMD operators.
+  const Operator* CreateFloat32x4();
+  const Operator* Float32x4ExtractLane();
+  const Operator* Float32x4ReplaceLane();
+  const Operator* Float32x4Abs();
+  const Operator* Float32x4Neg();
+  const Operator* Float32x4Sqrt();
+  const Operator* Float32x4RecipApprox();
+  const Operator* Float32x4RecipSqrtApprox();
+  const Operator* Float32x4Add();
+  const Operator* Float32x4Sub();
+  const Operator* Float32x4Mul();
+  const Operator* Float32x4Div();
+  const Operator* Float32x4Min();
+  const Operator* Float32x4Max();
+  const Operator* Float32x4MinNum();
+  const Operator* Float32x4MaxNum();
+  const Operator* Float32x4Equal();
+  const Operator* Float32x4NotEqual();
+  const Operator* Float32x4LessThan();
+  const Operator* Float32x4LessThanOrEqual();
+  const Operator* Float32x4GreaterThan();
+  const Operator* Float32x4GreaterThanOrEqual();
+  const Operator* Float32x4Select();
+  const Operator* Float32x4Swizzle();
+  const Operator* Float32x4Shuffle();
+  const Operator* Float32x4FromInt32x4();
+  const Operator* Float32x4FromUint32x4();
+
+  const Operator* CreateInt32x4();
+  const Operator* Int32x4ExtractLane();
+  const Operator* Int32x4ReplaceLane();
+  const Operator* Int32x4Neg();
+  const Operator* Int32x4Add();
+  const Operator* Int32x4Sub();
+  const Operator* Int32x4Mul();
+  const Operator* Int32x4Min();
+  const Operator* Int32x4Max();
+  const Operator* Int32x4ShiftLeftByScalar();
+  const Operator* Int32x4ShiftRightByScalar();
+  const Operator* Int32x4Equal();
+  const Operator* Int32x4NotEqual();
+  const Operator* Int32x4LessThan();
+  const Operator* Int32x4LessThanOrEqual();
+  const Operator* Int32x4GreaterThan();
+  const Operator* Int32x4GreaterThanOrEqual();
+  const Operator* Int32x4Select();
+  const Operator* Int32x4Swizzle();
+  const Operator* Int32x4Shuffle();
+  const Operator* Int32x4FromFloat32x4();
+
+  const Operator* Uint32x4Min();
+  const Operator* Uint32x4Max();
+  const Operator* Uint32x4ShiftLeftByScalar();
+  const Operator* Uint32x4ShiftRightByScalar();
+  const Operator* Uint32x4LessThan();
+  const Operator* Uint32x4LessThanOrEqual();
+  const Operator* Uint32x4GreaterThan();
+  const Operator* Uint32x4GreaterThanOrEqual();
+  const Operator* Uint32x4FromFloat32x4();
+
+  const Operator* CreateBool32x4();
+  const Operator* Bool32x4ExtractLane();
+  const Operator* Bool32x4ReplaceLane();
+  const Operator* Bool32x4And();
+  const Operator* Bool32x4Or();
+  const Operator* Bool32x4Xor();
+  const Operator* Bool32x4Not();
+  const Operator* Bool32x4AnyTrue();
+  const Operator* Bool32x4AllTrue();
+  const Operator* Bool32x4Swizzle();
+  const Operator* Bool32x4Shuffle();
+  const Operator* Bool32x4Equal();
+  const Operator* Bool32x4NotEqual();
+
+  const Operator* CreateInt16x8();
+  const Operator* Int16x8ExtractLane();
+  const Operator* Int16x8ReplaceLane();
+  const Operator* Int16x8Neg();
+  const Operator* Int16x8Add();
+  const Operator* Int16x8AddSaturate();
+  const Operator* Int16x8Sub();
+  const Operator* Int16x8SubSaturate();
+  const Operator* Int16x8Mul();
+  const Operator* Int16x8Min();
+  const Operator* Int16x8Max();
+  const Operator* Int16x8ShiftLeftByScalar();
+  const Operator* Int16x8ShiftRightByScalar();
+  const Operator* Int16x8Equal();
+  const Operator* Int16x8NotEqual();
+  const Operator* Int16x8LessThan();
+  const Operator* Int16x8LessThanOrEqual();
+  const Operator* Int16x8GreaterThan();
+  const Operator* Int16x8GreaterThanOrEqual();
+  const Operator* Int16x8Select();
+  const Operator* Int16x8Swizzle();
+  const Operator* Int16x8Shuffle();
+
+  const Operator* Uint16x8AddSaturate();
+  const Operator* Uint16x8SubSaturate();
+  const Operator* Uint16x8Min();
+  const Operator* Uint16x8Max();
+  const Operator* Uint16x8ShiftLeftByScalar();
+  const Operator* Uint16x8ShiftRightByScalar();
+  const Operator* Uint16x8LessThan();
+  const Operator* Uint16x8LessThanOrEqual();
+  const Operator* Uint16x8GreaterThan();
+  const Operator* Uint16x8GreaterThanOrEqual();
+
+  const Operator* CreateBool16x8();
+  const Operator* Bool16x8ExtractLane();
+  const Operator* Bool16x8ReplaceLane();
+  const Operator* Bool16x8And();
+  const Operator* Bool16x8Or();
+  const Operator* Bool16x8Xor();
+  const Operator* Bool16x8Not();
+  const Operator* Bool16x8AnyTrue();
+  const Operator* Bool16x8AllTrue();
+  const Operator* Bool16x8Swizzle();
+  const Operator* Bool16x8Shuffle();
+  const Operator* Bool16x8Equal();
+  const Operator* Bool16x8NotEqual();
+
+  const Operator* CreateInt8x16();
+  const Operator* Int8x16ExtractLane();
+  const Operator* Int8x16ReplaceLane();
+  const Operator* Int8x16Neg();
+  const Operator* Int8x16Add();
+  const Operator* Int8x16AddSaturate();
+  const Operator* Int8x16Sub();
+  const Operator* Int8x16SubSaturate();
+  const Operator* Int8x16Mul();
+  const Operator* Int8x16Min();
+  const Operator* Int8x16Max();
+  const Operator* Int8x16ShiftLeftByScalar();
+  const Operator* Int8x16ShiftRightByScalar();
+  const Operator* Int8x16Equal();
+  const Operator* Int8x16NotEqual();
+  const Operator* Int8x16LessThan();
+  const Operator* Int8x16LessThanOrEqual();
+  const Operator* Int8x16GreaterThan();
+  const Operator* Int8x16GreaterThanOrEqual();
+  const Operator* Int8x16Select();
+  const Operator* Int8x16Swizzle();
+  const Operator* Int8x16Shuffle();
+
+  const Operator* Uint8x16AddSaturate();
+  const Operator* Uint8x16SubSaturate();
+  const Operator* Uint8x16Min();
+  const Operator* Uint8x16Max();
+  const Operator* Uint8x16ShiftLeftByScalar();
+  const Operator* Uint8x16ShiftRightByScalar();
+  const Operator* Uint8x16LessThan();
+  const Operator* Uint8x16LessThanOrEqual();
+  const Operator* Uint8x16GreaterThan();
+  const Operator* Uint8x16GreaterThanOrEqual();
+
+  const Operator* CreateBool8x16();
+  const Operator* Bool8x16ExtractLane();
+  const Operator* Bool8x16ReplaceLane();
+  const Operator* Bool8x16And();
+  const Operator* Bool8x16Or();
+  const Operator* Bool8x16Xor();
+  const Operator* Bool8x16Not();
+  const Operator* Bool8x16AnyTrue();
+  const Operator* Bool8x16AllTrue();
+  const Operator* Bool8x16Swizzle();
+  const Operator* Bool8x16Shuffle();
+  const Operator* Bool8x16Equal();
+  const Operator* Bool8x16NotEqual();
+
+  const Operator* Simd128Load();
+  const Operator* Simd128Load1();
+  const Operator* Simd128Load2();
+  const Operator* Simd128Load3();
+  const Operator* Simd128Store();
+  const Operator* Simd128Store1();
+  const Operator* Simd128Store2();
+  const Operator* Simd128Store3();
+  const Operator* Simd128And();
+  const Operator* Simd128Or();
+  const Operator* Simd128Xor();
+  const Operator* Simd128Not();
+
   // load [base + index]
   const Operator* Load(LoadRepresentation rep);
 
@@ -335,11 +602,28 @@
   // checked-store heap, index, length, value
   const Operator* CheckedStore(CheckedStoreRepresentation);
 
+  // atomic-load [base + index]
+  const Operator* AtomicLoad(LoadRepresentation rep);
+  // atomic-store [base + index], value
+  const Operator* AtomicStore(MachineRepresentation rep);
+
   // Target machine word-size assumed by this builder.
   bool Is32() const { return word() == MachineRepresentation::kWord32; }
   bool Is64() const { return word() == MachineRepresentation::kWord64; }
   MachineRepresentation word() const { return word_; }
 
+  bool UnalignedLoadSupported(const MachineType& machineType,
+                              uint8_t alignment) {
+    return alignment_requirements_.IsUnalignedLoadSupported(machineType,
+                                                            alignment);
+  }
+
+  bool UnalignedStoreSupported(const MachineType& machineType,
+                               uint8_t alignment) {
+    return alignment_requirements_.IsUnalignedStoreSupported(machineType,
+                                                             alignment);
+  }
+
 // Pseudo operators that translate to 32/64-bit operators depending on the
 // word-size of the target machine assumed by this builder.
 #define PSEUDO_OP_LIST(V) \
@@ -371,9 +655,11 @@
 #undef PSEUDO_OP_LIST
 
  private:
+  Zone* zone_;
   MachineOperatorGlobalCache const& cache_;
   MachineRepresentation const word_;
   Flags const flags_;
+  AlignmentRequirements const alignment_requirements_;
 
   DISALLOW_COPY_AND_ASSIGN(MachineOperatorBuilder);
 };
diff --git a/src/compiler/memory-optimizer.cc b/src/compiler/memory-optimizer.cc
new file mode 100644
index 0000000..8c66347
--- /dev/null
+++ b/src/compiler/memory-optimizer.cc
@@ -0,0 +1,496 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/memory-optimizer.h"
+
+#include "src/compiler/js-graph.h"
+#include "src/compiler/linkage.h"
+#include "src/compiler/node-matchers.h"
+#include "src/compiler/node-properties.h"
+#include "src/compiler/node.h"
+#include "src/compiler/simplified-operator.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+MemoryOptimizer::MemoryOptimizer(JSGraph* jsgraph, Zone* zone)
+    : jsgraph_(jsgraph),
+      empty_state_(AllocationState::Empty(zone)),
+      pending_(zone),
+      tokens_(zone),
+      zone_(zone) {}
+
+void MemoryOptimizer::Optimize() {
+  EnqueueUses(graph()->start(), empty_state());
+  while (!tokens_.empty()) {
+    Token const token = tokens_.front();
+    tokens_.pop();
+    VisitNode(token.node, token.state);
+  }
+  DCHECK(pending_.empty());
+  DCHECK(tokens_.empty());
+}
+
+MemoryOptimizer::AllocationGroup::AllocationGroup(Node* node,
+                                                  PretenureFlag pretenure,
+                                                  Zone* zone)
+    : node_ids_(zone), pretenure_(pretenure), size_(nullptr) {
+  node_ids_.insert(node->id());
+}
+
+MemoryOptimizer::AllocationGroup::AllocationGroup(Node* node,
+                                                  PretenureFlag pretenure,
+                                                  Node* size, Zone* zone)
+    : node_ids_(zone), pretenure_(pretenure), size_(size) {
+  node_ids_.insert(node->id());
+}
+
+void MemoryOptimizer::AllocationGroup::Add(Node* node) {
+  node_ids_.insert(node->id());
+}
+
+bool MemoryOptimizer::AllocationGroup::Contains(Node* node) const {
+  return node_ids_.find(node->id()) != node_ids_.end();
+}
+
+MemoryOptimizer::AllocationState::AllocationState()
+    : group_(nullptr), size_(std::numeric_limits<int>::max()), top_(nullptr) {}
+
+MemoryOptimizer::AllocationState::AllocationState(AllocationGroup* group)
+    : group_(group), size_(std::numeric_limits<int>::max()), top_(nullptr) {}
+
+MemoryOptimizer::AllocationState::AllocationState(AllocationGroup* group,
+                                                  int size, Node* top)
+    : group_(group), size_(size), top_(top) {}
+
+bool MemoryOptimizer::AllocationState::IsNewSpaceAllocation() const {
+  return group() && group()->IsNewSpaceAllocation();
+}
+
+void MemoryOptimizer::VisitNode(Node* node, AllocationState const* state) {
+  DCHECK(!node->IsDead());
+  DCHECK_LT(0, node->op()->EffectInputCount());
+  switch (node->opcode()) {
+    case IrOpcode::kAllocate:
+      return VisitAllocate(node, state);
+    case IrOpcode::kCall:
+      return VisitCall(node, state);
+    case IrOpcode::kLoadElement:
+      return VisitLoadElement(node, state);
+    case IrOpcode::kLoadField:
+      return VisitLoadField(node, state);
+    case IrOpcode::kStoreElement:
+      return VisitStoreElement(node, state);
+    case IrOpcode::kStoreField:
+      return VisitStoreField(node, state);
+    case IrOpcode::kCheckedLoad:
+    case IrOpcode::kCheckedStore:
+    case IrOpcode::kDeoptimizeIf:
+    case IrOpcode::kDeoptimizeUnless:
+    case IrOpcode::kIfException:
+    case IrOpcode::kLoad:
+    case IrOpcode::kStore:
+      return VisitOtherEffect(node, state);
+    default:
+      break;
+  }
+  DCHECK_EQ(0, node->op()->EffectOutputCount());
+}
+
+void MemoryOptimizer::VisitAllocate(Node* node, AllocationState const* state) {
+  DCHECK_EQ(IrOpcode::kAllocate, node->opcode());
+  Node* value;
+  Node* size = node->InputAt(0);
+  Node* effect = node->InputAt(1);
+  Node* control = node->InputAt(2);
+  PretenureFlag pretenure = OpParameter<PretenureFlag>(node->op());
+
+  // Determine the top/limit addresses.
+  Node* top_address = jsgraph()->ExternalConstant(
+      pretenure == NOT_TENURED
+          ? ExternalReference::new_space_allocation_top_address(isolate())
+          : ExternalReference::old_space_allocation_top_address(isolate()));
+  Node* limit_address = jsgraph()->ExternalConstant(
+      pretenure == NOT_TENURED
+          ? ExternalReference::new_space_allocation_limit_address(isolate())
+          : ExternalReference::old_space_allocation_limit_address(isolate()));
+
+  // Check if we can fold this allocation into a previous allocation represented
+  // by the incoming {state}.
+  Int32Matcher m(size);
+  if (m.HasValue() && m.Value() < Page::kMaxRegularHeapObjectSize) {
+    int32_t const object_size = m.Value();
+    if (state->size() <= Page::kMaxRegularHeapObjectSize - object_size &&
+        state->group()->pretenure() == pretenure) {
+      // We can fold this Allocate {node} into the allocation {group}
+      // represented by the given {state}. Compute the upper bound for
+      // the new {state}.
+      int32_t const state_size = state->size() + object_size;
+
+      // Update the reservation check to the actual maximum upper bound.
+      AllocationGroup* const group = state->group();
+      if (OpParameter<int32_t>(group->size()) < state_size) {
+        NodeProperties::ChangeOp(group->size(),
+                                 common()->Int32Constant(state_size));
+      }
+
+      // Update the allocation top with the new object allocation.
+      // TODO(bmeurer): Defer writing back top as much as possible.
+      Node* top = graph()->NewNode(machine()->IntAdd(), state->top(),
+                                   jsgraph()->IntPtrConstant(object_size));
+      effect = graph()->NewNode(
+          machine()->Store(StoreRepresentation(
+              MachineType::PointerRepresentation(), kNoWriteBarrier)),
+          top_address, jsgraph()->IntPtrConstant(0), top, effect, control);
+
+      // Compute the effective inner allocated address.
+      value = graph()->NewNode(
+          machine()->BitcastWordToTagged(),
+          graph()->NewNode(machine()->IntAdd(), state->top(),
+                           jsgraph()->IntPtrConstant(kHeapObjectTag)));
+
+      // Extend the allocation {group}.
+      group->Add(value);
+      state = AllocationState::Open(group, state_size, top, zone());
+    } else {
+      // Setup a mutable reservation size node; will be patched as we fold
+      // additional allocations into this new group.
+      Node* size = graph()->NewNode(common()->Int32Constant(object_size));
+
+      // Load allocation top and limit.
+      Node* top = effect =
+          graph()->NewNode(machine()->Load(MachineType::Pointer()), top_address,
+                           jsgraph()->IntPtrConstant(0), effect, control);
+      Node* limit = effect = graph()->NewNode(
+          machine()->Load(MachineType::Pointer()), limit_address,
+          jsgraph()->IntPtrConstant(0), effect, control);
+
+      // Check if we need to collect garbage before we can start bump pointer
+      // allocation (always done for folded allocations).
+      Node* check = graph()->NewNode(
+          machine()->UintLessThan(),
+          graph()->NewNode(
+              machine()->IntAdd(), top,
+              machine()->Is64()
+                  ? graph()->NewNode(machine()->ChangeInt32ToInt64(), size)
+                  : size),
+          limit);
+      Node* branch =
+          graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
+
+      Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+      Node* etrue = effect;
+      Node* vtrue = top;
+
+      Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+      Node* efalse = effect;
+      Node* vfalse;
+      {
+        Node* target = pretenure == NOT_TENURED
+                           ? jsgraph()->AllocateInNewSpaceStubConstant()
+                           : jsgraph()->AllocateInOldSpaceStubConstant();
+        if (!allocate_operator_.is_set()) {
+          CallDescriptor* descriptor =
+              Linkage::GetAllocateCallDescriptor(graph()->zone());
+          allocate_operator_.set(common()->Call(descriptor));
+        }
+        vfalse = efalse = graph()->NewNode(allocate_operator_.get(), target,
+                                           size, efalse, if_false);
+        vfalse = graph()->NewNode(machine()->IntSub(), vfalse,
+                                  jsgraph()->IntPtrConstant(kHeapObjectTag));
+      }
+
+      control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+      effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+      value = graph()->NewNode(
+          common()->Phi(MachineType::PointerRepresentation(), 2), vtrue, vfalse,
+          control);
+
+      // Compute the new top and write it back.
+      top = graph()->NewNode(machine()->IntAdd(), value,
+                             jsgraph()->IntPtrConstant(object_size));
+      effect = graph()->NewNode(
+          machine()->Store(StoreRepresentation(
+              MachineType::PointerRepresentation(), kNoWriteBarrier)),
+          top_address, jsgraph()->IntPtrConstant(0), top, effect, control);
+
+      // Compute the initial object address.
+      value = graph()->NewNode(
+          machine()->BitcastWordToTagged(),
+          graph()->NewNode(machine()->IntAdd(), value,
+                           jsgraph()->IntPtrConstant(kHeapObjectTag)));
+
+      // Start a new allocation group.
+      AllocationGroup* group =
+          new (zone()) AllocationGroup(value, pretenure, size, zone());
+      state = AllocationState::Open(group, object_size, top, zone());
+    }
+  } else {
+    // Load allocation top and limit.
+    Node* top = effect =
+        graph()->NewNode(machine()->Load(MachineType::Pointer()), top_address,
+                         jsgraph()->IntPtrConstant(0), effect, control);
+    Node* limit = effect =
+        graph()->NewNode(machine()->Load(MachineType::Pointer()), limit_address,
+                         jsgraph()->IntPtrConstant(0), effect, control);
+
+    // Compute the new top.
+    Node* new_top = graph()->NewNode(
+        machine()->IntAdd(), top,
+        machine()->Is64()
+            ? graph()->NewNode(machine()->ChangeInt32ToInt64(), size)
+            : size);
+
+    // Check if we can do bump pointer allocation here.
+    Node* check = graph()->NewNode(machine()->UintLessThan(), new_top, limit);
+    Node* branch =
+        graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
+
+    Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+    Node* etrue = effect;
+    Node* vtrue;
+    {
+      etrue = graph()->NewNode(
+          machine()->Store(StoreRepresentation(
+              MachineType::PointerRepresentation(), kNoWriteBarrier)),
+          top_address, jsgraph()->IntPtrConstant(0), new_top, etrue, if_true);
+      vtrue = graph()->NewNode(
+          machine()->BitcastWordToTagged(),
+          graph()->NewNode(machine()->IntAdd(), top,
+                           jsgraph()->IntPtrConstant(kHeapObjectTag)));
+    }
+
+    Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+    Node* efalse = effect;
+    Node* vfalse;
+    {
+      Node* target = pretenure == NOT_TENURED
+                         ? jsgraph()->AllocateInNewSpaceStubConstant()
+                         : jsgraph()->AllocateInOldSpaceStubConstant();
+      if (!allocate_operator_.is_set()) {
+        CallDescriptor* descriptor =
+            Linkage::GetAllocateCallDescriptor(graph()->zone());
+        allocate_operator_.set(common()->Call(descriptor));
+      }
+      vfalse = efalse = graph()->NewNode(allocate_operator_.get(), target, size,
+                                         efalse, if_false);
+    }
+
+    control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+    effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+    value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
+                             vtrue, vfalse, control);
+
+    // Create an unfoldable allocation group.
+    AllocationGroup* group =
+        new (zone()) AllocationGroup(value, pretenure, zone());
+    state = AllocationState::Closed(group, zone());
+  }
+
+  // Replace all effect uses of {node} with the {effect}, enqueue the
+  // effect uses for further processing, and replace all value uses of
+  // {node} with the {value}.
+  for (Edge edge : node->use_edges()) {
+    if (NodeProperties::IsEffectEdge(edge)) {
+      EnqueueUse(edge.from(), edge.index(), state);
+      edge.UpdateTo(effect);
+    } else {
+      DCHECK(NodeProperties::IsValueEdge(edge));
+      edge.UpdateTo(value);
+    }
+  }
+
+  // Kill the {node} to make sure we don't leave dangling dead uses.
+  node->Kill();
+}
+
+void MemoryOptimizer::VisitCall(Node* node, AllocationState const* state) {
+  DCHECK_EQ(IrOpcode::kCall, node->opcode());
+  // If the call can allocate, we start with a fresh state.
+  if (!(CallDescriptorOf(node->op())->flags() & CallDescriptor::kNoAllocate)) {
+    state = empty_state();
+  }
+  EnqueueUses(node, state);
+}
+
+void MemoryOptimizer::VisitLoadElement(Node* node,
+                                       AllocationState const* state) {
+  DCHECK_EQ(IrOpcode::kLoadElement, node->opcode());
+  ElementAccess const& access = ElementAccessOf(node->op());
+  Node* index = node->InputAt(1);
+  node->ReplaceInput(1, ComputeIndex(access, index));
+  NodeProperties::ChangeOp(node, machine()->Load(access.machine_type));
+  EnqueueUses(node, state);
+}
+
+void MemoryOptimizer::VisitLoadField(Node* node, AllocationState const* state) {
+  DCHECK_EQ(IrOpcode::kLoadField, node->opcode());
+  FieldAccess const& access = FieldAccessOf(node->op());
+  Node* offset = jsgraph()->IntPtrConstant(access.offset - access.tag());
+  node->InsertInput(graph()->zone(), 1, offset);
+  NodeProperties::ChangeOp(node, machine()->Load(access.machine_type));
+  EnqueueUses(node, state);
+}
+
+void MemoryOptimizer::VisitStoreElement(Node* node,
+                                        AllocationState const* state) {
+  DCHECK_EQ(IrOpcode::kStoreElement, node->opcode());
+  ElementAccess const& access = ElementAccessOf(node->op());
+  Node* object = node->InputAt(0);
+  Node* index = node->InputAt(1);
+  WriteBarrierKind write_barrier_kind =
+      ComputeWriteBarrierKind(object, state, access.write_barrier_kind);
+  node->ReplaceInput(1, ComputeIndex(access, index));
+  NodeProperties::ChangeOp(
+      node, machine()->Store(StoreRepresentation(
+                access.machine_type.representation(), write_barrier_kind)));
+  EnqueueUses(node, state);
+}
+
+void MemoryOptimizer::VisitStoreField(Node* node,
+                                      AllocationState const* state) {
+  DCHECK_EQ(IrOpcode::kStoreField, node->opcode());
+  FieldAccess const& access = FieldAccessOf(node->op());
+  Node* object = node->InputAt(0);
+  WriteBarrierKind write_barrier_kind =
+      ComputeWriteBarrierKind(object, state, access.write_barrier_kind);
+  Node* offset = jsgraph()->IntPtrConstant(access.offset - access.tag());
+  node->InsertInput(graph()->zone(), 1, offset);
+  NodeProperties::ChangeOp(
+      node, machine()->Store(StoreRepresentation(
+                access.machine_type.representation(), write_barrier_kind)));
+  EnqueueUses(node, state);
+}
+
+void MemoryOptimizer::VisitOtherEffect(Node* node,
+                                       AllocationState const* state) {
+  EnqueueUses(node, state);
+}
+
+Node* MemoryOptimizer::ComputeIndex(ElementAccess const& access, Node* key) {
+  Node* index = key;
+  int element_size_shift =
+      ElementSizeLog2Of(access.machine_type.representation());
+  if (element_size_shift) {
+    index = graph()->NewNode(machine()->Word32Shl(), index,
+                             jsgraph()->Int32Constant(element_size_shift));
+  }
+  const int fixed_offset = access.header_size - access.tag();
+  if (fixed_offset) {
+    index = graph()->NewNode(machine()->Int32Add(), index,
+                             jsgraph()->Int32Constant(fixed_offset));
+  }
+  if (machine()->Is64()) {
+    // TODO(turbofan): This is probably only correct for typed arrays, and only
+    // if the typed arrays are at most 2GiB in size, which happens to match
+    // exactly our current situation.
+    index = graph()->NewNode(machine()->ChangeUint32ToUint64(), index);
+  }
+  return index;
+}
+
+WriteBarrierKind MemoryOptimizer::ComputeWriteBarrierKind(
+    Node* object, AllocationState const* state,
+    WriteBarrierKind write_barrier_kind) {
+  if (state->IsNewSpaceAllocation() && state->group()->Contains(object)) {
+    write_barrier_kind = kNoWriteBarrier;
+  }
+  return write_barrier_kind;
+}
+
+MemoryOptimizer::AllocationState const* MemoryOptimizer::MergeStates(
+    AllocationStates const& states) {
+  // Check if all states are the same; or at least if all allocation
+  // states belong to the same allocation group.
+  AllocationState const* state = states.front();
+  AllocationGroup* group = state->group();
+  for (size_t i = 1; i < states.size(); ++i) {
+    if (states[i] != state) state = nullptr;
+    if (states[i]->group() != group) group = nullptr;
+  }
+  if (state == nullptr) {
+    if (group != nullptr) {
+      // We cannot fold any more allocations into this group, but we can still
+      // eliminate write barriers on stores to this group.
+      // TODO(bmeurer): We could potentially just create a Phi here to merge
+      // the various tops; but we need to pay special attention not to create
+      // an unschedulable graph.
+      state = AllocationState::Closed(group, zone());
+    } else {
+      // The states are from different allocation groups.
+      state = empty_state();
+    }
+  }
+  return state;
+}
+
+void MemoryOptimizer::EnqueueMerge(Node* node, int index,
+                                   AllocationState const* state) {
+  DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode());
+  int const input_count = node->InputCount() - 1;
+  DCHECK_LT(0, input_count);
+  Node* const control = node->InputAt(input_count);
+  if (control->opcode() == IrOpcode::kLoop) {
+    // For loops we always start with an empty state at the beginning.
+    if (index == 0) EnqueueUses(node, empty_state());
+  } else {
+    DCHECK_EQ(IrOpcode::kMerge, control->opcode());
+    // Check if we already know about this pending merge.
+    NodeId const id = node->id();
+    auto it = pending_.find(id);
+    if (it == pending_.end()) {
+      // Insert a new pending merge.
+      it = pending_.insert(std::make_pair(id, AllocationStates(zone()))).first;
+    }
+    // Add the next input state.
+    it->second.push_back(state);
+    // Check if states for all inputs are available by now.
+    if (it->second.size() == static_cast<size_t>(input_count)) {
+      // All inputs to this effect merge are done, merge the states given all
+      // input constraints, drop the pending merge and enqueue uses of the
+      // EffectPhi {node}.
+      state = MergeStates(it->second);
+      EnqueueUses(node, state);
+      pending_.erase(it);
+    }
+  }
+}
+
+void MemoryOptimizer::EnqueueUses(Node* node, AllocationState const* state) {
+  for (Edge const edge : node->use_edges()) {
+    if (NodeProperties::IsEffectEdge(edge)) {
+      EnqueueUse(edge.from(), edge.index(), state);
+    }
+  }
+}
+
+void MemoryOptimizer::EnqueueUse(Node* node, int index,
+                                 AllocationState const* state) {
+  if (node->opcode() == IrOpcode::kEffectPhi) {
+    // An EffectPhi represents a merge of different effect chains, which
+    // needs special handling depending on whether the merge is part of a
+    // loop or just a normal control join.
+    EnqueueMerge(node, index, state);
+  } else {
+    Token token = {node, state};
+    tokens_.push(token);
+  }
+}
+
+Graph* MemoryOptimizer::graph() const { return jsgraph()->graph(); }
+
+Isolate* MemoryOptimizer::isolate() const { return jsgraph()->isolate(); }
+
+CommonOperatorBuilder* MemoryOptimizer::common() const {
+  return jsgraph()->common();
+}
+
+MachineOperatorBuilder* MemoryOptimizer::machine() const {
+  return jsgraph()->machine();
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/src/compiler/memory-optimizer.h b/src/compiler/memory-optimizer.h
new file mode 100644
index 0000000..f0cd546
--- /dev/null
+++ b/src/compiler/memory-optimizer.h
@@ -0,0 +1,149 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_MEMORY_OPTIMIZER_H_
+#define V8_COMPILER_MEMORY_OPTIMIZER_H_
+
+#include "src/zone-containers.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+// Forward declarations.
+class CommonOperatorBuilder;
+struct ElementAccess;
+class Graph;
+class JSGraph;
+class MachineOperatorBuilder;
+class Node;
+class Operator;
+
+// NodeIds are identifying numbers for nodes that can be used to index auxiliary
+// out-of-line data associated with each node.
+typedef uint32_t NodeId;
+
+// Lowers all simplified memory access and allocation related nodes (i.e.
+// Allocate, LoadField, StoreField and friends) to machine operators.
+// Performs allocation folding and store write barrier elimination
+// implicitly.
+class MemoryOptimizer final {
+ public:
+  MemoryOptimizer(JSGraph* jsgraph, Zone* zone);
+  ~MemoryOptimizer() {}
+
+  void Optimize();
+
+ private:
+  // An allocation group represents a set of allocations that have been folded
+  // together.
+  class AllocationGroup final : public ZoneObject {
+   public:
+    AllocationGroup(Node* node, PretenureFlag pretenure, Zone* zone);
+    AllocationGroup(Node* node, PretenureFlag pretenure, Node* size,
+                    Zone* zone);
+    ~AllocationGroup() {}
+
+    void Add(Node* object);
+    bool Contains(Node* object) const;
+    bool IsNewSpaceAllocation() const { return pretenure() == NOT_TENURED; }
+
+    PretenureFlag pretenure() const { return pretenure_; }
+    Node* size() const { return size_; }
+
+   private:
+    ZoneSet<NodeId> node_ids_;
+    PretenureFlag const pretenure_;
+    Node* const size_;
+
+    DISALLOW_IMPLICIT_CONSTRUCTORS(AllocationGroup);
+  };
+
+  // An allocation state is propagated on the effect paths through the graph.
+  class AllocationState final : public ZoneObject {
+   public:
+    static AllocationState const* Empty(Zone* zone) {
+      return new (zone) AllocationState();
+    }
+    static AllocationState const* Closed(AllocationGroup* group, Zone* zone) {
+      return new (zone) AllocationState(group);
+    }
+    static AllocationState const* Open(AllocationGroup* group, int size,
+                                       Node* top, Zone* zone) {
+      return new (zone) AllocationState(group, size, top);
+    }
+
+    bool IsNewSpaceAllocation() const;
+
+    AllocationGroup* group() const { return group_; }
+    Node* top() const { return top_; }
+    int size() const { return size_; }
+
+   private:
+    AllocationState();
+    explicit AllocationState(AllocationGroup* group);
+    AllocationState(AllocationGroup* group, int size, Node* top);
+
+    AllocationGroup* const group_;
+    // The upper bound of the combined allocated object size on the current path
+    // (max int if allocation folding is impossible on this path).
+    int const size_;
+    Node* const top_;
+
+    DISALLOW_COPY_AND_ASSIGN(AllocationState);
+  };
+
+  // An array of allocation states used to collect states on merges.
+  typedef ZoneVector<AllocationState const*> AllocationStates;
+
+  // We thread through tokens to represent the current state on a given effect
+  // path through the graph.
+  struct Token {
+    Node* node;
+    AllocationState const* state;
+  };
+
+  void VisitNode(Node*, AllocationState const*);
+  void VisitAllocate(Node*, AllocationState const*);
+  void VisitCall(Node*, AllocationState const*);
+  void VisitLoadElement(Node*, AllocationState const*);
+  void VisitLoadField(Node*, AllocationState const*);
+  void VisitStoreElement(Node*, AllocationState const*);
+  void VisitStoreField(Node*, AllocationState const*);
+  void VisitOtherEffect(Node*, AllocationState const*);
+
+  Node* ComputeIndex(ElementAccess const&, Node*);
+  WriteBarrierKind ComputeWriteBarrierKind(Node* object,
+                                           AllocationState const* state,
+                                           WriteBarrierKind);
+
+  AllocationState const* MergeStates(AllocationStates const& states);
+
+  void EnqueueMerge(Node*, int, AllocationState const*);
+  void EnqueueUses(Node*, AllocationState const*);
+  void EnqueueUse(Node*, int, AllocationState const*);
+
+  AllocationState const* empty_state() const { return empty_state_; }
+  Graph* graph() const;
+  Isolate* isolate() const;
+  JSGraph* jsgraph() const { return jsgraph_; }
+  CommonOperatorBuilder* common() const;
+  MachineOperatorBuilder* machine() const;
+  Zone* zone() const { return zone_; }
+
+  SetOncePointer<const Operator> allocate_operator_;
+  JSGraph* const jsgraph_;
+  AllocationState const* const empty_state_;
+  ZoneMap<NodeId, AllocationStates> pending_;
+  ZoneQueue<Token> tokens_;
+  Zone* const zone_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryOptimizer);
+};
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_COMPILER_MEMORY_OPTIMIZER_H_
diff --git a/src/compiler/mips/code-generator-mips.cc b/src/compiler/mips/code-generator-mips.cc
index 9b0d706..5e30e34 100644
--- a/src/compiler/mips/code-generator-mips.cc
+++ b/src/compiler/mips/code-generator-mips.cc
@@ -119,7 +119,7 @@
 
   MemOperand ToMemOperand(InstructionOperand* op) const {
     DCHECK_NOT_NULL(op);
-    DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
+    DCHECK(op->IsStackSlot() || op->IsFPStackSlot());
     return SlotToMemOperand(AllocatedOperand::cast(op)->index());
   }
 
@@ -472,13 +472,47 @@
     __ bind(&done);                                                           \
   }
 
+#define ASSEMBLE_ATOMIC_LOAD_INTEGER(asm_instr)          \
+  do {                                                   \
+    __ asm_instr(i.OutputRegister(), i.MemoryOperand()); \
+    __ sync();                                           \
+  } while (0)
+
+#define ASSEMBLE_ATOMIC_STORE_INTEGER(asm_instr)         \
+  do {                                                   \
+    __ sync();                                           \
+    __ asm_instr(i.InputRegister(2), i.MemoryOperand()); \
+    __ sync();                                           \
+  } while (0)
+
+#define ASSEMBLE_IEEE754_BINOP(name)                                          \
+  do {                                                                        \
+    FrameScope scope(masm(), StackFrame::MANUAL);                             \
+    __ PrepareCallCFunction(0, 2, kScratchReg);                               \
+    __ MovToFloatParameters(i.InputDoubleRegister(0),                         \
+                            i.InputDoubleRegister(1));                        \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \
+                     0, 2);                                                   \
+    /* Move the result in the double result register. */                      \
+    __ MovFromFloatResult(i.OutputDoubleRegister());                          \
+  } while (0)
+
+#define ASSEMBLE_IEEE754_UNOP(name)                                           \
+  do {                                                                        \
+    FrameScope scope(masm(), StackFrame::MANUAL);                             \
+    __ PrepareCallCFunction(0, 1, kScratchReg);                               \
+    __ MovToFloatParameter(i.InputDoubleRegister(0));                         \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \
+                     0, 1);                                                   \
+    /* Move the result in the double result register. */                      \
+    __ MovFromFloatResult(i.OutputDoubleRegister());                          \
+  } while (0)
+
 void CodeGenerator::AssembleDeconstructFrame() {
   __ mov(sp, fp);
   __ Pop(ra, fp);
 }
 
-void CodeGenerator::AssembleSetupStackPointer() {}
-
 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
   int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
   if (sp_slot_delta > 0) {
@@ -527,7 +561,8 @@
 }
 
 // Assembles an instruction after register allocation, producing machine code.
-void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
+CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
+    Instruction* instr) {
   MipsOperandConverter i(this, instr);
   InstructionCode opcode = instr->opcode();
   ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode);
@@ -564,6 +599,14 @@
       frame_access_state()->ClearSPDelta();
       break;
     }
+    case kArchTailCallAddress: {
+      int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
+      AssembleDeconstructActivationRecord(stack_param_delta);
+      CHECK(!instr->InputAt(0)->IsImmediate());
+      __ Jump(i.InputRegister(0));
+      frame_access_state()->ClearSPDelta();
+      break;
+    }
     case kArchCallJSFunction: {
       EnsureSpaceForLazyDeopt();
       Register func = i.InputRegister(0);
@@ -632,6 +675,14 @@
     case kArchTableSwitch:
       AssembleArchTableSwitch(instr);
       break;
+    case kArchDebugBreak:
+      __ stop("kArchDebugBreak");
+      break;
+    case kArchComment: {
+      Address comment_string = i.InputExternalReference(0).address();
+      __ RecordComment(reinterpret_cast<const char*>(comment_string));
+      break;
+    }
     case kArchNop:
     case kArchThrowTerminator:
       // don't emit code for nops.
@@ -641,7 +692,9 @@
           BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
       Deoptimizer::BailoutType bailout_type =
           Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
-      AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      CodeGenResult result =
+          AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      if (result != kSuccess) return result;
       break;
     }
     case kArchRet:
@@ -688,6 +741,45 @@
               Operand(offset.offset()));
       break;
     }
+    case kIeee754Float64Atan:
+      ASSEMBLE_IEEE754_UNOP(atan);
+      break;
+    case kIeee754Float64Atan2:
+      ASSEMBLE_IEEE754_BINOP(atan2);
+      break;
+    case kIeee754Float64Cos:
+      ASSEMBLE_IEEE754_UNOP(cos);
+      break;
+    case kIeee754Float64Cbrt:
+      ASSEMBLE_IEEE754_UNOP(cbrt);
+      break;
+    case kIeee754Float64Exp:
+      ASSEMBLE_IEEE754_UNOP(exp);
+      break;
+    case kIeee754Float64Expm1:
+      ASSEMBLE_IEEE754_UNOP(expm1);
+      break;
+    case kIeee754Float64Atanh:
+      ASSEMBLE_IEEE754_UNOP(atanh);
+      break;
+    case kIeee754Float64Log:
+      ASSEMBLE_IEEE754_UNOP(log);
+      break;
+    case kIeee754Float64Log1p:
+      ASSEMBLE_IEEE754_UNOP(log1p);
+      break;
+    case kIeee754Float64Log10:
+      ASSEMBLE_IEEE754_UNOP(log10);
+      break;
+    case kIeee754Float64Log2:
+      ASSEMBLE_IEEE754_UNOP(log2);
+      break;
+    case kIeee754Float64Sin:
+      ASSEMBLE_IEEE754_UNOP(sin);
+      break;
+    case kIeee754Float64Tan:
+      ASSEMBLE_IEEE754_UNOP(tan);
+      break;
     case kMipsAdd:
       __ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
       break;
@@ -839,6 +931,36 @@
         __ sra(i.OutputRegister(), i.InputRegister(0), imm);
       }
       break;
+    case kMipsShlPair: {
+      if (instr->InputAt(2)->IsRegister()) {
+        __ ShlPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
+                   i.InputRegister(1), i.InputRegister(2));
+      } else {
+        uint32_t imm = i.InputOperand(2).immediate();
+        __ ShlPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
+                   i.InputRegister(1), imm);
+      }
+    } break;
+    case kMipsShrPair: {
+      if (instr->InputAt(2)->IsRegister()) {
+        __ ShrPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
+                   i.InputRegister(1), i.InputRegister(2));
+      } else {
+        uint32_t imm = i.InputOperand(2).immediate();
+        __ ShrPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
+                   i.InputRegister(1), imm);
+      }
+    } break;
+    case kMipsSarPair: {
+      if (instr->InputAt(2)->IsRegister()) {
+        __ SarPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
+                   i.InputRegister(1), i.InputRegister(2));
+      } else {
+        uint32_t imm = i.InputOperand(2).immediate();
+        __ SarPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
+                   i.InputRegister(1), imm);
+      }
+    } break;
     case kMipsExt:
       __ Ext(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1),
              i.InputInt8(2));
@@ -869,7 +991,11 @@
         __ li(i.OutputRegister(), i.InputOperand(0));
       }
       break;
-
+    case kMipsLsa:
+      DCHECK(instr->InputAt(2)->IsImmediate());
+      __ Lsa(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
+             i.InputInt8(2));
+      break;
     case kMipsCmpS:
       // Psuedo-instruction used for FP cmp/branch. No opcode emitted here.
       break;
@@ -882,6 +1008,11 @@
       __ sub_s(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
                i.InputDoubleRegister(1));
       break;
+    case kMipsSubPreserveNanS:
+      __ SubNanPreservePayloadAndSign_s(i.OutputDoubleRegister(),
+                                        i.InputDoubleRegister(0),
+                                        i.InputDoubleRegister(1));
+      break;
     case kMipsMulS:
       // TODO(plind): add special case: right op is -1.0, see arm port.
       __ mul_s(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
@@ -923,6 +1054,14 @@
     case kMipsCmpD:
       // Psuedo-instruction used for FP cmp/branch. No opcode emitted here.
       break;
+    case kMipsAddPair:
+      __ AddPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
+                 i.InputRegister(1), i.InputRegister(2), i.InputRegister(3));
+      break;
+    case kMipsSubPair:
+      __ SubPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
+                 i.InputRegister(1), i.InputRegister(2), i.InputRegister(3));
+      break;
     case kMipsMulPair: {
       __ Mulu(i.OutputRegister(1), i.OutputRegister(0), i.InputRegister(0),
               i.InputRegister(2));
@@ -940,6 +1079,11 @@
       __ sub_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
                i.InputDoubleRegister(1));
       break;
+    case kMipsSubPreserveNanD:
+      __ SubNanPreservePayloadAndSign_d(i.OutputDoubleRegister(),
+                                        i.InputDoubleRegister(0),
+                                        i.InputDoubleRegister(1));
+      break;
     case kMipsMulD:
       // TODO(plind): add special case: right op is -1.0, see arm port.
       __ mul_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
@@ -1169,6 +1313,20 @@
     case kMipsFloat64InsertHighWord32:
       __ FmoveHigh(i.OutputDoubleRegister(), i.InputRegister(1));
       break;
+    case kMipsFloat64SilenceNaN: {
+      FPURegister value = i.InputDoubleRegister(0);
+      FPURegister result = i.OutputDoubleRegister();
+      Register scratch0 = i.TempRegister(0);
+      Label is_nan, not_nan;
+      __ BranchF(NULL, &is_nan, eq, value, value);
+      __ Branch(&not_nan);
+      __ bind(&is_nan);
+      __ LoadRoot(scratch0, Heap::kNanValueRootIndex);
+      __ ldc1(result, FieldMemOperand(scratch0, HeapNumber::kValueOffset));
+      __ bind(&not_nan);
+      break;
+    }
+
     // ... more basic instructions ...
 
     case kMipsLbu:
@@ -1212,7 +1370,7 @@
       __ sdc1(i.InputDoubleRegister(2), i.MemoryOperand());
       break;
     case kMipsPush:
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ sdc1(i.InputDoubleRegister(0), MemOperand(sp, -kDoubleSize));
         __ Subu(sp, sp, Operand(kDoubleSize));
         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
@@ -1227,8 +1385,14 @@
       break;
     }
     case kMipsStoreToStackSlot: {
-      if (instr->InputAt(0)->IsDoubleRegister()) {
-        __ sdc1(i.InputDoubleRegister(0), MemOperand(sp, i.InputInt32(1)));
+      if (instr->InputAt(0)->IsFPRegister()) {
+        LocationOperand* op = LocationOperand::cast(instr->InputAt(0));
+        if (op->representation() == MachineRepresentation::kFloat64) {
+          __ sdc1(i.InputDoubleRegister(0), MemOperand(sp, i.InputInt32(1)));
+        } else {
+          DCHECK_EQ(MachineRepresentation::kFloat32, op->representation());
+          __ swc1(i.InputSingleRegister(0), MemOperand(sp, i.InputInt32(1)));
+        }
       } else {
         __ sw(i.InputRegister(0), MemOperand(sp, i.InputInt32(1)));
       }
@@ -1274,7 +1438,32 @@
     case kCheckedStoreWord64:
       UNREACHABLE();  // currently unsupported checked int64 load/store.
       break;
+    case kAtomicLoadInt8:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(lb);
+      break;
+    case kAtomicLoadUint8:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(lbu);
+      break;
+    case kAtomicLoadInt16:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(lh);
+      break;
+    case kAtomicLoadUint16:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(lhu);
+      break;
+    case kAtomicLoadWord32:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(lw);
+      break;
+    case kAtomicStoreWord8:
+      ASSEMBLE_ATOMIC_STORE_INTEGER(sb);
+      break;
+    case kAtomicStoreWord16:
+      ASSEMBLE_ATOMIC_STORE_INTEGER(sh);
+      break;
+    case kAtomicStoreWord32:
+      ASSEMBLE_ATOMIC_STORE_INTEGER(sw);
+      break;
   }
+  return kSuccess;
 }  // NOLINT(readability/fn_size)
 
 
@@ -1569,18 +1758,40 @@
   });
 }
 
-
-void CodeGenerator::AssembleDeoptimizerCall(
+CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
     int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
   Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
       isolate(), deoptimization_id, bailout_type);
+  if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
   __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
+  return kSuccess;
 }
 
-
-void CodeGenerator::AssemblePrologue() {
+void CodeGenerator::FinishFrame(Frame* frame) {
   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
-  int stack_shrink_slots = frame()->GetSpillSlotCount();
+
+  const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
+  if (saves_fpu != 0) {
+    frame->AlignSavedCalleeRegisterSlots();
+  }
+
+  if (saves_fpu != 0) {
+    int count = base::bits::CountPopulation32(saves_fpu);
+    DCHECK(kNumCalleeSavedFPU == count);
+    frame->AllocateSavedCalleeRegisterSlots(count *
+                                            (kDoubleSize / kPointerSize));
+  }
+
+  const RegList saves = descriptor->CalleeSavedRegisters();
+  if (saves != 0) {
+    int count = base::bits::CountPopulation32(saves);
+    DCHECK(kNumCalleeSaved == count + 1);
+    frame->AllocateSavedCalleeRegisterSlots(count);
+  }
+}
+
+void CodeGenerator::AssembleConstructFrame() {
+  CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
   if (frame_access_state()->has_frame()) {
     if (descriptor->IsCFunctionCall()) {
       __ Push(ra, fp);
@@ -1592,6 +1803,8 @@
     }
   }
 
+  int shrink_slots = frame()->GetSpillSlotCount();
+
   if (info()->is_osr()) {
     // TurboFan OSR-compiled functions cannot be entered directly.
     __ Abort(kShouldNotDirectlyEnterOsrFunction);
@@ -1602,35 +1815,24 @@
     // remaining stack slots.
     if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
     osr_pc_offset_ = __ pc_offset();
-    stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
+    shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
   }
 
   const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
-  if (saves_fpu != 0) {
-    stack_shrink_slots += frame()->AlignSavedCalleeRegisterSlots();
-  }
-  if (stack_shrink_slots > 0) {
-    __ Subu(sp, sp, Operand(stack_shrink_slots * kPointerSize));
+  if (shrink_slots > 0) {
+    __ Subu(sp, sp, Operand(shrink_slots * kPointerSize));
   }
 
   // Save callee-saved FPU registers.
   if (saves_fpu != 0) {
     __ MultiPushFPU(saves_fpu);
-    int count = base::bits::CountPopulation32(saves_fpu);
-    DCHECK(kNumCalleeSavedFPU == count);
-    frame()->AllocateSavedCalleeRegisterSlots(count *
-                                              (kDoubleSize / kPointerSize));
   }
 
   const RegList saves = descriptor->CalleeSavedRegisters();
   if (saves != 0) {
     // Save callee-saved registers.
     __ MultiPush(saves);
-    // kNumCalleeSaved includes the fp register, but the fp register
-    // is saved separately in TF.
-    int count = base::bits::CountPopulation32(saves);
-    DCHECK(kNumCalleeSaved == count + 1);
-    frame()->AllocateSavedCalleeRegisterSlots(count);
+    DCHECK(kNumCalleeSaved == base::bits::CountPopulation32(saves) + 1);
   }
 }
 
@@ -1701,7 +1903,13 @@
           destination->IsRegister() ? g.ToRegister(destination) : kScratchReg;
       switch (src.type()) {
         case Constant::kInt32:
-          __ li(dst, Operand(src.ToInt32()));
+          if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
+              src.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE ||
+              src.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) {
+            __ li(dst, Operand(src.ToInt32(), src.rmode()));
+          } else {
+            __ li(dst, Operand(src.ToInt32()));
+          }
           break;
         case Constant::kFloat32:
           __ li(dst, isolate()->factory()->NewNumber(src.ToFloat32(), TENURED));
@@ -1734,7 +1942,7 @@
       }
       if (destination->IsStackSlot()) __ sw(dst, g.ToMemOperand(destination));
     } else if (src.type() == Constant::kFloat32) {
-      if (destination->IsDoubleStackSlot()) {
+      if (destination->IsFPStackSlot()) {
         MemOperand dst = g.ToMemOperand(destination);
         __ li(at, Operand(bit_cast<int32_t>(src.ToFloat32())));
         __ sw(at, dst);
@@ -1744,28 +1952,34 @@
       }
     } else {
       DCHECK_EQ(Constant::kFloat64, src.type());
-      DoubleRegister dst = destination->IsDoubleRegister()
+      DoubleRegister dst = destination->IsFPRegister()
                                ? g.ToDoubleRegister(destination)
                                : kScratchDoubleReg;
       __ Move(dst, src.ToFloat64());
-      if (destination->IsDoubleStackSlot()) {
+      if (destination->IsFPStackSlot()) {
         __ sdc1(dst, g.ToMemOperand(destination));
       }
     }
-  } else if (source->IsDoubleRegister()) {
+  } else if (source->IsFPRegister()) {
     FPURegister src = g.ToDoubleRegister(source);
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       FPURegister dst = g.ToDoubleRegister(destination);
       __ Move(dst, src);
     } else {
-      DCHECK(destination->IsDoubleStackSlot());
+      DCHECK(destination->IsFPStackSlot());
       __ sdc1(src, g.ToMemOperand(destination));
     }
-  } else if (source->IsDoubleStackSlot()) {
-    DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
+  } else if (source->IsFPStackSlot()) {
+    DCHECK(destination->IsFPRegister() || destination->IsFPStackSlot());
     MemOperand src = g.ToMemOperand(source);
-    if (destination->IsDoubleRegister()) {
-      __ ldc1(g.ToDoubleRegister(destination), src);
+    if (destination->IsFPRegister()) {
+      LocationOperand* op = LocationOperand::cast(source);
+      if (op->representation() == MachineRepresentation::kFloat64) {
+        __ ldc1(g.ToDoubleRegister(destination), src);
+      } else {
+        DCHECK_EQ(MachineRepresentation::kFloat32, op->representation());
+        __ lwc1(g.ToDoubleRegister(destination), src);
+      }
     } else {
       FPURegister temp = kScratchDoubleReg;
       __ ldc1(temp, src);
@@ -1808,23 +2022,23 @@
     __ lw(temp_1, dst);
     __ sw(temp_0, dst);
     __ sw(temp_1, src);
-  } else if (source->IsDoubleRegister()) {
+  } else if (source->IsFPRegister()) {
     FPURegister temp = kScratchDoubleReg;
     FPURegister src = g.ToDoubleRegister(source);
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       FPURegister dst = g.ToDoubleRegister(destination);
       __ Move(temp, src);
       __ Move(src, dst);
       __ Move(dst, temp);
     } else {
-      DCHECK(destination->IsDoubleStackSlot());
+      DCHECK(destination->IsFPStackSlot());
       MemOperand dst = g.ToMemOperand(destination);
       __ Move(temp, src);
       __ ldc1(src, dst);
       __ sdc1(temp, dst);
     }
-  } else if (source->IsDoubleStackSlot()) {
-    DCHECK(destination->IsDoubleStackSlot());
+  } else if (source->IsFPStackSlot()) {
+    DCHECK(destination->IsFPStackSlot());
     Register temp_0 = kScratchReg;
     FPURegister temp_1 = kScratchDoubleReg;
     MemOperand src0 = g.ToMemOperand(source);
@@ -1850,13 +2064,6 @@
 }
 
 
-void CodeGenerator::AddNopForSmiCodeInlining() {
-  // Unused on 32-bit ARM. Still exists on 64-bit arm.
-  // TODO(plind): Unclear when this is called now. Understand, fix if needed.
-  __ nop();  // Maybe PROPERTY_ACCESS_INLINED?
-}
-
-
 void CodeGenerator::EnsureSpaceForLazyDeopt() {
   if (!info()->ShouldEnsureSpaceForLazyDeopt()) {
     return;
diff --git a/src/compiler/mips/instruction-codes-mips.h b/src/compiler/mips/instruction-codes-mips.h
index d85c2a7..766a5b1 100644
--- a/src/compiler/mips/instruction-codes-mips.h
+++ b/src/compiler/mips/instruction-codes-mips.h
@@ -30,9 +30,13 @@
   V(MipsClz)                       \
   V(MipsCtz)                       \
   V(MipsPopcnt)                    \
+  V(MipsLsa)                       \
   V(MipsShl)                       \
   V(MipsShr)                       \
   V(MipsSar)                       \
+  V(MipsShlPair)                   \
+  V(MipsShrPair)                   \
+  V(MipsSarPair)                   \
   V(MipsExt)                       \
   V(MipsIns)                       \
   V(MipsRor)                       \
@@ -42,6 +46,7 @@
   V(MipsCmpS)                      \
   V(MipsAddS)                      \
   V(MipsSubS)                      \
+  V(MipsSubPreserveNanS)           \
   V(MipsMulS)                      \
   V(MipsDivS)                      \
   V(MipsModS)                      \
@@ -52,6 +57,7 @@
   V(MipsCmpD)                      \
   V(MipsAddD)                      \
   V(MipsSubD)                      \
+  V(MipsSubPreserveNanD)           \
   V(MipsMulD)                      \
   V(MipsDivD)                      \
   V(MipsModD)                      \
@@ -59,6 +65,8 @@
   V(MipsSqrtD)                     \
   V(MipsMaxD)                      \
   V(MipsMinD)                      \
+  V(MipsAddPair)                   \
+  V(MipsSubPair)                   \
   V(MipsMulPair)                   \
   V(MipsFloat32RoundDown)          \
   V(MipsFloat32RoundTruncate)      \
@@ -100,6 +108,7 @@
   V(MipsFloat64ExtractHighWord32)  \
   V(MipsFloat64InsertLowWord32)    \
   V(MipsFloat64InsertHighWord32)   \
+  V(MipsFloat64SilenceNaN)         \
   V(MipsFloat64Max)                \
   V(MipsFloat64Min)                \
   V(MipsFloat32Max)                \
diff --git a/src/compiler/mips/instruction-selector-mips.cc b/src/compiler/mips/instruction-selector-mips.cc
index f86ffe7..c95613e 100644
--- a/src/compiler/mips/instruction-selector-mips.cc
+++ b/src/compiler/mips/instruction-selector-mips.cc
@@ -395,27 +395,71 @@
   VisitRRO(this, kMipsSar, node);
 }
 
-void InstructionSelector::VisitInt32PairAdd(Node* node) { UNIMPLEMENTED(); }
+static void VisitInt32PairBinop(InstructionSelector* selector,
+                                InstructionCode opcode, Node* node) {
+  MipsOperandGenerator g(selector);
 
-void InstructionSelector::VisitInt32PairSub(Node* node) { UNIMPLEMENTED(); }
-
-void InstructionSelector::VisitInt32PairMul(Node* node) {
-  MipsOperandGenerator g(this);
+  // We use UseUniqueRegister here to avoid register sharing with the output
+  // register.
   InstructionOperand inputs[] = {g.UseUniqueRegister(node->InputAt(0)),
                                  g.UseUniqueRegister(node->InputAt(1)),
                                  g.UseUniqueRegister(node->InputAt(2)),
                                  g.UseUniqueRegister(node->InputAt(3))};
+
   InstructionOperand outputs[] = {
       g.DefineAsRegister(node),
       g.DefineAsRegister(NodeProperties::FindProjection(node, 1))};
-  Emit(kMipsMulPair, 2, outputs, 4, inputs);
+  selector->Emit(opcode, 2, outputs, 4, inputs);
 }
 
-void InstructionSelector::VisitWord32PairShl(Node* node) { UNIMPLEMENTED(); }
+void InstructionSelector::VisitInt32PairAdd(Node* node) {
+  VisitInt32PairBinop(this, kMipsAddPair, node);
+}
 
-void InstructionSelector::VisitWord32PairShr(Node* node) { UNIMPLEMENTED(); }
+void InstructionSelector::VisitInt32PairSub(Node* node) {
+  VisitInt32PairBinop(this, kMipsSubPair, node);
+}
 
-void InstructionSelector::VisitWord32PairSar(Node* node) { UNIMPLEMENTED(); }
+void InstructionSelector::VisitInt32PairMul(Node* node) {
+  VisitInt32PairBinop(this, kMipsMulPair, node);
+}
+
+// Shared routine for multiple shift operations.
+static void VisitWord32PairShift(InstructionSelector* selector,
+                                 InstructionCode opcode, Node* node) {
+  MipsOperandGenerator g(selector);
+  Int32Matcher m(node->InputAt(2));
+  InstructionOperand shift_operand;
+  if (m.HasValue()) {
+    shift_operand = g.UseImmediate(m.node());
+  } else {
+    shift_operand = g.UseUniqueRegister(m.node());
+  }
+
+  // We use UseUniqueRegister here to avoid register sharing with the output
+  // register.
+  InstructionOperand inputs[] = {g.UseUniqueRegister(node->InputAt(0)),
+                                 g.UseUniqueRegister(node->InputAt(1)),
+                                 shift_operand};
+
+  InstructionOperand outputs[] = {
+      g.DefineAsRegister(node),
+      g.DefineAsRegister(NodeProperties::FindProjection(node, 1))};
+
+  selector->Emit(opcode, 2, outputs, 3, inputs);
+}
+
+void InstructionSelector::VisitWord32PairShl(Node* node) {
+  VisitWord32PairShift(this, kMipsShlPair, node);
+}
+
+void InstructionSelector::VisitWord32PairShr(Node* node) {
+  VisitWord32PairShift(this, kMipsShrPair, node);
+}
+
+void InstructionSelector::VisitWord32PairSar(Node* node) {
+  VisitWord32PairShift(this, kMipsSarPair, node);
+}
 
 void InstructionSelector::VisitWord32Ror(Node* node) {
   VisitRRO(this, kMipsRor, node);
@@ -444,8 +488,32 @@
 
 void InstructionSelector::VisitInt32Add(Node* node) {
   MipsOperandGenerator g(this);
+  Int32BinopMatcher m(node);
 
-  // TODO(plind): Consider multiply & add optimization from arm port.
+  // Select Lsa for (left + (left_of_right << imm)).
+  if (m.right().opcode() == IrOpcode::kWord32Shl &&
+      CanCover(node, m.left().node()) && CanCover(node, m.right().node())) {
+    Int32BinopMatcher mright(m.right().node());
+    if (mright.right().HasValue()) {
+      int32_t shift_value = static_cast<int32_t>(mright.right().Value());
+      Emit(kMipsLsa, g.DefineAsRegister(node), g.UseRegister(m.left().node()),
+           g.UseRegister(mright.left().node()), g.TempImmediate(shift_value));
+      return;
+    }
+  }
+
+  // Select Lsa for ((left_of_left << imm) + right).
+  if (m.left().opcode() == IrOpcode::kWord32Shl &&
+      CanCover(node, m.right().node()) && CanCover(node, m.left().node())) {
+    Int32BinopMatcher mleft(m.left().node());
+    if (mleft.right().HasValue()) {
+      int32_t shift_value = static_cast<int32_t>(mleft.right().Value());
+      Emit(kMipsLsa, g.DefineAsRegister(node), g.UseRegister(m.right().node()),
+           g.UseRegister(mleft.left().node()), g.TempImmediate(shift_value));
+      return;
+    }
+  }
+
   VisitBinop(this, node, kMipsAdd);
 }
 
@@ -467,12 +535,9 @@
       return;
     }
     if (base::bits::IsPowerOfTwo32(value - 1)) {
-      InstructionOperand temp = g.TempRegister();
-      Emit(kMipsShl | AddressingModeField::encode(kMode_None), temp,
+      Emit(kMipsLsa, g.DefineAsRegister(node), g.UseRegister(m.left().node()),
            g.UseRegister(m.left().node()),
            g.TempImmediate(WhichPowerOf2(value - 1)));
-      Emit(kMipsAdd | AddressingModeField::encode(kMode_None),
-           g.DefineAsRegister(node), g.UseRegister(m.left().node()), temp);
       return;
     }
     if (base::bits::IsPowerOfTwo32(value + 1)) {
@@ -654,17 +719,13 @@
   VisitRR(this, kMipsCvtSD, node);
 }
 
-
-void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
-  switch (TruncationModeOf(node->op())) {
-    case TruncationMode::kJavaScript:
-      return VisitRR(this, kArchTruncateDoubleToI, node);
-    case TruncationMode::kRoundToZero:
-      return VisitRR(this, kMipsTruncWD, node);
-  }
-  UNREACHABLE();
+void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
+  VisitRR(this, kArchTruncateDoubleToI, node);
 }
 
+void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
+  VisitRR(this, kMipsTruncWD, node);
+}
 
 void InstructionSelector::VisitBitcastFloat32ToInt32(Node* node) {
   VisitRR(this, kMipsFloat64ExtractLowWord32, node);
@@ -693,6 +754,9 @@
   VisitRRR(this, kMipsSubS, node);
 }
 
+void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
+  VisitRRR(this, kMipsSubPreserveNanS, node);
+}
 
 void InstructionSelector::VisitFloat64Sub(Node* node) {
   MipsOperandGenerator g(this);
@@ -712,6 +776,9 @@
   VisitRRR(this, kMipsSubD, node);
 }
 
+void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
+  VisitRRR(this, kMipsSubPreserveNanD, node);
+}
 
 void InstructionSelector::VisitFloat32Mul(Node* node) {
   VisitRRR(this, kMipsMulS, node);
@@ -809,7 +876,6 @@
   VisitRR(this, kMipsAbsD, node);
 }
 
-
 void InstructionSelector::VisitFloat32Sqrt(Node* node) {
   VisitRR(this, kMipsSqrtS, node);
 }
@@ -864,6 +930,24 @@
   VisitRR(this, kMipsFloat64RoundTiesEven, node);
 }
 
+void InstructionSelector::VisitFloat32Neg(Node* node) { UNREACHABLE(); }
+
+void InstructionSelector::VisitFloat64Neg(Node* node) { UNREACHABLE(); }
+
+void InstructionSelector::VisitFloat64Ieee754Binop(Node* node,
+                                                   InstructionCode opcode) {
+  MipsOperandGenerator g(this);
+  Emit(opcode, g.DefineAsFixed(node, f0), g.UseFixed(node->InputAt(0), f12),
+       g.UseFixed(node->InputAt(1), f14))
+      ->MarkAsCall();
+}
+
+void InstructionSelector::VisitFloat64Ieee754Unop(Node* node,
+                                                  InstructionCode opcode) {
+  MipsOperandGenerator g(this);
+  Emit(opcode, g.DefineAsFixed(node, f0), g.UseFixed(node->InputAt(0), f12))
+      ->MarkAsCall();
+}
 
 void InstructionSelector::EmitPrepareArguments(
     ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
@@ -999,7 +1083,6 @@
 
 
 namespace {
-
 // Shared routine for multiple compare operations.
 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
                          InstructionOperand left, InstructionOperand right,
@@ -1388,6 +1471,81 @@
        g.UseRegister(left), g.UseRegister(right));
 }
 
+void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
+  MipsOperandGenerator g(this);
+  Node* left = node->InputAt(0);
+  InstructionOperand temps[] = {g.TempRegister()};
+  Emit(kMipsFloat64SilenceNaN, g.DefineSameAsFirst(node), g.UseRegister(left),
+       arraysize(temps), temps);
+}
+
+void InstructionSelector::VisitAtomicLoad(Node* node) {
+  LoadRepresentation load_rep = LoadRepresentationOf(node->op());
+  MipsOperandGenerator g(this);
+  Node* base = node->InputAt(0);
+  Node* index = node->InputAt(1);
+  ArchOpcode opcode = kArchNop;
+  switch (load_rep.representation()) {
+    case MachineRepresentation::kWord8:
+      opcode = load_rep.IsSigned() ? kAtomicLoadInt8 : kAtomicLoadUint8;
+      break;
+    case MachineRepresentation::kWord16:
+      opcode = load_rep.IsSigned() ? kAtomicLoadInt16 : kAtomicLoadUint16;
+      break;
+    case MachineRepresentation::kWord32:
+      opcode = kAtomicLoadWord32;
+      break;
+    default:
+      UNREACHABLE();
+      return;
+  }
+  if (g.CanBeImmediate(index, opcode)) {
+    Emit(opcode | AddressingModeField::encode(kMode_MRI),
+         g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
+  } else {
+    InstructionOperand addr_reg = g.TempRegister();
+    Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg,
+         g.UseRegister(index), g.UseRegister(base));
+    // Emit desired load opcode, using temp addr_reg.
+    Emit(opcode | AddressingModeField::encode(kMode_MRI),
+         g.DefineAsRegister(node), addr_reg, g.TempImmediate(0));
+  }
+}
+
+void InstructionSelector::VisitAtomicStore(Node* node) {
+  MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
+  MipsOperandGenerator g(this);
+  Node* base = node->InputAt(0);
+  Node* index = node->InputAt(1);
+  Node* value = node->InputAt(2);
+  ArchOpcode opcode = kArchNop;
+  switch (rep) {
+    case MachineRepresentation::kWord8:
+      opcode = kAtomicStoreWord8;
+      break;
+    case MachineRepresentation::kWord16:
+      opcode = kAtomicStoreWord16;
+      break;
+    case MachineRepresentation::kWord32:
+      opcode = kAtomicStoreWord32;
+      break;
+    default:
+      UNREACHABLE();
+      return;
+  }
+
+  if (g.CanBeImmediate(index, opcode)) {
+    Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
+         g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value));
+  } else {
+    InstructionOperand addr_reg = g.TempRegister();
+    Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg,
+         g.UseRegister(index), g.UseRegister(base));
+    // Emit desired store opcode, using temp addr_reg.
+    Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
+         addr_reg, g.TempImmediate(0), g.UseRegister(value));
+  }
+}
 
 // static
 MachineOperatorBuilder::Flags
@@ -1415,6 +1573,20 @@
          MachineOperatorBuilder::kFloat32RoundTiesEven;
 }
 
+// static
+MachineOperatorBuilder::AlignmentRequirements
+InstructionSelector::AlignmentRequirements() {
+  if (IsMipsArchVariant(kMips32r6)) {
+    return MachineOperatorBuilder::AlignmentRequirements::
+        FullUnalignedAccessSupport();
+  } else {
+    DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) ||
+           IsMipsArchVariant(kMips32r2));
+    return MachineOperatorBuilder::AlignmentRequirements::
+        NoUnalignedAccessSupport();
+  }
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/src/compiler/mips64/code-generator-mips64.cc b/src/compiler/mips64/code-generator-mips64.cc
index c6341b1..9d4201f 100644
--- a/src/compiler/mips64/code-generator-mips64.cc
+++ b/src/compiler/mips64/code-generator-mips64.cc
@@ -119,7 +119,7 @@
 
   MemOperand ToMemOperand(InstructionOperand* op) const {
     DCHECK_NOT_NULL(op);
-    DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
+    DCHECK(op->IsStackSlot() || op->IsFPStackSlot());
     return SlotToMemOperand(AllocatedOperand::cast(op)->index());
   }
 
@@ -359,7 +359,6 @@
 
 }  // namespace
 
-
 #define ASSEMBLE_CHECKED_LOAD_FLOAT(width, asm_instr)                         \
   do {                                                                        \
     auto result = i.Output##width##Register();                                \
@@ -367,7 +366,8 @@
     if (instr->InputAt(0)->IsRegister()) {                                    \
       auto offset = i.InputRegister(0);                                       \
       __ Branch(USE_DELAY_SLOT, ool->entry(), hs, offset, i.InputOperand(1)); \
-      __ Daddu(kScratchReg, i.InputRegister(2), offset);                      \
+      __ And(kScratchReg, offset, Operand(0xffffffff));                       \
+      __ Daddu(kScratchReg, i.InputRegister(2), kScratchReg);                 \
       __ asm_instr(result, MemOperand(kScratchReg, 0));                       \
     } else {                                                                  \
       int offset = static_cast<int>(i.InputOperand(0).immediate());           \
@@ -377,7 +377,6 @@
     __ bind(ool->exit());                                                     \
   } while (0)
 
-
 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr)                              \
   do {                                                                        \
     auto result = i.OutputRegister();                                         \
@@ -385,7 +384,8 @@
     if (instr->InputAt(0)->IsRegister()) {                                    \
       auto offset = i.InputRegister(0);                                       \
       __ Branch(USE_DELAY_SLOT, ool->entry(), hs, offset, i.InputOperand(1)); \
-      __ Daddu(kScratchReg, i.InputRegister(2), offset);                      \
+      __ And(kScratchReg, offset, Operand(0xffffffff));                       \
+      __ Daddu(kScratchReg, i.InputRegister(2), kScratchReg);                 \
       __ asm_instr(result, MemOperand(kScratchReg, 0));                       \
     } else {                                                                  \
       int offset = static_cast<int>(i.InputOperand(0).immediate());           \
@@ -395,7 +395,6 @@
     __ bind(ool->exit());                                                     \
   } while (0)
 
-
 #define ASSEMBLE_CHECKED_STORE_FLOAT(width, asm_instr)                 \
   do {                                                                 \
     Label done;                                                        \
@@ -403,7 +402,8 @@
       auto offset = i.InputRegister(0);                                \
       auto value = i.Input##width##Register(2);                        \
       __ Branch(USE_DELAY_SLOT, &done, hs, offset, i.InputOperand(1)); \
-      __ Daddu(kScratchReg, i.InputRegister(3), offset);               \
+      __ And(kScratchReg, offset, Operand(0xffffffff));                \
+      __ Daddu(kScratchReg, i.InputRegister(3), kScratchReg);          \
       __ asm_instr(value, MemOperand(kScratchReg, 0));                 \
     } else {                                                           \
       int offset = static_cast<int>(i.InputOperand(0).immediate());    \
@@ -414,7 +414,6 @@
     __ bind(&done);                                                    \
   } while (0)
 
-
 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr)                      \
   do {                                                                 \
     Label done;                                                        \
@@ -422,7 +421,8 @@
       auto offset = i.InputRegister(0);                                \
       auto value = i.InputRegister(2);                                 \
       __ Branch(USE_DELAY_SLOT, &done, hs, offset, i.InputOperand(1)); \
-      __ Daddu(kScratchReg, i.InputRegister(3), offset);               \
+      __ And(kScratchReg, offset, Operand(0xffffffff));                \
+      __ Daddu(kScratchReg, i.InputRegister(3), kScratchReg);          \
       __ asm_instr(value, MemOperand(kScratchReg, 0));                 \
     } else {                                                           \
       int offset = static_cast<int>(i.InputOperand(0).immediate());    \
@@ -433,7 +433,6 @@
     __ bind(&done);                                                    \
   } while (0)
 
-
 #define ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(mode)                                  \
   if (kArchVariant == kMips64r6) {                                             \
     __ cfc1(kScratchReg, FCSR);                                                \
@@ -484,13 +483,47 @@
     __ bind(&done);                                                           \
   }
 
+#define ASSEMBLE_ATOMIC_LOAD_INTEGER(asm_instr)          \
+  do {                                                   \
+    __ asm_instr(i.OutputRegister(), i.MemoryOperand()); \
+    __ sync();                                           \
+  } while (0)
+
+#define ASSEMBLE_ATOMIC_STORE_INTEGER(asm_instr)         \
+  do {                                                   \
+    __ sync();                                           \
+    __ asm_instr(i.InputRegister(2), i.MemoryOperand()); \
+    __ sync();                                           \
+  } while (0)
+
+#define ASSEMBLE_IEEE754_BINOP(name)                                          \
+  do {                                                                        \
+    FrameScope scope(masm(), StackFrame::MANUAL);                             \
+    __ PrepareCallCFunction(0, 2, kScratchReg);                               \
+    __ MovToFloatParameters(i.InputDoubleRegister(0),                         \
+                            i.InputDoubleRegister(1));                        \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \
+                     0, 2);                                                   \
+    /* Move the result in the double result register. */                      \
+    __ MovFromFloatResult(i.OutputDoubleRegister());                          \
+  } while (0)
+
+#define ASSEMBLE_IEEE754_UNOP(name)                                           \
+  do {                                                                        \
+    FrameScope scope(masm(), StackFrame::MANUAL);                             \
+    __ PrepareCallCFunction(0, 1, kScratchReg);                               \
+    __ MovToFloatParameter(i.InputDoubleRegister(0));                         \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \
+                     0, 1);                                                   \
+    /* Move the result in the double result register. */                      \
+    __ MovFromFloatResult(i.OutputDoubleRegister());                          \
+  } while (0)
+
 void CodeGenerator::AssembleDeconstructFrame() {
   __ mov(sp, fp);
   __ Pop(ra, fp);
 }
 
-void CodeGenerator::AssembleSetupStackPointer() {}
-
 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
   int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
   if (sp_slot_delta > 0) {
@@ -539,7 +572,8 @@
 }
 
 // Assembles an instruction after register allocation, producing machine code.
-void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
+CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
+    Instruction* instr) {
   MipsOperandConverter i(this, instr);
   InstructionCode opcode = instr->opcode();
   ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode);
@@ -576,6 +610,14 @@
       frame_access_state()->ClearSPDelta();
       break;
     }
+    case kArchTailCallAddress: {
+      int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
+      AssembleDeconstructActivationRecord(stack_param_delta);
+      CHECK(!instr->InputAt(0)->IsImmediate());
+      __ Jump(i.InputRegister(0));
+      frame_access_state()->ClearSPDelta();
+      break;
+    }
     case kArchCallJSFunction: {
       EnsureSpaceForLazyDeopt();
       Register func = i.InputRegister(0);
@@ -642,6 +684,14 @@
     case kArchTableSwitch:
       AssembleArchTableSwitch(instr);
       break;
+    case kArchDebugBreak:
+      __ stop("kArchDebugBreak");
+      break;
+    case kArchComment: {
+      Address comment_string = i.InputExternalReference(0).address();
+      __ RecordComment(reinterpret_cast<const char*>(comment_string));
+      break;
+    }
     case kArchNop:
     case kArchThrowTerminator:
       // don't emit code for nops.
@@ -651,7 +701,9 @@
           BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
       Deoptimizer::BailoutType bailout_type =
           Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
-      AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      CodeGenResult result =
+          AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      if (result != kSuccess) return result;
       break;
     }
     case kArchRet:
@@ -698,6 +750,45 @@
                Operand(offset.offset()));
       break;
     }
+    case kIeee754Float64Atan:
+      ASSEMBLE_IEEE754_UNOP(atan);
+      break;
+    case kIeee754Float64Atan2:
+      ASSEMBLE_IEEE754_BINOP(atan2);
+      break;
+    case kIeee754Float64Atanh:
+      ASSEMBLE_IEEE754_UNOP(atanh);
+      break;
+    case kIeee754Float64Cos:
+      ASSEMBLE_IEEE754_UNOP(cos);
+      break;
+    case kIeee754Float64Cbrt:
+      ASSEMBLE_IEEE754_UNOP(cbrt);
+      break;
+    case kIeee754Float64Exp:
+      ASSEMBLE_IEEE754_UNOP(exp);
+      break;
+    case kIeee754Float64Expm1:
+      ASSEMBLE_IEEE754_UNOP(expm1);
+      break;
+    case kIeee754Float64Log:
+      ASSEMBLE_IEEE754_UNOP(log);
+      break;
+    case kIeee754Float64Log1p:
+      ASSEMBLE_IEEE754_UNOP(log1p);
+      break;
+    case kIeee754Float64Log2:
+      ASSEMBLE_IEEE754_UNOP(log2);
+      break;
+    case kIeee754Float64Log10:
+      ASSEMBLE_IEEE754_UNOP(log10);
+      break;
+    case kIeee754Float64Sin:
+      ASSEMBLE_IEEE754_UNOP(sin);
+      break;
+    case kIeee754Float64Tan:
+      ASSEMBLE_IEEE754_UNOP(tan);
+      break;
     case kMips64Add:
       __ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
       break;
@@ -775,6 +866,16 @@
     case kMips64DmodU:
       __ Dmodu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
       break;
+    case kMips64Dlsa:
+      DCHECK(instr->InputAt(2)->IsImmediate());
+      __ Dlsa(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
+              i.InputInt8(2));
+      break;
+    case kMips64Lsa:
+      DCHECK(instr->InputAt(2)->IsImmediate());
+      __ Lsa(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
+             i.InputInt8(2));
+      break;
     case kMips64And:
       __ And(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
       break;
@@ -1071,6 +1172,11 @@
       __ sub_s(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
                i.InputDoubleRegister(1));
       break;
+    case kMips64SubPreserveNanS:
+      __ SubNanPreservePayloadAndSign_s(i.OutputDoubleRegister(),
+                                        i.InputDoubleRegister(0),
+                                        i.InputDoubleRegister(1));
+      break;
     case kMips64MulS:
       // TODO(plind): add special case: right op is -1.0, see arm port.
       __ mul_s(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
@@ -1121,6 +1227,11 @@
       __ sub_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
                i.InputDoubleRegister(1));
       break;
+    case kMips64SubPreserveNanD:
+      __ SubNanPreservePayloadAndSign_d(i.OutputDoubleRegister(),
+                                        i.InputDoubleRegister(0),
+                                        i.InputDoubleRegister(1));
+      break;
     case kMips64MulD:
       // TODO(plind): add special case: right op is -1.0, see arm port.
       __ mul_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
@@ -1218,6 +1329,9 @@
       }
       break;
     }
+    case kMips64Float64SilenceNaN:
+      __ FPUCanonicalizeNaN(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
+      break;
     case kMips64Float32Max: {
       // (b < a) ? a : b
       if (kArchVariant == kMips64r6) {
@@ -1466,6 +1580,9 @@
     case kMips64Lw:
       __ lw(i.OutputRegister(), i.MemoryOperand());
       break;
+    case kMips64Lwu:
+      __ lwu(i.OutputRegister(), i.MemoryOperand());
+      break;
     case kMips64Ld:
       __ ld(i.OutputRegister(), i.MemoryOperand());
       break;
@@ -1492,7 +1609,7 @@
       __ sdc1(i.InputDoubleRegister(2), i.MemoryOperand());
       break;
     case kMips64Push:
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ sdc1(i.InputDoubleRegister(0), MemOperand(sp, -kDoubleSize));
         __ Subu(sp, sp, Operand(kDoubleSize));
         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
@@ -1507,7 +1624,7 @@
       break;
     }
     case kMips64StoreToStackSlot: {
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ sdc1(i.InputDoubleRegister(0), MemOperand(sp, i.InputInt32(1)));
       } else {
         __ sd(i.InputRegister(0), MemOperand(sp, i.InputInt32(1)));
@@ -1556,7 +1673,32 @@
     case kCheckedStoreFloat64:
       ASSEMBLE_CHECKED_STORE_FLOAT(Double, sdc1);
       break;
+    case kAtomicLoadInt8:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(lb);
+      break;
+    case kAtomicLoadUint8:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(lbu);
+      break;
+    case kAtomicLoadInt16:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(lh);
+      break;
+    case kAtomicLoadUint16:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(lhu);
+      break;
+    case kAtomicLoadWord32:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(lw);
+      break;
+    case kAtomicStoreWord8:
+      ASSEMBLE_ATOMIC_STORE_INTEGER(sb);
+      break;
+    case kAtomicStoreWord16:
+      ASSEMBLE_ATOMIC_STORE_INTEGER(sh);
+      break;
+    case kAtomicStoreWord32:
+      ASSEMBLE_ATOMIC_STORE_INTEGER(sw);
+      break;
   }
+  return kSuccess;
 }  // NOLINT(readability/fn_size)
 
 
@@ -1868,16 +2010,35 @@
   });
 }
 
-
-void CodeGenerator::AssembleDeoptimizerCall(
+CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
     int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
   Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
       isolate(), deoptimization_id, bailout_type);
+  if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
   __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
+  return kSuccess;
 }
 
+void CodeGenerator::FinishFrame(Frame* frame) {
+  CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
 
-void CodeGenerator::AssemblePrologue() {
+  const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
+  if (saves_fpu != 0) {
+    int count = base::bits::CountPopulation32(saves_fpu);
+    DCHECK(kNumCalleeSavedFPU == count);
+    frame->AllocateSavedCalleeRegisterSlots(count *
+                                            (kDoubleSize / kPointerSize));
+  }
+
+  const RegList saves = descriptor->CalleeSavedRegisters();
+  if (saves != 0) {
+    int count = base::bits::CountPopulation32(saves);
+    DCHECK(kNumCalleeSaved == count + 1);
+    frame->AllocateSavedCalleeRegisterSlots(count);
+  }
+}
+
+void CodeGenerator::AssembleConstructFrame() {
   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
   if (frame_access_state()->has_frame()) {
     if (descriptor->IsCFunctionCall()) {
@@ -1890,7 +2051,8 @@
     }
   }
 
-  int stack_shrink_slots = frame()->GetSpillSlotCount();
+  int shrink_slots = frame()->GetSpillSlotCount();
+
   if (info()->is_osr()) {
     // TurboFan OSR-compiled functions cannot be entered directly.
     __ Abort(kShouldNotDirectlyEnterOsrFunction);
@@ -1901,32 +2063,25 @@
     // remaining stack slots.
     if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
     osr_pc_offset_ = __ pc_offset();
-    stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
+    shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
   }
 
-  if (stack_shrink_slots > 0) {
-    __ Dsubu(sp, sp, Operand(stack_shrink_slots * kPointerSize));
+  if (shrink_slots > 0) {
+    __ Dsubu(sp, sp, Operand(shrink_slots * kPointerSize));
   }
 
   const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
   if (saves_fpu != 0) {
     // Save callee-saved FPU registers.
     __ MultiPushFPU(saves_fpu);
-    int count = base::bits::CountPopulation32(saves_fpu);
-    DCHECK(kNumCalleeSavedFPU == count);
-    frame()->AllocateSavedCalleeRegisterSlots(count *
-                                              (kDoubleSize / kPointerSize));
+    DCHECK(kNumCalleeSavedFPU == base::bits::CountPopulation32(saves_fpu));
   }
 
   const RegList saves = descriptor->CalleeSavedRegisters();
   if (saves != 0) {
     // Save callee-saved registers.
     __ MultiPush(saves);
-    // kNumCalleeSaved includes the fp register, but the fp register
-    // is saved separately in TF.
-    int count = base::bits::CountPopulation32(saves);
-    DCHECK(kNumCalleeSaved == count + 1);
-    frame()->AllocateSavedCalleeRegisterSlots(count);
+    DCHECK(kNumCalleeSaved == base::bits::CountPopulation32(saves) + 1);
   }
 }
 
@@ -1997,13 +2152,23 @@
           destination->IsRegister() ? g.ToRegister(destination) : kScratchReg;
       switch (src.type()) {
         case Constant::kInt32:
-          __ li(dst, Operand(src.ToInt32()));
+          if (src.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) {
+            __ li(dst, Operand(src.ToInt32(), src.rmode()));
+          } else {
+            __ li(dst, Operand(src.ToInt32()));
+          }
           break;
         case Constant::kFloat32:
           __ li(dst, isolate()->factory()->NewNumber(src.ToFloat32(), TENURED));
           break;
         case Constant::kInt64:
-          __ li(dst, Operand(src.ToInt64()));
+          if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
+              src.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE) {
+            __ li(dst, Operand(src.ToInt64(), src.rmode()));
+          } else {
+            DCHECK(src.rmode() != RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
+            __ li(dst, Operand(src.ToInt64()));
+          }
           break;
         case Constant::kFloat64:
           __ li(dst, isolate()->factory()->NewNumber(src.ToFloat64(), TENURED));
@@ -2030,7 +2195,7 @@
       }
       if (destination->IsStackSlot()) __ sd(dst, g.ToMemOperand(destination));
     } else if (src.type() == Constant::kFloat32) {
-      if (destination->IsDoubleStackSlot()) {
+      if (destination->IsFPStackSlot()) {
         MemOperand dst = g.ToMemOperand(destination);
         __ li(at, Operand(bit_cast<int32_t>(src.ToFloat32())));
         __ sw(at, dst);
@@ -2040,27 +2205,27 @@
       }
     } else {
       DCHECK_EQ(Constant::kFloat64, src.type());
-      DoubleRegister dst = destination->IsDoubleRegister()
+      DoubleRegister dst = destination->IsFPRegister()
                                ? g.ToDoubleRegister(destination)
                                : kScratchDoubleReg;
       __ Move(dst, src.ToFloat64());
-      if (destination->IsDoubleStackSlot()) {
+      if (destination->IsFPStackSlot()) {
         __ sdc1(dst, g.ToMemOperand(destination));
       }
     }
-  } else if (source->IsDoubleRegister()) {
+  } else if (source->IsFPRegister()) {
     FPURegister src = g.ToDoubleRegister(source);
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       FPURegister dst = g.ToDoubleRegister(destination);
       __ Move(dst, src);
     } else {
-      DCHECK(destination->IsDoubleStackSlot());
+      DCHECK(destination->IsFPStackSlot());
       __ sdc1(src, g.ToMemOperand(destination));
     }
-  } else if (source->IsDoubleStackSlot()) {
-    DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
+  } else if (source->IsFPStackSlot()) {
+    DCHECK(destination->IsFPRegister() || destination->IsFPStackSlot());
     MemOperand src = g.ToMemOperand(source);
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       __ ldc1(g.ToDoubleRegister(destination), src);
     } else {
       FPURegister temp = kScratchDoubleReg;
@@ -2104,23 +2269,23 @@
     __ ld(temp_1, dst);
     __ sd(temp_0, dst);
     __ sd(temp_1, src);
-  } else if (source->IsDoubleRegister()) {
+  } else if (source->IsFPRegister()) {
     FPURegister temp = kScratchDoubleReg;
     FPURegister src = g.ToDoubleRegister(source);
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       FPURegister dst = g.ToDoubleRegister(destination);
       __ Move(temp, src);
       __ Move(src, dst);
       __ Move(dst, temp);
     } else {
-      DCHECK(destination->IsDoubleStackSlot());
+      DCHECK(destination->IsFPStackSlot());
       MemOperand dst = g.ToMemOperand(destination);
       __ Move(temp, src);
       __ ldc1(src, dst);
       __ sdc1(temp, dst);
     }
-  } else if (source->IsDoubleStackSlot()) {
-    DCHECK(destination->IsDoubleStackSlot());
+  } else if (source->IsFPStackSlot()) {
+    DCHECK(destination->IsFPStackSlot());
     Register temp_0 = kScratchReg;
     FPURegister temp_1 = kScratchDoubleReg;
     MemOperand src0 = g.ToMemOperand(source);
@@ -2146,13 +2311,6 @@
 }
 
 
-void CodeGenerator::AddNopForSmiCodeInlining() {
-  // Unused on 32-bit ARM. Still exists on 64-bit arm.
-  // TODO(plind): Unclear when this is called now. Understand, fix if needed.
-  __ nop();  // Maybe PROPERTY_ACCESS_INLINED?
-}
-
-
 void CodeGenerator::EnsureSpaceForLazyDeopt() {
   if (!info()->ShouldEnsureSpaceForLazyDeopt()) {
     return;
diff --git a/src/compiler/mips64/instruction-codes-mips64.h b/src/compiler/mips64/instruction-codes-mips64.h
index 9e94c09..67c84f1 100644
--- a/src/compiler/mips64/instruction-codes-mips64.h
+++ b/src/compiler/mips64/instruction-codes-mips64.h
@@ -36,6 +36,8 @@
   V(Mips64Nor)                      \
   V(Mips64Xor)                      \
   V(Mips64Clz)                      \
+  V(Mips64Lsa)                      \
+  V(Mips64Dlsa)                     \
   V(Mips64Shl)                      \
   V(Mips64Shr)                      \
   V(Mips64Sar)                      \
@@ -59,6 +61,7 @@
   V(Mips64CmpS)                     \
   V(Mips64AddS)                     \
   V(Mips64SubS)                     \
+  V(Mips64SubPreserveNanS)          \
   V(Mips64MulS)                     \
   V(Mips64DivS)                     \
   V(Mips64ModS)                     \
@@ -69,6 +72,7 @@
   V(Mips64CmpD)                     \
   V(Mips64AddD)                     \
   V(Mips64SubD)                     \
+  V(Mips64SubPreserveNanD)          \
   V(Mips64MulD)                     \
   V(Mips64DivD)                     \
   V(Mips64ModD)                     \
@@ -114,9 +118,10 @@
   V(Mips64Lh)                       \
   V(Mips64Lhu)                      \
   V(Mips64Sh)                       \
-  V(Mips64Ld)                       \
   V(Mips64Lw)                       \
+  V(Mips64Lwu)                      \
   V(Mips64Sw)                       \
+  V(Mips64Ld)                       \
   V(Mips64Sd)                       \
   V(Mips64Lwc1)                     \
   V(Mips64Swc1)                     \
@@ -130,6 +135,7 @@
   V(Mips64Float64InsertHighWord32)  \
   V(Mips64Float64Max)               \
   V(Mips64Float64Min)               \
+  V(Mips64Float64SilenceNaN)        \
   V(Mips64Float32Max)               \
   V(Mips64Float32Min)               \
   V(Mips64Push)                     \
diff --git a/src/compiler/mips64/instruction-selector-mips64.cc b/src/compiler/mips64/instruction-selector-mips64.cc
index 5e2b5f2..3e1f98e 100644
--- a/src/compiler/mips64/instruction-selector-mips64.cc
+++ b/src/compiler/mips64/instruction-selector-mips64.cc
@@ -158,7 +158,7 @@
       opcode = load_rep.IsUnsigned() ? kMips64Lhu : kMips64Lh;
       break;
     case MachineRepresentation::kWord32:
-      opcode = kMips64Lw;
+      opcode = load_rep.IsUnsigned() ? kMips64Lwu : kMips64Lw;
       break;
     case MachineRepresentation::kTagged:  // Fall through.
     case MachineRepresentation::kWord64:
@@ -611,14 +611,66 @@
 
 void InstructionSelector::VisitInt32Add(Node* node) {
   Mips64OperandGenerator g(this);
-  // TODO(plind): Consider multiply & add optimization from arm port.
+  Int32BinopMatcher m(node);
+
+  // Select Lsa for (left + (left_of_right << imm)).
+  if (m.right().opcode() == IrOpcode::kWord32Shl &&
+      CanCover(node, m.left().node()) && CanCover(node, m.right().node())) {
+    Int32BinopMatcher mright(m.right().node());
+    if (mright.right().HasValue()) {
+      int32_t shift_value = static_cast<int32_t>(mright.right().Value());
+      Emit(kMips64Lsa, g.DefineAsRegister(node), g.UseRegister(m.left().node()),
+           g.UseRegister(mright.left().node()), g.TempImmediate(shift_value));
+      return;
+    }
+  }
+
+  // Select Lsa for ((left_of_left << imm) + right).
+  if (m.left().opcode() == IrOpcode::kWord32Shl &&
+      CanCover(node, m.right().node()) && CanCover(node, m.left().node())) {
+    Int32BinopMatcher mleft(m.left().node());
+    if (mleft.right().HasValue()) {
+      int32_t shift_value = static_cast<int32_t>(mleft.right().Value());
+      Emit(kMips64Lsa, g.DefineAsRegister(node),
+           g.UseRegister(m.right().node()), g.UseRegister(mleft.left().node()),
+           g.TempImmediate(shift_value));
+      return;
+    }
+  }
   VisitBinop(this, node, kMips64Add);
 }
 
 
 void InstructionSelector::VisitInt64Add(Node* node) {
   Mips64OperandGenerator g(this);
-  // TODO(plind): Consider multiply & add optimization from arm port.
+  Int64BinopMatcher m(node);
+
+  // Select Dlsa for (left + (left_of_right << imm)).
+  if (m.right().opcode() == IrOpcode::kWord64Shl &&
+      CanCover(node, m.left().node()) && CanCover(node, m.right().node())) {
+    Int64BinopMatcher mright(m.right().node());
+    if (mright.right().HasValue()) {
+      int32_t shift_value = static_cast<int32_t>(mright.right().Value());
+      Emit(kMips64Dlsa, g.DefineAsRegister(node),
+           g.UseRegister(m.left().node()), g.UseRegister(mright.left().node()),
+           g.TempImmediate(shift_value));
+      return;
+    }
+  }
+
+  // Select Dlsa for ((left_of_left << imm) + right).
+  if (m.left().opcode() == IrOpcode::kWord64Shl &&
+      CanCover(node, m.right().node()) && CanCover(node, m.left().node())) {
+    Int64BinopMatcher mleft(m.left().node());
+    if (mleft.right().HasValue()) {
+      int32_t shift_value = static_cast<int32_t>(mleft.right().Value());
+      Emit(kMips64Dlsa, g.DefineAsRegister(node),
+           g.UseRegister(m.right().node()), g.UseRegister(mleft.left().node()),
+           g.TempImmediate(shift_value));
+      return;
+    }
+  }
+
   VisitBinop(this, node, kMips64Dadd);
 }
 
@@ -645,12 +697,9 @@
       return;
     }
     if (base::bits::IsPowerOfTwo32(value - 1)) {
-      InstructionOperand temp = g.TempRegister();
-      Emit(kMips64Shl | AddressingModeField::encode(kMode_None), temp,
+      Emit(kMips64Lsa, g.DefineAsRegister(node), g.UseRegister(m.left().node()),
            g.UseRegister(m.left().node()),
            g.TempImmediate(WhichPowerOf2(value - 1)));
-      Emit(kMips64Add | AddressingModeField::encode(kMode_None),
-           g.DefineAsRegister(node), g.UseRegister(m.left().node()), temp);
       return;
     }
     if (base::bits::IsPowerOfTwo32(value + 1)) {
@@ -705,12 +754,10 @@
       return;
     }
     if (base::bits::IsPowerOfTwo32(value - 1)) {
-      InstructionOperand temp = g.TempRegister();
-      Emit(kMips64Dshl | AddressingModeField::encode(kMode_None), temp,
-           g.UseRegister(m.left().node()),
+      // Dlsa macro will handle the shifting value out of bound cases.
+      Emit(kMips64Dlsa, g.DefineAsRegister(node),
+           g.UseRegister(m.left().node()), g.UseRegister(m.left().node()),
            g.TempImmediate(WhichPowerOf2(value - 1)));
-      Emit(kMips64Dadd | AddressingModeField::encode(kMode_None),
-           g.DefineAsRegister(node), g.UseRegister(m.left().node()), temp);
       return;
     }
     if (base::bits::IsPowerOfTwo32(value + 1)) {
@@ -1047,17 +1094,13 @@
   VisitRR(this, kMips64CvtSD, node);
 }
 
-
-void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
-  switch (TruncationModeOf(node->op())) {
-    case TruncationMode::kJavaScript:
-      return VisitRR(this, kArchTruncateDoubleToI, node);
-    case TruncationMode::kRoundToZero:
-      return VisitRR(this, kMips64TruncWD, node);
-  }
-  UNREACHABLE();
+void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
+  VisitRR(this, kArchTruncateDoubleToI, node);
 }
 
+void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
+  VisitRR(this, kMips64TruncWD, node);
+}
 
 void InstructionSelector::VisitRoundInt64ToFloat32(Node* node) {
   VisitRR(this, kMips64CvtSL, node);
@@ -1116,6 +1159,9 @@
   VisitRRR(this, kMips64SubS, node);
 }
 
+void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
+  VisitRRR(this, kMips64SubPreserveNanS, node);
+}
 
 void InstructionSelector::VisitFloat64Sub(Node* node) {
   Mips64OperandGenerator g(this);
@@ -1135,6 +1181,9 @@
   VisitRRR(this, kMips64SubD, node);
 }
 
+void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
+  VisitRRR(this, kMips64SubPreserveNanD, node);
+}
 
 void InstructionSelector::VisitFloat32Mul(Node* node) {
   VisitRRR(this, kMips64MulS, node);
@@ -1233,7 +1282,6 @@
   VisitRR(this, kMips64AbsD, node);
 }
 
-
 void InstructionSelector::VisitFloat32Sqrt(Node* node) {
   VisitRR(this, kMips64SqrtS, node);
 }
@@ -1288,6 +1336,24 @@
   VisitRR(this, kMips64Float64RoundTiesEven, node);
 }
 
+void InstructionSelector::VisitFloat32Neg(Node* node) { UNREACHABLE(); }
+
+void InstructionSelector::VisitFloat64Neg(Node* node) { UNREACHABLE(); }
+
+void InstructionSelector::VisitFloat64Ieee754Binop(Node* node,
+                                                   InstructionCode opcode) {
+  Mips64OperandGenerator g(this);
+  Emit(opcode, g.DefineAsFixed(node, f0), g.UseFixed(node->InputAt(0), f12),
+       g.UseFixed(node->InputAt(1), f14))
+      ->MarkAsCall();
+}
+
+void InstructionSelector::VisitFloat64Ieee754Unop(Node* node,
+                                                  InstructionCode opcode) {
+  Mips64OperandGenerator g(this);
+  Emit(opcode, g.DefineAsFixed(node, f0), g.UseFixed(node->InputAt(0), f12))
+      ->MarkAsCall();
+}
 
 void InstructionSelector::EmitPrepareArguments(
     ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
@@ -1898,6 +1964,9 @@
   VisitRR(this, kMips64Float64ExtractHighWord32, node);
 }
 
+void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
+  VisitRR(this, kMips64Float64SilenceNaN, node);
+}
 
 void InstructionSelector::VisitFloat64InsertLowWord32(Node* node) {
   Mips64OperandGenerator g(this);
@@ -1916,6 +1985,73 @@
        g.UseRegister(left), g.UseRegister(right));
 }
 
+void InstructionSelector::VisitAtomicLoad(Node* node) {
+  LoadRepresentation load_rep = LoadRepresentationOf(node->op());
+  Mips64OperandGenerator g(this);
+  Node* base = node->InputAt(0);
+  Node* index = node->InputAt(1);
+  ArchOpcode opcode = kArchNop;
+  switch (load_rep.representation()) {
+    case MachineRepresentation::kWord8:
+      opcode = load_rep.IsSigned() ? kAtomicLoadInt8 : kAtomicLoadUint8;
+      break;
+    case MachineRepresentation::kWord16:
+      opcode = load_rep.IsSigned() ? kAtomicLoadInt16 : kAtomicLoadUint16;
+      break;
+    case MachineRepresentation::kWord32:
+      opcode = kAtomicLoadWord32;
+      break;
+    default:
+      UNREACHABLE();
+      return;
+  }
+  if (g.CanBeImmediate(index, opcode)) {
+    Emit(opcode | AddressingModeField::encode(kMode_MRI),
+         g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
+  } else {
+    InstructionOperand addr_reg = g.TempRegister();
+    Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg,
+         g.UseRegister(index), g.UseRegister(base));
+    // Emit desired load opcode, using temp addr_reg.
+    Emit(opcode | AddressingModeField::encode(kMode_MRI),
+         g.DefineAsRegister(node), addr_reg, g.TempImmediate(0));
+  }
+}
+
+void InstructionSelector::VisitAtomicStore(Node* node) {
+  MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
+  Mips64OperandGenerator g(this);
+  Node* base = node->InputAt(0);
+  Node* index = node->InputAt(1);
+  Node* value = node->InputAt(2);
+  ArchOpcode opcode = kArchNop;
+  switch (rep) {
+    case MachineRepresentation::kWord8:
+      opcode = kAtomicStoreWord8;
+      break;
+    case MachineRepresentation::kWord16:
+      opcode = kAtomicStoreWord16;
+      break;
+    case MachineRepresentation::kWord32:
+      opcode = kAtomicStoreWord32;
+      break;
+    default:
+      UNREACHABLE();
+      return;
+  }
+
+  if (g.CanBeImmediate(index, opcode)) {
+    Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
+         g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value));
+  } else {
+    InstructionOperand addr_reg = g.TempRegister();
+    Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg,
+         g.UseRegister(index), g.UseRegister(base));
+    // Emit desired store opcode, using temp addr_reg.
+    Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
+         addr_reg, g.TempImmediate(0), g.UseRegister(value));
+  }
+}
 
 // static
 MachineOperatorBuilder::Flags
@@ -1941,6 +2077,19 @@
          MachineOperatorBuilder::kFloat32RoundTiesEven;
 }
 
+// static
+MachineOperatorBuilder::AlignmentRequirements
+InstructionSelector::AlignmentRequirements() {
+  if (kArchVariant == kMips64r6) {
+    return MachineOperatorBuilder::AlignmentRequirements::
+        FullUnalignedAccessSupport();
+  } else {
+    DCHECK(kArchVariant == kMips64r2);
+    return MachineOperatorBuilder::AlignmentRequirements::
+        NoUnalignedAccessSupport();
+  }
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/src/compiler/move-optimizer.cc b/src/compiler/move-optimizer.cc
index 477f139..4753d15 100644
--- a/src/compiler/move-optimizer.cc
+++ b/src/compiler/move-optimizer.cc
@@ -24,16 +24,38 @@
   }
 };
 
-struct OperandCompare {
-  bool operator()(const InstructionOperand& a,
-                  const InstructionOperand& b) const {
-    return a.CompareCanonicalized(b);
-  }
-};
-
 typedef ZoneMap<MoveKey, unsigned, MoveKeyCompare> MoveMap;
 typedef ZoneSet<InstructionOperand, CompareOperandModuloType> OperandSet;
 
+bool Blocks(const OperandSet& set, const InstructionOperand& operand) {
+  if (set.find(operand) != set.end()) return true;
+  // Only FP registers on archs with non-simple aliasing need extra checks.
+  if (!operand.IsFPRegister() || kSimpleFPAliasing) return false;
+
+  const LocationOperand& loc = LocationOperand::cast(operand);
+  MachineRepresentation rep = loc.representation();
+  MachineRepresentation other_fp_rep = rep == MachineRepresentation::kFloat64
+                                           ? MachineRepresentation::kFloat32
+                                           : MachineRepresentation::kFloat64;
+  const RegisterConfiguration* config = RegisterConfiguration::Turbofan();
+  if (config->fp_aliasing_kind() != RegisterConfiguration::COMBINE) {
+    // Overlap aliasing case.
+    return set.find(LocationOperand(loc.kind(), loc.location_kind(),
+                                    other_fp_rep, loc.register_code())) !=
+           set.end();
+  }
+  // Combine aliasing case.
+  int alias_base_index = -1;
+  int aliases = config->GetAliases(rep, loc.register_code(), other_fp_rep,
+                                   &alias_base_index);
+  while (aliases--) {
+    int aliased_reg = alias_base_index + aliases;
+    if (set.find(LocationOperand(loc.kind(), loc.location_kind(), other_fp_rep,
+                                 aliased_reg)) != set.end())
+      return true;
+  }
+  return false;
+}
 
 int FindFirstNonEmptySlot(const Instruction* instr) {
   int i = Instruction::FIRST_GAP_POSITION;
@@ -138,8 +160,8 @@
   ParallelMove* from_moves = from->parallel_moves()[0];
   if (from_moves == nullptr || from_moves->empty()) return;
 
-  ZoneSet<InstructionOperand, OperandCompare> dst_cant_be(local_zone());
-  ZoneSet<InstructionOperand, OperandCompare> src_cant_be(local_zone());
+  OperandSet dst_cant_be(local_zone());
+  OperandSet src_cant_be(local_zone());
 
   // If an operand is an input to the instruction, we cannot move assignments
   // where it appears on the LHS.
@@ -172,7 +194,7 @@
   // destination operands are eligible for being moved down.
   for (MoveOperands* move : *from_moves) {
     if (move->IsRedundant()) continue;
-    if (dst_cant_be.find(move->destination()) == dst_cant_be.end()) {
+    if (!Blocks(dst_cant_be, move->destination())) {
       MoveKey key = {move->source(), move->destination()};
       move_candidates.insert(key);
     }
@@ -187,7 +209,7 @@
       auto current = iter;
       ++iter;
       InstructionOperand src = current->source;
-      if (src_cant_be.find(src) != src_cant_be.end()) {
+      if (Blocks(src_cant_be, src)) {
         src_cant_be.insert(current->destination);
         move_candidates.erase(current);
         changed = true;
diff --git a/src/compiler/node-cache.cc b/src/compiler/node-cache.cc
index 79c342b..061a3ae 100644
--- a/src/compiler/node-cache.cc
+++ b/src/compiler/node-cache.cc
@@ -115,6 +115,9 @@
 template class NodeCache<int32_t>;
 template class NodeCache<int64_t>;
 
+template class NodeCache<RelocInt32Key>;
+template class NodeCache<RelocInt64Key>;
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/src/compiler/node-cache.h b/src/compiler/node-cache.h
index a8f9071..7063a3b 100644
--- a/src/compiler/node-cache.h
+++ b/src/compiler/node-cache.h
@@ -63,6 +63,14 @@
 // Various default cache types.
 typedef NodeCache<int32_t> Int32NodeCache;
 typedef NodeCache<int64_t> Int64NodeCache;
+
+// All we want is the numeric value of the RelocInfo::Mode enum. We typedef
+// below to avoid pulling in assembler.h
+typedef char RelocInfoMode;
+typedef std::pair<int32_t, RelocInfoMode> RelocInt32Key;
+typedef std::pair<int64_t, RelocInfoMode> RelocInt64Key;
+typedef NodeCache<RelocInt32Key> RelocInt32NodeCache;
+typedef NodeCache<RelocInt64Key> RelocInt64NodeCache;
 #if V8_HOST_ARCH_32_BIT
 typedef Int32NodeCache IntPtrNodeCache;
 #else
diff --git a/src/compiler/node-marker.h b/src/compiler/node-marker.h
index 5ef2063..84666d5 100644
--- a/src/compiler/node-marker.h
+++ b/src/compiler/node-marker.h
@@ -42,9 +42,22 @@
   DISALLOW_COPY_AND_ASSIGN(NodeMarkerBase);
 };
 
-
-// A NodeMarker uses monotonically increasing marks to assign local "states"
-// to nodes. Only one NodeMarker per graph is valid at a given time.
+// A NodeMarker assigns a local "state" to every node of a graph in constant
+// memory. Only one NodeMarker per graph is valid at a given time, that is,
+// after you create a NodeMarker you should no longer use NodeMarkers that
+// were created earlier. Internally, the local state is stored in the Node
+// structure.
+//
+// When you initialize a NodeMarker, all the local states are conceptually
+// set to State(0) in constant time.
+//
+// In its current implementation, in debug mode NodeMarker will try to
+// (efficiently) detect invalid use of an older NodeMarker. Namely, if you get
+// or set a node with a NodeMarker, and then get or set that node
+// with an older NodeMarker you will get a crash.
+//
+// GraphReducer uses a NodeMarker, so individual Reducers cannot use a
+// NodeMarker.
 template <typename State>
 class NodeMarker : public NodeMarkerBase {
  public:
diff --git a/src/compiler/node-matchers.h b/src/compiler/node-matchers.h
index 37d0e1a..6238be3 100644
--- a/src/compiler/node-matchers.h
+++ b/src/compiler/node-matchers.h
@@ -253,7 +253,8 @@
 typedef BinopMatcher<Float32Matcher, Float32Matcher> Float32BinopMatcher;
 typedef BinopMatcher<Float64Matcher, Float64Matcher> Float64BinopMatcher;
 typedef BinopMatcher<NumberMatcher, NumberMatcher> NumberBinopMatcher;
-
+typedef BinopMatcher<HeapObjectMatcher, HeapObjectMatcher>
+    HeapObjectBinopMatcher;
 
 template <class BinopMatcher, IrOpcode::Value kMulOpcode,
           IrOpcode::Value kShiftOpcode>
diff --git a/src/compiler/node-properties.cc b/src/compiler/node-properties.cc
index ac9cc34..dc33d60 100644
--- a/src/compiler/node-properties.cc
+++ b/src/compiler/node-properties.cc
@@ -158,8 +158,9 @@
 
 
 // static
-void NodeProperties::ReplaceControlInput(Node* node, Node* control) {
-  node->ReplaceInput(FirstControlIndex(node), control);
+void NodeProperties::ReplaceControlInput(Node* node, Node* control, int index) {
+  DCHECK(index < node->op()->ControlInputCount());
+  node->ReplaceInput(FirstControlIndex(node) + index, control);
 }
 
 
@@ -179,13 +180,6 @@
 
 
 // static
-void NodeProperties::RemoveFrameStateInput(Node* node, int index) {
-  DCHECK_LT(index, OperatorProperties::GetFrameStateInputCount(node->op()));
-  node->RemoveInput(FirstFrameStateIndex(node) + index);
-}
-
-
-// static
 void NodeProperties::RemoveNonValueInputs(Node* node) {
   node->TrimInputCount(node->op()->ValueInputCount());
 }
@@ -221,7 +215,8 @@
         DCHECK_NOT_NULL(exception);
         edge.UpdateTo(exception);
       } else {
-        UNREACHABLE();
+        DCHECK_NOT_NULL(success);
+        edge.UpdateTo(success);
       }
     } else if (IsEffectEdge(edge)) {
       DCHECK_NOT_NULL(effect);
@@ -242,6 +237,18 @@
 
 
 // static
+Node* NodeProperties::FindFrameStateBefore(Node* node) {
+  Node* effect = NodeProperties::GetEffectInput(node);
+  while (effect->opcode() != IrOpcode::kCheckpoint) {
+    if (effect->opcode() == IrOpcode::kDead) return effect;
+    DCHECK_EQ(1, effect->op()->EffectInputCount());
+    effect = NodeProperties::GetEffectInput(effect);
+  }
+  Node* frame_state = GetFrameStateInput(effect, 0);
+  return frame_state;
+}
+
+// static
 Node* NodeProperties::FindProjection(Node* node, size_t projection_index) {
   for (auto use : node->uses()) {
     if (use->opcode() == IrOpcode::kProjection &&
diff --git a/src/compiler/node-properties.h b/src/compiler/node-properties.h
index 58005a7..fbc06fc 100644
--- a/src/compiler/node-properties.h
+++ b/src/compiler/node-properties.h
@@ -81,10 +81,9 @@
 
   static void ReplaceValueInput(Node* node, Node* value, int index);
   static void ReplaceContextInput(Node* node, Node* context);
-  static void ReplaceControlInput(Node* node, Node* control);
+  static void ReplaceControlInput(Node* node, Node* control, int index = 0);
   static void ReplaceEffectInput(Node* node, Node* effect, int index = 0);
   static void ReplaceFrameStateInput(Node* node, int index, Node* frame_state);
-  static void RemoveFrameStateInput(Node* node, int index);
   static void RemoveNonValueInputs(Node* node);
   static void RemoveValueInputs(Node* node);
 
@@ -109,6 +108,11 @@
   // ---------------------------------------------------------------------------
   // Miscellaneous utilities.
 
+  // Find the last frame state that is effect-wise before the given node. This
+  // assumes a linear effect-chain up to a {CheckPoint} node in the graph.
+  static Node* FindFrameStateBefore(Node* node);
+
+  // Collect the output-value projection for the given output index.
   static Node* FindProjection(Node* node, size_t projection_index);
 
   // Collect the branch-related projections from a node, such as IfTrue,
diff --git a/src/compiler/opcodes.h b/src/compiler/opcodes.h
index b038d15..c823afb 100644
--- a/src/compiler/opcodes.h
+++ b/src/compiler/opcodes.h
@@ -32,21 +32,22 @@
   V(End)
 
 // Opcodes for constant operators.
-#define CONSTANT_OP_LIST(V) \
-  V(Int32Constant)          \
-  V(Int64Constant)          \
-  V(Float32Constant)        \
-  V(Float64Constant)        \
-  V(ExternalConstant)       \
-  V(NumberConstant)         \
-  V(HeapConstant)
+#define CONSTANT_OP_LIST(V)   \
+  V(Int32Constant)            \
+  V(Int64Constant)            \
+  V(Float32Constant)          \
+  V(Float64Constant)          \
+  V(ExternalConstant)         \
+  V(NumberConstant)           \
+  V(HeapConstant)             \
+  V(RelocatableInt32Constant) \
+  V(RelocatableInt64Constant)
 
 #define INNER_OP_LIST(V) \
   V(Select)              \
   V(Phi)                 \
-  V(EffectSet)           \
   V(EffectPhi)           \
-  V(Guard)               \
+  V(Checkpoint)          \
   V(BeginRegion)         \
   V(FinishRegion)        \
   V(FrameState)          \
@@ -139,18 +140,20 @@
   V(JSCreateModuleContext)    \
   V(JSCreateScriptContext)
 
-#define JS_OTHER_OP_LIST(V) \
-  V(JSCallConstruct)        \
-  V(JSCallFunction)         \
-  V(JSCallRuntime)          \
-  V(JSConvertReceiver)      \
-  V(JSForInDone)            \
-  V(JSForInNext)            \
-  V(JSForInPrepare)         \
-  V(JSForInStep)            \
-  V(JSLoadMessage)          \
-  V(JSStoreMessage)         \
-  V(JSYield)                \
+#define JS_OTHER_OP_LIST(V)         \
+  V(JSCallConstruct)                \
+  V(JSCallFunction)                 \
+  V(JSCallRuntime)                  \
+  V(JSConvertReceiver)              \
+  V(JSForInDone)                    \
+  V(JSForInNext)                    \
+  V(JSForInPrepare)                 \
+  V(JSForInStep)                    \
+  V(JSLoadMessage)                  \
+  V(JSStoreMessage)                 \
+  V(JSGeneratorStore)               \
+  V(JSGeneratorRestoreContinuation) \
+  V(JSGeneratorRestoreRegister)     \
   V(JSStackCheck)
 
 #define JS_OP_LIST(V)     \
@@ -170,51 +173,96 @@
   V(StringLessThan)                      \
   V(StringLessThanOrEqual)
 
-#define SIMPLIFIED_OP_LIST(V)      \
-  SIMPLIFIED_COMPARE_BINOP_LIST(V) \
-  V(BooleanNot)                    \
-  V(BooleanToNumber)               \
-  V(NumberAdd)                     \
-  V(NumberSubtract)                \
-  V(NumberMultiply)                \
-  V(NumberDivide)                  \
-  V(NumberModulus)                 \
-  V(NumberBitwiseOr)               \
-  V(NumberBitwiseXor)              \
-  V(NumberBitwiseAnd)              \
-  V(NumberShiftLeft)               \
-  V(NumberShiftRight)              \
-  V(NumberShiftRightLogical)       \
-  V(NumberImul)                    \
-  V(NumberClz32)                   \
-  V(NumberCeil)                    \
-  V(NumberFloor)                   \
-  V(NumberRound)                   \
-  V(NumberTrunc)                   \
-  V(NumberToInt32)                 \
-  V(NumberToUint32)                \
-  V(NumberIsHoleNaN)               \
-  V(PlainPrimitiveToNumber)        \
-  V(StringToNumber)                \
-  V(ChangeTaggedToInt32)           \
-  V(ChangeTaggedToUint32)          \
-  V(ChangeTaggedToFloat64)         \
-  V(ChangeInt32ToTagged)           \
-  V(ChangeUint32ToTagged)          \
-  V(ChangeFloat64ToTagged)         \
-  V(ChangeBoolToBit)               \
-  V(ChangeBitToBool)               \
-  V(Allocate)                      \
-  V(LoadField)                     \
-  V(LoadBuffer)                    \
-  V(LoadElement)                   \
-  V(StoreField)                    \
-  V(StoreBuffer)                   \
-  V(StoreElement)                  \
-  V(ObjectIsNumber)                \
-  V(ObjectIsReceiver)              \
-  V(ObjectIsSmi)                   \
-  V(ObjectIsUndetectable)
+#define SIMPLIFIED_OP_LIST(V)         \
+  SIMPLIFIED_COMPARE_BINOP_LIST(V)    \
+  V(PlainPrimitiveToNumber)           \
+  V(PlainPrimitiveToWord32)           \
+  V(PlainPrimitiveToFloat64)          \
+  V(BooleanNot)                       \
+  V(BooleanToNumber)                  \
+  V(SpeculativeNumberAdd)             \
+  V(SpeculativeNumberSubtract)        \
+  V(SpeculativeNumberMultiply)        \
+  V(SpeculativeNumberDivide)          \
+  V(SpeculativeNumberModulus)         \
+  V(SpeculativeNumberEqual)           \
+  V(SpeculativeNumberLessThan)        \
+  V(SpeculativeNumberLessThanOrEqual) \
+  V(NumberAdd)                        \
+  V(NumberSubtract)                   \
+  V(NumberMultiply)                   \
+  V(NumberDivide)                     \
+  V(NumberModulus)                    \
+  V(NumberBitwiseOr)                  \
+  V(NumberBitwiseXor)                 \
+  V(NumberBitwiseAnd)                 \
+  V(NumberShiftLeft)                  \
+  V(NumberShiftRight)                 \
+  V(NumberShiftRightLogical)          \
+  V(NumberImul)                       \
+  V(NumberAbs)                        \
+  V(NumberClz32)                      \
+  V(NumberCeil)                       \
+  V(NumberCos)                        \
+  V(NumberFloor)                      \
+  V(NumberFround)                     \
+  V(NumberAtan)                       \
+  V(NumberAtan2)                      \
+  V(NumberAtanh)                      \
+  V(NumberExp)                        \
+  V(NumberExpm1)                      \
+  V(NumberLog)                        \
+  V(NumberLog1p)                      \
+  V(NumberLog2)                       \
+  V(NumberLog10)                      \
+  V(NumberCbrt)                       \
+  V(NumberRound)                      \
+  V(NumberSin)                        \
+  V(NumberSqrt)                       \
+  V(NumberTan)                        \
+  V(NumberTrunc)                      \
+  V(NumberToInt32)                    \
+  V(NumberToUint32)                   \
+  V(NumberSilenceNaN)                 \
+  V(StringFromCharCode)               \
+  V(StringToNumber)                   \
+  V(ChangeTaggedSignedToInt32)        \
+  V(ChangeTaggedToInt32)              \
+  V(ChangeTaggedToUint32)             \
+  V(ChangeTaggedToFloat64)            \
+  V(ChangeInt31ToTaggedSigned)        \
+  V(ChangeInt32ToTagged)              \
+  V(ChangeUint32ToTagged)             \
+  V(ChangeFloat64ToTagged)            \
+  V(ChangeTaggedToBit)                \
+  V(ChangeBitToTagged)                \
+  V(CheckBounds)                      \
+  V(CheckTaggedPointer)               \
+  V(CheckTaggedSigned)                \
+  V(CheckedInt32Add)                  \
+  V(CheckedInt32Sub)                  \
+  V(CheckedUint32ToInt32)             \
+  V(CheckedFloat64ToInt32)            \
+  V(CheckedTaggedToInt32)             \
+  V(CheckedTaggedToFloat64)           \
+  V(CheckFloat64Hole)                 \
+  V(CheckTaggedHole)                  \
+  V(TruncateTaggedToWord32)           \
+  V(TruncateTaggedToFloat64)          \
+  V(Allocate)                         \
+  V(LoadField)                        \
+  V(LoadBuffer)                       \
+  V(LoadElement)                      \
+  V(StoreField)                       \
+  V(StoreBuffer)                      \
+  V(StoreElement)                     \
+  V(ObjectIsCallable)                 \
+  V(ObjectIsNumber)                   \
+  V(ObjectIsReceiver)                 \
+  V(ObjectIsSmi)                      \
+  V(ObjectIsString)                   \
+  V(ObjectIsUndetectable)             \
+  V(TypeGuard)
 
 // Opcodes for Machine-level operators.
 #define MACHINE_COMPARE_BINOP_LIST(V) \
@@ -237,6 +285,8 @@
 
 #define MACHINE_OP_LIST(V)      \
   MACHINE_COMPARE_BINOP_LIST(V) \
+  V(DebugBreak)                 \
+  V(Comment)                    \
   V(Load)                       \
   V(Store)                      \
   V(StackSlot)                  \
@@ -282,9 +332,12 @@
   V(Int64Mod)                   \
   V(Uint64Div)                  \
   V(Uint64Mod)                  \
+  V(BitcastWordToTagged)        \
+  V(TruncateFloat64ToWord32)    \
   V(ChangeFloat32ToFloat64)     \
   V(ChangeFloat64ToInt32)       \
   V(ChangeFloat64ToUint32)      \
+  V(Float64SilenceNaN)          \
   V(TruncateFloat64ToUint32)    \
   V(TruncateFloat32ToInt32)     \
   V(TruncateFloat32ToUint32)    \
@@ -297,8 +350,8 @@
   V(ChangeUint32ToFloat64)      \
   V(ChangeUint32ToUint64)       \
   V(TruncateFloat64ToFloat32)   \
-  V(TruncateFloat64ToInt32)     \
   V(TruncateInt64ToInt32)       \
+  V(RoundFloat64ToInt32)        \
   V(RoundInt32ToFloat32)        \
   V(RoundInt64ToFloat32)        \
   V(RoundInt64ToFloat64)        \
@@ -311,6 +364,8 @@
   V(BitcastInt64ToFloat64)      \
   V(Float32Add)                 \
   V(Float32Sub)                 \
+  V(Float32SubPreserveNan)      \
+  V(Float32Neg)                 \
   V(Float32Mul)                 \
   V(Float32Div)                 \
   V(Float32Max)                 \
@@ -320,13 +375,28 @@
   V(Float32RoundDown)           \
   V(Float64Add)                 \
   V(Float64Sub)                 \
+  V(Float64SubPreserveNan)      \
+  V(Float64Neg)                 \
   V(Float64Mul)                 \
   V(Float64Div)                 \
   V(Float64Mod)                 \
   V(Float64Max)                 \
   V(Float64Min)                 \
   V(Float64Abs)                 \
+  V(Float64Atan)                \
+  V(Float64Atan2)               \
+  V(Float64Atanh)               \
+  V(Float64Cbrt)                \
+  V(Float64Cos)                 \
+  V(Float64Exp)                 \
+  V(Float64Expm1)               \
+  V(Float64Log)                 \
+  V(Float64Log1p)               \
+  V(Float64Log10)               \
+  V(Float64Log2)                \
+  V(Float64Sin)                 \
   V(Float64Sqrt)                \
+  V(Float64Tan)                 \
   V(Float64RoundDown)           \
   V(Float32RoundUp)             \
   V(Float64RoundUp)             \
@@ -349,12 +419,201 @@
   V(Int32PairMul)               \
   V(Word32PairShl)              \
   V(Word32PairShr)              \
-  V(Word32PairSar)
+  V(Word32PairSar)              \
+  V(AtomicLoad)                 \
+  V(AtomicStore)
 
-#define VALUE_OP_LIST(V) \
-  COMMON_OP_LIST(V)      \
-  SIMPLIFIED_OP_LIST(V)  \
-  MACHINE_OP_LIST(V)     \
+#define MACHINE_SIMD_RETURN_SIMD_OP_LIST(V) \
+  V(CreateFloat32x4)                        \
+  V(Float32x4ReplaceLane)                   \
+  V(Float32x4Abs)                           \
+  V(Float32x4Neg)                           \
+  V(Float32x4Sqrt)                          \
+  V(Float32x4RecipApprox)                   \
+  V(Float32x4RecipSqrtApprox)               \
+  V(Float32x4Add)                           \
+  V(Float32x4Sub)                           \
+  V(Float32x4Mul)                           \
+  V(Float32x4Div)                           \
+  V(Float32x4Min)                           \
+  V(Float32x4Max)                           \
+  V(Float32x4MinNum)                        \
+  V(Float32x4MaxNum)                        \
+  V(Float32x4Equal)                         \
+  V(Float32x4NotEqual)                      \
+  V(Float32x4LessThan)                      \
+  V(Float32x4LessThanOrEqual)               \
+  V(Float32x4GreaterThan)                   \
+  V(Float32x4GreaterThanOrEqual)            \
+  V(Float32x4Select)                        \
+  V(Float32x4Swizzle)                       \
+  V(Float32x4Shuffle)                       \
+  V(Float32x4FromInt32x4)                   \
+  V(Float32x4FromUint32x4)                  \
+  V(CreateInt32x4)                          \
+  V(Int32x4ReplaceLane)                     \
+  V(Int32x4Neg)                             \
+  V(Int32x4Add)                             \
+  V(Int32x4Sub)                             \
+  V(Int32x4Mul)                             \
+  V(Int32x4Min)                             \
+  V(Int32x4Max)                             \
+  V(Int32x4ShiftLeftByScalar)               \
+  V(Int32x4ShiftRightByScalar)              \
+  V(Int32x4Equal)                           \
+  V(Int32x4NotEqual)                        \
+  V(Int32x4LessThan)                        \
+  V(Int32x4LessThanOrEqual)                 \
+  V(Int32x4GreaterThan)                     \
+  V(Int32x4GreaterThanOrEqual)              \
+  V(Int32x4Select)                          \
+  V(Int32x4Swizzle)                         \
+  V(Int32x4Shuffle)                         \
+  V(Int32x4FromFloat32x4)                   \
+  V(Uint32x4Min)                            \
+  V(Uint32x4Max)                            \
+  V(Uint32x4ShiftLeftByScalar)              \
+  V(Uint32x4ShiftRightByScalar)             \
+  V(Uint32x4LessThan)                       \
+  V(Uint32x4LessThanOrEqual)                \
+  V(Uint32x4GreaterThan)                    \
+  V(Uint32x4GreaterThanOrEqual)             \
+  V(Uint32x4FromFloat32x4)                  \
+  V(CreateBool32x4)                         \
+  V(Bool32x4ReplaceLane)                    \
+  V(Bool32x4And)                            \
+  V(Bool32x4Or)                             \
+  V(Bool32x4Xor)                            \
+  V(Bool32x4Not)                            \
+  V(Bool32x4Swizzle)                        \
+  V(Bool32x4Shuffle)                        \
+  V(Bool32x4Equal)                          \
+  V(Bool32x4NotEqual)                       \
+  V(CreateInt16x8)                          \
+  V(Int16x8ReplaceLane)                     \
+  V(Int16x8Neg)                             \
+  V(Int16x8Add)                             \
+  V(Int16x8AddSaturate)                     \
+  V(Int16x8Sub)                             \
+  V(Int16x8SubSaturate)                     \
+  V(Int16x8Mul)                             \
+  V(Int16x8Min)                             \
+  V(Int16x8Max)                             \
+  V(Int16x8ShiftLeftByScalar)               \
+  V(Int16x8ShiftRightByScalar)              \
+  V(Int16x8Equal)                           \
+  V(Int16x8NotEqual)                        \
+  V(Int16x8LessThan)                        \
+  V(Int16x8LessThanOrEqual)                 \
+  V(Int16x8GreaterThan)                     \
+  V(Int16x8GreaterThanOrEqual)              \
+  V(Int16x8Select)                          \
+  V(Int16x8Swizzle)                         \
+  V(Int16x8Shuffle)                         \
+  V(Uint16x8AddSaturate)                    \
+  V(Uint16x8SubSaturate)                    \
+  V(Uint16x8Min)                            \
+  V(Uint16x8Max)                            \
+  V(Uint16x8ShiftLeftByScalar)              \
+  V(Uint16x8ShiftRightByScalar)             \
+  V(Uint16x8LessThan)                       \
+  V(Uint16x8LessThanOrEqual)                \
+  V(Uint16x8GreaterThan)                    \
+  V(Uint16x8GreaterThanOrEqual)             \
+  V(CreateBool16x8)                         \
+  V(Bool16x8ReplaceLane)                    \
+  V(Bool16x8And)                            \
+  V(Bool16x8Or)                             \
+  V(Bool16x8Xor)                            \
+  V(Bool16x8Not)                            \
+  V(Bool16x8Swizzle)                        \
+  V(Bool16x8Shuffle)                        \
+  V(Bool16x8Equal)                          \
+  V(Bool16x8NotEqual)                       \
+  V(CreateInt8x16)                          \
+  V(Int8x16ReplaceLane)                     \
+  V(Int8x16Neg)                             \
+  V(Int8x16Add)                             \
+  V(Int8x16AddSaturate)                     \
+  V(Int8x16Sub)                             \
+  V(Int8x16SubSaturate)                     \
+  V(Int8x16Mul)                             \
+  V(Int8x16Min)                             \
+  V(Int8x16Max)                             \
+  V(Int8x16ShiftLeftByScalar)               \
+  V(Int8x16ShiftRightByScalar)              \
+  V(Int8x16Equal)                           \
+  V(Int8x16NotEqual)                        \
+  V(Int8x16LessThan)                        \
+  V(Int8x16LessThanOrEqual)                 \
+  V(Int8x16GreaterThan)                     \
+  V(Int8x16GreaterThanOrEqual)              \
+  V(Int8x16Select)                          \
+  V(Int8x16Swizzle)                         \
+  V(Int8x16Shuffle)                         \
+  V(Uint8x16AddSaturate)                    \
+  V(Uint8x16SubSaturate)                    \
+  V(Uint8x16Min)                            \
+  V(Uint8x16Max)                            \
+  V(Uint8x16ShiftLeftByScalar)              \
+  V(Uint8x16ShiftRightByScalar)             \
+  V(Uint8x16LessThan)                       \
+  V(Uint8x16LessThanOrEqual)                \
+  V(Uint8x16GreaterThan)                    \
+  V(Uint8x16GreaterThanOrEqual)             \
+  V(CreateBool8x16)                         \
+  V(Bool8x16ReplaceLane)                    \
+  V(Bool8x16And)                            \
+  V(Bool8x16Or)                             \
+  V(Bool8x16Xor)                            \
+  V(Bool8x16Not)                            \
+  V(Bool8x16Swizzle)                        \
+  V(Bool8x16Shuffle)                        \
+  V(Bool8x16Equal)                          \
+  V(Bool8x16NotEqual)
+
+#define MACHINE_SIMD_RETURN_NUM_OP_LIST(V) \
+  V(Float32x4ExtractLane)                  \
+  V(Int32x4ExtractLane)                    \
+  V(Int16x8ExtractLane)                    \
+  V(Int8x16ExtractLane)
+
+#define MACHINE_SIMD_RETURN_BOOL_OP_LIST(V) \
+  V(Bool32x4ExtractLane)                    \
+  V(Bool32x4AnyTrue)                        \
+  V(Bool32x4AllTrue)                        \
+  V(Bool16x8ExtractLane)                    \
+  V(Bool16x8AnyTrue)                        \
+  V(Bool16x8AllTrue)                        \
+  V(Bool8x16ExtractLane)                    \
+  V(Bool8x16AnyTrue)                        \
+  V(Bool8x16AllTrue)
+
+#define MACHINE_SIMD_GENERIC_OP_LIST(V) \
+  V(Simd128Load)                        \
+  V(Simd128Load1)                       \
+  V(Simd128Load2)                       \
+  V(Simd128Load3)                       \
+  V(Simd128Store)                       \
+  V(Simd128Store1)                      \
+  V(Simd128Store2)                      \
+  V(Simd128Store3)                      \
+  V(Simd128And)                         \
+  V(Simd128Or)                          \
+  V(Simd128Xor)                         \
+  V(Simd128Not)
+
+#define MACHINE_SIMD_OP_LIST(V)       \
+  MACHINE_SIMD_RETURN_SIMD_OP_LIST(V) \
+  MACHINE_SIMD_RETURN_NUM_OP_LIST(V)  \
+  MACHINE_SIMD_RETURN_BOOL_OP_LIST(V) \
+  MACHINE_SIMD_GENERIC_OP_LIST(V)
+
+#define VALUE_OP_LIST(V)  \
+  COMMON_OP_LIST(V)       \
+  SIMPLIFIED_OP_LIST(V)   \
+  MACHINE_OP_LIST(V)      \
+  MACHINE_SIMD_OP_LIST(V) \
   JS_OP_LIST(V)
 
 // The combination of all operators at all levels and the common operators.
@@ -400,7 +659,7 @@
 
   // Returns true if opcode for constant operator.
   static bool IsConstantOpcode(Value value) {
-    return kInt32Constant <= value && value <= kHeapConstant;
+    return kInt32Constant <= value && value <= kRelocatableInt64Constant;
   }
 
   static bool IsPhiOpcode(Value value) {
diff --git a/src/compiler/operation-typer.cc b/src/compiler/operation-typer.cc
new file mode 100644
index 0000000..b2860e0
--- /dev/null
+++ b/src/compiler/operation-typer.cc
@@ -0,0 +1,424 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/operation-typer.h"
+
+#include "src/factory.h"
+#include "src/isolate.h"
+#include "src/type-cache.h"
+#include "src/types.h"
+
+#include "src/objects-inl.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+OperationTyper::OperationTyper(Isolate* isolate, Zone* zone)
+    : zone_(zone), cache_(TypeCache::Get()) {
+  Factory* factory = isolate->factory();
+  singleton_false_ = Type::Constant(factory->false_value(), zone);
+  singleton_true_ = Type::Constant(factory->true_value(), zone);
+  singleton_the_hole_ = Type::Constant(factory->the_hole_value(), zone);
+}
+
+Type* OperationTyper::Merge(Type* left, Type* right) {
+  return Type::Union(left, right, zone());
+}
+
+Type* OperationTyper::WeakenRange(Type* previous_range, Type* current_range) {
+  static const double kWeakenMinLimits[] = {0.0,
+                                            -1073741824.0,
+                                            -2147483648.0,
+                                            -4294967296.0,
+                                            -8589934592.0,
+                                            -17179869184.0,
+                                            -34359738368.0,
+                                            -68719476736.0,
+                                            -137438953472.0,
+                                            -274877906944.0,
+                                            -549755813888.0,
+                                            -1099511627776.0,
+                                            -2199023255552.0,
+                                            -4398046511104.0,
+                                            -8796093022208.0,
+                                            -17592186044416.0,
+                                            -35184372088832.0,
+                                            -70368744177664.0,
+                                            -140737488355328.0,
+                                            -281474976710656.0,
+                                            -562949953421312.0};
+  static const double kWeakenMaxLimits[] = {0.0,
+                                            1073741823.0,
+                                            2147483647.0,
+                                            4294967295.0,
+                                            8589934591.0,
+                                            17179869183.0,
+                                            34359738367.0,
+                                            68719476735.0,
+                                            137438953471.0,
+                                            274877906943.0,
+                                            549755813887.0,
+                                            1099511627775.0,
+                                            2199023255551.0,
+                                            4398046511103.0,
+                                            8796093022207.0,
+                                            17592186044415.0,
+                                            35184372088831.0,
+                                            70368744177663.0,
+                                            140737488355327.0,
+                                            281474976710655.0,
+                                            562949953421311.0};
+  STATIC_ASSERT(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits));
+
+  double current_min = current_range->Min();
+  double new_min = current_min;
+  // Find the closest lower entry in the list of allowed
+  // minima (or negative infinity if there is no such entry).
+  if (current_min != previous_range->Min()) {
+    new_min = -V8_INFINITY;
+    for (double const min : kWeakenMinLimits) {
+      if (min <= current_min) {
+        new_min = min;
+        break;
+      }
+    }
+  }
+
+  double current_max = current_range->Max();
+  double new_max = current_max;
+  // Find the closest greater entry in the list of allowed
+  // maxima (or infinity if there is no such entry).
+  if (current_max != previous_range->Max()) {
+    new_max = V8_INFINITY;
+    for (double const max : kWeakenMaxLimits) {
+      if (max >= current_max) {
+        new_max = max;
+        break;
+      }
+    }
+  }
+
+  return Type::Range(new_min, new_max, zone());
+}
+
+Type* OperationTyper::Rangify(Type* type) {
+  if (type->IsRange()) return type;  // Shortcut.
+  if (!type->Is(cache_.kInteger)) {
+    return type;  // Give up on non-integer types.
+  }
+  double min = type->Min();
+  double max = type->Max();
+  // Handle the degenerate case of empty bitset types (such as
+  // OtherUnsigned31 and OtherSigned32 on 64-bit architectures).
+  if (std::isnan(min)) {
+    DCHECK(std::isnan(max));
+    return type;
+  }
+  return Type::Range(min, max, zone());
+}
+
+namespace {
+
+// Returns the array's least element, ignoring NaN.
+// There must be at least one non-NaN element.
+// Any -0 is converted to 0.
+double array_min(double a[], size_t n) {
+  DCHECK(n != 0);
+  double x = +V8_INFINITY;
+  for (size_t i = 0; i < n; ++i) {
+    if (!std::isnan(a[i])) {
+      x = std::min(a[i], x);
+    }
+  }
+  DCHECK(!std::isnan(x));
+  return x == 0 ? 0 : x;  // -0 -> 0
+}
+
+// Returns the array's greatest element, ignoring NaN.
+// There must be at least one non-NaN element.
+// Any -0 is converted to 0.
+double array_max(double a[], size_t n) {
+  DCHECK(n != 0);
+  double x = -V8_INFINITY;
+  for (size_t i = 0; i < n; ++i) {
+    if (!std::isnan(a[i])) {
+      x = std::max(a[i], x);
+    }
+  }
+  DCHECK(!std::isnan(x));
+  return x == 0 ? 0 : x;  // -0 -> 0
+}
+
+}  // namespace
+
+Type* OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min,
+                                double rhs_max) {
+  double results[4];
+  results[0] = lhs_min + rhs_min;
+  results[1] = lhs_min + rhs_max;
+  results[2] = lhs_max + rhs_min;
+  results[3] = lhs_max + rhs_max;
+  // Since none of the inputs can be -0, the result cannot be -0 either.
+  // However, it can be nan (the sum of two infinities of opposite sign).
+  // On the other hand, if none of the "results" above is nan, then the actual
+  // result cannot be nan either.
+  int nans = 0;
+  for (int i = 0; i < 4; ++i) {
+    if (std::isnan(results[i])) ++nans;
+  }
+  if (nans == 4) return Type::NaN();  // [-inf..-inf] + [inf..inf] or vice versa
+  Type* range =
+      Type::Range(array_min(results, 4), array_max(results, 4), zone());
+  return nans == 0 ? range : Type::Union(range, Type::NaN(), zone());
+  // Examples:
+  //   [-inf, -inf] + [+inf, +inf] = NaN
+  //   [-inf, -inf] + [n, +inf] = [-inf, -inf] \/ NaN
+  //   [-inf, +inf] + [n, +inf] = [-inf, +inf] \/ NaN
+  //   [-inf, m] + [n, +inf] = [-inf, +inf] \/ NaN
+}
+
+Type* OperationTyper::SubtractRanger(RangeType* lhs, RangeType* rhs) {
+  double results[4];
+  results[0] = lhs->Min() - rhs->Min();
+  results[1] = lhs->Min() - rhs->Max();
+  results[2] = lhs->Max() - rhs->Min();
+  results[3] = lhs->Max() - rhs->Max();
+  // Since none of the inputs can be -0, the result cannot be -0.
+  // However, it can be nan (the subtraction of two infinities of same sign).
+  // On the other hand, if none of the "results" above is nan, then the actual
+  // result cannot be nan either.
+  int nans = 0;
+  for (int i = 0; i < 4; ++i) {
+    if (std::isnan(results[i])) ++nans;
+  }
+  if (nans == 4) return Type::NaN();  // [inf..inf] - [inf..inf] (all same sign)
+  Type* range =
+      Type::Range(array_min(results, 4), array_max(results, 4), zone());
+  return nans == 0 ? range : Type::Union(range, Type::NaN(), zone());
+  // Examples:
+  //   [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN
+  //   [-inf, -inf] - [-inf, -inf] = NaN
+  //   [-inf, -inf] - [n, +inf] = [-inf, -inf] \/ NaN
+  //   [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN
+}
+
+Type* OperationTyper::ModulusRanger(RangeType* lhs, RangeType* rhs) {
+  double lmin = lhs->Min();
+  double lmax = lhs->Max();
+  double rmin = rhs->Min();
+  double rmax = rhs->Max();
+
+  double labs = std::max(std::abs(lmin), std::abs(lmax));
+  double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
+  double abs = std::min(labs, rabs);
+  bool maybe_minus_zero = false;
+  double omin = 0;
+  double omax = 0;
+  if (lmin >= 0) {  // {lhs} positive.
+    omin = 0;
+    omax = abs;
+  } else if (lmax <= 0) {  // {lhs} negative.
+    omin = 0 - abs;
+    omax = 0;
+    maybe_minus_zero = true;
+  } else {
+    omin = 0 - abs;
+    omax = abs;
+    maybe_minus_zero = true;
+  }
+
+  Type* result = Type::Range(omin, omax, zone());
+  if (maybe_minus_zero) result = Type::Union(result, Type::MinusZero(), zone());
+  return result;
+}
+
+Type* OperationTyper::MultiplyRanger(Type* lhs, Type* rhs) {
+  double results[4];
+  double lmin = lhs->AsRange()->Min();
+  double lmax = lhs->AsRange()->Max();
+  double rmin = rhs->AsRange()->Min();
+  double rmax = rhs->AsRange()->Max();
+  results[0] = lmin * rmin;
+  results[1] = lmin * rmax;
+  results[2] = lmax * rmin;
+  results[3] = lmax * rmax;
+  // If the result may be nan, we give up on calculating a precise type,
+  // because
+  // the discontinuity makes it too complicated.  Note that even if none of
+  // the
+  // "results" above is nan, the actual result may still be, so we have to do
+  // a
+  // different check:
+  bool maybe_nan = (lhs->Maybe(cache_.kSingletonZero) &&
+                    (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) ||
+                   (rhs->Maybe(cache_.kSingletonZero) &&
+                    (lmin == -V8_INFINITY || lmax == +V8_INFINITY));
+  if (maybe_nan) return cache_.kIntegerOrMinusZeroOrNaN;  // Giving up.
+  bool maybe_minuszero = (lhs->Maybe(cache_.kSingletonZero) && rmin < 0) ||
+                         (rhs->Maybe(cache_.kSingletonZero) && lmin < 0);
+  Type* range =
+      Type::Range(array_min(results, 4), array_max(results, 4), zone());
+  return maybe_minuszero ? Type::Union(range, Type::MinusZero(), zone())
+                         : range;
+}
+
+Type* OperationTyper::ToNumber(Type* type) {
+  if (type->Is(Type::Number())) return type;
+  if (type->Is(Type::NullOrUndefined())) {
+    if (type->Is(Type::Null())) return cache_.kSingletonZero;
+    if (type->Is(Type::Undefined())) return Type::NaN();
+    return Type::Union(Type::NaN(), cache_.kSingletonZero, zone());
+  }
+  if (type->Is(Type::NumberOrUndefined())) {
+    return Type::Union(Type::Intersect(type, Type::Number(), zone()),
+                       Type::NaN(), zone());
+  }
+  if (type->Is(singleton_false_)) return cache_.kSingletonZero;
+  if (type->Is(singleton_true_)) return cache_.kSingletonOne;
+  if (type->Is(Type::Boolean())) return cache_.kZeroOrOne;
+  if (type->Is(Type::BooleanOrNumber())) {
+    return Type::Union(Type::Intersect(type, Type::Number(), zone()),
+                       cache_.kZeroOrOne, zone());
+  }
+  return Type::Number();
+}
+
+Type* OperationTyper::NumericAdd(Type* lhs, Type* rhs) {
+  DCHECK(lhs->Is(Type::Number()));
+  DCHECK(rhs->Is(Type::Number()));
+
+  // We can give more precise types for integers.
+  if (!lhs->Is(cache_.kIntegerOrMinusZeroOrNaN) ||
+      !rhs->Is(cache_.kIntegerOrMinusZeroOrNaN)) {
+    return Type::Number();
+  }
+  Type* int_lhs = Type::Intersect(lhs, cache_.kInteger, zone());
+  Type* int_rhs = Type::Intersect(rhs, cache_.kInteger, zone());
+  Type* result =
+      AddRanger(int_lhs->Min(), int_lhs->Max(), int_rhs->Min(), int_rhs->Max());
+  if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) {
+    result = Type::Union(result, Type::NaN(), zone());
+  }
+  if (lhs->Maybe(Type::MinusZero()) && rhs->Maybe(Type::MinusZero())) {
+    result = Type::Union(result, Type::MinusZero(), zone());
+  }
+  return result;
+}
+
+Type* OperationTyper::NumericSubtract(Type* lhs, Type* rhs) {
+  DCHECK(lhs->Is(Type::Number()));
+  DCHECK(rhs->Is(Type::Number()));
+
+  lhs = Rangify(lhs);
+  rhs = Rangify(rhs);
+  if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
+  if (lhs->IsRange() && rhs->IsRange()) {
+    return SubtractRanger(lhs->AsRange(), rhs->AsRange());
+  }
+  // TODO(neis): Deal with numeric bitsets here and elsewhere.
+  return Type::Number();
+}
+
+Type* OperationTyper::NumericMultiply(Type* lhs, Type* rhs) {
+  DCHECK(lhs->Is(Type::Number()));
+  DCHECK(rhs->Is(Type::Number()));
+  lhs = Rangify(lhs);
+  rhs = Rangify(rhs);
+  if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
+  if (lhs->IsRange() && rhs->IsRange()) {
+    return MultiplyRanger(lhs, rhs);
+  }
+  return Type::Number();
+}
+
+Type* OperationTyper::NumericDivide(Type* lhs, Type* rhs) {
+  DCHECK(lhs->Is(Type::Number()));
+  DCHECK(rhs->Is(Type::Number()));
+
+  if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
+  // Division is tricky, so all we do is try ruling out nan.
+  bool maybe_nan =
+      lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) ||
+      ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) &&
+       (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY));
+  return maybe_nan ? Type::Number() : Type::OrderedNumber();
+}
+
+Type* OperationTyper::NumericModulus(Type* lhs, Type* rhs) {
+  DCHECK(lhs->Is(Type::Number()));
+  DCHECK(rhs->Is(Type::Number()));
+  if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
+
+  if (lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) ||
+      lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) {
+    // Result maybe NaN.
+    return Type::Number();
+  }
+
+  lhs = Rangify(lhs);
+  rhs = Rangify(rhs);
+  if (lhs->IsRange() && rhs->IsRange()) {
+    return ModulusRanger(lhs->AsRange(), rhs->AsRange());
+  }
+  return Type::OrderedNumber();
+}
+
+Type* OperationTyper::ToPrimitive(Type* type) {
+  if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) {
+    return type;
+  }
+  return Type::Primitive();
+}
+
+Type* OperationTyper::Invert(Type* type) {
+  DCHECK(type->Is(Type::Boolean()));
+  DCHECK(type->IsInhabited());
+  if (type->Is(singleton_false())) return singleton_true();
+  if (type->Is(singleton_true())) return singleton_false();
+  return type;
+}
+
+OperationTyper::ComparisonOutcome OperationTyper::Invert(
+    ComparisonOutcome outcome) {
+  ComparisonOutcome result(0);
+  if ((outcome & kComparisonUndefined) != 0) result |= kComparisonUndefined;
+  if ((outcome & kComparisonTrue) != 0) result |= kComparisonFalse;
+  if ((outcome & kComparisonFalse) != 0) result |= kComparisonTrue;
+  return result;
+}
+
+Type* OperationTyper::FalsifyUndefined(ComparisonOutcome outcome) {
+  if ((outcome & kComparisonFalse) != 0 ||
+      (outcome & kComparisonUndefined) != 0) {
+    return (outcome & kComparisonTrue) != 0 ? Type::Boolean()
+                                            : singleton_false();
+  }
+  // Type should be non empty, so we know it should be true.
+  DCHECK((outcome & kComparisonTrue) != 0);
+  return singleton_true();
+}
+
+Type* OperationTyper::TypeJSAdd(Type* lhs, Type* rhs) {
+  lhs = ToPrimitive(lhs);
+  rhs = ToPrimitive(rhs);
+  if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) {
+    if (lhs->Is(Type::String()) || rhs->Is(Type::String())) {
+      return Type::String();
+    } else {
+      return Type::NumberOrString();
+    }
+  }
+  lhs = ToNumber(lhs);
+  rhs = ToNumber(rhs);
+  return NumericAdd(lhs, rhs);
+}
+
+Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) {
+  return NumericSubtract(ToNumber(lhs), ToNumber(rhs));
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/src/compiler/operation-typer.h b/src/compiler/operation-typer.h
new file mode 100644
index 0000000..aa669ac
--- /dev/null
+++ b/src/compiler/operation-typer.h
@@ -0,0 +1,84 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_OPERATION_TYPER_H_
+#define V8_COMPILER_OPERATION_TYPER_H_
+
+#include "src/base/flags.h"
+#include "src/compiler/opcodes.h"
+
+namespace v8 {
+namespace internal {
+
+class Isolate;
+class RangeType;
+class Type;
+class TypeCache;
+class Zone;
+
+namespace compiler {
+
+class OperationTyper {
+ public:
+  OperationTyper(Isolate* isolate, Zone* zone);
+
+  // Typing Phi.
+  Type* Merge(Type* left, Type* right);
+
+  Type* ToPrimitive(Type* type);
+
+  // Helpers for number operation typing.
+  Type* ToNumber(Type* type);
+  Type* WeakenRange(Type* current_range, Type* previous_range);
+
+  Type* NumericAdd(Type* lhs, Type* rhs);
+  Type* NumericSubtract(Type* lhs, Type* rhs);
+  Type* NumericMultiply(Type* lhs, Type* rhs);
+  Type* NumericDivide(Type* lhs, Type* rhs);
+  Type* NumericModulus(Type* lhs, Type* rhs);
+
+  enum ComparisonOutcomeFlags {
+    kComparisonTrue = 1,
+    kComparisonFalse = 2,
+    kComparisonUndefined = 4
+  };
+
+// Javascript binop typers.
+#define DECLARE_CASE(x) Type* Type##x(Type* lhs, Type* rhs);
+  JS_SIMPLE_BINOP_LIST(DECLARE_CASE)
+#undef DECLARE_CASE
+
+  Type* singleton_false() { return singleton_false_; }
+  Type* singleton_true() { return singleton_true_; }
+  Type* singleton_the_hole() { return singleton_the_hole_; }
+
+ private:
+  typedef base::Flags<ComparisonOutcomeFlags> ComparisonOutcome;
+
+  ComparisonOutcome Invert(ComparisonOutcome);
+  Type* Invert(Type*);
+  Type* FalsifyUndefined(ComparisonOutcome);
+
+  Type* Rangify(Type*);
+  Type* AddRanger(double lhs_min, double lhs_max, double rhs_min,
+                  double rhs_max);
+  Type* SubtractRanger(RangeType* lhs, RangeType* rhs);
+  Type* MultiplyRanger(Type* lhs, Type* rhs);
+  Type* ModulusRanger(RangeType* lhs, RangeType* rhs);
+
+  Zone* zone() { return zone_; }
+
+  Zone* zone_;
+  TypeCache const& cache_;
+
+  Type* singleton_false_;
+  Type* singleton_true_;
+  Type* singleton_the_hole_;
+};
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_COMPILER_OPERATION_TYPER_H_
diff --git a/src/compiler/operator-properties.cc b/src/compiler/operator-properties.cc
index 7f38ca7..43b0076 100644
--- a/src/compiler/operator-properties.cc
+++ b/src/compiler/operator-properties.cc
@@ -22,11 +22,12 @@
 // static
 int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
   switch (op->opcode()) {
+    case IrOpcode::kCheckpoint:
     case IrOpcode::kFrameState:
       return 1;
     case IrOpcode::kJSCallRuntime: {
       const CallRuntimeParameters& p = CallRuntimeParametersOf(op);
-      return Linkage::FrameStateInputCount(p.id());
+      return Linkage::NeedsFrameStateInput(p.id()) ? 1 : 0;
     }
 
     // Strict equality cannot lazily deoptimize.
@@ -34,12 +35,6 @@
     case IrOpcode::kJSStrictNotEqual:
       return 0;
 
-    // We record the frame state immediately before and immediately after every
-    // construct/function call.
-    case IrOpcode::kJSCallConstruct:
-    case IrOpcode::kJSCallFunction:
-      return 2;
-
     // Compare operations
     case IrOpcode::kJSEqual:
     case IrOpcode::kJSNotEqual:
@@ -54,6 +49,15 @@
     case IrOpcode::kJSCreateLiteralObject:
     case IrOpcode::kJSCreateLiteralRegExp:
 
+    // Property access operations
+    case IrOpcode::kJSLoadNamed:
+    case IrOpcode::kJSStoreNamed:
+    case IrOpcode::kJSLoadProperty:
+    case IrOpcode::kJSStoreProperty:
+    case IrOpcode::kJSLoadGlobal:
+    case IrOpcode::kJSStoreGlobal:
+    case IrOpcode::kJSDeleteProperty:
+
     // Context operations
     case IrOpcode::kJSCreateScriptContext:
 
@@ -65,24 +69,17 @@
     case IrOpcode::kJSToObject:
     case IrOpcode::kJSToString:
 
+    // Call operations
+    case IrOpcode::kJSCallConstruct:
+    case IrOpcode::kJSCallFunction:
+
     // Misc operations
     case IrOpcode::kJSConvertReceiver:
     case IrOpcode::kJSForInNext:
     case IrOpcode::kJSForInPrepare:
     case IrOpcode::kJSStackCheck:
-    case IrOpcode::kJSDeleteProperty:
       return 1;
 
-    // We record the frame state immediately before and immediately after
-    // every property or global variable access.
-    case IrOpcode::kJSLoadNamed:
-    case IrOpcode::kJSStoreNamed:
-    case IrOpcode::kJSLoadProperty:
-    case IrOpcode::kJSStoreProperty:
-    case IrOpcode::kJSLoadGlobal:
-    case IrOpcode::kJSStoreGlobal:
-      return 2;
-
     // Binary operators that can deopt in the middle the operation (e.g.,
     // as a result of lazy deopt in ToNumber conversion) need a second frame
     // state so that we can resume before the operation.
diff --git a/src/compiler/operator.h b/src/compiler/operator.h
index fa85d59..8f288cb 100644
--- a/src/compiler/operator.h
+++ b/src/compiler/operator.h
@@ -36,18 +36,18 @@
   // transformations for nodes that have this operator.
   enum Property {
     kNoProperties = 0,
-    kReducible = 1 << 0,    // Participates in strength reduction.
-    kCommutative = 1 << 1,  // OP(a, b) == OP(b, a) for all inputs.
-    kAssociative = 1 << 2,  // OP(a, OP(b,c)) == OP(OP(a,b), c) for all inputs.
-    kIdempotent = 1 << 3,   // OP(a); OP(a) == OP(a).
-    kNoRead = 1 << 4,       // Has no scheduling dependency on Effects
-    kNoWrite = 1 << 5,      // Does not modify any Effects and thereby
+    kCommutative = 1 << 0,  // OP(a, b) == OP(b, a) for all inputs.
+    kAssociative = 1 << 1,  // OP(a, OP(b,c)) == OP(OP(a,b), c) for all inputs.
+    kIdempotent = 1 << 2,   // OP(a); OP(a) == OP(a).
+    kNoRead = 1 << 3,       // Has no scheduling dependency on Effects
+    kNoWrite = 1 << 4,      // Does not modify any Effects and thereby
                             // create new scheduling dependencies.
-    kNoThrow = 1 << 6,      // Can never generate an exception.
+    kNoThrow = 1 << 5,      // Can never generate an exception.
+    kNoDeopt = 1 << 6,      // Can never generate an eager deoptimization exit.
     kFoldable = kNoRead | kNoWrite,
-    kKontrol = kFoldable | kNoThrow,
-    kEliminatable = kNoWrite | kNoThrow,
-    kPure = kNoRead | kNoWrite | kNoThrow | kIdempotent
+    kKontrol = kNoDeopt | kFoldable | kNoThrow,
+    kEliminatable = kNoDeopt | kNoWrite | kNoThrow,
+    kPure = kNoDeopt | kNoRead | kNoWrite | kNoThrow | kIdempotent
   };
   typedef base::Flags<Property, uint8_t> Properties;
 
diff --git a/src/compiler/pipeline-statistics.h b/src/compiler/pipeline-statistics.h
index 2b6563d..c52c61c 100644
--- a/src/compiler/pipeline-statistics.h
+++ b/src/compiler/pipeline-statistics.h
@@ -7,6 +7,8 @@
 
 #include <string>
 
+#include "src/base/platform/elapsed-timer.h"
+#include "src/base/smart-pointers.h"
 #include "src/compilation-statistics.h"
 #include "src/compiler/zone-pool.h"
 
@@ -22,6 +24,7 @@
   ~PipelineStatistics();
 
   void BeginPhaseKind(const char* phase_kind_name);
+  void EndPhaseKind();
 
  private:
   size_t OuterZoneSize() {
@@ -43,7 +46,6 @@
   };
 
   bool InPhaseKind() { return !phase_kind_stats_.scope_.is_empty(); }
-  void EndPhaseKind();
 
   friend class PhaseScope;
   bool InPhase() { return !phase_stats_.scope_.is_empty(); }
diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc
index 1d7e967..d592000 100644
--- a/src/compiler/pipeline.cc
+++ b/src/compiler/pipeline.cc
@@ -14,20 +14,20 @@
 #include "src/compiler/basic-block-instrumentor.h"
 #include "src/compiler/branch-elimination.h"
 #include "src/compiler/bytecode-graph-builder.h"
-#include "src/compiler/change-lowering.h"
+#include "src/compiler/checkpoint-elimination.h"
 #include "src/compiler/code-generator.h"
 #include "src/compiler/common-operator-reducer.h"
 #include "src/compiler/control-flow-optimizer.h"
 #include "src/compiler/dead-code-elimination.h"
-#include "src/compiler/escape-analysis.h"
+#include "src/compiler/effect-control-linearizer.h"
 #include "src/compiler/escape-analysis-reducer.h"
+#include "src/compiler/escape-analysis.h"
 #include "src/compiler/frame-elider.h"
 #include "src/compiler/graph-replay.h"
 #include "src/compiler/graph-trimmer.h"
 #include "src/compiler/graph-visualizer.h"
-#include "src/compiler/greedy-allocator.h"
-#include "src/compiler/instruction.h"
 #include "src/compiler/instruction-selector.h"
+#include "src/compiler/instruction.h"
 #include "src/compiler/js-builtin-reducer.h"
 #include "src/compiler/js-call-reducer.h"
 #include "src/compiler/js-context-specialization.h"
@@ -45,24 +45,29 @@
 #include "src/compiler/loop-analysis.h"
 #include "src/compiler/loop-peeling.h"
 #include "src/compiler/machine-operator-reducer.h"
+#include "src/compiler/memory-optimizer.h"
 #include "src/compiler/move-optimizer.h"
 #include "src/compiler/osr.h"
 #include "src/compiler/pipeline-statistics.h"
-#include "src/compiler/register-allocator.h"
+#include "src/compiler/redundancy-elimination.h"
 #include "src/compiler/register-allocator-verifier.h"
+#include "src/compiler/register-allocator.h"
 #include "src/compiler/schedule.h"
 #include "src/compiler/scheduler.h"
 #include "src/compiler/select-lowering.h"
 #include "src/compiler/simplified-lowering.h"
-#include "src/compiler/simplified-operator.h"
 #include "src/compiler/simplified-operator-reducer.h"
+#include "src/compiler/simplified-operator.h"
+#include "src/compiler/store-store-elimination.h"
 #include "src/compiler/tail-call-optimization.h"
 #include "src/compiler/type-hint-analyzer.h"
 #include "src/compiler/typer.h"
 #include "src/compiler/value-numbering-reducer.h"
 #include "src/compiler/verifier.h"
 #include "src/compiler/zone-pool.h"
+#include "src/isolate-inl.h"
 #include "src/ostreams.h"
+#include "src/parsing/parser.h"
 #include "src/register-configuration.h"
 #include "src/type-info.h"
 #include "src/utils.h"
@@ -78,31 +83,19 @@
                PipelineStatistics* pipeline_statistics)
       : isolate_(info->isolate()),
         info_(info),
+        debug_name_(info_->GetDebugName()),
         outer_zone_(info_->zone()),
         zone_pool_(zone_pool),
         pipeline_statistics_(pipeline_statistics),
-        compilation_failed_(false),
-        code_(Handle<Code>::null()),
         graph_zone_scope_(zone_pool_),
         graph_zone_(graph_zone_scope_.zone()),
-        graph_(nullptr),
-        loop_assignment_(nullptr),
-        simplified_(nullptr),
-        machine_(nullptr),
-        common_(nullptr),
-        javascript_(nullptr),
-        jsgraph_(nullptr),
-        schedule_(nullptr),
         instruction_zone_scope_(zone_pool_),
         instruction_zone_(instruction_zone_scope_.zone()),
-        sequence_(nullptr),
-        frame_(nullptr),
         register_allocation_zone_scope_(zone_pool_),
-        register_allocation_zone_(register_allocation_zone_scope_.zone()),
-        register_allocation_data_(nullptr) {
+        register_allocation_zone_(register_allocation_zone_scope_.zone()) {
     PhaseScope scope(pipeline_statistics, "init pipeline data");
     graph_ = new (graph_zone_) Graph(graph_zone_);
-    source_positions_.Reset(new SourcePositionTable(graph_));
+    source_positions_ = new (graph_zone_) SourcePositionTable(graph_);
     simplified_ = new (graph_zone_) SimplifiedOperatorBuilder(graph_zone_);
     machine_ = new (graph_zone_) MachineOperatorBuilder(
         graph_zone_, MachineType::PointerRepresentation(),
@@ -113,62 +106,50 @@
         JSGraph(isolate_, graph_, common_, javascript_, simplified_, machine_);
   }
 
+  // For WASM compile entry point.
+  PipelineData(ZonePool* zone_pool, CompilationInfo* info, Graph* graph,
+               SourcePositionTable* source_positions)
+      : isolate_(info->isolate()),
+        info_(info),
+        debug_name_(info_->GetDebugName()),
+        zone_pool_(zone_pool),
+        graph_zone_scope_(zone_pool_),
+        graph_(graph),
+        source_positions_(source_positions),
+        instruction_zone_scope_(zone_pool_),
+        instruction_zone_(instruction_zone_scope_.zone()),
+        register_allocation_zone_scope_(zone_pool_),
+        register_allocation_zone_(register_allocation_zone_scope_.zone()) {}
+
   // For machine graph testing entry point.
   PipelineData(ZonePool* zone_pool, CompilationInfo* info, Graph* graph,
                Schedule* schedule)
       : isolate_(info->isolate()),
         info_(info),
-        outer_zone_(nullptr),
+        debug_name_(info_->GetDebugName()),
         zone_pool_(zone_pool),
-        pipeline_statistics_(nullptr),
-        compilation_failed_(false),
-        code_(Handle<Code>::null()),
         graph_zone_scope_(zone_pool_),
-        graph_zone_(nullptr),
         graph_(graph),
-        source_positions_(new SourcePositionTable(graph_)),
-        loop_assignment_(nullptr),
-        simplified_(nullptr),
-        machine_(nullptr),
-        common_(nullptr),
-        javascript_(nullptr),
-        jsgraph_(nullptr),
+        source_positions_(new (info->zone()) SourcePositionTable(graph_)),
         schedule_(schedule),
         instruction_zone_scope_(zone_pool_),
         instruction_zone_(instruction_zone_scope_.zone()),
-        sequence_(nullptr),
-        frame_(nullptr),
         register_allocation_zone_scope_(zone_pool_),
-        register_allocation_zone_(register_allocation_zone_scope_.zone()),
-        register_allocation_data_(nullptr) {}
+        register_allocation_zone_(register_allocation_zone_scope_.zone()) {}
 
   // For register allocation testing entry point.
   PipelineData(ZonePool* zone_pool, CompilationInfo* info,
                InstructionSequence* sequence)
       : isolate_(info->isolate()),
         info_(info),
-        outer_zone_(nullptr),
+        debug_name_(info_->GetDebugName()),
         zone_pool_(zone_pool),
-        pipeline_statistics_(nullptr),
-        compilation_failed_(false),
-        code_(Handle<Code>::null()),
         graph_zone_scope_(zone_pool_),
-        graph_zone_(nullptr),
-        graph_(nullptr),
-        loop_assignment_(nullptr),
-        simplified_(nullptr),
-        machine_(nullptr),
-        common_(nullptr),
-        javascript_(nullptr),
-        jsgraph_(nullptr),
-        schedule_(nullptr),
         instruction_zone_scope_(zone_pool_),
         instruction_zone_(sequence->zone()),
         sequence_(sequence),
-        frame_(nullptr),
         register_allocation_zone_scope_(zone_pool_),
-        register_allocation_zone_(register_allocation_zone_scope_.zone()),
-        register_allocation_data_(nullptr) {}
+        register_allocation_zone_(register_allocation_zone_scope_.zone()) {}
 
   ~PipelineData() {
     DeleteRegisterAllocationZone();
@@ -193,9 +174,7 @@
 
   Zone* graph_zone() const { return graph_zone_; }
   Graph* graph() const { return graph_; }
-  SourcePositionTable* source_positions() const {
-    return source_positions_.get();
-  }
+  SourcePositionTable* source_positions() const { return source_positions_; }
   MachineOperatorBuilder* machine() const { return machine_; }
   CommonOperatorBuilder* common() const { return common_; }
   JSOperatorBuilder* javascript() const { return javascript_; }
@@ -224,6 +203,7 @@
     DCHECK(!schedule_);
     schedule_ = schedule;
   }
+  void reset_schedule() { schedule_ = nullptr; }
 
   Zone* instruction_zone() const { return instruction_zone_; }
   InstructionSequence* sequence() const { return sequence_; }
@@ -234,14 +214,24 @@
     return register_allocation_data_;
   }
 
+  BasicBlockProfiler::Data* profiler_data() const { return profiler_data_; }
+  void set_profiler_data(BasicBlockProfiler::Data* profiler_data) {
+    profiler_data_ = profiler_data;
+  }
+
+  std::string const& source_position_output() const {
+    return source_position_output_;
+  }
+  void set_source_position_output(std::string const& source_position_output) {
+    source_position_output_ = source_position_output;
+  }
+
   void DeleteGraphZone() {
-    // Destroy objects with destructors first.
-    source_positions_.Reset(nullptr);
     if (graph_zone_ == nullptr) return;
-    // Destroy zone and clear pointers.
     graph_zone_scope_.Destroy();
     graph_zone_ = nullptr;
     graph_ = nullptr;
+    source_positions_ = nullptr;
     loop_assignment_ = nullptr;
     type_hint_analysis_ = nullptr;
     simplified_ = nullptr;
@@ -288,42 +278,53 @@
     if (descriptor != nullptr) {
       fixed_frame_size = CalculateFixedFrameSize(descriptor);
     }
-    frame_ = new (instruction_zone()) Frame(fixed_frame_size, descriptor);
+    frame_ = new (instruction_zone()) Frame(fixed_frame_size);
   }
 
   void InitializeRegisterAllocationData(const RegisterConfiguration* config,
-                                        CallDescriptor* descriptor,
-                                        const char* debug_name) {
+                                        CallDescriptor* descriptor) {
     DCHECK(register_allocation_data_ == nullptr);
     register_allocation_data_ = new (register_allocation_zone())
         RegisterAllocationData(config, register_allocation_zone(), frame(),
-                               sequence(), debug_name);
+                               sequence(), debug_name_.get());
+  }
+
+  void BeginPhaseKind(const char* phase_kind_name) {
+    if (pipeline_statistics() != nullptr) {
+      pipeline_statistics()->BeginPhaseKind(phase_kind_name);
+    }
+  }
+
+  void EndPhaseKind() {
+    if (pipeline_statistics() != nullptr) {
+      pipeline_statistics()->EndPhaseKind();
+    }
   }
 
  private:
-  Isolate* isolate_;
-  CompilationInfo* info_;
-  Zone* outer_zone_;
+  Isolate* const isolate_;
+  CompilationInfo* const info_;
+  base::SmartArrayPointer<char> debug_name_;
+  Zone* outer_zone_ = nullptr;
   ZonePool* const zone_pool_;
-  PipelineStatistics* pipeline_statistics_;
-  bool compilation_failed_;
-  Handle<Code> code_;
+  PipelineStatistics* pipeline_statistics_ = nullptr;
+  bool compilation_failed_ = false;
+  Handle<Code> code_ = Handle<Code>::null();
 
   // All objects in the following group of fields are allocated in graph_zone_.
   // They are all set to nullptr when the graph_zone_ is destroyed.
   ZonePool::Scope graph_zone_scope_;
-  Zone* graph_zone_;
-  Graph* graph_;
-  // TODO(dcarney): make this into a ZoneObject.
-  base::SmartPointer<SourcePositionTable> source_positions_;
-  LoopAssignmentAnalysis* loop_assignment_;
+  Zone* graph_zone_ = nullptr;
+  Graph* graph_ = nullptr;
+  SourcePositionTable* source_positions_ = nullptr;
+  LoopAssignmentAnalysis* loop_assignment_ = nullptr;
   TypeHintAnalysis* type_hint_analysis_ = nullptr;
-  SimplifiedOperatorBuilder* simplified_;
-  MachineOperatorBuilder* machine_;
-  CommonOperatorBuilder* common_;
-  JSOperatorBuilder* javascript_;
-  JSGraph* jsgraph_;
-  Schedule* schedule_;
+  SimplifiedOperatorBuilder* simplified_ = nullptr;
+  MachineOperatorBuilder* machine_ = nullptr;
+  CommonOperatorBuilder* common_ = nullptr;
+  JSOperatorBuilder* javascript_ = nullptr;
+  JSGraph* jsgraph_ = nullptr;
+  Schedule* schedule_ = nullptr;
 
   // All objects in the following group of fields are allocated in
   // instruction_zone_.  They are all set to nullptr when the instruction_zone_
@@ -331,15 +332,21 @@
   // destroyed.
   ZonePool::Scope instruction_zone_scope_;
   Zone* instruction_zone_;
-  InstructionSequence* sequence_;
-  Frame* frame_;
+  InstructionSequence* sequence_ = nullptr;
+  Frame* frame_ = nullptr;
 
   // All objects in the following group of fields are allocated in
   // register_allocation_zone_.  They are all set to nullptr when the zone is
   // destroyed.
   ZonePool::Scope register_allocation_zone_scope_;
   Zone* register_allocation_zone_;
-  RegisterAllocationData* register_allocation_data_;
+  RegisterAllocationData* register_allocation_data_ = nullptr;
+
+  // Basic block profiling support.
+  BasicBlockProfiler::Data* profiler_data_ = nullptr;
+
+  // Source position output for --trace-turbo.
+  std::string source_position_output_;
 
   int CalculateFixedFrameSize(CallDescriptor* descriptor) {
     if (descriptor->IsJSFunctionCall()) {
@@ -354,6 +361,38 @@
   DISALLOW_COPY_AND_ASSIGN(PipelineData);
 };
 
+class PipelineImpl final {
+ public:
+  explicit PipelineImpl(PipelineData* data) : data_(data) {}
+
+  // Helpers for executing pipeline phases.
+  template <typename Phase>
+  void Run();
+  template <typename Phase, typename Arg0>
+  void Run(Arg0 arg_0);
+  template <typename Phase, typename Arg0, typename Arg1>
+  void Run(Arg0 arg_0, Arg1 arg_1);
+
+  // Run the graph creation and initial optimization passes.
+  bool CreateGraph();
+
+  // Run the concurrent optimization passes.
+  bool OptimizeGraph(Linkage* linkage);
+
+  // Perform the actual code generation and return handle to a code object.
+  Handle<Code> GenerateCode(Linkage* linkage);
+
+  bool ScheduleAndSelectInstructions(Linkage* linkage);
+  void RunPrintAndVerify(const char* phase, bool untyped = false);
+  Handle<Code> ScheduleAndGenerateCode(CallDescriptor* call_descriptor);
+  void AllocateRegisters(const RegisterConfiguration* config,
+                         CallDescriptor* descriptor, bool run_verifier);
+
+  CompilationInfo* info() const;
+  Isolate* isolate() const;
+
+  PipelineData* const data_;
+};
 
 namespace {
 
@@ -363,26 +402,30 @@
                       std::ios_base::app) {}
 };
 
+struct TurboJsonFile : public std::ofstream {
+  TurboJsonFile(CompilationInfo* info, std::ios_base::openmode mode)
+      : std::ofstream(GetVisualizerLogFileName(info, nullptr, "json").get(),
+                      mode) {}
+};
 
 void TraceSchedule(CompilationInfo* info, Schedule* schedule) {
   if (FLAG_trace_turbo) {
-    FILE* json_file = OpenVisualizerLogFile(info, nullptr, "json", "a+");
-    if (json_file != nullptr) {
-      OFStream json_of(json_file);
-      json_of << "{\"name\":\"Schedule\",\"type\":\"schedule\",\"data\":\"";
-      std::stringstream schedule_stream;
-      schedule_stream << *schedule;
-      std::string schedule_string(schedule_stream.str());
-      for (const auto& c : schedule_string) {
-        json_of << AsEscapedUC16ForJSON(c);
-      }
-      json_of << "\"},\n";
-      fclose(json_file);
+    AllowHandleDereference allow_deref;
+    TurboJsonFile json_of(info, std::ios_base::app);
+    json_of << "{\"name\":\"Schedule\",\"type\":\"schedule\",\"data\":\"";
+    std::stringstream schedule_stream;
+    schedule_stream << *schedule;
+    std::string schedule_string(schedule_stream.str());
+    for (const auto& c : schedule_string) {
+      json_of << AsEscapedUC16ForJSON(c);
     }
+    json_of << "\"},\n";
   }
-  if (!FLAG_trace_turbo_graph && !FLAG_trace_turbo_scheduler) return;
-  OFStream os(stdout);
-  os << "-- Schedule --------------------------------------\n" << *schedule;
+  if (FLAG_trace_turbo_graph || FLAG_trace_turbo_scheduler) {
+    AllowHandleDereference allow_deref;
+    OFStream os(stdout);
+    os << "-- Schedule --------------------------------------\n" << *schedule;
+  }
 }
 
 
@@ -476,32 +519,204 @@
   ZonePool::Scope zone_scope_;
 };
 
+PipelineStatistics* CreatePipelineStatistics(CompilationInfo* info,
+                                             ZonePool* zone_pool) {
+  PipelineStatistics* pipeline_statistics = nullptr;
+
+  if (FLAG_turbo_stats || FLAG_turbo_stats_nvp) {
+    pipeline_statistics = new PipelineStatistics(info, zone_pool);
+    pipeline_statistics->BeginPhaseKind("initializing");
+  }
+
+  if (FLAG_trace_turbo) {
+    TurboJsonFile json_of(info, std::ios_base::trunc);
+    Handle<Script> script = info->script();
+    base::SmartArrayPointer<char> function_name = info->GetDebugName();
+    int pos = info->shared_info()->start_position();
+    json_of << "{\"function\":\"" << function_name.get()
+            << "\", \"sourcePosition\":" << pos << ", \"source\":\"";
+    Isolate* isolate = info->isolate();
+    if (!script->IsUndefined(isolate) &&
+        !script->source()->IsUndefined(isolate)) {
+      DisallowHeapAllocation no_allocation;
+      int start = info->shared_info()->start_position();
+      int len = info->shared_info()->end_position() - start;
+      String::SubStringRange source(String::cast(script->source()), start, len);
+      for (const auto& c : source) {
+        json_of << AsEscapedUC16ForJSON(c);
+      }
+    }
+    json_of << "\",\n\"phases\":[";
+  }
+
+  return pipeline_statistics;
+}
+
 }  // namespace
 
+class PipelineCompilationJob final : public CompilationJob {
+ public:
+  PipelineCompilationJob(Isolate* isolate, Handle<JSFunction> function)
+      // Note that the CompilationInfo is not initialized at the time we pass it
+      // to the CompilationJob constructor, but it is not dereferenced there.
+      : CompilationJob(&info_, "TurboFan"),
+        zone_(isolate->allocator()),
+        zone_pool_(isolate->allocator()),
+        parse_info_(&zone_, function),
+        info_(&parse_info_, function),
+        pipeline_statistics_(CreatePipelineStatistics(info(), &zone_pool_)),
+        data_(&zone_pool_, info(), pipeline_statistics_.get()),
+        pipeline_(&data_),
+        linkage_(nullptr) {}
+
+ protected:
+  Status CreateGraphImpl() final;
+  Status OptimizeGraphImpl() final;
+  Status GenerateCodeImpl() final;
+
+ private:
+  Zone zone_;
+  ZonePool zone_pool_;
+  ParseInfo parse_info_;
+  CompilationInfo info_;
+  base::SmartPointer<PipelineStatistics> pipeline_statistics_;
+  PipelineData data_;
+  PipelineImpl pipeline_;
+  Linkage* linkage_;
+};
+
+PipelineCompilationJob::Status PipelineCompilationJob::CreateGraphImpl() {
+  if (info()->shared_info()->asm_function()) {
+    if (info()->osr_frame()) info()->MarkAsFrameSpecializing();
+    info()->MarkAsFunctionContextSpecializing();
+  } else {
+    if (!FLAG_always_opt) {
+      info()->MarkAsBailoutOnUninitialized();
+    }
+    if (FLAG_native_context_specialization) {
+      info()->MarkAsNativeContextSpecializing();
+    }
+  }
+  if (!info()->shared_info()->asm_function() || FLAG_turbo_asm_deoptimization) {
+    info()->MarkAsDeoptimizationEnabled();
+  }
+  if (!info()->is_optimizing_from_bytecode()) {
+    if (info()->is_deoptimization_enabled() && FLAG_turbo_type_feedback) {
+      info()->MarkAsTypeFeedbackEnabled();
+    }
+    if (!Compiler::EnsureDeoptimizationSupport(info())) return FAILED;
+  }
+
+  linkage_ = new (&zone_) Linkage(Linkage::ComputeIncoming(&zone_, info()));
+
+  if (!pipeline_.CreateGraph()) {
+    if (isolate()->has_pending_exception()) return FAILED;  // Stack overflowed.
+    return AbortOptimization(kGraphBuildingFailed);
+  }
+
+  return SUCCEEDED;
+}
+
+PipelineCompilationJob::Status PipelineCompilationJob::OptimizeGraphImpl() {
+  if (!pipeline_.OptimizeGraph(linkage_)) return FAILED;
+  return SUCCEEDED;
+}
+
+PipelineCompilationJob::Status PipelineCompilationJob::GenerateCodeImpl() {
+  Handle<Code> code = pipeline_.GenerateCode(linkage_);
+  if (code.is_null()) {
+    if (info()->bailout_reason() == kNoReason) {
+      return AbortOptimization(kCodeGenerationFailed);
+    }
+    return FAILED;
+  }
+  info()->dependencies()->Commit(code);
+  info()->SetCode(code);
+  if (info()->is_deoptimization_enabled()) {
+    info()->context()->native_context()->AddOptimizedCode(*code);
+    RegisterWeakObjectsInOptimizedCode(code);
+  }
+  return SUCCEEDED;
+}
+
+class PipelineWasmCompilationJob final : public CompilationJob {
+ public:
+  explicit PipelineWasmCompilationJob(CompilationInfo* info, Graph* graph,
+                                      CallDescriptor* descriptor,
+                                      SourcePositionTable* source_positions)
+      : CompilationJob(info, "TurboFan"),
+        zone_pool_(info->isolate()->allocator()),
+        data_(&zone_pool_, info, graph, source_positions),
+        pipeline_(&data_),
+        linkage_(descriptor) {}
+
+ protected:
+  Status CreateGraphImpl() final;
+  Status OptimizeGraphImpl() final;
+  Status GenerateCodeImpl() final;
+
+ private:
+  ZonePool zone_pool_;
+  PipelineData data_;
+  PipelineImpl pipeline_;
+  Linkage linkage_;
+};
+
+PipelineWasmCompilationJob::Status
+PipelineWasmCompilationJob::CreateGraphImpl() {
+  return SUCCEEDED;
+}
+
+PipelineWasmCompilationJob::Status
+PipelineWasmCompilationJob::OptimizeGraphImpl() {
+  if (FLAG_trace_turbo) {
+    TurboJsonFile json_of(info(), std::ios_base::trunc);
+    json_of << "{\"function\":\"" << info()->GetDebugName().get()
+            << "\", \"source\":\"\",\n\"phases\":[";
+  }
+
+  pipeline_.RunPrintAndVerify("Machine", true);
+
+  if (!pipeline_.ScheduleAndSelectInstructions(&linkage_)) return FAILED;
+  return SUCCEEDED;
+}
+
+PipelineWasmCompilationJob::Status
+PipelineWasmCompilationJob::GenerateCodeImpl() {
+  pipeline_.GenerateCode(&linkage_);
+  return SUCCEEDED;
+}
 
 template <typename Phase>
-void Pipeline::Run() {
+void PipelineImpl::Run() {
   PipelineRunScope scope(this->data_, Phase::phase_name());
   Phase phase;
   phase.Run(this->data_, scope.zone());
 }
 
-
 template <typename Phase, typename Arg0>
-void Pipeline::Run(Arg0 arg_0) {
+void PipelineImpl::Run(Arg0 arg_0) {
   PipelineRunScope scope(this->data_, Phase::phase_name());
   Phase phase;
   phase.Run(this->data_, scope.zone(), arg_0);
 }
 
+template <typename Phase, typename Arg0, typename Arg1>
+void PipelineImpl::Run(Arg0 arg_0, Arg1 arg_1) {
+  PipelineRunScope scope(this->data_, Phase::phase_name());
+  Phase phase;
+  phase.Run(this->data_, scope.zone(), arg_0, arg_1);
+}
 
 struct LoopAssignmentAnalysisPhase {
   static const char* phase_name() { return "loop assignment analysis"; }
 
   void Run(PipelineData* data, Zone* temp_zone) {
-    AstLoopAssignmentAnalyzer analyzer(data->graph_zone(), data->info());
-    LoopAssignmentAnalysis* loop_assignment = analyzer.Analyze();
-    data->set_loop_assignment(loop_assignment);
+    if (!data->info()->is_optimizing_from_bytecode()) {
+      AstLoopAssignmentAnalyzer analyzer(data->graph_zone(), data->info());
+      LoopAssignmentAnalysis* loop_assignment = analyzer.Analyze();
+      data->set_loop_assignment(loop_assignment);
+    }
   }
 };
 
@@ -510,10 +725,12 @@
   static const char* phase_name() { return "type hint analysis"; }
 
   void Run(PipelineData* data, Zone* temp_zone) {
-    TypeHintAnalyzer analyzer(data->graph_zone());
-    Handle<Code> code(data->info()->shared_info()->code(), data->isolate());
-    TypeHintAnalysis* type_hint_analysis = analyzer.Analyze(code);
-    data->set_type_hint_analysis(type_hint_analysis);
+    if (data->info()->is_type_feedback_enabled()) {
+      TypeHintAnalyzer analyzer(data->graph_zone());
+      Handle<Code> code(data->info()->shared_info()->code(), data->isolate());
+      TypeHintAnalysis* type_hint_analysis = analyzer.Analyze(code);
+      data->set_type_hint_analysis(type_hint_analysis);
+    }
   }
 };
 
@@ -525,7 +742,7 @@
     bool stack_check = !data->info()->IsStub();
     bool succeeded = false;
 
-    if (data->info()->shared_info()->HasBytecodeArray()) {
+    if (data->info()->is_optimizing_from_bytecode()) {
       BytecodeGraphBuilder graph_builder(temp_zone, data->info(),
                                          data->jsgraph());
       succeeded = graph_builder.CreateGraph();
@@ -594,7 +811,9 @@
     AddReducer(data, &graph_reducer, &native_context_specialization);
     AddReducer(data, &graph_reducer, &context_specialization);
     AddReducer(data, &graph_reducer, &call_reducer);
-    AddReducer(data, &graph_reducer, &inlining);
+    if (!data->info()->is_optimizing_from_bytecode()) {
+      AddReducer(data, &graph_reducer, &inlining);
+    }
     graph_reducer.ReduceGraph();
   }
 };
@@ -610,6 +829,31 @@
   }
 };
 
+#ifdef DEBUG
+
+struct UntyperPhase {
+  static const char* phase_name() { return "untyper"; }
+
+  void Run(PipelineData* data, Zone* temp_zone) {
+    class RemoveTypeReducer final : public Reducer {
+     public:
+      Reduction Reduce(Node* node) final {
+        if (NodeProperties::IsTyped(node)) {
+          NodeProperties::RemoveType(node);
+          return Changed(node);
+        }
+        return NoChange();
+      }
+    };
+
+    JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
+    RemoveTypeReducer remove_type_reducer;
+    AddReducer(data, &graph_reducer, &remove_type_reducer);
+    graph_reducer.ReduceGraph();
+  }
+};
+
+#endif  // DEBUG
 
 struct OsrDeconstructionPhase {
   static const char* phase_name() { return "OSR deconstruction"; }
@@ -629,7 +873,7 @@
     DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
                                               data->common());
     LoadElimination load_elimination(&graph_reducer, data->graph(),
-                                     data->common());
+                                     data->jsgraph()->simplified());
     JSBuiltinReducer builtin_reducer(&graph_reducer, data->jsgraph());
     MaybeHandle<LiteralsArray> literals_array =
         data->info()->is_native_context_specializing()
@@ -645,6 +889,9 @@
     if (data->info()->shared_info()->HasBytecodeArray()) {
       typed_lowering_flags |= JSTypedLowering::kDisableBinaryOpReduction;
     }
+    if (data->info()->is_type_feedback_enabled()) {
+      typed_lowering_flags |= JSTypedLowering::kTypeFeedbackEnabled;
+    }
     JSTypedLowering typed_lowering(&graph_reducer, data->info()->dependencies(),
                                    typed_lowering_flags, data->jsgraph(),
                                    temp_zone);
@@ -653,7 +900,8 @@
         data->info()->is_deoptimization_enabled()
             ? JSIntrinsicLowering::kDeoptimizationEnabled
             : JSIntrinsicLowering::kDeoptimizationDisabled);
-    SimplifiedOperatorReducer simple_reducer(data->jsgraph());
+    SimplifiedOperatorReducer simple_reducer(&graph_reducer, data->jsgraph());
+    CheckpointElimination checkpoint_elimination(&graph_reducer);
     CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
                                          data->common(), data->machine());
     AddReducer(data, &graph_reducer, &dead_code_elimination);
@@ -665,6 +913,7 @@
     AddReducer(data, &graph_reducer, &intrinsic_lowering);
     AddReducer(data, &graph_reducer, &load_elimination);
     AddReducer(data, &graph_reducer, &simple_reducer);
+    AddReducer(data, &graph_reducer, &checkpoint_elimination);
     AddReducer(data, &graph_reducer, &common_reducer);
     graph_reducer.ReduceGraph();
   }
@@ -697,39 +946,44 @@
     JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
     EscapeAnalysisReducer escape_reducer(&graph_reducer, data->jsgraph(),
                                          &escape_analysis, temp_zone);
-    escape_reducer.SetExistsVirtualAllocate(
-        escape_analysis.ExistsVirtualAllocate());
     AddReducer(data, &graph_reducer, &escape_reducer);
     graph_reducer.ReduceGraph();
     escape_reducer.VerifyReplacement();
   }
 };
 
-
-struct SimplifiedLoweringPhase {
-  static const char* phase_name() { return "simplified lowering"; }
+struct RepresentationSelectionPhase {
+  static const char* phase_name() { return "representation selection"; }
 
   void Run(PipelineData* data, Zone* temp_zone) {
+    SimplifiedLowering::Flags flags =
+        data->info()->is_type_feedback_enabled()
+            ? SimplifiedLowering::kTypeFeedbackEnabled
+            : SimplifiedLowering::kNoFlag;
     SimplifiedLowering lowering(data->jsgraph(), temp_zone,
-                                data->source_positions());
+                                data->source_positions(), flags);
     lowering.LowerAllNodes();
+  }
+};
 
-    // TODO(bmeurer): See comment on SimplifiedLowering::abort_compilation_.
-    if (lowering.abort_compilation_) {
-      data->set_compilation_failed();
-      return;
-    }
+struct EarlyOptimizationPhase {
+  static const char* phase_name() { return "early optimization"; }
 
+  void Run(PipelineData* data, Zone* temp_zone) {
     JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
+    JSGenericLowering generic_lowering(data->jsgraph());
     DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
                                               data->common());
-    SimplifiedOperatorReducer simple_reducer(data->jsgraph());
+    SimplifiedOperatorReducer simple_reducer(&graph_reducer, data->jsgraph());
+    RedundancyElimination redundancy_elimination(&graph_reducer, temp_zone);
     ValueNumberingReducer value_numbering(temp_zone);
     MachineOperatorReducer machine_reducer(data->jsgraph());
     CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
                                          data->common(), data->machine());
     AddReducer(data, &graph_reducer, &dead_code_elimination);
     AddReducer(data, &graph_reducer, &simple_reducer);
+    AddReducer(data, &graph_reducer, &redundancy_elimination);
+    AddReducer(data, &graph_reducer, &generic_lowering);
     AddReducer(data, &graph_reducer, &value_numbering);
     AddReducer(data, &graph_reducer, &machine_reducer);
     AddReducer(data, &graph_reducer, &common_reducer);
@@ -737,7 +991,6 @@
   }
 };
 
-
 struct ControlFlowOptimizationPhase {
   static const char* phase_name() { return "control flow optimization"; }
 
@@ -748,31 +1001,86 @@
   }
 };
 
+struct EffectControlLinearizationPhase {
+  static const char* phase_name() { return "effect linearization"; }
 
-struct ChangeLoweringPhase {
-  static const char* phase_name() { return "change lowering"; }
+  void Run(PipelineData* data, Zone* temp_zone) {
+    // The scheduler requires the graphs to be trimmed, so trim now.
+    // TODO(jarin) Remove the trimming once the scheduler can handle untrimmed
+    // graphs.
+    GraphTrimmer trimmer(temp_zone, data->graph());
+    NodeVector roots(temp_zone);
+    data->jsgraph()->GetCachedNodes(&roots);
+    trimmer.TrimGraph(roots.begin(), roots.end());
+
+    // Schedule the graph without node splitting so that we can
+    // fix the effect and control flow for nodes with low-level side
+    // effects (such as changing representation to tagged or
+    // 'floating' allocation regions.)
+    Schedule* schedule = Scheduler::ComputeSchedule(temp_zone, data->graph(),
+                                                    Scheduler::kNoFlags);
+    if (FLAG_turbo_verify) ScheduleVerifier::Run(schedule);
+    TraceSchedule(data->info(), schedule);
+
+    // Post-pass for wiring the control/effects
+    // - connect allocating representation changes into the control&effect
+    //   chains and lower them,
+    // - get rid of the region markers,
+    // - introduce effect phis and rewire effects to get SSA again.
+    EffectControlLinearizer linearizer(data->jsgraph(), schedule, temp_zone);
+    linearizer.Run();
+  }
+};
+
+struct StoreStoreEliminationPhase {
+  static const char* phase_name() { return "Store-store elimination"; }
+
+  void Run(PipelineData* data, Zone* temp_zone) {
+    StoreStoreElimination store_store_elimination(data->jsgraph(), temp_zone);
+    store_store_elimination.Run();
+  }
+};
+
+struct MemoryOptimizationPhase {
+  static const char* phase_name() { return "memory optimization"; }
+
+  void Run(PipelineData* data, Zone* temp_zone) {
+    // The memory optimizer requires the graphs to be trimmed, so trim now.
+    GraphTrimmer trimmer(temp_zone, data->graph());
+    NodeVector roots(temp_zone);
+    data->jsgraph()->GetCachedNodes(&roots);
+    trimmer.TrimGraph(roots.begin(), roots.end());
+
+    // Optimize allocations and load/store operations.
+    MemoryOptimizer optimizer(data->jsgraph(), temp_zone);
+    optimizer.Optimize();
+  }
+};
+
+struct LateOptimizationPhase {
+  static const char* phase_name() { return "late optimization"; }
 
   void Run(PipelineData* data, Zone* temp_zone) {
     JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
     DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
                                               data->common());
-    SimplifiedOperatorReducer simple_reducer(data->jsgraph());
     ValueNumberingReducer value_numbering(temp_zone);
-    ChangeLowering lowering(data->jsgraph());
     MachineOperatorReducer machine_reducer(data->jsgraph());
     CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
                                          data->common(), data->machine());
+    SelectLowering select_lowering(data->jsgraph()->graph(),
+                                   data->jsgraph()->common());
+    TailCallOptimization tco(data->common(), data->graph());
     AddReducer(data, &graph_reducer, &dead_code_elimination);
-    AddReducer(data, &graph_reducer, &simple_reducer);
     AddReducer(data, &graph_reducer, &value_numbering);
-    AddReducer(data, &graph_reducer, &lowering);
     AddReducer(data, &graph_reducer, &machine_reducer);
     AddReducer(data, &graph_reducer, &common_reducer);
+    AddReducer(data, &graph_reducer, &select_lowering);
+    AddReducer(data, &graph_reducer, &tco);
     graph_reducer.ReduceGraph();
   }
 };
 
-
 struct EarlyGraphTrimmingPhase {
   static const char* phase_name() { return "early graph trimming"; }
   void Run(PipelineData* data, Zone* temp_zone) {
@@ -810,30 +1118,6 @@
 };
 
 
-struct GenericLoweringPhase {
-  static const char* phase_name() { return "generic lowering"; }
-
-  void Run(PipelineData* data, Zone* temp_zone) {
-    JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
-    DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
-                                              data->common());
-    CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
-                                         data->common(), data->machine());
-    JSGenericLowering generic_lowering(data->info()->is_typing_enabled(),
-                                       data->jsgraph());
-    SelectLowering select_lowering(data->jsgraph()->graph(),
-                                   data->jsgraph()->common());
-    TailCallOptimization tco(data->common(), data->graph());
-    AddReducer(data, &graph_reducer, &dead_code_elimination);
-    AddReducer(data, &graph_reducer, &common_reducer);
-    AddReducer(data, &graph_reducer, &generic_lowering);
-    AddReducer(data, &graph_reducer, &select_lowering);
-    AddReducer(data, &graph_reducer, &tco);
-    graph_reducer.ReduceGraph();
-  }
-};
-
-
 struct ComputeSchedulePhase {
   static const char* phase_name() { return "scheduling"; }
 
@@ -915,13 +1199,14 @@
   }
 };
 
-
 template <typename RegAllocator>
-struct AllocateDoubleRegistersPhase {
-  static const char* phase_name() { return "allocate double registers"; }
+struct AllocateFPRegistersPhase {
+  static const char* phase_name() {
+    return "allocate floating point registers";
+  }
 
   void Run(PipelineData* data, Zone* temp_zone) {
-    RegAllocator allocator(data->register_allocation_data(), DOUBLE_REGISTERS,
+    RegAllocator allocator(data->register_allocation_data(), FP_REGISTERS,
                            temp_zone);
     allocator.AllocateRegisters();
   }
@@ -1049,15 +1334,14 @@
     Graph* graph = data->graph();
 
     {  // Print JSON.
-      FILE* json_file = OpenVisualizerLogFile(info, nullptr, "json", "a+");
-      if (json_file == nullptr) return;
-      OFStream json_of(json_file);
+      AllowHandleDereference allow_deref;
+      TurboJsonFile json_of(info, std::ios_base::app);
       json_of << "{\"name\":\"" << phase << "\",\"type\":\"graph\",\"data\":"
               << AsJSON(*graph, data->source_positions()) << "},\n";
-      fclose(json_file);
     }
 
     if (FLAG_trace_turbo_graph) {  // Simple textual RPO.
+      AllowHandleDereference allow_deref;
       OFStream os(stdout);
       os << "-- Graph after " << phase << " -- " << std::endl;
       os << AsRPO(*graph);
@@ -1069,22 +1353,14 @@
 struct VerifyGraphPhase {
   static const char* phase_name() { return nullptr; }
 
-  void Run(PipelineData* data, Zone* temp_zone, const bool untyped) {
-    Verifier::Run(data->graph(), FLAG_turbo_types && !untyped
-                                     ? Verifier::TYPED
-                                     : Verifier::UNTYPED);
+  void Run(PipelineData* data, Zone* temp_zone, const bool untyped,
+           bool values_only = false) {
+    Verifier::Run(data->graph(), !untyped ? Verifier::TYPED : Verifier::UNTYPED,
+                  values_only ? Verifier::kValuesOnly : Verifier::kAll);
   }
 };
 
-
-void Pipeline::BeginPhaseKind(const char* phase_kind_name) {
-  if (data_->pipeline_statistics() != nullptr) {
-    data_->pipeline_statistics()->BeginPhaseKind(phase_kind_name);
-  }
-}
-
-
-void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) {
+void PipelineImpl::RunPrintAndVerify(const char* phase, bool untyped) {
   if (FLAG_trace_turbo) {
     Run<PrintGraphPhase>(phase);
   }
@@ -1093,46 +1369,10 @@
   }
 }
 
+bool PipelineImpl::CreateGraph() {
+  PipelineData* data = this->data_;
 
-Handle<Code> Pipeline::GenerateCode() {
-  ZonePool zone_pool(isolate()->allocator());
-  base::SmartPointer<PipelineStatistics> pipeline_statistics;
-
-  if (FLAG_turbo_stats) {
-    pipeline_statistics.Reset(new PipelineStatistics(info(), &zone_pool));
-    pipeline_statistics->BeginPhaseKind("initializing");
-  }
-
-  if (FLAG_trace_turbo) {
-    FILE* json_file = OpenVisualizerLogFile(info(), nullptr, "json", "w+");
-    if (json_file != nullptr) {
-      OFStream json_of(json_file);
-      Handle<Script> script = info()->script();
-      base::SmartArrayPointer<char> function_name = info()->GetDebugName();
-      int pos = info()->shared_info()->start_position();
-      json_of << "{\"function\":\"" << function_name.get()
-              << "\", \"sourcePosition\":" << pos << ", \"source\":\"";
-      if (info()->has_literal() && !script->IsUndefined() &&
-          !script->source()->IsUndefined()) {
-        DisallowHeapAllocation no_allocation;
-        FunctionLiteral* function = info()->literal();
-        int start = function->start_position();
-        int len = function->end_position() - start;
-        String::SubStringRange source(String::cast(script->source()), start,
-                                      len);
-        for (const auto& c : source) {
-          json_of << AsEscapedUC16ForJSON(c);
-        }
-      }
-      json_of << "\",\n\"phases\":[";
-      fclose(json_file);
-    }
-  }
-
-  PipelineData data(&zone_pool, info(), pipeline_statistics.get());
-  this->data_ = &data;
-
-  BeginPhaseKind("graph creation");
+  data->BeginPhaseKind("graph creation");
 
   if (FLAG_trace_turbo) {
     OFStream os(stdout);
@@ -1143,18 +1383,19 @@
     tcf << AsC1VCompilation(info());
   }
 
-  data.source_positions()->AddDecorator();
+  data->source_positions()->AddDecorator();
 
   if (FLAG_loop_assignment_analysis) {
     Run<LoopAssignmentAnalysisPhase>();
   }
 
-  if (info()->is_typing_enabled()) {
-    Run<TypeHintAnalysisPhase>();
-  }
+  Run<TypeHintAnalysisPhase>();
 
   Run<GraphBuilderPhase>();
-  if (data.compilation_failed()) return Handle<Code>::null();
+  if (data->compilation_failed()) {
+    data->EndPhaseKind();
+    return false;
+  }
   RunPrintAndVerify("Initial untyped", true);
 
   // Perform OSR deconstruction.
@@ -1173,24 +1414,23 @@
 
   if (FLAG_print_turbo_replay) {
     // Print a replay of the initial graph.
-    GraphReplayPrinter::PrintReplay(data.graph());
+    GraphReplayPrinter::PrintReplay(data->graph());
   }
 
-  base::SmartPointer<Typer> typer;
-  if (info()->is_typing_enabled()) {
-    // Type the graph.
-    typer.Reset(new Typer(isolate(), data.graph(),
-                          info()->is_deoptimization_enabled()
-                              ? Typer::kDeoptimizationEnabled
-                              : Typer::kNoFlags,
-                          info()->dependencies()));
-    Run<TyperPhase>(typer.get());
+  // Run the type-sensitive lowerings and optimizations on the graph.
+  {
+    // Type the graph and keep the Typer running on newly created nodes within
+    // this scope; the Typer is automatically unlinked from the Graph once we
+    // leave this scope below.
+    Typer typer(isolate(), data->graph(), info()->is_deoptimization_enabled()
+                                              ? Typer::kDeoptimizationEnabled
+                                              : Typer::kNoFlags,
+                info()->dependencies());
+    Run<TyperPhase>(&typer);
     RunPrintAndVerify("Typed");
-  }
 
-  BeginPhaseKind("lowering");
+    data->BeginPhaseKind("lowering");
 
-  if (info()->is_typing_enabled()) {
     // Lower JSOperators where we can determine types.
     Run<TypedLoweringPhase>();
     RunPrintAndVerify("Lowered typed");
@@ -1205,84 +1445,126 @@
       RunPrintAndVerify("Escape Analysed");
     }
 
-    // Lower simplified operators and insert changes.
-    Run<SimplifiedLoweringPhase>();
-    RunPrintAndVerify("Lowered simplified");
-
-    Run<BranchEliminationPhase>();
-    RunPrintAndVerify("Branch conditions eliminated");
-
-    // Optimize control flow.
-    if (FLAG_turbo_cf_optimization) {
-      Run<ControlFlowOptimizationPhase>();
-      RunPrintAndVerify("Control flow optimized");
-    }
-
-    // Lower changes that have been inserted before.
-    Run<ChangeLoweringPhase>();
-    // TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
-    RunPrintAndVerify("Lowered changes", true);
+    // Select representations.
+    Run<RepresentationSelectionPhase>();
+    RunPrintAndVerify("Representations selected", true);
   }
 
-  // Lower any remaining generic JSOperators.
-  Run<GenericLoweringPhase>();
+#ifdef DEBUG
+  // From now on it is invalid to look at types on the nodes, because:
+  //
+  //  (a) The remaining passes (might) run concurrent to the main thread and
+  //      therefore must not access the Heap or the Isolate in an uncontrolled
+  //      way (as done by the type system), and
+  //  (b) the types on the nodes might not make sense after representation
+  //      selection due to the way we handle truncations; if we'd want to look
+  //      at types afterwards we'd essentially need to re-type (large portions
+  //      of) the graph.
+  //
+  // In order to catch bugs related to type access after this point we remove
+  // the types from the nodes at this point (currently only in Debug builds).
+  Run<UntyperPhase>();
+  RunPrintAndVerify("Untyped", true);
+#endif
+
+  // Run early optimization pass.
+  Run<EarlyOptimizationPhase>();
+  RunPrintAndVerify("Early optimized", true);
+
+  data->EndPhaseKind();
+
+  return true;
+}
+
+bool PipelineImpl::OptimizeGraph(Linkage* linkage) {
+  PipelineData* data = this->data_;
+
+  data->BeginPhaseKind("block building");
+
+  Run<EffectControlLinearizationPhase>();
+  RunPrintAndVerify("Effect and control linearized", true);
+
+  if (FLAG_turbo_store_elimination) {
+    Run<StoreStoreEliminationPhase>();
+    RunPrintAndVerify("Store-store elimination", true);
+  }
+
+  Run<BranchEliminationPhase>();
+  RunPrintAndVerify("Branch conditions eliminated", true);
+
+  // Optimize control flow.
+  if (FLAG_turbo_cf_optimization) {
+    Run<ControlFlowOptimizationPhase>();
+    RunPrintAndVerify("Control flow optimized", true);
+  }
+
+  // Optimize memory access and allocation operations.
+  Run<MemoryOptimizationPhase>();
   // TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
-  RunPrintAndVerify("Lowered generic", true);
+  RunPrintAndVerify("Memory optimized", true);
+
+  // Lower changes that have been inserted before.
+  Run<LateOptimizationPhase>();
+  // TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
+  RunPrintAndVerify("Late optimized", true);
 
   Run<LateGraphTrimmingPhase>();
   // TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
   RunPrintAndVerify("Late trimmed", true);
 
-  BeginPhaseKind("block building");
+  data->source_positions()->RemoveDecorator();
 
-  data.source_positions()->RemoveDecorator();
-
-  // Kill the Typer and thereby uninstall the decorator (if any).
-  typer.Reset(nullptr);
-
-  // TODO(bmeurer): See comment on SimplifiedLowering::abort_compilation_.
-  if (data.compilation_failed()) return Handle<Code>::null();
-
-  return ScheduleAndGenerateCode(
-      Linkage::ComputeIncoming(data.instruction_zone(), info()));
+  return ScheduleAndSelectInstructions(linkage);
 }
 
-
 Handle<Code> Pipeline::GenerateCodeForCodeStub(Isolate* isolate,
                                                CallDescriptor* call_descriptor,
                                                Graph* graph, Schedule* schedule,
                                                Code::Flags flags,
                                                const char* debug_name) {
-  CompilationInfo info(debug_name, isolate, graph->zone(), flags);
+  CompilationInfo info(CStrVector(debug_name), isolate, graph->zone(), flags);
 
   // Construct a pipeline for scheduling and code generation.
   ZonePool zone_pool(isolate->allocator());
   PipelineData data(&zone_pool, &info, graph, schedule);
   base::SmartPointer<PipelineStatistics> pipeline_statistics;
-  if (FLAG_turbo_stats) {
+  if (FLAG_turbo_stats || FLAG_turbo_stats_nvp) {
     pipeline_statistics.Reset(new PipelineStatistics(&info, &zone_pool));
     pipeline_statistics->BeginPhaseKind("stub codegen");
   }
 
-  Pipeline pipeline(&info);
-  pipeline.data_ = &data;
+  PipelineImpl pipeline(&data);
   DCHECK_NOT_NULL(data.schedule());
 
   if (FLAG_trace_turbo) {
-    FILE* json_file = OpenVisualizerLogFile(&info, nullptr, "json", "w+");
-    if (json_file != nullptr) {
-      OFStream json_of(json_file);
+    {
+      TurboJsonFile json_of(&info, std::ios_base::trunc);
       json_of << "{\"function\":\"" << info.GetDebugName().get()
               << "\", \"source\":\"\",\n\"phases\":[";
-      fclose(json_file);
     }
     pipeline.Run<PrintGraphPhase>("Machine");
   }
 
+  pipeline.Run<VerifyGraphPhase>(false, true);
   return pipeline.ScheduleAndGenerateCode(call_descriptor);
 }
 
+// static
+Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info) {
+  ZonePool zone_pool(info->isolate()->allocator());
+  base::SmartPointer<PipelineStatistics> pipeline_statistics(
+      CreatePipelineStatistics(info, &zone_pool));
+  PipelineData data(&zone_pool, info, pipeline_statistics.get());
+  PipelineImpl pipeline(&data);
 
+  Linkage linkage(Linkage::ComputeIncoming(data.instruction_zone(), info));
+
+  if (!pipeline.CreateGraph()) return Handle<Code>::null();
+  if (!pipeline.OptimizeGraph(&linkage)) return Handle<Code>::null();
+  return pipeline.GenerateCode(&linkage);
+}
+
+// static
 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info,
                                               Graph* graph,
                                               Schedule* schedule) {
@@ -1291,7 +1573,7 @@
   return GenerateCodeForTesting(info, call_descriptor, graph, schedule);
 }
 
-
+// static
 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info,
                                               CallDescriptor* call_descriptor,
                                               Graph* graph,
@@ -1300,38 +1582,52 @@
   ZonePool zone_pool(info->isolate()->allocator());
   PipelineData data(&zone_pool, info, graph, schedule);
   base::SmartPointer<PipelineStatistics> pipeline_statistics;
-  if (FLAG_turbo_stats) {
+  if (FLAG_turbo_stats || FLAG_turbo_stats_nvp) {
     pipeline_statistics.Reset(new PipelineStatistics(info, &zone_pool));
     pipeline_statistics->BeginPhaseKind("test codegen");
   }
 
-  Pipeline pipeline(info);
-  pipeline.data_ = &data;
-  if (data.schedule() == nullptr) {
-    // TODO(rossberg): Should this really be untyped?
-    pipeline.RunPrintAndVerify("Machine", true);
+  PipelineImpl pipeline(&data);
+
+  if (FLAG_trace_turbo) {
+    TurboJsonFile json_of(info, std::ios_base::trunc);
+    json_of << "{\"function\":\"" << info->GetDebugName().get()
+            << "\", \"source\":\"\",\n\"phases\":[";
   }
+  // TODO(rossberg): Should this really be untyped?
+  pipeline.RunPrintAndVerify("Machine", true);
 
   return pipeline.ScheduleAndGenerateCode(call_descriptor);
 }
 
+// static
+CompilationJob* Pipeline::NewCompilationJob(Handle<JSFunction> function) {
+  return new PipelineCompilationJob(function->GetIsolate(), function);
+}
+
+// static
+CompilationJob* Pipeline::NewWasmCompilationJob(
+    CompilationInfo* info, Graph* graph, CallDescriptor* descriptor,
+    SourcePositionTable* source_positions) {
+  return new PipelineWasmCompilationJob(info, graph, descriptor,
+                                        source_positions);
+}
 
 bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config,
                                            InstructionSequence* sequence,
                                            bool run_verifier) {
-  CompilationInfo info("testing", sequence->isolate(), sequence->zone());
+  CompilationInfo info(ArrayVector("testing"), sequence->isolate(),
+                       sequence->zone());
   ZonePool zone_pool(sequence->isolate()->allocator());
   PipelineData data(&zone_pool, &info, sequence);
-  Pipeline pipeline(&info);
-  pipeline.data_ = &data;
+  PipelineImpl pipeline(&data);
   pipeline.data_->InitializeFrameData(nullptr);
   pipeline.AllocateRegisters(config, nullptr, run_verifier);
   return !data.compilation_failed();
 }
 
-
-Handle<Code> Pipeline::ScheduleAndGenerateCode(
-    CallDescriptor* call_descriptor) {
+bool PipelineImpl::ScheduleAndSelectInstructions(Linkage* linkage) {
+  CallDescriptor* call_descriptor = linkage->GetIncomingDescriptor();
   PipelineData* data = this->data_;
 
   DCHECK_NOT_NULL(data->graph());
@@ -1339,48 +1635,47 @@
   if (data->schedule() == nullptr) Run<ComputeSchedulePhase>();
   TraceSchedule(data->info(), data->schedule());
 
-  BasicBlockProfiler::Data* profiler_data = nullptr;
   if (FLAG_turbo_profiling) {
-    profiler_data = BasicBlockInstrumentor::Instrument(info(), data->graph(),
-                                                       data->schedule());
+    data->set_profiler_data(BasicBlockInstrumentor::Instrument(
+        info(), data->graph(), data->schedule()));
   }
 
   data->InitializeInstructionSequence(call_descriptor);
 
   data->InitializeFrameData(call_descriptor);
   // Select and schedule instructions covering the scheduled graph.
-  Linkage linkage(call_descriptor);
-  Run<InstructionSelectionPhase>(&linkage);
+  Run<InstructionSelectionPhase>(linkage);
 
   if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
+    AllowHandleDereference allow_deref;
     TurboCfgFile tcf(isolate());
     tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(),
                  data->sequence());
   }
 
-  std::ostringstream source_position_output;
   if (FLAG_trace_turbo) {
+    std::ostringstream source_position_output;
     // Output source position information before the graph is deleted.
     data_->source_positions()->Print(source_position_output);
+    data_->set_source_position_output(source_position_output.str());
   }
 
   data->DeleteGraphZone();
 
-  BeginPhaseKind("register allocation");
+  data->BeginPhaseKind("register allocation");
 
   bool run_verifier = FLAG_turbo_verify_allocation;
 
   // Allocate registers.
-  AllocateRegisters(
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN),
-      call_descriptor, run_verifier);
+  AllocateRegisters(RegisterConfiguration::Turbofan(), call_descriptor,
+                    run_verifier);
   Run<FrameElisionPhase>();
   if (data->compilation_failed()) {
     info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc);
-    return Handle<Code>();
+    data->EndPhaseKind();
+    return false;
   }
 
-  BeginPhaseKind("code generation");
   // TODO(mtrofin): move this off to the register allocator.
   bool generate_frame_at_start =
       data_->sequence()->instruction_blocks().front()->must_construct_frame();
@@ -1389,15 +1684,25 @@
     Run<JumpThreadingPhase>(generate_frame_at_start);
   }
 
+  data->EndPhaseKind();
+
+  return true;
+}
+
+Handle<Code> PipelineImpl::GenerateCode(Linkage* linkage) {
+  PipelineData* data = this->data_;
+
+  data->BeginPhaseKind("code generation");
+
   // Generate final machine code.
-  Run<GenerateCodePhase>(&linkage);
+  Run<GenerateCodePhase>(linkage);
 
   Handle<Code> code = data->code();
-  if (profiler_data != nullptr) {
+  if (data->profiler_data()) {
 #if ENABLE_DISASSEMBLER
     std::ostringstream os;
     code->Disassemble(nullptr, os);
-    profiler_data->SetCode(&os);
+    data->profiler_data()->SetCode(&os);
 #endif
   }
 
@@ -1405,25 +1710,21 @@
   v8::internal::CodeGenerator::PrintCode(code, info());
 
   if (FLAG_trace_turbo) {
-    FILE* json_file = OpenVisualizerLogFile(info(), nullptr, "json", "a+");
-    if (json_file != nullptr) {
-      OFStream json_of(json_file);
-      json_of
-          << "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\"";
+    TurboJsonFile json_of(info(), std::ios_base::app);
+    json_of << "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\"";
 #if ENABLE_DISASSEMBLER
-      std::stringstream disassembly_stream;
-      code->Disassemble(nullptr, disassembly_stream);
-      std::string disassembly_string(disassembly_stream.str());
-      for (const auto& c : disassembly_string) {
-        json_of << AsEscapedUC16ForJSON(c);
-      }
-#endif  // ENABLE_DISASSEMBLER
-      json_of << "\"}\n],\n";
-      json_of << "\"nodePositions\":";
-      json_of << source_position_output.str();
-      json_of << "}";
-      fclose(json_file);
+    std::stringstream disassembly_stream;
+    code->Disassemble(nullptr, disassembly_stream);
+    std::string disassembly_string(disassembly_stream.str());
+    for (const auto& c : disassembly_string) {
+      json_of << AsEscapedUC16ForJSON(c);
     }
+#endif  // ENABLE_DISASSEMBLER
+    json_of << "\"}\n],\n";
+    json_of << "\"nodePositions\":";
+    json_of << data->source_position_output();
+    json_of << "}";
+
     OFStream os(stdout);
     os << "---------------------------------------------------\n"
        << "Finished compiling method " << info()->GetDebugName().get()
@@ -1433,12 +1734,21 @@
   return code;
 }
 
+Handle<Code> PipelineImpl::ScheduleAndGenerateCode(
+    CallDescriptor* call_descriptor) {
+  Linkage linkage(call_descriptor);
 
-void Pipeline::AllocateRegisters(const RegisterConfiguration* config,
-                                 CallDescriptor* descriptor,
-                                 bool run_verifier) {
+  // Schedule the graph, perform instruction selection and register allocation.
+  if (!ScheduleAndSelectInstructions(&linkage)) return Handle<Code>();
+
+  // Generate the final machine code.
+  return GenerateCode(&linkage);
+}
+
+void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config,
+                                     CallDescriptor* descriptor,
+                                     bool run_verifier) {
   PipelineData* data = this->data_;
-
   // Don't track usage for this zone in compiler stats.
   base::SmartPointer<Zone> verifier_zone;
   RegisterAllocatorVerifier* verifier = nullptr;
@@ -1448,14 +1758,13 @@
         verifier_zone.get(), config, data->sequence());
   }
 
-  base::SmartArrayPointer<char> debug_name;
 #ifdef DEBUG
-  debug_name = info()->GetDebugName();
   data_->sequence()->ValidateEdgeSplitForm();
+  data_->sequence()->ValidateDeferredBlockEntryPaths();
   data_->sequence()->ValidateDeferredBlockExitPaths();
 #endif
 
-  data->InitializeRegisterAllocationData(config, descriptor, debug_name.get());
+  data->InitializeRegisterAllocationData(config, descriptor);
   if (info()->is_osr()) {
     OsrHelper osr_helper(info());
     osr_helper.SetupFrame(data->frame());
@@ -1465,10 +1774,10 @@
   Run<ResolvePhisPhase>();
   Run<BuildLiveRangesPhase>();
   if (FLAG_trace_turbo_graph) {
+    AllowHandleDereference allow_deref;
     OFStream os(stdout);
-    PrintableInstructionSequence printable = {config, data->sequence()};
     os << "----- Instruction sequence before register allocation -----\n"
-       << printable;
+       << PrintableInstructionSequence({config, data->sequence()});
   }
   if (verifier != nullptr) {
     CHECK(!data->register_allocation_data()->ExistsUseWithoutDefinition());
@@ -1480,13 +1789,8 @@
     Run<SplinterLiveRangesPhase>();
   }
 
-  if (FLAG_turbo_greedy_regalloc) {
-    Run<AllocateGeneralRegistersPhase<GreedyAllocator>>();
-    Run<AllocateDoubleRegistersPhase<GreedyAllocator>>();
-  } else {
-    Run<AllocateGeneralRegistersPhase<LinearScanAllocator>>();
-    Run<AllocateDoubleRegistersPhase<LinearScanAllocator>>();
-  }
+  Run<AllocateGeneralRegistersPhase<LinearScanAllocator>>();
+  Run<AllocateFPRegistersPhase<LinearScanAllocator>>();
 
   if (FLAG_turbo_preprocess_ranges) {
     Run<MergeSplintersPhase>();
@@ -1505,10 +1809,10 @@
   Run<LocateSpillSlotsPhase>();
 
   if (FLAG_trace_turbo_graph) {
+    AllowHandleDereference allow_deref;
     OFStream os(stdout);
-    PrintableInstructionSequence printable = {config, data->sequence()};
     os << "----- Instruction sequence after register allocation -----\n"
-       << printable;
+       << PrintableInstructionSequence({config, data->sequence()});
   }
 
   if (verifier != nullptr) {
@@ -1525,7 +1829,9 @@
   data->DeleteRegisterAllocationZone();
 }
 
-Isolate* Pipeline::isolate() const { return info()->isolate(); }
+CompilationInfo* PipelineImpl::info() const { return data_->info(); }
+
+Isolate* PipelineImpl::isolate() const { return info()->isolate(); }
 
 }  // namespace compiler
 }  // namespace internal
diff --git a/src/compiler/pipeline.h b/src/compiler/pipeline.h
index edb8191..64befbf 100644
--- a/src/compiler/pipeline.h
+++ b/src/compiler/pipeline.h
@@ -13,6 +13,7 @@
 namespace internal {
 
 class CompilationInfo;
+class CompilationJob;
 class RegisterConfiguration;
 
 namespace compiler {
@@ -20,16 +21,18 @@
 class CallDescriptor;
 class Graph;
 class InstructionSequence;
-class Linkage;
-class PipelineData;
 class Schedule;
+class SourcePositionTable;
 
-class Pipeline {
+class Pipeline : public AllStatic {
  public:
-  explicit Pipeline(CompilationInfo* info) : info_(info) {}
+  // Returns a new compilation job for the given function.
+  static CompilationJob* NewCompilationJob(Handle<JSFunction> function);
 
-  // Run the entire pipeline and generate a handle to a code object.
-  Handle<Code> GenerateCode();
+  // Returns a new compilation job for the WebAssembly compilation info.
+  static CompilationJob* NewWasmCompilationJob(
+      CompilationInfo* info, Graph* graph, CallDescriptor* descriptor,
+      SourcePositionTable* source_positions);
 
   // Run the pipeline on a machine graph and generate code. The {schedule} must
   // be valid, hence the given {graph} does not need to be schedulable.
@@ -39,6 +42,10 @@
                                               Code::Flags flags,
                                               const char* debug_name);
 
+  // Run the entire pipeline and generate a handle to a code object suitable for
+  // testing.
+  static Handle<Code> GenerateCodeForTesting(CompilationInfo* info);
+
   // Run the pipeline on a machine graph and generate code. If {schedule} is
   // {nullptr}, then compute a new schedule for code generation.
   static Handle<Code> GenerateCodeForTesting(CompilationInfo* info,
@@ -58,27 +65,7 @@
                                              Schedule* schedule = nullptr);
 
  private:
-  // Helpers for executing pipeline phases.
-  template <typename Phase>
-  void Run();
-  template <typename Phase, typename Arg0>
-  void Run(Arg0 arg_0);
-  template <typename Phase, typename Arg0, typename Arg1>
-  void Run(Arg0 arg_0, Arg1 arg_1);
-
-  void BeginPhaseKind(const char* phase_kind);
-  void RunPrintAndVerify(const char* phase, bool untyped = false);
-  Handle<Code> ScheduleAndGenerateCode(CallDescriptor* call_descriptor);
-  void AllocateRegisters(const RegisterConfiguration* config,
-                         CallDescriptor* descriptor, bool run_verifier);
-
-  CompilationInfo* info() const { return info_; }
-  Isolate* isolate() const;
-
-  CompilationInfo* const info_;
-  PipelineData* data_;
-
-  DISALLOW_COPY_AND_ASSIGN(Pipeline);
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Pipeline);
 };
 
 }  // namespace compiler
diff --git a/src/compiler/ppc/OWNERS b/src/compiler/ppc/OWNERS
index eb007cb..752e8e3 100644
--- a/src/compiler/ppc/OWNERS
+++ b/src/compiler/ppc/OWNERS
@@ -3,3 +3,4 @@
 joransiu@ca.ibm.com
 mbrandy@us.ibm.com
 michael_dawson@ca.ibm.com
+bjaideep@ca.ibm.com
diff --git a/src/compiler/ppc/code-generator-ppc.cc b/src/compiler/ppc/code-generator-ppc.cc
index 6f1e588..4909414 100644
--- a/src/compiler/ppc/code-generator-ppc.cc
+++ b/src/compiler/ppc/code-generator-ppc.cc
@@ -103,7 +103,7 @@
 
   MemOperand ToMemOperand(InstructionOperand* op) const {
     DCHECK_NOT_NULL(op);
-    DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
+    DCHECK(op->IsStackSlot() || op->IsFPStackSlot());
     return SlotToMemOperand(AllocatedOperand::cast(op)->index());
   }
 
@@ -175,7 +175,8 @@
         value_(value),
         scratch0_(scratch0),
         scratch1_(scratch1),
-        mode_(mode) {}
+        mode_(mode),
+        must_save_lr_(!gen->frame_access_state()->has_frame()) {}
 
   OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t offset,
                        Register value, Register scratch0, Register scratch1,
@@ -215,7 +216,12 @@
       DCHECK_EQ(0, offset_immediate_);
       __ add(scratch1_, object_, offset_);
     }
-    __ CallStub(&stub);
+    if (must_save_lr_ && FLAG_enable_embedded_constant_pool) {
+      ConstantPoolUnavailableScope constant_pool_unavailable(masm());
+      __ CallStub(&stub);
+    } else {
+      __ CallStub(&stub);
+    }
     if (must_save_lr_) {
       // We need to save and restore lr if the frame was elided.
       __ Pop(scratch1_);
@@ -259,15 +265,10 @@
 #if V8_TARGET_ARCH_PPC64
         case kPPC_Add:
         case kPPC_Sub:
-          return lt;
 #endif
         case kPPC_AddWithOverflow32:
         case kPPC_SubWithOverflow32:
-#if V8_TARGET_ARCH_PPC64
-          return ne;
-#else
           return lt;
-#endif
         default:
           break;
       }
@@ -277,15 +278,10 @@
 #if V8_TARGET_ARCH_PPC64
         case kPPC_Add:
         case kPPC_Sub:
-          return ge;
 #endif
         case kPPC_AddWithOverflow32:
         case kPPC_SubWithOverflow32:
-#if V8_TARGET_ARCH_PPC64
-          return eq;
-#else
           return ge;
-#endif
         default:
           break;
       }
@@ -378,17 +374,16 @@
 
 
 #if V8_TARGET_ARCH_PPC64
-#define ASSEMBLE_ADD_WITH_OVERFLOW32()           \
-  do {                                           \
-    ASSEMBLE_BINOP(add, addi);                   \
-    __ TestIfInt32(i.OutputRegister(), r0, cr0); \
+#define ASSEMBLE_ADD_WITH_OVERFLOW32()         \
+  do {                                         \
+    ASSEMBLE_ADD_WITH_OVERFLOW();              \
+    __ extsw(kScratchReg, kScratchReg, SetRC); \
   } while (0)
 
-
-#define ASSEMBLE_SUB_WITH_OVERFLOW32()           \
-  do {                                           \
-    ASSEMBLE_BINOP(sub, subi);                   \
-    __ TestIfInt32(i.OutputRegister(), r0, cr0); \
+#define ASSEMBLE_SUB_WITH_OVERFLOW32()         \
+  do {                                         \
+    ASSEMBLE_SUB_WITH_OVERFLOW();              \
+    __ extsw(kScratchReg, kScratchReg, SetRC); \
   } while (0)
 #else
 #define ASSEMBLE_ADD_WITH_OVERFLOW32 ASSEMBLE_ADD_WITH_OVERFLOW
@@ -446,6 +441,34 @@
     DCHECK_EQ(LeaveRC, i.OutputRCBit());                                      \
   } while (0)
 
+#define ASSEMBLE_IEEE754_UNOP(name)                                            \
+  do {                                                                         \
+    /* TODO(bmeurer): We should really get rid of this special instruction, */ \
+    /* and generate a CallAddress instruction instead. */                      \
+    FrameScope scope(masm(), StackFrame::MANUAL);                              \
+    __ PrepareCallCFunction(0, 1, kScratchReg);                                \
+    __ MovToFloatParameter(i.InputDoubleRegister(0));                          \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()),  \
+                     0, 1);                                                    \
+    /* Move the result in the double result register. */                       \
+    __ MovFromFloatResult(i.OutputDoubleRegister());                           \
+    DCHECK_EQ(LeaveRC, i.OutputRCBit());                                       \
+  } while (0)
+
+#define ASSEMBLE_IEEE754_BINOP(name)                                           \
+  do {                                                                         \
+    /* TODO(bmeurer): We should really get rid of this special instruction, */ \
+    /* and generate a CallAddress instruction instead. */                      \
+    FrameScope scope(masm(), StackFrame::MANUAL);                              \
+    __ PrepareCallCFunction(0, 2, kScratchReg);                                \
+    __ MovToFloatParameters(i.InputDoubleRegister(0),                          \
+                           i.InputDoubleRegister(1));                          \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()),  \
+                     0, 2);                                                    \
+    /* Move the result in the double result register. */                       \
+    __ MovFromFloatResult(i.OutputDoubleRegister());                           \
+    DCHECK_EQ(LeaveRC, i.OutputRCBit());                                       \
+  } while (0)
 
 #define ASSEMBLE_FLOAT_MAX(scratch_reg)                                       \
   do {                                                                        \
@@ -536,8 +559,13 @@
     DCHECK_EQ(LeaveRC, i.OutputRCBit());                 \
   } while (0)
 
-
+#if V8_TARGET_ARCH_PPC64
 // TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits.
+#define CleanUInt32(x) __ ClearLeftImm(x, x, Operand(32))
+#else
+#define CleanUInt32(x)
+#endif
+
 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr, asm_instrx, width)  \
   do {                                                             \
     DoubleRegister result = i.OutputDoubleRegister();              \
@@ -546,7 +574,6 @@
     MemOperand operand = i.MemoryOperand(&mode, index);            \
     DCHECK_EQ(kMode_MRR, mode);                                    \
     Register offset = operand.rb();                                \
-    __ extsw(offset, offset);                                      \
     if (HasRegisterInput(instr, 2)) {                              \
       __ cmplw(offset, i.InputRegister(2));                        \
     } else {                                                       \
@@ -557,14 +584,13 @@
     if (mode == kMode_MRI) {                                       \
       __ asm_instr(result, operand);                               \
     } else {                                                       \
+      CleanUInt32(offset);                                         \
       __ asm_instrx(result, operand);                              \
     }                                                              \
     __ bind(ool->exit());                                          \
     DCHECK_EQ(LeaveRC, i.OutputRCBit());                           \
   } while (0)
 
-
-// TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits.
 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr, asm_instrx) \
   do {                                                       \
     Register result = i.OutputRegister();                    \
@@ -573,7 +599,6 @@
     MemOperand operand = i.MemoryOperand(&mode, index);      \
     DCHECK_EQ(kMode_MRR, mode);                              \
     Register offset = operand.rb();                          \
-    __ extsw(offset, offset);                                \
     if (HasRegisterInput(instr, 2)) {                        \
       __ cmplw(offset, i.InputRegister(2));                  \
     } else {                                                 \
@@ -584,14 +609,13 @@
     if (mode == kMode_MRI) {                                 \
       __ asm_instr(result, operand);                         \
     } else {                                                 \
+      CleanUInt32(offset);                                   \
       __ asm_instrx(result, operand);                        \
     }                                                        \
     __ bind(ool->exit());                                    \
     DCHECK_EQ(LeaveRC, i.OutputRCBit());                     \
   } while (0)
 
-
-// TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits.
 #define ASSEMBLE_CHECKED_STORE_FLOAT32()                \
   do {                                                  \
     Label done;                                         \
@@ -600,7 +624,6 @@
     MemOperand operand = i.MemoryOperand(&mode, index); \
     DCHECK_EQ(kMode_MRR, mode);                         \
     Register offset = operand.rb();                     \
-    __ extsw(offset, offset);                           \
     if (HasRegisterInput(instr, 2)) {                   \
       __ cmplw(offset, i.InputRegister(2));             \
     } else {                                            \
@@ -612,14 +635,13 @@
     if (mode == kMode_MRI) {                            \
       __ stfs(kScratchDoubleReg, operand);              \
     } else {                                            \
+      CleanUInt32(offset);                              \
       __ stfsx(kScratchDoubleReg, operand);             \
     }                                                   \
     __ bind(&done);                                     \
     DCHECK_EQ(LeaveRC, i.OutputRCBit());                \
   } while (0)
 
-
-// TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits.
 #define ASSEMBLE_CHECKED_STORE_DOUBLE()                 \
   do {                                                  \
     Label done;                                         \
@@ -628,7 +650,6 @@
     MemOperand operand = i.MemoryOperand(&mode, index); \
     DCHECK_EQ(kMode_MRR, mode);                         \
     Register offset = operand.rb();                     \
-    __ extsw(offset, offset);                           \
     if (HasRegisterInput(instr, 2)) {                   \
       __ cmplw(offset, i.InputRegister(2));             \
     } else {                                            \
@@ -639,14 +660,13 @@
     if (mode == kMode_MRI) {                            \
       __ stfd(value, operand);                          \
     } else {                                            \
+      CleanUInt32(offset);                              \
       __ stfdx(value, operand);                         \
     }                                                   \
     __ bind(&done);                                     \
     DCHECK_EQ(LeaveRC, i.OutputRCBit());                \
   } while (0)
 
-
-// TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits.
 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr, asm_instrx) \
   do {                                                        \
     Label done;                                               \
@@ -655,7 +675,6 @@
     MemOperand operand = i.MemoryOperand(&mode, index);       \
     DCHECK_EQ(kMode_MRR, mode);                               \
     Register offset = operand.rb();                           \
-    __ extsw(offset, offset);                                 \
     if (HasRegisterInput(instr, 2)) {                         \
       __ cmplw(offset, i.InputRegister(2));                   \
     } else {                                                  \
@@ -666,18 +685,49 @@
     if (mode == kMode_MRI) {                                  \
       __ asm_instr(value, operand);                           \
     } else {                                                  \
+      CleanUInt32(offset);                                    \
       __ asm_instrx(value, operand);                          \
     }                                                         \
     __ bind(&done);                                           \
     DCHECK_EQ(LeaveRC, i.OutputRCBit());                      \
   } while (0)
 
+#define ASSEMBLE_ATOMIC_LOAD_INTEGER(asm_instr, asm_instrx)   \
+  do {                                                        \
+    Label done;                                               \
+    Register result = i.OutputRegister();                     \
+    AddressingMode mode = kMode_None;                         \
+    MemOperand operand = i.MemoryOperand(&mode);              \
+    __ sync();                                                \
+    if (mode == kMode_MRI) {                                  \
+    __ asm_instr(result, operand);                            \
+    } else {                                                  \
+    __ asm_instrx(result, operand);                           \
+    }                                                         \
+    __ bind(&done);                                           \
+    __ cmp(result, result);                                   \
+    __ bne(&done);                                            \
+    __ isync();                                               \
+  } while (0)
+#define ASSEMBLE_ATOMIC_STORE_INTEGER(asm_instr, asm_instrx)  \
+  do {                                                        \
+    size_t index = 0;                                         \
+    AddressingMode mode = kMode_None;                         \
+    MemOperand operand = i.MemoryOperand(&mode, &index);      \
+    Register value = i.InputRegister(index);                  \
+    __ sync();                                                \
+    if (mode == kMode_MRI) {                                  \
+      __ asm_instr(value, operand);                           \
+    } else {                                                  \
+      __ asm_instrx(value, operand);                          \
+    }                                                         \
+    DCHECK_EQ(LeaveRC, i.OutputRCBit());                      \
+  } while (0)
+
 void CodeGenerator::AssembleDeconstructFrame() {
   __ LeaveFrame(StackFrame::MANUAL);
 }
 
-void CodeGenerator::AssembleSetupStackPointer() {}
-
 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
   int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
   if (sp_slot_delta > 0) {
@@ -725,7 +775,8 @@
 }
 
 // Assembles an instruction after register allocation, producing machine code.
-void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
+CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
+    Instruction* instr) {
   PPCOperandConverter i(this, instr);
   ArchOpcode opcode = ArchOpcodeField::decode(instr->opcode());
 
@@ -771,6 +822,14 @@
       frame_access_state()->ClearSPDelta();
       break;
     }
+    case kArchTailCallAddress: {
+      int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
+      AssembleDeconstructActivationRecord(stack_param_delta);
+      CHECK(!instr->InputAt(0)->IsImmediate());
+      __ Jump(i.InputRegister(0));
+      frame_access_state()->ClearSPDelta();
+      break;
+    }
     case kArchCallJSFunction: {
       v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool(
           masm());
@@ -848,6 +907,9 @@
       AssembleArchTableSwitch(instr);
       DCHECK_EQ(LeaveRC, i.OutputRCBit());
       break;
+    case kArchDebugBreak:
+      __ stop("kArchDebugBreak");
+      break;
     case kArchNop:
     case kArchThrowTerminator:
       // don't emit code for nops.
@@ -858,7 +920,9 @@
           BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
       Deoptimizer::BailoutType bailout_type =
           Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
-      AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      CodeGenResult result =
+          AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      if (result != kSuccess) return result;
       break;
     }
     case kArchRet:
@@ -1198,6 +1262,45 @@
       // and generate a CallAddress instruction instead.
       ASSEMBLE_FLOAT_MODULO();
       break;
+    case kIeee754Float64Atan:
+      ASSEMBLE_IEEE754_UNOP(atan);
+      break;
+    case kIeee754Float64Atan2:
+      ASSEMBLE_IEEE754_BINOP(atan2);
+      break;
+    case kIeee754Float64Tan:
+      ASSEMBLE_IEEE754_UNOP(tan);
+      break;
+    case kIeee754Float64Cbrt:
+      ASSEMBLE_IEEE754_UNOP(cbrt);
+      break;
+    case kIeee754Float64Sin:
+      ASSEMBLE_IEEE754_UNOP(sin);
+      break;
+    case kIeee754Float64Cos:
+      ASSEMBLE_IEEE754_UNOP(cos);
+      break;
+    case kIeee754Float64Exp:
+      ASSEMBLE_IEEE754_UNOP(exp);
+      break;
+    case kIeee754Float64Expm1:
+      ASSEMBLE_IEEE754_UNOP(expm1);
+      break;
+    case kIeee754Float64Atanh:
+      ASSEMBLE_IEEE754_UNOP(atanh);
+      break;
+    case kIeee754Float64Log:
+      ASSEMBLE_IEEE754_UNOP(log);
+      break;
+    case kIeee754Float64Log1p:
+      ASSEMBLE_IEEE754_UNOP(log1p);
+      break;
+    case kIeee754Float64Log2:
+      ASSEMBLE_IEEE754_UNOP(log2);
+      break;
+    case kIeee754Float64Log10:
+      ASSEMBLE_IEEE754_UNOP(log10);
+      break;
     case kPPC_Neg:
       __ neg(i.OutputRegister(), i.InputRegister(0), LeaveOE, i.OutputRCBit());
       break;
@@ -1280,8 +1383,14 @@
       DCHECK_EQ(SetRC, i.OutputRCBit());
       break;
 #endif
+    case kPPC_Float64SilenceNaN: {
+      DoubleRegister value = i.InputDoubleRegister(0);
+      DoubleRegister result = i.OutputDoubleRegister();
+      __ CanonicalizeNaN(result, value);
+      break;
+    }
     case kPPC_Push:
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ stfdu(i.InputDoubleRegister(0), MemOperand(sp, -kDoubleSize));
         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
       } else {
@@ -1292,21 +1401,36 @@
       break;
     case kPPC_PushFrame: {
       int num_slots = i.InputInt32(1);
-      if (instr->InputAt(0)->IsDoubleRegister()) {
-        __ stfdu(i.InputDoubleRegister(0),
-                 MemOperand(sp, -num_slots * kPointerSize));
+      if (instr->InputAt(0)->IsFPRegister()) {
+        LocationOperand* op = LocationOperand::cast(instr->InputAt(0));
+        if (op->representation() == MachineRepresentation::kFloat64) {
+          __ StoreDoubleU(i.InputDoubleRegister(0),
+                        MemOperand(sp, -num_slots * kPointerSize), r0);
+        } else {
+          DCHECK(op->representation() == MachineRepresentation::kFloat32);
+          __ StoreSingleU(i.InputDoubleRegister(0),
+                        MemOperand(sp, -num_slots * kPointerSize), r0);
+        }
       } else {
         __ StorePU(i.InputRegister(0),
-                   MemOperand(sp, -num_slots * kPointerSize));
+                   MemOperand(sp, -num_slots * kPointerSize), r0);
       }
       break;
     }
     case kPPC_StoreToStackSlot: {
       int slot = i.InputInt32(1);
-      if (instr->InputAt(0)->IsDoubleRegister()) {
-        __ stfd(i.InputDoubleRegister(0), MemOperand(sp, slot * kPointerSize));
+      if (instr->InputAt(0)->IsFPRegister()) {
+        LocationOperand* op = LocationOperand::cast(instr->InputAt(0));
+        if (op->representation() == MachineRepresentation::kFloat64) {
+          __ StoreDouble(i.InputDoubleRegister(0),
+                        MemOperand(sp, slot * kPointerSize), r0);
+        } else {
+          DCHECK(op->representation() == MachineRepresentation::kFloat32);
+          __ StoreSingle(i.InputDoubleRegister(0),
+                        MemOperand(sp, slot * kPointerSize), r0);
+        }
       } else {
-        __ StoreP(i.InputRegister(0), MemOperand(sp, slot * kPointerSize));
+        __ StoreP(i.InputRegister(0), MemOperand(sp, slot * kPointerSize), r0);
       }
       break;
     }
@@ -1492,6 +1616,9 @@
     case kPPC_LoadWordS16:
       ASSEMBLE_LOAD_INTEGER(lha, lhax);
       break;
+    case kPPC_LoadWordU32:
+      ASSEMBLE_LOAD_INTEGER(lwz, lwzx);
+      break;
     case kPPC_LoadWordS32:
       ASSEMBLE_LOAD_INTEGER(lwa, lwax);
       break;
@@ -1540,7 +1667,7 @@
       ASSEMBLE_CHECKED_LOAD_INTEGER(lhz, lhzx);
       break;
     case kCheckedLoadWord32:
-      ASSEMBLE_CHECKED_LOAD_INTEGER(lwa, lwax);
+      ASSEMBLE_CHECKED_LOAD_INTEGER(lwz, lwzx);
       break;
     case kCheckedLoadWord64:
 #if V8_TARGET_ARCH_PPC64
@@ -1577,10 +1704,38 @@
     case kCheckedStoreFloat64:
       ASSEMBLE_CHECKED_STORE_DOUBLE();
       break;
+
+    case kAtomicLoadInt8:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(lbz, lbzx);
+      __ extsb(i.OutputRegister(), i.OutputRegister());
+      break;
+    case kAtomicLoadUint8:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(lbz, lbzx);
+      break;
+    case kAtomicLoadInt16:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(lha, lhax);
+      break;
+    case kAtomicLoadUint16:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(lhz, lhzx);
+      break;
+    case kAtomicLoadWord32:
+      ASSEMBLE_ATOMIC_LOAD_INTEGER(lwz, lwzx);
+      break;
+
+    case kAtomicStoreWord8:
+      ASSEMBLE_ATOMIC_STORE_INTEGER(stb, stbx);
+      break;
+    case kAtomicStoreWord16:
+      ASSEMBLE_ATOMIC_STORE_INTEGER(sth, sthx);
+      break;
+    case kAtomicStoreWord32:
+      ASSEMBLE_ATOMIC_STORE_INTEGER(stw, stwx);
+      break;
     default:
       UNREACHABLE();
       break;
   }
+  return kSuccess;
 }  // NOLINT(readability/fn_size)
 
 
@@ -1676,7 +1831,7 @@
   PPCOperandConverter i(this, instr);
   Register input = i.InputRegister(0);
   for (size_t index = 2; index < instr->InputCount(); index += 2) {
-    __ Cmpi(input, Operand(i.InputInt32(index + 0)), r0);
+    __ Cmpwi(input, Operand(i.InputInt32(index + 0)), r0);
     __ beq(GetLabel(i.InputRpo(index + 1)));
   }
   AssembleArchJump(i.InputRpo(1));
@@ -1700,19 +1855,45 @@
   __ Jump(kScratchReg);
 }
 
-
-void CodeGenerator::AssembleDeoptimizerCall(
+CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
     int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
   Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
       isolate(), deoptimization_id, bailout_type);
   // TODO(turbofan): We should be able to generate better code by sharing the
   // actual final call site and just bl'ing to it here, similar to what we do
   // in the lithium backend.
+  if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
   __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
+  return kSuccess;
 }
 
+void CodeGenerator::FinishFrame(Frame* frame) {
+  CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
+  const RegList double_saves = descriptor->CalleeSavedFPRegisters();
 
-void CodeGenerator::AssemblePrologue() {
+  // Save callee-saved Double registers.
+  if (double_saves != 0) {
+    frame->AlignSavedCalleeRegisterSlots();
+    DCHECK(kNumCalleeSavedDoubles ==
+           base::bits::CountPopulation32(double_saves));
+    frame->AllocateSavedCalleeRegisterSlots(kNumCalleeSavedDoubles *
+                                             (kDoubleSize / kPointerSize));
+  }
+  // Save callee-saved registers.
+  const RegList saves =
+      FLAG_enable_embedded_constant_pool
+          ? descriptor->CalleeSavedRegisters() & ~kConstantPoolRegister.bit()
+          : descriptor->CalleeSavedRegisters();
+  if (saves != 0) {
+    // register save area does not include the fp or constant pool pointer.
+    const int num_saves =
+        kNumCalleeSaved - 1 - (FLAG_enable_embedded_constant_pool ? 1 : 0);
+    DCHECK(num_saves == base::bits::CountPopulation32(saves));
+    frame->AllocateSavedCalleeRegisterSlots(num_saves);
+  }
+}
+
+void CodeGenerator::AssembleConstructFrame() {
   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
   if (frame_access_state()->has_frame()) {
     if (descriptor->IsCFunctionCall()) {
@@ -1736,7 +1917,7 @@
     }
   }
 
-  int stack_shrink_slots = frame()->GetSpillSlotCount();
+  int shrink_slots = frame()->GetSpillSlotCount();
   if (info()->is_osr()) {
     // TurboFan OSR-compiled functions cannot be entered directly.
     __ Abort(kShouldNotDirectlyEnterOsrFunction);
@@ -1747,15 +1928,12 @@
     // remaining stack slots.
     if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
     osr_pc_offset_ = __ pc_offset();
-    stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
+    shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
   }
 
   const RegList double_saves = descriptor->CalleeSavedFPRegisters();
-  if (double_saves != 0) {
-    stack_shrink_slots += frame()->AlignSavedCalleeRegisterSlots();
-  }
-  if (stack_shrink_slots > 0) {
-    __ Add(sp, sp, -stack_shrink_slots * kPointerSize, r0);
+  if (shrink_slots > 0) {
+    __ Add(sp, sp, -shrink_slots * kPointerSize, r0);
   }
 
   // Save callee-saved Double registers.
@@ -1763,8 +1941,6 @@
     __ MultiPushDoubles(double_saves);
     DCHECK(kNumCalleeSavedDoubles ==
            base::bits::CountPopulation32(double_saves));
-    frame()->AllocateSavedCalleeRegisterSlots(kNumCalleeSavedDoubles *
-                                              (kDoubleSize / kPointerSize));
   }
 
   // Save callee-saved registers.
@@ -1775,10 +1951,6 @@
   if (saves != 0) {
     __ MultiPush(saves);
     // register save area does not include the fp or constant pool pointer.
-    const int num_saves =
-        kNumCalleeSaved - 1 - (FLAG_enable_embedded_constant_pool ? 1 : 0);
-    DCHECK(num_saves == base::bits::CountPopulation32(saves));
-    frame()->AllocateSavedCalleeRegisterSlots(num_saves);
   }
 }
 
@@ -1848,10 +2020,30 @@
           destination->IsRegister() ? g.ToRegister(destination) : kScratchReg;
       switch (src.type()) {
         case Constant::kInt32:
-          __ mov(dst, Operand(src.ToInt32()));
+#if V8_TARGET_ARCH_PPC64
+          if (src.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) {
+#else
+          if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
+              src.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE ||
+              src.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) {
+#endif
+            __ mov(dst, Operand(src.ToInt32(), src.rmode()));
+          } else {
+            __ mov(dst, Operand(src.ToInt32()));
+          }
           break;
         case Constant::kInt64:
-          __ mov(dst, Operand(src.ToInt64()));
+#if V8_TARGET_ARCH_PPC64
+          if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
+              src.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE) {
+            __ mov(dst, Operand(src.ToInt64(), src.rmode()));
+          } else {
+            DCHECK(src.rmode() != RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
+#endif
+            __ mov(dst, Operand(src.ToInt64()));
+#if V8_TARGET_ARCH_PPC64
+          }
+#endif
           break;
         case Constant::kFloat32:
           __ Move(dst,
@@ -1885,34 +2077,50 @@
         __ StoreP(dst, g.ToMemOperand(destination), r0);
       }
     } else {
-      DoubleRegister dst = destination->IsDoubleRegister()
+      DoubleRegister dst = destination->IsFPRegister()
                                ? g.ToDoubleRegister(destination)
                                : kScratchDoubleReg;
       double value = (src.type() == Constant::kFloat32) ? src.ToFloat32()
                                                         : src.ToFloat64();
       __ LoadDoubleLiteral(dst, value, kScratchReg);
-      if (destination->IsDoubleStackSlot()) {
+      if (destination->IsFPStackSlot()) {
         __ StoreDouble(dst, g.ToMemOperand(destination), r0);
       }
     }
-  } else if (source->IsDoubleRegister()) {
+  } else if (source->IsFPRegister()) {
     DoubleRegister src = g.ToDoubleRegister(source);
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       DoubleRegister dst = g.ToDoubleRegister(destination);
       __ Move(dst, src);
     } else {
-      DCHECK(destination->IsDoubleStackSlot());
-      __ StoreDouble(src, g.ToMemOperand(destination), r0);
+      DCHECK(destination->IsFPStackSlot());
+      LocationOperand* op = LocationOperand::cast(source);
+      if (op->representation() == MachineRepresentation::kFloat64) {
+        __ StoreDouble(src, g.ToMemOperand(destination), r0);
+      } else {
+        __ StoreSingle(src, g.ToMemOperand(destination), r0);
+      }
     }
-  } else if (source->IsDoubleStackSlot()) {
-    DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
+  } else if (source->IsFPStackSlot()) {
+    DCHECK(destination->IsFPRegister() || destination->IsFPStackSlot());
     MemOperand src = g.ToMemOperand(source);
-    if (destination->IsDoubleRegister()) {
-      __ LoadDouble(g.ToDoubleRegister(destination), src, r0);
+    if (destination->IsFPRegister()) {
+      LocationOperand* op = LocationOperand::cast(source);
+      if (op->representation() == MachineRepresentation::kFloat64) {
+        __ LoadDouble(g.ToDoubleRegister(destination), src, r0);
+      } else {
+        __ LoadSingle(g.ToDoubleRegister(destination), src, r0);
+      }
     } else {
+      LocationOperand* op = LocationOperand::cast(source);
       DoubleRegister temp = kScratchDoubleReg;
-      __ LoadDouble(temp, src, r0);
-      __ StoreDouble(temp, g.ToMemOperand(destination), r0);
+      if (op->representation() == MachineRepresentation::kFloat64) {
+        __ LoadDouble(temp, src, r0);
+        __ StoreDouble(temp, g.ToMemOperand(destination), r0);
+      } else {
+        __ LoadSingle(temp, src, r0);
+        __ StoreSingle(temp, g.ToMemOperand(destination), r0);
+      }
     }
   } else {
     UNREACHABLE();
@@ -1942,7 +2150,7 @@
       __ StoreP(temp, dst);
     }
 #if V8_TARGET_ARCH_PPC64
-  } else if (source->IsStackSlot() || source->IsDoubleStackSlot()) {
+  } else if (source->IsStackSlot() || source->IsFPStackSlot()) {
 #else
   } else if (source->IsStackSlot()) {
     DCHECK(destination->IsStackSlot());
@@ -1955,24 +2163,24 @@
     __ LoadP(temp_1, dst);
     __ StoreP(temp_0, dst);
     __ StoreP(temp_1, src);
-  } else if (source->IsDoubleRegister()) {
+  } else if (source->IsFPRegister()) {
     DoubleRegister temp = kScratchDoubleReg;
     DoubleRegister src = g.ToDoubleRegister(source);
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       DoubleRegister dst = g.ToDoubleRegister(destination);
       __ fmr(temp, src);
       __ fmr(src, dst);
       __ fmr(dst, temp);
     } else {
-      DCHECK(destination->IsDoubleStackSlot());
+      DCHECK(destination->IsFPStackSlot());
       MemOperand dst = g.ToMemOperand(destination);
       __ fmr(temp, src);
       __ lfd(src, dst);
       __ stfd(temp, dst);
     }
 #if !V8_TARGET_ARCH_PPC64
-  } else if (source->IsDoubleStackSlot()) {
-    DCHECK(destination->IsDoubleStackSlot());
+  } else if (source->IsFPStackSlot()) {
+    DCHECK(destination->IsFPStackSlot());
     DoubleRegister temp_0 = kScratchDoubleReg;
     DoubleRegister temp_1 = d0;
     MemOperand src = g.ToMemOperand(source);
@@ -1996,11 +2204,6 @@
 }
 
 
-void CodeGenerator::AddNopForSmiCodeInlining() {
-  // We do not insert nops for inlined Smi code.
-}
-
-
 void CodeGenerator::EnsureSpaceForLazyDeopt() {
   if (!info()->ShouldEnsureSpaceForLazyDeopt()) {
     return;
diff --git a/src/compiler/ppc/instruction-codes-ppc.h b/src/compiler/ppc/instruction-codes-ppc.h
index 66c2e99..d697da3 100644
--- a/src/compiler/ppc/instruction-codes-ppc.h
+++ b/src/compiler/ppc/instruction-codes-ppc.h
@@ -93,6 +93,7 @@
   V(PPC_Uint32ToFloat32)           \
   V(PPC_Uint32ToDouble)            \
   V(PPC_Float32ToDouble)           \
+  V(PPC_Float64SilenceNaN)         \
   V(PPC_DoubleToInt32)             \
   V(PPC_DoubleToUint32)            \
   V(PPC_DoubleToInt64)             \
@@ -112,6 +113,7 @@
   V(PPC_LoadWordS16)               \
   V(PPC_LoadWordU16)               \
   V(PPC_LoadWordS32)               \
+  V(PPC_LoadWordU32)               \
   V(PPC_LoadWord64)                \
   V(PPC_LoadFloat32)               \
   V(PPC_LoadDouble)                \
diff --git a/src/compiler/ppc/instruction-scheduler-ppc.cc b/src/compiler/ppc/instruction-scheduler-ppc.cc
index e7d7719..f41900d 100644
--- a/src/compiler/ppc/instruction-scheduler-ppc.cc
+++ b/src/compiler/ppc/instruction-scheduler-ppc.cc
@@ -92,6 +92,7 @@
     case kPPC_Uint32ToFloat32:
     case kPPC_Uint32ToDouble:
     case kPPC_Float32ToDouble:
+    case kPPC_Float64SilenceNaN:
     case kPPC_DoubleToInt32:
     case kPPC_DoubleToUint32:
     case kPPC_DoubleToInt64:
@@ -113,6 +114,7 @@
     case kPPC_LoadWordS16:
     case kPPC_LoadWordU16:
     case kPPC_LoadWordS32:
+    case kPPC_LoadWordU32:
     case kPPC_LoadWord64:
     case kPPC_LoadFloat32:
     case kPPC_LoadDouble:
diff --git a/src/compiler/ppc/instruction-selector-ppc.cc b/src/compiler/ppc/instruction-selector-ppc.cc
index 5abb5f1..b724001 100644
--- a/src/compiler/ppc/instruction-selector-ppc.cc
+++ b/src/compiler/ppc/instruction-selector-ppc.cc
@@ -190,11 +190,7 @@
     case MachineRepresentation::kTagged:  // Fall through.
 #endif
     case MachineRepresentation::kWord32:
-      opcode = kPPC_LoadWordS32;
-#if V8_TARGET_ARCH_PPC64
-      // TODO(mbrandy): this applies to signed loads only (lwa)
-      mode = kInt16Imm_4ByteAligned;
-#endif
+      opcode = kPPC_LoadWordU32;
       break;
 #if V8_TARGET_ARCH_PPC64
     case MachineRepresentation::kTagged:  // Fall through.
@@ -1137,15 +1133,12 @@
   VisitRR(this, kPPC_DoubleToFloat32, node);
 }
 
+void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
+  VisitRR(this, kArchTruncateDoubleToI, node);
+}
 
-void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
-  switch (TruncationModeOf(node->op())) {
-    case TruncationMode::kJavaScript:
-      return VisitRR(this, kArchTruncateDoubleToI, node);
-    case TruncationMode::kRoundToZero:
-      return VisitRR(this, kPPC_DoubleToInt32, node);
-  }
-  UNREACHABLE();
+void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
+  VisitRR(this, kPPC_DoubleToInt32, node);
 }
 
 
@@ -1233,6 +1226,10 @@
   VisitRRR(this, kPPC_SubDouble | MiscField::encode(1), node);
 }
 
+void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
+  PPCOperandGenerator g(this);
+  VisitRRR(this, kPPC_SubDouble | MiscField::encode(1), node);
+}
 
 void InstructionSelector::VisitFloat64Sub(Node* node) {
   // TODO(mbrandy): detect multiply-subtract
@@ -1259,6 +1256,9 @@
   VisitRRR(this, kPPC_SubDouble, node);
 }
 
+void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
+  VisitRRR(this, kPPC_SubDouble, node);
+}
 
 void InstructionSelector::VisitFloat32Mul(Node* node) {
   VisitRRR(this, kPPC_MulDouble | MiscField::encode(1), node);
@@ -1294,6 +1294,10 @@
 
 void InstructionSelector::VisitFloat64Max(Node* node) { UNREACHABLE(); }
 
+void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
+  VisitRR(this, kPPC_Float64SilenceNaN, node);
+}
+
 
 void InstructionSelector::VisitFloat32Min(Node* node) { UNREACHABLE(); }
 
@@ -1310,11 +1314,24 @@
   VisitRR(this, kPPC_AbsDouble, node);
 }
 
-
 void InstructionSelector::VisitFloat32Sqrt(Node* node) {
   VisitRR(this, kPPC_SqrtDouble | MiscField::encode(1), node);
 }
 
+void InstructionSelector::VisitFloat64Ieee754Unop(Node* node,
+                                                  InstructionCode opcode) {
+  PPCOperandGenerator g(this);
+  Emit(opcode, g.DefineAsFixed(node, d1), g.UseFixed(node->InputAt(0), d1))
+       ->MarkAsCall();
+}
+
+void InstructionSelector::VisitFloat64Ieee754Binop(Node* node,
+                                                  InstructionCode opcode) {
+  PPCOperandGenerator g(this);
+  Emit(opcode, g.DefineAsFixed(node, d1),
+       g.UseFixed(node->InputAt(0), d1),
+       g.UseFixed(node->InputAt(1), d2))->MarkAsCall();
+}
 
 void InstructionSelector::VisitFloat64Sqrt(Node* node) {
   VisitRR(this, kPPC_SqrtDouble, node);
@@ -1365,6 +1382,9 @@
   UNREACHABLE();
 }
 
+void InstructionSelector::VisitFloat32Neg(Node* node) { UNREACHABLE(); }
+
+void InstructionSelector::VisitFloat64Neg(Node* node) { UNREACHABLE(); }
 
 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
   if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
@@ -1921,6 +1941,60 @@
        g.UseRegister(left), g.UseRegister(right));
 }
 
+void InstructionSelector::VisitAtomicLoad(Node* node) {
+  LoadRepresentation load_rep = LoadRepresentationOf(node->op());
+  PPCOperandGenerator g(this);
+  Node* base = node->InputAt(0);
+  Node* index = node->InputAt(1);
+  ArchOpcode opcode = kArchNop;
+  switch (load_rep.representation()) {
+    case MachineRepresentation::kWord8:
+      opcode = load_rep.IsSigned() ? kAtomicLoadInt8 : kAtomicLoadUint8;
+      break;
+    case MachineRepresentation::kWord16:
+      opcode = load_rep.IsSigned() ? kAtomicLoadInt16 : kAtomicLoadUint16;
+      break;
+    case MachineRepresentation::kWord32:
+      opcode = kAtomicLoadWord32;
+      break;
+    default:
+      UNREACHABLE();
+      return;
+  }
+  Emit(opcode | AddressingModeField::encode(kMode_MRR),
+      g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
+}
+
+void InstructionSelector::VisitAtomicStore(Node* node) {
+  MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
+  PPCOperandGenerator g(this);
+  Node* base = node->InputAt(0);
+  Node* index = node->InputAt(1);
+  Node* value = node->InputAt(2);
+  ArchOpcode opcode = kArchNop;
+  switch (rep) {
+    case MachineRepresentation::kWord8:
+      opcode = kAtomicStoreWord8;
+      break;
+    case MachineRepresentation::kWord16:
+      opcode = kAtomicStoreWord16;
+      break;
+    case MachineRepresentation::kWord32:
+      opcode = kAtomicStoreWord32;
+      break;
+    default:
+      UNREACHABLE();
+      return;
+  }
+
+  InstructionOperand inputs[4];
+  size_t input_count = 0;
+  inputs[input_count++] = g.UseUniqueRegister(base);
+  inputs[input_count++] = g.UseUniqueRegister(index);
+  inputs[input_count++] = g.UseUniqueRegister(value);
+  Emit(opcode | AddressingModeField::encode(kMode_MRR),
+      0, nullptr, input_count, inputs);
+}
 
 // static
 MachineOperatorBuilder::Flags
@@ -1937,6 +2011,13 @@
   // We omit kWord32ShiftIsSafe as s[rl]w use 0x3f as a mask rather than 0x1f.
 }
 
+// static
+MachineOperatorBuilder::AlignmentRequirements
+InstructionSelector::AlignmentRequirements() {
+  return MachineOperatorBuilder::AlignmentRequirements::
+      FullUnalignedAccessSupport();
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/src/compiler/raw-machine-assembler.cc b/src/compiler/raw-machine-assembler.cc
index 728d79a..ef23bc4 100644
--- a/src/compiler/raw-machine-assembler.cc
+++ b/src/compiler/raw-machine-assembler.cc
@@ -35,6 +35,12 @@
   graph->SetEnd(graph->NewNode(common_.End(0)));
 }
 
+Node* RawMachineAssembler::RelocatableIntPtrConstant(intptr_t value,
+                                                     RelocInfo::Mode rmode) {
+  return kPointerSize == 8
+             ? RelocatableInt64Constant(value, rmode)
+             : RelocatableInt32Constant(static_cast<int>(value), rmode);
+}
 
 Schedule* RawMachineAssembler::Export() {
   // Compute the correct codegen order.
@@ -44,7 +50,7 @@
     PrintF("--- RAW SCHEDULE -------------------------------------------\n");
     os << *schedule_;
   }
-  schedule_->EnsureSplitEdgeForm();
+  schedule_->EnsureCFGWellFormedness();
   schedule_->PropagateDeferredMark();
   if (FLAG_trace_turbo_scheduler) {
     PrintF("--- EDGE SPLIT AND PROPAGATED DEFERRED SCHEDULE ------------\n");
@@ -109,7 +115,6 @@
 
 void RawMachineAssembler::Return(Node* value) {
   Node* ret = MakeNode(common()->Return(), 1, &value);
-  NodeProperties::MergeControlToEnd(graph(), common(), ret);
   schedule()->AddReturn(CurrentBlock(), ret);
   current_block_ = nullptr;
 }
@@ -118,7 +123,6 @@
 void RawMachineAssembler::Return(Node* v1, Node* v2) {
   Node* values[] = {v1, v2};
   Node* ret = MakeNode(common()->Return(2), 2, values);
-  NodeProperties::MergeControlToEnd(graph(), common(), ret);
   schedule()->AddReturn(CurrentBlock(), ret);
   current_block_ = nullptr;
 }
@@ -127,11 +131,15 @@
 void RawMachineAssembler::Return(Node* v1, Node* v2, Node* v3) {
   Node* values[] = {v1, v2, v3};
   Node* ret = MakeNode(common()->Return(3), 3, values);
-  NodeProperties::MergeControlToEnd(graph(), common(), ret);
   schedule()->AddReturn(CurrentBlock(), ret);
   current_block_ = nullptr;
 }
 
+void RawMachineAssembler::DebugBreak() { AddNode(machine()->DebugBreak()); }
+
+void RawMachineAssembler::Comment(const char* msg) {
+  AddNode(machine()->Comment(msg));
+}
 
 Node* RawMachineAssembler::CallN(CallDescriptor* desc, Node* function,
                                  Node** args) {
@@ -254,7 +262,6 @@
     buffer[index++] = args[i];
   }
   Node* tail_call = MakeNode(common()->TailCall(desc), input_count, buffer);
-  NodeProperties::MergeControlToEnd(graph(), common(), tail_call);
   schedule()->AddTailCall(CurrentBlock(), tail_call);
   current_block_ = nullptr;
   return tail_call;
@@ -276,7 +283,6 @@
   Node* nodes[] = {centry, ref, arity, context};
   Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);
 
-  NodeProperties::MergeControlToEnd(graph(), common(), tail_call);
   schedule()->AddTailCall(CurrentBlock(), tail_call);
   current_block_ = nullptr;
   return tail_call;
@@ -298,7 +304,6 @@
   Node* nodes[] = {centry, arg1, ref, arity, context};
   Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);
 
-  NodeProperties::MergeControlToEnd(graph(), common(), tail_call);
   schedule()->AddTailCall(CurrentBlock(), tail_call);
   current_block_ = nullptr;
   return tail_call;
@@ -322,7 +327,6 @@
   Node* nodes[] = {centry, arg1, arg2, ref, arity, context};
   Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);
 
-  NodeProperties::MergeControlToEnd(graph(), common(), tail_call);
   schedule()->AddTailCall(CurrentBlock(), tail_call);
   current_block_ = nullptr;
   return tail_call;
@@ -345,7 +349,6 @@
   Node* nodes[] = {centry, arg1, arg2, arg3, ref, arity, context};
   Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);
 
-  NodeProperties::MergeControlToEnd(graph(), common(), tail_call);
   schedule()->AddTailCall(CurrentBlock(), tail_call);
   current_block_ = nullptr;
   return tail_call;
@@ -368,7 +371,6 @@
   Node* nodes[] = {centry, arg1, arg2, arg3, arg4, ref, arity, context};
   Node* tail_call = MakeNode(common()->TailCall(desc), arraysize(nodes), nodes);
 
-  NodeProperties::MergeControlToEnd(graph(), common(), tail_call);
   schedule()->AddTailCall(CurrentBlock(), tail_call);
   current_block_ = nullptr;
   return tail_call;
diff --git a/src/compiler/raw-machine-assembler.h b/src/compiler/raw-machine-assembler.h
index f3445ac..387e961 100644
--- a/src/compiler/raw-machine-assembler.h
+++ b/src/compiler/raw-machine-assembler.h
@@ -76,6 +76,7 @@
     return kPointerSize == 8 ? Int64Constant(value)
                              : Int32Constant(static_cast<int>(value));
   }
+  Node* RelocatableIntPtrConstant(intptr_t value, RelocInfo::Mode rmode);
   Node* Int32Constant(int32_t value) {
     return AddNode(common()->Int32Constant(value));
   }
@@ -104,6 +105,12 @@
   Node* ExternalConstant(ExternalReference address) {
     return AddNode(common()->ExternalConstant(address));
   }
+  Node* RelocatableInt32Constant(int32_t value, RelocInfo::Mode rmode) {
+    return AddNode(common()->RelocatableInt32Constant(value, rmode));
+  }
+  Node* RelocatableInt64Constant(int64_t value, RelocInfo::Mode rmode) {
+    return AddNode(common()->RelocatableInt64Constant(value, rmode));
+  }
 
   Node* Projection(int index, Node* a) {
     return AddNode(common()->Projection(index), a);
@@ -126,6 +133,15 @@
                    base, index, value);
   }
 
+  // Atomic memory operations.
+  Node* AtomicLoad(MachineType rep, Node* base, Node* index) {
+    return AddNode(machine()->AtomicLoad(rep), base, index);
+  }
+  Node* AtomicStore(MachineRepresentation rep, Node* base, Node* index,
+                    Node* value) {
+    return AddNode(machine()->AtomicStore(rep), base, index, value);
+  }
+
   // Arithmetic Operations.
   Node* WordAnd(Node* a, Node* b) {
     return AddNode(machine()->WordAnd(), a, b);
@@ -353,6 +369,8 @@
   INTPTR_BINOP(Int, AddWithOverflow);
   INTPTR_BINOP(Int, Sub);
   INTPTR_BINOP(Int, SubWithOverflow);
+  INTPTR_BINOP(Int, Mul);
+  INTPTR_BINOP(Int, Div);
   INTPTR_BINOP(Int, LessThan);
   INTPTR_BINOP(Int, LessThanOrEqual);
   INTPTR_BINOP(Word, Equal);
@@ -381,6 +399,9 @@
   Node* Float32Sub(Node* a, Node* b) {
     return AddNode(machine()->Float32Sub(), a, b);
   }
+  Node* Float32SubPreserveNan(Node* a, Node* b) {
+    return AddNode(machine()->Float32SubPreserveNan(), a, b);
+  }
   Node* Float32Mul(Node* a, Node* b) {
     return AddNode(machine()->Float32Mul(), a, b);
   }
@@ -419,6 +440,9 @@
   Node* Float64Sub(Node* a, Node* b) {
     return AddNode(machine()->Float64Sub(), a, b);
   }
+  Node* Float64SubPreserveNan(Node* a, Node* b) {
+    return AddNode(machine()->Float64SubPreserveNan(), a, b);
+  }
   Node* Float64Mul(Node* a, Node* b) {
     return AddNode(machine()->Float64Mul(), a, b);
   }
@@ -436,7 +460,22 @@
   }
   Node* Float64Abs(Node* a) { return AddNode(machine()->Float64Abs(), a); }
   Node* Float64Neg(Node* a) { return Float64Sub(Float64Constant(-0.0), a); }
+  Node* Float64Atan(Node* a) { return AddNode(machine()->Float64Atan(), a); }
+  Node* Float64Atan2(Node* a, Node* b) {
+    return AddNode(machine()->Float64Atan2(), a, b);
+  }
+  Node* Float64Atanh(Node* a) { return AddNode(machine()->Float64Atanh(), a); }
+  Node* Float64Cbrt(Node* a) { return AddNode(machine()->Float64Cbrt(), a); }
+  Node* Float64Cos(Node* a) { return AddNode(machine()->Float64Cos(), a); }
+  Node* Float64Exp(Node* a) { return AddNode(machine()->Float64Exp(), a); }
+  Node* Float64Expm1(Node* a) { return AddNode(machine()->Float64Expm1(), a); }
+  Node* Float64Log(Node* a) { return AddNode(machine()->Float64Log(), a); }
+  Node* Float64Log1p(Node* a) { return AddNode(machine()->Float64Log1p(), a); }
+  Node* Float64Log10(Node* a) { return AddNode(machine()->Float64Log10(), a); }
+  Node* Float64Log2(Node* a) { return AddNode(machine()->Float64Log2(), a); }
+  Node* Float64Sin(Node* a) { return AddNode(machine()->Float64Sin(), a); }
   Node* Float64Sqrt(Node* a) { return AddNode(machine()->Float64Sqrt(), a); }
+  Node* Float64Tan(Node* a) { return AddNode(machine()->Float64Tan(), a); }
   Node* Float64Equal(Node* a, Node* b) {
     return AddNode(machine()->Float64Equal(), a, b);
   }
@@ -455,6 +494,12 @@
   }
 
   // Conversions.
+  Node* BitcastWordToTagged(Node* a) {
+    return AddNode(machine()->BitcastWordToTagged(), a);
+  }
+  Node* TruncateFloat64ToWord32(Node* a) {
+    return AddNode(machine()->TruncateFloat64ToWord32(), a);
+  }
   Node* ChangeFloat32ToFloat64(Node* a) {
     return AddNode(machine()->ChangeFloat32ToFloat64(), a);
   }
@@ -500,12 +545,12 @@
   Node* TruncateFloat64ToFloat32(Node* a) {
     return AddNode(machine()->TruncateFloat64ToFloat32(), a);
   }
-  Node* TruncateFloat64ToInt32(TruncationMode mode, Node* a) {
-    return AddNode(machine()->TruncateFloat64ToInt32(mode), a);
-  }
   Node* TruncateInt64ToInt32(Node* a) {
     return AddNode(machine()->TruncateInt64ToInt32(), a);
   }
+  Node* RoundFloat64ToInt32(Node* a) {
+    return AddNode(machine()->RoundFloat64ToInt32(), a);
+  }
   Node* RoundInt32ToFloat32(Node* a) {
     return AddNode(machine()->RoundInt32ToFloat32(), a);
   }
@@ -667,6 +712,8 @@
   void Return(Node* v1, Node* v2, Node* v3);
   void Bind(RawMachineLabel* label);
   void Deoptimize(Node* state);
+  void DebugBreak();
+  void Comment(const char* msg);
 
   // Variables.
   Node* Phi(MachineRepresentation rep, Node* n1, Node* n2) {
diff --git a/src/compiler/redundancy-elimination.cc b/src/compiler/redundancy-elimination.cc
new file mode 100644
index 0000000..ae87349
--- /dev/null
+++ b/src/compiler/redundancy-elimination.cc
@@ -0,0 +1,216 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/redundancy-elimination.h"
+
+#include "src/compiler/node-properties.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+RedundancyElimination::RedundancyElimination(Editor* editor, Zone* zone)
+    : AdvancedReducer(editor), node_checks_(zone), zone_(zone) {}
+
+RedundancyElimination::~RedundancyElimination() {}
+
+Reduction RedundancyElimination::Reduce(Node* node) {
+  switch (node->opcode()) {
+    case IrOpcode::kCheckFloat64Hole:
+    case IrOpcode::kCheckTaggedHole:
+    case IrOpcode::kCheckTaggedPointer:
+    case IrOpcode::kCheckTaggedSigned:
+    case IrOpcode::kCheckedFloat64ToInt32:
+    case IrOpcode::kCheckedInt32Add:
+    case IrOpcode::kCheckedInt32Sub:
+    case IrOpcode::kCheckedTaggedToFloat64:
+    case IrOpcode::kCheckedTaggedToInt32:
+    case IrOpcode::kCheckedUint32ToInt32:
+      return ReduceCheckNode(node);
+    case IrOpcode::kEffectPhi:
+      return ReduceEffectPhi(node);
+    case IrOpcode::kDead:
+      break;
+    case IrOpcode::kStart:
+      return ReduceStart(node);
+    default:
+      return ReduceOtherNode(node);
+  }
+  return NoChange();
+}
+
+// static
+RedundancyElimination::EffectPathChecks*
+RedundancyElimination::EffectPathChecks::Copy(Zone* zone,
+                                              EffectPathChecks const* checks) {
+  return new (zone->New(sizeof(EffectPathChecks))) EffectPathChecks(*checks);
+}
+
+// static
+RedundancyElimination::EffectPathChecks const*
+RedundancyElimination::EffectPathChecks::Empty(Zone* zone) {
+  return new (zone->New(sizeof(EffectPathChecks))) EffectPathChecks(nullptr, 0);
+}
+
+void RedundancyElimination::EffectPathChecks::Merge(
+    EffectPathChecks const* that) {
+  // Change the current check list to a longest common tail of this check
+  // list and the other list.
+
+  // First, we throw away the prefix of the longer list, so that
+  // we have lists of the same length.
+  Check* that_head = that->head_;
+  size_t that_size = that->size_;
+  while (that_size > size_) {
+    that_head = that_head->next;
+    that_size--;
+  }
+  while (size_ > that_size) {
+    head_ = head_->next;
+    size_--;
+  }
+
+  // Then we go through both lists in lock-step until we find
+  // the common tail.
+  while (head_ != that_head) {
+    DCHECK_LT(0u, size_);
+    DCHECK_NOT_NULL(head_);
+    size_--;
+    head_ = head_->next;
+    that_head = that_head->next;
+  }
+}
+
+RedundancyElimination::EffectPathChecks const*
+RedundancyElimination::EffectPathChecks::AddCheck(Zone* zone,
+                                                  Node* node) const {
+  Check* head = new (zone->New(sizeof(Check))) Check(node, head_);
+  return new (zone->New(sizeof(EffectPathChecks)))
+      EffectPathChecks(head, size_ + 1);
+}
+
+namespace {
+
+bool IsCompatibleCheck(Node const* a, Node const* b) {
+  if (a->op() != b->op()) return false;
+  for (int i = a->op()->ValueInputCount(); --i >= 0;) {
+    if (a->InputAt(i) != b->InputAt(i)) return false;
+  }
+  return true;
+}
+
+}  // namespace
+
+Node* RedundancyElimination::EffectPathChecks::LookupCheck(Node* node) const {
+  for (Check const* check = head_; check != nullptr; check = check->next) {
+    if (IsCompatibleCheck(check->node, node)) {
+      DCHECK(!check->node->IsDead());
+      return check->node;
+    }
+  }
+  return nullptr;
+}
+
+RedundancyElimination::EffectPathChecks const*
+RedundancyElimination::PathChecksForEffectNodes::Get(Node* node) const {
+  size_t const id = node->id();
+  if (id < info_for_node_.size()) return info_for_node_[id];
+  return nullptr;
+}
+
+void RedundancyElimination::PathChecksForEffectNodes::Set(
+    Node* node, EffectPathChecks const* checks) {
+  size_t const id = node->id();
+  if (id >= info_for_node_.size()) info_for_node_.resize(id + 1, nullptr);
+  info_for_node_[id] = checks;
+}
+
+Reduction RedundancyElimination::ReduceCheckNode(Node* node) {
+  Node* const effect = NodeProperties::GetEffectInput(node);
+  EffectPathChecks const* checks = node_checks_.Get(effect);
+  // If we do not know anything about the predecessor, do not propagate just yet
+  // because we will have to recompute anyway once we compute the predecessor.
+  if (checks == nullptr) return NoChange();
+  // See if we have another check that dominates us.
+  if (Node* check = checks->LookupCheck(node)) {
+    ReplaceWithValue(node, check);
+    return Replace(check);
+  }
+  // Learn from this check.
+  return UpdateChecks(node, checks->AddCheck(zone(), node));
+}
+
+Reduction RedundancyElimination::ReduceEffectPhi(Node* node) {
+  Node* const control = NodeProperties::GetControlInput(node);
+  if (control->opcode() == IrOpcode::kLoop) {
+    // Here we rely on having only reducible loops:
+    // The loop entry edge always dominates the header, so we can just use
+    // the information from the loop entry edge.
+    return TakeChecksFromFirstEffect(node);
+  }
+  DCHECK_EQ(IrOpcode::kMerge, control->opcode());
+
+  // Shortcut for the case when we do not know anything about some input.
+  int const input_count = node->op()->EffectInputCount();
+  for (int i = 0; i < input_count; ++i) {
+    Node* const effect = NodeProperties::GetEffectInput(node, i);
+    if (node_checks_.Get(effect) == nullptr) return NoChange();
+  }
+
+  // Make a copy of the first input's checks and merge with the checks
+  // from other inputs.
+  EffectPathChecks* checks = EffectPathChecks::Copy(
+      zone(), node_checks_.Get(NodeProperties::GetEffectInput(node, 0)));
+  for (int i = 1; i < input_count; ++i) {
+    Node* const input = NodeProperties::GetEffectInput(node, i);
+    checks->Merge(node_checks_.Get(input));
+  }
+  return UpdateChecks(node, checks);
+}
+
+Reduction RedundancyElimination::ReduceStart(Node* node) {
+  return UpdateChecks(node, EffectPathChecks::Empty(zone()));
+}
+
+Reduction RedundancyElimination::ReduceOtherNode(Node* node) {
+  if (node->op()->EffectInputCount() == 1) {
+    if (node->op()->EffectOutputCount() == 1) {
+      return TakeChecksFromFirstEffect(node);
+    } else {
+      // Effect terminators should be handled specially.
+      return NoChange();
+    }
+  }
+  DCHECK_EQ(0, node->op()->EffectInputCount());
+  DCHECK_EQ(0, node->op()->EffectOutputCount());
+  return NoChange();
+}
+
+Reduction RedundancyElimination::TakeChecksFromFirstEffect(Node* node) {
+  DCHECK_EQ(1, node->op()->EffectOutputCount());
+  Node* const effect = NodeProperties::GetEffectInput(node);
+  EffectPathChecks const* checks = node_checks_.Get(effect);
+  // If we do not know anything about the predecessor, do not propagate just yet
+  // because we will have to recompute anyway once we compute the predecessor.
+  if (checks == nullptr) return NoChange();
+  // We just propagate the information from the effect input (ideally,
+  // we would only revisit effect uses if there is change).
+  return UpdateChecks(node, checks);
+}
+
+Reduction RedundancyElimination::UpdateChecks(Node* node,
+                                              EffectPathChecks const* checks) {
+  EffectPathChecks const* original = node_checks_.Get(node);
+  // Only signal that the {node} has Changed, if the information about {checks}
+  // has changed wrt. the {original}.
+  if (checks != original) {
+    node_checks_.Set(node, checks);
+    return Changed(node);
+  }
+  return NoChange();
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/src/compiler/redundancy-elimination.h b/src/compiler/redundancy-elimination.h
new file mode 100644
index 0000000..a4886e4
--- /dev/null
+++ b/src/compiler/redundancy-elimination.h
@@ -0,0 +1,76 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_REDUNDANCY_ELIMINATION_H_
+#define V8_COMPILER_REDUNDANCY_ELIMINATION_H_
+
+#include "src/compiler/graph-reducer.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class RedundancyElimination final : public AdvancedReducer {
+ public:
+  RedundancyElimination(Editor* editor, Zone* zone);
+  ~RedundancyElimination() final;
+
+  Reduction Reduce(Node* node) final;
+
+ private:
+  struct Check {
+    Check(Node* node, Check* next) : node(node), next(next) {}
+    Node* node;
+    Check* next;
+  };
+
+  class EffectPathChecks final {
+   public:
+    static EffectPathChecks* Copy(Zone* zone, EffectPathChecks const* checks);
+    static EffectPathChecks const* Empty(Zone* zone);
+    void Merge(EffectPathChecks const* that);
+
+    EffectPathChecks const* AddCheck(Zone* zone, Node* node) const;
+    Node* LookupCheck(Node* node) const;
+
+   private:
+    EffectPathChecks(Check* head, size_t size) : head_(head), size_(size) {}
+
+    // We keep track of the list length so that we can find the longest
+    // common tail easily.
+    Check* head_;
+    size_t size_;
+  };
+
+  class PathChecksForEffectNodes final {
+   public:
+    explicit PathChecksForEffectNodes(Zone* zone) : info_for_node_(zone) {}
+    EffectPathChecks const* Get(Node* node) const;
+    void Set(Node* node, EffectPathChecks const* checks);
+
+   private:
+    ZoneVector<EffectPathChecks const*> info_for_node_;
+  };
+
+  Reduction ReduceCheckNode(Node* node);
+  Reduction ReduceEffectPhi(Node* node);
+  Reduction ReduceStart(Node* node);
+  Reduction ReduceOtherNode(Node* node);
+
+  Reduction TakeChecksFromFirstEffect(Node* node);
+  Reduction UpdateChecks(Node* node, EffectPathChecks const* checks);
+
+  Zone* zone() const { return zone_; }
+
+  PathChecksForEffectNodes node_checks_;
+  Zone* const zone_;
+
+  DISALLOW_COPY_AND_ASSIGN(RedundancyElimination);
+};
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_COMPILER_REDUNDANCY_ELIMINATION_H_
diff --git a/src/compiler/register-allocator-verifier.cc b/src/compiler/register-allocator-verifier.cc
index f2160f5..2d10de0 100644
--- a/src/compiler/register-allocator-verifier.cc
+++ b/src/compiler/register-allocator-verifier.cc
@@ -44,39 +44,15 @@
 
 }  // namespace
 
-
-void RegisterAllocatorVerifier::VerifyInput(
-    const OperandConstraint& constraint) {
-  CHECK_NE(kSameAsFirst, constraint.type_);
-  if (constraint.type_ != kImmediate && constraint.type_ != kExplicit) {
-    CHECK_NE(InstructionOperand::kInvalidVirtualRegister,
-             constraint.virtual_register_);
-  }
-}
-
-
-void RegisterAllocatorVerifier::VerifyTemp(
-    const OperandConstraint& constraint) {
-  CHECK_NE(kSameAsFirst, constraint.type_);
-  CHECK_NE(kImmediate, constraint.type_);
-  CHECK_NE(kExplicit, constraint.type_);
-  CHECK_NE(kConstant, constraint.type_);
-}
-
-
-void RegisterAllocatorVerifier::VerifyOutput(
-    const OperandConstraint& constraint) {
-  CHECK_NE(kImmediate, constraint.type_);
-  CHECK_NE(kExplicit, constraint.type_);
-  CHECK_NE(InstructionOperand::kInvalidVirtualRegister,
-           constraint.virtual_register_);
-}
-
-
 RegisterAllocatorVerifier::RegisterAllocatorVerifier(
     Zone* zone, const RegisterConfiguration* config,
     const InstructionSequence* sequence)
-    : zone_(zone), config_(config), sequence_(sequence), constraints_(zone) {
+    : zone_(zone),
+      config_(config),
+      sequence_(sequence),
+      constraints_(zone),
+      assessments_(zone),
+      outstanding_assessments_(zone) {
   constraints_.reserve(sequence->instructions().size());
   // TODO(dcarney): model unique constraints.
   // Construct OperandConstraints for all InstructionOperands, eliminating
@@ -111,6 +87,30 @@
   }
 }
 
+void RegisterAllocatorVerifier::VerifyInput(
+    const OperandConstraint& constraint) {
+  CHECK_NE(kSameAsFirst, constraint.type_);
+  if (constraint.type_ != kImmediate && constraint.type_ != kExplicit) {
+    CHECK_NE(InstructionOperand::kInvalidVirtualRegister,
+             constraint.virtual_register_);
+  }
+}
+
+void RegisterAllocatorVerifier::VerifyTemp(
+    const OperandConstraint& constraint) {
+  CHECK_NE(kSameAsFirst, constraint.type_);
+  CHECK_NE(kImmediate, constraint.type_);
+  CHECK_NE(kExplicit, constraint.type_);
+  CHECK_NE(kConstant, constraint.type_);
+}
+
+void RegisterAllocatorVerifier::VerifyOutput(
+    const OperandConstraint& constraint) {
+  CHECK_NE(kImmediate, constraint.type_);
+  CHECK_NE(kExplicit, constraint.type_);
+  CHECK_NE(InstructionOperand::kInvalidVirtualRegister,
+           constraint.virtual_register_);
+}
 
 void RegisterAllocatorVerifier::VerifyAssignment() {
   CHECK(sequence()->instructions().size() == constraints()->size());
@@ -138,7 +138,6 @@
   }
 }
 
-
 void RegisterAllocatorVerifier::BuildConstraint(const InstructionOperand* op,
                                                 OperandConstraint* constraint) {
   constraint->value_ = kMinInt;
@@ -161,14 +160,14 @@
     int vreg = unallocated->virtual_register();
     constraint->virtual_register_ = vreg;
     if (unallocated->basic_policy() == UnallocatedOperand::FIXED_SLOT) {
-      constraint->type_ = sequence()->IsFloat(vreg) ? kDoubleSlot : kSlot;
+      constraint->type_ = sequence()->IsFP(vreg) ? kFPSlot : kSlot;
       constraint->value_ = unallocated->fixed_slot_index();
     } else {
       switch (unallocated->extended_policy()) {
         case UnallocatedOperand::ANY:
         case UnallocatedOperand::NONE:
-          if (sequence()->IsFloat(vreg)) {
-            constraint->type_ = kNoneDouble;
+          if (sequence()->IsFP(vreg)) {
+            constraint->type_ = kNoneFP;
           } else {
             constraint->type_ = kNone;
           }
@@ -182,19 +181,19 @@
           }
           constraint->value_ = unallocated->fixed_register_index();
           break;
-        case UnallocatedOperand::FIXED_DOUBLE_REGISTER:
-          constraint->type_ = kFixedDoubleRegister;
+        case UnallocatedOperand::FIXED_FP_REGISTER:
+          constraint->type_ = kFixedFPRegister;
           constraint->value_ = unallocated->fixed_register_index();
           break;
         case UnallocatedOperand::MUST_HAVE_REGISTER:
-          if (sequence()->IsFloat(vreg)) {
-            constraint->type_ = kDoubleRegister;
+          if (sequence()->IsFP(vreg)) {
+            constraint->type_ = kFPRegister;
           } else {
             constraint->type_ = kRegister;
           }
           break;
         case UnallocatedOperand::MUST_HAVE_SLOT:
-          constraint->type_ = sequence()->IsFloat(vreg) ? kDoubleSlot : kSlot;
+          constraint->type_ = sequence()->IsFP(vreg) ? kFPSlot : kSlot;
           break;
         case UnallocatedOperand::SAME_AS_FIRST_INPUT:
           constraint->type_ = kSameAsFirst;
@@ -204,7 +203,6 @@
   }
 }
 
-
 void RegisterAllocatorVerifier::CheckConstraint(
     const InstructionOperand* op, const OperandConstraint* constraint) {
   switch (constraint->type_) {
@@ -225,8 +223,8 @@
     case kRegister:
       CHECK(op->IsRegister());
       return;
-    case kDoubleRegister:
-      CHECK(op->IsDoubleRegister());
+    case kFPRegister:
+      CHECK(op->IsFPRegister());
       return;
     case kExplicit:
       CHECK(op->IsExplicit());
@@ -234,13 +232,11 @@
     case kFixedRegister:
     case kRegisterAndSlot:
       CHECK(op->IsRegister());
-      CHECK_EQ(LocationOperand::cast(op)->GetRegister().code(),
-               constraint->value_);
+      CHECK_EQ(LocationOperand::cast(op)->register_code(), constraint->value_);
       return;
-    case kFixedDoubleRegister:
-      CHECK(op->IsDoubleRegister());
-      CHECK_EQ(LocationOperand::cast(op)->GetDoubleRegister().code(),
-               constraint->value_);
+    case kFixedFPRegister:
+      CHECK(op->IsFPRegister());
+      CHECK_EQ(LocationOperand::cast(op)->register_code(), constraint->value_);
       return;
     case kFixedSlot:
       CHECK(op->IsStackSlot());
@@ -249,14 +245,14 @@
     case kSlot:
       CHECK(op->IsStackSlot());
       return;
-    case kDoubleSlot:
-      CHECK(op->IsDoubleStackSlot());
+    case kFPSlot:
+      CHECK(op->IsFPStackSlot());
       return;
     case kNone:
       CHECK(op->IsRegister() || op->IsStackSlot());
       return;
-    case kNoneDouble:
-      CHECK(op->IsDoubleRegister() || op->IsDoubleStackSlot());
+    case kNoneFP:
+      CHECK(op->IsFPRegister() || op->IsFPStackSlot());
       return;
     case kSameAsFirst:
       CHECK(false);
@@ -264,457 +260,235 @@
   }
 }
 
-namespace {
-
-typedef RpoNumber Rpo;
-
-static const int kInvalidVreg = InstructionOperand::kInvalidVirtualRegister;
-
-struct PhiData : public ZoneObject {
-  PhiData(Rpo definition_rpo, const PhiInstruction* phi, int first_pred_vreg,
-          const PhiData* first_pred_phi, Zone* zone)
-      : definition_rpo(definition_rpo),
-        virtual_register(phi->virtual_register()),
-        first_pred_vreg(first_pred_vreg),
-        first_pred_phi(first_pred_phi),
-        operands(zone) {
-    operands.reserve(phi->operands().size());
-    operands.insert(operands.begin(), phi->operands().begin(),
-                    phi->operands().end());
-  }
-  const Rpo definition_rpo;
-  const int virtual_register;
-  const int first_pred_vreg;
-  const PhiData* first_pred_phi;
-  IntVector operands;
-};
-
-class PhiMap : public ZoneMap<int, PhiData*>, public ZoneObject {
- public:
-  explicit PhiMap(Zone* zone) : ZoneMap<int, PhiData*>(zone) {}
-};
-
-struct OperandLess {
-  bool operator()(const InstructionOperand* a,
-                  const InstructionOperand* b) const {
-    return a->CompareCanonicalized(*b);
-  }
-};
-
-class OperandMap : public ZoneObject {
- public:
-  struct MapValue : public ZoneObject {
-    MapValue()
-        : incoming(nullptr),
-          define_vreg(kInvalidVreg),
-          use_vreg(kInvalidVreg),
-          succ_vreg(kInvalidVreg) {}
-    MapValue* incoming;  // value from first predecessor block.
-    int define_vreg;     // valid if this value was defined in this block.
-    int use_vreg;        // valid if this value was used in this block.
-    int succ_vreg;       // valid if propagated back from successor block.
-  };
-
-  class Map
-      : public ZoneMap<const InstructionOperand*, MapValue*, OperandLess> {
-   public:
-    explicit Map(Zone* zone)
-        : ZoneMap<const InstructionOperand*, MapValue*, OperandLess>(zone) {}
-
-    // Remove all entries with keys not in other.
-    void Intersect(const Map& other) {
-      if (this->empty()) return;
-      auto it = this->begin();
-      OperandLess less;
-      for (const std::pair<const InstructionOperand*, MapValue*>& o : other) {
-        while (less(it->first, o.first)) {
-          this->erase(it++);
-          if (it == this->end()) return;
-        }
-        if (it->first->EqualsCanonicalized(*o.first)) {
-          ++it;
-          if (it == this->end()) return;
-        } else {
-          CHECK(less(o.first, it->first));
-        }
-      }
-    }
-  };
-
-  explicit OperandMap(Zone* zone) : map_(zone) {}
-
-  Map& map() { return map_; }
-
-  void RunParallelMoves(Zone* zone, const ParallelMove* moves) {
-    // Compute outgoing mappings.
-    Map to_insert(zone);
-    for (const MoveOperands* move : *moves) {
-      if (move->IsEliminated()) continue;
-      auto cur = map().find(&move->source());
-      CHECK(cur != map().end());
-      auto res =
-          to_insert.insert(std::make_pair(&move->destination(), cur->second));
-      // Ensure injectivity of moves.
-      CHECK(res.second);
-    }
-    // Drop current mappings.
-    for (const MoveOperands* move : *moves) {
-      if (move->IsEliminated()) continue;
-      auto cur = map().find(&move->destination());
-      if (cur != map().end()) map().erase(cur);
-    }
-    // Insert new values.
-    map().insert(to_insert.begin(), to_insert.end());
-  }
-
-  void RunGaps(Zone* zone, const Instruction* instr) {
-    for (int i = Instruction::FIRST_GAP_POSITION;
-         i <= Instruction::LAST_GAP_POSITION; i++) {
-      Instruction::GapPosition inner_pos =
-          static_cast<Instruction::GapPosition>(i);
-      const ParallelMove* move = instr->GetParallelMove(inner_pos);
-      if (move == nullptr) continue;
-      RunParallelMoves(zone, move);
-    }
-  }
-
-  void Drop(const InstructionOperand* op) {
-    auto it = map().find(op);
-    if (it != map().end()) map().erase(it);
-  }
-
-  void DropRegisters(const RegisterConfiguration* config) {
-    // TODO(dcarney): sort map by kind and drop range.
-    for (auto it = map().begin(); it != map().end();) {
-      const InstructionOperand* op = it->first;
-      if (op->IsRegister() || op->IsDoubleRegister()) {
-        map().erase(it++);
-      } else {
-        ++it;
-      }
-    }
-  }
-
-  MapValue* Define(Zone* zone, const InstructionOperand* op,
-                   int virtual_register) {
-    MapValue* value = new (zone) MapValue();
-    value->define_vreg = virtual_register;
-    auto res = map().insert(std::make_pair(op, value));
-    if (!res.second) res.first->second = value;
-    return value;
-  }
-
-  void Use(const InstructionOperand* op, int use_vreg, bool initial_pass) {
-    auto it = map().find(op);
-    CHECK(it != map().end());
-    MapValue* v = it->second;
-    if (v->define_vreg != kInvalidVreg) {
-      CHECK_EQ(v->define_vreg, use_vreg);
-    }
-    // Already used this vreg in this block.
-    if (v->use_vreg != kInvalidVreg) {
-      CHECK_EQ(v->use_vreg, use_vreg);
-      return;
-    }
-    if (!initial_pass) {
-      // A value may be defined and used in this block or the use must have
-      // propagated up.
-      if (v->succ_vreg != kInvalidVreg) {
-        CHECK_EQ(v->succ_vreg, use_vreg);
-      } else {
-        CHECK_EQ(v->define_vreg, use_vreg);
-      }
-      // Mark the use.
-      it->second->use_vreg = use_vreg;
-      return;
-    }
-    // Go up block list and ensure the correct definition is reached.
-    for (; v != nullptr; v = v->incoming) {
-      // Value unused in block.
-      if (v->define_vreg == kInvalidVreg && v->use_vreg == kInvalidVreg) {
-        continue;
-      }
-      // Found correct definition or use.
-      CHECK(v->define_vreg == use_vreg || v->use_vreg == use_vreg);
-      // Mark the use.
-      it->second->use_vreg = use_vreg;
-      return;
-    }
-    // Use of a non-phi value without definition.
-    CHECK(false);
-  }
-
-  void UsePhi(const InstructionOperand* op, const PhiData* phi,
-              bool initial_pass) {
-    auto it = map().find(op);
-    CHECK(it != map().end());
-    MapValue* v = it->second;
-    int use_vreg = phi->virtual_register;
-    // Phis are not defined.
-    CHECK_EQ(kInvalidVreg, v->define_vreg);
-    // Already used this vreg in this block.
-    if (v->use_vreg != kInvalidVreg) {
-      CHECK_EQ(v->use_vreg, use_vreg);
-      return;
-    }
-    if (!initial_pass) {
-      // A used phi must have propagated its use to a predecessor.
-      CHECK_EQ(v->succ_vreg, use_vreg);
-      // Mark the use.
-      v->use_vreg = use_vreg;
-      return;
-    }
-    // Go up the block list starting at the first predecessor and ensure this
-    // phi has a correct use or definition.
-    for (v = v->incoming; v != nullptr; v = v->incoming) {
-      // Value unused in block.
-      if (v->define_vreg == kInvalidVreg && v->use_vreg == kInvalidVreg) {
-        continue;
-      }
-      // Found correct definition or use.
-      if (v->define_vreg != kInvalidVreg) {
-        CHECK(v->define_vreg == phi->first_pred_vreg);
-      } else if (v->use_vreg != phi->first_pred_vreg) {
-        // Walk the phi chain, hunting for a matching phi use.
-        const PhiData* p = phi;
-        for (; p != nullptr; p = p->first_pred_phi) {
-          if (p->virtual_register == v->use_vreg) break;
-        }
-        CHECK(p);
-      }
-      // Mark the use.
-      it->second->use_vreg = use_vreg;
-      return;
-    }
-    // Use of a phi value without definition.
-    UNREACHABLE();
-  }
-
- private:
-  Map map_;
-  DISALLOW_COPY_AND_ASSIGN(OperandMap);
-};
-
-}  // namespace
-
-
-class RegisterAllocatorVerifier::BlockMaps {
- public:
-  BlockMaps(Zone* zone, const InstructionSequence* sequence)
-      : zone_(zone),
-        sequence_(sequence),
-        phi_map_guard_(sequence->VirtualRegisterCount(), zone),
-        phi_map_(zone),
-        incoming_maps_(zone),
-        outgoing_maps_(zone) {
-    InitializePhis();
-    InitializeOperandMaps();
-  }
-
-  bool IsPhi(int virtual_register) {
-    return phi_map_guard_.Contains(virtual_register);
-  }
-
-  const PhiData* GetPhi(int virtual_register) {
-    auto it = phi_map_.find(virtual_register);
-    CHECK(it != phi_map_.end());
-    return it->second;
-  }
-
-  OperandMap* InitializeIncoming(size_t block_index, bool initial_pass) {
-    return initial_pass ? InitializeFromFirstPredecessor(block_index)
-                        : InitializeFromIntersection(block_index);
-  }
-
-  void PropagateUsesBackwards() {
-    typedef std::set<size_t, std::greater<size_t>, zone_allocator<size_t>>
-        BlockIds;
-    BlockIds block_ids((BlockIds::key_compare()),
-                       zone_allocator<size_t>(zone()));
-    // First ensure that incoming contains only keys in all predecessors.
-    for (const InstructionBlock* block : sequence()->instruction_blocks()) {
-      size_t index = block->rpo_number().ToSize();
-      block_ids.insert(index);
-      OperandMap::Map& succ_map = incoming_maps_[index]->map();
-      for (size_t i = 0; i < block->PredecessorCount(); ++i) {
-        RpoNumber pred_rpo = block->predecessors()[i];
-        succ_map.Intersect(outgoing_maps_[pred_rpo.ToSize()]->map());
-      }
-    }
-    // Back propagation fixpoint.
-    while (!block_ids.empty()) {
-      // Pop highest block_id.
-      auto block_id_it = block_ids.begin();
-      const size_t succ_index = *block_id_it;
-      block_ids.erase(block_id_it);
-      // Propagate uses back to their definition blocks using succ_vreg.
-      const InstructionBlock* block =
-          sequence()->instruction_blocks()[succ_index];
-      OperandMap::Map& succ_map = incoming_maps_[succ_index]->map();
-      for (size_t i = 0; i < block->PredecessorCount(); ++i) {
-        for (auto& succ_val : succ_map) {
-          // An incoming map contains no defines.
-          CHECK_EQ(kInvalidVreg, succ_val.second->define_vreg);
-          // Compute succ_vreg.
-          int succ_vreg = succ_val.second->succ_vreg;
-          if (succ_vreg == kInvalidVreg) {
-            succ_vreg = succ_val.second->use_vreg;
-            // Initialize succ_vreg in back propagation chain.
-            succ_val.second->succ_vreg = succ_vreg;
-          }
-          if (succ_vreg == kInvalidVreg) continue;
-          // May need to transition phi.
-          if (IsPhi(succ_vreg)) {
-            const PhiData* phi = GetPhi(succ_vreg);
-            if (phi->definition_rpo.ToSize() == succ_index) {
-              // phi definition block, transition to pred value.
-              succ_vreg = phi->operands[i];
-            }
-          }
-          // Push succ_vreg up to all predecessors.
-          RpoNumber pred_rpo = block->predecessors()[i];
-          OperandMap::Map& pred_map = outgoing_maps_[pred_rpo.ToSize()]->map();
-          auto& pred_val = *pred_map.find(succ_val.first);
-          if (pred_val.second->use_vreg != kInvalidVreg) {
-            CHECK_EQ(succ_vreg, pred_val.second->use_vreg);
-          }
-          if (pred_val.second->define_vreg != kInvalidVreg) {
-            CHECK_EQ(succ_vreg, pred_val.second->define_vreg);
-          }
-          if (pred_val.second->succ_vreg != kInvalidVreg) {
-            if (succ_vreg != pred_val.second->succ_vreg) {
-              // When a block introduces 2 identical phis A and B, and both are
-              // operands to other phis C and D, and we optimized the moves
-              // defining A or B such that they now appear in the block defining
-              // A and B, the back propagation will get confused when visiting
-              // upwards from C and D. The operand in the block defining A and B
-              // will be attributed to C (or D, depending which of these is
-              // visited first).
-              CHECK(IsPhi(pred_val.second->succ_vreg));
-              CHECK(IsPhi(succ_vreg));
-              const PhiData* current_phi = GetPhi(succ_vreg);
-              const PhiData* assigned_phi = GetPhi(pred_val.second->succ_vreg);
-              CHECK_EQ(current_phi->operands.size(),
-                       assigned_phi->operands.size());
-              CHECK_EQ(current_phi->definition_rpo,
-                       assigned_phi->definition_rpo);
-              for (size_t i = 0; i < current_phi->operands.size(); ++i) {
-                CHECK_EQ(current_phi->operands[i], assigned_phi->operands[i]);
-              }
-            }
-          } else {
-            pred_val.second->succ_vreg = succ_vreg;
-            block_ids.insert(pred_rpo.ToSize());
-          }
-        }
-      }
-    }
-    // Clear uses and back links for second pass.
-    for (OperandMap* operand_map : incoming_maps_) {
-      for (auto& succ_val : operand_map->map()) {
-        succ_val.second->incoming = nullptr;
-        succ_val.second->use_vreg = kInvalidVreg;
-      }
-    }
-  }
-
- private:
-  OperandMap* InitializeFromFirstPredecessor(size_t block_index) {
-    OperandMap* to_init = outgoing_maps_[block_index];
-    CHECK(to_init->map().empty());
-    const InstructionBlock* block =
-        sequence()->instruction_blocks()[block_index];
-    if (block->predecessors().empty()) return to_init;
-    size_t predecessor_index = block->predecessors()[0].ToSize();
-    // Ensure not a backedge.
-    CHECK(predecessor_index < block->rpo_number().ToSize());
-    OperandMap* incoming = outgoing_maps_[predecessor_index];
-    // Copy map and replace values.
-    to_init->map() = incoming->map();
-    for (auto& it : to_init->map()) {
-      OperandMap::MapValue* incoming = it.second;
-      it.second = new (zone()) OperandMap::MapValue();
-      it.second->incoming = incoming;
-    }
-    // Copy to incoming map for second pass.
-    incoming_maps_[block_index]->map() = to_init->map();
-    return to_init;
-  }
-
-  OperandMap* InitializeFromIntersection(size_t block_index) {
-    return incoming_maps_[block_index];
-  }
-
-  void InitializeOperandMaps() {
-    size_t block_count = sequence()->instruction_blocks().size();
-    incoming_maps_.reserve(block_count);
-    outgoing_maps_.reserve(block_count);
-    for (size_t i = 0; i < block_count; ++i) {
-      incoming_maps_.push_back(new (zone()) OperandMap(zone()));
-      outgoing_maps_.push_back(new (zone()) OperandMap(zone()));
-    }
-  }
-
-  void InitializePhis() {
-    const size_t block_count = sequence()->instruction_blocks().size();
-    for (size_t block_index = 0; block_index < block_count; ++block_index) {
-      const InstructionBlock* block =
-          sequence()->instruction_blocks()[block_index];
-      for (const PhiInstruction* phi : block->phis()) {
-        int first_pred_vreg = phi->operands()[0];
-        const PhiData* first_pred_phi = nullptr;
-        if (IsPhi(first_pred_vreg)) {
-          first_pred_phi = GetPhi(first_pred_vreg);
-          first_pred_vreg = first_pred_phi->first_pred_vreg;
-        }
-        CHECK(!IsPhi(first_pred_vreg));
-        PhiData* phi_data = new (zone()) PhiData(
-            block->rpo_number(), phi, first_pred_vreg, first_pred_phi, zone());
-        auto res =
-            phi_map_.insert(std::make_pair(phi->virtual_register(), phi_data));
-        CHECK(res.second);
-        phi_map_guard_.Add(phi->virtual_register());
-      }
-    }
-  }
-
-  typedef ZoneVector<OperandMap*> OperandMaps;
-  typedef ZoneVector<PhiData*> PhiVector;
-
-  Zone* zone() const { return zone_; }
-  const InstructionSequence* sequence() const { return sequence_; }
-
-  Zone* const zone_;
-  const InstructionSequence* const sequence_;
-  BitVector phi_map_guard_;
-  PhiMap phi_map_;
-  OperandMaps incoming_maps_;
-  OperandMaps outgoing_maps_;
-};
-
-
-void RegisterAllocatorVerifier::VerifyGapMoves() {
-  BlockMaps block_maps(zone(), sequence());
-  VerifyGapMoves(&block_maps, true);
-  block_maps.PropagateUsesBackwards();
-  VerifyGapMoves(&block_maps, false);
+void BlockAssessments::PerformMoves(const Instruction* instruction) {
+  const ParallelMove* first =
+      instruction->GetParallelMove(Instruction::GapPosition::START);
+  PerformParallelMoves(first);
+  const ParallelMove* last =
+      instruction->GetParallelMove(Instruction::GapPosition::END);
+  PerformParallelMoves(last);
 }
 
+void BlockAssessments::PerformParallelMoves(const ParallelMove* moves) {
+  if (moves == nullptr) return;
 
-// Compute and verify outgoing values for every block.
-void RegisterAllocatorVerifier::VerifyGapMoves(BlockMaps* block_maps,
-                                               bool initial_pass) {
+  CHECK(map_for_moves_.empty());
+  for (MoveOperands* move : *moves) {
+    if (move->IsEliminated() || move->IsRedundant()) continue;
+    auto it = map_.find(move->source());
+    // The RHS of a parallel move should have been already assessed.
+    CHECK(it != map_.end());
+    // The LHS of a parallel move should not have been assigned in this
+    // parallel move.
+    CHECK(map_for_moves_.find(move->destination()) == map_for_moves_.end());
+    // Copy the assessment to the destination.
+    map_for_moves_[move->destination()] = it->second;
+  }
+  for (auto pair : map_for_moves_) {
+    map_[pair.first] = pair.second;
+  }
+  map_for_moves_.clear();
+}
+
+void BlockAssessments::DropRegisters() {
+  for (auto iterator = map().begin(), end = map().end(); iterator != end;) {
+    auto current = iterator;
+    ++iterator;
+    InstructionOperand op = current->first;
+    if (op.IsAnyRegister()) map().erase(current);
+  }
+}
+
+BlockAssessments* RegisterAllocatorVerifier::CreateForBlock(
+    const InstructionBlock* block) {
+  RpoNumber current_block_id = block->rpo_number();
+
+  BlockAssessments* ret = new (zone()) BlockAssessments(zone());
+  if (block->PredecessorCount() == 0) {
+    // TODO(mtrofin): the following check should hold, however, in certain
+    // unit tests it is invalidated by the last block. Investigate and
+    // normalize the CFG.
+    // CHECK(current_block_id.ToInt() == 0);
+    // The phi size test below is because we can, technically, have phi
+    // instructions with one argument. Some tests expose that, too.
+  } else if (block->PredecessorCount() == 1 && block->phis().size() == 0) {
+    const BlockAssessments* prev_block = assessments_[block->predecessors()[0]];
+    ret->CopyFrom(prev_block);
+  } else {
+    for (RpoNumber pred_id : block->predecessors()) {
+      // For every operand coming from any of the predecessors, create an
+      // Unfinalized assessment.
+      auto iterator = assessments_.find(pred_id);
+      if (iterator == assessments_.end()) {
+        // This block is the head of a loop, and this predecessor is the
+        // loopback
+        // arc.
+        // Validate this is a loop case, otherwise the CFG is malformed.
+        CHECK(pred_id >= current_block_id);
+        CHECK(block->IsLoopHeader());
+        continue;
+      }
+      const BlockAssessments* pred_assessments = iterator->second;
+      CHECK_NOT_NULL(pred_assessments);
+      for (auto pair : pred_assessments->map()) {
+        InstructionOperand operand = pair.first;
+        if (ret->map().find(operand) == ret->map().end()) {
+          ret->map().insert(std::make_pair(
+              operand, new (zone()) PendingAssessment(block, operand)));
+        }
+      }
+    }
+  }
+  return ret;
+}
+
+void RegisterAllocatorVerifier::ValidatePendingAssessment(
+    RpoNumber block_id, InstructionOperand op,
+    BlockAssessments* current_assessments, const PendingAssessment* assessment,
+    int virtual_register) {
+  // When validating a pending assessment, it is possible some of the
+  // assessments
+  // for the original operand (the one where the assessment was created for
+  // first) are also pending. To avoid recursion, we use a work list. To
+  // deal with cycles, we keep a set of seen nodes.
+  ZoneQueue<std::pair<const PendingAssessment*, int>> worklist(zone());
+  ZoneSet<RpoNumber> seen(zone());
+  worklist.push(std::make_pair(assessment, virtual_register));
+  seen.insert(block_id);
+
+  while (!worklist.empty()) {
+    auto work = worklist.front();
+    const PendingAssessment* current_assessment = work.first;
+    int current_virtual_register = work.second;
+    InstructionOperand current_operand = current_assessment->operand();
+    worklist.pop();
+
+    const InstructionBlock* origin = current_assessment->origin();
+    CHECK(origin->PredecessorCount() > 1 || origin->phis().size() > 0);
+
+    // Check if the virtual register is a phi first, instead of relying on
+    // the incoming assessments. In particular, this handles the case
+    // v1 = phi v0 v0, which structurally is identical to v0 having been
+    // defined at the top of a diamond, and arriving at the node joining the
+    // diamond's branches.
+    const PhiInstruction* phi = nullptr;
+    for (const PhiInstruction* candidate : origin->phis()) {
+      if (candidate->virtual_register() == current_virtual_register) {
+        phi = candidate;
+        break;
+      }
+    }
+
+    int op_index = 0;
+    for (RpoNumber pred : origin->predecessors()) {
+      int expected =
+          phi != nullptr ? phi->operands()[op_index] : current_virtual_register;
+
+      ++op_index;
+      auto pred_assignment = assessments_.find(pred);
+      if (pred_assignment == assessments_.end()) {
+        CHECK(origin->IsLoopHeader());
+        auto todo_iter = outstanding_assessments_.find(pred);
+        DelayedAssessments* set = nullptr;
+        if (todo_iter == outstanding_assessments_.end()) {
+          set = new (zone()) DelayedAssessments(zone());
+          outstanding_assessments_.insert(std::make_pair(pred, set));
+        } else {
+          set = todo_iter->second;
+        }
+        set->AddDelayedAssessment(current_operand, expected);
+        continue;
+      }
+
+      const BlockAssessments* pred_assessments = pred_assignment->second;
+      auto found_contribution = pred_assessments->map().find(current_operand);
+      CHECK(found_contribution != pred_assessments->map().end());
+      Assessment* contribution = found_contribution->second;
+
+      switch (contribution->kind()) {
+        case Final:
+          ValidateFinalAssessment(
+              block_id, current_operand, current_assessments,
+              FinalAssessment::cast(contribution), expected);
+          break;
+        case Pending: {
+          // This happens if we have a diamond feeding into another one, and
+          // the inner one never being used - other than for carrying the value.
+          const PendingAssessment* next = PendingAssessment::cast(contribution);
+          if (seen.find(pred) == seen.end()) {
+            worklist.push({next, expected});
+            seen.insert(pred);
+          }
+          // Note that we do not want to finalize pending assessments at the
+          // beginning of a block - which is the information we'd have
+          // available here. This is because this operand may be reused to
+          // define
+          // duplicate phis.
+          break;
+        }
+      }
+    }
+  }
+  // If everything checks out, we may make the assessment.
+  current_assessments->map()[op] =
+      new (zone()) FinalAssessment(virtual_register, assessment);
+}
+
+void RegisterAllocatorVerifier::ValidateFinalAssessment(
+    RpoNumber block_id, InstructionOperand op,
+    BlockAssessments* current_assessments, const FinalAssessment* assessment,
+    int virtual_register) {
+  if (assessment->virtual_register() == virtual_register) return;
+  // If we have 2 phis with the exact same operand list, and the first phi is
+  // used before the second one, via the operand incoming to the block,
+  // and the second one's operand is defined (via a parallel move) after the
+  // use, then the original operand will be assigned to the first phi. We
+  // then look at the original pending assessment to ascertain if op
+  // is virtual_register.
+  const PendingAssessment* old = assessment->original_pending_assessment();
+  CHECK_NOT_NULL(old);
+  ValidatePendingAssessment(block_id, op, current_assessments, old,
+                            virtual_register);
+}
+
+void RegisterAllocatorVerifier::ValidateUse(
+    RpoNumber block_id, BlockAssessments* current_assessments,
+    InstructionOperand op, int virtual_register) {
+  auto iterator = current_assessments->map().find(op);
+  // We should have seen this operand before.
+  CHECK(iterator != current_assessments->map().end());
+  Assessment* assessment = iterator->second;
+
+  switch (assessment->kind()) {
+    case Final:
+      ValidateFinalAssessment(block_id, op, current_assessments,
+                              FinalAssessment::cast(assessment),
+                              virtual_register);
+      break;
+    case Pending: {
+      const PendingAssessment* pending = PendingAssessment::cast(assessment);
+      ValidatePendingAssessment(block_id, op, current_assessments, pending,
+                                virtual_register);
+      break;
+    }
+  }
+}
+
+void RegisterAllocatorVerifier::VerifyGapMoves() {
+  CHECK(assessments_.empty());
+  CHECK(outstanding_assessments_.empty());
   const size_t block_count = sequence()->instruction_blocks().size();
   for (size_t block_index = 0; block_index < block_count; ++block_index) {
-    OperandMap* current =
-        block_maps->InitializeIncoming(block_index, initial_pass);
     const InstructionBlock* block =
         sequence()->instruction_blocks()[block_index];
+    BlockAssessments* block_assessments = CreateForBlock(block);
+
     for (int instr_index = block->code_start(); instr_index < block->code_end();
          ++instr_index) {
       const InstructionConstraint& instr_constraint = constraints_[instr_index];
       const Instruction* instr = instr_constraint.instruction_;
-      current->RunGaps(zone(), instr);
+      block_assessments->PerformMoves(instr);
+
       const OperandConstraint* op_constraints =
           instr_constraint.operand_constraints_;
       size_t count = 0;
@@ -724,24 +498,19 @@
           continue;
         }
         int virtual_register = op_constraints[count].virtual_register_;
-        const InstructionOperand* op = instr->InputAt(i);
-        if (!block_maps->IsPhi(virtual_register)) {
-          current->Use(op, virtual_register, initial_pass);
-        } else {
-          const PhiData* phi = block_maps->GetPhi(virtual_register);
-          current->UsePhi(op, phi, initial_pass);
-        }
+        InstructionOperand op = *instr->InputAt(i);
+        ValidateUse(block->rpo_number(), block_assessments, op,
+                    virtual_register);
       }
       for (size_t i = 0; i < instr->TempCount(); ++i, ++count) {
-        current->Drop(instr->TempAt(i));
+        block_assessments->Drop(*instr->TempAt(i));
       }
       if (instr->IsCall()) {
-        current->DropRegisters(config());
+        block_assessments->DropRegisters();
       }
       for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) {
         int virtual_register = op_constraints[count].virtual_register_;
-        OperandMap::MapValue* value =
-            current->Define(zone(), instr->OutputAt(i), virtual_register);
+        block_assessments->AddDefinition(*instr->OutputAt(i), virtual_register);
         if (op_constraints[count].type_ == kRegisterAndSlot) {
           const AllocatedOperand* reg_op =
               AllocatedOperand::cast(instr->OutputAt(i));
@@ -749,13 +518,38 @@
           const AllocatedOperand* stack_op = AllocatedOperand::New(
               zone(), LocationOperand::LocationKind::STACK_SLOT, rep,
               op_constraints[i].spilled_slot_);
-          auto insert_result =
-              current->map().insert(std::make_pair(stack_op, value));
-          DCHECK(insert_result.second);
-          USE(insert_result);
+          block_assessments->AddDefinition(*stack_op, virtual_register);
         }
       }
     }
+    // Now commit the assessments for this block. If there are any delayed
+    // assessments, ValidatePendingAssessment should see this block, too.
+    assessments_[block->rpo_number()] = block_assessments;
+
+    auto todo_iter = outstanding_assessments_.find(block->rpo_number());
+    if (todo_iter == outstanding_assessments_.end()) continue;
+    DelayedAssessments* todo = todo_iter->second;
+    for (auto pair : todo->map()) {
+      InstructionOperand op = pair.first;
+      int vreg = pair.second;
+      auto found_op = block_assessments->map().find(op);
+      CHECK(found_op != block_assessments->map().end());
+      switch (found_op->second->kind()) {
+        case Final:
+          ValidateFinalAssessment(block->rpo_number(), op, block_assessments,
+                                  FinalAssessment::cast(found_op->second),
+                                  vreg);
+          break;
+        case Pending:
+          const PendingAssessment* pending =
+              PendingAssessment::cast(found_op->second);
+          ValidatePendingAssessment(block->rpo_number(), op, block_assessments,
+                                    pending, vreg);
+          block_assessments->map()[op] =
+              new (zone()) FinalAssessment(vreg, pending);
+          break;
+      }
+    }
   }
 }
 
diff --git a/src/compiler/register-allocator-verifier.h b/src/compiler/register-allocator-verifier.h
index f3ab54f..72e6e06 100644
--- a/src/compiler/register-allocator-verifier.h
+++ b/src/compiler/register-allocator-verifier.h
@@ -14,6 +14,153 @@
 class InstructionOperand;
 class InstructionSequence;
 
+// The register allocator validator traverses instructions in the instruction
+// sequence, and verifies the correctness of machine operand substitutions of
+// virtual registers. It collects the virtual register instruction signatures
+// before register allocation. Then, after the register allocation pipeline
+// completes, it compares the operand substitutions against the pre-allocation
+// data.
+// At a high level, validation works as follows: we iterate through each block,
+// and, in a block, through each instruction; then:
+// - when an operand is the output of an instruction, we associate it to the
+// virtual register that the instruction sequence declares as its output. We
+// use the concept of "FinalAssessment" to model this.
+// - when an operand is used in an instruction, we check that the assessment
+// matches the expectation of the instruction
+// - moves simply copy the assessment over to the new operand
+// - blocks with more than one predecessor associate to each operand a "Pending"
+// assessment. The pending assessment remembers the operand and block where it
+// was created. Then, when the value is used (which may be as a different
+// operand, because of moves), we check that the virtual register at the use
+// site matches the definition of this pending operand: either the phi inputs
+// match, or, if it's not a phi, all the predecessors at the point the pending
+// assessment was defined have that operand assigned to the given virtual
+// register.
+// If a block is a loop header - so one or more of its predecessors are it or
+// below - we still treat uses of operands as above, but we record which operand
+// assessments haven't been made yet, and what virtual register they must
+// correspond to, and verify that when we are done with the respective
+// predecessor blocks.
+// This way, the algorithm always makes a final decision about the operands
+// in an instruction, ensuring convergence.
+// Operand assessments are recorded per block, as the result at the exit from
+// the block. When moving to a new block, we copy assessments from its single
+// predecessor, or, if the block has multiple predecessors, the mechanism was
+// described already.
+
+enum AssessmentKind { Final, Pending };
+
+class Assessment : public ZoneObject {
+ public:
+  AssessmentKind kind() const { return kind_; }
+
+ protected:
+  explicit Assessment(AssessmentKind kind) : kind_(kind) {}
+  AssessmentKind kind_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Assessment);
+};
+
+// PendingAssessments are associated to operands coming from the multiple
+// predecessors of a block. We only record the operand and the block, and
+// will determine if the way the operand is defined (from the predecessors)
+// matches a particular use. This handles scenarios where multiple phis are
+// defined with identical operands, and the move optimizer moved down the moves
+// separating the 2 phis in the block defining them.
+class PendingAssessment final : public Assessment {
+ public:
+  explicit PendingAssessment(const InstructionBlock* origin,
+                             InstructionOperand operand)
+      : Assessment(Pending), origin_(origin), operand_(operand) {}
+
+  static const PendingAssessment* cast(const Assessment* assessment) {
+    CHECK(assessment->kind() == Pending);
+    return static_cast<const PendingAssessment*>(assessment);
+  }
+
+  const InstructionBlock* origin() const { return origin_; }
+  InstructionOperand operand() const { return operand_; }
+
+ private:
+  const InstructionBlock* const origin_;
+  InstructionOperand operand_;
+
+  DISALLOW_COPY_AND_ASSIGN(PendingAssessment);
+};
+
+// FinalAssessments are associated to operands that we know to be a certain
+// virtual register.
+class FinalAssessment final : public Assessment {
+ public:
+  explicit FinalAssessment(int virtual_register,
+                           const PendingAssessment* original_pending = nullptr)
+      : Assessment(Final),
+        virtual_register_(virtual_register),
+        original_pending_assessment_(original_pending) {}
+
+  int virtual_register() const { return virtual_register_; }
+  static const FinalAssessment* cast(const Assessment* assessment) {
+    CHECK(assessment->kind() == Final);
+    return static_cast<const FinalAssessment*>(assessment);
+  }
+
+  const PendingAssessment* original_pending_assessment() const {
+    return original_pending_assessment_;
+  }
+
+ private:
+  int virtual_register_;
+  const PendingAssessment* original_pending_assessment_;
+
+  DISALLOW_COPY_AND_ASSIGN(FinalAssessment);
+};
+
+struct OperandAsKeyLess {
+  bool operator()(const InstructionOperand& a,
+                  const InstructionOperand& b) const {
+    return a.CompareCanonicalized(b);
+  }
+};
+
+// Assessments associated with a basic block.
+class BlockAssessments : public ZoneObject {
+ public:
+  typedef ZoneMap<InstructionOperand, Assessment*, OperandAsKeyLess> OperandMap;
+  explicit BlockAssessments(Zone* zone)
+      : map_(zone), map_for_moves_(zone), zone_(zone) {}
+  void Drop(InstructionOperand operand) { map_.erase(operand); }
+  void DropRegisters();
+  void AddDefinition(InstructionOperand operand, int virtual_register) {
+    auto existent = map_.find(operand);
+    if (existent != map_.end()) {
+      // Drop the assignment
+      map_.erase(existent);
+    }
+    map_.insert(
+        std::make_pair(operand, new (zone_) FinalAssessment(virtual_register)));
+  }
+
+  void PerformMoves(const Instruction* instruction);
+  void PerformParallelMoves(const ParallelMove* moves);
+  void CopyFrom(const BlockAssessments* other) {
+    CHECK(map_.empty());
+    CHECK_NOT_NULL(other);
+    map_.insert(other->map_.begin(), other->map_.end());
+  }
+
+  OperandMap& map() { return map_; }
+  const OperandMap& map() const { return map_; }
+  void Print() const;
+
+ private:
+  OperandMap map_;
+  OperandMap map_for_moves_;
+  Zone* zone_;
+
+  DISALLOW_COPY_AND_ASSIGN(BlockAssessments);
+};
+
 class RegisterAllocatorVerifier final : public ZoneObject {
  public:
   RegisterAllocatorVerifier(Zone* zone, const RegisterConfiguration* config,
@@ -28,13 +175,13 @@
     kImmediate,
     kRegister,
     kFixedRegister,
-    kDoubleRegister,
-    kFixedDoubleRegister,
+    kFPRegister,
+    kFixedFPRegister,
     kSlot,
-    kDoubleSlot,
+    kFPSlot,
     kFixedSlot,
     kNone,
-    kNoneDouble,
+    kNoneFP,
     kExplicit,
     kSameAsFirst,
     kRegisterAndSlot
@@ -53,10 +200,29 @@
     OperandConstraint* operand_constraints_;
   };
 
-  class BlockMaps;
-
   typedef ZoneVector<InstructionConstraint> Constraints;
 
+  class DelayedAssessments : public ZoneObject {
+   public:
+    explicit DelayedAssessments(Zone* zone) : map_(zone) {}
+
+    const ZoneMap<InstructionOperand, int, OperandAsKeyLess>& map() const {
+      return map_;
+    }
+
+    void AddDelayedAssessment(InstructionOperand op, int vreg) {
+      auto it = map_.find(op);
+      if (it == map_.end()) {
+        map_.insert(std::make_pair(op, vreg));
+      } else {
+        CHECK_EQ(it->second, vreg);
+      }
+    }
+
+   private:
+    ZoneMap<InstructionOperand, int, OperandAsKeyLess> map_;
+  };
+
   Zone* zone() const { return zone_; }
   const RegisterConfiguration* config() { return config_; }
   const InstructionSequence* sequence() const { return sequence_; }
@@ -70,13 +236,25 @@
                        OperandConstraint* constraint);
   void CheckConstraint(const InstructionOperand* op,
                        const OperandConstraint* constraint);
+  BlockAssessments* CreateForBlock(const InstructionBlock* block);
 
-  void VerifyGapMoves(BlockMaps* outgoing_mappings, bool initial_pass);
+  void ValidatePendingAssessment(RpoNumber block_id, InstructionOperand op,
+                                 BlockAssessments* current_assessments,
+                                 const PendingAssessment* assessment,
+                                 int virtual_register);
+  void ValidateFinalAssessment(RpoNumber block_id, InstructionOperand op,
+                               BlockAssessments* current_assessments,
+                               const FinalAssessment* assessment,
+                               int virtual_register);
+  void ValidateUse(RpoNumber block_id, BlockAssessments* current_assessments,
+                   InstructionOperand op, int virtual_register);
 
   Zone* const zone_;
   const RegisterConfiguration* config_;
   const InstructionSequence* const sequence_;
   Constraints constraints_;
+  ZoneMap<RpoNumber, BlockAssessments*> assessments_;
+  ZoneMap<RpoNumber, DelayedAssessments*> outstanding_assessments_;
 
   DISALLOW_COPY_AND_ASSIGN(RegisterAllocatorVerifier);
 };
diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc
index 82faf75..9c8d999 100644
--- a/src/compiler/register-allocator.cc
+++ b/src/compiler/register-allocator.cc
@@ -26,23 +26,22 @@
 }
 
 int GetRegisterCount(const RegisterConfiguration* cfg, RegisterKind kind) {
-  return kind == DOUBLE_REGISTERS ? cfg->num_double_registers()
-                                  : cfg->num_general_registers();
+  return kind == FP_REGISTERS ? cfg->num_double_registers()
+                              : cfg->num_general_registers();
 }
 
 
 int GetAllocatableRegisterCount(const RegisterConfiguration* cfg,
                                 RegisterKind kind) {
-  return kind == DOUBLE_REGISTERS
-             ? cfg->num_allocatable_aliased_double_registers()
-             : cfg->num_allocatable_general_registers();
+  return kind == FP_REGISTERS ? cfg->num_allocatable_double_registers()
+                              : cfg->num_allocatable_general_registers();
 }
 
 
 const int* GetAllocatableRegisterCodes(const RegisterConfiguration* cfg,
                                        RegisterKind kind) {
-  return kind == DOUBLE_REGISTERS ? cfg->allocatable_double_codes()
-                                  : cfg->allocatable_general_codes();
+  return kind == FP_REGISTERS ? cfg->allocatable_double_codes()
+                              : cfg->allocatable_general_codes();
 }
 
 
@@ -65,25 +64,31 @@
   return code->InstructionAt(block->last_instruction_index());
 }
 
-
-bool IsOutputRegisterOf(Instruction* instr, Register reg) {
+bool IsOutputRegisterOf(Instruction* instr, int code) {
   for (size_t i = 0; i < instr->OutputCount(); i++) {
     InstructionOperand* output = instr->OutputAt(i);
     if (output->IsRegister() &&
-        LocationOperand::cast(output)->GetRegister().is(reg)) {
+        LocationOperand::cast(output)->register_code() == code) {
       return true;
     }
   }
   return false;
 }
 
-
-bool IsOutputDoubleRegisterOf(Instruction* instr, DoubleRegister reg) {
+bool IsOutputFPRegisterOf(Instruction* instr, MachineRepresentation rep,
+                          int code) {
   for (size_t i = 0; i < instr->OutputCount(); i++) {
     InstructionOperand* output = instr->OutputAt(i);
-    if (output->IsDoubleRegister() &&
-        LocationOperand::cast(output)->GetDoubleRegister().is(reg)) {
-      return true;
+    if (output->IsFPRegister()) {
+      const LocationOperand* op = LocationOperand::cast(output);
+      if (kSimpleFPAliasing) {
+        if (op->register_code() == code) return true;
+      } else {
+        if (RegisterConfiguration::Turbofan()->AreAliases(
+                op->representation(), op->register_code(), rep, code)) {
+          return true;
+        }
+      }
     }
   }
   return false;
@@ -320,11 +325,7 @@
     case UsePositionHintType::kOperand: {
       InstructionOperand* operand =
           reinterpret_cast<InstructionOperand*>(hint_);
-      int assigned_register =
-          operand->IsRegister()
-              ? LocationOperand::cast(operand)->GetRegister().code()
-              : LocationOperand::cast(operand)->GetDoubleRegister().code();
-      *register_code = assigned_register;
+      *register_code = LocationOperand::cast(operand)->register_code();
       return true;
     }
     case UsePositionHintType::kPhi: {
@@ -351,10 +352,10 @@
     case InstructionOperand::UNALLOCATED:
       return UsePositionHintType::kUnresolved;
     case InstructionOperand::ALLOCATED:
-      if (op.IsRegister() || op.IsDoubleRegister()) {
+      if (op.IsRegister() || op.IsFPRegister()) {
         return UsePositionHintType::kOperand;
       } else {
-        DCHECK(op.IsStackSlot() || op.IsDoubleStackSlot());
+        DCHECK(op.IsStackSlot() || op.IsFPStackSlot());
         return UsePositionHintType::kNone;
       }
     case InstructionOperand::INVALID:
@@ -414,11 +415,6 @@
   return os;
 }
 
-
-const float LiveRange::kInvalidWeight = -1;
-const float LiveRange::kMaxWeight = std::numeric_limits<float>::max();
-
-
 LiveRange::LiveRange(int relative_id, MachineRepresentation rep,
                      TopLevelLiveRange* top_level)
     : relative_id_(relative_id),
@@ -431,10 +427,7 @@
       current_interval_(nullptr),
       last_processed_use_(nullptr),
       current_hint_position_(nullptr),
-      splitting_pointer_(nullptr),
-      size_(kInvalidSize),
-      weight_(kInvalidWeight),
-      group_(nullptr) {
+      splitting_pointer_(nullptr) {
   DCHECK(AllocatedOperand::IsSupportedRepresentation(rep));
   bits_ = AssignedRegisterField::encode(kUnassignedRegister) |
           RepresentationField::encode(rep);
@@ -489,8 +482,7 @@
 
 
 RegisterKind LiveRange::kind() const {
-  return IsFloatingPoint(representation()) ? DOUBLE_REGISTERS
-                                           : GENERAL_REGISTERS;
+  return IsFloatingPoint(representation()) ? FP_REGISTERS : GENERAL_REGISTERS;
 }
 
 
@@ -701,10 +693,6 @@
   last_processed_use_ = nullptr;
   current_interval_ = nullptr;
 
-  // Invalidate size and weight of this range. The child range has them
-  // invalid at construction.
-  size_ = kInvalidSize;
-  weight_ = kInvalidWeight;
 #ifdef DEBUG
   VerifyChildStructure();
   result->VerifyChildStructure();
@@ -728,11 +716,11 @@
     if (!pos->HasOperand()) continue;
     switch (pos->type()) {
       case UsePositionType::kRequiresSlot:
-        DCHECK(spill_op.IsStackSlot() || spill_op.IsDoubleStackSlot());
+        DCHECK(spill_op.IsStackSlot() || spill_op.IsFPStackSlot());
         InstructionOperand::ReplaceWith(pos->operand(), &spill_op);
         break;
       case UsePositionType::kRequiresRegister:
-        DCHECK(op.IsRegister() || op.IsDoubleRegister());
+        DCHECK(op.IsRegister() || op.IsFPRegister());
       // Fall through.
       case UsePositionType::kAny:
         InstructionOperand::ReplaceWith(pos->operand(), &op);
@@ -820,20 +808,6 @@
   return LifetimePosition::Invalid();
 }
 
-
-unsigned LiveRange::GetSize() {
-  if (size_ == kInvalidSize) {
-    size_ = 0;
-    for (const UseInterval* interval = first_interval(); interval != nullptr;
-         interval = interval->next()) {
-      size_ += (interval->end().value() - interval->start().value());
-    }
-  }
-
-  return static_cast<unsigned>(size_);
-}
-
-
 void LiveRange::Print(const RegisterConfiguration* config,
                       bool with_children) const {
   OFStream os(stdout);
@@ -848,9 +822,7 @@
 
 
 void LiveRange::Print(bool with_children) const {
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
-  Print(config, with_children);
+  Print(RegisterConfiguration::Turbofan(), with_children);
 }
 
 
@@ -1282,12 +1254,6 @@
   parent->SetSpillRange(this);
 }
 
-
-int SpillRange::ByteWidth() const {
-  return GetByteWidth(live_ranges_[0]->representation());
-}
-
-
 bool SpillRange::IsIntersectingWith(SpillRange* other) const {
   if (this->use_interval_ == nullptr || other->use_interval_ == nullptr ||
       this->End() <= other->use_interval_->start() ||
@@ -1390,7 +1356,6 @@
   }
 }
 
-
 RegisterAllocationData::RegisterAllocationData(
     const RegisterConfiguration* config, Zone* zone, Frame* frame,
     InstructionSequence* code, const char* debug_name)
@@ -1400,16 +1365,14 @@
       debug_name_(debug_name),
       config_(config),
       phi_map_(allocation_zone()),
-      allocatable_codes_(this->config()->num_general_registers(), -1,
-                         allocation_zone()),
-      allocatable_double_codes_(this->config()->num_double_registers(), -1,
-                                allocation_zone()),
       live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()),
       live_out_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()),
       live_ranges_(code->VirtualRegisterCount() * 2, nullptr,
                    allocation_zone()),
       fixed_live_ranges_(this->config()->num_general_registers(), nullptr,
                          allocation_zone()),
+      fixed_float_live_ranges_(this->config()->num_float_registers(), nullptr,
+                               allocation_zone()),
       fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr,
                                 allocation_zone()),
       spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()),
@@ -1418,10 +1381,6 @@
       assigned_double_registers_(nullptr),
       virtual_register_count_(code->VirtualRegisterCount()),
       preassigned_slot_ranges_(zone) {
-  DCHECK(this->config()->num_general_registers() <=
-         RegisterConfiguration::kMaxGeneralRegisters);
-  DCHECK(this->config()->num_double_registers() <=
-         RegisterConfiguration::kMaxDoubleRegisters);
   assigned_registers_ = new (code_zone())
       BitVector(this->config()->num_general_registers(), code_zone());
   assigned_double_registers_ = new (code_zone())
@@ -1589,17 +1548,32 @@
   return spill_range;
 }
 
-
-void RegisterAllocationData::MarkAllocated(RegisterKind kind, int index) {
-  if (kind == DOUBLE_REGISTERS) {
-    assigned_double_registers_->Add(index);
-  } else {
-    DCHECK(kind == GENERAL_REGISTERS);
-    assigned_registers_->Add(index);
+void RegisterAllocationData::MarkAllocated(MachineRepresentation rep,
+                                           int index) {
+  switch (rep) {
+    case MachineRepresentation::kFloat32:
+      if (kSimpleFPAliasing) {
+        assigned_double_registers_->Add(index);
+      } else {
+        int alias_base_index = -1;
+        int aliases = config()->GetAliases(
+            rep, index, MachineRepresentation::kFloat64, &alias_base_index);
+        while (aliases--) {
+          int aliased_reg = alias_base_index + aliases;
+          assigned_double_registers_->Add(aliased_reg);
+        }
+      }
+      break;
+    case MachineRepresentation::kFloat64:
+      assigned_double_registers_->Add(index);
+      break;
+    default:
+      DCHECK(!IsFloatingPoint(rep));
+      assigned_registers_->Add(index);
+      break;
   }
 }
 
-
 bool RegisterAllocationData::IsBlockBoundary(LifetimePosition pos) const {
   return pos.IsFullStart() &&
          code()->GetInstructionBlock(pos.ToInstructionIndex())->code_start() ==
@@ -1628,7 +1602,7 @@
     DCHECK(!IsFloatingPoint(rep));
     allocated = AllocatedOperand(AllocatedOperand::REGISTER, rep,
                                  operand->fixed_register_index());
-  } else if (operand->HasFixedDoubleRegisterPolicy()) {
+  } else if (operand->HasFixedFPRegisterPolicy()) {
     DCHECK(IsFloatingPoint(rep));
     DCHECK_NE(InstructionOperand::kInvalidVirtualRegister, virtual_register);
     allocated = AllocatedOperand(AllocatedOperand::REGISTER, rep,
@@ -1913,42 +1887,62 @@
   }
 }
 
-
-int LiveRangeBuilder::FixedDoubleLiveRangeID(int index) {
-  return -index - 1 - config()->num_general_registers();
+int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) {
+  switch (rep) {
+    case MachineRepresentation::kFloat32:
+      return -index - 1 - config()->num_general_registers();
+    case MachineRepresentation::kFloat64:
+      return -index - 1 - config()->num_general_registers() -
+             config()->num_float_registers();
+    default:
+      break;
+  }
+  UNREACHABLE();
+  return 0;
 }
 
-
 TopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) {
   DCHECK(index < config()->num_general_registers());
   TopLevelLiveRange* result = data()->fixed_live_ranges()[index];
   if (result == nullptr) {
-    result = data()->NewLiveRange(FixedLiveRangeID(index),
-                                  InstructionSequence::DefaultRepresentation());
+    MachineRepresentation rep = InstructionSequence::DefaultRepresentation();
+    result = data()->NewLiveRange(FixedLiveRangeID(index), rep);
     DCHECK(result->IsFixed());
     result->set_assigned_register(index);
-    data()->MarkAllocated(GENERAL_REGISTERS, index);
+    data()->MarkAllocated(rep, index);
     data()->fixed_live_ranges()[index] = result;
   }
   return result;
 }
 
-
-TopLevelLiveRange* LiveRangeBuilder::FixedDoubleLiveRangeFor(int index) {
-  DCHECK(index < config()->num_double_registers());
-  TopLevelLiveRange* result = data()->fixed_double_live_ranges()[index];
-  if (result == nullptr) {
-    result = data()->NewLiveRange(FixedDoubleLiveRangeID(index),
-                                  MachineRepresentation::kFloat64);
-    DCHECK(result->IsFixed());
-    result->set_assigned_register(index);
-    data()->MarkAllocated(DOUBLE_REGISTERS, index);
-    data()->fixed_double_live_ranges()[index] = result;
+TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor(
+    int index, MachineRepresentation rep) {
+  TopLevelLiveRange* result = nullptr;
+  if (rep == MachineRepresentation::kFloat64) {
+    DCHECK(index < config()->num_double_registers());
+    result = data()->fixed_double_live_ranges()[index];
+    if (result == nullptr) {
+      result = data()->NewLiveRange(FixedFPLiveRangeID(index, rep), rep);
+      DCHECK(result->IsFixed());
+      result->set_assigned_register(index);
+      data()->MarkAllocated(rep, index);
+      data()->fixed_double_live_ranges()[index] = result;
+    }
+  } else {
+    DCHECK(rep == MachineRepresentation::kFloat32);
+    DCHECK(index < config()->num_float_registers());
+    result = data()->fixed_float_live_ranges()[index];
+    if (result == nullptr) {
+      result = data()->NewLiveRange(FixedFPLiveRangeID(index, rep), rep);
+      DCHECK(result->IsFixed());
+      result->set_assigned_register(index);
+      data()->MarkAllocated(rep, index);
+      data()->fixed_float_live_ranges()[index] = result;
+    }
   }
   return result;
 }
 
-
 TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) {
   if (operand->IsUnallocated()) {
     return data()->GetOrCreateLiveRangeFor(
@@ -1959,9 +1953,9 @@
   } else if (operand->IsRegister()) {
     return FixedLiveRangeFor(
         LocationOperand::cast(operand)->GetRegister().code());
-  } else if (operand->IsDoubleRegister()) {
-    return FixedDoubleLiveRangeFor(
-        LocationOperand::cast(operand)->GetDoubleRegister().code());
+  } else if (operand->IsFPRegister()) {
+    LocationOperand* op = LocationOperand::cast(operand);
+    return FixedFPLiveRangeFor(op->register_code(), op->representation());
   } else {
     return nullptr;
   }
@@ -2057,7 +2051,7 @@
     if (instr->ClobbersRegisters()) {
       for (int i = 0; i < config()->num_allocatable_general_registers(); ++i) {
         int code = config()->GetAllocatableGeneralCode(i);
-        if (!IsOutputRegisterOf(instr, Register::from_code(code))) {
+        if (!IsOutputRegisterOf(instr, code)) {
           TopLevelLiveRange* range = FixedLiveRangeFor(code);
           range->AddUseInterval(curr_position, curr_position.End(),
                                 allocation_zone());
@@ -2066,15 +2060,29 @@
     }
 
     if (instr->ClobbersDoubleRegisters()) {
-      for (int i = 0; i < config()->num_allocatable_aliased_double_registers();
-           ++i) {
+      for (int i = 0; i < config()->num_allocatable_double_registers(); ++i) {
         int code = config()->GetAllocatableDoubleCode(i);
-        if (!IsOutputDoubleRegisterOf(instr, DoubleRegister::from_code(code))) {
-          TopLevelLiveRange* range = FixedDoubleLiveRangeFor(code);
+        if (!IsOutputFPRegisterOf(instr, MachineRepresentation::kFloat64,
+                                  code)) {
+          TopLevelLiveRange* range =
+              FixedFPLiveRangeFor(code, MachineRepresentation::kFloat64);
           range->AddUseInterval(curr_position, curr_position.End(),
                                 allocation_zone());
         }
       }
+      // Preserve fixed float registers on archs with non-simple aliasing.
+      if (!kSimpleFPAliasing) {
+        for (int i = 0; i < config()->num_allocatable_float_registers(); ++i) {
+          int code = config()->GetAllocatableFloatCode(i);
+          if (!IsOutputFPRegisterOf(instr, MachineRepresentation::kFloat32,
+                                    code)) {
+            TopLevelLiveRange* range =
+                FixedFPLiveRangeFor(code, MachineRepresentation::kFloat32);
+            range->AddUseInterval(curr_position, curr_position.End(),
+                                  allocation_zone());
+          }
+        }
+      }
     }
 
     for (size_t i = 0; i < instr->InputCount(); i++) {
@@ -2194,23 +2202,24 @@
     // block.
     int phi_vreg = phi->virtual_register();
     live->Remove(phi_vreg);
-    InstructionOperand* hint = nullptr;
+    // Select the hint from the first predecessor block that preceeds this block
+    // in the rpo ordering. Prefer non-deferred blocks. The enforcement of
+    // hinting in rpo order is required because hint resolution that happens
+    // later in the compiler pipeline visits instructions in reverse rpo,
+    // relying on the fact that phis are encountered before their hints.
+    const Instruction* instr = nullptr;
     const InstructionBlock::Predecessors& predecessors = block->predecessors();
-    const InstructionBlock* predecessor_block =
-        code()->InstructionBlockAt(predecessors[0]);
-    const Instruction* instr = GetLastInstruction(code(), predecessor_block);
-    if (predecessor_block->IsDeferred()) {
-      // "Prefer the hint from the first non-deferred predecessor, if any.
-      for (size_t i = 1; i < predecessors.size(); ++i) {
-        predecessor_block = code()->InstructionBlockAt(predecessors[i]);
-        if (!predecessor_block->IsDeferred()) {
-          instr = GetLastInstruction(code(), predecessor_block);
-          break;
-        }
+    for (size_t i = 0; i < predecessors.size(); ++i) {
+      const InstructionBlock* predecessor_block =
+          code()->InstructionBlockAt(predecessors[i]);
+      if (predecessor_block->rpo_number() < block->rpo_number()) {
+        instr = GetLastInstruction(code(), predecessor_block);
+        if (!predecessor_block->IsDeferred()) break;
       }
     }
     DCHECK_NOT_NULL(instr);
 
+    InstructionOperand* hint = nullptr;
     for (MoveOperands* move : *instr->GetParallelMove(Instruction::END)) {
       InstructionOperand& to = move->destination();
       if (to.IsUnallocated() &&
@@ -2418,7 +2427,6 @@
       allocatable_register_codes_(
           GetAllocatableRegisterCodes(data->config(), kind)) {}
 
-
 LifetimePosition RegisterAllocator::GetSplitPositionForInstruction(
     const LiveRange* range, int instruction_index) {
   LifetimePosition ret = LifetimePosition::Invalid();
@@ -2587,14 +2595,6 @@
   range->Spill();
 }
 
-
-const ZoneVector<TopLevelLiveRange*>& RegisterAllocator::GetFixedRegisters()
-    const {
-  return mode() == DOUBLE_REGISTERS ? data()->fixed_double_live_ranges()
-                                    : data()->fixed_live_ranges();
-}
-
-
 const char* RegisterAllocator::RegisterName(int register_code) const {
   if (mode() == GENERAL_REGISTERS) {
     return data()->config()->GetGeneralRegisterName(register_code);
@@ -2616,7 +2616,7 @@
   inactive_live_ranges().reserve(8);
   // TryAllocateFreeReg and AllocateBlockedReg assume this
   // when allocating local arrays.
-  DCHECK(RegisterConfiguration::kMaxDoubleRegisters >=
+  DCHECK(RegisterConfiguration::kMaxFPRegisters >=
          this->data()->config()->num_general_registers());
 }
 
@@ -2641,11 +2641,16 @@
   SortUnhandled();
   DCHECK(UnhandledIsSorted());
 
-  auto& fixed_ranges = GetFixedRegisters();
-  for (TopLevelLiveRange* current : fixed_ranges) {
-    if (current != nullptr) {
-      DCHECK_EQ(mode(), current->kind());
-      AddToInactive(current);
+  if (mode() == GENERAL_REGISTERS) {
+    for (TopLevelLiveRange* current : data()->fixed_live_ranges()) {
+      if (current != nullptr) AddToInactive(current);
+    }
+  } else {
+    for (TopLevelLiveRange* current : data()->fixed_float_live_ranges()) {
+      if (current != nullptr) AddToInactive(current);
+    }
+    for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) {
+      if (current != nullptr) AddToInactive(current);
     }
   }
 
@@ -2699,7 +2704,7 @@
 
 void LinearScanAllocator::SetLiveRangeAssignedRegister(LiveRange* range,
                                                        int reg) {
-  data()->MarkAllocated(range->kind(), reg);
+  data()->MarkAllocated(range->representation(), reg);
   range->set_assigned_register(reg);
   range->SetUseHints(reg);
   if (range->IsTopLevel() && range->TopLevel()->is_phi()) {
@@ -2813,18 +2818,37 @@
 
 
 bool LinearScanAllocator::TryAllocateFreeReg(LiveRange* current) {
-  LifetimePosition free_until_pos[RegisterConfiguration::kMaxDoubleRegisters];
-
-  for (int i = 0; i < num_registers(); i++) {
+  int num_regs = num_registers();
+  int num_codes = num_allocatable_registers();
+  const int* codes = allocatable_register_codes();
+  if (!kSimpleFPAliasing &&
+      (current->representation() == MachineRepresentation::kFloat32)) {
+    num_regs = data()->config()->num_float_registers();
+    num_codes = data()->config()->num_allocatable_float_registers();
+    codes = data()->config()->allocatable_float_codes();
+  }
+  LifetimePosition free_until_pos[RegisterConfiguration::kMaxFPRegisters];
+  for (int i = 0; i < num_regs; i++) {
     free_until_pos[i] = LifetimePosition::MaxPosition();
   }
 
   for (LiveRange* cur_active : active_live_ranges()) {
-    free_until_pos[cur_active->assigned_register()] =
-        LifetimePosition::GapFromInstructionIndex(0);
-    TRACE("Register %s is free until pos %d (1)\n",
-          RegisterName(cur_active->assigned_register()),
-          LifetimePosition::GapFromInstructionIndex(0).value());
+    int cur_reg = cur_active->assigned_register();
+    if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
+      free_until_pos[cur_reg] = LifetimePosition::GapFromInstructionIndex(0);
+      TRACE("Register %s is free until pos %d (1)\n", RegisterName(cur_reg),
+            LifetimePosition::GapFromInstructionIndex(0).value());
+    } else {
+      int alias_base_index = -1;
+      int aliases = data()->config()->GetAliases(
+          cur_active->representation(), cur_reg, current->representation(),
+          &alias_base_index);
+      while (aliases--) {
+        int aliased_reg = alias_base_index + aliases;
+        free_until_pos[aliased_reg] =
+            LifetimePosition::GapFromInstructionIndex(0);
+      }
+    }
   }
 
   for (LiveRange* cur_inactive : inactive_live_ranges()) {
@@ -2833,9 +2857,21 @@
         cur_inactive->FirstIntersection(current);
     if (!next_intersection.IsValid()) continue;
     int cur_reg = cur_inactive->assigned_register();
-    free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection);
-    TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg),
-          Min(free_until_pos[cur_reg], next_intersection).value());
+    if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
+      free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection);
+      TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg),
+            Min(free_until_pos[cur_reg], next_intersection).value());
+    } else {
+      int alias_base_index = -1;
+      int aliases = data()->config()->GetAliases(
+          cur_inactive->representation(), cur_reg, current->representation(),
+          &alias_base_index);
+      while (aliases--) {
+        int aliased_reg = alias_base_index + aliases;
+        free_until_pos[aliased_reg] =
+            Min(free_until_pos[aliased_reg], next_intersection);
+      }
+    }
   }
 
   int hint_register;
@@ -2857,9 +2893,9 @@
   }
 
   // Find the register which stays free for the longest time.
-  int reg = allocatable_register_code(0);
-  for (int i = 1; i < num_allocatable_registers(); ++i) {
-    int code = allocatable_register_code(i);
+  int reg = codes[0];
+  for (int i = 1; i < num_codes; ++i) {
+    int code = codes[i];
     if (free_until_pos[code] > free_until_pos[reg]) {
       reg = code;
     }
@@ -2879,8 +2915,8 @@
     AddToUnhandledSorted(tail);
   }
 
-  // Register reg is available at the range start and is free until
-  // the range end.
+  // Register reg is available at the range start and is free until the range
+  // end.
   DCHECK(pos >= current->End());
   TRACE("Assigning free reg %s to live range %d:%d\n", RegisterName(reg),
         current->TopLevel()->vreg(), current->relative_id());
@@ -2899,26 +2935,58 @@
     return;
   }
 
-  LifetimePosition use_pos[RegisterConfiguration::kMaxDoubleRegisters];
-  LifetimePosition block_pos[RegisterConfiguration::kMaxDoubleRegisters];
+  int num_regs = num_registers();
+  int num_codes = num_allocatable_registers();
+  const int* codes = allocatable_register_codes();
+  if (!kSimpleFPAliasing &&
+      (current->representation() == MachineRepresentation::kFloat32)) {
+    num_regs = data()->config()->num_float_registers();
+    num_codes = data()->config()->num_allocatable_float_registers();
+    codes = data()->config()->allocatable_float_codes();
+  }
 
-  for (int i = 0; i < num_registers(); i++) {
+  LifetimePosition use_pos[RegisterConfiguration::kMaxFPRegisters];
+  LifetimePosition block_pos[RegisterConfiguration::kMaxFPRegisters];
+  for (int i = 0; i < num_regs; i++) {
     use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition();
   }
 
   for (LiveRange* range : active_live_ranges()) {
     int cur_reg = range->assigned_register();
-    if (range->TopLevel()->IsFixed() ||
-        !range->CanBeSpilled(current->Start())) {
-      block_pos[cur_reg] = use_pos[cur_reg] =
-          LifetimePosition::GapFromInstructionIndex(0);
-    } else {
-      UsePosition* next_use =
-          range->NextUsePositionRegisterIsBeneficial(current->Start());
-      if (next_use == nullptr) {
-        use_pos[cur_reg] = range->End();
+    bool is_fixed_or_cant_spill =
+        range->TopLevel()->IsFixed() || !range->CanBeSpilled(current->Start());
+    if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
+      if (is_fixed_or_cant_spill) {
+        block_pos[cur_reg] = use_pos[cur_reg] =
+            LifetimePosition::GapFromInstructionIndex(0);
       } else {
-        use_pos[cur_reg] = next_use->pos();
+        UsePosition* next_use =
+            range->NextUsePositionRegisterIsBeneficial(current->Start());
+        if (next_use == nullptr) {
+          use_pos[cur_reg] = range->End();
+        } else {
+          use_pos[cur_reg] = next_use->pos();
+        }
+      }
+    } else {
+      int alias_base_index = -1;
+      int aliases = data()->config()->GetAliases(
+          range->representation(), cur_reg, current->representation(),
+          &alias_base_index);
+      while (aliases--) {
+        int aliased_reg = alias_base_index + aliases;
+        if (is_fixed_or_cant_spill) {
+          block_pos[aliased_reg] = use_pos[aliased_reg] =
+              LifetimePosition::GapFromInstructionIndex(0);
+        } else {
+          UsePosition* next_use =
+              range->NextUsePositionRegisterIsBeneficial(current->Start());
+          if (next_use == nullptr) {
+            use_pos[aliased_reg] = range->End();
+          } else {
+            use_pos[aliased_reg] = next_use->pos();
+          }
+        }
       }
     }
   }
@@ -2928,17 +2996,36 @@
     LifetimePosition next_intersection = range->FirstIntersection(current);
     if (!next_intersection.IsValid()) continue;
     int cur_reg = range->assigned_register();
-    if (range->TopLevel()->IsFixed()) {
-      block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection);
-      use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]);
+    bool is_fixed = range->TopLevel()->IsFixed();
+    if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
+      if (is_fixed) {
+        block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection);
+        use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]);
+      } else {
+        use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection);
+      }
     } else {
-      use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection);
+      int alias_base_index = -1;
+      int aliases = data()->config()->GetAliases(
+          range->representation(), cur_reg, current->representation(),
+          &alias_base_index);
+      while (aliases--) {
+        int aliased_reg = alias_base_index + aliases;
+        if (is_fixed) {
+          block_pos[aliased_reg] =
+              Min(block_pos[aliased_reg], next_intersection);
+          use_pos[aliased_reg] =
+              Min(block_pos[aliased_reg], use_pos[aliased_reg]);
+        } else {
+          use_pos[aliased_reg] = Min(use_pos[aliased_reg], next_intersection);
+        }
+      }
     }
   }
 
-  int reg = allocatable_register_code(0);
-  for (int i = 1; i < num_allocatable_registers(); ++i) {
-    int code = allocatable_register_code(i);
+  int reg = codes[0];
+  for (int i = 1; i < num_codes; ++i) {
+    int code = codes[i];
     if (use_pos[code] > use_pos[reg]) {
       reg = code;
     }
@@ -2947,9 +3034,13 @@
   LifetimePosition pos = use_pos[reg];
 
   if (pos < register_use->pos()) {
-    // All registers are blocked before the first use that requires a register.
-    // Spill starting part of live range up to that use.
-    SpillBetween(current, current->Start(), register_use->pos());
+    if (LifetimePosition::ExistsGapPositionBetween(current->Start(),
+                                                   register_use->pos())) {
+      SpillBetween(current, current->Start(), register_use->pos());
+    } else {
+      SetLiveRangeAssignedRegister(current, reg);
+      SplitAndSpillIntersecting(current);
+    }
     return;
   }
 
@@ -2980,43 +3071,61 @@
   LifetimePosition split_pos = current->Start();
   for (size_t i = 0; i < active_live_ranges().size(); ++i) {
     LiveRange* range = active_live_ranges()[i];
-    if (range->assigned_register() == reg) {
-      UsePosition* next_pos = range->NextRegisterPosition(current->Start());
-      LifetimePosition spill_pos = FindOptimalSpillingPos(range, split_pos);
-      if (next_pos == nullptr) {
-        SpillAfter(range, spill_pos);
-      } else {
-        // When spilling between spill_pos and next_pos ensure that the range
-        // remains spilled at least until the start of the current live range.
-        // This guarantees that we will not introduce new unhandled ranges that
-        // start before the current range as this violates allocation invariant
-        // and will lead to an inconsistent state of active and inactive
-        // live-ranges: ranges are allocated in order of their start positions,
-        // ranges are retired from active/inactive when the start of the
-        // current live-range is larger than their end.
-        SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos());
+    if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
+      if (range->assigned_register() != reg) continue;
+    } else {
+      if (!data()->config()->AreAliases(current->representation(), reg,
+                                        range->representation(),
+                                        range->assigned_register())) {
+        continue;
       }
-      ActiveToHandled(range);
-      --i;
     }
+
+    UsePosition* next_pos = range->NextRegisterPosition(current->Start());
+    LifetimePosition spill_pos = FindOptimalSpillingPos(range, split_pos);
+    if (next_pos == nullptr) {
+      SpillAfter(range, spill_pos);
+    } else {
+      // When spilling between spill_pos and next_pos ensure that the range
+      // remains spilled at least until the start of the current live range.
+      // This guarantees that we will not introduce new unhandled ranges that
+      // start before the current range as this violates allocation invariants
+      // and will lead to an inconsistent state of active and inactive
+      // live-ranges: ranges are allocated in order of their start positions,
+      // ranges are retired from active/inactive when the start of the
+      // current live-range is larger than their end.
+      DCHECK(LifetimePosition::ExistsGapPositionBetween(current->Start(),
+                                                        next_pos->pos()));
+      SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos());
+    }
+    ActiveToHandled(range);
+    --i;
   }
 
   for (size_t i = 0; i < inactive_live_ranges().size(); ++i) {
     LiveRange* range = inactive_live_ranges()[i];
     DCHECK(range->End() > current->Start());
-    if (range->assigned_register() == reg && !range->TopLevel()->IsFixed()) {
-      LifetimePosition next_intersection = range->FirstIntersection(current);
-      if (next_intersection.IsValid()) {
-        UsePosition* next_pos = range->NextRegisterPosition(current->Start());
-        if (next_pos == nullptr) {
-          SpillAfter(range, split_pos);
-        } else {
-          next_intersection = Min(next_intersection, next_pos->pos());
-          SpillBetween(range, split_pos, next_intersection);
-        }
-        InactiveToHandled(range);
-        --i;
+    if (range->TopLevel()->IsFixed()) continue;
+    if (kSimpleFPAliasing || mode() == GENERAL_REGISTERS) {
+      if (range->assigned_register() != reg) continue;
+    } else {
+      if (!data()->config()->AreAliases(current->representation(), reg,
+                                        range->representation(),
+                                        range->assigned_register()))
+        continue;
+    }
+
+    LifetimePosition next_intersection = range->FirstIntersection(current);
+    if (next_intersection.IsValid()) {
+      UsePosition* next_pos = range->NextRegisterPosition(current->Start());
+      if (next_pos == nullptr) {
+        SpillAfter(range, split_pos);
+      } else {
+        next_intersection = Min(next_intersection, next_pos->pos());
+        SpillBetween(range, split_pos, next_intersection);
       }
+      InactiveToHandled(range);
+      --i;
     }
   }
 }
@@ -3092,7 +3201,7 @@
             ? range->TopLevel()->GetSpillRange()
             : data()->AssignSpillRangeToLiveRange(range->TopLevel());
     bool merged = first_op_spill->TryMerge(spill_range);
-    CHECK(merged);
+    if (!merged) return false;
     Spill(range);
     return true;
   } else if (pos->pos() > range->Start().NextStart()) {
@@ -3101,7 +3210,7 @@
             ? range->TopLevel()->GetSpillRange()
             : data()->AssignSpillRangeToLiveRange(range->TopLevel());
     bool merged = first_op_spill->TryMerge(spill_range);
-    CHECK(merged);
+    if (!merged) return false;
     SpillBetween(range, range->Start(), pos->pos());
     DCHECK(UnhandledIsSorted());
     return true;
@@ -3196,8 +3305,7 @@
     if (range == nullptr || range->IsEmpty()) continue;
     // Allocate a new operand referring to the spill slot.
     if (!range->HasSlot()) {
-      int byte_width = range->ByteWidth();
-      int index = data()->frame()->AllocateSpillSlot(byte_width);
+      int index = data()->frame()->AllocateSpillSlot(range->byte_width());
       range->set_assigned_slot(index);
     }
   }
@@ -3405,7 +3513,8 @@
     BitVector* live = live_in_sets[block->rpo_number().ToInt()];
     BitVector::Iterator iterator(live);
     while (!iterator.Done()) {
-      LiveRangeBoundArray* array = finder.ArrayFor(iterator.Current());
+      int vreg = iterator.Current();
+      LiveRangeBoundArray* array = finder.ArrayFor(vreg);
       for (const RpoNumber& pred : block->predecessors()) {
         FindResult result;
         const InstructionBlock* pred_block = code()->InstructionBlockAt(pred);
@@ -3622,6 +3731,7 @@
     worklist.push(iterator.Current());
   }
 
+  ZoneSet<std::pair<RpoNumber, int>> done_moves(temp_zone);
   // Seek the deferred blocks that dominate locations requiring spill operands,
   // and spill there. We only need to spill at the start of such blocks.
   BitVector done_blocks(
@@ -3648,10 +3758,15 @@
 
         InstructionOperand pred_op = bound->range_->GetAssignedOperand();
 
-        data()->AddGapMove(spill_block->first_instruction_index(),
-                           Instruction::GapPosition::START, pred_op,
-                           spill_operand);
-        spill_block->mark_needs_frame();
+        RpoNumber spill_block_number = spill_block->rpo_number();
+        if (done_moves.find(std::make_pair(
+                spill_block_number, range->vreg())) == done_moves.end()) {
+          data()->AddGapMove(spill_block->first_instruction_index(),
+                             Instruction::GapPosition::START, pred_op,
+                             spill_operand);
+          done_moves.insert(std::make_pair(spill_block_number, range->vreg()));
+          spill_block->mark_needs_frame();
+        }
       }
     }
   }
diff --git a/src/compiler/register-allocator.h b/src/compiler/register-allocator.h
index d6ed005..caadcba 100644
--- a/src/compiler/register-allocator.h
+++ b/src/compiler/register-allocator.h
@@ -14,11 +14,7 @@
 namespace internal {
 namespace compiler {
 
-enum RegisterKind {
-  GENERAL_REGISTERS,
-  DOUBLE_REGISTERS
-};
-
+enum RegisterKind { GENERAL_REGISTERS, FP_REGISTERS };
 
 // This class represents a single point of a InstructionOperand's lifetime. For
 // each instruction there are four lifetime positions:
@@ -46,6 +42,14 @@
     return LifetimePosition(index * kStep + kHalfStep);
   }
 
+  static bool ExistsGapPositionBetween(LifetimePosition pos1,
+                                       LifetimePosition pos2) {
+    if (pos1 > pos2) std::swap(pos1, pos2);
+    LifetimePosition next(pos1.value_ + 1);
+    if (next.IsGapPosition()) return next < pos2;
+    return next.NextFullStart() < pos2;
+  }
+
   // Returns a numeric representation of this lifetime position.
   int value() const { return value_; }
 
@@ -238,11 +242,9 @@
 static const int32_t kUnassignedRegister =
     RegisterConfiguration::kMaxGeneralRegisters;
 
-
-static_assert(kUnassignedRegister <= RegisterConfiguration::kMaxDoubleRegisters,
+static_assert(kUnassignedRegister <= RegisterConfiguration::kMaxFPRegisters,
               "kUnassignedRegister too small");
 
-
 // Representation of a use position.
 class UsePosition final : public ZoneObject {
  public:
@@ -410,19 +412,9 @@
   void SetUseHints(int register_index);
   void UnsetUseHints() { SetUseHints(kUnassignedRegister); }
 
-  // Used solely by the Greedy Allocator:
-  unsigned GetSize();
-  float weight() const { return weight_; }
-  void set_weight(float weight) { weight_ = weight; }
-  LiveRangeGroup* group() const { return group_; }
-  void set_group(LiveRangeGroup* group) { group_ = group; }
   void Print(const RegisterConfiguration* config, bool with_children) const;
   void Print(bool with_children) const;
 
-  static const int kInvalidSize = -1;
-  static const float kInvalidWeight;
-  static const float kMaxWeight;
-
  private:
   friend class TopLevelLiveRange;
   explicit LiveRange(int relative_id, MachineRepresentation rep,
@@ -459,17 +451,6 @@
   mutable UsePosition* current_hint_position_;
   // Cache the last position splintering stopped at.
   mutable UsePosition* splitting_pointer_;
-  // greedy: the number of LifetimePositions covered by this range. Used to
-  // prioritize selecting live ranges for register assignment, as well as
-  // in weight calculations.
-  int size_;
-
-  // greedy: a metric for resolving conflicts between ranges with an assigned
-  // register and ranges that intersect them and need a register.
-  float weight_;
-
-  // greedy: groupping
-  LiveRangeGroup* group_;
 
   DISALLOW_COPY_AND_ASSIGN(LiveRange);
 };
@@ -481,7 +462,6 @@
   ZoneVector<LiveRange*>& ranges() { return ranges_; }
   const ZoneVector<LiveRange*>& ranges() const { return ranges_; }
 
-  // TODO(mtrofin): populate assigned register and use in weight calculation.
   int assigned_register() const { return assigned_register_; }
   void set_assigned_register(int reg) { assigned_register_ = reg; }
 
@@ -698,8 +678,7 @@
   SpillRange(TopLevelLiveRange* range, Zone* zone);
 
   UseInterval* interval() const { return use_interval_; }
-  // Currently, only 4 or 8 byte slots are supported.
-  int ByteWidth() const;
+
   bool IsEmpty() const { return live_ranges_.empty(); }
   bool TryMerge(SpillRange* other);
   bool HasSlot() const { return assigned_slot_ != kUnassignedSlot; }
@@ -788,6 +767,12 @@
   ZoneVector<TopLevelLiveRange*>& fixed_live_ranges() {
     return fixed_live_ranges_;
   }
+  ZoneVector<TopLevelLiveRange*>& fixed_float_live_ranges() {
+    return fixed_float_live_ranges_;
+  }
+  const ZoneVector<TopLevelLiveRange*>& fixed_float_live_ranges() const {
+    return fixed_float_live_ranges_;
+  }
   ZoneVector<TopLevelLiveRange*>& fixed_double_live_ranges() {
     return fixed_double_live_ranges_;
   }
@@ -799,7 +784,7 @@
   ZoneVector<SpillRange*>& spill_ranges() { return spill_ranges_; }
   DelayedReferences& delayed_references() { return delayed_references_; }
   InstructionSequence* code() const { return code_; }
-  // This zone is for datastructures only needed during register allocation
+  // This zone is for data structures only needed during register allocation
   // phases.
   Zone* allocation_zone() const { return allocation_zone_; }
   // This zone is for InstructionOperands and moves that live beyond register
@@ -830,7 +815,7 @@
   bool ExistsUseWithoutDefinition();
   bool RangesDefinedInDeferredStayInDeferred();
 
-  void MarkAllocated(RegisterKind kind, int index);
+  void MarkAllocated(MachineRepresentation rep, int index);
 
   PhiMapValue* InitializePhiMap(const InstructionBlock* block,
                                 PhiInstruction* phi);
@@ -851,12 +836,11 @@
   const char* const debug_name_;
   const RegisterConfiguration* const config_;
   PhiMap phi_map_;
-  ZoneVector<int> allocatable_codes_;
-  ZoneVector<int> allocatable_double_codes_;
   ZoneVector<BitVector*> live_in_sets_;
   ZoneVector<BitVector*> live_out_sets_;
   ZoneVector<TopLevelLiveRange*> live_ranges_;
   ZoneVector<TopLevelLiveRange*> fixed_live_ranges_;
+  ZoneVector<TopLevelLiveRange*> fixed_float_live_ranges_;
   ZoneVector<TopLevelLiveRange*> fixed_double_live_ranges_;
   ZoneVector<SpillRange*> spill_ranges_;
   DelayedReferences delayed_references_;
@@ -933,9 +917,9 @@
   void ProcessLoopHeader(const InstructionBlock* block, BitVector* live);
 
   static int FixedLiveRangeID(int index) { return -index - 1; }
-  int FixedDoubleLiveRangeID(int index);
+  int FixedFPLiveRangeID(int index, MachineRepresentation rep);
   TopLevelLiveRange* FixedLiveRangeFor(int index);
-  TopLevelLiveRange* FixedDoubleLiveRangeFor(int index);
+  TopLevelLiveRange* FixedFPLiveRangeFor(int index, MachineRepresentation rep);
 
   void MapPhiHint(InstructionOperand* operand, UsePosition* use_pos);
   void ResolvePhiHint(InstructionOperand* operand, UsePosition* use_pos);
@@ -969,7 +953,7 @@
 
 class RegisterAllocator : public ZoneObject {
  public:
-  explicit RegisterAllocator(RegisterAllocationData* data, RegisterKind kind);
+  RegisterAllocator(RegisterAllocationData* data, RegisterKind kind);
 
  protected:
   RegisterAllocationData* data() const { return data_; }
@@ -977,8 +961,8 @@
   RegisterKind mode() const { return mode_; }
   int num_registers() const { return num_registers_; }
   int num_allocatable_registers() const { return num_allocatable_registers_; }
-  int allocatable_register_code(int allocatable_index) const {
-    return allocatable_register_codes_[allocatable_index];
+  const int* allocatable_register_codes() const {
+    return allocatable_register_codes_;
   }
 
   // TODO(mtrofin): explain why splitting in gap START is always OK.
@@ -1031,6 +1015,9 @@
   int num_allocatable_registers_;
   const int* allocatable_register_codes_;
 
+ private:
+  bool no_combining_;
+
   DISALLOW_COPY_AND_ASSIGN(RegisterAllocator);
 };
 
diff --git a/src/compiler/representation-change.cc b/src/compiler/representation-change.cc
index f59c8bc..d1aa5af 100644
--- a/src/compiler/representation-change.cc
+++ b/src/compiler/representation-change.cc
@@ -105,46 +105,55 @@
 
 }  // namespace
 
-
 // Changes representation from {output_rep} to {use_rep}. The {truncation}
 // parameter is only used for sanity checking - if the changer cannot figure
 // out signedness for the word32->float64 conversion, then we check that the
 // uses truncate to word32 (so they do not care about signedness).
 Node* RepresentationChanger::GetRepresentationFor(
     Node* node, MachineRepresentation output_rep, Type* output_type,
-    MachineRepresentation use_rep, Truncation truncation) {
+    Node* use_node, UseInfo use_info) {
   if (output_rep == MachineRepresentation::kNone) {
     // The output representation should be set.
-    return TypeError(node, output_rep, output_type, use_rep);
+    return TypeError(node, output_rep, output_type, use_info.representation());
   }
-  if (use_rep == output_rep) {
-    // Representations are the same. That's a no-op.
-    return node;
+
+  // Handle the no-op shortcuts when no checking is necessary.
+  if (use_info.type_check() == TypeCheckKind::kNone ||
+      output_rep != MachineRepresentation::kWord32) {
+    if (use_info.representation() == output_rep) {
+      // Representations are the same. That's a no-op.
+      return node;
+    }
+    if (IsWord(use_info.representation()) && IsWord(output_rep)) {
+      // Both are words less than or equal to 32-bits.
+      // Since loads of integers from memory implicitly sign or zero extend the
+      // value to the full machine word size and stores implicitly truncate,
+      // no representation change is necessary.
+      return node;
+    }
   }
-  if (IsWord(use_rep) && IsWord(output_rep)) {
-    // Both are words less than or equal to 32-bits.
-    // Since loads of integers from memory implicitly sign or zero extend the
-    // value to the full machine word size and stores implicitly truncate,
-    // no representation change is necessary.
-    return node;
-  }
-  switch (use_rep) {
+
+  switch (use_info.representation()) {
     case MachineRepresentation::kTagged:
+      DCHECK(use_info.type_check() == TypeCheckKind::kNone);
       return GetTaggedRepresentationFor(node, output_rep, output_type);
     case MachineRepresentation::kFloat32:
+      DCHECK(use_info.type_check() == TypeCheckKind::kNone);
       return GetFloat32RepresentationFor(node, output_rep, output_type,
-                                         truncation);
+                                         use_info.truncation());
     case MachineRepresentation::kFloat64:
       return GetFloat64RepresentationFor(node, output_rep, output_type,
-                                         truncation);
+                                         use_node, use_info);
     case MachineRepresentation::kBit:
+      DCHECK(use_info.type_check() == TypeCheckKind::kNone);
       return GetBitRepresentationFor(node, output_rep, output_type);
     case MachineRepresentation::kWord8:
     case MachineRepresentation::kWord16:
     case MachineRepresentation::kWord32:
-      return GetWord32RepresentationFor(node, output_rep, output_type,
-                                        truncation);
+      return GetWord32RepresentationFor(node, output_rep, output_type, use_node,
+                                        use_info);
     case MachineRepresentation::kWord64:
+      DCHECK(use_info.type_check() == TypeCheckKind::kNone);
       return GetWord64RepresentationFor(node, output_rep, output_type);
     case MachineRepresentation::kSimd128:  // Fall through.
       // TODO(bbudge) Handle conversions between tagged and untagged.
@@ -156,7 +165,6 @@
   return nullptr;
 }
 
-
 Node* RepresentationChanger::GetTaggedRepresentationFor(
     Node* node, MachineRepresentation output_rep, Type* output_type) {
   // Eagerly fold representation changes for constants.
@@ -188,12 +196,14 @@
   // Select the correct X -> Tagged operator.
   const Operator* op;
   if (output_rep == MachineRepresentation::kBit) {
-    op = simplified()->ChangeBitToBool();
+    op = simplified()->ChangeBitToTagged();
   } else if (IsWord(output_rep)) {
-    if (output_type->Is(Type::Unsigned32())) {
-      op = simplified()->ChangeUint32ToTagged();
+    if (output_type->Is(Type::Signed31())) {
+      op = simplified()->ChangeInt31ToTaggedSigned();
     } else if (output_type->Is(Type::Signed32())) {
       op = simplified()->ChangeInt32ToTagged();
+    } else if (output_type->Is(Type::Unsigned32())) {
+      op = simplified()->ChangeUint32ToTagged();
     } else {
       return TypeError(node, output_rep, output_type,
                        MachineRepresentation::kTagged);
@@ -201,9 +211,24 @@
   } else if (output_rep ==
              MachineRepresentation::kFloat32) {  // float32 -> float64 -> tagged
     node = InsertChangeFloat32ToFloat64(node);
+    // TODO(bmeurer): Pass -0 hint to ChangeFloat64ToTagged.
     op = simplified()->ChangeFloat64ToTagged();
   } else if (output_rep == MachineRepresentation::kFloat64) {
-    op = simplified()->ChangeFloat64ToTagged();
+    if (output_type->Is(Type::Signed31())) {  // float64 -> int32 -> tagged
+      node = InsertChangeFloat64ToInt32(node);
+      op = simplified()->ChangeInt31ToTaggedSigned();
+    } else if (output_type->Is(
+                   Type::Signed32())) {  // float64 -> int32 -> tagged
+      node = InsertChangeFloat64ToInt32(node);
+      op = simplified()->ChangeInt32ToTagged();
+    } else if (output_type->Is(
+                   Type::Unsigned32())) {  // float64 -> uint32 -> tagged
+      node = InsertChangeFloat64ToUint32(node);
+      op = simplified()->ChangeUint32ToTagged();
+    } else {
+      // TODO(bmeurer): Pass -0 hint to ChangeFloat64ToTagged.
+      op = simplified()->ChangeFloat64ToTagged();
+    }
   } else {
     return TypeError(node, output_rep, output_type,
                      MachineRepresentation::kTagged);
@@ -253,9 +278,13 @@
       op = machine()->TruncateFloat64ToFloat32();
     }
   } else if (output_rep == MachineRepresentation::kTagged) {
-    if (output_type->Is(Type::Number())) {
-      op = simplified()
-               ->ChangeTaggedToFloat64();  // tagged -> float64 -> float32
+    if (output_type->Is(Type::NumberOrUndefined())) {
+      // tagged -> float64 -> float32
+      if (output_type->Is(Type::Number())) {
+        op = simplified()->ChangeTaggedToFloat64();
+      } else {
+        op = simplified()->TruncateTaggedToFloat64();
+      }
       node = jsgraph()->graph()->NewNode(op, node);
       op = machine()->TruncateFloat64ToFloat32();
     }
@@ -269,29 +298,31 @@
   return jsgraph()->graph()->NewNode(op, node);
 }
 
-
 Node* RepresentationChanger::GetFloat64RepresentationFor(
     Node* node, MachineRepresentation output_rep, Type* output_type,
-    Truncation truncation) {
+    Node* use_node, UseInfo use_info) {
   // Eagerly fold representation changes for constants.
-  switch (node->opcode()) {
-    case IrOpcode::kNumberConstant:
-      return jsgraph()->Float64Constant(OpParameter<double>(node));
-    case IrOpcode::kInt32Constant:
-      if (output_type->Is(Type::Signed32())) {
-        int32_t value = OpParameter<int32_t>(node);
-        return jsgraph()->Float64Constant(value);
-      } else {
-        DCHECK(output_type->Is(Type::Unsigned32()));
-        uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
-        return jsgraph()->Float64Constant(static_cast<double>(value));
-      }
-    case IrOpcode::kFloat64Constant:
-      return node;  // No change necessary.
-    case IrOpcode::kFloat32Constant:
-      return jsgraph()->Float64Constant(OpParameter<float>(node));
-    default:
-      break;
+  if ((use_info.type_check() == TypeCheckKind::kNone)) {
+    // TODO(jarin) Handle checked constant conversions.
+    switch (node->opcode()) {
+      case IrOpcode::kNumberConstant:
+        return jsgraph()->Float64Constant(OpParameter<double>(node));
+      case IrOpcode::kInt32Constant:
+        if (output_type->Is(Type::Signed32())) {
+          int32_t value = OpParameter<int32_t>(node);
+          return jsgraph()->Float64Constant(value);
+        } else {
+          DCHECK(output_type->Is(Type::Unsigned32()));
+          uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
+          return jsgraph()->Float64Constant(static_cast<double>(value));
+        }
+      case IrOpcode::kFloat64Constant:
+        return node;  // No change necessary.
+      case IrOpcode::kFloat32Constant:
+        return jsgraph()->Float64Constant(OpParameter<float>(node));
+      default:
+        break;
+    }
   }
   // Select the correct X -> Float64 operator.
   const Operator* op = nullptr;
@@ -299,14 +330,25 @@
     if (output_type->Is(Type::Signed32())) {
       op = machine()->ChangeInt32ToFloat64();
     } else if (output_type->Is(Type::Unsigned32()) ||
-               truncation.TruncatesToWord32()) {
+               use_info.truncation().TruncatesToWord32()) {
       // Either the output is uint32 or the uses only care about the
       // low 32 bits (so we can pick uint32 safely).
       op = machine()->ChangeUint32ToFloat64();
     }
   } else if (output_rep == MachineRepresentation::kTagged) {
-    if (output_type->Is(Type::Number())) {
+    if (output_type->Is(Type::Undefined())) {
+      return jsgraph()->Float64Constant(
+          std::numeric_limits<double>::quiet_NaN());
+    } else if (output_type->Is(Type::TaggedSigned())) {
+      node = InsertChangeTaggedSignedToInt32(node);
+      op = machine()->ChangeInt32ToFloat64();
+    } else if (output_type->Is(Type::Number())) {
       op = simplified()->ChangeTaggedToFloat64();
+    } else if (output_type->Is(Type::NumberOrUndefined())) {
+      // TODO(jarin) Here we should check that truncation is Number.
+      op = simplified()->TruncateTaggedToFloat64();
+    } else if (use_info.type_check() == TypeCheckKind::kNumberOrUndefined) {
+      op = simplified()->CheckedTaggedToFloat64();
     }
   } else if (output_rep == MachineRepresentation::kFloat32) {
     op = machine()->ChangeFloat32ToFloat64();
@@ -315,29 +357,43 @@
     return TypeError(node, output_rep, output_type,
                      MachineRepresentation::kFloat64);
   }
-  return jsgraph()->graph()->NewNode(op, node);
+  return InsertConversion(node, op, use_node);
 }
 
-
 Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) {
   return jsgraph()->Int32Constant(DoubleToInt32(value));
 }
 
 Node* RepresentationChanger::GetWord32RepresentationFor(
     Node* node, MachineRepresentation output_rep, Type* output_type,
-    Truncation truncation) {
+    Node* use_node, UseInfo use_info) {
   // Eagerly fold representation changes for constants.
   switch (node->opcode()) {
     case IrOpcode::kInt32Constant:
       return node;  // No change necessary.
-    case IrOpcode::kFloat32Constant:
-      return MakeTruncatedInt32Constant(OpParameter<float>(node));
+    case IrOpcode::kFloat32Constant: {
+      float const fv = OpParameter<float>(node);
+      if (use_info.type_check() == TypeCheckKind::kNone ||
+          (use_info.type_check() == TypeCheckKind::kSigned32 &&
+           IsInt32Double(fv))) {
+        return MakeTruncatedInt32Constant(fv);
+      }
+      break;
+    }
     case IrOpcode::kNumberConstant:
-    case IrOpcode::kFloat64Constant:
-      return MakeTruncatedInt32Constant(OpParameter<double>(node));
+    case IrOpcode::kFloat64Constant: {
+      double const fv = OpParameter<double>(node);
+      if (use_info.type_check() == TypeCheckKind::kNone ||
+          (use_info.type_check() == TypeCheckKind::kSigned32 &&
+           IsInt32Double(fv))) {
+        return MakeTruncatedInt32Constant(fv);
+      }
+      break;
+    }
     default:
       break;
   }
+
   // Select the correct X -> Word32 operator.
   const Operator* op = nullptr;
   if (output_rep == MachineRepresentation::kBit) {
@@ -347,8 +403,10 @@
       op = machine()->ChangeFloat64ToUint32();
     } else if (output_type->Is(Type::Signed32())) {
       op = machine()->ChangeFloat64ToInt32();
-    } else if (truncation.TruncatesToWord32()) {
-      op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
+    } else if (use_info.truncation().TruncatesToWord32()) {
+      op = machine()->TruncateFloat64ToWord32();
+    } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
+      op = simplified()->CheckedFloat64ToInt32();
     }
   } else if (output_rep == MachineRepresentation::kFloat32) {
     node = InsertChangeFloat32ToFloat64(node);  // float32 -> float64 -> int32
@@ -356,23 +414,57 @@
       op = machine()->ChangeFloat64ToUint32();
     } else if (output_type->Is(Type::Signed32())) {
       op = machine()->ChangeFloat64ToInt32();
-    } else if (truncation.TruncatesToWord32()) {
-      op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
+    } else if (use_info.truncation().TruncatesToWord32()) {
+      op = machine()->TruncateFloat64ToWord32();
+    } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
+      op = simplified()->CheckedFloat64ToInt32();
     }
   } else if (output_rep == MachineRepresentation::kTagged) {
-    if (output_type->Is(Type::Unsigned32())) {
+    if (output_type->Is(Type::TaggedSigned())) {
+      op = simplified()->ChangeTaggedSignedToInt32();
+    } else if (output_type->Is(Type::Unsigned32())) {
       op = simplified()->ChangeTaggedToUint32();
     } else if (output_type->Is(Type::Signed32())) {
       op = simplified()->ChangeTaggedToInt32();
-    } else if (truncation.TruncatesToWord32()) {
-      node = InsertChangeTaggedToFloat64(node);
-      op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
+    } else if (use_info.truncation().TruncatesToWord32()) {
+      op = simplified()->TruncateTaggedToWord32();
+    } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
+      op = simplified()->CheckedTaggedToInt32();
     }
+  } else if (output_rep == MachineRepresentation::kWord32) {
+    // Only the checked case should get here, the non-checked case is
+    // handled in GetRepresentationFor.
+    DCHECK(use_info.type_check() == TypeCheckKind::kSigned32);
+    if (output_type->Is(Type::Signed32())) {
+      return node;
+    } else if (output_type->Is(Type::Unsigned32())) {
+      op = simplified()->CheckedUint32ToInt32();
+    }
+  } else if (output_rep == MachineRepresentation::kWord8 ||
+             output_rep == MachineRepresentation::kWord16) {
+    DCHECK(use_info.representation() == MachineRepresentation::kWord32);
+    DCHECK(use_info.type_check() == TypeCheckKind::kSigned32);
+    return node;
   }
+
   if (op == nullptr) {
     return TypeError(node, output_rep, output_type,
                      MachineRepresentation::kWord32);
   }
+  return InsertConversion(node, op, use_node);
+}
+
+Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op,
+                                              Node* use_node) {
+  if (op->ControlInputCount() > 0) {
+    // If the operator can deoptimize (which means it has control
+    // input), we need to connect it to the effect and control chains.
+    Node* effect = NodeProperties::GetEffectInput(use_node);
+    Node* control = NodeProperties::GetControlInput(use_node);
+    Node* conversion = jsgraph()->graph()->NewNode(op, node, effect, control);
+    NodeProperties::ReplaceEffectInput(use_node, conversion);
+    return conversion;
+  }
   return jsgraph()->graph()->NewNode(op, node);
 }
 
@@ -394,7 +486,7 @@
   // Select the correct X -> Bit operator.
   const Operator* op;
   if (output_rep == MachineRepresentation::kTagged) {
-    op = simplified()->ChangeBoolToBit();
+    op = simplified()->ChangeTaggedToBit();
   } else {
     return TypeError(node, output_rep, output_type,
                      MachineRepresentation::kBit);
@@ -402,7 +494,6 @@
   return jsgraph()->graph()->NewNode(op, node);
 }
 
-
 Node* RepresentationChanger::GetWord64RepresentationFor(
     Node* node, MachineRepresentation output_rep, Type* output_type) {
   if (output_rep == MachineRepresentation::kBit) {
@@ -413,18 +504,90 @@
                    MachineRepresentation::kWord64);
 }
 
+Node* RepresentationChanger::GetCheckedWord32RepresentationFor(
+    Node* node, MachineRepresentation output_rep, Type* output_type,
+    Node* use_node, Truncation truncation, TypeCheckKind check) {
+  // TODO(jarin) Eagerly fold constants (or insert hard deopt if the constant
+  // does not pass the check).
+
+  // If the input is already Signed32 in Word32 representation, we do not
+  // have to do anything. (We could fold this into the big if below, but
+  // it feels nicer to have the shortcut return first).
+  if (output_rep == MachineRepresentation::kWord32 ||
+      output_type->Is(Type::Signed32())) {
+    return node;
+  }
+
+  // Select the correct X -> Word32 operator.
+  const Operator* op = nullptr;
+  if (output_rep == MachineRepresentation::kWord32) {
+    if (output_type->Is(Type::Unsigned32())) {
+      op = simplified()->CheckedUint32ToInt32();
+    }
+  } else if (output_rep == MachineRepresentation::kBit) {
+    return node;  // Sloppy comparison -> word32
+  } else if (output_rep == MachineRepresentation::kFloat64) {
+    if (output_type->Is(Type::Unsigned32())) {
+      op = machine()->ChangeFloat64ToUint32();
+    } else if (output_type->Is(Type::Signed32())) {
+      op = machine()->ChangeFloat64ToInt32();
+    } else if (truncation.TruncatesToWord32()) {
+      op = machine()->TruncateFloat64ToWord32();
+    } else if (check == TypeCheckKind::kSigned32) {
+      op = simplified()->CheckedFloat64ToInt32();
+    }
+  } else if (output_rep == MachineRepresentation::kFloat32) {
+    node = InsertChangeFloat32ToFloat64(node);  // float32 -> float64 -> int32
+    if (output_type->Is(Type::Unsigned32())) {
+      op = machine()->ChangeFloat64ToUint32();
+    } else if (output_type->Is(Type::Signed32())) {
+      op = machine()->ChangeFloat64ToInt32();
+    } else if (truncation.TruncatesToWord32()) {
+      op = machine()->TruncateFloat64ToWord32();
+    } else if (check == TypeCheckKind::kSigned32) {
+      op = simplified()->CheckedFloat64ToInt32();
+    }
+  } else if (output_rep == MachineRepresentation::kTagged) {
+    if (output_type->Is(Type::TaggedSigned())) {
+      op = simplified()->ChangeTaggedSignedToInt32();
+    } else if (output_type->Is(Type::Unsigned32())) {
+      op = simplified()->ChangeTaggedToUint32();
+    } else if (output_type->Is(Type::Signed32())) {
+      op = simplified()->ChangeTaggedToInt32();
+    } else if (truncation.TruncatesToWord32()) {
+      op = simplified()->TruncateTaggedToWord32();
+    } else if (check == TypeCheckKind::kSigned32) {
+      op = simplified()->CheckedTaggedToInt32();
+    }
+  }
+  if (op == nullptr) {
+    return TypeError(node, output_rep, output_type,
+                     MachineRepresentation::kWord32);
+  }
+  if (op->ControlInputCount() > 0) {
+    // If the operator can deoptimize (which means it has control
+    // input), we need to connect it to the effect and control chains.
+    UNIMPLEMENTED();
+  }
+  return jsgraph()->graph()->NewNode(op, node);
+}
 
 const Operator* RepresentationChanger::Int32OperatorFor(
     IrOpcode::Value opcode) {
   switch (opcode) {
+    case IrOpcode::kSpeculativeNumberAdd:  // Fall through.
     case IrOpcode::kNumberAdd:
       return machine()->Int32Add();
+    case IrOpcode::kSpeculativeNumberSubtract:  // Fall through.
     case IrOpcode::kNumberSubtract:
       return machine()->Int32Sub();
+    case IrOpcode::kSpeculativeNumberMultiply:
     case IrOpcode::kNumberMultiply:
       return machine()->Int32Mul();
+    case IrOpcode::kSpeculativeNumberDivide:
     case IrOpcode::kNumberDivide:
       return machine()->Int32Div();
+    case IrOpcode::kSpeculativeNumberModulus:
     case IrOpcode::kNumberModulus:
       return machine()->Int32Mod();
     case IrOpcode::kNumberBitwiseOr:
@@ -434,10 +597,13 @@
     case IrOpcode::kNumberBitwiseAnd:
       return machine()->Word32And();
     case IrOpcode::kNumberEqual:
+    case IrOpcode::kSpeculativeNumberEqual:
       return machine()->Word32Equal();
     case IrOpcode::kNumberLessThan:
+    case IrOpcode::kSpeculativeNumberLessThan:
       return machine()->Int32LessThan();
     case IrOpcode::kNumberLessThanOrEqual:
+    case IrOpcode::kSpeculativeNumberLessThanOrEqual:
       return machine()->Int32LessThanOrEqual();
     default:
       UNREACHABLE();
@@ -445,6 +611,18 @@
   }
 }
 
+const Operator* RepresentationChanger::Int32OverflowOperatorFor(
+    IrOpcode::Value opcode) {
+  switch (opcode) {
+    case IrOpcode::kSpeculativeNumberAdd:  // Fall through.
+      return simplified()->CheckedInt32Add();
+    case IrOpcode::kSpeculativeNumberSubtract:  // Fall through.
+      return simplified()->CheckedInt32Sub();
+    default:
+      UNREACHABLE();
+      return nullptr;
+  }
+}
 
 const Operator* RepresentationChanger::Uint32OperatorFor(
     IrOpcode::Value opcode) {
@@ -453,17 +631,23 @@
       return machine()->Int32Add();
     case IrOpcode::kNumberSubtract:
       return machine()->Int32Sub();
+    case IrOpcode::kSpeculativeNumberMultiply:
     case IrOpcode::kNumberMultiply:
       return machine()->Int32Mul();
+    case IrOpcode::kSpeculativeNumberDivide:
     case IrOpcode::kNumberDivide:
       return machine()->Uint32Div();
+    case IrOpcode::kSpeculativeNumberModulus:
     case IrOpcode::kNumberModulus:
       return machine()->Uint32Mod();
     case IrOpcode::kNumberEqual:
+    case IrOpcode::kSpeculativeNumberEqual:
       return machine()->Word32Equal();
     case IrOpcode::kNumberLessThan:
+    case IrOpcode::kSpeculativeNumberLessThan:
       return machine()->Uint32LessThan();
     case IrOpcode::kNumberLessThanOrEqual:
+    case IrOpcode::kSpeculativeNumberLessThanOrEqual:
       return machine()->Uint32LessThanOrEqual();
     case IrOpcode::kNumberClz32:
       return machine()->Word32Clz();
@@ -479,22 +663,64 @@
 const Operator* RepresentationChanger::Float64OperatorFor(
     IrOpcode::Value opcode) {
   switch (opcode) {
+    case IrOpcode::kSpeculativeNumberAdd:
     case IrOpcode::kNumberAdd:
       return machine()->Float64Add();
+    case IrOpcode::kSpeculativeNumberSubtract:
     case IrOpcode::kNumberSubtract:
       return machine()->Float64Sub();
+    case IrOpcode::kSpeculativeNumberMultiply:
     case IrOpcode::kNumberMultiply:
       return machine()->Float64Mul();
+    case IrOpcode::kSpeculativeNumberDivide:
     case IrOpcode::kNumberDivide:
       return machine()->Float64Div();
+    case IrOpcode::kSpeculativeNumberModulus:
     case IrOpcode::kNumberModulus:
       return machine()->Float64Mod();
     case IrOpcode::kNumberEqual:
+    case IrOpcode::kSpeculativeNumberEqual:
       return machine()->Float64Equal();
     case IrOpcode::kNumberLessThan:
+    case IrOpcode::kSpeculativeNumberLessThan:
       return machine()->Float64LessThan();
     case IrOpcode::kNumberLessThanOrEqual:
+    case IrOpcode::kSpeculativeNumberLessThanOrEqual:
       return machine()->Float64LessThanOrEqual();
+    case IrOpcode::kNumberAbs:
+      return machine()->Float64Abs();
+    case IrOpcode::kNumberAtan:
+      return machine()->Float64Atan();
+    case IrOpcode::kNumberAtan2:
+      return machine()->Float64Atan2();
+    case IrOpcode::kNumberCos:
+      return machine()->Float64Cos();
+    case IrOpcode::kNumberExp:
+      return machine()->Float64Exp();
+    case IrOpcode::kNumberFround:
+      return machine()->TruncateFloat64ToFloat32();
+    case IrOpcode::kNumberAtanh:
+      return machine()->Float64Atanh();
+    case IrOpcode::kNumberLog:
+      return machine()->Float64Log();
+    case IrOpcode::kNumberLog1p:
+      return machine()->Float64Log1p();
+    case IrOpcode::kNumberLog2:
+      return machine()->Float64Log2();
+    case IrOpcode::kNumberLog10:
+      return machine()->Float64Log10();
+    case IrOpcode::kNumberSin:
+      return machine()->Float64Sin();
+    case IrOpcode::kNumberTan:
+      return machine()->Float64Tan();
+    case IrOpcode::kNumberSqrt:
+      return machine()->Float64Sqrt();
+    case IrOpcode::kNumberCbrt:
+      return machine()->Float64Cbrt();
+    case IrOpcode::kNumberExpm1:
+      return machine()->Float64Expm1();
+    case IrOpcode::kNumberSilenceNaN:
+      return machine()->Float64SilenceNaN();
     default:
       UNREACHABLE();
       return nullptr;
@@ -530,6 +756,18 @@
   return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node);
 }
 
+Node* RepresentationChanger::InsertChangeFloat64ToUint32(Node* node) {
+  return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToUint32(), node);
+}
+
+Node* RepresentationChanger::InsertChangeFloat64ToInt32(Node* node) {
+  return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToInt32(), node);
+}
+
+Node* RepresentationChanger::InsertChangeTaggedSignedToInt32(Node* node) {
+  return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(),
+                                     node);
+}
 
 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) {
   return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
diff --git a/src/compiler/representation-change.h b/src/compiler/representation-change.h
index 24e28f3..8a38644 100644
--- a/src/compiler/representation-change.h
+++ b/src/compiler/representation-change.h
@@ -31,6 +31,9 @@
   bool TruncatesToWord32() const {
     return LessGeneral(kind_, TruncationKind::kWord32);
   }
+  bool TruncatesToFloat64() const {
+    return LessGeneral(kind_, TruncationKind::kFloat64);
+  }
   bool TruncatesNaNToZero() {
     return LessGeneral(kind_, TruncationKind::kWord32) ||
            LessGeneral(kind_, TruncationKind::kBool);
@@ -70,6 +73,86 @@
   static bool LessGeneral(TruncationKind rep1, TruncationKind rep2);
 };
 
+enum class TypeCheckKind : uint8_t {
+  kNone,
+  kSigned32,
+  kNumberOrUndefined,
+  kNumber
+};
+
+// The {UseInfo} class is used to describe a use of an input of a node.
+//
+// This information is used in two different ways, based on the phase:
+//
+// 1. During propagation, the use info is used to inform the input node
+//    about what part of the input is used (we call this truncation) and what
+//    is the preferred representation.
+//
+// 2. During lowering, the use info is used to properly convert the input
+//    to the preferred representation. The preferred representation might be
+//    insufficient to do the conversion (e.g. word32->float64 conv), so we also
+//    need the signedness information to produce the correct value.
+class UseInfo {
+ public:
+  UseInfo(MachineRepresentation representation, Truncation truncation,
+          TypeCheckKind type_check = TypeCheckKind::kNone)
+      : representation_(representation),
+        truncation_(truncation),
+        type_check_(type_check) {}
+  static UseInfo TruncatingWord32() {
+    return UseInfo(MachineRepresentation::kWord32, Truncation::Word32());
+  }
+  static UseInfo TruncatingWord64() {
+    return UseInfo(MachineRepresentation::kWord64, Truncation::Word64());
+  }
+  static UseInfo Bool() {
+    return UseInfo(MachineRepresentation::kBit, Truncation::Bool());
+  }
+  static UseInfo TruncatingFloat32() {
+    return UseInfo(MachineRepresentation::kFloat32, Truncation::Float32());
+  }
+  static UseInfo TruncatingFloat64() {
+    return UseInfo(MachineRepresentation::kFloat64, Truncation::Float64());
+  }
+  static UseInfo PointerInt() {
+    return kPointerSize == 4 ? TruncatingWord32() : TruncatingWord64();
+  }
+  static UseInfo AnyTagged() {
+    return UseInfo(MachineRepresentation::kTagged, Truncation::Any());
+  }
+
+  // Possibly deoptimizing conversions.
+  static UseInfo CheckedSigned32AsWord32() {
+    return UseInfo(MachineRepresentation::kWord32, Truncation::Any(),
+                   TypeCheckKind::kSigned32);
+  }
+  static UseInfo CheckedNumberOrUndefinedAsFloat64() {
+    return UseInfo(MachineRepresentation::kFloat64, Truncation::Any(),
+                   TypeCheckKind::kNumberOrUndefined);
+  }
+
+  // Undetermined representation.
+  static UseInfo Any() {
+    return UseInfo(MachineRepresentation::kNone, Truncation::Any());
+  }
+  static UseInfo AnyTruncatingToBool() {
+    return UseInfo(MachineRepresentation::kNone, Truncation::Bool());
+  }
+
+  // Value not used.
+  static UseInfo None() {
+    return UseInfo(MachineRepresentation::kNone, Truncation::None());
+  }
+
+  MachineRepresentation representation() const { return representation_; }
+  Truncation truncation() const { return truncation_; }
+  TypeCheckKind type_check() const { return type_check_; }
+
+ private:
+  MachineRepresentation representation_;
+  Truncation truncation_;
+  TypeCheckKind type_check_;
+};
 
 // Contains logic related to changing the representation of values for constants
 // and other nodes, as well as lowering Simplified->Machine operators.
@@ -87,9 +170,10 @@
   // out signedness for the word32->float64 conversion, then we check that the
   // uses truncate to word32 (so they do not care about signedness).
   Node* GetRepresentationFor(Node* node, MachineRepresentation output_rep,
-                             Type* output_type, MachineRepresentation use_rep,
-                             Truncation truncation = Truncation::None());
+                             Type* output_type, Node* use_node,
+                             UseInfo use_info);
   const Operator* Int32OperatorFor(IrOpcode::Value opcode);
+  const Operator* Int32OverflowOperatorFor(IrOpcode::Value opcode);
   const Operator* Uint32OperatorFor(IrOpcode::Value opcode);
   const Operator* Float64OperatorFor(IrOpcode::Value opcode);
 
@@ -119,19 +203,31 @@
                                     Type* output_type, Truncation truncation);
   Node* GetFloat64RepresentationFor(Node* node,
                                     MachineRepresentation output_rep,
-                                    Type* output_type, Truncation truncation);
+                                    Type* output_type, Node* use_node,
+                                    UseInfo use_info);
   Node* GetWord32RepresentationFor(Node* node, MachineRepresentation output_rep,
-                                   Type* output_type, Truncation truncation);
+                                   Type* output_type, Node* use_node,
+                                   UseInfo use_info);
   Node* GetBitRepresentationFor(Node* node, MachineRepresentation output_rep,
                                 Type* output_type);
   Node* GetWord64RepresentationFor(Node* node, MachineRepresentation output_rep,
                                    Type* output_type);
+  Node* GetCheckedWord32RepresentationFor(Node* node,
+                                          MachineRepresentation output_rep,
+                                          Type* output_type, Node* use_node,
+                                          Truncation truncation,
+                                          TypeCheckKind check);
   Node* TypeError(Node* node, MachineRepresentation output_rep,
                   Type* output_type, MachineRepresentation use);
   Node* MakeTruncatedInt32Constant(double value);
   Node* InsertChangeFloat32ToFloat64(Node* node);
+  Node* InsertChangeFloat64ToInt32(Node* node);
+  Node* InsertChangeFloat64ToUint32(Node* node);
+  Node* InsertChangeTaggedSignedToInt32(Node* node);
   Node* InsertChangeTaggedToFloat64(Node* node);
 
+  Node* InsertConversion(Node* node, const Operator* op, Node* use_node);
+
   JSGraph* jsgraph() const { return jsgraph_; }
   Isolate* isolate() const { return isolate_; }
   Factory* factory() const { return isolate()->factory(); }
diff --git a/src/compiler/s390/OWNERS b/src/compiler/s390/OWNERS
index eb007cb..752e8e3 100644
--- a/src/compiler/s390/OWNERS
+++ b/src/compiler/s390/OWNERS
@@ -3,3 +3,4 @@
 joransiu@ca.ibm.com
 mbrandy@us.ibm.com
 michael_dawson@ca.ibm.com
+bjaideep@ca.ibm.com
diff --git a/src/compiler/s390/code-generator-s390.cc b/src/compiler/s390/code-generator-s390.cc
index 1d96856..ac24529 100644
--- a/src/compiler/s390/code-generator-s390.cc
+++ b/src/compiler/s390/code-generator-s390.cc
@@ -67,8 +67,8 @@
 
   MemOperand MemoryOperand(AddressingMode* mode, size_t* first_index) {
     const size_t index = *first_index;
-    *mode = AddressingModeField::decode(instr_->opcode());
-    switch (*mode) {
+    if (mode) *mode = AddressingModeField::decode(instr_->opcode());
+    switch (AddressingModeField::decode(instr_->opcode())) {
       case kMode_None:
         break;
       case kMode_MRI:
@@ -82,13 +82,14 @@
     return MemOperand(r0);
   }
 
-  MemOperand MemoryOperand(AddressingMode* mode, size_t first_index = 0) {
+  MemOperand MemoryOperand(AddressingMode* mode = NULL,
+                           size_t first_index = 0) {
     return MemoryOperand(mode, &first_index);
   }
 
   MemOperand ToMemOperand(InstructionOperand* op) const {
     DCHECK_NOT_NULL(op);
-    DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
+    DCHECK(op->IsStackSlot() || op->IsFPStackSlot());
     return SlotToMemOperand(AllocatedOperand::cast(op)->index());
   }
 
@@ -155,7 +156,8 @@
         value_(value),
         scratch0_(scratch0),
         scratch1_(scratch1),
-        mode_(mode) {}
+        mode_(mode),
+        must_save_lr_(!gen->frame_access_state()->has_frame()) {}
 
   OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t offset,
                        Register value, Register scratch0, Register scratch1,
@@ -236,15 +238,10 @@
 #if V8_TARGET_ARCH_S390X
         case kS390_Add:
         case kS390_Sub:
-          return lt;
 #endif
         case kS390_AddWithOverflow32:
         case kS390_SubWithOverflow32:
-#if V8_TARGET_ARCH_S390X
-          return ne;
-#else
           return lt;
-#endif
         default:
           break;
       }
@@ -254,15 +251,10 @@
 #if V8_TARGET_ARCH_S390X
         case kS390_Add:
         case kS390_Sub:
-          return ge;
 #endif
         case kS390_AddWithOverflow32:
         case kS390_SubWithOverflow32:
-#if V8_TARGET_ARCH_S390X
-          return eq;
-#else
           return ge;
-#endif
         default:
           break;
       }
@@ -332,16 +324,16 @@
   } while (0)
 
 #if V8_TARGET_ARCH_S390X
-#define ASSEMBLE_ADD_WITH_OVERFLOW32()      \
-  do {                                      \
-    ASSEMBLE_BINOP(AddP, AddP);             \
-    __ TestIfInt32(i.OutputRegister(), r0); \
+#define ASSEMBLE_ADD_WITH_OVERFLOW32()                   \
+  do {                                                   \
+    ASSEMBLE_ADD_WITH_OVERFLOW();                        \
+    __ LoadAndTestP_ExtendSrc(kScratchReg, kScratchReg); \
   } while (0)
 
-#define ASSEMBLE_SUB_WITH_OVERFLOW32()      \
-  do {                                      \
-    ASSEMBLE_BINOP(SubP, SubP);             \
-    __ TestIfInt32(i.OutputRegister(), r0); \
+#define ASSEMBLE_SUB_WITH_OVERFLOW32()                   \
+  do {                                                   \
+    ASSEMBLE_SUB_WITH_OVERFLOW();                        \
+    __ LoadAndTestP_ExtendSrc(kScratchReg, kScratchReg); \
   } while (0)
 #else
 #define ASSEMBLE_ADD_WITH_OVERFLOW32 ASSEMBLE_ADD_WITH_OVERFLOW
@@ -393,6 +385,33 @@
     __ MovFromFloatResult(i.OutputDoubleRegister());                          \
   } while (0)
 
+#define ASSEMBLE_IEEE754_UNOP(name)                                            \
+  do {                                                                         \
+    /* TODO(bmeurer): We should really get rid of this special instruction, */ \
+    /* and generate a CallAddress instruction instead. */                      \
+    FrameScope scope(masm(), StackFrame::MANUAL);                              \
+    __ PrepareCallCFunction(0, 1, kScratchReg);                                \
+    __ MovToFloatParameter(i.InputDoubleRegister(0));                          \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()),  \
+                     0, 1);                                                    \
+    /* Move the result in the double result register. */                       \
+    __ MovFromFloatResult(i.OutputDoubleRegister());                           \
+  } while (0)
+
+#define ASSEMBLE_IEEE754_BINOP(name)                                           \
+  do {                                                                         \
+    /* TODO(bmeurer): We should really get rid of this special instruction, */ \
+    /* and generate a CallAddress instruction instead. */                      \
+    FrameScope scope(masm(), StackFrame::MANUAL);                              \
+    __ PrepareCallCFunction(0, 2, kScratchReg);                                \
+    __ MovToFloatParameters(i.InputDoubleRegister(0),                          \
+                            i.InputDoubleRegister(1));                         \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()),  \
+                     0, 2);                                                    \
+    /* Move the result in the double result register. */                       \
+    __ MovFromFloatResult(i.OutputDoubleRegister());                           \
+  } while (0)
+
 #define ASSEMBLE_FLOAT_MAX(double_scratch_reg, general_scratch_reg) \
   do {                                                              \
     Label ge, done;                                                 \
@@ -461,7 +480,6 @@
     __ asm_instr(value, operand);                        \
   } while (0)
 
-// TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits.
 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr, width)              \
   do {                                                             \
     DoubleRegister result = i.OutputDoubleRegister();              \
@@ -469,7 +487,6 @@
     AddressingMode mode = kMode_None;                              \
     MemOperand operand = i.MemoryOperand(&mode, index);            \
     Register offset = operand.rb();                                \
-    __ lgfr(offset, offset);                                       \
     if (HasRegisterInput(instr, 2)) {                              \
       __ CmpLogical32(offset, i.InputRegister(2));                 \
     } else {                                                       \
@@ -477,11 +494,11 @@
     }                                                              \
     auto ool = new (zone()) OutOfLineLoadNAN##width(this, result); \
     __ bge(ool->entry());                                          \
+    __ CleanUInt32(offset);                                        \
     __ asm_instr(result, operand);                                 \
     __ bind(ool->exit());                                          \
   } while (0)
 
-// TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits.
 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr)             \
   do {                                                       \
     Register result = i.OutputRegister();                    \
@@ -489,7 +506,6 @@
     AddressingMode mode = kMode_None;                        \
     MemOperand operand = i.MemoryOperand(&mode, index);      \
     Register offset = operand.rb();                          \
-    __ lgfr(offset, offset);                                 \
     if (HasRegisterInput(instr, 2)) {                        \
       __ CmpLogical32(offset, i.InputRegister(2));           \
     } else {                                                 \
@@ -497,11 +513,11 @@
     }                                                        \
     auto ool = new (zone()) OutOfLineLoadZero(this, result); \
     __ bge(ool->entry());                                    \
+    __ CleanUInt32(offset);                                  \
     __ asm_instr(result, operand);                           \
     __ bind(ool->exit());                                    \
   } while (0)
 
-// TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits.
 #define ASSEMBLE_CHECKED_STORE_FLOAT32()                \
   do {                                                  \
     Label done;                                         \
@@ -509,7 +525,6 @@
     AddressingMode mode = kMode_None;                   \
     MemOperand operand = i.MemoryOperand(&mode, index); \
     Register offset = operand.rb();                     \
-    __ lgfr(offset, offset);                            \
     if (HasRegisterInput(instr, 2)) {                   \
       __ CmpLogical32(offset, i.InputRegister(2));      \
     } else {                                            \
@@ -517,11 +532,11 @@
     }                                                   \
     __ bge(&done);                                      \
     DoubleRegister value = i.InputDoubleRegister(3);    \
+    __ CleanUInt32(offset);                             \
     __ StoreFloat32(value, operand);                    \
     __ bind(&done);                                     \
   } while (0)
 
-// TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits.
 #define ASSEMBLE_CHECKED_STORE_DOUBLE()                 \
   do {                                                  \
     Label done;                                         \
@@ -530,7 +545,6 @@
     MemOperand operand = i.MemoryOperand(&mode, index); \
     DCHECK_EQ(kMode_MRR, mode);                         \
     Register offset = operand.rb();                     \
-    __ lgfr(offset, offset);                            \
     if (HasRegisterInput(instr, 2)) {                   \
       __ CmpLogical32(offset, i.InputRegister(2));      \
     } else {                                            \
@@ -538,11 +552,11 @@
     }                                                   \
     __ bge(&done);                                      \
     DoubleRegister value = i.InputDoubleRegister(3);    \
+    __ CleanUInt32(offset);                             \
     __ StoreDouble(value, operand);                     \
     __ bind(&done);                                     \
   } while (0)
 
-// TODO(mbrandy): fix paths that produce garbage in offset's upper 32-bits.
 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr)       \
   do {                                                  \
     Label done;                                         \
@@ -550,7 +564,6 @@
     AddressingMode mode = kMode_None;                   \
     MemOperand operand = i.MemoryOperand(&mode, index); \
     Register offset = operand.rb();                     \
-    __ lgfr(offset, offset);                            \
     if (HasRegisterInput(instr, 2)) {                   \
       __ CmpLogical32(offset, i.InputRegister(2));      \
     } else {                                            \
@@ -558,6 +571,7 @@
     }                                                   \
     __ bge(&done);                                      \
     Register value = i.InputRegister(3);                \
+    __ CleanUInt32(offset);                             \
     __ asm_instr(value, operand);                       \
     __ bind(&done);                                     \
   } while (0)
@@ -566,8 +580,6 @@
   __ LeaveFrame(StackFrame::MANUAL);
 }
 
-void CodeGenerator::AssembleSetupStackPointer() {}
-
 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
   int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
   if (sp_slot_delta > 0) {
@@ -614,7 +626,8 @@
 }
 
 // Assembles an instruction after register allocation, producing machine code.
-void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
+CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
+    Instruction* instr) {
   S390OperandConverter i(this, instr);
   ArchOpcode opcode = ArchOpcodeField::decode(instr->opcode());
 
@@ -656,6 +669,14 @@
       frame_access_state()->ClearSPDelta();
       break;
     }
+    case kArchTailCallAddress: {
+      int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
+      AssembleDeconstructActivationRecord(stack_param_delta);
+      CHECK(!instr->InputAt(0)->IsImmediate());
+      __ Jump(i.InputRegister(0));
+      frame_access_state()->ClearSPDelta();
+      break;
+    }
     case kArchCallJSFunction: {
       EnsureSpaceForLazyDeopt();
       Register func = i.InputRegister(0);
@@ -726,6 +747,9 @@
     case kArchTableSwitch:
       AssembleArchTableSwitch(instr);
       break;
+    case kArchDebugBreak:
+      __ stop("kArchDebugBreak");
+      break;
     case kArchNop:
     case kArchThrowTerminator:
       // don't emit code for nops.
@@ -735,7 +759,9 @@
           BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
       Deoptimizer::BailoutType bailout_type =
           Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
-      AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      CodeGenResult result =
+          AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      if (result != kSuccess) return result;
       break;
     }
     case kArchRet:
@@ -1220,6 +1246,45 @@
     case kS390_ModDouble:
       ASSEMBLE_FLOAT_MODULO();
       break;
+    case kIeee754Float64Atan:
+      ASSEMBLE_IEEE754_UNOP(atan);
+      break;
+    case kIeee754Float64Atan2:
+      ASSEMBLE_IEEE754_BINOP(atan2);
+      break;
+    case kIeee754Float64Tan:
+      ASSEMBLE_IEEE754_UNOP(tan);
+      break;
+    case kIeee754Float64Cbrt:
+      ASSEMBLE_IEEE754_UNOP(cbrt);
+      break;
+    case kIeee754Float64Sin:
+      ASSEMBLE_IEEE754_UNOP(sin);
+      break;
+    case kIeee754Float64Cos:
+      ASSEMBLE_IEEE754_UNOP(cos);
+      break;
+    case kIeee754Float64Exp:
+      ASSEMBLE_IEEE754_UNOP(exp);
+      break;
+    case kIeee754Float64Expm1:
+      ASSEMBLE_IEEE754_UNOP(expm1);
+      break;
+    case kIeee754Float64Atanh:
+      ASSEMBLE_IEEE754_UNOP(atanh);
+      break;
+    case kIeee754Float64Log:
+      ASSEMBLE_IEEE754_UNOP(log);
+      break;
+    case kIeee754Float64Log1p:
+      ASSEMBLE_IEEE754_UNOP(log1p);
+      break;
+    case kIeee754Float64Log2:
+      ASSEMBLE_IEEE754_UNOP(log2);
+      break;
+    case kIeee754Float64Log10:
+      ASSEMBLE_IEEE754_UNOP(log10);
+      break;
     case kS390_Neg:
       __ LoadComplementRR(i.OutputRegister(), i.InputRegister(0));
       break;
@@ -1305,8 +1370,14 @@
       }
       break;
 #endif
+    case kS390_Float64SilenceNaN: {
+      DoubleRegister value = i.InputDoubleRegister(0);
+      DoubleRegister result = i.OutputDoubleRegister();
+      __ CanonicalizeNaN(result, value);
+      break;
+    }
     case kS390_Push:
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ lay(sp, MemOperand(sp, -kDoubleSize));
         __ StoreDouble(i.InputDoubleRegister(0), MemOperand(sp));
         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
@@ -1318,9 +1389,14 @@
     case kS390_PushFrame: {
       int num_slots = i.InputInt32(1);
       __ lay(sp, MemOperand(sp, -num_slots * kPointerSize));
-      if (instr->InputAt(0)->IsDoubleRegister()) {
-        __ StoreDouble(i.InputDoubleRegister(0),
-                 MemOperand(sp));
+      if (instr->InputAt(0)->IsFPRegister()) {
+        LocationOperand* op = LocationOperand::cast(instr->InputAt(0));
+        if (op->representation() == MachineRepresentation::kFloat64) {
+          __ StoreDouble(i.InputDoubleRegister(0), MemOperand(sp));
+        } else {
+          DCHECK(op->representation() == MachineRepresentation::kFloat32);
+          __ StoreFloat32(i.InputDoubleRegister(0), MemOperand(sp));
+        }
       } else {
         __ StoreP(i.InputRegister(0),
                   MemOperand(sp));
@@ -1329,9 +1405,16 @@
     }
     case kS390_StoreToStackSlot: {
       int slot = i.InputInt32(1);
-      if (instr->InputAt(0)->IsDoubleRegister()) {
-        __ StoreDouble(i.InputDoubleRegister(0),
-                       MemOperand(sp, slot * kPointerSize));
+      if (instr->InputAt(0)->IsFPRegister()) {
+        LocationOperand* op = LocationOperand::cast(instr->InputAt(0));
+        if (op->representation() == MachineRepresentation::kFloat64) {
+          __ StoreDouble(i.InputDoubleRegister(0),
+                         MemOperand(sp, slot * kPointerSize));
+        } else {
+          DCHECK(op->representation() == MachineRepresentation::kFloat32);
+          __ StoreFloat32(i.InputDoubleRegister(0),
+                          MemOperand(sp, slot * kPointerSize));
+        }
       } else {
         __ StoreP(i.InputRegister(0), MemOperand(sp, slot * kPointerSize));
       }
@@ -1555,6 +1638,9 @@
     case kS390_LoadWordS16:
       ASSEMBLE_LOAD_INTEGER(LoadHalfWordP);
       break;
+    case kS390_LoadWordU32:
+      ASSEMBLE_LOAD_INTEGER(LoadlW);
+      break;
     case kS390_LoadWordS32:
       ASSEMBLE_LOAD_INTEGER(LoadW);
       break;
@@ -1607,7 +1693,7 @@
       ASSEMBLE_CHECKED_LOAD_INTEGER(LoadLogicalHalfWordP);
       break;
     case kCheckedLoadWord32:
-      ASSEMBLE_CHECKED_LOAD_INTEGER(LoadW);
+      ASSEMBLE_CHECKED_LOAD_INTEGER(LoadlW);
       break;
     case kCheckedLoadWord64:
 #if V8_TARGET_ARCH_S390X
@@ -1644,10 +1730,35 @@
     case kCheckedStoreFloat64:
       ASSEMBLE_CHECKED_STORE_DOUBLE();
       break;
+    case kAtomicLoadInt8:
+      __ LoadB(i.OutputRegister(), i.MemoryOperand());
+      break;
+    case kAtomicLoadUint8:
+      __ LoadlB(i.OutputRegister(), i.MemoryOperand());
+      break;
+    case kAtomicLoadInt16:
+      __ LoadHalfWordP(i.OutputRegister(), i.MemoryOperand());
+      break;
+    case kAtomicLoadUint16:
+      __ LoadLogicalHalfWordP(i.OutputRegister(), i.MemoryOperand());
+      break;
+    case kAtomicLoadWord32:
+      __ LoadlW(i.OutputRegister(), i.MemoryOperand());
+      break;
+    case kAtomicStoreWord8:
+      __ StoreByte(i.InputRegister(0), i.MemoryOperand(NULL, 1));
+      break;
+    case kAtomicStoreWord16:
+      __ StoreHalfWord(i.InputRegister(0), i.MemoryOperand(NULL, 1));
+      break;
+    case kAtomicStoreWord32:
+      __ StoreW(i.InputRegister(0), i.MemoryOperand(NULL, 1));
+      break;
     default:
       UNREACHABLE();
       break;
   }
+  return kSuccess;
 }  // NOLINT(readability/fn_size)
 
 // Assembles branches after an instruction.
@@ -1744,7 +1855,7 @@
   S390OperandConverter i(this, instr);
   Register input = i.InputRegister(0);
   for (size_t index = 2; index < instr->InputCount(); index += 2) {
-    __ CmpP(input, Operand(i.InputInt32(index + 0)));
+    __ Cmp32(input, Operand(i.InputInt32(index + 0)));
     __ beq(GetLabel(i.InputRpo(index + 1)));
   }
   AssembleArchJump(i.InputRpo(1));
@@ -1767,17 +1878,41 @@
   __ Jump(kScratchReg);
 }
 
-void CodeGenerator::AssembleDeoptimizerCall(
+CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
     int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
   Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
       isolate(), deoptimization_id, bailout_type);
   // TODO(turbofan): We should be able to generate better code by sharing the
   // actual final call site and just bl'ing to it here, similar to what we do
   // in the lithium backend.
+  if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
   __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
+  return kSuccess;
 }
 
-void CodeGenerator::AssemblePrologue() {
+void CodeGenerator::FinishFrame(Frame* frame) {
+  CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
+  const RegList double_saves = descriptor->CalleeSavedFPRegisters();
+
+  // Save callee-saved Double registers.
+  if (double_saves != 0) {
+    frame->AlignSavedCalleeRegisterSlots();
+    DCHECK(kNumCalleeSavedDoubles ==
+           base::bits::CountPopulation32(double_saves));
+    frame->AllocateSavedCalleeRegisterSlots(kNumCalleeSavedDoubles *
+                                            (kDoubleSize / kPointerSize));
+  }
+  // Save callee-saved registers.
+  const RegList saves = descriptor->CalleeSavedRegisters();
+  if (saves != 0) {
+    // register save area does not include the fp or constant pool pointer.
+    const int num_saves = kNumCalleeSaved - 1;
+    DCHECK(num_saves == base::bits::CountPopulation32(saves));
+    frame->AllocateSavedCalleeRegisterSlots(num_saves);
+  }
+}
+
+void CodeGenerator::AssembleConstructFrame() {
   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
 
   if (frame_access_state()->has_frame()) {
@@ -1794,7 +1929,7 @@
     }
   }
 
-  int stack_shrink_slots = frame()->GetSpillSlotCount();
+  int shrink_slots = frame()->GetSpillSlotCount();
   if (info()->is_osr()) {
     // TurboFan OSR-compiled functions cannot be entered directly.
     __ Abort(kShouldNotDirectlyEnterOsrFunction);
@@ -1805,15 +1940,12 @@
     // remaining stack slots.
     if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
     osr_pc_offset_ = __ pc_offset();
-    stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
+    shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
   }
 
   const RegList double_saves = descriptor->CalleeSavedFPRegisters();
-  if (double_saves != 0) {
-    stack_shrink_slots += frame()->AlignSavedCalleeRegisterSlots();
-  }
-  if (stack_shrink_slots > 0) {
-    __ lay(sp, MemOperand(sp, -stack_shrink_slots * kPointerSize));
+  if (shrink_slots > 0) {
+    __ lay(sp, MemOperand(sp, -shrink_slots * kPointerSize));
   }
 
   // Save callee-saved Double registers.
@@ -1821,8 +1953,6 @@
     __ MultiPushDoubles(double_saves);
     DCHECK(kNumCalleeSavedDoubles ==
            base::bits::CountPopulation32(double_saves));
-    frame()->AllocateSavedCalleeRegisterSlots(kNumCalleeSavedDoubles *
-                                              (kDoubleSize / kPointerSize));
   }
 
   // Save callee-saved registers.
@@ -1830,10 +1960,6 @@
   if (saves != 0) {
     __ MultiPush(saves);
     // register save area does not include the fp or constant pool pointer.
-    const int num_saves =
-        kNumCalleeSaved - 1 - (FLAG_enable_embedded_constant_pool ? 1 : 0);
-    DCHECK(num_saves == base::bits::CountPopulation32(saves));
-    frame()->AllocateSavedCalleeRegisterSlots(num_saves);
   }
 }
 
@@ -1898,10 +2024,30 @@
           destination->IsRegister() ? g.ToRegister(destination) : kScratchReg;
       switch (src.type()) {
         case Constant::kInt32:
-          __ mov(dst, Operand(src.ToInt32()));
+#if V8_TARGET_ARCH_S390X
+          if (src.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) {
+#else
+          if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
+              src.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE ||
+              src.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) {
+#endif
+            __ mov(dst, Operand(src.ToInt32(), src.rmode()));
+          } else {
+            __ mov(dst, Operand(src.ToInt32()));
+          }
           break;
         case Constant::kInt64:
+#if V8_TARGET_ARCH_S390X
+          if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
+              src.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE) {
+            __ mov(dst, Operand(src.ToInt64(), src.rmode()));
+          } else {
+            DCHECK(src.rmode() != RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
+            __ mov(dst, Operand(src.ToInt64()));
+          }
+#else
           __ mov(dst, Operand(src.ToInt64()));
+#endif  // V8_TARGET_ARCH_S390X
           break;
         case Constant::kFloat32:
           __ Move(dst,
@@ -1935,7 +2081,7 @@
         __ StoreP(dst, g.ToMemOperand(destination), r0);
       }
     } else {
-      DoubleRegister dst = destination->IsDoubleRegister()
+      DoubleRegister dst = destination->IsFPRegister()
                                ? g.ToDoubleRegister(destination)
                                : kScratchDoubleReg;
       double value = (src.type() == Constant::kFloat32) ? src.ToFloat32()
@@ -1946,28 +2092,44 @@
         __ LoadDoubleLiteral(dst, value, kScratchReg);
       }
 
-      if (destination->IsDoubleStackSlot()) {
+      if (destination->IsFPStackSlot()) {
         __ StoreDouble(dst, g.ToMemOperand(destination));
       }
     }
-  } else if (source->IsDoubleRegister()) {
+  } else if (source->IsFPRegister()) {
     DoubleRegister src = g.ToDoubleRegister(source);
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       DoubleRegister dst = g.ToDoubleRegister(destination);
       __ Move(dst, src);
     } else {
-      DCHECK(destination->IsDoubleStackSlot());
-      __ StoreDouble(src, g.ToMemOperand(destination));
+      DCHECK(destination->IsFPStackSlot());
+      LocationOperand* op = LocationOperand::cast(source);
+      if (op->representation() == MachineRepresentation::kFloat64) {
+        __ StoreDouble(src, g.ToMemOperand(destination));
+      } else {
+        __ StoreFloat32(src, g.ToMemOperand(destination));
+      }
     }
-  } else if (source->IsDoubleStackSlot()) {
-    DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
+  } else if (source->IsFPStackSlot()) {
+    DCHECK(destination->IsFPRegister() || destination->IsFPStackSlot());
     MemOperand src = g.ToMemOperand(source);
-    if (destination->IsDoubleRegister()) {
-      __ LoadDouble(g.ToDoubleRegister(destination), src);
+    if (destination->IsFPRegister()) {
+      LocationOperand* op = LocationOperand::cast(source);
+      if (op->representation() == MachineRepresentation::kFloat64) {
+        __ LoadDouble(g.ToDoubleRegister(destination), src);
+      } else {
+        __ LoadFloat32(g.ToDoubleRegister(destination), src);
+      }
     } else {
+      LocationOperand* op = LocationOperand::cast(source);
       DoubleRegister temp = kScratchDoubleReg;
-      __ LoadDouble(temp, src);
-      __ StoreDouble(temp, g.ToMemOperand(destination));
+      if (op->representation() == MachineRepresentation::kFloat64) {
+        __ LoadDouble(temp, src);
+        __ StoreDouble(temp, g.ToMemOperand(destination));
+      } else {
+        __ LoadFloat32(temp, src);
+        __ StoreFloat32(temp, g.ToMemOperand(destination));
+      }
     }
   } else {
     UNREACHABLE();
@@ -1996,7 +2158,7 @@
       __ StoreP(temp, dst);
     }
 #if V8_TARGET_ARCH_S390X
-  } else if (source->IsStackSlot() || source->IsDoubleStackSlot()) {
+  } else if (source->IsStackSlot() || source->IsFPStackSlot()) {
 #else
   } else if (source->IsStackSlot()) {
     DCHECK(destination->IsStackSlot());
@@ -2009,24 +2171,24 @@
     __ LoadP(temp_1, dst);
     __ StoreP(temp_0, dst);
     __ StoreP(temp_1, src);
-  } else if (source->IsDoubleRegister()) {
+  } else if (source->IsFPRegister()) {
     DoubleRegister temp = kScratchDoubleReg;
     DoubleRegister src = g.ToDoubleRegister(source);
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       DoubleRegister dst = g.ToDoubleRegister(destination);
       __ ldr(temp, src);
       __ ldr(src, dst);
       __ ldr(dst, temp);
     } else {
-      DCHECK(destination->IsDoubleStackSlot());
+      DCHECK(destination->IsFPStackSlot());
       MemOperand dst = g.ToMemOperand(destination);
       __ ldr(temp, src);
       __ LoadDouble(src, dst);
       __ StoreDouble(temp, dst);
     }
 #if !V8_TARGET_ARCH_S390X
-  } else if (source->IsDoubleStackSlot()) {
-    DCHECK(destination->IsDoubleStackSlot());
+  } else if (source->IsFPStackSlot()) {
+    DCHECK(destination->IsFPStackSlot());
     DoubleRegister temp_0 = kScratchDoubleReg;
     DoubleRegister temp_1 = d0;
     MemOperand src = g.ToMemOperand(source);
@@ -2049,10 +2211,6 @@
   }
 }
 
-void CodeGenerator::AddNopForSmiCodeInlining() {
-  // We do not insert nops for inlined Smi code.
-}
-
 void CodeGenerator::EnsureSpaceForLazyDeopt() {
   if (!info()->ShouldEnsureSpaceForLazyDeopt()) {
     return;
diff --git a/src/compiler/s390/instruction-codes-s390.h b/src/compiler/s390/instruction-codes-s390.h
index a32f875..b53136c 100644
--- a/src/compiler/s390/instruction-codes-s390.h
+++ b/src/compiler/s390/instruction-codes-s390.h
@@ -107,6 +107,7 @@
   V(S390_Float32ToInt32)           \
   V(S390_Float32ToUint32)          \
   V(S390_Float32ToDouble)          \
+  V(S390_Float64SilenceNaN)        \
   V(S390_DoubleToInt32)            \
   V(S390_DoubleToUint32)           \
   V(S390_DoubleToInt64)            \
@@ -126,6 +127,7 @@
   V(S390_LoadWordS16)              \
   V(S390_LoadWordU16)              \
   V(S390_LoadWordS32)              \
+  V(S390_LoadWordU32)              \
   V(S390_LoadWord64)               \
   V(S390_LoadFloat32)              \
   V(S390_LoadDouble)               \
diff --git a/src/compiler/s390/instruction-scheduler-s390.cc b/src/compiler/s390/instruction-scheduler-s390.cc
index 2d98e11..5b9722e 100644
--- a/src/compiler/s390/instruction-scheduler-s390.cc
+++ b/src/compiler/s390/instruction-scheduler-s390.cc
@@ -104,6 +104,7 @@
     case kS390_Float32ToUint32:
     case kS390_Float32ToUint64:
     case kS390_Float32ToDouble:
+    case kS390_Float64SilenceNaN:
     case kS390_DoubleToInt32:
     case kS390_DoubleToUint32:
     case kS390_Float32ToInt64:
@@ -126,6 +127,7 @@
     case kS390_LoadWordS16:
     case kS390_LoadWordU16:
     case kS390_LoadWordS32:
+    case kS390_LoadWordU32:
     case kS390_LoadWord64:
     case kS390_LoadFloat32:
     case kS390_LoadDouble:
diff --git a/src/compiler/s390/instruction-selector-s390.cc b/src/compiler/s390/instruction-selector-s390.cc
index 8a4af5e..1b1bd2f 100644
--- a/src/compiler/s390/instruction-selector-s390.cc
+++ b/src/compiler/s390/instruction-selector-s390.cc
@@ -182,11 +182,7 @@
     case MachineRepresentation::kTagged:  // Fall through.
 #endif
     case MachineRepresentation::kWord32:
-      opcode = kS390_LoadWordS32;
-#if V8_TARGET_ARCH_S390X
-      // TODO(john.yan): Remove this mode since s390 do not has this restriction
-      mode = kInt16Imm_4ByteAligned;
-#endif
+      opcode = kS390_LoadWordU32;
       break;
 #if V8_TARGET_ARCH_S390X
     case MachineRepresentation::kTagged:  // Fall through.
@@ -1042,14 +1038,12 @@
   VisitRR(this, kS390_DoubleToFloat32, node);
 }
 
-void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
-  switch (TruncationModeOf(node->op())) {
-    case TruncationMode::kJavaScript:
-      return VisitRR(this, kArchTruncateDoubleToI, node);
-    case TruncationMode::kRoundToZero:
-      return VisitRR(this, kS390_DoubleToInt32, node);
-  }
-  UNREACHABLE();
+void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
+  VisitRR(this, kArchTruncateDoubleToI, node);
+}
+
+void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
+  VisitRR(this, kS390_DoubleToInt32, node);
 }
 
 void InstructionSelector::VisitTruncateFloat32ToInt32(Node* node) {
@@ -1123,6 +1117,11 @@
   VisitRRR(this, kS390_SubFloat, node);
 }
 
+void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
+  S390OperandGenerator g(this);
+  VisitRRR(this, kS390_SubFloat, node);
+}
+
 void InstructionSelector::VisitFloat64Sub(Node* node) {
   // TODO(mbrandy): detect multiply-subtract
   S390OperandGenerator g(this);
@@ -1148,6 +1147,10 @@
   VisitRRR(this, kS390_SubDouble, node);
 }
 
+void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
+  VisitRRR(this, kS390_SubDouble, node);
+}
+
 void InstructionSelector::VisitFloat32Mul(Node* node) {
   VisitRRR(this, kS390_MulFloat, node);
 }
@@ -1176,6 +1179,10 @@
 
 void InstructionSelector::VisitFloat64Max(Node* node) { UNREACHABLE(); }
 
+void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
+  VisitRR(this, kS390_Float64SilenceNaN, node);
+}
+
 void InstructionSelector::VisitFloat32Min(Node* node) { UNREACHABLE(); }
 
 void InstructionSelector::VisitFloat64Min(Node* node) { UNREACHABLE(); }
@@ -1192,6 +1199,21 @@
   VisitRR(this, kS390_SqrtFloat, node);
 }
 
+void InstructionSelector::VisitFloat64Ieee754Unop(Node* node,
+                                                  InstructionCode opcode) {
+  S390OperandGenerator g(this);
+  Emit(opcode, g.DefineAsFixed(node, d0), g.UseFixed(node->InputAt(0), d0))
+      ->MarkAsCall();
+}
+
+void InstructionSelector::VisitFloat64Ieee754Binop(Node* node,
+                                                   InstructionCode opcode) {
+  S390OperandGenerator g(this);
+  Emit(opcode, g.DefineAsFixed(node, d0), g.UseFixed(node->InputAt(0), d0),
+       g.UseFixed(node->InputAt(1), d2))
+      ->MarkAsCall();
+}
+
 void InstructionSelector::VisitFloat64Sqrt(Node* node) {
   VisitRR(this, kS390_SqrtDouble, node);
 }
@@ -1232,6 +1254,10 @@
   UNREACHABLE();
 }
 
+void InstructionSelector::VisitFloat32Neg(Node* node) { UNREACHABLE(); }
+
+void InstructionSelector::VisitFloat64Neg(Node* node) { UNREACHABLE(); }
+
 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
   if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
     FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
@@ -1750,6 +1776,61 @@
        g.UseRegister(left), g.UseRegister(right));
 }
 
+void InstructionSelector::VisitAtomicLoad(Node* node) {
+  LoadRepresentation load_rep = LoadRepresentationOf(node->op());
+  S390OperandGenerator g(this);
+  Node* base = node->InputAt(0);
+  Node* index = node->InputAt(1);
+  ArchOpcode opcode = kArchNop;
+  switch (load_rep.representation()) {
+    case MachineRepresentation::kWord8:
+      opcode = load_rep.IsSigned() ? kAtomicLoadInt8 : kAtomicLoadUint8;
+      break;
+    case MachineRepresentation::kWord16:
+      opcode = load_rep.IsSigned() ? kAtomicLoadInt16 : kAtomicLoadUint16;
+      break;
+    case MachineRepresentation::kWord32:
+      opcode = kAtomicLoadWord32;
+      break;
+    default:
+      UNREACHABLE();
+      return;
+  }
+  Emit(opcode | AddressingModeField::encode(kMode_MRR),
+       g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
+}
+
+void InstructionSelector::VisitAtomicStore(Node* node) {
+  MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
+  S390OperandGenerator g(this);
+  Node* base = node->InputAt(0);
+  Node* index = node->InputAt(1);
+  Node* value = node->InputAt(2);
+  ArchOpcode opcode = kArchNop;
+  switch (rep) {
+    case MachineRepresentation::kWord8:
+      opcode = kAtomicStoreWord8;
+      break;
+    case MachineRepresentation::kWord16:
+      opcode = kAtomicStoreWord16;
+      break;
+    case MachineRepresentation::kWord32:
+      opcode = kAtomicStoreWord32;
+      break;
+    default:
+      UNREACHABLE();
+      return;
+  }
+
+  InstructionOperand inputs[4];
+  size_t input_count = 0;
+  inputs[input_count++] = g.UseUniqueRegister(value);
+  inputs[input_count++] = g.UseUniqueRegister(base);
+  inputs[input_count++] = g.UseUniqueRegister(index);
+  Emit(opcode | AddressingModeField::encode(kMode_MRR), 0, nullptr, input_count,
+       inputs);
+}
+
 // static
 MachineOperatorBuilder::Flags
 InstructionSelector::SupportedMachineOperatorFlags() {
@@ -1764,6 +1845,13 @@
          MachineOperatorBuilder::kWord64Popcnt;
 }
 
+// static
+MachineOperatorBuilder::AlignmentRequirements
+InstructionSelector::AlignmentRequirements() {
+  return MachineOperatorBuilder::AlignmentRequirements::
+      FullUnalignedAccessSupport();
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/src/compiler/schedule.cc b/src/compiler/schedule.cc
index 4ac65e5..6bd1a17 100644
--- a/src/compiler/schedule.cc
+++ b/src/compiler/schedule.cc
@@ -199,11 +199,28 @@
   AddSuccessor(block, succ);
 }
 
+#if DEBUG
+namespace {
+
+bool IsPotentiallyThrowingCall(IrOpcode::Value opcode) {
+  switch (opcode) {
+#define BUILD_BLOCK_JS_CASE(Name) case IrOpcode::k##Name:
+    JS_OP_LIST(BUILD_BLOCK_JS_CASE)
+#undef BUILD_BLOCK_JS_CASE
+    case IrOpcode::kCall:
+      return true;
+    default:
+      return false;
+  }
+}
+
+}  // namespace
+#endif  // DEBUG
 
 void Schedule::AddCall(BasicBlock* block, Node* call, BasicBlock* success_block,
                        BasicBlock* exception_block) {
   DCHECK_EQ(BasicBlock::kNone, block->control());
-  DCHECK_EQ(IrOpcode::kCall, call->opcode());
+  DCHECK(IsPotentiallyThrowingCall(call->opcode()));
   block->set_control(BasicBlock::kCall);
   AddSuccessor(block, success_block);
   AddSuccessor(block, exception_block);
@@ -298,41 +315,87 @@
   SetControlInput(block, sw);
 }
 
-void Schedule::EnsureSplitEdgeForm() {
+void Schedule::EnsureCFGWellFormedness() {
   // Make a copy of all the blocks for the iteration, since adding the split
   // edges will allocate new blocks.
   BasicBlockVector all_blocks_copy(all_blocks_);
 
   // Insert missing split edge blocks.
   for (auto block : all_blocks_copy) {
-    if (block->PredecessorCount() > 1 && block != end_) {
-      for (auto current_pred = block->predecessors().begin();
-           current_pred != block->predecessors().end(); ++current_pred) {
-        BasicBlock* pred = *current_pred;
-        if (pred->SuccessorCount() > 1) {
-          // Found a predecessor block with multiple successors.
-          BasicBlock* split_edge_block = NewBasicBlock();
-          split_edge_block->set_control(BasicBlock::kGoto);
-          split_edge_block->successors().push_back(block);
-          split_edge_block->predecessors().push_back(pred);
-          split_edge_block->set_deferred(pred->deferred());
-          *current_pred = split_edge_block;
-          // Find a corresponding successor in the previous block, replace it
-          // with the split edge block... but only do it once, since we only
-          // replace the previous blocks in the current block one at a time.
-          for (auto successor = pred->successors().begin();
-               successor != pred->successors().end(); ++successor) {
-            if (*successor == block) {
-              *successor = split_edge_block;
-              break;
-            }
-          }
+    if (block->PredecessorCount() > 1) {
+      if (block != end_) {
+        EnsureSplitEdgeForm(block);
+      }
+      if (block->deferred()) {
+        EnsureDeferredCodeSingleEntryPoint(block);
+      }
+    }
+  }
+}
+
+void Schedule::EnsureSplitEdgeForm(BasicBlock* block) {
+  DCHECK(block->PredecessorCount() > 1 && block != end_);
+  for (auto current_pred = block->predecessors().begin();
+       current_pred != block->predecessors().end(); ++current_pred) {
+    BasicBlock* pred = *current_pred;
+    if (pred->SuccessorCount() > 1) {
+      // Found a predecessor block with multiple successors.
+      BasicBlock* split_edge_block = NewBasicBlock();
+      split_edge_block->set_control(BasicBlock::kGoto);
+      split_edge_block->successors().push_back(block);
+      split_edge_block->predecessors().push_back(pred);
+      split_edge_block->set_deferred(pred->deferred());
+      *current_pred = split_edge_block;
+      // Find a corresponding successor in the previous block, replace it
+      // with the split edge block... but only do it once, since we only
+      // replace the previous blocks in the current block one at a time.
+      for (auto successor = pred->successors().begin();
+           successor != pred->successors().end(); ++successor) {
+        if (*successor == block) {
+          *successor = split_edge_block;
+          break;
         }
       }
     }
   }
 }
 
+void Schedule::EnsureDeferredCodeSingleEntryPoint(BasicBlock* block) {
+  // If a deferred block has multiple predecessors, they have to
+  // all be deferred. Otherwise, we can run into a situation where a range
+  // that spills only in deferred blocks inserts its spill in the block, but
+  // other ranges need moves inserted by ResolveControlFlow in the predecessors,
+  // which may clobber the register of this range.
+  // To ensure that, when a deferred block has multiple predecessors, and some
+  // are not deferred, we add a non-deferred block to collect all such edges.
+
+  DCHECK(block->deferred() && block->PredecessorCount() > 1);
+  bool all_deferred = true;
+  for (auto current_pred = block->predecessors().begin();
+       current_pred != block->predecessors().end(); ++current_pred) {
+    BasicBlock* pred = *current_pred;
+    if (!pred->deferred()) {
+      all_deferred = false;
+      break;
+    }
+  }
+
+  if (all_deferred) return;
+  BasicBlock* merger = NewBasicBlock();
+  merger->set_control(BasicBlock::kGoto);
+  merger->successors().push_back(block);
+  for (auto current_pred = block->predecessors().begin();
+       current_pred != block->predecessors().end(); ++current_pred) {
+    BasicBlock* pred = *current_pred;
+    merger->predecessors().push_back(pred);
+    pred->successors().clear();
+    pred->successors().push_back(merger);
+  }
+  merger->set_deferred(false);
+  block->predecessors().clear();
+  block->predecessors().push_back(merger);
+}
+
 void Schedule::PropagateDeferredMark() {
   // Push forward the deferred block marks through newly inserted blocks and
   // other improperly marked blocks until a fixed point is reached.
diff --git a/src/compiler/schedule.h b/src/compiler/schedule.h
index c99a0fc..74ba835 100644
--- a/src/compiler/schedule.h
+++ b/src/compiler/schedule.h
@@ -257,8 +257,12 @@
   friend class BasicBlockInstrumentor;
   friend class RawMachineAssembler;
 
+  // Ensure properties of the CFG assumed by further stages.
+  void EnsureCFGWellFormedness();
   // Ensure split-edge form for a hand-assembled schedule.
-  void EnsureSplitEdgeForm();
+  void EnsureSplitEdgeForm(BasicBlock* block);
+  // Ensure entry into a deferred block happens from a single hot block.
+  void EnsureDeferredCodeSingleEntryPoint(BasicBlock* block);
   // Copy deferred block markers down as far as possible
   void PropagateDeferredMark();
 
diff --git a/src/compiler/scheduler.cc b/src/compiler/scheduler.cc
index b04ba6f..58c01cc 100644
--- a/src/compiler/scheduler.cc
+++ b/src/compiler/scheduler.cc
@@ -324,6 +324,10 @@
       case IrOpcode::kSwitch:
         BuildBlocksForSuccessors(node);
         break;
+#define BUILD_BLOCK_JS_CASE(Name) case IrOpcode::k##Name:
+        JS_OP_LIST(BUILD_BLOCK_JS_CASE)
+// JS opcodes are just like calls => fall through.
+#undef BUILD_BLOCK_JS_CASE
       case IrOpcode::kCall:
         if (NodeProperties::IsExceptionalCall(node)) {
           BuildBlocksForSuccessors(node);
@@ -364,6 +368,10 @@
         scheduler_->UpdatePlacement(node, Scheduler::kFixed);
         ConnectThrow(node);
         break;
+#define CONNECT_BLOCK_JS_CASE(Name) case IrOpcode::k##Name:
+        JS_OP_LIST(CONNECT_BLOCK_JS_CASE)
+// JS opcodes are just like calls => fall through.
+#undef CONNECT_BLOCK_JS_CASE
       case IrOpcode::kCall:
         if (NodeProperties::IsExceptionalCall(node)) {
           scheduler_->UpdatePlacement(node, Scheduler::kFixed);
diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
index 88931f5..c56494c 100644
--- a/src/compiler/simplified-lowering.cc
+++ b/src/compiler/simplified-lowering.cc
@@ -6,17 +6,21 @@
 
 #include <limits>
 
+#include "src/address-map.h"
 #include "src/base/bits.h"
 #include "src/code-factory.h"
+#include "src/compiler/access-builder.h"
 #include "src/compiler/common-operator.h"
 #include "src/compiler/diamond.h"
 #include "src/compiler/linkage.h"
 #include "src/compiler/node-matchers.h"
 #include "src/compiler/node-properties.h"
+#include "src/compiler/operation-typer.h"
 #include "src/compiler/operator-properties.h"
 #include "src/compiler/representation-change.h"
 #include "src/compiler/simplified-operator.h"
 #include "src/compiler/source-position.h"
+#include "src/conversions-inl.h"
 #include "src/objects.h"
 #include "src/type-cache.h"
 
@@ -59,78 +63,21 @@
 
 namespace {
 
-// The {UseInfo} class is used to describe a use of an input of a node.
-//
-// This information is used in two different ways, based on the phase:
-//
-// 1. During propagation, the use info is used to inform the input node
-//    about what part of the input is used (we call this truncation) and what
-//    is the preferred representation.
-//
-// 2. During lowering, the use info is used to properly convert the input
-//    to the preferred representation. The preferred representation might be
-//    insufficient to do the conversion (e.g. word32->float64 conv), so we also
-//    need the signedness information to produce the correct value.
-class UseInfo {
- public:
-  UseInfo(MachineRepresentation preferred, Truncation truncation)
-      : preferred_(preferred), truncation_(truncation) {}
-  static UseInfo TruncatingWord32() {
-    return UseInfo(MachineRepresentation::kWord32, Truncation::Word32());
-  }
-  static UseInfo TruncatingWord64() {
-    return UseInfo(MachineRepresentation::kWord64, Truncation::Word64());
-  }
-  static UseInfo Bool() {
-    return UseInfo(MachineRepresentation::kBit, Truncation::Bool());
-  }
-  static UseInfo Float32() {
-    return UseInfo(MachineRepresentation::kFloat32, Truncation::Float32());
-  }
-  static UseInfo Float64() {
-    return UseInfo(MachineRepresentation::kFloat64, Truncation::Float64());
-  }
-  static UseInfo PointerInt() {
-    return kPointerSize == 4 ? TruncatingWord32() : TruncatingWord64();
-  }
-  static UseInfo AnyTagged() {
-    return UseInfo(MachineRepresentation::kTagged, Truncation::Any());
-  }
-
-  // Undetermined representation.
-  static UseInfo Any() {
-    return UseInfo(MachineRepresentation::kNone, Truncation::Any());
-  }
-  static UseInfo None() {
-    return UseInfo(MachineRepresentation::kNone, Truncation::None());
-  }
-  static UseInfo AnyTruncatingToBool() {
-    return UseInfo(MachineRepresentation::kNone, Truncation::Bool());
-  }
-
-  MachineRepresentation preferred() const { return preferred_; }
-  Truncation truncation() const { return truncation_; }
-
- private:
-  MachineRepresentation preferred_;
-  Truncation truncation_;
-};
-
 
 UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) {
   switch (rep) {
     case MachineRepresentation::kTagged:
       return UseInfo::AnyTagged();
     case MachineRepresentation::kFloat64:
-    return UseInfo::Float64();
+      return UseInfo::TruncatingFloat64();
     case MachineRepresentation::kFloat32:
-      return UseInfo::Float32();
+      return UseInfo::TruncatingFloat32();
     case MachineRepresentation::kWord64:
-    return UseInfo::TruncatingWord64();
+      return UseInfo::TruncatingWord64();
     case MachineRepresentation::kWord8:
     case MachineRepresentation::kWord16:
     case MachineRepresentation::kWord32:
-    return UseInfo::TruncatingWord32();
+      return UseInfo::TruncatingWord32();
     case MachineRepresentation::kBit:
       return UseInfo::Bool();
     case MachineRepresentation::kSimd128:  // Fall through.
@@ -220,7 +167,8 @@
   ZoneVector<UseInfo> input_use_infos_;
 
   static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) {
-    return MachineRepresentationIsSubtype(use1.preferred(), use2.preferred()) &&
+    return MachineRepresentationIsSubtype(use1.representation(),
+                                          use2.representation()) &&
            use1.truncation().IsLessGeneralThan(use2.truncation());
   }
 };
@@ -243,27 +191,43 @@
       return truncation_ != old_truncation;
     }
 
-    void set_queued(bool value) { queued_ = value; }
-    bool queued() const { return queued_; }
-    void set_visited() { visited_ = true; }
-    bool visited() const { return visited_; }
+    void set_queued() { state_ = kQueued; }
+    void set_visited() { state_ = kVisited; }
+    void set_pushed() { state_ = kPushed; }
+    void reset_state() { state_ = kUnvisited; }
+    bool visited() const { return state_ == kVisited; }
+    bool queued() const { return state_ == kQueued; }
+    bool unvisited() const { return state_ == kUnvisited; }
     Truncation truncation() const { return truncation_; }
     void set_output(MachineRepresentation output) { representation_ = output; }
 
     MachineRepresentation representation() const { return representation_; }
 
+    // Helpers for feedback typing.
+    void set_feedback_type(Type* type) { feedback_type_ = type; }
+    Type* feedback_type() { return feedback_type_; }
+    void set_weakened() { weakened_ = true; }
+    bool weakened() { return weakened_; }
+    TypeCheckKind type_check() { return type_check_; }
+    void set_type_check(TypeCheckKind type_check) { type_check_ = type_check; }
+
    private:
-    bool queued_ = false;   // Bookkeeping for the traversal.
-    bool visited_ = false;  // Bookkeeping for the traversal.
+    enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued };
+    State state_ = kUnvisited;
     MachineRepresentation representation_ =
         MachineRepresentation::kNone;             // Output representation.
     Truncation truncation_ = Truncation::None();  // Information about uses.
+    TypeCheckKind type_check_ = TypeCheckKind::kNone;  // Runtime check kind.
+
+    Type* feedback_type_ = nullptr;
+    bool weakened_ = false;
   };
 
   RepresentationSelector(JSGraph* jsgraph, Zone* zone,
                          RepresentationChanger* changer,
                          SourcePositionTable* source_positions)
       : jsgraph_(jsgraph),
+        zone_(zone),
         count_(jsgraph->graph()->NodeCount()),
         info_(count_, zone),
 #ifdef DEBUG
@@ -274,11 +238,320 @@
         phase_(PROPAGATE),
         changer_(changer),
         queue_(zone),
+        typing_stack_(zone),
         source_positions_(source_positions),
-        type_cache_(TypeCache::Get()) {
+        type_cache_(TypeCache::Get()),
+        op_typer_(jsgraph->isolate(), graph_zone()) {
   }
 
-  void Run(SimplifiedLowering* lowering) {
+  // Forward propagation of types from type feedback.
+  void RunTypePropagationPhase() {
+    DCHECK(typing_stack_.empty());
+
+    typing_stack_.push({graph()->end(), 0});
+    GetInfo(graph()->end())->set_pushed();
+    while (!typing_stack_.empty()) {
+      NodeState& current = typing_stack_.top();
+
+      // If there is an unvisited input, push it and continue.
+      bool pushed_unvisited = false;
+      while (current.input_index < current.node->InputCount()) {
+        Node* input = current.node->InputAt(current.input_index);
+        NodeInfo* input_info = GetInfo(input);
+        current.input_index++;
+        if (input_info->unvisited()) {
+          input_info->set_pushed();
+          typing_stack_.push({input, 0});
+          pushed_unvisited = true;
+          break;
+        }
+      }
+      if (pushed_unvisited) continue;
+
+      // Process the top of the stack.
+      Node* node = current.node;
+      typing_stack_.pop();
+      NodeInfo* info = GetInfo(node);
+      info->set_visited();
+      bool updated = UpdateFeedbackType(node);
+      if (updated) {
+        for (Node* const user : node->uses()) {
+          if (GetInfo(user)->visited()) {
+            GetInfo(user)->set_queued();
+            queue_.push(user);
+          }
+        }
+      }
+    }
+
+    // Process the revisit queue.
+    while (!queue_.empty()) {
+      Node* node = queue_.front();
+      queue_.pop();
+      NodeInfo* info = GetInfo(node);
+      info->set_visited();
+      bool updated = UpdateFeedbackType(node);
+      if (updated) {
+        for (Node* const user : node->uses()) {
+          if (GetInfo(user)->visited()) {
+            GetInfo(user)->set_queued();
+            queue_.push(user);
+          }
+        }
+      }
+    }
+  }
+
+  void ResetNodeInfoState() {
+    // Clean up for the next phase.
+    for (NodeInfo& info : info_) {
+      info.reset_state();
+    }
+  }
+
+  Type* TypeOf(Node* node) {
+    Type* type = GetInfo(node)->feedback_type();
+    return type == nullptr ? NodeProperties::GetType(node) : type;
+  }
+
+  Type* FeedbackTypeOf(Node* node) {
+    Type* type = GetInfo(node)->feedback_type();
+    return type == nullptr ? Type::None() : type;
+  }
+
+  Type* TypePhi(Node* node) {
+    int arity = node->op()->ValueInputCount();
+    Type* type = FeedbackTypeOf(node->InputAt(0));
+    for (int i = 1; i < arity; ++i) {
+      type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i)));
+    }
+    return type;
+  }
+
+  Type* TypeSelect(Node* node) {
+    return op_typer_.Merge(FeedbackTypeOf(node->InputAt(1)),
+                           FeedbackTypeOf(node->InputAt(2)));
+  }
+
+  static Type* TypeOfSpeculativeOp(TypeCheckKind type_check) {
+    switch (type_check) {
+      case TypeCheckKind::kNone:
+        return Type::Any();
+      case TypeCheckKind::kSigned32:
+        return Type::Signed32();
+      case TypeCheckKind::kNumber:
+        return Type::Number();
+      // Unexpected cases.
+      case TypeCheckKind::kNumberOrUndefined:
+        FATAL("Unexpected checked type.");
+        break;
+    }
+    UNREACHABLE();
+    return nullptr;
+  }
+
+  bool UpdateFeedbackType(Node* node) {
+    if (node->op()->ValueOutputCount() == 0) return false;
+
+    NodeInfo* info = GetInfo(node);
+    Type* type = info->feedback_type();
+    Type* new_type = type;
+
+    switch (node->opcode()) {
+      case IrOpcode::kSpeculativeNumberAdd: {
+        Type* lhs = FeedbackTypeOf(node->InputAt(0));
+        Type* rhs = FeedbackTypeOf(node->InputAt(1));
+        if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
+        // TODO(jarin) The ToNumber conversion is too conservative here,
+        // e.g. it will treat true as 1 even though the number check will
+        // fail on a boolean. OperationTyper should have a function that
+        // computes a more precise type.
+        lhs = op_typer_.ToNumber(lhs);
+        rhs = op_typer_.ToNumber(rhs);
+        Type* static_type = op_typer_.NumericAdd(lhs, rhs);
+        if (info->type_check() == TypeCheckKind::kNone) {
+          new_type = static_type;
+        } else {
+          Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
+          new_type = Type::Intersect(static_type, feedback_type, graph_zone());
+        }
+        break;
+      }
+
+      case IrOpcode::kSpeculativeNumberSubtract: {
+        Type* lhs = FeedbackTypeOf(node->InputAt(0));
+        Type* rhs = FeedbackTypeOf(node->InputAt(1));
+        if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
+        // TODO(jarin) The ToNumber conversion is too conservative here,
+        // e.g. it will treat true as 1 even though the number check will
+        // fail on a boolean. OperationTyper should have a function that
+        // computes a more precise type.
+        lhs = op_typer_.ToNumber(lhs);
+        rhs = op_typer_.ToNumber(rhs);
+        Type* static_type = op_typer_.NumericSubtract(lhs, rhs);
+        if (info->type_check() == TypeCheckKind::kNone) {
+          new_type = static_type;
+        } else {
+          Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
+          new_type = Type::Intersect(static_type, feedback_type, graph_zone());
+        }
+        break;
+      }
+
+      case IrOpcode::kSpeculativeNumberMultiply: {
+        Type* lhs = FeedbackTypeOf(node->InputAt(0));
+        Type* rhs = FeedbackTypeOf(node->InputAt(1));
+        if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
+        // TODO(jarin) The ToNumber conversion is too conservative here,
+        // e.g. it will treat true as 1 even though the number check will
+        // fail on a boolean. OperationTyper should have a function that
+        // computes a more precise type.
+        lhs = op_typer_.ToNumber(lhs);
+        rhs = op_typer_.ToNumber(rhs);
+        Type* static_type = op_typer_.NumericMultiply(lhs, rhs);
+        if (info->type_check() == TypeCheckKind::kNone) {
+          new_type = static_type;
+        } else {
+          Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
+          new_type = Type::Intersect(static_type, feedback_type, graph_zone());
+        }
+        break;
+      }
+
+      case IrOpcode::kSpeculativeNumberDivide: {
+        Type* lhs = FeedbackTypeOf(node->InputAt(0));
+        Type* rhs = FeedbackTypeOf(node->InputAt(1));
+        if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
+        // TODO(jarin) The ToNumber conversion is too conservative here,
+        // e.g. it will treat true as 1 even though the number check will
+        // fail on a boolean. OperationTyper should have a function that
+        // computes a more precise type.
+        lhs = op_typer_.ToNumber(lhs);
+        rhs = op_typer_.ToNumber(rhs);
+        Type* static_type = op_typer_.NumericDivide(lhs, rhs);
+        if (info->type_check() == TypeCheckKind::kNone) {
+          new_type = static_type;
+        } else {
+          Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
+          new_type = Type::Intersect(static_type, feedback_type, graph_zone());
+        }
+        break;
+      }
+
+      case IrOpcode::kSpeculativeNumberModulus: {
+        Type* lhs = FeedbackTypeOf(node->InputAt(0));
+        Type* rhs = FeedbackTypeOf(node->InputAt(1));
+        if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
+        // TODO(jarin) The ToNumber conversion is too conservative here,
+        // e.g. it will treat true as 1 even though the number check will
+        // fail on a boolean. OperationTyper should have a function that
+        // computes a more precise type.
+        lhs = op_typer_.ToNumber(lhs);
+        rhs = op_typer_.ToNumber(rhs);
+        Type* static_type = op_typer_.NumericModulus(lhs, rhs);
+        if (info->type_check() == TypeCheckKind::kNone) {
+          new_type = static_type;
+        } else {
+          Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
+          new_type = Type::Intersect(static_type, feedback_type, graph_zone());
+        }
+        break;
+      }
+
+      case IrOpcode::kPhi: {
+        new_type = TypePhi(node);
+        if (type != nullptr) {
+          new_type = Weaken(node, type, new_type);
+        }
+        // Recompute the phi representation based on the new type.
+        MachineRepresentation output =
+            GetOutputInfoForPhi(node, GetInfo(node)->truncation(), new_type);
+        ResetOutput(node, output);
+        break;
+      }
+
+      case IrOpcode::kSelect: {
+        new_type = TypeSelect(node);
+        // Recompute representation based on the new type.
+        MachineRepresentation output =
+            GetOutputInfoForPhi(node, GetInfo(node)->truncation(), new_type);
+        ResetOutput(node, output);
+        break;
+      }
+
+      default:
+        // Shortcut for operations that we do not handle.
+        if (type == nullptr) {
+          GetInfo(node)->set_feedback_type(NodeProperties::GetType(node));
+          return true;
+        }
+        return false;
+    }
+    if (type != nullptr && new_type->Is(type)) return false;
+    GetInfo(node)->set_feedback_type(new_type);
+    if (FLAG_trace_representation) {
+      PrintNodeFeedbackType(node);
+    }
+    return true;
+  }
+
+  void PrintNodeFeedbackType(Node* n) {
+    OFStream os(stdout);
+    os << "#" << n->id() << ":" << *n->op() << "(";
+    int j = 0;
+    for (Node* const i : n->inputs()) {
+      if (j++ > 0) os << ", ";
+      os << "#" << i->id() << ":" << i->op()->mnemonic();
+    }
+    os << ")";
+    if (NodeProperties::IsTyped(n)) {
+      os << "  [Static type: ";
+      Type* static_type = NodeProperties::GetType(n);
+      static_type->PrintTo(os);
+      Type* feedback_type = GetInfo(n)->feedback_type();
+      if (feedback_type != nullptr && feedback_type != static_type) {
+        os << ", Feedback type: ";
+        feedback_type->PrintTo(os);
+      }
+      os << "]";
+    }
+    os << std::endl;
+  }
+
+  Type* Weaken(Node* node, Type* previous_type, Type* current_type) {
+    // If the types have nothing to do with integers, return the types.
+    Type* const integer = type_cache_.kInteger;
+    if (!previous_type->Maybe(integer)) {
+      return current_type;
+    }
+    DCHECK(current_type->Maybe(integer));
+
+    Type* current_integer =
+        Type::Intersect(current_type, integer, graph_zone());
+    Type* previous_integer =
+        Type::Intersect(previous_type, integer, graph_zone());
+
+    // Once we start weakening a node, we should always weaken.
+    if (!GetInfo(node)->weakened()) {
+      // Only weaken if there is range involved; we should converge quickly
+      // for all other types (the exception is a union of many constants,
+      // but we currently do not increase the number of constants in unions).
+      Type* previous = previous_integer->GetRange();
+      Type* current = current_integer->GetRange();
+      if (current == nullptr || previous == nullptr) {
+        return current_type;
+      }
+      // Range is involved => we are weakening.
+      GetInfo(node)->set_weakened();
+    }
+
+    return Type::Union(current_type,
+                       op_typer_.WeakenRange(previous_integer, current_integer),
+                       graph_zone());
+  }
+
+  // Backward propagation of truncations.
+  void RunTruncationPropagationPhase() {
     // Run propagation phase to a fixpoint.
     TRACE("--{Propagation phase}--\n");
     phase_ = PROPAGATE;
@@ -288,13 +561,22 @@
       Node* node = queue_.front();
       NodeInfo* info = GetInfo(node);
       queue_.pop();
-      info->set_queued(false);
+      info->set_visited();
       TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
       VisitNode(node, info->truncation(), nullptr);
       TRACE("  ==> output ");
       PrintOutputInfo(info);
       TRACE("\n");
     }
+  }
+
+  void Run(SimplifiedLowering* lowering) {
+    RunTruncationPropagationPhase();
+
+    if (lowering->flags() & SimplifiedLowering::kTypeFeedbackEnabled) {
+      ResetNodeInfoState();
+      RunTypePropagationPhase();
+    }
 
     // Run lowering and change insertion phase.
     TRACE("--{Simplified lowering phase}--\n");
@@ -316,6 +598,7 @@
       Node* node = *i;
       Node* replacement = *(++i);
       node->ReplaceUses(replacement);
+      node->Kill();
       // We also need to replace the node in the rest of the vector.
       for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) {
         ++j;
@@ -326,8 +609,7 @@
 
   void EnqueueInitial(Node* node) {
     NodeInfo* info = GetInfo(node);
-    info->set_visited();
-    info->set_queued(true);
+    info->set_queued();
     nodes_.push_back(node);
     queue_.push(node);
   }
@@ -345,10 +627,9 @@
     node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index,
                                                            use_info);
 #endif  // DEBUG
-    if (!info->visited()) {
+    if (info->unvisited()) {
       // First visit of this node.
-      info->set_visited();
-      info->set_queued(true);
+      info->set_queued();
       nodes_.push_back(node);
       queue_.push(node);
       TRACE("  initial: ");
@@ -362,7 +643,7 @@
       // New usage information for the node is available.
       if (!info->queued()) {
         queue_.push(node);
-        info->set_queued(true);
+        info->set_queued();
         TRACE("   added: ");
       } else {
         TRACE(" inqueue: ");
@@ -372,48 +653,39 @@
   }
 
   bool lower() { return phase_ == LOWER; }
+  bool propagate() { return phase_ == PROPAGATE; }
 
-  void EnqueueUses(Node* node) {
-    for (Edge edge : node->use_edges()) {
-      if (NodeProperties::IsValueEdge(edge)) {
-        Node* const user = edge.from();
-        if (user->id() < count_) {
-          // New type information for the node is available.
-          NodeInfo* info = GetInfo(user);
-          // Enqueue the node only if we are sure it is reachable from
-          // the end and it has not been queued yet.
-          if (info->visited() && !info->queued()) {
-            queue_.push(user);
-            info->set_queued(true);
-          }
-        }
-      }
-    }
+  void SetOutput(Node* node, MachineRepresentation representation,
+                 TypeCheckKind type_check = TypeCheckKind::kNone) {
+    DCHECK(MachineRepresentationIsSubtype(GetInfo(node)->representation(),
+                                          representation));
+    ResetOutput(node, representation, type_check);
   }
 
-  void SetOutput(Node* node, MachineRepresentation representation) {
+  void ResetOutput(Node* node, MachineRepresentation representation,
+                   TypeCheckKind type_check = TypeCheckKind::kNone) {
     NodeInfo* info = GetInfo(node);
-    DCHECK(
-        MachineRepresentationIsSubtype(info->representation(), representation));
     info->set_output(representation);
+    info->set_type_check(type_check);
   }
 
   Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); }
 
+  bool InputIs(Node* node, Type* type) {
+    DCHECK_EQ(1, node->op()->ValueInputCount());
+    return GetUpperBound(node->InputAt(0))->Is(type);
+  }
+
   bool BothInputsAreSigned32(Node* node) {
-    DCHECK_EQ(2, node->InputCount());
-    return GetUpperBound(node->InputAt(0))->Is(Type::Signed32()) &&
-           GetUpperBound(node->InputAt(1))->Is(Type::Signed32());
+    return BothInputsAre(node, Type::Signed32());
   }
 
   bool BothInputsAreUnsigned32(Node* node) {
-    DCHECK_EQ(2, node->InputCount());
-    return GetUpperBound(node->InputAt(0))->Is(Type::Unsigned32()) &&
-           GetUpperBound(node->InputAt(1))->Is(Type::Unsigned32());
+    return BothInputsAre(node, Type::Unsigned32());
   }
 
   bool BothInputsAre(Node* node, Type* type) {
-    DCHECK_EQ(2, node->InputCount());
+    DCHECK_EQ(2, node->op()->ValueInputCount());
     return GetUpperBound(node->InputAt(0))->Is(type) &&
            GetUpperBound(node->InputAt(1))->Is(type);
   }
@@ -421,11 +693,13 @@
   void ConvertInput(Node* node, int index, UseInfo use) {
     Node* input = node->InputAt(index);
     // In the change phase, insert a change before the use if necessary.
-    if (use.preferred() == MachineRepresentation::kNone)
+    if (use.representation() == MachineRepresentation::kNone)
       return;  // No input requirement on the use.
+    DCHECK_NOT_NULL(input);
     NodeInfo* input_info = GetInfo(input);
     MachineRepresentation input_rep = input_info->representation();
-    if (input_rep != use.preferred()) {
+    if (input_rep != use.representation() ||
+        use.type_check() != TypeCheckKind::kNone) {
       // Output representation doesn't match usage.
       TRACE("  change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(),
             index, input->id(), input->op()->mnemonic());
@@ -435,8 +709,7 @@
       PrintUseInfo(use);
       TRACE("\n");
       Node* n = changer_->GetRepresentationFor(
-          input, input_info->representation(), GetUpperBound(input),
-          use.preferred(), use.truncation());
+          input, input_info->representation(), TypeOf(input), node, use);
       node->ReplaceInput(index, n);
     }
   }
@@ -481,25 +754,28 @@
 
   // Helper for binops of the R x L -> O variety.
   void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
-                  MachineRepresentation output) {
+                  MachineRepresentation output,
+                  TypeCheckKind type_check = TypeCheckKind::kNone) {
     DCHECK_EQ(2, node->op()->ValueInputCount());
     ProcessInput(node, 0, left_use);
     ProcessInput(node, 1, right_use);
     for (int i = 2; i < node->InputCount(); i++) {
       EnqueueInput(node, i);
     }
-    SetOutput(node, output);
+    SetOutput(node, output, type_check);
   }
 
   // Helper for binops of the I x I -> O variety.
-  void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output) {
-    VisitBinop(node, input_use, input_use, output);
+  void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output,
+                  TypeCheckKind type_check = TypeCheckKind::kNone) {
+    VisitBinop(node, input_use, input_use, output, type_check);
   }
 
   // Helper for unops of the I -> O variety.
   void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output) {
-    DCHECK_EQ(1, node->InputCount());
+    DCHECK_EQ(1, node->op()->ValueInputCount());
     ProcessInput(node, 0, input_use);
+    ProcessRemainingInputs(node, 1);
     SetOutput(node, output);
   }
 
@@ -511,7 +787,8 @@
 
   // Helpers for specific types of binops.
   void VisitFloat64Binop(Node* node) {
-    VisitBinop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+    VisitBinop(node, UseInfo::TruncatingFloat64(),
+               MachineRepresentation::kFloat64);
   }
   void VisitInt32Binop(Node* node) {
     VisitBinop(node, UseInfo::TruncatingWord32(),
@@ -534,7 +811,7 @@
                MachineRepresentation::kWord64);
   }
   void VisitFloat64Cmp(Node* node) {
-    VisitBinop(node, UseInfo::Float64(), MachineRepresentation::kBit);
+    VisitBinop(node, UseInfo::TruncatingFloat64(), MachineRepresentation::kBit);
   }
   void VisitInt32Cmp(Node* node) {
     VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit);
@@ -550,9 +827,12 @@
   }
 
   // Infer representation for phi-like nodes.
-  MachineRepresentation GetOutputInfoForPhi(Node* node, Truncation use) {
+  MachineRepresentation GetOutputInfoForPhi(Node* node, Truncation use,
+                                            Type* type = nullptr) {
     // Compute the representation.
-    Type* type = GetUpperBound(node);
+    if (type == nullptr) {
+      type = TypeOf(node);
+    }
     if (type->Is(Type::None())) {
       return MachineRepresentation::kNone;
     } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) {
@@ -563,6 +843,8 @@
       return MachineRepresentation::kBit;
     } else if (type->Is(Type::Number())) {
       return MachineRepresentation::kFloat64;
+    } else if (use.TruncatesToFloat64()) {
+      return MachineRepresentation::kFloat64;
     } else if (type->Is(Type::Internal())) {
       // We mark (u)int64 as Type::Internal.
       // TODO(jarin) This is a workaround for our lack of (u)int64
@@ -573,6 +855,7 @@
                        MachineRepresentation::kWord64;
 #ifdef DEBUG
       // Check that all the inputs agree on being Word64.
+      DCHECK_EQ(IrOpcode::kPhi, node->opcode());  // This only works for phis.
       for (int i = 1; i < node->op()->ValueInputCount(); i++) {
         DCHECK_EQ(is_word64, GetInfo(node->InputAt(i))->representation() ==
                                  MachineRepresentation::kWord64);
@@ -611,6 +894,8 @@
   void VisitPhi(Node* node, Truncation truncation,
                 SimplifiedLowering* lowering) {
     MachineRepresentation output = GetOutputInfoForPhi(node, truncation);
+    // Only set the output representation if not running with type
+    // feedback. (Feedback typing will set the representation.)
     SetOutput(node, output);
 
     int values = node->op()->ValueInputCount();
@@ -630,7 +915,7 @@
   }
 
   void VisitCall(Node* node, SimplifiedLowering* lowering) {
-    const CallDescriptor* desc = OpParameter<const CallDescriptor*>(node->op());
+    const CallDescriptor* desc = CallDescriptorOf(node->op());
     const MachineSignature* sig = desc->GetMachineSignature();
     int params = static_cast<int>(sig->parameter_count());
     // Propagate representation information from call descriptor.
@@ -680,7 +965,7 @@
         Node* input = node->InputAt(i);
         NodeInfo* input_info = GetInfo(input);
         MachineType machine_type(input_info->representation(),
-                                 DeoptValueSemanticOf(GetUpperBound(input)));
+                                 DeoptValueSemanticOf(TypeOf(input)));
         DCHECK(machine_type.representation() !=
                    MachineRepresentation::kWord32 ||
                machine_type.semantic() == MachineSemantic::kInt32 ||
@@ -697,6 +982,10 @@
     return changer_->Int32OperatorFor(node->opcode());
   }
 
+  const Operator* Int32OverflowOp(Node* node) {
+    return changer_->Int32OverflowOperatorFor(node->opcode());
+  }
+
   const Operator* Uint32Op(Node* node) {
     return changer_->Uint32OperatorFor(node->opcode());
   }
@@ -705,6 +994,167 @@
     return changer_->Float64OperatorFor(node->opcode());
   }
 
+  WriteBarrierKind WriteBarrierKindFor(
+      BaseTaggedness base_taggedness,
+      MachineRepresentation field_representation, Type* field_type,
+      Node* value) {
+    if (base_taggedness == kTaggedBase &&
+        field_representation == MachineRepresentation::kTagged) {
+      Type* value_type = NodeProperties::GetType(value);
+      if (field_type->Is(Type::TaggedSigned()) ||
+          value_type->Is(Type::TaggedSigned())) {
+        // Write barriers are only for stores of heap objects.
+        return kNoWriteBarrier;
+      }
+      if (field_type->Is(Type::BooleanOrNullOrUndefined()) ||
+          value_type->Is(Type::BooleanOrNullOrUndefined())) {
+        // Write barriers are not necessary when storing true, false, null or
+        // undefined, because these special oddballs are always in the root set.
+        return kNoWriteBarrier;
+      }
+      if (value_type->IsConstant() &&
+          value_type->AsConstant()->Value()->IsHeapObject()) {
+        Handle<HeapObject> value_object =
+            Handle<HeapObject>::cast(value_type->AsConstant()->Value());
+        RootIndexMap root_index_map(jsgraph_->isolate());
+        int root_index = root_index_map.Lookup(*value_object);
+        if (root_index != RootIndexMap::kInvalidRootIndex &&
+            jsgraph_->isolate()->heap()->RootIsImmortalImmovable(root_index)) {
+          // Write barriers are unnecessary for immortal immovable roots.
+          return kNoWriteBarrier;
+        }
+        if (value_object->IsMap()) {
+          // Write barriers for storing maps are cheaper.
+          return kMapWriteBarrier;
+        }
+      }
+      if (field_type->Is(Type::TaggedPointer()) ||
+          value_type->Is(Type::TaggedPointer())) {
+        // Write barriers for heap objects are cheaper.
+        return kPointerWriteBarrier;
+      }
+      NumberMatcher m(value);
+      if (m.HasValue()) {
+        if (IsSmiDouble(m.Value())) {
+          // Storing a smi doesn't need a write barrier.
+          return kNoWriteBarrier;
+        }
+        // The NumberConstant will be represented as HeapNumber.
+        return kPointerWriteBarrier;
+      }
+      return kFullWriteBarrier;
+    }
+    return kNoWriteBarrier;
+  }
+
+  WriteBarrierKind WriteBarrierKindFor(
+      BaseTaggedness base_taggedness,
+      MachineRepresentation field_representation, int field_offset,
+      Type* field_type, Node* value) {
+    if (base_taggedness == kTaggedBase &&
+        field_offset == HeapObject::kMapOffset) {
+      return kMapWriteBarrier;
+    }
+    return WriteBarrierKindFor(base_taggedness, field_representation,
+                               field_type, value);
+  }
+
+  Graph* graph() const { return jsgraph_->graph(); }
+  CommonOperatorBuilder* common() const { return jsgraph_->common(); }
+  SimplifiedOperatorBuilder* simplified() const {
+    return jsgraph_->simplified();
+  }
+
+  void ReplaceEffectControlUses(Node* node, Node* effect, Node* control) {
+    for (Edge edge : node->use_edges()) {
+      if (NodeProperties::IsControlEdge(edge)) {
+        edge.UpdateTo(control);
+      } else if (NodeProperties::IsEffectEdge(edge)) {
+        edge.UpdateTo(effect);
+      } else {
+        DCHECK(NodeProperties::IsValueEdge(edge));
+      }
+    }
+  }
+
+  void ChangeToPureOp(Node* node, const Operator* new_op) {
+    if (node->op()->EffectInputCount() > 0) {
+      DCHECK_LT(0, node->op()->ControlInputCount());
+      // Disconnect the node from effect and control chains.
+      Node* control = NodeProperties::GetControlInput(node);
+      Node* effect = NodeProperties::GetEffectInput(node);
+      ReplaceEffectControlUses(node, effect, control);
+      node->TrimInputCount(new_op->ValueInputCount());
+    } else {
+      DCHECK_EQ(0, node->op()->ControlInputCount());
+    }
+
+    NodeProperties::ChangeOp(node, new_op);
+  }
+
+  void ChangeToInt32OverflowOp(Node* node, const Operator* new_op) {
+    NodeProperties::ChangeOp(node, new_op);
+  }
+
+  void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation,
+                                  SimplifiedLowering* lowering) {
+    if (BothInputsAre(node, type_cache_.kSigned32OrMinusZero) &&
+        NodeProperties::GetType(node)->Is(Type::Signed32())) {
+      // int32 + int32 = int32   ==>   signed Int32Add/Sub
+      VisitInt32Binop(node);
+      if (lower()) ChangeToPureOp(node, Int32Op(node));
+      return;
+    }
+
+    // Use truncation if available.
+    if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) &&
+        truncation.TruncatesToWord32()) {
+      // safe-int + safe-int = x (truncated to int32)
+      // => signed Int32Add/Sub (truncated)
+      VisitWord32TruncatingBinop(node);
+      if (lower()) ChangeToPureOp(node, Int32Op(node));
+      return;
+    }
+
+    // Try to use type feedback.
+    BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op());
+
+    // Handle the case when no int32 checks on inputs are necessary
+    // (but an overflow check is needed on the output).
+    if (BothInputsAre(node, Type::Signed32()) ||
+        (BothInputsAre(node, type_cache_.kSigned32OrMinusZero) &&
+         NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger))) {
+      // If both the inputs the feedback are int32, use the overflow op.
+      if (hint == BinaryOperationHints::kSignedSmall ||
+          hint == BinaryOperationHints::kSigned32) {
+        VisitBinop(node, UseInfo::TruncatingWord32(),
+                   MachineRepresentation::kWord32, TypeCheckKind::kSigned32);
+        if (lower()) {
+          ChangeToInt32OverflowOp(node, Int32OverflowOp(node));
+        }
+        return;
+      }
+    }
+
+    if (hint == BinaryOperationHints::kSignedSmall ||
+        hint == BinaryOperationHints::kSigned32) {
+      VisitBinop(node, UseInfo::CheckedSigned32AsWord32(),
+                 MachineRepresentation::kWord32, TypeCheckKind::kSigned32);
+      if (lower()) {
+        ChangeToInt32OverflowOp(node, Int32OverflowOp(node));
+      }
+      return;
+    }
+
+    // default case => Float64Add/Sub
+    VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(),
+               MachineRepresentation::kFloat64, TypeCheckKind::kNumber);
+    if (lower()) {
+      ChangeToPureOp(node, Float64Op(node));
+    }
+    return;
+  }
+
   // Dispatching routine for visiting the node {node} with the usage {use}.
   // Depending on the operator, propagate new usage info to the inputs.
   void VisitNode(Node* node, Truncation truncation,
@@ -742,15 +1192,15 @@
         ProcessInput(node, 0, UseInfo::Bool());
         ProcessInput(node, 1, UseInfo::AnyTagged());
         ProcessRemainingInputs(node, 2);
-        break;
+        return;
       case IrOpcode::kBranch:
         ProcessInput(node, 0, UseInfo::Bool());
         EnqueueInput(node, NodeProperties::FirstControlIndex(node));
-        break;
+        return;
       case IrOpcode::kSwitch:
         ProcessInput(node, 0, UseInfo::TruncatingWord32());
         EnqueueInput(node, NodeProperties::FirstControlIndex(node));
-        break;
+        return;
       case IrOpcode::kSelect:
         return VisitSelect(node, truncation, lowering);
       case IrOpcode::kPhi:
@@ -758,19 +1208,23 @@
       case IrOpcode::kCall:
         return VisitCall(node, lowering);
 
-//------------------------------------------------------------------
-// JavaScript operators.
-//------------------------------------------------------------------
-// For now, we assume that all JS operators were too complex to lower
-// to Simplified and that they will always require tagged value inputs
-// and produce tagged value outputs.
-// TODO(turbofan): it might be possible to lower some JSOperators here,
-// but that responsibility really lies in the typed lowering phase.
-#define DEFINE_JS_CASE(x) case IrOpcode::k##x:
-        JS_OP_LIST(DEFINE_JS_CASE)
-#undef DEFINE_JS_CASE
+      //------------------------------------------------------------------
+      // JavaScript operators.
+      //------------------------------------------------------------------
+      case IrOpcode::kJSToNumber: {
         VisitInputs(node);
-        return SetOutput(node, MachineRepresentation::kTagged);
+        // TODO(bmeurer): Optimize somewhat based on input type?
+        if (truncation.TruncatesToWord32()) {
+          SetOutput(node, MachineRepresentation::kWord32);
+          if (lower()) lowering->DoJSToNumberTruncatesToWord32(node, this);
+        } else if (truncation.TruncatesToFloat64()) {
+          SetOutput(node, MachineRepresentation::kFloat64);
+          if (lower()) lowering->DoJSToNumberTruncatesToFloat64(node, this);
+        } else {
+          SetOutput(node, MachineRepresentation::kTagged);
+        }
+        return;
+      }
 
       //------------------------------------------------------------------
       // Simplified operators.
@@ -792,7 +1246,7 @@
           ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
           SetOutput(node, MachineRepresentation::kBit);
         }
-        break;
+        return;
       }
       case IrOpcode::kBooleanToNumber: {
         if (lower()) {
@@ -810,17 +1264,19 @@
           ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
           SetOutput(node, MachineRepresentation::kWord32);
         }
-        break;
+        return;
       }
       case IrOpcode::kNumberEqual:
       case IrOpcode::kNumberLessThan:
       case IrOpcode::kNumberLessThanOrEqual: {
         // Number comparisons reduce to integer comparisons for integer inputs.
-        if (BothInputsAreSigned32(node)) {
+        if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
+            TypeOf(node->InputAt(1))->Is(Type::Signed32())) {
           // => signed Int32Cmp
           VisitInt32Cmp(node);
           if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
-        } else if (BothInputsAreUnsigned32(node)) {
+        } else if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
+                   TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
           // => unsigned Int32Cmp
           VisitUint32Cmp(node);
           if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
@@ -829,8 +1285,47 @@
           VisitFloat64Cmp(node);
           if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
         }
-        break;
+        return;
       }
+
+      case IrOpcode::kSpeculativeNumberAdd:
+      case IrOpcode::kSpeculativeNumberSubtract:
+        return VisitSpeculativeAdditiveOp(node, truncation, lowering);
+
+      case IrOpcode::kSpeculativeNumberLessThan:
+      case IrOpcode::kSpeculativeNumberLessThanOrEqual:
+      case IrOpcode::kSpeculativeNumberEqual: {
+        // Number comparisons reduce to integer comparisons for integer inputs.
+        if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
+            TypeOf(node->InputAt(1))->Is(Type::Signed32())) {
+          // => signed Int32Cmp
+          VisitInt32Cmp(node);
+          if (lower()) ChangeToPureOp(node, Int32Op(node));
+          return;
+        } else if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
+                   TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
+          // => unsigned Int32Cmp
+          VisitUint32Cmp(node);
+          if (lower()) ChangeToPureOp(node, Uint32Op(node));
+          return;
+        }
+        // Try to use type feedback.
+        CompareOperationHints::Hint hint = CompareOperationHintOf(node->op());
+
+        if (hint == CompareOperationHints::kSignedSmall) {
+          VisitBinop(node, UseInfo::CheckedSigned32AsWord32(),
+                     MachineRepresentation::kBit);
+          if (lower()) ChangeToPureOp(node, Int32Op(node));
+          return;
+        }
+        DCHECK_EQ(CompareOperationHints::kNumber, hint);
+        // default case => Float64 comparison
+        VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(),
+                   MachineRepresentation::kBit);
+        if (lower()) ChangeToPureOp(node, Float64Op(node));
+        return;
+      }
+
       case IrOpcode::kNumberAdd:
       case IrOpcode::kNumberSubtract: {
         if (BothInputsAre(node, Type::Signed32()) &&
@@ -839,7 +1334,8 @@
           // => signed Int32Add/Sub
           VisitInt32Binop(node);
           if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
-        } else if (BothInputsAre(node, type_cache_.kAdditiveSafeInteger) &&
+        } else if (BothInputsAre(node,
+                                 type_cache_.kAdditiveSafeIntegerOrMinusZero) &&
                    truncation.TruncatesToWord32()) {
           // safe-int + safe-int = x (truncated to int32)
           // => signed Int32Add/Sub (truncated)
@@ -850,90 +1346,119 @@
           VisitFloat64Binop(node);
           if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
         }
-        break;
+        return;
       }
+      case IrOpcode::kSpeculativeNumberMultiply:
       case IrOpcode::kNumberMultiply: {
         if (BothInputsAreSigned32(node)) {
           if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
             // Multiply reduces to Int32Mul if the inputs and the output
             // are integers.
             VisitInt32Binop(node);
-            if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
-            break;
+            if (lower()) ChangeToPureOp(node, Int32Op(node));
+            return;
           }
           if (truncation.TruncatesToWord32() &&
-              NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger)) {
+              NodeProperties::GetType(node)->Is(
+                  type_cache_.kSafeIntegerOrMinusZero)) {
             // Multiply reduces to Int32Mul if the inputs are integers,
             // the uses are truncating and the result is in the safe
             // integer range.
             VisitWord32TruncatingBinop(node);
-            if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
-            break;
+            if (lower()) ChangeToPureOp(node, Int32Op(node));
+            return;
           }
         }
-        // => Float64Mul
-        VisitFloat64Binop(node);
-        if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
-        break;
+        // Number x Number => Float64Mul
+        if (BothInputsAre(node, Type::NumberOrUndefined())) {
+          VisitFloat64Binop(node);
+          if (lower()) ChangeToPureOp(node, Float64Op(node));
+          return;
+        }
+        // Checked float64 x float64 => float64
+        DCHECK_EQ(IrOpcode::kSpeculativeNumberMultiply, node->opcode());
+        VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(),
+                   MachineRepresentation::kFloat64, TypeCheckKind::kNumber);
+        if (lower()) ChangeToPureOp(node, Float64Op(node));
+        return;
       }
+      case IrOpcode::kSpeculativeNumberDivide:
       case IrOpcode::kNumberDivide: {
         if (BothInputsAreSigned32(node)) {
           if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
           // => signed Int32Div
           VisitInt32Binop(node);
           if (lower()) DeferReplacement(node, lowering->Int32Div(node));
-          break;
+          return;
           }
           if (truncation.TruncatesToWord32()) {
             // => signed Int32Div
             VisitWord32TruncatingBinop(node);
             if (lower()) DeferReplacement(node, lowering->Int32Div(node));
-            break;
+            return;
           }
         }
         if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
           // => unsigned Uint32Div
           VisitWord32TruncatingBinop(node);
           if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
-          break;
+          return;
         }
-        // => Float64Div
-        VisitFloat64Binop(node);
-        if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
-        break;
+        // Number x Number => Float64Div
+        if (BothInputsAre(node, Type::NumberOrUndefined())) {
+          VisitFloat64Binop(node);
+          if (lower()) ChangeToPureOp(node, Float64Op(node));
+          return;
+        }
+        // Checked float64 x float64 => float64
+        DCHECK_EQ(IrOpcode::kSpeculativeNumberDivide, node->opcode());
+        VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(),
+                   MachineRepresentation::kFloat64, TypeCheckKind::kNumber);
+        if (lower()) ChangeToPureOp(node, Float64Op(node));
+        return;
       }
+      case IrOpcode::kSpeculativeNumberModulus:
       case IrOpcode::kNumberModulus: {
         if (BothInputsAreSigned32(node)) {
           if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
             // => signed Int32Mod
             VisitInt32Binop(node);
             if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
-            break;
+            return;
           }
           if (truncation.TruncatesToWord32()) {
             // => signed Int32Mod
             VisitWord32TruncatingBinop(node);
             if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
-            break;
+            return;
           }
         }
         if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
           // => unsigned Uint32Mod
           VisitWord32TruncatingBinop(node);
           if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
-          break;
+          return;
         }
-        // => Float64Mod
-        VisitFloat64Binop(node);
-        if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
-        break;
+        // Number x Number => Float64Mod
+        if (BothInputsAre(node, Type::NumberOrUndefined())) {
+          // => Float64Mod
+          VisitFloat64Binop(node);
+          if (lower()) ChangeToPureOp(node, Float64Op(node));
+          return;
+        }
+        // Checked float64 x float64 => float64
+        DCHECK_EQ(IrOpcode::kSpeculativeNumberModulus, node->opcode());
+        VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(),
+                   MachineRepresentation::kFloat64, TypeCheckKind::kNumber);
+        if (lower()) ChangeToPureOp(node, Float64Op(node));
+        return;
       }
       case IrOpcode::kNumberBitwiseOr:
       case IrOpcode::kNumberBitwiseXor:
       case IrOpcode::kNumberBitwiseAnd: {
         VisitInt32Binop(node);
         if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
-        break;
+        return;
       }
       case IrOpcode::kNumberShiftLeft: {
         Type* rhs_type = GetUpperBound(node->InputAt(1));
@@ -942,7 +1467,7 @@
         if (lower()) {
           lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
         }
-        break;
+        return;
       }
       case IrOpcode::kNumberShiftRight: {
         Type* rhs_type = GetUpperBound(node->InputAt(1));
@@ -951,7 +1476,7 @@
         if (lower()) {
           lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
         }
-        break;
+        return;
       }
       case IrOpcode::kNumberShiftRightLogical: {
         Type* rhs_type = GetUpperBound(node->InputAt(1));
@@ -960,98 +1485,127 @@
         if (lower()) {
           lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
         }
-        break;
+        return;
       }
-      case IrOpcode::kNumberImul: {
-        VisitBinop(node, UseInfo::TruncatingWord32(),
-                   UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
-        if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
-        break;
+      case IrOpcode::kNumberAbs: {
+        if (InputIs(node, Type::Unsigned32())) {
+          VisitUnop(node, UseInfo::TruncatingWord32(),
+                    MachineRepresentation::kWord32);
+          if (lower()) DeferReplacement(node, node->InputAt(0));
+        } else if (InputIs(node, type_cache_.kSafeSigned32)) {
+          VisitUnop(node, UseInfo::TruncatingWord32(),
+                    MachineRepresentation::kWord32);
+          if (lower()) DeferReplacement(node, lowering->Int32Abs(node));
+        } else if (InputIs(node,
+                           type_cache_.kPositiveIntegerOrMinusZeroOrNaN)) {
+          VisitUnop(node, UseInfo::TruncatingFloat64(),
+                    MachineRepresentation::kFloat64);
+          if (lower()) DeferReplacement(node, node->InputAt(0));
+        } else {
+          VisitUnop(node, UseInfo::TruncatingFloat64(),
+                    MachineRepresentation::kFloat64);
+          if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
+        }
+        return;
       }
       case IrOpcode::kNumberClz32: {
         VisitUnop(node, UseInfo::TruncatingWord32(),
                   MachineRepresentation::kWord32);
         if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
-        break;
+        return;
+      }
+      case IrOpcode::kNumberImul: {
+        VisitBinop(node, UseInfo::TruncatingWord32(),
+                   UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
+        if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
+        return;
       }
       case IrOpcode::kNumberCeil: {
-        VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+        VisitUnop(node, UseInfo::TruncatingFloat64(),
+                  MachineRepresentation::kFloat64);
         if (lower()) DeferReplacement(node, lowering->Float64Ceil(node));
-        break;
+        return;
       }
       case IrOpcode::kNumberFloor: {
-        VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+        VisitUnop(node, UseInfo::TruncatingFloat64(),
+                  MachineRepresentation::kFloat64);
         if (lower()) DeferReplacement(node, lowering->Float64Floor(node));
-        break;
+        return;
+      }
+      case IrOpcode::kNumberFround: {
+        VisitUnop(node, UseInfo::TruncatingFloat64(),
+                  MachineRepresentation::kFloat32);
+        if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
+        return;
+      }
+      case IrOpcode::kNumberAtan2: {
+        VisitBinop(node, UseInfo::TruncatingFloat64(),
+                   MachineRepresentation::kFloat64);
+        if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
+        return;
+      }
+      case IrOpcode::kNumberAtan:
+      case IrOpcode::kNumberAtanh:
+      case IrOpcode::kNumberCos:
+      case IrOpcode::kNumberExp:
+      case IrOpcode::kNumberExpm1:
+      case IrOpcode::kNumberLog:
+      case IrOpcode::kNumberLog1p:
+      case IrOpcode::kNumberLog2:
+      case IrOpcode::kNumberLog10:
+      case IrOpcode::kNumberCbrt:
+      case IrOpcode::kNumberSin:
+      case IrOpcode::kNumberTan: {
+        VisitUnop(node, UseInfo::TruncatingFloat64(),
+                  MachineRepresentation::kFloat64);
+        if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
+        return;
       }
       case IrOpcode::kNumberRound: {
-        VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+        VisitUnop(node, UseInfo::TruncatingFloat64(),
+                  MachineRepresentation::kFloat64);
         if (lower()) DeferReplacement(node, lowering->Float64Round(node));
-        break;
+        return;
+      }
+      case IrOpcode::kNumberSqrt: {
+        VisitUnop(node, UseInfo::TruncatingFloat64(),
+                  MachineRepresentation::kFloat64);
+        if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
+        return;
       }
       case IrOpcode::kNumberTrunc: {
-        VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+        VisitUnop(node, UseInfo::TruncatingFloat64(),
+                  MachineRepresentation::kFloat64);
         if (lower()) DeferReplacement(node, lowering->Float64Trunc(node));
-        break;
+        return;
       }
       case IrOpcode::kNumberToInt32: {
         // Just change representation if necessary.
         VisitUnop(node, UseInfo::TruncatingWord32(),
                   MachineRepresentation::kWord32);
         if (lower()) DeferReplacement(node, node->InputAt(0));
-        break;
+        return;
       }
       case IrOpcode::kNumberToUint32: {
         // Just change representation if necessary.
         VisitUnop(node, UseInfo::TruncatingWord32(),
                   MachineRepresentation::kWord32);
         if (lower()) DeferReplacement(node, node->InputAt(0));
-        break;
-      }
-      case IrOpcode::kNumberIsHoleNaN: {
-        VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kBit);
-        if (lower()) {
-          // NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x),
-          //                                   #HoleNaNLower32)
-          node->ReplaceInput(0,
-                             jsgraph_->graph()->NewNode(
-                                 lowering->machine()->Float64ExtractLowWord32(),
-                                 node->InputAt(0)));
-          node->AppendInput(jsgraph_->zone(),
-                            jsgraph_->Int32Constant(kHoleNanLower32));
-          NodeProperties::ChangeOp(node, jsgraph_->machine()->Word32Equal());
-        }
-        break;
-      }
-      case IrOpcode::kPlainPrimitiveToNumber: {
-        VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
-        if (lower()) {
-          // PlainPrimitiveToNumber(x) => Call(ToNumberStub, x, no-context)
-          Operator::Properties properties = node->op()->properties();
-          Callable callable = CodeFactory::ToNumber(jsgraph_->isolate());
-          CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
-          CallDescriptor* desc = Linkage::GetStubCallDescriptor(
-              jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
-              flags, properties);
-          node->InsertInput(jsgraph_->zone(), 0,
-                            jsgraph_->HeapConstant(callable.code()));
-          node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
-          NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
-        }
-        break;
+        return;
       }
       case IrOpcode::kReferenceEqual: {
         VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
         if (lower()) {
           NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
         }
-        break;
+        return;
       }
       case IrOpcode::kStringEqual: {
         VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
         if (lower()) {
           // StringEqual(x, y) => Call(StringEqualStub, x, y, no-context)
-          Operator::Properties properties = node->op()->properties();
+          Operator::Properties properties =
+              Operator::kCommutative | Operator::kEliminatable;
           Callable callable = CodeFactory::StringEqual(jsgraph_->isolate());
           CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
           CallDescriptor* desc = Linkage::GetStubCallDescriptor(
@@ -1059,16 +1613,17 @@
               flags, properties);
           node->InsertInput(jsgraph_->zone(), 0,
                             jsgraph_->HeapConstant(callable.code()));
-          node->InsertInput(jsgraph_->zone(), 3, jsgraph_->NoContextConstant());
+          node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
+          node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
           NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
         }
-        break;
+        return;
       }
       case IrOpcode::kStringLessThan: {
         VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
         if (lower()) {
           // StringLessThan(x, y) => Call(StringLessThanStub, x, y, no-context)
-          Operator::Properties properties = node->op()->properties();
+          Operator::Properties properties = Operator::kEliminatable;
           Callable callable = CodeFactory::StringLessThan(jsgraph_->isolate());
           CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
           CallDescriptor* desc = Linkage::GetStubCallDescriptor(
@@ -1076,17 +1631,18 @@
               flags, properties);
           node->InsertInput(jsgraph_->zone(), 0,
                             jsgraph_->HeapConstant(callable.code()));
-          node->InsertInput(jsgraph_->zone(), 3, jsgraph_->NoContextConstant());
+          node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
+          node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
           NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
         }
-        break;
+        return;
       }
       case IrOpcode::kStringLessThanOrEqual: {
         VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
         if (lower()) {
           // StringLessThanOrEqual(x, y)
           //   => Call(StringLessThanOrEqualStub, x, y, no-context)
-          Operator::Properties properties = node->op()->properties();
+          Operator::Properties properties = Operator::kEliminatable;
           Callable callable =
               CodeFactory::StringLessThanOrEqual(jsgraph_->isolate());
           CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
@@ -1095,16 +1651,22 @@
               flags, properties);
           node->InsertInput(jsgraph_->zone(), 0,
                             jsgraph_->HeapConstant(callable.code()));
-          node->InsertInput(jsgraph_->zone(), 3, jsgraph_->NoContextConstant());
+          node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
+          node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
           NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
         }
-        break;
+        return;
+      }
+      case IrOpcode::kStringFromCharCode: {
+        VisitUnop(node, UseInfo::TruncatingWord32(),
+                  MachineRepresentation::kTagged);
+        return;
       }
       case IrOpcode::kStringToNumber: {
         VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
         if (lower()) {
-          // StringToNumber(x) => Call(StringToNumberStub, x, no-context)
-          Operator::Properties properties = node->op()->properties();
+          // StringToNumber(x) => Call(StringToNumber, x, no-context)
+          Operator::Properties properties = Operator::kEliminatable;
           Callable callable = CodeFactory::StringToNumber(jsgraph_->isolate());
           CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
           CallDescriptor* desc = Linkage::GetStubCallDescriptor(
@@ -1113,22 +1675,55 @@
           node->InsertInput(jsgraph_->zone(), 0,
                             jsgraph_->HeapConstant(callable.code()));
           node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
+          node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
           NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
         }
-        break;
+        return;
       }
+
+      case IrOpcode::kCheckBounds: {
+        VisitBinop(node, UseInfo::CheckedSigned32AsWord32(),
+                   UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
+        return;
+      }
+      case IrOpcode::kCheckTaggedPointer: {
+        VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
+        if (lower()) {
+          if (InputIs(node, Type::TaggedPointer())) {
+            DeferReplacement(node, node->InputAt(0));
+          }
+        }
+        return;
+      }
+      case IrOpcode::kCheckTaggedSigned: {
+        if (SmiValuesAre32Bits() && truncation.TruncatesToWord32()) {
+          // TODO(jarin,bmeurer): Add CheckedSignedSmallAsWord32?
+          VisitUnop(node, UseInfo::CheckedSigned32AsWord32(),
+                    MachineRepresentation::kWord32);
+          if (lower()) DeferReplacement(node, node->InputAt(0));
+        } else {
+          VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
+          if (lower()) {
+            if (InputIs(node, Type::TaggedSigned())) {
+              DeferReplacement(node, node->InputAt(0));
+            }
+          }
+        }
+        return;
+      }
+
       case IrOpcode::kAllocate: {
-        ProcessInput(node, 0, UseInfo::AnyTagged());
+        ProcessInput(node, 0, UseInfo::TruncatingWord32());
         ProcessRemainingInputs(node, 1);
         SetOutput(node, MachineRepresentation::kTagged);
-        break;
+        return;
       }
       case IrOpcode::kLoadField: {
         FieldAccess access = FieldAccessOf(node->op());
         ProcessInput(node, 0, UseInfoForBasePointer(access));
         ProcessRemainingInputs(node, 1);
         SetOutput(node, access.machine_type.representation());
-        break;
+        return;
       }
       case IrOpcode::kStoreField: {
         FieldAccess access = FieldAccessOf(node->op());
@@ -1137,7 +1732,17 @@
                                   access.machine_type.representation()));
         ProcessRemainingInputs(node, 2);
         SetOutput(node, MachineRepresentation::kNone);
-        break;
+        if (lower()) {
+          WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
+              access.base_is_tagged, access.machine_type.representation(),
+              access.offset, access.type, node->InputAt(1));
+          if (write_barrier_kind < access.write_barrier_kind) {
+            access.write_barrier_kind = write_barrier_kind;
+            NodeProperties::ChangeOp(
+                node, jsgraph_->simplified()->StoreField(access));
+          }
+        }
+        return;
       }
       case IrOpcode::kLoadBuffer: {
         BufferAccess access = BufferAccessOf(node->op());
@@ -1160,25 +1765,17 @@
                 MachineRepresentation::kFloat32) {
               output = access.machine_type().representation();
             } else {
-              if (access.machine_type().representation() !=
-                  MachineRepresentation::kFloat64) {
-                // TODO(bmeurer): See comment on abort_compilation_.
-                if (lower()) lowering->abort_compilation_ = true;
-              }
               output = MachineRepresentation::kFloat64;
             }
           }
         } else {
-          // TODO(bmeurer): See comment on abort_compilation_.
-          if (lower()) lowering->abort_compilation_ = true;
-
           // If undefined is not truncated away, we need to have the tagged
           // representation.
           output = MachineRepresentation::kTagged;
         }
         SetOutput(node, output);
         if (lower()) lowering->DoLoadBuffer(node, output, changer_);
-        break;
+        return;
       }
       case IrOpcode::kStoreBuffer: {
         BufferAccess access = BufferAccessOf(node->op());
@@ -1191,7 +1788,7 @@
         ProcessRemainingInputs(node, 4);
         SetOutput(node, MachineRepresentation::kNone);
         if (lower()) lowering->DoStoreBuffer(node);
-        break;
+        return;
       }
       case IrOpcode::kLoadElement: {
         ElementAccess access = ElementAccessOf(node->op());
@@ -1199,7 +1796,7 @@
         ProcessInput(node, 1, UseInfo::TruncatingWord32());    // index
         ProcessRemainingInputs(node, 2);
         SetOutput(node, access.machine_type.representation());
-        break;
+        return;
       }
       case IrOpcode::kStoreElement: {
         ElementAccess access = ElementAccessOf(node->op());
@@ -1210,15 +1807,86 @@
                          access.machine_type.representation()));  // value
         ProcessRemainingInputs(node, 3);
         SetOutput(node, MachineRepresentation::kNone);
-        break;
+        if (lower()) {
+          WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
+              access.base_is_tagged, access.machine_type.representation(),
+              access.type, node->InputAt(2));
+          if (write_barrier_kind < access.write_barrier_kind) {
+            access.write_barrier_kind = write_barrier_kind;
+            NodeProperties::ChangeOp(
+                node, jsgraph_->simplified()->StoreElement(access));
+          }
+        }
+        return;
       }
+      case IrOpcode::kPlainPrimitiveToNumber:
+        if (truncation.TruncatesToWord32()) {
+          // TODO(jarin): Extend this to Number \/ Oddball
+          if (InputIs(node, Type::NumberOrUndefined())) {
+            VisitUnop(node, UseInfo::TruncatingWord32(),
+                      MachineRepresentation::kWord32);
+            if (lower()) DeferReplacement(node, node->InputAt(0));
+          } else {
+            VisitUnop(node, UseInfo::AnyTagged(),
+                      MachineRepresentation::kWord32);
+            if (lower()) {
+              NodeProperties::ChangeOp(node,
+                                       simplified()->PlainPrimitiveToWord32());
+            }
+          }
+        } else if (truncation.TruncatesToFloat64()) {
+          // TODO(jarin): Extend this to Number \/ Oddball
+          if (InputIs(node, Type::NumberOrUndefined())) {
+            VisitUnop(node, UseInfo::TruncatingFloat64(),
+                      MachineRepresentation::kFloat64);
+            if (lower()) DeferReplacement(node, node->InputAt(0));
+          } else {
+            VisitUnop(node, UseInfo::AnyTagged(),
+                      MachineRepresentation::kFloat64);
+            if (lower()) {
+              NodeProperties::ChangeOp(node,
+                                       simplified()->PlainPrimitiveToFloat64());
+            }
+          }
+        } else {
+          VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
+        }
+        return;
+      case IrOpcode::kObjectIsCallable:
       case IrOpcode::kObjectIsNumber:
       case IrOpcode::kObjectIsReceiver:
       case IrOpcode::kObjectIsSmi:
+      case IrOpcode::kObjectIsString:
       case IrOpcode::kObjectIsUndetectable: {
         ProcessInput(node, 0, UseInfo::AnyTagged());
         SetOutput(node, MachineRepresentation::kBit);
-        break;
+        return;
+      }
+      case IrOpcode::kCheckFloat64Hole: {
+        CheckFloat64HoleMode mode = CheckFloat64HoleModeOf(node->op());
+        ProcessInput(node, 0, UseInfo::TruncatingFloat64());
+        ProcessRemainingInputs(node, 1);
+        SetOutput(node, MachineRepresentation::kFloat64);
+        if (truncation.TruncatesToFloat64() &&
+            mode == CheckFloat64HoleMode::kAllowReturnHole) {
+          if (lower()) DeferReplacement(node, node->InputAt(0));
+        }
+        return;
+      }
+      case IrOpcode::kCheckTaggedHole: {
+        CheckTaggedHoleMode mode = CheckTaggedHoleModeOf(node->op());
+        if (truncation.TruncatesToWord32() &&
+            mode == CheckTaggedHoleMode::kConvertHoleToUndefined) {
+          ProcessInput(node, 0, UseInfo::CheckedSigned32AsWord32());
+          ProcessRemainingInputs(node, 1);
+          SetOutput(node, MachineRepresentation::kWord32);
+          if (lower()) DeferReplacement(node, node->InputAt(0));
+        } else {
+          ProcessInput(node, 0, UseInfo::AnyTagged());
+          ProcessRemainingInputs(node, 1);
+          SetOutput(node, MachineRepresentation::kTagged);
+        }
+        return;
       }
 
       //------------------------------------------------------------------
@@ -1231,8 +1899,7 @@
         ProcessInput(node, 0, UseInfo::AnyTagged());   // tagged pointer
         ProcessInput(node, 1, UseInfo::PointerInt());  // index
         ProcessRemainingInputs(node, 2);
-        SetOutput(node, rep.representation());
-        break;
+        return SetOutput(node, rep.representation());
       }
       case IrOpcode::kStore: {
         // TODO(jarin) Eventually, we should get rid of all machine stores
@@ -1243,8 +1910,7 @@
         ProcessInput(node, 2,
                      TruncatingUseInfoFromRepresentation(rep.representation()));
         ProcessRemainingInputs(node, 3);
-        SetOutput(node, MachineRepresentation::kNone);
-        break;
+        return SetOutput(node, MachineRepresentation::kNone);
       }
       case IrOpcode::kWord32Shr:
         // We output unsigned int32 for shift right because JavaScript.
@@ -1323,15 +1989,12 @@
         return VisitUnop(node, UseInfo::TruncatingWord32(),
                          MachineRepresentation::kWord64);
       case IrOpcode::kTruncateFloat64ToFloat32:
-        return VisitUnop(node, UseInfo::Float64(),
+        return VisitUnop(node, UseInfo::TruncatingFloat64(),
                          MachineRepresentation::kFloat32);
-      case IrOpcode::kTruncateFloat64ToInt32:
-        return VisitUnop(node, UseInfo::Float64(),
+      case IrOpcode::kTruncateFloat64ToWord32:
+        return VisitUnop(node, UseInfo::TruncatingFloat64(),
                          MachineRepresentation::kWord32);
 
-      case IrOpcode::kChangeFloat32ToFloat64:
-        return VisitUnop(node, UseInfo::Float32(),
-                         MachineRepresentation::kFloat64);
       case IrOpcode::kChangeInt32ToFloat64:
         return VisitUnop(node, UseInfo::TruncatingWord32(),
                          MachineRepresentation::kFloat64);
@@ -1351,7 +2014,10 @@
       case IrOpcode::kFloat64RoundTruncate:
       case IrOpcode::kFloat64RoundTiesAway:
       case IrOpcode::kFloat64RoundUp:
-        return VisitUnop(node, UseInfo::Float64(),
+        return VisitUnop(node, UseInfo::TruncatingFloat64(),
+                         MachineRepresentation::kFloat64);
+      case IrOpcode::kFloat64SilenceNaN:
+        return VisitUnop(node, UseInfo::TruncatingFloat64(),
                          MachineRepresentation::kFloat64);
       case IrOpcode::kFloat64Equal:
       case IrOpcode::kFloat64LessThan:
@@ -1359,19 +2025,24 @@
         return VisitFloat64Cmp(node);
       case IrOpcode::kFloat64ExtractLowWord32:
       case IrOpcode::kFloat64ExtractHighWord32:
-        return VisitUnop(node, UseInfo::Float64(),
+        return VisitUnop(node, UseInfo::TruncatingFloat64(),
                          MachineRepresentation::kWord32);
       case IrOpcode::kFloat64InsertLowWord32:
       case IrOpcode::kFloat64InsertHighWord32:
-        return VisitBinop(node, UseInfo::Float64(), UseInfo::TruncatingWord32(),
+        return VisitBinop(node, UseInfo::TruncatingFloat64(),
+                          UseInfo::TruncatingWord32(),
                           MachineRepresentation::kFloat64);
+      case IrOpcode::kNumberSilenceNaN:
+        VisitUnop(node, UseInfo::TruncatingFloat64(),
+                  MachineRepresentation::kFloat64);
+        if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
+        return;
       case IrOpcode::kLoadStackPointer:
       case IrOpcode::kLoadFramePointer:
       case IrOpcode::kLoadParentFramePointer:
         return VisitLeaf(node, MachineType::PointerRepresentation());
       case IrOpcode::kStateValues:
-        VisitStateValues(node);
-        break;
+        return VisitStateValues(node);
 
       // The following opcodes are not produced before representation
       // inference runs, so we do not have any real test coverage.
@@ -1379,14 +2050,24 @@
       case IrOpcode::kChangeFloat64ToInt32:
       case IrOpcode::kChangeFloat64ToUint32:
       case IrOpcode::kTruncateInt64ToInt32:
+      case IrOpcode::kChangeFloat32ToFloat64:
+      case IrOpcode::kCheckedInt32Add:
+      case IrOpcode::kCheckedInt32Sub:
+      case IrOpcode::kCheckedUint32ToInt32:
+      case IrOpcode::kCheckedFloat64ToInt32:
+      case IrOpcode::kCheckedTaggedToInt32:
+      case IrOpcode::kCheckedTaggedToFloat64:
+      case IrOpcode::kPlainPrimitiveToWord32:
+      case IrOpcode::kPlainPrimitiveToFloat64:
         FATAL("Representation inference: unsupported opcodes.");
+        break;
 
       default:
         VisitInputs(node);
         // Assume the output is tagged.
-        SetOutput(node, MachineRepresentation::kTagged);
-        break;
+        return SetOutput(node, MachineRepresentation::kTagged);
     }
+    UNREACHABLE();
   }
 
   void DeferReplacement(Node* node, Node* replacement) {
@@ -1394,8 +2075,20 @@
           node->op()->mnemonic(), replacement->id(),
           replacement->op()->mnemonic());
 
+    // Disconnect the node from effect and control chains, if necessary.
+    if (node->op()->EffectInputCount() > 0) {
+      DCHECK_LT(0, node->op()->ControlInputCount());
+      // Disconnect the node from effect and control chains.
+      Node* control = NodeProperties::GetControlInput(node);
+      Node* effect = NodeProperties::GetEffectInput(node);
+      ReplaceEffectControlUses(node, effect, control);
+    } else {
+      DCHECK_EQ(0, node->op()->ControlInputCount());
+    }
+
     if (replacement->id() < count_ &&
-        GetUpperBound(node)->Is(GetUpperBound(replacement))) {
+        GetUpperBound(node)->Is(GetUpperBound(replacement)) &&
+        TypeOf(node)->Is(TypeOf(replacement))) {
       // Replace with a previously existing node eagerly only if the type is the
       // same.
       node->ReplaceUses(replacement);
@@ -1427,19 +2120,20 @@
   void PrintTruncation(Truncation truncation) {
     if (FLAG_trace_representation) {
       OFStream os(stdout);
-      os << truncation.description();
+      os << truncation.description() << std::endl;
     }
   }
 
   void PrintUseInfo(UseInfo info) {
     if (FLAG_trace_representation) {
       OFStream os(stdout);
-      os << info.preferred() << ":" << info.truncation().description();
+      os << info.representation() << ":" << info.truncation().description();
     }
   }
 
  private:
   JSGraph* jsgraph_;
+  Zone* zone_;                      // Temporary zone.
   size_t const count_;              // number of nodes in the graph
   ZoneVector<NodeInfo> info_;       // node id -> usage information
 #ifdef DEBUG
@@ -1451,6 +2145,12 @@
   Phase phase_;                     // current phase of algorithm
   RepresentationChanger* changer_;  // for inserting representation changes
   ZoneQueue<Node*> queue_;          // queue for traversing the graph
+
+  struct NodeState {
+    Node* node;
+    int input_index;
+  };
+  ZoneStack<NodeState> typing_stack_;  // stack for graph typing.
   // TODO(danno): RepresentationSelector shouldn't know anything about the
   // source positions table, but must for now since there currently is no other
   // way to pass down source position information to nodes created during
@@ -1458,23 +2158,26 @@
   // position information via the SourcePositionWrapper like all other reducers.
   SourcePositionTable* source_positions_;
   TypeCache const& type_cache_;
+  OperationTyper op_typer_;  // helper for the feedback typer
 
   NodeInfo* GetInfo(Node* node) {
     DCHECK(node->id() >= 0);
     DCHECK(node->id() < count_);
     return &info_[node->id()];
   }
+  Zone* zone() { return zone_; }
+  Zone* graph_zone() { return jsgraph_->zone(); }
 };
 
-
 SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone,
-                                       SourcePositionTable* source_positions)
+                                       SourcePositionTable* source_positions,
+                                       Flags flags)
     : jsgraph_(jsgraph),
       zone_(zone),
       type_cache_(TypeCache::Get()),
+      flags_(flags),
       source_positions_(source_positions) {}
 
-
 void SimplifiedLowering::LowerAllNodes() {
   RepresentationChanger changer(jsgraph(), jsgraph()->isolate());
   RepresentationSelector selector(jsgraph(), zone_, &changer,
@@ -1482,6 +2185,166 @@
   selector.Run(this);
 }
 
+void SimplifiedLowering::DoJSToNumberTruncatesToFloat64(
+    Node* node, RepresentationSelector* selector) {
+  DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode());
+  Node* value = node->InputAt(0);
+  Node* context = node->InputAt(1);
+  Node* frame_state = node->InputAt(2);
+  Node* effect = node->InputAt(3);
+  Node* control = node->InputAt(4);
+  Node* throwing;
+
+  Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
+  Node* branch0 =
+      graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
+
+  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
+  Node* etrue0 = effect;
+  Node* vtrue0;
+  {
+    vtrue0 = graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
+    vtrue0 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue0);
+  }
+
+  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
+  Node* efalse0 = effect;
+  Node* vfalse0;
+  {
+    throwing = vfalse0 = efalse0 =
+        graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context,
+                         frame_state, efalse0, if_false0);
+    if_false0 = graph()->NewNode(common()->IfSuccess(), throwing);
+
+    Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
+    Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
+
+    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+    Node* etrue1 = efalse0;
+    Node* vtrue1;
+    {
+      vtrue1 =
+          graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
+      vtrue1 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue1);
+    }
+
+    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+    Node* efalse1 = efalse0;
+    Node* vfalse1;
+    {
+      vfalse1 = efalse1 = graph()->NewNode(
+          simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
+          efalse1, if_false1);
+    }
+
+    if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+    efalse0 =
+        graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
+    vfalse0 =
+        graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+                         vtrue1, vfalse1, if_false0);
+  }
+
+  control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
+  effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+                           vtrue0, vfalse0, control);
+
+  // Replace effect and control uses appropriately.
+  for (Edge edge : node->use_edges()) {
+    if (NodeProperties::IsControlEdge(edge)) {
+      if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
+        edge.from()->ReplaceUses(control);
+        edge.from()->Kill();
+      } else if (edge.from()->opcode() == IrOpcode::kIfException) {
+        edge.UpdateTo(throwing);
+      } else {
+        UNREACHABLE();
+      }
+    } else if (NodeProperties::IsEffectEdge(edge)) {
+      edge.UpdateTo(effect);
+    }
+  }
+
+  selector->DeferReplacement(node, value);
+}
+
+void SimplifiedLowering::DoJSToNumberTruncatesToWord32(
+    Node* node, RepresentationSelector* selector) {
+  DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode());
+  Node* value = node->InputAt(0);
+  Node* context = node->InputAt(1);
+  Node* frame_state = node->InputAt(2);
+  Node* effect = node->InputAt(3);
+  Node* control = node->InputAt(4);
+  Node* throwing;
+
+  Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
+  Node* branch0 =
+      graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
+
+  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
+  Node* etrue0 = effect;
+  Node* vtrue0 =
+      graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
+
+  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
+  Node* efalse0 = effect;
+  Node* vfalse0;
+  {
+    throwing = vfalse0 = efalse0 =
+        graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context,
+                         frame_state, efalse0, if_false0);
+    if_false0 = graph()->NewNode(common()->IfSuccess(), throwing);
+
+    Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
+    Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
+
+    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+    Node* etrue1 = efalse0;
+    Node* vtrue1 =
+        graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
+
+    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+    Node* efalse1 = efalse0;
+    Node* vfalse1;
+    {
+      vfalse1 = efalse1 = graph()->NewNode(
+          simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
+          efalse1, if_false1);
+      vfalse1 = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse1);
+    }
+
+    if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+    efalse0 =
+        graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
+    vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
+                               vtrue1, vfalse1, if_false0);
+  }
+
+  control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
+  effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
+  value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
+                           vtrue0, vfalse0, control);
+
+  // Replace effect and control uses appropriately.
+  for (Edge edge : node->use_edges()) {
+    if (NodeProperties::IsControlEdge(edge)) {
+      if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
+        edge.from()->ReplaceUses(control);
+        edge.from()->Kill();
+      } else if (edge.from()->opcode() == IrOpcode::kIfException) {
+        edge.UpdateTo(throwing);
+      } else {
+        UNREACHABLE();
+      }
+    } else if (NodeProperties::IsEffectEdge(edge)) {
+      edge.UpdateTo(effect);
+    }
+  }
+
+  selector->DeferReplacement(node, value);
+}
 
 void SimplifiedLowering::DoLoadBuffer(Node* node,
                                       MachineRepresentation output_rep,
@@ -1507,9 +2370,11 @@
     Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
     Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index,
                                    effect, if_true);
+    Type* element_type =
+        Type::Intersect(NodeProperties::GetType(node), Type::Number(), zone());
     Node* vtrue = changer->GetRepresentationFor(
-        etrue, access_type.representation(), NodeProperties::GetType(node),
-        output_rep, Truncation::None());
+        etrue, access_type.representation(), element_type, node,
+        UseInfo(output_rep, Truncation::None()));
 
     Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
     Node* efalse = effect;
@@ -1938,6 +2803,17 @@
                           vtrue0, vfalse0, merge0);
 }
 
+Node* SimplifiedLowering::Int32Abs(Node* const node) {
+  Node* const zero = jsgraph()->Int32Constant(0);
+  Node* const input = node->InputAt(0);
+
+  // if 0 < input then input else 0 - input
+  return graph()->NewNode(
+      common()->Select(MachineRepresentation::kWord32, BranchHint::kTrue),
+      graph()->NewNode(machine()->Int32LessThan(), zero, input), input,
+      graph()->NewNode(machine()->Int32Sub(), zero, input));
+}
+
 Node* SimplifiedLowering::Int32Div(Node* const node) {
   Int32BinopMatcher m(node);
   Node* const zero = jsgraph()->Int32Constant(0);
@@ -2200,6 +3076,26 @@
   NodeProperties::ChangeOp(node, op);
 }
 
+Node* SimplifiedLowering::ToNumberCode() {
+  if (!to_number_code_.is_set()) {
+    Callable callable = CodeFactory::ToNumber(isolate());
+    to_number_code_.set(jsgraph()->HeapConstant(callable.code()));
+  }
+  return to_number_code_.get();
+}
+
+Operator const* SimplifiedLowering::ToNumberOperator() {
+  if (!to_number_operator_.is_set()) {
+    Callable callable = CodeFactory::ToNumber(isolate());
+    CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
+    CallDescriptor* desc = Linkage::GetStubCallDescriptor(
+        isolate(), graph()->zone(), callable.descriptor(), 0, flags,
+        Operator::kNoProperties);
+    to_number_operator_.set(common()->Call(desc));
+  }
+  return to_number_operator_.get();
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/src/compiler/simplified-lowering.h b/src/compiler/simplified-lowering.h
index 8b711a9..75fd9c2 100644
--- a/src/compiler/simplified-lowering.h
+++ b/src/compiler/simplified-lowering.h
@@ -5,6 +5,7 @@
 #ifndef V8_COMPILER_SIMPLIFIED_LOWERING_H_
 #define V8_COMPILER_SIMPLIFIED_LOWERING_H_
 
+#include "src/base/flags.h"
 #include "src/compiler/js-graph.h"
 #include "src/compiler/machine-operator.h"
 #include "src/compiler/node.h"
@@ -21,16 +22,24 @@
 
 // Forward declarations.
 class RepresentationChanger;
+class RepresentationSelector;
 class SourcePositionTable;
 
 class SimplifiedLowering final {
  public:
+  enum Flag { kNoFlag = 0u, kTypeFeedbackEnabled = 1u << 0 };
+  typedef base::Flags<Flag> Flags;
   SimplifiedLowering(JSGraph* jsgraph, Zone* zone,
-                     SourcePositionTable* source_positions);
+                     SourcePositionTable* source_positions,
+                     Flags flags = kNoFlag);
   ~SimplifiedLowering() {}
 
   void LowerAllNodes();
 
+  void DoJSToNumberTruncatesToFloat64(Node* node,
+                                      RepresentationSelector* selector);
+  void DoJSToNumberTruncatesToWord32(Node* node,
+                                     RepresentationSelector* selector);
   // TODO(turbofan): The representation can be removed once the result of the
   // representation analysis is stored in the node bounds.
   void DoLoadBuffer(Node* node, MachineRepresentation rep,
@@ -38,15 +47,15 @@
   void DoStoreBuffer(Node* node);
   void DoShift(Node* node, Operator const* op, Type* rhs_type);
 
-  // TODO(bmeurer): This is a gigantic hack to support the gigantic LoadBuffer
-  // typing hack to support the gigantic "asm.js should be fast without proper
-  // verifier"-hack, ... Kill this! Soon! Really soon! I'm serious!
-  bool abort_compilation_ = false;
+  Flags flags() const { return flags_; }
 
  private:
   JSGraph* const jsgraph_;
   Zone* const zone_;
   TypeCache const& type_cache_;
+  SetOncePointer<Node> to_number_code_;
+  SetOncePointer<Operator const> to_number_operator_;
+  Flags flags_;
 
   // TODO(danno): SimplifiedLowering shouldn't know anything about the source
   // positions table, but must for now since there currently is no other way to
@@ -59,11 +68,15 @@
   Node* Float64Floor(Node* const node);
   Node* Float64Round(Node* const node);
   Node* Float64Trunc(Node* const node);
+  Node* Int32Abs(Node* const node);
   Node* Int32Div(Node* const node);
   Node* Int32Mod(Node* const node);
   Node* Uint32Div(Node* const node);
   Node* Uint32Mod(Node* const node);
 
+  Node* ToNumberCode();
+  Operator const* ToNumberOperator();
+
   friend class RepresentationSelector;
 
   Isolate* isolate() { return jsgraph_->isolate(); }
@@ -72,6 +85,7 @@
   Graph* graph() { return jsgraph()->graph(); }
   CommonOperatorBuilder* common() { return jsgraph()->common(); }
   MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
+  SimplifiedOperatorBuilder* simplified() { return jsgraph()->simplified(); }
 };
 
 }  // namespace compiler
diff --git a/src/compiler/simplified-operator-reducer.cc b/src/compiler/simplified-operator-reducer.cc
index 012004a..5db9dfb 100644
--- a/src/compiler/simplified-operator-reducer.cc
+++ b/src/compiler/simplified-operator-reducer.cc
@@ -8,6 +8,7 @@
 #include "src/compiler/machine-operator.h"
 #include "src/compiler/node-matchers.h"
 #include "src/compiler/operator-properties.h"
+#include "src/compiler/simplified-operator.h"
 #include "src/conversions-inl.h"
 #include "src/type-cache.h"
 
@@ -15,8 +16,27 @@
 namespace internal {
 namespace compiler {
 
-SimplifiedOperatorReducer::SimplifiedOperatorReducer(JSGraph* jsgraph)
-    : jsgraph_(jsgraph), type_cache_(TypeCache::Get()) {}
+namespace {
+
+Decision DecideObjectIsSmi(Node* const input) {
+  NumberMatcher m(input);
+  if (m.HasValue()) {
+    return IsSmiDouble(m.Value()) ? Decision::kTrue : Decision::kFalse;
+  }
+  if (m.IsAllocate()) return Decision::kFalse;
+  if (m.IsChangeBitToTagged()) return Decision::kFalse;
+  if (m.IsChangeInt31ToTaggedSigned()) return Decision::kTrue;
+  if (m.IsHeapConstant()) return Decision::kFalse;
+  return Decision::kUnknown;
+}
+
+}  // namespace
+
+SimplifiedOperatorReducer::SimplifiedOperatorReducer(Editor* editor,
+                                                     JSGraph* jsgraph)
+    : AdvancedReducer(editor),
+      jsgraph_(jsgraph),
+      type_cache_(TypeCache::Get()) {}
 
 SimplifiedOperatorReducer::~SimplifiedOperatorReducer() {}
 
@@ -31,34 +51,40 @@
       if (m.IsBooleanNot()) return Replace(m.InputAt(0));
       break;
     }
-    case IrOpcode::kChangeBitToBool: {
+    case IrOpcode::kChangeBitToTagged: {
       Int32Matcher m(node->InputAt(0));
       if (m.Is(0)) return Replace(jsgraph()->FalseConstant());
       if (m.Is(1)) return Replace(jsgraph()->TrueConstant());
-      if (m.IsChangeBoolToBit()) return Replace(m.InputAt(0));
+      if (m.IsChangeTaggedToBit()) return Replace(m.InputAt(0));
       break;
     }
-    case IrOpcode::kChangeBoolToBit: {
+    case IrOpcode::kChangeTaggedToBit: {
       HeapObjectMatcher m(node->InputAt(0));
       if (m.HasValue()) return ReplaceInt32(m.Value()->BooleanValue());
-      if (m.IsChangeBitToBool()) return Replace(m.InputAt(0));
+      if (m.IsChangeBitToTagged()) return Replace(m.InputAt(0));
       break;
     }
     case IrOpcode::kChangeFloat64ToTagged: {
       Float64Matcher m(node->InputAt(0));
       if (m.HasValue()) return ReplaceNumber(m.Value());
+      if (m.IsChangeTaggedToFloat64()) return Replace(m.node()->InputAt(0));
       break;
     }
+    case IrOpcode::kChangeInt31ToTaggedSigned:
     case IrOpcode::kChangeInt32ToTagged: {
       Int32Matcher m(node->InputAt(0));
       if (m.HasValue()) return ReplaceNumber(m.Value());
+      if (m.IsChangeTaggedToInt32() || m.IsChangeTaggedSignedToInt32()) {
+        return Replace(m.InputAt(0));
+      }
       break;
     }
-    case IrOpcode::kChangeTaggedToFloat64: {
+    case IrOpcode::kChangeTaggedToFloat64:
+    case IrOpcode::kTruncateTaggedToFloat64: {
       NumberMatcher m(node->InputAt(0));
       if (m.HasValue()) return ReplaceFloat64(m.Value());
       if (m.IsChangeFloat64ToTagged()) return Replace(m.node()->InputAt(0));
-      if (m.IsChangeInt32ToTagged()) {
+      if (m.IsChangeInt31ToTaggedSigned() || m.IsChangeInt32ToTagged()) {
         return Change(node, machine()->ChangeInt32ToFloat64(), m.InputAt(0));
       }
       if (m.IsChangeUint32ToTagged()) {
@@ -72,7 +98,9 @@
       if (m.IsChangeFloat64ToTagged()) {
         return Change(node, machine()->ChangeFloat64ToInt32(), m.InputAt(0));
       }
-      if (m.IsChangeInt32ToTagged()) return Replace(m.InputAt(0));
+      if (m.IsChangeInt31ToTaggedSigned() || m.IsChangeInt32ToTagged()) {
+        return Replace(m.InputAt(0));
+      }
       break;
     }
     case IrOpcode::kChangeTaggedToUint32: {
@@ -89,6 +117,51 @@
       if (m.HasValue()) return ReplaceNumber(FastUI2D(m.Value()));
       break;
     }
+    case IrOpcode::kTruncateTaggedToWord32: {
+      NumberMatcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
+      if (m.IsChangeInt31ToTaggedSigned() || m.IsChangeInt32ToTagged() ||
+          m.IsChangeUint32ToTagged()) {
+        return Replace(m.InputAt(0));
+      }
+      if (m.IsChangeFloat64ToTagged()) {
+        return Change(node, machine()->TruncateFloat64ToWord32(), m.InputAt(0));
+      }
+      break;
+    }
+    case IrOpcode::kCheckTaggedPointer: {
+      Node* const input = node->InputAt(0);
+      if (DecideObjectIsSmi(input) == Decision::kFalse) {
+        ReplaceWithValue(node, input);
+        return Replace(input);
+      }
+      break;
+    }
+    case IrOpcode::kCheckTaggedSigned: {
+      Node* const input = node->InputAt(0);
+      if (DecideObjectIsSmi(input) == Decision::kTrue) {
+        ReplaceWithValue(node, input);
+        return Replace(input);
+      }
+      break;
+    }
+    case IrOpcode::kObjectIsSmi: {
+      Node* const input = node->InputAt(0);
+      switch (DecideObjectIsSmi(input)) {
+        case Decision::kTrue:
+          return ReplaceBoolean(true);
+        case Decision::kFalse:
+          return ReplaceBoolean(false);
+        case Decision::kUnknown:
+          break;
+      }
+      break;
+    }
+    case IrOpcode::kNumberAbs: {
+      NumberMatcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceNumber(std::fabs(m.Value()));
+      break;
+    }
     case IrOpcode::kNumberCeil:
     case IrOpcode::kNumberFloor:
     case IrOpcode::kNumberRound:
@@ -102,6 +175,8 @@
     }
     case IrOpcode::kReferenceEqual:
       return ReduceReferenceEqual(node);
+    case IrOpcode::kTypeGuard:
+      return ReduceTypeGuard(node);
     default:
       break;
   }
@@ -124,6 +199,14 @@
   return NoChange();
 }
 
+Reduction SimplifiedOperatorReducer::ReduceTypeGuard(Node* node) {
+  DCHECK_EQ(IrOpcode::kTypeGuard, node->opcode());
+  Node* const input = NodeProperties::GetValueInput(node, 0);
+  Type* const input_type = NodeProperties::GetTypeOrAny(input);
+  Type* const guard_type = TypeOf(node->op());
+  if (input_type->Is(guard_type)) return Replace(input);
+  return NoChange();
+}
 
 Reduction SimplifiedOperatorReducer::Change(Node* node, const Operator* op,
                                             Node* a) {
@@ -134,6 +217,9 @@
   return Changed(node);
 }
 
+Reduction SimplifiedOperatorReducer::ReplaceBoolean(bool value) {
+  return Replace(jsgraph()->BooleanConstant(value));
+}
 
 Reduction SimplifiedOperatorReducer::ReplaceFloat64(double value) {
   return Replace(jsgraph()->Float64Constant(value));
diff --git a/src/compiler/simplified-operator-reducer.h b/src/compiler/simplified-operator-reducer.h
index 13301c2..6ee903b 100644
--- a/src/compiler/simplified-operator-reducer.h
+++ b/src/compiler/simplified-operator-reducer.h
@@ -20,18 +20,19 @@
 class MachineOperatorBuilder;
 class SimplifiedOperatorBuilder;
 
-
-class SimplifiedOperatorReducer final : public Reducer {
+class SimplifiedOperatorReducer final : public AdvancedReducer {
  public:
-  explicit SimplifiedOperatorReducer(JSGraph* jsgraph);
+  SimplifiedOperatorReducer(Editor* editor, JSGraph* jsgraph);
   ~SimplifiedOperatorReducer() final;
 
   Reduction Reduce(Node* node) final;
 
  private:
   Reduction ReduceReferenceEqual(Node* node);
+  Reduction ReduceTypeGuard(Node* node);
 
   Reduction Change(Node* node, const Operator* op, Node* a);
+  Reduction ReplaceBoolean(bool value);
   Reduction ReplaceFloat64(double value);
   Reduction ReplaceInt32(int32_t value);
   Reduction ReplaceUint32(uint32_t value) {
diff --git a/src/compiler/simplified-operator.cc b/src/compiler/simplified-operator.cc
index daa9501..0f32b0c 100644
--- a/src/compiler/simplified-operator.cc
+++ b/src/compiler/simplified-operator.cc
@@ -13,6 +13,10 @@
 namespace internal {
 namespace compiler {
 
+size_t hash_value(BaseTaggedness base_taggedness) {
+  return static_cast<uint8_t>(base_taggedness);
+}
+
 std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) {
   switch (base_taggedness) {
     case kUntaggedBase:
@@ -84,6 +88,9 @@
 
 
 bool operator==(FieldAccess const& lhs, FieldAccess const& rhs) {
+  // On purpose we don't include the write barrier kind here, as this method is
+  // really only relevant for eliminating loads and they don't care about the
+  // write barrier mode.
   return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset &&
          lhs.machine_type == rhs.machine_type;
 }
@@ -95,6 +102,9 @@
 
 
 size_t hash_value(FieldAccess const& access) {
+  // On purpose we don't include the write barrier kind here, as this method is
+  // really only relevant for eliminating loads and they don't care about the
+  // write barrier mode.
   return base::hash_combine(access.base_is_tagged, access.offset,
                             access.machine_type);
 }
@@ -110,12 +120,15 @@
   }
 #endif
   access.type->PrintTo(os);
-  os << ", " << access.machine_type << "]";
+  os << ", " << access.machine_type << ", " << access.write_barrier_kind << "]";
   return os;
 }
 
 
 bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) {
+  // On purpose we don't include the write barrier kind here, as this method is
+  // really only relevant for eliminating loads and they don't care about the
+  // write barrier mode.
   return lhs.base_is_tagged == rhs.base_is_tagged &&
          lhs.header_size == rhs.header_size &&
          lhs.machine_type == rhs.machine_type;
@@ -128,6 +141,9 @@
 
 
 size_t hash_value(ElementAccess const& access) {
+  // On purpose we don't include the write barrier kind here, as this method is
+  // really only relevant for eliminating loads and they don't care about the
+  // write barrier mode.
   return base::hash_combine(access.base_is_tagged, access.header_size,
                             access.machine_type);
 }
@@ -136,7 +152,7 @@
 std::ostream& operator<<(std::ostream& os, ElementAccess const& access) {
   os << access.base_is_tagged << ", " << access.header_size << ", ";
   access.type->PrintTo(os);
-  os << ", " << access.machine_type;
+  os << ", " << access.machine_type << ", " << access.write_barrier_kind;
   return os;
 }
 
@@ -156,51 +172,152 @@
   return OpParameter<ElementAccess>(op);
 }
 
-#define PURE_OP_LIST(V)                                  \
-  V(BooleanNot, Operator::kNoProperties, 1)              \
-  V(BooleanToNumber, Operator::kNoProperties, 1)         \
-  V(NumberEqual, Operator::kCommutative, 2)              \
-  V(NumberLessThan, Operator::kNoProperties, 2)          \
-  V(NumberLessThanOrEqual, Operator::kNoProperties, 2)   \
-  V(NumberAdd, Operator::kCommutative, 2)                \
-  V(NumberSubtract, Operator::kNoProperties, 2)          \
-  V(NumberMultiply, Operator::kCommutative, 2)           \
-  V(NumberDivide, Operator::kNoProperties, 2)            \
-  V(NumberModulus, Operator::kNoProperties, 2)           \
-  V(NumberBitwiseOr, Operator::kCommutative, 2)          \
-  V(NumberBitwiseXor, Operator::kCommutative, 2)         \
-  V(NumberBitwiseAnd, Operator::kCommutative, 2)         \
-  V(NumberShiftLeft, Operator::kNoProperties, 2)         \
-  V(NumberShiftRight, Operator::kNoProperties, 2)        \
-  V(NumberShiftRightLogical, Operator::kNoProperties, 2) \
-  V(NumberImul, Operator::kNoProperties, 2)              \
-  V(NumberClz32, Operator::kNoProperties, 1)             \
-  V(NumberCeil, Operator::kNoProperties, 1)              \
-  V(NumberFloor, Operator::kNoProperties, 1)             \
-  V(NumberRound, Operator::kNoProperties, 1)             \
-  V(NumberTrunc, Operator::kNoProperties, 1)             \
-  V(NumberToInt32, Operator::kNoProperties, 1)           \
-  V(NumberToUint32, Operator::kNoProperties, 1)          \
-  V(NumberIsHoleNaN, Operator::kNoProperties, 1)         \
-  V(PlainPrimitiveToNumber, Operator::kNoProperties, 1)  \
-  V(StringToNumber, Operator::kNoProperties, 1)          \
-  V(ChangeTaggedToInt32, Operator::kNoProperties, 1)     \
-  V(ChangeTaggedToUint32, Operator::kNoProperties, 1)    \
-  V(ChangeTaggedToFloat64, Operator::kNoProperties, 1)   \
-  V(ChangeInt32ToTagged, Operator::kNoProperties, 1)     \
-  V(ChangeUint32ToTagged, Operator::kNoProperties, 1)    \
-  V(ChangeFloat64ToTagged, Operator::kNoProperties, 1)   \
-  V(ChangeBoolToBit, Operator::kNoProperties, 1)         \
-  V(ChangeBitToBool, Operator::kNoProperties, 1)         \
-  V(ObjectIsNumber, Operator::kNoProperties, 1)          \
-  V(ObjectIsReceiver, Operator::kNoProperties, 1)        \
-  V(ObjectIsSmi, Operator::kNoProperties, 1)             \
-  V(ObjectIsUndetectable, Operator::kNoProperties, 1)
+size_t hash_value(CheckFloat64HoleMode mode) {
+  return static_cast<size_t>(mode);
+}
 
-#define NO_THROW_OP_LIST(V)                 \
-  V(StringEqual, Operator::kCommutative, 2) \
-  V(StringLessThan, Operator::kNoThrow, 2)  \
-  V(StringLessThanOrEqual, Operator::kNoThrow, 2)
+std::ostream& operator<<(std::ostream& os, CheckFloat64HoleMode mode) {
+  switch (mode) {
+    case CheckFloat64HoleMode::kAllowReturnHole:
+      return os << "allow-return-hole";
+    case CheckFloat64HoleMode::kNeverReturnHole:
+      return os << "never-return-hole";
+  }
+  UNREACHABLE();
+  return os;
+}
+
+CheckFloat64HoleMode CheckFloat64HoleModeOf(const Operator* op) {
+  DCHECK_EQ(IrOpcode::kCheckFloat64Hole, op->opcode());
+  return OpParameter<CheckFloat64HoleMode>(op);
+}
+
+size_t hash_value(CheckTaggedHoleMode mode) {
+  return static_cast<size_t>(mode);
+}
+
+std::ostream& operator<<(std::ostream& os, CheckTaggedHoleMode mode) {
+  switch (mode) {
+    case CheckTaggedHoleMode::kConvertHoleToUndefined:
+      return os << "convert-hole-to-undefined";
+    case CheckTaggedHoleMode::kNeverReturnHole:
+      return os << "never-return-hole";
+  }
+  UNREACHABLE();
+  return os;
+}
+
+CheckTaggedHoleMode CheckTaggedHoleModeOf(const Operator* op) {
+  DCHECK_EQ(IrOpcode::kCheckTaggedHole, op->opcode());
+  return OpParameter<CheckTaggedHoleMode>(op);
+}
+
+Type* TypeOf(const Operator* op) {
+  DCHECK_EQ(IrOpcode::kTypeGuard, op->opcode());
+  return OpParameter<Type*>(op);
+}
+
+BinaryOperationHints::Hint BinaryOperationHintOf(const Operator* op) {
+  DCHECK(op->opcode() == IrOpcode::kSpeculativeNumberAdd ||
+         op->opcode() == IrOpcode::kSpeculativeNumberSubtract ||
+         op->opcode() == IrOpcode::kSpeculativeNumberMultiply ||
+         op->opcode() == IrOpcode::kSpeculativeNumberDivide ||
+         op->opcode() == IrOpcode::kSpeculativeNumberModulus);
+  return OpParameter<BinaryOperationHints::Hint>(op);
+}
+
+CompareOperationHints::Hint CompareOperationHintOf(const Operator* op) {
+  DCHECK(op->opcode() == IrOpcode::kSpeculativeNumberEqual ||
+         op->opcode() == IrOpcode::kSpeculativeNumberLessThan ||
+         op->opcode() == IrOpcode::kSpeculativeNumberLessThanOrEqual);
+  return OpParameter<CompareOperationHints::Hint>(op);
+}
+
+#define PURE_OP_LIST(V)                                    \
+  V(BooleanNot, Operator::kNoProperties, 1)                \
+  V(BooleanToNumber, Operator::kNoProperties, 1)           \
+  V(NumberEqual, Operator::kCommutative, 2)                \
+  V(NumberLessThan, Operator::kNoProperties, 2)            \
+  V(NumberLessThanOrEqual, Operator::kNoProperties, 2)     \
+  V(NumberAdd, Operator::kCommutative, 2)                  \
+  V(NumberSubtract, Operator::kNoProperties, 2)            \
+  V(NumberMultiply, Operator::kCommutative, 2)             \
+  V(NumberDivide, Operator::kNoProperties, 2)              \
+  V(NumberModulus, Operator::kNoProperties, 2)             \
+  V(NumberBitwiseOr, Operator::kCommutative, 2)            \
+  V(NumberBitwiseXor, Operator::kCommutative, 2)           \
+  V(NumberBitwiseAnd, Operator::kCommutative, 2)           \
+  V(NumberShiftLeft, Operator::kNoProperties, 2)           \
+  V(NumberShiftRight, Operator::kNoProperties, 2)          \
+  V(NumberShiftRightLogical, Operator::kNoProperties, 2)   \
+  V(NumberImul, Operator::kCommutative, 2)                 \
+  V(NumberAbs, Operator::kNoProperties, 1)                 \
+  V(NumberClz32, Operator::kNoProperties, 1)               \
+  V(NumberCeil, Operator::kNoProperties, 1)                \
+  V(NumberFloor, Operator::kNoProperties, 1)               \
+  V(NumberFround, Operator::kNoProperties, 1)              \
+  V(NumberAtan, Operator::kNoProperties, 1)                \
+  V(NumberAtan2, Operator::kNoProperties, 2)               \
+  V(NumberAtanh, Operator::kNoProperties, 1)               \
+  V(NumberCbrt, Operator::kNoProperties, 1)                \
+  V(NumberCos, Operator::kNoProperties, 1)                 \
+  V(NumberExp, Operator::kNoProperties, 1)                 \
+  V(NumberExpm1, Operator::kNoProperties, 1)               \
+  V(NumberLog, Operator::kNoProperties, 1)                 \
+  V(NumberLog1p, Operator::kNoProperties, 1)               \
+  V(NumberLog10, Operator::kNoProperties, 1)               \
+  V(NumberLog2, Operator::kNoProperties, 1)                \
+  V(NumberRound, Operator::kNoProperties, 1)               \
+  V(NumberSin, Operator::kNoProperties, 1)                 \
+  V(NumberSqrt, Operator::kNoProperties, 1)                \
+  V(NumberTan, Operator::kNoProperties, 1)                 \
+  V(NumberTrunc, Operator::kNoProperties, 1)               \
+  V(NumberToInt32, Operator::kNoProperties, 1)             \
+  V(NumberToUint32, Operator::kNoProperties, 1)            \
+  V(NumberSilenceNaN, Operator::kNoProperties, 1)          \
+  V(StringFromCharCode, Operator::kNoProperties, 1)        \
+  V(StringToNumber, Operator::kNoProperties, 1)            \
+  V(PlainPrimitiveToNumber, Operator::kNoProperties, 1)    \
+  V(PlainPrimitiveToWord32, Operator::kNoProperties, 1)    \
+  V(PlainPrimitiveToFloat64, Operator::kNoProperties, 1)   \
+  V(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1) \
+  V(ChangeTaggedToInt32, Operator::kNoProperties, 1)       \
+  V(ChangeTaggedToUint32, Operator::kNoProperties, 1)      \
+  V(ChangeTaggedToFloat64, Operator::kNoProperties, 1)     \
+  V(ChangeInt31ToTaggedSigned, Operator::kNoProperties, 1) \
+  V(ChangeInt32ToTagged, Operator::kNoProperties, 1)       \
+  V(ChangeUint32ToTagged, Operator::kNoProperties, 1)      \
+  V(ChangeFloat64ToTagged, Operator::kNoProperties, 1)     \
+  V(ChangeTaggedToBit, Operator::kNoProperties, 1)         \
+  V(ChangeBitToTagged, Operator::kNoProperties, 1)         \
+  V(TruncateTaggedToWord32, Operator::kNoProperties, 1)    \
+  V(TruncateTaggedToFloat64, Operator::kNoProperties, 1)   \
+  V(ObjectIsCallable, Operator::kNoProperties, 1)          \
+  V(ObjectIsNumber, Operator::kNoProperties, 1)            \
+  V(ObjectIsReceiver, Operator::kNoProperties, 1)          \
+  V(ObjectIsSmi, Operator::kNoProperties, 1)               \
+  V(ObjectIsString, Operator::kNoProperties, 1)            \
+  V(ObjectIsUndetectable, Operator::kNoProperties, 1)      \
+  V(StringEqual, Operator::kCommutative, 2)                \
+  V(StringLessThan, Operator::kNoProperties, 2)            \
+  V(StringLessThanOrEqual, Operator::kNoProperties, 2)
+
+#define SPECULATIVE_BINOP_LIST(V) \
+  V(SpeculativeNumberAdd)         \
+  V(SpeculativeNumberSubtract)    \
+  V(SpeculativeNumberDivide)      \
+  V(SpeculativeNumberMultiply)    \
+  V(SpeculativeNumberModulus)
+
+#define CHECKED_OP_LIST(V)    \
+  V(CheckTaggedPointer, 1)    \
+  V(CheckTaggedSigned, 1)     \
+  V(CheckedInt32Add, 2)       \
+  V(CheckedInt32Sub, 2)       \
+  V(CheckedUint32ToInt32, 1)  \
+  V(CheckedFloat64ToInt32, 1) \
+  V(CheckedTaggedToInt32, 1)  \
+  V(CheckedTaggedToFloat64, 1)
 
 struct SimplifiedOperatorGlobalCache final {
 #define PURE(Name, properties, input_count)                                \
@@ -213,30 +330,71 @@
   PURE_OP_LIST(PURE)
 #undef PURE
 
-#define NO_THROW(Name, properties, input_count)                               \
-  struct Name##Operator final : public Operator {                             \
-    Name##Operator()                                                          \
-        : Operator(IrOpcode::k##Name, Operator::kNoThrow | properties, #Name, \
-                   input_count, 1, 1, 1, 1, 0) {}                             \
-  };                                                                          \
+#define CHECKED(Name, value_input_count)                            \
+  struct Name##Operator final : public Operator {                   \
+    Name##Operator()                                                \
+        : Operator(IrOpcode::k##Name,                               \
+                   Operator::kFoldable | Operator::kNoThrow, #Name, \
+                   value_input_count, 1, 1, 1, 1, 0) {}             \
+  };                                                                \
   Name##Operator k##Name;
-  NO_THROW_OP_LIST(NO_THROW)
-#undef NO_THROW
+  CHECKED_OP_LIST(CHECKED)
+#undef CHECKED
+
+  template <CheckFloat64HoleMode kMode>
+  struct CheckFloat64HoleNaNOperator final
+      : public Operator1<CheckFloat64HoleMode> {
+    CheckFloat64HoleNaNOperator()
+        : Operator1<CheckFloat64HoleMode>(
+              IrOpcode::kCheckFloat64Hole,
+              Operator::kFoldable | Operator::kNoThrow, "CheckFloat64Hole", 1,
+              1, 1, 1, 1, 0, kMode) {}
+  };
+  CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kAllowReturnHole>
+      kCheckFloat64HoleAllowReturnHoleOperator;
+  CheckFloat64HoleNaNOperator<CheckFloat64HoleMode::kNeverReturnHole>
+      kCheckFloat64HoleNeverReturnHoleOperator;
+
+  template <CheckTaggedHoleMode kMode>
+  struct CheckTaggedHoleOperator final : public Operator1<CheckTaggedHoleMode> {
+    CheckTaggedHoleOperator()
+        : Operator1<CheckTaggedHoleMode>(
+              IrOpcode::kCheckTaggedHole,
+              Operator::kFoldable | Operator::kNoThrow, "CheckTaggedHole", 1, 1,
+              1, 1, 1, 0, kMode) {}
+  };
+  CheckTaggedHoleOperator<CheckTaggedHoleMode::kConvertHoleToUndefined>
+      kCheckTaggedHoleConvertHoleToUndefinedOperator;
+  CheckTaggedHoleOperator<CheckTaggedHoleMode::kNeverReturnHole>
+      kCheckTaggedHoleNeverReturnHoleOperator;
+
+  template <PretenureFlag kPretenure>
+  struct AllocateOperator final : public Operator1<PretenureFlag> {
+    AllocateOperator()
+        : Operator1<PretenureFlag>(
+              IrOpcode::kAllocate,
+              Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite,
+              "Allocate", 1, 1, 1, 1, 1, 0, kPretenure) {}
+  };
+  AllocateOperator<NOT_TENURED> kAllocateNotTenuredOperator;
+  AllocateOperator<TENURED> kAllocateTenuredOperator;
 
 #define BUFFER_ACCESS(Type, type, TYPE, ctype, size)                          \
   struct LoadBuffer##Type##Operator final : public Operator1<BufferAccess> {  \
     LoadBuffer##Type##Operator()                                              \
-        : Operator1<BufferAccess>(IrOpcode::kLoadBuffer,                      \
-                                  Operator::kNoThrow | Operator::kNoWrite,    \
-                                  "LoadBuffer", 3, 1, 1, 1, 1, 0,             \
-                                  BufferAccess(kExternal##Type##Array)) {}    \
+        : Operator1<BufferAccess>(                                            \
+              IrOpcode::kLoadBuffer,                                          \
+              Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite,   \
+              "LoadBuffer", 3, 1, 1, 1, 1, 0,                                 \
+              BufferAccess(kExternal##Type##Array)) {}                        \
   };                                                                          \
   struct StoreBuffer##Type##Operator final : public Operator1<BufferAccess> { \
     StoreBuffer##Type##Operator()                                             \
-        : Operator1<BufferAccess>(IrOpcode::kStoreBuffer,                     \
-                                  Operator::kNoRead | Operator::kNoThrow,     \
-                                  "StoreBuffer", 4, 1, 1, 0, 1, 0,            \
-                                  BufferAccess(kExternal##Type##Array)) {}    \
+        : Operator1<BufferAccess>(                                            \
+              IrOpcode::kStoreBuffer,                                         \
+              Operator::kNoDeopt | Operator::kNoRead | Operator::kNoThrow,    \
+              "StoreBuffer", 4, 1, 1, 0, 1, 0,                                \
+              BufferAccess(kExternal##Type##Array)) {}                        \
   };                                                                          \
   LoadBuffer##Type##Operator kLoadBuffer##Type;                               \
   StoreBuffer##Type##Operator kStoreBuffer##Type;
@@ -252,13 +410,39 @@
 SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
     : cache_(kCache.Get()), zone_(zone) {}
 
-
 #define GET_FROM_CACHE(Name, properties, input_count) \
   const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
 PURE_OP_LIST(GET_FROM_CACHE)
-NO_THROW_OP_LIST(GET_FROM_CACHE)
 #undef GET_FROM_CACHE
 
+#define GET_FROM_CACHE(Name, value_input_count) \
+  const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
+CHECKED_OP_LIST(GET_FROM_CACHE)
+#undef GET_FROM_CACHE
+
+const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole(
+    CheckFloat64HoleMode mode) {
+  switch (mode) {
+    case CheckFloat64HoleMode::kAllowReturnHole:
+      return &cache_.kCheckFloat64HoleAllowReturnHoleOperator;
+    case CheckFloat64HoleMode::kNeverReturnHole:
+      return &cache_.kCheckFloat64HoleNeverReturnHoleOperator;
+  }
+  UNREACHABLE();
+  return nullptr;
+}
+
+const Operator* SimplifiedOperatorBuilder::CheckTaggedHole(
+    CheckTaggedHoleMode mode) {
+  switch (mode) {
+    case CheckTaggedHoleMode::kConvertHoleToUndefined:
+      return &cache_.kCheckTaggedHoleConvertHoleToUndefinedOperator;
+    case CheckTaggedHoleMode::kNeverReturnHole:
+      return &cache_.kCheckTaggedHoleNeverReturnHoleOperator;
+  }
+  UNREACHABLE();
+  return nullptr;
+}
 
 const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) {
   return new (zone()) Operator(IrOpcode::kReferenceEqual,
@@ -266,11 +450,39 @@
                                "ReferenceEqual", 2, 0, 0, 1, 0, 0);
 }
 
+const Operator* SimplifiedOperatorBuilder::CheckBounds() {
+  // TODO(bmeurer): Cache this operator. Make it pure!
+  return new (zone())
+      Operator(IrOpcode::kCheckBounds, Operator::kFoldable | Operator::kNoThrow,
+               "CheckBounds", 2, 1, 1, 1, 1, 0);
+}
+
+const Operator* SimplifiedOperatorBuilder::TypeGuard(Type* type) {
+  class TypeGuardOperator final : public Operator1<Type*> {
+   public:
+    explicit TypeGuardOperator(Type* type)
+        : Operator1<Type*>(                           // --
+              IrOpcode::kTypeGuard, Operator::kPure,  // opcode
+              "TypeGuard",                            // name
+              1, 0, 1, 1, 0, 0,                       // counts
+              type) {}                                // parameter
+
+    void PrintParameter(std::ostream& os) const final {
+      parameter()->PrintTo(os);
+    }
+  };
+  return new (zone()) TypeGuardOperator(type);
+}
 
 const Operator* SimplifiedOperatorBuilder::Allocate(PretenureFlag pretenure) {
-  return new (zone())
-      Operator1<PretenureFlag>(IrOpcode::kAllocate, Operator::kNoThrow,
-                               "Allocate", 1, 1, 1, 1, 1, 0, pretenure);
+  switch (pretenure) {
+    case NOT_TENURED:
+      return &cache_.kAllocateNotTenuredOperator;
+    case TENURED:
+      return &cache_.kAllocateTenuredOperator;
+  }
+  UNREACHABLE();
+  return nullptr;
 }
 
 
@@ -299,6 +511,39 @@
   return nullptr;
 }
 
+#define SPECULATIVE_BINOP_DEF(Name)                                            \
+  const Operator* SimplifiedOperatorBuilder::Name(                             \
+      BinaryOperationHints::Hint hint) {                                       \
+    return new (zone()) Operator1<BinaryOperationHints::Hint>(                 \
+        IrOpcode::k##Name, Operator::kFoldable | Operator::kNoThrow, #Name, 2, \
+        1, 1, 1, 1, 0, hint);                                                  \
+  }
+SPECULATIVE_BINOP_LIST(SPECULATIVE_BINOP_DEF)
+#undef SPECULATIVE_BINOP_DEF
+
+const Operator* SimplifiedOperatorBuilder::SpeculativeNumberEqual(
+    CompareOperationHints::Hint hint) {
+  return new (zone()) Operator1<CompareOperationHints::Hint>(
+      IrOpcode::kSpeculativeNumberEqual,
+      Operator::kFoldable | Operator::kNoThrow, "SpeculativeNumberEqual", 2, 1,
+      1, 1, 1, 0, hint);
+}
+
+const Operator* SimplifiedOperatorBuilder::SpeculativeNumberLessThan(
+    CompareOperationHints::Hint hint) {
+  return new (zone()) Operator1<CompareOperationHints::Hint>(
+      IrOpcode::kSpeculativeNumberLessThan,
+      Operator::kFoldable | Operator::kNoThrow, "SpeculativeNumberLessThan", 2,
+      1, 1, 1, 1, 0, hint);
+}
+
+const Operator* SimplifiedOperatorBuilder::SpeculativeNumberLessThanOrEqual(
+    CompareOperationHints::Hint hint) {
+  return new (zone()) Operator1<CompareOperationHints::Hint>(
+      IrOpcode::kSpeculativeNumberLessThanOrEqual,
+      Operator::kFoldable | Operator::kNoThrow,
+      "SpeculativeNumberLessThanOrEqual", 2, 1, 1, 1, 1, 0, hint);
+}
 
 #define ACCESS_OP_LIST(V)                                    \
   V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1)     \
@@ -306,12 +551,12 @@
   V(LoadElement, ElementAccess, Operator::kNoWrite, 2, 1, 1) \
   V(StoreElement, ElementAccess, Operator::kNoRead, 3, 1, 0)
 
-
 #define ACCESS(Name, Type, properties, value_input_count, control_input_count, \
                output_count)                                                   \
   const Operator* SimplifiedOperatorBuilder::Name(const Type& access) {        \
     return new (zone())                                                        \
-        Operator1<Type>(IrOpcode::k##Name, Operator::kNoThrow | properties,    \
+        Operator1<Type>(IrOpcode::k##Name,                                     \
+                        Operator::kNoDeopt | Operator::kNoThrow | properties,  \
                         #Name, value_input_count, 1, control_input_count,      \
                         output_count, 1, 0, access);                           \
   }
diff --git a/src/compiler/simplified-operator.h b/src/compiler/simplified-operator.h
index a39d864..ffdf33f 100644
--- a/src/compiler/simplified-operator.h
+++ b/src/compiler/simplified-operator.h
@@ -7,6 +7,7 @@
 
 #include <iosfwd>
 
+#include "src/compiler/type-hints.h"
 #include "src/handles.h"
 #include "src/machine-type.h"
 #include "src/objects.h"
@@ -25,8 +26,9 @@
 class Operator;
 struct SimplifiedOperatorGlobalCache;
 
+enum BaseTaggedness : uint8_t { kUntaggedBase, kTaggedBase };
 
-enum BaseTaggedness { kUntaggedBase, kTaggedBase };
+size_t hash_value(BaseTaggedness);
 
 std::ostream& operator<<(std::ostream&, BaseTaggedness);
 
@@ -63,6 +65,7 @@
   MaybeHandle<Name> name;         // debugging only.
   Type* type;                     // type of the field.
   MachineType machine_type;       // machine type of the field.
+  WriteBarrierKind write_barrier_kind;  // write barrier hint.
 
   int tag() const { return base_is_tagged == kTaggedBase ? kHeapObjectTag : 0; }
 };
@@ -86,6 +89,7 @@
   int header_size;                // size of the header, without tag.
   Type* type;                     // type of the element.
   MachineType machine_type;       // machine type of the element.
+  WriteBarrierKind write_barrier_kind;  // write barrier hint.
 
   int tag() const { return base_is_tagged == kTaggedBase ? kHeapObjectTag : 0; }
 };
@@ -99,6 +103,33 @@
 
 ElementAccess const& ElementAccessOf(const Operator* op) WARN_UNUSED_RESULT;
 
+enum class CheckFloat64HoleMode : uint8_t {
+  kNeverReturnHole,  // Never return the hole (deoptimize instead).
+  kAllowReturnHole   // Allow to return the hole (signaling NaN).
+};
+
+size_t hash_value(CheckFloat64HoleMode);
+
+std::ostream& operator<<(std::ostream&, CheckFloat64HoleMode);
+
+CheckFloat64HoleMode CheckFloat64HoleModeOf(const Operator*) WARN_UNUSED_RESULT;
+
+enum class CheckTaggedHoleMode : uint8_t {
+  kNeverReturnHole,        // Never return the hole (deoptimize instead).
+  kConvertHoleToUndefined  // Convert the hole to undefined.
+};
+
+size_t hash_value(CheckTaggedHoleMode);
+
+std::ostream& operator<<(std::ostream&, CheckTaggedHoleMode);
+
+CheckTaggedHoleMode CheckTaggedHoleModeOf(const Operator*) WARN_UNUSED_RESULT;
+
+Type* TypeOf(const Operator* op) WARN_UNUSED_RESULT;
+
+BinaryOperationHints::Hint BinaryOperationHintOf(const Operator* op);
+
+CompareOperationHints::Hint CompareOperationHintOf(const Operator* op);
 
 // Interface for building simplified operators, which represent the
 // medium-level operations of V8, including adding numbers, allocating objects,
@@ -144,38 +175,91 @@
   const Operator* NumberShiftRight();
   const Operator* NumberShiftRightLogical();
   const Operator* NumberImul();
+  const Operator* NumberAbs();
   const Operator* NumberClz32();
   const Operator* NumberCeil();
   const Operator* NumberFloor();
+  const Operator* NumberFround();
+  const Operator* NumberAtan();
+  const Operator* NumberAtan2();
+  const Operator* NumberAtanh();
+  const Operator* NumberCbrt();
+  const Operator* NumberCos();
+  const Operator* NumberExp();
+  const Operator* NumberExpm1();
+  const Operator* NumberLog();
+  const Operator* NumberLog1p();
+  const Operator* NumberLog10();
+  const Operator* NumberLog2();
   const Operator* NumberRound();
+  const Operator* NumberSin();
+  const Operator* NumberSqrt();
+  const Operator* NumberTan();
   const Operator* NumberTrunc();
   const Operator* NumberToInt32();
   const Operator* NumberToUint32();
-  const Operator* NumberIsHoleNaN();
 
-  const Operator* PlainPrimitiveToNumber();
+  const Operator* NumberSilenceNaN();
+
+  const Operator* SpeculativeNumberAdd(BinaryOperationHints::Hint hint);
+  const Operator* SpeculativeNumberSubtract(BinaryOperationHints::Hint hint);
+  const Operator* SpeculativeNumberMultiply(BinaryOperationHints::Hint hint);
+  const Operator* SpeculativeNumberDivide(BinaryOperationHints::Hint hint);
+  const Operator* SpeculativeNumberModulus(BinaryOperationHints::Hint hint);
+
+  const Operator* SpeculativeNumberLessThan(CompareOperationHints::Hint hint);
+  const Operator* SpeculativeNumberLessThanOrEqual(
+      CompareOperationHints::Hint hint);
+  const Operator* SpeculativeNumberEqual(CompareOperationHints::Hint hint);
 
   const Operator* ReferenceEqual(Type* type);
 
   const Operator* StringEqual();
   const Operator* StringLessThan();
   const Operator* StringLessThanOrEqual();
+  const Operator* StringFromCharCode();
   const Operator* StringToNumber();
 
+  const Operator* PlainPrimitiveToNumber();
+  const Operator* PlainPrimitiveToWord32();
+  const Operator* PlainPrimitiveToFloat64();
+
+  const Operator* ChangeTaggedSignedToInt32();
   const Operator* ChangeTaggedToInt32();
   const Operator* ChangeTaggedToUint32();
   const Operator* ChangeTaggedToFloat64();
+  const Operator* ChangeInt31ToTaggedSigned();
   const Operator* ChangeInt32ToTagged();
   const Operator* ChangeUint32ToTagged();
   const Operator* ChangeFloat64ToTagged();
-  const Operator* ChangeBoolToBit();
-  const Operator* ChangeBitToBool();
+  const Operator* ChangeTaggedToBit();
+  const Operator* ChangeBitToTagged();
+  const Operator* TruncateTaggedToWord32();
+  const Operator* TruncateTaggedToFloat64();
 
+  const Operator* CheckBounds();
+  const Operator* CheckTaggedPointer();
+  const Operator* CheckTaggedSigned();
+
+  const Operator* CheckedInt32Add();
+  const Operator* CheckedInt32Sub();
+  const Operator* CheckedUint32ToInt32();
+  const Operator* CheckedFloat64ToInt32();
+  const Operator* CheckedTaggedToInt32();
+  const Operator* CheckedTaggedToFloat64();
+
+  const Operator* CheckFloat64Hole(CheckFloat64HoleMode);
+  const Operator* CheckTaggedHole(CheckTaggedHoleMode);
+
+  const Operator* ObjectIsCallable();
   const Operator* ObjectIsNumber();
   const Operator* ObjectIsReceiver();
   const Operator* ObjectIsSmi();
+  const Operator* ObjectIsString();
   const Operator* ObjectIsUndetectable();
 
+  const Operator* TypeGuard(Type* type);
+
   const Operator* Allocate(PretenureFlag pretenure = NOT_TENURED);
 
   const Operator* LoadField(FieldAccess const&);
diff --git a/src/compiler/source-position.cc b/src/compiler/source-position.cc
index 48361ec..80f1800 100644
--- a/src/compiler/source-position.cc
+++ b/src/compiler/source-position.cc
@@ -16,7 +16,8 @@
       : source_positions_(source_positions) {}
 
   void Decorate(Node* node) final {
-    source_positions_->table_.Set(node, source_positions_->current_position_);
+    source_positions_->SetSourcePosition(node,
+                                         source_positions_->current_position_);
   }
 
  private:
@@ -49,6 +50,10 @@
   return table_.Get(node);
 }
 
+void SourcePositionTable::SetSourcePosition(Node* node,
+                                            SourcePosition position) {
+  table_.Set(node, position);
+}
 
 void SourcePositionTable::Print(std::ostream& os) const {
   os << "{";
diff --git a/src/compiler/source-position.h b/src/compiler/source-position.h
index 81db1d2..912f188 100644
--- a/src/compiler/source-position.h
+++ b/src/compiler/source-position.h
@@ -38,8 +38,7 @@
   return !(lhs == rhs);
 }
 
-
-class SourcePositionTable final {
+class SourcePositionTable final : public ZoneObject {
  public:
   class Scope final {
    public:
@@ -66,14 +65,12 @@
   };
 
   explicit SourcePositionTable(Graph* graph);
-  ~SourcePositionTable() {
-    if (decorator_) RemoveDecorator();
-  }
 
   void AddDecorator();
   void RemoveDecorator();
 
   SourcePosition GetSourcePosition(Node* node) const;
+  void SetSourcePosition(Node* node, SourcePosition position);
 
   void Print(std::ostream& os) const;
 
diff --git a/src/compiler/store-store-elimination.cc b/src/compiler/store-store-elimination.cc
new file mode 100644
index 0000000..a469b20
--- /dev/null
+++ b/src/compiler/store-store-elimination.cc
@@ -0,0 +1,264 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/store-store-elimination.h"
+
+#include "src/compiler/all-nodes.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/node-properties.h"
+#include "src/compiler/simplified-operator.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+#define TRACE(fmt, ...)                                              \
+  do {                                                               \
+    if (FLAG_trace_store_elimination) {                              \
+      PrintF("StoreStoreElimination::ReduceEligibleNode: " fmt "\n", \
+             ##__VA_ARGS__);                                         \
+    }                                                                \
+  } while (false)
+
+// A simple store-store elimination. When the effect chain contains the
+// following sequence,
+//
+// - StoreField[[+off_1]](x1, y1)
+// - StoreField[[+off_2]](x2, y2)
+// - StoreField[[+off_3]](x3, y3)
+//   ...
+// - StoreField[[+off_n]](xn, yn)
+//
+// where the xes are the objects and the ys are the values to be stored, then
+// we are going to say that a store is superfluous if the same offset of the
+// same object will be stored to in the future. If off_i == off_j and xi == xj
+// and i < j, then we optimize the i'th StoreField away.
+//
+// This optimization should be initiated on the last StoreField in such a
+// sequence.
+//
+// The algorithm works by walking the effect chain from the last StoreField
+// upwards. While walking, we maintain a map {futureStore} from offsets to
+// nodes; initially it is empty. As we walk the effect chain upwards, if
+// futureStore[off] = n, then any store to node {n} with offset {off} is
+// guaranteed to be useless because we do a full-width[1] store to that offset
+// of that object in the near future anyway. For example, for this effect
+// chain
+//
+// 71: StoreField(60, 0)
+// 72: StoreField(65, 8)
+// 73: StoreField(63, 8)
+// 74: StoreField(65, 16)
+// 75: StoreField(62, 8)
+//
+// just before we get to 72, we will have futureStore = {8: 63, 16: 65}.
+//
+// Here is the complete process.
+//
+// - We are at the end of a sequence of consecutive StoreFields.
+// - We start out with futureStore = empty.
+// - We then walk the effect chain upwards to find the next StoreField [2].
+//
+//   1. If the offset is not a key of {futureStore} yet, we put it in.
+//   2. If the offset is a key of {futureStore}, but futureStore[offset] is a
+//      different node, we overwrite futureStore[offset] with the current node.
+//   3. If the offset is a key of {futureStore} and futureStore[offset] equals
+//      this node, we eliminate this StoreField.
+//
+//   As long as the current effect input points to a node with a single effect
+//   output, and as long as its opcode is StoreField, we keep traversing
+//   upwards.
+//
+// [1] This optimization is unsound if we optimize away a store to an offset
+//   because we store to the same offset in the future, even though the future
+//   store is narrower than the store we optimize away. Therefore, in case (1)
+//   and (2) we only add/overwrite to the dictionary when the field access has
+//   maximal size. For simplicity of implementation, we do not try to detect
+//   case (3).
+//
+// [2] We make sure that we only traverse the linear part, that is, the part
+//   where every node has exactly one incoming and one outgoing effect edge.
+//   Also, we only keep walking upwards as long as we keep finding consecutive
+//   StoreFields on the same node.
+
+StoreStoreElimination::StoreStoreElimination(JSGraph* js_graph, Zone* temp_zone)
+    : jsgraph_(js_graph), temp_zone_(temp_zone) {}
+
+StoreStoreElimination::~StoreStoreElimination() {}
+
+void StoreStoreElimination::Run() {
+  // The store-store elimination performs work on chains of certain types of
+  // nodes. The elimination must be invoked on the lowest node in such a
+  // chain; we have a helper function IsEligibleNode that returns true
+  // precisely on the lowest node in such a chain.
+  //
+  // Because the elimination removes nodes from the graph, even remove nodes
+  // that the elimination was not invoked on, we cannot use a normal
+  // AdvancedReducer but we manually find which nodes to invoke the
+  // elimination on. Then in a next step, we invoke the elimination for each
+  // node that was eligible.
+
+  NodeVector eligible(temp_zone());  // loops over all nodes
+  AllNodes all(temp_zone(), jsgraph()->graph());
+
+  for (Node* node : all.live) {
+    if (IsEligibleNode(node)) {
+      eligible.push_back(node);
+    }
+  }
+
+  for (Node* node : eligible) {
+    ReduceEligibleNode(node);
+  }
+}
+
+namespace {
+
+// 16 bits was chosen fairly arbitrarily; it seems enough now. 8 bits is too
+// few.
+typedef uint16_t Offset;
+
+// To safely cast an offset from a FieldAccess, which has a wider range
+// (namely int).
+Offset ToOffset(int offset) {
+  CHECK(0 <= offset && offset < (1 << 8 * sizeof(Offset)));
+  return (Offset)offset;
+}
+
+Offset ToOffset(const FieldAccess& access) { return ToOffset(access.offset); }
+
+// If node has a single effect use, return that node. If node has no or
+// multiple effect uses, return nullptr.
+Node* SingleEffectUse(Node* node) {
+  Node* last_use = nullptr;
+  for (Edge edge : node->use_edges()) {
+    if (!NodeProperties::IsEffectEdge(edge)) {
+      continue;
+    }
+    if (last_use != nullptr) {
+      // more than one
+      return nullptr;
+    }
+    last_use = edge.from();
+    DCHECK_NOT_NULL(last_use);
+  }
+  return last_use;
+}
+
+// Return true if node is the last consecutive StoreField node in a linear
+// part of the effect chain.
+bool IsEndOfStoreFieldChain(Node* node) {
+  Node* next_on_chain = SingleEffectUse(node);
+  return (next_on_chain == nullptr ||
+          next_on_chain->op()->opcode() != IrOpcode::kStoreField);
+}
+
+// The argument must be a StoreField node. If there is a node before it in the
+// effect chain, and if this part of the effect chain is linear (no other
+// effect uses of that previous node), then return that previous node.
+// Otherwise, return nullptr.
+//
+// The returned node need not be a StoreField.
+Node* PreviousEffectBeforeStoreField(Node* node) {
+  DCHECK_EQ(node->op()->opcode(), IrOpcode::kStoreField);
+  DCHECK_EQ(node->op()->EffectInputCount(), 1);
+
+  Node* previous = NodeProperties::GetEffectInput(node);
+  if (previous != nullptr && node == SingleEffectUse(previous)) {
+    return previous;
+  } else {
+    return nullptr;
+  }
+}
+
+size_t rep_size_of(MachineRepresentation rep) {
+  return ((size_t)1) << ElementSizeLog2Of(rep);
+}
+size_t rep_size_of(FieldAccess access) {
+  return rep_size_of(access.machine_type.representation());
+}
+
+}  // namespace
+
+bool StoreStoreElimination::IsEligibleNode(Node* node) {
+  return (node->op()->opcode() == IrOpcode::kStoreField) &&
+         IsEndOfStoreFieldChain(node);
+}
+
+void StoreStoreElimination::ReduceEligibleNode(Node* node) {
+  DCHECK(IsEligibleNode(node));
+
+  // if (FLAG_trace_store_elimination) {
+  //   PrintF("** StoreStoreElimination::ReduceEligibleNode: activated:
+  //   #%d\n",
+  //          node->id());
+  // }
+
+  TRACE("activated: #%d", node->id());
+
+  // Initialize empty futureStore.
+  ZoneMap<Offset, Node*> futureStore(temp_zone());
+
+  Node* current_node = node;
+
+  do {
+    FieldAccess access = OpParameter<FieldAccess>(current_node->op());
+    Offset offset = ToOffset(access);
+    Node* object_input = current_node->InputAt(0);
+
+    Node* previous = PreviousEffectBeforeStoreField(current_node);
+
+    CHECK(rep_size_of(access) <= rep_size_of(MachineRepresentation::kTagged));
+    if (rep_size_of(access) == rep_size_of(MachineRepresentation::kTagged)) {
+      // Try to insert. If it was present, this will preserve the original
+      // value.
+      auto insert_result =
+          futureStore.insert(std::make_pair(offset, object_input));
+      if (insert_result.second) {
+        // Key was not present. This means that there is no matching
+        // StoreField to this offset in the future, so we cannot optimize
+        // current_node away. However, we will record the current StoreField
+        // in futureStore, and continue ascending up the chain.
+        TRACE("#%d[[+%d]] -- wide, key not present", current_node->id(),
+              offset);
+      } else if (insert_result.first->second != object_input) {
+        // Key was present, and the value did not equal object_input. This
+        // means
+        // that there is a StoreField to this offset in the future, but the
+        // object instance comes from a different Node. We pessimistically
+        // assume that we cannot optimize current_node away. However, we will
+        // record the current StoreField in futureStore, and continue
+        // ascending up the chain.
+        insert_result.first->second = object_input;
+        TRACE("#%d[[+%d]] -- wide, diff object", current_node->id(), offset);
+      } else {
+        // Key was present, and the value equalled object_input. This means
+        // that soon after in the effect chain, we will do a StoreField to the
+        // same object with the same offset, therefore current_node can be
+        // optimized away. We don't need to update futureStore.
+
+        Node* previous_effect = NodeProperties::GetEffectInput(current_node);
+
+        NodeProperties::ReplaceUses(current_node, nullptr, previous_effect,
+                                    nullptr, nullptr);
+        current_node->Kill();
+        TRACE("#%d[[+%d]] -- wide, eliminated", current_node->id(), offset);
+      }
+    } else {
+      TRACE("#%d[[+%d]] -- narrow, not eliminated", current_node->id(), offset);
+    }
+
+    // Regardless of whether we eliminated node {current}, we want to
+    // continue walking up the effect chain.
+
+    current_node = previous;
+  } while (current_node != nullptr &&
+           current_node->op()->opcode() == IrOpcode::kStoreField);
+
+  TRACE("finished");
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/src/compiler/store-store-elimination.h b/src/compiler/store-store-elimination.h
new file mode 100644
index 0000000..1c9ae3d
--- /dev/null
+++ b/src/compiler/store-store-elimination.h
@@ -0,0 +1,40 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_STORE_STORE_ELIMINATION_H_
+#define V8_COMPILER_STORE_STORE_ELIMINATION_H_
+
+#include "src/compiler/common-operator.h"
+#include "src/compiler/graph-reducer.h"
+#include "src/compiler/js-graph.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+// Forward declarations.
+class CommonOperatorBuilder;
+class JSGraph;
+
+class StoreStoreElimination final {
+ public:
+  StoreStoreElimination(JSGraph* js_graph, Zone* temp_zone);
+  ~StoreStoreElimination();
+  void Run();
+
+ private:
+  static bool IsEligibleNode(Node* node);
+  void ReduceEligibleNode(Node* node);
+  JSGraph* jsgraph() const { return jsgraph_; }
+  Zone* temp_zone() const { return temp_zone_; }
+
+  JSGraph* const jsgraph_;
+  Zone* const temp_zone_;
+};
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_COMPILER_STORE_STORE_ELIMINATION_H_
diff --git a/src/compiler/tail-call-optimization.cc b/src/compiler/tail-call-optimization.cc
index 6635fb9..7e1623a 100644
--- a/src/compiler/tail-call-optimization.cc
+++ b/src/compiler/tail-call-optimization.cc
@@ -20,7 +20,7 @@
   // other effect between the Call and the Return nodes.
   Node* const call = NodeProperties::GetValueInput(node, 0);
   if (call->opcode() == IrOpcode::kCall &&
-      OpParameter<CallDescriptor const*>(call)->SupportsTailCalls() &&
+      CallDescriptorOf(call->op())->SupportsTailCalls() &&
       NodeProperties::GetEffectInput(node) == call &&
       !NodeProperties::IsExceptionalCall(call)) {
     Node* const control = NodeProperties::GetControlInput(node);
@@ -71,7 +71,7 @@
                           NodeProperties::GetValueInput(call, index));
       }
       NodeProperties::ChangeOp(
-          node, common()->TailCall(OpParameter<CallDescriptor const*>(call)));
+          node, common()->TailCall(CallDescriptorOf(call->op())));
       return Changed(node);
     }
   }
diff --git a/src/compiler/type-hint-analyzer.cc b/src/compiler/type-hint-analyzer.cc
index da4f268..791aa9d 100644
--- a/src/compiler/type-hint-analyzer.cc
+++ b/src/compiler/type-hint-analyzer.cc
@@ -16,17 +16,43 @@
 namespace {
 
 // TODO(bmeurer): This detour via types is ugly.
-BinaryOperationHints::Hint ToHint(Type* type) {
+BinaryOperationHints::Hint ToBinaryOperationHint(Type* type) {
   if (type->Is(Type::None())) return BinaryOperationHints::kNone;
   if (type->Is(Type::SignedSmall())) return BinaryOperationHints::kSignedSmall;
   if (type->Is(Type::Signed32())) return BinaryOperationHints::kSigned32;
-  if (type->Is(Type::Number())) return BinaryOperationHints::kNumber;
+  if (type->Is(Type::Number())) return BinaryOperationHints::kNumberOrUndefined;
   if (type->Is(Type::String())) return BinaryOperationHints::kString;
   return BinaryOperationHints::kAny;
 }
 
-}  // namespace
+CompareOperationHints::Hint ToCompareOperationHint(
+    CompareICState::State state) {
+  switch (state) {
+    case CompareICState::UNINITIALIZED:
+      return CompareOperationHints::kNone;
+    case CompareICState::BOOLEAN:
+      return CompareOperationHints::kBoolean;
+    case CompareICState::SMI:
+      return CompareOperationHints::kSignedSmall;
+    case CompareICState::NUMBER:
+      return CompareOperationHints::kNumber;
+    case CompareICState::STRING:
+      return CompareOperationHints::kString;
+    case CompareICState::INTERNALIZED_STRING:
+      return CompareOperationHints::kInternalizedString;
+    case CompareICState::UNIQUE_NAME:
+      return CompareOperationHints::kUniqueName;
+    case CompareICState::RECEIVER:
+    case CompareICState::KNOWN_RECEIVER:
+      return CompareOperationHints::kReceiver;
+    case CompareICState::GENERIC:
+      return CompareOperationHints::kAny;
+  }
+  UNREACHABLE();
+  return CompareOperationHints::kAny;
+}
 
+}  // namespace
 
 bool TypeHintAnalysis::GetBinaryOperationHints(
     TypeFeedbackId id, BinaryOperationHints* hints) const {
@@ -35,12 +61,29 @@
   Handle<Code> code = i->second;
   DCHECK_EQ(Code::BINARY_OP_IC, code->kind());
   BinaryOpICState state(code->GetIsolate(), code->extra_ic_state());
-  *hints = BinaryOperationHints(ToHint(state.GetLeftType()),
-                                ToHint(state.GetRightType()),
-                                ToHint(state.GetResultType()));
+  *hints = BinaryOperationHints(ToBinaryOperationHint(state.GetLeftType()),
+                                ToBinaryOperationHint(state.GetRightType()),
+                                ToBinaryOperationHint(state.GetResultType()));
   return true;
 }
 
+bool TypeHintAnalysis::GetCompareOperationHints(
+    TypeFeedbackId id, CompareOperationHints* hints) const {
+  auto i = infos_.find(id);
+  if (i == infos_.end()) return false;
+  Handle<Code> code = i->second;
+  DCHECK_EQ(Code::COMPARE_IC, code->kind());
+
+  Handle<Map> map;
+  Map* raw_map = code->FindFirstMap();
+  if (raw_map != nullptr) Map::TryUpdate(handle(raw_map)).ToHandle(&map);
+
+  CompareICStub stub(code->stub_key(), code->GetIsolate());
+  *hints = CompareOperationHints(ToCompareOperationHint(stub.left()),
+                                 ToCompareOperationHint(stub.right()),
+                                 ToCompareOperationHint(stub.state()));
+  return true;
+}
 
 bool TypeHintAnalysis::GetToBooleanHints(TypeFeedbackId id,
                                          ToBooleanHints* hints) const {
@@ -67,7 +110,6 @@
   return true;
 }
 
-
 TypeHintAnalysis* TypeHintAnalyzer::Analyze(Handle<Code> code) {
   DisallowHeapAllocation no_gc;
   TypeHintAnalysis::Infos infos(zone());
@@ -79,6 +121,7 @@
     Code* target = Code::GetCodeFromTargetAddress(target_address);
     switch (target->kind()) {
       case Code::BINARY_OP_IC:
+      case Code::COMPARE_IC:
       case Code::TO_BOOLEAN_IC: {
         // Add this feedback to the {infos}.
         TypeFeedbackId id(static_cast<unsigned>(rinfo->data()));
@@ -90,7 +133,7 @@
         break;
     }
   }
-  return new (zone()) TypeHintAnalysis(infos);
+  return new (zone()) TypeHintAnalysis(infos, zone());
 }
 
 }  // namespace compiler
diff --git a/src/compiler/type-hint-analyzer.h b/src/compiler/type-hint-analyzer.h
index 1a79905..bfb6232 100644
--- a/src/compiler/type-hint-analyzer.h
+++ b/src/compiler/type-hint-analyzer.h
@@ -18,14 +18,20 @@
  public:
   typedef ZoneMap<TypeFeedbackId, Handle<Code>> Infos;
 
-  explicit TypeHintAnalysis(Infos const& infos) : infos_(infos) {}
+  explicit TypeHintAnalysis(Infos const& infos, Zone* zone)
+      : infos_(infos), zone_(zone) {}
 
   bool GetBinaryOperationHints(TypeFeedbackId id,
                                BinaryOperationHints* hints) const;
+  bool GetCompareOperationHints(TypeFeedbackId id,
+                                CompareOperationHints* hints) const;
   bool GetToBooleanHints(TypeFeedbackId id, ToBooleanHints* hints) const;
 
  private:
+  Zone* zone() const { return zone_; }
+
   Infos const infos_;
+  Zone* zone_;
 };
 
 
diff --git a/src/compiler/type-hints.cc b/src/compiler/type-hints.cc
index 06abad6..e608832 100644
--- a/src/compiler/type-hints.cc
+++ b/src/compiler/type-hints.cc
@@ -16,8 +16,8 @@
       return os << "SignedSmall";
     case BinaryOperationHints::kSigned32:
       return os << "Signed32";
-    case BinaryOperationHints::kNumber:
-      return os << "Number";
+    case BinaryOperationHints::kNumberOrUndefined:
+      return os << "NumberOrUndefined";
     case BinaryOperationHints::kString:
       return os << "String";
     case BinaryOperationHints::kAny:
@@ -27,11 +27,39 @@
   return os;
 }
 
-
 std::ostream& operator<<(std::ostream& os, BinaryOperationHints hints) {
   return os << hints.left() << "*" << hints.right() << "->" << hints.result();
 }
 
+std::ostream& operator<<(std::ostream& os, CompareOperationHints::Hint hint) {
+  switch (hint) {
+    case CompareOperationHints::kNone:
+      return os << "None";
+    case CompareOperationHints::kBoolean:
+      return os << "Boolean";
+    case CompareOperationHints::kSignedSmall:
+      return os << "SignedSmall";
+    case CompareOperationHints::kNumber:
+      return os << "Number";
+    case CompareOperationHints::kString:
+      return os << "String";
+    case CompareOperationHints::kInternalizedString:
+      return os << "InternalizedString";
+    case CompareOperationHints::kUniqueName:
+      return os << "UniqueName";
+    case CompareOperationHints::kReceiver:
+      return os << "Receiver";
+    case CompareOperationHints::kAny:
+      return os << "Any";
+  }
+  UNREACHABLE();
+  return os;
+}
+
+std::ostream& operator<<(std::ostream& os, CompareOperationHints hints) {
+  return os << hints.left() << "*" << hints.right() << " (" << hints.combined()
+            << ")";
+}
 
 std::ostream& operator<<(std::ostream& os, ToBooleanHint hint) {
   switch (hint) {
@@ -62,7 +90,6 @@
   return os;
 }
 
-
 std::ostream& operator<<(std::ostream& os, ToBooleanHints hints) {
   if (hints == ToBooleanHint::kAny) return os << "Any";
   if (hints == ToBooleanHint::kNone) return os << "None";
@@ -78,6 +105,34 @@
   return os;
 }
 
+// static
+bool BinaryOperationHints::Is(Hint h1, Hint h2) {
+  if (h1 == h2) return true;
+  switch (h1) {
+    case kNone:
+      return true;
+    case kSignedSmall:
+      return h2 == kSigned32 || h2 == kNumberOrUndefined || h2 == kAny;
+    case kSigned32:
+      return h2 == kNumberOrUndefined || h2 == kAny;
+    case kNumberOrUndefined:
+      return h2 == kAny;
+    case kString:
+      return h2 == kAny;
+    case kAny:
+      return false;
+  }
+  UNREACHABLE();
+  return false;
+}
+
+// static
+BinaryOperationHints::Hint BinaryOperationHints::Combine(Hint h1, Hint h2) {
+  if (Is(h1, h2)) return h2;
+  if (Is(h2, h1)) return h1;
+  return kAny;
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/src/compiler/type-hints.h b/src/compiler/type-hints.h
index f1cc640..7c9badd 100644
--- a/src/compiler/type-hints.h
+++ b/src/compiler/type-hints.h
@@ -15,7 +15,14 @@
 // Type hints for an binary operation.
 class BinaryOperationHints final {
  public:
-  enum Hint { kNone, kSignedSmall, kSigned32, kNumber, kString, kAny };
+  enum Hint {
+    kNone,
+    kSignedSmall,
+    kSigned32,
+    kNumberOrUndefined,
+    kString,
+    kAny
+  };
 
   BinaryOperationHints() : BinaryOperationHints(kNone, kNone, kNone) {}
   BinaryOperationHints(Hint left, Hint right, Hint result)
@@ -29,6 +36,11 @@
   Hint left() const { return LeftField::decode(bit_field_); }
   Hint right() const { return RightField::decode(bit_field_); }
   Hint result() const { return ResultField::decode(bit_field_); }
+  Hint combined() const { return Combine(Combine(left(), right()), result()); }
+
+  // Hint 'subtyping' and generalization.
+  static bool Is(Hint h1, Hint h2);
+  static Hint Combine(Hint h1, Hint h2);
 
   bool operator==(BinaryOperationHints const& that) const {
     return this->bit_field_ == that.bit_field_;
@@ -52,6 +64,55 @@
 std::ostream& operator<<(std::ostream&, BinaryOperationHints::Hint);
 std::ostream& operator<<(std::ostream&, BinaryOperationHints);
 
+// Type hints for an binary operation.
+class CompareOperationHints final {
+ public:
+  enum Hint {
+    kNone,
+    kBoolean,
+    kSignedSmall,
+    kNumber,
+    kString,
+    kInternalizedString,
+    kUniqueName,
+    kReceiver,
+    kAny
+  };
+
+  CompareOperationHints() : CompareOperationHints(kNone, kNone, kNone) {}
+  CompareOperationHints(Hint left, Hint right, Hint combined)
+      : bit_field_(LeftField::encode(left) | RightField::encode(right) |
+                   CombinedField::encode(combined)) {}
+
+  static CompareOperationHints Any() {
+    return CompareOperationHints(kAny, kAny, kAny);
+  }
+
+  Hint left() const { return LeftField::decode(bit_field_); }
+  Hint right() const { return RightField::decode(bit_field_); }
+  Hint combined() const { return CombinedField::decode(bit_field_); }
+
+  bool operator==(CompareOperationHints const& that) const {
+    return this->bit_field_ == that.bit_field_;
+  }
+  bool operator!=(CompareOperationHints const& that) const {
+    return !(*this == that);
+  }
+
+  friend size_t hash_value(CompareOperationHints const& hints) {
+    return hints.bit_field_;
+  }
+
+ private:
+  typedef BitField<Hint, 0, 4> LeftField;
+  typedef BitField<Hint, 4, 4> RightField;
+  typedef BitField<Hint, 8, 4> CombinedField;
+
+  uint32_t bit_field_;
+};
+
+std::ostream& operator<<(std::ostream&, CompareOperationHints::Hint);
+std::ostream& operator<<(std::ostream&, CompareOperationHints);
 
 // Type hints for the ToBoolean type conversion.
 enum class ToBooleanHint : uint16_t {
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index 81c3d3d..2bc0bb3 100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -10,8 +10,9 @@
 #include "src/compiler/common-operator.h"
 #include "src/compiler/graph-reducer.h"
 #include "src/compiler/js-operator.h"
-#include "src/compiler/node.h"
 #include "src/compiler/node-properties.h"
+#include "src/compiler/node.h"
+#include "src/compiler/operation-typer.h"
 #include "src/compiler/simplified-operator.h"
 #include "src/objects-inl.h"
 #include "src/type-cache.h"
@@ -37,14 +38,15 @@
       dependencies_(dependencies),
       function_type_(function_type),
       decorator_(nullptr),
-      cache_(TypeCache::Get()) {
+      cache_(TypeCache::Get()),
+      operation_typer_(isolate, zone()) {
   Zone* zone = this->zone();
   Factory* const factory = isolate->factory();
 
   Type* infinity = Type::Constant(factory->infinity_value(), zone);
   Type* minus_infinity = Type::Constant(factory->minus_infinity_value(), zone);
-  // TODO(neis): Unfortunately, the infinities created in other places might
-  // be different ones (eg the result of NewNumber in TypeNumberConstant).
+  // Unfortunately, the infinities created in other places might be different
+  // ones (eg the result of NewNumber in TypeNumberConstant).
   Type* truncating_to_zero =
       Type::Union(Type::Union(infinity, minus_infinity, zone),
                   Type::MinusZeroOrNaN(), zone);
@@ -97,6 +99,7 @@
       COMMON_OP_LIST(DECLARE_CASE)
       SIMPLIFIED_OP_LIST(DECLARE_CASE)
       MACHINE_OP_LIST(DECLARE_CASE)
+      MACHINE_SIMD_OP_LIST(DECLARE_CASE)
       JS_SIMPLE_UNOP_LIST(DECLARE_CASE)
       JS_OBJECT_OP_LIST(DECLARE_CASE)
       JS_CONTEXT_OP_LIST(DECLARE_CASE)
@@ -143,6 +146,7 @@
       COMMON_OP_LIST(DECLARE_CASE)
       SIMPLIFIED_OP_LIST(DECLARE_CASE)
       MACHINE_OP_LIST(DECLARE_CASE)
+      MACHINE_SIMD_OP_LIST(DECLARE_CASE)
       JS_SIMPLE_UNOP_LIST(DECLARE_CASE)
       JS_OBJECT_OP_LIST(DECLARE_CASE)
       JS_CONTEXT_OP_LIST(DECLARE_CASE)
@@ -230,7 +234,6 @@
   static ComparisonOutcome Invert(ComparisonOutcome, Typer*);
   static Type* Invert(Type*, Typer*);
   static Type* FalsifyUndefined(ComparisonOutcome, Typer*);
-  static Type* Rangify(Type*, Typer*);
 
   static Type* ToPrimitive(Type*, Typer*);
   static Type* ToBoolean(Type*, Typer*);
@@ -240,6 +243,7 @@
   static Type* ToNumber(Type*, Typer*);
   static Type* ToObject(Type*, Typer*);
   static Type* ToString(Type*, Typer*);
+  static Type* NumberAbs(Type*, Typer*);
   static Type* NumberCeil(Type*, Typer*);
   static Type* NumberFloor(Type*, Typer*);
   static Type* NumberRound(Type*, Typer*);
@@ -247,16 +251,13 @@
   static Type* NumberToInt32(Type*, Typer*);
   static Type* NumberToUint32(Type*, Typer*);
 
+  static Type* ObjectIsCallable(Type*, Typer*);
   static Type* ObjectIsNumber(Type*, Typer*);
   static Type* ObjectIsReceiver(Type*, Typer*);
   static Type* ObjectIsSmi(Type*, Typer*);
+  static Type* ObjectIsString(Type*, Typer*);
   static Type* ObjectIsUndetectable(Type*, Typer*);
 
-  static Type* JSAddRanger(RangeType*, RangeType*, Typer*);
-  static Type* JSSubtractRanger(RangeType*, RangeType*, Typer*);
-  static Type* JSDivideRanger(RangeType*, RangeType*, Typer*);
-  static Type* JSModulusRanger(RangeType*, RangeType*, Typer*);
-
   static ComparisonOutcome JSCompareTyper(Type*, Type*, Typer*);
 
 #define DECLARE_METHOD(x) static Type* x##Typer(Type*, Type*, Typer*);
@@ -268,6 +269,7 @@
   static Type* JSCallFunctionTyper(Type*, Typer*);
 
   static Type* ReferenceEqualTyper(Type*, Type*, Typer*);
+  static Type* StringFromCharCodeTyper(Type*, Typer*);
 
   Reduction UpdateType(Node* node, Type* current) {
     if (NodeProperties::IsTyped(node)) {
@@ -376,27 +378,8 @@
   return t->singleton_true_;
 }
 
-
-Type* Typer::Visitor::Rangify(Type* type, Typer* t) {
-  if (type->IsRange()) return type;        // Shortcut.
-  if (!type->Is(t->cache_.kInteger)) {
-    return type;  // Give up on non-integer types.
-  }
-  double min = type->Min();
-  double max = type->Max();
-  // Handle the degenerate case of empty bitset types (such as
-  // OtherUnsigned31 and OtherSigned32 on 64-bit architectures).
-  if (std::isnan(min)) {
-    DCHECK(std::isnan(max));
-    return type;
-  }
-  return Type::Range(min, max, t->zone());
-}
-
-
 // Type conversion.
 
-
 Type* Typer::Visitor::ToPrimitive(Type* type, Typer* t) {
   if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) {
     return type;
@@ -497,6 +480,34 @@
 }
 
 // static
+Type* Typer::Visitor::NumberAbs(Type* type, Typer* t) {
+  DCHECK(type->Is(Type::Number()));
+  Factory* const f = t->isolate()->factory();
+  bool const maybe_nan = type->Maybe(Type::NaN());
+  bool const maybe_minuszero = type->Maybe(Type::MinusZero());
+  type = Type::Intersect(type, Type::PlainNumber(), t->zone());
+  double const max = type->Max();
+  double const min = type->Min();
+  if (min < 0) {
+    if (type->Is(t->cache_.kInteger)) {
+      type =
+          Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), t->zone());
+    } else if (min == max) {
+      type = Type::Constant(f->NewNumber(std::fabs(min)), t->zone());
+    } else {
+      type = Type::PlainNumber();
+    }
+  }
+  if (maybe_minuszero) {
+    type = Type::Union(type, t->cache_.kSingletonZero, t->zone());
+  }
+  if (maybe_nan) {
+    type = Type::Union(type, Type::NaN(), t->zone());
+  }
+  return type;
+}
+
+// static
 Type* Typer::Visitor::NumberCeil(Type* type, Typer* t) {
   DCHECK(type->Is(Type::Number()));
   if (type->Is(t->cache_.kIntegerOrMinusZeroOrNaN)) return type;
@@ -529,7 +540,6 @@
 }
 
 Type* Typer::Visitor::NumberToInt32(Type* type, Typer* t) {
-  // TODO(neis): DCHECK(type->Is(Type::Number()));
   if (type->Is(Type::Signed32())) return type;
   if (type->Is(t->cache_.kZeroish)) return t->cache_.kSingletonZero;
   if (type->Is(t->signed32ish_)) {
@@ -542,7 +552,6 @@
 
 
 Type* Typer::Visitor::NumberToUint32(Type* type, Typer* t) {
-  // TODO(neis): DCHECK(type->Is(Type::Number()));
   if (type->Is(Type::Unsigned32())) return type;
   if (type->Is(t->cache_.kZeroish)) return t->cache_.kSingletonZero;
   if (type->Is(t->unsigned32ish_)) {
@@ -553,9 +562,13 @@
   return Type::Unsigned32();
 }
 
-
 // Type checks.
 
+Type* Typer::Visitor::ObjectIsCallable(Type* type, Typer* t) {
+  if (type->Is(Type::Function())) return t->singleton_true_;
+  if (type->Is(Type::Primitive())) return t->singleton_false_;
+  return Type::Boolean();
+}
 
 Type* Typer::Visitor::ObjectIsNumber(Type* type, Typer* t) {
   if (type->Is(Type::Number())) return t->singleton_true_;
@@ -577,6 +590,11 @@
   return Type::Boolean();
 }
 
+Type* Typer::Visitor::ObjectIsString(Type* type, Typer* t) {
+  if (type->Is(Type::String())) return t->singleton_true_;
+  if (!type->Maybe(Type::String())) return t->singleton_false_;
+  return Type::Boolean();
+}
 
 Type* Typer::Visitor::ObjectIsUndetectable(Type* type, Typer* t) {
   if (type->Is(Type::Undetectable())) return t->singleton_true_;
@@ -624,6 +642,14 @@
   return Type::Internal();  // TODO(rossberg): Add int64 bitset type?
 }
 
+// TODO(gdeepti) : Fix this to do something meaningful.
+Type* Typer::Visitor::TypeRelocatableInt32Constant(Node* node) {
+  return Type::Internal();
+}
+
+Type* Typer::Visitor::TypeRelocatableInt64Constant(Node* node) {
+  return Type::Internal();
+}
 
 Type* Typer::Visitor::TypeFloat32Constant(Node* node) {
   return Type::Intersect(Type::Of(OpParameter<float>(node), zone()),
@@ -677,19 +703,16 @@
   return nullptr;
 }
 
-
-Type* Typer::Visitor::TypeEffectSet(Node* node) {
-  UNREACHABLE();
-  return nullptr;
-}
-
-
-Type* Typer::Visitor::TypeGuard(Node* node) {
+Type* Typer::Visitor::TypeTypeGuard(Node* node) {
   Type* input_type = Operand(node, 0);
-  Type* guard_type = OpParameter<Type*>(node);
+  Type* guard_type = TypeOf(node->op());
   return Type::Intersect(input_type, guard_type, zone());
 }
 
+Type* Typer::Visitor::TypeCheckpoint(Node* node) {
+  UNREACHABLE();
+  return nullptr;
+}
 
 Type* Typer::Visitor::TypeBeginRegion(Node* node) {
   UNREACHABLE();
@@ -746,7 +769,6 @@
   if (lhs->IsConstant() && rhs->Is(lhs)) {
     // Types are equal and are inhabited only by a single semantic value,
     // which is not nan due to the earlier check.
-    // TODO(neis): Extend this to Range(x,x), MinusZero, ...?
     return t->singleton_true_;
   }
   return Type::Boolean();
@@ -857,7 +879,6 @@
   return FalsifyUndefined(Invert(JSCompareTyper(lhs, rhs, t), t), t);
 }
 
-
 // JS bitwise operators.
 
 
@@ -890,7 +911,6 @@
     max = std::min(max, -1.0);
   }
   return Type::Range(min, max, t->zone());
-  // TODO(neis): Be precise for singleton inputs, here and elsewhere.
 }
 
 
@@ -991,64 +1011,6 @@
 
 // JS arithmetic operators.
 
-
-// Returns the array's least element, ignoring NaN.
-// There must be at least one non-NaN element.
-// Any -0 is converted to 0.
-static double array_min(double a[], size_t n) {
-  DCHECK(n != 0);
-  double x = +V8_INFINITY;
-  for (size_t i = 0; i < n; ++i) {
-    if (!std::isnan(a[i])) {
-      x = std::min(a[i], x);
-    }
-  }
-  DCHECK(!std::isnan(x));
-  return x == 0 ? 0 : x;  // -0 -> 0
-}
-
-
-// Returns the array's greatest element, ignoring NaN.
-// There must be at least one non-NaN element.
-// Any -0 is converted to 0.
-static double array_max(double a[], size_t n) {
-  DCHECK(n != 0);
-  double x = -V8_INFINITY;
-  for (size_t i = 0; i < n; ++i) {
-    if (!std::isnan(a[i])) {
-      x = std::max(a[i], x);
-    }
-  }
-  DCHECK(!std::isnan(x));
-  return x == 0 ? 0 : x;  // -0 -> 0
-}
-
-Type* Typer::Visitor::JSAddRanger(RangeType* lhs, RangeType* rhs, Typer* t) {
-  double results[4];
-  results[0] = lhs->Min() + rhs->Min();
-  results[1] = lhs->Min() + rhs->Max();
-  results[2] = lhs->Max() + rhs->Min();
-  results[3] = lhs->Max() + rhs->Max();
-  // Since none of the inputs can be -0, the result cannot be -0 either.
-  // However, it can be nan (the sum of two infinities of opposite sign).
-  // On the other hand, if none of the "results" above is nan, then the actual
-  // result cannot be nan either.
-  int nans = 0;
-  for (int i = 0; i < 4; ++i) {
-    if (std::isnan(results[i])) ++nans;
-  }
-  if (nans == 4) return Type::NaN();  // [-inf..-inf] + [inf..inf] or vice versa
-  Type* range =
-      Type::Range(array_min(results, 4), array_max(results, 4), t->zone());
-  return nans == 0 ? range : Type::Union(range, Type::NaN(), t->zone());
-  // Examples:
-  //   [-inf, -inf] + [+inf, +inf] = NaN
-  //   [-inf, -inf] + [n, +inf] = [-inf, -inf] \/ NaN
-  //   [-inf, +inf] + [n, +inf] = [-inf, +inf] \/ NaN
-  //   [-inf, m] + [n, +inf] = [-inf, +inf] \/ NaN
-}
-
-
 Type* Typer::Visitor::JSAddTyper(Type* lhs, Type* rhs, Typer* t) {
   lhs = ToPrimitive(lhs, t);
   rhs = ToPrimitive(rhs, t);
@@ -1059,97 +1021,27 @@
       return Type::NumberOrString();
     }
   }
-  lhs = Rangify(ToNumber(lhs, t), t);
-  rhs = Rangify(ToNumber(rhs, t), t);
-  if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
-  if (lhs->IsRange() && rhs->IsRange()) {
-    return JSAddRanger(lhs->AsRange(), rhs->AsRange(), t);
-  }
-  // TODO(neis): Deal with numeric bitsets here and elsewhere.
-  return Type::Number();
+  // The addition must be numeric.
+  return t->operation_typer()->NumericAdd(ToNumber(lhs, t), ToNumber(rhs, t));
 }
 
-Type* Typer::Visitor::JSSubtractRanger(RangeType* lhs, RangeType* rhs,
-                                       Typer* t) {
-  double results[4];
-  results[0] = lhs->Min() - rhs->Min();
-  results[1] = lhs->Min() - rhs->Max();
-  results[2] = lhs->Max() - rhs->Min();
-  results[3] = lhs->Max() - rhs->Max();
-  // Since none of the inputs can be -0, the result cannot be -0.
-  // However, it can be nan (the subtraction of two infinities of same sign).
-  // On the other hand, if none of the "results" above is nan, then the actual
-  // result cannot be nan either.
-  int nans = 0;
-  for (int i = 0; i < 4; ++i) {
-    if (std::isnan(results[i])) ++nans;
-  }
-  if (nans == 4) return Type::NaN();  // [inf..inf] - [inf..inf] (all same sign)
-  Type* range =
-      Type::Range(array_min(results, 4), array_max(results, 4), t->zone());
-  return nans == 0 ? range : Type::Union(range, Type::NaN(), t->zone());
-  // Examples:
-  //   [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN
-  //   [-inf, -inf] - [-inf, -inf] = NaN
-  //   [-inf, -inf] - [n, +inf] = [-inf, -inf] \/ NaN
-  //   [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN
-}
-
-
 Type* Typer::Visitor::JSSubtractTyper(Type* lhs, Type* rhs, Typer* t) {
-  lhs = Rangify(ToNumber(lhs, t), t);
-  rhs = Rangify(ToNumber(rhs, t), t);
-  if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
-  if (lhs->IsRange() && rhs->IsRange()) {
-    return JSSubtractRanger(lhs->AsRange(), rhs->AsRange(), t);
-  }
-  return Type::Number();
+  return t->operation_typer()->NumericSubtract(ToNumber(lhs, t),
+                                               ToNumber(rhs, t));
 }
 
-
 Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) {
-  lhs = Rangify(ToNumber(lhs, t), t);
-  rhs = Rangify(ToNumber(rhs, t), t);
-  if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
-  if (lhs->IsRange() && rhs->IsRange()) {
-    double results[4];
-    double lmin = lhs->AsRange()->Min();
-    double lmax = lhs->AsRange()->Max();
-    double rmin = rhs->AsRange()->Min();
-    double rmax = rhs->AsRange()->Max();
-    results[0] = lmin * rmin;
-    results[1] = lmin * rmax;
-    results[2] = lmax * rmin;
-    results[3] = lmax * rmax;
-    // If the result may be nan, we give up on calculating a precise type,
-    // because
-    // the discontinuity makes it too complicated.  Note that even if none of
-    // the
-    // "results" above is nan, the actual result may still be, so we have to do
-    // a
-    // different check:
-    bool maybe_nan = (lhs->Maybe(t->cache_.kSingletonZero) &&
-                      (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) ||
-                     (rhs->Maybe(t->cache_.kSingletonZero) &&
-                      (lmin == -V8_INFINITY || lmax == +V8_INFINITY));
-    if (maybe_nan) return t->cache_.kIntegerOrMinusZeroOrNaN;  // Giving up.
-    bool maybe_minuszero = (lhs->Maybe(t->cache_.kSingletonZero) && rmin < 0) ||
-                           (rhs->Maybe(t->cache_.kSingletonZero) && lmin < 0);
-    Type* range =
-        Type::Range(array_min(results, 4), array_max(results, 4), t->zone());
-    return maybe_minuszero ? Type::Union(range, Type::MinusZero(), t->zone())
-                           : range;
-  }
-  return Type::Number();
+  return t->operation_typer()->NumericMultiply(ToNumber(lhs, t),
+                                               ToNumber(rhs, t));
 }
 
-
 Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) {
+  return t->operation_typer()->NumericDivide(ToNumber(lhs, t),
+                                             ToNumber(rhs, t));
   lhs = ToNumber(lhs, t);
   rhs = ToNumber(rhs, t);
   if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
   // Division is tricky, so all we do is try ruling out nan.
-  // TODO(neis): try ruling out -0 as well?
   bool maybe_nan =
       lhs->Maybe(Type::NaN()) || rhs->Maybe(t->cache_.kZeroish) ||
       ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) &&
@@ -1157,56 +1049,9 @@
   return maybe_nan ? Type::Number() : Type::OrderedNumber();
 }
 
-Type* Typer::Visitor::JSModulusRanger(RangeType* lhs, RangeType* rhs,
-                                      Typer* t) {
-  double lmin = lhs->Min();
-  double lmax = lhs->Max();
-  double rmin = rhs->Min();
-  double rmax = rhs->Max();
-
-  double labs = std::max(std::abs(lmin), std::abs(lmax));
-  double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
-  double abs = std::min(labs, rabs);
-  bool maybe_minus_zero = false;
-  double omin = 0;
-  double omax = 0;
-  if (lmin >= 0) {  // {lhs} positive.
-    omin = 0;
-    omax = abs;
-  } else if (lmax <= 0) {  // {lhs} negative.
-    omin = 0 - abs;
-    omax = 0;
-    maybe_minus_zero = true;
-  } else {
-    omin = 0 - abs;
-    omax = abs;
-    maybe_minus_zero = true;
-  }
-
-  Type* result = Type::Range(omin, omax, t->zone());
-  if (maybe_minus_zero)
-    result = Type::Union(result, Type::MinusZero(), t->zone());
-  return result;
-}
-
-
 Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) {
-  lhs = ToNumber(lhs, t);
-  rhs = ToNumber(rhs, t);
-  if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
-
-  if (lhs->Maybe(Type::NaN()) || rhs->Maybe(t->cache_.kZeroish) ||
-      lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) {
-    // Result maybe NaN.
-    return Type::Number();
-  }
-
-  lhs = Rangify(lhs, t);
-  rhs = Rangify(rhs, t);
-  if (lhs->IsRange() && rhs->IsRange()) {
-    return JSModulusRanger(lhs->AsRange(), rhs->AsRange(), t);
-  }
-  return Type::OrderedNumber();
+  return t->operation_typer()->NumericModulus(ToNumber(lhs, t),
+                                              ToNumber(rhs, t));
 }
 
 
@@ -1331,34 +1176,6 @@
 
 
 Type* Typer::Visitor::TypeJSLoadNamed(Node* node) {
-  Factory* const f = isolate()->factory();
-  Handle<Name> name = NamedAccessOf(node->op()).name();
-  if (name.is_identical_to(f->prototype_string())) {
-    Type* receiver = Operand(node, 0);
-    if (receiver->Is(Type::None())) return Type::None();
-    if (receiver->IsConstant() &&
-        receiver->AsConstant()->Value()->IsJSFunction()) {
-      Handle<JSFunction> function =
-          Handle<JSFunction>::cast(receiver->AsConstant()->Value());
-      if (function->has_prototype()) {
-        // We need to add a code dependency on the initial map of the {function}
-        // in order to be notified about changes to "prototype" of {function},
-        // so we can only infer a constant type if deoptimization is enabled.
-        if (flags() & kDeoptimizationEnabled) {
-          JSFunction::EnsureHasInitialMap(function);
-          Handle<Map> initial_map(function->initial_map(), isolate());
-          dependencies()->AssumeInitialMapCantChange(initial_map);
-          return Type::Constant(handle(initial_map->prototype(), isolate()),
-                                zone());
-        }
-      }
-    } else if (receiver->IsClass() &&
-               receiver->AsClass()->Map()->IsJSFunctionMap()) {
-      Handle<Map> map = receiver->AsClass()->Map();
-      return map->has_non_instance_prototype() ? Type::Primitive()
-                                               : Type::Receiver();
-    }
-  }
   return Type::Any();
 }
 
@@ -1537,9 +1354,6 @@
 // JS other operators.
 
 
-Type* Typer::Visitor::TypeJSYield(Node* node) { return Type::Any(); }
-
-
 Type* Typer::Visitor::TypeJSCallConstruct(Node* node) {
   return Type::Receiver();
 }
@@ -1562,9 +1376,10 @@
         case kMathTrunc:
           return t->cache_.kIntegerOrMinusZeroOrNaN;
         // Unary math functions.
+        case kMathExp:
+          return Type::Union(Type::PlainNumber(), Type::NaN(), t->zone());
         case kMathAbs:
         case kMathLog:
-        case kMathExp:
         case kMathSqrt:
         case kMathCos:
         case kMathSin:
@@ -1628,9 +1443,6 @@
     case Runtime::kInlineDoubleLo:
     case Runtime::kInlineDoubleHi:
       return Type::Signed32();
-    case Runtime::kInlineConstructDouble:
-    case Runtime::kInlineMathAtan2:
-      return Type::Number();
     case Runtime::kInlineCreateIterResultObject:
     case Runtime::kInlineRegExpConstructResult:
       return Type::OtherObject();
@@ -1698,10 +1510,21 @@
   return nullptr;
 }
 
+Type* Typer::Visitor::TypeJSGeneratorStore(Node* node) {
+  UNREACHABLE();
+  return nullptr;
+}
+
+Type* Typer::Visitor::TypeJSGeneratorRestoreContinuation(Node* node) {
+  return typer_->cache_.kSmi;
+}
+
+Type* Typer::Visitor::TypeJSGeneratorRestoreRegister(Node* node) {
+  return Type::Any();
+}
 
 Type* Typer::Visitor::TypeJSStackCheck(Node* node) { return Type::Any(); }
 
-
 // Simplified operators.
 
 Type* Typer::Visitor::TypeBooleanNot(Node* node) { return Type::Boolean(); }
@@ -1718,10 +1541,42 @@
   return Type::Boolean();
 }
 
+Type* Typer::Visitor::TypeSpeculativeNumberEqual(Node* node) {
+  return Type::Boolean();
+}
+
+Type* Typer::Visitor::TypeSpeculativeNumberLessThan(Node* node) {
+  return Type::Boolean();
+}
+
+Type* Typer::Visitor::TypeSpeculativeNumberLessThanOrEqual(Node* node) {
+  return Type::Boolean();
+}
+
 Type* Typer::Visitor::TypeNumberAdd(Node* node) { return Type::Number(); }
 
 Type* Typer::Visitor::TypeNumberSubtract(Node* node) { return Type::Number(); }
 
+Type* Typer::Visitor::TypeSpeculativeNumberAdd(Node* node) {
+  return Type::Number();
+}
+
+Type* Typer::Visitor::TypeSpeculativeNumberSubtract(Node* node) {
+  return Type::Number();
+}
+
+Type* Typer::Visitor::TypeSpeculativeNumberMultiply(Node* node) {
+  return Type::Number();
+}
+
+Type* Typer::Visitor::TypeSpeculativeNumberDivide(Node* node) {
+  return Type::Number();
+}
+
+Type* Typer::Visitor::TypeSpeculativeNumberModulus(Node* node) {
+  return Type::Number();
+}
+
 Type* Typer::Visitor::TypeNumberMultiply(Node* node) { return Type::Number(); }
 
 Type* Typer::Visitor::TypeNumberDivide(Node* node) { return Type::Number(); }
@@ -1757,8 +1612,24 @@
   return Type::Unsigned32();
 }
 
+Type* Typer::Visitor::TypePlainPrimitiveToNumber(Node* node) {
+  return TypeUnaryOp(node, ToNumber);
+}
+
+Type* Typer::Visitor::TypePlainPrimitiveToWord32(Node* node) {
+  return Type::Integral32();
+}
+
+Type* Typer::Visitor::TypePlainPrimitiveToFloat64(Node* node) {
+  return Type::Number();
+}
+
 Type* Typer::Visitor::TypeNumberImul(Node* node) { return Type::Signed32(); }
 
+Type* Typer::Visitor::TypeNumberAbs(Node* node) {
+  return TypeUnaryOp(node, NumberAbs);
+}
+
 Type* Typer::Visitor::TypeNumberClz32(Node* node) {
   return typer_->cache_.kZeroToThirtyTwo;
 }
@@ -1771,10 +1642,43 @@
   return TypeUnaryOp(node, NumberFloor);
 }
 
+Type* Typer::Visitor::TypeNumberFround(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberAtan(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberAtan2(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberAtanh(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberCos(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberExp(Node* node) {
+  return Type::Union(Type::PlainNumber(), Type::NaN(), zone());
+}
+
+// TODO(mvstanton): Is this type sufficient, or should it look like Exp()?
+Type* Typer::Visitor::TypeNumberExpm1(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberLog(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberLog1p(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberLog2(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberLog10(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberCbrt(Node* node) { return Type::Number(); }
+
 Type* Typer::Visitor::TypeNumberRound(Node* node) {
   return TypeUnaryOp(node, NumberRound);
 }
 
+Type* Typer::Visitor::TypeNumberSin(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberSqrt(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeNumberTan(Node* node) { return Type::Number(); }
+
 Type* Typer::Visitor::TypeNumberTrunc(Node* node) {
   return TypeUnaryOp(node, NumberTrunc);
 }
@@ -1789,16 +1693,6 @@
 }
 
 
-Type* Typer::Visitor::TypeNumberIsHoleNaN(Node* node) {
-  return Type::Boolean();
-}
-
-
-Type* Typer::Visitor::TypePlainPrimitiveToNumber(Node* node) {
-  return TypeUnaryOp(node, ToNumber);
-}
-
-
 // static
 Type* Typer::Visitor::ReferenceEqualTyper(Type* lhs, Type* rhs, Typer* t) {
   if (lhs->IsConstant() && rhs->Is(lhs)) {
@@ -1820,6 +1714,23 @@
   return Type::Boolean();
 }
 
+Type* Typer::Visitor::StringFromCharCodeTyper(Type* type, Typer* t) {
+  type = NumberToUint32(ToNumber(type, t), t);
+  Factory* f = t->isolate()->factory();
+  double min = type->Min();
+  double max = type->Max();
+  if (min == max) {
+    uint32_t code = static_cast<uint32_t>(min) & String::kMaxUtf16CodeUnitU;
+    Handle<String> string = f->LookupSingleCharacterStringFromCode(code);
+    return Type::Constant(string, t->zone());
+  }
+  return Type::String();
+}
+
+Type* Typer::Visitor::TypeStringFromCharCode(Node* node) {
+  return TypeUnaryOp(node, StringFromCharCodeTyper);
+}
+
 Type* Typer::Visitor::TypeStringToNumber(Node* node) {
   return TypeUnaryOp(node, ToNumber);
 }
@@ -1833,64 +1744,159 @@
 
 }  // namespace
 
+Type* Typer::Visitor::TypeChangeTaggedSignedToInt32(Node* node) {
+  Type* arg = Operand(node, 0);
+  // TODO(jarin): DCHECK(arg->Is(Type::Signed32()));
+  // Many tests fail this check.
+  return ChangeRepresentation(arg, Type::UntaggedIntegral32(), zone());
+}
 
 Type* Typer::Visitor::TypeChangeTaggedToInt32(Node* node) {
   Type* arg = Operand(node, 0);
-  // TODO(neis): DCHECK(arg->Is(Type::Signed32()));
+  DCHECK(arg->Is(Type::Signed32()));
   return ChangeRepresentation(arg, Type::UntaggedIntegral32(), zone());
 }
 
 
 Type* Typer::Visitor::TypeChangeTaggedToUint32(Node* node) {
   Type* arg = Operand(node, 0);
-  // TODO(neis): DCHECK(arg->Is(Type::Unsigned32()));
+  DCHECK(arg->Is(Type::Unsigned32()));
   return ChangeRepresentation(arg, Type::UntaggedIntegral32(), zone());
 }
 
 
 Type* Typer::Visitor::TypeChangeTaggedToFloat64(Node* node) {
   Type* arg = Operand(node, 0);
-  // TODO(neis): DCHECK(arg->Is(Type::Number()));
+  DCHECK(arg->Is(Type::Number()));
   return ChangeRepresentation(arg, Type::UntaggedFloat64(), zone());
 }
 
-
-Type* Typer::Visitor::TypeChangeInt32ToTagged(Node* node) {
+Type* Typer::Visitor::TypeTruncateTaggedToFloat64(Node* node) {
   Type* arg = Operand(node, 0);
-  // TODO(neis): DCHECK(arg->Is(Type::Signed32()));
+  // TODO(jarin) This DCHECK does not work because of speculative feedback.
+  // Re-enable once we record the speculative feedback in types.
+  // DCHECK(arg->Is(Type::NumberOrOddball()));
+  return ChangeRepresentation(arg, Type::UntaggedFloat64(), zone());
+}
+
+Type* Typer::Visitor::TypeChangeInt31ToTaggedSigned(Node* node) {
+  Type* arg = Operand(node, 0);
+  // TODO(jarin): DCHECK(arg->Is(Type::Signed31()));
+  // Some mjsunit/asm and mjsunit/wasm tests fail this check.
+  // For instance, asm/int32-umod fails with Signed32/UntaggedIntegral32 in
+  // simplified-lowering (after propagation).
   Type* rep =
       arg->Is(Type::SignedSmall()) ? Type::TaggedSigned() : Type::Tagged();
   return ChangeRepresentation(arg, rep, zone());
 }
 
+Type* Typer::Visitor::TypeChangeInt32ToTagged(Node* node) {
+  Type* arg = Operand(node, 0);
+  // TODO(jarin): DCHECK(arg->Is(Type::Signed32()));
+  // Two tests fail this check: mjsunit/asm/sqlite3/sqlite-safe-heap and
+  // mjsunit/wasm/embenchen/lua_binarytrees. The first one fails with Any/Any in
+  // simplified-lowering (after propagation).
+  Type* rep =
+      arg->Is(Type::SignedSmall()) ? Type::TaggedSigned() : Type::Tagged();
+  return ChangeRepresentation(arg, rep, zone());
+}
 
 Type* Typer::Visitor::TypeChangeUint32ToTagged(Node* node) {
   Type* arg = Operand(node, 0);
-  // TODO(neis): DCHECK(arg->Is(Type::Unsigned32()));
+  // TODO(jarin): DCHECK(arg->Is(Type::Unsigned32()));
+  // This fails in benchmarks/octane/mandreel (--turbo).
   return ChangeRepresentation(arg, Type::Tagged(), zone());
 }
 
-
 Type* Typer::Visitor::TypeChangeFloat64ToTagged(Node* node) {
   Type* arg = Operand(node, 0);
-  // TODO(neis): CHECK(arg.upper->Is(Type::Number()));
+  // TODO(jarin): DCHECK(arg->Is(Type::Number()));
+  // Some (or all) mjsunit/wasm/embenchen/ tests fail this check when run with
+  // --turbo and --always-opt.
   return ChangeRepresentation(arg, Type::Tagged(), zone());
 }
 
-
-Type* Typer::Visitor::TypeChangeBoolToBit(Node* node) {
+Type* Typer::Visitor::TypeChangeTaggedToBit(Node* node) {
   Type* arg = Operand(node, 0);
-  // TODO(neis): DCHECK(arg.upper->Is(Type::Boolean()));
+  DCHECK(arg->Is(Type::Boolean()));
   return ChangeRepresentation(arg, Type::UntaggedBit(), zone());
 }
 
-
-Type* Typer::Visitor::TypeChangeBitToBool(Node* node) {
+Type* Typer::Visitor::TypeChangeBitToTagged(Node* node) {
   Type* arg = Operand(node, 0);
-  // TODO(neis): DCHECK(arg.upper->Is(Type::Boolean()));
   return ChangeRepresentation(arg, Type::TaggedPointer(), zone());
 }
 
+Type* Typer::Visitor::TypeCheckBounds(Node* node) {
+  // TODO(bmeurer): We could do better here based on the limit.
+  return Type::Unsigned31();
+}
+
+Type* Typer::Visitor::TypeCheckTaggedPointer(Node* node) {
+  Type* arg = Operand(node, 0);
+  return Type::Intersect(arg, Type::TaggedPointer(), zone());
+}
+
+Type* Typer::Visitor::TypeCheckTaggedSigned(Node* node) {
+  Type* arg = Operand(node, 0);
+  return Type::Intersect(arg, typer_->cache_.kSmi, zone());
+}
+
+Type* Typer::Visitor::TypeCheckedInt32Add(Node* node) {
+  return Type::Integral32();
+}
+
+Type* Typer::Visitor::TypeCheckedInt32Sub(Node* node) {
+  return Type::Integral32();
+}
+
+Type* Typer::Visitor::TypeCheckedUint32ToInt32(Node* node) {
+  return Type::Signed32();
+}
+
+Type* Typer::Visitor::TypeCheckedFloat64ToInt32(Node* node) {
+  return Type::Signed32();
+}
+
+Type* Typer::Visitor::TypeCheckedTaggedToInt32(Node* node) {
+  return Type::Signed32();
+}
+
+Type* Typer::Visitor::TypeCheckedTaggedToFloat64(Node* node) {
+  return Type::Number();
+}
+
+Type* Typer::Visitor::TypeCheckFloat64Hole(Node* node) {
+  Type* type = Operand(node, 0);
+  return type;
+}
+
+Type* Typer::Visitor::TypeCheckTaggedHole(Node* node) {
+  CheckTaggedHoleMode mode = CheckTaggedHoleModeOf(node->op());
+  Type* type = Operand(node, 0);
+  type = Type::Intersect(type, Type::NonInternal(), zone());
+  switch (mode) {
+    case CheckTaggedHoleMode::kConvertHoleToUndefined: {
+      // The hole is turned into undefined.
+      type = Type::Union(type, Type::Undefined(), zone());
+      break;
+    }
+    case CheckTaggedHoleMode::kNeverReturnHole: {
+      // We deoptimize in case of the hole.
+      break;
+    }
+  }
+  return type;
+}
+
+Type* Typer::Visitor::TypeTruncateTaggedToWord32(Node* node) {
+  Type* arg = Operand(node, 0);
+  // TODO(jarin): DCHECK(arg->Is(Type::NumberOrUndefined()));
+  // Several mjsunit and cctest tests fail this check. For instance,
+  // mjsunit/compiler/regress-607493 fails with Any/Any in simplified-lowering
+  // (after propagation).
+  return ChangeRepresentation(arg, Type::UntaggedIntegral32(), zone());
+}
 
 Type* Typer::Visitor::TypeAllocate(Node* node) { return Type::TaggedPointer(); }
 
@@ -1949,9 +1955,9 @@
   // TODO(bmeurer): This typing is not yet correct. Since we can still access
   // out of bounds, the type in the general case has to include Undefined.
   switch (BufferAccessOf(node->op()).external_array_type()) {
-#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
-  case kExternal##Type##Array:                          \
-    return typer_->cache_.k##Type;
+#define TYPED_ARRAY_CASE(ElemType, type, TYPE, ctype, size) \
+  case kExternal##ElemType##Array:                          \
+    return Type::Union(typer_->cache_.k##ElemType, Type::Undefined(), zone());
     TYPED_ARRAYS(TYPED_ARRAY_CASE)
 #undef TYPED_ARRAY_CASE
   }
@@ -1982,6 +1988,9 @@
   return nullptr;
 }
 
+Type* Typer::Visitor::TypeObjectIsCallable(Node* node) {
+  return TypeUnaryOp(node, ObjectIsCallable);
+}
 
 Type* Typer::Visitor::TypeObjectIsNumber(Node* node) {
   return TypeUnaryOp(node, ObjectIsNumber);
@@ -1997,6 +2006,9 @@
   return TypeUnaryOp(node, ObjectIsSmi);
 }
 
+Type* Typer::Visitor::TypeObjectIsString(Node* node) {
+  return TypeUnaryOp(node, ObjectIsString);
+}
 
 Type* Typer::Visitor::TypeObjectIsUndetectable(Node* node) {
   return TypeUnaryOp(node, ObjectIsUndetectable);
@@ -2005,6 +2017,10 @@
 
 // Machine operators.
 
+Type* Typer::Visitor::TypeDebugBreak(Node* node) { return Type::None(); }
+
+Type* Typer::Visitor::TypeComment(Node* node) { return Type::None(); }
+
 Type* Typer::Visitor::TypeLoad(Node* node) { return Type::Any(); }
 
 Type* Typer::Visitor::TypeStackSlot(Node* node) { return Type::Any(); }
@@ -2194,6 +2210,9 @@
 
 Type* Typer::Visitor::TypeUint64Mod(Node* node) { return Type::Internal(); }
 
+Type* Typer::Visitor::TypeBitcastWordToTagged(Node* node) {
+  return Type::TaggedPointer();
+}
 
 Type* Typer::Visitor::TypeChangeFloat32ToFloat64(Node* node) {
   return Type::Intersect(Type::Number(), Type::UntaggedFloat64(), zone());
@@ -2204,6 +2223,9 @@
   return Type::Intersect(Type::Signed32(), Type::UntaggedIntegral32(), zone());
 }
 
+Type* Typer::Visitor::TypeNumberSilenceNaN(Node* node) {
+  return Type::Number();
+}
 
 Type* Typer::Visitor::TypeChangeFloat64ToUint32(Node* node) {
   return Type::Intersect(Type::Unsigned32(), Type::UntaggedIntegral32(),
@@ -2250,6 +2272,9 @@
   return Type::Intersect(Type::Signed32(), Type::UntaggedFloat64(), zone());
 }
 
+Type* Typer::Visitor::TypeFloat64SilenceNaN(Node* node) {
+  return Type::UntaggedFloat64();
+}
 
 Type* Typer::Visitor::TypeChangeInt32ToInt64(Node* node) {
   return Type::Internal();
@@ -2270,9 +2295,9 @@
   return Type::Intersect(Type::Number(), Type::UntaggedFloat32(), zone());
 }
 
-
-Type* Typer::Visitor::TypeTruncateFloat64ToInt32(Node* node) {
-  return Type::Intersect(Type::Signed32(), Type::UntaggedIntegral32(), zone());
+Type* Typer::Visitor::TypeTruncateFloat64ToWord32(Node* node) {
+  return Type::Intersect(Type::Integral32(), Type::UntaggedIntegral32(),
+                         zone());
 }
 
 
@@ -2280,6 +2305,9 @@
   return Type::Intersect(Type::Signed32(), Type::UntaggedIntegral32(), zone());
 }
 
+Type* Typer::Visitor::TypeRoundFloat64ToInt32(Node* node) {
+  return Type::Intersect(Type::Signed32(), Type::UntaggedIntegral32(), zone());
+}
 
 Type* Typer::Visitor::TypeRoundInt32ToFloat32(Node* node) {
   return Type::Intersect(Type::PlainNumber(), Type::UntaggedFloat32(), zone());
@@ -2336,6 +2364,11 @@
 
 Type* Typer::Visitor::TypeFloat32Sub(Node* node) { return Type::Number(); }
 
+Type* Typer::Visitor::TypeFloat32SubPreserveNan(Node* node) {
+  return Type::Number();
+}
+
+Type* Typer::Visitor::TypeFloat32Neg(Node* node) { return Type::Number(); }
 
 Type* Typer::Visitor::TypeFloat32Mul(Node* node) { return Type::Number(); }
 
@@ -2376,6 +2409,11 @@
 
 Type* Typer::Visitor::TypeFloat64Sub(Node* node) { return Type::Number(); }
 
+Type* Typer::Visitor::TypeFloat64SubPreserveNan(Node* node) {
+  return Type::Number();
+}
+
+Type* Typer::Visitor::TypeFloat64Neg(Node* node) { return Type::Number(); }
 
 Type* Typer::Visitor::TypeFloat64Mul(Node* node) { return Type::Number(); }
 
@@ -2397,9 +2435,33 @@
   return Type::Number();
 }
 
+Type* Typer::Visitor::TypeFloat64Atan(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Atan2(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Atanh(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Cos(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Exp(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Expm1(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Log(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Log1p(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Log2(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Log10(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Cbrt(Node* node) { return Type::Number(); }
+
+Type* Typer::Visitor::TypeFloat64Sin(Node* node) { return Type::Number(); }
 
 Type* Typer::Visitor::TypeFloat64Sqrt(Node* node) { return Type::Number(); }
 
+Type* Typer::Visitor::TypeFloat64Tan(Node* node) { return Type::Number(); }
 
 Type* Typer::Visitor::TypeFloat64Equal(Node* node) { return Type::Boolean(); }
 
@@ -2503,12 +2565,18 @@
 
 Type* Typer::Visitor::TypeCheckedLoad(Node* node) { return Type::Any(); }
 
-
 Type* Typer::Visitor::TypeCheckedStore(Node* node) {
   UNREACHABLE();
   return nullptr;
 }
 
+Type* Typer::Visitor::TypeAtomicLoad(Node* node) { return Type::Any(); }
+
+Type* Typer::Visitor::TypeAtomicStore(Node* node) {
+  UNREACHABLE();
+  return nullptr;
+}
+
 Type* Typer::Visitor::TypeInt32PairAdd(Node* node) { return Type::Internal(); }
 
 Type* Typer::Visitor::TypeInt32PairSub(Node* node) { return Type::Internal(); }
@@ -2521,8 +2589,25 @@
 
 Type* Typer::Visitor::TypeWord32PairSar(Node* node) { return Type::Internal(); }
 
-// Heap constants.
+// SIMD type methods.
 
+#define SIMD_RETURN_SIMD(Name) \
+  Type* Typer::Visitor::Type##Name(Node* node) { return Type::Simd(); }
+MACHINE_SIMD_RETURN_SIMD_OP_LIST(SIMD_RETURN_SIMD)
+MACHINE_SIMD_GENERIC_OP_LIST(SIMD_RETURN_SIMD)
+#undef SIMD_RETURN_SIMD
+
+#define SIMD_RETURN_NUM(Name) \
+  Type* Typer::Visitor::Type##Name(Node* node) { return Type::Number(); }
+MACHINE_SIMD_RETURN_NUM_OP_LIST(SIMD_RETURN_NUM)
+#undef SIMD_RETURN_NUM
+
+#define SIMD_RETURN_BOOL(Name) \
+  Type* Typer::Visitor::Type##Name(Node* node) { return Type::Boolean(); }
+MACHINE_SIMD_RETURN_BOOL_OP_LIST(SIMD_RETURN_BOOL)
+#undef SIMD_RETURN_BOOL
+
+// Heap constants.
 
 Type* Typer::Visitor::TypeConstant(Handle<Object> value) {
   if (value->IsJSTypedArray()) {
diff --git a/src/compiler/typer.h b/src/compiler/typer.h
index 0982b28..b6c5cb3 100644
--- a/src/compiler/typer.h
+++ b/src/compiler/typer.h
@@ -7,6 +7,7 @@
 
 #include "src/base/flags.h"
 #include "src/compiler/graph.h"
+#include "src/compiler/operation-typer.h"
 #include "src/types.h"
 
 namespace v8 {
@@ -18,6 +19,7 @@
 
 namespace compiler {
 
+class OperationTyper;
 
 class Typer {
  public:
@@ -47,6 +49,7 @@
   Flags flags() const { return flags_; }
   CompilationDependencies* dependencies() const { return dependencies_; }
   FunctionType* function_type() const { return function_type_; }
+  OperationTyper* operation_typer() { return &operation_typer_; }
 
   Isolate* const isolate_;
   Graph* const graph_;
@@ -55,6 +58,7 @@
   FunctionType* function_type_;
   Decorator* decorator_;
   TypeCache const& cache_;
+  OperationTyper operation_typer_;
 
   Type* singleton_false_;
   Type* singleton_true_;
diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc
index a69ace9..365f075 100644
--- a/src/compiler/verifier.cc
+++ b/src/compiler/verifier.cc
@@ -42,12 +42,14 @@
 
 class Verifier::Visitor {
  public:
-  Visitor(Zone* z, Typing typed) : zone(z), typing(typed) {}
+  Visitor(Zone* z, Typing typed, CheckInputs check_inputs)
+      : zone(z), typing(typed), check_inputs(check_inputs) {}
 
   void Check(Node* node);
 
   Zone* zone;
   Typing typing;
+  CheckInputs check_inputs;
 
  private:
   void CheckNotTyped(Node* node) {
@@ -114,8 +116,10 @@
   int control_count = node->op()->ControlInputCount();
 
   // Verify number of inputs matches up.
-  int input_count = value_count + context_count + frame_state_count +
-                    effect_count + control_count;
+  int input_count = value_count + context_count + frame_state_count;
+  if (check_inputs == kAll) {
+    input_count += effect_count + control_count;
+  }
   CHECK_EQ(input_count, node->InputCount());
 
   // Verify that frame state has been inserted for the nodes that need it.
@@ -150,20 +154,23 @@
     CHECK(IsUseDefChainLinkPresent(context, node));
   }
 
-  // Verify all effect inputs actually have an effect.
-  for (int i = 0; i < effect_count; ++i) {
-    Node* effect = NodeProperties::GetEffectInput(node);
-    CheckOutput(effect, node, effect->op()->EffectOutputCount(), "effect");
-    CHECK(IsDefUseChainLinkPresent(effect, node));
-    CHECK(IsUseDefChainLinkPresent(effect, node));
-  }
+  if (check_inputs == kAll) {
+    // Verify all effect inputs actually have an effect.
+    for (int i = 0; i < effect_count; ++i) {
+      Node* effect = NodeProperties::GetEffectInput(node);
+      CheckOutput(effect, node, effect->op()->EffectOutputCount(), "effect");
+      CHECK(IsDefUseChainLinkPresent(effect, node));
+      CHECK(IsUseDefChainLinkPresent(effect, node));
+    }
 
-  // Verify all control inputs are control nodes.
-  for (int i = 0; i < control_count; ++i) {
-    Node* control = NodeProperties::GetControlInput(node, i);
-    CheckOutput(control, node, control->op()->ControlOutputCount(), "control");
-    CHECK(IsDefUseChainLinkPresent(control, node));
-    CHECK(IsUseDefChainLinkPresent(control, node));
+    // Verify all control inputs are control nodes.
+    for (int i = 0; i < control_count; ++i) {
+      Node* control = NodeProperties::GetControlInput(node, i);
+      CheckOutput(control, node, control->op()->ControlOutputCount(),
+                  "control");
+      CHECK(IsDefUseChainLinkPresent(control, node));
+      CHECK(IsUseDefChainLinkPresent(control, node));
+    }
   }
 
   switch (node->opcode()) {
@@ -345,6 +352,10 @@
       // Type is a number.
       CheckUpperIs(node, Type::Number());
       break;
+    case IrOpcode::kRelocatableInt32Constant:
+    case IrOpcode::kRelocatableInt64Constant:
+      CHECK_EQ(0, input_count);
+      break;
     case IrOpcode::kHeapConstant:
       // Constants have no inputs.
       CHECK_EQ(0, input_count);
@@ -406,15 +417,13 @@
       CHECK_EQ(input_count, 1 + effect_count);
       break;
     }
-    case IrOpcode::kEffectSet: {
-      CHECK_EQ(0, value_count);
-      CHECK_EQ(0, control_count);
-      CHECK_LT(1, effect_count);
-      break;
-    }
-    case IrOpcode::kGuard:
+    case IrOpcode::kTypeGuard:
       // TODO(bmeurer): what are the constraints on these?
       break;
+    case IrOpcode::kCheckpoint:
+      // Type is empty.
+      CheckNotTyped(node);
+      break;
     case IrOpcode::kBeginRegion:
       // TODO(rossberg): what are the constraints on these?
       break;
@@ -596,7 +605,6 @@
       break;
     case IrOpcode::kJSCallFunction:
     case IrOpcode::kJSCallRuntime:
-    case IrOpcode::kJSYield:
       // Type can be anything.
       CheckUpperIs(node, Type::Any());
       break;
@@ -628,11 +636,31 @@
     case IrOpcode::kJSStoreMessage:
       break;
 
+    case IrOpcode::kJSGeneratorStore:
+      CheckNotTyped(node);
+      break;
+
+    case IrOpcode::kJSGeneratorRestoreContinuation:
+      CheckUpperIs(node, Type::SignedSmall());
+      break;
+
+    case IrOpcode::kJSGeneratorRestoreRegister:
+      CheckUpperIs(node, Type::Any());
+      break;
+
     case IrOpcode::kJSStackCheck:
       // Type is empty.
       CheckNotTyped(node);
       break;
 
+    case IrOpcode::kDebugBreak:
+      CheckNotTyped(node);
+      break;
+
+    case IrOpcode::kComment:
+      CheckNotTyped(node);
+      break;
+
     // Simplified operators
     // -------------------------------
     case IrOpcode::kBooleanNot:
@@ -646,6 +674,11 @@
       CheckUpperIs(node, Type::Number());
       break;
     case IrOpcode::kNumberEqual:
+      // (Number, Number) -> Boolean
+      CheckValueInputIs(node, 0, Type::Number());
+      CheckValueInputIs(node, 1, Type::Number());
+      CheckUpperIs(node, Type::Boolean());
+      break;
     case IrOpcode::kNumberLessThan:
     case IrOpcode::kNumberLessThanOrEqual:
       // (Number, Number) -> Boolean
@@ -653,16 +686,32 @@
       CheckValueInputIs(node, 1, Type::Number());
       CheckUpperIs(node, Type::Boolean());
       break;
+    case IrOpcode::kSpeculativeNumberAdd:
+    case IrOpcode::kSpeculativeNumberSubtract:
+    case IrOpcode::kSpeculativeNumberMultiply:
+    case IrOpcode::kSpeculativeNumberDivide:
+    case IrOpcode::kSpeculativeNumberModulus:
+      CheckUpperIs(node, Type::Number());
+      break;
+    case IrOpcode::kSpeculativeNumberEqual:
+    case IrOpcode::kSpeculativeNumberLessThan:
+    case IrOpcode::kSpeculativeNumberLessThanOrEqual:
+      CheckUpperIs(node, Type::Boolean());
+      break;
     case IrOpcode::kNumberAdd:
     case IrOpcode::kNumberSubtract:
     case IrOpcode::kNumberMultiply:
     case IrOpcode::kNumberDivide:
+      // (Number, Number) -> Number
+      CheckValueInputIs(node, 0, Type::Number());
+      CheckValueInputIs(node, 1, Type::Number());
+      CheckUpperIs(node, Type::Number());
+      break;
     case IrOpcode::kNumberModulus:
       // (Number, Number) -> Number
       CheckValueInputIs(node, 0, Type::Number());
       CheckValueInputIs(node, 1, Type::Number());
-      // TODO(rossberg): activate once we retype after opcode changes.
-      // CheckUpperIs(node, Type::Number());
+      CheckUpperIs(node, Type::Number());
       break;
     case IrOpcode::kNumberBitwiseOr:
     case IrOpcode::kNumberBitwiseXor:
@@ -696,9 +745,30 @@
       CheckValueInputIs(node, 0, Type::Unsigned32());
       CheckUpperIs(node, Type::Unsigned32());
       break;
+    case IrOpcode::kNumberAtan2:
+      // (Number, Number) -> Number
+      CheckValueInputIs(node, 0, Type::Number());
+      CheckValueInputIs(node, 1, Type::Number());
+      CheckUpperIs(node, Type::Number());
+      break;
+    case IrOpcode::kNumberAbs:
     case IrOpcode::kNumberCeil:
     case IrOpcode::kNumberFloor:
+    case IrOpcode::kNumberFround:
+    case IrOpcode::kNumberAtan:
+    case IrOpcode::kNumberAtanh:
+    case IrOpcode::kNumberCos:
+    case IrOpcode::kNumberExp:
+    case IrOpcode::kNumberExpm1:
+    case IrOpcode::kNumberLog:
+    case IrOpcode::kNumberLog1p:
+    case IrOpcode::kNumberLog2:
+    case IrOpcode::kNumberLog10:
+    case IrOpcode::kNumberCbrt:
     case IrOpcode::kNumberRound:
+    case IrOpcode::kNumberSin:
+    case IrOpcode::kNumberSqrt:
+    case IrOpcode::kNumberTan:
     case IrOpcode::kNumberTrunc:
       // Number -> Number
       CheckValueInputIs(node, 0, Type::Number());
@@ -714,14 +784,14 @@
       CheckValueInputIs(node, 0, Type::Number());
       CheckUpperIs(node, Type::Unsigned32());
       break;
-    case IrOpcode::kNumberIsHoleNaN:
-      // Number -> Boolean
-      CheckValueInputIs(node, 0, Type::Number());
-      CheckUpperIs(node, Type::Boolean());
-      break;
     case IrOpcode::kPlainPrimitiveToNumber:
-      // PlainPrimitive -> Number
-      CheckValueInputIs(node, 0, Type::PlainPrimitive());
+      // Type is Number.
+      CheckUpperIs(node, Type::Number());
+      break;
+    case IrOpcode::kPlainPrimitiveToWord32:
+      CheckUpperIs(node, Type::Number());
+      break;
+    case IrOpcode::kPlainPrimitiveToFloat64:
       CheckUpperIs(node, Type::Number());
       break;
     case IrOpcode::kStringEqual:
@@ -732,6 +802,11 @@
       CheckValueInputIs(node, 1, Type::String());
       CheckUpperIs(node, Type::Boolean());
       break;
+    case IrOpcode::kStringFromCharCode:
+      // Number -> String
+      CheckValueInputIs(node, 0, Type::Number());
+      CheckUpperIs(node, Type::String());
+      break;
     case IrOpcode::kStringToNumber:
       // String -> Number
       CheckValueInputIs(node, 0, Type::String());
@@ -743,9 +818,11 @@
       CheckUpperIs(node, Type::Boolean());
       break;
     }
+    case IrOpcode::kObjectIsCallable:
     case IrOpcode::kObjectIsNumber:
     case IrOpcode::kObjectIsReceiver:
     case IrOpcode::kObjectIsSmi:
+    case IrOpcode::kObjectIsString:
     case IrOpcode::kObjectIsUndetectable:
       CheckValueInputIs(node, 0, Type::Any());
       CheckUpperIs(node, Type::Boolean());
@@ -755,6 +832,15 @@
       CheckUpperIs(node, Type::TaggedPointer());
       break;
 
+    case IrOpcode::kChangeTaggedSignedToInt32: {
+      // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32
+      // TODO(neis): Activate once ChangeRepresentation works in typer.
+      // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged());
+      // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
+      // CheckValueInputIs(node, 0, from));
+      // CheckUpperIs(node, to));
+      break;
+    }
     case IrOpcode::kChangeTaggedToInt32: {
       // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32
       // TODO(neis): Activate once ChangeRepresentation works in typer.
@@ -774,7 +860,7 @@
       break;
     }
     case IrOpcode::kChangeTaggedToFloat64: {
-      // Number /\ Tagged -> Number /\ UntaggedFloat64
+      // NumberOrUndefined /\ Tagged -> Number /\ UntaggedFloat64
       // TODO(neis): Activate once ChangeRepresentation works in typer.
       // Type* from = Type::Intersect(Type::Number(), Type::Tagged());
       // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64());
@@ -782,6 +868,25 @@
       // CheckUpperIs(node, to));
       break;
     }
+    case IrOpcode::kTruncateTaggedToFloat64: {
+      // NumberOrUndefined /\ Tagged -> Number /\ UntaggedFloat64
+      // TODO(neis): Activate once ChangeRepresentation works in typer.
+      // Type* from = Type::Intersect(Type::NumberOrUndefined(),
+      // Type::Tagged());
+      // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64());
+      // CheckValueInputIs(node, 0, from));
+      // CheckUpperIs(node, to));
+      break;
+    }
+    case IrOpcode::kChangeInt31ToTaggedSigned: {
+      // Signed31 /\ UntaggedInt32 -> Signed31 /\ Tagged
+      // TODO(neis): Activate once ChangeRepresentation works in typer.
+      // Type* from =Type::Intersect(Type::Signed31(), Type::UntaggedInt32());
+      // Type* to = Type::Intersect(Type::Signed31(), Type::Tagged());
+      // CheckValueInputIs(node, 0, from));
+      // CheckUpperIs(node, to));
+      break;
+    }
     case IrOpcode::kChangeInt32ToTagged: {
       // Signed32 /\ UntaggedInt32 -> Signed32 /\ Tagged
       // TODO(neis): Activate once ChangeRepresentation works in typer.
@@ -809,7 +914,7 @@
       // CheckUpperIs(node, to));
       break;
     }
-    case IrOpcode::kChangeBoolToBit: {
+    case IrOpcode::kChangeTaggedToBit: {
       // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1
       // TODO(neis): Activate once ChangeRepresentation works in typer.
       // Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
@@ -818,7 +923,7 @@
       // CheckUpperIs(node, to));
       break;
     }
-    case IrOpcode::kChangeBitToBool: {
+    case IrOpcode::kChangeBitToTagged: {
       // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr
       // TODO(neis): Activate once ChangeRepresentation works in typer.
       // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
@@ -827,6 +932,46 @@
       // CheckUpperIs(node, to));
       break;
     }
+    case IrOpcode::kTruncateTaggedToWord32: {
+      // Number /\ Tagged -> Signed32 /\ UntaggedInt32
+      // TODO(neis): Activate once ChangeRepresentation works in typer.
+      // Type* from = Type::Intersect(Type::Number(), Type::Tagged());
+      // Type* to = Type::Intersect(Type::Number(), Type::UntaggedInt32());
+      // CheckValueInputIs(node, 0, from));
+      // CheckUpperIs(node, to));
+      break;
+    }
+
+    case IrOpcode::kCheckBounds:
+      CheckValueInputIs(node, 0, Type::Any());
+      CheckValueInputIs(node, 1, Type::Unsigned31());
+      CheckUpperIs(node, Type::Unsigned31());
+      break;
+    case IrOpcode::kCheckTaggedSigned:
+      CheckValueInputIs(node, 0, Type::Any());
+      CheckUpperIs(node, Type::TaggedSigned());
+      break;
+    case IrOpcode::kCheckTaggedPointer:
+      CheckValueInputIs(node, 0, Type::Any());
+      CheckUpperIs(node, Type::TaggedPointer());
+      break;
+
+    case IrOpcode::kCheckedInt32Add:
+    case IrOpcode::kCheckedInt32Sub:
+    case IrOpcode::kCheckedUint32ToInt32:
+    case IrOpcode::kCheckedFloat64ToInt32:
+    case IrOpcode::kCheckedTaggedToInt32:
+    case IrOpcode::kCheckedTaggedToFloat64:
+      break;
+
+    case IrOpcode::kCheckFloat64Hole:
+      CheckValueInputIs(node, 0, Type::Number());
+      CheckUpperIs(node, Type::Number());
+      break;
+    case IrOpcode::kCheckTaggedHole:
+      CheckValueInputIs(node, 0, Type::Any());
+      CheckUpperIs(node, Type::Any());
+      break;
 
     case IrOpcode::kLoadField:
       // Object -> fieldtype
@@ -858,6 +1003,10 @@
       // CheckValueInputIs(node, 1, ElementAccessOf(node->op()).type));
       CheckNotTyped(node);
       break;
+    case IrOpcode::kNumberSilenceNaN:
+      CheckValueInputIs(node, 0, Type::Number());
+      CheckUpperIs(node, Type::Number());
+      break;
 
     // Machine operators
     // -----------------------
@@ -918,6 +1067,8 @@
     case IrOpcode::kUint64LessThanOrEqual:
     case IrOpcode::kFloat32Add:
     case IrOpcode::kFloat32Sub:
+    case IrOpcode::kFloat32SubPreserveNan:
+    case IrOpcode::kFloat32Neg:
     case IrOpcode::kFloat32Mul:
     case IrOpcode::kFloat32Div:
     case IrOpcode::kFloat32Max:
@@ -929,13 +1080,28 @@
     case IrOpcode::kFloat32LessThanOrEqual:
     case IrOpcode::kFloat64Add:
     case IrOpcode::kFloat64Sub:
+    case IrOpcode::kFloat64SubPreserveNan:
+    case IrOpcode::kFloat64Neg:
     case IrOpcode::kFloat64Mul:
     case IrOpcode::kFloat64Div:
     case IrOpcode::kFloat64Mod:
     case IrOpcode::kFloat64Max:
     case IrOpcode::kFloat64Min:
     case IrOpcode::kFloat64Abs:
+    case IrOpcode::kFloat64Atan:
+    case IrOpcode::kFloat64Atan2:
+    case IrOpcode::kFloat64Atanh:
+    case IrOpcode::kFloat64Cos:
+    case IrOpcode::kFloat64Exp:
+    case IrOpcode::kFloat64Expm1:
+    case IrOpcode::kFloat64Log:
+    case IrOpcode::kFloat64Log1p:
+    case IrOpcode::kFloat64Log2:
+    case IrOpcode::kFloat64Log10:
+    case IrOpcode::kFloat64Cbrt:
+    case IrOpcode::kFloat64Sin:
     case IrOpcode::kFloat64Sqrt:
+    case IrOpcode::kFloat64Tan:
     case IrOpcode::kFloat32RoundDown:
     case IrOpcode::kFloat64RoundDown:
     case IrOpcode::kFloat32RoundUp:
@@ -949,6 +1115,7 @@
     case IrOpcode::kFloat64LessThan:
     case IrOpcode::kFloat64LessThanOrEqual:
     case IrOpcode::kTruncateInt64ToInt32:
+    case IrOpcode::kRoundFloat64ToInt32:
     case IrOpcode::kRoundInt32ToFloat32:
     case IrOpcode::kRoundInt64ToFloat32:
     case IrOpcode::kRoundInt64ToFloat64:
@@ -956,11 +1123,12 @@
     case IrOpcode::kRoundUint64ToFloat64:
     case IrOpcode::kRoundUint64ToFloat32:
     case IrOpcode::kTruncateFloat64ToFloat32:
-    case IrOpcode::kTruncateFloat64ToInt32:
+    case IrOpcode::kTruncateFloat64ToWord32:
     case IrOpcode::kBitcastFloat32ToInt32:
     case IrOpcode::kBitcastFloat64ToInt64:
     case IrOpcode::kBitcastInt32ToFloat32:
     case IrOpcode::kBitcastInt64ToFloat64:
+    case IrOpcode::kBitcastWordToTagged:
     case IrOpcode::kChangeInt32ToInt64:
     case IrOpcode::kChangeUint32ToUint64:
     case IrOpcode::kChangeInt32ToFloat64:
@@ -968,6 +1136,7 @@
     case IrOpcode::kChangeFloat32ToFloat64:
     case IrOpcode::kChangeFloat64ToInt32:
     case IrOpcode::kChangeFloat64ToUint32:
+    case IrOpcode::kFloat64SilenceNaN:
     case IrOpcode::kTruncateFloat64ToUint32:
     case IrOpcode::kTruncateFloat32ToInt32:
     case IrOpcode::kTruncateFloat32ToUint32:
@@ -990,17 +1159,23 @@
     case IrOpcode::kLoadParentFramePointer:
     case IrOpcode::kCheckedLoad:
     case IrOpcode::kCheckedStore:
+    case IrOpcode::kAtomicLoad:
+    case IrOpcode::kAtomicStore:
+
+#define SIMD_MACHINE_OP_CASE(Name) case IrOpcode::k##Name:
+      MACHINE_SIMD_OP_LIST(SIMD_MACHINE_OP_CASE)
+#undef SIMD_MACHINE_OP_CASE
+
       // TODO(rossberg): Check.
       break;
   }
 }  // NOLINT(readability/fn_size)
 
-
-void Verifier::Run(Graph* graph, Typing typing) {
+void Verifier::Run(Graph* graph, Typing typing, CheckInputs check_inputs) {
   CHECK_NOT_NULL(graph->start());
   CHECK_NOT_NULL(graph->end());
   Zone zone(graph->zone()->allocator());
-  Visitor visitor(&zone, typing);
+  Visitor visitor(&zone, typing, check_inputs);
   AllNodes all(&zone, graph);
   for (Node* node : all.live) visitor.Check(node);
 
diff --git a/src/compiler/verifier.h b/src/compiler/verifier.h
index 428558d..60849e0 100644
--- a/src/compiler/verifier.h
+++ b/src/compiler/verifier.h
@@ -21,8 +21,10 @@
 class Verifier {
  public:
   enum Typing { TYPED, UNTYPED };
+  enum CheckInputs { kValuesOnly, kAll };
 
-  static void Run(Graph* graph, Typing typing = TYPED);
+  static void Run(Graph* graph, Typing typing = TYPED,
+                  CheckInputs check_inputs = kAll);
 
 #ifdef DEBUG
   // Verifies consistency of node inputs and uses:
diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc
index 93d5a08..0a13f98 100644
--- a/src/compiler/wasm-compiler.cc
+++ b/src/compiler/wasm-compiler.cc
@@ -10,11 +10,10 @@
 #include "src/base/platform/platform.h"
 
 #include "src/compiler/access-builder.h"
-#include "src/compiler/change-lowering.h"
 #include "src/compiler/common-operator.h"
 #include "src/compiler/diamond.h"
-#include "src/compiler/graph.h"
 #include "src/compiler/graph-visualizer.h"
+#include "src/compiler/graph.h"
 #include "src/compiler/instruction-selector.h"
 #include "src/compiler/int64-lowering.h"
 #include "src/compiler/js-generic-lowering.h"
@@ -24,16 +23,13 @@
 #include "src/compiler/machine-operator.h"
 #include "src/compiler/node-matchers.h"
 #include "src/compiler/pipeline.h"
-#include "src/compiler/simplified-lowering.h"
-#include "src/compiler/simplified-operator.h"
 #include "src/compiler/source-position.h"
-#include "src/compiler/typer.h"
+#include "src/compiler/zone-pool.h"
 
 #include "src/code-factory.h"
 #include "src/code-stubs.h"
 #include "src/factory.h"
 #include "src/log-inl.h"
-#include "src/profiler/cpu-profiler.h"
 
 #include "src/wasm/ast-decoder.h"
 #include "src/wasm/wasm-module.h"
@@ -52,17 +48,11 @@
 
 namespace {
 const Operator* UnsupportedOpcode(wasm::WasmOpcode opcode) {
-  if (wasm::WasmOpcodes::IsSupported(opcode)) {
-    V8_Fatal(__FILE__, __LINE__,
-             "Unsupported opcode #%d:%s reported as supported", opcode,
-             wasm::WasmOpcodes::OpcodeName(opcode));
-  }
   V8_Fatal(__FILE__, __LINE__, "Unsupported opcode #%d:%s", opcode,
            wasm::WasmOpcodes::OpcodeName(opcode));
   return nullptr;
 }
 
-
 void MergeControlToEnd(JSGraph* jsgraph, Node* node) {
   Graph* g = jsgraph->graph();
   if (g->end()) {
@@ -83,62 +73,72 @@
   explicit WasmTrapHelper(WasmGraphBuilder* builder)
       : builder_(builder),
         jsgraph_(builder->jsgraph()),
-        graph_(builder->jsgraph() ? builder->jsgraph()->graph() : nullptr) {
-    for (int i = 0; i < wasm::kTrapCount; i++) traps_[i] = nullptr;
-  }
+        graph_(builder->jsgraph() ? builder->jsgraph()->graph() : nullptr) {}
 
   // Make the current control path trap to unreachable.
-  void Unreachable() { ConnectTrap(wasm::kTrapUnreachable); }
+  void Unreachable(wasm::WasmCodePosition position) {
+    ConnectTrap(wasm::kTrapUnreachable, position);
+  }
 
   // Always trap with the given reason.
-  void TrapAlways(wasm::TrapReason reason) { ConnectTrap(reason); }
+  void TrapAlways(wasm::TrapReason reason, wasm::WasmCodePosition position) {
+    ConnectTrap(reason, position);
+  }
 
   // Add a check that traps if {node} is equal to {val}.
-  Node* TrapIfEq32(wasm::TrapReason reason, Node* node, int32_t val) {
+  Node* TrapIfEq32(wasm::TrapReason reason, Node* node, int32_t val,
+                   wasm::WasmCodePosition position) {
     Int32Matcher m(node);
     if (m.HasValue() && !m.Is(val)) return graph()->start();
     if (val == 0) {
-      AddTrapIfFalse(reason, node);
+      AddTrapIfFalse(reason, node, position);
     } else {
       AddTrapIfTrue(reason,
                     graph()->NewNode(jsgraph()->machine()->Word32Equal(), node,
-                                     jsgraph()->Int32Constant(val)));
+                                     jsgraph()->Int32Constant(val)),
+                    position);
     }
     return builder_->Control();
   }
 
   // Add a check that traps if {node} is zero.
-  Node* ZeroCheck32(wasm::TrapReason reason, Node* node) {
-    return TrapIfEq32(reason, node, 0);
+  Node* ZeroCheck32(wasm::TrapReason reason, Node* node,
+                    wasm::WasmCodePosition position) {
+    return TrapIfEq32(reason, node, 0, position);
   }
 
   // Add a check that traps if {node} is equal to {val}.
-  Node* TrapIfEq64(wasm::TrapReason reason, Node* node, int64_t val) {
+  Node* TrapIfEq64(wasm::TrapReason reason, Node* node, int64_t val,
+                   wasm::WasmCodePosition position) {
     Int64Matcher m(node);
     if (m.HasValue() && !m.Is(val)) return graph()->start();
-    AddTrapIfTrue(reason,
-                  graph()->NewNode(jsgraph()->machine()->Word64Equal(), node,
-                                   jsgraph()->Int64Constant(val)));
+    AddTrapIfTrue(reason, graph()->NewNode(jsgraph()->machine()->Word64Equal(),
+                                           node, jsgraph()->Int64Constant(val)),
+                  position);
     return builder_->Control();
   }
 
   // Add a check that traps if {node} is zero.
-  Node* ZeroCheck64(wasm::TrapReason reason, Node* node) {
-    return TrapIfEq64(reason, node, 0);
+  Node* ZeroCheck64(wasm::TrapReason reason, Node* node,
+                    wasm::WasmCodePosition position) {
+    return TrapIfEq64(reason, node, 0, position);
   }
 
   // Add a trap if {cond} is true.
-  void AddTrapIfTrue(wasm::TrapReason reason, Node* cond) {
-    AddTrapIf(reason, cond, true);
+  void AddTrapIfTrue(wasm::TrapReason reason, Node* cond,
+                     wasm::WasmCodePosition position) {
+    AddTrapIf(reason, cond, true, position);
   }
 
   // Add a trap if {cond} is false.
-  void AddTrapIfFalse(wasm::TrapReason reason, Node* cond) {
-    AddTrapIf(reason, cond, false);
+  void AddTrapIfFalse(wasm::TrapReason reason, Node* cond,
+                      wasm::WasmCodePosition position) {
+    AddTrapIf(reason, cond, false, position);
   }
 
   // Add a trap if {cond} is true or false according to {iftrue}.
-  void AddTrapIf(wasm::TrapReason reason, Node* cond, bool iftrue) {
+  void AddTrapIf(wasm::TrapReason reason, Node* cond, bool iftrue,
+                 wasm::WasmCodePosition position) {
     Node** effect_ptr = builder_->effect_;
     Node** control_ptr = builder_->control_;
     Node* before = *effect_ptr;
@@ -148,7 +148,7 @@
     Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
 
     *control_ptr = iftrue ? if_true : if_false;
-    ConnectTrap(reason);
+    ConnectTrap(reason, position);
     *control_ptr = iftrue ? if_false : if_true;
     *effect_ptr = before;
   }
@@ -179,49 +179,69 @@
   WasmGraphBuilder* builder_;
   JSGraph* jsgraph_;
   Graph* graph_;
-  Node* traps_[wasm::kTrapCount];
-  Node* effects_[wasm::kTrapCount];
+  Node* trap_merge_ = nullptr;
+  Node* trap_effect_;
+  Node* trap_reason_;
+  Node* trap_position_;
 
   JSGraph* jsgraph() { return jsgraph_; }
   Graph* graph() { return jsgraph_->graph(); }
   CommonOperatorBuilder* common() { return jsgraph()->common(); }
 
-  void ConnectTrap(wasm::TrapReason reason) {
-    if (traps_[reason] == nullptr) {
-      // Create trap code for the first time this trap is used.
-      return BuildTrapCode(reason);
+  void ConnectTrap(wasm::TrapReason reason, wasm::WasmCodePosition position) {
+    DCHECK(position != wasm::kNoCodePosition);
+    Node* reason_node = builder_->Int32Constant(
+        wasm::WasmOpcodes::TrapReasonToMessageId(reason));
+    Node* position_node = builder_->Int32Constant(position);
+    if (trap_merge_ == nullptr) {
+      // Create trap code for the first time.
+      return BuildTrapCode(reason_node, position_node);
     }
     // Connect the current control and effect to the existing trap code.
-    builder_->AppendToMerge(traps_[reason], builder_->Control());
-    builder_->AppendToPhi(traps_[reason], effects_[reason], builder_->Effect());
+    builder_->AppendToMerge(trap_merge_, builder_->Control());
+    builder_->AppendToPhi(trap_effect_, builder_->Effect());
+    builder_->AppendToPhi(trap_reason_, reason_node);
+    builder_->AppendToPhi(trap_position_, position_node);
   }
 
-  void BuildTrapCode(wasm::TrapReason reason) {
-    Node* exception =
-        builder_->String(wasm::WasmOpcodes::TrapReasonName(reason));
+  void BuildTrapCode(Node* reason_node, Node* position_node) {
     Node* end;
     Node** control_ptr = builder_->control_;
     Node** effect_ptr = builder_->effect_;
     wasm::ModuleEnv* module = builder_->module_;
-    *control_ptr = traps_[reason] =
+    DCHECK(trap_merge_ == NULL);
+    *control_ptr = trap_merge_ =
         graph()->NewNode(common()->Merge(1), *control_ptr);
-    *effect_ptr = effects_[reason] =
+    *effect_ptr = trap_effect_ =
         graph()->NewNode(common()->EffectPhi(1), *effect_ptr, *control_ptr);
+    trap_reason_ =
+        graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 1),
+                         reason_node, *control_ptr);
+    trap_position_ =
+        graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 1),
+                         position_node, *control_ptr);
+
+    Node* trap_reason_smi = builder_->BuildChangeInt32ToSmi(trap_reason_);
+    Node* trap_position_smi = builder_->BuildChangeInt32ToSmi(trap_position_);
 
     if (module && !module->instance->context.is_null()) {
       // Use the module context to call the runtime to throw an exception.
-      Runtime::FunctionId f = Runtime::kThrow;
+      Runtime::FunctionId f = Runtime::kThrowWasmError;
       const Runtime::Function* fun = Runtime::FunctionForId(f);
       CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
           jsgraph()->zone(), f, fun->nargs, Operator::kNoProperties,
           CallDescriptor::kNoFlags);
+      // CEntryStubConstant nodes have to be created and cached in the main
+      // thread. At the moment this is only done for CEntryStubConstant(1).
+      DCHECK_EQ(1, fun->result_size);
       Node* inputs[] = {
           jsgraph()->CEntryStubConstant(fun->result_size),  // C entry
-          exception,                                        // exception
+          trap_reason_smi,                                  // message id
+          trap_position_smi,                                // byte position
           jsgraph()->ExternalConstant(
-              ExternalReference(f, jsgraph()->isolate())),  // ref
-          jsgraph()->Int32Constant(fun->nargs),             // arity
-          jsgraph()->Constant(module->instance->context),   // context
+              ExternalReference(f, jsgraph()->isolate())),    // ref
+          jsgraph()->Int32Constant(fun->nargs),               // arity
+          builder_->HeapConstant(module->instance->context),  // context
           *effect_ptr,
           *control_ptr};
 
@@ -247,8 +267,9 @@
   }
 };
 
-WasmGraphBuilder::WasmGraphBuilder(Zone* zone, JSGraph* jsgraph,
-                                   wasm::FunctionSig* function_signature)
+WasmGraphBuilder::WasmGraphBuilder(
+    Zone* zone, JSGraph* jsgraph, wasm::FunctionSig* function_signature,
+    compiler::SourcePositionTable* source_position_table)
     : zone_(zone),
       jsgraph_(jsgraph),
       module_(nullptr),
@@ -260,32 +281,28 @@
       cur_buffer_(def_buffer_),
       cur_bufsize_(kDefaultBufferSize),
       trap_(new (zone) WasmTrapHelper(this)),
-      function_signature_(function_signature) {
+      function_signature_(function_signature),
+      source_position_table_(source_position_table) {
   DCHECK_NOT_NULL(jsgraph_);
 }
 
-
 Node* WasmGraphBuilder::Error() { return jsgraph()->Dead(); }
 
-
 Node* WasmGraphBuilder::Start(unsigned params) {
   Node* start = graph()->NewNode(jsgraph()->common()->Start(params));
   graph()->SetStart(start);
   return start;
 }
 
-
 Node* WasmGraphBuilder::Param(unsigned index, wasm::LocalType type) {
   return graph()->NewNode(jsgraph()->common()->Parameter(index),
                           graph()->start());
 }
 
-
 Node* WasmGraphBuilder::Loop(Node* entry) {
   return graph()->NewNode(jsgraph()->common()->Loop(1), entry);
 }
 
-
 Node* WasmGraphBuilder::Terminate(Node* effect, Node* control) {
   Node* terminate =
       graph()->NewNode(jsgraph()->common()->Terminate(), effect, control);
@@ -293,18 +310,15 @@
   return terminate;
 }
 
-
 unsigned WasmGraphBuilder::InputCount(Node* node) {
   return static_cast<unsigned>(node->InputCount());
 }
 
-
 bool WasmGraphBuilder::IsPhiWithMerge(Node* phi, Node* merge) {
   return phi && IrOpcode::IsPhiOpcode(phi->opcode()) &&
          NodeProperties::GetControlInput(phi) == merge;
 }
 
-
 void WasmGraphBuilder::AppendToMerge(Node* merge, Node* from) {
   DCHECK(IrOpcode::IsMergeOpcode(merge->opcode()));
   merge->AppendInput(jsgraph()->zone(), from);
@@ -313,22 +327,18 @@
       merge, jsgraph()->common()->ResizeMergeOrPhi(merge->op(), new_size));
 }
 
-
-void WasmGraphBuilder::AppendToPhi(Node* merge, Node* phi, Node* from) {
+void WasmGraphBuilder::AppendToPhi(Node* phi, Node* from) {
   DCHECK(IrOpcode::IsPhiOpcode(phi->opcode()));
-  DCHECK(IrOpcode::IsMergeOpcode(merge->opcode()));
   int new_size = phi->InputCount();
   phi->InsertInput(jsgraph()->zone(), phi->InputCount() - 1, from);
   NodeProperties::ChangeOp(
       phi, jsgraph()->common()->ResizeMergeOrPhi(phi->op(), new_size));
 }
 
-
 Node* WasmGraphBuilder::Merge(unsigned count, Node** controls) {
   return graph()->NewNode(jsgraph()->common()->Merge(count), count, controls);
 }
 
-
 Node* WasmGraphBuilder::Phi(wasm::LocalType type, unsigned count, Node** vals,
                             Node* control) {
   DCHECK(IrOpcode::IsMergeOpcode(control->opcode()));
@@ -338,7 +348,6 @@
                           buf);
 }
 
-
 Node* WasmGraphBuilder::EffectPhi(unsigned count, Node** effects,
                                   Node* control) {
   DCHECK(IrOpcode::IsMergeOpcode(control->opcode()));
@@ -348,19 +357,20 @@
                           buf);
 }
 
+Node* WasmGraphBuilder::NumberConstant(int32_t value) {
+  return jsgraph()->Constant(value);
+}
 
 Node* WasmGraphBuilder::Int32Constant(int32_t value) {
   return jsgraph()->Int32Constant(value);
 }
 
-
 Node* WasmGraphBuilder::Int64Constant(int64_t value) {
   return jsgraph()->Int64Constant(value);
 }
 
-
-Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left,
-                              Node* right) {
+Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
+                              wasm::WasmCodePosition position) {
   const Operator* op;
   MachineOperatorBuilder* m = jsgraph()->machine();
   switch (opcode) {
@@ -374,13 +384,13 @@
       op = m->Int32Mul();
       break;
     case wasm::kExprI32DivS:
-      return BuildI32DivS(left, right);
+      return BuildI32DivS(left, right, position);
     case wasm::kExprI32DivU:
-      return BuildI32DivU(left, right);
+      return BuildI32DivU(left, right, position);
     case wasm::kExprI32RemS:
-      return BuildI32RemS(left, right);
+      return BuildI32RemS(left, right, position);
     case wasm::kExprI32RemU:
-      return BuildI32RemU(left, right);
+      return BuildI32RemU(left, right, position);
     case wasm::kExprI32And:
       op = m->Word32And();
       break;
@@ -445,62 +455,46 @@
     case wasm::kExprI64And:
       op = m->Word64And();
       break;
-    // todo(ahaas): I added a list of missing instructions here to make merging
-    // easier when I do them one by one.
-    // kExprI64Add:
     case wasm::kExprI64Add:
       op = m->Int64Add();
       break;
-    // kExprI64Sub:
     case wasm::kExprI64Sub:
       op = m->Int64Sub();
       break;
-    // kExprI64Mul:
     case wasm::kExprI64Mul:
       op = m->Int64Mul();
       break;
-    // kExprI64DivS:
     case wasm::kExprI64DivS:
-      return BuildI64DivS(left, right);
-    // kExprI64DivU:
+      return BuildI64DivS(left, right, position);
     case wasm::kExprI64DivU:
-      return BuildI64DivU(left, right);
-    // kExprI64RemS:
+      return BuildI64DivU(left, right, position);
     case wasm::kExprI64RemS:
-      return BuildI64RemS(left, right);
-    // kExprI64RemU:
+      return BuildI64RemS(left, right, position);
     case wasm::kExprI64RemU:
-      return BuildI64RemU(left, right);
+      return BuildI64RemU(left, right, position);
     case wasm::kExprI64Ior:
       op = m->Word64Or();
       break;
-// kExprI64Xor:
     case wasm::kExprI64Xor:
       op = m->Word64Xor();
       break;
-// kExprI64Shl:
     case wasm::kExprI64Shl:
       op = m->Word64Shl();
       right = MaskShiftCount64(right);
       break;
-    // kExprI64ShrU:
     case wasm::kExprI64ShrU:
       op = m->Word64Shr();
       right = MaskShiftCount64(right);
       break;
-    // kExprI64ShrS:
     case wasm::kExprI64ShrS:
       op = m->Word64Sar();
       right = MaskShiftCount64(right);
       break;
-    // kExprI64Eq:
     case wasm::kExprI64Eq:
       op = m->Word64Equal();
       break;
-// kExprI64Ne:
     case wasm::kExprI64Ne:
       return Invert(Binop(wasm::kExprI64Eq, left, right));
-// kExprI64LtS:
     case wasm::kExprI64LtS:
       op = m->Int64LessThan();
       break;
@@ -543,7 +537,7 @@
       op = m->Float32Add();
       break;
     case wasm::kExprF32Sub:
-      op = m->Float32Sub();
+      op = m->Float32SubPreserveNan();
       break;
     case wasm::kExprF32Mul:
       op = m->Float32Mul();
@@ -574,7 +568,7 @@
       op = m->Float64Add();
       break;
     case wasm::kExprF64Sub:
-      op = m->Float64Sub();
+      op = m->Float64SubPreserveNan();
       break;
     case wasm::kExprF64Mul:
       op = m->Float64Mul();
@@ -609,23 +603,39 @@
       return BuildF32Max(left, right);
     case wasm::kExprF64Max:
       return BuildF64Max(left, right);
-    case wasm::kExprF64Pow: {
+    case wasm::kExprF64Pow:
       return BuildF64Pow(left, right);
-    }
-    case wasm::kExprF64Atan2: {
-      return BuildF64Atan2(left, right);
-    }
-    case wasm::kExprF64Mod: {
+    case wasm::kExprF64Atan2:
+      op = m->Float64Atan2();
+      break;
+    case wasm::kExprF64Mod:
       return BuildF64Mod(left, right);
-    }
+    case wasm::kExprI32AsmjsDivS:
+      return BuildI32AsmjsDivS(left, right);
+    case wasm::kExprI32AsmjsDivU:
+      return BuildI32AsmjsDivU(left, right);
+    case wasm::kExprI32AsmjsRemS:
+      return BuildI32AsmjsRemS(left, right);
+    case wasm::kExprI32AsmjsRemU:
+      return BuildI32AsmjsRemU(left, right);
+    case wasm::kExprI32AsmjsStoreMem8:
+      return BuildAsmjsStoreMem(MachineType::Int8(), left, right);
+    case wasm::kExprI32AsmjsStoreMem16:
+      return BuildAsmjsStoreMem(MachineType::Int16(), left, right);
+    case wasm::kExprI32AsmjsStoreMem:
+      return BuildAsmjsStoreMem(MachineType::Int32(), left, right);
+    case wasm::kExprF32AsmjsStoreMem:
+      return BuildAsmjsStoreMem(MachineType::Float32(), left, right);
+    case wasm::kExprF64AsmjsStoreMem:
+      return BuildAsmjsStoreMem(MachineType::Float64(), left, right);
     default:
       op = UnsupportedOpcode(opcode);
   }
   return graph()->NewNode(op, left, right);
 }
 
-
-Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
+Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input,
+                             wasm::WasmCodePosition position) {
   const Operator* op;
   MachineOperatorBuilder* m = jsgraph()->machine();
   switch (opcode) {
@@ -635,23 +645,39 @@
     case wasm::kExprF32Abs:
       op = m->Float32Abs();
       break;
-    case wasm::kExprF32Neg:
-      return BuildF32Neg(input);
+    case wasm::kExprF32Neg: {
+      if (m->Float32Neg().IsSupported()) {
+        op = m->Float32Neg().op();
+        break;
+      } else {
+        return BuildF32Neg(input);
+      }
+    }
     case wasm::kExprF32Sqrt:
       op = m->Float32Sqrt();
       break;
     case wasm::kExprF64Abs:
       op = m->Float64Abs();
       break;
-    case wasm::kExprF64Neg:
-      return BuildF64Neg(input);
+    case wasm::kExprF64Neg: {
+      if (m->Float64Neg().IsSupported()) {
+        op = m->Float64Neg().op();
+        break;
+      } else {
+        return BuildF64Neg(input);
+      }
+    }
     case wasm::kExprF64Sqrt:
       op = m->Float64Sqrt();
       break;
     case wasm::kExprI32SConvertF64:
-      return BuildI32SConvertF64(input);
+      return BuildI32SConvertF64(input, position);
     case wasm::kExprI32UConvertF64:
-      return BuildI32UConvertF64(input);
+      return BuildI32UConvertF64(input, position);
+    case wasm::kExprI32AsmjsSConvertF64:
+      return BuildI32AsmjsSConvertF64(input);
+    case wasm::kExprI32AsmjsUConvertF64:
+      return BuildI32AsmjsUConvertF64(input);
     case wasm::kExprF32ConvertF64:
       op = m->TruncateFloat64ToFloat32();
       break;
@@ -668,9 +694,13 @@
       op = m->RoundUint32ToFloat32();
       break;
     case wasm::kExprI32SConvertF32:
-      return BuildI32SConvertF32(input);
+      return BuildI32SConvertF32(input, position);
     case wasm::kExprI32UConvertF32:
-      return BuildI32UConvertF32(input);
+      return BuildI32UConvertF32(input, position);
+    case wasm::kExprI32AsmjsSConvertF32:
+      return BuildI32AsmjsSConvertF32(input);
+    case wasm::kExprI32AsmjsUConvertF32:
+      return BuildI32AsmjsUConvertF32(input);
     case wasm::kExprF64ConvertF32:
       op = m->ChangeFloat32ToFloat64();
       break;
@@ -751,49 +781,46 @@
     case wasm::kExprF64Asin: {
       return BuildF64Asin(input);
     }
-    case wasm::kExprF64Atan: {
-      return BuildF64Atan(input);
-    }
+    case wasm::kExprF64Atan:
+      op = m->Float64Atan();
+      break;
     case wasm::kExprF64Cos: {
-      return BuildF64Cos(input);
+      op = m->Float64Cos();
+      break;
     }
     case wasm::kExprF64Sin: {
-      return BuildF64Sin(input);
+      op = m->Float64Sin();
+      break;
     }
     case wasm::kExprF64Tan: {
-      return BuildF64Tan(input);
+      op = m->Float64Tan();
+      break;
     }
     case wasm::kExprF64Exp: {
-      return BuildF64Exp(input);
+      op = m->Float64Exp();
+      break;
     }
-    case wasm::kExprF64Log: {
-      return BuildF64Log(input);
-    }
-    // kExprI32ConvertI64:
+    case wasm::kExprF64Log:
+      op = m->Float64Log();
+      break;
     case wasm::kExprI32ConvertI64:
       op = m->TruncateInt64ToInt32();
       break;
-    // kExprI64SConvertI32:
     case wasm::kExprI64SConvertI32:
       op = m->ChangeInt32ToInt64();
       break;
-    // kExprI64UConvertI32:
     case wasm::kExprI64UConvertI32:
       op = m->ChangeUint32ToUint64();
       break;
-    // kExprF64ReinterpretI64:
     case wasm::kExprF64ReinterpretI64:
       op = m->BitcastInt64ToFloat64();
       break;
-    // kExprI64ReinterpretF64:
     case wasm::kExprI64ReinterpretF64:
       op = m->BitcastFloat64ToInt64();
       break;
-    // kExprI64Clz:
     case wasm::kExprI64Clz:
       op = m->Word64Clz();
       break;
-    // kExprI64Ctz:
     case wasm::kExprI64Ctz: {
       if (m->Word64Ctz().IsSupported()) {
         op = m->Word64Ctz().op();
@@ -809,7 +836,6 @@
         return BuildI64Ctz(input);
       }
     }
-    // kExprI64Popcnt:
     case wasm::kExprI64Popcnt: {
       if (m->Word64Popcnt().IsSupported()) {
         op = m->Word64Popcnt().op();
@@ -820,7 +846,6 @@
       }
       break;
     }
-    // kExprF32SConvertI64:
     case wasm::kExprI64Eqz:
       op = m->Word64Equal();
       return graph()->NewNode(op, input, jsgraph()->Int64Constant(0));
@@ -830,65 +855,64 @@
       }
       op = m->RoundInt64ToFloat32();
       break;
-    // kExprF32UConvertI64:
     case wasm::kExprF32UConvertI64:
       if (m->Is32()) {
         return BuildF32UConvertI64(input);
       }
       op = m->RoundUint64ToFloat32();
       break;
-    // kExprF64SConvertI64:
     case wasm::kExprF64SConvertI64:
       if (m->Is32()) {
         return BuildF64SConvertI64(input);
       }
       op = m->RoundInt64ToFloat64();
       break;
-    // kExprF64UConvertI64:
     case wasm::kExprF64UConvertI64:
       if (m->Is32()) {
         return BuildF64UConvertI64(input);
       }
       op = m->RoundUint64ToFloat64();
       break;
-// kExprI64SConvertF32:
-    case wasm::kExprI64SConvertF32: {
-      return BuildI64SConvertF32(input);
-    }
-    // kExprI64SConvertF64:
-    case wasm::kExprI64SConvertF64: {
-      return BuildI64SConvertF64(input);
-    }
-    // kExprI64UConvertF32:
-    case wasm::kExprI64UConvertF32: {
-      return BuildI64UConvertF32(input);
-    }
-    // kExprI64UConvertF64:
-    case wasm::kExprI64UConvertF64: {
-      return BuildI64UConvertF64(input);
-    }
+    case wasm::kExprI64SConvertF32:
+      return BuildI64SConvertF32(input, position);
+    case wasm::kExprI64SConvertF64:
+      return BuildI64SConvertF64(input, position);
+    case wasm::kExprI64UConvertF32:
+      return BuildI64UConvertF32(input, position);
+    case wasm::kExprI64UConvertF64:
+      return BuildI64UConvertF64(input, position);
+    case wasm::kExprI32AsmjsLoadMem8S:
+      return BuildAsmjsLoadMem(MachineType::Int8(), input);
+    case wasm::kExprI32AsmjsLoadMem8U:
+      return BuildAsmjsLoadMem(MachineType::Uint8(), input);
+    case wasm::kExprI32AsmjsLoadMem16S:
+      return BuildAsmjsLoadMem(MachineType::Int16(), input);
+    case wasm::kExprI32AsmjsLoadMem16U:
+      return BuildAsmjsLoadMem(MachineType::Uint16(), input);
+    case wasm::kExprI32AsmjsLoadMem:
+      return BuildAsmjsLoadMem(MachineType::Int32(), input);
+    case wasm::kExprF32AsmjsLoadMem:
+      return BuildAsmjsLoadMem(MachineType::Float32(), input);
+    case wasm::kExprF64AsmjsLoadMem:
+      return BuildAsmjsLoadMem(MachineType::Float64(), input);
     default:
       op = UnsupportedOpcode(opcode);
   }
   return graph()->NewNode(op, input);
 }
 
-
 Node* WasmGraphBuilder::Float32Constant(float value) {
   return jsgraph()->Float32Constant(value);
 }
 
-
 Node* WasmGraphBuilder::Float64Constant(double value) {
   return jsgraph()->Float64Constant(value);
 }
 
-
-Node* WasmGraphBuilder::Constant(Handle<Object> value) {
-  return jsgraph()->Constant(value);
+Node* WasmGraphBuilder::HeapConstant(Handle<HeapObject> value) {
+  return jsgraph()->HeapConstant(value);
 }
 
-
 Node* WasmGraphBuilder::Branch(Node* cond, Node** true_node,
                                Node** false_node) {
   DCHECK_NOT_NULL(cond);
@@ -900,24 +924,20 @@
   return branch;
 }
 
-
 Node* WasmGraphBuilder::Switch(unsigned count, Node* key) {
   return graph()->NewNode(jsgraph()->common()->Switch(count), key, *control_);
 }
 
-
 Node* WasmGraphBuilder::IfValue(int32_t value, Node* sw) {
   DCHECK_EQ(IrOpcode::kSwitch, sw->opcode());
   return graph()->NewNode(jsgraph()->common()->IfValue(value), sw);
 }
 
-
 Node* WasmGraphBuilder::IfDefault(Node* sw) {
   DCHECK_EQ(IrOpcode::kSwitch, sw->opcode());
   return graph()->NewNode(jsgraph()->common()->IfDefault(), sw);
 }
 
-
 Node* WasmGraphBuilder::Return(unsigned count, Node** vals) {
   DCHECK_NOT_NULL(*control_);
   DCHECK_NOT_NULL(*effect_);
@@ -937,12 +957,10 @@
   return ret;
 }
 
-
 Node* WasmGraphBuilder::ReturnVoid() { return Return(0, Buffer(0)); }
 
-
-Node* WasmGraphBuilder::Unreachable() {
-  trap_->Unreachable();
+Node* WasmGraphBuilder::Unreachable(wasm::WasmCodePosition position) {
+  trap_->Unreachable(position);
   return nullptr;
 }
 
@@ -987,7 +1005,6 @@
   return result;
 }
 
-
 Node* WasmGraphBuilder::BuildF64Neg(Node* input) {
 #if WASM_64
   Node* result =
@@ -1007,7 +1024,6 @@
 #endif
 }
 
-
 Node* WasmGraphBuilder::BuildF32CopySign(Node* left, Node* right) {
   Node* result = Unop(
       wasm::kExprF32ReinterpretI32,
@@ -1020,7 +1036,6 @@
   return result;
 }
 
-
 Node* WasmGraphBuilder::BuildF64CopySign(Node* left, Node* right) {
 #if WASM_64
   Node* result = Unop(
@@ -1049,7 +1064,6 @@
 #endif
 }
 
-
 Node* WasmGraphBuilder::BuildF32Min(Node* left, Node* right) {
   Diamond left_le_right(graph(), jsgraph()->common(),
                         Binop(wasm::kExprF32Le, left, right));
@@ -1070,7 +1084,6 @@
               Binop(wasm::kExprF32Mul, left, Float32Constant(1.0)))));
 }
 
-
 Node* WasmGraphBuilder::BuildF32Max(Node* left, Node* right) {
   Diamond left_ge_right(graph(), jsgraph()->common(),
                         Binop(wasm::kExprF32Ge, left, right));
@@ -1091,7 +1104,6 @@
               Binop(wasm::kExprF32Mul, left, Float32Constant(1.0)))));
 }
 
-
 Node* WasmGraphBuilder::BuildF64Min(Node* left, Node* right) {
   Diamond left_le_right(graph(), jsgraph()->common(),
                         Binop(wasm::kExprF64Le, left, right));
@@ -1112,7 +1124,6 @@
               Binop(wasm::kExprF64Mul, left, Float64Constant(1.0)))));
 }
 
-
 Node* WasmGraphBuilder::BuildF64Max(Node* left, Node* right) {
   Diamond left_ge_right(graph(), jsgraph()->common(),
                         Binop(wasm::kExprF64Ge, left, right));
@@ -1133,16 +1144,9 @@
               Binop(wasm::kExprF64Mul, left, Float64Constant(1.0)))));
 }
 
-
-Node* WasmGraphBuilder::BuildI32SConvertF32(Node* input) {
+Node* WasmGraphBuilder::BuildI32SConvertF32(Node* input,
+                                            wasm::WasmCodePosition position) {
   MachineOperatorBuilder* m = jsgraph()->machine();
-  if (module_ && module_->asm_js()) {
-    // asm.js must use the wacky JS semantics.
-    input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
-    return graph()->NewNode(
-        m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input);
-  }
-
   // Truncation of the input value is needed for the overflow check later.
   Node* trunc = Unop(wasm::kExprF32Trunc, input);
   Node* result = graph()->NewNode(m->TruncateFloat32ToInt32(), trunc);
@@ -1151,19 +1155,14 @@
   // truncated input value, then there has been an overflow and we trap.
   Node* check = Unop(wasm::kExprF32SConvertI32, result);
   Node* overflow = Binop(wasm::kExprF32Ne, trunc, check);
-  trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow);
+  trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow, position);
 
   return result;
 }
 
-
-Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input) {
+Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input,
+                                            wasm::WasmCodePosition position) {
   MachineOperatorBuilder* m = jsgraph()->machine();
-  if (module_ && module_->asm_js()) {
-    // asm.js must use the wacky JS semantics.
-    return graph()->NewNode(
-        m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input);
-  }
   // Truncation of the input value is needed for the overflow check later.
   Node* trunc = Unop(wasm::kExprF64Trunc, input);
   Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), trunc);
@@ -1172,21 +1171,14 @@
   // truncated input value, then there has been an overflow and we trap.
   Node* check = Unop(wasm::kExprF64SConvertI32, result);
   Node* overflow = Binop(wasm::kExprF64Ne, trunc, check);
-  trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow);
+  trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow, position);
 
   return result;
 }
 
-
-Node* WasmGraphBuilder::BuildI32UConvertF32(Node* input) {
+Node* WasmGraphBuilder::BuildI32UConvertF32(Node* input,
+                                            wasm::WasmCodePosition position) {
   MachineOperatorBuilder* m = jsgraph()->machine();
-  if (module_ && module_->asm_js()) {
-    // asm.js must use the wacky JS semantics.
-    input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
-    return graph()->NewNode(
-        m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input);
-  }
-
   // Truncation of the input value is needed for the overflow check later.
   Node* trunc = Unop(wasm::kExprF32Trunc, input);
   Node* result = graph()->NewNode(m->TruncateFloat32ToUint32(), trunc);
@@ -1195,19 +1187,14 @@
   // truncated input value, then there has been an overflow and we trap.
   Node* check = Unop(wasm::kExprF32UConvertI32, result);
   Node* overflow = Binop(wasm::kExprF32Ne, trunc, check);
-  trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow);
+  trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow, position);
 
   return result;
 }
 
-
-Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input) {
+Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input,
+                                            wasm::WasmCodePosition position) {
   MachineOperatorBuilder* m = jsgraph()->machine();
-  if (module_ && module_->asm_js()) {
-    // asm.js must use the wacky JS semantics.
-    return graph()->NewNode(
-        m->TruncateFloat64ToInt32(TruncationMode::kJavaScript), input);
-  }
   // Truncation of the input value is needed for the overflow check later.
   Node* trunc = Unop(wasm::kExprF64Trunc, input);
   Node* result = graph()->NewNode(m->TruncateFloat64ToUint32(), trunc);
@@ -1216,185 +1203,82 @@
   // truncated input value, then there has been an overflow and we trap.
   Node* check = Unop(wasm::kExprF64UConvertI32, result);
   Node* overflow = Binop(wasm::kExprF64Ne, trunc, check);
-  trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow);
+  trap_->AddTrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow, position);
 
   return result;
 }
 
+Node* WasmGraphBuilder::BuildI32AsmjsSConvertF32(Node* input) {
+  MachineOperatorBuilder* m = jsgraph()->machine();
+  // asm.js must use the wacky JS semantics.
+  input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
+  return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
+}
+
+Node* WasmGraphBuilder::BuildI32AsmjsSConvertF64(Node* input) {
+  MachineOperatorBuilder* m = jsgraph()->machine();
+  // asm.js must use the wacky JS semantics.
+  return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
+}
+
+Node* WasmGraphBuilder::BuildI32AsmjsUConvertF32(Node* input) {
+  MachineOperatorBuilder* m = jsgraph()->machine();
+  // asm.js must use the wacky JS semantics.
+  input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
+  return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
+}
+
+Node* WasmGraphBuilder::BuildI32AsmjsUConvertF64(Node* input) {
+  MachineOperatorBuilder* m = jsgraph()->machine();
+  // asm.js must use the wacky JS semantics.
+  return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
+}
+
+Node* WasmGraphBuilder::BuildBitCountingCall(Node* input, ExternalReference ref,
+                                             MachineRepresentation input_type) {
+  Node* stack_slot_param =
+      graph()->NewNode(jsgraph()->machine()->StackSlot(input_type));
+
+  const Operator* store_op = jsgraph()->machine()->Store(
+      StoreRepresentation(input_type, kNoWriteBarrier));
+  *effect_ =
+      graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0),
+                       input, *effect_, *control_);
+
+  MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 1);
+  sig_builder.AddReturn(MachineType::Int32());
+  sig_builder.AddParam(MachineType::Pointer());
+
+  Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
+  Node* args[] = {function, stack_slot_param};
+
+  return BuildCCall(sig_builder.Build(), args);
+}
 
 Node* WasmGraphBuilder::BuildI32Ctz(Node* input) {
-  //// Implement the following code as TF graph.
-  // value = value | (value << 1);
-  // value = value | (value << 2);
-  // value = value | (value << 4);
-  // value = value | (value << 8);
-  // value = value | (value << 16);
-  // return CountPopulation32(0xffffffff XOR value);
-
-  Node* result =
-      Binop(wasm::kExprI32Ior, input,
-            Binop(wasm::kExprI32Shl, input, jsgraph()->Int32Constant(1)));
-
-  result = Binop(wasm::kExprI32Ior, result,
-                 Binop(wasm::kExprI32Shl, result, jsgraph()->Int32Constant(2)));
-
-  result = Binop(wasm::kExprI32Ior, result,
-                 Binop(wasm::kExprI32Shl, result, jsgraph()->Int32Constant(4)));
-
-  result = Binop(wasm::kExprI32Ior, result,
-                 Binop(wasm::kExprI32Shl, result, jsgraph()->Int32Constant(8)));
-
-  result =
-      Binop(wasm::kExprI32Ior, result,
-            Binop(wasm::kExprI32Shl, result, jsgraph()->Int32Constant(16)));
-
-  result = BuildI32Popcnt(
-      Binop(wasm::kExprI32Xor, jsgraph()->Int32Constant(0xffffffff), result));
-
-  return result;
+  return BuildBitCountingCall(
+      input, ExternalReference::wasm_word32_ctz(jsgraph()->isolate()),
+      MachineRepresentation::kWord32);
 }
 
-
 Node* WasmGraphBuilder::BuildI64Ctz(Node* input) {
-  //// Implement the following code as TF graph.
-  // value = value | (value << 1);
-  // value = value | (value << 2);
-  // value = value | (value << 4);
-  // value = value | (value << 8);
-  // value = value | (value << 16);
-  // value = value | (value << 32);
-  // return CountPopulation64(0xffffffffffffffff XOR value);
-
-  Node* result =
-      Binop(wasm::kExprI64Ior, input,
-            Binop(wasm::kExprI64Shl, input, jsgraph()->Int64Constant(1)));
-
-  result = Binop(wasm::kExprI64Ior, result,
-                 Binop(wasm::kExprI64Shl, result, jsgraph()->Int64Constant(2)));
-
-  result = Binop(wasm::kExprI64Ior, result,
-                 Binop(wasm::kExprI64Shl, result, jsgraph()->Int64Constant(4)));
-
-  result = Binop(wasm::kExprI64Ior, result,
-                 Binop(wasm::kExprI64Shl, result, jsgraph()->Int64Constant(8)));
-
-  result =
-      Binop(wasm::kExprI64Ior, result,
-            Binop(wasm::kExprI64Shl, result, jsgraph()->Int64Constant(16)));
-
-  result =
-      Binop(wasm::kExprI64Ior, result,
-            Binop(wasm::kExprI64Shl, result, jsgraph()->Int64Constant(32)));
-
-  result = BuildI64Popcnt(Binop(
-      wasm::kExprI64Xor, jsgraph()->Int64Constant(0xffffffffffffffff), result));
-
-  return result;
+  return Unop(wasm::kExprI64UConvertI32,
+              BuildBitCountingCall(input, ExternalReference::wasm_word64_ctz(
+                                              jsgraph()->isolate()),
+                                   MachineRepresentation::kWord64));
 }
 
-
 Node* WasmGraphBuilder::BuildI32Popcnt(Node* input) {
-  //// Implement the following code as a TF graph.
-  // value = ((value >> 1) & 0x55555555) + (value & 0x55555555);
-  // value = ((value >> 2) & 0x33333333) + (value & 0x33333333);
-  // value = ((value >> 4) & 0x0f0f0f0f) + (value & 0x0f0f0f0f);
-  // value = ((value >> 8) & 0x00ff00ff) + (value & 0x00ff00ff);
-  // value = ((value >> 16) & 0x0000ffff) + (value & 0x0000ffff);
-
-  Node* result = Binop(
-      wasm::kExprI32Add,
-      Binop(wasm::kExprI32And,
-            Binop(wasm::kExprI32ShrU, input, jsgraph()->Int32Constant(1)),
-            jsgraph()->Int32Constant(0x55555555)),
-      Binop(wasm::kExprI32And, input, jsgraph()->Int32Constant(0x55555555)));
-
-  result = Binop(
-      wasm::kExprI32Add,
-      Binop(wasm::kExprI32And,
-            Binop(wasm::kExprI32ShrU, result, jsgraph()->Int32Constant(2)),
-            jsgraph()->Int32Constant(0x33333333)),
-      Binop(wasm::kExprI32And, result, jsgraph()->Int32Constant(0x33333333)));
-
-  result = Binop(
-      wasm::kExprI32Add,
-      Binop(wasm::kExprI32And,
-            Binop(wasm::kExprI32ShrU, result, jsgraph()->Int32Constant(4)),
-            jsgraph()->Int32Constant(0x0f0f0f0f)),
-      Binop(wasm::kExprI32And, result, jsgraph()->Int32Constant(0x0f0f0f0f)));
-
-  result = Binop(
-      wasm::kExprI32Add,
-      Binop(wasm::kExprI32And,
-            Binop(wasm::kExprI32ShrU, result, jsgraph()->Int32Constant(8)),
-            jsgraph()->Int32Constant(0x00ff00ff)),
-      Binop(wasm::kExprI32And, result, jsgraph()->Int32Constant(0x00ff00ff)));
-
-  result = Binop(
-      wasm::kExprI32Add,
-      Binop(wasm::kExprI32And,
-            Binop(wasm::kExprI32ShrU, result, jsgraph()->Int32Constant(16)),
-            jsgraph()->Int32Constant(0x0000ffff)),
-      Binop(wasm::kExprI32And, result, jsgraph()->Int32Constant(0x0000ffff)));
-
-  return result;
+  return BuildBitCountingCall(
+      input, ExternalReference::wasm_word32_popcnt(jsgraph()->isolate()),
+      MachineRepresentation::kWord32);
 }
 
-
 Node* WasmGraphBuilder::BuildI64Popcnt(Node* input) {
-  //// Implement the following code as a TF graph.
-  // value = ((value >> 1) & 0x5555555555555555) + (value & 0x5555555555555555);
-  // value = ((value >> 2) & 0x3333333333333333) + (value & 0x3333333333333333);
-  // value = ((value >> 4) & 0x0f0f0f0f0f0f0f0f) + (value & 0x0f0f0f0f0f0f0f0f);
-  // value = ((value >> 8) & 0x00ff00ff00ff00ff) + (value & 0x00ff00ff00ff00ff);
-  // value = ((value >> 16) & 0x0000ffff0000ffff) + (value &
-  // 0x0000ffff0000ffff);
-  // value = ((value >> 32) & 0x00000000ffffffff) + (value &
-  // 0x00000000ffffffff);
-
-  Node* result =
-      Binop(wasm::kExprI64Add,
-            Binop(wasm::kExprI64And,
-                  Binop(wasm::kExprI64ShrU, input, jsgraph()->Int64Constant(1)),
-                  jsgraph()->Int64Constant(0x5555555555555555)),
-            Binop(wasm::kExprI64And, input,
-                  jsgraph()->Int64Constant(0x5555555555555555)));
-
-  result = Binop(wasm::kExprI64Add,
-                 Binop(wasm::kExprI64And, Binop(wasm::kExprI64ShrU, result,
-                                                jsgraph()->Int64Constant(2)),
-                       jsgraph()->Int64Constant(0x3333333333333333)),
-                 Binop(wasm::kExprI64And, result,
-                       jsgraph()->Int64Constant(0x3333333333333333)));
-
-  result = Binop(wasm::kExprI64Add,
-                 Binop(wasm::kExprI64And, Binop(wasm::kExprI64ShrU, result,
-                                                jsgraph()->Int64Constant(4)),
-                       jsgraph()->Int64Constant(0x0f0f0f0f0f0f0f0f)),
-                 Binop(wasm::kExprI64And, result,
-                       jsgraph()->Int64Constant(0x0f0f0f0f0f0f0f0f)));
-
-  result = Binop(wasm::kExprI64Add,
-                 Binop(wasm::kExprI64And, Binop(wasm::kExprI64ShrU, result,
-                                                jsgraph()->Int64Constant(8)),
-                       jsgraph()->Int64Constant(0x00ff00ff00ff00ff)),
-                 Binop(wasm::kExprI64And, result,
-                       jsgraph()->Int64Constant(0x00ff00ff00ff00ff)));
-
-  result = Binop(wasm::kExprI64Add,
-                 Binop(wasm::kExprI64And, Binop(wasm::kExprI64ShrU, result,
-                                                jsgraph()->Int64Constant(16)),
-                       jsgraph()->Int64Constant(0x0000ffff0000ffff)),
-                 Binop(wasm::kExprI64And, result,
-                       jsgraph()->Int64Constant(0x0000ffff0000ffff)));
-
-  result = Binop(wasm::kExprI64Add,
-                 Binop(wasm::kExprI64And, Binop(wasm::kExprI64ShrU, result,
-                                                jsgraph()->Int64Constant(32)),
-                       jsgraph()->Int64Constant(0x00000000ffffffff)),
-                 Binop(wasm::kExprI64And, result,
-                       jsgraph()->Int64Constant(0x00000000ffffffff)));
-
-  return result;
+  return Unop(wasm::kExprI64UConvertI32,
+              BuildBitCountingCall(input, ExternalReference::wasm_word64_popcnt(
+                                              jsgraph()->isolate()),
+                                   MachineRepresentation::kWord64));
 }
 
 Node* WasmGraphBuilder::BuildF32Trunc(Node* input) {
@@ -1468,55 +1352,6 @@
   return BuildCFuncInstruction(ref, type, input);
 }
 
-Node* WasmGraphBuilder::BuildF64Atan(Node* input) {
-  MachineType type = MachineType::Float64();
-  ExternalReference ref =
-      ExternalReference::f64_atan_wrapper_function(jsgraph()->isolate());
-  return BuildCFuncInstruction(ref, type, input);
-}
-
-Node* WasmGraphBuilder::BuildF64Cos(Node* input) {
-  MachineType type = MachineType::Float64();
-  ExternalReference ref =
-      ExternalReference::f64_cos_wrapper_function(jsgraph()->isolate());
-  return BuildCFuncInstruction(ref, type, input);
-}
-
-Node* WasmGraphBuilder::BuildF64Sin(Node* input) {
-  MachineType type = MachineType::Float64();
-  ExternalReference ref =
-      ExternalReference::f64_sin_wrapper_function(jsgraph()->isolate());
-  return BuildCFuncInstruction(ref, type, input);
-}
-
-Node* WasmGraphBuilder::BuildF64Tan(Node* input) {
-  MachineType type = MachineType::Float64();
-  ExternalReference ref =
-      ExternalReference::f64_tan_wrapper_function(jsgraph()->isolate());
-  return BuildCFuncInstruction(ref, type, input);
-}
-
-Node* WasmGraphBuilder::BuildF64Exp(Node* input) {
-  MachineType type = MachineType::Float64();
-  ExternalReference ref =
-      ExternalReference::f64_exp_wrapper_function(jsgraph()->isolate());
-  return BuildCFuncInstruction(ref, type, input);
-}
-
-Node* WasmGraphBuilder::BuildF64Log(Node* input) {
-  MachineType type = MachineType::Float64();
-  ExternalReference ref =
-      ExternalReference::f64_log_wrapper_function(jsgraph()->isolate());
-  return BuildCFuncInstruction(ref, type, input);
-}
-
-Node* WasmGraphBuilder::BuildF64Atan2(Node* left, Node* right) {
-  MachineType type = MachineType::Float64();
-  ExternalReference ref =
-      ExternalReference::f64_atan2_wrapper_function(jsgraph()->isolate());
-  return BuildCFuncInstruction(ref, type, left, right);
-}
-
 Node* WasmGraphBuilder::BuildF64Pow(Node* left, Node* right) {
   MachineType type = MachineType::Float64();
   ExternalReference ref =
@@ -1635,66 +1470,74 @@
   return load;
 }
 
-Node* WasmGraphBuilder::BuildI64SConvertF32(Node* input) {
+Node* WasmGraphBuilder::BuildI64SConvertF32(Node* input,
+                                            wasm::WasmCodePosition position) {
   if (jsgraph()->machine()->Is32()) {
     return BuildFloatToIntConversionInstruction(
         input, ExternalReference::wasm_float32_to_int64(jsgraph()->isolate()),
-        MachineRepresentation::kFloat32, MachineType::Int64());
+        MachineRepresentation::kFloat32, MachineType::Int64(), position);
   } else {
     Node* trunc = graph()->NewNode(
         jsgraph()->machine()->TryTruncateFloat32ToInt64(), input);
-    Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc);
-    Node* overflow =
-        graph()->NewNode(jsgraph()->common()->Projection(1), trunc);
-    trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow);
+    Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc,
+                                    graph()->start());
+    Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc,
+                                      graph()->start());
+    trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position);
     return result;
   }
 }
 
-Node* WasmGraphBuilder::BuildI64UConvertF32(Node* input) {
+Node* WasmGraphBuilder::BuildI64UConvertF32(Node* input,
+                                            wasm::WasmCodePosition position) {
   if (jsgraph()->machine()->Is32()) {
     return BuildFloatToIntConversionInstruction(
         input, ExternalReference::wasm_float32_to_uint64(jsgraph()->isolate()),
-        MachineRepresentation::kFloat32, MachineType::Int64());
+        MachineRepresentation::kFloat32, MachineType::Int64(), position);
   } else {
     Node* trunc = graph()->NewNode(
         jsgraph()->machine()->TryTruncateFloat32ToUint64(), input);
-    Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc);
-    Node* overflow =
-        graph()->NewNode(jsgraph()->common()->Projection(1), trunc);
-    trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow);
+    Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc,
+                                    graph()->start());
+    Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc,
+                                      graph()->start());
+    trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position);
     return result;
   }
 }
 
-Node* WasmGraphBuilder::BuildI64SConvertF64(Node* input) {
+Node* WasmGraphBuilder::BuildI64SConvertF64(Node* input,
+                                            wasm::WasmCodePosition position) {
   if (jsgraph()->machine()->Is32()) {
     return BuildFloatToIntConversionInstruction(
         input, ExternalReference::wasm_float64_to_int64(jsgraph()->isolate()),
-        MachineRepresentation::kFloat64, MachineType::Int64());
+        MachineRepresentation::kFloat64, MachineType::Int64(), position);
   } else {
     Node* trunc = graph()->NewNode(
         jsgraph()->machine()->TryTruncateFloat64ToInt64(), input);
-    Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc);
-    Node* overflow =
-        graph()->NewNode(jsgraph()->common()->Projection(1), trunc);
-    trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow);
+    Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc,
+                                    graph()->start());
+    Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc,
+                                      graph()->start());
+    trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position);
     return result;
   }
 }
 
-Node* WasmGraphBuilder::BuildI64UConvertF64(Node* input) {
+Node* WasmGraphBuilder::BuildI64UConvertF64(Node* input,
+                                            wasm::WasmCodePosition position) {
   if (jsgraph()->machine()->Is32()) {
     return BuildFloatToIntConversionInstruction(
         input, ExternalReference::wasm_float64_to_uint64(jsgraph()->isolate()),
-        MachineRepresentation::kFloat64, MachineType::Int64());
+        MachineRepresentation::kFloat64, MachineType::Int64(), position);
   } else {
     Node* trunc = graph()->NewNode(
         jsgraph()->machine()->TryTruncateFloat64ToUint64(), input);
-    Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc);
-    Node* overflow =
-        graph()->NewNode(jsgraph()->common()->Projection(1), trunc);
-    trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow);
+    Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc,
+                                    graph()->start());
+    Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc,
+                                      graph()->start());
+    trap_->ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position);
     return result;
   }
 }
@@ -1702,7 +1545,7 @@
 Node* WasmGraphBuilder::BuildFloatToIntConversionInstruction(
     Node* input, ExternalReference ref,
     MachineRepresentation parameter_representation,
-    const MachineType result_type) {
+    const MachineType result_type, wasm::WasmCodePosition position) {
   Node* stack_slot_param = graph()->NewNode(
       jsgraph()->machine()->StackSlot(parameter_representation));
   Node* stack_slot_result = graph()->NewNode(
@@ -1719,7 +1562,7 @@
   Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
   Node* args[] = {function, stack_slot_param, stack_slot_result};
   trap_->ZeroCheck32(wasm::kTrapFloatUnrepresentable,
-                     BuildCCall(sig_builder.Build(), args));
+                     BuildCCall(sig_builder.Build(), args), position);
   const Operator* load_op = jsgraph()->machine()->Load(result_type);
   Node* load =
       graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0),
@@ -1728,37 +1571,10 @@
   return load;
 }
 
-Node* WasmGraphBuilder::BuildI32DivS(Node* left, Node* right) {
+Node* WasmGraphBuilder::BuildI32DivS(Node* left, Node* right,
+                                     wasm::WasmCodePosition position) {
   MachineOperatorBuilder* m = jsgraph()->machine();
-  if (module_ && module_->asm_js()) {
-    // asm.js semantics return 0 on divide or mod by zero.
-    if (m->Int32DivIsSafe()) {
-      // The hardware instruction does the right thing (e.g. arm).
-      return graph()->NewNode(m->Int32Div(), left, right, graph()->start());
-    }
-
-    // Check denominator for zero.
-    Diamond z(
-        graph(), jsgraph()->common(),
-        graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
-        BranchHint::kFalse);
-
-    // Check numerator for -1. (avoid minint / -1 case).
-    Diamond n(
-        graph(), jsgraph()->common(),
-        graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)),
-        BranchHint::kFalse);
-
-    Node* div = graph()->NewNode(m->Int32Div(), left, right, z.if_false);
-    Node* neg =
-        graph()->NewNode(m->Int32Sub(), jsgraph()->Int32Constant(0), left);
-
-    return n.Phi(MachineRepresentation::kWord32, neg,
-                 z.Phi(MachineRepresentation::kWord32,
-                       jsgraph()->Int32Constant(0), div));
-  }
-
-  trap_->ZeroCheck32(wasm::kTrapDivByZero, right);
+  trap_->ZeroCheck32(wasm::kTrapDivByZero, right, position);
   Node* before = *control_;
   Node* denom_is_m1;
   Node* denom_is_not_m1;
@@ -1766,7 +1582,7 @@
       graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)),
       &denom_is_m1, &denom_is_not_m1);
   *control_ = denom_is_m1;
-  trap_->TrapIfEq32(wasm::kTrapDivUnrepresentable, left, kMinInt);
+  trap_->TrapIfEq32(wasm::kTrapDivUnrepresentable, left, kMinInt, position);
   if (*control_ != denom_is_m1) {
     *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1,
                                  *control_);
@@ -1776,30 +1592,11 @@
   return graph()->NewNode(m->Int32Div(), left, right, *control_);
 }
 
-Node* WasmGraphBuilder::BuildI32RemS(Node* left, Node* right) {
+Node* WasmGraphBuilder::BuildI32RemS(Node* left, Node* right,
+                                     wasm::WasmCodePosition position) {
   MachineOperatorBuilder* m = jsgraph()->machine();
-  if (module_ && module_->asm_js()) {
-    // asm.js semantics return 0 on divide or mod by zero.
-    // Explicit check for x % 0.
-    Diamond z(
-        graph(), jsgraph()->common(),
-        graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
-        BranchHint::kFalse);
 
-    // Explicit check for x % -1.
-    Diamond d(
-        graph(), jsgraph()->common(),
-        graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)),
-        BranchHint::kFalse);
-    d.Chain(z.if_false);
-
-    return z.Phi(
-        MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
-        d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
-              graph()->NewNode(m->Int32Mod(), left, right, d.if_false)));
-  }
-
-  trap_->ZeroCheck32(wasm::kTrapRemByZero, right);
+  trap_->ZeroCheck32(wasm::kTrapRemByZero, right, position);
 
   Diamond d(
       graph(), jsgraph()->common(),
@@ -1811,56 +1608,115 @@
                graph()->NewNode(m->Int32Mod(), left, right, d.if_false));
 }
 
-Node* WasmGraphBuilder::BuildI32DivU(Node* left, Node* right) {
+Node* WasmGraphBuilder::BuildI32DivU(Node* left, Node* right,
+                                     wasm::WasmCodePosition position) {
   MachineOperatorBuilder* m = jsgraph()->machine();
-  if (module_ && module_->asm_js()) {
-    // asm.js semantics return 0 on divide or mod by zero.
-    if (m->Uint32DivIsSafe()) {
-      // The hardware instruction does the right thing (e.g. arm).
-      return graph()->NewNode(m->Uint32Div(), left, right, graph()->start());
-    }
-
-    // Explicit check for x % 0.
-    Diamond z(
-        graph(), jsgraph()->common(),
-        graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
-        BranchHint::kFalse);
-
-    return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
-                 graph()->NewNode(jsgraph()->machine()->Uint32Div(), left,
-                                  right, z.if_false));
-  }
-  return graph()->NewNode(m->Uint32Div(), left, right,
-                          trap_->ZeroCheck32(wasm::kTrapDivByZero, right));
+  return graph()->NewNode(
+      m->Uint32Div(), left, right,
+      trap_->ZeroCheck32(wasm::kTrapDivByZero, right, position));
 }
 
-Node* WasmGraphBuilder::BuildI32RemU(Node* left, Node* right) {
+Node* WasmGraphBuilder::BuildI32RemU(Node* left, Node* right,
+                                     wasm::WasmCodePosition position) {
   MachineOperatorBuilder* m = jsgraph()->machine();
-  if (module_ && module_->asm_js()) {
-    // asm.js semantics return 0 on divide or mod by zero.
-    // Explicit check for x % 0.
-    Diamond z(
-        graph(), jsgraph()->common(),
-        graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
-        BranchHint::kFalse);
-
-    Node* rem = graph()->NewNode(jsgraph()->machine()->Uint32Mod(), left, right,
-                                 z.if_false);
-    return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
-                 rem);
-  }
-
-  return graph()->NewNode(m->Uint32Mod(), left, right,
-                          trap_->ZeroCheck32(wasm::kTrapRemByZero, right));
+  return graph()->NewNode(
+      m->Uint32Mod(), left, right,
+      trap_->ZeroCheck32(wasm::kTrapRemByZero, right, position));
 }
 
-Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right) {
+Node* WasmGraphBuilder::BuildI32AsmjsDivS(Node* left, Node* right) {
+  MachineOperatorBuilder* m = jsgraph()->machine();
+  // asm.js semantics return 0 on divide or mod by zero.
+  if (m->Int32DivIsSafe()) {
+    // The hardware instruction does the right thing (e.g. arm).
+    return graph()->NewNode(m->Int32Div(), left, right, graph()->start());
+  }
+
+  // Check denominator for zero.
+  Diamond z(
+      graph(), jsgraph()->common(),
+      graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
+      BranchHint::kFalse);
+
+  // Check numerator for -1. (avoid minint / -1 case).
+  Diamond n(
+      graph(), jsgraph()->common(),
+      graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)),
+      BranchHint::kFalse);
+
+  Node* div = graph()->NewNode(m->Int32Div(), left, right, z.if_false);
+  Node* neg =
+      graph()->NewNode(m->Int32Sub(), jsgraph()->Int32Constant(0), left);
+
+  return n.Phi(
+      MachineRepresentation::kWord32, neg,
+      z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), div));
+}
+
+Node* WasmGraphBuilder::BuildI32AsmjsRemS(Node* left, Node* right) {
+  MachineOperatorBuilder* m = jsgraph()->machine();
+  // asm.js semantics return 0 on divide or mod by zero.
+  // Explicit check for x % 0.
+  Diamond z(
+      graph(), jsgraph()->common(),
+      graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
+      BranchHint::kFalse);
+
+  // Explicit check for x % -1.
+  Diamond d(
+      graph(), jsgraph()->common(),
+      graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)),
+      BranchHint::kFalse);
+  d.Chain(z.if_false);
+
+  return z.Phi(
+      MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
+      d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
+            graph()->NewNode(m->Int32Mod(), left, right, d.if_false)));
+}
+
+Node* WasmGraphBuilder::BuildI32AsmjsDivU(Node* left, Node* right) {
+  MachineOperatorBuilder* m = jsgraph()->machine();
+  // asm.js semantics return 0 on divide or mod by zero.
+  if (m->Uint32DivIsSafe()) {
+    // The hardware instruction does the right thing (e.g. arm).
+    return graph()->NewNode(m->Uint32Div(), left, right, graph()->start());
+  }
+
+  // Explicit check for x % 0.
+  Diamond z(
+      graph(), jsgraph()->common(),
+      graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
+      BranchHint::kFalse);
+
+  return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
+               graph()->NewNode(jsgraph()->machine()->Uint32Div(), left, right,
+                                z.if_false));
+}
+
+Node* WasmGraphBuilder::BuildI32AsmjsRemU(Node* left, Node* right) {
+  MachineOperatorBuilder* m = jsgraph()->machine();
+  // asm.js semantics return 0 on divide or mod by zero.
+  // Explicit check for x % 0.
+  Diamond z(
+      graph(), jsgraph()->common(),
+      graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
+      BranchHint::kFalse);
+
+  Node* rem = graph()->NewNode(jsgraph()->machine()->Uint32Mod(), left, right,
+                               z.if_false);
+  return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
+               rem);
+}
+
+Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right,
+                                     wasm::WasmCodePosition position) {
   if (jsgraph()->machine()->Is32()) {
     return BuildDiv64Call(
         left, right, ExternalReference::wasm_int64_div(jsgraph()->isolate()),
-        MachineType::Int64(), wasm::kTrapDivByZero);
+        MachineType::Int64(), wasm::kTrapDivByZero, position);
   }
-  trap_->ZeroCheck64(wasm::kTrapDivByZero, right);
+  trap_->ZeroCheck64(wasm::kTrapDivByZero, right, position);
   Node* before = *control_;
   Node* denom_is_m1;
   Node* denom_is_not_m1;
@@ -1869,7 +1725,7 @@
          &denom_is_m1, &denom_is_not_m1);
   *control_ = denom_is_m1;
   trap_->TrapIfEq64(wasm::kTrapDivUnrepresentable, left,
-                    std::numeric_limits<int64_t>::min());
+                    std::numeric_limits<int64_t>::min(), position);
   if (*control_ != denom_is_m1) {
     *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1,
                                  *control_);
@@ -1880,13 +1736,14 @@
                           *control_);
 }
 
-Node* WasmGraphBuilder::BuildI64RemS(Node* left, Node* right) {
+Node* WasmGraphBuilder::BuildI64RemS(Node* left, Node* right,
+                                     wasm::WasmCodePosition position) {
   if (jsgraph()->machine()->Is32()) {
     return BuildDiv64Call(
         left, right, ExternalReference::wasm_int64_mod(jsgraph()->isolate()),
-        MachineType::Int64(), wasm::kTrapRemByZero);
+        MachineType::Int64(), wasm::kTrapRemByZero, position);
   }
-  trap_->ZeroCheck64(wasm::kTrapRemByZero, right);
+  trap_->ZeroCheck64(wasm::kTrapRemByZero, right, position);
   Diamond d(jsgraph()->graph(), jsgraph()->common(),
             graph()->NewNode(jsgraph()->machine()->Word64Equal(), right,
                              jsgraph()->Int64Constant(-1)));
@@ -1898,28 +1755,33 @@
                rem);
 }
 
-Node* WasmGraphBuilder::BuildI64DivU(Node* left, Node* right) {
+Node* WasmGraphBuilder::BuildI64DivU(Node* left, Node* right,
+                                     wasm::WasmCodePosition position) {
   if (jsgraph()->machine()->Is32()) {
     return BuildDiv64Call(
         left, right, ExternalReference::wasm_uint64_div(jsgraph()->isolate()),
-        MachineType::Int64(), wasm::kTrapDivByZero);
+        MachineType::Int64(), wasm::kTrapDivByZero, position);
   }
-  return graph()->NewNode(jsgraph()->machine()->Uint64Div(), left, right,
-                          trap_->ZeroCheck64(wasm::kTrapDivByZero, right));
+  return graph()->NewNode(
+      jsgraph()->machine()->Uint64Div(), left, right,
+      trap_->ZeroCheck64(wasm::kTrapDivByZero, right, position));
 }
-Node* WasmGraphBuilder::BuildI64RemU(Node* left, Node* right) {
+Node* WasmGraphBuilder::BuildI64RemU(Node* left, Node* right,
+                                     wasm::WasmCodePosition position) {
   if (jsgraph()->machine()->Is32()) {
     return BuildDiv64Call(
         left, right, ExternalReference::wasm_uint64_mod(jsgraph()->isolate()),
-        MachineType::Int64(), wasm::kTrapRemByZero);
+        MachineType::Int64(), wasm::kTrapRemByZero, position);
   }
-  return graph()->NewNode(jsgraph()->machine()->Uint64Mod(), left, right,
-                          trap_->ZeroCheck64(wasm::kTrapRemByZero, right));
+  return graph()->NewNode(
+      jsgraph()->machine()->Uint64Mod(), left, right,
+      trap_->ZeroCheck64(wasm::kTrapRemByZero, right, position));
 }
 
 Node* WasmGraphBuilder::BuildDiv64Call(Node* left, Node* right,
                                        ExternalReference ref,
-                                       MachineType result_type, int trap_zero) {
+                                       MachineType result_type, int trap_zero,
+                                       wasm::WasmCodePosition position) {
   Node* stack_slot_dst = graph()->NewNode(
       jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64));
   Node* stack_slot_src = graph()->NewNode(
@@ -1946,8 +1808,8 @@
 
   // TODO(wasm): This can get simpler if we have a specialized runtime call to
   // throw WASM exceptions by trap code instead of by string.
-  trap_->ZeroCheck32(static_cast<wasm::TrapReason>(trap_zero), call);
-  trap_->TrapIfEq32(wasm::kTrapDivUnrepresentable, call, -1);
+  trap_->ZeroCheck32(static_cast<wasm::TrapReason>(trap_zero), call, position);
+  trap_->TrapIfEq32(wasm::kTrapDivUnrepresentable, call, -1, position);
   const Operator* load_op = jsgraph()->machine()->Load(result_type);
   Node* load =
       graph()->NewNode(load_op, stack_slot_dst, jsgraph()->Int32Constant(0),
@@ -1977,7 +1839,8 @@
   return call;
 }
 
-Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args) {
+Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args,
+                                      wasm::WasmCodePosition position) {
   const size_t params = sig->parameter_count();
   const size_t extra = 2;  // effect and control inputs.
   const size_t count = 1 + params + extra;
@@ -1993,32 +1856,36 @@
       wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig);
   const Operator* op = jsgraph()->common()->Call(descriptor);
   Node* call = graph()->NewNode(op, static_cast<int>(count), args);
+  SetSourcePosition(call, position);
 
   *effect_ = call;
   return call;
 }
 
-Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args) {
+Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args,
+                                   wasm::WasmCodePosition position) {
   DCHECK_NULL(args[0]);
 
   // Add code object as constant.
-  args[0] = Constant(module_->GetFunctionCode(index));
+  args[0] = HeapConstant(module_->GetCodeOrPlaceholder(index));
   wasm::FunctionSig* sig = module_->GetFunctionSignature(index);
 
-  return BuildWasmCall(sig, args);
+  return BuildWasmCall(sig, args, position);
 }
 
-Node* WasmGraphBuilder::CallImport(uint32_t index, Node** args) {
+Node* WasmGraphBuilder::CallImport(uint32_t index, Node** args,
+                                   wasm::WasmCodePosition position) {
   DCHECK_NULL(args[0]);
 
   // Add code object as constant.
-  args[0] = Constant(module_->GetImportCode(index));
+  args[0] = HeapConstant(module_->GetImportCode(index));
   wasm::FunctionSig* sig = module_->GetImportSignature(index);
 
-  return BuildWasmCall(sig, args);
+  return BuildWasmCall(sig, args, position);
 }
 
-Node* WasmGraphBuilder::CallIndirect(uint32_t index, Node** args) {
+Node* WasmGraphBuilder::CallIndirect(uint32_t index, Node** args,
+                                     wasm::WasmCodePosition position) {
   DCHECK_NOT_NULL(args[0]);
   DCHECK(module_ && module_->instance);
 
@@ -2033,10 +1900,10 @@
     // Bounds check against the table size.
     Node* size = Int32Constant(static_cast<int>(table_size));
     Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size);
-    trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, in_bounds);
+    trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, in_bounds, position);
   } else {
     // No function table. Generate a trap and return a constant.
-    trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0));
+    trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0), position);
     return trap_->GetTrapValue(module_->GetSignature(index));
   }
   Node* table = FunctionTable();
@@ -2054,9 +1921,10 @@
                                           Int32Constant(kPointerSizeLog2)),
                          Int32Constant(fixed_offset)),
         *effect_, *control_);
-    Node* sig_match = graph()->NewNode(machine->WordEqual(), load_sig,
-                                       jsgraph()->SmiConstant(index));
-    trap_->AddTrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match);
+    Node* sig_match =
+        graph()->NewNode(machine->Word32Equal(),
+                         BuildChangeSmiToInt32(load_sig), Int32Constant(index));
+    trap_->AddTrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match, position);
   }
 
   // Load code object from the table.
@@ -2071,77 +1939,7 @@
 
   args[0] = load_code;
   wasm::FunctionSig* sig = module_->GetSignature(index);
-  return BuildWasmCall(sig, args);
-}
-
-
-Node* WasmGraphBuilder::ToJS(Node* node, Node* context, wasm::LocalType type) {
-  SimplifiedOperatorBuilder simplified(jsgraph()->zone());
-  switch (type) {
-    case wasm::kAstI32:
-      return graph()->NewNode(simplified.ChangeInt32ToTagged(), node);
-    case wasm::kAstI64:
-      // TODO(titzer): i64->JS has no good solution right now. Using lower 32
-      // bits.
-      node =
-          graph()->NewNode(jsgraph()->machine()->TruncateInt64ToInt32(), node);
-      return graph()->NewNode(simplified.ChangeInt32ToTagged(), node);
-    case wasm::kAstF32:
-      node = graph()->NewNode(jsgraph()->machine()->ChangeFloat32ToFloat64(),
-                              node);
-      return graph()->NewNode(simplified.ChangeFloat64ToTagged(), node);
-    case wasm::kAstF64:
-      return graph()->NewNode(simplified.ChangeFloat64ToTagged(), node);
-    case wasm::kAstStmt:
-      return jsgraph()->UndefinedConstant();
-    default:
-      UNREACHABLE();
-      return nullptr;
-  }
-}
-
-
-Node* WasmGraphBuilder::FromJS(Node* node, Node* context,
-                               wasm::LocalType type) {
-  // Do a JavaScript ToNumber.
-  Node* num =
-      graph()->NewNode(jsgraph()->javascript()->ToNumber(), node, context,
-                       jsgraph()->EmptyFrameState(), *effect_, *control_);
-  *control_ = num;
-  *effect_ = num;
-
-  // Change representation.
-  SimplifiedOperatorBuilder simplified(jsgraph()->zone());
-  num = graph()->NewNode(simplified.ChangeTaggedToFloat64(), num);
-
-  switch (type) {
-    case wasm::kAstI32: {
-      num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToInt32(
-                                 TruncationMode::kJavaScript),
-                             num);
-      break;
-    }
-    case wasm::kAstI64:
-      // TODO(titzer): JS->i64 has no good solution right now. Using 32 bits.
-      num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToInt32(
-                                 TruncationMode::kJavaScript),
-                             num);
-      num = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), num);
-      break;
-    case wasm::kAstF32:
-      num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToFloat32(),
-                             num);
-      break;
-    case wasm::kAstF64:
-      break;
-    case wasm::kAstStmt:
-      num = jsgraph()->Int32Constant(0);
-      break;
-    default:
-      UNREACHABLE();
-      return nullptr;
-  }
-  return num;
+  return BuildWasmCall(sig, args, position);
 }
 
 Node* WasmGraphBuilder::BuildI32Rol(Node* left, Node* right) {
@@ -2174,31 +1972,407 @@
   return Unop(wasm::kExprI32Eqz, node);
 }
 
+Node* WasmGraphBuilder::BuildChangeInt32ToTagged(Node* value) {
+  MachineOperatorBuilder* machine = jsgraph()->machine();
+  CommonOperatorBuilder* common = jsgraph()->common();
+
+  if (machine->Is64()) {
+    return BuildChangeInt32ToSmi(value);
+  }
+
+  Node* add = graph()->NewNode(machine->Int32AddWithOverflow(), value, value,
+                               graph()->start());
+
+  Node* ovf = graph()->NewNode(common->Projection(1), add, graph()->start());
+  Node* branch = graph()->NewNode(common->Branch(BranchHint::kFalse), ovf,
+                                  graph()->start());
+
+  Node* if_true = graph()->NewNode(common->IfTrue(), branch);
+  Node* vtrue = BuildAllocateHeapNumberWithValue(
+      graph()->NewNode(machine->ChangeInt32ToFloat64(), value), if_true);
+
+  Node* if_false = graph()->NewNode(common->IfFalse(), branch);
+  Node* vfalse = graph()->NewNode(common->Projection(0), add, if_false);
+
+  Node* merge = graph()->NewNode(common->Merge(2), if_true, if_false);
+  Node* phi = graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2),
+                               vtrue, vfalse, merge);
+  return phi;
+}
+
+Node* WasmGraphBuilder::BuildChangeFloat64ToTagged(Node* value) {
+  MachineOperatorBuilder* machine = jsgraph()->machine();
+  CommonOperatorBuilder* common = jsgraph()->common();
+
+  Node* value32 = graph()->NewNode(machine->RoundFloat64ToInt32(), value);
+  Node* check_same = graph()->NewNode(
+      machine->Float64Equal(), value,
+      graph()->NewNode(machine->ChangeInt32ToFloat64(), value32));
+  Node* branch_same =
+      graph()->NewNode(common->Branch(), check_same, graph()->start());
+
+  Node* if_smi = graph()->NewNode(common->IfTrue(), branch_same);
+  Node* vsmi;
+  Node* if_box = graph()->NewNode(common->IfFalse(), branch_same);
+  Node* vbox;
+
+  // We only need to check for -0 if the {value} can potentially contain -0.
+  Node* check_zero = graph()->NewNode(machine->Word32Equal(), value32,
+                                      jsgraph()->Int32Constant(0));
+  Node* branch_zero =
+      graph()->NewNode(common->Branch(BranchHint::kFalse), check_zero, if_smi);
+
+  Node* if_zero = graph()->NewNode(common->IfTrue(), branch_zero);
+  Node* if_notzero = graph()->NewNode(common->IfFalse(), branch_zero);
+
+  // In case of 0, we need to check the high bits for the IEEE -0 pattern.
+  Node* check_negative = graph()->NewNode(
+      machine->Int32LessThan(),
+      graph()->NewNode(machine->Float64ExtractHighWord32(), value),
+      jsgraph()->Int32Constant(0));
+  Node* branch_negative = graph()->NewNode(common->Branch(BranchHint::kFalse),
+                                           check_negative, if_zero);
+
+  Node* if_negative = graph()->NewNode(common->IfTrue(), branch_negative);
+  Node* if_notnegative = graph()->NewNode(common->IfFalse(), branch_negative);
+
+  // We need to create a box for negative 0.
+  if_smi = graph()->NewNode(common->Merge(2), if_notzero, if_notnegative);
+  if_box = graph()->NewNode(common->Merge(2), if_box, if_negative);
+
+  // On 64-bit machines we can just wrap the 32-bit integer in a smi, for 32-bit
+  // machines we need to deal with potential overflow and fallback to boxing.
+  if (machine->Is64()) {
+    vsmi = BuildChangeInt32ToSmi(value32);
+  } else {
+    Node* smi_tag = graph()->NewNode(machine->Int32AddWithOverflow(), value32,
+                                     value32, if_smi);
+
+    Node* check_ovf = graph()->NewNode(common->Projection(1), smi_tag, if_smi);
+    Node* branch_ovf =
+        graph()->NewNode(common->Branch(BranchHint::kFalse), check_ovf, if_smi);
+
+    Node* if_ovf = graph()->NewNode(common->IfTrue(), branch_ovf);
+    if_box = graph()->NewNode(common->Merge(2), if_ovf, if_box);
+
+    if_smi = graph()->NewNode(common->IfFalse(), branch_ovf);
+    vsmi = graph()->NewNode(common->Projection(0), smi_tag, if_smi);
+  }
+
+  // Allocate the box for the {value}.
+  vbox = BuildAllocateHeapNumberWithValue(value, if_box);
+
+  Node* control = graph()->NewNode(common->Merge(2), if_smi, if_box);
+  value = graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2), vsmi,
+                           vbox, control);
+  return value;
+}
+
+Node* WasmGraphBuilder::ToJS(Node* node, Node* context, wasm::LocalType type) {
+  switch (type) {
+    case wasm::kAstI32:
+      return BuildChangeInt32ToTagged(node);
+    case wasm::kAstI64:
+      // TODO(titzer): i64->JS has no good solution right now. Using lower 32
+      // bits.
+      if (jsgraph()->machine()->Is64()) {
+        // On 32 bit platforms we do not have to do the truncation because the
+        // node we get in as a parameter only contains the low word anyways.
+        node = graph()->NewNode(jsgraph()->machine()->TruncateInt64ToInt32(),
+                                node);
+      }
+      return BuildChangeInt32ToTagged(node);
+    case wasm::kAstF32:
+      node = graph()->NewNode(jsgraph()->machine()->ChangeFloat32ToFloat64(),
+                              node);
+      return BuildChangeFloat64ToTagged(node);
+    case wasm::kAstF64:
+      return BuildChangeFloat64ToTagged(node);
+    case wasm::kAstStmt:
+      return jsgraph()->UndefinedConstant();
+    default:
+      UNREACHABLE();
+      return nullptr;
+  }
+}
+
+Node* WasmGraphBuilder::BuildJavaScriptToNumber(Node* node, Node* context,
+                                                Node* effect, Node* control) {
+  Callable callable = CodeFactory::ToNumber(jsgraph()->isolate());
+  CallDescriptor* desc = Linkage::GetStubCallDescriptor(
+      jsgraph()->isolate(), jsgraph()->zone(), callable.descriptor(), 0,
+      CallDescriptor::kNoFlags, Operator::kNoProperties);
+  Node* stub_code = jsgraph()->HeapConstant(callable.code());
+
+  Node* result = graph()->NewNode(jsgraph()->common()->Call(desc), stub_code,
+                                  node, context, effect, control);
+
+  *control_ = result;
+  *effect_ = result;
+
+  return result;
+}
+
+bool CanCover(Node* value, IrOpcode::Value opcode) {
+  if (value->opcode() != opcode) return false;
+  bool first = true;
+  for (Edge const edge : value->use_edges()) {
+    if (NodeProperties::IsControlEdge(edge)) continue;
+    if (NodeProperties::IsEffectEdge(edge)) continue;
+    DCHECK(NodeProperties::IsValueEdge(edge));
+    if (!first) return false;
+    first = false;
+  }
+  return true;
+}
+
+Node* WasmGraphBuilder::BuildChangeTaggedToFloat64(Node* value) {
+  MachineOperatorBuilder* machine = jsgraph()->machine();
+  CommonOperatorBuilder* common = jsgraph()->common();
+
+  if (CanCover(value, IrOpcode::kJSToNumber)) {
+    // ChangeTaggedToFloat64(JSToNumber(x)) =>
+    //   if IsSmi(x) then ChangeSmiToFloat64(x)
+    //   else let y = JSToNumber(x) in
+    //     if IsSmi(y) then ChangeSmiToFloat64(y)
+    //     else BuildLoadHeapNumberValue(y)
+    Node* object = NodeProperties::GetValueInput(value, 0);
+    Node* context = NodeProperties::GetContextInput(value);
+    Node* frame_state = NodeProperties::GetFrameStateInput(value, 0);
+    Node* effect = NodeProperties::GetEffectInput(value);
+    Node* control = NodeProperties::GetControlInput(value);
+
+    const Operator* merge_op = common->Merge(2);
+    const Operator* ephi_op = common->EffectPhi(2);
+    const Operator* phi_op = common->Phi(MachineRepresentation::kFloat64, 2);
+
+    Node* check1 = BuildTestNotSmi(object);
+    Node* branch1 =
+        graph()->NewNode(common->Branch(BranchHint::kFalse), check1, control);
+
+    Node* if_true1 = graph()->NewNode(common->IfTrue(), branch1);
+    Node* vtrue1 = graph()->NewNode(value->op(), object, context, frame_state,
+                                    effect, if_true1);
+    Node* etrue1 = vtrue1;
+
+    Node* check2 = BuildTestNotSmi(vtrue1);
+    Node* branch2 = graph()->NewNode(common->Branch(), check2, if_true1);
+
+    Node* if_true2 = graph()->NewNode(common->IfTrue(), branch2);
+    Node* vtrue2 = BuildLoadHeapNumberValue(vtrue1, if_true2);
+
+    Node* if_false2 = graph()->NewNode(common->IfFalse(), branch2);
+    Node* vfalse2 = BuildChangeSmiToFloat64(vtrue1);
+
+    if_true1 = graph()->NewNode(merge_op, if_true2, if_false2);
+    vtrue1 = graph()->NewNode(phi_op, vtrue2, vfalse2, if_true1);
+
+    Node* if_false1 = graph()->NewNode(common->IfFalse(), branch1);
+    Node* vfalse1 = BuildChangeSmiToFloat64(object);
+    Node* efalse1 = effect;
+
+    Node* merge1 = graph()->NewNode(merge_op, if_true1, if_false1);
+    Node* ephi1 = graph()->NewNode(ephi_op, etrue1, efalse1, merge1);
+    Node* phi1 = graph()->NewNode(phi_op, vtrue1, vfalse1, merge1);
+
+    // Wire the new diamond into the graph, {JSToNumber} can still throw.
+    NodeProperties::ReplaceUses(value, phi1, ephi1, etrue1, etrue1);
+
+    // TODO(mstarzinger): This iteration cuts out the IfSuccess projection from
+    // the node and places it inside the diamond. Come up with a helper method!
+    for (Node* use : etrue1->uses()) {
+      if (use->opcode() == IrOpcode::kIfSuccess) {
+        use->ReplaceUses(merge1);
+        NodeProperties::ReplaceControlInput(branch2, use);
+      }
+    }
+    return phi1;
+  }
+
+  Node* check = BuildTestNotSmi(value);
+  Node* branch = graph()->NewNode(common->Branch(BranchHint::kFalse), check,
+                                  graph()->start());
+
+  Node* if_not_smi = graph()->NewNode(common->IfTrue(), branch);
+
+  Node* vnot_smi;
+  Node* check_undefined = graph()->NewNode(machine->WordEqual(), value,
+                                           jsgraph()->UndefinedConstant());
+  Node* branch_undefined = graph()->NewNode(common->Branch(BranchHint::kFalse),
+                                            check_undefined, if_not_smi);
+
+  Node* if_undefined = graph()->NewNode(common->IfTrue(), branch_undefined);
+  Node* vundefined =
+      jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN());
+
+  Node* if_not_undefined =
+      graph()->NewNode(common->IfFalse(), branch_undefined);
+  Node* vheap_number = BuildLoadHeapNumberValue(value, if_not_undefined);
+
+  if_not_smi =
+      graph()->NewNode(common->Merge(2), if_undefined, if_not_undefined);
+  vnot_smi = graph()->NewNode(common->Phi(MachineRepresentation::kFloat64, 2),
+                              vundefined, vheap_number, if_not_smi);
+
+  Node* if_smi = graph()->NewNode(common->IfFalse(), branch);
+  Node* vfrom_smi = BuildChangeSmiToFloat64(value);
+
+  Node* merge = graph()->NewNode(common->Merge(2), if_not_smi, if_smi);
+  Node* phi = graph()->NewNode(common->Phi(MachineRepresentation::kFloat64, 2),
+                               vnot_smi, vfrom_smi, merge);
+
+  return phi;
+}
+
+Node* WasmGraphBuilder::FromJS(Node* node, Node* context,
+                               wasm::LocalType type) {
+  // Do a JavaScript ToNumber.
+  Node* num = BuildJavaScriptToNumber(node, context, *effect_, *control_);
+
+  // Change representation.
+  SimplifiedOperatorBuilder simplified(jsgraph()->zone());
+  num = BuildChangeTaggedToFloat64(num);
+
+  switch (type) {
+    case wasm::kAstI32: {
+      num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToWord32(),
+                             num);
+      break;
+    }
+    case wasm::kAstI64:
+      // TODO(titzer): JS->i64 has no good solution right now. Using 32 bits.
+      num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToWord32(),
+                             num);
+      if (jsgraph()->machine()->Is64()) {
+        // We cannot change an int32 to an int64 on a 32 bit platform. Instead
+        // we will split the parameter node later.
+        num = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), num);
+      }
+      break;
+    case wasm::kAstF32:
+      num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToFloat32(),
+                             num);
+      break;
+    case wasm::kAstF64:
+      break;
+    case wasm::kAstStmt:
+      num = jsgraph()->Int32Constant(0);
+      break;
+    default:
+      UNREACHABLE();
+      return nullptr;
+  }
+  return num;
+}
+
+Node* WasmGraphBuilder::BuildChangeInt32ToSmi(Node* value) {
+  if (jsgraph()->machine()->Is64()) {
+    value = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), value);
+  }
+  return graph()->NewNode(jsgraph()->machine()->WordShl(), value,
+                          BuildSmiShiftBitsConstant());
+}
+
+Node* WasmGraphBuilder::BuildChangeSmiToInt32(Node* value) {
+  value = graph()->NewNode(jsgraph()->machine()->WordSar(), value,
+                           BuildSmiShiftBitsConstant());
+  if (jsgraph()->machine()->Is64()) {
+    value =
+        graph()->NewNode(jsgraph()->machine()->TruncateInt64ToInt32(), value);
+  }
+  return value;
+}
+
+Node* WasmGraphBuilder::BuildChangeSmiToFloat64(Node* value) {
+  return graph()->NewNode(jsgraph()->machine()->ChangeInt32ToFloat64(),
+                          BuildChangeSmiToInt32(value));
+}
+
+Node* WasmGraphBuilder::BuildTestNotSmi(Node* value) {
+  STATIC_ASSERT(kSmiTag == 0);
+  STATIC_ASSERT(kSmiTagMask == 1);
+  return graph()->NewNode(jsgraph()->machine()->WordAnd(), value,
+                          jsgraph()->IntPtrConstant(kSmiTagMask));
+}
+
+Node* WasmGraphBuilder::BuildSmiShiftBitsConstant() {
+  return jsgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize);
+}
+
+Node* WasmGraphBuilder::BuildAllocateHeapNumberWithValue(Node* value,
+                                                         Node* control) {
+  MachineOperatorBuilder* machine = jsgraph()->machine();
+  CommonOperatorBuilder* common = jsgraph()->common();
+  // The AllocateHeapNumberStub does not use the context, so we can safely pass
+  // in Smi zero here.
+  Callable callable = CodeFactory::AllocateHeapNumber(jsgraph()->isolate());
+  Node* target = jsgraph()->HeapConstant(callable.code());
+  Node* context = jsgraph()->NoContextConstant();
+  Node* effect =
+      graph()->NewNode(common->BeginRegion(RegionObservability::kNotObservable),
+                       graph()->start());
+  if (!allocate_heap_number_operator_.is_set()) {
+    CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
+        jsgraph()->isolate(), jsgraph()->zone(), callable.descriptor(), 0,
+        CallDescriptor::kNoFlags, Operator::kNoThrow);
+    allocate_heap_number_operator_.set(common->Call(descriptor));
+  }
+  Node* heap_number = graph()->NewNode(allocate_heap_number_operator_.get(),
+                                       target, context, effect, control);
+  Node* store =
+      graph()->NewNode(machine->Store(StoreRepresentation(
+                           MachineRepresentation::kFloat64, kNoWriteBarrier)),
+                       heap_number, BuildHeapNumberValueIndexConstant(), value,
+                       heap_number, control);
+  return graph()->NewNode(common->FinishRegion(), heap_number, store);
+}
+
+Node* WasmGraphBuilder::BuildLoadHeapNumberValue(Node* value, Node* control) {
+  return graph()->NewNode(jsgraph()->machine()->Load(MachineType::Float64()),
+                          value, BuildHeapNumberValueIndexConstant(),
+                          graph()->start(), control);
+}
+
+Node* WasmGraphBuilder::BuildHeapNumberValueIndexConstant() {
+  return jsgraph()->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag);
+}
 
 void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<Code> wasm_code,
                                             wasm::FunctionSig* sig) {
-  int params = static_cast<int>(sig->parameter_count());
-  int count = params + 3;
+  int wasm_count = static_cast<int>(sig->parameter_count());
+  int param_count;
+  if (jsgraph()->machine()->Is64()) {
+    param_count = static_cast<int>(sig->parameter_count());
+  } else {
+    param_count = Int64Lowering::GetParameterCountAfterLowering(sig);
+  }
+  int count = param_count + 3;
   Node** args = Buffer(count);
 
   // Build the start and the JS parameter nodes.
-  Node* start = Start(params + 5);
+  Node* start = Start(param_count + 5);
   *control_ = start;
   *effect_ = start;
   // Create the context parameter
   Node* context = graph()->NewNode(
       jsgraph()->common()->Parameter(
-          Linkage::GetJSCallContextParamIndex(params + 1), "%context"),
+          Linkage::GetJSCallContextParamIndex(wasm_count + 1), "%context"),
       graph()->start());
 
   int pos = 0;
-  args[pos++] = Constant(wasm_code);
+  args[pos++] = HeapConstant(wasm_code);
 
   // Convert JS parameters to WASM numbers.
-  for (int i = 0; i < params; i++) {
+  for (int i = 0; i < wasm_count; ++i) {
     Node* param =
         graph()->NewNode(jsgraph()->common()->Parameter(i + 1), start);
-    args[pos++] = FromJS(param, context, sig->GetParam(i));
+    Node* wasm_param = FromJS(param, context, sig->GetParam(i));
+    args[pos++] = wasm_param;
+    if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64) {
+      // We make up the high word with SAR to get the proper sign extension.
+      args[pos++] = graph()->NewNode(jsgraph()->machine()->Word32Sar(),
+                                     wasm_param, jsgraph()->Int32Constant(31));
+    }
   }
 
   args[pos++] = *effect_;
@@ -2207,9 +2381,19 @@
   // Call the WASM code.
   CallDescriptor* desc =
       wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig);
+  if (jsgraph()->machine()->Is32()) {
+    desc = wasm::ModuleEnv::GetI32WasmCallDescriptor(jsgraph()->zone(), desc);
+  }
   Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), count, args);
+  Node* retval = call;
+  if (jsgraph()->machine()->Is32() && sig->return_count() > 0 &&
+      sig->GetReturn(0) == wasm::kAstI64) {
+    // The return values comes as two values, we pick the low word.
+    retval = graph()->NewNode(jsgraph()->common()->Projection(0), retval,
+                              graph()->start());
+  }
   Node* jsval =
-      ToJS(call, context,
+      ToJS(retval, context,
            sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn());
   Node* ret =
       graph()->NewNode(jsgraph()->common()->Return(), jsval, call, start);
@@ -2217,20 +2401,25 @@
   MergeControlToEnd(jsgraph(), ret);
 }
 
-
 void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSFunction> function,
                                             wasm::FunctionSig* sig) {
   int js_count = function->shared()->internal_formal_parameter_count();
   int wasm_count = static_cast<int>(sig->parameter_count());
+  int param_count;
+  if (jsgraph()->machine()->Is64()) {
+    param_count = wasm_count;
+  } else {
+    param_count = Int64Lowering::GetParameterCountAfterLowering(sig);
+  }
 
   // Build the start and the parameter nodes.
   Isolate* isolate = jsgraph()->isolate();
   CallDescriptor* desc;
-  Node* start = Start(wasm_count + 3);
+  Node* start = Start(param_count + 3);
   *effect_ = start;
   *control_ = start;
   // JS context is the last parameter.
-  Node* context = Constant(Handle<Context>(function->context(), isolate));
+  Node* context = HeapConstant(Handle<Context>(function->context(), isolate));
   Node** args = Buffer(wasm_count + 7);
 
   bool arg_count_before_args = false;
@@ -2262,9 +2451,15 @@
   args[pos++] = jsgraph()->Constant(global);
 
   // Convert WASM numbers to JS values.
-  for (int i = 0; i < wasm_count; i++) {
-    Node* param = graph()->NewNode(jsgraph()->common()->Parameter(i), start);
+  int param_index = 0;
+  for (int i = 0; i < wasm_count; ++i) {
+    Node* param =
+        graph()->NewNode(jsgraph()->common()->Parameter(param_index++), start);
     args[pos++] = ToJS(param, context, sig->GetParam(i));
+    if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64) {
+      // On 32 bit platforms we have to skip the high word of int64 parameters.
+      param_index++;
+    }
   }
 
   if (add_new_target_undefined) {
@@ -2281,58 +2476,68 @@
   Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args);
 
   // Convert the return value back.
+  Node* ret;
   Node* val =
       FromJS(call, context,
              sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn());
-  Node* ret = graph()->NewNode(jsgraph()->common()->Return(), val, call, start);
+  if (jsgraph()->machine()->Is32() && sig->return_count() > 0 &&
+      sig->GetReturn() == wasm::kAstI64) {
+    ret = graph()->NewNode(jsgraph()->common()->Return(), val,
+                           graph()->NewNode(jsgraph()->machine()->Word32Sar(),
+                                            val, jsgraph()->Int32Constant(31)),
+                           call, start);
+  } else {
+    ret = graph()->NewNode(jsgraph()->common()->Return(), val, call, start);
+  }
 
   MergeControlToEnd(jsgraph(), ret);
 }
 
-
 Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
   DCHECK(module_ && module_->instance);
   if (offset == 0) {
     if (!mem_buffer_) {
-      mem_buffer_ = jsgraph()->IntPtrConstant(
-          reinterpret_cast<uintptr_t>(module_->instance->mem_start));
+      mem_buffer_ = jsgraph()->RelocatableIntPtrConstant(
+          reinterpret_cast<uintptr_t>(module_->instance->mem_start),
+          RelocInfo::WASM_MEMORY_REFERENCE);
     }
     return mem_buffer_;
   } else {
-    return jsgraph()->IntPtrConstant(
-        reinterpret_cast<uintptr_t>(module_->instance->mem_start + offset));
+    return jsgraph()->RelocatableIntPtrConstant(
+        reinterpret_cast<uintptr_t>(module_->instance->mem_start + offset),
+        RelocInfo::WASM_MEMORY_REFERENCE);
   }
 }
 
-
 Node* WasmGraphBuilder::MemSize(uint32_t offset) {
   DCHECK(module_ && module_->instance);
   uint32_t size = static_cast<uint32_t>(module_->instance->mem_size);
   if (offset == 0) {
-    if (!mem_size_) mem_size_ = jsgraph()->Int32Constant(size);
+    if (!mem_size_)
+      mem_size_ = jsgraph()->RelocatableInt32Constant(
+          size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
     return mem_size_;
   } else {
-    return jsgraph()->Int32Constant(size + offset);
+    return jsgraph()->RelocatableInt32Constant(
+        size + offset, RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
   }
 }
 
-
 Node* WasmGraphBuilder::FunctionTable() {
   DCHECK(module_ && module_->instance &&
          !module_->instance->function_table.is_null());
   if (!function_table_) {
-    function_table_ = jsgraph()->Constant(module_->instance->function_table);
+    function_table_ = HeapConstant(module_->instance->function_table);
   }
   return function_table_;
 }
 
-
 Node* WasmGraphBuilder::LoadGlobal(uint32_t index) {
-  DCHECK(module_ && module_->instance && module_->instance->globals_start);
   MachineType mem_type = module_->GetGlobalType(index);
-  Node* addr = jsgraph()->IntPtrConstant(
+  Node* addr = jsgraph()->RelocatableIntPtrConstant(
       reinterpret_cast<uintptr_t>(module_->instance->globals_start +
-                                  module_->module->globals[index].offset));
+                                  module_->module->globals[index].offset),
+      RelocInfo::WASM_GLOBAL_REFERENCE);
   const Operator* op = jsgraph()->machine()->Load(mem_type);
   Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), *effect_,
                                 *control_);
@@ -2340,13 +2545,12 @@
   return node;
 }
 
-
 Node* WasmGraphBuilder::StoreGlobal(uint32_t index, Node* val) {
-  DCHECK(module_ && module_->instance && module_->instance->globals_start);
   MachineType mem_type = module_->GetGlobalType(index);
-  Node* addr = jsgraph()->IntPtrConstant(
+  Node* addr = jsgraph()->RelocatableIntPtrConstant(
       reinterpret_cast<uintptr_t>(module_->instance->globals_start +
-                                  module_->module->globals[index].offset));
+                                  module_->module->globals[index].offset),
+      RelocInfo::WASM_GLOBAL_REFERENCE);
   const Operator* op = jsgraph()->machine()->Store(
       StoreRepresentation(mem_type.representation(), kNoWriteBarrier));
   Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), val,
@@ -2355,48 +2559,181 @@
   return node;
 }
 
-
 void WasmGraphBuilder::BoundsCheckMem(MachineType memtype, Node* index,
-                                      uint32_t offset) {
-  // TODO(turbofan): fold bounds checks for constant indexes.
+                                      uint32_t offset,
+                                      wasm::WasmCodePosition position) {
   DCHECK(module_ && module_->instance);
-  size_t size = module_->instance->mem_size;
+  uint32_t size = module_->instance->mem_size;
   byte memsize = wasm::WasmOpcodes::MemSize(memtype);
-  Node* cond;
+
+  // Check against the effective size.
+  size_t effective_size;
   if (offset >= size || (static_cast<uint64_t>(offset) + memsize) > size) {
-    // The access will always throw.
-    cond = jsgraph()->Int32Constant(0);
+    effective_size = 0;
   } else {
-    // Check against the limit.
-    size_t limit = size - offset - memsize;
-    CHECK(limit <= kMaxUInt32);
-    cond = graph()->NewNode(
-        jsgraph()->machine()->Uint32LessThanOrEqual(), index,
-        jsgraph()->Int32Constant(static_cast<uint32_t>(limit)));
+    effective_size = size - offset - memsize + 1;
+  }
+  CHECK(effective_size <= kMaxUInt32);
+
+  Uint32Matcher m(index);
+  if (m.HasValue()) {
+    uint32_t value = m.Value();
+    if (value < effective_size) {
+      // The bounds check will always succeed.
+      return;
+    }
   }
 
-  trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, cond);
+  Node* cond = graph()->NewNode(jsgraph()->machine()->Uint32LessThan(), index,
+                                jsgraph()->RelocatableInt32Constant(
+                                    static_cast<uint32_t>(effective_size),
+                                    RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
+
+  trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position);
 }
 
+MachineType WasmGraphBuilder::GetTypeForUnalignedAccess(uint32_t alignment,
+                                                        bool signExtend) {
+  switch (alignment) {
+    case 0:
+      return signExtend ? MachineType::Int8() : MachineType::Uint8();
+    case 1:
+      return signExtend ? MachineType::Int16() : MachineType::Uint16();
+    case 2:
+      return signExtend ? MachineType::Int32() : MachineType::Uint32();
+    default:
+      UNREACHABLE();
+      return MachineType::None();
+  }
+}
 
-Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype,
-                                Node* index, uint32_t offset) {
-  Node* load;
+Node* WasmGraphBuilder::GetUnalignedLoadOffsetNode(Node* baseOffset,
+                                                   int numberOfBytes,
+                                                   int stride, int current) {
+  int offset;
+  wasm::WasmOpcode addOpcode;
 
-  if (module_ && module_->asm_js()) {
-    // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish).
-    DCHECK_EQ(0, offset);
-    const Operator* op = jsgraph()->machine()->CheckedLoad(memtype);
-    load = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), *effect_,
-                            *control_);
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+  offset = numberOfBytes - stride - current;
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  offset = current;
+#else
+#error Unsupported endianness
+#endif
+
+#if WASM_64
+  addOpcode = wasm::kExprI64Add;
+#else
+  addOpcode = wasm::kExprI32Add;
+#endif
+
+  if (offset == 0) {
+    return baseOffset;
   } else {
-    // WASM semantics throw on OOB. Introduce explicit bounds check.
-    BoundsCheckMem(memtype, index, offset);
-    load = graph()->NewNode(jsgraph()->machine()->Load(memtype),
-                            MemBuffer(offset), index, *effect_, *control_);
+    return Binop(addOpcode, baseOffset, jsgraph()->Int32Constant(offset));
+  }
+}
+
+Node* WasmGraphBuilder::BuildUnalignedLoad(wasm::LocalType type,
+                                           MachineType memtype, Node* index,
+                                           uint32_t offset,
+                                           uint32_t alignment) {
+  Node* result;
+  Node* load;
+  bool extendTo64Bit = false;
+
+  wasm::WasmOpcode shiftOpcode;
+  wasm::WasmOpcode orOpcode;
+  Node* shiftConst;
+
+  bool signExtend = memtype.IsSigned();
+
+  bool isFloat = IsFloatingPoint(memtype.representation());
+  int stride =
+      1 << ElementSizeLog2Of(
+          GetTypeForUnalignedAccess(alignment, false).representation());
+  int numberOfBytes = 1 << ElementSizeLog2Of(memtype.representation());
+  DCHECK(numberOfBytes % stride == 0);
+
+  switch (type) {
+    case wasm::kAstI64:
+    case wasm::kAstF64:
+      shiftOpcode = wasm::kExprI64Shl;
+      orOpcode = wasm::kExprI64Ior;
+      result = jsgraph()->Int64Constant(0);
+      shiftConst = jsgraph()->Int64Constant(8 * stride);
+      extendTo64Bit = true;
+      break;
+    case wasm::kAstI32:
+    case wasm::kAstF32:
+      shiftOpcode = wasm::kExprI32Shl;
+      orOpcode = wasm::kExprI32Ior;
+      result = jsgraph()->Int32Constant(0);
+      shiftConst = jsgraph()->Int32Constant(8 * stride);
+      break;
+    default:
+      UNREACHABLE();
   }
 
-  *effect_ = load;
+  Node* baseOffset = MemBuffer(offset);
+
+  for (int i = 0; i < numberOfBytes; i += stride) {
+    result = Binop(shiftOpcode, result, shiftConst);
+    load = graph()->NewNode(
+        jsgraph()->machine()->Load(
+            GetTypeForUnalignedAccess(alignment, signExtend)),
+        GetUnalignedLoadOffsetNode(baseOffset, numberOfBytes, stride, i), index,
+        *effect_, *control_);
+    *effect_ = load;
+    if (extendTo64Bit) {
+      if (signExtend) {
+        load =
+            graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load);
+      } else {
+        load = graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(),
+                                load);
+      }
+    }
+    signExtend = false;
+    result = Binop(orOpcode, result, load);
+  }
+
+  // Convert to float
+  if (isFloat) {
+    switch (type) {
+      case wasm::kAstF32:
+        result = Unop(wasm::kExprF32ReinterpretI32, result);
+        break;
+      case wasm::kAstF64:
+        result = Unop(wasm::kExprF64ReinterpretI64, result);
+        break;
+      default:
+        UNREACHABLE();
+    }
+  }
+
+  return result;
+}
+
+Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype,
+                                Node* index, uint32_t offset,
+                                uint32_t alignment,
+                                wasm::WasmCodePosition position) {
+  Node* load;
+
+  // WASM semantics throw on OOB. Introduce explicit bounds check.
+  BoundsCheckMem(memtype, index, offset, position);
+  bool aligned = static_cast<int>(alignment) >=
+                 ElementSizeLog2Of(memtype.representation());
+
+  if (aligned ||
+      jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) {
+    load = graph()->NewNode(jsgraph()->machine()->Load(memtype),
+                            MemBuffer(offset), index, *effect_, *control_);
+    *effect_ = load;
+  } else {
+    load = BuildUnalignedLoad(type, memtype, index, offset, alignment);
+  }
 
   if (type == wasm::kAstI64 &&
       ElementSizeLog2Of(memtype.representation()) < 3) {
@@ -2414,41 +2751,154 @@
   return load;
 }
 
+Node* WasmGraphBuilder::GetUnalignedStoreOffsetNode(Node* baseOffset,
+                                                    int numberOfBytes,
+                                                    int stride, int current) {
+  int offset;
+  wasm::WasmOpcode addOpcode;
+
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+  offset = current;
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  offset = numberOfBytes - stride - current;
+#else
+#error Unsupported endianness
+#endif
+
+#if WASM_64
+  addOpcode = wasm::kExprI64Add;
+#else
+  addOpcode = wasm::kExprI32Add;
+#endif
+
+  if (offset == 0) {
+    return baseOffset;
+  } else {
+    return Binop(addOpcode, baseOffset, jsgraph()->Int32Constant(offset));
+  }
+}
+
+Node* WasmGraphBuilder::BuildUnalignedStore(MachineType memtype, Node* index,
+                                            uint32_t offset, uint32_t alignment,
+                                            Node* val) {
+  Node* store;
+  Node* newValue;
+
+  wasm::WasmOpcode shiftOpcode;
+
+  Node* shiftConst;
+  bool extendTo64Bit = false;
+  bool isFloat = IsFloatingPoint(memtype.representation());
+  int stride = 1 << ElementSizeLog2Of(
+                   GetTypeForUnalignedAccess(alignment).representation());
+  int numberOfBytes = 1 << ElementSizeLog2Of(memtype.representation());
+  DCHECK(numberOfBytes % stride == 0);
+
+  StoreRepresentation rep(GetTypeForUnalignedAccess(alignment).representation(),
+                          kNoWriteBarrier);
+
+  if (ElementSizeLog2Of(memtype.representation()) <= 2) {
+    shiftOpcode = wasm::kExprI32ShrU;
+    shiftConst = jsgraph()->Int32Constant(8 * stride);
+  } else {
+    shiftOpcode = wasm::kExprI64ShrU;
+    shiftConst = jsgraph()->Int64Constant(8 * stride);
+    extendTo64Bit = true;
+  }
+
+  newValue = val;
+  if (isFloat) {
+    switch (memtype.representation()) {
+      case MachineRepresentation::kFloat64:
+        newValue = Unop(wasm::kExprI64ReinterpretF64, val);
+        break;
+      case MachineRepresentation::kFloat32:
+        newValue = Unop(wasm::kExprI32ReinterpretF32, val);
+        break;
+      default:
+        UNREACHABLE();
+    }
+  }
+
+  Node* baseOffset = MemBuffer(offset);
+
+  for (int i = 0; i < numberOfBytes - stride; i += stride) {
+    store = graph()->NewNode(
+        jsgraph()->machine()->Store(rep),
+        GetUnalignedStoreOffsetNode(baseOffset, numberOfBytes, stride, i),
+        index,
+        extendTo64Bit ? Unop(wasm::kExprI32ConvertI64, newValue) : newValue,
+        *effect_, *control_);
+    newValue = Binop(shiftOpcode, newValue, shiftConst);
+    *effect_ = store;
+  }
+  store = graph()->NewNode(
+      jsgraph()->machine()->Store(rep),
+      GetUnalignedStoreOffsetNode(baseOffset, numberOfBytes, stride,
+                                  numberOfBytes - stride),
+      index,
+      extendTo64Bit ? Unop(wasm::kExprI32ConvertI64, newValue) : newValue,
+      *effect_, *control_);
+  *effect_ = store;
+  return val;
+}
 
 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index,
-                                 uint32_t offset, Node* val) {
+                                 uint32_t offset, uint32_t alignment, Node* val,
+                                 wasm::WasmCodePosition position) {
   Node* store;
-  if (module_ && module_->asm_js()) {
-    // asm.js semantics use CheckedStore (i.e. ignore OOB writes).
-    DCHECK_EQ(0, offset);
-    const Operator* op =
-        jsgraph()->machine()->CheckedStore(memtype.representation());
-    store = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), val, *effect_,
-                             *control_);
-  } else {
-    // WASM semantics throw on OOB. Introduce explicit bounds check.
-    BoundsCheckMem(memtype, index, offset);
+
+  // WASM semantics throw on OOB. Introduce explicit bounds check.
+  BoundsCheckMem(memtype, index, offset, position);
+  StoreRepresentation rep(memtype.representation(), kNoWriteBarrier);
+  bool aligned = static_cast<int>(alignment) >=
+                 ElementSizeLog2Of(memtype.representation());
+
+  if (aligned ||
+      jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) {
     StoreRepresentation rep(memtype.representation(), kNoWriteBarrier);
     store =
         graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset),
                          index, val, *effect_, *control_);
+    *effect_ = store;
+  } else {
+    store = BuildUnalignedStore(memtype, index, offset, alignment, val);
   }
-  *effect_ = store;
+
   return store;
 }
 
+Node* WasmGraphBuilder::BuildAsmjsLoadMem(MachineType type, Node* index) {
+  // TODO(turbofan): fold bounds checks for constant asm.js loads.
+  // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish).
+  const Operator* op = jsgraph()->machine()->CheckedLoad(type);
+  Node* load = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), *effect_,
+                                *control_);
+  *effect_ = load;
+  return load;
+}
+
+Node* WasmGraphBuilder::BuildAsmjsStoreMem(MachineType type, Node* index,
+                                           Node* val) {
+  // TODO(turbofan): fold bounds checks for constant asm.js stores.
+  // asm.js semantics use CheckedStore (i.e. ignore OOB writes).
+  const Operator* op =
+      jsgraph()->machine()->CheckedStore(type.representation());
+  Node* store = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), val,
+                                 *effect_, *control_);
+  *effect_ = store;
+  return val;
+}
 
 void WasmGraphBuilder::PrintDebugName(Node* node) {
   PrintF("#%d:%s", node->id(), node->op()->mnemonic());
 }
 
-
 Node* WasmGraphBuilder::String(const char* string) {
   return jsgraph()->Constant(
       jsgraph()->isolate()->factory()->NewStringFromAsciiChecked(string));
 }
 
-
 Graph* WasmGraphBuilder::graph() { return jsgraph()->graph(); }
 
 void WasmGraphBuilder::Int64LoweringForTesting() {
@@ -2460,16 +2910,23 @@
   }
 }
 
-static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
+void WasmGraphBuilder::SetSourcePosition(Node* node,
+                                         wasm::WasmCodePosition position) {
+  DCHECK_NE(position, wasm::kNoCodePosition);
+  compiler::SourcePosition pos(position);
+  if (source_position_table_)
+    source_position_table_->SetSourcePosition(node, pos);
+}
+
+static void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
                                       CompilationInfo* info,
                                       const char* message, uint32_t index,
                                       wasm::WasmName func_name) {
   Isolate* isolate = info->isolate();
-  if (isolate->logger()->is_logging_code_events() ||
-      isolate->cpu_profiler()->is_profiling()) {
+  if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) {
     ScopedVector<char> buffer(128);
-    SNPrintF(buffer, "%s#%d:%.*s", message, index, func_name.length,
-             func_name.name);
+    SNPrintF(buffer, "%s#%d:%.*s", message, index, func_name.length(),
+             func_name.start());
     Handle<String> name_str =
         isolate->factory()->NewStringFromAsciiChecked(buffer.start());
     Handle<String> script_str =
@@ -2478,14 +2935,14 @@
     Handle<SharedFunctionInfo> shared =
         isolate->factory()->NewSharedFunctionInfo(name_str, code, false);
     PROFILE(isolate, CodeCreateEvent(tag, AbstractCode::cast(*code), *shared,
-                                     info, *script_str, 0, 0));
+                                     *script_str, 0, 0));
   }
 }
 
 Handle<JSFunction> CompileJSToWasmWrapper(
     Isolate* isolate, wasm::ModuleEnv* module, Handle<String> name,
     Handle<Code> wasm_code, Handle<JSObject> module_object, uint32_t index) {
-  wasm::WasmFunction* func = &module->module->functions[index];
+  const wasm::WasmFunction* func = &module->module->functions[index];
 
   //----------------------------------------------------------------------------
   // Create the JSFunction object.
@@ -2506,9 +2963,8 @@
   Zone zone(isolate->allocator());
   Graph graph(&zone);
   CommonOperatorBuilder common(&zone);
-  JSOperatorBuilder javascript(&zone);
   MachineOperatorBuilder machine(&zone);
-  JSGraph jsgraph(isolate, &graph, &common, &javascript, nullptr, &machine);
+  JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
 
   Node* control = nullptr;
   Node* effect = nullptr;
@@ -2523,20 +2979,6 @@
   // Run the compilation pipeline.
   //----------------------------------------------------------------------------
   {
-    // Changes lowering requires types.
-    Typer typer(isolate, &graph);
-    NodeVector roots(&zone);
-    jsgraph.GetCachedNodes(&roots);
-    typer.Run(roots);
-
-    // Run generic and change lowering.
-    JSGenericLowering generic(true, &jsgraph);
-    ChangeLowering changes(&jsgraph);
-    GraphReducer graph_reducer(&zone, &graph, jsgraph.Dead());
-    graph_reducer.AddReducer(&changes);
-    graph_reducer.AddReducer(&generic);
-    graph_reducer.ReduceGraph();
-
     if (FLAG_trace_turbo_graph) {  // Simple textual RPO.
       OFStream os(stdout);
       os << "-- Graph after change lowering -- " << std::endl;
@@ -2555,19 +2997,19 @@
 #else
         FLAG_print_opt_code || FLAG_trace_turbo || FLAG_trace_turbo_graph;
 #endif
-    const char* func_name = "js-to-wasm";
+    Vector<const char> func_name = ArrayVector("js-to-wasm");
 
     static unsigned id = 0;
     Vector<char> buffer;
     if (debugging) {
       buffer = Vector<char>::New(128);
-      SNPrintF(buffer, "js-to-wasm#%d", id);
-      func_name = buffer.start();
+      int chars = SNPrintF(buffer, "js-to-wasm#%d", id);
+      func_name = Vector<const char>::cast(buffer.SubVector(0, chars));
     }
 
     CompilationInfo info(func_name, isolate, &zone, flags);
     Handle<Code> code =
-        Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr);
+        Pipeline::GenerateCodeForTesting(&info, incoming, &graph);
 #ifdef ENABLE_DISASSEMBLER
     if (FLAG_print_opt_code && !code.is_null()) {
       OFStream os(stdout);
@@ -2579,7 +3021,7 @@
     }
 
     RecordFunctionCompilation(
-        Logger::FUNCTION_TAG, &info, "js-to-wasm", index,
+        CodeEventListener::FUNCTION_TAG, &info, "js-to-wasm", index,
         module->module->GetName(func->name_offset, func->name_length));
     // Set the JSFunction's machine code.
     function->set_code(*code);
@@ -2587,7 +3029,7 @@
   return function;
 }
 
-Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module,
+Handle<Code> CompileWasmToJSWrapper(Isolate* isolate,
                                     Handle<JSFunction> function,
                                     wasm::FunctionSig* sig,
                                     wasm::WasmName module_name,
@@ -2598,9 +3040,8 @@
   Zone zone(isolate->allocator());
   Graph graph(&zone);
   CommonOperatorBuilder common(&zone);
-  JSOperatorBuilder javascript(&zone);
   MachineOperatorBuilder machine(&zone);
-  JSGraph jsgraph(isolate, &graph, &common, &javascript, nullptr, &machine);
+  JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
 
   Node* control = nullptr;
   Node* effect = nullptr;
@@ -2608,25 +3049,10 @@
   WasmGraphBuilder builder(&zone, &jsgraph, sig);
   builder.set_control_ptr(&control);
   builder.set_effect_ptr(&effect);
-  builder.set_module(module);
   builder.BuildWasmToJSWrapper(function, sig);
 
   Handle<Code> code = Handle<Code>::null();
   {
-    // Changes lowering requires types.
-    Typer typer(isolate, &graph);
-    NodeVector roots(&zone);
-    jsgraph.GetCachedNodes(&roots);
-    typer.Run(roots);
-
-    // Run generic and change lowering.
-    JSGenericLowering generic(true, &jsgraph);
-    ChangeLowering changes(&jsgraph);
-    GraphReducer graph_reducer(&zone, &graph, jsgraph.Dead());
-    graph_reducer.AddReducer(&changes);
-    graph_reducer.AddReducer(&generic);
-    graph_reducer.ReduceGraph();
-
     if (FLAG_trace_turbo_graph) {  // Simple textual RPO.
       OFStream os(stdout);
       os << "-- Graph after change lowering -- " << std::endl;
@@ -2636,6 +3062,9 @@
     // Schedule and compile to machine code.
     CallDescriptor* incoming =
         wasm::ModuleEnv::GetWasmCallDescriptor(&zone, sig);
+    if (machine.Is32()) {
+      incoming = wasm::ModuleEnv::GetI32WasmCallDescriptor(&zone, incoming);
+    }
     Code::Flags flags = Code::ComputeFlags(Code::WASM_TO_JS_FUNCTION);
     bool debugging =
 #if DEBUG
@@ -2643,13 +3072,13 @@
 #else
         FLAG_print_opt_code || FLAG_trace_turbo || FLAG_trace_turbo_graph;
 #endif
-    const char* func_name = "wasm-to-js";
+    Vector<const char> func_name = ArrayVector("wasm-to-js");
     static unsigned id = 0;
     Vector<char> buffer;
     if (debugging) {
       buffer = Vector<char>::New(128);
-      SNPrintF(buffer, "wasm-to-js#%d", id);
-      func_name = buffer.start();
+      int chars = SNPrintF(buffer, "wasm-to-js#%d", id);
+      func_name = Vector<const char>::cast(buffer.SubVector(0, chars));
     }
 
     CompilationInfo info(func_name, isolate, &zone, flags);
@@ -2664,124 +3093,188 @@
       buffer.Dispose();
     }
 
-    RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, "wasm-to-js", 0,
-                              module_name);
+    RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, &info,
+                              "wasm-to-js", 0, module_name);
   }
   return code;
 }
 
-
-// Helper function to compile a single function.
-Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
-                                 wasm::ModuleEnv* module_env,
-                                 const wasm::WasmFunction& function) {
-  if (FLAG_trace_wasm_compiler) {
-    OFStream os(stdout);
-    os << "Compiling WASM function "
-       << wasm::WasmFunctionName(&function, module_env) << std::endl;
-    os << std::endl;
-  }
-
-  double decode_ms = 0;
+SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
+    double* decode_ms) {
   base::ElapsedTimer decode_timer;
   if (FLAG_trace_wasm_decode_time) {
     decode_timer.Start();
   }
-
   // Create a TF graph during decoding.
-  Zone zone(isolate->allocator());
-  Graph graph(&zone);
-  CommonOperatorBuilder common(&zone);
-  MachineOperatorBuilder machine(
-      &zone, MachineType::PointerRepresentation(),
-      InstructionSelector::SupportedMachineOperatorFlags());
-  JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
-  WasmGraphBuilder builder(&zone, &jsgraph, function.sig);
-  wasm::FunctionBody body = {
-      module_env, function.sig, module_env->module->module_start,
-      module_env->module->module_start + function.code_start_offset,
-      module_env->module->module_start + function.code_end_offset};
-  wasm::TreeResult result =
-      wasm::BuildTFGraph(isolate->allocator(), &builder, body);
 
-  if (result.failed()) {
+  Graph* graph = jsgraph_->graph();
+  CommonOperatorBuilder* common = jsgraph_->common();
+  MachineOperatorBuilder* machine = jsgraph_->machine();
+  SourcePositionTable* source_position_table =
+      new (jsgraph_->zone()) SourcePositionTable(graph);
+  WasmGraphBuilder builder(jsgraph_->zone(), jsgraph_, function_->sig,
+                           source_position_table);
+  wasm::FunctionBody body = {
+      module_env_, function_->sig, module_env_->module->module_start,
+      module_env_->module->module_start + function_->code_start_offset,
+      module_env_->module->module_start + function_->code_end_offset};
+  graph_construction_result_ =
+      wasm::BuildTFGraph(isolate_->allocator(), &builder, body);
+
+  if (graph_construction_result_.failed()) {
     if (FLAG_trace_wasm_compiler) {
       OFStream os(stdout);
-      os << "Compilation failed: " << result << std::endl;
+      os << "Compilation failed: " << graph_construction_result_ << std::endl;
     }
-    // Add the function as another context for the exception
-    ScopedVector<char> buffer(128);
-    wasm::WasmName name =
-        module_env->module->GetName(function.name_offset, function.name_length);
-    SNPrintF(buffer, "Compiling WASM function #%d:%.*s failed:",
-             function.func_index, name.length, name.name);
-    thrower.Failed(buffer.start(), result);
-    return Handle<Code>::null();
+    return nullptr;
   }
 
-  int index = static_cast<int>(function.func_index);
-  if (index >= FLAG_trace_wasm_ast_start && index < FLAG_trace_wasm_ast_end) {
-    PrintAst(isolate->allocator(), body);
+  if (machine->Is32()) {
+    Int64Lowering r(graph, machine, common, jsgraph_->zone(), function_->sig);
+    r.LowerGraph();
   }
 
+  int index = static_cast<int>(function_->func_index);
+  if (index >= FLAG_trace_wasm_ast_start && index < FLAG_trace_wasm_ast_end) {
+    OFStream os(stdout);
+    PrintAst(isolate_->allocator(), body, os, nullptr);
+  }
+  if (FLAG_trace_wasm_decode_time) {
+    *decode_ms = decode_timer.Elapsed().InMillisecondsF();
+  }
+  return source_position_table;
+}
+
+WasmCompilationUnit::WasmCompilationUnit(wasm::ErrorThrower* thrower,
+                                         Isolate* isolate,
+                                         wasm::ModuleEnv* module_env,
+                                         const wasm::WasmFunction* function,
+                                         uint32_t index)
+    : thrower_(thrower),
+      isolate_(isolate),
+      module_env_(module_env),
+      function_(function),
+      graph_zone_(new Zone(isolate->allocator())),
+      jsgraph_(new (graph_zone()) JSGraph(
+          isolate, new (graph_zone()) Graph(graph_zone()),
+          new (graph_zone()) CommonOperatorBuilder(graph_zone()), nullptr,
+          nullptr, new (graph_zone()) MachineOperatorBuilder(
+                       graph_zone(), MachineType::PointerRepresentation(),
+                       InstructionSelector::SupportedMachineOperatorFlags()))),
+      compilation_zone_(isolate->allocator()),
+      info_(function->name_length != 0
+                ? module_env->module->GetNameOrNull(function->name_offset,
+                                                    function->name_length)
+                : ArrayVector("wasm"),
+            isolate, &compilation_zone_,
+            Code::ComputeFlags(Code::WASM_FUNCTION)),
+      job_(),
+      index_(index),
+      ok_(true) {
+  // Create and cache this node in the main thread.
+  jsgraph_->CEntryStubConstant(1);
+}
+
+void WasmCompilationUnit::ExecuteCompilation() {
+  // TODO(ahaas): The counters are not thread-safe at the moment.
+  //    HistogramTimerScope wasm_compile_function_time_scope(
+  //        isolate_->counters()->wasm_compile_function_time());
+  if (FLAG_trace_wasm_compiler) {
+    OFStream os(stdout);
+    os << "Compiling WASM function "
+       << wasm::WasmFunctionName(function_, module_env_) << std::endl;
+    os << std::endl;
+  }
+
+  double decode_ms = 0;
+  size_t node_count = 0;
+
+  base::SmartPointer<Zone> graph_zone(graph_zone_.Detach());
+  SourcePositionTable* source_positions = BuildGraphForWasmFunction(&decode_ms);
+
+  if (graph_construction_result_.failed()) {
+    ok_ = false;
+    return;
+  }
+
+  base::ElapsedTimer pipeline_timer;
+  if (FLAG_trace_wasm_decode_time) {
+    node_count = jsgraph_->graph()->NodeCount();
+    pipeline_timer.Start();
+  }
+
+  // Run the compiler pipeline to generate machine code.
+  CallDescriptor* descriptor = wasm::ModuleEnv::GetWasmCallDescriptor(
+      &compilation_zone_, function_->sig);
+  if (jsgraph_->machine()->Is32()) {
+    descriptor =
+        module_env_->GetI32WasmCallDescriptor(&compilation_zone_, descriptor);
+  }
+  job_.Reset(Pipeline::NewWasmCompilationJob(&info_, jsgraph_->graph(),
+                                             descriptor, source_positions));
+
+  // The function name {OptimizeGraph()} is misleading but necessary because we
+  // want to use the CompilationJob interface. A better name would be
+  // ScheduleGraphAndSelectInstructions.
+  ok_ = job_->OptimizeGraph() == CompilationJob::SUCCEEDED;
+  // TODO(bradnelson): Improve histogram handling of size_t.
+  // TODO(ahaas): The counters are not thread-safe at the moment.
+  //    isolate_->counters()->wasm_compile_function_peak_memory_bytes()
+  // ->AddSample(
+  //        static_cast<int>(jsgraph->graph()->zone()->allocation_size()));
+
   if (FLAG_trace_wasm_decode_time) {
-    decode_ms = decode_timer.Elapsed().InMillisecondsF();
+    double pipeline_ms = pipeline_timer.Elapsed().InMillisecondsF();
+    PrintF(
+        "wasm-compilation phase 1 ok: %d bytes, %0.3f ms decode, %zu nodes, "
+        "%0.3f ms pipeline\n",
+        static_cast<int>(function_->code_end_offset -
+                         function_->code_start_offset),
+        decode_ms, node_count, pipeline_ms);
   }
+}
 
+Handle<Code> WasmCompilationUnit::FinishCompilation() {
+  if (!ok_) {
+    if (graph_construction_result_.failed()) {
+      // Add the function as another context for the exception
+      ScopedVector<char> buffer(128);
+      wasm::WasmName name = module_env_->module->GetName(
+          function_->name_offset, function_->name_length);
+      SNPrintF(buffer, "Compiling WASM function #%d:%.*s failed:",
+               function_->func_index, name.length(), name.start());
+      thrower_->Failed(buffer.start(), graph_construction_result_);
+    }
+
+    return Handle<Code>::null();
+  }
+  if (job_->GenerateCode() != CompilationJob::SUCCEEDED) {
+    return Handle<Code>::null();
+  }
   base::ElapsedTimer compile_timer;
   if (FLAG_trace_wasm_decode_time) {
     compile_timer.Start();
   }
-  // Run the compiler pipeline to generate machine code.
-  CallDescriptor* descriptor =
-      wasm::ModuleEnv::GetWasmCallDescriptor(&zone, function.sig);
-  if (machine.Is32()) {
-    descriptor = module_env->GetI32WasmCallDescriptor(&zone, descriptor);
-  }
-  Code::Flags flags = Code::ComputeFlags(Code::WASM_FUNCTION);
-  // add flags here if a meaningful name is helpful for debugging.
-  bool debugging =
-#if DEBUG
-      true;
-#else
-      FLAG_print_opt_code || FLAG_trace_turbo || FLAG_trace_turbo_graph;
-#endif
-  const char* func_name = "wasm";
-  Vector<char> buffer;
-  if (debugging) {
-    buffer = Vector<char>::New(128);
-    wasm::WasmName name =
-        module_env->module->GetName(function.name_offset, function.name_length);
-    SNPrintF(buffer, "WASM_function_#%d:%.*s", function.func_index, name.length,
-             name.name);
-    func_name = buffer.start();
-  }
-  CompilationInfo info(func_name, isolate, &zone, flags);
+  Handle<Code> code = info_.code();
+  DCHECK(!code.is_null());
 
-  Handle<Code> code =
-      Pipeline::GenerateCodeForTesting(&info, descriptor, &graph);
-  if (debugging) {
-    buffer.Dispose();
-  }
-  if (!code.is_null()) {
-    RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, "WASM_function",
-                              function.func_index,
-                              module_env->module->GetName(
-                                  function.name_offset, function.name_length));
-  }
+  RecordFunctionCompilation(
+      CodeEventListener::FUNCTION_TAG, &info_, "WASM_function",
+      function_->func_index,
+      module_env_->module->GetName(function_->name_offset,
+                                   function_->name_length));
 
   if (FLAG_trace_wasm_decode_time) {
     double compile_ms = compile_timer.Elapsed().InMillisecondsF();
-    PrintF(
-        "wasm-compile ok: %d bytes, %0.3f ms decode, %d nodes, %0.3f ms "
-        "compile\n",
-        static_cast<int>(function.code_end_offset - function.code_start_offset),
-        decode_ms, static_cast<int>(graph.NodeCount()), compile_ms);
+    PrintF("wasm-code-generation ok: %d bytes, %0.3f ms code generation\n",
+           static_cast<int>(function_->code_end_offset -
+                            function_->code_start_offset),
+           compile_ms);
   }
+
   return code;
 }
 
-
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/src/compiler/wasm-compiler.h b/src/compiler/wasm-compiler.h
index bbcafa7..c03de3d 100644
--- a/src/compiler/wasm-compiler.h
+++ b/src/compiler/wasm-compiler.h
@@ -7,7 +7,9 @@
 
 // Clients of this interface shouldn't depend on lots of compiler internals.
 // Do not include anything from src/compiler here!
+#include "src/compiler.h"
 #include "src/wasm/wasm-opcodes.h"
+#include "src/wasm/wasm-result.h"
 #include "src/zone.h"
 
 namespace v8 {
@@ -18,27 +20,64 @@
 class Node;
 class JSGraph;
 class Graph;
-}
+class Operator;
+class SourcePositionTable;
+}  // namespace compiler
 
 namespace wasm {
 // Forward declarations for some WASM data structures.
 struct ModuleEnv;
 struct WasmFunction;
 class ErrorThrower;
+struct Tree;
 
 // Expose {Node} and {Graph} opaquely as {wasm::TFNode} and {wasm::TFGraph}.
 typedef compiler::Node TFNode;
 typedef compiler::JSGraph TFGraph;
-}
+}  // namespace wasm
 
 namespace compiler {
-// Compiles a single function, producing a code object.
-Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
-                                 wasm::ModuleEnv* module_env,
-                                 const wasm::WasmFunction& function);
+class WasmCompilationUnit final {
+ public:
+  WasmCompilationUnit(wasm::ErrorThrower* thrower, Isolate* isolate,
+                      wasm::ModuleEnv* module_env,
+                      const wasm::WasmFunction* function, uint32_t index);
+
+  Zone* graph_zone() { return graph_zone_.get(); }
+  int index() const { return index_; }
+
+  void ExecuteCompilation();
+  Handle<Code> FinishCompilation();
+
+  static Handle<Code> CompileWasmFunction(wasm::ErrorThrower* thrower,
+                                          Isolate* isolate,
+                                          wasm::ModuleEnv* module_env,
+                                          const wasm::WasmFunction* function) {
+    WasmCompilationUnit unit(thrower, isolate, module_env, function, 0);
+    unit.ExecuteCompilation();
+    return unit.FinishCompilation();
+  }
+
+ private:
+  SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms);
+
+  wasm::ErrorThrower* thrower_;
+  Isolate* isolate_;
+  wasm::ModuleEnv* module_env_;
+  const wasm::WasmFunction* function_;
+  // The graph zone is deallocated at the end of ExecuteCompilation.
+  base::SmartPointer<Zone> graph_zone_;
+  JSGraph* jsgraph_;
+  Zone compilation_zone_;
+  CompilationInfo info_;
+  base::SmartPointer<CompilationJob> job_;
+  uint32_t index_;
+  wasm::Result<wasm::Tree*> graph_construction_result_;
+  bool ok_;
+};
 
 // Wraps a JS function, producing a code object that can be called from WASM.
-Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module,
+Handle<Code> CompileWasmToJSWrapper(Isolate* isolate,
                                     Handle<JSFunction> function,
                                     wasm::FunctionSig* sig,
                                     wasm::WasmName module_name,
@@ -55,7 +94,9 @@
 class WasmTrapHelper;
 class WasmGraphBuilder {
  public:
-  WasmGraphBuilder(Zone* z, JSGraph* g, wasm::FunctionSig* function_signature);
+  WasmGraphBuilder(
+      Zone* z, JSGraph* g, wasm::FunctionSig* function_signature,
+      compiler::SourcePositionTable* source_position_table = nullptr);
 
   Node** Buffer(size_t count) {
     if (count > cur_bufsize_) {
@@ -78,17 +119,20 @@
   Node* Merge(unsigned count, Node** controls);
   Node* Phi(wasm::LocalType type, unsigned count, Node** vals, Node* control);
   Node* EffectPhi(unsigned count, Node** effects, Node* control);
+  Node* NumberConstant(int32_t value);
   Node* Int32Constant(int32_t value);
   Node* Int64Constant(int64_t value);
   Node* Float32Constant(float value);
   Node* Float64Constant(double value);
-  Node* Constant(Handle<Object> value);
-  Node* Binop(wasm::WasmOpcode opcode, Node* left, Node* right);
-  Node* Unop(wasm::WasmOpcode opcode, Node* input);
+  Node* HeapConstant(Handle<HeapObject> value);
+  Node* Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
+              wasm::WasmCodePosition position = wasm::kNoCodePosition);
+  Node* Unop(wasm::WasmOpcode opcode, Node* input,
+             wasm::WasmCodePosition position = wasm::kNoCodePosition);
   unsigned InputCount(Node* node);
   bool IsPhiWithMerge(Node* phi, Node* merge);
   void AppendToMerge(Node* merge, Node* from);
-  void AppendToPhi(Node* merge, Node* phi, Node* from);
+  void AppendToPhi(Node* phi, Node* from);
 
   //-----------------------------------------------------------------------
   // Operations that read and/or write {control} and {effect}.
@@ -99,14 +143,18 @@
   Node* IfDefault(Node* sw);
   Node* Return(unsigned count, Node** vals);
   Node* ReturnVoid();
-  Node* Unreachable();
+  Node* Unreachable(wasm::WasmCodePosition position);
 
-  Node* CallDirect(uint32_t index, Node** args);
-  Node* CallImport(uint32_t index, Node** args);
-  Node* CallIndirect(uint32_t index, Node** args);
+  Node* CallDirect(uint32_t index, Node** args,
+                   wasm::WasmCodePosition position);
+  Node* CallImport(uint32_t index, Node** args,
+                   wasm::WasmCodePosition position);
+  Node* CallIndirect(uint32_t index, Node** args,
+                     wasm::WasmCodePosition position);
   void BuildJSToWasmWrapper(Handle<Code> wasm_code, wasm::FunctionSig* sig);
   void BuildWasmToJSWrapper(Handle<JSFunction> function,
                             wasm::FunctionSig* sig);
+
   Node* ToJS(Node* node, Node* context, wasm::LocalType type);
   Node* FromJS(Node* node, Node* context, wasm::LocalType type);
   Node* Invert(Node* node);
@@ -119,8 +167,11 @@
   Node* LoadGlobal(uint32_t index);
   Node* StoreGlobal(uint32_t index, Node* val);
   Node* LoadMem(wasm::LocalType type, MachineType memtype, Node* index,
-                uint32_t offset);
-  Node* StoreMem(MachineType type, Node* index, uint32_t offset, Node* val);
+                uint32_t offset, uint32_t alignment,
+                wasm::WasmCodePosition position);
+  Node* StoreMem(MachineType type, Node* index, uint32_t offset,
+                 uint32_t alignment, Node* val,
+                 wasm::WasmCodePosition position);
 
   static void PrintDebugName(Node* node);
 
@@ -137,6 +188,8 @@
 
   void Int64LoweringForTesting();
 
+  void SetSourcePosition(Node* node, wasm::WasmCodePosition position);
+
  private:
   static const int kDefaultBufferSize = 16;
   friend class WasmTrapHelper;
@@ -155,6 +208,9 @@
 
   WasmTrapHelper* trap_;
   wasm::FunctionSig* function_signature_;
+  SetOncePointer<const Operator> allocate_heap_number_operator_;
+
+  compiler::SourcePositionTable* source_position_table_ = nullptr;
 
   // Internal helper methods.
   JSGraph* jsgraph() { return jsgraph_; }
@@ -162,13 +218,28 @@
 
   Node* String(const char* string);
   Node* MemBuffer(uint32_t offset);
-  void BoundsCheckMem(MachineType memtype, Node* index, uint32_t offset);
+  void BoundsCheckMem(MachineType memtype, Node* index, uint32_t offset,
+                      wasm::WasmCodePosition position);
+
+  MachineType GetTypeForUnalignedAccess(uint32_t alignment,
+                                        bool signExtend = false);
+
+  Node* GetUnalignedLoadOffsetNode(Node* baseOffset, int numberOfBytes,
+                                   int stride, int current);
+
+  Node* BuildUnalignedLoad(wasm::LocalType type, MachineType memtype,
+                           Node* index, uint32_t offset, uint32_t alignment);
+  Node* GetUnalignedStoreOffsetNode(Node* baseOffset, int numberOfBytes,
+                                    int stride, int current);
+  Node* BuildUnalignedStore(MachineType memtype, Node* index, uint32_t offset,
+                            uint32_t alignment, Node* val);
 
   Node* MaskShiftCount32(Node* node);
   Node* MaskShiftCount64(Node* node);
 
   Node* BuildCCall(MachineSignature* sig, Node** args);
-  Node* BuildWasmCall(wasm::FunctionSig* sig, Node** args);
+  Node* BuildWasmCall(wasm::FunctionSig* sig, Node** args,
+                      wasm::WasmCodePosition position);
 
   Node* BuildF32Neg(Node* input);
   Node* BuildF64Neg(Node* input);
@@ -178,14 +249,17 @@
   Node* BuildF32Max(Node* left, Node* right);
   Node* BuildF64Min(Node* left, Node* right);
   Node* BuildF64Max(Node* left, Node* right);
-  Node* BuildI32SConvertF32(Node* input);
-  Node* BuildI32SConvertF64(Node* input);
-  Node* BuildI32UConvertF32(Node* input);
-  Node* BuildI32UConvertF64(Node* input);
+  Node* BuildI32SConvertF32(Node* input, wasm::WasmCodePosition position);
+  Node* BuildI32SConvertF64(Node* input, wasm::WasmCodePosition position);
+  Node* BuildI32UConvertF32(Node* input, wasm::WasmCodePosition position);
+  Node* BuildI32UConvertF64(Node* input, wasm::WasmCodePosition position);
   Node* BuildI32Ctz(Node* input);
   Node* BuildI32Popcnt(Node* input);
   Node* BuildI64Ctz(Node* input);
   Node* BuildI64Popcnt(Node* input);
+  Node* BuildBitCountingCall(Node* input, ExternalReference ref,
+                             MachineRepresentation input_type);
+
   Node* BuildCFuncInstruction(ExternalReference ref, MachineType type,
                               Node* input0, Node* input1 = nullptr);
   Node* BuildF32Trunc(Node* input);
@@ -201,14 +275,7 @@
 
   Node* BuildF64Acos(Node* input);
   Node* BuildF64Asin(Node* input);
-  Node* BuildF64Atan(Node* input);
-  Node* BuildF64Cos(Node* input);
-  Node* BuildF64Sin(Node* input);
-  Node* BuildF64Tan(Node* input);
-  Node* BuildF64Exp(Node* input);
-  Node* BuildF64Log(Node* input);
   Node* BuildF64Pow(Node* left, Node* right);
-  Node* BuildF64Atan2(Node* left, Node* right);
   Node* BuildF64Mod(Node* left, Node* right);
 
   Node* BuildIntToFloatConversionInstruction(
@@ -223,23 +290,52 @@
   Node* BuildFloatToIntConversionInstruction(
       Node* input, ExternalReference ref,
       MachineRepresentation parameter_representation,
-      const MachineType result_type);
-  Node* BuildI64SConvertF32(Node* input);
-  Node* BuildI64UConvertF32(Node* input);
-  Node* BuildI64SConvertF64(Node* input);
-  Node* BuildI64UConvertF64(Node* input);
+      const MachineType result_type, wasm::WasmCodePosition position);
+  Node* BuildI64SConvertF32(Node* input, wasm::WasmCodePosition position);
+  Node* BuildI64UConvertF32(Node* input, wasm::WasmCodePosition position);
+  Node* BuildI64SConvertF64(Node* input, wasm::WasmCodePosition position);
+  Node* BuildI64UConvertF64(Node* input, wasm::WasmCodePosition position);
 
-  Node* BuildI32DivS(Node* left, Node* right);
-  Node* BuildI32RemS(Node* left, Node* right);
-  Node* BuildI32DivU(Node* left, Node* right);
-  Node* BuildI32RemU(Node* left, Node* right);
+  Node* BuildI32DivS(Node* left, Node* right, wasm::WasmCodePosition position);
+  Node* BuildI32RemS(Node* left, Node* right, wasm::WasmCodePosition position);
+  Node* BuildI32DivU(Node* left, Node* right, wasm::WasmCodePosition position);
+  Node* BuildI32RemU(Node* left, Node* right, wasm::WasmCodePosition position);
 
-  Node* BuildI64DivS(Node* left, Node* right);
-  Node* BuildI64RemS(Node* left, Node* right);
-  Node* BuildI64DivU(Node* left, Node* right);
-  Node* BuildI64RemU(Node* left, Node* right);
+  Node* BuildI64DivS(Node* left, Node* right, wasm::WasmCodePosition position);
+  Node* BuildI64RemS(Node* left, Node* right, wasm::WasmCodePosition position);
+  Node* BuildI64DivU(Node* left, Node* right, wasm::WasmCodePosition position);
+  Node* BuildI64RemU(Node* left, Node* right, wasm::WasmCodePosition position);
   Node* BuildDiv64Call(Node* left, Node* right, ExternalReference ref,
-                       MachineType result_type, int trap_zero);
+                       MachineType result_type, int trap_zero,
+                       wasm::WasmCodePosition position);
+
+  Node* BuildJavaScriptToNumber(Node* node, Node* context, Node* effect,
+                                Node* control);
+  Node* BuildChangeInt32ToTagged(Node* value);
+  Node* BuildChangeFloat64ToTagged(Node* value);
+  Node* BuildChangeTaggedToFloat64(Node* value);
+
+  Node* BuildChangeInt32ToSmi(Node* value);
+  Node* BuildChangeSmiToInt32(Node* value);
+  Node* BuildChangeSmiToFloat64(Node* value);
+  Node* BuildTestNotSmi(Node* value);
+  Node* BuildSmiShiftBitsConstant();
+
+  Node* BuildAllocateHeapNumberWithValue(Node* value, Node* control);
+  Node* BuildLoadHeapNumberValue(Node* value, Node* control);
+  Node* BuildHeapNumberValueIndexConstant();
+
+  // Asm.js specific functionality.
+  Node* BuildI32AsmjsSConvertF32(Node* input);
+  Node* BuildI32AsmjsSConvertF64(Node* input);
+  Node* BuildI32AsmjsUConvertF32(Node* input);
+  Node* BuildI32AsmjsUConvertF64(Node* input);
+  Node* BuildI32AsmjsDivS(Node* left, Node* right);
+  Node* BuildI32AsmjsRemS(Node* left, Node* right);
+  Node* BuildI32AsmjsDivU(Node* left, Node* right);
+  Node* BuildI32AsmjsRemU(Node* left, Node* right);
+  Node* BuildAsmjsLoadMem(MachineType type, Node* index);
+  Node* BuildAsmjsStoreMem(MachineType type, Node* index, Node* val);
 
   Node** Realloc(Node** buffer, size_t old_count, size_t new_count) {
     Node** buf = Buffer(new_count);
diff --git a/src/compiler/wasm-linkage.cc b/src/compiler/wasm-linkage.cc
index f0e14ce..cfeb6c5 100644
--- a/src/compiler/wasm-linkage.cc
+++ b/src/compiler/wasm-linkage.cc
@@ -4,6 +4,7 @@
 
 #include "src/assembler.h"
 #include "src/macro-assembler.h"
+#include "src/register-configuration.h"
 
 #include "src/wasm/wasm-module.h"
 
@@ -31,6 +32,8 @@
       return MachineType::Float64();
     case kAstF32:
       return MachineType::Float32();
+    case kAstS128:
+      return MachineType::Simd128();
     default:
       UNREACHABLE();
       return MachineType::AnyTagged();
@@ -58,7 +61,7 @@
 // ===========================================================================
 // == ia32 ===================================================================
 // ===========================================================================
-#define GP_PARAM_REGISTERS eax, edx, ecx, ebx
+#define GP_PARAM_REGISTERS eax, edx, ecx, ebx, esi
 #define GP_RETURN_REGISTERS eax, edx
 #define FP_PARAM_REGISTERS xmm1, xmm2, xmm3, xmm4, xmm5, xmm6
 #define FP_RETURN_REGISTERS xmm1, xmm2
@@ -176,7 +179,18 @@
     if (IsFloatingPoint(type)) {
       // Allocate a floating point register/stack location.
       if (fp_offset < fp_count) {
-        return regloc(fp_regs[fp_offset++]);
+        DoubleRegister reg = fp_regs[fp_offset++];
+#if V8_TARGET_ARCH_ARM
+        // Allocate floats using a double register, but modify the code to
+        // reflect how ARM FP registers alias.
+        // TODO(bbudge) Modify wasm linkage to allow use of all float regs.
+        if (type == kAstF32) {
+          int float_reg_code = reg.code() * 2;
+          DCHECK(float_reg_code < RegisterConfiguration::kMaxFPRegisters);
+          return regloc(DoubleRegister::from_code(float_reg_code));
+        }
+#endif
+        return regloc(reg);
       } else {
         int offset = -1 - stack_offset;
         stack_offset += Words(type);
@@ -197,11 +211,7 @@
     return type == kAstF32 || type == kAstF64;
   }
   int Words(LocalType type) {
-    // The code generation for pushing parameters on the stack does not
-    // distinguish between float32 and float64. Therefore also float32 needs
-    // two words.
-    if (kPointerSize < 8 &&
-        (type == kAstI64 || type == kAstF64 || type == kAstF32)) {
+    if (kPointerSize < 8 && (type == kAstI64 || type == kAstF64)) {
       return 2;
     }
     return 1;
diff --git a/src/compiler/x64/code-generator-x64.cc b/src/compiler/x64/code-generator-x64.cc
index 2e4eccb..2ae1fc9 100644
--- a/src/compiler/x64/code-generator-x64.cc
+++ b/src/compiler/x64/code-generator-x64.cc
@@ -18,10 +18,6 @@
 
 #define __ masm()->
 
-
-#define kScratchDoubleReg xmm0
-
-
 // Adds X64 specific methods for decoding operands.
 class X64OperandConverter : public InstructionOperandConverter {
  public:
@@ -44,11 +40,16 @@
       DCHECK_EQ(0, bit_cast<int64_t>(constant.ToFloat64()));
       return Immediate(0);
     }
+    if (constant.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
+        constant.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE ||
+        constant.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE) {
+      return Immediate(constant.ToInt32(), constant.rmode());
+    }
     return Immediate(constant.ToInt32());
   }
 
   Operand ToOperand(InstructionOperand* op, int extra = 0) {
-    DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
+    DCHECK(op->IsStackSlot() || op->IsFPStackSlot());
     return SlotToOperand(AllocatedOperand::cast(op)->index(), extra);
   }
 
@@ -341,31 +342,28 @@
     }                                                       \
   } while (0)
 
-
 #define ASSEMBLE_SSE_BINOP(asm_instr)                                   \
   do {                                                                  \
-    if (instr->InputAt(1)->IsDoubleRegister()) {                        \
+    if (instr->InputAt(1)->IsFPRegister()) {                            \
       __ asm_instr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \
     } else {                                                            \
       __ asm_instr(i.InputDoubleRegister(0), i.InputOperand(1));        \
     }                                                                   \
   } while (0)
 
-
 #define ASSEMBLE_SSE_UNOP(asm_instr)                                    \
   do {                                                                  \
-    if (instr->InputAt(0)->IsDoubleRegister()) {                        \
+    if (instr->InputAt(0)->IsFPRegister()) {                            \
       __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
     } else {                                                            \
       __ asm_instr(i.OutputDoubleRegister(), i.InputOperand(0));        \
     }                                                                   \
   } while (0)
 
-
 #define ASSEMBLE_AVX_BINOP(asm_instr)                                  \
   do {                                                                 \
     CpuFeatureScope avx_scope(masm(), AVX);                            \
-    if (instr->InputAt(1)->IsDoubleRegister()) {                       \
+    if (instr->InputAt(1)->IsFPRegister()) {                           \
       __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \
                    i.InputDoubleRegister(1));                          \
     } else {                                                           \
@@ -374,13 +372,12 @@
     }                                                                  \
   } while (0)
 
-
 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr)                               \
   do {                                                                       \
     auto result = i.OutputDoubleRegister();                                  \
     auto buffer = i.InputRegister(0);                                        \
     auto index1 = i.InputRegister(1);                                        \
-    auto index2 = i.InputInt32(2);                                           \
+    auto index2 = i.InputUint32(2);                                          \
     OutOfLineCode* ool;                                                      \
     if (instr->InputAt(3)->IsRegister()) {                                   \
       auto length = i.InputRegister(3);                                      \
@@ -388,25 +385,27 @@
       __ cmpl(index1, length);                                               \
       ool = new (zone()) OutOfLineLoadNaN(this, result);                     \
     } else {                                                                 \
-      auto length = i.InputInt32(3);                                         \
+      auto length = i.InputUint32(3);                                        \
+      RelocInfo::Mode rmode = i.ToConstant(instr->InputAt(3)).rmode();       \
       DCHECK_LE(index2, length);                                             \
-      __ cmpq(index1, Immediate(length - index2));                           \
+      __ cmpl(index1, Immediate(length - index2, rmode));                    \
       class OutOfLineLoadFloat final : public OutOfLineCode {                \
        public:                                                               \
         OutOfLineLoadFloat(CodeGenerator* gen, XMMRegister result,           \
                            Register buffer, Register index1, int32_t index2, \
-                           int32_t length)                                   \
+                           int32_t length, RelocInfo::Mode rmode)            \
             : OutOfLineCode(gen),                                            \
               result_(result),                                               \
               buffer_(buffer),                                               \
               index1_(index1),                                               \
               index2_(index2),                                               \
-              length_(length) {}                                             \
+              length_(length),                                               \
+              rmode_(rmode) {}                                               \
                                                                              \
         void Generate() final {                                              \
           __ leal(kScratchRegister, Operand(index1_, index2_));              \
           __ Pcmpeqd(result_, result_);                                      \
-          __ cmpl(kScratchRegister, Immediate(length_));                     \
+          __ cmpl(kScratchRegister, Immediate(length_, rmode_));             \
           __ j(above_equal, exit());                                         \
           __ asm_instr(result_,                                              \
                        Operand(buffer_, kScratchRegister, times_1, 0));      \
@@ -418,22 +417,22 @@
         Register const index1_;                                              \
         int32_t const index2_;                                               \
         int32_t const length_;                                               \
+        RelocInfo::Mode rmode_;                                              \
       };                                                                     \
-      ool = new (zone())                                                     \
-          OutOfLineLoadFloat(this, result, buffer, index1, index2, length);  \
+      ool = new (zone()) OutOfLineLoadFloat(this, result, buffer, index1,    \
+                                            index2, length, rmode);          \
     }                                                                        \
     __ j(above_equal, ool->entry());                                         \
     __ asm_instr(result, Operand(buffer, index1, times_1, index2));          \
     __ bind(ool->exit());                                                    \
   } while (false)
 
-
 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr)                               \
   do {                                                                         \
     auto result = i.OutputRegister();                                          \
     auto buffer = i.InputRegister(0);                                          \
     auto index1 = i.InputRegister(1);                                          \
-    auto index2 = i.InputInt32(2);                                             \
+    auto index2 = i.InputUint32(2);                                            \
     OutOfLineCode* ool;                                                        \
     if (instr->InputAt(3)->IsRegister()) {                                     \
       auto length = i.InputRegister(3);                                        \
@@ -441,25 +440,27 @@
       __ cmpl(index1, length);                                                 \
       ool = new (zone()) OutOfLineLoadZero(this, result);                      \
     } else {                                                                   \
-      auto length = i.InputInt32(3);                                           \
+      auto length = i.InputUint32(3);                                          \
+      RelocInfo::Mode rmode = i.ToConstant(instr->InputAt(3)).rmode();         \
       DCHECK_LE(index2, length);                                               \
-      __ cmpq(index1, Immediate(length - index2));                             \
+      __ cmpl(index1, Immediate(length - index2, rmode));                      \
       class OutOfLineLoadInteger final : public OutOfLineCode {                \
        public:                                                                 \
         OutOfLineLoadInteger(CodeGenerator* gen, Register result,              \
                              Register buffer, Register index1, int32_t index2, \
-                             int32_t length)                                   \
+                             int32_t length, RelocInfo::Mode rmode)            \
             : OutOfLineCode(gen),                                              \
               result_(result),                                                 \
               buffer_(buffer),                                                 \
               index1_(index1),                                                 \
               index2_(index2),                                                 \
-              length_(length) {}                                               \
+              length_(length),                                                 \
+              rmode_(rmode) {}                                                 \
                                                                                \
         void Generate() final {                                                \
           Label oob;                                                           \
           __ leal(kScratchRegister, Operand(index1_, index2_));                \
-          __ cmpl(kScratchRegister, Immediate(length_));                       \
+          __ cmpl(kScratchRegister, Immediate(length_, rmode_));               \
           __ j(above_equal, &oob, Label::kNear);                               \
           __ asm_instr(result_,                                                \
                        Operand(buffer_, kScratchRegister, times_1, 0));        \
@@ -474,21 +475,21 @@
         Register const index1_;                                                \
         int32_t const index2_;                                                 \
         int32_t const length_;                                                 \
+        RelocInfo::Mode const rmode_;                                          \
       };                                                                       \
-      ool = new (zone())                                                       \
-          OutOfLineLoadInteger(this, result, buffer, index1, index2, length);  \
+      ool = new (zone()) OutOfLineLoadInteger(this, result, buffer, index1,    \
+                                              index2, length, rmode);          \
     }                                                                          \
     __ j(above_equal, ool->entry());                                           \
     __ asm_instr(result, Operand(buffer, index1, times_1, index2));            \
     __ bind(ool->exit());                                                      \
   } while (false)
 
-
 #define ASSEMBLE_CHECKED_STORE_FLOAT(asm_instr)                              \
   do {                                                                       \
     auto buffer = i.InputRegister(0);                                        \
     auto index1 = i.InputRegister(1);                                        \
-    auto index2 = i.InputInt32(2);                                           \
+    auto index2 = i.InputUint32(2);                                          \
     auto value = i.InputDoubleRegister(4);                                   \
     if (instr->InputAt(3)->IsRegister()) {                                   \
       auto length = i.InputRegister(3);                                      \
@@ -499,24 +500,26 @@
       __ asm_instr(Operand(buffer, index1, times_1, index2), value);         \
       __ bind(&done);                                                        \
     } else {                                                                 \
-      auto length = i.InputInt32(3);                                         \
+      auto length = i.InputUint32(3);                                        \
+      RelocInfo::Mode rmode = i.ToConstant(instr->InputAt(3)).rmode();       \
       DCHECK_LE(index2, length);                                             \
-      __ cmpq(index1, Immediate(length - index2));                           \
+      __ cmpl(index1, Immediate(length - index2, rmode));                    \
       class OutOfLineStoreFloat final : public OutOfLineCode {               \
        public:                                                               \
         OutOfLineStoreFloat(CodeGenerator* gen, Register buffer,             \
                             Register index1, int32_t index2, int32_t length, \
-                            XMMRegister value)                               \
+                            XMMRegister value, RelocInfo::Mode rmode)        \
             : OutOfLineCode(gen),                                            \
               buffer_(buffer),                                               \
               index1_(index1),                                               \
               index2_(index2),                                               \
               length_(length),                                               \
-              value_(value) {}                                               \
+              value_(value),                                                 \
+              rmode_(rmode) {}                                               \
                                                                              \
         void Generate() final {                                              \
           __ leal(kScratchRegister, Operand(index1_, index2_));              \
-          __ cmpl(kScratchRegister, Immediate(length_));                     \
+          __ cmpl(kScratchRegister, Immediate(length_, rmode_));             \
           __ j(above_equal, exit());                                         \
           __ asm_instr(Operand(buffer_, kScratchRegister, times_1, 0),       \
                        value_);                                              \
@@ -528,21 +531,21 @@
         int32_t const index2_;                                               \
         int32_t const length_;                                               \
         XMMRegister const value_;                                            \
+        RelocInfo::Mode rmode_;                                              \
       };                                                                     \
-      auto ool = new (zone())                                                \
-          OutOfLineStoreFloat(this, buffer, index1, index2, length, value);  \
+      auto ool = new (zone()) OutOfLineStoreFloat(                           \
+          this, buffer, index1, index2, length, value, rmode);               \
       __ j(above_equal, ool->entry());                                       \
       __ asm_instr(Operand(buffer, index1, times_1, index2), value);         \
       __ bind(ool->exit());                                                  \
     }                                                                        \
   } while (false)
 
-
 #define ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Value)                  \
   do {                                                                         \
     auto buffer = i.InputRegister(0);                                          \
     auto index1 = i.InputRegister(1);                                          \
-    auto index2 = i.InputInt32(2);                                             \
+    auto index2 = i.InputUint32(2);                                            \
     if (instr->InputAt(3)->IsRegister()) {                                     \
       auto length = i.InputRegister(3);                                        \
       DCHECK_EQ(0, index2);                                                    \
@@ -552,24 +555,26 @@
       __ asm_instr(Operand(buffer, index1, times_1, index2), value);           \
       __ bind(&done);                                                          \
     } else {                                                                   \
-      auto length = i.InputInt32(3);                                           \
+      auto length = i.InputUint32(3);                                          \
+      RelocInfo::Mode rmode = i.ToConstant(instr->InputAt(3)).rmode();         \
       DCHECK_LE(index2, length);                                               \
-      __ cmpq(index1, Immediate(length - index2));                             \
+      __ cmpl(index1, Immediate(length - index2, rmode));                      \
       class OutOfLineStoreInteger final : public OutOfLineCode {               \
        public:                                                                 \
         OutOfLineStoreInteger(CodeGenerator* gen, Register buffer,             \
                               Register index1, int32_t index2, int32_t length, \
-                              Value value)                                     \
+                              Value value, RelocInfo::Mode rmode)              \
             : OutOfLineCode(gen),                                              \
               buffer_(buffer),                                                 \
               index1_(index1),                                                 \
               index2_(index2),                                                 \
               length_(length),                                                 \
-              value_(value) {}                                                 \
+              value_(value),                                                   \
+              rmode_(rmode) {}                                                 \
                                                                                \
         void Generate() final {                                                \
           __ leal(kScratchRegister, Operand(index1_, index2_));                \
-          __ cmpl(kScratchRegister, Immediate(length_));                       \
+          __ cmpl(kScratchRegister, Immediate(length_, rmode_));               \
           __ j(above_equal, exit());                                           \
           __ asm_instr(Operand(buffer_, kScratchRegister, times_1, 0),         \
                        value_);                                                \
@@ -581,16 +586,16 @@
         int32_t const index2_;                                                 \
         int32_t const length_;                                                 \
         Value const value_;                                                    \
+        RelocInfo::Mode rmode_;                                                \
       };                                                                       \
-      auto ool = new (zone())                                                  \
-          OutOfLineStoreInteger(this, buffer, index1, index2, length, value);  \
+      auto ool = new (zone()) OutOfLineStoreInteger(                           \
+          this, buffer, index1, index2, length, value, rmode);                 \
       __ j(above_equal, ool->entry());                                         \
       __ asm_instr(Operand(buffer, index1, times_1, index2), value);           \
       __ bind(ool->exit());                                                    \
     }                                                                          \
   } while (false)
 
-
 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr)                \
   do {                                                           \
     if (instr->InputAt(4)->IsRegister()) {                       \
@@ -602,13 +607,25 @@
     }                                                            \
   } while (false)
 
+#define ASSEMBLE_IEEE754_BINOP(name)                                          \
+  do {                                                                        \
+    __ PrepareCallCFunction(2);                                               \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \
+                     2);                                                      \
+  } while (false)
+
+#define ASSEMBLE_IEEE754_UNOP(name)                                           \
+  do {                                                                        \
+    __ PrepareCallCFunction(1);                                               \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \
+                     1);                                                      \
+  } while (false)
+
 void CodeGenerator::AssembleDeconstructFrame() {
   __ movq(rsp, rbp);
   __ popq(rbp);
 }
 
-void CodeGenerator::AssembleSetupStackPointer() {}
-
 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
   int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
   if (sp_slot_delta > 0) {
@@ -656,7 +673,8 @@
 }
 
 // Assembles an instruction after register allocation, producing machine code.
-void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
+CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
+    Instruction* instr) {
   X64OperandConverter i(this, instr);
   InstructionCode opcode = instr->opcode();
   ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode);
@@ -695,6 +713,15 @@
       frame_access_state()->ClearSPDelta();
       break;
     }
+    case kArchTailCallAddress: {
+      int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
+      AssembleDeconstructActivationRecord(stack_param_delta);
+      CHECK(!HasImmediateInput(instr, 0));
+      Register reg = i.InputRegister(0);
+      __ jmp(reg);
+      frame_access_state()->ClearSPDelta();
+      break;
+    }
     case kArchCallJSFunction: {
       EnsureSpaceForLazyDeopt();
       Register func = i.InputRegister(0);
@@ -759,6 +786,14 @@
     case kArchTableSwitch:
       AssembleArchTableSwitch(instr);
       break;
+    case kArchComment: {
+      Address comment_string = i.InputExternalReference(0).address();
+      __ RecordComment(reinterpret_cast<const char*>(comment_string));
+      break;
+    }
+    case kArchDebugBreak:
+      __ int3();
+      break;
     case kArchNop:
     case kArchThrowTerminator:
       // don't emit code for nops.
@@ -768,7 +803,9 @@
           BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
       Deoptimizer::BailoutType bailout_type =
           Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
-      AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      CodeGenResult result =
+          AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      if (result != kSuccess) return result;
       break;
     }
     case kArchRet:
@@ -791,10 +828,13 @@
       auto result = i.OutputRegister();
       auto input = i.InputDoubleRegister(0);
       auto ool = new (zone()) OutOfLineTruncateDoubleToI(this, result, input);
+      // We use Cvttsd2siq instead of Cvttsd2si due to performance reasons. The
+      // use of Cvttsd2siq requires the movl below to avoid sign extension.
       __ Cvttsd2siq(result, input);
       __ cmpq(result, Immediate(1));
       __ j(overflow, ool->entry());
       __ bind(ool->exit());
+      __ movl(result, result);
       break;
     }
     case kArchStoreWithWriteBarrier: {
@@ -827,6 +867,45 @@
       __ leaq(i.OutputRegister(), Operand(base, offset.offset()));
       break;
     }
+    case kIeee754Float64Atan:
+      ASSEMBLE_IEEE754_UNOP(atan);
+      break;
+    case kIeee754Float64Atan2:
+      ASSEMBLE_IEEE754_BINOP(atan2);
+      break;
+    case kIeee754Float64Atanh:
+      ASSEMBLE_IEEE754_UNOP(atanh);
+      break;
+    case kIeee754Float64Cbrt:
+      ASSEMBLE_IEEE754_UNOP(cbrt);
+      break;
+    case kIeee754Float64Cos:
+      ASSEMBLE_IEEE754_UNOP(cos);
+      break;
+    case kIeee754Float64Exp:
+      ASSEMBLE_IEEE754_UNOP(exp);
+      break;
+    case kIeee754Float64Expm1:
+      ASSEMBLE_IEEE754_UNOP(expm1);
+      break;
+    case kIeee754Float64Log:
+      ASSEMBLE_IEEE754_UNOP(log);
+      break;
+    case kIeee754Float64Log1p:
+      ASSEMBLE_IEEE754_UNOP(log1p);
+      break;
+    case kIeee754Float64Log2:
+      ASSEMBLE_IEEE754_UNOP(log2);
+      break;
+    case kIeee754Float64Log10:
+      ASSEMBLE_IEEE754_UNOP(log10);
+      break;
+    case kIeee754Float64Sin:
+      ASSEMBLE_IEEE754_UNOP(sin);
+      break;
+    case kIeee754Float64Tan:
+      ASSEMBLE_IEEE754_UNOP(tan);
+      break;
     case kX64Add32:
       ASSEMBLE_BINOP(addl);
       break;
@@ -1047,14 +1126,14 @@
       break;
     }
     case kSSEFloat32ToInt32:
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ Cvttss2si(i.OutputRegister(), i.InputDoubleRegister(0));
       } else {
         __ Cvttss2si(i.OutputRegister(), i.InputOperand(0));
       }
       break;
     case kSSEFloat32ToUint32: {
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ Cvttss2siq(i.OutputRegister(), i.InputDoubleRegister(0));
       } else {
         __ Cvttss2siq(i.OutputRegister(), i.InputOperand(0));
@@ -1145,14 +1224,14 @@
       ASSEMBLE_SSE_UNOP(Cvtsd2ss);
       break;
     case kSSEFloat64ToInt32:
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ Cvttsd2si(i.OutputRegister(), i.InputDoubleRegister(0));
       } else {
         __ Cvttsd2si(i.OutputRegister(), i.InputOperand(0));
       }
       break;
     case kSSEFloat64ToUint32: {
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ Cvttsd2siq(i.OutputRegister(), i.InputDoubleRegister(0));
       } else {
         __ Cvttsd2siq(i.OutputRegister(), i.InputOperand(0));
@@ -1163,7 +1242,7 @@
       break;
     }
     case kSSEFloat32ToInt64:
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ Cvttss2siq(i.OutputRegister(), i.InputDoubleRegister(0));
       } else {
         __ Cvttss2siq(i.OutputRegister(), i.InputOperand(0));
@@ -1173,7 +1252,7 @@
         Label done;
         Label fail;
         __ Move(kScratchDoubleReg, static_cast<float>(INT64_MIN));
-        if (instr->InputAt(0)->IsDoubleRegister()) {
+        if (instr->InputAt(0)->IsFPRegister()) {
           __ Ucomiss(kScratchDoubleReg, i.InputDoubleRegister(0));
         } else {
           __ Ucomiss(kScratchDoubleReg, i.InputOperand(0));
@@ -1192,7 +1271,7 @@
       }
       break;
     case kSSEFloat64ToInt64:
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ Cvttsd2siq(i.OutputRegister(0), i.InputDoubleRegister(0));
       } else {
         __ Cvttsd2siq(i.OutputRegister(0), i.InputOperand(0));
@@ -1202,7 +1281,7 @@
         Label done;
         Label fail;
         __ Move(kScratchDoubleReg, static_cast<double>(INT64_MIN));
-        if (instr->InputAt(0)->IsDoubleRegister()) {
+        if (instr->InputAt(0)->IsFPRegister()) {
           __ Ucomisd(kScratchDoubleReg, i.InputDoubleRegister(0));
         } else {
           __ Ucomisd(kScratchDoubleReg, i.InputOperand(0));
@@ -1228,7 +1307,7 @@
       }
       // There does not exist a Float32ToUint64 instruction, so we have to use
       // the Float32ToInt64 instruction.
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ Cvttss2siq(i.OutputRegister(), i.InputDoubleRegister(0));
       } else {
         __ Cvttss2siq(i.OutputRegister(), i.InputOperand(0));
@@ -1241,7 +1320,7 @@
       // input value was not within the positive int64 range. We subtract 2^64
       // and convert it again to see if it is within the uint64 range.
       __ Move(kScratchDoubleReg, -9223372036854775808.0f);
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ addss(kScratchDoubleReg, i.InputDoubleRegister(0));
       } else {
         __ addss(kScratchDoubleReg, i.InputOperand(0));
@@ -1271,7 +1350,7 @@
       }
       // There does not exist a Float64ToUint64 instruction, so we have to use
       // the Float64ToInt64 instruction.
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ Cvttsd2siq(i.OutputRegister(), i.InputDoubleRegister(0));
       } else {
         __ Cvttsd2siq(i.OutputRegister(), i.InputOperand(0));
@@ -1284,7 +1363,7 @@
       // input value was not within the positive int64 range. We subtract 2^64
       // and convert it again to see if it is within the uint64 range.
       __ Move(kScratchDoubleReg, -9223372036854775808.0);
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ addsd(kScratchDoubleReg, i.InputDoubleRegister(0));
       } else {
         __ addsd(kScratchDoubleReg, i.InputOperand(0));
@@ -1369,14 +1448,14 @@
       __ Cvtqsi2ss(i.OutputDoubleRegister(), kScratchRegister);
       break;
     case kSSEFloat64ExtractLowWord32:
-      if (instr->InputAt(0)->IsDoubleStackSlot()) {
+      if (instr->InputAt(0)->IsFPStackSlot()) {
         __ movl(i.OutputRegister(), i.InputOperand(0));
       } else {
         __ Movd(i.OutputRegister(), i.InputDoubleRegister(0));
       }
       break;
     case kSSEFloat64ExtractHighWord32:
-      if (instr->InputAt(0)->IsDoubleStackSlot()) {
+      if (instr->InputAt(0)->IsFPStackSlot()) {
         __ movl(i.OutputRegister(), i.InputOperand(0, kDoubleSize / 2));
       } else {
         __ Pextrd(i.OutputRegister(), i.InputDoubleRegister(0), 1);
@@ -1405,7 +1484,7 @@
       break;
     case kAVXFloat32Cmp: {
       CpuFeatureScope avx_scope(masm(), AVX);
-      if (instr->InputAt(1)->IsDoubleRegister()) {
+      if (instr->InputAt(1)->IsFPRegister()) {
         __ vucomiss(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
       } else {
         __ vucomiss(i.InputDoubleRegister(0), i.InputOperand(1));
@@ -1435,7 +1514,7 @@
       break;
     case kAVXFloat64Cmp: {
       CpuFeatureScope avx_scope(masm(), AVX);
-      if (instr->InputAt(1)->IsDoubleRegister()) {
+      if (instr->InputAt(1)->IsFPRegister()) {
         __ vucomisd(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
       } else {
         __ vucomisd(i.InputDoubleRegister(0), i.InputOperand(1));
@@ -1468,7 +1547,7 @@
       CpuFeatureScope avx_scope(masm(), AVX);
       __ vpcmpeqd(kScratchDoubleReg, kScratchDoubleReg, kScratchDoubleReg);
       __ vpsrlq(kScratchDoubleReg, kScratchDoubleReg, 33);
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ vandps(i.OutputDoubleRegister(), kScratchDoubleReg,
                   i.InputDoubleRegister(0));
       } else {
@@ -1482,7 +1561,7 @@
       CpuFeatureScope avx_scope(masm(), AVX);
       __ vpcmpeqd(kScratchDoubleReg, kScratchDoubleReg, kScratchDoubleReg);
       __ vpsllq(kScratchDoubleReg, kScratchDoubleReg, 31);
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ vxorps(i.OutputDoubleRegister(), kScratchDoubleReg,
                   i.InputDoubleRegister(0));
       } else {
@@ -1496,7 +1575,7 @@
       CpuFeatureScope avx_scope(masm(), AVX);
       __ vpcmpeqd(kScratchDoubleReg, kScratchDoubleReg, kScratchDoubleReg);
       __ vpsrlq(kScratchDoubleReg, kScratchDoubleReg, 1);
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ vandpd(i.OutputDoubleRegister(), kScratchDoubleReg,
                   i.InputDoubleRegister(0));
       } else {
@@ -1510,7 +1589,7 @@
       CpuFeatureScope avx_scope(masm(), AVX);
       __ vpcmpeqd(kScratchDoubleReg, kScratchDoubleReg, kScratchDoubleReg);
       __ vpsllq(kScratchDoubleReg, kScratchDoubleReg, 63);
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ vxorpd(i.OutputDoubleRegister(), kScratchDoubleReg,
                   i.InputDoubleRegister(0));
       } else {
@@ -1519,6 +1598,10 @@
       }
       break;
     }
+    case kSSEFloat64SilenceNaN:
+      __ Xorpd(kScratchDoubleReg, kScratchDoubleReg);
+      __ Subsd(i.InputDoubleRegister(0), kScratchDoubleReg);
+      break;
     case kX64Movsxbl:
       ASSEMBLE_MOVX(movsxbl);
       __ AssertZeroExtended(i.OutputRegister());
@@ -1612,14 +1695,14 @@
       }
       break;
     case kX64BitcastFI:
-      if (instr->InputAt(0)->IsDoubleStackSlot()) {
+      if (instr->InputAt(0)->IsFPStackSlot()) {
         __ movl(i.OutputRegister(), i.InputOperand(0));
       } else {
         __ Movd(i.OutputRegister(), i.InputDoubleRegister(0));
       }
       break;
     case kX64BitcastDL:
-      if (instr->InputAt(0)->IsDoubleStackSlot()) {
+      if (instr->InputAt(0)->IsFPStackSlot()) {
         __ movq(i.OutputRegister(), i.InputOperand(0));
       } else {
         __ Movq(i.OutputRegister(), i.InputDoubleRegister(0));
@@ -1690,7 +1773,7 @@
         if (instr->InputAt(0)->IsRegister()) {
           __ pushq(i.InputRegister(0));
           frame_access_state()->IncreaseSPDelta(1);
-        } else if (instr->InputAt(0)->IsDoubleRegister()) {
+        } else if (instr->InputAt(0)->IsFPRegister()) {
           // TODO(titzer): use another machine instruction?
           __ subq(rsp, Immediate(kDoubleSize));
           frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
@@ -1710,6 +1793,24 @@
       }
       break;
     }
+    case kX64Xchgb: {
+      size_t index = 0;
+      Operand operand = i.MemoryOperand(&index);
+      __ xchgb(i.InputRegister(index), operand);
+      break;
+    }
+    case kX64Xchgw: {
+      size_t index = 0;
+      Operand operand = i.MemoryOperand(&index);
+      __ xchgw(i.InputRegister(index), operand);
+      break;
+    }
+    case kX64Xchgl: {
+      size_t index = 0;
+      Operand operand = i.MemoryOperand(&index);
+      __ xchgl(i.InputRegister(index), operand);
+      break;
+    }
     case kCheckedLoadInt8:
       ASSEMBLE_CHECKED_LOAD_INTEGER(movsxbl);
       break;
@@ -1755,7 +1856,18 @@
     case kX64StackCheck:
       __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
       break;
+    case kAtomicLoadInt8:
+    case kAtomicLoadUint8:
+    case kAtomicLoadInt16:
+    case kAtomicLoadUint16:
+    case kAtomicLoadWord32:
+    case kAtomicStoreWord8:
+    case kAtomicStoreWord16:
+    case kAtomicStoreWord32:
+      UNREACHABLE();  // Won't be generated by instruction selector.
+      break;
   }
+  return kSuccess;
 }  // NOLINT(readability/fn_size)
 
 
@@ -1918,12 +2030,13 @@
   __ jmp(Operand(kScratchRegister, input, times_8, 0));
 }
 
-
-void CodeGenerator::AssembleDeoptimizerCall(
+CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
     int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
   Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
       isolate(), deoptimization_id, bailout_type);
+  if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
   __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
+  return kSuccess;
 }
 
 
@@ -1933,8 +2046,31 @@
 
 }  // namespace
 
+void CodeGenerator::FinishFrame(Frame* frame) {
+  CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
 
-void CodeGenerator::AssemblePrologue() {
+  const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
+  if (saves_fp != 0) {
+    frame->AlignSavedCalleeRegisterSlots();
+    if (saves_fp != 0) {  // Save callee-saved XMM registers.
+      const uint32_t saves_fp_count = base::bits::CountPopulation32(saves_fp);
+      frame->AllocateSavedCalleeRegisterSlots(saves_fp_count *
+                                              (kQuadWordSize / kPointerSize));
+    }
+  }
+  const RegList saves = descriptor->CalleeSavedRegisters();
+  if (saves != 0) {  // Save callee-saved registers.
+    int count = 0;
+    for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
+      if (((1 << i) & saves)) {
+        ++count;
+      }
+    }
+    frame->AllocateSavedCalleeRegisterSlots(count);
+  }
+}
+
+void CodeGenerator::AssembleConstructFrame() {
   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
   if (frame_access_state()->has_frame()) {
     if (descriptor->IsCFunctionCall()) {
@@ -1946,7 +2082,8 @@
       __ StubPrologue(info()->GetOutputStackFrameType());
     }
   }
-  int stack_shrink_slots = frame()->GetSpillSlotCount();
+  int shrink_slots = frame()->GetSpillSlotCount();
+
   if (info()->is_osr()) {
     // TurboFan OSR-compiled functions cannot be entered directly.
     __ Abort(kShouldNotDirectlyEnterOsrFunction);
@@ -1957,16 +2094,12 @@
     // remaining stack slots.
     if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
     osr_pc_offset_ = __ pc_offset();
-    stack_shrink_slots -=
-        static_cast<int>(OsrHelper(info()).UnoptimizedFrameSlots());
+    shrink_slots -= static_cast<int>(OsrHelper(info()).UnoptimizedFrameSlots());
   }
 
   const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
-  if (saves_fp != 0) {
-    stack_shrink_slots += frame()->AlignSavedCalleeRegisterSlots();
-  }
-  if (stack_shrink_slots > 0) {
-    __ subq(rsp, Immediate(stack_shrink_slots * kPointerSize));
+  if (shrink_slots > 0) {
+    __ subq(rsp, Immediate(shrink_slots * kPointerSize));
   }
 
   if (saves_fp != 0) {  // Save callee-saved XMM registers.
@@ -1982,8 +2115,6 @@
                 XMMRegister::from_code(i));
       slot_idx++;
     }
-    frame()->AllocateSavedCalleeRegisterSlots(saves_fp_count *
-                                              (kQuadWordSize / kPointerSize));
   }
 
   const RegList saves = descriptor->CalleeSavedRegisters();
@@ -1991,7 +2122,6 @@
     for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
       if (!((1 << i) & saves)) continue;
       __ pushq(Register::from_code(i));
-      frame()->AllocateSavedCalleeRegisterSlots(1);
     }
   }
 }
@@ -2077,12 +2207,29 @@
       Register dst = destination->IsRegister() ? g.ToRegister(destination)
                                                : kScratchRegister;
       switch (src.type()) {
-        case Constant::kInt32:
-          // TODO(dcarney): don't need scratch in this case.
-          __ Set(dst, src.ToInt32());
+        case Constant::kInt32: {
+          if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
+              src.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE) {
+            __ movq(dst, src.ToInt64(), src.rmode());
+          } else {
+            // TODO(dcarney): don't need scratch in this case.
+            int32_t value = src.ToInt32();
+            if (value == 0) {
+              __ xorl(dst, dst);
+            } else {
+              __ movl(dst, Immediate(value));
+            }
+          }
           break;
+        }
         case Constant::kInt64:
-          __ Set(dst, src.ToInt64());
+          if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
+              src.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE) {
+            __ movq(dst, src.ToInt64(), src.rmode());
+          } else {
+            DCHECK(src.rmode() != RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
+            __ Set(dst, src.ToInt64());
+          }
           break;
         case Constant::kFloat32:
           __ Move(dst,
@@ -2118,45 +2265,44 @@
     } else if (src.type() == Constant::kFloat32) {
       // TODO(turbofan): Can we do better here?
       uint32_t src_const = bit_cast<uint32_t>(src.ToFloat32());
-      if (destination->IsDoubleRegister()) {
+      if (destination->IsFPRegister()) {
         __ Move(g.ToDoubleRegister(destination), src_const);
       } else {
-        DCHECK(destination->IsDoubleStackSlot());
+        DCHECK(destination->IsFPStackSlot());
         Operand dst = g.ToOperand(destination);
         __ movl(dst, Immediate(src_const));
       }
     } else {
       DCHECK_EQ(Constant::kFloat64, src.type());
       uint64_t src_const = bit_cast<uint64_t>(src.ToFloat64());
-      if (destination->IsDoubleRegister()) {
+      if (destination->IsFPRegister()) {
         __ Move(g.ToDoubleRegister(destination), src_const);
       } else {
-        DCHECK(destination->IsDoubleStackSlot());
+        DCHECK(destination->IsFPStackSlot());
         __ movq(kScratchRegister, src_const);
         __ movq(g.ToOperand(destination), kScratchRegister);
       }
     }
-  } else if (source->IsDoubleRegister()) {
+  } else if (source->IsFPRegister()) {
     XMMRegister src = g.ToDoubleRegister(source);
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       XMMRegister dst = g.ToDoubleRegister(destination);
       __ Movapd(dst, src);
     } else {
-      DCHECK(destination->IsDoubleStackSlot());
+      DCHECK(destination->IsFPStackSlot());
       Operand dst = g.ToOperand(destination);
       __ Movsd(dst, src);
     }
-  } else if (source->IsDoubleStackSlot()) {
-    DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
+  } else if (source->IsFPStackSlot()) {
+    DCHECK(destination->IsFPRegister() || destination->IsFPStackSlot());
     Operand src = g.ToOperand(source);
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       XMMRegister dst = g.ToDoubleRegister(destination);
       __ Movsd(dst, src);
     } else {
-      // We rely on having xmm0 available as a fixed scratch register.
       Operand dst = g.ToOperand(destination);
-      __ Movsd(xmm0, src);
-      __ Movsd(dst, xmm0);
+      __ Movsd(kScratchDoubleReg, src);
+      __ Movsd(dst, kScratchDoubleReg);
     }
   } else {
     UNREACHABLE();
@@ -2186,8 +2332,7 @@
     dst = g.ToOperand(destination);
     __ popq(dst);
   } else if ((source->IsStackSlot() && destination->IsStackSlot()) ||
-             (source->IsDoubleStackSlot() &&
-              destination->IsDoubleStackSlot())) {
+             (source->IsFPStackSlot() && destination->IsFPStackSlot())) {
     // Memory-memory.
     Register tmp = kScratchRegister;
     Operand src = g.ToOperand(source);
@@ -2200,22 +2345,20 @@
     frame_access_state()->IncreaseSPDelta(-1);
     dst = g.ToOperand(destination);
     __ popq(dst);
-  } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) {
-    // XMM register-register swap. We rely on having xmm0
-    // available as a fixed scratch register.
+  } else if (source->IsFPRegister() && destination->IsFPRegister()) {
+    // XMM register-register swap.
     XMMRegister src = g.ToDoubleRegister(source);
     XMMRegister dst = g.ToDoubleRegister(destination);
-    __ Movapd(xmm0, src);
+    __ Movapd(kScratchDoubleReg, src);
     __ Movapd(src, dst);
-    __ Movapd(dst, xmm0);
-  } else if (source->IsDoubleRegister() && destination->IsDoubleStackSlot()) {
-    // XMM register-memory swap.  We rely on having xmm0
-    // available as a fixed scratch register.
+    __ Movapd(dst, kScratchDoubleReg);
+  } else if (source->IsFPRegister() && destination->IsFPStackSlot()) {
+    // XMM register-memory swap.
     XMMRegister src = g.ToDoubleRegister(source);
     Operand dst = g.ToOperand(destination);
-    __ Movsd(xmm0, src);
+    __ Movsd(kScratchDoubleReg, src);
     __ Movsd(src, dst);
-    __ Movsd(dst, xmm0);
+    __ Movsd(dst, kScratchDoubleReg);
   } else {
     // No other combinations are possible.
     UNREACHABLE();
@@ -2230,9 +2373,6 @@
 }
 
 
-void CodeGenerator::AddNopForSmiCodeInlining() { __ nop(); }
-
-
 void CodeGenerator::EnsureSpaceForLazyDeopt() {
   if (!info()->ShouldEnsureSpaceForLazyDeopt()) {
     return;
diff --git a/src/compiler/x64/instruction-codes-x64.h b/src/compiler/x64/instruction-codes-x64.h
index bd19386..29acee3 100644
--- a/src/compiler/x64/instruction-codes-x64.h
+++ b/src/compiler/x64/instruction-codes-x64.h
@@ -102,6 +102,7 @@
   V(SSEFloat64InsertLowWord32)     \
   V(SSEFloat64InsertHighWord32)    \
   V(SSEFloat64LoadLowWord32)       \
+  V(SSEFloat64SilenceNaN)          \
   V(AVXFloat32Cmp)                 \
   V(AVXFloat32Add)                 \
   V(AVXFloat32Sub)                 \
@@ -141,7 +142,10 @@
   V(X64Inc32)                      \
   V(X64Push)                       \
   V(X64Poke)                       \
-  V(X64StackCheck)
+  V(X64StackCheck)                 \
+  V(X64Xchgb)                      \
+  V(X64Xchgw)                      \
+  V(X64Xchgl)
 
 // Addressing modes represent the "shape" of inputs to an instruction.
 // Many instructions support multiple addressing modes. Addressing modes
diff --git a/src/compiler/x64/instruction-scheduler-x64.cc b/src/compiler/x64/instruction-scheduler-x64.cc
index 3c31965..eecefdb 100644
--- a/src/compiler/x64/instruction-scheduler-x64.cc
+++ b/src/compiler/x64/instruction-scheduler-x64.cc
@@ -104,6 +104,7 @@
     case kSSEFloat64InsertLowWord32:
     case kSSEFloat64InsertHighWord32:
     case kSSEFloat64LoadLowWord32:
+    case kSSEFloat64SilenceNaN:
     case kAVXFloat32Cmp:
     case kAVXFloat32Add:
     case kAVXFloat32Sub:
@@ -168,6 +169,11 @@
     case kX64Poke:
       return kHasSideEffect;
 
+    case kX64Xchgb:
+    case kX64Xchgw:
+    case kX64Xchgl:
+      return kIsLoadOperation | kHasSideEffect;
+
 #define CASE(Name) case k##Name:
     COMMON_ARCH_OPCODE_LIST(CASE)
 #undef CASE
diff --git a/src/compiler/x64/instruction-selector-x64.cc b/src/compiler/x64/instruction-selector-x64.cc
index ea1d48b..be56dce 100644
--- a/src/compiler/x64/instruction-selector-x64.cc
+++ b/src/compiler/x64/instruction-selector-x64.cc
@@ -22,6 +22,7 @@
   bool CanBeImmediate(Node* node) {
     switch (node->opcode()) {
       case IrOpcode::kInt32Constant:
+      case IrOpcode::kRelocatableInt32Constant:
         return true;
       case IrOpcode::kInt64Constant: {
         const int64_t value = OpParameter<int64_t>(node);
@@ -36,11 +37,15 @@
     }
   }
 
-  bool CanBeMemoryOperand(InstructionCode opcode, Node* node, Node* input) {
+  bool CanBeMemoryOperand(InstructionCode opcode, Node* node, Node* input,
+                          int effect_level) {
     if (input->opcode() != IrOpcode::kLoad ||
         !selector()->CanCover(node, input)) {
       return false;
     }
+    if (effect_level != selector()->GetEffectLevel(input)) {
+      return false;
+    }
     MachineRepresentation rep =
         LoadRepresentationOf(input->op()).representation();
     switch (opcode) {
@@ -1140,15 +1145,8 @@
   VisitRO(this, node, kSSEFloat64ToFloat32);
 }
 
-
-void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
-  switch (TruncationModeOf(node->op())) {
-    case TruncationMode::kJavaScript:
-      return VisitRR(this, node, kArchTruncateDoubleToI);
-    case TruncationMode::kRoundToZero:
-      return VisitRO(this, node, kSSEFloat64ToInt32);
-  }
-  UNREACHABLE();
+void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
+  VisitRR(this, node, kArchTruncateDoubleToI);
 }
 
 
@@ -1174,6 +1172,9 @@
   Emit(kX64Movl, g.DefineAsRegister(node), g.Use(value));
 }
 
+void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
+  VisitRO(this, node, kSSEFloat64ToInt32);
+}
 
 void InstructionSelector::VisitRoundInt32ToFloat32(Node* node) {
   X64OperandGenerator g(this);
@@ -1255,6 +1256,9 @@
   VisitFloatBinop(this, node, kAVXFloat32Sub, kSSEFloat32Sub);
 }
 
+void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
+  VisitFloatBinop(this, node, kAVXFloat32Sub, kSSEFloat32Sub);
+}
 
 void InstructionSelector::VisitFloat32Mul(Node* node) {
   VisitFloatBinop(this, node, kAVXFloat32Mul, kSSEFloat32Mul);
@@ -1314,6 +1318,9 @@
   VisitFloatBinop(this, node, kAVXFloat64Sub, kSSEFloat64Sub);
 }
 
+void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
+  VisitFloatBinop(this, node, kAVXFloat64Sub, kSSEFloat64Sub);
+}
 
 void InstructionSelector::VisitFloat64Mul(Node* node) {
   VisitFloatBinop(this, node, kAVXFloat64Mul, kSSEFloat64Mul);
@@ -1348,7 +1355,6 @@
   VisitFloatUnop(this, node, node->InputAt(0), kAVXFloat64Abs, kSSEFloat64Abs);
 }
 
-
 void InstructionSelector::VisitFloat64Sqrt(Node* node) {
   VisitRO(this, node, kSSEFloat64Sqrt);
 }
@@ -1398,6 +1404,24 @@
   VisitRR(this, node, kSSEFloat64Round | MiscField::encode(kRoundToNearest));
 }
 
+void InstructionSelector::VisitFloat32Neg(Node* node) { UNREACHABLE(); }
+
+void InstructionSelector::VisitFloat64Neg(Node* node) { UNREACHABLE(); }
+
+void InstructionSelector::VisitFloat64Ieee754Binop(Node* node,
+                                                   InstructionCode opcode) {
+  X64OperandGenerator g(this);
+  Emit(opcode, g.DefineAsFixed(node, xmm0), g.UseFixed(node->InputAt(0), xmm0),
+       g.UseFixed(node->InputAt(1), xmm1))
+      ->MarkAsCall();
+}
+
+void InstructionSelector::VisitFloat64Ieee754Unop(Node* node,
+                                                  InstructionCode opcode) {
+  X64OperandGenerator g(this);
+  Emit(opcode, g.DefineAsFixed(node, xmm0), g.UseFixed(node->InputAt(0), xmm0))
+      ->MarkAsCall();
+}
 
 void InstructionSelector::EmitPrepareArguments(
     ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
@@ -1430,7 +1454,7 @@
           g.CanBeImmediate(input.node())
               ? g.UseImmediate(input.node())
               : IsSupported(ATOM) ||
-                        sequence()->IsFloat(GetVirtualRegister(input.node()))
+                        sequence()->IsFP(GetVirtualRegister(input.node()))
                     ? g.UseRegister(input.node())
                     : g.Use(input.node());
       Emit(kX64Push, g.NoOutput(), value);
@@ -1545,16 +1569,22 @@
 
   // If one of the two inputs is an immediate, make sure it's on the right, or
   // if one of the two inputs is a memory operand, make sure it's on the left.
+  int effect_level = selector->GetEffectLevel(node);
+  if (cont->IsBranch()) {
+    effect_level = selector->GetEffectLevel(
+        cont->true_block()->PredecessorAt(0)->control_input());
+  }
+
   if ((!g.CanBeImmediate(right) && g.CanBeImmediate(left)) ||
-      (g.CanBeMemoryOperand(opcode, node, right) &&
-       !g.CanBeMemoryOperand(opcode, node, left))) {
+      (g.CanBeMemoryOperand(opcode, node, right, effect_level) &&
+       !g.CanBeMemoryOperand(opcode, node, left, effect_level))) {
     if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
     std::swap(left, right);
   }
 
   // Match immediates on right side of comparison.
   if (g.CanBeImmediate(right)) {
-    if (g.CanBeMemoryOperand(opcode, node, left)) {
+    if (g.CanBeMemoryOperand(opcode, node, left, effect_level)) {
       return VisitCompareWithMemoryOperand(selector, opcode, left,
                                            g.UseImmediate(right), cont);
     }
@@ -1563,7 +1593,7 @@
   }
 
   // Match memory operands on left side of comparison.
-  if (g.CanBeMemoryOperand(opcode, node, left)) {
+  if (g.CanBeMemoryOperand(opcode, node, left, effect_level)) {
     return VisitCompareWithMemoryOperand(selector, opcode, left,
                                          g.UseRegister(right), cont);
   }
@@ -2023,6 +2053,58 @@
        g.UseRegister(left), g.Use(right));
 }
 
+void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
+  X64OperandGenerator g(this);
+  Emit(kSSEFloat64SilenceNaN, g.DefineSameAsFirst(node),
+       g.UseRegister(node->InputAt(0)));
+}
+
+void InstructionSelector::VisitAtomicLoad(Node* node) {
+  LoadRepresentation load_rep = LoadRepresentationOf(node->op());
+  DCHECK(load_rep.representation() == MachineRepresentation::kWord8 ||
+         load_rep.representation() == MachineRepresentation::kWord16 ||
+         load_rep.representation() == MachineRepresentation::kWord32);
+  USE(load_rep);
+  VisitLoad(node);
+}
+
+void InstructionSelector::VisitAtomicStore(Node* node) {
+  X64OperandGenerator g(this);
+  Node* base = node->InputAt(0);
+  Node* index = node->InputAt(1);
+  Node* value = node->InputAt(2);
+
+  MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
+  ArchOpcode opcode = kArchNop;
+  switch (rep) {
+    case MachineRepresentation::kWord8:
+      opcode = kX64Xchgb;
+      break;
+    case MachineRepresentation::kWord16:
+      opcode = kX64Xchgw;
+      break;
+    case MachineRepresentation::kWord32:
+      opcode = kX64Xchgl;
+      break;
+    default:
+      UNREACHABLE();
+      return;
+  }
+  AddressingMode addressing_mode;
+  InstructionOperand inputs[4];
+  size_t input_count = 0;
+  inputs[input_count++] = g.UseUniqueRegister(base);
+  if (g.CanBeImmediate(index)) {
+    inputs[input_count++] = g.UseImmediate(index);
+    addressing_mode = kMode_MRI;
+  } else {
+    inputs[input_count++] = g.UseUniqueRegister(index);
+    addressing_mode = kMode_MR1;
+  }
+  inputs[input_count++] = g.UseUniqueRegister(value);
+  InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
+  Emit(code, 0, static_cast<InstructionOperand*>(nullptr), input_count, inputs);
+}
 
 // static
 MachineOperatorBuilder::Flags
@@ -2051,6 +2133,13 @@
   return flags;
 }
 
+// static
+MachineOperatorBuilder::AlignmentRequirements
+InstructionSelector::AlignmentRequirements() {
+  return MachineOperatorBuilder::AlignmentRequirements::
+      FullUnalignedAccessSupport();
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/src/compiler/x87/code-generator-x87.cc b/src/compiler/x87/code-generator-x87.cc
index da7fdb4..6bacda0 100644
--- a/src/compiler/x87/code-generator-x87.cc
+++ b/src/compiler/x87/code-generator-x87.cc
@@ -42,7 +42,7 @@
       DCHECK(extra == 0);
       return Operand(ToRegister(op));
     }
-    DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
+    DCHECK(op->IsStackSlot() || op->IsFPStackSlot());
     return SlotToOperand(AllocatedOperand::cast(op)->index(), extra);
   }
 
@@ -53,12 +53,19 @@
   }
 
   Operand HighOperand(InstructionOperand* op) {
-    DCHECK(op->IsDoubleStackSlot());
+    DCHECK(op->IsFPStackSlot());
     return ToOperand(op, kPointerSize);
   }
 
   Immediate ToImmediate(InstructionOperand* operand) {
     Constant constant = ToConstant(operand);
+    if (constant.type() == Constant::kInt32 &&
+        (constant.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
+         constant.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE ||
+         constant.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE)) {
+      return Immediate(reinterpret_cast<Address>(constant.ToInt32()),
+                       constant.rmode());
+    }
     switch (constant.type()) {
       case Constant::kInt32:
         return Immediate(constant.ToInt32());
@@ -107,8 +114,8 @@
       }
       case kMode_MRI: {
         Register base = InputRegister(NextOffset(offset));
-        int32_t disp = InputInt32(NextOffset(offset));
-        return Operand(base, disp);
+        Constant ctant = ToConstant(instr_->InputAt(NextOffset(offset)));
+        return Operand(base, ctant.ToInt32(), ctant.rmode());
       }
       case kMode_MR1:
       case kMode_MR2:
@@ -127,8 +134,8 @@
         Register base = InputRegister(NextOffset(offset));
         Register index = InputRegister(NextOffset(offset));
         ScaleFactor scale = ScaleFor(kMode_MR1I, mode);
-        int32_t disp = InputInt32(NextOffset(offset));
-        return Operand(base, index, scale, disp);
+        Constant ctant = ToConstant(instr_->InputAt(NextOffset(offset)));
+        return Operand(base, index, scale, ctant.ToInt32(), ctant.rmode());
       }
       case kMode_M1:
       case kMode_M2:
@@ -145,12 +152,12 @@
       case kMode_M8I: {
         Register index = InputRegister(NextOffset(offset));
         ScaleFactor scale = ScaleFor(kMode_M1I, mode);
-        int32_t disp = InputInt32(NextOffset(offset));
-        return Operand(index, scale, disp);
+        Constant ctant = ToConstant(instr_->InputAt(NextOffset(offset)));
+        return Operand(index, scale, ctant.ToInt32(), ctant.rmode());
       }
       case kMode_MI: {
-        int32_t disp = InputInt32(NextOffset(offset));
-        return Operand(Immediate(disp));
+        Constant ctant = ToConstant(instr_->InputAt(NextOffset(offset)));
+        return Operand(ctant.ToInt32(), ctant.rmode());
       }
       case kMode_None:
         UNREACHABLE();
@@ -364,16 +371,55 @@
     }                                                                 \
   } while (0)
 
+#define ASSEMBLE_IEEE754_BINOP(name)                                          \
+  do {                                                                        \
+    /* Saves the esp into ebx */                                              \
+    __ push(ebx);                                                             \
+    __ mov(ebx, esp);                                                         \
+    /* Pass one double as argument on the stack. */                           \
+    __ PrepareCallCFunction(4, eax);                                          \
+    __ fstp(0);                                                               \
+    /* Load first operand from original stack */                              \
+    __ fld_d(MemOperand(ebx, 4 + kDoubleSize));                               \
+    /* Put first operand into stack for function call */                      \
+    __ fstp_d(Operand(esp, 0 * kDoubleSize));                                 \
+    /* Load second operand from original stack */                             \
+    __ fld_d(MemOperand(ebx, 4));                                             \
+    /* Put second operand into stack for function call */                     \
+    __ fstp_d(Operand(esp, 1 * kDoubleSize));                                 \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \
+                     4);                                                      \
+    /* Restore the ebx */                                                     \
+    __ pop(ebx);                                                              \
+    /* Return value is in st(0) on x87. */                                    \
+    __ lea(esp, Operand(esp, 2 * kDoubleSize));                               \
+  } while (false)
+
+#define ASSEMBLE_IEEE754_UNOP(name)                                           \
+  do {                                                                        \
+    /* Saves the esp into ebx */                                              \
+    __ push(ebx);                                                             \
+    __ mov(ebx, esp);                                                         \
+    /* Pass one double as argument on the stack. */                           \
+    __ PrepareCallCFunction(2, eax);                                          \
+    __ fstp(0);                                                               \
+    /* Load operand from original stack */                                    \
+    __ fld_d(MemOperand(ebx, 4));                                             \
+    /* Put operand into stack for function call */                            \
+    __ fstp_d(Operand(esp, 0));                                               \
+    __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \
+                     2);                                                      \
+    /* Restore the ebx */                                                     \
+    __ pop(ebx);                                                              \
+    /* Return value is in st(0) on x87. */                                    \
+    __ lea(esp, Operand(esp, kDoubleSize));                                   \
+  } while (false)
+
 void CodeGenerator::AssembleDeconstructFrame() {
   __ mov(esp, ebp);
   __ pop(ebp);
 }
 
-// For insert fninit/fld1 instructions after the Prologue
-thread_local bool is_block_0 = false;
-
-void CodeGenerator::AssembleSetupStackPointer() { is_block_0 = true; }
-
 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
   int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
   if (sp_slot_delta > 0) {
@@ -434,18 +480,12 @@
 }
 
 // Assembles an instruction after register allocation, producing machine code.
-void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
+CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
+    Instruction* instr) {
   X87OperandConverter i(this, instr);
   InstructionCode opcode = instr->opcode();
   ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode);
 
-  // Workaround for CL #35139 (https://codereview.chromium.org/1775323002)
-  if (is_block_0) {
-    __ fninit();
-    __ fld1();
-    is_block_0 = false;
-  }
-
   switch (arch_opcode) {
     case kArchCallCodeObject: {
       if (FLAG_debug_code && FLAG_enable_slow_asserts) {
@@ -463,7 +503,7 @@
       }
       RecordCallPosition(instr);
       bool double_result =
-          instr->HasOutput() && instr->Output()->IsDoubleRegister();
+          instr->HasOutput() && instr->Output()->IsFPRegister();
       if (double_result) {
         __ lea(esp, Operand(esp, -kDoubleSize));
         __ fstp_d(Operand(esp, 0));
@@ -501,6 +541,15 @@
       frame_access_state()->ClearSPDelta();
       break;
     }
+    case kArchTailCallAddress: {
+      int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
+      AssembleDeconstructActivationRecord(stack_param_delta);
+      CHECK(!HasImmediateInput(instr, 0));
+      Register reg = i.InputRegister(0);
+      __ jmp(reg);
+      frame_access_state()->ClearSPDelta();
+      break;
+    }
     case kArchCallJSFunction: {
       EnsureSpaceForLazyDeopt();
       Register func = i.InputRegister(0);
@@ -516,7 +565,7 @@
       __ call(FieldOperand(func, JSFunction::kCodeEntryOffset));
       RecordCallPosition(instr);
       bool double_result =
-          instr->HasOutput() && instr->Output()->IsDoubleRegister();
+          instr->HasOutput() && instr->Output()->IsFPRegister();
       if (double_result) {
         __ lea(esp, Operand(esp, -kDoubleSize));
         __ fstp_d(Operand(esp, 0));
@@ -577,7 +626,7 @@
         __ CallCFunction(func, num_parameters);
       }
       bool double_result =
-          instr->HasOutput() && instr->Output()->IsDoubleRegister();
+          instr->HasOutput() && instr->Output()->IsFPRegister();
       if (double_result) {
         __ lea(esp, Operand(esp, -kDoubleSize));
         __ fstp_d(Operand(esp, 0));
@@ -602,6 +651,14 @@
     case kArchTableSwitch:
       AssembleArchTableSwitch(instr);
       break;
+    case kArchComment: {
+      Address comment_string = i.InputExternalReference(0).address();
+      __ RecordComment(reinterpret_cast<const char*>(comment_string));
+      break;
+    }
+    case kArchDebugBreak:
+      __ int3();
+      break;
     case kArchNop:
     case kArchThrowTerminator:
       // don't emit code for nops.
@@ -612,7 +669,7 @@
       int double_register_param_count = 0;
       int x87_layout = 0;
       for (size_t i = 0; i < instr->InputCount(); i++) {
-        if (instr->InputAt(i)->IsDoubleRegister()) {
+        if (instr->InputAt(i)->IsFPRegister()) {
           double_register_param_count++;
         }
       }
@@ -630,7 +687,9 @@
 
       Deoptimizer::BailoutType bailout_type =
           Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
-      AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      CodeGenResult result =
+          AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+      if (result != kSuccess) return result;
       break;
     }
     case kArchRet:
@@ -650,11 +709,11 @@
       }
       break;
     case kArchTruncateDoubleToI: {
-      if (!instr->InputAt(0)->IsDoubleRegister()) {
+      if (!instr->InputAt(0)->IsFPRegister()) {
         __ fld_d(i.InputOperand(0));
       }
       __ TruncateX87TOSToI(i.OutputRegister());
-      if (!instr->InputAt(0)->IsDoubleRegister()) {
+      if (!instr->InputAt(0)->IsFPRegister()) {
         __ fstp(0);
       }
       break;
@@ -689,6 +748,53 @@
       __ lea(i.OutputRegister(), Operand(base, offset.offset()));
       break;
     }
+    case kIeee754Float64Atan:
+      ASSEMBLE_IEEE754_UNOP(atan);
+      break;
+    case kIeee754Float64Atan2:
+      ASSEMBLE_IEEE754_BINOP(atan2);
+      break;
+    case kIeee754Float64Cbrt:
+      ASSEMBLE_IEEE754_UNOP(cbrt);
+      break;
+    case kIeee754Float64Cos:
+      __ X87SetFPUCW(0x027F);
+      ASSEMBLE_IEEE754_UNOP(cos);
+      __ X87SetFPUCW(0x037F);
+      break;
+    case kIeee754Float64Expm1:
+      __ X87SetFPUCW(0x027F);
+      ASSEMBLE_IEEE754_UNOP(expm1);
+      __ X87SetFPUCW(0x037F);
+      break;
+    case kIeee754Float64Exp:
+      ASSEMBLE_IEEE754_UNOP(exp);
+      break;
+    case kIeee754Float64Atanh:
+      ASSEMBLE_IEEE754_UNOP(atanh);
+      break;
+    case kIeee754Float64Log:
+      ASSEMBLE_IEEE754_UNOP(log);
+      break;
+    case kIeee754Float64Log1p:
+      ASSEMBLE_IEEE754_UNOP(log1p);
+      break;
+    case kIeee754Float64Log2:
+      ASSEMBLE_IEEE754_UNOP(log2);
+      break;
+    case kIeee754Float64Log10:
+      ASSEMBLE_IEEE754_UNOP(log10);
+      break;
+    case kIeee754Float64Sin:
+      __ X87SetFPUCW(0x027F);
+      ASSEMBLE_IEEE754_UNOP(sin);
+      __ X87SetFPUCW(0x037F);
+      break;
+    case kIeee754Float64Tan:
+      __ X87SetFPUCW(0x027F);
+      ASSEMBLE_IEEE754_UNOP(tan);
+      __ X87SetFPUCW(0x037F);
+      break;
     case kX87Add:
       if (HasImmediateInput(instr, 1)) {
         __ add(i.InputOperand(0), i.InputImmediate(1));
@@ -900,7 +1006,7 @@
       uint64_t src = bit_cast<uint64_t>(src_constant.ToFloat64());
       uint32_t lower = static_cast<uint32_t>(src);
       uint32_t upper = static_cast<uint32_t>(src >> 32);
-      if (destination->IsDoubleRegister()) {
+      if (destination->IsFPRegister()) {
         __ sub(esp, Immediate(kDoubleSize));
         __ mov(MemOperand(esp, 0), Immediate(lower));
         __ mov(MemOperand(esp, kInt32Size), Immediate(upper));
@@ -1092,10 +1198,10 @@
       // Set the correct round mode in x87 control register
       __ X87SetRC((mode << 10));
 
-      if (!instr->InputAt(0)->IsDoubleRegister()) {
+      if (!instr->InputAt(0)->IsFPRegister()) {
         InstructionOperand* input = instr->InputAt(0);
         USE(input);
-        DCHECK(input->IsDoubleStackSlot());
+        DCHECK(input->IsFPStackSlot());
         if (FLAG_debug_code && FLAG_enable_slow_asserts) {
           __ VerifyX87StackDepth(1);
         }
@@ -1333,13 +1439,13 @@
     }
     case kX87Float32ToFloat64: {
       InstructionOperand* input = instr->InputAt(0);
-      if (input->IsDoubleRegister()) {
+      if (input->IsFPRegister()) {
         __ sub(esp, Immediate(kDoubleSize));
         __ fstp_s(MemOperand(esp, 0));
         __ fld_s(MemOperand(esp, 0));
         __ add(esp, Immediate(kDoubleSize));
       } else {
-        DCHECK(input->IsDoubleStackSlot());
+        DCHECK(input->IsFPStackSlot());
         if (FLAG_debug_code && FLAG_enable_slow_asserts) {
           __ VerifyX87StackDepth(1);
         }
@@ -1357,17 +1463,17 @@
       break;
     }
     case kX87Float32ToInt32: {
-      if (!instr->InputAt(0)->IsDoubleRegister()) {
+      if (!instr->InputAt(0)->IsFPRegister()) {
         __ fld_s(i.InputOperand(0));
       }
       __ TruncateX87TOSToI(i.OutputRegister(0));
-      if (!instr->InputAt(0)->IsDoubleRegister()) {
+      if (!instr->InputAt(0)->IsFPRegister()) {
         __ fstp(0);
       }
       break;
     }
     case kX87Float32ToUint32: {
-      if (!instr->InputAt(0)->IsDoubleRegister()) {
+      if (!instr->InputAt(0)->IsFPRegister()) {
         __ fld_s(i.InputOperand(0));
       }
       Label success;
@@ -1381,30 +1487,30 @@
       __ TruncateX87TOSToI(i.OutputRegister(0));
       __ or_(i.OutputRegister(0), Immediate(0x80000000));
       __ bind(&success);
-      if (!instr->InputAt(0)->IsDoubleRegister()) {
+      if (!instr->InputAt(0)->IsFPRegister()) {
         __ fstp(0);
       }
       break;
     }
     case kX87Float64ToInt32: {
-      if (!instr->InputAt(0)->IsDoubleRegister()) {
+      if (!instr->InputAt(0)->IsFPRegister()) {
         __ fld_d(i.InputOperand(0));
       }
       __ TruncateX87TOSToI(i.OutputRegister(0));
-      if (!instr->InputAt(0)->IsDoubleRegister()) {
+      if (!instr->InputAt(0)->IsFPRegister()) {
         __ fstp(0);
       }
       break;
     }
     case kX87Float64ToFloat32: {
       InstructionOperand* input = instr->InputAt(0);
-      if (input->IsDoubleRegister()) {
+      if (input->IsFPRegister()) {
         __ sub(esp, Immediate(kDoubleSize));
         __ fstp_s(MemOperand(esp, 0));
         __ fld_s(MemOperand(esp, 0));
         __ add(esp, Immediate(kDoubleSize));
       } else {
-        DCHECK(input->IsDoubleStackSlot());
+        DCHECK(input->IsFPStackSlot());
         if (FLAG_debug_code && FLAG_enable_slow_asserts) {
           __ VerifyX87StackDepth(1);
         }
@@ -1419,7 +1525,7 @@
     }
     case kX87Float64ToUint32: {
       __ push_imm32(-2147483648);
-      if (!instr->InputAt(0)->IsDoubleRegister()) {
+      if (!instr->InputAt(0)->IsFPRegister()) {
         __ fld_d(i.InputOperand(0));
       }
       __ fild_s(Operand(esp, 0));
@@ -1429,13 +1535,13 @@
       __ add(esp, Immediate(kInt32Size));
       __ add(i.OutputRegister(), Immediate(0x80000000));
       __ fstp(0);
-      if (!instr->InputAt(0)->IsDoubleRegister()) {
+      if (!instr->InputAt(0)->IsFPRegister()) {
         __ fstp(0);
       }
       break;
     }
     case kX87Float64ExtractHighWord32: {
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ sub(esp, Immediate(kDoubleSize));
         __ fst_d(MemOperand(esp, 0));
         __ mov(i.OutputRegister(), MemOperand(esp, kDoubleSize / 2));
@@ -1443,13 +1549,13 @@
       } else {
         InstructionOperand* input = instr->InputAt(0);
         USE(input);
-        DCHECK(input->IsDoubleStackSlot());
+        DCHECK(input->IsFPStackSlot());
         __ mov(i.OutputRegister(), i.InputOperand(0, kDoubleSize / 2));
       }
       break;
     }
     case kX87Float64ExtractLowWord32: {
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         __ sub(esp, Immediate(kDoubleSize));
         __ fst_d(MemOperand(esp, 0));
         __ mov(i.OutputRegister(), MemOperand(esp, 0));
@@ -1457,7 +1563,7 @@
       } else {
         InstructionOperand* input = instr->InputAt(0);
         USE(input);
-        DCHECK(input->IsDoubleStackSlot());
+        DCHECK(input->IsFPStackSlot());
         __ mov(i.OutputRegister(), i.InputOperand(0));
       }
       break;
@@ -1496,10 +1602,10 @@
       // Set the correct round mode in x87 control register
       __ X87SetRC((mode << 10));
 
-      if (!instr->InputAt(0)->IsDoubleRegister()) {
+      if (!instr->InputAt(0)->IsFPRegister()) {
         InstructionOperand* input = instr->InputAt(0);
         USE(input);
-        DCHECK(input->IsDoubleStackSlot());
+        DCHECK(input->IsFPStackSlot());
         if (FLAG_debug_code && FLAG_enable_slow_asserts) {
           __ VerifyX87StackDepth(1);
         }
@@ -1517,6 +1623,30 @@
       __ lea(esp, Operand(esp, 2 * kDoubleSize));
       break;
     }
+    case kX87Float64SilenceNaN: {
+      Label end, return_qnan;
+      __ fstp(0);
+      __ push(ebx);
+      // Load Half word of HoleNan(SNaN) into ebx
+      __ mov(ebx, MemOperand(esp, 2 * kInt32Size));
+      __ cmp(ebx, Immediate(kHoleNanUpper32));
+      // Check input is HoleNaN(SNaN)?
+      __ j(equal, &return_qnan, Label::kNear);
+      // If input isn't HoleNaN(SNaN), just load it and return
+      __ fld_d(MemOperand(esp, 1 * kInt32Size));
+      __ jmp(&end);
+      __ bind(&return_qnan);
+      // If input is HoleNaN(SNaN), Return QNaN
+      __ push(Immediate(0xffffffff));
+      __ push(Immediate(0xfff7ffff));
+      __ fld_d(MemOperand(esp, 0));
+      __ lea(esp, Operand(esp, kDoubleSize));
+      __ bind(&end);
+      __ pop(ebx);
+      // Clear stack.
+      __ lea(esp, Operand(esp, 1 * kDoubleSize));
+      break;
+    }
     case kX87Movsxbl:
       __ movsx_b(i.OutputRegister(), i.MemoryOperand());
       break;
@@ -1652,30 +1782,32 @@
       break;
     }
     case kX87Push:
-      if (instr->InputAt(0)->IsDoubleRegister()) {
+      if (instr->InputAt(0)->IsFPRegister()) {
         auto allocated = AllocatedOperand::cast(*instr->InputAt(0));
         if (allocated.representation() == MachineRepresentation::kFloat32) {
-          __ sub(esp, Immediate(kDoubleSize));
+          __ sub(esp, Immediate(kFloatSize));
           __ fst_s(Operand(esp, 0));
+          frame_access_state()->IncreaseSPDelta(kFloatSize / kPointerSize);
         } else {
           DCHECK(allocated.representation() == MachineRepresentation::kFloat64);
           __ sub(esp, Immediate(kDoubleSize));
           __ fst_d(Operand(esp, 0));
-        }
         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
-      } else if (instr->InputAt(0)->IsDoubleStackSlot()) {
+        }
+      } else if (instr->InputAt(0)->IsFPStackSlot()) {
         auto allocated = AllocatedOperand::cast(*instr->InputAt(0));
         if (allocated.representation() == MachineRepresentation::kFloat32) {
-          __ sub(esp, Immediate(kDoubleSize));
+          __ sub(esp, Immediate(kFloatSize));
           __ fld_s(i.InputOperand(0));
           __ fstp_s(MemOperand(esp, 0));
+          frame_access_state()->IncreaseSPDelta(kFloatSize / kPointerSize);
         } else {
           DCHECK(allocated.representation() == MachineRepresentation::kFloat64);
           __ sub(esp, Immediate(kDoubleSize));
           __ fld_d(i.InputOperand(0));
           __ fstp_d(MemOperand(esp, 0));
-        }
         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
+        }
       } else if (HasImmediateInput(instr, 0)) {
         __ push(i.InputImmediate(0));
         frame_access_state()->IncreaseSPDelta(1);
@@ -1693,12 +1825,30 @@
       }
       break;
     }
+    case kX87Xchgb: {
+      size_t index = 0;
+      Operand operand = i.MemoryOperand(&index);
+      __ xchg_b(i.InputRegister(index), operand);
+      break;
+    }
+    case kX87Xchgw: {
+      size_t index = 0;
+      Operand operand = i.MemoryOperand(&index);
+      __ xchg_w(i.InputRegister(index), operand);
+      break;
+    }
+    case kX87Xchgl: {
+      size_t index = 0;
+      Operand operand = i.MemoryOperand(&index);
+      __ xchg(i.InputRegister(index), operand);
+      break;
+    }
     case kX87PushFloat32:
       __ lea(esp, Operand(esp, -kFloatSize));
-      if (instr->InputAt(0)->IsDoubleStackSlot()) {
+      if (instr->InputAt(0)->IsFPStackSlot()) {
         __ fld_s(i.InputOperand(0));
         __ fstp_s(MemOperand(esp, 0));
-      } else if (instr->InputAt(0)->IsDoubleRegister()) {
+      } else if (instr->InputAt(0)->IsFPRegister()) {
         __ fst_s(MemOperand(esp, 0));
       } else {
         UNREACHABLE();
@@ -1706,10 +1856,10 @@
       break;
     case kX87PushFloat64:
       __ lea(esp, Operand(esp, -kDoubleSize));
-      if (instr->InputAt(0)->IsDoubleStackSlot()) {
+      if (instr->InputAt(0)->IsFPStackSlot()) {
         __ fld_d(i.InputOperand(0));
         __ fstp_d(MemOperand(esp, 0));
-      } else if (instr->InputAt(0)->IsDoubleRegister()) {
+      } else if (instr->InputAt(0)->IsFPRegister()) {
         __ fst_d(MemOperand(esp, 0));
       } else {
         UNREACHABLE();
@@ -1761,7 +1911,18 @@
     case kCheckedStoreWord64:
       UNREACHABLE();  // currently unsupported checked int64 load/store.
       break;
+    case kAtomicLoadInt8:
+    case kAtomicLoadUint8:
+    case kAtomicLoadInt16:
+    case kAtomicLoadUint16:
+    case kAtomicLoadWord32:
+    case kAtomicStoreWord8:
+    case kAtomicStoreWord16:
+    case kAtomicStoreWord32:
+      UNREACHABLE();  // Won't be generated by instruction selector.
+      break;
   }
+  return kSuccess;
 }  // NOLINT(readability/fn_size)
 
 
@@ -1837,7 +1998,7 @@
     int double_register_param_count = 0;
     int x87_layout = 0;
     for (size_t i = 0; i < instr->InputCount(); i++) {
-      if (instr->InputAt(i)->IsDoubleRegister()) {
+      if (instr->InputAt(i)->IsFPRegister()) {
         double_register_param_count++;
       }
     }
@@ -1971,12 +2132,13 @@
   __ jmp(Operand::JumpTable(input, times_4, table));
 }
 
-
-void CodeGenerator::AssembleDeoptimizerCall(
+CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
     int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
   Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
       isolate(), deoptimization_id, bailout_type);
+  if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
   __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
+  return kSuccess;
 }
 
 
@@ -2107,8 +2269,25 @@
 //                                            | RET | args |  caller frame |
 //                                            ^ esp                        ^ ebp
 
+void CodeGenerator::FinishFrame(Frame* frame) {
+  CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
+  const RegList saves = descriptor->CalleeSavedRegisters();
+  if (saves != 0) {  // Save callee-saved registers.
+    DCHECK(!info()->is_osr());
+    int pushed = 0;
+    for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
+      if (!((1 << i) & saves)) continue;
+      ++pushed;
+    }
+    frame->AllocateSavedCalleeRegisterSlots(pushed);
+  }
 
-void CodeGenerator::AssemblePrologue() {
+  // Initailize FPU state.
+  __ fninit();
+  __ fld1();
+}
+
+void CodeGenerator::AssembleConstructFrame() {
   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
   if (frame_access_state()->has_frame()) {
     if (descriptor->IsCFunctionCall()) {
@@ -2120,7 +2299,9 @@
       __ StubPrologue(info()->GetOutputStackFrameType());
     }
   }
-  int stack_shrink_slots = frame()->GetSpillSlotCount();
+
+  int shrink_slots = frame()->GetSpillSlotCount();
+
   if (info()->is_osr()) {
     // TurboFan OSR-compiled functions cannot be entered directly.
     __ Abort(kShouldNotDirectlyEnterOsrFunction);
@@ -2131,7 +2312,7 @@
     // remaining stack slots.
     if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
     osr_pc_offset_ = __ pc_offset();
-    stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
+    shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
 
     // Initailize FPU state.
     __ fninit();
@@ -2139,8 +2320,8 @@
   }
 
   const RegList saves = descriptor->CalleeSavedRegisters();
-  if (stack_shrink_slots > 0) {
-    __ sub(esp, Immediate(stack_shrink_slots * kPointerSize));
+  if (shrink_slots > 0) {
+    __ sub(esp, Immediate(shrink_slots * kPointerSize));
   }
 
   if (saves != 0) {  // Save callee-saved registers.
@@ -2151,7 +2332,6 @@
       __ push(Register::from_code(i));
       ++pushed;
     }
-    frame()->AllocateSavedCalleeRegisterSlots(pushed);
   }
 }
 
@@ -2263,7 +2443,7 @@
     } else if (src_constant.type() == Constant::kFloat32) {
       // TODO(turbofan): Can we do better here?
       uint32_t src = bit_cast<uint32_t>(src_constant.ToFloat32());
-      if (destination->IsDoubleRegister()) {
+      if (destination->IsFPRegister()) {
         __ sub(esp, Immediate(kInt32Size));
         __ mov(MemOperand(esp, 0), Immediate(src));
         // always only push one value into the x87 stack.
@@ -2271,7 +2451,7 @@
         __ fld_s(MemOperand(esp, 0));
         __ add(esp, Immediate(kInt32Size));
       } else {
-        DCHECK(destination->IsDoubleStackSlot());
+        DCHECK(destination->IsFPStackSlot());
         Operand dst = g.ToOperand(destination);
         __ Move(dst, Immediate(src));
       }
@@ -2280,7 +2460,7 @@
       uint64_t src = bit_cast<uint64_t>(src_constant.ToFloat64());
       uint32_t lower = static_cast<uint32_t>(src);
       uint32_t upper = static_cast<uint32_t>(src >> 32);
-      if (destination->IsDoubleRegister()) {
+      if (destination->IsFPRegister()) {
         __ sub(esp, Immediate(kDoubleSize));
         __ mov(MemOperand(esp, 0), Immediate(lower));
         __ mov(MemOperand(esp, kInt32Size), Immediate(upper));
@@ -2289,15 +2469,15 @@
         __ fld_d(MemOperand(esp, 0));
         __ add(esp, Immediate(kDoubleSize));
       } else {
-        DCHECK(destination->IsDoubleStackSlot());
+        DCHECK(destination->IsFPStackSlot());
         Operand dst0 = g.ToOperand(destination);
         Operand dst1 = g.HighOperand(destination);
         __ Move(dst0, Immediate(lower));
         __ Move(dst1, Immediate(upper));
       }
     }
-  } else if (source->IsDoubleRegister()) {
-    DCHECK(destination->IsDoubleStackSlot());
+  } else if (source->IsFPRegister()) {
+    DCHECK(destination->IsFPStackSlot());
     Operand dst = g.ToOperand(destination);
     auto allocated = AllocatedOperand::cast(*source);
     switch (allocated.representation()) {
@@ -2310,11 +2490,11 @@
       default:
         UNREACHABLE();
     }
-  } else if (source->IsDoubleStackSlot()) {
-    DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
+  } else if (source->IsFPStackSlot()) {
+    DCHECK(destination->IsFPRegister() || destination->IsFPStackSlot());
     Operand src = g.ToOperand(source);
     auto allocated = AllocatedOperand::cast(*source);
-    if (destination->IsDoubleRegister()) {
+    if (destination->IsFPRegister()) {
       // always only push one value into the x87 stack.
       __ fstp(0);
       switch (allocated.representation()) {
@@ -2373,9 +2553,9 @@
     frame_access_state()->IncreaseSPDelta(-1);
     Operand src2 = g.ToOperand(source);
     __ pop(src2);
-  } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) {
+  } else if (source->IsFPRegister() && destination->IsFPRegister()) {
     UNREACHABLE();
-  } else if (source->IsDoubleRegister() && destination->IsDoubleStackSlot()) {
+  } else if (source->IsFPRegister() && destination->IsFPStackSlot()) {
     auto allocated = AllocatedOperand::cast(*source);
     switch (allocated.representation()) {
       case MachineRepresentation::kFloat32:
@@ -2391,7 +2571,7 @@
       default:
         UNREACHABLE();
     }
-  } else if (source->IsDoubleStackSlot() && destination->IsDoubleStackSlot()) {
+  } else if (source->IsFPStackSlot() && destination->IsFPStackSlot()) {
     auto allocated = AllocatedOperand::cast(*source);
     switch (allocated.representation()) {
       case MachineRepresentation::kFloat32:
@@ -2423,9 +2603,6 @@
 }
 
 
-void CodeGenerator::AddNopForSmiCodeInlining() { __ nop(); }
-
-
 void CodeGenerator::EnsureSpaceForLazyDeopt() {
   if (!info()->ShouldEnsureSpaceForLazyDeopt()) {
     return;
diff --git a/src/compiler/x87/instruction-codes-x87.h b/src/compiler/x87/instruction-codes-x87.h
index d70a737..2b4be3e 100644
--- a/src/compiler/x87/instruction-codes-x87.h
+++ b/src/compiler/x87/instruction-codes-x87.h
@@ -80,6 +80,7 @@
   V(X87Float64Sqrt)                \
   V(X87Float64Round)               \
   V(X87Float64Cmp)                 \
+  V(X87Float64SilenceNaN)          \
   V(X87Movsxbl)                    \
   V(X87Movzxbl)                    \
   V(X87Movb)                       \
@@ -96,7 +97,10 @@
   V(X87PushFloat64)                \
   V(X87PushFloat32)                \
   V(X87Poke)                       \
-  V(X87StackCheck)
+  V(X87StackCheck)                 \
+  V(X87Xchgb)                      \
+  V(X87Xchgw)                      \
+  V(X87Xchgl)
 
 // Addressing modes represent the "shape" of inputs to an instruction.
 // Many instructions support multiple addressing modes. Addressing modes
diff --git a/src/compiler/x87/instruction-selector-x87.cc b/src/compiler/x87/instruction-selector-x87.cc
index e4d085e..45779c7 100644
--- a/src/compiler/x87/instruction-selector-x87.cc
+++ b/src/compiler/x87/instruction-selector-x87.cc
@@ -27,11 +27,15 @@
     return DefineAsRegister(node);
   }
 
-  bool CanBeMemoryOperand(InstructionCode opcode, Node* node, Node* input) {
+  bool CanBeMemoryOperand(InstructionCode opcode, Node* node, Node* input,
+                          int effect_level) {
     if (input->opcode() != IrOpcode::kLoad ||
         !selector()->CanCover(node, input)) {
       return false;
     }
+    if (effect_level != selector()->GetEffectLevel(input)) {
+      return false;
+    }
     MachineRepresentation rep =
         LoadRepresentationOf(input->op()).representation();
     switch (opcode) {
@@ -60,13 +64,20 @@
       case IrOpcode::kInt32Constant:
       case IrOpcode::kNumberConstant:
       case IrOpcode::kExternalConstant:
+      case IrOpcode::kRelocatableInt32Constant:
+      case IrOpcode::kRelocatableInt64Constant:
         return true;
       case IrOpcode::kHeapConstant: {
+// TODO(bmeurer): We must not dereference handles concurrently. If we
+// really have to this here, then we need to find a way to put this
+// information on the HeapConstant node already.
+#if 0
         // Constants in new space cannot be used as immediates in V8 because
         // the GC does not scan code objects when collecting the new generation.
         Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node);
         Isolate* isolate = value->GetIsolate();
         return !isolate->heap()->InNewSpace(*value);
+#endif
       }
       default:
         return false;
@@ -842,21 +853,15 @@
        g.Use(node->InputAt(0)));
 }
 
-
-void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
+void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
   X87OperandGenerator g(this);
+  Emit(kArchTruncateDoubleToI, g.DefineAsRegister(node),
+       g.Use(node->InputAt(0)));
+}
 
-  switch (TruncationModeOf(node->op())) {
-    case TruncationMode::kJavaScript:
-      Emit(kArchTruncateDoubleToI, g.DefineAsRegister(node),
-           g.Use(node->InputAt(0)));
-      return;
-    case TruncationMode::kRoundToZero:
-      Emit(kX87Float64ToInt32, g.DefineAsRegister(node),
-           g.Use(node->InputAt(0)));
-      return;
-  }
-  UNREACHABLE();
+void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
+  X87OperandGenerator g(this);
+  Emit(kX87Float64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
 }
 
 
@@ -896,6 +901,12 @@
   Emit(kX87Float32Sub, g.DefineAsFixed(node, stX_0), 0, nullptr);
 }
 
+void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
+  X87OperandGenerator g(this);
+  Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0)));
+  Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(1)));
+  Emit(kX87Float32Sub, g.DefineAsFixed(node, stX_0), 0, nullptr);
+}
 
 void InstructionSelector::VisitFloat64Sub(Node* node) {
   X87OperandGenerator g(this);
@@ -904,6 +915,13 @@
   Emit(kX87Float64Sub, g.DefineAsFixed(node, stX_0), 0, nullptr);
 }
 
+void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
+  X87OperandGenerator g(this);
+  Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0)));
+  Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(1)));
+  Emit(kX87Float64Sub, g.DefineAsFixed(node, stX_0), 0, nullptr);
+}
+
 
 void InstructionSelector::VisitFloat32Mul(Node* node) {
   X87OperandGenerator g(this);
@@ -991,7 +1009,6 @@
   Emit(kX87Float64Abs, g.DefineAsFixed(node, stX_0), 0, nullptr);
 }
 
-
 void InstructionSelector::VisitFloat32Sqrt(Node* node) {
   X87OperandGenerator g(this);
   Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0)));
@@ -1066,6 +1083,24 @@
        g.UseFixed(node, stX_0), g.Use(node->InputAt(0)));
 }
 
+void InstructionSelector::VisitFloat32Neg(Node* node) { UNREACHABLE(); }
+
+void InstructionSelector::VisitFloat64Neg(Node* node) { UNREACHABLE(); }
+
+void InstructionSelector::VisitFloat64Ieee754Binop(Node* node,
+                                                   InstructionCode opcode) {
+  X87OperandGenerator g(this);
+  Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0)));
+  Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(1)));
+  Emit(opcode, g.DefineAsFixed(node, stX_0), 0, nullptr)->MarkAsCall();
+}
+
+void InstructionSelector::VisitFloat64Ieee754Unop(Node* node,
+                                                  InstructionCode opcode) {
+  X87OperandGenerator g(this);
+  Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0)));
+  Emit(opcode, g.DefineAsFixed(node, stX_0), 0, nullptr)->MarkAsCall();
+}
 
 void InstructionSelector::EmitPrepareArguments(
     ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
@@ -1100,7 +1135,7 @@
           g.CanBeImmediate(input.node())
               ? g.UseImmediate(input.node())
               : IsSupported(ATOM) ||
-                        sequence()->IsFloat(GetVirtualRegister(input.node()))
+                        sequence()->IsFP(GetVirtualRegister(input.node()))
                     ? g.UseRegister(input.node())
                     : g.Use(input.node());
       Emit(kX87Push, g.NoOutput(), value);
@@ -1254,18 +1289,24 @@
 
   InstructionCode narrowed_opcode = TryNarrowOpcodeSize(opcode, left, right);
 
+  int effect_level = selector->GetEffectLevel(node);
+  if (cont->IsBranch()) {
+    effect_level = selector->GetEffectLevel(
+        cont->true_block()->PredecessorAt(0)->control_input());
+  }
+
   // If one of the two inputs is an immediate, make sure it's on the right, or
   // if one of the two inputs is a memory operand, make sure it's on the left.
   if ((!g.CanBeImmediate(right) && g.CanBeImmediate(left)) ||
-      (g.CanBeMemoryOperand(narrowed_opcode, node, right) &&
-       !g.CanBeMemoryOperand(narrowed_opcode, node, left))) {
+      (g.CanBeMemoryOperand(narrowed_opcode, node, right, effect_level) &&
+       !g.CanBeMemoryOperand(narrowed_opcode, node, left, effect_level))) {
     if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
     std::swap(left, right);
   }
 
   // Match immediates on right side of comparison.
   if (g.CanBeImmediate(right)) {
-    if (g.CanBeMemoryOperand(opcode, node, left)) {
+    if (g.CanBeMemoryOperand(opcode, node, left, effect_level)) {
       // TODO(epertoso): we should use `narrowed_opcode' here once we match
       // immediates too.
       return VisitCompareWithMemoryOperand(selector, opcode, left,
@@ -1276,7 +1317,7 @@
   }
 
   // Match memory operands on left side of comparison.
-  if (g.CanBeMemoryOperand(narrowed_opcode, node, left)) {
+  if (g.CanBeMemoryOperand(narrowed_opcode, node, left, effect_level)) {
     bool needs_byte_register =
         narrowed_opcode == kX87Test8 || narrowed_opcode == kX87Cmp8;
     return VisitCompareWithMemoryOperand(
@@ -1588,6 +1629,58 @@
        g.UseRegister(left), g.UseRegister(right));
 }
 
+void InstructionSelector::VisitFloat64SilenceNaN(Node* node) {
+  X87OperandGenerator g(this);
+  Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0)));
+  Emit(kX87Float64SilenceNaN, g.DefineAsFixed(node, stX_0), 0, nullptr);
+}
+
+void InstructionSelector::VisitAtomicLoad(Node* node) {
+  LoadRepresentation load_rep = LoadRepresentationOf(node->op());
+  DCHECK(load_rep.representation() == MachineRepresentation::kWord8 ||
+         load_rep.representation() == MachineRepresentation::kWord16 ||
+         load_rep.representation() == MachineRepresentation::kWord32);
+  USE(load_rep);
+  VisitLoad(node);
+}
+
+void InstructionSelector::VisitAtomicStore(Node* node) {
+  X87OperandGenerator g(this);
+  Node* base = node->InputAt(0);
+  Node* index = node->InputAt(1);
+  Node* value = node->InputAt(2);
+
+  MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
+  ArchOpcode opcode = kArchNop;
+  switch (rep) {
+    case MachineRepresentation::kWord8:
+      opcode = kX87Xchgb;
+      break;
+    case MachineRepresentation::kWord16:
+      opcode = kX87Xchgw;
+      break;
+    case MachineRepresentation::kWord32:
+      opcode = kX87Xchgl;
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+  AddressingMode addressing_mode;
+  InstructionOperand inputs[4];
+  size_t input_count = 0;
+  inputs[input_count++] = g.UseUniqueRegister(base);
+  if (g.CanBeImmediate(index)) {
+    inputs[input_count++] = g.UseImmediate(index);
+    addressing_mode = kMode_MRI;
+  } else {
+    inputs[input_count++] = g.UseUniqueRegister(index);
+    addressing_mode = kMode_MR1;
+  }
+  inputs[input_count++] = g.UseUniqueRegister(value);
+  InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
+  Emit(code, 0, nullptr, input_count, inputs);
+}
 
 // static
 MachineOperatorBuilder::Flags
@@ -1613,6 +1706,13 @@
   return flags;
 }
 
+// static
+MachineOperatorBuilder::AlignmentRequirements
+InstructionSelector::AlignmentRequirements() {
+  return MachineOperatorBuilder::AlignmentRequirements::
+      FullUnalignedAccessSupport();
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/src/context-measure.cc b/src/context-measure.cc
index 3423629..00c11ee 100644
--- a/src/context-measure.cc
+++ b/src/context-measure.cc
@@ -18,7 +18,7 @@
       count_(0),
       size_(0) {
   DCHECK(context_->IsNativeContext());
-  Object* next_link = context_->get(Context::NEXT_CONTEXT_LINK);
+  Object* next_link = context_->next_context_link();
   MeasureObject(context_);
   MeasureDeferredObjects();
   context_->set(Context::NEXT_CONTEXT_LINK, next_link);
@@ -37,10 +37,10 @@
 
 
 void ContextMeasure::MeasureObject(HeapObject* object) {
-  if (back_reference_map_.Lookup(object).is_valid()) return;
+  if (reference_map_.Lookup(object).is_valid()) return;
   if (root_index_map_.Lookup(object) != RootIndexMap::kInvalidRootIndex) return;
   if (IsShared(object)) return;
-  back_reference_map_.Add(object, BackReference::DummyReference());
+  reference_map_.Add(object, SerializerReference::DummyReference());
   recursion_depth_++;
   if (recursion_depth_ > kMaxRecursion) {
     deferred_objects_.Add(object);
diff --git a/src/context-measure.h b/src/context-measure.h
index 665c547..7e94f2c 100644
--- a/src/context-measure.h
+++ b/src/context-measure.h
@@ -29,7 +29,7 @@
 
   Context* context_;
 
-  BackReferenceMap back_reference_map_;
+  SerializerReferenceMap reference_map_;
   RootIndexMap root_index_map_;
 
   static const int kMaxRecursion = 16;
diff --git a/src/contexts-inl.h b/src/contexts-inl.h
index 344d5db..990b50e 100644
--- a/src/contexts-inl.h
+++ b/src/contexts-inl.h
@@ -56,8 +56,9 @@
 }
 void Context::set_previous(Context* context) { set(PREVIOUS_INDEX, context); }
 
+Object* Context::next_context_link() { return get(Context::NEXT_CONTEXT_LINK); }
 
-bool Context::has_extension() { return !extension()->IsTheHole(); }
+bool Context::has_extension() { return !extension()->IsTheHole(GetIsolate()); }
 HeapObject* Context::extension() {
   return HeapObject::cast(get(EXTENSION_INDEX));
 }
diff --git a/src/contexts.cc b/src/contexts.cc
index 67a9fea..aa46b47 100644
--- a/src/contexts.cc
+++ b/src/contexts.cc
@@ -92,7 +92,7 @@
 JSObject* Context::extension_object() {
   DCHECK(IsNativeContext() || IsFunctionContext() || IsBlockContext());
   HeapObject* object = extension();
-  if (object->IsTheHole()) return nullptr;
+  if (object->IsTheHole(GetIsolate())) return nullptr;
   if (IsBlockContext()) {
     if (!object->IsSloppyBlockWithEvalContextExtension()) return nullptr;
     object = SloppyBlockWithEvalContextExtension::cast(object)->extension();
@@ -184,29 +184,24 @@
   switch (mode) {
     case VAR:
       *attributes = NONE;
-      *binding_flags = MUTABLE_IS_INITIALIZED;
+      *binding_flags = BINDING_IS_INITIALIZED;
       break;
     case LET:
       *attributes = NONE;
       *binding_flags = (init_flag == kNeedsInitialization)
-                           ? MUTABLE_CHECK_INITIALIZED
-                           : MUTABLE_IS_INITIALIZED;
+                           ? BINDING_CHECK_INITIALIZED
+                           : BINDING_IS_INITIALIZED;
       break;
     case CONST_LEGACY:
+      DCHECK_EQ(kCreatedInitialized, init_flag);
       *attributes = READ_ONLY;
-      *binding_flags = (init_flag == kNeedsInitialization)
-                           ? IMMUTABLE_CHECK_INITIALIZED
-                           : IMMUTABLE_IS_INITIALIZED;
+      *binding_flags = BINDING_IS_INITIALIZED;
       break;
     case CONST:
       *attributes = READ_ONLY;
       *binding_flags = (init_flag == kNeedsInitialization)
-                           ? IMMUTABLE_CHECK_INITIALIZED_HARMONY
-                           : IMMUTABLE_IS_INITIALIZED_HARMONY;
-      break;
-    case IMPORT:
-      // TODO(ES6)
-      UNREACHABLE();
+                           ? BINDING_CHECK_INITIALIZED
+                           : BINDING_IS_INITIALIZED;
       break;
     case DYNAMIC:
     case DYNAMIC_GLOBAL:
@@ -362,8 +357,7 @@
           *index = function_index;
           *attributes = READ_ONLY;
           DCHECK(mode == CONST_LEGACY || mode == CONST);
-          *binding_flags = (mode == CONST_LEGACY)
-              ? IMMUTABLE_IS_INITIALIZED : IMMUTABLE_IS_INITIALIZED_HARMONY;
+          *binding_flags = BINDING_IS_INITIALIZED;
           return context;
         }
       }
@@ -376,7 +370,7 @@
         }
         *index = Context::THROWN_OBJECT_INDEX;
         *attributes = NONE;
-        *binding_flags = MUTABLE_IS_INITIALIZED;
+        *binding_flags = BINDING_IS_INITIALIZED;
         return context;
       }
     } else if (context->IsDebugEvaluateContext()) {
@@ -449,10 +443,11 @@
 
 void Context::AddOptimizedFunction(JSFunction* function) {
   DCHECK(IsNativeContext());
+  Isolate* isolate = GetIsolate();
 #ifdef ENABLE_SLOW_DCHECKS
   if (FLAG_enable_slow_asserts) {
     Object* element = get(OPTIMIZED_FUNCTIONS_LIST);
-    while (!element->IsUndefined()) {
+    while (!element->IsUndefined(isolate)) {
       CHECK(element != function);
       element = JSFunction::cast(element)->next_function_link();
     }
@@ -460,25 +455,25 @@
 
   // Check that the context belongs to the weak native contexts list.
   bool found = false;
-  Object* context = GetHeap()->native_contexts_list();
-  while (!context->IsUndefined()) {
+  Object* context = isolate->heap()->native_contexts_list();
+  while (!context->IsUndefined(isolate)) {
     if (context == this) {
       found = true;
       break;
     }
-    context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
+    context = Context::cast(context)->next_context_link();
   }
   CHECK(found);
 #endif
 
   // If the function link field is already used then the function was
   // enqueued as a code flushing candidate and we remove it now.
-  if (!function->next_function_link()->IsUndefined()) {
+  if (!function->next_function_link()->IsUndefined(isolate)) {
     CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
     flusher->EvictCandidate(function);
   }
 
-  DCHECK(function->next_function_link()->IsUndefined());
+  DCHECK(function->next_function_link()->IsUndefined(isolate));
 
   function->set_next_function_link(get(OPTIMIZED_FUNCTIONS_LIST),
                                    UPDATE_WEAK_WRITE_BARRIER);
@@ -490,9 +485,10 @@
   DCHECK(IsNativeContext());
   Object* element = get(OPTIMIZED_FUNCTIONS_LIST);
   JSFunction* prev = NULL;
-  while (!element->IsUndefined()) {
+  Isolate* isolate = function->GetIsolate();
+  while (!element->IsUndefined(isolate)) {
     JSFunction* element_function = JSFunction::cast(element);
-    DCHECK(element_function->next_function_link()->IsUndefined() ||
+    DCHECK(element_function->next_function_link()->IsUndefined(isolate) ||
            element_function->next_function_link()->IsJSFunction());
     if (element_function == function) {
       if (prev == NULL) {
@@ -528,7 +524,7 @@
 void Context::AddOptimizedCode(Code* code) {
   DCHECK(IsNativeContext());
   DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
-  DCHECK(code->next_code_link()->IsUndefined());
+  DCHECK(code->next_code_link()->IsUndefined(GetIsolate()));
   code->set_next_code_link(get(OPTIMIZED_CODE_LIST));
   set(OPTIMIZED_CODE_LIST, code, UPDATE_WEAK_WRITE_BARRIER);
 }
@@ -561,7 +557,7 @@
 Handle<Object> Context::ErrorMessageForCodeGenerationFromStrings() {
   Isolate* isolate = GetIsolate();
   Handle<Object> result(error_message_for_code_gen_from_strings(), isolate);
-  if (!result->IsUndefined()) return result;
+  if (!result->IsUndefined(isolate)) return result;
   return isolate->factory()->NewStringFromStaticChars(
       "Code generation from strings disallowed for this context");
 }
diff --git a/src/contexts.h b/src/contexts.h
index 90fb9a4..78ec431 100644
--- a/src/contexts.h
+++ b/src/contexts.h
@@ -30,44 +30,34 @@
 // their state is changed by the InitializeImmutableBinding method. The
 // BindingFlags enum represents information if a binding has definitely been
 // initialized. A mutable binding does not need to be checked and thus has
-// the BindingFlag MUTABLE_IS_INITIALIZED.
+// the BindingFlag BINDING_IS_INITIALIZED.
 //
-// There are two possibilities for immutable bindings
-//  * 'const' declared variables. They are initialized when evaluating the
-//    corresponding declaration statement. They need to be checked for being
-//    initialized and thus get the flag IMMUTABLE_CHECK_INITIALIZED.
+// There is one possibility for legacy immutable bindings:
 //  * The function name of a named function literal. The binding is immediately
 //    initialized when entering the function and thus does not need to be
-//    checked. it gets the BindingFlag IMMUTABLE_IS_INITIALIZED.
-// Accessing an uninitialized binding produces the undefined value.
+//    checked. it gets the BindingFlag BINDING_IS_INITIALIZED.
 //
 // The harmony proposal for block scoped bindings also introduces the
 // uninitialized state for mutable bindings.
 //  * A 'let' declared variable. They are initialized when evaluating the
 //    corresponding declaration statement. They need to be checked for being
-//    initialized and thus get the flag MUTABLE_CHECK_INITIALIZED.
+//    initialized and thus get the flag BINDING_CHECK_INITIALIZED.
 //  * A 'var' declared variable. It is initialized immediately upon creation
 //    and thus doesn't need to be checked. It gets the flag
-//    MUTABLE_IS_INITIALIZED.
+//    BINDING_IS_INITIALIZED.
 //  * Catch bound variables, function parameters and variables introduced by
 //    function declarations are initialized immediately and do not need to be
-//    checked. Thus they get the flag MUTABLE_IS_INITIALIZED.
-// Immutable bindings in harmony mode get the _HARMONY flag variants. Accessing
-// an uninitialized binding produces a reference error.
+//    checked. Thus they get the flag BINDING_IS_INITIALIZED.
+// Accessing an uninitialized binding produces a reference error.
 //
 // In V8 uninitialized bindings are set to the hole value upon creation and set
 // to a different value upon initialization.
 enum BindingFlags {
-  MUTABLE_IS_INITIALIZED,
-  MUTABLE_CHECK_INITIALIZED,
-  IMMUTABLE_IS_INITIALIZED,
-  IMMUTABLE_CHECK_INITIALIZED,
-  IMMUTABLE_IS_INITIALIZED_HARMONY,
-  IMMUTABLE_CHECK_INITIALIZED_HARMONY,
+  BINDING_IS_INITIALIZED,
+  BINDING_CHECK_INITIALIZED,
   MISSING_BINDING
 };
 
-
 // Heap-allocated activation contexts.
 //
 // Contexts are implemented as FixedArray objects; the Context
@@ -77,79 +67,77 @@
 // must always be allocated via Heap::AllocateContext() or
 // Factory::NewContext.
 
-#define NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(V)                             \
-  V(IS_ARRAYLIKE, JSFunction, is_arraylike)                               \
-  V(GET_TEMPLATE_CALL_SITE_INDEX, JSFunction, get_template_call_site)     \
-  V(MAKE_RANGE_ERROR_INDEX, JSFunction, make_range_error)                 \
-  V(MAKE_TYPE_ERROR_INDEX, JSFunction, make_type_error)                   \
-  V(OBJECT_FREEZE, JSFunction, object_freeze)                             \
-  V(OBJECT_IS_EXTENSIBLE, JSFunction, object_is_extensible)               \
-  V(OBJECT_IS_FROZEN, JSFunction, object_is_frozen)                       \
-  V(OBJECT_IS_SEALED, JSFunction, object_is_sealed)                       \
-  V(OBJECT_KEYS, JSFunction, object_keys)                                 \
-  V(REFLECT_APPLY_INDEX, JSFunction, reflect_apply)                       \
-  V(REFLECT_CONSTRUCT_INDEX, JSFunction, reflect_construct)               \
-  V(REFLECT_DEFINE_PROPERTY_INDEX, JSFunction, reflect_define_property)   \
-  V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property)   \
-  V(SPREAD_ARGUMENTS_INDEX, JSFunction, spread_arguments)                 \
-  V(SPREAD_ITERABLE_INDEX, JSFunction, spread_iterable)                   \
-  V(ORDINARY_HAS_INSTANCE_INDEX, JSFunction, ordinary_has_instance)       \
-  V(MATH_FLOOR, JSFunction, math_floor)                                   \
-  V(MATH_SQRT, JSFunction, math_sqrt)
+#define NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(V)                           \
+  V(IS_ARRAYLIKE, JSFunction, is_arraylike)                             \
+  V(GET_TEMPLATE_CALL_SITE_INDEX, JSFunction, get_template_call_site)   \
+  V(MAKE_RANGE_ERROR_INDEX, JSFunction, make_range_error)               \
+  V(MAKE_TYPE_ERROR_INDEX, JSFunction, make_type_error)                 \
+  V(OBJECT_DEFINE_PROPERTIES, JSFunction, object_define_properties)     \
+  V(OBJECT_DEFINE_PROPERTY, JSFunction, object_define_property)         \
+  V(OBJECT_FREEZE, JSFunction, object_freeze)                           \
+  V(OBJECT_GET_PROTOTYPE_OF, JSFunction, object_get_prototype_of)       \
+  V(OBJECT_IS_EXTENSIBLE, JSFunction, object_is_extensible)             \
+  V(OBJECT_IS_FROZEN, JSFunction, object_is_frozen)                     \
+  V(OBJECT_IS_SEALED, JSFunction, object_is_sealed)                     \
+  V(OBJECT_KEYS, JSFunction, object_keys)                               \
+  V(REFLECT_APPLY_INDEX, JSFunction, reflect_apply)                     \
+  V(REFLECT_CONSTRUCT_INDEX, JSFunction, reflect_construct)             \
+  V(REFLECT_DEFINE_PROPERTY_INDEX, JSFunction, reflect_define_property) \
+  V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property) \
+  V(SPREAD_ARGUMENTS_INDEX, JSFunction, spread_arguments)               \
+  V(SPREAD_ITERABLE_INDEX, JSFunction, spread_iterable)                 \
+  V(MATH_EXP_INDEX, JSFunction, math_exp)                               \
+  V(MATH_FLOOR_INDEX, JSFunction, math_floor)                           \
+  V(MATH_LOG_INDEX, JSFunction, math_log)                               \
+  V(MATH_SQRT_INDEX, JSFunction, math_sqrt)
 
-#define NATIVE_CONTEXT_IMPORTED_FIELDS(V)                                     \
-  V(ARRAY_CONCAT_INDEX, JSFunction, array_concat)                             \
-  V(ARRAY_POP_INDEX, JSFunction, array_pop)                                   \
-  V(ARRAY_PUSH_INDEX, JSFunction, array_push)                                 \
-  V(ARRAY_SHIFT_INDEX, JSFunction, array_shift)                               \
-  V(ARRAY_SPLICE_INDEX, JSFunction, array_splice)                             \
-  V(ARRAY_SLICE_INDEX, JSFunction, array_slice)                               \
-  V(ARRAY_UNSHIFT_INDEX, JSFunction, array_unshift)                           \
-  V(ARRAY_VALUES_ITERATOR_INDEX, JSFunction, array_values_iterator)           \
-  V(DERIVED_GET_TRAP_INDEX, JSFunction, derived_get_trap)                     \
-  V(ERROR_FUNCTION_INDEX, JSFunction, error_function)                         \
-  V(EVAL_ERROR_FUNCTION_INDEX, JSFunction, eval_error_function)               \
-  V(GET_STACK_TRACE_LINE_INDEX, JSFunction, get_stack_trace_line_fun)         \
-  V(GLOBAL_EVAL_FUN_INDEX, JSFunction, global_eval_fun)                       \
-  V(JSON_SERIALIZE_ADAPTER_INDEX, JSFunction, json_serialize_adapter)         \
-  V(MAKE_ERROR_FUNCTION_INDEX, JSFunction, make_error_function)               \
-  V(MAP_DELETE_METHOD_INDEX, JSFunction, map_delete)                          \
-  V(MAP_GET_METHOD_INDEX, JSFunction, map_get)                                \
-  V(MAP_HAS_METHOD_INDEX, JSFunction, map_has)                                \
-  V(MAP_SET_METHOD_INDEX, JSFunction, map_set)                                \
-  V(MATH_POW_METHOD_INDEX, JSFunction, math_pow)                              \
-  V(MESSAGE_GET_COLUMN_NUMBER_INDEX, JSFunction, message_get_column_number)   \
-  V(MESSAGE_GET_LINE_NUMBER_INDEX, JSFunction, message_get_line_number)       \
-  V(MESSAGE_GET_SOURCE_LINE_INDEX, JSFunction, message_get_source_line)       \
-  V(NATIVE_OBJECT_GET_NOTIFIER_INDEX, JSFunction, native_object_get_notifier) \
-  V(NATIVE_OBJECT_NOTIFIER_PERFORM_CHANGE, JSFunction,                        \
-    native_object_notifier_perform_change)                                    \
-  V(NATIVE_OBJECT_OBSERVE_INDEX, JSFunction, native_object_observe)           \
-  V(NO_SIDE_EFFECTS_TO_STRING_FUN_INDEX, JSFunction,                          \
-    no_side_effects_to_string_fun)                                            \
-  V(OBJECT_VALUE_OF, JSFunction, object_value_of)                             \
-  V(OBJECT_TO_STRING, JSFunction, object_to_string)                           \
-  V(OBSERVERS_BEGIN_SPLICE_INDEX, JSFunction, observers_begin_perform_splice) \
-  V(OBSERVERS_END_SPLICE_INDEX, JSFunction, observers_end_perform_splice)     \
-  V(OBSERVERS_ENQUEUE_SPLICE_INDEX, JSFunction, observers_enqueue_splice)     \
-  V(OBSERVERS_NOTIFY_CHANGE_INDEX, JSFunction, observers_notify_change)       \
-  V(PROMISE_CATCH_INDEX, JSFunction, promise_catch)                           \
-  V(PROMISE_CHAIN_INDEX, JSFunction, promise_chain)                           \
-  V(PROMISE_CREATE_INDEX, JSFunction, promise_create)                         \
-  V(PROMISE_FUNCTION_INDEX, JSFunction, promise_function)                     \
-  V(PROMISE_HAS_USER_DEFINED_REJECT_HANDLER_INDEX, JSFunction,                \
-    promise_has_user_defined_reject_handler)                                  \
-  V(PROMISE_REJECT_INDEX, JSFunction, promise_reject)                         \
-  V(PROMISE_RESOLVE_INDEX, JSFunction, promise_resolve)                       \
-  V(PROMISE_THEN_INDEX, JSFunction, promise_then)                             \
-  V(RANGE_ERROR_FUNCTION_INDEX, JSFunction, range_error_function)             \
-  V(REFERENCE_ERROR_FUNCTION_INDEX, JSFunction, reference_error_function)     \
-  V(SET_ADD_METHOD_INDEX, JSFunction, set_add)                                \
-  V(SET_DELETE_METHOD_INDEX, JSFunction, set_delete)                          \
-  V(SET_HAS_METHOD_INDEX, JSFunction, set_has)                                \
-  V(STACK_OVERFLOW_BOILERPLATE_INDEX, JSObject, stack_overflow_boilerplate)   \
-  V(SYNTAX_ERROR_FUNCTION_INDEX, JSFunction, syntax_error_function)           \
-  V(TYPE_ERROR_FUNCTION_INDEX, JSFunction, type_error_function)               \
+#define NATIVE_CONTEXT_IMPORTED_FIELDS(V)                                   \
+  V(ARRAY_CONCAT_INDEX, JSFunction, array_concat)                           \
+  V(ARRAY_POP_INDEX, JSFunction, array_pop)                                 \
+  V(ARRAY_PUSH_INDEX, JSFunction, array_push)                               \
+  V(ARRAY_SHIFT_INDEX, JSFunction, array_shift)                             \
+  V(ARRAY_SPLICE_INDEX, JSFunction, array_splice)                           \
+  V(ARRAY_SLICE_INDEX, JSFunction, array_slice)                             \
+  V(ARRAY_UNSHIFT_INDEX, JSFunction, array_unshift)                         \
+  V(ARRAY_VALUES_ITERATOR_INDEX, JSFunction, array_values_iterator)         \
+  V(ASYNC_FUNCTION_AWAIT_INDEX, JSFunction, async_function_await)           \
+  V(DERIVED_GET_TRAP_INDEX, JSFunction, derived_get_trap)                   \
+  V(ERROR_FUNCTION_INDEX, JSFunction, error_function)                       \
+  V(EVAL_ERROR_FUNCTION_INDEX, JSFunction, eval_error_function)             \
+  V(GET_STACK_TRACE_LINE_INDEX, JSFunction, get_stack_trace_line_fun)       \
+  V(GLOBAL_EVAL_FUN_INDEX, JSFunction, global_eval_fun)                     \
+  V(MAKE_ERROR_FUNCTION_INDEX, JSFunction, make_error_function)             \
+  V(MAP_DELETE_METHOD_INDEX, JSFunction, map_delete)                        \
+  V(MAP_GET_METHOD_INDEX, JSFunction, map_get)                              \
+  V(MAP_HAS_METHOD_INDEX, JSFunction, map_has)                              \
+  V(MAP_SET_METHOD_INDEX, JSFunction, map_set)                              \
+  V(MATH_POW_METHOD_INDEX, JSFunction, math_pow)                            \
+  V(MESSAGE_GET_COLUMN_NUMBER_INDEX, JSFunction, message_get_column_number) \
+  V(MESSAGE_GET_LINE_NUMBER_INDEX, JSFunction, message_get_line_number)     \
+  V(MESSAGE_GET_SOURCE_LINE_INDEX, JSFunction, message_get_source_line)     \
+  V(NO_SIDE_EFFECTS_TO_STRING_FUN_INDEX, JSFunction,                        \
+    no_side_effects_to_string_fun)                                          \
+  V(OBJECT_VALUE_OF, JSFunction, object_value_of)                           \
+  V(OBJECT_TO_STRING, JSFunction, object_to_string)                         \
+  V(PROMISE_CATCH_INDEX, JSFunction, promise_catch)                         \
+  V(PROMISE_CHAIN_INDEX, JSFunction, promise_chain)                         \
+  V(PROMISE_CREATE_INDEX, JSFunction, promise_create)                       \
+  V(PROMISE_FUNCTION_INDEX, JSFunction, promise_function)                   \
+  V(PROMISE_HAS_USER_DEFINED_REJECT_HANDLER_INDEX, JSFunction,              \
+    promise_has_user_defined_reject_handler)                                \
+  V(PROMISE_REJECT_INDEX, JSFunction, promise_reject)                       \
+  V(PROMISE_RESOLVE_INDEX, JSFunction, promise_resolve)                     \
+  V(PROMISE_CREATE_RESOLVED_INDEX, JSFunction, promise_create_resolved)     \
+  V(PROMISE_CREATE_REJECTED_INDEX, JSFunction, promise_create_rejected)     \
+  V(PROMISE_THEN_INDEX, JSFunction, promise_then)                           \
+  V(RANGE_ERROR_FUNCTION_INDEX, JSFunction, range_error_function)           \
+  V(REFERENCE_ERROR_FUNCTION_INDEX, JSFunction, reference_error_function)   \
+  V(SET_ADD_METHOD_INDEX, JSFunction, set_add)                              \
+  V(SET_DELETE_METHOD_INDEX, JSFunction, set_delete)                        \
+  V(SET_HAS_METHOD_INDEX, JSFunction, set_has)                              \
+  V(STACK_OVERFLOW_BOILERPLATE_INDEX, JSObject, stack_overflow_boilerplate) \
+  V(SYNTAX_ERROR_FUNCTION_INDEX, JSFunction, syntax_error_function)         \
+  V(TYPE_ERROR_FUNCTION_INDEX, JSFunction, type_error_function)             \
   V(URI_ERROR_FUNCTION_INDEX, JSFunction, uri_error_function)
 
 #define NATIVE_CONTEXT_FIELDS(V)                                               \
@@ -162,6 +150,7 @@
   V(ARRAY_BUFFER_FUN_INDEX, JSFunction, array_buffer_fun)                      \
   V(ARRAY_BUFFER_MAP_INDEX, Map, array_buffer_map)                             \
   V(ARRAY_FUNCTION_INDEX, JSFunction, array_function)                          \
+  V(ASYNC_FUNCTION_FUNCTION_INDEX, JSFunction, async_function_constructor)     \
   V(BOOL16X8_FUNCTION_INDEX, JSFunction, bool16x8_function)                    \
   V(BOOL32X4_FUNCTION_INDEX, JSFunction, bool32x4_function)                    \
   V(BOOL8X16_FUNCTION_INDEX, JSFunction, bool8x16_function)                    \
@@ -193,6 +182,7 @@
     generator_function_function)                                               \
   V(GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX, Map, generator_object_prototype_map) \
   V(INITIAL_ARRAY_PROTOTYPE_INDEX, JSObject, initial_array_prototype)          \
+  V(INITIAL_GENERATOR_PROTOTYPE_INDEX, JSObject, initial_generator_prototype)  \
   V(INITIAL_OBJECT_PROTOTYPE_INDEX, JSObject, initial_object_prototype)        \
   V(INT16_ARRAY_FUN_INDEX, JSFunction, int16_array_fun)                        \
   V(INT16X8_FUNCTION_INDEX, JSFunction, int16x8_function)                      \
@@ -227,6 +217,7 @@
   V(NORMALIZED_MAP_CACHE_INDEX, Object, normalized_map_cache)                  \
   V(NUMBER_FUNCTION_INDEX, JSFunction, number_function)                        \
   V(OBJECT_FUNCTION_INDEX, JSFunction, object_function)                        \
+  V(OBJECT_WITH_NULL_PROTOTYPE_MAP, Map, object_with_null_prototype_map)       \
   V(OBJECT_FUNCTION_PROTOTYPE_MAP_INDEX, Map, object_function_prototype_map)   \
   V(OPAQUE_REFERENCE_FUNCTION_INDEX, JSFunction, opaque_reference_function)    \
   V(PROXY_CALLABLE_MAP_INDEX, Map, proxy_callable_map)                         \
@@ -249,8 +240,14 @@
   V(SLOPPY_FUNCTION_WITH_READONLY_PROTOTYPE_MAP_INDEX, Map,                    \
     sloppy_function_with_readonly_prototype_map)                               \
   V(WASM_FUNCTION_MAP_INDEX, Map, wasm_function_map)                           \
+  V(WASM_MODULE_CONSTRUCTOR_INDEX, JSFunction, wasm_module_constructor)        \
+  V(WASM_INSTANCE_CONSTRUCTOR_INDEX, JSFunction, wasm_instance_constructor)    \
+  V(WASM_MODULE_SYM_INDEX, Symbol, wasm_module_sym)                            \
+  V(WASM_INSTANCE_SYM_INDEX, Symbol, wasm_instance_sym)                        \
+  V(SLOPPY_ASYNC_FUNCTION_MAP_INDEX, Map, sloppy_async_function_map)           \
   V(SLOPPY_GENERATOR_FUNCTION_MAP_INDEX, Map, sloppy_generator_function_map)   \
   V(SLOW_ALIASED_ARGUMENTS_MAP_INDEX, Map, slow_aliased_arguments_map)         \
+  V(STRICT_ASYNC_FUNCTION_MAP_INDEX, Map, strict_async_function_map)           \
   V(STRICT_ARGUMENTS_MAP_INDEX, Map, strict_arguments_map)                     \
   V(STRICT_FUNCTION_MAP_INDEX, Map, strict_function_map)                       \
   V(STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map,                          \
@@ -259,6 +256,8 @@
   V(STRING_FUNCTION_INDEX, JSFunction, string_function)                        \
   V(STRING_FUNCTION_PROTOTYPE_MAP_INDEX, Map, string_function_prototype_map)   \
   V(SYMBOL_FUNCTION_INDEX, JSFunction, symbol_function)                        \
+  V(TYPED_ARRAY_FUN_INDEX, JSFunction, typed_array_function)                   \
+  V(TYPED_ARRAY_PROTOTYPE_INDEX, JSObject, typed_array_prototype)              \
   V(UINT16_ARRAY_FUN_INDEX, JSFunction, uint16_array_fun)                      \
   V(UINT16X8_FUNCTION_INDEX, JSFunction, uint16x8_function)                    \
   V(UINT32_ARRAY_FUN_INDEX, JSFunction, uint32_array_fun)                      \
@@ -421,6 +420,8 @@
   inline Context* previous();
   inline void set_previous(Context* context);
 
+  inline Object* next_context_link();
+
   inline bool has_extension();
   inline HeapObject* extension();
   inline void set_extension(HeapObject* object);
@@ -531,6 +532,11 @@
                                       : SLOPPY_GENERATOR_FUNCTION_MAP_INDEX;
     }
 
+    if (IsAsyncFunction(kind)) {
+      return is_strict(language_mode) ? STRICT_ASYNC_FUNCTION_MAP_INDEX
+                                      : SLOPPY_ASYNC_FUNCTION_MAP_INDEX;
+    }
+
     if (IsClassConstructor(kind)) {
       // Use strict function map (no own "caller" / "arguments")
       return STRICT_FUNCTION_MAP_INDEX;
diff --git a/src/counters-inl.h b/src/counters-inl.h
new file mode 100644
index 0000000..c8c06d2
--- /dev/null
+++ b/src/counters-inl.h
@@ -0,0 +1,24 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COUNTERS_INL_H_
+#define V8_COUNTERS_INL_H_
+
+#include "src/counters.h"
+
+namespace v8 {
+namespace internal {
+
+RuntimeCallTimerScope::RuntimeCallTimerScope(
+    HeapObject* heap_object, RuntimeCallStats::CounterId counter_id) {
+  if (V8_UNLIKELY(FLAG_runtime_call_stats)) {
+    isolate_ = heap_object->GetIsolate();
+    RuntimeCallStats::Enter(isolate_, &timer_, counter_id);
+  }
+}
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_COUNTERS_INL_H_
diff --git a/src/counters.cc b/src/counters.cc
index 4f5c251..57dad3d 100644
--- a/src/counters.cc
+++ b/src/counters.cc
@@ -9,6 +9,7 @@
 #include "src/base/platform/platform.h"
 #include "src/isolate.h"
 #include "src/log-inl.h"
+#include "src/log.h"
 
 namespace v8 {
 namespace internal {
@@ -200,14 +201,14 @@
   void Print(std::ostream& os) {
     if (total_call_count == 0) return;
     std::sort(entries.rbegin(), entries.rend());
-    os << std::setw(50) << "Runtime Function/C++ Builtin" << std::setw(10)
+    os << std::setw(50) << "Runtime Function/C++ Builtin" << std::setw(12)
        << "Time" << std::setw(18) << "Count" << std::endl
-       << std::string(86, '=') << std::endl;
+       << std::string(88, '=') << std::endl;
     for (Entry& entry : entries) {
       entry.SetTotal(total_time, total_call_count);
       entry.Print(os);
     }
-    os << std::string(86, '-') << std::endl;
+    os << std::string(88, '-') << std::endl;
     Entry("Total", total_time, total_call_count).Print(os);
   }
 
@@ -223,7 +224,7 @@
    public:
     Entry(const char* name, base::TimeDelta time, uint64_t count)
         : name_(name),
-          time_(time.InMilliseconds()),
+          time_(time.InMicroseconds()),
           count_(count),
           time_percent_(100),
           count_percent_(100) {}
@@ -236,9 +237,9 @@
 
     void Print(std::ostream& os) {
       os.precision(2);
-      os << std::fixed;
+      os << std::fixed << std::setprecision(2);
       os << std::setw(50) << name_;
-      os << std::setw(8) << time_ << "ms ";
+      os << std::setw(10) << static_cast<double>(time_) / 1000 << "ms ";
       os << std::setw(6) << time_percent_ << "%";
       os << std::setw(10) << count_ << " ";
       os << std::setw(6) << count_percent_ << "%";
@@ -246,10 +247,10 @@
     }
 
     void SetTotal(base::TimeDelta total_time, uint64_t total_count) {
-      if (total_time.InMilliseconds() == 0) {
+      if (total_time.InMicroseconds() == 0) {
         time_percent_ = 0;
       } else {
-        time_percent_ = 100.0 * time_ / total_time.InMilliseconds();
+        time_percent_ = 100.0 * time_ / total_time.InMicroseconds();
       }
       count_percent_ = 100.0 * count_ / total_count;
     }
@@ -272,68 +273,87 @@
   time = base::TimeDelta();
 }
 
-void RuntimeCallStats::Enter(RuntimeCallCounter* counter) {
-  RuntimeCallTimer* timer = new RuntimeCallTimer();
-  timer->Initialize(counter, current_timer_);
-  Enter(timer);
+// static
+void RuntimeCallStats::Enter(Isolate* isolate, RuntimeCallTimer* timer,
+                             CounterId counter_id) {
+  RuntimeCallStats* stats = isolate->counters()->runtime_call_stats();
+  RuntimeCallCounter* counter = &(stats->*counter_id);
+  timer->Start(counter, stats->current_timer_);
+  stats->current_timer_ = timer;
 }
 
-void RuntimeCallStats::Enter(RuntimeCallTimer* timer_) {
-  current_timer_ = timer_;
-  current_timer_->Start();
+// static
+void RuntimeCallStats::Leave(Isolate* isolate, RuntimeCallTimer* timer) {
+  RuntimeCallStats* stats = isolate->counters()->runtime_call_stats();
+
+  if (stats->current_timer_ == timer) {
+    stats->current_timer_ = timer->Stop();
+  } else {
+    // Must be a Threading cctest. Walk the chain of Timers to find the
+    // buried one that's leaving. We don't care about keeping nested timings
+    // accurate, just avoid crashing by keeping the chain intact.
+    RuntimeCallTimer* next = stats->current_timer_;
+    while (next->parent_ != timer) next = next->parent_;
+    next->parent_ = timer->Stop();
+  }
 }
 
-void RuntimeCallStats::Leave() {
-  RuntimeCallTimer* timer = current_timer_;
-  Leave(timer);
-  delete timer;
-}
-
-void RuntimeCallStats::Leave(RuntimeCallTimer* timer) {
-  current_timer_ = timer->Stop();
+// static
+void RuntimeCallStats::CorrectCurrentCounterId(Isolate* isolate,
+                                               CounterId counter_id) {
+  RuntimeCallStats* stats = isolate->counters()->runtime_call_stats();
+  DCHECK_NOT_NULL(stats->current_timer_);
+  RuntimeCallCounter* counter = &(stats->*counter_id);
+  stats->current_timer_->counter_ = counter;
 }
 
 void RuntimeCallStats::Print(std::ostream& os) {
   RuntimeCallStatEntries entries;
 
+#define PRINT_COUNTER(name) entries.Add(&this->name);
+  FOR_EACH_MANUAL_COUNTER(PRINT_COUNTER)
+#undef PRINT_COUNTER
+
 #define PRINT_COUNTER(name, nargs, ressize) entries.Add(&this->Runtime_##name);
   FOR_EACH_INTRINSIC(PRINT_COUNTER)
 #undef PRINT_COUNTER
 
-#define PRINT_COUNTER(name, type) entries.Add(&this->Builtin_##name);
+#define PRINT_COUNTER(name) entries.Add(&this->Builtin_##name);
   BUILTIN_LIST_C(PRINT_COUNTER)
 #undef PRINT_COUNTER
 
-  entries.Add(&this->ExternalCallback);
-  entries.Add(&this->GC);
-  entries.Add(&this->UnexpectedStubMiss);
+#define PRINT_COUNTER(name) entries.Add(&this->API_##name);
+  FOR_EACH_API_COUNTER(PRINT_COUNTER)
+#undef PRINT_COUNTER
+
+#define PRINT_COUNTER(name) entries.Add(&this->Handler_##name);
+  FOR_EACH_HANDLER_COUNTER(PRINT_COUNTER)
+#undef PRINT_COUNTER
 
   entries.Print(os);
 }
 
 void RuntimeCallStats::Reset() {
   if (!FLAG_runtime_call_stats) return;
-#define RESET_COUNTER(name, nargs, ressize) this->Runtime_##name.Reset();
+#define RESET_COUNTER(name) this->name.Reset();
+  FOR_EACH_MANUAL_COUNTER(RESET_COUNTER)
+#undef RESET_COUNTER
+
+#define RESET_COUNTER(name, nargs, result_size) this->Runtime_##name.Reset();
   FOR_EACH_INTRINSIC(RESET_COUNTER)
 #undef RESET_COUNTER
-#define RESET_COUNTER(name, type) this->Builtin_##name.Reset();
+
+#define RESET_COUNTER(name) this->Builtin_##name.Reset();
   BUILTIN_LIST_C(RESET_COUNTER)
 #undef RESET_COUNTER
-  this->ExternalCallback.Reset();
-  this->GC.Reset();
-  this->UnexpectedStubMiss.Reset();
-}
 
-void RuntimeCallTimerScope::Enter(Isolate* isolate,
-                                  RuntimeCallCounter* counter) {
-  isolate_ = isolate;
-  RuntimeCallStats* stats = isolate->counters()->runtime_call_stats();
-  timer_.Initialize(counter, stats->current_timer());
-  stats->Enter(&timer_);
-}
+#define RESET_COUNTER(name) this->API_##name.Reset();
+  FOR_EACH_API_COUNTER(RESET_COUNTER)
+#undef RESET_COUNTER
 
-void RuntimeCallTimerScope::Leave() {
-  isolate_->counters()->runtime_call_stats()->Leave(&timer_);
+#define RESET_COUNTER(name) this->Handler_##name.Reset();
+  FOR_EACH_HANDLER_COUNTER(RESET_COUNTER)
+#undef RESET_COUNTER
 }
 
 }  // namespace internal
diff --git a/src/counters.h b/src/counters.h
index 7183d0e..3c82a18 100644
--- a/src/counters.h
+++ b/src/counters.h
@@ -492,87 +492,331 @@
 // timers used for properly measuring the own time of a RuntimeCallCounter.
 class RuntimeCallTimer {
  public:
-  inline void Initialize(RuntimeCallCounter* counter,
-                         RuntimeCallTimer* parent) {
+  RuntimeCallTimer() {}
+  RuntimeCallCounter* counter() { return counter_; }
+  base::ElapsedTimer timer() { return timer_; }
+
+ private:
+  friend class RuntimeCallStats;
+
+  inline void Start(RuntimeCallCounter* counter, RuntimeCallTimer* parent) {
     counter_ = counter;
     parent_ = parent;
-  }
-
-  inline void Start() {
     timer_.Start();
-    counter_->count++;
   }
 
   inline RuntimeCallTimer* Stop() {
     base::TimeDelta delta = timer_.Elapsed();
+    timer_.Stop();
+    counter_->count++;
     counter_->time += delta;
     if (parent_ != NULL) {
-      parent_->AdjustForSubTimer(delta);
+      // Adjust parent timer so that it does not include sub timer's time.
+      parent_->counter_->time -= delta;
     }
     return parent_;
   }
 
-  inline void AdjustForSubTimer(base::TimeDelta delta) {
-    counter_->time -= delta;
-  }
-
- private:
-  RuntimeCallCounter* counter_;
-  RuntimeCallTimer* parent_;
+  RuntimeCallCounter* counter_ = nullptr;
+  RuntimeCallTimer* parent_ = nullptr;
   base::ElapsedTimer timer_;
 };
 
-struct RuntimeCallStats {
-  // Dummy counter for the unexpected stub miss.
-  RuntimeCallCounter UnexpectedStubMiss =
-      RuntimeCallCounter("UnexpectedStubMiss");
-  // Counter for runtime callbacks into JavaScript.
-  RuntimeCallCounter ExternalCallback = RuntimeCallCounter("ExternalCallback");
-  RuntimeCallCounter GC = RuntimeCallCounter("GC");
+#define FOR_EACH_API_COUNTER(V)                            \
+  V(ArrayBuffer_Cast)                                      \
+  V(ArrayBuffer_Neuter)                                    \
+  V(ArrayBuffer_New)                                       \
+  V(Array_CloneElementAt)                                  \
+  V(Array_New)                                             \
+  V(BooleanObject_BooleanValue)                            \
+  V(BooleanObject_New)                                     \
+  V(Context_New)                                           \
+  V(DataView_New)                                          \
+  V(Date_DateTimeConfigurationChangeNotification)          \
+  V(Date_New)                                              \
+  V(Date_NumberValue)                                      \
+  V(Debug_Call)                                            \
+  V(Debug_GetMirror)                                       \
+  V(Error_New)                                             \
+  V(External_New)                                          \
+  V(Float32Array_New)                                      \
+  V(Float64Array_New)                                      \
+  V(Function_Call)                                         \
+  V(Function_New)                                          \
+  V(Function_NewInstance)                                  \
+  V(FunctionTemplate_GetFunction)                          \
+  V(FunctionTemplate_New)                                  \
+  V(FunctionTemplate_NewWithFastHandler)                   \
+  V(Int16Array_New)                                        \
+  V(Int32Array_New)                                        \
+  V(Int8Array_New)                                         \
+  V(JSON_Parse)                                            \
+  V(JSON_Stringify)                                        \
+  V(Map_AsArray)                                           \
+  V(Map_Clear)                                             \
+  V(Map_Delete)                                            \
+  V(Map_Get)                                               \
+  V(Map_Has)                                               \
+  V(Map_New)                                               \
+  V(Map_Set)                                               \
+  V(Message_GetEndColumn)                                  \
+  V(Message_GetLineNumber)                                 \
+  V(Message_GetSourceLine)                                 \
+  V(Message_GetStartColumn)                                \
+  V(NumberObject_New)                                      \
+  V(NumberObject_NumberValue)                              \
+  V(Object_CallAsConstructor)                              \
+  V(Object_CallAsFunction)                                 \
+  V(Object_CreateDataProperty)                             \
+  V(Object_DefineOwnProperty)                              \
+  V(Object_Delete)                                         \
+  V(Object_DeleteProperty)                                 \
+  V(Object_ForceSet)                                       \
+  V(Object_Get)                                            \
+  V(Object_GetOwnPropertyDescriptor)                       \
+  V(Object_GetOwnPropertyNames)                            \
+  V(Object_GetPropertyAttributes)                          \
+  V(Object_GetPropertyNames)                               \
+  V(Object_GetRealNamedProperty)                           \
+  V(Object_GetRealNamedPropertyAttributes)                 \
+  V(Object_GetRealNamedPropertyAttributesInPrototypeChain) \
+  V(Object_GetRealNamedPropertyInPrototypeChain)           \
+  V(Object_HasOwnProperty)                                 \
+  V(Object_HasRealIndexedProperty)                         \
+  V(Object_HasRealNamedCallbackProperty)                   \
+  V(Object_HasRealNamedProperty)                           \
+  V(Object_Int32Value)                                     \
+  V(Object_IntegerValue)                                   \
+  V(Object_New)                                            \
+  V(Object_NumberValue)                                    \
+  V(Object_ObjectProtoToString)                            \
+  V(Object_Set)                                            \
+  V(Object_SetAccessor)                                    \
+  V(Object_SetIntegrityLevel)                              \
+  V(Object_SetPrivate)                                     \
+  V(Object_SetPrototype)                                   \
+  V(ObjectTemplate_New)                                    \
+  V(ObjectTemplate_NewInstance)                            \
+  V(Object_ToArrayIndex)                                   \
+  V(Object_ToDetailString)                                 \
+  V(Object_ToInt32)                                        \
+  V(Object_ToInteger)                                      \
+  V(Object_ToNumber)                                       \
+  V(Object_ToObject)                                       \
+  V(Object_ToString)                                       \
+  V(Object_ToUint32)                                       \
+  V(Object_Uint32Value)                                    \
+  V(Persistent_New)                                        \
+  V(Private_New)                                           \
+  V(Promise_Catch)                                         \
+  V(Promise_Chain)                                         \
+  V(Promise_HasRejectHandler)                              \
+  V(Promise_Resolver_New)                                  \
+  V(Promise_Resolver_Resolve)                              \
+  V(Promise_Then)                                          \
+  V(Proxy_New)                                             \
+  V(RangeError_New)                                        \
+  V(ReferenceError_New)                                    \
+  V(RegExp_New)                                            \
+  V(ScriptCompiler_Compile)                                \
+  V(ScriptCompiler_CompileFunctionInContext)               \
+  V(ScriptCompiler_CompileUnbound)                         \
+  V(Script_Run)                                            \
+  V(Set_Add)                                               \
+  V(Set_AsArray)                                           \
+  V(Set_Clear)                                             \
+  V(Set_Delete)                                            \
+  V(Set_Has)                                               \
+  V(Set_New)                                               \
+  V(SharedArrayBuffer_New)                                 \
+  V(String_Concat)                                         \
+  V(String_NewExternalOneByte)                             \
+  V(String_NewExternalTwoByte)                             \
+  V(String_NewFromOneByte)                                 \
+  V(String_NewFromTwoByte)                                 \
+  V(String_NewFromUtf8)                                    \
+  V(StringObject_New)                                      \
+  V(StringObject_StringValue)                              \
+  V(String_Write)                                          \
+  V(String_WriteUtf8)                                      \
+  V(Symbol_New)                                            \
+  V(SymbolObject_New)                                      \
+  V(SymbolObject_SymbolValue)                              \
+  V(SyntaxError_New)                                       \
+  V(TryCatch_StackTrace)                                   \
+  V(TypeError_New)                                         \
+  V(Uint16Array_New)                                       \
+  V(Uint32Array_New)                                       \
+  V(Uint8Array_New)                                        \
+  V(Uint8ClampedArray_New)                                 \
+  V(UnboundScript_GetId)                                   \
+  V(UnboundScript_GetLineNumber)                           \
+  V(UnboundScript_GetName)                                 \
+  V(UnboundScript_GetSourceMappingURL)                     \
+  V(UnboundScript_GetSourceURL)                            \
+  V(Value_TypeOf)
+
+#define FOR_EACH_MANUAL_COUNTER(V)                  \
+  V(AccessorGetterCallback)                         \
+  V(AccessorNameGetterCallback)                     \
+  V(AccessorNameSetterCallback)                     \
+  V(Compile)                                        \
+  V(CompileCode)                                    \
+  V(CompileCodeLazy)                                \
+  V(CompileDeserialize)                             \
+  V(CompileEval)                                    \
+  V(CompileFullCode)                                \
+  V(CompileIgnition)                                \
+  V(CompileSerialize)                               \
+  V(DeoptimizeCode)                                 \
+  V(FunctionCallback)                               \
+  V(GC)                                             \
+  V(GenericNamedPropertyDeleterCallback)            \
+  V(GenericNamedPropertyQueryCallback)              \
+  V(GenericNamedPropertySetterCallback)             \
+  V(IndexedPropertyDeleterCallback)                 \
+  V(IndexedPropertyGetterCallback)                  \
+  V(IndexedPropertyQueryCallback)                   \
+  V(IndexedPropertySetterCallback)                  \
+  V(InvokeFunctionCallback)                         \
+  V(JS_Execution)                                   \
+  V(Map_SetPrototype)                               \
+  V(Map_TransitionToAccessorProperty)               \
+  V(Map_TransitionToDataProperty)                   \
+  V(Object_DeleteProperty)                          \
+  V(OptimizeCode)                                   \
+  V(Parse)                                          \
+  V(ParseLazy)                                      \
+  V(PropertyCallback)                               \
+  V(PrototypeMap_TransitionToAccessorProperty)      \
+  V(PrototypeMap_TransitionToDataProperty)          \
+  V(PrototypeObject_DeleteProperty)                 \
+  V(RecompileConcurrent)                            \
+  V(RecompileSynchronous)                           \
+  /* Dummy counter for the unexpected stub miss. */ \
+  V(UnexpectedStubMiss)
+
+#define FOR_EACH_HANDLER_COUNTER(V)             \
+  V(IC_HandlerCacheHit)                         \
+  V(KeyedLoadIC_LoadIndexedStringStub)          \
+  V(KeyedLoadIC_LoadIndexedInterceptorStub)     \
+  V(KeyedLoadIC_KeyedLoadSloppyArgumentsStub)   \
+  V(KeyedLoadIC_LoadFastElementStub)            \
+  V(KeyedLoadIC_LoadDictionaryElementStub)      \
+  V(KeyedLoadIC_PolymorphicElement)             \
+  V(KeyedStoreIC_KeyedStoreSloppyArgumentsStub) \
+  V(KeyedStoreIC_StoreFastElementStub)          \
+  V(KeyedStoreIC_StoreElementStub)              \
+  V(KeyedStoreIC_Polymorphic)                   \
+  V(LoadIC_FunctionPrototypeStub)               \
+  V(LoadIC_LoadApiGetterStub)                   \
+  V(LoadIC_LoadCallback)                        \
+  V(LoadIC_LoadConstant)                        \
+  V(LoadIC_LoadConstantStub)                    \
+  V(LoadIC_LoadField)                           \
+  V(LoadIC_LoadFieldStub)                       \
+  V(LoadIC_LoadGlobal)                          \
+  V(LoadIC_LoadInterceptor)                     \
+  V(LoadIC_LoadNonexistent)                     \
+  V(LoadIC_LoadNormal)                          \
+  V(LoadIC_LoadScriptContextFieldStub)          \
+  V(LoadIC_LoadViaGetter)                       \
+  V(LoadIC_SlowStub)                            \
+  V(LoadIC_StringLengthStub)                    \
+  V(StoreIC_SlowStub)                           \
+  V(StoreIC_StoreCallback)                      \
+  V(StoreIC_StoreField)                         \
+  V(StoreIC_StoreFieldStub)                     \
+  V(StoreIC_StoreGlobal)                        \
+  V(StoreIC_StoreGlobalTransition)              \
+  V(StoreIC_StoreInterceptorStub)               \
+  V(StoreIC_StoreNormal)                        \
+  V(StoreIC_StoreScriptContextFieldStub)        \
+  V(StoreIC_StoreTransition)                    \
+  V(StoreIC_StoreViaSetter)
+
+class RuntimeCallStats {
+ public:
+  typedef RuntimeCallCounter RuntimeCallStats::*CounterId;
+
+#define CALL_RUNTIME_COUNTER(name) \
+  RuntimeCallCounter name = RuntimeCallCounter(#name);
+  FOR_EACH_MANUAL_COUNTER(CALL_RUNTIME_COUNTER)
+#undef CALL_RUNTIME_COUNTER
 #define CALL_RUNTIME_COUNTER(name, nargs, ressize) \
   RuntimeCallCounter Runtime_##name = RuntimeCallCounter(#name);
   FOR_EACH_INTRINSIC(CALL_RUNTIME_COUNTER)
 #undef CALL_RUNTIME_COUNTER
-#define CALL_BUILTIN_COUNTER(name, type) \
+#define CALL_BUILTIN_COUNTER(name) \
   RuntimeCallCounter Builtin_##name = RuntimeCallCounter(#name);
   BUILTIN_LIST_C(CALL_BUILTIN_COUNTER)
 #undef CALL_BUILTIN_COUNTER
-
-  // Counter to track recursive time events.
-  RuntimeCallTimer* current_timer_ = NULL;
+#define CALL_BUILTIN_COUNTER(name) \
+  RuntimeCallCounter API_##name = RuntimeCallCounter("API_" #name);
+  FOR_EACH_API_COUNTER(CALL_BUILTIN_COUNTER)
+#undef CALL_BUILTIN_COUNTER
+#define CALL_BUILTIN_COUNTER(name) \
+  RuntimeCallCounter Handler_##name = RuntimeCallCounter(#name);
+  FOR_EACH_HANDLER_COUNTER(CALL_BUILTIN_COUNTER)
+#undef CALL_BUILTIN_COUNTER
 
   // Starting measuring the time for a function. This will establish the
   // connection to the parent counter for properly calculating the own times.
-  void Enter(RuntimeCallCounter* counter);
-  void Enter(RuntimeCallTimer* timer);
+  static void Enter(Isolate* isolate, RuntimeCallTimer* timer,
+                    CounterId counter_id);
+
   // Leave a scope for a measured runtime function. This will properly add
   // the time delta to the current_counter and subtract the delta from its
   // parent.
-  void Leave();
-  void Leave(RuntimeCallTimer* timer);
+  static void Leave(Isolate* isolate, RuntimeCallTimer* timer);
 
-  RuntimeCallTimer* current_timer() { return current_timer_; }
+  // Set counter id for the innermost measurement. It can be used to refine
+  // event kind when a runtime entry counter is too generic.
+  static void CorrectCurrentCounterId(Isolate* isolate, CounterId counter_id);
 
   void Reset();
   void Print(std::ostream& os);
 
   RuntimeCallStats() { Reset(); }
+  RuntimeCallTimer* current_timer() { return current_timer_; }
+
+ private:
+  // Counter to track recursive time events.
+  RuntimeCallTimer* current_timer_ = NULL;
 };
 
+#define TRACE_RUNTIME_CALL_STATS(isolate, counter_name) \
+  do {                                                  \
+    if (FLAG_runtime_call_stats) {                      \
+      RuntimeCallStats::CorrectCurrentCounterId(        \
+          isolate, &RuntimeCallStats::counter_name);    \
+    }                                                   \
+  } while (false)
+
+#define TRACE_HANDLER_STATS(isolate, counter_name) \
+  TRACE_RUNTIME_CALL_STATS(isolate, Handler_##counter_name)
+
 // A RuntimeCallTimerScopes wraps around a RuntimeCallTimer to measure the
 // the time of C++ scope.
 class RuntimeCallTimerScope {
  public:
-  inline explicit RuntimeCallTimerScope(Isolate* isolate,
-                                        RuntimeCallCounter* counter) {
-    if (FLAG_runtime_call_stats) Enter(isolate, counter);
+  inline RuntimeCallTimerScope(Isolate* isolate,
+                               RuntimeCallStats::CounterId counter_id) {
+    if (V8_UNLIKELY(FLAG_runtime_call_stats)) {
+      isolate_ = isolate;
+      RuntimeCallStats::Enter(isolate_, &timer_, counter_id);
+    }
   }
-  inline ~RuntimeCallTimerScope() {
-    if (FLAG_runtime_call_stats) Leave();
-  }
+  // This constructor is here just to avoid calling GetIsolate() when the
+  // stats are disabled and the isolate is not directly available.
+  inline RuntimeCallTimerScope(HeapObject* heap_object,
+                               RuntimeCallStats::CounterId counter_id);
 
-  void Enter(Isolate* isolate, RuntimeCallCounter* counter);
-  void Leave();
+  inline ~RuntimeCallTimerScope() {
+    if (V8_UNLIKELY(FLAG_runtime_call_stats)) {
+      RuntimeCallStats::Leave(isolate_, &timer_);
+    }
+  }
 
  private:
   Isolate* isolate_;
@@ -588,39 +832,53 @@
      101)                                                                     \
   HR(code_cache_reject_reason, V8.CodeCacheRejectReason, 1, 6, 6)             \
   HR(errors_thrown_per_context, V8.ErrorsThrownPerContext, 0, 200, 20)        \
-  HR(debug_feature_usage, V8.DebugFeatureUsage, 1, 7, 7)
+  HR(debug_feature_usage, V8.DebugFeatureUsage, 1, 7, 7)                      \
+  /* Asm/Wasm. */                                                             \
+  HR(wasm_functions_per_module, V8.WasmFunctionsPerModule, 1, 10000, 51)
 
-#define HISTOGRAM_TIMER_LIST(HT)                                              \
-  /* Garbage collection timers. */                                            \
-  HT(gc_compactor, V8.GCCompactor, 10000, MILLISECOND)                        \
-  HT(gc_finalize, V8.GCFinalizeMC, 10000, MILLISECOND)                        \
-  HT(gc_finalize_reduce_memory, V8.GCFinalizeMCReduceMemory, 10000,           \
-     MILLISECOND)                                                             \
-  HT(gc_scavenger, V8.GCScavenger, 10000, MILLISECOND)                        \
-  HT(gc_context, V8.GCContext, 10000,                                         \
-     MILLISECOND) /* GC context cleanup time */                               \
-  HT(gc_idle_notification, V8.GCIdleNotification, 10000, MILLISECOND)         \
-  HT(gc_incremental_marking, V8.GCIncrementalMarking, 10000, MILLISECOND)     \
-  HT(gc_incremental_marking_start, V8.GCIncrementalMarkingStart, 10000,       \
-     MILLISECOND)                                                             \
-  HT(gc_incremental_marking_finalize, V8.GCIncrementalMarkingFinalize, 10000, \
-     MILLISECOND)                                                             \
-  HT(gc_low_memory_notification, V8.GCLowMemoryNotification, 10000,           \
-     MILLISECOND)                                                             \
-  /* Parsing timers. */                                                       \
-  HT(parse, V8.ParseMicroSeconds, 1000000, MICROSECOND)                       \
-  HT(parse_lazy, V8.ParseLazyMicroSeconds, 1000000, MICROSECOND)              \
-  HT(pre_parse, V8.PreParseMicroSeconds, 1000000, MICROSECOND)                \
-  /* Compilation times. */                                                    \
-  HT(compile, V8.CompileMicroSeconds, 1000000, MICROSECOND)                   \
-  HT(compile_eval, V8.CompileEvalMicroSeconds, 1000000, MICROSECOND)          \
-  /* Serialization as part of compilation (code caching) */                   \
-  HT(compile_serialize, V8.CompileSerializeMicroSeconds, 100000, MICROSECOND) \
-  HT(compile_deserialize, V8.CompileDeserializeMicroSeconds, 1000000,         \
-     MICROSECOND)                                                             \
-  /* Total compilation time incl. caching/parsing */                          \
-  HT(compile_script, V8.CompileScriptMicroSeconds, 1000000, MICROSECOND)
-
+#define HISTOGRAM_TIMER_LIST(HT)                                               \
+  /* Garbage collection timers. */                                             \
+  HT(gc_compactor, V8.GCCompactor, 10000, MILLISECOND)                         \
+  HT(gc_finalize, V8.GCFinalizeMC, 10000, MILLISECOND)                         \
+  HT(gc_finalize_reduce_memory, V8.GCFinalizeMCReduceMemory, 10000,            \
+     MILLISECOND)                                                              \
+  HT(gc_scavenger, V8.GCScavenger, 10000, MILLISECOND)                         \
+  HT(gc_context, V8.GCContext, 10000,                                          \
+     MILLISECOND) /* GC context cleanup time */                                \
+  HT(gc_idle_notification, V8.GCIdleNotification, 10000, MILLISECOND)          \
+  HT(gc_incremental_marking, V8.GCIncrementalMarking, 10000, MILLISECOND)      \
+  HT(gc_incremental_marking_start, V8.GCIncrementalMarkingStart, 10000,        \
+     MILLISECOND)                                                              \
+  HT(gc_incremental_marking_finalize, V8.GCIncrementalMarkingFinalize, 10000,  \
+     MILLISECOND)                                                              \
+  HT(gc_low_memory_notification, V8.GCLowMemoryNotification, 10000,            \
+     MILLISECOND)                                                              \
+  /* Parsing timers. */                                                        \
+  HT(parse, V8.ParseMicroSeconds, 1000000, MICROSECOND)                        \
+  HT(parse_lazy, V8.ParseLazyMicroSeconds, 1000000, MICROSECOND)               \
+  HT(pre_parse, V8.PreParseMicroSeconds, 1000000, MICROSECOND)                 \
+  /* Compilation times. */                                                     \
+  HT(compile, V8.CompileMicroSeconds, 1000000, MICROSECOND)                    \
+  HT(compile_eval, V8.CompileEvalMicroSeconds, 1000000, MICROSECOND)           \
+  /* Serialization as part of compilation (code caching) */                    \
+  HT(compile_serialize, V8.CompileSerializeMicroSeconds, 100000, MICROSECOND)  \
+  HT(compile_deserialize, V8.CompileDeserializeMicroSeconds, 1000000,          \
+     MICROSECOND)                                                              \
+  /* Total compilation time incl. caching/parsing */                           \
+  HT(compile_script, V8.CompileScriptMicroSeconds, 1000000, MICROSECOND)       \
+  /* Total JavaScript execution time (including callbacks and runtime calls */ \
+  HT(execute, V8.Execute, 1000000, MICROSECOND)                                \
+  /* Asm/Wasm */                                                               \
+  HT(wasm_instantiate_module_time, V8.WasmInstantiateModuleMicroSeconds,       \
+     1000000, MICROSECOND)                                                     \
+  HT(wasm_decode_module_time, V8.WasmDecodeModuleMicroSeconds, 1000000,        \
+     MICROSECOND)                                                              \
+  HT(wasm_decode_function_time, V8.WasmDecodeFunctionMicroSeconds, 1000000,    \
+     MICROSECOND)                                                              \
+  HT(wasm_compile_module_time, V8.WasmCompileModuleMicroSeconds, 1000000,      \
+     MICROSECOND)                                                              \
+  HT(wasm_compile_function_time, V8.WasmCompileFunctionMicroSeconds, 1000000,  \
+     MICROSECOND)
 
 #define AGGREGATABLE_HISTOGRAM_TIMER_LIST(AHT) \
   AHT(compile_lazy, V8.CompileLazyMicroSeconds)
@@ -651,10 +909,17 @@
   HM(heap_sample_code_space_committed, V8.MemoryHeapSampleCodeSpaceCommitted) \
   HM(heap_sample_maximum_committed, V8.MemoryHeapSampleMaximumCommitted)
 
-#define HISTOGRAM_MEMORY_LIST(HM)                   \
-  HM(memory_heap_committed, V8.MemoryHeapCommitted) \
-  HM(memory_heap_used, V8.MemoryHeapUsed)
-
+#define HISTOGRAM_MEMORY_LIST(HM)                                              \
+  HM(memory_heap_committed, V8.MemoryHeapCommitted)                            \
+  HM(memory_heap_used, V8.MemoryHeapUsed)                                      \
+  /* Asm/Wasm */                                                               \
+  HM(wasm_decode_module_peak_memory_bytes, V8.WasmDecodeModulePeakMemoryBytes) \
+  HM(wasm_compile_function_peak_memory_bytes,                                  \
+     V8.WasmCompileFunctionPeakMemoryBytes)                                    \
+  HM(wasm_min_mem_pages_count, V8.WasmMinMemPagesCount)                        \
+  HM(wasm_max_mem_pages_count, V8.WasmMaxMemPagesCount)                        \
+  HM(wasm_function_size_bytes, V8.WasmFunctionSizeBytes)                       \
+  HM(wasm_module_size_bytes, V8.WasmModuleSizeBytes)
 
 // WARNING: STATS_COUNTER_LIST_* is a very large macro that is causing MSVC
 // Intellisense to crash.  It was broken into two macros (each of length 40
@@ -703,7 +968,6 @@
   /* The store-buffer implementation of the write barrier. */         \
   SC(store_buffer_overflows, V8.StoreBufferOverflows)
 
-
 #define STATS_COUNTER_LIST_2(SC)                                               \
   /* Number of code stubs. */                                                  \
   SC(code_stubs, V8.CodeStubs)                                                 \
@@ -743,8 +1007,6 @@
   SC(enum_cache_hits, V8.EnumCacheHits)                                        \
   SC(enum_cache_misses, V8.EnumCacheMisses)                                    \
   SC(fast_new_closure_total, V8.FastNewClosureTotal)                           \
-  SC(fast_new_closure_try_optimized, V8.FastNewClosureTryOptimized)            \
-  SC(fast_new_closure_install_optimized, V8.FastNewClosureInstallOptimized)    \
   SC(string_add_runtime, V8.StringAddRuntime)                                  \
   SC(string_add_native, V8.StringAddNative)                                    \
   SC(string_add_runtime_ext_to_one_byte, V8.StringAddRuntimeExtToOneByte)      \
@@ -756,14 +1018,12 @@
   SC(regexp_entry_native, V8.RegExpEntryNative)                                \
   SC(number_to_string_native, V8.NumberToStringNative)                         \
   SC(number_to_string_runtime, V8.NumberToStringRuntime)                       \
-  SC(math_atan2_runtime, V8.MathAtan2Runtime)                                  \
-  SC(math_clz32_runtime, V8.MathClz32Runtime)                                  \
   SC(math_exp_runtime, V8.MathExpRuntime)                                      \
   SC(math_log_runtime, V8.MathLogRuntime)                                      \
   SC(math_pow_runtime, V8.MathPowRuntime)                                      \
   SC(stack_interrupts, V8.StackInterrupts)                                     \
   SC(runtime_profiler_ticks, V8.RuntimeProfilerTicks)                          \
-  SC(runtime_calls, V8.RuntimeCalls)                          \
+  SC(runtime_calls, V8.RuntimeCalls)                                           \
   SC(bounds_checks_eliminated, V8.BoundsChecksEliminated)                      \
   SC(bounds_checks_hoisted, V8.BoundsChecksHoisted)                            \
   SC(soft_deopts_requested, V8.SoftDeoptsRequested)                            \
diff --git a/src/crankshaft/arm/lithium-arm.cc b/src/crankshaft/arm/lithium-arm.cc
index 4072982..538b309 100644
--- a/src/crankshaft/arm/lithium-arm.cc
+++ b/src/crankshaft/arm/lithium-arm.cc
@@ -877,7 +877,7 @@
 
 LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) {
   LInstruction* result = new (zone()) LPrologue();
-  if (info_->num_heap_slots() > 0) {
+  if (info_->scope()->num_heap_slots() > 0) {
     result = MarkAsCall(result, instr);
   }
   return result;
@@ -934,17 +934,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
-  LOperand* left =
-      UseFixed(instr->left(), InstanceOfDescriptor::LeftRegister());
-  LOperand* right =
-      UseFixed(instr->right(), InstanceOfDescriptor::RightRegister());
-  LOperand* context = UseFixed(instr->context(), cp);
-  LInstanceOf* result = new (zone()) LInstanceOf(context, left, right);
-  return MarkAsCall(DefineFixed(result, r0), instr);
-}
-
-
 LInstruction* LChunkBuilder::DoHasInPrototypeChainAndBranch(
     HHasInPrototypeChainAndBranch* instr) {
   LOperand* object = UseRegister(instr->object());
@@ -1080,6 +1069,10 @@
       return DoMathAbs(instr);
     case kMathLog:
       return DoMathLog(instr);
+    case kMathCos:
+      return DoMathCos(instr);
+    case kMathSin:
+      return DoMathSin(instr);
     case kMathExp:
       return DoMathExp(instr);
     case kMathSqrt:
@@ -1145,16 +1138,25 @@
   return DefineAsRegister(result);
 }
 
+LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
+  DCHECK(instr->representation().IsDouble());
+  DCHECK(instr->value()->representation().IsDouble());
+  LOperand* input = UseFixedDouble(instr->value(), d0);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathCos(input), d0), instr);
+}
+
+LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
+  DCHECK(instr->representation().IsDouble());
+  DCHECK(instr->value()->representation().IsDouble());
+  LOperand* input = UseFixedDouble(instr->value(), d0);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathSin(input), d0), instr);
+}
 
 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
   DCHECK(instr->representation().IsDouble());
   DCHECK(instr->value()->representation().IsDouble());
-  LOperand* input = UseRegister(instr->value());
-  LOperand* temp1 = TempRegister();
-  LOperand* temp2 = TempRegister();
-  LOperand* double_temp = TempDoubleRegister();
-  LMathExp* result = new(zone()) LMathExp(input, double_temp, temp1, temp2);
-  return DefineAsRegister(result);
+  LOperand* input = UseFixedDouble(instr->value(), d0);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathExp(input), d0), instr);
 }
 
 
@@ -1985,13 +1987,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
-  LOperand* lo = UseRegister(instr->lo());
-  LOperand* hi = UseRegister(instr->hi());
-  return DefineAsRegister(new(zone()) LConstructDouble(hi, lo));
-}
-
-
 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
   LOperand* context = info()->IsStub()
       ? UseFixed(instr->context(), cp)
@@ -2023,14 +2018,9 @@
 
 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
-  LOperand* global_object =
-      UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
-  LLoadGlobalGeneric* result =
-      new(zone()) LLoadGlobalGeneric(context, global_object, vector);
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
+
+  LLoadGlobalGeneric* result = new (zone()) LLoadGlobalGeneric(context, vector);
   return MarkAsCall(DefineFixed(result, r0), instr);
 }
 
@@ -2074,10 +2064,7 @@
   LOperand* context = UseFixed(instr->context(), cp);
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
   LInstruction* result =
       DefineFixed(new(zone()) LLoadNamedGeneric(context, object, vector), r0);
@@ -2149,10 +2136,7 @@
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
   LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
   LInstruction* result =
       DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key, vector),
@@ -2214,12 +2198,8 @@
   DCHECK(instr->key()->representation().IsTagged());
   DCHECK(instr->value()->representation().IsTagged());
 
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
 
   LStoreKeyedGeneric* result =
       new (zone()) LStoreKeyedGeneric(context, obj, key, val, slot, vector);
@@ -2308,12 +2288,8 @@
   LOperand* obj =
       UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
   LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
 
   LStoreNamedGeneric* result =
       new (zone()) LStoreNamedGeneric(context, obj, val, slot, vector);
@@ -2351,13 +2327,18 @@
 
 
 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
-  info()->MarkAsDeferredCalling();
-  LOperand* context = UseAny(instr->context());
   LOperand* size = UseRegisterOrConstant(instr->size());
   LOperand* temp1 = TempRegister();
   LOperand* temp2 = TempRegister();
-  LAllocate* result = new(zone()) LAllocate(context, size, temp1, temp2);
-  return AssignPointerMap(DefineAsRegister(result));
+  if (instr->IsAllocationFolded()) {
+    LFastAllocate* result = new (zone()) LFastAllocate(size, temp1, temp2);
+    return DefineAsRegister(result);
+  } else {
+    info()->MarkAsDeferredCalling();
+    LOperand* context = UseAny(instr->context());
+    LAllocate* result = new (zone()) LAllocate(context, size, temp1, temp2);
+    return AssignPointerMap(DefineAsRegister(result));
+  }
 }
 
 
diff --git a/src/crankshaft/arm/lithium-arm.h b/src/crankshaft/arm/lithium-arm.h
index 60fe79d..4aa4a71 100644
--- a/src/crankshaft/arm/lithium-arm.h
+++ b/src/crankshaft/arm/lithium-arm.h
@@ -53,7 +53,6 @@
   V(ConstantI)                               \
   V(ConstantS)                               \
   V(ConstantT)                               \
-  V(ConstructDouble)                         \
   V(Context)                                 \
   V(DebugBreak)                              \
   V(DeclareGlobals)                          \
@@ -67,6 +66,7 @@
   V(Drop)                                    \
   V(Dummy)                                   \
   V(DummyUse)                                \
+  V(FastAllocate)                            \
   V(FlooringDivByConstI)                     \
   V(FlooringDivByPowerOf2I)                  \
   V(FlooringDivI)                            \
@@ -78,7 +78,6 @@
   V(HasInPrototypeChainAndBranch)            \
   V(HasInstanceTypeAndBranch)                \
   V(InnerAllocatedObject)                    \
-  V(InstanceOf)                              \
   V(InstructionGap)                          \
   V(Integer32ToDouble)                       \
   V(InvokeFunction)                          \
@@ -98,6 +97,8 @@
   V(LoadNamedGeneric)                        \
   V(MathAbs)                                 \
   V(MathClz32)                               \
+  V(MathCos)                                 \
+  V(MathSin)                                 \
   V(MathExp)                                 \
   V(MathFloor)                               \
   V(MathFround)                              \
@@ -151,7 +152,6 @@
   V(UnknownOSRValue)                         \
   V(WrapReceiver)
 
-
 #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic)            \
   Opcode opcode() const final { return LInstruction::k##type; } \
   void CompileToNative(LCodeGen* generator) final;              \
@@ -906,24 +906,29 @@
   DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
 };
 
-
-class LMathExp final : public LTemplateInstruction<1, 1, 3> {
+class LMathCos final : public LTemplateInstruction<1, 1, 0> {
  public:
-  LMathExp(LOperand* value,
-           LOperand* double_temp,
-           LOperand* temp1,
-           LOperand* temp2) {
-    inputs_[0] = value;
-    temps_[0] = temp1;
-    temps_[1] = temp2;
-    temps_[2] = double_temp;
-    ExternalReference::InitializeMathExpData();
-  }
+  explicit LMathCos(LOperand* value) { inputs_[0] = value; }
 
   LOperand* value() { return inputs_[0]; }
-  LOperand* temp1() { return temps_[0]; }
-  LOperand* temp2() { return temps_[1]; }
-  LOperand* double_temp() { return temps_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
+};
+
+class LMathSin final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathSin(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
+};
+
+class LMathExp final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathExp(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
 };
@@ -1135,22 +1140,6 @@
 };
 
 
-class LInstanceOf final : public LTemplateInstruction<1, 3, 0> {
- public:
-  LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
-    inputs_[0] = context;
-    inputs_[1] = left;
-    inputs_[2] = right;
-  }
-
-  LOperand* context() const { return inputs_[0]; }
-  LOperand* left() const { return inputs_[1]; }
-  LOperand* right() const { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
-};
-
-
 class LHasInPrototypeChainAndBranch final : public LControlInstruction<2, 0> {
  public:
   LHasInPrototypeChainAndBranch(LOperand* object, LOperand* prototype) {
@@ -1584,18 +1573,14 @@
   DECLARE_HYDROGEN_ACCESSOR(LoadKeyedGeneric)
 };
 
-
-class LLoadGlobalGeneric final : public LTemplateInstruction<1, 2, 1> {
+class LLoadGlobalGeneric final : public LTemplateInstruction<1, 1, 1> {
  public:
-  LLoadGlobalGeneric(LOperand* context, LOperand* global_object,
-                     LOperand* vector) {
+  LLoadGlobalGeneric(LOperand* context, LOperand* vector) {
     inputs_[0] = context;
-    inputs_[1] = global_object;
     temps_[0] = vector;
   }
 
   LOperand* context() { return inputs_[0]; }
-  LOperand* global_object() { return inputs_[1]; }
   LOperand* temp_vector() { return temps_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
@@ -2356,20 +2341,6 @@
 };
 
 
-class LConstructDouble final : public LTemplateInstruction<1, 2, 0> {
- public:
-  LConstructDouble(LOperand* hi, LOperand* lo) {
-    inputs_[0] = hi;
-    inputs_[1] = lo;
-  }
-
-  LOperand* hi() { return inputs_[0]; }
-  LOperand* lo() { return inputs_[1]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
-};
-
-
 class LAllocate final : public LTemplateInstruction<1, 2, 2> {
  public:
   LAllocate(LOperand* context,
@@ -2391,6 +2362,21 @@
   DECLARE_HYDROGEN_ACCESSOR(Allocate)
 };
 
+class LFastAllocate final : public LTemplateInstruction<1, 1, 2> {
+ public:
+  LFastAllocate(LOperand* size, LOperand* temp1, LOperand* temp2) {
+    inputs_[0] = size;
+    temps_[0] = temp1;
+    temps_[1] = temp2;
+  }
+
+  LOperand* size() { return inputs_[0]; }
+  LOperand* temp1() { return temps_[0]; }
+  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(FastAllocate, "fast-allocate")
+  DECLARE_HYDROGEN_ACCESSOR(Allocate)
+};
 
 class LTypeof final : public LTemplateInstruction<1, 2, 0> {
  public:
@@ -2547,6 +2533,8 @@
   LInstruction* DoMathFround(HUnaryMathOperation* instr);
   LInstruction* DoMathAbs(HUnaryMathOperation* instr);
   LInstruction* DoMathLog(HUnaryMathOperation* instr);
+  LInstruction* DoMathCos(HUnaryMathOperation* instr);
+  LInstruction* DoMathSin(HUnaryMathOperation* instr);
   LInstruction* DoMathExp(HUnaryMathOperation* instr);
   LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
   LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
diff --git a/src/crankshaft/arm/lithium-codegen-arm.cc b/src/crankshaft/arm/lithium-codegen-arm.cc
index c64aac3..e9d3f46 100644
--- a/src/crankshaft/arm/lithium-codegen-arm.cc
+++ b/src/crankshaft/arm/lithium-codegen-arm.cc
@@ -11,7 +11,6 @@
 #include "src/crankshaft/hydrogen-osr.h"
 #include "src/ic/ic.h"
 #include "src/ic/stub-cache.h"
-#include "src/profiler/cpu-profiler.h"
 
 namespace v8 {
 namespace internal {
@@ -329,8 +328,6 @@
       } else {
         __ bl(&call_deopt_entry);
       }
-      info()->LogDeoptCallPosition(masm()->pc_offset(),
-                                   table_entry->deopt_info.inlining_id);
       masm()->CheckConstPool(false, false);
     }
 
@@ -823,7 +820,7 @@
     __ stop("trap_on_deopt", condition);
   }
 
-  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason);
+  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason, id);
 
   DCHECK(info()->IsStub() || frame_is_built_);
   // Go through jump table if we need to handle condition, build frame, or
@@ -832,13 +829,12 @@
       !info()->saves_caller_doubles()) {
     DeoptComment(deopt_info);
     __ Call(entry, RelocInfo::RUNTIME_ENTRY);
-    info()->LogDeoptCallPosition(masm()->pc_offset(), deopt_info.inlining_id);
   } else {
     Deoptimizer::JumpTableEntry table_entry(entry, deopt_info, bailout_type,
                                             !frame_is_built_);
     // We often have several deopts to the same entry, reuse the last
     // jump entry if this is the case.
-    if (FLAG_trace_deopt || isolate()->cpu_profiler()->is_profiling() ||
+    if (FLAG_trace_deopt || isolate()->is_profiling() ||
         jump_table_.is_empty() ||
         !table_entry.IsEquivalentTo(jump_table_.last())) {
       jump_table_.Add(table_entry, zone());
@@ -913,7 +909,6 @@
 void LCodeGen::RecordAndWritePosition(int position) {
   if (position == RelocInfo::kNoPosition) return;
   masm()->positions_recorder()->RecordPosition(position);
-  masm()->positions_recorder()->WriteRecordedPositions();
 }
 
 
@@ -2498,16 +2493,6 @@
 }
 
 
-void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
-  DCHECK(ToRegister(instr->context()).is(cp));
-  DCHECK(ToRegister(instr->left()).is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(ToRegister(instr->right()).is(InstanceOfDescriptor::RightRegister()));
-  DCHECK(ToRegister(instr->result()).is(r0));
-  InstanceOfStub stub(isolate());
-  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
-}
-
-
 void LCodeGen::DoHasInPrototypeChainAndBranch(
     LHasInPrototypeChainAndBranch* instr) {
   Register const object = ToRegister(instr->object());
@@ -2539,10 +2524,10 @@
   DeoptimizeIf(eq, instr, Deoptimizer::kProxy);
 
   __ ldr(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset));
-  __ cmp(object_prototype, prototype);
-  EmitTrueBranch(instr, eq);
   __ CompareRoot(object_prototype, Heap::kNullValueRootIndex);
   EmitFalseBranch(instr, eq);
+  __ cmp(object_prototype, prototype);
+  EmitTrueBranch(instr, eq);
   __ ldr(object_map, FieldMemOperand(object_prototype, HeapObject::kMapOffset));
   __ b(&loop);
 }
@@ -2636,15 +2621,12 @@
 
 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   DCHECK(ToRegister(instr->context()).is(cp));
-  DCHECK(ToRegister(instr->global_object())
-             .is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->result()).is(r0));
 
-  __ mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), instr->typeof_mode(), PREMONOMORPHIC)
-                        .code();
+  Handle<Code> ic =
+      CodeFactory::LoadGlobalICInOptimizedCode(isolate(), instr->typeof_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2739,10 +2721,7 @@
   // Name is always in r2.
   __ mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_INSIDE_TYPEOF,
-                        instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
 }
 
@@ -3036,13 +3015,9 @@
   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
-  }
+  EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
 
-  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
-                        isolate(), instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
 }
 
@@ -3559,26 +3534,32 @@
   }
 }
 
+void LCodeGen::DoMathCos(LMathCos* instr) {
+  __ PrepareCallCFunction(0, 1, scratch0());
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
+  __ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 0, 1);
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
+}
+
+void LCodeGen::DoMathSin(LMathSin* instr) {
+  __ PrepareCallCFunction(0, 1, scratch0());
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
+  __ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 0, 1);
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
+}
 
 void LCodeGen::DoMathExp(LMathExp* instr) {
-  DwVfpRegister input = ToDoubleRegister(instr->value());
-  DwVfpRegister result = ToDoubleRegister(instr->result());
-  DwVfpRegister double_scratch1 = ToDoubleRegister(instr->double_temp());
-  DwVfpRegister double_scratch2 = double_scratch0();
-  Register temp1 = ToRegister(instr->temp1());
-  Register temp2 = ToRegister(instr->temp2());
-
-  MathExpGenerator::EmitMathExp(
-      masm(), input, result, double_scratch1, double_scratch2,
-      temp1, temp2, scratch0());
+  __ PrepareCallCFunction(0, 1, scratch0());
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
+  __ CallCFunction(ExternalReference::ieee754_exp_function(isolate()), 0, 1);
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
 }
 
 
 void LCodeGen::DoMathLog(LMathLog* instr) {
   __ PrepareCallCFunction(0, 1, scratch0());
   __ MovToFloatParameter(ToDoubleRegister(instr->value()));
-  __ CallCFunction(ExternalReference::math_log_double_function(isolate()),
-                   0, 1);
+  __ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
   __ MovFromFloatResult(ToDoubleRegister(instr->result()));
 }
 
@@ -3601,7 +3582,9 @@
 #endif
   if (FLAG_code_comments) {
     if (actual.is_reg()) {
-      Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString());
+      Comment(";;; PrepareForTailCall, actual: %s {",
+              RegisterConfiguration::Crankshaft()->GetGeneralRegisterName(
+                  actual.reg().code()));
     } else {
       Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate());
     }
@@ -3728,14 +3711,8 @@
   DCHECK(ToRegister(instr->result()).is(r0));
 
   __ mov(r0, Operand(instr->arity()));
-  if (instr->arity() == 1) {
-    // We only need the allocation site for the case we have a length argument.
-    // The case may bail out to the runtime, which will determine the correct
-    // elements kind with the site.
-    __ Move(r2, instr->hydrogen()->site());
-  } else {
-    __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
-  }
+  __ Move(r2, instr->hydrogen()->site());
+
   ElementsKind kind = instr->hydrogen()->elements_kind();
   AllocationSiteOverrideMode override_mode =
       (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
@@ -3768,7 +3745,7 @@
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
     __ bind(&done);
   } else {
-    ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
+    ArrayNArgumentsConstructorStub stub(isolate());
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   }
 }
@@ -3889,14 +3866,12 @@
   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
 
   __ mov(StoreDescriptor::NameRegister(), Operand(instr->name()));
-  Handle<Code> ic = CodeFactory::StoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic =
+      CodeFactory::StoreICInOptimizedCode(isolate(), instr->language_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
 }
 
@@ -4031,11 +4006,6 @@
 
   if (instr->NeedsCanonicalization()) {
     // Force a canonical NaN.
-    if (masm()->emit_debug_code()) {
-      __ vmrs(ip);
-      __ tst(ip, Operand(kVFPDefaultNaNModeControlBit));
-      __ Assert(ne, kDefaultNaNModeNotSet);
-    }
     __ VFPCanonicalizeNaN(double_scratch, value);
     __ vstr(double_scratch, scratch, 0);
   } else {
@@ -4108,13 +4078,11 @@
   DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
 
   Handle<Code> ic = CodeFactory::KeyedStoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state()).code();
+                        isolate(), instr->language_mode())
+                        .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
 }
 
@@ -4193,7 +4161,15 @@
 
     LOperand* key = instr->key();
     if (key->IsConstantOperand()) {
-      __ Move(r3, Operand(ToSmi(LConstantOperand::cast(key))));
+      LConstantOperand* constant_key = LConstantOperand::cast(key);
+      int32_t int_key = ToInteger32(constant_key);
+      if (Smi::IsValid(int_key)) {
+        __ mov(r3, Operand(Smi::FromInt(int_key)));
+      } else {
+        // We should never get here at runtime because there is a smi check on
+        // the key before this point.
+        __ stop("expected smi");
+      }
     } else {
       __ Move(r3, ToRegister(key));
       __ SmiTag(r3);
@@ -4242,8 +4218,7 @@
     DCHECK(object_reg.is(r0));
     PushSafepointRegistersScope scope(this);
     __ Move(r1, to_map);
-    bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
-    TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
+    TransitionElementsKindStub stub(isolate(), from_kind, to_kind);
     __ CallStub(&stub);
     RecordSafepointWithRegisters(
         instr->pointer_map(), 0, Safepoint::kLazyDeopt);
@@ -4494,7 +4469,7 @@
 
   if (FLAG_inline_new) {
     __ LoadRoot(tmp3, Heap::kHeapNumberMapRootIndex);
-    __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow, DONT_TAG_RESULT);
+    __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow);
     __ b(&done);
   }
 
@@ -4518,15 +4493,13 @@
     __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
     RecordSafepointWithRegisters(
         instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
-    __ sub(r0, r0, Operand(kHeapObjectTag));
     __ StoreToSafepointRegisterSlot(r0, dst);
   }
 
   // Done. Put the value in dbl_scratch into the value of the allocated heap
   // number.
   __ bind(&done);
-  __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset);
-  __ add(dst, dst, Operand(kHeapObjectTag));
+  __ vstr(dbl_scratch, FieldMemOperand(dst, HeapNumber::kValueOffset));
 }
 
 
@@ -4551,16 +4524,12 @@
   DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr);
   if (FLAG_inline_new) {
     __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
-    // We want the untagged address first for performance
-    __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(),
-                          DONT_TAG_RESULT);
+    __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry());
   } else {
     __ jmp(deferred->entry());
   }
   __ bind(deferred->exit());
-  __ vstr(input_reg, reg, HeapNumber::kValueOffset);
-  // Now that we have finished with the object's real address tag it
-  __ add(reg, reg, Operand(kHeapObjectTag));
+  __ vstr(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset));
 }
 
 
@@ -4581,7 +4550,6 @@
   __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
   RecordSafepointWithRegisters(
       instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
-  __ sub(r0, r0, Operand(kHeapObjectTag));
   __ StoreToSafepointRegisterSlot(r0, reg);
 }
 
@@ -5076,15 +5044,6 @@
 }
 
 
-void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
-  Register hi_reg = ToRegister(instr->hi());
-  Register lo_reg = ToRegister(instr->lo());
-  DwVfpRegister result_reg = ToDoubleRegister(instr->result());
-  __ VmovHigh(result_reg, hi_reg);
-  __ VmovLow(result_reg, lo_reg);
-}
-
-
 void LCodeGen::DoAllocate(LAllocate* instr) {
   class DeferredAllocate final : public LDeferredCode {
    public:
@@ -5105,7 +5064,7 @@
   Register scratch2 = ToRegister(instr->temp2());
 
   // Allocate memory for the object.
-  AllocationFlags flags = TAG_OBJECT;
+  AllocationFlags flags = NO_ALLOCATION_FLAGS;
   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
   }
@@ -5114,6 +5073,11 @@
     flags = static_cast<AllocationFlags>(flags | PRETENURE);
   }
 
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    flags = static_cast<AllocationFlags>(flags | ALLOCATION_FOLDING_DOMINATOR);
+  }
+  DCHECK(!instr->hydrogen()->IsAllocationFolded());
+
   if (instr->size()->IsConstantOperand()) {
     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
     CHECK(size <= Page::kMaxRegularHeapObjectSize);
@@ -5181,6 +5145,49 @@
   CallRuntimeFromDeferred(
       Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
   __ StoreToSafepointRegisterSlot(r0, result);
+
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    AllocationFlags allocation_flags = NO_ALLOCATION_FLAGS;
+    if (instr->hydrogen()->IsOldSpaceAllocation()) {
+      DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+      allocation_flags = static_cast<AllocationFlags>(flags | PRETENURE);
+    }
+    // If the allocation folding dominator allocate triggered a GC, allocation
+    // happend in the runtime. We have to reset the top pointer to virtually
+    // undo the allocation.
+    ExternalReference allocation_top =
+        AllocationUtils::GetAllocationTopReference(isolate(), allocation_flags);
+    Register top_address = scratch0();
+    __ sub(r0, r0, Operand(kHeapObjectTag));
+    __ mov(top_address, Operand(allocation_top));
+    __ str(r0, MemOperand(top_address));
+    __ add(r0, r0, Operand(kHeapObjectTag));
+  }
+}
+
+void LCodeGen::DoFastAllocate(LFastAllocate* instr) {
+  DCHECK(instr->hydrogen()->IsAllocationFolded());
+  DCHECK(!instr->hydrogen()->IsAllocationFoldingDominator());
+  Register result = ToRegister(instr->result());
+  Register scratch1 = ToRegister(instr->temp1());
+  Register scratch2 = ToRegister(instr->temp2());
+
+  AllocationFlags flags = ALLOCATION_FOLDED;
+  if (instr->hydrogen()->MustAllocateDoubleAligned()) {
+    flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
+  }
+  if (instr->hydrogen()->IsOldSpaceAllocation()) {
+    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+    flags = static_cast<AllocationFlags>(flags | PRETENURE);
+  }
+  if (instr->size()->IsConstantOperand()) {
+    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
+    CHECK(size <= Page::kMaxRegularHeapObjectSize);
+    __ FastAllocate(size, result, scratch1, scratch2, flags);
+  } else {
+    Register size = ToRegister(instr->size());
+    __ FastAllocate(size, result, scratch1, scratch2, flags);
+  }
 }
 
 
diff --git a/src/crankshaft/arm/lithium-codegen-arm.h b/src/crankshaft/arm/lithium-codegen-arm.h
index 8bbacc3..30a26f2 100644
--- a/src/crankshaft/arm/lithium-codegen-arm.h
+++ b/src/crankshaft/arm/lithium-codegen-arm.h
@@ -135,8 +135,6 @@
 #undef DECLARE_DO
 
  private:
-  LanguageMode language_mode() const { return info()->language_mode(); }
-
   Scope* scope() const { return scope_; }
 
   Register scratch0() { return r9; }
diff --git a/src/crankshaft/arm64/lithium-arm64.cc b/src/crankshaft/arm64/lithium-arm64.cc
index 6cfc846..9a0a7c4 100644
--- a/src/crankshaft/arm64/lithium-arm64.cc
+++ b/src/crankshaft/arm64/lithium-arm64.cc
@@ -726,7 +726,7 @@
 
 LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) {
   LInstruction* result = new (zone()) LPrologue();
-  if (info_->num_heap_slots() > 0) {
+  if (info_->scope()->num_heap_slots() > 0) {
     result = MarkAsCall(result, instr);
   }
   return result;
@@ -841,14 +841,20 @@
 
 
 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
-  info()->MarkAsDeferredCalling();
-  LOperand* context = UseAny(instr->context());
   LOperand* size = UseRegisterOrConstant(instr->size());
   LOperand* temp1 = TempRegister();
   LOperand* temp2 = TempRegister();
-  LOperand* temp3 = instr->MustPrefillWithFiller() ? TempRegister() : NULL;
-  LAllocate* result = new(zone()) LAllocate(context, size, temp1, temp2, temp3);
-  return AssignPointerMap(DefineAsRegister(result));
+  if (instr->IsAllocationFolded()) {
+    LFastAllocate* result = new (zone()) LFastAllocate(size, temp1, temp2);
+    return DefineAsRegister(result);
+  } else {
+    info()->MarkAsDeferredCalling();
+    LOperand* context = UseAny(instr->context());
+    LOperand* temp3 = instr->MustPrefillWithFiller() ? TempRegister() : NULL;
+    LAllocate* result =
+        new (zone()) LAllocate(context, size, temp1, temp2, temp3);
+    return AssignPointerMap(DefineAsRegister(result));
+  }
 }
 
 
@@ -1461,17 +1467,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
-  LOperand* left =
-      UseFixed(instr->left(), InstanceOfDescriptor::LeftRegister());
-  LOperand* right =
-      UseFixed(instr->right(), InstanceOfDescriptor::RightRegister());
-  LOperand* context = UseFixed(instr->context(), cp);
-  LInstanceOf* result = new (zone()) LInstanceOf(context, left, right);
-  return MarkAsCall(DefineFixed(result, x0), instr);
-}
-
-
 LInstruction* LChunkBuilder::DoHasInPrototypeChainAndBranch(
     HHasInPrototypeChainAndBranch* instr) {
   LOperand* object = UseRegister(instr->object());
@@ -1558,15 +1553,9 @@
 
 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
-  LOperand* global_object =
-      UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
-  LLoadGlobalGeneric* result =
-      new(zone()) LLoadGlobalGeneric(context, global_object, vector);
+  LLoadGlobalGeneric* result = new (zone()) LLoadGlobalGeneric(context, vector);
   return MarkAsCall(DefineFixed(result, x0), instr);
 }
 
@@ -1626,10 +1615,7 @@
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
   LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
   LInstruction* result =
       DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key, vector),
@@ -1648,10 +1634,7 @@
   LOperand* context = UseFixed(instr->context(), cp);
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
   LInstruction* result =
       DefineFixed(new(zone()) LLoadNamedGeneric(context, object, vector), x0);
@@ -1936,13 +1919,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
-  LOperand* lo = UseRegisterAndClobber(instr->lo());
-  LOperand* hi = UseRegister(instr->hi());
-  return DefineAsRegister(new(zone()) LConstructDouble(hi, lo));
-}
-
-
 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
   LOperand* context = info()->IsStub()
       ? UseFixed(instr->context(), cp)
@@ -2251,12 +2227,8 @@
   DCHECK(instr->key()->representation().IsTagged());
   DCHECK(instr->value()->representation().IsTagged());
 
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
 
   LStoreKeyedGeneric* result = new (zone())
       LStoreKeyedGeneric(context, object, key, value, slot, vector);
@@ -2299,12 +2271,8 @@
       UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
   LOperand* value = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
 
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
 
   LStoreNamedGeneric* result =
       new (zone()) LStoreNamedGeneric(context, object, value, slot, vector);
@@ -2481,17 +2449,26 @@
         return result;
       }
     }
+    case kMathCos: {
+      DCHECK(instr->representation().IsDouble());
+      DCHECK(instr->value()->representation().IsDouble());
+      LOperand* input = UseFixedDouble(instr->value(), d0);
+      LMathCos* result = new (zone()) LMathCos(input);
+      return MarkAsCall(DefineFixedDouble(result, d0), instr);
+    }
+    case kMathSin: {
+      DCHECK(instr->representation().IsDouble());
+      DCHECK(instr->value()->representation().IsDouble());
+      LOperand* input = UseFixedDouble(instr->value(), d0);
+      LMathSin* result = new (zone()) LMathSin(input);
+      return MarkAsCall(DefineFixedDouble(result, d0), instr);
+    }
     case kMathExp: {
       DCHECK(instr->representation().IsDouble());
       DCHECK(instr->value()->representation().IsDouble());
-      LOperand* input = UseRegister(instr->value());
-      LOperand* double_temp1 = TempDoubleRegister();
-      LOperand* temp1 = TempRegister();
-      LOperand* temp2 = TempRegister();
-      LOperand* temp3 = TempRegister();
-      LMathExp* result = new(zone()) LMathExp(input, double_temp1,
-                                              temp1, temp2, temp3);
-      return DefineAsRegister(result);
+      LOperand* input = UseFixedDouble(instr->value(), d0);
+      LMathExp* result = new (zone()) LMathExp(input);
+      return MarkAsCall(DefineFixedDouble(result, d0), instr);
     }
     case kMathFloor: {
       DCHECK(instr->value()->representation().IsDouble());
diff --git a/src/crankshaft/arm64/lithium-arm64.h b/src/crankshaft/arm64/lithium-arm64.h
index 237487f..231008d 100644
--- a/src/crankshaft/arm64/lithium-arm64.h
+++ b/src/crankshaft/arm64/lithium-arm64.h
@@ -57,7 +57,6 @@
   V(ConstantI)                               \
   V(ConstantS)                               \
   V(ConstantT)                               \
-  V(ConstructDouble)                         \
   V(Context)                                 \
   V(DebugBreak)                              \
   V(DeclareGlobals)                          \
@@ -70,6 +69,7 @@
   V(Drop)                                    \
   V(Dummy)                                   \
   V(DummyUse)                                \
+  V(FastAllocate)                            \
   V(FlooringDivByConstI)                     \
   V(FlooringDivByPowerOf2I)                  \
   V(FlooringDivI)                            \
@@ -81,7 +81,6 @@
   V(HasInPrototypeChainAndBranch)            \
   V(HasInstanceTypeAndBranch)                \
   V(InnerAllocatedObject)                    \
-  V(InstanceOf)                              \
   V(InstructionGap)                          \
   V(Integer32ToDouble)                       \
   V(InvokeFunction)                          \
@@ -104,6 +103,8 @@
   V(MathAbs)                                 \
   V(MathAbsTagged)                           \
   V(MathClz32)                               \
+  V(MathCos)                                 \
+  V(MathSin)                                 \
   V(MathExp)                                 \
   V(MathFloorD)                              \
   V(MathFloorI)                              \
@@ -163,7 +164,6 @@
   V(UnknownOSRValue)                         \
   V(WrapReceiver)
 
-
 #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic)            \
   Opcode opcode() const final { return LInstruction::k##type; } \
   void CompileToNative(LCodeGen* generator) final;              \
@@ -626,6 +626,21 @@
   DECLARE_HYDROGEN_ACCESSOR(Allocate)
 };
 
+class LFastAllocate final : public LTemplateInstruction<1, 1, 2> {
+ public:
+  LFastAllocate(LOperand* size, LOperand* temp1, LOperand* temp2) {
+    inputs_[0] = size;
+    temps_[0] = temp1;
+    temps_[1] = temp2;
+  }
+
+  LOperand* size() { return inputs_[0]; }
+  LOperand* temp1() { return temps_[0]; }
+  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(FastAllocate, "fast-allocate")
+  DECLARE_HYDROGEN_ACCESSOR(Allocate)
+};
 
 class LApplyArguments final : public LTemplateInstruction<1, 4, 0> {
  public:
@@ -979,20 +994,6 @@
 };
 
 
-class LConstructDouble final : public LTemplateInstruction<1, 2, 0> {
- public:
-  LConstructDouble(LOperand* hi, LOperand* lo) {
-    inputs_[0] = hi;
-    inputs_[1] = lo;
-  }
-
-  LOperand* hi() { return inputs_[0]; }
-  LOperand* lo() { return inputs_[1]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
-};
-
-
 class LClassOfTestAndBranch final : public LControlInstruction<1, 2> {
  public:
   LClassOfTestAndBranch(LOperand* value, LOperand* temp1, LOperand* temp2) {
@@ -1363,22 +1364,6 @@
 };
 
 
-class LInstanceOf final : public LTemplateInstruction<1, 3, 0> {
- public:
-  LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
-    inputs_[0] = context;
-    inputs_[1] = left;
-    inputs_[2] = right;
-  }
-
-  LOperand* context() const { return inputs_[0]; }
-  LOperand* left() const { return inputs_[1]; }
-  LOperand* right() const { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
-};
-
-
 class LHasInPrototypeChainAndBranch final : public LControlInstruction<2, 2> {
  public:
   LHasInPrototypeChainAndBranch(LOperand* object, LOperand* prototype,
@@ -1568,18 +1553,14 @@
   DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
 };
 
-
-class LLoadGlobalGeneric final : public LTemplateInstruction<1, 2, 1> {
+class LLoadGlobalGeneric final : public LTemplateInstruction<1, 1, 1> {
  public:
-  LLoadGlobalGeneric(LOperand* context, LOperand* global_object,
-                     LOperand* vector) {
+  LLoadGlobalGeneric(LOperand* context, LOperand* vector) {
     inputs_[0] = context;
-    inputs_[1] = global_object;
     temps_[0] = vector;
   }
 
   LOperand* context() { return inputs_[0]; }
-  LOperand* global_object() { return inputs_[1]; }
   LOperand* temp_vector() { return temps_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
@@ -1765,26 +1746,23 @@
   DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
 };
 
-
-class LMathExp final : public LUnaryMathOperation<4> {
+class LMathCos final : public LUnaryMathOperation<0> {
  public:
-  LMathExp(LOperand* value,
-                LOperand* double_temp1,
-                LOperand* temp1,
-                LOperand* temp2,
-                LOperand* temp3)
-      : LUnaryMathOperation<4>(value) {
-    temps_[0] = double_temp1;
-    temps_[1] = temp1;
-    temps_[2] = temp2;
-    temps_[3] = temp3;
-    ExternalReference::InitializeMathExpData();
-  }
+  explicit LMathCos(LOperand* value) : LUnaryMathOperation<0>(value) {}
 
-  LOperand* double_temp1() { return temps_[0]; }
-  LOperand* temp1() { return temps_[1]; }
-  LOperand* temp2() { return temps_[2]; }
-  LOperand* temp3() { return temps_[3]; }
+  DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
+};
+
+class LMathSin final : public LUnaryMathOperation<0> {
+ public:
+  explicit LMathSin(LOperand* value) : LUnaryMathOperation<0>(value) {}
+
+  DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
+};
+
+class LMathExp final : public LUnaryMathOperation<0> {
+ public:
+  explicit LMathExp(LOperand* value) : LUnaryMathOperation<0>(value) {}
 
   DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
 };
diff --git a/src/crankshaft/arm64/lithium-codegen-arm64.cc b/src/crankshaft/arm64/lithium-codegen-arm64.cc
index 9bbc8b8..8df6580 100644
--- a/src/crankshaft/arm64/lithium-codegen-arm64.cc
+++ b/src/crankshaft/arm64/lithium-codegen-arm64.cc
@@ -12,7 +12,6 @@
 #include "src/crankshaft/hydrogen-osr.h"
 #include "src/ic/ic.h"
 #include "src/ic/stub-cache.h"
-#include "src/profiler/cpu-profiler.h"
 
 namespace v8 {
 namespace internal {
@@ -365,15 +364,7 @@
   DCHECK(ToRegister(instr->constructor()).is(x1));
 
   __ Mov(x0, Operand(instr->arity()));
-  if (instr->arity() == 1) {
-    // We only need the allocation site for the case we have a length argument.
-    // The case may bail out to the runtime, which will determine the correct
-    // elements kind with the site.
-    __ Mov(x2, instr->hydrogen()->site());
-  } else {
-    __ LoadRoot(x2, Heap::kUndefinedValueRootIndex);
-  }
-
+  __ Mov(x2, instr->hydrogen()->site());
 
   ElementsKind kind = instr->hydrogen()->elements_kind();
   AllocationSiteOverrideMode override_mode =
@@ -406,7 +397,7 @@
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
     __ Bind(&done);
   } else {
-    ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
+    ArrayNArgumentsConstructorStub stub(isolate());
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   }
   RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta());
@@ -457,7 +448,6 @@
 void LCodeGen::RecordAndWritePosition(int position) {
   if (position == RelocInfo::kNoPosition) return;
   masm()->positions_recorder()->RecordPosition(position);
-  masm()->positions_recorder()->WriteRecordedPositions();
 }
 
 
@@ -599,7 +589,7 @@
   Comment(";;; Prologue begin");
 
   // Allocate a local context if needed.
-  if (info()->num_heap_slots() > 0) {
+  if (info()->scope()->num_heap_slots() > 0) {
     Comment(";;; Allocate local context");
     bool need_write_barrier = true;
     // Argument to NewContext is the function, which is in x1.
@@ -775,8 +765,6 @@
         // table.
         __ Bl(&call_deopt_entry);
       }
-      info()->LogDeoptCallPosition(masm()->pc_offset(),
-                                   table_entry->deopt_info.inlining_id);
 
       masm()->CheckConstPool(false, false);
     }
@@ -892,7 +880,7 @@
     __ Bind(&dont_trap);
   }
 
-  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason);
+  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason, id);
 
   DCHECK(info()->IsStub() || frame_is_built_);
   // Go through jump table if we need to build frame, or restore caller doubles.
@@ -900,14 +888,13 @@
       frame_is_built_ && !info()->saves_caller_doubles()) {
     DeoptComment(deopt_info);
     __ Call(entry, RelocInfo::RUNTIME_ENTRY);
-    info()->LogDeoptCallPosition(masm()->pc_offset(), deopt_info.inlining_id);
   } else {
     Deoptimizer::JumpTableEntry* table_entry =
         new (zone()) Deoptimizer::JumpTableEntry(
             entry, deopt_info, bailout_type, !frame_is_built_);
     // We often have several deopts to the same entry, reuse the last
     // jump entry if this is the case.
-    if (FLAG_trace_deopt || isolate()->cpu_profiler()->is_profiling() ||
+    if (FLAG_trace_deopt || isolate()->is_profiling() ||
         jump_table_.is_empty() ||
         !table_entry->IsEquivalentTo(*jump_table_.last())) {
       jump_table_.Add(table_entry, zone());
@@ -1416,7 +1403,7 @@
   Register temp2 = ToRegister(instr->temp2());
 
   // Allocate memory for the object.
-  AllocationFlags flags = TAG_OBJECT;
+  AllocationFlags flags = NO_ALLOCATION_FLAGS;
   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
   }
@@ -1426,6 +1413,11 @@
     flags = static_cast<AllocationFlags>(flags | PRETENURE);
   }
 
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    flags = static_cast<AllocationFlags>(flags | ALLOCATION_FOLDING_DOMINATOR);
+  }
+  DCHECK(!instr->hydrogen()->IsAllocationFolded());
+
   if (instr->size()->IsConstantOperand()) {
     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
     CHECK(size <= Page::kMaxRegularHeapObjectSize);
@@ -1487,6 +1479,49 @@
   CallRuntimeFromDeferred(
       Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
   __ StoreToSafepointRegisterSlot(x0, ToRegister(instr->result()));
+
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    AllocationFlags allocation_flags = NO_ALLOCATION_FLAGS;
+    if (instr->hydrogen()->IsOldSpaceAllocation()) {
+      DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+      allocation_flags = static_cast<AllocationFlags>(flags | PRETENURE);
+    }
+    // If the allocation folding dominator allocate triggered a GC, allocation
+    // happend in the runtime. We have to reset the top pointer to virtually
+    // undo the allocation.
+    ExternalReference allocation_top =
+        AllocationUtils::GetAllocationTopReference(isolate(), allocation_flags);
+    Register top_address = x10;
+    __ Sub(x0, x0, Operand(kHeapObjectTag));
+    __ Mov(top_address, Operand(allocation_top));
+    __ Str(x0, MemOperand(top_address));
+    __ Add(x0, x0, Operand(kHeapObjectTag));
+  }
+}
+
+void LCodeGen::DoFastAllocate(LFastAllocate* instr) {
+  DCHECK(instr->hydrogen()->IsAllocationFolded());
+  DCHECK(!instr->hydrogen()->IsAllocationFoldingDominator());
+  Register result = ToRegister(instr->result());
+  Register scratch1 = ToRegister(instr->temp1());
+  Register scratch2 = ToRegister(instr->temp2());
+
+  AllocationFlags flags = ALLOCATION_FOLDED;
+  if (instr->hydrogen()->MustAllocateDoubleAligned()) {
+    flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
+  }
+  if (instr->hydrogen()->IsOldSpaceAllocation()) {
+    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+    flags = static_cast<AllocationFlags>(flags | PRETENURE);
+  }
+  if (instr->size()->IsConstantOperand()) {
+    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
+    CHECK(size <= Page::kMaxRegularHeapObjectSize);
+    __ FastAllocate(size, result, scratch1, scratch2, flags);
+  } else {
+    Register size = ToRegister(instr->size());
+    __ FastAllocate(size, result, scratch1, scratch2, flags);
+  }
 }
 
 
@@ -2182,18 +2217,6 @@
 }
 
 
-void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
-  Register hi_reg = ToRegister(instr->hi());
-  Register lo_reg = ToRegister(instr->lo());
-  DoubleRegister result_reg = ToDoubleRegister(instr->result());
-
-  // Insert the least significant 32 bits of hi_reg into the most significant
-  // 32 bits of lo_reg, and move to a floating point register.
-  __ Bfi(lo_reg, hi_reg, 32, 32);
-  __ Fmov(result_reg, lo_reg);
-}
-
-
 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
   Handle<String> class_name = instr->hydrogen()->class_name();
   Label* true_label = instr->TrueLabel(chunk_);
@@ -2758,16 +2781,6 @@
 }
 
 
-void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
-  DCHECK(ToRegister(instr->context()).is(cp));
-  DCHECK(ToRegister(instr->left()).is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(ToRegister(instr->right()).is(InstanceOfDescriptor::RightRegister()));
-  DCHECK(ToRegister(instr->result()).is(x0));
-  InstanceOfStub stub(isolate());
-  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
-}
-
-
 void LCodeGen::DoHasInPrototypeChainAndBranch(
     LHasInPrototypeChainAndBranch* instr) {
   Register const object = ToRegister(instr->object());
@@ -2798,10 +2811,10 @@
   DeoptimizeIf(eq, instr, Deoptimizer::kProxy);
 
   __ Ldr(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset));
-  __ Cmp(object_prototype, prototype);
-  __ B(eq, instr->TrueLabel(chunk_));
   __ CompareRoot(object_prototype, Heap::kNullValueRootIndex);
   __ B(eq, instr->FalseLabel(chunk_));
+  __ Cmp(object_prototype, prototype);
+  __ B(eq, instr->TrueLabel(chunk_));
   __ Ldr(object_map, FieldMemOperand(object_prototype, HeapObject::kMapOffset));
   __ B(&loop);
 }
@@ -2830,7 +2843,9 @@
 #endif
   if (FLAG_code_comments) {
     if (actual.is_reg()) {
-      Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString());
+      Comment(";;; PrepareForTailCall, actual: %s {",
+              RegisterConfiguration::Crankshaft()->GetGeneralRegisterName(
+                  actual.reg().code()));
     } else {
       Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate());
     }
@@ -3051,14 +3066,12 @@
 
 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   DCHECK(ToRegister(instr->context()).is(cp));
-  DCHECK(ToRegister(instr->global_object())
-             .is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->result()).Is(x0));
-  __ Mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
+
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), instr->typeof_mode(), PREMONOMORPHIC)
-                        .code();
+  Handle<Code> ic =
+      CodeFactory::LoadGlobalICInOptimizedCode(isolate(), instr->typeof_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3316,13 +3329,9 @@
   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
-  }
+  EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
 
-  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
-                        isolate(), instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 
   DCHECK(ToRegister(instr->result()).Is(x0));
@@ -3376,10 +3385,7 @@
   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
   __ Mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_INSIDE_TYPEOF,
-                        instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 
   DCHECK(ToRegister(instr->result()).is(x0));
@@ -3527,19 +3533,25 @@
   __ Bind(&done);
 }
 
+void LCodeGen::DoMathCos(LMathCos* instr) {
+  DCHECK(instr->IsMarkedAsCall());
+  DCHECK(ToDoubleRegister(instr->value()).is(d0));
+  __ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 0, 1);
+  DCHECK(ToDoubleRegister(instr->result()).Is(d0));
+}
+
+void LCodeGen::DoMathSin(LMathSin* instr) {
+  DCHECK(instr->IsMarkedAsCall());
+  DCHECK(ToDoubleRegister(instr->value()).is(d0));
+  __ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 0, 1);
+  DCHECK(ToDoubleRegister(instr->result()).Is(d0));
+}
 
 void LCodeGen::DoMathExp(LMathExp* instr) {
-  DoubleRegister input = ToDoubleRegister(instr->value());
-  DoubleRegister result = ToDoubleRegister(instr->result());
-  DoubleRegister double_temp1 = ToDoubleRegister(instr->double_temp1());
-  DoubleRegister double_temp2 = double_scratch();
-  Register temp1 = ToRegister(instr->temp1());
-  Register temp2 = ToRegister(instr->temp2());
-  Register temp3 = ToRegister(instr->temp3());
-
-  MathExpGenerator::EmitMathExp(masm(), input, result,
-                                double_temp1, double_temp2,
-                                temp1, temp2, temp3);
+  DCHECK(instr->IsMarkedAsCall());
+  DCHECK(ToDoubleRegister(instr->value()).is(d0));
+  __ CallCFunction(ExternalReference::ieee754_exp_function(isolate()), 0, 1);
+  DCHECK(ToDoubleRegister(instr->result()).Is(d0));
 }
 
 
@@ -3708,8 +3720,7 @@
 void LCodeGen::DoMathLog(LMathLog* instr) {
   DCHECK(instr->IsMarkedAsCall());
   DCHECK(ToDoubleRegister(instr->value()).is(d0));
-  __ CallCFunction(ExternalReference::math_log_double_function(isolate()),
-                   0, 1);
+  __ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
   DCHECK(ToDoubleRegister(instr->result()).Is(d0));
 }
 
@@ -4960,13 +4971,11 @@
   DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
 
   Handle<Code> ic = CodeFactory::KeyedStoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state()).code();
+                        isolate(), instr->language_mode())
+                        .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -5160,14 +5169,12 @@
   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
 
   __ Mov(StoreDescriptor::NameRegister(), Operand(instr->name()));
-  Handle<Code> ic = CodeFactory::StoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic =
+      CodeFactory::StoreICInOptimizedCode(isolate(), instr->language_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -5442,8 +5449,7 @@
     DCHECK(ToRegister(instr->context()).is(cp));
     PushSafepointRegistersScope scope(this);
     __ Mov(x1, Operand(to_map));
-    bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
-    TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
+    TransitionElementsKindStub stub(isolate(), from_kind, to_kind);
     __ CallStub(&stub);
     RecordSafepointWithRegisters(
         instr->pointer_map(), 0, Safepoint::kLazyDeopt);
diff --git a/src/crankshaft/arm64/lithium-gap-resolver-arm64.h b/src/crankshaft/arm64/lithium-gap-resolver-arm64.h
index 4f5eb22..acac4e1 100644
--- a/src/crankshaft/arm64/lithium-gap-resolver-arm64.h
+++ b/src/crankshaft/arm64/lithium-gap-resolver-arm64.h
@@ -66,7 +66,8 @@
 
   // Registers used to solve cycles.
   const Register& SavedValueRegister() {
-    DCHECK(!masm_.ScratchRegister().IsAllocatable());
+    DCHECK(!RegisterConfiguration::Crankshaft()->IsAllocatableGeneralCode(
+        masm_.ScratchRegister().code()));
     return masm_.ScratchRegister();
   }
   // The scratch register is used to break cycles and to store constant.
@@ -77,7 +78,8 @@
     // We use the Crankshaft floating-point scratch register to break a cycle
     // involving double values as the MacroAssembler will not need it for the
     // operations performed by the gap resolver.
-    DCHECK(!crankshaft_fp_scratch.IsAllocatable());
+    DCHECK(!RegisterConfiguration::Crankshaft()->IsAllocatableGeneralCode(
+        crankshaft_fp_scratch.code()));
     return crankshaft_fp_scratch;
   }
 
diff --git a/src/crankshaft/hydrogen-gvn.cc b/src/crankshaft/hydrogen-gvn.cc
index 07bfabc..e6ddd75 100644
--- a/src/crankshaft/hydrogen-gvn.cc
+++ b/src/crankshaft/hydrogen-gvn.cc
@@ -637,17 +637,12 @@
 }
 
 
-bool HGlobalValueNumberingPhase::AllowCodeMotion() {
-  return info()->IsStub() || info()->opt_count() + 1 < FLAG_max_opt_count;
-}
-
-
 bool HGlobalValueNumberingPhase::ShouldMove(HInstruction* instr,
                                             HBasicBlock* loop_header) {
   // If we've disabled code motion or we're in a block that unconditionally
   // deoptimizes, don't move any instructions.
-  return AllowCodeMotion() && !instr->block()->IsDeoptimizing() &&
-      instr->block()->IsReachable();
+  return graph()->allow_code_motion() && !instr->block()->IsDeoptimizing() &&
+         instr->block()->IsReachable();
 }
 
 
diff --git a/src/crankshaft/hydrogen-gvn.h b/src/crankshaft/hydrogen-gvn.h
index a5e2168..9a8d407 100644
--- a/src/crankshaft/hydrogen-gvn.h
+++ b/src/crankshaft/hydrogen-gvn.h
@@ -126,7 +126,6 @@
   void ProcessLoopBlock(HBasicBlock* block,
                         HBasicBlock* before_loop,
                         SideEffects loop_kills);
-  bool AllowCodeMotion();
   bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header);
   TrackedEffects Print(SideEffects side_effects) {
     return TrackedEffects(&side_effects_tracker_, side_effects);
diff --git a/src/crankshaft/hydrogen-instructions.cc b/src/crankshaft/hydrogen-instructions.cc
index 7de8b5d..6036d3f 100644
--- a/src/crankshaft/hydrogen-instructions.cc
+++ b/src/crankshaft/hydrogen-instructions.cc
@@ -5,6 +5,7 @@
 #include "src/crankshaft/hydrogen-instructions.h"
 
 #include "src/base/bits.h"
+#include "src/base/ieee754.h"
 #include "src/base/safe_math.h"
 #include "src/crankshaft/hydrogen-infer-representation.h"
 #include "src/double.h"
@@ -784,7 +785,6 @@
     case HValue::kCompareNumericAndBranch:
     case HValue::kCompareObjectEqAndBranch:
     case HValue::kConstant:
-    case HValue::kConstructDouble:
     case HValue::kContext:
     case HValue::kDebugBreak:
     case HValue::kDeclareGlobals:
@@ -798,7 +798,6 @@
     case HValue::kHasCachedArrayIndexAndBranch:
     case HValue::kHasInstanceTypeAndBranch:
     case HValue::kInnerAllocatedObject:
-    case HValue::kInstanceOf:
     case HValue::kIsSmiAndBranch:
     case HValue::kIsStringAndBranch:
     case HValue::kIsUndetectableAndBranch:
@@ -1115,10 +1114,14 @@
       return "round";
     case kMathAbs:
       return "abs";
+    case kMathCos:
+      return "cos";
     case kMathLog:
       return "log";
     case kMathExp:
       return "exp";
+    case kMathSin:
+      return "sin";
     case kMathSqrt:
       return "sqrt";
     case kMathPowHalf:
@@ -1203,7 +1206,6 @@
 String* TypeOfString(HConstant* constant, Isolate* isolate) {
   Heap* heap = isolate->heap();
   if (constant->HasNumberValue()) return heap->number_string();
-  if (constant->IsUndetectable()) return heap->undefined_string();
   if (constant->HasStringValue()) return heap->string_string();
   switch (constant->GetInstanceType()) {
     case ODDBALL_TYPE: {
@@ -1232,6 +1234,7 @@
       return nullptr;
     }
     default:
+      if (constant->IsUndetectable()) return heap->undefined_string();
       if (constant->IsCallable()) return heap->function_string();
       return heap->object_string();
   }
@@ -1554,6 +1557,9 @@
     case IS_JS_ARRAY:
       *first = *last = JS_ARRAY_TYPE;
       return;
+    case IS_JS_FUNCTION:
+      *first = *last = JS_FUNCTION_TYPE;
+      return;
     case IS_JS_DATE:
       *first = *last = JS_DATE_TYPE;
       return;
@@ -1626,6 +1632,8 @@
   switch (check_) {
     case IS_JS_RECEIVER: return "object";
     case IS_JS_ARRAY: return "array";
+    case IS_JS_FUNCTION:
+      return "function";
     case IS_JS_DATE:
       return "date";
     case IS_STRING: return "string";
@@ -1652,12 +1660,6 @@
 }
 
 
-std::ostream& HInstanceOf::PrintDataTo(std::ostream& os) const {  // NOLINT
-  return os << NameOf(left()) << " " << NameOf(right()) << " "
-            << NameOf(context());
-}
-
-
 Range* HValue::InferRange(Zone* zone) {
   Range* result;
   if (representation().IsSmi() || type().IsSmi()) {
@@ -2419,9 +2421,9 @@
   if (handle->IsBoolean()) {
     res = handle->BooleanValue() ?
       new(zone) HConstant(1) : new(zone) HConstant(0);
-  } else if (handle->IsUndefined()) {
+  } else if (handle->IsUndefined(isolate)) {
     res = new (zone) HConstant(std::numeric_limits<double>::quiet_NaN());
-  } else if (handle->IsNull()) {
+  } else if (handle->IsNull(isolate)) {
     res = new(zone) HConstant(0);
   } else if (handle->IsString()) {
     res = new(zone) HConstant(String::ToNumber(Handle<String>::cast(handle)));
@@ -3126,6 +3128,7 @@
 bool HAllocate::HandleSideEffectDominator(GVNFlag side_effect,
                                           HValue* dominator) {
   DCHECK(side_effect == kNewSpacePromotion);
+  DCHECK(!IsAllocationFolded());
   Zone* zone = block()->zone();
   Isolate* isolate = block()->isolate();
   if (!FLAG_use_allocation_folding) return false;
@@ -3153,7 +3156,8 @@
   HValue* current_size = size();
 
   // TODO(hpayer): Add support for non-constant allocation in dominator.
-  if (!dominator_size->IsInteger32Constant()) {
+  if (!current_size->IsInteger32Constant() ||
+      !dominator_size->IsInteger32Constant()) {
     if (FLAG_trace_allocation_folding) {
       PrintF("#%d (%s) cannot fold into #%d (%s), "
              "dynamic allocation size in dominator\n",
@@ -3171,32 +3175,6 @@
     return false;
   }
 
-  if (!has_size_upper_bound()) {
-    if (FLAG_trace_allocation_folding) {
-      PrintF("#%d (%s) cannot fold into #%d (%s), "
-             "can't estimate total allocation size\n",
-          id(), Mnemonic(), dominator->id(), dominator->Mnemonic());
-    }
-    return false;
-  }
-
-  if (!current_size->IsInteger32Constant()) {
-    // If it's not constant then it is a size_in_bytes calculation graph
-    // like this: (const_header_size + const_element_size * size).
-    DCHECK(current_size->IsInstruction());
-
-    HInstruction* current_instr = HInstruction::cast(current_size);
-    if (!current_instr->Dominates(dominator_allocate)) {
-      if (FLAG_trace_allocation_folding) {
-        PrintF("#%d (%s) cannot fold into #%d (%s), dynamic size "
-               "value does not dominate target allocation\n",
-            id(), Mnemonic(), dominator_allocate->id(),
-            dominator_allocate->Mnemonic());
-      }
-      return false;
-    }
-  }
-
   DCHECK(
       (IsNewSpaceAllocation() && dominator_allocate->IsNewSpaceAllocation()) ||
       (IsOldSpaceAllocation() && dominator_allocate->IsOldSpaceAllocation()));
@@ -3213,7 +3191,7 @@
     }
   }
 
-  int32_t current_size_max_value = size_upper_bound()->GetInteger32Constant();
+  int32_t current_size_max_value = size()->GetInteger32Constant();
   int32_t new_dominator_size = dominator_size_constant + current_size_max_value;
 
   // Since we clear the first word after folded memory, we cannot use the
@@ -3227,27 +3205,9 @@
     return false;
   }
 
-  HInstruction* new_dominator_size_value;
-
-  if (current_size->IsInteger32Constant()) {
-    new_dominator_size_value = HConstant::CreateAndInsertBefore(
-        isolate, zone, context(), new_dominator_size, Representation::None(),
-        dominator_allocate);
-  } else {
-    HValue* new_dominator_size_constant = HConstant::CreateAndInsertBefore(
-        isolate, zone, context(), dominator_size_constant,
-        Representation::Integer32(), dominator_allocate);
-
-    // Add old and new size together and insert.
-    current_size->ChangeRepresentation(Representation::Integer32());
-
-    new_dominator_size_value = HAdd::New(
-        isolate, zone, context(), new_dominator_size_constant, current_size);
-    new_dominator_size_value->ClearFlag(HValue::kCanOverflow);
-    new_dominator_size_value->ChangeRepresentation(Representation::Integer32());
-
-    new_dominator_size_value->InsertBefore(dominator_allocate);
-  }
+  HInstruction* new_dominator_size_value = HConstant::CreateAndInsertBefore(
+      isolate, zone, context(), new_dominator_size, Representation::None(),
+      dominator_allocate);
 
   dominator_allocate->UpdateSize(new_dominator_size_value);
 
@@ -3257,103 +3217,45 @@
     }
   }
 
-  bool keep_heap_iterable = FLAG_log_gc || FLAG_heap_stats;
-#ifdef VERIFY_HEAP
-  keep_heap_iterable = keep_heap_iterable || FLAG_verify_heap;
-#endif
-
-  if (keep_heap_iterable) {
-    dominator_allocate->MakePrefillWithFiller();
-  } else {
-    // TODO(hpayer): This is a short-term hack to make allocation mementos
-    // work again in new space.
-    dominator_allocate->ClearNextMapWord(original_object_size);
+  if (IsAllocationFoldingDominator()) {
+    DeleteAndReplaceWith(dominator_allocate);
+    if (FLAG_trace_allocation_folding) {
+      PrintF(
+          "#%d (%s) folded dominator into #%d (%s), new dominator size: %d\n",
+          id(), Mnemonic(), dominator_allocate->id(),
+          dominator_allocate->Mnemonic(), new_dominator_size);
+    }
+    return true;
   }
 
-  dominator_allocate->UpdateClearNextMapWord(MustClearNextMapWord());
+  if (!dominator_allocate->IsAllocationFoldingDominator()) {
+    HAllocate* first_alloc =
+        HAllocate::New(isolate, zone, dominator_allocate->context(),
+                       dominator_size, dominator_allocate->type(),
+                       IsNewSpaceAllocation() ? NOT_TENURED : TENURED,
+                       JS_OBJECT_TYPE, block()->graph()->GetConstant0());
+    first_alloc->InsertAfter(dominator_allocate);
+    dominator_allocate->ReplaceAllUsesWith(first_alloc);
+    dominator_allocate->MakeAllocationFoldingDominator();
+    first_alloc->MakeFoldedAllocation(dominator_allocate);
+    if (FLAG_trace_allocation_folding) {
+      PrintF("#%d (%s) inserted for dominator #%d (%s)\n", first_alloc->id(),
+             first_alloc->Mnemonic(), dominator_allocate->id(),
+             dominator_allocate->Mnemonic());
+    }
+  }
 
-  // After that replace the dominated allocate instruction.
-  HInstruction* inner_offset = HConstant::CreateAndInsertBefore(
-      isolate, zone, context(), dominator_size_constant, Representation::None(),
-      this);
+  MakeFoldedAllocation(dominator_allocate);
 
-  HInstruction* dominated_allocate_instr = HInnerAllocatedObject::New(
-      isolate, zone, context(), dominator_allocate, inner_offset, type());
-  dominated_allocate_instr->InsertBefore(this);
-  DeleteAndReplaceWith(dominated_allocate_instr);
   if (FLAG_trace_allocation_folding) {
-    PrintF("#%d (%s) folded into #%d (%s)\n",
-        id(), Mnemonic(), dominator_allocate->id(),
-        dominator_allocate->Mnemonic());
+    PrintF("#%d (%s) folded into #%d (%s), new dominator size: %d\n", id(),
+           Mnemonic(), dominator_allocate->id(), dominator_allocate->Mnemonic(),
+           new_dominator_size);
   }
   return true;
 }
 
 
-void HAllocate::UpdateFreeSpaceFiller(int32_t free_space_size) {
-  DCHECK(filler_free_space_size_ != NULL);
-  Zone* zone = block()->zone();
-  // We must explicitly force Smi representation here because on x64 we
-  // would otherwise automatically choose int32, but the actual store
-  // requires a Smi-tagged value.
-  HConstant* new_free_space_size = HConstant::CreateAndInsertBefore(
-      block()->isolate(), zone, context(),
-      filler_free_space_size_->value()->GetInteger32Constant() +
-          free_space_size,
-      Representation::Smi(), filler_free_space_size_);
-  filler_free_space_size_->UpdateValue(new_free_space_size);
-}
-
-
-void HAllocate::CreateFreeSpaceFiller(int32_t free_space_size) {
-  DCHECK(filler_free_space_size_ == NULL);
-  Isolate* isolate = block()->isolate();
-  Zone* zone = block()->zone();
-  HInstruction* free_space_instr =
-      HInnerAllocatedObject::New(isolate, zone, context(), dominating_allocate_,
-                                 dominating_allocate_->size(), type());
-  free_space_instr->InsertBefore(this);
-  HConstant* filler_map = HConstant::CreateAndInsertAfter(
-      zone, Unique<Map>::CreateImmovable(isolate->factory()->free_space_map()),
-      true, free_space_instr);
-  HInstruction* store_map =
-      HStoreNamedField::New(isolate, zone, context(), free_space_instr,
-                            HObjectAccess::ForMap(), filler_map);
-  store_map->SetFlag(HValue::kHasNoObservableSideEffects);
-  store_map->InsertAfter(filler_map);
-
-  // We must explicitly force Smi representation here because on x64 we
-  // would otherwise automatically choose int32, but the actual store
-  // requires a Smi-tagged value.
-  HConstant* filler_size =
-      HConstant::CreateAndInsertAfter(isolate, zone, context(), free_space_size,
-                                      Representation::Smi(), store_map);
-  // Must force Smi representation for x64 (see comment above).
-  HObjectAccess access = HObjectAccess::ForMapAndOffset(
-      isolate->factory()->free_space_map(), FreeSpace::kSizeOffset,
-      Representation::Smi());
-  HStoreNamedField* store_size = HStoreNamedField::New(
-      isolate, zone, context(), free_space_instr, access, filler_size);
-  store_size->SetFlag(HValue::kHasNoObservableSideEffects);
-  store_size->InsertAfter(filler_size);
-  filler_free_space_size_ = store_size;
-}
-
-
-void HAllocate::ClearNextMapWord(int offset) {
-  if (MustClearNextMapWord()) {
-    Zone* zone = block()->zone();
-    HObjectAccess access =
-        HObjectAccess::ForObservableJSObjectOffset(offset);
-    HStoreNamedField* clear_next_map =
-        HStoreNamedField::New(block()->isolate(), zone, context(), this, access,
-                              block()->graph()->GetConstant0());
-    clear_next_map->ClearAllSideEffects();
-    clear_next_map->InsertAfter(this);
-  }
-}
-
-
 std::ostream& HAllocate::PrintDataTo(std::ostream& os) const {  // NOLINT
   os << NameOf(size()) << " (";
   if (IsNewSpaceAllocation()) os << "N";
@@ -3502,6 +3404,9 @@
     }
     if (std::isinf(d)) {  // +Infinity and -Infinity.
       switch (op) {
+        case kMathCos:
+        case kMathSin:
+          return H_CONSTANT_DOUBLE(std::numeric_limits<double>::quiet_NaN());
         case kMathExp:
           return H_CONSTANT_DOUBLE((d > 0.0) ? d : 0.0);
         case kMathLog:
@@ -3523,11 +3428,14 @@
       }
     }
     switch (op) {
+      case kMathCos:
+        return H_CONSTANT_DOUBLE(base::ieee754::cos(d));
       case kMathExp:
-        lazily_initialize_fast_exp(isolate);
-        return H_CONSTANT_DOUBLE(fast_exp(d, isolate));
+        return H_CONSTANT_DOUBLE(base::ieee754::exp(d));
       case kMathLog:
-        return H_CONSTANT_DOUBLE(std::log(d));
+        return H_CONSTANT_DOUBLE(base::ieee754::log(d));
+      case kMathSin:
+        return H_CONSTANT_DOUBLE(base::ieee754::sin(d));
       case kMathSqrt:
         lazily_initialize_fast_sqrt(isolate);
         return H_CONSTANT_DOUBLE(fast_sqrt(d, isolate));
diff --git a/src/crankshaft/hydrogen-instructions.h b/src/crankshaft/hydrogen-instructions.h
index 196a14f..9a757c8 100644
--- a/src/crankshaft/hydrogen-instructions.h
+++ b/src/crankshaft/hydrogen-instructions.h
@@ -77,7 +77,6 @@
   V(CompareObjectEqAndBranch)                 \
   V(CompareMap)                               \
   V(Constant)                                 \
-  V(ConstructDouble)                          \
   V(Context)                                  \
   V(DebugBreak)                               \
   V(DeclareGlobals)                           \
@@ -95,7 +94,6 @@
   V(HasCachedArrayIndexAndBranch)             \
   V(HasInstanceTypeAndBranch)                 \
   V(InnerAllocatedObject)                     \
-  V(InstanceOf)                               \
   V(InvokeFunction)                           \
   V(HasInPrototypeChainAndBranch)             \
   V(IsStringAndBranch)                        \
@@ -1692,34 +1690,6 @@
 };
 
 
-class HConstructDouble final : public HTemplateInstruction<2> {
- public:
-  DECLARE_INSTRUCTION_FACTORY_P2(HConstructDouble, HValue*, HValue*);
-
-  Representation RequiredInputRepresentation(int index) override {
-    return Representation::Integer32();
-  }
-
-  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble)
-
-  HValue* hi() { return OperandAt(0); }
-  HValue* lo() { return OperandAt(1); }
-
- protected:
-  bool DataEquals(HValue* other) override { return true; }
-
- private:
-  explicit HConstructDouble(HValue* hi, HValue* lo) {
-    set_representation(Representation::Double());
-    SetFlag(kUseGVN);
-    SetOperandAt(0, hi);
-    SetOperandAt(1, lo);
-  }
-
-  bool IsDeletable() const override { return true; }
-};
-
-
 enum RemovableSimulate {
   REMOVABLE_SIMULATE,
   FIXED_SIMULATE
@@ -2162,8 +2132,6 @@
     this->SetAllSideEffects();
   }
 
-  HType CalculateInferredType() final { return HType::Tagged(); }
-
   virtual int argument_count() const {
     return argument_count_;
   }
@@ -2241,8 +2209,6 @@
 
   DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor)
 
-  HType CalculateInferredType() final { return HType::Tagged(); }
-
   // Defines whether this instruction corresponds to a JS call at tail position.
   TailCallMode syntactic_tail_call_mode() const {
     return SyntacticTailCallModeField::decode(bit_field_);
@@ -2458,9 +2424,11 @@
       return Representation::Tagged();
     } else {
       switch (op_) {
+        case kMathCos:
         case kMathFloor:
         case kMathRound:
         case kMathFround:
+        case kMathSin:
         case kMathSqrt:
         case kMathPowHalf:
         case kMathLog:
@@ -2498,7 +2466,7 @@
   // Indicates if we support a double (and int32) output for Math.floor and
   // Math.round.
   bool SupportsFlexibleFloorAndRound() const {
-#if V8_TARGET_ARCH_ARM64
+#if V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_PPC
     return true;
 #elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
     return CpuFeatures::IsSupported(SSE4_1);
@@ -2529,9 +2497,11 @@
         // is tagged, and not when it is an unboxed double or unboxed integer.
         SetChangesFlag(kNewSpacePromotion);
         break;
+      case kMathCos:
       case kMathFround:
       case kMathLog:
       case kMathExp:
+      case kMathSin:
       case kMathSqrt:
       case kMathPowHalf:
         set_representation(Representation::Double());
@@ -2791,6 +2761,7 @@
   enum Check {
     IS_JS_RECEIVER,
     IS_JS_ARRAY,
+    IS_JS_FUNCTION,
     IS_JS_DATE,
     IS_STRING,
     IS_INTERNALIZED_STRING,
@@ -2809,6 +2780,8 @@
     switch (check_) {
       case IS_JS_RECEIVER: return HType::JSReceiver();
       case IS_JS_ARRAY: return HType::JSArray();
+      case IS_JS_FUNCTION:
+        return HType::JSObject();
       case IS_JS_DATE: return HType::JSObject();
       case IS_STRING: return HType::String();
       case IS_INTERNALIZED_STRING: return HType::String();
@@ -3767,6 +3740,7 @@
       : HBinaryOperation(context, left, right, type) {
     SetFlag(kFlexibleRepresentation);
     SetFlag(kTruncatingToInt32);
+    SetFlag(kAllowUndefinedAsNaN);
     SetAllSideEffects();
   }
 
@@ -4271,27 +4245,6 @@
 };
 
 
-class HInstanceOf final : public HBinaryOperation {
- public:
-  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HInstanceOf, HValue*, HValue*);
-
-  Representation RequiredInputRepresentation(int index) override {
-    return Representation::Tagged();
-  }
-
-  std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
-
-  DECLARE_CONCRETE_INSTRUCTION(InstanceOf)
-
- private:
-  HInstanceOf(HValue* context, HValue* left, HValue* right)
-      : HBinaryOperation(context, left, right, HType::Boolean()) {
-    set_representation(Representation::Tagged());
-    SetAllSideEffects();
-  }
-};
-
-
 class HHasInPrototypeChainAndBranch final
     : public HTemplateControlInstruction<2, 2> {
  public:
@@ -4396,6 +4349,11 @@
       SetChangesFlag(kNewSpacePromotion);
       ClearFlag(kAllowUndefinedAsNaN);
     }
+    if (!right()->type().IsTaggedNumber() &&
+        !right()->representation().IsDouble() &&
+        !right()->representation().IsSmiOrInteger32()) {
+      ClearFlag(kAllowUndefinedAsNaN);
+    }
   }
 
   Representation RepresentationFromInputs() override;
@@ -4894,26 +4852,20 @@
   HPhi* incoming_value_;
 };
 
-
-class HLoadGlobalGeneric final : public HTemplateInstruction<2> {
+class HLoadGlobalGeneric final : public HTemplateInstruction<1> {
  public:
-  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadGlobalGeneric, HValue*,
-                                              Handle<String>, TypeofMode);
+  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadGlobalGeneric,
+                                              Handle<String>, TypeofMode,
+                                              Handle<TypeFeedbackVector>,
+                                              FeedbackVectorSlot);
 
   HValue* context() { return OperandAt(0); }
-  HValue* global_object() { return OperandAt(1); }
   Handle<String> name() const { return name_; }
   TypeofMode typeof_mode() const { return typeof_mode_; }
   FeedbackVectorSlot slot() const { return slot_; }
   Handle<TypeFeedbackVector> feedback_vector() const {
     return feedback_vector_;
   }
-  bool HasVectorAndSlot() const { return true; }
-  void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
-                        FeedbackVectorSlot slot) {
-    feedback_vector_ = vector;
-    slot_ = slot;
-  }
 
   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
 
@@ -4924,11 +4876,14 @@
   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric)
 
  private:
-  HLoadGlobalGeneric(HValue* context, HValue* global_object,
-                     Handle<String> name, TypeofMode typeof_mode)
-      : name_(name), typeof_mode_(typeof_mode) {
+  HLoadGlobalGeneric(HValue* context, Handle<String> name,
+                     TypeofMode typeof_mode, Handle<TypeFeedbackVector> vector,
+                     FeedbackVectorSlot slot)
+      : name_(name),
+        typeof_mode_(typeof_mode),
+        feedback_vector_(vector),
+        slot_(slot) {
     SetOperandAt(0, context);
-    SetOperandAt(1, global_object);
     set_representation(Representation::Tagged());
     SetAllSideEffects();
   }
@@ -4939,8 +4894,7 @@
   FeedbackVectorSlot slot_;
 };
 
-
-class HAllocate final : public HTemplateInstruction<2> {
+class HAllocate final : public HTemplateInstruction<3> {
  public:
   static bool CompatibleInstanceTypes(InstanceType type1,
                                       InstanceType type2) {
@@ -4951,9 +4905,10 @@
   static HAllocate* New(
       Isolate* isolate, Zone* zone, HValue* context, HValue* size, HType type,
       PretenureFlag pretenure_flag, InstanceType instance_type,
+      HValue* dominator,
       Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null()) {
-    return new(zone) HAllocate(context, size, type, pretenure_flag,
-        instance_type, allocation_site);
+    return new (zone) HAllocate(context, size, type, pretenure_flag,
+                                instance_type, dominator, allocation_site);
   }
 
   // Maximum instance size for which allocations will be inlined.
@@ -4961,13 +4916,7 @@
 
   HValue* context() const { return OperandAt(0); }
   HValue* size() const { return OperandAt(1); }
-
-  bool has_size_upper_bound() { return size_upper_bound_ != NULL; }
-  HConstant* size_upper_bound() { return size_upper_bound_; }
-  void set_size_upper_bound(HConstant* value) {
-    DCHECK(size_upper_bound_ == NULL);
-    size_upper_bound_ = value;
-  }
+  HValue* allocation_folding_dominator() const { return OperandAt(2); }
 
   Representation RequiredInputRepresentation(int index) override {
     if (index == 0) {
@@ -5005,14 +4954,28 @@
     flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER);
   }
 
-  bool MustClearNextMapWord() const {
-    return (flags_ & CLEAR_NEXT_MAP_WORD) != 0;
-  }
-
   void MakeDoubleAligned() {
     flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED);
   }
 
+  void MakeAllocationFoldingDominator() {
+    flags_ =
+        static_cast<HAllocate::Flags>(flags_ | ALLOCATION_FOLDING_DOMINATOR);
+  }
+
+  bool IsAllocationFoldingDominator() {
+    return (flags_ & ALLOCATION_FOLDING_DOMINATOR) != 0;
+  }
+
+  void MakeFoldedAllocation(HAllocate* dominator) {
+    flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATION_FOLDED);
+    ClearFlag(kTrackSideEffectDominators);
+    ClearChangesFlag(kNewSpacePromotion);
+    SetOperandAt(2, dominator);
+  }
+
+  bool IsAllocationFolded() { return (flags_ & ALLOCATION_FOLDED) != 0; }
+
   bool HandleSideEffectDominator(GVNFlag side_effect,
                                  HValue* dominator) override;
 
@@ -5026,23 +4989,19 @@
     ALLOCATE_IN_OLD_SPACE = 1 << 2,
     ALLOCATE_DOUBLE_ALIGNED = 1 << 3,
     PREFILL_WITH_FILLER = 1 << 4,
-    CLEAR_NEXT_MAP_WORD = 1 << 5
+    ALLOCATION_FOLDING_DOMINATOR = 1 << 5,
+    ALLOCATION_FOLDED = 1 << 6
   };
 
-  HAllocate(HValue* context,
-            HValue* size,
-            HType type,
-            PretenureFlag pretenure_flag,
-            InstanceType instance_type,
-            Handle<AllocationSite> allocation_site =
-                Handle<AllocationSite>::null())
-      : HTemplateInstruction<2>(type),
-        flags_(ComputeFlags(pretenure_flag, instance_type)),
-        dominating_allocate_(NULL),
-        filler_free_space_size_(NULL),
-        size_upper_bound_(NULL) {
+  HAllocate(
+      HValue* context, HValue* size, HType type, PretenureFlag pretenure_flag,
+      InstanceType instance_type, HValue* dominator,
+      Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null())
+      : HTemplateInstruction<3>(type),
+        flags_(ComputeFlags(pretenure_flag, instance_type)) {
     SetOperandAt(0, context);
     UpdateSize(size);
+    SetOperandAt(2, dominator);
     set_representation(Representation::Tagged());
     SetFlag(kTrackSideEffectDominators);
     SetChangesFlag(kNewSpacePromotion);
@@ -5072,46 +5031,20 @@
     if (!FLAG_use_gvn || !FLAG_use_allocation_folding) {
       flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER);
     }
-    if (pretenure_flag == NOT_TENURED &&
-        AllocationSite::CanTrack(instance_type)) {
-      flags = static_cast<Flags>(flags | CLEAR_NEXT_MAP_WORD);
-    }
     return flags;
   }
 
-  void UpdateClearNextMapWord(bool clear_next_map_word) {
-    flags_ = static_cast<Flags>(clear_next_map_word
-                                ? flags_ | CLEAR_NEXT_MAP_WORD
-                                : flags_ & ~CLEAR_NEXT_MAP_WORD);
-  }
-
   void UpdateSize(HValue* size) {
     SetOperandAt(1, size);
-    if (size->IsInteger32Constant()) {
-      size_upper_bound_ = HConstant::cast(size);
-    } else {
-      size_upper_bound_ = NULL;
-    }
   }
 
-  HAllocate* GetFoldableDominator(HAllocate* dominator);
-
-  void UpdateFreeSpaceFiller(int32_t filler_size);
-
-  void CreateFreeSpaceFiller(int32_t filler_size);
-
   bool IsFoldable(HAllocate* allocate) {
     return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) ||
            (IsOldSpaceAllocation() && allocate->IsOldSpaceAllocation());
   }
 
-  void ClearNextMapWord(int offset);
-
   Flags flags_;
   Handle<Map> known_initial_map_;
-  HAllocate* dominating_allocate_;
-  HStoreNamedField* filler_free_space_size_;
-  HConstant* size_upper_bound_;
 };
 
 
@@ -5183,9 +5116,23 @@
 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
                                             HValue* value,
                                             HValue* dominator) {
+  // There may be multiple inner allocates dominated by one allocate.
   while (object->IsInnerAllocatedObject()) {
     object = HInnerAllocatedObject::cast(object)->base_object();
   }
+
+  if (object->IsAllocate()) {
+    HAllocate* allocate = HAllocate::cast(object);
+    if (allocate->IsAllocationFolded()) {
+      HValue* dominator = allocate->allocation_folding_dominator();
+      // There is no guarantee that all allocations are folded together because
+      // GVN performs a fixpoint.
+      if (HAllocate::cast(dominator)->IsAllocationFoldingDominator()) {
+        object = dominator;
+      }
+    }
+  }
+
   if (object->IsConstant() &&
       HConstant::cast(object)->HasExternalReferenceValue()) {
     // Stores to external references require no write barriers
@@ -5226,10 +5173,7 @@
     // hole value. This is used for checking for loading of uninitialized
     // harmony bindings where we deoptimize into full-codegen generated code
     // which will subsequently throw a reference error.
-    kCheckDeoptimize,
-    // Load and check the value of the context slot. Return undefined if it's
-    // the hole value. This is used for non-harmony const assignments
-    kCheckReturnUndefined
+    kCheckDeoptimize
   };
 
   HLoadContextSlot(HValue* context, int slot_index, Mode mode)
@@ -5282,9 +5226,7 @@
     // hole value. This is used for checking for assignments to uninitialized
     // harmony bindings where we deoptimize into full-codegen generated code
     // which will subsequently throw a reference error.
-    kCheckDeoptimize,
-    // Check the previous value and ignore assignment if it isn't a hole value
-    kCheckIgnoreAssignment
+    kCheckDeoptimize
   };
 
   DECLARE_INSTRUCTION_FACTORY_P4(HStoreContextSlot, HValue*, int,
@@ -5604,6 +5546,19 @@
                          Handle<Name>::null(), false, false);
   }
 
+  static HObjectAccess ForBoundTargetFunction() {
+    return HObjectAccess(kInobject,
+                         JSBoundFunction::kBoundTargetFunctionOffset);
+  }
+
+  static HObjectAccess ForBoundThis() {
+    return HObjectAccess(kInobject, JSBoundFunction::kBoundThisOffset);
+  }
+
+  static HObjectAccess ForBoundArguments() {
+    return HObjectAccess(kInobject, JSBoundFunction::kBoundArgumentsOffset);
+  }
+
   // Create an access to an offset in a fixed array header.
   static HObjectAccess ForFixedArrayHeader(int offset);
 
@@ -5925,26 +5880,19 @@
 
 class HLoadNamedGeneric final : public HTemplateInstruction<2> {
  public:
-  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadNamedGeneric, HValue*,
-                                              Handle<Name>, InlineCacheState);
+  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadNamedGeneric, HValue*,
+                                              Handle<Name>,
+                                              Handle<TypeFeedbackVector>,
+                                              FeedbackVectorSlot);
 
   HValue* context() const { return OperandAt(0); }
   HValue* object() const { return OperandAt(1); }
   Handle<Name> name() const { return name_; }
 
-  InlineCacheState initialization_state() const {
-    return initialization_state_;
-  }
   FeedbackVectorSlot slot() const { return slot_; }
   Handle<TypeFeedbackVector> feedback_vector() const {
     return feedback_vector_;
   }
-  bool HasVectorAndSlot() const { return true; }
-  void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
-                        FeedbackVectorSlot slot) {
-    feedback_vector_ = vector;
-    slot_ = slot;
-  }
 
   Representation RequiredInputRepresentation(int index) override {
     return Representation::Tagged();
@@ -5956,9 +5904,8 @@
 
  private:
   HLoadNamedGeneric(HValue* context, HValue* object, Handle<Name> name,
-                    InlineCacheState initialization_state)
-      : name_(name),
-        initialization_state_(initialization_state) {
+                    Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
+      : name_(name), feedback_vector_(vector), slot_(slot) {
     SetOperandAt(0, context);
     SetOperandAt(1, object);
     set_representation(Representation::Tagged());
@@ -5968,7 +5915,6 @@
   Handle<Name> name_;
   Handle<TypeFeedbackVector> feedback_vector_;
   FeedbackVectorSlot slot_;
-  InlineCacheState initialization_state_;
 };
 
 
@@ -6210,27 +6156,17 @@
 
 class HLoadKeyedGeneric final : public HTemplateInstruction<3> {
  public:
-  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P3(HLoadKeyedGeneric, HValue*,
-                                              HValue*, InlineCacheState);
+  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HLoadKeyedGeneric, HValue*,
+                                              HValue*,
+                                              Handle<TypeFeedbackVector>,
+                                              FeedbackVectorSlot);
   HValue* object() const { return OperandAt(0); }
   HValue* key() const { return OperandAt(1); }
   HValue* context() const { return OperandAt(2); }
-  InlineCacheState initialization_state() const {
-    return initialization_state_;
-  }
   FeedbackVectorSlot slot() const { return slot_; }
   Handle<TypeFeedbackVector> feedback_vector() const {
     return feedback_vector_;
   }
-  bool HasVectorAndSlot() const {
-    DCHECK(initialization_state_ == MEGAMORPHIC || !feedback_vector_.is_null());
-    return !feedback_vector_.is_null();
-  }
-  void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
-                        FeedbackVectorSlot slot) {
-    feedback_vector_ = vector;
-    slot_ = slot;
-  }
 
   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
 
@@ -6245,8 +6181,8 @@
 
  private:
   HLoadKeyedGeneric(HValue* context, HValue* obj, HValue* key,
-                    InlineCacheState initialization_state)
-      : initialization_state_(initialization_state) {
+                    Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
+      : feedback_vector_(vector), slot_(slot) {
     set_representation(Representation::Tagged());
     SetOperandAt(0, obj);
     SetOperandAt(1, key);
@@ -6256,7 +6192,6 @@
 
   Handle<TypeFeedbackVector> feedback_vector_;
   FeedbackVectorSlot slot_;
-  InlineCacheState initialization_state_;
 };
 
 
@@ -6418,20 +6353,18 @@
   uint32_t bit_field_;
 };
 
-
 class HStoreNamedGeneric final : public HTemplateInstruction<3> {
  public:
-  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HStoreNamedGeneric, HValue*,
+  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(HStoreNamedGeneric, HValue*,
                                               Handle<Name>, HValue*,
-                                              LanguageMode, InlineCacheState);
+                                              LanguageMode,
+                                              Handle<TypeFeedbackVector>,
+                                              FeedbackVectorSlot);
   HValue* object() const { return OperandAt(0); }
   HValue* value() const { return OperandAt(1); }
   HValue* context() const { return OperandAt(2); }
   Handle<Name> name() const { return name_; }
   LanguageMode language_mode() const { return language_mode_; }
-  InlineCacheState initialization_state() const {
-    return initialization_state_;
-  }
 
   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
 
@@ -6443,22 +6376,17 @@
   Handle<TypeFeedbackVector> feedback_vector() const {
     return feedback_vector_;
   }
-  bool HasVectorAndSlot() const { return true; }
-  void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
-                        FeedbackVectorSlot slot) {
-    feedback_vector_ = vector;
-    slot_ = slot;
-  }
 
   DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric)
 
  private:
   HStoreNamedGeneric(HValue* context, HValue* object, Handle<Name> name,
                      HValue* value, LanguageMode language_mode,
-                     InlineCacheState initialization_state)
+                     Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
       : name_(name),
-        language_mode_(language_mode),
-        initialization_state_(initialization_state) {
+        feedback_vector_(vector),
+        slot_(slot),
+        language_mode_(language_mode) {
     SetOperandAt(0, object);
     SetOperandAt(1, value);
     SetOperandAt(2, context);
@@ -6469,10 +6397,8 @@
   Handle<TypeFeedbackVector> feedback_vector_;
   FeedbackVectorSlot slot_;
   LanguageMode language_mode_;
-  InlineCacheState initialization_state_;
 };
 
-
 class HStoreKeyed final : public HTemplateInstruction<4>,
                           public ArrayInstructionInterface {
  public:
@@ -6655,21 +6581,18 @@
   HValue* dominator_;
 };
 
-
 class HStoreKeyedGeneric final : public HTemplateInstruction<4> {
  public:
-  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P5(HStoreKeyedGeneric, HValue*,
+  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P6(HStoreKeyedGeneric, HValue*,
                                               HValue*, HValue*, LanguageMode,
-                                              InlineCacheState);
+                                              Handle<TypeFeedbackVector>,
+                                              FeedbackVectorSlot);
 
   HValue* object() const { return OperandAt(0); }
   HValue* key() const { return OperandAt(1); }
   HValue* value() const { return OperandAt(2); }
   HValue* context() const { return OperandAt(3); }
   LanguageMode language_mode() const { return language_mode_; }
-  InlineCacheState initialization_state() const {
-    return initialization_state_;
-  }
 
   Representation RequiredInputRepresentation(int index) override {
     // tagged[tagged] = tagged
@@ -6680,14 +6603,6 @@
   Handle<TypeFeedbackVector> feedback_vector() const {
     return feedback_vector_;
   }
-  bool HasVectorAndSlot() const {
-    return !feedback_vector_.is_null();
-  }
-  void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
-                        FeedbackVectorSlot slot) {
-    feedback_vector_ = vector;
-    slot_ = slot;
-  }
 
   std::ostream& PrintDataTo(std::ostream& os) const override;  // NOLINT
 
@@ -6696,9 +6611,8 @@
  private:
   HStoreKeyedGeneric(HValue* context, HValue* object, HValue* key,
                      HValue* value, LanguageMode language_mode,
-                     InlineCacheState initialization_state)
-      : language_mode_(language_mode),
-        initialization_state_(initialization_state) {
+                     Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
+      : feedback_vector_(vector), slot_(slot), language_mode_(language_mode) {
     SetOperandAt(0, object);
     SetOperandAt(1, key);
     SetOperandAt(2, value);
@@ -6709,10 +6623,8 @@
   Handle<TypeFeedbackVector> feedback_vector_;
   FeedbackVectorSlot slot_;
   LanguageMode language_mode_;
-  InlineCacheState initialization_state_;
 };
 
-
 class HTransitionElementsKind final : public HTemplateInstruction<2> {
  public:
   inline static HTransitionElementsKind* New(Isolate* isolate, Zone* zone,
diff --git a/src/crankshaft/hydrogen-range-analysis.h b/src/crankshaft/hydrogen-range-analysis.h
index cff7026..eeac690 100644
--- a/src/crankshaft/hydrogen-range-analysis.h
+++ b/src/crankshaft/hydrogen-range-analysis.h
@@ -5,6 +5,7 @@
 #ifndef V8_CRANKSHAFT_HYDROGEN_RANGE_ANALYSIS_H_
 #define V8_CRANKSHAFT_HYDROGEN_RANGE_ANALYSIS_H_
 
+#include "src/base/compiler-specific.h"
 #include "src/crankshaft/hydrogen.h"
 
 namespace v8 {
@@ -21,7 +22,7 @@
   void Run();
 
  private:
-  void TraceRange(const char* msg, ...);
+  PRINTF_FORMAT(2, 3) void TraceRange(const char* msg, ...);
   void InferControlFlowRange(HCompareNumericAndBranch* test,
                              HBasicBlock* dest);
   void UpdateControlFlowRange(Token::Value op, HValue* value, HValue* other);
diff --git a/src/crankshaft/hydrogen-types.cc b/src/crankshaft/hydrogen-types.cc
index 4266e28..20d50d8 100644
--- a/src/crankshaft/hydrogen-types.cc
+++ b/src/crankshaft/hydrogen-types.cc
@@ -34,23 +34,25 @@
 
 // static
 HType HType::FromValue(Handle<Object> value) {
-  if (value->IsSmi()) return HType::Smi();
-  if (value->IsNull()) return HType::Null();
-  if (value->IsHeapNumber()) {
+  Object* raw_value = *value;
+  if (raw_value->IsSmi()) return HType::Smi();
+  DCHECK(raw_value->IsHeapObject());
+  Isolate* isolate = HeapObject::cast(*value)->GetIsolate();
+  if (raw_value->IsNull(isolate)) return HType::Null();
+  if (raw_value->IsHeapNumber()) {
     double n = Handle<v8::internal::HeapNumber>::cast(value)->value();
     return IsSmiDouble(n) ? HType::Smi() : HType::HeapNumber();
   }
-  if (value->IsString()) return HType::String();
-  if (value->IsBoolean()) return HType::Boolean();
-  if (value->IsUndefined()) return HType::Undefined();
-  if (value->IsJSArray()) {
-    DCHECK(!value->IsUndetectable());
+  if (raw_value->IsString()) return HType::String();
+  if (raw_value->IsBoolean()) return HType::Boolean();
+  if (raw_value->IsUndefined(isolate)) return HType::Undefined();
+  if (raw_value->IsJSArray()) {
+    DCHECK(!raw_value->IsUndetectable());
     return HType::JSArray();
   }
-  if (value->IsJSObject() && !value->IsUndetectable()) {
+  if (raw_value->IsJSObject() && !raw_value->IsUndetectable()) {
     return HType::JSObject();
   }
-  DCHECK(value->IsHeapObject());
   return HType::HeapObject();
 }
 
diff --git a/src/crankshaft/hydrogen.cc b/src/crankshaft/hydrogen.cc
index 0de6dac..1a6f863 100644
--- a/src/crankshaft/hydrogen.cc
+++ b/src/crankshaft/hydrogen.cc
@@ -68,6 +68,179 @@
 namespace v8 {
 namespace internal {
 
+const auto GetRegConfig = RegisterConfiguration::Crankshaft;
+
+class HOptimizedGraphBuilderWithPositions : public HOptimizedGraphBuilder {
+ public:
+  explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info)
+      : HOptimizedGraphBuilder(info) {}
+
+#define DEF_VISIT(type)                                      \
+  void Visit##type(type* node) override {                    \
+    SourcePosition old_position = SourcePosition::Unknown(); \
+    if (node->position() != RelocInfo::kNoPosition) {        \
+      old_position = source_position();                      \
+      SetSourcePosition(node->position());                   \
+    }                                                        \
+    HOptimizedGraphBuilder::Visit##type(node);               \
+    if (!old_position.IsUnknown()) {                         \
+      set_source_position(old_position);                     \
+    }                                                        \
+  }
+  EXPRESSION_NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+
+#define DEF_VISIT(type)                                      \
+  void Visit##type(type* node) override {                    \
+    SourcePosition old_position = SourcePosition::Unknown(); \
+    if (node->position() != RelocInfo::kNoPosition) {        \
+      old_position = source_position();                      \
+      SetSourcePosition(node->position());                   \
+    }                                                        \
+    HOptimizedGraphBuilder::Visit##type(node);               \
+    if (!old_position.IsUnknown()) {                         \
+      set_source_position(old_position);                     \
+    }                                                        \
+  }
+  STATEMENT_NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+
+#define DEF_VISIT(type)                        \
+  void Visit##type(type* node) override {      \
+    HOptimizedGraphBuilder::Visit##type(node); \
+  }
+  DECLARATION_NODE_LIST(DEF_VISIT)
+#undef DEF_VISIT
+};
+
+HCompilationJob::Status HCompilationJob::CreateGraphImpl() {
+  bool dont_crankshaft = info()->shared_info()->dont_crankshaft();
+
+  // Optimization requires a version of fullcode with deoptimization support.
+  // Recompile the unoptimized version of the code if the current version
+  // doesn't have deoptimization support already.
+  // Otherwise, if we are gathering compilation time and space statistics
+  // for hydrogen, gather baseline statistics for a fullcode compilation.
+  bool should_recompile = !info()->shared_info()->has_deoptimization_support();
+  if (should_recompile || FLAG_hydrogen_stats) {
+    base::ElapsedTimer timer;
+    if (FLAG_hydrogen_stats) {
+      timer.Start();
+    }
+    if (!Compiler::EnsureDeoptimizationSupport(info())) {
+      return FAILED;
+    }
+    if (FLAG_hydrogen_stats) {
+      isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed());
+    }
+  }
+  DCHECK(info()->shared_info()->has_deoptimization_support());
+  DCHECK(!info()->shared_info()->never_compiled());
+
+  if (!isolate()->use_crankshaft() || dont_crankshaft) {
+    // Crankshaft is entirely disabled.
+    return FAILED;
+  }
+
+  // Check the whitelist for Crankshaft.
+  if (!info()->shared_info()->PassesFilter(FLAG_hydrogen_filter)) {
+    return AbortOptimization(kHydrogenFilter);
+  }
+
+  Scope* scope = info()->scope();
+  if (LUnallocated::TooManyParameters(scope->num_parameters())) {
+    // Crankshaft would require too many Lithium operands.
+    return AbortOptimization(kTooManyParameters);
+  }
+
+  if (info()->is_osr() &&
+      LUnallocated::TooManyParametersOrStackSlots(scope->num_parameters(),
+                                                  scope->num_stack_slots())) {
+    // Crankshaft would require too many Lithium operands.
+    return AbortOptimization(kTooManyParametersLocals);
+  }
+
+  if (IsGeneratorFunction(info()->shared_info()->kind())) {
+    // Crankshaft does not support generators.
+    return AbortOptimization(kGenerator);
+  }
+
+  if (FLAG_trace_hydrogen) {
+    isolate()->GetHTracer()->TraceCompilation(info());
+  }
+
+  // Optimization could have been disabled by the parser. Note that this check
+  // is only needed because the Hydrogen graph builder is missing some bailouts.
+  if (info()->shared_info()->optimization_disabled()) {
+    return AbortOptimization(
+        info()->shared_info()->disable_optimization_reason());
+  }
+
+  HOptimizedGraphBuilder* graph_builder =
+      (info()->is_tracking_positions() || FLAG_trace_ic)
+          ? new (info()->zone()) HOptimizedGraphBuilderWithPositions(info())
+          : new (info()->zone()) HOptimizedGraphBuilder(info());
+
+  // Type-check the function.
+  AstTyper(info()->isolate(), info()->zone(), info()->closure(),
+           info()->scope(), info()->osr_ast_id(), info()->literal(),
+           graph_builder->bounds())
+      .Run();
+
+  graph_ = graph_builder->CreateGraph();
+
+  if (isolate()->has_pending_exception()) {
+    return FAILED;
+  }
+
+  if (graph_ == NULL) return FAILED;
+
+  if (info()->dependencies()->HasAborted()) {
+    // Dependency has changed during graph creation. Let's try again later.
+    return RetryOptimization(kBailedOutDueToDependencyChange);
+  }
+
+  return SUCCEEDED;
+}
+
+HCompilationJob::Status HCompilationJob::OptimizeGraphImpl() {
+  DCHECK(graph_ != NULL);
+  BailoutReason bailout_reason = kNoReason;
+
+  if (graph_->Optimize(&bailout_reason)) {
+    chunk_ = LChunk::NewChunk(graph_);
+    if (chunk_ != NULL) return SUCCEEDED;
+  } else if (bailout_reason != kNoReason) {
+    info()->AbortOptimization(bailout_reason);
+  }
+
+  return FAILED;
+}
+
+HCompilationJob::Status HCompilationJob::GenerateCodeImpl() {
+  DCHECK(chunk_ != NULL);
+  DCHECK(graph_ != NULL);
+  {
+    // Deferred handles reference objects that were accessible during
+    // graph creation.  To make sure that we don't encounter inconsistencies
+    // between graph creation and code generation, we disallow accessing
+    // objects through deferred handles during the latter, with exceptions.
+    DisallowDeferredHandleDereference no_deferred_handle_deref;
+    Handle<Code> optimized_code = chunk_->Codegen();
+    if (optimized_code.is_null()) {
+      if (info()->bailout_reason() == kNoReason) {
+        return AbortOptimization(kCodeGenerationFailed);
+      }
+      return FAILED;
+    }
+    RegisterWeakObjectsInOptimizedCode(optimized_code);
+    info()->SetCode(optimized_code);
+  }
+  // Add to the weak list of optimized code objects.
+  info()->context()->native_context()->AddOptimizedCode(*info()->code());
+  return SUCCEEDED;
+}
+
 HBasicBlock::HBasicBlock(HGraph* graph)
     : block_id_(graph->GetNextBlockID()),
       graph_(graph),
@@ -1188,6 +1361,9 @@
 HGraph* HGraphBuilder::CreateGraph() {
   graph_ = new (zone()) HGraph(info_, descriptor_);
   if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
+  if (!info_->IsStub() && info_->is_tracking_positions()) {
+    TraceInlinedFunction(info_->shared_info(), SourcePosition::Unknown());
+  }
   CompilationPhase phase("H_Block building", info_);
   set_current_block(graph()->entry_block());
   if (!BuildGraph()) return NULL;
@@ -1195,6 +1371,53 @@
   return graph_;
 }
 
+int HGraphBuilder::TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
+                                        SourcePosition position) {
+  DCHECK(info_->is_tracking_positions());
+
+  int inline_id = static_cast<int>(graph()->inlined_function_infos().size());
+  HInlinedFunctionInfo info(shared->start_position());
+  if (!shared->script()->IsUndefined(isolate())) {
+    Handle<Script> script(Script::cast(shared->script()), isolate());
+
+    if (FLAG_hydrogen_track_positions &&
+        !script->source()->IsUndefined(isolate())) {
+      CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
+      Object* source_name = script->name();
+      OFStream os(tracing_scope.file());
+      os << "--- FUNCTION SOURCE (";
+      if (source_name->IsString()) {
+        os << String::cast(source_name)->ToCString().get() << ":";
+      }
+      os << shared->DebugName()->ToCString().get() << ") id{";
+      os << info_->optimization_id() << "," << inline_id << "} ---\n";
+      {
+        DisallowHeapAllocation no_allocation;
+        int start = shared->start_position();
+        int len = shared->end_position() - start;
+        String::SubStringRange source(String::cast(script->source()), start,
+                                      len);
+        for (const auto& c : source) {
+          os << AsReversiblyEscapedUC16(c);
+        }
+      }
+
+      os << "\n--- END ---\n";
+    }
+  }
+
+  graph()->inlined_function_infos().push_back(info);
+
+  if (FLAG_hydrogen_track_positions && inline_id != 0) {
+    CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
+    OFStream os(tracing_scope.file());
+    os << "INLINE (" << shared->DebugName()->ToCString().get() << ") id{"
+       << info_->optimization_id() << "," << inline_id << "} AS " << inline_id
+       << " AT " << position << std::endl;
+  }
+
+  return inline_id;
+}
 
 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
   DCHECK(current_block() != NULL);
@@ -1822,7 +2045,7 @@
   // Allocate the JSIteratorResult object.
   HValue* result =
       Add<HAllocate>(Add<HConstant>(JSIteratorResult::kSize), HType::JSObject(),
-                     NOT_TENURED, JS_OBJECT_TYPE);
+                     NOT_TENURED, JS_OBJECT_TYPE, graph()->GetConstant0());
 
   // Initialize the JSIteratorResult object.
   HValue* native_context = BuildGetNativeContext();
@@ -1859,9 +2082,9 @@
   HValue* size = BuildCalculateElementsSize(elements_kind, length);
 
   // Allocate the JSRegExpResult and the FixedArray in one step.
-  HValue* result = Add<HAllocate>(
-      Add<HConstant>(JSRegExpResult::kSize), HType::JSArray(),
-      NOT_TENURED, JS_ARRAY_TYPE);
+  HValue* result =
+      Add<HAllocate>(Add<HConstant>(JSRegExpResult::kSize), HType::JSArray(),
+                     NOT_TENURED, JS_ARRAY_TYPE, graph()->GetConstant0());
 
   // Initialize the JSRegExpResult header.
   HValue* native_context = Add<HLoadNamedField>(
@@ -1895,12 +2118,6 @@
   HAllocate* elements = BuildAllocateElements(elements_kind, size);
   BuildInitializeElementsHeader(elements, elements_kind, length);
 
-  if (!elements->has_size_upper_bound()) {
-    HConstant* size_in_bytes_upper_bound = EstablishElementsAllocationSize(
-        elements_kind, max_length->Integer32Value());
-    elements->set_size_upper_bound(size_in_bytes_upper_bound);
-  }
-
   Add<HStoreNamedField>(
       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
       elements);
@@ -2062,9 +2279,8 @@
   Callable callable = CodeFactory::ToNumber(isolate());
   HValue* stub = Add<HConstant>(callable.code());
   HValue* values[] = {context(), input};
-  HCallWithDescriptor* instr =
-      Add<HCallWithDescriptor>(stub, 0, callable.descriptor(),
-                               Vector<HValue*>(values, arraysize(values)));
+  HCallWithDescriptor* instr = Add<HCallWithDescriptor>(
+      stub, 0, callable.descriptor(), ArrayVector(values));
   instr->set_type(HType::TaggedNumber());
   return instr;
 }
@@ -2177,8 +2393,8 @@
 
   // Perform the actual allocation.
   HAllocate* object = Add<HAllocate>(
-      size, type, allocation_mode.GetPretenureMode(),
-      instance_type, allocation_mode.feedback_site());
+      size, type, allocation_mode.GetPretenureMode(), instance_type,
+      graph()->GetConstant0(), allocation_mode.feedback_site());
 
   // Setup the allocation memento.
   if (allocation_mode.CreateAllocationMementos()) {
@@ -2673,7 +2889,6 @@
       return array_builder->AllocateEmptyArray();
     } else {
       return array_builder->AllocateArray(length_argument,
-                                          array_length,
                                           length_argument);
     }
   }
@@ -2706,7 +2921,7 @@
   // Figure out total size
   HValue* length = Pop();
   HValue* capacity = Pop();
-  return array_builder->AllocateArray(capacity, max_alloc_length, length);
+  return array_builder->AllocateArray(capacity, length);
 }
 
 
@@ -2738,8 +2953,8 @@
     base_size += AllocationMemento::kSize;
   }
   HConstant* size_in_bytes = Add<HConstant>(base_size);
-  return Add<HAllocate>(
-      size_in_bytes, HType::JSArray(), NOT_TENURED, JS_OBJECT_TYPE);
+  return Add<HAllocate>(size_in_bytes, HType::JSArray(), NOT_TENURED,
+                        JS_OBJECT_TYPE, graph()->GetConstant0());
 }
 
 
@@ -2761,7 +2976,7 @@
       : FIXED_ARRAY_TYPE;
 
   return Add<HAllocate>(size_in_bytes, HType::HeapObject(), NOT_TENURED,
-                        instance_type);
+                        instance_type, graph()->GetConstant0());
 }
 
 
@@ -3149,14 +3364,6 @@
 
   HAllocate* elements = BuildAllocateElements(kind, elements_size);
 
-  // This function implicitly relies on the fact that the
-  // FastCloneShallowArrayStub is called only for literals shorter than
-  // JSArray::kInitialMaxFastElementArray.
-  // Can't add HBoundsCheck here because otherwise the stub will eager a frame.
-  HConstant* size_upper_bound = EstablishElementsAllocationSize(
-      kind, JSArray::kInitialMaxFastElementArray);
-  elements->set_size_upper_bound(size_upper_bound);
-
   Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(), elements);
 
   // The allocation for the cloned array above causes register pressure on
@@ -3396,42 +3603,12 @@
 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() {
   HConstant* capacity = builder()->Add<HConstant>(initial_capacity());
   return AllocateArray(capacity,
-                       capacity,
                        builder()->graph()->GetConstant0());
 }
 
 
 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
     HValue* capacity,
-    HConstant* capacity_upper_bound,
-    HValue* length_field,
-    FillMode fill_mode) {
-  return AllocateArray(capacity,
-                       capacity_upper_bound->GetInteger32Constant(),
-                       length_field,
-                       fill_mode);
-}
-
-
-HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
-    HValue* capacity,
-    int capacity_upper_bound,
-    HValue* length_field,
-    FillMode fill_mode) {
-  HConstant* elememts_size_upper_bound = capacity->IsInteger32Constant()
-      ? HConstant::cast(capacity)
-      : builder()->EstablishElementsAllocationSize(kind_, capacity_upper_bound);
-
-  HAllocate* array = AllocateArray(capacity, length_field, fill_mode);
-  if (!elements_location_->has_size_upper_bound()) {
-    elements_location_->set_size_upper_bound(elememts_size_upper_bound);
-  }
-  return array;
-}
-
-
-HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
-    HValue* capacity,
     HValue* length_field,
     FillMode fill_mode) {
   // These HForceRepresentations are because we store these as fields in the
@@ -3506,7 +3683,8 @@
       break_scope_(NULL),
       inlined_count_(0),
       globals_(10, info->zone()),
-      osr_(new (info->zone()) HOsrBuilder(this)) {
+      osr_(new (info->zone()) HOsrBuilder(this)),
+      bounds_(info->zone()) {
   // This is not initialized in the initializer list because the
   // constructor for the initial state relies on function_state_ == NULL
   // to know it's the initial state.
@@ -3599,7 +3777,6 @@
   return os << "B" << b.block_id();
 }
 
-
 HGraph::HGraph(CompilationInfo* info, CallInterfaceDescriptor descriptor)
     : isolate_(info->isolate()),
       next_block_id_(0),
@@ -3612,21 +3789,19 @@
       info_(info),
       descriptor_(descriptor),
       zone_(info->zone()),
+      allow_code_motion_(false),
       use_optimistic_licm_(false),
       depends_on_empty_array_proto_elements_(false),
       type_change_checksum_(0),
       maximum_environment_size_(0),
       no_side_effects_scope_count_(0),
-      disallow_adding_new_values_(false) {
+      disallow_adding_new_values_(false),
+      inlined_function_infos_(info->zone()) {
   if (info->IsStub()) {
     // For stubs, explicitly add the context to the environment.
     start_environment_ = new (zone_)
         HEnvironment(zone_, descriptor.GetRegisterParameterCount() + 1);
   } else {
-    if (info->is_tracking_positions()) {
-      info->TraceInlinedFunction(info->shared_info(), SourcePosition::Unknown(),
-                                 InlinedFunctionInfo::kNoParentId);
-    }
     start_environment_ =
         new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
   }
@@ -3655,7 +3830,8 @@
 
 int HGraph::SourcePositionToScriptPosition(SourcePosition pos) {
   return (FLAG_hydrogen_track_positions && !pos.IsUnknown())
-             ? info()->start_position_for(pos.inlining_id()) + pos.position()
+             ? inlined_function_infos_.at(pos.inlining_id()).start_position +
+                   pos.position()
              : pos.raw();
 }
 
@@ -4445,6 +4621,11 @@
       !type_info->matches_inlined_type_change_checksum(composite_checksum));
   type_info->set_inlined_type_change_checksum(composite_checksum);
 
+  // Set this predicate early to avoid handle deref during graph optimization.
+  graph()->set_allow_code_motion(
+      current_info()->IsStub() ||
+      current_info()->shared_info()->opt_count() + 1 < FLAG_max_opt_count);
+
   // Perform any necessary OSR-specific cleanups or changes to the graph.
   osr()->FinishGraph();
 
@@ -4991,7 +5172,7 @@
   CHECK_ALIVE(VisitForValue(stmt->tag()));
   Add<HSimulate>(stmt->EntryId());
   HValue* tag_value = Top();
-  Type* tag_type = stmt->tag()->bounds().lower;
+  Type* tag_type = bounds_.get(stmt->tag()).lower;
 
   // 1. Build all the tests, with dangling true branches
   BailoutId default_id = BailoutId::None();
@@ -5008,7 +5189,7 @@
     if (current_block() == NULL) return Bailout(kUnsupportedSwitchStatement);
     HValue* label_value = Pop();
 
-    Type* label_type = clause->label()->bounds().lower;
+    Type* label_type = bounds_.get(clause->label()).lower;
     Type* combined_type = clause->compare_type();
     HControlInstruction* compare = BuildCompareInstruction(
         Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
@@ -5491,17 +5672,17 @@
   // We also have a stack overflow if the recursive compilation did.
   if (HasStackOverflow()) return;
   // Use the fast case closure allocation code that allocates in new
-  // space for nested functions that don't need literals cloning.
+  // space for nested functions that don't need pretenuring.
   HConstant* shared_info_value = Add<HConstant>(shared_info);
   HInstruction* instr;
-  if (!expr->pretenure() && shared_info->num_literals() == 0) {
+  if (!expr->pretenure()) {
     FastNewClosureStub stub(isolate(), shared_info->language_mode(),
                             shared_info->kind());
     FastNewClosureDescriptor descriptor(isolate());
     HValue* values[] = {context(), shared_info_value};
     HConstant* stub_value = Add<HConstant>(stub.GetCode());
-    instr = New<HCallWithDescriptor>(
-        stub_value, 0, descriptor, Vector<HValue*>(values, arraysize(values)));
+    instr = New<HCallWithDescriptor>(stub_value, 0, descriptor,
+                                     ArrayVector(values));
   } else {
     Add<HPushArguments>(shared_info_value);
     Runtime::FunctionId function_id =
@@ -5593,6 +5774,7 @@
       return kUseGeneric;
     case LookupIterator::DATA:
       if (access_type == STORE && it->IsReadOnly()) return kUseGeneric;
+      if (!it->GetHolder<JSObject>()->IsJSGlobalObject()) return kUseGeneric;
       return kUseCell;
     case LookupIterator::JSPROXY:
     case LookupIterator::TRANSITION:
@@ -5653,7 +5835,7 @@
 
           // If the values is not the hole, it will stay initialized,
           // so no need to generate a check.
-          if (*current_value == *isolate()->factory()->the_hole_value()) {
+          if (current_value->IsTheHole(isolate())) {
             return Bailout(kReferenceToUninitializedVariable);
           }
           HInstruction* result = New<HLoadNamedField>(
@@ -5716,13 +5898,10 @@
           return ast_context()->ReturnInstruction(instr, expr->id());
         }
       } else {
-        HValue* global_object = Add<HLoadNamedField>(
-            BuildGetNativeContext(), nullptr,
-            HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX));
+        Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate());
         HLoadGlobalGeneric* instr = New<HLoadGlobalGeneric>(
-            global_object, variable->name(), ast_context()->typeof_mode());
-        instr->SetVectorAndSlot(handle(current_feedback_vector(), isolate()),
-                                expr->VariableFeedbackSlot());
+            variable->name(), ast_context()->typeof_mode(), vector,
+            expr->VariableFeedbackSlot());
         return ast_context()->ReturnInstruction(instr, expr->id());
       }
     }
@@ -5746,9 +5925,6 @@
         case CONST:
           mode = HLoadContextSlot::kCheckDeoptimize;
           break;
-        case CONST_LEGACY:
-          mode = HLoadContextSlot::kCheckReturnUndefined;
-          break;
         default:
           mode = HLoadContextSlot::kNoCheck;
           break;
@@ -5782,9 +5958,8 @@
       context(), AddThisFunction(), Add<HConstant>(expr->literal_index()),
       Add<HConstant>(expr->pattern()), Add<HConstant>(expr->flags())};
   HConstant* stub_value = Add<HConstant>(callable.code());
-  HInstruction* instr =
-      New<HCallWithDescriptor>(stub_value, 0, callable.descriptor(),
-                               Vector<HValue*>(values, arraysize(values)));
+  HInstruction* instr = New<HCallWithDescriptor>(
+      stub_value, 0, callable.descriptor(), ArrayVector(values));
   return ast_context()->ReturnInstruction(instr, expr->id());
 }
 
@@ -5880,7 +6055,7 @@
       closure->literals()->literal(expr->literal_index()), isolate());
   Handle<AllocationSite> site;
   Handle<JSObject> boilerplate;
-  if (!literals_cell->IsUndefined()) {
+  if (!literals_cell->IsUndefined(isolate())) {
     // Retrieve the boilerplate
     site = Handle<AllocationSite>::cast(literals_cell);
     boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
@@ -5995,59 +6170,29 @@
   Handle<AllocationSite> site;
   Handle<LiteralsArray> literals(environment()->closure()->literals(),
                                  isolate());
-  bool uninitialized = false;
   Handle<Object> literals_cell(literals->literal(expr->literal_index()),
                                isolate());
   Handle<JSObject> boilerplate_object;
-  if (literals_cell->IsUndefined()) {
-    uninitialized = true;
-    Handle<Object> raw_boilerplate;
-    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-        isolate(), raw_boilerplate,
-        Runtime::CreateArrayLiteralBoilerplate(isolate(), literals,
-                                               expr->constant_elements()),
-        Bailout(kArrayBoilerplateCreationFailed));
-
-    boilerplate_object = Handle<JSObject>::cast(raw_boilerplate);
-    AllocationSiteCreationContext creation_context(isolate());
-    site = creation_context.EnterNewScope();
-    if (JSObject::DeepWalk(boilerplate_object, &creation_context).is_null()) {
-      return Bailout(kArrayBoilerplateCreationFailed);
-    }
-    creation_context.ExitScope(site, boilerplate_object);
-    literals->set_literal(expr->literal_index(), *site);
-
-    if (boilerplate_object->elements()->map() ==
-        isolate()->heap()->fixed_cow_array_map()) {
-      isolate()->counters()->cow_arrays_created_runtime()->Increment();
-    }
-  } else {
+  if (!literals_cell->IsUndefined(isolate())) {
     DCHECK(literals_cell->IsAllocationSite());
     site = Handle<AllocationSite>::cast(literals_cell);
     boilerplate_object = Handle<JSObject>(
         JSObject::cast(site->transition_info()), isolate());
   }
 
-  DCHECK(!boilerplate_object.is_null());
-  DCHECK(site->SitePointsToLiteral());
-
-  ElementsKind boilerplate_elements_kind =
-      boilerplate_object->GetElementsKind();
-
   // Check whether to use fast or slow deep-copying for boilerplate.
   int max_properties = kMaxFastLiteralProperties;
-  if (IsFastLiteral(boilerplate_object,
-                    kMaxFastLiteralDepth,
+  if (!boilerplate_object.is_null() &&
+      IsFastLiteral(boilerplate_object, kMaxFastLiteralDepth,
                     &max_properties)) {
+    DCHECK(site->SitePointsToLiteral());
     AllocationSiteUsageContext site_context(isolate(), site, false);
     site_context.EnterNewScope();
     literal = BuildFastLiteral(boilerplate_object, &site_context);
     site_context.ExitScope(site, boilerplate_object);
   } else {
     NoObservableSideEffectsScope no_effects(this);
-    // Boilerplate already exists and constant elements are never accessed,
-    // pass an empty fixed array to the runtime function instead.
-    Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
+    Handle<FixedArray> constants = expr->constant_elements();
     int literal_index = expr->literal_index();
     int flags = expr->ComputeFlags(true);
 
@@ -6058,7 +6203,9 @@
     literal = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 4);
 
     // Register to deopt if the boilerplate ElementsKind changes.
-    top_info()->dependencies()->AssumeTransitionStable(site);
+    if (!site.is_null()) {
+      top_info()->dependencies()->AssumeTransitionStable(site);
+    }
   }
 
   // The array is expected in the bailout environment during computation
@@ -6083,21 +6230,28 @@
 
     HValue* key = Add<HConstant>(i);
 
-    switch (boilerplate_elements_kind) {
-      case FAST_SMI_ELEMENTS:
-      case FAST_HOLEY_SMI_ELEMENTS:
-      case FAST_ELEMENTS:
-      case FAST_HOLEY_ELEMENTS:
-      case FAST_DOUBLE_ELEMENTS:
-      case FAST_HOLEY_DOUBLE_ELEMENTS: {
-        HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value, nullptr,
-                                              boilerplate_elements_kind);
-        instr->SetUninitialized(uninitialized);
-        break;
+    if (!boilerplate_object.is_null()) {
+      ElementsKind boilerplate_elements_kind =
+          boilerplate_object->GetElementsKind();
+      switch (boilerplate_elements_kind) {
+        case FAST_SMI_ELEMENTS:
+        case FAST_HOLEY_SMI_ELEMENTS:
+        case FAST_ELEMENTS:
+        case FAST_HOLEY_ELEMENTS:
+        case FAST_DOUBLE_ELEMENTS:
+        case FAST_HOLEY_DOUBLE_ELEMENTS: {
+          Add<HStoreKeyed>(elements, key, value, nullptr,
+                           boilerplate_elements_kind);
+          break;
+        }
+        default:
+          UNREACHABLE();
+          break;
       }
-      default:
-        UNREACHABLE();
-        break;
+    } else {
+      HInstruction* instr = BuildKeyedGeneric(
+          STORE, expr, expr->LiteralFeedbackSlot(), literal, key, value);
+      AddInstruction(instr);
     }
 
     Add<HSimulate>(expr->GetIdForElement(i));
@@ -6176,10 +6330,9 @@
       HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
 
       // TODO(hpayer): Allocation site pretenuring support.
-      HInstruction* heap_number = Add<HAllocate>(heap_number_size,
-          HType::HeapObject(),
-          NOT_TENURED,
-          MUTABLE_HEAP_NUMBER_TYPE);
+      HInstruction* heap_number =
+          Add<HAllocate>(heap_number_size, HType::HeapObject(), NOT_TENURED,
+                         MUTABLE_HEAP_NUMBER_TYPE, graph()->GetConstant0());
       AddStoreMapConstant(
           heap_number, isolate()->factory()->mutable_heap_number_map());
       Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
@@ -6409,7 +6562,6 @@
 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
   if (!CanInlinePropertyAccess(map_)) return false;
   if (IsJSObjectFieldAccessor()) return IsLoad();
-  if (IsJSArrayBufferViewFieldAccessor()) return IsLoad();
   if (map_->IsJSFunctionMap() && map_->is_constructor() &&
       !map_->has_non_instance_prototype() &&
       name_.is_identical_to(isolate()->factory()->prototype_string())) {
@@ -6457,17 +6609,6 @@
     }
     return true;
   }
-  if (GetJSArrayBufferViewFieldAccess(&access)) {
-    for (int i = 1; i < maps->length(); ++i) {
-      PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
-      HObjectAccess test_access = HObjectAccess::ForMap();  // bogus default
-      if (!test_info.GetJSArrayBufferViewFieldAccess(&test_access)) {
-        return false;
-      }
-      if (!access.Equals(test_access)) return false;
-    }
-    return true;
-  }
 
   // Currently only handle numbers as a polymorphic case.
   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
@@ -6521,12 +6662,6 @@
     return New<HLoadNamedField>(object, checked_object, access);
   }
 
-  if (info->GetJSArrayBufferViewFieldAccess(&access)) {
-    DCHECK(info->IsLoad());
-    checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object);
-    return New<HLoadNamedField>(object, checked_object, access);
-  }
-
   if (info->name().is_identical_to(isolate()->factory()->prototype_string()) &&
       info->map()->IsJSFunctionMap() && info->map()->is_constructor()) {
     DCHECK(!info->map()->has_non_instance_prototype());
@@ -6761,7 +6896,6 @@
       // possible if the receiver had a known map at some point, and no
       // map-changing stores have happened to it since.
       Handle<Map> candidate_map = receiver->GetMonomorphicJSObjectMap();
-      if (candidate_map->is_observed()) return false;
       for (HInstruction* current = builder->current_block()->last();
            current != nullptr; current = current->previous()) {
         if (current->IsBlockEntry()) break;
@@ -6880,7 +7014,7 @@
 
       // If the values is not the hole, it will stay initialized,
       // so no need to generate a check.
-      if (*current_value == *isolate()->factory()->the_hole_value()) {
+      if (current_value->IsTheHole(isolate())) {
         return Bailout(kReferenceToUninitializedVariable);
       }
 
@@ -6952,12 +7086,11 @@
     HValue* global_object = Add<HLoadNamedField>(
         BuildGetNativeContext(), nullptr,
         HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX));
-    HStoreNamedGeneric* instr =
-        Add<HStoreNamedGeneric>(global_object, var->name(), value,
-                                function_language_mode(), PREMONOMORPHIC);
     Handle<TypeFeedbackVector> vector =
         handle(current_feedback_vector(), isolate());
-    instr->SetVectorAndSlot(vector, slot);
+    HStoreNamedGeneric* instr =
+        Add<HStoreNamedGeneric>(global_object, var->name(), value,
+                                function_language_mode(), vector, slot);
     USE(instr);
     DCHECK(instr->HasObservableSideEffects());
     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
@@ -7026,7 +7159,11 @@
           case CONST:
             return Bailout(kNonInitializerAssignmentToConst);
           case CONST_LEGACY:
-            return ast_context()->ReturnValue(Pop());
+            if (is_strict(function_language_mode())) {
+              return Bailout(kNonInitializerAssignmentToConst);
+            } else {
+              return ast_context()->ReturnValue(Pop());
+            }
           default:
             mode = HStoreContextSlot::kNoCheck;
         }
@@ -7095,10 +7232,16 @@
       }
     } else if (var->mode() == CONST_LEGACY) {
       if (expr->op() != Token::INIT) {
-        CHECK_ALIVE(VisitForValue(expr->value()));
-        return ast_context()->ReturnValue(Pop());
+        if (is_strict(function_language_mode())) {
+          return Bailout(kNonInitializerAssignmentToConst);
+        } else {
+          CHECK_ALIVE(VisitForValue(expr->value()));
+          return ast_context()->ReturnValue(Pop());
+        }
       }
 
+      // TODO(adamk): Is this required? Legacy const variables are always
+      // initialized before use.
       if (var->IsStackAllocated()) {
         // We insert a use of the old value to detect unsupported uses of const
         // variables (e.g. initialization inside a loop).
@@ -7170,11 +7313,7 @@
           }
         } else {
           DCHECK_EQ(Token::INIT, expr->op());
-          if (var->mode() == CONST_LEGACY) {
-            mode = HStoreContextSlot::kCheckIgnoreAssignment;
-          } else {
-            mode = HStoreContextSlot::kNoCheck;
-          }
+          mode = HStoreContextSlot::kNoCheck;
         }
 
         HValue* context = BuildContextChainWalk(var);
@@ -7277,16 +7416,17 @@
       // it has to share information with full code.
       HConstant* key = Add<HConstant>(name);
       HLoadKeyedGeneric* result =
-          New<HLoadKeyedGeneric>(object, key, PREMONOMORPHIC);
-      result->SetVectorAndSlot(vector, slot);
+          New<HLoadKeyedGeneric>(object, key, vector, slot);
       return result;
     }
 
     HLoadNamedGeneric* result =
-        New<HLoadNamedGeneric>(object, name, PREMONOMORPHIC);
-    result->SetVectorAndSlot(vector, slot);
+        New<HLoadNamedGeneric>(object, name, vector, slot);
     return result;
   } else {
+    Handle<TypeFeedbackVector> vector =
+        handle(current_feedback_vector(), isolate());
+
     if (current_feedback_vector()->GetKind(slot) ==
         FeedbackVectorSlotKind::KEYED_STORE_IC) {
       // It's possible that a keyed store of a constant string was converted
@@ -7295,18 +7435,12 @@
       // it has to share information with full code.
       HConstant* key = Add<HConstant>(name);
       HStoreKeyedGeneric* result = New<HStoreKeyedGeneric>(
-          object, key, value, function_language_mode(), PREMONOMORPHIC);
-      Handle<TypeFeedbackVector> vector =
-          handle(current_feedback_vector(), isolate());
-      result->SetVectorAndSlot(vector, slot);
+          object, key, value, function_language_mode(), vector, slot);
       return result;
     }
 
     HStoreNamedGeneric* result = New<HStoreNamedGeneric>(
-        object, name, value, function_language_mode(), PREMONOMORPHIC);
-    Handle<TypeFeedbackVector> vector =
-        handle(current_feedback_vector(), isolate());
-    result->SetVectorAndSlot(vector, slot);
+        object, name, value, function_language_mode(), vector, slot);
     return result;
   }
 }
@@ -7315,25 +7449,15 @@
 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
     PropertyAccessType access_type, Expression* expr, FeedbackVectorSlot slot,
     HValue* object, HValue* key, HValue* value) {
+  Handle<TypeFeedbackVector> vector =
+      handle(current_feedback_vector(), isolate());
   if (access_type == LOAD) {
-    InlineCacheState initial_state = expr->AsProperty()->GetInlineCacheState();
     HLoadKeyedGeneric* result =
-        New<HLoadKeyedGeneric>(object, key, initial_state);
-    // HLoadKeyedGeneric with vector ics benefits from being encoded as
-    // MEGAMORPHIC because the vector/slot combo becomes unnecessary.
-    if (initial_state != MEGAMORPHIC) {
-      // We need to pass vector information.
-      Handle<TypeFeedbackVector> vector =
-          handle(current_feedback_vector(), isolate());
-      result->SetVectorAndSlot(vector, slot);
-    }
+        New<HLoadKeyedGeneric>(object, key, vector, slot);
     return result;
   } else {
     HStoreKeyedGeneric* result = New<HStoreKeyedGeneric>(
-        object, key, value, function_language_mode(), PREMONOMORPHIC);
-    Handle<TypeFeedbackVector> vector =
-        handle(current_feedback_vector(), isolate());
-    result->SetVectorAndSlot(vector, slot);
+        object, key, value, function_language_mode(), vector, slot);
     return result;
   }
 }
@@ -7546,9 +7670,13 @@
   // Get transition target for each map (NULL == no transition).
   for (int i = 0; i < maps->length(); ++i) {
     Handle<Map> map = maps->at(i);
-    Handle<Map> transitioned_map =
-        Map::FindTransitionedMap(map, &possible_transitioned_maps);
-    transition_target.Add(transitioned_map);
+    Map* transitioned_map =
+        map->FindElementsKindTransitionedMap(&possible_transitioned_maps);
+    if (transitioned_map != nullptr) {
+      transition_target.Add(handle(transitioned_map));
+    } else {
+      transition_target.Add(Handle<Map>());
+    }
   }
 
   MapHandleList untransitionable_maps(maps->length());
@@ -7810,6 +7938,11 @@
       return false;
     }
 
+    // Make sure we visit the arguments object so that the liveness analysis
+    // still records the access.
+    CHECK_ALIVE_OR_RETURN(VisitForValue(expr->obj(), ARGUMENTS_ALLOWED), true);
+    Drop(1);
+
     if (function_state()->outer() == NULL) {
       HInstruction* elements = Add<HArgumentsElements>(false);
       result = New<HArgumentsLength>(elements);
@@ -7963,8 +8096,7 @@
 
 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
                                                      Handle<JSObject> holder) {
-  PrototypeIterator iter(isolate(), prototype,
-                         PrototypeIterator::START_AT_RECEIVER);
+  PrototypeIterator iter(isolate(), prototype, kStartAtReceiver);
   while (holder.is_null() ||
          !PrototypeIterator::GetCurrent(iter).is_identical_to(holder)) {
     BuildConstantMapCheck(PrototypeIterator::GetCurrent<JSObject>(iter));
@@ -8025,7 +8157,7 @@
   HConstant* stub = Add<HConstant>(callable.code());
 
   return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(),
-                                  Vector<HValue*>(op_vals, arraysize(op_vals)),
+                                  ArrayVector(op_vals),
                                   syntactic_tail_call_mode);
 }
 
@@ -8050,7 +8182,7 @@
   HConstant* stub = Add<HConstant>(callable.code());
 
   return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(),
-                                  Vector<HValue*>(op_vals, arraysize(op_vals)),
+                                  ArrayVector(op_vals),
                                   syntactic_tail_call_mode);
 }
 
@@ -8402,7 +8534,7 @@
       top_info()->parse_info()->ast_value_factory());
   parse_info.set_ast_value_factory_owned(false);
 
-  CompilationInfo target_info(&parse_info);
+  CompilationInfo target_info(&parse_info, target);
   Handle<SharedFunctionInfo> target_shared(target->shared());
 
   if (inlining_kind != CONSTRUCT_CALL_RETURN &&
@@ -8424,6 +8556,10 @@
     TraceInline(target, caller, "parse failure");
     return false;
   }
+  if (target_shared->dont_crankshaft()) {
+    TraceInline(target, caller, "ParseAndAnalyze found incompatibility");
+    return false;
+  }
 
   if (target_info.scope()->num_heap_slots() > 0) {
     TraceInline(target, caller, "target has context-allocated variables");
@@ -8484,6 +8620,7 @@
     TraceInline(target, caller, "could not generate deoptimization info");
     return false;
   }
+
   // Remember that we inlined this function. This needs to be called right
   // after the EnsureDeoptimizationSupport call so that the code flusher
   // does not remove the code with the deoptimization support.
@@ -8493,16 +8630,19 @@
   // After this point, we've made a decision to inline this function (so
   // TryInline should always return true).
 
+  // If target was lazily compiled, it's literals array may not yet be set up.
+  JSFunction::EnsureLiterals(target);
+
   // Type-check the inlined function.
   DCHECK(target_shared->has_deoptimization_support());
   AstTyper(target_info.isolate(), target_info.zone(), target_info.closure(),
-           target_info.scope(), target_info.osr_ast_id(), target_info.literal())
+           target_info.scope(), target_info.osr_ast_id(), target_info.literal(),
+           &bounds_)
       .Run();
 
   int inlining_id = 0;
   if (top_info()->is_tracking_positions()) {
-    inlining_id = top_info()->TraceInlinedFunction(
-        target_shared, source_position(), function_state()->inlining_id());
+    inlining_id = TraceInlinedFunction(target_shared, source_position());
   }
 
   // Save the pending call context. Set up new one for the inlined function.
@@ -8678,9 +8818,13 @@
                                              BailoutId ast_id,
                                              BailoutId return_id) {
   if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
-  return getter->IsJSFunction() &&
-         TryInline(Handle<JSFunction>::cast(getter), 0, NULL, ast_id, return_id,
-                   GETTER_CALL_RETURN, TailCallMode::kDisallow);
+  if (getter->IsJSFunction()) {
+    Handle<JSFunction> getter_function = Handle<JSFunction>::cast(getter);
+    return TryInlineBuiltinGetterCall(getter_function, receiver_map, ast_id) ||
+           TryInline(getter_function, 0, NULL, ast_id, return_id,
+                     GETTER_CALL_RETURN, TailCallMode::kDisallow);
+  }
+  return false;
 }
 
 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<Object> setter,
@@ -8710,13 +8854,13 @@
   // We intentionally ignore expr->tail_call_mode() here because builtins
   // we inline here do not observe if they were tail called or not.
   switch (id) {
+    case kMathCos:
     case kMathExp:
-      if (!FLAG_fast_math) break;
-      // Fall through if FLAG_fast_math.
     case kMathRound:
     case kMathFround:
     case kMathFloor:
     case kMathAbs:
+    case kMathSin:
     case kMathSqrt:
     case kMathLog:
     case kMathClz32:
@@ -8767,15 +8911,67 @@
   return !receiver_map.is_null() && receiver_map->prototype()->IsJSObject() &&
          receiver_map->instance_type() == JS_ARRAY_TYPE &&
          IsFastElementsKind(receiver_map->elements_kind()) &&
-         !receiver_map->is_dictionary_map() && !receiver_map->is_observed() &&
-         receiver_map->is_extensible() &&
+         !receiver_map->is_dictionary_map() && receiver_map->is_extensible() &&
          (!receiver_map->is_prototype_map() || receiver_map->is_stable()) &&
          !IsReadOnlyLengthDescriptor(receiver_map);
 }
 
+bool HOptimizedGraphBuilder::TryInlineBuiltinGetterCall(
+    Handle<JSFunction> function, Handle<Map> receiver_map, BailoutId ast_id) {
+  if (!function->shared()->HasBuiltinFunctionId()) return false;
+  BuiltinFunctionId id = function->shared()->builtin_function_id();
+
+  // Try to inline getter calls like DataView.prototype.byteLength/byteOffset
+  // as operations in the calling function.
+  switch (id) {
+    case kDataViewBuffer: {
+      if (!receiver_map->IsJSDataViewMap()) return false;
+      HObjectAccess access = HObjectAccess::ForMapAndOffset(
+          receiver_map, JSDataView::kBufferOffset);
+      HValue* object = Pop();  // receiver
+      HInstruction* result = New<HLoadNamedField>(object, object, access);
+      ast_context()->ReturnInstruction(result, ast_id);
+      return true;
+    }
+    case kDataViewByteLength:
+    case kDataViewByteOffset: {
+      if (!receiver_map->IsJSDataViewMap()) return false;
+      int offset = (id == kDataViewByteLength) ? JSDataView::kByteLengthOffset
+                                               : JSDataView::kByteOffsetOffset;
+      HObjectAccess access =
+          HObjectAccess::ForMapAndOffset(receiver_map, offset);
+      HValue* object = Pop();  // receiver
+      HValue* checked_object = Add<HCheckArrayBufferNotNeutered>(object);
+      HInstruction* result =
+          New<HLoadNamedField>(object, checked_object, access);
+      ast_context()->ReturnInstruction(result, ast_id);
+      return true;
+    }
+    case kTypedArrayByteLength:
+    case kTypedArrayByteOffset:
+    case kTypedArrayLength: {
+      if (!receiver_map->IsJSTypedArrayMap()) return false;
+      int offset = (id == kTypedArrayLength)
+                       ? JSTypedArray::kLengthOffset
+                       : (id == kTypedArrayByteLength)
+                             ? JSTypedArray::kByteLengthOffset
+                             : JSTypedArray::kByteOffsetOffset;
+      HObjectAccess access =
+          HObjectAccess::ForMapAndOffset(receiver_map, offset);
+      HValue* object = Pop();  // receiver
+      HValue* checked_object = Add<HCheckArrayBufferNotNeutered>(object);
+      HInstruction* result =
+          New<HLoadNamedField>(object, checked_object, access);
+      ast_context()->ReturnInstruction(result, ast_id);
+      return true;
+    }
+    default:
+      return false;
+  }
+}
 
 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
-    Call* expr, Handle<JSFunction> function, Handle<Map> receiver_map,
+    Handle<JSFunction> function, Handle<Map> receiver_map, BailoutId ast_id,
     int args_count_no_receiver) {
   if (!function->shared()->HasBuiltinFunctionId()) return false;
   BuiltinFunctionId id = function->shared()->builtin_function_id();
@@ -8820,12 +9016,12 @@
         HInstruction* char_code =
             BuildStringCharCodeAt(string, index);
         if (id == kStringCharCodeAt) {
-          ast_context()->ReturnInstruction(char_code, expr->id());
+          ast_context()->ReturnInstruction(char_code, ast_id);
           return true;
         }
         AddInstruction(char_code);
         HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
-        ast_context()->ReturnInstruction(result, expr->id());
+        ast_context()->ReturnInstruction(result, ast_id);
         return true;
       }
       break;
@@ -8837,17 +9033,17 @@
             argument, Representation::Integer32());
         argument->SetFlag(HValue::kTruncatingToInt32);
         HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
-        ast_context()->ReturnInstruction(result, expr->id());
+        ast_context()->ReturnInstruction(result, ast_id);
         return true;
       }
       break;
+    case kMathCos:
     case kMathExp:
-      if (!FLAG_fast_math) break;
-      // Fall through if FLAG_fast_math.
     case kMathRound:
     case kMathFround:
     case kMathFloor:
     case kMathAbs:
+    case kMathSin:
     case kMathSqrt:
     case kMathLog:
     case kMathClz32:
@@ -8855,7 +9051,7 @@
         HValue* argument = Pop();
         Drop(2);  // Receiver and function.
         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
-        ast_context()->ReturnInstruction(op, expr->id());
+        ast_context()->ReturnInstruction(op, ast_id);
         return true;
       }
       break;
@@ -8886,7 +9082,7 @@
         if (result == NULL) {
           result = NewUncasted<HPower>(left, right);
         }
-        ast_context()->ReturnInstruction(result, expr->id());
+        ast_context()->ReturnInstruction(result, ast_id);
         return true;
       }
       break;
@@ -8899,7 +9095,7 @@
         HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
                                                      : HMathMinMax::kMathMax;
         HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
-        ast_context()->ReturnInstruction(result, expr->id());
+        ast_context()->ReturnInstruction(result, ast_id);
         return true;
       }
       break;
@@ -8910,7 +9106,7 @@
         Drop(2);  // Receiver and function.
         HInstruction* result =
             HMul::NewImul(isolate(), zone(), context(), left, right);
-        ast_context()->ReturnInstruction(result, expr->id());
+        ast_context()->ReturnInstruction(result, ast_id);
         return true;
       }
       break;
@@ -8966,7 +9162,7 @@
         length_checker.End();
       }
       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
-      Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
+      Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
       if (!ast_context()->IsEffect()) Drop(1);
 
       ast_context()->ReturnValue(result);
@@ -9019,7 +9215,7 @@
             STORE, NEVER_RETURN_HOLE, STORE_AND_GROW_NO_TRANSITION);
 
         if (!ast_context()->IsEffect()) Push(new_size);
-        Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
+        Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
         if (!ast_context()->IsEffect()) Drop(1);
       }
 
@@ -9133,7 +9329,7 @@
         if_lengthiszero.End();
       }
       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
-      Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
+      Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
       if (!ast_context()->IsEffect()) Drop(1);
       ast_context()->ReturnValue(result);
       return true;
@@ -9145,7 +9341,6 @@
       if (!receiver_map->prototype()->IsJSObject()) return false;
       ElementsKind kind = receiver_map->elements_kind();
       if (!IsFastElementsKind(kind)) return false;
-      if (receiver_map->is_observed()) return false;
       if (argument_count != 2) return false;
       if (!receiver_map->is_extensible()) return false;
 
@@ -9171,7 +9366,7 @@
       HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode);
 
       if (!ast_context()->IsEffect()) Push(index);
-      Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
+      Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
       if (!ast_context()->IsEffect()) Drop(1);
       ast_context()->ReturnValue(index);
       return true;
@@ -9322,7 +9517,7 @@
   }
   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
   Handle<Object> call_data_obj(api_call_info->data(), isolate());
-  bool call_data_undefined = call_data_obj->IsUndefined();
+  bool call_data_undefined = call_data_obj->IsUndefined(isolate());
   HValue* call_data = Add<HConstant>(call_data_obj);
   ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
   ExternalReference ref = ExternalReference(&fun,
@@ -9368,7 +9563,7 @@
       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
     known_function =
         Handle<JSFunction>::cast(HConstant::cast(function)->handle(isolate()));
-    if (TryInlineBuiltinMethodCall(expr, known_function, Handle<Map>(),
+    if (TryInlineBuiltinMethodCall(known_function, Handle<Map>(), expr->id(),
                                    args_count_no_receiver)) {
       if (FLAG_trace_inlining) {
         PrintF("Inlining builtin ");
@@ -9769,7 +9964,7 @@
       CHECK_ALIVE(VisitExpressions(expr->arguments()));
 
       Handle<Map> map = maps->length() == 1 ? maps->first() : Handle<Map>();
-      if (TryInlineBuiltinMethodCall(expr, known_function, map,
+      if (TryInlineBuiltinMethodCall(known_function, map, expr->id(),
                                      expr->arguments()->length())) {
         if (FLAG_trace_inlining) {
           PrintF("Inlining builtin ");
@@ -10091,9 +10286,8 @@
   Callable callable = CodeFactory::Construct(isolate());
   HConstant* stub = Add<HConstant>(callable.code());
   PushArgumentsFromEnvironment(argument_count);
-  HInstruction* construct =
-      New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(),
-                               Vector<HValue*>(op_vals, arraysize(op_vals)));
+  HInstruction* construct = New<HCallWithDescriptor>(
+      stub, argument_count, callable.descriptor(), ArrayVector(op_vals));
   return ast_context()->ReturnInstruction(construct, expr->id());
 }
 
@@ -10202,7 +10396,8 @@
   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
   HValue* elements = Add<HAllocate>(
       Add<HConstant>(FixedTypedArrayBase::kHeaderSize), HType::HeapObject(),
-      NOT_TENURED, external_array_map->instance_type());
+      NOT_TENURED, external_array_map->instance_type(),
+      graph()->GetConstant0());
 
   AddStoreMapConstant(elements, external_array_map);
   Add<HStoreNamedField>(elements,
@@ -10258,9 +10453,9 @@
   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
   Handle<Map> fixed_typed_array_map(
       isolate()->heap()->MapForFixedTypedArray(array_type));
-  HAllocate* elements =
-      Add<HAllocate>(total_size, HType::HeapObject(), NOT_TENURED,
-                     fixed_typed_array_map->instance_type());
+  HAllocate* elements = Add<HAllocate>(
+      total_size, HType::HeapObject(), NOT_TENURED,
+      fixed_typed_array_map->instance_type(), graph()->GetConstant0());
 
 #ifndef V8_HOST_ARCH_64_BIT
   if (array_type == kExternalFloat64Array) {
@@ -10972,9 +11167,9 @@
     HValue* left,
     HValue* right,
     PushBeforeSimulateBehavior push_sim_result) {
-  Type* left_type = expr->left()->bounds().lower;
-  Type* right_type = expr->right()->bounds().lower;
-  Type* result_type = expr->bounds().lower;
+  Type* left_type = bounds_.get(expr->left()).lower;
+  Type* right_type = bounds_.get(expr->right()).lower;
+  Type* result_type = bounds_.get(expr).lower;
   Maybe<int> fixed_right_arg = expr->fixed_right_arg();
   Handle<AllocationSite> allocation_site = expr->allocation_site();
 
@@ -11159,46 +11354,53 @@
   // inline several instructions (including the two pushes) for every tagged
   // operation in optimized code, which is more expensive, than a stub call.
   if (graph()->info()->IsStub() && is_non_primitive) {
-    Runtime::FunctionId function_id;
+    HValue* values[] = {context(), left, right};
+#define GET_STUB(Name)                                                       \
+  do {                                                                       \
+    Callable callable = CodeFactory::Name(isolate());                        \
+    HValue* stub = Add<HConstant>(callable.code());                          \
+    instr = AddUncasted<HCallWithDescriptor>(stub, 0, callable.descriptor(), \
+                                             ArrayVector(values));           \
+  } while (false)
+
     switch (op) {
       default:
         UNREACHABLE();
       case Token::ADD:
-        function_id = Runtime::kAdd;
+        GET_STUB(Add);
         break;
       case Token::SUB:
-        function_id = Runtime::kSubtract;
+        GET_STUB(Subtract);
         break;
       case Token::MUL:
-        function_id = Runtime::kMultiply;
+        GET_STUB(Multiply);
         break;
       case Token::DIV:
-        function_id = Runtime::kDivide;
+        GET_STUB(Divide);
         break;
       case Token::MOD:
-        function_id = Runtime::kModulus;
+        GET_STUB(Modulus);
         break;
       case Token::BIT_OR:
-        function_id = Runtime::kBitwiseOr;
+        GET_STUB(BitwiseOr);
         break;
       case Token::BIT_AND:
-        function_id = Runtime::kBitwiseAnd;
+        GET_STUB(BitwiseAnd);
         break;
       case Token::BIT_XOR:
-        function_id = Runtime::kBitwiseXor;
+        GET_STUB(BitwiseXor);
         break;
       case Token::SAR:
-        function_id = Runtime::kShiftRight;
+        GET_STUB(ShiftRight);
         break;
       case Token::SHR:
-        function_id = Runtime::kShiftRightLogical;
+        GET_STUB(ShiftRightLogical);
         break;
       case Token::SHL:
-        function_id = Runtime::kShiftLeft;
+        GET_STUB(ShiftLeft);
         break;
     }
-    Add<HPushArguments>(left, right);
-    instr = AddUncasted<HCallRuntime>(Runtime::FunctionForId(function_id), 2);
+#undef GET_STUB
   } else {
     switch (op) {
       case Token::ADD:
@@ -11456,18 +11658,22 @@
   return ast_context()->ReturnControl(instr, expr->id());
 }
 
+namespace {
 
-static bool IsLiteralCompareBool(Isolate* isolate,
-                                 HValue* left,
-                                 Token::Value op,
-                                 HValue* right) {
+bool IsLiteralCompareStrict(Isolate* isolate, HValue* left, Token::Value op,
+                            HValue* right) {
   return op == Token::EQ_STRICT &&
-      ((left->IsConstant() &&
-          HConstant::cast(left)->handle(isolate)->IsBoolean()) ||
-       (right->IsConstant() &&
-           HConstant::cast(right)->handle(isolate)->IsBoolean()));
+         ((left->IsConstant() &&
+           !HConstant::cast(left)->handle(isolate)->IsNumber() &&
+           !HConstant::cast(left)->handle(isolate)->IsSimd128Value() &&
+           !HConstant::cast(left)->handle(isolate)->IsString()) ||
+          (right->IsConstant() &&
+           !HConstant::cast(right)->handle(isolate)->IsNumber() &&
+           !HConstant::cast(right)->handle(isolate)->IsSimd128Value() &&
+           !HConstant::cast(right)->handle(isolate)->IsString()));
 }
 
+}  // namespace
 
 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
   DCHECK(!HasStackOverflow());
@@ -11502,8 +11708,8 @@
     return ast_context()->ReturnControl(instr, expr->id());
   }
 
-  Type* left_type = expr->left()->bounds().lower;
-  Type* right_type = expr->right()->bounds().lower;
+  Type* left_type = bounds_.get(expr->left()).lower;
+  Type* right_type = bounds_.get(expr->right()).lower;
   Type* combined_type = expr->combined_type();
 
   CHECK_ALIVE(VisitForValue(expr->left()));
@@ -11513,25 +11719,31 @@
   HValue* left = Pop();
   Token::Value op = expr->op();
 
-  if (IsLiteralCompareBool(isolate(), left, op, right)) {
+  if (IsLiteralCompareStrict(isolate(), left, op, right)) {
     HCompareObjectEqAndBranch* result =
         New<HCompareObjectEqAndBranch>(left, right);
     return ast_context()->ReturnControl(result, expr->id());
   }
 
   if (op == Token::INSTANCEOF) {
-    DCHECK(!FLAG_harmony_instanceof);
     // Check to see if the rhs of the instanceof is a known function.
     if (right->IsConstant() &&
         HConstant::cast(right)->handle(isolate())->IsJSFunction()) {
-      Handle<JSFunction> constructor =
+      Handle<JSFunction> function =
           Handle<JSFunction>::cast(HConstant::cast(right)->handle(isolate()));
-      if (constructor->IsConstructor() &&
-          !constructor->map()->has_non_instance_prototype()) {
-        JSFunction::EnsureHasInitialMap(constructor);
-        DCHECK(constructor->has_initial_map());
-        Handle<Map> initial_map(constructor->initial_map(), isolate());
+      // Make sure the prototype of {function} is the %FunctionPrototype%, and
+      // it already has a meaningful initial map (i.e. we constructed at least
+      // one instance using the constructor {function}).
+      // We can only use the fast case if @@hasInstance was not used so far.
+      if (function->has_initial_map() &&
+          function->map()->prototype() ==
+              function->native_context()->closure() &&
+          !function->map()->has_non_instance_prototype() &&
+          isolate()->IsHasInstanceLookupChainIntact()) {
+        Handle<Map> initial_map(function->initial_map(), isolate());
         top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
+        top_info()->dependencies()->AssumePropertyCell(
+            isolate()->factory()->has_instance_protector());
         HInstruction* prototype =
             Add<HConstant>(handle(initial_map->prototype(), isolate()));
         HHasInPrototypeChainAndBranch* result =
@@ -11540,13 +11752,21 @@
       }
     }
 
-    HInstanceOf* result = New<HInstanceOf>(left, right);
+    Callable callable = CodeFactory::InstanceOf(isolate());
+    HValue* stub = Add<HConstant>(callable.code());
+    HValue* values[] = {context(), left, right};
+    HCallWithDescriptor* result = New<HCallWithDescriptor>(
+        stub, 0, callable.descriptor(), ArrayVector(values));
+    result->set_type(HType::Boolean());
     return ast_context()->ReturnInstruction(result, expr->id());
 
   } else if (op == Token::IN) {
-    Add<HPushArguments>(left, right);
+    Callable callable = CodeFactory::HasProperty(isolate());
+    HValue* stub = Add<HConstant>(callable.code());
+    HValue* values[] = {context(), left, right};
     HInstruction* result =
-        New<HCallRuntime>(Runtime::FunctionForId(Runtime::kHasProperty), 2);
+        New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
+                                 Vector<HValue*>(values, arraysize(values)));
     return ast_context()->ReturnInstruction(result, expr->id());
   }
 
@@ -11827,8 +12047,9 @@
   }
   top_info()->dependencies()->AssumeTransitionStable(current_site);
 
-  HInstruction* object = Add<HAllocate>(
-      object_size_constant, type, pretenure_flag, instance_type, top_site);
+  HInstruction* object =
+      Add<HAllocate>(object_size_constant, type, pretenure_flag, instance_type,
+                     graph()->GetConstant0(), top_site);
 
   // If allocation folding reaches Page::kMaxRegularHeapObjectSize the
   // elements array may not get folded into the object. Hence, we set the
@@ -11869,7 +12090,8 @@
     InstanceType instance_type = boilerplate_object->HasFastDoubleElements()
         ? FIXED_DOUBLE_ARRAY_TYPE : FIXED_ARRAY_TYPE;
     object_elements = Add<HAllocate>(object_elements_size, HType::HeapObject(),
-                                     pretenure_flag, instance_type, top_site);
+                                     pretenure_flag, instance_type,
+                                     graph()->GetConstant0(), top_site);
     BuildEmitElements(boilerplate_object, elements, object_elements,
                       site_context);
     Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
@@ -11970,9 +12192,9 @@
       if (representation.IsDouble()) {
         // Allocate a HeapNumber box and store the value into it.
         HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
-        HInstruction* double_box =
-            Add<HAllocate>(heap_number_constant, HType::HeapObject(),
-                pretenure_flag, MUTABLE_HEAP_NUMBER_TYPE);
+        HInstruction* double_box = Add<HAllocate>(
+            heap_number_constant, HType::HeapObject(), pretenure_flag,
+            MUTABLE_HEAP_NUMBER_TYPE, graph()->GetConstant0());
         AddStoreMapConstant(double_box,
             isolate()->factory()->mutable_heap_number_map());
         // Unwrap the mutable heap number from the boilerplate.
@@ -11982,9 +12204,9 @@
             double_box, HObjectAccess::ForHeapNumberValue(), double_value);
         value_instruction = double_box;
       } else if (representation.IsSmi()) {
-        value_instruction = value->IsUninitialized()
-            ? graph()->GetConstant0()
-            : Add<HConstant>(value);
+        value_instruction = value->IsUninitialized(isolate())
+                                ? graph()->GetConstant0()
+                                : Add<HConstant>(value);
         // Ensure that value is stored as smi.
         access = access.WithRepresentation(representation);
       } else {
@@ -12113,10 +12335,7 @@
     Handle<FixedArray> array =
        isolate()->factory()->NewFixedArray(globals_.length(), TENURED);
     for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
-    int flags =
-        DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) |
-        DeclareGlobalsNativeFlag::encode(current_info()->is_native()) |
-        DeclareGlobalsLanguageMode::encode(current_info()->language_mode());
+    int flags = current_info()->GetDeclareGlobalsFlags();
     Add<HDeclareGlobals>(array, flags);
     globals_.Rewind(0);
   }
@@ -12128,14 +12347,13 @@
   VariableProxy* proxy = declaration->proxy();
   VariableMode mode = declaration->mode();
   Variable* variable = proxy->var();
-  bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
+  bool hole_init = mode == LET || mode == CONST;
   switch (variable->location()) {
     case VariableLocation::GLOBAL:
     case VariableLocation::UNALLOCATED:
+      DCHECK(!variable->binding_needs_init());
       globals_.Add(variable->name(), zone());
-      globals_.Add(variable->binding_needs_init()
-                       ? isolate()->factory()->the_hole_value()
-                       : isolate()->factory()->undefined_value(), zone());
+      globals_.Add(isolate()->factory()->undefined_value(), zone());
       return;
     case VariableLocation::PARAMETER:
     case VariableLocation::LOCAL:
@@ -12291,9 +12509,8 @@
     Callable callable = CodeFactory::ToInteger(isolate());
     HValue* stub = Add<HConstant>(callable.code());
     HValue* values[] = {context(), input};
-    HInstruction* result =
-        New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
-                                 Vector<HValue*>(values, arraysize(values)));
+    HInstruction* result = New<HCallWithDescriptor>(
+        stub, 0, callable.descriptor(), ArrayVector(values));
     return ast_context()->ReturnInstruction(result, call->id());
   }
 }
@@ -12315,9 +12532,8 @@
     Callable callable = CodeFactory::ToName(isolate());
     HValue* stub = Add<HConstant>(callable.code());
     HValue* values[] = {context(), input};
-    HInstruction* result =
-        New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
-                                 Vector<HValue*>(values, arraysize(values)));
+    HInstruction* result = New<HCallWithDescriptor>(
+        stub, 0, callable.descriptor(), ArrayVector(values));
     return ast_context()->ReturnInstruction(result, call->id());
   }
 }
@@ -12342,9 +12558,8 @@
     Callable callable = CodeFactory::ToString(isolate());
     HValue* stub = Add<HConstant>(callable.code());
     HValue* values[] = {context(), input};
-    HInstruction* result =
-        New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
-                                 Vector<HValue*>(values, arraysize(values)));
+    HInstruction* result = New<HCallWithDescriptor>(
+        stub, 0, callable.descriptor(), ArrayVector(values));
     return ast_context()->ReturnInstruction(result, call->id());
   }
 }
@@ -12357,9 +12572,8 @@
   HValue* input = Pop();
   HValue* stub = Add<HConstant>(callable.code());
   HValue* values[] = {context(), input};
-  HInstruction* result =
-      New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
-                               Vector<HValue*>(values, arraysize(values)));
+  HInstruction* result = New<HCallWithDescriptor>(
+      stub, 0, callable.descriptor(), ArrayVector(values));
   return ast_context()->ReturnInstruction(result, call->id());
 }
 
@@ -12456,38 +12670,6 @@
 }
 
 
-void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
-    CallRuntime* call) {
-  DCHECK(call->arguments()->length() == 3);
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
-  HValue* string = Pop();
-  HValue* value = Pop();
-  HValue* index = Pop();
-  Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string,
-                         index, value);
-  Add<HSimulate>(call->id(), FIXED_SIMULATE);
-  return ast_context()->ReturnValue(graph()->GetConstantUndefined());
-}
-
-
-void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar(
-    CallRuntime* call) {
-  DCHECK(call->arguments()->length() == 3);
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
-  HValue* string = Pop();
-  HValue* value = Pop();
-  HValue* index = Pop();
-  Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string,
-                         index, value);
-  Add<HSimulate>(call->id(), FIXED_SIMULATE);
-  return ast_context()->ReturnValue(graph()->GetConstantUndefined());
-}
-
-
 // Fast support for charCodeAt(n).
 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
   DCHECK(call->arguments()->length() == 2);
@@ -12510,20 +12692,6 @@
 }
 
 
-// Fast support for string.charAt(n) and string[n].
-void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
-  DCHECK(call->arguments()->length() == 2);
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
-  HValue* index = Pop();
-  HValue* string = Pop();
-  HInstruction* char_code = BuildStringCharCodeAt(string, index);
-  AddInstruction(char_code);
-  HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
-  return ast_context()->ReturnInstruction(result, call->id());
-}
-
-
 // Fast support for SubString.
 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
   DCHECK_EQ(3, call->arguments()->length());
@@ -12532,9 +12700,9 @@
   Callable callable = CodeFactory::SubString(isolate());
   HValue* stub = Add<HConstant>(callable.code());
   HValue* values[] = {context()};
-  HInstruction* result = New<HCallWithDescriptor>(
-      stub, call->arguments()->length(), callable.descriptor(),
-      Vector<HValue*>(values, arraysize(values)));
+  HInstruction* result =
+      New<HCallWithDescriptor>(stub, call->arguments()->length(),
+                               callable.descriptor(), ArrayVector(values));
   result->set_type(HType::String());
   return ast_context()->ReturnInstruction(result, call->id());
 }
@@ -12547,8 +12715,8 @@
   FastNewObjectDescriptor descriptor(isolate());
   HValue* values[] = {context(), Pop(), Pop()};
   HConstant* stub_value = Add<HConstant>(stub.GetCode());
-  HInstruction* result = New<HCallWithDescriptor>(
-      stub_value, 0, descriptor, Vector<HValue*>(values, arraysize(values)));
+  HInstruction* result =
+      New<HCallWithDescriptor>(stub_value, 0, descriptor, ArrayVector(values));
   return ast_context()->ReturnInstruction(result, call->id());
 }
 
@@ -12560,9 +12728,9 @@
   Callable callable = CodeFactory::RegExpExec(isolate());
   HValue* stub = Add<HConstant>(callable.code());
   HValue* values[] = {context()};
-  HInstruction* result = New<HCallWithDescriptor>(
-      stub, call->arguments()->length(), callable.descriptor(),
-      Vector<HValue*>(values, arraysize(values)));
+  HInstruction* result =
+      New<HCallWithDescriptor>(stub, call->arguments()->length(),
+                               callable.descriptor(), ArrayVector(values));
   return ast_context()->ReturnInstruction(result, call->id());
 }
 
@@ -12605,17 +12773,6 @@
 }
 
 
-void HOptimizedGraphBuilder::GenerateConstructDouble(CallRuntime* call) {
-  DCHECK_EQ(2, call->arguments()->length());
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
-  HValue* lo = Pop();
-  HValue* hi = Pop();
-  HInstruction* result = NewUncasted<HConstructDouble>(hi, lo);
-  return ast_context()->ReturnInstruction(result, call->id());
-}
-
-
 // Construct a RegExp exec result with two in-object properties.
 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
   DCHECK_EQ(3, call->arguments()->length());
@@ -12644,54 +12801,15 @@
 void HOptimizedGraphBuilder::GenerateCall(CallRuntime* call) {
   DCHECK_LE(2, call->arguments()->length());
   CHECK_ALIVE(VisitExpressions(call->arguments()));
-
-  // Try and customize ES6 instanceof here.
-  // We should at least have the constructor on the expression stack.
-  if (FLAG_harmony_instanceof && FLAG_harmony_instanceof_opt &&
-      call->arguments()->length() == 3) {
-    HValue* target = environment()->ExpressionStackAt(2);
-    if (target->IsConstant()) {
-      HConstant* constant_function = HConstant::cast(target);
-      if (constant_function->handle(isolate())->IsJSFunction()) {
-        Handle<JSFunction> func =
-            Handle<JSFunction>::cast(constant_function->handle(isolate()));
-        if (*func == isolate()->native_context()->ordinary_has_instance()) {
-          // Look at the function, which will be argument 1.
-          HValue* right = environment()->ExpressionStackAt(1);
-          if (right->IsConstant() &&
-              HConstant::cast(right)->handle(isolate())->IsJSFunction()) {
-            Handle<JSFunction> constructor = Handle<JSFunction>::cast(
-                HConstant::cast(right)->handle(isolate()));
-            if (constructor->IsConstructor() &&
-                !constructor->map()->has_non_instance_prototype()) {
-              JSFunction::EnsureHasInitialMap(constructor);
-              DCHECK(constructor->has_initial_map());
-              Handle<Map> initial_map(constructor->initial_map(), isolate());
-              top_info()->dependencies()->AssumeInitialMapCantChange(
-                  initial_map);
-              HInstruction* prototype =
-                  Add<HConstant>(handle(initial_map->prototype(), isolate()));
-              HValue* left = environment()->ExpressionStackAt(0);
-              HHasInPrototypeChainAndBranch* result =
-                  New<HHasInPrototypeChainAndBranch>(left, prototype);
-              Drop(3);
-              return ast_context()->ReturnControl(result, call->id());
-            }
-          }
-        }
-      }
-    }
-  }
-
   CallTrampolineDescriptor descriptor(isolate());
   PushArgumentsFromEnvironment(call->arguments()->length() - 1);
   HValue* trampoline = Add<HConstant>(isolate()->builtins()->Call());
   HValue* target = Pop();
   HValue* values[] = {context(), target,
                       Add<HConstant>(call->arguments()->length() - 2)};
-  HInstruction* result = New<HCallWithDescriptor>(
-      trampoline, call->arguments()->length() - 1, descriptor,
-      Vector<HValue*>(values, arraysize(values)));
+  HInstruction* result =
+      New<HCallWithDescriptor>(trampoline, call->arguments()->length() - 1,
+                               descriptor, ArrayVector(values));
   return ast_context()->ReturnInstruction(result, call->id());
 }
 
@@ -12708,15 +12826,6 @@
 }
 
 
-void HOptimizedGraphBuilder::GenerateMathLogRT(CallRuntime* call) {
-  DCHECK(call->arguments()->length() == 1);
-  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
-  HValue* value = Pop();
-  HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathLog);
-  return ast_context()->ReturnInstruction(result, call->id());
-}
-
-
 void HOptimizedGraphBuilder::GenerateFixedArrayGet(CallRuntime* call) {
   DCHECK(call->arguments()->length() == 2);
   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
@@ -12793,7 +12902,7 @@
   // Allocate the table and add the proper map.
   HValue* table =
       Add<HAllocate>(Add<HConstant>(kSizeInBytes), HType::HeapObject(),
-                     NOT_TENURED, FIXED_ARRAY_TYPE);
+                     NOT_TENURED, FIXED_ARRAY_TYPE, graph()->GetConstant0());
   AddStoreMapConstant(table, isolate()->factory()->ordered_hash_table_map());
 
   // Initialize the FixedArray...
@@ -12923,13 +13032,6 @@
   return ast_context()->ReturnValue(value);
 }
 
-void HOptimizedGraphBuilder::GenerateGetOrdinaryHasInstance(CallRuntime* call) {
-  DCHECK(call->arguments()->length() == 0);
-  // ordinary_has_instance is immutable so we can treat it as a constant.
-  HValue* value = Add<HConstant>(isolate()->ordinary_has_instance());
-  return ast_context()->ReturnValue(value);
-}
-
 #undef CHECK_BAILOUT
 #undef CHECK_ALIVE
 
@@ -13251,13 +13353,26 @@
 
 void HTracer::TraceCompilation(CompilationInfo* info) {
   Tag tag(this, "compilation");
-  base::SmartArrayPointer<char> name = info->GetDebugName();
+  std::string name;
+  if (info->parse_info()) {
+    Object* source_name = info->script()->name();
+    if (source_name->IsString()) {
+      String* str = String::cast(source_name);
+      if (str->length() > 0) {
+        name.append(str->ToCString().get());
+        name.append(":");
+      }
+    }
+  }
+  base::SmartArrayPointer<char> method_name = info->GetDebugName();
+  name.append(method_name.get());
   if (info->IsOptimizing()) {
-    PrintStringProperty("name", name.get());
+    PrintStringProperty("name", name.c_str());
     PrintIndent();
-    trace_.Add("method \"%s:%d\"\n", name.get(), info->optimization_id());
+    trace_.Add("method \"%s:%d\"\n", method_name.get(),
+               info->optimization_id());
   } else {
-    PrintStringProperty("name", name.get());
+    PrintStringProperty("name", name.c_str());
     PrintStringProperty("method", "stub");
   }
   PrintLongProperty("date",
@@ -13439,10 +13554,11 @@
       int assigned_reg = op->index();
       if (op->IsDoubleRegister()) {
         trace_.Add(" \"%s\"",
-                   DoubleRegister::from_code(assigned_reg).ToString());
+                   GetRegConfig()->GetDoubleRegisterName(assigned_reg));
       } else {
         DCHECK(op->IsRegister());
-        trace_.Add(" \"%s\"", Register::from_code(assigned_reg).ToString());
+        trace_.Add(" \"%s\"",
+                   GetRegConfig()->GetGeneralRegisterName(assigned_reg));
       }
     } else if (range->IsSpilled()) {
       LOperand* op = range->TopLevel()->GetSpillOperand();
diff --git a/src/crankshaft/hydrogen.h b/src/crankshaft/hydrogen.h
index 10c0baa..d0f757b 100644
--- a/src/crankshaft/hydrogen.h
+++ b/src/crankshaft/hydrogen.h
@@ -7,12 +7,14 @@
 
 #include "src/accessors.h"
 #include "src/allocation.h"
+#include "src/ast/ast-type-bounds.h"
 #include "src/ast/ast.h"
 #include "src/ast/scopes.h"
 #include "src/bailout-reason.h"
 #include "src/compiler.h"
 #include "src/crankshaft/compilation-phase.h"
 #include "src/crankshaft/hydrogen-instructions.h"
+#include "src/parsing/parser.h"
 #include "src/zone.h"
 
 namespace v8 {
@@ -30,6 +32,28 @@
 class LChunk;
 class LiveRange;
 
+class HCompilationJob final : public CompilationJob {
+ public:
+  explicit HCompilationJob(Handle<JSFunction> function)
+      : CompilationJob(&info_, "Crankshaft"),
+        zone_(function->GetIsolate()->allocator()),
+        parse_info_(&zone_, function),
+        info_(&parse_info_, function),
+        graph_(nullptr),
+        chunk_(nullptr) {}
+
+ protected:
+  virtual Status CreateGraphImpl();
+  virtual Status OptimizeGraphImpl();
+  virtual Status GenerateCodeImpl();
+
+ private:
+  Zone zone_;
+  ParseInfo parse_info_;
+  CompilationInfo info_;
+  HGraph* graph_;
+  LChunk* chunk_;
+};
 
 class HBasicBlock final : public ZoneObject {
  public:
@@ -293,6 +317,11 @@
   HStackCheck* stack_check_;
 };
 
+struct HInlinedFunctionInfo {
+  explicit HInlinedFunctionInfo(int start_position)
+      : start_position(start_position) {}
+  int start_position;
+};
 
 class HGraph final : public ZoneObject {
  public:
@@ -392,13 +421,11 @@
   }
   int maximum_environment_size() { return maximum_environment_size_; }
 
-  bool use_optimistic_licm() {
-    return use_optimistic_licm_;
-  }
+  bool allow_code_motion() const { return allow_code_motion_; }
+  void set_allow_code_motion(bool value) { allow_code_motion_ = value; }
 
-  void set_use_optimistic_licm(bool value) {
-    use_optimistic_licm_ = value;
-  }
+  bool use_optimistic_licm() const { return use_optimistic_licm_; }
+  void set_use_optimistic_licm(bool value) { use_optimistic_licm_ = value; }
 
   void MarkDependsOnEmptyArrayProtoElements() {
     // Add map dependency if not already added.
@@ -444,6 +471,10 @@
   // the corresponding script.
   int SourcePositionToScriptPosition(SourcePosition position);
 
+  ZoneVector<HInlinedFunctionInfo>& inlined_function_infos() {
+    return inlined_function_infos_;
+  }
+
  private:
   HConstant* ReinsertConstantIfNecessary(HConstant* constant);
   HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
@@ -480,6 +511,7 @@
   CallInterfaceDescriptor descriptor_;
   Zone* zone_;
 
+  bool allow_code_motion_;
   bool use_optimistic_licm_;
   bool depends_on_empty_array_proto_elements_;
   int type_change_checksum_;
@@ -487,6 +519,8 @@
   int no_side_effects_scope_count_;
   bool disallow_adding_new_values_;
 
+  ZoneVector<HInlinedFunctionInfo> inlined_function_infos_;
+
   DISALLOW_COPY_AND_ASSIGN(HGraph);
 };
 
@@ -1299,7 +1333,7 @@
             class P7, class P8, class P9>
   HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7,
                             P8 p8, P9 p9) {
-    return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8, p8));
+    return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8, p9));
   }
 
   template <class I, class P1, class P2, class P3, class P4, class P5, class P6,
@@ -1768,18 +1802,6 @@
     HAllocate* AllocateArray(HValue* capacity,
                              HValue* length_field,
                              FillMode fill_mode = FILL_WITH_HOLE);
-    // Use these allocators when capacity could be unknown at compile time
-    // but its limit is known. For constant |capacity| the value of
-    // |capacity_upper_bound| is ignored and the actual |capacity|
-    // value is used as an upper bound.
-    HAllocate* AllocateArray(HValue* capacity,
-                             int capacity_upper_bound,
-                             HValue* length_field,
-                             FillMode fill_mode = FILL_WITH_HOLE);
-    HAllocate* AllocateArray(HValue* capacity,
-                             HConstant* capacity_upper_bound,
-                             HValue* length_field,
-                             FillMode fill_mode = FILL_WITH_HOLE);
     HValue* GetElementsLocation() { return elements_location_; }
     HValue* EmitMapCode();
 
@@ -1929,6 +1951,9 @@
   SourcePosition source_position() { return position_; }
   void set_source_position(SourcePosition position) { position_ = position; }
 
+  int TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
+                           SourcePosition position);
+
   HValue* BuildAllocateEmptyArrayBuffer(HValue* byte_length);
   template <typename ViewClass>
   void BuildArrayBufferViewInitialization(HValue* obj,
@@ -2170,6 +2195,8 @@
 
   void VisitDeclarations(ZoneList<Declaration*>* declarations) override;
 
+  AstTypeBounds* bounds() { return &bounds_; }
+
   void* operator new(size_t size, Zone* zone) { return zone->New(size); }
   void operator delete(void* pointer, Zone* zone) { }
   void operator delete(void* pointer) { }
@@ -2214,17 +2241,20 @@
   TestContext* inlined_test_context() const {
     return function_state()->test_context();
   }
+  Handle<JSFunction> current_closure() const {
+    return current_info()->closure();
+  }
   Handle<SharedFunctionInfo> current_shared_info() const {
     return current_info()->shared_info();
   }
   TypeFeedbackVector* current_feedback_vector() const {
-    return current_shared_info()->feedback_vector();
+    return current_closure()->feedback_vector();
   }
   void ClearInlinedTestContext() {
     function_state()->ClearInlinedTestContext();
   }
   LanguageMode function_language_mode() {
-    return function_state()->compilation_info()->language_mode();
+    return function_state()->compilation_info()->parse_info()->language_mode();
   }
 
 #define FOR_EACH_HYDROGEN_INTRINSIC(F) \
@@ -2237,9 +2267,6 @@
   F(NewObject)                         \
   F(ValueOf)                           \
   F(StringCharFromCode)                \
-  F(StringCharAt)                      \
-  F(OneByteSeqStringSetChar)           \
-  F(TwoByteSeqStringSetChar)           \
   F(ToInteger)                         \
   F(ToName)                            \
   F(ToObject)                          \
@@ -2259,7 +2286,6 @@
   F(RegExpSource)                      \
   F(NumberToString)                    \
   F(DebugIsActive)                     \
-  F(GetOrdinaryHasInstance)            \
   /* Typed Arrays */                   \
   F(TypedArrayInitialize)              \
   F(MaxSmi)                            \
@@ -2270,10 +2296,8 @@
   /* ArrayBuffer */                    \
   F(ArrayBufferGetByteLength)          \
   /* Maths */                          \
-  F(ConstructDouble)                   \
   F(DoubleHi)                          \
   F(DoubleLo)                          \
-  F(MathLogRT)                         \
   /* ES6 Collections */                \
   F(MapClear)                          \
   F(MapInitialize)                     \
@@ -2336,21 +2360,19 @@
   void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
   bool IsEligibleForEnvironmentLivenessAnalysis(Variable* var,
                                                 int index,
-                                                HValue* value,
                                                 HEnvironment* env) {
     if (!FLAG_analyze_environment_liveness) return false;
     // |this| and |arguments| are always live; zapping parameters isn't
     // safe because function.arguments can inspect them at any time.
     return !var->is_this() &&
            !var->is_arguments() &&
-           !value->IsArgumentsObject() &&
            env->is_local_index(index);
   }
   void BindIfLive(Variable* var, HValue* value) {
     HEnvironment* env = environment();
     int index = env->IndexFor(var);
     env->Bind(index, value);
-    if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
+    if (IsEligibleForEnvironmentLivenessAnalysis(var, index, env)) {
       HEnvironmentMarker* bind =
           Add<HEnvironmentMarker>(HEnvironmentMarker::BIND, index);
       USE(bind);
@@ -2362,8 +2384,7 @@
   HValue* LookupAndMakeLive(Variable* var) {
     HEnvironment* env = environment();
     int index = env->IndexFor(var);
-    HValue* value = env->Lookup(index);
-    if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
+    if (IsEligibleForEnvironmentLivenessAnalysis(var, index, env)) {
       HEnvironmentMarker* lookup =
           Add<HEnvironmentMarker>(HEnvironmentMarker::LOOKUP, index);
       USE(lookup);
@@ -2371,7 +2392,7 @@
       lookup->set_closure(env->closure());
 #endif
     }
-    return value;
+    return env->Lookup(index);
   }
 
   // The value of the arguments object is allowed in some but not most value
@@ -2451,8 +2472,10 @@
                        HValue* implicit_return_value);
   bool TryInlineIndirectCall(Handle<JSFunction> function, Call* expr,
                              int arguments_count);
-  bool TryInlineBuiltinMethodCall(Call* expr, Handle<JSFunction> function,
-                                  Handle<Map> receiver_map,
+  bool TryInlineBuiltinGetterCall(Handle<JSFunction> function,
+                                  Handle<Map> receiver_map, BailoutId ast_id);
+  bool TryInlineBuiltinMethodCall(Handle<JSFunction> function,
+                                  Handle<Map> receiver_map, BailoutId ast_id,
                                   int args_count_no_receiver);
   bool TryInlineBuiltinFunctionCall(Call* expr);
   enum ApiCallType {
@@ -2596,20 +2619,6 @@
       return false;
     }
 
-    bool IsJSArrayBufferViewFieldAccessor() {
-      int offset;  // unused
-      return Accessors::IsJSArrayBufferViewFieldAccessor(map_, name_, &offset);
-    }
-
-    bool GetJSArrayBufferViewFieldAccess(HObjectAccess* access) {
-      int offset;
-      if (Accessors::IsJSArrayBufferViewFieldAccessor(map_, name_, &offset)) {
-        *access = HObjectAccess::ForMapAndOffset(map_, offset);
-        return true;
-      }
-      return false;
-    }
-
     bool has_holder() { return !holder_.is_null(); }
     bool IsLoad() const { return access_type_ == LOAD; }
 
@@ -2903,6 +2912,8 @@
 
   HOsrBuilder* osr_;
 
+  AstTypeBounds bounds_;
+
   friend class FunctionState;  // Pushes and pops the state stack.
   friend class AstContext;  // Pushes and pops the AST context stack.
   friend class KeyedLoadFastElementStub;
diff --git a/src/crankshaft/ia32/lithium-codegen-ia32.cc b/src/crankshaft/ia32/lithium-codegen-ia32.cc
index ae1ca1f..e4854e7 100644
--- a/src/crankshaft/ia32/lithium-codegen-ia32.cc
+++ b/src/crankshaft/ia32/lithium-codegen-ia32.cc
@@ -15,7 +15,6 @@
 #include "src/ia32/frames-ia32.h"
 #include "src/ic/ic.h"
 #include "src/ic/stub-cache.h"
-#include "src/profiler/cpu-profiler.h"
 
 namespace v8 {
 namespace internal {
@@ -165,11 +164,11 @@
   Comment(";;; Prologue begin");
 
   // Possibly allocate a local context.
-  if (info_->num_heap_slots() > 0) {
+  if (info_->scope()->num_heap_slots() > 0) {
     Comment(";;; Allocate local context");
     bool need_write_barrier = true;
     // Argument to NewContext is the function, which is still in edi.
-    int slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+    int slots = info_->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
     Safepoint::DeoptMode deopt_mode = Safepoint::kNoLazyDeopt;
     if (info()->scope()->is_script_scope()) {
       __ push(edi);
@@ -274,8 +273,6 @@
       if (info()->saves_caller_doubles()) RestoreCallerDoubles();
       __ call(entry, RelocInfo::RUNTIME_ENTRY);
     }
-    info()->LogDeoptCallPosition(masm()->pc_offset(),
-                                 table_entry->deopt_info.inlining_id);
   }
   if (needs_frame.is_linked()) {
     __ bind(&needs_frame);
@@ -725,19 +722,18 @@
     __ bind(&done);
   }
 
-  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason);
+  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason, id);
 
   DCHECK(info()->IsStub() || frame_is_built_);
   if (cc == no_condition && frame_is_built_) {
     DeoptComment(deopt_info);
     __ call(entry, RelocInfo::RUNTIME_ENTRY);
-    info()->LogDeoptCallPosition(masm()->pc_offset(), deopt_info.inlining_id);
   } else {
     Deoptimizer::JumpTableEntry table_entry(entry, deopt_info, bailout_type,
                                             !frame_is_built_);
     // We often have several deopts to the same entry, reuse the last
     // jump entry if this is the case.
-    if (FLAG_trace_deopt || isolate()->cpu_profiler()->is_profiling() ||
+    if (FLAG_trace_deopt || isolate()->is_profiling() ||
         jump_table_.is_empty() ||
         !table_entry.IsEquivalentTo(jump_table_.last())) {
       jump_table_.Add(table_entry, zone());
@@ -814,7 +810,6 @@
 void LCodeGen::RecordAndWritePosition(int position) {
   if (position == RelocInfo::kNoPosition) return;
   masm()->positions_recorder()->RecordPosition(position);
-  masm()->positions_recorder()->WriteRecordedPositions();
 }
 
 
@@ -2291,16 +2286,6 @@
 }
 
 
-void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
-  DCHECK(ToRegister(instr->context()).is(esi));
-  DCHECK(ToRegister(instr->left()).is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(ToRegister(instr->right()).is(InstanceOfDescriptor::RightRegister()));
-  DCHECK(ToRegister(instr->result()).is(eax));
-  InstanceOfStub stub(isolate());
-  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
-}
-
-
 void LCodeGen::DoHasInPrototypeChainAndBranch(
     LHasInPrototypeChainAndBranch* instr) {
   Register const object = ToRegister(instr->object());
@@ -2330,10 +2315,10 @@
   DeoptimizeIf(equal, instr, Deoptimizer::kProxy);
 
   __ mov(object_prototype, FieldOperand(object_map, Map::kPrototypeOffset));
-  __ cmp(object_prototype, prototype);
-  EmitTrueBranch(instr, equal);
   __ cmp(object_prototype, factory()->null_value());
   EmitFalseBranch(instr, equal);
+  __ cmp(object_prototype, prototype);
+  EmitTrueBranch(instr, equal);
   __ mov(object_map, FieldOperand(object_prototype, HeapObject::kMapOffset));
   __ jmp(&loop);
 }
@@ -2431,15 +2416,12 @@
 
 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   DCHECK(ToRegister(instr->context()).is(esi));
-  DCHECK(ToRegister(instr->global_object())
-             .is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->result()).is(eax));
 
-  __ mov(LoadDescriptor::NameRegister(), instr->name());
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), instr->typeof_mode(), PREMONOMORPHIC)
-                        .code();
+  Handle<Code> ic =
+      CodeFactory::LoadGlobalICInOptimizedCode(isolate(), instr->typeof_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2554,10 +2536,7 @@
 
   __ mov(LoadDescriptor::NameRegister(), instr->name());
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_INSIDE_TYPEOF,
-                        instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2728,9 +2707,9 @@
     __ j(not_equal, &done);
     if (info()->IsStub()) {
       // A stub can safely convert the hole to undefined only if the array
-      // protector cell contains (Smi) Isolate::kArrayProtectorValid. Otherwise
-      // it needs to bail out.
-      __ mov(result, isolate()->factory()->array_protector());
+      // protector cell contains (Smi) Isolate::kArrayProtectorValid.
+      // Otherwise it needs to bail out.
+      __ LoadRoot(result, Heap::kArrayProtectorRootIndex);
       __ cmp(FieldOperand(result, PropertyCell::kValueOffset),
              Immediate(Smi::FromInt(Isolate::kArrayProtectorValid)));
       DeoptimizeIf(not_equal, instr, Deoptimizer::kHole);
@@ -2788,13 +2767,9 @@
   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
-  }
+  EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
 
-  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
-                        isolate(), instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3091,8 +3066,19 @@
   DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
 
   Label slow, allocated, done;
-  Register tmp = input_reg.is(eax) ? ecx : eax;
-  Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx;
+  uint32_t available_regs = eax.bit() | ecx.bit() | edx.bit() | ebx.bit();
+  available_regs &= ~input_reg.bit();
+  if (instr->context()->IsRegister()) {
+    // Make sure that the context isn't overwritten in the AllocateHeapNumber
+    // macro below.
+    available_regs &= ~ToRegister(instr->context()).bit();
+  }
+
+  Register tmp =
+      Register::from_code(base::bits::CountTrailingZeros32(available_regs));
+  available_regs &= ~tmp.bit();
+  Register tmp2 =
+      Register::from_code(base::bits::CountTrailingZeros32(available_regs));
 
   // Preserve the value of all registers.
   PushSafepointRegistersScope scope(this);
@@ -3409,31 +3395,18 @@
 
 
 void LCodeGen::DoMathLog(LMathLog* instr) {
-  DCHECK(instr->value()->Equals(instr->result()));
-  XMMRegister input_reg = ToDoubleRegister(instr->value());
-  XMMRegister xmm_scratch = double_scratch0();
-  Label positive, done, zero;
-  __ xorps(xmm_scratch, xmm_scratch);
-  __ ucomisd(input_reg, xmm_scratch);
-  __ j(above, &positive, Label::kNear);
-  __ j(not_carry, &zero, Label::kNear);
-  __ pcmpeqd(input_reg, input_reg);
-  __ jmp(&done, Label::kNear);
-  __ bind(&zero);
-  ExternalReference ninf =
-      ExternalReference::address_of_negative_infinity();
-  __ movsd(input_reg, Operand::StaticVariable(ninf));
-  __ jmp(&done, Label::kNear);
-  __ bind(&positive);
-  __ fldln2();
-  __ sub(Operand(esp), Immediate(kDoubleSize));
-  __ movsd(Operand(esp, 0), input_reg);
-  __ fld_d(Operand(esp, 0));
-  __ fyl2x();
+  XMMRegister input = ToDoubleRegister(instr->value());
+  XMMRegister result = ToDoubleRegister(instr->result());
+  // Pass one double as argument on the stack.
+  __ PrepareCallCFunction(2, eax);
+  __ movsd(Operand(esp, 0 * kDoubleSize), input);
+  __ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 2);
+  // Return value is in st(0) on ia32.
+  // Store it into the result register.
+  __ sub(esp, Immediate(kDoubleSize));
   __ fstp_d(Operand(esp, 0));
-  __ movsd(input_reg, Operand(esp, 0));
-  __ add(Operand(esp), Immediate(kDoubleSize));
-  __ bind(&done);
+  __ movsd(result, Operand(esp, 0));
+  __ add(esp, Immediate(kDoubleSize));
 }
 
 
@@ -3444,15 +3417,49 @@
   __ Lzcnt(result, input);
 }
 
+void LCodeGen::DoMathCos(LMathCos* instr) {
+  XMMRegister input = ToDoubleRegister(instr->value());
+  XMMRegister result = ToDoubleRegister(instr->result());
+  // Pass one double as argument on the stack.
+  __ PrepareCallCFunction(2, eax);
+  __ movsd(Operand(esp, 0 * kDoubleSize), input);
+  __ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 2);
+  // Return value is in st(0) on ia32.
+  // Store it into the result register.
+  __ sub(esp, Immediate(kDoubleSize));
+  __ fstp_d(Operand(esp, 0));
+  __ movsd(result, Operand(esp, 0));
+  __ add(esp, Immediate(kDoubleSize));
+}
+
+void LCodeGen::DoMathSin(LMathSin* instr) {
+  XMMRegister input = ToDoubleRegister(instr->value());
+  XMMRegister result = ToDoubleRegister(instr->result());
+  // Pass one double as argument on the stack.
+  __ PrepareCallCFunction(2, eax);
+  __ movsd(Operand(esp, 0 * kDoubleSize), input);
+  __ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 2);
+  // Return value is in st(0) on ia32.
+  // Store it into the result register.
+  __ sub(esp, Immediate(kDoubleSize));
+  __ fstp_d(Operand(esp, 0));
+  __ movsd(result, Operand(esp, 0));
+  __ add(esp, Immediate(kDoubleSize));
+}
 
 void LCodeGen::DoMathExp(LMathExp* instr) {
   XMMRegister input = ToDoubleRegister(instr->value());
   XMMRegister result = ToDoubleRegister(instr->result());
-  XMMRegister temp0 = double_scratch0();
-  Register temp1 = ToRegister(instr->temp1());
-  Register temp2 = ToRegister(instr->temp2());
-
-  MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2);
+  // Pass one double as argument on the stack.
+  __ PrepareCallCFunction(2, eax);
+  __ movsd(Operand(esp, 0 * kDoubleSize), input);
+  __ CallCFunction(ExternalReference::ieee754_exp_function(isolate()), 2);
+  // Return value is in st(0) on ia32.
+  // Store it into the result register.
+  __ sub(esp, Immediate(kDoubleSize));
+  __ fstp_d(Operand(esp, 0));
+  __ movsd(result, Operand(esp, 0));
+  __ add(esp, Immediate(kDoubleSize));
 }
 
 void LCodeGen::PrepareForTailCall(const ParameterCount& actual,
@@ -3467,7 +3474,9 @@
 #endif
   if (FLAG_code_comments) {
     if (actual.is_reg()) {
-      Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString());
+      Comment(";;; PrepareForTailCall, actual: %s {",
+              RegisterConfiguration::Crankshaft()->GetGeneralRegisterName(
+                  actual.reg().code()));
     } else {
       Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate());
     }
@@ -3537,14 +3546,7 @@
   DCHECK(ToRegister(instr->result()).is(eax));
 
   __ Move(eax, Immediate(instr->arity()));
-  if (instr->arity() == 1) {
-    // We only need the allocation site for the case we have a length argument.
-    // The case may bail out to the runtime, which will determine the correct
-    // elements kind with the site.
-    __ mov(ebx, instr->hydrogen()->site());
-  } else {
-    __ mov(ebx, isolate()->factory()->undefined_value());
-  }
+  __ mov(ebx, instr->hydrogen()->site());
 
   ElementsKind kind = instr->hydrogen()->elements_kind();
   AllocationSiteOverrideMode override_mode =
@@ -3578,7 +3580,7 @@
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
     __ bind(&done);
   } else {
-    ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
+    ArrayNArgumentsConstructorStub stub(isolate());
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   }
 }
@@ -3708,14 +3710,12 @@
   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
 
   __ mov(StoreDescriptor::NameRegister(), instr->name());
-  Handle<Code> ic = CodeFactory::StoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic =
+      CodeFactory::StoreICInOptimizedCode(isolate(), instr->language_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3885,13 +3885,11 @@
   DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
 
   Handle<Code> ic = CodeFactory::KeyedStoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state()).code();
+                        isolate(), instr->language_mode())
+                        .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3975,7 +3973,15 @@
 
     LOperand* key = instr->key();
     if (key->IsConstantOperand()) {
-      __ mov(ebx, ToImmediate(key, Representation::Smi()));
+      LConstantOperand* constant_key = LConstantOperand::cast(key);
+      int32_t int_key = ToInteger32(constant_key);
+      if (Smi::IsValid(int_key)) {
+        __ mov(ebx, Immediate(Smi::FromInt(int_key)));
+      } else {
+        // We should never get here at runtime because there is a smi check on
+        // the key before this point.
+        __ int3();
+      }
     } else {
       __ Move(ebx, ToRegister(key));
       __ SmiTag(ebx);
@@ -4024,8 +4030,7 @@
     DCHECK(object_reg.is(eax));
     PushSafepointRegistersScope scope(this);
     __ mov(ebx, to_map);
-    bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
-    TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
+    TransitionElementsKindStub stub(isolate(), from_kind, to_kind);
     __ CallStub(&stub);
     RecordSafepointWithLazyDeopt(instr,
         RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
@@ -4817,25 +4822,6 @@
 }
 
 
-void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
-  Register hi_reg = ToRegister(instr->hi());
-  Register lo_reg = ToRegister(instr->lo());
-  XMMRegister result_reg = ToDoubleRegister(instr->result());
-
-  if (CpuFeatures::IsSupported(SSE4_1)) {
-    CpuFeatureScope scope2(masm(), SSE4_1);
-    __ movd(result_reg, lo_reg);
-    __ pinsrd(result_reg, hi_reg, 1);
-  } else {
-    XMMRegister xmm_scratch = double_scratch0();
-    __ movd(result_reg, hi_reg);
-    __ psllq(result_reg, 32);
-    __ movd(xmm_scratch, lo_reg);
-    __ orps(result_reg, xmm_scratch);
-  }
-}
-
-
 void LCodeGen::DoAllocate(LAllocate* instr) {
   class DeferredAllocate final : public LDeferredCode {
    public:
@@ -4854,7 +4840,7 @@
   Register temp = ToRegister(instr->temp());
 
   // Allocate memory for the object.
-  AllocationFlags flags = TAG_OBJECT;
+  AllocationFlags flags = NO_ALLOCATION_FLAGS;
   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
   }
@@ -4862,6 +4848,10 @@
     DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
     flags = static_cast<AllocationFlags>(flags | PRETENURE);
   }
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    flags = static_cast<AllocationFlags>(flags | ALLOCATION_FOLDING_DOMINATOR);
+  }
+  DCHECK(!instr->hydrogen()->IsAllocationFolded());
 
   if (instr->size()->IsConstantOperand()) {
     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
@@ -4892,6 +4882,29 @@
   }
 }
 
+void LCodeGen::DoFastAllocate(LFastAllocate* instr) {
+  DCHECK(instr->hydrogen()->IsAllocationFolded());
+  DCHECK(!instr->hydrogen()->IsAllocationFoldingDominator());
+  Register result = ToRegister(instr->result());
+  Register temp = ToRegister(instr->temp());
+
+  AllocationFlags flags = ALLOCATION_FOLDED;
+  if (instr->hydrogen()->MustAllocateDoubleAligned()) {
+    flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
+  }
+  if (instr->hydrogen()->IsOldSpaceAllocation()) {
+    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+    flags = static_cast<AllocationFlags>(flags | PRETENURE);
+  }
+  if (instr->size()->IsConstantOperand()) {
+    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
+    CHECK(size <= Page::kMaxRegularHeapObjectSize);
+    __ FastAllocate(size, result, temp, flags);
+  } else {
+    Register size = ToRegister(instr->size());
+    __ FastAllocate(size, result, temp, flags);
+  }
+}
 
 void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
   Register result = ToRegister(instr->result());
@@ -4931,6 +4944,22 @@
   CallRuntimeFromDeferred(
       Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
   __ StoreToSafepointRegisterSlot(result, eax);
+
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    AllocationFlags allocation_flags = NO_ALLOCATION_FLAGS;
+    if (instr->hydrogen()->IsOldSpaceAllocation()) {
+      DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+      allocation_flags = static_cast<AllocationFlags>(flags | PRETENURE);
+    }
+    // If the allocation folding dominator allocate triggered a GC, allocation
+    // happend in the runtime. We have to reset the top pointer to virtually
+    // undo the allocation.
+    ExternalReference allocation_top =
+        AllocationUtils::GetAllocationTopReference(isolate(), allocation_flags);
+    __ sub(eax, Immediate(kHeapObjectTag));
+    __ mov(Operand::StaticVariable(allocation_top), eax);
+    __ add(eax, Immediate(kHeapObjectTag));
+  }
 }
 
 
diff --git a/src/crankshaft/ia32/lithium-codegen-ia32.h b/src/crankshaft/ia32/lithium-codegen-ia32.h
index bc61c96..5084819 100644
--- a/src/crankshaft/ia32/lithium-codegen-ia32.h
+++ b/src/crankshaft/ia32/lithium-codegen-ia32.h
@@ -115,8 +115,6 @@
 #undef DECLARE_DO
 
  private:
-  LanguageMode language_mode() const { return info()->language_mode(); }
-
   Scope* scope() const { return scope_; }
 
   XMMRegister double_scratch0() const { return xmm0; }
diff --git a/src/crankshaft/ia32/lithium-gap-resolver-ia32.cc b/src/crankshaft/ia32/lithium-gap-resolver-ia32.cc
index c3284df..be8251c 100644
--- a/src/crankshaft/ia32/lithium-gap-resolver-ia32.cc
+++ b/src/crankshaft/ia32/lithium-gap-resolver-ia32.cc
@@ -167,8 +167,7 @@
 
 Register LGapResolver::GetFreeRegisterNot(Register reg) {
   int skip_index = reg.is(no_reg) ? -1 : reg.code();
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
     int code = config->GetAllocatableGeneralCode(i);
     if (source_uses_[code] == 0 && destination_uses_[code] > 0 &&
@@ -183,8 +182,7 @@
 bool LGapResolver::HasBeenReset() {
   if (!moves_.is_empty()) return false;
   if (spilled_register_ >= 0) return false;
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
     int code = config->GetAllocatableGeneralCode(i);
     if (source_uses_[code] != 0) return false;
@@ -238,8 +236,7 @@
 
   // 3. Prefer to spill a register that is not used in any remaining move
   // because it will not need to be restored until the end.
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
     int code = config->GetAllocatableGeneralCode(i);
     if (source_uses_[code] == 0 && destination_uses_[code] == 0) {
diff --git a/src/crankshaft/ia32/lithium-ia32.cc b/src/crankshaft/ia32/lithium-ia32.cc
index 4afeef5..501ff47 100644
--- a/src/crankshaft/ia32/lithium-ia32.cc
+++ b/src/crankshaft/ia32/lithium-ia32.cc
@@ -910,7 +910,7 @@
 
 LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) {
   LInstruction* result = new (zone()) LPrologue();
-  if (info_->num_heap_slots() > 0) {
+  if (info_->scope()->num_heap_slots() > 0) {
     result = MarkAsCall(result, instr);
   }
   return result;
@@ -966,17 +966,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
-  LOperand* left =
-      UseFixed(instr->left(), InstanceOfDescriptor::LeftRegister());
-  LOperand* right =
-      UseFixed(instr->right(), InstanceOfDescriptor::RightRegister());
-  LOperand* context = UseFixed(instr->context(), esi);
-  LInstanceOf* result = new (zone()) LInstanceOf(context, left, right);
-  return MarkAsCall(DefineFixed(result, eax), instr);
-}
-
-
 LInstruction* LChunkBuilder::DoHasInPrototypeChainAndBranch(
     HHasInPrototypeChainAndBranch* instr) {
   LOperand* object = UseRegister(instr->object());
@@ -1104,6 +1093,8 @@
 
 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
   switch (instr->op()) {
+    case kMathCos:
+      return DoMathCos(instr);
     case kMathFloor:
       return DoMathFloor(instr);
     case kMathRound:
@@ -1122,6 +1113,8 @@
       return DoMathPowHalf(instr);
     case kMathClz32:
       return DoMathClz32(instr);
+    case kMathSin:
+      return DoMathSin(instr);
     default:
       UNREACHABLE();
       return NULL;
@@ -1188,15 +1181,25 @@
   return DefineAsRegister(result);
 }
 
+LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
+  DCHECK(instr->representation().IsDouble());
+  DCHECK(instr->value()->representation().IsDouble());
+  LOperand* input = UseRegisterAtStart(instr->value());
+  return MarkAsCall(DefineSameAsFirst(new (zone()) LMathCos(input)), instr);
+}
+
+LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
+  DCHECK(instr->representation().IsDouble());
+  DCHECK(instr->value()->representation().IsDouble());
+  LOperand* input = UseRegisterAtStart(instr->value());
+  return MarkAsCall(DefineSameAsFirst(new (zone()) LMathSin(input)), instr);
+}
 
 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
   DCHECK(instr->representation().IsDouble());
   DCHECK(instr->value()->representation().IsDouble());
-  LOperand* value = UseTempRegister(instr->value());
-  LOperand* temp1 = TempRegister();
-  LOperand* temp2 = TempRegister();
-  LMathExp* result = new(zone()) LMathExp(value, temp1, temp2);
-  return DefineAsRegister(result);
+  LOperand* input = UseRegisterAtStart(instr->value());
+  return MarkAsCall(DefineSameAsFirst(new (zone()) LMathExp(input)), instr);
 }
 
 
@@ -1991,13 +1994,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
-  LOperand* lo = UseRegister(instr->lo());
-  LOperand* hi = UseRegister(instr->hi());
-  return DefineAsRegister(new(zone()) LConstructDouble(hi, lo));
-}
-
-
 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
   LOperand* context = info()->IsStub() ? UseFixed(instr->context(), esi) : NULL;
   LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
@@ -2029,15 +2025,9 @@
 
 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), esi);
-  LOperand* global_object =
-      UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
-  LLoadGlobalGeneric* result =
-      new(zone()) LLoadGlobalGeneric(context, global_object, vector);
+  LLoadGlobalGeneric* result = new (zone()) LLoadGlobalGeneric(context, vector);
   return MarkAsCall(DefineFixed(result, eax), instr);
 }
 
@@ -2085,10 +2075,7 @@
   LOperand* context = UseFixed(instr->context(), esi);
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
   LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(
       context, object, vector);
   return MarkAsCall(DefineFixed(result, eax), instr);
@@ -2158,10 +2145,7 @@
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
   LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
   LLoadKeyedGeneric* result =
       new(zone()) LLoadKeyedGeneric(context, object, key, vector);
   return MarkAsCall(DefineFixed(result, eax), instr);
@@ -2245,12 +2229,8 @@
   DCHECK(instr->key()->representation().IsTagged());
   DCHECK(instr->value()->representation().IsTagged());
 
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
 
   LStoreKeyedGeneric* result = new (zone())
       LStoreKeyedGeneric(context, object, key, value, slot, vector);
@@ -2364,12 +2344,8 @@
   LOperand* object =
       UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
   LOperand* value = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
 
   LStoreNamedGeneric* result =
       new (zone()) LStoreNamedGeneric(context, object, value, slot, vector);
@@ -2406,14 +2382,19 @@
 
 
 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
-  info()->MarkAsDeferredCalling();
-  LOperand* context = UseAny(instr->context());
-  LOperand* size = instr->size()->IsConstant()
-      ? UseConstant(instr->size())
-      : UseTempRegister(instr->size());
-  LOperand* temp = TempRegister();
-  LAllocate* result = new(zone()) LAllocate(context, size, temp);
-  return AssignPointerMap(DefineAsRegister(result));
+  LOperand* size = instr->size()->IsConstant() ? UseConstant(instr->size())
+                                               : UseRegister(instr->size());
+  if (instr->IsAllocationFolded()) {
+    LOperand* temp = TempRegister();
+    LFastAllocate* result = new (zone()) LFastAllocate(size, temp);
+    return DefineAsRegister(result);
+  } else {
+    info()->MarkAsDeferredCalling();
+    LOperand* context = UseAny(instr->context());
+    LOperand* temp = TempRegister();
+    LAllocate* result = new (zone()) LAllocate(context, size, temp);
+    return AssignPointerMap(DefineAsRegister(result));
+  }
 }
 
 
diff --git a/src/crankshaft/ia32/lithium-ia32.h b/src/crankshaft/ia32/lithium-ia32.h
index 68541a4..7dd22e0 100644
--- a/src/crankshaft/ia32/lithium-ia32.h
+++ b/src/crankshaft/ia32/lithium-ia32.h
@@ -57,7 +57,6 @@
   V(ConstantI)                               \
   V(ConstantS)                               \
   V(ConstantT)                               \
-  V(ConstructDouble)                         \
   V(Context)                                 \
   V(DebugBreak)                              \
   V(DeclareGlobals)                          \
@@ -71,6 +70,7 @@
   V(Drop)                                    \
   V(Dummy)                                   \
   V(DummyUse)                                \
+  V(FastAllocate)                            \
   V(FlooringDivByConstI)                     \
   V(FlooringDivByPowerOf2I)                  \
   V(FlooringDivI)                            \
@@ -82,7 +82,6 @@
   V(HasInPrototypeChainAndBranch)            \
   V(HasInstanceTypeAndBranch)                \
   V(InnerAllocatedObject)                    \
-  V(InstanceOf)                              \
   V(InstructionGap)                          \
   V(Integer32ToDouble)                       \
   V(InvokeFunction)                          \
@@ -102,6 +101,7 @@
   V(LoadRoot)                                \
   V(MathAbs)                                 \
   V(MathClz32)                               \
+  V(MathCos)                                 \
   V(MathExp)                                 \
   V(MathFloorD)                              \
   V(MathFloorI)                              \
@@ -111,6 +111,7 @@
   V(MathPowHalf)                             \
   V(MathRoundD)                              \
   V(MathRoundI)                              \
+  V(MathSin)                                 \
   V(MathSqrt)                                \
   V(MaybeGrowElements)                       \
   V(ModByConstI)                             \
@@ -912,21 +913,29 @@
   DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
 };
 
-
-class LMathExp final : public LTemplateInstruction<1, 1, 2> {
+class LMathCos final : public LTemplateInstruction<1, 1, 0> {
  public:
-  LMathExp(LOperand* value,
-           LOperand* temp1,
-           LOperand* temp2) {
-    inputs_[0] = value;
-    temps_[0] = temp1;
-    temps_[1] = temp2;
-    ExternalReference::InitializeMathExpData();
-  }
+  explicit LMathCos(LOperand* value) { inputs_[0] = value; }
 
   LOperand* value() { return inputs_[0]; }
-  LOperand* temp1() { return temps_[0]; }
-  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
+};
+
+class LMathSin final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathSin(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
+};
+
+class LMathExp final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathExp(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
 };
@@ -1139,22 +1148,6 @@
 };
 
 
-class LInstanceOf final : public LTemplateInstruction<1, 3, 0> {
- public:
-  LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
-    inputs_[0] = context;
-    inputs_[1] = left;
-    inputs_[2] = right;
-  }
-
-  LOperand* context() const { return inputs_[0]; }
-  LOperand* left() const { return inputs_[1]; }
-  LOperand* right() const { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
-};
-
-
 class LHasInPrototypeChainAndBranch final : public LControlInstruction<2, 1> {
  public:
   LHasInPrototypeChainAndBranch(LOperand* object, LOperand* prototype,
@@ -1605,18 +1598,14 @@
   DECLARE_HYDROGEN_ACCESSOR(LoadKeyedGeneric)
 };
 
-
-class LLoadGlobalGeneric final : public LTemplateInstruction<1, 2, 1> {
+class LLoadGlobalGeneric final : public LTemplateInstruction<1, 1, 1> {
  public:
-  LLoadGlobalGeneric(LOperand* context, LOperand* global_object,
-                     LOperand* vector) {
+  LLoadGlobalGeneric(LOperand* context, LOperand* vector) {
     inputs_[0] = context;
-    inputs_[1] = global_object;
     temps_[0] = vector;
   }
 
   LOperand* context() { return inputs_[0]; }
-  LOperand* global_object() { return inputs_[1]; }
   LOperand* temp_vector() { return temps_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
@@ -2371,20 +2360,6 @@
 };
 
 
-class LConstructDouble final : public LTemplateInstruction<1, 2, 0> {
- public:
-  LConstructDouble(LOperand* hi, LOperand* lo) {
-    inputs_[0] = hi;
-    inputs_[1] = lo;
-  }
-
-  LOperand* hi() { return inputs_[0]; }
-  LOperand* lo() { return inputs_[1]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
-};
-
-
 class LAllocate final : public LTemplateInstruction<1, 2, 1> {
  public:
   LAllocate(LOperand* context, LOperand* size, LOperand* temp) {
@@ -2401,6 +2376,19 @@
   DECLARE_HYDROGEN_ACCESSOR(Allocate)
 };
 
+class LFastAllocate final : public LTemplateInstruction<1, 1, 1> {
+ public:
+  LFastAllocate(LOperand* size, LOperand* temp) {
+    inputs_[0] = size;
+    temps_[0] = temp;
+  }
+
+  LOperand* size() const { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(FastAllocate, "fast-allocate")
+  DECLARE_HYDROGEN_ACCESSOR(Allocate)
+};
 
 class LTypeof final : public LTemplateInstruction<1, 2, 0> {
  public:
@@ -2555,6 +2543,8 @@
   LInstruction* DoMathFround(HUnaryMathOperation* instr);
   LInstruction* DoMathAbs(HUnaryMathOperation* instr);
   LInstruction* DoMathLog(HUnaryMathOperation* instr);
+  LInstruction* DoMathCos(HUnaryMathOperation* instr);
+  LInstruction* DoMathSin(HUnaryMathOperation* instr);
   LInstruction* DoMathExp(HUnaryMathOperation* instr);
   LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
   LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
diff --git a/src/crankshaft/lithium-allocator.cc b/src/crankshaft/lithium-allocator.cc
index 6155dc0..d17cd27 100644
--- a/src/crankshaft/lithium-allocator.cc
+++ b/src/crankshaft/lithium-allocator.cc
@@ -13,6 +13,8 @@
 namespace v8 {
 namespace internal {
 
+const auto GetRegConfig = RegisterConfiguration::Crankshaft;
+
 static inline LifetimePosition Min(LifetimePosition a, LifetimePosition b) {
   return a.Value() < b.Value() ? a : b;
 }
@@ -940,7 +942,7 @@
 
         if (instr->ClobbersRegisters()) {
           for (int i = 0; i < Register::kNumRegisters; ++i) {
-            if (Register::from_code(i).IsAllocatable()) {
+            if (GetRegConfig()->IsAllocatableGeneralCode(i)) {
               if (output == NULL || !output->IsRegister() ||
                   output->index() != i) {
                 LiveRange* range = FixedLiveRangeFor(i);
@@ -953,7 +955,7 @@
 
         if (instr->ClobbersDoubleRegisters(isolate())) {
           for (int i = 0; i < DoubleRegister::kMaxNumRegisters; ++i) {
-            if (DoubleRegister::from_code(i).IsAllocatable()) {
+            if (GetRegConfig()->IsAllocatableDoubleCode(i)) {
               if (output == NULL || !output->IsDoubleRegister() ||
                   output->index() != i) {
                 LiveRange* range = FixedDoubleLiveRangeFor(i);
@@ -1460,12 +1462,8 @@
 
 void LAllocator::AllocateGeneralRegisters() {
   LAllocatorPhase phase("L_Allocate general registers", this);
-  num_registers_ =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
-          ->num_allocatable_general_registers();
-  allocatable_register_codes_ =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
-          ->allocatable_general_codes();
+  num_registers_ = GetRegConfig()->num_allocatable_general_registers();
+  allocatable_register_codes_ = GetRegConfig()->allocatable_general_codes();
   mode_ = GENERAL_REGISTERS;
   AllocateRegisters();
 }
@@ -1473,12 +1471,8 @@
 
 void LAllocator::AllocateDoubleRegisters() {
   LAllocatorPhase phase("L_Allocate double registers", this);
-  num_registers_ =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
-          ->num_allocatable_double_registers();
-  allocatable_register_codes_ =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
-          ->allocatable_double_codes();
+  num_registers_ = GetRegConfig()->num_allocatable_double_registers();
+  allocatable_register_codes_ = GetRegConfig()->allocatable_double_codes();
   mode_ = DOUBLE_REGISTERS;
   AllocateRegisters();
 }
@@ -1596,9 +1590,9 @@
 
 const char* LAllocator::RegisterName(int allocation_index) {
   if (mode_ == GENERAL_REGISTERS) {
-    return Register::from_code(allocation_index).ToString();
+    return GetRegConfig()->GetGeneralRegisterName(allocation_index);
   } else {
-    return DoubleRegister::from_code(allocation_index).ToString();
+    return GetRegConfig()->GetDoubleRegisterName(allocation_index);
   }
 }
 
diff --git a/src/crankshaft/lithium-allocator.h b/src/crankshaft/lithium-allocator.h
index b648bd8..ce0e565 100644
--- a/src/crankshaft/lithium-allocator.h
+++ b/src/crankshaft/lithium-allocator.h
@@ -6,6 +6,7 @@
 #define V8_CRANKSHAFT_LITHIUM_ALLOCATOR_H_
 
 #include "src/allocation.h"
+#include "src/base/compiler-specific.h"
 #include "src/crankshaft/compilation-phase.h"
 #include "src/crankshaft/lithium.h"
 #include "src/zone.h"
@@ -327,7 +328,7 @@
  public:
   LAllocator(int first_virtual_register, HGraph* graph);
 
-  static void TraceAlloc(const char* msg, ...);
+  static PRINTF_FORMAT(1, 2) void TraceAlloc(const char* msg, ...);
 
   // Checks whether the value of a given virtual register is tagged.
   bool HasTaggedValue(int virtual_register) const;
diff --git a/src/crankshaft/lithium-codegen.cc b/src/crankshaft/lithium-codegen.cc
index 53fedcf..4bf2100 100644
--- a/src/crankshaft/lithium-codegen.cc
+++ b/src/crankshaft/lithium-codegen.cc
@@ -158,8 +158,9 @@
 
 void LCodeGenBase::DeoptComment(const Deoptimizer::DeoptInfo& deopt_info) {
   SourcePosition position = deopt_info.position;
+  int deopt_id = deopt_info.deopt_id;
   int raw_position = position.IsUnknown() ? 0 : position.raw();
-  masm()->RecordDeoptReason(deopt_info.deopt_reason, raw_position);
+  masm()->RecordDeoptReason(deopt_info.deopt_reason, raw_position, deopt_id);
 }
 
 
@@ -364,13 +365,10 @@
   }
 }
 
-
 Deoptimizer::DeoptInfo LCodeGenBase::MakeDeoptInfo(
-    LInstruction* instr, Deoptimizer::DeoptReason deopt_reason) {
+    LInstruction* instr, Deoptimizer::DeoptReason deopt_reason, int deopt_id) {
   Deoptimizer::DeoptInfo deopt_info(instr->hydrogen_value()->position(),
-                                    instr->Mnemonic(), deopt_reason);
-  HEnterInlined* enter_inlined = instr->environment()->entry();
-  deopt_info.inlining_id = enter_inlined ? enter_inlined->inlining_id() : 0;
+                                    deopt_reason, deopt_id);
   return deopt_info;
 }
 }  // namespace internal
diff --git a/src/crankshaft/lithium-codegen.h b/src/crankshaft/lithium-codegen.h
index b1f7dac..70b8897 100644
--- a/src/crankshaft/lithium-codegen.h
+++ b/src/crankshaft/lithium-codegen.h
@@ -12,6 +12,8 @@
 namespace v8 {
 namespace internal {
 
+class HGraph;
+class LChunk;
 class LEnvironment;
 class LInstruction;
 class LPlatformChunk;
@@ -33,10 +35,10 @@
   LPlatformChunk* chunk() const { return chunk_; }
   HGraph* graph() const;
 
-  void FPRINTF_CHECKING Comment(const char* format, ...);
+  void PRINTF_FORMAT(2, 3) Comment(const char* format, ...);
   void DeoptComment(const Deoptimizer::DeoptInfo& deopt_info);
   static Deoptimizer::DeoptInfo MakeDeoptInfo(
-      LInstruction* instr, Deoptimizer::DeoptReason deopt_reason);
+      LInstruction* instr, Deoptimizer::DeoptReason deopt_reason, int deopt_id);
 
   bool GenerateBody();
   virtual void GenerateBodyInstructionPre(LInstruction* instr) {}
diff --git a/src/crankshaft/lithium.cc b/src/crankshaft/lithium.cc
index d34b04f..4b3e0bc 100644
--- a/src/crankshaft/lithium.cc
+++ b/src/crankshaft/lithium.cc
@@ -40,6 +40,7 @@
 namespace v8 {
 namespace internal {
 
+const auto GetRegConfig = RegisterConfiguration::Crankshaft;
 
 void LOperand::PrintTo(StringStream* stream) {
   LUnallocated* unalloc = NULL;
@@ -63,7 +64,7 @@
             stream->Add("(=invalid_reg#%d)", reg_index);
           } else {
             const char* register_name =
-                Register::from_code(reg_index).ToString();
+                GetRegConfig()->GetGeneralRegisterName(reg_index);
             stream->Add("(=%s)", register_name);
           }
           break;
@@ -74,7 +75,7 @@
             stream->Add("(=invalid_double_reg#%d)", reg_index);
           } else {
             const char* double_register_name =
-                DoubleRegister::from_code(reg_index).ToString();
+                GetRegConfig()->GetDoubleRegisterName(reg_index);
             stream->Add("(=%s)", double_register_name);
           }
           break;
@@ -110,7 +111,8 @@
       if (reg_index < 0 || reg_index >= Register::kNumRegisters) {
         stream->Add("(=invalid_reg#%d|R)", reg_index);
       } else {
-        stream->Add("[%s|R]", Register::from_code(reg_index).ToString());
+        stream->Add("[%s|R]",
+                    GetRegConfig()->GetGeneralRegisterName(reg_index));
       }
       break;
     }
@@ -119,7 +121,7 @@
       if (reg_index < 0 || reg_index >= DoubleRegister::kMaxNumRegisters) {
         stream->Add("(=invalid_double_reg#%d|R)", reg_index);
       } else {
-        stream->Add("[%s|R]", DoubleRegister::from_code(reg_index).ToString());
+        stream->Add("[%s|R]", GetRegConfig()->GetDoubleRegisterName(reg_index));
       }
       break;
     }
@@ -469,8 +471,7 @@
                                                  jit_handler_data));
 
     CodeGenerator::PrintCode(code, info());
-    DCHECK(!(info()->isolate()->serializer_enabled() &&
-             info()->GetMustNotHaveEagerFrame() &&
+    DCHECK(!(info()->GetMustNotHaveEagerFrame() &&
              generator.NeedsEagerFrame()));
     return code;
   }
diff --git a/src/crankshaft/mips/lithium-codegen-mips.cc b/src/crankshaft/mips/lithium-codegen-mips.cc
index f1717ca..30a59fc 100644
--- a/src/crankshaft/mips/lithium-codegen-mips.cc
+++ b/src/crankshaft/mips/lithium-codegen-mips.cc
@@ -34,8 +34,6 @@
 #include "src/crankshaft/mips/lithium-gap-resolver-mips.h"
 #include "src/ic/ic.h"
 #include "src/ic/stub-cache.h"
-#include "src/profiler/cpu-profiler.h"
-
 
 namespace v8 {
 namespace internal {
@@ -330,8 +328,6 @@
       } else {
         __ Call(&call_deopt_entry);
       }
-      info()->LogDeoptCallPosition(masm()->pc_offset(),
-                                   table_entry->deopt_info.inlining_id);
     }
 
     if (needs_frame.is_linked()) {
@@ -789,7 +785,7 @@
     __ bind(&skip);
   }
 
-  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason);
+  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason, id);
 
   DCHECK(info()->IsStub() || frame_is_built_);
   // Go through jump table if we need to handle condition, build frame, or
@@ -798,13 +794,12 @@
       !info()->saves_caller_doubles()) {
     DeoptComment(deopt_info);
     __ Call(entry, RelocInfo::RUNTIME_ENTRY, condition, src1, src2);
-    info()->LogDeoptCallPosition(masm()->pc_offset(), deopt_info.inlining_id);
   } else {
     Deoptimizer::JumpTableEntry table_entry(entry, deopt_info, bailout_type,
                                             !frame_is_built_);
     // We often have several deopts to the same entry, reuse the last
     // jump entry if this is the case.
-    if (FLAG_trace_deopt || isolate()->cpu_profiler()->is_profiling() ||
+    if (FLAG_trace_deopt || isolate()->is_profiling() ||
         jump_table_.is_empty() ||
         !table_entry.IsEquivalentTo(jump_table_.last())) {
       jump_table_.Add(table_entry, zone());
@@ -880,7 +875,6 @@
 void LCodeGen::RecordAndWritePosition(int position) {
   if (position == RelocInfo::kNoPosition) return;
   masm()->positions_recorder()->RecordPosition(position);
-  masm()->positions_recorder()->WriteRecordedPositions();
 }
 
 
@@ -1728,13 +1722,13 @@
   LOperand* left = instr->left();
   LOperand* right = instr->right();
   HMathMinMax::Operation operation = instr->hydrogen()->operation();
-  Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge;
+  Register scratch = scratch1();
   if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
+    Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge;
     Register left_reg = ToRegister(left);
     Register right_reg = EmitLoadRegister(right, scratch0());
     Register result_reg = ToRegister(instr->result());
     Label return_right, done;
-    Register scratch = scratch1();
     __ Slt(scratch, left_reg, Operand(right_reg));
     if (condition == ge) {
      __  Movz(result_reg, left_reg, scratch);
@@ -1749,43 +1743,19 @@
     FPURegister left_reg = ToDoubleRegister(left);
     FPURegister right_reg = ToDoubleRegister(right);
     FPURegister result_reg = ToDoubleRegister(instr->result());
-    Label check_nan_left, check_zero, return_left, return_right, done;
-    __ BranchF(&check_zero, &check_nan_left, eq, left_reg, right_reg);
-    __ BranchF(&return_left, NULL, condition, left_reg, right_reg);
-    __ Branch(&return_right);
-
-    __ bind(&check_zero);
-    // left == right != 0.
-    __ BranchF(&return_left, NULL, ne, left_reg, kDoubleRegZero);
-    // At this point, both left and right are either 0 or -0.
-    if (operation == HMathMinMax::kMathMin) {
-      // The algorithm is: -((-L) + (-R)), which in case of L and R being
-      // different registers is most efficiently expressed as -((-L) - R).
-      __ neg_d(left_reg, left_reg);
-      if (left_reg.is(right_reg)) {
-        __ add_d(result_reg, left_reg, right_reg);
-      } else {
-        __ sub_d(result_reg, left_reg, right_reg);
-      }
-      __ neg_d(result_reg, result_reg);
+    Label nan, done;
+    if (operation == HMathMinMax::kMathMax) {
+      __ MaxNaNCheck_d(result_reg, left_reg, right_reg, &nan);
     } else {
-      __ add_d(result_reg, left_reg, right_reg);
+      DCHECK(operation == HMathMinMax::kMathMin);
+      __ MinNaNCheck_d(result_reg, left_reg, right_reg, &nan);
     }
     __ Branch(&done);
 
-    __ bind(&check_nan_left);
-    // left == NaN.
-    __ BranchF(NULL, &return_left, eq, left_reg, left_reg);
-    __ bind(&return_right);
-    if (!right_reg.is(result_reg)) {
-      __ mov_d(result_reg, right_reg);
-    }
-    __ Branch(&done);
+    __ bind(&nan);
+    __ LoadRoot(scratch, Heap::kNanValueRootIndex);
+    __ ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset));
 
-    __ bind(&return_left);
-    if (!left_reg.is(result_reg)) {
-      __ mov_d(result_reg, left_reg);
-    }
     __ bind(&done);
   }
 }
@@ -2409,16 +2379,6 @@
 }
 
 
-void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
-  DCHECK(ToRegister(instr->context()).is(cp));
-  DCHECK(ToRegister(instr->left()).is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(ToRegister(instr->right()).is(InstanceOfDescriptor::RightRegister()));
-  DCHECK(ToRegister(instr->result()).is(v0));
-  InstanceOfStub stub(isolate());
-  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
-}
-
-
 void LCodeGen::DoHasInPrototypeChainAndBranch(
     LHasInPrototypeChainAndBranch* instr) {
   Register const object = ToRegister(instr->object());
@@ -2454,9 +2414,9 @@
                Operand(JS_PROXY_TYPE));
 
   __ lw(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset));
-  EmitTrueBranch(instr, eq, object_prototype, Operand(prototype));
   __ LoadRoot(at, Heap::kNullValueRootIndex);
   EmitFalseBranch(instr, eq, object_prototype, Operand(at));
+  EmitTrueBranch(instr, eq, object_prototype, Operand(prototype));
   __ Branch(USE_DELAY_SLOT, &loop);
   __ lw(object_map, FieldMemOperand(object_prototype, HeapObject::kMapOffset));
 }
@@ -2552,15 +2512,12 @@
 
 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   DCHECK(ToRegister(instr->context()).is(cp));
-  DCHECK(ToRegister(instr->global_object())
-             .is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->result()).is(v0));
 
-  __ li(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), instr->typeof_mode(), PREMONOMORPHIC)
-                        .code();
+  Handle<Code> ic =
+      CodeFactory::LoadGlobalICInOptimizedCode(isolate(), instr->typeof_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2659,10 +2616,7 @@
   // Name is always in a2.
   __ li(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_INSIDE_TYPEOF,
-                        instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2967,13 +2921,9 @@
   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
-  }
+  EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
 
-  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
-                        isolate(), instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3536,26 +3486,32 @@
   }
 }
 
+void LCodeGen::DoMathCos(LMathCos* instr) {
+  __ PrepareCallCFunction(0, 1, scratch0());
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
+  __ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 0, 1);
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
+}
+
+void LCodeGen::DoMathSin(LMathSin* instr) {
+  __ PrepareCallCFunction(0, 1, scratch0());
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
+  __ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 0, 1);
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
+}
 
 void LCodeGen::DoMathExp(LMathExp* instr) {
-  DoubleRegister input = ToDoubleRegister(instr->value());
-  DoubleRegister result = ToDoubleRegister(instr->result());
-  DoubleRegister double_scratch1 = ToDoubleRegister(instr->double_temp());
-  DoubleRegister double_scratch2 = double_scratch0();
-  Register temp1 = ToRegister(instr->temp1());
-  Register temp2 = ToRegister(instr->temp2());
-
-  MathExpGenerator::EmitMathExp(
-      masm(), input, result, double_scratch1, double_scratch2,
-      temp1, temp2, scratch0());
+  __ PrepareCallCFunction(0, 1, scratch0());
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
+  __ CallCFunction(ExternalReference::ieee754_exp_function(isolate()), 0, 1);
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
 }
 
 
 void LCodeGen::DoMathLog(LMathLog* instr) {
   __ PrepareCallCFunction(0, 1, scratch0());
   __ MovToFloatParameter(ToDoubleRegister(instr->value()));
-  __ CallCFunction(ExternalReference::math_log_double_function(isolate()),
-                   0, 1);
+  __ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
   __ MovFromFloatResult(ToDoubleRegister(instr->result()));
 }
 
@@ -3578,7 +3534,9 @@
 #endif
   if (FLAG_code_comments) {
     if (actual.is_reg()) {
-      Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString());
+      Comment(";;; PrepareForTailCall, actual: %s {",
+              RegisterConfiguration::Crankshaft()->GetGeneralRegisterName(
+                  actual.reg().code()));
     } else {
       Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate());
     }
@@ -3685,14 +3643,8 @@
   DCHECK(ToRegister(instr->result()).is(v0));
 
   __ li(a0, Operand(instr->arity()));
-  if (instr->arity() == 1) {
-    // We only need the allocation site for the case we have a length argument.
-    // The case may bail out to the runtime, which will determine the correct
-    // elements kind with the site.
-    __ li(a2, instr->hydrogen()->site());
-  } else {
-    __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
-  }
+  __ li(a2, instr->hydrogen()->site());
+
   ElementsKind kind = instr->hydrogen()->elements_kind();
   AllocationSiteOverrideMode override_mode =
       (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
@@ -3724,7 +3676,7 @@
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
     __ bind(&done);
   } else {
-    ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
+    ArrayNArgumentsConstructorStub stub(isolate());
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   }
 }
@@ -3846,14 +3798,12 @@
   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
 
   __ li(StoreDescriptor::NameRegister(), Operand(instr->name()));
-  Handle<Code> ic = CodeFactory::StoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic =
+      CodeFactory::StoreICInOptimizedCode(isolate(), instr->language_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -4074,13 +4024,11 @@
   DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
 
   Handle<Code> ic = CodeFactory::KeyedStoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state()).code();
+                        isolate(), instr->language_mode())
+                        .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -4159,7 +4107,15 @@
 
     LOperand* key = instr->key();
     if (key->IsConstantOperand()) {
-      __ li(a3, Operand(ToSmi(LConstantOperand::cast(key))));
+      LConstantOperand* constant_key = LConstantOperand::cast(key);
+      int32_t int_key = ToInteger32(constant_key);
+      if (Smi::IsValid(int_key)) {
+        __ li(a3, Operand(Smi::FromInt(int_key)));
+      } else {
+        // We should never get here at runtime because there is a smi check on
+        // the key before this point.
+        __ stop("expected smi");
+      }
     } else {
       __ mov(a3, ToRegister(key));
       __ SmiTag(a3);
@@ -4208,8 +4164,7 @@
     DCHECK(ToRegister(instr->context()).is(cp));
     PushSafepointRegistersScope scope(this);
     __ li(a1, Operand(to_map));
-    bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
-    TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
+    TransitionElementsKindStub stub(isolate(), from_kind, to_kind);
     __ CallStub(&stub);
     RecordSafepointWithRegisters(
         instr->pointer_map(), 0, Safepoint::kLazyDeopt);
@@ -4456,7 +4411,7 @@
 
   if (FLAG_inline_new) {
     __ LoadRoot(tmp3, Heap::kHeapNumberMapRootIndex);
-    __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow, DONT_TAG_RESULT);
+    __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow);
     __ Branch(&done);
   }
 
@@ -4480,16 +4435,13 @@
     __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
     RecordSafepointWithRegisters(
         instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
-    __ Subu(v0, v0, kHeapObjectTag);
     __ StoreToSafepointRegisterSlot(v0, dst);
   }
 
-
   // Done. Put the value in dbl_scratch into the value of the allocated heap
   // number.
   __ bind(&done);
-  __ sdc1(dbl_scratch, MemOperand(dst, HeapNumber::kValueOffset));
-  __ Addu(dst, dst, kHeapObjectTag);
+  __ sdc1(dbl_scratch, FieldMemOperand(dst, HeapNumber::kValueOffset));
 }
 
 
@@ -4514,16 +4466,13 @@
   DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr);
   if (FLAG_inline_new) {
     __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
-    // We want the untagged address first for performance
-    __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(),
-                          DONT_TAG_RESULT);
+    __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry());
   } else {
     __ Branch(deferred->entry());
   }
   __ bind(deferred->exit());
-  __ sdc1(input_reg, MemOperand(reg, HeapNumber::kValueOffset));
+  __ sdc1(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset));
   // Now that we have finished with the object's real address tag it
-  __ Addu(reg, reg, kHeapObjectTag);
 }
 
 
@@ -4544,7 +4493,6 @@
   __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
   RecordSafepointWithRegisters(
       instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
-  __ Subu(v0, v0, kHeapObjectTag);
   __ StoreToSafepointRegisterSlot(v0, reg);
 }
 
@@ -5064,14 +5012,6 @@
 }
 
 
-void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
-  Register hi_reg = ToRegister(instr->hi());
-  Register lo_reg = ToRegister(instr->lo());
-  DoubleRegister result_reg = ToDoubleRegister(instr->result());
-  __ Move(result_reg, lo_reg, hi_reg);
-}
-
-
 void LCodeGen::DoAllocate(LAllocate* instr) {
   class DeferredAllocate final : public LDeferredCode {
    public:
@@ -5092,7 +5032,7 @@
   Register scratch2 = ToRegister(instr->temp2());
 
   // Allocate memory for the object.
-  AllocationFlags flags = TAG_OBJECT;
+  AllocationFlags flags = NO_ALLOCATION_FLAGS;
   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
   }
@@ -5100,6 +5040,12 @@
     DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
     flags = static_cast<AllocationFlags>(flags | PRETENURE);
   }
+
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    flags = static_cast<AllocationFlags>(flags | ALLOCATION_FOLDING_DOMINATOR);
+  }
+  DCHECK(!instr->hydrogen()->IsAllocationFolded());
+
   if (instr->size()->IsConstantOperand()) {
     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
     CHECK(size <= Page::kMaxRegularHeapObjectSize);
@@ -5168,6 +5114,49 @@
   CallRuntimeFromDeferred(
       Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
   __ StoreToSafepointRegisterSlot(v0, result);
+
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    AllocationFlags allocation_flags = NO_ALLOCATION_FLAGS;
+    if (instr->hydrogen()->IsOldSpaceAllocation()) {
+      DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+      allocation_flags = static_cast<AllocationFlags>(flags | PRETENURE);
+    }
+    // If the allocation folding dominator allocate triggered a GC, allocation
+    // happend in the runtime. We have to reset the top pointer to virtually
+    // undo the allocation.
+    ExternalReference allocation_top =
+        AllocationUtils::GetAllocationTopReference(isolate(), allocation_flags);
+    Register top_address = scratch0();
+    __ Subu(v0, v0, Operand(kHeapObjectTag));
+    __ li(top_address, Operand(allocation_top));
+    __ sw(v0, MemOperand(top_address));
+    __ Addu(v0, v0, Operand(kHeapObjectTag));
+  }
+}
+
+void LCodeGen::DoFastAllocate(LFastAllocate* instr) {
+  DCHECK(instr->hydrogen()->IsAllocationFolded());
+  DCHECK(!instr->hydrogen()->IsAllocationFoldingDominator());
+  Register result = ToRegister(instr->result());
+  Register scratch1 = ToRegister(instr->temp1());
+  Register scratch2 = ToRegister(instr->temp2());
+
+  AllocationFlags flags = ALLOCATION_FOLDED;
+  if (instr->hydrogen()->MustAllocateDoubleAligned()) {
+    flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
+  }
+  if (instr->hydrogen()->IsOldSpaceAllocation()) {
+    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+    flags = static_cast<AllocationFlags>(flags | PRETENURE);
+  }
+  if (instr->size()->IsConstantOperand()) {
+    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
+    CHECK(size <= Page::kMaxRegularHeapObjectSize);
+    __ FastAllocate(size, result, scratch1, scratch2, flags);
+  } else {
+    Register size = ToRegister(instr->size());
+    __ FastAllocate(size, result, scratch1, scratch2, flags);
+  }
 }
 
 
diff --git a/src/crankshaft/mips/lithium-codegen-mips.h b/src/crankshaft/mips/lithium-codegen-mips.h
index 7a316e5..d2b0d2d 100644
--- a/src/crankshaft/mips/lithium-codegen-mips.h
+++ b/src/crankshaft/mips/lithium-codegen-mips.h
@@ -134,8 +134,6 @@
 #undef DECLARE_DO
 
  private:
-  LanguageMode language_mode() const { return info()->language_mode(); }
-
   Scope* scope() const { return scope_; }
 
   Register scratch0() { return kLithiumScratchReg; }
diff --git a/src/crankshaft/mips/lithium-mips.cc b/src/crankshaft/mips/lithium-mips.cc
index 71c34df..e706620 100644
--- a/src/crankshaft/mips/lithium-mips.cc
+++ b/src/crankshaft/mips/lithium-mips.cc
@@ -887,7 +887,7 @@
 
 LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) {
   LInstruction* result = new (zone()) LPrologue();
-  if (info_->num_heap_slots() > 0) {
+  if (info_->scope()->num_heap_slots() > 0) {
     result = MarkAsCall(result, instr);
   }
   return result;
@@ -939,17 +939,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
-  LOperand* left =
-      UseFixed(instr->left(), InstanceOfDescriptor::LeftRegister());
-  LOperand* right =
-      UseFixed(instr->right(), InstanceOfDescriptor::RightRegister());
-  LOperand* context = UseFixed(instr->context(), cp);
-  LInstanceOf* result = new (zone()) LInstanceOf(context, left, right);
-  return MarkAsCall(DefineFixed(result, v0), instr);
-}
-
-
 LInstruction* LChunkBuilder::DoHasInPrototypeChainAndBranch(
     HHasInPrototypeChainAndBranch* instr) {
   LOperand* object = UseRegister(instr->object());
@@ -1085,6 +1074,10 @@
       return DoMathAbs(instr);
     case kMathLog:
       return DoMathLog(instr);
+    case kMathCos:
+      return DoMathCos(instr);
+    case kMathSin:
+      return DoMathSin(instr);
     case kMathExp:
       return DoMathExp(instr);
     case kMathSqrt:
@@ -1114,16 +1107,25 @@
   return DefineAsRegister(result);
 }
 
+LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
+  DCHECK(instr->representation().IsDouble());
+  DCHECK(instr->value()->representation().IsDouble());
+  LOperand* input = UseFixedDouble(instr->value(), f4);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathCos(input), f4), instr);
+}
+
+LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
+  DCHECK(instr->representation().IsDouble());
+  DCHECK(instr->value()->representation().IsDouble());
+  LOperand* input = UseFixedDouble(instr->value(), f4);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathSin(input), f4), instr);
+}
 
 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
   DCHECK(instr->representation().IsDouble());
   DCHECK(instr->value()->representation().IsDouble());
-  LOperand* input = UseRegister(instr->value());
-  LOperand* temp1 = TempRegister();
-  LOperand* temp2 = TempRegister();
-  LOperand* double_temp = TempDoubleRegister();
-  LMathExp* result = new(zone()) LMathExp(input, double_temp, temp1, temp2);
-  return DefineAsRegister(result);
+  LOperand* input = UseFixedDouble(instr->value(), f4);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathExp(input), f4), instr);
 }
 
 
@@ -1932,13 +1934,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
-  LOperand* lo = UseRegister(instr->lo());
-  LOperand* hi = UseRegister(instr->hi());
-  return DefineAsRegister(new(zone()) LConstructDouble(hi, lo));
-}
-
-
 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
   LOperand* context = info()->IsStub()
       ? UseFixed(instr->context(), cp)
@@ -1970,14 +1965,9 @@
 
 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
-  LOperand* global_object =
-      UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
-  LLoadGlobalGeneric* result =
-      new(zone()) LLoadGlobalGeneric(context, global_object, vector);
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
+
+  LLoadGlobalGeneric* result = new (zone()) LLoadGlobalGeneric(context, vector);
   return MarkAsCall(DefineFixed(result, v0), instr);
 }
 
@@ -2021,10 +2011,7 @@
   LOperand* context = UseFixed(instr->context(), cp);
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
   LInstruction* result =
       DefineFixed(new(zone()) LLoadNamedGeneric(context, object, vector), v0);
@@ -2096,10 +2083,7 @@
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
   LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
   LInstruction* result =
       DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key, vector),
@@ -2161,12 +2145,8 @@
   DCHECK(instr->key()->representation().IsTagged());
   DCHECK(instr->value()->representation().IsTagged());
 
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
 
   LStoreKeyedGeneric* result =
       new (zone()) LStoreKeyedGeneric(context, obj, key, val, slot, vector);
@@ -2255,12 +2235,8 @@
   LOperand* obj =
       UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
   LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
 
   LStoreNamedGeneric* result =
       new (zone()) LStoreNamedGeneric(context, obj, val, slot, vector);
@@ -2298,13 +2274,18 @@
 
 
 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
-  info()->MarkAsDeferredCalling();
-  LOperand* context = UseAny(instr->context());
   LOperand* size = UseRegisterOrConstant(instr->size());
   LOperand* temp1 = TempRegister();
   LOperand* temp2 = TempRegister();
-  LAllocate* result = new(zone()) LAllocate(context, size, temp1, temp2);
-  return AssignPointerMap(DefineAsRegister(result));
+  if (instr->IsAllocationFolded()) {
+    LFastAllocate* result = new (zone()) LFastAllocate(size, temp1, temp2);
+    return DefineAsRegister(result);
+  } else {
+    info()->MarkAsDeferredCalling();
+    LOperand* context = UseAny(instr->context());
+    LAllocate* result = new (zone()) LAllocate(context, size, temp1, temp2);
+    return AssignPointerMap(DefineAsRegister(result));
+  }
 }
 
 
diff --git a/src/crankshaft/mips/lithium-mips.h b/src/crankshaft/mips/lithium-mips.h
index 7d41093..f220a15 100644
--- a/src/crankshaft/mips/lithium-mips.h
+++ b/src/crankshaft/mips/lithium-mips.h
@@ -53,7 +53,6 @@
   V(ConstantI)                               \
   V(ConstantS)                               \
   V(ConstantT)                               \
-  V(ConstructDouble)                         \
   V(Context)                                 \
   V(DebugBreak)                              \
   V(DeclareGlobals)                          \
@@ -67,6 +66,7 @@
   V(Drop)                                    \
   V(Dummy)                                   \
   V(DummyUse)                                \
+  V(FastAllocate)                            \
   V(FlooringDivByConstI)                     \
   V(FlooringDivByPowerOf2I)                  \
   V(FlooringDivI)                            \
@@ -78,7 +78,6 @@
   V(HasInPrototypeChainAndBranch)            \
   V(HasInstanceTypeAndBranch)                \
   V(InnerAllocatedObject)                    \
-  V(InstanceOf)                              \
   V(InstructionGap)                          \
   V(Integer32ToDouble)                       \
   V(InvokeFunction)                          \
@@ -97,6 +96,8 @@
   V(LoadNamedField)                          \
   V(LoadNamedGeneric)                        \
   V(MathAbs)                                 \
+  V(MathCos)                                 \
+  V(MathSin)                                 \
   V(MathExp)                                 \
   V(MathClz32)                               \
   V(MathFloor)                               \
@@ -882,24 +883,29 @@
   DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
 };
 
-
-class LMathExp final : public LTemplateInstruction<1, 1, 3> {
+class LMathCos final : public LTemplateInstruction<1, 1, 0> {
  public:
-  LMathExp(LOperand* value,
-           LOperand* double_temp,
-           LOperand* temp1,
-           LOperand* temp2) {
-    inputs_[0] = value;
-    temps_[0] = temp1;
-    temps_[1] = temp2;
-    temps_[2] = double_temp;
-    ExternalReference::InitializeMathExpData();
-  }
+  explicit LMathCos(LOperand* value) { inputs_[0] = value; }
 
   LOperand* value() { return inputs_[0]; }
-  LOperand* temp1() { return temps_[0]; }
-  LOperand* temp2() { return temps_[1]; }
-  LOperand* double_temp() { return temps_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
+};
+
+class LMathSin final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathSin(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
+};
+
+class LMathExp final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathExp(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
 };
@@ -1113,22 +1119,6 @@
 };
 
 
-class LInstanceOf final : public LTemplateInstruction<1, 3, 0> {
- public:
-  LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
-    inputs_[0] = context;
-    inputs_[1] = left;
-    inputs_[2] = right;
-  }
-
-  LOperand* context() const { return inputs_[0]; }
-  LOperand* left() const { return inputs_[1]; }
-  LOperand* right() const { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
-};
-
-
 class LHasInPrototypeChainAndBranch final : public LControlInstruction<2, 0> {
  public:
   LHasInPrototypeChainAndBranch(LOperand* object, LOperand* prototype) {
@@ -1547,18 +1537,14 @@
   DECLARE_HYDROGEN_ACCESSOR(LoadKeyedGeneric)
 };
 
-
-class LLoadGlobalGeneric final : public LTemplateInstruction<1, 2, 1> {
+class LLoadGlobalGeneric final : public LTemplateInstruction<1, 1, 1> {
  public:
-  LLoadGlobalGeneric(LOperand* context, LOperand* global_object,
-                     LOperand* vector) {
+  LLoadGlobalGeneric(LOperand* context, LOperand* vector) {
     inputs_[0] = context;
-    inputs_[1] = global_object;
     temps_[0] = vector;
   }
 
   LOperand* context() { return inputs_[0]; }
-  LOperand* global_object() { return inputs_[1]; }
   LOperand* temp_vector() { return temps_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
@@ -2315,20 +2301,6 @@
 };
 
 
-class LConstructDouble final : public LTemplateInstruction<1, 2, 0> {
- public:
-  LConstructDouble(LOperand* hi, LOperand* lo) {
-    inputs_[0] = hi;
-    inputs_[1] = lo;
-  }
-
-  LOperand* hi() { return inputs_[0]; }
-  LOperand* lo() { return inputs_[1]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
-};
-
-
 class LAllocate final : public LTemplateInstruction<1, 2, 2> {
  public:
   LAllocate(LOperand* context,
@@ -2350,6 +2322,21 @@
   DECLARE_HYDROGEN_ACCESSOR(Allocate)
 };
 
+class LFastAllocate final : public LTemplateInstruction<1, 1, 2> {
+ public:
+  LFastAllocate(LOperand* size, LOperand* temp1, LOperand* temp2) {
+    inputs_[0] = size;
+    temps_[0] = temp1;
+    temps_[1] = temp2;
+  }
+
+  LOperand* size() { return inputs_[0]; }
+  LOperand* temp1() { return temps_[0]; }
+  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(FastAllocate, "fast-allocate")
+  DECLARE_HYDROGEN_ACCESSOR(Allocate)
+};
 
 class LTypeof final : public LTemplateInstruction<1, 2, 0> {
  public:
@@ -2504,6 +2491,8 @@
   LInstruction* DoMathFround(HUnaryMathOperation* instr);
   LInstruction* DoMathAbs(HUnaryMathOperation* instr);
   LInstruction* DoMathLog(HUnaryMathOperation* instr);
+  LInstruction* DoMathCos(HUnaryMathOperation* instr);
+  LInstruction* DoMathSin(HUnaryMathOperation* instr);
   LInstruction* DoMathExp(HUnaryMathOperation* instr);
   LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
   LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
diff --git a/src/crankshaft/mips64/lithium-codegen-mips64.cc b/src/crankshaft/mips64/lithium-codegen-mips64.cc
index c7bbe9f..41ed95e 100644
--- a/src/crankshaft/mips64/lithium-codegen-mips64.cc
+++ b/src/crankshaft/mips64/lithium-codegen-mips64.cc
@@ -10,7 +10,6 @@
 #include "src/crankshaft/mips64/lithium-gap-resolver-mips64.h"
 #include "src/ic/ic.h"
 #include "src/ic/stub-cache.h"
-#include "src/profiler/cpu-profiler.h"
 
 namespace v8 {
 namespace internal {
@@ -315,8 +314,6 @@
           __ BranchAndLink(&call_deopt_entry);
         }
       }
-      info()->LogDeoptCallPosition(masm()->pc_offset(),
-                                   table_entry->deopt_info.inlining_id);
     }
     if (needs_frame.is_linked()) {
       __ bind(&needs_frame);
@@ -776,7 +773,7 @@
     __ bind(&skip);
   }
 
-  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason);
+  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason, id);
 
   DCHECK(info()->IsStub() || frame_is_built_);
   // Go through jump table if we need to handle condition, build frame, or
@@ -785,14 +782,13 @@
       !info()->saves_caller_doubles()) {
     DeoptComment(deopt_info);
     __ Call(entry, RelocInfo::RUNTIME_ENTRY, condition, src1, src2);
-    info()->LogDeoptCallPosition(masm()->pc_offset(), deopt_info.inlining_id);
   } else {
     Deoptimizer::JumpTableEntry* table_entry =
         new (zone()) Deoptimizer::JumpTableEntry(
             entry, deopt_info, bailout_type, !frame_is_built_);
     // We often have several deopts to the same entry, reuse the last
     // jump entry if this is the case.
-    if (FLAG_trace_deopt || isolate()->cpu_profiler()->is_profiling() ||
+    if (FLAG_trace_deopt || isolate()->is_profiling() ||
         jump_table_.is_empty() ||
         !table_entry->IsEquivalentTo(*jump_table_.last())) {
       jump_table_.Add(table_entry, zone());
@@ -868,7 +864,6 @@
 void LCodeGen::RecordAndWritePosition(int position) {
   if (position == RelocInfo::kNoPosition) return;
   masm()->positions_recorder()->RecordPosition(position);
-  masm()->positions_recorder()->WriteRecordedPositions();
 }
 
 
@@ -1170,7 +1165,7 @@
   DCHECK(!result.is(dividend) || !scratch.is(dividend));
 
   // If the divisor is 1, return the dividend.
-  if (divisor == 1) {
+  if (divisor == 0) {
     __ Move(result, dividend);
     return;
   }
@@ -1846,13 +1841,13 @@
   LOperand* left = instr->left();
   LOperand* right = instr->right();
   HMathMinMax::Operation operation = instr->hydrogen()->operation();
-  Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge;
+  Register scratch = scratch1();
   if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
+    Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge;
     Register left_reg = ToRegister(left);
     Register right_reg = EmitLoadRegister(right, scratch0());
     Register result_reg = ToRegister(instr->result());
     Label return_right, done;
-    Register scratch = scratch1();
     __ Slt(scratch, left_reg, Operand(right_reg));
     if (condition == ge) {
      __  Movz(result_reg, left_reg, scratch);
@@ -1867,43 +1862,19 @@
     FPURegister left_reg = ToDoubleRegister(left);
     FPURegister right_reg = ToDoubleRegister(right);
     FPURegister result_reg = ToDoubleRegister(instr->result());
-    Label check_nan_left, check_zero, return_left, return_right, done;
-    __ BranchF(&check_zero, &check_nan_left, eq, left_reg, right_reg);
-    __ BranchF(&return_left, NULL, condition, left_reg, right_reg);
-    __ Branch(&return_right);
-
-    __ bind(&check_zero);
-    // left == right != 0.
-    __ BranchF(&return_left, NULL, ne, left_reg, kDoubleRegZero);
-    // At this point, both left and right are either 0 or -0.
-    if (operation == HMathMinMax::kMathMin) {
-      // The algorithm is: -((-L) + (-R)), which in case of L and R being
-      // different registers is most efficiently expressed as -((-L) - R).
-      __ neg_d(left_reg, left_reg);
-      if (left_reg.is(right_reg)) {
-        __ add_d(result_reg, left_reg, right_reg);
-      } else {
-        __ sub_d(result_reg, left_reg, right_reg);
-      }
-      __ neg_d(result_reg, result_reg);
+    Label nan, done;
+    if (operation == HMathMinMax::kMathMax) {
+      __ MaxNaNCheck_d(result_reg, left_reg, right_reg, &nan);
     } else {
-      __ add_d(result_reg, left_reg, right_reg);
+      DCHECK(operation == HMathMinMax::kMathMin);
+      __ MinNaNCheck_d(result_reg, left_reg, right_reg, &nan);
     }
     __ Branch(&done);
 
-    __ bind(&check_nan_left);
-    // left == NaN.
-    __ BranchF(NULL, &return_left, eq, left_reg, left_reg);
-    __ bind(&return_right);
-    if (!right_reg.is(result_reg)) {
-      __ mov_d(result_reg, right_reg);
-    }
-    __ Branch(&done);
+    __ bind(&nan);
+    __ LoadRoot(scratch, Heap::kNanValueRootIndex);
+    __ ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset));
 
-    __ bind(&return_left);
-    if (!left_reg.is(result_reg)) {
-      __ mov_d(result_reg, left_reg);
-    }
     __ bind(&done);
   }
 }
@@ -2529,18 +2500,6 @@
 }
 
 
-void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
-  DCHECK(ToRegister(instr->context()).is(cp));
-  Label true_label, done;
-  DCHECK(ToRegister(instr->left()).is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(ToRegister(instr->right()).is(InstanceOfDescriptor::RightRegister()));
-  DCHECK(ToRegister(instr->result()).is(v0));
-
-  InstanceOfStub stub(isolate());
-  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
-}
-
-
 void LCodeGen::DoHasInPrototypeChainAndBranch(
     LHasInPrototypeChainAndBranch* instr) {
   Register const object = ToRegister(instr->object());
@@ -2575,9 +2534,9 @@
                Operand(JS_PROXY_TYPE));
 
   __ ld(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset));
-  EmitTrueBranch(instr, eq, object_prototype, Operand(prototype));
   __ LoadRoot(at, Heap::kNullValueRootIndex);
   EmitFalseBranch(instr, eq, object_prototype, Operand(at));
+  EmitTrueBranch(instr, eq, object_prototype, Operand(prototype));
   __ Branch(&loop, USE_DELAY_SLOT);
   __ ld(object_map, FieldMemOperand(object_prototype,
                                     HeapObject::kMapOffset));  // In delay slot.
@@ -2674,15 +2633,12 @@
 
 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   DCHECK(ToRegister(instr->context()).is(cp));
-  DCHECK(ToRegister(instr->global_object())
-            .is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->result()).is(v0));
 
-  __ li(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), instr->typeof_mode(), PREMONOMORPHIC)
-                        .code();
+  Handle<Code> ic =
+      CodeFactory::LoadGlobalICInOptimizedCode(isolate(), instr->typeof_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2796,10 +2752,7 @@
   // Name is always in a2.
   __ li(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_INSIDE_TYPEOF,
-                        instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3148,13 +3101,9 @@
   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
-  }
+  EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
 
-  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
-                        isolate(), instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3740,26 +3689,32 @@
   }
 }
 
+void LCodeGen::DoMathCos(LMathCos* instr) {
+  __ PrepareCallCFunction(0, 1, scratch0());
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
+  __ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 0, 1);
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
+}
+
+void LCodeGen::DoMathSin(LMathSin* instr) {
+  __ PrepareCallCFunction(0, 1, scratch0());
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
+  __ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 0, 1);
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
+}
 
 void LCodeGen::DoMathExp(LMathExp* instr) {
-  DoubleRegister input = ToDoubleRegister(instr->value());
-  DoubleRegister result = ToDoubleRegister(instr->result());
-  DoubleRegister double_scratch1 = ToDoubleRegister(instr->double_temp());
-  DoubleRegister double_scratch2 = double_scratch0();
-  Register temp1 = ToRegister(instr->temp1());
-  Register temp2 = ToRegister(instr->temp2());
-
-  MathExpGenerator::EmitMathExp(
-      masm(), input, result, double_scratch1, double_scratch2,
-      temp1, temp2, scratch0());
+  __ PrepareCallCFunction(0, 1, scratch0());
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
+  __ CallCFunction(ExternalReference::ieee754_exp_function(isolate()), 0, 1);
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
 }
 
 
 void LCodeGen::DoMathLog(LMathLog* instr) {
   __ PrepareCallCFunction(0, 1, scratch0());
   __ MovToFloatParameter(ToDoubleRegister(instr->value()));
-  __ CallCFunction(ExternalReference::math_log_double_function(isolate()),
-                   0, 1);
+  __ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
   __ MovFromFloatResult(ToDoubleRegister(instr->result()));
 }
 
@@ -3782,7 +3737,9 @@
 #endif
   if (FLAG_code_comments) {
     if (actual.is_reg()) {
-      Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString());
+      Comment(";;; PrepareForTailCall, actual: %s {",
+              RegisterConfiguration::Crankshaft()->GetGeneralRegisterName(
+                  actual.reg().code()));
     } else {
       Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate());
     }
@@ -3886,14 +3843,8 @@
   DCHECK(ToRegister(instr->result()).is(v0));
 
   __ li(a0, Operand(instr->arity()));
-  if (instr->arity() == 1) {
-    // We only need the allocation site for the case we have a length argument.
-    // The case may bail out to the runtime, which will determine the correct
-    // elements kind with the site.
-    __ li(a2, instr->hydrogen()->site());
-  } else {
-    __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
-  }
+  __ li(a2, instr->hydrogen()->site());
+
   ElementsKind kind = instr->hydrogen()->elements_kind();
   AllocationSiteOverrideMode override_mode =
       (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
@@ -3925,7 +3876,7 @@
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
     __ bind(&done);
   } else {
-    ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
+    ArrayNArgumentsConstructorStub stub(isolate());
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   }
 }
@@ -4056,14 +4007,12 @@
   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
 
   __ li(StoreDescriptor::NameRegister(), Operand(instr->name()));
-  Handle<Code> ic = CodeFactory::StoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic =
+      CodeFactory::StoreICInOptimizedCode(isolate(), instr->language_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -4306,13 +4255,11 @@
   DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
 
   Handle<Code> ic = CodeFactory::KeyedStoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state()).code();
+                        isolate(), instr->language_mode())
+                        .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -4391,7 +4338,15 @@
 
     LOperand* key = instr->key();
     if (key->IsConstantOperand()) {
-      __ li(a3, Operand(ToSmi(LConstantOperand::cast(key))));
+      LConstantOperand* constant_key = LConstantOperand::cast(key);
+      int32_t int_key = ToInteger32(constant_key);
+      if (Smi::IsValid(int_key)) {
+        __ li(a3, Operand(Smi::FromInt(int_key)));
+      } else {
+        // We should never get here at runtime because there is a smi check on
+        // the key before this point.
+        __ stop("expected smi");
+      }
     } else {
       __ mov(a3, ToRegister(key));
       __ SmiTag(a3);
@@ -4440,8 +4395,7 @@
     DCHECK(ToRegister(instr->context()).is(cp));
     PushSafepointRegistersScope scope(this);
     __ li(a1, Operand(to_map));
-    bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
-    TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
+    TransitionElementsKindStub stub(isolate(), from_kind, to_kind);
     __ CallStub(&stub);
     RecordSafepointWithRegisters(
         instr->pointer_map(), 0, Safepoint::kLazyDeopt);
@@ -4662,7 +4616,7 @@
 
   if (FLAG_inline_new) {
     __ LoadRoot(tmp3, Heap::kHeapNumberMapRootIndex);
-    __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow, TAG_RESULT);
+    __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow);
     __ Branch(&done);
   }
 
@@ -4717,15 +4671,12 @@
   if (FLAG_inline_new) {
     __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
     // We want the untagged address first for performance
-    __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry(),
-                          DONT_TAG_RESULT);
+    __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry());
   } else {
     __ Branch(deferred->entry());
   }
   __ bind(deferred->exit());
-  __ sdc1(input_reg, MemOperand(reg, HeapNumber::kValueOffset));
-  // Now that we have finished with the object's real address tag it
-  __ Daddu(reg, reg, kHeapObjectTag);
+  __ sdc1(input_reg, FieldMemOperand(reg, HeapNumber::kValueOffset));
 }
 
 
@@ -4746,7 +4697,6 @@
   __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
   RecordSafepointWithRegisters(
       instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
-  __ Dsubu(v0, v0, kHeapObjectTag);
   __ StoreToSafepointRegisterSlot(v0, reg);
 }
 
@@ -5265,14 +5215,6 @@
 }
 
 
-void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
-  Register hi_reg = ToRegister(instr->hi());
-  Register lo_reg = ToRegister(instr->lo());
-  DoubleRegister result_reg = ToDoubleRegister(instr->result());
-  __ Move(result_reg, lo_reg, hi_reg);
-}
-
-
 void LCodeGen::DoAllocate(LAllocate* instr) {
   class DeferredAllocate final : public LDeferredCode {
    public:
@@ -5293,7 +5235,7 @@
   Register scratch2 = ToRegister(instr->temp2());
 
   // Allocate memory for the object.
-  AllocationFlags flags = TAG_OBJECT;
+  AllocationFlags flags = NO_ALLOCATION_FLAGS;
   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
   }
@@ -5301,6 +5243,12 @@
     DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
     flags = static_cast<AllocationFlags>(flags | PRETENURE);
   }
+
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    flags = static_cast<AllocationFlags>(flags | ALLOCATION_FOLDING_DOMINATOR);
+  }
+  DCHECK(!instr->hydrogen()->IsAllocationFolded());
+
   if (instr->size()->IsConstantOperand()) {
     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
     CHECK(size <= Page::kMaxRegularHeapObjectSize);
@@ -5371,6 +5319,49 @@
   CallRuntimeFromDeferred(
       Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
   __ StoreToSafepointRegisterSlot(v0, result);
+
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    AllocationFlags allocation_flags = NO_ALLOCATION_FLAGS;
+    if (instr->hydrogen()->IsOldSpaceAllocation()) {
+      DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+      allocation_flags = static_cast<AllocationFlags>(flags | PRETENURE);
+    }
+    // If the allocation folding dominator allocate triggered a GC, allocation
+    // happend in the runtime. We have to reset the top pointer to virtually
+    // undo the allocation.
+    ExternalReference allocation_top =
+        AllocationUtils::GetAllocationTopReference(isolate(), allocation_flags);
+    Register top_address = scratch0();
+    __ Dsubu(v0, v0, Operand(kHeapObjectTag));
+    __ li(top_address, Operand(allocation_top));
+    __ sd(v0, MemOperand(top_address));
+    __ Daddu(v0, v0, Operand(kHeapObjectTag));
+  }
+}
+
+void LCodeGen::DoFastAllocate(LFastAllocate* instr) {
+  DCHECK(instr->hydrogen()->IsAllocationFolded());
+  DCHECK(!instr->hydrogen()->IsAllocationFoldingDominator());
+  Register result = ToRegister(instr->result());
+  Register scratch1 = ToRegister(instr->temp1());
+  Register scratch2 = ToRegister(instr->temp2());
+
+  AllocationFlags flags = ALLOCATION_FOLDED;
+  if (instr->hydrogen()->MustAllocateDoubleAligned()) {
+    flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
+  }
+  if (instr->hydrogen()->IsOldSpaceAllocation()) {
+    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+    flags = static_cast<AllocationFlags>(flags | PRETENURE);
+  }
+  if (instr->size()->IsConstantOperand()) {
+    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
+    CHECK(size <= Page::kMaxRegularHeapObjectSize);
+    __ FastAllocate(size, result, scratch1, scratch2, flags);
+  } else {
+    Register size = ToRegister(instr->size());
+    __ FastAllocate(size, result, scratch1, scratch2, flags);
+  }
 }
 
 
diff --git a/src/crankshaft/mips64/lithium-codegen-mips64.h b/src/crankshaft/mips64/lithium-codegen-mips64.h
index 4a700bd..9ac3192 100644
--- a/src/crankshaft/mips64/lithium-codegen-mips64.h
+++ b/src/crankshaft/mips64/lithium-codegen-mips64.h
@@ -136,8 +136,6 @@
 #undef DECLARE_DO
 
  private:
-  LanguageMode language_mode() const { return info()->language_mode(); }
-
   Scope* scope() const { return scope_; }
 
   Register scratch0() { return kLithiumScratchReg; }
diff --git a/src/crankshaft/mips64/lithium-mips64.cc b/src/crankshaft/mips64/lithium-mips64.cc
index bcfbc24..b682d19 100644
--- a/src/crankshaft/mips64/lithium-mips64.cc
+++ b/src/crankshaft/mips64/lithium-mips64.cc
@@ -887,7 +887,7 @@
 
 LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) {
   LInstruction* result = new (zone()) LPrologue();
-  if (info_->num_heap_slots() > 0) {
+  if (info_->scope()->num_heap_slots() > 0) {
     result = MarkAsCall(result, instr);
   }
   return result;
@@ -939,17 +939,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
-  LOperand* left =
-      UseFixed(instr->left(), InstanceOfDescriptor::LeftRegister());
-  LOperand* right =
-      UseFixed(instr->right(), InstanceOfDescriptor::RightRegister());
-  LOperand* context = UseFixed(instr->context(), cp);
-  LInstanceOf* result = new (zone()) LInstanceOf(context, left, right);
-  return MarkAsCall(DefineFixed(result, v0), instr);
-}
-
-
 LInstruction* LChunkBuilder::DoHasInPrototypeChainAndBranch(
     HHasInPrototypeChainAndBranch* instr) {
   LOperand* object = UseRegister(instr->object());
@@ -1085,6 +1074,10 @@
       return DoMathAbs(instr);
     case kMathLog:
       return DoMathLog(instr);
+    case kMathCos:
+      return DoMathCos(instr);
+    case kMathSin:
+      return DoMathSin(instr);
     case kMathExp:
       return DoMathExp(instr);
     case kMathSqrt:
@@ -1114,16 +1107,25 @@
   return DefineAsRegister(result);
 }
 
+LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
+  DCHECK(instr->representation().IsDouble());
+  DCHECK(instr->value()->representation().IsDouble());
+  LOperand* input = UseFixedDouble(instr->value(), f4);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathCos(input), f4), instr);
+}
+
+LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
+  DCHECK(instr->representation().IsDouble());
+  DCHECK(instr->value()->representation().IsDouble());
+  LOperand* input = UseFixedDouble(instr->value(), f4);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathSin(input), f4), instr);
+}
 
 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
   DCHECK(instr->representation().IsDouble());
   DCHECK(instr->value()->representation().IsDouble());
-  LOperand* input = UseRegister(instr->value());
-  LOperand* temp1 = TempRegister();
-  LOperand* temp2 = TempRegister();
-  LOperand* double_temp = TempDoubleRegister();
-  LMathExp* result = new(zone()) LMathExp(input, double_temp, temp1, temp2);
-  return DefineAsRegister(result);
+  LOperand* input = UseFixedDouble(instr->value(), f4);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathExp(input), f4), instr);
 }
 
 
@@ -1935,13 +1937,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
-  LOperand* lo = UseRegister(instr->lo());
-  LOperand* hi = UseRegister(instr->hi());
-  return DefineAsRegister(new(zone()) LConstructDouble(hi, lo));
-}
-
-
 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
   LOperand* context = info()->IsStub()
       ? UseFixed(instr->context(), cp)
@@ -1973,14 +1968,9 @@
 
 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
-  LOperand* global_object =
-      UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
-  LLoadGlobalGeneric* result =
-      new(zone()) LLoadGlobalGeneric(context, global_object, vector);
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
+
+  LLoadGlobalGeneric* result = new (zone()) LLoadGlobalGeneric(context, vector);
   return MarkAsCall(DefineFixed(result, v0), instr);
 }
 
@@ -2024,10 +2014,7 @@
   LOperand* context = UseFixed(instr->context(), cp);
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
   LInstruction* result =
       DefineFixed(new(zone()) LLoadNamedGeneric(context, object, vector), v0);
@@ -2100,10 +2087,7 @@
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
   LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
   LInstruction* result =
       DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key, vector),
@@ -2166,12 +2150,8 @@
   DCHECK(instr->key()->representation().IsTagged());
   DCHECK(instr->value()->representation().IsTagged());
 
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
 
   LStoreKeyedGeneric* result =
       new (zone()) LStoreKeyedGeneric(context, obj, key, val, slot, vector);
@@ -2260,12 +2240,8 @@
   LOperand* obj =
       UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
   LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
 
   LStoreNamedGeneric* result =
       new (zone()) LStoreNamedGeneric(context, obj, val, slot, vector);
@@ -2303,13 +2279,18 @@
 
 
 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
-  info()->MarkAsDeferredCalling();
-  LOperand* context = UseAny(instr->context());
   LOperand* size = UseRegisterOrConstant(instr->size());
   LOperand* temp1 = TempRegister();
   LOperand* temp2 = TempRegister();
-  LAllocate* result = new(zone()) LAllocate(context, size, temp1, temp2);
-  return AssignPointerMap(DefineAsRegister(result));
+  if (instr->IsAllocationFolded()) {
+    LFastAllocate* result = new (zone()) LFastAllocate(size, temp1, temp2);
+    return DefineAsRegister(result);
+  } else {
+    info()->MarkAsDeferredCalling();
+    LOperand* context = UseAny(instr->context());
+    LAllocate* result = new (zone()) LAllocate(context, size, temp1, temp2);
+    return AssignPointerMap(DefineAsRegister(result));
+  }
 }
 
 
diff --git a/src/crankshaft/mips64/lithium-mips64.h b/src/crankshaft/mips64/lithium-mips64.h
index 41cf93c..ad3fb87 100644
--- a/src/crankshaft/mips64/lithium-mips64.h
+++ b/src/crankshaft/mips64/lithium-mips64.h
@@ -55,7 +55,6 @@
   V(ConstantI)                               \
   V(ConstantS)                               \
   V(ConstantT)                               \
-  V(ConstructDouble)                         \
   V(Context)                                 \
   V(DebugBreak)                              \
   V(DeclareGlobals)                          \
@@ -69,6 +68,7 @@
   V(Drop)                                    \
   V(Dummy)                                   \
   V(DummyUse)                                \
+  V(FastAllocate)                            \
   V(FlooringDivByConstI)                     \
   V(FlooringDivByPowerOf2I)                  \
   V(FlooringDivI)                            \
@@ -80,7 +80,6 @@
   V(HasInPrototypeChainAndBranch)            \
   V(HasInstanceTypeAndBranch)                \
   V(InnerAllocatedObject)                    \
-  V(InstanceOf)                              \
   V(InstructionGap)                          \
   V(Integer32ToDouble)                       \
   V(InvokeFunction)                          \
@@ -99,6 +98,8 @@
   V(LoadNamedField)                          \
   V(LoadNamedGeneric)                        \
   V(MathAbs)                                 \
+  V(MathCos)                                 \
+  V(MathSin)                                 \
   V(MathExp)                                 \
   V(MathClz32)                               \
   V(MathFloor)                               \
@@ -900,24 +901,29 @@
   DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
 };
 
-
-class LMathExp final : public LTemplateInstruction<1, 1, 3> {
+class LMathCos final : public LTemplateInstruction<1, 1, 0> {
  public:
-  LMathExp(LOperand* value,
-           LOperand* double_temp,
-           LOperand* temp1,
-           LOperand* temp2) {
-    inputs_[0] = value;
-    temps_[0] = temp1;
-    temps_[1] = temp2;
-    temps_[2] = double_temp;
-    ExternalReference::InitializeMathExpData();
-  }
+  explicit LMathCos(LOperand* value) { inputs_[0] = value; }
 
   LOperand* value() { return inputs_[0]; }
-  LOperand* temp1() { return temps_[0]; }
-  LOperand* temp2() { return temps_[1]; }
-  LOperand* double_temp() { return temps_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
+};
+
+class LMathSin final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathSin(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
+};
+
+class LMathExp final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathExp(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
 };
@@ -1131,22 +1137,6 @@
 };
 
 
-class LInstanceOf final : public LTemplateInstruction<1, 3, 0> {
- public:
-  LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
-    inputs_[0] = context;
-    inputs_[1] = left;
-    inputs_[2] = right;
-  }
-
-  LOperand* context() const { return inputs_[0]; }
-  LOperand* left() const { return inputs_[1]; }
-  LOperand* right() const { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
-};
-
-
 class LHasInPrototypeChainAndBranch final : public LControlInstruction<2, 0> {
  public:
   LHasInPrototypeChainAndBranch(LOperand* object, LOperand* prototype) {
@@ -1609,18 +1599,14 @@
   DECLARE_HYDROGEN_ACCESSOR(LoadKeyedGeneric)
 };
 
-
-class LLoadGlobalGeneric final : public LTemplateInstruction<1, 2, 1> {
+class LLoadGlobalGeneric final : public LTemplateInstruction<1, 1, 1> {
  public:
-  LLoadGlobalGeneric(LOperand* context, LOperand* global_object,
-                     LOperand* vector) {
+  LLoadGlobalGeneric(LOperand* context, LOperand* vector) {
     inputs_[0] = context;
-    inputs_[1] = global_object;
     temps_[0] = vector;
   }
 
   LOperand* context() { return inputs_[0]; }
-  LOperand* global_object() { return inputs_[1]; }
   LOperand* temp_vector() { return temps_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
@@ -2361,20 +2347,6 @@
 };
 
 
-class LConstructDouble final : public LTemplateInstruction<1, 2, 0> {
- public:
-  LConstructDouble(LOperand* hi, LOperand* lo) {
-    inputs_[0] = hi;
-    inputs_[1] = lo;
-  }
-
-  LOperand* hi() { return inputs_[0]; }
-  LOperand* lo() { return inputs_[1]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
-};
-
-
 class LAllocate final : public LTemplateInstruction<1, 2, 2> {
  public:
   LAllocate(LOperand* context,
@@ -2396,6 +2368,21 @@
   DECLARE_HYDROGEN_ACCESSOR(Allocate)
 };
 
+class LFastAllocate final : public LTemplateInstruction<1, 1, 2> {
+ public:
+  LFastAllocate(LOperand* size, LOperand* temp1, LOperand* temp2) {
+    inputs_[0] = size;
+    temps_[0] = temp1;
+    temps_[1] = temp2;
+  }
+
+  LOperand* size() { return inputs_[0]; }
+  LOperand* temp1() { return temps_[0]; }
+  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(FastAllocate, "fast-allocate")
+  DECLARE_HYDROGEN_ACCESSOR(Allocate)
+};
 
 class LTypeof final : public LTemplateInstruction<1, 2, 0> {
  public:
@@ -2550,6 +2537,8 @@
   LInstruction* DoMathFround(HUnaryMathOperation* instr);
   LInstruction* DoMathAbs(HUnaryMathOperation* instr);
   LInstruction* DoMathLog(HUnaryMathOperation* instr);
+  LInstruction* DoMathCos(HUnaryMathOperation* instr);
+  LInstruction* DoMathSin(HUnaryMathOperation* instr);
   LInstruction* DoMathExp(HUnaryMathOperation* instr);
   LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
   LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
diff --git a/src/crankshaft/ppc/OWNERS b/src/crankshaft/ppc/OWNERS
index eb007cb..752e8e3 100644
--- a/src/crankshaft/ppc/OWNERS
+++ b/src/crankshaft/ppc/OWNERS
@@ -3,3 +3,4 @@
 joransiu@ca.ibm.com
 mbrandy@us.ibm.com
 michael_dawson@ca.ibm.com
+bjaideep@ca.ibm.com
diff --git a/src/crankshaft/ppc/lithium-codegen-ppc.cc b/src/crankshaft/ppc/lithium-codegen-ppc.cc
index d5d0104..056c93a 100644
--- a/src/crankshaft/ppc/lithium-codegen-ppc.cc
+++ b/src/crankshaft/ppc/lithium-codegen-ppc.cc
@@ -11,7 +11,6 @@
 #include "src/crankshaft/ppc/lithium-gap-resolver-ppc.h"
 #include "src/ic/ic.h"
 #include "src/ic/stub-cache.h"
-#include "src/profiler/cpu-profiler.h"
 
 namespace v8 {
 namespace internal {
@@ -326,8 +325,6 @@
       } else {
         __ b(&call_deopt_entry, SetLK);
       }
-      info()->LogDeoptCallPosition(masm()->pc_offset(),
-                                   table_entry->deopt_info.inlining_id);
     }
 
     if (needs_frame.is_linked()) {
@@ -755,7 +752,7 @@
     __ stop("trap_on_deopt", cond, kDefaultStopCode, cr);
   }
 
-  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason);
+  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason, id);
 
   DCHECK(info()->IsStub() || frame_is_built_);
   // Go through jump table if we need to handle condition, build frame, or
@@ -763,13 +760,12 @@
   if (cond == al && frame_is_built_ && !info()->saves_caller_doubles()) {
     DeoptComment(deopt_info);
     __ Call(entry, RelocInfo::RUNTIME_ENTRY);
-    info()->LogDeoptCallPosition(masm()->pc_offset(), deopt_info.inlining_id);
   } else {
     Deoptimizer::JumpTableEntry table_entry(entry, deopt_info, bailout_type,
                                             !frame_is_built_);
     // We often have several deopts to the same entry, reuse the last
     // jump entry if this is the case.
-    if (FLAG_trace_deopt || isolate()->cpu_profiler()->is_profiling() ||
+    if (FLAG_trace_deopt || isolate()->is_profiling() ||
         jump_table_.is_empty() ||
         !table_entry.IsEquivalentTo(jump_table_.last())) {
       jump_table_.Add(table_entry, zone());
@@ -840,7 +836,6 @@
 void LCodeGen::RecordAndWritePosition(int position) {
   if (position == RelocInfo::kNoPosition) return;
   masm()->positions_recorder()->RecordPosition(position);
-  masm()->positions_recorder()->WriteRecordedPositions();
 }
 
 
@@ -1143,6 +1138,10 @@
     }
   }
 
+#if V8_TARGET_ARCH_PPC64
+  __ extsw(result, result);
+#endif
+
   if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
     // Deoptimize if remainder is not 0.
     Register scratch = scratch0();
@@ -1336,6 +1335,9 @@
   // We performed a truncating division. Correct the result.
   __ subi(result, result, Operand(1));
   __ bind(&done);
+#if V8_TARGET_ARCH_PPC64
+  __ extsw(result, result);
+#endif
 }
 
 
@@ -2555,16 +2557,6 @@
 }
 
 
-void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
-  DCHECK(ToRegister(instr->context()).is(cp));
-  DCHECK(ToRegister(instr->left()).is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(ToRegister(instr->right()).is(InstanceOfDescriptor::RightRegister()));
-  DCHECK(ToRegister(instr->result()).is(r3));
-  InstanceOfStub stub(isolate());
-  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
-}
-
-
 void LCodeGen::DoHasInPrototypeChainAndBranch(
     LHasInPrototypeChainAndBranch* instr) {
   Register const object = ToRegister(instr->object());
@@ -2596,10 +2588,10 @@
   DeoptimizeIf(eq, instr, Deoptimizer::kProxy);
   __ LoadP(object_prototype,
            FieldMemOperand(object_map, Map::kPrototypeOffset));
-  __ cmp(object_prototype, prototype);
-  EmitTrueBranch(instr, eq);
   __ CompareRoot(object_prototype, Heap::kNullValueRootIndex);
   EmitFalseBranch(instr, eq);
+  __ cmp(object_prototype, prototype);
+  EmitTrueBranch(instr, eq);
   __ LoadP(object_map,
            FieldMemOperand(object_prototype, HeapObject::kMapOffset));
   __ b(&loop);
@@ -2705,15 +2697,12 @@
 
 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   DCHECK(ToRegister(instr->context()).is(cp));
-  DCHECK(ToRegister(instr->global_object())
-             .is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->result()).is(r3));
 
-  __ mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), instr->typeof_mode(), PREMONOMORPHIC)
-                        .code();
+  Handle<Code> ic =
+      CodeFactory::LoadGlobalICInOptimizedCode(isolate(), instr->typeof_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2828,10 +2817,7 @@
   // Name is always in r5.
   __ mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_INSIDE_TYPEOF,
-                        instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3189,14 +3175,9 @@
   DCHECK(ToRegister(instr->context()).is(cp));
   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister()));
+  EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
-  }
-
-  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
-                        isolate(), instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3614,8 +3595,13 @@
   }
 }
 
+void LCodeGen::DoMathFloorD(LMathFloorD* instr) {
+  DoubleRegister input_reg = ToDoubleRegister(instr->value());
+  DoubleRegister output_reg = ToDoubleRegister(instr->result());
+  __ frim(output_reg, input_reg);
+}
 
-void LCodeGen::DoMathFloor(LMathFloor* instr) {
+void LCodeGen::DoMathFloorI(LMathFloorI* instr) {
   DoubleRegister input = ToDoubleRegister(instr->value());
   Register result = ToRegister(instr->result());
   Register input_high = scratch0();
@@ -3637,8 +3623,30 @@
   __ bind(&done);
 }
 
+void LCodeGen::DoMathRoundD(LMathRoundD* instr) {
+  DoubleRegister input_reg = ToDoubleRegister(instr->value());
+  DoubleRegister output_reg = ToDoubleRegister(instr->result());
+  DoubleRegister dot_five = double_scratch0();
+  Label done;
 
-void LCodeGen::DoMathRound(LMathRound* instr) {
+  __ frin(output_reg, input_reg);
+  __ fcmpu(input_reg, kDoubleRegZero);
+  __ bge(&done);
+  __ fcmpu(output_reg, input_reg);
+  __ beq(&done);
+
+  // Negative, non-integer case
+  __ LoadDoubleLiteral(dot_five, 0.5, r0);
+  __ fadd(output_reg, input_reg, dot_five);
+  __ frim(output_reg, output_reg);
+  // The range [-0.5, -0.0[ yielded +0.0. Force the sign to negative.
+  __ fabs(output_reg, output_reg);
+  __ fneg(output_reg, output_reg);
+
+  __ bind(&done);
+}
+
+void LCodeGen::DoMathRoundI(LMathRoundI* instr) {
   DoubleRegister input = ToDoubleRegister(instr->value());
   Register result = ToRegister(instr->result());
   DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp());
@@ -3762,29 +3770,34 @@
   }
 }
 
-
-void LCodeGen::DoMathExp(LMathExp* instr) {
-  DoubleRegister input = ToDoubleRegister(instr->value());
-  DoubleRegister result = ToDoubleRegister(instr->result());
-  DoubleRegister double_scratch1 = ToDoubleRegister(instr->double_temp());
-  DoubleRegister double_scratch2 = double_scratch0();
-  Register temp1 = ToRegister(instr->temp1());
-  Register temp2 = ToRegister(instr->temp2());
-
-  MathExpGenerator::EmitMathExp(masm(), input, result, double_scratch1,
-                                double_scratch2, temp1, temp2, scratch0());
+void LCodeGen::DoMathCos(LMathCos* instr) {
+  __ PrepareCallCFunction(0, 1, scratch0());
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
+  __ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 0, 1);
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
 }
 
+void LCodeGen::DoMathSin(LMathSin* instr) {
+  __ PrepareCallCFunction(0, 1, scratch0());
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
+  __ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 0, 1);
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
+}
+
+void LCodeGen::DoMathExp(LMathExp* instr) {
+  __ PrepareCallCFunction(0, 1, scratch0());
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
+  __ CallCFunction(ExternalReference::ieee754_exp_function(isolate()), 0, 1);
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
+}
 
 void LCodeGen::DoMathLog(LMathLog* instr) {
   __ PrepareCallCFunction(0, 1, scratch0());
   __ MovToFloatParameter(ToDoubleRegister(instr->value()));
-  __ CallCFunction(ExternalReference::math_log_double_function(isolate()), 0,
-                   1);
+  __ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
   __ MovFromFloatResult(ToDoubleRegister(instr->result()));
 }
 
-
 void LCodeGen::DoMathClz32(LMathClz32* instr) {
   Register input = ToRegister(instr->value());
   Register result = ToRegister(instr->result());
@@ -3803,7 +3816,9 @@
 #endif
   if (FLAG_code_comments) {
     if (actual.is_reg()) {
-      Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString());
+      Comment(";;; PrepareForTailCall, actual: %s {",
+              RegisterConfiguration::Crankshaft()->GetGeneralRegisterName(
+                  actual.reg().code()));
     } else {
       Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate());
     }
@@ -3909,14 +3924,8 @@
   DCHECK(ToRegister(instr->result()).is(r3));
 
   __ mov(r3, Operand(instr->arity()));
-  if (instr->arity() == 1) {
-    // We only need the allocation site for the case we have a length argument.
-    // The case may bail out to the runtime, which will determine the correct
-    // elements kind with the site.
-    __ Move(r5, instr->hydrogen()->site());
-  } else {
-    __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
-  }
+  __ Move(r5, instr->hydrogen()->site());
+
   ElementsKind kind = instr->hydrogen()->elements_kind();
   AllocationSiteOverrideMode override_mode =
       (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
@@ -3948,7 +3957,7 @@
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
     __ bind(&done);
   } else {
-    ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
+    ArrayNArgumentsConstructorStub stub(isolate());
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   }
 }
@@ -4083,14 +4092,12 @@
   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
 
   __ mov(StoreDescriptor::NameRegister(), Operand(instr->name()));
-  Handle<Code> ic = CodeFactory::StoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic =
+      CodeFactory::StoreICInOptimizedCode(isolate(), instr->language_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -4345,13 +4352,11 @@
   DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
 
   Handle<Code> ic = CodeFactory::KeyedStoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state()).code();
+                        isolate(), instr->language_mode())
+                        .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -4430,7 +4435,15 @@
 
     LOperand* key = instr->key();
     if (key->IsConstantOperand()) {
-      __ LoadSmiLiteral(r6, ToSmi(LConstantOperand::cast(key)));
+      LConstantOperand* constant_key = LConstantOperand::cast(key);
+      int32_t int_key = ToInteger32(constant_key);
+      if (Smi::IsValid(int_key)) {
+        __ LoadSmiLiteral(r6, Smi::FromInt(int_key));
+      } else {
+        // We should never get here at runtime because there is a smi check on
+        // the key before this point.
+        __ stop("expected smi");
+      }
     } else {
       __ SmiTag(r6, ToRegister(key));
     }
@@ -4476,8 +4489,7 @@
     DCHECK(object_reg.is(r3));
     PushSafepointRegistersScope scope(this);
     __ Move(r4, to_map);
-    bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
-    TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
+    TransitionElementsKindStub stub(isolate(), from_kind, to_kind);
     __ CallStub(&stub);
     RecordSafepointWithRegisters(instr->pointer_map(), 0,
                                  Safepoint::kLazyDeopt);
@@ -5295,23 +5307,11 @@
 }
 
 
-void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
-  Register hi_reg = ToRegister(instr->hi());
-  Register lo_reg = ToRegister(instr->lo());
-  DoubleRegister result_reg = ToDoubleRegister(instr->result());
-#if V8_TARGET_ARCH_PPC64
-  __ MovInt64ComponentsToDouble(result_reg, hi_reg, lo_reg, r0);
-#else
-  __ MovInt64ToDouble(result_reg, hi_reg, lo_reg);
-#endif
-}
-
-
 void LCodeGen::DoAllocate(LAllocate* instr) {
   class DeferredAllocate final : public LDeferredCode {
    public:
     DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
-        : LDeferredCode(codegen), instr_(instr) {}
+        : LDeferredCode(codegen), instr_(instr) { }
     void Generate() override { codegen()->DoDeferredAllocate(instr_); }
     LInstruction* instr() override { return instr_; }
 
@@ -5319,14 +5319,15 @@
     LAllocate* instr_;
   };
 
-  DeferredAllocate* deferred = new (zone()) DeferredAllocate(this, instr);
+  DeferredAllocate* deferred =
+      new(zone()) DeferredAllocate(this, instr);
 
   Register result = ToRegister(instr->result());
   Register scratch = ToRegister(instr->temp1());
   Register scratch2 = ToRegister(instr->temp2());
 
   // Allocate memory for the object.
-  AllocationFlags flags = TAG_OBJECT;
+  AllocationFlags flags = NO_ALLOCATION_FLAGS;
   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
   }
@@ -5335,6 +5336,12 @@
     flags = static_cast<AllocationFlags>(flags | PRETENURE);
   }
 
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    flags = static_cast<AllocationFlags>(flags | ALLOCATION_FOLDING_DOMINATOR);
+  }
+
+  DCHECK(!instr->hydrogen()->IsAllocationFolded());
+
   if (instr->size()->IsConstantOperand()) {
     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
     CHECK(size <= Page::kMaxRegularHeapObjectSize);
@@ -5406,6 +5413,49 @@
   CallRuntimeFromDeferred(Runtime::kAllocateInTargetSpace, 2, instr,
                           instr->context());
   __ StoreToSafepointRegisterSlot(r3, result);
+
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    AllocationFlags allocation_flags = NO_ALLOCATION_FLAGS;
+    if (instr->hydrogen()->IsOldSpaceAllocation()) {
+      DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+      allocation_flags = static_cast<AllocationFlags>(flags | PRETENURE);
+    }
+    // If the allocation folding dominator allocate triggered a GC, allocation
+    // happend in the runtime. We have to reset the top pointer to virtually
+    // undo the allocation.
+    ExternalReference allocation_top =
+        AllocationUtils::GetAllocationTopReference(isolate(), allocation_flags);
+    Register top_address = scratch0();
+    __ subi(r3, r3, Operand(kHeapObjectTag));
+    __ mov(top_address, Operand(allocation_top));
+    __ StoreP(r3, MemOperand(top_address));
+    __ addi(r3, r3, Operand(kHeapObjectTag));
+  }
+}
+
+void LCodeGen::DoFastAllocate(LFastAllocate* instr) {
+  DCHECK(instr->hydrogen()->IsAllocationFolded());
+  DCHECK(!instr->hydrogen()->IsAllocationFoldingDominator());
+  Register result = ToRegister(instr->result());
+  Register scratch1 = ToRegister(instr->temp1());
+  Register scratch2 = ToRegister(instr->temp2());
+
+  AllocationFlags flags = ALLOCATION_FOLDED;
+  if (instr->hydrogen()->MustAllocateDoubleAligned()) {
+    flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
+  }
+  if (instr->hydrogen()->IsOldSpaceAllocation()) {
+    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+    flags = static_cast<AllocationFlags>(flags | PRETENURE);
+  }
+  if (instr->size()->IsConstantOperand()) {
+    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
+    CHECK(size <= Page::kMaxRegularHeapObjectSize);
+    __ FastAllocate(size, result, scratch1, scratch2, flags);
+  } else {
+    Register size = ToRegister(instr->size());
+    __ FastAllocate(size, result, scratch1, scratch2, flags);
+  }
 }
 
 
diff --git a/src/crankshaft/ppc/lithium-codegen-ppc.h b/src/crankshaft/ppc/lithium-codegen-ppc.h
index 28f1680..730c4bd 100644
--- a/src/crankshaft/ppc/lithium-codegen-ppc.h
+++ b/src/crankshaft/ppc/lithium-codegen-ppc.h
@@ -128,8 +128,6 @@
 #undef DECLARE_DO
 
  private:
-  LanguageMode language_mode() const { return info()->language_mode(); }
-
   Scope* scope() const { return scope_; }
 
   Register scratch0() { return kLithiumScratch; }
diff --git a/src/crankshaft/ppc/lithium-ppc.cc b/src/crankshaft/ppc/lithium-ppc.cc
index b739786..81b2205 100644
--- a/src/crankshaft/ppc/lithium-ppc.cc
+++ b/src/crankshaft/ppc/lithium-ppc.cc
@@ -892,7 +892,7 @@
 
 LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) {
   LInstruction* result = new (zone()) LPrologue();
-  if (info_->num_heap_slots() > 0) {
+  if (info_->scope()->num_heap_slots() > 0) {
     result = MarkAsCall(result, instr);
   }
   return result;
@@ -949,17 +949,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
-  LOperand* left =
-      UseFixed(instr->left(), InstanceOfDescriptor::LeftRegister());
-  LOperand* right =
-      UseFixed(instr->right(), InstanceOfDescriptor::RightRegister());
-  LOperand* context = UseFixed(instr->context(), cp);
-  LInstanceOf* result = new (zone()) LInstanceOf(context, left, right);
-  return MarkAsCall(DefineFixed(result, r3), instr);
-}
-
-
 LInstruction* LChunkBuilder::DoHasInPrototypeChainAndBranch(
     HHasInPrototypeChainAndBranch* instr) {
   LOperand* object = UseRegister(instr->object());
@@ -1091,6 +1080,10 @@
       return DoMathAbs(instr);
     case kMathLog:
       return DoMathLog(instr);
+    case kMathCos:
+      return DoMathCos(instr);
+    case kMathSin:
+      return DoMathSin(instr);
     case kMathExp:
       return DoMathExp(instr);
     case kMathSqrt:
@@ -1107,20 +1100,32 @@
 
 
 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) {
+  DCHECK(instr->value()->representation().IsDouble());
   LOperand* input = UseRegister(instr->value());
-  LMathFloor* result = new (zone()) LMathFloor(input);
-  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
+  if (instr->representation().IsInteger32()) {
+    LMathFloorI* result = new (zone()) LMathFloorI(input);
+    return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
+  } else {
+    DCHECK(instr->representation().IsDouble());
+    LMathFloorD* result = new (zone()) LMathFloorD(input);
+    return DefineAsRegister(result);
+  }
 }
 
-
 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
+  DCHECK(instr->value()->representation().IsDouble());
   LOperand* input = UseRegister(instr->value());
-  LOperand* temp = TempDoubleRegister();
-  LMathRound* result = new (zone()) LMathRound(input, temp);
-  return AssignEnvironment(DefineAsRegister(result));
+  if (instr->representation().IsInteger32()) {
+    LOperand* temp = TempDoubleRegister();
+    LMathRoundI* result = new (zone()) LMathRoundI(input, temp);
+    return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
+  } else {
+    DCHECK(instr->representation().IsDouble());
+    LMathRoundD* result = new (zone()) LMathRoundD(input);
+    return DefineAsRegister(result);
+  }
 }
 
-
 LInstruction* LChunkBuilder::DoMathFround(HUnaryMathOperation* instr) {
   LOperand* input = UseRegister(instr->value());
   LMathFround* result = new (zone()) LMathFround(input);
@@ -1145,8 +1150,8 @@
 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
   DCHECK(instr->representation().IsDouble());
   DCHECK(instr->value()->representation().IsDouble());
-  LOperand* input = UseFixedDouble(instr->value(), d1);
-  return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), d1), instr);
+  LOperand* input = UseFixedDouble(instr->value(), d0);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), d0), instr);
 }
 
 
@@ -1156,16 +1161,25 @@
   return DefineAsRegister(result);
 }
 
+LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
+  DCHECK(instr->representation().IsDouble());
+  DCHECK(instr->value()->representation().IsDouble());
+  LOperand* input = UseFixedDouble(instr->value(), d0);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathCos(input), d0), instr);
+}
+
+LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
+  DCHECK(instr->representation().IsDouble());
+  DCHECK(instr->value()->representation().IsDouble());
+  LOperand* input = UseFixedDouble(instr->value(), d0);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathSin(input), d0), instr);
+}
 
 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
   DCHECK(instr->representation().IsDouble());
   DCHECK(instr->value()->representation().IsDouble());
-  LOperand* input = UseRegister(instr->value());
-  LOperand* temp1 = TempRegister();
-  LOperand* temp2 = TempRegister();
-  LOperand* double_temp = TempDoubleRegister();
-  LMathExp* result = new (zone()) LMathExp(input, double_temp, temp1, temp2);
-  return DefineAsRegister(result);
+  LOperand* input = UseFixedDouble(instr->value(), d0);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathExp(input), d0), instr);
 }
 
 
@@ -1950,13 +1964,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
-  LOperand* lo = UseRegister(instr->lo());
-  LOperand* hi = UseRegister(instr->hi());
-  return DefineAsRegister(new (zone()) LConstructDouble(hi, lo));
-}
-
-
 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
   LOperand* context = info()->IsStub() ? UseFixed(instr->context(), cp) : NULL;
   LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
@@ -1986,14 +1993,9 @@
 
 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
-  LOperand* global_object =
-      UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
-  LLoadGlobalGeneric* result =
-      new (zone()) LLoadGlobalGeneric(context, global_object, vector);
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
+
+  LLoadGlobalGeneric* result = new (zone()) LLoadGlobalGeneric(context, vector);
   return MarkAsCall(DefineFixed(result, r3), instr);
 }
 
@@ -2037,10 +2039,7 @@
   LOperand* context = UseFixed(instr->context(), cp);
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
   LInstruction* result =
       DefineFixed(new (zone()) LLoadNamedGeneric(context, object, vector), r3);
@@ -2110,10 +2109,7 @@
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
   LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
   LInstruction* result = DefineFixed(
       new (zone()) LLoadKeyedGeneric(context, object, key, vector), r3);
@@ -2172,12 +2168,8 @@
   DCHECK(instr->key()->representation().IsTagged());
   DCHECK(instr->value()->representation().IsTagged());
 
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
 
   LStoreKeyedGeneric* result =
       new (zone()) LStoreKeyedGeneric(context, obj, key, val, slot, vector);
@@ -2265,13 +2257,8 @@
   LOperand* obj =
       UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
   LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
-
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
   LStoreNamedGeneric* result =
       new (zone()) LStoreNamedGeneric(context, obj, val, slot, vector);
   return MarkAsCall(result, instr);
@@ -2307,13 +2294,18 @@
 
 
 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
-  info()->MarkAsDeferredCalling();
-  LOperand* context = UseAny(instr->context());
   LOperand* size = UseRegisterOrConstant(instr->size());
   LOperand* temp1 = TempRegister();
   LOperand* temp2 = TempRegister();
-  LAllocate* result = new (zone()) LAllocate(context, size, temp1, temp2);
-  return AssignPointerMap(DefineAsRegister(result));
+  if (instr->IsAllocationFolded()) {
+    LFastAllocate* result = new (zone()) LFastAllocate(size, temp1, temp2);
+    return DefineAsRegister(result);
+  } else {
+    info()->MarkAsDeferredCalling();
+    LOperand* context = UseAny(instr->context());
+    LAllocate* result = new (zone()) LAllocate(context, size, temp1, temp2);
+    return AssignPointerMap(DefineAsRegister(result));
+  }
 }
 
 
diff --git a/src/crankshaft/ppc/lithium-ppc.h b/src/crankshaft/ppc/lithium-ppc.h
index c39f620..f5e11e3 100644
--- a/src/crankshaft/ppc/lithium-ppc.h
+++ b/src/crankshaft/ppc/lithium-ppc.h
@@ -53,7 +53,6 @@
   V(ConstantI)                               \
   V(ConstantS)                               \
   V(ConstantT)                               \
-  V(ConstructDouble)                         \
   V(Context)                                 \
   V(DebugBreak)                              \
   V(DeclareGlobals)                          \
@@ -67,6 +66,7 @@
   V(Drop)                                    \
   V(Dummy)                                   \
   V(DummyUse)                                \
+  V(FastAllocate)                            \
   V(FlooringDivByConstI)                     \
   V(FlooringDivByPowerOf2I)                  \
   V(FlooringDivI)                            \
@@ -78,7 +78,6 @@
   V(HasInPrototypeChainAndBranch)            \
   V(HasInstanceTypeAndBranch)                \
   V(InnerAllocatedObject)                    \
-  V(InstanceOf)                              \
   V(InstructionGap)                          \
   V(Integer32ToDouble)                       \
   V(InvokeFunction)                          \
@@ -98,13 +97,17 @@
   V(LoadNamedGeneric)                        \
   V(MathAbs)                                 \
   V(MathClz32)                               \
+  V(MathCos)                                 \
+  V(MathSin)                                 \
   V(MathExp)                                 \
-  V(MathFloor)                               \
+  V(MathFloorD)                              \
+  V(MathFloorI)                              \
   V(MathFround)                              \
   V(MathLog)                                 \
   V(MathMinMax)                              \
   V(MathPowHalf)                             \
-  V(MathRound)                               \
+  V(MathRoundD)                              \
+  V(MathRoundI)                              \
   V(MathSqrt)                                \
   V(MaybeGrowElements)                       \
   V(ModByConstI)                             \
@@ -151,7 +154,6 @@
   V(UnknownOSRValue)                         \
   V(WrapReceiver)
 
-
 #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic)            \
   Opcode opcode() const final { return LInstruction::k##type; } \
   void CompileToNative(LCodeGen* generator) final;              \
@@ -807,21 +809,43 @@
   void PrintDataTo(StringStream* stream) override;
 };
 
-
-class LMathFloor final : public LTemplateInstruction<1, 1, 0> {
+// Math.floor with a double result.
+class LMathFloorD final : public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LMathFloor(LOperand* value) { inputs_[0] = value; }
+  explicit LMathFloorD(LOperand* value) { inputs_[0] = value; }
 
   LOperand* value() { return inputs_[0]; }
 
-  DECLARE_CONCRETE_INSTRUCTION(MathFloor, "math-floor")
+  DECLARE_CONCRETE_INSTRUCTION(MathFloorD, "math-floor-d")
   DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
 };
 
-
-class LMathRound final : public LTemplateInstruction<1, 1, 1> {
+// Math.floor with an integer result.
+class LMathFloorI final : public LTemplateInstruction<1, 1, 0> {
  public:
-  LMathRound(LOperand* value, LOperand* temp) {
+  explicit LMathFloorI(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathFloorI, "math-floor-i")
+  DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
+};
+
+// Math.round with a double result.
+class LMathRoundD final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathRoundD(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathRoundD, "math-round-d")
+  DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
+};
+
+// Math.round with an integer result.
+class LMathRoundI final : public LTemplateInstruction<1, 1, 1> {
+ public:
+  LMathRoundI(LOperand* value, LOperand* temp) {
     inputs_[0] = value;
     temps_[0] = temp;
   }
@@ -829,7 +853,7 @@
   LOperand* value() { return inputs_[0]; }
   LOperand* temp() { return temps_[0]; }
 
-  DECLARE_CONCRETE_INSTRUCTION(MathRound, "math-round")
+  DECLARE_CONCRETE_INSTRUCTION(MathRoundI, "math-round-i")
   DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
 };
 
@@ -878,22 +902,31 @@
   DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
 };
 
-
-class LMathExp final : public LTemplateInstruction<1, 1, 3> {
+class LMathCos final : public LTemplateInstruction<1, 1, 0> {
  public:
-  LMathExp(LOperand* value, LOperand* double_temp, LOperand* temp1,
-           LOperand* temp2) {
-    inputs_[0] = value;
-    temps_[0] = temp1;
-    temps_[1] = temp2;
-    temps_[2] = double_temp;
-    ExternalReference::InitializeMathExpData();
-  }
+  explicit LMathCos(LOperand* value) { inputs_[0] = value; }
 
   LOperand* value() { return inputs_[0]; }
-  LOperand* temp1() { return temps_[0]; }
-  LOperand* temp2() { return temps_[1]; }
-  LOperand* double_temp() { return temps_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
+};
+
+
+class LMathSin final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathSin(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
+};
+
+
+class LMathExp final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathExp(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
 };
@@ -1092,22 +1125,6 @@
 };
 
 
-class LInstanceOf final : public LTemplateInstruction<1, 3, 0> {
- public:
-  LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
-    inputs_[0] = context;
-    inputs_[1] = left;
-    inputs_[2] = right;
-  }
-
-  LOperand* context() const { return inputs_[0]; }
-  LOperand* left() const { return inputs_[1]; }
-  LOperand* right() const { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
-};
-
-
 class LHasInPrototypeChainAndBranch final : public LControlInstruction<2, 0> {
  public:
   LHasInPrototypeChainAndBranch(LOperand* object, LOperand* prototype) {
@@ -1528,18 +1545,14 @@
   DECLARE_HYDROGEN_ACCESSOR(LoadKeyedGeneric)
 };
 
-
-class LLoadGlobalGeneric final : public LTemplateInstruction<1, 2, 1> {
+class LLoadGlobalGeneric final : public LTemplateInstruction<1, 1, 1> {
  public:
-  LLoadGlobalGeneric(LOperand* context, LOperand* global_object,
-                     LOperand* vector) {
+  LLoadGlobalGeneric(LOperand* context, LOperand* vector) {
     inputs_[0] = context;
-    inputs_[1] = global_object;
     temps_[0] = vector;
   }
 
   LOperand* context() { return inputs_[0]; }
-  LOperand* global_object() { return inputs_[1]; }
   LOperand* temp_vector() { return temps_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
@@ -2261,20 +2274,6 @@
 };
 
 
-class LConstructDouble final : public LTemplateInstruction<1, 2, 0> {
- public:
-  LConstructDouble(LOperand* hi, LOperand* lo) {
-    inputs_[0] = hi;
-    inputs_[1] = lo;
-  }
-
-  LOperand* hi() { return inputs_[0]; }
-  LOperand* lo() { return inputs_[1]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
-};
-
-
 class LAllocate final : public LTemplateInstruction<1, 2, 2> {
  public:
   LAllocate(LOperand* context, LOperand* size, LOperand* temp1,
@@ -2294,6 +2293,22 @@
   DECLARE_HYDROGEN_ACCESSOR(Allocate)
 };
 
+class LFastAllocate final : public LTemplateInstruction<1, 1, 2> {
+ public:
+  LFastAllocate(LOperand* size, LOperand* temp1, LOperand* temp2) {
+    inputs_[0] = size;
+    temps_[0] = temp1;
+    temps_[1] = temp2;
+  }
+
+  LOperand* size() { return inputs_[0]; }
+  LOperand* temp1() { return temps_[0]; }
+  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(FastAllocate, "fast-allocate")
+  DECLARE_HYDROGEN_ACCESSOR(Allocate)
+};
+
 
 class LTypeof final : public LTemplateInstruction<1, 2, 0> {
  public:
@@ -2441,6 +2456,8 @@
   LInstruction* DoMathFround(HUnaryMathOperation* instr);
   LInstruction* DoMathAbs(HUnaryMathOperation* instr);
   LInstruction* DoMathLog(HUnaryMathOperation* instr);
+  LInstruction* DoMathCos(HUnaryMathOperation* instr);
+  LInstruction* DoMathSin(HUnaryMathOperation* instr);
   LInstruction* DoMathExp(HUnaryMathOperation* instr);
   LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
   LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
diff --git a/src/crankshaft/s390/OWNERS b/src/crankshaft/s390/OWNERS
index eb007cb..752e8e3 100644
--- a/src/crankshaft/s390/OWNERS
+++ b/src/crankshaft/s390/OWNERS
@@ -3,3 +3,4 @@
 joransiu@ca.ibm.com
 mbrandy@us.ibm.com
 michael_dawson@ca.ibm.com
+bjaideep@ca.ibm.com
diff --git a/src/crankshaft/s390/lithium-codegen-s390.cc b/src/crankshaft/s390/lithium-codegen-s390.cc
index 689f4bc..890545c 100644
--- a/src/crankshaft/s390/lithium-codegen-s390.cc
+++ b/src/crankshaft/s390/lithium-codegen-s390.cc
@@ -12,7 +12,6 @@
 #include "src/crankshaft/s390/lithium-gap-resolver-s390.h"
 #include "src/ic/ic.h"
 #include "src/ic/stub-cache.h"
-#include "src/profiler/cpu-profiler.h"
 
 namespace v8 {
 namespace internal {
@@ -312,8 +311,6 @@
       } else {
         __ b(r14, &call_deopt_entry);
       }
-      info()->LogDeoptCallPosition(masm()->pc_offset(),
-                                   table_entry->deopt_info.inlining_id);
     }
 
     if (needs_frame.is_linked()) {
@@ -746,20 +743,19 @@
     __ stop("trap_on_deopt", cond, kDefaultStopCode, cr);
   }
 
-  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason);
+  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason, id);
 
   DCHECK(info()->IsStub() || frame_is_built_);
   // Go through jump table if we need to handle condition, build frame, or
   // restore caller doubles.
   if (cond == al && frame_is_built_ && !info()->saves_caller_doubles()) {
     __ Call(entry, RelocInfo::RUNTIME_ENTRY);
-    info()->LogDeoptCallPosition(masm()->pc_offset(), deopt_info.inlining_id);
   } else {
     Deoptimizer::JumpTableEntry table_entry(entry, deopt_info, bailout_type,
                                             !frame_is_built_);
     // We often have several deopts to the same entry, reuse the last
     // jump entry if this is the case.
-    if (FLAG_trace_deopt || isolate()->cpu_profiler()->is_profiling() ||
+    if (FLAG_trace_deopt || isolate()->is_profiling() ||
         jump_table_.is_empty() ||
         !table_entry.IsEquivalentTo(jump_table_.last())) {
       jump_table_.Add(table_entry, zone());
@@ -823,7 +819,6 @@
 void LCodeGen::RecordAndWritePosition(int position) {
   if (position == RelocInfo::kNoPosition) return;
   masm()->positions_recorder()->RecordPosition(position);
-  masm()->positions_recorder()->WriteRecordedPositions();
 }
 
 static const char* LabelType(LLabel* label) {
@@ -2541,15 +2536,6 @@
   EmitBranch(instr, eq);
 }
 
-void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
-  DCHECK(ToRegister(instr->context()).is(cp));
-  DCHECK(ToRegister(instr->left()).is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(ToRegister(instr->right()).is(InstanceOfDescriptor::RightRegister()));
-  DCHECK(ToRegister(instr->result()).is(r2));
-  InstanceOfStub stub(isolate());
-  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
-}
-
 void LCodeGen::DoHasInPrototypeChainAndBranch(
     LHasInPrototypeChainAndBranch* instr) {
   Register const object = ToRegister(instr->object());
@@ -2580,10 +2566,10 @@
   DeoptimizeIf(eq, instr, Deoptimizer::kProxy);
   __ LoadP(object_prototype,
            FieldMemOperand(object_map, Map::kPrototypeOffset));
-  __ CmpP(object_prototype, prototype);
-  EmitTrueBranch(instr, eq);
   __ CompareRoot(object_prototype, Heap::kNullValueRootIndex);
   EmitFalseBranch(instr, eq);
+  __ CmpP(object_prototype, prototype);
+  EmitTrueBranch(instr, eq);
   __ LoadP(object_map,
            FieldMemOperand(object_prototype, HeapObject::kMapOffset));
   __ b(&loop);
@@ -2682,15 +2668,12 @@
 
 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   DCHECK(ToRegister(instr->context()).is(cp));
-  DCHECK(ToRegister(instr->global_object())
-             .is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->result()).is(r2));
 
-  __ mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), instr->typeof_mode(), PREMONOMORPHIC)
-                        .code();
+  Handle<Code> ic =
+      CodeFactory::LoadGlobalICInOptimizedCode(isolate(), instr->typeof_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2791,10 +2774,7 @@
   // Name is always in r4.
   __ mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_INSIDE_TYPEOF,
-                        instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2884,6 +2864,7 @@
   }
   int element_size_shift = ElementsKindToShiftSize(elements_kind);
   bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi();
+  bool keyMaybeNegative = instr->hydrogen()->IsDehoisted();
   int base_offset = instr->base_offset();
   bool use_scratch = false;
 
@@ -2897,7 +2878,8 @@
         use_scratch = true;
       }
     } else {
-      __ IndexToArrayOffset(scratch0(), key, element_size_shift, key_is_smi);
+      __ IndexToArrayOffset(scratch0(), key, element_size_shift, key_is_smi,
+                            keyMaybeNegative);
       use_scratch = true;
     }
     if (elements_kind == FLOAT32_ELEMENTS) {
@@ -2917,7 +2899,8 @@
     Register result = ToRegister(instr->result());
     MemOperand mem_operand =
         PrepareKeyedOperand(key, external_pointer, key_is_constant, key_is_smi,
-                            constant_key, element_size_shift, base_offset);
+                            constant_key, element_size_shift, base_offset,
+                            keyMaybeNegative);
     switch (elements_kind) {
       case INT8_ELEMENTS:
         __ LoadB(result, mem_operand);
@@ -2971,6 +2954,7 @@
 
   int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
   bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi();
+  bool keyMaybeNegative = instr->hydrogen()->IsDehoisted();
   int constant_key = 0;
   if (key_is_constant) {
     constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
@@ -2985,7 +2969,8 @@
   intptr_t base_offset = instr->base_offset() + constant_key * kDoubleSize;
   if (!key_is_constant) {
     use_scratch = true;
-    __ IndexToArrayOffset(scratch, key, element_size_shift, key_is_smi);
+    __ IndexToArrayOffset(scratch, key, element_size_shift, key_is_smi,
+                          keyMaybeNegative);
   }
 
   // Memory references support up to 20-bits signed displacement in RXY form
@@ -3107,7 +3092,8 @@
                                          bool key_is_constant, bool key_is_smi,
                                          int constant_key,
                                          int element_size_shift,
-                                         int base_offset) {
+                                         int base_offset,
+                                         bool keyMaybeNegative) {
   Register scratch = scratch0();
 
   if (key_is_constant) {
@@ -3125,7 +3111,8 @@
       (element_size_shift != (key_is_smi ? kSmiTagSize + kSmiShiftSize : 0));
 
   if (needs_shift) {
-    __ IndexToArrayOffset(scratch, key, element_size_shift, key_is_smi);
+    __ IndexToArrayOffset(scratch, key, element_size_shift, key_is_smi,
+                          keyMaybeNegative);
   } else {
     scratch = key;
   }
@@ -3141,14 +3128,9 @@
   DCHECK(ToRegister(instr->context()).is(cp));
   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister()));
+  EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
-  }
-
-  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
-                        isolate(), instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3683,23 +3665,31 @@
   }
 }
 
-void LCodeGen::DoMathExp(LMathExp* instr) {
-  DoubleRegister input = ToDoubleRegister(instr->value());
-  DoubleRegister result = ToDoubleRegister(instr->result());
-  DoubleRegister double_scratch1 = ToDoubleRegister(instr->double_temp());
-  DoubleRegister double_scratch2 = double_scratch0();
-  Register temp1 = ToRegister(instr->temp1());
-  Register temp2 = ToRegister(instr->temp2());
+void LCodeGen::DoMathCos(LMathCos* instr) {
+  __ PrepareCallCFunction(0, 1, scratch0());
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
+  __ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 0, 1);
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
+}
 
-  MathExpGenerator::EmitMathExp(masm(), input, result, double_scratch1,
-                                double_scratch2, temp1, temp2, scratch0());
+void LCodeGen::DoMathSin(LMathSin* instr) {
+  __ PrepareCallCFunction(0, 1, scratch0());
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
+  __ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 0, 1);
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
+}
+
+void LCodeGen::DoMathExp(LMathExp* instr) {
+  __ PrepareCallCFunction(0, 1, scratch0());
+  __ MovToFloatParameter(ToDoubleRegister(instr->value()));
+  __ CallCFunction(ExternalReference::ieee754_exp_function(isolate()), 0, 1);
+  __ MovFromFloatResult(ToDoubleRegister(instr->result()));
 }
 
 void LCodeGen::DoMathLog(LMathLog* instr) {
   __ PrepareCallCFunction(0, 1, scratch0());
   __ MovToFloatParameter(ToDoubleRegister(instr->value()));
-  __ CallCFunction(ExternalReference::math_log_double_function(isolate()), 0,
-                   1);
+  __ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 0, 1);
   __ MovFromFloatResult(ToDoubleRegister(instr->result()));
 }
 
@@ -3728,7 +3718,9 @@
 #endif
   if (FLAG_code_comments) {
     if (actual.is_reg()) {
-      Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString());
+      Comment(";;; PrepareForTailCall, actual: %s {",
+              RegisterConfiguration::Crankshaft()->GetGeneralRegisterName(
+                  actual.reg().code()));
     } else {
       Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate());
     }
@@ -3832,14 +3824,8 @@
   DCHECK(ToRegister(instr->result()).is(r2));
 
   __ mov(r2, Operand(instr->arity()));
-  if (instr->arity() == 1) {
-    // We only need the allocation site for the case we have a length argument.
-    // The case may bail out to the runtime, which will determine the correct
-    // elements kind with the site.
-    __ Move(r4, instr->hydrogen()->site());
-  } else {
-    __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
-  }
+  __ Move(r4, instr->hydrogen()->site());
+
   ElementsKind kind = instr->hydrogen()->elements_kind();
   AllocationSiteOverrideMode override_mode =
       (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
@@ -3871,7 +3857,7 @@
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
     __ bind(&done);
   } else {
-    ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
+    ArrayNArgumentsConstructorStub stub(isolate());
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   }
 }
@@ -4002,15 +3988,12 @@
   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
 
   __ mov(StoreDescriptor::NameRegister(), Operand(instr->name()));
-  Handle<Code> ic = CodeFactory::StoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic =
+      CodeFactory::StoreICInOptimizedCode(isolate(), instr->language_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -4072,6 +4055,7 @@
   }
   int element_size_shift = ElementsKindToShiftSize(elements_kind);
   bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi();
+  bool keyMaybeNegative = instr->hydrogen()->IsDehoisted();
   int base_offset = instr->base_offset();
 
   if (elements_kind == FLOAT32_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) {
@@ -4091,7 +4075,8 @@
         address = external_pointer;
       }
     } else {
-      __ IndexToArrayOffset(address, key, element_size_shift, key_is_smi);
+      __ IndexToArrayOffset(address, key, element_size_shift, key_is_smi,
+                            keyMaybeNegative);
       __ AddP(address, external_pointer);
     }
     if (elements_kind == FLOAT32_ELEMENTS) {
@@ -4104,7 +4089,8 @@
     Register value(ToRegister(instr->value()));
     MemOperand mem_operand =
         PrepareKeyedOperand(key, external_pointer, key_is_constant, key_is_smi,
-                            constant_key, element_size_shift, base_offset);
+                            constant_key, element_size_shift, base_offset,
+                            keyMaybeNegative);
     switch (elements_kind) {
       case UINT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
@@ -4172,6 +4158,7 @@
   }
   int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
   bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi();
+  bool keyMaybeNegative = instr->hydrogen()->IsDehoisted();
   int base_offset = instr->base_offset() + constant_key * kDoubleSize;
   bool use_scratch = false;
   intptr_t address_offset = base_offset;
@@ -4185,7 +4172,8 @@
     }
   } else {
     use_scratch = true;
-    __ IndexToArrayOffset(scratch, key, element_size_shift, key_is_smi);
+    __ IndexToArrayOffset(scratch, key, element_size_shift, key_is_smi,
+                          keyMaybeNegative);
     // Memory references support up to 20-bits signed displacement in RXY form
     if (!is_int20((address_offset))) {
       __ AddP(scratch, Operand(address_offset));
@@ -4303,13 +4291,10 @@
   DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
 
   Handle<Code> ic = CodeFactory::KeyedStoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state())
+                        isolate(), instr->language_mode())
                         .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
@@ -4387,7 +4372,15 @@
 
     LOperand* key = instr->key();
     if (key->IsConstantOperand()) {
-      __ LoadSmiLiteral(r5, ToSmi(LConstantOperand::cast(key)));
+      LConstantOperand* constant_key = LConstantOperand::cast(key);
+      int32_t int_key = ToInteger32(constant_key);
+      if (Smi::IsValid(int_key)) {
+        __ LoadSmiLiteral(r5, Smi::FromInt(int_key));
+      } else {
+        // We should never get here at runtime because there is a smi check on
+        // the key before this point.
+        __ stop("expected smi");
+      }
     } else {
       __ SmiTag(r5, ToRegister(key));
     }
@@ -4431,8 +4424,7 @@
     DCHECK(object_reg.is(r2));
     PushSafepointRegistersScope scope(this);
     __ Move(r3, to_map);
-    bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
-    TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
+    TransitionElementsKindStub stub(isolate(), from_kind, to_kind);
     __ CallStub(&stub);
     RecordSafepointWithRegisters(instr->pointer_map(), 0,
                                  Safepoint::kLazyDeopt);
@@ -5211,20 +5203,6 @@
   }
 }
 
-void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
-  Register hi_reg = ToRegister(instr->hi());
-  Register lo_reg = ToRegister(instr->lo());
-  DoubleRegister result_reg = ToDoubleRegister(instr->result());
-  Register scratch = scratch0();
-
-  // Combine hi_reg:lo_reg into a single 64-bit register.
-  __ sllg(scratch, hi_reg, Operand(32));
-  __ lr(scratch, lo_reg);
-
-  // Bitwise convert from GPR to FPR
-  __ ldgr(result_reg, scratch);
-}
-
 void LCodeGen::DoAllocate(LAllocate* instr) {
   class DeferredAllocate final : public LDeferredCode {
    public:
@@ -5244,7 +5222,7 @@
   Register scratch2 = ToRegister(instr->temp2());
 
   // Allocate memory for the object.
-  AllocationFlags flags = TAG_OBJECT;
+  AllocationFlags flags = NO_ALLOCATION_FLAGS;
   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
   }
@@ -5253,6 +5231,12 @@
     flags = static_cast<AllocationFlags>(flags | PRETENURE);
   }
 
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    flags = static_cast<AllocationFlags>(flags | ALLOCATION_FOLDING_DOMINATOR);
+  }
+
+  DCHECK(!instr->hydrogen()->IsAllocationFolded());
+
   if (instr->size()->IsConstantOperand()) {
     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
     CHECK(size <= Page::kMaxRegularHeapObjectSize);
@@ -5331,6 +5315,49 @@
   CallRuntimeFromDeferred(Runtime::kAllocateInTargetSpace, 2, instr,
                           instr->context());
   __ StoreToSafepointRegisterSlot(r2, result);
+
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    AllocationFlags allocation_flags = NO_ALLOCATION_FLAGS;
+    if (instr->hydrogen()->IsOldSpaceAllocation()) {
+      DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+      allocation_flags = static_cast<AllocationFlags>(flags | PRETENURE);
+    }
+    // If the allocation folding dominator allocate triggered a GC, allocation
+    // happend in the runtime. We have to reset the top pointer to virtually
+    // undo the allocation.
+    ExternalReference allocation_top =
+        AllocationUtils::GetAllocationTopReference(isolate(), allocation_flags);
+    Register top_address = scratch0();
+    __ SubP(r2, r2, Operand(kHeapObjectTag));
+    __ mov(top_address, Operand(allocation_top));
+    __ StoreP(r2, MemOperand(top_address));
+    __ AddP(r2, r2, Operand(kHeapObjectTag));
+  }
+}
+
+void LCodeGen::DoFastAllocate(LFastAllocate* instr) {
+  DCHECK(instr->hydrogen()->IsAllocationFolded());
+  DCHECK(!instr->hydrogen()->IsAllocationFoldingDominator());
+  Register result = ToRegister(instr->result());
+  Register scratch1 = ToRegister(instr->temp1());
+  Register scratch2 = ToRegister(instr->temp2());
+
+  AllocationFlags flags = ALLOCATION_FOLDED;
+  if (instr->hydrogen()->MustAllocateDoubleAligned()) {
+    flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
+  }
+  if (instr->hydrogen()->IsOldSpaceAllocation()) {
+    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+    flags = static_cast<AllocationFlags>(flags | PRETENURE);
+  }
+  if (instr->size()->IsConstantOperand()) {
+    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
+    CHECK(size <= Page::kMaxRegularHeapObjectSize);
+    __ FastAllocate(size, result, scratch1, scratch2, flags);
+  } else {
+    Register size = ToRegister(instr->size());
+    __ FastAllocate(size, result, scratch1, scratch2, flags);
+  }
 }
 
 void LCodeGen::DoTypeof(LTypeof* instr) {
diff --git a/src/crankshaft/s390/lithium-codegen-s390.h b/src/crankshaft/s390/lithium-codegen-s390.h
index 6d364cb..6abd4fa 100644
--- a/src/crankshaft/s390/lithium-codegen-s390.h
+++ b/src/crankshaft/s390/lithium-codegen-s390.h
@@ -116,7 +116,8 @@
   MemOperand PrepareKeyedOperand(Register key, Register base,
                                  bool key_is_constant, bool key_is_tagged,
                                  int constant_key, int element_size_shift,
-                                 int base_offset);
+                                 int base_offset,
+                                 bool keyMaybeNegative = true);
 
   // Emit frame translation commands for an environment.
   void WriteTranslation(LEnvironment* environment, Translation* translation);
@@ -127,8 +128,6 @@
 #undef DECLARE_DO
 
  private:
-  LanguageMode language_mode() const { return info()->language_mode(); }
-
   Scope* scope() const { return scope_; }
 
   Register scratch0() { return kLithiumScratch; }
diff --git a/src/crankshaft/s390/lithium-s390.cc b/src/crankshaft/s390/lithium-s390.cc
index a18f877..033484c 100644
--- a/src/crankshaft/s390/lithium-s390.cc
+++ b/src/crankshaft/s390/lithium-s390.cc
@@ -815,7 +815,7 @@
 
 LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) {
   LInstruction* result = new (zone()) LPrologue();
-  if (info_->num_heap_slots() > 0) {
+  if (info_->scope()->num_heap_slots() > 0) {
     result = MarkAsCall(result, instr);
   }
   return result;
@@ -865,16 +865,6 @@
   return DefineAsRegister(new (zone()) LArgumentsElements);
 }
 
-LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
-  LOperand* left =
-      UseFixed(instr->left(), InstanceOfDescriptor::LeftRegister());
-  LOperand* right =
-      UseFixed(instr->right(), InstanceOfDescriptor::RightRegister());
-  LOperand* context = UseFixed(instr->context(), cp);
-  LInstanceOf* result = new (zone()) LInstanceOf(context, left, right);
-  return MarkAsCall(DefineFixed(result, r2), instr);
-}
-
 LInstruction* LChunkBuilder::DoHasInPrototypeChainAndBranch(
     HHasInPrototypeChainAndBranch* instr) {
   LOperand* object = UseRegister(instr->object());
@@ -995,6 +985,10 @@
       return DoMathAbs(instr);
     case kMathLog:
       return DoMathLog(instr);
+    case kMathCos:
+      return DoMathCos(instr);
+    case kMathSin:
+      return DoMathSin(instr);
     case kMathExp:
       return DoMathExp(instr);
     case kMathSqrt:
@@ -1044,8 +1038,8 @@
 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
   DCHECK(instr->representation().IsDouble());
   DCHECK(instr->value()->representation().IsDouble());
-  LOperand* input = UseFixedDouble(instr->value(), d1);
-  return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), d1), instr);
+  LOperand* input = UseFixedDouble(instr->value(), d0);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), d0), instr);
 }
 
 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
@@ -1054,15 +1048,25 @@
   return DefineAsRegister(result);
 }
 
+LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
+  DCHECK(instr->representation().IsDouble());
+  DCHECK(instr->value()->representation().IsDouble());
+  LOperand* input = UseFixedDouble(instr->value(), d0);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathCos(input), d0), instr);
+}
+
+LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
+  DCHECK(instr->representation().IsDouble());
+  DCHECK(instr->value()->representation().IsDouble());
+  LOperand* input = UseFixedDouble(instr->value(), d0);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathSin(input), d0), instr);
+}
+
 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
   DCHECK(instr->representation().IsDouble());
   DCHECK(instr->value()->representation().IsDouble());
-  LOperand* input = UseRegister(instr->value());
-  LOperand* temp1 = TempRegister();
-  LOperand* temp2 = TempRegister();
-  LOperand* double_temp = TempDoubleRegister();
-  LMathExp* result = new (zone()) LMathExp(input, double_temp, temp1, temp2);
-  return DefineAsRegister(result);
+  LOperand* input = UseFixedDouble(instr->value(), d0);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathExp(input), d0), instr);
 }
 
 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
@@ -1789,12 +1793,6 @@
   return DefineAsRegister(new (zone()) LDoubleBits(UseRegister(value)));
 }
 
-LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
-  LOperand* lo = UseRegister(instr->lo());
-  LOperand* hi = UseRegister(instr->hi());
-  return DefineAsRegister(new (zone()) LConstructDouble(hi, lo));
-}
-
 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
   LOperand* context = info()->IsStub() ? UseFixed(instr->context(), cp) : NULL;
   LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
@@ -1822,14 +1820,9 @@
 
 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
-  LOperand* global_object =
-      UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
-  LLoadGlobalGeneric* result =
-      new (zone()) LLoadGlobalGeneric(context, global_object, vector);
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
+
+  LLoadGlobalGeneric* result = new (zone()) LLoadGlobalGeneric(context, vector);
   return MarkAsCall(DefineFixed(result, r2), instr);
 }
 
@@ -1869,10 +1862,7 @@
   LOperand* context = UseFixed(instr->context(), cp);
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
   LInstruction* result =
       DefineFixed(new (zone()) LLoadNamedGeneric(context, object, vector), r2);
@@ -1938,10 +1928,7 @@
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
   LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
   LInstruction* result = DefineFixed(
       new (zone()) LLoadKeyedGeneric(context, object, key, vector), r2);
@@ -1998,12 +1985,8 @@
   DCHECK(instr->key()->representation().IsTagged());
   DCHECK(instr->value()->representation().IsTagged());
 
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
 
   LStoreKeyedGeneric* result =
       new (zone()) LStoreKeyedGeneric(context, obj, key, val, slot, vector);
@@ -2086,13 +2069,8 @@
   LOperand* obj =
       UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
   LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
-
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
   LStoreNamedGeneric* result =
       new (zone()) LStoreNamedGeneric(context, obj, val, slot, vector);
   return MarkAsCall(result, instr);
@@ -2124,13 +2102,18 @@
 }
 
 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
-  info()->MarkAsDeferredCalling();
-  LOperand* context = UseAny(instr->context());
   LOperand* size = UseRegisterOrConstant(instr->size());
   LOperand* temp1 = TempRegister();
   LOperand* temp2 = TempRegister();
-  LAllocate* result = new (zone()) LAllocate(context, size, temp1, temp2);
-  return AssignPointerMap(DefineAsRegister(result));
+  if (instr->IsAllocationFolded()) {
+    LFastAllocate* result = new (zone()) LFastAllocate(size, temp1, temp2);
+    return DefineAsRegister(result);
+  } else {
+    info()->MarkAsDeferredCalling();
+    LOperand* context = UseAny(instr->context());
+    LAllocate* result = new (zone()) LAllocate(context, size, temp1, temp2);
+    return AssignPointerMap(DefineAsRegister(result));
+  }
 }
 
 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
diff --git a/src/crankshaft/s390/lithium-s390.h b/src/crankshaft/s390/lithium-s390.h
index b6a1614..283629f 100644
--- a/src/crankshaft/s390/lithium-s390.h
+++ b/src/crankshaft/s390/lithium-s390.h
@@ -53,7 +53,6 @@
   V(ConstantI)                               \
   V(ConstantS)                               \
   V(ConstantT)                               \
-  V(ConstructDouble)                         \
   V(Context)                                 \
   V(DebugBreak)                              \
   V(DeclareGlobals)                          \
@@ -67,6 +66,7 @@
   V(Drop)                                    \
   V(Dummy)                                   \
   V(DummyUse)                                \
+  V(FastAllocate)                            \
   V(FlooringDivByConstI)                     \
   V(FlooringDivByPowerOf2I)                  \
   V(FlooringDivI)                            \
@@ -78,7 +78,6 @@
   V(HasInPrototypeChainAndBranch)            \
   V(HasInstanceTypeAndBranch)                \
   V(InnerAllocatedObject)                    \
-  V(InstanceOf)                              \
   V(InstructionGap)                          \
   V(Integer32ToDouble)                       \
   V(InvokeFunction)                          \
@@ -98,6 +97,8 @@
   V(LoadNamedGeneric)                        \
   V(MathAbs)                                 \
   V(MathClz32)                               \
+  V(MathCos)                                 \
+  V(MathSin)                                 \
   V(MathExp)                                 \
   V(MathFloor)                               \
   V(MathFround)                              \
@@ -836,21 +837,29 @@
   DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
 };
 
-class LMathExp final : public LTemplateInstruction<1, 1, 3> {
+class LMathCos final : public LTemplateInstruction<1, 1, 0> {
  public:
-  LMathExp(LOperand* value, LOperand* double_temp, LOperand* temp1,
-           LOperand* temp2) {
-    inputs_[0] = value;
-    temps_[0] = temp1;
-    temps_[1] = temp2;
-    temps_[2] = double_temp;
-    ExternalReference::InitializeMathExpData();
-  }
+  explicit LMathCos(LOperand* value) { inputs_[0] = value; }
 
   LOperand* value() { return inputs_[0]; }
-  LOperand* temp1() { return temps_[0]; }
-  LOperand* temp2() { return temps_[1]; }
-  LOperand* double_temp() { return temps_[2]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
+};
+
+class LMathSin final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathSin(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
+};
+
+class LMathExp final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathExp(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
 };
@@ -1035,21 +1044,6 @@
   Token::Value op() const { return hydrogen()->token(); }
 };
 
-class LInstanceOf final : public LTemplateInstruction<1, 3, 0> {
- public:
-  LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
-    inputs_[0] = context;
-    inputs_[1] = left;
-    inputs_[2] = right;
-  }
-
-  LOperand* context() const { return inputs_[0]; }
-  LOperand* left() const { return inputs_[1]; }
-  LOperand* right() const { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
-};
-
 class LHasInPrototypeChainAndBranch final : public LControlInstruction<2, 0> {
  public:
   LHasInPrototypeChainAndBranch(LOperand* object, LOperand* prototype) {
@@ -1445,17 +1439,14 @@
   DECLARE_HYDROGEN_ACCESSOR(LoadKeyedGeneric)
 };
 
-class LLoadGlobalGeneric final : public LTemplateInstruction<1, 2, 1> {
+class LLoadGlobalGeneric final : public LTemplateInstruction<1, 1, 1> {
  public:
-  LLoadGlobalGeneric(LOperand* context, LOperand* global_object,
-                     LOperand* vector) {
+  LLoadGlobalGeneric(LOperand* context, LOperand* vector) {
     inputs_[0] = context;
-    inputs_[1] = global_object;
     temps_[0] = vector;
   }
 
   LOperand* context() { return inputs_[0]; }
-  LOperand* global_object() { return inputs_[1]; }
   LOperand* temp_vector() { return temps_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
@@ -2133,19 +2124,6 @@
   DECLARE_HYDROGEN_ACCESSOR(DoubleBits)
 };
 
-class LConstructDouble final : public LTemplateInstruction<1, 2, 0> {
- public:
-  LConstructDouble(LOperand* hi, LOperand* lo) {
-    inputs_[0] = hi;
-    inputs_[1] = lo;
-  }
-
-  LOperand* hi() { return inputs_[0]; }
-  LOperand* lo() { return inputs_[1]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
-};
-
 class LAllocate final : public LTemplateInstruction<1, 2, 2> {
  public:
   LAllocate(LOperand* context, LOperand* size, LOperand* temp1,
@@ -2165,6 +2143,22 @@
   DECLARE_HYDROGEN_ACCESSOR(Allocate)
 };
 
+class LFastAllocate final : public LTemplateInstruction<1, 1, 2> {
+ public:
+  LFastAllocate(LOperand* size, LOperand* temp1, LOperand* temp2) {
+    inputs_[0] = size;
+    temps_[0] = temp1;
+    temps_[1] = temp2;
+  }
+
+  LOperand* size() { return inputs_[0]; }
+  LOperand* temp1() { return temps_[0]; }
+  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(FastAllocate, "fast-allocate")
+  DECLARE_HYDROGEN_ACCESSOR(Allocate)
+};
+
 class LTypeof final : public LTemplateInstruction<1, 2, 0> {
  public:
   LTypeof(LOperand* context, LOperand* value) {
@@ -2302,6 +2296,8 @@
   LInstruction* DoMathFround(HUnaryMathOperation* instr);
   LInstruction* DoMathAbs(HUnaryMathOperation* instr);
   LInstruction* DoMathLog(HUnaryMathOperation* instr);
+  LInstruction* DoMathCos(HUnaryMathOperation* instr);
+  LInstruction* DoMathSin(HUnaryMathOperation* instr);
   LInstruction* DoMathExp(HUnaryMathOperation* instr);
   LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
   LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
diff --git a/src/crankshaft/typing.cc b/src/crankshaft/typing.cc
index 69d7efe..013f50f 100644
--- a/src/crankshaft/typing.cc
+++ b/src/crankshaft/typing.cc
@@ -14,9 +14,9 @@
 namespace v8 {
 namespace internal {
 
-
 AstTyper::AstTyper(Isolate* isolate, Zone* zone, Handle<JSFunction> closure,
-                   Scope* scope, BailoutId osr_ast_id, FunctionLiteral* root)
+                   Scope* scope, BailoutId osr_ast_id, FunctionLiteral* root,
+                   AstTypeBounds* bounds)
     : isolate_(isolate),
       zone_(zone),
       closure_(closure),
@@ -24,9 +24,10 @@
       osr_ast_id_(osr_ast_id),
       root_(root),
       oracle_(isolate, zone, handle(closure->shared()->code()),
-              handle(closure->shared()->feedback_vector()),
+              handle(closure->feedback_vector()),
               handle(closure->context()->native_context())),
-      store_(zone) {
+      store_(zone),
+      bounds_(bounds) {
   InitializeAstVisitor(isolate);
 }
 
@@ -304,14 +305,7 @@
   store_.Forget();  // Control may transfer here via 'break'.
 }
 
-
-void AstTyper::VisitForOfStatement(ForOfStatement* stmt) {
-  RECURSE(Visit(stmt->iterable()));
-  store_.Forget();  // Control may transfer here via looping or 'continue'.
-  RECURSE(Visit(stmt->body()));
-  store_.Forget();  // Control may transfer here via 'break'.
-}
-
+void AstTyper::VisitForOfStatement(ForOfStatement* stmt) {}
 
 void AstTyper::VisitTryCatchStatement(TryCatchStatement* stmt) {
   Effects try_effects = EnterEffects();
@@ -353,7 +347,7 @@
 void AstTyper::VisitDoExpression(DoExpression* expr) {
   RECURSE(VisitBlock(expr->block()));
   RECURSE(VisitVariableProxy(expr->result()));
-  NarrowType(expr, expr->result()->bounds());
+  NarrowType(expr, bounds_->get(expr->result()));
 }
 
 
@@ -371,9 +365,9 @@
   then_effects.Alt(else_effects);
   store_.Seq(then_effects);
 
-  NarrowType(expr, Bounds::Either(
-      expr->then_expression()->bounds(),
-      expr->else_expression()->bounds(), zone()));
+  NarrowType(expr,
+             Bounds::Either(bounds_->get(expr->then_expression()),
+                            bounds_->get(expr->else_expression()), zone()));
 }
 
 
@@ -464,11 +458,11 @@
       expr->is_compound() ? expr->binary_operation() : expr->value();
   RECURSE(Visit(expr->target()));
   RECURSE(Visit(rhs));
-  NarrowType(expr, rhs->bounds());
+  NarrowType(expr, bounds_->get(rhs));
 
   VariableProxy* proxy = expr->target()->AsVariableProxy();
   if (proxy != NULL && proxy->var()->IsStackAllocated()) {
-    store_.Seq(variable_index(proxy->var()), Effect(expr->bounds()));
+    store_.Seq(variable_index(proxy->var()), Effect(bounds_->get(expr)));
   }
 }
 
@@ -628,7 +622,7 @@
 
   VariableProxy* proxy = expr->expression()->AsVariableProxy();
   if (proxy != NULL && proxy->var()->IsStackAllocated()) {
-    store_.Seq(variable_index(proxy->var()), Effect(expr->bounds()));
+    store_.Seq(variable_index(proxy->var()), Effect(bounds_->get(expr)));
   }
 }
 
@@ -656,7 +650,7 @@
     case Token::COMMA:
       RECURSE(Visit(expr->left()));
       RECURSE(Visit(expr->right()));
-      NarrowType(expr, expr->right()->bounds());
+      NarrowType(expr, bounds_->get(expr->right()));
       break;
     case Token::OR:
     case Token::AND: {
@@ -669,16 +663,16 @@
       left_effects.Alt(right_effects);
       store_.Seq(left_effects);
 
-      NarrowType(expr, Bounds::Either(
-          expr->left()->bounds(), expr->right()->bounds(), zone()));
+      NarrowType(expr, Bounds::Either(bounds_->get(expr->left()),
+                                      bounds_->get(expr->right()), zone()));
       break;
     }
     case Token::BIT_OR:
     case Token::BIT_AND: {
       RECURSE(Visit(expr->left()));
       RECURSE(Visit(expr->right()));
-      Type* upper = Type::Union(
-          expr->left()->bounds().upper, expr->right()->bounds().upper, zone());
+      Type* upper = Type::Union(bounds_->get(expr->left()).upper,
+                                bounds_->get(expr->right()).upper, zone());
       if (!upper->Is(Type::Signed32())) upper = Type::Signed32();
       Type* lower = Type::Intersect(Type::SignedSmall(), upper, zone());
       NarrowType(expr, Bounds(lower, upper));
@@ -702,8 +696,8 @@
     case Token::ADD: {
       RECURSE(Visit(expr->left()));
       RECURSE(Visit(expr->right()));
-      Bounds l = expr->left()->bounds();
-      Bounds r = expr->right()->bounds();
+      Bounds l = bounds_->get(expr->left());
+      Bounds r = bounds_->get(expr->right());
       Type* lower =
           !l.lower->IsInhabited() || !r.lower->IsInhabited()
               ? Type::None()
diff --git a/src/crankshaft/typing.h b/src/crankshaft/typing.h
index 40b538a..27b6809 100644
--- a/src/crankshaft/typing.h
+++ b/src/crankshaft/typing.h
@@ -6,6 +6,7 @@
 #define V8_CRANKSHAFT_TYPING_H_
 
 #include "src/allocation.h"
+#include "src/ast/ast-type-bounds.h"
 #include "src/ast/ast.h"
 #include "src/ast/scopes.h"
 #include "src/effects.h"
@@ -16,11 +17,11 @@
 namespace v8 {
 namespace internal {
 
-
 class AstTyper: public AstVisitor {
  public:
   AstTyper(Isolate* isolate, Zone* zone, Handle<JSFunction> closure,
-           Scope* scope, BailoutId osr_ast_id, FunctionLiteral* root);
+           Scope* scope, BailoutId osr_ast_id, FunctionLiteral* root,
+           AstTypeBounds* bounds);
   void Run();
 
   DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
@@ -41,15 +42,16 @@
   FunctionLiteral* root_;
   TypeFeedbackOracle oracle_;
   Store store_;
+  AstTypeBounds* bounds_;
 
   Zone* zone() const { return zone_; }
   TypeFeedbackOracle* oracle() { return &oracle_; }
 
   void NarrowType(Expression* e, Bounds b) {
-    e->set_bounds(Bounds::Both(e->bounds(), b, zone()));
+    bounds_->set(e, Bounds::Both(bounds_->get(e), b, zone()));
   }
   void NarrowLowerType(Expression* e, Type* t) {
-    e->set_bounds(Bounds::NarrowLower(e->bounds(), t, zone()));
+    bounds_->set(e, Bounds::NarrowLower(bounds_->get(e), t, zone()));
   }
 
   Effects EnterEffects() {
diff --git a/src/crankshaft/x64/lithium-codegen-x64.cc b/src/crankshaft/x64/lithium-codegen-x64.cc
index fbda59b..c82f6c1 100644
--- a/src/crankshaft/x64/lithium-codegen-x64.cc
+++ b/src/crankshaft/x64/lithium-codegen-x64.cc
@@ -12,7 +12,6 @@
 #include "src/crankshaft/hydrogen-osr.h"
 #include "src/ic/ic.h"
 #include "src/ic/stub-cache.h"
-#include "src/profiler/cpu-profiler.h"
 
 namespace v8 {
 namespace internal {
@@ -168,11 +167,11 @@
   Comment(";;; Prologue begin");
 
   // Possibly allocate a local context.
-  if (info_->num_heap_slots() > 0) {
+  if (info_->scope()->num_heap_slots() > 0) {
     Comment(";;; Allocate local context");
     bool need_write_barrier = true;
     // Argument to NewContext is the function, which is still in rdi.
-    int slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+    int slots = info_->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
     Safepoint::DeoptMode deopt_mode = Safepoint::kNoLazyDeopt;
     if (info()->scope()->is_script_scope()) {
       __ Push(rdi);
@@ -299,8 +298,6 @@
       }
       __ call(entry, RelocInfo::RUNTIME_ENTRY);
     }
-    info()->LogDeoptCallPosition(masm()->pc_offset(),
-                                 table_entry->deopt_info.inlining_id);
   }
 
   if (needs_frame.is_linked()) {
@@ -748,7 +745,7 @@
     __ bind(&done);
   }
 
-  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason);
+  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason, id);
 
   DCHECK(info()->IsStub() || frame_is_built_);
   // Go through jump table if we need to handle condition, build frame, or
@@ -757,13 +754,12 @@
       !info()->saves_caller_doubles()) {
     DeoptComment(deopt_info);
     __ call(entry, RelocInfo::RUNTIME_ENTRY);
-    info()->LogDeoptCallPosition(masm()->pc_offset(), deopt_info.inlining_id);
   } else {
     Deoptimizer::JumpTableEntry table_entry(entry, deopt_info, bailout_type,
                                             !frame_is_built_);
     // We often have several deopts to the same entry, reuse the last
     // jump entry if this is the case.
-    if (FLAG_trace_deopt || isolate()->cpu_profiler()->is_profiling() ||
+    if (FLAG_trace_deopt || isolate()->is_profiling() ||
         jump_table_.is_empty() ||
         !table_entry.IsEquivalentTo(jump_table_.last())) {
       jump_table_.Add(table_entry, zone());
@@ -842,7 +838,6 @@
 void LCodeGen::RecordAndWritePosition(int position) {
   if (position == RelocInfo::kNoPosition) return;
   masm()->positions_recorder()->RecordPosition(position);
-  masm()->positions_recorder()->WriteRecordedPositions();
 }
 
 
@@ -1782,7 +1777,7 @@
           : SmiValuesAre31Bits());
       __ cmpl(left_reg, right_imm);
       __ j(condition, &return_left, Label::kNear);
-      __ movp(left_reg, right_imm);
+      __ movl(left_reg, right_imm);
     } else if (right->IsRegister()) {
       Register right_reg = ToRegister(right);
       if (instr->hydrogen_value()->representation().IsSmi()) {
@@ -1890,13 +1885,12 @@
       __ Movapd(result, result);
       break;
     case Token::MOD: {
-      XMMRegister xmm_scratch = double_scratch0();
-      __ PrepareCallCFunction(2);
-      __ Movapd(xmm_scratch, left);
+      DCHECK(left.is(xmm0));
       DCHECK(right.is(xmm1));
+      DCHECK(result.is(xmm0));
+      __ PrepareCallCFunction(2);
       __ CallCFunction(
           ExternalReference::mod_two_doubles_operation(isolate()), 2);
-      __ Movapd(result, xmm_scratch);
       break;
     }
     default:
@@ -2441,16 +2435,6 @@
 }
 
 
-void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
-  DCHECK(ToRegister(instr->context()).is(rsi));
-  DCHECK(ToRegister(instr->left()).is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(ToRegister(instr->right()).is(InstanceOfDescriptor::RightRegister()));
-  DCHECK(ToRegister(instr->result()).is(rax));
-  InstanceOfStub stub(isolate());
-  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
-}
-
-
 void LCodeGen::DoHasInPrototypeChainAndBranch(
     LHasInPrototypeChainAndBranch* instr) {
   Register const object = ToRegister(instr->object());
@@ -2471,7 +2455,6 @@
   Label loop;
   __ bind(&loop);
 
-
   // Deoptimize if the object needs to be access checked.
   __ testb(FieldOperand(object_map, Map::kBitFieldOffset),
            Immediate(1 << Map::kIsAccessCheckNeeded));
@@ -2481,10 +2464,10 @@
   DeoptimizeIf(equal, instr, Deoptimizer::kProxy);
 
   __ movp(object_prototype, FieldOperand(object_map, Map::kPrototypeOffset));
-  __ cmpp(object_prototype, prototype);
-  EmitTrueBranch(instr, equal);
   __ CompareRoot(object_prototype, Heap::kNullValueRootIndex);
   EmitFalseBranch(instr, equal);
+  __ cmpp(object_prototype, prototype);
+  EmitTrueBranch(instr, equal);
   __ movp(object_map, FieldOperand(object_prototype, HeapObject::kMapOffset));
   __ jmp(&loop);
 }
@@ -2576,15 +2559,12 @@
 
 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   DCHECK(ToRegister(instr->context()).is(rsi));
-  DCHECK(ToRegister(instr->global_object())
-             .is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->result()).is(rax));
 
-  __ Move(LoadDescriptor::NameRegister(), instr->name());
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), instr->typeof_mode(), PREMONOMORPHIC)
-                        .code();
+  Handle<Code> ic =
+      CodeFactory::LoadGlobalICInOptimizedCode(isolate(), instr->typeof_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2699,10 +2679,7 @@
 
   __ Move(LoadDescriptor::NameRegister(), instr->name());
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_INSIDE_TYPEOF,
-                        instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2986,13 +2963,9 @@
   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
-  }
+  EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
 
-  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
-                        isolate(), instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3287,8 +3260,19 @@
   DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
 
   Label slow, allocated, done;
-  Register tmp = input_reg.is(rax) ? rcx : rax;
-  Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx;
+  uint32_t available_regs = rax.bit() | rcx.bit() | rdx.bit() | rbx.bit();
+  available_regs &= ~input_reg.bit();
+  if (instr->context()->IsRegister()) {
+    // Make sure that the context isn't overwritten in the AllocateHeapNumber
+    // macro below.
+    available_regs &= ~ToRegister(instr->context()).bit();
+  }
+
+  Register tmp =
+      Register::from_code(base::bits::CountTrailingZeros32(available_regs));
+  available_regs &= ~tmp.bit();
+  Register tmp2 =
+      Register::from_code(base::bits::CountTrailingZeros32(available_regs));
 
   // Preserve the value of all registers.
   PushSafepointRegistersScope scope(this);
@@ -3610,45 +3594,32 @@
   }
 }
 
-
-void LCodeGen::DoMathExp(LMathExp* instr) {
-  XMMRegister input = ToDoubleRegister(instr->value());
-  XMMRegister result = ToDoubleRegister(instr->result());
-  XMMRegister temp0 = double_scratch0();
-  Register temp1 = ToRegister(instr->temp1());
-  Register temp2 = ToRegister(instr->temp2());
-
-  MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2);
+void LCodeGen::DoMathCos(LMathCos* instr) {
+  DCHECK(ToDoubleRegister(instr->value()).is(xmm0));
+  DCHECK(ToDoubleRegister(instr->result()).is(xmm0));
+  __ PrepareCallCFunction(1);
+  __ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 1);
 }
 
+void LCodeGen::DoMathExp(LMathExp* instr) {
+  DCHECK(ToDoubleRegister(instr->value()).is(xmm0));
+  DCHECK(ToDoubleRegister(instr->result()).is(xmm0));
+  __ PrepareCallCFunction(1);
+  __ CallCFunction(ExternalReference::ieee754_exp_function(isolate()), 1);
+}
+
+void LCodeGen::DoMathSin(LMathSin* instr) {
+  DCHECK(ToDoubleRegister(instr->value()).is(xmm0));
+  DCHECK(ToDoubleRegister(instr->result()).is(xmm0));
+  __ PrepareCallCFunction(1);
+  __ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 1);
+}
 
 void LCodeGen::DoMathLog(LMathLog* instr) {
-  DCHECK(instr->value()->Equals(instr->result()));
-  XMMRegister input_reg = ToDoubleRegister(instr->value());
-  XMMRegister xmm_scratch = double_scratch0();
-  Label positive, done, zero;
-  __ Xorpd(xmm_scratch, xmm_scratch);
-  __ Ucomisd(input_reg, xmm_scratch);
-  __ j(above, &positive, Label::kNear);
-  __ j(not_carry, &zero, Label::kNear);
-  __ Pcmpeqd(input_reg, input_reg);
-  __ jmp(&done, Label::kNear);
-  __ bind(&zero);
-  ExternalReference ninf =
-      ExternalReference::address_of_negative_infinity();
-  Operand ninf_operand = masm()->ExternalOperand(ninf);
-  __ Movsd(input_reg, ninf_operand);
-  __ jmp(&done, Label::kNear);
-  __ bind(&positive);
-  __ fldln2();
-  __ subp(rsp, Immediate(kDoubleSize));
-  __ Movsd(Operand(rsp, 0), input_reg);
-  __ fld_d(Operand(rsp, 0));
-  __ fyl2x();
-  __ fstp_d(Operand(rsp, 0));
-  __ Movsd(input_reg, Operand(rsp, 0));
-  __ addp(rsp, Immediate(kDoubleSize));
-  __ bind(&done);
+  DCHECK(ToDoubleRegister(instr->value()).is(xmm0));
+  DCHECK(ToDoubleRegister(instr->result()).is(xmm0));
+  __ PrepareCallCFunction(1);
+  __ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 1);
 }
 
 
@@ -3671,7 +3642,9 @@
 #endif
   if (FLAG_code_comments) {
     if (actual.is_reg()) {
-      Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString());
+      Comment(";;; PrepareForTailCall, actual: %s {",
+              RegisterConfiguration::Crankshaft()->GetGeneralRegisterName(
+                  actual.reg().code()));
     } else {
       Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate());
     }
@@ -3740,14 +3713,7 @@
   DCHECK(ToRegister(instr->result()).is(rax));
 
   __ Set(rax, instr->arity());
-  if (instr->arity() == 1) {
-    // We only need the allocation site for the case we have a length argument.
-    // The case may bail out to the runtime, which will determine the correct
-    // elements kind with the site.
-    __ Move(rbx, instr->hydrogen()->site());
-  } else {
-    __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
-  }
+  __ Move(rbx, instr->hydrogen()->site());
 
   ElementsKind kind = instr->hydrogen()->elements_kind();
   AllocationSiteOverrideMode override_mode =
@@ -3781,7 +3747,7 @@
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
     __ bind(&done);
   } else {
-    ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
+    ArrayNArgumentsConstructorStub stub(isolate());
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   }
 }
@@ -3944,14 +3910,12 @@
   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
 
   __ Move(StoreDescriptor::NameRegister(), instr->hydrogen()->name());
-  Handle<Code> ic = CodeFactory::StoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic =
+      CodeFactory::StoreICInOptimizedCode(isolate(), instr->language_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -4203,13 +4167,11 @@
   DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
 
   Handle<Code> ic = CodeFactory::KeyedStoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state()).code();
+                        isolate(), instr->language_mode())
+                        .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -4340,8 +4302,7 @@
     DCHECK(ToRegister(instr->context()).is(rsi));
     PushSafepointRegistersScope scope(this);
     __ Move(rbx, to_map);
-    bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
-    TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
+    TransitionElementsKindStub stub(isolate(), from_kind, to_kind);
     __ CallStub(&stub);
     RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0);
   }
@@ -4791,20 +4752,21 @@
     __ Set(input_reg, 0);
   } else {
     XMMRegister scratch = ToDoubleRegister(instr->temp());
-    DCHECK(!scratch.is(xmm0));
+    DCHECK(!scratch.is(double_scratch0()));
     __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
                    Heap::kHeapNumberMapRootIndex);
     DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
-    __ Movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
-    __ Cvttsd2si(input_reg, xmm0);
+    __ Movsd(double_scratch0(),
+             FieldOperand(input_reg, HeapNumber::kValueOffset));
+    __ Cvttsd2si(input_reg, double_scratch0());
     __ Cvtlsi2sd(scratch, input_reg);
-    __ Ucomisd(xmm0, scratch);
+    __ Ucomisd(double_scratch0(), scratch);
     DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision);
     DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN);
     if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) {
       __ testl(input_reg, input_reg);
       __ j(not_zero, done);
-      __ Movmskpd(input_reg, xmm0);
+      __ Movmskpd(input_reg, double_scratch0());
       __ andl(input_reg, Immediate(1));
       DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero);
     }
@@ -5132,17 +5094,6 @@
 }
 
 
-void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
-  Register hi_reg = ToRegister(instr->hi());
-  Register lo_reg = ToRegister(instr->lo());
-  XMMRegister result_reg = ToDoubleRegister(instr->result());
-  __ movl(kScratchRegister, hi_reg);
-  __ shlq(kScratchRegister, Immediate(32));
-  __ orq(kScratchRegister, lo_reg);
-  __ Movq(result_reg, kScratchRegister);
-}
-
-
 void LCodeGen::DoAllocate(LAllocate* instr) {
   class DeferredAllocate final : public LDeferredCode {
    public:
@@ -5162,7 +5113,7 @@
   Register temp = ToRegister(instr->temp());
 
   // Allocate memory for the object.
-  AllocationFlags flags = TAG_OBJECT;
+  AllocationFlags flags = NO_ALLOCATION_FLAGS;
   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
   }
@@ -5171,6 +5122,11 @@
     flags = static_cast<AllocationFlags>(flags | PRETENURE);
   }
 
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    flags = static_cast<AllocationFlags>(flags | ALLOCATION_FOLDING_DOMINATOR);
+  }
+  DCHECK(!instr->hydrogen()->IsAllocationFolded());
+
   if (instr->size()->IsConstantOperand()) {
     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
     CHECK(size <= Page::kMaxRegularHeapObjectSize);
@@ -5200,6 +5156,29 @@
   }
 }
 
+void LCodeGen::DoFastAllocate(LFastAllocate* instr) {
+  DCHECK(instr->hydrogen()->IsAllocationFolded());
+  DCHECK(!instr->hydrogen()->IsAllocationFoldingDominator());
+  Register result = ToRegister(instr->result());
+  Register temp = ToRegister(instr->temp());
+
+  AllocationFlags flags = ALLOCATION_FOLDED;
+  if (instr->hydrogen()->MustAllocateDoubleAligned()) {
+    flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
+  }
+  if (instr->hydrogen()->IsOldSpaceAllocation()) {
+    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+    flags = static_cast<AllocationFlags>(flags | PRETENURE);
+  }
+  if (instr->size()->IsConstantOperand()) {
+    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
+    CHECK(size <= Page::kMaxRegularHeapObjectSize);
+    __ FastAllocate(size, result, temp, flags);
+  } else {
+    Register size = ToRegister(instr->size());
+    __ FastAllocate(size, result, temp, flags);
+  }
+}
 
 void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
   Register result = ToRegister(instr->result());
@@ -5232,6 +5211,22 @@
   CallRuntimeFromDeferred(
       Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
   __ StoreToSafepointRegisterSlot(result, rax);
+
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    AllocationFlags allocation_flags = NO_ALLOCATION_FLAGS;
+    if (instr->hydrogen()->IsOldSpaceAllocation()) {
+      DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+      allocation_flags = static_cast<AllocationFlags>(flags | PRETENURE);
+    }
+    // If the allocation folding dominator allocate triggered a GC, allocation
+    // happend in the runtime. We have to reset the top pointer to virtually
+    // undo the allocation.
+    ExternalReference allocation_top =
+        AllocationUtils::GetAllocationTopReference(isolate(), allocation_flags);
+    __ subp(rax, Immediate(kHeapObjectTag));
+    __ Store(allocation_top, rax);
+    __ addp(rax, Immediate(kHeapObjectTag));
+  }
 }
 
 
diff --git a/src/crankshaft/x64/lithium-codegen-x64.h b/src/crankshaft/x64/lithium-codegen-x64.h
index 139645e..c586ef5 100644
--- a/src/crankshaft/x64/lithium-codegen-x64.h
+++ b/src/crankshaft/x64/lithium-codegen-x64.h
@@ -111,13 +111,11 @@
 #undef DECLARE_DO
 
  private:
-  LanguageMode language_mode() const { return info()->language_mode(); }
-
   LPlatformChunk* chunk() const { return chunk_; }
   Scope* scope() const { return scope_; }
   HGraph* graph() const { return chunk()->graph(); }
 
-  XMMRegister double_scratch0() const { return xmm0; }
+  XMMRegister double_scratch0() const { return kScratchDoubleReg; }
 
   void EmitClassOfTest(Label* if_true,
                        Label* if_false,
diff --git a/src/crankshaft/x64/lithium-gap-resolver-x64.cc b/src/crankshaft/x64/lithium-gap-resolver-x64.cc
index 3808c37..94dffb3 100644
--- a/src/crankshaft/x64/lithium-gap-resolver-x64.cc
+++ b/src/crankshaft/x64/lithium-gap-resolver-x64.cc
@@ -223,8 +223,8 @@
       __ Movsd(cgen_->ToDoubleRegister(destination), src);
     } else {
       DCHECK(destination->IsDoubleStackSlot());
-      __ Movsd(xmm0, src);
-      __ Movsd(cgen_->ToOperand(destination), xmm0);
+      __ Movsd(kScratchDoubleReg, src);
+      __ Movsd(cgen_->ToOperand(destination), kScratchDoubleReg);
     }
   } else {
     UNREACHABLE();
@@ -264,18 +264,18 @@
     // Swap two stack slots or two double stack slots.
     Operand src = cgen_->ToOperand(source);
     Operand dst = cgen_->ToOperand(destination);
-    __ Movsd(xmm0, src);
+    __ Movsd(kScratchDoubleReg, src);
     __ movp(kScratchRegister, dst);
-    __ Movsd(dst, xmm0);
+    __ Movsd(dst, kScratchDoubleReg);
     __ movp(src, kScratchRegister);
 
   } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) {
     // Swap two double registers.
     XMMRegister source_reg = cgen_->ToDoubleRegister(source);
     XMMRegister destination_reg = cgen_->ToDoubleRegister(destination);
-    __ Movapd(xmm0, source_reg);
+    __ Movapd(kScratchDoubleReg, source_reg);
     __ Movapd(source_reg, destination_reg);
-    __ Movapd(destination_reg, xmm0);
+    __ Movapd(destination_reg, kScratchDoubleReg);
 
   } else if (source->IsDoubleRegister() || destination->IsDoubleRegister()) {
     // Swap a double register and a double stack slot.
@@ -287,9 +287,9 @@
     LOperand* other = source->IsDoubleRegister() ? destination : source;
     DCHECK(other->IsDoubleStackSlot());
     Operand other_operand = cgen_->ToOperand(other);
-    __ Movapd(xmm0, reg);
+    __ Movapd(kScratchDoubleReg, reg);
     __ Movsd(reg, other_operand);
-    __ Movsd(other_operand, xmm0);
+    __ Movsd(other_operand, kScratchDoubleReg);
 
   } else {
     // No other combinations are possible.
diff --git a/src/crankshaft/x64/lithium-x64.cc b/src/crankshaft/x64/lithium-x64.cc
index e86b90c..01b9918 100644
--- a/src/crankshaft/x64/lithium-x64.cc
+++ b/src/crankshaft/x64/lithium-x64.cc
@@ -714,10 +714,10 @@
   DCHECK(instr->left()->representation().IsDouble());
   DCHECK(instr->right()->representation().IsDouble());
   if (op == Token::MOD) {
-    LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
+    LOperand* left = UseFixedDouble(instr->BetterLeftOperand(), xmm0);
     LOperand* right = UseFixedDouble(instr->BetterRightOperand(), xmm1);
     LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
-    return MarkAsCall(DefineSameAsFirst(result), instr);
+    return MarkAsCall(DefineFixedDouble(result, xmm0), instr);
   } else {
     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
     LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
@@ -907,7 +907,7 @@
 
 LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) {
   LInstruction* result = new (zone()) LPrologue();
-  if (info_->num_heap_slots() > 0) {
+  if (info_->scope()->num_heap_slots() > 0) {
     result = MarkAsCall(result, instr);
   }
   return result;
@@ -957,17 +957,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
-  LOperand* left =
-      UseFixed(instr->left(), InstanceOfDescriptor::LeftRegister());
-  LOperand* right =
-      UseFixed(instr->right(), InstanceOfDescriptor::RightRegister());
-  LOperand* context = UseFixed(instr->context(), rsi);
-  LInstanceOf* result = new (zone()) LInstanceOf(context, left, right);
-  return MarkAsCall(DefineFixed(result, rax), instr);
-}
-
-
 LInstruction* LChunkBuilder::DoHasInPrototypeChainAndBranch(
     HHasInPrototypeChainAndBranch* instr) {
   LOperand* object = UseRegister(instr->object());
@@ -1101,10 +1090,14 @@
       return DoMathFround(instr);
     case kMathAbs:
       return DoMathAbs(instr);
+    case kMathCos:
+      return DoMathCos(instr);
     case kMathLog:
       return DoMathLog(instr);
     case kMathExp:
       return DoMathExp(instr);
+    case kMathSin:
+      return DoMathSin(instr);
     case kMathSqrt:
       return DoMathSqrt(instr);
     case kMathPowHalf:
@@ -1166,8 +1159,9 @@
 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
   DCHECK(instr->representation().IsDouble());
   DCHECK(instr->value()->representation().IsDouble());
-  LOperand* input = UseRegisterAtStart(instr->value());
-  return MarkAsCall(DefineSameAsFirst(new(zone()) LMathLog(input)), instr);
+  LOperand* input = UseFixedDouble(instr->value(), xmm0);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), xmm0),
+                    instr);
 }
 
 
@@ -1177,17 +1171,29 @@
   return DefineAsRegister(result);
 }
 
+LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
+  DCHECK(instr->representation().IsDouble());
+  DCHECK(instr->value()->representation().IsDouble());
+  LOperand* input = UseFixedDouble(instr->value(), xmm0);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathCos(input), xmm0),
+                    instr);
+}
 
 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
   DCHECK(instr->representation().IsDouble());
   DCHECK(instr->value()->representation().IsDouble());
-  LOperand* value = UseTempRegister(instr->value());
-  LOperand* temp1 = TempRegister();
-  LOperand* temp2 = TempRegister();
-  LMathExp* result = new(zone()) LMathExp(value, temp1, temp2);
-  return DefineAsRegister(result);
+  LOperand* input = UseFixedDouble(instr->value(), xmm0);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathExp(input), xmm0),
+                    instr);
 }
 
+LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
+  DCHECK(instr->representation().IsDouble());
+  DCHECK(instr->value()->representation().IsDouble());
+  LOperand* input = UseFixedDouble(instr->value(), xmm0);
+  return MarkAsCall(DefineFixedDouble(new (zone()) LMathSin(input), xmm0),
+                    instr);
+}
 
 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
   LOperand* input = UseAtStart(instr->value());
@@ -1968,13 +1974,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
-  LOperand* lo = UseRegister(instr->lo());
-  LOperand* hi = UseRegister(instr->hi());
-  return DefineAsRegister(new(zone()) LConstructDouble(hi, lo));
-}
-
-
 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
   LOperand* context = info()->IsStub() ? UseFixed(instr->context(), rsi) : NULL;
   LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
@@ -2004,15 +2003,9 @@
 
 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), rsi);
-  LOperand* global_object =
-      UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
-  LLoadGlobalGeneric* result =
-      new(zone()) LLoadGlobalGeneric(context, global_object, vector);
+  LLoadGlobalGeneric* result = new (zone()) LLoadGlobalGeneric(context, vector);
   return MarkAsCall(DefineFixed(result, rax), instr);
 }
 
@@ -2069,10 +2062,7 @@
   LOperand* context = UseFixed(instr->context(), rsi);
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
   LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(
       context, object, vector);
   return MarkAsCall(DefineFixed(result, rax), instr);
@@ -2170,10 +2160,7 @@
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
   LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
   LLoadKeyedGeneric* result =
       new(zone()) LLoadKeyedGeneric(context, object, key, vector);
@@ -2254,12 +2241,8 @@
   DCHECK(instr->key()->representation().IsTagged());
   DCHECK(instr->value()->representation().IsTagged());
 
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
 
   LStoreKeyedGeneric* result = new (zone())
       LStoreKeyedGeneric(context, object, key, value, slot, vector);
@@ -2366,12 +2349,8 @@
   LOperand* object =
       UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
   LOperand* value = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
 
   LStoreNamedGeneric* result =
       new (zone()) LStoreNamedGeneric(context, object, value, slot, vector);
@@ -2408,14 +2387,19 @@
 
 
 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
-  info()->MarkAsDeferredCalling();
-  LOperand* context = UseAny(instr->context());
-  LOperand* size = instr->size()->IsConstant()
-      ? UseConstant(instr->size())
-      : UseTempRegister(instr->size());
-  LOperand* temp = TempRegister();
-  LAllocate* result = new(zone()) LAllocate(context, size, temp);
-  return AssignPointerMap(DefineAsRegister(result));
+  LOperand* size = instr->size()->IsConstant() ? UseConstant(instr->size())
+                                               : UseRegister(instr->size());
+  if (instr->IsAllocationFolded()) {
+    LOperand* temp = TempRegister();
+    LFastAllocate* result = new (zone()) LFastAllocate(size, temp);
+    return DefineAsRegister(result);
+  } else {
+    info()->MarkAsDeferredCalling();
+    LOperand* context = UseAny(instr->context());
+    LOperand* temp = TempRegister();
+    LAllocate* result = new (zone()) LAllocate(context, size, temp);
+    return AssignPointerMap(DefineAsRegister(result));
+  }
 }
 
 
diff --git a/src/crankshaft/x64/lithium-x64.h b/src/crankshaft/x64/lithium-x64.h
index 1feba4b..623421c 100644
--- a/src/crankshaft/x64/lithium-x64.h
+++ b/src/crankshaft/x64/lithium-x64.h
@@ -53,7 +53,6 @@
   V(ConstantI)                               \
   V(ConstantS)                               \
   V(ConstantT)                               \
-  V(ConstructDouble)                         \
   V(Context)                                 \
   V(DebugBreak)                              \
   V(DeclareGlobals)                          \
@@ -67,6 +66,7 @@
   V(Drop)                                    \
   V(DummyUse)                                \
   V(Dummy)                                   \
+  V(FastAllocate)                            \
   V(FlooringDivByConstI)                     \
   V(FlooringDivByPowerOf2I)                  \
   V(FlooringDivI)                            \
@@ -78,7 +78,6 @@
   V(HasInPrototypeChainAndBranch)            \
   V(HasInstanceTypeAndBranch)                \
   V(InnerAllocatedObject)                    \
-  V(InstanceOf)                              \
   V(InstructionGap)                          \
   V(Integer32ToDouble)                       \
   V(InvokeFunction)                          \
@@ -98,6 +97,7 @@
   V(LoadNamedGeneric)                        \
   V(MathAbs)                                 \
   V(MathClz32)                               \
+  V(MathCos)                                 \
   V(MathExp)                                 \
   V(MathFloorD)                              \
   V(MathFloorI)                              \
@@ -107,6 +107,7 @@
   V(MathPowHalf)                             \
   V(MathRoundD)                              \
   V(MathRoundI)                              \
+  V(MathSin)                                 \
   V(MathSqrt)                                \
   V(MaybeGrowElements)                       \
   V(ModByConstI)                             \
@@ -909,23 +910,32 @@
   DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
 };
 
-
-class LMathExp final : public LTemplateInstruction<1, 1, 2> {
+class LMathCos final : public LTemplateInstruction<1, 1, 0> {
  public:
-  LMathExp(LOperand* value, LOperand* temp1, LOperand* temp2) {
-    inputs_[0] = value;
-    temps_[0] = temp1;
-    temps_[1] = temp2;
-    ExternalReference::InitializeMathExpData();
-  }
+  explicit LMathCos(LOperand* value) { inputs_[0] = value; }
 
   LOperand* value() { return inputs_[0]; }
-  LOperand* temp1() { return temps_[0]; }
-  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
+};
+
+class LMathExp final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathExp(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
 };
 
+class LMathSin final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathSin(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
+};
 
 class LMathSqrt final : public LTemplateInstruction<1, 1, 0> {
  public:
@@ -1136,22 +1146,6 @@
 };
 
 
-class LInstanceOf final : public LTemplateInstruction<1, 3, 0> {
- public:
-  LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
-    inputs_[0] = context;
-    inputs_[1] = left;
-    inputs_[2] = right;
-  }
-
-  LOperand* context() { return inputs_[0]; }
-  LOperand* left() { return inputs_[1]; }
-  LOperand* right() { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
-};
-
-
 class LHasInPrototypeChainAndBranch final : public LControlInstruction<2, 0> {
  public:
   LHasInPrototypeChainAndBranch(LOperand* object, LOperand* prototype) {
@@ -1597,13 +1591,10 @@
   LOperand* temp_vector() { return temps_[0]; }
 };
 
-
-class LLoadGlobalGeneric final : public LTemplateInstruction<1, 2, 1> {
+class LLoadGlobalGeneric final : public LTemplateInstruction<1, 1, 1> {
  public:
-  explicit LLoadGlobalGeneric(LOperand* context, LOperand* global_object,
-                              LOperand* vector) {
+  explicit LLoadGlobalGeneric(LOperand* context, LOperand* vector) {
     inputs_[0] = context;
-    inputs_[1] = global_object;
     temps_[0] = vector;
   }
 
@@ -1611,7 +1602,6 @@
   DECLARE_HYDROGEN_ACCESSOR(LoadGlobalGeneric)
 
   LOperand* context() { return inputs_[0]; }
-  LOperand* global_object() { return inputs_[1]; }
   LOperand* temp_vector() { return temps_[0]; }
 
   Handle<Object> name() const { return hydrogen()->name(); }
@@ -2355,20 +2345,6 @@
 };
 
 
-class LConstructDouble final : public LTemplateInstruction<1, 2, 0> {
- public:
-  LConstructDouble(LOperand* hi, LOperand* lo) {
-    inputs_[0] = hi;
-    inputs_[1] = lo;
-  }
-
-  LOperand* hi() { return inputs_[0]; }
-  LOperand* lo() { return inputs_[1]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
-};
-
-
 class LAllocate final : public LTemplateInstruction<1, 2, 1> {
  public:
   LAllocate(LOperand* context, LOperand* size, LOperand* temp) {
@@ -2385,6 +2361,19 @@
   DECLARE_HYDROGEN_ACCESSOR(Allocate)
 };
 
+class LFastAllocate final : public LTemplateInstruction<1, 1, 1> {
+ public:
+  LFastAllocate(LOperand* size, LOperand* temp) {
+    inputs_[0] = size;
+    temps_[0] = temp;
+  }
+
+  LOperand* size() const { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(FastAllocate, "fast-allocate")
+  DECLARE_HYDROGEN_ACCESSOR(Allocate)
+};
 
 class LTypeof final : public LTemplateInstruction<1, 2, 0> {
  public:
@@ -2542,8 +2531,10 @@
   LInstruction* DoMathRound(HUnaryMathOperation* instr);
   LInstruction* DoMathFround(HUnaryMathOperation* instr);
   LInstruction* DoMathAbs(HUnaryMathOperation* instr);
+  LInstruction* DoMathCos(HUnaryMathOperation* instr);
   LInstruction* DoMathLog(HUnaryMathOperation* instr);
   LInstruction* DoMathExp(HUnaryMathOperation* instr);
+  LInstruction* DoMathSin(HUnaryMathOperation* instr);
   LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
   LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
   LInstruction* DoMathClz32(HUnaryMathOperation* instr);
diff --git a/src/crankshaft/x87/lithium-codegen-x87.cc b/src/crankshaft/x87/lithium-codegen-x87.cc
index 1751199..7bf974c 100644
--- a/src/crankshaft/x87/lithium-codegen-x87.cc
+++ b/src/crankshaft/x87/lithium-codegen-x87.cc
@@ -14,7 +14,6 @@
 #include "src/deoptimizer.h"
 #include "src/ic/ic.h"
 #include "src/ic/stub-cache.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/x87/frames-x87.h"
 
 namespace v8 {
@@ -135,11 +134,11 @@
   Comment(";;; Prologue begin");
 
   // Possibly allocate a local context.
-  if (info_->num_heap_slots() > 0) {
+  if (info_->scope()->num_heap_slots() > 0) {
     Comment(";;; Allocate local context");
     bool need_write_barrier = true;
     // Argument to NewContext is the function, which is still in edi.
-    int slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+    int slots = info_->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
     Safepoint::DeoptMode deopt_mode = Safepoint::kNoLazyDeopt;
     if (info()->scope()->is_script_scope()) {
       __ push(edi);
@@ -201,6 +200,13 @@
 
   osr_pc_offset_ = masm()->pc_offset();
 
+  // Interpreter is the first tier compiler now. It will run the code generated
+  // by TurboFan compiler which will always put "1" on x87 FPU stack.
+  // This behavior will affect crankshaft's x87 FPU stack depth check under
+  // debug mode.
+  // Need to reset the FPU stack here for this scenario.
+  __ fninit();
+
   // Adjust the frame size, subsuming the unoptimized frame into the
   // optimized frame.
   int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots();
@@ -268,8 +274,6 @@
     } else {
       __ call(entry, RelocInfo::RUNTIME_ENTRY);
     }
-    info()->LogDeoptCallPosition(masm()->pc_offset(),
-                                 table_entry->deopt_info.inlining_id);
   }
   if (needs_frame.is_linked()) {
     __ bind(&needs_frame);
@@ -1009,19 +1013,18 @@
     __ bind(&done);
   }
 
-  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason);
+  Deoptimizer::DeoptInfo deopt_info = MakeDeoptInfo(instr, deopt_reason, id);
 
   DCHECK(info()->IsStub() || frame_is_built_);
   if (cc == no_condition && frame_is_built_) {
     DeoptComment(deopt_info);
     __ call(entry, RelocInfo::RUNTIME_ENTRY);
-    info()->LogDeoptCallPosition(masm()->pc_offset(), deopt_info.inlining_id);
   } else {
     Deoptimizer::JumpTableEntry table_entry(entry, deopt_info, bailout_type,
                                             !frame_is_built_);
     // We often have several deopts to the same entry, reuse the last
     // jump entry if this is the case.
-    if (FLAG_trace_deopt || isolate()->cpu_profiler()->is_profiling() ||
+    if (FLAG_trace_deopt || isolate()->is_profiling() ||
         jump_table_.is_empty() ||
         !table_entry.IsEquivalentTo(jump_table_.last())) {
       jump_table_.Add(table_entry, zone());
@@ -1098,7 +1101,6 @@
 void LCodeGen::RecordAndWritePosition(int position) {
   if (position == RelocInfo::kNoPosition) return;
   masm()->positions_recorder()->RecordPosition(position);
-  masm()->positions_recorder()->WriteRecordedPositions();
 }
 
 
@@ -2358,9 +2360,7 @@
 
   __ add(esp, Immediate(kDoubleSize));
   int offset = sizeof(kHoleNanUpper32);
-  // x87 converts sNaN(0xfff7fffffff7ffff) to QNaN(0xfffffffffff7ffff),
-  // so we check the upper with 0xffffffff for hole as a temporary fix.
-  __ cmp(MemOperand(esp, -offset), Immediate(0xffffffff));
+  __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32));
   EmitBranch(instr, equal);
 }
 
@@ -2572,16 +2572,6 @@
 }
 
 
-void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
-  DCHECK(ToRegister(instr->context()).is(esi));
-  DCHECK(ToRegister(instr->left()).is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(ToRegister(instr->right()).is(InstanceOfDescriptor::RightRegister()));
-  DCHECK(ToRegister(instr->result()).is(eax));
-  InstanceOfStub stub(isolate());
-  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
-}
-
-
 void LCodeGen::DoHasInPrototypeChainAndBranch(
     LHasInPrototypeChainAndBranch* instr) {
   Register const object = ToRegister(instr->object());
@@ -2611,10 +2601,10 @@
   DeoptimizeIf(equal, instr, Deoptimizer::kProxy);
 
   __ mov(object_prototype, FieldOperand(object_map, Map::kPrototypeOffset));
-  __ cmp(object_prototype, prototype);
-  EmitTrueBranch(instr, equal);
   __ cmp(object_prototype, factory()->null_value());
   EmitFalseBranch(instr, equal);
+  __ cmp(object_prototype, prototype);
+  EmitTrueBranch(instr, equal);
   __ mov(object_map, FieldOperand(object_prototype, HeapObject::kMapOffset));
   __ jmp(&loop);
 }
@@ -2711,15 +2701,12 @@
 
 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
   DCHECK(ToRegister(instr->context()).is(esi));
-  DCHECK(ToRegister(instr->global_object())
-             .is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->result()).is(eax));
 
-  __ mov(LoadDescriptor::NameRegister(), instr->name());
   EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), instr->typeof_mode(), PREMONOMORPHIC)
-                        .code();
+  Handle<Code> ic =
+      CodeFactory::LoadGlobalICInOptimizedCode(isolate(), instr->typeof_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2828,10 +2815,7 @@
 
   __ mov(LoadDescriptor::NameRegister(), instr->name());
   EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
-  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
-                        isolate(), NOT_INSIDE_TYPEOF,
-                        instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2999,9 +2983,9 @@
     __ j(not_equal, &done);
     if (info()->IsStub()) {
       // A stub can safely convert the hole to undefined only if the array
-      // protector cell contains (Smi) Isolate::kArrayProtectorValid. Otherwise
-      // it needs to bail out.
-      __ mov(result, isolate()->factory()->array_protector());
+      // protector cell contains (Smi) Isolate::kArrayProtectorValid.
+      // Otherwise it needs to bail out.
+      __ LoadRoot(result, Heap::kArrayProtectorRootIndex);
       __ cmp(FieldOperand(result, PropertyCell::kValueOffset),
              Immediate(Smi::FromInt(Isolate::kArrayProtectorValid)));
       DeoptimizeIf(not_equal, instr, Deoptimizer::kHole);
@@ -3059,13 +3043,9 @@
   DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
-  }
+  EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
 
-  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(
-                        isolate(), instr->hydrogen()->initialization_state())
-                        .code();
+  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -3362,8 +3342,19 @@
   DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber);
 
   Label slow, allocated, done;
-  Register tmp = input_reg.is(eax) ? ecx : eax;
-  Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx;
+  uint32_t available_regs = eax.bit() | ecx.bit() | edx.bit() | ebx.bit();
+  available_regs &= ~input_reg.bit();
+  if (instr->context()->IsRegister()) {
+    // Make sure that the context isn't overwritten in the AllocateHeapNumber
+    // macro below.
+    available_regs &= ~ToRegister(instr->context()).bit();
+  }
+
+  Register tmp =
+      Register::from_code(base::bits::CountTrailingZeros32(available_regs));
+  available_regs &= ~tmp.bit();
+  Register tmp2 =
+      Register::from_code(base::bits::CountTrailingZeros32(available_regs));
 
   // Preserve the value of all registers.
   PushSafepointRegistersScope scope(this);
@@ -3685,40 +3676,17 @@
 
 void LCodeGen::DoMathLog(LMathLog* instr) {
   DCHECK(instr->value()->Equals(instr->result()));
+  X87Register result = ToX87Register(instr->result());
   X87Register input_reg = ToX87Register(instr->value());
   X87Fxch(input_reg);
 
-  Label positive, done, zero, nan_result;
-  __ fldz();
-  __ fld(1);
-  __ FCmp();
-  __ j(below, &nan_result, Label::kNear);
-  __ j(equal, &zero, Label::kNear);
-  // Positive input.
-  // {input, ln2}.
-  __ fldln2();
-  // {ln2, input}.
-  __ fxch();
-  // {result}.
-  __ fyl2x();
-  __ jmp(&done, Label::kNear);
-
-  __ bind(&nan_result);
-  X87PrepareToWrite(input_reg);
-  __ push(Immediate(0xffffffff));
-  __ push(Immediate(0x7fffffff));
-  __ fld_d(MemOperand(esp, 0));
-  __ lea(esp, Operand(esp, kDoubleSize));
-  X87CommitWrite(input_reg);
-  __ jmp(&done, Label::kNear);
-
-  __ bind(&zero);
-  ExternalReference ninf = ExternalReference::address_of_negative_infinity();
-  X87PrepareToWrite(input_reg);
-  __ fld_d(Operand::StaticVariable(ninf));
-  X87CommitWrite(input_reg);
-
-  __ bind(&done);
+  // Pass one double as argument on the stack.
+  __ PrepareCallCFunction(2, eax);
+  __ fstp_d(MemOperand(esp, 0));
+  X87PrepareToWrite(result);
+  __ CallCFunction(ExternalReference::ieee754_log_function(isolate()), 2);
+  // Return value is in st(0) on ia32.
+  X87CommitWrite(result);
 }
 
 
@@ -3729,67 +3697,46 @@
   __ Lzcnt(result, input);
 }
 
+void LCodeGen::DoMathCos(LMathCos* instr) {
+  X87Register result = ToX87Register(instr->result());
+  X87Register input_reg = ToX87Register(instr->value());
+  __ fld(x87_stack_.st(input_reg));
+
+  // Pass one double as argument on the stack.
+  __ PrepareCallCFunction(2, eax);
+  __ fstp_d(MemOperand(esp, 0));
+  X87PrepareToWrite(result);
+  __ CallCFunction(ExternalReference::ieee754_cos_function(isolate()), 2);
+  // Return value is in st(0) on ia32.
+  X87CommitWrite(result);
+}
+
+void LCodeGen::DoMathSin(LMathSin* instr) {
+  X87Register result = ToX87Register(instr->result());
+  X87Register input_reg = ToX87Register(instr->value());
+  __ fld(x87_stack_.st(input_reg));
+
+  // Pass one double as argument on the stack.
+  __ PrepareCallCFunction(2, eax);
+  __ fstp_d(MemOperand(esp, 0));
+  X87PrepareToWrite(result);
+  __ CallCFunction(ExternalReference::ieee754_sin_function(isolate()), 2);
+  // Return value is in st(0) on ia32.
+  X87CommitWrite(result);
+}
 
 void LCodeGen::DoMathExp(LMathExp* instr) {
-  X87Register input = ToX87Register(instr->value());
-  X87Register result_reg = ToX87Register(instr->result());
-  Register temp_result = ToRegister(instr->temp1());
-  Register temp = ToRegister(instr->temp2());
-  Label slow, done, smi, finish;
-  DCHECK(result_reg.is(input));
+  X87Register result = ToX87Register(instr->result());
+  X87Register input_reg = ToX87Register(instr->value());
+  __ fld(x87_stack_.st(input_reg));
 
-  // Store input into Heap number and call runtime function kMathExpRT.
-  if (FLAG_inline_new) {
-    __ AllocateHeapNumber(temp_result, temp, no_reg, &slow);
-    __ jmp(&done, Label::kNear);
-  }
-
-  // Slow case: Call the runtime system to do the number allocation.
-  __ bind(&slow);
-  {
-    // TODO(3095996): Put a valid pointer value in the stack slot where the
-    // result register is stored, as this register is in the pointer map, but
-    // contains an integer value.
-    __ Move(temp_result, Immediate(0));
-
-    // Preserve the value of all registers.
-    PushSafepointRegistersScope scope(this);
-
-    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-    __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
-    RecordSafepointWithRegisters(instr->pointer_map(), 0,
-                                 Safepoint::kNoLazyDeopt);
-    __ StoreToSafepointRegisterSlot(temp_result, eax);
-  }
-  __ bind(&done);
-  X87LoadForUsage(input);
-  __ fstp_d(FieldOperand(temp_result, HeapNumber::kValueOffset));
-
-  {
-    // Preserve the value of all registers.
-    PushSafepointRegistersScope scope(this);
-
-    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-    __ push(temp_result);
-    __ CallRuntimeSaveDoubles(Runtime::kMathExpRT);
-    RecordSafepointWithRegisters(instr->pointer_map(), 1,
-                                 Safepoint::kNoLazyDeopt);
-    __ StoreToSafepointRegisterSlot(temp_result, eax);
-  }
-  X87PrepareToWrite(result_reg);
-  // return value of MathExpRT is Smi or Heap Number.
-  __ JumpIfSmi(temp_result, &smi);
-  // Heap number(double)
-  __ fld_d(FieldOperand(temp_result, HeapNumber::kValueOffset));
-  __ jmp(&finish);
-  // SMI
-  __ bind(&smi);
-  __ SmiUntag(temp_result);
-  __ push(temp_result);
-  __ fild_s(MemOperand(esp, 0));
-  __ pop(temp_result);
-  __ bind(&finish);
-  X87CommitWrite(result_reg);
+  // Pass one double as argument on the stack.
+  __ PrepareCallCFunction(2, eax);
+  __ fstp_d(MemOperand(esp, 0));
+  X87PrepareToWrite(result);
+  __ CallCFunction(ExternalReference::ieee754_exp_function(isolate()), 2);
+  // Return value is in st(0) on ia32.
+  X87CommitWrite(result);
 }
 
 void LCodeGen::PrepareForTailCall(const ParameterCount& actual,
@@ -3804,7 +3751,9 @@
 #endif
   if (FLAG_code_comments) {
     if (actual.is_reg()) {
-      Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString());
+      Comment(";;; PrepareForTailCall, actual: %s {",
+              RegisterConfiguration::Crankshaft()->GetGeneralRegisterName(
+                  actual.reg().code()));
     } else {
       Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate());
     }
@@ -3874,14 +3823,7 @@
   DCHECK(ToRegister(instr->result()).is(eax));
 
   __ Move(eax, Immediate(instr->arity()));
-  if (instr->arity() == 1) {
-    // We only need the allocation site for the case we have a length argument.
-    // The case may bail out to the runtime, which will determine the correct
-    // elements kind with the site.
-    __ mov(ebx, instr->hydrogen()->site());
-  } else {
-    __ mov(ebx, isolate()->factory()->undefined_value());
-  }
+  __ mov(ebx, instr->hydrogen()->site());
 
   ElementsKind kind = instr->hydrogen()->elements_kind();
   AllocationSiteOverrideMode override_mode =
@@ -3915,7 +3857,7 @@
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
     __ bind(&done);
   } else {
-    ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
+    ArrayNArgumentsConstructorStub stub(isolate());
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   }
 }
@@ -4042,14 +3984,12 @@
   DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreNamedGeneric>(instr);
 
   __ mov(StoreDescriptor::NameRegister(), instr->name());
-  Handle<Code> ic = CodeFactory::StoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state()).code();
+  Handle<Code> ic =
+      CodeFactory::StoreICInOptimizedCode(isolate(), instr->language_mode())
+          .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -4111,9 +4051,7 @@
     __ fst_d(MemOperand(esp, 0));
     __ lea(esp, Operand(esp, kDoubleSize));
     int offset = sizeof(kHoleNanUpper32);
-    // x87 converts sNaN(0xfff7fffffff7ffff) to QNaN(0xfffffffffff7ffff),
-    // so we check the upper with 0xffffffff for hole as a temporary fix.
-    __ cmp(MemOperand(esp, -offset), Immediate(0xffffffff));
+    __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32));
     __ j(not_equal, &no_special_nan_handling, Label::kNear);
     __ mov(operand, Immediate(lower));
     __ mov(operand2, Immediate(upper));
@@ -4199,9 +4137,7 @@
       __ fst_d(MemOperand(esp, 0));
       __ lea(esp, Operand(esp, kDoubleSize));
       int offset = sizeof(kHoleNanUpper32);
-      // x87 converts sNaN(0xfff7fffffff7ffff) to QNaN(0xfffffffffff7ffff),
-      // so we check the upper with 0xffffffff for hole as a temporary fix.
-      __ cmp(MemOperand(esp, -offset), Immediate(0xffffffff));
+      __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32));
       __ j(not_equal, &no_special_nan_handling, Label::kNear);
       __ mov(double_store_operand, Immediate(lower));
       __ mov(double_store_operand2, Immediate(upper));
@@ -4272,13 +4208,11 @@
   DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister()));
   DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
 
-  if (instr->hydrogen()->HasVectorAndSlot()) {
-    EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
-  }
+  EmitVectorStoreICRegisters<LStoreKeyedGeneric>(instr);
 
   Handle<Code> ic = CodeFactory::KeyedStoreICInOptimizedCode(
-                        isolate(), instr->language_mode(),
-                        instr->hydrogen()->initialization_state()).code();
+                        isolate(), instr->language_mode())
+                        .code();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -4364,7 +4298,15 @@
 
     LOperand* key = instr->key();
     if (key->IsConstantOperand()) {
-      __ mov(ebx, ToImmediate(key, Representation::Smi()));
+      LConstantOperand* constant_key = LConstantOperand::cast(key);
+      int32_t int_key = ToInteger32(constant_key);
+      if (Smi::IsValid(int_key)) {
+        __ mov(ebx, Immediate(Smi::FromInt(int_key)));
+      } else {
+        // We should never get here at runtime because there is a smi check on
+        // the key before this point.
+        __ int3();
+      }
     } else {
       __ Move(ebx, ToRegister(key));
       __ SmiTag(ebx);
@@ -4412,8 +4354,7 @@
     DCHECK(object_reg.is(eax));
     PushSafepointRegistersScope scope(this);
     __ mov(ebx, to_map);
-    bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
-    TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
+    TransitionElementsKindStub stub(isolate(), from_kind, to_kind);
     __ CallStub(&stub);
     RecordSafepointWithLazyDeopt(instr,
         RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
@@ -5360,21 +5301,6 @@
 }
 
 
-void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
-  Register hi_reg = ToRegister(instr->hi());
-  Register lo_reg = ToRegister(instr->lo());
-  X87Register result_reg = ToX87Register(instr->result());
-  // Follow below pattern to write a x87 fp register.
-  X87PrepareToWrite(result_reg);
-  __ sub(esp, Immediate(kDoubleSize));
-  __ mov(Operand(esp, 0), lo_reg);
-  __ mov(Operand(esp, kPointerSize), hi_reg);
-  __ fld_d(Operand(esp, 0));
-  __ add(esp, Immediate(kDoubleSize));
-  X87CommitWrite(result_reg);
-}
-
-
 void LCodeGen::DoAllocate(LAllocate* instr) {
   class DeferredAllocate final : public LDeferredCode {
    public:
@@ -5396,7 +5322,7 @@
   Register temp = ToRegister(instr->temp());
 
   // Allocate memory for the object.
-  AllocationFlags flags = TAG_OBJECT;
+  AllocationFlags flags = NO_ALLOCATION_FLAGS;
   if (instr->hydrogen()->MustAllocateDoubleAligned()) {
     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
   }
@@ -5405,6 +5331,11 @@
     flags = static_cast<AllocationFlags>(flags | PRETENURE);
   }
 
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    flags = static_cast<AllocationFlags>(flags | ALLOCATION_FOLDING_DOMINATOR);
+  }
+  DCHECK(!instr->hydrogen()->IsAllocationFolded());
+
   if (instr->size()->IsConstantOperand()) {
     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
     CHECK(size <= Page::kMaxRegularHeapObjectSize);
@@ -5434,6 +5365,29 @@
   }
 }
 
+void LCodeGen::DoFastAllocate(LFastAllocate* instr) {
+  DCHECK(instr->hydrogen()->IsAllocationFolded());
+  DCHECK(!instr->hydrogen()->IsAllocationFoldingDominator());
+  Register result = ToRegister(instr->result());
+  Register temp = ToRegister(instr->temp());
+
+  AllocationFlags flags = ALLOCATION_FOLDED;
+  if (instr->hydrogen()->MustAllocateDoubleAligned()) {
+    flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
+  }
+  if (instr->hydrogen()->IsOldSpaceAllocation()) {
+    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+    flags = static_cast<AllocationFlags>(flags | PRETENURE);
+  }
+  if (instr->size()->IsConstantOperand()) {
+    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
+    CHECK(size <= Page::kMaxRegularHeapObjectSize);
+    __ FastAllocate(size, result, temp, flags);
+  } else {
+    Register size = ToRegister(instr->size());
+    __ FastAllocate(size, result, temp, flags);
+  }
+}
 
 void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
   Register result = ToRegister(instr->result());
@@ -5473,6 +5427,22 @@
   CallRuntimeFromDeferred(
       Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
   __ StoreToSafepointRegisterSlot(result, eax);
+
+  if (instr->hydrogen()->IsAllocationFoldingDominator()) {
+    AllocationFlags allocation_flags = NO_ALLOCATION_FLAGS;
+    if (instr->hydrogen()->IsOldSpaceAllocation()) {
+      DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
+      allocation_flags = static_cast<AllocationFlags>(flags | PRETENURE);
+    }
+    // If the allocation folding dominator allocate triggered a GC, allocation
+    // happend in the runtime. We have to reset the top pointer to virtually
+    // undo the allocation.
+    ExternalReference allocation_top =
+        AllocationUtils::GetAllocationTopReference(isolate(), allocation_flags);
+    __ sub(eax, Immediate(kHeapObjectTag));
+    __ mov(Operand::StaticVariable(allocation_top), eax);
+    __ add(eax, Immediate(kHeapObjectTag));
+  }
 }
 
 
diff --git a/src/crankshaft/x87/lithium-codegen-x87.h b/src/crankshaft/x87/lithium-codegen-x87.h
index 3719236..f979cf0 100644
--- a/src/crankshaft/x87/lithium-codegen-x87.h
+++ b/src/crankshaft/x87/lithium-codegen-x87.h
@@ -150,8 +150,6 @@
 #undef DECLARE_DO
 
  private:
-  LanguageMode language_mode() const { return info()->language_mode(); }
-
   Scope* scope() const { return scope_; }
 
   void EmitClassOfTest(Label* if_true,
diff --git a/src/crankshaft/x87/lithium-gap-resolver-x87.cc b/src/crankshaft/x87/lithium-gap-resolver-x87.cc
index aa91835..6bfc2e2 100644
--- a/src/crankshaft/x87/lithium-gap-resolver-x87.cc
+++ b/src/crankshaft/x87/lithium-gap-resolver-x87.cc
@@ -168,8 +168,7 @@
 
 Register LGapResolver::GetFreeRegisterNot(Register reg) {
   int skip_index = reg.is(no_reg) ? -1 : reg.code();
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
     int code = config->GetAllocatableGeneralCode(i);
     if (source_uses_[code] == 0 && destination_uses_[code] > 0 &&
@@ -184,8 +183,7 @@
 bool LGapResolver::HasBeenReset() {
   if (!moves_.is_empty()) return false;
   if (spilled_register_ >= 0) return false;
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
     int code = config->GetAllocatableGeneralCode(i);
     if (source_uses_[code] != 0) return false;
@@ -239,8 +237,7 @@
 
   // 3. Prefer to spill a register that is not used in any remaining move
   // because it will not need to be restored until the end.
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
     int code = config->GetAllocatableGeneralCode(i);
     if (source_uses_[code] == 0 && destination_uses_[code] == 0) {
diff --git a/src/crankshaft/x87/lithium-x87.cc b/src/crankshaft/x87/lithium-x87.cc
index 163d2c9..23941ad 100644
--- a/src/crankshaft/x87/lithium-x87.cc
+++ b/src/crankshaft/x87/lithium-x87.cc
@@ -925,7 +925,7 @@
 
 LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) {
   LInstruction* result = new (zone()) LPrologue();
-  if (info_->num_heap_slots() > 0) {
+  if (info_->scope()->num_heap_slots() > 0) {
     result = MarkAsCall(result, instr);
   }
   return result;
@@ -983,17 +983,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
-  LOperand* left =
-      UseFixed(instr->left(), InstanceOfDescriptor::LeftRegister());
-  LOperand* right =
-      UseFixed(instr->right(), InstanceOfDescriptor::RightRegister());
-  LOperand* context = UseFixed(instr->context(), esi);
-  LInstanceOf* result = new (zone()) LInstanceOf(context, left, right);
-  return MarkAsCall(DefineFixed(result, eax), instr);
-}
-
-
 LInstruction* LChunkBuilder::DoHasInPrototypeChainAndBranch(
     HHasInPrototypeChainAndBranch* instr) {
   LOperand* object = UseRegister(instr->object());
@@ -1121,15 +1110,28 @@
 
 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
   switch (instr->op()) {
-    case kMathFloor: return DoMathFloor(instr);
-    case kMathRound: return DoMathRound(instr);
-    case kMathFround: return DoMathFround(instr);
-    case kMathAbs: return DoMathAbs(instr);
-    case kMathLog: return DoMathLog(instr);
-    case kMathExp: return DoMathExp(instr);
-    case kMathSqrt: return DoMathSqrt(instr);
-    case kMathPowHalf: return DoMathPowHalf(instr);
-    case kMathClz32: return DoMathClz32(instr);
+    case kMathCos:
+      return DoMathCos(instr);
+    case kMathFloor:
+      return DoMathFloor(instr);
+    case kMathRound:
+      return DoMathRound(instr);
+    case kMathFround:
+      return DoMathFround(instr);
+    case kMathAbs:
+      return DoMathAbs(instr);
+    case kMathLog:
+      return DoMathLog(instr);
+    case kMathExp:
+      return DoMathExp(instr);
+    case kMathSqrt:
+      return DoMathSqrt(instr);
+    case kMathPowHalf:
+      return DoMathPowHalf(instr);
+    case kMathClz32:
+      return DoMathClz32(instr);
+    case kMathSin:
+      return DoMathSin(instr);
     default:
       UNREACHABLE();
       return NULL;
@@ -1184,15 +1186,25 @@
   return DefineAsRegister(result);
 }
 
+LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
+  DCHECK(instr->representation().IsDouble());
+  DCHECK(instr->value()->representation().IsDouble());
+  LOperand* input = UseRegisterAtStart(instr->value());
+  return MarkAsCall(DefineSameAsFirst(new (zone()) LMathCos(input)), instr);
+}
+
+LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
+  DCHECK(instr->representation().IsDouble());
+  DCHECK(instr->value()->representation().IsDouble());
+  LOperand* input = UseRegisterAtStart(instr->value());
+  return MarkAsCall(DefineSameAsFirst(new (zone()) LMathSin(input)), instr);
+}
 
 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
   DCHECK(instr->representation().IsDouble());
   DCHECK(instr->value()->representation().IsDouble());
-  LOperand* value = UseRegisterAtStart(instr->value());
-  LOperand* temp1 = FixedTemp(ecx);
-  LOperand* temp2 = FixedTemp(edx);
-  LMathExp* result = new(zone()) LMathExp(value, temp1, temp2);
-  return MarkAsCall(DefineSameAsFirst(result), instr);
+  LOperand* input = UseRegisterAtStart(instr->value());
+  return MarkAsCall(DefineSameAsFirst(new (zone()) LMathExp(input)), instr);
 }
 
 
@@ -1980,13 +1992,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
-  LOperand* lo = UseRegister(instr->lo());
-  LOperand* hi = UseRegister(instr->hi());
-  return DefineAsRegister(new(zone()) LConstructDouble(hi, lo));
-}
-
-
 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
   LOperand* context = info()->IsStub() ? UseFixed(instr->context(), esi) : NULL;
   LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
@@ -2016,15 +2021,9 @@
 
 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), esi);
-  LOperand* global_object =
-      UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
 
-  LLoadGlobalGeneric* result =
-      new(zone()) LLoadGlobalGeneric(context, global_object, vector);
+  LLoadGlobalGeneric* result = new (zone()) LLoadGlobalGeneric(context, vector);
   return MarkAsCall(DefineFixed(result, eax), instr);
 }
 
@@ -2072,10 +2071,7 @@
   LOperand* context = UseFixed(instr->context(), esi);
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
   LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(
       context, object, vector);
   return MarkAsCall(DefineFixed(result, eax), instr);
@@ -2145,10 +2141,7 @@
   LOperand* object =
       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
   LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister());
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
-  }
+  LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
   LLoadKeyedGeneric* result =
       new(zone()) LLoadKeyedGeneric(context, object, key, vector);
   return MarkAsCall(DefineFixed(result, eax), instr);
@@ -2238,12 +2231,8 @@
   DCHECK(instr->key()->representation().IsTagged());
   DCHECK(instr->value()->representation().IsTagged());
 
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
 
   LStoreKeyedGeneric* result = new (zone())
       LStoreKeyedGeneric(context, object, key, value, slot, vector);
@@ -2357,12 +2346,8 @@
   LOperand* object =
       UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
   LOperand* value = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
-  LOperand* slot = NULL;
-  LOperand* vector = NULL;
-  if (instr->HasVectorAndSlot()) {
-    slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
-    vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
-  }
+  LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
+  LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
 
   LStoreNamedGeneric* result =
       new (zone()) LStoreNamedGeneric(context, object, value, slot, vector);
@@ -2399,14 +2384,19 @@
 
 
 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
-  info()->MarkAsDeferredCalling();
-  LOperand* context = UseAny(instr->context());
-  LOperand* size = instr->size()->IsConstant()
-      ? UseConstant(instr->size())
-      : UseTempRegister(instr->size());
-  LOperand* temp = TempRegister();
-  LAllocate* result = new(zone()) LAllocate(context, size, temp);
-  return AssignPointerMap(DefineAsRegister(result));
+  LOperand* size = instr->size()->IsConstant() ? UseConstant(instr->size())
+                                               : UseRegister(instr->size());
+  if (instr->IsAllocationFolded()) {
+    LOperand* temp = TempRegister();
+    LFastAllocate* result = new (zone()) LFastAllocate(size, temp);
+    return DefineAsRegister(result);
+  } else {
+    info()->MarkAsDeferredCalling();
+    LOperand* context = UseAny(instr->context());
+    LOperand* temp = TempRegister();
+    LAllocate* result = new (zone()) LAllocate(context, size, temp);
+    return AssignPointerMap(DefineAsRegister(result));
+  }
 }
 
 
diff --git a/src/crankshaft/x87/lithium-x87.h b/src/crankshaft/x87/lithium-x87.h
index d83322a..d05d6eb 100644
--- a/src/crankshaft/x87/lithium-x87.h
+++ b/src/crankshaft/x87/lithium-x87.h
@@ -58,7 +58,6 @@
   V(ConstantI)                               \
   V(ConstantS)                               \
   V(ConstantT)                               \
-  V(ConstructDouble)                         \
   V(Context)                                 \
   V(DebugBreak)                              \
   V(DeclareGlobals)                          \
@@ -72,6 +71,7 @@
   V(Drop)                                    \
   V(Dummy)                                   \
   V(DummyUse)                                \
+  V(FastAllocate)                            \
   V(FlooringDivByConstI)                     \
   V(FlooringDivByPowerOf2I)                  \
   V(FlooringDivI)                            \
@@ -83,7 +83,6 @@
   V(HasInPrototypeChainAndBranch)            \
   V(HasInstanceTypeAndBranch)                \
   V(InnerAllocatedObject)                    \
-  V(InstanceOf)                              \
   V(InstructionGap)                          \
   V(Integer32ToDouble)                       \
   V(InvokeFunction)                          \
@@ -103,6 +102,7 @@
   V(LoadRoot)                                \
   V(MathAbs)                                 \
   V(MathClz32)                               \
+  V(MathCos)                                 \
   V(MathExp)                                 \
   V(MathFloor)                               \
   V(MathFround)                              \
@@ -112,6 +112,7 @@
   V(MathRound)                               \
   V(MathSqrt)                                \
   V(MaybeGrowElements)                       \
+  V(MathSin)                                 \
   V(ModByConstI)                             \
   V(ModByPowerOf2I)                          \
   V(ModI)                                    \
@@ -153,7 +154,6 @@
   V(UnknownOSRValue)                         \
   V(WrapReceiver)
 
-
 #define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic)            \
   Opcode opcode() const final { return LInstruction::k##type; } \
   void CompileToNative(LCodeGen* generator) final;              \
@@ -905,21 +905,29 @@
   DECLARE_CONCRETE_INSTRUCTION(MathClz32, "math-clz32")
 };
 
-
-class LMathExp final : public LTemplateInstruction<1, 1, 2> {
+class LMathCos final : public LTemplateInstruction<1, 1, 0> {
  public:
-  LMathExp(LOperand* value,
-           LOperand* temp1,
-           LOperand* temp2) {
-    inputs_[0] = value;
-    temps_[0] = temp1;
-    temps_[1] = temp2;
-    ExternalReference::InitializeMathExpData();
-  }
+  explicit LMathCos(LOperand* value) { inputs_[0] = value; }
 
   LOperand* value() { return inputs_[0]; }
-  LOperand* temp1() { return temps_[0]; }
-  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathCos, "math-cos")
+};
+
+class LMathSin final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathSin(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(MathSin, "math-sin")
+};
+
+class LMathExp final : public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LMathExp(LOperand* value) { inputs_[0] = value; }
+
+  LOperand* value() { return inputs_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(MathExp, "math-exp")
 };
@@ -1134,22 +1142,6 @@
 };
 
 
-class LInstanceOf final : public LTemplateInstruction<1, 3, 0> {
- public:
-  LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
-    inputs_[0] = context;
-    inputs_[1] = left;
-    inputs_[2] = right;
-  }
-
-  LOperand* context() const { return inputs_[0]; }
-  LOperand* left() const { return inputs_[1]; }
-  LOperand* right() const { return inputs_[2]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
-};
-
-
 class LHasInPrototypeChainAndBranch final : public LControlInstruction<2, 1> {
  public:
   LHasInPrototypeChainAndBranch(LOperand* object, LOperand* prototype,
@@ -1596,18 +1588,14 @@
   DECLARE_HYDROGEN_ACCESSOR(LoadKeyedGeneric)
 };
 
-
-class LLoadGlobalGeneric final : public LTemplateInstruction<1, 2, 1> {
+class LLoadGlobalGeneric final : public LTemplateInstruction<1, 1, 1> {
  public:
-  LLoadGlobalGeneric(LOperand* context, LOperand* global_object,
-                     LOperand* vector) {
+  LLoadGlobalGeneric(LOperand* context, LOperand* vector) {
     inputs_[0] = context;
-    inputs_[1] = global_object;
     temps_[0] = vector;
   }
 
   LOperand* context() { return inputs_[0]; }
-  LOperand* global_object() { return inputs_[1]; }
   LOperand* temp_vector() { return temps_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadGlobalGeneric, "load-global-generic")
@@ -2368,20 +2356,6 @@
 };
 
 
-class LConstructDouble final : public LTemplateInstruction<1, 2, 0> {
- public:
-  LConstructDouble(LOperand* hi, LOperand* lo) {
-    inputs_[0] = hi;
-    inputs_[1] = lo;
-  }
-
-  LOperand* hi() { return inputs_[0]; }
-  LOperand* lo() { return inputs_[1]; }
-
-  DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
-};
-
-
 class LAllocate final : public LTemplateInstruction<1, 2, 1> {
  public:
   LAllocate(LOperand* context, LOperand* size, LOperand* temp) {
@@ -2398,6 +2372,19 @@
   DECLARE_HYDROGEN_ACCESSOR(Allocate)
 };
 
+class LFastAllocate final : public LTemplateInstruction<1, 1, 1> {
+ public:
+  LFastAllocate(LOperand* size, LOperand* temp) {
+    inputs_[0] = size;
+    temps_[0] = temp;
+  }
+
+  LOperand* size() const { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(FastAllocate, "fast-allocate")
+  DECLARE_HYDROGEN_ACCESSOR(Allocate)
+};
 
 class LTypeof final : public LTemplateInstruction<1, 2, 0> {
  public:
@@ -2552,6 +2539,8 @@
   LInstruction* DoMathFround(HUnaryMathOperation* instr);
   LInstruction* DoMathAbs(HUnaryMathOperation* instr);
   LInstruction* DoMathLog(HUnaryMathOperation* instr);
+  LInstruction* DoMathCos(HUnaryMathOperation* instr);
+  LInstruction* DoMathSin(HUnaryMathOperation* instr);
   LInstruction* DoMathExp(HUnaryMathOperation* instr);
   LInstruction* DoMathSqrt(HUnaryMathOperation* instr);
   LInstruction* DoMathPowHalf(HUnaryMathOperation* instr);
diff --git a/src/d8-posix.cc b/src/d8-posix.cc
index 36d83b5..fb14f95 100644
--- a/src/d8-posix.cc
+++ b/src/d8-posix.cc
@@ -531,21 +531,18 @@
   OpenFDCloser error_read_closer(exec_error_fds[kReadFD]);
   OpenFDCloser stdout_read_closer(stdout_fds[kReadFD]);
 
-  if (!ChildLaunchedOK(args.GetIsolate(), exec_error_fds)) return;
+  Isolate* isolate = args.GetIsolate();
+  if (!ChildLaunchedOK(isolate, exec_error_fds)) return;
 
-  Local<Value> accumulator = GetStdout(args.GetIsolate(), stdout_fds[kReadFD],
-                                       start_time, read_timeout, total_timeout);
+  Local<Value> accumulator = GetStdout(isolate, stdout_fds[kReadFD], start_time,
+                                       read_timeout, total_timeout);
   if (accumulator->IsUndefined()) {
     kill(pid, SIGINT);  // On timeout, kill the subprocess.
     args.GetReturnValue().Set(accumulator);
     return;
   }
 
-  if (!WaitForChild(args.GetIsolate(),
-                    pid,
-                    child_waiter,
-                    start_time,
-                    read_timeout,
+  if (!WaitForChild(isolate, pid, child_waiter, start_time, read_timeout,
                     total_timeout)) {
     return;
   }
diff --git a/src/d8.cc b/src/d8.cc
index 0688380..7b62707 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -19,6 +19,7 @@
 
 #ifndef V8_SHARED
 #include <algorithm>
+#include <fstream>
 #include <vector>
 #endif  // !V8_SHARED
 
@@ -41,6 +42,7 @@
 #include "src/base/platform/platform.h"
 #include "src/base/sys-info.h"
 #include "src/basic-block-profiler.h"
+#include "src/interpreter/interpreter.h"
 #include "src/snapshot/natives.h"
 #include "src/utils.h"
 #include "src/v8.h"
@@ -336,7 +338,9 @@
     ScriptCompiler::CompileOptions compile_options, SourceType source_type) {
   Local<Context> context(isolate->GetCurrentContext());
   ScriptOrigin origin(name);
-  if (compile_options == ScriptCompiler::kNoCompileOptions) {
+  // TODO(adamk): Make use of compile options for Modules.
+  if (compile_options == ScriptCompiler::kNoCompileOptions ||
+      source_type == MODULE) {
     ScriptCompiler::Source script_source(source, origin);
     return source_type == SCRIPT
                ? ScriptCompiler::Compile(context, &script_source,
@@ -356,11 +360,9 @@
     DCHECK(false);  // A new compile option?
   }
   if (data == NULL) compile_options = ScriptCompiler::kNoCompileOptions;
+  DCHECK_EQ(SCRIPT, source_type);
   MaybeLocal<Script> result =
-      source_type == SCRIPT
-          ? ScriptCompiler::Compile(context, &cached_source, compile_options)
-          : ScriptCompiler::CompileModule(context, &cached_source,
-                                          compile_options);
+      ScriptCompiler::Compile(context, &cached_source, compile_options);
   CHECK(data == NULL || !data->rejected);
   return result;
 }
@@ -521,9 +523,8 @@
       Local<Context>::New(args.GetIsolate(), data->realms_[index])->Global());
 }
 
-
-// Realm.create() creates a new realm and returns its index.
-void Shell::RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args) {
+MaybeLocal<Context> Shell::CreateRealm(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
   Isolate* isolate = args.GetIsolate();
   TryCatch try_catch(isolate);
   PerIsolateData* data = PerIsolateData::Get(isolate);
@@ -540,12 +541,29 @@
   if (context.IsEmpty()) {
     DCHECK(try_catch.HasCaught());
     try_catch.ReThrow();
-    return;
+    return MaybeLocal<Context>();
   }
   data->realms_[index].Reset(isolate, context);
   args.GetReturnValue().Set(index);
+  return context;
 }
 
+// Realm.create() creates a new realm with a distinct security token
+// and returns its index.
+void Shell::RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  CreateRealm(args);
+}
+
+// Realm.createAllowCrossRealmAccess() creates a new realm with the same
+// security token as the current realm.
+void Shell::RealmCreateAllowCrossRealmAccess(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  Local<Context> context;
+  if (CreateRealm(args).ToLocal(&context)) {
+    context->SetSecurityToken(
+        args.GetIsolate()->GetEnteredContext()->GetSecurityToken());
+  }
+}
 
 // Realm.dispose(i) disposes the reference to the realm i.
 void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
@@ -907,25 +925,28 @@
     // Print (filename):(line number): (message).
     v8::String::Utf8Value filename(message->GetScriptOrigin().ResourceName());
     const char* filename_string = ToCString(filename);
-    int linenum =
-        message->GetLineNumber(isolate->GetCurrentContext()).FromJust();
+    Maybe<int> maybeline = message->GetLineNumber(isolate->GetCurrentContext());
+    int linenum = maybeline.IsJust() ? maybeline.FromJust() : -1;
     printf("%s:%i: %s\n", filename_string, linenum, exception_string);
-    // Print line of source code.
-    v8::String::Utf8Value sourceline(
-        message->GetSourceLine(isolate->GetCurrentContext()).ToLocalChecked());
-    const char* sourceline_string = ToCString(sourceline);
-    printf("%s\n", sourceline_string);
-    // Print wavy underline (GetUnderline is deprecated).
-    int start =
-        message->GetStartColumn(isolate->GetCurrentContext()).FromJust();
-    for (int i = 0; i < start; i++) {
-      printf(" ");
+    Local<String> sourceline;
+    if (message->GetSourceLine(isolate->GetCurrentContext())
+            .ToLocal(&sourceline)) {
+      // Print line of source code.
+      v8::String::Utf8Value sourcelinevalue(sourceline);
+      const char* sourceline_string = ToCString(sourcelinevalue);
+      printf("%s\n", sourceline_string);
+      // Print wavy underline (GetUnderline is deprecated).
+      int start =
+          message->GetStartColumn(isolate->GetCurrentContext()).FromJust();
+      for (int i = 0; i < start; i++) {
+        printf(" ");
+      }
+      int end = message->GetEndColumn(isolate->GetCurrentContext()).FromJust();
+      for (int i = start; i < end; i++) {
+        printf("^");
+      }
+      printf("\n");
     }
-    int end = message->GetEndColumn(isolate->GetCurrentContext()).FromJust();
-    for (int i = start; i < end; i++) {
-      printf("^");
-    }
-    printf("\n");
     Local<Value> stack_trace_string;
     if (try_catch->StackTrace(isolate->GetCurrentContext())
             .ToLocal(&stack_trace_string) &&
@@ -1114,6 +1135,10 @@
       String::NewFromUtf8(isolate, "version", NewStringType::kNormal)
           .ToLocalChecked(),
       FunctionTemplate::New(isolate, Version));
+  global_template->Set(
+      Symbol::GetToStringTag(isolate),
+      String::NewFromUtf8(isolate, "global", NewStringType::kNormal)
+          .ToLocalChecked());
 
   // Bind the Realm object.
   Local<ObjectTemplate> realm_template = ObjectTemplate::New(isolate);
@@ -1134,6 +1159,11 @@
           .ToLocalChecked(),
       FunctionTemplate::New(isolate, RealmCreate));
   realm_template->Set(
+      String::NewFromUtf8(isolate, "createAllowCrossRealmAccess",
+                          NewStringType::kNormal)
+          .ToLocalChecked(),
+      FunctionTemplate::New(isolate, RealmCreateAllowCrossRealmAccess));
+  realm_template->Set(
       String::NewFromUtf8(isolate, "dispose", NewStringType::kNormal)
           .ToLocalChecked(),
       FunctionTemplate::New(isolate, RealmDispose));
@@ -1275,6 +1305,21 @@
 inline bool operator<(const CounterAndKey& lhs, const CounterAndKey& rhs) {
   return strcmp(lhs.key, rhs.key) < 0;
 }
+
+void Shell::WriteIgnitionDispatchCountersFile(v8::Isolate* isolate) {
+  HandleScope handle_scope(isolate);
+  Local<Context> context = Context::New(isolate);
+  Context::Scope context_scope(context);
+
+  Local<Object> dispatch_counters = reinterpret_cast<i::Isolate*>(isolate)
+                                        ->interpreter()
+                                        ->GetDispatchCountersObject();
+  std::ofstream dispatch_counters_stream(
+      i::FLAG_trace_ignition_dispatches_output_file);
+  dispatch_counters_stream << *String::Utf8Value(
+      JSON::Stringify(context, dispatch_counters).ToLocalChecked());
+}
+
 #endif  // !V8_SHARED
 
 
@@ -1312,6 +1357,7 @@
            "-------------+\n");
     delete [] counters;
   }
+
   delete counters_file_;
   delete counter_map_;
 #endif  // !V8_SHARED
@@ -2383,7 +2429,7 @@
 #endif  // defined(_MSC_VER)
 #endif  // defined(_WIN32) || defined(_WIN64)
   if (!SetOptions(argc, argv)) return 1;
-  v8::V8::InitializeICU(options.icu_data_file);
+  v8::V8::InitializeICUDefaultLocation(argv[0], options.icu_data_file);
 #ifndef V8_SHARED
   g_platform = i::FLAG_verify_predictable
                    ? new PredictablePlatform()
@@ -2476,6 +2522,13 @@
       RunShell(isolate);
     }
 
+#ifndef V8_SHARED
+    if (i::FLAG_ignition && i::FLAG_trace_ignition_dispatches &&
+        i::FLAG_trace_ignition_dispatches_output_file != nullptr) {
+      WriteIgnitionDispatchCountersFile(isolate);
+    }
+#endif
+
     // Shut down contexts and collect garbage.
     evaluation_context_.Reset();
 #ifndef V8_SHARED
diff --git a/src/d8.gyp b/src/d8.gyp
index f249a78..e60b01f 100644
--- a/src/d8.gyp
+++ b/src/d8.gyp
@@ -31,16 +31,15 @@
     # Enable support for Intel VTune. Supported on ia32/x64 only
     'v8_enable_vtunejit%': 0,
     'v8_enable_i18n_support%': 1,
-    'v8_toolset_for_d8%': 'target',
   },
-  'includes': ['../build/toolchain.gypi', '../build/features.gypi'],
+  'includes': ['../gypfiles/toolchain.gypi', '../gypfiles/features.gypi'],
   'targets': [
     {
       'target_name': 'd8',
       'type': 'executable',
       'dependencies': [
-        '../tools/gyp/v8.gyp:v8',
-        '../tools/gyp/v8.gyp:v8_libplatform',
+        'v8.gyp:v8',
+        'v8.gyp:v8_libplatform',
       ],
       # Generated source files need this explicitly:
       'include_dirs+': [
@@ -52,7 +51,7 @@
       ],
       'conditions': [
         [ 'want_separate_host_toolset==1', {
-          'toolsets': [ '<(v8_toolset_for_d8)', ],
+          'toolsets': [ 'target', ],
         }],
         ['(OS=="linux" or OS=="mac" or OS=="freebsd" or OS=="netbsd" \
            or OS=="openbsd" or OS=="solaris" or OS=="android" \
@@ -141,7 +140,7 @@
     },
   ],
   'conditions': [
-    ['test_isolation_mode != "noop" and v8_toolset_for_d8 == "target"', {
+    ['test_isolation_mode != "noop"', {
       'targets': [
         {
           'target_name': 'd8_run',
@@ -150,7 +149,7 @@
             'd8',
           ],
           'includes': [
-            '../build/isolate.gypi',
+            '../gypfiles/isolate.gypi',
           ],
           'sources': [
             'd8.isolate',
diff --git a/src/d8.h b/src/d8.h
index 321d9c1..36ec43e 100644
--- a/src/d8.h
+++ b/src/d8.h
@@ -7,8 +7,8 @@
 
 #ifndef V8_SHARED
 #include "src/allocation.h"
+#include "src/base/hashmap.h"
 #include "src/base/platform/time.h"
-#include "src/hashmap.h"
 #include "src/list.h"
 #else
 #include "include/v8.h"
@@ -61,13 +61,13 @@
  public:
   CounterMap(): hash_map_(Match) { }
   Counter* Lookup(const char* name) {
-    i::HashMap::Entry* answer =
+    base::HashMap::Entry* answer =
         hash_map_.Lookup(const_cast<char*>(name), Hash(name));
     if (!answer) return NULL;
     return reinterpret_cast<Counter*>(answer->value);
   }
   void Set(const char* name, Counter* value) {
-    i::HashMap::Entry* answer =
+    base::HashMap::Entry* answer =
         hash_map_.LookupOrInsert(const_cast<char*>(name), Hash(name));
     DCHECK(answer != NULL);
     answer->value = value;
@@ -81,14 +81,14 @@
     const char* CurrentKey() { return static_cast<const char*>(entry_->key); }
     Counter* CurrentValue() { return static_cast<Counter*>(entry_->value); }
    private:
-    i::HashMap* map_;
-    i::HashMap::Entry* entry_;
+    base::HashMap* map_;
+    base::HashMap::Entry* entry_;
   };
 
  private:
   static int Hash(const char* name);
   static bool Match(void* key1, void* key2);
-  i::HashMap hash_map_;
+  base::HashMap hash_map_;
 };
 #endif  // !V8_SHARED
 
@@ -350,7 +350,7 @@
 
 #ifndef V8_SHARED
   // TODO(binji): stupid implementation for now. Is there an easy way to hash an
-  // object for use in i::HashMap? By pointer?
+  // object for use in base::HashMap? By pointer?
   typedef i::List<Local<Object>> ObjectList;
   static bool SerializeValue(Isolate* isolate, Local<Value> value,
                              const ObjectList& to_transfer,
@@ -375,6 +375,8 @@
   static void RealmOwner(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void RealmGlobal(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args);
+  static void RealmCreateAllowCrossRealmAccess(
+      const v8::FunctionCallbackInfo<v8::Value>& args);
   static void RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void RealmSwitch(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void RealmEval(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -461,6 +463,7 @@
   static i::List<Worker*> workers_;
   static i::List<SharedArrayBuffer::Contents> externalized_shared_contents_;
 
+  static void WriteIgnitionDispatchCountersFile(v8::Isolate* isolate);
   static Counter* GetCounter(const char* name, bool is_histogram);
   static Local<String> Stringify(Isolate* isolate, Local<Value> value);
 #endif  // !V8_SHARED
@@ -468,6 +471,8 @@
   static void RunShell(Isolate* isolate);
   static bool SetOptions(int argc, char* argv[]);
   static Local<ObjectTemplate> CreateGlobalTemplate(Isolate* isolate);
+  static MaybeLocal<Context> CreateRealm(
+      const v8::FunctionCallbackInfo<v8::Value>& args);
 };
 
 
diff --git a/src/dateparser-inl.h b/src/dateparser-inl.h
index 7e5c4e3..47a7c6e 100644
--- a/src/dateparser-inl.h
+++ b/src/dateparser-inl.h
@@ -13,9 +13,8 @@
 namespace internal {
 
 template <typename Char>
-bool DateParser::Parse(Vector<Char> str,
-                       FixedArray* out,
-                       UnicodeCache* unicode_cache) {
+bool DateParser::Parse(Isolate* isolate, Vector<Char> str, FixedArray* out) {
+  UnicodeCache* unicode_cache = isolate->unicode_cache();
   DCHECK(out->length() >= OUTPUT_SIZE);
   InputReader<Char> in(unicode_cache, str);
   DateStringTokenizer<Char> scanner(&in);
@@ -76,10 +75,12 @@
   if (next_unhandled_token.IsInvalid()) return false;
   bool has_read_number = !day.IsEmpty();
   // If there's anything left, continue with the legacy parser.
+  bool legacy_parser = false;
   for (DateToken token = next_unhandled_token;
        !token.IsEndOfInput();
        token = scanner.Next()) {
     if (token.IsNumber()) {
+      legacy_parser = true;
       has_read_number = true;
       int n = token.number();
       if (scanner.SkipSymbol(':')) {
@@ -115,6 +116,7 @@
         scanner.SkipSymbol('-');
       }
     } else if (token.IsKeyword()) {
+      legacy_parser = true;
       // Parse a "word" (sequence of chars. >= 'A').
       KeywordType type = token.keyword_type();
       int value = token.keyword_value();
@@ -133,6 +135,7 @@
         if (scanner.Peek().IsNumber()) return false;
       }
     } else if (token.IsAsciiSign() && (tz.IsUTC() || !time.IsEmpty())) {
+      legacy_parser = true;
       // Parse UTC offset (only after UTC or time).
       tz.SetSign(token.ascii_sign());
       // The following number may be empty.
@@ -170,7 +173,13 @@
     }
   }
 
-  return day.Write(out) && time.Write(out) && tz.Write(out);
+  bool success = day.Write(out) && time.Write(out) && tz.Write(out);
+
+  if (legacy_parser && success) {
+    isolate->CountUsage(v8::Isolate::kLegacyDateParser);
+  }
+
+  return success;
 }
 
 
diff --git a/src/dateparser.h b/src/dateparser.h
index 5331739..d7676cb 100644
--- a/src/dateparser.h
+++ b/src/dateparser.h
@@ -26,7 +26,7 @@
   // [7]: UTC offset in seconds, or null value if no timezone specified
   // If parsing fails, return false (content of output array is not defined).
   template <typename Char>
-  static bool Parse(Vector<Char> str, FixedArray* output, UnicodeCache* cache);
+  static bool Parse(Isolate* isolate, Vector<Char> str, FixedArray* output);
 
   enum {
     YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, MILLISECOND, UTC_OFFSET, OUTPUT_SIZE
diff --git a/src/debug/arm/debug-arm.cc b/src/debug/arm/debug-arm.cc
index fa3540e..29e4827 100644
--- a/src/debug/arm/debug-arm.cc
+++ b/src/debug/arm/debug-arm.cc
@@ -41,7 +41,7 @@
 
 void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
                                        Handle<Code> code) {
-  DCHECK_EQ(Code::BUILTIN, code->kind());
+  DCHECK(code->is_debug_stub());
   CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotInstructions);
   // Patch the code changing the debug break slot code from
   //   mov r2, r2
diff --git a/src/debug/arm64/debug-arm64.cc b/src/debug/arm64/debug-arm64.cc
index cd01721..bf7964a 100644
--- a/src/debug/arm64/debug-arm64.cc
+++ b/src/debug/arm64/debug-arm64.cc
@@ -43,7 +43,7 @@
 
 void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
                                        Handle<Code> code) {
-  DCHECK_EQ(Code::BUILTIN, code->kind());
+  DCHECK(code->is_debug_stub());
   PatchingAssembler patcher(isolate, reinterpret_cast<Instruction*>(pc),
                             Assembler::kDebugBreakSlotInstructions);
   // Patch the code emitted by DebugCodegen::GenerateSlots, changing the debug
diff --git a/src/debug/debug-evaluate.cc b/src/debug/debug-evaluate.cc
index 1729408..62b7a2b 100644
--- a/src/debug/debug-evaluate.cc
+++ b/src/debug/debug-evaluate.cc
@@ -95,11 +95,12 @@
   }
 
   Handle<JSFunction> eval_fun;
-  ASSIGN_RETURN_ON_EXCEPTION(isolate, eval_fun,
-                             Compiler::GetFunctionFromEval(
-                                 source, outer_info, context, SLOPPY,
-                                 NO_PARSE_RESTRICTION, RelocInfo::kNoPosition),
-                             Object);
+  ASSIGN_RETURN_ON_EXCEPTION(
+      isolate, eval_fun,
+      Compiler::GetFunctionFromEval(
+          source, outer_info, context, SLOPPY, NO_PARSE_RESTRICTION,
+          RelocInfo::kNoPosition, RelocInfo::kNoPosition),
+      Object);
 
   Handle<Object> result;
   ASSIGN_RETURN_ON_EXCEPTION(
@@ -182,7 +183,8 @@
         context_chain_element.wrapped_context = current_context;
       }
       context_chain_.Add(context_chain_element);
-    } else if (scope_type == ScopeIterator::ScopeTypeBlock) {
+    } else if (scope_type == ScopeIterator::ScopeTypeBlock ||
+               scope_type == ScopeIterator::ScopeTypeEval) {
       Handle<JSObject> materialized = factory->NewJSObjectWithNullProto();
       frame_inspector.MaterializeStackLocals(materialized,
                                              it.CurrentScopeInfo());
@@ -247,7 +249,8 @@
     // 'this' is allocated in an outer context and is is already being
     // referenced by the current function, so it can be correctly resolved.
     return;
-  } else if (local_function->shared()->scope_info()->HasReceiver()) {
+  } else if (local_function->shared()->scope_info()->HasReceiver() &&
+             !frame_->receiver()->IsTheHole(isolate_)) {
     recv = handle(frame_->receiver(), isolate_);
   }
   JSObject::SetOwnPropertyIgnoreAttributes(target, name, recv, NONE).Check();
diff --git a/src/debug/debug-frames.cc b/src/debug/debug-frames.cc
index a7956ff..b1a8af2 100644
--- a/src/debug/debug-frames.cc
+++ b/src/debug/debug-frames.cc
@@ -72,8 +72,7 @@
     return deoptimized_frame_->GetSourcePosition();
   } else if (is_interpreted_) {
     InterpretedFrame* frame = reinterpret_cast<InterpretedFrame*>(frame_);
-    BytecodeArray* bytecode_array =
-        frame->function()->shared()->bytecode_array();
+    BytecodeArray* bytecode_array = frame->GetBytecodeArray();
     return bytecode_array->SourcePosition(frame->GetBytecodeOffset());
   } else {
     Code* code = frame_->LookupCode();
@@ -117,26 +116,31 @@
     // TODO(yangguo): check whether this is necessary, now that we materialize
     //                context locals as well.
     Handle<String> name(scope_info->ParameterName(i));
+    if (ScopeInfo::VariableIsSynthetic(*name)) continue;
     if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
 
     Handle<Object> value =
         i < GetParametersCount()
             ? GetParameter(i)
             : Handle<Object>::cast(isolate_->factory()->undefined_value());
-    DCHECK(!value->IsTheHole());
+    DCHECK(!value->IsTheHole(isolate_));
 
     JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
   }
 
   // Second fill all stack locals.
   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
-    if (scope_info->LocalIsSynthetic(i)) continue;
     Handle<String> name(scope_info->StackLocalName(i));
+    if (ScopeInfo::VariableIsSynthetic(*name)) continue;
     Handle<Object> value = GetExpression(scope_info->StackLocalIndex(i));
     // TODO(yangguo): We convert optimized out values to {undefined} when they
     // are passed to the debugger. Eventually we should handle them somehow.
-    if (value->IsTheHole()) value = isolate_->factory()->undefined_value();
-    if (value->IsOptimizedOut()) value = isolate_->factory()->undefined_value();
+    if (value->IsTheHole(isolate_)) {
+      value = isolate_->factory()->undefined_value();
+    }
+    if (value->IsOptimizedOut(isolate_)) {
+      value = isolate_->factory()->undefined_value();
+    }
     JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check();
   }
 }
@@ -163,9 +167,10 @@
   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
     // Shadowed parameters were not materialized.
     Handle<String> name(scope_info->ParameterName(i));
+    if (ScopeInfo::VariableIsSynthetic(*name)) continue;
     if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
 
-    DCHECK(!frame_->GetParameter(i)->IsTheHole());
+    DCHECK(!frame_->GetParameter(i)->IsTheHole(isolate_));
     Handle<Object> value =
         Object::GetPropertyOrElement(target, name).ToHandleChecked();
     frame_->SetParameterValue(i, *value);
@@ -173,13 +178,12 @@
 
   // Stack locals.
   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
-    if (scope_info->LocalIsSynthetic(i)) continue;
+    Handle<String> name(scope_info->StackLocalName(i));
+    if (ScopeInfo::VariableIsSynthetic(*name)) continue;
     int index = scope_info->StackLocalIndex(i);
-    if (frame_->GetExpression(index)->IsTheHole()) continue;
+    if (frame_->GetExpression(index)->IsTheHole(isolate_)) continue;
     Handle<Object> value =
-        Object::GetPropertyOrElement(
-            target, handle(scope_info->StackLocalName(i), isolate_))
-            .ToHandleChecked();
+        Object::GetPropertyOrElement(target, name).ToHandleChecked();
     frame_->SetExpression(index, *value);
   }
 }
diff --git a/src/debug/debug-scopes.cc b/src/debug/debug-scopes.cc
index d9c615b..400b1e1 100644
--- a/src/debug/debug-scopes.cc
+++ b/src/debug/debug-scopes.cc
@@ -5,6 +5,7 @@
 #include "src/debug/debug-scopes.h"
 
 #include "src/ast/scopes.h"
+#include "src/compiler.h"
 #include "src/debug/debug.h"
 #include "src/frames-inl.h"
 #include "src/globals.h"
@@ -33,7 +34,7 @@
   Handle<JSFunction> function = GetFunction();
   Handle<SharedFunctionInfo> shared_info(function->shared());
   Handle<ScopeInfo> scope_info(shared_info->scope_info());
-  if (shared_info->script() == isolate->heap()->undefined_value()) {
+  if (shared_info->script()->IsUndefined(isolate)) {
     while (context_->closure() == *function) {
       context_ = Handle<Context>(context_->previous(), isolate_);
     }
@@ -80,34 +81,29 @@
   }
 
   // Reparse the code and analyze the scopes.
-  Scope* scope = NULL;
   // Check whether we are in global, eval or function code.
   Zone zone(isolate->allocator());
+  base::SmartPointer<ParseInfo> info;
   if (scope_info->scope_type() != FUNCTION_SCOPE) {
     // Global or eval code.
     Handle<Script> script(Script::cast(shared_info->script()));
-    ParseInfo info(&zone, script);
+    info.Reset(new ParseInfo(&zone, script));
+    info->set_toplevel();
     if (scope_info->scope_type() == SCRIPT_SCOPE) {
-      info.set_global();
+      info->set_global();
     } else {
       DCHECK(scope_info->scope_type() == EVAL_SCOPE);
-      info.set_eval();
-      info.set_context(Handle<Context>(function->context()));
+      info->set_eval();
+      info->set_context(Handle<Context>(function->context()));
     }
-    if (Parser::ParseStatic(&info) && Scope::Analyze(&info)) {
-      scope = info.literal()->scope();
-    }
-    if (!ignore_nested_scopes) RetrieveScopeChain(scope);
-    if (collect_non_locals) CollectNonLocals(scope);
   } else {
-    // Function code
-    ParseInfo info(&zone, function);
-    if (Parser::ParseStatic(&info) && Scope::Analyze(&info)) {
-      scope = info.literal()->scope();
-    }
-    if (!ignore_nested_scopes) RetrieveScopeChain(scope);
-    if (collect_non_locals) CollectNonLocals(scope);
+    // Inner function.
+    info.Reset(new ParseInfo(&zone, function));
   }
+  Scope* scope = NULL;
+  if (Compiler::ParseAndAnalyze(info.get())) scope = info->literal()->scope();
+  if (!ignore_nested_scopes) RetrieveScopeChain(scope);
+  if (collect_non_locals) CollectNonLocals(scope);
   UnwrapEvaluationContext();
 }
 
@@ -126,8 +122,6 @@
   while (true) {
     if (context_.is_null()) return;
     if (!context_->IsDebugEvaluateContext()) return;
-    // An existing debug-evaluate context can only be outside the local scope.
-    DCHECK(nested_scope_chain_.is_empty());
     Handle<Object> wrapped(context_->get(Context::WRAPPED_CONTEXT_INDEX),
                            isolate_);
     if (wrapped->IsContext()) {
@@ -201,11 +195,15 @@
   } else if (nested_scope_chain_.is_empty()) {
     context_ = Handle<Context>(context_->previous(), isolate_);
   } else {
-    if (nested_scope_chain_.last().scope_info->HasContext()) {
-      DCHECK(context_->previous() != NULL);
-      context_ = Handle<Context>(context_->previous(), isolate_);
-    }
-    nested_scope_chain_.RemoveLast();
+    do {
+      if (nested_scope_chain_.last().scope_info->HasContext()) {
+        DCHECK(context_->previous() != NULL);
+        context_ = Handle<Context>(context_->previous(), isolate_);
+      }
+      nested_scope_chain_.RemoveLast();
+      if (nested_scope_chain_.is_empty()) break;
+      // Repeat to skip hidden scopes.
+    } while (nested_scope_chain_.last().is_hidden());
   }
   UnwrapEvaluationContext();
 }
@@ -236,8 +234,10 @@
         DCHECK(!scope_info->HasContext() || context_->IsBlockContext());
         return ScopeTypeBlock;
       case EVAL_SCOPE:
-        UNREACHABLE();
+        DCHECK(!scope_info->HasContext() || context_->IsFunctionContext());
+        return ScopeTypeEval;
     }
+    UNREACHABLE();
   }
   if (context_->IsNativeContext()) {
     DCHECK(context_->global_object()->IsJSGlobalObject());
@@ -284,7 +284,8 @@
       // Materialize the content of the closure scope into a JSObject.
       return MaterializeClosure();
     case ScopeIterator::ScopeTypeBlock:
-      return MaterializeBlockScope();
+    case ScopeIterator::ScopeTypeEval:
+      return MaterializeInnerScope();
     case ScopeIterator::ScopeTypeModule:
       return MaterializeModuleScope();
   }
@@ -295,7 +296,8 @@
 
 bool ScopeIterator::HasContext() {
   ScopeType type = Type();
-  if (type == ScopeTypeBlock || type == ScopeTypeLocal) {
+  if (type == ScopeTypeBlock || type == ScopeTypeLocal ||
+      type == ScopeTypeEval) {
     if (!nested_scope_chain_.is_empty()) {
       return nested_scope_chain_.last().scope_info->HasContext();
     }
@@ -321,7 +323,8 @@
     case ScopeIterator::ScopeTypeScript:
       return SetScriptVariableValue(variable_name, new_value);
     case ScopeIterator::ScopeTypeBlock:
-      return SetBlockVariableValue(variable_name, new_value);
+    case ScopeIterator::ScopeTypeEval:
+      return SetInnerScopeVariableValue(variable_name, new_value);
     case ScopeIterator::ScopeTypeModule:
       // TODO(2399): should we implement it?
       break;
@@ -453,7 +456,7 @@
       global->native_context()->script_context_table());
 
   Handle<JSObject> script_scope =
-      isolate_->factory()->NewJSObject(isolate_->object_function());
+      isolate_->factory()->NewJSObjectWithNullProto();
 
   for (int context_index = 0; context_index < script_contexts->used();
        context_index++) {
@@ -470,7 +473,7 @@
   Handle<JSFunction> function = GetFunction();
 
   Handle<JSObject> local_scope =
-      isolate_->factory()->NewJSObject(isolate_->object_function());
+      isolate_->factory()->NewJSObjectWithNullProto();
   frame_inspector_->MaterializeStackLocals(local_scope, function);
 
   Handle<Context> frame_context =
@@ -482,19 +485,16 @@
 
   if (!scope_info->HasContext()) return local_scope;
 
-  // Third fill all context locals.
+  // Fill all context locals.
   Handle<Context> function_context(frame_context->closure_context());
   CopyContextLocalsToScopeObject(scope_info, function_context, local_scope);
 
   // Finally copy any properties from the function context extension.
   // These will be variables introduced by eval.
   if (function_context->closure() == *function &&
-      function_context->has_extension() &&
       !function_context->IsNativeContext()) {
-    bool success = CopyContextExtensionToScopeObject(
-        handle(function_context->extension_object(), isolate_), local_scope,
-        INCLUDE_PROTOS);
-    if (!success) return MaybeHandle<JSObject>();
+    CopyContextExtensionToScopeObject(function_context, local_scope,
+                                      KeyCollectionMode::kIncludePrototypes);
   }
 
   return local_scope;
@@ -513,19 +513,15 @@
   // Allocate and initialize a JSObject with all the content of this function
   // closure.
   Handle<JSObject> closure_scope =
-      isolate_->factory()->NewJSObject(isolate_->object_function());
+      isolate_->factory()->NewJSObjectWithNullProto();
 
   // Fill all context locals to the context extension.
   CopyContextLocalsToScopeObject(scope_info, context, closure_scope);
 
   // Finally copy any properties from the function context extension. This will
   // be variables introduced by eval.
-  if (context->has_extension()) {
-    bool success = CopyContextExtensionToScopeObject(
-        handle(context->extension_object(), isolate_), closure_scope, OWN_ONLY);
-    DCHECK(success);
-    USE(success);
-  }
+  CopyContextExtensionToScopeObject(context, closure_scope,
+                                    KeyCollectionMode::kOwnOnly);
 
   return closure_scope;
 }
@@ -540,7 +536,7 @@
   Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX),
                                isolate_);
   Handle<JSObject> catch_scope =
-      isolate_->factory()->NewJSObject(isolate_->object_function());
+      isolate_->factory()->NewJSObjectWithNullProto();
   JSObject::SetOwnPropertyIgnoreAttributes(catch_scope, name, thrown_object,
                                            NONE)
       .Check();
@@ -560,14 +556,14 @@
 
 // Create a plain JSObject which materializes the block scope for the specified
 // block context.
-Handle<JSObject> ScopeIterator::MaterializeBlockScope() {
-  Handle<JSObject> block_scope =
-      isolate_->factory()->NewJSObject(isolate_->object_function());
+Handle<JSObject> ScopeIterator::MaterializeInnerScope() {
+  Handle<JSObject> inner_scope =
+      isolate_->factory()->NewJSObjectWithNullProto();
 
   Handle<Context> context = Handle<Context>::null();
   if (!nested_scope_chain_.is_empty()) {
     Handle<ScopeInfo> scope_info = nested_scope_chain_.last().scope_info;
-    frame_inspector_->MaterializeStackLocals(block_scope, scope_info);
+    frame_inspector_->MaterializeStackLocals(inner_scope, scope_info);
     if (scope_info->HasContext()) context = CurrentContext();
   } else {
     context = CurrentContext();
@@ -575,17 +571,11 @@
 
   if (!context.is_null()) {
     // Fill all context locals.
-    CopyContextLocalsToScopeObject(handle(context->scope_info()),
-                                   context, block_scope);
-    // Fill all extension variables.
-    if (context->extension_object() != nullptr) {
-      bool success = CopyContextExtensionToScopeObject(
-          handle(context->extension_object()), block_scope, OWN_ONLY);
-      DCHECK(success);
-      USE(success);
-    }
+    CopyContextLocalsToScopeObject(CurrentScopeInfo(), context, inner_scope);
+    CopyContextExtensionToScopeObject(context, inner_scope,
+                                      KeyCollectionMode::kOwnOnly);
   }
-  return block_scope;
+  return inner_scope;
 }
 
 
@@ -599,7 +589,7 @@
   // Allocate and initialize a JSObject with all the members of the debugged
   // module.
   Handle<JSObject> module_scope =
-      isolate_->factory()->NewJSObject(isolate_->object_function());
+      isolate_->factory()->NewJSObjectWithNullProto();
 
   // Fill all context locals.
   CopyContextLocalsToScopeObject(scope_info, context, module_scope);
@@ -607,12 +597,43 @@
   return module_scope;
 }
 
+bool ScopeIterator::SetParameterValue(Handle<ScopeInfo> scope_info,
+                                      JavaScriptFrame* frame,
+                                      Handle<String> parameter_name,
+                                      Handle<Object> new_value) {
+  // Setting stack locals of optimized frames is not supported.
+  if (frame->is_optimized()) return false;
+  HandleScope scope(isolate_);
+  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
+    if (String::Equals(handle(scope_info->ParameterName(i)), parameter_name)) {
+      frame->SetParameterValue(i, *new_value);
+      return true;
+    }
+  }
+  return false;
+}
 
-// Set the context local variable value.
-bool ScopeIterator::SetContextLocalValue(Handle<ScopeInfo> scope_info,
-                                         Handle<Context> context,
-                                         Handle<String> variable_name,
-                                         Handle<Object> new_value) {
+bool ScopeIterator::SetStackVariableValue(Handle<ScopeInfo> scope_info,
+                                          JavaScriptFrame* frame,
+                                          Handle<String> variable_name,
+                                          Handle<Object> new_value) {
+  // Setting stack locals of optimized frames is not supported.
+  if (frame->is_optimized()) return false;
+  HandleScope scope(isolate_);
+  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
+    if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) {
+      frame->SetExpression(scope_info->StackLocalIndex(i), *new_value);
+      return true;
+    }
+  }
+  return false;
+}
+
+bool ScopeIterator::SetContextVariableValue(Handle<ScopeInfo> scope_info,
+                                            Handle<Context> context,
+                                            Handle<String> variable_name,
+                                            Handle<Object> new_value) {
+  HandleScope scope(isolate_);
   for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
     Handle<String> next_name(scope_info->ContextLocalName(i));
     if (String::Equals(variable_name, next_name)) {
@@ -626,128 +647,8 @@
     }
   }
 
-  return false;
-}
-
-
-bool ScopeIterator::SetLocalVariableValue(Handle<String> variable_name,
-                                          Handle<Object> new_value) {
-  JavaScriptFrame* frame = GetFrame();
-  // Optimized frames are not supported.
-  if (frame->is_optimized()) return false;
-
-  Handle<JSFunction> function(frame->function());
-  Handle<SharedFunctionInfo> shared(function->shared());
-  Handle<ScopeInfo> scope_info(shared->scope_info());
-
-  bool default_result = false;
-
-  // Parameters.
-  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
-    HandleScope scope(isolate_);
-    if (String::Equals(handle(scope_info->ParameterName(i)), variable_name)) {
-      frame->SetParameterValue(i, *new_value);
-      // Argument might be shadowed in heap context, don't stop here.
-      default_result = true;
-    }
-  }
-
-  // Stack locals.
-  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
-    HandleScope scope(isolate_);
-    if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) {
-      frame->SetExpression(scope_info->StackLocalIndex(i), *new_value);
-      return true;
-    }
-  }
-
-  if (scope_info->HasContext()) {
-    // Context locals.
-    Handle<Context> frame_context(Context::cast(frame->context()));
-    Handle<Context> function_context(frame_context->declaration_context());
-    if (SetContextLocalValue(scope_info, function_context, variable_name,
-                             new_value)) {
-      return true;
-    }
-
-    // Function context extension. These are variables introduced by eval.
-    if (function_context->closure() == *function) {
-      if (function_context->has_extension() &&
-          !function_context->IsNativeContext()) {
-        Handle<JSObject> ext(function_context->extension_object());
-
-        Maybe<bool> maybe = JSReceiver::HasProperty(ext, variable_name);
-        DCHECK(maybe.IsJust());
-        if (maybe.FromJust()) {
-          // We don't expect this to do anything except replacing
-          // property value.
-          Runtime::SetObjectProperty(isolate_, ext, variable_name, new_value,
-                                     SLOPPY)
-              .Assert();
-          return true;
-        }
-      }
-    }
-  }
-
-  return default_result;
-}
-
-
-bool ScopeIterator::SetBlockVariableValue(Handle<String> variable_name,
-                                          Handle<Object> new_value) {
-  Handle<ScopeInfo> scope_info = CurrentScopeInfo();
-  JavaScriptFrame* frame = GetFrame();
-
-  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
-    HandleScope scope(isolate_);
-    if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) {
-      frame->SetExpression(scope_info->StackLocalIndex(i), *new_value);
-      return true;
-    }
-  }
-
-  if (HasContext()) {
-    Handle<Context> context = CurrentContext();
-    if (SetContextLocalValue(scope_info, context, variable_name, new_value)) {
-      return true;
-    }
-
-    Handle<JSObject> ext(context->extension_object(), isolate_);
-    if (!ext.is_null()) {
-      Maybe<bool> maybe = JSReceiver::HasOwnProperty(ext, variable_name);
-      DCHECK(maybe.IsJust());
-      if (maybe.FromJust()) {
-        // We don't expect this to do anything except replacing property value.
-        JSObject::SetOwnPropertyIgnoreAttributes(ext, variable_name, new_value,
-                                                 NONE)
-            .Check();
-        return true;
-      }
-    }
-  }
-
-  return false;
-}
-
-
-// This method copies structure of MaterializeClosure method above.
-bool ScopeIterator::SetClosureVariableValue(Handle<String> variable_name,
-                                            Handle<Object> new_value) {
-  Handle<Context> context = CurrentContext();
-  DCHECK(context->IsFunctionContext());
-
-  // Context locals to the context extension.
-  Handle<SharedFunctionInfo> shared(context->closure()->shared());
-  Handle<ScopeInfo> scope_info(shared->scope_info());
-  if (SetContextLocalValue(scope_info, context, variable_name, new_value)) {
-    return true;
-  }
-
-  // Properties from the function context extension. This will
-  // be variables introduced by eval.
   if (context->has_extension()) {
-    Handle<JSObject> ext(JSObject::cast(context->extension_object()));
+    Handle<JSObject> ext(context->extension_object());
     Maybe<bool> maybe = JSReceiver::HasOwnProperty(ext, variable_name);
     DCHECK(maybe.IsJust());
     if (maybe.FromJust()) {
@@ -762,6 +663,55 @@
   return false;
 }
 
+bool ScopeIterator::SetLocalVariableValue(Handle<String> variable_name,
+                                          Handle<Object> new_value) {
+  JavaScriptFrame* frame = GetFrame();
+  Handle<ScopeInfo> scope_info(frame->function()->shared()->scope_info());
+
+  // Parameter might be shadowed in context. Don't stop here.
+  bool result = SetParameterValue(scope_info, frame, variable_name, new_value);
+
+  // Stack locals.
+  if (SetStackVariableValue(scope_info, frame, variable_name, new_value)) {
+    return true;
+  }
+
+  if (scope_info->HasContext() &&
+      SetContextVariableValue(scope_info, CurrentContext(), variable_name,
+                              new_value)) {
+    return true;
+  }
+
+  return result;
+}
+
+bool ScopeIterator::SetInnerScopeVariableValue(Handle<String> variable_name,
+                                               Handle<Object> new_value) {
+  Handle<ScopeInfo> scope_info = CurrentScopeInfo();
+  DCHECK(scope_info->scope_type() == BLOCK_SCOPE ||
+         scope_info->scope_type() == EVAL_SCOPE);
+  JavaScriptFrame* frame = GetFrame();
+
+  // Setting stack locals of optimized frames is not supported.
+  if (SetStackVariableValue(scope_info, frame, variable_name, new_value)) {
+    return true;
+  }
+
+  if (HasContext() && SetContextVariableValue(scope_info, CurrentContext(),
+                                              variable_name, new_value)) {
+    return true;
+  }
+
+  return false;
+}
+
+// This method copies structure of MaterializeClosure method above.
+bool ScopeIterator::SetClosureVariableValue(Handle<String> variable_name,
+                                            Handle<Object> new_value) {
+  DCHECK(CurrentContext()->IsFunctionContext());
+  return SetContextVariableValue(CurrentScopeInfo(), CurrentContext(),
+                                 variable_name, new_value);
+}
 
 bool ScopeIterator::SetScriptVariableValue(Handle<String> variable_name,
                                            Handle<Object> new_value) {
@@ -780,7 +730,6 @@
   return false;
 }
 
-
 bool ScopeIterator::SetCatchVariableValue(Handle<String> variable_name,
                                           Handle<Object> new_value) {
   Handle<Context> context = CurrentContext();
@@ -801,48 +750,53 @@
   int local_count = scope_info->ContextLocalCount();
   if (local_count == 0) return;
   // Fill all context locals to the context extension.
-  int first_context_var = scope_info->StackLocalCount();
-  int start = scope_info->ContextLocalNameEntriesIndex();
   for (int i = 0; i < local_count; ++i) {
-    if (scope_info->LocalIsSynthetic(first_context_var + i)) continue;
+    Handle<String> name(scope_info->ContextLocalName(i));
+    if (ScopeInfo::VariableIsSynthetic(*name)) continue;
     int context_index = Context::MIN_CONTEXT_SLOTS + i;
     Handle<Object> value = Handle<Object>(context->get(context_index), isolate);
     // Reflect variables under TDZ as undefined in scope object.
-    if (value->IsTheHole()) continue;
+    if (value->IsTheHole(isolate)) continue;
     // This should always succeed.
     // TODO(verwaest): Use AddDataProperty instead.
-    JSObject::SetOwnPropertyIgnoreAttributes(
-        scope_object, handle(String::cast(scope_info->get(i + start))), value,
-        NONE)
+    JSObject::SetOwnPropertyIgnoreAttributes(scope_object, name, value, NONE)
         .Check();
   }
 }
 
-bool ScopeIterator::CopyContextExtensionToScopeObject(
-    Handle<JSObject> extension, Handle<JSObject> scope_object,
-    KeyCollectionType type) {
-  Handle<FixedArray> keys;
-  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-      isolate_, keys, JSReceiver::GetKeys(extension, type, ENUMERABLE_STRINGS),
-      false);
+void ScopeIterator::CopyContextExtensionToScopeObject(
+    Handle<Context> context, Handle<JSObject> scope_object,
+    KeyCollectionMode mode) {
+  if (context->extension_object() == nullptr) return;
+  Handle<JSObject> extension(context->extension_object());
+  Handle<FixedArray> keys =
+      KeyAccumulator::GetKeys(extension, mode, ENUMERABLE_STRINGS)
+          .ToHandleChecked();
 
   for (int i = 0; i < keys->length(); i++) {
     // Names of variables introduced by eval are strings.
     DCHECK(keys->get(i)->IsString());
     Handle<String> key(String::cast(keys->get(i)));
-    Handle<Object> value;
-    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-        isolate_, value, Object::GetPropertyOrElement(extension, key), false);
-    RETURN_ON_EXCEPTION_VALUE(
-        isolate_, JSObject::SetOwnPropertyIgnoreAttributes(
-            scope_object, key, value, NONE), false);
+    Handle<Object> value =
+        Object::GetPropertyOrElement(extension, key).ToHandleChecked();
+    JSObject::SetOwnPropertyIgnoreAttributes(scope_object, key, value, NONE)
+        .Check();
   }
-  return true;
 }
 
 void ScopeIterator::GetNestedScopeChain(Isolate* isolate, Scope* scope,
                                         int position) {
-  if (!scope->is_eval_scope()) {
+  if (scope->is_function_scope()) {
+    // Do not collect scopes of nested inner functions inside the current one.
+    Handle<JSFunction> function =
+        Handle<JSFunction>::cast(frame_inspector_->GetFunction());
+    if (scope->end_position() < function->shared()->end_position()) return;
+  }
+  if (scope->is_hidden()) {
+    // We need to add this chain element in case the scope has a context
+    // associated. We need to keep the scope chain and context chain in sync.
+    nested_scope_chain_.Add(ExtendedScopeInfo(scope->GetScopeInfo(isolate)));
+  } else {
     nested_scope_chain_.Add(ExtendedScopeInfo(scope->GetScopeInfo(isolate),
                                               scope->start_position(),
                                               scope->end_position()));
@@ -851,7 +805,7 @@
     Scope* inner_scope = scope->inner_scopes()->at(i);
     int beg_pos = inner_scope->start_position();
     int end_pos = inner_scope->end_position();
-    DCHECK(beg_pos >= 0 && end_pos >= 0);
+    DCHECK((beg_pos >= 0 && end_pos >= 0) || inner_scope->is_hidden());
     if (beg_pos <= position && position < end_pos) {
       GetNestedScopeChain(isolate, inner_scope, position);
       return;
diff --git a/src/debug/debug-scopes.h b/src/debug/debug-scopes.h
index 4e95fc4..1338e7b 100644
--- a/src/debug/debug-scopes.h
+++ b/src/debug/debug-scopes.h
@@ -25,6 +25,7 @@
     ScopeTypeCatch,
     ScopeTypeBlock,
     ScopeTypeScript,
+    ScopeTypeEval,
     ScopeTypeModule
   };
 
@@ -85,9 +86,12 @@
   struct ExtendedScopeInfo {
     ExtendedScopeInfo(Handle<ScopeInfo> info, int start, int end)
         : scope_info(info), start_position(start), end_position(end) {}
+    explicit ExtendedScopeInfo(Handle<ScopeInfo> info)
+        : scope_info(info), start_position(-1), end_position(-1) {}
     Handle<ScopeInfo> scope_info;
     int start_position;
     int end_position;
+    bool is_hidden() { return start_position == -1 && end_position == -1; }
   };
 
   Isolate* isolate_;
@@ -117,30 +121,39 @@
   MUST_USE_RESULT MaybeHandle<JSObject> MaterializeModuleScope();
   Handle<JSObject> MaterializeClosure();
   Handle<JSObject> MaterializeCatchScope();
-  Handle<JSObject> MaterializeBlockScope();
+  Handle<JSObject> MaterializeInnerScope();
   Handle<JSObject> WithContextExtension();
 
   bool SetLocalVariableValue(Handle<String> variable_name,
                              Handle<Object> new_value);
-  bool SetBlockVariableValue(Handle<String> variable_name,
-                             Handle<Object> new_value);
+  bool SetInnerScopeVariableValue(Handle<String> variable_name,
+                                  Handle<Object> new_value);
   bool SetClosureVariableValue(Handle<String> variable_name,
                                Handle<Object> new_value);
   bool SetScriptVariableValue(Handle<String> variable_name,
                               Handle<Object> new_value);
   bool SetCatchVariableValue(Handle<String> variable_name,
                              Handle<Object> new_value);
-  bool SetContextLocalValue(Handle<ScopeInfo> scope_info,
-                            Handle<Context> context,
-                            Handle<String> variable_name,
-                            Handle<Object> new_value);
+
+  // Helper functions.
+  bool SetParameterValue(Handle<ScopeInfo> scope_info, JavaScriptFrame* frame,
+                         Handle<String> parameter_name,
+                         Handle<Object> new_value);
+  bool SetStackVariableValue(Handle<ScopeInfo> scope_info,
+                             JavaScriptFrame* frame,
+                             Handle<String> variable_name,
+                             Handle<Object> new_value);
+  bool SetContextVariableValue(Handle<ScopeInfo> scope_info,
+                               Handle<Context> context,
+                               Handle<String> variable_name,
+                               Handle<Object> new_value);
 
   void CopyContextLocalsToScopeObject(Handle<ScopeInfo> scope_info,
                                       Handle<Context> context,
                                       Handle<JSObject> scope_object);
-  bool CopyContextExtensionToScopeObject(Handle<JSObject> extension,
+  void CopyContextExtensionToScopeObject(Handle<Context> context,
                                          Handle<JSObject> scope_object,
-                                         KeyCollectionType type);
+                                         KeyCollectionMode mode);
 
   // Get the chain of nested scopes within this scope for the source statement
   // position. The scopes will be added to the list from the outermost scope to
diff --git a/src/debug/debug.cc b/src/debug/debug.cc
index 6e94012..c69b04b 100644
--- a/src/debug/debug.cc
+++ b/src/debug/debug.cc
@@ -260,12 +260,6 @@
   return it->GetBreakLocation();
 }
 
-FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) {
-  List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
-  frame->Summarize(&frames);
-  return frames.first();
-}
-
 int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) {
   // Code offset points to the instruction after the call. Subtract 1 to
   // exclude that instruction from the search. For bytecode, the code offset
@@ -275,7 +269,7 @@
 
 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
                                        JavaScriptFrame* frame) {
-  FrameSummary summary = GetFirstFrameSummary(frame);
+  FrameSummary summary = FrameSummary::GetFirst(frame);
   int call_offset =
       CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted());
   return FromCodeOffset(debug_info, call_offset);
@@ -483,8 +477,8 @@
   thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
   thread_local_.last_fp_ = 0;
   thread_local_.target_fp_ = 0;
-  thread_local_.step_in_enabled_ = false;
   thread_local_.return_value_ = Handle<Object>();
+  clear_suspended_generator();
   // TODO(isolates): frames_are_dropped_?
   base::NoBarrier_Store(&thread_local_.current_debug_scope_,
                         static_cast<base::AtomicWord>(0));
@@ -492,25 +486,24 @@
 
 
 char* Debug::ArchiveDebug(char* storage) {
-  char* to = storage;
-  MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
+  // Simply reset state. Don't archive anything.
   ThreadInit();
   return storage + ArchiveSpacePerThread();
 }
 
 
 char* Debug::RestoreDebug(char* storage) {
-  char* from = storage;
-  MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
+  // Simply reset state. Don't restore anything.
+  ThreadInit();
   return storage + ArchiveSpacePerThread();
 }
 
+int Debug::ArchiveSpacePerThread() { return 0; }
 
-int Debug::ArchiveSpacePerThread() {
-  return sizeof(ThreadLocal);
+void Debug::Iterate(ObjectVisitor* v) {
+  v->VisitPointer(&thread_local_.suspended_generator_);
 }
 
-
 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
   // Globalize the request debug info object and make it weak.
   GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
@@ -543,9 +536,13 @@
   // Create the debugger context.
   HandleScope scope(isolate_);
   ExtensionConfiguration no_extensions;
+  // TODO(yangguo): we rely on the fact that first context snapshot is usable
+  //                as debug context. This dependency is gone once we remove
+  //                debug context completely.
+  static const int kFirstContextSnapshotIndex = 0;
   Handle<Context> context = isolate_->bootstrapper()->CreateEnvironment(
       MaybeHandle<JSGlobalProxy>(), v8::Local<ObjectTemplate>(), &no_extensions,
-      DEBUG_CONTEXT);
+      kFirstContextSnapshotIndex, DEBUG_CONTEXT);
 
   // Fail if no context could be created.
   if (context.is_null()) return false;
@@ -594,14 +591,14 @@
     // Return if we failed to retrieve the debug info.
     return;
   }
-  Handle<DebugInfo> debug_info(shared->GetDebugInfo());
+  Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
 
   // Find the break location where execution has stopped.
   BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
 
   // Find actual break points, if any, and trigger debug break event.
   Handle<Object> break_points_hit = CheckBreakPoints(&location);
-  if (!break_points_hit->IsUndefined()) {
+  if (!break_points_hit->IsUndefined(isolate_)) {
     // Clear all current stepping setup.
     ClearStepping();
     // Notify the debug event listeners.
@@ -631,7 +628,7 @@
       step_break = location.IsTailCall();
     // Fall through.
     case StepIn: {
-      FrameSummary summary = GetFirstFrameSummary(frame);
+      FrameSummary summary = FrameSummary::GetFirst(frame);
       int offset = summary.code_offset();
       step_break = step_break || location.IsReturn() ||
                    (current_fp != last_fp) ||
@@ -672,7 +669,7 @@
   // they are in a FixedArray.
   Handle<FixedArray> break_points_hit;
   int break_points_hit_count = 0;
-  DCHECK(!break_point_objects->IsUndefined());
+  DCHECK(!break_point_objects->IsUndefined(isolate_));
   if (break_point_objects->IsFixedArray()) {
     Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
     break_points_hit = factory->NewFixedArray(array->length());
@@ -720,7 +717,7 @@
     Handle<Object> check_result =
         CheckBreakPoints(&break_locations[i], &has_break_points);
     has_break_points_at_all |= has_break_points;
-    if (has_break_points && !check_result->IsUndefined()) return false;
+    if (has_break_points && !check_result->IsUndefined(isolate_)) return false;
   }
   return has_break_points_at_all;
 }
@@ -759,7 +756,7 @@
   }
 
   // Return whether the break point is triggered.
-  return result->IsTrue();
+  return result->IsTrue(isolate_);
 }
 
 
@@ -801,7 +798,7 @@
   // Obtain shared function info for the function.
   Handle<Object> result =
       FindSharedFunctionInfoInScript(script, *source_position);
-  if (result->IsUndefined()) return false;
+  if (result->IsUndefined(isolate_)) return false;
 
   // Make sure the function has set up the debug info.
   Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
@@ -848,7 +845,7 @@
   while (node != NULL) {
     Handle<Object> result =
         DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object);
-    if (!result->IsUndefined()) {
+    if (!result->IsUndefined(isolate_)) {
       // Get information in the break point.
       Handle<BreakPointInfo> break_point_info =
           Handle<BreakPointInfo>::cast(result);
@@ -938,14 +935,22 @@
 
 
 void Debug::PrepareStepIn(Handle<JSFunction> function) {
+  CHECK(last_step_action() >= StepIn);
   if (!is_active()) return;
-  if (last_step_action() < StepIn) return;
   if (in_debug_scope()) return;
-  if (thread_local_.step_in_enabled_) {
-    FloodWithOneShot(function);
-  }
+  FloodWithOneShot(function);
 }
 
+void Debug::PrepareStepInSuspendedGenerator() {
+  CHECK(has_suspended_generator());
+  if (!is_active()) return;
+  if (in_debug_scope()) return;
+  thread_local_.last_step_action_ = StepIn;
+  Handle<JSFunction> function(
+      JSGeneratorObject::cast(thread_local_.suspended_generator_)->function());
+  FloodWithOneShot(function);
+  clear_suspended_generator();
+}
 
 void Debug::PrepareStepOnThrow() {
   if (!is_active()) return;
@@ -962,6 +967,14 @@
     it.Advance();
   }
 
+  if (last_step_action() == StepNext) {
+    while (!it.done()) {
+      Address current_fp = it.frame()->UnpaddedFP();
+      if (current_fp >= thread_local_.target_fp_) break;
+      it.Advance();
+    }
+  }
+
   // Find the closest Javascript frame we can flood with one-shots.
   while (!it.done() &&
          !it.frame()->function()->shared()->IsSubjectToDebugging()) {
@@ -992,10 +1005,7 @@
 
   feature_tracker()->Track(DebugFeatureTracker::kStepping);
 
-  // Remember this step action and count.
   thread_local_.last_step_action_ = step_action;
-  STATIC_ASSERT(StepFrame > StepIn);
-  thread_local_.step_in_enabled_ = (step_action >= StepIn);
 
   // If the function on the top frame is unresolved perform step out. This will
   // be the case when calling unknown function and having the debugger stopped
@@ -1011,7 +1021,7 @@
   }
 
   // Get the debug info (create it if it does not exist).
-  FrameSummary summary = GetFirstFrameSummary(frame);
+  FrameSummary summary = FrameSummary::GetFirst(frame);
   Handle<JSFunction> function(summary.function());
   Handle<SharedFunctionInfo> shared(function->shared());
   if (!EnsureDebugInfo(shared, function)) {
@@ -1022,7 +1032,7 @@
   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
   // Refresh frame summary if the code has been recompiled for debugging.
   if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) {
-    summary = GetFirstFrameSummary(frame);
+    summary = FrameSummary::GetFirst(frame);
   }
 
   int call_offset =
@@ -1039,6 +1049,8 @@
       debug_info->abstract_code()->SourceStatementPosition(
           summary.code_offset());
   thread_local_.last_fp_ = frame->UnpaddedFP();
+  // No longer perform the current async step.
+  clear_suspended_generator();
 
   switch (step_action) {
     case StepNone:
@@ -1055,11 +1067,7 @@
         Deoptimizer::DeoptimizeFunction(frames_it.frame()->function());
         frames_it.Advance();
       }
-      if (frames_it.done()) {
-        // Stepping out to the embedder. Disable step-in to avoid stepping into
-        // the next (unrelated) call that the embedder makes.
-        thread_local_.step_in_enabled_ = false;
-      } else {
+      if (!frames_it.done()) {
         // Fill the caller function to return to with one-shot break points.
         Handle<JSFunction> caller_function(frames_it.frame()->function());
         FloodWithOneShot(caller_function);
@@ -1090,19 +1098,18 @@
     Handle<SharedFunctionInfo> shared,
     BreakPositionAlignment position_alignment) {
   Isolate* isolate = shared->GetIsolate();
-  Heap* heap = isolate->heap();
   if (!shared->HasDebugInfo()) {
-    return Handle<Object>(heap->undefined_value(), isolate);
+    return isolate->factory()->undefined_value();
   }
   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
   if (debug_info->GetBreakPointCount() == 0) {
-    return Handle<Object>(heap->undefined_value(), isolate);
+    return isolate->factory()->undefined_value();
   }
   Handle<FixedArray> locations =
       isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
   int count = 0;
   for (int i = 0; i < debug_info->break_points()->length(); ++i) {
-    if (!debug_info->break_points()->get(i)->IsUndefined()) {
+    if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
       BreakPointInfo* break_point_info =
           BreakPointInfo::cast(debug_info->break_points()->get(i));
       int break_points = break_point_info->GetBreakPointCount();
@@ -1128,7 +1135,6 @@
   ClearOneShot();
 
   thread_local_.last_step_action_ = StepNone;
-  thread_local_.step_in_enabled_ = false;
   thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
   thread_local_.last_fp_ = 0;
   thread_local_.target_fp_ = 0;
@@ -1153,12 +1159,6 @@
 }
 
 
-void Debug::EnableStepIn() {
-  STATIC_ASSERT(StepFrame > StepIn);
-  thread_local_.step_in_enabled_ = (last_step_action() >= StepIn);
-}
-
-
 bool MatchingCodeTargets(Code* target1, Code* target2) {
   if (target1 == target2) return true;
   if (target1->kind() != target2->kind()) return false;
@@ -1311,9 +1311,7 @@
   {
     SharedFunctionInfo::Iterator iterator(isolate_);
     while (SharedFunctionInfo* shared = iterator.Next()) {
-      if (!shared->OptimizedCodeMapIsCleared()) {
-        shared->ClearOptimizedCodeMap();
-      }
+      shared->ClearCodeFromOptimizedCodeMap();
     }
   }
 
@@ -1321,6 +1319,7 @@
   isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
                                       "prepare for break points");
 
+  DCHECK(shared->is_compiled());
   bool is_interpreted = shared->HasBytecodeArray();
 
   {
@@ -1329,7 +1328,7 @@
     // smarter here and avoid the heap walk.
     HeapIterator iterator(isolate_->heap());
     HeapObject* obj;
-    bool include_generators = !is_interpreted && shared->is_generator();
+    bool find_resumables = !is_interpreted && shared->is_resumable();
 
     while ((obj = iterator.next())) {
       if (obj->IsJSFunction()) {
@@ -1340,7 +1339,9 @@
         }
         if (is_interpreted) continue;
         if (function->shared() == *shared) functions.Add(handle(function));
-      } else if (include_generators && obj->IsJSGeneratorObject()) {
+      } else if (find_resumables && obj->IsJSGeneratorObject()) {
+        // This case handles async functions as well, as they use generator
+        // objects for in-progress async function execution.
         JSGeneratorObject* generator_obj = JSGeneratorObject::cast(obj);
         if (!generator_obj->is_suspended()) continue;
         JSFunction* function = generator_obj->function();
@@ -1366,6 +1367,7 @@
 
   for (Handle<JSFunction> const function : functions) {
     function->ReplaceCode(shared->code());
+    JSFunction::EnsureLiterals(function);
   }
 
   for (Handle<JSGeneratorObject> const generator_obj : suspended_generators) {
@@ -1382,6 +1384,13 @@
   return true;
 }
 
+void Debug::RecordAsyncFunction(Handle<JSGeneratorObject> generator_object) {
+  if (last_step_action() <= StepOut) return;
+  if (!generator_object->function()->shared()->is_async()) return;
+  DCHECK(!has_suspended_generator());
+  thread_local_.suspended_generator_ = *generator_object;
+  ClearStepping();
+}
 
 class SharedFunctionInfoFinder {
  public:
@@ -1604,7 +1613,7 @@
   if (!shared->HasDebugInfo()) return false;
 
   DCHECK(!frame->is_optimized());
-  FrameSummary summary = GetFirstFrameSummary(frame);
+  FrameSummary summary = FrameSummary::GetFirst(frame);
 
   Handle<DebugInfo> debug_info(shared->GetDebugInfo());
   BreakLocation location =
@@ -1656,21 +1665,6 @@
 }
 
 
-void Debug::RecordEvalCaller(Handle<Script> script) {
-  script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
-  // For eval scripts add information on the function from which eval was
-  // called.
-  StackTraceFrameIterator it(script->GetIsolate());
-  if (!it.done()) {
-    script->set_eval_from_shared(it.frame()->function()->shared());
-    Code* code = it.frame()->LookupCode();
-    int offset = static_cast<int>(
-        it.frame()->pc() - code->instruction_start());
-    script->set_eval_from_instructions_offset(offset);
-  }
-}
-
-
 MaybeHandle<Object> Debug::MakeExecutionState() {
   // Create the execution state object.
   Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) };
@@ -1738,7 +1732,7 @@
   HandleScope scope(isolate_);
   // Check whether the promise has been marked as having triggered a message.
   Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
-  if (JSReceiver::GetDataProperty(promise, key)->IsUndefined()) {
+  if (JSReceiver::GetDataProperty(promise, key)->IsUndefined(isolate_)) {
     OnException(value, promise);
   }
 }
@@ -1765,7 +1759,7 @@
     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
         isolate_, has_reject_handler,
         PromiseHasUserDefinedRejectHandler(jspromise), /* void */);
-    uncaught = has_reject_handler->IsFalse();
+    uncaught = has_reject_handler->IsFalse(isolate_);
   }
   // Bail out if exception breaks are not active
   if (uncaught) {
@@ -1911,7 +1905,7 @@
                               exec_state,
                               event_data,
                               event_listener_data_ };
-    Handle<JSReceiver> global(isolate_->global_proxy());
+    Handle<JSReceiver> global = isolate_->global_proxy();
     Execution::TryCall(isolate_, Handle<JSFunction>::cast(event_listener_),
                        global, arraysize(argv), argv);
   }
@@ -2064,7 +2058,7 @@
                            request_args, &maybe_exception);
 
     if (maybe_result.ToHandle(&answer_value)) {
-      if (answer_value->IsUndefined()) {
+      if (answer_value->IsUndefined(isolate_)) {
         answer = isolate_->factory()->empty_string();
       } else {
         answer = Handle<String>::cast(answer_value);
@@ -2081,7 +2075,7 @@
           isolate_, is_running, cmd_processor, 1, is_running_args);
       Handle<Object> result;
       if (!maybe_result.ToHandle(&result)) break;
-      running = result->IsTrue();
+      running = result->IsTrue(isolate_);
     } else {
       Handle<Object> exception;
       if (!maybe_exception.ToHandle(&exception)) break;
@@ -2115,7 +2109,7 @@
   event_listener_data_ = Handle<Object>();
 
   // Set new entry.
-  if (!callback->IsUndefined() && !callback->IsNull()) {
+  if (!callback->IsUndefined(isolate_) && !callback->IsNull(isolate_)) {
     event_listener_ = global_handles->Create(*callback);
     if (data.is_null()) data = isolate_->factory()->undefined_value();
     event_listener_data_ = global_handles->Create(*data);
@@ -2260,7 +2254,7 @@
   JavaScriptFrameIterator iterator(isolate_);
   if (iterator.done()) return;
   JavaScriptFrame* frame = iterator.frame();
-  FrameSummary summary = GetFirstFrameSummary(frame);
+  FrameSummary summary = FrameSummary::GetFirst(frame);
   int source_position =
       summary.abstract_code()->SourcePosition(summary.code_offset());
   Handle<Object> script_obj(summary.function()->shared()->script(), isolate_);
@@ -2271,8 +2265,10 @@
     Handle<Script> script = Handle<Script>::cast(script_obj);
     Handle<String> source(String::cast(script->source()));
     Script::InitLineEnds(script);
-    int line = Script::GetLineNumber(script, source_position);
-    int column = Script::GetColumnNumber(script, source_position);
+    int line =
+        Script::GetLineNumber(script, source_position) - script->line_offset();
+    int column = Script::GetColumnNumber(script, source_position) -
+                 (line == 0 ? script->column_offset() : 0);
     Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
     int line_start =
         line == 0 ? 0 : Smi::cast(line_ends->get(line - 1))->value() + 1;
@@ -2503,6 +2499,9 @@
   return client_data_;
 }
 
+v8::Isolate* EventDetailsImpl::GetIsolate() const {
+  return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
+}
 
 CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
                                    client_data_(NULL) {
diff --git a/src/debug/debug.h b/src/debug/debug.h
index 501de63..eb2708c 100644
--- a/src/debug/debug.h
+++ b/src/debug/debug.h
@@ -9,13 +9,13 @@
 #include "src/arguments.h"
 #include "src/assembler.h"
 #include "src/base/atomicops.h"
+#include "src/base/hashmap.h"
 #include "src/base/platform/platform.h"
 #include "src/debug/liveedit.h"
 #include "src/execution.h"
 #include "src/factory.h"
 #include "src/flags.h"
 #include "src/frames.h"
-#include "src/hashmap.h"
 #include "src/interpreter/source-position-table.h"
 #include "src/runtime/runtime.h"
 #include "src/string-stream.h"
@@ -38,9 +38,10 @@
   StepNext = 1,   // Step to the next statement in the current function.
   StepIn = 2,     // Step into new functions invoked or the next statement
                   // in the current function.
-  StepFrame = 3   // Step into a new frame or return to previous frame.
-};
+  StepFrame = 3,  // Step into a new frame or return to previous frame.
 
+  LastStepAction = StepFrame
+};
 
 // Type of exception break. NOTE: These values are in macros.py as well.
 enum ExceptionBreakType {
@@ -305,6 +306,8 @@
   virtual v8::Local<v8::Context> GetEventContext() const;
   virtual v8::Local<v8::Value> GetCallbackData() const;
   virtual v8::Debug::ClientData* GetClientData() const;
+  virtual v8::Isolate* GetIsolate() const;
+
  private:
   DebugEvent event_;  // Debug event causing the break.
   Handle<JSObject> exec_state_;         // Current execution state.
@@ -456,13 +459,15 @@
   // Stepping handling.
   void PrepareStep(StepAction step_action);
   void PrepareStepIn(Handle<JSFunction> function);
+  void PrepareStepInSuspendedGenerator();
   void PrepareStepOnThrow();
   void ClearStepping();
   void ClearStepOut();
-  void EnableStepIn();
 
   bool PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared);
 
+  void RecordAsyncFunction(Handle<JSGeneratorObject> generator_object);
+
   // Returns whether the operation succeeded. Compilation can only be triggered
   // if a valid closure is passed as the second argument, otherwise the shared
   // function needs to be compiled already.
@@ -497,9 +502,7 @@
   char* RestoreDebug(char* from);
   static int ArchiveSpacePerThread();
   void FreeThreadResources() { }
-
-  // Record function from which eval was called.
-  static void RecordEvalCaller(Handle<Script> script);
+  void Iterate(ObjectVisitor* v);
 
   bool CheckExecutionState(int id) {
     return is_active() && !debug_context().is_null() && break_id() != 0 &&
@@ -543,8 +546,12 @@
     return reinterpret_cast<Address>(&after_break_target_);
   }
 
-  Address step_in_enabled_address() {
-    return reinterpret_cast<Address>(&thread_local_.step_in_enabled_);
+  Address last_step_action_address() {
+    return reinterpret_cast<Address>(&thread_local_.last_step_action_);
+  }
+
+  Address suspended_generator_address() {
+    return reinterpret_cast<Address>(&thread_local_.suspended_generator_);
   }
 
   StepAction last_step_action() { return thread_local_.last_step_action_; }
@@ -567,6 +574,14 @@
     return break_disabled_ || in_debug_event_listener_;
   }
 
+  void clear_suspended_generator() {
+    thread_local_.suspended_generator_ = Smi::FromInt(0);
+  }
+
+  bool has_suspended_generator() const {
+    return thread_local_.suspended_generator_ != Smi::FromInt(0);
+  }
+
   void OnException(Handle<Object> exception, Handle<Object> promise);
 
   // Constructors for debug event objects.
@@ -678,11 +693,6 @@
     // Frame pointer of the target frame we want to arrive at.
     Address target_fp_;
 
-    // Whether functions are flooded on entry for step-in and step-frame.
-    // If we stepped out to the embedder, disable flooding to spill stepping
-    // to the next call that the embedder makes.
-    bool step_in_enabled_;
-
     // Stores the way how LiveEdit has patched the stack. It is used when
     // debugger returns control back to user script.
     LiveEdit::FrameDropMode frame_drop_mode_;
@@ -690,6 +700,8 @@
     // Value of accumulator in interpreter frames. In non-interpreter frames
     // this value will be the hole.
     Handle<Object> return_value_;
+
+    Object* suspended_generator_;
   };
 
   // Storage location for registers when handling debug break calls
diff --git a/src/debug/debug.js b/src/debug/debug.js
index 7f06ca1..cbd4dd2 100644
--- a/src/debug/debug.js
+++ b/src/debug/debug.js
@@ -361,7 +361,7 @@
   } else {
     // We might want to account columns here as well.
     if (!(script.line_offset <= this.line_  &&
-          this.line_ < script.line_offset + script.lineCount())) {
+          this.line_ < script.line_offset + %ScriptLineCount(script))) {
       return false;
     }
     if (this.type_ == Debug.ScriptBreakPointType.ScriptName) {
@@ -383,11 +383,11 @@
   // first piece of breakable code on the line try to find the column on the
   // line which contains some source.
   if (IS_UNDEFINED(column)) {
-    var source_line = script.sourceLine(this.line());
+    var source_line = %ScriptSourceLine(script, line || script.line_offset);
 
     // Allocate array for caching the columns where the actual source starts.
     if (!script.sourceColumnStart_) {
-      script.sourceColumnStart_ = new GlobalArray(script.lineCount());
+      script.sourceColumnStart_ = new GlobalArray(%ScriptLineCount(script));
     }
 
     // Fill cache if needed and get column where the actual source starts.
@@ -536,14 +536,14 @@
 Debug.findFunctionSourceLocation = function(func, opt_line, opt_column) {
   var script = %FunctionGetScript(func);
   var script_offset = %FunctionGetScriptSourcePosition(func);
-  return script.locationFromLine(opt_line, opt_column, script_offset);
+  return %ScriptLocationFromLine(script, opt_line, opt_column, script_offset);
 };
 
 
 // Returns the character position in a script based on a line number and an
 // optional position within that line.
 Debug.findScriptSourcePosition = function(script, opt_line, opt_column) {
-  var location = script.locationFromLine(opt_line, opt_column);
+  var location = %ScriptLocationFromLine(script, opt_line, opt_column, 0);
   return location ? location.position : null;
 };
 
@@ -894,10 +894,6 @@
   return %GetFrameCount(this.break_id);
 };
 
-ExecutionState.prototype.threadCount = function() {
-  return %GetThreadCount(this.break_id);
-};
-
 ExecutionState.prototype.frame = function(opt_index) {
   // If no index supplied return the selected frame.
   if (opt_index == null) opt_index = this.selected_frame;
@@ -2089,18 +2085,34 @@
     return response.failed('No source');
   }
 
-  // Get the source slice and fill it into the response.
-  var slice = script.sourceSlice(from_line, to_line);
-  if (!slice) {
+  var raw_script = script.value();
+
+  // Sanitize arguments and remove line offset.
+  var line_offset = raw_script.line_offset;
+  var line_count = %ScriptLineCount(raw_script);
+  from_line = IS_UNDEFINED(from_line) ? 0 : from_line - line_offset;
+  to_line = IS_UNDEFINED(to_line) ? line_count : to_line - line_offset;
+
+  if (from_line < 0) from_line = 0;
+  if (to_line > line_count) to_line = line_count;
+
+  if (from_line >= line_count || to_line < 0 || from_line > to_line) {
     return response.failed('Invalid line interval');
   }
+
+  // Fill in the response.
+
   response.body = {};
-  response.body.source = slice.sourceText();
-  response.body.fromLine = slice.from_line;
-  response.body.toLine = slice.to_line;
-  response.body.fromPosition = slice.from_position;
-  response.body.toPosition = slice.to_position;
-  response.body.totalLines = script.lineCount();
+  response.body.fromLine = from_line + line_offset;
+  response.body.toLine = to_line + line_offset;
+  response.body.fromPosition = %ScriptLineStartPosition(raw_script, from_line);
+  response.body.toPosition =
+    (to_line == 0) ? 0 : %ScriptLineEndPosition(raw_script, to_line - 1);
+  response.body.totalLines = %ScriptLineCount(raw_script);
+
+  response.body.source = %_SubString(raw_script.source,
+                                     response.body.fromPosition,
+                                     response.body.toPosition);
 };
 
 
@@ -2173,28 +2185,6 @@
 };
 
 
-DebugCommandProcessor.prototype.threadsRequest_ = function(request, response) {
-  // Get the number of threads.
-  var total_threads = this.exec_state_.threadCount();
-
-  // Get information for all threads.
-  var threads = [];
-  for (var i = 0; i < total_threads; i++) {
-    var details = %GetThreadDetails(this.exec_state_.break_id, i);
-    var thread_info = { current: details[0],
-                        id: details[1]
-                      };
-    threads.push(thread_info);
-  }
-
-  // Create the response body.
-  response.body = {
-    totalThreads: total_threads,
-    threads: threads
-  };
-};
-
-
 DebugCommandProcessor.prototype.suspendRequest_ = function(request, response) {
   response.running = false;
 };
@@ -2360,7 +2350,6 @@
     "references":           proto.referencesRequest_,
     "source":               proto.sourceRequest_,
     "scripts":              proto.scriptsRequest_,
-    "threads":              proto.threadsRequest_,
     "suspend":              proto.suspendRequest_,
     "version":              proto.versionRequest_,
     "changelive":           proto.changeLiveRequest_,
diff --git a/src/debug/ia32/debug-ia32.cc b/src/debug/ia32/debug-ia32.cc
index 056407f..8e4dee7 100644
--- a/src/debug/ia32/debug-ia32.cc
+++ b/src/debug/ia32/debug-ia32.cc
@@ -38,7 +38,7 @@
 
 void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
                                        Handle<Code> code) {
-  DCHECK_EQ(Code::BUILTIN, code->kind());
+  DCHECK(code->is_debug_stub());
   static const int kSize = Assembler::kDebugBreakSlotLength;
   CodePatcher patcher(isolate, pc, kSize);
 
diff --git a/src/debug/liveedit.cc b/src/debug/liveedit.cc
index 78ed6f1..aa67537 100644
--- a/src/debug/liveedit.cc
+++ b/src/debug/liveedit.cc
@@ -13,6 +13,7 @@
 #include "src/deoptimizer.h"
 #include "src/frames-inl.h"
 #include "src/global-handles.h"
+#include "src/interpreter/source-position-table.h"
 #include "src/isolate-inl.h"
 #include "src/messages.h"
 #include "src/parsing/parser.h"
@@ -620,9 +621,9 @@
   this->SetSmiValueField(kParentIndexOffset_, parent_index);
 }
 
-
-void FunctionInfoWrapper::SetFunctionCode(Handle<Code> function_code,
+void FunctionInfoWrapper::SetFunctionCode(Handle<AbstractCode> function_code,
                                           Handle<HeapObject> code_scope_info) {
+  // CompileForLiveEdit must deliver full-codegen code.
   Handle<JSValue> code_wrapper = WrapInJSValue(function_code);
   this->SetField(kCodeOffset_, code_wrapper);
 
@@ -637,27 +638,25 @@
   this->SetField(kSharedFunctionInfoOffset_, info_holder);
 }
 
-
-Handle<Code> FunctionInfoWrapper::GetFunctionCode() {
+Handle<AbstractCode> FunctionInfoWrapper::GetFunctionCode() {
   Handle<Object> element = this->GetField(kCodeOffset_);
   Handle<JSValue> value_wrapper = Handle<JSValue>::cast(element);
   Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
-  CHECK(raw_result->IsCode());
-  return Handle<Code>::cast(raw_result);
+  CHECK(raw_result->IsAbstractCode());
+  return Handle<AbstractCode>::cast(raw_result);
 }
 
-
-MaybeHandle<TypeFeedbackVector> FunctionInfoWrapper::GetFeedbackVector() {
+MaybeHandle<TypeFeedbackMetadata> FunctionInfoWrapper::GetFeedbackMetadata() {
   Handle<Object> element = this->GetField(kSharedFunctionInfoOffset_);
   if (element->IsJSValue()) {
     Handle<JSValue> value_wrapper = Handle<JSValue>::cast(element);
     Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
     Handle<SharedFunctionInfo> shared =
         Handle<SharedFunctionInfo>::cast(raw_result);
-    return Handle<TypeFeedbackVector>(shared->feedback_vector(), isolate());
+    return Handle<TypeFeedbackMetadata>(shared->feedback_metadata(), isolate());
   } else {
     // Scripts may never have a SharedFunctionInfo created.
-    return MaybeHandle<TypeFeedbackVector>();
+    return MaybeHandle<TypeFeedbackMetadata>();
   }
 }
 
@@ -688,115 +687,6 @@
 }
 
 
-class FunctionInfoListener {
- public:
-  explicit FunctionInfoListener(Isolate* isolate) {
-    current_parent_index_ = -1;
-    len_ = 0;
-    result_ = isolate->factory()->NewJSArray(10);
-  }
-
-  void FunctionStarted(FunctionLiteral* fun) {
-    HandleScope scope(isolate());
-    FunctionInfoWrapper info = FunctionInfoWrapper::Create(isolate());
-    info.SetInitialProperties(fun->name(), fun->start_position(),
-                              fun->end_position(), fun->parameter_count(),
-                              fun->materialized_literal_count(),
-                              current_parent_index_);
-    current_parent_index_ = len_;
-    SetElementSloppy(result_, len_, info.GetJSArray());
-    len_++;
-  }
-
-  void FunctionDone() {
-    HandleScope scope(isolate());
-    FunctionInfoWrapper info = FunctionInfoWrapper::cast(
-        *JSReceiver::GetElement(isolate(), result_, current_parent_index_)
-             .ToHandleChecked());
-    current_parent_index_ = info.GetParentIndex();
-  }
-
-  // Saves only function code, because for a script function we
-  // may never create a SharedFunctionInfo object.
-  void FunctionCode(Handle<Code> function_code) {
-    FunctionInfoWrapper info = FunctionInfoWrapper::cast(
-        *JSReceiver::GetElement(isolate(), result_, current_parent_index_)
-             .ToHandleChecked());
-    info.SetFunctionCode(function_code,
-                         Handle<HeapObject>(isolate()->heap()->null_value()));
-  }
-
-  // Saves full information about a function: its code, its scope info
-  // and a SharedFunctionInfo object.
-  void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope,
-                    Zone* zone) {
-    if (!shared->IsSharedFunctionInfo()) {
-      return;
-    }
-    FunctionInfoWrapper info = FunctionInfoWrapper::cast(
-        *JSReceiver::GetElement(isolate(), result_, current_parent_index_)
-             .ToHandleChecked());
-    info.SetFunctionCode(Handle<Code>(shared->code()),
-                         Handle<HeapObject>(shared->scope_info()));
-    info.SetSharedFunctionInfo(shared);
-
-    Handle<Object> scope_info_list = SerializeFunctionScope(scope, zone);
-    info.SetFunctionScopeInfo(scope_info_list);
-  }
-
-  Handle<JSArray> GetResult() { return result_; }
-
- private:
-  Isolate* isolate() const { return result_->GetIsolate(); }
-
-  Handle<Object> SerializeFunctionScope(Scope* scope, Zone* zone) {
-    Handle<JSArray> scope_info_list = isolate()->factory()->NewJSArray(10);
-    int scope_info_length = 0;
-
-    // Saves some description of scope. It stores name and indexes of
-    // variables in the whole scope chain. Null-named slots delimit
-    // scopes of this chain.
-    Scope* current_scope = scope;
-    while (current_scope != NULL) {
-      HandleScope handle_scope(isolate());
-      ZoneList<Variable*> stack_list(current_scope->StackLocalCount(), zone);
-      ZoneList<Variable*> context_list(
-          current_scope->ContextLocalCount(), zone);
-      ZoneList<Variable*> globals_list(current_scope->ContextGlobalCount(),
-                                       zone);
-      current_scope->CollectStackAndContextLocals(&stack_list, &context_list,
-                                                  &globals_list);
-      context_list.Sort(&Variable::CompareIndex);
-
-      for (int i = 0; i < context_list.length(); i++) {
-        SetElementSloppy(scope_info_list,
-                         scope_info_length,
-                         context_list[i]->name());
-        scope_info_length++;
-        SetElementSloppy(
-            scope_info_list,
-            scope_info_length,
-            Handle<Smi>(Smi::FromInt(context_list[i]->index()), isolate()));
-        scope_info_length++;
-      }
-      SetElementSloppy(scope_info_list,
-                       scope_info_length,
-                       Handle<Object>(isolate()->heap()->null_value(),
-                                      isolate()));
-      scope_info_length++;
-
-      current_scope = current_scope->outer_scope();
-    }
-
-    return scope_info_list;
-  }
-
-  Handle<JSArray> result_;
-  int len_;
-  int current_parent_index_;
-};
-
-
 void LiveEdit::InitializeThreadLocal(Debug* debug) {
   debug->thread_local_.frame_drop_mode_ = LiveEdit::FRAMES_UNTOUCHED;
 }
@@ -832,11 +722,10 @@
                                                  Handle<String> source) {
   Isolate* isolate = script->GetIsolate();
 
-  FunctionInfoListener listener(isolate);
+  MaybeHandle<JSArray> infos;
   Handle<Object> original_source =
       Handle<Object>(script->source(), isolate);
   script->set_source(*source);
-  isolate->set_active_function_info_listener(&listener);
 
   {
     // Creating verbose TryCatch from public API is currently the only way to
@@ -845,7 +734,7 @@
     try_catch.SetVerbose(true);
 
     // A logical 'try' section.
-    Compiler::CompileForLiveEdit(script);
+    infos = Compiler::CompileForLiveEdit(script);
   }
 
   // A logical 'catch' section.
@@ -883,11 +772,10 @@
   }
 
   // A logical 'finally' section.
-  isolate->set_active_function_info_listener(NULL);
   script->set_source(*original_source);
 
   if (rethrow_exception.is_null()) {
-    return listener.GetResult();
+    return infos.ToHandleChecked();
   } else {
     return isolate->Throw<JSArray>(rethrow_exception);
   }
@@ -971,11 +859,11 @@
  public:
   static void PatchLiterals(FunctionInfoWrapper* compile_info_wrapper,
                             Handle<SharedFunctionInfo> shared_info,
-                            Isolate* isolate) {
+                            bool feedback_metadata_changed, Isolate* isolate) {
     int new_literal_count = compile_info_wrapper->GetLiteralCount();
     int old_literal_count = shared_info->num_literals();
 
-    if (old_literal_count == new_literal_count) {
+    if (old_literal_count == new_literal_count && !feedback_metadata_changed) {
       // If literal count didn't change, simply go over all functions
       // and clear literal arrays.
       ClearValuesVisitor visitor;
@@ -986,10 +874,13 @@
       // collect all functions and fix their literal arrays.
       Handle<FixedArray> function_instances =
           CollectJSFunctions(shared_info, isolate);
-      Handle<TypeFeedbackVector> vector(shared_info->feedback_vector());
+      Handle<TypeFeedbackMetadata> feedback_metadata(
+          shared_info->feedback_metadata());
 
       for (int i = 0; i < function_instances->length(); i++) {
         Handle<JSFunction> fun(JSFunction::cast(function_instances->get(i)));
+        Handle<TypeFeedbackVector> vector =
+            TypeFeedbackVector::New(isolate, feedback_metadata);
         Handle<LiteralsArray> new_literals =
             LiteralsArray::New(isolate, vector, new_literal_count, TENURED);
         fun->set_literals(*new_literals);
@@ -1037,10 +928,10 @@
   class ClearValuesVisitor {
    public:
     void visit(JSFunction* fun) {
-      FixedArray* literals = fun->literals();
-      int len = literals->length();
+      LiteralsArray* literals = fun->literals();
+      int len = literals->literals_count();
       for (int j = 0; j < len; j++) {
-        literals->set_undefined(j);
+        literals->set_literal_undefined(j);
       }
     }
   };
@@ -1115,20 +1006,40 @@
   SharedInfoWrapper shared_info_wrapper(shared_info_array);
 
   Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
+  bool feedback_metadata_changed = false;
 
-  if (shared_info->code()->kind() == Code::FUNCTION) {
-    Handle<Code> code = compile_info_wrapper.GetFunctionCode();
-    ReplaceCodeObject(Handle<Code>(shared_info->code()), code);
+  if (shared_info->is_compiled()) {
+    Handle<AbstractCode> new_code = compile_info_wrapper.GetFunctionCode();
+    if (shared_info->HasBytecodeArray()) {
+      DCHECK(new_code->IsBytecodeArray());
+      // The old code is interpreted, the new code must be interpreted as well.
+      shared_info->ClearBytecodeArray();
+      shared_info->set_bytecode_array(BytecodeArray::cast(*new_code));
+    } else {
+      Handle<Code> old_code(shared_info->code());
+      DCHECK(old_code->kind() == Code::FUNCTION);
+      DCHECK(new_code->kind() == AbstractCode::FUNCTION);
+      ReplaceCodeObject(old_code, Handle<Code>::cast(new_code));
+    }
+    if (shared_info->HasDebugInfo()) {
+      // Existing break points will be re-applied. Reset the debug info here.
+      isolate->debug()->RemoveDebugInfoAndClearFromShared(
+          handle(shared_info->GetDebugInfo()));
+    }
     Handle<Object> code_scope_info = compile_info_wrapper.GetCodeScopeInfo();
     if (code_scope_info->IsFixedArray()) {
       shared_info->set_scope_info(ScopeInfo::cast(*code_scope_info));
     }
     shared_info->DisableOptimization(kLiveEdit);
     // Update the type feedback vector, if needed.
-    MaybeHandle<TypeFeedbackVector> feedback_vector =
-        compile_info_wrapper.GetFeedbackVector();
-    if (!feedback_vector.is_null()) {
-      shared_info->set_feedback_vector(*feedback_vector.ToHandleChecked());
+    MaybeHandle<TypeFeedbackMetadata> feedback_metadata =
+        compile_info_wrapper.GetFeedbackMetadata();
+    if (!feedback_metadata.is_null()) {
+      Handle<TypeFeedbackMetadata> checked_feedback_metadata =
+          feedback_metadata.ToHandleChecked();
+      feedback_metadata_changed = checked_feedback_metadata->DiffersFrom(
+          shared_info->feedback_metadata());
+      shared_info->set_feedback_metadata(*checked_feedback_metadata);
     }
   }
 
@@ -1137,7 +1048,8 @@
   shared_info->set_start_position(start_position);
   shared_info->set_end_position(end_position);
 
-  LiteralFixer::PatchLiterals(&compile_info_wrapper, shared_info, isolate);
+  LiteralFixer::PatchLiterals(&compile_info_wrapper, shared_info,
+                              feedback_metadata_changed, isolate);
 
   DeoptimizeDependentFunctions(*shared_info);
   isolate->compilation_cache()->Remove(shared_info);
@@ -1157,7 +1069,8 @@
                                  Handle<Object> script_handle) {
   Handle<SharedFunctionInfo> shared_info =
       UnwrapSharedFunctionInfoFromJSValue(function_wrapper);
-  CHECK(script_handle->IsScript() || script_handle->IsUndefined());
+  Isolate* isolate = function_wrapper->GetIsolate();
+  CHECK(script_handle->IsScript() || script_handle->IsUndefined(isolate));
   SharedFunctionInfo::SetScript(shared_info, script_handle);
   shared_info->DisableOptimization(kLiveEdit);
 
@@ -1282,12 +1195,11 @@
   static const int kMaximalBufferSize = 512*MB;
 };
 
-
+namespace {
 // Patch positions in code (changes relocation info section) and possibly
 // returns new instance of code.
-static Handle<Code> PatchPositionsInCode(
-    Handle<Code> code,
-    Handle<JSArray> position_change_array) {
+Handle<Code> PatchPositionsInCode(Handle<Code> code,
+                                  Handle<JSArray> position_change_array) {
   Isolate* isolate = code->GetIsolate();
 
   RelocInfoBuffer buffer_writer(code->relocation_size(),
@@ -1314,20 +1226,34 @@
   }
 
   Vector<byte> buffer = buffer_writer.GetResult();
+  Handle<ByteArray> reloc_info =
+      isolate->factory()->NewByteArray(buffer.length(), TENURED);
 
-  if (buffer.length() == code->relocation_size()) {
-    // Simply patch relocation area of code.
-    MemCopy(code->relocation_start(), buffer.start(), buffer.length());
-    return code;
-  } else {
-    // Relocation info section now has different size. We cannot simply
-    // rewrite it inside code object. Instead we have to create a new
-    // code object.
-    Handle<Code> result(isolate->factory()->CopyCode(code, buffer));
-    return result;
-  }
+  DisallowHeapAllocation no_gc;
+  code->set_relocation_info(*reloc_info);
+  CopyBytes(code->relocation_start(), buffer.start(), buffer.length());
+  return code;
 }
 
+void PatchPositionsInBytecodeArray(Handle<BytecodeArray> bytecode,
+                                   Handle<JSArray> position_change_array) {
+  Isolate* isolate = bytecode->GetIsolate();
+  Zone zone(isolate->allocator());
+  interpreter::SourcePositionTableBuilder builder(isolate, &zone);
+
+  for (interpreter::SourcePositionTableIterator iterator(
+           bytecode->source_position_table());
+       !iterator.done(); iterator.Advance()) {
+    int position = iterator.source_position();
+    int new_position = TranslatePosition(position, position_change_array);
+    builder.AddPosition(iterator.bytecode_offset(), new_position,
+                        iterator.is_statement());
+  }
+
+  Handle<ByteArray> source_position_table = builder.ToSourcePositionTable();
+  bytecode->set_source_position_table(*source_position_table);
+}
+}  // namespace
 
 void LiveEdit::PatchFunctionPositions(Handle<JSArray> shared_info_array,
                                       Handle<JSArray> position_change_array) {
@@ -1358,6 +1284,9 @@
       // untouched).
       ReplaceCodeObject(Handle<Code>(info->code()), patched_code);
     }
+  } else if (info->HasBytecodeArray()) {
+    PatchPositionsInBytecodeArray(Handle<BytecodeArray>(info->bytecode_array()),
+                                  position_change_array);
   }
 }
 
@@ -1374,8 +1303,7 @@
   copy->set_type(original->type());
   copy->set_context_data(original->context_data());
   copy->set_eval_from_shared(original->eval_from_shared());
-  copy->set_eval_from_instructions_offset(
-      original->eval_from_instructions_offset());
+  copy->set_eval_from_position(original->eval_from_position());
 
   // Copy all the flags, but clear compilation state.
   copy->set_flags(original->flags());
@@ -1555,6 +1483,13 @@
     top_frame = frames[top_frame_index - 2];
     *mode = LiveEdit::CURRENTLY_SET_MODE;
     frame_has_padding = false;
+  } else if (pre_top_frame_code->kind() == Code::BYTECODE_HANDLER) {
+    // Interpreted bytecode takes up two stack frames, one for the bytecode
+    // handler and one for the interpreter entry trampoline. Therefore we shift
+    // up by one frame.
+    *mode = LiveEdit::FRAME_DROPPED_IN_DIRECT_CALL;
+    pre_top_frame = frames[top_frame_index - 2];
+    top_frame = frames[top_frame_index - 1];
   } else {
     return "Unknown structure of stack above changing function";
   }
@@ -1669,7 +1604,7 @@
       Handle<Object> new_element =
           JSReceiver::GetElement(isolate, new_shared_array_, i)
               .ToHandleChecked();
-      if (new_element->IsUndefined()) return false;
+      if (new_element->IsUndefined(isolate)) return false;
       Handle<SharedFunctionInfo> new_shared =
           UnwrapSharedFunctionInfoFromJSValue(
               Handle<JSValue>::cast(new_element));
@@ -1687,6 +1622,21 @@
     return false;
   }
 
+  void set_status(LiveEdit::FunctionPatchabilityStatus status) {
+    Isolate* isolate = old_shared_array_->GetIsolate();
+    int len = GetArrayLength(old_shared_array_);
+    for (int i = 0; i < len; ++i) {
+      Handle<Object> old_element =
+          JSReceiver::GetElement(isolate, result_, i).ToHandleChecked();
+      if (!old_element->IsSmi() ||
+          Smi::cast(*old_element)->value() ==
+              LiveEdit::FUNCTION_AVAILABLE_FOR_PATCH) {
+        SetElementSloppy(result_, i,
+                         Handle<Smi>(Smi::FromInt(status), isolate));
+      }
+    }
+  }
+
  private:
   Handle<JSArray> old_shared_array_;
   Handle<JSArray> new_shared_array_;
@@ -1740,7 +1690,7 @@
     if (frame->is_java_script()) {
       SharedFunctionInfo* shared =
           JavaScriptFrame::cast(frame)->function()->shared();
-      if (shared->is_generator()) {
+      if (shared->is_resumable()) {
         non_droppable_frame_found = true;
         non_droppable_reason = LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR;
         break;
@@ -1764,6 +1714,13 @@
           // Fail.
           return NULL;
         }
+        if (non_droppable_reason ==
+                LiveEdit::FUNCTION_BLOCKED_UNDER_GENERATOR &&
+            !target_frame_found) {
+          // Fail.
+          target.set_status(non_droppable_reason);
+          return NULL;
+        }
       }
     }
   }
@@ -1792,7 +1749,8 @@
   // Adjust break_frame after some frames has been dropped.
   StackFrame::Id new_id = StackFrame::NO_ID;
   for (int i = bottom_js_frame_index + 1; i < frames.length(); i++) {
-    if (frames[i]->type() == StackFrame::JAVA_SCRIPT) {
+    if (frames[i]->type() == StackFrame::JAVA_SCRIPT ||
+        frames[i]->type() == StackFrame::INTERPRETED) {
       new_id = frames[i]->id();
       break;
     }
@@ -2004,40 +1962,107 @@
   return NULL;
 }
 
+Handle<JSArray> LiveEditFunctionTracker::Collect(FunctionLiteral* node,
+                                                 Handle<Script> script,
+                                                 Zone* zone, Isolate* isolate) {
+  LiveEditFunctionTracker visitor(script, zone, isolate);
+  visitor.VisitFunctionLiteral(node);
+  return visitor.result_;
+}
 
-LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate,
-                                                 FunctionLiteral* fun)
-    : isolate_(isolate) {
-  if (isolate_->active_function_info_listener() != NULL) {
-    isolate_->active_function_info_listener()->FunctionStarted(fun);
+LiveEditFunctionTracker::LiveEditFunctionTracker(Handle<Script> script,
+                                                 Zone* zone, Isolate* isolate)
+    : AstTraversalVisitor(isolate) {
+  current_parent_index_ = -1;
+  isolate_ = isolate;
+  len_ = 0;
+  result_ = isolate->factory()->NewJSArray(10);
+  script_ = script;
+  zone_ = zone;
+}
+
+void LiveEditFunctionTracker::VisitFunctionLiteral(FunctionLiteral* node) {
+  Scope* scope = node->scope();
+
+  // FunctionStarted is called in pre-order.
+  FunctionStarted(node);
+
+  VisitDeclarations(scope->declarations());
+  VisitStatements(node->body());
+
+  // FunctionDone are called in post-order.
+  // TODO(jgruber): If required, replace the (linear cost)
+  // FindSharedFunctionInfo call with a more efficient implementation.
+  Handle<SharedFunctionInfo> info =
+      script_->FindSharedFunctionInfo(node).ToHandleChecked();
+  FunctionDone(info, scope);
+}
+
+void LiveEditFunctionTracker::FunctionStarted(FunctionLiteral* fun) {
+  HandleScope handle_scope(isolate_);
+  FunctionInfoWrapper info = FunctionInfoWrapper::Create(isolate_);
+  info.SetInitialProperties(fun->name(), fun->start_position(),
+                            fun->end_position(), fun->parameter_count(),
+                            fun->materialized_literal_count(),
+                            current_parent_index_);
+  current_parent_index_ = len_;
+  SetElementSloppy(result_, len_, info.GetJSArray());
+  len_++;
+}
+
+// Saves full information about a function: its code, its scope info
+// and a SharedFunctionInfo object.
+void LiveEditFunctionTracker::FunctionDone(Handle<SharedFunctionInfo> shared,
+                                           Scope* scope) {
+  HandleScope handle_scope(isolate_);
+  FunctionInfoWrapper info = FunctionInfoWrapper::cast(
+      *JSReceiver::GetElement(isolate_, result_, current_parent_index_)
+           .ToHandleChecked());
+  info.SetFunctionCode(Handle<AbstractCode>(shared->abstract_code()),
+                       Handle<HeapObject>(shared->scope_info()));
+  info.SetSharedFunctionInfo(shared);
+
+  Handle<Object> scope_info_list = SerializeFunctionScope(scope);
+  info.SetFunctionScopeInfo(scope_info_list);
+
+  current_parent_index_ = info.GetParentIndex();
+}
+
+Handle<Object> LiveEditFunctionTracker::SerializeFunctionScope(Scope* scope) {
+  Handle<JSArray> scope_info_list = isolate_->factory()->NewJSArray(10);
+  int scope_info_length = 0;
+
+  // Saves some description of scope. It stores name and indexes of
+  // variables in the whole scope chain. Null-named slots delimit
+  // scopes of this chain.
+  Scope* current_scope = scope;
+  while (current_scope != NULL) {
+    HandleScope handle_scope(isolate_);
+    ZoneList<Variable*> stack_list(current_scope->StackLocalCount(), zone_);
+    ZoneList<Variable*> context_list(current_scope->ContextLocalCount(), zone_);
+    ZoneList<Variable*> globals_list(current_scope->ContextGlobalCount(),
+                                     zone_);
+    current_scope->CollectStackAndContextLocals(&stack_list, &context_list,
+                                                &globals_list);
+    context_list.Sort(&Variable::CompareIndex);
+
+    for (int i = 0; i < context_list.length(); i++) {
+      SetElementSloppy(scope_info_list, scope_info_length,
+                       context_list[i]->name());
+      scope_info_length++;
+      SetElementSloppy(
+          scope_info_list, scope_info_length,
+          Handle<Smi>(Smi::FromInt(context_list[i]->index()), isolate_));
+      scope_info_length++;
+    }
+    SetElementSloppy(scope_info_list, scope_info_length,
+                     Handle<Object>(isolate_->heap()->null_value(), isolate_));
+    scope_info_length++;
+
+    current_scope = current_scope->outer_scope();
   }
-}
 
-
-LiveEditFunctionTracker::~LiveEditFunctionTracker() {
-  if (isolate_->active_function_info_listener() != NULL) {
-    isolate_->active_function_info_listener()->FunctionDone();
-  }
-}
-
-
-void LiveEditFunctionTracker::RecordFunctionInfo(
-    Handle<SharedFunctionInfo> info, FunctionLiteral* lit,
-    Zone* zone) {
-  if (isolate_->active_function_info_listener() != NULL) {
-    isolate_->active_function_info_listener()->FunctionInfo(info, lit->scope(),
-                                                            zone);
-  }
-}
-
-
-void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) {
-  isolate_->active_function_info_listener()->FunctionCode(code);
-}
-
-
-bool LiveEditFunctionTracker::IsActive(Isolate* isolate) {
-  return isolate->active_function_info_listener() != NULL;
+  return scope_info_list;
 }
 
 }  // namespace internal
diff --git a/src/debug/liveedit.h b/src/debug/liveedit.h
index 67be70e..32328d9 100644
--- a/src/debug/liveedit.h
+++ b/src/debug/liveedit.h
@@ -32,26 +32,39 @@
 namespace internal {
 
 // This class collects some specific information on structure of functions
-// in a particular script. It gets called from compiler all the time, but
-// actually records any data only when liveedit operation is in process;
-// in any other time this class is very cheap.
+// in a particular script.
 //
 // The primary interest of the Tracker is to record function scope structures
-// in order to analyze whether function code maybe safely patched (with new
+// in order to analyze whether function code may be safely patched (with new
 // code successfully reading existing data from function scopes). The Tracker
 // also collects compiled function codes.
-class LiveEditFunctionTracker {
+class LiveEditFunctionTracker : public AstTraversalVisitor {
  public:
-  explicit LiveEditFunctionTracker(Isolate* isolate, FunctionLiteral* fun);
-  ~LiveEditFunctionTracker();
-  void RecordFunctionInfo(Handle<SharedFunctionInfo> info,
-                          FunctionLiteral* lit, Zone* zone);
-  void RecordRootFunctionInfo(Handle<Code> code);
+  // Traverses the entire AST, and records information about all
+  // FunctionLiterals for further use by LiveEdit code patching. The collected
+  // information is returned as a serialized array.
+  static Handle<JSArray> Collect(FunctionLiteral* node, Handle<Script> script,
+                                 Zone* zone, Isolate* isolate);
 
-  static bool IsActive(Isolate* isolate);
+  virtual ~LiveEditFunctionTracker() {}
+  void VisitFunctionLiteral(FunctionLiteral* node) override;
 
  private:
+  LiveEditFunctionTracker(Handle<Script> script, Zone* zone, Isolate* isolate);
+
+  void FunctionStarted(FunctionLiteral* fun);
+  void FunctionDone(Handle<SharedFunctionInfo> shared, Scope* scope);
+  Handle<Object> SerializeFunctionScope(Scope* scope);
+
+  Handle<Script> script_;
+  Zone* zone_;
   Isolate* isolate_;
+
+  Handle<JSArray> result_;
+  int len_;
+  int current_parent_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(LiveEditFunctionTracker);
 };
 
 
@@ -279,7 +292,7 @@
                             int end_position, int param_num, int literal_count,
                             int parent_index);
 
-  void SetFunctionCode(Handle<Code> function_code,
+  void SetFunctionCode(Handle<AbstractCode> function_code,
                        Handle<HeapObject> code_scope_info);
 
   void SetFunctionScopeInfo(Handle<Object> scope_info_array) {
@@ -296,9 +309,9 @@
     return this->GetSmiValueField(kParentIndexOffset_);
   }
 
-  Handle<Code> GetFunctionCode();
+  Handle<AbstractCode> GetFunctionCode();
 
-  MaybeHandle<TypeFeedbackVector> GetFeedbackVector();
+  MaybeHandle<TypeFeedbackMetadata> GetFeedbackMetadata();
 
   Handle<Object> GetCodeScopeInfo();
 
diff --git a/src/debug/mips/debug-mips.cc b/src/debug/mips/debug-mips.cc
index 8e00d61..49320d8 100644
--- a/src/debug/mips/debug-mips.cc
+++ b/src/debug/mips/debug-mips.cc
@@ -41,7 +41,7 @@
 
 void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
                                        Handle<Code> code) {
-  DCHECK_EQ(Code::BUILTIN, code->kind());
+  DCHECK(code->is_debug_stub());
   CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotInstructions);
   // Patch the code changing the debug break slot code from:
   //   nop(DEBUG_BREAK_NOP) - nop(1) is sll(zero_reg, zero_reg, 1)
diff --git a/src/debug/mips64/debug-mips64.cc b/src/debug/mips64/debug-mips64.cc
index aad095b..2e967d7 100644
--- a/src/debug/mips64/debug-mips64.cc
+++ b/src/debug/mips64/debug-mips64.cc
@@ -40,7 +40,7 @@
 
 void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
                                        Handle<Code> code) {
-  DCHECK_EQ(Code::BUILTIN, code->kind());
+  DCHECK(code->is_debug_stub());
   CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotInstructions);
   // Patch the code changing the debug break slot code from:
   //   nop(DEBUG_BREAK_NOP) - nop(1) is sll(zero_reg, zero_reg, 1)
diff --git a/src/debug/mirrors.js b/src/debug/mirrors.js
index 881f303..6f839fe 100644
--- a/src/debug/mirrors.js
+++ b/src/debug/mirrors.js
@@ -16,8 +16,8 @@
 var MapEntries;
 var MapIteratorNext;
 var MathMin = global.Math.min;
-var promiseStatusSymbol = utils.ImportNow("promise_status_symbol");
-var promiseValueSymbol = utils.ImportNow("promise_value_symbol");
+var promiseStateSymbol = utils.ImportNow("promise_state_symbol");
+var promiseResultSymbol = utils.ImportNow("promise_result_symbol");
 var SetIteratorNext;
 var SetValues;
 var SymbolToString;
@@ -115,7 +115,7 @@
 
 function ObjectIsPromise(value) {
   return IS_RECEIVER(value) &&
-         !IS_UNDEFINED(%DebugGetProperty(value, promiseStatusSymbol));
+         !IS_UNDEFINED(%DebugGetProperty(value, promiseStateSymbol));
 }
 
 
@@ -256,13 +256,15 @@
 // A copy of the scope types from runtime-debug.cc.
 // NOTE: these constants should be backward-compatible, so
 // add new ones to the end of this list.
-var ScopeType = { Global: 0,
-                  Local: 1,
-                  With: 2,
+var ScopeType = { Global:  0,
+                  Local:   1,
+                  With:    2,
                   Closure: 3,
-                  Catch: 4,
-                  Block: 5,
-                  Script: 6 };
+                  Catch:   4,
+                  Block:   5,
+                  Script:  6,
+                  Eval:    7,
+                };
 
 /**
  * Base class for all mirror objects.
@@ -1272,7 +1274,7 @@
 
 
 function PromiseGetStatus_(value) {
-  var status = %DebugGetProperty(value, promiseStatusSymbol);
+  var status = %DebugGetProperty(value, promiseStateSymbol);
   if (status == 0) return "pending";
   if (status == 1) return "resolved";
   return "rejected";
@@ -1280,7 +1282,7 @@
 
 
 function PromiseGetValue_(value) {
-  return %DebugGetProperty(value, promiseValueSymbol);
+  return %DebugGetProperty(value, promiseResultSymbol);
 }
 
 
@@ -1408,8 +1410,8 @@
 
 function GeneratorGetStatus_(value) {
   var continuation = %GeneratorGetContinuation(value);
-  if (continuation < 0) return "running";
-  if (continuation == 0) return "closed";
+  if (continuation < -1) return "running";
+  if (continuation == -1) return "closed";
   return "suspended";
 }
 
@@ -1495,6 +1497,12 @@
 };
 
 
+PropertyMirror.prototype.toText = function() {
+  if (IS_SYMBOL(this.name_)) return %SymbolDescriptiveString(this.name_);
+  return this.name_;
+};
+
+
 PropertyMirror.prototype.isIndexed = function() {
   for (var i = 0; i < this.name_.length; i++) {
     if (this.name_[i] < '0' || '9' < this.name_[i]) {
@@ -1529,11 +1537,6 @@
 };
 
 
-PropertyMirror.prototype.insertionIndex = function() {
-  return %DebugPropertyIndexFromDetails(this.details_);
-};
-
-
 /**
  * Returns whether this property has a getter defined through __defineGetter__.
  * @return {booolean} True if this property has a getter
@@ -1953,7 +1956,7 @@
 FrameMirror.prototype.sourceLineText = function() {
   var location = this.sourceLocation();
   if (location) {
-    return location.sourceText();
+    return location.sourceText;
   }
 };
 
@@ -2027,10 +2030,10 @@
         if (display_receiver) {
           result += '.';
         }
-        result += property.name();
+        result += property.toText();
       } else {
         result += '[';
-        result += property.name();
+        result += property.toText();
         result += ']';
       }
       // Also known as - if the name in the function doesn't match the name
@@ -2359,7 +2362,7 @@
 
 
 ScriptMirror.prototype.lineCount = function() {
-  return this.script_.lineCount();
+  return %ScriptLineCount(this.script_);
 };
 
 
@@ -2369,11 +2372,6 @@
 };
 
 
-ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
-  return this.script_.sourceSlice(opt_from_line, opt_to_line);
-};
-
-
 ScriptMirror.prototype.context = function() {
   return this.context_;
 };
diff --git a/src/debug/ppc/OWNERS b/src/debug/ppc/OWNERS
index eb007cb..752e8e3 100644
--- a/src/debug/ppc/OWNERS
+++ b/src/debug/ppc/OWNERS
@@ -3,3 +3,4 @@
 joransiu@ca.ibm.com
 mbrandy@us.ibm.com
 michael_dawson@ca.ibm.com
+bjaideep@ca.ibm.com
diff --git a/src/debug/ppc/debug-ppc.cc b/src/debug/ppc/debug-ppc.cc
index a160bc2..7facf95 100644
--- a/src/debug/ppc/debug-ppc.cc
+++ b/src/debug/ppc/debug-ppc.cc
@@ -41,7 +41,7 @@
 
 void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
                                        Handle<Code> code) {
-  DCHECK_EQ(Code::BUILTIN, code->kind());
+  DCHECK(code->is_debug_stub());
   CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotInstructions);
   // Patch the code changing the debug break slot code from
   //
diff --git a/src/debug/s390/OWNERS b/src/debug/s390/OWNERS
index eb007cb..752e8e3 100644
--- a/src/debug/s390/OWNERS
+++ b/src/debug/s390/OWNERS
@@ -3,3 +3,4 @@
 joransiu@ca.ibm.com
 mbrandy@us.ibm.com
 michael_dawson@ca.ibm.com
+bjaideep@ca.ibm.com
diff --git a/src/debug/s390/debug-s390.cc b/src/debug/s390/debug-s390.cc
index c6764c2..9c33b95 100644
--- a/src/debug/s390/debug-s390.cc
+++ b/src/debug/s390/debug-s390.cc
@@ -45,7 +45,7 @@
 
 void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
                                        Handle<Code> code) {
-  DCHECK_EQ(Code::BUILTIN, code->kind());
+  DCHECK(code->is_debug_stub());
   CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotLength);
   // Patch the code changing the debug break slot code from
   //
diff --git a/src/debug/x64/debug-x64.cc b/src/debug/x64/debug-x64.cc
index a85ddb3..910d1ca 100644
--- a/src/debug/x64/debug-x64.cc
+++ b/src/debug/x64/debug-x64.cc
@@ -39,7 +39,7 @@
 
 void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
                                        Handle<Code> code) {
-  DCHECK_EQ(Code::BUILTIN, code->kind());
+  DCHECK(code->is_debug_stub());
   static const int kSize = Assembler::kDebugBreakSlotLength;
   CodePatcher patcher(isolate, pc, kSize);
   Label check_codesize;
diff --git a/src/debug/x87/debug-x87.cc b/src/debug/x87/debug-x87.cc
index 029a004..1cbdf45 100644
--- a/src/debug/x87/debug-x87.cc
+++ b/src/debug/x87/debug-x87.cc
@@ -38,7 +38,7 @@
 
 void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
                                        Handle<Code> code) {
-  DCHECK_EQ(Code::BUILTIN, code->kind());
+  DCHECK(code->is_debug_stub());
   static const int kSize = Assembler::kDebugBreakSlotLength;
   CodePatcher patcher(isolate, pc, kSize);
 
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index b2c5d42..4cf41a9 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -13,7 +13,6 @@
 #include "src/global-handles.h"
 #include "src/interpreter/interpreter.h"
 #include "src/macro-assembler.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/tracing/trace-event.h"
 #include "src/v8.h"
 
@@ -47,7 +46,7 @@
 
 DeoptimizerData::~DeoptimizerData() {
   for (int i = 0; i <= Deoptimizer::kLastBailoutType; ++i) {
-    allocator_->Free(deopt_entry_code_[i]);
+    allocator_->Free<MemoryAllocator::kFull>(deopt_entry_code_[i]);
     deopt_entry_code_[i] = NULL;
   }
 }
@@ -56,9 +55,10 @@
 Code* Deoptimizer::FindDeoptimizingCode(Address addr) {
   if (function_->IsHeapObject()) {
     // Search all deoptimizing code in the native context of the function.
+    Isolate* isolate = function_->GetIsolate();
     Context* native_context = function_->context()->native_context();
     Object* element = native_context->DeoptimizedCodeListHead();
-    while (!element->IsUndefined()) {
+    while (!element->IsUndefined(isolate)) {
       Code* code = Code::cast(element);
       CHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
       if (code->contains(addr)) return code;
@@ -186,7 +186,8 @@
   // no longer refer to optimized code.
   JSFunction* prev = NULL;
   Object* element = context->OptimizedFunctionsListHead();
-  while (!element->IsUndefined()) {
+  Isolate* isolate = context->GetIsolate();
+  while (!element->IsUndefined(isolate)) {
     JSFunction* function = JSFunction::cast(element);
     Object* next = function->next_function_link();
     if (function->code()->kind() != Code::OPTIMIZED_FUNCTION ||
@@ -226,9 +227,9 @@
 
   // Run through the list of all native contexts.
   Object* context = isolate->heap()->native_contexts_list();
-  while (!context->IsUndefined()) {
+  while (!context->IsUndefined(isolate)) {
     VisitAllOptimizedFunctionsForContext(Context::cast(context), visitor);
-    context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
+    context = Context::cast(context)->next_context_link();
   }
 }
 
@@ -296,7 +297,9 @@
                          !FLAG_turbo_asm_deoptimization;
       bool safe_to_deopt =
           deopt_index != Safepoint::kNoDeoptimizationIndex || turbofanned;
-      CHECK(topmost_optimized_code == NULL || safe_to_deopt || turbofanned);
+      bool builtin = code->kind() == Code::BUILTIN;
+      CHECK(topmost_optimized_code == NULL || safe_to_deopt || turbofanned ||
+            builtin);
       if (topmost_optimized_code == NULL) {
         topmost_optimized_code = code;
         safe_to_deopt_topmost_optimized_code = safe_to_deopt;
@@ -313,7 +316,7 @@
   // Walk over all optimized code objects in this native context.
   Code* prev = NULL;
   Object* element = context->OptimizedCodeListHead();
-  while (!element->IsUndefined()) {
+  while (!element->IsUndefined(isolate)) {
     Code* code = Code::cast(element);
     CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
     Object* next = code->next_code_link();
@@ -372,6 +375,8 @@
 
 
 void Deoptimizer::DeoptimizeAll(Isolate* isolate) {
+  RuntimeCallTimerScope runtimeTimer(isolate,
+                                     &RuntimeCallStats::DeoptimizeCode);
   TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
   TRACE_EVENT0("v8", "V8.DeoptimizeCode");
   if (FLAG_trace_deopt) {
@@ -381,16 +386,18 @@
   DisallowHeapAllocation no_allocation;
   // For all contexts, mark all code, then deoptimize.
   Object* context = isolate->heap()->native_contexts_list();
-  while (!context->IsUndefined()) {
+  while (!context->IsUndefined(isolate)) {
     Context* native_context = Context::cast(context);
     MarkAllCodeForContext(native_context);
     DeoptimizeMarkedCodeForContext(native_context);
-    context = native_context->get(Context::NEXT_CONTEXT_LINK);
+    context = native_context->next_context_link();
   }
 }
 
 
 void Deoptimizer::DeoptimizeMarkedCode(Isolate* isolate) {
+  RuntimeCallTimerScope runtimeTimer(isolate,
+                                     &RuntimeCallStats::DeoptimizeCode);
   TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
   TRACE_EVENT0("v8", "V8.DeoptimizeCode");
   if (FLAG_trace_deopt) {
@@ -400,17 +407,18 @@
   DisallowHeapAllocation no_allocation;
   // For all contexts, deoptimize code already marked.
   Object* context = isolate->heap()->native_contexts_list();
-  while (!context->IsUndefined()) {
+  while (!context->IsUndefined(isolate)) {
     Context* native_context = Context::cast(context);
     DeoptimizeMarkedCodeForContext(native_context);
-    context = native_context->get(Context::NEXT_CONTEXT_LINK);
+    context = native_context->next_context_link();
   }
 }
 
 
 void Deoptimizer::MarkAllCodeForContext(Context* context) {
   Object* element = context->OptimizedCodeListHead();
-  while (!element->IsUndefined()) {
+  Isolate* isolate = context->GetIsolate();
+  while (!element->IsUndefined(isolate)) {
     Code* code = Code::cast(element);
     CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
     code->set_marked_for_deoptimization(true);
@@ -420,7 +428,10 @@
 
 
 void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
-  TimerEventScope<TimerEventDeoptimizeCode> timer(function->GetIsolate());
+  Isolate* isolate = function->GetIsolate();
+  RuntimeCallTimerScope runtimeTimer(isolate,
+                                     &RuntimeCallStats::DeoptimizeCode);
+  TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
   TRACE_EVENT0("v8", "V8.DeoptimizeCode");
   Code* code = function->code();
   if (code->kind() == Code::OPTIMIZED_FUNCTION) {
@@ -556,7 +567,7 @@
 
 
 void Deoptimizer::PrintFunctionName() {
-  if (function_->IsJSFunction()) {
+  if (function_ != nullptr && function_->IsJSFunction()) {
     function_->ShortPrint(trace_scope_->file());
   } else {
     PrintF(trace_scope_->file(),
@@ -651,16 +662,16 @@
   int length = 0;
   // Count all entries in the deoptimizing code list of every context.
   Object* context = isolate->heap()->native_contexts_list();
-  while (!context->IsUndefined()) {
+  while (!context->IsUndefined(isolate)) {
     Context* native_context = Context::cast(context);
     Object* element = native_context->DeoptimizedCodeListHead();
-    while (!element->IsUndefined()) {
+    while (!element->IsUndefined(isolate)) {
       Code* code = Code::cast(element);
       DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
       length++;
       element = code->next_code_link();
     }
-    context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
+    context = Context::cast(context)->next_context_link();
   }
   return length;
 }
@@ -839,9 +850,8 @@
            " @%d => node=%d, pc=0x%08" V8PRIxPTR ", caller sp=0x%08" V8PRIxPTR
            ", state=%s, took %0.3f ms]\n",
            bailout_id_, node_id.ToInt(), output_[index]->GetPc(),
-           caller_frame_top_, FullCodeGenerator::State2String(
-                                  static_cast<FullCodeGenerator::State>(
-                                      output_[index]->GetState()->value())),
+           caller_frame_top_, BailoutStateToString(static_cast<BailoutState>(
+                                  output_[index]->GetState()->value())),
            ms);
   }
 }
@@ -981,7 +991,7 @@
   }
   // Read the context from the translations.
   Object* context = context_pos->GetRawValue();
-  if (context == isolate_->heap()->undefined_value()) {
+  if (context->IsUndefined(isolate_)) {
     // If the context was optimized away, just use the context from
     // the activation. This should only apply to Crankshaft code.
     CHECK(!compiled_code_->is_turbofanned());
@@ -1053,10 +1063,11 @@
 
   // If we are going to the catch handler, then the exception lives in
   // the accumulator.
-  FullCodeGenerator::State state =
-      goto_catch_handler ? FullCodeGenerator::TOS_REG
-                         : FullCodeGenerator::StateField::decode(pc_and_state);
-  output_frame->SetState(Smi::FromInt(state));
+  BailoutState state =
+      goto_catch_handler
+          ? BailoutState::TOS_REGISTER
+          : FullCodeGenerator::BailoutStateField::decode(pc_and_state);
+  output_frame->SetState(Smi::FromInt(static_cast<int>(state)));
 
   // Set the continuation for the topmost frame.
   if (is_topmost) {
@@ -1272,7 +1283,9 @@
   Code* dispatch_builtin =
       builtins->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
   output_frame->SetPc(reinterpret_cast<intptr_t>(dispatch_builtin->entry()));
-  output_frame->SetState(0);
+  // Restore accumulator (TOS) register.
+  output_frame->SetState(
+      Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER)));
 
   // Update constant pool.
   if (FLAG_enable_embedded_constant_pool) {
@@ -1288,14 +1301,11 @@
 
   // Set the continuation for the topmost frame.
   if (is_topmost) {
-    Code* continuation =
-        builtins->builtin(Builtins::kInterpreterNotifyDeoptimized);
+    Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
     if (bailout_type_ == LAZY) {
-      continuation =
-          builtins->builtin(Builtins::kInterpreterNotifyLazyDeoptimized);
+      continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
     } else if (bailout_type_ == SOFT) {
-      continuation =
-          builtins->builtin(Builtins::kInterpreterNotifySoftDeoptimized);
+      continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized);
     } else {
       CHECK_EQ(bailout_type_, EAGER);
     }
@@ -1509,7 +1519,7 @@
   // value of result register is preserved during continuation execution.
   // We do this here by "pushing" the result of the constructor function to the
   // top of the reconstructed stack and then using the
-  // FullCodeGenerator::TOS_REG machinery.
+  // BailoutState::TOS_REGISTER machinery.
   if (is_topmost) {
     height_in_bytes += kPointerSize;
   }
@@ -1630,7 +1640,8 @@
     DebugPrintOutputSlot(value, frame_index, output_offset,
                          "constructor result\n");
 
-    output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG));
+    output_frame->SetState(
+        Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER)));
   }
 
   CHECK_EQ(0u, output_offset);
@@ -1684,7 +1695,7 @@
   // value of result register is preserved during continuation execution.
   // We do this here by "pushing" the result of the accessor function to the
   // top of the reconstructed stack and then using the
-  // FullCodeGenerator::TOS_REG machinery.
+  // BailoutState::TOS_REGISTER machinery.
   // We don't need to restore the result in case of a setter call because we
   // have to return the stored value but not the result of the setter function.
   bool should_preserve_result = is_topmost && !is_setter_stub_frame;
@@ -1803,9 +1814,11 @@
     DebugPrintOutputSlot(value, frame_index, output_offset,
                          "accessor result\n");
 
-    output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG));
+    output_frame->SetState(
+        Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER)));
   } else {
-    output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS));
+    output_frame->SetState(
+        Smi::FromInt(static_cast<int>(BailoutState::NO_REGISTERS)));
   }
 
   CHECK_EQ(0u, output_offset);
@@ -2060,7 +2073,8 @@
     output_frame->SetConstantPool(constant_pool_value);
     output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
   }
-  output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS));
+  output_frame->SetState(
+      Smi::FromInt(static_cast<int>(BailoutState::NO_REGISTERS)));
   Code* notify_failure =
       isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles);
   output_frame->SetContinuation(
@@ -2439,6 +2453,10 @@
   buffer_->Add(reg.code(), zone());
 }
 
+void Translation::StoreFloatRegister(FloatRegister reg) {
+  buffer_->Add(FLOAT_REGISTER, zone());
+  buffer_->Add(reg.code(), zone());
+}
 
 void Translation::StoreDoubleRegister(DoubleRegister reg) {
   buffer_->Add(DOUBLE_REGISTER, zone());
@@ -2469,6 +2487,10 @@
   buffer_->Add(index, zone());
 }
 
+void Translation::StoreFloatStackSlot(int index) {
+  buffer_->Add(FLOAT_STACK_SLOT, zone());
+  buffer_->Add(index, zone());
+}
 
 void Translation::StoreDoubleStackSlot(int index) {
   buffer_->Add(DOUBLE_STACK_SLOT, zone());
@@ -2509,11 +2531,13 @@
     case INT32_REGISTER:
     case UINT32_REGISTER:
     case BOOL_REGISTER:
+    case FLOAT_REGISTER:
     case DOUBLE_REGISTER:
     case STACK_SLOT:
     case INT32_STACK_SLOT:
     case UINT32_STACK_SLOT:
     case BOOL_STACK_SLOT:
+    case FLOAT_STACK_SLOT:
     case DOUBLE_STACK_SLOT:
     case LITERAL:
     case COMPILED_STUB_FRAME:
@@ -2639,23 +2663,6 @@
   return it->GetValue();
 }
 
-int ComputeSourcePosition(Handle<SharedFunctionInfo> shared,
-                          BailoutId node_id) {
-  if (shared->HasBytecodeArray()) {
-    BytecodeArray* bytecodes = shared->bytecode_array();
-    // BailoutId points to the next bytecode in the bytecode aray. Subtract
-    // 1 to get the end of current bytecode.
-    return bytecodes->SourcePosition(node_id.ToInt() - 1);
-  } else {
-    Code* non_optimized_code = shared->code();
-    FixedArray* raw_data = non_optimized_code->deoptimization_data();
-    DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
-    unsigned pc_and_state = Deoptimizer::GetOutputInfo(data, node_id, *shared);
-    unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
-    return non_optimized_code->SourcePosition(pc_offset);
-  }
-}
-
 }  // namespace
 
 DeoptimizedFrameInfo::DeoptimizedFrameInfo(TranslatedState* state,
@@ -2685,8 +2692,8 @@
       parameter_frame != state->begin() &&
       (parameter_frame - 1)->kind() == TranslatedFrame::kConstructStub;
 
-  source_position_ =
-      ComputeSourcePosition(frame_it->shared_info(), frame_it->node_id());
+  source_position_ = Deoptimizer::ComputeSourcePosition(
+      *frame_it->shared_info(), frame_it->node_id());
 
   TranslatedFrame::iterator value_it = frame_it->begin();
   // Get the function. Note that this might materialize the function.
@@ -2750,24 +2757,48 @@
 Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code* code, Address pc) {
   SourcePosition last_position = SourcePosition::Unknown();
   Deoptimizer::DeoptReason last_reason = Deoptimizer::kNoReason;
+  int last_deopt_id = Deoptimizer::DeoptInfo::kNoDeoptId;
   int mask = RelocInfo::ModeMask(RelocInfo::DEOPT_REASON) |
+             RelocInfo::ModeMask(RelocInfo::DEOPT_ID) |
              RelocInfo::ModeMask(RelocInfo::POSITION);
   for (RelocIterator it(code, mask); !it.done(); it.next()) {
     RelocInfo* info = it.rinfo();
-    if (info->pc() >= pc) return DeoptInfo(last_position, NULL, last_reason);
+    if (info->pc() >= pc) {
+      return DeoptInfo(last_position, last_reason, last_deopt_id);
+    }
     if (info->rmode() == RelocInfo::POSITION) {
       int raw_position = static_cast<int>(info->data());
       last_position = raw_position ? SourcePosition::FromRaw(raw_position)
                                    : SourcePosition::Unknown();
+    } else if (info->rmode() == RelocInfo::DEOPT_ID) {
+      last_deopt_id = static_cast<int>(info->data());
     } else if (info->rmode() == RelocInfo::DEOPT_REASON) {
       last_reason = static_cast<Deoptimizer::DeoptReason>(info->data());
     }
   }
-  return DeoptInfo(SourcePosition::Unknown(), NULL, Deoptimizer::kNoReason);
+  return DeoptInfo(SourcePosition::Unknown(), Deoptimizer::kNoReason, -1);
 }
 
 
 // static
+int Deoptimizer::ComputeSourcePosition(SharedFunctionInfo* shared,
+                                       BailoutId node_id) {
+  if (shared->HasBytecodeArray()) {
+    BytecodeArray* bytecodes = shared->bytecode_array();
+    // BailoutId points to the next bytecode in the bytecode aray. Subtract
+    // 1 to get the end of current bytecode.
+    return bytecodes->SourcePosition(node_id.ToInt() - 1);
+  } else {
+    Code* non_optimized_code = shared->code();
+    FixedArray* raw_data = non_optimized_code->deoptimization_data();
+    DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
+    unsigned pc_and_state = Deoptimizer::GetOutputInfo(data, node_id, shared);
+    unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
+    return non_optimized_code->SourcePosition(pc_offset);
+  }
+}
+
+// static
 TranslatedValue TranslatedValue::NewArgumentsObject(TranslatedState* container,
                                                     int length,
                                                     int object_index) {
@@ -2797,6 +2828,14 @@
 
 
 // static
+TranslatedValue TranslatedValue::NewFloat(TranslatedState* container,
+                                          float value) {
+  TranslatedValue slot(container, kFloat);
+  slot.float_value_ = value;
+  return slot;
+}
+
+// static
 TranslatedValue TranslatedValue::NewDouble(TranslatedState* container,
                                            double value) {
   TranslatedValue slot(container, kDouble);
@@ -2867,6 +2906,10 @@
   return uint32_value_;
 }
 
+float TranslatedValue::float_value() const {
+  DCHECK_EQ(kFloat, kind());
+  return float_value_;
+}
 
 double TranslatedValue::double_value() const {
   DCHECK_EQ(kDouble, kind());
@@ -2945,6 +2988,7 @@
     case TranslatedValue::kInt32:
     case TranslatedValue::kUInt32:
     case TranslatedValue::kBoolBit:
+    case TranslatedValue::kFloat:
     case TranslatedValue::kDouble: {
       MaterializeSimple();
       return value_.ToHandleChecked();
@@ -2986,6 +3030,10 @@
       value_ = Handle<Object>(isolate()->factory()->NewNumber(uint32_value()));
       return;
 
+    case kFloat:
+      value_ = Handle<Object>(isolate()->factory()->NewNumber(float_value()));
+      return;
+
     case kDouble:
       value_ = Handle<Object>(isolate()->factory()->NewNumber(double_value()));
       return;
@@ -3262,11 +3310,13 @@
     case Translation::INT32_REGISTER:
     case Translation::UINT32_REGISTER:
     case Translation::BOOL_REGISTER:
+    case Translation::FLOAT_REGISTER:
     case Translation::DOUBLE_REGISTER:
     case Translation::STACK_SLOT:
     case Translation::INT32_STACK_SLOT:
     case Translation::UINT32_STACK_SLOT:
     case Translation::BOOL_STACK_SLOT:
+    case Translation::FLOAT_STACK_SLOT:
     case Translation::DOUBLE_STACK_SLOT:
     case Translation::LITERAL:
       break;
@@ -3393,13 +3443,26 @@
       return TranslatedValue::NewBool(this, static_cast<uint32_t>(value));
     }
 
+    case Translation::FLOAT_REGISTER: {
+      int input_reg = iterator->Next();
+      if (registers == nullptr) return TranslatedValue::NewInvalid(this);
+      float value = registers->GetFloatRegister(input_reg);
+      if (trace_file != nullptr) {
+        PrintF(trace_file, "%e ; %s (float)", value,
+               RegisterConfiguration::Crankshaft()->GetFloatRegisterName(
+                   input_reg));
+      }
+      return TranslatedValue::NewFloat(this, value);
+    }
+
     case Translation::DOUBLE_REGISTER: {
       int input_reg = iterator->Next();
       if (registers == nullptr) return TranslatedValue::NewInvalid(this);
       double value = registers->GetDoubleRegister(input_reg);
       if (trace_file != nullptr) {
-        PrintF(trace_file, "%e ; %s (bool)", value,
-               DoubleRegister::from_code(input_reg).ToString());
+        PrintF(trace_file, "%e ; %s (double)", value,
+               RegisterConfiguration::Crankshaft()->GetDoubleRegisterName(
+                   input_reg));
       }
       return TranslatedValue::NewDouble(this, value);
     }
@@ -3450,6 +3513,17 @@
       return TranslatedValue::NewBool(this, value);
     }
 
+    case Translation::FLOAT_STACK_SLOT: {
+      int slot_offset =
+          OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
+      float value = ReadFloatValue(fp + slot_offset);
+      if (trace_file != nullptr) {
+        PrintF(trace_file, "%e ; (float) [fp %c %d] ", value,
+               slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
+      }
+      return TranslatedValue::NewFloat(this, value);
+    }
+
     case Translation::DOUBLE_STACK_SLOT: {
       int slot_offset =
           OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
@@ -3486,6 +3560,7 @@
   int deopt_index = Safepoint::kNoDeoptimizationIndex;
   DeoptimizationInputData* data =
       static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index);
+  DCHECK(data != nullptr && deopt_index != Safepoint::kNoDeoptimizationIndex);
   TranslationIterator it(data->TranslationByteArray(),
                          data->TranslationIndex(deopt_index)->value());
   Init(frame->fp(), &it, data->LiteralArray(), nullptr /* registers */,
@@ -3596,6 +3671,7 @@
     case TranslatedValue::kInt32:
     case TranslatedValue::kUInt32:
     case TranslatedValue::kBoolBit:
+    case TranslatedValue::kFloat:
     case TranslatedValue::kDouble: {
       slot->MaterializeSimple();
       Handle<Object> value = slot->GetValue();
@@ -3664,7 +3740,9 @@
           }
           return object;
         }
-        case JS_OBJECT_TYPE: {
+        case JS_OBJECT_TYPE:
+        case JS_ERROR_TYPE:
+        case JS_ARGUMENTS_TYPE: {
           Handle<JSObject> object =
               isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED);
           slot->value_ = object;
@@ -3691,6 +3769,35 @@
           object->set_length(*length);
           return object;
         }
+        case JS_FUNCTION_TYPE: {
+          Handle<JSFunction> object =
+              isolate_->factory()->NewFunctionFromSharedFunctionInfo(
+                  handle(isolate_->object_function()->shared()),
+                  handle(isolate_->context()));
+          slot->value_ = object;
+          // We temporarily allocated a JSFunction for the {Object} function
+          // within the current context, to break cycles in the object graph.
+          // The correct function and context will be set below once available.
+          Handle<Object> properties = MaterializeAt(frame_index, value_index);
+          Handle<Object> elements = MaterializeAt(frame_index, value_index);
+          Handle<Object> prototype = MaterializeAt(frame_index, value_index);
+          Handle<Object> shared = MaterializeAt(frame_index, value_index);
+          Handle<Object> context = MaterializeAt(frame_index, value_index);
+          Handle<Object> literals = MaterializeAt(frame_index, value_index);
+          Handle<Object> entry = MaterializeAt(frame_index, value_index);
+          Handle<Object> next_link = MaterializeAt(frame_index, value_index);
+          object->ReplaceCode(*isolate_->builtins()->CompileLazy());
+          object->set_map(*map);
+          object->set_properties(FixedArray::cast(*properties));
+          object->set_elements(FixedArrayBase::cast(*elements));
+          object->set_prototype_or_initial_map(*prototype);
+          object->set_shared(SharedFunctionInfo::cast(*shared));
+          object->set_context(Context::cast(*context));
+          object->set_literals(LiteralsArray::cast(*literals));
+          CHECK(entry->IsNumber());  // Entry to compile lazy stub.
+          CHECK(next_link->IsUndefined(isolate_));
+          return object;
+        }
         case FIXED_ARRAY_TYPE: {
           Handle<Object> lengthObject = MaterializeAt(frame_index, value_index);
           int32_t length = 0;
diff --git a/src/deoptimizer.h b/src/deoptimizer.h
index 21ca84e..db20406 100644
--- a/src/deoptimizer.h
+++ b/src/deoptimizer.h
@@ -39,6 +39,7 @@
     kInt32,
     kUInt32,
     kBoolBit,
+    kFloat,
     kDouble,
     kCapturedObject,    // Object captured by the escape analysis.
                         // The number of nested objects can be obtained
@@ -61,6 +62,7 @@
   static TranslatedValue NewDeferredObject(TranslatedState* container,
                                            int length, int object_index);
   static TranslatedValue NewDuplicateObject(TranslatedState* container, int id);
+  static TranslatedValue NewFloat(TranslatedState* container, float value);
   static TranslatedValue NewDouble(TranslatedState* container, double value);
   static TranslatedValue NewInt32(TranslatedState* container, int32_t value);
   static TranslatedValue NewUInt32(TranslatedState* container, uint32_t value);
@@ -93,6 +95,8 @@
     uint32_t uint32_value_;
     // kind is kInt32.
     int32_t int32_value_;
+    // kind is kFloat
+    float float_value_;
     // kind is kDouble
     double double_value_;
     // kind is kDuplicatedObject or kArgumentsObject or kCapturedObject.
@@ -103,6 +107,7 @@
   Object* raw_literal() const;
   int32_t int32_value() const;
   uint32_t uint32_value() const;
+  float float_value() const;
   double double_value() const;
   int object_length() const;
   int object_index() const;
@@ -334,7 +339,7 @@
   V(kInstanceMigrationFailed, "instance migration failed")                     \
   V(kInsufficientTypeFeedbackForCallWithArguments,                             \
     "Insufficient type feedback for call with arguments")                      \
-  V(kFastArrayPushFailed, "Falling off the fast path for FastArrayPush")       \
+  V(kFastPathFailed, "Falling off the fast path")                              \
   V(kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation,                 \
     "Insufficient type feedback for combined type of binary operation")        \
   V(kInsufficientTypeFeedbackForGenericNamedAccess,                            \
@@ -402,6 +407,22 @@
  public:
   enum BailoutType { EAGER, LAZY, SOFT, kLastBailoutType = SOFT };
 
+  enum class BailoutState {
+    NO_REGISTERS,
+    TOS_REGISTER,
+  };
+
+  static const char* BailoutStateToString(BailoutState state) {
+    switch (state) {
+      case BailoutState::NO_REGISTERS:
+        return "NO_REGISTERS";
+      case BailoutState::TOS_REGISTER:
+        return "TOS_REGISTER";
+    }
+    UNREACHABLE();
+    return nullptr;
+  }
+
 #define DEOPT_MESSAGES_CONSTANTS(C, T) C,
   enum DeoptReason {
     DEOPT_MESSAGES_LIST(DEOPT_MESSAGES_CONSTANTS) kLastDeoptReason
@@ -410,17 +431,21 @@
   static const char* GetDeoptReason(DeoptReason deopt_reason);
 
   struct DeoptInfo {
-    DeoptInfo(SourcePosition position, const char* m, DeoptReason d)
-        : position(position), mnemonic(m), deopt_reason(d), inlining_id(0) {}
+    DeoptInfo(SourcePosition position, DeoptReason deopt_reason, int deopt_id)
+        : position(position), deopt_reason(deopt_reason), deopt_id(deopt_id) {}
 
     SourcePosition position;
-    const char* mnemonic;
     DeoptReason deopt_reason;
-    int inlining_id;
+    int deopt_id;
+
+    static const int kNoDeoptId = -1;
   };
 
   static DeoptInfo GetDeoptInfo(Code* code, byte* from);
 
+  static int ComputeSourcePosition(SharedFunctionInfo* shared,
+                                   BailoutId node_id);
+
   struct JumpTableEntry : public ZoneObject {
     inline JumpTableEntry(Address entry, const DeoptInfo& deopt_info,
                           Deoptimizer::BailoutType type, bool frame)
@@ -718,6 +743,11 @@
     return registers_[n];
   }
 
+  float GetFloatRegister(unsigned n) const {
+    DCHECK(n < arraysize(float_registers_));
+    return float_registers_[n];
+  }
+
   double GetDoubleRegister(unsigned n) const {
     DCHECK(n < arraysize(double_registers_));
     return double_registers_[n];
@@ -728,12 +758,18 @@
     registers_[n] = value;
   }
 
+  void SetFloatRegister(unsigned n, float value) {
+    DCHECK(n < arraysize(float_registers_));
+    float_registers_[n] = value;
+  }
+
   void SetDoubleRegister(unsigned n, double value) {
     DCHECK(n < arraysize(double_registers_));
     double_registers_[n] = value;
   }
 
   intptr_t registers_[Register::kNumRegisters];
+  float float_registers_[FloatRegister::kMaxNumRegisters];
   double double_registers_[DoubleRegister::kMaxNumRegisters];
 };
 
@@ -957,11 +993,13 @@
   V(INT32_REGISTER)                \
   V(UINT32_REGISTER)               \
   V(BOOL_REGISTER)                 \
+  V(FLOAT_REGISTER)                \
   V(DOUBLE_REGISTER)               \
   V(STACK_SLOT)                    \
   V(INT32_STACK_SLOT)              \
   V(UINT32_STACK_SLOT)             \
   V(BOOL_STACK_SLOT)               \
+  V(FLOAT_STACK_SLOT)              \
   V(DOUBLE_STACK_SLOT)             \
   V(LITERAL)
 
@@ -1003,11 +1041,13 @@
   void StoreInt32Register(Register reg);
   void StoreUint32Register(Register reg);
   void StoreBoolRegister(Register reg);
+  void StoreFloatRegister(FloatRegister reg);
   void StoreDoubleRegister(DoubleRegister reg);
   void StoreStackSlot(int index);
   void StoreInt32StackSlot(int index);
   void StoreUint32StackSlot(int index);
   void StoreBoolStackSlot(int index);
+  void StoreFloatStackSlot(int index);
   void StoreDoubleStackSlot(int index);
   void StoreLiteral(int literal_id);
   void StoreArgumentsObject(bool args_known, int args_index, int args_length);
diff --git a/src/disassembler.cc b/src/disassembler.cc
index ed9ca9a..8fe1e7f 100644
--- a/src/disassembler.cc
+++ b/src/disassembler.cc
@@ -9,6 +9,7 @@
 #include "src/debug/debug.h"
 #include "src/deoptimizer.h"
 #include "src/disasm.h"
+#include "src/ic/ic.h"
 #include "src/macro-assembler.h"
 #include "src/snapshot/serializer-common.h"
 #include "src/string-stream.h"
@@ -36,7 +37,7 @@
       code_ == NULL ? NULL : code_->GetIsolate()->builtins()->Lookup(pc);
 
   if (name != NULL) {
-    SNPrintF(v8_buffer_, "%s  (%p)", name, pc);
+    SNPrintF(v8_buffer_, "%s  (%p)", name, static_cast<void*>(pc));
     return v8_buffer_.start();
   }
 
@@ -44,7 +45,7 @@
     int offs = static_cast<int>(pc - code_->instruction_start());
     // print as code offset, if it seems reasonable
     if (0 <= offs && offs < code_->instruction_size()) {
-      SNPrintF(v8_buffer_, "%d  (%p)", offs, pc);
+      SNPrintF(v8_buffer_, "%d  (%p)", offs, static_cast<void*>(pc));
       return v8_buffer_.start();
     }
   }
@@ -109,10 +110,9 @@
           it->rinfo()->rmode() == RelocInfo::INTERNAL_REFERENCE) {
         // raw pointer embedded in code stream, e.g., jump table
         byte* ptr = *reinterpret_cast<byte**>(pc);
-        SNPrintF(decode_buffer,
-                 "%08" V8PRIxPTR "      jump table entry %4" V8PRIdPTR,
-                 reinterpret_cast<intptr_t>(ptr),
-                 ptr - begin);
+        SNPrintF(
+            decode_buffer, "%08" V8PRIxPTR "      jump table entry %4" PRIuS,
+            reinterpret_cast<intptr_t>(ptr), static_cast<size_t>(ptr - begin));
         pc += sizeof(ptr);
       } else {
         decode_buffer[0] = '\0';
@@ -147,7 +147,8 @@
     }
 
     // Instruction address and instruction offset.
-    out.AddFormatted("%p  %4d  ", prev_pc, prev_pc - begin);
+    out.AddFormatted("%p  %4" V8PRIdPTRDIFF "  ", static_cast<void*>(prev_pc),
+                     prev_pc - begin);
 
     // Instruction.
     out.AddFormatted("%s", decode_buffer.start());
@@ -171,15 +172,20 @@
       RelocInfo::Mode rmode = relocinfo.rmode();
       if (RelocInfo::IsPosition(rmode)) {
         if (RelocInfo::IsStatementPosition(rmode)) {
-          out.AddFormatted("    ;; debug: statement %d", relocinfo.data());
+          out.AddFormatted("    ;; debug: statement %" V8PRIdPTR,
+                           relocinfo.data());
         } else {
-          out.AddFormatted("    ;; debug: position %d", relocinfo.data());
+          out.AddFormatted("    ;; debug: position %" V8PRIdPTR,
+                           relocinfo.data());
         }
       } else if (rmode == RelocInfo::DEOPT_REASON) {
         Deoptimizer::DeoptReason reason =
             static_cast<Deoptimizer::DeoptReason>(relocinfo.data());
         out.AddFormatted("    ;; debug: deopt reason '%s'",
                          Deoptimizer::GetDeoptReason(reason));
+      } else if (rmode == RelocInfo::DEOPT_ID) {
+        out.AddFormatted("    ;; debug: deopt index %d",
+                         static_cast<int>(relocinfo.data()));
       } else if (rmode == RelocInfo::EMBEDDED_OBJECT) {
         HeapStringAllocator allocator;
         StringStream accumulator(&allocator);
@@ -195,17 +201,15 @@
         Code* code = Code::GetCodeFromTargetAddress(relocinfo.target_address());
         Code::Kind kind = code->kind();
         if (code->is_inline_cache_stub()) {
-          if (kind == Code::LOAD_IC &&
-              LoadICState::GetTypeofMode(code->extra_ic_state()) ==
-                  NOT_INSIDE_TYPEOF) {
-            out.AddFormatted(" contextual,");
+          if (kind == Code::LOAD_GLOBAL_IC &&
+              LoadGlobalICState::GetTypeofMode(code->extra_ic_state()) ==
+                  INSIDE_TYPEOF) {
+            out.AddFormatted(" inside typeof,");
           }
-          InlineCacheState ic_state = code->ic_state();
-          out.AddFormatted(" %s, %s", Code::Kind2String(kind),
-              Code::ICState2String(ic_state));
-          if (ic_state == MONOMORPHIC) {
-            Code::StubType type = code->type();
-            out.AddFormatted(", %s", Code::StubType2String(type));
+          out.AddFormatted(" %s", Code::Kind2String(kind));
+          if (!IC::ICUseVector(kind)) {
+            InlineCacheState ic_state = IC::StateFromCode(code);
+            out.AddFormatted(" %s", Code::ICState2String(ic_state));
           }
         } else if (kind == Code::STUB || kind == Code::HANDLER) {
           // Get the STUB key and extract major and minor key.
diff --git a/src/eh-frame.cc b/src/eh-frame.cc
new file mode 100644
index 0000000..af85e0b
--- /dev/null
+++ b/src/eh-frame.cc
@@ -0,0 +1,96 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/eh-frame.h"
+#include "src/objects-inl.h"
+#include "src/objects.h"
+
+namespace v8 {
+namespace internal {
+
+static const int DW_EH_PE_pcrel = 0x10;
+static const int DW_EH_PE_datarel = 0x30;
+static const int DW_EH_PE_udata4 = 0x03;
+static const int DW_EH_PE_sdata4 = 0x0b;
+
+const int EhFrameHdr::kCIESize = 0;
+
+static const int kVersionSize = 1;
+static const int kEncodingSpecifiersSize = 3;
+
+//
+// In order to calculate offsets in the .eh_frame_hdr, we must know the layout
+// of the DSO generated by perf inject, which is assumed to be the following:
+//
+//  |      ...      |                        |
+//  +---------------+ <-- (F) ---            |  Larger offsets in file
+//  |               |           ^            |
+//  |  Instructions |           | .text      v
+//  |               |           v
+//  +---------------+ <-- (E) ---
+//  |///////////////|
+//  |////Padding////|
+//  |///////////////|
+//  +---------------+ <-- (D) ---
+//  |               |           ^
+//  |      CIE      |           |
+//  |               |           |
+//  +---------------+ <-- (C)   | .eh_frame
+//  |               |           |
+//  |      FDE      |           |
+//  |               |           v
+//  +---------------+ <-- (B) ---
+//  |    version    |           ^
+//  +---------------+           |
+//  |   encoding    |           |
+//  |  specifiers   |           |
+//  +---------------+ <---(A)   | .eh_frame_hdr
+//  |   offset to   |           |
+//  |   .eh_frame   |           |
+//  +---------------+           |
+//  |      ...      |          ...
+//
+// (F) is aligned at a 16-byte boundary.
+// (D) is aligned at a  8-byte boundary.
+// (B) is aligned at a  4-byte boundary.
+// (E), (C) and (A) have no alignment requirements.
+//
+// The distance between (A) and (B) is 4 bytes.
+//
+// The size of the .eh_frame is required to be a multiple of the pointer size,
+// which means that (B) will be naturally aligned to a 4-byte boundary on all
+// the architectures we support.
+//
+// Because (E) has no alignment requirements, there is padding between (E) and
+// (D). (F) is aligned at a 16-byte boundary, thus to a 8-byte one as well.
+//
+EhFrameHdr::EhFrameHdr(Code* code) {
+  int code_size = code->is_crankshafted() ? code->safepoint_table_offset()
+                                          : code->instruction_size();
+  version_ = 1;
+  eh_frame_ptr_encoding_ = DW_EH_PE_sdata4 | DW_EH_PE_pcrel;
+  lut_size_encoding_ = DW_EH_PE_udata4;
+  lut_entries_encoding_ = DW_EH_PE_sdata4 | DW_EH_PE_datarel;
+
+  // .eh_frame pointer and LUT
+  if (code->has_unwinding_info()) {
+    DCHECK_GE(code->unwinding_info_size(), EhFrameHdr::kRecordSize);
+    int eh_frame_size = code->unwinding_info_size() - EhFrameHdr::kRecordSize;
+
+    offset_to_eh_frame_ =
+        -(eh_frame_size + kVersionSize + kEncodingSpecifiersSize);  // A -> D
+    lut_entries_number_ = 1;
+    offset_to_procedure_ = -(RoundUp(code_size, 8) + eh_frame_size);  // B -> F
+    offset_to_fde_ = -(eh_frame_size - kCIESize);                     // B -> C
+  } else {
+    // Create a dummy table
+    offset_to_eh_frame_ = 0;
+    lut_entries_number_ = 0;
+    offset_to_procedure_ = 0;
+    offset_to_fde_ = 0;
+  }
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/eh-frame.h b/src/eh-frame.h
new file mode 100644
index 0000000..75781ac
--- /dev/null
+++ b/src/eh-frame.h
@@ -0,0 +1,41 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_EH_FRAME_H_
+#define V8_EH_FRAME_H_
+
+#include <cstdint>
+
+namespace v8 {
+namespace internal {
+
+class Code;
+
+class EhFrameHdr final {
+ public:
+  static const int kRecordSize = 20;
+  static const int kCIESize;
+
+  explicit EhFrameHdr(Code* code);
+
+  int32_t offset_to_eh_frame() const { return offset_to_eh_frame_; }
+  uint32_t lut_entries_number() const { return lut_entries_number_; }
+  int32_t offset_to_procedure() const { return offset_to_procedure_; }
+  int32_t offset_to_fde() const { return offset_to_fde_; }
+
+ private:
+  uint8_t version_;
+  uint8_t eh_frame_ptr_encoding_;
+  uint8_t lut_size_encoding_;
+  uint8_t lut_entries_encoding_;
+  int32_t offset_to_eh_frame_;
+  uint32_t lut_entries_number_;
+  int32_t offset_to_procedure_;
+  int32_t offset_to_fde_;
+};
+
+}  // namespace internal
+}  // namespace v8
+
+#endif
diff --git a/src/elements.cc b/src/elements.cc
index 288c60e..d7e49cd 100644
--- a/src/elements.cc
+++ b/src/elements.cc
@@ -140,14 +140,11 @@
   if (copy_size == 0) return;
   FixedArray* from = FixedArray::cast(from_base);
   FixedArray* to = FixedArray::cast(to_base);
-  DCHECK(IsFastSmiOrObjectElementsKind(from_kind) ||
-         from_kind == FAST_STRING_WRAPPER_ELEMENTS);
+  DCHECK(IsFastSmiOrObjectElementsKind(from_kind));
   DCHECK(IsFastSmiOrObjectElementsKind(to_kind));
 
   WriteBarrierMode write_barrier_mode =
-      ((IsFastObjectElementsKind(from_kind) &&
-        IsFastObjectElementsKind(to_kind)) ||
-       from_kind == FAST_STRING_WRAPPER_ELEMENTS)
+      (IsFastObjectElementsKind(from_kind) && IsFastObjectElementsKind(to_kind))
           ? UPDATE_WRITE_BARRIER
           : SKIP_WRITE_BARRIER;
   for (int i = 0; i < copy_size; i++) {
@@ -192,7 +189,7 @@
     int entry = from->FindEntry(i + from_start);
     if (entry != SeededNumberDictionary::kNotFound) {
       Object* value = from->ValueAt(entry);
-      DCHECK(!value->IsTheHole());
+      DCHECK(!value->IsTheHole(from->GetIsolate()));
       to->set(i + to_start, value, write_barrier_mode);
     } else {
       to->set_the_hole(i + to_start);
@@ -355,7 +352,7 @@
   for (uint32_t from_end = from_start + static_cast<uint32_t>(packed_size);
        from_start < from_end; from_start++, to_start++) {
     Object* smi = from->get(from_start);
-    DCHECK(!smi->IsTheHole());
+    DCHECK(!smi->IsTheHole(from->GetIsolate()));
     to->set(to_start, Smi::cast(smi)->value());
   }
 }
@@ -448,6 +445,28 @@
   JavaScriptFrame::PrintTop(isolate, stdout, false, true);
 }
 
+static void SortIndices(
+    Handle<FixedArray> indices, uint32_t sort_size,
+    WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER) {
+  struct {
+    bool operator()(Object* a, Object* b) {
+      if (a->IsSmi() || !a->IsUndefined(HeapObject::cast(a)->GetIsolate())) {
+        if (!b->IsSmi() && b->IsUndefined(HeapObject::cast(b)->GetIsolate())) {
+          return true;
+        }
+        return a->Number() < b->Number();
+      }
+      return !b->IsSmi() && b->IsUndefined(HeapObject::cast(b)->GetIsolate());
+    }
+  } cmp;
+  Object** start =
+      reinterpret_cast<Object**>(indices->GetFirstElementAddress());
+  std::sort(start, start + sort_size, cmp);
+  if (write_barrier_mode != SKIP_WRITE_BARRIER) {
+    FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(indices->GetIsolate()->heap(), *indices,
+                                       0, sort_size);
+  }
+}
 
 // Base class for element handler implementations. Contains the
 // the common logic for objects with different ElementsKinds.
@@ -466,8 +485,7 @@
 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern).  We use
 // CRTP to guarantee aggressive compile time optimizations (i.e.  inlining and
 // specialization of SomeElementsAccessor methods).
-template <typename ElementsAccessorSubclass,
-          typename ElementsTraitsParam>
+template <typename Subclass, typename ElementsTraitsParam>
 class ElementsAccessorBase : public ElementsAccessor {
  public:
   explicit ElementsAccessorBase(const char* name)
@@ -495,12 +513,12 @@
     } else {
       length = fixed_array_base->length();
     }
-    ElementsAccessorSubclass::ValidateContents(holder, length);
+    Subclass::ValidateContents(holder, length);
   }
 
   void Validate(Handle<JSObject> holder) final {
     DisallowHeapAllocation no_gc;
-    ElementsAccessorSubclass::ValidateImpl(holder);
+    Subclass::ValidateImpl(holder);
   }
 
   static bool IsPackedImpl(Handle<JSObject> holder,
@@ -508,8 +526,7 @@
                            uint32_t end) {
     if (IsFastPackedElementsKind(kind())) return true;
     for (uint32_t i = start; i < end; i++) {
-      if (!ElementsAccessorSubclass::HasElementImpl(holder, i, backing_store,
-                                                    ALL_PROPERTIES)) {
+      if (!Subclass::HasElementImpl(holder, i, backing_store, ALL_PROPERTIES)) {
         return false;
       }
     }
@@ -520,8 +537,7 @@
     if (!IsHoleyElementsKind(kind())) return;
     int length = Smi::cast(array->length())->value();
     Handle<FixedArrayBase> backing_store(array->elements());
-    if (!ElementsAccessorSubclass::IsPackedImpl(array, backing_store, 0,
-                                                length)) {
+    if (!Subclass::IsPackedImpl(array, backing_store, 0, length)) {
       return;
     }
     ElementsKind packed_kind = GetPackedElementsKind(kind());
@@ -537,20 +553,18 @@
   bool HasElement(Handle<JSObject> holder, uint32_t index,
                   Handle<FixedArrayBase> backing_store,
                   PropertyFilter filter) final {
-    return ElementsAccessorSubclass::HasElementImpl(holder, index,
-                                                    backing_store, filter);
+    return Subclass::HasElementImpl(holder, index, backing_store, filter);
   }
 
   static bool HasElementImpl(Handle<JSObject> holder, uint32_t index,
                              Handle<FixedArrayBase> backing_store,
                              PropertyFilter filter) {
-    return ElementsAccessorSubclass::GetEntryForIndexImpl(
-               *holder, *backing_store, index, filter) != kMaxUInt32;
+    return Subclass::GetEntryForIndexImpl(*holder, *backing_store, index,
+                                          filter) != kMaxUInt32;
   }
 
   bool HasAccessors(JSObject* holder) final {
-    return ElementsAccessorSubclass::HasAccessorsImpl(holder,
-                                                      holder->elements());
+    return Subclass::HasAccessorsImpl(holder, holder->elements());
   }
 
   static bool HasAccessorsImpl(JSObject* holder,
@@ -559,11 +573,11 @@
   }
 
   Handle<Object> Get(Handle<JSObject> holder, uint32_t entry) final {
-    return ElementsAccessorSubclass::GetImpl(holder, entry);
+    return Subclass::GetImpl(holder, entry);
   }
 
   static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
-    return ElementsAccessorSubclass::GetImpl(holder->elements(), entry);
+    return Subclass::GetImpl(holder->elements(), entry);
   }
 
   static Handle<Object> GetImpl(FixedArrayBase* backing_store, uint32_t entry) {
@@ -573,14 +587,13 @@
   }
 
   void Set(Handle<JSObject> holder, uint32_t entry, Object* value) final {
-    ElementsAccessorSubclass::SetImpl(holder, entry, value);
+    Subclass::SetImpl(holder, entry, value);
   }
 
   void Reconfigure(Handle<JSObject> object, Handle<FixedArrayBase> store,
                    uint32_t entry, Handle<Object> value,
                    PropertyAttributes attributes) final {
-    ElementsAccessorSubclass::ReconfigureImpl(object, store, entry, value,
-                                              attributes);
+    Subclass::ReconfigureImpl(object, store, entry, value, attributes);
   }
 
   static void ReconfigureImpl(Handle<JSObject> object,
@@ -592,8 +605,7 @@
 
   void Add(Handle<JSObject> object, uint32_t index, Handle<Object> value,
            PropertyAttributes attributes, uint32_t new_capacity) final {
-    ElementsAccessorSubclass::AddImpl(object, index, value, attributes,
-                                      new_capacity);
+    Subclass::AddImpl(object, index, value, attributes, new_capacity);
   }
 
   static void AddImpl(Handle<JSObject> object, uint32_t index,
@@ -604,7 +616,7 @@
 
   uint32_t Push(Handle<JSArray> receiver, Arguments* args,
                 uint32_t push_size) final {
-    return ElementsAccessorSubclass::PushImpl(receiver, args, push_size);
+    return Subclass::PushImpl(receiver, args, push_size);
   }
 
   static uint32_t PushImpl(Handle<JSArray> receiver, Arguments* args,
@@ -615,7 +627,7 @@
 
   uint32_t Unshift(Handle<JSArray> receiver, Arguments* args,
                    uint32_t unshift_size) final {
-    return ElementsAccessorSubclass::UnshiftImpl(receiver, args, unshift_size);
+    return Subclass::UnshiftImpl(receiver, args, unshift_size);
   }
 
   static uint32_t UnshiftImpl(Handle<JSArray> receiver, Arguments* args,
@@ -626,7 +638,7 @@
 
   Handle<JSArray> Slice(Handle<JSObject> receiver, uint32_t start,
                         uint32_t end) final {
-    return ElementsAccessorSubclass::SliceImpl(receiver, start, end);
+    return Subclass::SliceImpl(receiver, start, end);
   }
 
   static Handle<JSArray> SliceImpl(Handle<JSObject> receiver,
@@ -638,8 +650,7 @@
   Handle<JSArray> Splice(Handle<JSArray> receiver, uint32_t start,
                          uint32_t delete_count, Arguments* args,
                          uint32_t add_count) final {
-    return ElementsAccessorSubclass::SpliceImpl(receiver, start, delete_count,
-                                                args, add_count);
+    return Subclass::SpliceImpl(receiver, start, delete_count, args, add_count);
   }
 
   static Handle<JSArray> SpliceImpl(Handle<JSArray> receiver,
@@ -650,7 +661,7 @@
   }
 
   Handle<Object> Pop(Handle<JSArray> receiver) final {
-    return ElementsAccessorSubclass::PopImpl(receiver);
+    return Subclass::PopImpl(receiver);
   }
 
   static Handle<Object> PopImpl(Handle<JSArray> receiver) {
@@ -659,7 +670,7 @@
   }
 
   Handle<Object> Shift(Handle<JSArray> receiver) final {
-    return ElementsAccessorSubclass::ShiftImpl(receiver);
+    return Subclass::ShiftImpl(receiver);
   }
 
   static Handle<Object> ShiftImpl(Handle<JSArray> receiver) {
@@ -668,8 +679,8 @@
   }
 
   void SetLength(Handle<JSArray> array, uint32_t length) final {
-    ElementsAccessorSubclass::SetLengthImpl(array->GetIsolate(), array, length,
-                                            handle(array->elements()));
+    Subclass::SetLengthImpl(array->GetIsolate(), array, length,
+                            handle(array->elements()));
   }
 
   static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array,
@@ -713,21 +724,25 @@
     } else {
       // Check whether the backing store should be expanded.
       capacity = Max(length, JSObject::NewElementsCapacity(capacity));
-      ElementsAccessorSubclass::GrowCapacityAndConvertImpl(array, capacity);
+      Subclass::GrowCapacityAndConvertImpl(array, capacity);
     }
 
     array->set_length(Smi::FromInt(length));
     JSObject::ValidateElements(array);
   }
 
-  static uint32_t GetIterationLength(JSObject* receiver,
-                                     FixedArrayBase* elements) {
+  static uint32_t GetMaxIndex(JSObject* receiver, FixedArrayBase* elements) {
     if (receiver->IsJSArray()) {
       DCHECK(JSArray::cast(receiver)->length()->IsSmi());
       return static_cast<uint32_t>(
           Smi::cast(JSArray::cast(receiver)->length())->value());
     }
-    return ElementsAccessorSubclass::GetCapacityImpl(receiver, elements);
+    return Subclass::GetCapacityImpl(receiver, elements);
+  }
+
+  static uint32_t GetMaxNumberOfEntries(JSObject* receiver,
+                                        FixedArrayBase* elements) {
+    return Subclass::GetMaxIndex(receiver, elements);
   }
 
   static Handle<FixedArrayBase> ConvertElementsWithCapacity(
@@ -762,9 +777,8 @@
       packed_size = Smi::cast(JSArray::cast(*object)->length())->value();
     }
 
-    ElementsAccessorSubclass::CopyElementsImpl(
-        *old_elements, src_index, *new_elements, from_kind, dst_index,
-        packed_size, copy_size);
+    Subclass::CopyElementsImpl(*old_elements, src_index, *new_elements,
+                               from_kind, dst_index, packed_size, copy_size);
 
     return new_elements;
   }
@@ -784,12 +798,17 @@
     DCHECK(IsFastDoubleElementsKind(from_kind) !=
                IsFastDoubleElementsKind(kind()) ||
            IsDictionaryElementsKind(from_kind) ||
-           from_kind == SLOW_STRING_WRAPPER_ELEMENTS ||
            static_cast<uint32_t>(old_elements->length()) < capacity);
+    Subclass::BasicGrowCapacityAndConvertImpl(object, old_elements, from_kind,
+                                              kind(), capacity);
+  }
+
+  static void BasicGrowCapacityAndConvertImpl(
+      Handle<JSObject> object, Handle<FixedArrayBase> old_elements,
+      ElementsKind from_kind, ElementsKind to_kind, uint32_t capacity) {
     Handle<FixedArrayBase> elements =
         ConvertElementsWithCapacity(object, old_elements, from_kind, capacity);
 
-    ElementsKind to_kind = kind();
     if (IsHoleyElementsKind(from_kind)) to_kind = GetHoleyElementsKind(to_kind);
     Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, to_kind);
     JSObject::SetMapAndElements(object, new_map, elements);
@@ -805,11 +824,11 @@
 
   void GrowCapacityAndConvert(Handle<JSObject> object,
                               uint32_t capacity) final {
-    ElementsAccessorSubclass::GrowCapacityAndConvertImpl(object, capacity);
+    Subclass::GrowCapacityAndConvertImpl(object, capacity);
   }
 
   void Delete(Handle<JSObject> obj, uint32_t entry) final {
-    ElementsAccessorSubclass::DeleteImpl(obj, entry);
+    Subclass::DeleteImpl(obj, entry);
   }
 
   static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
@@ -833,7 +852,7 @@
       }
     }
     FixedArrayBase* from = from_holder->elements();
-    // NOTE: the ElementsAccessorSubclass::CopyElementsImpl() methods
+    // NOTE: the Subclass::CopyElementsImpl() methods
     // violate the handlified function signature convention:
     // raw pointer parameters in the function that allocates. This is done
     // intentionally to avoid ArrayConcat() builtin performance degradation.
@@ -842,13 +861,12 @@
     // copying from object with fast double elements to object with object
     // elements. In all the other cases there are no allocations performed and
     // handle creation causes noticeable performance degradation of the builtin.
-    ElementsAccessorSubclass::CopyElementsImpl(
-        from, from_start, *to, from_kind, to_start, packed_size, copy_size);
+    Subclass::CopyElementsImpl(from, from_start, *to, from_kind, to_start,
+                               packed_size, copy_size);
   }
 
   Handle<SeededNumberDictionary> Normalize(Handle<JSObject> object) final {
-    return ElementsAccessorSubclass::NormalizeImpl(object,
-                                                   handle(object->elements()));
+    return Subclass::NormalizeImpl(object, handle(object->elements()));
   }
 
   static Handle<SeededNumberDictionary> NormalizeImpl(
@@ -861,7 +879,7 @@
                                      Handle<FixedArray> values_or_entries,
                                      bool get_entries, int* nof_items,
                                      PropertyFilter filter) {
-    return ElementsAccessorSubclass::CollectValuesOrEntriesImpl(
+    return Subclass::CollectValuesOrEntriesImpl(
         isolate, object, values_or_entries, get_entries, nof_items, filter);
   }
 
@@ -870,11 +888,10 @@
       Handle<FixedArray> values_or_entries, bool get_entries, int* nof_items,
       PropertyFilter filter) {
     int count = 0;
-    KeyAccumulator accumulator(isolate, OWN_ONLY, ALL_PROPERTIES);
-    accumulator.NextPrototype();
-    ElementsAccessorSubclass::CollectElementIndicesImpl(
-        object, handle(object->elements(), isolate), &accumulator, kMaxUInt32,
-        ALL_PROPERTIES, 0);
+    KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly,
+                               ALL_PROPERTIES);
+    Subclass::CollectElementIndicesImpl(
+        object, handle(object->elements(), isolate), &accumulator);
     Handle<FixedArray> keys = accumulator.GetKeys();
 
     for (int i = 0; i < keys->length(); ++i) {
@@ -883,15 +900,14 @@
       uint32_t index;
       if (!key->ToUint32(&index)) continue;
 
-      uint32_t entry = ElementsAccessorSubclass::GetEntryForIndexImpl(
+      uint32_t entry = Subclass::GetEntryForIndexImpl(
           *object, object->elements(), index, filter);
       if (entry == kMaxUInt32) continue;
 
-      PropertyDetails details =
-          ElementsAccessorSubclass::GetDetailsImpl(*object, entry);
+      PropertyDetails details = Subclass::GetDetailsImpl(*object, entry);
 
       if (details.kind() == kData) {
-        value = ElementsAccessorSubclass::GetImpl(object, entry);
+        value = Subclass::GetImpl(object, entry);
       } else {
         LookupIterator it(isolate, object, index, LookupIterator::OWN);
         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
@@ -909,26 +925,22 @@
 
   void CollectElementIndices(Handle<JSObject> object,
                              Handle<FixedArrayBase> backing_store,
-                             KeyAccumulator* keys, uint32_t range,
-                             PropertyFilter filter, uint32_t offset) final {
-    if (filter & ONLY_ALL_CAN_READ) return;
-    ElementsAccessorSubclass::CollectElementIndicesImpl(
-        object, backing_store, keys, range, filter, offset);
+                             KeyAccumulator* keys) final {
+    if (keys->filter() & ONLY_ALL_CAN_READ) return;
+    Subclass::CollectElementIndicesImpl(object, backing_store, keys);
   }
 
   static void CollectElementIndicesImpl(Handle<JSObject> object,
                                         Handle<FixedArrayBase> backing_store,
-                                        KeyAccumulator* keys, uint32_t range,
-                                        PropertyFilter filter,
-                                        uint32_t offset) {
+                                        KeyAccumulator* keys) {
     DCHECK_NE(DICTIONARY_ELEMENTS, kind());
     // Non-dictionary elements can't have all-can-read accessors.
-    uint32_t length = GetIterationLength(*object, *backing_store);
-    if (range < length) length = range;
-    for (uint32_t i = offset; i < length; i++) {
-      if (ElementsAccessorSubclass::HasElementImpl(object, i, backing_store,
-                                                   filter)) {
-        keys->AddKey(i);
+    uint32_t length = Subclass::GetMaxIndex(*object, *backing_store);
+    PropertyFilter filter = keys->filter();
+    Factory* factory = keys->isolate()->factory();
+    for (uint32_t i = 0; i < length; i++) {
+      if (Subclass::HasElementImpl(object, i, backing_store, filter)) {
+        keys->AddKey(factory->NewNumberFromUint(i));
       }
     }
   }
@@ -938,12 +950,10 @@
       Handle<FixedArrayBase> backing_store, GetKeysConversion convert,
       PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices,
       uint32_t insertion_index = 0) {
-    uint32_t length =
-        ElementsAccessorSubclass::GetIterationLength(*object, *backing_store);
+    uint32_t length = Subclass::GetMaxIndex(*object, *backing_store);
     for (uint32_t i = 0; i < length; i++) {
-      if (ElementsAccessorSubclass::HasElementImpl(object, i, backing_store,
-                                                   filter)) {
-        if (convert == CONVERT_TO_STRING) {
+      if (Subclass::HasElementImpl(object, i, backing_store, filter)) {
+        if (convert == GetKeysConversion::kConvertToString) {
           Handle<String> index_string = isolate->factory()->Uint32ToString(i);
           list->set(insertion_index, *index_string);
         } else {
@@ -961,8 +971,8 @@
                                            Handle<FixedArray> keys,
                                            GetKeysConversion convert,
                                            PropertyFilter filter) final {
-    return ElementsAccessorSubclass::PrependElementIndicesImpl(
-        object, backing_store, keys, convert, filter);
+    return Subclass::PrependElementIndicesImpl(object, backing_store, keys,
+                                               convert, filter);
   }
 
   static Handle<FixedArray> PrependElementIndicesImpl(
@@ -972,35 +982,24 @@
     Isolate* isolate = object->GetIsolate();
     uint32_t nof_property_keys = keys->length();
     uint32_t initial_list_length =
-        ElementsAccessorSubclass::GetCapacityImpl(*object, *backing_store);
+        Subclass::GetCapacityImpl(*object, *backing_store);
     initial_list_length += nof_property_keys;
 
     // Collect the element indices into a new list.
     uint32_t nof_indices = 0;
     Handle<FixedArray> combined_keys =
         isolate->factory()->NewFixedArray(initial_list_length);
-    combined_keys = ElementsAccessorSubclass::DirectCollectElementIndicesImpl(
+    combined_keys = Subclass::DirectCollectElementIndicesImpl(
         isolate, object, backing_store, convert, filter, combined_keys,
         &nof_indices);
 
     // Sort the indices list if necessary.
     if (IsDictionaryElementsKind(kind()) || IsSloppyArgumentsElements(kind())) {
-      struct {
-        bool operator()(Object* a, Object* b) {
-          if (!a->IsUndefined()) {
-            if (b->IsUndefined()) return true;
-            return a->Number() < b->Number();
-          }
-          return !b->IsUndefined();
-        }
-      } cmp;
-      Object** start =
-          reinterpret_cast<Object**>(combined_keys->GetFirstElementAddress());
-      std::sort(start, start + nof_indices, cmp);
+      SortIndices(combined_keys, nof_indices, SKIP_WRITE_BARRIER);
       uint32_t array_length = 0;
       // Indices from dictionary elements should only be converted after
       // sorting.
-      if (convert == CONVERT_TO_STRING) {
+      if (convert == GetKeysConversion::kConvertToString) {
         for (uint32_t i = 0; i < nof_indices; i++) {
           Handle<Object> index_string = isolate->factory()->Uint32ToString(
                   combined_keys->get(i)->Number());
@@ -1011,13 +1010,10 @@
                        &array_length) &&
                    array_length <= Smi::kMaxValue)) {
         // Since we use std::sort above, the GC will no longer know where the
-        // HeapNumbers are, hence we have to write them again.
-        // For Arrays with valid Smi length, we are sure to have no HeapNumber
-        // indices and thus we can skip this step.
-        for (uint32_t i = 0; i < nof_indices; i++) {
-          Object* index = combined_keys->get(i);
-          combined_keys->set(i, index);
-        }
+        // HeapNumbers are.  For Arrays with valid Smi length, we are sure to
+        // have no HeapNumber indices and thus we can skip this step.
+        FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(isolate->heap(), *combined_keys, 0,
+                                           nof_indices);
       }
     }
 
@@ -1038,8 +1034,7 @@
   void AddElementsToKeyAccumulator(Handle<JSObject> receiver,
                                    KeyAccumulator* accumulator,
                                    AddKeyConversion convert) final {
-    ElementsAccessorSubclass::AddElementsToKeyAccumulatorImpl(
-        receiver, accumulator, convert);
+    Subclass::AddElementsToKeyAccumulatorImpl(receiver, accumulator, convert);
   }
 
   static uint32_t GetCapacityImpl(JSObject* holder,
@@ -1048,7 +1043,7 @@
   }
 
   uint32_t GetCapacity(JSObject* holder, FixedArrayBase* backing_store) final {
-    return ElementsAccessorSubclass::GetCapacityImpl(holder, backing_store);
+    return Subclass::GetCapacityImpl(holder, backing_store);
   }
 
   static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store,
@@ -1060,21 +1055,20 @@
                                        FixedArrayBase* backing_store,
                                        uint32_t index, PropertyFilter filter) {
     if (IsHoleyElementsKind(kind())) {
-      return index < ElementsAccessorSubclass::GetCapacityImpl(holder,
-                                                               backing_store) &&
+      return index < Subclass::GetCapacityImpl(holder, backing_store) &&
                      !BackingStore::cast(backing_store)->is_the_hole(index)
                  ? index
                  : kMaxUInt32;
     } else {
-      uint32_t length = GetIterationLength(holder, backing_store);
+      uint32_t length = Subclass::GetMaxIndex(holder, backing_store);
       return index < length ? index : kMaxUInt32;
     }
   }
 
   uint32_t GetEntryForIndex(JSObject* holder, FixedArrayBase* backing_store,
                             uint32_t index) final {
-    return ElementsAccessorSubclass::GetEntryForIndexImpl(
-        holder, backing_store, index, ALL_PROPERTIES);
+    return Subclass::GetEntryForIndexImpl(holder, backing_store, index,
+                                          ALL_PROPERTIES);
   }
 
   static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store,
@@ -1087,7 +1081,7 @@
   }
 
   PropertyDetails GetDetails(JSObject* holder, uint32_t entry) final {
-    return ElementsAccessorSubclass::GetDetailsImpl(holder, entry);
+    return Subclass::GetDetailsImpl(holder, entry);
   }
 
  private:
@@ -1103,17 +1097,15 @@
       : ElementsAccessorBase<DictionaryElementsAccessor,
                              ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {}
 
-  static uint32_t GetIterationLength(JSObject* receiver,
-                                     FixedArrayBase* elements) {
-    uint32_t length;
-    if (receiver->IsJSArray()) {
-      // Special-case GetIterationLength for dictionary elements since the
-      // length of the array might be a HeapNumber.
-      JSArray::cast(receiver)->length()->ToArrayLength(&length);
-    } else {
-      length = GetCapacityImpl(receiver, elements);
-    }
-    return length;
+  static uint32_t GetMaxIndex(JSObject* receiver, FixedArrayBase* elements) {
+    // We cannot properly estimate this for dictionaries.
+    UNREACHABLE();
+  }
+
+  static uint32_t GetMaxNumberOfEntries(JSObject* receiver,
+                                        FixedArrayBase* backing_store) {
+    SeededNumberDictionary* dict = SeededNumberDictionary::cast(backing_store);
+    return dict->NumberOfElements();
   }
 
   static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array,
@@ -1184,7 +1176,7 @@
     uint32_t index = GetIndexForEntryImpl(*dict, entry);
     Handle<Object> result = SeededNumberDictionary::DeleteProperty(dict, entry);
     USE(result);
-    DCHECK(result->IsTrue());
+    DCHECK(result->IsTrue(dict->GetIsolate()));
     Handle<FixedArray> new_elements =
         SeededNumberDictionary::Shrink(dict, index);
     obj->set_elements(*new_elements);
@@ -1196,12 +1188,10 @@
     SeededNumberDictionary* dict = SeededNumberDictionary::cast(backing_store);
     if (!dict->requires_slow_elements()) return false;
     int capacity = dict->Capacity();
-    Heap* heap = holder->GetHeap();
-    Object* undefined = heap->undefined_value();
-    Object* the_hole = heap->the_hole_value();
+    Isolate* isolate = dict->GetIsolate();
     for (int i = 0; i < capacity; i++) {
       Object* key = dict->KeyAt(i);
-      if (key == the_hole || key == undefined) continue;
+      if (!dict->IsKey(isolate, key)) continue;
       DCHECK(!dict->IsDeleted(i));
       PropertyDetails details = dict->DetailsAt(i);
       if (details.type() == ACCESSOR_CONSTANT) return true;
@@ -1266,7 +1256,7 @@
     DisallowHeapAllocation no_gc;
     SeededNumberDictionary* dict = SeededNumberDictionary::cast(store);
     Object* index = dict->KeyAt(entry);
-    return !index->IsTheHole();
+    return !index->IsTheHole(dict->GetIsolate());
   }
 
   static uint32_t GetIndexForEntryImpl(FixedArrayBase* store, uint32_t entry) {
@@ -1311,46 +1301,38 @@
     return static_cast<uint32_t>(raw_key->Number());
   }
 
-  static uint32_t GetKeyForEntryImpl(Handle<SeededNumberDictionary> dictionary,
+  static uint32_t GetKeyForEntryImpl(Isolate* isolate,
+                                     Handle<SeededNumberDictionary> dictionary,
                                      int entry, PropertyFilter filter) {
     DisallowHeapAllocation no_gc;
     Object* raw_key = dictionary->KeyAt(entry);
-    if (!dictionary->IsKey(raw_key)) return kMaxUInt32;
-    return FilterKey(dictionary, entry, raw_key, filter);
-  }
-
-  static uint32_t GetKeyForEntryImpl(Handle<SeededNumberDictionary> dictionary,
-                                     int entry, PropertyFilter filter,
-                                     Object* undefined, Object* the_hole) {
-    DisallowHeapAllocation no_gc;
-    Object* raw_key = dictionary->KeyAt(entry);
-    // Replace the IsKey check with a direct comparison which is much faster.
-    if (raw_key == undefined || raw_key == the_hole) {
-      return kMaxUInt32;
-    }
+    if (!dictionary->IsKey(isolate, raw_key)) return kMaxUInt32;
     return FilterKey(dictionary, entry, raw_key, filter);
   }
 
   static void CollectElementIndicesImpl(Handle<JSObject> object,
                                         Handle<FixedArrayBase> backing_store,
-                                        KeyAccumulator* keys, uint32_t range,
-                                        PropertyFilter filter,
-                                        uint32_t offset) {
-    if (filter & SKIP_STRINGS) return;
+                                        KeyAccumulator* keys) {
+    if (keys->filter() & SKIP_STRINGS) return;
     Isolate* isolate = keys->isolate();
-    Handle<Object> undefined = isolate->factory()->undefined_value();
-    Handle<Object> the_hole = isolate->factory()->the_hole_value();
     Handle<SeededNumberDictionary> dictionary =
         Handle<SeededNumberDictionary>::cast(backing_store);
     int capacity = dictionary->Capacity();
+    Handle<FixedArray> elements = isolate->factory()->NewFixedArray(
+        GetMaxNumberOfEntries(*object, *backing_store));
+    int insertion_index = 0;
+    PropertyFilter filter = keys->filter();
     for (int i = 0; i < capacity; i++) {
-      uint32_t key =
-          GetKeyForEntryImpl(dictionary, i, filter, *undefined, *the_hole);
+      uint32_t key = GetKeyForEntryImpl(isolate, dictionary, i, filter);
       if (key == kMaxUInt32) continue;
-      keys->AddKey(key);
+      Handle<Object> key_handle = isolate->factory()->NewNumberFromUint(key);
+      elements->set(insertion_index, *key_handle);
+      insertion_index++;
     }
-
-    keys->SortCurrentElementsList();
+    SortIndices(elements, insertion_index);
+    for (int i = 0; i < insertion_index; i++) {
+      keys->AddKey(elements->get(i));
+    }
   }
 
   static Handle<FixedArray> DirectCollectElementIndicesImpl(
@@ -1361,14 +1343,11 @@
     if (filter & SKIP_STRINGS) return list;
     if (filter & ONLY_ALL_CAN_READ) return list;
 
-    Handle<Object> undefined = isolate->factory()->undefined_value();
-    Handle<Object> the_hole = isolate->factory()->the_hole_value();
     Handle<SeededNumberDictionary> dictionary =
         Handle<SeededNumberDictionary>::cast(backing_store);
     uint32_t capacity = dictionary->Capacity();
     for (uint32_t i = 0; i < capacity; i++) {
-      uint32_t key =
-          GetKeyForEntryImpl(dictionary, i, filter, *undefined, *the_hole);
+      uint32_t key = GetKeyForEntryImpl(isolate, dictionary, i, filter);
       if (key == kMaxUInt32) continue;
       Handle<Object> index = isolate->factory()->NewNumberFromUint(key);
       list->set(insertion_index, *index);
@@ -1393,7 +1372,7 @@
       if (k == *the_hole) continue;
       if (dictionary->IsDeleted(i)) continue;
       Object* value = dictionary->ValueAt(i);
-      DCHECK(!value->IsTheHole());
+      DCHECK(!value->IsTheHole(isolate));
       DCHECK(!value->IsAccessorPair());
       DCHECK(!value->IsAccessorInfo());
       accumulator->AddKey(value, convert);
@@ -1403,21 +1382,18 @@
 
 
 // Super class for all fast element arrays.
-template<typename FastElementsAccessorSubclass,
-         typename KindTraits>
-class FastElementsAccessor
-    : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> {
+template <typename Subclass, typename KindTraits>
+class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> {
  public:
   explicit FastElementsAccessor(const char* name)
-      : ElementsAccessorBase<FastElementsAccessorSubclass,
-                             KindTraits>(name) {}
+      : ElementsAccessorBase<Subclass, KindTraits>(name) {}
 
   typedef typename KindTraits::BackingStore BackingStore;
 
   static Handle<SeededNumberDictionary> NormalizeImpl(
       Handle<JSObject> object, Handle<FixedArrayBase> store) {
     Isolate* isolate = store->GetIsolate();
-    ElementsKind kind = FastElementsAccessorSubclass::kind();
+    ElementsKind kind = Subclass::kind();
 
     // Ensure that notifications fire if the array or object prototypes are
     // normalizing.
@@ -1436,7 +1412,7 @@
       if (IsHoleyElementsKind(kind)) {
         if (BackingStore::cast(*store)->is_the_hole(i)) continue;
       }
-      Handle<Object> value = FastElementsAccessorSubclass::GetImpl(*store, i);
+      Handle<Object> value = Subclass::GetImpl(*store, i);
       dictionary = SeededNumberDictionary::AddNumberEntry(
           dictionary, i, value, details, used_as_prototype);
       j++;
@@ -1453,7 +1429,9 @@
     }
     if (entry == 0) {
       FixedArray* empty = heap->empty_fixed_array();
-      if (obj->HasFastArgumentsElements()) {
+      // Dynamically ask for the elements kind here since we manually redirect
+      // the operations for argument backing stores.
+      if (obj->GetElementsKind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
         FixedArray::cast(obj->elements())->set(1, empty);
       } else {
         obj->set_elements(empty);
@@ -1538,14 +1516,13 @@
                       uint32_t new_capacity) {
     DCHECK_EQ(NONE, attributes);
     ElementsKind from_kind = object->GetElementsKind();
-    ElementsKind to_kind = FastElementsAccessorSubclass::kind();
+    ElementsKind to_kind = Subclass::kind();
     if (IsDictionaryElementsKind(from_kind) ||
         IsFastDoubleElementsKind(from_kind) !=
             IsFastDoubleElementsKind(to_kind) ||
-        FastElementsAccessorSubclass::GetCapacityImpl(
-            *object, object->elements()) != new_capacity) {
-      FastElementsAccessorSubclass::GrowCapacityAndConvertImpl(object,
-                                                               new_capacity);
+        Subclass::GetCapacityImpl(*object, object->elements()) !=
+            new_capacity) {
+      Subclass::GrowCapacityAndConvertImpl(object, new_capacity);
     } else {
       if (IsFastElementsKind(from_kind) && from_kind != to_kind) {
         JSObject::TransitionElementsKind(object, to_kind);
@@ -1555,7 +1532,7 @@
         JSObject::EnsureWritableFastElements(object);
       }
     }
-    FastElementsAccessorSubclass::SetImpl(object, index, *value);
+    Subclass::SetImpl(object, index, *value);
   }
 
   static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) {
@@ -1577,14 +1554,12 @@
                                               KeyAccumulator* accumulator,
                                               AddKeyConversion convert) {
     Handle<FixedArrayBase> elements(receiver->elements(),
-                                    receiver->GetIsolate());
-    uint32_t length =
-        FastElementsAccessorSubclass::GetIterationLength(*receiver, *elements);
+                                    accumulator->isolate());
+    uint32_t length = Subclass::GetMaxNumberOfEntries(*receiver, *elements);
     for (uint32_t i = 0; i < length; i++) {
       if (IsFastPackedElementsKind(KindTraits::Kind) ||
           HasEntryImpl(*elements, i)) {
-        accumulator->AddKey(FastElementsAccessorSubclass::GetImpl(*elements, i),
-                            convert);
+        accumulator->AddKey(Subclass::GetImpl(*elements, i), convert);
       }
     }
   }
@@ -1592,16 +1567,20 @@
   static void ValidateContents(Handle<JSObject> holder, int length) {
 #if DEBUG
     Isolate* isolate = holder->GetIsolate();
+    Heap* heap = isolate->heap();
     HandleScope scope(isolate);
     Handle<FixedArrayBase> elements(holder->elements(), isolate);
     Map* map = elements->map();
-    DCHECK((IsFastSmiOrObjectElementsKind(KindTraits::Kind) &&
-            (map == isolate->heap()->fixed_array_map() ||
-             map == isolate->heap()->fixed_cow_array_map())) ||
-           (IsFastDoubleElementsKind(KindTraits::Kind) ==
-            ((map == isolate->heap()->fixed_array_map() && length == 0) ||
-             map == isolate->heap()->fixed_double_array_map())));
+    if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) {
+      DCHECK_NE(map, heap->fixed_double_array_map());
+    } else if (IsFastDoubleElementsKind(KindTraits::Kind)) {
+      DCHECK_NE(map, heap->fixed_cow_array_map());
+      if (map == heap->fixed_array_map()) DCHECK_EQ(0, length);
+    } else {
+      UNREACHABLE();
+    }
     if (length == 0) return;  // nothing to do!
+#if ENABLE_SLOW_DCHECKS
     DisallowHeapAllocation no_gc;
     Handle<BackingStore> backing_store = Handle<BackingStore>::cast(elements);
     if (IsFastSmiElementsKind(KindTraits::Kind)) {
@@ -1610,30 +1589,38 @@
                (IsFastHoleyElementsKind(KindTraits::Kind) &&
                 backing_store->is_the_hole(i)));
       }
+    } else if (KindTraits::Kind == FAST_ELEMENTS ||
+               KindTraits::Kind == FAST_DOUBLE_ELEMENTS) {
+      for (int i = 0; i < length; i++) {
+        DCHECK(!backing_store->is_the_hole(i));
+      }
+    } else {
+      DCHECK(IsFastHoleyElementsKind(KindTraits::Kind));
     }
 #endif
+#endif
   }
 
   static Handle<Object> PopImpl(Handle<JSArray> receiver) {
-    return FastElementsAccessorSubclass::RemoveElement(receiver, AT_END);
+    return Subclass::RemoveElement(receiver, AT_END);
   }
 
   static Handle<Object> ShiftImpl(Handle<JSArray> receiver) {
-    return FastElementsAccessorSubclass::RemoveElement(receiver, AT_START);
+    return Subclass::RemoveElement(receiver, AT_START);
   }
 
   static uint32_t PushImpl(Handle<JSArray> receiver,
                            Arguments* args, uint32_t push_size) {
     Handle<FixedArrayBase> backing_store(receiver->elements());
-    return FastElementsAccessorSubclass::AddArguments(receiver, backing_store,
-                                                      args, push_size, AT_END);
+    return Subclass::AddArguments(receiver, backing_store, args, push_size,
+                                  AT_END);
   }
 
   static uint32_t UnshiftImpl(Handle<JSArray> receiver,
                               Arguments* args, uint32_t unshift_size) {
     Handle<FixedArrayBase> backing_store(receiver->elements());
-    return FastElementsAccessorSubclass::AddArguments(
-        receiver, backing_store, args, unshift_size, AT_START);
+    return Subclass::AddArguments(receiver, backing_store, args, unshift_size,
+                                  AT_START);
   }
 
   static Handle<JSArray> SliceImpl(Handle<JSObject> receiver,
@@ -1644,11 +1631,10 @@
     Handle<JSArray> result_array = isolate->factory()->NewJSArray(
         KindTraits::Kind, result_len, result_len);
     DisallowHeapAllocation no_gc;
-    FastElementsAccessorSubclass::CopyElementsImpl(
-        *backing_store, start, result_array->elements(), KindTraits::Kind, 0,
-        kPackedSizeNotKnown, result_len);
-    FastElementsAccessorSubclass::TryTransitionResultArrayToPacked(
-        result_array);
+    Subclass::CopyElementsImpl(*backing_store, start, result_array->elements(),
+                               KindTraits::Kind, 0, kPackedSizeNotKnown,
+                               result_len);
+    Subclass::TryTransitionResultArrayToPacked(result_array);
     return result_array;
   }
 
@@ -1681,29 +1667,26 @@
         KindTraits::Kind, delete_count, delete_count);
     if (delete_count > 0) {
       DisallowHeapAllocation no_gc;
-      FastElementsAccessorSubclass::CopyElementsImpl(
-          *backing_store, start, deleted_elements->elements(), KindTraits::Kind,
-          0, kPackedSizeNotKnown, delete_count);
+      Subclass::CopyElementsImpl(*backing_store, start,
+                                 deleted_elements->elements(), KindTraits::Kind,
+                                 0, kPackedSizeNotKnown, delete_count);
     }
 
     // Delete and move elements to make space for add_count new elements.
     if (add_count < delete_count) {
-      FastElementsAccessorSubclass::SpliceShrinkStep(
-          isolate, receiver, backing_store, start, delete_count, add_count,
-          length, new_length);
+      Subclass::SpliceShrinkStep(isolate, receiver, backing_store, start,
+                                 delete_count, add_count, length, new_length);
     } else if (add_count > delete_count) {
-      backing_store = FastElementsAccessorSubclass::SpliceGrowStep(
-          isolate, receiver, backing_store, start, delete_count, add_count,
-          length, new_length);
+      backing_store =
+          Subclass::SpliceGrowStep(isolate, receiver, backing_store, start,
+                                   delete_count, add_count, length, new_length);
     }
 
     // Copy over the arguments.
-    FastElementsAccessorSubclass::CopyArguments(args, backing_store, add_count,
-                                                3, start);
+    Subclass::CopyArguments(args, backing_store, add_count, 3, start);
 
     receiver->set_length(Smi::FromInt(new_length));
-    FastElementsAccessorSubclass::TryTransitionResultArrayToPacked(
-        deleted_elements);
+    Subclass::TryTransitionResultArrayToPacked(deleted_elements);
     return deleted_elements;
   }
 
@@ -1715,8 +1698,7 @@
     uint32_t length = object->elements()->length();
     for (uint32_t index = 0; index < length; ++index) {
       if (!HasEntryImpl(object->elements(), index)) continue;
-      Handle<Object> value =
-          FastElementsAccessorSubclass::GetImpl(object->elements(), index);
+      Handle<Object> value = Subclass::GetImpl(object->elements(), index);
       if (get_entries) {
         value = MakeEntryPair(isolate, index, value);
       }
@@ -1765,9 +1747,9 @@
                                uint32_t new_length) {
     const int move_left_count = len - delete_count - start;
     const int move_left_dst_index = start + add_count;
-    FastElementsAccessorSubclass::MoveElements(
-        isolate, receiver, backing_store, move_left_dst_index,
-        start + delete_count, move_left_count, new_length, len);
+    Subclass::MoveElements(isolate, receiver, backing_store,
+                           move_left_dst_index, start + delete_count,
+                           move_left_count, new_length, len);
   }
 
   // SpliceGrowStep might modify the backing_store.
@@ -1780,23 +1762,22 @@
     DCHECK((add_count - delete_count) <= (Smi::kMaxValue - length));
     // Check if backing_store is big enough.
     if (new_length <= static_cast<uint32_t>(backing_store->length())) {
-      FastElementsAccessorSubclass::MoveElements(
-          isolate, receiver, backing_store, start + add_count,
-          start + delete_count, (length - delete_count - start), 0, 0);
+      Subclass::MoveElements(isolate, receiver, backing_store,
+                             start + add_count, start + delete_count,
+                             (length - delete_count - start), 0, 0);
       // MoveElements updates the backing_store in-place.
       return backing_store;
     }
     // New backing storage is needed.
     int capacity = JSObject::NewElementsCapacity(new_length);
     // Partially copy all elements up to start.
-    Handle<FixedArrayBase> new_elms =
-        FastElementsAccessorSubclass::ConvertElementsWithCapacity(
-            receiver, backing_store, KindTraits::Kind, capacity, start);
+    Handle<FixedArrayBase> new_elms = Subclass::ConvertElementsWithCapacity(
+        receiver, backing_store, KindTraits::Kind, capacity, start);
     // Copy the trailing elements after start + delete_count
-    FastElementsAccessorSubclass::CopyElementsImpl(
-        *backing_store, start + delete_count, *new_elms, KindTraits::Kind,
-        start + add_count, kPackedSizeNotKnown,
-        ElementsAccessor::kCopyToEndAndInitializeToHole);
+    Subclass::CopyElementsImpl(*backing_store, start + delete_count, *new_elms,
+                               KindTraits::Kind, start + add_count,
+                               kPackedSizeNotKnown,
+                               ElementsAccessor::kCopyToEndAndInitializeToHole);
     receiver->set_elements(*new_elms);
     return new_elms;
   }
@@ -1815,16 +1796,14 @@
     DCHECK(length > 0);
     int new_length = length - 1;
     int remove_index = remove_position == AT_START ? 0 : new_length;
-    Handle<Object> result =
-        FastElementsAccessorSubclass::GetImpl(*backing_store, remove_index);
+    Handle<Object> result = Subclass::GetImpl(*backing_store, remove_index);
     if (remove_position == AT_START) {
-      FastElementsAccessorSubclass::MoveElements(
-          isolate, receiver, backing_store, 0, 1, new_length, 0, 0);
+      Subclass::MoveElements(isolate, receiver, backing_store, 0, 1, new_length,
+                             0, 0);
     }
-    FastElementsAccessorSubclass::SetLengthImpl(isolate, receiver, new_length,
-                                                backing_store);
+    Subclass::SetLengthImpl(isolate, receiver, new_length, backing_store);
 
-    if (IsHoleyElementsKind(kind) && result->IsTheHole()) {
+    if (IsHoleyElementsKind(kind) && result->IsTheHole(isolate)) {
       return isolate->factory()->undefined_value();
     }
     return result;
@@ -1833,7 +1812,7 @@
   static uint32_t AddArguments(Handle<JSArray> receiver,
                                Handle<FixedArrayBase> backing_store,
                                Arguments* args, uint32_t add_size,
-                               Where remove_position) {
+                               Where add_position) {
     uint32_t length = Smi::cast(receiver->length())->value();
     DCHECK(0 < add_size);
     uint32_t elms_len = backing_store->length();
@@ -1845,24 +1824,23 @@
       // New backing storage is needed.
       uint32_t capacity = JSObject::NewElementsCapacity(new_length);
       // If we add arguments to the start we have to shift the existing objects.
-      int copy_dst_index = remove_position == AT_START ? add_size : 0;
+      int copy_dst_index = add_position == AT_START ? add_size : 0;
       // Copy over all objects to a new backing_store.
-      backing_store = FastElementsAccessorSubclass::ConvertElementsWithCapacity(
+      backing_store = Subclass::ConvertElementsWithCapacity(
           receiver, backing_store, KindTraits::Kind, capacity, 0,
           copy_dst_index, ElementsAccessor::kCopyToEndAndInitializeToHole);
       receiver->set_elements(*backing_store);
-    } else if (remove_position == AT_START) {
+    } else if (add_position == AT_START) {
       // If the backing store has enough capacity and we add elements to the
       // start we have to shift the existing objects.
       Isolate* isolate = receiver->GetIsolate();
-      FastElementsAccessorSubclass::MoveElements(
-          isolate, receiver, backing_store, add_size, 0, length, 0, 0);
+      Subclass::MoveElements(isolate, receiver, backing_store, add_size, 0,
+                             length, 0, 0);
     }
 
-    int insertion_index = remove_position == AT_START ? 0 : length;
+    int insertion_index = add_position == AT_START ? 0 : length;
     // Copy the arguments to the start.
-    FastElementsAccessorSubclass::CopyArguments(args, backing_store, add_size,
-                                                1, insertion_index);
+    Subclass::CopyArguments(args, backing_store, add_size, 1, insertion_index);
     // Set the length.
     receiver->set_length(Smi::FromInt(new_length));
     return new_length;
@@ -1876,22 +1854,19 @@
     FixedArrayBase* raw_backing_store = *dst_store;
     WriteBarrierMode mode = raw_backing_store->GetWriteBarrierMode(no_gc);
     for (uint32_t i = 0; i < copy_size; i++) {
-      Object* argument = (*args)[i + src_index];
-      FastElementsAccessorSubclass::SetImpl(raw_backing_store, i + dst_index,
-                                            argument, mode);
+      Object* argument = (*args)[src_index + i];
+      DCHECK(!argument->IsTheHole(raw_backing_store->GetIsolate()));
+      Subclass::SetImpl(raw_backing_store, dst_index + i, argument, mode);
     }
   }
 };
 
-
-template<typename FastElementsAccessorSubclass,
-         typename KindTraits>
+template <typename Subclass, typename KindTraits>
 class FastSmiOrObjectElementsAccessor
-    : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> {
+    : public FastElementsAccessor<Subclass, KindTraits> {
  public:
   explicit FastSmiOrObjectElementsAccessor(const char* name)
-      : FastElementsAccessor<FastElementsAccessorSubclass,
-                             KindTraits>(name) {}
+      : FastElementsAccessor<Subclass, KindTraits>(name) {}
 
   static inline void SetImpl(Handle<JSObject> holder, uint32_t entry,
                              Object* value) {
@@ -1909,8 +1884,7 @@
   }
 
   static Object* GetRaw(FixedArray* backing_store, uint32_t entry) {
-    uint32_t index = FastElementsAccessorSubclass::GetIndexForEntryImpl(
-        backing_store, entry);
+    uint32_t index = Subclass::GetIndexForEntryImpl(backing_store, entry);
     return backing_store->get(index);
   }
 
@@ -1931,7 +1905,6 @@
       case FAST_HOLEY_SMI_ELEMENTS:
       case FAST_ELEMENTS:
       case FAST_HOLEY_ELEMENTS:
-      case FAST_STRING_WRAPPER_ELEMENTS:
         CopyObjectToObjectElements(from, from_kind, from_start, to, to_kind,
                                    to_start, copy_size);
         break;
@@ -1943,12 +1916,13 @@
         break;
       }
       case DICTIONARY_ELEMENTS:
-      case SLOW_STRING_WRAPPER_ELEMENTS:
         CopyDictionaryToObjectElements(from, from_start, to, to_kind, to_start,
                                        copy_size);
         break;
       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
+      case FAST_STRING_WRAPPER_ELEMENTS:
+      case SLOW_STRING_WRAPPER_ELEMENTS:
 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
       TYPED_ARRAYS(TYPED_ARRAY_CASE)
 #undef TYPED_ARRAY_CASE
@@ -2010,15 +1984,12 @@
           ElementsKindTraits<FAST_HOLEY_ELEMENTS> >(name) {}
 };
 
-
-template<typename FastElementsAccessorSubclass,
-         typename KindTraits>
+template <typename Subclass, typename KindTraits>
 class FastDoubleElementsAccessor
-    : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> {
+    : public FastElementsAccessor<Subclass, KindTraits> {
  public:
   explicit FastDoubleElementsAccessor(const char* name)
-      : FastElementsAccessor<FastElementsAccessorSubclass,
-                             KindTraits>(name) {}
+      : FastElementsAccessor<Subclass, KindTraits>(name) {}
 
   static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
     return GetImpl(holder->elements(), entry);
@@ -2239,16 +2210,12 @@
 TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR)
 #undef FIXED_ELEMENTS_ACCESSOR
 
-
-template <typename SloppyArgumentsElementsAccessorSubclass,
-          typename ArgumentsAccessor, typename KindTraits>
+template <typename Subclass, typename ArgumentsAccessor, typename KindTraits>
 class SloppyArgumentsElementsAccessor
-    : public ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass,
-                                  KindTraits> {
+    : public ElementsAccessorBase<Subclass, KindTraits> {
  public:
   explicit SloppyArgumentsElementsAccessor(const char* name)
-      : ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass,
-                             KindTraits>(name) {
+      : ElementsAccessorBase<Subclass, KindTraits>(name) {
     USE(KindTraits::Kind);
   }
 
@@ -2265,7 +2232,7 @@
       Object* probe = parameter_map->get(entry + 2);
       Context* context = Context::cast(parameter_map->get(0));
       int context_entry = Smi::cast(probe)->value();
-      DCHECK(!context->get(context_entry)->IsTheHole());
+      DCHECK(!context->get(context_entry)->IsTheHole(isolate));
       return handle(context->get(context_entry), isolate);
     } else {
       // Object is not mapped, defer to the arguments.
@@ -2277,7 +2244,7 @@
         AliasedArgumentsEntry* alias = AliasedArgumentsEntry::cast(*result);
         Context* context = Context::cast(parameter_map->get(0));
         int context_entry = alias->aliased_context_slot();
-        DCHECK(!context->get(context_entry)->IsTheHole());
+        DCHECK(!context->get(context_entry)->IsTheHole(isolate));
         return handle(context->get(context_entry), isolate);
       }
       return result;
@@ -2302,7 +2269,7 @@
       Object* probe = parameter_map->get(entry + 2);
       Context* context = Context::cast(parameter_map->get(0));
       int context_entry = Smi::cast(probe)->value();
-      DCHECK(!context->get(context_entry)->IsTheHole());
+      DCHECK(!context->get(context_entry)->IsTheHole(store->GetIsolate()));
       context->set(context_entry, value);
     } else {
       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
@@ -2311,7 +2278,7 @@
         AliasedArgumentsEntry* alias = AliasedArgumentsEntry::cast(current);
         Context* context = Context::cast(parameter_map->get(0));
         int context_entry = alias->aliased_context_slot();
-        DCHECK(!context->get(context_entry)->IsTheHole());
+        DCHECK(!context->get(context_entry)->IsTheHole(store->GetIsolate()));
         context->set(context_entry, value);
       } else {
         ArgumentsAccessor::SetImpl(arguments, entry - length, value);
@@ -2350,7 +2317,8 @@
     FixedArray* parameter_map = FixedArray::cast(parameters);
     uint32_t length = parameter_map->length() - 2;
     if (entry < length) {
-      return !GetParameterMapArg(parameter_map, entry)->IsTheHole();
+      return !GetParameterMapArg(parameter_map, entry)
+                  ->IsTheHole(parameter_map->GetIsolate());
     }
 
     FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
@@ -2379,12 +2347,12 @@
                                        uint32_t index, PropertyFilter filter) {
     FixedArray* parameter_map = FixedArray::cast(parameters);
     Object* probe = GetParameterMapArg(parameter_map, index);
-    if (!probe->IsTheHole()) return index;
+    if (!probe->IsTheHole(holder->GetIsolate())) return index;
 
     FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
     uint32_t entry = ArgumentsAccessor::GetEntryForIndexImpl(holder, arguments,
                                                              index, filter);
-    if (entry == kMaxUInt32) return entry;
+    if (entry == kMaxUInt32) return kMaxUInt32;
     return (parameter_map->length() - 2) + entry;
   }
 
@@ -2414,32 +2382,23 @@
       // would enable GC of the context.
       parameter_map->set_the_hole(entry + 2);
     } else {
-      SloppyArgumentsElementsAccessorSubclass::DeleteFromArguments(
-          obj, entry - length);
+      Subclass::DeleteFromArguments(obj, entry - length);
     }
   }
 
   static void CollectElementIndicesImpl(Handle<JSObject> object,
                                         Handle<FixedArrayBase> backing_store,
-                                        KeyAccumulator* keys, uint32_t range,
-                                        PropertyFilter filter,
-                                        uint32_t offset) {
-    FixedArray* parameter_map = FixedArray::cast(*backing_store);
-    uint32_t length = parameter_map->length() - 2;
-    if (range < length) length = range;
-
-    for (uint32_t i = offset; i < length; ++i) {
-      if (!parameter_map->get(i + 2)->IsTheHole()) {
-        keys->AddKey(i);
-      }
-    }
-
-    Handle<FixedArrayBase> store(FixedArrayBase::cast(parameter_map->get(1)));
-    ArgumentsAccessor::CollectElementIndicesImpl(object, store, keys, range,
-                                                 filter, offset);
-    if (SloppyArgumentsElementsAccessorSubclass::kind() ==
-        FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
-      keys->SortCurrentElementsList();
+                                        KeyAccumulator* keys) {
+    Isolate* isolate = keys->isolate();
+    uint32_t nof_indices = 0;
+    Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
+        GetCapacityImpl(*object, *backing_store));
+    DirectCollectElementIndicesImpl(isolate, object, backing_store,
+                                    GetKeysConversion::kKeepNumbers,
+                                    ENUMERABLE_STRINGS, indices, &nof_indices);
+    SortIndices(indices, nof_indices);
+    for (uint32_t i = 0; i < nof_indices; i++) {
+      keys->AddKey(indices->get(i));
     }
   }
 
@@ -2452,8 +2411,8 @@
     uint32_t length = parameter_map->length() - 2;
 
     for (uint32_t i = 0; i < length; ++i) {
-      if (parameter_map->get(i + 2)->IsTheHole()) continue;
-      if (convert == CONVERT_TO_STRING) {
+      if (parameter_map->get(i + 2)->IsTheHole(isolate)) continue;
+      if (convert == GetKeysConversion::kConvertToString) {
         Handle<String> index_string = isolate->factory()->Uint32ToString(i);
         list->set(insertion_index, *index_string);
       } else {
@@ -2488,7 +2447,7 @@
     uint32_t index = GetIndexForEntryImpl(*dict, entry);
     Handle<Object> result = SeededNumberDictionary::DeleteProperty(dict, entry);
     USE(result);
-    DCHECK(result->IsTrue());
+    DCHECK(result->IsTrue(dict->GetIsolate()));
     Handle<FixedArray> new_elements =
         SeededNumberDictionary::Shrink(dict, index);
     parameter_map->set(1, *new_elements);
@@ -2521,25 +2480,25 @@
                               PropertyAttributes attributes) {
     Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(store);
     uint32_t length = parameter_map->length() - 2;
+    Isolate* isolate = store->GetIsolate();
     if (entry < length) {
       Object* probe = parameter_map->get(entry + 2);
-      DCHECK(!probe->IsTheHole());
+      DCHECK(!probe->IsTheHole(isolate));
       Context* context = Context::cast(parameter_map->get(0));
       int context_entry = Smi::cast(probe)->value();
-      DCHECK(!context->get(context_entry)->IsTheHole());
+      DCHECK(!context->get(context_entry)->IsTheHole(isolate));
       context->set(context_entry, *value);
 
       // Redefining attributes of an aliased element destroys fast aliasing.
       parameter_map->set_the_hole(entry + 2);
       // For elements that are still writable we re-establish slow aliasing.
       if ((attributes & READ_ONLY) == 0) {
-        Isolate* isolate = store->GetIsolate();
         value = isolate->factory()->NewAliasedArgumentsEntry(context_entry);
       }
 
       PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
       Handle<SeededNumberDictionary> arguments(
-          SeededNumberDictionary::cast(parameter_map->get(1)));
+          SeededNumberDictionary::cast(parameter_map->get(1)), isolate);
       arguments = SeededNumberDictionary::AddNumberEntry(
           arguments, entry, value, details, object->map()->is_prototype_map());
       // If the attributes were NONE, we would have called set rather than
@@ -2549,7 +2508,7 @@
       parameter_map->set(1, *arguments);
     } else {
       Handle<FixedArrayBase> arguments(
-          FixedArrayBase::cast(parameter_map->get(1)));
+          FixedArrayBase::cast(parameter_map->get(1)), isolate);
       DictionaryElementsAccessor::ReconfigureImpl(
           object, arguments, entry - length, value, attributes);
     }
@@ -2568,16 +2527,45 @@
             FastHoleyObjectElementsAccessor,
             ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
 
+  static Handle<FixedArray> GetArguments(Isolate* isolate,
+                                         FixedArrayBase* backing_store) {
+    FixedArray* parameter_map = FixedArray::cast(backing_store);
+    return Handle<FixedArray>(FixedArray::cast(parameter_map->get(1)), isolate);
+  }
+
+  static Handle<JSArray> SliceImpl(Handle<JSObject> receiver, uint32_t start,
+                                   uint32_t end) {
+    Isolate* isolate = receiver->GetIsolate();
+    uint32_t result_len = end < start ? 0u : end - start;
+    Handle<JSArray> result_array = isolate->factory()->NewJSArray(
+        FAST_HOLEY_ELEMENTS, result_len, result_len);
+    DisallowHeapAllocation no_gc;
+    FixedArray* elements = FixedArray::cast(result_array->elements());
+    FixedArray* parameters = FixedArray::cast(receiver->elements());
+    uint32_t insertion_index = 0;
+    for (uint32_t i = start; i < end; i++) {
+      uint32_t entry =
+          GetEntryForIndexImpl(*receiver, parameters, i, ALL_PROPERTIES);
+      if (entry != kMaxUInt32 && HasEntryImpl(parameters, entry)) {
+        elements->set(insertion_index, *GetImpl(parameters, entry));
+      } else {
+        elements->set_the_hole(insertion_index);
+      }
+      insertion_index++;
+    }
+    return result_array;
+  }
+
   static Handle<SeededNumberDictionary> NormalizeImpl(
       Handle<JSObject> object, Handle<FixedArrayBase> elements) {
-    FixedArray* parameter_map = FixedArray::cast(*elements);
-    Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
+    Handle<FixedArray> arguments =
+        GetArguments(elements->GetIsolate(), *elements);
     return FastHoleyObjectElementsAccessor::NormalizeImpl(object, arguments);
   }
 
   static void DeleteFromArguments(Handle<JSObject> obj, uint32_t entry) {
-    FixedArray* parameter_map = FixedArray::cast(obj->elements());
-    Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
+    Handle<FixedArray> arguments =
+        GetArguments(obj->GetIsolate(), obj->elements());
     FastHoleyObjectElementsAccessor::DeleteCommon(obj, entry, arguments);
   }
 
@@ -2650,15 +2638,12 @@
   }
 };
 
-template <typename StringWrapperElementsAccessorSubclass,
-          typename BackingStoreAccessor, typename KindTraits>
+template <typename Subclass, typename BackingStoreAccessor, typename KindTraits>
 class StringWrapperElementsAccessor
-    : public ElementsAccessorBase<StringWrapperElementsAccessorSubclass,
-                                  KindTraits> {
+    : public ElementsAccessorBase<Subclass, KindTraits> {
  public:
   explicit StringWrapperElementsAccessor(const char* name)
-      : ElementsAccessorBase<StringWrapperElementsAccessorSubclass, KindTraits>(
-            name) {
+      : ElementsAccessorBase<Subclass, KindTraits>(name) {
     USE(KindTraits::Kind);
   }
 
@@ -2722,8 +2707,7 @@
         (object->GetElementsKind() == SLOW_STRING_WRAPPER_ELEMENTS ||
          BackingStoreAccessor::GetCapacityImpl(*object, object->elements()) !=
              new_capacity)) {
-      StringWrapperElementsAccessorSubclass::GrowCapacityAndConvertImpl(
-          object, new_capacity);
+      GrowCapacityAndConvertImpl(object, new_capacity);
     }
     BackingStoreAccessor::AddImpl(object, index, value, attributes,
                                   new_capacity);
@@ -2760,23 +2744,42 @@
 
   static void CollectElementIndicesImpl(Handle<JSObject> object,
                                         Handle<FixedArrayBase> backing_store,
-                                        KeyAccumulator* keys, uint32_t range,
-                                        PropertyFilter filter,
-                                        uint32_t offset) {
+                                        KeyAccumulator* keys) {
     uint32_t length = GetString(*object)->length();
+    Factory* factory = keys->isolate()->factory();
     for (uint32_t i = 0; i < length; i++) {
-      keys->AddKey(i);
+      keys->AddKey(factory->NewNumberFromUint(i));
     }
-    BackingStoreAccessor::CollectElementIndicesImpl(object, backing_store, keys,
-                                                    range, filter, offset);
+    BackingStoreAccessor::CollectElementIndicesImpl(object, backing_store,
+                                                    keys);
+  }
+
+  static void GrowCapacityAndConvertImpl(Handle<JSObject> object,
+                                         uint32_t capacity) {
+    Handle<FixedArrayBase> old_elements(object->elements());
+    ElementsKind from_kind = object->GetElementsKind();
+    // This method should only be called if there's a reason to update the
+    // elements.
+    DCHECK(from_kind == SLOW_STRING_WRAPPER_ELEMENTS ||
+           static_cast<uint32_t>(old_elements->length()) < capacity);
+    Subclass::BasicGrowCapacityAndConvertImpl(object, old_elements, from_kind,
+                                              FAST_STRING_WRAPPER_ELEMENTS,
+                                              capacity);
   }
 
   static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
                                FixedArrayBase* to, ElementsKind from_kind,
                                uint32_t to_start, int packed_size,
                                int copy_size) {
-    BackingStoreAccessor::CopyElementsImpl(from, from_start, to, from_kind,
-                                           to_start, packed_size, copy_size);
+    DCHECK(!to->IsDictionary());
+    if (from_kind == SLOW_STRING_WRAPPER_ELEMENTS) {
+      CopyDictionaryToObjectElements(from, from_start, to, FAST_HOLEY_ELEMENTS,
+                                     to_start, copy_size);
+    } else {
+      DCHECK_EQ(FAST_STRING_WRAPPER_ELEMENTS, from_kind);
+      CopyObjectToObjectElements(from, FAST_HOLEY_ELEMENTS, from_start, to,
+                                 FAST_HOLEY_ELEMENTS, to_start, copy_size);
+    }
   }
 
  private:
@@ -2914,7 +2917,7 @@
   }
 
   // Fill in the content
-  switch (array->GetElementsKind()) {
+  switch (elements_kind) {
     case FAST_HOLEY_SMI_ELEMENTS:
     case FAST_SMI_ELEMENTS: {
       Handle<FixedArray> smi_elms = Handle<FixedArray>::cast(elms);
@@ -2975,31 +2978,17 @@
   elements_accessors_ = NULL;
 }
 
-
 Handle<JSArray> ElementsAccessor::Concat(Isolate* isolate, Arguments* args,
-                                         uint32_t concat_size) {
-  const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
-  STATIC_ASSERT(FixedDoubleArray::kMaxLength < kHalfOfMaxInt);
-  USE(kHalfOfMaxInt);
-  uint32_t result_len = 0;
-  bool has_raw_doubles = false;
+                                         uint32_t concat_size,
+                                         uint32_t result_len) {
   ElementsKind result_elements_kind = GetInitialFastElementsKind();
+  bool has_raw_doubles = false;
   {
     DisallowHeapAllocation no_gc;
     bool is_holey = false;
-    // Iterate through all the arguments performing checks
-    // and calculating total length.
     for (uint32_t i = 0; i < concat_size; i++) {
-      JSArray* array = JSArray::cast((*args)[i]);
-      uint32_t len = 0;
-      array->length()->ToArrayLength(&len);
-
-      // We shouldn't overflow when adding another len.
-      result_len += len;
-      DCHECK(0 <= result_len);
-      DCHECK(result_len <= FixedDoubleArray::kMaxLength);
-
-      ElementsKind arg_kind = array->GetElementsKind();
+      Object* arg = (*args)[i];
+      ElementsKind arg_kind = JSArray::cast(arg)->GetElementsKind();
       has_raw_doubles = has_raw_doubles || IsFastDoubleElementsKind(arg_kind);
       is_holey = is_holey || IsFastHoleyElementsKind(arg_kind);
       result_elements_kind =
diff --git a/src/elements.h b/src/elements.h
index 2b18ab0..9f70f2a 100644
--- a/src/elements.h
+++ b/src/elements.h
@@ -81,18 +81,12 @@
   // whose PropertyAttribute match |filter|.
   virtual void CollectElementIndices(Handle<JSObject> object,
                                      Handle<FixedArrayBase> backing_store,
-                                     KeyAccumulator* keys,
-                                     uint32_t range = kMaxUInt32,
-                                     PropertyFilter filter = ALL_PROPERTIES,
-                                     uint32_t offset = 0) = 0;
+                                     KeyAccumulator* keys) = 0;
 
   inline void CollectElementIndices(Handle<JSObject> object,
-                                    KeyAccumulator* keys,
-                                    uint32_t range = kMaxUInt32,
-                                    PropertyFilter filter = ALL_PROPERTIES,
-                                    uint32_t offset = 0) {
-    CollectElementIndices(object, handle(object->elements()), keys, range,
-                          filter, offset);
+                                    KeyAccumulator* keys) {
+    CollectElementIndices(object, handle(object->elements(), keys->isolate()),
+                          keys);
   }
 
   virtual Maybe<bool> CollectValuesOrEntries(
@@ -100,7 +94,6 @@
       Handle<FixedArray> values_or_entries, bool get_entries, int* nof_items,
       PropertyFilter filter = ALL_PROPERTIES) = 0;
 
-  //
   virtual Handle<FixedArray> PrependElementIndices(
       Handle<JSObject> object, Handle<FixedArrayBase> backing_store,
       Handle<FixedArray> keys, GetKeysConversion convert,
@@ -135,7 +128,7 @@
                    uint32_t new_capacity) = 0;
 
   static Handle<JSArray> Concat(Isolate* isolate, Arguments* args,
-                                uint32_t concat_size);
+                                uint32_t concat_size, uint32_t result_length);
 
   virtual uint32_t Push(Handle<JSArray> receiver, Arguments* args,
                         uint32_t push_size) = 0;
diff --git a/src/execution.cc b/src/execution.cc
index a092a8a..243bb8a 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -94,6 +94,7 @@
     if (FLAG_profile_deserialization && target->IsJSFunction()) {
       PrintDeserializedCodeInfo(Handle<JSFunction>::cast(target));
     }
+    RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::JS_Execution);
     value = CALL_GENERATED_CODE(isolate, stub_entry, orig_func, func, recv,
                                 argc, argv);
   }
@@ -105,7 +106,7 @@
 #endif
 
   // Update the pending exception flag and return the value.
-  bool has_exception = value->IsException();
+  bool has_exception = value->IsException(isolate);
   DCHECK(has_exception == isolate->has_pending_exception());
   if (has_exception) {
     isolate->ReportPendingMessages();
@@ -139,7 +140,8 @@
     SaveContext save(isolate);
     isolate->set_context(function->context());
     DCHECK(function->context()->global_object()->IsJSGlobalObject());
-    auto value = Builtins::InvokeApiFunction(function, receiver, argc, argv);
+    auto value =
+        Builtins::InvokeApiFunction(isolate, function, receiver, argc, argv);
     bool has_exception = value.is_null();
     DCHECK(has_exception == isolate->has_pending_exception());
     if (has_exception) {
diff --git a/src/extensions/ignition-statistics-extension.cc b/src/extensions/ignition-statistics-extension.cc
new file mode 100644
index 0000000..b22c599
--- /dev/null
+++ b/src/extensions/ignition-statistics-extension.cc
@@ -0,0 +1,36 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/extensions/ignition-statistics-extension.h"
+
+#include "src/interpreter/bytecodes.h"
+#include "src/interpreter/interpreter.h"
+#include "src/isolate.h"
+
+namespace v8 {
+namespace internal {
+
+v8::Local<v8::FunctionTemplate>
+IgnitionStatisticsExtension::GetNativeFunctionTemplate(
+    v8::Isolate* isolate, v8::Local<v8::String> name) {
+  DCHECK_EQ(strcmp(*v8::String::Utf8Value(name), "getIgnitionDispatchCounters"),
+            0);
+  return v8::FunctionTemplate::New(
+      isolate, IgnitionStatisticsExtension::GetIgnitionDispatchCounters);
+}
+
+const char* const IgnitionStatisticsExtension::kSource =
+    "native function getIgnitionDispatchCounters();";
+
+void IgnitionStatisticsExtension::GetIgnitionDispatchCounters(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  DCHECK_EQ(args.Length(), 0);
+  DCHECK(FLAG_trace_ignition_dispatches);
+  args.GetReturnValue().Set(reinterpret_cast<Isolate*>(args.GetIsolate())
+                                ->interpreter()
+                                ->GetDispatchCountersObject());
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/extensions/ignition-statistics-extension.h b/src/extensions/ignition-statistics-extension.h
new file mode 100644
index 0000000..fee55f6
--- /dev/null
+++ b/src/extensions/ignition-statistics-extension.h
@@ -0,0 +1,31 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_EXTENSIONS_IGNITION_STATISTICS_EXTENSION_H_
+#define V8_EXTENSIONS_IGNITION_STATISTICS_EXTENSION_H_
+
+#include "include/v8.h"
+
+namespace v8 {
+namespace internal {
+
+class IgnitionStatisticsExtension : public v8::Extension {
+ public:
+  IgnitionStatisticsExtension()
+      : v8::Extension("v8/ignition-statistics", kSource) {}
+
+  v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
+      v8::Isolate* isolate, v8::Local<v8::String> name) override;
+
+  static void GetIgnitionDispatchCounters(
+      const v8::FunctionCallbackInfo<v8::Value>& args);
+
+ private:
+  static const char* const kSource;
+};
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_EXTENSIONS_IGNITION_STATISTICS_EXTENSION_H_
diff --git a/src/extensions/statistics-extension.cc b/src/extensions/statistics-extension.cc
index 76dcd43..387bd31 100644
--- a/src/extensions/statistics-extension.cc
+++ b/src/extensions/statistics-extension.cc
@@ -116,7 +116,7 @@
   };
 
   const StatisticNumber numbers[] = {
-      {isolate->memory_allocator()->Size(), "total_committed_bytes"},
+      {heap->memory_allocator()->Size(), "total_committed_bytes"},
       {heap->new_space()->Size(), "new_space_live_bytes"},
       {heap->new_space()->Available(), "new_space_available_bytes"},
       {heap->new_space()->CommittedMemory(), "new_space_commited_bytes"},
@@ -135,8 +135,7 @@
     AddNumber(args.GetIsolate(), result, numbers[i].number, numbers[i].name);
   }
 
-  AddNumber64(args.GetIsolate(), result,
-              heap->amount_of_external_allocated_memory(),
+  AddNumber64(args.GetIsolate(), result, heap->external_memory(),
               "amount_of_external_allocated_memory");
   args.GetReturnValue().Set(result);
 }
diff --git a/src/external-reference-table.cc b/src/external-reference-table.cc
index 29a2474..7e5ef84 100644
--- a/src/external-reference-table.cc
+++ b/src/external-reference-table.cc
@@ -59,14 +59,40 @@
   Add(ExternalReference::isolate_address(isolate).address(), "isolate");
   Add(ExternalReference::interpreter_dispatch_table_address(isolate).address(),
       "Interpreter::dispatch_table_address");
+  Add(ExternalReference::interpreter_dispatch_counters(isolate).address(),
+      "Interpreter::interpreter_dispatch_counters");
   Add(ExternalReference::address_of_negative_infinity().address(),
       "LDoubleConstant::negative_infinity");
   Add(ExternalReference::power_double_double_function(isolate).address(),
       "power_double_double_function");
   Add(ExternalReference::power_double_int_function(isolate).address(),
       "power_double_int_function");
-  Add(ExternalReference::math_log_double_function(isolate).address(),
-      "std::log");
+  Add(ExternalReference::ieee754_atan_function(isolate).address(),
+      "base::ieee754::atan");
+  Add(ExternalReference::ieee754_atan2_function(isolate).address(),
+      "base::ieee754::atan2");
+  Add(ExternalReference::ieee754_atanh_function(isolate).address(),
+      "base::ieee754::atanh");
+  Add(ExternalReference::ieee754_cbrt_function(isolate).address(),
+      "base::ieee754::cbrt");
+  Add(ExternalReference::ieee754_cos_function(isolate).address(),
+      "base::ieee754::cos");
+  Add(ExternalReference::ieee754_exp_function(isolate).address(),
+      "base::ieee754::exp");
+  Add(ExternalReference::ieee754_expm1_function(isolate).address(),
+      "base::ieee754::expm1");
+  Add(ExternalReference::ieee754_log_function(isolate).address(),
+      "base::ieee754::log");
+  Add(ExternalReference::ieee754_log1p_function(isolate).address(),
+      "base::ieee754::log1p");
+  Add(ExternalReference::ieee754_log10_function(isolate).address(),
+      "base::ieee754::log10");
+  Add(ExternalReference::ieee754_log2_function(isolate).address(),
+      "base::ieee754::log2");
+  Add(ExternalReference::ieee754_sin_function(isolate).address(),
+      "base::ieee754::sin");
+  Add(ExternalReference::ieee754_tan_function(isolate).address(),
+      "base::ieee754::tan");
   Add(ExternalReference::store_buffer_top(isolate).address(),
       "store_buffer_top");
   Add(ExternalReference::address_of_the_hole_nan().address(), "the_hole_nan");
@@ -89,7 +115,7 @@
   Add(ExternalReference::get_mark_code_as_executed_function(isolate).address(),
       "Code::MarkCodeAsExecuted");
   Add(ExternalReference::is_profiling_address(isolate).address(),
-      "CpuProfiler::is_profiling");
+      "Isolate::is_profiling");
   Add(ExternalReference::scheduled_exception_address(isolate).address(),
       "Isolate::scheduled_exception");
   Add(ExternalReference::invoke_function_callback(isolate).address(),
@@ -134,26 +160,20 @@
       "wasm::uint64_div");
   Add(ExternalReference::wasm_uint64_mod(isolate).address(),
       "wasm::uint64_mod");
+  Add(ExternalReference::wasm_word32_ctz(isolate).address(),
+      "wasm::word32_ctz");
+  Add(ExternalReference::wasm_word64_ctz(isolate).address(),
+      "wasm::word64_ctz");
+  Add(ExternalReference::wasm_word32_popcnt(isolate).address(),
+      "wasm::word32_popcnt");
+  Add(ExternalReference::wasm_word64_popcnt(isolate).address(),
+      "wasm::word64_popcnt");
   Add(ExternalReference::f64_acos_wrapper_function(isolate).address(),
       "f64_acos_wrapper");
   Add(ExternalReference::f64_asin_wrapper_function(isolate).address(),
       "f64_asin_wrapper");
-  Add(ExternalReference::f64_atan_wrapper_function(isolate).address(),
-      "f64_atan_wrapper");
-  Add(ExternalReference::f64_cos_wrapper_function(isolate).address(),
-      "f64_cos_wrapper");
-  Add(ExternalReference::f64_sin_wrapper_function(isolate).address(),
-      "f64_sin_wrapper");
-  Add(ExternalReference::f64_tan_wrapper_function(isolate).address(),
-      "f64_tan_wrapper");
-  Add(ExternalReference::f64_exp_wrapper_function(isolate).address(),
-      "f64_exp_wrapper");
-  Add(ExternalReference::f64_log_wrapper_function(isolate).address(),
-      "f64_log_wrapper");
   Add(ExternalReference::f64_pow_wrapper_function(isolate).address(),
       "f64_pow_wrapper");
-  Add(ExternalReference::f64_atan2_wrapper_function(isolate).address(),
-      "f64_atan2_wrapper");
   Add(ExternalReference::f64_mod_wrapper_function(isolate).address(),
       "f64_mod_wrapper");
   Add(ExternalReference::log_enter_external_function(isolate).address(),
@@ -179,8 +199,10 @@
       "Debug::after_break_target_address()");
   Add(ExternalReference::debug_is_active_address(isolate).address(),
       "Debug::is_active_address()");
-  Add(ExternalReference::debug_step_in_enabled_address(isolate).address(),
+  Add(ExternalReference::debug_last_step_action_address(isolate).address(),
       "Debug::step_in_enabled_address()");
+  Add(ExternalReference::debug_suspended_generator_address(isolate).address(),
+      "Debug::step_suspended_generator_address()");
 
 #ifndef V8_INTERPRETED_REGEXP
   Add(ExternalReference::re_case_insensitive_compare_uc16(isolate).address(),
@@ -216,7 +238,7 @@
   };
 
   static const RefTableEntry c_builtins[] = {
-#define DEF_ENTRY_C(name, ignored) {Builtins::c_##name, "Builtins::" #name},
+#define DEF_ENTRY_C(name) {Builtins::c_##name, "Builtins::" #name},
       BUILTIN_LIST_C(DEF_ENTRY_C)
 #undef DEF_ENTRY_C
   };
@@ -228,8 +250,8 @@
   }
 
   static const RefTableEntry builtins[] = {
-#define DEF_ENTRY_C(name, ignored) {Builtins::k##name, "Builtins::" #name},
-#define DEF_ENTRY_A(name, i1, i2, i3) {Builtins::k##name, "Builtins::" #name},
+#define DEF_ENTRY_C(name) {Builtins::k##name, "Builtins::" #name},
+#define DEF_ENTRY_A(name, i1, i2) {Builtins::k##name, "Builtins::" #name},
       BUILTIN_LIST_C(DEF_ENTRY_C) BUILTIN_LIST_A(DEF_ENTRY_A)
           BUILTIN_LIST_DEBUG_A(DEF_ENTRY_A)
 #undef DEF_ENTRY_C
@@ -295,19 +317,27 @@
     const char* name;
   };
 
-  static const AccessorRefTable accessors[] = {
+  static const AccessorRefTable getters[] = {
 #define ACCESSOR_INFO_DECLARATION(name) \
   {FUNCTION_ADDR(&Accessors::name##Getter), "Accessors::" #name "Getter"},
       ACCESSOR_INFO_LIST(ACCESSOR_INFO_DECLARATION)
 #undef ACCESSOR_INFO_DECLARATION
+  };
+  static const AccessorRefTable setters[] = {
 #define ACCESSOR_SETTER_DECLARATION(name) \
   {FUNCTION_ADDR(&Accessors::name), "Accessors::" #name},
-          ACCESSOR_SETTER_LIST(ACCESSOR_SETTER_DECLARATION)
+      ACCESSOR_SETTER_LIST(ACCESSOR_SETTER_DECLARATION)
 #undef ACCESSOR_INFO_DECLARATION
   };
 
-  for (unsigned i = 0; i < arraysize(accessors); ++i) {
-    Add(accessors[i].address, accessors[i].name);
+  for (unsigned i = 0; i < arraysize(getters); ++i) {
+    Add(getters[i].address, getters[i].name);
+    Add(AccessorInfo::redirect(isolate, getters[i].address, ACCESSOR_GETTER),
+        "");
+  }
+
+  for (unsigned i = 0; i < arraysize(setters); ++i) {
+    Add(setters[i].address, setters[i].name);
   }
 
   StubCache* stub_cache = isolate->stub_cache();
@@ -348,6 +378,15 @@
         Deoptimizer::CALCULATE_ENTRY_ADDRESS);
     Add(address, "lazy_deopt");
   }
+
+  // Add external references provided by the embedder (a null-terminated array).
+  intptr_t* api_external_references = isolate->api_external_references();
+  if (api_external_references != nullptr) {
+    while (*api_external_references != 0) {
+      Add(reinterpret_cast<Address>(*api_external_references), "<embedder>");
+      api_external_references++;
+    }
+  }
 }
 
 }  // namespace internal
diff --git a/src/factory.cc b/src/factory.cc
index 41c3cb5..bd4656e 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -96,6 +96,7 @@
   result->set_prototype_users(WeakFixedArray::Empty());
   result->set_registry_slot(PrototypeInfo::UNREGISTERED);
   result->set_validity_cell(Smi::FromInt(0));
+  result->set_bit_field(0);
   return result;
 }
 
@@ -190,8 +191,8 @@
 Handle<AccessorPair> Factory::NewAccessorPair() {
   Handle<AccessorPair> accessors =
       Handle<AccessorPair>::cast(NewStruct(ACCESSOR_PAIR_TYPE));
-  accessors->set_getter(*the_hole_value(), SKIP_WRITE_BARRIER);
-  accessors->set_setter(*the_hole_value(), SKIP_WRITE_BARRIER);
+  accessors->set_getter(*null_value(), SKIP_WRITE_BARRIER);
+  accessors->set_setter(*null_value(), SKIP_WRITE_BARRIER);
   return accessors;
 }
 
@@ -291,12 +292,10 @@
   return result;
 }
 
-
-MaybeHandle<String> Factory::NewStringFromTwoByte(Vector<const uc16> string,
+MaybeHandle<String> Factory::NewStringFromTwoByte(const uc16* string,
+                                                  int length,
                                                   PretenureFlag pretenure) {
-  int length = string.length();
-  const uc16* start = string.start();
-  if (String::IsOneByte(start, length)) {
+  if (String::IsOneByte(string, length)) {
     if (length == 1) return LookupSingleCharacterStringFromCode(string[0]);
     Handle<SeqOneByteString> result;
     ASSIGN_RETURN_ON_EXCEPTION(
@@ -304,7 +303,7 @@
         result,
         NewRawOneByteString(length, pretenure),
         String);
-    CopyChars(result->GetChars(), start, length);
+    CopyChars(result->GetChars(), string, length);
     return result;
   } else {
     Handle<SeqTwoByteString> result;
@@ -313,11 +312,21 @@
         result,
         NewRawTwoByteString(length, pretenure),
         String);
-    CopyChars(result->GetChars(), start, length);
+    CopyChars(result->GetChars(), string, length);
     return result;
   }
 }
 
+MaybeHandle<String> Factory::NewStringFromTwoByte(Vector<const uc16> string,
+                                                  PretenureFlag pretenure) {
+  return NewStringFromTwoByte(string.start(), string.length(), pretenure);
+}
+
+MaybeHandle<String> Factory::NewStringFromTwoByte(
+    const ZoneVector<uc16>* string, PretenureFlag pretenure) {
+  return NewStringFromTwoByte(string->data(), static_cast<int>(string->size()),
+                              pretenure);
+}
 
 Handle<String> Factory::NewInternalizedStringFromUtf8(Vector<const char> str,
                                                       int chars,
@@ -704,6 +713,21 @@
   return external_string;
 }
 
+Handle<ExternalOneByteString> Factory::NewNativeSourceString(
+    const ExternalOneByteString::Resource* resource) {
+  size_t length = resource->length();
+  DCHECK_LE(length, static_cast<size_t>(String::kMaxLength));
+
+  Handle<Map> map = native_source_string_map();
+  Handle<ExternalOneByteString> external_string =
+      New<ExternalOneByteString>(map, OLD_SPACE);
+  external_string->set_length(static_cast<int>(length));
+  external_string->set_hash_field(String::kEmptyHashField);
+  external_string->set_resource(resource);
+
+  return external_string;
+}
+
 
 Handle<Symbol> Factory::NewSymbol() {
   CALL_HEAP_FUNCTION(
@@ -853,15 +877,6 @@
 }
 
 
-Handle<CodeCache> Factory::NewCodeCache() {
-  Handle<CodeCache> code_cache =
-      Handle<CodeCache>::cast(NewStruct(CODE_CACHE_TYPE));
-  code_cache->set_default_cache(*empty_fixed_array(), SKIP_WRITE_BARRIER);
-  code_cache->set_normal_type_cache(*undefined_value(), SKIP_WRITE_BARRIER);
-  return code_cache;
-}
-
-
 Handle<AliasedArgumentsEntry> Factory::NewAliasedArgumentsEntry(
     int aliased_context_slot) {
   Handle<AliasedArgumentsEntry> entry = Handle<AliasedArgumentsEntry>::cast(
@@ -894,7 +909,7 @@
   script->set_wrapper(heap->undefined_value());
   script->set_line_ends(heap->undefined_value());
   script->set_eval_from_shared(heap->undefined_value());
-  script->set_eval_from_instructions_offset(0);
+  script->set_eval_from_position(0);
   script->set_shared_function_infos(Smi::FromInt(0));
   script->set_flags(0);
 
@@ -1216,7 +1231,7 @@
   function->set_code(info->code());
   function->set_context(*context);
   function->set_prototype_or_initial_map(*the_hole_value());
-  function->set_literals(LiteralsArray::cast(*empty_fixed_array()));
+  function->set_literals(LiteralsArray::cast(*empty_literals_array()));
   function->set_next_function_link(*undefined_value(), SKIP_WRITE_BARRIER);
   isolate()->heap()->InitializeJSObjectBody(*function, *map, JSFunction::kSize);
   return function;
@@ -1230,13 +1245,14 @@
   Handle<SharedFunctionInfo> info =
       NewSharedFunctionInfo(name, code, map->is_constructor());
   DCHECK(is_sloppy(info->language_mode()));
-  DCHECK(!map->IsUndefined());
+  DCHECK(!map->IsUndefined(isolate()));
   DCHECK(
       map.is_identical_to(isolate()->sloppy_function_map()) ||
       map.is_identical_to(isolate()->sloppy_function_without_prototype_map()) ||
       map.is_identical_to(
           isolate()->sloppy_function_with_readonly_prototype_map()) ||
       map.is_identical_to(isolate()->strict_function_map()) ||
+      map.is_identical_to(isolate()->strict_function_without_prototype_map()) ||
       // TODO(titzer): wasm_function_map() could be undefined here. ugly.
       (*map == context->get(Context::WASM_FUNCTION_MAP_INDEX)) ||
       map.is_identical_to(isolate()->proxy_function_map()));
@@ -1262,16 +1278,9 @@
 
 Handle<JSFunction> Factory::NewFunction(Handle<String> name, Handle<Code> code,
                                         Handle<Object> prototype,
-                                        bool read_only_prototype,
                                         bool is_strict) {
-  // In strict mode, readonly strict map is only available during bootstrap
-  DCHECK(!is_strict || !read_only_prototype ||
-         isolate()->bootstrapper()->IsActive());
-  Handle<Map> map =
-      is_strict ? isolate()->strict_function_map()
-                : read_only_prototype
-                      ? isolate()->sloppy_function_with_readonly_prototype_map()
-                      : isolate()->sloppy_function_map();
+  Handle<Map> map = is_strict ? isolate()->strict_function_map()
+                              : isolate()->sloppy_function_map();
   Handle<JSFunction> result = NewFunction(map, name, code);
   result->set_prototype_or_initial_map(*prototype);
   return result;
@@ -1281,22 +1290,19 @@
 Handle<JSFunction> Factory::NewFunction(Handle<String> name, Handle<Code> code,
                                         Handle<Object> prototype,
                                         InstanceType type, int instance_size,
-                                        bool read_only_prototype,
-                                        bool install_constructor,
                                         bool is_strict) {
   // Allocate the function
-  Handle<JSFunction> function =
-      NewFunction(name, code, prototype, read_only_prototype, is_strict);
+  Handle<JSFunction> function = NewFunction(name, code, prototype, is_strict);
 
   ElementsKind elements_kind =
       type == JS_ARRAY_TYPE ? FAST_SMI_ELEMENTS : FAST_HOLEY_SMI_ELEMENTS;
   Handle<Map> initial_map = NewMap(type, instance_size, elements_kind);
-  if (!function->shared()->is_generator()) {
-    if (prototype->IsTheHole()) {
+  // TODO(littledan): Why do we have this is_generator test when
+  // NewFunctionPrototype already handles finding an appropriately
+  // shared prototype?
+  if (!function->shared()->is_resumable()) {
+    if (prototype->IsTheHole(isolate())) {
       prototype = NewFunctionPrototype(function);
-    } else if (install_constructor) {
-      JSObject::AddProperty(Handle<JSObject>::cast(prototype),
-                            constructor_string(), function, DONT_ENUM);
     }
   }
 
@@ -1320,11 +1326,12 @@
   // can be from a different context.
   Handle<Context> native_context(function->context()->native_context());
   Handle<Map> new_map;
-  if (function->shared()->is_generator()) {
-    // Generator prototypes can share maps since they don't have "constructor"
-    // properties.
+  if (function->shared()->is_resumable()) {
+    // Generator and async function prototypes can share maps since they
+    // don't have "constructor" properties.
     new_map = handle(native_context->generator_object_prototype_map());
   } else {
+    CHECK(!function->shared()->is_async());
     // Each function prototype gets a fresh map to avoid unwanted sharing of
     // maps between prototypes of different constructors.
     Handle<JSFunction> object_function(native_context->object_function());
@@ -1335,7 +1342,7 @@
   DCHECK(!new_map->is_prototype_map());
   Handle<JSObject> prototype = NewJSObjectFromMap(new_map);
 
-  if (!function->shared()->is_generator()) {
+  if (!function->shared()->is_resumable()) {
     JSObject::AddProperty(prototype, constructor_string(), function, DONT_ENUM);
   }
 
@@ -1406,13 +1413,23 @@
                               bool is_debug) {
   Handle<ByteArray> reloc_info = NewByteArray(desc.reloc_size, TENURED);
 
+  bool has_unwinding_info = desc.unwinding_info != nullptr;
+  DCHECK((has_unwinding_info && desc.unwinding_info_size > 0) ||
+         (!has_unwinding_info && desc.unwinding_info_size == 0));
+
   // Compute size.
-  int body_size = RoundUp(desc.instr_size, kObjectAlignment);
-  int obj_size = Code::SizeFor(body_size);
+  int body_size = desc.instr_size;
+  int unwinding_info_size_field_size = kInt64Size;
+  if (has_unwinding_info) {
+    body_size = RoundUp(body_size, kInt64Size) + desc.unwinding_info_size +
+                unwinding_info_size_field_size;
+  }
+  int obj_size = Code::SizeFor(RoundUp(body_size, kObjectAlignment));
 
   Handle<Code> code = NewCodeRaw(obj_size, immovable);
-  DCHECK(isolate()->code_range() == NULL || !isolate()->code_range()->valid() ||
-         isolate()->code_range()->contains(code->address()) ||
+  DCHECK(!isolate()->heap()->memory_allocator()->code_range()->valid() ||
+         isolate()->heap()->memory_allocator()->code_range()->contains(
+             code->address()) ||
          obj_size <= isolate()->heap()->code_space()->AreaSize());
 
   // The code object has not been fully initialized yet.  We rely on the
@@ -1423,6 +1440,7 @@
   code->set_instruction_size(desc.instr_size);
   code->set_relocation_info(*reloc_info);
   code->set_flags(flags);
+  code->set_has_unwinding_info(has_unwinding_info);
   code->set_raw_kind_specific_flags1(0);
   code->set_raw_kind_specific_flags2(0);
   code->set_is_crankshafted(crankshafted);
@@ -1467,12 +1485,6 @@
 }
 
 
-Handle<Code> Factory::CopyCode(Handle<Code> code, Vector<byte> reloc_info) {
-  CALL_HEAP_FUNCTION(isolate(),
-                     isolate()->heap()->CopyCode(*code, reloc_info),
-                     Code);
-}
-
 Handle<BytecodeArray> Factory::CopyBytecodeArray(
     Handle<BytecodeArray> bytecode_array) {
   CALL_HEAP_FUNCTION(isolate(),
@@ -1668,7 +1680,7 @@
 
 Handle<JSGeneratorObject> Factory::NewJSGeneratorObject(
     Handle<JSFunction> function) {
-  DCHECK(function->shared()->is_generator());
+  DCHECK(function->shared()->is_resumable());
   JSFunction::EnsureHasInitialMap(function);
   Handle<Map> map(function->initial_map());
   DCHECK_EQ(JS_GENERATOR_OBJECT_TYPE, map->instance_type());
@@ -1968,13 +1980,9 @@
   }
 
   // Setup the map for the JSBoundFunction instance.
-  Handle<Map> map = handle(
-      target_function->IsConstructor()
-          ? isolate()->native_context()->bound_function_with_constructor_map()
-          : isolate()
-                ->native_context()
-                ->bound_function_without_constructor_map(),
-      isolate());
+  Handle<Map> map = target_function->IsConstructor()
+                        ? isolate()->bound_function_with_constructor_map()
+                        : isolate()->bound_function_without_constructor_map();
   if (map->prototype() != *prototype) {
     map = Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE);
   }
@@ -1986,8 +1994,6 @@
   result->set_bound_target_function(*target_function);
   result->set_bound_this(*bound_this);
   result->set_bound_arguments(*bound_arguments);
-  result->set_length(Smi::FromInt(0));
-  result->set_name(*undefined_value(), SKIP_WRITE_BARRIER);
   return result;
 }
 
@@ -2006,7 +2012,7 @@
   } else {
     map = Handle<Map>(isolate()->proxy_map());
   }
-  DCHECK(map->prototype()->IsNull());
+  DCHECK(map->prototype()->IsNull(isolate()));
   Handle<JSProxy> result = New<JSProxy>(map, NEW_SPACE);
   result->initialize_properties();
   result->set_target(*target);
@@ -2078,7 +2084,6 @@
   shared->set_num_literals(number_of_literals);
   if (IsGeneratorFunction(kind)) {
     shared->set_instance_class_name(isolate()->heap()->Generator_string());
-    shared->DisableOptimization(kGenerator);
   }
   return shared;
 }
@@ -2133,9 +2138,7 @@
   StaticFeedbackVectorSpec empty_spec;
   Handle<TypeFeedbackMetadata> feedback_metadata =
       TypeFeedbackMetadata::New(isolate(), &empty_spec);
-  Handle<TypeFeedbackVector> feedback_vector =
-      TypeFeedbackVector::New(isolate(), feedback_metadata);
-  share->set_feedback_vector(*feedback_vector, SKIP_WRITE_BARRIER);
+  share->set_feedback_metadata(*feedback_metadata, SKIP_WRITE_BARRIER);
 #if TRACE_MAPS
   share->set_unique_id(isolate()->GetNextUniqueSharedFunctionInfoId());
 #endif
@@ -2211,7 +2214,7 @@
   isolate()->counters()->number_to_string_runtime()->Increment();
   if (check_number_string_cache) {
     Handle<Object> cached = GetNumberStringCache(number);
-    if (!cached->IsUndefined()) return Handle<String>::cast(cached);
+    if (!cached->IsUndefined(isolate())) return Handle<String>::cast(cached);
   }
 
   char arr[100];
@@ -2247,14 +2250,19 @@
       Handle<DebugInfo>::cast(NewStruct(DEBUG_INFO_TYPE));
   debug_info->set_shared(*shared);
   if (shared->HasBytecodeArray()) {
-    // Create a copy for debugging.
-    Handle<BytecodeArray> original(shared->bytecode_array(), isolate());
-    Handle<BytecodeArray> copy = CopyBytecodeArray(original);
-    debug_info->set_abstract_code(AbstractCode::cast(*copy));
+    // We need to create a copy, but delay since this may cause heap
+    // verification.
+    debug_info->set_abstract_code(AbstractCode::cast(shared->bytecode_array()));
   } else {
     debug_info->set_abstract_code(AbstractCode::cast(shared->code()));
   }
   debug_info->set_break_points(*break_points);
+  if (shared->HasBytecodeArray()) {
+    // Create a copy for debugging.
+    Handle<BytecodeArray> original(shared->bytecode_array());
+    Handle<BytecodeArray> copy = CopyBytecodeArray(original);
+    debug_info->set_abstract_code(AbstractCode::cast(*copy));
+  }
 
   // Link debug info to function.
   shared->set_debug_info(*debug_info);
@@ -2312,7 +2320,7 @@
 
   int cache_index = number_of_properties - 1;
   Handle<Object> maybe_cache(context->map_cache(), isolate());
-  if (maybe_cache->IsUndefined()) {
+  if (maybe_cache->IsUndefined(isolate())) {
     // Allocate the new map cache for the native context.
     maybe_cache = NewFixedArray(kMapCacheSize, TENURED);
     context->set_map_cache(*maybe_cache);
@@ -2368,6 +2376,7 @@
   store->set(JSRegExp::kIrregexpMaxRegisterCountIndex, Smi::FromInt(0));
   store->set(JSRegExp::kIrregexpCaptureCountIndex,
              Smi::FromInt(capture_count));
+  store->set(JSRegExp::kIrregexpCaptureNameMapIndex, uninitialized);
   regexp->set_data(*store);
 }
 
diff --git a/src/factory.h b/src/factory.h
index 2fa2901..f8b91a9 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -163,6 +163,9 @@
       Vector<const uc16> str,
       PretenureFlag pretenure = NOT_TENURED);
 
+  MUST_USE_RESULT MaybeHandle<String> NewStringFromTwoByte(
+      const ZoneVector<uc16>* str, PretenureFlag pretenure = NOT_TENURED);
+
   // Allocates an internalized string in old space based on the character
   // stream.
   Handle<String> NewInternalizedStringFromUtf8(Vector<const char> str,
@@ -224,6 +227,10 @@
       const ExternalOneByteString::Resource* resource);
   MUST_USE_RESULT MaybeHandle<String> NewExternalStringFromTwoByte(
       const ExternalTwoByteString::Resource* resource);
+  // Create a new external string object for one-byte encoded native script.
+  // It does not cache the resource data pointer.
+  Handle<ExternalOneByteString> NewNativeSourceString(
+      const ExternalOneByteString::Resource* resource);
 
   // Create a symbol.
   Handle<Symbol> NewSymbol();
@@ -270,8 +277,6 @@
   // the old generation).
   Handle<Struct> NewStruct(InstanceType type);
 
-  Handle<CodeCache> NewCodeCache();
-
   Handle<AliasedArgumentsEntry> NewAliasedArgumentsEntry(
       int aliased_context_slot);
 
@@ -503,7 +508,6 @@
 
   Handle<JSFunction> NewFunction(Handle<String> name, Handle<Code> code,
                                  Handle<Object> prototype,
-                                 bool read_only_prototype = false,
                                  bool is_strict = false);
   Handle<JSFunction> NewFunction(Handle<String> name);
   Handle<JSFunction> NewFunctionWithoutPrototype(Handle<String> name,
@@ -521,8 +525,6 @@
   Handle<JSFunction> NewFunction(Handle<String> name, Handle<Code> code,
                                  Handle<Object> prototype, InstanceType type,
                                  int instance_size,
-                                 bool read_only_prototype = false,
-                                 bool install_constructor = false,
                                  bool is_strict = false);
   Handle<JSFunction> NewFunction(Handle<String> name,
                                  Handle<Code> code,
@@ -562,6 +564,11 @@
     return NewRangeError(MessageTemplate::kInvalidStringLength);
   }
 
+  Handle<Object> NewURIError() {
+    return NewError(isolate()->uri_error_function(),
+                    MessageTemplate::kURIMalformed);
+  }
+
   Handle<Object> NewError(Handle<JSFunction> constructor,
                           MessageTemplate::Template template_index,
                           Handle<Object> arg0 = Handle<Object>(),
@@ -693,6 +700,9 @@
                 AllocationSpace space,
                 Handle<AllocationSite> allocation_site);
 
+  MaybeHandle<String> NewStringFromTwoByte(const uc16* string, int length,
+                                           PretenureFlag pretenure);
+
   // Creates a code object that is not yet fully initialized yet.
   inline Handle<Code> NewCodeRaw(int object_size, bool immovable);
 
diff --git a/src/fast-accessor-assembler.cc b/src/fast-accessor-assembler.cc
index cd2910c..1fbe1a8 100644
--- a/src/fast-accessor-assembler.cc
+++ b/src/fast-accessor-assembler.cc
@@ -5,12 +5,12 @@
 #include "src/fast-accessor-assembler.h"
 
 #include "src/base/logging.h"
+#include "src/code-stub-assembler.h"
 #include "src/code-stubs.h"  // For CallApiCallbackStub.
-#include "src/compiler/code-stub-assembler.h"
 #include "src/handles-inl.h"
 #include "src/objects.h"  // For FAA::LoadInternalField impl.
 
-using v8::internal::compiler::CodeStubAssembler;
+using v8::internal::CodeStubAssembler;
 using v8::internal::compiler::Node;
 
 namespace v8 {
@@ -56,12 +56,13 @@
   CodeStubAssembler::Variable result(assembler_.get(),
                                      MachineRepresentation::kTagged);
   CodeStubAssembler::Label is_jsobject(assembler_.get());
+  CodeStubAssembler::Label maybe_api_object(assembler_.get());
   CodeStubAssembler::Label is_not_jsobject(assembler_.get());
   CodeStubAssembler::Label merge(assembler_.get(), &result);
   assembler_->Branch(
       assembler_->WordEqual(
           instance_type, assembler_->IntPtrConstant(Internals::kJSObjectType)),
-      &is_jsobject, &is_not_jsobject);
+      &is_jsobject, &maybe_api_object);
 
   // JSObject? Then load the internal field field_no.
   assembler_->Bind(&is_jsobject);
@@ -71,6 +72,12 @@
   result.Bind(internal_field);
   assembler_->Goto(&merge);
 
+  assembler_->Bind(&maybe_api_object);
+  assembler_->Branch(
+      assembler_->WordEqual(instance_type, assembler_->IntPtrConstant(
+                                               Internals::kJSApiObjectType)),
+      &is_jsobject, &is_not_jsobject);
+
   // No JSObject? Return undefined.
   // TODO(vogelheim): Check whether this is the appropriate action, or whether
   //                  the method should take a label instead.
diff --git a/src/fast-accessor-assembler.h b/src/fast-accessor-assembler.h
index 57e72e8..346592e 100644
--- a/src/fast-accessor-assembler.h
+++ b/src/fast-accessor-assembler.h
@@ -14,7 +14,7 @@
 #include "src/handles.h"
 
 // For CodeStubAssembler::Label. (We cannot forward-declare inner classes.)
-#include "src/compiler/code-stub-assembler.h"
+#include "src/code-stub-assembler.h"
 
 namespace v8 {
 namespace internal {
@@ -73,9 +73,9 @@
 
  private:
   ValueId FromRaw(compiler::Node* node);
-  LabelId FromRaw(compiler::CodeStubAssembler::Label* label);
+  LabelId FromRaw(CodeStubAssembler::Label* label);
   compiler::Node* FromId(ValueId value) const;
-  compiler::CodeStubAssembler::Label* FromId(LabelId value) const;
+  CodeStubAssembler::Label* FromId(LabelId value) const;
 
   void Clear();
   Zone* zone() { return &zone_; }
@@ -83,13 +83,13 @@
 
   Zone zone_;
   Isolate* isolate_;
-  base::SmartPointer<compiler::CodeStubAssembler> assembler_;
+  base::SmartPointer<CodeStubAssembler> assembler_;
 
   // To prevent exposing the RMA internals to the outside world, we'll map
   // Node + Label pointers integers wrapped in ValueId and LabelId instances.
   // These vectors maintain this mapping.
   std::vector<compiler::Node*> nodes_;
-  std::vector<compiler::CodeStubAssembler::Label*> labels_;
+  std::vector<CodeStubAssembler::Label*> labels_;
 
   // Remember the current state for easy error checking. (We prefer to be
   // strict as this class will be exposed at the API.)
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index c1fffec..e3dcf29 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -184,9 +184,13 @@
 DEFINE_BOOL(harmony_shipping, true, "enable all shipped harmony features")
 DEFINE_IMPLICATION(es_staging, harmony)
 
-DEFINE_BOOL(promise_extra, true, "additional V8 Promise functions")
-// Removing extra Promise functions is staged
-DEFINE_NEG_IMPLICATION(harmony, promise_extra)
+DEFINE_BOOL(promise_extra, false, "additional V8 Promise functions")
+// Removing extra Promise functions is shipped
+DEFINE_NEG_VALUE_IMPLICATION(harmony_shipping, promise_extra, true)
+
+DEFINE_BOOL(intl_extra, false, "additional V8 Intl functions")
+// Removing extra Intl functions is shipped
+DEFINE_NEG_VALUE_IMPLICATION(harmony_shipping, intl_extra, true)
 
 // Activate on ClusterFuzz.
 DEFINE_IMPLICATION(es_staging, harmony_regexp_lookbehind)
@@ -194,38 +198,41 @@
 
 // Features that are still work in progress (behind individual flags).
 #define HARMONY_INPROGRESS(V)                                           \
-  V(harmony_object_observe, "harmony Object.observe")                   \
+  V(harmony_array_prototype_values, "harmony Array.prototype.values")   \
   V(harmony_function_sent, "harmony function.sent")                     \
   V(harmony_sharedarraybuffer, "harmony sharedarraybuffer")             \
   V(harmony_simd, "harmony simd")                                       \
+  V(harmony_explicit_tailcalls, "harmony explicit tail calls")          \
   V(harmony_do_expressions, "harmony do-expressions")                   \
+  V(harmony_restrictive_generators,                                     \
+    "harmony restrictions on generator declarations")                   \
+  V(harmony_regexp_named_captures, "harmony regexp named captures")     \
   V(harmony_regexp_property, "harmony unicode regexp property classes") \
-  V(harmony_string_padding, "harmony String-padding methods")
+  V(harmony_for_in, "harmony for-in syntax")
 
 // Features that are complete (but still behind --harmony/es-staging flag).
-#define HARMONY_STAGED(V)                                                    \
+#define HARMONY_STAGED_BASE(V)                                               \
   V(harmony_regexp_lookbehind, "harmony regexp lookbehind")                  \
   V(harmony_tailcalls, "harmony tail calls")                                 \
   V(harmony_object_values_entries, "harmony Object.values / Object.entries") \
   V(harmony_object_own_property_descriptors,                                 \
     "harmony Object.getOwnPropertyDescriptors()")                            \
-  V(harmony_exponentiation_operator, "harmony exponentiation operator `**`")
+  V(harmony_async_await, "harmony async-await")                              \
+  V(harmony_string_padding, "harmony String-padding methods")
+
+#ifdef V8_I18N_SUPPORT
+#define HARMONY_STAGED(V) \
+  HARMONY_STAGED_BASE(V)  \
+  V(icu_case_mapping, "case mapping with ICU rather than Unibrow")
+#else
+#define HARMONY_STAGED(V) HARMONY_STAGED_BASE(V)
+#endif
 
 // Features that are shipping (turned on by default, but internal flag remains).
 #define HARMONY_SHIPPING(V)                                           \
-  V(harmony_array_prototype_values, "harmony Array.prototype.values") \
-  V(harmony_function_name, "harmony Function name inference")         \
-  V(harmony_instanceof, "harmony instanceof support")                 \
-  V(harmony_iterator_close, "harmony iterator finalization")          \
-  V(harmony_unicode_regexps, "harmony unicode regexps")               \
-  V(harmony_regexp_exec, "harmony RegExp exec override behavior")     \
-  V(harmony_sloppy, "harmony features in sloppy mode")                \
-  V(harmony_sloppy_let, "harmony let in sloppy mode")                 \
-  V(harmony_sloppy_function, "harmony sloppy function block scoping") \
-  V(harmony_regexp_subclass, "harmony regexp subclassing")            \
   V(harmony_restrictive_declarations,                                 \
     "harmony limitations on sloppy mode function declarations")       \
-  V(harmony_species, "harmony Symbol.species")
+  V(harmony_exponentiation_operator, "harmony exponentiation operator `**`")
 
 // Once a shipping feature has proved stable in the wild, it will be dropped
 // from HARMONY_SHIPPING, all occurrences of the FLAG_ variable are removed,
@@ -250,16 +257,14 @@
 HARMONY_SHIPPING(FLAG_SHIPPING_FEATURES)
 #undef FLAG_SHIPPING_FEATURES
 
-
-// Feature dependencies.
-DEFINE_IMPLICATION(harmony_sloppy_let, harmony_sloppy)
-DEFINE_IMPLICATION(harmony_sloppy_function, harmony_sloppy)
-
 // Flags for experimental implementation features.
 DEFINE_BOOL(compiled_keyed_generic_loads, false,
             "use optimizing compiler to generate keyed generic load stubs")
 DEFINE_BOOL(allocation_site_pretenuring, true,
             "pretenure with allocation sites")
+DEFINE_BOOL(page_promotion, true, "promote pages based on utilization")
+DEFINE_INT(page_promotion_threshold, 70,
+           "min percentage of live bytes on a page to enable fast evacuation")
 DEFINE_BOOL(trace_pretenuring, false,
             "trace pretenuring decisions of HAllocate instructions")
 DEFINE_BOOL(trace_pretenuring_statistics, false,
@@ -268,7 +273,6 @@
 DEFINE_BOOL(track_double_fields, true, "track fields with double values")
 DEFINE_BOOL(track_heap_object_fields, true, "track fields with heap values")
 DEFINE_BOOL(track_computed_fields, true, "track computed boilerplate fields")
-DEFINE_BOOL(harmony_instanceof_opt, true, "optimize ES6 instanceof support")
 DEFINE_IMPLICATION(track_double_fields, track_fields)
 DEFINE_IMPLICATION(track_heap_object_fields, track_fields)
 DEFINE_IMPLICATION(track_computed_fields, track_fields)
@@ -290,14 +294,28 @@
 
 // Flags for Ignition.
 DEFINE_BOOL(ignition, false, "use ignition interpreter")
-DEFINE_BOOL(ignition_eager, true, "eagerly compile and parse with ignition")
+DEFINE_BOOL(ignition_eager, false, "eagerly compile and parse with ignition")
+DEFINE_BOOL(ignition_generators, true,
+            "enable experimental ignition support for generators")
 DEFINE_STRING(ignition_filter, "*", "filter for ignition interpreter")
+DEFINE_BOOL(ignition_deadcode, true,
+            "use ignition dead code elimination optimizer")
+DEFINE_BOOL(ignition_peephole, true, "use ignition peephole optimizer")
+DEFINE_BOOL(ignition_reo, true, "use ignition register equivalence optimizer")
+DEFINE_BOOL(ignition_filter_expression_positions, true,
+            "filter expression positions before the bytecode pipeline")
 DEFINE_BOOL(print_bytecode, false,
             "print bytecode generated by ignition interpreter")
 DEFINE_BOOL(trace_ignition, false,
             "trace the bytecodes executed by the ignition interpreter")
 DEFINE_BOOL(trace_ignition_codegen, false,
             "trace the codegen of ignition interpreter bytecode handlers")
+DEFINE_BOOL(trace_ignition_dispatches, false,
+            "traces the dispatches to bytecode handlers by the ignition "
+            "interpreter")
+DEFINE_STRING(trace_ignition_dispatches_output_file, nullptr,
+              "the file to which the bytecode handler dispatch table is "
+              "written (by default, the table is not written to a file)")
 
 // Flags for Crankshaft.
 DEFINE_BOOL(crankshaft, true, "use crankshaft")
@@ -403,8 +421,9 @@
 // Flags for TurboFan.
 DEFINE_BOOL(turbo, false, "enable TurboFan compiler")
 DEFINE_IMPLICATION(turbo, turbo_asm_deoptimization)
+DEFINE_IMPLICATION(turbo, turbo_type_feedback)
 DEFINE_BOOL(turbo_shipping, true, "enable TurboFan compiler on subset")
-DEFINE_BOOL(turbo_greedy_regalloc, false, "use the greedy register allocator")
+DEFINE_BOOL(turbo_from_bytecode, false, "enable building graphs from bytecode")
 DEFINE_BOOL(turbo_sp_frame_access, false,
             "use stack pointer-relative access to frame wherever possible")
 DEFINE_BOOL(turbo_preprocess_ranges, true,
@@ -426,8 +445,11 @@
             "enable deoptimization in TurboFan for asm.js code")
 DEFINE_BOOL(turbo_verify, DEBUG_BOOL, "verify TurboFan graphs at each phase")
 DEFINE_BOOL(turbo_stats, false, "print TurboFan statistics")
+DEFINE_BOOL(turbo_stats_nvp, false,
+            "print TurboFan statistics in machine-readable format")
 DEFINE_BOOL(turbo_splitting, true, "split nodes during scheduling in TurboFan")
-DEFINE_BOOL(turbo_types, true, "use typed lowering in TurboFan")
+DEFINE_BOOL(turbo_type_feedback, false,
+            "use typed feedback for representation inference in Turbofan")
 DEFINE_BOOL(turbo_source_positions, false,
             "track source code positions when building TurboFan IR")
 DEFINE_IMPLICATION(trace_turbo, turbo_source_positions)
@@ -443,7 +465,6 @@
             "verify register allocation in TurboFan")
 DEFINE_BOOL(turbo_move_optimization, true, "optimize gap moves in TurboFan")
 DEFINE_BOOL(turbo_jt, true, "enable jump threading in TurboFan")
-DEFINE_BOOL(turbo_osr, true, "enable OSR in TurboFan")
 DEFINE_BOOL(turbo_stress_loop_peeling, false,
             "stress loop peeling optimization")
 DEFINE_BOOL(turbo_cf_optimization, true, "optimize control flow in TurboFan")
@@ -455,13 +476,18 @@
             "enable instruction scheduling in TurboFan")
 DEFINE_BOOL(turbo_stress_instruction_scheduling, false,
             "randomly schedule instructions to stress dependency tracking")
+DEFINE_BOOL(turbo_store_elimination, false,
+            "enable store-store elimination in TurboFan")
 
 // Flags for native WebAssembly.
 DEFINE_BOOL(expose_wasm, false, "expose WASM interface to JavaScript")
+DEFINE_INT(wasm_num_compilation_tasks, 10,
+           "number of parallel compilation tasks for wasm")
 DEFINE_BOOL(trace_wasm_encoder, false, "trace encoding of wasm code")
 DEFINE_BOOL(trace_wasm_decoder, false, "trace decoding of wasm code")
 DEFINE_BOOL(trace_wasm_decode_time, false, "trace decoding time of wasm code")
 DEFINE_BOOL(trace_wasm_compiler, false, "trace compiling of wasm code")
+DEFINE_BOOL(trace_wasm_interpreter, false, "trace interpretation of wasm code")
 DEFINE_INT(trace_wasm_ast_start, 0,
            "start function for WASM AST trace (inclusive)")
 DEFINE_INT(trace_wasm_ast_end, 0, "end function for WASM AST trace (exclusive)")
@@ -471,14 +497,20 @@
 DEFINE_BOOL(wasm_loop_assignment_analysis, true,
             "perform loop assignment analysis for WASM")
 
+DEFINE_BOOL(validate_asm, false, "validate asm.js modules before compiling")
 DEFINE_BOOL(enable_simd_asmjs, false, "enable SIMD.js in asm.js stdlib")
 
 DEFINE_BOOL(dump_wasm_module, false, "dump WASM module bytes")
 DEFINE_STRING(dump_wasm_module_path, NULL, "directory to dump wasm modules to")
+DEFINE_BOOL(print_wasm_code_size, false,
+            "print the generated code size for each wasm module")
 
 DEFINE_INT(typed_array_max_size_in_heap, 64,
            "threshold for in-heap typed array")
 
+DEFINE_BOOL(wasm_jit_prototype, false,
+            "enable experimental wasm runtime dynamic code generation")
+
 // Profiler flags.
 DEFINE_INT(frame_count, 1, "number of stack frames inspected by the profiler")
 // 0x1800 fits in the immediate field of an ARM instruction.
@@ -518,8 +550,6 @@
             "enable use of NEON instructions if available (ARM only)")
 DEFINE_BOOL(enable_sudiv, true,
             "enable use of SDIV and UDIV instructions if available (ARM only)")
-DEFINE_BOOL(enable_mls, true,
-            "enable use of MLS instructions if available (ARM only)")
 DEFINE_BOOL(enable_movw_movt, false,
             "enable loading 32-bit constant by means of movw/movt "
             "instruction pairs (ARM only)")
@@ -537,7 +567,6 @@
 DEFINE_IMPLICATION(enable_armv8, enable_neon)
 DEFINE_IMPLICATION(enable_armv8, enable_32dregs)
 DEFINE_IMPLICATION(enable_armv8, enable_sudiv)
-DEFINE_IMPLICATION(enable_armv8, enable_mls)
 
 // bootstrapper.cc
 DEFINE_STRING(expose_natives_as, NULL, "expose natives in global object")
@@ -569,6 +598,8 @@
 DEFINE_BOOL(lazy, true, "use lazy compilation")
 DEFINE_BOOL(trace_opt, false, "trace lazy optimization")
 DEFINE_BOOL(trace_opt_stats, false, "trace lazy optimization statistics")
+DEFINE_BOOL(trace_file_names, false,
+            "include file names in trace-opt/trace-deopt output")
 DEFINE_BOOL(opt, true, "use adaptive optimizations")
 DEFINE_BOOL(always_opt, false, "always try to optimize functions")
 DEFINE_BOOL(always_osr, false, "always try to OSR functions")
@@ -686,7 +717,7 @@
            "least this many unmarked objects")
 DEFINE_INT(max_incremental_marking_finalization_rounds, 3,
            "at most try this many times to finalize incremental marking")
-DEFINE_BOOL(black_allocation, true, "use black allocation")
+DEFINE_BOOL(black_allocation, false, "use black allocation")
 DEFINE_BOOL(concurrent_sweeping, true, "use concurrent sweeping")
 DEFINE_BOOL(parallel_compaction, true, "use parallel compaction")
 DEFINE_BOOL(parallel_pointer_update, true,
@@ -737,6 +768,7 @@
 // ic.cc
 DEFINE_BOOL(use_ic, true, "use inline caching")
 DEFINE_BOOL(trace_ic, false, "trace inline cache state transitions")
+DEFINE_BOOL(tf_load_ic_stub, true, "use TF LoadIC stub")
 
 // macro-assembler-ia32.cc
 DEFINE_BOOL(native_code_counters, false,
@@ -761,13 +793,8 @@
 
 // objects.cc
 DEFINE_BOOL(trace_weak_arrays, false, "Trace WeakFixedArray usage")
-DEFINE_BOOL(track_prototype_users, false,
-            "Keep track of which maps refer to a given prototype object")
 DEFINE_BOOL(trace_prototype_users, false,
             "Trace updates to prototype user tracking")
-DEFINE_BOOL(eliminate_prototype_chain_checks, true,
-            "Collapse prototype chain checks into single-cell checks")
-DEFINE_IMPLICATION(eliminate_prototype_chain_checks, track_prototype_users)
 DEFINE_BOOL(use_verbose_printer, true, "allows verbose printing")
 DEFINE_BOOL(trace_for_in_enumerate, false, "Trace for-in enumerate slow-paths")
 #if TRACE_MAPS
@@ -816,6 +843,7 @@
 DEFINE_INT(hash_seed, 0,
            "Fixed seed to use to hash property keys (0 means random)"
            "(with snapshots this option cannot override the baked-in seed)")
+DEFINE_BOOL(trace_rail, false, "trace RAIL mode")
 
 // runtime.cc
 DEFINE_BOOL(runtime_call_stats, false, "report runtime call counts and times")
@@ -1025,6 +1053,8 @@
 DEFINE_NEG_IMPLICATION(perf_prof, compact_code_space)
 DEFINE_BOOL(perf_prof_debug_info, false,
             "Enable debug info for perf linux profiler (experimental).")
+DEFINE_BOOL(perf_prof_unwinding_info, false,
+            "Enable unwinding info for perf linux profiler (experimental).")
 DEFINE_STRING(gc_fake_mmap, "/tmp/__v8_gc__",
               "Specify the name of the file for fake gc mmap used in ll_prof")
 DEFINE_BOOL(log_internal_timer_events, false, "Time internal events.")
diff --git a/src/flags.cc b/src/flags.cc
index f67defd..f7ae004 100644
--- a/src/flags.cc
+++ b/src/flags.cc
@@ -429,6 +429,10 @@
         PrintF(stderr, "Error: illegal value for flag %s of type %s\n"
                "Try --help for options\n",
                arg, Type2String(flag->type()));
+        if (is_bool_type) {
+          PrintF(stderr,
+                 "To set or unset a boolean flag, use --flag or --no-flag.\n");
+        }
         return_code = j;
         break;
       }
diff --git a/src/frames-inl.h b/src/frames-inl.h
index 5ecbd45..c45f015 100644
--- a/src/frames-inl.h
+++ b/src/frames-inl.h
@@ -199,11 +199,6 @@
 }
 
 
-inline Object* JavaScriptFrame::receiver() const {
-  return GetParameter(-1);
-}
-
-
 inline void JavaScriptFrame::set_receiver(Object* value) {
   Memory::Object_at(GetParameterSlot(-1)) = value;
 }
@@ -214,11 +209,6 @@
 }
 
 
-inline JSFunction* JavaScriptFrame::function() const {
-  return JSFunction::cast(function_slot_object());
-}
-
-
 inline Object* JavaScriptFrame::function_slot_object() const {
   const int offset = JavaScriptFrameConstants::kFunctionOffset;
   return Memory::Object_at(fp() + offset);
@@ -243,6 +233,9 @@
     StackFrameIteratorBase* iterator) : JavaScriptFrame(iterator) {
 }
 
+inline BuiltinFrame::BuiltinFrame(StackFrameIteratorBase* iterator)
+    : JavaScriptFrame(iterator) {}
+
 inline WasmFrame::WasmFrame(StackFrameIteratorBase* iterator)
     : StandardFrame(iterator) {}
 
@@ -288,6 +281,28 @@
   return static_cast<JavaScriptFrame*>(frame);
 }
 
+inline StandardFrame* StackTraceFrameIterator::frame() const {
+  StackFrame* frame = iterator_.frame();
+  DCHECK(frame->is_java_script() || frame->is_arguments_adaptor() ||
+         frame->is_wasm());
+  return static_cast<StandardFrame*>(frame);
+}
+
+bool StackTraceFrameIterator::is_javascript() const {
+  return frame()->is_java_script();
+}
+
+bool StackTraceFrameIterator::is_wasm() const { return frame()->is_wasm(); }
+
+JavaScriptFrame* StackTraceFrameIterator::javascript_frame() const {
+  DCHECK(is_javascript());
+  return static_cast<JavaScriptFrame*>(frame());
+}
+
+WasmFrame* StackTraceFrameIterator::wasm_frame() const {
+  DCHECK(is_wasm());
+  return static_cast<WasmFrame*>(frame());
+}
 
 inline StackFrame* SafeStackFrameIterator::frame() const {
   DCHECK(!done());
diff --git a/src/frames.cc b/src/frames.cc
index 0e57429..698b935 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -104,17 +104,15 @@
   StackFrame::Type type = ExitFrame::GetStateForFramePointer(
       Isolate::c_entry_fp(top), &state);
   handler_ = StackHandler::FromAddress(Isolate::handler(top));
-  if (SingletonFor(type) == NULL) return;
   frame_ = SingletonFor(type, &state);
 }
 
 
 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type,
                                              StackFrame::State* state) {
-  if (type == StackFrame::NONE) return NULL;
   StackFrame* result = SingletonFor(type);
-  DCHECK(result != NULL);
-  result->state_ = *state;
+  DCHECK((!result) == (type == StackFrame::NONE));
+  if (result) result->state_ = *state;
   return result;
 }
 
@@ -162,28 +160,29 @@
 
 // -------------------------------------------------------------------------
 
-
 StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
-    : JavaScriptFrameIterator(isolate) {
-  if (!done() && !IsValidFrame()) Advance();
+    : iterator_(isolate) {
+  if (!done() && !IsValidFrame(iterator_.frame())) Advance();
 }
 
 
 void StackTraceFrameIterator::Advance() {
-  while (true) {
-    JavaScriptFrameIterator::Advance();
-    if (done()) return;
-    if (IsValidFrame()) return;
-  }
+  do {
+    iterator_.Advance();
+  } while (!done() && !IsValidFrame(iterator_.frame()));
 }
 
-
-bool StackTraceFrameIterator::IsValidFrame() {
-    if (!frame()->function()->IsJSFunction()) return false;
-    Object* script = frame()->function()->shared()->script();
+bool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) const {
+  if (frame->is_java_script()) {
+    JavaScriptFrame* jsFrame = static_cast<JavaScriptFrame*>(frame);
+    if (!jsFrame->function()->IsJSFunction()) return false;
+    Object* script = jsFrame->function()->shared()->script();
     // Don't show functions from native scripts to user.
     return (script->IsScript() &&
             Script::TYPE_NATIVE != Script::cast(script)->type());
+  }
+  // apart from javascript, only wasm is valid
+  return frame->is_wasm();
 }
 
 
@@ -230,10 +229,8 @@
   } else {
     return;
   }
-  if (SingletonFor(type) == NULL) return;
   frame_ = SingletonFor(type, &state);
-  DCHECK(frame_);
-  Advance();
+  if (frame_) Advance();
 }
 
 
@@ -261,12 +258,8 @@
   // Advance to the previous frame.
   StackFrame::State state;
   StackFrame::Type type = frame_->GetCallerState(&state);
-  if (SingletonFor(type) == NULL) {
-    frame_ = NULL;
-    return;
-  }
   frame_ = SingletonFor(type, &state);
-  DCHECK(frame_);
+  if (!frame_) return;
 
   // Check that we have actually moved to the previous frame in the stack.
   if (frame_->sp() < last_sp || frame_->fp() < last_fp) {
@@ -406,11 +399,15 @@
       isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline);
   Code* interpreter_bytecode_dispatch =
       isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
+  Code* interpreter_baseline_on_return =
+      isolate->builtins()->builtin(Builtins::kInterpreterMarkBaselineOnReturn);
 
   return (pc >= interpreter_entry_trampoline->instruction_start() &&
           pc < interpreter_entry_trampoline->instruction_end()) ||
          (pc >= interpreter_bytecode_dispatch->instruction_start() &&
-          pc < interpreter_bytecode_dispatch->instruction_end());
+          pc < interpreter_bytecode_dispatch->instruction_end()) ||
+         (pc >= interpreter_baseline_on_return->instruction_start() &&
+          pc < interpreter_baseline_on_return->instruction_end());
 }
 
 StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
@@ -451,17 +448,20 @@
     Code* code_obj =
         GetContainingCode(iterator->isolate(), *(state->pc_address));
     if (code_obj != nullptr) {
-      if (code_obj->is_interpreter_entry_trampoline() ||
-          code_obj->is_interpreter_enter_bytecode_dispatch()) {
-        return INTERPRETED;
-      }
       switch (code_obj->kind()) {
         case Code::BUILTIN:
           if (marker->IsSmi()) break;
-          // We treat frames for BUILTIN Code objects as OptimizedFrame for now
-          // (all the builtins with JavaScript linkage are actually generated
-          // with TurboFan currently, so this is sound).
-          return OPTIMIZED;
+          if (code_obj->is_interpreter_trampoline_builtin()) {
+            return INTERPRETED;
+          }
+          if (code_obj->is_turbofanned()) {
+            // TODO(bmeurer): We treat frames for BUILTIN Code objects as
+            // OptimizedFrame for now (all the builtins with JavaScript
+            // linkage are actually generated with TurboFan currently, so
+            // this is sound).
+            return OPTIMIZED;
+          }
+          return BUILTIN;
         case Code::FUNCTION:
           return JAVA_SCRIPT;
         case Code::OPTIMIZED_FUNCTION:
@@ -493,10 +493,10 @@
     case INTERNAL:
     case CONSTRUCT:
     case ARGUMENTS_ADAPTOR:
-      return candidate;
-    case JS_TO_WASM:
     case WASM_TO_JS:
     case WASM:
+      return candidate;
+    case JS_TO_WASM:
     case JAVA_SCRIPT:
     case OPTIMIZED:
     case INTERPRETED:
@@ -606,12 +606,13 @@
   return EXIT;
 }
 
-
 Address ExitFrame::ComputeStackPointer(Address fp) {
+#if defined(USE_SIMULATOR)
+  MSAN_MEMORY_IS_INITIALIZED(fp + ExitFrameConstants::kSPOffset, kPointerSize);
+#endif
   return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
 }
 
-
 void ExitFrame::FillState(Address fp, Address sp, State* state) {
   state->sp = sp;
   state->fp = fp;
@@ -624,7 +625,6 @@
   state->constant_pool_address = NULL;
 }
 
-
 Address StandardFrame::GetExpressionAddress(int n) const {
   const int offset = StandardFrameConstants::kExpressionsOffset;
   return fp() + offset - n * kPointerSize;
@@ -696,6 +696,7 @@
       case JAVA_SCRIPT:
       case OPTIMIZED:
       case INTERPRETED:
+      case BUILTIN:
         // These frame types have a context, but they are actually stored
         // in the place on the stack that one finds the frame type.
         UNREACHABLE();
@@ -711,7 +712,8 @@
       (frame_header_size + StandardFrameConstants::kFixedFrameSizeAboveFp);
 
   Object** frame_header_base = &Memory::Object_at(fp() - frame_header_size);
-  Object** frame_header_limit = &Memory::Object_at(fp());
+  Object** frame_header_limit =
+      &Memory::Object_at(fp() - StandardFrameConstants::kCPSlotSize);
   Object** parameters_base = &Memory::Object_at(sp());
   Object** parameters_limit = frame_header_base - slot_space / kPointerSize;
 
@@ -726,10 +728,9 @@
   if (safepoint_entry.has_doubles()) {
     // Number of doubles not known at snapshot time.
     DCHECK(!isolate()->serializer_enabled());
-    parameters_base +=
-        RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
-            ->num_allocatable_double_registers() *
-        kDoubleSize / kPointerSize;
+    parameters_base += RegisterConfiguration::Crankshaft()
+                           ->num_allocatable_double_registers() *
+                       kDoubleSize / kPointerSize;
   }
 
   // Visit the registers that contain pointers if any.
@@ -854,17 +855,23 @@
   functions->Add(function());
 }
 
-
-void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
+void JavaScriptFrame::Summarize(List<FrameSummary>* functions,
+                                FrameSummary::Mode mode) const {
   DCHECK(functions->length() == 0);
   Code* code = LookupCode();
   int offset = static_cast<int>(pc() - code->instruction_start());
   AbstractCode* abstract_code = AbstractCode::cast(code);
   FrameSummary summary(receiver(), function(), abstract_code, offset,
-                       IsConstructor());
+                       IsConstructor(), mode);
   functions->Add(summary);
 }
 
+JSFunction* JavaScriptFrame::function() const {
+  return JSFunction::cast(function_slot_object());
+}
+
+Object* JavaScriptFrame::receiver() const { return GetParameter(-1); }
+
 int JavaScriptFrame::LookupExceptionHandlerInTable(
     int* stack_depth, HandlerTable::CatchPrediction* prediction) {
   Code* code = LookupCode();
@@ -944,16 +951,6 @@
   }
 }
 
-
-void JavaScriptFrame::RestoreOperandStack(FixedArray* store) {
-  int operands_count = store->length();
-  DCHECK_LE(operands_count, ComputeOperandsCount());
-  for (int i = 0; i < operands_count; i++) {
-    DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value());
-    Memory::Object_at(GetOperandSlot(i)) = store->get(i);
-  }
-}
-
 namespace {
 
 bool CannotDeoptFromAsmCode(Code* code, JSFunction* function) {
@@ -965,7 +962,7 @@
 
 FrameSummary::FrameSummary(Object* receiver, JSFunction* function,
                            AbstractCode* abstract_code, int code_offset,
-                           bool is_constructor)
+                           bool is_constructor, Mode mode)
     : receiver_(receiver, function->GetIsolate()),
       function_(function),
       abstract_code_(abstract_code),
@@ -973,7 +970,14 @@
       is_constructor_(is_constructor) {
   DCHECK(abstract_code->IsBytecodeArray() ||
          Code::cast(abstract_code)->kind() != Code::OPTIMIZED_FUNCTION ||
-         CannotDeoptFromAsmCode(Code::cast(abstract_code), function));
+         CannotDeoptFromAsmCode(Code::cast(abstract_code), function) ||
+         mode == kApproximateSummary);
+}
+
+FrameSummary FrameSummary::GetFirst(JavaScriptFrame* frame) {
+  List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
+  frame->Summarize(&frames);
+  return frames.first();
 }
 
 void FrameSummary::Print() {
@@ -987,8 +991,12 @@
     Code* code = abstract_code_->GetCode();
     if (code->kind() == Code::FUNCTION) PrintF(" UNOPT ");
     if (code->kind() == Code::OPTIMIZED_FUNCTION) {
-      DCHECK(CannotDeoptFromAsmCode(code, *function()));
-      PrintF(" ASM ");
+      if (function()->shared()->asm_function()) {
+        DCHECK(CannotDeoptFromAsmCode(code, *function()));
+        PrintF(" ASM ");
+      } else {
+        PrintF(" OPT (approximate)");
+      }
     }
   } else {
     PrintF(" BYTECODE ");
@@ -996,8 +1004,8 @@
   PrintF("\npc: %d\n", code_offset_);
 }
 
-
-void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
+void OptimizedFrame::Summarize(List<FrameSummary>* frames,
+                               FrameSummary::Mode mode) const {
   DCHECK(frames->length() == 0);
   DCHECK(is_optimized());
 
@@ -1012,6 +1020,13 @@
   DisallowHeapAllocation no_gc;
   int deopt_index = Safepoint::kNoDeoptimizationIndex;
   DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
+  if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
+    DCHECK(data == nullptr);
+    if (mode == FrameSummary::kApproximateSummary) {
+      return JavaScriptFrame::Summarize(frames, mode);
+    }
+    FATAL("Missing deoptimization information for OptimizedFrame::Summarize.");
+  }
   FixedArray* const literal_array = data->LiteralArray();
 
   TranslationIterator it(data->TranslationByteArray(),
@@ -1134,9 +1149,10 @@
 
   SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
   *deopt_index = safepoint_entry.deoptimization_index();
-  DCHECK(*deopt_index != Safepoint::kNoDeoptimizationIndex);
-
-  return DeoptimizationInputData::cast(code->deoptimization_data());
+  if (*deopt_index != Safepoint::kNoDeoptimizationIndex) {
+    return DeoptimizationInputData::cast(code->deoptimization_data());
+  }
+  return nullptr;
 }
 
 
@@ -1155,6 +1171,8 @@
   DisallowHeapAllocation no_gc;
   int deopt_index = Safepoint::kNoDeoptimizationIndex;
   DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
+  DCHECK_NOT_NULL(data);
+  DCHECK_NE(Safepoint::kNoDeoptimizationIndex, deopt_index);
   FixedArray* const literal_array = data->LiteralArray();
 
   TranslationIterator it(data->TranslationByteArray(),
@@ -1228,15 +1246,15 @@
   SetExpression(index, Smi::FromInt(raw_offset));
 }
 
-Object* InterpretedFrame::GetBytecodeArray() const {
+BytecodeArray* InterpretedFrame::GetBytecodeArray() const {
   const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
   DCHECK_EQ(
       InterpreterFrameConstants::kBytecodeArrayFromFp,
       InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
-  return GetExpression(index);
+  return BytecodeArray::cast(GetExpression(index));
 }
 
-void InterpretedFrame::PatchBytecodeArray(Object* bytecode_array) {
+void InterpretedFrame::PatchBytecodeArray(BytecodeArray* bytecode_array) {
   const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
   DCHECK_EQ(
       InterpreterFrameConstants::kBytecodeArrayFromFp,
@@ -1244,15 +1262,25 @@
   SetExpression(index, bytecode_array);
 }
 
-Object* InterpretedFrame::GetInterpreterRegister(int register_index) const {
+Object* InterpretedFrame::ReadInterpreterRegister(int register_index) const {
   const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex;
   DCHECK_EQ(
-      InterpreterFrameConstants::kRegisterFilePointerFromFp,
+      InterpreterFrameConstants::kRegisterFileFromFp,
       InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
   return GetExpression(index + register_index);
 }
 
-void InterpretedFrame::Summarize(List<FrameSummary>* functions) {
+void InterpretedFrame::WriteInterpreterRegister(int register_index,
+                                                Object* value) {
+  const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex;
+  DCHECK_EQ(
+      InterpreterFrameConstants::kRegisterFileFromFp,
+      InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
+  return SetExpression(index + register_index, value);
+}
+
+void InterpretedFrame::Summarize(List<FrameSummary>* functions,
+                                 FrameSummary::Mode mode) const {
   DCHECK(functions->length() == 0);
   AbstractCode* abstract_code =
       AbstractCode::cast(function()->shared()->bytecode_array());
@@ -1265,11 +1293,6 @@
   return Smi::cast(GetExpression(0))->value();
 }
 
-
-Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
-  return fp() + StandardFrameConstants::kCallerSPOffset;
-}
-
 int ArgumentsAdaptorFrame::GetLength(Address fp) {
   const int offset = ArgumentsAdaptorFrameConstants::kLengthOffset;
   return Smi::cast(Memory::Object_at(fp + offset))->value();
@@ -1280,6 +1303,15 @@
       Builtins::kArgumentsAdaptorTrampoline);
 }
 
+void BuiltinFrame::Print(StringStream* accumulator, PrintMode mode,
+                         int index) const {
+  // TODO(bmeurer)
+}
+
+int BuiltinFrame::GetNumberOfIncomingArguments() const {
+  return Smi::cast(GetExpression(0))->value();
+}
+
 Address InternalFrame::GetCallerStackPointer() const {
   // Internal frames have no arguments. The stack pointer of the
   // caller is at a fixed offset from the frame pointer.
@@ -1315,6 +1347,25 @@
   return fp() + ExitFrameConstants::kCallerSPOffset;
 }
 
+Object* WasmFrame::wasm_obj() {
+  FixedArray* deopt_data = LookupCode()->deoptimization_data();
+  DCHECK(deopt_data->length() == 2);
+  return deopt_data->get(0);
+}
+
+uint32_t WasmFrame::function_index() {
+  FixedArray* deopt_data = LookupCode()->deoptimization_data();
+  DCHECK(deopt_data->length() == 2);
+  Object* func_index_obj = deopt_data->get(1);
+  if (func_index_obj->IsUndefined(isolate())) return static_cast<uint32_t>(-1);
+  if (func_index_obj->IsSmi()) return Smi::cast(func_index_obj)->value();
+  DCHECK(func_index_obj->IsHeapNumber());
+  uint32_t val = static_cast<uint32_t>(-1);
+  func_index_obj->ToUint32(&val);
+  DCHECK(val != static_cast<uint32_t>(-1));
+  return val;
+}
+
 namespace {
 
 
@@ -1364,14 +1415,20 @@
       int offset = static_cast<int>(pc - code->instruction_start());
       int source_pos = code->SourcePosition(offset);
       int line = script->GetLineNumber(source_pos) + 1;
-      accumulator->Add(":%d", line);
+      accumulator->Add(":%d] [pc=%p]", line, pc);
+    } else if (is_interpreted()) {
+      const InterpretedFrame* iframe =
+          reinterpret_cast<const InterpretedFrame*>(this);
+      BytecodeArray* bytecodes = iframe->GetBytecodeArray();
+      int offset = iframe->GetBytecodeOffset();
+      int source_pos = bytecodes->SourcePosition(offset);
+      int line = script->GetLineNumber(source_pos) + 1;
+      accumulator->Add(":%d] [bytecode=%p offset=%d]", line, bytecodes, offset);
     } else {
       int function_start_pos = shared->start_position();
       int line = script->GetLineNumber(function_start_pos) + 1;
-      accumulator->Add(":~%d", line);
+      accumulator->Add(":~%d] [pc=%p]", line, pc);
     }
-
-    accumulator->Add("] [pc=%p] ", pc);
   }
 
   accumulator->Add("(this=%o", receiver);
@@ -1632,7 +1689,8 @@
   Page* page = Page::FromAddress(inner_pointer);
 
   DCHECK_EQ(page->owner(), heap->code_space());
-  heap->mark_compact_collector()->SweepOrWaitUntilSweepingCompleted(page);
+  heap->mark_compact_collector()->sweeper().SweepOrWaitUntilSweepingCompleted(
+      page);
 
   Address addr = page->skip_list()->StartFor(inner_pointer);
 
diff --git a/src/frames.h b/src/frames.h
index f6806d7..a1e438c 100644
--- a/src/frames.h
+++ b/src/frames.h
@@ -111,7 +111,8 @@
   V(STUB_FAILURE_TRAMPOLINE, StubFailureTrampolineFrame) \
   V(INTERNAL, InternalFrame)                             \
   V(CONSTRUCT, ConstructFrame)                           \
-  V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
+  V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)            \
+  V(BUILTIN, BuiltinFrame)
 
 // Every pointer in a frame has a slot id. On 32-bit platforms, doubles consume
 // two slots.
@@ -280,6 +281,14 @@
   DEFINE_TYPED_FRAME_SIZES(2);
 };
 
+class BuiltinFrameConstants : public TypedFrameConstants {
+ public:
+  // FP-relative.
+  static const int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
+  static const int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
+  DEFINE_TYPED_FRAME_SIZES(2);
+};
+
 class InternalFrameConstants : public TypedFrameConstants {
  public:
   // FP-relative.
@@ -324,31 +333,24 @@
       StandardFrameConstants::kFixedFrameSizeFromFp + 3 * kPointerSize;
 
   // FP-relative.
+  static const int kLastParamFromFp = StandardFrameConstants::kCallerSPOffset;
+  static const int kCallerPCOffsetFromFp =
+      StandardFrameConstants::kCallerPCOffset;
   static const int kNewTargetFromFp =
       -StandardFrameConstants::kFixedFrameSizeFromFp - 1 * kPointerSize;
   static const int kBytecodeArrayFromFp =
       -StandardFrameConstants::kFixedFrameSizeFromFp - 2 * kPointerSize;
   static const int kBytecodeOffsetFromFp =
       -StandardFrameConstants::kFixedFrameSizeFromFp - 3 * kPointerSize;
-  static const int kRegisterFilePointerFromFp =
+  static const int kRegisterFileFromFp =
       -StandardFrameConstants::kFixedFrameSizeFromFp - 4 * kPointerSize;
 
-  static const int kExpressionsOffset = kRegisterFilePointerFromFp;
+  static const int kExpressionsOffset = kRegisterFileFromFp;
 
   // Expression index for {StandardFrame::GetExpressionAddress}.
   static const int kBytecodeArrayExpressionIndex = -2;
   static const int kBytecodeOffsetExpressionIndex = -1;
   static const int kRegisterFileExpressionIndex = 0;
-
-  // Register file pointer relative.
-  static const int kLastParamFromRegisterPointer =
-      StandardFrameConstants::kFixedFrameSize + 4 * kPointerSize;
-
-  static const int kBytecodeOffsetFromRegisterPointer = 1 * kPointerSize;
-  static const int kBytecodeArrayFromRegisterPointer = 2 * kPointerSize;
-  static const int kNewTargetFromRegisterPointer = 3 * kPointerSize;
-  static const int kFunctionFromRegisterPointer = 4 * kPointerSize;
-  static const int kContextFromRegisterPointer = 5 * kPointerSize;
 };
 
 inline static int FPOffsetToFrameSlot(int frame_offset) {
@@ -418,6 +420,7 @@
   bool is_wasm_to_js() const { return type() == WASM_TO_JS; }
   bool is_js_to_wasm() const { return type() == JS_TO_WASM; }
   bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
+  bool is_builtin() const { return type() == BUILTIN; }
   bool is_internal() const { return type() == INTERNAL; }
   bool is_stub_failure_trampoline() const {
     return type() == STUB_FAILURE_TRAMPOLINE;
@@ -428,7 +431,7 @@
   bool is_java_script() const {
     Type type = this->type();
     return (type == JAVA_SCRIPT) || (type == OPTIMIZED) ||
-           (type == INTERPRETED);
+           (type == INTERPRETED) || (type == BUILTIN);
   }
 
   // Accessors.
@@ -640,8 +643,40 @@
   friend class StackFrameIteratorBase;
 };
 
+class JavaScriptFrame;
 
-class StandardFrame: public StackFrame {
+class FrameSummary BASE_EMBEDDED {
+ public:
+  // Mode for JavaScriptFrame::Summarize. Exact summary is required to produce
+  // an exact stack trace. It will trigger an assertion failure if that is not
+  // possible, e.g., because of missing deoptimization information. The
+  // approximate mode should produce a summary even without deoptimization
+  // information, but it might miss frames.
+  enum Mode { kExactSummary, kApproximateSummary };
+
+  FrameSummary(Object* receiver, JSFunction* function,
+               AbstractCode* abstract_code, int code_offset,
+               bool is_constructor, Mode mode = kExactSummary);
+
+  static FrameSummary GetFirst(JavaScriptFrame* frame);
+
+  Handle<Object> receiver() { return receiver_; }
+  Handle<JSFunction> function() { return function_; }
+  Handle<AbstractCode> abstract_code() { return abstract_code_; }
+  int code_offset() { return code_offset_; }
+  bool is_constructor() { return is_constructor_; }
+
+  void Print();
+
+ private:
+  Handle<Object> receiver_;
+  Handle<JSFunction> function_;
+  Handle<AbstractCode> abstract_code_;
+  int code_offset_;
+  bool is_constructor_;
+};
+
+class StandardFrame : public StackFrame {
  public:
   // Testers.
   bool is_standard() const override { return true; }
@@ -701,36 +736,19 @@
   friend class SafeStackFrameIterator;
 };
 
-
-class FrameSummary BASE_EMBEDDED {
- public:
-  FrameSummary(Object* receiver, JSFunction* function,
-               AbstractCode* abstract_code, int code_offset,
-               bool is_constructor);
-
-  Handle<Object> receiver() { return receiver_; }
-  Handle<JSFunction> function() { return function_; }
-  Handle<AbstractCode> abstract_code() { return abstract_code_; }
-  int code_offset() { return code_offset_; }
-  bool is_constructor() { return is_constructor_; }
-
-  void Print();
-
- private:
-  Handle<Object> receiver_;
-  Handle<JSFunction> function_;
-  Handle<AbstractCode> abstract_code_;
-  int code_offset_;
-  bool is_constructor_;
-};
-
 class JavaScriptFrame : public StandardFrame {
  public:
   Type type() const override { return JAVA_SCRIPT; }
 
+  // Build a list with summaries for this frame including all inlined frames.
+  virtual void Summarize(
+      List<FrameSummary>* frames,
+      FrameSummary::Mode mode = FrameSummary::kExactSummary) const;
+
   // Accessors.
-  inline JSFunction* function() const;
-  inline Object* receiver() const;
+  virtual JSFunction* function() const;
+  virtual Object* receiver() const;
+
   inline void set_receiver(Object* value);
 
   // Access the parameters.
@@ -747,7 +765,6 @@
 
   // Generator support to preserve operand stack.
   void SaveOperandStack(FixedArray* store) const;
-  void RestoreOperandStack(FixedArray* store);
 
   // Debugger access.
   void SetParameterValue(int index, Object* value) const;
@@ -778,9 +795,6 @@
   // Return a list with JSFunctions of this frame.
   virtual void GetFunctions(List<JSFunction*>* functions) const;
 
-  // Build a list with summaries for this frame including all inlined frames.
-  virtual void Summarize(List<FrameSummary>* frames);
-
   // Lookup exception handler for current {pc}, returns -1 if none found. Also
   // returns data associated with the handler site specific to the frame type:
   //  - JavaScriptFrame : Data is the stack depth at entry of the try-block.
@@ -857,7 +871,9 @@
   // is the top-most activation)
   void GetFunctions(List<JSFunction*>* functions) const override;
 
-  void Summarize(List<FrameSummary>* frames) override;
+  void Summarize(
+      List<FrameSummary>* frames,
+      FrameSummary::Mode mode = FrameSummary::kExactSummary) const override;
 
   // Lookup exception handler for current {pc}, returns -1 if none found.
   int LookupExceptionHandlerInTable(
@@ -893,17 +909,20 @@
   void PatchBytecodeOffset(int new_offset);
 
   // Returns the frame's current bytecode array.
-  Object* GetBytecodeArray() const;
+  BytecodeArray* GetBytecodeArray() const;
 
   // Updates the frame's BytecodeArray with |bytecode_array|. Used by the
   // debugger to swap execution onto a BytecodeArray patched with breakpoints.
-  void PatchBytecodeArray(Object* bytecode_array);
+  void PatchBytecodeArray(BytecodeArray* bytecode_array);
 
   // Access to the interpreter register file for this frame.
-  Object* GetInterpreterRegister(int register_index) const;
+  Object* ReadInterpreterRegister(int register_index) const;
+  void WriteInterpreterRegister(int register_index, Object* value);
 
   // Build a list with summaries for this frame including all inlined frames.
-  void Summarize(List<FrameSummary>* frames) override;
+  void Summarize(
+      List<FrameSummary>* frames,
+      FrameSummary::Mode mode = FrameSummary::kExactSummary) const override;
 
  protected:
   inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);
@@ -941,7 +960,28 @@
 
   int GetNumberOfIncomingArguments() const override;
 
-  Address GetCallerStackPointer() const override;
+ private:
+  friend class StackFrameIteratorBase;
+};
+
+// Builtin frames are built for builtins with JavaScript linkage, such as
+// various standard library functions (i.e. Math.asin, Math.floor, etc.).
+class BuiltinFrame final : public JavaScriptFrame {
+ public:
+  Type type() const final { return BUILTIN; }
+
+  static BuiltinFrame* cast(StackFrame* frame) {
+    DCHECK(frame->is_builtin());
+    return static_cast<BuiltinFrame*>(frame);
+  }
+
+  // Printing support.
+  void Print(StringStream* accumulator, PrintMode mode, int index) const final;
+
+ protected:
+  inline explicit BuiltinFrame(StackFrameIteratorBase* iterator);
+
+  int GetNumberOfIncomingArguments() const final;
 
  private:
   friend class StackFrameIteratorBase;
@@ -961,6 +1001,9 @@
   // Determine the code for the frame.
   Code* unchecked_code() const override;
 
+  Object* wasm_obj();
+  uint32_t function_index();
+
   static WasmFrame* cast(StackFrame* frame) {
     DCHECK(frame->is_wasm());
     return static_cast<WasmFrame*>(frame);
@@ -1143,17 +1186,25 @@
   StackFrameIterator iterator_;
 };
 
-// NOTE: The stack trace frame iterator is an iterator that only
-// traverse proper JavaScript frames; that is JavaScript frames that
-// have proper JavaScript functions. This excludes the problematic
-// functions in runtime.js.
-class StackTraceFrameIterator: public JavaScriptFrameIterator {
+// NOTE: The stack trace frame iterator is an iterator that only traverse proper
+// JavaScript frames that have proper JavaScript functions and WASM frames.
+// This excludes the problematic functions in runtime.js.
+class StackTraceFrameIterator BASE_EMBEDDED {
  public:
   explicit StackTraceFrameIterator(Isolate* isolate);
+  bool done() const { return iterator_.done(); }
   void Advance();
 
+  inline StandardFrame* frame() const;
+
+  inline bool is_javascript() const;
+  inline bool is_wasm() const;
+  inline JavaScriptFrame* javascript_frame() const;
+  inline WasmFrame* wasm_frame() const;
+
  private:
-  bool IsValidFrame();
+  StackFrameIterator iterator_;
+  bool IsValidFrame(StackFrame* frame) const;
 };
 
 
diff --git a/src/full-codegen/arm/full-codegen-arm.cc b/src/full-codegen/arm/full-codegen-arm.cc
index 81c5ff2..73e4750 100644
--- a/src/full-codegen/arm/full-codegen-arm.cc
+++ b/src/full-codegen/arm/full-codegen-arm.cc
@@ -176,7 +176,8 @@
       __ push(r1);
       __ Push(info->scope()->GetScopeInfo(info->isolate()));
       __ CallRuntime(Runtime::kNewScriptContext);
-      PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
+      PrepareForBailoutForId(BailoutId::ScriptContext(),
+                             BailoutState::TOS_REGISTER);
       // The new target value is not used, clobbering is safe.
       DCHECK_NULL(info->scope()->new_target_var());
     } else {
@@ -232,7 +233,8 @@
   // Register holding this function and new target are both trashed in case we
   // bailout here. But since that can happen only when new target is not used
   // and we allocate a context, the value of |function_in_register| is correct.
-  PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionContext(),
+                         BailoutState::NO_REGISTERS);
 
   // Possibly set up a local binding to the this function which is used in
   // derived constructors with super calls.
@@ -294,7 +296,8 @@
   }
 
   // Visit the declarations and body.
-  PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionEntry(),
+                         BailoutState::NO_REGISTERS);
   {
     Comment cmnt(masm_, "[ Declarations");
     VisitDeclarations(scope()->declarations());
@@ -307,7 +310,8 @@
 
   {
     Comment cmnt(masm_, "[ Stack check");
-    PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
+    PrepareForBailoutForId(BailoutId::Declarations(),
+                           BailoutState::NO_REGISTERS);
     Label ok;
     __ LoadRoot(ip, Heap::kStackLimitRootIndex);
     __ cmp(sp, Operand(ip));
@@ -405,11 +409,11 @@
   EmitProfilingCounterReset();
 
   __ bind(&ok);
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
   // Record a mapping of the OSR id to this PC.  This is used if the OSR
   // entry becomes the target of a bailout.  We don't expect it to be, but
   // we want it to work if it is.
-  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
 }
 
 void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
@@ -468,6 +472,9 @@
   }
 }
 
+void FullCodeGenerator::RestoreContext() {
+  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+}
 
 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
   DCHECK(var->IsStackAllocated() || var->IsContextSlot());
@@ -533,10 +540,12 @@
                                           true,
                                           true_label_,
                                           false_label_);
-  DCHECK(lit->IsNull() || lit->IsUndefined() || !lit->IsUndetectable());
-  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
+  DCHECK(lit->IsNull(isolate()) || lit->IsUndefined(isolate()) ||
+         !lit->IsUndetectable());
+  if (lit->IsUndefined(isolate()) || lit->IsNull(isolate()) ||
+      lit->IsFalse(isolate())) {
     if (false_label_ != fall_through_) __ b(false_label_);
-  } else if (lit->IsTrue() || lit->IsJSObject()) {
+  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
     if (true_label_ != fall_through_) __ b(true_label_);
   } else if (lit->IsString()) {
     if (String::cast(*lit)->length() == 0) {
@@ -728,7 +737,7 @@
 
   Label skip;
   if (should_normalize) __ b(&skip);
-  PrepareForBailout(expr, TOS_REG);
+  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
   if (should_normalize) {
     __ LoadRoot(ip, Heap::kTrueValueRootIndex);
     __ cmp(r0, ip);
@@ -761,15 +770,13 @@
   VariableProxy* proxy = declaration->proxy();
   VariableMode mode = declaration->mode();
   Variable* variable = proxy->var();
-  bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
+  bool hole_init = mode == LET || mode == CONST;
   switch (variable->location()) {
     case VariableLocation::GLOBAL:
     case VariableLocation::UNALLOCATED:
+      DCHECK(!variable->binding_needs_init());
       globals_->Add(variable->name(), zone());
-      globals_->Add(variable->binding_needs_init()
-                        ? isolate()->factory()->the_hole_value()
-                        : isolate()->factory()->undefined_value(),
-                    zone());
+      globals_->Add(isolate()->factory()->undefined_value(), zone());
       break;
 
     case VariableLocation::PARAMETER:
@@ -788,27 +795,18 @@
         __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
         __ str(r0, ContextMemOperand(cp, variable->index()));
         // No write barrier since the_hole_value is in old space.
-        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+        PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       }
       break;
 
     case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
+      DCHECK_EQ(VAR, mode);
+      DCHECK(!hole_init);
       __ mov(r2, Operand(variable->name()));
-      // Declaration nodes are always introduced in one of four modes.
-      DCHECK(IsDeclaredVariableMode(mode));
-      // Push initial value, if any.
-      // Note: For variables we must not push an initial value (such as
-      // 'undefined') because we may have a (legal) redeclaration and we
-      // must not destroy the current value.
-      if (hole_init) {
-        __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
-      } else {
-        __ mov(r0, Operand(Smi::FromInt(0)));  // Indicates no initial value.
-      }
-      __ Push(r2, r0);
-      __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes()));
-      __ CallRuntime(Runtime::kDeclareLookupSlot);
+      __ Push(r2);
+      __ CallRuntime(Runtime::kDeclareEvalVar);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -854,7 +852,7 @@
                                 kDontSaveFPRegs,
                                 EMIT_REMEMBERED_SET,
                                 OMIT_SMI_CHECK);
-      PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
 
@@ -864,8 +862,8 @@
       PushOperand(r2);
       // Push initial value for function declaration.
       VisitForStackValue(declaration->fun());
-      PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
-      CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
+      CallRuntimeWithOperands(Runtime::kDeclareEvalFunction);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -897,7 +895,7 @@
 
   // Keep the switch value on the stack until a case matches.
   VisitForStackValue(stmt->tag());
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
 
   ZoneList<CaseClause*>* clauses = stmt->cases();
   CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
@@ -946,7 +944,7 @@
 
     Label skip;
     __ b(&skip);
-    PrepareForBailout(clause, TOS_REG);
+    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
     __ LoadRoot(ip, Heap::kTrueValueRootIndex);
     __ cmp(r0, ip);
     __ b(ne, &next_test);
@@ -975,12 +973,12 @@
     Comment cmnt(masm_, "[ Case body");
     CaseClause* clause = clauses->at(i);
     __ bind(clause->body_target());
-    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
+    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
     VisitStatements(clause->statements());
   }
 
   __ bind(nested_statement.break_label());
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
 }
 
 
@@ -1013,15 +1011,13 @@
   ToObjectStub stub(isolate());
   __ CallStub(&stub);
   __ bind(&done_convert);
-  PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
+  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
   __ push(r0);
 
-  // Check cache validity in generated code. This is a fast case for
-  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
-  // guarantee cache validity, call the runtime system to check cache
-  // validity or get the property names in a fixed array.
-  // Note: Proxies never have an enum cache, so will always take the
-  // slow path.
+  // Check cache validity in generated code. If we cannot guarantee cache
+  // validity, call the runtime system to check cache validity or get the
+  // property names in a fixed array. Note: Proxies never have an enum cache,
+  // so will always take the slow path.
   Label call_runtime;
   __ CheckEnumCache(&call_runtime);
 
@@ -1035,7 +1031,7 @@
   __ bind(&call_runtime);
   __ push(r0);  // Duplicate the enumerable object on the stack.
   __ CallRuntime(Runtime::kForInEnumerate);
-  PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
+  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
 
   // If we got a map from the runtime call, we can do a fast
   // modification check. Otherwise, we got a fixed array, and we have
@@ -1076,7 +1072,7 @@
   __ Push(r1, r0);  // Smi and array
   __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset));
   __ Push(r1);  // Fixed array length (as smi).
-  PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
   __ mov(r0, Operand(Smi::FromInt(0)));
   __ Push(r0);  // Initial index.
 
@@ -1118,7 +1114,7 @@
   __ push(r1);  // Enumerable.
   __ push(r3);  // Current entry.
   __ CallRuntime(Runtime::kForInFilter);
-  PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
+  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
   __ mov(r3, Operand(r0));
   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
   __ cmp(r0, ip);
@@ -1131,11 +1127,11 @@
   // Perform the assignment as if via '='.
   { EffectContext context(this);
     EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
-    PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
+    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
   }
 
   // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
-  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
   // Generate code for the body of the loop.
   Visit(stmt->body());
 
@@ -1154,7 +1150,7 @@
   DropOperands(5);
 
   // Exit and decrement the loop depth.
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   __ bind(&exit);
   decrement_loop_depth();
 }
@@ -1284,17 +1280,12 @@
   } else if (var->mode() == DYNAMIC_LOCAL) {
     Variable* local = var->local_if_not_shadowed();
     __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow));
-    if (local->mode() == LET || local->mode() == CONST ||
-        local->mode() == CONST_LEGACY) {
+    if (local->mode() == LET || local->mode() == CONST) {
       __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
-      if (local->mode() == CONST_LEGACY) {
-        __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
-      } else {  // LET || CONST
-        __ b(ne, done);
-        __ mov(r0, Operand(var->name()));
-        __ push(r0);
-        __ CallRuntime(Runtime::kThrowReferenceError);
-      }
+      __ b(ne, done);
+      __ mov(r0, Operand(var->name()));
+      __ push(r0);
+      __ CallRuntime(Runtime::kThrowReferenceError);
     }
     __ jmp(done);
   }
@@ -1303,14 +1294,14 @@
 
 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
                                                TypeofMode typeof_mode) {
+#ifdef DEBUG
   Variable* var = proxy->var();
   DCHECK(var->IsUnallocatedOrGlobalSlot() ||
          (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
-  __ LoadGlobalObject(LoadDescriptor::ReceiverRegister());
-  __ mov(LoadDescriptor::NameRegister(), Operand(var->name()));
-  __ mov(LoadDescriptor::SlotRegister(),
+#endif
+  __ mov(LoadGlobalDescriptor::SlotRegister(),
          Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
-  CallLoadIC(typeof_mode);
+  CallLoadGlobalIC(typeof_mode);
 }
 
 
@@ -1318,7 +1309,7 @@
                                          TypeofMode typeof_mode) {
   // Record position before possible IC call.
   SetExpressionPosition(proxy);
-  PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
+  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
   Variable* var = proxy->var();
 
   // Three cases: global variables, lookup variables, and all other types of
@@ -1351,10 +1342,6 @@
           __ push(r0);
           __ CallRuntime(Runtime::kThrowReferenceError);
           __ bind(&done);
-        } else {
-          // Uninitialized legacy const bindings are unholed.
-          DCHECK(var->mode() == CONST_LEGACY);
-          __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
         }
         context()->Plug(r0);
         break;
@@ -1383,18 +1370,6 @@
 }
 
 
-void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
-  Comment cmnt(masm_, "[ RegExpLiteral");
-  __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
-  __ mov(r1, Operand(expr->pattern()));
-  __ mov(r0, Operand(Smi::FromInt(expr->flags())));
-  FastCloneRegExpStub stub(isolate());
-  __ CallStub(&stub);
-  context()->Plug(r0);
-}
-
-
 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
   Expression* expression = (property == NULL) ? NULL : property->value();
   if (expression == NULL) {
@@ -1427,8 +1402,9 @@
   } else {
     FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
     __ CallStub(&stub);
+    RestoreContext();
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   // If result_saved is true the result is on top of the stack.  If
   // result_saved is false the result is in r0.
@@ -1464,7 +1440,7 @@
             __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
             EmitLoadStoreICSlot(property->GetSlot(0));
             CallStoreIC();
-            PrepareForBailoutForId(key->id(), NO_REGISTERS);
+            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
 
             if (NeedsHomeObject(value)) {
               EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
@@ -1498,17 +1474,21 @@
         DCHECK(property->emit_store());
         CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
         PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                               NO_REGISTERS);
+                               BailoutState::NO_REGISTERS);
         break;
 
       case ObjectLiteral::Property::GETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->getter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->getter = property;
         }
         break;
       case ObjectLiteral::Property::SETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->setter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->setter = property;
         }
         break;
     }
@@ -1527,6 +1507,7 @@
     __ mov(r0, Operand(Smi::FromInt(NONE)));
     PushOperand(r0);
     CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
+    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
   }
 
   // Object literals have two parts. The "static" part on the left contains no
@@ -1556,7 +1537,7 @@
       DCHECK(property->emit_store());
       CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
       PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                             NO_REGISTERS);
+                             BailoutState::NO_REGISTERS);
     } else {
       EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
       VisitForStackValue(value);
@@ -1572,6 +1553,8 @@
             PushOperand(Smi::FromInt(NONE));
             PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
             CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
+            PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
+                                   BailoutState::NO_REGISTERS);
           } else {
             DropOperands(3);
           }
@@ -1629,7 +1612,7 @@
     FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
     __ CallStub(&stub);
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   bool result_saved = false;  // Is the result saved to the stack?
   ZoneList<Expression*>* subexprs = expr->values();
@@ -1659,7 +1642,8 @@
         CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
     CallIC(ic);
 
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   // In case the array literal contains spread expressions it has two parts. The
@@ -1679,7 +1663,8 @@
     VisitForStackValue(subexpr);
     CallRuntimeWithOperands(Runtime::kAppendElement);
 
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   if (result_saved) {
@@ -1694,7 +1679,6 @@
   DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
 
   Comment cmnt(masm_, "[ Assignment");
-  SetExpressionPosition(expr, INSERT_BREAK);
 
   Property* property = expr->target()->AsProperty();
   LhsKind assign_type = Property::GetAssignType(property);
@@ -1763,23 +1747,27 @@
       switch (assign_type) {
         case VARIABLE:
           EmitVariableLoad(expr->target()->AsVariableProxy());
-          PrepareForBailout(expr->target(), TOS_REG);
+          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
           break;
         case NAMED_PROPERTY:
           EmitNamedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case NAMED_SUPER_PROPERTY:
           EmitNamedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_SUPER_PROPERTY:
           EmitKeyedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_PROPERTY:
           EmitKeyedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
       }
     }
@@ -1799,7 +1787,7 @@
     }
 
     // Deoptimization point in case the binary operation may have side effects.
-    PrepareForBailout(expr->binary_operation(), TOS_REG);
+    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
   } else {
     VisitForAccumulatorValue(expr->value());
   }
@@ -1811,7 +1799,7 @@
     case VARIABLE:
       EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
                              expr->op(), expr->AssignmentSlot());
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       context()->Plug(r0);
       break;
     case NAMED_PROPERTY:
@@ -1840,21 +1828,26 @@
   // this.  It stays on the stack while we update the iterator.
   VisitForStackValue(expr->expression());
 
-  Label suspend, continuation, post_runtime, resume;
+  Label suspend, continuation, post_runtime, resume, exception;
 
   __ jmp(&suspend);
   __ bind(&continuation);
-  // When we arrive here, the stack top is the resume mode and
-  // result_register() holds the input value (the argument given to the
-  // respective resume operation).
+  // When we arrive here, r0 holds the generator object.
   __ RecordGeneratorContinuation();
-  __ pop(r1);
-  __ cmp(r1, Operand(Smi::FromInt(JSGeneratorObject::RETURN)));
-  __ b(ne, &resume);
-  __ push(result_register());
+  __ ldr(r1, FieldMemOperand(r0, JSGeneratorObject::kResumeModeOffset));
+  __ ldr(r0, FieldMemOperand(r0, JSGeneratorObject::kInputOrDebugPosOffset));
+  STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
+  STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
+  __ cmp(r1, Operand(Smi::FromInt(JSGeneratorObject::kReturn)));
+  __ b(lt, &resume);
+  __ Push(result_register());
+  __ b(gt, &exception);
   EmitCreateIteratorResult(true);
   EmitUnwindAndReturn();
 
+  __ bind(&exception);
+  __ CallRuntime(Runtime::kThrow);
+
   __ bind(&suspend);
   OperandStackDepthIncrement(1);  // Not popped on this path.
   VisitForAccumulatorValue(expr->generator_object());
@@ -1870,7 +1863,7 @@
   __ b(eq, &post_runtime);
   __ push(r0);  // generator object
   __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   __ bind(&post_runtime);
   PopOperand(result_register());
   EmitReturnSequence();
@@ -1879,113 +1872,6 @@
   context()->Plug(result_register());
 }
 
-
-void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
-    Expression *value,
-    JSGeneratorObject::ResumeMode resume_mode) {
-  // The value stays in r0, and is ultimately read by the resumed generator, as
-  // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it
-  // is read to throw the value when the resumed generator is already closed.
-  // r1 will hold the generator object until the activation has been resumed.
-  VisitForStackValue(generator);
-  VisitForAccumulatorValue(value);
-  PopOperand(r1);
-
-  // Store input value into generator object.
-  __ str(result_register(),
-         FieldMemOperand(r1, JSGeneratorObject::kInputOffset));
-  __ mov(r2, result_register());
-  __ RecordWriteField(r1, JSGeneratorObject::kInputOffset, r2, r3,
-                      kLRHasBeenSaved, kDontSaveFPRegs);
-
-  // Load suspended function and context.
-  __ ldr(cp, FieldMemOperand(r1, JSGeneratorObject::kContextOffset));
-  __ ldr(r4, FieldMemOperand(r1, JSGeneratorObject::kFunctionOffset));
-
-  // Load receiver and store as the first argument.
-  __ ldr(r2, FieldMemOperand(r1, JSGeneratorObject::kReceiverOffset));
-  __ push(r2);
-
-  // Push holes for arguments to generator function. Since the parser forced
-  // context allocation for any variables in generators, the actual argument
-  // values have already been copied into the context and these dummy values
-  // will never be used.
-  __ ldr(r3, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
-  __ ldr(r3,
-         FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ LoadRoot(r2, Heap::kTheHoleValueRootIndex);
-  Label push_argument_holes, push_frame;
-  __ bind(&push_argument_holes);
-  __ sub(r3, r3, Operand(Smi::FromInt(1)), SetCC);
-  __ b(mi, &push_frame);
-  __ push(r2);
-  __ jmp(&push_argument_holes);
-
-  // Enter a new JavaScript frame, and initialize its slots as they were when
-  // the generator was suspended.
-  Label resume_frame, done;
-  __ bind(&push_frame);
-  __ bl(&resume_frame);
-  __ jmp(&done);
-  __ bind(&resume_frame);
-  // lr = return address.
-  // fp = caller's frame pointer.
-  // pp = caller's constant pool (if FLAG_enable_embedded_constant_pool),
-  // cp = callee's context,
-  // r4 = callee's JS function.
-  __ PushStandardFrame(r4);
-
-  // Load the operand stack size.
-  __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset));
-  __ ldr(r3, FieldMemOperand(r3, FixedArray::kLengthOffset));
-  __ SmiUntag(r3);
-
-  // If we are sending a value and there is no operand stack, we can jump back
-  // in directly.
-  if (resume_mode == JSGeneratorObject::NEXT) {
-    Label slow_resume;
-    __ cmp(r3, Operand(0));
-    __ b(ne, &slow_resume);
-    __ ldr(r3, FieldMemOperand(r4, JSFunction::kCodeEntryOffset));
-
-    { ConstantPoolUnavailableScope constant_pool_unavailable(masm_);
-      if (FLAG_enable_embedded_constant_pool) {
-        // Load the new code object's constant pool pointer.
-        __ LoadConstantPoolPointerRegisterFromCodeTargetAddress(r3);
-      }
-
-      __ ldr(r2, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset));
-      __ SmiUntag(r2);
-      __ add(r3, r3, r2);
-      __ mov(r2, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
-      __ str(r2, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset));
-      __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-      __ Jump(r3);
-    }
-    __ bind(&slow_resume);
-  }
-
-  // Otherwise, we push holes for the operand stack and call the runtime to fix
-  // up the stack and the handlers.
-  Label push_operand_holes, call_resume;
-  __ bind(&push_operand_holes);
-  __ sub(r3, r3, Operand(1), SetCC);
-  __ b(mi, &call_resume);
-  __ push(r2);
-  __ b(&push_operand_holes);
-  __ bind(&call_resume);
-  __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-  DCHECK(!result_register().is(r1));
-  __ Push(r1, result_register());
-  __ Push(Smi::FromInt(resume_mode));
-  __ CallRuntime(Runtime::kResumeJSGeneratorObject);
-  // Not reached: the runtime call returns elsewhere.
-  __ stop("not-reached");
-
-  __ bind(&done);
-  context()->Plug(result_register());
-}
-
 void FullCodeGenerator::PushOperands(Register reg1, Register reg2) {
   OperandStackDepthIncrement(2);
   __ Push(reg1, reg2);
@@ -2009,7 +1895,8 @@
 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
   Label allocate, done_allocate;
 
-  __ Allocate(JSIteratorResult::kSize, r0, r2, r3, &allocate, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, r0, r2, r3, &allocate,
+              NO_ALLOCATION_FLAGS);
   __ b(&done_allocate);
 
   __ bind(&allocate);
@@ -2336,8 +2223,7 @@
     __ bind(&uninitialized_this);
     EmitStoreToStackLocalOrContextSlot(var, location);
 
-  } else if (!var->is_const_mode() ||
-             (var->mode() == CONST && op == Token::INIT)) {
+  } else if (!var->is_const_mode() || op == Token::INIT) {
     if (var->IsLookupSlot()) {
       // Assignment to var.
       __ Push(var->name());
@@ -2359,25 +2245,6 @@
       EmitStoreToStackLocalOrContextSlot(var, location);
     }
 
-  } else if (var->mode() == CONST_LEGACY && op == Token::INIT) {
-    // Const initializers need a write barrier.
-    DCHECK(!var->IsParameter());  // No const parameters.
-    if (var->IsLookupSlot()) {
-      __ push(r0);
-      __ mov(r0, Operand(var->name()));
-      __ Push(cp, r0);  // Context and name.
-      __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot);
-    } else {
-      DCHECK(var->IsStackAllocated() || var->IsContextSlot());
-      Label skip;
-      MemOperand location = VarOperand(var, r1);
-      __ ldr(r2, location);
-      __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
-      __ b(ne, &skip);
-      EmitStoreToStackLocalOrContextSlot(var, location);
-      __ bind(&skip);
-    }
-
   } else {
     DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT);
     if (is_strict(language_mode())) {
@@ -2400,7 +2267,7 @@
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallStoreIC();
 
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(r0);
 }
 
@@ -2445,44 +2312,7 @@
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallIC(ic);
 
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
-  context()->Plug(r0);
-}
-
-
-void FullCodeGenerator::VisitProperty(Property* expr) {
-  Comment cmnt(masm_, "[ Property");
-  SetExpressionPosition(expr);
-
-  Expression* key = expr->key();
-
-  if (key->IsPropertyName()) {
-    if (!expr->IsSuperAccess()) {
-      VisitForAccumulatorValue(expr->obj());
-      __ Move(LoadDescriptor::ReceiverRegister(), r0);
-      EmitNamedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      EmitNamedSuperPropertyLoad(expr);
-    }
-  } else {
-    if (!expr->IsSuperAccess()) {
-      VisitForStackValue(expr->obj());
-      VisitForAccumulatorValue(expr->key());
-      __ Move(LoadDescriptor::NameRegister(), r0);
-      PopOperand(LoadDescriptor::ReceiverRegister());
-      EmitKeyedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      VisitForStackValue(expr->key());
-      EmitKeyedSuperPropertyLoad(expr);
-    }
-  }
-  PrepareForBailoutForId(expr->LoadId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(r0);
 }
 
@@ -2506,7 +2336,7 @@
   if (callee->IsVariableProxy()) {
     { StackValueContext context(this);
       EmitVariableLoad(callee->AsVariableProxy());
-      PrepareForBailout(callee, NO_REGISTERS);
+      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
     }
     // Push undefined as receiver. This is patched in the method prologue if it
     // is a sloppy mode method.
@@ -2519,7 +2349,8 @@
     DCHECK(!callee->AsProperty()->IsSuperAccess());
     __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
     EmitNamedPropertyLoad(callee->AsProperty());
-    PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                           BailoutState::TOS_REGISTER);
     // Push the target function under the receiver.
     __ ldr(ip, MemOperand(sp, 0));
     PushOperand(ip);
@@ -2558,6 +2389,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ str(r0, MemOperand(sp, kPointerSize));
@@ -2582,7 +2414,8 @@
   __ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
   __ Move(LoadDescriptor::NameRegister(), r0);
   EmitKeyedPropertyLoad(callee->AsProperty());
-  PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                         BailoutState::TOS_REGISTER);
 
   // Push the target function under the receiver.
   __ ldr(ip, MemOperand(sp, 0));
@@ -2618,6 +2451,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ str(r0, MemOperand(sp, kPointerSize));
@@ -2637,7 +2471,7 @@
     VisitForStackValue(args->at(i));
   }
 
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   SetCallPosition(expr, expr->tail_call_mode());
   if (expr->tail_call_mode() == TailCallMode::kAllow) {
     if (FLAG_trace) {
@@ -2658,13 +2492,12 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-  // Restore context register.
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->DropAndPlug(1, r0);
 }
 
-
-void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
+void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
+  int arg_count = expr->arguments()->length();
   // r4: copy of the first argument or undefined if it doesn't exist.
   if (arg_count > 0) {
     __ ldr(r4, MemOperand(sp, arg_count * kPointerSize));
@@ -2681,8 +2514,11 @@
   // r1: the start position of the scope the calls resides in.
   __ mov(r1, Operand(Smi::FromInt(scope()->start_position())));
 
+  // r0: the source position of the eval call.
+  __ mov(r0, Operand(Smi::FromInt(expr->position())));
+
   // Do the runtime call.
-  __ Push(r4, r3, r2, r1);
+  __ Push(r4, r3, r2, r1, r0);
   __ CallRuntime(Runtime::kResolvePossiblyDirectEval);
 }
 
@@ -2703,7 +2539,7 @@
     __ Push(callee->name());
     __ CallRuntime(Runtime::kLoadLookupSlotForCall);
     PushOperands(r0, r1);  // Function, receiver.
-    PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
+    PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
 
     // If fast case code has been generated, emit code to push the
     // function and receiver and have the slow path jump around this
@@ -2731,7 +2567,7 @@
 
 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
   // In a call to eval, we first call
-  // RuntimeHidden_asResolvePossiblyDirectEval to resolve the function we need
+  // Runtime_ResolvePossiblyDirectEval to resolve the function we need
   // to call.  Then we call the resolved function using the given arguments.
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
@@ -2747,12 +2583,12 @@
   // resolve eval.
   __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
   __ push(r1);
-  EmitResolvePossiblyDirectEval(arg_count);
+  EmitResolvePossiblyDirectEval(expr);
 
   // Touch up the stack with the resolved function.
   __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
 
-  PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
 
   // Record source position for debugger.
   SetCallPosition(expr);
@@ -2763,8 +2599,7 @@
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
   RecordJSReturnSite(expr);
-  // Restore context register.
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->DropAndPlug(1, r0);
 }
 
@@ -2803,9 +2638,8 @@
   CallConstructStub stub(isolate());
   __ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
-  // Restore context register.
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
+  RestoreContext();
   context()->Plug(r0);
 }
 
@@ -2848,9 +2682,7 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-
-  // Restore context register.
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->Plug(r0);
 }
 
@@ -3055,73 +2887,6 @@
 }
 
 
-void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = r0;
-  Register index = r1;
-  Register value = r2;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-  PopOperands(index, value);
-
-  if (FLAG_debug_code) {
-    __ SmiTst(value);
-    __ Check(eq, kNonSmiValue);
-    __ SmiTst(index);
-    __ Check(eq, kNonSmiIndex);
-    __ SmiUntag(index, index);
-    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
-    __ SmiTag(index, index);
-  }
-
-  __ SmiUntag(value, value);
-  __ add(ip,
-         string,
-         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
-  __ strb(value, MemOperand(ip, index, LSR, kSmiTagSize));
-  context()->Plug(string);
-}
-
-
-void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = r0;
-  Register index = r1;
-  Register value = r2;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-  PopOperands(index, value);
-
-  if (FLAG_debug_code) {
-    __ SmiTst(value);
-    __ Check(eq, kNonSmiValue);
-    __ SmiTst(index);
-    __ Check(eq, kNonSmiIndex);
-    __ SmiUntag(index, index);
-    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
-    __ SmiTag(index, index);
-  }
-
-  __ SmiUntag(value, value);
-  __ add(ip,
-         string,
-         Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
-  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
-  __ strh(value, MemOperand(ip, index));
-  context()->Plug(string);
-}
-
-
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
@@ -3155,13 +2920,8 @@
   Label need_conversion;
   Label index_out_of_range;
   Label done;
-  StringCharCodeAtGenerator generator(object,
-                                      index,
-                                      result,
-                                      &need_conversion,
-                                      &need_conversion,
-                                      &index_out_of_range,
-                                      STRING_INDEX_IS_NUMBER);
+  StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
+                                      &need_conversion, &index_out_of_range);
   generator.GenerateFast(masm_);
   __ jmp(&done);
 
@@ -3185,53 +2945,6 @@
 }
 
 
-void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK(args->length() == 2);
-  VisitForStackValue(args->at(0));
-  VisitForAccumulatorValue(args->at(1));
-
-  Register object = r1;
-  Register index = r0;
-  Register scratch = r3;
-  Register result = r0;
-
-  PopOperand(object);
-
-  Label need_conversion;
-  Label index_out_of_range;
-  Label done;
-  StringCharAtGenerator generator(object,
-                                  index,
-                                  scratch,
-                                  result,
-                                  &need_conversion,
-                                  &need_conversion,
-                                  &index_out_of_range,
-                                  STRING_INDEX_IS_NUMBER);
-  generator.GenerateFast(masm_);
-  __ jmp(&done);
-
-  __ bind(&index_out_of_range);
-  // When the index is out of range, the spec requires us to return
-  // the empty string.
-  __ LoadRoot(result, Heap::kempty_stringRootIndex);
-  __ jmp(&done);
-
-  __ bind(&need_conversion);
-  // Move smi zero into the result register, which will trigger
-  // conversion.
-  __ mov(result, Operand(Smi::FromInt(0)));
-  __ jmp(&done);
-
-  NopRuntimeCallHelper call_helper;
-  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
-
-  __ bind(&done);
-  context()->Plug(result);
-}
-
-
 void FullCodeGenerator::EmitCall(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK_LE(2, args->length());
@@ -3239,7 +2952,7 @@
   for (Expression* const arg : *args) {
     VisitForStackValue(arg);
   }
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   // Move target to r1.
   int const argc = args->length() - 2;
   __ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize));
@@ -3247,8 +2960,7 @@
   __ mov(r0, Operand(argc));
   __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(argc + 1);
-  // Restore context register.
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   // Discard the function left on TOS.
   context()->DropAndPlug(1, r0);
 }
@@ -3298,12 +3010,6 @@
   context()->Plug(r0);
 }
 
-void FullCodeGenerator::EmitGetOrdinaryHasInstance(CallRuntime* expr) {
-  DCHECK_EQ(0, expr->arguments()->length());
-  __ LoadNativeContextSlot(Context::ORDINARY_HAS_INSTANCE_INDEX, r0);
-  context()->Plug(r0);
-}
-
 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
   DCHECK(expr->arguments()->length() == 0);
   ExternalReference debug_is_active =
@@ -3323,7 +3029,8 @@
 
   Label runtime, done;
 
-  __ Allocate(JSIteratorResult::kSize, r0, r2, r3, &runtime, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, r0, r2, r3, &runtime,
+              NO_ALLOCATION_FLAGS);
   __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, r1);
   __ pop(r3);
   __ pop(r2);
@@ -3365,9 +3072,7 @@
   __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-
-  // Restore context register.
-  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
 }
 
 
@@ -3451,12 +3156,14 @@
                         &materialize_true);
         if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
         __ bind(&materialize_true);
-        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeTrueId(),
+                               BailoutState::NO_REGISTERS);
         __ LoadRoot(r0, Heap::kTrueValueRootIndex);
         if (context()->IsStackValue()) __ push(r0);
         __ jmp(&done);
         __ bind(&materialize_false);
-        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeFalseId(),
+                               BailoutState::NO_REGISTERS);
         __ LoadRoot(r0, Heap::kFalseValueRootIndex);
         if (context()->IsStackValue()) __ push(r0);
         __ bind(&done);
@@ -3558,9 +3265,9 @@
   // We need a second deoptimization point after loading the value
   // in case evaluating the property load my have a side effect.
   if (assign_type == VARIABLE) {
-    PrepareForBailout(expr->expression(), TOS_REG);
+    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
   } else {
-    PrepareForBailoutForId(prop->LoadId(), TOS_REG);
+    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
   }
 
   // Inline smi case if we are in a loop.
@@ -3607,9 +3314,8 @@
   }
 
   // Convert old value into a number.
-  ToNumberStub convert_stub(isolate());
-  __ CallStub(&convert_stub);
-  PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
+  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
+  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
 
   // Save result for postfix expressions.
   if (expr->is_postfix()) {
@@ -3656,7 +3362,8 @@
         { EffectContext context(this);
           EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                  Token::ASSIGN, expr->CountSlot());
-          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+          PrepareForBailoutForId(expr->AssignmentId(),
+                                 BailoutState::TOS_REGISTER);
           context.Plug(r0);
         }
         // For all contexts except EffectConstant We have the result on
@@ -3667,7 +3374,8 @@
       } else {
         EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                Token::ASSIGN, expr->CountSlot());
-        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+        PrepareForBailoutForId(expr->AssignmentId(),
+                               BailoutState::TOS_REGISTER);
         context()->Plug(r0);
       }
       break;
@@ -3677,7 +3385,7 @@
       PopOperand(StoreDescriptor::ReceiverRegister());
       EmitLoadStoreICSlot(expr->CountSlot());
       CallStoreIC();
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         if (!context()->IsEffect()) {
           context()->PlugTOS();
@@ -3716,7 +3424,7 @@
           CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
       EmitLoadStoreICSlot(expr->CountSlot());
       CallIC(ic);
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         if (!context()->IsEffect()) {
           context()->PlugTOS();
@@ -3813,7 +3521,6 @@
 
 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
   Comment cmnt(masm_, "[ CompareOperation");
-  SetExpressionPosition(expr);
 
   // First we try a fast inlined version of the compare when one of
   // the operands is a literal.
@@ -3833,7 +3540,8 @@
   switch (op) {
     case Token::IN:
       VisitForStackValue(expr->right());
-      CallRuntimeWithOperands(Runtime::kHasProperty);
+      SetExpressionPosition(expr);
+      EmitHasProperty();
       PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
       __ CompareRoot(r0, Heap::kTrueValueRootIndex);
       Split(eq, if_true, if_false, fall_through);
@@ -3841,6 +3549,7 @@
 
     case Token::INSTANCEOF: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       PopOperand(r1);
       InstanceOfStub stub(isolate());
       __ CallStub(&stub);
@@ -3852,6 +3561,7 @@
 
     default: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       Condition cond = CompareIC::ComputeCondition(op);
       PopOperand(r1);
 
diff --git a/src/full-codegen/arm64/full-codegen-arm64.cc b/src/full-codegen/arm64/full-codegen-arm64.cc
index aa67117..7848d0d 100644
--- a/src/full-codegen/arm64/full-codegen-arm64.cc
+++ b/src/full-codegen/arm64/full-codegen-arm64.cc
@@ -179,7 +179,8 @@
       __ Mov(x10, Operand(info->scope()->GetScopeInfo(info->isolate())));
       __ Push(x1, x10);
       __ CallRuntime(Runtime::kNewScriptContext);
-      PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
+      PrepareForBailoutForId(BailoutId::ScriptContext(),
+                             BailoutState::TOS_REGISTER);
       // The new target value is not used, clobbering is safe.
       DCHECK_NULL(info->scope()->new_target_var());
     } else {
@@ -235,7 +236,8 @@
   // Register holding this function and new target are both trashed in case we
   // bailout here. But since that can happen only when new target is not used
   // and we allocate a context, the value of |function_in_register| is correct.
-  PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionContext(),
+                         BailoutState::NO_REGISTERS);
 
   // Possibly set up a local binding to the this function which is used in
   // derived constructors with super calls.
@@ -297,7 +299,8 @@
   }
 
   // Visit the declarations and body.
-  PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionEntry(),
+                         BailoutState::NO_REGISTERS);
   {
     Comment cmnt(masm_, "[ Declarations");
     VisitDeclarations(scope()->declarations());
@@ -310,7 +313,8 @@
 
   {
     Comment cmnt(masm_, "[ Stack check");
-    PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
+    PrepareForBailoutForId(BailoutId::Declarations(),
+                           BailoutState::NO_REGISTERS);
     Label ok;
     DCHECK(jssp.Is(__ StackPointer()));
     __ CompareRoot(jssp, Heap::kStackLimitRootIndex);
@@ -393,11 +397,11 @@
   EmitProfilingCounterReset();
 
   __ Bind(&ok);
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
   // Record a mapping of the OSR id to this PC.  This is used if the OSR
   // entry becomes the target of a bailout.  We don't expect it to be, but
   // we want it to work if it is.
-  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
 }
 
 void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
@@ -460,6 +464,9 @@
   }
 }
 
+void FullCodeGenerator::RestoreContext() {
+  __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+}
 
 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
   DCHECK(var->IsStackAllocated() || var->IsContextSlot());
@@ -524,10 +531,12 @@
                                           true,
                                           true_label_,
                                           false_label_);
-  DCHECK(lit->IsNull() || lit->IsUndefined() || !lit->IsUndetectable());
-  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
+  DCHECK(lit->IsNull(isolate()) || lit->IsUndefined(isolate()) ||
+         !lit->IsUndetectable());
+  if (lit->IsUndefined(isolate()) || lit->IsNull(isolate()) ||
+      lit->IsFalse(isolate())) {
     if (false_label_ != fall_through_) __ B(false_label_);
-  } else if (lit->IsTrue() || lit->IsJSObject()) {
+  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
     if (true_label_ != fall_through_) __ B(true_label_);
   } else if (lit->IsString()) {
     if (String::cast(*lit)->length() == 0) {
@@ -725,7 +734,7 @@
   if (should_normalize) {
     __ B(&skip);
   }
-  PrepareForBailout(expr, TOS_REG);
+  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
   if (should_normalize) {
     __ CompareRoot(x0, Heap::kTrueValueRootIndex);
     Split(eq, if_true, if_false, NULL);
@@ -757,16 +766,14 @@
   VariableProxy* proxy = declaration->proxy();
   VariableMode mode = declaration->mode();
   Variable* variable = proxy->var();
-  bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
+  bool hole_init = mode == LET || mode == CONST;
 
   switch (variable->location()) {
     case VariableLocation::GLOBAL:
     case VariableLocation::UNALLOCATED:
+      DCHECK(!variable->binding_needs_init());
       globals_->Add(variable->name(), zone());
-      globals_->Add(variable->binding_needs_init()
-                        ? isolate()->factory()->the_hole_value()
-                        : isolate()->factory()->undefined_value(),
-                    zone());
+      globals_->Add(isolate()->factory()->undefined_value(), zone());
       break;
 
     case VariableLocation::PARAMETER:
@@ -785,28 +792,18 @@
         __ LoadRoot(x10, Heap::kTheHoleValueRootIndex);
         __ Str(x10, ContextMemOperand(cp, variable->index()));
         // No write barrier since the_hole_value is in old space.
-        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+        PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       }
       break;
 
     case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
+      DCHECK_EQ(VAR, mode);
+      DCHECK(!hole_init);
       __ Mov(x2, Operand(variable->name()));
-      // Declaration nodes are always introduced in one of four modes.
-      DCHECK(IsDeclaredVariableMode(mode));
-      // Push initial value, if any.
-      // Note: For variables we must not push an initial value (such as
-      // 'undefined') because we may have a (legal) redeclaration and we
-      // must not destroy the current value.
-      if (hole_init) {
-        __ LoadRoot(x0, Heap::kTheHoleValueRootIndex);
-        __ Push(x2, x0);
-      } else {
-        // Pushing 0 (xzr) indicates no initial value.
-        __ Push(x2, xzr);
-      }
-      __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes()));
-      __ CallRuntime(Runtime::kDeclareLookupSlot);
+      __ Push(x2);
+      __ CallRuntime(Runtime::kDeclareEvalVar);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -852,7 +849,7 @@
                                 kDontSaveFPRegs,
                                 EMIT_REMEMBERED_SET,
                                 OMIT_SMI_CHECK);
-      PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
 
@@ -862,8 +859,8 @@
       PushOperand(x2);
       // Push initial value for function declaration.
       VisitForStackValue(declaration->fun());
-      PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
-      CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
+      CallRuntimeWithOperands(Runtime::kDeclareEvalFunction);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -900,7 +897,7 @@
 
   // Keep the switch value on the stack until a case matches.
   VisitForStackValue(stmt->tag());
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
 
   ZoneList<CaseClause*>* clauses = stmt->cases();
   CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
@@ -947,7 +944,7 @@
 
     Label skip;
     __ B(&skip);
-    PrepareForBailout(clause, TOS_REG);
+    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
     __ JumpIfNotRoot(x0, Heap::kTrueValueRootIndex, &next_test);
     __ Drop(1);
     __ B(clause->body_target());
@@ -973,12 +970,12 @@
     Comment cmnt(masm_, "[ Case body");
     CaseClause* clause = clauses->at(i);
     __ Bind(clause->body_target());
-    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
+    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
     VisitStatements(clause->statements());
   }
 
   __ Bind(nested_statement.break_label());
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
 }
 
 
@@ -1011,15 +1008,13 @@
   ToObjectStub stub(isolate());
   __ CallStub(&stub);
   __ Bind(&done_convert);
-  PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
+  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
   __ Push(x0);
 
-  // Check cache validity in generated code. This is a fast case for
-  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
-  // guarantee cache validity, call the runtime system to check cache
-  // validity or get the property names in a fixed array.
-  // Note: Proxies never have an enum cache, so will always take the
-  // slow path.
+  // Check cache validity in generated code. If we cannot guarantee cache
+  // validity, call the runtime system to check cache validity or get the
+  // property names in a fixed array. Note: Proxies never have an enum cache,
+  // so will always take the slow path.
   Label call_runtime;
   __ CheckEnumCache(x0, x15, x10, x11, x12, x13, &call_runtime);
 
@@ -1033,7 +1028,7 @@
   __ Bind(&call_runtime);
   __ Push(x0);  // Duplicate the enumerable object on the stack.
   __ CallRuntime(Runtime::kForInEnumerate);
-  PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
+  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
 
   // If we got a map from the runtime call, we can do a fast
   // modification check. Otherwise, we got a fixed array, and we have
@@ -1069,7 +1064,7 @@
   __ Mov(x1, Smi::FromInt(1));  // Smi(1) indicates slow check.
   __ Ldr(x2, FieldMemOperand(x0, FixedArray::kLengthOffset));
   __ Push(x1, x0, x2);  // Smi and array, fixed array length (as smi).
-  PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
   __ Push(xzr);  // Initial index.
 
   // Generate code for doing the condition check.
@@ -1109,7 +1104,7 @@
   // just skip it.
   __ Push(x1, x3);
   __ CallRuntime(Runtime::kForInFilter);
-  PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
+  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
   __ Mov(x3, x0);
   __ JumpIfRoot(x0, Heap::kUndefinedValueRootIndex,
                 loop_statement.continue_label());
@@ -1121,11 +1116,11 @@
   // Perform the assignment as if via '='.
   { EffectContext context(this);
     EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
-    PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
+    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
   }
 
   // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
-  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
   // Generate code for the body of the loop.
   Visit(stmt->body());
 
@@ -1145,7 +1140,7 @@
   DropOperands(5);
 
   // Exit and decrement the loop depth.
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   __ Bind(&exit);
   decrement_loop_depth();
 }
@@ -1270,16 +1265,11 @@
   } else if (var->mode() == DYNAMIC_LOCAL) {
     Variable* local = var->local_if_not_shadowed();
     __ Ldr(x0, ContextSlotOperandCheckExtensions(local, slow));
-    if (local->mode() == LET || local->mode() == CONST ||
-        local->mode() == CONST_LEGACY) {
+    if (local->mode() == LET || local->mode() == CONST) {
       __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, done);
-      if (local->mode() == CONST_LEGACY) {
-        __ LoadRoot(x0, Heap::kUndefinedValueRootIndex);
-      } else {  // LET || CONST
-        __ Mov(x0, Operand(var->name()));
-        __ Push(x0);
-        __ CallRuntime(Runtime::kThrowReferenceError);
-      }
+      __ Mov(x0, Operand(var->name()));
+      __ Push(x0);
+      __ CallRuntime(Runtime::kThrowReferenceError);
     }
     __ B(done);
   }
@@ -1288,14 +1278,14 @@
 
 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
                                                TypeofMode typeof_mode) {
+#ifdef DEBUG
   Variable* var = proxy->var();
   DCHECK(var->IsUnallocatedOrGlobalSlot() ||
          (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
-  __ LoadGlobalObject(LoadDescriptor::ReceiverRegister());
-  __ Mov(LoadDescriptor::NameRegister(), Operand(var->name()));
-  __ Mov(LoadDescriptor::SlotRegister(),
+#endif
+  __ Mov(LoadGlobalDescriptor::SlotRegister(),
          SmiFromSlot(proxy->VariableFeedbackSlot()));
-  CallLoadIC(typeof_mode);
+  CallLoadGlobalIC(typeof_mode);
 }
 
 
@@ -1303,7 +1293,7 @@
                                          TypeofMode typeof_mode) {
   // Record position before possible IC call.
   SetExpressionPosition(proxy);
-  PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
+  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
   Variable* var = proxy->var();
 
   // Three cases: global variables, lookup variables, and all other types of
@@ -1336,11 +1326,6 @@
           __ Push(x0);
           __ CallRuntime(Runtime::kThrowReferenceError);
           __ Bind(&done);
-        } else {
-          // Uninitialized legacy const bindings are unholed.
-          DCHECK(var->mode() == CONST_LEGACY);
-          __ LoadRoot(x0, Heap::kUndefinedValueRootIndex);
-          __ Bind(&done);
         }
         context()->Plug(x0);
         break;
@@ -1370,18 +1355,6 @@
 }
 
 
-void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
-  Comment cmnt(masm_, "[ RegExpLiteral");
-  __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  __ Mov(x2, Smi::FromInt(expr->literal_index()));
-  __ Mov(x1, Operand(expr->pattern()));
-  __ Mov(x0, Smi::FromInt(expr->flags()));
-  FastCloneRegExpStub stub(isolate());
-  __ CallStub(&stub);
-  context()->Plug(x0);
-}
-
-
 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
   Expression* expression = (property == NULL) ? NULL : property->value();
   if (expression == NULL) {
@@ -1414,8 +1387,9 @@
   } else {
     FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
     __ CallStub(&stub);
+    RestoreContext();
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   // If result_saved is true the result is on top of the stack.  If
   // result_saved is false the result is in x0.
@@ -1451,7 +1425,7 @@
             __ Peek(StoreDescriptor::ReceiverRegister(), 0);
             EmitLoadStoreICSlot(property->GetSlot(0));
             CallStoreIC();
-            PrepareForBailoutForId(key->id(), NO_REGISTERS);
+            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
 
             if (NeedsHomeObject(value)) {
               EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
@@ -1484,16 +1458,20 @@
         VisitForStackValue(value);
         CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
         PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                               NO_REGISTERS);
+                               BailoutState::NO_REGISTERS);
         break;
       case ObjectLiteral::Property::GETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->getter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->getter = property;
         }
         break;
       case ObjectLiteral::Property::SETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->setter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->setter = property;
         }
         break;
     }
@@ -1504,14 +1482,15 @@
   for (AccessorTable::Iterator it = accessor_table.begin();
        it != accessor_table.end();
        ++it) {
-      __ Peek(x10, 0);  // Duplicate receiver.
-      PushOperand(x10);
-      VisitForStackValue(it->first);
-      EmitAccessor(it->second->getter);
-      EmitAccessor(it->second->setter);
-      __ Mov(x10, Smi::FromInt(NONE));
-      PushOperand(x10);
-      CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
+    __ Peek(x10, 0);  // Duplicate receiver.
+    PushOperand(x10);
+    VisitForStackValue(it->first);
+    EmitAccessor(it->second->getter);
+    EmitAccessor(it->second->setter);
+    __ Mov(x10, Smi::FromInt(NONE));
+    PushOperand(x10);
+    CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
+    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
   }
 
   // Object literals have two parts. The "static" part on the left contains no
@@ -1541,7 +1520,7 @@
       DCHECK(property->emit_store());
       CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
       PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                             NO_REGISTERS);
+                             BailoutState::NO_REGISTERS);
     } else {
       EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
       VisitForStackValue(value);
@@ -1557,6 +1536,8 @@
             PushOperand(Smi::FromInt(NONE));
             PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
             CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
+            PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
+                                   BailoutState::NO_REGISTERS);
           } else {
             DropOperands(3);
           }
@@ -1612,7 +1593,7 @@
     FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
     __ CallStub(&stub);
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   bool result_saved = false;  // Is the result saved to the stack?
   ZoneList<Expression*>* subexprs = expr->values();
@@ -1642,7 +1623,8 @@
         CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
     CallIC(ic);
 
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   // In case the array literal contains spread expressions it has two parts. The
@@ -1662,7 +1644,8 @@
     VisitForStackValue(subexpr);
     CallRuntimeWithOperands(Runtime::kAppendElement);
 
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   if (result_saved) {
@@ -1677,7 +1660,6 @@
   DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
 
   Comment cmnt(masm_, "[ Assignment");
-  SetExpressionPosition(expr, INSERT_BREAK);
 
   Property* property = expr->target()->AsProperty();
   LhsKind assign_type = Property::GetAssignType(property);
@@ -1743,23 +1725,27 @@
       switch (assign_type) {
         case VARIABLE:
           EmitVariableLoad(expr->target()->AsVariableProxy());
-          PrepareForBailout(expr->target(), TOS_REG);
+          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
           break;
         case NAMED_PROPERTY:
           EmitNamedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case NAMED_SUPER_PROPERTY:
           EmitNamedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_SUPER_PROPERTY:
           EmitKeyedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_PROPERTY:
           EmitKeyedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
       }
     }
@@ -1779,7 +1765,7 @@
     }
 
     // Deoptimization point in case the binary operation may have side effects.
-    PrepareForBailout(expr->binary_operation(), TOS_REG);
+    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
   } else {
     VisitForAccumulatorValue(expr->value());
   }
@@ -1791,7 +1777,7 @@
     case VARIABLE:
       EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
                              expr->op(), expr->AssignmentSlot());
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       context()->Plug(x0);
       break;
     case NAMED_PROPERTY:
@@ -2127,8 +2113,7 @@
     __ bind(&uninitialized_this);
     EmitStoreToStackLocalOrContextSlot(var, location);
 
-  } else if (!var->is_const_mode() ||
-             (var->mode() == CONST && op == Token::INIT)) {
+  } else if (!var->is_const_mode() || op == Token::INIT) {
     if (var->IsLookupSlot()) {
       // Assignment to var.
       __ Push(var->name());
@@ -2149,23 +2134,6 @@
       EmitStoreToStackLocalOrContextSlot(var, location);
     }
 
-  } else if (var->mode() == CONST_LEGACY && op == Token::INIT) {
-    // Const initializers need a write barrier.
-    DCHECK(!var->IsParameter());  // No const parameters.
-    if (var->IsLookupSlot()) {
-      __ Mov(x1, Operand(var->name()));
-      __ Push(x0, cp, x1);
-      __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot);
-    } else {
-      DCHECK(var->IsStackLocal() || var->IsContextSlot());
-      Label skip;
-      MemOperand location = VarOperand(var, x1);
-      __ Ldr(x10, location);
-      __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &skip);
-      EmitStoreToStackLocalOrContextSlot(var, location);
-      __ Bind(&skip);
-    }
-
   } else {
     DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT);
     if (is_strict(language_mode())) {
@@ -2189,7 +2157,7 @@
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallStoreIC();
 
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(x0);
 }
 
@@ -2237,43 +2205,7 @@
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallIC(ic);
 
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
-  context()->Plug(x0);
-}
-
-
-void FullCodeGenerator::VisitProperty(Property* expr) {
-  Comment cmnt(masm_, "[ Property");
-  SetExpressionPosition(expr);
-  Expression* key = expr->key();
-
-  if (key->IsPropertyName()) {
-    if (!expr->IsSuperAccess()) {
-      VisitForAccumulatorValue(expr->obj());
-      __ Move(LoadDescriptor::ReceiverRegister(), x0);
-      EmitNamedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      EmitNamedSuperPropertyLoad(expr);
-    }
-  } else {
-    if (!expr->IsSuperAccess()) {
-      VisitForStackValue(expr->obj());
-      VisitForAccumulatorValue(expr->key());
-      __ Move(LoadDescriptor::NameRegister(), x0);
-      PopOperand(LoadDescriptor::ReceiverRegister());
-      EmitKeyedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      VisitForStackValue(expr->key());
-      EmitKeyedSuperPropertyLoad(expr);
-    }
-  }
-  PrepareForBailoutForId(expr->LoadId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(x0);
 }
 
@@ -2297,7 +2229,7 @@
   if (callee->IsVariableProxy()) {
     { StackValueContext context(this);
       EmitVariableLoad(callee->AsVariableProxy());
-      PrepareForBailout(callee, NO_REGISTERS);
+      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
     }
     // Push undefined as receiver. This is patched in the method prologue if it
     // is a sloppy mode method.
@@ -2314,7 +2246,8 @@
     DCHECK(!callee->AsProperty()->IsSuperAccess());
     __ Peek(LoadDescriptor::ReceiverRegister(), 0);
     EmitNamedPropertyLoad(callee->AsProperty());
-    PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                           BailoutState::TOS_REGISTER);
     // Push the target function under the receiver.
     PopOperand(x10);
     PushOperands(x0, x10);
@@ -2354,6 +2287,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ Poke(x0, kPointerSize);
@@ -2379,7 +2313,8 @@
   __ Peek(LoadDescriptor::ReceiverRegister(), 0);
   __ Move(LoadDescriptor::NameRegister(), x0);
   EmitKeyedPropertyLoad(callee->AsProperty());
-  PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                         BailoutState::TOS_REGISTER);
 
   // Push the target function under the receiver.
   PopOperand(x10);
@@ -2415,6 +2350,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ Poke(x0, kPointerSize);
@@ -2435,7 +2371,7 @@
     VisitForStackValue(args->at(i));
   }
 
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   SetCallPosition(expr, expr->tail_call_mode());
   if (expr->tail_call_mode() == TailCallMode::kAllow) {
     if (FLAG_trace) {
@@ -2456,13 +2392,12 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-  // Restore context register.
-  __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->DropAndPlug(1, x0);
 }
 
-
-void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
+void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
+  int arg_count = expr->arguments()->length();
   ASM_LOCATION("FullCodeGenerator::EmitResolvePossiblyDirectEval");
   // Prepare to push a copy of the first argument or undefined if it doesn't
   // exist.
@@ -2478,9 +2413,11 @@
   __ Mov(x11, Smi::FromInt(language_mode()));
   // Prepare to push the start position of the scope the calls resides in.
   __ Mov(x12, Smi::FromInt(scope()->start_position()));
+  // Prepare to push the source position of the eval call.
+  __ Mov(x13, Smi::FromInt(expr->position()));
 
   // Push.
-  __ Push(x9, x10, x11, x12);
+  __ Push(x9, x10, x11, x12, x13);
 
   // Do the runtime call.
   __ CallRuntime(Runtime::kResolvePossiblyDirectEval);
@@ -2503,7 +2440,7 @@
     __ Push(callee->name());
     __ CallRuntime(Runtime::kLoadLookupSlotForCall);
     PushOperands(x0, x1);  // Receiver, function.
-    PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
+    PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
 
     // If fast case code has been generated, emit code to push the
     // function and receiver and have the slow path jump around this
@@ -2530,7 +2467,7 @@
 
 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
   ASM_LOCATION("FullCodeGenerator::EmitPossiblyEvalCall");
-  // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
+  // In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
   // to resolve the function we need to call.  Then we call the resolved
   // function using the given arguments.
   ZoneList<Expression*>* args = expr->arguments();
@@ -2547,12 +2484,12 @@
   // resolve eval.
   __ Peek(x10, (arg_count + 1) * kPointerSize);
   __ Push(x10);
-  EmitResolvePossiblyDirectEval(arg_count);
+  EmitResolvePossiblyDirectEval(expr);
 
   // Touch up the stack with the resolved function.
   __ Poke(x0, (arg_count + 1) * kPointerSize);
 
-  PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
 
   // Record source position for debugger.
   SetCallPosition(expr);
@@ -2565,8 +2502,7 @@
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
   RecordJSReturnSite(expr);
-  // Restore context register.
-  __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->DropAndPlug(1, x0);
 }
 
@@ -2605,9 +2541,8 @@
   CallConstructStub stub(isolate());
   __ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
-  // Restore context register.
-  __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
+  RestoreContext();
   context()->Plug(x0);
 }
 
@@ -2651,9 +2586,7 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-
-  // Restore context register.
-  __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->Plug(x0);
 }
 
@@ -2861,66 +2794,6 @@
 }
 
 
-void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = x0;
-  Register index = x1;
-  Register value = x2;
-  Register scratch = x10;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-  PopOperands(value, index);
-
-  if (FLAG_debug_code) {
-    __ AssertSmi(value, kNonSmiValue);
-    __ AssertSmi(index, kNonSmiIndex);
-    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    __ EmitSeqStringSetCharCheck(string, index, kIndexIsSmi, scratch,
-                                 one_byte_seq_type);
-  }
-
-  __ Add(scratch, string, SeqOneByteString::kHeaderSize - kHeapObjectTag);
-  __ SmiUntag(value);
-  __ SmiUntag(index);
-  __ Strb(value, MemOperand(scratch, index));
-  context()->Plug(string);
-}
-
-
-void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = x0;
-  Register index = x1;
-  Register value = x2;
-  Register scratch = x10;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-  PopOperands(value, index);
-
-  if (FLAG_debug_code) {
-    __ AssertSmi(value, kNonSmiValue);
-    __ AssertSmi(index, kNonSmiIndex);
-    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    __ EmitSeqStringSetCharCheck(string, index, kIndexIsSmi, scratch,
-                                 two_byte_seq_type);
-  }
-
-  __ Add(scratch, string, SeqTwoByteString::kHeaderSize - kHeapObjectTag);
-  __ SmiUntag(value);
-  __ SmiUntag(index);
-  __ Strh(value, MemOperand(scratch, index, LSL, 1));
-  context()->Plug(string);
-}
-
-
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
@@ -2959,13 +2832,8 @@
   Label need_conversion;
   Label index_out_of_range;
   Label done;
-  StringCharCodeAtGenerator generator(object,
-                                      index,
-                                      result,
-                                      &need_conversion,
-                                      &need_conversion,
-                                      &index_out_of_range,
-                                      STRING_INDEX_IS_NUMBER);
+  StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
+                                      &need_conversion, &index_out_of_range);
   generator.GenerateFast(masm_);
   __ B(&done);
 
@@ -2988,52 +2856,6 @@
 }
 
 
-void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK(args->length() == 2);
-
-  VisitForStackValue(args->at(0));
-  VisitForAccumulatorValue(args->at(1));
-
-  Register object = x1;
-  Register index = x0;
-  Register result = x0;
-
-  PopOperand(object);
-
-  Label need_conversion;
-  Label index_out_of_range;
-  Label done;
-  StringCharAtGenerator generator(object,
-                                  index,
-                                  x3,
-                                  result,
-                                  &need_conversion,
-                                  &need_conversion,
-                                  &index_out_of_range,
-                                  STRING_INDEX_IS_NUMBER);
-  generator.GenerateFast(masm_);
-  __ B(&done);
-
-  __ Bind(&index_out_of_range);
-  // When the index is out of range, the spec requires us to return
-  // the empty string.
-  __ LoadRoot(result, Heap::kempty_stringRootIndex);
-  __ B(&done);
-
-  __ Bind(&need_conversion);
-  // Move smi zero into the result register, which will trigger conversion.
-  __ Mov(result, Smi::FromInt(0));
-  __ B(&done);
-
-  NopRuntimeCallHelper call_helper;
-  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
-
-  __ Bind(&done);
-  context()->Plug(result);
-}
-
-
 void FullCodeGenerator::EmitCall(CallRuntime* expr) {
   ASM_LOCATION("FullCodeGenerator::EmitCall");
   ZoneList<Expression*>* args = expr->arguments();
@@ -3042,7 +2864,7 @@
   for (Expression* const arg : *args) {
     VisitForStackValue(arg);
   }
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   // Move target to x1.
   int const argc = args->length() - 2;
   __ Peek(x1, (argc + 1) * kXRegSize);
@@ -3050,8 +2872,7 @@
   __ Mov(x0, argc);
   __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(argc + 1);
-  // Restore context register.
-  __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   // Discard the function left on TOS.
   context()->DropAndPlug(1, x0);
 }
@@ -3101,12 +2922,6 @@
   context()->Plug(x0);
 }
 
-void FullCodeGenerator::EmitGetOrdinaryHasInstance(CallRuntime* expr) {
-  DCHECK_EQ(0, expr->arguments()->length());
-  __ LoadNativeContextSlot(Context::ORDINARY_HAS_INSTANCE_INDEX, x0);
-  context()->Plug(x0);
-}
-
 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
   DCHECK(expr->arguments()->length() == 0);
   ExternalReference debug_is_active =
@@ -3127,7 +2942,8 @@
   Label runtime, done;
 
   Register result = x0;
-  __ Allocate(JSIteratorResult::kSize, result, x10, x11, &runtime, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, result, x10, x11, &runtime,
+              NO_ALLOCATION_FLAGS);
   Register map_reg = x1;
   Register result_value = x2;
   Register boolean_done = x3;
@@ -3179,9 +2995,7 @@
   __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-
-  // Restore context register.
-  __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
 }
 
 
@@ -3263,12 +3077,14 @@
         if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
 
         __ Bind(&materialize_true);
-        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeTrueId(),
+                               BailoutState::NO_REGISTERS);
         __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
         __ B(&done);
 
         __ Bind(&materialize_false);
-        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeFalseId(),
+                               BailoutState::NO_REGISTERS);
         __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
         __ B(&done);
 
@@ -3368,9 +3184,9 @@
   // We need a second deoptimization point after loading the value
   // in case evaluating the property load my have a side effect.
   if (assign_type == VARIABLE) {
-    PrepareForBailout(expr->expression(), TOS_REG);
+    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
   } else {
-    PrepareForBailoutForId(prop->LoadId(), TOS_REG);
+    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
   }
 
   // Inline smi case if we are in a loop.
@@ -3417,9 +3233,8 @@
   }
 
   // Convert old value into a number.
-  ToNumberStub convert_stub(isolate());
-  __ CallStub(&convert_stub);
-  PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
+  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
+  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
 
   // Save result for postfix expressions.
   if (expr->is_postfix()) {
@@ -3468,7 +3283,8 @@
         { EffectContext context(this);
           EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                  Token::ASSIGN, expr->CountSlot());
-          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+          PrepareForBailoutForId(expr->AssignmentId(),
+                                 BailoutState::TOS_REGISTER);
           context.Plug(x0);
         }
         // For all contexts except EffectConstant We have the result on
@@ -3479,7 +3295,8 @@
       } else {
         EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                Token::ASSIGN, expr->CountSlot());
-        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+        PrepareForBailoutForId(expr->AssignmentId(),
+                               BailoutState::TOS_REGISTER);
         context()->Plug(x0);
       }
       break;
@@ -3489,7 +3306,7 @@
       PopOperand(StoreDescriptor::ReceiverRegister());
       EmitLoadStoreICSlot(expr->CountSlot());
       CallStoreIC();
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         if (!context()->IsEffect()) {
           context()->PlugTOS();
@@ -3528,7 +3345,7 @@
           CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
       EmitLoadStoreICSlot(expr->CountSlot());
       CallIC(ic);
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         if (!context()->IsEffect()) {
           context()->PlugTOS();
@@ -3631,7 +3448,6 @@
 
 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
   Comment cmnt(masm_, "[ CompareOperation");
-  SetExpressionPosition(expr);
 
   // Try to generate an optimized comparison with a literal value.
   // TODO(jbramley): This only checks common values like NaN or undefined.
@@ -3654,7 +3470,8 @@
   switch (op) {
     case Token::IN:
       VisitForStackValue(expr->right());
-      CallRuntimeWithOperands(Runtime::kHasProperty);
+      SetExpressionPosition(expr);
+      EmitHasProperty();
       PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
       __ CompareRoot(x0, Heap::kTrueValueRootIndex);
       Split(eq, if_true, if_false, fall_through);
@@ -3662,6 +3479,7 @@
 
     case Token::INSTANCEOF: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       PopOperand(x1);
       InstanceOfStub stub(isolate());
       __ CallStub(&stub);
@@ -3673,6 +3491,7 @@
 
     default: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       Condition cond = CompareIC::ComputeCondition(op);
 
       // Pop the stack value.
@@ -3745,24 +3564,29 @@
   // and suchlike. The implementation changes a little by bleeding_edge so I
   // don't want to spend too much time on it now.
 
-  Label suspend, continuation, post_runtime, resume;
+  Label suspend, continuation, post_runtime, resume, exception;
 
   __ B(&suspend);
   // TODO(jbramley): This label is bound here because the following code
   // looks at its pos(). Is it possible to do something more efficient here,
   // perhaps using Adr?
   __ Bind(&continuation);
-  // When we arrive here, the stack top is the resume mode and
-  // result_register() holds the input value (the argument given to the
-  // respective resume operation).
+  // When we arrive here, x0 holds the generator object.
   __ RecordGeneratorContinuation();
-  __ Pop(x1);
-  __ Cmp(x1, Smi::FromInt(JSGeneratorObject::RETURN));
-  __ B(ne, &resume);
+  __ Ldr(x1, FieldMemOperand(x0, JSGeneratorObject::kResumeModeOffset));
+  __ Ldr(x0, FieldMemOperand(x0, JSGeneratorObject::kInputOrDebugPosOffset));
+  STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
+  STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
+  __ Cmp(x1, Operand(Smi::FromInt(JSGeneratorObject::kReturn)));
+  __ B(lt, &resume);
   __ Push(result_register());
+  __ B(gt, &exception);
   EmitCreateIteratorResult(true);
   EmitUnwindAndReturn();
 
+  __ Bind(&exception);
+  __ CallRuntime(Runtime::kThrow);
+
   __ Bind(&suspend);
   OperandStackDepthIncrement(1);  // Not popped on this path.
   VisitForAccumulatorValue(expr->generator_object());
@@ -3778,7 +3602,7 @@
   __ B(eq, &post_runtime);
   __ Push(x0);  // generator object
   __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
-  __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   __ Bind(&post_runtime);
   PopOperand(result_register());
   EmitReturnSequence();
@@ -3787,110 +3611,6 @@
   context()->Plug(result_register());
 }
 
-
-void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
-    Expression *value,
-    JSGeneratorObject::ResumeMode resume_mode) {
-  ASM_LOCATION("FullCodeGenerator::EmitGeneratorResume");
-  Register generator_object = x1;
-  Register the_hole = x2;
-  Register operand_stack_size = w3;
-  Register function = x4;
-
-  // The value stays in x0, and is ultimately read by the resumed generator, as
-  // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it
-  // is read to throw the value when the resumed generator is already closed. x1
-  // will hold the generator object until the activation has been resumed.
-  VisitForStackValue(generator);
-  VisitForAccumulatorValue(value);
-  PopOperand(generator_object);
-
-  // Store input value into generator object.
-  __ Str(result_register(),
-         FieldMemOperand(x1, JSGeneratorObject::kInputOffset));
-  __ Mov(x2, result_register());
-  __ RecordWriteField(x1, JSGeneratorObject::kInputOffset, x2, x3,
-                      kLRHasBeenSaved, kDontSaveFPRegs);
-
-  // Load suspended function and context.
-  __ Ldr(cp, FieldMemOperand(generator_object,
-                             JSGeneratorObject::kContextOffset));
-  __ Ldr(function, FieldMemOperand(generator_object,
-                                   JSGeneratorObject::kFunctionOffset));
-
-  // Load receiver and store as the first argument.
-  __ Ldr(x10, FieldMemOperand(generator_object,
-                              JSGeneratorObject::kReceiverOffset));
-  __ Push(x10);
-
-  // Push holes for arguments to generator function. Since the parser forced
-  // context allocation for any variables in generators, the actual argument
-  // values have already been copied into the context and these dummy values
-  // will never be used.
-  __ Ldr(x10, FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
-
-  // The number of arguments is stored as an int32_t, and -1 is a marker
-  // (SharedFunctionInfo::kDontAdaptArgumentsSentinel), so we need sign
-  // extension to correctly handle it. However, in this case, we operate on
-  // 32-bit W registers, so extension isn't required.
-  __ Ldr(w10, FieldMemOperand(x10,
-                              SharedFunctionInfo::kFormalParameterCountOffset));
-  __ LoadRoot(the_hole, Heap::kTheHoleValueRootIndex);
-  __ PushMultipleTimes(the_hole, w10);
-
-  // Enter a new JavaScript frame, and initialize its slots as they were when
-  // the generator was suspended.
-  Label resume_frame, done;
-  __ Bl(&resume_frame);
-  __ B(&done);
-
-  __ Bind(&resume_frame);
-  __ Push(lr,           // Return address.
-          fp,           // Caller's frame pointer.
-          cp,           // Callee's context.
-          function);    // Callee's JS Function.
-  __ Add(fp, __ StackPointer(), kPointerSize * 2);
-
-  // Load and untag the operand stack size.
-  __ Ldr(x10, FieldMemOperand(generator_object,
-                              JSGeneratorObject::kOperandStackOffset));
-  __ Ldr(operand_stack_size,
-         UntagSmiFieldMemOperand(x10, FixedArray::kLengthOffset));
-
-  // If we are sending a value and there is no operand stack, we can jump back
-  // in directly.
-  if (resume_mode == JSGeneratorObject::NEXT) {
-    Label slow_resume;
-    __ Cbnz(operand_stack_size, &slow_resume);
-    __ Ldr(x10, FieldMemOperand(function, JSFunction::kCodeEntryOffset));
-    __ Ldrsw(x11,
-             UntagSmiFieldMemOperand(generator_object,
-                                     JSGeneratorObject::kContinuationOffset));
-    __ Add(x10, x10, x11);
-    __ Mov(x12, Smi::FromInt(JSGeneratorObject::kGeneratorExecuting));
-    __ Str(x12, FieldMemOperand(generator_object,
-                                JSGeneratorObject::kContinuationOffset));
-    __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-    __ Br(x10);
-
-    __ Bind(&slow_resume);
-  }
-
-  // Otherwise, we push holes for the operand stack and call the runtime to fix
-  // up the stack and the handlers.
-  __ PushMultipleTimes(the_hole, operand_stack_size);
-
-  __ Mov(x10, Smi::FromInt(resume_mode));
-  __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-  __ Push(generator_object, result_register(), x10);
-  __ CallRuntime(Runtime::kResumeJSGeneratorObject);
-  // Not reached: the runtime call returns elsewhere.
-  __ Unreachable();
-
-  __ Bind(&done);
-  context()->Plug(result_register());
-}
-
 void FullCodeGenerator::PushOperands(Register reg1, Register reg2) {
   OperandStackDepthIncrement(2);
   __ Push(reg1, reg2);
@@ -3923,7 +3643,8 @@
   // Allocate and populate an object with this form: { value: VAL, done: DONE }
 
   Register result = x0;
-  __ Allocate(JSIteratorResult::kSize, result, x10, x11, &allocate, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, result, x10, x11, &allocate,
+              NO_ALLOCATION_FLAGS);
   __ B(&done_allocate);
 
   __ Bind(&allocate);
diff --git a/src/full-codegen/full-codegen.cc b/src/full-codegen/full-codegen.cc
index af5dd41..03140c9 100644
--- a/src/full-codegen/full-codegen.cc
+++ b/src/full-codegen/full-codegen.cc
@@ -28,11 +28,14 @@
 bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
   Isolate* isolate = info->isolate();
 
+  RuntimeCallTimerScope runtimeTimer(isolate,
+                                     &RuntimeCallStats::CompileFullCode);
   TimerEventScope<TimerEventCompileFullCode> timer(info->isolate());
   TRACE_EVENT0("v8", "V8.CompileFullCode");
 
   Handle<Script> script = info->script();
-  if (!script->IsUndefined() && !script->source()->IsUndefined()) {
+  if (!script->IsUndefined(isolate) &&
+      !script->source()->IsUndefined(isolate)) {
     int len = String::cast(script->source())->length();
     isolate->counters()->total_full_codegen_source_size()->Increment(len);
   }
@@ -144,13 +147,8 @@
 
 bool FullCodeGenerator::MustCreateObjectLiteralWithRuntime(
     ObjectLiteral* expr) const {
-  // FastCloneShallowObjectStub doesn't copy elements, and object literals don't
-  // support copy-on-write (COW) elements for now.
-  // TODO(mvstanton): make object literals support COW elements.
-  return masm()->serializer_enabled() || !expr->fast_elements() ||
-         !expr->has_shallow_properties() ||
-         expr->properties_count() >
-             FastCloneShallowObjectStub::kMaximumClonedProperties;
+  return masm()->serializer_enabled() ||
+         !FastCloneShallowObjectStub::IsSupported(expr);
 }
 
 
@@ -167,18 +165,21 @@
   masm_->set_predictable_code_size(true);
 }
 
-
-void FullCodeGenerator::PrepareForBailout(Expression* node, State state) {
+void FullCodeGenerator::PrepareForBailout(Expression* node,
+                                          BailoutState state) {
   PrepareForBailoutForId(node->id(), state);
 }
 
-
-void FullCodeGenerator::CallLoadIC(TypeofMode typeof_mode,
-                                   TypeFeedbackId id) {
-  Handle<Code> ic = CodeFactory::LoadIC(isolate(), typeof_mode).code();
+void FullCodeGenerator::CallLoadIC(TypeFeedbackId id) {
+  Handle<Code> ic = CodeFactory::LoadIC(isolate()).code();
   CallIC(ic, id);
 }
 
+void FullCodeGenerator::CallLoadGlobalIC(TypeofMode typeof_mode,
+                                         TypeFeedbackId id) {
+  Handle<Code> ic = CodeFactory::LoadGlobalIC(isolate(), typeof_mode).code();
+  CallIC(ic, id);
+}
 
 void FullCodeGenerator::CallStoreIC(TypeFeedbackId id) {
   Handle<Code> ic = CodeFactory::StoreIC(isolate(), language_mode()).code();
@@ -191,9 +192,9 @@
   // if the function was inlined, i.e., this is the return address in the
   // inlined function's frame.
   //
-  // The state is ignored.  We defensively set it to TOS_REG, which is the
-  // real state of the unoptimized code at the return site.
-  PrepareForBailoutForId(call->ReturnId(), TOS_REG);
+  // The bailout state is ignored.  We defensively set it to TOS_REGISTER, which
+  // is the real state of the unoptimized code at the return site.
+  PrepareForBailoutForId(call->ReturnId(), BailoutState::TOS_REGISTER);
 #ifdef DEBUG
   // In debug builds, mark the return so we can verify that this function
   // was called.
@@ -202,13 +203,13 @@
 #endif
 }
 
-
-void FullCodeGenerator::PrepareForBailoutForId(BailoutId id, State state) {
+void FullCodeGenerator::PrepareForBailoutForId(BailoutId id,
+                                               BailoutState state) {
   // There's no need to prepare this code for bailouts from already optimized
   // code or code that can't be optimized.
   if (!info_->HasDeoptimizationSupport()) return;
   unsigned pc_and_state =
-      StateField::encode(state) | PcField::encode(masm_->pc_offset());
+      BailoutStateField::encode(state) | PcField::encode(masm_->pc_offset());
   DCHECK(Smi::IsValid(pc_and_state));
 #ifdef DEBUG
   for (int i = 0; i < bailout_entries_.length(); ++i) {
@@ -447,10 +448,7 @@
 
 
 int FullCodeGenerator::DeclareGlobalsFlags() {
-  DCHECK(DeclareGlobalsLanguageMode::is_valid(language_mode()));
-  return DeclareGlobalsEvalFlag::encode(is_eval()) |
-         DeclareGlobalsNativeFlag::encode(is_native()) |
-         DeclareGlobalsLanguageMode::encode(language_mode());
+  return info_->GetDeclareGlobalsFlags();
 }
 
 void FullCodeGenerator::PushOperand(Handle<Object> handle) {
@@ -609,19 +607,22 @@
   EmitIntrinsicAsStubCall(expr, CodeFactory::RegExpConstructResult(isolate()));
 }
 
-
-bool RecordStatementPosition(MacroAssembler* masm, int pos) {
-  if (pos == RelocInfo::kNoPosition) return false;
-  masm->positions_recorder()->RecordStatementPosition(pos);
-  masm->positions_recorder()->RecordPosition(pos);
-  return masm->positions_recorder()->WriteRecordedPositions();
+void FullCodeGenerator::EmitHasProperty() {
+  Callable callable = CodeFactory::HasProperty(isolate());
+  PopOperand(callable.descriptor().GetRegisterParameter(1));
+  PopOperand(callable.descriptor().GetRegisterParameter(0));
+  __ Call(callable.code(), RelocInfo::CODE_TARGET);
+  RestoreContext();
 }
 
+void RecordStatementPosition(MacroAssembler* masm, int pos) {
+  if (pos == RelocInfo::kNoPosition) return;
+  masm->positions_recorder()->RecordStatementPosition(pos);
+}
 
-bool RecordPosition(MacroAssembler* masm, int pos) {
-  if (pos == RelocInfo::kNoPosition) return false;
+void RecordPosition(MacroAssembler* masm, int pos) {
+  if (pos == RelocInfo::kNoPosition) return;
   masm->positions_recorder()->RecordPosition(pos);
-  return masm->positions_recorder()->WriteRecordedPositions();
 }
 
 
@@ -645,28 +646,23 @@
 void FullCodeGenerator::SetStatementPosition(
     Statement* stmt, FullCodeGenerator::InsertBreak insert_break) {
   if (stmt->position() == RelocInfo::kNoPosition) return;
-  bool recorded = RecordStatementPosition(masm_, stmt->position());
-  if (recorded && insert_break == INSERT_BREAK && info_->is_debug() &&
+  RecordStatementPosition(masm_, stmt->position());
+  if (insert_break == INSERT_BREAK && info_->is_debug() &&
       !stmt->IsDebuggerStatement()) {
     DebugCodegen::GenerateSlot(masm_, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
   }
 }
 
-
-void FullCodeGenerator::SetExpressionPosition(
-    Expression* expr, FullCodeGenerator::InsertBreak insert_break) {
+void FullCodeGenerator::SetExpressionPosition(Expression* expr) {
   if (expr->position() == RelocInfo::kNoPosition) return;
-  bool recorded = RecordPosition(masm_, expr->position());
-  if (recorded && insert_break == INSERT_BREAK && info_->is_debug()) {
-    DebugCodegen::GenerateSlot(masm_, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
-  }
+  RecordPosition(masm_, expr->position());
 }
 
 
 void FullCodeGenerator::SetExpressionAsStatementPosition(Expression* expr) {
   if (expr->position() == RelocInfo::kNoPosition) return;
-  bool recorded = RecordStatementPosition(masm_, expr->position());
-  if (recorded && info_->is_debug()) {
+  RecordStatementPosition(masm_, expr->position());
+  if (info_->is_debug()) {
     DebugCodegen::GenerateSlot(masm_, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
   }
 }
@@ -688,32 +684,15 @@
 void FullCodeGenerator::VisitSuperPropertyReference(
     SuperPropertyReference* super) {
   __ CallRuntime(Runtime::kThrowUnsupportedSuperError);
+  // Even though this expression doesn't produce a value, we need to simulate
+  // plugging of the value context to ensure stack depth tracking is in sync.
+  if (context()->IsStackValue()) OperandStackDepthIncrement(1);
 }
 
 
 void FullCodeGenerator::VisitSuperCallReference(SuperCallReference* super) {
-  __ CallRuntime(Runtime::kThrowUnsupportedSuperError);
-}
-
-
-void FullCodeGenerator::EmitGeneratorNext(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK(args->length() == 2);
-  EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::NEXT);
-}
-
-
-void FullCodeGenerator::EmitGeneratorReturn(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK(args->length() == 2);
-  EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::RETURN);
-}
-
-
-void FullCodeGenerator::EmitGeneratorThrow(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK(args->length() == 2);
-  EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::THROW);
+  // Handled by VisitCall
+  UNREACHABLE();
 }
 
 
@@ -773,7 +752,7 @@
     } else {
       VisitForControl(left, test->true_label(), &eval_right, &eval_right);
     }
-    PrepareForBailoutForId(right_id, NO_REGISTERS);
+    PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
     __ bind(&eval_right);
 
   } else if (context()->IsAccumulatorValue()) {
@@ -792,7 +771,7 @@
     __ jmp(&done);
     __ bind(&discard);
     __ Drop(1);
-    PrepareForBailoutForId(right_id, NO_REGISTERS);
+    PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
 
   } else if (context()->IsStackValue()) {
     VisitForAccumulatorValue(left);
@@ -807,7 +786,7 @@
     }
     __ bind(&discard);
     __ Drop(1);
-    PrepareForBailoutForId(right_id, NO_REGISTERS);
+    PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
 
   } else {
     DCHECK(context()->IsEffect());
@@ -817,7 +796,7 @@
     } else {
       VisitForControl(left, &done, &eval_right, &eval_right);
     }
-    PrepareForBailoutForId(right_id, NO_REGISTERS);
+    PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
     __ bind(&eval_right);
   }
 
@@ -843,6 +822,41 @@
   }
 }
 
+void FullCodeGenerator::VisitProperty(Property* expr) {
+  Comment cmnt(masm_, "[ Property");
+  SetExpressionPosition(expr);
+
+  Expression* key = expr->key();
+
+  if (key->IsPropertyName()) {
+    if (!expr->IsSuperAccess()) {
+      VisitForAccumulatorValue(expr->obj());
+      __ Move(LoadDescriptor::ReceiverRegister(), result_register());
+      EmitNamedPropertyLoad(expr);
+    } else {
+      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          expr->obj()->AsSuperPropertyReference()->home_object());
+      EmitNamedSuperPropertyLoad(expr);
+    }
+  } else {
+    if (!expr->IsSuperAccess()) {
+      VisitForStackValue(expr->obj());
+      VisitForAccumulatorValue(expr->key());
+      __ Move(LoadDescriptor::NameRegister(), result_register());
+      PopOperand(LoadDescriptor::ReceiverRegister());
+      EmitKeyedPropertyLoad(expr);
+    } else {
+      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
+      VisitForStackValue(
+          expr->obj()->AsSuperPropertyReference()->home_object());
+      VisitForStackValue(expr->key());
+      EmitKeyedSuperPropertyLoad(expr);
+    }
+  }
+  PrepareForBailoutForId(expr->LoadId(), BailoutState::TOS_REGISTER);
+  context()->Plug(result_register());
+}
 
 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
   VariableProxy* proxy = expr->AsVariableProxy();
@@ -852,7 +866,7 @@
   if (proxy != NULL && (proxy->var()->IsUnallocatedOrGlobalSlot() ||
                         proxy->var()->IsLookupSlot())) {
     EmitVariableLoad(proxy, INSIDE_TYPEOF);
-    PrepareForBailout(proxy, TOS_REG);
+    PrepareForBailout(proxy, BailoutState::TOS_REGISTER);
   } else {
     // This expression cannot throw a reference error at the top level.
     VisitInDuplicateContext(expr);
@@ -875,7 +889,6 @@
 
 void FullCodeGenerator::VisitDoExpression(DoExpression* expr) {
   Comment cmnt(masm_, "[ Do Expression");
-  NestedStatement nested_block(this);
   SetExpressionPosition(expr);
   VisitBlock(expr->block());
   EmitVariableLoad(expr->result());
@@ -901,24 +914,24 @@
 
   if (stmt->HasElseStatement()) {
     VisitForControl(stmt->condition(), &then_part, &else_part, &then_part);
-    PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
+    PrepareForBailoutForId(stmt->ThenId(), BailoutState::NO_REGISTERS);
     __ bind(&then_part);
     Visit(stmt->then_statement());
     __ jmp(&done);
 
-    PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
+    PrepareForBailoutForId(stmt->ElseId(), BailoutState::NO_REGISTERS);
     __ bind(&else_part);
     Visit(stmt->else_statement());
   } else {
     VisitForControl(stmt->condition(), &then_part, &done, &then_part);
-    PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
+    PrepareForBailoutForId(stmt->ThenId(), BailoutState::NO_REGISTERS);
     __ bind(&then_part);
     Visit(stmt->then_statement());
 
-    PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
+    PrepareForBailoutForId(stmt->ElseId(), BailoutState::NO_REGISTERS);
   }
   __ bind(&done);
-  PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->IfId(), BailoutState::NO_REGISTERS);
 }
 
 void FullCodeGenerator::EmitContinue(Statement* target) {
@@ -1019,17 +1032,12 @@
 
 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
                                        bool pretenure) {
-  // Use the fast case closure allocation code that allocates in new
-  // space for nested functions that don't need literals cloning. If
-  // we're running with the --always-opt or the --prepare-always-opt
+  // If we're running with the --always-opt or the --prepare-always-opt
   // flag, we need to use the runtime function so that the new function
   // we are creating here gets a chance to have its code optimized and
   // doesn't just get a copy of the existing unoptimized code.
-  if (!FLAG_always_opt &&
-      !FLAG_prepare_always_opt &&
-      !pretenure &&
-      scope()->is_function_scope() &&
-      info->num_literals() == 0) {
+  if (!FLAG_always_opt && !FLAG_prepare_always_opt && !pretenure &&
+      scope()->is_function_scope()) {
     FastNewClosureStub stub(isolate(), info->language_mode(), info->kind());
     __ Move(stub.GetCallInterfaceDescriptor().GetRegisterParameter(0), info);
     __ CallStub(&stub);
@@ -1050,7 +1058,7 @@
   __ Move(LoadDescriptor::NameRegister(), key->value());
   __ Move(LoadDescriptor::SlotRegister(),
           SmiFromSlot(prop->PropertyFeedbackSlot()));
-  CallLoadIC(NOT_INSIDE_TYPEOF);
+  CallLoadIC();
 }
 
 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
@@ -1082,7 +1090,7 @@
                                         BailoutId bailout_id) {
   VisitForStackValue(property->key());
   CallRuntimeWithOperands(Runtime::kToName);
-  PrepareForBailoutForId(bailout_id, NO_REGISTERS);
+  PrepareForBailoutForId(bailout_id, BailoutState::NO_REGISTERS);
   PushOperand(result_register());
 }
 
@@ -1108,12 +1116,12 @@
   Callable callable = CodeFactory::ToObject(isolate());
   __ Move(callable.descriptor().GetRegisterParameter(0), result_register());
   __ Call(callable.code(), RelocInfo::CODE_TARGET);
-  PrepareForBailoutForId(stmt->ToObjectId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::NO_REGISTERS);
   PushOperand(result_register());
   PushFunctionArgumentForContextAllocation();
   CallRuntimeWithOperands(Runtime::kPushWithContext);
   StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
 
   Scope* saved_scope = scope();
   scope_ = stmt->scope();
@@ -1145,7 +1153,7 @@
   // Record the position of the do while condition and make sure it is
   // possible to break on the condition.
   __ bind(loop_statement.continue_label());
-  PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ContinueId(), BailoutState::NO_REGISTERS);
 
   // Here is the actual 'while' keyword.
   SetExpressionAsStatementPosition(stmt->cond());
@@ -1155,12 +1163,12 @@
                   &book_keeping);
 
   // Check stack before looping.
-  PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->BackEdgeId(), BailoutState::NO_REGISTERS);
   __ bind(&book_keeping);
   EmitBackEdgeBookkeeping(stmt, &body);
   __ jmp(&body);
 
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   __ bind(loop_statement.break_label());
   decrement_loop_depth();
 }
@@ -1181,7 +1189,7 @@
                   loop_statement.break_label(),
                   &body);
 
-  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
   __ bind(&body);
   Visit(stmt->body());
 
@@ -1191,7 +1199,7 @@
   EmitBackEdgeBookkeeping(stmt, &loop);
   __ jmp(&loop);
 
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   __ bind(loop_statement.break_label());
   decrement_loop_depth();
 }
@@ -1214,11 +1222,11 @@
   // Emit the test at the bottom of the loop (even if empty).
   __ jmp(&test);
 
-  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
   __ bind(&body);
   Visit(stmt->body());
 
-  PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ContinueId(), BailoutState::NO_REGISTERS);
   __ bind(loop_statement.continue_label());
   if (stmt->next() != NULL) {
     SetStatementPosition(stmt->next());
@@ -1239,7 +1247,7 @@
     __ jmp(&body);
   }
 
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   __ bind(loop_statement.break_label());
   decrement_loop_depth();
 }
@@ -1252,6 +1260,7 @@
   increment_loop_depth();
 
   // var iterator = iterable[Symbol.iterator]();
+  SetExpressionAsStatementPosition(stmt->assign_iterator());
   VisitForEffect(stmt->assign_iterator());
 
   // Loop entry.
@@ -1274,12 +1283,12 @@
   Visit(stmt->body());
 
   // Check stack before looping.
-  PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->BackEdgeId(), BailoutState::NO_REGISTERS);
   EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
   __ jmp(loop_statement.continue_label());
 
   // Exit and decrement the loop depth.
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   __ bind(loop_statement.break_label());
   decrement_loop_depth();
 }
@@ -1423,7 +1432,7 @@
   __ DebugBreak();
   // Ignore the return value.
 
-  PrepareForBailoutForId(stmt->DebugBreakId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->DebugBreakId(), BailoutState::NO_REGISTERS);
 }
 
 
@@ -1438,7 +1447,7 @@
   VisitForControl(expr->condition(), &true_case, &false_case, &true_case);
 
   int original_stack_depth = operand_stack_depth_;
-  PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->ThenId(), BailoutState::NO_REGISTERS);
   __ bind(&true_case);
   SetExpressionPosition(expr->then_expression());
   if (context()->IsTest()) {
@@ -1453,7 +1462,7 @@
   }
 
   operand_stack_depth_ = original_stack_depth;
-  PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->ElseId(), BailoutState::NO_REGISTERS);
   __ bind(&false_case);
   SetExpressionPosition(expr->else_expression());
   VisitInDuplicateContext(expr->else_expression());
@@ -1504,7 +1513,7 @@
     PushOperand(Smi::FromInt(lit->end_position()));
 
     CallRuntimeWithOperands(Runtime::kDefineClass);
-    PrepareForBailoutForId(lit->CreateLiteralId(), TOS_REG);
+    PrepareForBailoutForId(lit->CreateLiteralId(), BailoutState::TOS_REGISTER);
     PushOperand(result_register());
 
     // Load the "prototype" from the constructor.
@@ -1512,14 +1521,15 @@
     __ LoadRoot(LoadDescriptor::NameRegister(),
                 Heap::kprototype_stringRootIndex);
     __ Move(LoadDescriptor::SlotRegister(), SmiFromSlot(lit->PrototypeSlot()));
-    CallLoadIC(NOT_INSIDE_TYPEOF);
-    PrepareForBailoutForId(lit->PrototypeId(), TOS_REG);
+    CallLoadIC();
+    PrepareForBailoutForId(lit->PrototypeId(), BailoutState::TOS_REGISTER);
     PushOperand(result_register());
 
     EmitClassDefineProperties(lit);
+    DropOperands(1);
 
-    // Set both the prototype and constructor to have fast properties.
-    CallRuntimeWithOperands(Runtime::kFinalizeClassDefinition);
+    // Set the constructor to have fast properties.
+    CallRuntimeWithOperands(Runtime::kToFastProperties);
 
     if (lit->class_variable_proxy() != nullptr) {
       EmitVariableAssignment(lit->class_variable_proxy()->var(), Token::INIT,
@@ -1530,6 +1540,19 @@
   context()->Plug(result_register());
 }
 
+void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
+  Comment cmnt(masm_, "[ RegExpLiteral");
+  Callable callable = CodeFactory::FastCloneRegExp(isolate());
+  CallInterfaceDescriptor descriptor = callable.descriptor();
+  LoadFromFrameField(JavaScriptFrameConstants::kFunctionOffset,
+                     descriptor.GetRegisterParameter(0));
+  __ Move(descriptor.GetRegisterParameter(1),
+          Smi::FromInt(expr->literal_index()));
+  __ Move(descriptor.GetRegisterParameter(2), expr->pattern());
+  __ Move(descriptor.GetRegisterParameter(3), Smi::FromInt(expr->flags()));
+  __ Call(callable.code(), RelocInfo::CODE_TARGET);
+  context()->Plug(result_register());
+}
 
 void FullCodeGenerator::VisitNativeFunctionLiteral(
     NativeFunctionLiteral* expr) {
@@ -1653,7 +1676,7 @@
       VisitForStackValue(args->at(i));
     }
 
-    PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+    PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
     EmitCallJSRuntimeFunction(expr);
     context()->DropAndPlug(1, result_register());
 
@@ -1675,7 +1698,7 @@
         }
 
         // Call the C runtime function.
-        PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
         __ CallRuntime(expr->function(), arg_count);
         OperandStackDepthDecrement(arg_count);
         context()->Plug(result_register());
@@ -1768,16 +1791,19 @@
   Expression* sub_expr;
   Handle<String> check;
   if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
+    SetExpressionPosition(expr);
     EmitLiteralCompareTypeof(expr, sub_expr, check);
     return true;
   }
 
   if (expr->IsLiteralCompareUndefined(&sub_expr)) {
+    SetExpressionPosition(expr);
     EmitLiteralCompareNil(expr, sub_expr, kUndefinedValue);
     return true;
   }
 
   if (expr->IsLiteralCompareNull(&sub_expr)) {
+    SetExpressionPosition(expr);
     EmitLiteralCompareNil(expr, sub_expr, kNullValue);
     return true;
   }
@@ -1861,7 +1887,7 @@
   saved_scope_ = codegen_->scope();
 
   if (scope == NULL) {
-    codegen_->PrepareForBailoutForId(entry_id, NO_REGISTERS);
+    codegen_->PrepareForBailoutForId(entry_id, BailoutState::NO_REGISTERS);
     needs_block_context_ = false;
   } else {
     needs_block_context_ = scope->NeedsContext();
@@ -1878,12 +1904,13 @@
                                     codegen_->context_register());
       }
       CHECK_EQ(0, scope->num_stack_slots());
-      codegen_->PrepareForBailoutForId(entry_id, NO_REGISTERS);
+      codegen_->PrepareForBailoutForId(entry_id, BailoutState::NO_REGISTERS);
     }
     {
       Comment cmnt(masm(), "[ Declarations");
       codegen_->VisitDeclarations(scope->declarations());
-      codegen_->PrepareForBailoutForId(declarations_id, NO_REGISTERS);
+      codegen_->PrepareForBailoutForId(declarations_id,
+                                       BailoutState::NO_REGISTERS);
     }
   }
 }
@@ -1897,7 +1924,7 @@
     codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
                                 codegen_->context_register());
   }
-  codegen_->PrepareForBailoutForId(exit_id_, NO_REGISTERS);
+  codegen_->PrepareForBailoutForId(exit_id_, BailoutState::NO_REGISTERS);
   codegen_->scope_ = saved_scope_;
 }
 
@@ -1956,7 +1983,7 @@
   DCHECK(var->initializer_position() != RelocInfo::kNoPosition);
   DCHECK(proxy->position() != RelocInfo::kNoPosition);
 
-  return var->mode() == CONST_LEGACY || var->scope()->is_nonlinear() ||
+  return var->scope()->is_nonlinear() ||
          var->initializer_position() >= proxy->position();
 }
 
diff --git a/src/full-codegen/full-codegen.h b/src/full-codegen/full-codegen.h
index 0c12937..87367ca 100644
--- a/src/full-codegen/full-codegen.h
+++ b/src/full-codegen/full-codegen.h
@@ -14,6 +14,7 @@
 #include "src/code-stubs.h"
 #include "src/codegen.h"
 #include "src/compiler.h"
+#include "src/deoptimizer.h"
 #include "src/globals.h"
 #include "src/objects.h"
 
@@ -28,11 +29,6 @@
 
 class FullCodeGenerator: public AstVisitor {
  public:
-  enum State {
-    NO_REGISTERS,
-    TOS_REG
-  };
-
   FullCodeGenerator(MacroAssembler* masm, CompilationInfo* info)
       : masm_(masm),
         info_(info),
@@ -60,19 +56,10 @@
 
   static bool MakeCode(CompilationInfo* info);
 
-  // Encode state and pc-offset as a BitField<type, start, size>.
+  // Encode bailout state and pc-offset as a BitField<type, start, size>.
   // Only use 30 bits because we encode the result as a smi.
-  class StateField : public BitField<State, 0, 1> { };
-  class PcField    : public BitField<unsigned, 1, 30-1> { };
-
-  static const char* State2String(State state) {
-    switch (state) {
-      case NO_REGISTERS: return "NO_REGISTERS";
-      case TOS_REG: return "TOS_REG";
-    }
-    UNREACHABLE();
-    return NULL;
-  }
+  class BailoutStateField : public BitField<Deoptimizer::BailoutState, 0, 1> {};
+  class PcField : public BitField<unsigned, 1, 30 - 1> {};
 
   static const int kMaxBackEdgeWeight = 127;
 
@@ -106,6 +93,8 @@
   static Register result_register();
 
  private:
+  typedef Deoptimizer::BailoutState BailoutState;
+
   class Breakable;
   class Iteration;
   class TryFinally;
@@ -366,21 +355,21 @@
     if (FLAG_verify_operand_stack_depth) EmitOperandStackDepthCheck();
     EffectContext context(this);
     Visit(expr);
-    PrepareForBailout(expr, NO_REGISTERS);
+    PrepareForBailout(expr, BailoutState::NO_REGISTERS);
   }
 
   void VisitForAccumulatorValue(Expression* expr) {
     if (FLAG_verify_operand_stack_depth) EmitOperandStackDepthCheck();
     AccumulatorValueContext context(this);
     Visit(expr);
-    PrepareForBailout(expr, TOS_REG);
+    PrepareForBailout(expr, BailoutState::TOS_REGISTER);
   }
 
   void VisitForStackValue(Expression* expr) {
     if (FLAG_verify_operand_stack_depth) EmitOperandStackDepthCheck();
     StackValueContext context(this);
     Visit(expr);
-    PrepareForBailout(expr, NO_REGISTERS);
+    PrepareForBailout(expr, BailoutState::NO_REGISTERS);
   }
 
   void VisitForControl(Expression* expr,
@@ -452,8 +441,8 @@
                              NilValue nil);
 
   // Bailout support.
-  void PrepareForBailout(Expression* node, State state);
-  void PrepareForBailoutForId(BailoutId id, State state);
+  void PrepareForBailout(Expression* node, Deoptimizer::BailoutState state);
+  void PrepareForBailoutForId(BailoutId id, Deoptimizer::BailoutState state);
 
   // Returns a smi for the index into the FixedArray that backs the feedback
   // vector
@@ -523,17 +512,11 @@
   F(NewObject)                          \
   F(ValueOf)                            \
   F(StringCharFromCode)                 \
-  F(StringCharAt)                       \
-  F(OneByteSeqStringSetChar)            \
-  F(TwoByteSeqStringSetChar)            \
   F(IsJSReceiver)                       \
   F(MathPow)                            \
   F(HasCachedArrayIndex)                \
   F(GetCachedArrayIndex)                \
   F(GetSuperConstructor)                \
-  F(GeneratorNext)                      \
-  F(GeneratorReturn)                    \
-  F(GeneratorThrow)                     \
   F(DebugBreakInOptimizedCode)          \
   F(ClassOf)                            \
   F(StringCharCodeAt)                   \
@@ -548,7 +531,6 @@
   F(ToName)                             \
   F(ToObject)                           \
   F(DebugIsActive)                      \
-  F(GetOrdinaryHasInstance)             \
   F(CreateIterResultObject)
 
 #define GENERATOR_DECLARATION(Name) void Emit##Name(CallRuntime* call);
@@ -557,10 +539,11 @@
 
   void EmitIntrinsicAsStubCall(CallRuntime* expr, const Callable& callable);
 
-  // Platform-specific code for resuming generators.
-  void EmitGeneratorResume(Expression *generator,
-                           Expression *value,
-                           JSGeneratorObject::ResumeMode resume_mode);
+  // Emits call to respective code stub.
+  void EmitHasProperty();
+
+  // Platform-specific code for restoring context from current JS frame.
+  void RestoreContext();
 
   // Platform-specific code for loading variables.
   void EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
@@ -577,7 +560,7 @@
   bool NeedsHoleCheckForLoad(VariableProxy* proxy);
 
   // Expects the arguments and the function already pushed.
-  void EmitResolvePossiblyDirectEval(int arg_count);
+  void EmitResolvePossiblyDirectEval(Call* expr);
 
   // Platform-specific support for allocating a new closure based on
   // the given function info.
@@ -671,9 +654,10 @@
   void CallIC(Handle<Code> code,
               TypeFeedbackId id = TypeFeedbackId::None());
 
+  void CallLoadIC(TypeFeedbackId id = TypeFeedbackId::None());
   // Inside typeof reference errors are never thrown.
-  void CallLoadIC(TypeofMode typeof_mode,
-                  TypeFeedbackId id = TypeFeedbackId::None());
+  void CallLoadGlobalIC(TypeofMode typeof_mode,
+                        TypeFeedbackId id = TypeFeedbackId::None());
   void CallStoreIC(TypeFeedbackId id = TypeFeedbackId::None());
 
   void SetFunctionPosition(FunctionLiteral* fun);
@@ -687,8 +671,7 @@
   // otherwise.
   void SetStatementPosition(Statement* stmt,
                             InsertBreak insert_break = INSERT_BREAK);
-  void SetExpressionPosition(Expression* expr,
-                             InsertBreak insert_break = SKIP_BREAK);
+  void SetExpressionPosition(Expression* expr);
 
   // Consider an expression a statement. As such, we also insert a break.
   // This is used in loop headers where we want to break for each iteration.
@@ -729,8 +712,6 @@
   Isolate* isolate() const { return isolate_; }
   Zone* zone() const { return zone_; }
   Handle<Script> script() { return info_->script(); }
-  bool is_eval() { return info_->is_eval(); }
-  bool is_native() { return info_->is_native(); }
   LanguageMode language_mode() { return scope()->language_mode(); }
   bool has_simple_parameters() { return info_->has_simple_parameters(); }
   FunctionLiteral* literal() const { return info_->literal(); }
diff --git a/src/full-codegen/ia32/full-codegen-ia32.cc b/src/full-codegen/ia32/full-codegen-ia32.cc
index f1945c8..c0f8396 100644
--- a/src/full-codegen/ia32/full-codegen-ia32.cc
+++ b/src/full-codegen/ia32/full-codegen-ia32.cc
@@ -168,7 +168,8 @@
       __ push(edi);
       __ Push(info->scope()->GetScopeInfo(info->isolate()));
       __ CallRuntime(Runtime::kNewScriptContext);
-      PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
+      PrepareForBailoutForId(BailoutId::ScriptContext(),
+                             BailoutState::TOS_REGISTER);
       // The new target value is not used, clobbering is safe.
       DCHECK_NULL(info->scope()->new_target_var());
     } else {
@@ -227,7 +228,8 @@
   // Register holding this function and new target are both trashed in case we
   // bailout here. But since that can happen only when new target is not used
   // and we allocate a context, the value of |function_in_register| is correct.
-  PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionContext(),
+                         BailoutState::NO_REGISTERS);
 
   // Possibly set up a local binding to the this function which is used in
   // derived constructors with super calls.
@@ -289,7 +291,8 @@
   }
 
   // Visit the declarations and body.
-  PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionEntry(),
+                         BailoutState::NO_REGISTERS);
   {
     Comment cmnt(masm_, "[ Declarations");
     VisitDeclarations(scope()->declarations());
@@ -302,7 +305,8 @@
 
   {
     Comment cmnt(masm_, "[ Stack check");
-    PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
+    PrepareForBailoutForId(BailoutId::Declarations(),
+                           BailoutState::NO_REGISTERS);
     Label ok;
     ExternalReference stack_limit =
         ExternalReference::address_of_stack_limit(isolate());
@@ -369,11 +373,11 @@
   EmitProfilingCounterReset();
 
   __ bind(&ok);
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
   // Record a mapping of the OSR id to this PC.  This is used if the OSR
   // entry becomes the target of a bailout.  We don't expect it to be, but
   // we want it to work if it is.
-  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
 }
 
 void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
@@ -423,6 +427,9 @@
   }
 }
 
+void FullCodeGenerator::RestoreContext() {
+  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+}
 
 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
   DCHECK(var->IsStackAllocated() || var->IsContextSlot());
@@ -483,10 +490,12 @@
                                           true,
                                           true_label_,
                                           false_label_);
-  DCHECK(lit->IsNull() || lit->IsUndefined() || !lit->IsUndetectable());
-  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
+  DCHECK(lit->IsNull(isolate()) || lit->IsUndefined(isolate()) ||
+         !lit->IsUndetectable());
+  if (lit->IsUndefined(isolate()) || lit->IsNull(isolate()) ||
+      lit->IsFalse(isolate())) {
     if (false_label_ != fall_through_) __ jmp(false_label_);
-  } else if (lit->IsTrue() || lit->IsJSObject()) {
+  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
     if (true_label_ != fall_through_) __ jmp(true_label_);
   } else if (lit->IsString()) {
     if (String::cast(*lit)->length() == 0) {
@@ -677,7 +686,7 @@
 
   Label skip;
   if (should_normalize) __ jmp(&skip, Label::kNear);
-  PrepareForBailout(expr, TOS_REG);
+  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
   if (should_normalize) {
     __ cmp(eax, isolate()->factory()->true_value());
     Split(equal, if_true, if_false, NULL);
@@ -708,14 +717,13 @@
   VariableProxy* proxy = declaration->proxy();
   VariableMode mode = declaration->mode();
   Variable* variable = proxy->var();
-  bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
+  bool hole_init = mode == LET || mode == CONST;
   switch (variable->location()) {
     case VariableLocation::GLOBAL:
     case VariableLocation::UNALLOCATED:
+      DCHECK(!variable->binding_needs_init());
       globals_->Add(variable->name(), zone());
-      globals_->Add(variable->binding_needs_init()
-                        ? isolate()->factory()->the_hole_value()
-                        : isolate()->factory()->undefined_value(), zone());
+      globals_->Add(isolate()->factory()->undefined_value(), zone());
       break;
 
     case VariableLocation::PARAMETER:
@@ -734,27 +742,17 @@
         __ mov(ContextOperand(esi, variable->index()),
                Immediate(isolate()->factory()->the_hole_value()));
         // No write barrier since the hole value is in old space.
-        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+        PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       }
       break;
 
     case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
+      DCHECK_EQ(VAR, mode);
+      DCHECK(!hole_init);
       __ push(Immediate(variable->name()));
-      // VariableDeclaration nodes are always introduced in one of four modes.
-      DCHECK(IsDeclaredVariableMode(mode));
-      // Push initial value, if any.
-      // Note: For variables we must not push an initial value (such as
-      // 'undefined') because we may have a (legal) redeclaration and we
-      // must not destroy the current value.
-      if (hole_init) {
-        __ push(Immediate(isolate()->factory()->the_hole_value()));
-      } else {
-        __ push(Immediate(Smi::FromInt(0)));  // Indicates no initial value.
-      }
-      __ push(
-          Immediate(Smi::FromInt(variable->DeclarationPropertyAttributes())));
-      __ CallRuntime(Runtime::kDeclareLookupSlot);
+      __ CallRuntime(Runtime::kDeclareEvalVar);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -798,7 +796,7 @@
                                 kDontSaveFPRegs,
                                 EMIT_REMEMBERED_SET,
                                 OMIT_SMI_CHECK);
-      PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
 
@@ -806,8 +804,8 @@
       Comment cmnt(masm_, "[ FunctionDeclaration");
       PushOperand(variable->name());
       VisitForStackValue(declaration->fun());
-      PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
-      CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
+      CallRuntimeWithOperands(Runtime::kDeclareEvalFunction);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -838,7 +836,7 @@
 
   // Keep the switch value on the stack until a case matches.
   VisitForStackValue(stmt->tag());
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
 
   ZoneList<CaseClause*>* clauses = stmt->cases();
   CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
@@ -887,7 +885,7 @@
 
     Label skip;
     __ jmp(&skip, Label::kNear);
-    PrepareForBailout(clause, TOS_REG);
+    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
     __ cmp(eax, isolate()->factory()->true_value());
     __ j(not_equal, &next_test);
     __ Drop(1);
@@ -915,12 +913,12 @@
     Comment cmnt(masm_, "[ Case body");
     CaseClause* clause = clauses->at(i);
     __ bind(clause->body_target());
-    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
+    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
     VisitStatements(clause->statements());
   }
 
   __ bind(nested_statement.break_label());
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
 }
 
 
@@ -953,15 +951,13 @@
   ToObjectStub stub(isolate());
   __ CallStub(&stub);
   __ bind(&done_convert);
-  PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
+  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
   __ push(eax);
 
-  // Check cache validity in generated code. This is a fast case for
-  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
-  // guarantee cache validity, call the runtime system to check cache
-  // validity or get the property names in a fixed array.
-  // Note: Proxies never have an enum cache, so will always take the
-  // slow path.
+  // Check cache validity in generated code. If we cannot guarantee cache
+  // validity, call the runtime system to check cache validity or get the
+  // property names in a fixed array. Note: Proxies never have an enum cache,
+  // so will always take the slow path.
   Label call_runtime, use_cache, fixed_array;
   __ CheckEnumCache(&call_runtime);
 
@@ -972,7 +968,7 @@
   __ bind(&call_runtime);
   __ push(eax);
   __ CallRuntime(Runtime::kForInEnumerate);
-  PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
+  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
   __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
          isolate()->factory()->meta_map());
   __ j(not_equal, &fixed_array);
@@ -1008,7 +1004,7 @@
   __ push(eax);  // Array
   __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
   __ push(eax);  // Fixed array length (as smi).
-  PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
   __ push(Immediate(Smi::FromInt(0)));  // Initial index.
 
   // Generate code for doing the condition check.
@@ -1046,7 +1042,7 @@
   __ push(ecx);  // Enumerable.
   __ push(ebx);  // Current entry.
   __ CallRuntime(Runtime::kForInFilter);
-  PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
+  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
   __ cmp(eax, isolate()->factory()->undefined_value());
   __ j(equal, loop_statement.continue_label());
   __ mov(ebx, eax);
@@ -1058,11 +1054,11 @@
   // Perform the assignment as if via '='.
   { EffectContext context(this);
     EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
-    PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
+    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
   }
 
   // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
-  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
   // Generate code for the body of the loop.
   Visit(stmt->body());
 
@@ -1079,7 +1075,7 @@
   DropOperands(5);
 
   // Exit and decrement the loop depth.
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   __ bind(&exit);
   decrement_loop_depth();
 }
@@ -1207,16 +1203,11 @@
   } else if (var->mode() == DYNAMIC_LOCAL) {
     Variable* local = var->local_if_not_shadowed();
     __ mov(eax, ContextSlotOperandCheckExtensions(local, slow));
-    if (local->mode() == LET || local->mode() == CONST ||
-        local->mode() == CONST_LEGACY) {
+    if (local->mode() == LET || local->mode() == CONST) {
       __ cmp(eax, isolate()->factory()->the_hole_value());
       __ j(not_equal, done);
-      if (local->mode() == CONST_LEGACY) {
-        __ mov(eax, isolate()->factory()->undefined_value());
-      } else {  // LET || CONST
-        __ push(Immediate(var->name()));
-        __ CallRuntime(Runtime::kThrowReferenceError);
-      }
+      __ push(Immediate(var->name()));
+      __ CallRuntime(Runtime::kThrowReferenceError);
     }
     __ jmp(done);
   }
@@ -1225,24 +1216,21 @@
 
 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
                                                TypeofMode typeof_mode) {
+#ifdef DEBUG
   Variable* var = proxy->var();
   DCHECK(var->IsUnallocatedOrGlobalSlot() ||
          (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
-  __ mov(LoadDescriptor::ReceiverRegister(), NativeContextOperand());
-  __ mov(LoadDescriptor::ReceiverRegister(),
-         ContextOperand(LoadDescriptor::ReceiverRegister(),
-                        Context::EXTENSION_INDEX));
-  __ mov(LoadDescriptor::NameRegister(), var->name());
-  __ mov(LoadDescriptor::SlotRegister(),
+#endif
+  __ mov(LoadGlobalDescriptor::SlotRegister(),
          Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
-  CallLoadIC(typeof_mode);
+  CallLoadGlobalIC(typeof_mode);
 }
 
 
 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
                                          TypeofMode typeof_mode) {
   SetExpressionPosition(proxy);
-  PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
+  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
   Variable* var = proxy->var();
 
   // Three cases: global variables, lookup variables, and all other types of
@@ -1274,10 +1262,6 @@
           // binding in harmony mode.
           __ push(Immediate(var->name()));
           __ CallRuntime(Runtime::kThrowReferenceError);
-        } else {
-          // Uninitialized legacy const bindings are unholed.
-          DCHECK(var->mode() == CONST_LEGACY);
-          __ mov(eax, isolate()->factory()->undefined_value());
         }
         __ bind(&done);
         context()->Plug(eax);
@@ -1308,18 +1292,6 @@
 }
 
 
-void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
-  Comment cmnt(masm_, "[ RegExpLiteral");
-  __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
-  __ Move(eax, Immediate(Smi::FromInt(expr->literal_index())));
-  __ Move(ecx, Immediate(expr->pattern()));
-  __ Move(edx, Immediate(Smi::FromInt(expr->flags())));
-  FastCloneRegExpStub stub(isolate());
-  __ CallStub(&stub);
-  context()->Plug(eax);
-}
-
-
 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
   Expression* expression = (property == NULL) ? NULL : property->value();
   if (expression == NULL) {
@@ -1356,8 +1328,9 @@
     __ mov(edx, Immediate(Smi::FromInt(flags)));
     FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
     __ CallStub(&stub);
+    RestoreContext();
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   // If result_saved is true the result is on top of the stack.  If
   // result_saved is false the result is in eax.
@@ -1393,7 +1366,7 @@
             __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
             EmitLoadStoreICSlot(property->GetSlot(0));
             CallStoreIC();
-            PrepareForBailoutForId(key->id(), NO_REGISTERS);
+            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
             if (NeedsHomeObject(value)) {
               EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
             }
@@ -1421,16 +1394,20 @@
         DCHECK(property->emit_store());
         CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
         PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                               NO_REGISTERS);
+                               BailoutState::NO_REGISTERS);
         break;
       case ObjectLiteral::Property::GETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->getter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->getter = property;
         }
         break;
       case ObjectLiteral::Property::SETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->setter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->setter = property;
         }
         break;
     }
@@ -1449,6 +1426,7 @@
 
     PushOperand(Smi::FromInt(NONE));
     CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
+    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
   }
 
   // Object literals have two parts. The "static" part on the left contains no
@@ -1477,7 +1455,7 @@
       DCHECK(property->emit_store());
       CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
       PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                             NO_REGISTERS);
+                             BailoutState::NO_REGISTERS);
     } else {
       EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
       VisitForStackValue(value);
@@ -1493,6 +1471,8 @@
             PushOperand(Smi::FromInt(NONE));
             PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
             CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
+            PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
+                                   BailoutState::NO_REGISTERS);
           } else {
             DropOperands(3);
           }
@@ -1550,7 +1530,7 @@
     FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
     __ CallStub(&stub);
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   bool result_saved = false;  // Is the result saved to the stack?
   ZoneList<Expression*>* subexprs = expr->values();
@@ -1580,7 +1560,8 @@
     Handle<Code> ic =
         CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
     CallIC(ic);
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   // In case the array literal contains spread expressions it has two parts. The
@@ -1600,7 +1581,8 @@
     VisitForStackValue(subexpr);
     CallRuntimeWithOperands(Runtime::kAppendElement);
 
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   if (result_saved) {
@@ -1615,7 +1597,6 @@
   DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
 
   Comment cmnt(masm_, "[ Assignment");
-  SetExpressionPosition(expr, INSERT_BREAK);
 
   Property* property = expr->target()->AsProperty();
   LhsKind assign_type = Property::GetAssignType(property);
@@ -1680,23 +1661,27 @@
       switch (assign_type) {
         case VARIABLE:
           EmitVariableLoad(expr->target()->AsVariableProxy());
-          PrepareForBailout(expr->target(), TOS_REG);
+          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
           break;
         case NAMED_SUPER_PROPERTY:
           EmitNamedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case NAMED_PROPERTY:
           EmitNamedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_SUPER_PROPERTY:
           EmitKeyedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_PROPERTY:
           EmitKeyedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
       }
     }
@@ -1715,7 +1700,7 @@
     }
 
     // Deoptimization point in case the binary operation may have side effects.
-    PrepareForBailout(expr->binary_operation(), TOS_REG);
+    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
   } else {
     VisitForAccumulatorValue(expr->value());
   }
@@ -1727,7 +1712,7 @@
     case VARIABLE:
       EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
                              expr->op(), expr->AssignmentSlot());
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       context()->Plug(eax);
       break;
     case NAMED_PROPERTY:
@@ -1756,21 +1741,26 @@
   // this.  It stays on the stack while we update the iterator.
   VisitForStackValue(expr->expression());
 
-  Label suspend, continuation, post_runtime, resume;
+  Label suspend, continuation, post_runtime, resume, exception;
 
   __ jmp(&suspend);
   __ bind(&continuation);
-  // When we arrive here, the stack top is the resume mode and
-  // result_register() holds the input value (the argument given to the
-  // respective resume operation).
+  // When we arrive here, eax holds the generator object.
   __ RecordGeneratorContinuation();
-  __ pop(ebx);
-  __ cmp(ebx, Immediate(Smi::FromInt(JSGeneratorObject::RETURN)));
-  __ j(not_equal, &resume);
-  __ push(result_register());
+  __ mov(ebx, FieldOperand(eax, JSGeneratorObject::kResumeModeOffset));
+  __ mov(eax, FieldOperand(eax, JSGeneratorObject::kInputOrDebugPosOffset));
+  STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
+  STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
+  __ cmp(ebx, Immediate(Smi::FromInt(JSGeneratorObject::kReturn)));
+  __ j(less, &resume);
+  __ Push(result_register());
+  __ j(greater, &exception);
   EmitCreateIteratorResult(true);
   EmitUnwindAndReturn();
 
+  __ bind(&exception);
+  __ CallRuntime(Runtime::kThrow);
+
   __ bind(&suspend);
   OperandStackDepthIncrement(1);  // Not popped on this path.
   VisitForAccumulatorValue(expr->generator_object());
@@ -1786,8 +1776,7 @@
   __ j(equal, &post_runtime);
   __ push(eax);  // generator object
   __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
-  __ mov(context_register(),
-         Operand(ebp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   __ bind(&post_runtime);
   PopOperand(result_register());
   EmitReturnSequence();
@@ -1796,101 +1785,6 @@
   context()->Plug(result_register());
 }
 
-
-void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
-    Expression *value,
-    JSGeneratorObject::ResumeMode resume_mode) {
-  // The value stays in eax, and is ultimately read by the resumed generator, as
-  // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it
-  // is read to throw the value when the resumed generator is already closed.
-  // ebx will hold the generator object until the activation has been resumed.
-  VisitForStackValue(generator);
-  VisitForAccumulatorValue(value);
-  PopOperand(ebx);
-
-  // Store input value into generator object.
-  __ mov(FieldOperand(ebx, JSGeneratorObject::kInputOffset), result_register());
-  __ mov(ecx, result_register());
-  __ RecordWriteField(ebx, JSGeneratorObject::kInputOffset, ecx, edx,
-                      kDontSaveFPRegs);
-
-  // Load suspended function and context.
-  __ mov(esi, FieldOperand(ebx, JSGeneratorObject::kContextOffset));
-  __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset));
-
-  // Push receiver.
-  __ push(FieldOperand(ebx, JSGeneratorObject::kReceiverOffset));
-
-  // Push holes for arguments to generator function. Since the parser forced
-  // context allocation for any variables in generators, the actual argument
-  // values have already been copied into the context and these dummy values
-  // will never be used.
-  __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
-  __ mov(edx,
-         FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ mov(ecx, isolate()->factory()->the_hole_value());
-  Label push_argument_holes, push_frame;
-  __ bind(&push_argument_holes);
-  __ sub(edx, Immediate(Smi::FromInt(1)));
-  __ j(carry, &push_frame);
-  __ push(ecx);
-  __ jmp(&push_argument_holes);
-
-  // Enter a new JavaScript frame, and initialize its slots as they were when
-  // the generator was suspended.
-  Label resume_frame, done;
-  __ bind(&push_frame);
-  __ call(&resume_frame);
-  __ jmp(&done);
-  __ bind(&resume_frame);
-  __ push(ebp);  // Caller's frame pointer.
-  __ mov(ebp, esp);
-  __ push(esi);  // Callee's context.
-  __ push(edi);  // Callee's JS Function.
-
-  // Load the operand stack size.
-  __ mov(edx, FieldOperand(ebx, JSGeneratorObject::kOperandStackOffset));
-  __ mov(edx, FieldOperand(edx, FixedArray::kLengthOffset));
-  __ SmiUntag(edx);
-
-  // If we are sending a value and there is no operand stack, we can jump back
-  // in directly.
-  if (resume_mode == JSGeneratorObject::NEXT) {
-    Label slow_resume;
-    __ cmp(edx, Immediate(0));
-    __ j(not_zero, &slow_resume);
-    __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
-    __ mov(ecx, FieldOperand(ebx, JSGeneratorObject::kContinuationOffset));
-    __ SmiUntag(ecx);
-    __ add(edx, ecx);
-    __ mov(FieldOperand(ebx, JSGeneratorObject::kContinuationOffset),
-           Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
-    __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-    __ jmp(edx);
-    __ bind(&slow_resume);
-  }
-
-  // Otherwise, we push holes for the operand stack and call the runtime to fix
-  // up the stack and the handlers.
-  Label push_operand_holes, call_resume;
-  __ bind(&push_operand_holes);
-  __ sub(edx, Immediate(1));
-  __ j(carry, &call_resume);
-  __ push(ecx);
-  __ jmp(&push_operand_holes);
-  __ bind(&call_resume);
-  __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-  __ push(ebx);
-  __ push(result_register());
-  __ Push(Smi::FromInt(resume_mode));
-  __ CallRuntime(Runtime::kResumeJSGeneratorObject);
-  // Not reached: the runtime call returns elsewhere.
-  __ Abort(kGeneratorFailedToResume);
-
-  __ bind(&done);
-  context()->Plug(result_register());
-}
-
 void FullCodeGenerator::PushOperand(MemOperand operand) {
   OperandStackDepthIncrement(1);
   __ Push(operand);
@@ -1910,7 +1804,8 @@
 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
   Label allocate, done_allocate;
 
-  __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate,
+              NO_ALLOCATION_FLAGS);
   __ jmp(&done_allocate, Label::kNear);
 
   __ bind(&allocate);
@@ -2232,8 +2127,7 @@
     __ bind(&uninitialized_this);
     EmitStoreToStackLocalOrContextSlot(var, location);
 
-  } else if (!var->is_const_mode() ||
-             (var->mode() == CONST && op == Token::INIT)) {
+  } else if (!var->is_const_mode() || op == Token::INIT) {
     if (var->IsLookupSlot()) {
       // Assignment to var.
       __ Push(Immediate(var->name()));
@@ -2255,25 +2149,6 @@
       EmitStoreToStackLocalOrContextSlot(var, location);
     }
 
-  } else if (var->mode() == CONST_LEGACY && op == Token::INIT) {
-    // Const initializers need a write barrier.
-    DCHECK(!var->IsParameter());  // No const parameters.
-    if (var->IsLookupSlot()) {
-      __ push(eax);
-      __ push(esi);
-      __ push(Immediate(var->name()));
-      __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot);
-    } else {
-      DCHECK(var->IsStackLocal() || var->IsContextSlot());
-      Label skip;
-      MemOperand location = VarOperand(var, ecx);
-      __ mov(edx, location);
-      __ cmp(edx, isolate()->factory()->the_hole_value());
-      __ j(not_equal, &skip, Label::kNear);
-      EmitStoreToStackLocalOrContextSlot(var, location);
-      __ bind(&skip);
-    }
-
   } else {
     DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT);
     if (is_strict(language_mode())) {
@@ -2296,7 +2171,7 @@
   PopOperand(StoreDescriptor::ReceiverRegister());
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallStoreIC();
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(eax);
 }
 
@@ -2342,44 +2217,7 @@
       CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallIC(ic);
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
-  context()->Plug(eax);
-}
-
-
-void FullCodeGenerator::VisitProperty(Property* expr) {
-  Comment cmnt(masm_, "[ Property");
-  SetExpressionPosition(expr);
-
-  Expression* key = expr->key();
-
-  if (key->IsPropertyName()) {
-    if (!expr->IsSuperAccess()) {
-      VisitForAccumulatorValue(expr->obj());
-      __ Move(LoadDescriptor::ReceiverRegister(), result_register());
-      EmitNamedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      EmitNamedSuperPropertyLoad(expr);
-    }
-  } else {
-    if (!expr->IsSuperAccess()) {
-      VisitForStackValue(expr->obj());
-      VisitForAccumulatorValue(expr->key());
-      PopOperand(LoadDescriptor::ReceiverRegister());              // Object.
-      __ Move(LoadDescriptor::NameRegister(), result_register());  // Key.
-      EmitKeyedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      VisitForStackValue(expr->key());
-      EmitKeyedSuperPropertyLoad(expr);
-    }
-  }
-  PrepareForBailoutForId(expr->LoadId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(eax);
 }
 
@@ -2400,7 +2238,7 @@
   if (callee->IsVariableProxy()) {
     { StackValueContext context(this);
       EmitVariableLoad(callee->AsVariableProxy());
-      PrepareForBailout(callee, NO_REGISTERS);
+      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
     }
     // Push undefined as receiver. This is patched in the method prologue if it
     // is a sloppy mode method.
@@ -2412,7 +2250,8 @@
     DCHECK(!callee->AsProperty()->IsSuperAccess());
     __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
     EmitNamedPropertyLoad(callee->AsProperty());
-    PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                           BailoutState::TOS_REGISTER);
     // Push the target function under the receiver.
     PushOperand(Operand(esp, 0));
     __ mov(Operand(esp, kPointerSize), eax);
@@ -2447,6 +2286,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ mov(Operand(esp, kPointerSize), eax);
@@ -2471,7 +2311,8 @@
   __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
   __ mov(LoadDescriptor::NameRegister(), eax);
   EmitKeyedPropertyLoad(callee->AsProperty());
-  PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                         BailoutState::TOS_REGISTER);
 
   // Push the target function under the receiver.
   PushOperand(Operand(esp, 0));
@@ -2503,6 +2344,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ mov(Operand(esp, kPointerSize), eax);
@@ -2522,7 +2364,7 @@
     VisitForStackValue(args->at(i));
   }
 
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   SetCallPosition(expr, expr->tail_call_mode());
   if (expr->tail_call_mode() == TailCallMode::kAllow) {
     if (FLAG_trace) {
@@ -2543,15 +2385,12 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-
-  // Restore context register.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-
+  RestoreContext();
   context()->DropAndPlug(1, eax);
 }
 
-
-void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
+void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
+  int arg_count = expr->arguments()->length();
   // Push copy of the first argument or undefined if it doesn't exist.
   if (arg_count > 0) {
     __ push(Operand(esp, arg_count * kPointerSize));
@@ -2568,6 +2407,9 @@
   // Push the start position of the scope the calls resides in.
   __ push(Immediate(Smi::FromInt(scope()->start_position())));
 
+  // Push the source position of the eval call.
+  __ push(Immediate(Smi::FromInt(expr->position())));
+
   // Do the runtime call.
   __ CallRuntime(Runtime::kResolvePossiblyDirectEval);
 }
@@ -2590,7 +2432,7 @@
     __ CallRuntime(Runtime::kLoadLookupSlotForCall);
     PushOperand(eax);  // Function.
     PushOperand(edx);  // Receiver.
-    PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
+    PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
 
     // If fast case code has been generated, emit code to push the function
     // and receiver and have the slow path jump around this code.
@@ -2614,7 +2456,7 @@
 
 
 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
-  // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
+  // In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
   // to resolve the function we need to call.  Then we call the resolved
   // function using the given arguments.
   ZoneList<Expression*>* args = expr->arguments();
@@ -2630,12 +2472,12 @@
   // Push a copy of the function (found below the arguments) and
   // resolve eval.
   __ push(Operand(esp, (arg_count + 1) * kPointerSize));
-  EmitResolvePossiblyDirectEval(arg_count);
+  EmitResolvePossiblyDirectEval(expr);
 
   // Touch up the stack with the resolved function.
   __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
 
-  PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
 
   SetCallPosition(expr);
   __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
@@ -2645,8 +2487,7 @@
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
   RecordJSReturnSite(expr);
-  // Restore context register.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->DropAndPlug(1, eax);
 }
 
@@ -2685,9 +2526,8 @@
   CallConstructStub stub(isolate());
   __ call(stub.GetCode(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
-  // Restore context register.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
+  RestoreContext();
   context()->Plug(eax);
 }
 
@@ -2728,9 +2568,7 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-
-  // Restore context register.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->Plug(eax);
 }
 
@@ -2935,75 +2773,6 @@
 }
 
 
-void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = eax;
-  Register index = ebx;
-  Register value = ecx;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-
-  PopOperand(value);
-  PopOperand(index);
-
-  if (FLAG_debug_code) {
-    __ test(value, Immediate(kSmiTagMask));
-    __ Check(zero, kNonSmiValue);
-    __ test(index, Immediate(kSmiTagMask));
-    __ Check(zero, kNonSmiValue);
-  }
-
-  __ SmiUntag(value);
-  __ SmiUntag(index);
-
-  if (FLAG_debug_code) {
-    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
-  }
-
-  __ mov_b(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize),
-           value);
-  context()->Plug(string);
-}
-
-
-void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = eax;
-  Register index = ebx;
-  Register value = ecx;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-  PopOperand(value);
-  PopOperand(index);
-
-  if (FLAG_debug_code) {
-    __ test(value, Immediate(kSmiTagMask));
-    __ Check(zero, kNonSmiValue);
-    __ test(index, Immediate(kSmiTagMask));
-    __ Check(zero, kNonSmiValue);
-    __ SmiUntag(index);
-    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
-    __ SmiTag(index);
-  }
-
-  __ SmiUntag(value);
-  // No need to untag a smi for two-byte addressing.
-  __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize),
-           value);
-  context()->Plug(string);
-}
-
-
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
@@ -3039,13 +2808,8 @@
   Label need_conversion;
   Label index_out_of_range;
   Label done;
-  StringCharCodeAtGenerator generator(object,
-                                      index,
-                                      result,
-                                      &need_conversion,
-                                      &need_conversion,
-                                      &index_out_of_range,
-                                      STRING_INDEX_IS_NUMBER);
+  StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
+                                      &need_conversion, &index_out_of_range);
   generator.GenerateFast(masm_);
   __ jmp(&done);
 
@@ -3069,54 +2833,6 @@
 }
 
 
-void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK(args->length() == 2);
-
-  VisitForStackValue(args->at(0));
-  VisitForAccumulatorValue(args->at(1));
-
-  Register object = ebx;
-  Register index = eax;
-  Register scratch = edx;
-  Register result = eax;
-
-  PopOperand(object);
-
-  Label need_conversion;
-  Label index_out_of_range;
-  Label done;
-  StringCharAtGenerator generator(object,
-                                  index,
-                                  scratch,
-                                  result,
-                                  &need_conversion,
-                                  &need_conversion,
-                                  &index_out_of_range,
-                                  STRING_INDEX_IS_NUMBER);
-  generator.GenerateFast(masm_);
-  __ jmp(&done);
-
-  __ bind(&index_out_of_range);
-  // When the index is out of range, the spec requires us to return
-  // the empty string.
-  __ Move(result, Immediate(isolate()->factory()->empty_string()));
-  __ jmp(&done);
-
-  __ bind(&need_conversion);
-  // Move smi zero into the result register, which will trigger
-  // conversion.
-  __ Move(result, Immediate(Smi::FromInt(0)));
-  __ jmp(&done);
-
-  NopRuntimeCallHelper call_helper;
-  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
-
-  __ bind(&done);
-  context()->Plug(result);
-}
-
-
 void FullCodeGenerator::EmitCall(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK_LE(2, args->length());
@@ -3124,7 +2840,7 @@
   for (Expression* const arg : *args) {
     VisitForStackValue(arg);
   }
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   // Move target to edi.
   int const argc = args->length() - 2;
   __ mov(edi, Operand(esp, (argc + 1) * kPointerSize));
@@ -3132,8 +2848,7 @@
   __ mov(eax, Immediate(argc));
   __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(argc + 1);
-  // Restore context register.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   // Discard the function left on TOS.
   context()->DropAndPlug(1, eax);
 }
@@ -3187,13 +2902,6 @@
   context()->Plug(eax);
 }
 
-void FullCodeGenerator::EmitGetOrdinaryHasInstance(CallRuntime* expr) {
-  DCHECK_EQ(0, expr->arguments()->length());
-  __ mov(eax, NativeContextOperand());
-  __ mov(eax, ContextOperand(eax, Context::ORDINARY_HAS_INSTANCE_INDEX));
-  context()->Plug(eax);
-}
-
 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
   DCHECK(expr->arguments()->length() == 0);
   ExternalReference debug_is_active =
@@ -3212,7 +2920,8 @@
 
   Label runtime, done;
 
-  __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &runtime, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &runtime,
+              NO_ALLOCATION_FLAGS);
   __ mov(ebx, NativeContextOperand());
   __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX));
   __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx);
@@ -3253,9 +2962,7 @@
   __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-
-  // Restore context register.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
 }
 
 
@@ -3340,7 +3047,8 @@
                         &materialize_true);
         if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
         __ bind(&materialize_true);
-        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeTrueId(),
+                               BailoutState::NO_REGISTERS);
         if (context()->IsAccumulatorValue()) {
           __ mov(eax, isolate()->factory()->true_value());
         } else {
@@ -3348,7 +3056,8 @@
         }
         __ jmp(&done, Label::kNear);
         __ bind(&materialize_false);
-        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeFalseId(),
+                               BailoutState::NO_REGISTERS);
         if (context()->IsAccumulatorValue()) {
           __ mov(eax, isolate()->factory()->false_value());
         } else {
@@ -3447,9 +3156,9 @@
   // We need a second deoptimization point after loading the value
   // in case evaluating the property load my have a side effect.
   if (assign_type == VARIABLE) {
-    PrepareForBailout(expr->expression(), TOS_REG);
+    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
   } else {
-    PrepareForBailoutForId(prop->LoadId(), TOS_REG);
+    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
   }
 
   // Inline smi case if we are in a loop.
@@ -3502,9 +3211,8 @@
   }
 
   // Convert old value into a number.
-  ToNumberStub convert_stub(isolate());
-  __ CallStub(&convert_stub);
-  PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
+  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
+  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
 
   // Save result for postfix expressions.
   if (expr->is_postfix()) {
@@ -3552,7 +3260,8 @@
         { EffectContext context(this);
           EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                  Token::ASSIGN, expr->CountSlot());
-          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+          PrepareForBailoutForId(expr->AssignmentId(),
+                                 BailoutState::TOS_REGISTER);
           context.Plug(eax);
         }
         // For all contexts except EffectContext We have the result on
@@ -3564,7 +3273,8 @@
         // Perform the assignment as if via '='.
         EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                Token::ASSIGN, expr->CountSlot());
-        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+        PrepareForBailoutForId(expr->AssignmentId(),
+                               BailoutState::TOS_REGISTER);
         context()->Plug(eax);
       }
       break;
@@ -3574,7 +3284,7 @@
       PopOperand(StoreDescriptor::ReceiverRegister());
       EmitLoadStoreICSlot(expr->CountSlot());
       CallStoreIC();
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         if (!context()->IsEffect()) {
           context()->PlugTOS();
@@ -3613,7 +3323,7 @@
           CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
       EmitLoadStoreICSlot(expr->CountSlot());
       CallIC(ic);
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         // Result is on the stack
         if (!context()->IsEffect()) {
@@ -3709,7 +3419,6 @@
 
 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
   Comment cmnt(masm_, "[ CompareOperation");
-  SetExpressionPosition(expr);
 
   // First we try a fast inlined version of the compare when one of
   // the operands is a literal.
@@ -3729,7 +3438,8 @@
   switch (op) {
     case Token::IN:
       VisitForStackValue(expr->right());
-      CallRuntimeWithOperands(Runtime::kHasProperty);
+      SetExpressionPosition(expr);
+      EmitHasProperty();
       PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
       __ cmp(eax, isolate()->factory()->true_value());
       Split(equal, if_true, if_false, fall_through);
@@ -3737,6 +3447,7 @@
 
     case Token::INSTANCEOF: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       PopOperand(edx);
       InstanceOfStub stub(isolate());
       __ CallStub(&stub);
@@ -3748,6 +3459,7 @@
 
     default: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       Condition cc = CompareIC::ComputeCondition(op);
       PopOperand(edx);
 
diff --git a/src/full-codegen/mips/full-codegen-mips.cc b/src/full-codegen/mips/full-codegen-mips.cc
index f329a23..014aaf6 100644
--- a/src/full-codegen/mips/full-codegen-mips.cc
+++ b/src/full-codegen/mips/full-codegen-mips.cc
@@ -186,7 +186,8 @@
       __ push(a1);
       __ Push(info->scope()->GetScopeInfo(info->isolate()));
       __ CallRuntime(Runtime::kNewScriptContext);
-      PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
+      PrepareForBailoutForId(BailoutId::ScriptContext(),
+                             BailoutState::TOS_REGISTER);
       // The new target value is not used, clobbering is safe.
       DCHECK_NULL(info->scope()->new_target_var());
     } else {
@@ -242,7 +243,8 @@
   // Register holding this function and new target are both trashed in case we
   // bailout here. But since that can happen only when new target is not used
   // and we allocate a context, the value of |function_in_register| is correct.
-  PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionContext(),
+                         BailoutState::NO_REGISTERS);
 
   // Possibly set up a local binding to the this function which is used in
   // derived constructors with super calls.
@@ -305,7 +307,8 @@
 
   // Visit the declarations and body unless there is an illegal
   // redeclaration.
-  PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionEntry(),
+                         BailoutState::NO_REGISTERS);
   {
     Comment cmnt(masm_, "[ Declarations");
     VisitDeclarations(scope()->declarations());
@@ -318,7 +321,8 @@
 
   {
     Comment cmnt(masm_, "[ Stack check");
-    PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
+    PrepareForBailoutForId(BailoutId::Declarations(),
+                           BailoutState::NO_REGISTERS);
     Label ok;
     __ LoadRoot(at, Heap::kStackLimitRootIndex);
     __ Branch(&ok, hs, sp, Operand(at));
@@ -397,11 +401,11 @@
   EmitProfilingCounterReset();
 
   __ bind(&ok);
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
   // Record a mapping of the OSR id to this PC.  This is used if the OSR
   // entry becomes the target of a bailout.  We don't expect it to be, but
   // we want it to work if it is.
-  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
 }
 
 void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
@@ -459,6 +463,9 @@
   }
 }
 
+void FullCodeGenerator::RestoreContext() {
+  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+}
 
 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
   DCHECK(var->IsStackAllocated() || var->IsContextSlot());
@@ -524,10 +531,12 @@
                                           true,
                                           true_label_,
                                           false_label_);
-  DCHECK(lit->IsNull() || lit->IsUndefined() || !lit->IsUndetectable());
-  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
+  DCHECK(lit->IsNull(isolate()) || lit->IsUndefined(isolate()) ||
+         !lit->IsUndetectable());
+  if (lit->IsUndefined(isolate()) || lit->IsNull(isolate()) ||
+      lit->IsFalse(isolate())) {
     if (false_label_ != fall_through_) __ Branch(false_label_);
-  } else if (lit->IsTrue() || lit->IsJSObject()) {
+  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
     if (true_label_ != fall_through_) __ Branch(true_label_);
   } else if (lit->IsString()) {
     if (String::cast(*lit)->length() == 0) {
@@ -724,7 +733,7 @@
 
   Label skip;
   if (should_normalize) __ Branch(&skip);
-  PrepareForBailout(expr, TOS_REG);
+  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
   if (should_normalize) {
     __ LoadRoot(t0, Heap::kTrueValueRootIndex);
     Split(eq, a0, Operand(t0), if_true, if_false, NULL);
@@ -758,15 +767,13 @@
   VariableProxy* proxy = declaration->proxy();
   VariableMode mode = declaration->mode();
   Variable* variable = proxy->var();
-  bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
+  bool hole_init = mode == LET || mode == CONST;
   switch (variable->location()) {
     case VariableLocation::GLOBAL:
     case VariableLocation::UNALLOCATED:
+      DCHECK(!variable->binding_needs_init());
       globals_->Add(variable->name(), zone());
-      globals_->Add(variable->binding_needs_init()
-                        ? isolate()->factory()->the_hole_value()
-                        : isolate()->factory()->undefined_value(),
-                    zone());
+      globals_->Add(isolate()->factory()->undefined_value(), zone());
       break;
 
     case VariableLocation::PARAMETER:
@@ -785,28 +792,18 @@
           __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
           __ sw(at, ContextMemOperand(cp, variable->index()));
           // No write barrier since the_hole_value is in old space.
-          PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+          PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       }
       break;
 
     case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
+      DCHECK_EQ(VAR, mode);
+      DCHECK(!hole_init);
       __ li(a2, Operand(variable->name()));
-      // Declaration nodes are always introduced in one of four modes.
-      DCHECK(IsDeclaredVariableMode(mode));
-      // Push initial value, if any.
-      // Note: For variables we must not push an initial value (such as
-      // 'undefined') because we may have a (legal) redeclaration and we
-      // must not destroy the current value.
-      if (hole_init) {
-        __ LoadRoot(a0, Heap::kTheHoleValueRootIndex);
-      } else {
-        DCHECK(Smi::FromInt(0) == 0);
-        __ mov(a0, zero_reg);  // Smi::FromInt(0) indicates no initial value.
-      }
-      __ Push(a2, a0);
-      __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes()));
-      __ CallRuntime(Runtime::kDeclareLookupSlot);
+      __ Push(a2);
+      __ CallRuntime(Runtime::kDeclareEvalVar);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -852,7 +849,7 @@
                                 kDontSaveFPRegs,
                                 EMIT_REMEMBERED_SET,
                                 OMIT_SMI_CHECK);
-      PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
 
@@ -862,8 +859,8 @@
       PushOperand(a2);
       // Push initial value for function declaration.
       VisitForStackValue(declaration->fun());
-      PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
-      CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
+      CallRuntimeWithOperands(Runtime::kDeclareEvalFunction);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -895,7 +892,7 @@
 
   // Keep the switch value on the stack until a case matches.
   VisitForStackValue(stmt->tag());
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
 
   ZoneList<CaseClause*>* clauses = stmt->cases();
   CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
@@ -945,7 +942,7 @@
 
     Label skip;
     __ Branch(&skip);
-    PrepareForBailout(clause, TOS_REG);
+    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
     __ LoadRoot(at, Heap::kTrueValueRootIndex);
     __ Branch(&next_test, ne, v0, Operand(at));
     __ Drop(1);
@@ -972,12 +969,12 @@
     Comment cmnt(masm_, "[ Case body");
     CaseClause* clause = clauses->at(i);
     __ bind(clause->body_target());
-    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
+    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
     VisitStatements(clause->statements());
   }
 
   __ bind(nested_statement.break_label());
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
 }
 
 
@@ -1013,15 +1010,13 @@
   __ CallStub(&stub);
   __ mov(a0, v0);
   __ bind(&done_convert);
-  PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
+  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
   __ push(a0);
 
-  // Check cache validity in generated code. This is a fast case for
-  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
-  // guarantee cache validity, call the runtime system to check cache
-  // validity or get the property names in a fixed array.
-  // Note: Proxies never have an enum cache, so will always take the
-  // slow path.
+  // Check cache validity in generated code. If we cannot guarantee cache
+  // validity, call the runtime system to check cache validity or get the
+  // property names in a fixed array. Note: Proxies never have an enum cache,
+  // so will always take the slow path.
   Label call_runtime;
   __ CheckEnumCache(&call_runtime);
 
@@ -1035,7 +1030,7 @@
   __ bind(&call_runtime);
   __ push(a0);  // Duplicate the enumerable object on the stack.
   __ CallRuntime(Runtime::kForInEnumerate);
-  PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
+  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
 
   // If we got a map from the runtime call, we can do a fast
   // modification check. Otherwise, we got a fixed array, and we have
@@ -1073,7 +1068,7 @@
   __ Push(a1, v0);  // Smi and array
   __ lw(a1, FieldMemOperand(v0, FixedArray::kLengthOffset));
   __ Push(a1);  // Fixed array length (as smi).
-  PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
   __ li(a0, Operand(Smi::FromInt(0)));
   __ Push(a0);  // Initial index.
 
@@ -1114,7 +1109,7 @@
   // just skip it.
   __ Push(a1, a3);  // Enumerable and current entry.
   __ CallRuntime(Runtime::kForInFilter);
-  PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
+  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
   __ mov(a3, result_register());
   __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
   __ Branch(loop_statement.continue_label(), eq, a3, Operand(at));
@@ -1126,11 +1121,11 @@
   // Perform the assignment as if via '='.
   { EffectContext context(this);
     EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
-    PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
+    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
   }
 
   // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
-  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
   // Generate code for the body of the loop.
   Visit(stmt->body());
 
@@ -1149,7 +1144,7 @@
   DropOperands(5);
 
   // Exit and decrement the loop depth.
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   __ bind(&exit);
   decrement_loop_depth();
 }
@@ -1278,19 +1273,13 @@
   } else if (var->mode() == DYNAMIC_LOCAL) {
     Variable* local = var->local_if_not_shadowed();
     __ lw(v0, ContextSlotOperandCheckExtensions(local, slow));
-    if (local->mode() == LET || local->mode() == CONST ||
-        local->mode() == CONST_LEGACY) {
+    if (local->mode() == LET || local->mode() == CONST) {
       __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
       __ subu(at, v0, at);  // Sub as compare: at == 0 on eq.
-      if (local->mode() == CONST_LEGACY) {
-        __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
-        __ Movz(v0, a0, at);  // Conditional move: return Undefined if TheHole.
-      } else {  // LET || CONST
-        __ Branch(done, ne, at, Operand(zero_reg));
-        __ li(a0, Operand(var->name()));
-        __ push(a0);
-        __ CallRuntime(Runtime::kThrowReferenceError);
-      }
+      __ Branch(done, ne, at, Operand(zero_reg));
+      __ li(a0, Operand(var->name()));
+      __ push(a0);
+      __ CallRuntime(Runtime::kThrowReferenceError);
     }
     __ Branch(done);
   }
@@ -1299,14 +1288,14 @@
 
 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
                                                TypeofMode typeof_mode) {
+#ifdef DEBUG
   Variable* var = proxy->var();
   DCHECK(var->IsUnallocatedOrGlobalSlot() ||
          (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
-  __ LoadGlobalObject(LoadDescriptor::ReceiverRegister());
-  __ li(LoadDescriptor::NameRegister(), Operand(var->name()));
-  __ li(LoadDescriptor::SlotRegister(),
+#endif
+  __ li(LoadGlobalDescriptor::SlotRegister(),
         Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
-  CallLoadIC(typeof_mode);
+  CallLoadGlobalIC(typeof_mode);
 }
 
 
@@ -1314,7 +1303,7 @@
                                          TypeofMode typeof_mode) {
   // Record position before possible IC call.
   SetExpressionPosition(proxy);
-  PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
+  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
   Variable* var = proxy->var();
 
   // Three cases: global variables, lookup variables, and all other types of
@@ -1348,11 +1337,6 @@
           __ push(a0);
           __ CallRuntime(Runtime::kThrowReferenceError);
           __ bind(&done);
-        } else {
-          // Uninitialized legacy const bindings are unholed.
-          DCHECK(var->mode() == CONST_LEGACY);
-          __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
-          __ Movz(v0, a0, at);  // Conditional move: Undefined if TheHole.
         }
         context()->Plug(v0);
         break;
@@ -1381,18 +1365,6 @@
 }
 
 
-void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
-  Comment cmnt(masm_, "[ RegExpLiteral");
-  __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  __ li(a2, Operand(Smi::FromInt(expr->literal_index())));
-  __ li(a1, Operand(expr->pattern()));
-  __ li(a0, Operand(Smi::FromInt(expr->flags())));
-  FastCloneRegExpStub stub(isolate());
-  __ CallStub(&stub);
-  context()->Plug(v0);
-}
-
-
 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
   Expression* expression = (property == NULL) ? NULL : property->value();
   if (expression == NULL) {
@@ -1424,8 +1396,9 @@
   } else {
     FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
     __ CallStub(&stub);
+    RestoreContext();
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   // If result_saved is true the result is on top of the stack.  If
   // result_saved is false the result is in v0.
@@ -1462,7 +1435,7 @@
             __ lw(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
             EmitLoadStoreICSlot(property->GetSlot(0));
             CallStoreIC();
-            PrepareForBailoutForId(key->id(), NO_REGISTERS);
+            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
 
             if (NeedsHomeObject(value)) {
               EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
@@ -1496,16 +1469,20 @@
         DCHECK(property->emit_store());
         CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
         PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                               NO_REGISTERS);
+                               BailoutState::NO_REGISTERS);
         break;
       case ObjectLiteral::Property::GETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->getter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->getter = property;
         }
         break;
       case ObjectLiteral::Property::SETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->setter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->setter = property;
         }
         break;
     }
@@ -1524,6 +1501,7 @@
     __ li(a0, Operand(Smi::FromInt(NONE)));
     PushOperand(a0);
     CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
+    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
   }
 
   // Object literals have two parts. The "static" part on the left contains no
@@ -1553,7 +1531,7 @@
       DCHECK(property->emit_store());
       CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
       PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                             NO_REGISTERS);
+                             BailoutState::NO_REGISTERS);
     } else {
       EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
       VisitForStackValue(value);
@@ -1569,6 +1547,8 @@
             PushOperand(Smi::FromInt(NONE));
             PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
             CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
+            PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
+                                   BailoutState::NO_REGISTERS);
           } else {
             DropOperands(3);
           }
@@ -1625,7 +1605,7 @@
     FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
     __ CallStub(&stub);
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   bool result_saved = false;  // Is the result saved to the stack?
   ZoneList<Expression*>* subexprs = expr->values();
@@ -1657,7 +1637,8 @@
         CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
     CallIC(ic);
 
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   // In case the array literal contains spread expressions it has two parts. The
@@ -1677,7 +1658,8 @@
     VisitForStackValue(subexpr);
     CallRuntimeWithOperands(Runtime::kAppendElement);
 
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   if (result_saved) {
@@ -1692,7 +1674,6 @@
   DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
 
   Comment cmnt(masm_, "[ Assignment");
-  SetExpressionPosition(expr, INSERT_BREAK);
 
   Property* property = expr->target()->AsProperty();
   LhsKind assign_type = Property::GetAssignType(property);
@@ -1761,23 +1742,27 @@
       switch (assign_type) {
         case VARIABLE:
           EmitVariableLoad(expr->target()->AsVariableProxy());
-          PrepareForBailout(expr->target(), TOS_REG);
+          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
           break;
         case NAMED_PROPERTY:
           EmitNamedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case NAMED_SUPER_PROPERTY:
           EmitNamedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_SUPER_PROPERTY:
           EmitKeyedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_PROPERTY:
           EmitKeyedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
       }
     }
@@ -1797,7 +1782,7 @@
     }
 
     // Deoptimization point in case the binary operation may have side effects.
-    PrepareForBailout(expr->binary_operation(), TOS_REG);
+    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
   } else {
     VisitForAccumulatorValue(expr->value());
   }
@@ -1809,7 +1794,7 @@
     case VARIABLE:
       EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
                              expr->op(), expr->AssignmentSlot());
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       context()->Plug(v0);
       break;
     case NAMED_PROPERTY:
@@ -1838,20 +1823,24 @@
   // this.  It stays on the stack while we update the iterator.
   VisitForStackValue(expr->expression());
 
-  Label suspend, continuation, post_runtime, resume;
+  Label suspend, continuation, post_runtime, resume, exception;
 
   __ jmp(&suspend);
   __ bind(&continuation);
-  // When we arrive here, the stack top is the resume mode and
-  // result_register() holds the input value (the argument given to the
-  // respective resume operation).
+  // When we arrive here, v0 holds the generator object.
   __ RecordGeneratorContinuation();
-  __ pop(a1);
-  __ Branch(&resume, ne, a1, Operand(Smi::FromInt(JSGeneratorObject::RETURN)));
-  __ push(result_register());
+  __ lw(a1, FieldMemOperand(v0, JSGeneratorObject::kResumeModeOffset));
+  __ lw(v0, FieldMemOperand(v0, JSGeneratorObject::kInputOrDebugPosOffset));
+  __ Branch(&resume, eq, a1, Operand(Smi::FromInt(JSGeneratorObject::kNext)));
+  __ Push(result_register());
+  __ Branch(&exception, eq, a1,
+            Operand(Smi::FromInt(JSGeneratorObject::kThrow)));
   EmitCreateIteratorResult(true);
   EmitUnwindAndReturn();
 
+  __ bind(&exception);
+  __ CallRuntime(Runtime::kThrow);
+
   __ bind(&suspend);
   OperandStackDepthIncrement(1);  // Not popped on this path.
   VisitForAccumulatorValue(expr->generator_object());
@@ -1866,7 +1855,7 @@
   __ Branch(&post_runtime, eq, sp, Operand(a1));
   __ push(v0);  // generator object
   __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
-  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   __ bind(&post_runtime);
   PopOperand(result_register());
   EmitReturnSequence();
@@ -1875,103 +1864,6 @@
   context()->Plug(result_register());
 }
 
-
-void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
-    Expression *value,
-    JSGeneratorObject::ResumeMode resume_mode) {
-  // The value stays in a0, and is ultimately read by the resumed generator, as
-  // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it
-  // is read to throw the value when the resumed generator is already closed.
-  // a1 will hold the generator object until the activation has been resumed.
-  VisitForStackValue(generator);
-  VisitForAccumulatorValue(value);
-  PopOperand(a1);
-
-  // Store input value into generator object.
-  __ sw(result_register(),
-        FieldMemOperand(a1, JSGeneratorObject::kInputOffset));
-  __ mov(a2, result_register());
-  __ RecordWriteField(a1, JSGeneratorObject::kInputOffset, a2, a3,
-                      kRAHasBeenSaved, kDontSaveFPRegs);
-
-  // Load suspended function and context.
-  __ lw(cp, FieldMemOperand(a1, JSGeneratorObject::kContextOffset));
-  __ lw(t0, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
-
-  // Load receiver and store as the first argument.
-  __ lw(a2, FieldMemOperand(a1, JSGeneratorObject::kReceiverOffset));
-  __ push(a2);
-
-  // Push holes for arguments to generator function. Since the parser forced
-  // context allocation for any variables in generators, the actual argument
-  // values have already been copied into the context and these dummy values
-  // will never be used.
-  __ lw(a3, FieldMemOperand(t0, JSFunction::kSharedFunctionInfoOffset));
-  __ lw(a3,
-        FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ LoadRoot(a2, Heap::kTheHoleValueRootIndex);
-  Label push_argument_holes, push_frame;
-  __ bind(&push_argument_holes);
-  __ Subu(a3, a3, Operand(Smi::FromInt(1)));
-  __ Branch(&push_frame, lt, a3, Operand(zero_reg));
-  __ push(a2);
-  __ jmp(&push_argument_holes);
-
-  // Enter a new JavaScript frame, and initialize its slots as they were when
-  // the generator was suspended.
-  Label resume_frame, done;
-  __ bind(&push_frame);
-  __ Call(&resume_frame);
-  __ jmp(&done);
-  __ bind(&resume_frame);
-  // ra = return address.
-  // fp = caller's frame pointer.
-  // cp = callee's context,
-  // t0 = callee's JS function.
-  __ PushStandardFrame(t0);
-
-  // Load the operand stack size.
-  __ lw(a3, FieldMemOperand(a1, JSGeneratorObject::kOperandStackOffset));
-  __ lw(a3, FieldMemOperand(a3, FixedArray::kLengthOffset));
-  __ SmiUntag(a3);
-
-  // If we are sending a value and there is no operand stack, we can jump back
-  // in directly.
-  if (resume_mode == JSGeneratorObject::NEXT) {
-    Label slow_resume;
-    __ Branch(&slow_resume, ne, a3, Operand(zero_reg));
-    __ lw(a3, FieldMemOperand(t0, JSFunction::kCodeEntryOffset));
-    __ lw(a2, FieldMemOperand(a1, JSGeneratorObject::kContinuationOffset));
-    __ SmiUntag(a2);
-    __ Addu(a3, a3, Operand(a2));
-    __ li(a2, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
-    __ sw(a2, FieldMemOperand(a1, JSGeneratorObject::kContinuationOffset));
-    __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-    __ Jump(a3);
-    __ bind(&slow_resume);
-  }
-
-  // Otherwise, we push holes for the operand stack and call the runtime to fix
-  // up the stack and the handlers.
-  Label push_operand_holes, call_resume;
-  __ bind(&push_operand_holes);
-  __ Subu(a3, a3, Operand(1));
-  __ Branch(&call_resume, lt, a3, Operand(zero_reg));
-  __ push(a2);
-  __ Branch(&push_operand_holes);
-  __ bind(&call_resume);
-  __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-  DCHECK(!result_register().is(a1));
-  __ Push(a1, result_register());
-  __ Push(Smi::FromInt(resume_mode));
-  __ CallRuntime(Runtime::kResumeJSGeneratorObject);
-  // Not reached: the runtime call returns elsewhere.
-  __ stop("not-reached");
-
-  __ bind(&done);
-  context()->Plug(result_register());
-}
-
 void FullCodeGenerator::PushOperands(Register reg1, Register reg2) {
   OperandStackDepthIncrement(2);
   __ Push(reg1, reg2);
@@ -2006,7 +1898,8 @@
 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
   Label allocate, done_allocate;
 
-  __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &allocate, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &allocate,
+              NO_ALLOCATION_FLAGS);
   __ jmp(&done_allocate);
 
   __ bind(&allocate);
@@ -2333,8 +2226,7 @@
     __ bind(&uninitialized_this);
     EmitStoreToStackLocalOrContextSlot(var, location);
 
-  } else if (!var->is_const_mode() ||
-             (var->mode() == CONST && op == Token::INIT)) {
+  } else if (!var->is_const_mode() || op == Token::INIT) {
     if (var->IsLookupSlot()) {
       // Assignment to var.
       __ Push(var->name());
@@ -2356,24 +2248,6 @@
       EmitStoreToStackLocalOrContextSlot(var, location);
     }
 
-  } else if (var->mode() == CONST_LEGACY && op == Token::INIT) {
-    // Const initializers need a write barrier.
-    DCHECK(!var->IsParameter());  // No const parameters.
-    if (var->IsLookupSlot()) {
-      __ li(a0, Operand(var->name()));
-      __ Push(v0, cp, a0);  // Context and name.
-      __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot);
-    } else {
-      DCHECK(var->IsStackAllocated() || var->IsContextSlot());
-      Label skip;
-      MemOperand location = VarOperand(var, a1);
-      __ lw(a2, location);
-      __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
-      __ Branch(&skip, ne, a2, Operand(at));
-      EmitStoreToStackLocalOrContextSlot(var, location);
-      __ bind(&skip);
-    }
-
   } else {
     DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT);
     if (is_strict(language_mode())) {
@@ -2397,7 +2271,7 @@
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallStoreIC();
 
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(v0);
 }
 
@@ -2448,44 +2322,7 @@
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallIC(ic);
 
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
-  context()->Plug(v0);
-}
-
-
-void FullCodeGenerator::VisitProperty(Property* expr) {
-  Comment cmnt(masm_, "[ Property");
-  SetExpressionPosition(expr);
-
-  Expression* key = expr->key();
-
-  if (key->IsPropertyName()) {
-    if (!expr->IsSuperAccess()) {
-      VisitForAccumulatorValue(expr->obj());
-      __ Move(LoadDescriptor::ReceiverRegister(), v0);
-      EmitNamedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      EmitNamedSuperPropertyLoad(expr);
-    }
-  } else {
-    if (!expr->IsSuperAccess()) {
-      VisitForStackValue(expr->obj());
-      VisitForAccumulatorValue(expr->key());
-      __ Move(LoadDescriptor::NameRegister(), v0);
-      PopOperand(LoadDescriptor::ReceiverRegister());
-      EmitKeyedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      VisitForStackValue(expr->key());
-      EmitKeyedSuperPropertyLoad(expr);
-    }
-  }
-  PrepareForBailoutForId(expr->LoadId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(v0);
 }
 
@@ -2506,7 +2343,7 @@
   if (callee->IsVariableProxy()) {
     { StackValueContext context(this);
       EmitVariableLoad(callee->AsVariableProxy());
-      PrepareForBailout(callee, NO_REGISTERS);
+      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
     }
     // Push undefined as receiver. This is patched in the method prologue if it
     // is a sloppy mode method.
@@ -2519,7 +2356,8 @@
     DCHECK(!callee->AsProperty()->IsSuperAccess());
     __ lw(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
     EmitNamedPropertyLoad(callee->AsProperty());
-    PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                           BailoutState::TOS_REGISTER);
     // Push the target function under the receiver.
     __ lw(at, MemOperand(sp, 0));
     PushOperand(at);
@@ -2556,6 +2394,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ sw(v0, MemOperand(sp, kPointerSize));
@@ -2580,7 +2419,8 @@
   __ lw(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
   __ Move(LoadDescriptor::NameRegister(), v0);
   EmitKeyedPropertyLoad(callee->AsProperty());
-  PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                         BailoutState::TOS_REGISTER);
 
   // Push the target function under the receiver.
   __ lw(at, MemOperand(sp, 0));
@@ -2614,6 +2454,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ sw(v0, MemOperand(sp, kPointerSize));
@@ -2633,7 +2474,7 @@
     VisitForStackValue(args->at(i));
   }
 
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   // Record source position of the IC call.
   SetCallPosition(expr, expr->tail_call_mode());
   if (expr->tail_call_mode() == TailCallMode::kAllow) {
@@ -2655,31 +2496,33 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-  // Restore context register.
-  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->DropAndPlug(1, v0);
 }
 
-
-void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
-  // t3: copy of the first argument or undefined if it doesn't exist.
+void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
+  int arg_count = expr->arguments()->length();
+  // t4: copy of the first argument or undefined if it doesn't exist.
   if (arg_count > 0) {
-    __ lw(t3, MemOperand(sp, arg_count * kPointerSize));
+    __ lw(t4, MemOperand(sp, arg_count * kPointerSize));
   } else {
-    __ LoadRoot(t3, Heap::kUndefinedValueRootIndex);
+    __ LoadRoot(t4, Heap::kUndefinedValueRootIndex);
   }
 
-  // t2: the receiver of the enclosing function.
-  __ lw(t2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+  // t3: the receiver of the enclosing function.
+  __ lw(t3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
 
-  // t1: the language mode.
-  __ li(t1, Operand(Smi::FromInt(language_mode())));
+  // t2: the language mode.
+  __ li(t2, Operand(Smi::FromInt(language_mode())));
 
-  // t0: the start position of the scope the calls resides in.
-  __ li(t0, Operand(Smi::FromInt(scope()->start_position())));
+  // t1: the start position of the scope the calls resides in.
+  __ li(t1, Operand(Smi::FromInt(scope()->start_position())));
+
+  // t0: the source position of the eval call.
+  __ li(t0, Operand(Smi::FromInt(expr->position())));
 
   // Do the runtime call.
-  __ Push(t3, t2, t1, t0);
+  __ Push(t4, t3, t2, t1, t0);
   __ CallRuntime(Runtime::kResolvePossiblyDirectEval);
 }
 
@@ -2701,7 +2544,7 @@
     __ Push(callee->name());
     __ CallRuntime(Runtime::kLoadLookupSlotForCall);
     PushOperands(v0, v1);  // Function, receiver.
-    PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
+    PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
 
     // If fast case code has been generated, emit code to push the
     // function and receiver and have the slow path jump around this
@@ -2728,7 +2571,7 @@
 
 
 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
-  // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
+  // In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
   // to resolve the function we need to call.  Then we call the resolved
   // function using the given arguments.
   ZoneList<Expression*>* args = expr->arguments();
@@ -2744,12 +2587,12 @@
   // resolve eval.
   __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
   __ push(a1);
-  EmitResolvePossiblyDirectEval(arg_count);
+  EmitResolvePossiblyDirectEval(expr);
 
   // Touch up the stack with the resolved function.
   __ sw(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
 
-  PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
   // Record source position for debugger.
   SetCallPosition(expr);
   __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
@@ -2759,8 +2602,7 @@
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
   RecordJSReturnSite(expr);
-  // Restore context register.
-  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->DropAndPlug(1, v0);
 }
 
@@ -2799,9 +2641,8 @@
   CallConstructStub stub(isolate());
   __ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
-  // Restore context register.
-  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
+  RestoreContext();
   context()->Plug(v0);
 }
 
@@ -2844,9 +2685,7 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-
-  // Restore context register.
-  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->Plug(v0);
 }
 
@@ -3054,80 +2893,6 @@
 }
 
 
-void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = v0;
-  Register index = a1;
-  Register value = a2;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-  PopOperands(index, value);
-
-  if (FLAG_debug_code) {
-    __ SmiTst(value, at);
-    __ Check(eq, kNonSmiValue, at, Operand(zero_reg));
-    __ SmiTst(index, at);
-    __ Check(eq, kNonSmiIndex, at, Operand(zero_reg));
-    __ SmiUntag(index, index);
-    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    Register scratch = t5;
-    __ EmitSeqStringSetCharCheck(
-        string, index, value, scratch, one_byte_seq_type);
-    __ SmiTag(index, index);
-  }
-
-  __ SmiUntag(value, value);
-  __ Addu(at,
-          string,
-          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
-  __ SmiUntag(index);
-  __ Addu(at, at, index);
-  __ sb(value, MemOperand(at));
-  context()->Plug(string);
-}
-
-
-void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = v0;
-  Register index = a1;
-  Register value = a2;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-  PopOperands(index, value);
-
-  if (FLAG_debug_code) {
-    __ SmiTst(value, at);
-    __ Check(eq, kNonSmiValue, at, Operand(zero_reg));
-    __ SmiTst(index, at);
-    __ Check(eq, kNonSmiIndex, at, Operand(zero_reg));
-    __ SmiUntag(index, index);
-    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    Register scratch = t5;
-    __ EmitSeqStringSetCharCheck(
-        string, index, value, scratch, two_byte_seq_type);
-    __ SmiTag(index, index);
-  }
-
-  __ SmiUntag(value, value);
-  __ Addu(at,
-          string,
-          Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
-  __ Addu(at, at, index);
-  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
-  __ sh(value, MemOperand(at));
-    context()->Plug(string);
-}
-
-
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
@@ -3164,13 +2929,8 @@
   Label need_conversion;
   Label index_out_of_range;
   Label done;
-  StringCharCodeAtGenerator generator(object,
-                                      index,
-                                      result,
-                                      &need_conversion,
-                                      &need_conversion,
-                                      &index_out_of_range,
-                                      STRING_INDEX_IS_NUMBER);
+  StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
+                                      &need_conversion, &index_out_of_range);
   generator.GenerateFast(masm_);
   __ jmp(&done);
 
@@ -3194,55 +2954,6 @@
 }
 
 
-void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK(args->length() == 2);
-
-  VisitForStackValue(args->at(0));
-  VisitForAccumulatorValue(args->at(1));
-  __ mov(a0, result_register());
-
-  Register object = a1;
-  Register index = a0;
-  Register scratch = a3;
-  Register result = v0;
-
-  PopOperand(object);
-
-  Label need_conversion;
-  Label index_out_of_range;
-  Label done;
-  StringCharAtGenerator generator(object,
-                                  index,
-                                  scratch,
-                                  result,
-                                  &need_conversion,
-                                  &need_conversion,
-                                  &index_out_of_range,
-                                  STRING_INDEX_IS_NUMBER);
-  generator.GenerateFast(masm_);
-  __ jmp(&done);
-
-  __ bind(&index_out_of_range);
-  // When the index is out of range, the spec requires us to return
-  // the empty string.
-  __ LoadRoot(result, Heap::kempty_stringRootIndex);
-  __ jmp(&done);
-
-  __ bind(&need_conversion);
-  // Move smi zero into the result register, which will trigger
-  // conversion.
-  __ li(result, Operand(Smi::FromInt(0)));
-  __ jmp(&done);
-
-  NopRuntimeCallHelper call_helper;
-  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
-
-  __ bind(&done);
-  context()->Plug(result);
-}
-
-
 void FullCodeGenerator::EmitCall(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK_LE(2, args->length());
@@ -3250,7 +2961,7 @@
   for (Expression* const arg : *args) {
     VisitForStackValue(arg);
   }
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   // Move target to a1.
   int const argc = args->length() - 2;
   __ lw(a1, MemOperand(sp, (argc + 1) * kPointerSize));
@@ -3258,8 +2969,7 @@
   __ li(a0, Operand(argc));
   __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(argc + 1);
-  // Restore context register.
-  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   // Discard the function left on TOS.
   context()->DropAndPlug(1, v0);
 }
@@ -3310,12 +3020,6 @@
   context()->Plug(v0);
 }
 
-void FullCodeGenerator::EmitGetOrdinaryHasInstance(CallRuntime* expr) {
-  DCHECK_EQ(0, expr->arguments()->length());
-  __ LoadNativeContextSlot(Context::ORDINARY_HAS_INSTANCE_INDEX, v0);
-  context()->Plug(v0);
-}
-
 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
   DCHECK(expr->arguments()->length() == 0);
   ExternalReference debug_is_active =
@@ -3335,7 +3039,8 @@
 
   Label runtime, done;
 
-  __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &runtime, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &runtime,
+              NO_ALLOCATION_FLAGS);
   __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, a1);
   __ Pop(a2, a3);
   __ LoadRoot(t0, Heap::kEmptyFixedArrayRootIndex);
@@ -3376,9 +3081,7 @@
   __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-
-  // Restore context register.
-  __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
 }
 
 
@@ -3462,12 +3165,14 @@
                         &materialize_true);
         if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
         __ bind(&materialize_true);
-        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeTrueId(),
+                               BailoutState::NO_REGISTERS);
         __ LoadRoot(v0, Heap::kTrueValueRootIndex);
         if (context()->IsStackValue()) __ push(v0);
         __ jmp(&done);
         __ bind(&materialize_false);
-        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeFalseId(),
+                               BailoutState::NO_REGISTERS);
         __ LoadRoot(v0, Heap::kFalseValueRootIndex);
         if (context()->IsStackValue()) __ push(v0);
         __ bind(&done);
@@ -3567,9 +3272,9 @@
   // We need a second deoptimization point after loading the value
   // in case evaluating the property load my have a side effect.
   if (assign_type == VARIABLE) {
-    PrepareForBailout(expr->expression(), TOS_REG);
+    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
   } else {
-    PrepareForBailoutForId(prop->LoadId(), TOS_REG);
+    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
   }
 
   // Inline smi case if we are in a loop.
@@ -3618,9 +3323,8 @@
   }
 
   // Convert old value into a number.
-  ToNumberStub convert_stub(isolate());
-  __ CallStub(&convert_stub);
-  PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
+  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
+  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
 
   // Save result for postfix expressions.
   if (expr->is_postfix()) {
@@ -3666,7 +3370,8 @@
         { EffectContext context(this);
           EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                  Token::ASSIGN, expr->CountSlot());
-          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+          PrepareForBailoutForId(expr->AssignmentId(),
+                                 BailoutState::TOS_REGISTER);
           context.Plug(v0);
         }
         // For all contexts except EffectConstant we have the result on
@@ -3677,7 +3382,8 @@
       } else {
         EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                Token::ASSIGN, expr->CountSlot());
-        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+        PrepareForBailoutForId(expr->AssignmentId(),
+                               BailoutState::TOS_REGISTER);
         context()->Plug(v0);
       }
       break;
@@ -3688,7 +3394,7 @@
       PopOperand(StoreDescriptor::ReceiverRegister());
       EmitLoadStoreICSlot(expr->CountSlot());
       CallStoreIC();
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         if (!context()->IsEffect()) {
           context()->PlugTOS();
@@ -3728,7 +3434,7 @@
           CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
       EmitLoadStoreICSlot(expr->CountSlot());
       CallIC(ic);
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         if (!context()->IsEffect()) {
           context()->PlugTOS();
@@ -3825,7 +3531,6 @@
 
 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
   Comment cmnt(masm_, "[ CompareOperation");
-  SetExpressionPosition(expr);
 
   // First we try a fast inlined version of the compare when one of
   // the operands is a literal.
@@ -3845,7 +3550,8 @@
   switch (op) {
     case Token::IN:
       VisitForStackValue(expr->right());
-      CallRuntimeWithOperands(Runtime::kHasProperty);
+      SetExpressionPosition(expr);
+      EmitHasProperty();
       PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
       __ LoadRoot(t0, Heap::kTrueValueRootIndex);
       Split(eq, v0, Operand(t0), if_true, if_false, fall_through);
@@ -3853,6 +3559,7 @@
 
     case Token::INSTANCEOF: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       __ mov(a0, result_register());
       PopOperand(a1);
       InstanceOfStub stub(isolate());
@@ -3865,6 +3572,7 @@
 
     default: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       Condition cc = CompareIC::ComputeCondition(op);
       __ mov(a0, result_register());
       PopOperand(a1);
diff --git a/src/full-codegen/mips64/full-codegen-mips64.cc b/src/full-codegen/mips64/full-codegen-mips64.cc
index 681abd1..a58f173 100644
--- a/src/full-codegen/mips64/full-codegen-mips64.cc
+++ b/src/full-codegen/mips64/full-codegen-mips64.cc
@@ -185,7 +185,8 @@
       __ push(a1);
       __ Push(info->scope()->GetScopeInfo(info->isolate()));
       __ CallRuntime(Runtime::kNewScriptContext);
-      PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
+      PrepareForBailoutForId(BailoutId::ScriptContext(),
+                             BailoutState::TOS_REGISTER);
       // The new target value is not used, clobbering is safe.
       DCHECK_NULL(info->scope()->new_target_var());
     } else {
@@ -241,7 +242,8 @@
   // Register holding this function and new target are both trashed in case we
   // bailout here. But since that can happen only when new target is not used
   // and we allocate a context, the value of |function_in_register| is correct.
-  PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionContext(),
+                         BailoutState::NO_REGISTERS);
 
   // Possibly set up a local binding to the this function which is used in
   // derived constructors with super calls.
@@ -302,7 +304,8 @@
   }
 
   // Visit the declarations and body.
-  PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionEntry(),
+                         BailoutState::NO_REGISTERS);
   {
     Comment cmnt(masm_, "[ Declarations");
     VisitDeclarations(scope()->declarations());
@@ -315,7 +318,8 @@
 
   {
     Comment cmnt(masm_, "[ Stack check");
-    PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
+    PrepareForBailoutForId(BailoutId::Declarations(),
+                           BailoutState::NO_REGISTERS);
     Label ok;
     __ LoadRoot(at, Heap::kStackLimitRootIndex);
     __ Branch(&ok, hs, sp, Operand(at));
@@ -396,11 +400,11 @@
   EmitProfilingCounterReset();
 
   __ bind(&ok);
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
   // Record a mapping of the OSR id to this PC.  This is used if the OSR
   // entry becomes the target of a bailout.  We don't expect it to be, but
   // we want it to work if it is.
-  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
 }
 
 void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
@@ -458,6 +462,9 @@
   }
 }
 
+void FullCodeGenerator::RestoreContext() {
+  __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+}
 
 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
   DCHECK(var->IsStackAllocated() || var->IsContextSlot());
@@ -523,10 +530,12 @@
                                           true,
                                           true_label_,
                                           false_label_);
-  DCHECK(lit->IsNull() || lit->IsUndefined() || !lit->IsUndetectable());
-  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
+  DCHECK(lit->IsNull(isolate()) || lit->IsUndefined(isolate()) ||
+         !lit->IsUndetectable());
+  if (lit->IsUndefined(isolate()) || lit->IsNull(isolate()) ||
+      lit->IsFalse(isolate())) {
     if (false_label_ != fall_through_) __ Branch(false_label_);
-  } else if (lit->IsTrue() || lit->IsJSObject()) {
+  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
     if (true_label_ != fall_through_) __ Branch(true_label_);
   } else if (lit->IsString()) {
     if (String::cast(*lit)->length() == 0) {
@@ -723,7 +732,7 @@
 
   Label skip;
   if (should_normalize) __ Branch(&skip);
-  PrepareForBailout(expr, TOS_REG);
+  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
   if (should_normalize) {
     __ LoadRoot(a4, Heap::kTrueValueRootIndex);
     Split(eq, a0, Operand(a4), if_true, if_false, NULL);
@@ -757,15 +766,13 @@
   VariableProxy* proxy = declaration->proxy();
   VariableMode mode = declaration->mode();
   Variable* variable = proxy->var();
-  bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
+  bool hole_init = mode == LET || mode == CONST;
   switch (variable->location()) {
     case VariableLocation::GLOBAL:
     case VariableLocation::UNALLOCATED:
+      DCHECK(!variable->binding_needs_init());
       globals_->Add(variable->name(), zone());
-      globals_->Add(variable->binding_needs_init()
-                        ? isolate()->factory()->the_hole_value()
-                        : isolate()->factory()->undefined_value(),
-                    zone());
+      globals_->Add(isolate()->factory()->undefined_value(), zone());
       break;
 
     case VariableLocation::PARAMETER:
@@ -784,28 +791,18 @@
           __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
           __ sd(at, ContextMemOperand(cp, variable->index()));
           // No write barrier since the_hole_value is in old space.
-          PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+          PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       }
       break;
 
     case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
+      DCHECK_EQ(VAR, mode);
+      DCHECK(!hole_init);
       __ li(a2, Operand(variable->name()));
-      // Declaration nodes are always introduced in one of four modes.
-      DCHECK(IsDeclaredVariableMode(mode));
-      // Push initial value, if any.
-      // Note: For variables we must not push an initial value (such as
-      // 'undefined') because we may have a (legal) redeclaration and we
-      // must not destroy the current value.
-      if (hole_init) {
-        __ LoadRoot(a0, Heap::kTheHoleValueRootIndex);
-      } else {
-        DCHECK(Smi::FromInt(0) == 0);
-        __ mov(a0, zero_reg);  // Smi::FromInt(0) indicates no initial value.
-      }
-      __ Push(a2, a0);
-      __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes()));
-      __ CallRuntime(Runtime::kDeclareLookupSlot);
+      __ Push(a2);
+      __ CallRuntime(Runtime::kDeclareEvalVar);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -851,7 +848,7 @@
                                 kDontSaveFPRegs,
                                 EMIT_REMEMBERED_SET,
                                 OMIT_SMI_CHECK);
-      PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
 
@@ -861,8 +858,8 @@
       PushOperand(a2);
       // Push initial value for function declaration.
       VisitForStackValue(declaration->fun());
-      PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
-      CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
+      CallRuntimeWithOperands(Runtime::kDeclareEvalFunction);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -894,7 +891,7 @@
 
   // Keep the switch value on the stack until a case matches.
   VisitForStackValue(stmt->tag());
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
 
   ZoneList<CaseClause*>* clauses = stmt->cases();
   CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
@@ -944,7 +941,7 @@
 
     Label skip;
     __ Branch(&skip);
-    PrepareForBailout(clause, TOS_REG);
+    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
     __ LoadRoot(at, Heap::kTrueValueRootIndex);
     __ Branch(&next_test, ne, v0, Operand(at));
     __ Drop(1);
@@ -971,12 +968,12 @@
     Comment cmnt(masm_, "[ Case body");
     CaseClause* clause = clauses->at(i);
     __ bind(clause->body_target());
-    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
+    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
     VisitStatements(clause->statements());
   }
 
   __ bind(nested_statement.break_label());
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
 }
 
 
@@ -1013,15 +1010,13 @@
   __ CallStub(&stub);
   __ mov(a0, v0);
   __ bind(&done_convert);
-  PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
+  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
   __ push(a0);
 
-  // Check cache validity in generated code. This is a fast case for
-  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
-  // guarantee cache validity, call the runtime system to check cache
-  // validity or get the property names in a fixed array.
-  // Note: Proxies never have an enum cache, so will always take the
-  // slow path.
+  // Check cache validity in generated code. If we cannot guarantee cache
+  // validity, call the runtime system to check cache validity or get the
+  // property names in a fixed array. Note: Proxies never have an enum cache,
+  // so will always take the slow path.
   Label call_runtime;
   __ CheckEnumCache(&call_runtime);
 
@@ -1035,7 +1030,7 @@
   __ bind(&call_runtime);
   __ push(a0);  // Duplicate the enumerable object on the stack.
   __ CallRuntime(Runtime::kForInEnumerate);
-  PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
+  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
 
   // If we got a map from the runtime call, we can do a fast
   // modification check. Otherwise, we got a fixed array, and we have
@@ -1073,7 +1068,7 @@
   __ Push(a1, v0);  // Smi and array
   __ ld(a1, FieldMemOperand(v0, FixedArray::kLengthOffset));
   __ Push(a1);  // Fixed array length (as smi).
-  PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
   __ li(a0, Operand(Smi::FromInt(0)));
   __ Push(a0);  // Initial index.
 
@@ -1115,7 +1110,7 @@
   // just skip it.
   __ Push(a1, a3);  // Enumerable and current entry.
   __ CallRuntime(Runtime::kForInFilter);
-  PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
+  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
   __ mov(a3, result_register());
   __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
   __ Branch(loop_statement.continue_label(), eq, a3, Operand(at));
@@ -1127,11 +1122,11 @@
   // Perform the assignment as if via '='.
   { EffectContext context(this);
     EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
-    PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
+    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
   }
 
   // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
-  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
   // Generate code for the body of the loop.
   Visit(stmt->body());
 
@@ -1150,7 +1145,7 @@
   DropOperands(5);
 
   // Exit and decrement the loop depth.
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   __ bind(&exit);
   decrement_loop_depth();
 }
@@ -1279,19 +1274,13 @@
   } else if (var->mode() == DYNAMIC_LOCAL) {
     Variable* local = var->local_if_not_shadowed();
     __ ld(v0, ContextSlotOperandCheckExtensions(local, slow));
-    if (local->mode() == LET || local->mode() == CONST ||
-        local->mode() == CONST_LEGACY) {
+    if (local->mode() == LET || local->mode() == CONST) {
       __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
       __ dsubu(at, v0, at);  // Sub as compare: at == 0 on eq.
-      if (local->mode() == CONST_LEGACY) {
-        __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
-        __ Movz(v0, a0, at);  // Conditional move: return Undefined if TheHole.
-      } else {  // LET || CONST
-        __ Branch(done, ne, at, Operand(zero_reg));
-        __ li(a0, Operand(var->name()));
-        __ push(a0);
-        __ CallRuntime(Runtime::kThrowReferenceError);
-      }
+      __ Branch(done, ne, at, Operand(zero_reg));
+      __ li(a0, Operand(var->name()));
+      __ push(a0);
+      __ CallRuntime(Runtime::kThrowReferenceError);
     }
     __ Branch(done);
   }
@@ -1300,14 +1289,14 @@
 
 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
                                                TypeofMode typeof_mode) {
+#ifdef DEBUG
   Variable* var = proxy->var();
   DCHECK(var->IsUnallocatedOrGlobalSlot() ||
          (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
-  __ LoadGlobalObject(LoadDescriptor::ReceiverRegister());
-  __ li(LoadDescriptor::NameRegister(), Operand(var->name()));
-  __ li(LoadDescriptor::SlotRegister(),
+#endif
+  __ li(LoadGlobalDescriptor::SlotRegister(),
         Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
-  CallLoadIC(typeof_mode);
+  CallLoadGlobalIC(typeof_mode);
 }
 
 
@@ -1315,7 +1304,7 @@
                                          TypeofMode typeof_mode) {
   // Record position before possible IC call.
   SetExpressionPosition(proxy);
-  PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
+  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
   Variable* var = proxy->var();
 
   // Three cases: global variables, lookup variables, and all other types of
@@ -1349,11 +1338,6 @@
           __ push(a0);
           __ CallRuntime(Runtime::kThrowReferenceError);
           __ bind(&done);
-        } else {
-          // Uninitialized legacy const bindings are unholed.
-          DCHECK(var->mode() == CONST_LEGACY);
-          __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
-          __ Movz(v0, a0, at);  // Conditional move: Undefined if TheHole.
         }
         context()->Plug(v0);
         break;
@@ -1382,18 +1366,6 @@
 }
 
 
-void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
-  Comment cmnt(masm_, "[ RegExpLiteral");
-  __ ld(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  __ li(a2, Operand(Smi::FromInt(expr->literal_index())));
-  __ li(a1, Operand(expr->pattern()));
-  __ li(a0, Operand(Smi::FromInt(expr->flags())));
-  FastCloneRegExpStub stub(isolate());
-  __ CallStub(&stub);
-  context()->Plug(v0);
-}
-
-
 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
   Expression* expression = (property == NULL) ? NULL : property->value();
   if (expression == NULL) {
@@ -1425,8 +1397,9 @@
   } else {
     FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
     __ CallStub(&stub);
+    RestoreContext();
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   // If result_saved is true the result is on top of the stack.  If
   // result_saved is false the result is in v0.
@@ -1463,7 +1436,7 @@
             __ ld(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
             EmitLoadStoreICSlot(property->GetSlot(0));
             CallStoreIC();
-            PrepareForBailoutForId(key->id(), NO_REGISTERS);
+            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
 
             if (NeedsHomeObject(value)) {
               EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
@@ -1497,16 +1470,20 @@
         DCHECK(property->emit_store());
         CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
         PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                               NO_REGISTERS);
+                               BailoutState::NO_REGISTERS);
         break;
       case ObjectLiteral::Property::GETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->getter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->getter = property;
         }
         break;
       case ObjectLiteral::Property::SETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->setter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->setter = property;
         }
         break;
     }
@@ -1525,6 +1502,7 @@
     __ li(a0, Operand(Smi::FromInt(NONE)));
     PushOperand(a0);
     CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
+    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
   }
 
   // Object literals have two parts. The "static" part on the left contains no
@@ -1554,7 +1532,7 @@
       DCHECK(property->emit_store());
       CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
       PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                             NO_REGISTERS);
+                             BailoutState::NO_REGISTERS);
     } else {
       EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
       VisitForStackValue(value);
@@ -1570,6 +1548,8 @@
             PushOperand(Smi::FromInt(NONE));
             PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
             CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
+            PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
+                                   BailoutState::NO_REGISTERS);
           } else {
             DropOperands(3);
           }
@@ -1626,7 +1606,7 @@
     FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
     __ CallStub(&stub);
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   bool result_saved = false;  // Is the result saved to the stack?
   ZoneList<Expression*>* subexprs = expr->values();
@@ -1658,7 +1638,8 @@
         CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
     CallIC(ic);
 
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   // In case the array literal contains spread expressions it has two parts. The
@@ -1678,7 +1659,8 @@
     VisitForStackValue(subexpr);
     CallRuntimeWithOperands(Runtime::kAppendElement);
 
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   if (result_saved) {
@@ -1693,7 +1675,6 @@
   DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
 
   Comment cmnt(masm_, "[ Assignment");
-  SetExpressionPosition(expr, INSERT_BREAK);
 
   Property* property = expr->target()->AsProperty();
   LhsKind assign_type = Property::GetAssignType(property);
@@ -1762,23 +1743,27 @@
       switch (assign_type) {
         case VARIABLE:
           EmitVariableLoad(expr->target()->AsVariableProxy());
-          PrepareForBailout(expr->target(), TOS_REG);
+          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
           break;
         case NAMED_PROPERTY:
           EmitNamedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case NAMED_SUPER_PROPERTY:
           EmitNamedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_SUPER_PROPERTY:
           EmitKeyedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_PROPERTY:
           EmitKeyedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
       }
     }
@@ -1798,7 +1783,7 @@
     }
 
     // Deoptimization point in case the binary operation may have side effects.
-    PrepareForBailout(expr->binary_operation(), TOS_REG);
+    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
   } else {
     VisitForAccumulatorValue(expr->value());
   }
@@ -1810,7 +1795,7 @@
     case VARIABLE:
       EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
                              expr->op(), expr->AssignmentSlot());
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       context()->Plug(v0);
       break;
     case NAMED_PROPERTY:
@@ -1839,20 +1824,24 @@
   // this.  It stays on the stack while we update the iterator.
   VisitForStackValue(expr->expression());
 
-  Label suspend, continuation, post_runtime, resume;
+  Label suspend, continuation, post_runtime, resume, exception;
 
   __ jmp(&suspend);
   __ bind(&continuation);
-  // When we arrive here, the stack top is the resume mode and
-  // result_register() holds the input value (the argument given to the
-  // respective resume operation).
+  // When we arrive here, v0 holds the generator object.
   __ RecordGeneratorContinuation();
-  __ pop(a1);
-  __ Branch(&resume, ne, a1, Operand(Smi::FromInt(JSGeneratorObject::RETURN)));
-  __ push(result_register());
+  __ ld(a1, FieldMemOperand(v0, JSGeneratorObject::kResumeModeOffset));
+  __ ld(v0, FieldMemOperand(v0, JSGeneratorObject::kInputOrDebugPosOffset));
+  __ Branch(&resume, eq, a1, Operand(Smi::FromInt(JSGeneratorObject::kNext)));
+  __ Push(result_register());
+  __ Branch(&exception, eq, a1,
+            Operand(Smi::FromInt(JSGeneratorObject::kThrow)));
   EmitCreateIteratorResult(true);
   EmitUnwindAndReturn();
 
+  __ bind(&exception);
+  __ CallRuntime(Runtime::kThrow);
+
   __ bind(&suspend);
   OperandStackDepthIncrement(1);  // Not popped on this path.
   VisitForAccumulatorValue(expr->generator_object());
@@ -1867,7 +1856,7 @@
   __ Branch(&post_runtime, eq, sp, Operand(a1));
   __ push(v0);  // generator object
   __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
-  __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   __ bind(&post_runtime);
   PopOperand(result_register());
   EmitReturnSequence();
@@ -1876,105 +1865,6 @@
   context()->Plug(result_register());
 }
 
-
-void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
-    Expression *value,
-    JSGeneratorObject::ResumeMode resume_mode) {
-  // The value stays in a0, and is ultimately read by the resumed generator, as
-  // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it
-  // is read to throw the value when the resumed generator is already closed.
-  // a1 will hold the generator object until the activation has been resumed.
-  VisitForStackValue(generator);
-  VisitForAccumulatorValue(value);
-  PopOperand(a1);
-
-  // Store input value into generator object.
-  __ sd(result_register(),
-        FieldMemOperand(a1, JSGeneratorObject::kInputOffset));
-  __ mov(a2, result_register());
-  __ RecordWriteField(a1, JSGeneratorObject::kInputOffset, a2, a3,
-                      kRAHasBeenSaved, kDontSaveFPRegs);
-
-  // Load suspended function and context.
-  __ ld(cp, FieldMemOperand(a1, JSGeneratorObject::kContextOffset));
-  __ ld(a4, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
-
-  // Load receiver and store as the first argument.
-  __ ld(a2, FieldMemOperand(a1, JSGeneratorObject::kReceiverOffset));
-  __ push(a2);
-
-  // Push holes for arguments to generator function. Since the parser forced
-  // context allocation for any variables in generators, the actual argument
-  // values have already been copied into the context and these dummy values
-  // will never be used.
-  __ ld(a3, FieldMemOperand(a4, JSFunction::kSharedFunctionInfoOffset));
-  // The argument count is stored as int32_t on 64-bit platforms.
-  // TODO(plind): Smi on 32-bit platforms.
-  __ lw(a3,
-        FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ LoadRoot(a2, Heap::kTheHoleValueRootIndex);
-  Label push_argument_holes, push_frame;
-  __ bind(&push_argument_holes);
-  __ Dsubu(a3, a3, Operand(1));
-  __ Branch(&push_frame, lt, a3, Operand(zero_reg));
-  __ push(a2);
-  __ jmp(&push_argument_holes);
-
-  // Enter a new JavaScript frame, and initialize its slots as they were when
-  // the generator was suspended.
-  Label resume_frame, done;
-  __ bind(&push_frame);
-  __ Call(&resume_frame);
-  __ jmp(&done);
-  __ bind(&resume_frame);
-  // ra = return address.
-  // fp = caller's frame pointer.
-  // cp = callee's context,
-  // a4 = callee's JS function.
-  __ PushStandardFrame(a4);
-
-  // Load the operand stack size.
-  __ ld(a3, FieldMemOperand(a1, JSGeneratorObject::kOperandStackOffset));
-  __ ld(a3, FieldMemOperand(a3, FixedArray::kLengthOffset));
-  __ SmiUntag(a3);
-
-  // If we are sending a value and there is no operand stack, we can jump back
-  // in directly.
-  if (resume_mode == JSGeneratorObject::NEXT) {
-    Label slow_resume;
-    __ Branch(&slow_resume, ne, a3, Operand(zero_reg));
-    __ ld(a3, FieldMemOperand(a4, JSFunction::kCodeEntryOffset));
-    __ ld(a2, FieldMemOperand(a1, JSGeneratorObject::kContinuationOffset));
-    __ SmiUntag(a2);
-    __ Daddu(a3, a3, Operand(a2));
-    __ li(a2, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
-    __ sd(a2, FieldMemOperand(a1, JSGeneratorObject::kContinuationOffset));
-    __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-    __ Jump(a3);
-    __ bind(&slow_resume);
-  }
-
-  // Otherwise, we push holes for the operand stack and call the runtime to fix
-  // up the stack and the handlers.
-  Label push_operand_holes, call_resume;
-  __ bind(&push_operand_holes);
-  __ Dsubu(a3, a3, Operand(1));
-  __ Branch(&call_resume, lt, a3, Operand(zero_reg));
-  __ push(a2);
-  __ Branch(&push_operand_holes);
-  __ bind(&call_resume);
-  __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-  DCHECK(!result_register().is(a1));
-  __ Push(a1, result_register());
-  __ Push(Smi::FromInt(resume_mode));
-  __ CallRuntime(Runtime::kResumeJSGeneratorObject);
-  // Not reached: the runtime call returns elsewhere.
-  __ stop("not-reached");
-
-  __ bind(&done);
-  context()->Plug(result_register());
-}
-
 void FullCodeGenerator::PushOperands(Register reg1, Register reg2) {
   OperandStackDepthIncrement(2);
   __ Push(reg1, reg2);
@@ -2009,7 +1899,8 @@
 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
   Label allocate, done_allocate;
 
-  __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &allocate, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &allocate,
+              NO_ALLOCATION_FLAGS);
   __ jmp(&done_allocate);
 
   __ bind(&allocate);
@@ -2335,8 +2226,7 @@
     __ bind(&uninitialized_this);
     EmitStoreToStackLocalOrContextSlot(var, location);
 
-  } else if (!var->is_const_mode() ||
-             (var->mode() == CONST && op == Token::INIT)) {
+  } else if (!var->is_const_mode() || op == Token::INIT) {
     if (var->IsLookupSlot()) {
       __ Push(var->name());
       __ Push(v0);
@@ -2357,24 +2247,6 @@
       EmitStoreToStackLocalOrContextSlot(var, location);
     }
 
-  } else if (var->mode() == CONST_LEGACY && op == Token::INIT) {
-    // Const initializers need a write barrier.
-    DCHECK(!var->IsParameter());  // No const parameters.
-    if (var->IsLookupSlot()) {
-      __ li(a0, Operand(var->name()));
-      __ Push(v0, cp, a0);  // Context and name.
-      __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot);
-    } else {
-      DCHECK(var->IsStackAllocated() || var->IsContextSlot());
-      Label skip;
-      MemOperand location = VarOperand(var, a1);
-      __ ld(a2, location);
-      __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
-      __ Branch(&skip, ne, a2, Operand(at));
-      EmitStoreToStackLocalOrContextSlot(var, location);
-      __ bind(&skip);
-    }
-
   } else {
     DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT);
     if (is_strict(language_mode())) {
@@ -2398,7 +2270,7 @@
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallStoreIC();
 
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(v0);
 }
 
@@ -2449,44 +2321,7 @@
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallIC(ic);
 
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
-  context()->Plug(v0);
-}
-
-
-void FullCodeGenerator::VisitProperty(Property* expr) {
-  Comment cmnt(masm_, "[ Property");
-  SetExpressionPosition(expr);
-
-  Expression* key = expr->key();
-
-  if (key->IsPropertyName()) {
-    if (!expr->IsSuperAccess()) {
-      VisitForAccumulatorValue(expr->obj());
-      __ Move(LoadDescriptor::ReceiverRegister(), v0);
-      EmitNamedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      EmitNamedSuperPropertyLoad(expr);
-    }
-  } else {
-    if (!expr->IsSuperAccess()) {
-      VisitForStackValue(expr->obj());
-      VisitForAccumulatorValue(expr->key());
-      __ Move(LoadDescriptor::NameRegister(), v0);
-      PopOperand(LoadDescriptor::ReceiverRegister());
-      EmitKeyedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      VisitForStackValue(expr->key());
-      EmitKeyedSuperPropertyLoad(expr);
-    }
-  }
-  PrepareForBailoutForId(expr->LoadId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(v0);
 }
 
@@ -2507,7 +2342,7 @@
   if (callee->IsVariableProxy()) {
     { StackValueContext context(this);
       EmitVariableLoad(callee->AsVariableProxy());
-      PrepareForBailout(callee, NO_REGISTERS);
+      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
     }
     // Push undefined as receiver. This is patched in the method prologue if it
     // is a sloppy mode method.
@@ -2520,7 +2355,8 @@
     DCHECK(!callee->AsProperty()->IsSuperAccess());
     __ ld(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
     EmitNamedPropertyLoad(callee->AsProperty());
-    PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                           BailoutState::TOS_REGISTER);
     // Push the target function under the receiver.
     __ ld(at, MemOperand(sp, 0));
     PushOperand(at);
@@ -2557,6 +2393,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ sd(v0, MemOperand(sp, kPointerSize));
@@ -2581,7 +2418,8 @@
   __ ld(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
   __ Move(LoadDescriptor::NameRegister(), v0);
   EmitKeyedPropertyLoad(callee->AsProperty());
-  PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                         BailoutState::TOS_REGISTER);
 
   // Push the target function under the receiver.
   __ ld(at, MemOperand(sp, 0));
@@ -2615,6 +2453,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ sd(v0, MemOperand(sp, kPointerSize));
@@ -2634,7 +2473,7 @@
     VisitForStackValue(args->at(i));
   }
 
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   // Record source position of the IC call.
   SetCallPosition(expr, expr->tail_call_mode());
   if (expr->tail_call_mode() == TailCallMode::kAllow) {
@@ -2656,13 +2495,12 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-  // Restore context register.
-  __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->DropAndPlug(1, v0);
 }
 
-
-void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
+void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
+  int arg_count = expr->arguments()->length();
   // a6: copy of the first argument or undefined if it doesn't exist.
   if (arg_count > 0) {
     __ ld(a6, MemOperand(sp, arg_count * kPointerSize));
@@ -2679,8 +2517,11 @@
   // a1: the start position of the scope the calls resides in.
   __ li(a1, Operand(Smi::FromInt(scope()->start_position())));
 
+  // a0: the source position of the eval call.
+  __ li(a0, Operand(Smi::FromInt(expr->position())));
+
   // Do the runtime call.
-  __ Push(a6, a5, a4, a1);
+  __ Push(a6, a5, a4, a1, a0);
   __ CallRuntime(Runtime::kResolvePossiblyDirectEval);
 }
 
@@ -2702,7 +2543,7 @@
     __ Push(callee->name());
     __ CallRuntime(Runtime::kLoadLookupSlotForCall);
     PushOperands(v0, v1);  // Function, receiver.
-    PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
+    PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
 
     // If fast case code has been generated, emit code to push the
     // function and receiver and have the slow path jump around this
@@ -2729,7 +2570,7 @@
 
 
 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
-  // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
+  // In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
   // to resolve the function we need to call.  Then we call the resolved
   // function using the given arguments.
   ZoneList<Expression*>* args = expr->arguments();
@@ -2745,12 +2586,12 @@
   // resolve eval.
   __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
   __ push(a1);
-  EmitResolvePossiblyDirectEval(arg_count);
+  EmitResolvePossiblyDirectEval(expr);
 
   // Touch up the stack with the resolved function.
   __ sd(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
 
-  PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
   // Record source position for debugger.
   SetCallPosition(expr);
   __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
@@ -2760,8 +2601,7 @@
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
   RecordJSReturnSite(expr);
-  // Restore context register.
-  __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->DropAndPlug(1, v0);
 }
 
@@ -2800,9 +2640,8 @@
   CallConstructStub stub(isolate());
   __ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
-  // Restore context register.
-  __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
+  RestoreContext();
   context()->Plug(v0);
 }
 
@@ -2845,9 +2684,7 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-
-  // Restore context register.
-  __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->Plug(v0);
 }
 
@@ -3055,81 +2892,6 @@
 }
 
 
-void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = v0;
-  Register index = a1;
-  Register value = a2;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-  PopOperands(index, value);
-
-  if (FLAG_debug_code) {
-    __ SmiTst(value, at);
-    __ Check(eq, kNonSmiValue, at, Operand(zero_reg));
-    __ SmiTst(index, at);
-    __ Check(eq, kNonSmiIndex, at, Operand(zero_reg));
-    __ SmiUntag(index, index);
-    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    Register scratch = t1;
-    __ EmitSeqStringSetCharCheck(
-        string, index, value, scratch, one_byte_seq_type);
-    __ SmiTag(index, index);
-  }
-
-  __ SmiUntag(value, value);
-  __ Daddu(at,
-          string,
-          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
-  __ SmiUntag(index);
-  __ Daddu(at, at, index);
-  __ sb(value, MemOperand(at));
-  context()->Plug(string);
-}
-
-
-void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = v0;
-  Register index = a1;
-  Register value = a2;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-  PopOperands(index, value);
-
-  if (FLAG_debug_code) {
-    __ SmiTst(value, at);
-    __ Check(eq, kNonSmiValue, at, Operand(zero_reg));
-    __ SmiTst(index, at);
-    __ Check(eq, kNonSmiIndex, at, Operand(zero_reg));
-    __ SmiUntag(index, index);
-    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    Register scratch = t1;
-    __ EmitSeqStringSetCharCheck(
-        string, index, value, scratch, two_byte_seq_type);
-    __ SmiTag(index, index);
-  }
-
-  __ SmiUntag(value, value);
-  __ Daddu(at,
-          string,
-          Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
-  __ dsra(index, index, 32 - 1);
-  __ Daddu(at, at, index);
-  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
-  __ sh(value, MemOperand(at));
-    context()->Plug(string);
-}
-
-
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
@@ -3166,13 +2928,8 @@
   Label need_conversion;
   Label index_out_of_range;
   Label done;
-  StringCharCodeAtGenerator generator(object,
-                                      index,
-                                      result,
-                                      &need_conversion,
-                                      &need_conversion,
-                                      &index_out_of_range,
-                                      STRING_INDEX_IS_NUMBER);
+  StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
+                                      &need_conversion, &index_out_of_range);
   generator.GenerateFast(masm_);
   __ jmp(&done);
 
@@ -3196,55 +2953,6 @@
 }
 
 
-void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK(args->length() == 2);
-
-  VisitForStackValue(args->at(0));
-  VisitForAccumulatorValue(args->at(1));
-  __ mov(a0, result_register());
-
-  Register object = a1;
-  Register index = a0;
-  Register scratch = a3;
-  Register result = v0;
-
-  PopOperand(object);
-
-  Label need_conversion;
-  Label index_out_of_range;
-  Label done;
-  StringCharAtGenerator generator(object,
-                                  index,
-                                  scratch,
-                                  result,
-                                  &need_conversion,
-                                  &need_conversion,
-                                  &index_out_of_range,
-                                  STRING_INDEX_IS_NUMBER);
-  generator.GenerateFast(masm_);
-  __ jmp(&done);
-
-  __ bind(&index_out_of_range);
-  // When the index is out of range, the spec requires us to return
-  // the empty string.
-  __ LoadRoot(result, Heap::kempty_stringRootIndex);
-  __ jmp(&done);
-
-  __ bind(&need_conversion);
-  // Move smi zero into the result register, which will trigger
-  // conversion.
-  __ li(result, Operand(Smi::FromInt(0)));
-  __ jmp(&done);
-
-  NopRuntimeCallHelper call_helper;
-  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
-
-  __ bind(&done);
-  context()->Plug(result);
-}
-
-
 void FullCodeGenerator::EmitCall(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK_LE(2, args->length());
@@ -3252,7 +2960,7 @@
   for (Expression* const arg : *args) {
     VisitForStackValue(arg);
   }
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   // Move target to a1.
   int const argc = args->length() - 2;
   __ ld(a1, MemOperand(sp, (argc + 1) * kPointerSize));
@@ -3260,8 +2968,7 @@
   __ li(a0, Operand(argc));
   __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(argc + 1);
-  // Restore context register.
-  __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   // Discard the function left on TOS.
   context()->DropAndPlug(1, v0);
 }
@@ -3312,12 +3019,6 @@
   context()->Plug(v0);
 }
 
-void FullCodeGenerator::EmitGetOrdinaryHasInstance(CallRuntime* expr) {
-  DCHECK_EQ(0, expr->arguments()->length());
-  __ LoadNativeContextSlot(Context::ORDINARY_HAS_INSTANCE_INDEX, v0);
-  context()->Plug(v0);
-}
-
 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
   DCHECK(expr->arguments()->length() == 0);
   ExternalReference debug_is_active =
@@ -3337,7 +3038,8 @@
 
   Label runtime, done;
 
-  __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &runtime, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &runtime,
+              NO_ALLOCATION_FLAGS);
   __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, a1);
   __ Pop(a2, a3);
   __ LoadRoot(a4, Heap::kEmptyFixedArrayRootIndex);
@@ -3378,9 +3080,7 @@
   __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-
-  // Restore context register.
-  __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
 }
 
 
@@ -3465,12 +3165,14 @@
                         &materialize_true);
         if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
         __ bind(&materialize_true);
-        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeTrueId(),
+                               BailoutState::NO_REGISTERS);
         __ LoadRoot(v0, Heap::kTrueValueRootIndex);
         if (context()->IsStackValue()) __ push(v0);
         __ jmp(&done);
         __ bind(&materialize_false);
-        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeFalseId(),
+                               BailoutState::NO_REGISTERS);
         __ LoadRoot(v0, Heap::kFalseValueRootIndex);
         if (context()->IsStackValue()) __ push(v0);
         __ bind(&done);
@@ -3570,9 +3272,9 @@
   // We need a second deoptimization point after loading the value
   // in case evaluating the property load my have a side effect.
   if (assign_type == VARIABLE) {
-    PrepareForBailout(expr->expression(), TOS_REG);
+    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
   } else {
-    PrepareForBailoutForId(prop->LoadId(), TOS_REG);
+    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
   }
 
   // Inline smi case if we are in a loop.
@@ -3621,9 +3323,8 @@
   }
 
   // Convert old value into a number.
-  ToNumberStub convert_stub(isolate());
-  __ CallStub(&convert_stub);
-  PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
+  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
+  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
 
   // Save result for postfix expressions.
   if (expr->is_postfix()) {
@@ -3669,7 +3370,8 @@
         { EffectContext context(this);
           EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                  Token::ASSIGN, expr->CountSlot());
-          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+          PrepareForBailoutForId(expr->AssignmentId(),
+                                 BailoutState::TOS_REGISTER);
           context.Plug(v0);
         }
         // For all contexts except EffectConstant we have the result on
@@ -3680,7 +3382,8 @@
       } else {
         EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                Token::ASSIGN, expr->CountSlot());
-        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+        PrepareForBailoutForId(expr->AssignmentId(),
+                               BailoutState::TOS_REGISTER);
         context()->Plug(v0);
       }
       break;
@@ -3691,7 +3394,7 @@
       PopOperand(StoreDescriptor::ReceiverRegister());
       EmitLoadStoreICSlot(expr->CountSlot());
       CallStoreIC();
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         if (!context()->IsEffect()) {
           context()->PlugTOS();
@@ -3731,7 +3434,7 @@
           CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
       EmitLoadStoreICSlot(expr->CountSlot());
       CallIC(ic);
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         if (!context()->IsEffect()) {
           context()->PlugTOS();
@@ -3828,7 +3531,6 @@
 
 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
   Comment cmnt(masm_, "[ CompareOperation");
-  SetExpressionPosition(expr);
 
   // First we try a fast inlined version of the compare when one of
   // the operands is a literal.
@@ -3848,7 +3550,8 @@
   switch (op) {
     case Token::IN:
       VisitForStackValue(expr->right());
-      CallRuntimeWithOperands(Runtime::kHasProperty);
+      SetExpressionPosition(expr);
+      EmitHasProperty();
       PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
       __ LoadRoot(a4, Heap::kTrueValueRootIndex);
       Split(eq, v0, Operand(a4), if_true, if_false, fall_through);
@@ -3856,6 +3559,7 @@
 
     case Token::INSTANCEOF: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       __ mov(a0, result_register());
       PopOperand(a1);
       InstanceOfStub stub(isolate());
@@ -3868,6 +3572,7 @@
 
     default: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       Condition cc = CompareIC::ComputeCondition(op);
       __ mov(a0, result_register());
       PopOperand(a1);
diff --git a/src/full-codegen/ppc/OWNERS b/src/full-codegen/ppc/OWNERS
index eb007cb..752e8e3 100644
--- a/src/full-codegen/ppc/OWNERS
+++ b/src/full-codegen/ppc/OWNERS
@@ -3,3 +3,4 @@
 joransiu@ca.ibm.com
 mbrandy@us.ibm.com
 michael_dawson@ca.ibm.com
+bjaideep@ca.ibm.com
diff --git a/src/full-codegen/ppc/full-codegen-ppc.cc b/src/full-codegen/ppc/full-codegen-ppc.cc
index 301ccf5..1f47983 100644
--- a/src/full-codegen/ppc/full-codegen-ppc.cc
+++ b/src/full-codegen/ppc/full-codegen-ppc.cc
@@ -182,7 +182,8 @@
       __ push(r4);
       __ Push(info->scope()->GetScopeInfo(info->isolate()));
       __ CallRuntime(Runtime::kNewScriptContext);
-      PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
+      PrepareForBailoutForId(BailoutId::ScriptContext(),
+                             BailoutState::TOS_REGISTER);
       // The new target value is not used, clobbering is safe.
       DCHECK_NULL(info->scope()->new_target_var());
     } else {
@@ -238,7 +239,8 @@
   // Register holding this function and new target are both trashed in case we
   // bailout here. But since that can happen only when new target is not used
   // and we allocate a context, the value of |function_in_register| is correct.
-  PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionContext(),
+                         BailoutState::NO_REGISTERS);
 
   // Possibly set up a local binding to the this function which is used in
   // derived constructors with super calls.
@@ -300,7 +302,8 @@
   }
 
   // Visit the declarations and body.
-  PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionEntry(),
+                         BailoutState::NO_REGISTERS);
   {
     Comment cmnt(masm_, "[ Declarations");
     VisitDeclarations(scope()->declarations());
@@ -313,7 +316,8 @@
 
   {
     Comment cmnt(masm_, "[ Stack check");
-    PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
+    PrepareForBailoutForId(BailoutId::Declarations(),
+                           BailoutState::NO_REGISTERS);
     Label ok;
     __ LoadRoot(ip, Heap::kStackLimitRootIndex);
     __ cmpl(sp, ip);
@@ -390,11 +394,11 @@
   EmitProfilingCounterReset();
 
   __ bind(&ok);
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
   // Record a mapping of the OSR id to this PC.  This is used if the OSR
   // entry becomes the target of a bailout.  We don't expect it to be, but
   // we want it to work if it is.
-  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
 }
 
 void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
@@ -450,6 +454,9 @@
   }
 }
 
+void FullCodeGenerator::RestoreContext() {
+  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+}
 
 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
   DCHECK(var->IsStackAllocated() || var->IsContextSlot());
@@ -509,10 +516,12 @@
 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
   codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_label_,
                                           false_label_);
-  DCHECK(lit->IsNull() || lit->IsUndefined() || !lit->IsUndetectable());
-  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
+  DCHECK(lit->IsNull(isolate()) || lit->IsUndefined(isolate()) ||
+         !lit->IsUndetectable());
+  if (lit->IsUndefined(isolate()) || lit->IsNull(isolate()) ||
+      lit->IsFalse(isolate())) {
     if (false_label_ != fall_through_) __ b(false_label_);
-  } else if (lit->IsTrue() || lit->IsJSObject()) {
+  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
     if (true_label_ != fall_through_) __ b(true_label_);
   } else if (lit->IsString()) {
     if (String::cast(*lit)->length() == 0) {
@@ -690,7 +699,7 @@
 
   Label skip;
   if (should_normalize) __ b(&skip);
-  PrepareForBailout(expr, TOS_REG);
+  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
   if (should_normalize) {
     __ LoadRoot(ip, Heap::kTrueValueRootIndex);
     __ cmp(r3, ip);
@@ -723,15 +732,13 @@
   VariableProxy* proxy = declaration->proxy();
   VariableMode mode = declaration->mode();
   Variable* variable = proxy->var();
-  bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
+  bool hole_init = mode == LET || mode == CONST;
   switch (variable->location()) {
     case VariableLocation::GLOBAL:
     case VariableLocation::UNALLOCATED:
+      DCHECK(!variable->binding_needs_init());
       globals_->Add(variable->name(), zone());
-      globals_->Add(variable->binding_needs_init()
-                        ? isolate()->factory()->the_hole_value()
-                        : isolate()->factory()->undefined_value(),
-                    zone());
+      globals_->Add(isolate()->factory()->undefined_value(), zone());
       break;
 
     case VariableLocation::PARAMETER:
@@ -750,27 +757,18 @@
         __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
         __ StoreP(ip, ContextMemOperand(cp, variable->index()), r0);
         // No write barrier since the_hole_value is in old space.
-        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+        PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       }
       break;
 
     case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
+      DCHECK_EQ(VAR, mode);
+      DCHECK(!hole_init);
       __ mov(r5, Operand(variable->name()));
-      // Declaration nodes are always introduced in one of four modes.
-      DCHECK(IsDeclaredVariableMode(mode));
-      // Push initial value, if any.
-      // Note: For variables we must not push an initial value (such as
-      // 'undefined') because we may have a (legal) redeclaration and we
-      // must not destroy the current value.
-      if (hole_init) {
-        __ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
-      } else {
-        __ LoadSmiLiteral(r3, Smi::FromInt(0));  // Indicates no initial value.
-      }
-      __ Push(r5, r3);
-      __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes()));
-      __ CallRuntime(Runtime::kDeclareLookupSlot);
+      __ Push(r5);
+      __ CallRuntime(Runtime::kDeclareEvalVar);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -812,7 +810,7 @@
       __ RecordWriteContextSlot(cp, offset, result_register(), r5,
                                 kLRHasBeenSaved, kDontSaveFPRegs,
                                 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
-      PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
 
@@ -822,8 +820,8 @@
       PushOperand(r5);
       // Push initial value for function declaration.
       VisitForStackValue(declaration->fun());
-      PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
-      CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
+      CallRuntimeWithOperands(Runtime::kDeclareEvalFunction);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -855,7 +853,7 @@
 
   // Keep the switch value on the stack until a case matches.
   VisitForStackValue(stmt->tag());
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
 
   ZoneList<CaseClause*>* clauses = stmt->cases();
   CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
@@ -904,7 +902,7 @@
 
     Label skip;
     __ b(&skip);
-    PrepareForBailout(clause, TOS_REG);
+    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
     __ LoadRoot(ip, Heap::kTrueValueRootIndex);
     __ cmp(r3, ip);
     __ bne(&next_test);
@@ -933,12 +931,12 @@
     Comment cmnt(masm_, "[ Case body");
     CaseClause* clause = clauses->at(i);
     __ bind(clause->body_target());
-    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
+    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
     VisitStatements(clause->statements());
   }
 
   __ bind(nested_statement.break_label());
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
 }
 
 
@@ -971,15 +969,13 @@
   ToObjectStub stub(isolate());
   __ CallStub(&stub);
   __ bind(&done_convert);
-  PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
+  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
   __ push(r3);
 
-  // Check cache validity in generated code. This is a fast case for
-  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
-  // guarantee cache validity, call the runtime system to check cache
-  // validity or get the property names in a fixed array.
-  // Note: Proxies never have an enum cache, so will always take the
-  // slow path.
+  // Check cache validity in generated code. If we cannot guarantee cache
+  // validity, call the runtime system to check cache validity or get the
+  // property names in a fixed array. Note: Proxies never have an enum cache,
+  // so will always take the slow path.
   Label call_runtime;
   __ CheckEnumCache(&call_runtime);
 
@@ -993,7 +989,7 @@
   __ bind(&call_runtime);
   __ push(r3);  // Duplicate the enumerable object on the stack.
   __ CallRuntime(Runtime::kForInEnumerate);
-  PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
+  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
 
   // If we got a map from the runtime call, we can do a fast
   // modification check. Otherwise, we got a fixed array, and we have
@@ -1035,7 +1031,7 @@
   __ Push(r4, r3);  // Smi and array
   __ LoadP(r4, FieldMemOperand(r3, FixedArray::kLengthOffset));
   __ Push(r4);  // Fixed array length (as smi).
-  PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
   __ LoadSmiLiteral(r3, Smi::FromInt(0));
   __ Push(r3);  // Initial index.
 
@@ -1079,7 +1075,7 @@
   // just skip it.
   __ Push(r4, r6);  // Enumerable and current entry.
   __ CallRuntime(Runtime::kForInFilter);
-  PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
+  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
   __ mr(r6, r3);
   __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
   __ cmp(r3, r0);
@@ -1093,11 +1089,11 @@
   {
     EffectContext context(this);
     EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
-    PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
+    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
   }
 
   // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
-  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
   // Generate code for the body of the loop.
   Visit(stmt->body());
 
@@ -1116,7 +1112,7 @@
   DropOperands(5);
 
   // Exit and decrement the loop depth.
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   __ bind(&exit);
   decrement_loop_depth();
 }
@@ -1246,17 +1242,12 @@
   } else if (var->mode() == DYNAMIC_LOCAL) {
     Variable* local = var->local_if_not_shadowed();
     __ LoadP(r3, ContextSlotOperandCheckExtensions(local, slow));
-    if (local->mode() == LET || local->mode() == CONST ||
-        local->mode() == CONST_LEGACY) {
+    if (local->mode() == LET || local->mode() == CONST) {
       __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
       __ bne(done);
-      if (local->mode() == CONST_LEGACY) {
-        __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
-      } else {  // LET || CONST
-        __ mov(r3, Operand(var->name()));
-        __ push(r3);
-        __ CallRuntime(Runtime::kThrowReferenceError);
-      }
+      __ mov(r3, Operand(var->name()));
+      __ push(r3);
+      __ CallRuntime(Runtime::kThrowReferenceError);
     }
     __ b(done);
   }
@@ -1265,14 +1256,14 @@
 
 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
                                                TypeofMode typeof_mode) {
+#ifdef DEBUG
   Variable* var = proxy->var();
   DCHECK(var->IsUnallocatedOrGlobalSlot() ||
          (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
-  __ LoadGlobalObject(LoadDescriptor::ReceiverRegister());
-  __ mov(LoadDescriptor::NameRegister(), Operand(var->name()));
-  __ mov(LoadDescriptor::SlotRegister(),
+#endif
+  __ mov(LoadGlobalDescriptor::SlotRegister(),
          Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
-  CallLoadIC(typeof_mode);
+  CallLoadGlobalIC(typeof_mode);
 }
 
 
@@ -1280,7 +1271,7 @@
                                          TypeofMode typeof_mode) {
   // Record position before possible IC call.
   SetExpressionPosition(proxy);
-  PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
+  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
   Variable* var = proxy->var();
 
   // Three cases: global variables, lookup variables, and all other types of
@@ -1312,10 +1303,6 @@
           __ mov(r3, Operand(var->name()));
           __ push(r3);
           __ CallRuntime(Runtime::kThrowReferenceError);
-        } else {
-          // Uninitialized legacy const bindings are unholed.
-          DCHECK(var->mode() == CONST_LEGACY);
-          __ LoadRoot(r3, Heap::kUndefinedValueRootIndex);
         }
         __ bind(&done);
         context()->Plug(r3);
@@ -1345,18 +1332,6 @@
 }
 
 
-void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
-  Comment cmnt(masm_, "[ RegExpLiteral");
-  __ LoadP(r6, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  __ LoadSmiLiteral(r5, Smi::FromInt(expr->literal_index()));
-  __ mov(r4, Operand(expr->pattern()));
-  __ LoadSmiLiteral(r3, Smi::FromInt(expr->flags()));
-  FastCloneRegExpStub stub(isolate());
-  __ CallStub(&stub);
-  context()->Plug(r3);
-}
-
-
 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
   Expression* expression = (property == NULL) ? NULL : property->value();
   if (expression == NULL) {
@@ -1389,8 +1364,9 @@
   } else {
     FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
     __ CallStub(&stub);
+    RestoreContext();
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   // If result_saved is true the result is on top of the stack.  If
   // result_saved is false the result is in r3.
@@ -1426,7 +1402,7 @@
             __ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
             EmitLoadStoreICSlot(property->GetSlot(0));
             CallStoreIC();
-            PrepareForBailoutForId(key->id(), NO_REGISTERS);
+            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
 
             if (NeedsHomeObject(value)) {
               EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
@@ -1460,16 +1436,20 @@
         DCHECK(property->emit_store());
         CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
         PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                               NO_REGISTERS);
+                               BailoutState::NO_REGISTERS);
         break;
       case ObjectLiteral::Property::GETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->getter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->getter = property;
         }
         break;
       case ObjectLiteral::Property::SETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->setter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->setter = property;
         }
         break;
     }
@@ -1487,6 +1467,7 @@
     __ LoadSmiLiteral(r3, Smi::FromInt(NONE));
     PushOperand(r3);
     CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
+    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
   }
 
   // Object literals have two parts. The "static" part on the left contains no
@@ -1516,7 +1497,7 @@
       DCHECK(property->emit_store());
       CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
       PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                             NO_REGISTERS);
+                             BailoutState::NO_REGISTERS);
     } else {
       EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
       VisitForStackValue(value);
@@ -1532,6 +1513,8 @@
             PushOperand(Smi::FromInt(NONE));
             PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
             CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
+            PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
+                                   BailoutState::NO_REGISTERS);
           } else {
             DropOperands(3);
           }
@@ -1589,7 +1572,7 @@
     FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
     __ CallStub(&stub);
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   bool result_saved = false;  // Is the result saved to the stack?
   ZoneList<Expression*>* subexprs = expr->values();
@@ -1619,7 +1602,8 @@
         CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
     CallIC(ic);
 
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   // In case the array literal contains spread expressions it has two parts. The
@@ -1639,7 +1623,8 @@
     VisitForStackValue(subexpr);
     CallRuntimeWithOperands(Runtime::kAppendElement);
 
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   if (result_saved) {
@@ -1654,7 +1639,6 @@
   DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
 
   Comment cmnt(masm_, "[ Assignment");
-  SetExpressionPosition(expr, INSERT_BREAK);
 
   Property* property = expr->target()->AsProperty();
   LhsKind assign_type = Property::GetAssignType(property);
@@ -1723,23 +1707,27 @@
       switch (assign_type) {
         case VARIABLE:
           EmitVariableLoad(expr->target()->AsVariableProxy());
-          PrepareForBailout(expr->target(), TOS_REG);
+          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
           break;
         case NAMED_PROPERTY:
           EmitNamedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case NAMED_SUPER_PROPERTY:
           EmitNamedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_SUPER_PROPERTY:
           EmitKeyedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_PROPERTY:
           EmitKeyedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
       }
     }
@@ -1757,7 +1745,7 @@
     }
 
     // Deoptimization point in case the binary operation may have side effects.
-    PrepareForBailout(expr->binary_operation(), TOS_REG);
+    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
   } else {
     VisitForAccumulatorValue(expr->value());
   }
@@ -1769,7 +1757,7 @@
     case VARIABLE:
       EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
                              expr->op(), expr->AssignmentSlot());
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       context()->Plug(r3);
       break;
     case NAMED_PROPERTY:
@@ -1798,21 +1786,26 @@
   // this.  It stays on the stack while we update the iterator.
   VisitForStackValue(expr->expression());
 
-  Label suspend, continuation, post_runtime, resume;
+  Label suspend, continuation, post_runtime, resume, exception;
 
   __ b(&suspend);
   __ bind(&continuation);
-  // When we arrive here, the stack top is the resume mode and
-  // result_register() holds the input value (the argument given to the
-  // respective resume operation).
+  // When we arrive here, r3 holds the generator object.
   __ RecordGeneratorContinuation();
-  __ pop(r4);
-  __ CmpSmiLiteral(r4, Smi::FromInt(JSGeneratorObject::RETURN), r0);
-  __ bne(&resume);
-  __ push(result_register());
+  __ LoadP(r4, FieldMemOperand(r3, JSGeneratorObject::kResumeModeOffset));
+  __ LoadP(r3, FieldMemOperand(r3, JSGeneratorObject::kInputOrDebugPosOffset));
+  STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
+  STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
+  __ CmpSmiLiteral(r4, Smi::FromInt(JSGeneratorObject::kReturn), r0);
+  __ blt(&resume);
+  __ Push(result_register());
+  __ bgt(&exception);
   EmitCreateIteratorResult(true);
   EmitUnwindAndReturn();
 
+  __ bind(&exception);
+  __ CallRuntime(Runtime::kThrow);
+
   __ bind(&suspend);
   OperandStackDepthIncrement(1);  // Not popped on this path.
   VisitForAccumulatorValue(expr->generator_object());
@@ -1829,7 +1822,7 @@
   __ beq(&post_runtime);
   __ push(r3);  // generator object
   __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
-  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   __ bind(&post_runtime);
   PopOperand(result_register());
   EmitReturnSequence();
@@ -1838,120 +1831,6 @@
   context()->Plug(result_register());
 }
 
-
-void FullCodeGenerator::EmitGeneratorResume(
-    Expression* generator, Expression* value,
-    JSGeneratorObject::ResumeMode resume_mode) {
-  // The value stays in r3, and is ultimately read by the resumed generator, as
-  // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it
-  // is read to throw the value when the resumed generator is already closed.
-  // r4 will hold the generator object until the activation has been resumed.
-  VisitForStackValue(generator);
-  VisitForAccumulatorValue(value);
-  PopOperand(r4);
-
-  // Store input value into generator object.
-  __ StoreP(result_register(),
-            FieldMemOperand(r4, JSGeneratorObject::kInputOffset), r0);
-  __ mr(r5, result_register());
-  __ RecordWriteField(r4, JSGeneratorObject::kInputOffset, r5, r6,
-                      kLRHasBeenSaved, kDontSaveFPRegs);
-
-  // Load suspended function and context.
-  __ LoadP(cp, FieldMemOperand(r4, JSGeneratorObject::kContextOffset));
-  __ LoadP(r7, FieldMemOperand(r4, JSGeneratorObject::kFunctionOffset));
-
-  // Load receiver and store as the first argument.
-  __ LoadP(r5, FieldMemOperand(r4, JSGeneratorObject::kReceiverOffset));
-  __ push(r5);
-
-  // Push holes for arguments to generator function. Since the parser forced
-  // context allocation for any variables in generators, the actual argument
-  // values have already been copied into the context and these dummy values
-  // will never be used.
-  __ LoadP(r6, FieldMemOperand(r7, JSFunction::kSharedFunctionInfoOffset));
-  __ LoadWordArith(
-      r6, FieldMemOperand(r6, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ LoadRoot(r5, Heap::kTheHoleValueRootIndex);
-  Label argument_loop, push_frame;
-#if V8_TARGET_ARCH_PPC64
-  __ cmpi(r6, Operand::Zero());
-  __ beq(&push_frame);
-#else
-  __ SmiUntag(r6, SetRC);
-  __ beq(&push_frame, cr0);
-#endif
-  __ mtctr(r6);
-  __ bind(&argument_loop);
-  __ push(r5);
-  __ bdnz(&argument_loop);
-
-  // Enter a new JavaScript frame, and initialize its slots as they were when
-  // the generator was suspended.
-  Label resume_frame, done;
-  __ bind(&push_frame);
-  __ b(&resume_frame, SetLK);
-  __ b(&done);
-  __ bind(&resume_frame);
-  // lr = return address.
-  // fp = caller's frame pointer.
-  // cp = callee's context,
-  // r7 = callee's JS function.
-  __ PushStandardFrame(r7);
-
-  // Load the operand stack size.
-  __ LoadP(r6, FieldMemOperand(r4, JSGeneratorObject::kOperandStackOffset));
-  __ LoadP(r6, FieldMemOperand(r6, FixedArray::kLengthOffset));
-  __ SmiUntag(r6, SetRC);
-
-  // If we are sending a value and there is no operand stack, we can jump back
-  // in directly.
-  Label call_resume;
-  if (resume_mode == JSGeneratorObject::NEXT) {
-    Label slow_resume;
-    __ bne(&slow_resume, cr0);
-    __ LoadP(ip, FieldMemOperand(r7, JSFunction::kCodeEntryOffset));
-    {
-      ConstantPoolUnavailableScope constant_pool_unavailable(masm_);
-      if (FLAG_enable_embedded_constant_pool) {
-        __ LoadConstantPoolPointerRegisterFromCodeTargetAddress(ip);
-      }
-      __ LoadP(r5, FieldMemOperand(r4, JSGeneratorObject::kContinuationOffset));
-      __ SmiUntag(r5);
-      __ add(ip, ip, r5);
-      __ LoadSmiLiteral(r5,
-                        Smi::FromInt(JSGeneratorObject::kGeneratorExecuting));
-      __ StoreP(r5, FieldMemOperand(r4, JSGeneratorObject::kContinuationOffset),
-                r0);
-      __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-      __ Jump(ip);
-      __ bind(&slow_resume);
-    }
-  } else {
-    __ beq(&call_resume, cr0);
-  }
-
-  // Otherwise, we push holes for the operand stack and call the runtime to fix
-  // up the stack and the handlers.
-  Label operand_loop;
-  __ mtctr(r6);
-  __ bind(&operand_loop);
-  __ push(r5);
-  __ bdnz(&operand_loop);
-
-  __ bind(&call_resume);
-  __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-  DCHECK(!result_register().is(r4));
-  __ Push(r4, result_register());
-  __ Push(Smi::FromInt(resume_mode));
-  __ CallRuntime(Runtime::kResumeJSGeneratorObject);
-  // Not reached: the runtime call returns elsewhere.
-  __ stop("not-reached");
-
-  __ bind(&done);
-  context()->Plug(result_register());
-}
-
 void FullCodeGenerator::PushOperands(Register reg1, Register reg2) {
   OperandStackDepthIncrement(2);
   __ Push(reg1, reg2);
@@ -1987,7 +1866,8 @@
 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
   Label allocate, done_allocate;
 
-  __ Allocate(JSIteratorResult::kSize, r3, r5, r6, &allocate, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, r3, r5, r6, &allocate,
+              NO_ALLOCATION_FLAGS);
   __ b(&done_allocate);
 
   __ bind(&allocate);
@@ -2346,8 +2226,7 @@
     __ bind(&uninitialized_this);
     EmitStoreToStackLocalOrContextSlot(var, location);
 
-  } else if (!var->is_const_mode() ||
-             (var->mode() == CONST && op == Token::INIT)) {
+  } else if (!var->is_const_mode() || op == Token::INIT) {
     if (var->IsLookupSlot()) {
       // Assignment to var.
       __ Push(var->name());
@@ -2368,25 +2247,6 @@
       }
       EmitStoreToStackLocalOrContextSlot(var, location);
     }
-  } else if (var->mode() == CONST_LEGACY && op == Token::INIT) {
-    // Const initializers need a write barrier.
-    DCHECK(!var->IsParameter());  // No const parameters.
-    if (var->IsLookupSlot()) {
-      __ push(r3);
-      __ mov(r3, Operand(var->name()));
-      __ Push(cp, r3);  // Context and name.
-      __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot);
-    } else {
-      DCHECK(var->IsStackAllocated() || var->IsContextSlot());
-      Label skip;
-      MemOperand location = VarOperand(var, r4);
-      __ LoadP(r5, location);
-      __ CompareRoot(r5, Heap::kTheHoleValueRootIndex);
-      __ bne(&skip);
-      EmitStoreToStackLocalOrContextSlot(var, location);
-      __ bind(&skip);
-    }
-
   } else {
     DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT);
     if (is_strict(language_mode())) {
@@ -2409,7 +2269,7 @@
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallStoreIC();
 
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(r3);
 }
 
@@ -2454,44 +2314,7 @@
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallIC(ic);
 
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
-  context()->Plug(r3);
-}
-
-
-void FullCodeGenerator::VisitProperty(Property* expr) {
-  Comment cmnt(masm_, "[ Property");
-  SetExpressionPosition(expr);
-
-  Expression* key = expr->key();
-
-  if (key->IsPropertyName()) {
-    if (!expr->IsSuperAccess()) {
-      VisitForAccumulatorValue(expr->obj());
-      __ Move(LoadDescriptor::ReceiverRegister(), r3);
-      EmitNamedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      EmitNamedSuperPropertyLoad(expr);
-    }
-  } else {
-    if (!expr->IsSuperAccess()) {
-      VisitForStackValue(expr->obj());
-      VisitForAccumulatorValue(expr->key());
-      __ Move(LoadDescriptor::NameRegister(), r3);
-      PopOperand(LoadDescriptor::ReceiverRegister());
-      EmitKeyedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      VisitForStackValue(expr->key());
-      EmitKeyedSuperPropertyLoad(expr);
-    }
-  }
-  PrepareForBailoutForId(expr->LoadId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(r3);
 }
 
@@ -2512,7 +2335,7 @@
     {
       StackValueContext context(this);
       EmitVariableLoad(callee->AsVariableProxy());
-      PrepareForBailout(callee, NO_REGISTERS);
+      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
     }
     // Push undefined as receiver. This is patched in the method prologue if it
     // is a sloppy mode method.
@@ -2525,7 +2348,8 @@
     DCHECK(!callee->AsProperty()->IsSuperAccess());
     __ LoadP(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
     EmitNamedPropertyLoad(callee->AsProperty());
-    PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                           BailoutState::TOS_REGISTER);
     // Push the target function under the receiver.
     __ LoadP(r0, MemOperand(sp, 0));
     PushOperand(r0);
@@ -2562,6 +2386,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ StoreP(r3, MemOperand(sp, kPointerSize));
@@ -2585,7 +2410,8 @@
   __ LoadP(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
   __ Move(LoadDescriptor::NameRegister(), r3);
   EmitKeyedPropertyLoad(callee->AsProperty());
-  PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                         BailoutState::TOS_REGISTER);
 
   // Push the target function under the receiver.
   __ LoadP(ip, MemOperand(sp, 0));
@@ -2619,6 +2445,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ StoreP(r3, MemOperand(sp, kPointerSize));
@@ -2638,7 +2465,7 @@
     VisitForStackValue(args->at(i));
   }
 
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   SetCallPosition(expr, expr->tail_call_mode());
   if (expr->tail_call_mode() == TailCallMode::kAllow) {
     if (FLAG_trace) {
@@ -2659,13 +2486,13 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-  // Restore context register.
-  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->DropAndPlug(1, r3);
 }
 
 
-void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
+void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
+  int arg_count = expr->arguments()->length();
   // r7: copy of the first argument or undefined if it doesn't exist.
   if (arg_count > 0) {
     __ LoadP(r7, MemOperand(sp, arg_count * kPointerSize), r0);
@@ -2682,8 +2509,11 @@
   // r4: the start position of the scope the calls resides in.
   __ LoadSmiLiteral(r4, Smi::FromInt(scope()->start_position()));
 
+  // r3: the source position of the eval call.
+  __ LoadSmiLiteral(r3, Smi::FromInt(expr->position()));
+
   // Do the runtime call.
-  __ Push(r7, r6, r5, r4);
+  __ Push(r7, r6, r5, r4, r3);
   __ CallRuntime(Runtime::kResolvePossiblyDirectEval);
 }
 
@@ -2704,7 +2534,7 @@
     __ Push(callee->name());
     __ CallRuntime(Runtime::kLoadLookupSlotForCall);
     PushOperands(r3, r4);  // Function, receiver.
-    PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
+    PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
 
     // If fast case code has been generated, emit code to push the function
     // and receiver and have the slow path jump around this code.
@@ -2731,9 +2561,9 @@
 
 
 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
-  // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
-  // to resolve the function we need to call.  Then we call the resolved
-  // function using the given arguments.
+  // In a call to eval, we first call
+  // Runtime_ResolvePossiblyDirectEval to resolve the function we need
+  // to call.  Then we call the resolved function using the given arguments.
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
 
@@ -2748,12 +2578,12 @@
   // resolve eval.
   __ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
   __ push(r4);
-  EmitResolvePossiblyDirectEval(arg_count);
+  EmitResolvePossiblyDirectEval(expr);
 
   // Touch up the stack with the resolved function.
   __ StoreP(r3, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
 
-  PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
 
   // Record source position for debugger.
   SetCallPosition(expr);
@@ -2764,8 +2594,7 @@
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
   RecordJSReturnSite(expr);
-  // Restore context register.
-  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->DropAndPlug(1, r3);
 }
 
@@ -2804,9 +2633,8 @@
   CallConstructStub stub(isolate());
   __ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
-  // Restore context register.
-  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
+  RestoreContext();
   context()->Plug(r3);
 }
 
@@ -2849,9 +2677,7 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-
-  // Restore context register.
-  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->Plug(r3);
 }
 
@@ -3058,70 +2884,6 @@
 }
 
 
-void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = r3;
-  Register index = r4;
-  Register value = r5;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-  PopOperands(index, value);
-
-  if (FLAG_debug_code) {
-    __ TestIfSmi(value, r0);
-    __ Check(eq, kNonSmiValue, cr0);
-    __ TestIfSmi(index, r0);
-    __ Check(eq, kNonSmiIndex, cr0);
-    __ SmiUntag(index, index);
-    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
-    __ SmiTag(index, index);
-  }
-
-  __ SmiUntag(value);
-  __ addi(ip, string, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
-  __ SmiToByteArrayOffset(r0, index);
-  __ stbx(value, MemOperand(ip, r0));
-  context()->Plug(string);
-}
-
-
-void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = r3;
-  Register index = r4;
-  Register value = r5;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-  PopOperands(index, value);
-
-  if (FLAG_debug_code) {
-    __ TestIfSmi(value, r0);
-    __ Check(eq, kNonSmiValue, cr0);
-    __ TestIfSmi(index, r0);
-    __ Check(eq, kNonSmiIndex, cr0);
-    __ SmiUntag(index, index);
-    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
-    __ SmiTag(index, index);
-  }
-
-  __ SmiUntag(value);
-  __ addi(ip, string, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
-  __ SmiToShortArrayOffset(r0, index);
-  __ sthx(value, MemOperand(ip, r0));
-  context()->Plug(string);
-}
-
-
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
@@ -3156,8 +2918,7 @@
   Label index_out_of_range;
   Label done;
   StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
-                                      &need_conversion, &index_out_of_range,
-                                      STRING_INDEX_IS_NUMBER);
+                                      &need_conversion, &index_out_of_range);
   generator.GenerateFast(masm_);
   __ b(&done);
 
@@ -3181,48 +2942,6 @@
 }
 
 
-void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK(args->length() == 2);
-  VisitForStackValue(args->at(0));
-  VisitForAccumulatorValue(args->at(1));
-
-  Register object = r4;
-  Register index = r3;
-  Register scratch = r6;
-  Register result = r3;
-
-  PopOperand(object);
-
-  Label need_conversion;
-  Label index_out_of_range;
-  Label done;
-  StringCharAtGenerator generator(object, index, scratch, result,
-                                  &need_conversion, &need_conversion,
-                                  &index_out_of_range, STRING_INDEX_IS_NUMBER);
-  generator.GenerateFast(masm_);
-  __ b(&done);
-
-  __ bind(&index_out_of_range);
-  // When the index is out of range, the spec requires us to return
-  // the empty string.
-  __ LoadRoot(result, Heap::kempty_stringRootIndex);
-  __ b(&done);
-
-  __ bind(&need_conversion);
-  // Move smi zero into the result register, which will trigger
-  // conversion.
-  __ LoadSmiLiteral(result, Smi::FromInt(0));
-  __ b(&done);
-
-  NopRuntimeCallHelper call_helper;
-  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
-
-  __ bind(&done);
-  context()->Plug(result);
-}
-
-
 void FullCodeGenerator::EmitCall(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK_LE(2, args->length());
@@ -3230,7 +2949,7 @@
   for (Expression* const arg : *args) {
     VisitForStackValue(arg);
   }
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   // Move target to r4.
   int const argc = args->length() - 2;
   __ LoadP(r4, MemOperand(sp, (argc + 1) * kPointerSize));
@@ -3238,8 +2957,7 @@
   __ mov(r3, Operand(argc));
   __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(argc + 1);
-  // Restore context register.
-  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   // Discard the function left on TOS.
   context()->DropAndPlug(1, r3);
 }
@@ -3291,12 +3009,6 @@
   context()->Plug(r3);
 }
 
-void FullCodeGenerator::EmitGetOrdinaryHasInstance(CallRuntime* expr) {
-  DCHECK_EQ(0, expr->arguments()->length());
-  __ LoadNativeContextSlot(Context::ORDINARY_HAS_INSTANCE_INDEX, r3);
-  context()->Plug(r3);
-}
-
 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
   DCHECK(expr->arguments()->length() == 0);
   ExternalReference debug_is_active =
@@ -3316,7 +3028,8 @@
 
   Label runtime, done;
 
-  __ Allocate(JSIteratorResult::kSize, r3, r5, r6, &runtime, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, r3, r5, r6, &runtime,
+              NO_ALLOCATION_FLAGS);
   __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, r4);
   __ Pop(r5, r6);
   __ LoadRoot(r7, Heap::kEmptyFixedArrayRootIndex);
@@ -3357,9 +3070,7 @@
   __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-
-  // Restore context register.
-  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
 }
 
 
@@ -3439,12 +3150,14 @@
                         &materialize_true, &materialize_true);
         if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
         __ bind(&materialize_true);
-        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeTrueId(),
+                               BailoutState::NO_REGISTERS);
         __ LoadRoot(r3, Heap::kTrueValueRootIndex);
         if (context()->IsStackValue()) __ push(r3);
         __ b(&done);
         __ bind(&materialize_false);
-        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeFalseId(),
+                               BailoutState::NO_REGISTERS);
         __ LoadRoot(r3, Heap::kFalseValueRootIndex);
         if (context()->IsStackValue()) __ push(r3);
         __ bind(&done);
@@ -3544,9 +3257,9 @@
   // We need a second deoptimization point after loading the value
   // in case evaluating the property load my have a side effect.
   if (assign_type == VARIABLE) {
-    PrepareForBailout(expr->expression(), TOS_REG);
+    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
   } else {
-    PrepareForBailoutForId(prop->LoadId(), TOS_REG);
+    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
   }
 
   // Inline smi case if we are in a loop.
@@ -3596,9 +3309,8 @@
   }
 
   // Convert old value into a number.
-  ToNumberStub convert_stub(isolate());
-  __ CallStub(&convert_stub);
-  PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
+  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
+  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
 
   // Save result for postfix expressions.
   if (expr->is_postfix()) {
@@ -3645,7 +3357,8 @@
           EffectContext context(this);
           EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                  Token::ASSIGN, expr->CountSlot());
-          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+          PrepareForBailoutForId(expr->AssignmentId(),
+                                 BailoutState::TOS_REGISTER);
           context.Plug(r3);
         }
         // For all contexts except EffectConstant We have the result on
@@ -3656,7 +3369,8 @@
       } else {
         EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                Token::ASSIGN, expr->CountSlot());
-        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+        PrepareForBailoutForId(expr->AssignmentId(),
+                               BailoutState::TOS_REGISTER);
         context()->Plug(r3);
       }
       break;
@@ -3666,7 +3380,7 @@
       PopOperand(StoreDescriptor::ReceiverRegister());
       EmitLoadStoreICSlot(expr->CountSlot());
       CallStoreIC();
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         if (!context()->IsEffect()) {
           context()->PlugTOS();
@@ -3705,7 +3419,7 @@
           CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
       EmitLoadStoreICSlot(expr->CountSlot());
       CallIC(ic);
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         if (!context()->IsEffect()) {
           context()->PlugTOS();
@@ -3804,7 +3518,6 @@
 
 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
   Comment cmnt(masm_, "[ CompareOperation");
-  SetExpressionPosition(expr);
 
   // First we try a fast inlined version of the compare when one of
   // the operands is a literal.
@@ -3824,7 +3537,8 @@
   switch (op) {
     case Token::IN:
       VisitForStackValue(expr->right());
-      CallRuntimeWithOperands(Runtime::kHasProperty);
+      SetExpressionPosition(expr);
+      EmitHasProperty();
       PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
       __ CompareRoot(r3, Heap::kTrueValueRootIndex);
       Split(eq, if_true, if_false, fall_through);
@@ -3832,6 +3546,7 @@
 
     case Token::INSTANCEOF: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       PopOperand(r4);
       InstanceOfStub stub(isolate());
       __ CallStub(&stub);
@@ -3843,6 +3558,7 @@
 
     default: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       Condition cond = CompareIC::ComputeCondition(op);
       PopOperand(r4);
 
diff --git a/src/full-codegen/s390/OWNERS b/src/full-codegen/s390/OWNERS
index eb007cb..752e8e3 100644
--- a/src/full-codegen/s390/OWNERS
+++ b/src/full-codegen/s390/OWNERS
@@ -3,3 +3,4 @@
 joransiu@ca.ibm.com
 mbrandy@us.ibm.com
 michael_dawson@ca.ibm.com
+bjaideep@ca.ibm.com
diff --git a/src/full-codegen/s390/full-codegen-s390.cc b/src/full-codegen/s390/full-codegen-s390.cc
index 88bec4c..ee0b3e3 100644
--- a/src/full-codegen/s390/full-codegen-s390.cc
+++ b/src/full-codegen/s390/full-codegen-s390.cc
@@ -187,7 +187,8 @@
       __ push(r3);
       __ Push(info->scope()->GetScopeInfo(info->isolate()));
       __ CallRuntime(Runtime::kNewScriptContext);
-      PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
+      PrepareForBailoutForId(BailoutId::ScriptContext(),
+                             BailoutState::TOS_REGISTER);
       // The new target value is not used, clobbering is safe.
       DCHECK_NULL(info->scope()->new_target_var());
     } else {
@@ -243,7 +244,8 @@
   // Register holding this function and new target are both trashed in case we
   // bailout here. But since that can happen only when new target is not used
   // and we allocate a context, the value of |function_in_register| is correct.
-  PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionContext(),
+                         BailoutState::NO_REGISTERS);
 
   // Possibly set up a local binding to the this function which is used in
   // derived constructors with super calls.
@@ -307,7 +309,8 @@
   }
 
   // Visit the declarations and body.
-  PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionEntry(),
+                         BailoutState::NO_REGISTERS);
   {
     Comment cmnt(masm_, "[ Declarations");
     VisitDeclarations(scope()->declarations());
@@ -320,7 +323,8 @@
 
   {
     Comment cmnt(masm_, "[ Stack check");
-    PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
+    PrepareForBailoutForId(BailoutId::Declarations(),
+                           BailoutState::NO_REGISTERS);
     Label ok;
     __ LoadRoot(ip, Heap::kStackLimitRootIndex);
     __ CmpLogicalP(sp, ip);
@@ -392,11 +396,11 @@
   EmitProfilingCounterReset();
 
   __ bind(&ok);
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
   // Record a mapping of the OSR id to this PC.  This is used if the OSR
   // entry becomes the target of a bailout.  We don't expect it to be, but
   // we want it to work if it is.
-  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
 }
 
 void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
@@ -454,6 +458,10 @@
   }
 }
 
+void FullCodeGenerator::RestoreContext() {
+  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+}
+
 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
   DCHECK(var->IsStackAllocated() || var->IsContextSlot());
   codegen()->GetVar(result_register(), var);
@@ -504,10 +512,12 @@
 void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
   codegen()->PrepareForBailoutBeforeSplit(condition(), true, true_label_,
                                           false_label_);
-  DCHECK(lit->IsNull() || lit->IsUndefined() || !lit->IsUndetectable());
-  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
+  DCHECK(lit->IsNull(isolate()) || lit->IsUndefined(isolate()) ||
+         !lit->IsUndetectable());
+  if (lit->IsUndefined(isolate()) || lit->IsNull(isolate()) ||
+      lit->IsFalse(isolate())) {
     if (false_label_ != fall_through_) __ b(false_label_);
-  } else if (lit->IsTrue() || lit->IsJSObject()) {
+  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
     if (true_label_ != fall_through_) __ b(true_label_);
   } else if (lit->IsString()) {
     if (String::cast(*lit)->length() == 0) {
@@ -670,7 +680,7 @@
 
   Label skip;
   if (should_normalize) __ b(&skip);
-  PrepareForBailout(expr, TOS_REG);
+  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
   if (should_normalize) {
     __ CompareRoot(r2, Heap::kTrueValueRootIndex);
     Split(eq, if_true, if_false, NULL);
@@ -700,15 +710,13 @@
   VariableProxy* proxy = declaration->proxy();
   VariableMode mode = declaration->mode();
   Variable* variable = proxy->var();
-  bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
+  bool hole_init = mode == LET || mode == CONST;
   switch (variable->location()) {
     case VariableLocation::GLOBAL:
     case VariableLocation::UNALLOCATED:
+      DCHECK(!variable->binding_needs_init());
       globals_->Add(variable->name(), zone());
-      globals_->Add(variable->binding_needs_init()
-                        ? isolate()->factory()->the_hole_value()
-                        : isolate()->factory()->undefined_value(),
-                    zone());
+      globals_->Add(isolate()->factory()->undefined_value(), zone());
       break;
 
     case VariableLocation::PARAMETER:
@@ -727,27 +735,18 @@
         __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
         __ StoreP(ip, ContextMemOperand(cp, variable->index()));
         // No write barrier since the_hole_value is in old space.
-        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+        PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       }
       break;
 
     case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
+      DCHECK_EQ(VAR, mode);
+      DCHECK(!hole_init);
       __ mov(r4, Operand(variable->name()));
-      // Declaration nodes are always introduced in one of four modes.
-      DCHECK(IsDeclaredVariableMode(mode));
-      // Push initial value, if any.
-      // Note: For variables we must not push an initial value (such as
-      // 'undefined') because we may have a (legal) redeclaration and we
-      // must not destroy the current value.
-      if (hole_init) {
-        __ LoadRoot(r2, Heap::kTheHoleValueRootIndex);
-      } else {
-        __ LoadSmiLiteral(r2, Smi::FromInt(0));  // Indicates no initial value.
-      }
-      __ Push(r4, r2);
-      __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes()));
-      __ CallRuntime(Runtime::kDeclareLookupSlot);
+      __ Push(r4);
+      __ CallRuntime(Runtime::kDeclareEvalVar);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -787,7 +786,7 @@
       __ RecordWriteContextSlot(cp, offset, result_register(), r4,
                                 kLRHasBeenSaved, kDontSaveFPRegs,
                                 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
-      PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
 
@@ -797,8 +796,8 @@
       PushOperand(r4);
       // Push initial value for function declaration.
       VisitForStackValue(declaration->fun());
-      PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
-      CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
+      CallRuntimeWithOperands(Runtime::kDeclareEvalFunction);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -827,7 +826,7 @@
 
   // Keep the switch value on the stack until a case matches.
   VisitForStackValue(stmt->tag());
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
 
   ZoneList<CaseClause*>* clauses = stmt->cases();
   CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
@@ -877,7 +876,7 @@
 
     Label skip;
     __ b(&skip);
-    PrepareForBailout(clause, TOS_REG);
+    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
     __ CompareRoot(r2, Heap::kTrueValueRootIndex);
     __ bne(&next_test);
     __ Drop(1);
@@ -905,12 +904,12 @@
     Comment cmnt(masm_, "[ Case body");
     CaseClause* clause = clauses->at(i);
     __ bind(clause->body_target());
-    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
+    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
     VisitStatements(clause->statements());
   }
 
   __ bind(nested_statement.break_label());
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
 }
 
 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
@@ -942,15 +941,13 @@
   ToObjectStub stub(isolate());
   __ CallStub(&stub);
   __ bind(&done_convert);
-  PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
+  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
   __ push(r2);
 
-  // Check cache validity in generated code. This is a fast case for
-  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
-  // guarantee cache validity, call the runtime system to check cache
-  // validity or get the property names in a fixed array.
-  // Note: Proxies never have an enum cache, so will always take the
-  // slow path.
+  // Check cache validity in generated code. If we cannot guarantee cache
+  // validity, call the runtime system to check cache validity or get the
+  // property names in a fixed array. Note: Proxies never have an enum cache,
+  // so will always take the slow path.
   Label call_runtime;
   __ CheckEnumCache(&call_runtime);
 
@@ -964,7 +961,7 @@
   __ bind(&call_runtime);
   __ push(r2);  // Duplicate the enumerable object on the stack.
   __ CallRuntime(Runtime::kForInEnumerate);
-  PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
+  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
 
   // If we got a map from the runtime call, we can do a fast
   // modification check. Otherwise, we got a fixed array, and we have
@@ -1005,7 +1002,7 @@
   __ Push(r3, r2);                         // Smi and array
   __ LoadP(r3, FieldMemOperand(r2, FixedArray::kLengthOffset));
   __ Push(r3);  // Fixed array length (as smi).
-  PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
   __ LoadSmiLiteral(r2, Smi::FromInt(0));
   __ Push(r2);  // Initial index.
 
@@ -1049,7 +1046,7 @@
   // just skip it.
   __ Push(r3, r5);  // Enumerable and current entry.
   __ CallRuntime(Runtime::kForInFilter);
-  PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
+  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
   __ LoadRR(r5, r2);
   __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
   __ CmpP(r2, r0);
@@ -1063,11 +1060,11 @@
   {
     EffectContext context(this);
     EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
-    PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
+    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
   }
 
   // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
-  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
   // Generate code for the body of the loop.
   Visit(stmt->body());
 
@@ -1086,7 +1083,7 @@
   DropOperands(5);
 
   // Exit and decrement the loop depth.
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   __ bind(&exit);
   decrement_loop_depth();
 }
@@ -1210,17 +1207,12 @@
   } else if (var->mode() == DYNAMIC_LOCAL) {
     Variable* local = var->local_if_not_shadowed();
     __ LoadP(r2, ContextSlotOperandCheckExtensions(local, slow));
-    if (local->mode() == LET || local->mode() == CONST ||
-        local->mode() == CONST_LEGACY) {
+    if (local->mode() == LET || local->mode() == CONST) {
       __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
       __ bne(done);
-      if (local->mode() == CONST_LEGACY) {
-        __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
-      } else {  // LET || CONST
-        __ mov(r2, Operand(var->name()));
-        __ push(r2);
-        __ CallRuntime(Runtime::kThrowReferenceError);
-      }
+      __ mov(r2, Operand(var->name()));
+      __ push(r2);
+      __ CallRuntime(Runtime::kThrowReferenceError);
     }
     __ b(done);
   }
@@ -1228,21 +1220,21 @@
 
 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
                                                TypeofMode typeof_mode) {
+#ifdef DEBUG
   Variable* var = proxy->var();
   DCHECK(var->IsUnallocatedOrGlobalSlot() ||
          (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
-  __ LoadGlobalObject(LoadDescriptor::ReceiverRegister());
-  __ mov(LoadDescriptor::NameRegister(), Operand(var->name()));
-  __ mov(LoadDescriptor::SlotRegister(),
+#endif
+  __ mov(LoadGlobalDescriptor::SlotRegister(),
          Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
-  CallLoadIC(typeof_mode);
+  CallLoadGlobalIC(typeof_mode);
 }
 
 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
                                          TypeofMode typeof_mode) {
   // Record position before possible IC call.
   SetExpressionPosition(proxy);
-  PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
+  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
   Variable* var = proxy->var();
 
   // Three cases: global variables, lookup variables, and all other types of
@@ -1274,10 +1266,6 @@
           __ mov(r2, Operand(var->name()));
           __ push(r2);
           __ CallRuntime(Runtime::kThrowReferenceError);
-        } else {
-          // Uninitialized legacy const bindings are unholed.
-          DCHECK(var->mode() == CONST_LEGACY);
-          __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
         }
         __ bind(&done);
         context()->Plug(r2);
@@ -1306,17 +1294,6 @@
   }
 }
 
-void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
-  Comment cmnt(masm_, "[ RegExpLiteral");
-  __ LoadP(r5, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  __ LoadSmiLiteral(r4, Smi::FromInt(expr->literal_index()));
-  __ mov(r3, Operand(expr->pattern()));
-  __ LoadSmiLiteral(r2, Smi::FromInt(expr->flags()));
-  FastCloneRegExpStub stub(isolate());
-  __ CallStub(&stub);
-  context()->Plug(r2);
-}
-
 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
   Expression* expression = (property == NULL) ? NULL : property->value();
   if (expression == NULL) {
@@ -1348,8 +1325,9 @@
   } else {
     FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
     __ CallStub(&stub);
+    RestoreContext();
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   // If result_saved is true the result is on top of the stack.  If
   // result_saved is false the result is in r2.
@@ -1385,7 +1363,7 @@
             __ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
             EmitLoadStoreICSlot(property->GetSlot(0));
             CallStoreIC();
-            PrepareForBailoutForId(key->id(), NO_REGISTERS);
+            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
 
             if (NeedsHomeObject(value)) {
               EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
@@ -1419,16 +1397,20 @@
         DCHECK(property->emit_store());
         CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
         PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                               NO_REGISTERS);
+                               BailoutState::NO_REGISTERS);
         break;
       case ObjectLiteral::Property::GETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->getter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->getter = property;
         }
         break;
       case ObjectLiteral::Property::SETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->setter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->setter = property;
         }
         break;
     }
@@ -1446,6 +1428,7 @@
     __ LoadSmiLiteral(r2, Smi::FromInt(NONE));
     PushOperand(r2);
     CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
+    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
   }
 
   // Object literals have two parts. The "static" part on the left contains no
@@ -1475,7 +1458,7 @@
       DCHECK(property->emit_store());
       CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
       PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                             NO_REGISTERS);
+                             BailoutState::NO_REGISTERS);
     } else {
       EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
       VisitForStackValue(value);
@@ -1491,6 +1474,8 @@
             PushOperand(Smi::FromInt(NONE));
             PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
             CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
+            PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
+                                   BailoutState::NO_REGISTERS);
           } else {
             DropOperands(3);
           }
@@ -1547,7 +1532,7 @@
     FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
     __ CallStub(&stub);
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   bool result_saved = false;  // Is the result saved to the stack?
   ZoneList<Expression*>* subexprs = expr->values();
@@ -1577,7 +1562,8 @@
         CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
     CallIC(ic);
 
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   // In case the array literal contains spread expressions it has two parts. The
@@ -1597,7 +1583,8 @@
     VisitForStackValue(subexpr);
     CallRuntimeWithOperands(Runtime::kAppendElement);
 
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   if (result_saved) {
@@ -1611,7 +1598,6 @@
   DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
 
   Comment cmnt(masm_, "[ Assignment");
-  SetExpressionPosition(expr, INSERT_BREAK);
 
   Property* property = expr->target()->AsProperty();
   LhsKind assign_type = Property::GetAssignType(property);
@@ -1680,23 +1666,27 @@
       switch (assign_type) {
         case VARIABLE:
           EmitVariableLoad(expr->target()->AsVariableProxy());
-          PrepareForBailout(expr->target(), TOS_REG);
+          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
           break;
         case NAMED_PROPERTY:
           EmitNamedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case NAMED_SUPER_PROPERTY:
           EmitNamedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_SUPER_PROPERTY:
           EmitKeyedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_PROPERTY:
           EmitKeyedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
       }
     }
@@ -1714,7 +1704,7 @@
     }
 
     // Deoptimization point in case the binary operation may have side effects.
-    PrepareForBailout(expr->binary_operation(), TOS_REG);
+    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
   } else {
     VisitForAccumulatorValue(expr->value());
   }
@@ -1726,7 +1716,7 @@
     case VARIABLE:
       EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
                              expr->op(), expr->AssignmentSlot());
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       context()->Plug(r2);
       break;
     case NAMED_PROPERTY:
@@ -1754,21 +1744,26 @@
   // this.  It stays on the stack while we update the iterator.
   VisitForStackValue(expr->expression());
 
-  Label suspend, continuation, post_runtime, resume;
+  Label suspend, continuation, post_runtime, resume, exception;
 
   __ b(&suspend);
   __ bind(&continuation);
-  // When we arrive here, the stack top is the resume mode and
-  // result_register() holds the input value (the argument given to the
-  // respective resume operation).
+  // When we arrive here, r2 holds the generator object.
   __ RecordGeneratorContinuation();
-  __ pop(r3);
-  __ CmpSmiLiteral(r3, Smi::FromInt(JSGeneratorObject::RETURN), r0);
-  __ bne(&resume);
-  __ push(result_register());
+  __ LoadP(r3, FieldMemOperand(r2, JSGeneratorObject::kResumeModeOffset));
+  __ LoadP(r2, FieldMemOperand(r2, JSGeneratorObject::kInputOrDebugPosOffset));
+  STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
+  STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
+  __ CmpSmiLiteral(r3, Smi::FromInt(JSGeneratorObject::kReturn), r0);
+  __ blt(&resume);
+  __ Push(result_register());
+  __ bgt(&exception);
   EmitCreateIteratorResult(true);
   EmitUnwindAndReturn();
 
+  __ bind(&exception);
+  __ CallRuntime(Runtime::kThrow);
+
   __ bind(&suspend);
   OperandStackDepthIncrement(1);  // Not popped on this path.
   VisitForAccumulatorValue(expr->generator_object());
@@ -1785,7 +1780,7 @@
   __ beq(&post_runtime);
   __ push(r2);  // generator object
   __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
-  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   __ bind(&post_runtime);
   PopOperand(result_register());
   EmitReturnSequence();
@@ -1794,113 +1789,6 @@
   context()->Plug(result_register());
 }
 
-void FullCodeGenerator::EmitGeneratorResume(
-    Expression* generator, Expression* value,
-    JSGeneratorObject::ResumeMode resume_mode) {
-  // The value stays in r2, and is ultimately read by the resumed generator, as
-  // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it
-  // is read to throw the value when the resumed generator is already closed.
-  // r3 will hold the generator object until the activation has been resumed.
-  VisitForStackValue(generator);
-  VisitForAccumulatorValue(value);
-  PopOperand(r3);
-
-  // Store input value into generator object.
-  __ StoreP(result_register(),
-            FieldMemOperand(r3, JSGeneratorObject::kInputOffset), r0);
-  __ LoadRR(r4, result_register());
-  __ RecordWriteField(r3, JSGeneratorObject::kInputOffset, r4, r5,
-                      kLRHasBeenSaved, kDontSaveFPRegs);
-
-  // Load suspended function and context.
-  __ LoadP(cp, FieldMemOperand(r3, JSGeneratorObject::kContextOffset));
-  __ LoadP(r6, FieldMemOperand(r3, JSGeneratorObject::kFunctionOffset));
-
-  // Load receiver and store as the first argument.
-  __ LoadP(r4, FieldMemOperand(r3, JSGeneratorObject::kReceiverOffset));
-  __ push(r4);
-
-  // Push holes for arguments to generator function. Since the parser forced
-  // context allocation for any variables in generators, the actual argument
-  // values have already been copied into the context and these dummy values
-  // will never be used.
-  __ LoadP(r5, FieldMemOperand(r6, JSFunction::kSharedFunctionInfoOffset));
-  __ LoadW(
-      r5, FieldMemOperand(r5, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ LoadRoot(r4, Heap::kTheHoleValueRootIndex);
-  Label argument_loop, push_frame;
-#if V8_TARGET_ARCH_S390X
-  __ CmpP(r5, Operand::Zero());
-  __ beq(&push_frame, Label::kNear);
-#else
-  __ SmiUntag(r5);
-  __ beq(&push_frame, Label::kNear);
-#endif
-  __ LoadRR(r0, r5);
-  __ bind(&argument_loop);
-  __ push(r4);
-  __ SubP(r0, Operand(1));
-  __ bne(&argument_loop);
-
-  // Enter a new JavaScript frame, and initialize its slots as they were when
-  // the generator was suspended.
-  Label resume_frame, done;
-  __ bind(&push_frame);
-  __ b(r14, &resume_frame);  // brasl
-  __ b(&done);
-  __ bind(&resume_frame);
-  // lr = return address.
-  // fp = caller's frame pointer.
-  // cp = callee's context,
-  // r6 = callee's JS function.
-  __ PushStandardFrame(r6);
-
-  // Load the operand stack size.
-  __ LoadP(r5, FieldMemOperand(r3, JSGeneratorObject::kOperandStackOffset));
-  __ LoadP(r5, FieldMemOperand(r5, FixedArray::kLengthOffset));
-  __ SmiUntag(r5);
-
-  // If we are sending a value and there is no operand stack, we can jump back
-  // in directly.
-  Label call_resume;
-  if (resume_mode == JSGeneratorObject::NEXT) {
-    Label slow_resume;
-    __ bne(&slow_resume, Label::kNear);
-    __ LoadP(ip, FieldMemOperand(r6, JSFunction::kCodeEntryOffset));
-    __ LoadP(r4, FieldMemOperand(r3, JSGeneratorObject::kContinuationOffset));
-    __ SmiUntag(r4);
-    __ AddP(ip, ip, r4);
-    __ LoadSmiLiteral(r4, Smi::FromInt(JSGeneratorObject::kGeneratorExecuting));
-    __ StoreP(r4, FieldMemOperand(r3, JSGeneratorObject::kContinuationOffset));
-    __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-    __ Jump(ip);
-    __ bind(&slow_resume);
-  } else {
-    __ beq(&call_resume);
-  }
-
-  // Otherwise, we push holes for the operand stack and call the runtime to fix
-  // up the stack and the handlers.
-  Label operand_loop;
-  __ LoadRR(r0, r5);
-  __ bind(&operand_loop);
-  __ push(r4);
-  __ SubP(r0, Operand(1));
-  __ bne(&operand_loop);
-
-  __ bind(&call_resume);
-  __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-  DCHECK(!result_register().is(r3));
-  __ Push(r3, result_register());
-  __ Push(Smi::FromInt(resume_mode));
-  __ CallRuntime(Runtime::kResumeJSGeneratorObject);
-  // Not reached: the runtime call returns elsewhere.
-  __ stop("not-reached");
-
-  __ bind(&done);
-  context()->Plug(result_register());
-}
-
 void FullCodeGenerator::PushOperands(Register reg1, Register reg2) {
   OperandStackDepthIncrement(2);
   __ Push(reg1, reg2);
@@ -1936,7 +1824,8 @@
 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
   Label allocate, done_allocate;
 
-  __ Allocate(JSIteratorResult::kSize, r2, r4, r5, &allocate, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, r2, r4, r5, &allocate,
+              NO_ALLOCATION_FLAGS);
   __ b(&done_allocate);
 
   __ bind(&allocate);
@@ -2292,8 +2181,7 @@
     __ bind(&uninitialized_this);
     EmitStoreToStackLocalOrContextSlot(var, location);
 
-  } else if (!var->is_const_mode() ||
-             (var->mode() == CONST && op == Token::INIT)) {
+  } else if (!var->is_const_mode() || op == Token::INIT) {
     if (var->IsLookupSlot()) {
       // Assignment to var.
       __ Push(var->name());
@@ -2314,25 +2202,6 @@
       }
       EmitStoreToStackLocalOrContextSlot(var, location);
     }
-  } else if (var->mode() == CONST_LEGACY && op == Token::INIT) {
-    // Const initializers need a write barrier.
-    DCHECK(!var->IsParameter());  // No const parameters.
-    if (var->IsLookupSlot()) {
-      __ push(r2);
-      __ mov(r2, Operand(var->name()));
-      __ Push(cp, r2);  // Context and name.
-      __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot);
-    } else {
-      DCHECK(var->IsStackAllocated() || var->IsContextSlot());
-      Label skip;
-      MemOperand location = VarOperand(var, r3);
-      __ LoadP(r4, location);
-      __ CompareRoot(r4, Heap::kTheHoleValueRootIndex);
-      __ bne(&skip);
-      EmitStoreToStackLocalOrContextSlot(var, location);
-      __ bind(&skip);
-    }
-
   } else {
     DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT);
     if (is_strict(language_mode())) {
@@ -2354,7 +2223,7 @@
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallStoreIC();
 
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(r2);
 }
 
@@ -2396,43 +2265,7 @@
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallIC(ic);
 
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
-  context()->Plug(r2);
-}
-
-void FullCodeGenerator::VisitProperty(Property* expr) {
-  Comment cmnt(masm_, "[ Property");
-  SetExpressionPosition(expr);
-
-  Expression* key = expr->key();
-
-  if (key->IsPropertyName()) {
-    if (!expr->IsSuperAccess()) {
-      VisitForAccumulatorValue(expr->obj());
-      __ Move(LoadDescriptor::ReceiverRegister(), r2);
-      EmitNamedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      EmitNamedSuperPropertyLoad(expr);
-    }
-  } else {
-    if (!expr->IsSuperAccess()) {
-      VisitForStackValue(expr->obj());
-      VisitForAccumulatorValue(expr->key());
-      __ Move(LoadDescriptor::NameRegister(), r2);
-      PopOperand(LoadDescriptor::ReceiverRegister());
-      EmitKeyedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      VisitForStackValue(expr->key());
-      EmitKeyedSuperPropertyLoad(expr);
-    }
-  }
-  PrepareForBailoutForId(expr->LoadId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(r2);
 }
 
@@ -2451,7 +2284,7 @@
     {
       StackValueContext context(this);
       EmitVariableLoad(callee->AsVariableProxy());
-      PrepareForBailout(callee, NO_REGISTERS);
+      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
     }
     // Push undefined as receiver. This is patched in the method prologue if it
     // is a sloppy mode method.
@@ -2464,7 +2297,8 @@
     DCHECK(!callee->AsProperty()->IsSuperAccess());
     __ LoadP(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
     EmitNamedPropertyLoad(callee->AsProperty());
-    PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                           BailoutState::TOS_REGISTER);
     // Push the target function under the receiver.
     __ LoadP(r1, MemOperand(sp, 0));
     PushOperand(r1);
@@ -2500,6 +2334,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ StoreP(r2, MemOperand(sp, kPointerSize));
@@ -2522,7 +2357,8 @@
   __ LoadP(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
   __ Move(LoadDescriptor::NameRegister(), r2);
   EmitKeyedPropertyLoad(callee->AsProperty());
-  PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                         BailoutState::TOS_REGISTER);
 
   // Push the target function under the receiver.
   __ LoadP(ip, MemOperand(sp, 0));
@@ -2555,6 +2391,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ StoreP(r2, MemOperand(sp, kPointerSize));
@@ -2573,7 +2410,7 @@
     VisitForStackValue(args->at(i));
   }
 
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   SetCallPosition(expr, expr->tail_call_mode());
   if (expr->tail_call_mode() == TailCallMode::kAllow) {
     if (FLAG_trace) {
@@ -2594,12 +2431,12 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-  // Restore context register.
-  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->DropAndPlug(1, r2);
 }
 
-void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
+void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
+  int arg_count = expr->arguments()->length();
   // r6: copy of the first argument or undefined if it doesn't exist.
   if (arg_count > 0) {
     __ LoadP(r6, MemOperand(sp, arg_count * kPointerSize), r0);
@@ -2616,8 +2453,11 @@
   // r3: the start position of the scope the calls resides in.
   __ LoadSmiLiteral(r3, Smi::FromInt(scope()->start_position()));
 
+  // r2: the source position of the eval call.
+  __ LoadSmiLiteral(r2, Smi::FromInt(expr->position()));
+
   // Do the runtime call.
-  __ Push(r6, r5, r4, r3);
+  __ Push(r6, r5, r4, r3, r2);
   __ CallRuntime(Runtime::kResolvePossiblyDirectEval);
 }
 
@@ -2637,7 +2477,7 @@
     __ Push(callee->name());
     __ CallRuntime(Runtime::kLoadLookupSlotForCall);
     PushOperands(r2, r3);  // Function, receiver.
-    PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
+    PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
 
     // If fast case code has been generated, emit code to push the function
     // and receiver and have the slow path jump around this code.
@@ -2663,9 +2503,9 @@
 }
 
 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
-  // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
-  // to resolve the function we need to call.  Then we call the resolved
-  // function using the given arguments.
+  // In a call to eval, we first call
+  // Runtime_ResolvePossiblyDirectEval to resolve the function we need
+  // to call.  Then we call the resolved function using the given arguments.
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
 
@@ -2680,12 +2520,12 @@
   // resolve eval.
   __ LoadP(r3, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
   __ push(r3);
-  EmitResolvePossiblyDirectEval(arg_count);
+  EmitResolvePossiblyDirectEval(expr);
 
   // Touch up the stack with the resolved function.
   __ StoreP(r2, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
 
-  PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
 
   // Record source position for debugger.
   SetCallPosition(expr);
@@ -2696,8 +2536,7 @@
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
   RecordJSReturnSite(expr);
-  // Restore context register.
-  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->DropAndPlug(1, r2);
 }
 
@@ -2735,9 +2574,8 @@
   CallConstructStub stub(isolate());
   __ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
-  // Restore context register.
-  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
+  RestoreContext();
   context()->Plug(r2);
 }
 
@@ -2779,9 +2617,7 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-
-  // Restore context register.
-  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->Plug(r2);
 }
 
@@ -2979,68 +2815,6 @@
   context()->Plug(r2);
 }
 
-void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = r2;
-  Register index = r3;
-  Register value = r4;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-  PopOperands(index, value);
-
-  if (FLAG_debug_code) {
-    __ TestIfSmi(value);
-    __ Check(eq, kNonSmiValue, cr0);
-    __ TestIfSmi(index);
-    __ Check(eq, kNonSmiIndex, cr0);
-    __ SmiUntag(index);
-    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
-    __ SmiTag(index);
-  }
-
-  __ SmiUntag(value);
-  __ AddP(ip, string, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
-  __ SmiToByteArrayOffset(r1, index);
-  __ StoreByte(value, MemOperand(ip, r1));
-  context()->Plug(string);
-}
-
-void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = r2;
-  Register index = r3;
-  Register value = r4;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-  PopOperands(index, value);
-
-  if (FLAG_debug_code) {
-    __ TestIfSmi(value);
-    __ Check(eq, kNonSmiValue, cr0);
-    __ TestIfSmi(index);
-    __ Check(eq, kNonSmiIndex, cr0);
-    __ SmiUntag(index, index);
-    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
-    __ SmiTag(index, index);
-  }
-
-  __ SmiUntag(value);
-  __ SmiToShortArrayOffset(r1, index);
-  __ StoreHalfWord(value, MemOperand(r1, string, SeqTwoByteString::kHeaderSize -
-                                                     kHeapObjectTag));
-  context()->Plug(string);
-}
-
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
@@ -3074,8 +2848,7 @@
   Label index_out_of_range;
   Label done;
   StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
-                                      &need_conversion, &index_out_of_range,
-                                      STRING_INDEX_IS_NUMBER);
+                                      &need_conversion, &index_out_of_range);
   generator.GenerateFast(masm_);
   __ b(&done);
 
@@ -3098,47 +2871,6 @@
   context()->Plug(result);
 }
 
-void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK(args->length() == 2);
-  VisitForStackValue(args->at(0));
-  VisitForAccumulatorValue(args->at(1));
-
-  Register object = r3;
-  Register index = r2;
-  Register scratch = r5;
-  Register result = r2;
-
-  PopOperand(object);
-
-  Label need_conversion;
-  Label index_out_of_range;
-  Label done;
-  StringCharAtGenerator generator(object, index, scratch, result,
-                                  &need_conversion, &need_conversion,
-                                  &index_out_of_range, STRING_INDEX_IS_NUMBER);
-  generator.GenerateFast(masm_);
-  __ b(&done);
-
-  __ bind(&index_out_of_range);
-  // When the index is out of range, the spec requires us to return
-  // the empty string.
-  __ LoadRoot(result, Heap::kempty_stringRootIndex);
-  __ b(&done);
-
-  __ bind(&need_conversion);
-  // Move smi zero into the result register, which will trigger
-  // conversion.
-  __ LoadSmiLiteral(result, Smi::FromInt(0));
-  __ b(&done);
-
-  NopRuntimeCallHelper call_helper;
-  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
-
-  __ bind(&done);
-  context()->Plug(result);
-}
-
 void FullCodeGenerator::EmitCall(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK_LE(2, args->length());
@@ -3146,7 +2878,7 @@
   for (Expression* const arg : *args) {
     VisitForStackValue(arg);
   }
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   // Move target to r3.
   int const argc = args->length() - 2;
   __ LoadP(r3, MemOperand(sp, (argc + 1) * kPointerSize));
@@ -3154,8 +2886,7 @@
   __ mov(r2, Operand(argc));
   __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(argc + 1);
-  // Restore context register.
-  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   // Discard the function left on TOS.
   context()->DropAndPlug(1, r2);
 }
@@ -3202,12 +2933,6 @@
   context()->Plug(r2);
 }
 
-void FullCodeGenerator::EmitGetOrdinaryHasInstance(CallRuntime* expr) {
-  DCHECK_EQ(0, expr->arguments()->length());
-  __ LoadNativeContextSlot(Context::ORDINARY_HAS_INSTANCE_INDEX, r2);
-  context()->Plug(r2);
-}
-
 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
   DCHECK(expr->arguments()->length() == 0);
   ExternalReference debug_is_active =
@@ -3226,7 +2951,8 @@
 
   Label runtime, done;
 
-  __ Allocate(JSIteratorResult::kSize, r2, r4, r5, &runtime, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, r2, r4, r5, &runtime,
+              NO_ALLOCATION_FLAGS);
   __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, r3);
   __ Pop(r4, r5);
   __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
@@ -3265,9 +2991,7 @@
   __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-
-  // Restore context register.
-  __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
 }
 
 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
@@ -3346,12 +3070,14 @@
                         &materialize_true, &materialize_true);
         if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
         __ bind(&materialize_true);
-        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeTrueId(),
+                               BailoutState::NO_REGISTERS);
         __ LoadRoot(r2, Heap::kTrueValueRootIndex);
         if (context()->IsStackValue()) __ push(r2);
         __ b(&done);
         __ bind(&materialize_false);
-        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeFalseId(),
+                               BailoutState::NO_REGISTERS);
         __ LoadRoot(r2, Heap::kFalseValueRootIndex);
         if (context()->IsStackValue()) __ push(r2);
         __ bind(&done);
@@ -3450,9 +3176,9 @@
   // We need a second deoptimization point after loading the value
   // in case evaluating the property load my have a side effect.
   if (assign_type == VARIABLE) {
-    PrepareForBailout(expr->expression(), TOS_REG);
+    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
   } else {
-    PrepareForBailoutForId(prop->LoadId(), TOS_REG);
+    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
   }
 
   // Inline smi case if we are in a loop.
@@ -3502,9 +3228,8 @@
   }
 
   // Convert old value into a number.
-  ToNumberStub convert_stub(isolate());
-  __ CallStub(&convert_stub);
-  PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
+  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
+  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
 
   // Save result for postfix expressions.
   if (expr->is_postfix()) {
@@ -3551,7 +3276,8 @@
           EffectContext context(this);
           EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                  Token::ASSIGN, expr->CountSlot());
-          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+          PrepareForBailoutForId(expr->AssignmentId(),
+                                 BailoutState::TOS_REGISTER);
           context.Plug(r2);
         }
         // For all contexts except EffectConstant We have the result on
@@ -3562,7 +3288,8 @@
       } else {
         EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                Token::ASSIGN, expr->CountSlot());
-        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+        PrepareForBailoutForId(expr->AssignmentId(),
+                               BailoutState::TOS_REGISTER);
         context()->Plug(r2);
       }
       break;
@@ -3572,7 +3299,7 @@
       PopOperand(StoreDescriptor::ReceiverRegister());
       EmitLoadStoreICSlot(expr->CountSlot());
       CallStoreIC();
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         if (!context()->IsEffect()) {
           context()->PlugTOS();
@@ -3611,7 +3338,7 @@
           CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
       EmitLoadStoreICSlot(expr->CountSlot());
       CallIC(ic);
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         if (!context()->IsEffect()) {
           context()->PlugTOS();
@@ -3705,7 +3432,6 @@
 
 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
   Comment cmnt(masm_, "[ CompareOperation");
-  SetExpressionPosition(expr);
 
   // First we try a fast inlined version of the compare when one of
   // the operands is a literal.
@@ -3725,7 +3451,8 @@
   switch (op) {
     case Token::IN:
       VisitForStackValue(expr->right());
-      CallRuntimeWithOperands(Runtime::kHasProperty);
+      SetExpressionPosition(expr);
+      EmitHasProperty();
       PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
       __ CompareRoot(r2, Heap::kTrueValueRootIndex);
       Split(eq, if_true, if_false, fall_through);
@@ -3733,6 +3460,7 @@
 
     case Token::INSTANCEOF: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       PopOperand(r3);
       InstanceOfStub stub(isolate());
       __ CallStub(&stub);
@@ -3744,6 +3472,7 @@
 
     default: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       Condition cond = CompareIC::ComputeCondition(op);
       PopOperand(r3);
 
diff --git a/src/full-codegen/x64/full-codegen-x64.cc b/src/full-codegen/x64/full-codegen-x64.cc
index 992e7fe..eabb2f1 100644
--- a/src/full-codegen/x64/full-codegen-x64.cc
+++ b/src/full-codegen/x64/full-codegen-x64.cc
@@ -166,7 +166,8 @@
       __ Push(rdi);
       __ Push(info->scope()->GetScopeInfo(info->isolate()));
       __ CallRuntime(Runtime::kNewScriptContext);
-      PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
+      PrepareForBailoutForId(BailoutId::ScriptContext(),
+                             BailoutState::TOS_REGISTER);
       // The new target value is not used, clobbering is safe.
       DCHECK_NULL(info->scope()->new_target_var());
     } else {
@@ -222,7 +223,8 @@
   // Register holding this function and new target are both trashed in case we
   // bailout here. But since that can happen only when new target is not used
   // and we allocate a context, the value of |function_in_register| is correct.
-  PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionContext(),
+                         BailoutState::NO_REGISTERS);
 
   // Possibly set up a local binding to the this function which is used in
   // derived constructors with super calls.
@@ -286,7 +288,8 @@
 
   // Visit the declarations and body unless there is an illegal
   // redeclaration.
-  PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionEntry(),
+                         BailoutState::NO_REGISTERS);
   {
     Comment cmnt(masm_, "[ Declarations");
     VisitDeclarations(scope()->declarations());
@@ -299,7 +302,8 @@
 
   {
     Comment cmnt(masm_, "[ Stack check");
-    PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
+    PrepareForBailoutForId(BailoutId::Declarations(),
+                           BailoutState::NO_REGISTERS);
     Label ok;
     __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
     __ j(above_equal, &ok, Label::kNear);
@@ -372,11 +376,11 @@
   }
   __ bind(&ok);
 
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
   // Record a mapping of the OSR id to this PC.  This is used if the OSR
   // entry becomes the target of a bailout.  We don't expect it to be, but
   // we want it to work if it is.
-  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
 }
 
 void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
@@ -425,6 +429,9 @@
   }
 }
 
+void FullCodeGenerator::RestoreContext() {
+  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+}
 
 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
   DCHECK(var->IsStackAllocated() || var->IsContextSlot());
@@ -497,10 +504,12 @@
                                           true,
                                           true_label_,
                                           false_label_);
-  DCHECK(lit->IsNull() || lit->IsUndefined() || !lit->IsUndetectable());
-  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
+  DCHECK(lit->IsNull(isolate()) || lit->IsUndefined(isolate()) ||
+         !lit->IsUndetectable());
+  if (lit->IsUndefined(isolate()) || lit->IsNull(isolate()) ||
+      lit->IsFalse(isolate())) {
     if (false_label_ != fall_through_) __ jmp(false_label_);
-  } else if (lit->IsTrue() || lit->IsJSObject()) {
+  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
     if (true_label_ != fall_through_) __ jmp(true_label_);
   } else if (lit->IsString()) {
     if (String::cast(*lit)->length() == 0) {
@@ -689,7 +698,7 @@
 
   Label skip;
   if (should_normalize) __ jmp(&skip, Label::kNear);
-  PrepareForBailout(expr, TOS_REG);
+  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
   if (should_normalize) {
     __ CompareRoot(rax, Heap::kTrueValueRootIndex);
     Split(equal, if_true, if_false, NULL);
@@ -720,15 +729,13 @@
   VariableProxy* proxy = declaration->proxy();
   VariableMode mode = declaration->mode();
   Variable* variable = proxy->var();
-  bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
+  bool hole_init = mode == LET || mode == CONST;
   switch (variable->location()) {
     case VariableLocation::GLOBAL:
     case VariableLocation::UNALLOCATED:
+      DCHECK(!variable->binding_needs_init());
       globals_->Add(variable->name(), zone());
-      globals_->Add(variable->binding_needs_init()
-                        ? isolate()->factory()->the_hole_value()
-                    : isolate()->factory()->undefined_value(),
-                    zone());
+      globals_->Add(isolate()->factory()->undefined_value(), zone());
       break;
 
     case VariableLocation::PARAMETER:
@@ -747,26 +754,17 @@
         __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
         __ movp(ContextOperand(rsi, variable->index()), kScratchRegister);
         // No write barrier since the hole value is in old space.
-        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+        PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       }
       break;
 
     case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
+      DCHECK_EQ(VAR, mode);
+      DCHECK(!hole_init);
       __ Push(variable->name());
-      // Declaration nodes are always introduced in one of four modes.
-      DCHECK(IsDeclaredVariableMode(mode));
-      // Push initial value, if any.
-      // Note: For variables we must not push an initial value (such as
-      // 'undefined') because we may have a (legal) redeclaration and we
-      // must not destroy the current value.
-      if (hole_init) {
-        __ PushRoot(Heap::kTheHoleValueRootIndex);
-      } else {
-        __ Push(Smi::FromInt(0));  // Indicates no initial value.
-      }
-      __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes()));
-      __ CallRuntime(Runtime::kDeclareLookupSlot);
+      __ CallRuntime(Runtime::kDeclareEvalVar);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -811,7 +809,7 @@
                                 kDontSaveFPRegs,
                                 EMIT_REMEMBERED_SET,
                                 OMIT_SMI_CHECK);
-      PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
 
@@ -819,8 +817,8 @@
       Comment cmnt(masm_, "[ FunctionDeclaration");
       PushOperand(variable->name());
       VisitForStackValue(declaration->fun());
-      PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
-      CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
+      CallRuntimeWithOperands(Runtime::kDeclareEvalFunction);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -851,7 +849,7 @@
 
   // Keep the switch value on the stack until a case matches.
   VisitForStackValue(stmt->tag());
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
 
   ZoneList<CaseClause*>* clauses = stmt->cases();
   CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
@@ -901,7 +899,7 @@
 
     Label skip;
     __ jmp(&skip, Label::kNear);
-    PrepareForBailout(clause, TOS_REG);
+    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
     __ CompareRoot(rax, Heap::kTrueValueRootIndex);
     __ j(not_equal, &next_test);
     __ Drop(1);
@@ -929,12 +927,12 @@
     Comment cmnt(masm_, "[ Case body");
     CaseClause* clause = clauses->at(i);
     __ bind(clause->body_target());
-    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
+    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
     VisitStatements(clause->statements());
   }
 
   __ bind(nested_statement.break_label());
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
 }
 
 
@@ -967,15 +965,13 @@
   ToObjectStub stub(isolate());
   __ CallStub(&stub);
   __ bind(&done_convert);
-  PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
+  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
   __ Push(rax);
 
-  // Check cache validity in generated code. This is a fast case for
-  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
-  // guarantee cache validity, call the runtime system to check cache
-  // validity or get the property names in a fixed array.
-  // Note: Proxies never have an enum cache, so will always take the
-  // slow path.
+  // Check cache validity in generated code. If we cannot guarantee cache
+  // validity, call the runtime system to check cache validity or get the
+  // property names in a fixed array. Note: Proxies never have an enum cache,
+  // so will always take the slow path.
   Label call_runtime;
   __ CheckEnumCache(&call_runtime);
 
@@ -989,7 +985,7 @@
   __ bind(&call_runtime);
   __ Push(rax);  // Duplicate the enumerable object on the stack.
   __ CallRuntime(Runtime::kForInEnumerate);
-  PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
+  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
 
   // If we got a map from the runtime call, we can do a fast
   // modification check. Otherwise, we got a fixed array, and we have
@@ -1031,7 +1027,7 @@
   __ Push(rax);  // Array
   __ movp(rax, FieldOperand(rax, FixedArray::kLengthOffset));
   __ Push(rax);  // Fixed array length (as smi).
-  PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
   __ Push(Smi::FromInt(0));  // Initial index.
 
   // Generate code for doing the condition check.
@@ -1073,7 +1069,7 @@
   __ Push(rcx);  // Enumerable.
   __ Push(rbx);  // Current entry.
   __ CallRuntime(Runtime::kForInFilter);
-  PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
+  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
   __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
   __ j(equal, loop_statement.continue_label());
   __ movp(rbx, rax);
@@ -1085,11 +1081,11 @@
   // Perform the assignment as if via '='.
   { EffectContext context(this);
     EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
-    PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
+    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
   }
 
   // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
-  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
   // Generate code for the body of the loop.
   Visit(stmt->body());
 
@@ -1106,7 +1102,7 @@
   DropOperands(5);
 
   // Exit and decrement the loop depth.
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   __ bind(&exit);
   decrement_loop_depth();
 }
@@ -1237,16 +1233,11 @@
   } else if (var->mode() == DYNAMIC_LOCAL) {
     Variable* local = var->local_if_not_shadowed();
     __ movp(rax, ContextSlotOperandCheckExtensions(local, slow));
-    if (local->mode() == LET || local->mode() == CONST ||
-        local->mode() == CONST_LEGACY) {
+    if (local->mode() == LET || local->mode() == CONST) {
       __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
       __ j(not_equal, done);
-      if (local->mode() == CONST_LEGACY) {
-        __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
-      } else {  // LET || CONST
-        __ Push(var->name());
-        __ CallRuntime(Runtime::kThrowReferenceError);
-      }
+      __ Push(var->name());
+      __ CallRuntime(Runtime::kThrowReferenceError);
     }
     __ jmp(done);
   }
@@ -1255,14 +1246,14 @@
 
 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
                                                TypeofMode typeof_mode) {
+#ifdef DEBUG
   Variable* var = proxy->var();
   DCHECK(var->IsUnallocatedOrGlobalSlot() ||
          (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
-  __ Move(LoadDescriptor::NameRegister(), var->name());
-  __ LoadGlobalObject(LoadDescriptor::ReceiverRegister());
-  __ Move(LoadDescriptor::SlotRegister(),
+#endif
+  __ Move(LoadGlobalDescriptor::SlotRegister(),
           SmiFromSlot(proxy->VariableFeedbackSlot()));
-  CallLoadIC(typeof_mode);
+  CallLoadGlobalIC(typeof_mode);
 }
 
 
@@ -1270,7 +1261,7 @@
                                          TypeofMode typeof_mode) {
   // Record position before possible IC call.
   SetExpressionPosition(proxy);
-  PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
+  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
   Variable* var = proxy->var();
 
   // Three cases: global variables, lookup variables, and all other types of
@@ -1301,10 +1292,6 @@
           // binding in harmony mode.
           __ Push(var->name());
           __ CallRuntime(Runtime::kThrowReferenceError);
-        } else {
-          // Uninitialized legacy const bindings are unholed.
-          DCHECK(var->mode() == CONST_LEGACY);
-          __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
         }
         __ bind(&done);
         context()->Plug(rax);
@@ -1335,18 +1322,6 @@
 }
 
 
-void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
-  Comment cmnt(masm_, "[ RegExpLiteral");
-  __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
-  __ Move(rax, Smi::FromInt(expr->literal_index()));
-  __ Move(rcx, expr->pattern());
-  __ Move(rdx, Smi::FromInt(expr->flags()));
-  FastCloneRegExpStub stub(isolate());
-  __ CallStub(&stub);
-  context()->Plug(rax);
-}
-
-
 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
   Expression* expression = (property == NULL) ? NULL : property->value();
   if (expression == NULL) {
@@ -1382,8 +1357,9 @@
     __ Move(rdx, Smi::FromInt(flags));
     FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
     __ CallStub(&stub);
+    RestoreContext();
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   // If result_saved is true the result is on top of the stack.  If
   // result_saved is false the result is in rax.
@@ -1419,7 +1395,7 @@
             __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
             EmitLoadStoreICSlot(property->GetSlot(0));
             CallStoreIC();
-            PrepareForBailoutForId(key->id(), NO_REGISTERS);
+            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
 
             if (NeedsHomeObject(value)) {
               EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
@@ -1448,16 +1424,20 @@
         DCHECK(property->emit_store());
         CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
         PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                               NO_REGISTERS);
+                               BailoutState::NO_REGISTERS);
         break;
       case ObjectLiteral::Property::GETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->getter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->getter = property;
         }
         break;
       case ObjectLiteral::Property::SETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->setter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->setter = property;
         }
         break;
     }
@@ -1474,6 +1454,7 @@
     EmitAccessor(it->second->setter);
     PushOperand(Smi::FromInt(NONE));
     CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
+    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
   }
 
   // Object literals have two parts. The "static" part on the left contains no
@@ -1502,7 +1483,7 @@
       DCHECK(property->emit_store());
       CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
       PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                             NO_REGISTERS);
+                             BailoutState::NO_REGISTERS);
     } else {
       EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
       VisitForStackValue(value);
@@ -1518,6 +1499,8 @@
             PushOperand(Smi::FromInt(NONE));
             PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
             CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
+            PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
+                                   BailoutState::NO_REGISTERS);
           } else {
             DropOperands(3);
           }
@@ -1575,7 +1558,7 @@
     FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
     __ CallStub(&stub);
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   bool result_saved = false;  // Is the result saved to the stack?
   ZoneList<Expression*>* subexprs = expr->values();
@@ -1605,7 +1588,8 @@
         CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
     CallIC(ic);
 
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   // In case the array literal contains spread expressions it has two parts. The
@@ -1625,7 +1609,8 @@
     VisitForStackValue(subexpr);
     CallRuntimeWithOperands(Runtime::kAppendElement);
 
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   if (result_saved) {
@@ -1640,7 +1625,6 @@
   DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
 
   Comment cmnt(masm_, "[ Assignment");
-  SetExpressionPosition(expr, INSERT_BREAK);
 
   Property* property = expr->target()->AsProperty();
   LhsKind assign_type = Property::GetAssignType(property);
@@ -1704,23 +1688,27 @@
       switch (assign_type) {
         case VARIABLE:
           EmitVariableLoad(expr->target()->AsVariableProxy());
-          PrepareForBailout(expr->target(), TOS_REG);
+          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
           break;
         case NAMED_PROPERTY:
           EmitNamedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case NAMED_SUPER_PROPERTY:
           EmitNamedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_SUPER_PROPERTY:
           EmitKeyedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_PROPERTY:
           EmitKeyedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
       }
     }
@@ -1739,7 +1727,7 @@
       EmitBinaryOp(expr->binary_operation(), op);
     }
     // Deoptimization point in case the binary operation may have side effects.
-    PrepareForBailout(expr->binary_operation(), TOS_REG);
+    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
   } else {
     VisitForAccumulatorValue(expr->value());
   }
@@ -1751,7 +1739,7 @@
     case VARIABLE:
       EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
                              expr->op(), expr->AssignmentSlot());
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       context()->Plug(rax);
       break;
     case NAMED_PROPERTY:
@@ -1780,21 +1768,26 @@
   // this.  It stays on the stack while we update the iterator.
   VisitForStackValue(expr->expression());
 
-  Label suspend, continuation, post_runtime, resume;
+  Label suspend, continuation, post_runtime, resume, exception;
 
   __ jmp(&suspend);
   __ bind(&continuation);
-  // When we arrive here, the stack top is the resume mode and
-  // result_register() holds the input value (the argument given to the
-  // respective resume operation).
+  // When we arrive here, rax holds the generator object.
   __ RecordGeneratorContinuation();
-  __ Pop(rbx);
-  __ SmiCompare(rbx, Smi::FromInt(JSGeneratorObject::RETURN));
-  __ j(not_equal, &resume);
+  __ movp(rbx, FieldOperand(rax, JSGeneratorObject::kResumeModeOffset));
+  __ movp(rax, FieldOperand(rax, JSGeneratorObject::kInputOrDebugPosOffset));
+  STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
+  STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
+  __ SmiCompare(rbx, Smi::FromInt(JSGeneratorObject::kReturn));
+  __ j(less, &resume);
   __ Push(result_register());
+  __ j(greater, &exception);
   EmitCreateIteratorResult(true);
   EmitUnwindAndReturn();
 
+  __ bind(&exception);
+  __ CallRuntime(Runtime::kThrow);
+
   __ bind(&suspend);
   OperandStackDepthIncrement(1);  // Not popped on this path.
   VisitForAccumulatorValue(expr->generator_object());
@@ -1810,8 +1803,7 @@
   __ j(equal, &post_runtime);
   __ Push(rax);  // generator object
   __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
-  __ movp(context_register(),
-          Operand(rbp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   __ bind(&post_runtime);
 
   PopOperand(result_register());
@@ -1821,102 +1813,6 @@
   context()->Plug(result_register());
 }
 
-
-void FullCodeGenerator::EmitGeneratorResume(
-    Expression* generator, Expression* value,
-    JSGeneratorObject::ResumeMode resume_mode) {
-  // The value stays in rax, and is ultimately read by the resumed generator, as
-  // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it
-  // is read to throw the value when the resumed generator is already closed.
-  // rbx will hold the generator object until the activation has been resumed.
-  VisitForStackValue(generator);
-  VisitForAccumulatorValue(value);
-  PopOperand(rbx);
-
-  // Store input value into generator object.
-  __ movp(FieldOperand(rbx, JSGeneratorObject::kInputOffset),
-          result_register());
-  __ movp(rcx, result_register());
-  __ RecordWriteField(rbx, JSGeneratorObject::kInputOffset, rcx, rdx,
-                      kDontSaveFPRegs);
-
-  // Load suspended function and context.
-  __ movp(rsi, FieldOperand(rbx, JSGeneratorObject::kContextOffset));
-  __ movp(rdi, FieldOperand(rbx, JSGeneratorObject::kFunctionOffset));
-
-  // Push receiver.
-  __ Push(FieldOperand(rbx, JSGeneratorObject::kReceiverOffset));
-
-  // Push holes for arguments to generator function. Since the parser forced
-  // context allocation for any variables in generators, the actual argument
-  // values have already been copied into the context and these dummy values
-  // will never be used.
-  __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
-  __ LoadSharedFunctionInfoSpecialField(rdx, rdx,
-      SharedFunctionInfo::kFormalParameterCountOffset);
-  __ LoadRoot(rcx, Heap::kTheHoleValueRootIndex);
-  Label push_argument_holes, push_frame;
-  __ bind(&push_argument_holes);
-  __ subp(rdx, Immediate(1));
-  __ j(carry, &push_frame);
-  __ Push(rcx);
-  __ jmp(&push_argument_holes);
-
-  // Enter a new JavaScript frame, and initialize its slots as they were when
-  // the generator was suspended.
-  Label resume_frame, done;
-  __ bind(&push_frame);
-  __ call(&resume_frame);
-  __ jmp(&done);
-  __ bind(&resume_frame);
-  __ pushq(rbp);  // Caller's frame pointer.
-  __ movp(rbp, rsp);
-  __ Push(rsi);  // Callee's context.
-  __ Push(rdi);  // Callee's JS Function.
-
-  // Load the operand stack size.
-  __ movp(rdx, FieldOperand(rbx, JSGeneratorObject::kOperandStackOffset));
-  __ movp(rdx, FieldOperand(rdx, FixedArray::kLengthOffset));
-  __ SmiToInteger32(rdx, rdx);
-
-  // If we are sending a value and there is no operand stack, we can jump back
-  // in directly.
-  if (resume_mode == JSGeneratorObject::NEXT) {
-    Label slow_resume;
-    __ cmpp(rdx, Immediate(0));
-    __ j(not_zero, &slow_resume);
-    __ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
-    __ SmiToInteger64(rcx,
-        FieldOperand(rbx, JSGeneratorObject::kContinuationOffset));
-    __ addp(rdx, rcx);
-    __ Move(FieldOperand(rbx, JSGeneratorObject::kContinuationOffset),
-            Smi::FromInt(JSGeneratorObject::kGeneratorExecuting));
-    __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-    __ jmp(rdx);
-    __ bind(&slow_resume);
-  }
-
-  // Otherwise, we push holes for the operand stack and call the runtime to fix
-  // up the stack and the handlers.
-  Label push_operand_holes, call_resume;
-  __ bind(&push_operand_holes);
-  __ subp(rdx, Immediate(1));
-  __ j(carry, &call_resume);
-  __ Push(rcx);
-  __ jmp(&push_operand_holes);
-  __ bind(&call_resume);
-  __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-  __ Push(rbx);
-  __ Push(result_register());
-  __ Push(Smi::FromInt(resume_mode));
-  __ CallRuntime(Runtime::kResumeJSGeneratorObject);
-  // Not reached: the runtime call returns elsewhere.
-  __ Abort(kGeneratorFailedToResume);
-
-  __ bind(&done);
-  context()->Plug(result_register());
-}
-
 void FullCodeGenerator::PushOperand(MemOperand operand) {
   OperandStackDepthIncrement(1);
   __ Push(operand);
@@ -1936,7 +1832,8 @@
 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
   Label allocate, done_allocate;
 
-  __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &allocate, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &allocate,
+              NO_ALLOCATION_FLAGS);
   __ jmp(&done_allocate, Label::kNear);
 
   __ bind(&allocate);
@@ -2222,8 +2119,7 @@
     __ bind(&uninitialized_this);
     EmitStoreToStackLocalOrContextSlot(var, location);
 
-  } else if (!var->is_const_mode() ||
-             (var->mode() == CONST && op == Token::INIT)) {
+  } else if (!var->is_const_mode() || op == Token::INIT) {
     if (var->IsLookupSlot()) {
       // Assignment to var.
       __ Push(var->name());
@@ -2245,25 +2141,6 @@
       EmitStoreToStackLocalOrContextSlot(var, location);
     }
 
-  } else if (var->mode() == CONST_LEGACY && op == Token::INIT) {
-    // Const initializers need a write barrier.
-    DCHECK(!var->IsParameter());  // No const parameters.
-    if (var->IsLookupSlot()) {
-      __ Push(rax);
-      __ Push(rsi);
-      __ Push(var->name());
-      __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot);
-    } else {
-      DCHECK(var->IsStackLocal() || var->IsContextSlot());
-      Label skip;
-      MemOperand location = VarOperand(var, rcx);
-      __ movp(rdx, location);
-      __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
-      __ j(not_equal, &skip);
-      EmitStoreToStackLocalOrContextSlot(var, location);
-      __ bind(&skip);
-    }
-
   } else {
     DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT);
     if (is_strict(language_mode())) {
@@ -2285,7 +2162,7 @@
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallStoreIC();
 
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(rax);
 }
 
@@ -2329,45 +2206,7 @@
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallIC(ic);
 
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
-  context()->Plug(rax);
-}
-
-
-void FullCodeGenerator::VisitProperty(Property* expr) {
-  Comment cmnt(masm_, "[ Property");
-  SetExpressionPosition(expr);
-
-  Expression* key = expr->key();
-
-  if (key->IsPropertyName()) {
-    if (!expr->IsSuperAccess()) {
-      VisitForAccumulatorValue(expr->obj());
-      DCHECK(!rax.is(LoadDescriptor::ReceiverRegister()));
-      __ movp(LoadDescriptor::ReceiverRegister(), rax);
-      EmitNamedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      EmitNamedSuperPropertyLoad(expr);
-    }
-  } else {
-    if (!expr->IsSuperAccess()) {
-      VisitForStackValue(expr->obj());
-      VisitForAccumulatorValue(expr->key());
-      __ Move(LoadDescriptor::NameRegister(), rax);
-      PopOperand(LoadDescriptor::ReceiverRegister());
-      EmitKeyedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      VisitForStackValue(expr->key());
-      EmitKeyedSuperPropertyLoad(expr);
-    }
-  }
-  PrepareForBailoutForId(expr->LoadId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(rax);
 }
 
@@ -2388,7 +2227,7 @@
   if (callee->IsVariableProxy()) {
     { StackValueContext context(this);
       EmitVariableLoad(callee->AsVariableProxy());
-      PrepareForBailout(callee, NO_REGISTERS);
+      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
     }
     // Push undefined as receiver. This is patched in the Call builtin if it
     // is a sloppy mode method.
@@ -2400,7 +2239,8 @@
     DCHECK(!callee->AsProperty()->IsSuperAccess());
     __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
     EmitNamedPropertyLoad(callee->AsProperty());
-    PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                           BailoutState::TOS_REGISTER);
     // Push the target function under the receiver.
     PushOperand(Operand(rsp, 0));
     __ movp(Operand(rsp, kPointerSize), rax);
@@ -2436,6 +2276,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ movp(Operand(rsp, kPointerSize), rax);
@@ -2460,7 +2301,8 @@
   __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
   __ Move(LoadDescriptor::NameRegister(), rax);
   EmitKeyedPropertyLoad(callee->AsProperty());
-  PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                         BailoutState::TOS_REGISTER);
 
   // Push the target function under the receiver.
   PushOperand(Operand(rsp, 0));
@@ -2493,6 +2335,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ movp(Operand(rsp, kPointerSize), rax);
@@ -2512,7 +2355,7 @@
     VisitForStackValue(args->at(i));
   }
 
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   SetCallPosition(expr, expr->tail_call_mode());
   if (expr->tail_call_mode() == TailCallMode::kAllow) {
     if (FLAG_trace) {
@@ -2533,15 +2376,13 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-
-  // Restore context register.
-  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   // Discard the function left on TOS.
   context()->DropAndPlug(1, rax);
 }
 
-
-void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
+void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
+  int arg_count = expr->arguments()->length();
   // Push copy of the first argument or undefined if it doesn't exist.
   if (arg_count > 0) {
     __ Push(Operand(rsp, arg_count * kPointerSize));
@@ -2558,6 +2399,9 @@
   // Push the start position of the scope the calls resides in.
   __ Push(Smi::FromInt(scope()->start_position()));
 
+  // Push the source position of the eval call.
+  __ Push(Smi::FromInt(expr->position()));
+
   // Do the runtime call.
   __ CallRuntime(Runtime::kResolvePossiblyDirectEval);
 }
@@ -2579,7 +2423,7 @@
     __ CallRuntime(Runtime::kLoadLookupSlotForCall);
     PushOperand(rax);  // Function.
     PushOperand(rdx);  // Receiver.
-    PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
+    PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
 
     // If fast case code has been generated, emit code to push the function
     // and receiver and have the slow path jump around this code.
@@ -2605,7 +2449,7 @@
 
 
 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
-  // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
+  // In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
   // to resolve the function we need to call.  Then we call the resolved
   // function using the given arguments.
   ZoneList<Expression*>* args = expr->arguments();
@@ -2620,12 +2464,12 @@
   // Push a copy of the function (found below the arguments) and resolve
   // eval.
   __ Push(Operand(rsp, (arg_count + 1) * kPointerSize));
-  EmitResolvePossiblyDirectEval(arg_count);
+  EmitResolvePossiblyDirectEval(expr);
 
   // Touch up the callee.
   __ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
 
-  PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
 
   SetCallPosition(expr);
   __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
@@ -2635,8 +2479,7 @@
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
   RecordJSReturnSite(expr);
-  // Restore context register.
-  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->DropAndPlug(1, rax);
 }
 
@@ -2675,9 +2518,8 @@
   CallConstructStub stub(isolate());
   __ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
-  // Restore context register.
-  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
+  RestoreContext();
   context()->Plug(rax);
 }
 
@@ -2718,10 +2560,7 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-
-  // Restore context register.
-  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
-
+  RestoreContext();
   context()->Plug(rax);
 }
 
@@ -2927,72 +2766,6 @@
 }
 
 
-void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = rax;
-  Register index = rbx;
-  Register value = rcx;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-  PopOperand(value);
-  PopOperand(index);
-
-  if (FLAG_debug_code) {
-    __ Check(__ CheckSmi(value), kNonSmiValue);
-    __ Check(__ CheckSmi(index), kNonSmiValue);
-  }
-
-  __ SmiToInteger32(value, value);
-  __ SmiToInteger32(index, index);
-
-  if (FLAG_debug_code) {
-    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
-  }
-
-  __ movb(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize),
-          value);
-  context()->Plug(string);
-}
-
-
-void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = rax;
-  Register index = rbx;
-  Register value = rcx;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-  PopOperand(value);
-  PopOperand(index);
-
-  if (FLAG_debug_code) {
-    __ Check(__ CheckSmi(value), kNonSmiValue);
-    __ Check(__ CheckSmi(index), kNonSmiValue);
-  }
-
-  __ SmiToInteger32(value, value);
-  __ SmiToInteger32(index, index);
-
-  if (FLAG_debug_code) {
-    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
-  }
-
-  __ movw(FieldOperand(string, index, times_2, SeqTwoByteString::kHeaderSize),
-          value);
-  context()->Plug(rax);
-}
-
-
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
@@ -3028,13 +2801,8 @@
   Label need_conversion;
   Label index_out_of_range;
   Label done;
-  StringCharCodeAtGenerator generator(object,
-                                      index,
-                                      result,
-                                      &need_conversion,
-                                      &need_conversion,
-                                      &index_out_of_range,
-                                      STRING_INDEX_IS_NUMBER);
+  StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
+                                      &need_conversion, &index_out_of_range);
   generator.GenerateFast(masm_);
   __ jmp(&done);
 
@@ -3058,54 +2826,6 @@
 }
 
 
-void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK(args->length() == 2);
-
-  VisitForStackValue(args->at(0));
-  VisitForAccumulatorValue(args->at(1));
-
-  Register object = rbx;
-  Register index = rax;
-  Register scratch = rdx;
-  Register result = rax;
-
-  PopOperand(object);
-
-  Label need_conversion;
-  Label index_out_of_range;
-  Label done;
-  StringCharAtGenerator generator(object,
-                                  index,
-                                  scratch,
-                                  result,
-                                  &need_conversion,
-                                  &need_conversion,
-                                  &index_out_of_range,
-                                  STRING_INDEX_IS_NUMBER);
-  generator.GenerateFast(masm_);
-  __ jmp(&done);
-
-  __ bind(&index_out_of_range);
-  // When the index is out of range, the spec requires us to return
-  // the empty string.
-  __ LoadRoot(result, Heap::kempty_stringRootIndex);
-  __ jmp(&done);
-
-  __ bind(&need_conversion);
-  // Move smi zero into the result register, which will trigger
-  // conversion.
-  __ Move(result, Smi::FromInt(0));
-  __ jmp(&done);
-
-  NopRuntimeCallHelper call_helper;
-  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
-
-  __ bind(&done);
-  context()->Plug(result);
-}
-
-
 void FullCodeGenerator::EmitCall(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK_LE(2, args->length());
@@ -3113,7 +2833,7 @@
   for (Expression* const arg : *args) {
     VisitForStackValue(arg);
   }
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   // Move target to rdi.
   int const argc = args->length() - 2;
   __ movp(rdi, Operand(rsp, (argc + 1) * kPointerSize));
@@ -3121,8 +2841,7 @@
   __ Set(rax, argc);
   __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(argc + 1);
-  // Restore context register.
-  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   // Discard the function left on TOS.
   context()->DropAndPlug(1, rax);
 }
@@ -3176,12 +2895,6 @@
   context()->Plug(rax);
 }
 
-void FullCodeGenerator::EmitGetOrdinaryHasInstance(CallRuntime* expr) {
-  DCHECK_EQ(0, expr->arguments()->length());
-  __ LoadNativeContextSlot(Context::ORDINARY_HAS_INSTANCE_INDEX, rax);
-  context()->Plug(rax);
-}
-
 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
   DCHECK(expr->arguments()->length() == 0);
   ExternalReference debug_is_active =
@@ -3201,7 +2914,8 @@
 
   Label runtime, done;
 
-  __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &runtime, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &runtime,
+              NO_ALLOCATION_FLAGS);
   __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, rbx);
   __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx);
   __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex);
@@ -3241,9 +2955,7 @@
   __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-
-  // Restore context register.
-  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
 }
 
 
@@ -3328,7 +3040,8 @@
                         &materialize_true);
         if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
         __ bind(&materialize_true);
-        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeTrueId(),
+                               BailoutState::NO_REGISTERS);
         if (context()->IsAccumulatorValue()) {
           __ LoadRoot(rax, Heap::kTrueValueRootIndex);
         } else {
@@ -3336,7 +3049,8 @@
         }
         __ jmp(&done, Label::kNear);
         __ bind(&materialize_false);
-        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeFalseId(),
+                               BailoutState::NO_REGISTERS);
         if (context()->IsAccumulatorValue()) {
           __ LoadRoot(rax, Heap::kFalseValueRootIndex);
         } else {
@@ -3435,9 +3149,9 @@
   // We need a second deoptimization point after loading the value
   // in case evaluating the property load my have a side effect.
   if (assign_type == VARIABLE) {
-    PrepareForBailout(expr->expression(), TOS_REG);
+    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
   } else {
-    PrepareForBailoutForId(prop->LoadId(), TOS_REG);
+    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
   }
 
   // Inline smi case if we are in a loop.
@@ -3488,9 +3202,8 @@
   }
 
   // Convert old value into a number.
-  ToNumberStub convert_stub(isolate());
-  __ CallStub(&convert_stub);
-  PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
+  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
+  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
 
   // Save result for postfix expressions.
   if (expr->is_postfix()) {
@@ -3538,7 +3251,8 @@
         { EffectContext context(this);
           EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                  Token::ASSIGN, expr->CountSlot());
-          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+          PrepareForBailoutForId(expr->AssignmentId(),
+                                 BailoutState::TOS_REGISTER);
           context.Plug(rax);
         }
         // For all contexts except kEffect: We have the result on
@@ -3550,7 +3264,8 @@
         // Perform the assignment as if via '='.
         EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                Token::ASSIGN, expr->CountSlot());
-        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+        PrepareForBailoutForId(expr->AssignmentId(),
+                               BailoutState::TOS_REGISTER);
         context()->Plug(rax);
       }
       break;
@@ -3560,7 +3275,7 @@
       PopOperand(StoreDescriptor::ReceiverRegister());
       EmitLoadStoreICSlot(expr->CountSlot());
       CallStoreIC();
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         if (!context()->IsEffect()) {
           context()->PlugTOS();
@@ -3599,7 +3314,7 @@
           CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
       EmitLoadStoreICSlot(expr->CountSlot());
       CallIC(ic);
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         if (!context()->IsEffect()) {
           context()->PlugTOS();
@@ -3695,7 +3410,6 @@
 
 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
   Comment cmnt(masm_, "[ CompareOperation");
-  SetExpressionPosition(expr);
 
   // First we try a fast inlined version of the compare when one of
   // the operands is a literal.
@@ -3715,7 +3429,8 @@
   switch (op) {
     case Token::IN:
       VisitForStackValue(expr->right());
-      CallRuntimeWithOperands(Runtime::kHasProperty);
+      SetExpressionPosition(expr);
+      EmitHasProperty();
       PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
       __ CompareRoot(rax, Heap::kTrueValueRootIndex);
       Split(equal, if_true, if_false, fall_through);
@@ -3723,6 +3438,7 @@
 
     case Token::INSTANCEOF: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       PopOperand(rdx);
       InstanceOfStub stub(isolate());
       __ CallStub(&stub);
@@ -3734,6 +3450,7 @@
 
     default: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       Condition cc = CompareIC::ComputeCondition(op);
       PopOperand(rdx);
 
diff --git a/src/full-codegen/x87/full-codegen-x87.cc b/src/full-codegen/x87/full-codegen-x87.cc
index f14aaf6..2fb9961 100644
--- a/src/full-codegen/x87/full-codegen-x87.cc
+++ b/src/full-codegen/x87/full-codegen-x87.cc
@@ -168,7 +168,8 @@
       __ push(edi);
       __ Push(info->scope()->GetScopeInfo(info->isolate()));
       __ CallRuntime(Runtime::kNewScriptContext);
-      PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
+      PrepareForBailoutForId(BailoutId::ScriptContext(),
+                             BailoutState::TOS_REGISTER);
       // The new target value is not used, clobbering is safe.
       DCHECK_NULL(info->scope()->new_target_var());
     } else {
@@ -224,7 +225,8 @@
   // Register holding this function and new target are both trashed in case we
   // bailout here. But since that can happen only when new target is not used
   // and we allocate a context, the value of |function_in_register| is correct.
-  PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionContext(),
+                         BailoutState::NO_REGISTERS);
 
   // Possibly set up a local binding to the this function which is used in
   // derived constructors with super calls.
@@ -286,7 +288,8 @@
   }
 
   // Visit the declarations and body.
-  PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
+  PrepareForBailoutForId(BailoutId::FunctionEntry(),
+                         BailoutState::NO_REGISTERS);
   {
     Comment cmnt(masm_, "[ Declarations");
     VisitDeclarations(scope()->declarations());
@@ -299,7 +302,8 @@
 
   {
     Comment cmnt(masm_, "[ Stack check");
-    PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
+    PrepareForBailoutForId(BailoutId::Declarations(),
+                           BailoutState::NO_REGISTERS);
     Label ok;
     ExternalReference stack_limit =
         ExternalReference::address_of_stack_limit(isolate());
@@ -366,11 +370,11 @@
   EmitProfilingCounterReset();
 
   __ bind(&ok);
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
   // Record a mapping of the OSR id to this PC.  This is used if the OSR
   // entry becomes the target of a bailout.  We don't expect it to be, but
   // we want it to work if it is.
-  PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
 }
 
 void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
@@ -420,6 +424,9 @@
   }
 }
 
+void FullCodeGenerator::RestoreContext() {
+  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+}
 
 void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
   DCHECK(var->IsStackAllocated() || var->IsContextSlot());
@@ -480,10 +487,12 @@
                                           true,
                                           true_label_,
                                           false_label_);
-  DCHECK(lit->IsNull() || lit->IsUndefined() || !lit->IsUndetectable());
-  if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
+  DCHECK(lit->IsNull(isolate()) || lit->IsUndefined(isolate()) ||
+         !lit->IsUndetectable());
+  if (lit->IsUndefined(isolate()) || lit->IsNull(isolate()) ||
+      lit->IsFalse(isolate())) {
     if (false_label_ != fall_through_) __ jmp(false_label_);
-  } else if (lit->IsTrue() || lit->IsJSObject()) {
+  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
     if (true_label_ != fall_through_) __ jmp(true_label_);
   } else if (lit->IsString()) {
     if (String::cast(*lit)->length() == 0) {
@@ -674,7 +683,7 @@
 
   Label skip;
   if (should_normalize) __ jmp(&skip, Label::kNear);
-  PrepareForBailout(expr, TOS_REG);
+  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
   if (should_normalize) {
     __ cmp(eax, isolate()->factory()->true_value());
     Split(equal, if_true, if_false, NULL);
@@ -705,14 +714,13 @@
   VariableProxy* proxy = declaration->proxy();
   VariableMode mode = declaration->mode();
   Variable* variable = proxy->var();
-  bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
+  bool hole_init = mode == LET || mode == CONST;
   switch (variable->location()) {
     case VariableLocation::GLOBAL:
     case VariableLocation::UNALLOCATED:
+      DCHECK(!variable->binding_needs_init());
       globals_->Add(variable->name(), zone());
-      globals_->Add(variable->binding_needs_init()
-                        ? isolate()->factory()->the_hole_value()
-                        : isolate()->factory()->undefined_value(), zone());
+      globals_->Add(isolate()->factory()->undefined_value(), zone());
       break;
 
     case VariableLocation::PARAMETER:
@@ -731,27 +739,17 @@
         __ mov(ContextOperand(esi, variable->index()),
                Immediate(isolate()->factory()->the_hole_value()));
         // No write barrier since the hole value is in old space.
-        PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+        PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       }
       break;
 
     case VariableLocation::LOOKUP: {
       Comment cmnt(masm_, "[ VariableDeclaration");
+      DCHECK_EQ(VAR, mode);
+      DCHECK(!hole_init);
       __ push(Immediate(variable->name()));
-      // VariableDeclaration nodes are always introduced in one of four modes.
-      DCHECK(IsDeclaredVariableMode(mode));
-      // Push initial value, if any.
-      // Note: For variables we must not push an initial value (such as
-      // 'undefined') because we may have a (legal) redeclaration and we
-      // must not destroy the current value.
-      if (hole_init) {
-        __ push(Immediate(isolate()->factory()->the_hole_value()));
-      } else {
-        __ push(Immediate(Smi::FromInt(0)));  // Indicates no initial value.
-      }
-      __ push(
-          Immediate(Smi::FromInt(variable->DeclarationPropertyAttributes())));
-      __ CallRuntime(Runtime::kDeclareLookupSlot);
+      __ CallRuntime(Runtime::kDeclareEvalVar);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -790,7 +788,7 @@
       __ RecordWriteContextSlot(esi, Context::SlotOffset(variable->index()),
                                 result_register(), ecx, kDontSaveFPRegs,
                                 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
-      PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
 
@@ -798,8 +796,8 @@
       Comment cmnt(masm_, "[ FunctionDeclaration");
       PushOperand(variable->name());
       VisitForStackValue(declaration->fun());
-      PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
-      CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
+      CallRuntimeWithOperands(Runtime::kDeclareEvalFunction);
+      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
       break;
     }
   }
@@ -830,7 +828,7 @@
 
   // Keep the switch value on the stack until a case matches.
   VisitForStackValue(stmt->tag());
-  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
 
   ZoneList<CaseClause*>* clauses = stmt->cases();
   CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
@@ -879,7 +877,7 @@
 
     Label skip;
     __ jmp(&skip, Label::kNear);
-    PrepareForBailout(clause, TOS_REG);
+    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
     __ cmp(eax, isolate()->factory()->true_value());
     __ j(not_equal, &next_test);
     __ Drop(1);
@@ -907,12 +905,12 @@
     Comment cmnt(masm_, "[ Case body");
     CaseClause* clause = clauses->at(i);
     __ bind(clause->body_target());
-    PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
+    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
     VisitStatements(clause->statements());
   }
 
   __ bind(nested_statement.break_label());
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
 }
 
 
@@ -945,15 +943,13 @@
   ToObjectStub stub(isolate());
   __ CallStub(&stub);
   __ bind(&done_convert);
-  PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
+  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
   __ push(eax);
 
-  // Check cache validity in generated code. This is a fast case for
-  // the JSObject::IsSimpleEnum cache validity checks. If we cannot
-  // guarantee cache validity, call the runtime system to check cache
-  // validity or get the property names in a fixed array.
-  // Note: Proxies never have an enum cache, so will always take the
-  // slow path.
+  // Check cache validity in generated code. If we cannot guarantee cache
+  // validity, call the runtime system to check cache validity or get the
+  // property names in a fixed array. Note: Proxies never have an enum cache,
+  // so will always take the slow path.
   Label call_runtime, use_cache, fixed_array;
   __ CheckEnumCache(&call_runtime);
 
@@ -964,7 +960,7 @@
   __ bind(&call_runtime);
   __ push(eax);
   __ CallRuntime(Runtime::kForInEnumerate);
-  PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
+  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
   __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
          isolate()->factory()->meta_map());
   __ j(not_equal, &fixed_array);
@@ -996,11 +992,11 @@
   // We got a fixed array in register eax. Iterate through that.
   __ bind(&fixed_array);
 
-  __ push(Immediate(Smi::FromInt(1)));  // Smi(1) undicates slow check
+  __ push(Immediate(Smi::FromInt(1)));  // Smi(1) indicates slow check
   __ push(eax);  // Array
   __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
   __ push(eax);  // Fixed array length (as smi).
-  PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
   __ push(Immediate(Smi::FromInt(0)));  // Initial index.
 
   // Generate code for doing the condition check.
@@ -1038,7 +1034,7 @@
   __ push(ecx);  // Enumerable.
   __ push(ebx);  // Current entry.
   __ CallRuntime(Runtime::kForInFilter);
-  PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
+  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
   __ cmp(eax, isolate()->factory()->undefined_value());
   __ j(equal, loop_statement.continue_label());
   __ mov(ebx, eax);
@@ -1050,11 +1046,11 @@
   // Perform the assignment as if via '='.
   { EffectContext context(this);
     EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
-    PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
+    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
   }
 
   // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
-  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
   // Generate code for the body of the loop.
   Visit(stmt->body());
 
@@ -1071,7 +1067,7 @@
   DropOperands(5);
 
   // Exit and decrement the loop depth.
-  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   __ bind(&exit);
   decrement_loop_depth();
 }
@@ -1199,16 +1195,11 @@
   } else if (var->mode() == DYNAMIC_LOCAL) {
     Variable* local = var->local_if_not_shadowed();
     __ mov(eax, ContextSlotOperandCheckExtensions(local, slow));
-    if (local->mode() == LET || local->mode() == CONST ||
-        local->mode() == CONST_LEGACY) {
+    if (local->mode() == LET || local->mode() == CONST) {
       __ cmp(eax, isolate()->factory()->the_hole_value());
       __ j(not_equal, done);
-      if (local->mode() == CONST_LEGACY) {
-        __ mov(eax, isolate()->factory()->undefined_value());
-      } else {  // LET || CONST
-        __ push(Immediate(var->name()));
-        __ CallRuntime(Runtime::kThrowReferenceError);
-      }
+      __ push(Immediate(var->name()));
+      __ CallRuntime(Runtime::kThrowReferenceError);
     }
     __ jmp(done);
   }
@@ -1217,24 +1208,21 @@
 
 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
                                                TypeofMode typeof_mode) {
+#ifdef DEBUG
   Variable* var = proxy->var();
   DCHECK(var->IsUnallocatedOrGlobalSlot() ||
          (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
-  __ mov(LoadDescriptor::ReceiverRegister(), NativeContextOperand());
-  __ mov(LoadDescriptor::ReceiverRegister(),
-         ContextOperand(LoadDescriptor::ReceiverRegister(),
-                        Context::EXTENSION_INDEX));
-  __ mov(LoadDescriptor::NameRegister(), var->name());
-  __ mov(LoadDescriptor::SlotRegister(),
+#endif
+  __ mov(LoadGlobalDescriptor::SlotRegister(),
          Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
-  CallLoadIC(typeof_mode);
+  CallLoadGlobalIC(typeof_mode);
 }
 
 
 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
                                          TypeofMode typeof_mode) {
   SetExpressionPosition(proxy);
-  PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
+  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
   Variable* var = proxy->var();
 
   // Three cases: global variables, lookup variables, and all other types of
@@ -1266,10 +1254,6 @@
           // binding in harmony mode.
           __ push(Immediate(var->name()));
           __ CallRuntime(Runtime::kThrowReferenceError);
-        } else {
-          // Uninitialized legacy const bindings are unholed.
-          DCHECK(var->mode() == CONST_LEGACY);
-          __ mov(eax, isolate()->factory()->undefined_value());
         }
         __ bind(&done);
         context()->Plug(eax);
@@ -1300,18 +1284,6 @@
 }
 
 
-void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
-  Comment cmnt(masm_, "[ RegExpLiteral");
-  __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
-  __ Move(eax, Immediate(Smi::FromInt(expr->literal_index())));
-  __ Move(ecx, Immediate(expr->pattern()));
-  __ Move(edx, Immediate(Smi::FromInt(expr->flags())));
-  FastCloneRegExpStub stub(isolate());
-  __ CallStub(&stub);
-  context()->Plug(eax);
-}
-
-
 void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
   Expression* expression = (property == NULL) ? NULL : property->value();
   if (expression == NULL) {
@@ -1348,8 +1320,9 @@
     __ mov(edx, Immediate(Smi::FromInt(flags)));
     FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
     __ CallStub(&stub);
+    RestoreContext();
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   // If result_saved is true the result is on top of the stack.  If
   // result_saved is false the result is in eax.
@@ -1385,7 +1358,7 @@
             __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
             EmitLoadStoreICSlot(property->GetSlot(0));
             CallStoreIC();
-            PrepareForBailoutForId(key->id(), NO_REGISTERS);
+            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
             if (NeedsHomeObject(value)) {
               EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
             }
@@ -1413,16 +1386,20 @@
         DCHECK(property->emit_store());
         CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
         PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                               NO_REGISTERS);
+                               BailoutState::NO_REGISTERS);
         break;
       case ObjectLiteral::Property::GETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->getter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->getter = property;
         }
         break;
       case ObjectLiteral::Property::SETTER:
         if (property->emit_store()) {
-          accessor_table.lookup(key)->second->setter = property;
+          AccessorTable::Iterator it = accessor_table.lookup(key);
+          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
+          it->second->setter = property;
         }
         break;
     }
@@ -1441,6 +1418,7 @@
 
     PushOperand(Smi::FromInt(NONE));
     CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
+    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
   }
 
   // Object literals have two parts. The "static" part on the left contains no
@@ -1469,7 +1447,7 @@
       DCHECK(property->emit_store());
       CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
       PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
-                             NO_REGISTERS);
+                             BailoutState::NO_REGISTERS);
     } else {
       EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
       VisitForStackValue(value);
@@ -1485,6 +1463,8 @@
             PushOperand(Smi::FromInt(NONE));
             PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
             CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
+            PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
+                                   BailoutState::NO_REGISTERS);
           } else {
             DropOperands(3);
           }
@@ -1542,7 +1522,7 @@
     FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
     __ CallStub(&stub);
   }
-  PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
+  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
 
   bool result_saved = false;  // Is the result saved to the stack?
   ZoneList<Expression*>* subexprs = expr->values();
@@ -1572,7 +1552,8 @@
     Handle<Code> ic =
         CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
     CallIC(ic);
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   // In case the array literal contains spread expressions it has two parts. The
@@ -1592,7 +1573,8 @@
     VisitForStackValue(subexpr);
     CallRuntimeWithOperands(Runtime::kAppendElement);
 
-    PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
+    PrepareForBailoutForId(expr->GetIdForElement(array_index),
+                           BailoutState::NO_REGISTERS);
   }
 
   if (result_saved) {
@@ -1607,7 +1589,6 @@
   DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
 
   Comment cmnt(masm_, "[ Assignment");
-  SetExpressionPosition(expr, INSERT_BREAK);
 
   Property* property = expr->target()->AsProperty();
   LhsKind assign_type = Property::GetAssignType(property);
@@ -1672,23 +1653,27 @@
       switch (assign_type) {
         case VARIABLE:
           EmitVariableLoad(expr->target()->AsVariableProxy());
-          PrepareForBailout(expr->target(), TOS_REG);
+          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
           break;
         case NAMED_SUPER_PROPERTY:
           EmitNamedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case NAMED_PROPERTY:
           EmitNamedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_SUPER_PROPERTY:
           EmitKeyedSuperPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
         case KEYED_PROPERTY:
           EmitKeyedPropertyLoad(property);
-          PrepareForBailoutForId(property->LoadId(), TOS_REG);
+          PrepareForBailoutForId(property->LoadId(),
+                                 BailoutState::TOS_REGISTER);
           break;
       }
     }
@@ -1707,7 +1692,7 @@
     }
 
     // Deoptimization point in case the binary operation may have side effects.
-    PrepareForBailout(expr->binary_operation(), TOS_REG);
+    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
   } else {
     VisitForAccumulatorValue(expr->value());
   }
@@ -1719,7 +1704,7 @@
     case VARIABLE:
       EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
                              expr->op(), expr->AssignmentSlot());
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       context()->Plug(eax);
       break;
     case NAMED_PROPERTY:
@@ -1748,21 +1733,26 @@
   // this.  It stays on the stack while we update the iterator.
   VisitForStackValue(expr->expression());
 
-  Label suspend, continuation, post_runtime, resume;
+  Label suspend, continuation, post_runtime, resume, exception;
 
   __ jmp(&suspend);
   __ bind(&continuation);
-  // When we arrive here, the stack top is the resume mode and
-  // result_register() holds the input value (the argument given to the
-  // respective resume operation).
+  // When we arrive here, eax holds the generator object.
   __ RecordGeneratorContinuation();
-  __ pop(ebx);
-  __ cmp(ebx, Immediate(Smi::FromInt(JSGeneratorObject::RETURN)));
-  __ j(not_equal, &resume);
-  __ push(result_register());
+  __ mov(ebx, FieldOperand(eax, JSGeneratorObject::kResumeModeOffset));
+  __ mov(eax, FieldOperand(eax, JSGeneratorObject::kInputOrDebugPosOffset));
+  STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn);
+  STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn);
+  __ cmp(ebx, Immediate(Smi::FromInt(JSGeneratorObject::kReturn)));
+  __ j(less, &resume);
+  __ Push(result_register());
+  __ j(greater, &exception);
   EmitCreateIteratorResult(true);
   EmitUnwindAndReturn();
 
+  __ bind(&exception);
+  __ CallRuntime(Runtime::kThrow);
+
   __ bind(&suspend);
   OperandStackDepthIncrement(1);  // Not popped on this path.
   VisitForAccumulatorValue(expr->generator_object());
@@ -1778,8 +1768,7 @@
   __ j(equal, &post_runtime);
   __ push(eax);  // generator object
   __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
-  __ mov(context_register(),
-         Operand(ebp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   __ bind(&post_runtime);
   PopOperand(result_register());
   EmitReturnSequence();
@@ -1788,101 +1777,6 @@
   context()->Plug(result_register());
 }
 
-
-void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
-    Expression *value,
-    JSGeneratorObject::ResumeMode resume_mode) {
-  // The value stays in eax, and is ultimately read by the resumed generator, as
-  // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it
-  // is read to throw the value when the resumed generator is already closed.
-  // ebx will hold the generator object until the activation has been resumed.
-  VisitForStackValue(generator);
-  VisitForAccumulatorValue(value);
-  PopOperand(ebx);
-
-  // Store input value into generator object.
-  __ mov(FieldOperand(ebx, JSGeneratorObject::kInputOffset), result_register());
-  __ mov(ecx, result_register());
-  __ RecordWriteField(ebx, JSGeneratorObject::kInputOffset, ecx, edx,
-                      kDontSaveFPRegs);
-
-  // Load suspended function and context.
-  __ mov(esi, FieldOperand(ebx, JSGeneratorObject::kContextOffset));
-  __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset));
-
-  // Push receiver.
-  __ push(FieldOperand(ebx, JSGeneratorObject::kReceiverOffset));
-
-  // Push holes for arguments to generator function. Since the parser forced
-  // context allocation for any variables in generators, the actual argument
-  // values have already been copied into the context and these dummy values
-  // will never be used.
-  __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
-  __ mov(edx,
-         FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ mov(ecx, isolate()->factory()->the_hole_value());
-  Label push_argument_holes, push_frame;
-  __ bind(&push_argument_holes);
-  __ sub(edx, Immediate(Smi::FromInt(1)));
-  __ j(carry, &push_frame);
-  __ push(ecx);
-  __ jmp(&push_argument_holes);
-
-  // Enter a new JavaScript frame, and initialize its slots as they were when
-  // the generator was suspended.
-  Label resume_frame, done;
-  __ bind(&push_frame);
-  __ call(&resume_frame);
-  __ jmp(&done);
-  __ bind(&resume_frame);
-  __ push(ebp);  // Caller's frame pointer.
-  __ mov(ebp, esp);
-  __ push(esi);  // Callee's context.
-  __ push(edi);  // Callee's JS Function.
-
-  // Load the operand stack size.
-  __ mov(edx, FieldOperand(ebx, JSGeneratorObject::kOperandStackOffset));
-  __ mov(edx, FieldOperand(edx, FixedArray::kLengthOffset));
-  __ SmiUntag(edx);
-
-  // If we are sending a value and there is no operand stack, we can jump back
-  // in directly.
-  if (resume_mode == JSGeneratorObject::NEXT) {
-    Label slow_resume;
-    __ cmp(edx, Immediate(0));
-    __ j(not_zero, &slow_resume);
-    __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
-    __ mov(ecx, FieldOperand(ebx, JSGeneratorObject::kContinuationOffset));
-    __ SmiUntag(ecx);
-    __ add(edx, ecx);
-    __ mov(FieldOperand(ebx, JSGeneratorObject::kContinuationOffset),
-           Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
-    __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-    __ jmp(edx);
-    __ bind(&slow_resume);
-  }
-
-  // Otherwise, we push holes for the operand stack and call the runtime to fix
-  // up the stack and the handlers.
-  Label push_operand_holes, call_resume;
-  __ bind(&push_operand_holes);
-  __ sub(edx, Immediate(1));
-  __ j(carry, &call_resume);
-  __ push(ecx);
-  __ jmp(&push_operand_holes);
-  __ bind(&call_resume);
-  __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation.
-  __ push(ebx);
-  __ push(result_register());
-  __ Push(Smi::FromInt(resume_mode));
-  __ CallRuntime(Runtime::kResumeJSGeneratorObject);
-  // Not reached: the runtime call returns elsewhere.
-  __ Abort(kGeneratorFailedToResume);
-
-  __ bind(&done);
-  context()->Plug(result_register());
-}
-
 void FullCodeGenerator::PushOperand(MemOperand operand) {
   OperandStackDepthIncrement(1);
   __ Push(operand);
@@ -1902,7 +1796,8 @@
 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
   Label allocate, done_allocate;
 
-  __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate,
+              NO_ALLOCATION_FLAGS);
   __ jmp(&done_allocate, Label::kNear);
 
   __ bind(&allocate);
@@ -2224,8 +2119,7 @@
     __ bind(&uninitialized_this);
     EmitStoreToStackLocalOrContextSlot(var, location);
 
-  } else if (!var->is_const_mode() ||
-             (var->mode() == CONST && op == Token::INIT)) {
+  } else if (!var->is_const_mode() || op == Token::INIT) {
     if (var->IsLookupSlot()) {
       // Assignment to var.
       __ Push(Immediate(var->name()));
@@ -2247,25 +2141,6 @@
       EmitStoreToStackLocalOrContextSlot(var, location);
     }
 
-  } else if (var->mode() == CONST_LEGACY && op == Token::INIT) {
-    // Const initializers need a write barrier.
-    DCHECK(!var->IsParameter());  // No const parameters.
-    if (var->IsLookupSlot()) {
-      __ push(eax);
-      __ push(esi);
-      __ push(Immediate(var->name()));
-      __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot);
-    } else {
-      DCHECK(var->IsStackLocal() || var->IsContextSlot());
-      Label skip;
-      MemOperand location = VarOperand(var, ecx);
-      __ mov(edx, location);
-      __ cmp(edx, isolate()->factory()->the_hole_value());
-      __ j(not_equal, &skip, Label::kNear);
-      EmitStoreToStackLocalOrContextSlot(var, location);
-      __ bind(&skip);
-    }
-
   } else {
     DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT);
     if (is_strict(language_mode())) {
@@ -2288,7 +2163,7 @@
   PopOperand(StoreDescriptor::ReceiverRegister());
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallStoreIC();
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(eax);
 }
 
@@ -2334,44 +2209,7 @@
       CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
   EmitLoadStoreICSlot(expr->AssignmentSlot());
   CallIC(ic);
-  PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
-  context()->Plug(eax);
-}
-
-
-void FullCodeGenerator::VisitProperty(Property* expr) {
-  Comment cmnt(masm_, "[ Property");
-  SetExpressionPosition(expr);
-
-  Expression* key = expr->key();
-
-  if (key->IsPropertyName()) {
-    if (!expr->IsSuperAccess()) {
-      VisitForAccumulatorValue(expr->obj());
-      __ Move(LoadDescriptor::ReceiverRegister(), result_register());
-      EmitNamedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      EmitNamedSuperPropertyLoad(expr);
-    }
-  } else {
-    if (!expr->IsSuperAccess()) {
-      VisitForStackValue(expr->obj());
-      VisitForAccumulatorValue(expr->key());
-      PopOperand(LoadDescriptor::ReceiverRegister());              // Object.
-      __ Move(LoadDescriptor::NameRegister(), result_register());  // Key.
-      EmitKeyedPropertyLoad(expr);
-    } else {
-      VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
-      VisitForStackValue(
-          expr->obj()->AsSuperPropertyReference()->home_object());
-      VisitForStackValue(expr->key());
-      EmitKeyedSuperPropertyLoad(expr);
-    }
-  }
-  PrepareForBailoutForId(expr->LoadId(), TOS_REG);
+  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
   context()->Plug(eax);
 }
 
@@ -2392,7 +2230,7 @@
   if (callee->IsVariableProxy()) {
     { StackValueContext context(this);
       EmitVariableLoad(callee->AsVariableProxy());
-      PrepareForBailout(callee, NO_REGISTERS);
+      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
     }
     // Push undefined as receiver. This is patched in the method prologue if it
     // is a sloppy mode method.
@@ -2404,7 +2242,8 @@
     DCHECK(!callee->AsProperty()->IsSuperAccess());
     __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
     EmitNamedPropertyLoad(callee->AsProperty());
-    PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                           BailoutState::TOS_REGISTER);
     // Push the target function under the receiver.
     PushOperand(Operand(esp, 0));
     __ mov(Operand(esp, kPointerSize), eax);
@@ -2439,6 +2278,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ mov(Operand(esp, kPointerSize), eax);
@@ -2463,7 +2303,8 @@
   __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
   __ mov(LoadDescriptor::NameRegister(), eax);
   EmitKeyedPropertyLoad(callee->AsProperty());
-  PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
+  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
+                         BailoutState::TOS_REGISTER);
 
   // Push the target function under the receiver.
   PushOperand(Operand(esp, 0));
@@ -2495,6 +2336,7 @@
   //  - home_object
   //  - key
   CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
+  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
 
   // Replace home_object with target function.
   __ mov(Operand(esp, kPointerSize), eax);
@@ -2514,7 +2356,7 @@
     VisitForStackValue(args->at(i));
   }
 
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   SetCallPosition(expr, expr->tail_call_mode());
   if (expr->tail_call_mode() == TailCallMode::kAllow) {
     if (FLAG_trace) {
@@ -2535,15 +2377,12 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-
-  // Restore context register.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-
+  RestoreContext();
   context()->DropAndPlug(1, eax);
 }
 
-
-void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
+void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
+  int arg_count = expr->arguments()->length();
   // Push copy of the first argument or undefined if it doesn't exist.
   if (arg_count > 0) {
     __ push(Operand(esp, arg_count * kPointerSize));
@@ -2560,6 +2399,9 @@
   // Push the start position of the scope the calls resides in.
   __ push(Immediate(Smi::FromInt(scope()->start_position())));
 
+  // Push the source position of the eval call.
+  __ push(Immediate(Smi::FromInt(expr->position())));
+
   // Do the runtime call.
   __ CallRuntime(Runtime::kResolvePossiblyDirectEval);
 }
@@ -2582,7 +2424,7 @@
     __ CallRuntime(Runtime::kLoadLookupSlotForCall);
     PushOperand(eax);  // Function.
     PushOperand(edx);  // Receiver.
-    PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
+    PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
 
     // If fast case code has been generated, emit code to push the function
     // and receiver and have the slow path jump around this code.
@@ -2606,7 +2448,7 @@
 
 
 void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
-  // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
+  // In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
   // to resolve the function we need to call.  Then we call the resolved
   // function using the given arguments.
   ZoneList<Expression*>* args = expr->arguments();
@@ -2622,12 +2464,12 @@
   // Push a copy of the function (found below the arguments) and
   // resolve eval.
   __ push(Operand(esp, (arg_count + 1) * kPointerSize));
-  EmitResolvePossiblyDirectEval(arg_count);
+  EmitResolvePossiblyDirectEval(expr);
 
   // Touch up the stack with the resolved function.
   __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
 
-  PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
 
   SetCallPosition(expr);
   __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
@@ -2637,8 +2479,7 @@
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
   RecordJSReturnSite(expr);
-  // Restore context register.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->DropAndPlug(1, eax);
 }
 
@@ -2677,9 +2518,8 @@
   CallConstructStub stub(isolate());
   __ call(stub.GetCode(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-  PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
-  // Restore context register.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
+  RestoreContext();
   context()->Plug(eax);
 }
 
@@ -2720,9 +2560,7 @@
   OperandStackDepthDecrement(arg_count + 1);
 
   RecordJSReturnSite(expr);
-
-  // Restore context register.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   context()->Plug(eax);
 }
 
@@ -2927,75 +2765,6 @@
 }
 
 
-void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = eax;
-  Register index = ebx;
-  Register value = ecx;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-
-  PopOperand(value);
-  PopOperand(index);
-
-  if (FLAG_debug_code) {
-    __ test(value, Immediate(kSmiTagMask));
-    __ Check(zero, kNonSmiValue);
-    __ test(index, Immediate(kSmiTagMask));
-    __ Check(zero, kNonSmiValue);
-  }
-
-  __ SmiUntag(value);
-  __ SmiUntag(index);
-
-  if (FLAG_debug_code) {
-    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
-  }
-
-  __ mov_b(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize),
-           value);
-  context()->Plug(string);
-}
-
-
-void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK_EQ(3, args->length());
-
-  Register string = eax;
-  Register index = ebx;
-  Register value = ecx;
-
-  VisitForStackValue(args->at(0));        // index
-  VisitForStackValue(args->at(1));        // value
-  VisitForAccumulatorValue(args->at(2));  // string
-  PopOperand(value);
-  PopOperand(index);
-
-  if (FLAG_debug_code) {
-    __ test(value, Immediate(kSmiTagMask));
-    __ Check(zero, kNonSmiValue);
-    __ test(index, Immediate(kSmiTagMask));
-    __ Check(zero, kNonSmiValue);
-    __ SmiUntag(index);
-    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
-    __ SmiTag(index);
-  }
-
-  __ SmiUntag(value);
-  // No need to untag a smi for two-byte addressing.
-  __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize),
-           value);
-  context()->Plug(string);
-}
-
-
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
@@ -3031,13 +2800,8 @@
   Label need_conversion;
   Label index_out_of_range;
   Label done;
-  StringCharCodeAtGenerator generator(object,
-                                      index,
-                                      result,
-                                      &need_conversion,
-                                      &need_conversion,
-                                      &index_out_of_range,
-                                      STRING_INDEX_IS_NUMBER);
+  StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
+                                      &need_conversion, &index_out_of_range);
   generator.GenerateFast(masm_);
   __ jmp(&done);
 
@@ -3061,54 +2825,6 @@
 }
 
 
-void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  DCHECK(args->length() == 2);
-
-  VisitForStackValue(args->at(0));
-  VisitForAccumulatorValue(args->at(1));
-
-  Register object = ebx;
-  Register index = eax;
-  Register scratch = edx;
-  Register result = eax;
-
-  PopOperand(object);
-
-  Label need_conversion;
-  Label index_out_of_range;
-  Label done;
-  StringCharAtGenerator generator(object,
-                                  index,
-                                  scratch,
-                                  result,
-                                  &need_conversion,
-                                  &need_conversion,
-                                  &index_out_of_range,
-                                  STRING_INDEX_IS_NUMBER);
-  generator.GenerateFast(masm_);
-  __ jmp(&done);
-
-  __ bind(&index_out_of_range);
-  // When the index is out of range, the spec requires us to return
-  // the empty string.
-  __ Move(result, Immediate(isolate()->factory()->empty_string()));
-  __ jmp(&done);
-
-  __ bind(&need_conversion);
-  // Move smi zero into the result register, which will trigger
-  // conversion.
-  __ Move(result, Immediate(Smi::FromInt(0)));
-  __ jmp(&done);
-
-  NopRuntimeCallHelper call_helper;
-  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
-
-  __ bind(&done);
-  context()->Plug(result);
-}
-
-
 void FullCodeGenerator::EmitCall(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK_LE(2, args->length());
@@ -3116,7 +2832,7 @@
   for (Expression* const arg : *args) {
     VisitForStackValue(arg);
   }
-  PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
+  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   // Move target to edi.
   int const argc = args->length() - 2;
   __ mov(edi, Operand(esp, (argc + 1) * kPointerSize));
@@ -3124,8 +2840,7 @@
   __ mov(eax, Immediate(argc));
   __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(argc + 1);
-  // Restore context register.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
   // Discard the function left on TOS.
   context()->DropAndPlug(1, eax);
 }
@@ -3179,13 +2894,6 @@
   context()->Plug(eax);
 }
 
-void FullCodeGenerator::EmitGetOrdinaryHasInstance(CallRuntime* expr) {
-  DCHECK_EQ(0, expr->arguments()->length());
-  __ mov(eax, NativeContextOperand());
-  __ mov(eax, ContextOperand(eax, Context::ORDINARY_HAS_INSTANCE_INDEX));
-  context()->Plug(eax);
-}
-
 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
   DCHECK(expr->arguments()->length() == 0);
   ExternalReference debug_is_active =
@@ -3204,7 +2912,8 @@
 
   Label runtime, done;
 
-  __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &runtime, TAG_OBJECT);
+  __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &runtime,
+              NO_ALLOCATION_FLAGS);
   __ mov(ebx, NativeContextOperand());
   __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX));
   __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx);
@@ -3245,9 +2954,7 @@
   __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
           RelocInfo::CODE_TARGET);
   OperandStackDepthDecrement(arg_count + 1);
-
-  // Restore context register.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  RestoreContext();
 }
 
 
@@ -3332,7 +3039,8 @@
                         &materialize_true);
         if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
         __ bind(&materialize_true);
-        PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeTrueId(),
+                               BailoutState::NO_REGISTERS);
         if (context()->IsAccumulatorValue()) {
           __ mov(eax, isolate()->factory()->true_value());
         } else {
@@ -3340,7 +3048,8 @@
         }
         __ jmp(&done, Label::kNear);
         __ bind(&materialize_false);
-        PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
+        PrepareForBailoutForId(expr->MaterializeFalseId(),
+                               BailoutState::NO_REGISTERS);
         if (context()->IsAccumulatorValue()) {
           __ mov(eax, isolate()->factory()->false_value());
         } else {
@@ -3439,9 +3148,9 @@
   // We need a second deoptimization point after loading the value
   // in case evaluating the property load my have a side effect.
   if (assign_type == VARIABLE) {
-    PrepareForBailout(expr->expression(), TOS_REG);
+    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
   } else {
-    PrepareForBailoutForId(prop->LoadId(), TOS_REG);
+    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
   }
 
   // Inline smi case if we are in a loop.
@@ -3494,9 +3203,8 @@
   }
 
   // Convert old value into a number.
-  ToNumberStub convert_stub(isolate());
-  __ CallStub(&convert_stub);
-  PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
+  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
+  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
 
   // Save result for postfix expressions.
   if (expr->is_postfix()) {
@@ -3544,7 +3252,8 @@
         { EffectContext context(this);
           EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                  Token::ASSIGN, expr->CountSlot());
-          PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+          PrepareForBailoutForId(expr->AssignmentId(),
+                                 BailoutState::TOS_REGISTER);
           context.Plug(eax);
         }
         // For all contexts except EffectContext We have the result on
@@ -3556,7 +3265,8 @@
         // Perform the assignment as if via '='.
         EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
                                Token::ASSIGN, expr->CountSlot());
-        PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+        PrepareForBailoutForId(expr->AssignmentId(),
+                               BailoutState::TOS_REGISTER);
         context()->Plug(eax);
       }
       break;
@@ -3566,7 +3276,7 @@
       PopOperand(StoreDescriptor::ReceiverRegister());
       EmitLoadStoreICSlot(expr->CountSlot());
       CallStoreIC();
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         if (!context()->IsEffect()) {
           context()->PlugTOS();
@@ -3605,7 +3315,7 @@
           CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
       EmitLoadStoreICSlot(expr->CountSlot());
       CallIC(ic);
-      PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
+      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
       if (expr->is_postfix()) {
         // Result is on the stack
         if (!context()->IsEffect()) {
@@ -3701,7 +3411,6 @@
 
 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
   Comment cmnt(masm_, "[ CompareOperation");
-  SetExpressionPosition(expr);
 
   // First we try a fast inlined version of the compare when one of
   // the operands is a literal.
@@ -3721,7 +3430,8 @@
   switch (op) {
     case Token::IN:
       VisitForStackValue(expr->right());
-      CallRuntimeWithOperands(Runtime::kHasProperty);
+      SetExpressionPosition(expr);
+      EmitHasProperty();
       PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
       __ cmp(eax, isolate()->factory()->true_value());
       Split(equal, if_true, if_false, fall_through);
@@ -3729,6 +3439,7 @@
 
     case Token::INSTANCEOF: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       PopOperand(edx);
       InstanceOfStub stub(isolate());
       __ CallStub(&stub);
@@ -3740,6 +3451,7 @@
 
     default: {
       VisitForAccumulatorValue(expr->right());
+      SetExpressionPosition(expr);
       Condition cc = CompareIC::ComputeCondition(op);
       PopOperand(edx);
 
diff --git a/src/futex-emulation.cc b/src/futex-emulation.cc
index 991e4c3..1f7e8a6 100644
--- a/src/futex-emulation.cc
+++ b/src/futex-emulation.cc
@@ -142,7 +142,7 @@
     // be false, so we'll loop and then check interrupts.
     if (interrupted) {
       Object* interrupt_object = isolate->stack_guard()->HandleInterrupts();
-      if (interrupt_object->IsException()) {
+      if (interrupt_object->IsException(isolate)) {
         result = interrupt_object;
         mutex_.Pointer()->Lock();
         break;
diff --git a/src/gdb-jit.cc b/src/gdb-jit.cc
index 0df5975..e73b733 100644
--- a/src/gdb-jit.cc
+++ b/src/gdb-jit.cc
@@ -2012,17 +2012,19 @@
   return static_cast<uint32_t>((offset >> kCodeAlignmentBits) * kGoldenRatio);
 }
 
-
-static HashMap* GetLineMap() {
-  static HashMap* line_map = NULL;
-  if (line_map == NULL) line_map = new HashMap(&HashMap::PointersMatch);
+static base::HashMap* GetLineMap() {
+  static base::HashMap* line_map = NULL;
+  if (line_map == NULL) {
+    line_map = new base::HashMap(&base::HashMap::PointersMatch);
+  }
   return line_map;
 }
 
 
 static void PutLineInfo(Address addr, LineInfo* info) {
-  HashMap* line_map = GetLineMap();
-  HashMap::Entry* e = line_map->LookupOrInsert(addr, HashCodeAddress(addr));
+  base::HashMap* line_map = GetLineMap();
+  base::HashMap::Entry* e =
+      line_map->LookupOrInsert(addr, HashCodeAddress(addr));
   if (e->value != NULL) delete static_cast<LineInfo*>(e->value);
   e->value = info;
 }
diff --git a/src/global-handles.cc b/src/global-handles.cc
index ed9caa9..dffa237 100644
--- a/src/global-handles.cc
+++ b/src/global-handles.cc
@@ -82,7 +82,6 @@
     index_ = static_cast<uint8_t>(index);
     DCHECK(static_cast<int>(index_) == index);
     set_state(FREE);
-    set_weakness_type(NORMAL_WEAK);
     set_in_new_space_list(false);
     parameter_or_next_free_.next_free = *first_free;
     *first_free = this;
@@ -195,16 +194,26 @@
 
   bool IsInUse() const { return state() != FREE; }
 
+  bool IsPendingPhantomCallback() const {
+    return state() == PENDING &&
+           (weakness_type() == PHANTOM_WEAK ||
+            weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS);
+  }
+
+  bool IsPendingPhantomResetHandle() const {
+    return state() == PENDING && weakness_type() == PHANTOM_WEAK_RESET_HANDLE;
+  }
+
   bool IsRetainer() const {
     return state() != FREE &&
-           !(state() == NEAR_DEATH && weakness_type() != NORMAL_WEAK);
+           !(state() == NEAR_DEATH && weakness_type() != FINALIZER_WEAK);
   }
 
   bool IsStrongRetainer() const { return state() == NORMAL; }
 
   bool IsWeakRetainer() const {
     return state() == WEAK || state() == PENDING ||
-           (state() == NEAR_DEATH && weakness_type() == NORMAL_WEAK);
+           (state() == NEAR_DEATH && weakness_type() == FINALIZER_WEAK);
   }
 
   void MarkPending() {
@@ -250,16 +259,6 @@
     parameter_or_next_free_.next_free = value;
   }
 
-  void MakeWeak(void* parameter, WeakCallback weak_callback) {
-    DCHECK(weak_callback != nullptr);
-    DCHECK(IsInUse());
-    CHECK_NE(object_, reinterpret_cast<Object*>(kGlobalHandleZapValue));
-    set_state(WEAK);
-    set_weakness_type(NORMAL_WEAK);
-    set_parameter(parameter);
-    weak_callback_ = weak_callback;
-  }
-
   void MakeWeak(void* parameter,
                 WeakCallbackInfo<void>::Callback phantom_callback,
                 v8::WeakCallbackType type) {
@@ -272,11 +271,23 @@
         set_weakness_type(PHANTOM_WEAK);
         break;
       case v8::WeakCallbackType::kInternalFields:
-      set_weakness_type(PHANTOM_WEAK_2_INTERNAL_FIELDS);
-      break;
+        set_weakness_type(PHANTOM_WEAK_2_INTERNAL_FIELDS);
+        break;
+      case v8::WeakCallbackType::kFinalizer:
+        set_weakness_type(FINALIZER_WEAK);
+        break;
     }
     set_parameter(parameter);
-    weak_callback_ = reinterpret_cast<WeakCallback>(phantom_callback);
+    weak_callback_ = phantom_callback;
+  }
+
+  void MakeWeak(Object*** location_addr) {
+    DCHECK(IsInUse());
+    CHECK_NE(object_, reinterpret_cast<Object*>(kGlobalHandleZapValue));
+    set_state(WEAK);
+    set_weakness_type(PHANTOM_WEAK_RESET_HANDLE);
+    set_parameter(location_addr);
+    weak_callback_ = nullptr;
   }
 
   void* ClearWeakness() {
@@ -293,6 +304,7 @@
     DCHECK(weakness_type() == PHANTOM_WEAK ||
            weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS);
     DCHECK(state() == PENDING);
+    DCHECK(weak_callback_ != nullptr);
 
     void* internal_fields[v8::kInternalFieldsInWeakCallback] = {nullptr,
                                                                 nullptr};
@@ -317,6 +329,15 @@
     set_state(NEAR_DEATH);
   }
 
+  void ResetPhantomHandle() {
+    DCHECK(weakness_type() == PHANTOM_WEAK_RESET_HANDLE);
+    DCHECK(state() == PENDING);
+    DCHECK(weak_callback_ == nullptr);
+    Object*** handle = reinterpret_cast<Object***>(parameter());
+    *handle = nullptr;
+    Release();
+  }
+
   bool PostGarbageCollectionProcessing(Isolate* isolate) {
     // Handles only weak handles (not phantom) that are dying.
     if (state() != Node::PENDING) return false;
@@ -332,17 +353,17 @@
            ExternalOneByteString::cast(object_)->resource() != NULL);
     DCHECK(!object_->IsExternalTwoByteString() ||
            ExternalTwoByteString::cast(object_)->resource() != NULL);
-    if (weakness_type() != NORMAL_WEAK) return false;
+    if (weakness_type() != FINALIZER_WEAK) {
+      return false;
+    }
 
     // Leaving V8.
     VMState<EXTERNAL> vmstate(isolate);
     HandleScope handle_scope(isolate);
-    Object** object = location();
-    Handle<Object> handle(*object, isolate);
-    v8::WeakCallbackData<v8::Value, void> data(
-        reinterpret_cast<v8::Isolate*>(isolate), parameter(),
-        v8::Utils::ToLocal(handle));
-    set_parameter(NULL);
+    void* internal_fields[v8::kInternalFieldsInWeakCallback] = {nullptr,
+                                                                nullptr};
+    v8::WeakCallbackInfo<void> data(reinterpret_cast<v8::Isolate*>(isolate),
+                                    parameter(), internal_fields, nullptr);
     weak_callback_(data);
 
     // Absence of explicit cleanup or revival of weak handle
@@ -384,7 +405,7 @@
   uint8_t flags_;
 
   // Handle specific callback - might be a weak reference in disguise.
-  WeakCallback weak_callback_;
+  WeakCallbackInfo<void>::Callback weak_callback_;
 
   // Provided data for callback.  In FREE state, this is used for
   // the free list link.
@@ -534,6 +555,7 @@
   }
 
   void RunInternal() override {
+    TRACE_EVENT0("v8", "V8.GCPhantomHandleProcessingCallback");
     isolate()->heap()->CallGCPrologueCallbacks(
         GCType::kGCTypeProcessWeakCallbacks, kNoGCCallbackFlags);
     InvokeSecondPassPhantomCallbacks(&pending_phantom_callbacks_, isolate());
@@ -547,7 +569,6 @@
   DISALLOW_COPY_AND_ASSIGN(PendingPhantomCallbacksSecondPassTask);
 };
 
-
 GlobalHandles::GlobalHandles(Isolate* isolate)
     : isolate_(isolate),
       number_of_global_handles_(0),
@@ -555,9 +576,9 @@
       first_used_block_(NULL),
       first_free_(NULL),
       post_gc_processing_count_(0),
+      number_of_phantom_handle_resets_(0),
       object_group_connections_(kObjectGroupConnectionsCapacity) {}
 
-
 GlobalHandles::~GlobalHandles() {
   NodeBlock* block = first_block_;
   while (block != NULL) {
@@ -599,12 +620,6 @@
 }
 
 
-void GlobalHandles::MakeWeak(Object** location, void* parameter,
-                             WeakCallback weak_callback) {
-  Node::FromLocation(location)->MakeWeak(parameter, weak_callback);
-}
-
-
 typedef v8::WeakCallbackInfo<void>::Callback GenericCallback;
 
 
@@ -614,6 +629,9 @@
   Node::FromLocation(location)->MakeWeak(parameter, phantom_callback, type);
 }
 
+void GlobalHandles::MakeWeak(Object*** location_addr) {
+  Node::FromLocation(*location_addr)->MakeWeak(location_addr);
+}
 
 void* GlobalHandles::ClearWeakness(Object** location) {
   return Node::FromLocation(location)->ClearWeakness();
@@ -649,10 +667,12 @@
     Node* node = it.node();
     if (node->IsWeakRetainer()) {
       // Pending weak phantom handles die immediately. Everything else survives.
-      if (node->state() == Node::PENDING &&
-          node->weakness_type() != NORMAL_WEAK) {
-          node->CollectPhantomCallbackData(isolate(),
-                                           &pending_phantom_callbacks_);
+      if (node->IsPendingPhantomResetHandle()) {
+        node->ResetPhantomHandle();
+        ++number_of_phantom_handle_resets_;
+      } else if (node->IsPendingPhantomCallback()) {
+        node->CollectPhantomCallbackData(isolate(),
+                                         &pending_phantom_callbacks_);
       } else {
         v->VisitPointer(node->location());
       }
@@ -710,8 +730,10 @@
     if ((node->is_independent() || node->is_partially_dependent()) &&
         node->IsWeakRetainer()) {
       // Pending weak phantom handles die immediately. Everything else survives.
-      if (node->state() == Node::PENDING &&
-          node->weakness_type() != NORMAL_WEAK) {
+      if (node->IsPendingPhantomResetHandle()) {
+        node->ResetPhantomHandle();
+        ++number_of_phantom_handle_resets_;
+      } else if (node->IsPendingPhantomCallback()) {
         node->CollectPhantomCallbackData(isolate(),
                                          &pending_phantom_callbacks_);
       } else {
@@ -753,8 +775,10 @@
     if ((node->is_independent() || !node->is_active()) &&
         node->IsWeakRetainer()) {
       // Pending weak phantom handles die immediately. Everything else survives.
-      if (node->state() == Node::PENDING &&
-          node->weakness_type() != NORMAL_WEAK) {
+      if (node->IsPendingPhantomResetHandle()) {
+        node->ResetPhantomHandle();
+        ++number_of_phantom_handle_resets_;
+      } else if (node->IsPendingPhantomCallback()) {
         node->CollectPhantomCallbackData(isolate(),
                                          &pending_phantom_callbacks_);
       } else {
@@ -855,7 +879,7 @@
     PrintInternalFields(js_object);
     PrintF(" ] }\n");
   } else {
-    PrintF("object of unexpected type: %p\n", object);
+    PrintF("object of unexpected type: %p\n", static_cast<void*>(object));
   }
 }
 
@@ -867,7 +891,7 @@
     if (name->length() == 0) name = constructor->shared()->inferred_name();
 
     PrintF("%s", name->ToCString().get());
-  } else if (maybe_constructor->IsNull()) {
+  } else if (maybe_constructor->IsNull(isolate_)) {
     if (js_object->IsOddball()) {
       PrintF("<oddball>");
     } else {
@@ -883,12 +907,12 @@
     if (i != 0) {
       PrintF(", ");
     }
-    PrintF("%p", js_object->GetInternalField(i));
+    PrintF("%p", static_cast<void*>(js_object->GetInternalField(i)));
   }
 }
 
 void ObjectGroupsTracer::PrintObjectGroup(ObjectGroup* group) {
-  PrintIsolate(isolate_, "ObjectGroup (size: %lu)\n", group->length);
+  PrintIsolate(isolate_, "ObjectGroup (size: %" PRIuS ")\n", group->length);
   Object*** objects = group->objects;
 
   for (size_t i = 0; i < group->length; ++i) {
@@ -898,7 +922,7 @@
 }
 
 void ObjectGroupsTracer::PrintImplicitRefGroup(ImplicitRefGroup* group) {
-  PrintIsolate(isolate_, "ImplicitRefGroup (children count: %lu)\n",
+  PrintIsolate(isolate_, "ImplicitRefGroup (children count: %" PRIuS ")\n",
                group->length);
   PrintIsolate(isolate_, "  - Parent: ");
   PrintObject(*(group->parent));
@@ -1223,8 +1247,7 @@
   }
 
   PrintF("Global Handle Statistics:\n");
-  PrintF("  allocated memory = %" V8_SIZET_PREFIX V8_PTR_PREFIX "dB\n",
-         total * sizeof(Node));
+  PrintF("  allocated memory = %" PRIuS "B\n", total * sizeof(Node));
   PrintF("  # weak       = %d\n", weak);
   PrintF("  # pending    = %d\n", pending);
   PrintF("  # near_death = %d\n", near_death);
diff --git a/src/global-handles.h b/src/global-handles.h
index ac8487b..24a2273 100644
--- a/src/global-handles.h
+++ b/src/global-handles.h
@@ -96,19 +96,21 @@
   RetainedObjectInfo* info;
 };
 
-
 enum WeaknessType {
-  NORMAL_WEAK,  // Embedder gets a handle to the dying object.
+  // Embedder gets a handle to the dying object.
+  FINALIZER_WEAK,
   // In the following cases, the embedder gets the parameter they passed in
   // earlier, and 0 or 2 first internal fields. Note that the internal
   // fields must contain aligned non-V8 pointers.  Getting pointers to V8
   // objects through this interface would be GC unsafe so in that case the
   // embedder gets a null pointer instead.
   PHANTOM_WEAK,
-  PHANTOM_WEAK_2_INTERNAL_FIELDS
+  PHANTOM_WEAK_2_INTERNAL_FIELDS,
+  // The handle is automatically reset by the garbage collector when
+  // the object is no longer reachable.
+  PHANTOM_WEAK_RESET_HANDLE
 };
 
-
 class GlobalHandles {
  public:
   ~GlobalHandles();
@@ -122,14 +124,6 @@
   // Destroy a global handle.
   static void Destroy(Object** location);
 
-  typedef WeakCallbackData<v8::Value, void>::Callback WeakCallback;
-
-  // For a phantom weak reference, the callback does not have access to the
-  // dying object.  Phantom weak references are preferred because they allow
-  // memory to be reclaimed in one GC cycle rather than two.  However, for
-  // historical reasons the default is non-phantom.
-  enum PhantomState { Nonphantom, Phantom };
-
   // Make the global handle weak and set the callback parameter for the
   // handle.  When the garbage collector recognizes that only weak global
   // handles point to an object the callback function is invoked (for each
@@ -140,14 +134,11 @@
   // before the callback is invoked, but the handle can still be identified
   // in the callback by using the location() of the handle.
   static void MakeWeak(Object** location, void* parameter,
-                       WeakCallback weak_callback);
-
-  // It would be nice to template this one, but it's really hard to get
-  // the template instantiator to work right if you do.
-  static void MakeWeak(Object** location, void* parameter,
                        WeakCallbackInfo<void>::Callback weak_callback,
                        v8::WeakCallbackType type);
 
+  static void MakeWeak(Object*** location_addr);
+
   void RecordStats(HeapStats* stats);
 
   // Returns the current number of weak handles.
@@ -162,6 +153,14 @@
     return number_of_global_handles_;
   }
 
+  size_t NumberOfPhantomHandleResets() {
+    return number_of_phantom_handle_resets_;
+  }
+
+  void ResetNumberOfPhantomHandleResets() {
+    number_of_phantom_handle_resets_ = 0;
+  }
+
   // Clear the weakness of a global handle.
   static void* ClearWeakness(Object** location);
 
@@ -344,6 +343,8 @@
 
   int post_gc_processing_count_;
 
+  size_t number_of_phantom_handle_resets_;
+
   // Object groups and implicit references, public and more efficient
   // representation.
   List<ObjectGroup*> object_groups_;
diff --git a/src/globals.h b/src/globals.h
index e7ac2b9..a31f237 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -124,11 +124,6 @@
 const int kDoubleSize    = sizeof(double);    // NOLINT
 const int kIntptrSize    = sizeof(intptr_t);  // NOLINT
 const int kPointerSize   = sizeof(void*);     // NOLINT
-#if V8_TARGET_ARCH_ARM64
-const int kFrameAlignmentInBytes = 2 * kPointerSize;
-#else
-const int kFrameAlignmentInBytes = kPointerSize;
-#endif
 #if V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
 const int kRegisterSize  = kPointerSize + kPointerSize;
 #else
@@ -155,12 +150,21 @@
 // encoded immediate, the addresses have to be in range of 256MB aligned
 // region. Used only for large object space.
 const size_t kMaximalCodeRangeSize = 256 * MB;
+const size_t kCodeRangeAreaAlignment = 256 * MB;
+#elif V8_HOST_ARCH_PPC && V8_TARGET_ARCH_PPC && V8_OS_LINUX
+const size_t kMaximalCodeRangeSize = 512 * MB;
+const size_t kCodeRangeAreaAlignment = 64 * KB;  // OS page on PPC Linux
 #else
 const size_t kMaximalCodeRangeSize = 512 * MB;
+const size_t kCodeRangeAreaAlignment = 4 * KB;  // OS page.
 #endif
 #if V8_OS_WIN
 const size_t kMinimumCodeRangeSize = 4 * MB;
 const size_t kReservedCodeRangePages = 1;
+// On PPC Linux PageSize is 4MB
+#elif V8_HOST_ARCH_PPC && V8_TARGET_ARCH_PPC && V8_OS_LINUX
+const size_t kMinimumCodeRangeSize = 12 * MB;
+const size_t kReservedCodeRangePages = 0;
 #else
 const size_t kMinimumCodeRangeSize = 3 * MB;
 const size_t kReservedCodeRangePages = 0;
@@ -174,14 +178,24 @@
 const bool kRequiresCodeRange = true;
 const size_t kMaximalCodeRangeSize = 256 * MB;
 const size_t kMinimumCodeRangeSize = 3 * MB;
-const size_t kReservedCodeRangePages = 0;
+const size_t kCodeRangeAreaAlignment = 4 * KB;  // OS page.
+#elif V8_HOST_ARCH_PPC && V8_TARGET_ARCH_PPC && V8_OS_LINUX
+const bool kRequiresCodeRange = false;
+const size_t kMaximalCodeRangeSize = 0 * MB;
+const size_t kMinimumCodeRangeSize = 0 * MB;
+const size_t kCodeRangeAreaAlignment = 64 * KB;  // OS page on PPC Linux
 #else
 const bool kRequiresCodeRange = false;
 const size_t kMaximalCodeRangeSize = 0 * MB;
 const size_t kMinimumCodeRangeSize = 0 * MB;
+const size_t kCodeRangeAreaAlignment = 4 * KB;  // OS page.
+#endif
 const size_t kReservedCodeRangePages = 0;
 #endif
-#endif
+
+// The external allocation limit should be below 256 MB on all architectures
+// to avoid that resource-constrained embedders run low on memory.
+const int kExternalAllocationLimit = 192 * 1024 * 1024;
 
 STATIC_ASSERT(kPointerSize == (1 << kPointerSizeLog2));
 
@@ -457,6 +471,53 @@
   kSimd128Unaligned
 };
 
+// Possible outcomes for decisions.
+enum class Decision : uint8_t { kUnknown, kTrue, kFalse };
+
+inline size_t hash_value(Decision decision) {
+  return static_cast<uint8_t>(decision);
+}
+
+inline std::ostream& operator<<(std::ostream& os, Decision decision) {
+  switch (decision) {
+    case Decision::kUnknown:
+      return os << "Unknown";
+    case Decision::kTrue:
+      return os << "True";
+    case Decision::kFalse:
+      return os << "False";
+  }
+  UNREACHABLE();
+  return os;
+}
+
+// Supported write barrier modes.
+enum WriteBarrierKind : uint8_t {
+  kNoWriteBarrier,
+  kMapWriteBarrier,
+  kPointerWriteBarrier,
+  kFullWriteBarrier
+};
+
+inline size_t hash_value(WriteBarrierKind kind) {
+  return static_cast<uint8_t>(kind);
+}
+
+inline std::ostream& operator<<(std::ostream& os, WriteBarrierKind kind) {
+  switch (kind) {
+    case kNoWriteBarrier:
+      return os << "NoWriteBarrier";
+    case kMapWriteBarrier:
+      return os << "MapWriteBarrier";
+    case kPointerWriteBarrier:
+      return os << "PointerWriteBarrier";
+    case kFullWriteBarrier:
+      return os << "FullWriteBarrier";
+  }
+  UNREACHABLE();
+  return os;
+}
+
 // A flag that indicates whether objects should be pretenured when
 // allocated (allocated directly into the old generation) or not
 // (allocated in the young generation if the object size and type
@@ -527,6 +588,8 @@
   int instr_size;
   int reloc_size;
   int constant_pool_size;
+  byte* unwinding_info;
+  int unwinding_info_size;
   Assembler* origin;
 };
 
@@ -551,18 +614,15 @@
   // Has been executed and only one receiver type has been seen.
   MONOMORPHIC,
   // Check failed due to prototype (or map deprecation).
-  PROTOTYPE_FAILURE,
+  RECOMPUTE_HANDLER,
   // Multiple receiver types have been seen.
   POLYMORPHIC,
   // Many receiver types have been seen.
   MEGAMORPHIC,
   // A generic handler is installed and no extra typefeedback is recorded.
   GENERIC,
-  // Special state for debug break or step in prepare stubs.
-  DEBUG_STUB
 };
 
-
 enum CacheHolderFlag {
   kCacheOnPrototype,
   kCacheOnPrototypeReceiverIsDictionary,
@@ -570,6 +630,7 @@
   kCacheOnReceiver
 };
 
+enum WhereToStart { kStartAtReceiver, kStartAtPrototype };
 
 // The Store Buffer (GC).
 typedef enum {
@@ -619,6 +680,15 @@
   } bits;
 };
 
+#if V8_TARGET_LITTLE_ENDIAN
+typedef IeeeDoubleLittleEndianArchType IeeeDoubleArchType;
+const int kIeeeDoubleMantissaWordOffset = 0;
+const int kIeeeDoubleExponentWordOffset = 4;
+#else
+typedef IeeeDoubleBigEndianArchType IeeeDoubleArchType;
+const int kIeeeDoubleMantissaWordOffset = 4;
+const int kIeeeDoubleExponentWordOffset = 0;
+#endif
 
 // AccessorCallback
 struct AccessorDescriptor {
@@ -672,7 +742,6 @@
   ARMv7,
   ARMv8,
   SUDIV,
-  MLS,
   UNALIGNED_ACCESSES,
   MOVW_MOVT_IMMEDIATE_LOADS,
   VFP32DREGS,
@@ -685,7 +754,6 @@
   MIPSr6,
   // ARM64
   ALWAYS_ALIGN_CSP,
-  COHERENT_CACHE,
   // PPC
   FPR_GPR_MOV,
   LWSYNC,
@@ -780,8 +848,14 @@
 };
 
 // The mips architecture prior to revision 5 has inverted encoding for sNaN.
-#if (V8_TARGET_ARCH_MIPS && !defined(_MIPS_ARCH_MIPS32R6)) || \
-    (V8_TARGET_ARCH_MIPS64 && !defined(_MIPS_ARCH_MIPS64R6))
+// The x87 FPU convert the sNaN to qNaN automatically when loading sNaN from
+// memmory.
+// Use mips sNaN which is a not used qNaN in x87 port as sNaN to workaround this
+// issue
+// for some test cases.
+#if (V8_TARGET_ARCH_MIPS && !defined(_MIPS_ARCH_MIPS32R6)) ||   \
+    (V8_TARGET_ARCH_MIPS64 && !defined(_MIPS_ARCH_MIPS64R6)) || \
+    (V8_TARGET_ARCH_X87)
 const uint32_t kHoleNanUpper32 = 0xFFFF7FFF;
 const uint32_t kHoleNanLower32 = 0xFFFF7FFF;
 #else
@@ -800,51 +874,48 @@
 // The order of this enum has to be kept in sync with the predicates below.
 enum VariableMode {
   // User declared variables:
-  VAR,             // declared via 'var', and 'function' declarations
+  VAR,  // declared via 'var', and 'function' declarations
 
-  CONST_LEGACY,    // declared via legacy 'const' declarations
+  CONST_LEGACY,  // declared via legacy 'const' declarations
 
-  LET,             // declared via 'let' declarations (first lexical)
+  LET,  // declared via 'let' declarations (first lexical)
 
-  CONST,           // declared via 'const' declarations
-
-  IMPORT,          // declared via 'import' declarations (last lexical)
+  CONST,  // declared via 'const' declarations (last lexical)
 
   // Variables introduced by the compiler:
-  TEMPORARY,       // temporary variables (not user-visible), stack-allocated
-                   // unless the scope as a whole has forced context allocation
+  TEMPORARY,  // temporary variables (not user-visible), stack-allocated
+              // unless the scope as a whole has forced context allocation
 
-  DYNAMIC,         // always require dynamic lookup (we don't know
-                   // the declaration)
+  DYNAMIC,  // always require dynamic lookup (we don't know
+            // the declaration)
 
   DYNAMIC_GLOBAL,  // requires dynamic lookup, but we know that the
                    // variable is global unless it has been shadowed
                    // by an eval-introduced variable
 
-  DYNAMIC_LOCAL    // requires dynamic lookup, but we know that the
-                   // variable is local and where it is unless it
-                   // has been shadowed by an eval-introduced
-                   // variable
+  DYNAMIC_LOCAL  // requires dynamic lookup, but we know that the
+                 // variable is local and where it is unless it
+                 // has been shadowed by an eval-introduced
+                 // variable
 };
 
-
 inline bool IsDynamicVariableMode(VariableMode mode) {
   return mode >= DYNAMIC && mode <= DYNAMIC_LOCAL;
 }
 
 
 inline bool IsDeclaredVariableMode(VariableMode mode) {
-  return mode >= VAR && mode <= IMPORT;
+  return mode >= VAR && mode <= CONST;
 }
 
 
 inline bool IsLexicalVariableMode(VariableMode mode) {
-  return mode >= LET && mode <= IMPORT;
+  return mode >= LET && mode <= CONST;
 }
 
 
 inline bool IsImmutableVariableMode(VariableMode mode) {
-  return mode == CONST || mode == CONST_LEGACY || mode == IMPORT;
+  return mode == CONST || mode == CONST_LEGACY;
 }
 
 
@@ -945,11 +1016,14 @@
   kBaseConstructor = 1 << 5,
   kGetterFunction = 1 << 6,
   kSetterFunction = 1 << 7,
+  kAsyncFunction = 1 << 8,
   kAccessorFunction = kGetterFunction | kSetterFunction,
   kDefaultBaseConstructor = kDefaultConstructor | kBaseConstructor,
   kDefaultSubclassConstructor = kDefaultConstructor | kSubclassConstructor,
   kClassConstructor =
       kBaseConstructor | kSubclassConstructor | kDefaultConstructor,
+  kAsyncArrowFunction = kArrowFunction | kAsyncFunction,
+  kAsyncConciseMethod = kAsyncFunction | kConciseMethod
 };
 
 inline bool IsValidFunctionKind(FunctionKind kind) {
@@ -964,7 +1038,10 @@
          kind == FunctionKind::kDefaultBaseConstructor ||
          kind == FunctionKind::kDefaultSubclassConstructor ||
          kind == FunctionKind::kBaseConstructor ||
-         kind == FunctionKind::kSubclassConstructor;
+         kind == FunctionKind::kSubclassConstructor ||
+         kind == FunctionKind::kAsyncFunction ||
+         kind == FunctionKind::kAsyncArrowFunction ||
+         kind == FunctionKind::kAsyncConciseMethod;
 }
 
 
@@ -979,6 +1056,14 @@
   return kind & FunctionKind::kGeneratorFunction;
 }
 
+inline bool IsAsyncFunction(FunctionKind kind) {
+  DCHECK(IsValidFunctionKind(kind));
+  return kind & FunctionKind::kAsyncFunction;
+}
+
+inline bool IsResumableFunction(FunctionKind kind) {
+  return IsGeneratorFunction(kind) || IsAsyncFunction(kind);
+}
 
 inline bool IsConciseMethod(FunctionKind kind) {
   DCHECK(IsValidFunctionKind(kind));
@@ -1030,6 +1115,7 @@
   if (IsConciseMethod(kind)) return false;
   if (IsArrowFunction(kind)) return false;
   if (IsGeneratorFunction(kind)) return false;
+  if (IsAsyncFunction(kind)) return false;
   return true;
 }
 
diff --git a/src/handles.h b/src/handles.h
index 1f97d6f..ab8ed09 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -43,6 +43,10 @@
 
   V8_INLINE bool is_null() const { return location_ == nullptr; }
 
+  // Returns the raw address where this handle is stored. This should only be
+  // used for hashing handles; do not ever try to dereference it.
+  V8_INLINE Address address() const { return bit_cast<Address>(location_); }
+
  protected:
   // Provides the C++ dereference operator.
   V8_INLINE Object* operator*() const {
@@ -132,14 +136,14 @@
   // Provide function object for location equality comparison.
   struct equal_to : public std::binary_function<Handle<T>, Handle<T>, bool> {
     V8_INLINE bool operator()(Handle<T> lhs, Handle<T> rhs) const {
-      return lhs.location() == rhs.location();
+      return lhs.address() == rhs.address();
     }
   };
 
   // Provide function object for location hashing.
   struct hash : public std::unary_function<Handle<T>, size_t> {
     V8_INLINE size_t operator()(Handle<T> const& handle) const {
-      return base::hash<void*>()(handle.location());
+      return base::hash<void*>()(handle.address());
     }
   };
 
diff --git a/src/hashmap.h b/src/hashmap.h
deleted file mode 100644
index f94def7..0000000
--- a/src/hashmap.h
+++ /dev/null
@@ -1,356 +0,0 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_HASHMAP_H_
-#define V8_HASHMAP_H_
-
-#include "src/allocation.h"
-#include "src/base/bits.h"
-#include "src/base/logging.h"
-#include "src/utils.h"
-
-namespace v8 {
-namespace internal {
-
-template<class AllocationPolicy>
-class TemplateHashMapImpl {
- public:
-  typedef bool (*MatchFun) (void* key1, void* key2);
-
-  // The default capacity.  This is used by the call sites which want
-  // to pass in a non-default AllocationPolicy but want to use the
-  // default value of capacity specified by the implementation.
-  static const uint32_t kDefaultHashMapCapacity = 8;
-
-  // initial_capacity is the size of the initial hash map;
-  // it must be a power of 2 (and thus must not be 0).
-  TemplateHashMapImpl(MatchFun match,
-                      uint32_t capacity = kDefaultHashMapCapacity,
-                      AllocationPolicy allocator = AllocationPolicy());
-
-  ~TemplateHashMapImpl();
-
-  // HashMap entries are (key, value, hash) triplets.
-  // Some clients may not need to use the value slot
-  // (e.g. implementers of sets, where the key is the value).
-  struct Entry {
-    void* key;
-    void* value;
-    uint32_t hash;  // The full hash value for key
-    int order;  // If you never remove entries this is the insertion order.
-  };
-
-  // If an entry with matching key is found, returns that entry.
-  // Otherwise, NULL is returned.
-  Entry* Lookup(void* key, uint32_t hash) const;
-
-  // If an entry with matching key is found, returns that entry.
-  // If no matching entry is found, a new entry is inserted with
-  // corresponding key, key hash, and NULL value.
-  Entry* LookupOrInsert(void* key, uint32_t hash,
-                        AllocationPolicy allocator = AllocationPolicy());
-
-  // Removes the entry with matching key.
-  // It returns the value of the deleted entry
-  // or null if there is no value for such key.
-  void* Remove(void* key, uint32_t hash);
-
-  // Empties the hash map (occupancy() == 0).
-  void Clear();
-
-  // The number of (non-empty) entries in the table.
-  uint32_t occupancy() const { return occupancy_; }
-
-  // The capacity of the table. The implementation
-  // makes sure that occupancy is at most 80% of
-  // the table capacity.
-  uint32_t capacity() const { return capacity_; }
-
-  // Iteration
-  //
-  // for (Entry* p = map.Start(); p != NULL; p = map.Next(p)) {
-  //   ...
-  // }
-  //
-  // If entries are inserted during iteration, the effect of
-  // calling Next() is undefined.
-  Entry* Start() const;
-  Entry* Next(Entry* p) const;
-
-  // Some match functions defined for convenience.
-  static bool PointersMatch(void* key1, void* key2) {
-    return key1 == key2;
-  }
-
- private:
-  MatchFun match_;
-  Entry* map_;
-  uint32_t capacity_;
-  uint32_t occupancy_;
-
-  Entry* map_end() const { return map_ + capacity_; }
-  Entry* Probe(void* key, uint32_t hash) const;
-  void Initialize(uint32_t capacity, AllocationPolicy allocator);
-  void Resize(AllocationPolicy allocator);
-};
-
-typedef TemplateHashMapImpl<FreeStoreAllocationPolicy> HashMap;
-
-template<class AllocationPolicy>
-TemplateHashMapImpl<AllocationPolicy>::TemplateHashMapImpl(
-    MatchFun match, uint32_t initial_capacity, AllocationPolicy allocator) {
-  match_ = match;
-  Initialize(initial_capacity, allocator);
-}
-
-
-template<class AllocationPolicy>
-TemplateHashMapImpl<AllocationPolicy>::~TemplateHashMapImpl() {
-  AllocationPolicy::Delete(map_);
-}
-
-
-template <class AllocationPolicy>
-typename TemplateHashMapImpl<AllocationPolicy>::Entry*
-TemplateHashMapImpl<AllocationPolicy>::Lookup(void* key, uint32_t hash) const {
-  Entry* p = Probe(key, hash);
-  return p->key != NULL ? p : NULL;
-}
-
-
-template <class AllocationPolicy>
-typename TemplateHashMapImpl<AllocationPolicy>::Entry*
-TemplateHashMapImpl<AllocationPolicy>::LookupOrInsert(
-    void* key, uint32_t hash, AllocationPolicy allocator) {
-  // Find a matching entry.
-  Entry* p = Probe(key, hash);
-  if (p->key != NULL) {
-    return p;
-  }
-
-  // No entry found; insert one.
-  p->key = key;
-  p->value = NULL;
-  p->hash = hash;
-  p->order = occupancy_;
-  occupancy_++;
-
-  // Grow the map if we reached >= 80% occupancy.
-  if (occupancy_ + occupancy_ / 4 >= capacity_) {
-    Resize(allocator);
-    p = Probe(key, hash);
-  }
-
-  return p;
-}
-
-
-template<class AllocationPolicy>
-void* TemplateHashMapImpl<AllocationPolicy>::Remove(void* key, uint32_t hash) {
-  // Lookup the entry for the key to remove.
-  Entry* p = Probe(key, hash);
-  if (p->key == NULL) {
-    // Key not found nothing to remove.
-    return NULL;
-  }
-
-  void* value = p->value;
-  // To remove an entry we need to ensure that it does not create an empty
-  // entry that will cause the search for another entry to stop too soon. If all
-  // the entries between the entry to remove and the next empty slot have their
-  // initial position inside this interval, clearing the entry to remove will
-  // not break the search. If, while searching for the next empty entry, an
-  // entry is encountered which does not have its initial position between the
-  // entry to remove and the position looked at, then this entry can be moved to
-  // the place of the entry to remove without breaking the search for it. The
-  // entry made vacant by this move is now the entry to remove and the process
-  // starts over.
-  // Algorithm from http://en.wikipedia.org/wiki/Open_addressing.
-
-  // This guarantees loop termination as there is at least one empty entry so
-  // eventually the removed entry will have an empty entry after it.
-  DCHECK(occupancy_ < capacity_);
-
-  // p is the candidate entry to clear. q is used to scan forwards.
-  Entry* q = p;  // Start at the entry to remove.
-  while (true) {
-    // Move q to the next entry.
-    q = q + 1;
-    if (q == map_end()) {
-      q = map_;
-    }
-
-    // All entries between p and q have their initial position between p and q
-    // and the entry p can be cleared without breaking the search for these
-    // entries.
-    if (q->key == NULL) {
-      break;
-    }
-
-    // Find the initial position for the entry at position q.
-    Entry* r = map_ + (q->hash & (capacity_ - 1));
-
-    // If the entry at position q has its initial position outside the range
-    // between p and q it can be moved forward to position p and will still be
-    // found. There is now a new candidate entry for clearing.
-    if ((q > p && (r <= p || r > q)) ||
-        (q < p && (r <= p && r > q))) {
-      *p = *q;
-      p = q;
-    }
-  }
-
-  // Clear the entry which is allowed to en emptied.
-  p->key = NULL;
-  occupancy_--;
-  return value;
-}
-
-
-template<class AllocationPolicy>
-void TemplateHashMapImpl<AllocationPolicy>::Clear() {
-  // Mark all entries as empty.
-  const Entry* end = map_end();
-  for (Entry* p = map_; p < end; p++) {
-    p->key = NULL;
-  }
-  occupancy_ = 0;
-}
-
-
-template<class AllocationPolicy>
-typename TemplateHashMapImpl<AllocationPolicy>::Entry*
-    TemplateHashMapImpl<AllocationPolicy>::Start() const {
-  return Next(map_ - 1);
-}
-
-
-template<class AllocationPolicy>
-typename TemplateHashMapImpl<AllocationPolicy>::Entry*
-    TemplateHashMapImpl<AllocationPolicy>::Next(Entry* p) const {
-  const Entry* end = map_end();
-  DCHECK(map_ - 1 <= p && p < end);
-  for (p++; p < end; p++) {
-    if (p->key != NULL) {
-      return p;
-    }
-  }
-  return NULL;
-}
-
-
-template <class AllocationPolicy>
-typename TemplateHashMapImpl<AllocationPolicy>::Entry*
-TemplateHashMapImpl<AllocationPolicy>::Probe(void* key, uint32_t hash) const {
-  DCHECK(key != NULL);
-
-  DCHECK(base::bits::IsPowerOfTwo32(capacity_));
-  Entry* p = map_ + (hash & (capacity_ - 1));
-  const Entry* end = map_end();
-  DCHECK(map_ <= p && p < end);
-
-  DCHECK(occupancy_ < capacity_);  // Guarantees loop termination.
-  while (p->key != NULL && (hash != p->hash || !match_(key, p->key))) {
-    p++;
-    if (p >= end) {
-      p = map_;
-    }
-  }
-
-  return p;
-}
-
-
-template<class AllocationPolicy>
-void TemplateHashMapImpl<AllocationPolicy>::Initialize(
-    uint32_t capacity, AllocationPolicy allocator) {
-  DCHECK(base::bits::IsPowerOfTwo32(capacity));
-  map_ = reinterpret_cast<Entry*>(allocator.New(capacity * sizeof(Entry)));
-  if (map_ == NULL) {
-    v8::internal::FatalProcessOutOfMemory("HashMap::Initialize");
-    return;
-  }
-  capacity_ = capacity;
-  Clear();
-}
-
-
-template<class AllocationPolicy>
-void TemplateHashMapImpl<AllocationPolicy>::Resize(AllocationPolicy allocator) {
-  Entry* map = map_;
-  uint32_t n = occupancy_;
-
-  // Allocate larger map.
-  Initialize(capacity_ * 2, allocator);
-
-  // Rehash all current entries.
-  for (Entry* p = map; n > 0; p++) {
-    if (p->key != NULL) {
-      Entry* entry = LookupOrInsert(p->key, p->hash, allocator);
-      entry->value = p->value;
-      entry->order = p->order;
-      n--;
-    }
-  }
-
-  // Delete old map.
-  AllocationPolicy::Delete(map);
-}
-
-
-// A hash map for pointer keys and values with an STL-like interface.
-template<class Key, class Value, class AllocationPolicy>
-class TemplateHashMap: private TemplateHashMapImpl<AllocationPolicy> {
- public:
-  STATIC_ASSERT(sizeof(Key*) == sizeof(void*));  // NOLINT
-  STATIC_ASSERT(sizeof(Value*) == sizeof(void*));  // NOLINT
-  struct value_type {
-    Key* first;
-    Value* second;
-  };
-
-  class Iterator {
-   public:
-    Iterator& operator++() {
-      entry_ = map_->Next(entry_);
-      return *this;
-    }
-
-    value_type* operator->() { return reinterpret_cast<value_type*>(entry_); }
-    bool operator!=(const Iterator& other) { return  entry_ != other.entry_; }
-
-   private:
-    Iterator(const TemplateHashMapImpl<AllocationPolicy>* map,
-             typename TemplateHashMapImpl<AllocationPolicy>::Entry* entry) :
-        map_(map), entry_(entry) { }
-
-    const TemplateHashMapImpl<AllocationPolicy>* map_;
-    typename TemplateHashMapImpl<AllocationPolicy>::Entry* entry_;
-
-    friend class TemplateHashMap;
-  };
-
-  TemplateHashMap(
-      typename TemplateHashMapImpl<AllocationPolicy>::MatchFun match,
-      AllocationPolicy allocator = AllocationPolicy())
-        : TemplateHashMapImpl<AllocationPolicy>(
-            match,
-            TemplateHashMapImpl<AllocationPolicy>::kDefaultHashMapCapacity,
-            allocator) { }
-
-  Iterator begin() const { return Iterator(this, this->Start()); }
-  Iterator end() const { return Iterator(this, NULL); }
-  Iterator find(Key* key, bool insert = false,
-                AllocationPolicy allocator = AllocationPolicy()) {
-    if (insert) {
-      return Iterator(this, this->LookupOrInsert(key, key->Hash(), allocator));
-    }
-    return Iterator(this, this->Lookup(key, key->Hash()));
-  }
-};
-
-}  // namespace internal
-}  // namespace v8
-
-#endif  // V8_HASHMAP_H_
diff --git a/src/heap-symbols.h b/src/heap-symbols.h
index f019ace..03b25ee 100644
--- a/src/heap-symbols.h
+++ b/src/heap-symbols.h
@@ -12,6 +12,16 @@
   V(arguments_string, "arguments")                                 \
   V(Arguments_string, "Arguments")                                 \
   V(Array_string, "Array")                                         \
+  V(arguments_to_string, "[object Arguments]")                     \
+  V(array_to_string, "[object Array]")                             \
+  V(boolean_to_string, "[object Boolean]")                         \
+  V(date_to_string, "[object Date]")                               \
+  V(error_to_string, "[object Error]")                             \
+  V(function_to_string, "[object Function]")                       \
+  V(number_to_string, "[object Number]")                           \
+  V(object_to_string, "[object Object]")                           \
+  V(regexp_to_string, "[object RegExp]")                           \
+  V(string_to_string, "[object String]")                           \
   V(bind_string, "bind")                                           \
   V(bool16x8_string, "bool16x8")                                   \
   V(Bool16x8_string, "Bool16x8")                                   \
@@ -22,6 +32,7 @@
   V(boolean_string, "boolean")                                     \
   V(Boolean_string, "Boolean")                                     \
   V(bound__string, "bound ")                                       \
+  V(buffer_string, "buffer")                                       \
   V(byte_length_string, "byteLength")                              \
   V(byte_offset_string, "byteOffset")                              \
   V(call_string, "call")                                           \
@@ -30,6 +41,7 @@
   V(cell_value_string, "%cell_value")                              \
   V(char_at_string, "CharAt")                                      \
   V(closure_string, "(closure)")                                   \
+  V(column_string, "column")                                       \
   V(compare_ic_string, "==")                                       \
   V(configurable_string, "configurable")                           \
   V(constructor_string, "constructor")                             \
@@ -78,6 +90,7 @@
   V(KeyedStoreMonomorphic_string, "KeyedStoreMonomorphic")         \
   V(last_index_string, "lastIndex")                                \
   V(length_string, "length")                                       \
+  V(line_string, "line")                                           \
   V(Map_string, "Map")                                             \
   V(minus_infinity_string, "-Infinity")                            \
   V(minus_zero_string, "-0")                                       \
@@ -91,6 +104,7 @@
   V(object_string, "object")                                       \
   V(Object_string, "Object")                                       \
   V(ownKeys_string, "ownKeys")                                     \
+  V(position_string, "position")                                   \
   V(preventExtensions_string, "preventExtensions")                 \
   V(private_api_string, "private_api")                             \
   V(Promise_string, "Promise")                                     \
@@ -99,11 +113,13 @@
   V(Proxy_string, "Proxy")                                         \
   V(query_colon_string, "(?:)")                                    \
   V(RegExp_string, "RegExp")                                       \
+  V(script_string, "script")                                       \
   V(setPrototypeOf_string, "setPrototypeOf")                       \
   V(set_string, "set")                                             \
   V(Set_string, "Set")                                             \
   V(source_mapping_url_string, "source_mapping_url")               \
   V(source_string, "source")                                       \
+  V(sourceText_string, "sourceText")                               \
   V(source_url_string, "source_url")                               \
   V(stack_string, "stack")                                         \
   V(strict_compare_ic_string, "===")                               \
@@ -139,6 +155,8 @@
   V(call_site_position_symbol)              \
   V(call_site_receiver_symbol)              \
   V(call_site_strict_symbol)                \
+  V(call_site_wasm_obj_symbol)              \
+  V(call_site_wasm_func_index_symbol)       \
   V(class_end_position_symbol)              \
   V(class_start_position_symbol)            \
   V(detailed_stack_trace_symbol)            \
@@ -149,7 +167,6 @@
   V(formatted_stack_trace_symbol)           \
   V(frozen_symbol)                          \
   V(hash_code_symbol)                       \
-  V(hidden_properties_symbol)               \
   V(home_object_symbol)                     \
   V(internal_error_symbol)                  \
   V(intl_impl_object_symbol)                \
@@ -162,16 +179,16 @@
   V(nonextensible_symbol)                   \
   V(normal_ic_symbol)                       \
   V(not_mapped_symbol)                      \
-  V(observed_symbol)                        \
   V(premonomorphic_symbol)                  \
   V(promise_combined_deferred_symbol)       \
   V(promise_debug_marker_symbol)            \
+  V(promise_deferred_reactions_symbol)      \
+  V(promise_fulfill_reactions_symbol)       \
   V(promise_has_handler_symbol)             \
-  V(promise_on_resolve_symbol)              \
-  V(promise_on_reject_symbol)               \
   V(promise_raw_symbol)                     \
-  V(promise_status_symbol)                  \
-  V(promise_value_symbol)                   \
+  V(promise_reject_reactions_symbol)        \
+  V(promise_result_symbol)                  \
+  V(promise_state_symbol)                   \
   V(sealed_symbol)                          \
   V(stack_trace_symbol)                     \
   V(strict_function_transition_symbol)      \
diff --git a/src/heap/array-buffer-tracker-inl.h b/src/heap/array-buffer-tracker-inl.h
new file mode 100644
index 0000000..a176744
--- /dev/null
+++ b/src/heap/array-buffer-tracker-inl.h
@@ -0,0 +1,67 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/conversions-inl.h"
+#include "src/heap/array-buffer-tracker.h"
+#include "src/heap/heap.h"
+#include "src/objects.h"
+
+namespace v8 {
+namespace internal {
+
+void ArrayBufferTracker::RegisterNew(Heap* heap, JSArrayBuffer* buffer) {
+  void* data = buffer->backing_store();
+  if (!data) return;
+
+  size_t length = NumberToSize(heap->isolate(), buffer->byte_length());
+  Page* page = Page::FromAddress(buffer->address());
+  {
+    base::LockGuard<base::Mutex> guard(page->mutex());
+    LocalArrayBufferTracker* tracker = page->local_tracker();
+    if (tracker == nullptr) {
+      page->AllocateLocalTracker();
+      tracker = page->local_tracker();
+    }
+    DCHECK_NOT_NULL(tracker);
+    tracker->Add(buffer, std::make_pair(data, length));
+  }
+  // We may go over the limit of externally allocated memory here. We call the
+  // api function to trigger a GC in this case.
+  reinterpret_cast<v8::Isolate*>(heap->isolate())
+      ->AdjustAmountOfExternalAllocatedMemory(length);
+}
+
+void ArrayBufferTracker::Unregister(Heap* heap, JSArrayBuffer* buffer) {
+  void* data = buffer->backing_store();
+  if (!data) return;
+
+  Page* page = Page::FromAddress(buffer->address());
+  size_t length = 0;
+  {
+    base::LockGuard<base::Mutex> guard(page->mutex());
+    LocalArrayBufferTracker* tracker = page->local_tracker();
+    DCHECK_NOT_NULL(tracker);
+    length = tracker->Remove(buffer).second;
+  }
+  heap->update_external_memory(-static_cast<intptr_t>(length));
+}
+
+void LocalArrayBufferTracker::Add(Key key, const Value& value) {
+  auto ret = array_buffers_.insert(std::make_pair(key, value));
+  USE(ret);
+  // Check that we indeed inserted a new value and did not overwrite an existing
+  // one (which would be a bug).
+  DCHECK(ret.second);
+}
+
+LocalArrayBufferTracker::Value LocalArrayBufferTracker::Remove(Key key) {
+  TrackingMap::iterator it = array_buffers_.find(key);
+  DCHECK(it != array_buffers_.end());
+  Value value = it->second;
+  array_buffers_.erase(it);
+  return value;
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/heap/array-buffer-tracker.cc b/src/heap/array-buffer-tracker.cc
index 6e389c1..a870b35 100644
--- a/src/heap/array-buffer-tracker.cc
+++ b/src/heap/array-buffer-tracker.cc
@@ -3,138 +3,133 @@
 // found in the LICENSE file.
 
 #include "src/heap/array-buffer-tracker.h"
+#include "src/heap/array-buffer-tracker-inl.h"
 #include "src/heap/heap.h"
-#include "src/isolate.h"
-#include "src/objects.h"
-#include "src/objects-inl.h"
-#include "src/v8.h"
 
 namespace v8 {
 namespace internal {
 
-ArrayBufferTracker::~ArrayBufferTracker() {
-  Isolate* isolate = heap()->isolate();
+LocalArrayBufferTracker::~LocalArrayBufferTracker() {
+  CHECK(array_buffers_.empty());
+}
+
+template <LocalArrayBufferTracker::FreeMode free_mode>
+void LocalArrayBufferTracker::Free() {
   size_t freed_memory = 0;
-  for (auto& buffer : live_array_buffers_) {
-    isolate->array_buffer_allocator()->Free(buffer.first, buffer.second);
-    freed_memory += buffer.second;
-  }
-  for (auto& buffer : live_array_buffers_for_scavenge_) {
-    isolate->array_buffer_allocator()->Free(buffer.first, buffer.second);
-    freed_memory += buffer.second;
-  }
-  live_array_buffers_.clear();
-  live_array_buffers_for_scavenge_.clear();
-  not_yet_discovered_array_buffers_.clear();
-  not_yet_discovered_array_buffers_for_scavenge_.clear();
-
-  if (freed_memory > 0) {
-    heap()->update_amount_of_external_allocated_memory(
-        -static_cast<int64_t>(freed_memory));
-  }
-}
-
-
-void ArrayBufferTracker::RegisterNew(JSArrayBuffer* buffer) {
-  void* data = buffer->backing_store();
-  if (!data) return;
-
-  bool in_new_space = heap()->InNewSpace(buffer);
-  size_t length = NumberToSize(heap()->isolate(), buffer->byte_length());
-  if (in_new_space) {
-    live_array_buffers_for_scavenge_[data] = length;
-  } else {
-    live_array_buffers_[data] = length;
-  }
-
-  // We may go over the limit of externally allocated memory here. We call the
-  // api function to trigger a GC in this case.
-  reinterpret_cast<v8::Isolate*>(heap()->isolate())
-      ->AdjustAmountOfExternalAllocatedMemory(length);
-}
-
-
-void ArrayBufferTracker::Unregister(JSArrayBuffer* buffer) {
-  void* data = buffer->backing_store();
-  if (!data) return;
-
-  bool in_new_space = heap()->InNewSpace(buffer);
-  std::map<void*, size_t>* live_buffers =
-      in_new_space ? &live_array_buffers_for_scavenge_ : &live_array_buffers_;
-  std::map<void*, size_t>* not_yet_discovered_buffers =
-      in_new_space ? &not_yet_discovered_array_buffers_for_scavenge_
-                   : &not_yet_discovered_array_buffers_;
-
-  DCHECK(live_buffers->count(data) > 0);
-
-  size_t length = (*live_buffers)[data];
-  live_buffers->erase(data);
-  not_yet_discovered_buffers->erase(data);
-
-  heap()->update_amount_of_external_allocated_memory(
-      -static_cast<int64_t>(length));
-}
-
-
-void ArrayBufferTracker::MarkLive(JSArrayBuffer* buffer) {
-  base::LockGuard<base::Mutex> guard(&mutex_);
-  void* data = buffer->backing_store();
-
-  // ArrayBuffer might be in the middle of being constructed.
-  if (data == heap()->undefined_value()) return;
-  if (heap()->InNewSpace(buffer)) {
-    not_yet_discovered_array_buffers_for_scavenge_.erase(data);
-  } else {
-    not_yet_discovered_array_buffers_.erase(data);
-  }
-}
-
-
-void ArrayBufferTracker::FreeDead(bool from_scavenge) {
-  size_t freed_memory = 0;
-  Isolate* isolate = heap()->isolate();
-  for (auto& buffer : not_yet_discovered_array_buffers_for_scavenge_) {
-    isolate->array_buffer_allocator()->Free(buffer.first, buffer.second);
-    freed_memory += buffer.second;
-    live_array_buffers_for_scavenge_.erase(buffer.first);
-  }
-
-  if (!from_scavenge) {
-    for (auto& buffer : not_yet_discovered_array_buffers_) {
-      isolate->array_buffer_allocator()->Free(buffer.first, buffer.second);
-      freed_memory += buffer.second;
-      live_array_buffers_.erase(buffer.first);
+  for (TrackingMap::iterator it = array_buffers_.begin();
+       it != array_buffers_.end();) {
+    if ((free_mode == kFreeAll) ||
+        Marking::IsWhite(Marking::MarkBitFrom(it->first))) {
+      heap_->isolate()->array_buffer_allocator()->Free(it->second.first,
+                                                       it->second.second);
+      freed_memory += it->second.second;
+      it = array_buffers_.erase(it);
+    } else {
+      it++;
     }
   }
-
-  not_yet_discovered_array_buffers_for_scavenge_ =
-      live_array_buffers_for_scavenge_;
-  if (!from_scavenge) not_yet_discovered_array_buffers_ = live_array_buffers_;
-
-  // Do not call through the api as this code is triggered while doing a GC.
-  heap()->update_amount_of_external_allocated_memory(
-      -static_cast<int64_t>(freed_memory));
+  if (freed_memory > 0) {
+    heap_->update_external_memory_concurrently_freed(
+        static_cast<intptr_t>(freed_memory));
+  }
 }
 
-
-void ArrayBufferTracker::PrepareDiscoveryInNewSpace() {
-  not_yet_discovered_array_buffers_for_scavenge_ =
-      live_array_buffers_for_scavenge_;
+template <typename Callback>
+void LocalArrayBufferTracker::Process(Callback callback) {
+  JSArrayBuffer* new_buffer = nullptr;
+  size_t freed_memory = 0;
+  for (TrackingMap::iterator it = array_buffers_.begin();
+       it != array_buffers_.end();) {
+    const CallbackResult result = callback(it->first, &new_buffer);
+    if (result == kKeepEntry) {
+      it++;
+    } else if (result == kUpdateEntry) {
+      DCHECK_NOT_NULL(new_buffer);
+      Page* target_page = Page::FromAddress(new_buffer->address());
+      // We need to lock the target page because we cannot guarantee
+      // exclusive access to new space pages.
+      if (target_page->InNewSpace()) target_page->mutex()->Lock();
+      LocalArrayBufferTracker* tracker = target_page->local_tracker();
+      if (tracker == nullptr) {
+        target_page->AllocateLocalTracker();
+        tracker = target_page->local_tracker();
+      }
+      DCHECK_NOT_NULL(tracker);
+      tracker->Add(new_buffer, it->second);
+      if (target_page->InNewSpace()) target_page->mutex()->Unlock();
+      it = array_buffers_.erase(it);
+    } else if (result == kRemoveEntry) {
+      heap_->isolate()->array_buffer_allocator()->Free(it->second.first,
+                                                       it->second.second);
+      freed_memory += it->second.second;
+      it = array_buffers_.erase(it);
+    } else {
+      UNREACHABLE();
+    }
+  }
+  if (freed_memory > 0) {
+    heap_->update_external_memory_concurrently_freed(
+        static_cast<intptr_t>(freed_memory));
+  }
 }
 
+void ArrayBufferTracker::FreeDeadInNewSpace(Heap* heap) {
+  DCHECK_EQ(heap->gc_state(), Heap::HeapState::SCAVENGE);
+  for (Page* page : NewSpacePageRange(heap->new_space()->FromSpaceStart(),
+                                      heap->new_space()->FromSpaceEnd())) {
+    bool empty = ProcessBuffers(page, kUpdateForwardedRemoveOthers);
+    CHECK(empty);
+  }
+  heap->account_external_memory_concurrently_freed();
+}
 
-void ArrayBufferTracker::Promote(JSArrayBuffer* buffer) {
-  base::LockGuard<base::Mutex> guard(&mutex_);
+void ArrayBufferTracker::FreeDead(Page* page) {
+  // Callers need to ensure having the page lock.
+  LocalArrayBufferTracker* tracker = page->local_tracker();
+  if (tracker == nullptr) return;
+  DCHECK(!page->SweepingDone());
+  tracker->Free<LocalArrayBufferTracker::kFreeDead>();
+  if (tracker->IsEmpty()) {
+    page->ReleaseLocalTracker();
+  }
+}
 
-  if (buffer->is_external()) return;
-  void* data = buffer->backing_store();
-  if (!data) return;
-  // ArrayBuffer might be in the middle of being constructed.
-  if (data == heap()->undefined_value()) return;
-  DCHECK(live_array_buffers_for_scavenge_.count(data) > 0);
-  live_array_buffers_[data] = live_array_buffers_for_scavenge_[data];
-  live_array_buffers_for_scavenge_.erase(data);
-  not_yet_discovered_array_buffers_for_scavenge_.erase(data);
+void ArrayBufferTracker::FreeAll(Page* page) {
+  LocalArrayBufferTracker* tracker = page->local_tracker();
+  if (tracker == nullptr) return;
+  tracker->Free<LocalArrayBufferTracker::kFreeAll>();
+  if (tracker->IsEmpty()) {
+    page->ReleaseLocalTracker();
+  }
+}
+
+bool ArrayBufferTracker::ProcessBuffers(Page* page, ProcessingMode mode) {
+  LocalArrayBufferTracker* tracker = page->local_tracker();
+  if (tracker == nullptr) return true;
+
+  DCHECK(page->SweepingDone());
+  tracker->Process(
+      [mode](JSArrayBuffer* old_buffer, JSArrayBuffer** new_buffer) {
+        MapWord map_word = old_buffer->map_word();
+        if (map_word.IsForwardingAddress()) {
+          *new_buffer = JSArrayBuffer::cast(map_word.ToForwardingAddress());
+          return LocalArrayBufferTracker::kUpdateEntry;
+        }
+        return mode == kUpdateForwardedKeepOthers
+                   ? LocalArrayBufferTracker::kKeepEntry
+                   : LocalArrayBufferTracker::kRemoveEntry;
+      });
+  return tracker->IsEmpty();
+}
+
+bool ArrayBufferTracker::IsTracked(JSArrayBuffer* buffer) {
+  Page* page = Page::FromAddress(buffer->address());
+  {
+    base::LockGuard<base::Mutex> guard(page->mutex());
+    LocalArrayBufferTracker* tracker = page->local_tracker();
+    if (tracker == nullptr) return false;
+    return tracker->IsTracked(buffer);
+  }
 }
 
 }  // namespace internal
diff --git a/src/heap/array-buffer-tracker.h b/src/heap/array-buffer-tracker.h
index 6130003..b015aa0 100644
--- a/src/heap/array-buffer-tracker.h
+++ b/src/heap/array-buffer-tracker.h
@@ -5,71 +5,97 @@
 #ifndef V8_HEAP_ARRAY_BUFFER_TRACKER_H_
 #define V8_HEAP_ARRAY_BUFFER_TRACKER_H_
 
-#include <map>
+#include <unordered_map>
 
+#include "src/allocation.h"
 #include "src/base/platform/mutex.h"
 #include "src/globals.h"
 
 namespace v8 {
 namespace internal {
 
-// Forward declarations.
 class Heap;
 class JSArrayBuffer;
+class Page;
 
-class ArrayBufferTracker {
+class ArrayBufferTracker : public AllStatic {
  public:
-  explicit ArrayBufferTracker(Heap* heap) : heap_(heap) {}
-  ~ArrayBufferTracker();
-
-  inline Heap* heap() { return heap_; }
+  enum ProcessingMode {
+    kUpdateForwardedRemoveOthers,
+    kUpdateForwardedKeepOthers,
+  };
 
   // The following methods are used to track raw C++ pointers to externally
   // allocated memory used as backing store in live array buffers.
 
-  // A new ArrayBuffer was created with |data| as backing store.
-  void RegisterNew(JSArrayBuffer* buffer);
+  // Register/unregister a new JSArrayBuffer |buffer| for tracking. Guards all
+  // access to the tracker by taking the page lock for the corresponding page.
+  inline static void RegisterNew(Heap* heap, JSArrayBuffer* buffer);
+  inline static void Unregister(Heap* heap, JSArrayBuffer* buffer);
 
-  // The backing store |data| is no longer owned by V8.
-  void Unregister(JSArrayBuffer* buffer);
+  // Frees all backing store pointers for dead JSArrayBuffers in new space.
+  // Does not take any locks and can only be called during Scavenge.
+  static void FreeDeadInNewSpace(Heap* heap);
 
-  // A live ArrayBuffer was discovered during marking/scavenge.
-  void MarkLive(JSArrayBuffer* buffer);
+  // Frees all backing store pointers for dead JSArrayBuffer on a given page.
+  // Requires marking information to be present. Requires the page lock to be
+  // taken by the caller.
+  static void FreeDead(Page* page);
 
-  // Frees all backing store pointers that weren't discovered in the previous
-  // marking or scavenge phase.
-  void FreeDead(bool from_scavenge);
+  // Frees all remaining, live or dead, array buffers on a page. Only useful
+  // during tear down.
+  static void FreeAll(Page* page);
 
-  // Prepare for a new scavenge phase. A new marking phase is implicitly
-  // prepared by finishing the previous one.
-  void PrepareDiscoveryInNewSpace();
+  // Processes all array buffers on a given page. |mode| specifies the action
+  // to perform on the buffers. Returns whether the tracker is empty or not.
+  static bool ProcessBuffers(Page* page, ProcessingMode mode);
 
-  // An ArrayBuffer moved from new space to old space.
-  void Promote(JSArrayBuffer* buffer);
+  // Returns whether a buffer is currently tracked.
+  static bool IsTracked(JSArrayBuffer* buffer);
+};
+
+// LocalArrayBufferTracker tracks internalized array buffers.
+//
+// Never use directly but instead always call through |ArrayBufferTracker|.
+class LocalArrayBufferTracker {
+ public:
+  typedef std::pair<void*, size_t> Value;
+  typedef JSArrayBuffer* Key;
+
+  enum CallbackResult { kKeepEntry, kUpdateEntry, kRemoveEntry };
+  enum FreeMode { kFreeDead, kFreeAll };
+
+  explicit LocalArrayBufferTracker(Heap* heap) : heap_(heap) {}
+  ~LocalArrayBufferTracker();
+
+  inline void Add(Key key, const Value& value);
+  inline Value Remove(Key key);
+
+  // Frees up array buffers determined by |free_mode|.
+  template <FreeMode free_mode>
+  void Free();
+
+  // Processes buffers one by one. The CallbackResult of the callback decides
+  // what action to take on the buffer.
+  //
+  // Callback should be of type:
+  //   CallbackResult fn(JSArrayBuffer* buffer, JSArrayBuffer** new_buffer);
+  template <typename Callback>
+  inline void Process(Callback callback);
+
+  bool IsEmpty() { return array_buffers_.empty(); }
+
+  bool IsTracked(Key key) {
+    return array_buffers_.find(key) != array_buffers_.end();
+  }
 
  private:
-  base::Mutex mutex_;
+  typedef std::unordered_map<Key, Value> TrackingMap;
+
   Heap* heap_;
-
-  // |live_array_buffers_| maps externally allocated memory used as backing
-  // store for ArrayBuffers to the length of the respective memory blocks.
-  //
-  // At the beginning of mark/compact, |not_yet_discovered_array_buffers_| is
-  // a copy of |live_array_buffers_| and we remove pointers as we discover live
-  // ArrayBuffer objects during marking. At the end of mark/compact, the
-  // remaining memory blocks can be freed.
-  std::map<void*, size_t> live_array_buffers_;
-  std::map<void*, size_t> not_yet_discovered_array_buffers_;
-
-  // To be able to free memory held by ArrayBuffers during scavenge as well, we
-  // have a separate list of allocated memory held by ArrayBuffers in new space.
-  //
-  // Since mark/compact also evacuates the new space, all pointers in the
-  // |live_array_buffers_for_scavenge_| list are also in the
-  // |live_array_buffers_| list.
-  std::map<void*, size_t> live_array_buffers_for_scavenge_;
-  std::map<void*, size_t> not_yet_discovered_array_buffers_for_scavenge_;
+  TrackingMap array_buffers_;
 };
+
 }  // namespace internal
 }  // namespace v8
 #endif  // V8_HEAP_ARRAY_BUFFER_TRACKER_H_
diff --git a/src/heap/gc-idle-time-handler.cc b/src/heap/gc-idle-time-handler.cc
index 972dfa6..0c411f7 100644
--- a/src/heap/gc-idle-time-handler.cc
+++ b/src/heap/gc-idle-time-handler.cc
@@ -41,8 +41,7 @@
 void GCIdleTimeHeapState::Print() {
   PrintF("contexts_disposed=%d ", contexts_disposed);
   PrintF("contexts_disposal_rate=%f ", contexts_disposal_rate);
-  PrintF("size_of_objects=%" V8_SIZET_PREFIX V8_PTR_PREFIX "d ",
-         size_of_objects);
+  PrintF("size_of_objects=%" PRIuS " ", size_of_objects);
   PrintF("incremental_marking_stopped=%d ", incremental_marking_stopped);
 }
 
diff --git a/src/heap/gc-tracer.cc b/src/heap/gc-tracer.cc
index 3c46f52..2b1f06a 100644
--- a/src/heap/gc-tracer.cc
+++ b/src/heap/gc-tracer.cc
@@ -26,10 +26,8 @@
   start_time_ = tracer_->heap_->MonotonicallyIncreasingTimeInMs();
   // TODO(cbruni): remove once we fully moved to a trace-based system.
   if (FLAG_runtime_call_stats) {
-    RuntimeCallStats* stats =
-        tracer_->heap_->isolate()->counters()->runtime_call_stats();
-    timer_.Initialize(&stats->GC, stats->current_timer());
-    stats->Enter(&timer_);
+    RuntimeCallStats::Enter(tracer_->heap_->isolate(), &timer_,
+                            &RuntimeCallStats::GC);
   }
 }
 
@@ -40,7 +38,7 @@
       tracer_->heap_->MonotonicallyIncreasingTimeInMs() - start_time_;
   // TODO(cbruni): remove once we fully moved to a trace-based system.
   if (FLAG_runtime_call_stats) {
-    tracer_->heap_->isolate()->counters()->runtime_call_stats()->Leave(&timer_);
+    RuntimeCallStats::Leave(tracer_->heap_->isolate(), &timer_);
   }
 }
 
@@ -137,6 +135,26 @@
   previous_ = previous_incremental_mark_compactor_event_ = current_;
 }
 
+void GCTracer::ResetForTesting() {
+  cumulative_incremental_marking_steps_ = 0.0;
+  cumulative_incremental_marking_bytes_ = 0.0;
+  cumulative_incremental_marking_duration_ = 0.0;
+  cumulative_pure_incremental_marking_duration_ = 0.0;
+  longest_incremental_marking_step_ = 0.0;
+  cumulative_incremental_marking_finalization_steps_ = 0.0;
+  cumulative_incremental_marking_finalization_duration_ = 0.0;
+  longest_incremental_marking_finalization_step_ = 0.0;
+  cumulative_marking_duration_ = 0.0;
+  cumulative_sweeping_duration_ = 0.0;
+  allocation_time_ms_ = 0.0;
+  new_space_allocation_counter_bytes_ = 0.0;
+  old_generation_allocation_counter_bytes_ = 0.0;
+  allocation_duration_since_gc_ = 0.0;
+  new_space_allocation_in_bytes_since_gc_ = 0.0;
+  old_generation_allocation_in_bytes_since_gc_ = 0.0;
+  combined_mark_compact_speed_cache_ = 0.0;
+  start_counter_ = 0;
+}
 
 void GCTracer::Start(GarbageCollector collector, const char* gc_reason,
                      const char* collector_reason) {
@@ -164,7 +182,7 @@
   current_.reduce_memory = heap_->ShouldReduceMemory();
   current_.start_time = start_time;
   current_.start_object_size = heap_->SizeOfObjects();
-  current_.start_memory_size = heap_->isolate()->memory_allocator()->Size();
+  current_.start_memory_size = heap_->memory_allocator()->Size();
   current_.start_holes_size = CountTotalHolesSize(heap_);
   current_.new_space_object_size =
       heap_->new_space()->top() - heap_->new_space()->bottom();
@@ -190,10 +208,7 @@
       start_time, used_memory);
   // TODO(cbruni): remove once we fully moved to a trace-based system.
   if (FLAG_runtime_call_stats) {
-    RuntimeCallStats* stats =
-        heap_->isolate()->counters()->runtime_call_stats();
-    timer_.Initialize(&stats->GC, stats->current_timer());
-    stats->Enter(&timer_);
+    RuntimeCallStats::Enter(heap_->isolate(), &timer_, &RuntimeCallStats::GC);
   }
 }
 
@@ -214,7 +229,7 @@
 
   current_.end_time = heap_->MonotonicallyIncreasingTimeInMs();
   current_.end_object_size = heap_->SizeOfObjects();
-  current_.end_memory_size = heap_->isolate()->memory_allocator()->Size();
+  current_.end_memory_size = heap_->memory_allocator()->Size();
   current_.end_holes_size = CountTotalHolesSize(heap_);
   current_.survived_new_space_object_size = heap_->SurvivedNewSpaceObjectSize();
 
@@ -303,7 +318,7 @@
   cumulative_incremental_marking_finalization_duration_ = 0.0;
   // TODO(cbruni): remove once we fully moved to a trace-based system.
   if (FLAG_runtime_call_stats) {
-    heap_->isolate()->counters()->runtime_call_stats()->Leave(&timer_);
+    RuntimeCallStats::Leave(heap_->isolate(), &timer_);
   }
 }
 
@@ -411,7 +426,7 @@
 
 void GCTracer::Print() const {
   if (FLAG_trace_gc) {
-    PrintIsolate(heap_->isolate(), "");
+    PrintIsolate(heap_->isolate(), "%s", "");
   }
   Output("%8.0f ms: ", heap_->isolate()->time_millis_since_init());
 
@@ -480,20 +495,20 @@
                    "steps_count=%d "
                    "steps_took=%.1f "
                    "scavenge_throughput=%.f "
-                   "total_size_before=%" V8_PTR_PREFIX
-                   "d "
-                   "total_size_after=%" V8_PTR_PREFIX
-                   "d "
-                   "holes_size_before=%" V8_PTR_PREFIX
-                   "d "
-                   "holes_size_after=%" V8_PTR_PREFIX
-                   "d "
-                   "allocated=%" V8_PTR_PREFIX
-                   "d "
-                   "promoted=%" V8_PTR_PREFIX
-                   "d "
-                   "semi_space_copied=%" V8_PTR_PREFIX
-                   "d "
+                   "total_size_before=%" V8PRIdPTR
+                   " "
+                   "total_size_after=%" V8PRIdPTR
+                   " "
+                   "holes_size_before=%" V8PRIdPTR
+                   " "
+                   "holes_size_after=%" V8PRIdPTR
+                   " "
+                   "allocated=%" V8PRIdPTR
+                   " "
+                   "promoted=%" V8PRIdPTR
+                   " "
+                   "semi_space_copied=%" V8PRIdPTR
+                   " "
                    "nodes_died_in_new=%d "
                    "nodes_copied_in_new=%d "
                    "nodes_promoted=%d "
@@ -555,7 +570,6 @@
           "evacuate.clean_up=%.1f "
           "evacuate.copy=%.1f "
           "evacuate.update_pointers=%.1f "
-          "evacuate.update_pointers.between_evacuated=%.1f "
           "evacuate.update_pointers.to_evacuated=%.1f "
           "evacuate.update_pointers.to_new=%.1f "
           "evacuate.update_pointers.weak=%.1f "
@@ -586,20 +600,20 @@
           "finalization_steps_took=%.1f "
           "finalization_longest_step=%.1f "
           "incremental_marking_throughput=%.f "
-          "total_size_before=%" V8_PTR_PREFIX
-          "d "
-          "total_size_after=%" V8_PTR_PREFIX
-          "d "
-          "holes_size_before=%" V8_PTR_PREFIX
-          "d "
-          "holes_size_after=%" V8_PTR_PREFIX
-          "d "
-          "allocated=%" V8_PTR_PREFIX
-          "d "
-          "promoted=%" V8_PTR_PREFIX
-          "d "
-          "semi_space_copied=%" V8_PTR_PREFIX
-          "d "
+          "total_size_before=%" V8PRIdPTR
+          " "
+          "total_size_after=%" V8PRIdPTR
+          " "
+          "holes_size_before=%" V8PRIdPTR
+          " "
+          "holes_size_after=%" V8PRIdPTR
+          " "
+          "allocated=%" V8PRIdPTR
+          " "
+          "promoted=%" V8PRIdPTR
+          " "
+          "semi_space_copied=%" V8PRIdPTR
+          " "
           "nodes_died_in_new=%d "
           "nodes_copied_in_new=%d "
           "nodes_promoted=%d "
@@ -628,7 +642,6 @@
           current_.scopes[Scope::MC_EVACUATE_CLEAN_UP],
           current_.scopes[Scope::MC_EVACUATE_COPY],
           current_.scopes[Scope::MC_EVACUATE_UPDATE_POINTERS],
-          current_.scopes[Scope::MC_EVACUATE_UPDATE_POINTERS_BETWEEN_EVACUATED],
           current_.scopes[Scope::MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED],
           current_.scopes[Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW],
           current_.scopes[Scope::MC_EVACUATE_UPDATE_POINTERS_WEAK],
diff --git a/src/heap/gc-tracer.h b/src/heap/gc-tracer.h
index 9ea3cce..ed07750 100644
--- a/src/heap/gc-tracer.h
+++ b/src/heap/gc-tracer.h
@@ -5,6 +5,7 @@
 #ifndef V8_HEAP_GC_TRACER_H_
 #define V8_HEAP_GC_TRACER_H_
 
+#include "src/base/compiler-specific.h"
 #include "src/base/platform/platform.h"
 #include "src/counters.h"
 #include "src/globals.h"
@@ -76,7 +77,6 @@
   F(MC_EVACUATE_CLEAN_UP)                          \
   F(MC_EVACUATE_COPY)                              \
   F(MC_EVACUATE_UPDATE_POINTERS)                   \
-  F(MC_EVACUATE_UPDATE_POINTERS_BETWEEN_EVACUATED) \
   F(MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED)      \
   F(MC_EVACUATE_UPDATE_POINTERS_TO_NEW)            \
   F(MC_EVACUATE_UPDATE_POINTERS_WEAK)              \
@@ -112,7 +112,7 @@
 #define TRACE_GC(tracer, scope_id)                             \
   GCTracer::Scope::ScopeId gc_tracer_scope_id(scope_id);       \
   GCTracer::Scope gc_tracer_scope(tracer, gc_tracer_scope_id); \
-  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"),                \
+  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.gc"),             \
                GCTracer::Scope::Name(gc_tracer_scope_id))
 
 // GCTracer collects and prints ONE line after each garbage collector
@@ -372,6 +372,8 @@
   static double AverageSpeed(const RingBuffer<BytesAndDuration>& buffer,
                              const BytesAndDuration& initial, double time_ms);
 
+  void ResetForTesting();
+
  private:
   // Print one detailed trace line in name=value format.
   // TODO(ernstm): Move to Heap.
@@ -383,7 +385,7 @@
 
   // Prints a line and also adds it to the heap's ring buffer so that
   // it can be included in later crash dumps.
-  void Output(const char* format, ...) const;
+  void PRINTF_FORMAT(2, 3) Output(const char* format, ...) const;
 
   void ClearMarkCompactStatistics() {
     cumulative_incremental_marking_steps_ = 0;
diff --git a/src/heap/heap-inl.h b/src/heap/heap-inl.h
index e31d3d6..d6c509e 100644
--- a/src/heap/heap-inl.h
+++ b/src/heap/heap-inl.h
@@ -393,21 +393,48 @@
   return OldGenerationSpaceAvailable() < 0;
 }
 
-
+template <PromotionMode promotion_mode>
 bool Heap::ShouldBePromoted(Address old_address, int object_size) {
-  NewSpacePage* page = NewSpacePage::FromAddress(old_address);
+  Page* page = Page::FromAddress(old_address);
   Address age_mark = new_space_.age_mark();
+
+  if (promotion_mode == PROMOTE_MARKED) {
+    MarkBit mark_bit = Marking::MarkBitFrom(old_address);
+    if (!Marking::IsWhite(mark_bit)) {
+      return true;
+    }
+  }
+
   return page->IsFlagSet(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK) &&
          (!page->ContainsLimit(age_mark) || old_address < age_mark);
 }
 
+PromotionMode Heap::CurrentPromotionMode() {
+  if (incremental_marking()->IsMarking()) {
+    return PROMOTE_MARKED;
+  } else {
+    return DEFAULT_PROMOTION;
+  }
+}
+
 void Heap::RecordWrite(Object* object, int offset, Object* o) {
   if (!InNewSpace(o) || !object->IsHeapObject() || InNewSpace(object)) {
     return;
   }
-  Page* page = Page::FromAddress(reinterpret_cast<Address>(object));
-  Address slot = HeapObject::cast(object)->address() + offset;
-  RememberedSet<OLD_TO_NEW>::Insert(page, slot);
+  RememberedSet<OLD_TO_NEW>::Insert(
+      Page::FromAddress(reinterpret_cast<Address>(object)),
+      HeapObject::cast(object)->address() + offset);
+}
+
+void Heap::RecordFixedArrayElements(FixedArray* array, int offset, int length) {
+  if (InNewSpace(array)) return;
+  Page* page = Page::FromAddress(reinterpret_cast<Address>(array));
+  for (int i = 0; i < length; i++) {
+    if (!InNewSpace(array->get(offset + i))) continue;
+    RememberedSet<OLD_TO_NEW>::Insert(
+        page,
+        reinterpret_cast<Address>(array->RawFieldOfElementAt(offset + i)));
+  }
 }
 
 
@@ -449,6 +476,31 @@
             static_cast<size_t>(byte_size / kPointerSize));
 }
 
+bool Heap::PurgeLeftTrimmedObject(Object** object) {
+  HeapObject* current = reinterpret_cast<HeapObject*>(*object);
+  const MapWord map_word = current->map_word();
+  if (current->IsFiller() && !map_word.IsForwardingAddress()) {
+#ifdef DEBUG
+    // We need to find a FixedArrayBase map after walking the fillers.
+    while (current->IsFiller()) {
+      Address next = reinterpret_cast<Address>(current);
+      if (current->map() == one_pointer_filler_map()) {
+        next += kPointerSize;
+      } else if (current->map() == two_pointer_filler_map()) {
+        next += 2 * kPointerSize;
+      } else {
+        next += current->Size();
+      }
+      current = reinterpret_cast<HeapObject*>(next);
+    }
+    DCHECK(current->IsFixedArrayBase());
+#endif  // DEBUG
+    *object = nullptr;
+    return true;
+  }
+  return false;
+}
+
 template <Heap::FindMementoMode mode>
 AllocationMemento* Heap::FindAllocationMemento(HeapObject* object) {
   // Check if there is potentially a memento behind the object. If
@@ -457,7 +509,7 @@
   Address object_address = object->address();
   Address memento_address = object_address + object->Size();
   Address last_memento_word_address = memento_address + kPointerSize;
-  if (!NewSpacePage::OnSamePage(object_address, last_memento_word_address)) {
+  if (!Page::OnSamePage(object_address, last_memento_word_address)) {
     return nullptr;
   }
   HeapObject* candidate = HeapObject::FromAddress(memento_address);
@@ -485,7 +537,7 @@
       top = NewSpaceTop();
       DCHECK(memento_address == top ||
              memento_address + HeapObject::kHeaderSize <= top ||
-             !NewSpacePage::OnSamePage(memento_address, top - 1));
+             !Page::OnSamePage(memento_address, top - 1));
       if ((memento_address != top) && memento_candidate->IsValid()) {
         return memento_candidate;
       }
@@ -499,7 +551,7 @@
 
 template <Heap::UpdateAllocationSiteMode mode>
 void Heap::UpdateAllocationSite(HeapObject* object,
-                                HashMap* pretenuring_feedback) {
+                                base::HashMap* pretenuring_feedback) {
   DCHECK(InFromSpace(object));
   if (!FLAG_allocation_site_pretenuring ||
       !AllocationSite::CanTrack(object->map()->instance_type()))
@@ -527,7 +579,7 @@
     // to dereference the allocation site and rather have to postpone all checks
     // till actually merging the data.
     Address key = memento_candidate->GetAllocationSiteUnchecked();
-    HashMap::Entry* e =
+    base::HashMap::Entry* e =
         pretenuring_feedback->LookupOrInsert(key, ObjectHash(key));
     DCHECK(e != nullptr);
     (*bit_cast<intptr_t*>(&e->value))++;
@@ -585,12 +637,12 @@
   for (int i = 0; i < new_space_strings_.length(); ++i) {
     Object* obj = Object::cast(new_space_strings_[i]);
     DCHECK(heap_->InNewSpace(obj));
-    DCHECK(obj != heap_->the_hole_value());
+    DCHECK(!obj->IsTheHole(heap_->isolate()));
   }
   for (int i = 0; i < old_space_strings_.length(); ++i) {
     Object* obj = Object::cast(old_space_strings_[i]);
     DCHECK(!heap_->InNewSpace(obj));
-    DCHECK(obj != heap_->the_hole_value());
+    DCHECK(!obj->IsTheHole(heap_->isolate()));
   }
 #endif
 }
@@ -674,30 +726,41 @@
   return last_id;
 }
 
-
 void Heap::SetArgumentsAdaptorDeoptPCOffset(int pc_offset) {
   DCHECK(arguments_adaptor_deopt_pc_offset() == Smi::FromInt(0));
   set_arguments_adaptor_deopt_pc_offset(Smi::FromInt(pc_offset));
 }
 
-
 void Heap::SetConstructStubDeoptPCOffset(int pc_offset) {
   DCHECK(construct_stub_deopt_pc_offset() == Smi::FromInt(0));
   set_construct_stub_deopt_pc_offset(Smi::FromInt(pc_offset));
 }
 
-
 void Heap::SetGetterStubDeoptPCOffset(int pc_offset) {
   DCHECK(getter_stub_deopt_pc_offset() == Smi::FromInt(0));
   set_getter_stub_deopt_pc_offset(Smi::FromInt(pc_offset));
 }
 
-
 void Heap::SetSetterStubDeoptPCOffset(int pc_offset) {
   DCHECK(setter_stub_deopt_pc_offset() == Smi::FromInt(0));
   set_setter_stub_deopt_pc_offset(Smi::FromInt(pc_offset));
 }
 
+void Heap::SetInterpreterEntryReturnPCOffset(int pc_offset) {
+  DCHECK(interpreter_entry_return_pc_offset() == Smi::FromInt(0));
+  set_interpreter_entry_return_pc_offset(Smi::FromInt(pc_offset));
+}
+
+int Heap::GetNextTemplateSerialNumber() {
+  int next_serial_number = next_template_serial_number()->value() + 1;
+  set_next_template_serial_number(Smi::FromInt(next_serial_number));
+  return next_serial_number;
+}
+
+void Heap::SetSerializedTemplates(FixedArray* templates) {
+  DCHECK_EQ(empty_fixed_array(), serialized_templates());
+  set_serialized_templates(templates);
+}
 
 AlwaysAllocateScope::AlwaysAllocateScope(Isolate* isolate)
     : heap_(isolate->heap()) {
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
index c3f56ac..c59a8d3 100644
--- a/src/heap/heap.cc
+++ b/src/heap/heap.cc
@@ -17,7 +17,7 @@
 #include "src/debug/debug.h"
 #include "src/deoptimizer.h"
 #include "src/global-handles.h"
-#include "src/heap/array-buffer-tracker.h"
+#include "src/heap/array-buffer-tracker-inl.h"
 #include "src/heap/gc-idle-time-handler.h"
 #include "src/heap/gc-tracer.h"
 #include "src/heap/incremental-marking.h"
@@ -32,7 +32,6 @@
 #include "src/heap/scavenger-inl.h"
 #include "src/heap/store-buffer.h"
 #include "src/interpreter/interpreter.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/regexp/jsregexp.h"
 #include "src/runtime-profiler.h"
 #include "src/snapshot/natives.h"
@@ -69,9 +68,10 @@
 };
 
 Heap::Heap()
-    : amount_of_external_allocated_memory_(0),
-      amount_of_external_allocated_memory_at_last_global_gc_(0),
-      isolate_(NULL),
+    : external_memory_(0),
+      external_memory_limit_(kExternalAllocationLimit),
+      external_memory_at_last_mark_compact_(0),
+      isolate_(nullptr),
       code_range_size_(0),
       // semispace_size_ should be a power of 2 and old_generation_size_ should
       // be a multiple of Page::kPageSize.
@@ -115,7 +115,6 @@
       inline_allocation_disabled_(false),
       total_regexp_code_generated_(0),
       tracer_(nullptr),
-      embedder_heap_tracer_(nullptr),
       high_survival_rate_period_length_(0),
       promoted_objects_size_(0),
       promotion_ratio_(0),
@@ -136,6 +135,7 @@
       last_gc_time_(0.0),
       scavenge_collector_(nullptr),
       mark_compact_collector_(nullptr),
+      memory_allocator_(nullptr),
       store_buffer_(this),
       incremental_marking_(nullptr),
       gc_idle_time_handler_(nullptr),
@@ -157,13 +157,9 @@
       current_gc_flags_(Heap::kNoGCFlags),
       current_gc_callback_flags_(GCCallbackFlags::kNoGCCallbackFlags),
       external_string_table_(this),
-      chunks_queued_for_free_(NULL),
-      concurrent_unmapping_tasks_active_(0),
-      pending_unmapping_tasks_semaphore_(0),
       gc_callbacks_depth_(0),
       deserialization_complete_(false),
       strong_roots_list_(NULL),
-      array_buffer_tracker_(NULL),
       heap_iterator_depth_(0),
       force_oom_(false) {
 // Allow build-time customization of the max semispace size. Building
@@ -191,8 +187,14 @@
 intptr_t Heap::Capacity() {
   if (!HasBeenSetUp()) return 0;
 
-  return new_space_.Capacity() + old_space_->Capacity() +
-         code_space_->Capacity() + map_space_->Capacity();
+  return new_space_.Capacity() + OldGenerationCapacity();
+}
+
+intptr_t Heap::OldGenerationCapacity() {
+  if (!HasBeenSetUp()) return 0;
+
+  return old_space_->Capacity() + code_space_->Capacity() +
+         map_space_->Capacity() + lo_space_->SizeOfObjects();
 }
 
 
@@ -225,7 +227,7 @@
 intptr_t Heap::CommittedMemoryExecutable() {
   if (!HasBeenSetUp()) return 0;
 
-  return isolate()->memory_allocator()->SizeExecutable();
+  return memory_allocator()->SizeExecutable();
 }
 
 
@@ -296,7 +298,7 @@
   // and does not count available bytes already in the old space or code
   // space.  Undercounting is safe---we may get an unrequested full GC when
   // a scavenge would have succeeded.
-  if (isolate_->memory_allocator()->MaxAvailable() <= new_space_.Size()) {
+  if (memory_allocator()->MaxAvailable() <= new_space_.Size()) {
     isolate_->counters()
         ->gc_compactor_caused_by_oldspace_exhaustion()
         ->Increment();
@@ -336,61 +338,58 @@
 
 void Heap::PrintShortHeapStatistics() {
   if (!FLAG_trace_gc_verbose) return;
-  PrintIsolate(isolate_, "Memory allocator,   used: %6" V8_PTR_PREFIX
-                         "d KB"
-                         ", available: %6" V8_PTR_PREFIX "d KB\n",
-               isolate_->memory_allocator()->Size() / KB,
-               isolate_->memory_allocator()->Available() / KB);
-  PrintIsolate(isolate_, "New space,          used: %6" V8_PTR_PREFIX
-                         "d KB"
-                         ", available: %6" V8_PTR_PREFIX
-                         "d KB"
-                         ", committed: %6" V8_PTR_PREFIX "d KB\n",
+  PrintIsolate(isolate_, "Memory allocator,   used: %6" V8PRIdPTR
+                         " KB, available: %6" V8PRIdPTR " KB\n",
+               memory_allocator()->Size() / KB,
+               memory_allocator()->Available() / KB);
+  PrintIsolate(isolate_, "New space,          used: %6" V8PRIdPTR
+                         " KB"
+                         ", available: %6" V8PRIdPTR
+                         " KB"
+                         ", committed: %6" V8PRIdPTR " KB\n",
                new_space_.Size() / KB, new_space_.Available() / KB,
                new_space_.CommittedMemory() / KB);
-  PrintIsolate(isolate_, "Old space,          used: %6" V8_PTR_PREFIX
-                         "d KB"
-                         ", available: %6" V8_PTR_PREFIX
-                         "d KB"
-                         ", committed: %6" V8_PTR_PREFIX "d KB\n",
+  PrintIsolate(isolate_, "Old space,          used: %6" V8PRIdPTR
+                         " KB"
+                         ", available: %6" V8PRIdPTR
+                         " KB"
+                         ", committed: %6" V8PRIdPTR " KB\n",
                old_space_->SizeOfObjects() / KB, old_space_->Available() / KB,
                old_space_->CommittedMemory() / KB);
-  PrintIsolate(isolate_, "Code space,         used: %6" V8_PTR_PREFIX
-                         "d KB"
-                         ", available: %6" V8_PTR_PREFIX
-                         "d KB"
-                         ", committed: %6" V8_PTR_PREFIX "d KB\n",
+  PrintIsolate(isolate_, "Code space,         used: %6" V8PRIdPTR
+                         " KB"
+                         ", available: %6" V8PRIdPTR
+                         " KB"
+                         ", committed: %6" V8PRIdPTR " KB\n",
                code_space_->SizeOfObjects() / KB, code_space_->Available() / KB,
                code_space_->CommittedMemory() / KB);
-  PrintIsolate(isolate_, "Map space,          used: %6" V8_PTR_PREFIX
-                         "d KB"
-                         ", available: %6" V8_PTR_PREFIX
-                         "d KB"
-                         ", committed: %6" V8_PTR_PREFIX "d KB\n",
+  PrintIsolate(isolate_, "Map space,          used: %6" V8PRIdPTR
+                         " KB"
+                         ", available: %6" V8PRIdPTR
+                         " KB"
+                         ", committed: %6" V8PRIdPTR " KB\n",
                map_space_->SizeOfObjects() / KB, map_space_->Available() / KB,
                map_space_->CommittedMemory() / KB);
-  PrintIsolate(isolate_, "Large object space, used: %6" V8_PTR_PREFIX
-                         "d KB"
-                         ", available: %6" V8_PTR_PREFIX
-                         "d KB"
-                         ", committed: %6" V8_PTR_PREFIX "d KB\n",
+  PrintIsolate(isolate_, "Large object space, used: %6" V8PRIdPTR
+                         " KB"
+                         ", available: %6" V8PRIdPTR
+                         " KB"
+                         ", committed: %6" V8PRIdPTR " KB\n",
                lo_space_->SizeOfObjects() / KB, lo_space_->Available() / KB,
                lo_space_->CommittedMemory() / KB);
-  PrintIsolate(isolate_, "All spaces,         used: %6" V8_PTR_PREFIX
-                         "d KB"
-                         ", available: %6" V8_PTR_PREFIX
-                         "d KB"
-                         ", committed: %6" V8_PTR_PREFIX "d KB\n",
+  PrintIsolate(isolate_, "All spaces,         used: %6" V8PRIdPTR
+                         " KB"
+                         ", available: %6" V8PRIdPTR
+                         " KB"
+                         ", committed: %6" V8PRIdPTR " KB\n",
                this->SizeOfObjects() / KB, this->Available() / KB,
                this->CommittedMemory() / KB);
-  PrintIsolate(
-      isolate_, "External memory reported: %6" V8_PTR_PREFIX "d KB\n",
-      static_cast<intptr_t>(amount_of_external_allocated_memory_ / KB));
+  PrintIsolate(isolate_, "External memory reported: %6" V8PRIdPTR " KB\n",
+               static_cast<intptr_t>(external_memory_ / KB));
   PrintIsolate(isolate_, "Total time spent in GC  : %.1f ms\n",
                total_gc_time_ms_);
 }
 
-
 // TODO(1238405): Combine the infrastructure for --heap-stats and
 // --log-gc to avoid the complicated preprocessor and flag testing.
 void Heap::ReportStatisticsAfterGC() {
@@ -501,11 +500,10 @@
   }
 }
 
-
 void Heap::MergeAllocationSitePretenuringFeedback(
-    const HashMap& local_pretenuring_feedback) {
+    const base::HashMap& local_pretenuring_feedback) {
   AllocationSite* site = nullptr;
-  for (HashMap::Entry* local_entry = local_pretenuring_feedback.Start();
+  for (base::HashMap::Entry* local_entry = local_pretenuring_feedback.Start();
        local_entry != nullptr;
        local_entry = local_pretenuring_feedback.Next(local_entry)) {
     site = reinterpret_cast<AllocationSite*>(local_entry->key);
@@ -534,8 +532,8 @@
 class Heap::PretenuringScope {
  public:
   explicit PretenuringScope(Heap* heap) : heap_(heap) {
-    heap_->global_pretenuring_feedback_ =
-        new HashMap(HashMap::PointersMatch, kInitialFeedbackCapacity);
+    heap_->global_pretenuring_feedback_ = new base::HashMap(
+        base::HashMap::PointersMatch, kInitialFeedbackCapacity);
   }
 
   ~PretenuringScope() {
@@ -561,7 +559,7 @@
 
     // Step 1: Digest feedback for recorded allocation sites.
     bool maximum_size_scavenge = MaximumSizeScavenge();
-    for (HashMap::Entry* e = global_pretenuring_feedback_->Start();
+    for (base::HashMap::Entry* e = global_pretenuring_feedback_->Start();
          e != nullptr; e = global_pretenuring_feedback_->Next(e)) {
       allocation_sites++;
       site = reinterpret_cast<AllocationSite*>(e->key);
@@ -762,10 +760,10 @@
       // If GC happens while adding a stack trace to the weak fixed array,
       // which has been copied into a larger backing store, we may run into
       // a stack trace that has already been preprocessed. Guard against this.
-      if (!maybe_code->IsCode()) break;
-      Code* code = Code::cast(maybe_code);
+      if (!maybe_code->IsAbstractCode()) break;
+      AbstractCode* abstract_code = AbstractCode::cast(maybe_code);
       int offset = Smi::cast(elements->get(j + 3))->value();
-      int pos = code->SourcePosition(offset);
+      int pos = abstract_code->SourcePosition(offset);
       elements->set(j + 2, Smi::FromInt(pos));
     }
   }
@@ -818,10 +816,10 @@
     PrintF("[IncrementalMarking] (%s).\n", gc_reason);
   }
 
-  TRACE_GC(tracer(), GCTracer::Scope::MC_INCREMENTAL_FINALIZE);
   HistogramTimerScope incremental_marking_scope(
       isolate()->counters()->gc_incremental_marking_finalize());
   TRACE_EVENT0("v8", "V8.GCIncrementalMarkingFinalize");
+  TRACE_GC(tracer(), GCTracer::Scope::MC_INCREMENTAL_FINALIZE);
 
   {
     GCCallbacksScope scope(this);
@@ -941,7 +939,7 @@
   // may be uninitialized memory behind top. We fill the remainder of the page
   // with a filler.
   Address to_top = new_space_.top();
-  NewSpacePage* page = NewSpacePage::FromAddress(to_top - kPointerSize);
+  Page* page = Page::FromAddress(to_top - kPointerSize);
   if (page->Contains(to_top)) {
     int remaining_in_page = static_cast<int>(page->area_end() - to_top);
     CreateFillerObjectAt(to_top, remaining_in_page, ClearRecordedSlots::kNo);
@@ -976,10 +974,6 @@
       !ShouldAbortIncrementalMarking() && !incremental_marking()->IsStopped() &&
       !incremental_marking()->should_hurry() && FLAG_incremental_marking &&
       OldGenerationAllocationLimitReached()) {
-    // Make progress in incremental marking.
-    const intptr_t kStepSizeWhenDelayedByScavenge = 1 * MB;
-    incremental_marking()->Step(kStepSizeWhenDelayedByScavenge,
-                                IncrementalMarking::NO_GC_VIA_STACK_GUARD);
     if (!incremental_marking()->IsComplete() &&
         !mark_compact_collector()->marking_deque_.IsEmpty() &&
         !FLAG_gc_global) {
@@ -1102,13 +1096,7 @@
   DCHECK(array->map() != fixed_cow_array_map());
   Object** dst_objects = array->data_start() + dst_index;
   MemMove(dst_objects, array->data_start() + src_index, len * kPointerSize);
-  if (!InNewSpace(array)) {
-    for (int i = 0; i < len; i++) {
-      RecordWrite(array, array->OffsetOfElementAt(dst_index + i),
-                  dst_objects[i]);
-    }
-  }
-  incremental_marking()->IterateBlackObject(array);
+  FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(this, array, dst_index, len);
 }
 
 
@@ -1120,9 +1108,11 @@
     // Visit all HeapObject pointers in [start, end).
     for (Object** p = start; p < end; p++) {
       if ((*p)->IsHeapObject()) {
+        HeapObject* object = HeapObject::cast(*p);
+        Isolate* isolate = object->GetIsolate();
         // Check that the string is actually internalized.
-        CHECK((*p)->IsTheHole() || (*p)->IsUndefined() ||
-              (*p)->IsInternalizedString());
+        CHECK(object->IsTheHole(isolate) || object->IsUndefined(isolate) ||
+              object->IsInternalizedString());
       }
     }
   }
@@ -1221,15 +1211,15 @@
   }
 
   Object* context = native_contexts_list();
-  while (!context->IsUndefined()) {
+  while (!context->IsUndefined(isolate())) {
     // GC can happen when the context is not fully initialized,
     // so the cache can be undefined.
     Object* cache =
         Context::cast(context)->get(Context::NORMALIZED_MAP_CACHE_INDEX);
-    if (!cache->IsUndefined()) {
+    if (!cache->IsUndefined(isolate())) {
       NormalizedMapCache::cast(cache)->Clear();
     }
-    context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
+    context = Context::cast(context)->next_context_link();
   }
 }
 
@@ -1349,8 +1339,8 @@
   intptr_t old_gen_size = PromotedSpaceSizeOfObjects();
   if (collector == MARK_COMPACTOR) {
     // Register the amount of external allocated memory.
-    amount_of_external_allocated_memory_at_last_global_gc_ =
-        amount_of_external_allocated_memory_;
+    external_memory_at_last_mark_compact_ = external_memory_;
+    external_memory_limit_ = external_memory_ + kExternalAllocationLimit;
     SetOldGenerationAllocationLimit(old_gen_size, gc_speed, mutator_speed);
   } else if (HasLowYoungGenerationAllocationRate() &&
              old_generation_size_configured_) {
@@ -1475,10 +1465,6 @@
   CompletelyClearInstanceofCache();
 
   FlushNumberStringCache();
-  if (FLAG_cleanup_code_caches_at_gc) {
-    polymorphic_code_cache()->set_cache(undefined_value());
-  }
-
   ClearNormalizedMapCaches();
 }
 
@@ -1545,15 +1531,12 @@
   if (object->IsSmi()) return false;
   HeapObject* heap_object = HeapObject::cast(object);
   if (!object->IsJSObject()) return false;
-  Object* obj_constructor = (JSObject::cast(object))->map()->GetConstructor();
-  if (!obj_constructor->IsJSFunction()) return false;
-  JSFunction* constructor = JSFunction::cast(obj_constructor);
-  if (!constructor->shared()->IsApiFunction()) return false;
-  if (constructor != nullptr &&
-      constructor->initial_map() == heap_object->map()) {
-    return true;
-  }
-  return false;
+  JSObject* js_object = JSObject::cast(object);
+  if (!js_object->WasConstructedFromApiFunction()) return false;
+  JSFunction* constructor =
+      JSFunction::cast(js_object->map()->GetConstructor());
+
+  return constructor->initial_map() == heap_object->map();
 }
 
 
@@ -1565,7 +1548,8 @@
   front_ = rear_ =
       reinterpret_cast<struct Entry*>(heap_->new_space()->ToSpaceEnd());
   limit_ = reinterpret_cast<struct Entry*>(
-      Page::FromAllocationTop(reinterpret_cast<Address>(rear_))->area_start());
+      Page::FromAllocationAreaAddress(reinterpret_cast<Address>(rear_))
+          ->area_start());
   emergency_stack_ = NULL;
 }
 
@@ -1573,7 +1557,7 @@
 void PromotionQueue::RelocateQueueHead() {
   DCHECK(emergency_stack_ == NULL);
 
-  Page* p = Page::FromAllocationTop(reinterpret_cast<Address>(rear_));
+  Page* p = Page::FromAllocationAreaAddress(reinterpret_cast<Address>(rear_));
   struct Entry* head_start = rear_;
   struct Entry* head_end =
       Min(front_, reinterpret_cast<struct Entry*>(p->area_end()));
@@ -1627,6 +1611,8 @@
   // Pause the inline allocation steps.
   PauseAllocationObserversScope pause_observers(this);
 
+  mark_compact_collector()->sweeper().EnsureNewSpaceCompleted();
+
 #ifdef VERIFY_HEAP
   if (FLAG_verify_heap) VerifyNonPointerSpacePointers(this);
 #endif
@@ -1641,7 +1627,12 @@
 
   scavenge_collector_->SelectScavengingVisitorsTable();
 
-  array_buffer_tracker()->PrepareDiscoveryInNewSpace();
+  if (UsingEmbedderHeapTracer()) {
+    // Register found wrappers with embedder so it can add them to its marking
+    // deque and correctly manage the case when v8 scavenger collects the
+    // wrappers by either keeping wrappables alive, or cleaning marking deque.
+    mark_compact_collector()->RegisterWrappersWithEmbedderHeapTracer();
+  }
 
   // Flip the semispaces.  After flipping, to space is empty, from space has
   // live objects.
@@ -1668,6 +1659,7 @@
   Address new_space_front = new_space_.ToSpaceStart();
   promotion_queue_.Initialize();
 
+  PromotionMode promotion_mode = CurrentPromotionMode();
   ScavengeVisitor scavenge_visitor(this);
 
   if (FLAG_scavenge_reclaim_unmodified_objects) {
@@ -1684,8 +1676,21 @@
   {
     // Copy objects reachable from the old generation.
     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_OLD_TO_NEW_POINTERS);
-    RememberedSet<OLD_TO_NEW>::IterateWithWrapper(this,
-                                                  Scavenger::ScavengeObject);
+    RememberedSet<OLD_TO_NEW>::Iterate(this, [this](Address addr) {
+      return Scavenger::CheckAndScavengeObject(this, addr);
+    });
+
+    RememberedSet<OLD_TO_NEW>::IterateTyped(
+        this, [this](SlotType type, Address host_addr, Address addr) {
+          return UpdateTypedSlotHelper::UpdateTypedSlot(
+              isolate(), type, addr, [this](Object** addr) {
+                // We expect that objects referenced by code are long living.
+                // If we do not force promotion, then we need to clear
+                // old_to_new slots in dead code objects after mark-compact.
+                return Scavenger::CheckAndScavengeObject(
+                    this, reinterpret_cast<Address>(addr));
+              });
+        });
   }
 
   {
@@ -1707,7 +1712,8 @@
 
   {
     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_SEMISPACE);
-    new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
+    new_space_front =
+        DoScavenge(&scavenge_visitor, new_space_front, promotion_mode);
   }
 
   if (FLAG_scavenge_reclaim_unmodified_objects) {
@@ -1716,12 +1722,14 @@
 
     isolate()->global_handles()->IterateNewSpaceWeakUnmodifiedRoots(
         &scavenge_visitor);
-    new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
+    new_space_front =
+        DoScavenge(&scavenge_visitor, new_space_front, promotion_mode);
   } else {
     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_OBJECT_GROUPS);
     while (isolate()->global_handles()->IterateObjectGroups(
         &scavenge_visitor, &IsUnscavengedHeapObject)) {
-      new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
+      new_space_front =
+          DoScavenge(&scavenge_visitor, new_space_front, promotion_mode);
     }
     isolate()->global_handles()->RemoveObjectGroups();
     isolate()->global_handles()->RemoveImplicitRefGroups();
@@ -1731,7 +1739,8 @@
 
     isolate()->global_handles()->IterateNewSpaceWeakIndependentRoots(
         &scavenge_visitor);
-    new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
+    new_space_front =
+        DoScavenge(&scavenge_visitor, new_space_front, promotion_mode);
   }
 
   UpdateNewSpaceReferencesInExternalStringTable(
@@ -1749,7 +1758,7 @@
   // Set age mark.
   new_space_.set_age_mark(new_space_.top());
 
-  array_buffer_tracker()->FreeDead(true);
+  ArrayBufferTracker::FreeDeadInNewSpace(this);
 
   // Update how much has survived scavenge.
   IncrementYoungSurvivorsCounter(static_cast<int>(
@@ -1778,12 +1787,6 @@
 
 void Heap::UpdateNewSpaceReferencesInExternalStringTable(
     ExternalStringTableUpdaterCallback updater_func) {
-#ifdef VERIFY_HEAP
-  if (FLAG_verify_heap) {
-    external_string_table_.Verify();
-  }
-#endif
-
   if (external_string_table_.new_space_strings_.is_empty()) return;
 
   Object** start = &external_string_table_.new_space_strings_[0];
@@ -1791,7 +1794,6 @@
   Object** last = start;
 
   for (Object** p = start; p < end; ++p) {
-    DCHECK(InFromSpace(*p));
     String* target = updater_func(this, p);
 
     if (target == NULL) continue;
@@ -1920,22 +1922,29 @@
   external_string_table_.Iterate(&external_string_table_visitor);
 }
 
-
 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor,
-                         Address new_space_front) {
+                         Address new_space_front,
+                         PromotionMode promotion_mode) {
   do {
     SemiSpace::AssertValidRange(new_space_front, new_space_.top());
     // The addresses new_space_front and new_space_.top() define a
     // queue of unprocessed copied objects.  Process them until the
     // queue is empty.
     while (new_space_front != new_space_.top()) {
-      if (!NewSpacePage::IsAtEnd(new_space_front)) {
+      if (!Page::IsAlignedToPageSize(new_space_front)) {
         HeapObject* object = HeapObject::FromAddress(new_space_front);
-        new_space_front +=
-            StaticScavengeVisitor::IterateBody(object->map(), object);
+        if (promotion_mode == PROMOTE_MARKED) {
+          new_space_front += StaticScavengeVisitor<PROMOTE_MARKED>::IterateBody(
+              object->map(), object);
+        } else {
+          new_space_front +=
+              StaticScavengeVisitor<DEFAULT_PROMOTION>::IterateBody(
+                  object->map(), object);
+        }
       } else {
-        new_space_front =
-            NewSpacePage::FromLimit(new_space_front)->next_page()->area_start();
+        new_space_front = Page::FromAllocationAreaAddress(new_space_front)
+                              ->next_page()
+                              ->area_start();
       }
     }
 
@@ -2035,12 +2044,12 @@
 
 
 void Heap::RegisterNewArrayBuffer(JSArrayBuffer* buffer) {
-  return array_buffer_tracker()->RegisterNew(buffer);
+  ArrayBufferTracker::RegisterNew(this, buffer);
 }
 
 
 void Heap::UnregisterArrayBuffer(JSArrayBuffer* buffer) {
-  return array_buffer_tracker()->Unregister(buffer);
+  ArrayBufferTracker::Unregister(this, buffer);
 }
 
 
@@ -2174,6 +2183,21 @@
 #undef STRUCT_TABLE_ELEMENT
 };
 
+namespace {
+
+void FinalizePartialMap(Heap* heap, Map* map) {
+  map->set_code_cache(heap->empty_fixed_array());
+  map->set_dependent_code(DependentCode::cast(heap->empty_fixed_array()));
+  map->set_raw_transitions(Smi::FromInt(0));
+  map->set_instance_descriptors(heap->empty_descriptor_array());
+  if (FLAG_unbox_double_fields) {
+    map->set_layout_descriptor(LayoutDescriptor::FastPointerLayout());
+  }
+  map->set_prototype(heap->null_value());
+  map->set_constructor_or_backpointer(heap->null_value());
+}
+
+}  // namespace
 
 bool Heap::CreateInitialMaps() {
   HeapObject* obj = nullptr;
@@ -2195,8 +2219,10 @@
   }
 
     ALLOCATE_PARTIAL_MAP(FIXED_ARRAY_TYPE, kVariableSizeSentinel, fixed_array);
+    fixed_array_map()->set_elements_kind(FAST_HOLEY_ELEMENTS);
     ALLOCATE_PARTIAL_MAP(ODDBALL_TYPE, Oddball::kSize, undefined);
     ALLOCATE_PARTIAL_MAP(ODDBALL_TYPE, Oddball::kSize, null);
+    ALLOCATE_PARTIAL_MAP(ODDBALL_TYPE, Oddball::kSize, the_hole);
 
 #undef ALLOCATE_PARTIAL_MAP
   }
@@ -2222,6 +2248,12 @@
   set_undefined_value(Oddball::cast(obj));
   Oddball::cast(obj)->set_kind(Oddball::kUndefined);
   DCHECK(!InNewSpace(undefined_value()));
+  {
+    AllocationResult allocation = Allocate(the_hole_map(), OLD_SPACE);
+    if (!allocation.To(&obj)) return false;
+  }
+  set_the_hole_value(Oddball::cast(obj));
+  Oddball::cast(obj)->set_kind(Oddball::kTheHole);
 
   // Set preliminary exception sentinel value before actually initializing it.
   set_exception(null_value());
@@ -2234,55 +2266,13 @@
   set_empty_descriptor_array(DescriptorArray::cast(obj));
 
   // Fix the instance_descriptors for the existing maps.
-  meta_map()->set_code_cache(empty_fixed_array());
-  meta_map()->set_dependent_code(DependentCode::cast(empty_fixed_array()));
-  meta_map()->set_raw_transitions(Smi::FromInt(0));
-  meta_map()->set_instance_descriptors(empty_descriptor_array());
-  if (FLAG_unbox_double_fields) {
-    meta_map()->set_layout_descriptor(LayoutDescriptor::FastPointerLayout());
-  }
-
-  fixed_array_map()->set_code_cache(empty_fixed_array());
-  fixed_array_map()->set_dependent_code(
-      DependentCode::cast(empty_fixed_array()));
-  fixed_array_map()->set_raw_transitions(Smi::FromInt(0));
-  fixed_array_map()->set_instance_descriptors(empty_descriptor_array());
-  if (FLAG_unbox_double_fields) {
-    fixed_array_map()->set_layout_descriptor(
-        LayoutDescriptor::FastPointerLayout());
-  }
-
-  undefined_map()->set_code_cache(empty_fixed_array());
-  undefined_map()->set_dependent_code(DependentCode::cast(empty_fixed_array()));
-  undefined_map()->set_raw_transitions(Smi::FromInt(0));
-  undefined_map()->set_instance_descriptors(empty_descriptor_array());
-  if (FLAG_unbox_double_fields) {
-    undefined_map()->set_layout_descriptor(
-        LayoutDescriptor::FastPointerLayout());
-  }
-
-  null_map()->set_code_cache(empty_fixed_array());
-  null_map()->set_dependent_code(DependentCode::cast(empty_fixed_array()));
-  null_map()->set_raw_transitions(Smi::FromInt(0));
-  null_map()->set_instance_descriptors(empty_descriptor_array());
-  if (FLAG_unbox_double_fields) {
-    null_map()->set_layout_descriptor(LayoutDescriptor::FastPointerLayout());
-  }
-  null_map()->set_is_undetectable();
-
-  // Fix prototype object for existing maps.
-  meta_map()->set_prototype(null_value());
-  meta_map()->set_constructor_or_backpointer(null_value());
-
-  fixed_array_map()->set_prototype(null_value());
-  fixed_array_map()->set_constructor_or_backpointer(null_value());
-
-  undefined_map()->set_prototype(null_value());
-  undefined_map()->set_constructor_or_backpointer(null_value());
+  FinalizePartialMap(this, meta_map());
+  FinalizePartialMap(this, fixed_array_map());
+  FinalizePartialMap(this, undefined_map());
   undefined_map()->set_is_undetectable();
-
-  null_map()->set_prototype(null_value());
-  null_map()->set_constructor_or_backpointer(null_value());
+  FinalizePartialMap(this, null_map());
+  null_map()->set_is_undetectable();
+  FinalizePartialMap(this, the_hole_map());
 
   {  // Map allocation
 #define ALLOCATE_MAP(instance_type, size, field_name)               \
@@ -2304,7 +2294,8 @@
   }
 
     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, fixed_cow_array)
-    DCHECK(fixed_array_map() != fixed_cow_array_map());
+    fixed_cow_array_map()->set_elements_kind(FAST_HOLEY_ELEMENTS);
+    DCHECK_NE(fixed_array_map(), fixed_cow_array_map());
 
     ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, scope_info)
     ALLOCATE_PRIMITIVE_MAP(HEAP_NUMBER_TYPE, HeapNumber::kSize, heap_number,
@@ -2320,7 +2311,6 @@
 #undef ALLOCATE_SIMD128_MAP
     ALLOCATE_MAP(FOREIGN_TYPE, Foreign::kSize, foreign)
 
-    ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, the_hole);
     ALLOCATE_PRIMITIVE_MAP(ODDBALL_TYPE, Oddball::kSize, boolean,
                            Context::BOOLEAN_FUNCTION_INDEX);
     ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, uninitialized);
@@ -2329,6 +2319,7 @@
     ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, exception);
     ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, termination_exception);
     ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, optimized_out);
+    ALLOCATE_MAP(ODDBALL_TYPE, Oddball::kSize, stale_register);
 
     for (unsigned i = 0; i < arraysize(string_type_table); i++) {
       const StringTypeTable& entry = string_type_table[i];
@@ -2345,8 +2336,9 @@
     }
 
     {  // Create a separate external one byte string map for native sources.
-      AllocationResult allocation = AllocateMap(EXTERNAL_ONE_BYTE_STRING_TYPE,
-                                                ExternalOneByteString::kSize);
+      AllocationResult allocation =
+          AllocateMap(SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE,
+                      ExternalOneByteString::kShortSize);
       if (!allocation.To(&obj)) return false;
       Map* map = Map::cast(obj);
       map->SetConstructorFunctionIndex(Context::STRING_FUNCTION_INDEX);
@@ -2354,6 +2346,7 @@
     }
 
     ALLOCATE_VARSIZE_MAP(FIXED_DOUBLE_ARRAY_TYPE, fixed_double_array)
+    fixed_double_array_map()->set_elements_kind(FAST_HOLEY_DOUBLE_ELEMENTS);
     ALLOCATE_VARSIZE_MAP(BYTE_ARRAY_TYPE, byte_array)
     ALLOCATE_VARSIZE_MAP(BYTECODE_ARRAY_TYPE, bytecode_array)
     ALLOCATE_VARSIZE_MAP(FREE_SPACE_TYPE, free_space)
@@ -2644,10 +2637,6 @@
   set_minus_infinity_value(
       *factory->NewHeapNumber(-V8_INFINITY, IMMUTABLE, TENURED));
 
-  // The hole has not been created yet, but we want to put something
-  // predictable in the gaps in the string table, so lets make that Smi zero.
-  set_the_hole_value(reinterpret_cast<Oddball*>(Smi::FromInt(0)));
-
   // Allocate initial string table.
   set_string_table(*StringTable::New(isolate(), kInitialStringTableSize));
 
@@ -2663,6 +2652,11 @@
                       handle(Smi::FromInt(0), isolate()), false, "object",
                       Oddball::kNull);
 
+  // Initialize the_hole_value.
+  Oddball::Initialize(isolate(), factory->the_hole_value(), "hole",
+                      handle(Smi::FromInt(-1), isolate()), false, "undefined",
+                      Oddball::kTheHole);
+
   // Initialize the true_value.
   Oddball::Initialize(isolate(), factory->true_value(), "true",
                       handle(Smi::FromInt(1), isolate()), true, "boolean",
@@ -2673,10 +2667,6 @@
                       handle(Smi::FromInt(0), isolate()), false, "boolean",
                       Oddball::kFalse);
 
-  set_the_hole_value(*factory->NewOddball(
-      factory->the_hole_map(), "hole", handle(Smi::FromInt(-1), isolate()),
-      false, "undefined", Oddball::kTheHole));
-
   set_uninitialized_value(
       *factory->NewOddball(factory->uninitialized_map(), "uninitialized",
                            handle(Smi::FromInt(-1), isolate()), false,
@@ -2706,6 +2696,11 @@
                            handle(Smi::FromInt(-6), isolate()), false,
                            "undefined", Oddball::kOptimizedOut));
 
+  set_stale_register(
+      *factory->NewOddball(factory->stale_register_map(), "stale_register",
+                           handle(Smi::FromInt(-7), isolate()), false,
+                           "undefined", Oddball::kStaleRegister));
+
   for (unsigned i = 0; i < arraysize(constant_string_table); i++) {
     Handle<String> str =
         factory->InternalizeUtf8String(constant_string_table[i].contents);
@@ -2716,13 +2711,6 @@
   // expanding the dictionary during bootstrapping.
   set_code_stubs(*UnseededNumberDictionary::New(isolate(), 128));
 
-  // Create the non_monomorphic_cache used in stub-cache.cc. The initial size
-  // is set to avoid expanding the dictionary during bootstrapping.
-  set_non_monomorphic_cache(*UnseededNumberDictionary::New(isolate(), 64));
-
-  set_polymorphic_code_cache(PolymorphicCodeCache::cast(
-      *factory->NewStruct(POLYMORPHIC_CODE_CACHE_TYPE)));
-
   set_instanceof_cache_function(Smi::FromInt(0));
   set_instanceof_cache_map(Smi::FromInt(0));
   set_instanceof_cache_answer(Smi::FromInt(0));
@@ -2740,14 +2728,6 @@
 #undef SYMBOL_INIT
   }
 
-  // The {hidden_properties_symbol} is special because it is the only name with
-  // hash code zero. This ensures that it will always be the first entry as
-  // sorted by hash code in descriptor arrays. It is used to identify the hidden
-  // properties in JSObjects.
-  // kIsNotArrayIndexMask is a computed hash with value zero.
-  Symbol::cast(roots_[khidden_properties_symbolRootIndex])
-      ->set_hash_field(Name::kIsNotArrayIndexMask);
-
   {
     HandleScope scope(isolate());
 #define SYMBOL_INIT(name, description)                                      \
@@ -2768,8 +2748,6 @@
 #undef SYMBOL_INIT
   }
 
-  CreateFixedStubs();
-
   // Allocate the dictionary of intrinsic function names.
   Handle<NameDictionary> intrinsic_names =
       NameDictionary::New(isolate(), Runtime::kNumFunctions, TENURED);
@@ -2812,10 +2790,6 @@
   // The symbol registry is initialized lazily.
   set_symbol_registry(Smi::FromInt(0));
 
-  // Allocate object to hold object observation state.
-  set_observation_state(*factory->NewJSObjectFromMap(
-      factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize)));
-
   // Microtask queue uses the empty fixed array as a sentinel for "empty".
   // Number of queued microtasks stored in Isolate::pending_microtask_count().
   set_microtask_queue(empty_fixed_array());
@@ -2851,6 +2825,20 @@
   }
 
   {
+    Handle<FixedArray> empty_literals_array =
+        factory->NewFixedArray(1, TENURED);
+    empty_literals_array->set(0, *factory->empty_fixed_array());
+    set_empty_literals_array(*empty_literals_array);
+  }
+
+  {
+    Handle<FixedArray> empty_sloppy_arguments_elements =
+        factory->NewFixedArray(2, TENURED);
+    empty_sloppy_arguments_elements->set_map(sloppy_arguments_elements_map());
+    set_empty_sloppy_arguments_elements(*empty_sloppy_arguments_elements);
+  }
+
+  {
     Handle<WeakCell> cell = factory->NewWeakCell(factory->undefined_value());
     set_empty_weak_cell(*cell);
     cell->clear();
@@ -2882,6 +2870,7 @@
 
   // Handling of script id generation is in Heap::NextScriptId().
   set_last_script_id(Smi::FromInt(v8::UnboundScript::kNoScriptId));
+  set_next_template_serial_number(Smi::FromInt(0));
 
   // Allocate the empty script.
   Handle<Script> script = factory->NewScript(factory->empty_string());
@@ -2896,10 +2885,20 @@
   cell->set_value(the_hole_value());
   set_empty_property_cell(*cell);
 
-  Handle<PropertyCell> species_cell = factory->NewPropertyCell();
-  species_cell->set_value(Smi::FromInt(Isolate::kArrayProtectorValid));
+  cell = factory->NewPropertyCell();
+  cell->set_value(Smi::FromInt(Isolate::kArrayProtectorValid));
+  set_has_instance_protector(*cell);
+
+  Handle<Cell> is_concat_spreadable_cell = factory->NewCell(
+      handle(Smi::FromInt(Isolate::kArrayProtectorValid), isolate()));
+  set_is_concat_spreadable_protector(*is_concat_spreadable_cell);
+
+  Handle<Cell> species_cell = factory->NewCell(
+      handle(Smi::FromInt(Isolate::kArrayProtectorValid), isolate()));
   set_species_protector(*species_cell);
 
+  set_serialized_templates(empty_fixed_array());
+
   set_weak_stack_trace_list(Smi::FromInt(0));
 
   set_noscript_shared_function_infos(Smi::FromInt(0));
@@ -2915,6 +2914,8 @@
 
   // Initialize compilation cache.
   isolate_->compilation_cache()->Clear();
+
+  CreateFixedStubs();
 }
 
 
@@ -2925,8 +2926,6 @@
     case kInstanceofCacheMapRootIndex:
     case kInstanceofCacheAnswerRootIndex:
     case kCodeStubsRootIndex:
-    case kNonMonomorphicCacheRootIndex:
-    case kPolymorphicCodeCacheRootIndex:
     case kEmptyScriptRootIndex:
     case kSymbolRegistryRootIndex:
     case kScriptListRootIndex:
@@ -2937,6 +2936,7 @@
     case kRetainedMapsRootIndex:
     case kNoScriptSharedFunctionInfosRootIndex:
     case kWeakStackTraceListRootIndex:
+    case kSerializedTemplatesRootIndex:
 // Smi values
 #define SMI_ENTRY(type, name, Name) case k##Name##RootIndex:
       SMI_ROOT_LIST(SMI_ENTRY)
@@ -3122,14 +3122,8 @@
 
   if (lo_space()->Contains(object)) return false;
 
-  Page* page = Page::FromAddress(address);
-  // We can move the object start if:
-  // (1) the object is not in old space,
-  // (2) the page of the object was already swept,
-  // (3) the page was already concurrently swept. This case is an optimization
-  // for concurrent sweeping. The WasSwept predicate for concurrently swept
-  // pages is set after sweeping all pages.
-  return !InOldSpace(object) || page->SweepingDone();
+  // We can move the object start if the page was already swept.
+  return Page::FromAddress(address)->SweepingDone();
 }
 
 
@@ -3154,6 +3148,7 @@
 
 FixedArrayBase* Heap::LeftTrimFixedArray(FixedArrayBase* object,
                                          int elements_to_trim) {
+  CHECK_NOT_NULL(object);
   DCHECK(!object->IsFixedTypedArrayBase());
   DCHECK(!object->IsByteArray());
   const int element_size = object->IsFixedArray() ? kPointerSize : kDoubleSize;
@@ -3166,10 +3161,6 @@
   DCHECK(!lo_space()->Contains(object));
   DCHECK(object->map() != fixed_cow_array_map());
 
-  // Ensure that the no handle-scope has more than one pointer to the same
-  // backing-store.
-  SLOW_DCHECK(CountHandlesForObject(object) <= 1);
-
   STATIC_ASSERT(FixedArrayBase::kMapOffset == 0);
   STATIC_ASSERT(FixedArrayBase::kLengthOffset == kPointerSize);
   STATIC_ASSERT(FixedArrayBase::kHeaderSize == 2 * kPointerSize);
@@ -3185,7 +3176,6 @@
   // we still do it.
   CreateFillerObjectAt(object->address(), bytes_to_trim,
                        ClearRecordedSlots::kYes);
-
   // Initialize header of the trimmed array. Since left trimming is only
   // performed on pages which are not concurrently swept creating a filler
   // object does not require synchronization.
@@ -3197,6 +3187,11 @@
   FixedArrayBase* new_object =
       FixedArrayBase::cast(HeapObject::FromAddress(new_start));
 
+  // Remove recorded slots for the new map and length offset.
+  ClearRecordedSlot(new_object, HeapObject::RawField(new_object, 0));
+  ClearRecordedSlot(new_object, HeapObject::RawField(
+                                    new_object, FixedArrayBase::kLengthOffset));
+
   // Maintain consistency of live bytes during incremental marking
   Marking::TransferMark(this, object->address(), new_start);
   AdjustLiveBytes(new_object, -bytes_to_trim, Heap::CONCURRENT_TO_SWEEPER);
@@ -3372,8 +3367,8 @@
   result->set_map_no_write_barrier(code_map());
   Code* code = Code::cast(result);
   DCHECK(IsAligned(bit_cast<intptr_t>(code->address()), kCodeAlignment));
-  DCHECK(isolate_->code_range() == NULL || !isolate_->code_range()->valid() ||
-         isolate_->code_range()->contains(code->address()) ||
+  DCHECK(!memory_allocator()->code_range()->valid() ||
+         memory_allocator()->code_range()->contains(code->address()) ||
          object_size <= code_space()->AreaSize());
   code->set_gc_metadata(Smi::FromInt(0));
   code->set_ic_age(global_ic_age_);
@@ -3398,8 +3393,8 @@
 
   // Relocate the copy.
   DCHECK(IsAligned(bit_cast<intptr_t>(new_code->address()), kCodeAlignment));
-  DCHECK(isolate_->code_range() == NULL || !isolate_->code_range()->valid() ||
-         isolate_->code_range()->contains(code->address()) ||
+  DCHECK(!memory_allocator()->code_range()->valid() ||
+         memory_allocator()->code_range()->contains(code->address()) ||
          obj_size <= code_space()->AreaSize());
   new_code->Relocate(new_addr - old_addr);
   // We have to iterate over the object and process its pointers when black
@@ -3429,59 +3424,6 @@
   return copy;
 }
 
-AllocationResult Heap::CopyCode(Code* code, Vector<byte> reloc_info) {
-  // Allocate ByteArray before the Code object, so that we do not risk
-  // leaving uninitialized Code object (and breaking the heap).
-  ByteArray* reloc_info_array = nullptr;
-  {
-    AllocationResult allocation =
-        AllocateByteArray(reloc_info.length(), TENURED);
-    if (!allocation.To(&reloc_info_array)) return allocation;
-  }
-
-  int new_body_size = RoundUp(code->instruction_size(), kObjectAlignment);
-
-  int new_obj_size = Code::SizeFor(new_body_size);
-
-  Address old_addr = code->address();
-
-  size_t relocation_offset =
-      static_cast<size_t>(code->instruction_end() - old_addr);
-
-  HeapObject* result = nullptr;
-  AllocationResult allocation = AllocateRaw(new_obj_size, CODE_SPACE);
-  if (!allocation.To(&result)) return allocation;
-
-  // Copy code object.
-  Address new_addr = result->address();
-
-  // Copy header and instructions.
-  CopyBytes(new_addr, old_addr, relocation_offset);
-
-  Code* new_code = Code::cast(result);
-  new_code->set_relocation_info(reloc_info_array);
-
-  // Copy patched rinfo.
-  CopyBytes(new_code->relocation_start(), reloc_info.start(),
-            static_cast<size_t>(reloc_info.length()));
-
-  // Relocate the copy.
-  DCHECK(IsAligned(bit_cast<intptr_t>(new_code->address()), kCodeAlignment));
-  DCHECK(isolate_->code_range() == NULL || !isolate_->code_range()->valid() ||
-         isolate_->code_range()->contains(code->address()) ||
-         new_obj_size <= code_space()->AreaSize());
-
-  new_code->Relocate(new_addr - old_addr);
-  // We have to iterate over over the object and process its pointers when
-  // black allocation is on.
-  incremental_marking()->IterateBlackObject(new_code);
-#ifdef VERIFY_HEAP
-  if (FLAG_verify_heap) code->ObjectVerify();
-#endif
-  return new_code;
-}
-
-
 void Heap::InitializeAllocationMemento(AllocationMemento* memento,
                                        AllocationSite* allocation_site) {
   memento->set_map_no_write_barrier(allocation_memento_map());
@@ -3579,7 +3521,8 @@
   // Initialize the JSObject.
   InitializeJSObjectFromMap(js_obj, properties, map);
   DCHECK(js_obj->HasFastElements() || js_obj->HasFixedTypedArrayElements() ||
-         js_obj->HasFastStringWrapperElements());
+         js_obj->HasFastStringWrapperElements() ||
+         js_obj->HasFastArgumentsElements());
   return js_obj;
 }
 
@@ -3605,11 +3548,13 @@
   // Make the clone.
   Map* map = source->map();
 
-  // We can only clone regexps, normal objects, api objects or arrays. Copying
-  // anything else will break invariants.
+  // We can only clone regexps, normal objects, api objects, errors or arrays.
+  // Copying anything else will break invariants.
   CHECK(map->instance_type() == JS_REGEXP_TYPE ||
         map->instance_type() == JS_OBJECT_TYPE ||
+        map->instance_type() == JS_ERROR_TYPE ||
         map->instance_type() == JS_ARRAY_TYPE ||
+        map->instance_type() == JS_API_OBJECT_TYPE ||
         map->instance_type() == JS_SPECIAL_API_OBJECT_TYPE);
 
   int object_size = map->instance_size();
@@ -4018,8 +3963,7 @@
 AllocationResult Heap::AllocateRawFixedDoubleArray(int length,
                                                    PretenureFlag pretenure) {
   if (length < 0 || length > FixedDoubleArray::kMaxLength) {
-    v8::internal::Heap::FatalProcessOutOfMemory("invalid array length",
-                                                kDoubleAligned);
+    v8::internal::Heap::FatalProcessOutOfMemory("invalid array length", true);
   }
   int size = FixedDoubleArray::SizeFor(length);
   AllocationSpace space = SelectSpace(pretenure);
@@ -4466,8 +4410,36 @@
 }
 
 void Heap::CollectGarbageOnMemoryPressure(const char* source) {
+  const int kGarbageThresholdInBytes = 8 * MB;
+  const double kGarbageThresholdAsFractionOfTotalMemory = 0.1;
+  // This constant is the maximum response time in RAIL performance model.
+  const double kMaxMemoryPressurePauseMs = 100;
+
+  double start = MonotonicallyIncreasingTimeInMs();
   CollectAllGarbage(kReduceMemoryFootprintMask | kAbortIncrementalMarkingMask,
-                    source);
+                    source, kGCCallbackFlagCollectAllAvailableGarbage);
+  double end = MonotonicallyIncreasingTimeInMs();
+
+  // Estimate how much memory we can free.
+  int64_t potential_garbage =
+      (CommittedMemory() - SizeOfObjects()) + external_memory_;
+  // If we can potentially free large amount of memory, then start GC right
+  // away instead of waiting for memory reducer.
+  if (potential_garbage >= kGarbageThresholdInBytes &&
+      potential_garbage >=
+          CommittedMemory() * kGarbageThresholdAsFractionOfTotalMemory) {
+    // If we spent less than half of the time budget, then perform full GC
+    // Otherwise, start incremental marking.
+    if (end - start < kMaxMemoryPressurePauseMs / 2) {
+      CollectAllGarbage(
+          kReduceMemoryFootprintMask | kAbortIncrementalMarkingMask, source,
+          kGCCallbackFlagCollectAllAvailableGarbage);
+    } else {
+      if (FLAG_incremental_marking && incremental_marking()->IsStopped()) {
+        StartIdleIncrementalMarking();
+      }
+    }
+  }
 }
 
 void Heap::MemoryPressureNotification(MemoryPressureLevel level,
@@ -4490,6 +4462,15 @@
   }
 }
 
+void Heap::CollectCodeStatistics() {
+  PagedSpace::ResetCodeAndMetadataStatistics(isolate());
+  // We do not look for code in new space, or map space.  If code
+  // somehow ends up in those spaces, we would miss it here.
+  code_space_->CollectCodeStatistics();
+  old_space_->CollectCodeStatistics();
+  lo_space_->CollectCodeStatistics();
+}
+
 #ifdef DEBUG
 
 void Heap::Print() {
@@ -4504,11 +4485,7 @@
 
 void Heap::ReportCodeStatistics(const char* title) {
   PrintF(">>>>>> Code Stats (%s) >>>>>>\n", title);
-  PagedSpace::ResetCodeStatistics(isolate());
-  // We do not look for code in new space, map space, or old space.  If code
-  // somehow ends up in those spaces, we would miss it here.
-  code_space_->CollectCodeStatistics();
-  lo_space_->CollectCodeStatistics();
+  CollectCodeStatistics();
   PagedSpace::ReportCodeStatistics(isolate());
 }
 
@@ -4520,7 +4497,7 @@
   USE(title);
   PrintF(">>>>>> =============== %s (%d) =============== >>>>>>\n", title,
          gc_count_);
-  PrintF("old_generation_allocation_limit_ %" V8_PTR_PREFIX "d\n",
+  PrintF("old_generation_allocation_limit_ %" V8PRIdPTR "\n",
          old_generation_allocation_limit_);
 
   PrintF("\n");
@@ -4529,7 +4506,7 @@
   PrintF("\n");
 
   PrintF("Heap statistics : ");
-  isolate_->memory_allocator()->ReportStatistics();
+  memory_allocator()->ReportStatistics();
   PrintF("To space : ");
   new_space_.ReportStatistics();
   PrintF("Old space : ");
@@ -4546,7 +4523,7 @@
 #endif  // DEBUG
 
 bool Heap::Contains(HeapObject* value) {
-  if (isolate_->memory_allocator()->IsOutsideAllocatedSpace(value->address())) {
+  if (memory_allocator()->IsOutsideAllocatedSpace(value->address())) {
     return false;
   }
   return HasBeenSetUp() &&
@@ -4556,7 +4533,7 @@
 }
 
 bool Heap::ContainsSlow(Address addr) {
-  if (isolate_->memory_allocator()->IsOutsideAllocatedSpace(addr)) {
+  if (memory_allocator()->IsOutsideAllocatedSpace(addr)) {
     return false;
   }
   return HasBeenSetUp() &&
@@ -4566,7 +4543,7 @@
 }
 
 bool Heap::InSpace(HeapObject* value, AllocationSpace space) {
-  if (isolate_->memory_allocator()->IsOutsideAllocatedSpace(value->address())) {
+  if (memory_allocator()->IsOutsideAllocatedSpace(value->address())) {
     return false;
   }
   if (!HasBeenSetUp()) return false;
@@ -4588,7 +4565,7 @@
 }
 
 bool Heap::InSpaceSlow(Address addr, AllocationSpace space) {
-  if (isolate_->memory_allocator()->IsOutsideAllocatedSpace(addr)) {
+  if (memory_allocator()->IsOutsideAllocatedSpace(addr)) {
     return false;
   }
   if (!HasBeenSetUp()) return false;
@@ -4678,10 +4655,8 @@
 
 void Heap::ZapFromSpace() {
   if (!new_space_.IsFromSpaceCommitted()) return;
-  NewSpacePageIterator it(new_space_.FromSpaceStart(),
-                          new_space_.FromSpaceEnd());
-  while (it.has_next()) {
-    NewSpacePage* page = it.next();
+  for (Page* page : NewSpacePageRange(new_space_.FromSpaceStart(),
+                                      new_space_.FromSpaceEnd())) {
     for (Address cursor = page->area_start(), limit = page->area_end();
          cursor < limit; cursor += kPointerSize) {
       Memory::Address_at(cursor) = kFromSpaceZapValue;
@@ -4820,6 +4795,8 @@
   v->Synchronize(VisitorSynchronization::kTop);
   Relocatable::Iterate(isolate_, v);
   v->Synchronize(VisitorSynchronization::kRelocatable);
+  isolate_->debug()->Iterate(v);
+  v->Synchronize(VisitorSynchronization::kDebug);
 
   isolate_->compilation_cache()->Iterate(v);
   v->Synchronize(VisitorSynchronization::kCompilationCache);
@@ -5029,12 +5006,11 @@
   *stats->map_space_capacity = map_space_->Capacity();
   *stats->lo_space_size = lo_space_->Size();
   isolate_->global_handles()->RecordStats(stats);
-  *stats->memory_allocator_size = isolate()->memory_allocator()->Size();
+  *stats->memory_allocator_size = memory_allocator()->Size();
   *stats->memory_allocator_capacity =
-      isolate()->memory_allocator()->Size() +
-      isolate()->memory_allocator()->Available();
+      memory_allocator()->Size() + memory_allocator()->Available();
   *stats->os_error = base::OS::GetLastError();
-  isolate()->memory_allocator()->Available();
+  memory_allocator()->Available();
   if (take_snapshot) {
     HeapIterator iterator(this);
     for (HeapObject* obj = iterator.next(); obj != NULL;
@@ -5066,11 +5042,8 @@
 
 
 int64_t Heap::PromotedExternalMemorySize() {
-  if (amount_of_external_allocated_memory_ <=
-      amount_of_external_allocated_memory_at_last_global_gc_)
-    return 0;
-  return amount_of_external_allocated_memory_ -
-         amount_of_external_allocated_memory_at_last_global_gc_;
+  if (external_memory_ <= external_memory_at_last_mark_compact_) return 0;
+  return external_memory_ - external_memory_at_last_mark_compact_;
 }
 
 
@@ -5188,8 +5161,8 @@
       CalculateOldGenerationAllocationLimit(factor, old_gen_size);
 
   if (FLAG_trace_gc_verbose) {
-    PrintIsolate(isolate_, "Grow: old size: %" V8_PTR_PREFIX
-                           "d KB, new limit: %" V8_PTR_PREFIX "d KB (%.1f)\n",
+    PrintIsolate(isolate_, "Grow: old size: %" V8PRIdPTR
+                           " KB, new limit: %" V8PRIdPTR " KB (%.1f)\n",
                  old_gen_size / KB, old_generation_allocation_limit_ / KB,
                  factor);
   }
@@ -5203,10 +5176,10 @@
   intptr_t limit = CalculateOldGenerationAllocationLimit(factor, old_gen_size);
   if (limit < old_generation_allocation_limit_) {
     if (FLAG_trace_gc_verbose) {
-      PrintIsolate(isolate_, "Dampen: old size: %" V8_PTR_PREFIX
-                             "d KB, old limit: %" V8_PTR_PREFIX
-                             "d KB, "
-                             "new limit: %" V8_PTR_PREFIX "d KB (%.1f)\n",
+      PrintIsolate(isolate_,
+                   "Dampen: old size: %" V8PRIdPTR " KB, old limit: %" V8PRIdPTR
+                   " KB, "
+                   "new limit: %" V8PRIdPTR " KB (%.1f)\n",
                    old_gen_size / KB, old_generation_allocation_limit_ / KB,
                    limit / KB, factor);
     }
@@ -5244,7 +5217,8 @@
 
 static void InitializeGCOnce() {
   Scavenger::Initialize();
-  StaticScavengeVisitor::Initialize();
+  StaticScavengeVisitor<DEFAULT_PROMOTION>::Initialize();
+  StaticScavengeVisitor<PROMOTE_MARKED>::Initialize();
   MarkCompactCollector::Initialize();
 }
 
@@ -5269,7 +5243,9 @@
   base::CallOnce(&initialize_gc_once, &InitializeGCOnce);
 
   // Set up memory allocator.
-  if (!isolate_->memory_allocator()->SetUp(MaxReserved(), MaxExecutableSize()))
+  memory_allocator_ = new MemoryAllocator(isolate_);
+  if (!memory_allocator_->SetUp(MaxReserved(), MaxExecutableSize(),
+                                code_range_size_))
     return false;
 
   // Initialize incremental marking.
@@ -5286,8 +5262,6 @@
   if (old_space_ == NULL) return false;
   if (!old_space_->SetUp()) return false;
 
-  if (!isolate_->code_range()->SetUp(code_range_size_)) return false;
-
   // Initialize the code space, set its maximum capacity to the old
   // generation size. It needs executable memory.
   code_space_ = new OldSpace(this, CODE_SPACE, EXECUTABLE);
@@ -5337,8 +5311,6 @@
 
   scavenge_job_ = new ScavengeJob();
 
-  array_buffer_tracker_ = new ArrayBufferTracker(this);
-
   LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity()));
   LOG(isolate_, IntPtrTEvent("heap-available", Available()));
 
@@ -5401,18 +5373,27 @@
   // All pages right after bootstrapping must be marked as never-evacuate.
   PagedSpaces spaces(this);
   for (PagedSpace* s = spaces.next(); s != NULL; s = spaces.next()) {
-    PageIterator it(s);
-    while (it.has_next()) CHECK(it.next()->NeverEvacuate());
+    for (Page* p : *s) {
+      CHECK(p->NeverEvacuate());
+    }
   }
 #endif  // DEBUG
 }
 
+void Heap::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) {
+  mark_compact_collector()->SetEmbedderHeapTracer(tracer);
+}
+
+bool Heap::UsingEmbedderHeapTracer() {
+  return mark_compact_collector()->UsingEmbedderHeapTracer();
+}
+
+void Heap::TracePossibleWrapper(JSObject* js_object) {
+  mark_compact_collector()->TracePossibleWrapper(js_object);
+}
+
 void Heap::RegisterExternallyReferencedObject(Object** object) {
-  DCHECK(mark_compact_collector()->in_use());
-  HeapObject* heap_object = HeapObject::cast(*object);
-  DCHECK(Contains(heap_object));
-  MarkBit mark_bit = Marking::MarkBitFrom(heap_object);
-  mark_compact_collector()->MarkObject(heap_object, mark_bit);
+  mark_compact_collector()->RegisterExternallyReferencedObject(object);
 }
 
 void Heap::TearDown() {
@@ -5431,7 +5412,7 @@
     PrintF("max_gc_pause=%.1f ", get_max_gc_pause());
     PrintF("total_gc_time=%.1f ", total_gc_time_ms_);
     PrintF("min_in_mutator=%.1f ", get_min_in_mutator());
-    PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", get_max_alive_after_gc());
+    PrintF("max_alive_after_gc=%" V8PRIdPTR " ", get_max_alive_after_gc());
     PrintF("total_marking_time=%.1f ", tracer()->cumulative_marking_duration());
     PrintF("total_sweeping_time=%.1f ",
            tracer()->cumulative_sweeping_duration());
@@ -5440,17 +5421,17 @@
 
   if (FLAG_print_max_heap_committed) {
     PrintF("\n");
-    PrintF("maximum_committed_by_heap=%" V8_PTR_PREFIX "d ",
+    PrintF("maximum_committed_by_heap=%" V8PRIdPTR " ",
            MaximumCommittedMemory());
-    PrintF("maximum_committed_by_new_space=%" V8_PTR_PREFIX "d ",
+    PrintF("maximum_committed_by_new_space=%" V8PRIdPTR " ",
            new_space_.MaximumCommittedMemory());
-    PrintF("maximum_committed_by_old_space=%" V8_PTR_PREFIX "d ",
+    PrintF("maximum_committed_by_old_space=%" V8PRIdPTR " ",
            old_space_->MaximumCommittedMemory());
-    PrintF("maximum_committed_by_code_space=%" V8_PTR_PREFIX "d ",
+    PrintF("maximum_committed_by_code_space=%" V8PRIdPTR " ",
            code_space_->MaximumCommittedMemory());
-    PrintF("maximum_committed_by_map_space=%" V8_PTR_PREFIX "d ",
+    PrintF("maximum_committed_by_map_space=%" V8PRIdPTR " ",
            map_space_->MaximumCommittedMemory());
-    PrintF("maximum_committed_by_lo_space=%" V8_PTR_PREFIX "d ",
+    PrintF("maximum_committed_by_lo_space=%" V8PRIdPTR " ",
            lo_space_->MaximumCommittedMemory());
     PrintF("\n\n");
   }
@@ -5490,11 +5471,6 @@
   delete scavenge_job_;
   scavenge_job_ = nullptr;
 
-  WaitUntilUnmappingOfFreeChunksCompleted();
-
-  delete array_buffer_tracker_;
-  array_buffer_tracker_ = nullptr;
-
   isolate_->global_handles()->TearDown();
 
   external_string_table_.TearDown();
@@ -5527,7 +5503,7 @@
 
   store_buffer()->TearDown();
 
-  isolate_->memory_allocator()->TearDown();
+  memory_allocator()->TearDown();
 
   StrongRootsList* next = NULL;
   for (StrongRootsList* list = strong_roots_list_; list; list = next) {
@@ -5535,6 +5511,9 @@
     delete list;
   }
   strong_roots_list_ = NULL;
+
+  delete memory_allocator_;
+  memory_allocator_ = nullptr;
 }
 
 
@@ -5579,12 +5558,6 @@
   UNREACHABLE();
 }
 
-void Heap::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) {
-  DCHECK_NOT_NULL(tracer);
-  CHECK_NULL(embedder_heap_tracer_);
-  embedder_heap_tracer_ = tracer;
-}
-
 // TODO(ishell): Find a better place for this.
 void Heap::AddWeakObjectToCodeDependency(Handle<HeapObject> obj,
                                          Handle<DependentCode> dep) {
@@ -5604,6 +5577,33 @@
   return DependentCode::cast(empty_fixed_array());
 }
 
+namespace {
+void CompactWeakFixedArray(Object* object) {
+  if (object->IsWeakFixedArray()) {
+    WeakFixedArray* array = WeakFixedArray::cast(object);
+    array->Compact<WeakFixedArray::NullCallback>();
+  }
+}
+}  // anonymous namespace
+
+void Heap::CompactWeakFixedArrays() {
+  // Find known WeakFixedArrays and compact them.
+  HeapIterator iterator(this);
+  for (HeapObject* o = iterator.next(); o != NULL; o = iterator.next()) {
+    if (o->IsPrototypeInfo()) {
+      Object* prototype_users = PrototypeInfo::cast(o)->prototype_users();
+      if (prototype_users->IsWeakFixedArray()) {
+        WeakFixedArray* array = WeakFixedArray::cast(prototype_users);
+        array->Compact<JSObject::PrototypeRegistryCompactionCallback>();
+      }
+    } else if (o->IsScript()) {
+      CompactWeakFixedArray(Script::cast(o)->shared_function_infos());
+    }
+  }
+  CompactWeakFixedArray(noscript_shared_function_infos());
+  CompactWeakFixedArray(script_list());
+  CompactWeakFixedArray(weak_stack_trace_list());
+}
 
 void Heap::AddRetainedMap(Handle<Map> map) {
   Handle<WeakCell> cell = Map::WeakCellForMap(map);
@@ -5648,9 +5648,8 @@
   if (new_length != length) retained_maps->SetLength(new_length);
 }
 
-
-void Heap::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
-  v8::internal::V8::FatalProcessOutOfMemory(location, take_snapshot);
+void Heap::FatalProcessOutOfMemory(const char* location, bool is_heap_oom) {
+  v8::internal::V8::FatalProcessOutOfMemory(location, is_heap_oom);
 }
 
 #ifdef DEBUG
@@ -5673,32 +5672,6 @@
 
 #endif
 
-#ifdef ENABLE_SLOW_DCHECKS
-
-class CountHandleVisitor : public ObjectVisitor {
- public:
-  explicit CountHandleVisitor(Object* object) : object_(object) {}
-
-  void VisitPointers(Object** start, Object** end) override {
-    for (Object** p = start; p < end; p++) {
-      if (object_ == reinterpret_cast<Object*>(*p)) count_++;
-    }
-  }
-
-  int count() { return count_; }
-
- private:
-  Object* object_;
-  int count_ = 0;
-};
-
-int Heap::CountHandlesForObject(Object* object) {
-  CountHandleVisitor v(object);
-  isolate_->handle_scope_implementer()->Iterate(&v);
-  return v.count();
-}
-#endif
-
 class CheckHandleCountVisitor : public ObjectVisitor {
  public:
   CheckHandleCountVisitor() : handle_count_(0) {}
@@ -5958,14 +5931,14 @@
   // No iterator means we are done.
   if (object_iterator_ == nullptr) return nullptr;
 
-  if (HeapObject* obj = object_iterator_->next_object()) {
+  if (HeapObject* obj = object_iterator_->Next()) {
     // If the current iterator has more objects we are fine.
     return obj;
   } else {
     // Go though the spaces looking for one that has objects.
     while (space_iterator_->has_next()) {
       object_iterator_ = space_iterator_->next();
-      if (HeapObject* obj = object_iterator_->next_object()) {
+      if (HeapObject* obj = object_iterator_->Next()) {
         return obj;
       }
     }
@@ -6255,11 +6228,11 @@
   for (int index = 0; index < kLength; index++) keys_[index].source = NULL;
 }
 
-
 void Heap::ExternalStringTable::CleanUp() {
   int last = 0;
+  Isolate* isolate = heap_->isolate();
   for (int i = 0; i < new_space_strings_.length(); ++i) {
-    if (new_space_strings_[i] == heap_->the_hole_value()) {
+    if (new_space_strings_[i]->IsTheHole(isolate)) {
       continue;
     }
     DCHECK(new_space_strings_[i]->IsExternalString());
@@ -6274,7 +6247,7 @@
 
   last = 0;
   for (int i = 0; i < old_space_strings_.length(); ++i) {
-    if (old_space_strings_[i] == heap_->the_hole_value()) {
+    if (old_space_strings_[i]->IsTheHole(isolate)) {
       continue;
     }
     DCHECK(old_space_strings_[i]->IsExternalString());
@@ -6290,7 +6263,6 @@
 #endif
 }
 
-
 void Heap::ExternalStringTable::TearDown() {
   for (int i = 0; i < new_space_strings_.length(); ++i) {
     heap_->FinalizeExternalString(ExternalString::cast(new_space_strings_[i]));
@@ -6303,75 +6275,6 @@
 }
 
 
-class Heap::UnmapFreeMemoryTask : public v8::Task {
- public:
-  UnmapFreeMemoryTask(Heap* heap, MemoryChunk* head)
-      : heap_(heap), head_(head) {}
-  virtual ~UnmapFreeMemoryTask() {}
-
- private:
-  // v8::Task overrides.
-  void Run() override {
-    heap_->FreeQueuedChunks(head_);
-    heap_->pending_unmapping_tasks_semaphore_.Signal();
-  }
-
-  Heap* heap_;
-  MemoryChunk* head_;
-
-  DISALLOW_COPY_AND_ASSIGN(UnmapFreeMemoryTask);
-};
-
-
-void Heap::WaitUntilUnmappingOfFreeChunksCompleted() {
-  while (concurrent_unmapping_tasks_active_ > 0) {
-    pending_unmapping_tasks_semaphore_.Wait();
-    concurrent_unmapping_tasks_active_--;
-  }
-}
-
-
-void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) {
-  // PreFree logically frees the memory chunk. However, the actual freeing
-  // will happen on a separate thread sometime later.
-  isolate_->memory_allocator()->PreFreeMemory(chunk);
-
-  // The chunks added to this queue will be freed by a concurrent thread.
-  chunk->set_next_chunk(chunks_queued_for_free_);
-  chunks_queued_for_free_ = chunk;
-}
-
-
-void Heap::FreeQueuedChunks() {
-  if (chunks_queued_for_free_ != NULL) {
-    if (FLAG_concurrent_sweeping) {
-      V8::GetCurrentPlatform()->CallOnBackgroundThread(
-          new UnmapFreeMemoryTask(this, chunks_queued_for_free_),
-          v8::Platform::kShortRunningTask);
-    } else {
-      FreeQueuedChunks(chunks_queued_for_free_);
-      pending_unmapping_tasks_semaphore_.Signal();
-    }
-    chunks_queued_for_free_ = NULL;
-  } else {
-    // If we do not have anything to unmap, we just signal the semaphore
-    // that we are done.
-    pending_unmapping_tasks_semaphore_.Signal();
-  }
-  concurrent_unmapping_tasks_active_++;
-}
-
-
-void Heap::FreeQueuedChunks(MemoryChunk* list_head) {
-  MemoryChunk* next;
-  MemoryChunk* chunk;
-  for (chunk = list_head; chunk != NULL; chunk = next) {
-    next = chunk->next_chunk();
-    isolate_->memory_allocator()->PerformFreeMemory(chunk);
-  }
-}
-
-
 void Heap::RememberUnmappedPage(Address page, bool compacted) {
   uintptr_t p = reinterpret_cast<uintptr_t>(page);
   // Tag the page pointer to make it findable in the dump file.
diff --git a/src/heap/heap.h b/src/heap/heap.h
index 9457453..ed1e652 100644
--- a/src/heap/heap.h
+++ b/src/heap/heap.h
@@ -13,7 +13,7 @@
 #include "include/v8.h"
 #include "src/allocation.h"
 #include "src/assert-scope.h"
-#include "src/atomic-utils.h"
+#include "src/base/atomic-utils.h"
 #include "src/globals.h"
 #include "src/heap-symbols.h"
 // TODO(mstarzinger): Two more includes to kill!
@@ -28,67 +28,72 @@
 
 // Defines all the roots in Heap.
 #define STRONG_ROOT_LIST(V)                                                    \
-  V(Map, byte_array_map, ByteArrayMap)                                         \
+  /* Cluster the most popular ones in a few cache lines here at the top.    */ \
+  /* The first 32 entries are most often used in the startup snapshot and   */ \
+  /* can use a shorter representation in the serialization format.          */ \
   V(Map, free_space_map, FreeSpaceMap)                                         \
   V(Map, one_pointer_filler_map, OnePointerFillerMap)                          \
   V(Map, two_pointer_filler_map, TwoPointerFillerMap)                          \
-  /* Cluster the most popular ones in a few cache lines here at the top.    */ \
+  V(Oddball, uninitialized_value, UninitializedValue)                          \
   V(Oddball, undefined_value, UndefinedValue)                                  \
   V(Oddball, the_hole_value, TheHoleValue)                                     \
   V(Oddball, null_value, NullValue)                                            \
   V(Oddball, true_value, TrueValue)                                            \
   V(Oddball, false_value, FalseValue)                                          \
   V(String, empty_string, empty_string)                                        \
-  V(Oddball, uninitialized_value, UninitializedValue)                          \
-  V(Map, cell_map, CellMap)                                                    \
-  V(Map, global_property_cell_map, GlobalPropertyCellMap)                      \
-  V(Map, shared_function_info_map, SharedFunctionInfoMap)                      \
   V(Map, meta_map, MetaMap)                                                    \
-  V(Map, heap_number_map, HeapNumberMap)                                       \
-  V(Map, mutable_heap_number_map, MutableHeapNumberMap)                        \
-  V(Map, float32x4_map, Float32x4Map)                                          \
-  V(Map, int32x4_map, Int32x4Map)                                              \
-  V(Map, uint32x4_map, Uint32x4Map)                                            \
-  V(Map, bool32x4_map, Bool32x4Map)                                            \
-  V(Map, int16x8_map, Int16x8Map)                                              \
-  V(Map, uint16x8_map, Uint16x8Map)                                            \
-  V(Map, bool16x8_map, Bool16x8Map)                                            \
-  V(Map, int8x16_map, Int8x16Map)                                              \
-  V(Map, uint8x16_map, Uint8x16Map)                                            \
-  V(Map, bool8x16_map, Bool8x16Map)                                            \
-  V(Map, native_context_map, NativeContextMap)                                 \
+  V(Map, byte_array_map, ByteArrayMap)                                         \
   V(Map, fixed_array_map, FixedArrayMap)                                       \
-  V(Map, code_map, CodeMap)                                                    \
-  V(Map, scope_info_map, ScopeInfoMap)                                         \
   V(Map, fixed_cow_array_map, FixedCOWArrayMap)                                \
-  V(Map, fixed_double_array_map, FixedDoubleArrayMap)                          \
-  V(Map, weak_cell_map, WeakCellMap)                                           \
-  V(Map, transition_array_map, TransitionArrayMap)                             \
+  V(Map, hash_table_map, HashTableMap)                                         \
+  V(Map, symbol_map, SymbolMap)                                                \
   V(Map, one_byte_string_map, OneByteStringMap)                                \
   V(Map, one_byte_internalized_string_map, OneByteInternalizedStringMap)       \
+  V(Map, scope_info_map, ScopeInfoMap)                                         \
+  V(Map, shared_function_info_map, SharedFunctionInfoMap)                      \
+  V(Map, code_map, CodeMap)                                                    \
   V(Map, function_context_map, FunctionContextMap)                             \
+  V(Map, cell_map, CellMap)                                                    \
+  V(Map, weak_cell_map, WeakCellMap)                                           \
+  V(Map, global_property_cell_map, GlobalPropertyCellMap)                      \
+  V(Map, foreign_map, ForeignMap)                                              \
+  V(Map, heap_number_map, HeapNumberMap)                                       \
+  V(Map, transition_array_map, TransitionArrayMap)                             \
+  V(FixedArray, empty_literals_array, EmptyLiteralsArray)                      \
   V(FixedArray, empty_fixed_array, EmptyFixedArray)                            \
-  V(ByteArray, empty_byte_array, EmptyByteArray)                               \
+  V(FixedArray, cleared_optimized_code_map, ClearedOptimizedCodeMap)           \
   V(DescriptorArray, empty_descriptor_array, EmptyDescriptorArray)             \
+  /* Entries beyond the first 32                                            */ \
   /* The roots above this line should be boring from a GC point of view.    */ \
   /* This means they are never in new space and never on a page that is     */ \
   /* being compacted.                                                       */ \
+  /* Oddballs */                                                               \
   V(Oddball, no_interceptor_result_sentinel, NoInterceptorResultSentinel)      \
   V(Oddball, arguments_marker, ArgumentsMarker)                                \
   V(Oddball, exception, Exception)                                             \
   V(Oddball, termination_exception, TerminationException)                      \
   V(Oddball, optimized_out, OptimizedOut)                                      \
-  V(FixedArray, number_string_cache, NumberStringCache)                        \
-  V(Object, instanceof_cache_function, InstanceofCacheFunction)                \
-  V(Object, instanceof_cache_map, InstanceofCacheMap)                          \
-  V(Object, instanceof_cache_answer, InstanceofCacheAnswer)                    \
-  V(FixedArray, single_character_string_cache, SingleCharacterStringCache)     \
-  V(FixedArray, string_split_cache, StringSplitCache)                          \
-  V(FixedArray, regexp_multiple_cache, RegExpMultipleCache)                    \
-  V(Smi, hash_seed, HashSeed)                                                  \
-  V(Map, hash_table_map, HashTableMap)                                         \
+  V(Oddball, stale_register, StaleRegister)                                    \
+  /* Context maps */                                                           \
+  V(Map, native_context_map, NativeContextMap)                                 \
+  V(Map, module_context_map, ModuleContextMap)                                 \
+  V(Map, script_context_map, ScriptContextMap)                                 \
+  V(Map, block_context_map, BlockContextMap)                                   \
+  V(Map, catch_context_map, CatchContextMap)                                   \
+  V(Map, with_context_map, WithContextMap)                                     \
+  V(Map, debug_evaluate_context_map, DebugEvaluateContextMap)                  \
+  V(Map, script_context_table_map, ScriptContextTableMap)                      \
+  /* Maps */                                                                   \
+  V(Map, fixed_double_array_map, FixedDoubleArrayMap)                          \
+  V(Map, mutable_heap_number_map, MutableHeapNumberMap)                        \
   V(Map, ordered_hash_table_map, OrderedHashTableMap)                          \
-  V(Map, symbol_map, SymbolMap)                                                \
+  V(Map, sloppy_arguments_elements_map, SloppyArgumentsElementsMap)            \
+  V(Map, message_object_map, JSMessageObjectMap)                               \
+  V(Map, neander_map, NeanderMap)                                              \
+  V(Map, external_map, ExternalMap)                                            \
+  V(Map, bytecode_array_map, BytecodeArrayMap)                                 \
+  /* String maps */                                                            \
+  V(Map, native_source_string_map, NativeSourceStringMap)                      \
   V(Map, string_map, StringMap)                                                \
   V(Map, cons_one_byte_string_map, ConsOneByteStringMap)                       \
   V(Map, cons_string_map, ConsStringMap)                                       \
@@ -98,7 +103,6 @@
   V(Map, external_string_with_one_byte_data_map,                               \
     ExternalStringWithOneByteDataMap)                                          \
   V(Map, external_one_byte_string_map, ExternalOneByteStringMap)               \
-  V(Map, native_source_string_map, NativeSourceStringMap)                      \
   V(Map, short_external_string_map, ShortExternalStringMap)                    \
   V(Map, short_external_string_with_one_byte_data_map,                         \
     ShortExternalStringWithOneByteDataMap)                                     \
@@ -115,6 +119,7 @@
   V(Map, short_external_one_byte_internalized_string_map,                      \
     ShortExternalOneByteInternalizedStringMap)                                 \
   V(Map, short_external_one_byte_string_map, ShortExternalOneByteStringMap)    \
+  /* Array element maps */                                                     \
   V(Map, fixed_uint8_array_map, FixedUint8ArrayMap)                            \
   V(Map, fixed_int8_array_map, FixedInt8ArrayMap)                              \
   V(Map, fixed_uint16_array_map, FixedUint16ArrayMap)                          \
@@ -124,6 +129,18 @@
   V(Map, fixed_float32_array_map, FixedFloat32ArrayMap)                        \
   V(Map, fixed_float64_array_map, FixedFloat64ArrayMap)                        \
   V(Map, fixed_uint8_clamped_array_map, FixedUint8ClampedArrayMap)             \
+  V(Map, float32x4_map, Float32x4Map)                                          \
+  V(Map, int32x4_map, Int32x4Map)                                              \
+  V(Map, uint32x4_map, Uint32x4Map)                                            \
+  V(Map, bool32x4_map, Bool32x4Map)                                            \
+  V(Map, int16x8_map, Int16x8Map)                                              \
+  V(Map, uint16x8_map, Uint16x8Map)                                            \
+  V(Map, bool16x8_map, Bool16x8Map)                                            \
+  V(Map, int8x16_map, Int8x16Map)                                              \
+  V(Map, uint8x16_map, Uint8x16Map)                                            \
+  V(Map, bool8x16_map, Bool8x16Map)                                            \
+  /* Canonical empty values */                                                 \
+  V(ByteArray, empty_byte_array, EmptyByteArray)                               \
   V(FixedTypedArrayBase, empty_fixed_uint8_array, EmptyFixedUint8Array)        \
   V(FixedTypedArrayBase, empty_fixed_int8_array, EmptyFixedInt8Array)          \
   V(FixedTypedArrayBase, empty_fixed_uint16_array, EmptyFixedUint16Array)      \
@@ -134,14 +151,57 @@
   V(FixedTypedArrayBase, empty_fixed_float64_array, EmptyFixedFloat64Array)    \
   V(FixedTypedArrayBase, empty_fixed_uint8_clamped_array,                      \
     EmptyFixedUint8ClampedArray)                                               \
-  V(Map, sloppy_arguments_elements_map, SloppyArgumentsElementsMap)            \
-  V(Map, catch_context_map, CatchContextMap)                                   \
-  V(Map, with_context_map, WithContextMap)                                     \
-  V(Map, debug_evaluate_context_map, DebugEvaluateContextMap)                  \
-  V(Map, block_context_map, BlockContextMap)                                   \
-  V(Map, module_context_map, ModuleContextMap)                                 \
-  V(Map, script_context_map, ScriptContextMap)                                 \
-  V(Map, script_context_table_map, ScriptContextTableMap)                      \
+  V(Script, empty_script, EmptyScript)                                         \
+  V(Cell, undefined_cell, UndefinedCell)                                       \
+  V(FixedArray, empty_sloppy_arguments_elements, EmptySloppyArgumentsElements) \
+  V(SeededNumberDictionary, empty_slow_element_dictionary,                     \
+    EmptySlowElementDictionary)                                                \
+  V(TypeFeedbackVector, dummy_vector, DummyVector)                             \
+  V(PropertyCell, empty_property_cell, EmptyPropertyCell)                      \
+  V(WeakCell, empty_weak_cell, EmptyWeakCell)                                  \
+  /* Protectors */                                                             \
+  V(PropertyCell, array_protector, ArrayProtector)                             \
+  V(Cell, is_concat_spreadable_protector, IsConcatSpreadableProtector)         \
+  V(PropertyCell, has_instance_protector, HasInstanceProtector)                \
+  V(Cell, species_protector, SpeciesProtector)                                 \
+  /* Special numbers */                                                        \
+  V(HeapNumber, nan_value, NanValue)                                           \
+  V(HeapNumber, infinity_value, InfinityValue)                                 \
+  V(HeapNumber, minus_zero_value, MinusZeroValue)                              \
+  V(HeapNumber, minus_infinity_value, MinusInfinityValue)                      \
+  /* Caches */                                                                 \
+  V(FixedArray, number_string_cache, NumberStringCache)                        \
+  V(FixedArray, single_character_string_cache, SingleCharacterStringCache)     \
+  V(FixedArray, string_split_cache, StringSplitCache)                          \
+  V(FixedArray, regexp_multiple_cache, RegExpMultipleCache)                    \
+  V(Object, instanceof_cache_function, InstanceofCacheFunction)                \
+  V(Object, instanceof_cache_map, InstanceofCacheMap)                          \
+  V(Object, instanceof_cache_answer, InstanceofCacheAnswer)                    \
+  V(FixedArray, natives_source_cache, NativesSourceCache)                      \
+  V(FixedArray, experimental_natives_source_cache,                             \
+    ExperimentalNativesSourceCache)                                            \
+  V(FixedArray, extra_natives_source_cache, ExtraNativesSourceCache)           \
+  V(FixedArray, experimental_extra_natives_source_cache,                       \
+    ExperimentalExtraNativesSourceCache)                                       \
+  /* Lists and dictionaries */                                                 \
+  V(NameDictionary, intrinsic_function_names, IntrinsicFunctionNames)          \
+  V(NameDictionary, empty_properties_dictionary, EmptyPropertiesDictionary)    \
+  V(Object, symbol_registry, SymbolRegistry)                                   \
+  V(Object, script_list, ScriptList)                                           \
+  V(UnseededNumberDictionary, code_stubs, CodeStubs)                           \
+  V(FixedArray, materialized_objects, MaterializedObjects)                     \
+  V(FixedArray, microtask_queue, MicrotaskQueue)                               \
+  V(FixedArray, detached_contexts, DetachedContexts)                           \
+  V(ArrayList, retained_maps, RetainedMaps)                                    \
+  V(WeakHashTable, weak_object_to_code_table, WeakObjectToCodeTable)           \
+  V(Object, weak_stack_trace_list, WeakStackTraceList)                         \
+  V(Object, noscript_shared_function_infos, NoScriptSharedFunctionInfos)       \
+  V(FixedArray, serialized_templates, SerializedTemplates)                     \
+  /* Configured values */                                                      \
+  V(JSObject, message_listeners, MessageListeners)                             \
+  V(Code, js_entry_code, JsEntryCode)                                          \
+  V(Code, js_construct_entry_code, JsConstructEntryCode)                       \
+  /* Oddball maps */                                                           \
   V(Map, undefined_map, UndefinedMap)                                          \
   V(Map, the_hole_map, TheHoleMap)                                             \
   V(Map, null_map, NullMap)                                                    \
@@ -152,60 +212,22 @@
   V(Map, exception_map, ExceptionMap)                                          \
   V(Map, termination_exception_map, TerminationExceptionMap)                   \
   V(Map, optimized_out_map, OptimizedOutMap)                                   \
-  V(Map, message_object_map, JSMessageObjectMap)                               \
-  V(Map, foreign_map, ForeignMap)                                              \
-  V(Map, neander_map, NeanderMap)                                              \
-  V(Map, external_map, ExternalMap)                                            \
-  V(HeapNumber, nan_value, NanValue)                                           \
-  V(HeapNumber, infinity_value, InfinityValue)                                 \
-  V(HeapNumber, minus_zero_value, MinusZeroValue)                              \
-  V(HeapNumber, minus_infinity_value, MinusInfinityValue)                      \
-  V(JSObject, message_listeners, MessageListeners)                             \
-  V(UnseededNumberDictionary, code_stubs, CodeStubs)                           \
-  V(UnseededNumberDictionary, non_monomorphic_cache, NonMonomorphicCache)      \
-  V(PolymorphicCodeCache, polymorphic_code_cache, PolymorphicCodeCache)        \
-  V(Code, js_entry_code, JsEntryCode)                                          \
-  V(Code, js_construct_entry_code, JsConstructEntryCode)                       \
-  V(FixedArray, natives_source_cache, NativesSourceCache)                      \
-  V(FixedArray, experimental_natives_source_cache,                             \
-    ExperimentalNativesSourceCache)                                            \
-  V(FixedArray, extra_natives_source_cache, ExtraNativesSourceCache)           \
-  V(FixedArray, experimental_extra_natives_source_cache,                       \
-    ExperimentalExtraNativesSourceCache)                                       \
-  V(Script, empty_script, EmptyScript)                                         \
-  V(NameDictionary, intrinsic_function_names, IntrinsicFunctionNames)          \
-  V(NameDictionary, empty_properties_dictionary, EmptyPropertiesDictionary)    \
-  V(Cell, undefined_cell, UndefinedCell)                                       \
-  V(JSObject, observation_state, ObservationState)                             \
-  V(Object, symbol_registry, SymbolRegistry)                                   \
-  V(Object, script_list, ScriptList)                                           \
-  V(SeededNumberDictionary, empty_slow_element_dictionary,                     \
-    EmptySlowElementDictionary)                                                \
-  V(FixedArray, materialized_objects, MaterializedObjects)                     \
-  V(FixedArray, microtask_queue, MicrotaskQueue)                               \
-  V(TypeFeedbackVector, dummy_vector, DummyVector)                             \
-  V(FixedArray, cleared_optimized_code_map, ClearedOptimizedCodeMap)           \
-  V(FixedArray, detached_contexts, DetachedContexts)                           \
-  V(ArrayList, retained_maps, RetainedMaps)                                    \
-  V(WeakHashTable, weak_object_to_code_table, WeakObjectToCodeTable)           \
-  V(PropertyCell, array_protector, ArrayProtector)                             \
-  V(PropertyCell, empty_property_cell, EmptyPropertyCell)                      \
-  V(Object, weak_stack_trace_list, WeakStackTraceList)                         \
-  V(Object, noscript_shared_function_infos, NoScriptSharedFunctionInfos)       \
-  V(Map, bytecode_array_map, BytecodeArrayMap)                                 \
-  V(WeakCell, empty_weak_cell, EmptyWeakCell)                                  \
-  V(PropertyCell, species_protector, SpeciesProtector)
+  V(Map, stale_register_map, StaleRegisterMap)
 
 // Entries in this list are limited to Smis and are not visited during GC.
-#define SMI_ROOT_LIST(V)                                                   \
-  V(Smi, stack_limit, StackLimit)                                          \
-  V(Smi, real_stack_limit, RealStackLimit)                                 \
-  V(Smi, last_script_id, LastScriptId)                                     \
-  V(Smi, arguments_adaptor_deopt_pc_offset, ArgumentsAdaptorDeoptPCOffset) \
-  V(Smi, construct_stub_deopt_pc_offset, ConstructStubDeoptPCOffset)       \
-  V(Smi, getter_stub_deopt_pc_offset, GetterStubDeoptPCOffset)             \
-  V(Smi, setter_stub_deopt_pc_offset, SetterStubDeoptPCOffset)
-
+#define SMI_ROOT_LIST(V)                                                       \
+  V(Smi, stack_limit, StackLimit)                                              \
+  V(Smi, real_stack_limit, RealStackLimit)                                     \
+  V(Smi, last_script_id, LastScriptId)                                         \
+  V(Smi, hash_seed, HashSeed)                                                  \
+  /* To distinguish the function templates, so that we can find them in the */ \
+  /* function cache of the native context. */                                  \
+  V(Smi, next_template_serial_number, NextTemplateSerialNumber)                \
+  V(Smi, arguments_adaptor_deopt_pc_offset, ArgumentsAdaptorDeoptPCOffset)     \
+  V(Smi, construct_stub_deopt_pc_offset, ConstructStubDeoptPCOffset)           \
+  V(Smi, getter_stub_deopt_pc_offset, GetterStubDeoptPCOffset)                 \
+  V(Smi, setter_stub_deopt_pc_offset, SetterStubDeoptPCOffset)                 \
+  V(Smi, interpreter_entry_return_pc_offset, InterpreterEntryReturnPCOffset)
 
 #define ROOT_LIST(V)  \
   STRONG_ROOT_LIST(V) \
@@ -300,6 +322,8 @@
 class ScavengeJob;
 class WeakObjectRetainer;
 
+enum PromotionMode { PROMOTE_MARKED, DEFAULT_PROMOTION };
+
 typedef void (*ObjectSlotCallback)(HeapObject** from, HeapObject* to);
 
 // A queue of objects promoted during scavenge. Each object is accompanied
@@ -325,7 +349,7 @@
   }
 
   Page* GetHeadPage() {
-    return Page::FromAllocationTop(reinterpret_cast<Address>(rear_));
+    return Page::FromAllocationAreaAddress(reinterpret_cast<Address>(rear_));
   }
 
   void SetNewLimit(Address limit) {
@@ -333,7 +357,7 @@
     if (emergency_stack_) return;
 
     // If the limit is not on the same page, we can ignore it.
-    if (Page::FromAllocationTop(limit) != GetHeadPage()) return;
+    if (Page::FromAllocationAreaAddress(limit) != GetHeadPage()) return;
 
     limit_ = reinterpret_cast<struct Entry*>(limit);
 
@@ -568,7 +592,7 @@
   static inline bool IsOneByte(T t, int chars);
 
   static void FatalProcessOutOfMemory(const char* location,
-                                      bool take_snapshot = false);
+                                      bool is_heap_oom = false);
 
   static bool RootIsImmortalImmovable(int root_index);
 
@@ -602,6 +626,12 @@
   // stored on the map to facilitate fast dispatch for {StaticVisitorBase}.
   static int GetStaticVisitorIdForMap(Map* map);
 
+  // We cannot avoid stale handles to left-trimmed objects, but can only make
+  // sure all handles still needed are updated. Filter out a stale pointer
+  // and clear the slot to allow post processing of handles (needed because
+  // the sweeper might actually free the underlying page).
+  inline bool PurgeLeftTrimmedObject(Object** object);
+
   // Notifies the heap that is ok to start marking or other activities that
   // should not happen during deserialization.
   void NotifyDeserializationComplete();
@@ -626,11 +656,9 @@
     return old_space_->allocation_limit_address();
   }
 
-  // TODO(hpayer): There is still a missmatch between capacity and actual
-  // committed memory size.
-  bool CanExpandOldGeneration(int size = 0) {
+  bool CanExpandOldGeneration(int size) {
     if (force_oom_) return false;
-    return (CommittedOldGenerationMemory() + size) < MaxOldGenerationSize();
+    return (OldGenerationCapacity() + size) < MaxOldGenerationSize();
   }
 
   // Clear the Instanceof cache (used when a prototype changes).
@@ -730,6 +758,14 @@
   // Returns false if not able to reserve.
   bool ReserveSpace(Reservation* reservations);
 
+  void SetEmbedderHeapTracer(EmbedderHeapTracer* tracer);
+
+  bool UsingEmbedderHeapTracer();
+
+  void TracePossibleWrapper(JSObject* js_object);
+
+  void RegisterExternallyReferencedObject(Object** object);
+
   //
   // Support for the API.
   //
@@ -767,19 +803,17 @@
 
   // An object should be promoted if the object has survived a
   // scavenge operation.
+  template <PromotionMode promotion_mode>
   inline bool ShouldBePromoted(Address old_address, int object_size);
 
+  inline PromotionMode CurrentPromotionMode();
+
   void ClearNormalizedMapCaches();
 
   void IncrementDeferredCount(v8::Isolate::UseCounterFeature feature);
 
   inline bool OldGenerationAllocationLimitReached();
 
-  void QueueMemoryChunkForFree(MemoryChunk* chunk);
-  void FreeQueuedChunks(MemoryChunk* list_head);
-  void FreeQueuedChunks();
-  void WaitUntilUnmappingOfFreeChunksCompleted();
-
   // Completely clear the Instanceof cache (to stop it keeping objects alive
   // around a GC).
   inline void CompletelyClearInstanceofCache();
@@ -792,6 +826,10 @@
   inline void SetConstructStubDeoptPCOffset(int pc_offset);
   inline void SetGetterStubDeoptPCOffset(int pc_offset);
   inline void SetSetterStubDeoptPCOffset(int pc_offset);
+  inline void SetInterpreterEntryReturnPCOffset(int pc_offset);
+  inline int GetNextTemplateSerialNumber();
+
+  inline void SetSerializedTemplates(FixedArray* templates);
 
   // For post mortem debugging.
   void RememberUnmappedPage(Address page, bool compacted);
@@ -804,12 +842,16 @@
     global_ic_age_ = (global_ic_age_ + 1) & SharedFunctionInfo::ICAgeBits::kMax;
   }
 
-  int64_t amount_of_external_allocated_memory() {
-    return amount_of_external_allocated_memory_;
+  int64_t external_memory() { return external_memory_; }
+  void update_external_memory(int64_t delta) { external_memory_ += delta; }
+
+  void update_external_memory_concurrently_freed(intptr_t freed) {
+    external_memory_concurrently_freed_.Increment(freed);
   }
 
-  void update_amount_of_external_allocated_memory(int64_t delta) {
-    amount_of_external_allocated_memory_ += delta;
+  void account_external_memory_concurrently_freed() {
+    external_memory_ -= external_memory_concurrently_freed_.Value();
+    external_memory_concurrently_freed_.SetValue(0);
   }
 
   void DeoptMarkedAllocationSites();
@@ -823,6 +865,8 @@
 
   DependentCode* LookupWeakObjectToCodeDependency(Handle<HeapObject> obj);
 
+  void CompactWeakFixedArrays();
+
   void AddRetainedMap(Handle<Map> map);
 
   // This event is triggered after successful allocation of a new object made
@@ -916,20 +960,12 @@
   const char* GetSpaceName(int idx);
 
   // ===========================================================================
-  // API. ======================================================================
-  // ===========================================================================
-
-  void SetEmbedderHeapTracer(EmbedderHeapTracer* tracer);
-
-  void RegisterExternallyReferencedObject(Object** object);
-
-  // ===========================================================================
   // Getters to other components. ==============================================
   // ===========================================================================
 
   GCTracer* tracer() { return tracer_; }
 
-  EmbedderHeapTracer* embedder_heap_tracer() { return embedder_heap_tracer_; }
+  MemoryAllocator* memory_allocator() { return memory_allocator_; }
 
   PromotionQueue* promotion_queue() { return &promotion_queue_; }
 
@@ -979,11 +1015,6 @@
     roots_[kCodeStubsRootIndex] = value;
   }
 
-  // Sets the non_monomorphic_cache_ (only used when expanding the dictionary).
-  void SetRootNonMonomorphicCache(UnseededNumberDictionary* value) {
-    roots_[kNonMonomorphicCacheRootIndex] = value;
-  }
-
   void SetRootMaterializedObjects(FixedArray* objects) {
     roots_[kMaterializedObjectsRootIndex] = objects;
   }
@@ -1089,6 +1120,8 @@
 
   // Write barrier support for object[offset] = o;
   inline void RecordWrite(Object* object, int offset, Object* o);
+  inline void RecordFixedArrayElements(FixedArray* array, int offset,
+                                       int length);
 
   Address* store_buffer_top_address() { return store_buffer()->top_address(); }
 
@@ -1176,6 +1209,13 @@
                          const char** object_sub_type);
 
   // ===========================================================================
+  // Code statistics. ==========================================================
+  // ===========================================================================
+
+  // Collect code (Code and BytecodeArray objects) statistics.
+  void CollectCodeStatistics();
+
+  // ===========================================================================
   // GC statistics. ============================================================
   // ===========================================================================
 
@@ -1192,6 +1232,9 @@
   // more spaces are needed until it reaches the limit.
   intptr_t Capacity();
 
+  // Returns the capacity of the old generation.
+  intptr_t OldGenerationCapacity();
+
   // Returns the amount of memory currently committed for the heap.
   intptr_t CommittedMemory();
 
@@ -1347,10 +1390,6 @@
   void RegisterNewArrayBuffer(JSArrayBuffer* buffer);
   void UnregisterArrayBuffer(JSArrayBuffer* buffer);
 
-  inline ArrayBufferTracker* array_buffer_tracker() {
-    return array_buffer_tracker_;
-  }
-
   // ===========================================================================
   // Allocation site tracking. =================================================
   // ===========================================================================
@@ -1362,7 +1401,7 @@
   // value) is cached on the local pretenuring feedback.
   template <UpdateAllocationSiteMode mode>
   inline void UpdateAllocationSite(HeapObject* object,
-                                   HashMap* pretenuring_feedback);
+                                   base::HashMap* pretenuring_feedback);
 
   // Removes an entry from the global pretenuring storage.
   inline void RemoveAllocationSitePretenuringFeedback(AllocationSite* site);
@@ -1371,7 +1410,7 @@
   // method needs to be called after evacuation, as allocation sites may be
   // evacuated and this method resolves forward pointers accordingly.
   void MergeAllocationSitePretenuringFeedback(
-      const HashMap& local_pretenuring_feedback);
+      const base::HashMap& local_pretenuring_feedback);
 
 // =============================================================================
 
@@ -1394,13 +1433,9 @@
   void ReportHeapStatistics(const char* title);
   void ReportCodeStatistics(const char* title);
 #endif
-#ifdef ENABLE_SLOW_DCHECKS
-  int CountHandlesForObject(Object* object);
-#endif
 
  private:
   class PretenuringScope;
-  class UnmapFreeMemoryTask;
 
   // External strings table is a place where all external strings are
   // registered.  We need to keep track of such strings to properly
@@ -1692,7 +1727,8 @@
   // Performs a minor collection in new generation.
   void Scavenge();
 
-  Address DoScavenge(ObjectVisitor* scavenge_visitor, Address new_space_front);
+  Address DoScavenge(ObjectVisitor* scavenge_visitor, Address new_space_front,
+                     PromotionMode promotion_mode);
 
   void UpdateNewSpaceReferencesInExternalStringTable(
       ExternalStringTableUpdaterCallback updater_func);
@@ -1817,11 +1853,6 @@
   AllocateBytecodeArray(int length, const byte* raw_bytecodes, int frame_size,
                         int parameter_count, FixedArray* constant_pool);
 
-  // Copy the code and scope info part of the code object, but insert
-  // the provided data as the relocation information.
-  MUST_USE_RESULT AllocationResult CopyCode(Code* code,
-                                            Vector<byte> reloc_info);
-
   MUST_USE_RESULT AllocationResult CopyCode(Code* code);
 
   MUST_USE_RESULT AllocationResult
@@ -1981,12 +2012,17 @@
 
   void set_force_oom(bool value) { force_oom_ = value; }
 
-  // The amount of external memory registered through the API kept alive
-  // by global handles
-  int64_t amount_of_external_allocated_memory_;
+  // The amount of external memory registered through the API.
+  int64_t external_memory_;
 
-  // Caches the amount of external memory registered at the last global gc.
-  int64_t amount_of_external_allocated_memory_at_last_global_gc_;
+  // The limit when to trigger memory pressure from the API.
+  int64_t external_memory_limit_;
+
+  // Caches the amount of external memory registered at the last MC.
+  int64_t external_memory_at_last_mark_compact_;
+
+  // The amount of memory that has been freed concurrently.
+  base::AtomicNumber<intptr_t> external_memory_concurrently_freed_;
 
   // This can be calculated directly from a pointer to the heap; however, it is
   // more expedient to get at the isolate directly from within Heap methods.
@@ -2012,11 +2048,11 @@
 
   // This is not the depth of nested AlwaysAllocateScope's but rather a single
   // count, as scopes can be acquired from multiple tasks (read: threads).
-  AtomicNumber<size_t> always_allocate_scope_count_;
+  base::AtomicNumber<size_t> always_allocate_scope_count_;
 
   // Stores the memory pressure level that set by MemoryPressureNotification
   // and reset by a mark-compact garbage collection.
-  AtomicValue<MemoryPressureLevel> memory_pressure_level_;
+  base::AtomicValue<MemoryPressureLevel> memory_pressure_level_;
 
   // For keeping track of context disposals.
   int contexts_disposed_;
@@ -2104,7 +2140,6 @@
   int deferred_counters_[v8::Isolate::kUseCounterFeatureCount];
 
   GCTracer* tracer_;
-  EmbedderHeapTracer* embedder_heap_tracer_;
 
   int high_survival_rate_period_length_;
   intptr_t promoted_objects_size_;
@@ -2151,6 +2186,8 @@
 
   MarkCompactCollector* mark_compact_collector_;
 
+  MemoryAllocator* memory_allocator_;
+
   StoreBuffer store_buffer_;
 
   IncrementalMarking* incremental_marking_;
@@ -2192,7 +2229,7 @@
   // storage is only alive temporary during a GC. The invariant is that all
   // pointers in this map are already fixed, i.e., they do not point to
   // forwarding pointers.
-  HashMap* global_pretenuring_feedback_;
+  base::HashMap* global_pretenuring_feedback_;
 
   char trace_ring_buffer_[kTraceRingBufferSize];
   // If it's not full then the data is from 0 to ring_buffer_end_.  If it's
@@ -2217,12 +2254,6 @@
 
   ExternalStringTable external_string_table_;
 
-  MemoryChunk* chunks_queued_for_free_;
-
-  size_t concurrent_unmapping_tasks_active_;
-
-  base::Semaphore pending_unmapping_tasks_semaphore_;
-
   base::Mutex relocation_mutex_;
 
   int gc_callbacks_depth_;
@@ -2231,8 +2262,6 @@
 
   StrongRootsList* strong_roots_list_;
 
-  ArrayBufferTracker* array_buffer_tracker_;
-
   // The depth of HeapIterator nestings.
   int heap_iterator_depth_;
 
@@ -2250,10 +2279,11 @@
   friend class MarkCompactCollector;
   friend class MarkCompactMarkingVisitor;
   friend class NewSpace;
-  friend class ObjectStatsVisitor;
+  friend class ObjectStatsCollector;
   friend class Page;
   friend class Scavenger;
   friend class StoreBuffer;
+  friend class TestMemoryAllocatorScope;
 
   // The allocator interface.
   friend class Factory;
diff --git a/src/heap/incremental-marking-job.cc b/src/heap/incremental-marking-job.cc
index 3ccbec2..fe14dd0 100644
--- a/src/heap/incremental-marking-job.cc
+++ b/src/heap/incremental-marking-job.cc
@@ -71,14 +71,12 @@
 IncrementalMarkingJob::IdleTask::Progress IncrementalMarkingJob::IdleTask::Step(
     Heap* heap, double deadline_in_ms) {
   IncrementalMarking* incremental_marking = heap->incremental_marking();
-  MarkCompactCollector* mark_compact_collector = heap->mark_compact_collector();
   if (incremental_marking->IsStopped()) {
     return kDone;
   }
-  if (mark_compact_collector->sweeping_in_progress()) {
-    if (mark_compact_collector->IsSweepingCompleted()) {
-      mark_compact_collector->EnsureSweepingCompleted();
-    }
+  if (incremental_marking->IsSweeping()) {
+    incremental_marking->FinalizeSweeping();
+    // TODO(hpayer): We can continue here if enough idle time is left.
     return kMoreWork;
   }
   const double remaining_idle_time_in_ms =
diff --git a/src/heap/incremental-marking.cc b/src/heap/incremental-marking.cc
index 376e848..f578d43 100644
--- a/src/heap/incremental-marking.cc
+++ b/src/heap/incremental-marking.cc
@@ -10,8 +10,9 @@
 #include "src/heap/gc-idle-time-handler.h"
 #include "src/heap/gc-tracer.h"
 #include "src/heap/mark-compact-inl.h"
-#include "src/heap/objects-visiting.h"
+#include "src/heap/object-stats.h"
 #include "src/heap/objects-visiting-inl.h"
+#include "src/heap/objects-visiting.h"
 #include "src/tracing/trace-event.h"
 #include "src/v8.h"
 
@@ -175,6 +176,9 @@
     table_.Register(kVisitFixedArray, &VisitFixedArrayIncremental);
     table_.Register(kVisitNativeContext, &VisitNativeContextIncremental);
     table_.Register(kVisitJSRegExp, &VisitJSRegExp);
+    if (FLAG_track_gc_object_stats) {
+      IncrementalMarkingObjectStatsVisitor::Initialize(&table_);
+    }
   }
 
   static const int kProgressBarScanningChunk = 32 * 1024;
@@ -231,7 +235,7 @@
     // Note that GC can happen when the context is not fully initialized,
     // so the cache can be undefined.
     Object* cache = context->get(Context::NORMALIZED_MAP_CACHE_INDEX);
-    if (!cache->IsUndefined()) {
+    if (!cache->IsUndefined(map->GetIsolate())) {
       MarkObjectGreyDoNotEnqueue(cache);
     }
     VisitNativeContext(map, context);
@@ -279,7 +283,7 @@
   if (IsMarking() && Marking::IsBlack(Marking::MarkBitFrom(object))) {
     Page* page = Page::FromAddress(object->address());
     if ((page->owner() != nullptr) && (page->owner()->identity() == LO_SPACE)) {
-      // IterateBlackObject requires us to visit the hole object.
+      // IterateBlackObject requires us to visit the whole object.
       page->ResetProgressBar();
     }
     IncrementalMarkingMarkingVisitor::IterateBody(object->map(), object);
@@ -341,9 +345,7 @@
 
 void IncrementalMarking::DeactivateIncrementalWriteBarrierForSpace(
     PagedSpace* space) {
-  PageIterator it(space);
-  while (it.has_next()) {
-    Page* p = it.next();
+  for (Page* p : *space) {
     SetOldSpacePageFlags(p, false, false);
   }
 }
@@ -351,9 +353,7 @@
 
 void IncrementalMarking::DeactivateIncrementalWriteBarrierForSpace(
     NewSpace* space) {
-  NewSpacePageIterator it(space);
-  while (it.has_next()) {
-    NewSpacePage* p = it.next();
+  for (Page* p : *space) {
     SetNewSpacePageFlags(p, false);
   }
 }
@@ -365,27 +365,21 @@
   DeactivateIncrementalWriteBarrierForSpace(heap_->code_space());
   DeactivateIncrementalWriteBarrierForSpace(heap_->new_space());
 
-  LargePage* lop = heap_->lo_space()->first_page();
-  while (lop->is_valid()) {
+  for (LargePage* lop : *heap_->lo_space()) {
     SetOldSpacePageFlags(lop, false, false);
-    lop = lop->next_page();
   }
 }
 
 
 void IncrementalMarking::ActivateIncrementalWriteBarrier(PagedSpace* space) {
-  PageIterator it(space);
-  while (it.has_next()) {
-    Page* p = it.next();
+  for (Page* p : *space) {
     SetOldSpacePageFlags(p, true, is_compacting_);
   }
 }
 
 
 void IncrementalMarking::ActivateIncrementalWriteBarrier(NewSpace* space) {
-  NewSpacePageIterator it(space->ToSpaceStart(), space->ToSpaceEnd());
-  while (it.has_next()) {
-    NewSpacePage* p = it.next();
+  for (Page* p : *space) {
     SetNewSpacePageFlags(p, true);
   }
 }
@@ -397,10 +391,8 @@
   ActivateIncrementalWriteBarrier(heap_->code_space());
   ActivateIncrementalWriteBarrier(heap_->new_space());
 
-  LargePage* lop = heap_->lo_space()->first_page();
-  while (lop->is_valid()) {
+  for (LargePage* lop : *heap_->lo_space()) {
     SetOldSpacePageFlags(lop, true, is_compacting_);
-    lop = lop->next_page();
   }
 }
 
@@ -469,9 +461,10 @@
   UnseededNumberDictionary* stubs = heap->code_stubs();
 
   int capacity = stubs->Capacity();
+  Isolate* isolate = heap->isolate();
   for (int i = 0; i < capacity; i++) {
     Object* k = stubs->KeyAt(i);
-    if (stubs->IsKey(k)) {
+    if (stubs->IsKey(isolate, k)) {
       uint32_t key = NumberToUint32(k);
 
       if (CodeStub::MajorKeyFromKey(key) == CodeStub::RecordWrite) {
@@ -537,6 +530,10 @@
 
   state_ = MARKING;
 
+  if (heap_->UsingEmbedderHeapTracer()) {
+    heap_->mark_compact_collector()->embedder_heap_tracer()->TracePrologue();
+  }
+
   RecordWriteStub::Mode mode = is_compacting_
                                    ? RecordWriteStub::INCREMENTAL_COMPACTION
                                    : RecordWriteStub::INCREMENTAL;
@@ -558,12 +555,6 @@
   heap_->CompletelyClearInstanceofCache();
   heap_->isolate()->compilation_cache()->MarkCompactPrologue();
 
-  if (FLAG_cleanup_code_caches_at_gc) {
-    // We will mark cache black with a separate pass
-    // when we finish marking.
-    MarkObjectGreyDoNotEnqueue(heap_->polymorphic_code_cache());
-  }
-
   // Mark strong roots grey.
   IncrementalMarkingRootMarkingVisitor visitor(this);
   heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG);
@@ -605,6 +596,7 @@
 
 
 void IncrementalMarking::MarkObjectGroups() {
+  DCHECK(!heap_->UsingEmbedderHeapTracer());
   DCHECK(!finalize_marking_completed_);
   DCHECK(IsMarking());
 
@@ -735,7 +727,9 @@
   // 4) Remove weak cell with live values from the list of weak cells, they
   // do not need processing during GC.
   MarkRoots();
-  MarkObjectGroups();
+  if (!heap_->UsingEmbedderHeapTracer()) {
+    MarkObjectGroups();
+  }
   if (incremental_marking_finalization_rounds_ == 0) {
     // Map retaining is needed for perfromance, not correctness,
     // so we can do it only once at the beginning of the finalization.
@@ -932,27 +926,20 @@
     }
   }
 
-  if (FLAG_cleanup_code_caches_at_gc) {
-    PolymorphicCodeCache* poly_cache = heap_->polymorphic_code_cache();
-    Marking::GreyToBlack(Marking::MarkBitFrom(poly_cache));
-    MemoryChunk::IncrementLiveBytesFromGC(poly_cache,
-                                          PolymorphicCodeCache::kSize);
-  }
-
   Object* context = heap_->native_contexts_list();
-  while (!context->IsUndefined()) {
+  while (!context->IsUndefined(heap_->isolate())) {
     // GC can happen when the context is not fully initialized,
     // so the cache can be undefined.
     HeapObject* cache = HeapObject::cast(
         Context::cast(context)->get(Context::NORMALIZED_MAP_CACHE_INDEX));
-    if (!cache->IsUndefined()) {
+    if (!cache->IsUndefined(heap_->isolate())) {
       MarkBit mark_bit = Marking::MarkBitFrom(cache);
       if (Marking::IsGrey(mark_bit)) {
         Marking::GreyToBlack(mark_bit);
         MemoryChunk::IncrementLiveBytesFromGC(cache, cache->Size());
       }
     }
-    context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
+    context = Context::cast(context)->next_context_link();
   }
 }
 
@@ -1130,6 +1117,18 @@
   }
 }
 
+void IncrementalMarking::FinalizeSweeping() {
+  DCHECK(state_ == SWEEPING);
+  if (heap_->mark_compact_collector()->sweeping_in_progress() &&
+      (heap_->mark_compact_collector()->sweeper().IsSweepingCompleted() ||
+       !FLAG_concurrent_sweeping)) {
+    heap_->mark_compact_collector()->EnsureSweepingCompleted();
+  }
+  if (!heap_->mark_compact_collector()->sweeping_in_progress()) {
+    bytes_scanned_ = 0;
+    StartMarking();
+  }
+}
 
 intptr_t IncrementalMarking::Step(intptr_t allocated_bytes,
                                   CompletionAction action,
@@ -1179,17 +1178,11 @@
 
     bytes_scanned_ += bytes_to_process;
 
+    // TODO(hpayer): Do not account for sweeping finalization while marking.
     if (state_ == SWEEPING) {
-      if (heap_->mark_compact_collector()->sweeping_in_progress() &&
-          (heap_->mark_compact_collector()->IsSweepingCompleted() ||
-           !FLAG_concurrent_sweeping)) {
-        heap_->mark_compact_collector()->EnsureSweepingCompleted();
-      }
-      if (!heap_->mark_compact_collector()->sweeping_in_progress()) {
-        bytes_scanned_ = 0;
-        StartMarking();
-      }
+      FinalizeSweeping();
     }
+
     if (state_ == MARKING) {
       bytes_processed = ProcessMarkingDeque(bytes_to_process);
       if (heap_->mark_compact_collector()->marking_deque()->IsEmpty()) {
diff --git a/src/heap/incremental-marking.h b/src/heap/incremental-marking.h
index f10150d..5f5a1de 100644
--- a/src/heap/incremental-marking.h
+++ b/src/heap/incremental-marking.h
@@ -68,6 +68,8 @@
 
   inline bool IsStopped() { return state() == STOPPED; }
 
+  inline bool IsSweeping() { return state() == SWEEPING; }
+
   INLINE(bool IsMarking()) { return state() >= MARKING; }
 
   inline bool IsMarkingIncomplete() { return state() == MARKING; }
@@ -135,6 +137,8 @@
   // incremental marking to be postponed.
   static const size_t kMaxIdleMarkingDelayCounter = 3;
 
+  void FinalizeSweeping();
+
   void OldSpaceStep(intptr_t allocated);
 
   intptr_t Step(intptr_t allocated, CompletionAction action,
@@ -181,7 +185,7 @@
     SetOldSpacePageFlags(chunk, IsMarking(), IsCompacting());
   }
 
-  inline void SetNewSpacePageFlags(MemoryChunk* chunk) {
+  inline void SetNewSpacePageFlags(Page* chunk) {
     SetNewSpacePageFlags(chunk, IsMarking());
   }
 
@@ -211,6 +215,8 @@
 
   bool black_allocation() { return black_allocation_; }
 
+  void StartBlackAllocationForTesting() { StartBlackAllocation(); }
+
  private:
   class Observer : public AllocationObserver {
    public:
diff --git a/src/heap/mark-compact-inl.h b/src/heap/mark-compact-inl.h
index 281ece4..8ecdd62 100644
--- a/src/heap/mark-compact-inl.h
+++ b/src/heap/mark-compact-inl.h
@@ -12,17 +12,6 @@
 namespace v8 {
 namespace internal {
 
-inline std::vector<Page*>& MarkCompactCollector::sweeping_list(Space* space) {
-  if (space == heap()->old_space()) {
-    return sweeping_list_old_space_;
-  } else if (space == heap()->code_space()) {
-    return sweeping_list_code_space_;
-  }
-  DCHECK_EQ(space, heap()->map_space());
-  return sweeping_list_map_space_;
-}
-
-
 void MarkCompactCollector::PushBlack(HeapObject* obj) {
   DCHECK(Marking::IsBlack(Marking::MarkBitFrom(obj)));
   if (marking_deque_.Push(obj)) {
@@ -90,7 +79,7 @@
 
 void CodeFlusher::AddCandidate(JSFunction* function) {
   DCHECK(function->code() == function->shared()->code());
-  if (function->next_function_link()->IsUndefined()) {
+  if (function->next_function_link()->IsUndefined(isolate_)) {
     SetNextCandidate(function, jsfunction_candidates_head_);
     jsfunction_candidates_head_ = function;
   }
@@ -116,7 +105,7 @@
 
 
 void CodeFlusher::ClearNextCandidate(JSFunction* candidate, Object* undefined) {
-  DCHECK(undefined->IsUndefined());
+  DCHECK(undefined->IsUndefined(candidate->GetIsolate()));
   candidate->set_next_function_link(undefined, SKIP_WRITE_BARRIER);
 }
 
diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc
index e537689..f9a55df 100644
--- a/src/heap/mark-compact.cc
+++ b/src/heap/mark-compact.cc
@@ -25,7 +25,6 @@
 #include "src/heap/spaces-inl.h"
 #include "src/ic/ic.h"
 #include "src/ic/stub-cache.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/utils-inl.h"
 #include "src/v8.h"
 
@@ -49,21 +48,22 @@
 
 MarkCompactCollector::MarkCompactCollector(Heap* heap)
     :  // NOLINT
+      heap_(heap),
+      page_parallel_job_semaphore_(0),
 #ifdef DEBUG
       state_(IDLE),
 #endif
       marking_parity_(ODD_MARKING_PARITY),
       was_marked_incrementally_(false),
       evacuation_(false),
-      heap_(heap),
+      compacting_(false),
+      black_allocation_(false),
+      have_code_to_deoptimize_(false),
       marking_deque_memory_(NULL),
       marking_deque_memory_committed_(0),
       code_flusher_(nullptr),
-      have_code_to_deoptimize_(false),
-      compacting_(false),
-      sweeping_in_progress_(false),
-      pending_sweeper_tasks_semaphore_(0),
-      pending_compaction_tasks_semaphore_(0) {
+      embedder_heap_tracer_(nullptr),
+      sweeper_(heap) {
 }
 
 #ifdef VERIFY_HEAP
@@ -131,14 +131,14 @@
 
 static void VerifyMarking(NewSpace* space) {
   Address end = space->top();
-  NewSpacePageIterator it(space->bottom(), end);
   // The bottom position is at the start of its page. Allows us to use
   // page->area_start() as start of range on all pages.
-  CHECK_EQ(space->bottom(),
-           NewSpacePage::FromAddress(space->bottom())->area_start());
-  while (it.has_next()) {
-    NewSpacePage* page = it.next();
-    Address limit = it.has_next() ? page->area_end() : end;
+  CHECK_EQ(space->bottom(), Page::FromAddress(space->bottom())->area_start());
+
+  NewSpacePageRange range(space->bottom(), end);
+  for (auto it = range.begin(); it != range.end();) {
+    Page* page = *(it++);
+    Address limit = it != range.end() ? page->area_end() : end;
     CHECK(limit == end || !page->Contains(end));
     VerifyMarking(space->heap(), page->area_start(), limit);
   }
@@ -146,10 +146,7 @@
 
 
 static void VerifyMarking(PagedSpace* space) {
-  PageIterator it(space);
-
-  while (it.has_next()) {
-    Page* p = it.next();
+  for (Page* p : *space) {
     if (p->IsFlagSet(Page::BLACK_PAGE)) {
       VerifyMarkingBlackPage(space->heap(), p);
     } else {
@@ -205,13 +202,12 @@
 
 
 static void VerifyEvacuation(NewSpace* space) {
-  NewSpacePageIterator it(space->bottom(), space->top());
   VerifyEvacuationVisitor visitor;
-
-  while (it.has_next()) {
-    NewSpacePage* page = it.next();
+  NewSpacePageRange range(space->bottom(), space->top());
+  for (auto it = range.begin(); it != range.end();) {
+    Page* page = *(it++);
     Address current = page->area_start();
-    Address limit = it.has_next() ? page->area_end() : space->top();
+    Address limit = it != range.end() ? page->area_end() : space->top();
     CHECK(limit == space->top() || !page->Contains(space->top()));
     while (current < limit) {
       HeapObject* object = HeapObject::FromAddress(current);
@@ -226,10 +222,7 @@
   if (FLAG_use_allocation_folding && (space == heap->old_space())) {
     return;
   }
-  PageIterator it(space);
-
-  while (it.has_next()) {
-    Page* p = it.next();
+  for (Page* p : *space) {
     if (p->IsEvacuationCandidate()) continue;
     VerifyEvacuation(p);
   }
@@ -361,10 +354,7 @@
 
 #ifdef VERIFY_HEAP
 void MarkCompactCollector::VerifyMarkbitsAreClean(PagedSpace* space) {
-  PageIterator it(space);
-
-  while (it.has_next()) {
-    Page* p = it.next();
+  for (Page* p : *space) {
     CHECK(p->markbits()->IsClean());
     CHECK_EQ(0, p->LiveBytes());
   }
@@ -372,10 +362,7 @@
 
 
 void MarkCompactCollector::VerifyMarkbitsAreClean(NewSpace* space) {
-  NewSpacePageIterator it(space->bottom(), space->top());
-
-  while (it.has_next()) {
-    NewSpacePage* p = it.next();
+  for (Page* p : NewSpacePageRange(space->bottom(), space->top())) {
     CHECK(p->markbits()->IsClean());
     CHECK_EQ(0, p->LiveBytes());
   }
@@ -420,10 +407,7 @@
 
 
 static void ClearMarkbitsInPagedSpace(PagedSpace* space) {
-  PageIterator it(space);
-
-  while (it.has_next()) {
-    Page* p = it.next();
+  for (Page* p : *space) {
     Bitmap::Clear(p);
     if (p->IsFlagSet(Page::BLACK_PAGE)) {
       p->ClearFlag(Page::BLACK_PAGE);
@@ -433,10 +417,8 @@
 
 
 static void ClearMarkbitsInNewSpace(NewSpace* space) {
-  NewSpacePageIterator it(space->ToSpaceStart(), space->ToSpaceEnd());
-
-  while (it.has_next()) {
-    Bitmap::Clear(it.next());
+  for (Page* page : *space) {
+    Bitmap::Clear(page);
   }
 }
 
@@ -459,52 +441,65 @@
   }
 }
 
-
-class MarkCompactCollector::SweeperTask : public v8::Task {
+class MarkCompactCollector::Sweeper::SweeperTask : public v8::Task {
  public:
-  SweeperTask(Heap* heap, AllocationSpace space_to_start)
-      : heap_(heap), space_to_start_(space_to_start) {}
+  SweeperTask(Sweeper* sweeper, base::Semaphore* pending_sweeper_tasks,
+              AllocationSpace space_to_start)
+      : sweeper_(sweeper),
+        pending_sweeper_tasks_(pending_sweeper_tasks),
+        space_to_start_(space_to_start) {}
 
   virtual ~SweeperTask() {}
 
  private:
   // v8::Task overrides.
   void Run() override {
-    DCHECK_GE(space_to_start_, FIRST_PAGED_SPACE);
+    DCHECK_GE(space_to_start_, FIRST_SPACE);
     DCHECK_LE(space_to_start_, LAST_PAGED_SPACE);
-    const int offset = space_to_start_ - FIRST_PAGED_SPACE;
-    const int num_spaces = LAST_PAGED_SPACE - FIRST_PAGED_SPACE + 1;
+    const int offset = space_to_start_ - FIRST_SPACE;
+    const int num_spaces = LAST_PAGED_SPACE - FIRST_SPACE + 1;
     for (int i = 0; i < num_spaces; i++) {
-      const int space_id = FIRST_PAGED_SPACE + ((i + offset) % num_spaces);
-      DCHECK_GE(space_id, FIRST_PAGED_SPACE);
+      const int space_id = FIRST_SPACE + ((i + offset) % num_spaces);
+      DCHECK_GE(space_id, FIRST_SPACE);
       DCHECK_LE(space_id, LAST_PAGED_SPACE);
-      heap_->mark_compact_collector()->SweepInParallel(
-          heap_->paged_space(space_id), 0);
+      sweeper_->ParallelSweepSpace(static_cast<AllocationSpace>(space_id), 0);
     }
-    heap_->mark_compact_collector()->pending_sweeper_tasks_semaphore_.Signal();
+    pending_sweeper_tasks_->Signal();
   }
 
-  Heap* heap_;
+  Sweeper* sweeper_;
+  base::Semaphore* pending_sweeper_tasks_;
   AllocationSpace space_to_start_;
 
   DISALLOW_COPY_AND_ASSIGN(SweeperTask);
 };
 
-
-void MarkCompactCollector::StartSweeperThreads() {
-  V8::GetCurrentPlatform()->CallOnBackgroundThread(
-      new SweeperTask(heap(), OLD_SPACE), v8::Platform::kShortRunningTask);
-  V8::GetCurrentPlatform()->CallOnBackgroundThread(
-      new SweeperTask(heap(), CODE_SPACE), v8::Platform::kShortRunningTask);
-  V8::GetCurrentPlatform()->CallOnBackgroundThread(
-      new SweeperTask(heap(), MAP_SPACE), v8::Platform::kShortRunningTask);
+void MarkCompactCollector::Sweeper::StartSweeping() {
+  sweeping_in_progress_ = true;
+  ForAllSweepingSpaces([this](AllocationSpace space) {
+    std::sort(sweeping_list_[space].begin(), sweeping_list_[space].end(),
+              [](Page* a, Page* b) { return a->LiveBytes() < b->LiveBytes(); });
+  });
+  if (FLAG_concurrent_sweeping) {
+    ForAllSweepingSpaces([this](AllocationSpace space) {
+      if (space == NEW_SPACE) return;
+      StartSweepingHelper(space);
+    });
+  }
 }
 
+void MarkCompactCollector::Sweeper::StartSweepingHelper(
+    AllocationSpace space_to_start) {
+  num_sweeping_tasks_.Increment(1);
+  V8::GetCurrentPlatform()->CallOnBackgroundThread(
+      new SweeperTask(this, &pending_sweeper_tasks_semaphore_, space_to_start),
+      v8::Platform::kShortRunningTask);
+}
 
-void MarkCompactCollector::SweepOrWaitUntilSweepingCompleted(Page* page) {
-  PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner());
+void MarkCompactCollector::Sweeper::SweepOrWaitUntilSweepingCompleted(
+    Page* page) {
   if (!page->SweepingDone()) {
-    SweepInParallel(page, owner);
+    ParallelSweepPage(page, page->owner()->identity());
     if (!page->SweepingDone()) {
       // We were not able to sweep that page, i.e., a concurrent
       // sweeper thread currently owns this page. Wait for the sweeper
@@ -514,34 +509,62 @@
   }
 }
 
-
 void MarkCompactCollector::SweepAndRefill(CompactionSpace* space) {
-  if (FLAG_concurrent_sweeping && !IsSweepingCompleted()) {
-    SweepInParallel(heap()->paged_space(space->identity()), 0);
+  if (FLAG_concurrent_sweeping && !sweeper().IsSweepingCompleted()) {
+    sweeper().ParallelSweepSpace(space->identity(), 0);
     space->RefillFreeList();
   }
 }
 
+Page* MarkCompactCollector::Sweeper::GetSweptPageSafe(PagedSpace* space) {
+  base::LockGuard<base::Mutex> guard(&mutex_);
+  SweptList& list = swept_list_[space->identity()];
+  if (list.length() > 0) {
+    return list.RemoveLast();
+  }
+  return nullptr;
+}
 
-void MarkCompactCollector::EnsureSweepingCompleted() {
-  DCHECK(sweeping_in_progress_ == true);
+void MarkCompactCollector::Sweeper::EnsureCompleted() {
+  if (!sweeping_in_progress_) return;
 
   // If sweeping is not completed or not running at all, we try to complete it
   // here.
   if (!FLAG_concurrent_sweeping || !IsSweepingCompleted()) {
-    SweepInParallel(heap()->paged_space(OLD_SPACE), 0);
-    SweepInParallel(heap()->paged_space(CODE_SPACE), 0);
-    SweepInParallel(heap()->paged_space(MAP_SPACE), 0);
+    ForAllSweepingSpaces(
+        [this](AllocationSpace space) { ParallelSweepSpace(space, 0); });
   }
 
   if (FLAG_concurrent_sweeping) {
-    pending_sweeper_tasks_semaphore_.Wait();
-    pending_sweeper_tasks_semaphore_.Wait();
-    pending_sweeper_tasks_semaphore_.Wait();
+    while (num_sweeping_tasks_.Value() > 0) {
+      pending_sweeper_tasks_semaphore_.Wait();
+      num_sweeping_tasks_.Increment(-1);
+    }
   }
 
-  ParallelSweepSpacesComplete();
+  ForAllSweepingSpaces([this](AllocationSpace space) {
+    if (space == NEW_SPACE) {
+      swept_list_[NEW_SPACE].Clear();
+    }
+    DCHECK(sweeping_list_[space].empty());
+  });
+  late_pages_ = false;
   sweeping_in_progress_ = false;
+}
+
+void MarkCompactCollector::Sweeper::EnsureNewSpaceCompleted() {
+  if (!sweeping_in_progress_) return;
+  if (!FLAG_concurrent_sweeping || !IsSweepingCompleted()) {
+    for (Page* p : *heap_->new_space()) {
+      SweepOrWaitUntilSweepingCompleted(p);
+    }
+  }
+}
+
+void MarkCompactCollector::EnsureSweepingCompleted() {
+  if (!sweeper().sweeping_in_progress()) return;
+
+  sweeper().EnsureCompleted();
   heap()->old_space()->RefillFreeList();
   heap()->code_space()->RefillFreeList();
   heap()->map_space()->RefillFreeList();
@@ -553,17 +576,14 @@
 #endif
 }
 
-
-bool MarkCompactCollector::IsSweepingCompleted() {
-  if (!pending_sweeper_tasks_semaphore_.WaitFor(
-          base::TimeDelta::FromSeconds(0))) {
-    return false;
+bool MarkCompactCollector::Sweeper::IsSweepingCompleted() {
+  while (pending_sweeper_tasks_semaphore_.WaitFor(
+      base::TimeDelta::FromSeconds(0))) {
+    num_sweeping_tasks_.Increment(-1);
   }
-  pending_sweeper_tasks_semaphore_.Signal();
-  return true;
+  return num_sweeping_tasks_.Value() == 0;
 }
 
-
 void Marking::TransferMark(Heap* heap, Address old_start, Address new_start) {
   // This is only used when resizing an object.
   DCHECK(MemoryChunk::FromAddress(old_start) ==
@@ -676,9 +696,7 @@
   std::vector<LiveBytesPagePair> pages;
   pages.reserve(number_of_pages);
 
-  PageIterator it(space);
-  while (it.has_next()) {
-    Page* p = it.next();
+  for (Page* p : *space) {
     if (p->NeverEvacuate()) continue;
     if (p->IsFlagSet(Page::BLACK_PAGE)) continue;
     // Invariant: Evacuation candidates are just created when marking is
@@ -759,8 +777,8 @@
       if (FLAG_trace_fragmentation_verbose) {
         PrintIsolate(isolate(),
                      "compaction-selection-page: space=%s free_bytes_page=%d "
-                     "fragmentation_limit_kb=%d fragmentation_limit_percent=%d "
-                     "sum_compaction_kb=%d "
+                     "fragmentation_limit_kb=%" V8PRIdPTR
+                     " fragmentation_limit_percent=%d sum_compaction_kb=%d "
                      "compaction_limit_kb=%d\n",
                      AllocationSpaceName(space->identity()), free_bytes / KB,
                      free_bytes_threshold / KB, target_fragmentation_percent,
@@ -821,7 +839,7 @@
 
   // If concurrent unmapping tasks are still running, we should wait for
   // them here.
-  heap()->WaitUntilUnmappingOfFreeChunksCompleted();
+  heap()->memory_allocator()->unmapper()->WaitUntilCompleted();
 
   // Clear marking bits if incremental marking is aborted.
   if (was_marked_incrementally_ && heap_->ShouldAbortIncrementalMarking()) {
@@ -831,9 +849,22 @@
     AbortWeakCells();
     AbortTransitionArrays();
     AbortCompaction();
+    if (heap_->UsingEmbedderHeapTracer()) {
+      heap_->mark_compact_collector()->embedder_heap_tracer()->AbortTracing();
+    }
     was_marked_incrementally_ = false;
   }
 
+  if (!was_marked_incrementally_) {
+    if (heap_->UsingEmbedderHeapTracer()) {
+      heap_->mark_compact_collector()->embedder_heap_tracer()->TracePrologue();
+    }
+  }
+
+  if (UsingEmbedderHeapTracer()) {
+    embedder_heap_tracer()->EnterFinalPause();
+  }
+
   // Don't start compaction if we are in the middle of incremental
   // marking cycle. We did not collect any slots.
   if (!FLAG_never_compact && !was_marked_incrementally_) {
@@ -845,6 +876,7 @@
        space = spaces.next()) {
     space->PrepareForMarkCompact();
   }
+  heap()->account_external_memory_concurrently_freed();
 
 #ifdef VERIFY_HEAP
   if (!was_marked_incrementally_ && FLAG_verify_heap) {
@@ -857,6 +889,12 @@
 void MarkCompactCollector::Finish() {
   TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_FINISH);
 
+  if (sweeper().contains_late_pages() && FLAG_concurrent_sweeping) {
+    // If we added some more pages during MC, we need to start at least one
+    // more task as all other tasks might already be finished.
+    sweeper().StartSweepingHelper(OLD_SPACE);
+  }
+
   // The hashing of weak_object_to_code_table is no longer valid.
   heap()->weak_object_to_code_table()->Rehash(
       heap()->isolate()->factory()->undefined_value());
@@ -1041,7 +1079,7 @@
 
 
 void CodeFlusher::EvictCandidate(JSFunction* function) {
-  DCHECK(!function->next_function_link()->IsUndefined());
+  DCHECK(!function->next_function_link()->IsUndefined(isolate_));
   Object* undefined = isolate_->heap()->undefined_value();
 
   // Make sure previous flushing decisions are revisited.
@@ -1266,7 +1304,7 @@
   table_.Register(kVisitJSRegExp, &VisitRegExpAndFlushCode);
 
   if (FLAG_track_gc_object_stats) {
-    ObjectStatsVisitor::Initialize(&table_);
+    MarkCompactObjectStatsVisitor::Initialize(&table_);
   }
 }
 
@@ -1373,8 +1411,10 @@
   void MarkObjectByPointer(Object** p) {
     if (!(*p)->IsHeapObject()) return;
 
-    // Replace flat cons strings in place.
     HeapObject* object = HeapObject::cast(*p);
+
+    if (collector_->heap()->PurgeLeftTrimmedObject(p)) return;
+
     MarkBit mark_bit = Marking::MarkBitFrom(object);
     if (Marking::IsBlackOrGrey(mark_bit)) return;
 
@@ -1502,6 +1542,9 @@
 
 class RecordMigratedSlotVisitor final : public ObjectVisitor {
  public:
+  explicit RecordMigratedSlotVisitor(MarkCompactCollector* collector)
+      : collector_(collector) {}
+
   inline void VisitPointer(Object** p) final {
     RecordMigratedSlot(*p, reinterpret_cast<Address>(p));
   }
@@ -1517,10 +1560,59 @@
     Address code_entry = Memory::Address_at(code_entry_slot);
     if (Page::FromAddress(code_entry)->IsEvacuationCandidate()) {
       RememberedSet<OLD_TO_OLD>::InsertTyped(Page::FromAddress(code_entry_slot),
-                                             CODE_ENTRY_SLOT, code_entry_slot);
+                                             nullptr, CODE_ENTRY_SLOT,
+                                             code_entry_slot);
     }
   }
 
+  inline void VisitCodeTarget(RelocInfo* rinfo) final {
+    DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
+    Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
+    Code* host = rinfo->host();
+    collector_->RecordRelocSlot(host, rinfo, target);
+  }
+
+  inline void VisitDebugTarget(RelocInfo* rinfo) final {
+    DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
+           rinfo->IsPatchedDebugBreakSlotSequence());
+    Code* target = Code::GetCodeFromTargetAddress(rinfo->debug_call_address());
+    Code* host = rinfo->host();
+    collector_->RecordRelocSlot(host, rinfo, target);
+  }
+
+  inline void VisitEmbeddedPointer(RelocInfo* rinfo) final {
+    DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
+    HeapObject* object = HeapObject::cast(rinfo->target_object());
+    Code* host = rinfo->host();
+    collector_->RecordRelocSlot(host, rinfo, object);
+  }
+
+  inline void VisitCell(RelocInfo* rinfo) final {
+    DCHECK(rinfo->rmode() == RelocInfo::CELL);
+    Cell* cell = rinfo->target_cell();
+    Code* host = rinfo->host();
+    collector_->RecordRelocSlot(host, rinfo, cell);
+  }
+
+  // Entries that will never move.
+  inline void VisitCodeAgeSequence(RelocInfo* rinfo) final {
+    DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
+    Code* stub = rinfo->code_age_stub();
+    USE(stub);
+    DCHECK(!Page::FromAddress(stub->address())->IsEvacuationCandidate());
+  }
+
+  // Entries that are skipped for recording.
+  inline void VisitExternalReference(RelocInfo* rinfo) final {}
+  inline void VisitExternalReference(Address* p) final {}
+  inline void VisitRuntimeEntry(RelocInfo* rinfo) final {}
+  inline void VisitExternalOneByteString(
+      v8::String::ExternalOneByteStringResource** resource) final {}
+  inline void VisitExternalTwoByteString(
+      v8::String::ExternalStringResource** resource) final {}
+  inline void VisitInternalReference(RelocInfo* rinfo) final {}
+  inline void VisitEmbedderReference(Object** p, uint16_t class_id) final {}
+
  private:
   inline void RecordMigratedSlot(Object* value, Address slot) {
     if (value->IsHeapObject()) {
@@ -1532,6 +1624,8 @@
       }
     }
   }
+
+  MarkCompactCollector* collector_;
 };
 
 class MarkCompactCollector::HeapObjectVisitor {
@@ -1549,12 +1643,15 @@
       : heap_(heap),
         compaction_spaces_(compaction_spaces),
         profiling_(
-            heap->isolate()->cpu_profiler()->is_profiling() ||
+            heap->isolate()->is_profiling() ||
             heap->isolate()->logger()->is_logging_code_events() ||
             heap->isolate()->heap_profiler()->is_tracking_object_moves()) {}
 
   inline bool TryEvacuateObject(PagedSpace* target_space, HeapObject* object,
                                 HeapObject** target_object) {
+#ifdef VERIFY_HEAP
+    if (AbortCompactionForTesting(object)) return false;
+#endif  // VERIFY_HEAP
     int size = object->Size();
     AllocationAlignment alignment = object->RequiredAlignment();
     AllocationResult allocation = target_space->AllocateRaw(size, alignment);
@@ -1589,7 +1686,7 @@
         PROFILE(heap_->isolate(),
                 CodeMoveEvent(AbstractCode::cast(src), dst_addr));
       }
-      RecordMigratedSlotVisitor visitor;
+      RecordMigratedSlotVisitor visitor(heap_->mark_compact_collector());
       dst->IterateBodyFast(dst->map()->instance_type(), size, &visitor);
     } else if (dest == CODE_SPACE) {
       DCHECK_CODEOBJECT_SIZE(size, heap_->code_space());
@@ -1598,9 +1695,9 @@
                 CodeMoveEvent(AbstractCode::cast(src), dst_addr));
       }
       heap_->CopyBlock(dst_addr, src_addr, size);
-      RememberedSet<OLD_TO_OLD>::InsertTyped(Page::FromAddress(dst_addr),
-                                             RELOCATED_CODE_OBJECT, dst_addr);
       Code::cast(dst)->Relocate(dst_addr - src_addr);
+      RecordMigratedSlotVisitor visitor(heap_->mark_compact_collector());
+      dst->IterateBodyFast(dst->map()->instance_type(), size, &visitor);
     } else {
       DCHECK_OBJECT_SIZE(size);
       DCHECK(dest == NEW_SPACE);
@@ -1612,6 +1709,26 @@
     Memory::Address_at(src_addr) = dst_addr;
   }
 
+#ifdef VERIFY_HEAP
+  bool AbortCompactionForTesting(HeapObject* object) {
+    if (FLAG_stress_compaction) {
+      const uintptr_t mask = static_cast<uintptr_t>(FLAG_random_seed) &
+                             Page::kPageAlignmentMask & ~kPointerAlignmentMask;
+      if ((reinterpret_cast<uintptr_t>(object->address()) &
+           Page::kPageAlignmentMask) == mask) {
+        Page* page = Page::FromAddress(object->address());
+        if (page->IsFlagSet(Page::COMPACTION_WAS_ABORTED_FOR_TESTING)) {
+          page->ClearFlag(Page::COMPACTION_WAS_ABORTED_FOR_TESTING);
+        } else {
+          page->SetFlag(Page::COMPACTION_WAS_ABORTED_FOR_TESTING);
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+#endif  // VERIFY_HEAP
+
   Heap* heap_;
   CompactionSpaceCollection* compaction_spaces_;
   bool profiling_;
@@ -1625,7 +1742,7 @@
 
   explicit EvacuateNewSpaceVisitor(Heap* heap,
                                    CompactionSpaceCollection* compaction_spaces,
-                                   HashMap* local_pretenuring_feedback)
+                                   base::HashMap* local_pretenuring_feedback)
       : EvacuateVisitorBase(heap, compaction_spaces),
         buffer_(LocalAllocationBuffer::InvalidBuffer()),
         space_to_allocate_(NEW_SPACE),
@@ -1633,28 +1750,20 @@
         semispace_copied_size_(0),
         local_pretenuring_feedback_(local_pretenuring_feedback) {}
 
-  bool Visit(HeapObject* object) override {
+  inline bool Visit(HeapObject* object) override {
     heap_->UpdateAllocationSite<Heap::kCached>(object,
                                                local_pretenuring_feedback_);
     int size = object->Size();
     HeapObject* target_object = nullptr;
-    if (heap_->ShouldBePromoted(object->address(), size) &&
+    if (heap_->ShouldBePromoted<DEFAULT_PROMOTION>(object->address(), size) &&
         TryEvacuateObject(compaction_spaces_->Get(OLD_SPACE), object,
                           &target_object)) {
-      // If we end up needing more special cases, we should factor this out.
-      if (V8_UNLIKELY(target_object->IsJSArrayBuffer())) {
-        heap_->array_buffer_tracker()->Promote(
-            JSArrayBuffer::cast(target_object));
-      }
       promoted_size_ += size;
       return true;
     }
     HeapObject* target = nullptr;
     AllocationSpace space = AllocateTargetObject(object, &target);
     MigrateObject(HeapObject::cast(target), object, size, space);
-    if (V8_UNLIKELY(target->IsJSArrayBuffer())) {
-      heap_->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(target));
-    }
     semispace_copied_size_ += size;
     return true;
   }
@@ -1673,6 +1782,7 @@
     const int size = old_object->Size();
     AllocationAlignment alignment = old_object->RequiredAlignment();
     AllocationResult allocation;
+    AllocationSpace space_allocated_in = space_to_allocate_;
     if (space_to_allocate_ == NEW_SPACE) {
       if (size > kMaxLabObjectSize) {
         allocation =
@@ -1683,11 +1793,12 @@
     }
     if (allocation.IsRetry() || (space_to_allocate_ == OLD_SPACE)) {
       allocation = AllocateInOldSpace(size, alignment);
+      space_allocated_in = OLD_SPACE;
     }
     bool ok = allocation.To(target_object);
     DCHECK(ok);
     USE(ok);
-    return space_to_allocate_;
+    return space_allocated_in;
   }
 
   inline bool NewLocalAllocationBuffer() {
@@ -1727,8 +1838,8 @@
         compaction_spaces_->Get(OLD_SPACE)->AllocateRaw(size_in_bytes,
                                                         alignment);
     if (allocation.IsRetry()) {
-      FatalProcessOutOfMemory(
-          "MarkCompactCollector: semi-space copy, fallback in old gen\n");
+      v8::internal::Heap::FatalProcessOutOfMemory(
+          "MarkCompactCollector: semi-space copy, fallback in old gen", true);
     }
     return allocation;
   }
@@ -1762,9 +1873,45 @@
   AllocationSpace space_to_allocate_;
   intptr_t promoted_size_;
   intptr_t semispace_copied_size_;
-  HashMap* local_pretenuring_feedback_;
+  base::HashMap* local_pretenuring_feedback_;
 };
 
+class MarkCompactCollector::EvacuateNewSpacePageVisitor final
+    : public MarkCompactCollector::HeapObjectVisitor {
+ public:
+  explicit EvacuateNewSpacePageVisitor(Heap* heap)
+      : heap_(heap), promoted_size_(0), semispace_copied_size_(0) {}
+
+  static void MoveToOldSpace(Page* page, PagedSpace* owner) {
+    page->Unlink();
+    Page* new_page = Page::ConvertNewToOld(page, owner);
+    new_page->SetFlag(Page::PAGE_NEW_OLD_PROMOTION);
+  }
+
+  static void MoveToToSpace(Page* page) {
+    page->heap()->new_space()->MovePageFromSpaceToSpace(page);
+    page->SetFlag(Page::PAGE_NEW_NEW_PROMOTION);
+  }
+
+  inline bool Visit(HeapObject* object) {
+    RecordMigratedSlotVisitor visitor(heap_->mark_compact_collector());
+    object->IterateBodyFast(&visitor);
+    promoted_size_ += object->Size();
+    return true;
+  }
+
+  intptr_t promoted_size() { return promoted_size_; }
+  intptr_t semispace_copied_size() { return semispace_copied_size_; }
+
+  void account_semispace_copied(intptr_t copied) {
+    semispace_copied_size_ += copied;
+  }
+
+ private:
+  Heap* heap_;
+  intptr_t promoted_size_;
+  intptr_t semispace_copied_size_;
+};
 
 class MarkCompactCollector::EvacuateOldSpaceVisitor final
     : public MarkCompactCollector::EvacuateVisitorBase {
@@ -1773,7 +1920,7 @@
                           CompactionSpaceCollection* compaction_spaces)
       : EvacuateVisitorBase(heap, compaction_spaces) {}
 
-  bool Visit(HeapObject* object) override {
+  inline bool Visit(HeapObject* object) override {
     CompactionSpace* target_space = compaction_spaces_->Get(
         Page::FromAddress(object->address())->owner()->identity());
     HeapObject* target_object = nullptr;
@@ -1785,11 +1932,23 @@
   }
 };
 
+class MarkCompactCollector::EvacuateRecordOnlyVisitor final
+    : public MarkCompactCollector::HeapObjectVisitor {
+ public:
+  explicit EvacuateRecordOnlyVisitor(Heap* heap) : heap_(heap) {}
+
+  inline bool Visit(HeapObject* object) {
+    RecordMigratedSlotVisitor visitor(heap_->mark_compact_collector());
+    object->IterateBody(&visitor);
+    return true;
+  }
+
+ private:
+  Heap* heap_;
+};
 
 void MarkCompactCollector::DiscoverGreyObjectsInSpace(PagedSpace* space) {
-  PageIterator it(space);
-  while (it.has_next()) {
-    Page* p = it.next();
+  for (Page* p : *space) {
     if (!p->IsFlagSet(Page::BLACK_PAGE)) {
       DiscoverGreyObjectsOnPage(p);
     }
@@ -1800,9 +1959,7 @@
 
 void MarkCompactCollector::DiscoverGreyObjectsInNewSpace() {
   NewSpace* space = heap()->new_space();
-  NewSpacePageIterator it(space->bottom(), space->top());
-  while (it.has_next()) {
-    NewSpacePage* page = it.next();
+  for (Page* page : NewSpacePageRange(space->bottom(), space->top())) {
     DiscoverGreyObjectsOnPage(page);
     if (marking_deque()->IsFull()) return;
   }
@@ -1961,14 +2118,19 @@
   }
 }
 
-
 // Mark all objects reachable (transitively) from objects on the marking
 // stack including references only considered in the atomic marking pause.
 void MarkCompactCollector::ProcessEphemeralMarking(
     ObjectVisitor* visitor, bool only_process_harmony_weak_collections) {
-  bool work_to_do = true;
   DCHECK(marking_deque_.IsEmpty() && !marking_deque_.overflowed());
+  bool work_to_do = true;
   while (work_to_do) {
+    if (UsingEmbedderHeapTracer()) {
+      RegisterWrappersWithEmbedderHeapTracer();
+      embedder_heap_tracer()->AdvanceTracing(
+          0, EmbedderHeapTracer::AdvanceTracingActions(
+                 EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION));
+    }
     if (!only_process_harmony_weak_collections) {
       isolate()->global_handles()->IterateObjectGroups(
           visitor, &IsUnmarkedHeapObjectWithHeap);
@@ -1980,7 +2142,6 @@
   }
 }
 
-
 void MarkCompactCollector::ProcessTopOptimizedFrame(ObjectVisitor* visitor) {
   for (StackFrameIterator it(isolate(), isolate()->thread_local_top());
        !it.done(); it.Advance()) {
@@ -2079,6 +2240,41 @@
   in_use_ = false;
 }
 
+void MarkCompactCollector::SetEmbedderHeapTracer(EmbedderHeapTracer* tracer) {
+  DCHECK_NOT_NULL(tracer);
+  CHECK_NULL(embedder_heap_tracer_);
+  embedder_heap_tracer_ = tracer;
+}
+
+void MarkCompactCollector::RegisterWrappersWithEmbedderHeapTracer() {
+  DCHECK(UsingEmbedderHeapTracer());
+  if (wrappers_to_trace_.empty()) {
+    return;
+  }
+  embedder_heap_tracer()->RegisterV8References(wrappers_to_trace_);
+  wrappers_to_trace_.clear();
+}
+
+void MarkCompactCollector::TracePossibleWrapper(JSObject* js_object) {
+  DCHECK(js_object->WasConstructedFromApiFunction());
+  if (js_object->GetInternalFieldCount() >= 2 &&
+      js_object->GetInternalField(0) &&
+      js_object->GetInternalField(0) != heap_->undefined_value() &&
+      js_object->GetInternalField(1) != heap_->undefined_value()) {
+    DCHECK(reinterpret_cast<intptr_t>(js_object->GetInternalField(0)) % 2 == 0);
+    wrappers_to_trace_.push_back(std::pair<void*, void*>(
+        reinterpret_cast<void*>(js_object->GetInternalField(0)),
+        reinterpret_cast<void*>(js_object->GetInternalField(1))));
+  }
+}
+
+void MarkCompactCollector::RegisterExternallyReferencedObject(Object** object) {
+  DCHECK(in_use());
+  HeapObject* heap_object = HeapObject::cast(*object);
+  DCHECK(heap_->Contains(heap_object));
+  MarkBit mark_bit = Marking::MarkBitFrom(heap_object);
+  MarkObject(heap_object, mark_bit);
+}
 
 void MarkCompactCollector::MarkLiveObjects() {
   TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK);
@@ -2099,6 +2295,10 @@
     } else {
       // Abort any pending incremental activities e.g. incremental sweeping.
       incremental_marking->Stop();
+      if (FLAG_track_gc_object_stats) {
+        // Clear object stats collected during incremental marking.
+        heap()->object_stats_->ClearObjectStats();
+      }
       if (marking_deque_.in_use()) {
         marking_deque_.Uninitialize(true);
       }
@@ -2136,7 +2336,6 @@
       TRACE_GC(heap()->tracer(),
                GCTracer::Scope::MC_MARK_WEAK_CLOSURE_EPHEMERAL);
       ProcessEphemeralMarking(&root_visitor, false);
-      ProcessMarkingDeque();
     }
 
     // The objects reachable from the roots, weak maps or object groups
@@ -2170,7 +2369,9 @@
     {
       TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WEAK_CLOSURE_HARMONY);
       ProcessEphemeralMarking(&root_visitor, true);
-      ProcessMarkingDeque();
+      if (UsingEmbedderHeapTracer()) {
+        embedder_heap_tracer()->TraceEpilogue();
+      }
     }
   }
 
@@ -2262,7 +2463,7 @@
   for (uint32_t i = 0; i < capacity; i++) {
     uint32_t key_index = table->EntryToIndex(i);
     Object* key = table->get(key_index);
-    if (!table->IsKey(key)) continue;
+    if (!table->IsKey(isolate, key)) continue;
     uint32_t value_index = table->EntryToValueIndex(i);
     Object* value = table->get(value_index);
     DCHECK(key->IsWeakCell());
@@ -2634,128 +2835,20 @@
         slot_type = OBJECT_SLOT;
       }
     }
-    RememberedSet<OLD_TO_OLD>::InsertTyped(source_page, slot_type, addr);
+    RememberedSet<OLD_TO_OLD>::InsertTyped(
+        source_page, reinterpret_cast<Address>(host), slot_type, addr);
   }
 }
 
-static inline void UpdateTypedSlot(Isolate* isolate, ObjectVisitor* v,
-                                   SlotType slot_type, Address addr) {
-  switch (slot_type) {
-    case CODE_TARGET_SLOT: {
-      RelocInfo rinfo(isolate, addr, RelocInfo::CODE_TARGET, 0, NULL);
-      rinfo.Visit(isolate, v);
-      break;
-    }
-    case CELL_TARGET_SLOT: {
-      RelocInfo rinfo(isolate, addr, RelocInfo::CELL, 0, NULL);
-      rinfo.Visit(isolate, v);
-      break;
-    }
-    case CODE_ENTRY_SLOT: {
-      v->VisitCodeEntry(addr);
-      break;
-    }
-    case RELOCATED_CODE_OBJECT: {
-      HeapObject* obj = HeapObject::FromAddress(addr);
-      Code::BodyDescriptor::IterateBody(obj, v);
-      break;
-    }
-    case DEBUG_TARGET_SLOT: {
-      RelocInfo rinfo(isolate, addr, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION, 0,
-                      NULL);
-      if (rinfo.IsPatchedDebugBreakSlotSequence()) rinfo.Visit(isolate, v);
-      break;
-    }
-    case EMBEDDED_OBJECT_SLOT: {
-      RelocInfo rinfo(isolate, addr, RelocInfo::EMBEDDED_OBJECT, 0, NULL);
-      rinfo.Visit(isolate, v);
-      break;
-    }
-    case OBJECT_SLOT: {
-      v->VisitPointer(reinterpret_cast<Object**>(addr));
-      break;
-    }
-    default:
-      UNREACHABLE();
-      break;
-  }
-}
+static inline SlotCallbackResult UpdateSlot(Object** slot) {
+  Object* obj = reinterpret_cast<Object*>(
+      base::NoBarrier_Load(reinterpret_cast<base::AtomicWord*>(slot)));
 
-
-// Visitor for updating pointers from live objects in old spaces to new space.
-// It does not expect to encounter pointers to dead objects.
-class PointersUpdatingVisitor : public ObjectVisitor {
- public:
-  explicit PointersUpdatingVisitor(Heap* heap) : heap_(heap) {}
-
-  void VisitPointer(Object** p) override { UpdatePointer(p); }
-
-  void VisitPointers(Object** start, Object** end) override {
-    for (Object** p = start; p < end; p++) UpdatePointer(p);
-  }
-
-  void VisitCell(RelocInfo* rinfo) override {
-    DCHECK(rinfo->rmode() == RelocInfo::CELL);
-    Object* cell = rinfo->target_cell();
-    Object* old_cell = cell;
-    VisitPointer(&cell);
-    if (cell != old_cell) {
-      rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
-    }
-  }
-
-  void VisitEmbeddedPointer(RelocInfo* rinfo) override {
-    DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
-    Object* target = rinfo->target_object();
-    Object* old_target = target;
-    VisitPointer(&target);
-    // Avoid unnecessary changes that might unnecessary flush the instruction
-    // cache.
-    if (target != old_target) {
-      rinfo->set_target_object(target);
-    }
-  }
-
-  void VisitCodeTarget(RelocInfo* rinfo) override {
-    DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
-    Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
-    Object* old_target = target;
-    VisitPointer(&target);
-    if (target != old_target) {
-      rinfo->set_target_address(Code::cast(target)->instruction_start());
-    }
-  }
-
-  void VisitCodeAgeSequence(RelocInfo* rinfo) override {
-    DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
-    Object* stub = rinfo->code_age_stub();
-    DCHECK(stub != NULL);
-    VisitPointer(&stub);
-    if (stub != rinfo->code_age_stub()) {
-      rinfo->set_code_age_stub(Code::cast(stub));
-    }
-  }
-
-  void VisitDebugTarget(RelocInfo* rinfo) override {
-    DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
-           rinfo->IsPatchedDebugBreakSlotSequence());
-    Object* target =
-        Code::GetCodeFromTargetAddress(rinfo->debug_call_address());
-    VisitPointer(&target);
-    rinfo->set_debug_call_address(Code::cast(target)->instruction_start());
-  }
-
-  static inline void UpdateSlot(Heap* heap, Object** slot) {
-    Object* obj = reinterpret_cast<Object*>(
-        base::NoBarrier_Load(reinterpret_cast<base::AtomicWord*>(slot)));
-
-    if (!obj->IsHeapObject()) return;
-
+  if (obj->IsHeapObject()) {
     HeapObject* heap_obj = HeapObject::cast(obj);
-
     MapWord map_word = heap_obj->map_word();
     if (map_word.IsForwardingAddress()) {
-      DCHECK(heap->InFromSpace(heap_obj) ||
+      DCHECK(heap_obj->GetHeap()->InFromSpace(heap_obj) ||
              MarkCompactCollector::IsOnEvacuationCandidate(heap_obj) ||
              Page::FromAddress(heap_obj->address())
                  ->IsFlagSet(Page::COMPACTION_WAS_ABORTED));
@@ -2764,15 +2857,42 @@
           reinterpret_cast<base::AtomicWord*>(slot),
           reinterpret_cast<base::AtomicWord>(obj),
           reinterpret_cast<base::AtomicWord>(target));
-      DCHECK(!heap->InFromSpace(target) &&
+      DCHECK(!heap_obj->GetHeap()->InFromSpace(target) &&
              !MarkCompactCollector::IsOnEvacuationCandidate(target));
     }
   }
+  return REMOVE_SLOT;
+}
 
- private:
-  inline void UpdatePointer(Object** p) { UpdateSlot(heap_, p); }
+// Visitor for updating pointers from live objects in old spaces to new space.
+// It does not expect to encounter pointers to dead objects.
+class PointersUpdatingVisitor : public ObjectVisitor {
+ public:
+  void VisitPointer(Object** p) override { UpdateSlot(p); }
 
-  Heap* heap_;
+  void VisitPointers(Object** start, Object** end) override {
+    for (Object** p = start; p < end; p++) UpdateSlot(p);
+  }
+
+  void VisitCell(RelocInfo* rinfo) override {
+    UpdateTypedSlotHelper::UpdateCell(rinfo, UpdateSlot);
+  }
+
+  void VisitEmbeddedPointer(RelocInfo* rinfo) override {
+    UpdateTypedSlotHelper::UpdateEmbeddedPointer(rinfo, UpdateSlot);
+  }
+
+  void VisitCodeTarget(RelocInfo* rinfo) override {
+    UpdateTypedSlotHelper::UpdateCodeTarget(rinfo, UpdateSlot);
+  }
+
+  void VisitCodeEntry(Address entry_address) override {
+    UpdateTypedSlotHelper::UpdateCodeEntry(entry_address, UpdateSlot);
+  }
+
+  void VisitDebugTarget(RelocInfo* rinfo) override {
+    UpdateTypedSlotHelper::UpdateDebugTarget(rinfo, UpdateSlot);
+  }
 };
 
 static String* UpdateReferenceInExternalStringTableEntry(Heap* heap,
@@ -2917,34 +3037,55 @@
 
 void MarkCompactCollector::EvacuateNewSpacePrologue() {
   NewSpace* new_space = heap()->new_space();
-  NewSpacePageIterator it(new_space->bottom(), new_space->top());
   // Append the list of new space pages to be processed.
-  while (it.has_next()) {
-    newspace_evacuation_candidates_.Add(it.next());
+  for (Page* p : NewSpacePageRange(new_space->bottom(), new_space->top())) {
+    newspace_evacuation_candidates_.Add(p);
   }
   new_space->Flip();
   new_space->ResetAllocationInfo();
 }
 
-void MarkCompactCollector::EvacuateNewSpaceEpilogue() {
-  newspace_evacuation_candidates_.Rewind(0);
-}
-
-
 class MarkCompactCollector::Evacuator : public Malloced {
  public:
+  enum EvacuationMode {
+    kObjectsNewToOld,
+    kPageNewToOld,
+    kObjectsOldToOld,
+    kPageNewToNew,
+  };
+
+  static inline EvacuationMode ComputeEvacuationMode(MemoryChunk* chunk) {
+    // Note: The order of checks is important in this function.
+    if (chunk->IsFlagSet(MemoryChunk::PAGE_NEW_OLD_PROMOTION))
+      return kPageNewToOld;
+    if (chunk->IsFlagSet(MemoryChunk::PAGE_NEW_NEW_PROMOTION))
+      return kPageNewToNew;
+    if (chunk->InNewSpace()) return kObjectsNewToOld;
+    DCHECK(chunk->IsEvacuationCandidate());
+    return kObjectsOldToOld;
+  }
+
+  // NewSpacePages with more live bytes than this threshold qualify for fast
+  // evacuation.
+  static int PageEvacuationThreshold() {
+    if (FLAG_page_promotion)
+      return FLAG_page_promotion_threshold * Page::kAllocatableMemory / 100;
+    return Page::kAllocatableMemory + kPointerSize;
+  }
+
   explicit Evacuator(MarkCompactCollector* collector)
       : collector_(collector),
         compaction_spaces_(collector->heap()),
-        local_pretenuring_feedback_(HashMap::PointersMatch,
+        local_pretenuring_feedback_(base::HashMap::PointersMatch,
                                     kInitialLocalPretenuringFeedbackCapacity),
         new_space_visitor_(collector->heap(), &compaction_spaces_,
                            &local_pretenuring_feedback_),
+        new_space_page_visitor(collector->heap()),
         old_space_visitor_(collector->heap(), &compaction_spaces_),
         duration_(0.0),
         bytes_compacted_(0) {}
 
-  inline bool EvacuatePage(MemoryChunk* chunk);
+  inline bool EvacuatePage(Page* chunk);
 
   // Merge back locally cached info sequentially. Note that this method needs
   // to be called from the main thread.
@@ -2955,23 +3096,22 @@
  private:
   static const int kInitialLocalPretenuringFeedbackCapacity = 256;
 
-  Heap* heap() { return collector_->heap(); }
+  inline Heap* heap() { return collector_->heap(); }
 
   void ReportCompactionProgress(double duration, intptr_t bytes_compacted) {
     duration_ += duration;
     bytes_compacted_ += bytes_compacted;
   }
 
-  inline bool EvacuateSinglePage(MemoryChunk* p, HeapObjectVisitor* visitor);
-
   MarkCompactCollector* collector_;
 
   // Locally cached collector data.
   CompactionSpaceCollection compaction_spaces_;
-  HashMap local_pretenuring_feedback_;
+  base::HashMap local_pretenuring_feedback_;
 
   // Visitors for the corresponding spaces.
   EvacuateNewSpaceVisitor new_space_visitor_;
+  EvacuateNewSpacePageVisitor new_space_page_visitor;
   EvacuateOldSpaceVisitor old_space_visitor_;
 
   // Book keeping info.
@@ -2979,43 +3119,74 @@
   intptr_t bytes_compacted_;
 };
 
-bool MarkCompactCollector::Evacuator::EvacuateSinglePage(
-    MemoryChunk* p, HeapObjectVisitor* visitor) {
+bool MarkCompactCollector::Evacuator::EvacuatePage(Page* page) {
   bool success = false;
-  DCHECK(p->IsEvacuationCandidate() || p->InNewSpace());
-  int saved_live_bytes = p->LiveBytes();
-  double evacuation_time;
+  DCHECK(page->SweepingDone());
+  int saved_live_bytes = page->LiveBytes();
+  double evacuation_time = 0.0;
+  Heap* heap = page->heap();
   {
-    AlwaysAllocateScope always_allocate(heap()->isolate());
+    AlwaysAllocateScope always_allocate(heap->isolate());
     TimedScope timed_scope(&evacuation_time);
-    success = collector_->VisitLiveObjects(p, visitor, kClearMarkbits);
+    switch (ComputeEvacuationMode(page)) {
+      case kObjectsNewToOld:
+        success = collector_->VisitLiveObjects(page, &new_space_visitor_,
+                                               kClearMarkbits);
+        ArrayBufferTracker::ProcessBuffers(
+            page, ArrayBufferTracker::kUpdateForwardedRemoveOthers);
+        DCHECK(success);
+        break;
+      case kPageNewToOld:
+        success = collector_->VisitLiveObjects(page, &new_space_page_visitor,
+                                               kKeepMarking);
+        // ArrayBufferTracker will be updated during sweeping.
+        DCHECK(success);
+        break;
+      case kPageNewToNew:
+        new_space_page_visitor.account_semispace_copied(page->LiveBytes());
+        // ArrayBufferTracker will be updated during sweeping.
+        success = true;
+        break;
+      case kObjectsOldToOld:
+        success = collector_->VisitLiveObjects(page, &old_space_visitor_,
+                                               kClearMarkbits);
+        if (!success) {
+          // Aborted compaction page. We have to record slots here, since we
+          // might not have recorded them in first place.
+          // Note: We mark the page as aborted here to be able to record slots
+          // for code objects in |RecordMigratedSlotVisitor|.
+          page->SetFlag(Page::COMPACTION_WAS_ABORTED);
+          EvacuateRecordOnlyVisitor record_visitor(collector_->heap());
+          success =
+              collector_->VisitLiveObjects(page, &record_visitor, kKeepMarking);
+          ArrayBufferTracker::ProcessBuffers(
+              page, ArrayBufferTracker::kUpdateForwardedKeepOthers);
+          DCHECK(success);
+          // We need to return failure here to indicate that we want this page
+          // added to the sweeper.
+          success = false;
+        } else {
+          ArrayBufferTracker::ProcessBuffers(
+              page, ArrayBufferTracker::kUpdateForwardedRemoveOthers);
+        }
+        break;
+      default:
+        UNREACHABLE();
+    }
   }
+  ReportCompactionProgress(evacuation_time, saved_live_bytes);
   if (FLAG_trace_evacuation) {
-    PrintIsolate(heap()->isolate(),
-                 "evacuation[%p]: page=%p new_space=%d executable=%d "
+    PrintIsolate(heap->isolate(),
+                 "evacuation[%p]: page=%p new_space=%d "
+                 "page_evacuation=%d executable=%d contains_age_mark=%d "
                  "live_bytes=%d time=%f\n",
-                 this, p, p->InNewSpace(),
-                 p->IsFlagSet(MemoryChunk::IS_EXECUTABLE), saved_live_bytes,
-                 evacuation_time);
-  }
-  if (success) {
-    ReportCompactionProgress(evacuation_time, saved_live_bytes);
-  }
-  return success;
-}
-
-bool MarkCompactCollector::Evacuator::EvacuatePage(MemoryChunk* chunk) {
-  bool success = false;
-  if (chunk->InNewSpace()) {
-    DCHECK_EQ(chunk->concurrent_sweeping_state().Value(),
-              NewSpacePage::kSweepingDone);
-    success = EvacuateSinglePage(chunk, &new_space_visitor_);
-    DCHECK(success);
-    USE(success);
-  } else {
-    DCHECK(chunk->IsEvacuationCandidate());
-    DCHECK_EQ(chunk->concurrent_sweeping_state().Value(), Page::kSweepingDone);
-    success = EvacuateSinglePage(chunk, &old_space_visitor_);
+                 static_cast<void*>(this), static_cast<void*>(page),
+                 page->InNewSpace(),
+                 page->IsFlagSet(Page::PAGE_NEW_OLD_PROMOTION) ||
+                     page->IsFlagSet(Page::PAGE_NEW_NEW_PROMOTION),
+                 page->IsFlagSet(MemoryChunk::IS_EXECUTABLE),
+                 page->Contains(heap->new_space()->age_mark()),
+                 saved_live_bytes, evacuation_time);
   }
   return success;
 }
@@ -3025,12 +3196,16 @@
   heap()->code_space()->MergeCompactionSpace(
       compaction_spaces_.Get(CODE_SPACE));
   heap()->tracer()->AddCompactionEvent(duration_, bytes_compacted_);
-  heap()->IncrementPromotedObjectsSize(new_space_visitor_.promoted_size());
+  heap()->IncrementPromotedObjectsSize(new_space_visitor_.promoted_size() +
+                                       new_space_page_visitor.promoted_size());
   heap()->IncrementSemiSpaceCopiedObjectSize(
-      new_space_visitor_.semispace_copied_size());
+      new_space_visitor_.semispace_copied_size() +
+      new_space_page_visitor.semispace_copied_size());
   heap()->IncrementYoungSurvivorsCounter(
       new_space_visitor_.promoted_size() +
-      new_space_visitor_.semispace_copied_size());
+      new_space_visitor_.semispace_copied_size() +
+      new_space_page_visitor.promoted_size() +
+      new_space_page_visitor.semispace_copied_size());
   heap()->MergeAllocationSitePretenuringFeedback(local_pretenuring_feedback_);
 }
 
@@ -3073,42 +3248,46 @@
 
   static bool ProcessPageInParallel(Heap* heap, PerTaskData evacuator,
                                     MemoryChunk* chunk, PerPageData) {
-    return evacuator->EvacuatePage(chunk);
+    return evacuator->EvacuatePage(reinterpret_cast<Page*>(chunk));
   }
 
-  static void FinalizePageSequentially(Heap*, MemoryChunk* chunk, bool success,
-                                       PerPageData data) {
-    if (chunk->InNewSpace()) {
-      DCHECK(success);
-    } else {
-      Page* p = static_cast<Page*>(chunk);
-      if (success) {
-        DCHECK(p->IsEvacuationCandidate());
-        DCHECK(p->SweepingDone());
-        p->Unlink();
-      } else {
-        // We have partially compacted the page, i.e., some objects may have
-        // moved, others are still in place.
-        // We need to:
-        // - Leave the evacuation candidate flag for later processing of slots
-        //   buffer entries.
-        // - Leave the slots buffer there for processing of entries added by
-        //   the write barrier.
-        // - Rescan the page as slot recording in the migration buffer only
-        //   happens upon moving (which we potentially didn't do).
-        // - Leave the page in the list of pages of a space since we could not
-        //   fully evacuate it.
-        DCHECK(p->IsEvacuationCandidate());
-        p->SetFlag(Page::COMPACTION_WAS_ABORTED);
-        *data += 1;
-      }
+  static void FinalizePageSequentially(Heap* heap, MemoryChunk* chunk,
+                                       bool success, PerPageData data) {
+    using Evacuator = MarkCompactCollector::Evacuator;
+    Page* p = static_cast<Page*>(chunk);
+    switch (Evacuator::ComputeEvacuationMode(p)) {
+      case Evacuator::kPageNewToOld:
+        break;
+      case Evacuator::kPageNewToNew:
+        DCHECK(success);
+        break;
+      case Evacuator::kObjectsNewToOld:
+        DCHECK(success);
+        break;
+      case Evacuator::kObjectsOldToOld:
+        if (success) {
+          DCHECK(p->IsEvacuationCandidate());
+          DCHECK(p->SweepingDone());
+          p->Unlink();
+        } else {
+          // We have partially compacted the page, i.e., some objects may have
+          // moved, others are still in place.
+          p->ClearEvacuationCandidate();
+          // Slots have already been recorded so we just need to add it to the
+          // sweeper, which will happen after updating pointers.
+          *data += 1;
+        }
+        break;
+      default:
+        UNREACHABLE();
     }
   }
 };
 
 void MarkCompactCollector::EvacuatePagesInParallel() {
   PageParallelJob<EvacuationJobTraits> job(
-      heap_, heap_->isolate()->cancelable_task_manager());
+      heap_, heap_->isolate()->cancelable_task_manager(),
+      &page_parallel_job_semaphore_);
 
   int abandoned_pages = 0;
   intptr_t live_bytes = 0;
@@ -3116,8 +3295,20 @@
     live_bytes += page->LiveBytes();
     job.AddPage(page, &abandoned_pages);
   }
-  for (NewSpacePage* page : newspace_evacuation_candidates_) {
+
+  const Address age_mark = heap()->new_space()->age_mark();
+  for (Page* page : newspace_evacuation_candidates_) {
     live_bytes += page->LiveBytes();
+    if (!page->NeverEvacuate() &&
+        (page->LiveBytes() > Evacuator::PageEvacuationThreshold()) &&
+        !page->Contains(age_mark)) {
+      if (page->IsFlagSet(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK)) {
+        EvacuateNewSpacePageVisitor::MoveToOldSpace(page, heap()->old_space());
+      } else {
+        EvacuateNewSpacePageVisitor::MoveToToSpace(page);
+      }
+    }
+
     job.AddPage(page, &abandoned_pages);
   }
   DCHECK_GE(job.NumberOfPages(), 1);
@@ -3142,16 +3333,15 @@
   delete[] evacuators;
 
   if (FLAG_trace_evacuation) {
-    PrintIsolate(
-        isolate(),
-        "%8.0f ms: evacuation-summary: parallel=%s pages=%d aborted=%d "
-        "wanted_tasks=%d tasks=%d cores=%d live_bytes=%" V8_PTR_PREFIX
-        "d compaction_speed=%.f\n",
-        isolate()->time_millis_since_init(),
-        FLAG_parallel_compaction ? "yes" : "no", job.NumberOfPages(),
-        abandoned_pages, wanted_num_tasks, job.NumberOfTasks(),
-        V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads(),
-        live_bytes, compaction_speed);
+    PrintIsolate(isolate(),
+                 "%8.0f ms: evacuation-summary: parallel=%s pages=%d "
+                 "aborted=%d wanted_tasks=%d tasks=%d cores=%" PRIuS
+                 " live_bytes=%" V8PRIdPTR " compaction_speed=%.f\n",
+                 isolate()->time_millis_since_init(),
+                 FLAG_parallel_compaction ? "yes" : "no", job.NumberOfPages(),
+                 abandoned_pages, wanted_num_tasks, job.NumberOfTasks(),
+                 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads(),
+                 live_bytes, compaction_speed);
   }
 }
 
@@ -3169,28 +3359,23 @@
   }
 };
 
-enum SweepingMode { SWEEP_ONLY, SWEEP_AND_VISIT_LIVE_OBJECTS };
-
-enum SkipListRebuildingMode { REBUILD_SKIP_LIST, IGNORE_SKIP_LIST };
-
-enum FreeSpaceTreatmentMode { IGNORE_FREE_SPACE, ZAP_FREE_SPACE };
-
-// Sweeps a page. After sweeping the page can be iterated.
-// Slots in live objects pointing into evacuation candidates are updated
-// if requested.
-// Returns the size of the biggest continuous freed memory chunk in bytes.
-template <SweepingMode sweeping_mode,
-          MarkCompactCollector::SweepingParallelism parallelism,
-          SkipListRebuildingMode skip_list_mode,
-          FreeSpaceTreatmentMode free_space_mode>
-static int Sweep(PagedSpace* space, Page* p, ObjectVisitor* v) {
+template <MarkCompactCollector::Sweeper::SweepingMode sweeping_mode,
+          MarkCompactCollector::Sweeper::SweepingParallelism parallelism,
+          MarkCompactCollector::Sweeper::SkipListRebuildingMode skip_list_mode,
+          MarkCompactCollector::Sweeper::FreeListRebuildingMode free_list_mode,
+          MarkCompactCollector::Sweeper::FreeSpaceTreatmentMode free_space_mode>
+int MarkCompactCollector::Sweeper::RawSweep(PagedSpace* space, Page* p,
+                                            ObjectVisitor* v) {
   DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone());
   DCHECK(!p->IsFlagSet(Page::BLACK_PAGE));
-  DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST,
-            space->identity() == CODE_SPACE);
+  DCHECK((space == nullptr) || (space->identity() != CODE_SPACE) ||
+         (skip_list_mode == REBUILD_SKIP_LIST));
   DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST));
-  DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD ||
-         sweeping_mode == SWEEP_ONLY);
+  DCHECK(parallelism == SWEEP_ON_MAIN_THREAD || sweeping_mode == SWEEP_ONLY);
+
+  // Before we sweep objects on the page, we free dead array buffers which
+  // requires valid mark bits.
+  ArrayBufferTracker::FreeDead(p);
 
   Address free_start = p->area_start();
   DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0);
@@ -3217,8 +3402,13 @@
       if (free_space_mode == ZAP_FREE_SPACE) {
         memset(free_start, 0xcc, size);
       }
-      freed_bytes = space->UnaccountedFree(free_start, size);
-      max_freed_bytes = Max(freed_bytes, max_freed_bytes);
+      if (free_list_mode == REBUILD_FREE_LIST) {
+        freed_bytes = space->UnaccountedFree(free_start, size);
+        max_freed_bytes = Max(freed_bytes, max_freed_bytes);
+      } else {
+        p->heap()->CreateFillerObjectAt(free_start, size,
+                                        ClearRecordedSlots::kNo);
+      }
     }
     Map* map = object->synchronized_map();
     int size = object->SizeFromMap(map);
@@ -3245,14 +3435,19 @@
     if (free_space_mode == ZAP_FREE_SPACE) {
       memset(free_start, 0xcc, size);
     }
-    freed_bytes = space->UnaccountedFree(free_start, size);
-    max_freed_bytes = Max(freed_bytes, max_freed_bytes);
+    if (free_list_mode == REBUILD_FREE_LIST) {
+      freed_bytes = space->UnaccountedFree(free_start, size);
+      max_freed_bytes = Max(freed_bytes, max_freed_bytes);
+    } else {
+      p->heap()->CreateFillerObjectAt(free_start, size,
+                                      ClearRecordedSlots::kNo);
+    }
   }
   p->concurrent_sweeping_state().SetValue(Page::kSweepingDone);
+  if (free_list_mode == IGNORE_FREE_LIST) return 0;
   return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes));
 }
 
-
 void MarkCompactCollector::InvalidateCode(Code* code) {
   if (heap_->incremental_marking()->IsCompacting() &&
       !ShouldSkipEvacuationSlotRecording(code)) {
@@ -3269,6 +3464,7 @@
     Address start = code->instruction_start();
     Address end = code->address() + code->Size();
     RememberedSet<OLD_TO_OLD>::RemoveRangeTyped(page, start, end);
+    RememberedSet<OLD_TO_NEW>::RemoveRangeTyped(page, start, end);
   }
 }
 
@@ -3289,9 +3485,8 @@
 }
 #endif  // VERIFY_HEAP
 
-
-bool MarkCompactCollector::VisitLiveObjects(MemoryChunk* page,
-                                            HeapObjectVisitor* visitor,
+template <class Visitor>
+bool MarkCompactCollector::VisitLiveObjects(MemoryChunk* page, Visitor* visitor,
                                             IterationMode mode) {
 #ifdef VERIFY_HEAP
   VerifyAllBlackObjects(page);
@@ -3349,41 +3544,12 @@
   }
 }
 
-
-void MarkCompactCollector::SweepAbortedPages() {
-  // Second pass on aborted pages.
-  for (Page* p : evacuation_candidates_) {
-    if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) {
-      p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED);
-      p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress);
-      PagedSpace* space = static_cast<PagedSpace*>(p->owner());
-      switch (space->identity()) {
-        case OLD_SPACE:
-          Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST,
-                IGNORE_FREE_SPACE>(space, p, nullptr);
-          break;
-        case CODE_SPACE:
-          if (FLAG_zap_code_space) {
-            Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST,
-                  ZAP_FREE_SPACE>(space, p, nullptr);
-          } else {
-            Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST,
-                  IGNORE_FREE_SPACE>(space, p, nullptr);
-          }
-          break;
-        default:
-          UNREACHABLE();
-          break;
-      }
-      {
-        base::LockGuard<base::Mutex> guard(&swept_pages_mutex_);
-        swept_pages(space->identity())->Add(p);
-      }
-    }
-  }
+void MarkCompactCollector::Sweeper::AddSweptPageSafe(PagedSpace* space,
+                                                     Page* page) {
+  base::LockGuard<base::Mutex> guard(&mutex_);
+  swept_list_[space->identity()].Add(page);
 }
 
-
 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
   TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE);
   Heap::RelocationLock relocation_lock(heap());
@@ -3394,35 +3560,55 @@
 
     EvacuateNewSpacePrologue();
     EvacuatePagesInParallel();
-    EvacuateNewSpaceEpilogue();
     heap()->new_space()->set_age_mark(heap()->new_space()->top());
   }
 
   UpdatePointersAfterEvacuation();
 
+  if (!heap()->new_space()->Rebalance()) {
+    FatalProcessOutOfMemory("NewSpace::Rebalance");
+  }
+
   // Give pages that are queued to be freed back to the OS. Note that filtering
   // slots only handles old space (for unboxed doubles), and thus map space can
   // still contain stale pointers. We only free the chunks after pointer updates
   // to still have access to page headers.
-  heap()->FreeQueuedChunks();
+  heap()->memory_allocator()->unmapper()->FreeQueuedChunks();
 
   {
     TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_CLEAN_UP);
-    // After updating all pointers, we can finally sweep the aborted pages,
-    // effectively overriding any forward pointers.
-    SweepAbortedPages();
 
-    // EvacuateNewSpaceAndCandidates iterates over new space objects and for
-    // ArrayBuffers either re-registers them as live or promotes them. This is
-    // needed to properly free them.
-    heap()->array_buffer_tracker()->FreeDead(false);
+    for (Page* p : newspace_evacuation_candidates_) {
+      if (p->IsFlagSet(Page::PAGE_NEW_NEW_PROMOTION)) {
+        p->ClearFlag(Page::PAGE_NEW_NEW_PROMOTION);
+        sweeper().AddLatePage(p->owner()->identity(), p);
+      } else if (p->IsFlagSet(Page::PAGE_NEW_OLD_PROMOTION)) {
+        p->ClearFlag(Page::PAGE_NEW_OLD_PROMOTION);
+        p->ForAllFreeListCategories(
+            [](FreeListCategory* category) { DCHECK(!category->is_linked()); });
+        sweeper().AddLatePage(p->owner()->identity(), p);
+      }
+    }
+    newspace_evacuation_candidates_.Rewind(0);
+
+    for (Page* p : evacuation_candidates_) {
+      // Important: skip list should be cleared only after roots were updated
+      // because root iteration traverses the stack and might have to find
+      // code objects from non-updated pc pointing into evacuation candidate.
+      SkipList* list = p->skip_list();
+      if (list != NULL) list->Clear();
+      if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) {
+        sweeper().AddLatePage(p->owner()->identity(), p);
+        p->ClearFlag(Page::COMPACTION_WAS_ABORTED);
+      }
+    }
 
     // Deallocate evacuated candidate pages.
     ReleaseEvacuationCandidates();
   }
 
 #ifdef VERIFY_HEAP
-  if (FLAG_verify_heap && !sweeping_in_progress_) {
+  if (FLAG_verify_heap && !sweeper().sweeping_in_progress()) {
     VerifyEvacuation(heap());
   }
 #endif
@@ -3432,12 +3618,12 @@
 class PointerUpdateJobTraits {
  public:
   typedef int PerPageData;  // Per page data is not used in this job.
-  typedef PointersUpdatingVisitor* PerTaskData;
+  typedef int PerTaskData;  // Per task data is not used in this job.
 
-  static bool ProcessPageInParallel(Heap* heap, PerTaskData visitor,
-                                    MemoryChunk* chunk, PerPageData) {
+  static bool ProcessPageInParallel(Heap* heap, PerTaskData, MemoryChunk* chunk,
+                                    PerPageData) {
     UpdateUntypedPointers(heap, chunk);
-    UpdateTypedPointers(heap, chunk, visitor);
+    UpdateTypedPointers(heap, chunk);
     return true;
   }
   static const bool NeedSequentialFinalization = false;
@@ -3447,41 +3633,71 @@
  private:
   static void UpdateUntypedPointers(Heap* heap, MemoryChunk* chunk) {
     if (direction == OLD_TO_NEW) {
-      RememberedSet<OLD_TO_NEW>::IterateWithWrapper(heap, chunk,
-                                                    UpdateOldToNewSlot);
+      RememberedSet<OLD_TO_NEW>::Iterate(chunk, [heap, chunk](Address slot) {
+        return CheckAndUpdateOldToNewSlot(heap, slot);
+      });
     } else {
-      RememberedSet<OLD_TO_OLD>::Iterate(chunk, [heap](Address slot) {
-        PointersUpdatingVisitor::UpdateSlot(heap,
-                                            reinterpret_cast<Object**>(slot));
-        return REMOVE_SLOT;
+      RememberedSet<OLD_TO_OLD>::Iterate(chunk, [](Address slot) {
+        return UpdateSlot(reinterpret_cast<Object**>(slot));
       });
     }
   }
 
-  static void UpdateTypedPointers(Heap* heap, MemoryChunk* chunk,
-                                  PointersUpdatingVisitor* visitor) {
+  static void UpdateTypedPointers(Heap* heap, MemoryChunk* chunk) {
     if (direction == OLD_TO_OLD) {
       Isolate* isolate = heap->isolate();
       RememberedSet<OLD_TO_OLD>::IterateTyped(
-          chunk, [isolate, visitor](SlotType type, Address slot) {
-            UpdateTypedSlot(isolate, visitor, type, slot);
-            return REMOVE_SLOT;
+          chunk, [isolate](SlotType type, Address host_addr, Address slot) {
+            return UpdateTypedSlotHelper::UpdateTypedSlot(isolate, type, slot,
+                                                          UpdateSlot);
+          });
+    } else {
+      Isolate* isolate = heap->isolate();
+      RememberedSet<OLD_TO_NEW>::IterateTyped(
+          chunk,
+          [isolate, heap](SlotType type, Address host_addr, Address slot) {
+            return UpdateTypedSlotHelper::UpdateTypedSlot(
+                isolate, type, slot, [heap](Object** slot) {
+                  return CheckAndUpdateOldToNewSlot(
+                      heap, reinterpret_cast<Address>(slot));
+                });
           });
     }
   }
 
-  static void UpdateOldToNewSlot(HeapObject** address, HeapObject* object) {
-    MapWord map_word = object->map_word();
-    // Since we only filter invalid slots in old space, the store buffer can
-    // still contain stale pointers in large object and in map spaces. Ignore
-    // these pointers here.
-    DCHECK(map_word.IsForwardingAddress() ||
-           !object->GetHeap()->old_space()->Contains(
-               reinterpret_cast<Address>(address)));
-    if (map_word.IsForwardingAddress()) {
-      // Update the corresponding slot.
-      *address = map_word.ToForwardingAddress();
+  static SlotCallbackResult CheckAndUpdateOldToNewSlot(Heap* heap,
+                                                       Address slot_address) {
+    Object** slot = reinterpret_cast<Object**>(slot_address);
+    if (heap->InFromSpace(*slot)) {
+      HeapObject* heap_object = reinterpret_cast<HeapObject*>(*slot);
+      DCHECK(heap_object->IsHeapObject());
+      MapWord map_word = heap_object->map_word();
+      // There could still be stale pointers in large object space, map space,
+      // and old space for pages that have been promoted.
+      if (map_word.IsForwardingAddress()) {
+        // Update the corresponding slot.
+        *slot = map_word.ToForwardingAddress();
+      }
+      // If the object was in from space before and is after executing the
+      // callback in to space, the object is still live.
+      // Unfortunately, we do not know about the slot. It could be in a
+      // just freed free space object.
+      if (heap->InToSpace(*slot)) {
+        return KEEP_SLOT;
+      }
+    } else if (heap->InToSpace(*slot)) {
+      DCHECK(Page::FromAddress(reinterpret_cast<HeapObject*>(*slot)->address())
+                 ->IsFlagSet(Page::PAGE_NEW_NEW_PROMOTION));
+      // Slots can be in "to" space after a page has been moved. Since there is
+      // no forwarding information present we need to check the markbits to
+      // determine liveness.
+      if (Marking::IsBlack(
+              Marking::MarkBitFrom(reinterpret_cast<HeapObject*>(*slot))))
+        return KEEP_SLOT;
+    } else {
+      DCHECK(!heap->InNewSpace(*slot));
     }
+    return REMOVE_SLOT;
   }
 };
 
@@ -3493,15 +3709,14 @@
 }
 
 template <PointerDirection direction>
-void UpdatePointersInParallel(Heap* heap) {
+void UpdatePointersInParallel(Heap* heap, base::Semaphore* semaphore) {
   PageParallelJob<PointerUpdateJobTraits<direction> > job(
-      heap, heap->isolate()->cancelable_task_manager());
+      heap, heap->isolate()->cancelable_task_manager(), semaphore);
   RememberedSet<direction>::IterateMemoryChunks(
       heap, [&job](MemoryChunk* chunk) { job.AddPage(chunk, 0); });
-  PointersUpdatingVisitor visitor(heap);
   int num_pages = job.NumberOfPages();
   int num_tasks = NumberOfPointerUpdateTasks(num_pages);
-  job.Run(num_tasks, [&visitor](int i) { return &visitor; });
+  job.Run(num_tasks, [](int i) { return 0; });
 }
 
 class ToSpacePointerUpdateJobTraits {
@@ -3511,6 +3726,24 @@
 
   static bool ProcessPageInParallel(Heap* heap, PerTaskData visitor,
                                     MemoryChunk* chunk, PerPageData limits) {
+    if (chunk->IsFlagSet(Page::PAGE_NEW_NEW_PROMOTION)) {
+      // New->new promoted pages contain garbage so they require iteration
+      // using markbits.
+      ProcessPageInParallelVisitLive(heap, visitor, chunk, limits);
+    } else {
+      ProcessPageInParallelVisitAll(heap, visitor, chunk, limits);
+    }
+    return true;
+  }
+
+  static const bool NeedSequentialFinalization = false;
+  static void FinalizePageSequentially(Heap*, MemoryChunk*, bool, PerPageData) {
+  }
+
+ private:
+  static void ProcessPageInParallelVisitAll(Heap* heap, PerTaskData visitor,
+                                            MemoryChunk* chunk,
+                                            PerPageData limits) {
     for (Address cur = limits.first; cur < limits.second;) {
       HeapObject* object = HeapObject::FromAddress(cur);
       Map* map = object->map();
@@ -3518,27 +3751,33 @@
       object->IterateBody(map->instance_type(), size, visitor);
       cur += size;
     }
-    return true;
   }
-  static const bool NeedSequentialFinalization = false;
-  static void FinalizePageSequentially(Heap*, MemoryChunk*, bool, PerPageData) {
+
+  static void ProcessPageInParallelVisitLive(Heap* heap, PerTaskData visitor,
+                                             MemoryChunk* chunk,
+                                             PerPageData limits) {
+    LiveObjectIterator<kBlackObjects> it(chunk);
+    HeapObject* object = NULL;
+    while ((object = it.Next()) != NULL) {
+      Map* map = object->map();
+      int size = object->SizeFromMap(map);
+      object->IterateBody(map->instance_type(), size, visitor);
+    }
   }
 };
 
-void UpdateToSpacePointersInParallel(Heap* heap) {
+void UpdateToSpacePointersInParallel(Heap* heap, base::Semaphore* semaphore) {
   PageParallelJob<ToSpacePointerUpdateJobTraits> job(
-      heap, heap->isolate()->cancelable_task_manager());
+      heap, heap->isolate()->cancelable_task_manager(), semaphore);
   Address space_start = heap->new_space()->bottom();
   Address space_end = heap->new_space()->top();
-  NewSpacePageIterator it(space_start, space_end);
-  while (it.has_next()) {
-    NewSpacePage* page = it.next();
+  for (Page* page : NewSpacePageRange(space_start, space_end)) {
     Address start =
         page->Contains(space_start) ? space_start : page->area_start();
     Address end = page->Contains(space_end) ? space_end : page->area_end();
     job.AddPage(page, std::make_pair(start, end));
   }
-  PointersUpdatingVisitor visitor(heap);
+  PointersUpdatingVisitor visitor;
   int num_tasks = FLAG_parallel_pointer_update ? job.NumberOfPages() : 1;
   job.Run(num_tasks, [&visitor](int i) { return &visitor; });
 }
@@ -3546,41 +3785,22 @@
 void MarkCompactCollector::UpdatePointersAfterEvacuation() {
   TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS);
 
-  PointersUpdatingVisitor updating_visitor(heap());
+  PointersUpdatingVisitor updating_visitor;
 
   {
     TRACE_GC(heap()->tracer(),
              GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW);
-    UpdateToSpacePointersInParallel(heap_);
+    UpdateToSpacePointersInParallel(heap_, &page_parallel_job_semaphore_);
     // Update roots.
     heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE);
-    UpdatePointersInParallel<OLD_TO_NEW>(heap_);
+    UpdatePointersInParallel<OLD_TO_NEW>(heap_, &page_parallel_job_semaphore_);
   }
 
   {
     Heap* heap = this->heap();
     TRACE_GC(heap->tracer(),
              GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED);
-    UpdatePointersInParallel<OLD_TO_OLD>(heap_);
-  }
-
-  {
-    TRACE_GC(heap()->tracer(),
-             GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_BETWEEN_EVACUATED);
-    for (Page* p : evacuation_candidates_) {
-      DCHECK(p->IsEvacuationCandidate());
-      // Important: skip list should be cleared only after roots were updated
-      // because root iteration traverses the stack and might have to find
-      // code objects from non-updated pc pointing into evacuation candidate.
-      SkipList* list = p->skip_list();
-      if (list != NULL) list->Clear();
-
-      // First pass on aborted pages, fixing up all live objects.
-      if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) {
-        p->ClearEvacuationCandidate();
-        VisitLiveObjectsBody(p, &updating_visitor);
-      }
-    }
+    UpdatePointersInParallel<OLD_TO_OLD>(heap_, &page_parallel_job_semaphore_);
   }
 
   {
@@ -3606,33 +3826,29 @@
   }
   evacuation_candidates_.Rewind(0);
   compacting_ = false;
-  heap()->FreeQueuedChunks();
+  heap()->memory_allocator()->unmapper()->FreeQueuedChunks();
 }
 
-
-int MarkCompactCollector::SweepInParallel(PagedSpace* space,
-                                          int required_freed_bytes,
-                                          int max_pages) {
+int MarkCompactCollector::Sweeper::ParallelSweepSpace(AllocationSpace identity,
+                                                      int required_freed_bytes,
+                                                      int max_pages) {
   int max_freed = 0;
-  int max_freed_overall = 0;
-  int page_count = 0;
-  for (Page* p : sweeping_list(space)) {
-    max_freed = SweepInParallel(p, space);
-    DCHECK(max_freed >= 0);
-    if (required_freed_bytes > 0 && max_freed >= required_freed_bytes) {
+  int pages_freed = 0;
+  Page* page = nullptr;
+  while ((page = GetSweepingPageSafe(identity)) != nullptr) {
+    int freed = ParallelSweepPage(page, identity);
+    pages_freed += 1;
+    DCHECK_GE(freed, 0);
+    max_freed = Max(max_freed, freed);
+    if ((required_freed_bytes) > 0 && (max_freed >= required_freed_bytes))
       return max_freed;
-    }
-    max_freed_overall = Max(max_freed, max_freed_overall);
-    page_count++;
-    if (max_pages > 0 && page_count >= max_pages) {
-      break;
-    }
+    if ((max_pages > 0) && (pages_freed >= max_pages)) return max_freed;
   }
-  return max_freed_overall;
+  return max_freed;
 }
 
-
-int MarkCompactCollector::SweepInParallel(Page* page, PagedSpace* space) {
+int MarkCompactCollector::Sweeper::ParallelSweepPage(Page* page,
+                                                     AllocationSpace identity) {
   int max_freed = 0;
   if (page->mutex()->TryLock()) {
     // If this page was already swept in the meantime, we can return here.
@@ -3641,19 +3857,25 @@
       return 0;
     }
     page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress);
-    if (space->identity() == OLD_SPACE) {
-      max_freed = Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST,
-                        IGNORE_FREE_SPACE>(space, page, NULL);
-    } else if (space->identity() == CODE_SPACE) {
-      max_freed = Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, REBUILD_SKIP_LIST,
-                        IGNORE_FREE_SPACE>(space, page, NULL);
+    if (identity == NEW_SPACE) {
+      RawSweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST,
+               IGNORE_FREE_LIST, IGNORE_FREE_SPACE>(nullptr, page, nullptr);
+    } else if (identity == OLD_SPACE) {
+      max_freed = RawSweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST,
+                           REBUILD_FREE_LIST, IGNORE_FREE_SPACE>(
+          heap_->paged_space(identity), page, nullptr);
+    } else if (identity == CODE_SPACE) {
+      max_freed = RawSweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, REBUILD_SKIP_LIST,
+                           REBUILD_FREE_LIST, IGNORE_FREE_SPACE>(
+          heap_->paged_space(identity), page, nullptr);
     } else {
-      max_freed = Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST,
-                        IGNORE_FREE_SPACE>(space, page, NULL);
+      max_freed = RawSweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST,
+                           REBUILD_FREE_LIST, IGNORE_FREE_SPACE>(
+          heap_->paged_space(identity), page, nullptr);
     }
     {
-      base::LockGuard<base::Mutex> guard(&swept_pages_mutex_);
-      swept_pages(space->identity())->Add(page);
+      base::LockGuard<base::Mutex> guard(&mutex_);
+      swept_list_[identity].Add(page);
     }
     page->concurrent_sweeping_state().SetValue(Page::kSweepingDone);
     page->mutex()->Unlock();
@@ -3661,17 +3883,55 @@
   return max_freed;
 }
 
+void MarkCompactCollector::Sweeper::AddPage(AllocationSpace space, Page* page) {
+  DCHECK(!sweeping_in_progress_);
+  PrepareToBeSweptPage(space, page);
+  sweeping_list_[space].push_back(page);
+}
+
+void MarkCompactCollector::Sweeper::AddLatePage(AllocationSpace space,
+                                                Page* page) {
+  DCHECK(sweeping_in_progress_);
+  PrepareToBeSweptPage(space, page);
+  late_pages_ = true;
+  AddSweepingPageSafe(space, page);
+}
+
+void MarkCompactCollector::Sweeper::PrepareToBeSweptPage(AllocationSpace space,
+                                                         Page* page) {
+  page->concurrent_sweeping_state().SetValue(Page::kSweepingPending);
+  int to_sweep = page->area_size() - page->LiveBytes();
+  if (space != NEW_SPACE)
+    heap_->paged_space(space)->accounting_stats_.ShrinkSpace(to_sweep);
+}
+
+Page* MarkCompactCollector::Sweeper::GetSweepingPageSafe(
+    AllocationSpace space) {
+  base::LockGuard<base::Mutex> guard(&mutex_);
+  Page* page = nullptr;
+  if (!sweeping_list_[space].empty()) {
+    page = sweeping_list_[space].front();
+    sweeping_list_[space].pop_front();
+  }
+  return page;
+}
+
+void MarkCompactCollector::Sweeper::AddSweepingPageSafe(AllocationSpace space,
+                                                        Page* page) {
+  base::LockGuard<base::Mutex> guard(&mutex_);
+  sweeping_list_[space].push_back(page);
+}
 
 void MarkCompactCollector::StartSweepSpace(PagedSpace* space) {
+  Address space_top = space->top();
   space->ClearStats();
 
-  PageIterator it(space);
-
   int will_be_swept = 0;
   bool unused_page_present = false;
 
-  while (it.has_next()) {
-    Page* p = it.next();
+  // Loop needs to support deletion if live bytes == 0 for a page.
+  for (auto it = space->begin(); it != space->end();) {
+    Page* p = *(it++);
     DCHECK(p->SweepingDone());
 
     if (p->IsEvacuationCandidate()) {
@@ -3686,7 +3946,15 @@
       Bitmap::Clear(p);
       p->concurrent_sweeping_state().SetValue(Page::kSweepingDone);
       p->ClearFlag(Page::BLACK_PAGE);
-      // TODO(hpayer): Free unused memory of last black page.
+      // Area above the high watermark is free.
+      Address free_start = p->HighWaterMark();
+      // Check if the space top was in this page, which means that the
+      // high watermark is not up-to-date.
+      if (free_start < space_top && space_top <= p->area_end()) {
+        free_start = space_top;
+      }
+      int size = static_cast<int>(p->area_end() - free_start);
+      space->Free(free_start, size);
       continue;
     }
 
@@ -3696,8 +3964,9 @@
       // (in the free list) dropped again. Since we only use the flag for
       // testing this is fine.
       p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress);
-      Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST,
-            IGNORE_FREE_SPACE>(space, p, nullptr);
+      Sweeper::RawSweep<Sweeper::SWEEP_ONLY, Sweeper::SWEEP_ON_MAIN_THREAD,
+                        Sweeper::IGNORE_SKIP_LIST, Sweeper::IGNORE_FREE_LIST,
+                        Sweeper::IGNORE_FREE_SPACE>(space, p, nullptr);
       continue;
     }
 
@@ -3705,18 +3974,17 @@
     if (p->LiveBytes() == 0) {
       if (unused_page_present) {
         if (FLAG_gc_verbose) {
-          PrintIsolate(isolate(), "sweeping: released page: %p", p);
+          PrintIsolate(isolate(), "sweeping: released page: %p",
+                       static_cast<void*>(p));
         }
+        ArrayBufferTracker::FreeAll(p);
         space->ReleasePage(p);
         continue;
       }
       unused_page_present = true;
     }
 
-    p->concurrent_sweeping_state().SetValue(Page::kSweepingPending);
-    sweeping_list(space).push_back(p);
-    int to_sweep = p->area_size() - p->LiveBytes();
-    space->accounting_stats_.ShrinkSpace(to_sweep);
+    sweeper().AddPage(space->identity(), p);
     will_be_swept++;
   }
 
@@ -3724,8 +3992,6 @@
     PrintIsolate(isolate(), "sweeping: space=%s initialized_for_sweeping=%d",
                  AllocationSpaceName(space->identity()), will_be_swept);
   }
-  std::sort(sweeping_list(space).begin(), sweeping_list(space).end(),
-            [](Page* a, Page* b) { return a->LiveBytes() < b->LiveBytes(); });
 }
 
 
@@ -3741,7 +4007,6 @@
 #endif
 
   {
-    sweeping_in_progress_ = true;
     {
       GCTracer::Scope sweep_scope(heap()->tracer(),
                                   GCTracer::Scope::MC_SWEEP_OLD);
@@ -3757,9 +4022,7 @@
                                   GCTracer::Scope::MC_SWEEP_MAP);
       StartSweepSpace(heap()->map_space());
     }
-    if (FLAG_concurrent_sweeping) {
-      StartSweeperThreads();
-    }
+    sweeper().StartSweeping();
   }
 
   // Deallocate unmarked large objects.
@@ -3771,13 +4034,6 @@
   }
 }
 
-
-void MarkCompactCollector::ParallelSweepSpacesComplete() {
-  sweeping_list(heap()->old_space()).clear();
-  sweeping_list(heap()->code_space()).clear();
-  sweeping_list(heap()->map_space()).clear();
-}
-
 Isolate* MarkCompactCollector::isolate() const { return heap_->isolate(); }
 
 
@@ -3792,7 +4048,10 @@
   Page* source_page = Page::FromAddress(reinterpret_cast<Address>(host));
   if (target_page->IsEvacuationCandidate() &&
       !ShouldSkipEvacuationSlotRecording(host)) {
-    RememberedSet<OLD_TO_OLD>::InsertTyped(source_page, CODE_ENTRY_SLOT, slot);
+    // TODO(ulan): remove this check after investigating crbug.com/414964.
+    CHECK(target->IsCode());
+    RememberedSet<OLD_TO_OLD>::InsertTyped(
+        source_page, reinterpret_cast<Address>(host), CODE_ENTRY_SLOT, slot);
   }
 }
 
diff --git a/src/heap/mark-compact.h b/src/heap/mark-compact.h
index cd207bc..07b289e 100644
--- a/src/heap/mark-compact.h
+++ b/src/heap/mark-compact.h
@@ -5,6 +5,8 @@
 #ifndef V8_HEAP_MARK_COMPACT_H_
 #define V8_HEAP_MARK_COMPACT_H_
 
+#include <deque>
+
 #include "src/base/bits.h"
 #include "src/heap/spaces.h"
 #include "src/heap/store-buffer.h"
@@ -400,6 +402,77 @@
  public:
   class Evacuator;
 
+  class Sweeper {
+   public:
+    class SweeperTask;
+
+    enum SweepingMode { SWEEP_ONLY, SWEEP_AND_VISIT_LIVE_OBJECTS };
+    enum SkipListRebuildingMode { REBUILD_SKIP_LIST, IGNORE_SKIP_LIST };
+    enum FreeListRebuildingMode { REBUILD_FREE_LIST, IGNORE_FREE_LIST };
+    enum FreeSpaceTreatmentMode { IGNORE_FREE_SPACE, ZAP_FREE_SPACE };
+    enum SweepingParallelism { SWEEP_ON_MAIN_THREAD, SWEEP_IN_PARALLEL };
+
+    typedef std::deque<Page*> SweepingList;
+    typedef List<Page*> SweptList;
+
+    template <SweepingMode sweeping_mode, SweepingParallelism parallelism,
+              SkipListRebuildingMode skip_list_mode,
+              FreeListRebuildingMode free_list_mode,
+              FreeSpaceTreatmentMode free_space_mode>
+    static int RawSweep(PagedSpace* space, Page* p, ObjectVisitor* v);
+
+    explicit Sweeper(Heap* heap)
+        : heap_(heap),
+          pending_sweeper_tasks_semaphore_(0),
+          sweeping_in_progress_(false),
+          late_pages_(false),
+          num_sweeping_tasks_(0) {}
+
+    bool sweeping_in_progress() { return sweeping_in_progress_; }
+    bool contains_late_pages() { return late_pages_; }
+
+    void AddPage(AllocationSpace space, Page* page);
+    void AddLatePage(AllocationSpace space, Page* page);
+
+    int ParallelSweepSpace(AllocationSpace identity, int required_freed_bytes,
+                           int max_pages = 0);
+    int ParallelSweepPage(Page* page, AllocationSpace identity);
+
+    void StartSweeping();
+    void StartSweepingHelper(AllocationSpace space_to_start);
+    void EnsureCompleted();
+    void EnsureNewSpaceCompleted();
+    bool IsSweepingCompleted();
+    void SweepOrWaitUntilSweepingCompleted(Page* page);
+
+    void AddSweptPageSafe(PagedSpace* space, Page* page);
+    Page* GetSweptPageSafe(PagedSpace* space);
+
+   private:
+    static const int kAllocationSpaces = LAST_PAGED_SPACE + 1;
+
+    template <typename Callback>
+    void ForAllSweepingSpaces(Callback callback) {
+      for (int i = 0; i < kAllocationSpaces; i++) {
+        callback(static_cast<AllocationSpace>(i));
+      }
+    }
+
+    Page* GetSweepingPageSafe(AllocationSpace space);
+    void AddSweepingPageSafe(AllocationSpace space, Page* page);
+
+    void PrepareToBeSweptPage(AllocationSpace space, Page* page);
+
+    Heap* heap_;
+    base::Semaphore pending_sweeper_tasks_semaphore_;
+    base::Mutex mutex_;
+    SweptList swept_list_[kAllocationSpaces];
+    SweepingList sweeping_list_[kAllocationSpaces];
+    bool sweeping_in_progress_;
+    bool late_pages_;
+    base::AtomicNumber<intptr_t> num_sweeping_tasks_;
+  };
+
   enum IterationMode {
     kKeepMarking,
     kClearMarkbits,
@@ -451,8 +524,6 @@
   CodeFlusher* code_flusher() { return code_flusher_; }
   inline bool is_code_flushing_enabled() const { return code_flusher_ != NULL; }
 
-  enum SweepingParallelism { SWEEP_ON_MAIN_THREAD, SWEEP_IN_PARALLEL };
-
 #ifdef VERIFY_HEAP
   void VerifyValidStoreAndSlotsBufferEntries();
   void VerifyMarkbitsAreClean();
@@ -490,38 +561,19 @@
 
   MarkingParity marking_parity() { return marking_parity_; }
 
-  // Concurrent and parallel sweeping support. If required_freed_bytes was set
-  // to a value larger than 0, then sweeping returns after a block of at least
-  // required_freed_bytes was freed. If required_freed_bytes was set to zero
-  // then the whole given space is swept. It returns the size of the maximum
-  // continuous freed memory chunk.
-  int SweepInParallel(PagedSpace* space, int required_freed_bytes,
-                      int max_pages = 0);
-
-  // Sweeps a given page concurrently to the sweeper threads. It returns the
-  // size of the maximum continuous freed memory chunk.
-  int SweepInParallel(Page* page, PagedSpace* space);
-
   // Ensures that sweeping is finished.
   //
   // Note: Can only be called safely from main thread.
   void EnsureSweepingCompleted();
 
-  void SweepOrWaitUntilSweepingCompleted(Page* page);
-
   // Help out in sweeping the corresponding space and refill memory that has
   // been regained.
   //
   // Note: Thread-safe.
   void SweepAndRefill(CompactionSpace* space);
 
-  // If sweeper threads are not active this method will return true. If
-  // this is a latency issue we should be smarter here. Otherwise, it will
-  // return true if the sweeper threads are done processing the pages.
-  bool IsSweepingCompleted();
-
   // Checks if sweeping is in progress right now on any space.
-  bool sweeping_in_progress() { return sweeping_in_progress_; }
+  bool sweeping_in_progress() { return sweeper().sweeping_in_progress(); }
 
   void set_evacuation(bool evacuation) { evacuation_ = evacuation; }
 
@@ -562,62 +614,37 @@
   // address range.
   void RemoveObjectSlots(Address start_slot, Address end_slot);
 
-  base::Mutex* swept_pages_mutex() { return &swept_pages_mutex_; }
-  List<Page*>* swept_pages(AllocationSpace id) {
-    switch (id) {
-      case OLD_SPACE:
-        return &swept_old_space_pages_;
-      case CODE_SPACE:
-        return &swept_code_space_pages_;
-      case MAP_SPACE:
-        return &swept_map_space_pages_;
-      default:
-        UNREACHABLE();
-    }
-    return nullptr;
-  }
+  Sweeper& sweeper() { return sweeper_; }
+
+  void RegisterWrappersWithEmbedderHeapTracer();
+
+  void SetEmbedderHeapTracer(EmbedderHeapTracer* tracer);
+
+  EmbedderHeapTracer* embedder_heap_tracer() { return embedder_heap_tracer_; }
+
+  bool UsingEmbedderHeapTracer() { return embedder_heap_tracer(); }
+
+  void TracePossibleWrapper(JSObject* js_object);
+
+  void RegisterExternallyReferencedObject(Object** object);
 
  private:
+  class EvacuateNewSpacePageVisitor;
   class EvacuateNewSpaceVisitor;
   class EvacuateOldSpaceVisitor;
+  class EvacuateRecordOnlyVisitor;
   class EvacuateVisitorBase;
   class HeapObjectVisitor;
-  class SweeperTask;
-
-  typedef std::vector<Page*> SweepingList;
 
   explicit MarkCompactCollector(Heap* heap);
 
   bool WillBeDeoptimized(Code* code);
   void ClearInvalidRememberedSetSlots();
 
-  void StartSweeperThreads();
-
   void ComputeEvacuationHeuristics(int area_size,
                                    int* target_fragmentation_percent,
                                    int* max_evacuated_bytes);
 
-#ifdef DEBUG
-  enum CollectorState {
-    IDLE,
-    PREPARE_GC,
-    MARK_LIVE_OBJECTS,
-    SWEEP_SPACES,
-    ENCODE_FORWARDING_ADDRESSES,
-    UPDATE_POINTERS,
-    RELOCATE_OBJECTS
-  };
-
-  // The current stage of the collector.
-  CollectorState state_;
-#endif
-
-  MarkingParity marking_parity_;
-
-  bool was_marked_incrementally_;
-
-  bool evacuation_;
-
   // Finishes GC, performs heap verification if enabled.
   void Finish();
 
@@ -678,8 +705,8 @@
   // or overflowed in the heap.  This respects references only considered in
   // the final atomic marking pause including the following:
   //    - Processing of objects reachable through Harmony WeakMaps.
-  //    - Objects reachable due to host application logic like object groups
-  //      or implicit references' groups.
+  //    - Objects reachable due to host application logic like object groups,
+  //      implicit references' groups, or embedder heap tracing.
   void ProcessEphemeralMarking(ObjectVisitor* visitor,
                                bool only_process_harmony_weak_collections);
 
@@ -761,15 +788,12 @@
   //          evacuation.
   //
 
-  inline SweepingList& sweeping_list(Space* space);
-
   // If we are not compacting the heap, we simply sweep the spaces except
   // for the large object space, clearing mark bits and adding unmarked
   // regions to each space's free list.
   void SweepSpaces();
 
   void EvacuateNewSpacePrologue();
-  void EvacuateNewSpaceEpilogue();
 
   void EvacuatePagesInParallel();
 
@@ -782,25 +806,20 @@
 
   // Iterates through all live objects on a page using marking information.
   // Returns whether all objects have successfully been visited.
-  bool VisitLiveObjects(MemoryChunk* page, HeapObjectVisitor* visitor,
+  template <class Visitor>
+  bool VisitLiveObjects(MemoryChunk* page, Visitor* visitor,
                         IterationMode mode);
 
   void VisitLiveObjectsBody(Page* page, ObjectVisitor* visitor);
 
   void RecomputeLiveBytes(MemoryChunk* page);
 
-  void SweepAbortedPages();
-
   void ReleaseEvacuationCandidates();
 
   // Starts sweeping of a space by contributing on the main thread and setting
   // up other pages for sweeping.
   void StartSweepSpace(PagedSpace* space);
 
-  // Finalizes the parallel sweeping phase. Marks all the pages that were
-  // swept in parallel.
-  void ParallelSweepSpacesComplete();
-
 #ifdef DEBUG
   friend class MarkObjectVisitor;
   static void VisitObject(HeapObject* obj);
@@ -810,39 +829,52 @@
 #endif
 
   Heap* heap_;
-  base::VirtualMemory* marking_deque_memory_;
-  size_t marking_deque_memory_committed_;
-  MarkingDeque marking_deque_;
-  CodeFlusher* code_flusher_;
-  bool have_code_to_deoptimize_;
 
-  List<Page*> evacuation_candidates_;
-  List<NewSpacePage*> newspace_evacuation_candidates_;
+  base::Semaphore page_parallel_job_semaphore_;
 
-  base::Mutex swept_pages_mutex_;
-  List<Page*> swept_old_space_pages_;
-  List<Page*> swept_code_space_pages_;
-  List<Page*> swept_map_space_pages_;
+#ifdef DEBUG
+  enum CollectorState {
+    IDLE,
+    PREPARE_GC,
+    MARK_LIVE_OBJECTS,
+    SWEEP_SPACES,
+    ENCODE_FORWARDING_ADDRESSES,
+    UPDATE_POINTERS,
+    RELOCATE_OBJECTS
+  };
 
-  SweepingList sweeping_list_old_space_;
-  SweepingList sweeping_list_code_space_;
-  SweepingList sweeping_list_map_space_;
+  // The current stage of the collector.
+  CollectorState state_;
+#endif
+
+  MarkingParity marking_parity_;
+
+  bool was_marked_incrementally_;
+
+  bool evacuation_;
 
   // True if we are collecting slots to perform evacuation from evacuation
   // candidates.
   bool compacting_;
 
-  // True if concurrent or parallel sweeping is currently in progress.
-  bool sweeping_in_progress_;
-
-  // Semaphore used to synchronize sweeper tasks.
-  base::Semaphore pending_sweeper_tasks_semaphore_;
-
-  // Semaphore used to synchronize compaction tasks.
-  base::Semaphore pending_compaction_tasks_semaphore_;
-
   bool black_allocation_;
 
+  bool have_code_to_deoptimize_;
+
+  base::VirtualMemory* marking_deque_memory_;
+  size_t marking_deque_memory_committed_;
+  MarkingDeque marking_deque_;
+  std::vector<std::pair<void*, void*>> wrappers_to_trace_;
+
+  CodeFlusher* code_flusher_;
+
+  EmbedderHeapTracer* embedder_heap_tracer_;
+
+  List<Page*> evacuation_candidates_;
+  List<Page*> newspace_evacuation_candidates_;
+
+  Sweeper sweeper_;
+
   friend class Heap;
   friend class StoreBuffer;
 };
diff --git a/src/heap/object-stats.cc b/src/heap/object-stats.cc
index c1566ab..e7d90b3 100644
--- a/src/heap/object-stats.cc
+++ b/src/heap/object-stats.cc
@@ -134,8 +134,7 @@
 
 Isolate* ObjectStats::isolate() { return heap()->isolate(); }
 
-
-void ObjectStatsVisitor::CountFixedArray(
+void ObjectStatsCollector::CountFixedArray(
     FixedArrayBase* fixed_array, FixedArraySubInstanceType fast_type,
     FixedArraySubInstanceType dictionary_type) {
   Heap* heap = fixed_array->map()->GetHeap();
@@ -152,12 +151,32 @@
   }
 }
 
+void ObjectStatsCollector::CollectStatistics(StaticVisitorBase::VisitorId id,
+                                             Map* map, HeapObject* obj) {
+  // Record any type specific statistics here.
+  switch (id) {
+    case StaticVisitorBase::kVisitMap:
+      RecordMapStats(map, obj);
+      break;
+    case StaticVisitorBase::kVisitCode:
+      RecordCodeStats(map, obj);
+      break;
+    case StaticVisitorBase::kVisitSharedFunctionInfo:
+      RecordSharedFunctionInfoStats(map, obj);
+      break;
+    case StaticVisitorBase::kVisitFixedArray:
+      RecordFixedArrayStats(map, obj);
+      break;
+    default:
+      break;
+  }
 
-void ObjectStatsVisitor::VisitBase(VisitorId id, Map* map, HeapObject* obj) {
   Heap* heap = map->GetHeap();
   int object_size = obj->Size();
   heap->object_stats_->RecordObjectStats(map->instance_type(), object_size);
-  table_.GetVisitorById(id)(map, obj);
+}
+
+void ObjectStatsCollector::CollectFixedArrayStatistics(HeapObject* obj) {
   if (obj->IsJSObject()) {
     JSObject* object = JSObject::cast(obj);
     CountFixedArray(object->elements(), DICTIONARY_ELEMENTS_SUB_TYPE,
@@ -167,16 +186,7 @@
   }
 }
 
-
-template <ObjectStatsVisitor::VisitorId id>
-void ObjectStatsVisitor::Visit(Map* map, HeapObject* obj) {
-  VisitBase(id, map, obj);
-}
-
-
-template <>
-void ObjectStatsVisitor::Visit<ObjectStatsVisitor::kVisitMap>(Map* map,
-                                                              HeapObject* obj) {
+void ObjectStatsCollector::RecordMapStats(Map* map, HeapObject* obj) {
   Heap* heap = map->GetHeap();
   Map* map_obj = Map::cast(obj);
   DCHECK(map->instance_type() == MAP_TYPE);
@@ -187,59 +197,42 @@
                                                       fixed_array_size);
   }
   if (map_obj->has_code_cache()) {
-    CodeCache* cache = CodeCache::cast(map_obj->code_cache());
-    heap->object_stats_->RecordFixedArraySubTypeStats(
-        MAP_CODE_CACHE_SUB_TYPE, cache->default_cache()->Size());
-    if (!cache->normal_type_cache()->IsUndefined()) {
-      heap->object_stats_->RecordFixedArraySubTypeStats(
-          MAP_CODE_CACHE_SUB_TYPE,
-          FixedArray::cast(cache->normal_type_cache())->Size());
-    }
+    FixedArray* cache = map_obj->code_cache();
+    heap->object_stats_->RecordFixedArraySubTypeStats(MAP_CODE_CACHE_SUB_TYPE,
+                                                      cache->Size());
   }
-  VisitBase(kVisitMap, map, obj);
 }
 
-
-template <>
-void ObjectStatsVisitor::Visit<ObjectStatsVisitor::kVisitCode>(
-    Map* map, HeapObject* obj) {
+void ObjectStatsCollector::RecordCodeStats(Map* map, HeapObject* obj) {
   Heap* heap = map->GetHeap();
   int object_size = obj->Size();
   DCHECK(map->instance_type() == CODE_TYPE);
   Code* code_obj = Code::cast(obj);
   heap->object_stats_->RecordCodeSubTypeStats(code_obj->kind(),
                                               code_obj->GetAge(), object_size);
-  VisitBase(kVisitCode, map, obj);
 }
 
-
-template <>
-void ObjectStatsVisitor::Visit<ObjectStatsVisitor::kVisitSharedFunctionInfo>(
-    Map* map, HeapObject* obj) {
+void ObjectStatsCollector::RecordSharedFunctionInfoStats(Map* map,
+                                                         HeapObject* obj) {
   Heap* heap = map->GetHeap();
   SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
   if (sfi->scope_info() != heap->empty_fixed_array()) {
     heap->object_stats_->RecordFixedArraySubTypeStats(
         SCOPE_INFO_SUB_TYPE, FixedArray::cast(sfi->scope_info())->Size());
   }
-  VisitBase(kVisitSharedFunctionInfo, map, obj);
 }
 
-
-template <>
-void ObjectStatsVisitor::Visit<ObjectStatsVisitor::kVisitFixedArray>(
-    Map* map, HeapObject* obj) {
+void ObjectStatsCollector::RecordFixedArrayStats(Map* map, HeapObject* obj) {
   Heap* heap = map->GetHeap();
   FixedArray* fixed_array = FixedArray::cast(obj);
   if (fixed_array == heap->string_table()) {
     heap->object_stats_->RecordFixedArraySubTypeStats(STRING_TABLE_SUB_TYPE,
                                                       fixed_array->Size());
   }
-  VisitBase(kVisitFixedArray, map, obj);
 }
 
-
-void ObjectStatsVisitor::Initialize(VisitorDispatchTable<Callback>* original) {
+void MarkCompactObjectStatsVisitor::Initialize(
+    VisitorDispatchTable<Callback>* original) {
   // Copy the original visitor table to make call-through possible. After we
   // preserved a copy locally, we patch the original table to call us.
   table_.CopyFrom(original);
@@ -248,5 +241,29 @@
 #undef COUNT_FUNCTION
 }
 
+template <MarkCompactObjectStatsVisitor::VisitorId id>
+void MarkCompactObjectStatsVisitor::Visit(Map* map, HeapObject* obj) {
+  ObjectStatsCollector::CollectStatistics(id, map, obj);
+  table_.GetVisitorById(id)(map, obj);
+  ObjectStatsCollector::CollectFixedArrayStatistics(obj);
+}
+
+void IncrementalMarkingObjectStatsVisitor::Initialize(
+    VisitorDispatchTable<Callback>* original) {
+  // Copy the original visitor table to make call-through possible. After we
+  // preserved a copy locally, we patch the original table to call us.
+  table_.CopyFrom(original);
+#define COUNT_FUNCTION(id) original->Register(kVisit##id, Visit<kVisit##id>);
+  VISITOR_ID_LIST(COUNT_FUNCTION)
+#undef COUNT_FUNCTION
+}
+
+template <IncrementalMarkingObjectStatsVisitor::VisitorId id>
+void IncrementalMarkingObjectStatsVisitor::Visit(Map* map, HeapObject* obj) {
+  ObjectStatsCollector::CollectStatistics(id, map, obj);
+  table_.GetVisitorById(id)(map, obj);
+  ObjectStatsCollector::CollectFixedArrayStatistics(obj);
+}
+
 }  // namespace internal
 }  // namespace v8
diff --git a/src/heap/object-stats.h b/src/heap/object-stats.h
index e2dcfaa..ce0a317 100644
--- a/src/heap/object-stats.h
+++ b/src/heap/object-stats.h
@@ -81,16 +81,34 @@
   size_t object_sizes_last_time_[OBJECT_STATS_COUNT];
 };
 
-
-class ObjectStatsVisitor : public StaticMarkingVisitor<ObjectStatsVisitor> {
+class ObjectStatsCollector {
  public:
-  static void Initialize(VisitorDispatchTable<Callback>* original);
-
-  static void VisitBase(VisitorId id, Map* map, HeapObject* obj);
+  static void CollectStatistics(StaticVisitorBase::VisitorId id, Map* map,
+                                HeapObject* obj);
+  static void CollectFixedArrayStatistics(HeapObject* obj);
 
   static void CountFixedArray(FixedArrayBase* fixed_array,
                               FixedArraySubInstanceType fast_type,
                               FixedArraySubInstanceType dictionary_type);
+  static void RecordMapStats(Map* map, HeapObject* obj);
+  static void RecordCodeStats(Map* map, HeapObject* obj);
+  static void RecordSharedFunctionInfoStats(Map* map, HeapObject* obj);
+  static void RecordFixedArrayStats(Map* map, HeapObject* obj);
+};
+
+class MarkCompactObjectStatsVisitor
+    : public StaticMarkingVisitor<MarkCompactObjectStatsVisitor> {
+ public:
+  static void Initialize(VisitorDispatchTable<Callback>* original);
+
+  template <VisitorId id>
+  static inline void Visit(Map* map, HeapObject* obj);
+};
+
+class IncrementalMarkingObjectStatsVisitor
+    : public StaticMarkingVisitor<IncrementalMarkingObjectStatsVisitor> {
+ public:
+  static void Initialize(VisitorDispatchTable<Callback>* original);
 
   template <VisitorId id>
   static inline void Visit(Map* map, HeapObject* obj);
diff --git a/src/heap/objects-visiting-inl.h b/src/heap/objects-visiting-inl.h
index c415713..6d26ad0 100644
--- a/src/heap/objects-visiting-inl.h
+++ b/src/heap/objects-visiting-inl.h
@@ -77,7 +77,10 @@
       &FlexibleBodyVisitor<StaticVisitor, JSFunction::BodyDescriptorWeakCode,
                            int>::Visit);
 
-  table_.Register(kVisitJSArrayBuffer, &VisitJSArrayBuffer);
+  table_.Register(
+      kVisitJSArrayBuffer,
+      &FlexibleBodyVisitor<StaticVisitor, JSArrayBuffer::BodyDescriptor,
+                           int>::Visit);
 
   table_.Register(kVisitFreeSpace, &VisitFreeSpace);
 
@@ -90,25 +93,15 @@
 
   table_.template RegisterSpecializations<JSObjectVisitor, kVisitJSObject,
                                           kVisitJSObjectGeneric>();
+
+  // Not using specialized Api object visitor for newspace.
+  table_.template RegisterSpecializations<JSObjectVisitor, kVisitJSApiObject,
+                                          kVisitJSApiObjectGeneric>();
+
   table_.template RegisterSpecializations<StructVisitor, kVisitStruct,
                                           kVisitStructGeneric>();
 }
 
-
-template <typename StaticVisitor>
-int StaticNewSpaceVisitor<StaticVisitor>::VisitJSArrayBuffer(
-    Map* map, HeapObject* object) {
-  typedef FlexibleBodyVisitor<StaticVisitor, JSArrayBuffer::BodyDescriptor, int>
-      JSArrayBufferBodyVisitor;
-
-  if (!JSArrayBuffer::cast(object)->is_external()) {
-    Heap* heap = map->GetHeap();
-    heap->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(object));
-  }
-  return JSArrayBufferBodyVisitor::Visit(map, object);
-}
-
-
 template <typename StaticVisitor>
 int StaticNewSpaceVisitor<StaticVisitor>::VisitBytecodeArray(
     Map* map, HeapObject* object) {
@@ -180,7 +173,10 @@
 
   table_.Register(kVisitJSFunction, &VisitJSFunction);
 
-  table_.Register(kVisitJSArrayBuffer, &VisitJSArrayBuffer);
+  table_.Register(
+      kVisitJSArrayBuffer,
+      &FlexibleBodyVisitor<StaticVisitor, JSArrayBuffer::BodyDescriptor,
+                           void>::Visit);
 
   // Registration for kVisitJSRegExp is done by StaticVisitor.
 
@@ -200,6 +196,9 @@
   table_.template RegisterSpecializations<JSObjectVisitor, kVisitJSObject,
                                           kVisitJSObjectGeneric>();
 
+  table_.template RegisterSpecializations<JSApiObjectVisitor, kVisitJSApiObject,
+                                          kVisitJSApiObjectGeneric>();
+
   table_.template RegisterSpecializations<StructObjectVisitor, kVisitStruct,
                                           kVisitStructGeneric>();
 }
@@ -265,8 +264,8 @@
   // when they might be keeping a Context alive, or when the heap is about
   // to be serialized.
   if (FLAG_cleanup_code_caches_at_gc && target->is_inline_cache_stub() &&
-      !target->is_call_stub() && (heap->isolate()->serializer_enabled() ||
-                                  target->ic_age() != heap->global_ic_age())) {
+      (heap->isolate()->serializer_enabled() ||
+       target->ic_age() != heap->global_ic_age())) {
     ICUtility::Clear(heap->isolate(), rinfo->pc(),
                      rinfo->host()->constant_pool());
     target = Code::GetCodeFromTargetAddress(rinfo->target_address());
@@ -377,7 +376,7 @@
   }
   // Enqueue the array in linked list of encountered transition arrays if it is
   // not already in the list.
-  if (array->next_link()->IsUndefined()) {
+  if (array->next_link()->IsUndefined(heap->isolate())) {
     Heap* heap = map->GetHeap();
     array->set_next_link(heap->encountered_transition_arrays(),
                          UPDATE_WEAK_WRITE_BARRIER);
@@ -451,9 +450,6 @@
   if (shared->ic_age() != heap->global_ic_age()) {
     shared->ResetForNewContext(heap->global_ic_age());
   }
-  if (FLAG_cleanup_code_caches_at_gc) {
-    shared->ClearTypeFeedbackInfoAtGCTime();
-  }
   if (FLAG_flush_optimized_code_cache) {
     if (!shared->OptimizedCodeMapIsCleared()) {
       // Always flush the optimized code map if requested by flag.
@@ -484,6 +480,9 @@
                                                           HeapObject* object) {
   Heap* heap = map->GetHeap();
   JSFunction* function = JSFunction::cast(object);
+  if (FLAG_cleanup_code_caches_at_gc) {
+    function->ClearTypeFeedbackInfoAtGCTime();
+  }
   MarkCompactCollector* collector = heap->mark_compact_collector();
   if (collector->is_code_flushing_enabled()) {
     if (IsFlushable(heap, function)) {
@@ -512,24 +511,6 @@
   JSObjectVisitor::Visit(map, object);
 }
 
-
-template <typename StaticVisitor>
-void StaticMarkingVisitor<StaticVisitor>::VisitJSArrayBuffer(
-    Map* map, HeapObject* object) {
-  Heap* heap = map->GetHeap();
-
-  typedef FlexibleBodyVisitor<StaticVisitor, JSArrayBuffer::BodyDescriptor,
-                              void> JSArrayBufferBodyVisitor;
-
-  JSArrayBufferBodyVisitor::Visit(map, object);
-
-  if (!JSArrayBuffer::cast(object)->is_external() &&
-      !heap->InNewSpace(object)) {
-    heap->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(object));
-  }
-}
-
-
 template <typename StaticVisitor>
 void StaticMarkingVisitor<StaticVisitor>::VisitBytecodeArray(
     Map* map, HeapObject* object) {
@@ -625,8 +606,7 @@
   }
 
   // We never flush code for API functions.
-  Object* function_data = shared_info->function_data();
-  if (function_data->IsFunctionTemplateInfo()) {
+  if (shared_info->IsApiFunction()) {
     return false;
   }
 
@@ -640,9 +620,10 @@
     return false;
   }
 
-  // We do not (yet?) flush code for generator functions, because we don't know
-  // if there are still live activations (generator objects) on the heap.
-  if (shared_info->is_generator()) {
+  // We do not (yet?) flush code for generator functions, or async functions,
+  // because we don't know if there are still live activations
+  // (generator objects) on the heap.
+  if (shared_info->is_resumable()) {
     return false;
   }
 
diff --git a/src/heap/objects-visiting.cc b/src/heap/objects-visiting.cc
index 0b857dc..83e2e1c 100644
--- a/src/heap/objects-visiting.cc
+++ b/src/heap/objects-visiting.cc
@@ -103,6 +103,8 @@
       return kVisitJSArrayBuffer;
 
     case JS_OBJECT_TYPE:
+    case JS_ERROR_TYPE:
+    case JS_ARGUMENTS_TYPE:
     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
     case JS_GENERATOR_OBJECT_TYPE:
     case JS_MODULE_TYPE:
@@ -111,7 +113,6 @@
     case JS_ARRAY_TYPE:
     case JS_GLOBAL_PROXY_TYPE:
     case JS_GLOBAL_OBJECT_TYPE:
-    case JS_SPECIAL_API_OBJECT_TYPE:
     case JS_MESSAGE_OBJECT_TYPE:
     case JS_TYPED_ARRAY_TYPE:
     case JS_DATA_VIEW_TYPE:
@@ -123,6 +124,10 @@
     case JS_BOUND_FUNCTION_TYPE:
       return GetVisitorIdForSize(kVisitJSObject, kVisitJSObjectGeneric,
                                  instance_size, has_unboxed_fields);
+    case JS_API_OBJECT_TYPE:
+    case JS_SPECIAL_API_OBJECT_TYPE:
+      return GetVisitorIdForSize(kVisitJSApiObject, kVisitJSApiObjectGeneric,
+                                 instance_size, has_unboxed_fields);
 
     case JS_FUNCTION_TYPE:
       return kVisitJSFunction;
@@ -209,7 +214,7 @@
         }
       }
       // Retained object is new tail.
-      DCHECK(!retained->IsUndefined());
+      DCHECK(!retained->IsUndefined(heap->isolate()));
       candidate = reinterpret_cast<T*>(retained);
       tail = candidate;
 
@@ -282,7 +287,7 @@
   }
 
   static Object* WeakNext(Context* context) {
-    return context->get(Context::NEXT_CONTEXT_LINK);
+    return context->next_context_link();
   }
 
   static int WeakNextOffset() {
diff --git a/src/heap/objects-visiting.h b/src/heap/objects-visiting.h
index 1fe8a17..303db0e 100644
--- a/src/heap/objects-visiting.h
+++ b/src/heap/objects-visiting.h
@@ -58,6 +58,15 @@
   V(JSObject8)             \
   V(JSObject9)             \
   V(JSObjectGeneric)       \
+  V(JSApiObject2)          \
+  V(JSApiObject3)          \
+  V(JSApiObject4)          \
+  V(JSApiObject5)          \
+  V(JSApiObject6)          \
+  V(JSApiObject7)          \
+  V(JSApiObject8)          \
+  V(JSApiObject9)          \
+  V(JSApiObjectGeneric)    \
   V(Struct2)               \
   V(Struct3)               \
   V(Struct4)               \
@@ -96,9 +105,10 @@
 #define VISITOR_ID_ENUM_DECL(id) kVisit##id,
     VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
 #undef VISITOR_ID_ENUM_DECL
-    kVisitorIdCount,
+        kVisitorIdCount,
     kVisitDataObject = kVisitDataObject2,
     kVisitJSObject = kVisitJSObject2,
+    kVisitJSApiObject = kVisitJSApiObject2,
     kVisitStruct = kVisitStruct2,
   };
 
@@ -119,11 +129,12 @@
                                        int object_size,
                                        bool has_unboxed_fields) {
     DCHECK((base == kVisitDataObject) || (base == kVisitStruct) ||
-           (base == kVisitJSObject));
+           (base == kVisitJSObject) || (base == kVisitJSApiObject));
     DCHECK(IsAligned(object_size, kPointerSize));
     DCHECK(Heap::kMinObjectSizeInWords * kPointerSize <= object_size);
     DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
-    DCHECK(!has_unboxed_fields || (base == kVisitJSObject));
+    DCHECK(!has_unboxed_fields || (base == kVisitJSObject) ||
+           (base == kVisitJSApiObject));
 
     if (has_unboxed_fields) return generic;
 
@@ -289,7 +300,6 @@
     return FreeSpace::cast(object)->size();
   }
 
-  INLINE(static int VisitJSArrayBuffer(Map* map, HeapObject* object));
   INLINE(static int VisitBytecodeArray(Map* map, HeapObject* object));
 
   class DataObjectVisitor {
@@ -368,7 +378,6 @@
   INLINE(static void VisitWeakCollection(Map* map, HeapObject* object));
   INLINE(static void VisitJSFunction(Map* map, HeapObject* object));
   INLINE(static void VisitJSRegExp(Map* map, HeapObject* object));
-  INLINE(static void VisitJSArrayBuffer(Map* map, HeapObject* object));
   INLINE(static void VisitNativeContext(Map* map, HeapObject* object));
   INLINE(static void VisitBytecodeArray(Map* map, HeapObject* object));
 
@@ -400,6 +409,28 @@
   typedef FlexibleBodyVisitor<StaticVisitor, JSObject::BodyDescriptor, void>
       JSObjectVisitor;
 
+  class JSApiObjectVisitor : AllStatic {
+   public:
+    template <int size>
+    static inline void VisitSpecialized(Map* map, HeapObject* object) {
+      TracePossibleWrapper(object);
+      JSObjectVisitor::template VisitSpecialized<size>(map, object);
+    }
+
+    INLINE(static void Visit(Map* map, HeapObject* object)) {
+      TracePossibleWrapper(object);
+      JSObjectVisitor::Visit(map, object);
+    }
+
+   private:
+    INLINE(static void TracePossibleWrapper(HeapObject* object)) {
+      if (object->GetHeap()->UsingEmbedderHeapTracer()) {
+        DCHECK(object->IsJSObject());
+        object->GetHeap()->TracePossibleWrapper(JSObject::cast(object));
+      }
+    }
+  };
+
   typedef FlexibleBodyVisitor<StaticVisitor, StructBodyDescriptor, void>
       StructObjectVisitor;
 
diff --git a/src/heap/page-parallel-job.h b/src/heap/page-parallel-job.h
index 720e288..440c440 100644
--- a/src/heap/page-parallel-job.h
+++ b/src/heap/page-parallel-job.h
@@ -33,13 +33,20 @@
 template <typename JobTraits>
 class PageParallelJob {
  public:
-  PageParallelJob(Heap* heap, CancelableTaskManager* cancelable_task_manager)
+  // PageParallelJob cannot dynamically create a semaphore because of a bug in
+  // glibc. See http://crbug.com/609249 and
+  // https://sourceware.org/bugzilla/show_bug.cgi?id=12674.
+  // The caller must provide a semaphore with value 0 and ensure that
+  // the lifetime of the semaphore is the same as the lifetime of the Isolate.
+  // It is guaranteed that the semaphore value will be 0 after Run() call.
+  PageParallelJob(Heap* heap, CancelableTaskManager* cancelable_task_manager,
+                  base::Semaphore* semaphore)
       : heap_(heap),
         cancelable_task_manager_(cancelable_task_manager),
         items_(nullptr),
         num_items_(0),
         num_tasks_(0),
-        pending_tasks_(new base::Semaphore(0)) {}
+        pending_tasks_(semaphore) {}
 
   ~PageParallelJob() {
     Item* item = items_;
@@ -48,7 +55,6 @@
       delete item;
       item = next;
     }
-    delete pending_tasks_;
   }
 
   void AddPage(MemoryChunk* chunk, typename JobTraits::PerPageData data) {
@@ -121,7 +127,7 @@
     Item(MemoryChunk* chunk, typename JobTraits::PerPageData data, Item* next)
         : chunk(chunk), state(kAvailable), data(data), next(next) {}
     MemoryChunk* chunk;
-    AtomicValue<ProcessingState> state;
+    base::AtomicValue<ProcessingState> state;
     typename JobTraits::PerPageData data;
     Item* next;
   };
diff --git a/src/heap/remembered-set.cc b/src/heap/remembered-set.cc
index 403c99b..0bc5e6e 100644
--- a/src/heap/remembered-set.cc
+++ b/src/heap/remembered-set.cc
@@ -16,10 +16,7 @@
 template <PointerDirection direction>
 void RememberedSet<direction>::ClearInvalidSlots(Heap* heap) {
   STATIC_ASSERT(direction == OLD_TO_NEW);
-  PageIterator it(heap->old_space());
-  MemoryChunk* chunk;
-  while (it.has_next()) {
-    chunk = it.next();
+  for (MemoryChunk* chunk : *heap->old_space()) {
     SlotSet* slots = GetSlotSet(chunk);
     if (slots != nullptr) {
       slots->Iterate([heap, chunk](Address addr) {
diff --git a/src/heap/remembered-set.h b/src/heap/remembered-set.h
index 45408bf..339748c 100644
--- a/src/heap/remembered-set.h
+++ b/src/heap/remembered-set.h
@@ -5,6 +5,7 @@
 #ifndef V8_REMEMBERED_SET_H
 #define V8_REMEMBERED_SET_H
 
+#include "src/assembler.h"
 #include "src/heap/heap.h"
 #include "src/heap/slot-set.h"
 #include "src/heap/spaces.h"
@@ -14,6 +15,7 @@
 
 enum PointerDirection { OLD_TO_OLD, OLD_TO_NEW };
 
+// TODO(ulan): Investigate performance of de-templatizing this class.
 template <PointerDirection direction>
 class RememberedSet {
  public:
@@ -67,9 +69,7 @@
   // The callback should take (MemoryChunk* chunk) and return void.
   template <typename Callback>
   static void IterateMemoryChunks(Heap* heap, Callback callback) {
-    MemoryChunkIterator it(heap, direction == OLD_TO_OLD
-                                     ? MemoryChunkIterator::ALL
-                                     : MemoryChunkIterator::ALL_BUT_CODE_SPACE);
+    MemoryChunkIterator it(heap);
     MemoryChunk* chunk;
     while ((chunk = it.next()) != nullptr) {
       SlotSet* slots = GetSlotSet(chunk);
@@ -98,62 +98,58 @@
     }
   }
 
-  // Iterates and filters the remembered set with the given callback.
-  // The callback should take (HeapObject** slot, HeapObject* target) and
-  // update the slot.
-  // A special wrapper takes care of filtering the slots based on their values.
-  // For OLD_TO_NEW case: slots that do not point to the ToSpace after
-  // callback invocation will be removed from the set.
-  template <typename Callback>
-  static void IterateWithWrapper(Heap* heap, Callback callback) {
-    Iterate(heap, [heap, callback](Address addr) {
-      return Wrapper(heap, addr, callback);
-    });
-  }
-
-  template <typename Callback>
-  static void IterateWithWrapper(Heap* heap, MemoryChunk* chunk,
-                                 Callback callback) {
-    Iterate(chunk, [heap, callback](Address addr) {
-      return Wrapper(heap, addr, callback);
-    });
-  }
-
   // Given a page and a typed slot in that page, this function adds the slot
   // to the remembered set.
-  static void InsertTyped(Page* page, SlotType slot_type, Address slot_addr) {
-    STATIC_ASSERT(direction == OLD_TO_OLD);
-    TypedSlotSet* slot_set = page->typed_old_to_old_slots();
+  static void InsertTyped(Page* page, Address host_addr, SlotType slot_type,
+                          Address slot_addr) {
+    TypedSlotSet* slot_set = GetTypedSlotSet(page);
     if (slot_set == nullptr) {
-      page->AllocateTypedOldToOldSlots();
-      slot_set = page->typed_old_to_old_slots();
+      AllocateTypedSlotSet(page);
+      slot_set = GetTypedSlotSet(page);
+    }
+    if (host_addr == nullptr) {
+      host_addr = page->address();
     }
     uintptr_t offset = slot_addr - page->address();
+    uintptr_t host_offset = host_addr - page->address();
     DCHECK_LT(offset, static_cast<uintptr_t>(TypedSlotSet::kMaxOffset));
-    slot_set->Insert(slot_type, static_cast<uint32_t>(offset));
+    DCHECK_LT(host_offset, static_cast<uintptr_t>(TypedSlotSet::kMaxOffset));
+    slot_set->Insert(slot_type, static_cast<uint32_t>(host_offset),
+                     static_cast<uint32_t>(offset));
   }
 
   // Given a page and a range of typed slots in that page, this function removes
   // the slots from the remembered set.
   static void RemoveRangeTyped(Page* page, Address start, Address end) {
-    TypedSlotSet* slots = page->typed_old_to_old_slots();
+    TypedSlotSet* slots = GetTypedSlotSet(page);
     if (slots != nullptr) {
-      slots->Iterate([start, end](SlotType slot_type, Address slot_addr) {
+      slots->Iterate([start, end](SlotType slot_type, Address host_addr,
+                                  Address slot_addr) {
         return start <= slot_addr && slot_addr < end ? REMOVE_SLOT : KEEP_SLOT;
       });
     }
   }
 
+  // Iterates and filters the remembered set with the given callback.
+  // The callback should take (SlotType slot_type, SlotAddress slot) and return
+  // SlotCallbackResult.
+  template <typename Callback>
+  static void IterateTyped(Heap* heap, Callback callback) {
+    IterateMemoryChunks(heap, [callback](MemoryChunk* chunk) {
+      IterateTyped(chunk, callback);
+    });
+  }
+
   // Iterates and filters typed old to old pointers in the given memory chunk
   // with the given callback. The callback should take (SlotType slot_type,
   // Address slot_addr) and return SlotCallbackResult.
   template <typename Callback>
   static void IterateTyped(MemoryChunk* chunk, Callback callback) {
-    TypedSlotSet* slots = chunk->typed_old_to_old_slots();
+    TypedSlotSet* slots = GetTypedSlotSet(chunk);
     if (slots != nullptr) {
       int new_count = slots->Iterate(callback);
       if (new_count == 0) {
-        chunk->ReleaseTypedOldToOldSlots();
+        ReleaseTypedSlotSet(chunk);
       }
     }
   }
@@ -161,7 +157,7 @@
   // Clear all old to old slots from the remembered set.
   static void ClearAll(Heap* heap) {
     STATIC_ASSERT(direction == OLD_TO_OLD);
-    MemoryChunkIterator it(heap, MemoryChunkIterator::ALL);
+    MemoryChunkIterator it(heap);
     MemoryChunk* chunk;
     while ((chunk = it.next()) != nullptr) {
       chunk->ReleaseOldToOldSlots();
@@ -190,7 +186,7 @@
     if (direction == OLD_TO_OLD) {
       return chunk->typed_old_to_old_slots();
     } else {
-      return nullptr;
+      return chunk->typed_old_to_new_slots();
     }
   }
 
@@ -202,6 +198,14 @@
     }
   }
 
+  static void ReleaseTypedSlotSet(MemoryChunk* chunk) {
+    if (direction == OLD_TO_OLD) {
+      chunk->ReleaseTypedOldToOldSlots();
+    } else {
+      chunk->ReleaseTypedOldToNewSlots();
+    }
+  }
+
   static SlotSet* AllocateSlotSet(MemoryChunk* chunk) {
     if (direction == OLD_TO_OLD) {
       chunk->AllocateOldToOldSlots();
@@ -212,33 +216,135 @@
     }
   }
 
-  template <typename Callback>
-  static SlotCallbackResult Wrapper(Heap* heap, Address slot_address,
-                                    Callback slot_callback) {
-    STATIC_ASSERT(direction == OLD_TO_NEW);
-    Object** slot = reinterpret_cast<Object**>(slot_address);
-    Object* object = *slot;
-    if (heap->InFromSpace(object)) {
-      HeapObject* heap_object = reinterpret_cast<HeapObject*>(object);
-      DCHECK(heap_object->IsHeapObject());
-      slot_callback(reinterpret_cast<HeapObject**>(slot), heap_object);
-      object = *slot;
-      // If the object was in from space before and is after executing the
-      // callback in to space, the object is still live.
-      // Unfortunately, we do not know about the slot. It could be in a
-      // just freed free space object.
-      if (heap->InToSpace(object)) {
-        return KEEP_SLOT;
-      }
+  static TypedSlotSet* AllocateTypedSlotSet(MemoryChunk* chunk) {
+    if (direction == OLD_TO_OLD) {
+      chunk->AllocateTypedOldToOldSlots();
+      return chunk->typed_old_to_old_slots();
     } else {
-      DCHECK(!heap->InNewSpace(object));
+      chunk->AllocateTypedOldToNewSlots();
+      return chunk->typed_old_to_new_slots();
     }
-    return REMOVE_SLOT;
   }
 
   static bool IsValidSlot(Heap* heap, MemoryChunk* chunk, Object** slot);
 };
 
+class UpdateTypedSlotHelper {
+ public:
+  // Updates a cell slot using an untyped slot callback.
+  // The callback accepts (Heap*, Object**) and returns SlotCallbackResult.
+  template <typename Callback>
+  static SlotCallbackResult UpdateCell(RelocInfo* rinfo, Callback callback) {
+    DCHECK(rinfo->rmode() == RelocInfo::CELL);
+    Object* cell = rinfo->target_cell();
+    Object* old_cell = cell;
+    SlotCallbackResult result = callback(&cell);
+    if (cell != old_cell) {
+      rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
+    }
+    return result;
+  }
+
+  // Updates a code entry slot using an untyped slot callback.
+  // The callback accepts (Heap*, Object**) and returns SlotCallbackResult.
+  template <typename Callback>
+  static SlotCallbackResult UpdateCodeEntry(Address entry_address,
+                                            Callback callback) {
+    Object* code = Code::GetObjectFromEntryAddress(entry_address);
+    Object* old_code = code;
+    SlotCallbackResult result = callback(&code);
+    if (code != old_code) {
+      Memory::Address_at(entry_address) =
+          reinterpret_cast<Code*>(code)->entry();
+    }
+    return result;
+  }
+
+  // Updates a code target slot using an untyped slot callback.
+  // The callback accepts (Heap*, Object**) and returns SlotCallbackResult.
+  template <typename Callback>
+  static SlotCallbackResult UpdateCodeTarget(RelocInfo* rinfo,
+                                             Callback callback) {
+    DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
+    Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
+    Object* old_target = target;
+    SlotCallbackResult result = callback(&target);
+    if (target != old_target) {
+      rinfo->set_target_address(Code::cast(target)->instruction_start());
+    }
+    return result;
+  }
+
+  // Updates an embedded pointer slot using an untyped slot callback.
+  // The callback accepts (Heap*, Object**) and returns SlotCallbackResult.
+  template <typename Callback>
+  static SlotCallbackResult UpdateEmbeddedPointer(RelocInfo* rinfo,
+                                                  Callback callback) {
+    DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
+    Object* target = rinfo->target_object();
+    Object* old_target = target;
+    SlotCallbackResult result = callback(&target);
+    if (target != old_target) {
+      rinfo->set_target_object(target);
+    }
+    return result;
+  }
+
+  // Updates a debug target slot using an untyped slot callback.
+  // The callback accepts (Heap*, Object**) and returns SlotCallbackResult.
+  template <typename Callback>
+  static SlotCallbackResult UpdateDebugTarget(RelocInfo* rinfo,
+                                              Callback callback) {
+    DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
+           rinfo->IsPatchedDebugBreakSlotSequence());
+    Object* target =
+        Code::GetCodeFromTargetAddress(rinfo->debug_call_address());
+    SlotCallbackResult result = callback(&target);
+    rinfo->set_debug_call_address(Code::cast(target)->instruction_start());
+    return result;
+  }
+
+  // Updates a typed slot using an untyped slot callback.
+  // The callback accepts (Heap*, Object**) and returns SlotCallbackResult.
+  template <typename Callback>
+  static SlotCallbackResult UpdateTypedSlot(Isolate* isolate,
+                                            SlotType slot_type, Address addr,
+                                            Callback callback) {
+    switch (slot_type) {
+      case CODE_TARGET_SLOT: {
+        RelocInfo rinfo(isolate, addr, RelocInfo::CODE_TARGET, 0, NULL);
+        return UpdateCodeTarget(&rinfo, callback);
+      }
+      case CELL_TARGET_SLOT: {
+        RelocInfo rinfo(isolate, addr, RelocInfo::CELL, 0, NULL);
+        return UpdateCell(&rinfo, callback);
+      }
+      case CODE_ENTRY_SLOT: {
+        return UpdateCodeEntry(addr, callback);
+      }
+      case DEBUG_TARGET_SLOT: {
+        RelocInfo rinfo(isolate, addr, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION,
+                        0, NULL);
+        if (rinfo.IsPatchedDebugBreakSlotSequence()) {
+          return UpdateDebugTarget(&rinfo, callback);
+        }
+        return REMOVE_SLOT;
+      }
+      case EMBEDDED_OBJECT_SLOT: {
+        RelocInfo rinfo(isolate, addr, RelocInfo::EMBEDDED_OBJECT, 0, NULL);
+        return UpdateEmbeddedPointer(&rinfo, callback);
+      }
+      case OBJECT_SLOT: {
+        return callback(reinterpret_cast<Object**>(addr));
+      }
+      case NUMBER_OF_SLOT_TYPES:
+        break;
+    }
+    UNREACHABLE();
+    return REMOVE_SLOT;
+  }
+};
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/heap/scavenger-inl.h b/src/heap/scavenger-inl.h
index b8fd1c8..0b6a0f4 100644
--- a/src/heap/scavenger-inl.h
+++ b/src/heap/scavenger-inl.h
@@ -37,10 +37,35 @@
   return ScavengeObjectSlow(p, object);
 }
 
+SlotCallbackResult Scavenger::CheckAndScavengeObject(Heap* heap,
+                                                     Address slot_address) {
+  Object** slot = reinterpret_cast<Object**>(slot_address);
+  Object* object = *slot;
+  if (heap->InFromSpace(object)) {
+    HeapObject* heap_object = reinterpret_cast<HeapObject*>(object);
+    DCHECK(heap_object->IsHeapObject());
+
+    ScavengeObject(reinterpret_cast<HeapObject**>(slot), heap_object);
+
+    object = *slot;
+    // If the object was in from space before and is after executing the
+    // callback in to space, the object is still live.
+    // Unfortunately, we do not know about the slot. It could be in a
+    // just freed free space object.
+    if (heap->InToSpace(object)) {
+      return KEEP_SLOT;
+    }
+  } else {
+    DCHECK(!heap->InNewSpace(object));
+  }
+  return REMOVE_SLOT;
+}
 
 // static
-void StaticScavengeVisitor::VisitPointer(Heap* heap, HeapObject* obj,
-                                         Object** p) {
+template <PromotionMode promotion_mode>
+void StaticScavengeVisitor<promotion_mode>::VisitPointer(Heap* heap,
+                                                         HeapObject* obj,
+                                                         Object** p) {
   Object* object = *p;
   if (!heap->InNewSpace(object)) return;
   Scavenger::ScavengeObject(reinterpret_cast<HeapObject**>(p),
diff --git a/src/heap/scavenger.cc b/src/heap/scavenger.cc
index 3f532ea..9b8bfc2 100644
--- a/src/heap/scavenger.cc
+++ b/src/heap/scavenger.cc
@@ -10,7 +10,6 @@
 #include "src/heap/scavenger-inl.h"
 #include "src/isolate.h"
 #include "src/log.h"
-#include "src/profiler/cpu-profiler.h"
 
 namespace v8 {
 namespace internal {
@@ -23,8 +22,7 @@
 
 enum MarksHandling { TRANSFER_MARKS, IGNORE_MARKS };
 
-
-template <MarksHandling marks_handling,
+template <MarksHandling marks_handling, PromotionMode promotion_mode,
           LoggingAndProfiling logging_and_profiling_mode>
 class ScavengingVisitor : public StaticVisitorBase {
  public:
@@ -37,7 +35,8 @@
     table_.Register(kVisitFixedDoubleArray, &EvacuateFixedDoubleArray);
     table_.Register(kVisitFixedTypedArray, &EvacuateFixedTypedArray);
     table_.Register(kVisitFixedFloat64Array, &EvacuateFixedFloat64Array);
-    table_.Register(kVisitJSArrayBuffer, &EvacuateJSArrayBuffer);
+    table_.Register(kVisitJSArrayBuffer,
+                    &ObjectEvacuationStrategy<POINTER_OBJECT>::Visit);
 
     table_.Register(
         kVisitNativeContext,
@@ -78,6 +77,10 @@
     table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>,
                                    kVisitJSObject, kVisitJSObjectGeneric>();
 
+    table_
+        .RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>,
+                                 kVisitJSApiObject, kVisitJSApiObjectGeneric>();
+
     table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>,
                                    kVisitStruct, kVisitStructGeneric>();
   }
@@ -196,7 +199,6 @@
     return false;
   }
 
-
   template <ObjectContents object_contents, AllocationAlignment alignment>
   static inline void EvacuateObject(Map* map, HeapObject** slot,
                                     HeapObject* object, int object_size) {
@@ -204,7 +206,8 @@
     SLOW_DCHECK(object->Size() == object_size);
     Heap* heap = map->GetHeap();
 
-    if (!heap->ShouldBePromoted(object->address(), object_size)) {
+    if (!heap->ShouldBePromoted<promotion_mode>(object->address(),
+                                                object_size)) {
       // A semi-space copy may fail due to fragmentation. In that case, we
       // try to promote the object.
       if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) {
@@ -216,14 +219,15 @@
                                                   object_size)) {
       return;
     }
-
+    if (promotion_mode == PROMOTE_MARKED) {
+      FatalProcessOutOfMemory("Scavenger: promoting marked\n");
+    }
     // If promotion failed, we try to copy the object to the other semi-space
     if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) return;
 
     FatalProcessOutOfMemory("Scavenger: semi-space copy\n");
   }
 
-
   static inline void EvacuateJSFunction(Map* map, HeapObject** slot,
                                         HeapObject* object) {
     ObjectEvacuationStrategy<POINTER_OBJECT>::Visit(map, slot, object);
@@ -248,7 +252,6 @@
     }
   }
 
-
   static inline void EvacuateFixedArray(Map* map, HeapObject** slot,
                                         HeapObject* object) {
     int length = reinterpret_cast<FixedArray*>(object)->synchronized_length();
@@ -257,7 +260,6 @@
                                                  object_size);
   }
 
-
   static inline void EvacuateFixedDoubleArray(Map* map, HeapObject** slot,
                                               HeapObject* object) {
     int length = reinterpret_cast<FixedDoubleArray*>(object)->length();
@@ -265,7 +267,6 @@
     EvacuateObject<DATA_OBJECT, kDoubleAligned>(map, slot, object, object_size);
   }
 
-
   static inline void EvacuateFixedTypedArray(Map* map, HeapObject** slot,
                                              HeapObject* object) {
     int object_size = reinterpret_cast<FixedTypedArrayBase*>(object)->size();
@@ -273,7 +274,6 @@
                                                  object_size);
   }
 
-
   static inline void EvacuateFixedFloat64Array(Map* map, HeapObject** slot,
                                                HeapObject* object) {
     int object_size = reinterpret_cast<FixedFloat64Array*>(object)->size();
@@ -281,28 +281,12 @@
                                                    object_size);
   }
 
-
-  static inline void EvacuateJSArrayBuffer(Map* map, HeapObject** slot,
-                                           HeapObject* object) {
-    ObjectEvacuationStrategy<POINTER_OBJECT>::Visit(map, slot, object);
-
-    Heap* heap = map->GetHeap();
-    MapWord map_word = object->map_word();
-    DCHECK(map_word.IsForwardingAddress());
-    HeapObject* target = map_word.ToForwardingAddress();
-    if (!heap->InNewSpace(target)) {
-      heap->array_buffer_tracker()->Promote(JSArrayBuffer::cast(target));
-    }
-  }
-
-
   static inline void EvacuateByteArray(Map* map, HeapObject** slot,
                                        HeapObject* object) {
     int object_size = reinterpret_cast<ByteArray*>(object)->ByteArraySize();
     EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size);
   }
 
-
   static inline void EvacuateSeqOneByteString(Map* map, HeapObject** slot,
                                               HeapObject* object) {
     int object_size = SeqOneByteString::cast(object)
@@ -310,7 +294,6 @@
     EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size);
   }
 
-
   static inline void EvacuateSeqTwoByteString(Map* map, HeapObject** slot,
                                               HeapObject* object) {
     int object_size = SeqTwoByteString::cast(object)
@@ -318,7 +301,6 @@
     EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size);
   }
 
-
   static inline void EvacuateShortcutCandidate(Map* map, HeapObject** slot,
                                                HeapObject* object) {
     DCHECK(IsShortcutCandidate(map->instance_type()));
@@ -376,21 +358,21 @@
   static VisitorDispatchTable<ScavengingCallback> table_;
 };
 
-
-template <MarksHandling marks_handling,
+template <MarksHandling marks_handling, PromotionMode promotion_mode,
           LoggingAndProfiling logging_and_profiling_mode>
-VisitorDispatchTable<ScavengingCallback>
-    ScavengingVisitor<marks_handling, logging_and_profiling_mode>::table_;
-
+VisitorDispatchTable<ScavengingCallback> ScavengingVisitor<
+    marks_handling, promotion_mode, logging_and_profiling_mode>::table_;
 
 // static
 void Scavenger::Initialize() {
-  ScavengingVisitor<TRANSFER_MARKS,
+  ScavengingVisitor<TRANSFER_MARKS, PROMOTE_MARKED,
                     LOGGING_AND_PROFILING_DISABLED>::Initialize();
-  ScavengingVisitor<IGNORE_MARKS, LOGGING_AND_PROFILING_DISABLED>::Initialize();
-  ScavengingVisitor<TRANSFER_MARKS,
+  ScavengingVisitor<IGNORE_MARKS, DEFAULT_PROMOTION,
+                    LOGGING_AND_PROFILING_DISABLED>::Initialize();
+  ScavengingVisitor<TRANSFER_MARKS, PROMOTE_MARKED,
                     LOGGING_AND_PROFILING_ENABLED>::Initialize();
-  ScavengingVisitor<IGNORE_MARKS, LOGGING_AND_PROFILING_ENABLED>::Initialize();
+  ScavengingVisitor<IGNORE_MARKS, DEFAULT_PROMOTION,
+                    LOGGING_AND_PROFILING_ENABLED>::Initialize();
 }
 
 
@@ -408,28 +390,28 @@
 void Scavenger::SelectScavengingVisitorsTable() {
   bool logging_and_profiling =
       FLAG_verify_predictable || isolate()->logger()->is_logging() ||
-      isolate()->cpu_profiler()->is_profiling() ||
+      isolate()->is_profiling() ||
       (isolate()->heap_profiler() != NULL &&
        isolate()->heap_profiler()->is_tracking_object_moves());
 
   if (!heap()->incremental_marking()->IsMarking()) {
     if (!logging_and_profiling) {
       scavenging_visitors_table_.CopyFrom(
-          ScavengingVisitor<IGNORE_MARKS,
+          ScavengingVisitor<IGNORE_MARKS, DEFAULT_PROMOTION,
                             LOGGING_AND_PROFILING_DISABLED>::GetTable());
     } else {
       scavenging_visitors_table_.CopyFrom(
-          ScavengingVisitor<IGNORE_MARKS,
+          ScavengingVisitor<IGNORE_MARKS, DEFAULT_PROMOTION,
                             LOGGING_AND_PROFILING_ENABLED>::GetTable());
     }
   } else {
     if (!logging_and_profiling) {
       scavenging_visitors_table_.CopyFrom(
-          ScavengingVisitor<TRANSFER_MARKS,
+          ScavengingVisitor<TRANSFER_MARKS, PROMOTE_MARKED,
                             LOGGING_AND_PROFILING_DISABLED>::GetTable());
     } else {
       scavenging_visitors_table_.CopyFrom(
-          ScavengingVisitor<TRANSFER_MARKS,
+          ScavengingVisitor<TRANSFER_MARKS, PROMOTE_MARKED,
                             LOGGING_AND_PROFILING_ENABLED>::GetTable());
     }
 
@@ -462,6 +444,9 @@
 void ScavengeVisitor::ScavengePointer(Object** p) {
   Object* object = *p;
   if (!heap_->InNewSpace(object)) return;
+
+  if (heap_->PurgeLeftTrimmedObject(p)) return;
+
   Scavenger::ScavengeObject(reinterpret_cast<HeapObject**>(p),
                             reinterpret_cast<HeapObject*>(object));
 }
diff --git a/src/heap/scavenger.h b/src/heap/scavenger.h
index 5d0abf4..f2213b8 100644
--- a/src/heap/scavenger.h
+++ b/src/heap/scavenger.h
@@ -6,6 +6,7 @@
 #define V8_HEAP_SCAVENGER_H_
 
 #include "src/heap/objects-visiting.h"
+#include "src/heap/slot-set.h"
 
 namespace v8 {
 namespace internal {
@@ -25,6 +26,8 @@
   // ensure the precondition that the object is (a) a heap object and (b) in
   // the heap's from space.
   static inline void ScavengeObject(HeapObject** p, HeapObject* object);
+  static inline SlotCallbackResult CheckAndScavengeObject(Heap* heap,
+                                                          Address slot_address);
 
   // Slow part of {ScavengeObject} above.
   static void ScavengeObjectSlow(HeapObject** p, HeapObject* object);
@@ -60,8 +63,9 @@
 
 // Helper class for turning the scavenger into an object visitor that is also
 // filtering out non-HeapObjects and objects which do not reside in new space.
+template <PromotionMode promotion_mode>
 class StaticScavengeVisitor
-    : public StaticNewSpaceVisitor<StaticScavengeVisitor> {
+    : public StaticNewSpaceVisitor<StaticScavengeVisitor<promotion_mode>> {
  public:
   static inline void VisitPointer(Heap* heap, HeapObject* object, Object** p);
 };
diff --git a/src/heap/slot-set.h b/src/heap/slot-set.h
index e55ffe9..2fac50f 100644
--- a/src/heap/slot-set.h
+++ b/src/heap/slot-set.h
@@ -217,7 +217,6 @@
 enum SlotType {
   EMBEDDED_OBJECT_SLOT,
   OBJECT_SLOT,
-  RELOCATED_CODE_OBJECT,
   CELL_TARGET_SLOT,
   CODE_TARGET_SLOT,
   CODE_ENTRY_SLOT,
@@ -234,7 +233,30 @@
 // typed slots contain V8 internal pointers that are not directly exposed to JS.
 class TypedSlotSet {
  public:
-  typedef uint32_t TypedSlot;
+  struct TypedSlot {
+    TypedSlot() : type_and_offset_(0), host_offset_(0) {}
+
+    TypedSlot(SlotType type, uint32_t host_offset, uint32_t offset)
+        : type_and_offset_(TypeField::encode(type) |
+                           OffsetField::encode(offset)),
+          host_offset_(host_offset) {}
+
+    bool operator==(const TypedSlot other) {
+      return type_and_offset_ == other.type_and_offset_ &&
+             host_offset_ == other.host_offset_;
+    }
+
+    bool operator!=(const TypedSlot other) { return !(*this == other); }
+
+    SlotType type() { return TypeField::decode(type_and_offset_); }
+
+    uint32_t offset() { return OffsetField::decode(type_and_offset_); }
+
+    uint32_t host_offset() { return host_offset_; }
+
+    uint32_t type_and_offset_;
+    uint32_t host_offset_;
+  };
   static const int kMaxOffset = 1 << 29;
 
   explicit TypedSlotSet(Address page_start) : page_start_(page_start) {
@@ -251,8 +273,8 @@
   }
 
   // The slot offset specifies a slot at address page_start_ + offset.
-  void Insert(SlotType type, int offset) {
-    TypedSlot slot = ToTypedSlot(type, offset);
+  void Insert(SlotType type, uint32_t host_offset, uint32_t offset) {
+    TypedSlot slot(type, host_offset, offset);
     if (!chunk_->AddSlot(slot)) {
       chunk_ = new Chunk(chunk_, NextCapacity(chunk_->capacity));
       bool added = chunk_->AddSlot(slot);
@@ -273,7 +295,7 @@
   template <typename Callback>
   int Iterate(Callback callback) {
     STATIC_ASSERT(NUMBER_OF_SLOT_TYPES < 8);
-    const TypedSlot kRemovedSlot = TypeField::encode(NUMBER_OF_SLOT_TYPES);
+    const TypedSlot kRemovedSlot(NUMBER_OF_SLOT_TYPES, 0, 0);
     Chunk* chunk = chunk_;
     int new_count = 0;
     while (chunk != nullptr) {
@@ -282,9 +304,10 @@
       for (int i = 0; i < count; i++) {
         TypedSlot slot = buffer[i];
         if (slot != kRemovedSlot) {
-          SlotType type = TypeField::decode(slot);
-          Address addr = page_start_ + OffsetField::decode(slot);
-          if (callback(type, addr) == KEEP_SLOT) {
+          SlotType type = slot.type();
+          Address addr = page_start_ + slot.offset();
+          Address host_addr = page_start_ + slot.host_offset();
+          if (callback(type, host_addr, addr) == KEEP_SLOT) {
             new_count++;
           } else {
             buffer[i] = kRemovedSlot;
@@ -304,10 +327,6 @@
     return Min(kMaxBufferSize, capacity * 2);
   }
 
-  static TypedSlot ToTypedSlot(SlotType type, int offset) {
-    return TypeField::encode(type) | OffsetField::encode(offset);
-  }
-
   class OffsetField : public BitField<int, 0, 29> {};
   class TypeField : public BitField<SlotType, 29, 3> {};
 
diff --git a/src/heap/spaces-inl.h b/src/heap/spaces-inl.h
index 135498f..dbf3fff 100644
--- a/src/heap/spaces-inl.h
+++ b/src/heap/spaces-inl.h
@@ -15,6 +15,24 @@
 namespace v8 {
 namespace internal {
 
+template <class PAGE_TYPE>
+PageIteratorImpl<PAGE_TYPE>& PageIteratorImpl<PAGE_TYPE>::operator++() {
+  p_ = p_->next_page();
+  return *this;
+}
+
+template <class PAGE_TYPE>
+PageIteratorImpl<PAGE_TYPE> PageIteratorImpl<PAGE_TYPE>::operator++(int) {
+  PageIteratorImpl<PAGE_TYPE> tmp(*this);
+  operator++();
+  return tmp;
+}
+
+NewSpacePageRange::NewSpacePageRange(Address start, Address limit)
+    : range_(Page::FromAddress(start),
+             Page::FromAllocationAreaAddress(limit)->next_page()) {
+  SemiSpace::AssertValidRange(start, limit);
+}
 
 // -----------------------------------------------------------------------------
 // Bitmap
@@ -31,33 +49,14 @@
     bitmap->cells()[i] = 0xffffffff;
 }
 
-// -----------------------------------------------------------------------------
-// PageIterator
-
-PageIterator::PageIterator(PagedSpace* space)
-    : space_(space),
-      prev_page_(&space->anchor_),
-      next_page_(prev_page_->next_page()) {}
-
-
-bool PageIterator::has_next() { return next_page_ != &space_->anchor_; }
-
-
-Page* PageIterator::next() {
-  DCHECK(has_next());
-  prev_page_ = next_page_;
-  next_page_ = next_page_->next_page();
-  return prev_page_;
-}
-
 
 // -----------------------------------------------------------------------------
 // SemiSpaceIterator
 
 HeapObject* SemiSpaceIterator::Next() {
   while (current_ != limit_) {
-    if (NewSpacePage::IsAtEnd(current_)) {
-      NewSpacePage* page = NewSpacePage::FromLimit(current_);
+    if (Page::IsAlignedToPageSize(current_)) {
+      Page* page = Page::FromAllocationAreaAddress(current_);
       page = page->next_page();
       DCHECK(!page->is_anchor());
       current_ = page->area_start();
@@ -72,57 +71,17 @@
   return nullptr;
 }
 
-
-HeapObject* SemiSpaceIterator::next_object() { return Next(); }
-
-
-// -----------------------------------------------------------------------------
-// NewSpacePageIterator
-
-NewSpacePageIterator::NewSpacePageIterator(NewSpace* space)
-    : prev_page_(NewSpacePage::FromAddress(space->ToSpaceStart())->prev_page()),
-      next_page_(NewSpacePage::FromAddress(space->ToSpaceStart())),
-      last_page_(NewSpacePage::FromLimit(space->ToSpaceEnd())) {}
-
-NewSpacePageIterator::NewSpacePageIterator(SemiSpace* space)
-    : prev_page_(space->anchor()),
-      next_page_(prev_page_->next_page()),
-      last_page_(prev_page_->prev_page()) {}
-
-NewSpacePageIterator::NewSpacePageIterator(Address start, Address limit)
-    : prev_page_(NewSpacePage::FromAddress(start)->prev_page()),
-      next_page_(NewSpacePage::FromAddress(start)),
-      last_page_(NewSpacePage::FromLimit(limit)) {
-  SemiSpace::AssertValidRange(start, limit);
-}
-
-
-bool NewSpacePageIterator::has_next() { return prev_page_ != last_page_; }
-
-
-NewSpacePage* NewSpacePageIterator::next() {
-  DCHECK(has_next());
-  prev_page_ = next_page_;
-  next_page_ = next_page_->next_page();
-  return prev_page_;
-}
-
-
 // -----------------------------------------------------------------------------
 // HeapObjectIterator
 
 HeapObject* HeapObjectIterator::Next() {
   do {
     HeapObject* next_obj = FromCurrentPage();
-    if (next_obj != NULL) return next_obj;
+    if (next_obj != nullptr) return next_obj;
   } while (AdvanceToNextPage());
-  return NULL;
+  return nullptr;
 }
 
-
-HeapObject* HeapObjectIterator::next_object() { return Next(); }
-
-
 HeapObject* HeapObjectIterator::FromCurrentPage() {
   while (cur_addr_ != cur_end_) {
     if (cur_addr_ == space_->top() && cur_addr_ != space_->limit()) {
@@ -130,15 +89,9 @@
       continue;
     }
     HeapObject* obj = HeapObject::FromAddress(cur_addr_);
-    int obj_size = obj->Size();
+    const int obj_size = obj->Size();
     cur_addr_ += obj_size;
-    DCHECK(cur_addr_ <= cur_end_);
-    // TODO(hpayer): Remove the debugging code.
-    if (cur_addr_ > cur_end_) {
-      space_->heap()->isolate()->PushStackTraceAndDie(0xaaaaaaaa, obj, NULL,
-                                                      obj_size);
-    }
-
+    DCHECK_LE(cur_addr_, cur_end_);
     if (!obj->IsFiller()) {
       if (obj->IsCode()) {
         DCHECK_EQ(space_, space_->heap()->code_space());
@@ -149,21 +102,7 @@
       return obj;
     }
   }
-  return NULL;
-}
-
-// -----------------------------------------------------------------------------
-// LargePageIterator
-
-LargePageIterator::LargePageIterator(LargeObjectSpace* space)
-    : next_page_(space->first_page()) {}
-
-LargePage* LargePageIterator::next() {
-  LargePage* result = next_page_;
-  if (next_page_ != nullptr) {
-    next_page_ = next_page_->next_page();
-  }
-  return result;
+  return nullptr;
 }
 
 // -----------------------------------------------------------------------------
@@ -210,9 +149,8 @@
 }
 
 bool SemiSpace::ContainsSlow(Address a) {
-  NewSpacePageIterator it(this);
-  while (it.has_next()) {
-    if (it.next() == MemoryChunk::FromAddress(a)) return true;
+  for (Page* p : *this) {
+    if (p == MemoryChunk::FromAddress(a)) return true;
   }
   return false;
 }
@@ -251,27 +189,27 @@
   return static_cast<AllocationSpace>(Smi::cast(object_)->value());
 }
 
-NewSpacePage* NewSpacePage::Initialize(Heap* heap, MemoryChunk* chunk,
-                                       Executability executable,
-                                       SemiSpace* owner) {
+Page* Page::Initialize(Heap* heap, MemoryChunk* chunk, Executability executable,
+                       SemiSpace* owner) {
   DCHECK_EQ(executable, Executability::NOT_EXECUTABLE);
   bool in_to_space = (owner->id() != kFromSpace);
   chunk->SetFlag(in_to_space ? MemoryChunk::IN_TO_SPACE
                              : MemoryChunk::IN_FROM_SPACE);
   DCHECK(!chunk->IsFlagSet(in_to_space ? MemoryChunk::IN_FROM_SPACE
                                        : MemoryChunk::IN_TO_SPACE));
-  NewSpacePage* page = static_cast<NewSpacePage*>(chunk);
+  Page* page = static_cast<Page*>(chunk);
   heap->incremental_marking()->SetNewSpacePageFlags(page);
+  page->AllocateLocalTracker();
   return page;
 }
 
 // --------------------------------------------------------------------------
 // PagedSpace
 
+template <Page::InitializationMode mode>
 Page* Page::Initialize(Heap* heap, MemoryChunk* chunk, Executability executable,
                        PagedSpace* owner) {
   Page* page = reinterpret_cast<Page*>(chunk);
-  page->mutex_ = new base::Mutex();
   DCHECK(page->area_size() <= kAllocatableMemory);
   DCHECK(chunk->owner() == owner);
 
@@ -280,11 +218,26 @@
 
   // Make sure that categories are initialized before freeing the area.
   page->InitializeFreeListCategories();
-  owner->Free(page->area_start(), page->area_size());
+  // In the case we do not free the memory, we effectively account for the whole
+  // page as allocated memory that cannot be used for further allocations.
+  if (mode == kFreeMemory) {
+    owner->Free(page->area_start(), page->area_size());
+  }
 
   return page;
 }
 
+Page* Page::ConvertNewToOld(Page* old_page, PagedSpace* new_owner) {
+  DCHECK(old_page->InNewSpace());
+  old_page->set_owner(new_owner);
+  old_page->SetFlags(0, ~0);
+  new_owner->AccountCommitted(old_page->size());
+  Page* new_page = Page::Initialize<kDoNotFreeMemory>(
+      old_page->heap(), old_page, NOT_EXECUTABLE, new_owner);
+  new_page->InsertAfter(new_owner->anchor()->prev_page());
+  return new_page;
+}
+
 void Page::InitializeFreeListCategories() {
   for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
     categories_[i].Initialize(static_cast<FreeListCategoryType>(i));
@@ -297,8 +250,8 @@
 
 void MemoryChunk::ResetLiveBytes() {
   if (FLAG_trace_live_bytes) {
-    PrintIsolate(heap()->isolate(), "live-bytes: reset page=%p %d->0\n", this,
-                 live_byte_count_);
+    PrintIsolate(heap()->isolate(), "live-bytes: reset page=%p %d->0\n",
+                 static_cast<void*>(this), live_byte_count_);
   }
   live_byte_count_ = 0;
 }
@@ -306,9 +259,9 @@
 void MemoryChunk::IncrementLiveBytes(int by) {
   if (IsFlagSet(BLACK_PAGE)) return;
   if (FLAG_trace_live_bytes) {
-    PrintIsolate(heap()->isolate(),
-                 "live-bytes: update page=%p delta=%d %d->%d\n", this, by,
-                 live_byte_count_, live_byte_count_ + by);
+    PrintIsolate(
+        heap()->isolate(), "live-bytes: update page=%p delta=%d %d->%d\n",
+        static_cast<void*>(this), by, live_byte_count_, live_byte_count_ + by);
   }
   live_byte_count_ += by;
   DCHECK_GE(live_byte_count_, 0);
@@ -325,14 +278,14 @@
 
 bool PagedSpace::Contains(Address addr) {
   Page* p = Page::FromAddress(addr);
-  if (!p->is_valid()) return false;
+  if (!Page::IsValid(p)) return false;
   return p->owner() == this;
 }
 
 bool PagedSpace::Contains(Object* o) {
   if (!o->IsHeapObject()) return false;
   Page* p = Page::FromAddress(HeapObject::cast(o)->address());
-  if (!p->is_valid()) return false;
+  if (!Page::IsValid(p)) return false;
   return p->owner() == this;
 }
 
@@ -368,6 +321,7 @@
 }
 
 void Page::MarkNeverAllocateForTesting() {
+  DCHECK(this->owner()->identity() != NEW_SPACE);
   DCHECK(!IsFlagSet(NEVER_ALLOCATE_ON_PAGE));
   SetFlag(NEVER_ALLOCATE_ON_PAGE);
   reinterpret_cast<PagedSpace*>(owner())->free_list()->EvictFreeListItems(this);
@@ -382,48 +336,42 @@
 }
 
 void Page::ClearEvacuationCandidate() {
-  DCHECK_NULL(old_to_old_slots_);
-  DCHECK_NULL(typed_old_to_old_slots_);
+  if (!IsFlagSet(COMPACTION_WAS_ABORTED)) {
+    DCHECK_NULL(old_to_old_slots_);
+    DCHECK_NULL(typed_old_to_old_slots_);
+  }
   ClearFlag(EVACUATION_CANDIDATE);
   InitializeFreeListCategories();
 }
 
-MemoryChunkIterator::MemoryChunkIterator(Heap* heap, Mode mode)
-    : state_(kOldSpaceState),
-      mode_(mode),
-      old_iterator_(heap->old_space()),
-      code_iterator_(heap->code_space()),
-      map_iterator_(heap->map_space()),
-      lo_iterator_(heap->lo_space()) {}
+MemoryChunkIterator::MemoryChunkIterator(Heap* heap)
+    : heap_(heap),
+      state_(kOldSpaceState),
+      old_iterator_(heap->old_space()->begin()),
+      code_iterator_(heap->code_space()->begin()),
+      map_iterator_(heap->map_space()->begin()),
+      lo_iterator_(heap->lo_space()->begin()) {}
 
 MemoryChunk* MemoryChunkIterator::next() {
   switch (state_) {
     case kOldSpaceState: {
-      if (old_iterator_.has_next()) {
-        return old_iterator_.next();
-      }
+      if (old_iterator_ != heap_->old_space()->end()) return *(old_iterator_++);
       state_ = kMapState;
       // Fall through.
     }
     case kMapState: {
-      if (mode_ != ALL_BUT_MAP_SPACE && map_iterator_.has_next()) {
-        return map_iterator_.next();
-      }
+      if (map_iterator_ != heap_->map_space()->end()) return *(map_iterator_++);
       state_ = kCodeState;
       // Fall through.
     }
     case kCodeState: {
-      if (mode_ != ALL_BUT_CODE_SPACE && code_iterator_.has_next()) {
-        return code_iterator_.next();
-      }
+      if (code_iterator_ != heap_->code_space()->end())
+        return *(code_iterator_++);
       state_ = kLargeObjectState;
       // Fall through.
     }
     case kLargeObjectState: {
-      MemoryChunk* answer = lo_iterator_.next();
-      if (answer != nullptr) {
-        return answer;
-      }
+      if (lo_iterator_ != heap_->lo_space()->end()) return *(lo_iterator_++);
       state_ = kFinishedState;
       // Fall through;
     }
@@ -436,16 +384,6 @@
   return nullptr;
 }
 
-void Page::set_next_page(Page* page) {
-  DCHECK(page->owner() == owner());
-  set_next_chunk(page);
-}
-
-void Page::set_prev_page(Page* page) {
-  DCHECK(page->owner() == owner());
-  set_prev_chunk(page);
-}
-
 Page* FreeListCategory::page() {
   return Page::FromAddress(reinterpret_cast<Address>(this));
 }
@@ -668,15 +606,19 @@
   return AllocateRaw(size_in_bytes, alignment);
 }
 
-
-LargePage* LargePage::Initialize(Heap* heap, MemoryChunk* chunk) {
+LargePage* LargePage::Initialize(Heap* heap, MemoryChunk* chunk,
+                                 Executability executable, Space* owner) {
+  if (executable && chunk->size() > LargePage::kMaxCodePageSize) {
+    STATIC_ASSERT(LargePage::kMaxCodePageSize <= TypedSlotSet::kMaxOffset);
+    FATAL("Code page is too large.");
+  }
   heap->incremental_marking()->SetOldSpacePageFlags(chunk);
   return static_cast<LargePage*>(chunk);
 }
 
 
 intptr_t LargeObjectSpace::Available() {
-  return ObjectSizeFor(heap()->isolate()->memory_allocator()->Available());
+  return ObjectSizeFor(heap()->memory_allocator()->Available());
 }
 
 
diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc
index a0a3752..1dcd044 100644
--- a/src/heap/spaces.cc
+++ b/src/heap/spaces.cc
@@ -4,13 +4,18 @@
 
 #include "src/heap/spaces.h"
 
+#include <utility>
+
 #include "src/base/bits.h"
 #include "src/base/platform/platform.h"
+#include "src/base/platform/semaphore.h"
 #include "src/full-codegen/full-codegen.h"
+#include "src/heap/array-buffer-tracker.h"
 #include "src/heap/slot-set.h"
 #include "src/macro-assembler.h"
 #include "src/msan.h"
 #include "src/snapshot/snapshot.h"
+#include "src/v8.h"
 
 namespace v8 {
 namespace internal {
@@ -19,51 +24,37 @@
 // ----------------------------------------------------------------------------
 // HeapObjectIterator
 
-HeapObjectIterator::HeapObjectIterator(PagedSpace* space) {
-  // You can't actually iterate over the anchor page.  It is not a real page,
-  // just an anchor for the double linked page list.  Initialize as if we have
-  // reached the end of the anchor page, then the first iteration will move on
-  // to the first page.
-  Initialize(space, NULL, NULL, kAllPagesInSpace);
-}
+HeapObjectIterator::HeapObjectIterator(PagedSpace* space)
+    : cur_addr_(nullptr),
+      cur_end_(nullptr),
+      space_(space),
+      page_range_(space->anchor()->next_page(), space->anchor()),
+      current_page_(page_range_.begin()) {}
 
-
-HeapObjectIterator::HeapObjectIterator(Page* page) {
+HeapObjectIterator::HeapObjectIterator(Page* page)
+    : cur_addr_(nullptr),
+      cur_end_(nullptr),
+      space_(reinterpret_cast<PagedSpace*>(page->owner())),
+      page_range_(page),
+      current_page_(page_range_.begin()) {
+#ifdef DEBUG
   Space* owner = page->owner();
   DCHECK(owner == page->heap()->old_space() ||
          owner == page->heap()->map_space() ||
          owner == page->heap()->code_space());
-  Initialize(reinterpret_cast<PagedSpace*>(owner), page->area_start(),
-             page->area_end(), kOnePageOnly);
-  DCHECK(page->SweepingDone());
+#endif  // DEBUG
 }
 
-
-void HeapObjectIterator::Initialize(PagedSpace* space, Address cur, Address end,
-                                    HeapObjectIterator::PageMode mode) {
-  space_ = space;
-  cur_addr_ = cur;
-  cur_end_ = end;
-  page_mode_ = mode;
-}
-
-
 // We have hit the end of the page and should advance to the next block of
 // objects.  This happens at the end of the page.
 bool HeapObjectIterator::AdvanceToNextPage() {
-  DCHECK(cur_addr_ == cur_end_);
-  if (page_mode_ == kOnePageOnly) return false;
-  Page* cur_page;
-  if (cur_addr_ == NULL) {
-    cur_page = space_->anchor();
-  } else {
-    cur_page = Page::FromAddress(cur_addr_ - 1);
-    DCHECK(cur_addr_ == cur_page->area_end());
-  }
-  cur_page = cur_page->next_page();
-  if (cur_page == space_->anchor()) return false;
-  cur_page->heap()->mark_compact_collector()->SweepOrWaitUntilSweepingCompleted(
-      cur_page);
+  DCHECK_EQ(cur_addr_, cur_end_);
+  if (current_page_ == page_range_.end()) return false;
+  Page* cur_page = *(current_page_++);
+  space_->heap()
+      ->mark_compact_collector()
+      ->sweeper()
+      .SweepOrWaitUntilSweepingCompleted(cur_page);
   cur_addr_ = cur_page->area_start();
   cur_end_ = cur_page->area_end();
   DCHECK(cur_page->SweepingDone());
@@ -115,15 +106,16 @@
     requested = kMinimumCodeRangeSize;
   }
 
+  const size_t reserved_area =
+      kReservedCodeRangePages * base::OS::CommitPageSize();
+  if (requested < (kMaximalCodeRangeSize - reserved_area))
+    requested += reserved_area;
+
   DCHECK(!kRequiresCodeRange || requested <= kMaximalCodeRangeSize);
-#ifdef V8_TARGET_ARCH_MIPS64
-  // To use pseudo-relative jumps such as j/jal instructions which have 28-bit
-  // encoded immediate, the addresses have to be in range of 256Mb aligned
-  // region.
-  code_range_ = new base::VirtualMemory(requested, kMaximalCodeRangeSize);
-#else
-  code_range_ = new base::VirtualMemory(requested);
-#endif
+
+  code_range_ = new base::VirtualMemory(
+      requested, Max(kCodeRangeAreaAlignment,
+                     static_cast<size_t>(base::OS::AllocateAlignment())));
   CHECK(code_range_ != NULL);
   if (!code_range_->IsReserved()) {
     delete code_range_;
@@ -137,18 +129,16 @@
 
   // On some platforms, specifically Win64, we need to reserve some pages at
   // the beginning of an executable space.
-  if (kReservedCodeRangePages) {
-    if (!code_range_->Commit(
-            base, kReservedCodeRangePages * base::OS::CommitPageSize(), true)) {
+  if (reserved_area > 0) {
+    if (!code_range_->Commit(base, reserved_area, true)) {
       delete code_range_;
       code_range_ = NULL;
       return false;
     }
-    base += kReservedCodeRangePages * base::OS::CommitPageSize();
+    base += reserved_area;
   }
   Address aligned_base = RoundUp(base, MemoryChunk::kAlignment);
-  size_t size = code_range_->size() - (aligned_base - base) -
-                kReservedCodeRangePages * base::OS::CommitPageSize();
+  size_t size = code_range_->size() - (aligned_base - base) - reserved_area;
   allocation_list_.Add(FreeBlock(aligned_base, size));
   current_allocation_block_index_ = 0;
 
@@ -222,7 +212,7 @@
   *allocated = current.size;
   DCHECK(*allocated <= current.size);
   DCHECK(IsAddressAligned(current.start, MemoryChunk::kAlignment));
-  if (!isolate_->memory_allocator()->CommitExecutableMemory(
+  if (!isolate_->heap()->memory_allocator()->CommitExecutableMemory(
           code_range_, current.start, commit_size, *allocated)) {
     *allocated = 0;
     ReleaseBlock(&current);
@@ -233,7 +223,8 @@
 
 
 bool CodeRange::CommitRawMemory(Address start, size_t length) {
-  return isolate_->memory_allocator()->CommitMemory(start, length, EXECUTABLE);
+  return isolate_->heap()->memory_allocator()->CommitMemory(start, length,
+                                                            EXECUTABLE);
 }
 
 
@@ -294,15 +285,17 @@
 
 MemoryAllocator::MemoryAllocator(Isolate* isolate)
     : isolate_(isolate),
+      code_range_(nullptr),
       capacity_(0),
       capacity_executable_(0),
       size_(0),
       size_executable_(0),
       lowest_ever_allocated_(reinterpret_cast<void*>(-1)),
-      highest_ever_allocated_(reinterpret_cast<void*>(0)) {}
+      highest_ever_allocated_(reinterpret_cast<void*>(0)),
+      unmapper_(this) {}
 
-
-bool MemoryAllocator::SetUp(intptr_t capacity, intptr_t capacity_executable) {
+bool MemoryAllocator::SetUp(intptr_t capacity, intptr_t capacity_executable,
+                            intptr_t code_range_size) {
   capacity_ = RoundUp(capacity, Page::kPageSize);
   capacity_executable_ = RoundUp(capacity_executable, Page::kPageSize);
   DCHECK_GE(capacity_, capacity_executable_);
@@ -310,21 +303,103 @@
   size_ = 0;
   size_executable_ = 0;
 
+  code_range_ = new CodeRange(isolate_);
+  if (!code_range_->SetUp(static_cast<size_t>(code_range_size))) return false;
+
   return true;
 }
 
 
 void MemoryAllocator::TearDown() {
-  for (MemoryChunk* chunk : chunk_pool_) {
+  unmapper()->WaitUntilCompleted();
+
+  MemoryChunk* chunk = nullptr;
+  while ((chunk = unmapper()->TryGetPooledMemoryChunkSafe()) != nullptr) {
     FreeMemory(reinterpret_cast<Address>(chunk), MemoryChunk::kPageSize,
                NOT_EXECUTABLE);
   }
+
   // Check that spaces were torn down before MemoryAllocator.
   DCHECK_EQ(size_.Value(), 0);
   // TODO(gc) this will be true again when we fix FreeMemory.
   // DCHECK(size_executable_ == 0);
   capacity_ = 0;
   capacity_executable_ = 0;
+
+  if (last_chunk_.IsReserved()) {
+    last_chunk_.Release();
+  }
+
+  delete code_range_;
+  code_range_ = nullptr;
+}
+
+class MemoryAllocator::Unmapper::UnmapFreeMemoryTask : public v8::Task {
+ public:
+  explicit UnmapFreeMemoryTask(Unmapper* unmapper) : unmapper_(unmapper) {}
+
+ private:
+  // v8::Task overrides.
+  void Run() override {
+    unmapper_->PerformFreeMemoryOnQueuedChunks();
+    unmapper_->pending_unmapping_tasks_semaphore_.Signal();
+  }
+
+  Unmapper* unmapper_;
+  DISALLOW_COPY_AND_ASSIGN(UnmapFreeMemoryTask);
+};
+
+void MemoryAllocator::Unmapper::FreeQueuedChunks() {
+  ReconsiderDelayedChunks();
+  if (FLAG_concurrent_sweeping) {
+    V8::GetCurrentPlatform()->CallOnBackgroundThread(
+        new UnmapFreeMemoryTask(this), v8::Platform::kShortRunningTask);
+    concurrent_unmapping_tasks_active_++;
+  } else {
+    PerformFreeMemoryOnQueuedChunks();
+  }
+}
+
+bool MemoryAllocator::Unmapper::WaitUntilCompleted() {
+  bool waited = false;
+  while (concurrent_unmapping_tasks_active_ > 0) {
+    pending_unmapping_tasks_semaphore_.Wait();
+    concurrent_unmapping_tasks_active_--;
+    waited = true;
+  }
+  return waited;
+}
+
+void MemoryAllocator::Unmapper::PerformFreeMemoryOnQueuedChunks() {
+  MemoryChunk* chunk = nullptr;
+  // Regular chunks.
+  while ((chunk = GetMemoryChunkSafe<kRegular>()) != nullptr) {
+    bool pooled = chunk->IsFlagSet(MemoryChunk::POOLED);
+    allocator_->PerformFreeMemory(chunk);
+    if (pooled) AddMemoryChunkSafe<kPooled>(chunk);
+  }
+  // Non-regular chunks.
+  while ((chunk = GetMemoryChunkSafe<kNonRegular>()) != nullptr) {
+    allocator_->PerformFreeMemory(chunk);
+  }
+}
+
+void MemoryAllocator::Unmapper::ReconsiderDelayedChunks() {
+  std::list<MemoryChunk*> delayed_chunks(std::move(delayed_regular_chunks_));
+  // Move constructed, so the permanent list should be empty.
+  DCHECK(delayed_regular_chunks_.empty());
+  for (auto it = delayed_chunks.begin(); it != delayed_chunks.end(); ++it) {
+    AddMemoryChunkSafe<kRegular>(*it);
+  }
+}
+
+bool MemoryAllocator::CanFreeMemoryChunk(MemoryChunk* chunk) {
+  MarkCompactCollector* mc = isolate_->heap()->mark_compact_collector();
+  // We cannot free memory chunks in new space while the sweeper is running
+  // since a sweeper thread might be stuck right before trying to lock the
+  // corresponding page.
+  return !chunk->InNewSpace() || (mc == nullptr) ||
+         mc->sweeper().IsSweepingCompleted();
 }
 
 bool MemoryAllocator::CommitMemory(Address base, size_t size,
@@ -342,11 +417,9 @@
                                  Executability executable) {
   // TODO(gc) make code_range part of memory allocator?
   // Code which is part of the code-range does not have its own VirtualMemory.
-  DCHECK(isolate_->code_range() == NULL ||
-         !isolate_->code_range()->contains(
-             static_cast<Address>(reservation->address())));
-  DCHECK(executable == NOT_EXECUTABLE || isolate_->code_range() == NULL ||
-         !isolate_->code_range()->valid() ||
+  DCHECK(code_range() == NULL ||
+         !code_range()->contains(static_cast<Address>(reservation->address())));
+  DCHECK(executable == NOT_EXECUTABLE || !code_range()->valid() ||
          reservation->size() <= Page::kPageSize);
 
   reservation->Release();
@@ -356,20 +429,18 @@
 void MemoryAllocator::FreeMemory(Address base, size_t size,
                                  Executability executable) {
   // TODO(gc) make code_range part of memory allocator?
-  if (isolate_->code_range() != NULL &&
-      isolate_->code_range()->contains(static_cast<Address>(base))) {
+  if (code_range() != NULL &&
+      code_range()->contains(static_cast<Address>(base))) {
     DCHECK(executable == EXECUTABLE);
-    isolate_->code_range()->FreeRawMemory(base, size);
+    code_range()->FreeRawMemory(base, size);
   } else {
-    DCHECK(executable == NOT_EXECUTABLE || isolate_->code_range() == NULL ||
-           !isolate_->code_range()->valid());
+    DCHECK(executable == NOT_EXECUTABLE || !code_range()->valid());
     bool result = base::VirtualMemory::ReleaseRegion(base, size);
     USE(result);
     DCHECK(result);
   }
 }
 
-
 Address MemoryAllocator::ReserveAlignedMemory(size_t size, size_t alignment,
                                               base::VirtualMemory* controller) {
   base::VirtualMemory reservation(size, alignment);
@@ -382,7 +453,6 @@
   return base;
 }
 
-
 Address MemoryAllocator::AllocateAlignedMemory(
     size_t reserve_size, size_t commit_size, size_t alignment,
     Executability executable, base::VirtualMemory* controller) {
@@ -415,20 +485,12 @@
   return base;
 }
 
-
-void Page::InitializeAsAnchor(PagedSpace* owner) {
-  set_owner(owner);
-  set_prev_page(this);
-  set_next_page(this);
-}
-
-void NewSpacePage::InitializeAsAnchor(SemiSpace* semi_space) {
-  set_owner(semi_space);
+void Page::InitializeAsAnchor(Space* space) {
+  set_owner(space);
   set_next_chunk(this);
   set_prev_chunk(this);
-  // Flags marks this invalid page as not being in new-space.
-  // All real new-space pages will be in new-space.
   SetFlags(0, ~0);
+  SetFlag(ANCHOR);
 }
 
 MemoryChunk* MemoryChunk::Initialize(Heap* heap, Address base, size_t size,
@@ -448,19 +510,21 @@
   chunk->InitializeReservedMemory();
   chunk->old_to_new_slots_ = nullptr;
   chunk->old_to_old_slots_ = nullptr;
+  chunk->typed_old_to_new_slots_ = nullptr;
   chunk->typed_old_to_old_slots_ = nullptr;
   chunk->skip_list_ = nullptr;
   chunk->write_barrier_counter_ = kWriteBarrierCounterGranularity;
   chunk->progress_bar_ = 0;
   chunk->high_water_mark_.SetValue(static_cast<intptr_t>(area_start - base));
   chunk->concurrent_sweeping_state().SetValue(kSweepingDone);
-  chunk->mutex_ = nullptr;
+  chunk->mutex_ = new base::Mutex();
   chunk->available_in_free_list_ = 0;
   chunk->wasted_memory_ = 0;
   chunk->ResetLiveBytes();
   Bitmap::Clear(chunk);
   chunk->set_next_chunk(nullptr);
   chunk->set_prev_chunk(nullptr);
+  chunk->local_tracker_ = nullptr;
 
   DCHECK(OFFSET_OF(MemoryChunk, flags_) == kFlagsOffset);
   DCHECK(OFFSET_OF(MemoryChunk, live_byte_count_) == kLiveBytesOffset);
@@ -496,19 +560,18 @@
     if (reservation_.IsReserved()) {
       Executability executable =
           IsFlagSet(IS_EXECUTABLE) ? EXECUTABLE : NOT_EXECUTABLE;
-      if (!heap()->isolate()->memory_allocator()->CommitMemory(start, length,
-                                                               executable)) {
+      if (!heap()->memory_allocator()->CommitMemory(start, length,
+                                                    executable)) {
         return false;
       }
     } else {
-      CodeRange* code_range = heap_->isolate()->code_range();
-      DCHECK(code_range != NULL && code_range->valid() &&
-             IsFlagSet(IS_EXECUTABLE));
+      CodeRange* code_range = heap_->memory_allocator()->code_range();
+      DCHECK(code_range->valid() && IsFlagSet(IS_EXECUTABLE));
       if (!code_range->CommitRawMemory(start, length)) return false;
     }
 
     if (Heap::ShouldZapGarbage()) {
-      heap_->isolate()->memory_allocator()->ZapBlock(start, length);
+      heap_->memory_allocator()->ZapBlock(start, length);
     }
   } else if (commit_size < committed_size) {
     DCHECK(commit_size > 0);
@@ -518,9 +581,8 @@
     if (reservation_.IsReserved()) {
       if (!reservation_.Uncommit(start, length)) return false;
     } else {
-      CodeRange* code_range = heap_->isolate()->code_range();
-      DCHECK(code_range != NULL && code_range->valid() &&
-             IsFlagSet(IS_EXECUTABLE));
+      CodeRange* code_range = heap_->memory_allocator()->code_range();
+      DCHECK(code_range->valid() && IsFlagSet(IS_EXECUTABLE));
       if (!code_range->UncommitRawMemory(start, length)) return false;
     }
   }
@@ -614,13 +676,12 @@
 #ifdef V8_TARGET_ARCH_MIPS64
     // Use code range only for large object space on mips64 to keep address
     // range within 256-MB memory region.
-    if (isolate_->code_range() != NULL && isolate_->code_range()->valid() &&
-        reserve_area_size > CodePageAreaSize()) {
+    if (code_range()->valid() && reserve_area_size > CodePageAreaSize()) {
 #else
-    if (isolate_->code_range() != NULL && isolate_->code_range()->valid()) {
+    if (code_range()->valid()) {
 #endif
-      base = isolate_->code_range()->AllocateRawMemory(chunk_size, commit_size,
-                                                       &chunk_size);
+      base =
+          code_range()->AllocateRawMemory(chunk_size, commit_size, &chunk_size);
       DCHECK(
           IsAligned(reinterpret_cast<intptr_t>(base), MemoryChunk::kAlignment));
       if (base == NULL) return NULL;
@@ -669,9 +730,22 @@
       static_cast<int>(chunk_size));
 
   LOG(isolate_, NewEvent("MemoryChunk", base, chunk_size));
-  if (owner != NULL) {
-    ObjectSpace space = static_cast<ObjectSpace>(1 << owner->identity());
-    PerformAllocationCallback(space, kAllocationActionAllocate, chunk_size);
+
+  // We cannot use the last chunk in the address space because we would
+  // overflow when comparing top and limit if this chunk is used for a
+  // linear allocation area.
+  if ((reinterpret_cast<uintptr_t>(base) + chunk_size) == 0u) {
+    CHECK(!last_chunk_.IsReserved());
+    last_chunk_.TakeControl(&reservation);
+    UncommitBlock(reinterpret_cast<Address>(last_chunk_.address()),
+                  last_chunk_.size());
+    size_.Increment(-static_cast<intptr_t>(chunk_size));
+    if (executable == EXECUTABLE) {
+      size_executable_.Increment(-static_cast<intptr_t>(chunk_size));
+    }
+    CHECK(last_chunk_.IsReserved());
+    return AllocateChunk(reserve_area_size, commit_area_size, executable,
+                         owner);
   }
 
   return MemoryChunk::Initialize(heap, base, chunk_size, area_start, area_end,
@@ -684,28 +758,9 @@
   available_in_free_list_ = 0;
 }
 
-LargePage* MemoryAllocator::AllocateLargePage(intptr_t object_size,
-                                              Space* owner,
-                                              Executability executable) {
-  MemoryChunk* chunk =
-      AllocateChunk(object_size, object_size, executable, owner);
-  if (chunk == NULL) return NULL;
-  if (executable && chunk->size() > LargePage::kMaxCodePageSize) {
-    STATIC_ASSERT(LargePage::kMaxCodePageSize <= TypedSlotSet::kMaxOffset);
-    FATAL("Code page is too large.");
-  }
-  return LargePage::Initialize(isolate_->heap(), chunk);
-}
-
-
 void MemoryAllocator::PreFreeMemory(MemoryChunk* chunk) {
   DCHECK(!chunk->IsFlagSet(MemoryChunk::PRE_FREED));
   LOG(isolate_, DeleteEvent("MemoryChunk", chunk));
-  if (chunk->owner() != NULL) {
-    ObjectSpace space =
-        static_cast<ObjectSpace>(1 << chunk->owner()->identity());
-    PerformAllocationCallback(space, kAllocationActionFree, chunk->size());
-  }
 
   isolate_->heap()->RememberUnmappedPage(reinterpret_cast<Address>(chunk),
                                          chunk->IsEvacuationCandidate());
@@ -735,36 +790,52 @@
   chunk->ReleaseAllocatedMemory();
 
   base::VirtualMemory* reservation = chunk->reserved_memory();
-  if (reservation->IsReserved()) {
-    FreeMemory(reservation, chunk->executable());
+  if (chunk->IsFlagSet(MemoryChunk::POOLED)) {
+    UncommitBlock(reinterpret_cast<Address>(chunk), MemoryChunk::kPageSize);
   } else {
-    FreeMemory(chunk->address(), chunk->size(), chunk->executable());
+    if (reservation->IsReserved()) {
+      FreeMemory(reservation, chunk->executable());
+    } else {
+      FreeMemory(chunk->address(), chunk->size(), chunk->executable());
+    }
   }
 }
 
-template <MemoryAllocator::AllocationMode mode>
+template <MemoryAllocator::FreeMode mode>
 void MemoryAllocator::Free(MemoryChunk* chunk) {
-  if (mode == kRegular) {
-    PreFreeMemory(chunk);
-    PerformFreeMemory(chunk);
-  } else {
-    DCHECK_EQ(mode, kPooled);
-    FreePooled(chunk);
+  switch (mode) {
+    case kFull:
+      PreFreeMemory(chunk);
+      PerformFreeMemory(chunk);
+      break;
+    case kPooledAndQueue:
+      DCHECK_EQ(chunk->size(), static_cast<size_t>(MemoryChunk::kPageSize));
+      DCHECK_EQ(chunk->executable(), NOT_EXECUTABLE);
+      chunk->SetFlag(MemoryChunk::POOLED);
+    // Fall through to kPreFreeAndQueue.
+    case kPreFreeAndQueue:
+      PreFreeMemory(chunk);
+      // The chunks added to this queue will be freed by a concurrent thread.
+      unmapper()->AddMemoryChunkSafe(chunk);
+      break;
+    default:
+      UNREACHABLE();
   }
 }
 
-template void MemoryAllocator::Free<MemoryAllocator::kRegular>(
+template void MemoryAllocator::Free<MemoryAllocator::kFull>(MemoryChunk* chunk);
+
+template void MemoryAllocator::Free<MemoryAllocator::kPreFreeAndQueue>(
     MemoryChunk* chunk);
 
-template void MemoryAllocator::Free<MemoryAllocator::kPooled>(
+template void MemoryAllocator::Free<MemoryAllocator::kPooledAndQueue>(
     MemoryChunk* chunk);
 
-template <typename PageType, MemoryAllocator::AllocationMode mode,
-          typename SpaceType>
-PageType* MemoryAllocator::AllocatePage(intptr_t size, SpaceType* owner,
-                                        Executability executable) {
+template <MemoryAllocator::AllocationMode alloc_mode, typename SpaceType>
+Page* MemoryAllocator::AllocatePage(intptr_t size, SpaceType* owner,
+                                    Executability executable) {
   MemoryChunk* chunk = nullptr;
-  if (mode == kPooled) {
+  if (alloc_mode == kPooled) {
     DCHECK_EQ(size, static_cast<intptr_t>(MemoryChunk::kAllocatableMemory));
     DCHECK_EQ(executable, NOT_EXECUTABLE);
     chunk = AllocatePagePooled(owner);
@@ -773,22 +844,32 @@
     chunk = AllocateChunk(size, size, executable, owner);
   }
   if (chunk == nullptr) return nullptr;
-  return PageType::Initialize(isolate_->heap(), chunk, executable, owner);
+  return Page::Initialize(isolate_->heap(), chunk, executable, owner);
 }
 
-template Page* MemoryAllocator::AllocatePage<Page, MemoryAllocator::kRegular,
-                                             PagedSpace>(intptr_t, PagedSpace*,
-                                                         Executability);
+template Page*
+MemoryAllocator::AllocatePage<MemoryAllocator::kRegular, PagedSpace>(
+    intptr_t size, PagedSpace* owner, Executability executable);
+template Page*
+MemoryAllocator::AllocatePage<MemoryAllocator::kRegular, SemiSpace>(
+    intptr_t size, SemiSpace* owner, Executability executable);
+template Page*
+MemoryAllocator::AllocatePage<MemoryAllocator::kPooled, SemiSpace>(
+    intptr_t size, SemiSpace* owner, Executability executable);
 
-template NewSpacePage* MemoryAllocator::AllocatePage<
-    NewSpacePage, MemoryAllocator::kPooled, SemiSpace>(intptr_t, SemiSpace*,
-                                                       Executability);
+LargePage* MemoryAllocator::AllocateLargePage(intptr_t size,
+                                              LargeObjectSpace* owner,
+                                              Executability executable) {
+  MemoryChunk* chunk = AllocateChunk(size, size, executable, owner);
+  if (chunk == nullptr) return nullptr;
+  return LargePage::Initialize(isolate_->heap(), chunk, executable, owner);
+}
 
 template <typename SpaceType>
 MemoryChunk* MemoryAllocator::AllocatePagePooled(SpaceType* owner) {
-  if (chunk_pool_.is_empty()) return nullptr;
+  MemoryChunk* chunk = unmapper()->TryGetPooledMemoryChunkSafe();
+  if (chunk == nullptr) return nullptr;
   const int size = MemoryChunk::kPageSize;
-  MemoryChunk* chunk = chunk_pool_.RemoveLast();
   const Address start = reinterpret_cast<Address>(chunk);
   const Address area_start = start + MemoryChunk::kObjectStartOffset;
   const Address area_end = start + size;
@@ -802,18 +883,6 @@
   return chunk;
 }
 
-void MemoryAllocator::FreePooled(MemoryChunk* chunk) {
-  DCHECK_EQ(chunk->size(), static_cast<size_t>(MemoryChunk::kPageSize));
-  DCHECK_EQ(chunk->executable(), NOT_EXECUTABLE);
-  chunk_pool_.Add(chunk);
-  intptr_t chunk_size = static_cast<intptr_t>(chunk->size());
-  if (chunk->executable() == EXECUTABLE) {
-    size_executable_.Increment(-chunk_size);
-  }
-  size_.Increment(-chunk_size);
-  UncommitBlock(reinterpret_cast<Address>(chunk), MemoryChunk::kPageSize);
-}
-
 bool MemoryAllocator::CommitBlock(Address start, size_t size,
                                   Executability executable) {
   if (!CommitMemory(start, size, executable)) return false;
@@ -840,60 +909,11 @@
   }
 }
 
-
-void MemoryAllocator::PerformAllocationCallback(ObjectSpace space,
-                                                AllocationAction action,
-                                                size_t size) {
-  for (int i = 0; i < memory_allocation_callbacks_.length(); ++i) {
-    MemoryAllocationCallbackRegistration registration =
-        memory_allocation_callbacks_[i];
-    if ((registration.space & space) == space &&
-        (registration.action & action) == action)
-      registration.callback(space, action, static_cast<int>(size));
-  }
-}
-
-
-bool MemoryAllocator::MemoryAllocationCallbackRegistered(
-    MemoryAllocationCallback callback) {
-  for (int i = 0; i < memory_allocation_callbacks_.length(); ++i) {
-    if (memory_allocation_callbacks_[i].callback == callback) return true;
-  }
-  return false;
-}
-
-
-void MemoryAllocator::AddMemoryAllocationCallback(
-    MemoryAllocationCallback callback, ObjectSpace space,
-    AllocationAction action) {
-  DCHECK(callback != NULL);
-  MemoryAllocationCallbackRegistration registration(callback, space, action);
-  DCHECK(!MemoryAllocator::MemoryAllocationCallbackRegistered(callback));
-  return memory_allocation_callbacks_.Add(registration);
-}
-
-
-void MemoryAllocator::RemoveMemoryAllocationCallback(
-    MemoryAllocationCallback callback) {
-  DCHECK(callback != NULL);
-  for (int i = 0; i < memory_allocation_callbacks_.length(); ++i) {
-    if (memory_allocation_callbacks_[i].callback == callback) {
-      memory_allocation_callbacks_.Remove(i);
-      return;
-    }
-  }
-  UNREACHABLE();
-}
-
-
 #ifdef DEBUG
 void MemoryAllocator::ReportStatistics() {
   intptr_t size = Size();
   float pct = static_cast<float>(capacity_ - size) / capacity_;
-  PrintF("  capacity: %" V8_PTR_PREFIX
-         "d"
-         ", used: %" V8_PTR_PREFIX
-         "d"
+  PrintF("  capacity: %" V8PRIdPTR ", used: %" V8PRIdPTR
          ", available: %%%d\n\n",
          capacity_, size, static_cast<int>(pct * 100));
 }
@@ -959,12 +979,19 @@
 // MemoryChunk implementation
 
 void MemoryChunk::ReleaseAllocatedMemory() {
-  delete skip_list_;
-  skip_list_ = nullptr;
-  delete mutex_;
-  mutex_ = nullptr;
-  ReleaseOldToNewSlots();
-  ReleaseOldToOldSlots();
+  if (skip_list_ != nullptr) {
+    delete skip_list_;
+    skip_list_ = nullptr;
+  }
+  if (mutex_ != nullptr) {
+    delete mutex_;
+    mutex_ = nullptr;
+  }
+  if (old_to_new_slots_ != nullptr) ReleaseOldToNewSlots();
+  if (old_to_old_slots_ != nullptr) ReleaseOldToOldSlots();
+  if (typed_old_to_new_slots_ != nullptr) ReleaseTypedOldToNewSlots();
+  if (typed_old_to_old_slots_ != nullptr) ReleaseTypedOldToOldSlots();
+  if (local_tracker_ != nullptr) ReleaseLocalTracker();
 }
 
 static SlotSet* AllocateSlotSet(size_t size, Address page_start) {
@@ -997,6 +1024,16 @@
   old_to_old_slots_ = nullptr;
 }
 
+void MemoryChunk::AllocateTypedOldToNewSlots() {
+  DCHECK(nullptr == typed_old_to_new_slots_);
+  typed_old_to_new_slots_ = new TypedSlotSet(address());
+}
+
+void MemoryChunk::ReleaseTypedOldToNewSlots() {
+  delete typed_old_to_new_slots_;
+  typed_old_to_new_slots_ = nullptr;
+}
+
 void MemoryChunk::AllocateTypedOldToOldSlots() {
   DCHECK(nullptr == typed_old_to_old_slots_);
   typed_old_to_old_slots_ = new TypedSlotSet(address());
@@ -1006,6 +1043,18 @@
   delete typed_old_to_old_slots_;
   typed_old_to_old_slots_ = nullptr;
 }
+
+void MemoryChunk::AllocateLocalTracker() {
+  DCHECK_NULL(local_tracker_);
+  local_tracker_ = new LocalArrayBufferTracker(heap());
+}
+
+void MemoryChunk::ReleaseLocalTracker() {
+  DCHECK_NOT_NULL(local_tracker_);
+  delete local_tracker_;
+  local_tracker_ = nullptr;
+}
+
 // -----------------------------------------------------------------------------
 // PagedSpace implementation
 
@@ -1029,13 +1078,11 @@
 
 PagedSpace::PagedSpace(Heap* heap, AllocationSpace space,
                        Executability executable)
-    : Space(heap, space, executable), free_list_(this) {
+    : Space(heap, space, executable), anchor_(this), free_list_(this) {
   area_size_ = MemoryAllocator::PageAreaSize(space);
   accounting_stats_.Clear();
 
   allocation_info_.Reset(nullptr, nullptr);
-
-  anchor_.InitializeAsAnchor(this);
 }
 
 
@@ -1046,9 +1093,10 @@
 
 
 void PagedSpace::TearDown() {
-  PageIterator iterator(this);
-  while (iterator.has_next()) {
-    heap()->isolate()->memory_allocator()->Free(iterator.next());
+  for (auto it = begin(); it != end();) {
+    Page* page = *(it++);  // Will be erased.
+    ArrayBufferTracker::FreeAll(page);
+    heap()->memory_allocator()->Free<MemoryAllocator::kFull>(page);
   }
   anchor_.set_next_page(&anchor_);
   anchor_.set_prev_page(&anchor_);
@@ -1063,17 +1111,14 @@
     return;
   }
   MarkCompactCollector* collector = heap()->mark_compact_collector();
-  List<Page*>* swept_pages = collector->swept_pages(identity());
   intptr_t added = 0;
   {
-    base::LockGuard<base::Mutex> guard(collector->swept_pages_mutex());
-    for (int i = swept_pages->length() - 1; i >= 0; --i) {
-      Page* p = (*swept_pages)[i];
+    Page* p = nullptr;
+    while ((p = collector->sweeper().GetSweptPageSafe(this)) != nullptr) {
       // Only during compaction pages can actually change ownership. This is
       // safe because there exists no other competing action on the page links
       // during compaction.
       if (is_local() && (p->owner() != this)) {
-        if (added > kCompactionMemoryWanted) break;
         base::LockGuard<base::Mutex> guard(
             reinterpret_cast<PagedSpace*>(p->owner())->mutex());
         p->Unlink();
@@ -1082,7 +1127,7 @@
       }
       added += RelinkFreeListCategories(p);
       added += p->wasted_memory();
-      swept_pages->Remove(i);
+      if (is_local() && (added > kCompactionMemoryWanted)) break;
     }
   }
   accounting_stats_.IncreaseCapacity(added);
@@ -1107,10 +1152,8 @@
   AccountCommitted(other->CommittedMemory());
 
   // Move over pages.
-  PageIterator it(other);
-  Page* p = nullptr;
-  while (it.has_next()) {
-    p = it.next();
+  for (auto it = other->begin(); it != other->end();) {
+    Page* p = *(it++);
 
     // Relinking requires the category to be unlinked.
     other->UnlinkFreeListCategories(p);
@@ -1127,18 +1170,16 @@
   if (!base::VirtualMemory::HasLazyCommits()) return CommittedMemory();
   MemoryChunk::UpdateHighWaterMark(allocation_info_.top());
   size_t size = 0;
-  PageIterator it(this);
-  while (it.has_next()) {
-    size += it.next()->CommittedPhysicalMemory();
+  for (Page* page : *this) {
+    size += page->CommittedPhysicalMemory();
   }
   return size;
 }
 
 bool PagedSpace::ContainsSlow(Address addr) {
   Page* p = Page::FromAddress(addr);
-  PageIterator iterator(this);
-  while (iterator.has_next()) {
-    if (iterator.next() == p) return true;
+  for (Page* page : *this) {
+    if (page == p) return true;
   }
   return false;
 }
@@ -1162,31 +1203,16 @@
   return Smi::FromInt(0);
 }
 
-
-bool PagedSpace::CanExpand(size_t size) {
-  DCHECK(heap()->mark_compact_collector()->is_compacting() ||
-         Capacity() <= heap()->MaxOldGenerationSize());
-
-  // Are we going to exceed capacity for this space? At this point we can be
-  // way over the maximum size because of AlwaysAllocate scopes and large
-  // objects.
-  if (!heap()->CanExpandOldGeneration(static_cast<int>(size))) return false;
-
-  return true;
-}
-
-
 bool PagedSpace::Expand() {
-  intptr_t size = AreaSize();
+  int size = AreaSize();
   if (snapshotable() && !HasPages()) {
     size = Snapshot::SizeOfFirstPage(heap()->isolate(), identity());
   }
 
-  if (!CanExpand(size)) return false;
+  if (!heap()->CanExpandOldGeneration(size)) return false;
 
-  Page* p = heap()->isolate()->memory_allocator()->AllocatePage<Page>(
-      size, this, executable());
-  if (p == NULL) return false;
+  Page* p = heap()->memory_allocator()->AllocatePage(size, this, executable());
+  if (p == nullptr) return false;
 
   AccountCommitted(static_cast<intptr_t>(p->size()));
 
@@ -1200,7 +1226,8 @@
     Bitmap::SetAllBits(p);
     p->SetFlag(Page::BLACK_PAGE);
     if (FLAG_trace_incremental_marking) {
-      PrintIsolate(heap()->isolate(), "Added black page %p\n", p);
+      PrintIsolate(heap()->isolate(), "Added black page %p\n",
+                   static_cast<void*>(p));
     }
   }
 
@@ -1213,20 +1240,17 @@
 
 
 int PagedSpace::CountTotalPages() {
-  PageIterator it(this);
   int count = 0;
-  while (it.has_next()) {
-    it.next();
+  for (Page* page : *this) {
     count++;
+    USE(page);
   }
   return count;
 }
 
 
 void PagedSpace::ResetFreeListStatistics() {
-  PageIterator page_iterator(this);
-  while (page_iterator.has_next()) {
-    Page* page = page_iterator.next();
+  for (Page* page : *this) {
     page->ResetFreeListStatistics();
   }
 }
@@ -1244,7 +1268,7 @@
   free_list_.EvictFreeListItems(page);
   DCHECK(!free_list_.ContainsPageFreeListItems(page));
 
-  if (Page::FromAllocationTop(allocation_info_.top()) == page) {
+  if (Page::FromAllocationAreaAddress(allocation_info_.top()) == page) {
     allocation_info_.Reset(nullptr, nullptr);
   }
 
@@ -1255,7 +1279,7 @@
   }
 
   AccountUncommitted(static_cast<intptr_t>(page->size()));
-  heap()->QueueMemoryChunkForFree(page);
+  heap()->memory_allocator()->Free<MemoryAllocator::kPreFreeAndQueue>(page);
 
   DCHECK(Capacity() > 0);
   accounting_stats_.ShrinkSpace(AreaSize());
@@ -1269,11 +1293,9 @@
 void PagedSpace::Verify(ObjectVisitor* visitor) {
   bool allocation_pointer_found_in_space =
       (allocation_info_.top() == allocation_info_.limit());
-  PageIterator page_iterator(this);
-  while (page_iterator.has_next()) {
-    Page* page = page_iterator.next();
+  for (Page* page : *this) {
     CHECK(page->owner() == this);
-    if (page == Page::FromAllocationTop(allocation_info_.top())) {
+    if (page == Page::FromAllocationAreaAddress(allocation_info_.top())) {
       allocation_pointer_found_in_space = true;
     }
     CHECK(page->SweepingDone());
@@ -1358,7 +1380,6 @@
   from_space_.TearDown();
 }
 
-
 void NewSpace::Flip() { SemiSpace::Swap(&from_space_, &to_space_); }
 
 
@@ -1404,6 +1425,48 @@
   DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
 }
 
+bool NewSpace::Rebalance() {
+  CHECK(heap()->promotion_queue()->is_empty());
+  // Order here is important to make use of the page pool.
+  return to_space_.EnsureCurrentCapacity() &&
+         from_space_.EnsureCurrentCapacity();
+}
+
+bool SemiSpace::EnsureCurrentCapacity() {
+  if (is_committed()) {
+    const int expected_pages = current_capacity_ / Page::kPageSize;
+    int actual_pages = 0;
+    Page* current_page = anchor()->next_page();
+    while (current_page != anchor()) {
+      actual_pages++;
+      current_page = current_page->next_page();
+      if (actual_pages > expected_pages) {
+        Page* to_remove = current_page->prev_page();
+        // Make sure we don't overtake the actual top pointer.
+        CHECK_NE(to_remove, current_page_);
+        to_remove->Unlink();
+        heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>(
+            to_remove);
+      }
+    }
+    while (actual_pages < expected_pages) {
+      actual_pages++;
+      current_page =
+          heap()->memory_allocator()->AllocatePage<MemoryAllocator::kPooled>(
+              Page::kAllocatableMemory, this, executable());
+      if (current_page == nullptr) return false;
+      DCHECK_NOT_NULL(current_page);
+      current_page->InsertAfter(anchor());
+      Bitmap::Clear(current_page);
+      current_page->SetFlags(anchor()->prev_page()->GetFlags(),
+                             Page::kCopyAllFlags);
+      heap()->CreateFillerObjectAt(current_page->area_start(),
+                                   current_page->area_size(),
+                                   ClearRecordedSlots::kNo);
+    }
+  }
+  return true;
+}
 
 void LocalAllocationBuffer::Close() {
   if (IsValid()) {
@@ -1460,11 +1523,9 @@
   Address old_top = allocation_info_.top();
   to_space_.Reset();
   UpdateAllocationInfo();
-  pages_used_ = 0;
   // Clear all mark-bits in the to-space.
-  NewSpacePageIterator it(&to_space_);
-  while (it.has_next()) {
-    Bitmap::Clear(it.next());
+  for (Page* p : to_space_) {
+    Bitmap::Clear(p);
   }
   InlineAllocationStep(old_top, allocation_info_.top(), nullptr, 0);
 }
@@ -1492,21 +1553,20 @@
 
 bool NewSpace::AddFreshPage() {
   Address top = allocation_info_.top();
-  DCHECK(!NewSpacePage::IsAtStart(top));
+  DCHECK(!Page::IsAtObjectStart(top));
   if (!to_space_.AdvancePage()) {
     // No more pages left to advance.
     return false;
   }
 
   // Clear remainder of current page.
-  Address limit = NewSpacePage::FromLimit(top)->area_end();
+  Address limit = Page::FromAllocationAreaAddress(top)->area_end();
   if (heap()->gc_state() == Heap::SCAVENGE) {
     heap()->promotion_queue()->SetNewLimit(limit);
   }
 
   int remaining_in_page = static_cast<int>(limit - top);
   heap()->CreateFillerObjectAt(top, remaining_in_page, ClearRecordedSlots::kNo);
-  pages_used_++;
   UpdateAllocationInfo();
 
   return true;
@@ -1526,7 +1586,7 @@
   int filler_size = Heap::GetFillToAlign(old_top, alignment);
   int aligned_size_in_bytes = size_in_bytes + filler_size;
 
-  if (old_top + aligned_size_in_bytes >= high) {
+  if (old_top + aligned_size_in_bytes > high) {
     // Not enough room in the page, try to allocate a new one.
     if (!AddFreshPage()) {
       return false;
@@ -1537,10 +1597,9 @@
     old_top = allocation_info_.top();
     high = to_space_.page_high();
     filler_size = Heap::GetFillToAlign(old_top, alignment);
-    aligned_size_in_bytes = size_in_bytes + filler_size;
   }
 
-  DCHECK(old_top + aligned_size_in_bytes < high);
+  DCHECK(old_top + aligned_size_in_bytes <= high);
 
   if (allocation_info_.limit() < high) {
     // Either the limit has been lowered because linear allocation was disabled
@@ -1626,9 +1685,9 @@
   CHECK_EQ(current, to_space_.space_start());
 
   while (current != top()) {
-    if (!NewSpacePage::IsAtEnd(current)) {
+    if (!Page::IsAlignedToPageSize(current)) {
       // The allocation pointer should not be in the middle of an object.
-      CHECK(!NewSpacePage::FromLimit(current)->ContainsLimit(top()) ||
+      CHECK(!Page::FromAllocationAreaAddress(current)->ContainsLimit(top()) ||
             current < top());
 
       HeapObject* object = HeapObject::FromAddress(current);
@@ -1654,7 +1713,7 @@
       current += size;
     } else {
       // At end of page, switch to next page.
-      NewSpacePage* page = NewSpacePage::FromLimit(current)->next_page();
+      Page* page = Page::FromAllocationAreaAddress(current)->next_page();
       // Next page should be valid.
       CHECK(!page->is_anchor());
       current = page->area_start();
@@ -1683,22 +1742,24 @@
 
 void SemiSpace::TearDown() {
   // Properly uncommit memory to keep the allocator counters in sync.
-  if (is_committed()) Uncommit();
+  if (is_committed()) {
+    for (Page* p : *this) {
+      ArrayBufferTracker::FreeAll(p);
+    }
+    Uncommit();
+  }
   current_capacity_ = maximum_capacity_ = 0;
 }
 
 
 bool SemiSpace::Commit() {
   DCHECK(!is_committed());
-  NewSpacePage* current = anchor();
+  Page* current = anchor();
   const int num_pages = current_capacity_ / Page::kPageSize;
   for (int pages_added = 0; pages_added < num_pages; pages_added++) {
-    NewSpacePage* new_page =
-        heap()
-            ->isolate()
-            ->memory_allocator()
-            ->AllocatePage<NewSpacePage, MemoryAllocator::kPooled>(
-                NewSpacePage::kAllocatableMemory, this, executable());
+    Page* new_page =
+        heap()->memory_allocator()->AllocatePage<MemoryAllocator::kPooled>(
+            Page::kAllocatableMemory, this, executable());
     if (new_page == nullptr) {
       RewindPages(current, pages_added);
       return false;
@@ -1718,15 +1779,15 @@
 
 bool SemiSpace::Uncommit() {
   DCHECK(is_committed());
-  NewSpacePageIterator it(this);
-  while (it.has_next()) {
-    heap()->isolate()->memory_allocator()->Free<MemoryAllocator::kPooled>(
-        it.next());
+  for (auto it = begin(); it != end();) {
+    Page* p = *(it++);
+    heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>(p);
   }
   anchor()->set_next_page(anchor());
   anchor()->set_prev_page(anchor());
   AccountUncommitted(current_capacity_);
   committed_ = false;
+  heap()->memory_allocator()->unmapper()->FreeQueuedChunks();
   return true;
 }
 
@@ -1734,9 +1795,8 @@
 size_t SemiSpace::CommittedPhysicalMemory() {
   if (!is_committed()) return 0;
   size_t size = 0;
-  NewSpacePageIterator it(this);
-  while (it.has_next()) {
-    size += it.next()->CommittedPhysicalMemory();
+  for (Page* p : *this) {
+    size += p->CommittedPhysicalMemory();
   }
   return size;
 }
@@ -1746,21 +1806,18 @@
   if (!is_committed()) {
     if (!Commit()) return false;
   }
-  DCHECK_EQ(new_capacity & NewSpacePage::kPageAlignmentMask, 0);
+  DCHECK_EQ(new_capacity & Page::kPageAlignmentMask, 0);
   DCHECK_LE(new_capacity, maximum_capacity_);
   DCHECK_GT(new_capacity, current_capacity_);
   const int delta = new_capacity - current_capacity_;
   DCHECK(IsAligned(delta, base::OS::AllocateAlignment()));
-  int delta_pages = delta / NewSpacePage::kPageSize;
-  NewSpacePage* last_page = anchor()->prev_page();
+  const int delta_pages = delta / Page::kPageSize;
+  Page* last_page = anchor()->prev_page();
   DCHECK_NE(last_page, anchor());
   for (int pages_added = 0; pages_added < delta_pages; pages_added++) {
-    NewSpacePage* new_page =
-        heap()
-            ->isolate()
-            ->memory_allocator()
-            ->AllocatePage<NewSpacePage, MemoryAllocator::kPooled>(
-                NewSpacePage::kAllocatableMemory, this, executable());
+    Page* new_page =
+        heap()->memory_allocator()->AllocatePage<MemoryAllocator::kPooled>(
+            Page::kAllocatableMemory, this, executable());
     if (new_page == nullptr) {
       RewindPages(last_page, pages_added);
       return false;
@@ -1768,8 +1825,7 @@
     new_page->InsertAfter(last_page);
     Bitmap::Clear(new_page);
     // Duplicate the flags that was set on the old page.
-    new_page->SetFlags(last_page->GetFlags(),
-                       NewSpacePage::kCopyOnFlipFlagsMask);
+    new_page->SetFlags(last_page->GetFlags(), Page::kCopyOnFlipFlagsMask);
     last_page = new_page;
   }
   AccountCommitted(static_cast<intptr_t>(delta));
@@ -1777,9 +1833,9 @@
   return true;
 }
 
-void SemiSpace::RewindPages(NewSpacePage* start, int num_pages) {
-  NewSpacePage* new_last_page = nullptr;
-  NewSpacePage* last_page = start;
+void SemiSpace::RewindPages(Page* start, int num_pages) {
+  Page* new_last_page = nullptr;
+  Page* last_page = start;
   while (num_pages > 0) {
     DCHECK_NE(last_page, anchor());
     new_last_page = last_page->prev_page();
@@ -1791,25 +1847,26 @@
 }
 
 bool SemiSpace::ShrinkTo(int new_capacity) {
-  DCHECK_EQ(new_capacity & NewSpacePage::kPageAlignmentMask, 0);
+  DCHECK_EQ(new_capacity & Page::kPageAlignmentMask, 0);
   DCHECK_GE(new_capacity, minimum_capacity_);
   DCHECK_LT(new_capacity, current_capacity_);
   if (is_committed()) {
     const int delta = current_capacity_ - new_capacity;
     DCHECK(IsAligned(delta, base::OS::AllocateAlignment()));
-    int delta_pages = delta / NewSpacePage::kPageSize;
-    NewSpacePage* new_last_page;
-    NewSpacePage* last_page;
+    int delta_pages = delta / Page::kPageSize;
+    Page* new_last_page;
+    Page* last_page;
     while (delta_pages > 0) {
       last_page = anchor()->prev_page();
       new_last_page = last_page->prev_page();
       new_last_page->set_next_page(anchor());
       anchor()->set_prev_page(new_last_page);
-      heap()->isolate()->memory_allocator()->Free<MemoryAllocator::kPooled>(
+      heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>(
           last_page);
       delta_pages--;
     }
     AccountUncommitted(static_cast<intptr_t>(delta));
+    heap()->memory_allocator()->unmapper()->FreeQueuedChunks();
   }
   current_capacity_ = new_capacity;
   return true;
@@ -1817,13 +1874,10 @@
 
 void SemiSpace::FixPagesFlags(intptr_t flags, intptr_t mask) {
   anchor_.set_owner(this);
-  // Fixup back-pointers to anchor. Address of anchor changes when we swap.
   anchor_.prev_page()->set_next_page(&anchor_);
   anchor_.next_page()->set_prev_page(&anchor_);
 
-  NewSpacePageIterator it(this);
-  while (it.has_next()) {
-    NewSpacePage* page = it.next();
+  for (Page* page : *this) {
     page->set_owner(this);
     page->SetFlags(flags, mask);
     if (id_ == kToSpace) {
@@ -1844,8 +1898,22 @@
 void SemiSpace::Reset() {
   DCHECK_NE(anchor_.next_page(), &anchor_);
   current_page_ = anchor_.next_page();
+  pages_used_ = 0;
 }
 
+void SemiSpace::RemovePage(Page* page) {
+  if (current_page_ == page) {
+    current_page_ = page->prev_page();
+  }
+  page->Unlink();
+}
+
+void SemiSpace::PrependPage(Page* page) {
+  page->SetFlags(current_page()->GetFlags(), Page::kCopyAllFlags);
+  page->set_owner(this);
+  page->InsertAfter(anchor());
+  pages_used_++;
+}
 
 void SemiSpace::Swap(SemiSpace* from, SemiSpace* to) {
   // We won't be swapping semispaces without data in them.
@@ -1863,18 +1931,17 @@
   std::swap(from->anchor_, to->anchor_);
   std::swap(from->current_page_, to->current_page_);
 
-  to->FixPagesFlags(saved_to_space_flags, NewSpacePage::kCopyOnFlipFlagsMask);
+  to->FixPagesFlags(saved_to_space_flags, Page::kCopyOnFlipFlagsMask);
   from->FixPagesFlags(0, 0);
 }
 
 
 void SemiSpace::set_age_mark(Address mark) {
-  DCHECK_EQ(NewSpacePage::FromLimit(mark)->semi_space(), this);
+  DCHECK_EQ(Page::FromAllocationAreaAddress(mark)->owner(), this);
   age_mark_ = mark;
   // Mark all pages up to the one containing mark.
-  NewSpacePageIterator it(space_start(), mark);
-  while (it.has_next()) {
-    it.next()->SetFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK);
+  for (Page* p : NewSpacePageRange(space_start(), mark)) {
+    p->SetFlag(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK);
   }
 }
 
@@ -1886,10 +1953,10 @@
 #ifdef VERIFY_HEAP
 void SemiSpace::Verify() {
   bool is_from_space = (id_ == kFromSpace);
-  NewSpacePage* page = anchor_.next_page();
-  CHECK(anchor_.semi_space() == this);
+  Page* page = anchor_.next_page();
+  CHECK(anchor_.owner() == this);
   while (page != &anchor_) {
-    CHECK_EQ(page->semi_space(), this);
+    CHECK_EQ(page->owner(), this);
     CHECK(page->InNewSpace());
     CHECK(page->IsFlagSet(is_from_space ? MemoryChunk::IN_FROM_SPACE
                                         : MemoryChunk::IN_TO_SPACE));
@@ -1917,10 +1984,10 @@
 #ifdef DEBUG
 void SemiSpace::AssertValidRange(Address start, Address end) {
   // Addresses belong to same semi-space
-  NewSpacePage* page = NewSpacePage::FromLimit(start);
-  NewSpacePage* end_page = NewSpacePage::FromLimit(end);
-  SemiSpace* space = page->semi_space();
-  CHECK_EQ(space, end_page->semi_space());
+  Page* page = Page::FromAllocationAreaAddress(start);
+  Page* end_page = Page::FromAllocationAreaAddress(end);
+  SemiSpace* space = reinterpret_cast<SemiSpace*>(page->owner());
+  CHECK_EQ(space, end_page->owner());
   // Start address is before end address, either on same page,
   // or end address is on a later page in the linked list of
   // semi-space pages.
@@ -1950,7 +2017,6 @@
   limit_ = end;
 }
 
-
 #ifdef DEBUG
 // heap_histograms is shared, always clear it before using it.
 static void ClearHistograms(Isolate* isolate) {
@@ -1968,25 +2034,22 @@
 
 
 static void ClearCodeKindStatistics(int* code_kind_statistics) {
-  for (int i = 0; i < Code::NUMBER_OF_KINDS; i++) {
+  for (int i = 0; i < AbstractCode::NUMBER_OF_KINDS; i++) {
     code_kind_statistics[i] = 0;
   }
 }
-
-
 static void ReportCodeKindStatistics(int* code_kind_statistics) {
   PrintF("\n   Code kind histograms: \n");
-  for (int i = 0; i < Code::NUMBER_OF_KINDS; i++) {
+  for (int i = 0; i < AbstractCode::NUMBER_OF_KINDS; i++) {
     if (code_kind_statistics[i] > 0) {
       PrintF("     %-20s: %10d bytes\n",
-             Code::Kind2String(static_cast<Code::Kind>(i)),
+             AbstractCode::Kind2String(static_cast<AbstractCode::Kind>(i)),
              code_kind_statistics[i]);
     }
   }
   PrintF("\n");
 }
 
-
 static int CollectHistogramInfo(HeapObject* obj) {
   Isolate* isolate = obj->GetIsolate();
   InstanceType type = obj->map()->instance_type();
@@ -2087,9 +2150,7 @@
 #ifdef DEBUG
   if (FLAG_heap_stats) {
     float pct = static_cast<float>(Available()) / TotalCapacity();
-    PrintF("  capacity: %" V8_PTR_PREFIX
-           "d"
-           ", available: %" V8_PTR_PREFIX "d, %%%d\n",
+    PrintF("  capacity: %" V8PRIdPTR ", available: %" V8PRIdPTR ", %%%d\n",
            TotalCapacity(), Available(), static_cast<int>(pct * 100));
     PrintF("\n  Object Histogram:\n");
     for (int i = 0; i <= LAST_TYPE; i++) {
@@ -2382,7 +2443,6 @@
   int new_node_size = 0;
   FreeSpace* new_node = FindNodeFor(size_in_bytes, &new_node_size);
   if (new_node == nullptr) return nullptr;
-  owner_->AllocationStep(new_node->address(), size_in_bytes);
 
   int bytes_left = new_node_size - size_in_bytes;
   DCHECK(bytes_left >= 0);
@@ -2409,7 +2469,8 @@
     // Keep the linear allocation area empty if requested to do so, just
     // return area back to the free list instead.
     owner_->Free(new_node->address() + size_in_bytes, bytes_left);
-    DCHECK(owner_->top() == NULL && owner_->limit() == NULL);
+    owner_->SetTopAndLimit(new_node->address() + size_in_bytes,
+                           new_node->address() + size_in_bytes);
   } else if (bytes_left > kThreshold &&
              owner_->heap()->incremental_marking()->IsMarkingIncomplete() &&
              FLAG_incremental_marking) {
@@ -2421,13 +2482,16 @@
                  new_node_size - size_in_bytes - linear_size);
     owner_->SetTopAndLimit(new_node->address() + size_in_bytes,
                            new_node->address() + size_in_bytes + linear_size);
-  } else if (bytes_left > 0) {
+  } else {
+    DCHECK(bytes_left >= 0);
     // Normally we give the rest of the node to the allocator as its new
     // linear allocation area.
     owner_->SetTopAndLimit(new_node->address() + size_in_bytes,
                            new_node->address() + new_node_size);
   }
 
+  owner_->AllocationStep(new_node->address(), size_in_bytes);
+
   return new_node;
 }
 
@@ -2495,10 +2559,11 @@
 
 void FreeList::PrintCategories(FreeListCategoryType type) {
   FreeListCategoryIterator it(this, type);
-  PrintF("FreeList[%p, top=%p, %d] ", this, categories_[type], type);
+  PrintF("FreeList[%p, top=%p, %d] ", static_cast<void*>(this),
+         static_cast<void*>(categories_[type]), type);
   while (it.HasNext()) {
     FreeListCategory* current = it.Next();
-    PrintF("%p -> ", current);
+    PrintF("%p -> ", static_cast<void*>(current));
   }
   PrintF("null\n");
 }
@@ -2582,9 +2647,7 @@
   free_list_.RepairLists(heap());
   // Each page may have a small free space that is not tracked by a free list.
   // Update the maps for those free space objects.
-  PageIterator iterator(this);
-  while (iterator.has_next()) {
-    Page* page = iterator.next();
+  for (Page* page : *this) {
     int size = static_cast<int>(page->wasted_memory());
     if (size == 0) continue;
     Address address = page->OffsetToAddress(Page::kPageSize - size);
@@ -2596,7 +2659,7 @@
 void PagedSpace::EvictEvacuationCandidatesFromLinearAllocationArea() {
   if (allocation_info_.top() >= allocation_info_.limit()) return;
 
-  if (!Page::FromAllocationTop(allocation_info_.top())->CanAllocate()) {
+  if (!Page::FromAllocationAreaAddress(allocation_info_.top())->CanAllocate()) {
     // Create filler object to keep page iterable if it was iterable.
     int remaining =
         static_cast<int>(allocation_info_.limit() - allocation_info_.top());
@@ -2648,8 +2711,8 @@
     if (object != NULL) return object;
 
     // If sweeping is still in progress try to sweep pages on the main thread.
-    int max_freed = collector->SweepInParallel(heap()->paged_space(identity()),
-                                               size_in_bytes, kMaxPagesToSweep);
+    int max_freed = collector->sweeper().ParallelSweepSpace(
+        identity(), size_in_bytes, kMaxPagesToSweep);
     RefillFreeList();
     if (max_freed >= size_in_bytes) {
       object = free_list_.Allocate(size_in_bytes);
@@ -2681,12 +2744,15 @@
   return SweepAndRetryAllocation(size_in_bytes);
 }
 
-
 #ifdef DEBUG
 void PagedSpace::ReportCodeStatistics(Isolate* isolate) {
   CommentStatistic* comments_statistics =
       isolate->paged_space_comments_statistics();
   ReportCodeKindStatistics(isolate->code_kind_statistics());
+  PrintF("Code size including metadata    : %10d bytes\n",
+         isolate->code_and_metadata_size());
+  PrintF("Bytecode size including metadata: %10d bytes\n",
+         isolate->bytecode_and_metadata_size());
   PrintF(
       "Code comment statistics (\"   [ comment-txt   :    size/   "
       "count  (average)\"):\n");
@@ -2700,7 +2766,6 @@
   PrintF("\n");
 }
 
-
 void PagedSpace::ResetCodeStatistics(Isolate* isolate) {
   CommentStatistic* comments_statistics =
       isolate->paged_space_comments_statistics();
@@ -2776,50 +2841,35 @@
   EnterComment(isolate, comment_txt, flat_delta);
 }
 
-
-// Collects code size statistics:
-// - by code kind
-// - by code comment
-void PagedSpace::CollectCodeStatistics() {
-  Isolate* isolate = heap()->isolate();
-  HeapObjectIterator obj_it(this);
-  for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) {
-    if (obj->IsAbstractCode()) {
-      AbstractCode* code = AbstractCode::cast(obj);
-      isolate->code_kind_statistics()[code->kind()] += code->Size();
-    }
-    if (obj->IsCode()) {
-      // TODO(mythria): Also enable this for BytecodeArray when it supports
-      // RelocInformation.
-      Code* code = Code::cast(obj);
-      RelocIterator it(code);
-      int delta = 0;
-      const byte* prev_pc = code->instruction_start();
-      while (!it.done()) {
-        if (it.rinfo()->rmode() == RelocInfo::COMMENT) {
-          delta += static_cast<int>(it.rinfo()->pc() - prev_pc);
-          CollectCommentStatistics(isolate, &it);
-          prev_pc = it.rinfo()->pc();
-        }
-        it.next();
-      }
-
-      DCHECK(code->instruction_start() <= prev_pc &&
-             prev_pc <= code->instruction_end());
-      delta += static_cast<int>(code->instruction_end() - prev_pc);
-      EnterComment(isolate, "NoComment", delta);
-    }
+// Collects code comment statistics
+static void CollectCodeCommentStatistics(HeapObject* obj, Isolate* isolate) {
+  if (!obj->IsCode()) {
+    return;
   }
+  Code* code = Code::cast(obj);
+  RelocIterator it(code);
+  int delta = 0;
+  const byte* prev_pc = code->instruction_start();
+  while (!it.done()) {
+    if (it.rinfo()->rmode() == RelocInfo::COMMENT) {
+      delta += static_cast<int>(it.rinfo()->pc() - prev_pc);
+      CollectCommentStatistics(isolate, &it);
+      prev_pc = it.rinfo()->pc();
+    }
+    it.next();
+  }
+
+  DCHECK(code->instruction_start() <= prev_pc &&
+         prev_pc <= code->instruction_end());
+  delta += static_cast<int>(code->instruction_end() - prev_pc);
+  EnterComment(isolate, "NoComment", delta);
 }
 
 
 void PagedSpace::ReportStatistics() {
   int pct = static_cast<int>(Available() * 100 / Capacity());
-  PrintF("  capacity: %" V8_PTR_PREFIX
-         "d"
-         ", waste: %" V8_PTR_PREFIX
-         "d"
-         ", available: %" V8_PTR_PREFIX "d, %%%d\n",
+  PrintF("  capacity: %" V8PRIdPTR ", waste: %" V8PRIdPTR
+         ", available: %" V8PRIdPTR ", %%%d\n",
          Capacity(), Waste(), Available(), pct);
 
   if (heap()->mark_compact_collector()->sweeping_in_progress()) {
@@ -2833,6 +2883,44 @@
 }
 #endif
 
+static void RecordCodeSizeIncludingMetadata(AbstractCode* abstract_code,
+                                            Isolate* isolate) {
+  int size = abstract_code->SizeIncludingMetadata();
+  if (abstract_code->IsCode()) {
+    size += isolate->code_and_metadata_size();
+    isolate->set_code_and_metadata_size(size);
+  } else {
+    size += isolate->bytecode_and_metadata_size();
+    isolate->set_bytecode_and_metadata_size(size);
+  }
+}
+
+// Collects code size statistics:
+// - code and metadata size
+// - by code kind (only in debug mode)
+// - by code comment (only in debug mode)
+void PagedSpace::CollectCodeStatistics() {
+  Isolate* isolate = heap()->isolate();
+  HeapObjectIterator obj_it(this);
+  for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) {
+    if (obj->IsAbstractCode()) {
+      AbstractCode* code = AbstractCode::cast(obj);
+      RecordCodeSizeIncludingMetadata(code, isolate);
+#ifdef DEBUG
+      isolate->code_kind_statistics()[code->kind()] += code->Size();
+      CollectCodeCommentStatistics(obj, isolate);
+#endif
+    }
+  }
+}
+
+void PagedSpace::ResetCodeAndMetadataStatistics(Isolate* isolate) {
+  isolate->set_code_and_metadata_size(0);
+  isolate->set_bytecode_and_metadata_size(0);
+#ifdef DEBUG
+  ResetCodeStatistics(isolate);
+#endif
+}
 
 // -----------------------------------------------------------------------------
 // MapSpace implementation
@@ -2862,15 +2950,13 @@
 // -----------------------------------------------------------------------------
 // LargeObjectSpace
 
-
 LargeObjectSpace::LargeObjectSpace(Heap* heap, AllocationSpace id)
     : Space(heap, id, NOT_EXECUTABLE),  // Managed on a per-allocation basis
       first_page_(NULL),
       size_(0),
       page_count_(0),
       objects_size_(0),
-      chunk_map_(HashMap::PointersMatch, 1024) {}
-
+      chunk_map_(base::HashMap::PointersMatch, 1024) {}
 
 LargeObjectSpace::~LargeObjectSpace() {}
 
@@ -2890,11 +2976,7 @@
     LargePage* page = first_page_;
     first_page_ = first_page_->next_page();
     LOG(heap()->isolate(), DeleteEvent("LargeObjectChunk", page->address()));
-
-    ObjectSpace space = static_cast<ObjectSpace>(1 << identity());
-    heap()->isolate()->memory_allocator()->PerformAllocationCallback(
-        space, kAllocationActionFree, page->size());
-    heap()->isolate()->memory_allocator()->Free(page);
+    heap()->memory_allocator()->Free<MemoryAllocator::kFull>(page);
   }
   SetUp();
 }
@@ -2908,7 +2990,7 @@
     return AllocationResult::Retry(identity());
   }
 
-  LargePage* page = heap()->isolate()->memory_allocator()->AllocateLargePage(
+  LargePage* page = heap()->memory_allocator()->AllocateLargePage(
       object_size, this, executable);
   if (page == NULL) return AllocationResult::Retry(identity());
   DCHECK(page->area_size() >= object_size);
@@ -2925,7 +3007,7 @@
   uintptr_t base = reinterpret_cast<uintptr_t>(page) / MemoryChunk::kAlignment;
   uintptr_t limit = base + (page->size() - 1) / MemoryChunk::kAlignment;
   for (uintptr_t key = base; key <= limit; key++) {
-    HashMap::Entry* entry = chunk_map_.LookupOrInsert(
+    base::HashMap::Entry* entry = chunk_map_.LookupOrInsert(
         reinterpret_cast<void*>(key), static_cast<uint32_t>(key));
     DCHECK(entry != NULL);
     entry->value = page;
@@ -2949,14 +3031,10 @@
 
 
 size_t LargeObjectSpace::CommittedPhysicalMemory() {
-  if (!base::VirtualMemory::HasLazyCommits()) return CommittedMemory();
-  size_t size = 0;
-  LargePage* current = first_page_;
-  while (current != NULL) {
-    size += current->CommittedPhysicalMemory();
-    current = current->next_page();
-  }
-  return size;
+  // On a platform that provides lazy committing of memory, we over-account
+  // the actually committed memory. There is no easy way right now to support
+  // precise accounting of committed memory in large object space.
+  return CommittedMemory();
 }
 
 
@@ -2972,12 +3050,12 @@
 
 LargePage* LargeObjectSpace::FindPage(Address a) {
   uintptr_t key = reinterpret_cast<uintptr_t>(a) / MemoryChunk::kAlignment;
-  HashMap::Entry* e = chunk_map_.Lookup(reinterpret_cast<void*>(key),
-                                        static_cast<uint32_t>(key));
+  base::HashMap::Entry* e = chunk_map_.Lookup(reinterpret_cast<void*>(key),
+                                              static_cast<uint32_t>(key));
   if (e != NULL) {
     DCHECK(e->value != NULL);
     LargePage* page = reinterpret_cast<LargePage*>(e->value);
-    DCHECK(page->is_valid());
+    DCHECK(LargePage::IsValid(page));
     if (page->Contains(a)) {
       return page;
     }
@@ -3037,7 +3115,7 @@
                           static_cast<uint32_t>(key));
       }
 
-      heap()->QueueMemoryChunkForFree(page);
+      heap()->memory_allocator()->Free<MemoryAllocator::kPreFreeAndQueue>(page);
     }
   }
 }
@@ -3103,6 +3181,20 @@
 }
 #endif
 
+void LargeObjectSpace::CollectCodeStatistics() {
+  Isolate* isolate = heap()->isolate();
+  LargeObjectIterator obj_it(this);
+  for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) {
+    if (obj->IsAbstractCode()) {
+      AbstractCode* code = AbstractCode::cast(obj);
+      RecordCodeSizeIncludingMetadata(code, isolate);
+#ifdef DEBUG
+      isolate->code_kind_statistics()[code->kind()] += code->Size();
+      CollectCodeCommentStatistics(obj, isolate);
+#endif
+    }
+  }
+}
 
 #ifdef DEBUG
 void LargeObjectSpace::Print() {
@@ -3115,7 +3207,7 @@
 
 
 void LargeObjectSpace::ReportStatistics() {
-  PrintF("  size: %" V8_PTR_PREFIX "d\n", size_);
+  PrintF("  size: %" V8PRIdPTR "\n", size_);
   int num_objects = 0;
   ClearHistograms(heap()->isolate());
   LargeObjectIterator it(this);
@@ -3126,27 +3218,15 @@
 
   PrintF(
       "  number of objects %d, "
-      "size of objects %" V8_PTR_PREFIX "d\n",
+      "size of objects %" V8PRIdPTR "\n",
       num_objects, objects_size_);
   if (num_objects > 0) ReportHistogram(heap()->isolate(), false);
 }
 
 
-void LargeObjectSpace::CollectCodeStatistics() {
-  Isolate* isolate = heap()->isolate();
-  LargeObjectIterator obj_it(this);
-  for (HeapObject* obj = obj_it.Next(); obj != NULL; obj = obj_it.Next()) {
-    if (obj->IsAbstractCode()) {
-      AbstractCode* code = AbstractCode::cast(obj);
-      isolate->code_kind_statistics()[code->kind()] += code->Size();
-    }
-  }
-}
-
-
 void Page::Print() {
   // Make a best-effort to print the objects in the page.
-  PrintF("Page@%p in %s\n", this->address(),
+  PrintF("Page@%p in %s\n", static_cast<void*>(this->address()),
          AllocationSpaceName(this->owner()->identity()));
   printf(" --------------------------------------\n");
   HeapObjectIterator objects(this);
diff --git a/src/heap/spaces.h b/src/heap/spaces.h
index 93a81cc..04c89a8 100644
--- a/src/heap/spaces.h
+++ b/src/heap/spaces.h
@@ -5,13 +5,15 @@
 #ifndef V8_HEAP_SPACES_H_
 #define V8_HEAP_SPACES_H_
 
+#include <list>
+
 #include "src/allocation.h"
-#include "src/atomic-utils.h"
+#include "src/base/atomic-utils.h"
 #include "src/base/atomicops.h"
 #include "src/base/bits.h"
+#include "src/base/hashmap.h"
 #include "src/base/platform/mutex.h"
 #include "src/flags.h"
-#include "src/hashmap.h"
 #include "src/list.h"
 #include "src/objects.h"
 #include "src/utils.h"
@@ -25,9 +27,9 @@
 class CompactionSpaceCollection;
 class FreeList;
 class Isolate;
+class LocalArrayBufferTracker;
 class MemoryAllocator;
 class MemoryChunk;
-class NewSpacePage;
 class Page;
 class PagedSpace;
 class SemiSpace;
@@ -419,6 +421,14 @@
     // to grey transition is performed in the value.
     HAS_PROGRESS_BAR,
 
+    // |PAGE_NEW_OLD_PROMOTION|: A page tagged with this flag has been promoted
+    // from new to old space during evacuation.
+    PAGE_NEW_OLD_PROMOTION,
+
+    // |PAGE_NEW_NEW_PROMOTION|: A page tagged with this flag has been moved
+    // within the new space during evacuation.
+    PAGE_NEW_NEW_PROMOTION,
+
     // A black page has all mark bits set to 1 (black). A black page currently
     // cannot be iterated because it is not swept. Moreover live bytes are also
     // not updated.
@@ -437,10 +447,22 @@
     // still has to be performed.
     PRE_FREED,
 
+    // |POOLED|: When actually freeing this chunk, only uncommit and do not
+    // give up the reservation as we still reuse the chunk at some point.
+    POOLED,
+
     // |COMPACTION_WAS_ABORTED|: Indicates that the compaction in this page
     //   has been aborted and needs special handling by the sweeper.
     COMPACTION_WAS_ABORTED,
 
+    // |COMPACTION_WAS_ABORTED_FOR_TESTING|: During stress testing evacuation
+    // on pages is sometimes aborted. The flag is used to avoid repeatedly
+    // triggering on the same page.
+    COMPACTION_WAS_ABORTED_FOR_TESTING,
+
+    // |ANCHOR|: Flag is set if page is an anchor.
+    ANCHOR,
+
     // Last flag, keep at bottom.
     NUM_MEMORY_CHUNK_FLAGS
   };
@@ -497,6 +519,7 @@
   static const size_t kWriteBarrierCounterOffset =
       kOldToNewSlotsOffset + kPointerSize  // SlotSet* old_to_new_slots_;
       + kPointerSize                       // SlotSet* old_to_old_slots_;
+      + kPointerSize   // TypedSlotSet* typed_old_to_new_slots_;
       + kPointerSize   // TypedSlotSet* typed_old_to_old_slots_;
       + kPointerSize;  // SkipList* skip_list_;
 
@@ -510,7 +533,8 @@
       + kPointerSize      // AtomicValue next_chunk_
       + kPointerSize      // AtomicValue prev_chunk_
       // FreeListCategory categories_[kNumberOfCategories]
-      + FreeListCategory::kSize * kNumberOfCategories;
+      + FreeListCategory::kSize * kNumberOfCategories +
+      kPointerSize;  // LocalArrayBufferTracker* local_tracker_;
 
   // We add some more space to the computed header size to amount for missing
   // alignment requirements in our computation.
@@ -548,7 +572,7 @@
     if (mark == nullptr) return;
     // Need to subtract one from the mark because when a chunk is full the
     // top points to the next address after the chunk, which effectively belongs
-    // to another chunk. See the comment to Page::FromAllocationTop.
+    // to another chunk. See the comment to Page::FromTopOrLimit.
     MemoryChunk* chunk = MemoryChunk::FromAddress(mark - 1);
     intptr_t new_mark = static_cast<intptr_t>(mark - chunk->address());
     intptr_t old_mark = 0;
@@ -558,9 +582,9 @@
              !chunk->high_water_mark_.TrySetValue(old_mark, new_mark));
   }
 
-  Address address() { return reinterpret_cast<Address>(this); }
+  static bool IsValid(MemoryChunk* chunk) { return chunk != nullptr; }
 
-  bool is_valid() { return address() != NULL; }
+  Address address() { return reinterpret_cast<Address>(this); }
 
   base::Mutex* mutex() { return mutex_; }
 
@@ -574,7 +598,7 @@
     return addr >= area_start() && addr <= area_end();
   }
 
-  AtomicValue<ConcurrentSweepingState>& concurrent_sweeping_state() {
+  base::AtomicValue<ConcurrentSweepingState>& concurrent_sweeping_state() {
     return concurrent_sweeping_;
   }
 
@@ -613,16 +637,24 @@
 
   inline SlotSet* old_to_new_slots() { return old_to_new_slots_; }
   inline SlotSet* old_to_old_slots() { return old_to_old_slots_; }
+  inline TypedSlotSet* typed_old_to_new_slots() {
+    return typed_old_to_new_slots_;
+  }
   inline TypedSlotSet* typed_old_to_old_slots() {
     return typed_old_to_old_slots_;
   }
+  inline LocalArrayBufferTracker* local_tracker() { return local_tracker_; }
 
   void AllocateOldToNewSlots();
   void ReleaseOldToNewSlots();
   void AllocateOldToOldSlots();
   void ReleaseOldToOldSlots();
+  void AllocateTypedOldToNewSlots();
+  void ReleaseTypedOldToNewSlots();
   void AllocateTypedOldToOldSlots();
   void ReleaseTypedOldToOldSlots();
+  void AllocateLocalTracker();
+  void ReleaseLocalTracker();
 
   Address area_start() { return area_start_; }
   Address area_end() { return area_end_; }
@@ -633,6 +665,8 @@
   // Approximate amount of physical memory committed for this chunk.
   size_t CommittedPhysicalMemory() { return high_water_mark_.Value(); }
 
+  Address HighWaterMark() { return address() + high_water_mark_.Value(); }
+
   int progress_bar() {
     DCHECK(IsFlagSet(HAS_PROGRESS_BAR));
     return progress_bar_;
@@ -695,7 +729,8 @@
   }
 
   bool ShouldSkipEvacuationSlotRecording() {
-    return (flags_ & kSkipEvacuationSlotsRecordingMask) != 0;
+    return ((flags_ & kSkipEvacuationSlotsRecordingMask) != 0) &&
+           !IsFlagSet(COMPACTION_WAS_ABORTED);
   }
 
   Executability executable() {
@@ -780,6 +815,7 @@
   // is ceil(size() / kPageSize).
   SlotSet* old_to_new_slots_;
   SlotSet* old_to_old_slots_;
+  TypedSlotSet* typed_old_to_new_slots_;
   TypedSlotSet* typed_old_to_old_slots_;
 
   SkipList* skip_list_;
@@ -788,23 +824,25 @@
 
   // Assuming the initial allocation on a page is sequential,
   // count highest number of bytes ever allocated on the page.
-  AtomicValue<intptr_t> high_water_mark_;
+  base::AtomicValue<intptr_t> high_water_mark_;
 
   base::Mutex* mutex_;
 
-  AtomicValue<ConcurrentSweepingState> concurrent_sweeping_;
+  base::AtomicValue<ConcurrentSweepingState> concurrent_sweeping_;
 
   // PagedSpace free-list statistics.
-  AtomicNumber<intptr_t> available_in_free_list_;
-  AtomicNumber<intptr_t> wasted_memory_;
+  base::AtomicNumber<intptr_t> available_in_free_list_;
+  base::AtomicNumber<intptr_t> wasted_memory_;
 
   // next_chunk_ holds a pointer of type MemoryChunk
-  AtomicValue<MemoryChunk*> next_chunk_;
+  base::AtomicValue<MemoryChunk*> next_chunk_;
   // prev_chunk_ holds a pointer of type MemoryChunk
-  AtomicValue<MemoryChunk*> prev_chunk_;
+  base::AtomicValue<MemoryChunk*> prev_chunk_;
 
   FreeListCategory categories_[kNumberOfCategories];
 
+  LocalArrayBufferTracker* local_tracker_;
+
  private:
   void InitializeReservedMemory() { reservation_.Reset(); }
 
@@ -817,59 +855,15 @@
 //
 // The only way to get a page pointer is by calling factory methods:
 //   Page* p = Page::FromAddress(addr); or
-//   Page* p = Page::FromAllocationTop(top);
+//   Page* p = Page::FromTopOrLimit(top);
 class Page : public MemoryChunk {
  public:
-  // Returns the page containing a given address. The address ranges
-  // from [page_addr .. page_addr + kPageSize[
-  // This only works if the object is in fact in a page.  See also MemoryChunk::
-  // FromAddress() and FromAnyAddress().
-  INLINE(static Page* FromAddress(Address a)) {
-    return reinterpret_cast<Page*>(OffsetFrom(a) & ~kPageAlignmentMask);
-  }
+  static const intptr_t kCopyAllFlags = ~0;
 
-  // Only works for addresses in pointer spaces, not code space.
-  inline static Page* FromAnyPointerAddress(Heap* heap, Address addr);
-
-  // Returns the page containing an allocation top. Because an allocation
-  // top address can be the upper bound of the page, we need to subtract
-  // it with kPointerSize first. The address ranges from
-  // [page_addr + kObjectStartOffset .. page_addr + kPageSize].
-  INLINE(static Page* FromAllocationTop(Address top)) {
-    Page* p = FromAddress(top - kPointerSize);
-    return p;
-  }
-
-  // Returns the next page in the chain of pages owned by a space.
-  inline Page* next_page() {
-    DCHECK(next_chunk()->owner() == owner());
-    return static_cast<Page*>(next_chunk());
-  }
-  inline Page* prev_page() {
-    DCHECK(prev_chunk()->owner() == owner());
-    return static_cast<Page*>(prev_chunk());
-  }
-  inline void set_next_page(Page* page);
-  inline void set_prev_page(Page* page);
-
-  // Checks whether an address is page aligned.
-  static bool IsAlignedToPageSize(Address a) {
-    return 0 == (OffsetFrom(a) & kPageAlignmentMask);
-  }
-
-  // Returns the offset of a given address to this page.
-  INLINE(int Offset(Address a)) {
-    int offset = static_cast<int>(a - address());
-    return offset;
-  }
-
-  // Returns the address for a given offset to the this page.
-  Address OffsetToAddress(int offset) {
-    DCHECK_PAGE_OFFSET(offset);
-    return address() + offset;
-  }
-
-  // ---------------------------------------------------------------------
+  // Page flags copied from from-space to to-space when flipping semispaces.
+  static const intptr_t kCopyOnFlipFlagsMask =
+      (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) |
+      (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING);
 
   // Maximum object size that gets allocated into regular pages. Objects larger
   // than that size are allocated in large object space and are never moved in
@@ -880,12 +874,71 @@
   // short living objects >256K.
   static const int kMaxRegularHeapObjectSize = 600 * KB;
 
-  inline void ClearGCFields();
+  static inline Page* ConvertNewToOld(Page* old_page, PagedSpace* new_owner);
 
-  static inline Page* Initialize(Heap* heap, MemoryChunk* chunk,
-                                 Executability executable, PagedSpace* owner);
+  // Returns the page containing a given address. The address ranges
+  // from [page_addr .. page_addr + kPageSize[. This only works if the object
+  // is in fact in a page.
+  static Page* FromAddress(Address addr) {
+    return reinterpret_cast<Page*>(OffsetFrom(addr) & ~kPageAlignmentMask);
+  }
 
-  void InitializeAsAnchor(PagedSpace* owner);
+  // Returns the page containing the address provided. The address can
+  // potentially point righter after the page. To be also safe for tagged values
+  // we subtract a hole word. The valid address ranges from
+  // [page_addr + kObjectStartOffset .. page_addr + kPageSize + kPointerSize].
+  static Page* FromAllocationAreaAddress(Address address) {
+    return Page::FromAddress(address - kPointerSize);
+  }
+
+  // Checks if address1 and address2 are on the same new space page.
+  static bool OnSamePage(Address address1, Address address2) {
+    return Page::FromAddress(address1) == Page::FromAddress(address2);
+  }
+
+  // Checks whether an address is page aligned.
+  static bool IsAlignedToPageSize(Address addr) {
+    return (OffsetFrom(addr) & kPageAlignmentMask) == 0;
+  }
+
+  static bool IsAtObjectStart(Address addr) {
+    return (reinterpret_cast<intptr_t>(addr) & kPageAlignmentMask) ==
+           kObjectStartOffset;
+  }
+
+  inline static Page* FromAnyPointerAddress(Heap* heap, Address addr);
+
+  // Create a Page object that is only used as anchor for the doubly-linked
+  // list of real pages.
+  explicit Page(Space* owner) { InitializeAsAnchor(owner); }
+
+  inline void MarkNeverAllocateForTesting();
+  inline void MarkEvacuationCandidate();
+  inline void ClearEvacuationCandidate();
+
+  Page* next_page() { return static_cast<Page*>(next_chunk()); }
+  Page* prev_page() { return static_cast<Page*>(prev_chunk()); }
+  void set_next_page(Page* page) { set_next_chunk(page); }
+  void set_prev_page(Page* page) { set_prev_chunk(page); }
+
+  template <typename Callback>
+  inline void ForAllFreeListCategories(Callback callback) {
+    for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
+      callback(&categories_[i]);
+    }
+  }
+
+  // Returns the offset of a given address to this page.
+  inline int Offset(Address a) {
+    int offset = static_cast<int>(a - address());
+    return offset;
+  }
+
+  // Returns the address for a given offset to the this page.
+  Address OffsetToAddress(int offset) {
+    DCHECK_PAGE_OFFSET(offset);
+    return address() + offset;
+  }
 
   // WaitUntilSweepingCompleted only works when concurrent sweeping is in
   // progress. In particular, when we know that right before this call a
@@ -907,42 +960,39 @@
                             available_in_free_list());
   }
 
-  template <typename Callback>
-  inline void ForAllFreeListCategories(Callback callback) {
-    for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
-      callback(&categories_[i]);
-    }
-  }
-
   FreeListCategory* free_list_category(FreeListCategoryType type) {
     return &categories_[type];
   }
 
-#define FRAGMENTATION_STATS_ACCESSORS(type, name)        \
-  type name() { return name##_.Value(); }                \
-  void set_##name(type name) { name##_.SetValue(name); } \
-  void add_##name(type name) { name##_.Increment(name); }
+  bool is_anchor() { return IsFlagSet(Page::ANCHOR); }
 
-  FRAGMENTATION_STATS_ACCESSORS(intptr_t, wasted_memory)
-  FRAGMENTATION_STATS_ACCESSORS(intptr_t, available_in_free_list)
-
-#undef FRAGMENTATION_STATS_ACCESSORS
+  intptr_t wasted_memory() { return wasted_memory_.Value(); }
+  void add_wasted_memory(intptr_t waste) { wasted_memory_.Increment(waste); }
+  intptr_t available_in_free_list() { return available_in_free_list_.Value(); }
+  void add_available_in_free_list(intptr_t available) {
+    available_in_free_list_.Increment(available);
+  }
 
 #ifdef DEBUG
   void Print();
 #endif  // DEBUG
 
-  inline void MarkNeverAllocateForTesting();
-  inline void MarkEvacuationCandidate();
-  inline void ClearEvacuationCandidate();
-
  private:
+  enum InitializationMode { kFreeMemory, kDoNotFreeMemory };
+
+  template <InitializationMode mode = kFreeMemory>
+  static inline Page* Initialize(Heap* heap, MemoryChunk* chunk,
+                                 Executability executable, PagedSpace* owner);
+  static inline Page* Initialize(Heap* heap, MemoryChunk* chunk,
+                                 Executability executable, SemiSpace* owner);
+
   inline void InitializeFreeListCategories();
 
+  void InitializeAsAnchor(Space* owner);
+
   friend class MemoryAllocator;
 };
 
-
 class LargePage : public MemoryChunk {
  public:
   HeapObject* GetObject() { return HeapObject::FromAddress(area_start()); }
@@ -960,7 +1010,8 @@
   static const int kMaxCodePageSize = 512 * MB;
 
  private:
-  static inline LargePage* Initialize(Heap* heap, MemoryChunk* chunk);
+  static inline LargePage* Initialize(Heap* heap, MemoryChunk* chunk,
+                                      Executability executable, Space* owner);
 
   friend class MemoryAllocator;
 };
@@ -1036,11 +1087,6 @@
     }
   }
 
-#ifdef DEBUG
-  virtual void Print() = 0;
-#endif
-
- protected:
   void AccountCommitted(intptr_t bytes) {
     DCHECK_GE(bytes, 0);
     committed_ += bytes;
@@ -1055,6 +1101,11 @@
     DCHECK_GE(committed_, 0);
   }
 
+#ifdef DEBUG
+  virtual void Print() = 0;
+#endif
+
+ protected:
   v8::base::SmartPointer<List<AllocationObserver*>> allocation_observers_;
   bool allocation_observers_paused_;
 
@@ -1129,15 +1180,6 @@
   void FreeRawMemory(Address buf, size_t length);
 
  private:
-  // Frees the range of virtual memory, and frees the data structures used to
-  // manage it.
-  void TearDown();
-
-  Isolate* isolate_;
-
-  // The reserved range of virtual memory that all code objects are put in.
-  base::VirtualMemory* code_range_;
-  // Plain old data class, just a struct plus a constructor.
   class FreeBlock {
    public:
     FreeBlock() : start(0), size(0) {}
@@ -1156,6 +1198,26 @@
     size_t size;
   };
 
+  // Frees the range of virtual memory, and frees the data structures used to
+  // manage it.
+  void TearDown();
+
+  // Finds a block on the allocation list that contains at least the
+  // requested amount of memory.  If none is found, sorts and merges
+  // the existing free memory blocks, and searches again.
+  // If none can be found, returns false.
+  bool GetNextAllocationBlock(size_t requested);
+  // Compares the start addresses of two free blocks.
+  static int CompareFreeBlockAddress(const FreeBlock* left,
+                                     const FreeBlock* right);
+  bool ReserveBlock(const size_t requested_size, FreeBlock* block);
+  void ReleaseBlock(const FreeBlock* block);
+
+  Isolate* isolate_;
+
+  // The reserved range of virtual memory that all code objects are put in.
+  base::VirtualMemory* code_range_;
+
   // The global mutex guards free_list_ and allocation_list_ as GC threads may
   // access both lists concurrently to the main thread.
   base::Mutex code_range_mutex_;
@@ -1170,17 +1232,6 @@
   List<FreeBlock> allocation_list_;
   int current_allocation_block_index_;
 
-  // Finds a block on the allocation list that contains at least the
-  // requested amount of memory.  If none is found, sorts and merges
-  // the existing free memory blocks, and searches again.
-  // If none can be found, returns false.
-  bool GetNextAllocationBlock(size_t requested);
-  // Compares the start addresses of two free blocks.
-  static int CompareFreeBlockAddress(const FreeBlock* left,
-                                     const FreeBlock* right);
-  bool ReserveBlock(const size_t requested_size, FreeBlock* block);
-  void ReleaseBlock(const FreeBlock* block);
-
   DISALLOW_COPY_AND_ASSIGN(CodeRange);
 };
 
@@ -1242,47 +1293,127 @@
 // A space acquires chunks of memory from the operating system. The memory
 // allocator allocated and deallocates pages for the paged heap spaces and large
 // pages for large object space.
-//
-// Each space has to manage it's own pages.
-//
 class MemoryAllocator {
  public:
+  // Unmapper takes care of concurrently unmapping and uncommitting memory
+  // chunks.
+  class Unmapper {
+   public:
+    class UnmapFreeMemoryTask;
+
+    explicit Unmapper(MemoryAllocator* allocator)
+        : allocator_(allocator),
+          pending_unmapping_tasks_semaphore_(0),
+          concurrent_unmapping_tasks_active_(0) {}
+
+    void AddMemoryChunkSafe(MemoryChunk* chunk) {
+      if ((chunk->size() == Page::kPageSize) &&
+          (chunk->executable() != EXECUTABLE)) {
+        AddMemoryChunkSafe<kRegular>(chunk);
+      } else {
+        AddMemoryChunkSafe<kNonRegular>(chunk);
+      }
+    }
+
+    MemoryChunk* TryGetPooledMemoryChunkSafe() {
+      // Procedure:
+      // (1) Try to get a chunk that was declared as pooled and already has
+      // been uncommitted.
+      // (2) Try to steal any memory chunk of kPageSize that would've been
+      // unmapped.
+      MemoryChunk* chunk = GetMemoryChunkSafe<kPooled>();
+      if (chunk == nullptr) {
+        chunk = GetMemoryChunkSafe<kRegular>();
+        if (chunk != nullptr) {
+          // For stolen chunks we need to manually free any allocated memory.
+          chunk->ReleaseAllocatedMemory();
+        }
+      }
+      return chunk;
+    }
+
+    void FreeQueuedChunks();
+    bool WaitUntilCompleted();
+
+   private:
+    enum ChunkQueueType {
+      kRegular,     // Pages of kPageSize that do not live in a CodeRange and
+                    // can thus be used for stealing.
+      kNonRegular,  // Large chunks and executable chunks.
+      kPooled,      // Pooled chunks, already uncommited and ready for reuse.
+      kNumberOfChunkQueues,
+    };
+
+    template <ChunkQueueType type>
+    void AddMemoryChunkSafe(MemoryChunk* chunk) {
+      base::LockGuard<base::Mutex> guard(&mutex_);
+      if (type != kRegular || allocator_->CanFreeMemoryChunk(chunk)) {
+        chunks_[type].push_back(chunk);
+      } else {
+        DCHECK_EQ(type, kRegular);
+        delayed_regular_chunks_.push_back(chunk);
+      }
+    }
+
+    template <ChunkQueueType type>
+    MemoryChunk* GetMemoryChunkSafe() {
+      base::LockGuard<base::Mutex> guard(&mutex_);
+      if (chunks_[type].empty()) return nullptr;
+      MemoryChunk* chunk = chunks_[type].front();
+      chunks_[type].pop_front();
+      return chunk;
+    }
+
+    void ReconsiderDelayedChunks();
+    void PerformFreeMemoryOnQueuedChunks();
+
+    base::Mutex mutex_;
+    MemoryAllocator* allocator_;
+    std::list<MemoryChunk*> chunks_[kNumberOfChunkQueues];
+    // Delayed chunks cannot be processed in the current unmapping cycle because
+    // of dependencies such as an active sweeper.
+    // See MemoryAllocator::CanFreeMemoryChunk.
+    std::list<MemoryChunk*> delayed_regular_chunks_;
+    base::Semaphore pending_unmapping_tasks_semaphore_;
+    intptr_t concurrent_unmapping_tasks_active_;
+
+    friend class MemoryAllocator;
+  };
+
   enum AllocationMode {
     kRegular,
     kPooled,
   };
+  enum FreeMode {
+    kFull,
+    kPreFreeAndQueue,
+    kPooledAndQueue,
+  };
 
   explicit MemoryAllocator(Isolate* isolate);
 
   // Initializes its internal bookkeeping structures.
   // Max capacity of the total space and executable memory limit.
-  bool SetUp(intptr_t max_capacity, intptr_t capacity_executable);
+  bool SetUp(intptr_t max_capacity, intptr_t capacity_executable,
+             intptr_t code_range_size);
 
   void TearDown();
 
-  // Allocates either Page or NewSpacePage from the allocator. AllocationMode
-  // is used to indicate whether pooled allocation, which only works for
-  // MemoryChunk::kPageSize, should be tried first.
-  template <typename PageType, MemoryAllocator::AllocationMode mode = kRegular,
+  // Allocates a Page from the allocator. AllocationMode is used to indicate
+  // whether pooled allocation, which only works for MemoryChunk::kPageSize,
+  // should be tried first.
+  template <MemoryAllocator::AllocationMode alloc_mode = kRegular,
             typename SpaceType>
-  PageType* AllocatePage(intptr_t size, SpaceType* owner,
-                         Executability executable);
+  Page* AllocatePage(intptr_t size, SpaceType* owner, Executability executable);
 
-  LargePage* AllocateLargePage(intptr_t object_size, Space* owner,
+  LargePage* AllocateLargePage(intptr_t size, LargeObjectSpace* owner,
                                Executability executable);
 
-  // PreFree logically frees the object, i.e., it takes care of the size
-  // bookkeeping and calls the allocation callback.
-  void PreFreeMemory(MemoryChunk* chunk);
-
-  // FreeMemory can be called concurrently when PreFree was executed before.
-  void PerformFreeMemory(MemoryChunk* chunk);
-
-  // Free is a wrapper method. For kRegular AllocationMode it  calls PreFree and
-  // PerformFreeMemory together. For kPooled it will dispatch to pooled free.
-  template <MemoryAllocator::AllocationMode mode = kRegular>
+  template <MemoryAllocator::FreeMode mode = kFull>
   void Free(MemoryChunk* chunk);
 
+  bool CanFreeMemoryChunk(MemoryChunk* chunk);
+
   // Returns allocated spaces in bytes.
   intptr_t Size() { return size_.Value(); }
 
@@ -1353,16 +1484,6 @@
   // filling it up with a recognizable non-NULL bit pattern.
   void ZapBlock(Address start, size_t size);
 
-  void PerformAllocationCallback(ObjectSpace space, AllocationAction action,
-                                 size_t size);
-
-  void AddMemoryAllocationCallback(MemoryAllocationCallback callback,
-                                   ObjectSpace space, AllocationAction action);
-
-  void RemoveMemoryAllocationCallback(MemoryAllocationCallback callback);
-
-  bool MemoryAllocationCallbackRegistered(MemoryAllocationCallback callback);
-
   static int CodePageGuardStartOffset();
 
   static int CodePageGuardSize();
@@ -1385,47 +1506,43 @@
                                               Address start, size_t commit_size,
                                               size_t reserved_size);
 
+  CodeRange* code_range() { return code_range_; }
+  Unmapper* unmapper() { return &unmapper_; }
+
  private:
+  // PreFree logically frees the object, i.e., it takes care of the size
+  // bookkeeping and calls the allocation callback.
+  void PreFreeMemory(MemoryChunk* chunk);
+
+  // FreeMemory can be called concurrently when PreFree was executed before.
+  void PerformFreeMemory(MemoryChunk* chunk);
+
   // See AllocatePage for public interface. Note that currently we only support
   // pools for NOT_EXECUTABLE pages of size MemoryChunk::kPageSize.
   template <typename SpaceType>
   MemoryChunk* AllocatePagePooled(SpaceType* owner);
 
-  // Free that chunk into the pool.
-  void FreePooled(MemoryChunk* chunk);
-
   Isolate* isolate_;
 
+  CodeRange* code_range_;
+
   // Maximum space size in bytes.
   intptr_t capacity_;
   // Maximum subset of capacity_ that can be executable
   intptr_t capacity_executable_;
 
   // Allocated space size in bytes.
-  AtomicNumber<intptr_t> size_;
+  base::AtomicNumber<intptr_t> size_;
   // Allocated executable space size in bytes.
-  AtomicNumber<intptr_t> size_executable_;
+  base::AtomicNumber<intptr_t> size_executable_;
 
   // We keep the lowest and highest addresses allocated as a quick way
   // of determining that pointers are outside the heap. The estimate is
   // conservative, i.e. not all addrsses in 'allocated' space are allocated
   // to our heap. The range is [lowest, highest[, inclusive on the low end
   // and exclusive on the high end.
-  AtomicValue<void*> lowest_ever_allocated_;
-  AtomicValue<void*> highest_ever_allocated_;
-
-  struct MemoryAllocationCallbackRegistration {
-    MemoryAllocationCallbackRegistration(MemoryAllocationCallback callback,
-                                         ObjectSpace space,
-                                         AllocationAction action)
-        : callback(callback), space(space), action(action) {}
-    MemoryAllocationCallback callback;
-    ObjectSpace space;
-    AllocationAction action;
-  };
-
-  // A List of callback that are triggered when memory is allocated or free'd
-  List<MemoryAllocationCallbackRegistration> memory_allocation_callbacks_;
+  base::AtomicValue<void*> lowest_ever_allocated_;
+  base::AtomicValue<void*> highest_ever_allocated_;
 
   // Initializes pages in a chunk. Returns the first page address.
   // This function and GetChunkId() are provided for the mark-compact
@@ -1447,7 +1564,10 @@
     } while ((high > ptr) && !highest_ever_allocated_.TrySetValue(ptr, high));
   }
 
-  List<MemoryChunk*> chunk_pool_;
+  base::VirtualMemory last_chunk_;
+  Unmapper unmapper_;
+
+  friend class TestCodeRangeScope;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryAllocator);
 };
@@ -1464,10 +1584,44 @@
 class ObjectIterator : public Malloced {
  public:
   virtual ~ObjectIterator() {}
-
-  virtual HeapObject* next_object() = 0;
+  virtual HeapObject* Next() = 0;
 };
 
+template <class PAGE_TYPE>
+class PageIteratorImpl
+    : public std::iterator<std::forward_iterator_tag, PAGE_TYPE> {
+ public:
+  explicit PageIteratorImpl(PAGE_TYPE* p) : p_(p) {}
+  PageIteratorImpl(const PageIteratorImpl<PAGE_TYPE>& other) : p_(other.p_) {}
+  PAGE_TYPE* operator*() { return p_; }
+  bool operator==(const PageIteratorImpl<PAGE_TYPE>& rhs) {
+    return rhs.p_ == p_;
+  }
+  bool operator!=(const PageIteratorImpl<PAGE_TYPE>& rhs) {
+    return rhs.p_ != p_;
+  }
+  inline PageIteratorImpl<PAGE_TYPE>& operator++();
+  inline PageIteratorImpl<PAGE_TYPE> operator++(int);
+
+ private:
+  PAGE_TYPE* p_;
+};
+
+typedef PageIteratorImpl<Page> PageIterator;
+typedef PageIteratorImpl<LargePage> LargePageIterator;
+
+class PageRange {
+ public:
+  typedef PageIterator iterator;
+  PageRange(Page* begin, Page* end) : begin_(begin), end_(end) {}
+  explicit PageRange(Page* page) : PageRange(page, page->next_page()) {}
+  iterator begin() { return iterator(begin_); }
+  iterator end() { return iterator(end_); }
+
+ private:
+  Page* begin_;
+  Page* end_;
+};
 
 // -----------------------------------------------------------------------------
 // Heap object iterator in new/old/map spaces.
@@ -1486,18 +1640,10 @@
 
   // Advance to the next object, skipping free spaces and other fillers and
   // skipping the special garbage section of which there is one per space.
-  // Returns NULL when the iteration has ended.
-  inline HeapObject* Next();
-  inline HeapObject* next_object() override;
+  // Returns nullptr when the iteration has ended.
+  inline HeapObject* Next() override;
 
  private:
-  enum PageMode { kOnePageOnly, kAllPagesInSpace };
-
-  Address cur_addr_;              // Current iteration point.
-  Address cur_end_;               // End iteration point.
-  PagedSpace* space_;
-  PageMode page_mode_;
-
   // Fast (inlined) path of next().
   inline HeapObject* FromCurrentPage();
 
@@ -1505,28 +1651,11 @@
   // iteration has ended.
   bool AdvanceToNextPage();
 
-  // Initializes fields.
-  inline void Initialize(PagedSpace* owner, Address start, Address end,
-                         PageMode mode);
-};
-
-
-// -----------------------------------------------------------------------------
-// A PageIterator iterates the pages in a paged space.
-
-class PageIterator BASE_EMBEDDED {
- public:
-  explicit inline PageIterator(PagedSpace* space);
-
-  inline bool has_next();
-  inline Page* next();
-
- private:
+  Address cur_addr_;  // Current iteration point.
+  Address cur_end_;   // End iteration point.
   PagedSpace* space_;
-  Page* prev_page_;  // Previous page returned.
-  // Next page that will be returned.  Cached here so that we can use this
-  // iterator for operations that deallocate pages.
-  Page* next_page_;
+  PageRange page_range_;
+  PageRange::iterator current_page_;
 };
 
 
@@ -1572,7 +1701,8 @@
 
 #ifdef DEBUG
   bool VerifyPagedAllocation() {
-    return (Page::FromAllocationTop(top_) == Page::FromAllocationTop(limit_)) &&
+    return (Page::FromAllocationAreaAddress(top_) ==
+            Page::FromAllocationAreaAddress(limit_)) &&
            (top_ <= limit_);
   }
 #endif
@@ -1872,7 +2002,7 @@
   FreeListCategory* top(FreeListCategoryType type) { return categories_[type]; }
 
   PagedSpace* owner_;
-  AtomicNumber<intptr_t> wasted_bytes_;
+  base::AtomicNumber<intptr_t> wasted_bytes_;
   FreeListCategory* categories_[kNumberOfCategories];
 
   friend class FreeListCategory;
@@ -1977,8 +2107,21 @@
   AllocationInfo allocation_info_;
 };
 
+class NewSpacePageRange {
+ public:
+  typedef PageRange::iterator iterator;
+  inline NewSpacePageRange(Address start, Address limit);
+  iterator begin() { return range_.begin(); }
+  iterator end() { return range_.end(); }
+
+ private:
+  PageRange range_;
+};
+
 class PagedSpace : public Space {
  public:
+  typedef PageIterator iterator;
+
   static const intptr_t kCompactionMemoryWanted = 500 * KB;
 
   // Creates a space with an id.
@@ -2130,6 +2273,12 @@
   // The dummy page that anchors the linked list of pages.
   Page* anchor() { return &anchor_; }
 
+  // Collect code size related statistics
+  void CollectCodeStatistics();
+
+  // Reset code size related statistics
+  static void ResetCodeAndMetadataStatistics(Isolate* isolate);
+
 #ifdef VERIFY_HEAP
   // Verify integrity of this space.
   virtual void Verify(ObjectVisitor* visitor);
@@ -2147,17 +2296,10 @@
   void ReportStatistics();
 
   // Report code object related statistics
-  void CollectCodeStatistics();
   static void ReportCodeStatistics(Isolate* isolate);
   static void ResetCodeStatistics(Isolate* isolate);
 #endif
 
-  // This function tries to steal size_in_bytes memory from the sweeper threads
-  // free-lists. If it does not succeed stealing enough memory, it will wait
-  // for the sweeper threads to finish sweeping.
-  // It returns true when sweeping is completed and false otherwise.
-  bool EnsureSweeperProgress(intptr_t size_in_bytes);
-
   Page* FirstPage() { return anchor_.next_page(); }
   Page* LastPage() { return anchor_.prev_page(); }
 
@@ -2188,6 +2330,9 @@
   inline void UnlinkFreeListCategories(Page* page);
   inline intptr_t RelinkFreeListCategories(Page* page);
 
+  iterator begin() { return iterator(anchor_.next_page()); }
+  iterator end() { return iterator(&anchor_); }
+
  protected:
   // PagedSpaces that should be included in snapshots have different, i.e.,
   // smaller, initial pages.
@@ -2242,7 +2387,6 @@
 
   friend class IncrementalMarking;
   friend class MarkCompactCollector;
-  friend class PageIterator;
 
   // Used in cctest.
   friend class HeapTester;
@@ -2283,83 +2427,8 @@
   const char* name_;
 };
 
-
 enum SemiSpaceId { kFromSpace = 0, kToSpace = 1 };
 
-
-class NewSpacePage : public MemoryChunk {
- public:
-  static inline NewSpacePage* Initialize(Heap* heap, MemoryChunk* chunk,
-                                         Executability executable,
-                                         SemiSpace* owner);
-
-  static bool IsAtStart(Address addr) {
-    return (reinterpret_cast<intptr_t>(addr) & Page::kPageAlignmentMask) ==
-           kObjectStartOffset;
-  }
-
-  static bool IsAtEnd(Address addr) {
-    return (reinterpret_cast<intptr_t>(addr) & Page::kPageAlignmentMask) == 0;
-  }
-
-  // Finds the NewSpacePage containing the given address.
-  static inline NewSpacePage* FromAddress(Address address_in_page) {
-    Address page_start =
-        reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address_in_page) &
-                                  ~Page::kPageAlignmentMask);
-    NewSpacePage* page = reinterpret_cast<NewSpacePage*>(page_start);
-    return page;
-  }
-
-  // Find the page for a limit address. A limit address is either an address
-  // inside a page, or the address right after the last byte of a page.
-  static inline NewSpacePage* FromLimit(Address address_limit) {
-    return NewSpacePage::FromAddress(address_limit - 1);
-  }
-
-  // Checks if address1 and address2 are on the same new space page.
-  static inline bool OnSamePage(Address address1, Address address2) {
-    return NewSpacePage::FromAddress(address1) ==
-           NewSpacePage::FromAddress(address2);
-  }
-
-  inline NewSpacePage* next_page() {
-    return static_cast<NewSpacePage*>(next_chunk());
-  }
-
-  inline void set_next_page(NewSpacePage* page) { set_next_chunk(page); }
-
-  inline NewSpacePage* prev_page() {
-    return static_cast<NewSpacePage*>(prev_chunk());
-  }
-
-  inline void set_prev_page(NewSpacePage* page) { set_prev_chunk(page); }
-
-  SemiSpace* semi_space() { return reinterpret_cast<SemiSpace*>(owner()); }
-
-  bool is_anchor() { return !this->InNewSpace(); }
-
- private:
-  // GC related flags copied from from-space to to-space when
-  // flipping semispaces.
-  static const intptr_t kCopyOnFlipFlagsMask =
-      (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) |
-      (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING);
-
-  // Create a NewSpacePage object that is only used as anchor
-  // for the doubly-linked list of real pages.
-  explicit NewSpacePage(SemiSpace* owner) { InitializeAsAnchor(owner); }
-
-  // Intialize a fake NewSpacePage used as sentinel at the ends
-  // of a doubly-linked list of real NewSpacePages.
-  // Only uses the prev/next links, and sets flags to not be in new-space.
-  void InitializeAsAnchor(SemiSpace* owner);
-
-  friend class SemiSpace;
-  friend class SemiSpaceIterator;
-};
-
-
 // -----------------------------------------------------------------------------
 // SemiSpace in young generation
 //
@@ -2368,6 +2437,8 @@
 // space as a marking stack when tracing live objects.
 class SemiSpace : public Space {
  public:
+  typedef PageIterator iterator;
+
   static void Swap(SemiSpace* from, SemiSpace* to);
 
   SemiSpace(Heap* heap, SemiSpaceId semispace)
@@ -2379,7 +2450,8 @@
         committed_(false),
         id_(semispace),
         anchor_(this),
-        current_page_(nullptr) {}
+        current_page_(nullptr),
+        pages_used_(0) {}
 
   inline bool Contains(HeapObject* o);
   inline bool Contains(Object* o);
@@ -2402,14 +2474,17 @@
   // than the current capacity.
   bool ShrinkTo(int new_capacity);
 
+  bool EnsureCurrentCapacity();
+
   // Returns the start address of the first page of the space.
   Address space_start() {
     DCHECK_NE(anchor_.next_page(), anchor());
     return anchor_.next_page()->area_start();
   }
 
-  NewSpacePage* first_page() { return anchor_.next_page(); }
-  NewSpacePage* current_page() { return current_page_; }
+  Page* first_page() { return anchor_.next_page(); }
+  Page* current_page() { return current_page_; }
+  int pages_used() { return pages_used_; }
 
   // Returns one past the end address of the space.
   Address space_end() { return anchor_.prev_page()->area_end(); }
@@ -2421,15 +2496,25 @@
   Address page_high() { return current_page_->area_end(); }
 
   bool AdvancePage() {
-    NewSpacePage* next_page = current_page_->next_page();
-    if (next_page == anchor()) return false;
+    Page* next_page = current_page_->next_page();
+    // We cannot expand if we reached the maximum number of pages already. Note
+    // that we need to account for the next page already for this check as we
+    // could potentially fill the whole page after advancing.
+    const bool reached_max_pages = (pages_used_ + 1) == max_pages();
+    if (next_page == anchor() || reached_max_pages) {
+      return false;
+    }
     current_page_ = next_page;
+    pages_used_++;
     return true;
   }
 
   // Resets the space to using the first page.
   void Reset();
 
+  void RemovePage(Page* page);
+  void PrependPage(Page* page);
+
   // Age mark accessors.
   Address age_mark() { return age_mark_; }
   void set_age_mark(Address mark);
@@ -2478,10 +2563,14 @@
   virtual void Verify();
 #endif
 
- private:
-  void RewindPages(NewSpacePage* start, int num_pages);
+  iterator begin() { return iterator(anchor_.next_page()); }
+  iterator end() { return iterator(anchor()); }
 
-  inline NewSpacePage* anchor() { return &anchor_; }
+ private:
+  void RewindPages(Page* start, int num_pages);
+
+  inline Page* anchor() { return &anchor_; }
+  inline int max_pages() { return current_capacity_ / Page::kPageSize; }
 
   // Copies the flags into the masked positions on all pages in the space.
   void FixPagesFlags(intptr_t flags, intptr_t flag_mask);
@@ -2489,7 +2578,8 @@
   // The currently committed space capacity.
   int current_capacity_;
 
-  // The maximum capacity that can be used by this space.
+  // The maximum capacity that can be used by this space. A space cannot grow
+  // beyond that size.
   int maximum_capacity_;
 
   // The minimum capacity for the space. A space cannot shrink below this size.
@@ -2501,11 +2591,12 @@
   bool committed_;
   SemiSpaceId id_;
 
-  NewSpacePage anchor_;
-  NewSpacePage* current_page_;
+  Page anchor_;
+  Page* current_page_;
+  int pages_used_;
 
+  friend class NewSpace;
   friend class SemiSpaceIterator;
-  friend class NewSpacePageIterator;
 };
 
 
@@ -2519,10 +2610,7 @@
   // Create an iterator over the allocated objects in the given to-space.
   explicit SemiSpaceIterator(NewSpace* space);
 
-  inline HeapObject* Next();
-
-  // Implementation of the ObjectIterator functions.
-  inline HeapObject* next_object() override;
+  inline HeapObject* Next() override;
 
  private:
   void Initialize(Address start, Address end);
@@ -2533,35 +2621,6 @@
   Address limit_;
 };
 
-
-// -----------------------------------------------------------------------------
-// A PageIterator iterates the pages in a semi-space.
-class NewSpacePageIterator BASE_EMBEDDED {
- public:
-  // Make an iterator that runs over all pages in to-space.
-  explicit inline NewSpacePageIterator(NewSpace* space);
-
-  // Make an iterator that runs over all pages in the given semispace,
-  // even those not used in allocation.
-  explicit inline NewSpacePageIterator(SemiSpace* space);
-
-  // Make iterator that iterates from the page containing start
-  // to the page that contains limit in the same semispace.
-  inline NewSpacePageIterator(Address start, Address limit);
-
-  inline bool has_next();
-  inline NewSpacePage* next();
-
- private:
-  NewSpacePage* prev_page_;  // Previous page returned.
-  // Next page that will be returned.  Cached here so that we can use this
-  // iterator for operations that deallocate pages.
-  NewSpacePage* next_page_;
-  // Last page returned.
-  NewSpacePage* last_page_;
-};
-
-
 // -----------------------------------------------------------------------------
 // The young generation space.
 //
@@ -2570,12 +2629,13 @@
 
 class NewSpace : public Space {
  public:
+  typedef PageIterator iterator;
+
   explicit NewSpace(Heap* heap)
       : Space(heap, NEW_SPACE, NOT_EXECUTABLE),
         to_space_(heap, kToSpace),
         from_space_(heap, kFromSpace),
         reservation_(),
-        pages_used_(0),
         top_on_previous_step_(0),
         allocated_histogram_(nullptr),
         promoted_histogram_(nullptr) {}
@@ -2607,7 +2667,7 @@
 
   // Return the allocated bytes in the active semispace.
   intptr_t Size() override {
-    return pages_used_ * NewSpacePage::kAllocatableMemory +
+    return to_space_.pages_used() * Page::kAllocatableMemory +
            static_cast<int>(top() - to_space_.page_low());
   }
 
@@ -2620,7 +2680,7 @@
   intptr_t Capacity() {
     SLOW_DCHECK(to_space_.current_capacity() == from_space_.current_capacity());
     return (to_space_.current_capacity() / Page::kPageSize) *
-           NewSpacePage::kAllocatableMemory;
+           Page::kAllocatableMemory;
   }
 
   // Return the current size of a semispace, allocatable and non-allocatable
@@ -2650,9 +2710,9 @@
   size_t AllocatedSinceLastGC() {
     bool seen_age_mark = false;
     Address age_mark = to_space_.age_mark();
-    NewSpacePage* current_page = to_space_.first_page();
-    NewSpacePage* age_mark_page = NewSpacePage::FromAddress(age_mark);
-    NewSpacePage* last_page = NewSpacePage::FromAddress(top() - kPointerSize);
+    Page* current_page = to_space_.first_page();
+    Page* age_mark_page = Page::FromAddress(age_mark);
+    Page* last_page = Page::FromAddress(top() - kPointerSize);
     if (age_mark_page == last_page) {
       if (top() - age_mark >= 0) {
         return top() - age_mark;
@@ -2675,7 +2735,7 @@
     DCHECK_EQ(current_page, age_mark_page);
     current_page = age_mark_page->next_page();
     while (current_page != last_page) {
-      allocated += NewSpacePage::kAllocatableMemory;
+      allocated += Page::kAllocatableMemory;
       current_page = current_page->next_page();
     }
     allocated += top() - current_page->area_start();
@@ -2684,6 +2744,14 @@
     return static_cast<size_t>(allocated);
   }
 
+  void MovePageFromSpaceToSpace(Page* page) {
+    DCHECK(page->InFromSpace());
+    from_space_.RemovePage(page);
+    to_space_.PrependPage(page);
+  }
+
+  bool Rebalance();
+
   // Return the maximum capacity of a semispace.
   int MaximumCapacity() {
     DCHECK(to_space_.maximum_capacity() == from_space_.maximum_capacity());
@@ -2826,6 +2894,9 @@
   void PauseAllocationObservers() override;
   void ResumeAllocationObservers() override;
 
+  iterator begin() { return to_space_.begin(); }
+  iterator end() { return to_space_.end(); }
+
  private:
   // Update allocation info to match the current to-space page.
   void UpdateAllocationInfo();
@@ -2836,7 +2907,6 @@
   SemiSpace to_space_;
   SemiSpace from_space_;
   base::VirtualMemory reservation_;
-  int pages_used_;
 
   // Allocation pointer and limit for normal allocation and allocation during
   // mark-compact collection.
@@ -2970,6 +3040,8 @@
 
 class LargeObjectSpace : public Space {
  public:
+  typedef LargePageIterator iterator;
+
   LargeObjectSpace(Heap* heap, AllocationSpace id);
   virtual ~LargeObjectSpace();
 
@@ -3028,6 +3100,12 @@
 
   LargePage* first_page() { return first_page_; }
 
+  // Collect code statistics.
+  void CollectCodeStatistics();
+
+  iterator begin() { return iterator(first_page_); }
+  iterator end() { return iterator(nullptr); }
+
 #ifdef VERIFY_HEAP
   virtual void Verify();
 #endif
@@ -3035,7 +3113,6 @@
 #ifdef DEBUG
   void Print() override;
   void ReportStatistics();
-  void CollectCodeStatistics();
 #endif
 
  private:
@@ -3045,7 +3122,7 @@
   int page_count_;         // number of chunks
   intptr_t objects_size_;  // size of objects
   // Map MemoryChunk::kAlignment-aligned chunks to large pages covering them
-  HashMap chunk_map_;
+  base::HashMap chunk_map_;
 
   friend class LargeObjectIterator;
 };
@@ -3055,31 +3132,17 @@
  public:
   explicit LargeObjectIterator(LargeObjectSpace* space);
 
-  HeapObject* Next();
-
-  // implementation of ObjectIterator.
-  virtual HeapObject* next_object() { return Next(); }
+  HeapObject* Next() override;
 
  private:
   LargePage* current_;
 };
 
-class LargePageIterator BASE_EMBEDDED {
- public:
-  explicit inline LargePageIterator(LargeObjectSpace* space);
-
-  inline LargePage* next();
-
- private:
-  LargePage* next_page_;
-};
-
 // Iterates over the chunks (pages and large object pages) that can contain
 // pointers to new space or to evacuation candidates.
 class MemoryChunkIterator BASE_EMBEDDED {
  public:
-  enum Mode { ALL, ALL_BUT_MAP_SPACE, ALL_BUT_CODE_SPACE };
-  inline explicit MemoryChunkIterator(Heap* heap, Mode mode);
+  inline explicit MemoryChunkIterator(Heap* heap);
 
   // Return NULL when the iterator is done.
   inline MemoryChunk* next();
@@ -3092,8 +3155,8 @@
     kLargeObjectState,
     kFinishedState
   };
+  Heap* heap_;
   State state_;
-  const Mode mode_;
   PageIterator old_iterator_;
   PageIterator code_iterator_;
   PageIterator map_iterator_;
diff --git a/src/i18n.cc b/src/i18n.cc
index 623de50..b64fc17 100644
--- a/src/i18n.cc
+++ b/src/i18n.cc
@@ -768,28 +768,12 @@
   return NULL;
 }
 
-
-template<class T>
-void DeleteNativeObjectAt(const v8::WeakCallbackData<v8::Value, void>& data,
-                          int index) {
-  v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(data.GetValue());
-  delete reinterpret_cast<T*>(obj->GetAlignedPointerFromInternalField(index));
-}
-
-
-static void DestroyGlobalHandle(
-    const v8::WeakCallbackData<v8::Value, void>& data) {
+void DateFormat::DeleteDateFormat(const v8::WeakCallbackInfo<void>& data) {
+  delete reinterpret_cast<icu::SimpleDateFormat*>(data.GetInternalField(0));
   GlobalHandles::Destroy(reinterpret_cast<Object**>(data.GetParameter()));
 }
 
 
-void DateFormat::DeleteDateFormat(
-    const v8::WeakCallbackData<v8::Value, void>& data) {
-  DeleteNativeObjectAt<icu::SimpleDateFormat>(data, 0);
-  DestroyGlobalHandle(data);
-}
-
-
 icu::DecimalFormat* NumberFormat::InitializeNumberFormat(
     Isolate* isolate,
     Handle<String> locale,
@@ -847,11 +831,9 @@
   return NULL;
 }
 
-
-void NumberFormat::DeleteNumberFormat(
-    const v8::WeakCallbackData<v8::Value, void>& data) {
-  DeleteNativeObjectAt<icu::DecimalFormat>(data, 0);
-  DestroyGlobalHandle(data);
+void NumberFormat::DeleteNumberFormat(const v8::WeakCallbackInfo<void>& data) {
+  delete reinterpret_cast<icu::DecimalFormat*>(data.GetInternalField(0));
+  GlobalHandles::Destroy(reinterpret_cast<Object**>(data.GetParameter()));
 }
 
 
@@ -908,11 +890,9 @@
   return NULL;
 }
 
-
-void Collator::DeleteCollator(
-    const v8::WeakCallbackData<v8::Value, void>& data) {
-  DeleteNativeObjectAt<icu::Collator>(data, 0);
-  DestroyGlobalHandle(data);
+void Collator::DeleteCollator(const v8::WeakCallbackInfo<void>& data) {
+  delete reinterpret_cast<icu::Collator*>(data.GetInternalField(0));
+  GlobalHandles::Destroy(reinterpret_cast<Object**>(data.GetParameter()));
 }
 
 
@@ -973,12 +953,11 @@
   return NULL;
 }
 
-
 void BreakIterator::DeleteBreakIterator(
-    const v8::WeakCallbackData<v8::Value, void>& data) {
-  DeleteNativeObjectAt<icu::BreakIterator>(data, 0);
-  DeleteNativeObjectAt<icu::UnicodeString>(data, 1);
-  DestroyGlobalHandle(data);
+    const v8::WeakCallbackInfo<void>& data) {
+  delete reinterpret_cast<icu::BreakIterator*>(data.GetInternalField(0));
+  delete reinterpret_cast<icu::UnicodeString*>(data.GetInternalField(1));
+  GlobalHandles::Destroy(reinterpret_cast<Object**>(data.GetParameter()));
 }
 
 }  // namespace internal
diff --git a/src/i18n.h b/src/i18n.h
index a8db4d1..2a4c208 100644
--- a/src/i18n.h
+++ b/src/i18n.h
@@ -51,8 +51,7 @@
 
   // Release memory we allocated for the DateFormat once the JS object that
   // holds the pointer gets garbage collected.
-  static void DeleteDateFormat(
-      const v8::WeakCallbackData<v8::Value, void>& data);
+  static void DeleteDateFormat(const v8::WeakCallbackInfo<void>& data);
 
  private:
   DateFormat();
@@ -75,8 +74,7 @@
 
   // Release memory we allocated for the NumberFormat once the JS object that
   // holds the pointer gets garbage collected.
-  static void DeleteNumberFormat(
-      const v8::WeakCallbackData<v8::Value, void>& data);
+  static void DeleteNumberFormat(const v8::WeakCallbackInfo<void>& data);
 
  private:
   NumberFormat();
@@ -98,8 +96,7 @@
 
   // Release memory we allocated for the Collator once the JS object that holds
   // the pointer gets garbage collected.
-  static void DeleteCollator(
-      const v8::WeakCallbackData<v8::Value, void>& data);
+  static void DeleteCollator(const v8::WeakCallbackInfo<void>& data);
 
  private:
   Collator();
@@ -121,8 +118,7 @@
 
   // Release memory we allocated for the BreakIterator once the JS object that
   // holds the pointer gets garbage collected.
-  static void DeleteBreakIterator(
-      const v8::WeakCallbackData<v8::Value, void>& data);
+  static void DeleteBreakIterator(const v8::WeakCallbackInfo<void>& data);
 
  private:
   BreakIterator();
diff --git a/src/ia32/assembler-ia32-inl.h b/src/ia32/assembler-ia32-inl.h
index cafa676..2120a90 100644
--- a/src/ia32/assembler-ia32-inl.h
+++ b/src/ia32/assembler-ia32-inl.h
@@ -81,11 +81,6 @@
   return Assembler::target_address_at(pc_, host_);
 }
 
-Address RelocInfo::wasm_memory_reference() {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  return Memory::Address_at(pc_);
-}
-
 Address RelocInfo::target_address_address() {
   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
                               || rmode_ == EMBEDDED_OBJECT
@@ -119,21 +114,6 @@
   }
 }
 
-void RelocInfo::update_wasm_memory_reference(
-    Address old_base, Address new_base, size_t old_size, size_t new_size,
-    ICacheFlushMode icache_flush_mode) {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  DCHECK(old_base <= wasm_memory_reference() &&
-         wasm_memory_reference() < old_base + old_size);
-  Address updated_reference = new_base + (wasm_memory_reference() - old_base);
-  DCHECK(new_base <= updated_reference &&
-         updated_reference < new_base + new_size);
-  Memory::Address_at(pc_) = updated_reference;
-  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
-    Assembler::FlushICache(isolate_, pc_, sizeof(int32_t));
-  }
-}
-
 Object* RelocInfo::target_object() {
   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
   return Memory::Object_at(pc_);
@@ -283,7 +263,7 @@
   }
 }
 
-
+template <typename ObjectVisitor>
 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index 150131c..925ae48 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -186,6 +186,30 @@
   return false;
 }
 
+Address RelocInfo::wasm_memory_reference() {
+  DCHECK(IsWasmMemoryReference(rmode_));
+  return Memory::Address_at(pc_);
+}
+
+Address RelocInfo::wasm_global_reference() {
+  DCHECK(IsWasmGlobalReference(rmode_));
+  return Memory::Address_at(pc_);
+}
+
+uint32_t RelocInfo::wasm_memory_size_reference() {
+  DCHECK(IsWasmMemorySizeReference(rmode_));
+  return Memory::uint32_at(pc_);
+}
+
+void RelocInfo::unchecked_update_wasm_memory_reference(
+    Address address, ICacheFlushMode flush_mode) {
+  Memory::Address_at(pc_) = address;
+}
+
+void RelocInfo::unchecked_update_wasm_memory_size(uint32_t size,
+                                                  ICacheFlushMode flush_mode) {
+  Memory::uint32_at(pc_) = size;
+}
 
 // -----------------------------------------------------------------------------
 // Implementation of Operand
@@ -308,6 +332,8 @@
   desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
   desc->origin = this;
   desc->constant_pool_size = 0;
+  desc->unwinding_info_size = 0;
+  desc->unwinding_info = nullptr;
 }
 
 
@@ -681,6 +707,45 @@
   emit_operand(dst, src);
 }
 
+void Assembler::xchg_b(Register reg, const Operand& op) {
+  EnsureSpace ensure_space(this);
+  EMIT(0x86);
+  emit_operand(reg, op);
+}
+
+void Assembler::xchg_w(Register reg, const Operand& op) {
+  EnsureSpace ensure_space(this);
+  EMIT(0x66);
+  EMIT(0x87);
+  emit_operand(reg, op);
+}
+
+void Assembler::lock() {
+  EnsureSpace ensure_space(this);
+  EMIT(0xF0);
+}
+
+void Assembler::cmpxchg(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  EMIT(0x0F);
+  EMIT(0xB1);
+  emit_operand(src, dst);
+}
+
+void Assembler::cmpxchg_b(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  EMIT(0x0F);
+  EMIT(0xB0);
+  emit_operand(src, dst);
+}
+
+void Assembler::cmpxchg_w(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  EMIT(0x66);
+  EMIT(0x0F);
+  EMIT(0xB1);
+  emit_operand(src, dst);
+}
 
 void Assembler::adc(Register dst, int32_t imm32) {
   EnsureSpace ensure_space(this);
@@ -787,14 +852,14 @@
 void Assembler::cmpw(Register reg, const Operand& op) {
   EnsureSpace ensure_space(this);
   EMIT(0x66);
-  EMIT(0x39);
+  EMIT(0x3B);
   emit_operand(reg, op);
 }
 
 void Assembler::cmpw(const Operand& op, Register reg) {
   EnsureSpace ensure_space(this);
   EMIT(0x66);
-  EMIT(0x3B);
+  EMIT(0x39);
   emit_operand(reg, op);
 }
 
@@ -1468,7 +1533,6 @@
 
 
 void Assembler::call(Label* L) {
-  positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
   if (L->is_bound()) {
     const int long_size = 5;
@@ -1486,7 +1550,6 @@
 
 
 void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
-  positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
   DCHECK(!RelocInfo::IsCodeTarget(rmode));
   EMIT(0xE8);
@@ -1505,7 +1568,6 @@
 
 
 void Assembler::call(const Operand& adr) {
-  positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
   EMIT(0xFF);
   emit_operand(edx, adr);
@@ -1520,7 +1582,6 @@
 void Assembler::call(Handle<Code> code,
                      RelocInfo::Mode rmode,
                      TypeFeedbackId ast_id) {
-  positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
   DCHECK(RelocInfo::IsCodeTarget(rmode)
       || rmode == RelocInfo::CODE_AGE_SEQUENCE);
diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index 5105ff5..4e542d7 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -74,6 +74,9 @@
   V(xmm6)                   \
   V(xmm7)
 
+#define FLOAT_REGISTERS DOUBLE_REGISTERS
+#define SIMD_REGISTERS DOUBLE_REGISTERS
+
 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \
   V(xmm1)                               \
   V(xmm2)                               \
@@ -121,8 +124,6 @@
     Register r = {code};
     return r;
   }
-  const char* ToString();
-  bool IsAllocatable() const;
   bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
   bool is(Register reg) const { return reg_code == reg.reg_code; }
   int code() const {
@@ -146,8 +147,9 @@
 #undef DECLARE_REGISTER
 const Register no_reg = {Register::kCode_no_reg};
 
+static const bool kSimpleFPAliasing = true;
 
-struct DoubleRegister {
+struct XMMRegister {
   enum Code {
 #define REGISTER_CODE(R) kCode_##R,
     DOUBLE_REGISTERS(REGISTER_CODE)
@@ -158,12 +160,11 @@
 
   static const int kMaxNumRegisters = Code::kAfterLast;
 
-  static DoubleRegister from_code(int code) {
-    DoubleRegister result = {code};
+  static XMMRegister from_code(int code) {
+    XMMRegister result = {code};
     return result;
   }
 
-  bool IsAllocatable() const;
   bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
 
   int code() const {
@@ -171,23 +172,23 @@
     return reg_code;
   }
 
-  bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
-
-  const char* ToString();
+  bool is(XMMRegister reg) const { return reg_code == reg.reg_code; }
 
   int reg_code;
 };
 
+typedef XMMRegister FloatRegister;
+
+typedef XMMRegister DoubleRegister;
+
+typedef XMMRegister Simd128Register;
+
 #define DECLARE_REGISTER(R) \
   const DoubleRegister R = {DoubleRegister::kCode_##R};
 DOUBLE_REGISTERS(DECLARE_REGISTER)
 #undef DECLARE_REGISTER
 const DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg};
 
-typedef DoubleRegister Simd128Register;
-
-typedef DoubleRegister XMMRegister;
-
 enum Condition {
   // any value < 0 is considered no_condition
   no_condition  = -1,
@@ -655,6 +656,16 @@
   // Exchange
   void xchg(Register dst, Register src);
   void xchg(Register dst, const Operand& src);
+  void xchg_b(Register reg, const Operand& op);
+  void xchg_w(Register reg, const Operand& op);
+
+  // Lock prefix
+  void lock();
+
+  // CompareExchange
+  void cmpxchg(const Operand& dst, Register src);
+  void cmpxchg_b(const Operand& dst, Register src);
+  void cmpxchg_w(const Operand& dst, Register src);
 
   // Arithmetics
   void adc(Register dst, int32_t imm32);
@@ -1432,7 +1443,7 @@
 
   // Record a deoptimization reason that can be used by a log or cpu profiler.
   // Use --trace-deopt to enable.
-  void RecordDeoptReason(const int reason, int raw_position);
+  void RecordDeoptReason(const int reason, int raw_position, int id);
 
   // Writes a single byte or word of data in the code stream.  Used for
   // inline tables, e.g., jump-tables.
diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc
index b7e33d9..96b2787 100644
--- a/src/ia32/builtins-ia32.cc
+++ b/src/ia32/builtins-ia32.cc
@@ -16,10 +16,7 @@
 
 #define __ ACCESS_MASM(masm)
 
-
-void Builtins::Generate_Adaptor(MacroAssembler* masm,
-                                CFunctionId id,
-                                BuiltinExtraArguments extra_args) {
+void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
   // ----------- S t a t e -------------
   //  -- eax                : number of arguments excluding receiver
   //  -- edi                : target
@@ -39,19 +36,11 @@
   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
 
   // Insert extra arguments.
-  int num_extra_args = 0;
-  if (extra_args != BuiltinExtraArguments::kNone) {
-    __ PopReturnAddressTo(ecx);
-    if (extra_args & BuiltinExtraArguments::kTarget) {
-      ++num_extra_args;
-      __ Push(edi);
-    }
-    if (extra_args & BuiltinExtraArguments::kNewTarget) {
-      ++num_extra_args;
-      __ Push(edx);
-    }
-    __ PushReturnAddressFrom(ecx);
-  }
+  const int num_extra_args = 2;
+  __ PopReturnAddressTo(ecx);
+  __ Push(edi);
+  __ Push(edx);
+  __ PushReturnAddressFrom(ecx);
 
   // JumpToExternalReference expects eax to contain the number of arguments
   // including the receiver and the extra arguments.
@@ -186,16 +175,9 @@
     __ j(greater_equal, &loop);
 
     // Call the function.
-    if (is_api_function) {
-      __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
-      Handle<Code> code =
-          masm->isolate()->builtins()->HandleApiCallConstruct();
-      __ call(code, RelocInfo::CODE_TARGET);
-    } else {
-      ParameterCount actual(eax);
-      __ InvokeFunction(edi, edx, actual, CALL_FUNCTION,
-                        CheckDebugStepCallWrapper());
-    }
+    ParameterCount actual(eax);
+    __ InvokeFunction(edi, edx, actual, CALL_FUNCTION,
+                      CheckDebugStepCallWrapper());
 
     // Store offset of return address for deoptimizer.
     if (create_implicit_receiver && !is_api_function) {
@@ -391,6 +373,184 @@
   Generate_JSEntryTrampolineHelper(masm, true);
 }
 
+// static
+void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- eax    : the value to pass to the generator
+  //  -- ebx    : the JSGeneratorObject to resume
+  //  -- edx    : the resume mode (tagged)
+  //  -- esp[0] : return address
+  // -----------------------------------
+  __ AssertGeneratorObject(ebx);
+
+  // Store input value into generator object.
+  __ mov(FieldOperand(ebx, JSGeneratorObject::kInputOrDebugPosOffset), eax);
+  __ RecordWriteField(ebx, JSGeneratorObject::kInputOrDebugPosOffset, eax, ecx,
+                      kDontSaveFPRegs);
+
+  // Store resume mode into generator object.
+  __ mov(FieldOperand(ebx, JSGeneratorObject::kResumeModeOffset), edx);
+
+  // Load suspended function and context.
+  __ mov(esi, FieldOperand(ebx, JSGeneratorObject::kContextOffset));
+  __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset));
+
+  // Flood function if we are stepping.
+  Label prepare_step_in_if_stepping, prepare_step_in_suspended_generator;
+  Label stepping_prepared;
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(masm->isolate());
+  STATIC_ASSERT(StepFrame > StepIn);
+  __ cmpb(Operand::StaticVariable(last_step_action), Immediate(StepIn));
+  __ j(greater_equal, &prepare_step_in_if_stepping);
+
+  // Flood function if we need to continue stepping in the suspended generator.
+  ExternalReference debug_suspended_generator =
+      ExternalReference::debug_suspended_generator_address(masm->isolate());
+  __ cmp(ebx, Operand::StaticVariable(debug_suspended_generator));
+  __ j(equal, &prepare_step_in_suspended_generator);
+  __ bind(&stepping_prepared);
+
+  // Pop return address.
+  __ PopReturnAddressTo(eax);
+
+  // Push receiver.
+  __ Push(FieldOperand(ebx, JSGeneratorObject::kReceiverOffset));
+
+  // ----------- S t a t e -------------
+  //  -- eax    : return address
+  //  -- ebx    : the JSGeneratorObject to resume
+  //  -- edx    : the resume mode (tagged)
+  //  -- edi    : generator function
+  //  -- esi    : generator context
+  //  -- esp[0] : generator receiver
+  // -----------------------------------
+
+  // Push holes for arguments to generator function. Since the parser forced
+  // context allocation for any variables in generators, the actual argument
+  // values have already been copied into the context and these dummy values
+  // will never be used.
+  __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+  __ mov(ecx,
+         FieldOperand(ecx, SharedFunctionInfo::kFormalParameterCountOffset));
+  {
+    Label done_loop, loop;
+    __ bind(&loop);
+    __ sub(ecx, Immediate(Smi::FromInt(1)));
+    __ j(carry, &done_loop, Label::kNear);
+    __ PushRoot(Heap::kTheHoleValueRootIndex);
+    __ jmp(&loop);
+    __ bind(&done_loop);
+  }
+
+  // Dispatch on the kind of generator object.
+  Label old_generator;
+  __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+  __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kFunctionDataOffset));
+  __ CmpObjectType(ecx, BYTECODE_ARRAY_TYPE, ecx);
+  __ j(not_equal, &old_generator);
+
+  // New-style (ignition/turbofan) generator object
+  {
+    __ PushReturnAddressFrom(eax);
+    __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+    __ mov(eax,
+         FieldOperand(ecx, SharedFunctionInfo::kFormalParameterCountOffset));
+    // We abuse new.target both to indicate that this is a resume call and to
+    // pass in the generator object.  In ordinary calls, new.target is always
+    // undefined because generator functions are non-constructable.
+    __ mov(edx, ebx);
+    __ jmp(FieldOperand(edi, JSFunction::kCodeEntryOffset));
+  }
+
+  // Old-style (full-codegen) generator object
+  __ bind(&old_generator);
+  {
+    // Enter a new JavaScript frame, and initialize its slots as they were when
+    // the generator was suspended.
+    FrameScope scope(masm, StackFrame::MANUAL);
+    __ PushReturnAddressFrom(eax);  // Return address.
+    __ Push(ebp);                   // Caller's frame pointer.
+    __ Move(ebp, esp);
+    __ Push(esi);  // Callee's context.
+    __ Push(edi);  // Callee's JS Function.
+
+    // Restore the operand stack.
+    __ mov(eax, FieldOperand(ebx, JSGeneratorObject::kOperandStackOffset));
+    {
+      Label done_loop, loop;
+      __ Move(ecx, Smi::FromInt(0));
+      __ bind(&loop);
+      __ cmp(ecx, FieldOperand(eax, FixedArray::kLengthOffset));
+      __ j(equal, &done_loop, Label::kNear);
+      __ Push(FieldOperand(eax, ecx, times_half_pointer_size,
+                           FixedArray::kHeaderSize));
+      __ add(ecx, Immediate(Smi::FromInt(1)));
+      __ jmp(&loop);
+      __ bind(&done_loop);
+    }
+
+    // Reset operand stack so we don't leak.
+    __ mov(FieldOperand(ebx, JSGeneratorObject::kOperandStackOffset),
+           Immediate(masm->isolate()->factory()->empty_fixed_array()));
+
+    // Resume the generator function at the continuation.
+    __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+    __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));
+    __ mov(ecx, FieldOperand(ebx, JSGeneratorObject::kContinuationOffset));
+    __ SmiUntag(ecx);
+    __ lea(edx, FieldOperand(edx, ecx, times_1, Code::kHeaderSize));
+    __ mov(FieldOperand(ebx, JSGeneratorObject::kContinuationOffset),
+           Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
+    __ mov(eax, ebx);  // Continuation expects generator object in eax.
+    __ jmp(edx);
+  }
+
+  __ bind(&prepare_step_in_if_stepping);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ Push(ebx);
+    __ Push(edx);
+    __ Push(edi);
+    __ CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
+    __ Pop(edx);
+    __ Pop(ebx);
+    __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset));
+  }
+  __ jmp(&stepping_prepared);
+
+  __ bind(&prepare_step_in_suspended_generator);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ Push(ebx);
+    __ Push(edx);
+    __ CallRuntime(Runtime::kDebugPrepareStepInSuspendedGenerator);
+    __ Pop(edx);
+    __ Pop(ebx);
+    __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset));
+  }
+  __ jmp(&stepping_prepared);
+}
+
+static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch1,
+                                  Register scratch2) {
+  Register args_count = scratch1;
+  Register return_pc = scratch2;
+
+  // Get the arguments + reciever count.
+  __ mov(args_count,
+         Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp));
+  __ mov(args_count,
+         FieldOperand(args_count, BytecodeArray::kParameterSizeOffset));
+
+  // Leave the frame (also dropping the register file).
+  __ leave();
+
+  // Drop receiver + arguments.
+  __ pop(return_pc);
+  __ add(esp, args_count);
+  __ push(return_pc);
+}
 
 // Generate code for entering a JS function with the interpreter.
 // On entry to the function the receiver and arguments have been pushed on the
@@ -407,6 +567,8 @@
 // The function builds an interpreter frame.  See InterpreterFrameConstants in
 // frames.h for its layout.
 void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
+  ProfileEntryHookStub::MaybeCallEntryHook(masm);
+
   // Open a frame scope to indicate that there is a frame on the stack.  The
   // MANUAL indicates that the scope shouldn't actually generate code to set up
   // the frame (that is done below).
@@ -417,10 +579,9 @@
   __ push(edi);  // Callee's JS function.
   __ push(edx);  // Callee's new target.
 
-  // Get the bytecode array from the function object and load the pointer to the
-  // first entry into edi (InterpreterBytecodeRegister).
+  // Get the bytecode array from the function object (or from the DebugInfo if
+  // it is present) and load it into kInterpreterBytecodeArrayRegister.
   __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
-
   Label load_debug_bytecode_array, bytecode_array_loaded;
   __ cmp(FieldOperand(eax, SharedFunctionInfo::kDebugInfoOffset),
          Immediate(DebugInfo::uninitialized()));
@@ -429,8 +590,12 @@
          FieldOperand(eax, SharedFunctionInfo::kFunctionDataOffset));
   __ bind(&bytecode_array_loaded);
 
+  // Check function data field is actually a BytecodeArray object.
+  Label bytecode_array_not_present;
+  __ CompareRoot(kInterpreterBytecodeArrayRegister,
+                 Heap::kUndefinedValueRootIndex);
+  __ j(equal, &bytecode_array_not_present);
   if (FLAG_debug_code) {
-    // Check function data field is actually a BytecodeArray object.
     __ AssertNotSmi(kInterpreterBytecodeArrayRegister);
     __ CmpObjectType(kInterpreterBytecodeArrayRegister, BYTECODE_ARRAY_TYPE,
                      eax);
@@ -439,8 +604,8 @@
 
   // Push bytecode array.
   __ push(kInterpreterBytecodeArrayRegister);
-  // Push zero for bytecode array offset.
-  __ push(Immediate(0));
+  // Push Smi tagged initial bytecode array offset.
+  __ push(Immediate(Smi::FromInt(BytecodeArray::kHeaderSize - kHeapObjectTag)));
 
   // Allocate the local and temporary register file on the stack.
   {
@@ -473,41 +638,25 @@
     __ j(greater_equal, &loop_header);
   }
 
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's prologue:
-  //  - Call ProfileEntryHookStub when isolate has a function_entry_hook.
-  //  - Code aging of the BytecodeArray object.
-
-  // Load accumulator, register file, bytecode offset, dispatch table into
-  // registers.
+  // Load accumulator, bytecode offset and dispatch table into registers.
   __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
-  __ mov(kInterpreterRegisterFileRegister, ebp);
-  __ add(kInterpreterRegisterFileRegister,
-         Immediate(InterpreterFrameConstants::kRegisterFilePointerFromFp));
   __ mov(kInterpreterBytecodeOffsetRegister,
          Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
-  __ mov(ebx, Immediate(ExternalReference::interpreter_dispatch_table_address(
-                  masm->isolate())));
-
-  // Push dispatch table as a stack located parameter to the bytecode handler.
-  DCHECK_EQ(-1, kInterpreterDispatchTableSpillSlot);
-  __ push(ebx);
+  __ mov(kInterpreterDispatchTableRegister,
+         Immediate(ExternalReference::interpreter_dispatch_table_address(
+             masm->isolate())));
 
   // Dispatch to the first bytecode handler for the function.
-  __ movzx_b(eax, Operand(kInterpreterBytecodeArrayRegister,
+  __ movzx_b(ebx, Operand(kInterpreterBytecodeArrayRegister,
                           kInterpreterBytecodeOffsetRegister, times_1, 0));
-  __ mov(ebx, Operand(ebx, eax, times_pointer_size, 0));
-  // Restore undefined_value in accumulator (eax)
-  // TODO(rmcilroy): Remove this once we move the dispatch table back into a
-  // register.
-  __ mov(eax, Immediate(masm->isolate()->factory()->undefined_value()));
-  // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
-  // and header removal.
-  __ add(ebx, Immediate(Code::kHeaderSize - kHeapObjectTag));
+  __ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx,
+                      times_pointer_size, 0));
   __ call(ebx);
+  masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
 
-  // Even though the first bytecode handler was called, we will never return.
-  __ Abort(kUnexpectedReturnFromBytecodeHandler);
+  // The return value is in eax.
+  LeaveInterpreterFrame(masm, ebx, ecx);
+  __ ret(0);
 
   // Load debug copy of the bytecode array.
   __ bind(&load_debug_bytecode_array);
@@ -516,31 +665,48 @@
   __ mov(kInterpreterBytecodeArrayRegister,
          FieldOperand(debug_info, DebugInfo::kAbstractCodeIndex));
   __ jmp(&bytecode_array_loaded);
+
+  // If the bytecode array is no longer present, then the underlying function
+  // has been switched to a different kind of code and we heal the closure by
+  // switching the code entry field over to the new code object as well.
+  __ bind(&bytecode_array_not_present);
+  __ pop(edx);  // Callee's new target.
+  __ pop(edi);  // Callee's JS function.
+  __ pop(esi);  // Callee's context.
+  __ leave();   // Leave the frame so we can tail call.
+  __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+  __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kCodeOffset));
+  __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize));
+  __ mov(FieldOperand(edi, JSFunction::kCodeEntryOffset), ecx);
+  __ RecordWriteCodeEntryField(edi, ecx, ebx);
+  __ jmp(ecx);
 }
 
+void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) {
+  // Save the function and context for call to CompileBaseline.
+  __ mov(edi, Operand(ebp, StandardFrameConstants::kFunctionOffset));
+  __ mov(kContextRegister,
+         Operand(ebp, StandardFrameConstants::kContextOffset));
 
-void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's EmitReturnSequence.
-  //  - Supporting FLAG_trace for Runtime::TraceExit.
-  //  - Support profiler (specifically decrementing profiling_counter
-  //    appropriately and calling out to HandleInterrupts if necessary).
+  // Leave the frame before recompiling for baseline so that we don't count as
+  // an activation on the stack.
+  LeaveInterpreterFrame(masm, ebx, ecx);
 
-  // The return value is in accumulator, which is already in rax.
+  {
+    FrameScope frame_scope(masm, StackFrame::INTERNAL);
+    // Push return value.
+    __ push(eax);
 
-  // Leave the frame (also dropping the register file).
-  __ leave();
+    // Push function as argument and compile for baseline.
+    __ push(edi);
+    __ CallRuntime(Runtime::kCompileBaseline);
 
-  // Drop receiver + arguments and return.
-  __ mov(ebx, FieldOperand(kInterpreterBytecodeArrayRegister,
-                           BytecodeArray::kParameterSizeOffset));
-  __ pop(ecx);
-  __ add(esp, ebx);
-  __ push(ecx);
+    // Restore return value.
+    __ pop(eax);
+  }
   __ ret(0);
 }
 
-
 static void Generate_InterpreterPushArgs(MacroAssembler* masm,
                                          Register array_limit) {
   // ----------- S t a t e -------------
@@ -558,7 +724,6 @@
   __ j(greater, &loop_header, Label::kNear);
 }
 
-
 // static
 void Builtins::Generate_InterpreterPushArgsAndCallImpl(
     MacroAssembler* masm, TailCallMode tail_call_mode) {
@@ -627,17 +792,26 @@
   __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
 }
 
+void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
+  // Set the return address to the correct point in the interpreter entry
+  // trampoline.
+  Smi* interpreter_entry_return_pc_offset(
+      masm->isolate()->heap()->interpreter_entry_return_pc_offset());
+  DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
+  __ LoadHeapObject(ebx,
+                    masm->isolate()->builtins()->InterpreterEntryTrampoline());
+  __ add(ebx, Immediate(interpreter_entry_return_pc_offset->value() +
+                        Code::kHeaderSize - kHeapObjectTag));
+  __ push(ebx);
 
-static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
-  // Initialize register file register.
-  __ mov(kInterpreterRegisterFileRegister, ebp);
-  __ add(kInterpreterRegisterFileRegister,
-         Immediate(InterpreterFrameConstants::kRegisterFilePointerFromFp));
+  // Initialize the dispatch table register.
+  __ mov(kInterpreterDispatchTableRegister,
+         Immediate(ExternalReference::interpreter_dispatch_table_address(
+             masm->isolate())));
 
   // Get the bytecode array pointer from the frame.
   __ mov(kInterpreterBytecodeArrayRegister,
-         Operand(kInterpreterRegisterFileRegister,
-                 InterpreterFrameConstants::kBytecodeArrayFromRegisterPointer));
+         Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp));
 
   if (FLAG_debug_code) {
     // Check function data field is actually a BytecodeArray object.
@@ -648,92 +822,190 @@
   }
 
   // Get the target bytecode offset from the frame.
-  __ mov(
-      kInterpreterBytecodeOffsetRegister,
-      Operand(kInterpreterRegisterFileRegister,
-              InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
+  __ mov(kInterpreterBytecodeOffsetRegister,
+         Operand(ebp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
   __ SmiUntag(kInterpreterBytecodeOffsetRegister);
 
-  // Push dispatch table as a stack located parameter to the bytecode handler.
-  __ mov(ebx, Immediate(ExternalReference::interpreter_dispatch_table_address(
-                  masm->isolate())));
-  DCHECK_EQ(-1, kInterpreterDispatchTableSpillSlot);
-  __ Pop(esi);
-  __ Push(ebx);
-  __ Push(esi);
-
   // Dispatch to the target bytecode.
-  __ movzx_b(esi, Operand(kInterpreterBytecodeArrayRegister,
+  __ movzx_b(ebx, Operand(kInterpreterBytecodeArrayRegister,
                           kInterpreterBytecodeOffsetRegister, times_1, 0));
-  __ mov(ebx, Operand(ebx, esi, times_pointer_size, 0));
-
-  // Get the context from the frame.
-  __ mov(kContextRegister,
-         Operand(kInterpreterRegisterFileRegister,
-                 InterpreterFrameConstants::kContextFromRegisterPointer));
-
-  // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
-  // and header removal.
-  __ add(ebx, Immediate(Code::kHeaderSize - kHeapObjectTag));
+  __ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx,
+                      times_pointer_size, 0));
   __ jmp(ebx);
 }
 
-
-static void Generate_InterpreterNotifyDeoptimizedHelper(
-    MacroAssembler* masm, Deoptimizer::BailoutType type) {
-  // Enter an internal frame.
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Pass the deoptimization type to the runtime system.
-    __ Push(Smi::FromInt(static_cast<int>(type)));
-    __ CallRuntime(Runtime::kNotifyDeoptimized);
-    // Tear down internal frame.
-  }
-
-  // Drop state (we don't use these for interpreter deopts) and and pop the
-  // accumulator value into the accumulator register and push PC at top
-  // of stack (to simulate initial call to bytecode handler in interpreter entry
-  // trampoline).
-  __ Pop(ebx);
-  __ Drop(1);
-  __ Pop(kInterpreterAccumulatorRegister);
-  __ Push(ebx);
-
-  // Enter the bytecode dispatch.
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-
-void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
-}
-
-
-void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
-}
-
-
-void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
-}
-
-void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
-  // Set the address of the interpreter entry trampoline as a return address.
-  // This simulates the initial call to bytecode handlers in interpreter entry
-  // trampoline. The return will never actually be taken, but our stack walker
-  // uses this address to determine whether a frame is interpreted.
-  __ Push(masm->isolate()->builtins()->InterpreterEntryTrampoline());
-
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-
 void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- eax : argument count (preserved for callee)
+  //  -- edx : new target (preserved for callee)
+  //  -- edi : target function (preserved for callee)
+  // -----------------------------------
+  // First lookup code, maybe we don't need to compile!
+  Label gotta_call_runtime, gotta_call_runtime_no_stack;
+  Label maybe_call_runtime;
+  Label try_shared;
+  Label loop_top, loop_bottom;
+
+  Register closure = edi;
+  Register new_target = edx;
+  Register argument_count = eax;
+
+  __ push(argument_count);
+  __ push(new_target);
+  __ push(closure);
+
+  Register map = argument_count;
+  Register index = ebx;
+  __ mov(map, FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ mov(map, FieldOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset));
+  __ mov(index, FieldOperand(map, FixedArray::kLengthOffset));
+  __ cmp(index, Immediate(Smi::FromInt(2)));
+  __ j(less, &gotta_call_runtime);
+
+  // Find literals.
+  // edx : native context
+  // ebx : length / index
+  // eax : optimized code map
+  // stack[0] : new target
+  // stack[4] : closure
+  Register native_context = edx;
+  __ mov(native_context, NativeContextOperand());
+
+  __ bind(&loop_top);
+  Register temp = edi;
+
+  // Does the native context match?
+  __ mov(temp, FieldOperand(map, index, times_half_pointer_size,
+                            SharedFunctionInfo::kOffsetToPreviousContext));
+  __ mov(temp, FieldOperand(temp, WeakCell::kValueOffset));
+  __ cmp(temp, native_context);
+  __ j(not_equal, &loop_bottom);
+  // OSR id set to none?
+  __ mov(temp, FieldOperand(map, index, times_half_pointer_size,
+                            SharedFunctionInfo::kOffsetToPreviousOsrAstId));
+  const int bailout_id = BailoutId::None().ToInt();
+  __ cmp(temp, Immediate(Smi::FromInt(bailout_id)));
+  __ j(not_equal, &loop_bottom);
+
+  // Literals available?
+  Label got_literals, maybe_cleared_weakcell;
+  __ mov(temp, FieldOperand(map, index, times_half_pointer_size,
+                            SharedFunctionInfo::kOffsetToPreviousLiterals));
+
+  // temp contains either a WeakCell pointing to the literals array or the
+  // literals array directly.
+  STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
+  __ JumpIfSmi(FieldOperand(temp, WeakCell::kValueOffset),
+               &maybe_cleared_weakcell);
+  // The WeakCell value is a pointer, therefore it's a valid literals array.
+  __ mov(temp, FieldOperand(temp, WeakCell::kValueOffset));
+  __ jmp(&got_literals);
+
+  // We have a smi. If it's 0, then we are looking at a cleared WeakCell
+  // around the literals array, and we should visit the runtime. If it's > 0,
+  // then temp already contains the literals array.
+  __ bind(&maybe_cleared_weakcell);
+  __ cmp(FieldOperand(temp, WeakCell::kValueOffset), Immediate(0));
+  __ j(equal, &gotta_call_runtime);
+
+  // Save the literals in the closure.
+  __ bind(&got_literals);
+  __ mov(ecx, Operand(esp, 0));
+  __ mov(FieldOperand(ecx, JSFunction::kLiteralsOffset), temp);
+  __ push(index);
+  __ RecordWriteField(ecx, JSFunction::kLiteralsOffset, temp, index,
+                      kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+  __ pop(index);
+
+  // Code available?
+  Register entry = ecx;
+  __ mov(entry, FieldOperand(map, index, times_half_pointer_size,
+                             SharedFunctionInfo::kOffsetToPreviousCachedCode));
+  __ mov(entry, FieldOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &maybe_call_runtime);
+
+  // Found literals and code. Get them into the closure and return.
+  __ pop(closure);
+  // Store code entry in the closure.
+  __ lea(entry, FieldOperand(entry, Code::kHeaderSize));
+
+  Label install_optimized_code_and_tailcall;
+  __ bind(&install_optimized_code_and_tailcall);
+  __ mov(FieldOperand(closure, JSFunction::kCodeEntryOffset), entry);
+  __ RecordWriteCodeEntryField(closure, entry, eax);
+
+  // Link the closure into the optimized function list.
+  // ecx : code entry
+  // edx : native context
+  // edi : closure
+  __ mov(ebx,
+         ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
+  __ mov(FieldOperand(closure, JSFunction::kNextFunctionLinkOffset), ebx);
+  __ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, ebx, eax,
+                      kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+  const int function_list_offset =
+      Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
+  __ mov(ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST),
+         closure);
+  // Save closure before the write barrier.
+  __ mov(ebx, closure);
+  __ RecordWriteContextSlot(native_context, function_list_offset, closure, eax,
+                            kDontSaveFPRegs);
+  __ mov(closure, ebx);
+  __ pop(new_target);
+  __ pop(argument_count);
+  __ jmp(entry);
+
+  __ bind(&loop_bottom);
+  __ sub(index, Immediate(Smi::FromInt(SharedFunctionInfo::kEntryLength)));
+  __ cmp(index, Immediate(Smi::FromInt(1)));
+  __ j(greater, &loop_top);
+
+  // We found neither literals nor code.
+  __ jmp(&gotta_call_runtime);
+
+  __ bind(&maybe_call_runtime);
+  __ pop(closure);
+
+  // Last possibility. Check the context free optimized code map entry.
+  __ mov(entry, FieldOperand(map, FixedArray::kHeaderSize +
+                                      SharedFunctionInfo::kSharedCodeIndex));
+  __ mov(entry, FieldOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &try_shared);
+
+  // Store code entry in the closure.
+  __ lea(entry, FieldOperand(entry, Code::kHeaderSize));
+  __ jmp(&install_optimized_code_and_tailcall);
+
+  __ bind(&try_shared);
+  __ pop(new_target);
+  __ pop(argument_count);
+  // Is the full code valid?
+  __ mov(entry, FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ mov(entry, FieldOperand(entry, SharedFunctionInfo::kCodeOffset));
+  __ mov(ebx, FieldOperand(entry, Code::kFlagsOffset));
+  __ and_(ebx, Code::KindField::kMask);
+  __ shr(ebx, Code::KindField::kShift);
+  __ cmp(ebx, Immediate(Code::BUILTIN));
+  __ j(equal, &gotta_call_runtime_no_stack);
+  // Yes, install the full code.
+  __ lea(entry, FieldOperand(entry, Code::kHeaderSize));
+  __ mov(FieldOperand(closure, JSFunction::kCodeEntryOffset), entry);
+  __ RecordWriteCodeEntryField(closure, entry, ebx);
+  __ jmp(entry);
+
+  __ bind(&gotta_call_runtime);
+  __ pop(closure);
+  __ pop(new_target);
+  __ pop(argument_count);
+  __ bind(&gotta_call_runtime_no_stack);
+
   GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
 }
 
+void Builtins::Generate_CompileBaseline(MacroAssembler* masm) {
+  GenerateTailCallToReturnedCode(masm, Runtime::kCompileBaseline);
+}
 
 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
   GenerateTailCallToReturnedCode(masm,
@@ -875,13 +1147,14 @@
 
   // Switch on the state.
   Label not_no_registers, not_tos_eax;
-  __ cmp(ecx, FullCodeGenerator::NO_REGISTERS);
+  __ cmp(ecx, static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS));
   __ j(not_equal, &not_no_registers, Label::kNear);
   __ ret(1 * kPointerSize);  // Remove state.
 
   __ bind(&not_no_registers);
+  DCHECK_EQ(kInterpreterAccumulatorRegister.code(), eax.code());
   __ mov(eax, Operand(esp, 2 * kPointerSize));
-  __ cmp(ecx, FullCodeGenerator::TOS_REG);
+  __ cmp(ecx, static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER));
   __ j(not_equal, &not_tos_eax, Label::kNear);
   __ ret(2 * kPointerSize);  // Remove state, eax.
 
@@ -909,6 +1182,9 @@
 void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
                                                int field_index) {
   // ----------- S t a t e -------------
+  //  -- eax    : number of arguments
+  //  -- edi    : function
+  //  -- esi    : context
   //  -- esp[0] : return address
   //  -- esp[4] : receiver
   // -----------------------------------
@@ -951,35 +1227,16 @@
   __ bind(&receiver_not_date);
   {
     FrameScope scope(masm, StackFrame::MANUAL);
-    __ EnterFrame(StackFrame::INTERNAL);
+    __ Push(ebp);
+    __ Move(ebp, esp);
+    __ Push(esi);
+    __ Push(edi);
+    __ Push(Immediate(0));
     __ CallRuntime(Runtime::kThrowNotDateError);
   }
 }
 
 // static
-void Builtins::Generate_FunctionHasInstance(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- eax    : argc
-  //  -- esp[0] : return address
-  //  -- esp[4] : first argument (left-hand side)
-  //  -- esp[8] : receiver (right-hand side)
-  // -----------------------------------
-
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-    __ mov(InstanceOfDescriptor::LeftRegister(),
-           Operand(ebp, 2 * kPointerSize));  // Load left-hand side.
-    __ mov(InstanceOfDescriptor::RightRegister(),
-           Operand(ebp, 3 * kPointerSize));  // Load right-hand side.
-    InstanceOfStub stub(masm->isolate(), true);
-    __ CallStub(&stub);
-  }
-
-  // Pop the argument and the receiver.
-  __ ret(2 * kPointerSize);
-}
-
-// static
 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
   // ----------- S t a t e -------------
   //  -- eax     : argc
@@ -1308,6 +1565,8 @@
 void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
   // ----------- S t a t e -------------
   //  -- eax                 : number of arguments
+  //  -- edi                 : function
+  //  -- esi                 : context
   //  -- esp[0]              : return address
   //  -- esp[(argc - n) * 8] : arg[n] (zero-based)
   //  -- esp[(argc + 1) * 8] : receiver
@@ -1335,27 +1594,32 @@
     __ mov(ebx, Operand(esp, ecx, times_pointer_size, 0));
 
     // Load the double value of the parameter into xmm1, maybe converting the
-    // parameter to a number first using the ToNumberStub if necessary.
+    // parameter to a number first using the ToNumber builtin if necessary.
     Label convert, convert_smi, convert_number, done_convert;
     __ bind(&convert);
     __ JumpIfSmi(ebx, &convert_smi);
     __ JumpIfRoot(FieldOperand(ebx, HeapObject::kMapOffset),
                   Heap::kHeapNumberMapRootIndex, &convert_number);
     {
-      // Parameter is not a Number, use the ToNumberStub to convert it.
-      FrameScope scope(masm, StackFrame::INTERNAL);
+      // Parameter is not a Number, use the ToNumber builtin to convert it.
+      FrameScope scope(masm, StackFrame::MANUAL);
+      __ Push(ebp);
+      __ Move(ebp, esp);
+      __ Push(esi);
+      __ Push(edi);
       __ SmiTag(eax);
       __ SmiTag(ecx);
       __ Push(eax);
       __ Push(ecx);
       __ Push(edx);
       __ mov(eax, ebx);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
       __ mov(ebx, eax);
       __ Pop(edx);
       __ Pop(ecx);
       __ Pop(eax);
+      __ Pop(edi);
+      __ Pop(esi);
       {
         // Restore the double accumulator value (xmm0).
         Label restore_smi, done_restore;
@@ -1370,6 +1634,7 @@
       }
       __ SmiUntag(ecx);
       __ SmiUntag(eax);
+      __ leave();
     }
     __ jmp(&convert);
     __ bind(&convert_number);
@@ -1403,8 +1668,10 @@
 
     // Left and right hand side are equal, check for -0 vs. +0.
     __ bind(&compare_equal);
+    __ Push(edi);  // Preserve function in edi.
     __ movmskpd(edi, reg);
     __ test(edi, Immediate(1));
+    __ Pop(edi);
     __ j(not_zero, &compare_swap);
 
     __ bind(&done_compare);
@@ -1444,8 +1711,7 @@
   }
 
   // 2a. Convert the first argument to a number.
-  ToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
+  __ Jump(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
 
   // 2b. No arguments, return +0 (already in eax).
   __ bind(&no_arguments);
@@ -1495,8 +1761,7 @@
       __ Push(edi);
       __ Push(edx);
       __ Move(eax, ebx);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
       __ Move(ebx, eax);
       __ Pop(edx);
       __ Pop(edi);
@@ -2359,6 +2624,109 @@
           RelocInfo::CODE_TARGET);
 }
 
+// static
+void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- edx    : requested object size (untagged)
+  //  -- esp[0] : return address
+  // -----------------------------------
+  __ SmiTag(edx);
+  __ PopReturnAddressTo(ecx);
+  __ Push(edx);
+  __ PushReturnAddressFrom(ecx);
+  __ Move(esi, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInNewSpace);
+}
+
+// static
+void Builtins::Generate_AllocateInOldSpace(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- edx    : requested object size (untagged)
+  //  -- esp[0] : return address
+  // -----------------------------------
+  __ SmiTag(edx);
+  __ PopReturnAddressTo(ecx);
+  __ Push(edx);
+  __ Push(Smi::FromInt(AllocateTargetSpace::encode(OLD_SPACE)));
+  __ PushReturnAddressFrom(ecx);
+  __ Move(esi, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInTargetSpace);
+}
+
+// static
+void Builtins::Generate_StringToNumber(MacroAssembler* masm) {
+  // The StringToNumber stub takes one argument in eax.
+  __ AssertString(eax);
+
+  // Check if string has a cached array index.
+  Label runtime;
+  __ test(FieldOperand(eax, String::kHashFieldOffset),
+          Immediate(String::kContainsCachedArrayIndexMask));
+  __ j(not_zero, &runtime, Label::kNear);
+  __ mov(eax, FieldOperand(eax, String::kHashFieldOffset));
+  __ IndexFromHash(eax, eax);
+  __ Ret();
+
+  __ bind(&runtime);
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ push(eax);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kStringToNumber);
+  }
+  __ Ret();
+}
+
+// static
+void Builtins::Generate_ToNumber(MacroAssembler* masm) {
+  // The ToNumber stub takes one argument in eax.
+  Label not_smi;
+  __ JumpIfNotSmi(eax, &not_smi, Label::kNear);
+  __ Ret();
+  __ bind(&not_smi);
+
+  Label not_heap_number;
+  __ CompareMap(eax, masm->isolate()->factory()->heap_number_map());
+  __ j(not_equal, &not_heap_number, Label::kNear);
+  __ Ret();
+  __ bind(&not_heap_number);
+
+  __ Jump(masm->isolate()->builtins()->NonNumberToNumber(),
+          RelocInfo::CODE_TARGET);
+}
+
+// static
+void Builtins::Generate_NonNumberToNumber(MacroAssembler* masm) {
+  // The NonNumberToNumber stub takes one argument in eax.
+  __ AssertNotNumber(eax);
+
+  Label not_string;
+  __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edi);
+  // eax: object
+  // edi: object map
+  __ j(above_equal, &not_string, Label::kNear);
+  __ Jump(masm->isolate()->builtins()->StringToNumber(),
+          RelocInfo::CODE_TARGET);
+  __ bind(&not_string);
+
+  Label not_oddball;
+  __ CmpInstanceType(edi, ODDBALL_TYPE);
+  __ j(not_equal, &not_oddball, Label::kNear);
+  __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset));
+  __ Ret();
+  __ bind(&not_oddball);
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ push(eax);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kToNumber);
+  }
+  __ Ret();
+}
 
 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
   // ----------- S t a t e -------------
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 53b35a3..5761b16 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -22,67 +22,16 @@
 namespace v8 {
 namespace internal {
 
+#define __ ACCESS_MASM(masm)
 
-static void InitializeArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  // register state
-  // eax -- number of arguments
-  // edi -- function
-  // ebx -- allocation site with elements kind
-  Address deopt_handler = Runtime::FunctionForId(
-      Runtime::kArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(eax, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-
-static void InitializeInternalArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  // register state
-  // eax -- number of arguments
-  // edi -- constructor function
-  Address deopt_handler = Runtime::FunctionForId(
-      Runtime::kInternalArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(eax, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-
-void ArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 0);
-}
-
-
-void ArraySingleArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 1);
-}
-
-
-void ArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-void InternalArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0);
+void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
+  __ pop(ecx);
+  __ mov(MemOperand(esp, eax, times_4, 0), edi);
+  __ push(edi);
+  __ push(ebx);
+  __ push(ecx);
+  __ add(eax, Immediate(3));
+  __ TailCallRuntime(Runtime::kNewArray);
 }
 
 void FastArrayPushStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
@@ -90,21 +39,12 @@
   descriptor->Initialize(eax, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-void InternalArraySingleArgumentConstructorStub::InitializeDescriptor(
+void FastFunctionBindStub::InitializeDescriptor(
     CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1);
+  Address deopt_handler = Runtime::FunctionForId(Runtime::kFunctionBind)->entry;
+  descriptor->Initialize(eax, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-
-void InternalArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-#define __ ACCESS_MASM(masm)
-
-
 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm,
                                                ExternalReference miss) {
   // Update the static counter each time a new code stub is generated.
@@ -691,7 +631,6 @@
                                           &miss,  // When not a string.
                                           &miss,  // When not a number.
                                           &miss,  // When index out of range.
-                                          STRING_INDEX_IS_ARRAY_INDEX,
                                           RECEIVER_IS_STRING);
   char_at_generator.GenerateFast(masm);
   __ ret(0);
@@ -1480,6 +1419,7 @@
   // edi : the function to call
   Isolate* isolate = masm->isolate();
   Label initialize, done, miss, megamorphic, not_array_function;
+  Label done_increment_count, done_initialize_count;
 
   // Load the cache state into ecx.
   __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
@@ -1492,7 +1432,7 @@
   // type-feedback-vector.h).
   Label check_allocation_site;
   __ cmp(edi, FieldOperand(ecx, WeakCell::kValueOffset));
-  __ j(equal, &done, Label::kFar);
+  __ j(equal, &done_increment_count, Label::kFar);
   __ CompareRoot(ecx, Heap::kmegamorphic_symbolRootIndex);
   __ j(equal, &done, Label::kFar);
   __ CompareRoot(FieldOperand(ecx, HeapObject::kMapOffset),
@@ -1515,7 +1455,7 @@
   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx);
   __ cmp(edi, ecx);
   __ j(not_equal, &megamorphic);
-  __ jmp(&done, Label::kFar);
+  __ jmp(&done_increment_count, Label::kFar);
 
   __ bind(&miss);
 
@@ -1544,11 +1484,25 @@
   // slot.
   CreateAllocationSiteStub create_stub(isolate);
   CallStubInRecordCallTarget(masm, &create_stub);
-  __ jmp(&done);
+  __ jmp(&done_initialize_count);
 
   __ bind(&not_array_function);
   CreateWeakCellStub weak_cell_stub(isolate);
   CallStubInRecordCallTarget(masm, &weak_cell_stub);
+  __ bind(&done_initialize_count);
+
+  // Initialize the call counter.
+  __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
+                      FixedArray::kHeaderSize + kPointerSize),
+         Immediate(Smi::FromInt(1)));
+  __ jmp(&done);
+
+  __ bind(&done_increment_count);
+  // Increment the call count for monomorphic function calls.
+  __ add(FieldOperand(ebx, edx, times_half_pointer_size,
+                      FixedArray::kHeaderSize + kPointerSize),
+         Immediate(Smi::FromInt(1)));
+
   __ bind(&done);
 }
 
@@ -1612,7 +1566,7 @@
   // Increment the call count for monomorphic function calls.
   __ add(FieldOperand(ebx, edx, times_half_pointer_size,
                       FixedArray::kHeaderSize + kPointerSize),
-         Immediate(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+         Immediate(Smi::FromInt(1)));
 
   __ mov(ebx, ecx);
   __ mov(edx, edi);
@@ -1660,7 +1614,7 @@
   // Increment the call count for monomorphic function calls.
   __ add(FieldOperand(ebx, edx, times_half_pointer_size,
                       FixedArray::kHeaderSize + kPointerSize),
-         Immediate(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+         Immediate(Smi::FromInt(1)));
 
   __ bind(&call_function);
   __ Set(eax, argc);
@@ -1731,7 +1685,7 @@
   // Initialize the call counter.
   __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
                       FixedArray::kHeaderSize + kPointerSize),
-         Immediate(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+         Immediate(Smi::FromInt(1)));
 
   // Store the function. Use a stub since we need a frame for allocation.
   // ebx - vector
@@ -1785,7 +1739,7 @@
   StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
   StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
   // It is important that the store buffer overflow stubs are generated first.
-  ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
+  CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate);
   CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
   CreateWeakCellStub::GenerateAheadOfTime(isolate);
   BinaryOpICStub::GenerateAheadOfTime(isolate);
@@ -2057,129 +2011,6 @@
 }
 
 
-void InstanceOfStub::Generate(MacroAssembler* masm) {
-  Register const object = edx;                       // Object (lhs).
-  Register const function = eax;                     // Function (rhs).
-  Register const object_map = ecx;                   // Map of {object}.
-  Register const function_map = ebx;                 // Map of {function}.
-  Register const function_prototype = function_map;  // Prototype of {function}.
-  Register const scratch = edi;
-
-  DCHECK(object.is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(function.is(InstanceOfDescriptor::RightRegister()));
-
-  // Check if {object} is a smi.
-  Label object_is_smi;
-  __ JumpIfSmi(object, &object_is_smi, Label::kNear);
-
-  // Lookup the {function} and the {object} map in the global instanceof cache.
-  // Note: This is safe because we clear the global instanceof cache whenever
-  // we change the prototype of any object.
-  Label fast_case, slow_case;
-  __ mov(object_map, FieldOperand(object, HeapObject::kMapOffset));
-  __ CompareRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex);
-  __ j(not_equal, &fast_case, Label::kNear);
-  __ CompareRoot(object_map, scratch, Heap::kInstanceofCacheMapRootIndex);
-  __ j(not_equal, &fast_case, Label::kNear);
-  __ LoadRoot(eax, Heap::kInstanceofCacheAnswerRootIndex);
-  __ ret(0);
-
-  // If {object} is a smi we can safely return false if {function} is a JS
-  // function, otherwise we have to miss to the runtime and throw an exception.
-  __ bind(&object_is_smi);
-  __ JumpIfSmi(function, &slow_case);
-  __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map);
-  __ j(not_equal, &slow_case);
-  __ LoadRoot(eax, Heap::kFalseValueRootIndex);
-  __ ret(0);
-
-  // Fast-case: The {function} must be a valid JSFunction.
-  __ bind(&fast_case);
-  __ JumpIfSmi(function, &slow_case);
-  __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map);
-  __ j(not_equal, &slow_case);
-
-  // Go to the runtime if the function is not a constructor.
-  __ test_b(FieldOperand(function_map, Map::kBitFieldOffset),
-            Immediate(1 << Map::kIsConstructor));
-  __ j(zero, &slow_case);
-
-  // Ensure that {function} has an instance prototype.
-  __ test_b(FieldOperand(function_map, Map::kBitFieldOffset),
-            Immediate(1 << Map::kHasNonInstancePrototype));
-  __ j(not_zero, &slow_case);
-
-  // Get the "prototype" (or initial map) of the {function}.
-  __ mov(function_prototype,
-         FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
-  __ AssertNotSmi(function_prototype);
-
-  // Resolve the prototype if the {function} has an initial map.  Afterwards the
-  // {function_prototype} will be either the JSReceiver prototype object or the
-  // hole value, which means that no instances of the {function} were created so
-  // far and hence we should return false.
-  Label function_prototype_valid;
-  Register const function_prototype_map = scratch;
-  __ CmpObjectType(function_prototype, MAP_TYPE, function_prototype_map);
-  __ j(not_equal, &function_prototype_valid, Label::kNear);
-  __ mov(function_prototype,
-         FieldOperand(function_prototype, Map::kPrototypeOffset));
-  __ bind(&function_prototype_valid);
-  __ AssertNotSmi(function_prototype);
-
-  // Update the global instanceof cache with the current {object} map and
-  // {function}.  The cached answer will be set when it is known below.
-  __ StoreRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex);
-  __ StoreRoot(object_map, scratch, Heap::kInstanceofCacheMapRootIndex);
-
-  // Loop through the prototype chain looking for the {function} prototype.
-  // Assume true, and change to false if not found.
-  Label done, loop, fast_runtime_fallback;
-  __ mov(eax, isolate()->factory()->true_value());
-  __ bind(&loop);
-
-  // Check if the object needs to be access checked.
-  __ test_b(FieldOperand(object_map, Map::kBitFieldOffset),
-            Immediate(1 << Map::kIsAccessCheckNeeded));
-  __ j(not_zero, &fast_runtime_fallback, Label::kNear);
-  // Check if the current object is a Proxy.
-  __ CmpInstanceType(object_map, JS_PROXY_TYPE);
-  __ j(equal, &fast_runtime_fallback, Label::kNear);
-
-  __ mov(object, FieldOperand(object_map, Map::kPrototypeOffset));
-  __ cmp(object, function_prototype);
-  __ j(equal, &done, Label::kNear);
-  __ mov(object_map, FieldOperand(object, HeapObject::kMapOffset));
-  __ cmp(object, isolate()->factory()->null_value());
-  __ j(not_equal, &loop);
-  __ mov(eax, isolate()->factory()->false_value());
-
-  __ bind(&done);
-  __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex);
-  __ ret(0);
-
-  // Found Proxy or access check needed: Call the runtime.
-  __ bind(&fast_runtime_fallback);
-  __ PopReturnAddressTo(scratch);
-  __ Push(object);
-  __ Push(function_prototype);
-  __ PushReturnAddressFrom(scratch);
-  // Invalidate the instanceof cache.
-  __ Move(eax, Immediate(Smi::FromInt(0)));
-  __ StoreRoot(eax, scratch, Heap::kInstanceofCacheFunctionRootIndex);
-  __ TailCallRuntime(Runtime::kHasInPrototypeChain);
-
-  // Slow-case: Call the %InstanceOf runtime function.
-  __ bind(&slow_case);
-  __ PopReturnAddressTo(scratch);
-  __ Push(object);
-  __ Push(function);
-  __ PushReturnAddressFrom(scratch);
-  __ TailCallRuntime(is_es6_instanceof() ? Runtime::kOrdinaryHasInstance
-                                         : Runtime::kInstanceOf);
-}
-
-
 // -------------------------------------------------------------------------
 // StringCharCodeAtGenerator
 
@@ -2236,13 +2067,7 @@
   }
   __ push(object_);
   __ push(index_);  // Consumed by runtime conversion function.
-  if (index_flags_ == STRING_INDEX_IS_NUMBER) {
-    __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero);
-  } else {
-    DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
-    // NumberToSmi discards numbers that are not exact integers.
-    __ CallRuntime(Runtime::kNumberToSmi);
-  }
+  __ CallRuntime(Runtime::kNumberToSmi);
   if (!index_.is(eax)) {
     // Save the conversion result before the pop instructions below
     // have a chance to overwrite it.
@@ -2575,77 +2400,12 @@
   // ecx: sub string length (smi)
   // edx: from index (smi)
   StringCharAtGenerator generator(eax, edx, ecx, eax, &runtime, &runtime,
-                                  &runtime, STRING_INDEX_IS_NUMBER,
-                                  RECEIVER_IS_STRING);
+                                  &runtime, RECEIVER_IS_STRING);
   generator.GenerateFast(masm);
   __ ret(3 * kPointerSize);
   generator.SkipSlow(masm, &runtime);
 }
 
-
-void ToNumberStub::Generate(MacroAssembler* masm) {
-  // The ToNumber stub takes one argument in eax.
-  Label not_smi;
-  __ JumpIfNotSmi(eax, &not_smi, Label::kNear);
-  __ Ret();
-  __ bind(&not_smi);
-
-  Label not_heap_number;
-  __ CompareMap(eax, masm->isolate()->factory()->heap_number_map());
-  __ j(not_equal, &not_heap_number, Label::kNear);
-  __ Ret();
-  __ bind(&not_heap_number);
-
-  NonNumberToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
-}
-
-void NonNumberToNumberStub::Generate(MacroAssembler* masm) {
-  // The NonNumberToNumber stub takes one argument in eax.
-  __ AssertNotNumber(eax);
-
-  Label not_string;
-  __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edi);
-  // eax: object
-  // edi: object map
-  __ j(above_equal, &not_string, Label::kNear);
-  StringToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
-  __ bind(&not_string);
-
-  Label not_oddball;
-  __ CmpInstanceType(edi, ODDBALL_TYPE);
-  __ j(not_equal, &not_oddball, Label::kNear);
-  __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset));
-  __ Ret();
-  __ bind(&not_oddball);
-
-  __ pop(ecx);   // Pop return address.
-  __ push(eax);  // Push argument.
-  __ push(ecx);  // Push return address.
-  __ TailCallRuntime(Runtime::kToNumber);
-}
-
-void StringToNumberStub::Generate(MacroAssembler* masm) {
-  // The StringToNumber stub takes one argument in eax.
-  __ AssertString(eax);
-
-  // Check if string has a cached array index.
-  Label runtime;
-  __ test(FieldOperand(eax, String::kHashFieldOffset),
-          Immediate(String::kContainsCachedArrayIndexMask));
-  __ j(not_zero, &runtime, Label::kNear);
-  __ mov(eax, FieldOperand(eax, String::kHashFieldOffset));
-  __ IndexFromHash(eax, eax);
-  __ Ret();
-
-  __ bind(&runtime);
-  __ PopReturnAddressTo(ecx);     // Pop return address.
-  __ Push(eax);                   // Push argument.
-  __ PushReturnAddressFrom(ecx);  // Push return address.
-  __ TailCallRuntime(Runtime::kStringToNumber);
-}
-
 void ToStringStub::Generate(MacroAssembler* masm) {
   // The ToString stub takes one argument in eax.
   Label is_number;
@@ -2852,7 +2612,7 @@
   // Load ecx with the allocation site.  We stick an undefined dummy value here
   // and replace it with the real allocation site later when we instantiate this
   // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate().
-  __ mov(ecx, handle(isolate()->heap()->undefined_value()));
+  __ mov(ecx, isolate()->factory()->undefined_value());
 
   // Make sure that we actually patched the allocation site.
   if (FLAG_debug_code) {
@@ -3683,14 +3443,14 @@
 
 void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  LoadICStub stub(isolate(), state());
+  LoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate(), state());
+  KeyedLoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -3842,8 +3602,8 @@
   __ j(not_equal, &miss);
   __ push(slot);
   __ push(vector);
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::LOAD_IC, code_flags,
                                                receiver, name, vector, scratch);
   __ pop(vector);
@@ -4103,8 +3863,8 @@
   __ pop(value);
   __ push(slot);
   __ push(vector);
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, code_flags,
                                                receiver, key, slot, no_reg);
   __ pop(vector);
@@ -4466,19 +4226,14 @@
   }
 }
 
-
-void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
+void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
   ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
       isolate);
   ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
       isolate);
-  ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
-      isolate);
-}
+  ArrayNArgumentsConstructorStub stub(isolate);
+  stub.GetCode();
 
-
-void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
-    Isolate* isolate) {
   ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS };
   for (int i = 0; i < 2; i++) {
     // For internal arrays we only need a few things
@@ -4486,8 +4241,6 @@
     stubh1.GetCode();
     InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]);
     stubh2.GetCode();
-    InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]);
-    stubh3.GetCode();
   }
 }
 
@@ -4507,13 +4260,15 @@
     CreateArrayDispatchOneArgument(masm, mode);
 
     __ bind(&not_one_case);
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else if (argument_count() == NONE) {
     CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
   } else if (argument_count() == ONE) {
     CreateArrayDispatchOneArgument(masm, mode);
   } else if (argument_count() == MORE_THAN_ONE) {
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else {
     UNREACHABLE();
   }
@@ -4625,7 +4380,7 @@
   __ TailCallStub(&stub1);
 
   __ bind(&not_one_case);
-  InternalArrayNArgumentsConstructorStub stubN(isolate(), kind);
+  ArrayNArgumentsConstructorStub stubN(isolate());
   __ TailCallStub(&stubN);
 }
 
@@ -4714,16 +4469,16 @@
   __ bind(&done_allocate);
 
   // Initialize the JSObject fields.
-  __ mov(Operand(eax, JSObject::kMapOffset), ecx);
-  __ mov(Operand(eax, JSObject::kPropertiesOffset),
+  __ mov(FieldOperand(eax, JSObject::kMapOffset), ecx);
+  __ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
          masm->isolate()->factory()->empty_fixed_array());
-  __ mov(Operand(eax, JSObject::kElementsOffset),
+  __ mov(FieldOperand(eax, JSObject::kElementsOffset),
          masm->isolate()->factory()->empty_fixed_array());
   STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize);
-  __ lea(ebx, Operand(eax, JSObject::kHeaderSize));
+  __ lea(ebx, FieldOperand(eax, JSObject::kHeaderSize));
 
   // ----------- S t a t e -------------
-  //  -- eax    : result (untagged)
+  //  -- eax    : result (tagged)
   //  -- ebx    : result fields (untagged)
   //  -- edi    : result end (untagged)
   //  -- ecx    : initial map
@@ -4741,10 +4496,6 @@
     // Initialize all in-object fields with undefined.
     __ LoadRoot(edx, Heap::kUndefinedValueRootIndex);
     __ InitializeFieldsWithFiller(ebx, edi, edx);
-
-    // Add the object tag to make the JSObject real.
-    STATIC_ASSERT(kHeapObjectTag == 1);
-    __ inc(eax);
     __ Ret();
   }
   __ bind(&slack_tracking);
@@ -4767,10 +4518,6 @@
     __ LoadRoot(edi, Heap::kOnePointerFillerMapRootIndex);
     __ InitializeFieldsWithFiller(ebx, edx, edi);
 
-    // Add the object tag to make the JSObject real.
-    STATIC_ASSERT(kHeapObjectTag == 1);
-    __ inc(eax);
-
     // Check if we can finalize the instance size.
     Label finalize;
     STATIC_ASSERT(Map::kSlackTrackingCounterEnd == 1);
@@ -4801,10 +4548,10 @@
     __ CallRuntime(Runtime::kAllocateInNewSpace);
     __ Pop(ecx);
   }
-  STATIC_ASSERT(kHeapObjectTag == 1);
-  __ dec(eax);
   __ movzx_b(ebx, FieldOperand(ecx, Map::kInstanceSizeOffset));
   __ lea(edi, Operand(eax, ebx, times_pointer_size, 0));
+  STATIC_ASSERT(kHeapObjectTag == 1);
+  __ dec(edi);
   __ jmp(&done_allocate);
 
   // Fall back to %NewObject.
@@ -4826,19 +4573,19 @@
   // -----------------------------------
   __ AssertFunction(edi);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make edx point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ mov(edx, ebp);
-    __ jmp(&loop_entry, Label::kNear);
-    __ bind(&loop);
+  // Make edx point to the JavaScript frame.
+  __ mov(edx, ebp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ mov(edx, Operand(edx, StandardFrameConstants::kCallerFPOffset));
-    __ bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ cmp(edi, Operand(edx, StandardFrameConstants::kFunctionOffset));
-    __ j(not_equal, &loop);
+    __ j(equal, &ok);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
   }
 
   // Check if we have rest parameters (only possible if we have an
@@ -4868,7 +4615,7 @@
 
     // Allocate an empty rest parameter array.
     Label allocate, done_allocate;
-    __ Allocate(JSArray::kSize, eax, edx, ecx, &allocate, TAG_OBJECT);
+    __ Allocate(JSArray::kSize, eax, edx, ecx, &allocate, NO_ALLOCATION_FLAGS);
     __ bind(&done_allocate);
 
     // Setup the rest parameter array in rax.
@@ -4910,7 +4657,7 @@
     Label allocate, done_allocate;
     __ lea(ecx, Operand(eax, times_half_pointer_size,
                         JSArray::kSize + FixedArray::kHeaderSize));
-    __ Allocate(ecx, edx, edi, no_reg, &allocate, TAG_OBJECT);
+    __ Allocate(ecx, edx, edi, no_reg, &allocate, NO_ALLOCATION_FLAGS);
     __ bind(&done_allocate);
 
     // Setup the elements array in edx.
@@ -4946,8 +4693,11 @@
     __ mov(eax, edi);
     __ Ret();
 
-    // Fall back to %AllocateInNewSpace.
+    // Fall back to %AllocateInNewSpace (if not too big).
+    Label too_big_for_new_space;
     __ bind(&allocate);
+    __ cmp(ecx, Immediate(Page::kMaxRegularHeapObjectSize));
+    __ j(greater, &too_big_for_new_space);
     {
       FrameScope scope(masm, StackFrame::INTERNAL);
       __ SmiTag(ecx);
@@ -4960,6 +4710,22 @@
       __ Pop(eax);
     }
     __ jmp(&done_allocate);
+
+    // Fall back to %NewRestParameter.
+    __ bind(&too_big_for_new_space);
+    __ PopReturnAddressTo(ecx);
+    // We reload the function from the caller frame due to register pressure
+    // within this stub. This is the slow path, hence reloading is preferable.
+    if (skip_stub_frame()) {
+      // For Ignition we need to skip the handler/stub frame to reach the
+      // JavaScript frame for the function.
+      __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
+      __ Push(Operand(edx, StandardFrameConstants::kFunctionOffset));
+    } else {
+      __ Push(Operand(ebp, StandardFrameConstants::kFunctionOffset));
+    }
+    __ PushReturnAddressFrom(ecx);
+    __ TailCallRuntime(Runtime::kNewRestParameter);
   }
 }
 
@@ -4973,35 +4739,50 @@
   // -----------------------------------
   __ AssertFunction(edi);
 
+  // Make ecx point to the JavaScript frame.
+  __ mov(ecx, ebp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
+    __ mov(ecx, Operand(ecx, StandardFrameConstants::kCallerFPOffset));
+  }
+  if (FLAG_debug_code) {
+    Label ok;
+    __ cmp(edi, Operand(ecx, StandardFrameConstants::kFunctionOffset));
+    __ j(equal, &ok);
+    __ Abort(kInvalidFrameForFastNewSloppyArgumentsStub);
+    __ bind(&ok);
+  }
+
   // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub.
-  __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
-  __ mov(ecx,
-         FieldOperand(ecx, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ lea(edx, Operand(ebp, ecx, times_half_pointer_size,
+  __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+  __ mov(ebx,
+         FieldOperand(ebx, SharedFunctionInfo::kFormalParameterCountOffset));
+  __ lea(edx, Operand(ecx, ebx, times_half_pointer_size,
                       StandardFrameConstants::kCallerSPOffset));
 
-  // ecx : number of parameters (tagged)
+  // ebx : number of parameters (tagged)
   // edx : parameters pointer
   // edi : function
+  // ecx : JavaScript frame pointer.
   // esp[0] : return address
 
   // Check if the calling frame is an arguments adaptor frame.
   Label adaptor_frame, try_allocate, runtime;
-  __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
-  __ mov(eax, Operand(ebx, CommonFrameConstants::kContextOrFrameTypeOffset));
+  __ mov(eax, Operand(ecx, StandardFrameConstants::kCallerFPOffset));
+  __ mov(eax, Operand(eax, CommonFrameConstants::kContextOrFrameTypeOffset));
   __ cmp(eax, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
   __ j(equal, &adaptor_frame, Label::kNear);
 
   // No adaptor, parameter count = argument count.
-  __ mov(ebx, ecx);
-  __ push(ecx);
+  __ mov(ecx, ebx);
+  __ push(ebx);
   __ jmp(&try_allocate, Label::kNear);
 
   // We have an adaptor frame. Patch the parameters pointer.
   __ bind(&adaptor_frame);
-  __ mov(ebx, ecx);
-  __ push(ecx);
-  __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
+  __ push(ebx);
+  __ mov(edx, Operand(ecx, StandardFrameConstants::kCallerFPOffset));
   __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
   __ lea(edx, Operand(edx, ecx, times_2,
                       StandardFrameConstants::kCallerSPOffset));
@@ -5035,7 +4816,7 @@
   __ add(ebx, Immediate(JSSloppyArgumentsObject::kSize));
 
   // Do the allocation of all three objects in one go.
-  __ Allocate(ebx, eax, edi, no_reg, &runtime, TAG_OBJECT);
+  __ Allocate(ebx, eax, edi, no_reg, &runtime, NO_ALLOCATION_FLAGS);
 
   // eax = address of new object(s) (tagged)
   // ecx = argument count (smi-tagged)
@@ -5214,19 +4995,19 @@
   // -----------------------------------
   __ AssertFunction(edi);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make edx point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ mov(edx, ebp);
-    __ jmp(&loop_entry, Label::kNear);
-    __ bind(&loop);
+  // Make edx point to the JavaScript frame.
+  __ mov(edx, ebp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ mov(edx, Operand(edx, StandardFrameConstants::kCallerFPOffset));
-    __ bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ cmp(edi, Operand(edx, StandardFrameConstants::kFunctionOffset));
-    __ j(not_equal, &loop);
+    __ j(equal, &ok);
+    __ Abort(kInvalidFrameForFastNewStrictArgumentsStub);
+    __ bind(&ok);
   }
 
   // Check if we have an arguments adaptor frame below the function frame.
@@ -5265,7 +5046,7 @@
   __ lea(ecx,
          Operand(eax, times_half_pointer_size,
                  JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
-  __ Allocate(ecx, edx, edi, no_reg, &allocate, TAG_OBJECT);
+  __ Allocate(ecx, edx, edi, no_reg, &allocate, NO_ALLOCATION_FLAGS);
   __ bind(&done_allocate);
 
   // Setup the elements array in edx.
@@ -5301,8 +5082,11 @@
   __ mov(eax, edi);
   __ Ret();
 
-  // Fall back to %AllocateInNewSpace.
+  // Fall back to %AllocateInNewSpace (if not too big).
+  Label too_big_for_new_space;
   __ bind(&allocate);
+  __ cmp(ecx, Immediate(Page::kMaxRegularHeapObjectSize));
+  __ j(greater, &too_big_for_new_space);
   {
     FrameScope scope(masm, StackFrame::INTERNAL);
     __ SmiTag(ecx);
@@ -5315,37 +5099,22 @@
     __ Pop(eax);
   }
   __ jmp(&done_allocate);
-}
 
-
-void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
-  Register context_reg = esi;
-  Register slot_reg = ebx;
-  Register result_reg = eax;
-  Label slow_case;
-
-  // Go up context chain to the script context.
-  for (int i = 0; i < depth(); ++i) {
-    __ mov(result_reg, ContextOperand(context_reg, Context::PREVIOUS_INDEX));
-    context_reg = result_reg;
+  // Fall back to %NewStrictArguments.
+  __ bind(&too_big_for_new_space);
+  __ PopReturnAddressTo(ecx);
+  // We reload the function from the caller frame due to register pressure
+  // within this stub. This is the slow path, hence reloading is preferable.
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
+    __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
+    __ Push(Operand(edx, StandardFrameConstants::kFunctionOffset));
+  } else {
+    __ Push(Operand(ebp, StandardFrameConstants::kFunctionOffset));
   }
-
-  // Load the PropertyCell value at the specified slot.
-  __ mov(result_reg, ContextOperand(context_reg, slot_reg));
-  __ mov(result_reg, FieldOperand(result_reg, PropertyCell::kValueOffset));
-
-  // Check that value is not the_hole.
-  __ CompareRoot(result_reg, Heap::kTheHoleValueRootIndex);
-  __ j(equal, &slow_case, Label::kNear);
-  __ Ret();
-
-  // Fallback to the runtime.
-  __ bind(&slow_case);
-  __ SmiTag(slot_reg);
-  __ Pop(result_reg);  // Pop return address.
-  __ Push(slot_reg);
-  __ Push(result_reg);  // Push return address.
-  __ TailCallRuntime(Runtime::kLoadGlobalViaContext);
+  __ PushReturnAddressFrom(ecx);
+  __ TailCallRuntime(Runtime::kNewStrictArguments);
 }
 
 
@@ -5686,9 +5455,14 @@
   STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
   STATIC_ASSERT(FCA::kIsolateIndex == 1);
   STATIC_ASSERT(FCA::kHolderIndex == 0);
-  STATIC_ASSERT(FCA::kArgsLength == 7);
+  STATIC_ASSERT(FCA::kNewTargetIndex == 7);
+  STATIC_ASSERT(FCA::kArgsLength == 8);
 
   __ pop(return_address);
+
+  // new target
+  __ PushRoot(Heap::kUndefinedValueRootIndex);
+
   // context save.
   __ push(context);
 
@@ -5733,7 +5507,7 @@
 
   // Allocate the v8::Arguments structure in the arguments' space since
   // it's not controlled by GC.
-  const int kApiStackSpace = 4;
+  const int kApiStackSpace = 3;
 
   PrepareCallApiFunction(masm, kApiArgc + kApiStackSpace);
 
@@ -5744,8 +5518,6 @@
   __ mov(ApiParameterOperand(3), scratch);
   // FunctionCallbackInfo::length_.
   __ Move(ApiParameterOperand(4), Immediate(argc()));
-  // FunctionCallbackInfo::is_construct_call_.
-  __ Move(ApiParameterOperand(5), Immediate(0));
 
   // v8::InvocationCallback's argument.
   __ lea(scratch, ApiParameterOperand(2));
@@ -5765,8 +5537,8 @@
   }
   Operand return_value_operand(ebp, return_value_offset * kPointerSize);
   int stack_space = 0;
-  Operand is_construct_call_operand = ApiParameterOperand(5);
-  Operand* stack_space_operand = &is_construct_call_operand;
+  Operand length_operand = ApiParameterOperand(4);
+  Operand* stack_space_operand = &length_operand;
   stack_space = argc() + FCA::kArgsLength + 1;
   stack_space_operand = nullptr;
   CallApiFunctionAndReturn(masm, api_function_address, thunk_ref,
@@ -5777,14 +5549,34 @@
 
 
 void CallApiGetterStub::Generate(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- esp[0]                        : return address
-  //  -- esp[4]                        : name
-  //  -- esp[8 .. (8 + kArgsLength*4)] : v8::PropertyCallbackInfo::args_
-  //  -- ...
-  //  -- edx                           : api_function_address
-  // -----------------------------------
-  DCHECK(edx.is(ApiGetterDescriptor::function_address()));
+  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
+  // name below the exit frame to make GC aware of them.
+  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
+  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
+  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
+  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
+  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
+  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
+
+  Register receiver = ApiGetterDescriptor::ReceiverRegister();
+  Register holder = ApiGetterDescriptor::HolderRegister();
+  Register callback = ApiGetterDescriptor::CallbackRegister();
+  Register scratch = ebx;
+  DCHECK(!AreAliased(receiver, holder, callback, scratch));
+
+  __ pop(scratch);  // Pop return address to extend the frame.
+  __ push(receiver);
+  __ push(FieldOperand(callback, AccessorInfo::kDataOffset));
+  __ PushRoot(Heap::kUndefinedValueRootIndex);  // ReturnValue
+  // ReturnValue default value
+  __ PushRoot(Heap::kUndefinedValueRootIndex);
+  __ push(Immediate(ExternalReference::isolate_address(isolate())));
+  __ push(holder);
+  __ push(Immediate(Smi::FromInt(0)));  // should_throw_on_error -> false
+  __ push(FieldOperand(callback, AccessorInfo::kNameOffset));
+  __ push(scratch);  // Restore return address.
 
   // v8::PropertyCallbackInfo::args_ array and name handle.
   const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
@@ -5794,9 +5586,6 @@
   // active) in non-GCed stack space.
   const int kApiArgc = 3 + 1;
 
-  Register api_function_address = edx;
-  Register scratch = ebx;
-
   // Load address of v8::PropertyAccessorInfo::args_ array.
   __ lea(scratch, Operand(esp, 2 * kPointerSize));
 
@@ -5806,25 +5595,30 @@
   Operand info_object = ApiParameterOperand(3);
   __ mov(info_object, scratch);
 
+  // Name as handle.
   __ sub(scratch, Immediate(kPointerSize));
-  __ mov(ApiParameterOperand(0), scratch);  // name.
+  __ mov(ApiParameterOperand(0), scratch);
+  // Arguments pointer.
   __ lea(scratch, info_object);
-  __ mov(ApiParameterOperand(1), scratch);  // arguments pointer.
+  __ mov(ApiParameterOperand(1), scratch);
   // Reserve space for optional callback address parameter.
   Operand thunk_last_arg = ApiParameterOperand(2);
 
   ExternalReference thunk_ref =
       ExternalReference::invoke_accessor_getter_callback(isolate());
 
+  __ mov(scratch, FieldOperand(callback, AccessorInfo::kJsGetterOffset));
+  Register function_address = edx;
+  __ mov(function_address,
+         FieldOperand(scratch, Foreign::kForeignAddressOffset));
   // +3 is to skip prolog, return address and name handle.
   Operand return_value_operand(
       ebp, (PropertyCallbackArguments::kReturnValueOffset + 3) * kPointerSize);
-  CallApiFunctionAndReturn(masm, api_function_address, thunk_ref,
-                           thunk_last_arg, kStackUnwindSpace, nullptr,
-                           return_value_operand, NULL);
+  CallApiFunctionAndReturn(masm, function_address, thunk_ref, thunk_last_arg,
+                           kStackUnwindSpace, nullptr, return_value_operand,
+                           NULL);
 }
 
-
 #undef __
 
 }  // namespace internal
diff --git a/src/ia32/code-stubs-ia32.h b/src/ia32/code-stubs-ia32.h
index fc813f5..c1878f0 100644
--- a/src/ia32/code-stubs-ia32.h
+++ b/src/ia32/code-stubs-ia32.h
@@ -301,8 +301,8 @@
                                   Register r2,
                                   Register r3) {
       for (int i = 0; i < Register::kNumRegisters; i++) {
-        Register candidate = Register::from_code(i);
-        if (candidate.IsAllocatable()) {
+        if (RegisterConfiguration::Crankshaft()->IsAllocatableGeneralCode(i)) {
+          Register candidate = Register::from_code(i);
           if (candidate.is(ecx)) continue;
           if (candidate.is(r1)) continue;
           if (candidate.is(r2)) continue;
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index 2190531..18e5364 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -34,43 +34,6 @@
 #define __ masm.
 
 
-UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) {
-  size_t actual_size;
-  byte* buffer =
-      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
-  if (buffer == nullptr) return nullptr;
-  ExternalReference::InitializeMathExpData();
-
-  MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
-                      CodeObjectRequired::kNo);
-  // esp[1 * kPointerSize]: raw double input
-  // esp[0 * kPointerSize]: return address
-  {
-    XMMRegister input = xmm1;
-    XMMRegister result = xmm2;
-    __ movsd(input, Operand(esp, 1 * kPointerSize));
-    __ push(eax);
-    __ push(ebx);
-
-    MathExpGenerator::EmitMathExp(&masm, input, result, xmm0, eax, ebx);
-
-    __ pop(ebx);
-    __ pop(eax);
-    __ movsd(Operand(esp, 1 * kPointerSize), result);
-    __ fld_d(Operand(esp, 1 * kPointerSize));
-    __ Ret();
-  }
-
-  CodeDesc desc;
-  masm.GetCode(&desc);
-  DCHECK(!RelocInfo::RequiresRelocation(desc));
-
-  Assembler::FlushICache(isolate, buffer, actual_size);
-  base::OS::ProtectCode(buffer, actual_size);
-  return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
-}
-
-
 UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
   size_t actual_size;
   // Allocate buffer in executable space.
@@ -580,14 +543,14 @@
 
   __ push(eax);
   __ push(ebx);
+  __ push(esi);
 
   __ mov(edi, FieldOperand(edi, FixedArray::kLengthOffset));
 
   // Allocate new FixedDoubleArray.
   // edx: receiver
   // edi: length of source FixedArray (smi-tagged)
-  AllocationFlags flags =
-      static_cast<AllocationFlags>(TAG_OBJECT | DOUBLE_ALIGNMENT);
+  AllocationFlags flags = static_cast<AllocationFlags>(DOUBLE_ALIGNMENT);
   __ Allocate(FixedDoubleArray::kHeaderSize, times_8, edi,
               REGISTER_VALUE_IS_SMI, eax, ebx, no_reg, &gc_required, flags);
 
@@ -621,8 +584,9 @@
 
   // Call into runtime if GC is required.
   __ bind(&gc_required);
+
   // Restore registers before jumping into runtime.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  __ pop(esi);
   __ pop(ebx);
   __ pop(eax);
   __ jmp(fail);
@@ -657,12 +621,11 @@
   __ sub(edi, Immediate(Smi::FromInt(1)));
   __ j(not_sign, &loop);
 
+  // Restore registers.
+  __ pop(esi);
   __ pop(ebx);
   __ pop(eax);
 
-  // Restore esi.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-
   __ bind(&only_change_map);
   // eax: value
   // ebx: target map
@@ -714,7 +677,7 @@
   // Allocate new FixedArray.
   // ebx: length of source FixedDoubleArray (smi-tagged)
   __ lea(edi, Operand(ebx, times_2, FixedArray::kHeaderSize));
-  __ Allocate(edi, eax, esi, no_reg, &gc_required, TAG_OBJECT);
+  __ Allocate(edi, eax, esi, no_reg, &gc_required, NO_ALLOCATION_FLAGS);
 
   // eax: destination FixedArray
   // ebx: number of elements
@@ -928,64 +891,6 @@
   __ bind(&done);
 }
 
-
-static Operand ExpConstant(int index) {
-  return Operand::StaticVariable(ExternalReference::math_exp_constants(index));
-}
-
-
-void MathExpGenerator::EmitMathExp(MacroAssembler* masm,
-                                   XMMRegister input,
-                                   XMMRegister result,
-                                   XMMRegister double_scratch,
-                                   Register temp1,
-                                   Register temp2) {
-  DCHECK(!input.is(double_scratch));
-  DCHECK(!input.is(result));
-  DCHECK(!result.is(double_scratch));
-  DCHECK(!temp1.is(temp2));
-  DCHECK(ExternalReference::math_exp_constants(0).address() != NULL);
-  DCHECK(!masm->serializer_enabled());  // External references not serializable.
-
-  Label done;
-
-  __ movsd(double_scratch, ExpConstant(0));
-  __ xorpd(result, result);
-  __ ucomisd(double_scratch, input);
-  __ j(above_equal, &done);
-  __ ucomisd(input, ExpConstant(1));
-  __ movsd(result, ExpConstant(2));
-  __ j(above_equal, &done);
-  __ movsd(double_scratch, ExpConstant(3));
-  __ movsd(result, ExpConstant(4));
-  __ mulsd(double_scratch, input);
-  __ addsd(double_scratch, result);
-  __ movd(temp2, double_scratch);
-  __ subsd(double_scratch, result);
-  __ movsd(result, ExpConstant(6));
-  __ mulsd(double_scratch, ExpConstant(5));
-  __ subsd(double_scratch, input);
-  __ subsd(result, double_scratch);
-  __ movsd(input, double_scratch);
-  __ mulsd(input, double_scratch);
-  __ mulsd(result, input);
-  __ mov(temp1, temp2);
-  __ mulsd(result, ExpConstant(7));
-  __ subsd(result, double_scratch);
-  __ add(temp1, Immediate(0x1ff800));
-  __ addsd(result, ExpConstant(8));
-  __ and_(temp2, Immediate(0x7ff));
-  __ shr(temp1, 11);
-  __ shl(temp1, 20);
-  __ movd(input, temp1);
-  __ pshufd(input, input, static_cast<uint8_t>(0xe1));  // Order: 11 10 00 01
-  __ movsd(double_scratch, Operand::StaticArray(
-      temp2, times_8, ExternalReference::math_exp_log_table()));
-  __ orps(input, double_scratch);
-  __ mulsd(result, input);
-  __ bind(&done);
-}
-
 #undef __
 
 
diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h
index 133b1ad..46468e9 100644
--- a/src/ia32/codegen-ia32.h
+++ b/src/ia32/codegen-ia32.h
@@ -29,19 +29,6 @@
 };
 
 
-class MathExpGenerator : public AllStatic {
- public:
-  static void EmitMathExp(MacroAssembler* masm,
-                          XMMRegister input,
-                          XMMRegister result,
-                          XMMRegister double_scratch,
-                          Register temp1,
-                          Register temp2);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MathExpGenerator);
-};
-
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/ia32/deoptimizer-ia32.cc b/src/ia32/deoptimizer-ia32.cc
index 656d3e9..c14a2a1 100644
--- a/src/ia32/deoptimizer-ia32.cc
+++ b/src/ia32/deoptimizer-ia32.cc
@@ -196,8 +196,7 @@
 
   const int kDoubleRegsSize = kDoubleSize * XMMRegister::kMaxNumRegisters;
   __ sub(esp, Immediate(kDoubleRegsSize));
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
     int code = config->GetAllocatableDoubleCode(i);
     XMMRegister xmm_reg = XMMRegister::from_code(code);
diff --git a/src/ia32/disasm-ia32.cc b/src/ia32/disasm-ia32.cc
index 3cd0ac6..be3530c 100644
--- a/src/ia32/disasm-ia32.cc
+++ b/src/ia32/disasm-ia32.cc
@@ -8,6 +8,7 @@
 
 #if V8_TARGET_ARCH_IA32
 
+#include "src/base/compiler-specific.h"
 #include "src/disasm.h"
 
 namespace disasm {
@@ -29,18 +30,19 @@
 };
 
 static const ByteMnemonic two_operands_instr[] = {
-    {0x01, "add", OPER_REG_OP_ORDER},   {0x03, "add", REG_OPER_OP_ORDER},
-    {0x09, "or", OPER_REG_OP_ORDER},    {0x0B, "or", REG_OPER_OP_ORDER},
-    {0x13, "adc", REG_OPER_OP_ORDER},   {0x1B, "sbb", REG_OPER_OP_ORDER},
-    {0x21, "and", OPER_REG_OP_ORDER},   {0x23, "and", REG_OPER_OP_ORDER},
-    {0x29, "sub", OPER_REG_OP_ORDER},   {0x2A, "subb", REG_OPER_OP_ORDER},
-    {0x2B, "sub", REG_OPER_OP_ORDER},   {0x31, "xor", OPER_REG_OP_ORDER},
-    {0x33, "xor", REG_OPER_OP_ORDER},   {0x38, "cmpb", OPER_REG_OP_ORDER},
-    {0x39, "cmp", OPER_REG_OP_ORDER},   {0x3A, "cmpb", REG_OPER_OP_ORDER},
-    {0x3B, "cmp", REG_OPER_OP_ORDER},   {0x84, "test_b", REG_OPER_OP_ORDER},
-    {0x85, "test", REG_OPER_OP_ORDER},  {0x87, "xchg", REG_OPER_OP_ORDER},
-    {0x8A, "mov_b", REG_OPER_OP_ORDER}, {0x8B, "mov", REG_OPER_OP_ORDER},
-    {0x8D, "lea", REG_OPER_OP_ORDER},   {-1, "", UNSET_OP_ORDER}};
+    {0x01, "add", OPER_REG_OP_ORDER},  {0x03, "add", REG_OPER_OP_ORDER},
+    {0x09, "or", OPER_REG_OP_ORDER},   {0x0B, "or", REG_OPER_OP_ORDER},
+    {0x13, "adc", REG_OPER_OP_ORDER},  {0x1B, "sbb", REG_OPER_OP_ORDER},
+    {0x21, "and", OPER_REG_OP_ORDER},  {0x23, "and", REG_OPER_OP_ORDER},
+    {0x29, "sub", OPER_REG_OP_ORDER},  {0x2A, "subb", REG_OPER_OP_ORDER},
+    {0x2B, "sub", REG_OPER_OP_ORDER},  {0x31, "xor", OPER_REG_OP_ORDER},
+    {0x33, "xor", REG_OPER_OP_ORDER},  {0x38, "cmpb", OPER_REG_OP_ORDER},
+    {0x39, "cmp", OPER_REG_OP_ORDER},  {0x3A, "cmpb", REG_OPER_OP_ORDER},
+    {0x3B, "cmp", REG_OPER_OP_ORDER},  {0x84, "test_b", REG_OPER_OP_ORDER},
+    {0x85, "test", REG_OPER_OP_ORDER}, {0x86, "xchg_b", REG_OPER_OP_ORDER},
+    {0x87, "xchg", REG_OPER_OP_ORDER}, {0x8A, "mov_b", REG_OPER_OP_ORDER},
+    {0x8B, "mov", REG_OPER_OP_ORDER},  {0x8D, "lea", REG_OPER_OP_ORDER},
+    {-1, "", UNSET_OP_ORDER}};
 
 static const ByteMnemonic zero_operands_instr[] = {
   {0xC3, "ret", UNSET_OP_ORDER},
@@ -281,7 +283,7 @@
   bool vex_128() {
     DCHECK(vex_byte0_ == 0xc4 || vex_byte0_ == 0xc5);
     byte checked = vex_byte0_ == 0xc4 ? vex_byte2_ : vex_byte1_;
-    return (checked & 4) != 1;
+    return (checked & 4) == 0;
   }
 
   bool vex_none() {
@@ -389,8 +391,7 @@
   int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
   int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
   int AVXInstruction(byte* data);
-  void AppendToBuffer(const char* format, ...);
-
+  PRINTF_FORMAT(2, 3) void AppendToBuffer(const char* format, ...);
 
   void UnimplementedInstruction() {
     if (abort_on_unimplemented_) {
@@ -1231,6 +1232,10 @@
       return "shrd";  // 3-operand version.
     case 0xAB:
       return "bts";
+    case 0xB0:
+      return "cmpxchg_b";
+    case 0xB1:
+      return "cmpxchg";
     case 0xBC:
       return "bsf";
     case 0xBD:
@@ -1263,6 +1268,9 @@
     vex_byte0_ = *data;
     vex_byte1_ = *(data + 1);
     data += 2;
+  } else if (*data == 0xF0 /*lock*/) {
+    AppendToBuffer("lock ");
+    data++;
   }
 
   bool processed = true;  // Will be set to false if the current instruction
@@ -1274,7 +1282,7 @@
     const InstructionDesc& idesc = instruction_table_->Get(*data);
     switch (idesc.type) {
       case ZERO_OPERANDS_INSTR:
-        AppendToBuffer(idesc.mnem);
+        AppendToBuffer("%s", idesc.mnem);
         data++;
         break;
 
@@ -1495,6 +1503,18 @@
             } else {
               AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
             }
+          } else if (f0byte == 0xB0) {
+            // cmpxchg_b
+            data += 2;
+            AppendToBuffer("%s ", f0mnem);
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            data += PrintRightOperand(data);
+            AppendToBuffer(",%s", NameOfByteCPURegister(regop));
+          } else if (f0byte == 0xB1) {
+            // cmpxchg
+            data += 2;
+            data += PrintOperands(f0mnem, OPER_REG_OP_ORDER, data);
           } else if (f0byte == 0xBC) {
             data += 2;
             int mod, regop, rm;
@@ -1602,11 +1622,25 @@
         while (*data == 0x66) data++;
         if (*data == 0xf && data[1] == 0x1f) {
           AppendToBuffer("nop");  // 0x66 prefix
-        } else if (*data == 0x90) {
-          AppendToBuffer("nop");  // 0x66 prefix
-        } else if (*data == 0x8B) {
+        } else if (*data == 0x39) {
           data++;
-          data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data);
+          data += PrintOperands("cmpw", OPER_REG_OP_ORDER, data);
+        } else if (*data == 0x3B) {
+          data++;
+          data += PrintOperands("cmpw", REG_OPER_OP_ORDER, data);
+        } else if (*data == 0x81) {
+          data++;
+          AppendToBuffer("cmpw ");
+          data += PrintRightOperand(data);
+          int imm = *reinterpret_cast<int16_t*>(data);
+          AppendToBuffer(",0x%x", imm);
+          data += 2;
+        } else if (*data == 0x87) {
+          data++;
+          int mod, regop, rm;
+          get_modrm(*data, &mod, &regop, &rm);
+          AppendToBuffer("xchg_w %s,", NameOfCPURegister(regop));
+          data += PrintRightOperand(data);
         } else if (*data == 0x89) {
           data++;
           int mod, regop, rm;
@@ -1614,6 +1648,11 @@
           AppendToBuffer("mov_w ");
           data += PrintRightOperand(data);
           AppendToBuffer(",%s", NameOfCPURegister(regop));
+        } else if (*data == 0x8B) {
+          data++;
+          data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data);
+        } else if (*data == 0x90) {
+          AppendToBuffer("nop");  // 0x66 prefix
         } else if (*data == 0xC7) {
           data++;
           AppendToBuffer("%s ", "mov_w");
@@ -1876,6 +1915,9 @@
                            NameOfXMMRegister(regop),
                            NameOfXMMRegister(rm));
             data++;
+          } else if (*data == 0xB1) {
+            data++;
+            data += PrintOperands("cmpxchg_w", OPER_REG_OP_ORDER, data);
           } else {
             UnimplementedInstruction();
           }
@@ -2206,7 +2248,7 @@
 
 
 const char* NameConverter::NameOfAddress(byte* addr) const {
-  v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
+  v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
   return tmp_buffer_.start();
 }
 
@@ -2269,7 +2311,7 @@
     buffer[0] = '\0';
     byte* prev_pc = pc;
     pc += d.InstructionDecode(buffer, pc);
-    fprintf(f, "%p", prev_pc);
+    fprintf(f, "%p", static_cast<void*>(prev_pc));
     fprintf(f, "    ");
 
     for (byte* bp = prev_pc; bp < pc; bp++) {
diff --git a/src/ia32/interface-descriptors-ia32.cc b/src/ia32/interface-descriptors-ia32.cc
index 2748f90..98259c7 100644
--- a/src/ia32/interface-descriptors-ia32.cc
+++ b/src/ia32/interface-descriptors-ia32.cc
@@ -11,6 +11,14 @@
 
 const Register CallInterfaceDescriptor::ContextRegister() { return esi; }
 
+void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
+    CallInterfaceDescriptorData* data, int register_parameter_count) {
+  const Register default_stub_registers[] = {eax, ebx, ecx, edx, edi};
+  CHECK_LE(static_cast<size_t>(register_parameter_count),
+           arraysize(default_stub_registers));
+  data->InitializePlatformSpecific(register_parameter_count,
+                                   default_stub_registers);
+}
 
 const Register LoadDescriptor::ReceiverRegister() { return edx; }
 const Register LoadDescriptor::NameRegister() { return ecx; }
@@ -44,23 +52,15 @@
 const Register StoreTransitionDescriptor::MapRegister() { return ebx; }
 
 
-const Register LoadGlobalViaContextDescriptor::SlotRegister() { return ebx; }
-
-
 const Register StoreGlobalViaContextDescriptor::SlotRegister() { return ebx; }
 const Register StoreGlobalViaContextDescriptor::ValueRegister() { return eax; }
 
 
-const Register InstanceOfDescriptor::LeftRegister() { return edx; }
-const Register InstanceOfDescriptor::RightRegister() { return eax; }
-
-
 const Register StringCompareDescriptor::LeftRegister() { return edx; }
 const Register StringCompareDescriptor::RightRegister() { return eax; }
 
-
-const Register ApiGetterDescriptor::function_address() { return edx; }
-
+const Register ApiGetterDescriptor::HolderRegister() { return ecx; }
+const Register ApiGetterDescriptor::CallbackRegister() { return eax; }
 
 const Register MathPowTaggedDescriptor::exponent() { return eax; }
 
@@ -252,50 +252,37 @@
 SIMD128_TYPES(SIMD128_ALLOC_DESC)
 #undef SIMD128_ALLOC_DESC
 
-void AllocateInNewSpaceDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  Register registers[] = {eax};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-void ArrayConstructorConstantArgCountDescriptor::InitializePlatformSpecific(
+void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // register state
   // eax -- number of arguments
   // edi -- function
   // ebx -- allocation site with elements kind
-  Register registers[] = {edi, ebx};
+  Register registers[] = {edi, ebx, eax};
   data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
-
-void ArrayConstructorDescriptor::InitializePlatformSpecific(
+void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
-  // stack param count needs (constructor pointer, and single argument)
-  Register registers[] = {edi, ebx, eax};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-void InternalArrayConstructorConstantArgCountDescriptor::
-    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
   // register state
   // eax -- number of arguments
   // edi -- function
-  Register registers[] = {edi};
+  // ebx -- allocation site with elements kind
+  Register registers[] = {edi, ebx, eax};
   data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
-
-void InternalArrayConstructorDescriptor::InitializePlatformSpecific(
+void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
-  // stack param count needs (constructor pointer, and single argument)
-  Register registers[] = {edi, eax};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
+  // register state
+  // eax -- number of arguments
+  // edi -- function
+  // ebx -- allocation site with elements kind
+  Register registers[] = {edi, ebx, eax};
+  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
-void FastArrayPushDescriptor::InitializePlatformSpecific(
+void VarArgFunctionDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // stack param count needs (arg count)
   Register registers[] = {eax};
@@ -322,6 +309,11 @@
   data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
+void CountOpDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {eax};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
 
 void StringAddDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
@@ -382,8 +374,8 @@
 void InterpreterDispatchDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {
-      kInterpreterAccumulatorRegister, kInterpreterRegisterFileRegister,
-      kInterpreterBytecodeOffsetRegister, kInterpreterBytecodeArrayRegister };
+      kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
+      kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
@@ -418,6 +410,16 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
+void ResumeGeneratorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {
+      eax,  // the value to pass to the generator
+      ebx,  // the JSGeneratorObject to resume
+      edx   // the resume mode (tagged)
+  };
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index f9fd8d6..25a0a95 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -1025,6 +1025,16 @@
   }
 }
 
+void MacroAssembler::AssertGeneratorObject(Register object) {
+  if (emit_debug_code()) {
+    test(object, Immediate(kSmiTagMask));
+    Check(not_equal, kOperandIsASmiAndNotAGeneratorObject);
+    Push(object);
+    CmpObjectType(object, JS_GENERATOR_OBJECT_TYPE, object);
+    Pop(object);
+    Check(equal, kOperandIsNotAGeneratorObject);
+  }
+}
 
 void MacroAssembler::AssertReceiver(Register object) {
   if (emit_debug_code()) {
@@ -1085,8 +1095,8 @@
 
 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
   mov(vector, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
-  mov(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset));
-  mov(vector, FieldOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset));
+  mov(vector, FieldOperand(vector, JSFunction::kLiteralsOffset));
+  mov(vector, FieldOperand(vector, LiteralsArray::kFeedbackVectorOffset));
 }
 
 
@@ -1517,6 +1527,7 @@
                               AllocationFlags flags) {
   DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
   DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -1558,26 +1569,23 @@
 
   // Calculate new top and bail out if space is exhausted.
   Register top_reg = result_end.is_valid() ? result_end : result;
+
   if (!top_reg.is(result)) {
     mov(top_reg, result);
   }
   add(top_reg, Immediate(object_size));
-  j(carry, gc_required);
   cmp(top_reg, Operand::StaticVariable(allocation_limit));
   j(above, gc_required);
 
-  // Update allocation top.
-  UpdateAllocationTopHelper(top_reg, scratch, flags);
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    UpdateAllocationTopHelper(top_reg, scratch, flags);
+  }
 
-  // Tag result if requested.
-  bool tag_result = (flags & TAG_OBJECT) != 0;
   if (top_reg.is(result)) {
-    if (tag_result) {
-      sub(result, Immediate(object_size - kHeapObjectTag));
-    } else {
-      sub(result, Immediate(object_size));
-    }
-  } else if (tag_result) {
+    sub(result, Immediate(object_size - kHeapObjectTag));
+  } else {
+    // Tag the result.
     DCHECK(kHeapObjectTag == 1);
     inc(result);
   }
@@ -1594,6 +1602,8 @@
                               Label* gc_required,
                               AllocationFlags flags) {
   DCHECK((flags & SIZE_IN_WORDS) == 0);
+  DCHECK((flags & ALLOCATION_FOLDING_DOMINATOR) == 0);
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -1645,18 +1655,16 @@
   } else {
     DCHECK(element_count_type == REGISTER_VALUE_IS_INT32);
   }
+
   lea(result_end, Operand(element_count, element_size, header_size));
   add(result_end, result);
-  j(carry, gc_required);
   cmp(result_end, Operand::StaticVariable(allocation_limit));
   j(above, gc_required);
 
-  if ((flags & TAG_OBJECT) != 0) {
-    DCHECK(kHeapObjectTag == 1);
-    inc(result);
-  }
+  // Tag result.
+  DCHECK(kHeapObjectTag == 1);
+  inc(result);
 
-  // Update allocation top.
   UpdateAllocationTopHelper(result_end, scratch, flags);
 }
 
@@ -1668,6 +1676,7 @@
                               Label* gc_required,
                               AllocationFlags flags) {
   DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -1711,18 +1720,65 @@
     mov(result_end, object_size);
   }
   add(result_end, result);
-  j(carry, gc_required);
   cmp(result_end, Operand::StaticVariable(allocation_limit));
   j(above, gc_required);
 
-  // Tag result if requested.
-  if ((flags & TAG_OBJECT) != 0) {
-    DCHECK(kHeapObjectTag == 1);
-    inc(result);
+  // Tag result.
+  DCHECK(kHeapObjectTag == 1);
+  inc(result);
+
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    UpdateAllocationTopHelper(result_end, scratch, flags);
+  }
+}
+
+void MacroAssembler::FastAllocate(int object_size, Register result,
+                                  Register result_end, AllocationFlags flags) {
+  DCHECK(!result.is(result_end));
+  // Load address of new object into result.
+  LoadAllocationTopHelper(result, no_reg, flags);
+
+  if ((flags & DOUBLE_ALIGNMENT) != 0) {
+    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
+    Label aligned;
+    test(result, Immediate(kDoubleAlignmentMask));
+    j(zero, &aligned, Label::kNear);
+    mov(Operand(result, 0),
+        Immediate(isolate()->factory()->one_pointer_filler_map()));
+    add(result, Immediate(kDoubleSize / 2));
+    bind(&aligned);
   }
 
-  // Update allocation top.
-  UpdateAllocationTopHelper(result_end, scratch, flags);
+  lea(result_end, Operand(result, object_size));
+  UpdateAllocationTopHelper(result_end, no_reg, flags);
+
+  DCHECK(kHeapObjectTag == 1);
+  inc(result);
+}
+
+void MacroAssembler::FastAllocate(Register object_size, Register result,
+                                  Register result_end, AllocationFlags flags) {
+  DCHECK(!result.is(result_end));
+  // Load address of new object into result.
+  LoadAllocationTopHelper(result, no_reg, flags);
+
+  if ((flags & DOUBLE_ALIGNMENT) != 0) {
+    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
+    Label aligned;
+    test(result, Immediate(kDoubleAlignmentMask));
+    j(zero, &aligned, Label::kNear);
+    mov(Operand(result, 0),
+        Immediate(isolate()->factory()->one_pointer_filler_map()));
+    add(result, Immediate(kDoubleSize / 2));
+    bind(&aligned);
+  }
+
+  lea(result_end, Operand(result, object_size, times_1, 0));
+  UpdateAllocationTopHelper(result_end, no_reg, flags);
+
+  DCHECK(kHeapObjectTag == 1);
+  inc(result);
 }
 
 
@@ -1733,7 +1789,7 @@
                                         MutableMode mode) {
   // Allocate heap number in new space.
   Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   Handle<Map> map = mode == MUTABLE
       ? isolate()->factory()->mutable_heap_number_map()
@@ -1759,15 +1815,9 @@
   and_(scratch1, Immediate(~kObjectAlignmentMask));
 
   // Allocate two byte string in new space.
-  Allocate(SeqTwoByteString::kHeaderSize,
-           times_1,
-           scratch1,
-           REGISTER_VALUE_IS_INT32,
-           result,
-           scratch2,
-           scratch3,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(SeqTwoByteString::kHeaderSize, times_1, scratch1,
+           REGISTER_VALUE_IS_INT32, result, scratch2, scratch3, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1793,15 +1843,9 @@
   and_(scratch1, Immediate(~kObjectAlignmentMask));
 
   // Allocate one-byte string in new space.
-  Allocate(SeqOneByteString::kHeaderSize,
-           times_1,
-           scratch1,
-           REGISTER_VALUE_IS_INT32,
-           result,
-           scratch2,
-           scratch3,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(SeqOneByteString::kHeaderSize, times_1, scratch1,
+           REGISTER_VALUE_IS_INT32, result, scratch2, scratch3, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1821,7 +1865,7 @@
 
   // Allocate one-byte string in new space.
   Allocate(SeqOneByteString::SizeFor(length), result, scratch1, scratch2,
-           gc_required, TAG_OBJECT);
+           gc_required, NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1839,7 +1883,7 @@
                                         Label* gc_required) {
   // Allocate heap number in new space.
   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   // Set the map. The other fields are left uninitialized.
   mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1851,12 +1895,8 @@
                                                Register scratch1,
                                                Register scratch2,
                                                Label* gc_required) {
-  Allocate(ConsString::kSize,
-           result,
-           scratch1,
-           scratch2,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map. The other fields are left uninitialized.
   mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1870,7 +1910,7 @@
                                           Label* gc_required) {
   // Allocate heap number in new space.
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   // Set the map. The other fields are left uninitialized.
   mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1884,7 +1924,7 @@
                                                  Label* gc_required) {
   // Allocate heap number in new space.
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   // Set the map. The other fields are left uninitialized.
   mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1900,7 +1940,8 @@
   DCHECK(!result.is(value));
 
   // Allocate JSValue in new space.
-  Allocate(JSValue::kSize, result, scratch, no_reg, gc_required, TAG_OBJECT);
+  Allocate(JSValue::kSize, result, scratch, no_reg, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Initialize the JSValue.
   LoadGlobalFunctionInitialMap(constructor, scratch);
@@ -2321,10 +2362,11 @@
                                              const ParameterCount& expected,
                                              const ParameterCount& actual) {
   Label skip_flooding;
-  ExternalReference step_in_enabled =
-      ExternalReference::debug_step_in_enabled_address(isolate());
-  cmpb(Operand::StaticVariable(step_in_enabled), Immediate(0));
-  j(equal, &skip_flooding);
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(isolate());
+  STATIC_ASSERT(StepFrame > StepIn);
+  cmpb(Operand::StaticVariable(last_step_action), Immediate(StepIn));
+  j(less, &skip_flooding);
   {
     FrameScope frame(this,
                      has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
@@ -2637,7 +2679,7 @@
 
 
 void MacroAssembler::Move(Register dst, const Immediate& x) {
-  if (x.is_zero()) {
+  if (x.is_zero() && RelocInfo::IsNone(x.rmode_)) {
     xor_(dst, dst);  // Shorter than mov of 32-bit immediate 0.
   } else {
     mov(dst, x);
diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index be11f66..91c68d6 100644
--- a/src/ia32/macro-assembler-ia32.h
+++ b/src/ia32/macro-assembler-ia32.h
@@ -19,18 +19,16 @@
 const Register kReturnRegister2 = {Register::kCode_edi};
 const Register kJSFunctionRegister = {Register::kCode_edi};
 const Register kContextRegister = {Register::kCode_esi};
+const Register kAllocateSizeRegister = {Register::kCode_edx};
 const Register kInterpreterAccumulatorRegister = {Register::kCode_eax};
-const Register kInterpreterRegisterFileRegister = {Register::kCode_edx};
 const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_ecx};
 const Register kInterpreterBytecodeArrayRegister = {Register::kCode_edi};
+const Register kInterpreterDispatchTableRegister = {Register::kCode_esi};
 const Register kJavaScriptCallArgCountRegister = {Register::kCode_eax};
 const Register kJavaScriptCallNewTargetRegister = {Register::kCode_edx};
 const Register kRuntimeCallFunctionRegister = {Register::kCode_ebx};
 const Register kRuntimeCallArgCountRegister = {Register::kCode_eax};
 
-// Spill slots used by interpreter dispatch calling convention.
-const int kInterpreterDispatchTableSpillSlot = -1;
-
 // Convenience for platform-independent signatures.  We do not normally
 // distinguish memory operands from other operands on ia32.
 typedef Operand MemOperand;
@@ -511,6 +509,23 @@
     j(not_zero, not_smi_label, distance);
   }
 
+  // Jump if the value cannot be represented by a smi.
+  inline void JumpIfNotValidSmiValue(Register value, Register scratch,
+                                     Label* on_invalid,
+                                     Label::Distance distance = Label::kFar) {
+    mov(scratch, value);
+    add(scratch, Immediate(0x40000000U));
+    j(sign, on_invalid, distance);
+  }
+
+  // Jump if the unsigned integer value cannot be represented by a smi.
+  inline void JumpIfUIntNotValidSmiValue(
+      Register value, Label* on_invalid,
+      Label::Distance distance = Label::kFar) {
+    cmp(value, Immediate(0x40000000U));
+    j(above_equal, on_invalid, distance);
+  }
+
   void LoadInstanceDescriptors(Register map, Register descriptors);
   void EnumLength(Register dst, Register map);
   void NumberOfOwnDescriptors(Register dst, Register map);
@@ -566,6 +581,10 @@
   // enabled via --debug-code.
   void AssertBoundFunction(Register object);
 
+  // Abort execution if argument is not a JSGeneratorObject,
+  // enabled via --debug-code.
+  void AssertGeneratorObject(Register object);
+
   // Abort execution if argument is not a JSReceiver, enabled via --debug-code.
   void AssertReceiver(Register object);
 
@@ -621,6 +640,14 @@
   void Allocate(Register object_size, Register result, Register result_end,
                 Register scratch, Label* gc_required, AllocationFlags flags);
 
+  // FastAllocate is right now only used for folded allocations. It just
+  // increments the top pointer without checking against limit. This can only
+  // be done if it was proved earlier that the allocation will succeed.
+  void FastAllocate(int object_size, Register result, Register result_end,
+                    AllocationFlags flags);
+  void FastAllocate(Register object_size, Register result, Register result_end,
+                    AllocationFlags flags);
+
   // Allocate a heap number in new space with undefined value. The
   // register scratch2 can be passed as no_reg; the others must be
   // valid registers. Returns tagged pointer in result register, or
diff --git a/src/ic/access-compiler.h b/src/ic/access-compiler.h
index 50c2cc7..ecc5c08 100644
--- a/src/ic/access-compiler.h
+++ b/src/ic/access-compiler.h
@@ -58,7 +58,6 @@
   Register vector() const;
   Register scratch1() const { return registers_[2]; }
   Register scratch2() const { return registers_[3]; }
-  Register scratch3() const { return registers_[4]; }
 
   static Register* GetCallingConvention(Code::Kind);
   static Register* load_calling_convention();
diff --git a/src/ic/arm/access-compiler-arm.cc b/src/ic/arm/access-compiler-arm.cc
index d360f5a..9ce485e 100644
--- a/src/ic/arm/access-compiler-arm.cc
+++ b/src/ic/arm/access-compiler-arm.cc
@@ -19,19 +19,19 @@
 
 
 Register* PropertyAccessCompiler::load_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3, scratch4.
+  // receiver, name, scratch1, scratch2, scratch3.
   Register receiver = LoadDescriptor::ReceiverRegister();
   Register name = LoadDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, r3, r0, r4, r5};
+  static Register registers[] = {receiver, name, r3, r0, r4};
   return registers;
 }
 
 
 Register* PropertyAccessCompiler::store_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3.
+  // receiver, name, scratch1, scratch2.
   Register receiver = StoreDescriptor::ReceiverRegister();
   Register name = StoreDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, r3, r4, r5};
+  static Register registers[] = {receiver, name, r3, r4};
   return registers;
 }
 
diff --git a/src/ic/arm/handler-compiler-arm.cc b/src/ic/arm/handler-compiler-arm.cc
index a3f23d3..b98602b 100644
--- a/src/ic/arm/handler-compiler-arm.cc
+++ b/src/ic/arm/handler-compiler-arm.cc
@@ -204,8 +204,9 @@
     MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name,
     Register scratch, Label* miss) {
   Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name);
-  DCHECK(cell->value()->IsTheHole());
-  Handle<WeakCell> weak_cell = masm->isolate()->factory()->NewWeakCell(cell);
+  Isolate* isolate = masm->isolate();
+  DCHECK(cell->value()->IsTheHole(isolate));
+  Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
   __ LoadWeakValue(scratch, weak_cell, miss);
   __ ldr(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset));
   __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
@@ -290,7 +291,7 @@
   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
   bool call_data_undefined = false;
   // Put call data in place.
-  if (api_call_info->data()->IsUndefined()) {
+  if (api_call_info->data()->IsUndefined(isolate)) {
     call_data_undefined = true;
     __ LoadRoot(data, Heap::kUndefinedValueRootIndex);
   } else {
@@ -437,28 +438,25 @@
   DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
          !scratch2.is(scratch1));
 
-  if (FLAG_eliminate_prototype_chain_checks) {
-    Handle<Cell> validity_cell =
-        Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
-    if (!validity_cell.is_null()) {
-      DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
-                validity_cell->value());
-      __ mov(scratch1, Operand(validity_cell));
-      __ ldr(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
-      __ cmp(scratch1, Operand(Smi::FromInt(Map::kPrototypeChainValid)));
-      __ b(ne, miss);
-    }
+  Handle<Cell> validity_cell =
+      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
+  if (!validity_cell.is_null()) {
+    DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
+    __ mov(scratch1, Operand(validity_cell));
+    __ ldr(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
+    __ cmp(scratch1, Operand(Smi::FromInt(Map::kPrototypeChainValid)));
+    __ b(ne, miss);
+  }
 
-    // The prototype chain of primitives (and their JSValue wrappers) depends
-    // on the native context, which can't be guarded by validity cells.
-    // |object_reg| holds the native context specific prototype in this case;
-    // we need to check its map.
-    if (check == CHECK_ALL_MAPS) {
-      __ ldr(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
-      Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
-      __ CmpWeakValue(scratch1, cell, scratch2);
-      __ b(ne, miss);
-    }
+  // The prototype chain of primitives (and their JSValue wrappers) depends
+  // on the native context, which can't be guarded by validity cells.
+  // |object_reg| holds the native context specific prototype in this case;
+  // we need to check its map.
+  if (check == CHECK_ALL_MAPS) {
+    __ ldr(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
+    Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
+    __ CmpWeakValue(scratch1, cell, scratch2);
+    __ b(ne, miss);
   }
 
   // Keep track of the current object in register reg.
@@ -494,8 +492,10 @@
            !current_map->is_access_check_needed());
 
     prototype = handle(JSObject::cast(current_map->prototype()));
-    if (current_map->is_dictionary_map() &&
-        !current_map->IsJSGlobalObjectMap()) {
+    if (current_map->IsJSGlobalObjectMap()) {
+      GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
+                                name, scratch2, miss);
+    } else if (current_map->is_dictionary_map()) {
       DCHECK(!current_map->IsJSGlobalProxyMap());  // Proxy maps are fast.
       if (!name->IsUniqueName()) {
         DCHECK(name->IsString());
@@ -505,33 +505,12 @@
              current->property_dictionary()->FindEntry(name) ==
                  NameDictionary::kNotFound);
 
-      if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
+      if (depth > 1) {
         // TODO(jkummerow): Cache and re-use weak cell.
         __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
       }
       GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
                                        scratch2);
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
-        __ ldr(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
-      }
-    } else {
-      Register map_reg = scratch1;
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
-      }
-      if (current_map->IsJSGlobalObjectMap()) {
-        GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
-                                  name, scratch2, miss);
-      } else if (!FLAG_eliminate_prototype_chain_checks &&
-                 (depth != 1 || check == CHECK_ALL_MAPS)) {
-        Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-        __ CmpWeakValue(map_reg, cell, scratch2);
-        __ b(ne, miss);
-      }
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ ldr(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset));
-      }
     }
 
     reg = holder_reg;  // From now on the object will be in holder_reg.
@@ -545,17 +524,8 @@
   // Log the check depth.
   LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
 
-  if (!FLAG_eliminate_prototype_chain_checks &&
-      (depth != 0 || check == CHECK_ALL_MAPS)) {
-    // Check the holder map.
-    __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
-    Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-    __ CmpWeakValue(scratch1, cell, scratch2);
-    __ b(ne, miss);
-  }
-
   bool return_holder = return_what == RETURN_HOLDER;
-  if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
+  if (return_holder && depth != 0) {
     __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
   }
 
@@ -597,61 +567,10 @@
   __ Ret();
 }
 
-
-void NamedLoadHandlerCompiler::GenerateLoadCallback(
-    Register reg, Handle<AccessorInfo> callback) {
-  DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), receiver()));
-  DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), reg));
-
-  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
-  // name below the exit frame to make GC aware of them.
-  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
-  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
-  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
-  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
-  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
-  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
-
-  __ push(receiver());
-  // Push data from AccessorInfo.
-  Handle<Object> data(callback->data(), isolate());
-  if (data->IsUndefined() || data->IsSmi()) {
-    __ Move(scratch2(), data);
-  } else {
-    Handle<WeakCell> cell =
-        isolate()->factory()->NewWeakCell(Handle<HeapObject>::cast(data));
-    // The callback is alive if this instruction is executed,
-    // so the weak cell is not cleared and points to data.
-    __ GetWeakValue(scratch2(), cell);
-  }
-  __ push(scratch2());
-  __ LoadRoot(scratch2(), Heap::kUndefinedValueRootIndex);
-  __ Push(scratch2(), scratch2());
-  __ mov(scratch2(), Operand(ExternalReference::isolate_address(isolate())));
-  __ Push(scratch2(), reg);
-  __ Push(Smi::FromInt(0));  // should_throw_on_error -> false
-  __ push(name());
-
-  // Abi for CallApiGetter
-  Register getter_address_reg = ApiGetterDescriptor::function_address();
-
-  Address getter_address = v8::ToCData<Address>(callback->getter());
-  ApiFunction fun(getter_address);
-  ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
-  ExternalReference ref = ExternalReference(&fun, type, isolate());
-  __ mov(getter_address_reg, Operand(ref));
-
-  CallApiGetterStub stub(isolate());
-  __ TailCallStub(&stub);
-}
-
-
 void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
     LookupIterator* it, Register holder_reg) {
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
 
   // Compile the interceptor call, followed by inline code to load the
   // property from further up the prototype chain if the call fails.
@@ -711,7 +630,7 @@
 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
   // Call the runtime system to load the interceptor.
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
   PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
                            holder());
 
@@ -729,7 +648,7 @@
 
   // If the callback cannot leak, then push the callback directly,
   // otherwise wrap it in a weak cell.
-  if (callback->data()->IsUndefined() || callback->data()->IsSmi()) {
+  if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) {
     __ mov(ip, Operand(callback));
   } else {
     Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback);
@@ -744,7 +663,7 @@
   __ TailCallRuntime(Runtime::kStoreCallbackProperty);
 
   // Return the generated code.
-  return GetCode(kind(), Code::FAST, name);
+  return GetCode(kind(), name);
 }
 
 
@@ -784,7 +703,7 @@
   FrontendFooter(name, &miss);
 
   // Return the generated code.
-  return GetCode(kind(), Code::NORMAL, name);
+  return GetCode(kind(), name);
 }
 
 
diff --git a/src/ic/arm/ic-arm.cc b/src/ic/arm/ic-arm.cc
index 14ed8b4..f3af785 100644
--- a/src/ic/arm/ic-arm.cc
+++ b/src/ic/arm/ic-arm.cc
@@ -415,8 +415,8 @@
   __ LoadRoot(vector, Heap::kDummyVectorRootIndex);
   __ mov(slot, Operand(Smi::FromInt(slot_index)));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::KEYED_LOAD_IC, flags,
                                                receiver, key, r4, r5, r6, r9);
   // Cache miss.
@@ -626,10 +626,10 @@
   __ JumpIfSmi(receiver, &slow);
   // Get the map of the object.
   __ ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
-  // Check that the receiver does not require access checks and is not observed.
-  // The generic stub does not perform map checks or handle observed objects.
+  // Check that the receiver does not require access checks.
+  // The generic stub does not perform map checks.
   __ ldrb(ip, FieldMemOperand(receiver_map, Map::kBitFieldOffset));
-  __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved));
+  __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded));
   __ b(ne, &slow);
   // Check if the object is a JS array or not.
   __ ldrb(r4, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset));
@@ -682,10 +682,10 @@
   __ LoadRoot(vector, Heap::kDummyVectorRootIndex);
   __ mov(slot, Operand(Smi::FromInt(slot_index)));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
   masm->isolate()->stub_cache()->GenerateProbe(
-      masm, Code::STORE_IC, flags, receiver, key, r5, temporary2, r6, r9);
+      masm, Code::KEYED_STORE_IC, flags, receiver, key, r5, temporary2, r6, r9);
   // Cache miss.
   __ b(&miss);
 
@@ -734,26 +734,6 @@
   GenerateMiss(masm);
 }
 
-
-void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
-  Register receiver = StoreDescriptor::ReceiverRegister();
-  Register name = StoreDescriptor::NameRegister();
-  DCHECK(receiver.is(r1));
-  DCHECK(name.is(r2));
-  DCHECK(StoreDescriptor::ValueRegister().is(r0));
-
-  // Get the receiver from the stack and probe the stub cache.
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
-
-  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags,
-                                               receiver, name, r3, r4, r5, r6);
-
-  // Cache miss: Jump to runtime.
-  GenerateMiss(masm);
-}
-
-
 void StoreIC::GenerateMiss(MacroAssembler* masm) {
   StoreIC_PushArgs(masm);
 
@@ -845,8 +825,9 @@
   }
 
   if (FLAG_trace_ic) {
-    PrintF("[  patching ic at %p, cmp=%p, delta=%d\n", address,
-           cmp_instruction_address, delta);
+    PrintF("[  patching ic at %p, cmp=%p, delta=%d\n",
+           static_cast<void*>(address),
+           static_cast<void*>(cmp_instruction_address), delta);
   }
 
   Address patch_address =
diff --git a/src/ic/arm/stub-cache-arm.cc b/src/ic/arm/stub-cache-arm.cc
index 86710eb..db8be30 100644
--- a/src/ic/arm/stub-cache-arm.cc
+++ b/src/ic/arm/stub-cache-arm.cc
@@ -14,10 +14,9 @@
 
 #define __ ACCESS_MASM(masm)
 
-
 static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
-                       Code::Kind ic_kind, Code::Flags flags,
-                       StubCache::Table table, Register receiver, Register name,
+                       Code::Flags flags, StubCache::Table table,
+                       Register receiver, Register name,
                        // Number of the cache entry, not scaled.
                        Register offset, Register scratch, Register scratch2,
                        Register offset_scratch) {
@@ -103,9 +102,6 @@
   // entry size being 12.
   DCHECK(sizeof(Entry) == 12);
 
-  // Make sure the flags does not name a specific type.
-  DCHECK(Code::ExtractTypeFromFlags(flags) == 0);
-
   // Make sure that there are no register conflicts.
   DCHECK(!AreAliased(receiver, name, scratch, extra, extra2, extra3));
 
@@ -154,8 +150,8 @@
   __ and_(scratch, scratch, Operand(mask));
 
   // Probe the primary table.
-  ProbeTable(isolate, masm, ic_kind, flags, kPrimary, receiver, name, scratch,
-             extra, extra2, extra3);
+  ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch, extra,
+             extra2, extra3);
 
   // Primary miss: Compute hash for secondary probe.
   __ sub(scratch, scratch, Operand(name, LSR, kCacheIndexShift));
@@ -164,8 +160,8 @@
   __ and_(scratch, scratch, Operand(mask2));
 
   // Probe the secondary table.
-  ProbeTable(isolate, masm, ic_kind, flags, kSecondary, receiver, name, scratch,
-             extra, extra2, extra3);
+  ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch, extra,
+             extra2, extra3);
 
   // Cache miss: Fall-through and let caller handle the miss by
   // entering the runtime system.
diff --git a/src/ic/arm64/access-compiler-arm64.cc b/src/ic/arm64/access-compiler-arm64.cc
index 892ce85..6273633 100644
--- a/src/ic/arm64/access-compiler-arm64.cc
+++ b/src/ic/arm64/access-compiler-arm64.cc
@@ -26,19 +26,19 @@
 // we use the same assignments as ARM to remain on the safe side.
 
 Register* PropertyAccessCompiler::load_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3, scratch4.
+  // receiver, name, scratch1, scratch2, scratch3.
   Register receiver = LoadDescriptor::ReceiverRegister();
   Register name = LoadDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, x3, x0, x4, x5};
+  static Register registers[] = {receiver, name, x3, x0, x4};
   return registers;
 }
 
 
 Register* PropertyAccessCompiler::store_calling_convention() {
-  // receiver, value, scratch1, scratch2, scratch3.
+  // receiver, value, scratch1, scratch2.
   Register receiver = StoreDescriptor::ReceiverRegister();
   Register name = StoreDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, x3, x4, x5};
+  static Register registers[] = {receiver, name, x3, x4};
   return registers;
 }
 
diff --git a/src/ic/arm64/handler-compiler-arm64.cc b/src/ic/arm64/handler-compiler-arm64.cc
index a704492..1126beb 100644
--- a/src/ic/arm64/handler-compiler-arm64.cc
+++ b/src/ic/arm64/handler-compiler-arm64.cc
@@ -110,8 +110,9 @@
     MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name,
     Register scratch, Label* miss) {
   Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name);
-  DCHECK(cell->value()->IsTheHole());
-  Handle<WeakCell> weak_cell = masm->isolate()->factory()->NewWeakCell(cell);
+  Isolate* isolate = masm->isolate();
+  DCHECK(cell->value()->IsTheHole(isolate));
+  Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
   __ LoadWeakValue(scratch, weak_cell, miss);
   __ Ldr(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset));
   __ JumpIfNotRoot(scratch, Heap::kTheHoleValueRootIndex, miss);
@@ -197,7 +198,7 @@
   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
   bool call_data_undefined = false;
   // Put call data in place.
-  if (api_call_info->data()->IsUndefined()) {
+  if (api_call_info->data()->IsUndefined(isolate)) {
     call_data_undefined = true;
     __ LoadRoot(data, Heap::kUndefinedValueRootIndex);
   } else {
@@ -382,7 +383,7 @@
   FrontendFooter(name, &miss);
 
   // Return the generated code.
-  return GetCode(kind(), Code::NORMAL, name);
+  return GetCode(kind(), name);
 }
 
 
@@ -467,28 +468,25 @@
   DCHECK(!AreAliased(object_reg, scratch1, scratch2));
   DCHECK(!AreAliased(holder_reg, scratch1, scratch2));
 
-  if (FLAG_eliminate_prototype_chain_checks) {
-    Handle<Cell> validity_cell =
-        Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
-    if (!validity_cell.is_null()) {
-      DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
-                validity_cell->value());
-      __ Mov(scratch1, Operand(validity_cell));
-      __ Ldr(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
-      __ Cmp(scratch1, Operand(Smi::FromInt(Map::kPrototypeChainValid)));
-      __ B(ne, miss);
-    }
+  Handle<Cell> validity_cell =
+      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
+  if (!validity_cell.is_null()) {
+    DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
+    __ Mov(scratch1, Operand(validity_cell));
+    __ Ldr(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
+    __ Cmp(scratch1, Operand(Smi::FromInt(Map::kPrototypeChainValid)));
+    __ B(ne, miss);
+  }
 
-    // The prototype chain of primitives (and their JSValue wrappers) depends
-    // on the native context, which can't be guarded by validity cells.
-    // |object_reg| holds the native context specific prototype in this case;
-    // we need to check its map.
-    if (check == CHECK_ALL_MAPS) {
-      __ Ldr(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
-      Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
-      __ CmpWeakValue(scratch1, cell, scratch2);
-      __ B(ne, miss);
-    }
+  // The prototype chain of primitives (and their JSValue wrappers) depends
+  // on the native context, which can't be guarded by validity cells.
+  // |object_reg| holds the native context specific prototype in this case;
+  // we need to check its map.
+  if (check == CHECK_ALL_MAPS) {
+    __ Ldr(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
+    Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
+    __ CmpWeakValue(scratch1, cell, scratch2);
+    __ B(ne, miss);
   }
 
   // Keep track of the current object in register reg.
@@ -525,8 +523,10 @@
            !current_map->is_access_check_needed());
 
     prototype = handle(JSObject::cast(current_map->prototype()));
-    if (current_map->is_dictionary_map() &&
-        !current_map->IsJSGlobalObjectMap()) {
+    if (current_map->IsJSGlobalObjectMap()) {
+      GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
+                                name, scratch2, miss);
+    } else if (current_map->is_dictionary_map()) {
       DCHECK(!current_map->IsJSGlobalProxyMap());  // Proxy maps are fast.
       if (!name->IsUniqueName()) {
         DCHECK(name->IsString());
@@ -535,34 +535,12 @@
       DCHECK(current.is_null() || (current->property_dictionary()->FindEntry(
                                        name) == NameDictionary::kNotFound));
 
-      if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
+      if (depth > 1) {
         // TODO(jkummerow): Cache and re-use weak cell.
         __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
       }
       GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
                                        scratch2);
-
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ Ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
-        __ Ldr(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
-      }
-    } else {
-      Register map_reg = scratch1;
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ Ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
-      }
-      if (current_map->IsJSGlobalObjectMap()) {
-        GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
-                                  name, scratch2, miss);
-      } else if (!FLAG_eliminate_prototype_chain_checks &&
-                 (depth != 1 || check == CHECK_ALL_MAPS)) {
-        Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-        __ CmpWeakValue(map_reg, cell, scratch2);
-        __ B(ne, miss);
-      }
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ Ldr(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset));
-      }
     }
 
     reg = holder_reg;  // From now on the object will be in holder_reg.
@@ -576,17 +554,8 @@
   // Log the check depth.
   LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
 
-  if (!FLAG_eliminate_prototype_chain_checks &&
-      (depth != 0 || check == CHECK_ALL_MAPS)) {
-    // Check the holder map.
-    __ Ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
-    Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-    __ CmpWeakValue(scratch1, cell, scratch2);
-    __ B(ne, miss);
-  }
-
   bool return_holder = return_what == RETURN_HOLDER;
-  if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
+  if (return_holder && depth != 0) {
     __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
   }
 
@@ -632,62 +601,12 @@
   __ Ret();
 }
 
-
-void NamedLoadHandlerCompiler::GenerateLoadCallback(
-    Register reg, Handle<AccessorInfo> callback) {
-  DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), receiver()));
-  DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), reg));
-
-  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
-  // name below the exit frame to make GC aware of them.
-  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
-  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
-  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
-  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
-  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
-  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
-
-  __ Push(receiver());
-
-  Handle<Object> data(callback->data(), isolate());
-  if (data->IsUndefined() || data->IsSmi()) {
-    __ Mov(scratch3(), Operand(data));
-  } else {
-    Handle<WeakCell> cell =
-        isolate()->factory()->NewWeakCell(Handle<HeapObject>::cast(data));
-    // The callback is alive if this instruction is executed,
-    // so the weak cell is not cleared and points to data.
-    __ GetWeakValue(scratch3(), cell);
-  }
-  __ LoadRoot(scratch4(), Heap::kUndefinedValueRootIndex);
-  __ Mov(scratch2(), Operand(ExternalReference::isolate_address(isolate())));
-  __ Push(scratch3(), scratch4(), scratch4(), scratch2(), reg);
-  __ Push(Smi::FromInt(0));  // should_throw_on_error -> false
-  __ Push(name());
-
-  // Abi for CallApiGetter.
-  Register getter_address_reg = x2;
-
-  // Set up the call.
-  Address getter_address = v8::ToCData<Address>(callback->getter());
-  ApiFunction fun(getter_address);
-  ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
-  ExternalReference ref = ExternalReference(&fun, type, isolate());
-  __ Mov(getter_address_reg, ref);
-
-  CallApiGetterStub stub(isolate());
-  __ TailCallStub(&stub);
-}
-
-
 void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
     LookupIterator* it, Register holder_reg) {
   DCHECK(!AreAliased(receiver(), this->name(), scratch1(), scratch2(),
                      scratch3()));
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
 
   // Compile the interceptor call, followed by inline code to load the
   // property from further up the prototype chain if the call fails.
@@ -746,7 +665,7 @@
 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
   // Call the runtime system to load the interceptor.
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
   PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
                            holder());
 
@@ -768,7 +687,7 @@
   DCHECK(!AreAliased(holder_reg, scratch1(), scratch2(), value()));
   // If the callback cannot leak, then push the callback directly,
   // otherwise wrap it in a weak cell.
-  if (callback->data()->IsUndefined() || callback->data()->IsSmi()) {
+  if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) {
     __ Mov(scratch1(), Operand(callback));
   } else {
     Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback);
@@ -782,7 +701,7 @@
   __ TailCallRuntime(Runtime::kStoreCallbackProperty);
 
   // Return the generated code.
-  return GetCode(kind(), Code::FAST, name);
+  return GetCode(kind(), name);
 }
 
 
diff --git a/src/ic/arm64/ic-arm64.cc b/src/ic/arm64/ic-arm64.cc
index 726a68e..69b8c2f 100644
--- a/src/ic/arm64/ic-arm64.cc
+++ b/src/ic/arm64/ic-arm64.cc
@@ -394,8 +394,8 @@
   __ LoadRoot(vector, Heap::kDummyVectorRootIndex);
   __ Mov(slot, Operand(Smi::FromInt(slot_index)));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::KEYED_LOAD_IC, flags,
                                                receiver, key, scratch1,
                                                scratch2, scratch3, scratch4);
@@ -622,11 +622,10 @@
   __ JumpIfSmi(receiver, &slow);
   __ Ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
 
-  // Check that the receiver does not require access checks and is not observed.
-  // The generic stub does not perform map checks or handle observed objects.
+  // Check that the receiver does not require access checks.
+  // The generic stub does not perform map checks.
   __ Ldrb(x10, FieldMemOperand(receiver_map, Map::kBitFieldOffset));
-  __ TestAndBranchIfAnySet(
-      x10, (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kIsObserved), &slow);
+  __ TestAndBranchIfAnySet(x10, (1 << Map::kIsAccessCheckNeeded), &slow);
 
   // Check if the object is a JS array or not.
   Register instance_type = x10;
@@ -673,10 +672,10 @@
   __ LoadRoot(vector, Heap::kDummyVectorRootIndex);
   __ Mov(slot, Operand(Smi::FromInt(slot_index)));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags,
-                                               receiver, key, x5, x6, x7, x8);
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
+  masm->isolate()->stub_cache()->GenerateProbe(
+      masm, Code::KEYED_STORE_IC, flags, receiver, key, x5, x6, x7, x8);
   // Cache miss.
   __ B(&miss);
 
@@ -725,24 +724,6 @@
   GenerateMiss(masm);
 }
 
-
-void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
-  Register receiver = StoreDescriptor::ReceiverRegister();
-  Register name = StoreDescriptor::NameRegister();
-  DCHECK(!AreAliased(receiver, name, StoreDescriptor::ValueRegister(), x3, x4,
-                     x5, x6));
-
-  // Probe the stub cache.
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags,
-                                               receiver, name, x3, x4, x5, x6);
-
-  // Cache miss: Jump to runtime.
-  GenerateMiss(masm);
-}
-
-
 void StoreIC::GenerateMiss(MacroAssembler* masm) {
   StoreIC_PushArgs(masm);
 
@@ -822,8 +803,9 @@
   }
 
   if (FLAG_trace_ic) {
-    PrintF("[  Patching ic at %p, marker=%p, SMI check=%p\n", address,
-           info_address, reinterpret_cast<void*>(info.SmiCheck()));
+    PrintF("[  Patching ic at %p, marker=%p, SMI check=%p\n",
+           static_cast<void*>(address), static_cast<void*>(info_address),
+           static_cast<void*>(info.SmiCheck()));
   }
 
   // Patch and activate code generated by JumpPatchSite::EmitJumpIfNotSmi()
diff --git a/src/ic/arm64/stub-cache-arm64.cc b/src/ic/arm64/stub-cache-arm64.cc
index eb82f2a..8d378ce 100644
--- a/src/ic/arm64/stub-cache-arm64.cc
+++ b/src/ic/arm64/stub-cache-arm64.cc
@@ -23,10 +23,9 @@
 //
 // 'receiver', 'name' and 'offset' registers are preserved on miss.
 static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
-                       Code::Kind ic_kind, Code::Flags flags,
-                       StubCache::Table table, Register receiver, Register name,
-                       Register offset, Register scratch, Register scratch2,
-                       Register scratch3) {
+                       Code::Flags flags, StubCache::Table table,
+                       Register receiver, Register name, Register offset,
+                       Register scratch, Register scratch2, Register scratch3) {
   // Some code below relies on the fact that the Entry struct contains
   // 3 pointers (name, code, map).
   STATIC_ASSERT(sizeof(StubCache::Entry) == (3 * kPointerSize));
@@ -95,9 +94,6 @@
   Isolate* isolate = masm->isolate();
   Label miss;
 
-  // Make sure the flags does not name a specific type.
-  DCHECK(Code::ExtractTypeFromFlags(flags) == 0);
-
   // Make sure that there are no register conflicts.
   DCHECK(!AreAliased(receiver, name, scratch, extra, extra2, extra3));
 
@@ -140,8 +136,8 @@
           CountTrailingZeros(kPrimaryTableSize, 64));
 
   // Probe the primary table.
-  ProbeTable(isolate, masm, ic_kind, flags, kPrimary, receiver, name, scratch,
-             extra, extra2, extra3);
+  ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch, extra,
+             extra2, extra3);
 
   // Primary miss: Compute hash for secondary table.
   __ Sub(scratch, scratch, Operand(name, LSR, kCacheIndexShift));
@@ -149,8 +145,8 @@
   __ And(scratch, scratch, kSecondaryTableSize - 1);
 
   // Probe the secondary table.
-  ProbeTable(isolate, masm, ic_kind, flags, kSecondary, receiver, name, scratch,
-             extra, extra2, extra3);
+  ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch, extra,
+             extra2, extra3);
 
   // Cache miss: Fall-through and let caller handle the miss by
   // entering the runtime system.
diff --git a/src/ic/call-optimization.cc b/src/ic/call-optimization.cc
index 571b614..f7a1f69 100644
--- a/src/ic/call-optimization.cc
+++ b/src/ic/call-optimization.cc
@@ -89,11 +89,12 @@
 
 void CallOptimization::Initialize(
     Handle<FunctionTemplateInfo> function_template_info) {
-  if (function_template_info->call_code()->IsUndefined()) return;
+  Isolate* isolate = function_template_info->GetIsolate();
+  if (function_template_info->call_code()->IsUndefined(isolate)) return;
   api_call_info_ =
       handle(CallHandlerInfo::cast(function_template_info->call_code()));
 
-  if (!function_template_info->signature()->IsUndefined()) {
+  if (!function_template_info->signature()->IsUndefined(isolate)) {
     expected_receiver_type_ =
         handle(FunctionTemplateInfo::cast(function_template_info->signature()));
   }
@@ -110,15 +111,17 @@
 
 void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
   if (!function->shared()->IsApiFunction()) return;
-  Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data());
+  Isolate* isolate = function->GetIsolate();
+  Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data(),
+                                    isolate);
 
   // Require a C++ callback.
-  if (info->call_code()->IsUndefined()) return;
-  api_call_info_ = handle(CallHandlerInfo::cast(info->call_code()));
+  if (info->call_code()->IsUndefined(isolate)) return;
+  api_call_info_ = handle(CallHandlerInfo::cast(info->call_code()), isolate);
 
-  if (!info->signature()->IsUndefined()) {
+  if (!info->signature()->IsUndefined(isolate)) {
     expected_receiver_type_ =
-        handle(FunctionTemplateInfo::cast(info->signature()));
+        handle(FunctionTemplateInfo::cast(info->signature()), isolate);
   }
 
   is_simple_api_call_ = true;
diff --git a/src/ic/handler-compiler.cc b/src/ic/handler-compiler.cc
index 714888c..6d153bb 100644
--- a/src/ic/handler-compiler.cc
+++ b/src/ic/handler-compiler.cc
@@ -9,28 +9,25 @@
 #include "src/ic/ic-inl.h"
 #include "src/ic/ic.h"
 #include "src/isolate-inl.h"
-#include "src/profiler/cpu-profiler.h"
 
 namespace v8 {
 namespace internal {
 
-
 Handle<Code> PropertyHandlerCompiler::Find(Handle<Name> name,
                                            Handle<Map> stub_holder,
                                            Code::Kind kind,
-                                           CacheHolderFlag cache_holder,
-                                           Code::StubType type) {
-  Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder);
-  Object* probe = stub_holder->FindInCodeCache(*name, flags);
-  if (probe->IsCode()) return handle(Code::cast(probe));
-  return Handle<Code>::null();
+                                           CacheHolderFlag cache_holder) {
+  Code::Flags flags = Code::ComputeHandlerFlags(kind, cache_holder);
+  Code* code = stub_holder->LookupInCodeCache(*name, flags);
+  if (code == nullptr) return Handle<Code>();
+  return handle(code);
 }
 
 
 Handle<Code> NamedLoadHandlerCompiler::ComputeLoadNonexistent(
     Handle<Name> name, Handle<Map> receiver_map) {
   Isolate* isolate = name->GetIsolate();
-  if (receiver_map->prototype()->IsNull()) {
+  if (receiver_map->prototype()->IsNull(isolate)) {
     // TODO(jkummerow/verwaest): If there is no prototype and the property
     // is nonexistent, introduce a builtin to handle this (fast properties
     // -> return undefined, dictionary properties -> do negative lookup).
@@ -53,7 +50,7 @@
   Handle<JSObject> last(JSObject::cast(receiver_map->prototype()));
   while (true) {
     if (current_map->is_dictionary_map()) cache_name = name;
-    if (current_map->prototype()->IsNull()) break;
+    if (current_map->prototype()->IsNull(isolate)) break;
     if (name->IsPrivate()) {
       // TODO(verwaest): Use nonexistent_private_symbol.
       cache_name = name;
@@ -66,9 +63,10 @@
   // Compile the stub that is either shared for all names or
   // name specific if there are global objects involved.
   Handle<Code> handler = PropertyHandlerCompiler::Find(
-      cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST);
+      cache_name, stub_holder_map, Code::LOAD_IC, flag);
   if (!handler.is_null()) return handler;
 
+  TRACE_HANDLER_STATS(isolate, LoadIC_LoadNonexistent);
   NamedLoadHandlerCompiler compiler(isolate, receiver_map, last, flag);
   handler = compiler.CompileLoadNonexistent(cache_name);
   Map::UpdateCodeCache(stub_holder_map, cache_name, handler);
@@ -77,11 +75,10 @@
 
 
 Handle<Code> PropertyHandlerCompiler::GetCode(Code::Kind kind,
-                                              Code::StubType type,
                                               Handle<Name> name) {
-  Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder());
+  Code::Flags flags = Code::ComputeHandlerFlags(kind, cache_holder());
   Handle<Code> code = GetCodeWithFlags(flags, name);
-  PROFILE(isolate(), CodeCreateEvent(Logger::HANDLER_TAG,
+  PROFILE(isolate(), CodeCreateEvent(CodeEventListener::HANDLER_TAG,
                                      AbstractCode::cast(*code), *name));
 #ifdef DEBUG
   code->VerifyEmbeddedObjects();
@@ -194,7 +191,7 @@
   __ Move(receiver(), reg);
   LoadFieldStub stub(isolate(), field);
   GenerateTailCall(masm(), stub.GetCode());
-  return GetCode(kind(), Code::FAST, name);
+  return GetCode(kind(), name);
 }
 
 
@@ -204,7 +201,7 @@
   __ Move(receiver(), reg);
   LoadConstantStub stub(isolate(), constant_index);
   GenerateTailCall(masm(), stub.GetCode());
-  return GetCode(kind(), Code::FAST, name);
+  return GetCode(kind(), name);
 }
 
 
@@ -221,15 +218,19 @@
   }
   GenerateLoadConstant(isolate()->factory()->undefined_value());
   FrontendFooter(name, &miss);
-  return GetCode(kind(), Code::FAST, name);
+  return GetCode(kind(), name);
 }
 
 
 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
     Handle<Name> name, Handle<AccessorInfo> callback) {
   Register reg = Frontend(name);
-  GenerateLoadCallback(reg, callback);
-  return GetCode(kind(), Code::FAST, name);
+  if (FLAG_runtime_call_stats) {
+    TailCallBuiltin(masm(), Builtins::kLoadIC_Slow);
+  } else {
+    GenerateLoadCallback(reg, callback);
+  }
+  return GetCode(kind(), name);
 }
 
 
@@ -238,9 +239,13 @@
     int accessor_index) {
   DCHECK(call_optimization.is_simple_api_call());
   Register holder = Frontend(name);
-  GenerateApiAccessorCall(masm(), call_optimization, map(), receiver(),
-                          scratch2(), false, no_reg, holder, accessor_index);
-  return GetCode(kind(), Code::FAST, name);
+  if (FLAG_runtime_call_stats) {
+    TailCallBuiltin(masm(), Builtins::kLoadIC_Slow);
+  } else {
+    GenerateApiAccessorCall(masm(), call_optimization, map(), receiver(),
+                            scratch2(), false, no_reg, holder, accessor_index);
+  }
+  return GetCode(kind(), name);
 }
 
 
@@ -358,9 +363,21 @@
   } else {
     GenerateLoadInterceptor(reg);
   }
-  return GetCode(kind(), Code::FAST, it->name());
+  return GetCode(kind(), it->name());
 }
 
+void NamedLoadHandlerCompiler::GenerateLoadCallback(
+    Register reg, Handle<AccessorInfo> callback) {
+  DCHECK(receiver().is(ApiGetterDescriptor::ReceiverRegister()));
+  __ Move(ApiGetterDescriptor::HolderRegister(), reg);
+  // The callback is alive if this instruction is executed,
+  // so the weak cell is not cleared and points to data.
+  Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback);
+  __ GetWeakValue(ApiGetterDescriptor::CallbackRegister(), cell);
+
+  CallApiGetterStub stub(isolate());
+  __ TailCallStub(&stub);
+}
 
 void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor(
     LookupIterator* it, Register interceptor_reg) {
@@ -410,13 +427,12 @@
   }
 }
 
-
 Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter(
     Handle<Name> name, int accessor_index, int expected_arguments) {
   Register holder = Frontend(name);
   GenerateLoadViaGetter(masm(), map(), receiver(), holder, accessor_index,
                         expected_arguments, scratch2());
-  return GetCode(kind(), Code::FAST, name);
+  return GetCode(kind(), name);
 }
 
 
@@ -435,8 +451,7 @@
     PrototypeIterator::WhereToEnd end =
         name->IsPrivate() ? PrototypeIterator::END_AT_NON_HIDDEN
                           : PrototypeIterator::END_AT_NULL;
-    PrototypeIterator iter(isolate(), holder(),
-                           PrototypeIterator::START_AT_PROTOTYPE, end);
+    PrototypeIterator iter(isolate(), holder(), kStartAtPrototype, end);
     while (!iter.IsAtEnd()) {
       last = PrototypeIterator::GetCurrent<JSObject>(iter);
       iter.Advance();
@@ -506,7 +521,7 @@
   PopVectorAndSlot();
   TailCallBuiltin(masm(), MissBuiltin(kind()));
 
-  return GetCode(kind(), Code::FAST, name);
+  return GetCode(kind(), name);
 }
 
 bool NamedStoreHandlerCompiler::RequiresFieldTypeChecks(
@@ -534,7 +549,7 @@
   __ bind(&miss);
   if (need_save_restore) PopVectorAndSlot();
   TailCallBuiltin(masm(), MissBuiltin(kind()));
-  return GetCode(kind(), Code::FAST, it->name());
+  return GetCode(kind(), it->name());
 }
 
 
@@ -545,7 +560,7 @@
   GenerateStoreViaSetter(masm(), map(), receiver(), holder, accessor_index,
                          expected_arguments, scratch2());
 
-  return GetCode(kind(), Code::FAST, name);
+  return GetCode(kind(), name);
 }
 
 
@@ -553,10 +568,15 @@
     Handle<JSObject> object, Handle<Name> name,
     const CallOptimization& call_optimization, int accessor_index) {
   Register holder = Frontend(name);
-  GenerateApiAccessorCall(masm(), call_optimization, handle(object->map()),
-                          receiver(), scratch2(), true, value(), holder,
-                          accessor_index);
-  return GetCode(kind(), Code::FAST, name);
+  if (FLAG_runtime_call_stats) {
+    GenerateRestoreName(name);
+    TailCallBuiltin(masm(), Builtins::kStoreIC_Slow);
+  } else {
+    GenerateApiAccessorCall(masm(), call_optimization, handle(object->map()),
+                            receiver(), scratch2(), true, value(), holder,
+                            accessor_index);
+  }
+  return GetCode(kind(), name);
 }
 
 
@@ -583,7 +603,8 @@
            *receiver_map == isolate()->get_initial_js_array_map(elements_kind));
 
       if (receiver_map->has_indexed_interceptor() &&
-          !receiver_map->GetIndexedInterceptor()->getter()->IsUndefined() &&
+          !receiver_map->GetIndexedInterceptor()->getter()->IsUndefined(
+              isolate()) &&
           !receiver_map->GetIndexedInterceptor()->non_masking()) {
         cached_stub = LoadIndexedInterceptorStub(isolate()).GetCode();
       } else if (IsSloppyArgumentsElements(elements_kind)) {
@@ -594,8 +615,7 @@
                                           convert_hole_to_undefined).GetCode();
       } else {
         DCHECK(elements_kind == DICTIONARY_ELEMENTS);
-        LoadICState state = LoadICState(kNoExtraICState);
-        cached_stub = LoadDictionaryElementStub(isolate(), state).GetCode();
+        cached_stub = LoadDictionaryElementStub(isolate()).GetCode();
       }
     }
 
diff --git a/src/ic/handler-compiler.h b/src/ic/handler-compiler.h
index 76036a2..a571f4f 100644
--- a/src/ic/handler-compiler.h
+++ b/src/ic/handler-compiler.h
@@ -19,7 +19,7 @@
 class PropertyHandlerCompiler : public PropertyAccessCompiler {
  public:
   static Handle<Code> Find(Handle<Name> name, Handle<Map> map, Code::Kind kind,
-                           CacheHolderFlag cache_holder, Code::StubType type);
+                           CacheHolderFlag cache_holder);
 
  protected:
   PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind, Handle<Map> map,
@@ -98,7 +98,7 @@
                            Handle<Name> name, Label* miss,
                            PrototypeCheckType check, ReturnHolder return_what);
 
-  Handle<Code> GetCode(Code::Kind kind, Code::StubType type, Handle<Name> name);
+  Handle<Code> GetCode(Code::Kind kind, Handle<Name> name);
   void set_holder(Handle<JSObject> holder) { holder_ = holder; }
   Handle<Map> map() const { return map_; }
   void set_map(Handle<Map> map) { map_ = map; }
@@ -205,8 +205,7 @@
                                                         Register prototype,
                                                         Label* miss);
 
-
-  Register scratch4() { return registers_[5]; }
+  Register scratch3() { return registers_[4]; }
 };
 
 
diff --git a/src/ic/ia32/access-compiler-ia32.cc b/src/ic/ia32/access-compiler-ia32.cc
index 1825202..3219f3d 100644
--- a/src/ic/ia32/access-compiler-ia32.cc
+++ b/src/ic/ia32/access-compiler-ia32.cc
@@ -18,19 +18,19 @@
 
 
 Register* PropertyAccessCompiler::load_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3, scratch4.
+  // receiver, name, scratch1, scratch2, scratch3.
   Register receiver = LoadDescriptor::ReceiverRegister();
   Register name = LoadDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, ebx, eax, edi, no_reg};
+  static Register registers[] = {receiver, name, ebx, eax, edi};
   return registers;
 }
 
 
 Register* PropertyAccessCompiler::store_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3.
+  // receiver, name, scratch1, scratch2.
   Register receiver = StoreDescriptor::ReceiverRegister();
   Register name = StoreDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, ebx, edi, no_reg};
+  static Register registers[] = {receiver, name, ebx, edi};
   return registers;
 }
 
diff --git a/src/ic/ia32/handler-compiler-ia32.cc b/src/ic/ia32/handler-compiler-ia32.cc
index 132090d..2a883c7 100644
--- a/src/ic/ia32/handler-compiler-ia32.cc
+++ b/src/ic/ia32/handler-compiler-ia32.cc
@@ -199,7 +199,7 @@
   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
   bool call_data_undefined = false;
   // Put call data in place.
-  if (api_call_info->data()->IsUndefined()) {
+  if (api_call_info->data()->IsUndefined(isolate)) {
     call_data_undefined = true;
     __ mov(data, Immediate(isolate->factory()->undefined_value()));
   } else {
@@ -237,12 +237,12 @@
     MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name,
     Register scratch, Label* miss) {
   Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name);
-  DCHECK(cell->value()->IsTheHole());
-  Factory* factory = masm->isolate()->factory();
-  Handle<WeakCell> weak_cell = factory->NewWeakCell(cell);
+  Isolate* isolate = masm->isolate();
+  DCHECK(cell->value()->IsTheHole(isolate));
+  Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
   __ LoadWeakValue(scratch, weak_cell, miss);
   __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset),
-         Immediate(factory->the_hole_value()));
+         Immediate(isolate->factory()->the_hole_value()));
   __ j(not_equal, miss);
 }
 
@@ -439,28 +439,25 @@
   DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
          !scratch2.is(scratch1));
 
-  if (FLAG_eliminate_prototype_chain_checks) {
-    Handle<Cell> validity_cell =
-        Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
-    if (!validity_cell.is_null()) {
-      DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
-                validity_cell->value());
-      // Operand::ForCell(...) points to the cell's payload!
-      __ cmp(Operand::ForCell(validity_cell),
-             Immediate(Smi::FromInt(Map::kPrototypeChainValid)));
-      __ j(not_equal, miss);
-    }
+  Handle<Cell> validity_cell =
+      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
+  if (!validity_cell.is_null()) {
+    DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
+    // Operand::ForCell(...) points to the cell's payload!
+    __ cmp(Operand::ForCell(validity_cell),
+           Immediate(Smi::FromInt(Map::kPrototypeChainValid)));
+    __ j(not_equal, miss);
+  }
 
-    // The prototype chain of primitives (and their JSValue wrappers) depends
-    // on the native context, which can't be guarded by validity cells.
-    // |object_reg| holds the native context specific prototype in this case;
-    // we need to check its map.
-    if (check == CHECK_ALL_MAPS) {
-      __ mov(scratch1, FieldOperand(object_reg, HeapObject::kMapOffset));
-      Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
-      __ CmpWeakValue(scratch1, cell, scratch2);
-      __ j(not_equal, miss);
-    }
+  // The prototype chain of primitives (and their JSValue wrappers) depends
+  // on the native context, which can't be guarded by validity cells.
+  // |object_reg| holds the native context specific prototype in this case;
+  // we need to check its map.
+  if (check == CHECK_ALL_MAPS) {
+    __ mov(scratch1, FieldOperand(object_reg, HeapObject::kMapOffset));
+    Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
+    __ CmpWeakValue(scratch1, cell, scratch2);
+    __ j(not_equal, miss);
   }
 
   // Keep track of the current object in register reg.
@@ -496,8 +493,10 @@
            !current_map->is_access_check_needed());
 
     prototype = handle(JSObject::cast(current_map->prototype()));
-    if (current_map->is_dictionary_map() &&
-        !current_map->IsJSGlobalObjectMap()) {
+    if (current_map->IsJSGlobalObjectMap()) {
+      GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
+                                name, scratch2, miss);
+    } else if (current_map->is_dictionary_map()) {
       DCHECK(!current_map->IsJSGlobalProxyMap());  // Proxy maps are fast.
       if (!name->IsUniqueName()) {
         DCHECK(name->IsString());
@@ -507,34 +506,12 @@
              current->property_dictionary()->FindEntry(name) ==
                  NameDictionary::kNotFound);
 
-      if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
+      if (depth > 1) {
         // TODO(jkummerow): Cache and re-use weak cell.
         __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
       }
       GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
                                        scratch2);
-
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
-        __ mov(holder_reg, FieldOperand(scratch1, Map::kPrototypeOffset));
-      }
-    } else {
-      Register map_reg = scratch1;
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ mov(map_reg, FieldOperand(reg, HeapObject::kMapOffset));
-      }
-      if (current_map->IsJSGlobalObjectMap()) {
-        GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
-                                  name, scratch2, miss);
-      } else if (!FLAG_eliminate_prototype_chain_checks &&
-                 (depth != 1 || check == CHECK_ALL_MAPS)) {
-        Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-        __ CmpWeakValue(map_reg, cell, scratch2);
-        __ j(not_equal, miss);
-      }
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ mov(holder_reg, FieldOperand(map_reg, Map::kPrototypeOffset));
-      }
     }
 
     reg = holder_reg;  // From now on the object will be in holder_reg.
@@ -548,17 +525,8 @@
   // Log the check depth.
   LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
 
-  if (!FLAG_eliminate_prototype_chain_checks &&
-      (depth != 0 || check == CHECK_ALL_MAPS)) {
-    // Check the holder map.
-    __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
-    Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-    __ CmpWeakValue(scratch1, cell, scratch2);
-    __ j(not_equal, miss);
-  }
-
   bool return_holder = return_what == RETURN_HOLDER;
-  if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
+  if (return_holder && depth != 0) {
     __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
   }
 
@@ -594,58 +562,6 @@
 }
 
 
-void NamedLoadHandlerCompiler::GenerateLoadCallback(
-    Register reg, Handle<AccessorInfo> callback) {
-  DCHECK(!AreAliased(scratch2(), scratch3(), receiver()));
-  DCHECK(!AreAliased(scratch2(), scratch3(), reg));
-
-  // Insert additional parameters into the stack frame above return address.
-  __ pop(scratch3());  // Get return address to place it below.
-
-  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
-  // name below the exit frame to make GC aware of them.
-  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
-  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
-  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
-  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
-  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
-  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
-
-  __ push(receiver());  // receiver
-  // Push data from AccessorInfo.
-  Handle<Object> data(callback->data(), isolate());
-  if (data->IsUndefined() || data->IsSmi()) {
-    __ push(Immediate(data));
-  } else {
-    Handle<WeakCell> cell =
-        isolate()->factory()->NewWeakCell(Handle<HeapObject>::cast(data));
-    // The callback is alive if this instruction is executed,
-    // so the weak cell is not cleared and points to data.
-    __ GetWeakValue(scratch2(), cell);
-    __ push(scratch2());
-  }
-  __ push(Immediate(isolate()->factory()->undefined_value()));  // ReturnValue
-  // ReturnValue default value
-  __ push(Immediate(isolate()->factory()->undefined_value()));
-  __ push(Immediate(reinterpret_cast<int>(isolate())));
-  __ push(reg);  // holder
-  __ push(Immediate(Smi::FromInt(0)));  // should_throw_on_error -> false
-
-  __ push(name());  // name
-  __ push(scratch3());  // Restore return address.
-
-  // Abi for CallApiGetter
-  Register getter_address = ApiGetterDescriptor::function_address();
-  Address function_address = v8::ToCData<Address>(callback->getter());
-  __ mov(getter_address, Immediate(function_address));
-
-  CallApiGetterStub stub(isolate());
-  __ TailCallStub(&stub);
-}
-
-
 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
   // Return the constant value.
   __ LoadObject(eax, value);
@@ -656,7 +572,7 @@
 void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
     LookupIterator* it, Register holder_reg) {
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
 
   // Compile the interceptor call, followed by inline code to load the
   // property from further up the prototype chain if the call fails.
@@ -723,7 +639,7 @@
 
 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
   // Call the runtime system to load the interceptor.
   __ pop(scratch2());  // save old return address
   PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
@@ -744,7 +660,7 @@
   __ push(holder_reg);
   // If the callback cannot leak, then push the callback directly,
   // otherwise wrap it in a weak cell.
-  if (callback->data()->IsUndefined() || callback->data()->IsSmi()) {
+  if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) {
     __ Push(callback);
   } else {
     Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback);
@@ -759,7 +675,7 @@
   __ TailCallRuntime(Runtime::kStoreCallbackProperty);
 
   // Return the generated code.
-  return GetCode(kind(), Code::FAST, name);
+  return GetCode(kind(), name);
 }
 
 
@@ -801,7 +717,7 @@
   FrontendFooter(name, &miss);
 
   // Return the generated code.
-  return GetCode(kind(), Code::NORMAL, name);
+  return GetCode(kind(), name);
 }
 
 
diff --git a/src/ic/ia32/ic-ia32.cc b/src/ic/ia32/ic-ia32.cc
index e66716f..4fa990d 100644
--- a/src/ic/ia32/ic-ia32.cc
+++ b/src/ic/ia32/ic-ia32.cc
@@ -336,8 +336,8 @@
   __ push(Immediate(Smi::FromInt(slot)));
   __ push(Immediate(dummy_vector));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::KEYED_LOAD_IC, flags,
                                                receiver, key, ebx, edi);
 
@@ -519,10 +519,10 @@
   __ JumpIfSmi(receiver, &slow);
   // Get the map from the receiver.
   __ mov(edi, FieldOperand(receiver, HeapObject::kMapOffset));
-  // Check that the receiver does not require access checks and is not observed.
-  // The generic stub does not perform map checks or handle observed objects.
+  // Check that the receiver does not require access checks.
+  // The generic stub does not perform map checks.
   __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
-            Immediate(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved));
+            Immediate(1 << Map::kIsAccessCheckNeeded));
   __ j(not_zero, &slow);
   // Check that the key is a smi.
   __ JumpIfNotSmi(key, &maybe_name_key);
@@ -563,10 +563,10 @@
   __ push(Immediate(Smi::FromInt(slot)));
   __ push(Immediate(dummy_vector));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags,
-                                               receiver, key, edi, no_reg);
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
+  masm->isolate()->stub_cache()->GenerateProbe(
+      masm, Code::KEYED_STORE_IC, flags, receiver, key, edi, no_reg);
 
   __ pop(VectorStoreICDescriptor::VectorRegister());
   __ pop(VectorStoreICDescriptor::SlotRegister());
@@ -708,15 +708,6 @@
   __ TailCallRuntime(Runtime::kKeyedGetProperty);
 }
 
-
-void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
-  // This shouldn't be called.
-  // TODO(mvstanton): remove this method.
-  __ int3();
-  return;
-}
-
-
 static void StoreIC_PushArgs(MacroAssembler* masm) {
   Register receiver = StoreDescriptor::ReceiverRegister();
   Register name = StoreDescriptor::NameRegister();
@@ -836,8 +827,9 @@
   // condition code uses at the patched jump.
   uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address);
   if (FLAG_trace_ic) {
-    PrintF("[  patching ic at %p, test=%p, delta=%d\n", address,
-           test_instruction_address, delta);
+    PrintF("[  patching ic at %p, test=%p, delta=%d\n",
+           static_cast<void*>(address),
+           static_cast<void*>(test_instruction_address), delta);
   }
 
   // Patch with a short conditional jump. Enabling means switching from a short
diff --git a/src/ic/ia32/stub-cache-ia32.cc b/src/ic/ia32/stub-cache-ia32.cc
index fcfae4b..5a32858 100644
--- a/src/ic/ia32/stub-cache-ia32.cc
+++ b/src/ic/ia32/stub-cache-ia32.cc
@@ -153,9 +153,6 @@
   // being 12.
   DCHECK(sizeof(Entry) == 12);
 
-  // Assert the flags do not name a specific type.
-  DCHECK(Code::ExtractTypeFromFlags(flags) == 0);
-
   // Assert that there are no register conflicts.
   DCHECK(!scratch.is(receiver));
   DCHECK(!scratch.is(name));
diff --git a/src/ic/ic-compiler.cc b/src/ic/ic-compiler.cc
index 9f1d87a..af025fb 100644
--- a/src/ic/ic-compiler.cc
+++ b/src/ic/ic-compiler.cc
@@ -6,35 +6,14 @@
 
 #include "src/ic/handler-compiler.h"
 #include "src/ic/ic-inl.h"
-#include "src/profiler/cpu-profiler.h"
-
 
 namespace v8 {
 namespace internal {
 
 
-Handle<Code> PropertyICCompiler::Find(Handle<Name> name,
-                                      Handle<Map> stub_holder, Code::Kind kind,
-                                      ExtraICState extra_state,
-                                      CacheHolderFlag cache_holder) {
-  Code::Flags flags =
-      Code::ComputeMonomorphicFlags(kind, extra_state, cache_holder);
-  Object* probe = stub_holder->FindInCodeCache(*name, flags);
-  if (probe->IsCode()) return handle(Code::cast(probe));
-  return Handle<Code>::null();
-}
-
-
-bool PropertyICCompiler::IncludesNumberMap(MapHandleList* maps) {
-  for (int i = 0; i < maps->length(); ++i) {
-    if (maps->at(i)->instance_type() == HEAP_NUMBER_TYPE) return true;
-  }
-  return false;
-}
-
-
 Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
     Handle<Map> receiver_map, ExtraICState extra_ic_state) {
+  // TODO(ishell): remove extra_ic_state
   Isolate* isolate = receiver_map->GetIsolate();
   bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
   ElementsKind elements_kind = receiver_map->elements_kind();
@@ -46,179 +25,67 @@
       *receiver_map == isolate->get_initial_js_array_map(elements_kind);
   Handle<Code> stub;
   if (receiver_map->has_indexed_interceptor()) {
+    TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadIndexedInterceptorStub);
     stub = LoadIndexedInterceptorStub(isolate).GetCode();
   } else if (receiver_map->IsStringMap()) {
+    TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadIndexedStringStub);
     stub = LoadIndexedStringStub(isolate).GetCode();
   } else if (receiver_map->has_sloppy_arguments_elements()) {
+    TRACE_HANDLER_STATS(isolate, KeyedLoadIC_KeyedLoadSloppyArgumentsStub);
     stub = KeyedLoadSloppyArgumentsStub(isolate).GetCode();
   } else if (receiver_map->has_fast_elements() ||
              receiver_map->has_fixed_typed_array_elements()) {
+    TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadFastElementStub);
     stub = LoadFastElementStub(isolate, is_js_array, elements_kind,
                                convert_hole_to_undefined).GetCode();
   } else {
     DCHECK(receiver_map->has_dictionary_elements());
-    stub = LoadDictionaryElementStub(isolate, LoadICState(extra_ic_state))
-               .GetCode();
+    TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadDictionaryElementStub);
+    stub = LoadDictionaryElementStub(isolate).GetCode();
   }
   return stub;
 }
 
-
 Handle<Code> PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
-    Handle<Map> receiver_map, LanguageMode language_mode,
-    KeyedAccessStoreMode store_mode) {
+    Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
   Isolate* isolate = receiver_map->GetIsolate();
-  ExtraICState extra_state =
-      KeyedStoreIC::ComputeExtraICState(language_mode, store_mode);
 
   DCHECK(store_mode == STANDARD_STORE ||
          store_mode == STORE_AND_GROW_NO_TRANSITION ||
          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
          store_mode == STORE_NO_TRANSITION_HANDLE_COW);
 
-  PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state);
+  PropertyICCompiler compiler(isolate);
   Handle<Code> code =
       compiler.CompileKeyedStoreMonomorphicHandler(receiver_map, store_mode);
   return code;
 }
 
-
-Code* PropertyICCompiler::FindPreMonomorphic(Isolate* isolate, Code::Kind kind,
-                                             ExtraICState state) {
-  Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state);
-  UnseededNumberDictionary* dictionary =
-      isolate->heap()->non_monomorphic_cache();
-  int entry = dictionary->FindEntry(isolate, flags);
-  DCHECK(entry != -1);
-  Object* code = dictionary->ValueAt(entry);
-  // This might be called during the marking phase of the collector
-  // hence the unchecked cast.
-  return reinterpret_cast<Code*>(code);
-}
-
-
-static void FillCache(Isolate* isolate, Handle<Code> code) {
-  Handle<UnseededNumberDictionary> dictionary = UnseededNumberDictionary::Set(
-      isolate->factory()->non_monomorphic_cache(), code->flags(), code);
-  isolate->heap()->SetRootNonMonomorphicCache(*dictionary);
-}
-
-
-Handle<Code> PropertyICCompiler::ComputeStore(Isolate* isolate,
-                                              InlineCacheState ic_state,
-                                              ExtraICState extra_state) {
-  Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, ic_state, extra_state);
-  Handle<UnseededNumberDictionary> cache =
-      isolate->factory()->non_monomorphic_cache();
-  int entry = cache->FindEntry(isolate, flags);
-  if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
-
-  PropertyICCompiler compiler(isolate, Code::STORE_IC);
-  Handle<Code> code;
-  if (ic_state == UNINITIALIZED) {
-    code = compiler.CompileStoreInitialize(flags);
-  } else if (ic_state == PREMONOMORPHIC) {
-    code = compiler.CompileStorePreMonomorphic(flags);
-  } else if (ic_state == GENERIC) {
-    code = compiler.CompileStoreGeneric(flags);
-  } else if (ic_state == MEGAMORPHIC) {
-    code = compiler.CompileStoreMegamorphic(flags);
-  } else {
-    UNREACHABLE();
-  }
-
-  FillCache(isolate, code);
-  return code;
-}
-
-
 void PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers(
     MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
-    CodeHandleList* handlers, KeyedAccessStoreMode store_mode,
-    LanguageMode language_mode) {
+    CodeHandleList* handlers, KeyedAccessStoreMode store_mode) {
   Isolate* isolate = receiver_maps->at(0)->GetIsolate();
   DCHECK(store_mode == STANDARD_STORE ||
          store_mode == STORE_AND_GROW_NO_TRANSITION ||
          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
          store_mode == STORE_NO_TRANSITION_HANDLE_COW);
-  ExtraICState extra_state =
-      KeyedStoreIC::ComputeExtraICState(language_mode, store_mode);
-  PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state);
+  PropertyICCompiler compiler(isolate);
   compiler.CompileKeyedStorePolymorphicHandlers(
       receiver_maps, transitioned_maps, handlers, store_mode);
 }
 
 
-Handle<Code> PropertyICCompiler::CompileLoadInitialize(Code::Flags flags) {
-  LoadIC::GenerateInitialize(masm());
-  Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize");
-  PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG,
-                                     AbstractCode::cast(*code), 0));
-  return code;
-}
-
-
-Handle<Code> PropertyICCompiler::CompileStoreInitialize(Code::Flags flags) {
-  StoreIC::GenerateInitialize(masm());
-  Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreInitialize");
-  PROFILE(isolate(), CodeCreateEvent(Logger::STORE_INITIALIZE_TAG,
-                                     AbstractCode::cast(*code), 0));
-  return code;
-}
-
-
-Handle<Code> PropertyICCompiler::CompileStorePreMonomorphic(Code::Flags flags) {
-  StoreIC::GeneratePreMonomorphic(masm());
-  Handle<Code> code = GetCodeWithFlags(flags, "CompileStorePreMonomorphic");
-  PROFILE(isolate(), CodeCreateEvent(Logger::STORE_PREMONOMORPHIC_TAG,
-                                     AbstractCode::cast(*code), 0));
-  return code;
-}
-
-
-Handle<Code> PropertyICCompiler::CompileStoreGeneric(Code::Flags flags) {
-  ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
-  LanguageMode language_mode = StoreICState::GetLanguageMode(extra_state);
-  GenerateRuntimeSetProperty(masm(), language_mode);
-  Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric");
-  PROFILE(isolate(), CodeCreateEvent(Logger::STORE_GENERIC_TAG,
-                                     AbstractCode::cast(*code), 0));
-  return code;
-}
-
-
-Handle<Code> PropertyICCompiler::CompileStoreMegamorphic(Code::Flags flags) {
-  StoreIC::GenerateMegamorphic(masm());
-  Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic");
-  PROFILE(isolate(), CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG,
-                                     AbstractCode::cast(*code), 0));
-  return code;
-}
-
-
-Handle<Code> PropertyICCompiler::GetCode(Code::Kind kind, Code::StubType type,
-                                         Handle<Name> name,
-                                         InlineCacheState state) {
-  Code::Flags flags =
-      Code::ComputeFlags(kind, state, extra_ic_state_, type, cache_holder());
-  Handle<Code> code = GetCodeWithFlags(flags, name);
-  PROFILE(isolate(),
-          CodeCreateEvent(log_kind(code), AbstractCode::cast(*code), *name));
-#ifdef DEBUG
-  code->VerifyEmbeddedObjects();
-#endif
-  return code;
-}
-
-
 void PropertyICCompiler::CompileKeyedStorePolymorphicHandlers(
     MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
     CodeHandleList* handlers, KeyedAccessStoreMode store_mode) {
   for (int i = 0; i < receiver_maps->length(); ++i) {
     Handle<Map> receiver_map(receiver_maps->at(i));
     Handle<Code> cached_stub;
-    Handle<Map> transitioned_map =
-        Map::FindTransitionedMap(receiver_map, receiver_maps);
+    Handle<Map> transitioned_map;
+    {
+      Map* tmap = receiver_map->FindElementsKindTransitionedMap(receiver_maps);
+      if (tmap != nullptr) transitioned_map = handle(tmap);
+    }
 
     // TODO(mvstanton): The code below is doing pessimistic elements
     // transitions. I would like to stop doing that and rely on Allocation Site
@@ -265,34 +132,21 @@
   bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
   Handle<Code> stub;
   if (receiver_map->has_sloppy_arguments_elements()) {
+    TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_KeyedStoreSloppyArgumentsStub);
     stub = KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
   } else if (receiver_map->has_fast_elements() ||
              receiver_map->has_fixed_typed_array_elements()) {
+    TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreFastElementStub);
     stub = StoreFastElementStub(isolate(), is_jsarray, elements_kind,
                                 store_mode).GetCode();
   } else {
+    TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreElementStub);
     stub = StoreElementStub(isolate(), elements_kind, store_mode).GetCode();
   }
   return stub;
 }
 
 
-Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic(
-    Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
-  Handle<Code> stub =
-      CompileKeyedStoreMonomorphicHandler(receiver_map, store_mode);
-
-  Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
-
-  __ DispatchWeakMap(receiver(), scratch1(), scratch2(), cell, stub,
-                     DO_SMI_CHECK);
-
-  TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss);
-
-  return GetCode(kind(), Code::NORMAL, factory()->empty_string());
-}
-
-
 #undef __
 }  // namespace internal
 }  // namespace v8
diff --git a/src/ic/ic-compiler.h b/src/ic/ic-compiler.h
index 3a5aecc..9d8884f 100644
--- a/src/ic/ic-compiler.h
+++ b/src/ic/ic-compiler.h
@@ -13,25 +13,15 @@
 
 class PropertyICCompiler : public PropertyAccessCompiler {
  public:
-  // Finds the Code object stored in the Heap::non_monomorphic_cache().
-  static Code* FindPreMonomorphic(Isolate* isolate, Code::Kind kind,
-                                  ExtraICState extra_ic_state);
-
-  // Named
-  static Handle<Code> ComputeStore(Isolate* isolate, InlineCacheState ic_state,
-                                   ExtraICState extra_state);
-
   // Keyed
   static Handle<Code> ComputeKeyedLoadMonomorphicHandler(
       Handle<Map> receiver_map, ExtraICState extra_ic_state);
 
   static Handle<Code> ComputeKeyedStoreMonomorphicHandler(
-      Handle<Map> receiver_map, LanguageMode language_mode,
-      KeyedAccessStoreMode store_mode);
+      Handle<Map> receiver_map, KeyedAccessStoreMode store_mode);
   static void ComputeKeyedStorePolymorphicHandlers(
       MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
-      CodeHandleList* handlers, KeyedAccessStoreMode store_mode,
-      LanguageMode language_mode);
+      CodeHandleList* handlers, KeyedAccessStoreMode store_mode);
 
   // Helpers
   // TODO(verwaest): Move all uses of these helpers to the PropertyICCompiler
@@ -41,57 +31,16 @@
 
 
  private:
-  PropertyICCompiler(Isolate* isolate, Code::Kind kind,
-                     ExtraICState extra_ic_state = kNoExtraICState,
-                     CacheHolderFlag cache_holder = kCacheOnReceiver)
-      : PropertyAccessCompiler(isolate, kind, cache_holder),
-        extra_ic_state_(extra_ic_state) {}
-
-  static Handle<Code> Find(Handle<Name> name, Handle<Map> stub_holder_map,
-                           Code::Kind kind,
-                           ExtraICState extra_ic_state = kNoExtraICState,
-                           CacheHolderFlag cache_holder = kCacheOnReceiver);
-
-  Handle<Code> CompileLoadInitialize(Code::Flags flags);
-  Handle<Code> CompileStoreInitialize(Code::Flags flags);
-  Handle<Code> CompileStorePreMonomorphic(Code::Flags flags);
-  Handle<Code> CompileStoreGeneric(Code::Flags flags);
-  Handle<Code> CompileStoreMegamorphic(Code::Flags flags);
+  explicit PropertyICCompiler(Isolate* isolate)
+      : PropertyAccessCompiler(isolate, Code::KEYED_STORE_IC,
+                               kCacheOnReceiver) {}
 
   Handle<Code> CompileKeyedStoreMonomorphicHandler(
       Handle<Map> receiver_map, KeyedAccessStoreMode store_mode);
-  Handle<Code> CompileKeyedStoreMonomorphic(Handle<Map> receiver_map,
-                                            KeyedAccessStoreMode store_mode);
   void CompileKeyedStorePolymorphicHandlers(MapHandleList* receiver_maps,
                                             MapHandleList* transitioned_maps,
                                             CodeHandleList* handlers,
                                             KeyedAccessStoreMode store_mode);
-
-  bool IncludesNumberMap(MapHandleList* maps);
-
-  Handle<Code> GetCode(Code::Kind kind, Code::StubType type, Handle<Name> name,
-                       InlineCacheState state = MONOMORPHIC);
-
-  Logger::LogEventsAndTags log_kind(Handle<Code> code) {
-    if (kind() == Code::LOAD_IC) {
-      return code->ic_state() == MONOMORPHIC ? Logger::LOAD_IC_TAG
-                                             : Logger::LOAD_POLYMORPHIC_IC_TAG;
-    } else if (kind() == Code::KEYED_LOAD_IC) {
-      return code->ic_state() == MONOMORPHIC
-                 ? Logger::KEYED_LOAD_IC_TAG
-                 : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG;
-    } else if (kind() == Code::STORE_IC) {
-      return code->ic_state() == MONOMORPHIC ? Logger::STORE_IC_TAG
-                                             : Logger::STORE_POLYMORPHIC_IC_TAG;
-    } else {
-      DCHECK_EQ(Code::KEYED_STORE_IC, kind());
-      return code->ic_state() == MONOMORPHIC
-                 ? Logger::KEYED_STORE_IC_TAG
-                 : Logger::KEYED_STORE_POLYMORPHIC_IC_TAG;
-    }
-  }
-
-  const ExtraICState extra_ic_state_;
 };
 
 
diff --git a/src/ic/ic-inl.h b/src/ic/ic-inl.h
index 998bd8c..f77c40a 100644
--- a/src/ic/ic-inl.h
+++ b/src/ic/ic-inl.h
@@ -87,42 +87,12 @@
 
 void IC::set_target(Code* code) {
   SetTargetAtAddress(address(), code, constant_pool());
-  target_set_ = true;
 }
 
-
-void LoadIC::set_target(Code* code) {
-  // The contextual mode must be preserved across IC patching.
-  DCHECK(LoadICState::GetTypeofMode(code->extra_ic_state()) ==
-         LoadICState::GetTypeofMode(target()->extra_ic_state()));
-
-  IC::set_target(code);
-}
-
-
-void StoreIC::set_target(Code* code) {
-  // Language mode must be preserved across IC patching.
-  DCHECK(StoreICState::GetLanguageMode(code->extra_ic_state()) ==
-         StoreICState::GetLanguageMode(target()->extra_ic_state()));
-  IC::set_target(code);
-}
-
-
-void KeyedStoreIC::set_target(Code* code) {
-  // Language mode must be preserved across IC patching.
-  DCHECK(StoreICState::GetLanguageMode(code->extra_ic_state()) ==
-         language_mode());
-  IC::set_target(code);
-}
-
-
-Code* IC::raw_target() const {
+Code* IC::target() const {
   return GetTargetAtAddress(address(), constant_pool());
 }
 
-void IC::UpdateTarget() { target_ = handle(raw_target(), isolate_); }
-
-
 Handle<Map> IC::GetHandlerCacheHolder(Handle<Map> receiver_map,
                                       bool receiver_is_holder, Isolate* isolate,
                                       CacheHolderFlag* flag) {
diff --git a/src/ic/ic-state.cc b/src/ic/ic-state.cc
index bf1e45f..d157c92 100644
--- a/src/ic/ic-state.cc
+++ b/src/ic/ic-state.cc
@@ -257,10 +257,10 @@
 
   if (old_extra_ic_state == GetExtraICState()) {
     // Tagged operations can lead to non-truncating HChanges
-    if (left->IsUndefined() || left->IsBoolean()) {
+    if (left->IsUndefined(isolate_) || left->IsBoolean()) {
       left_kind_ = GENERIC;
     } else {
-      DCHECK(right->IsUndefined() || right->IsBoolean());
+      DCHECK(right->IsUndefined(isolate_) || right->IsBoolean());
       right_kind_ = GENERIC;
     }
   }
@@ -274,7 +274,7 @@
   if (object->IsBoolean() && is_truncating) {
     // Booleans will be automatically truncated by HChange.
     new_kind = INT32;
-  } else if (object->IsUndefined()) {
+  } else if (object->IsUndefined(isolate_)) {
     // Undefined will be automatically truncated by HChange.
     new_kind = is_truncating ? INT32 : NUMBER;
   } else if (object->IsSmi()) {
@@ -446,8 +446,9 @@
 
 // static
 CompareICState::State CompareICState::TargetState(
-    State old_state, State old_left, State old_right, Token::Value op,
-    bool has_inlined_smi_code, Handle<Object> x, Handle<Object> y) {
+    Isolate* isolate, State old_state, State old_left, State old_right,
+    Token::Value op, bool has_inlined_smi_code, Handle<Object> x,
+    Handle<Object> y) {
   switch (old_state) {
     case UNINITIALIZED:
       if (x->IsBoolean() && y->IsBoolean()) return BOOLEAN;
@@ -456,8 +457,8 @@
       if (Token::IsOrderedRelationalCompareOp(op)) {
         // Ordered comparisons treat undefined as NaN, so the
         // NUMBER stub will do the right thing.
-        if ((x->IsNumber() && y->IsUndefined()) ||
-            (y->IsNumber() && x->IsUndefined())) {
+        if ((x->IsNumber() && y->IsUndefined(isolate)) ||
+            (y->IsNumber() && x->IsUndefined(isolate))) {
           return NUMBER;
         }
       }
diff --git a/src/ic/ic-state.h b/src/ic/ic-state.h
index e1d33f8..b12b17d 100644
--- a/src/ic/ic-state.h
+++ b/src/ic/ic-state.h
@@ -193,13 +193,13 @@
 
   static const char* GetStateName(CompareICState::State state);
 
-  static State TargetState(State old_state, State old_left, State old_right,
-                           Token::Value op, bool has_inlined_smi_code,
-                           Handle<Object> x, Handle<Object> y);
+  static State TargetState(Isolate* isolate, State old_state, State old_left,
+                           State old_right, Token::Value op,
+                           bool has_inlined_smi_code, Handle<Object> x,
+                           Handle<Object> y);
 };
 
-
-class LoadICState final BASE_EMBEDDED {
+class LoadGlobalICState final BASE_EMBEDDED {
  private:
   class TypeofModeBits : public BitField<TypeofMode, 0, 1> {};
   STATIC_ASSERT(static_cast<int>(INSIDE_TYPEOF) == 0);
@@ -208,9 +208,10 @@
  public:
   static const uint32_t kNextBitFieldOffset = TypeofModeBits::kNext;
 
-  explicit LoadICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {}
+  explicit LoadGlobalICState(ExtraICState extra_ic_state)
+      : state_(extra_ic_state) {}
 
-  explicit LoadICState(TypeofMode typeof_mode)
+  explicit LoadGlobalICState(TypeofMode typeof_mode)
       : state_(TypeofModeBits::encode(typeof_mode)) {}
 
   ExtraICState GetExtraICState() const { return state_; }
@@ -218,7 +219,7 @@
   TypeofMode typeof_mode() const { return TypeofModeBits::decode(state_); }
 
   static TypeofMode GetTypeofMode(ExtraICState state) {
-    return LoadICState(state).typeof_mode();
+    return LoadGlobalICState(state).typeof_mode();
   }
 };
 
diff --git a/src/ic/ic.cc b/src/ic/ic.cc
index c5835e4..5d20420 100644
--- a/src/ic/ic.cc
+++ b/src/ic/ic.cc
@@ -5,11 +5,10 @@
 #include "src/ic/ic.h"
 
 #include "src/accessors.h"
+#include "src/api-arguments-inl.h"
 #include "src/api.h"
-#include "src/api-arguments.h"
 #include "src/arguments.h"
 #include "src/base/bits.h"
-#include "src/code-factory.h"
 #include "src/codegen.h"
 #include "src/conversions.h"
 #include "src/execution.h"
@@ -17,14 +16,14 @@
 #include "src/frames-inl.h"
 #include "src/ic/call-optimization.h"
 #include "src/ic/handler-compiler.h"
-#include "src/ic/ic-inl.h"
 #include "src/ic/ic-compiler.h"
+#include "src/ic/ic-inl.h"
 #include "src/ic/stub-cache.h"
 #include "src/isolate-inl.h"
 #include "src/macro-assembler.h"
 #include "src/prototype.h"
-#include "src/runtime/runtime.h"
 #include "src/runtime/runtime-utils.h"
+#include "src/runtime/runtime.h"
 #include "src/tracing/trace-event.h"
 
 namespace v8 {
@@ -38,7 +37,7 @@
       return '.';
     case MONOMORPHIC:
       return '1';
-    case PROTOTYPE_FAILURE:
+    case RECOMPUTE_HANDLER:
       return '^';
     case POLYMORPHIC:
       return 'P';
@@ -46,12 +45,6 @@
       return 'N';
     case GENERIC:
       return 'G';
-
-    // We never see the debugger states here, because the state is
-    // computed from the original code - not the patched code. Let
-    // these cases fall through to the unreachable code below.
-    case DEBUG_STUB:
-      break;
   }
   UNREACHABLE();
   return 0;
@@ -95,8 +88,8 @@
 void IC::TraceIC(const char* type, Handle<Object> name) {
   if (FLAG_trace_ic) {
     if (AddressIsDeoptimizedCode()) return;
-    State new_state =
-        UseVector() ? nexus()->StateFromFeedback() : raw_target()->ic_state();
+    DCHECK(UseVector());
+    State new_state = nexus()->StateFromFeedback();
     TraceIC(type, name, state(), new_state);
   }
 }
@@ -105,8 +98,7 @@
 void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
                  State new_state) {
   if (FLAG_trace_ic) {
-    Code* new_target = raw_target();
-    PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type);
+    PrintF("[%s%s in ", is_keyed() ? "Keyed" : "", type);
 
     // TODO(jkummerow): Add support for "apply". The logic is roughly:
     // marker = [fp_ + kMarkerOffset];
@@ -123,19 +115,18 @@
     }
 
     const char* modifier = "";
-    if (new_target->kind() == Code::KEYED_STORE_IC) {
+    if (kind() == Code::KEYED_STORE_IC) {
       KeyedAccessStoreMode mode =
           casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode();
       modifier = GetTransitionMarkModifier(mode);
     }
-    PrintF(" (%c->%c%s) ", TransitionMarkFromState(old_state),
-           TransitionMarkFromState(new_state), modifier);
-#ifdef OBJECT_PRINT
-    OFStream os(stdout);
-    name->Print(os);
-#else
+    void* map = nullptr;
+    if (!receiver_map().is_null()) {
+      map = reinterpret_cast<void*>(*receiver_map());
+    }
+    PrintF(" (%c->%c%s) map=%p ", TransitionMarkFromState(old_state),
+           TransitionMarkFromState(new_state), modifier, map);
     name->ShortPrint(stdout);
-#endif
     PrintF("]\n");
   }
 }
@@ -146,7 +137,6 @@
 
 IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus)
     : isolate_(isolate),
-      target_set_(false),
       vector_set_(false),
       target_maps_set_(false),
       nexus_(nexus) {
@@ -185,13 +175,34 @@
     constant_pool_address_ = constant_pool;
   }
   pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
-  target_ = handle(raw_target(), isolate);
-  kind_ = target_->kind();
-  state_ = UseVector() ? nexus->StateFromFeedback() : target_->ic_state();
+  Code* target = this->target();
+  kind_ = target->kind();
+  state_ = UseVector() ? nexus->StateFromFeedback() : StateFromCode(target);
   old_state_ = state_;
-  extra_ic_state_ = target_->extra_ic_state();
+  extra_ic_state_ = target->extra_ic_state();
 }
 
+InlineCacheState IC::StateFromCode(Code* code) {
+  Isolate* isolate = code->GetIsolate();
+  switch (code->kind()) {
+    case Code::BINARY_OP_IC: {
+      BinaryOpICState state(isolate, code->extra_ic_state());
+      return state.GetICState();
+    }
+    case Code::COMPARE_IC: {
+      CompareICStub stub(isolate, code->extra_ic_state());
+      return stub.GetICState();
+    }
+    case Code::TO_BOOLEAN_IC: {
+      ToBooleanICStub stub(isolate, code->extra_ic_state());
+      return stub.GetICState();
+    }
+    default:
+      if (code->is_debug_stub()) return UNINITIALIZED;
+      UNREACHABLE();
+      return UNINITIALIZED;
+  }
+}
 
 SharedFunctionInfo* IC::GetSharedFunctionInfo() const {
   // Compute the JavaScript frame for the frame pointer of this IC
@@ -226,7 +237,6 @@
   return host->kind() == Code::OPTIMIZED_FUNCTION;
 }
 
-
 static void LookupForRead(LookupIterator* it) {
   for (; it->IsFound(); it->Next()) {
     switch (it->state()) {
@@ -238,7 +248,8 @@
       case LookupIterator::INTERCEPTOR: {
         // If there is a getter, return; otherwise loop to perform the lookup.
         Handle<JSObject> holder = it->GetHolder<JSObject>();
-        if (!holder->GetNamedInterceptor()->getter()->IsUndefined()) {
+        if (!holder->GetNamedInterceptor()->getter()->IsUndefined(
+                it->isolate())) {
           return;
         }
         break;
@@ -258,15 +269,15 @@
   }
 }
 
+bool IC::ShouldRecomputeHandler(Handle<Object> receiver, Handle<String> name) {
+  if (!RecomputeHandlerForName(name)) return false;
 
-bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
-                                                Handle<String> name) {
-  if (!IsNameCompatibleWithPrototypeFailure(name)) return false;
-  if (UseVector()) {
-    maybe_handler_ = nexus()->FindHandlerForMap(receiver_map());
-  } else {
-    maybe_handler_ = target()->FindHandlerForMap(*receiver_map());
-  }
+  DCHECK(UseVector());
+  maybe_handler_ = nexus()->FindHandlerForMap(receiver_map());
+
+  // This is a contextual access, always just update the handler and stay
+  // monomorphic.
+  if (kind() == Code::LOAD_GLOBAL_IC) return true;
 
   // The current map wasn't handled yet. There's no reason to stay monomorphic,
   // *unless* we're moving from a deprecated map to its replacement, or
@@ -283,38 +294,15 @@
                                                receiver_map()->elements_kind());
   }
 
-  CacheHolderFlag flag;
-  Handle<Map> ic_holder_map(GetICCacheHolder(receiver_map(), isolate(), &flag));
-
-  DCHECK(flag != kCacheOnReceiver || receiver->IsJSObject());
-  DCHECK(flag != kCacheOnPrototype || !receiver->IsJSReceiver());
-  DCHECK(flag != kCacheOnPrototypeReceiverIsDictionary);
-
-  if (state() == MONOMORPHIC) {
-    int index = ic_holder_map->IndexInCodeCache(*name, *target());
-    if (index >= 0) {
-      ic_holder_map->RemoveFromCodeCache(*name, *target(), index);
-    }
-  }
-
-  if (receiver->IsJSGlobalObject()) {
-    Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(receiver);
-    LookupIterator it(global, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
-    if (it.state() == LookupIterator::ACCESS_CHECK) return false;
-    if (!it.IsFound()) return false;
-    return it.property_details().cell_type() == PropertyCellType::kConstant;
-  }
-
   return true;
 }
 
-
-bool IC::IsNameCompatibleWithPrototypeFailure(Handle<Object> name) {
-  if (target()->is_keyed_stub()) {
+bool IC::RecomputeHandlerForName(Handle<Object> name) {
+  if (is_keyed()) {
     // Determine whether the failure is due to a name failure.
     if (!name->IsName()) return false;
-    Name* stub_name =
-        UseVector() ? nexus()->FindFirstName() : target()->FindFirstName();
+    DCHECK(UseVector());
+    Name* stub_name = nexus()->FindFirstName();
     if (*name != stub_name) return false;
   }
 
@@ -326,15 +314,13 @@
   update_receiver_map(receiver);
   if (!name->IsString()) return;
   if (state() != MONOMORPHIC && state() != POLYMORPHIC) return;
-  if (receiver->IsUndefined() || receiver->IsNull()) return;
+  if (receiver->IsUndefined(isolate()) || receiver->IsNull(isolate())) return;
 
   // Remove the target from the code cache if it became invalid
   // because of changes in the prototype chain to avoid hitting it
   // again.
-  if (TryRemoveInvalidPrototypeDependentStub(receiver,
-                                             Handle<String>::cast(name))) {
-    MarkPrototypeFailure(name);
-    return;
+  if (ShouldRecomputeHandler(receiver, Handle<String>::cast(name))) {
+    MarkRecomputeHandler(name);
   }
 }
 
@@ -382,43 +368,11 @@
         *polymorphic_delta = 1;
       }
       break;
-    case PROTOTYPE_FAILURE:
-    case DEBUG_STUB:
+    case RECOMPUTE_HANDLER:
       UNREACHABLE();
   }
 }
 
-
-void IC::OnTypeFeedbackChanged(Isolate* isolate, Address address,
-                               State old_state, State new_state,
-                               bool target_remains_ic_stub) {
-  Code* host =
-      isolate->inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
-  if (host->kind() != Code::FUNCTION) return;
-
-  if (FLAG_type_info_threshold > 0 && target_remains_ic_stub &&
-      // Not all Code objects have TypeFeedbackInfo.
-      host->type_feedback_info()->IsTypeFeedbackInfo()) {
-    int polymorphic_delta = 0;  // "Polymorphic" here includes monomorphic.
-    int generic_delta = 0;      // "Generic" here includes megamorphic.
-    ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta,
-                              &generic_delta);
-    TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
-    info->change_ic_with_type_info_count(polymorphic_delta);
-    info->change_ic_generic_count(generic_delta);
-  }
-  if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
-    TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
-    info->change_own_type_change_checksum();
-  }
-  host->set_profiler_ticks(0);
-  isolate->runtime_profiler()->NotifyICChanged();
-  // TODO(2029): When an optimized function is patched, it would
-  // be nice to propagate the corresponding type information to its
-  // unoptimized version for the benefit of later inlining.
-}
-
-
 // static
 void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host) {
   if (host->kind() != Code::FUNCTION) return;
@@ -432,49 +386,51 @@
   // unoptimized version for the benefit of later inlining.
 }
 
-
 void IC::PostPatching(Address address, Code* target, Code* old_target) {
   // Type vector based ICs update these statistics at a different time because
   // they don't always patch on state change.
   if (ICUseVector(target->kind())) return;
 
-  Isolate* isolate = target->GetHeap()->isolate();
-  State old_state = UNINITIALIZED;
-  State new_state = UNINITIALIZED;
-  bool target_remains_ic_stub = false;
-  if (old_target->is_inline_cache_stub() && target->is_inline_cache_stub()) {
-    old_state = old_target->ic_state();
-    new_state = target->ic_state();
-    target_remains_ic_stub = true;
+  DCHECK(old_target->is_inline_cache_stub());
+  DCHECK(target->is_inline_cache_stub());
+  State old_state = StateFromCode(old_target);
+  State new_state = StateFromCode(target);
+
+  Isolate* isolate = target->GetIsolate();
+  Code* host =
+      isolate->inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
+  if (host->kind() != Code::FUNCTION) return;
+
+  // Not all Code objects have TypeFeedbackInfo.
+  if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
+    if (FLAG_type_info_threshold > 0) {
+      int polymorphic_delta = 0;  // "Polymorphic" here includes monomorphic.
+      int generic_delta = 0;      // "Generic" here includes megamorphic.
+      ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta,
+                                &generic_delta);
+      TypeFeedbackInfo* info =
+          TypeFeedbackInfo::cast(host->type_feedback_info());
+      info->change_ic_with_type_info_count(polymorphic_delta);
+      info->change_ic_generic_count(generic_delta);
+    }
+    TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
+    info->change_own_type_change_checksum();
   }
-
-  OnTypeFeedbackChanged(isolate, address, old_state, new_state,
-                        target_remains_ic_stub);
+  host->set_profiler_ticks(0);
+  isolate->runtime_profiler()->NotifyICChanged();
+  // TODO(2029): When an optimized function is patched, it would
+  // be nice to propagate the corresponding type information to its
+  // unoptimized version for the benefit of later inlining.
 }
 
-
 void IC::Clear(Isolate* isolate, Address address, Address constant_pool) {
   Code* target = GetTargetAtAddress(address, constant_pool);
 
   // Don't clear debug break inline cache as it will remove the break point.
   if (target->is_debug_stub()) return;
 
-  switch (target->kind()) {
-    case Code::LOAD_IC:
-    case Code::KEYED_LOAD_IC:
-    case Code::STORE_IC:
-    case Code::KEYED_STORE_IC:
-      return;
-    case Code::COMPARE_IC:
-      return CompareIC::Clear(isolate, address, target, constant_pool);
-    case Code::CALL_IC:  // CallICs are vector-based and cleared differently.
-    case Code::BINARY_OP_IC:
-    case Code::TO_BOOLEAN_IC:
-      // Clearing these is tricky and does not
-      // make any performance difference.
-      return;
-    default:
-      UNREACHABLE();
+  if (target->kind() == Code::COMPARE_IC) {
+    CompareIC::Clear(isolate, address, target, constant_pool);
   }
 }
 
@@ -508,16 +464,13 @@
   OnTypeFeedbackChanged(isolate, host);
 }
 
-
-void StoreIC::Clear(Isolate* isolate, Address address, Code* target,
-                    Address constant_pool) {
-  if (IsCleared(target)) return;
-  Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC,
-                                                      target->extra_ic_state());
-  SetTargetAtAddress(address, code, constant_pool);
+void LoadGlobalIC::Clear(Isolate* isolate, Code* host,
+                         LoadGlobalICNexus* nexus) {
+  if (IsCleared(nexus)) return;
+  nexus->ConfigureUninitialized();
+  OnTypeFeedbackChanged(isolate, host);
 }
 
-
 void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) {
   if (IsCleared(nexus)) return;
   nexus->ConfigurePremonomorphic();
@@ -525,15 +478,6 @@
 }
 
 
-void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target,
-                         Address constant_pool) {
-  if (IsCleared(target)) return;
-  Handle<Code> code = pre_monomorphic_stub(
-      isolate, StoreICState::GetLanguageMode(target->extra_ic_state()));
-  SetTargetAtAddress(address, *code, constant_pool);
-}
-
-
 void KeyedStoreIC::Clear(Isolate* isolate, Code* host,
                          KeyedStoreICNexus* nexus) {
   if (IsCleared(nexus)) return;
@@ -557,8 +501,9 @@
 // static
 Handle<Code> KeyedLoadIC::ChooseMegamorphicStub(Isolate* isolate,
                                                 ExtraICState extra_state) {
+  // TODO(ishell): remove extra_ic_state
   if (FLAG_compiled_keyed_generic_loads) {
-    return KeyedLoadGenericStub(isolate, LoadICState(extra_state)).GetCode();
+    return KeyedLoadGenericStub(isolate).GetCode();
   } else {
     return isolate->builtins()->KeyedLoadIC_Megamorphic();
   }
@@ -603,6 +548,9 @@
   if (kind() == Code::LOAD_IC) {
     LoadICNexus* nexus = casted_nexus<LoadICNexus>();
     nexus->ConfigureMonomorphic(map, handler);
+  } else if (kind() == Code::LOAD_GLOBAL_IC) {
+    LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>();
+    nexus->ConfigureHandlerMode(handler);
   } else if (kind() == Code::KEYED_LOAD_IC) {
     KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
     nexus->ConfigureMonomorphic(name, map, handler);
@@ -659,62 +607,21 @@
 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
   // If the object is undefined or null it's illegal to try to get any
   // of its properties; throw a TypeError in that case.
-  if (object->IsUndefined() || object->IsNull()) {
+  if (object->IsUndefined(isolate()) || object->IsNull(isolate())) {
     return TypeError(MessageTemplate::kNonObjectPropertyLoad, object, name);
   }
 
-  // Check if the name is trivially convertible to an index and get
-  // the element or char if so.
-  uint32_t index;
-  if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) {
-    // Rewrite to the generic keyed load stub.
-    if (FLAG_use_ic) {
-      DCHECK(UseVector());
-      ConfigureVectorState(MEGAMORPHIC, name);
-      TRACE_IC("LoadIC", name);
-      TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index");
-    }
-    Handle<Object> result;
-    ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
-                               Object::GetElement(isolate(), object, index),
-                               Object);
-    return result;
-  }
-
   bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
 
-  if (object->IsJSGlobalObject() && name->IsString()) {
-    // Look up in script context table.
-    Handle<String> str_name = Handle<String>::cast(name);
-    Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(object);
-    Handle<ScriptContextTable> script_contexts(
-        global->native_context()->script_context_table());
-
-    ScriptContextTable::LookupResult lookup_result;
-    if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
-      Handle<Object> result =
-          FixedArray::get(*ScriptContextTable::GetContext(
-                              script_contexts, lookup_result.context_index),
-                          lookup_result.slot_index, isolate());
-      if (*result == *isolate()->factory()->the_hole_value()) {
-        // Do not install stubs and stay pre-monomorphic for
-        // uninitialized accesses.
-        return ReferenceError(name);
-      }
-
-      if (use_ic && LoadScriptContextFieldStub::Accepted(&lookup_result)) {
-        LoadScriptContextFieldStub stub(isolate(), &lookup_result);
-        PatchCache(name, stub.GetCode());
-      }
-      return result;
-    }
+  if (state() != UNINITIALIZED) {
+    JSObject::MakePrototypesFast(object, kStartAtReceiver, isolate());
+    update_receiver_map(object);
   }
-
   // Named lookup in the object.
   LookupIterator it(object, name);
   LookupForRead(&it);
 
-  if (it.IsFound() || !ShouldThrowReferenceError(object)) {
+  if (it.IsFound() || !ShouldThrowReferenceError()) {
     // Update inline cache and stub cache.
     if (use_ic) UpdateCaches(&it);
 
@@ -725,7 +632,7 @@
                                Object);
     if (it.IsFound()) {
       return result;
-    } else if (!ShouldThrowReferenceError(object)) {
+    } else if (!ShouldThrowReferenceError()) {
       LOG(isolate(), SuspectReadEvent(*name, *object));
       return result;
     }
@@ -733,6 +640,38 @@
   return ReferenceError(name);
 }
 
+MaybeHandle<Object> LoadGlobalIC::Load(Handle<Name> name) {
+  Handle<JSGlobalObject> global = isolate()->global_object();
+
+  if (name->IsString()) {
+    // Look up in script context table.
+    Handle<String> str_name = Handle<String>::cast(name);
+    Handle<ScriptContextTable> script_contexts(
+        global->native_context()->script_context_table());
+
+    ScriptContextTable::LookupResult lookup_result;
+    if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
+      Handle<Object> result =
+          FixedArray::get(*ScriptContextTable::GetContext(
+                              script_contexts, lookup_result.context_index),
+                          lookup_result.slot_index, isolate());
+      if (result->IsTheHole(isolate())) {
+        // Do not install stubs and stay pre-monomorphic for
+        // uninitialized accesses.
+        return ReferenceError(name);
+      }
+
+      if (FLAG_use_ic && LoadScriptContextFieldStub::Accepted(&lookup_result)) {
+        TRACE_HANDLER_STATS(isolate(), LoadIC_LoadScriptContextFieldStub);
+        LoadScriptContextFieldStub stub(isolate(), &lookup_result);
+        PatchCache(name, stub.GetCode());
+        TRACE_IC("LoadGlobalIC", name);
+      }
+      return result;
+    }
+  }
+  return LoadIC::Load(global, name);
+}
 
 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
                                        Handle<Map> new_receiver_map) {
@@ -750,7 +689,7 @@
 
 bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) {
   if (!code->is_handler()) return false;
-  if (target()->is_keyed_stub() && state() != PROTOTYPE_FAILURE) return false;
+  if (is_keyed() && state() != RECOMPUTE_HANDLER) return false;
   Handle<Map> map = receiver_map();
   MapHandleList maps;
   CodeHandleList handlers;
@@ -783,14 +722,11 @@
   if (number_of_maps == 0 && state() != MONOMORPHIC && state() != POLYMORPHIC) {
     return false;
   }
-  if (UseVector()) {
-    if (!nexus()->FindHandlers(&handlers, maps.length())) return false;
-  } else {
-    if (!target()->FindHandlers(&handlers, maps.length())) return false;
-  }
+  DCHECK(UseVector());
+  if (!nexus()->FindHandlers(&handlers, maps.length())) return false;
 
   number_of_valid_maps++;
-  if (number_of_valid_maps > 1 && target()->is_keyed_stub()) return false;
+  if (number_of_valid_maps > 1 && is_keyed()) return false;
   Handle<Code> ic;
   if (number_of_valid_maps == 1) {
     ConfigureVectorState(name, receiver_map(), code);
@@ -808,7 +744,6 @@
     ConfigureVectorState(name, &maps, &handlers);
   }
 
-  if (!UseVector()) set_target(*ic);
   return true;
 }
 
@@ -823,7 +758,7 @@
   MapHandleList maps;
   CodeHandleList handlers;
   TargetMaps(&maps);
-  if (!target()->FindHandlers(&handlers, maps.length())) return;
+  if (!nexus()->FindHandlers(&handlers, maps.length())) return;
   for (int i = 0; i < maps.length(); i++) {
     UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i));
   }
@@ -836,11 +771,12 @@
   ElementsKind target_elements_kind = target_map->elements_kind();
   bool more_general_transition = IsMoreGeneralElementsKindTransition(
       source_map->elements_kind(), target_elements_kind);
-  Map* transitioned_map =
-      more_general_transition
-          ? source_map->LookupElementsTransitionMap(target_elements_kind)
-          : NULL;
-
+  Map* transitioned_map = nullptr;
+  if (more_general_transition) {
+    MapHandleList map_list;
+    map_list.Add(handle(target_map));
+    transitioned_map = source_map->FindElementsKindTransitionedMap(&map_list);
+  }
   return transitioned_map == target_map;
 }
 
@@ -851,31 +787,28 @@
     case PREMONOMORPHIC:
       UpdateMonomorphicIC(code, name);
       break;
-    case PROTOTYPE_FAILURE:
+    case RECOMPUTE_HANDLER:
     case MONOMORPHIC:
+      if (kind() == Code::LOAD_GLOBAL_IC) {
+        UpdateMonomorphicIC(code, name);
+        break;
+      }
+    // Fall through.
     case POLYMORPHIC:
-      if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) {
+      if (!is_keyed() || state() == RECOMPUTE_HANDLER) {
         if (UpdatePolymorphicIC(name, code)) break;
         // For keyed stubs, we can't know whether old handlers were for the
         // same key.
         CopyICToMegamorphicCache(name);
       }
-      if (UseVector()) {
-        ConfigureVectorState(MEGAMORPHIC, name);
-      } else {
-        set_target(*megamorphic_stub());
-      }
+      DCHECK(UseVector());
+      ConfigureVectorState(MEGAMORPHIC, name);
     // Fall through.
     case MEGAMORPHIC:
       UpdateMegamorphicCache(*receiver_map(), *name, *code);
       // Indicate that we've handled this case.
-      if (UseVector()) {
-        vector_set_ = true;
-      } else {
-        target_set_ = true;
-      }
-      break;
-    case DEBUG_STUB:
+      DCHECK(UseVector());
+      vector_set_ = true;
       break;
     case GENERIC:
       UNREACHABLE();
@@ -883,96 +816,42 @@
   }
 }
 
-
-Handle<Code> LoadIC::initialize_stub(Isolate* isolate,
-                                     ExtraICState extra_state) {
-  return LoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode();
+Handle<Code> LoadIC::initialize_stub_in_optimized_code(Isolate* isolate) {
+  if (FLAG_tf_load_ic_stub) {
+    return LoadICTFStub(isolate).GetCode();
+  }
+  return LoadICStub(isolate).GetCode();
 }
 
-
-Handle<Code> LoadIC::initialize_stub_in_optimized_code(
-    Isolate* isolate, ExtraICState extra_state, State initialization_state) {
-  return LoadICStub(isolate, LoadICState(extra_state)).GetCode();
+Handle<Code> LoadGlobalIC::initialize_stub_in_optimized_code(
+    Isolate* isolate, ExtraICState extra_state) {
+  return LoadGlobalICStub(isolate, LoadGlobalICState(extra_state)).GetCode();
 }
 
-
-Handle<Code> KeyedLoadIC::initialize_stub(Isolate* isolate,
-                                          ExtraICState extra_state) {
-  return KeyedLoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode();
-}
-
-
 Handle<Code> KeyedLoadIC::initialize_stub_in_optimized_code(
-    Isolate* isolate, State initialization_state, ExtraICState extra_state) {
-  if (initialization_state != MEGAMORPHIC) {
-    return KeyedLoadICStub(isolate, LoadICState(extra_state)).GetCode();
-  }
-  return isolate->builtins()->KeyedLoadIC_Megamorphic();
+    Isolate* isolate, ExtraICState extra_state) {
+  // TODO(ishell): remove extra_ic_state
+  return KeyedLoadICStub(isolate).GetCode();
 }
 
-
-static Handle<Code> KeyedStoreICInitializeStubHelper(
-    Isolate* isolate, LanguageMode language_mode,
-    InlineCacheState initialization_state) {
-  switch (initialization_state) {
-    case UNINITIALIZED:
-      return is_strict(language_mode)
-                 ? isolate->builtins()->KeyedStoreIC_Initialize_Strict()
-                 : isolate->builtins()->KeyedStoreIC_Initialize();
-    case PREMONOMORPHIC:
-      return is_strict(language_mode)
-                 ? isolate->builtins()->KeyedStoreIC_PreMonomorphic_Strict()
-                 : isolate->builtins()->KeyedStoreIC_PreMonomorphic();
-    case MEGAMORPHIC:
-      return is_strict(language_mode)
-                 ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict()
-                 : isolate->builtins()->KeyedStoreIC_Megamorphic();
-    default:
-      UNREACHABLE();
-  }
-  return Handle<Code>();
-}
-
-
-Handle<Code> KeyedStoreIC::initialize_stub(Isolate* isolate,
-                                           LanguageMode language_mode,
-                                           State initialization_state) {
-  if (initialization_state != MEGAMORPHIC) {
-    VectorKeyedStoreICTrampolineStub stub(isolate, StoreICState(language_mode));
-    return stub.GetCode();
-  }
-
-  return KeyedStoreICInitializeStubHelper(isolate, language_mode,
-                                          initialization_state);
-}
-
-
 Handle<Code> KeyedStoreIC::initialize_stub_in_optimized_code(
-    Isolate* isolate, LanguageMode language_mode, State initialization_state) {
-  if (initialization_state != MEGAMORPHIC) {
-    VectorKeyedStoreICStub stub(isolate, StoreICState(language_mode));
-    return stub.GetCode();
-  }
-
-  return KeyedStoreICInitializeStubHelper(isolate, language_mode,
-                                          initialization_state);
+    Isolate* isolate, LanguageMode language_mode) {
+  StoreICState state = StoreICState(language_mode);
+  return VectorKeyedStoreICStub(isolate, state).GetCode();
 }
 
 
 Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate,
                                                  ExtraICState extra_state) {
   LanguageMode mode = StoreICState::GetLanguageMode(extra_state);
-  return KeyedStoreICInitializeStubHelper(isolate, mode, MEGAMORPHIC);
-}
-
-
-Handle<Code> LoadIC::megamorphic_stub() {
-  DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
-  return KeyedLoadIC::ChooseMegamorphicStub(isolate(), extra_ic_state());
+  return is_strict(mode)
+             ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict()
+             : isolate->builtins()->KeyedStoreIC_Megamorphic();
 }
 
 
 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) {
+  TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub);
   LoadFieldStub stub(isolate(), index);
   return stub.GetCode();
 }
@@ -991,8 +870,9 @@
   } else if (accessors->IsAccessorPair()) {
     Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
                           isolate);
-    if (!getter->IsJSFunction() && !getter->IsFunctionTemplateInfo())
+    if (!getter->IsJSFunction() && !getter->IsFunctionTemplateInfo()) {
       return false;
+    }
     Handle<JSObject> holder = lookup->GetHolder<JSObject>();
     Handle<Object> receiver = lookup->GetReceiver();
     if (holder->HasFastProperties()) {
@@ -1017,7 +897,7 @@
 
 
 void LoadIC::UpdateCaches(LookupIterator* lookup) {
-  if (state() == UNINITIALIZED) {
+  if (state() == UNINITIALIZED && kind() != Code::LOAD_GLOBAL_IC) {
     // This is the first time we execute this inline cache. Set the target to
     // the pre monomorphic stub to delay setting the monomorphic state.
     ConfigureVectorState(PREMONOMORPHIC, Handle<Object>());
@@ -1030,7 +910,7 @@
       lookup->state() == LookupIterator::ACCESS_CHECK) {
     code = slow_stub();
   } else if (!lookup->IsFound()) {
-    if (kind() == Code::LOAD_IC) {
+    if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC) {
       code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(),
                                                               receiver_map());
       // TODO(jkummerow/verwaest): Introduce a builtin that handles this case.
@@ -1039,21 +919,41 @@
       code = slow_stub();
     }
   } else {
-    if (lookup->state() == LookupIterator::ACCESSOR) {
+    if (kind() == Code::LOAD_GLOBAL_IC &&
+        lookup->state() == LookupIterator::DATA &&
+        lookup->GetHolder<Object>()->IsJSGlobalObject()) {
+#if DEBUG
+      Handle<Object> holder = lookup->GetHolder<Object>();
+      Handle<Object> receiver = lookup->GetReceiver();
+      DCHECK_EQ(*receiver, *holder);
+#endif
+      // Now update the cell in the feedback vector.
+      LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>();
+      nexus->ConfigurePropertyCellMode(lookup->GetPropertyCell());
+      TRACE_IC("LoadGlobalIC", lookup->name());
+      return;
+    } else if (lookup->state() == LookupIterator::ACCESSOR) {
       if (!IsCompatibleReceiver(lookup, receiver_map())) {
         TRACE_GENERIC_IC(isolate(), "LoadIC", "incompatible receiver type");
         code = slow_stub();
       }
     } else if (lookup->state() == LookupIterator::INTERCEPTOR) {
-      // Perform a lookup behind the interceptor. Copy the LookupIterator since
-      // the original iterator will be used to fetch the value.
-      LookupIterator it = *lookup;
-      it.Next();
-      LookupForRead(&it);
-      if (it.state() == LookupIterator::ACCESSOR &&
-          !IsCompatibleReceiver(&it, receiver_map())) {
-        TRACE_GENERIC_IC(isolate(), "LoadIC", "incompatible receiver type");
+      if (kind() == Code::LOAD_GLOBAL_IC) {
+        // The interceptor handler requires name but it is not passed explicitly
+        // to LoadGlobalIC and the LoadGlobalIC dispatcher also does not load
+        // it so we will just use slow stub.
         code = slow_stub();
+      } else {
+        // Perform a lookup behind the interceptor. Copy the LookupIterator
+        // since the original iterator will be used to fetch the value.
+        LookupIterator it = *lookup;
+        it.Next();
+        LookupForRead(&it);
+        if (it.state() == LookupIterator::ACCESSOR &&
+            !IsCompatibleReceiver(&it, receiver_map())) {
+          TRACE_GENERIC_IC(isolate(), "LoadIC", "incompatible receiver type");
+          code = slow_stub();
+        }
       }
     }
     if (code.is_null()) code = ComputeHandler(lookup);
@@ -1070,23 +970,39 @@
 
 
 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) {
+  // Try to find a globally shared handler stub.
+  Handle<Code> code = GetMapIndependentHandler(lookup);
+  if (!code.is_null()) return code;
+
+  // Otherwise check the map's handler cache for a map-specific handler, and
+  // compile one if the cache comes up empty.
   bool receiver_is_holder =
       lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>());
   CacheHolderFlag flag;
-  Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder(
-      receiver_map(), receiver_is_holder, isolate(), &flag);
+  Handle<Map> stub_holder_map;
+  if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC ||
+      kind() == Code::KEYED_LOAD_IC) {
+    stub_holder_map = IC::GetHandlerCacheHolder(
+        receiver_map(), receiver_is_holder, isolate(), &flag);
+  } else {
+    DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC);
+    // Store handlers cannot be cached on prototypes.
+    flag = kCacheOnReceiver;
+    stub_holder_map = receiver_map();
+  }
 
-  Handle<Code> code = PropertyHandlerCompiler::Find(
-      lookup->name(), stub_holder_map, kind(), flag,
-      lookup->is_dictionary_holder() ? Code::NORMAL : Code::FAST);
+  code = PropertyHandlerCompiler::Find(lookup->name(), stub_holder_map, kind(),
+                                       flag);
   // Use the cached value if it exists, and if it is different from the
   // handler that just missed.
   if (!code.is_null()) {
-    if (!maybe_handler_.is_null() &&
-        !maybe_handler_.ToHandleChecked().is_identical_to(code)) {
-      return code;
-    }
-    if (maybe_handler_.is_null()) {
+    Handle<Code> handler;
+    if (maybe_handler_.ToHandle(&handler)) {
+      if (!handler.is_identical_to(code)) {
+        TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
+        return code;
+      }
+    } else {
       // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs.
       // In MEGAMORPHIC case, check if the handler in the megamorphic stub
       // cache (which just missed) is different from the cached handler.
@@ -1094,8 +1010,12 @@
         Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map();
         Code* megamorphic_cached_code =
             isolate()->stub_cache()->Get(*lookup->name(), map, code->flags());
-        if (megamorphic_cached_code != *code) return code;
+        if (megamorphic_cached_code != *code) {
+          TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
+          return code;
+        }
       } else {
+        TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
         return code;
       }
     }
@@ -1103,24 +1023,13 @@
 
   code = CompileHandler(lookup, value, flag);
   DCHECK(code->is_handler());
-
-  // TODO(mvstanton): we'd only like to cache code on the map when it's custom
-  // code compiled for this map, otherwise it's already cached in the global
-  // code cache. We are also guarding against installing code with flags that
-  // don't match the desired CacheHolderFlag computed above, which would lead to
-  // invalid lookups later.
-  if (code->type() != Code::NORMAL &&
-      Code::ExtractCacheHolderFromFlags(code->flags()) == flag) {
-    Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
-  }
+  DCHECK(Code::ExtractCacheHolderFromFlags(code->flags()) == flag);
+  Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
 
   return code;
 }
 
-
-Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
-                                    Handle<Object> unused,
-                                    CacheHolderFlag cache_holder) {
+Handle<Code> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
   Handle<Object> receiver = lookup->GetReceiver();
   if (receiver->IsString() &&
       Name::Equals(isolate()->factory()->length_string(), lookup->name())) {
@@ -1130,6 +1039,7 @@
 
   if (receiver->IsStringWrapper() &&
       Name::Equals(isolate()->factory()->length_string(), lookup->name())) {
+    TRACE_HANDLER_STATS(isolate(), LoadIC_StringLengthStub);
     StringLengthStub string_length_stub(isolate());
     return string_length_stub.GetCode();
   }
@@ -1142,6 +1052,7 @@
            ->map()
            ->has_non_instance_prototype()) {
     Handle<Code> stub;
+    TRACE_HANDLER_STATS(isolate(), LoadIC_FunctionPrototypeStub);
     FunctionPrototypeStub function_prototype_stub(isolate());
     return function_prototype_stub.GetCode();
   }
@@ -1150,16 +1061,8 @@
   Handle<JSObject> holder = lookup->GetHolder<JSObject>();
   bool receiver_is_holder = receiver.is_identical_to(holder);
   switch (lookup->state()) {
-    case LookupIterator::INTERCEPTOR: {
-      DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined());
-      NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
-      // Perform a lookup behind the interceptor. Copy the LookupIterator since
-      // the original iterator will be used to fetch the value.
-      LookupIterator it = *lookup;
-      it.Next();
-      LookupForRead(&it);
-      return compiler.CompileLoadInterceptor(&it);
-    }
+    case LookupIterator::INTERCEPTOR:
+      break;  // Custom-compiled handler.
 
     case LookupIterator::ACCESSOR: {
       // Use simple field loads for some well-known callback properties.
@@ -1171,72 +1074,64 @@
         FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map);
         return SimpleFieldLoad(index);
       }
-      if (Accessors::IsJSArrayBufferViewFieldAccessor(map, lookup->name(),
-                                                      &object_offset)) {
-        FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map);
-        ArrayBufferViewLoadFieldStub stub(isolate(), index);
-        return stub.GetCode();
-      }
 
       if (IsCompatibleReceiver(lookup, map)) {
         Handle<Object> accessors = lookup->GetAccessors();
         if (accessors->IsAccessorPair()) {
-          if (!holder->HasFastProperties()) break;
-          // When debugging we need to go the slow path to flood the accessor.
-          if (GetSharedFunctionInfo()->HasDebugInfo()) break;
-          Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
-                                isolate());
-          CallOptimization call_optimization(getter);
-          NamedLoadHandlerCompiler compiler(isolate(), map, holder,
-                                            cache_holder);
-          if (call_optimization.is_simple_api_call()) {
-            return compiler.CompileLoadCallback(
-                lookup->name(), call_optimization, lookup->GetAccessorIndex());
+          if (!holder->HasFastProperties()) {
+            TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+            return slow_stub();
           }
-          int expected_arguments = Handle<JSFunction>::cast(getter)
-                                       ->shared()
-                                       ->internal_formal_parameter_count();
-          return compiler.CompileLoadViaGetter(
-              lookup->name(), lookup->GetAccessorIndex(), expected_arguments);
+          // When debugging we need to go the slow path to flood the accessor.
+          if (GetSharedFunctionInfo()->HasDebugInfo()) {
+            TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+            return slow_stub();
+          }
+          break;  // Custom-compiled handler.
         } else if (accessors->IsAccessorInfo()) {
           Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
-          if (v8::ToCData<Address>(info->getter()) == 0) break;
-          if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map)) {
-            // This case should be already handled in LoadIC::UpdateCaches.
-            UNREACHABLE();
-            break;
+          if (v8::ToCData<Address>(info->getter()) == nullptr) {
+            TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+            return slow_stub();
           }
-          if (!holder->HasFastProperties()) break;
-          if (info->is_sloppy() && !receiver->IsJSReceiver()) break;
-          NamedLoadHandlerCompiler compiler(isolate(), map, holder,
-                                            cache_holder);
-          return compiler.CompileLoadCallback(lookup->name(), info);
+          // Ruled out by IsCompatibleReceiver() above.
+          DCHECK(AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map));
+          if (!holder->HasFastProperties()) return slow_stub();
+          if (receiver_is_holder) {
+            TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterStub);
+            int index = lookup->GetAccessorIndex();
+            LoadApiGetterStub stub(isolate(), true, index);
+            return stub.GetCode();
+          }
+          if (info->is_sloppy() && !receiver->IsJSReceiver()) {
+            TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+            return slow_stub();
+          }
+          break;  // Custom-compiled handler.
         }
       }
-      break;
+      TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+      return slow_stub();
     }
 
     case LookupIterator::DATA: {
       if (lookup->is_dictionary_holder()) {
-        if (kind() != Code::LOAD_IC) break;
+        if (kind() != Code::LOAD_IC && kind() != Code::LOAD_GLOBAL_IC) {
+          TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+          return slow_stub();
+        }
         if (holder->IsJSGlobalObject()) {
-          NamedLoadHandlerCompiler compiler(isolate(), map, holder,
-                                            cache_holder);
-          Handle<PropertyCell> cell = lookup->GetPropertyCell();
-          Handle<Code> code = compiler.CompileLoadGlobal(
-              cell, lookup->name(), lookup->IsConfigurable());
-          // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
-          CacheHolderFlag flag;
-          Handle<Map> stub_holder_map =
-              GetHandlerCacheHolder(map, receiver_is_holder, isolate(), &flag);
-          Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
-          return code;
+          break;  // Custom-compiled handler.
         }
         // There is only one shared stub for loading normalized
         // properties. It does not traverse the prototype chain, so the
         // property must be found in the object for the stub to be
         // applicable.
-        if (!receiver_is_holder) break;
+        if (!receiver_is_holder) {
+          TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
+          return slow_stub();
+        }
+        TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormal);
         return isolate()->builtins()->LoadIC_Normal();
       }
 
@@ -1246,22 +1141,21 @@
         if (receiver_is_holder) {
           return SimpleFieldLoad(field);
         }
-        NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
-        return compiler.CompileLoadField(lookup->name(), field);
+        break;  // Custom-compiled handler.
       }
 
       // -------------- Constant properties --------------
       DCHECK(lookup->property_details().type() == DATA_CONSTANT);
       if (receiver_is_holder) {
+        TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub);
         LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
         return stub.GetCode();
       }
-      NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
-      return compiler.CompileLoadConstant(lookup->name(),
-                                          lookup->GetConstantIndex());
+      break;  // Custom-compiled handler.
     }
 
     case LookupIterator::INTEGER_INDEXED_EXOTIC:
+      TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
       return slow_stub();
     case LookupIterator::ACCESS_CHECK:
     case LookupIterator::JSPROXY:
@@ -1270,6 +1164,129 @@
       UNREACHABLE();
   }
 
+  return Handle<Code>::null();
+}
+
+Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
+                                    Handle<Object> unused,
+                                    CacheHolderFlag cache_holder) {
+  Handle<JSObject> holder = lookup->GetHolder<JSObject>();
+#ifdef DEBUG
+  // Only used by DCHECKs below.
+  Handle<Object> receiver = lookup->GetReceiver();
+  bool receiver_is_holder = receiver.is_identical_to(holder);
+#endif
+  // Non-map-specific handler stubs have already been selected.
+  DCHECK(!receiver->IsString() ||
+         !Name::Equals(isolate()->factory()->length_string(), lookup->name()));
+  DCHECK(!receiver->IsStringWrapper() ||
+         !Name::Equals(isolate()->factory()->length_string(), lookup->name()));
+
+  DCHECK(!(
+      receiver->IsJSFunction() &&
+      Name::Equals(isolate()->factory()->prototype_string(), lookup->name()) &&
+      receiver->IsConstructor() &&
+      !Handle<JSFunction>::cast(receiver)
+           ->map()
+           ->has_non_instance_prototype()));
+
+  Handle<Map> map = receiver_map();
+  switch (lookup->state()) {
+    case LookupIterator::INTERCEPTOR: {
+      DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
+      TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptor);
+      NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
+      // Perform a lookup behind the interceptor. Copy the LookupIterator since
+      // the original iterator will be used to fetch the value.
+      LookupIterator it = *lookup;
+      it.Next();
+      LookupForRead(&it);
+      return compiler.CompileLoadInterceptor(&it);
+    }
+
+    case LookupIterator::ACCESSOR: {
+#ifdef DEBUG
+      int object_offset;
+      DCHECK(!Accessors::IsJSObjectFieldAccessor(map, lookup->name(),
+                                                 &object_offset));
+#endif
+
+      DCHECK(IsCompatibleReceiver(lookup, map));
+      Handle<Object> accessors = lookup->GetAccessors();
+      if (accessors->IsAccessorPair()) {
+        DCHECK(holder->HasFastProperties());
+        DCHECK(!GetSharedFunctionInfo()->HasDebugInfo());
+        Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
+                              isolate());
+        CallOptimization call_optimization(getter);
+        NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
+        if (call_optimization.is_simple_api_call()) {
+          TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
+          int index = lookup->GetAccessorIndex();
+          Handle<Code> code = compiler.CompileLoadCallback(
+              lookup->name(), call_optimization, index);
+          return code;
+        }
+        TRACE_HANDLER_STATS(isolate(), LoadIC_LoadViaGetter);
+        int expected_arguments = Handle<JSFunction>::cast(getter)
+                                     ->shared()
+                                     ->internal_formal_parameter_count();
+        return compiler.CompileLoadViaGetter(
+            lookup->name(), lookup->GetAccessorIndex(), expected_arguments);
+      } else {
+        DCHECK(accessors->IsAccessorInfo());
+        Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
+        DCHECK(v8::ToCData<Address>(info->getter()) != nullptr);
+        DCHECK(AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map));
+        DCHECK(holder->HasFastProperties());
+        DCHECK(!receiver_is_holder);
+        DCHECK(!info->is_sloppy() || receiver->IsJSReceiver());
+        TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
+        NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
+        Handle<Code> code = compiler.CompileLoadCallback(lookup->name(), info);
+        return code;
+      }
+      UNREACHABLE();
+    }
+
+    case LookupIterator::DATA: {
+      if (lookup->is_dictionary_holder()) {
+        DCHECK(kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC);
+        DCHECK(holder->IsJSGlobalObject());
+        TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobal);
+        NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
+        Handle<PropertyCell> cell = lookup->GetPropertyCell();
+        Handle<Code> code = compiler.CompileLoadGlobal(
+            cell, lookup->name(), lookup->IsConfigurable());
+        return code;
+      }
+
+      // -------------- Fields --------------
+      if (lookup->property_details().type() == DATA) {
+        FieldIndex field = lookup->GetFieldIndex();
+        DCHECK(!receiver_is_holder);
+        TRACE_HANDLER_STATS(isolate(), LoadIC_LoadField);
+        NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
+        return compiler.CompileLoadField(lookup->name(), field);
+      }
+
+      // -------------- Constant properties --------------
+      DCHECK(lookup->property_details().type() == DATA_CONSTANT);
+      DCHECK(!receiver_is_holder);
+      TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstant);
+      NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
+      return compiler.CompileLoadConstant(lookup->name(),
+                                          lookup->GetConstantIndex());
+    }
+
+    case LookupIterator::INTEGER_INDEXED_EXOTIC:
+    case LookupIterator::ACCESS_CHECK:
+    case LookupIterator::JSPROXY:
+    case LookupIterator::NOT_FOUND:
+    case LookupIterator::TRANSITION:
+      UNREACHABLE();
+  }
+  UNREACHABLE();
   return slow_stub();
 }
 
@@ -1287,17 +1304,16 @@
         key = handle(Smi::FromInt(int_value), isolate);
       }
     }
-  } else if (key->IsUndefined()) {
+  } else if (key->IsUndefined(isolate)) {
     key = isolate->factory()->undefined_string();
   }
   return key;
 }
 
-
-Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) {
-  Handle<Code> null_handle;
+void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) {
   Handle<Map> receiver_map(receiver->map(), isolate());
-  DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE);  // Checked by caller.
+  DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE &&
+         receiver_map->instance_type() != JS_PROXY_TYPE);  // Checked by caller.
   MapHandleList target_receiver_maps;
   TargetMaps(&target_receiver_maps);
 
@@ -1305,15 +1321,19 @@
     Handle<Code> handler =
         PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
             receiver_map, extra_ic_state());
-    ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
-    return null_handle;
+    return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
   }
 
   for (int i = 0; i < target_receiver_maps.length(); i++) {
-    if (!target_receiver_maps.at(i).is_null() &&
-        target_receiver_maps.at(i)->instance_type() == JS_VALUE_TYPE) {
+    Handle<Map> map = target_receiver_maps.at(i);
+    if (map.is_null()) continue;
+    if (map->instance_type() == JS_VALUE_TYPE) {
       TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "JSValue");
-      return megamorphic_stub();
+      return;
+    }
+    if (map->instance_type() == JS_PROXY_TYPE) {
+      TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "JSProxy");
+      return;
     }
   }
 
@@ -1331,8 +1351,7 @@
     Handle<Code> handler =
         PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
             receiver_map, extra_ic_state());
-    ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
-    return null_handle;
+    return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
   }
 
   DCHECK(state() != GENERIC);
@@ -1343,21 +1362,21 @@
     // If the miss wasn't due to an unseen map, a polymorphic stub
     // won't help, use the generic stub.
     TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice");
-    return megamorphic_stub();
+    return;
   }
 
   // If the maximum number of receiver maps has been exceeded, use the generic
   // version of the IC.
   if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
     TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded");
-    return megamorphic_stub();
+    return;
   }
 
   CodeHandleList handlers(target_receiver_maps.length());
+  TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_PolymorphicElement);
   ElementHandlerCompiler compiler(isolate());
   compiler.CompileElementHandlers(&target_receiver_maps, &handlers);
-  ConfigureVectorState(Handle<Name>::null(), &target_receiver_maps, &handlers);
-  return null_handle;
+  ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers);
 }
 
 
@@ -1372,13 +1391,15 @@
   }
 
   Handle<Object> load_handle;
-  Handle<Code> stub = megamorphic_stub();
 
   // Check for non-string values that can be converted into an
   // internalized string directly or is representable as a smi.
   key = TryConvertKey(key, isolate());
 
-  if (key->IsInternalizedString() || key->IsSymbol()) {
+  uint32_t index;
+  if ((key->IsInternalizedString() &&
+       !String::cast(*key)->AsArrayIndex(&index)) ||
+      key->IsSymbol()) {
     ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle,
                                LoadIC::Load(object, Handle<Name>::cast(key)),
                                Object);
@@ -1386,20 +1407,15 @@
              !object->IsJSValue()) {
     if (object->IsJSObject() || (object->IsString() && key->IsNumber())) {
       Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
-      if (object->IsString() || key->IsSmi()) stub = LoadElementStub(receiver);
+      if (object->IsString() || key->IsSmi()) UpdateLoadElement(receiver);
     }
   }
 
-  DCHECK(UseVector());
-  if (!is_vector_set() || stub.is_null()) {
-    Code* generic = *megamorphic_stub();
-    if (!stub.is_null() && *stub == generic) {
-      ConfigureVectorState(MEGAMORPHIC, key);
-      TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic");
-    }
-
-    TRACE_IC("LoadIC", key);
+  if (!is_vector_set()) {
+    ConfigureVectorState(MEGAMORPHIC, key);
+    TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic");
   }
+  TRACE_IC("LoadIC", key);
 
   if (!load_handle.is_null()) return load_handle;
 
@@ -1431,9 +1447,9 @@
         InterceptorInfo* info = holder->GetNamedInterceptor();
         if (it->HolderIsReceiverOrHiddenPrototype()) {
           return !info->non_masking() && receiver.is_identical_to(holder) &&
-                 !info->setter()->IsUndefined();
-        } else if (!info->getter()->IsUndefined() ||
-                   !info->query()->IsUndefined()) {
+                 !info->setter()->IsUndefined(it->isolate());
+        } else if (!info->getter()->IsUndefined(it->isolate()) ||
+                   !info->query()->IsUndefined(it->isolate())) {
           return false;
         }
         break;
@@ -1482,27 +1498,6 @@
 MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
                                    Handle<Object> value,
                                    JSReceiver::StoreFromKeyed store_mode) {
-  // Check if the name is trivially convertible to an index and set the element.
-  uint32_t index;
-  if (kind() == Code::KEYED_STORE_IC && name->AsArrayIndex(&index)) {
-    // Rewrite to the generic keyed store stub.
-    if (FLAG_use_ic) {
-      if (UseVector()) {
-        ConfigureVectorState(MEGAMORPHIC, name);
-      } else if (!AddressIsDeoptimizedCode()) {
-        set_target(*megamorphic_stub());
-      }
-      TRACE_IC("StoreIC", name);
-      TRACE_GENERIC_IC(isolate(), "StoreIC", "name as array index");
-    }
-    Handle<Object> result;
-    ASSIGN_RETURN_ON_EXCEPTION(
-        isolate(), result,
-        Object::SetElement(isolate(), object, index, value, language_mode()),
-        Object);
-    return result;
-  }
-
   if (object->IsJSGlobalObject() && name->IsString()) {
     // Look up in script context table.
     Handle<String> str_name = Handle<String>::cast(name);
@@ -1521,7 +1516,7 @@
       Handle<Object> previous_value =
           FixedArray::get(*script_context, lookup_result.slot_index, isolate());
 
-      if (*previous_value == *isolate()->factory()->the_hole_value()) {
+      if (previous_value->IsTheHole(isolate())) {
         // Do not install stubs and stay pre-monomorphic for
         // uninitialized accesses.
         return ReferenceError(name);
@@ -1529,6 +1524,7 @@
 
       if (FLAG_use_ic &&
           StoreScriptContextFieldStub::Accepted(&lookup_result)) {
+        TRACE_HANDLER_STATS(isolate(), StoreIC_StoreScriptContextFieldStub);
         StoreScriptContextFieldStub stub(isolate(), &lookup_result);
         PatchCache(name, stub.GetCode());
       }
@@ -1550,21 +1546,13 @@
 
   // If the object is undefined or null it's illegal to try to set any
   // properties on it; throw a TypeError in that case.
-  if (object->IsUndefined() || object->IsNull()) {
+  if (object->IsUndefined(isolate()) || object->IsNull(isolate())) {
     return TypeError(MessageTemplate::kNonObjectPropertyStore, object, name);
   }
 
-  // Observed objects are always modified through the runtime.
-  if (object->IsHeapObject() &&
-      Handle<HeapObject>::cast(object)->map()->is_observed()) {
-    Handle<Object> result;
-    ASSIGN_RETURN_ON_EXCEPTION(
-        isolate(), result,
-        Object::SetProperty(object, name, value, language_mode(), store_mode),
-        Object);
-    return result;
+  if (state() != UNINITIALIZED) {
+    JSObject::MakePrototypesFast(object, kStartAtPrototype, isolate());
   }
-
   LookupIterator it(object, name);
   if (FLAG_use_ic) UpdateCaches(&it, value, store_mode);
 
@@ -1573,14 +1561,6 @@
   return value;
 }
 
-Handle<Code> CallIC::initialize_stub(Isolate* isolate, int argc,
-                                     ConvertReceiverMode mode,
-                                     TailCallMode tail_call_mode) {
-  CallICTrampolineStub stub(isolate, CallICState(argc, mode, tail_call_mode));
-  Handle<Code> code = stub.GetCode();
-  return code;
-}
-
 Handle<Code> CallIC::initialize_stub_in_optimized_code(
     Isolate* isolate, int argc, ConvertReceiverMode mode,
     TailCallMode tail_call_mode) {
@@ -1589,74 +1569,12 @@
   return code;
 }
 
-
-static Handle<Code> StoreICInitializeStubHelper(
-    Isolate* isolate, ExtraICState extra_state,
-    InlineCacheState initialization_state) {
-  Handle<Code> ic = PropertyICCompiler::ComputeStore(
-      isolate, initialization_state, extra_state);
-  return ic;
-}
-
-
-Handle<Code> StoreIC::initialize_stub(Isolate* isolate,
-                                      LanguageMode language_mode,
-                                      State initialization_state) {
-  DCHECK(initialization_state == UNINITIALIZED ||
-         initialization_state == PREMONOMORPHIC ||
-         initialization_state == MEGAMORPHIC);
-  VectorStoreICTrampolineStub stub(isolate, StoreICState(language_mode));
+Handle<Code> StoreIC::initialize_stub_in_optimized_code(
+    Isolate* isolate, LanguageMode language_mode) {
+  VectorStoreICStub stub(isolate, StoreICState(language_mode));
   return stub.GetCode();
 }
 
-
-Handle<Code> StoreIC::initialize_stub_in_optimized_code(
-    Isolate* isolate, LanguageMode language_mode, State initialization_state) {
-  DCHECK(initialization_state == UNINITIALIZED ||
-         initialization_state == PREMONOMORPHIC ||
-         initialization_state == MEGAMORPHIC);
-  if (initialization_state != MEGAMORPHIC) {
-    VectorStoreICStub stub(isolate, StoreICState(language_mode));
-    return stub.GetCode();
-  }
-
-  return StoreICInitializeStubHelper(
-      isolate, ComputeExtraICState(language_mode), initialization_state);
-}
-
-
-Handle<Code> StoreIC::megamorphic_stub() {
-  if (kind() == Code::STORE_IC) {
-    return PropertyICCompiler::ComputeStore(isolate(), MEGAMORPHIC,
-                                            extra_ic_state());
-  } else {
-    DCHECK(kind() == Code::KEYED_STORE_IC);
-    if (is_strict(language_mode())) {
-      return isolate()->builtins()->KeyedStoreIC_Megamorphic_Strict();
-    } else {
-      return isolate()->builtins()->KeyedStoreIC_Megamorphic();
-    }
-  }
-}
-
-
-Handle<Code> StoreIC::slow_stub() const {
-  if (kind() == Code::STORE_IC) {
-    return isolate()->builtins()->StoreIC_Slow();
-  } else {
-    DCHECK(kind() == Code::KEYED_STORE_IC);
-    return isolate()->builtins()->KeyedStoreIC_Slow();
-  }
-}
-
-
-Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate,
-                                           LanguageMode language_mode) {
-  ExtraICState state = ComputeExtraICState(language_mode);
-  return PropertyICCompiler::ComputeStore(isolate, PREMONOMORPHIC, state);
-}
-
-
 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
                            JSReceiver::StoreFromKeyed store_mode) {
   if (state() == UNINITIALIZED) {
@@ -1693,6 +1611,135 @@
   return code;
 }
 
+Handle<Code> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
+  DCHECK_NE(LookupIterator::JSPROXY, lookup->state());
+
+  // This is currently guaranteed by checks in StoreIC::Store.
+  Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
+  Handle<JSObject> holder = lookup->GetHolder<JSObject>();
+  DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
+
+  switch (lookup->state()) {
+    case LookupIterator::TRANSITION: {
+      auto store_target = lookup->GetStoreTarget();
+      if (store_target->IsJSGlobalObject()) {
+        break;  // Custom-compiled handler.
+      }
+      // Currently not handled by CompileStoreTransition.
+      if (!holder->HasFastProperties()) {
+        TRACE_GENERIC_IC(isolate(), "StoreIC", "transition from slow");
+        TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+        return slow_stub();
+      }
+
+      DCHECK(lookup->IsCacheableTransition());
+      break;  // Custom-compiled handler.
+    }
+
+    case LookupIterator::INTERCEPTOR: {
+      DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined(isolate()));
+      TRACE_HANDLER_STATS(isolate(), StoreIC_StoreInterceptorStub);
+      StoreInterceptorStub stub(isolate());
+      return stub.GetCode();
+    }
+
+    case LookupIterator::ACCESSOR: {
+      if (!holder->HasFastProperties()) {
+        TRACE_GENERIC_IC(isolate(), "StoreIC", "accessor on slow map");
+        TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+        return slow_stub();
+      }
+      Handle<Object> accessors = lookup->GetAccessors();
+      if (accessors->IsAccessorInfo()) {
+        Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
+        if (v8::ToCData<Address>(info->setter()) == nullptr) {
+          TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == nullptr");
+          TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+          return slow_stub();
+        }
+        if (AccessorInfo::cast(*accessors)->is_special_data_property() &&
+            !lookup->HolderIsReceiverOrHiddenPrototype()) {
+          TRACE_GENERIC_IC(isolate(), "StoreIC",
+                           "special data property in prototype chain");
+          TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+          return slow_stub();
+        }
+        if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info,
+                                                   receiver_map())) {
+          TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type");
+          TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+          return slow_stub();
+        }
+        if (info->is_sloppy() && !receiver->IsJSReceiver()) {
+          TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+          return slow_stub();
+        }
+        break;  // Custom-compiled handler.
+      } else if (accessors->IsAccessorPair()) {
+        Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
+                              isolate());
+        if (!setter->IsJSFunction() && !setter->IsFunctionTemplateInfo()) {
+          TRACE_GENERIC_IC(isolate(), "StoreIC", "setter not a function");
+          TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+          return slow_stub();
+        }
+        CallOptimization call_optimization(setter);
+        if (call_optimization.is_simple_api_call()) {
+          if (call_optimization.IsCompatibleReceiver(receiver, holder)) {
+            break;  // Custom-compiled handler.
+          }
+          TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver");
+          TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+          return slow_stub();
+        }
+        break;  // Custom-compiled handler.
+      }
+      TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+      return slow_stub();
+    }
+
+    case LookupIterator::DATA: {
+      if (lookup->is_dictionary_holder()) {
+        if (holder->IsJSGlobalObject()) {
+          break;  // Custom-compiled handler.
+        }
+        TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormal);
+        DCHECK(holder.is_identical_to(receiver));
+        return isolate()->builtins()->StoreIC_Normal();
+      }
+
+      // -------------- Fields --------------
+      if (lookup->property_details().type() == DATA) {
+        bool use_stub = true;
+        if (lookup->representation().IsHeapObject()) {
+          // Only use a generic stub if no types need to be tracked.
+          Handle<FieldType> field_type = lookup->GetFieldType();
+          use_stub = !field_type->IsClass();
+        }
+        if (use_stub) {
+          TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldStub);
+          StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
+                              lookup->representation());
+          return stub.GetCode();
+        }
+        break;  // Custom-compiled handler.
+      }
+
+      // -------------- Constant properties --------------
+      DCHECK(lookup->property_details().type() == DATA_CONSTANT);
+      TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property");
+      TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
+      return slow_stub();
+    }
+
+    case LookupIterator::INTEGER_INDEXED_EXOTIC:
+    case LookupIterator::ACCESS_CHECK:
+    case LookupIterator::JSPROXY:
+    case LookupIterator::NOT_FOUND:
+      UNREACHABLE();
+  }
+  return Handle<Code>::null();
+}
 
 Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
                                      Handle<Object> value,
@@ -1709,6 +1756,7 @@
       auto store_target = lookup->GetStoreTarget();
       if (store_target->IsJSGlobalObject()) {
         // TODO(dcarney): this currently just deopts. Use the transition cell.
+        TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransition);
         auto cell = isolate()->factory()->NewPropertyCell();
         cell->set_value(*value);
         auto code = PropertyCellStoreHandler(
@@ -1719,111 +1767,92 @@
       }
       Handle<Map> transition = lookup->transition_map();
       // Currently not handled by CompileStoreTransition.
-      if (!holder->HasFastProperties()) {
-        TRACE_GENERIC_IC(isolate(), "StoreIC", "transition from slow");
-        break;
-      }
+      DCHECK(holder->HasFastProperties());
 
       DCHECK(lookup->IsCacheableTransition());
+      TRACE_HANDLER_STATS(isolate(), StoreIC_StoreTransition);
       NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
       return compiler.CompileStoreTransition(transition, lookup->name());
     }
 
-    case LookupIterator::INTERCEPTOR: {
-      DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined());
-      return CodeFactory::StoreInterceptor(isolate()).code();
-    }
+    case LookupIterator::INTERCEPTOR:
+      UNREACHABLE();
 
     case LookupIterator::ACCESSOR: {
-      if (!holder->HasFastProperties()) {
-        TRACE_GENERIC_IC(isolate(), "StoreIC", "accessor on slow map");
-        break;
-      }
+      DCHECK(holder->HasFastProperties());
       Handle<Object> accessors = lookup->GetAccessors();
       if (accessors->IsAccessorInfo()) {
         Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
-        if (v8::ToCData<Address>(info->setter()) == 0) {
-          TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == 0");
-          break;
-        }
-        if (AccessorInfo::cast(*accessors)->is_special_data_property() &&
-            !lookup->HolderIsReceiverOrHiddenPrototype()) {
-          TRACE_GENERIC_IC(isolate(), "StoreIC",
-                           "special data property in prototype chain");
-          break;
-        }
-        if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info,
-                                                   receiver_map())) {
-          TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type");
-          break;
-        }
-        if (info->is_sloppy() && !receiver->IsJSReceiver()) break;
+        DCHECK(v8::ToCData<Address>(info->setter()) != 0);
+        DCHECK(!AccessorInfo::cast(*accessors)->is_special_data_property() ||
+               lookup->HolderIsReceiverOrHiddenPrototype());
+        DCHECK(AccessorInfo::IsCompatibleReceiverMap(isolate(), info,
+                                                     receiver_map()));
+        DCHECK(!info->is_sloppy() || receiver->IsJSReceiver());
+        TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
         NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
-        return compiler.CompileStoreCallback(receiver, lookup->name(), info,
-                                             language_mode());
-      } else if (accessors->IsAccessorPair()) {
+        Handle<Code> code = compiler.CompileStoreCallback(
+            receiver, lookup->name(), info, language_mode());
+        return code;
+      } else {
+        DCHECK(accessors->IsAccessorPair());
         Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
                               isolate());
-        if (!setter->IsJSFunction()) {
-          TRACE_GENERIC_IC(isolate(), "StoreIC", "setter not a function");
-          break;
-        }
-        Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
-        CallOptimization call_optimization(function);
+        DCHECK(setter->IsJSFunction() || setter->IsFunctionTemplateInfo());
+        CallOptimization call_optimization(setter);
         NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
-        if (call_optimization.is_simple_api_call() &&
-            call_optimization.IsCompatibleReceiver(receiver, holder)) {
-          return compiler.CompileStoreCallback(receiver, lookup->name(),
-                                               call_optimization,
-                                               lookup->GetAccessorIndex());
+        if (call_optimization.is_simple_api_call()) {
+          DCHECK(call_optimization.IsCompatibleReceiver(receiver, holder));
+          TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
+          Handle<Code> code = compiler.CompileStoreCallback(
+              receiver, lookup->name(), call_optimization,
+              lookup->GetAccessorIndex());
+          return code;
         }
-        int expected_arguments =
-            function->shared()->internal_formal_parameter_count();
+        TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter);
+        int expected_arguments = JSFunction::cast(*setter)
+                                     ->shared()
+                                     ->internal_formal_parameter_count();
         return compiler.CompileStoreViaSetter(receiver, lookup->name(),
                                               lookup->GetAccessorIndex(),
                                               expected_arguments);
       }
-      break;
     }
 
     case LookupIterator::DATA: {
       if (lookup->is_dictionary_holder()) {
-        if (holder->IsJSGlobalObject()) {
-          DCHECK(holder.is_identical_to(receiver) ||
-                 receiver->map()->prototype() == *holder);
-          auto cell = lookup->GetPropertyCell();
-          auto updated_type = PropertyCell::UpdatedType(
-              cell, value, lookup->property_details());
-          auto code = PropertyCellStoreHandler(
-              isolate(), receiver, Handle<JSGlobalObject>::cast(holder),
-              lookup->name(), cell, updated_type);
-          return code;
-        }
-        DCHECK(holder.is_identical_to(receiver));
-        return isolate()->builtins()->StoreIC_Normal();
+        DCHECK(holder->IsJSGlobalObject());
+        TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobal);
+        DCHECK(holder.is_identical_to(receiver) ||
+               receiver->map()->prototype() == *holder);
+        auto cell = lookup->GetPropertyCell();
+        auto updated_type =
+            PropertyCell::UpdatedType(cell, value, lookup->property_details());
+        auto code = PropertyCellStoreHandler(
+            isolate(), receiver, Handle<JSGlobalObject>::cast(holder),
+            lookup->name(), cell, updated_type);
+        return code;
       }
 
       // -------------- Fields --------------
       if (lookup->property_details().type() == DATA) {
+#ifdef DEBUG
         bool use_stub = true;
         if (lookup->representation().IsHeapObject()) {
           // Only use a generic stub if no types need to be tracked.
           Handle<FieldType> field_type = lookup->GetFieldType();
           use_stub = !field_type->IsClass();
         }
-        if (use_stub) {
-          StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
-                              lookup->representation());
-          return stub.GetCode();
-        }
+        DCHECK(!use_stub);
+#endif
+        TRACE_HANDLER_STATS(isolate(), StoreIC_StoreField);
         NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
         return compiler.CompileStoreField(lookup);
       }
 
       // -------------- Constant properties --------------
       DCHECK(lookup->property_details().type() == DATA_CONSTANT);
-      TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property");
-      break;
+      UNREACHABLE();
     }
 
     case LookupIterator::INTEGER_INDEXED_EXOTIC:
@@ -1832,22 +1861,12 @@
     case LookupIterator::NOT_FOUND:
       UNREACHABLE();
   }
+  UNREACHABLE();
   return slow_stub();
 }
 
-
-Handle<Code> KeyedStoreIC::StoreElementStub(Handle<Map> receiver_map,
-                                            KeyedAccessStoreMode store_mode) {
-  Handle<Code> null_handle;
-  // Don't handle megamorphic property accesses for INTERCEPTORS or
-  // ACCESSOR_CONSTANT
-  // via megamorphic stubs, since they don't have a map in their relocation info
-  // and so the stubs can't be harvested for the object needed for a map check.
-  if (target()->type() != Code::NORMAL) {
-    TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-NORMAL target type");
-    return megamorphic_stub();
-  }
-
+void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
+                                      KeyedAccessStoreMode store_mode) {
   MapHandleList target_receiver_maps;
   TargetMaps(&target_receiver_maps);
   if (target_receiver_maps.length() == 0) {
@@ -1855,10 +1874,17 @@
         ComputeTransitionedMap(receiver_map, store_mode);
     store_mode = GetNonTransitioningStoreMode(store_mode);
     Handle<Code> handler =
-        PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
-            monomorphic_map, language_mode(), store_mode);
-    ConfigureVectorState(Handle<Name>::null(), monomorphic_map, handler);
-    return null_handle;
+        PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(monomorphic_map,
+                                                                store_mode);
+    return ConfigureVectorState(Handle<Name>(), monomorphic_map, handler);
+  }
+
+  for (int i = 0; i < target_receiver_maps.length(); i++) {
+    if (!target_receiver_maps.at(i).is_null() &&
+        target_receiver_maps.at(i)->instance_type() == JS_VALUE_TYPE) {
+      TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "JSValue");
+      return;
+    }
   }
 
   // There are several special cases where an IC that is MONOMORPHIC can still
@@ -1883,23 +1909,22 @@
       store_mode = GetNonTransitioningStoreMode(store_mode);
       Handle<Code> handler =
           PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
-              transitioned_receiver_map, language_mode(), store_mode);
-      ConfigureVectorState(Handle<Name>::null(), transitioned_receiver_map,
-                           handler);
-      return null_handle;
-    } else if (receiver_map.is_identical_to(previous_receiver_map) &&
-               old_store_mode == STANDARD_STORE &&
-               (store_mode == STORE_AND_GROW_NO_TRANSITION ||
-                store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
-                store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
+              transitioned_receiver_map, store_mode);
+      ConfigureVectorState(Handle<Name>(), transitioned_receiver_map, handler);
+      return;
+    }
+    if (receiver_map.is_identical_to(previous_receiver_map) &&
+        old_store_mode == STANDARD_STORE &&
+        (store_mode == STORE_AND_GROW_NO_TRANSITION ||
+         store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
+         store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
       // A "normal" IC that handles stores can switch to a version that can
       // grow at the end of the array, handle OOB accesses or copy COW arrays
       // and still stay MONOMORPHIC.
       Handle<Code> handler =
-          PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
-              receiver_map, language_mode(), store_mode);
-      ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
-      return null_handle;
+          PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(receiver_map,
+                                                                  store_mode);
+      return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
     }
   }
 
@@ -1919,14 +1944,12 @@
     // If the miss wasn't due to an unseen map, a polymorphic stub
     // won't help, use the megamorphic stub which can handle everything.
     TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "same map added twice");
-    return megamorphic_stub();
+    return;
   }
 
   // If the maximum number of receiver maps has been exceeded, use the
   // megamorphic version of the IC.
-  if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
-    return megamorphic_stub();
-  }
+  if (target_receiver_maps.length() > kMaxKeyedPolymorphism) return;
 
   // Make sure all polymorphic handlers have the same store mode, otherwise the
   // megamorphic stub must be used.
@@ -1936,7 +1959,7 @@
       store_mode = old_store_mode;
     } else if (store_mode != old_store_mode) {
       TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "store mode mismatch");
-      return megamorphic_stub();
+      return;
     }
   }
 
@@ -1954,17 +1977,16 @@
         external_arrays != target_receiver_maps.length()) {
       TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
                        "unsupported combination of external and normal arrays");
-      return megamorphic_stub();
+      return;
     }
   }
 
+  TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_Polymorphic);
   MapHandleList transitioned_maps(target_receiver_maps.length());
   CodeHandleList handlers(target_receiver_maps.length());
   PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers(
-      &target_receiver_maps, &transitioned_maps, &handlers, store_mode,
-      language_mode());
+      &target_receiver_maps, &transitioned_maps, &handlers, store_mode);
   ConfigureVectorState(&target_receiver_maps, &transitioned_maps, &handlers);
-  return null_handle;
 }
 
 
@@ -2077,7 +2099,6 @@
   key = TryConvertKey(key, isolate());
 
   Handle<Object> store_handle;
-  Handle<Code> stub = megamorphic_stub();
 
   uint32_t index;
   if ((key->IsInternalizedString() &&
@@ -2097,10 +2118,8 @@
     return store_handle;
   }
 
-  bool use_ic =
-      FLAG_use_ic && !object->IsStringWrapper() &&
-      !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy() &&
-      !(object->IsJSObject() && JSObject::cast(*object)->map()->is_observed());
+  bool use_ic = FLAG_use_ic && !object->IsStringWrapper() &&
+                !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy();
   if (use_ic && !object->IsSmi()) {
     // Don't use ICs for maps of the objects in Array's prototype chain. We
     // expect to be able to trap element sets to objects with those maps in
@@ -2148,7 +2167,7 @@
         // other non-dictionary receivers in the polymorphic case benefit
         // from fast path keyed stores.
         if (!old_receiver_map->DictionaryElementsInPrototypeChainOnly()) {
-          stub = StoreElementStub(old_receiver_map, store_mode);
+          UpdateStoreElement(old_receiver_map, store_mode);
         } else {
           TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
                            "dictionary or proxy prototype");
@@ -2161,13 +2180,9 @@
     }
   }
 
-  if (!is_vector_set() || stub.is_null()) {
-    Code* megamorphic = *megamorphic_stub();
-    if (!stub.is_null() && (*stub == megamorphic || *stub == *slow_stub())) {
-      ConfigureVectorState(MEGAMORPHIC, key);
-      TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
-                       *stub == megamorphic ? "set generic" : "slow stub");
-    }
+  if (!is_vector_set()) {
+    ConfigureVectorState(MEGAMORPHIC, key);
+    TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic");
   }
   TRACE_IC("StoreIC", key);
 
@@ -2247,32 +2262,111 @@
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
   HandleScope scope(isolate);
   Handle<Object> receiver = args.at<Object>(0);
-  Handle<Name> key = args.at<Name>(1);
-  Handle<Object> result;
 
-  DCHECK(args.length() == 4);
+  DCHECK_EQ(4, args.length());
   Handle<Smi> slot = args.at<Smi>(2);
   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
   // A monomorphic or polymorphic KeyedLoadIC with a string key can call the
   // LoadIC miss handler if the handler misses. Since the vector Nexus is
   // set up outside the IC, handle that here.
-  if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::LOAD_IC) {
+  FeedbackVectorSlotKind kind = vector->GetKind(vector_slot);
+  if (kind == FeedbackVectorSlotKind::LOAD_IC) {
+    Handle<Name> key = args.at<Name>(1);
     LoadICNexus nexus(vector, vector_slot);
     LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
     ic.UpdateState(receiver, key);
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
+    RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
+
+  } else if (kind == FeedbackVectorSlotKind::LOAD_GLOBAL_IC) {
+    Handle<Name> key(vector->GetName(vector_slot), isolate);
+    DCHECK_NE(*key, *isolate->factory()->empty_string());
+    DCHECK_EQ(*isolate->global_object(), *receiver);
+    LoadGlobalICNexus nexus(vector, vector_slot);
+    LoadGlobalIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
+    ic.UpdateState(receiver, key);
+    RETURN_RESULT_OR_FAILURE(isolate, ic.Load(key));
+
   } else {
-    DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC,
-              vector->GetKind(vector_slot));
+    Handle<Name> key = args.at<Name>(1);
+    DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, kind);
     KeyedLoadICNexus nexus(vector, vector_slot);
     KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
     ic.UpdateState(receiver, key);
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
+    RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
   }
+}
+
+// Used from ic-<arch>.cc.
+RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Miss) {
+  TimerEventScope<TimerEventIcMiss> timer(isolate);
+  HandleScope scope(isolate);
+  DCHECK_EQ(2, args.length());
+  Handle<JSGlobalObject> global = isolate->global_object();
+  Handle<Smi> slot = args.at<Smi>(0);
+  Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1);
+  FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
+  DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC,
+            vector->GetKind(vector_slot));
+  Handle<String> name(vector->GetName(vector_slot), isolate);
+  DCHECK_NE(*name, *isolate->factory()->empty_string());
+
+  LoadGlobalICNexus nexus(vector, vector_slot);
+  LoadGlobalIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
+  ic.UpdateState(global, name);
+
+  Handle<Object> result;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(name));
   return *result;
 }
 
+RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Slow) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(2, args.length());
+  CONVERT_SMI_ARG_CHECKED(slot, 0);
+  CONVERT_ARG_HANDLE_CHECKED(TypeFeedbackVector, vector, 1);
+
+  FeedbackVectorSlot vector_slot = vector->ToSlot(slot);
+  DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC,
+            vector->GetKind(vector_slot));
+  Handle<String> name(vector->GetName(vector_slot), isolate);
+  DCHECK_NE(*name, *isolate->factory()->empty_string());
+
+  Handle<JSGlobalObject> global = isolate->global_object();
+
+  Handle<ScriptContextTable> script_contexts(
+      global->native_context()->script_context_table());
+
+  ScriptContextTable::LookupResult lookup_result;
+  if (ScriptContextTable::Lookup(script_contexts, name, &lookup_result)) {
+    Handle<Context> script_context = ScriptContextTable::GetContext(
+        script_contexts, lookup_result.context_index);
+    Handle<Object> result =
+        FixedArray::get(*script_context, lookup_result.slot_index, isolate);
+    if (*result == *isolate->factory()->the_hole_value()) {
+      THROW_NEW_ERROR_RETURN_FAILURE(
+          isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
+    }
+    return *result;
+  }
+
+  Handle<Object> result;
+  bool is_found = false;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, result,
+      Runtime::GetObjectProperty(isolate, global, name, &is_found));
+  if (!is_found) {
+    LoadICNexus nexus(isolate);
+    LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
+    // It is actually a LoadGlobalICs here but the predicate handles this case
+    // properly.
+    if (ic.ShouldThrowReferenceError()) {
+      THROW_NEW_ERROR_RETURN_FAILURE(
+          isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
+    }
+  }
+  return *result;
+}
 
 // Used from ic-<arch>.cc
 RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) {
@@ -2281,7 +2375,6 @@
   HandleScope scope(isolate);
   Handle<Object> receiver = args.at<Object>(0);
   Handle<Object> key = args.at<Object>(1);
-  Handle<Object> result;
 
   DCHECK(args.length() == 4);
   Handle<Smi> slot = args.at<Smi>(2);
@@ -2290,8 +2383,7 @@
   KeyedLoadICNexus nexus(vector, vector_slot);
   KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
   ic.UpdateState(receiver, key);
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
 }
 
 
@@ -2301,7 +2393,6 @@
   HandleScope scope(isolate);
   Handle<Object> receiver = args.at<Object>(0);
   Handle<Object> key = args.at<Object>(1);
-  Handle<Object> result;
 
   DCHECK(args.length() == 4);
   Handle<Smi> slot = args.at<Smi>(2);
@@ -2310,9 +2401,7 @@
   KeyedLoadICNexus nexus(vector, vector_slot);
   KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
   ic.UpdateState(receiver, key);
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
-
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
 }
 
 
@@ -2324,7 +2413,6 @@
   Handle<Object> receiver = args.at<Object>(0);
   Handle<Name> key = args.at<Name>(1);
   Handle<Object> value = args.at<Object>(2);
-  Handle<Object> result;
 
   DCHECK(args.length() == 5 || args.length() == 6);
   Handle<Smi> slot = args.at<Smi>(3);
@@ -2334,18 +2422,15 @@
     StoreICNexus nexus(vector, vector_slot);
     StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
     ic.UpdateState(receiver, key);
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                       ic.Store(receiver, key, value));
+    RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
   } else {
     DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC,
               vector->GetKind(vector_slot));
     KeyedStoreICNexus nexus(vector, vector_slot);
     KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
     ic.UpdateState(receiver, key);
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                       ic.Store(receiver, key, value));
+    RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
   }
-  return *result;
 }
 
 
@@ -2356,7 +2441,6 @@
   Handle<Object> receiver = args.at<Object>(0);
   Handle<Name> key = args.at<Name>(1);
   Handle<Object> value = args.at<Object>(2);
-  Handle<Object> result;
 
   int length = args.length();
   DCHECK(length == 5 || length == 6);
@@ -2386,18 +2470,15 @@
     StoreICNexus nexus(vector, vector_slot);
     StoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
     ic.UpdateState(receiver, key);
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                       ic.Store(receiver, key, value));
+    RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
   } else {
     DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC,
               vector->GetKind(vector_slot));
     KeyedStoreICNexus nexus(vector, vector_slot);
     KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
     ic.UpdateState(receiver, key);
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                       ic.Store(receiver, key, value));
+    RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
   }
-  return *result;
 }
 
 
@@ -2409,7 +2490,6 @@
   Handle<Object> receiver = args.at<Object>(0);
   Handle<Object> key = args.at<Object>(1);
   Handle<Object> value = args.at<Object>(2);
-  Handle<Object> result;
 
   DCHECK(args.length() == 5);
   Handle<Smi> slot = args.at<Smi>(3);
@@ -2418,9 +2498,7 @@
   KeyedStoreICNexus nexus(vector, vector_slot);
   KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
   ic.UpdateState(receiver, key);
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     ic.Store(receiver, key, value));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
 }
 
 
@@ -2431,7 +2509,6 @@
   Handle<Object> receiver = args.at<Object>(0);
   Handle<Object> key = args.at<Object>(1);
   Handle<Object> value = args.at<Object>(2);
-  Handle<Object> result;
 
   DCHECK(args.length() == 5);
   Handle<Smi> slot = args.at<Smi>(3);
@@ -2440,9 +2517,7 @@
   KeyedStoreICNexus nexus(vector, vector_slot);
   KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
   ic.UpdateState(receiver, key);
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     ic.Store(receiver, key, value));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
 }
 
 
@@ -2456,11 +2531,9 @@
   StoreICNexus nexus(isolate);
   StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
   language_mode = ic.language_mode();
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
+  RETURN_RESULT_OR_FAILURE(
+      isolate,
       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
-  return *result;
 }
 
 
@@ -2474,11 +2547,9 @@
   KeyedStoreICNexus nexus(isolate);
   KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
   language_mode = ic.language_mode();
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
+  RETURN_RESULT_OR_FAILURE(
+      isolate,
       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
-  return *result;
 }
 
 
@@ -2501,18 +2572,16 @@
     JSObject::TransitionElementsKind(Handle<JSObject>::cast(object),
                                      map->elements_kind());
   }
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
+  RETURN_RESULT_OR_FAILURE(
+      isolate,
       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
-  return *result;
 }
 
 
 MaybeHandle<Object> BinaryOpIC::Transition(
     Handle<AllocationSite> allocation_site, Handle<Object> left,
     Handle<Object> right) {
-  BinaryOpICState state(isolate(), target()->extra_ic_state());
+  BinaryOpICState state(isolate(), extra_ic_state());
 
   // Compute the actual result using the builtin for the binary operation.
   Handle<Object> result;
@@ -2576,16 +2645,12 @@
     return result;
   }
 
-  // Execution::Call can execute arbitrary JavaScript, hence potentially
-  // update the state of this very IC, so we must update the stored state.
-  UpdateTarget();
-
   // Compute the new state.
   BinaryOpICState old_state(isolate(), target()->extra_ic_state());
   state.Update(left, right, result);
 
   // Check if we have a string operation here.
-  Handle<Code> target;
+  Handle<Code> new_target;
   if (!allocation_site.is_null() || state.ShouldCreateAllocationMementos()) {
     // Setup the allocation site on-demand.
     if (allocation_site.is_null()) {
@@ -2594,24 +2659,24 @@
 
     // Install the stub with an allocation site.
     BinaryOpICWithAllocationSiteStub stub(isolate(), state);
-    target = stub.GetCodeCopyFromTemplate(allocation_site);
+    new_target = stub.GetCodeCopyFromTemplate(allocation_site);
 
     // Sanity check the trampoline stub.
-    DCHECK_EQ(*allocation_site, target->FindFirstAllocationSite());
+    DCHECK_EQ(*allocation_site, new_target->FindFirstAllocationSite());
   } else {
     // Install the generic stub.
     BinaryOpICStub stub(isolate(), state);
-    target = stub.GetCode();
+    new_target = stub.GetCode();
 
     // Sanity check the generic stub.
-    DCHECK_NULL(target->FindFirstAllocationSite());
+    DCHECK_NULL(new_target->FindFirstAllocationSite());
   }
-  set_target(*target);
+  set_target(*new_target);
 
   if (FLAG_trace_ic) {
     OFStream os(stdout);
     os << "[BinaryOpIC" << old_state << " => " << state << " @ "
-       << static_cast<void*>(*target) << " <- ";
+       << static_cast<void*>(*new_target) << " <- ";
     JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
     if (!allocation_site.is_null()) {
       os << " using allocation site " << static_cast<void*>(*allocation_site);
@@ -2638,11 +2703,8 @@
   Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft);
   Handle<Object> right = args.at<Object>(BinaryOpICStub::kRight);
   BinaryOpIC ic(isolate);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      ic.Transition(Handle<AllocationSite>::null(), left, right));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, ic.Transition(Handle<AllocationSite>::null(), left, right));
 }
 
 
@@ -2657,10 +2719,8 @@
   Handle<Object> right =
       args.at<Object>(BinaryOpWithAllocationSiteStub::kRight);
   BinaryOpIC ic(isolate);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, ic.Transition(allocation_site, left, right));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate,
+                           ic.Transition(allocation_site, left, right));
 }
 
 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) {
@@ -2688,7 +2748,7 @@
   CompareICState::State new_right =
       CompareICState::NewInputState(old_stub.right(), y);
   CompareICState::State state = CompareICState::TargetState(
-      old_stub.state(), old_stub.left(), old_stub.right(), op_,
+      isolate(), old_stub.state(), old_stub.left(), old_stub.right(), op_,
       HasInlinedSmiCode(address()), x, y);
   CompareICStub stub(isolate(), op_, new_left, new_right, state);
   if (state == CompareICState::KNOWN_RECEIVER) {
@@ -2739,7 +2799,7 @@
 
 
 Handle<Object> ToBooleanIC::ToBoolean(Handle<Object> object) {
-  ToBooleanICStub stub(isolate(), target()->extra_ic_state());
+  ToBooleanICStub stub(isolate(), extra_ic_state());
   bool to_boolean_value = stub.UpdateStatus(object);
   Handle<Code> code = stub.GetCode();
   set_target(*code);
@@ -2767,6 +2827,12 @@
   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 5);
   HandleScope scope(isolate);
 
+  if (FLAG_runtime_call_stats) {
+    RETURN_RESULT_OR_FAILURE(
+        isolate, Runtime::SetObjectProperty(isolate, receiver, name, value,
+                                            language_mode));
+  }
+
   Handle<AccessorInfo> callback(
       callback_or_cell->IsWeakCell()
           ? AccessorInfo::cast(WeakCell::cast(*callback_or_cell)->value())
@@ -2872,15 +2938,15 @@
 
   if (it.IsFound()) return *result;
 
+#ifdef DEBUG
   LoadICNexus nexus(isolate);
   LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
-  if (!ic.ShouldThrowReferenceError(it.GetReceiver())) {
-    return isolate->heap()->undefined_value();
-  }
+  // It could actually be any kind of LoadICs here but the predicate handles
+  // all the cases properly.
+  DCHECK(!ic.ShouldThrowReferenceError());
+#endif
 
-  // Throw a reference error.
-  THROW_NEW_ERROR_RETURN_FAILURE(
-      isolate, NewReferenceError(MessageTemplate::kNotDefined, it.name()));
+  return isolate->heap()->undefined_value();
 }
 
 
@@ -2958,7 +3024,6 @@
   HandleScope scope(isolate);
   Handle<Object> receiver = args.at<Object>(0);
   Handle<Name> key = args.at<Name>(1);
-  Handle<Object> result;
 
   DCHECK(args.length() == 4);
   Handle<Smi> slot = args.at<Smi>(2);
@@ -2971,17 +3036,15 @@
     LoadICNexus nexus(vector, vector_slot);
     LoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
     ic.UpdateState(receiver, key);
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
+    RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
   } else {
     DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC,
               vector->GetKind(vector_slot));
     KeyedLoadICNexus nexus(vector, vector_slot);
     KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
     ic.UpdateState(receiver, key);
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
+    RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
   }
-
-  return *result;
 }
 }  // namespace internal
 }  // namespace v8
diff --git a/src/ic/ic.h b/src/ic/ic.h
index 8bd2f44..8d45eab 100644
--- a/src/ic/ic.h
+++ b/src/ic/ic.h
@@ -35,11 +35,11 @@
   // Compute the current IC state based on the target stub, receiver and name.
   void UpdateState(Handle<Object> receiver, Handle<Object> name);
 
-  bool IsNameCompatibleWithPrototypeFailure(Handle<Object> name);
-  void MarkPrototypeFailure(Handle<Object> name) {
-    DCHECK(IsNameCompatibleWithPrototypeFailure(name));
+  bool RecomputeHandlerForName(Handle<Object> name);
+  void MarkRecomputeHandler(Handle<Object> name) {
+    DCHECK(RecomputeHandlerForName(name));
     old_state_ = state_;
-    state_ = PROTOTYPE_FAILURE;
+    state_ = RECOMPUTE_HANDLER;
   }
 
   // Clear the inline cache to initial state.
@@ -47,14 +47,13 @@
 
 #ifdef DEBUG
   bool IsLoadStub() const {
-    return target()->is_load_stub() || target()->is_keyed_load_stub();
+    return kind_ == Code::LOAD_IC || kind_ == Code::LOAD_GLOBAL_IC ||
+           kind_ == Code::KEYED_LOAD_IC;
   }
-
   bool IsStoreStub() const {
-    return target()->is_store_stub() || target()->is_keyed_store_stub();
+    return kind_ == Code::STORE_IC || kind_ == Code::KEYED_STORE_IC;
   }
-
-  bool IsCallStub() const { return target()->is_call_stub(); }
+  bool IsCallStub() const { return kind_ == Code::CALL_IC; }
 #endif
 
   static inline Handle<Map> GetHandlerCacheHolder(Handle<Map> receiver_map,
@@ -65,26 +64,20 @@
                                              Isolate* isolate,
                                              CacheHolderFlag* flag);
 
-  static bool IsCleared(Code* code) {
-    InlineCacheState state = code->ic_state();
-    return !FLAG_use_ic || state == UNINITIALIZED || state == PREMONOMORPHIC;
-  }
-
   static bool IsCleared(FeedbackNexus* nexus) {
     InlineCacheState state = nexus->StateFromFeedback();
     return !FLAG_use_ic || state == UNINITIALIZED || state == PREMONOMORPHIC;
   }
 
   static bool ICUseVector(Code::Kind kind) {
-    return kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC ||
-           kind == Code::CALL_IC || kind == Code::STORE_IC ||
-           kind == Code::KEYED_STORE_IC;
+    return kind == Code::LOAD_IC || kind == Code::LOAD_GLOBAL_IC ||
+           kind == Code::KEYED_LOAD_IC || kind == Code::CALL_IC ||
+           kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC;
   }
 
- protected:
-  // Get the call-site target; used for determining the state.
-  Handle<Code> target() const { return target_; }
+  static InlineCacheState StateFromCode(Code* code);
 
+ protected:
   Address fp() const { return fp_; }
   Address pc() const { return *pc_address_; }
   Isolate* isolate() const { return isolate_; }
@@ -101,13 +94,12 @@
 
   // Set the call-site target.
   inline void set_target(Code* code);
-  bool is_target_set() { return target_set_; }
   bool is_vector_set() { return vector_set_; }
 
   bool UseVector() const {
     bool use = ICUseVector(kind());
     // If we are supposed to use the nexus, verify the nexus is non-null.
-    DCHECK(!use || nexus_ != NULL);
+    DCHECK(!use || nexus_ != nullptr);
     return use;
   }
 
@@ -139,9 +131,6 @@
                                          Address constant_pool);
   static inline void SetTargetAtAddress(Address address, Code* target,
                                         Address constant_pool);
-  static void OnTypeFeedbackChanged(Isolate* isolate, Address address,
-                                    State old_state, State new_state,
-                                    bool target_remains_ic_stub);
   // As a vector-based IC, type feedback must be updated differently.
   static void OnTypeFeedbackChanged(Isolate* isolate, Code* host);
   static void PostPatching(Address address, Code* target, Code* old_target);
@@ -149,6 +138,10 @@
   // Compute the handler either by compiling or by retrieving a cached version.
   Handle<Code> ComputeHandler(LookupIterator* lookup,
                               Handle<Object> value = Handle<Code>::null());
+  virtual Handle<Code> GetMapIndependentHandler(LookupIterator* lookup) {
+    UNREACHABLE();
+    return Handle<Code>::null();
+  }
   virtual Handle<Code> CompileHandler(LookupIterator* lookup,
                                       Handle<Object> value,
                                       CacheHolderFlag cache_holder) {
@@ -164,22 +157,18 @@
   bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map);
   void PatchCache(Handle<Name> name, Handle<Code> code);
   Code::Kind kind() const { return kind_; }
+  bool is_keyed() const {
+    return kind_ == Code::KEYED_LOAD_IC || kind_ == Code::KEYED_STORE_IC;
+  }
   Code::Kind handler_kind() const {
     if (kind_ == Code::KEYED_LOAD_IC) return Code::LOAD_IC;
     DCHECK(kind_ == Code::LOAD_IC || kind_ == Code::STORE_IC ||
            kind_ == Code::KEYED_STORE_IC);
     return kind_;
   }
-  virtual Handle<Code> megamorphic_stub() {
-    UNREACHABLE();
-    return Handle<Code>::null();
-  }
-
-  bool TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
-                                              Handle<String> name);
+  bool ShouldRecomputeHandler(Handle<Object> receiver, Handle<String> name);
 
   ExtraICState extra_ic_state() const { return extra_ic_state_; }
-  void set_extra_ic_state(ExtraICState state) { extra_ic_state_ = state; }
 
   Handle<Map> receiver_map() { return receiver_map_; }
   void update_receiver_map(Handle<Object> receiver) {
@@ -202,12 +191,10 @@
     return target_maps_.length() > 0 ? *target_maps_.at(0) : NULL;
   }
 
-  inline void UpdateTarget();
-
   Handle<TypeFeedbackVector> vector() const { return nexus()->vector_handle(); }
   FeedbackVectorSlot slot() const { return nexus()->slot(); }
   State saved_state() const {
-    return state() == PROTOTYPE_FAILURE ? old_state_ : state();
+    return state() == RECOMPUTE_HANDLER ? old_state_ : state();
   }
 
   template <class NexusClass>
@@ -217,25 +204,17 @@
   FeedbackNexus* nexus() const { return nexus_; }
 
   inline Code* get_host();
+  inline Code* target() const;
 
  private:
-  inline Code* raw_target() const;
   inline Address constant_pool() const;
   inline Address raw_constant_pool() const;
 
   void FindTargetMaps() {
     if (target_maps_set_) return;
     target_maps_set_ = true;
-    if (UseVector()) {
-      nexus()->ExtractMaps(&target_maps_);
-    } else {
-      if (state_ == MONOMORPHIC) {
-        Map* map = target_->FindFirstMap();
-        if (map != NULL) target_maps_.Add(handle(map));
-      } else if (state_ != UNINITIALIZED && state_ != PREMONOMORPHIC) {
-        target_->FindAllMaps(&target_maps_);
-      }
-    }
+    DCHECK(UseVector());
+    nexus()->ExtractMaps(&target_maps_);
   }
 
   // Frame pointer for the frame that uses (calls) the IC.
@@ -253,9 +232,6 @@
 
   Isolate* isolate_;
 
-  // The original code target that missed.
-  Handle<Code> target_;
-  bool target_set_;
   bool vector_set_;
   State old_state_;  // For saving if we marked as prototype failure.
   State state_;
@@ -283,9 +259,6 @@
   void HandleMiss(Handle<Object> function);
 
   // Code generator routines.
-  static Handle<Code> initialize_stub(Isolate* isolate, int argc,
-                                      ConvertReceiverMode mode,
-                                      TailCallMode tail_call_mode);
   static Handle<Code> initialize_stub_in_optimized_code(
       Isolate* isolate, int argc, ConvertReceiverMode mode,
       TailCallMode tail_call_mode);
@@ -296,31 +269,25 @@
 
 class LoadIC : public IC {
  public:
-  TypeofMode typeof_mode() const {
-    return LoadICState::GetTypeofMode(extra_ic_state());
-  }
-
   LoadIC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL)
       : IC(depth, isolate, nexus) {
     DCHECK(nexus != NULL);
     DCHECK(IsLoadStub());
   }
 
-  bool ShouldThrowReferenceError(Handle<Object> receiver) {
-    return receiver->IsJSGlobalObject() && typeof_mode() == NOT_INSIDE_TYPEOF;
+  bool ShouldThrowReferenceError() const {
+    return kind() == Code::LOAD_GLOBAL_IC &&
+           LoadGlobalICState::GetTypeofMode(extra_ic_state()) ==
+               NOT_INSIDE_TYPEOF;
   }
 
   // Code generator routines.
 
-  static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
   static void GenerateMiss(MacroAssembler* masm);
   static void GenerateRuntimeGetProperty(MacroAssembler* masm);
   static void GenerateNormal(MacroAssembler* masm);
 
-  static Handle<Code> initialize_stub(Isolate* isolate,
-                                      ExtraICState extra_state);
-  static Handle<Code> initialize_stub_in_optimized_code(
-      Isolate* isolate, ExtraICState extra_state, State initialization_state);
+  static Handle<Code> initialize_stub_in_optimized_code(Isolate* isolate);
 
   MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
                                            Handle<Name> name);
@@ -328,35 +295,42 @@
   static void Clear(Isolate* isolate, Code* host, LoadICNexus* nexus);
 
  protected:
-  inline void set_target(Code* code);
-
-  Handle<Code> slow_stub() const {
-    if (kind() == Code::LOAD_IC) {
-      return isolate()->builtins()->LoadIC_Slow();
-    } else {
-      DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
-      return isolate()->builtins()->KeyedLoadIC_Slow();
-    }
+  virtual Handle<Code> slow_stub() const {
+    return isolate()->builtins()->LoadIC_Slow();
   }
 
-  Handle<Code> megamorphic_stub() override;
-
   // Update the inline cache and the global stub cache based on the
   // lookup result.
   void UpdateCaches(LookupIterator* lookup);
 
+  Handle<Code> GetMapIndependentHandler(LookupIterator* lookup) override;
+
   Handle<Code> CompileHandler(LookupIterator* lookup, Handle<Object> unused,
                               CacheHolderFlag cache_holder) override;
 
  private:
   Handle<Code> SimpleFieldLoad(FieldIndex index);
 
-  static void Clear(Isolate* isolate, Address address, Code* target,
-                    Address constant_pool);
-
   friend class IC;
 };
 
+class LoadGlobalIC : public LoadIC {
+ public:
+  LoadGlobalIC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL)
+      : LoadIC(depth, isolate, nexus) {}
+
+  static Handle<Code> initialize_stub_in_optimized_code(
+      Isolate* isolate, ExtraICState extra_state);
+
+  MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Name> name);
+
+  static void Clear(Isolate* isolate, Code* host, LoadGlobalICNexus* nexus);
+
+ protected:
+  Handle<Code> slow_stub() const override {
+    return isolate()->builtins()->LoadGlobalIC_Slow();
+  }
+};
 
 class KeyedLoadIC : public LoadIC {
  public:
@@ -364,7 +338,6 @@
               KeyedLoadICNexus* nexus = NULL)
       : LoadIC(depth, isolate, nexus) {
     DCHECK(nexus != NULL);
-    DCHECK(target()->is_keyed_load_stub());
   }
 
   MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
@@ -373,20 +346,10 @@
   // Code generator routines.
   static void GenerateMiss(MacroAssembler* masm);
   static void GenerateRuntimeGetProperty(MacroAssembler* masm);
-  static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
   static void GenerateMegamorphic(MacroAssembler* masm);
 
-  // Bit mask to be tested against bit field for the cases when
-  // generic stub should go into slow case.
-  // Access check is necessary explicitly since generic stub does not perform
-  // map checks.
-  static const int kSlowCaseBitFieldMask =
-      (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
-
-  static Handle<Code> initialize_stub(Isolate* isolate,
-                                      ExtraICState extra_state);
   static Handle<Code> initialize_stub_in_optimized_code(
-      Isolate* isolate, State initialization_state, ExtraICState extra_state);
+      Isolate* isolate, ExtraICState extra_state);
   static Handle<Code> ChooseMegamorphicStub(Isolate* isolate,
                                             ExtraICState extra_state);
 
@@ -394,22 +357,15 @@
 
  protected:
   // receiver is HeapObject because it could be a String or a JSObject
-  Handle<Code> LoadElementStub(Handle<HeapObject> receiver);
+  void UpdateLoadElement(Handle<HeapObject> receiver);
 
  private:
-  static void Clear(Isolate* isolate, Address address, Code* target,
-                    Address constant_pool);
-
   friend class IC;
 };
 
 
 class StoreIC : public IC {
  public:
-  static ExtraICState ComputeExtraICState(LanguageMode flag) {
-    return StoreICState(flag).GetExtraICState();
-  }
-
   StoreIC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL)
       : IC(depth, isolate, nexus) {
     DCHECK(IsStoreStub());
@@ -421,21 +377,11 @@
 
   // Code generators for stub routines. Only called once at startup.
   static void GenerateSlow(MacroAssembler* masm);
-  static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
-  static void GeneratePreMonomorphic(MacroAssembler* masm) {
-    GenerateMiss(masm);
-  }
   static void GenerateMiss(MacroAssembler* masm);
-  static void GenerateMegamorphic(MacroAssembler* masm);
   static void GenerateNormal(MacroAssembler* masm);
-  static void GenerateRuntimeSetProperty(MacroAssembler* masm,
-                                         LanguageMode language_mode);
 
-  static Handle<Code> initialize_stub(Isolate* isolate,
-                                      LanguageMode language_mode,
-                                      State initialization_state);
   static Handle<Code> initialize_stub_in_optimized_code(
-      Isolate* isolate, LanguageMode language_mode, State initialization_state);
+      Isolate* isolate, LanguageMode language_mode);
 
   MUST_USE_RESULT MaybeHandle<Object> Store(
       Handle<Object> object, Handle<Name> name, Handle<Object> value,
@@ -449,29 +395,19 @@
 
  protected:
   // Stub accessors.
-  Handle<Code> megamorphic_stub() override;
-  Handle<Code> slow_stub() const;
-
-  virtual Handle<Code> pre_monomorphic_stub() const {
-    return pre_monomorphic_stub(isolate(), language_mode());
+  Handle<Code> slow_stub() const {
+    return isolate()->builtins()->StoreIC_Slow();
   }
 
-  static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
-                                           LanguageMode language_mode);
-
   // Update the inline cache and the global stub cache based on the
   // lookup result.
   void UpdateCaches(LookupIterator* lookup, Handle<Object> value,
                     JSReceiver::StoreFromKeyed store_mode);
+  Handle<Code> GetMapIndependentHandler(LookupIterator* lookup) override;
   Handle<Code> CompileHandler(LookupIterator* lookup, Handle<Object> value,
                               CacheHolderFlag cache_holder) override;
 
  private:
-  inline void set_target(Code* code);
-
-  static void Clear(Isolate* isolate, Address address, Code* target,
-                    Address constant_pool);
-
   friend class IC;
 };
 
@@ -484,79 +420,36 @@
 
 class KeyedStoreIC : public StoreIC {
  public:
-  // ExtraICState bits (building on IC)
-  // ExtraICState bits
-  // When more language modes are added, these BitFields need to move too.
-  STATIC_ASSERT(i::LANGUAGE_END == 3);
-  class ExtraICStateKeyedAccessStoreMode
-      : public BitField<KeyedAccessStoreMode, 3, 3> {};  // NOLINT
-
-  class IcCheckTypeField : public BitField<IcCheckType, 6, 1> {};
-
-  static ExtraICState ComputeExtraICState(LanguageMode flag,
-                                          KeyedAccessStoreMode mode) {
-    return StoreICState(flag).GetExtraICState() |
-           ExtraICStateKeyedAccessStoreMode::encode(mode) |
-           IcCheckTypeField::encode(ELEMENT);
-  }
-
   KeyedAccessStoreMode GetKeyedAccessStoreMode() {
     return casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode();
   }
 
   KeyedStoreIC(FrameDepth depth, Isolate* isolate,
                KeyedStoreICNexus* nexus = NULL)
-      : StoreIC(depth, isolate, nexus) {
-    DCHECK(target()->is_keyed_store_stub());
-  }
+      : StoreIC(depth, isolate, nexus) {}
 
   MUST_USE_RESULT MaybeHandle<Object> Store(Handle<Object> object,
                                             Handle<Object> name,
                                             Handle<Object> value);
 
   // Code generators for stub routines.  Only called once at startup.
-  static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
-  static void GeneratePreMonomorphic(MacroAssembler* masm) {
-    GenerateMiss(masm);
-  }
   static void GenerateMiss(MacroAssembler* masm);
   static void GenerateSlow(MacroAssembler* masm);
   static void GenerateMegamorphic(MacroAssembler* masm,
                                   LanguageMode language_mode);
 
-  static Handle<Code> initialize_stub(Isolate* isolate,
-                                      LanguageMode language_mode,
-                                      State initialization_state);
-
   static Handle<Code> initialize_stub_in_optimized_code(
-      Isolate* isolate, LanguageMode language_mode, State initialization_state);
+      Isolate* isolate, LanguageMode language_mode);
   static Handle<Code> ChooseMegamorphicStub(Isolate* isolate,
                                             ExtraICState extra_state);
 
   static void Clear(Isolate* isolate, Code* host, KeyedStoreICNexus* nexus);
 
  protected:
-  virtual Handle<Code> pre_monomorphic_stub() const {
-    return pre_monomorphic_stub(isolate(), language_mode());
-  }
-  static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
-                                           LanguageMode language_mode) {
-    if (is_strict(language_mode)) {
-      return isolate->builtins()->KeyedStoreIC_PreMonomorphic_Strict();
-    } else {
-      return isolate->builtins()->KeyedStoreIC_PreMonomorphic();
-    }
-  }
-
-  Handle<Code> StoreElementStub(Handle<Map> receiver_map,
-                                KeyedAccessStoreMode store_mode);
+  void UpdateStoreElement(Handle<Map> receiver_map,
+                          KeyedAccessStoreMode store_mode);
 
  private:
-  inline void set_target(Code* code);
-
-  static void Clear(Isolate* isolate, Address address, Code* target,
-                    Address constant_pool);
-
   Handle<Map> ComputeTransitionedMap(Handle<Map> map,
                                      KeyedAccessStoreMode store_mode);
 
diff --git a/src/ic/mips/access-compiler-mips.cc b/src/ic/mips/access-compiler-mips.cc
index b122946..2aa0283 100644
--- a/src/ic/mips/access-compiler-mips.cc
+++ b/src/ic/mips/access-compiler-mips.cc
@@ -19,19 +19,19 @@
 
 
 Register* PropertyAccessCompiler::load_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3, scratch4.
+  // receiver, name, scratch1, scratch2, scratch3.
   Register receiver = LoadDescriptor::ReceiverRegister();
   Register name = LoadDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, a3, a0, t0, t1};
+  static Register registers[] = {receiver, name, a3, a0, t0};
   return registers;
 }
 
 
 Register* PropertyAccessCompiler::store_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3.
+  // receiver, name, scratch1, scratch2.
   Register receiver = StoreDescriptor::ReceiverRegister();
   Register name = StoreDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, a3, t0, t1};
+  static Register registers[] = {receiver, name, a3, t0};
   return registers;
 }
 
diff --git a/src/ic/mips/handler-compiler-mips.cc b/src/ic/mips/handler-compiler-mips.cc
index b924bda..66789e4 100644
--- a/src/ic/mips/handler-compiler-mips.cc
+++ b/src/ic/mips/handler-compiler-mips.cc
@@ -196,8 +196,9 @@
     MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name,
     Register scratch, Label* miss) {
   Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name);
-  DCHECK(cell->value()->IsTheHole());
-  Handle<WeakCell> weak_cell = masm->isolate()->factory()->NewWeakCell(cell);
+  Isolate* isolate = masm->isolate();
+  DCHECK(cell->value()->IsTheHole(isolate));
+  Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
   __ LoadWeakValue(scratch, weak_cell, miss);
   __ lw(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset));
   __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
@@ -279,7 +280,7 @@
   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
   bool call_data_undefined = false;
   // Put call data in place.
-  if (api_call_info->data()->IsUndefined()) {
+  if (api_call_info->data()->IsUndefined(isolate)) {
     call_data_undefined = true;
     __ LoadRoot(data, Heap::kUndefinedValueRootIndex);
   } else {
@@ -423,28 +424,25 @@
   DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
          !scratch2.is(scratch1));
 
-  if (FLAG_eliminate_prototype_chain_checks) {
-    Handle<Cell> validity_cell =
-        Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
-    if (!validity_cell.is_null()) {
-      DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
-                validity_cell->value());
-      __ li(scratch1, Operand(validity_cell));
-      __ lw(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
-      __ Branch(miss, ne, scratch1,
-                Operand(Smi::FromInt(Map::kPrototypeChainValid)));
-    }
+  Handle<Cell> validity_cell =
+      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
+  if (!validity_cell.is_null()) {
+    DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
+    __ li(scratch1, Operand(validity_cell));
+    __ lw(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
+    __ Branch(miss, ne, scratch1,
+              Operand(Smi::FromInt(Map::kPrototypeChainValid)));
+  }
 
-    // The prototype chain of primitives (and their JSValue wrappers) depends
-    // on the native context, which can't be guarded by validity cells.
-    // |object_reg| holds the native context specific prototype in this case;
-    // we need to check its map.
-    if (check == CHECK_ALL_MAPS) {
-      __ lw(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
-      Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
-      __ GetWeakValue(scratch2, cell);
-      __ Branch(miss, ne, scratch1, Operand(scratch2));
-    }
+  // The prototype chain of primitives (and their JSValue wrappers) depends
+  // on the native context, which can't be guarded by validity cells.
+  // |object_reg| holds the native context specific prototype in this case;
+  // we need to check its map.
+  if (check == CHECK_ALL_MAPS) {
+    __ lw(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
+    Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
+    __ GetWeakValue(scratch2, cell);
+    __ Branch(miss, ne, scratch1, Operand(scratch2));
   }
 
   // Keep track of the current object in register reg.
@@ -480,8 +478,10 @@
            !current_map->is_access_check_needed());
 
     prototype = handle(JSObject::cast(current_map->prototype()));
-    if (current_map->is_dictionary_map() &&
-        !current_map->IsJSGlobalObjectMap()) {
+    if (current_map->IsJSGlobalObjectMap()) {
+      GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
+                                name, scratch2, miss);
+    } else if (current_map->is_dictionary_map()) {
       DCHECK(!current_map->IsJSGlobalProxyMap());  // Proxy maps are fast.
       if (!name->IsUniqueName()) {
         DCHECK(name->IsString());
@@ -491,33 +491,12 @@
              current->property_dictionary()->FindEntry(name) ==
                  NameDictionary::kNotFound);
 
-      if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
+      if (depth > 1) {
         // TODO(jkummerow): Cache and re-use weak cell.
         __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
       }
       GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
                                        scratch2);
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
-        __ lw(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
-      }
-    } else {
-      Register map_reg = scratch1;
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
-      }
-      if (current_map->IsJSGlobalObjectMap()) {
-        GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
-                                  name, scratch2, miss);
-      } else if (!FLAG_eliminate_prototype_chain_checks &&
-                 (depth != 1 || check == CHECK_ALL_MAPS)) {
-        Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-        __ GetWeakValue(scratch2, cell);
-        __ Branch(miss, ne, scratch2, Operand(map_reg));
-      }
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ lw(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset));
-      }
     }
 
     reg = holder_reg;  // From now on the object will be in holder_reg.
@@ -531,17 +510,8 @@
   // Log the check depth.
   LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
 
-  if (!FLAG_eliminate_prototype_chain_checks &&
-      (depth != 0 || check == CHECK_ALL_MAPS)) {
-    // Check the holder map.
-    __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
-    Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-    __ GetWeakValue(scratch2, cell);
-    __ Branch(miss, ne, scratch2, Operand(scratch1));
-  }
-
   bool return_holder = return_what == RETURN_HOLDER;
-  if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
+  if (return_holder && depth != 0) {
     __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
   }
 
@@ -584,70 +554,10 @@
 }
 
 
-void NamedLoadHandlerCompiler::GenerateLoadCallback(
-    Register reg, Handle<AccessorInfo> callback) {
-  DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), receiver()));
-  DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), reg));
-
-  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
-  // name below the exit frame to make GC aware of them.
-  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
-  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
-  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
-  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
-  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
-  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
-
-  // Here and below +1 is for name() pushed after the args_ array.
-  typedef PropertyCallbackArguments PCA;
-  __ Subu(sp, sp, (PCA::kArgsLength + 1) * kPointerSize);
-  __ sw(receiver(), MemOperand(sp, (PCA::kThisIndex + 1) * kPointerSize));
-  Handle<Object> data(callback->data(), isolate());
-  if (data->IsUndefined() || data->IsSmi()) {
-    __ li(scratch2(), data);
-  } else {
-    Handle<WeakCell> cell =
-        isolate()->factory()->NewWeakCell(Handle<HeapObject>::cast(data));
-    // The callback is alive if this instruction is executed,
-    // so the weak cell is not cleared and points to data.
-    __ GetWeakValue(scratch2(), cell);
-  }
-  __ sw(scratch2(), MemOperand(sp, (PCA::kDataIndex + 1) * kPointerSize));
-  __ LoadRoot(scratch2(), Heap::kUndefinedValueRootIndex);
-  __ sw(scratch2(),
-        MemOperand(sp, (PCA::kReturnValueOffset + 1) * kPointerSize));
-  __ sw(scratch2(), MemOperand(sp, (PCA::kReturnValueDefaultValueIndex + 1) *
-                                       kPointerSize));
-  __ li(scratch2(), Operand(ExternalReference::isolate_address(isolate())));
-  __ sw(scratch2(), MemOperand(sp, (PCA::kIsolateIndex + 1) * kPointerSize));
-  __ sw(reg, MemOperand(sp, (PCA::kHolderIndex + 1) * kPointerSize));
-  // should_throw_on_error -> false
-  DCHECK(Smi::FromInt(0) == nullptr);
-  __ sw(zero_reg,
-        MemOperand(sp, (PCA::kShouldThrowOnErrorIndex + 1) * kPointerSize));
-
-  __ sw(name(), MemOperand(sp, 0 * kPointerSize));
-
-  // Abi for CallApiGetter.
-  Register getter_address_reg = ApiGetterDescriptor::function_address();
-
-  Address getter_address = v8::ToCData<Address>(callback->getter());
-  ApiFunction fun(getter_address);
-  ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
-  ExternalReference ref = ExternalReference(&fun, type, isolate());
-  __ li(getter_address_reg, Operand(ref));
-
-  CallApiGetterStub stub(isolate());
-  __ TailCallStub(&stub);
-}
-
-
 void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
     LookupIterator* it, Register holder_reg) {
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
 
   // Compile the interceptor call, followed by inline code to load the
   // property from further up the prototype chain if the call fails.
@@ -706,7 +616,7 @@
 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
   // Call the runtime system to load the interceptor.
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
   PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
                            holder());
 
@@ -722,7 +632,7 @@
   __ Push(receiver(), holder_reg);  // Receiver.
   // If the callback cannot leak, then push the callback directly,
   // otherwise wrap it in a weak cell.
-  if (callback->data()->IsUndefined() || callback->data()->IsSmi()) {
+  if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) {
     __ li(at, Operand(callback));
   } else {
     Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback);
@@ -737,7 +647,7 @@
   __ TailCallRuntime(Runtime::kStoreCallbackProperty);
 
   // Return the generated code.
-  return GetCode(kind(), Code::FAST, name);
+  return GetCode(kind(), name);
 }
 
 
@@ -778,7 +688,7 @@
   FrontendFooter(name, &miss);
 
   // Return the generated code.
-  return GetCode(kind(), Code::NORMAL, name);
+  return GetCode(kind(), name);
 }
 
 
diff --git a/src/ic/mips/ic-mips.cc b/src/ic/mips/ic-mips.cc
index ae3615e..f20262b 100644
--- a/src/ic/mips/ic-mips.cc
+++ b/src/ic/mips/ic-mips.cc
@@ -419,9 +419,9 @@
   __ LoadRoot(vector, Heap::kDummyVectorRootIndex);
   __ li(slot, Operand(Smi::FromInt(slot_index)));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::LOAD_IC, flags,
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
+  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::KEYED_LOAD_IC, flags,
                                                receiver, key, t0, t1, t2, t5);
   // Cache miss.
   GenerateMiss(masm);
@@ -616,11 +616,10 @@
   __ JumpIfSmi(receiver, &slow);
   // Get the map of the object.
   __ lw(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
-  // Check that the receiver does not require access checks and is not observed.
-  // The generic stub does not perform map checks or handle observed objects.
+  // Check that the receiver does not require access checks.
+  // The generic stub does not perform map checks.
   __ lbu(t0, FieldMemOperand(receiver_map, Map::kBitFieldOffset));
-  __ And(t0, t0,
-         Operand(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved));
+  __ And(t0, t0, Operand(1 << Map::kIsAccessCheckNeeded));
   __ Branch(&slow, ne, t0, Operand(zero_reg));
   // Check if the object is a JS array or not.
   __ lbu(t0, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset));
@@ -663,10 +662,10 @@
   __ LoadRoot(vector, Heap::kDummyVectorRootIndex);
   __ li(slot, Operand(Smi::FromInt(slot_index)));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags,
-                                               receiver, key, t1, t2, t4, t5);
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
+  masm->isolate()->stub_cache()->GenerateProbe(
+      masm, Code::KEYED_STORE_IC, flags, receiver, key, t1, t2, t4, t5);
   // Cache miss.
   __ Branch(&miss);
 
@@ -728,25 +727,6 @@
   __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss);
 }
 
-
-void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
-  Register receiver = StoreDescriptor::ReceiverRegister();
-  Register name = StoreDescriptor::NameRegister();
-  DCHECK(receiver.is(a1));
-  DCHECK(name.is(a2));
-  DCHECK(StoreDescriptor::ValueRegister().is(a0));
-
-  // Get the receiver from the stack and probe the stub cache.
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags,
-                                               receiver, name, a3, t0, t1, t2);
-
-  // Cache miss: Jump to runtime.
-  GenerateMiss(masm);
-}
-
-
 void StoreIC::GenerateMiss(MacroAssembler* masm) {
   StoreIC_PushArgs(masm);
 
@@ -840,8 +820,9 @@
   }
 
   if (FLAG_trace_ic) {
-    PrintF("[  patching ic at %p, andi=%p, delta=%d\n", address,
-           andi_instruction_address, delta);
+    PrintF("[  patching ic at %p, andi=%p, delta=%d\n",
+           static_cast<void*>(address),
+           static_cast<void*>(andi_instruction_address), delta);
   }
 
   Address patch_address =
diff --git a/src/ic/mips/stub-cache-mips.cc b/src/ic/mips/stub-cache-mips.cc
index 039763c..ec9f043 100644
--- a/src/ic/mips/stub-cache-mips.cc
+++ b/src/ic/mips/stub-cache-mips.cc
@@ -14,10 +14,9 @@
 
 #define __ ACCESS_MASM(masm)
 
-
 static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
-                       Code::Kind ic_kind, Code::Flags flags,
-                       StubCache::Table table, Register receiver, Register name,
+                       Code::Flags flags, StubCache::Table table,
+                       Register receiver, Register name,
                        // Number of the cache entry, not scaled.
                        Register offset, Register scratch, Register scratch2,
                        Register offset_scratch) {
@@ -97,9 +96,6 @@
   // entry size being 12.
   DCHECK(sizeof(Entry) == 12);
 
-  // Make sure the flags does not name a specific type.
-  DCHECK(Code::ExtractTypeFromFlags(flags) == 0);
-
   // Make sure that there are no register conflicts.
   DCHECK(!AreAliased(receiver, name, scratch, extra, extra2, extra3));
 
@@ -145,8 +141,8 @@
   __ And(scratch, scratch, Operand(mask));
 
   // Probe the primary table.
-  ProbeTable(isolate, masm, ic_kind, flags, kPrimary, receiver, name, scratch,
-             extra, extra2, extra3);
+  ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch, extra,
+             extra2, extra3);
 
   // Primary miss: Compute hash for secondary probe.
   __ srl(at, name, kCacheIndexShift);
@@ -156,8 +152,8 @@
   __ And(scratch, scratch, Operand(mask2));
 
   // Probe the secondary table.
-  ProbeTable(isolate, masm, ic_kind, flags, kSecondary, receiver, name, scratch,
-             extra, extra2, extra3);
+  ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch, extra,
+             extra2, extra3);
 
   // Cache miss: Fall-through and let caller handle the miss by
   // entering the runtime system.
diff --git a/src/ic/mips64/access-compiler-mips64.cc b/src/ic/mips64/access-compiler-mips64.cc
index 96e921c..bf6c73e 100644
--- a/src/ic/mips64/access-compiler-mips64.cc
+++ b/src/ic/mips64/access-compiler-mips64.cc
@@ -19,19 +19,19 @@
 
 
 Register* PropertyAccessCompiler::load_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3, scratch4.
+  // receiver, name, scratch1, scratch2, scratch3.
   Register receiver = LoadDescriptor::ReceiverRegister();
   Register name = LoadDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, a3, a0, a4, a5};
+  static Register registers[] = {receiver, name, a3, a0, a4};
   return registers;
 }
 
 
 Register* PropertyAccessCompiler::store_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3.
+  // receiver, name, scratch1, scratch2.
   Register receiver = StoreDescriptor::ReceiverRegister();
   Register name = StoreDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, a3, a4, a5};
+  static Register registers[] = {receiver, name, a3, a4};
   return registers;
 }
 
diff --git a/src/ic/mips64/handler-compiler-mips64.cc b/src/ic/mips64/handler-compiler-mips64.cc
index 52260ee..99ecbe2 100644
--- a/src/ic/mips64/handler-compiler-mips64.cc
+++ b/src/ic/mips64/handler-compiler-mips64.cc
@@ -196,8 +196,9 @@
     MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name,
     Register scratch, Label* miss) {
   Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name);
-  DCHECK(cell->value()->IsTheHole());
-  Handle<WeakCell> weak_cell = masm->isolate()->factory()->NewWeakCell(cell);
+  Isolate* isolate = masm->isolate();
+  DCHECK(cell->value()->IsTheHole(isolate));
+  Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
   __ LoadWeakValue(scratch, weak_cell, miss);
   __ ld(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset));
   __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
@@ -279,7 +280,7 @@
   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
   bool call_data_undefined = false;
   // Put call data in place.
-  if (api_call_info->data()->IsUndefined()) {
+  if (api_call_info->data()->IsUndefined(isolate)) {
     call_data_undefined = true;
     __ LoadRoot(data, Heap::kUndefinedValueRootIndex);
   } else {
@@ -423,28 +424,25 @@
   DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
          !scratch2.is(scratch1));
 
-  if (FLAG_eliminate_prototype_chain_checks) {
-    Handle<Cell> validity_cell =
-        Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
-    if (!validity_cell.is_null()) {
-      DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
-                validity_cell->value());
-      __ li(scratch1, Operand(validity_cell));
-      __ ld(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
-      __ Branch(miss, ne, scratch1,
-                Operand(Smi::FromInt(Map::kPrototypeChainValid)));
-    }
+  Handle<Cell> validity_cell =
+      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
+  if (!validity_cell.is_null()) {
+    DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
+    __ li(scratch1, Operand(validity_cell));
+    __ ld(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
+    __ Branch(miss, ne, scratch1,
+              Operand(Smi::FromInt(Map::kPrototypeChainValid)));
+  }
 
-    // The prototype chain of primitives (and their JSValue wrappers) depends
-    // on the native context, which can't be guarded by validity cells.
-    // |object_reg| holds the native context specific prototype in this case;
-    // we need to check its map.
-    if (check == CHECK_ALL_MAPS) {
-      __ ld(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
-      Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
-      __ GetWeakValue(scratch2, cell);
-      __ Branch(miss, ne, scratch1, Operand(scratch2));
-    }
+  // The prototype chain of primitives (and their JSValue wrappers) depends
+  // on the native context, which can't be guarded by validity cells.
+  // |object_reg| holds the native context specific prototype in this case;
+  // we need to check its map.
+  if (check == CHECK_ALL_MAPS) {
+    __ ld(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
+    Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
+    __ GetWeakValue(scratch2, cell);
+    __ Branch(miss, ne, scratch1, Operand(scratch2));
   }
 
   // Keep track of the current object in register reg.
@@ -480,8 +478,10 @@
            !current_map->is_access_check_needed());
 
     prototype = handle(JSObject::cast(current_map->prototype()));
-    if (current_map->is_dictionary_map() &&
-        !current_map->IsJSGlobalObjectMap()) {
+    if (current_map->IsJSGlobalObjectMap()) {
+      GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
+                                name, scratch2, miss);
+    } else if (current_map->is_dictionary_map()) {
       DCHECK(!current_map->IsJSGlobalProxyMap());  // Proxy maps are fast.
       if (!name->IsUniqueName()) {
         DCHECK(name->IsString());
@@ -491,33 +491,12 @@
              current->property_dictionary()->FindEntry(name) ==
                  NameDictionary::kNotFound);
 
-      if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
+      if (depth > 1) {
         // TODO(jkummerow): Cache and re-use weak cell.
         __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
       }
       GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
                                        scratch2);
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ ld(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
-        __ ld(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
-      }
-    } else {
-      Register map_reg = scratch1;
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ ld(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
-      }
-      if (current_map->IsJSGlobalObjectMap()) {
-        GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
-                                  name, scratch2, miss);
-      } else if (!FLAG_eliminate_prototype_chain_checks &&
-                 (depth != 1 || check == CHECK_ALL_MAPS)) {
-        Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-        __ GetWeakValue(scratch2, cell);
-        __ Branch(miss, ne, scratch2, Operand(map_reg));
-      }
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ ld(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset));
-      }
     }
 
     reg = holder_reg;  // From now on the object will be in holder_reg.
@@ -531,17 +510,8 @@
   // Log the check depth.
   LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
 
-  if (!FLAG_eliminate_prototype_chain_checks &&
-      (depth != 0 || check == CHECK_ALL_MAPS)) {
-    // Check the holder map.
-    __ ld(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
-    Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-    __ GetWeakValue(scratch2, cell);
-    __ Branch(miss, ne, scratch2, Operand(scratch1));
-  }
-
   bool return_holder = return_what == RETURN_HOLDER;
-  if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
+  if (return_holder && depth != 0) {
     __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
   }
 
@@ -584,70 +554,10 @@
 }
 
 
-void NamedLoadHandlerCompiler::GenerateLoadCallback(
-    Register reg, Handle<AccessorInfo> callback) {
-  DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), receiver()));
-  DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), reg));
-
-  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
-  // name below the exit frame to make GC aware of them.
-  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
-  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
-  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
-  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
-  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
-  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
-
-  // Here and below +1 is for name() pushed after the args_ array.
-  typedef PropertyCallbackArguments PCA;
-  __ Dsubu(sp, sp, (PCA::kArgsLength + 1) * kPointerSize);
-  __ sd(receiver(), MemOperand(sp, (PCA::kThisIndex + 1) * kPointerSize));
-  Handle<Object> data(callback->data(), isolate());
-  if (data->IsUndefined() || data->IsSmi()) {
-    __ li(scratch2(), data);
-  } else {
-    Handle<WeakCell> cell =
-        isolate()->factory()->NewWeakCell(Handle<HeapObject>::cast(data));
-    // The callback is alive if this instruction is executed,
-    // so the weak cell is not cleared and points to data.
-    __ GetWeakValue(scratch2(), cell);
-  }
-  __ sd(scratch2(), MemOperand(sp, (PCA::kDataIndex + 1) * kPointerSize));
-  __ LoadRoot(scratch2(), Heap::kUndefinedValueRootIndex);
-  __ sd(scratch2(),
-        MemOperand(sp, (PCA::kReturnValueOffset + 1) * kPointerSize));
-  __ sd(scratch2(), MemOperand(sp, (PCA::kReturnValueDefaultValueIndex + 1) *
-                                       kPointerSize));
-  __ li(scratch2(), Operand(ExternalReference::isolate_address(isolate())));
-  __ sd(scratch2(), MemOperand(sp, (PCA::kIsolateIndex + 1) * kPointerSize));
-  __ sd(reg, MemOperand(sp, (PCA::kHolderIndex + 1) * kPointerSize));
-  // should_throw_on_error -> false
-  DCHECK(Smi::FromInt(0) == nullptr);
-  __ sd(zero_reg,
-        MemOperand(sp, (PCA::kShouldThrowOnErrorIndex + 1) * kPointerSize));
-
-  __ sd(name(), MemOperand(sp, 0 * kPointerSize));
-
-  // Abi for CallApiGetter.
-  Register getter_address_reg = ApiGetterDescriptor::function_address();
-
-  Address getter_address = v8::ToCData<Address>(callback->getter());
-  ApiFunction fun(getter_address);
-  ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
-  ExternalReference ref = ExternalReference(&fun, type, isolate());
-  __ li(getter_address_reg, Operand(ref));
-
-  CallApiGetterStub stub(isolate());
-  __ TailCallStub(&stub);
-}
-
-
 void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
     LookupIterator* it, Register holder_reg) {
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
 
   // Compile the interceptor call, followed by inline code to load the
   // property from further up the prototype chain if the call fails.
@@ -706,7 +616,7 @@
 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
   // Call the runtime system to load the interceptor.
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
   PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
                            holder());
 
@@ -722,7 +632,7 @@
   __ Push(receiver(), holder_reg);  // Receiver.
   // If the callback cannot leak, then push the callback directly,
   // otherwise wrap it in a weak cell.
-  if (callback->data()->IsUndefined() || callback->data()->IsSmi()) {
+  if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) {
     __ li(at, Operand(callback));
   } else {
     Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback);
@@ -737,7 +647,7 @@
   __ TailCallRuntime(Runtime::kStoreCallbackProperty);
 
   // Return the generated code.
-  return GetCode(kind(), Code::FAST, name);
+  return GetCode(kind(), name);
 }
 
 
@@ -778,7 +688,7 @@
   FrontendFooter(name, &miss);
 
   // Return the generated code.
-  return GetCode(kind(), Code::NORMAL, name);
+  return GetCode(kind(), name);
 }
 
 
diff --git a/src/ic/mips64/ic-mips64.cc b/src/ic/mips64/ic-mips64.cc
index f46c9dc..81f1f92 100644
--- a/src/ic/mips64/ic-mips64.cc
+++ b/src/ic/mips64/ic-mips64.cc
@@ -418,9 +418,9 @@
   __ LoadRoot(vector, Heap::kDummyVectorRootIndex);
   __ li(slot, Operand(Smi::FromInt(slot_index)));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::LOAD_IC, flags,
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
+  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::KEYED_LOAD_IC, flags,
                                                receiver, key, a4, a5, a6, t1);
   // Cache miss.
   GenerateMiss(masm);
@@ -622,11 +622,10 @@
   __ JumpIfSmi(receiver, &slow);
   // Get the map of the object.
   __ ld(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
-  // Check that the receiver does not require access checks and is not observed.
-  // The generic stub does not perform map checks or handle observed objects.
+  // Check that the receiver does not require access checks.
+  // The generic stub does not perform map checks.
   __ lbu(a4, FieldMemOperand(receiver_map, Map::kBitFieldOffset));
-  __ And(a4, a4,
-         Operand(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved));
+  __ And(a4, a4, Operand(1 << Map::kIsAccessCheckNeeded));
   __ Branch(&slow, ne, a4, Operand(zero_reg));
   // Check if the object is a JS array or not.
   __ lbu(a4, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset));
@@ -667,10 +666,10 @@
   __ LoadRoot(vector, Heap::kDummyVectorRootIndex);
   __ li(slot, Operand(Smi::FromInt(slot_index)));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags,
-                                               receiver, key, a5, a6, a7, t0);
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
+  masm->isolate()->stub_cache()->GenerateProbe(
+      masm, Code::KEYED_STORE_IC, flags, receiver, key, a5, a6, a7, t0);
   // Cache miss.
   __ Branch(&miss);
 
@@ -732,25 +731,6 @@
   __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss);
 }
 
-
-void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
-  Register receiver = StoreDescriptor::ReceiverRegister();
-  Register name = StoreDescriptor::NameRegister();
-  DCHECK(receiver.is(a1));
-  DCHECK(name.is(a2));
-  DCHECK(StoreDescriptor::ValueRegister().is(a0));
-
-  // Get the receiver from the stack and probe the stub cache.
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags,
-                                               receiver, name, a3, a4, a5, a6);
-
-  // Cache miss: Jump to runtime.
-  GenerateMiss(masm);
-}
-
-
 void StoreIC::GenerateMiss(MacroAssembler* masm) {
   StoreIC_PushArgs(masm);
 
@@ -842,8 +822,9 @@
   }
 
   if (FLAG_trace_ic) {
-    PrintF("[  patching ic at %p, andi=%p, delta=%d\n", address,
-           andi_instruction_address, delta);
+    PrintF("[  patching ic at %p, andi=%p, delta=%d\n",
+           static_cast<void*>(address),
+           static_cast<void*>(andi_instruction_address), delta);
   }
 
   Address patch_address =
diff --git a/src/ic/mips64/stub-cache-mips64.cc b/src/ic/mips64/stub-cache-mips64.cc
index 0bd7dd0..d000c52 100644
--- a/src/ic/mips64/stub-cache-mips64.cc
+++ b/src/ic/mips64/stub-cache-mips64.cc
@@ -14,10 +14,9 @@
 
 #define __ ACCESS_MASM(masm)
 
-
 static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
-                       Code::Kind ic_kind, Code::Flags flags,
-                       StubCache::Table table, Register receiver, Register name,
+                       Code::Flags flags, StubCache::Table table,
+                       Register receiver, Register name,
                        // Number of the cache entry, not scaled.
                        Register offset, Register scratch, Register scratch2,
                        Register offset_scratch) {
@@ -100,9 +99,6 @@
   // DCHECK(sizeof(Entry) == 12);
   // DCHECK(sizeof(Entry) == 3 * kPointerSize);
 
-  // Make sure the flags does not name a specific type.
-  DCHECK(Code::ExtractTypeFromFlags(flags) == 0);
-
   // Make sure that there are no register conflicts.
   DCHECK(!AreAliased(receiver, name, scratch, extra, extra2, extra3));
 
@@ -148,8 +144,8 @@
   __ And(scratch, scratch, Operand(mask));
 
   // Probe the primary table.
-  ProbeTable(isolate, masm, ic_kind, flags, kPrimary, receiver, name, scratch,
-             extra, extra2, extra3);
+  ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch, extra,
+             extra2, extra3);
 
   // Primary miss: Compute hash for secondary probe.
   __ dsrl(at, name, kCacheIndexShift);
@@ -159,8 +155,8 @@
   __ And(scratch, scratch, Operand(mask2));
 
   // Probe the secondary table.
-  ProbeTable(isolate, masm, ic_kind, flags, kSecondary, receiver, name, scratch,
-             extra, extra2, extra3);
+  ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch, extra,
+             extra2, extra3);
 
   // Cache miss: Fall-through and let caller handle the miss by
   // entering the runtime system.
diff --git a/src/ic/ppc/OWNERS b/src/ic/ppc/OWNERS
index eb007cb..752e8e3 100644
--- a/src/ic/ppc/OWNERS
+++ b/src/ic/ppc/OWNERS
@@ -3,3 +3,4 @@
 joransiu@ca.ibm.com
 mbrandy@us.ibm.com
 michael_dawson@ca.ibm.com
+bjaideep@ca.ibm.com
diff --git a/src/ic/ppc/access-compiler-ppc.cc b/src/ic/ppc/access-compiler-ppc.cc
index b1e06e1..6143b4c 100644
--- a/src/ic/ppc/access-compiler-ppc.cc
+++ b/src/ic/ppc/access-compiler-ppc.cc
@@ -19,19 +19,19 @@
 
 
 Register* PropertyAccessCompiler::load_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3, scratch4.
+  // receiver, name, scratch1, scratch2, scratch3.
   Register receiver = LoadDescriptor::ReceiverRegister();
   Register name = LoadDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, r6, r3, r7, r8};
+  static Register registers[] = {receiver, name, r6, r3, r7};
   return registers;
 }
 
 
 Register* PropertyAccessCompiler::store_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3.
+  // receiver, name, scratch1, scratch2.
   Register receiver = StoreDescriptor::ReceiverRegister();
   Register name = StoreDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, r6, r7, r8};
+  static Register registers[] = {receiver, name, r6, r7};
   return registers;
 }
 
diff --git a/src/ic/ppc/handler-compiler-ppc.cc b/src/ic/ppc/handler-compiler-ppc.cc
index 832c25a..3293d82 100644
--- a/src/ic/ppc/handler-compiler-ppc.cc
+++ b/src/ic/ppc/handler-compiler-ppc.cc
@@ -199,8 +199,9 @@
     MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name,
     Register scratch, Label* miss) {
   Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name);
-  DCHECK(cell->value()->IsTheHole());
-  Handle<WeakCell> weak_cell = masm->isolate()->factory()->NewWeakCell(cell);
+  Isolate* isolate = masm->isolate();
+  DCHECK(cell->value()->IsTheHole(isolate));
+  Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
   __ LoadWeakValue(scratch, weak_cell, miss);
   __ LoadP(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset));
   __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
@@ -285,7 +286,7 @@
   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
   bool call_data_undefined = false;
   // Put call data in place.
-  if (api_call_info->data()->IsUndefined()) {
+  if (api_call_info->data()->IsUndefined(isolate)) {
     call_data_undefined = true;
     __ LoadRoot(data, Heap::kUndefinedValueRootIndex);
   } else {
@@ -432,28 +433,25 @@
   DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
          !scratch2.is(scratch1));
 
-  if (FLAG_eliminate_prototype_chain_checks) {
-    Handle<Cell> validity_cell =
-        Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
-    if (!validity_cell.is_null()) {
-      DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
-                validity_cell->value());
-      __ mov(scratch1, Operand(validity_cell));
-      __ LoadP(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
-      __ CmpSmiLiteral(scratch1, Smi::FromInt(Map::kPrototypeChainValid), r0);
-      __ bne(miss);
-    }
+  Handle<Cell> validity_cell =
+      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
+  if (!validity_cell.is_null()) {
+    DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
+    __ mov(scratch1, Operand(validity_cell));
+    __ LoadP(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
+    __ CmpSmiLiteral(scratch1, Smi::FromInt(Map::kPrototypeChainValid), r0);
+    __ bne(miss);
+  }
 
-    // The prototype chain of primitives (and their JSValue wrappers) depends
-    // on the native context, which can't be guarded by validity cells.
-    // |object_reg| holds the native context specific prototype in this case;
-    // we need to check its map.
-    if (check == CHECK_ALL_MAPS) {
-      __ LoadP(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
-      Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
-      __ CmpWeakValue(scratch1, cell, scratch2);
-      __ b(ne, miss);
-    }
+  // The prototype chain of primitives (and their JSValue wrappers) depends
+  // on the native context, which can't be guarded by validity cells.
+  // |object_reg| holds the native context specific prototype in this case;
+  // we need to check its map.
+  if (check == CHECK_ALL_MAPS) {
+    __ LoadP(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
+    Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
+    __ CmpWeakValue(scratch1, cell, scratch2);
+    __ b(ne, miss);
   }
 
   // Keep track of the current object in register reg.
@@ -488,8 +486,10 @@
            !current_map->is_access_check_needed());
 
     prototype = handle(JSObject::cast(current_map->prototype()));
-    if (current_map->is_dictionary_map() &&
-        !current_map->IsJSGlobalObjectMap()) {
+    if (current_map->IsJSGlobalObjectMap()) {
+      GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
+                                name, scratch2, miss);
+    } else if (current_map->is_dictionary_map()) {
       DCHECK(!current_map->IsJSGlobalProxyMap());  // Proxy maps are fast.
       if (!name->IsUniqueName()) {
         DCHECK(name->IsString());
@@ -499,33 +499,12 @@
              current->property_dictionary()->FindEntry(name) ==
                  NameDictionary::kNotFound);
 
-      if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
+      if (depth > 1) {
         // TODO(jkummerow): Cache and re-use weak cell.
         __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
       }
       GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
                                        scratch2);
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ LoadP(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
-        __ LoadP(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
-      }
-    } else {
-      Register map_reg = scratch1;
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ LoadP(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
-      }
-      if (current_map->IsJSGlobalObjectMap()) {
-        GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
-                                  name, scratch2, miss);
-      } else if (!FLAG_eliminate_prototype_chain_checks &&
-                 (depth != 1 || check == CHECK_ALL_MAPS)) {
-        Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-        __ CmpWeakValue(map_reg, cell, scratch2);
-        __ bne(miss);
-      }
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ LoadP(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset));
-      }
     }
 
     reg = holder_reg;  // From now on the object will be in holder_reg.
@@ -539,17 +518,8 @@
   // Log the check depth.
   LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
 
-  if (!FLAG_eliminate_prototype_chain_checks &&
-      (depth != 0 || check == CHECK_ALL_MAPS)) {
-    // Check the holder map.
-    __ LoadP(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
-    Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-    __ CmpWeakValue(scratch1, cell, scratch2);
-    __ bne(miss);
-  }
-
   bool return_holder = return_what == RETURN_HOLDER;
-  if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
+  if (return_holder && depth != 0) {
     __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
   }
 
@@ -592,60 +562,10 @@
 }
 
 
-void NamedLoadHandlerCompiler::GenerateLoadCallback(
-    Register reg, Handle<AccessorInfo> callback) {
-  DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), receiver()));
-  DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), reg));
-
-  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
-  // name below the exit frame to make GC aware of them.
-  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
-  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
-  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
-  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
-  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
-  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
-
-  __ push(receiver());
-  // Push data from AccessorInfo.
-  Handle<Object> data(callback->data(), isolate());
-  if (data->IsUndefined() || data->IsSmi()) {
-    __ Move(scratch2(), data);
-  } else {
-    Handle<WeakCell> cell =
-        isolate()->factory()->NewWeakCell(Handle<HeapObject>::cast(data));
-    // The callback is alive if this instruction is executed,
-    // so the weak cell is not cleared and points to data.
-    __ GetWeakValue(scratch2(), cell);
-  }
-  __ push(scratch2());
-  __ LoadRoot(scratch2(), Heap::kUndefinedValueRootIndex);
-  __ Push(scratch2(), scratch2());
-  __ mov(scratch2(), Operand(ExternalReference::isolate_address(isolate())));
-  // should_throw_on_error -> false
-  __ mov(scratch3(), Operand(Smi::FromInt(0)));
-  __ Push(scratch2(), reg, scratch3(), name());
-
-  // Abi for CallApiGetter
-  Register getter_address_reg = ApiGetterDescriptor::function_address();
-
-  Address getter_address = v8::ToCData<Address>(callback->getter());
-  ApiFunction fun(getter_address);
-  ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
-  ExternalReference ref = ExternalReference(&fun, type, isolate());
-  __ mov(getter_address_reg, Operand(ref));
-
-  CallApiGetterStub stub(isolate());
-  __ TailCallStub(&stub);
-}
-
-
 void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
     LookupIterator* it, Register holder_reg) {
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
 
   // Compile the interceptor call, followed by inline code to load the
   // property from further up the prototype chain if the call fails.
@@ -705,7 +625,7 @@
 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
   // Call the runtime system to load the interceptor.
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
   PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
                            holder());
 
@@ -722,7 +642,7 @@
 
   // If the callback cannot leak, then push the callback directly,
   // otherwise wrap it in a weak cell.
-  if (callback->data()->IsUndefined() || callback->data()->IsSmi()) {
+  if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) {
     __ mov(ip, Operand(callback));
   } else {
     Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback);
@@ -737,7 +657,7 @@
   __ TailCallRuntime(Runtime::kStoreCallbackProperty);
 
   // Return the generated code.
-  return GetCode(kind(), Code::FAST, name);
+  return GetCode(kind(), name);
 }
 
 
@@ -777,7 +697,7 @@
   FrontendFooter(name, &miss);
 
   // Return the generated code.
-  return GetCode(kind(), Code::NORMAL, name);
+  return GetCode(kind(), name);
 }
 
 
diff --git a/src/ic/ppc/ic-ppc.cc b/src/ic/ppc/ic-ppc.cc
index 567296c..1f0236d 100644
--- a/src/ic/ppc/ic-ppc.cc
+++ b/src/ic/ppc/ic-ppc.cc
@@ -425,8 +425,8 @@
   __ LoadRoot(vector, Heap::kDummyVectorRootIndex);
   __ LoadSmiLiteral(slot, Smi::FromInt(slot_index));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::KEYED_LOAD_IC, flags,
                                                receiver, key, r7, r8, r9, r10);
   // Cache miss.
@@ -639,11 +639,10 @@
   __ JumpIfSmi(receiver, &slow);
   // Get the map of the object.
   __ LoadP(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
-  // Check that the receiver does not require access checks and is not observed.
-  // The generic stub does not perform map checks or handle observed objects.
+  // Check that the receiver does not require access checks.
+  // The generic stub does not perform map checks.
   __ lbz(ip, FieldMemOperand(receiver_map, Map::kBitFieldOffset));
-  __ andi(r0, ip,
-          Operand(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved));
+  __ andi(r0, ip, Operand(1 << Map::kIsAccessCheckNeeded));
   __ bne(&slow, cr0);
   // Check if the object is a JS array or not.
   __ lbz(r7, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset));
@@ -686,10 +685,10 @@
   __ LoadRoot(vector, Heap::kDummyVectorRootIndex);
   __ LoadSmiLiteral(slot, Smi::FromInt(slot_index));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags,
-                                               receiver, key, r8, r9, r10, r11);
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
+  masm->isolate()->stub_cache()->GenerateProbe(
+      masm, Code::KEYED_STORE_IC, flags, receiver, key, r8, r9, r10, r11);
   // Cache miss.
   __ b(&miss);
 
@@ -738,26 +737,6 @@
   GenerateMiss(masm);
 }
 
-
-void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
-  Register receiver = StoreDescriptor::ReceiverRegister();
-  Register name = StoreDescriptor::NameRegister();
-  DCHECK(receiver.is(r4));
-  DCHECK(name.is(r5));
-  DCHECK(StoreDescriptor::ValueRegister().is(r3));
-
-  // Get the receiver from the stack and probe the stub cache.
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
-
-  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags,
-                                               receiver, name, r6, r7, r8, r9);
-
-  // Cache miss: Jump to runtime.
-  GenerateMiss(masm);
-}
-
-
 void StoreIC::GenerateMiss(MacroAssembler* masm) {
   StoreIC_PushArgs(masm);
 
@@ -852,8 +831,9 @@
   }
 
   if (FLAG_trace_ic) {
-    PrintF("[  patching ic at %p, cmp=%p, delta=%d\n", address,
-           cmp_instruction_address, delta);
+    PrintF("[  patching ic at %p, cmp=%p, delta=%d\n",
+           static_cast<void*>(address),
+           static_cast<void*>(cmp_instruction_address), delta);
   }
 
   Address patch_address =
diff --git a/src/ic/ppc/stub-cache-ppc.cc b/src/ic/ppc/stub-cache-ppc.cc
index 6030b2c..45a620c 100644
--- a/src/ic/ppc/stub-cache-ppc.cc
+++ b/src/ic/ppc/stub-cache-ppc.cc
@@ -14,10 +14,9 @@
 
 #define __ ACCESS_MASM(masm)
 
-
 static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
-                       Code::Kind ic_kind, Code::Flags flags,
-                       StubCache::Table table, Register receiver, Register name,
+                       Code::Flags flags, StubCache::Table table,
+                       Register receiver, Register name,
                        // Number of the cache entry, not scaled.
                        Register offset, Register scratch, Register scratch2,
                        Register offset_scratch) {
@@ -120,9 +119,6 @@
   DCHECK(sizeof(Entry) == 12);
 #endif
 
-  // Make sure the flags does not name a specific type.
-  DCHECK(Code::ExtractTypeFromFlags(flags) == 0);
-
   // Make sure that there are no register conflicts.
   DCHECK(!AreAliased(receiver, name, scratch, extra, extra2, extra3));
 
@@ -166,8 +162,8 @@
           Operand((kPrimaryTableSize - 1) << kCacheIndexShift));
 
   // Probe the primary table.
-  ProbeTable(isolate, masm, ic_kind, flags, kPrimary, receiver, name, scratch,
-             extra, extra2, extra3);
+  ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch, extra,
+             extra2, extra3);
 
   // Primary miss: Compute hash for secondary probe.
   __ sub(scratch, scratch, name);
@@ -176,8 +172,8 @@
           Operand((kSecondaryTableSize - 1) << kCacheIndexShift));
 
   // Probe the secondary table.
-  ProbeTable(isolate, masm, ic_kind, flags, kSecondary, receiver, name, scratch,
-             extra, extra2, extra3);
+  ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch, extra,
+             extra2, extra3);
 
   // Cache miss: Fall-through and let caller handle the miss by
   // entering the runtime system.
diff --git a/src/ic/s390/OWNERS b/src/ic/s390/OWNERS
index eb007cb..752e8e3 100644
--- a/src/ic/s390/OWNERS
+++ b/src/ic/s390/OWNERS
@@ -3,3 +3,4 @@
 joransiu@ca.ibm.com
 mbrandy@us.ibm.com
 michael_dawson@ca.ibm.com
+bjaideep@ca.ibm.com
diff --git a/src/ic/s390/access-compiler-s390.cc b/src/ic/s390/access-compiler-s390.cc
index 316be71..0a3285d 100644
--- a/src/ic/s390/access-compiler-s390.cc
+++ b/src/ic/s390/access-compiler-s390.cc
@@ -19,18 +19,18 @@
 }
 
 Register* PropertyAccessCompiler::load_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3, scratch4.
+  // receiver, name, scratch1, scratch2, scratch3.
   Register receiver = LoadDescriptor::ReceiverRegister();
   Register name = LoadDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, r5, r2, r6, r7};
+  static Register registers[] = {receiver, name, r5, r2, r6};
   return registers;
 }
 
 Register* PropertyAccessCompiler::store_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3.
+  // receiver, name, scratch1, scratch2.
   Register receiver = StoreDescriptor::ReceiverRegister();
   Register name = StoreDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, r5, r6, r7};
+  static Register registers[] = {receiver, name, r5, r6};
   return registers;
 }
 
diff --git a/src/ic/s390/handler-compiler-s390.cc b/src/ic/s390/handler-compiler-s390.cc
index 1b39782..b643a84 100644
--- a/src/ic/s390/handler-compiler-s390.cc
+++ b/src/ic/s390/handler-compiler-s390.cc
@@ -188,8 +188,9 @@
     MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name,
     Register scratch, Label* miss) {
   Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name);
-  DCHECK(cell->value()->IsTheHole());
-  Handle<WeakCell> weak_cell = masm->isolate()->factory()->NewWeakCell(cell);
+  Isolate* isolate = masm->isolate();
+  DCHECK(cell->value()->IsTheHole(isolate));
+  Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
   __ LoadWeakValue(scratch, weak_cell, miss);
   __ LoadP(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset));
   __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex);
@@ -270,7 +271,7 @@
   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
   bool call_data_undefined = false;
   // Put call data in place.
-  if (api_call_info->data()->IsUndefined()) {
+  if (api_call_info->data()->IsUndefined(isolate)) {
     call_data_undefined = true;
     __ LoadRoot(data, Heap::kUndefinedValueRootIndex);
   } else {
@@ -406,28 +407,25 @@
   DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
          !scratch2.is(scratch1));
 
-  if (FLAG_eliminate_prototype_chain_checks) {
-    Handle<Cell> validity_cell =
-        Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
-    if (!validity_cell.is_null()) {
-      DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
-                validity_cell->value());
-      __ mov(scratch1, Operand(validity_cell));
-      __ LoadP(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
-      __ CmpSmiLiteral(scratch1, Smi::FromInt(Map::kPrototypeChainValid), r0);
-      __ bne(miss);
-    }
+  Handle<Cell> validity_cell =
+      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
+  if (!validity_cell.is_null()) {
+    DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
+    __ mov(scratch1, Operand(validity_cell));
+    __ LoadP(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
+    __ CmpSmiLiteral(scratch1, Smi::FromInt(Map::kPrototypeChainValid), r0);
+    __ bne(miss);
+  }
 
-    // The prototype chain of primitives (and their JSValue wrappers) depends
-    // on the native context, which can't be guarded by validity cells.
-    // |object_reg| holds the native context specific prototype in this case;
-    // we need to check its map.
-    if (check == CHECK_ALL_MAPS) {
-      __ LoadP(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
-      Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
-      __ CmpWeakValue(scratch1, cell, scratch2);
-      __ b(ne, miss);
-    }
+  // The prototype chain of primitives (and their JSValue wrappers) depends
+  // on the native context, which can't be guarded by validity cells.
+  // |object_reg| holds the native context specific prototype in this case;
+  // we need to check its map.
+  if (check == CHECK_ALL_MAPS) {
+    __ LoadP(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset));
+    Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
+    __ CmpWeakValue(scratch1, cell, scratch2);
+    __ b(ne, miss);
   }
 
   // Keep track of the current object in register reg.
@@ -462,8 +460,10 @@
            !current_map->is_access_check_needed());
 
     prototype = handle(JSObject::cast(current_map->prototype()));
-    if (current_map->is_dictionary_map() &&
-        !current_map->IsJSGlobalObjectMap()) {
+    if (current_map->IsJSGlobalObjectMap()) {
+      GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
+                                name, scratch2, miss);
+    } else if (current_map->is_dictionary_map()) {
       DCHECK(!current_map->IsJSGlobalProxyMap());  // Proxy maps are fast.
       if (!name->IsUniqueName()) {
         DCHECK(name->IsString());
@@ -473,33 +473,12 @@
              current->property_dictionary()->FindEntry(name) ==
                  NameDictionary::kNotFound);
 
-      if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
+      if (depth > 1) {
         // TODO(jkummerow): Cache and re-use weak cell.
         __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
       }
       GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
                                        scratch2);
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ LoadP(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
-        __ LoadP(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
-      }
-    } else {
-      Register map_reg = scratch1;
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ LoadP(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
-      }
-      if (current_map->IsJSGlobalObjectMap()) {
-        GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
-                                  name, scratch2, miss);
-      } else if (!FLAG_eliminate_prototype_chain_checks &&
-                 (depth != 1 || check == CHECK_ALL_MAPS)) {
-        Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-        __ CmpWeakValue(map_reg, cell, scratch2);
-        __ bne(miss);
-      }
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ LoadP(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset));
-      }
     }
 
     reg = holder_reg;  // From now on the object will be in holder_reg.
@@ -513,17 +492,8 @@
   // Log the check depth.
   LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
 
-  if (!FLAG_eliminate_prototype_chain_checks &&
-      (depth != 0 || check == CHECK_ALL_MAPS)) {
-    // Check the holder map.
-    __ LoadP(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
-    Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-    __ CmpWeakValue(scratch1, cell, scratch2);
-    __ bne(miss);
-  }
-
   bool return_holder = return_what == RETURN_HOLDER;
-  if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
+  if (return_holder && depth != 0) {
     __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
   }
 
@@ -562,59 +532,10 @@
   __ Ret();
 }
 
-void NamedLoadHandlerCompiler::GenerateLoadCallback(
-    Register reg, Handle<AccessorInfo> callback) {
-  DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), receiver()));
-  DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), reg));
-
-  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
-  // name below the exit frame to make GC aware of them.
-  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
-  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
-  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
-  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
-  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
-  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
-
-  __ Push(receiver());
-  // Push data from AccessorInfo.
-  Handle<Object> data(callback->data(), isolate());
-  if (data->IsUndefined() || data->IsSmi()) {
-    __ Move(scratch2(), data);
-  } else {
-    Handle<WeakCell> cell =
-        isolate()->factory()->NewWeakCell(Handle<HeapObject>::cast(data));
-    // The callback is alive if this instruction is executed,
-    // so the weak cell is not cleared and points to data.
-    __ GetWeakValue(scratch2(), cell);
-  }
-  __ push(scratch2());
-  __ LoadRoot(scratch2(), Heap::kUndefinedValueRootIndex);
-  __ Push(scratch2(), scratch2());
-  __ mov(scratch2(), Operand(ExternalReference::isolate_address(isolate())));
-  // should_throw_on_error -> false
-  __ mov(scratch3(), Operand(Smi::FromInt(0)));
-  __ Push(scratch2(), reg, scratch3(), name());
-
-  // Abi for CallApiGetter
-  Register getter_address_reg = ApiGetterDescriptor::function_address();
-
-  Address getter_address = v8::ToCData<Address>(callback->getter());
-  ApiFunction fun(getter_address);
-  ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
-  ExternalReference ref = ExternalReference(&fun, type, isolate());
-  __ mov(getter_address_reg, Operand(ref));
-
-  CallApiGetterStub stub(isolate());
-  __ TailCallStub(&stub);
-}
-
 void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
     LookupIterator* it, Register holder_reg) {
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
 
   // Compile the interceptor call, followed by inline code to load the
   // property from further up the prototype chain if the call fails.
@@ -672,7 +593,7 @@
 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
   // Call the runtime system to load the interceptor.
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
   PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
                            holder());
 
@@ -688,7 +609,7 @@
 
   // If the callback cannot leak, then push the callback directly,
   // otherwise wrap it in a weak cell.
-  if (callback->data()->IsUndefined() || callback->data()->IsSmi()) {
+  if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) {
     __ mov(ip, Operand(callback));
   } else {
     Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback);
@@ -703,7 +624,7 @@
   __ TailCallRuntime(Runtime::kStoreCallbackProperty);
 
   // Return the generated code.
-  return GetCode(kind(), Code::FAST, name);
+  return GetCode(kind(), name);
 }
 
 Register NamedStoreHandlerCompiler::value() {
@@ -740,7 +661,7 @@
   FrontendFooter(name, &miss);
 
   // Return the generated code.
-  return GetCode(kind(), Code::NORMAL, name);
+  return GetCode(kind(), name);
 }
 
 #undef __
diff --git a/src/ic/s390/ic-s390.cc b/src/ic/s390/ic-s390.cc
index d4f2886..64adc9f 100644
--- a/src/ic/s390/ic-s390.cc
+++ b/src/ic/s390/ic-s390.cc
@@ -412,8 +412,8 @@
   __ LoadRoot(vector, Heap::kDummyVectorRootIndex);
   __ LoadSmiLiteral(slot, Smi::FromInt(slot_index));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::KEYED_LOAD_IC, flags,
                                                receiver, key, r6, r7, r8, r9);
   // Cache miss.
@@ -625,11 +625,10 @@
   __ JumpIfSmi(receiver, &slow);
   // Get the map of the object.
   __ LoadP(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
-  // Check that the receiver does not require access checks and is not observed.
-  // The generic stub does not perform map checks or handle observed objects.
+  // Check that the receiver does not require access checks.
+  // The generic stub does not perform map checks.
   __ LoadlB(ip, FieldMemOperand(receiver_map, Map::kBitFieldOffset));
-  __ AndP(r0, ip,
-          Operand(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved));
+  __ AndP(r0, ip, Operand(1 << Map::kIsAccessCheckNeeded));
   __ bne(&slow, Label::kNear);
   // Check if the object is a JS array or not.
   __ LoadlB(r6, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset));
@@ -671,10 +670,10 @@
   __ LoadRoot(vector, Heap::kDummyVectorRootIndex);
   __ LoadSmiLiteral(slot, Smi::FromInt(slot_index));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags,
-                                               receiver, key, r7, r8, r9, ip);
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
+  masm->isolate()->stub_cache()->GenerateProbe(
+      masm, Code::KEYED_STORE_IC, flags, receiver, key, r7, r8, r9, ip);
   // Cache miss.
   __ b(&miss);
 
@@ -720,24 +719,6 @@
   GenerateMiss(masm);
 }
 
-void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
-  Register receiver = StoreDescriptor::ReceiverRegister();
-  Register name = StoreDescriptor::NameRegister();
-  DCHECK(receiver.is(r3));
-  DCHECK(name.is(r4));
-  DCHECK(StoreDescriptor::ValueRegister().is(r2));
-
-  // Get the receiver from the stack and probe the stub cache.
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
-
-  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags,
-                                               receiver, name, r5, r6, r7, r8);
-
-  // Cache miss: Jump to runtime.
-  GenerateMiss(masm);
-}
-
 void StoreIC::GenerateMiss(MacroAssembler* masm) {
   StoreIC_PushArgs(masm);
 
@@ -829,8 +810,9 @@
   }
 
   if (FLAG_trace_ic) {
-    PrintF("[  patching ic at %p, cmp=%p, delta=%d\n", address,
-           cmp_instruction_address, delta);
+    PrintF("[  patching ic at %p, cmp=%p, delta=%d\n",
+           static_cast<void*>(address),
+           static_cast<void*>(cmp_instruction_address), delta);
   }
 
   // Expected sequence to enable by changing the following
diff --git a/src/ic/s390/stub-cache-s390.cc b/src/ic/s390/stub-cache-s390.cc
index 054b946..cd50e56 100644
--- a/src/ic/s390/stub-cache-s390.cc
+++ b/src/ic/s390/stub-cache-s390.cc
@@ -15,8 +15,8 @@
 #define __ ACCESS_MASM(masm)
 
 static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
-                       Code::Kind ic_kind, Code::Flags flags,
-                       StubCache::Table table, Register receiver, Register name,
+                       Code::Flags flags, StubCache::Table table,
+                       Register receiver, Register name,
                        // Number of the cache entry, not scaled.
                        Register offset, Register scratch, Register scratch2,
                        Register offset_scratch) {
@@ -114,9 +114,6 @@
   DCHECK(sizeof(Entry) == 12);
 #endif
 
-  // Make sure the flags does not name a specific type.
-  DCHECK(Code::ExtractTypeFromFlags(flags) == 0);
-
   // Make sure that there are no register conflicts.
   DCHECK(!AreAliased(receiver, name, scratch, extra, extra2, extra3));
 
@@ -160,8 +157,8 @@
           Operand((kPrimaryTableSize - 1) << kCacheIndexShift));
 
   // Probe the primary table.
-  ProbeTable(isolate, masm, ic_kind, flags, kPrimary, receiver, name, scratch,
-             extra, extra2, extra3);
+  ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch, extra,
+             extra2, extra3);
 
   // Primary miss: Compute hash for secondary probe.
   __ SubP(scratch, scratch, name);
@@ -170,8 +167,8 @@
           Operand((kSecondaryTableSize - 1) << kCacheIndexShift));
 
   // Probe the secondary table.
-  ProbeTable(isolate, masm, ic_kind, flags, kSecondary, receiver, name, scratch,
-             extra, extra2, extra3);
+  ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch, extra,
+             extra2, extra3);
 
   // Cache miss: Fall-through and let caller handle the miss by
   // entering the runtime system.
diff --git a/src/ic/stub-cache.cc b/src/ic/stub-cache.cc
index 4a5f9bd..f51366f 100644
--- a/src/ic/stub-cache.cc
+++ b/src/ic/stub-cache.cc
@@ -23,7 +23,7 @@
 
 static Code::Flags CommonStubCacheChecks(Name* name, Map* map,
                                          Code::Flags flags) {
-  flags = Code::RemoveTypeAndHolderFromFlags(flags);
+  flags = Code::RemoveHolderFromFlags(flags);
 
   // Validate that the name does not move on scavenge, and that we
   // can use identity checks instead of structural equality checks.
@@ -34,10 +34,8 @@
   // cache only contains handlers. Make sure that the bits are the least
   // significant so they will be the ones masked out.
   DCHECK_EQ(Code::HANDLER, Code::ExtractKindFromFlags(flags));
-  STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1);
 
-  // Make sure that the code type and cache holder are not included in the hash.
-  DCHECK(Code::ExtractTypeFromFlags(flags) == 0);
+  // Make sure that the cache holder are not included in the hash.
   DCHECK(Code::ExtractCacheHolderFromFlags(flags) == 0);
 
   return flags;
@@ -56,8 +54,7 @@
   // secondary cache before overwriting it.
   if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) {
     Map* old_map = primary->map;
-    Code::Flags old_flags =
-        Code::RemoveTypeAndHolderFromFlags(old_code->flags());
+    Code::Flags old_flags = Code::RemoveHolderFromFlags(old_code->flags());
     int seed = PrimaryOffset(primary->key, old_flags, old_map);
     int secondary_offset = SecondaryOffset(primary->key, old_flags, seed);
     Entry* secondary = entry(secondary_, secondary_offset);
@@ -77,12 +74,14 @@
   flags = CommonStubCacheChecks(name, map, flags);
   int primary_offset = PrimaryOffset(name, flags, map);
   Entry* primary = entry(primary_, primary_offset);
-  if (primary->key == name && primary->map == map) {
+  if (primary->key == name && primary->map == map &&
+      flags == Code::RemoveHolderFromFlags(primary->value->flags())) {
     return primary->value;
   }
   int secondary_offset = SecondaryOffset(name, flags, primary_offset);
   Entry* secondary = entry(secondary_, secondary_offset);
-  if (secondary->key == name && secondary->map == map) {
+  if (secondary->key == name && secondary->map == map &&
+      flags == Code::RemoveHolderFromFlags(secondary->value->flags())) {
     return secondary->value;
   }
   return NULL;
diff --git a/src/ic/stub-cache.h b/src/ic/stub-cache.h
index 4b27e6e..03afcdc 100644
--- a/src/ic/stub-cache.h
+++ b/src/ic/stub-cache.h
@@ -92,9 +92,24 @@
   // automatically discards the hash bit field.
   static const int kCacheIndexShift = Name::kHashShift;
 
- private:
+  static const int kPrimaryTableBits = 11;
+  static const int kPrimaryTableSize = (1 << kPrimaryTableBits);
+  static const int kSecondaryTableBits = 9;
+  static const int kSecondaryTableSize = (1 << kSecondaryTableBits);
+
+  static int PrimaryOffsetForTesting(Name* name, Code::Flags flags, Map* map) {
+    return PrimaryOffset(name, flags, map);
+  }
+
+  static int SecondaryOffsetForTesting(Name* name, Code::Flags flags,
+                                       int seed) {
+    return SecondaryOffset(name, flags, seed);
+  }
+
+  // The constructor is made public only for the purposes of testing.
   explicit StubCache(Isolate* isolate);
 
+ private:
   // The stub cache has a primary and secondary level.  The two levels have
   // different hashing algorithms in order to avoid simultaneous collisions
   // in both caches.  Unlike a probing strategy (quadratic or otherwise) the
@@ -150,11 +165,6 @@
                                     offset * multiplier);
   }
 
-  static const int kPrimaryTableBits = 11;
-  static const int kPrimaryTableSize = (1 << kPrimaryTableBits);
-  static const int kSecondaryTableBits = 9;
-  static const int kSecondaryTableSize = (1 << kSecondaryTableBits);
-
  private:
   Entry primary_[kPrimaryTableSize];
   Entry secondary_[kSecondaryTableSize];
diff --git a/src/ic/x64/access-compiler-x64.cc b/src/ic/x64/access-compiler-x64.cc
index b8d50b3..2b29252 100644
--- a/src/ic/x64/access-compiler-x64.cc
+++ b/src/ic/x64/access-compiler-x64.cc
@@ -19,19 +19,19 @@
 
 
 Register* PropertyAccessCompiler::load_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3, scratch4.
+  // receiver, name, scratch1, scratch2, scratch3.
   Register receiver = LoadDescriptor::ReceiverRegister();
   Register name = LoadDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, rax, rbx, rdi, r8};
+  static Register registers[] = {receiver, name, rax, rbx, rdi};
   return registers;
 }
 
 
 Register* PropertyAccessCompiler::store_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3.
+  // receiver, name, scratch1, scratch2.
   Register receiver = StoreDescriptor::ReceiverRegister();
   Register name = StoreDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, rbx, rdi, r8};
+  static Register registers[] = {receiver, name, rbx, rdi};
   return registers;
 }
 
diff --git a/src/ic/x64/handler-compiler-x64.cc b/src/ic/x64/handler-compiler-x64.cc
index dde6169..5c64288 100644
--- a/src/ic/x64/handler-compiler-x64.cc
+++ b/src/ic/x64/handler-compiler-x64.cc
@@ -180,7 +180,7 @@
   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
   bool call_data_undefined = false;
   // Put call data in place.
-  if (api_call_info->data()->IsUndefined()) {
+  if (api_call_info->data()->IsUndefined(isolate)) {
     call_data_undefined = true;
     __ LoadRoot(data, Heap::kUndefinedValueRootIndex);
   } else {
@@ -220,12 +220,12 @@
     MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name,
     Register scratch, Label* miss) {
   Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name);
-  DCHECK(cell->value()->IsTheHole());
-  Factory* factory = masm->isolate()->factory();
-  Handle<WeakCell> weak_cell = factory->NewWeakCell(cell);
+  Isolate* isolate = masm->isolate();
+  DCHECK(cell->value()->IsTheHole(isolate));
+  Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
   __ LoadWeakValue(scratch, weak_cell, miss);
   __ Cmp(FieldOperand(scratch, PropertyCell::kValueOffset),
-         factory->the_hole_value());
+         isolate->factory()->the_hole_value());
   __ j(not_equal, miss);
 }
 
@@ -440,29 +440,26 @@
   DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
          !scratch2.is(scratch1));
 
-  if (FLAG_eliminate_prototype_chain_checks) {
-    Handle<Cell> validity_cell =
-        Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
-    if (!validity_cell.is_null()) {
-      DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
-                validity_cell->value());
-      __ Move(scratch1, validity_cell, RelocInfo::CELL);
-      // Move(..., CELL) loads the payload's address!
-      __ SmiCompare(Operand(scratch1, 0),
-                    Smi::FromInt(Map::kPrototypeChainValid));
-      __ j(not_equal, miss);
-    }
+  Handle<Cell> validity_cell =
+      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
+  if (!validity_cell.is_null()) {
+    DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
+    __ Move(scratch1, validity_cell, RelocInfo::CELL);
+    // Move(..., CELL) loads the payload's address!
+    __ SmiCompare(Operand(scratch1, 0),
+                  Smi::FromInt(Map::kPrototypeChainValid));
+    __ j(not_equal, miss);
+  }
 
-    // The prototype chain of primitives (and their JSValue wrappers) depends
-    // on the native context, which can't be guarded by validity cells.
-    // |object_reg| holds the native context specific prototype in this case;
-    // we need to check its map.
-    if (check == CHECK_ALL_MAPS) {
-      __ movp(scratch1, FieldOperand(object_reg, HeapObject::kMapOffset));
-      Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
-      __ CmpWeakValue(scratch1, cell, scratch2);
-      __ j(not_equal, miss);
-    }
+  // The prototype chain of primitives (and their JSValue wrappers) depends
+  // on the native context, which can't be guarded by validity cells.
+  // |object_reg| holds the native context specific prototype in this case;
+  // we need to check its map.
+  if (check == CHECK_ALL_MAPS) {
+    __ movp(scratch1, FieldOperand(object_reg, HeapObject::kMapOffset));
+    Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
+    __ CmpWeakValue(scratch1, cell, scratch2);
+    __ j(not_equal, miss);
   }
 
   // Keep track of the current object in register reg.  On the first
@@ -500,8 +497,10 @@
            !current_map->is_access_check_needed());
 
     prototype = handle(JSObject::cast(current_map->prototype()));
-    if (current_map->is_dictionary_map() &&
-        !current_map->IsJSGlobalObjectMap()) {
+    if (current_map->IsJSGlobalObjectMap()) {
+      GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
+                                name, scratch2, miss);
+    } else if (current_map->is_dictionary_map()) {
       DCHECK(!current_map->IsJSGlobalProxyMap());  // Proxy maps are fast.
       if (!name->IsUniqueName()) {
         DCHECK(name->IsString());
@@ -511,34 +510,12 @@
              current->property_dictionary()->FindEntry(name) ==
                  NameDictionary::kNotFound);
 
-      if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
+      if (depth > 1) {
         // TODO(jkummerow): Cache and re-use weak cell.
         __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
       }
       GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
                                        scratch2);
-
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ movp(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
-        __ movp(holder_reg, FieldOperand(scratch1, Map::kPrototypeOffset));
-      }
-    } else {
-      Register map_reg = scratch1;
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ movp(map_reg, FieldOperand(reg, HeapObject::kMapOffset));
-      }
-      if (current_map->IsJSGlobalObjectMap()) {
-        GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
-                                  name, scratch2, miss);
-      } else if (!FLAG_eliminate_prototype_chain_checks &&
-                 (depth != 1 || check == CHECK_ALL_MAPS)) {
-        Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-        __ CmpWeakValue(map_reg, cell, scratch2);
-        __ j(not_equal, miss);
-      }
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ movp(holder_reg, FieldOperand(map_reg, Map::kPrototypeOffset));
-      }
     }
 
     reg = holder_reg;  // From now on the object will be in holder_reg.
@@ -552,17 +529,8 @@
   // Log the check depth.
   LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
 
-  if (!FLAG_eliminate_prototype_chain_checks &&
-      (depth != 0 || check == CHECK_ALL_MAPS)) {
-    // Check the holder map.
-    __ movp(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
-    Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-    __ CmpWeakValue(scratch1, cell, scratch2);
-    __ j(not_equal, miss);
-  }
-
   bool return_holder = return_what == RETURN_HOLDER;
-  if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
+  if (return_holder && depth != 0) {
     __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
   }
 
@@ -597,58 +565,6 @@
   }
 }
 
-
-void NamedLoadHandlerCompiler::GenerateLoadCallback(
-    Register reg, Handle<AccessorInfo> callback) {
-  DCHECK(!AreAliased(kScratchRegister, scratch2(), scratch3(), receiver()));
-  DCHECK(!AreAliased(kScratchRegister, scratch2(), scratch3(), reg));
-
-  // Insert additional parameters into the stack frame above return address.
-  __ PopReturnAddressTo(scratch3());
-
-  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
-  // name below the exit frame to make GC aware of them.
-  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
-  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
-  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
-  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
-  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
-  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
-
-  __ Push(receiver());  // receiver
-  Handle<Object> data(callback->data(), isolate());
-  if (data->IsUndefined() || data->IsSmi()) {
-    __ Push(data);
-  } else {
-    Handle<WeakCell> cell =
-        isolate()->factory()->NewWeakCell(Handle<HeapObject>::cast(data));
-    // The callback is alive if this instruction is executed,
-    // so the weak cell is not cleared and points to data.
-    __ GetWeakValue(scratch2(), cell);
-    __ Push(scratch2());
-  }
-  __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
-  __ Push(kScratchRegister);  // return value
-  __ Push(kScratchRegister);  // return value default
-  __ PushAddress(ExternalReference::isolate_address(isolate()));
-  __ Push(reg);     // holder
-  __ Push(Smi::FromInt(0));  // should_throw_on_error -> false
-
-  __ Push(name());  // name
-  __ PushReturnAddressFrom(scratch3());
-
-  // Abi for CallApiGetter
-  Register api_function_address = ApiGetterDescriptor::function_address();
-  Address getter_address = v8::ToCData<Address>(callback->getter());
-  __ Move(api_function_address, getter_address, RelocInfo::EXTERNAL_REFERENCE);
-
-  CallApiGetterStub stub(isolate());
-  __ TailCallStub(&stub);
-}
-
-
 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
   // Return the constant value.
   __ Move(rax, value);
@@ -659,7 +575,7 @@
 void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
     LookupIterator* it, Register holder_reg) {
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
 
   // Compile the interceptor call, followed by inline code to load the
   // property from further up the prototype chain if the call fails.
@@ -721,7 +637,7 @@
 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
   // Call the runtime system to load the interceptor.
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
   __ PopReturnAddressTo(scratch2());
   PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
                            holder());
@@ -741,7 +657,7 @@
   __ Push(holder_reg);
   // If the callback cannot leak, then push the callback directly,
   // otherwise wrap it in a weak cell.
-  if (callback->data()->IsUndefined() || callback->data()->IsSmi()) {
+  if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) {
     __ Push(callback);
   } else {
     Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback);
@@ -756,7 +672,7 @@
   __ TailCallRuntime(Runtime::kStoreCallbackProperty);
 
   // Return the generated code.
-  return GetCode(kind(), Code::FAST, name);
+  return GetCode(kind(), name);
 }
 
 
@@ -798,7 +714,7 @@
   FrontendFooter(name, &miss);
 
   // Return the generated code.
-  return GetCode(kind(), Code::NORMAL, name);
+  return GetCode(kind(), name);
 }
 
 
diff --git a/src/ic/x64/ic-x64.cc b/src/ic/x64/ic-x64.cc
index 247116d..da74582 100644
--- a/src/ic/x64/ic-x64.cc
+++ b/src/ic/x64/ic-x64.cc
@@ -340,8 +340,8 @@
   __ Move(vector, dummy_vector);
   __ Move(slot, Smi::FromInt(slot_index));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::KEYED_LOAD_IC, flags,
                                                receiver, key,
                                                megamorphic_scratch, no_reg);
@@ -451,7 +451,7 @@
   __ JumpIfDictionaryInPrototypeChain(receiver, rdi, kScratchRegister, slow);
 
   __ bind(&fast_double_without_map_check);
-  __ StoreNumberToDoubleElements(value, rbx, key, xmm0,
+  __ StoreNumberToDoubleElements(value, rbx, key, kScratchDoubleReg,
                                  &transition_double_elements);
   if (increment_length == kIncrementLength) {
     // Add 1 to receiver->length.
@@ -519,10 +519,10 @@
   __ JumpIfSmi(receiver, &slow_with_tagged_index);
   // Get the map from the receiver.
   __ movp(r9, FieldOperand(receiver, HeapObject::kMapOffset));
-  // Check that the receiver does not require access checks and is not observed.
-  // The generic stub does not perform map checks or handle observed objects.
+  // Check that the receiver does not require access checks.
+  // The generic stub does not perform map checks.
   __ testb(FieldOperand(r9, Map::kBitFieldOffset),
-           Immediate(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved));
+           Immediate(1 << Map::kIsAccessCheckNeeded));
   __ j(not_zero, &slow_with_tagged_index);
   // Check that the key is a smi.
   __ JumpIfNotSmi(key, &maybe_name_key);
@@ -567,10 +567,10 @@
   __ Move(vector, dummy_vector);
   __ Move(slot, Smi::FromInt(slot_index));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags,
-                                               receiver, key, r9, no_reg);
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
+  masm->isolate()->stub_cache()->GenerateProbe(
+      masm, Code::KEYED_STORE_IC, flags, receiver, key, r9, no_reg);
   // Cache miss.
   __ jmp(&miss);
 
@@ -710,13 +710,6 @@
   __ TailCallRuntime(Runtime::kKeyedGetProperty);
 }
 
-
-void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
-  // This shouldn't be called.
-  __ int3();
-}
-
-
 static void StoreIC_PushArgs(MacroAssembler* masm) {
   Register receiver = StoreDescriptor::ReceiverRegister();
   Register name = StoreDescriptor::NameRegister();
@@ -829,8 +822,9 @@
   // condition code uses at the patched jump.
   uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address);
   if (FLAG_trace_ic) {
-    PrintF("[  patching ic at %p, test=%p, delta=%d\n", address,
-           test_instruction_address, delta);
+    PrintF("[  patching ic at %p, test=%p, delta=%d\n",
+           static_cast<void*>(address),
+           static_cast<void*>(test_instruction_address), delta);
   }
 
   // Patch with a short conditional jump. Enabling means switching from a short
diff --git a/src/ic/x64/stub-cache-x64.cc b/src/ic/x64/stub-cache-x64.cc
index 9a9dfe9..fa0a0b3 100644
--- a/src/ic/x64/stub-cache-x64.cc
+++ b/src/ic/x64/stub-cache-x64.cc
@@ -14,10 +14,9 @@
 
 #define __ ACCESS_MASM(masm)
 
-
 static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
-                       Code::Kind ic_kind, Code::Flags flags,
-                       StubCache::Table table, Register receiver, Register name,
+                       Code::Flags flags, StubCache::Table table,
+                       Register receiver, Register name,
                        // The offset is scaled by 4, based on
                        // kCacheIndexShift, which is two bits
                        Register offset) {
@@ -93,9 +92,6 @@
   // entry size being 3 * kPointerSize.
   DCHECK(sizeof(Entry) == 3 * kPointerSize);
 
-  // Make sure the flags do not name a specific type.
-  DCHECK(Code::ExtractTypeFromFlags(flags) == 0);
-
   // Make sure that there are no register conflicts.
   DCHECK(!scratch.is(receiver));
   DCHECK(!scratch.is(name));
@@ -110,7 +106,8 @@
   // the vector and slot registers, which need to be preserved for a handler
   // call or miss.
   if (IC::ICUseVector(ic_kind)) {
-    if (ic_kind == Code::LOAD_IC || ic_kind == Code::KEYED_LOAD_IC) {
+    if (ic_kind == Code::LOAD_IC || ic_kind == Code::LOAD_GLOBAL_IC ||
+        ic_kind == Code::KEYED_LOAD_IC) {
       Register vector = LoadWithVectorDescriptor::VectorRegister();
       Register slot = LoadDescriptor::SlotRegister();
       DCHECK(!AreAliased(vector, slot, scratch));
@@ -139,7 +136,7 @@
   __ andp(scratch, Immediate((kPrimaryTableSize - 1) << kCacheIndexShift));
 
   // Probe the primary table.
-  ProbeTable(isolate, masm, ic_kind, flags, kPrimary, receiver, name, scratch);
+  ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch);
 
   // Primary miss: Compute hash for secondary probe.
   __ movl(scratch, FieldOperand(name, Name::kHashFieldOffset));
@@ -151,8 +148,7 @@
   __ andp(scratch, Immediate((kSecondaryTableSize - 1) << kCacheIndexShift));
 
   // Probe the secondary table.
-  ProbeTable(isolate, masm, ic_kind, flags, kSecondary, receiver, name,
-             scratch);
+  ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch);
 
   // Cache miss: Fall-through and let caller handle the miss by
   // entering the runtime system.
diff --git a/src/ic/x87/access-compiler-x87.cc b/src/ic/x87/access-compiler-x87.cc
index 2c1b942..e528de6 100644
--- a/src/ic/x87/access-compiler-x87.cc
+++ b/src/ic/x87/access-compiler-x87.cc
@@ -18,19 +18,19 @@
 
 
 Register* PropertyAccessCompiler::load_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3, scratch4.
+  // receiver, name, scratch1, scratch2, scratch3.
   Register receiver = LoadDescriptor::ReceiverRegister();
   Register name = LoadDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, ebx, eax, edi, no_reg};
+  static Register registers[] = {receiver, name, ebx, eax, edi};
   return registers;
 }
 
 
 Register* PropertyAccessCompiler::store_calling_convention() {
-  // receiver, name, scratch1, scratch2, scratch3.
+  // receiver, name, scratch1, scratch2.
   Register receiver = StoreDescriptor::ReceiverRegister();
   Register name = StoreDescriptor::NameRegister();
-  static Register registers[] = {receiver, name, ebx, edi, no_reg};
+  static Register registers[] = {receiver, name, ebx, edi};
   return registers;
 }
 
diff --git a/src/ic/x87/handler-compiler-x87.cc b/src/ic/x87/handler-compiler-x87.cc
index 281faba..c5f2d9f 100644
--- a/src/ic/x87/handler-compiler-x87.cc
+++ b/src/ic/x87/handler-compiler-x87.cc
@@ -199,7 +199,7 @@
   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
   bool call_data_undefined = false;
   // Put call data in place.
-  if (api_call_info->data()->IsUndefined()) {
+  if (api_call_info->data()->IsUndefined(isolate)) {
     call_data_undefined = true;
     __ mov(data, Immediate(isolate->factory()->undefined_value()));
   } else {
@@ -237,12 +237,12 @@
     MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name,
     Register scratch, Label* miss) {
   Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name);
-  DCHECK(cell->value()->IsTheHole());
-  Factory* factory = masm->isolate()->factory();
-  Handle<WeakCell> weak_cell = factory->NewWeakCell(cell);
+  Isolate* isolate = masm->isolate();
+  DCHECK(cell->value()->IsTheHole(isolate));
+  Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
   __ LoadWeakValue(scratch, weak_cell, miss);
   __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset),
-         Immediate(factory->the_hole_value()));
+         Immediate(isolate->factory()->the_hole_value()));
   __ j(not_equal, miss);
 }
 
@@ -439,28 +439,25 @@
   DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
          !scratch2.is(scratch1));
 
-  if (FLAG_eliminate_prototype_chain_checks) {
-    Handle<Cell> validity_cell =
-        Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
-    if (!validity_cell.is_null()) {
-      DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid),
-                validity_cell->value());
-      // Operand::ForCell(...) points to the cell's payload!
-      __ cmp(Operand::ForCell(validity_cell),
-             Immediate(Smi::FromInt(Map::kPrototypeChainValid)));
-      __ j(not_equal, miss);
-    }
+  Handle<Cell> validity_cell =
+      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
+  if (!validity_cell.is_null()) {
+    DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
+    // Operand::ForCell(...) points to the cell's payload!
+    __ cmp(Operand::ForCell(validity_cell),
+           Immediate(Smi::FromInt(Map::kPrototypeChainValid)));
+    __ j(not_equal, miss);
+  }
 
-    // The prototype chain of primitives (and their JSValue wrappers) depends
-    // on the native context, which can't be guarded by validity cells.
-    // |object_reg| holds the native context specific prototype in this case;
-    // we need to check its map.
-    if (check == CHECK_ALL_MAPS) {
-      __ mov(scratch1, FieldOperand(object_reg, HeapObject::kMapOffset));
-      Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
-      __ CmpWeakValue(scratch1, cell, scratch2);
-      __ j(not_equal, miss);
-    }
+  // The prototype chain of primitives (and their JSValue wrappers) depends
+  // on the native context, which can't be guarded by validity cells.
+  // |object_reg| holds the native context specific prototype in this case;
+  // we need to check its map.
+  if (check == CHECK_ALL_MAPS) {
+    __ mov(scratch1, FieldOperand(object_reg, HeapObject::kMapOffset));
+    Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
+    __ CmpWeakValue(scratch1, cell, scratch2);
+    __ j(not_equal, miss);
   }
 
   // Keep track of the current object in register reg.
@@ -496,8 +493,10 @@
            !current_map->is_access_check_needed());
 
     prototype = handle(JSObject::cast(current_map->prototype()));
-    if (current_map->is_dictionary_map() &&
-        !current_map->IsJSGlobalObjectMap()) {
+    if (current_map->IsJSGlobalObjectMap()) {
+      GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
+                                name, scratch2, miss);
+    } else if (current_map->is_dictionary_map()) {
       DCHECK(!current_map->IsJSGlobalProxyMap());  // Proxy maps are fast.
       if (!name->IsUniqueName()) {
         DCHECK(name->IsString());
@@ -507,34 +506,12 @@
              current->property_dictionary()->FindEntry(name) ==
                  NameDictionary::kNotFound);
 
-      if (FLAG_eliminate_prototype_chain_checks && depth > 1) {
+      if (depth > 1) {
         // TODO(jkummerow): Cache and re-use weak cell.
         __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
       }
       GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
                                        scratch2);
-
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
-        __ mov(holder_reg, FieldOperand(scratch1, Map::kPrototypeOffset));
-      }
-    } else {
-      Register map_reg = scratch1;
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ mov(map_reg, FieldOperand(reg, HeapObject::kMapOffset));
-      }
-      if (current_map->IsJSGlobalObjectMap()) {
-        GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
-                                  name, scratch2, miss);
-      } else if (!FLAG_eliminate_prototype_chain_checks &&
-                 (depth != 1 || check == CHECK_ALL_MAPS)) {
-        Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-        __ CmpWeakValue(map_reg, cell, scratch2);
-        __ j(not_equal, miss);
-      }
-      if (!FLAG_eliminate_prototype_chain_checks) {
-        __ mov(holder_reg, FieldOperand(map_reg, Map::kPrototypeOffset));
-      }
     }
 
     reg = holder_reg;  // From now on the object will be in holder_reg.
@@ -548,17 +525,8 @@
   // Log the check depth.
   LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
 
-  if (!FLAG_eliminate_prototype_chain_checks &&
-      (depth != 0 || check == CHECK_ALL_MAPS)) {
-    // Check the holder map.
-    __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
-    Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-    __ CmpWeakValue(scratch1, cell, scratch2);
-    __ j(not_equal, miss);
-  }
-
   bool return_holder = return_what == RETURN_HOLDER;
-  if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) {
+  if (return_holder && depth != 0) {
     __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss);
   }
 
@@ -594,58 +562,6 @@
 }
 
 
-void NamedLoadHandlerCompiler::GenerateLoadCallback(
-    Register reg, Handle<AccessorInfo> callback) {
-  DCHECK(!AreAliased(scratch2(), scratch3(), receiver()));
-  DCHECK(!AreAliased(scratch2(), scratch3(), reg));
-
-  // Insert additional parameters into the stack frame above return address.
-  __ pop(scratch3());  // Get return address to place it below.
-
-  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
-  // name below the exit frame to make GC aware of them.
-  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
-  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
-  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
-  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
-  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
-  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
-  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
-
-  __ push(receiver());  // receiver
-  // Push data from AccessorInfo.
-  Handle<Object> data(callback->data(), isolate());
-  if (data->IsUndefined() || data->IsSmi()) {
-    __ push(Immediate(data));
-  } else {
-    Handle<WeakCell> cell =
-        isolate()->factory()->NewWeakCell(Handle<HeapObject>::cast(data));
-    // The callback is alive if this instruction is executed,
-    // so the weak cell is not cleared and points to data.
-    __ GetWeakValue(scratch2(), cell);
-    __ push(scratch2());
-  }
-  __ push(Immediate(isolate()->factory()->undefined_value()));  // ReturnValue
-  // ReturnValue default value
-  __ push(Immediate(isolate()->factory()->undefined_value()));
-  __ push(Immediate(reinterpret_cast<int>(isolate())));
-  __ push(reg);  // holder
-  __ push(Immediate(Smi::FromInt(0)));  // should_throw_on_error -> false
-
-  __ push(name());  // name
-  __ push(scratch3());  // Restore return address.
-
-  // Abi for CallApiGetter
-  Register getter_address = ApiGetterDescriptor::function_address();
-  Address function_address = v8::ToCData<Address>(callback->getter());
-  __ mov(getter_address, Immediate(function_address));
-
-  CallApiGetterStub stub(isolate());
-  __ TailCallStub(&stub);
-}
-
-
 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
   // Return the constant value.
   __ LoadObject(eax, value);
@@ -656,7 +572,7 @@
 void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
     LookupIterator* it, Register holder_reg) {
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
 
   // Compile the interceptor call, followed by inline code to load the
   // property from further up the prototype chain if the call fails.
@@ -723,7 +639,7 @@
 
 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
   DCHECK(holder()->HasNamedInterceptor());
-  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined());
+  DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
   // Call the runtime system to load the interceptor.
   __ pop(scratch2());  // save old return address
   PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(),
@@ -744,7 +660,7 @@
   __ push(holder_reg);
   // If the callback cannot leak, then push the callback directly,
   // otherwise wrap it in a weak cell.
-  if (callback->data()->IsUndefined() || callback->data()->IsSmi()) {
+  if (callback->data()->IsUndefined(isolate()) || callback->data()->IsSmi()) {
     __ Push(callback);
   } else {
     Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback);
@@ -759,7 +675,7 @@
   __ TailCallRuntime(Runtime::kStoreCallbackProperty);
 
   // Return the generated code.
-  return GetCode(kind(), Code::FAST, name);
+  return GetCode(kind(), name);
 }
 
 
@@ -801,7 +717,7 @@
   FrontendFooter(name, &miss);
 
   // Return the generated code.
-  return GetCode(kind(), Code::NORMAL, name);
+  return GetCode(kind(), name);
 }
 
 
diff --git a/src/ic/x87/ic-x87.cc b/src/ic/x87/ic-x87.cc
index b51045b..9db5591 100644
--- a/src/ic/x87/ic-x87.cc
+++ b/src/ic/x87/ic-x87.cc
@@ -336,8 +336,8 @@
   __ push(Immediate(Smi::FromInt(slot)));
   __ push(Immediate(dummy_vector));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::KEYED_LOAD_IC, flags,
                                                receiver, key, ebx, edi);
 
@@ -519,10 +519,10 @@
   __ JumpIfSmi(receiver, &slow);
   // Get the map from the receiver.
   __ mov(edi, FieldOperand(receiver, HeapObject::kMapOffset));
-  // Check that the receiver does not require access checks and is not observed.
-  // The generic stub does not perform map checks or handle observed objects.
+  // Check that the receiver does not require access checks.
+  // The generic stub does not perform map checks.
   __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
-            Immediate(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved));
+            Immediate(1 << Map::kIsAccessCheckNeeded));
   __ j(not_zero, &slow);
   // Check that the key is a smi.
   __ JumpIfNotSmi(key, &maybe_name_key);
@@ -563,10 +563,10 @@
   __ push(Immediate(Smi::FromInt(slot)));
   __ push(Immediate(dummy_vector));
 
-  Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
-  masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags,
-                                               receiver, key, edi, no_reg);
+  Code::Flags flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
+  masm->isolate()->stub_cache()->GenerateProbe(
+      masm, Code::KEYED_STORE_IC, flags, receiver, key, edi, no_reg);
 
   __ pop(VectorStoreICDescriptor::VectorRegister());
   __ pop(VectorStoreICDescriptor::SlotRegister());
@@ -708,15 +708,6 @@
   __ TailCallRuntime(Runtime::kKeyedGetProperty);
 }
 
-
-void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
-  // This shouldn't be called.
-  // TODO(mvstanton): remove this method.
-  __ int3();
-  return;
-}
-
-
 static void StoreIC_PushArgs(MacroAssembler* masm) {
   Register receiver = StoreDescriptor::ReceiverRegister();
   Register name = StoreDescriptor::NameRegister();
@@ -836,8 +827,9 @@
   // condition code uses at the patched jump.
   uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address);
   if (FLAG_trace_ic) {
-    PrintF("[  patching ic at %p, test=%p, delta=%d\n", address,
-           test_instruction_address, delta);
+    PrintF("[  patching ic at %p, test=%p, delta=%d\n",
+           static_cast<void*>(address),
+           static_cast<void*>(test_instruction_address), delta);
   }
 
   // Patch with a short conditional jump. Enabling means switching from a short
diff --git a/src/ic/x87/stub-cache-x87.cc b/src/ic/x87/stub-cache-x87.cc
index dfc0ef6..b238e5f 100644
--- a/src/ic/x87/stub-cache-x87.cc
+++ b/src/ic/x87/stub-cache-x87.cc
@@ -153,9 +153,6 @@
   // being 12.
   DCHECK(sizeof(Entry) == 12);
 
-  // Assert the flags do not name a specific type.
-  DCHECK(Code::ExtractTypeFromFlags(flags) == 0);
-
   // Assert that there are no register conflicts.
   DCHECK(!scratch.is(receiver));
   DCHECK(!scratch.is(name));
diff --git a/src/icu_util.cc b/src/icu_util.cc
index 0225130..a6f0453 100644
--- a/src/icu_util.cc
+++ b/src/icu_util.cc
@@ -15,6 +15,8 @@
 #include "unicode/putil.h"
 #include "unicode/udata.h"
 
+#include "src/base/file-utils.h"
+
 #define ICU_UTIL_DATA_FILE   0
 #define ICU_UTIL_DATA_SHARED 1
 #define ICU_UTIL_DATA_STATIC 2
@@ -38,6 +40,26 @@
 }  // namespace
 #endif
 
+bool InitializeICUDefaultLocation(const char* exec_path,
+                                  const char* icu_data_file) {
+#if !defined(V8_I18N_SUPPORT)
+  return true;
+#else
+#if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
+  if (icu_data_file) {
+    return InitializeICU(icu_data_file);
+  }
+  char* icu_data_file_default;
+  RelativePath(&icu_data_file_default, exec_path, "icudtl.dat");
+  bool result = InitializeICU(icu_data_file_default);
+  free(icu_data_file_default);
+  return result;
+#else
+  return InitializeICU(NULL);
+#endif
+#endif
+}
+
 bool InitializeICU(const char* icu_data_file) {
 #if !defined(V8_I18N_SUPPORT)
   return true;
diff --git a/src/icu_util.h b/src/icu_util.h
index c308dec..c5ef862 100644
--- a/src/icu_util.h
+++ b/src/icu_util.h
@@ -14,6 +14,11 @@
 // function should be called before ICU is used.
 bool InitializeICU(const char* icu_data_file);
 
+// Like above, but using the default icudtl.dat location if icu_data_file is
+// not specified.
+bool InitializeICUDefaultLocation(const char* exec_path,
+                                  const char* icu_data_file);
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/interface-descriptors.cc b/src/interface-descriptors.cc
index 9ee4269..50638f9 100644
--- a/src/interface-descriptors.cc
+++ b/src/interface-descriptors.cc
@@ -43,9 +43,8 @@
   return function;
 }
 
-
 void CallInterfaceDescriptorData::InitializePlatformSpecific(
-    int register_parameter_count, Register* registers,
+    int register_parameter_count, const Register* registers,
     PlatformInterfaceDescriptor* platform_descriptor) {
   platform_specific_descriptor_ = platform_descriptor;
   register_param_count_ = register_parameter_count;
@@ -75,12 +74,6 @@
 }
 
 
-void AllocateMutableHeapNumberDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  data->InitializePlatformSpecific(0, nullptr, nullptr);
-}
-
-
 void VoidDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   data->InitializePlatformSpecific(0, nullptr);
@@ -104,6 +97,38 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
+FunctionType* LoadGlobalDescriptor::BuildCallInterfaceDescriptorFunctionType(
+    Isolate* isolate, int paramater_count) {
+  Zone* zone = isolate->interface_descriptor_zone();
+  FunctionType* function =
+      Type::Function(AnyTagged(zone), Type::Undefined(), 1, zone)->AsFunction();
+  function->InitParameter(0, SmiType(zone));
+  return function;
+}
+
+void LoadGlobalDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {LoadWithVectorDescriptor::SlotRegister()};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+FunctionType*
+LoadGlobalWithVectorDescriptor::BuildCallInterfaceDescriptorFunctionType(
+    Isolate* isolate, int paramater_count) {
+  Zone* zone = isolate->interface_descriptor_zone();
+  FunctionType* function =
+      Type::Function(AnyTagged(zone), Type::Undefined(), 2, zone)->AsFunction();
+  function->InitParameter(0, SmiType(zone));
+  function->InitParameter(1, AnyTagged(zone));
+  return function;
+}
+
+void LoadGlobalWithVectorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {LoadWithVectorDescriptor::SlotRegister(),
+                          LoadWithVectorDescriptor::VectorRegister()};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
 
 void StoreDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
@@ -149,23 +174,6 @@
 }
 
 FunctionType*
-LoadGlobalViaContextDescriptor::BuildCallInterfaceDescriptorFunctionType(
-    Isolate* isolate, int paramater_count) {
-  Zone* zone = isolate->interface_descriptor_zone();
-  FunctionType* function =
-      Type::Function(AnyTagged(zone), Type::Undefined(), 1, zone)->AsFunction();
-  function->InitParameter(0, UntaggedIntegral32(zone));
-  return function;
-}
-
-
-void LoadGlobalViaContextDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  Register registers[] = {SlotRegister()};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-FunctionType*
 StoreGlobalViaContextDescriptor::BuildCallInterfaceDescriptorFunctionType(
     Isolate* isolate, int paramater_count) {
   Zone* zone = isolate->interface_descriptor_zone();
@@ -184,13 +192,6 @@
 }
 
 
-void InstanceOfDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  Register registers[] = {LeftRegister(), RightRegister()};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
 void StringCompareDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {LeftRegister(), RightRegister()};
@@ -203,14 +204,12 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
-
 void MathPowTaggedDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {exponent()};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
-
 void MathPowIntegerDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {exponent()};
@@ -301,28 +300,64 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
-FunctionType* ApiGetterDescriptor::BuildCallInterfaceDescriptorFunctionType(
-    Isolate* isolate, int paramater_count) {
-  Zone* zone = isolate->interface_descriptor_zone();
-  FunctionType* function =
-      Type::Function(AnyTagged(zone), Type::Undefined(), 1, zone)->AsFunction();
-  function->InitParameter(0, ExternalPointer(zone));
-  return function;
+const Register ApiGetterDescriptor::ReceiverRegister() {
+  return LoadDescriptor::ReceiverRegister();
 }
 
-
 void ApiGetterDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
-  Register registers[] = {function_address()};
+  Register registers[] = {ReceiverRegister(), HolderRegister(),
+                          CallbackRegister()};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
-
 void ContextOnlyDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   data->InitializePlatformSpecific(0, nullptr);
 }
 
+CallInterfaceDescriptor OnStackArgsDescriptorBase::ForArgs(
+    Isolate* isolate, int parameter_count) {
+  switch (parameter_count) {
+    case 1:
+      return OnStackWith1ArgsDescriptor(isolate);
+    case 2:
+      return OnStackWith2ArgsDescriptor(isolate);
+    case 3:
+      return OnStackWith3ArgsDescriptor(isolate);
+    case 4:
+      return OnStackWith4ArgsDescriptor(isolate);
+    case 5:
+      return OnStackWith5ArgsDescriptor(isolate);
+    case 6:
+      return OnStackWith6ArgsDescriptor(isolate);
+    case 7:
+      return OnStackWith7ArgsDescriptor(isolate);
+    default:
+      UNREACHABLE();
+      return VoidDescriptor(isolate);
+  }
+}
+
+FunctionType*
+OnStackArgsDescriptorBase::BuildCallInterfaceDescriptorFunctionTypeWithArg(
+    Isolate* isolate, int register_parameter_count, int parameter_count) {
+  DCHECK_EQ(0, register_parameter_count);
+  DCHECK_GT(parameter_count, 0);
+  Zone* zone = isolate->interface_descriptor_zone();
+  FunctionType* function =
+      Type::Function(AnyTagged(zone), AnyTagged(zone), parameter_count, zone)
+          ->AsFunction();
+  for (int i = 0; i < parameter_count; i++) {
+    function->InitParameter(i, AnyTagged(zone));
+  }
+  return function;
+}
+
+void OnStackArgsDescriptorBase::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  data->InitializePlatformSpecific(0, nullptr);
+}
 
 void GrowArrayElementsDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
@@ -330,7 +365,8 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
-FunctionType* FastArrayPushDescriptor::BuildCallInterfaceDescriptorFunctionType(
+FunctionType*
+VarArgFunctionDescriptor::BuildCallInterfaceDescriptorFunctionType(
     Isolate* isolate, int paramater_count) {
   Zone* zone = isolate->interface_descriptor_zone();
   FunctionType* function =
@@ -446,25 +482,41 @@
 }
 
 FunctionType*
-ArrayConstructorDescriptor::BuildCallInterfaceDescriptorFunctionType(
+ArrayNoArgumentConstructorDescriptor::BuildCallInterfaceDescriptorFunctionType(
+    Isolate* isolate, int paramater_count) {
+  Zone* zone = isolate->interface_descriptor_zone();
+  FunctionType* function =
+      Type::Function(AnyTagged(zone), Type::Undefined(), 4, zone)->AsFunction();
+  function->InitParameter(0, Type::Receiver());  // JSFunction
+  function->InitParameter(1, AnyTagged(zone));
+  function->InitParameter(2, UntaggedIntegral32(zone));
+  function->InitParameter(3, AnyTagged(zone));
+  return function;
+}
+
+FunctionType* ArraySingleArgumentConstructorDescriptor::
+    BuildCallInterfaceDescriptorFunctionType(Isolate* isolate,
+                                             int paramater_count) {
+  Zone* zone = isolate->interface_descriptor_zone();
+  FunctionType* function =
+      Type::Function(AnyTagged(zone), Type::Undefined(), 5, zone)->AsFunction();
+  function->InitParameter(0, Type::Receiver());  // JSFunction
+  function->InitParameter(1, AnyTagged(zone));
+  function->InitParameter(2, UntaggedIntegral32(zone));
+  function->InitParameter(3, AnyTagged(zone));
+  function->InitParameter(4, AnyTagged(zone));
+  return function;
+}
+
+FunctionType*
+ArrayNArgumentsConstructorDescriptor::BuildCallInterfaceDescriptorFunctionType(
     Isolate* isolate, int paramater_count) {
   Zone* zone = isolate->interface_descriptor_zone();
   FunctionType* function =
       Type::Function(AnyTagged(zone), Type::Undefined(), 3, zone)->AsFunction();
   function->InitParameter(0, Type::Receiver());  // JSFunction
-  function->InitParameter(1, AnyTagged(zone));
-  function->InitParameter(2, UntaggedIntegral32(zone));
-  return function;
-}
-
-FunctionType*
-InternalArrayConstructorDescriptor::BuildCallInterfaceDescriptorFunctionType(
-    Isolate* isolate, int paramater_count) {
-  Zone* zone = isolate->interface_descriptor_zone();
-  FunctionType* function =
-      Type::Function(AnyTagged(zone), Type::Undefined(), 2, zone)->AsFunction();
-  function->InitParameter(0, Type::Receiver());  // JSFunction
-  function->InitParameter(1, UntaggedIntegral32(zone));
+  function->InitParameter(1, AnyTagged(zone));   // Allocation site or undefined
+  function->InitParameter(2, UntaggedIntegral32(zone));  //  Arg count
   return function;
 }
 
@@ -528,9 +580,8 @@
     Isolate* isolate, int parameter_count) {
   Zone* zone = isolate->interface_descriptor_zone();
   FunctionType* function =
-      Type::Function(AnyTagged(zone), Type::Undefined(), 5, zone)->AsFunction();
+      Type::Function(AnyTagged(zone), Type::Undefined(), 4, zone)->AsFunction();
   function->InitParameter(kAccumulatorParameter, AnyTagged(zone));
-  function->InitParameter(kRegisterFileParameter, ExternalPointer(zone));
   function->InitParameter(kBytecodeOffsetParameter, UntaggedIntegral32(zone));
   function->InitParameter(kBytecodeArrayParameter, AnyTagged(zone));
   function->InitParameter(kDispatchTableParameter, AnyTagged(zone));
diff --git a/src/interface-descriptors.h b/src/interface-descriptors.h
index dcce0af..18fc9a8 100644
--- a/src/interface-descriptors.h
+++ b/src/interface-descriptors.h
@@ -13,84 +13,91 @@
 
 class PlatformInterfaceDescriptor;
 
-#define INTERFACE_DESCRIPTOR_LIST(V)          \
-  V(Void)                                     \
-  V(Load)                                     \
-  V(Store)                                    \
-  V(StoreTransition)                          \
-  V(VectorStoreTransition)                    \
-  V(VectorStoreICTrampoline)                  \
-  V(VectorStoreIC)                            \
-  V(InstanceOf)                               \
-  V(LoadWithVector)                           \
-  V(FastArrayPush)                            \
-  V(FastNewClosure)                           \
-  V(FastNewContext)                           \
-  V(FastNewObject)                            \
-  V(FastNewRestParameter)                     \
-  V(FastNewSloppyArguments)                   \
-  V(FastNewStrictArguments)                   \
-  V(TypeConversion)                           \
-  V(Typeof)                                   \
-  V(FastCloneRegExp)                          \
-  V(FastCloneShallowArray)                    \
-  V(FastCloneShallowObject)                   \
-  V(CreateAllocationSite)                     \
-  V(CreateWeakCell)                           \
-  V(CallFunction)                             \
-  V(CallFunctionWithFeedback)                 \
-  V(CallFunctionWithFeedbackAndVector)        \
-  V(CallConstruct)                            \
-  V(CallTrampoline)                           \
-  V(ConstructStub)                            \
-  V(ConstructTrampoline)                      \
-  V(RegExpConstructResult)                    \
-  V(TransitionElementsKind)                   \
-  V(AllocateHeapNumber)                       \
-  V(AllocateMutableHeapNumber)                \
-  V(AllocateFloat32x4)                        \
-  V(AllocateInt32x4)                          \
-  V(AllocateUint32x4)                         \
-  V(AllocateBool32x4)                         \
-  V(AllocateInt16x8)                          \
-  V(AllocateUint16x8)                         \
-  V(AllocateBool16x8)                         \
-  V(AllocateInt8x16)                          \
-  V(AllocateUint8x16)                         \
-  V(AllocateBool8x16)                         \
-  V(AllocateInNewSpace)                       \
-  V(ArrayConstructorConstantArgCount)         \
-  V(ArrayConstructor)                         \
-  V(InternalArrayConstructorConstantArgCount) \
-  V(InternalArrayConstructor)                 \
-  V(Compare)                                  \
-  V(BinaryOp)                                 \
-  V(BinaryOpWithAllocationSite)               \
-  V(StringAdd)                                \
-  V(StringCompare)                            \
-  V(Keyed)                                    \
-  V(Named)                                    \
-  V(CallHandler)                              \
-  V(ArgumentAdaptor)                          \
-  V(ApiCallbackWith0Args)                     \
-  V(ApiCallbackWith1Args)                     \
-  V(ApiCallbackWith2Args)                     \
-  V(ApiCallbackWith3Args)                     \
-  V(ApiCallbackWith4Args)                     \
-  V(ApiCallbackWith5Args)                     \
-  V(ApiCallbackWith6Args)                     \
-  V(ApiCallbackWith7Args)                     \
-  V(ApiGetter)                                \
-  V(LoadGlobalViaContext)                     \
-  V(StoreGlobalViaContext)                    \
-  V(MathPowTagged)                            \
-  V(MathPowInteger)                           \
-  V(ContextOnly)                              \
-  V(GrowArrayElements)                        \
-  V(InterpreterDispatch)                      \
-  V(InterpreterPushArgsAndCall)               \
-  V(InterpreterPushArgsAndConstruct)          \
-  V(InterpreterCEntry)
+#define INTERFACE_DESCRIPTOR_LIST(V)   \
+  V(Void)                              \
+  V(ContextOnly)                       \
+  V(OnStackWith1Args)                  \
+  V(OnStackWith2Args)                  \
+  V(OnStackWith3Args)                  \
+  V(OnStackWith4Args)                  \
+  V(OnStackWith5Args)                  \
+  V(OnStackWith6Args)                  \
+  V(OnStackWith7Args)                  \
+  V(Load)                              \
+  V(LoadGlobal)                        \
+  V(LoadGlobalWithVector)              \
+  V(Store)                             \
+  V(StoreTransition)                   \
+  V(VectorStoreTransition)             \
+  V(VectorStoreICTrampoline)           \
+  V(VectorStoreIC)                     \
+  V(LoadWithVector)                    \
+  V(VarArgFunction)                    \
+  V(FastNewClosure)                    \
+  V(FastNewContext)                    \
+  V(FastNewObject)                     \
+  V(FastNewRestParameter)              \
+  V(FastNewSloppyArguments)            \
+  V(FastNewStrictArguments)            \
+  V(TypeConversion)                    \
+  V(Typeof)                            \
+  V(FastCloneRegExp)                   \
+  V(FastCloneShallowArray)             \
+  V(FastCloneShallowObject)            \
+  V(CreateAllocationSite)              \
+  V(CreateWeakCell)                    \
+  V(CallFunction)                      \
+  V(CallFunctionWithFeedback)          \
+  V(CallFunctionWithFeedbackAndVector) \
+  V(CallConstruct)                     \
+  V(CallTrampoline)                    \
+  V(ConstructStub)                     \
+  V(ConstructTrampoline)               \
+  V(RegExpConstructResult)             \
+  V(TransitionElementsKind)            \
+  V(AllocateHeapNumber)                \
+  V(AllocateFloat32x4)                 \
+  V(AllocateInt32x4)                   \
+  V(AllocateUint32x4)                  \
+  V(AllocateBool32x4)                  \
+  V(AllocateInt16x8)                   \
+  V(AllocateUint16x8)                  \
+  V(AllocateBool16x8)                  \
+  V(AllocateInt8x16)                   \
+  V(AllocateUint8x16)                  \
+  V(AllocateBool8x16)                  \
+  V(ArrayNoArgumentConstructor)        \
+  V(ArraySingleArgumentConstructor)    \
+  V(ArrayNArgumentsConstructor)        \
+  V(Compare)                           \
+  V(BinaryOp)                          \
+  V(BinaryOpWithAllocationSite)        \
+  V(CountOp)                           \
+  V(StringAdd)                         \
+  V(StringCompare)                     \
+  V(Keyed)                             \
+  V(Named)                             \
+  V(HasProperty)                       \
+  V(CallHandler)                       \
+  V(ArgumentAdaptor)                   \
+  V(ApiCallbackWith0Args)              \
+  V(ApiCallbackWith1Args)              \
+  V(ApiCallbackWith2Args)              \
+  V(ApiCallbackWith3Args)              \
+  V(ApiCallbackWith4Args)              \
+  V(ApiCallbackWith5Args)              \
+  V(ApiCallbackWith6Args)              \
+  V(ApiCallbackWith7Args)              \
+  V(ApiGetter)                         \
+  V(StoreGlobalViaContext)             \
+  V(MathPowTagged)                     \
+  V(MathPowInteger)                    \
+  V(GrowArrayElements)                 \
+  V(InterpreterDispatch)               \
+  V(InterpreterPushArgsAndCall)        \
+  V(InterpreterPushArgsAndConstruct)   \
+  V(InterpreterCEntry)                 \
+  V(ResumeGenerator)
 
 class CallInterfaceDescriptorData {
  public:
@@ -109,7 +116,7 @@
   // and register side by side (eg, RegRep(r1, Representation::Tagged()).
   // The same should go for the CodeStubDescriptor class.
   void InitializePlatformSpecific(
-      int register_parameter_count, Register* registers,
+      int register_parameter_count, const Register* registers,
       PlatformInterfaceDescriptor* platform_descriptor = NULL);
 
   bool IsInitialized() const { return register_param_count_ >= 0; }
@@ -218,6 +225,12 @@
     }
   }
 
+  // Initializes |data| using the platform dependent default set of registers.
+  // It is intended to be used for TurboFan stubs when particular set of
+  // registers does not matter.
+  static void DefaultInitializePlatformSpecific(
+      CallInterfaceDescriptorData* data, int register_parameter_count);
+
  private:
   const CallInterfaceDescriptorData* data_;
 };
@@ -229,6 +242,17 @@
   }                                                        \
   static inline CallDescriptors::Key key();
 
+#define DECLARE_DEFAULT_DESCRIPTOR(name, base, parameter_count)            \
+  DECLARE_DESCRIPTOR_WITH_BASE(name, base)                                 \
+ protected:                                                                \
+  void InitializePlatformSpecific(CallInterfaceDescriptorData* data)       \
+      override {                                                           \
+    DefaultInitializePlatformSpecific(data, parameter_count);              \
+  }                                                                        \
+  name(Isolate* isolate, CallDescriptors::Key key) : base(isolate, key) {} \
+                                                                           \
+ public:
+
 #define DECLARE_DESCRIPTOR(name, base)                                         \
   DECLARE_DESCRIPTOR_WITH_BASE(name, base)                                     \
  protected:                                                                    \
@@ -261,6 +285,77 @@
   DECLARE_DESCRIPTOR(VoidDescriptor, CallInterfaceDescriptor)
 };
 
+class ContextOnlyDescriptor : public CallInterfaceDescriptor {
+ public:
+  DECLARE_DESCRIPTOR(ContextOnlyDescriptor, CallInterfaceDescriptor)
+};
+
+// The OnStackWith*ArgsDescriptors have a lot of boilerplate. The superclass
+// OnStackArgsDescriptorBase is not meant to be instantiated directly and has no
+// public constructors to ensure this is so.contains all the logic, and the
+//
+// Use OnStackArgsDescriptorBase::ForArgs(isolate, parameter_count) to
+// instantiate a descriptor with the number of args.
+class OnStackArgsDescriptorBase : public CallInterfaceDescriptor {
+ public:
+  static CallInterfaceDescriptor ForArgs(Isolate* isolate, int parameter_count);
+
+ protected:
+  OnStackArgsDescriptorBase(Isolate* isolate, CallDescriptors::Key key)
+      : CallInterfaceDescriptor(isolate, key) {}
+  void InitializePlatformSpecific(CallInterfaceDescriptorData* data) override;
+  FunctionType* BuildCallInterfaceDescriptorFunctionTypeWithArg(
+      Isolate* isolate, int register_parameter_count, int parameter_count);
+};
+
+class OnStackWith1ArgsDescriptor : public OnStackArgsDescriptorBase {
+ public:
+  DECLARE_DESCRIPTOR_WITH_BASE_AND_FUNCTION_TYPE_ARG(OnStackWith1ArgsDescriptor,
+                                                     OnStackArgsDescriptorBase,
+                                                     1)
+};
+
+class OnStackWith2ArgsDescriptor : public OnStackArgsDescriptorBase {
+ public:
+  DECLARE_DESCRIPTOR_WITH_BASE_AND_FUNCTION_TYPE_ARG(OnStackWith2ArgsDescriptor,
+                                                     OnStackArgsDescriptorBase,
+                                                     2)
+};
+
+class OnStackWith3ArgsDescriptor : public OnStackArgsDescriptorBase {
+ public:
+  DECLARE_DESCRIPTOR_WITH_BASE_AND_FUNCTION_TYPE_ARG(OnStackWith3ArgsDescriptor,
+                                                     OnStackArgsDescriptorBase,
+                                                     3)
+};
+
+class OnStackWith4ArgsDescriptor : public OnStackArgsDescriptorBase {
+ public:
+  DECLARE_DESCRIPTOR_WITH_BASE_AND_FUNCTION_TYPE_ARG(OnStackWith4ArgsDescriptor,
+                                                     OnStackArgsDescriptorBase,
+                                                     4)
+};
+
+class OnStackWith5ArgsDescriptor : public OnStackArgsDescriptorBase {
+ public:
+  DECLARE_DESCRIPTOR_WITH_BASE_AND_FUNCTION_TYPE_ARG(OnStackWith5ArgsDescriptor,
+                                                     OnStackArgsDescriptorBase,
+                                                     5)
+};
+
+class OnStackWith6ArgsDescriptor : public OnStackArgsDescriptorBase {
+ public:
+  DECLARE_DESCRIPTOR_WITH_BASE_AND_FUNCTION_TYPE_ARG(OnStackWith6ArgsDescriptor,
+                                                     OnStackArgsDescriptorBase,
+                                                     6)
+};
+
+class OnStackWith7ArgsDescriptor : public OnStackArgsDescriptorBase {
+ public:
+  DECLARE_DESCRIPTOR_WITH_BASE_AND_FUNCTION_TYPE_ARG(OnStackWith7ArgsDescriptor,
+                                                     OnStackArgsDescriptorBase,
+                                                     7)
+};
 
 // LoadDescriptor is used by all stubs that implement Load/KeyedLoad ICs.
 class LoadDescriptor : public CallInterfaceDescriptor {
@@ -274,6 +369,17 @@
   static const Register SlotRegister();
 };
 
+class LoadGlobalDescriptor : public CallInterfaceDescriptor {
+ public:
+  DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadGlobalDescriptor,
+                                               CallInterfaceDescriptor)
+
+  enum ParameterIndices { kSlotIndex };
+
+  static const Register SlotRegister() {
+    return LoadDescriptor::SlotRegister();
+  }
+};
 
 class StoreDescriptor : public CallInterfaceDescriptor {
  public:
@@ -334,16 +440,6 @@
 };
 
 
-class InstanceOfDescriptor final : public CallInterfaceDescriptor {
- public:
-  DECLARE_DESCRIPTOR(InstanceOfDescriptor, CallInterfaceDescriptor)
-
-  enum ParameterIndices { kLeftIndex, kRightIndex, kParameterCount };
-  static const Register LeftRegister();
-  static const Register RightRegister();
-};
-
-
 class VectorStoreICTrampolineDescriptor : public StoreDescriptor {
  public:
   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
@@ -387,6 +483,17 @@
   static const Register VectorRegister();
 };
 
+class LoadGlobalWithVectorDescriptor : public LoadGlobalDescriptor {
+ public:
+  DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadGlobalWithVectorDescriptor,
+                                               LoadGlobalDescriptor)
+
+  enum ParameterIndices { kSlotIndex, kVectorIndex };
+
+  static const Register VectorRegister() {
+    return LoadWithVectorDescriptor::VectorRegister();
+  }
+};
 
 class FastNewClosureDescriptor : public CallInterfaceDescriptor {
  public:
@@ -430,6 +537,12 @@
   static const Register ArgumentRegister();
 };
 
+class HasPropertyDescriptor final : public CallInterfaceDescriptor {
+ public:
+  enum ParameterIndices { kKeyIndex, kObjectIndex };
+
+  DECLARE_DEFAULT_DESCRIPTOR(HasPropertyDescriptor, CallInterfaceDescriptor, 2)
+};
 
 class TypeofDescriptor : public CallInterfaceDescriptor {
  public:
@@ -532,15 +645,6 @@
 };
 
 
-class LoadGlobalViaContextDescriptor : public CallInterfaceDescriptor {
- public:
-  DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadGlobalViaContextDescriptor,
-                                               CallInterfaceDescriptor)
-
-  static const Register SlotRegister();
-};
-
-
 class StoreGlobalViaContextDescriptor : public CallInterfaceDescriptor {
  public:
   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(StoreGlobalViaContextDescriptor,
@@ -570,46 +674,44 @@
 SIMD128_TYPES(SIMD128_ALLOC_DESC)
 #undef SIMD128_ALLOC_DESC
 
-class AllocateMutableHeapNumberDescriptor : public CallInterfaceDescriptor {
- public:
-  DECLARE_DESCRIPTOR(AllocateMutableHeapNumberDescriptor,
-                     CallInterfaceDescriptor)
-};
-
-
-class AllocateInNewSpaceDescriptor : public CallInterfaceDescriptor {
- public:
-  DECLARE_DESCRIPTOR(AllocateInNewSpaceDescriptor, CallInterfaceDescriptor)
-};
-
-
-class ArrayConstructorConstantArgCountDescriptor
-    : public CallInterfaceDescriptor {
- public:
-  DECLARE_DESCRIPTOR(ArrayConstructorConstantArgCountDescriptor,
-                     CallInterfaceDescriptor)
-};
-
-
-class ArrayConstructorDescriptor : public CallInterfaceDescriptor {
- public:
-  DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ArrayConstructorDescriptor,
-                                               CallInterfaceDescriptor)
-};
-
-
-class InternalArrayConstructorConstantArgCountDescriptor
-    : public CallInterfaceDescriptor {
- public:
-  DECLARE_DESCRIPTOR(InternalArrayConstructorConstantArgCountDescriptor,
-                     CallInterfaceDescriptor)
-};
-
-
-class InternalArrayConstructorDescriptor : public CallInterfaceDescriptor {
+class ArrayNoArgumentConstructorDescriptor : public CallInterfaceDescriptor {
  public:
   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
-      InternalArrayConstructorDescriptor, CallInterfaceDescriptor)
+      ArrayNoArgumentConstructorDescriptor, CallInterfaceDescriptor)
+  enum ParameterIndices {
+    kFunctionIndex,
+    kAllocationSiteIndex,
+    kArgumentCountIndex,
+    kFunctionParameterIndex,
+    kContextIndex
+  };
+};
+
+class ArraySingleArgumentConstructorDescriptor
+    : public CallInterfaceDescriptor {
+ public:
+  DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
+      ArraySingleArgumentConstructorDescriptor, CallInterfaceDescriptor)
+  enum ParameterIndices {
+    kFunctionIndex,
+    kAllocationSiteIndex,
+    kArgumentCountIndex,
+    kFunctionParameterIndex,
+    kArraySizeSmiParameterIndex,
+    kContextIndex
+  };
+};
+
+class ArrayNArgumentsConstructorDescriptor : public CallInterfaceDescriptor {
+ public:
+  DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
+      ArrayNArgumentsConstructorDescriptor, CallInterfaceDescriptor)
+  enum ParameterIndices {
+    kFunctionIndex,
+    kAllocationSiteIndex,
+    kArgumentCountIndex,
+    kContextIndex
+  };
 };
 
 
@@ -631,6 +733,10 @@
                      CallInterfaceDescriptor)
 };
 
+class CountOpDescriptor final : public CallInterfaceDescriptor {
+ public:
+  DECLARE_DESCRIPTOR(CountOpDescriptor, CallInterfaceDescriptor)
+};
 
 class StringAddDescriptor : public CallInterfaceDescriptor {
  public:
@@ -746,13 +852,13 @@
 
 class ApiGetterDescriptor : public CallInterfaceDescriptor {
  public:
-  DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ApiGetterDescriptor,
-                                               CallInterfaceDescriptor)
+  DECLARE_DESCRIPTOR(ApiGetterDescriptor, CallInterfaceDescriptor)
 
-  static const Register function_address();
+  static const Register ReceiverRegister();
+  static const Register HolderRegister();
+  static const Register CallbackRegister();
 };
 
-
 class MathPowTaggedDescriptor : public CallInterfaceDescriptor {
  public:
   DECLARE_DESCRIPTOR(MathPowTaggedDescriptor, CallInterfaceDescriptor)
@@ -760,7 +866,6 @@
   static const Register exponent();
 };
 
-
 class MathPowIntegerDescriptor : public CallInterfaceDescriptor {
  public:
   DECLARE_DESCRIPTOR(MathPowIntegerDescriptor, CallInterfaceDescriptor)
@@ -768,15 +873,9 @@
   static const Register exponent();
 };
 
-
-class ContextOnlyDescriptor : public CallInterfaceDescriptor {
+class VarArgFunctionDescriptor : public CallInterfaceDescriptor {
  public:
-  DECLARE_DESCRIPTOR(ContextOnlyDescriptor, CallInterfaceDescriptor)
-};
-
-class FastArrayPushDescriptor : public CallInterfaceDescriptor {
- public:
-  DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(FastArrayPushDescriptor,
+  DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(VarArgFunctionDescriptor,
                                                CallInterfaceDescriptor)
 };
 
@@ -795,11 +894,9 @@
                                                CallInterfaceDescriptor)
 
   static const int kAccumulatorParameter = 0;
-  static const int kRegisterFileParameter = 1;
-  static const int kBytecodeOffsetParameter = 2;
-  static const int kBytecodeArrayParameter = 3;
-  static const int kDispatchTableParameter = 4;
-  static const int kContextParameter = 5;
+  static const int kBytecodeOffsetParameter = 1;
+  static const int kBytecodeArrayParameter = 2;
+  static const int kDispatchTableParameter = 3;
 };
 
 class InterpreterPushArgsAndCallDescriptor : public CallInterfaceDescriptor {
@@ -822,6 +919,11 @@
   DECLARE_DESCRIPTOR(InterpreterCEntryDescriptor, CallInterfaceDescriptor)
 };
 
+class ResumeGeneratorDescriptor final : public CallInterfaceDescriptor {
+ public:
+  DECLARE_DESCRIPTOR(ResumeGeneratorDescriptor, CallInterfaceDescriptor)
+};
+
 #undef DECLARE_DESCRIPTOR_WITH_BASE
 #undef DECLARE_DESCRIPTOR
 #undef DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE
diff --git a/src/interpreter/bytecode-array-builder.cc b/src/interpreter/bytecode-array-builder.cc
index 109b01e..c74fe7e 100644
--- a/src/interpreter/bytecode-array-builder.cc
+++ b/src/interpreter/bytecode-array-builder.cc
@@ -3,265 +3,155 @@
 // found in the LICENSE file.
 
 #include "src/interpreter/bytecode-array-builder.h"
+
 #include "src/compiler.h"
+#include "src/interpreter/bytecode-array-writer.h"
+#include "src/interpreter/bytecode-dead-code-optimizer.h"
+#include "src/interpreter/bytecode-label.h"
+#include "src/interpreter/bytecode-peephole-optimizer.h"
+#include "src/interpreter/bytecode-register-optimizer.h"
 #include "src/interpreter/interpreter-intrinsics.h"
 
 namespace v8 {
 namespace internal {
 namespace interpreter {
 
-class BytecodeArrayBuilder::PreviousBytecodeHelper BASE_EMBEDDED {
- public:
-  explicit PreviousBytecodeHelper(const BytecodeArrayBuilder& array_builder)
-      : array_builder_(array_builder),
-        previous_bytecode_start_(array_builder_.last_bytecode_start_) {
-    // This helper is expected to be instantiated only when the last bytecode is
-    // in the same basic block.
-    DCHECK(array_builder_.LastBytecodeInSameBlock());
-    bytecode_ = Bytecodes::FromByte(
-        array_builder_.bytecodes()->at(previous_bytecode_start_));
-    operand_scale_ = OperandScale::kSingle;
-    if (Bytecodes::IsPrefixScalingBytecode(bytecode_)) {
-      operand_scale_ = Bytecodes::PrefixBytecodeToOperandScale(bytecode_);
-      bytecode_ = Bytecodes::FromByte(
-          array_builder_.bytecodes()->at(previous_bytecode_start_ + 1));
-    }
-  }
-
-  // Returns the previous bytecode in the same basic block.
-  MUST_USE_RESULT Bytecode GetBytecode() const {
-    DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_);
-    return bytecode_;
-  }
-
-  MUST_USE_RESULT Register GetRegisterOperand(int operand_index) const {
-    return Register::FromOperand(GetSignedOperand(operand_index));
-  }
-
-  MUST_USE_RESULT uint32_t GetIndexOperand(int operand_index) const {
-    return GetUnsignedOperand(operand_index);
-  }
-
-  Handle<Object> GetConstantForIndexOperand(int operand_index) const {
-    return array_builder_.constant_array_builder()->At(
-        GetIndexOperand(operand_index));
-  }
-
- private:
-  // Returns the signed operand at operand_index for the previous
-  // bytecode in the same basic block.
-  MUST_USE_RESULT int32_t GetSignedOperand(int operand_index) const {
-    DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_);
-    OperandType operand_type =
-        Bytecodes::GetOperandType(bytecode_, operand_index);
-    DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type));
-    const uint8_t* operand_start = GetOperandStart(operand_index);
-    return Bytecodes::DecodeSignedOperand(operand_start, operand_type,
-                                          operand_scale_);
-  }
-
-  // Returns the unsigned operand at operand_index for the previous
-  // bytecode in the same basic block.
-  MUST_USE_RESULT uint32_t GetUnsignedOperand(int operand_index) const {
-    DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_);
-    OperandType operand_type =
-        Bytecodes::GetOperandType(bytecode_, operand_index);
-    DCHECK(Bytecodes::IsUnsignedOperandType(operand_type));
-    const uint8_t* operand_start = GetOperandStart(operand_index);
-    return Bytecodes::DecodeUnsignedOperand(operand_start, operand_type,
-                                            operand_scale_);
-  }
-
-  const uint8_t* GetOperandStart(int operand_index) const {
-    size_t operand_offset =
-        previous_bytecode_start_ + prefix_offset() +
-        Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale_);
-    return &(*array_builder_.bytecodes())[0] + operand_offset;
-  }
-
-  int prefix_offset() const {
-    return Bytecodes::OperandScaleRequiresPrefixBytecode(operand_scale_) ? 1
-                                                                         : 0;
-  }
-
-  const BytecodeArrayBuilder& array_builder_;
-  OperandScale operand_scale_;
-  Bytecode bytecode_;
-  size_t previous_bytecode_start_;
-
-  DISALLOW_COPY_AND_ASSIGN(PreviousBytecodeHelper);
-};
-
 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone,
                                            int parameter_count,
                                            int context_count, int locals_count,
                                            FunctionLiteral* literal)
     : isolate_(isolate),
       zone_(zone),
-      bytecodes_(zone),
       bytecode_generated_(false),
       constant_array_builder_(isolate, zone),
       handler_table_builder_(isolate, zone),
-      source_position_table_builder_(isolate, zone),
-      last_block_end_(0),
-      last_bytecode_start_(~0),
-      exit_seen_in_block_(false),
-      unbound_jumps_(0),
+      return_seen_in_block_(false),
       parameter_count_(parameter_count),
       local_register_count_(locals_count),
       context_register_count_(context_count),
-      temporary_allocator_(zone, fixed_register_count()) {
+      temporary_allocator_(zone, fixed_register_count()),
+      bytecode_array_writer_(isolate, zone, &constant_array_builder_),
+      pipeline_(&bytecode_array_writer_) {
   DCHECK_GE(parameter_count_, 0);
   DCHECK_GE(context_register_count_, 0);
   DCHECK_GE(local_register_count_, 0);
+
+  if (FLAG_ignition_deadcode) {
+    pipeline_ = new (zone) BytecodeDeadCodeOptimizer(pipeline_);
+  }
+
+  if (FLAG_ignition_peephole) {
+    pipeline_ = new (zone)
+        BytecodePeepholeOptimizer(&constant_array_builder_, pipeline_);
+  }
+
+  if (FLAG_ignition_reo) {
+    pipeline_ = new (zone) BytecodeRegisterOptimizer(
+        zone, &temporary_allocator_, parameter_count, pipeline_);
+  }
+
   return_position_ =
       literal ? std::max(literal->start_position(), literal->end_position() - 1)
               : RelocInfo::kNoPosition;
-  LOG_CODE_EVENT(isolate_, CodeStartLinePosInfoRecordEvent(
-                               source_position_table_builder()));
 }
 
-BytecodeArrayBuilder::~BytecodeArrayBuilder() { DCHECK_EQ(0, unbound_jumps_); }
-
 Register BytecodeArrayBuilder::first_context_register() const {
   DCHECK_GT(context_register_count_, 0);
   return Register(local_register_count_);
 }
 
-
 Register BytecodeArrayBuilder::last_context_register() const {
   DCHECK_GT(context_register_count_, 0);
   return Register(local_register_count_ + context_register_count_ - 1);
 }
 
-
 Register BytecodeArrayBuilder::Parameter(int parameter_index) const {
   DCHECK_GE(parameter_index, 0);
   return Register::FromParameterIndex(parameter_index, parameter_count());
 }
 
-
 bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const {
   return reg.is_parameter() || reg.index() < locals_count();
 }
 
-
 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() {
-  DCHECK_EQ(bytecode_generated_, false);
-  DCHECK(exit_seen_in_block_);
-
-  int bytecode_size = static_cast<int>(bytecodes_.size());
-  int register_count = fixed_and_temporary_register_count();
-  int frame_size = register_count * kPointerSize;
-  Handle<FixedArray> constant_pool = constant_array_builder()->ToFixedArray();
-  Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable();
-  Handle<ByteArray> source_position_table =
-      source_position_table_builder()->ToSourcePositionTable();
-  Handle<BytecodeArray> bytecode_array = isolate_->factory()->NewBytecodeArray(
-      bytecode_size, &bytecodes_.front(), frame_size, parameter_count(),
-      constant_pool);
-  bytecode_array->set_handler_table(*handler_table);
-  bytecode_array->set_source_position_table(*source_position_table);
-
-  void* line_info = source_position_table_builder()->DetachJITHandlerData();
-  LOG_CODE_EVENT(isolate_, CodeEndLinePosInfoRecordEvent(
-                               AbstractCode::cast(*bytecode_array), line_info));
-
+  DCHECK(return_seen_in_block_);
+  DCHECK(!bytecode_generated_);
   bytecode_generated_ = true;
-  return bytecode_array;
+
+  Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable();
+  return pipeline_->ToBytecodeArray(fixed_register_count(), parameter_count(),
+                                    handler_table);
 }
 
-template <size_t N>
-void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t (&operands)[N],
-                                  OperandScale operand_scale) {
-  // Don't output dead code.
-  if (exit_seen_in_block_) return;
+namespace {
 
-  int operand_count = static_cast<int>(N);
-  DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count);
+static bool ExpressionPositionIsNeeded(Bytecode bytecode) {
+  // An expression position is always needed if filtering is turned
+  // off. Otherwise an expression is only needed if the bytecode has
+  // external side effects.
+  return !FLAG_ignition_filter_expression_positions ||
+         !Bytecodes::IsWithoutExternalSideEffects(bytecode);
+}
 
-  last_bytecode_start_ = bytecodes()->size();
-  // Emit prefix bytecode for scale if required.
-  if (Bytecodes::OperandScaleRequiresPrefixBytecode(operand_scale)) {
-    bytecodes()->push_back(Bytecodes::ToByte(
-        Bytecodes::OperandScaleToPrefixBytecode(operand_scale)));
-  }
+}  // namespace
 
-  // Emit bytecode.
-  bytecodes()->push_back(Bytecodes::ToByte(bytecode));
-
-  // Emit operands.
-  for (int i = 0; i < operand_count; i++) {
-    DCHECK(OperandIsValid(bytecode, operand_scale, i, operands[i]));
-    switch (Bytecodes::GetOperandSize(bytecode, i, operand_scale)) {
-      case OperandSize::kNone:
-        UNREACHABLE();
-        break;
-      case OperandSize::kByte:
-        bytecodes()->push_back(static_cast<uint8_t>(operands[i]));
-        break;
-      case OperandSize::kShort: {
-        uint8_t operand_bytes[2];
-        WriteUnalignedUInt16(operand_bytes, operands[i]);
-        bytecodes()->insert(bytecodes()->end(), operand_bytes,
-                            operand_bytes + 2);
-        break;
-      }
-      case OperandSize::kQuad: {
-        uint8_t operand_bytes[4];
-        WriteUnalignedUInt32(operand_bytes, operands[i]);
-        bytecodes()->insert(bytecodes()->end(), operand_bytes,
-                            operand_bytes + 4);
-        break;
-      }
+void BytecodeArrayBuilder::AttachSourceInfo(BytecodeNode* node) {
+  if (latest_source_info_.is_valid()) {
+    // Statement positions need to be emitted immediately.  Expression
+    // positions can be pushed back until a bytecode is found that can
+    // throw. Hence we only invalidate the existing source position
+    // information if it is used.
+    if (latest_source_info_.is_statement() ||
+        ExpressionPositionIsNeeded(node->bytecode())) {
+      node->source_info().Clone(latest_source_info_);
+      latest_source_info_.set_invalid();
     }
   }
 }
 
+void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
+                                  uint32_t operand1, uint32_t operand2,
+                                  uint32_t operand3) {
+  DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3));
+  BytecodeNode node(bytecode, operand0, operand1, operand2, operand3);
+  AttachSourceInfo(&node);
+  pipeline()->Write(&node);
+}
+
+void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
+                                  uint32_t operand1, uint32_t operand2) {
+  DCHECK(OperandsAreValid(bytecode, 3, operand0, operand1, operand2));
+  BytecodeNode node(bytecode, operand0, operand1, operand2);
+  AttachSourceInfo(&node);
+  pipeline()->Write(&node);
+}
+
+void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
+                                  uint32_t operand1) {
+  DCHECK(OperandsAreValid(bytecode, 2, operand0, operand1));
+  BytecodeNode node(bytecode, operand0, operand1);
+  AttachSourceInfo(&node);
+  pipeline()->Write(&node);
+}
+
+void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) {
+  DCHECK(OperandsAreValid(bytecode, 1, operand0));
+  BytecodeNode node(bytecode, operand0);
+  AttachSourceInfo(&node);
+  pipeline()->Write(&node);
+}
+
 void BytecodeArrayBuilder::Output(Bytecode bytecode) {
-  // Don't output dead code.
-  if (exit_seen_in_block_) return;
-
-  DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0);
-  last_bytecode_start_ = bytecodes()->size();
-  bytecodes()->push_back(Bytecodes::ToByte(bytecode));
-}
-
-void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode,
-                                        OperandScale operand_scale,
-                                        uint32_t operand0, uint32_t operand1,
-                                        uint32_t operand2, uint32_t operand3) {
-  uint32_t operands[] = {operand0, operand1, operand2, operand3};
-  Output(bytecode, operands, operand_scale);
-}
-
-void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode,
-                                        OperandScale operand_scale,
-                                        uint32_t operand0, uint32_t operand1,
-                                        uint32_t operand2) {
-  uint32_t operands[] = {operand0, operand1, operand2};
-  Output(bytecode, operands, operand_scale);
-}
-
-void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode,
-                                        OperandScale operand_scale,
-                                        uint32_t operand0, uint32_t operand1) {
-  uint32_t operands[] = {operand0, operand1};
-  Output(bytecode, operands, operand_scale);
-}
-
-void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode,
-                                        OperandScale operand_scale,
-                                        uint32_t operand0) {
-  uint32_t operands[] = {operand0};
-  Output(bytecode, operands, operand_scale);
+  DCHECK(OperandsAreValid(bytecode, 0));
+  BytecodeNode node(bytecode);
+  AttachSourceInfo(&node);
+  pipeline()->Write(&node);
 }
 
 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
                                                             Register reg) {
-  OperandScale operand_scale = OperandSizesToScale(SizeForRegisterOperand(reg));
-  OutputScaled(BytecodeForBinaryOperation(op), operand_scale,
-               RegisterOperand(reg));
+  Output(BytecodeForBinaryOperation(op), RegisterOperand(reg));
   return *this;
 }
 
@@ -270,9 +160,8 @@
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() {
-  Output(Bytecode::kLogicalNot);
+  Output(Bytecode::kToBooleanLogicalNot);
   return *this;
 }
 
@@ -284,61 +173,47 @@
 
 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op,
                                                              Register reg) {
-  OperandScale operand_scale = OperandSizesToScale(SizeForRegisterOperand(reg));
-  OutputScaled(BytecodeForCompareOperation(op), operand_scale,
-               RegisterOperand(reg));
+  Output(BytecodeForCompareOperation(op), RegisterOperand(reg));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
     v8::internal::Smi* smi) {
   int32_t raw_smi = smi->value();
   if (raw_smi == 0) {
     Output(Bytecode::kLdaZero);
   } else {
-    OperandSize operand_size = SizeForSignedOperand(raw_smi);
-    OperandScale operand_scale = OperandSizesToScale(operand_size);
-    OutputScaled(Bytecode::kLdaSmi, operand_scale,
-                 SignedOperand(raw_smi, operand_size));
+    Output(Bytecode::kLdaSmi, SignedOperand(raw_smi));
   }
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) {
   size_t entry = GetConstantPoolEntry(object);
-  OperandScale operand_scale =
-      OperandSizesToScale(SizeForUnsignedOperand(entry));
-  OutputScaled(Bytecode::kLdaConstant, operand_scale, UnsignedOperand(entry));
+  Output(Bytecode::kLdaConstant, UnsignedOperand(entry));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
   Output(Bytecode::kLdaUndefined);
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
   Output(Bytecode::kLdaNull);
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
   Output(Bytecode::kLdaTheHole);
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
   Output(Bytecode::kLdaTrue);
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
   Output(Bytecode::kLdaFalse);
   return *this;
@@ -346,47 +221,29 @@
 
 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
     Register reg) {
-  if (!IsRegisterInAccumulator(reg)) {
-    OperandScale operand_scale =
-        OperandSizesToScale(SizeForRegisterOperand(reg));
-    OutputScaled(Bytecode::kLdar, operand_scale, RegisterOperand(reg));
-  }
+  Output(Bytecode::kLdar, RegisterOperand(reg));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
     Register reg) {
-  if (!IsRegisterInAccumulator(reg)) {
-    OperandScale operand_scale =
-        OperandSizesToScale(SizeForRegisterOperand(reg));
-    OutputScaled(Bytecode::kStar, operand_scale, RegisterOperand(reg));
-  }
+  Output(Bytecode::kStar, RegisterOperand(reg));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
                                                          Register to) {
   DCHECK(from != to);
-  OperandScale operand_scale = OperandSizesToScale(SizeForRegisterOperand(from),
-                                                   SizeForRegisterOperand(to));
-  OutputScaled(Bytecode::kMov, operand_scale, RegisterOperand(from),
-               RegisterOperand(to));
+  Output(Bytecode::kMov, RegisterOperand(from), RegisterOperand(to));
   return *this;
 }
 
-BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(
-    const Handle<String> name, int feedback_slot, TypeofMode typeof_mode) {
+BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot,
+                                                       TypeofMode typeof_mode) {
   // TODO(rmcilroy): Potentially store typeof information in an
   // operand rather than having extra bytecodes.
   Bytecode bytecode = BytecodeForLoadGlobal(typeof_mode);
-  size_t name_index = GetConstantPoolEntry(name);
-  OperandScale operand_scale =
-      OperandSizesToScale(SizeForUnsignedOperand(name_index),
-                          SizeForUnsignedOperand(feedback_slot));
-  OutputScaled(bytecode, operand_scale, UnsignedOperand(name_index),
-               UnsignedOperand(feedback_slot));
+  Output(bytecode, UnsignedOperand(feedback_slot));
   return *this;
 }
 
@@ -394,31 +251,21 @@
     const Handle<String> name, int feedback_slot, LanguageMode language_mode) {
   Bytecode bytecode = BytecodeForStoreGlobal(language_mode);
   size_t name_index = GetConstantPoolEntry(name);
-  OperandScale operand_scale =
-      OperandSizesToScale(SizeForUnsignedOperand(name_index),
-                          SizeForUnsignedOperand(feedback_slot));
-  OutputScaled(bytecode, operand_scale, UnsignedOperand(name_index),
-               UnsignedOperand(feedback_slot));
+  Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(feedback_slot));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context,
                                                             int slot_index) {
-  OperandScale operand_scale = OperandSizesToScale(
-      SizeForRegisterOperand(context), SizeForUnsignedOperand(slot_index));
-  OutputScaled(Bytecode::kLdaContextSlot, operand_scale,
-               RegisterOperand(context), UnsignedOperand(slot_index));
+  Output(Bytecode::kLdaContextSlot, RegisterOperand(context),
+         UnsignedOperand(slot_index));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
                                                              int slot_index) {
-  OperandScale operand_scale = OperandSizesToScale(
-      SizeForRegisterOperand(context), SizeForUnsignedOperand(slot_index));
-  OutputScaled(Bytecode::kStaContextSlot, operand_scale,
-               RegisterOperand(context), UnsignedOperand(slot_index));
+  Output(Bytecode::kStaContextSlot, RegisterOperand(context),
+         UnsignedOperand(slot_index));
   return *this;
 }
 
@@ -428,9 +275,7 @@
                           ? Bytecode::kLdaLookupSlotInsideTypeof
                           : Bytecode::kLdaLookupSlot;
   size_t name_index = GetConstantPoolEntry(name);
-  OperandScale operand_scale =
-      OperandSizesToScale(SizeForUnsignedOperand(name_index));
-  OutputScaled(bytecode, operand_scale, UnsignedOperand(name_index));
+  Output(bytecode, UnsignedOperand(name_index));
   return *this;
 }
 
@@ -438,70 +283,52 @@
     const Handle<String> name, LanguageMode language_mode) {
   Bytecode bytecode = BytecodeForStoreLookupSlot(language_mode);
   size_t name_index = GetConstantPoolEntry(name);
-  OperandScale operand_scale =
-      OperandSizesToScale(SizeForUnsignedOperand(name_index));
-  OutputScaled(bytecode, operand_scale, UnsignedOperand(name_index));
+  Output(bytecode, UnsignedOperand(name_index));
   return *this;
 }
 
 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
     Register object, const Handle<Name> name, int feedback_slot) {
   size_t name_index = GetConstantPoolEntry(name);
-  OperandScale operand_scale = OperandSizesToScale(
-      SizeForRegisterOperand(object), SizeForUnsignedOperand(name_index),
-      SizeForUnsignedOperand(feedback_slot));
-  OutputScaled(Bytecode::kLoadIC, operand_scale, RegisterOperand(object),
-               UnsignedOperand(name_index), UnsignedOperand(feedback_slot));
+  Output(Bytecode::kLdaNamedProperty, RegisterOperand(object),
+         UnsignedOperand(name_index), UnsignedOperand(feedback_slot));
   return *this;
 }
 
 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
     Register object, int feedback_slot) {
-  OperandScale operand_scale = OperandSizesToScale(
-      SizeForRegisterOperand(object), SizeForUnsignedOperand(feedback_slot));
-  OutputScaled(Bytecode::kKeyedLoadIC, operand_scale, RegisterOperand(object),
-               UnsignedOperand(feedback_slot));
+  Output(Bytecode::kLdaKeyedProperty, RegisterOperand(object),
+         UnsignedOperand(feedback_slot));
   return *this;
 }
 
 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
     Register object, const Handle<Name> name, int feedback_slot,
     LanguageMode language_mode) {
-  Bytecode bytecode = BytecodeForStoreIC(language_mode);
+  Bytecode bytecode = BytecodeForStoreNamedProperty(language_mode);
   size_t name_index = GetConstantPoolEntry(name);
-  OperandScale operand_scale = OperandSizesToScale(
-      SizeForRegisterOperand(object), SizeForUnsignedOperand(name_index),
-      SizeForUnsignedOperand(feedback_slot));
-  OutputScaled(bytecode, operand_scale, RegisterOperand(object),
-               UnsignedOperand(name_index), UnsignedOperand(feedback_slot));
+  Output(bytecode, RegisterOperand(object), UnsignedOperand(name_index),
+         UnsignedOperand(feedback_slot));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
     Register object, Register key, int feedback_slot,
     LanguageMode language_mode) {
-  Bytecode bytecode = BytecodeForKeyedStoreIC(language_mode);
-  OperandScale operand_scale = OperandSizesToScale(
-      SizeForRegisterOperand(object), SizeForRegisterOperand(key),
-      SizeForUnsignedOperand(feedback_slot));
-  OutputScaled(bytecode, operand_scale, RegisterOperand(object),
-               RegisterOperand(key), UnsignedOperand(feedback_slot));
+  Bytecode bytecode = BytecodeForStoreKeyedProperty(language_mode);
+  Output(bytecode, RegisterOperand(object), RegisterOperand(key),
+         UnsignedOperand(feedback_slot));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(
     Handle<SharedFunctionInfo> shared_info, PretenureFlag tenured) {
   size_t entry = GetConstantPoolEntry(shared_info);
-  OperandScale operand_scale =
-      OperandSizesToScale(SizeForUnsignedOperand(entry));
-  OutputScaled(Bytecode::kCreateClosure, operand_scale, UnsignedOperand(entry),
-               UnsignedOperand(static_cast<size_t>(tenured)));
+  Output(Bytecode::kCreateClosure, UnsignedOperand(entry),
+         UnsignedOperand(static_cast<size_t>(tenured)));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
     CreateArgumentsType type) {
   // TODO(rmcilroy): Consider passing the type as a bytecode operand rather
@@ -512,387 +339,141 @@
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
     Handle<String> pattern, int literal_index, int flags) {
   size_t pattern_entry = GetConstantPoolEntry(pattern);
-  OperandScale operand_scale = OperandSizesToScale(
-      SizeForUnsignedOperand(pattern_entry),
-      SizeForUnsignedOperand(literal_index), SizeForUnsignedOperand(flags));
-  OutputScaled(Bytecode::kCreateRegExpLiteral, operand_scale,
-               UnsignedOperand(pattern_entry), UnsignedOperand(literal_index),
-               UnsignedOperand(flags));
+  Output(Bytecode::kCreateRegExpLiteral, UnsignedOperand(pattern_entry),
+         UnsignedOperand(literal_index), UnsignedOperand(flags));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
     Handle<FixedArray> constant_elements, int literal_index, int flags) {
   size_t constant_elements_entry = GetConstantPoolEntry(constant_elements);
-  OperandScale operand_scale = OperandSizesToScale(
-      SizeForUnsignedOperand(constant_elements_entry),
-      SizeForUnsignedOperand(literal_index), SizeForUnsignedOperand(flags));
-  OutputScaled(Bytecode::kCreateArrayLiteral, operand_scale,
-               UnsignedOperand(constant_elements_entry),
-               UnsignedOperand(literal_index), UnsignedOperand(flags));
+  Output(Bytecode::kCreateArrayLiteral,
+         UnsignedOperand(constant_elements_entry),
+         UnsignedOperand(literal_index), UnsignedOperand(flags));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
     Handle<FixedArray> constant_properties, int literal_index, int flags) {
   size_t constant_properties_entry = GetConstantPoolEntry(constant_properties);
-  OperandScale operand_scale = OperandSizesToScale(
-      SizeForUnsignedOperand(constant_properties_entry),
-      SizeForUnsignedOperand(literal_index), SizeForUnsignedOperand(flags));
-  OutputScaled(Bytecode::kCreateObjectLiteral, operand_scale,
-               UnsignedOperand(constant_properties_entry),
-               UnsignedOperand(literal_index), UnsignedOperand(flags));
+  Output(Bytecode::kCreateObjectLiteral,
+         UnsignedOperand(constant_properties_entry),
+         UnsignedOperand(literal_index), UnsignedOperand(flags));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
-  OperandScale operand_scale =
-      OperandSizesToScale(SizeForRegisterOperand(context));
-  OutputScaled(Bytecode::kPushContext, operand_scale, RegisterOperand(context));
+  Output(Bytecode::kPushContext, RegisterOperand(context));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
-  OperandScale operand_scale =
-      OperandSizesToScale(SizeForRegisterOperand(context));
-  OutputScaled(Bytecode::kPopContext, operand_scale, RegisterOperand(context));
+  Output(Bytecode::kPopContext, RegisterOperand(context));
   return *this;
 }
 
-
-bool BytecodeArrayBuilder::NeedToBooleanCast() {
-  if (!LastBytecodeInSameBlock()) {
-    return true;
-  }
-  PreviousBytecodeHelper previous_bytecode(*this);
-  switch (previous_bytecode.GetBytecode()) {
-    // If the previous bytecode puts a boolean in the accumulator return true.
-    case Bytecode::kLdaTrue:
-    case Bytecode::kLdaFalse:
-    case Bytecode::kLogicalNot:
-    case Bytecode::kTestEqual:
-    case Bytecode::kTestNotEqual:
-    case Bytecode::kTestEqualStrict:
-    case Bytecode::kTestLessThan:
-    case Bytecode::kTestLessThanOrEqual:
-    case Bytecode::kTestGreaterThan:
-    case Bytecode::kTestGreaterThanOrEqual:
-    case Bytecode::kTestInstanceOf:
-    case Bytecode::kTestIn:
-    case Bytecode::kForInDone:
-      return false;
-    default:
-      return true;
-  }
-}
-
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToJSObject() {
   Output(Bytecode::kToObject);
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() {
-  if (LastBytecodeInSameBlock()) {
-    PreviousBytecodeHelper previous_bytecode(*this);
-    switch (previous_bytecode.GetBytecode()) {
-      case Bytecode::kToName:
-      case Bytecode::kTypeOf:
-        return *this;
-      case Bytecode::kLdaConstant: {
-        Handle<Object> object = previous_bytecode.GetConstantForIndexOperand(0);
-        if (object->IsName()) return *this;
-        break;
-      }
-      default:
-        break;
-    }
-  }
   Output(Bytecode::kToName);
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToNumber() {
-  // TODO(rmcilroy): consider omitting if the preceeding bytecode always returns
-  // a number.
   Output(Bytecode::kToNumber);
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
-  if (label->is_forward_target()) {
-    // An earlier jump instruction refers to this label. Update it's location.
-    PatchJump(bytecodes()->end(), bytecodes()->begin() + label->offset());
-    // Now treat as if the label will only be back referred to.
-  }
-  label->bind_to(bytecodes()->size());
+  pipeline_->BindLabel(label);
   LeaveBasicBlock();
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target,
                                                  BytecodeLabel* label) {
-  DCHECK(!label->is_bound());
-  DCHECK(target.is_bound());
-  if (label->is_forward_target()) {
-    // An earlier jump instruction refers to this label. Update it's location.
-    PatchJump(bytecodes()->begin() + target.offset(),
-              bytecodes()->begin() + label->offset());
-    // Now treat as if the label will only be back referred to.
-  }
-  label->bind_to(target.offset());
+  pipeline_->BindLabel(target, label);
   LeaveBasicBlock();
   return *this;
 }
 
-
-// static
-Bytecode BytecodeArrayBuilder::GetJumpWithConstantOperand(
-    Bytecode jump_bytecode) {
-  switch (jump_bytecode) {
-    case Bytecode::kJump:
-      return Bytecode::kJumpConstant;
-    case Bytecode::kJumpIfTrue:
-      return Bytecode::kJumpIfTrueConstant;
-    case Bytecode::kJumpIfFalse:
-      return Bytecode::kJumpIfFalseConstant;
-    case Bytecode::kJumpIfToBooleanTrue:
-      return Bytecode::kJumpIfToBooleanTrueConstant;
-    case Bytecode::kJumpIfToBooleanFalse:
-      return Bytecode::kJumpIfToBooleanFalseConstant;
-    case Bytecode::kJumpIfNotHole:
-      return Bytecode::kJumpIfNotHoleConstant;
-    case Bytecode::kJumpIfNull:
-      return Bytecode::kJumpIfNullConstant;
-    case Bytecode::kJumpIfUndefined:
-      return Bytecode::kJumpIfUndefinedConstant;
-    default:
-      UNREACHABLE();
-      return Bytecode::kIllegal;
-  }
-}
-
-// static
-Bytecode BytecodeArrayBuilder::GetJumpWithToBoolean(Bytecode jump_bytecode) {
-  switch (jump_bytecode) {
-    case Bytecode::kJump:
-    case Bytecode::kJumpIfNull:
-    case Bytecode::kJumpIfUndefined:
-    case Bytecode::kJumpIfNotHole:
-      return jump_bytecode;
-    case Bytecode::kJumpIfTrue:
-      return Bytecode::kJumpIfToBooleanTrue;
-    case Bytecode::kJumpIfFalse:
-      return Bytecode::kJumpIfToBooleanFalse;
-    default:
-      UNREACHABLE();
-  }
-  return Bytecode::kIllegal;
-}
-
-
-void BytecodeArrayBuilder::PatchIndirectJumpWith8BitOperand(
-    const ZoneVector<uint8_t>::iterator& jump_location, int delta) {
-  Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location);
-  DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode));
-  ZoneVector<uint8_t>::iterator operand_location = jump_location + 1;
-  DCHECK_EQ(*operand_location, 0);
-  if (SizeForSignedOperand(delta) == OperandSize::kByte) {
-    // The jump fits within the range of an Imm operand, so cancel
-    // the reservation and jump directly.
-    constant_array_builder()->DiscardReservedEntry(OperandSize::kByte);
-    *operand_location = static_cast<uint8_t>(delta);
-  } else {
-    // The jump does not fit within the range of an Imm operand, so
-    // commit reservation putting the offset into the constant pool,
-    // and update the jump instruction and operand.
-    size_t entry = constant_array_builder()->CommitReservedEntry(
-        OperandSize::kByte, handle(Smi::FromInt(delta), isolate()));
-    DCHECK(SizeForUnsignedOperand(entry) == OperandSize::kByte);
-    jump_bytecode = GetJumpWithConstantOperand(jump_bytecode);
-    *jump_location = Bytecodes::ToByte(jump_bytecode);
-    *operand_location = static_cast<uint8_t>(entry);
-  }
-}
-
-void BytecodeArrayBuilder::PatchIndirectJumpWith16BitOperand(
-    const ZoneVector<uint8_t>::iterator& jump_location, int delta) {
-  Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location);
-  DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode));
-  ZoneVector<uint8_t>::iterator operand_location = jump_location + 1;
-  uint8_t operand_bytes[2];
-  if (SizeForSignedOperand(delta) <= OperandSize::kShort) {
-    constant_array_builder()->DiscardReservedEntry(OperandSize::kShort);
-    WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(delta));
-  } else {
-    jump_bytecode = GetJumpWithConstantOperand(jump_bytecode);
-    *jump_location = Bytecodes::ToByte(jump_bytecode);
-    size_t entry = constant_array_builder()->CommitReservedEntry(
-        OperandSize::kShort, handle(Smi::FromInt(delta), isolate()));
-    WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry));
-  }
-  DCHECK(*operand_location == 0 && *(operand_location + 1) == 0);
-  *operand_location++ = operand_bytes[0];
-  *operand_location = operand_bytes[1];
-}
-
-void BytecodeArrayBuilder::PatchIndirectJumpWith32BitOperand(
-    const ZoneVector<uint8_t>::iterator& jump_location, int delta) {
-  DCHECK(Bytecodes::IsJumpImmediate(Bytecodes::FromByte(*jump_location)));
-  constant_array_builder()->DiscardReservedEntry(OperandSize::kQuad);
-  ZoneVector<uint8_t>::iterator operand_location = jump_location + 1;
-  uint8_t operand_bytes[4];
-  WriteUnalignedUInt32(operand_bytes, static_cast<uint32_t>(delta));
-  DCHECK(*operand_location == 0 && *(operand_location + 1) == 0 &&
-         *(operand_location + 2) == 0 && *(operand_location + 3) == 0);
-  *operand_location++ = operand_bytes[0];
-  *operand_location++ = operand_bytes[1];
-  *operand_location++ = operand_bytes[2];
-  *operand_location = operand_bytes[3];
-}
-
-void BytecodeArrayBuilder::PatchJump(
-    const ZoneVector<uint8_t>::iterator& jump_target,
-    const ZoneVector<uint8_t>::iterator& jump_location) {
-  int delta = static_cast<int>(jump_target - jump_location);
-  Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location);
-  int prefix_offset = 0;
-  OperandScale operand_scale = OperandScale::kSingle;
-  if (Bytecodes::IsPrefixScalingBytecode(jump_bytecode)) {
-    // If a prefix scaling bytecode is emitted the target offset is one
-    // less than the case of no prefix scaling bytecode.
-    delta -= 1;
-    prefix_offset = 1;
-    operand_scale = Bytecodes::PrefixBytecodeToOperandScale(jump_bytecode);
-    jump_bytecode = Bytecodes::FromByte(*(jump_location + prefix_offset));
-  }
-
-  DCHECK(Bytecodes::IsJump(jump_bytecode));
-  switch (operand_scale) {
-    case OperandScale::kSingle:
-      PatchIndirectJumpWith8BitOperand(jump_location, delta);
-      break;
-    case OperandScale::kDouble:
-      PatchIndirectJumpWith16BitOperand(jump_location + prefix_offset, delta);
-      break;
-    case OperandScale::kQuadruple:
-      PatchIndirectJumpWith32BitOperand(jump_location + prefix_offset, delta);
-      break;
-    default:
-      UNREACHABLE();
-  }
-  unbound_jumps_--;
-}
-
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode,
                                                        BytecodeLabel* label) {
-  // Don't emit dead code.
-  if (exit_seen_in_block_) return *this;
-
-  // Check if the value in accumulator is boolean, if not choose an
-  // appropriate JumpIfToBoolean bytecode.
-  if (NeedToBooleanCast()) {
-    jump_bytecode = GetJumpWithToBoolean(jump_bytecode);
-  }
-
-  if (label->is_bound()) {
-    // Label has been bound already so this is a backwards jump.
-    CHECK_GE(bytecodes()->size(), label->offset());
-    CHECK_LE(bytecodes()->size(), static_cast<size_t>(kMaxInt));
-    size_t abs_delta = bytecodes()->size() - label->offset();
-    int delta = -static_cast<int>(abs_delta);
-    OperandSize operand_size = SizeForSignedOperand(delta);
-    if (operand_size > OperandSize::kByte) {
-      // Adjust for scaling byte prefix for wide jump offset.
-      DCHECK_LE(delta, 0);
-      delta -= 1;
-    }
-    OutputScaled(jump_bytecode, OperandSizesToScale(operand_size),
-                 SignedOperand(delta, operand_size));
-  } else {
-    // The label has not yet been bound so this is a forward reference
-    // that will be patched when the label is bound. We create a
-    // reservation in the constant pool so the jump can be patched
-    // when the label is bound. The reservation means the maximum size
-    // of the operand for the constant is known and the jump can
-    // be emitted into the bytecode stream with space for the operand.
-    label->set_referrer(bytecodes()->size());
-    unbound_jumps_++;
-    OperandSize reserved_operand_size =
-        constant_array_builder()->CreateReservedEntry();
-    OutputScaled(jump_bytecode, OperandSizesToScale(reserved_operand_size), 0);
-  }
+  BytecodeNode node(jump_bytecode, 0);
+  AttachSourceInfo(&node);
+  pipeline_->WriteJump(&node, label);
   LeaveBasicBlock();
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
   return OutputJump(Bytecode::kJump, label);
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) {
-  return OutputJump(Bytecode::kJumpIfTrue, label);
+  // The peephole optimizer attempts to simplify JumpIfToBooleanTrue
+  // to JumpIfTrue.
+  return OutputJump(Bytecode::kJumpIfToBooleanTrue, label);
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) {
-  return OutputJump(Bytecode::kJumpIfFalse, label);
+  // The peephole optimizer attempts to simplify JumpIfToBooleanFalse
+  // to JumpIfFalse.
+  return OutputJump(Bytecode::kJumpIfToBooleanFalse, label);
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
   return OutputJump(Bytecode::kJumpIfNull, label);
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
     BytecodeLabel* label) {
   return OutputJump(Bytecode::kJumpIfUndefined, label);
 }
 
-BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck() {
-  Output(Bytecode::kStackCheck);
-  return *this;
-}
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole(
     BytecodeLabel* label) {
   return OutputJump(Bytecode::kJumpIfNotHole, label);
 }
 
-BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
-  Output(Bytecode::kThrow);
-  exit_seen_in_block_ = true;
+BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) {
+  if (position != RelocInfo::kNoPosition) {
+    // We need to attach a non-breakable source position to a stack
+    // check, so we simply add it as expression position. There can be
+    // a prior statement position from constructs like:
+    //
+    //    do var x;  while (false);
+    //
+    // A Nop could be inserted for empty statements, but since no code
+    // is associated with these positions, instead we force the stack
+    // check's expression position which eliminates the empty
+    // statement's position.
+    latest_source_info_.ForceExpressionPosition(position);
+  }
+  Output(Bytecode::kStackCheck);
   return *this;
 }
 
+BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
+  Output(Bytecode::kThrow);
+  return *this;
+}
 
 BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
   Output(Bytecode::kReThrow);
-  exit_seen_in_block_ = true;
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
   SetReturnPosition();
   Output(Bytecode::kReturn);
-  exit_seen_in_block_ = true;
+  return_seen_in_block_ = true;
   return *this;
 }
 
@@ -903,77 +484,74 @@
 
 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
     Register cache_info_triple) {
-  OperandScale operand_scale =
-      OperandSizesToScale(SizeForRegisterOperand(cache_info_triple));
-  OutputScaled(Bytecode::kForInPrepare, operand_scale,
-               RegisterOperand(cache_info_triple));
+  Output(Bytecode::kForInPrepare, RegisterOperand(cache_info_triple));
   return *this;
 }
 
 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInDone(Register index,
                                                       Register cache_length) {
-  OperandScale operand_scale = OperandSizesToScale(
-      SizeForRegisterOperand(index), SizeForRegisterOperand(cache_length));
-  OutputScaled(Bytecode::kForInDone, operand_scale, RegisterOperand(index),
-               RegisterOperand(cache_length));
+  Output(Bytecode::kForInDone, RegisterOperand(index),
+         RegisterOperand(cache_length));
   return *this;
 }
 
 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(
     Register receiver, Register index, Register cache_type_array_pair,
     int feedback_slot) {
-  OperandScale operand_scale = OperandSizesToScale(
-      SizeForRegisterOperand(receiver), SizeForRegisterOperand(index),
-      SizeForRegisterOperand(cache_type_array_pair),
-      SizeForUnsignedOperand(feedback_slot));
-  OutputScaled(Bytecode::kForInNext, operand_scale, RegisterOperand(receiver),
-               RegisterOperand(index), RegisterOperand(cache_type_array_pair),
-               UnsignedOperand(feedback_slot));
+  Output(Bytecode::kForInNext, RegisterOperand(receiver),
+         RegisterOperand(index), RegisterOperand(cache_type_array_pair),
+         UnsignedOperand(feedback_slot));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
-  OperandScale operand_scale =
-      OperandSizesToScale(SizeForRegisterOperand(index));
-  OutputScaled(Bytecode::kForInStep, operand_scale, RegisterOperand(index));
+  Output(Bytecode::kForInStep, RegisterOperand(index));
   return *this;
 }
 
+BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator(
+    Register generator) {
+  Output(Bytecode::kSuspendGenerator, RegisterOperand(generator));
+  return *this;
+}
+
+BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
+    Register generator) {
+  Output(Bytecode::kResumeGenerator, RegisterOperand(generator));
+  return *this;
+}
 
 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(int handler_id,
                                                         bool will_catch) {
-  handler_table_builder()->SetHandlerTarget(handler_id, bytecodes()->size());
+  BytecodeLabel handler;
+  Bind(&handler);
+  handler_table_builder()->SetHandlerTarget(handler_id, handler.offset());
   handler_table_builder()->SetPrediction(handler_id, will_catch);
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id,
                                                          Register context) {
-  handler_table_builder()->SetTryRegionStart(handler_id, bytecodes()->size());
+  BytecodeLabel try_begin;
+  Bind(&try_begin);
+  handler_table_builder()->SetTryRegionStart(handler_id, try_begin.offset());
   handler_table_builder()->SetContextRegister(handler_id, context);
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
-  handler_table_builder()->SetTryRegionEnd(handler_id, bytecodes()->size());
+  BytecodeLabel try_end;
+  Bind(&try_end);
+  handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset());
   return *this;
 }
 
-
-void BytecodeArrayBuilder::LeaveBasicBlock() {
-  last_block_end_ = bytecodes()->size();
-  exit_seen_in_block_ = false;
-}
-
 void BytecodeArrayBuilder::EnsureReturn() {
-  if (!exit_seen_in_block_) {
+  if (!return_seen_in_block_) {
     LoadUndefined();
     Return();
   }
-  DCHECK(exit_seen_in_block_);
+  DCHECK(return_seen_in_block_);
 }
 
 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
@@ -982,14 +560,8 @@
                                                  int feedback_slot,
                                                  TailCallMode tail_call_mode) {
   Bytecode bytecode = BytecodeForCall(tail_call_mode);
-  OperandScale operand_scale = OperandSizesToScale(
-      SizeForRegisterOperand(callable), SizeForRegisterOperand(receiver_args),
-      SizeForUnsignedOperand(receiver_args_count),
-      SizeForUnsignedOperand(feedback_slot));
-  OutputScaled(bytecode, operand_scale, RegisterOperand(callable),
-               RegisterOperand(receiver_args),
-               UnsignedOperand(receiver_args_count),
-               UnsignedOperand(feedback_slot));
+  Output(bytecode, RegisterOperand(callable), RegisterOperand(receiver_args),
+         UnsignedOperand(receiver_args_count), UnsignedOperand(feedback_slot));
   return *this;
 }
 
@@ -1000,71 +572,57 @@
     DCHECK_EQ(0u, arg_count);
     first_arg = Register(0);
   }
-  OperandScale operand_scale = OperandSizesToScale(
-      SizeForRegisterOperand(constructor), SizeForRegisterOperand(first_arg),
-      SizeForUnsignedOperand(arg_count));
-  OutputScaled(Bytecode::kNew, operand_scale, RegisterOperand(constructor),
-               RegisterOperand(first_arg), UnsignedOperand(arg_count));
+  Output(Bytecode::kNew, RegisterOperand(constructor),
+         RegisterOperand(first_arg), UnsignedOperand(arg_count));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
     Runtime::FunctionId function_id, Register first_arg, size_t arg_count) {
   DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
-  DCHECK(SizeForUnsignedOperand(function_id) <= OperandSize::kShort);
+  DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort);
   if (!first_arg.is_valid()) {
     DCHECK_EQ(0u, arg_count);
     first_arg = Register(0);
   }
-  Bytecode bytecode = IntrinsicsHelper::IsSupported(function_id)
-                          ? Bytecode::kInvokeIntrinsic
-                          : Bytecode::kCallRuntime;
-  OperandScale operand_scale = OperandSizesToScale(
-      SizeForRegisterOperand(first_arg), SizeForUnsignedOperand(arg_count));
-  OutputScaled(bytecode, operand_scale, static_cast<uint16_t>(function_id),
-               RegisterOperand(first_arg), UnsignedOperand(arg_count));
+  Bytecode bytecode;
+  uint32_t id;
+  if (IntrinsicsHelper::IsSupported(function_id)) {
+    bytecode = Bytecode::kInvokeIntrinsic;
+    id = static_cast<uint32_t>(IntrinsicsHelper::FromRuntimeId(function_id));
+  } else {
+    bytecode = Bytecode::kCallRuntime;
+    id = static_cast<uint32_t>(function_id);
+  }
+  Output(bytecode, id, RegisterOperand(first_arg), UnsignedOperand(arg_count));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
     Runtime::FunctionId function_id, Register first_arg, size_t arg_count,
     Register first_return) {
   DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
-  DCHECK(SizeForUnsignedOperand(function_id) <= OperandSize::kShort);
+  DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort);
   if (!first_arg.is_valid()) {
     DCHECK_EQ(0u, arg_count);
     first_arg = Register(0);
   }
-  OperandScale operand_scale = OperandSizesToScale(
-      SizeForRegisterOperand(first_arg), SizeForUnsignedOperand(arg_count),
-      SizeForRegisterOperand(first_return));
-  OutputScaled(Bytecode::kCallRuntimeForPair, operand_scale,
-               static_cast<uint16_t>(function_id), RegisterOperand(first_arg),
-               UnsignedOperand(arg_count), RegisterOperand(first_return));
+  Output(Bytecode::kCallRuntimeForPair, static_cast<uint16_t>(function_id),
+         RegisterOperand(first_arg), UnsignedOperand(arg_count),
+         RegisterOperand(first_return));
   return *this;
 }
 
 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(
     int context_index, Register receiver_args, size_t receiver_args_count) {
-  OperandScale operand_scale =
-      OperandSizesToScale(SizeForUnsignedOperand(context_index),
-                          SizeForRegisterOperand(receiver_args),
-                          SizeForUnsignedOperand(receiver_args_count));
-  OutputScaled(Bytecode::kCallJSRuntime, operand_scale,
-               UnsignedOperand(context_index), RegisterOperand(receiver_args),
-               UnsignedOperand(receiver_args_count));
+  Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index),
+         RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count));
   return *this;
 }
 
-
 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
                                                    LanguageMode language_mode) {
-  OperandScale operand_scale =
-      OperandSizesToScale(SizeForRegisterOperand(object));
-  OutputScaled(BytecodeForDelete(language_mode), operand_scale,
-               RegisterOperand(object));
+  Output(BytecodeForDelete(language_mode), RegisterOperand(object));
   return *this;
 }
 
@@ -1074,105 +632,37 @@
 
 void BytecodeArrayBuilder::SetReturnPosition() {
   if (return_position_ == RelocInfo::kNoPosition) return;
-  if (exit_seen_in_block_) return;
-  source_position_table_builder_.AddStatementPosition(bytecodes_.size(),
-                                                      return_position_);
+  latest_source_info_.MakeStatementPosition(return_position_);
 }
 
 void BytecodeArrayBuilder::SetStatementPosition(Statement* stmt) {
   if (stmt->position() == RelocInfo::kNoPosition) return;
-  if (exit_seen_in_block_) return;
-  source_position_table_builder_.AddStatementPosition(bytecodes_.size(),
-                                                      stmt->position());
+  latest_source_info_.MakeStatementPosition(stmt->position());
 }
 
 void BytecodeArrayBuilder::SetExpressionPosition(Expression* expr) {
   if (expr->position() == RelocInfo::kNoPosition) return;
-  if (exit_seen_in_block_) return;
-  source_position_table_builder_.AddExpressionPosition(bytecodes_.size(),
-                                                       expr->position());
+  if (!latest_source_info_.is_statement()) {
+    // Ensure the current expression position is overwritten with the
+    // latest value.
+    latest_source_info_.MakeExpressionPosition(expr->position());
+  }
 }
 
 void BytecodeArrayBuilder::SetExpressionAsStatementPosition(Expression* expr) {
   if (expr->position() == RelocInfo::kNoPosition) return;
-  if (exit_seen_in_block_) return;
-  source_position_table_builder_.AddStatementPosition(bytecodes_.size(),
-                                                      expr->position());
+  latest_source_info_.MakeStatementPosition(expr->position());
 }
 
 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const {
   return temporary_register_allocator()->RegisterIsLive(reg);
 }
 
-bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode,
-                                          OperandScale operand_scale,
-                                          int operand_index,
-                                          uint32_t operand_value) const {
-  OperandSize operand_size =
-      Bytecodes::GetOperandSize(bytecode, operand_index, operand_scale);
-  OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index);
-  switch (operand_type) {
-    case OperandType::kNone:
-      return false;
-    case OperandType::kRegCount: {
-      if (operand_index > 0) {
-        OperandType previous_operand_type =
-            Bytecodes::GetOperandType(bytecode, operand_index - 1);
-        if (previous_operand_type != OperandType::kMaybeReg &&
-            previous_operand_type != OperandType::kReg) {
-          return false;
-        }
-      }
-    }  // Fall-through
-    case OperandType::kFlag8:
-    case OperandType::kIdx:
-    case OperandType::kRuntimeId:
-    case OperandType::kImm: {
-      size_t unsigned_value = static_cast<size_t>(operand_value);
-      return SizeForUnsignedOperand(unsigned_value) <= operand_size;
-    }
-    case OperandType::kMaybeReg:
-      if (operand_value == 0) {
-        return true;
-      }
-    // Fall-through to kReg case.
-    case OperandType::kReg:
-    case OperandType::kRegOut: {
-      Register reg = RegisterFromOperand(operand_value);
-      return RegisterIsValid(reg, operand_size);
-    }
-    case OperandType::kRegOutPair:
-    case OperandType::kRegPair: {
-      Register reg0 = RegisterFromOperand(operand_value);
-      Register reg1 = Register(reg0.index() + 1);
-      // The size of reg1 is immaterial.
-      return RegisterIsValid(reg0, operand_size) &&
-             RegisterIsValid(reg1, OperandSize::kQuad);
-    }
-    case OperandType::kRegOutTriple: {
-      Register reg0 = RegisterFromOperand(operand_value);
-      Register reg1 = Register(reg0.index() + 1);
-      Register reg2 = Register(reg0.index() + 2);
-      // The size of reg1 and reg2 is immaterial.
-      return RegisterIsValid(reg0, operand_size) &&
-             RegisterIsValid(reg1, OperandSize::kQuad) &&
-             RegisterIsValid(reg2, OperandSize::kQuad);
-    }
-  }
-  UNREACHABLE();
-  return false;
-}
-
-bool BytecodeArrayBuilder::RegisterIsValid(Register reg,
-                                           OperandSize reg_size) const {
+bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const {
   if (!reg.is_valid()) {
     return false;
   }
 
-  if (SizeForRegisterOperand(reg) > reg_size) {
-    return false;
-  }
-
   if (reg.is_current_context() || reg.is_function_closure() ||
       reg.is_new_target()) {
     return true;
@@ -1186,24 +676,89 @@
   }
 }
 
+bool BytecodeArrayBuilder::OperandsAreValid(
+    Bytecode bytecode, int operand_count, uint32_t operand0, uint32_t operand1,
+    uint32_t operand2, uint32_t operand3) const {
+  if (Bytecodes::NumberOfOperands(bytecode) != operand_count) {
+    return false;
+  }
 
-bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const {
-  return last_bytecode_start_ < bytecodes()->size() &&
-         last_bytecode_start_ >= last_block_end_;
-}
-
-
-bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) {
-  if (LastBytecodeInSameBlock()) {
-    PreviousBytecodeHelper previous_bytecode(*this);
-    Bytecode bytecode = previous_bytecode.GetBytecode();
-    if (bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) {
-      return previous_bytecode.GetRegisterOperand(0) == reg;
+  uint32_t operands[] = {operand0, operand1, operand2, operand3};
+  const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode);
+  for (int i = 0; i < operand_count; ++i) {
+    switch (operand_types[i]) {
+      case OperandType::kNone:
+        return false;
+      case OperandType::kRegCount: {
+        CHECK_NE(i, 0);
+        CHECK(operand_types[i - 1] == OperandType::kMaybeReg ||
+              operand_types[i - 1] == OperandType::kReg);
+        if (i > 0 && operands[i] > 0) {
+          Register start = Register::FromOperand(operands[i - 1]);
+          Register end(start.index() + static_cast<int>(operands[i]) - 1);
+          if (!RegisterIsValid(start) || !RegisterIsValid(end) || start > end) {
+            return false;
+          }
+        }
+        break;
+      }
+      case OperandType::kFlag8:
+      case OperandType::kIntrinsicId:
+        if (Bytecodes::SizeForUnsignedOperand(operands[i]) >
+            OperandSize::kByte) {
+          return false;
+        }
+        break;
+      case OperandType::kRuntimeId:
+        if (Bytecodes::SizeForUnsignedOperand(operands[i]) >
+            OperandSize::kShort) {
+          return false;
+        }
+        break;
+      case OperandType::kIdx:
+        // TODO(oth): Consider splitting OperandType::kIdx into two
+        // operand types. One which is a constant pool index that can
+        // be checked, and the other is an unsigned value.
+        break;
+      case OperandType::kImm:
+        break;
+      case OperandType::kMaybeReg:
+        if (Register::FromOperand(operands[i]) == Register(0)) {
+          break;
+        }
+      // Fall-through to kReg case.
+      case OperandType::kReg:
+      case OperandType::kRegOut: {
+        Register reg = Register::FromOperand(operands[i]);
+        if (!RegisterIsValid(reg)) {
+          return false;
+        }
+        break;
+      }
+      case OperandType::kRegOutPair:
+      case OperandType::kRegPair: {
+        Register reg0 = Register::FromOperand(operands[i]);
+        Register reg1 = Register(reg0.index() + 1);
+        if (!RegisterIsValid(reg0) || !RegisterIsValid(reg1)) {
+          return false;
+        }
+        break;
+      }
+      case OperandType::kRegOutTriple: {
+        Register reg0 = Register::FromOperand(operands[i]);
+        Register reg1 = Register(reg0.index() + 1);
+        Register reg2 = Register(reg0.index() + 2);
+        if (!RegisterIsValid(reg0) || !RegisterIsValid(reg1) ||
+            !RegisterIsValid(reg2)) {
+          return false;
+        }
+        break;
+      }
     }
   }
-  return false;
-}
 
+  return true;
+}
 
 // static
 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) {
@@ -1236,7 +791,6 @@
   }
 }
 
-
 // static
 Bytecode BytecodeArrayBuilder::BytecodeForCountOperation(Token::Value op) {
   switch (op) {
@@ -1250,7 +804,6 @@
   }
 }
 
-
 // static
 Bytecode BytecodeArrayBuilder::BytecodeForCompareOperation(Token::Value op) {
   switch (op) {
@@ -1278,35 +831,33 @@
   }
 }
 
-
 // static
-Bytecode BytecodeArrayBuilder::BytecodeForStoreIC(LanguageMode language_mode) {
-  switch (language_mode) {
-    case SLOPPY:
-      return Bytecode::kStoreICSloppy;
-    case STRICT:
-      return Bytecode::kStoreICStrict;
-    default:
-      UNREACHABLE();
-  }
-  return Bytecode::kIllegal;
-}
-
-
-// static
-Bytecode BytecodeArrayBuilder::BytecodeForKeyedStoreIC(
+Bytecode BytecodeArrayBuilder::BytecodeForStoreNamedProperty(
     LanguageMode language_mode) {
   switch (language_mode) {
     case SLOPPY:
-      return Bytecode::kKeyedStoreICSloppy;
+      return Bytecode::kStaNamedPropertySloppy;
     case STRICT:
-      return Bytecode::kKeyedStoreICStrict;
+      return Bytecode::kStaNamedPropertyStrict;
     default:
       UNREACHABLE();
   }
   return Bytecode::kIllegal;
 }
 
+// static
+Bytecode BytecodeArrayBuilder::BytecodeForStoreKeyedProperty(
+    LanguageMode language_mode) {
+  switch (language_mode) {
+    case SLOPPY:
+      return Bytecode::kStaKeyedPropertySloppy;
+    case STRICT:
+      return Bytecode::kStaKeyedPropertyStrict;
+    default:
+      UNREACHABLE();
+  }
+  return Bytecode::kIllegal;
+}
 
 // static
 Bytecode BytecodeArrayBuilder::BytecodeForLoadGlobal(TypeofMode typeof_mode) {
@@ -1314,7 +865,6 @@
                                       : Bytecode::kLdaGlobal;
 }
 
-
 // static
 Bytecode BytecodeArrayBuilder::BytecodeForStoreGlobal(
     LanguageMode language_mode) {
@@ -1329,7 +879,6 @@
   return Bytecode::kIllegal;
 }
 
-
 // static
 Bytecode BytecodeArrayBuilder::BytecodeForStoreLookupSlot(
     LanguageMode language_mode) {
@@ -1359,7 +908,6 @@
   return Bytecode::kIllegal;
 }
 
-
 // static
 Bytecode BytecodeArrayBuilder::BytecodeForDelete(LanguageMode language_mode) {
   switch (language_mode) {
@@ -1386,108 +934,6 @@
   return Bytecode::kIllegal;
 }
 
-// static
-OperandSize BytecodeArrayBuilder::SizeForRegisterOperand(Register value) {
-  if (value.is_byte_operand()) {
-    return OperandSize::kByte;
-  } else if (value.is_short_operand()) {
-    return OperandSize::kShort;
-  } else {
-    return OperandSize::kQuad;
-  }
-}
-
-// static
-OperandSize BytecodeArrayBuilder::SizeForSignedOperand(int value) {
-  if (kMinInt8 <= value && value <= kMaxInt8) {
-    return OperandSize::kByte;
-  } else if (kMinInt16 <= value && value <= kMaxInt16) {
-    return OperandSize::kShort;
-  } else {
-    return OperandSize::kQuad;
-  }
-}
-
-// static
-OperandSize BytecodeArrayBuilder::SizeForUnsignedOperand(int value) {
-  DCHECK_GE(value, 0);
-  if (value <= kMaxUInt8) {
-    return OperandSize::kByte;
-  } else if (value <= kMaxUInt16) {
-    return OperandSize::kShort;
-  } else {
-    return OperandSize::kQuad;
-  }
-}
-
-OperandSize BytecodeArrayBuilder::SizeForUnsignedOperand(size_t value) {
-  if (value <= static_cast<size_t>(kMaxUInt8)) {
-    return OperandSize::kByte;
-  } else if (value <= static_cast<size_t>(kMaxUInt16)) {
-    return OperandSize::kShort;
-  } else if (value <= kMaxUInt32) {
-    return OperandSize::kQuad;
-  } else {
-    UNREACHABLE();
-    return OperandSize::kQuad;
-  }
-}
-
-OperandScale BytecodeArrayBuilder::OperandSizesToScale(OperandSize size0,
-                                                       OperandSize size1,
-                                                       OperandSize size2,
-                                                       OperandSize size3) {
-  OperandSize upper = std::max(size0, size1);
-  OperandSize lower = std::max(size2, size3);
-  OperandSize result = std::max(upper, lower);
-  // Operand sizes have been scaled before calling this function.
-  // Currently all scalable operands are byte sized at
-  // OperandScale::kSingle.
-  STATIC_ASSERT(static_cast<int>(OperandSize::kByte) ==
-                    static_cast<int>(OperandScale::kSingle) &&
-                static_cast<int>(OperandSize::kShort) ==
-                    static_cast<int>(OperandScale::kDouble) &&
-                static_cast<int>(OperandSize::kQuad) ==
-                    static_cast<int>(OperandScale::kQuadruple));
-  OperandScale operand_scale = static_cast<OperandScale>(result);
-  DCHECK(operand_scale == OperandScale::kSingle ||
-         operand_scale == OperandScale::kDouble ||
-         operand_scale == OperandScale::kQuadruple);
-  return operand_scale;
-}
-
-uint32_t BytecodeArrayBuilder::RegisterOperand(Register reg) {
-  return static_cast<uint32_t>(reg.ToOperand());
-}
-
-Register BytecodeArrayBuilder::RegisterFromOperand(uint32_t operand) {
-  return Register::FromOperand(static_cast<int32_t>(operand));
-}
-
-uint32_t BytecodeArrayBuilder::SignedOperand(int value, OperandSize size) {
-  switch (size) {
-    case OperandSize::kByte:
-      return static_cast<uint8_t>(value & 0xff);
-    case OperandSize::kShort:
-      return static_cast<uint16_t>(value & 0xffff);
-    case OperandSize::kQuad:
-      return static_cast<uint32_t>(value);
-    case OperandSize::kNone:
-      UNREACHABLE();
-  }
-  return 0;
-}
-
-uint32_t BytecodeArrayBuilder::UnsignedOperand(int value) {
-  DCHECK_GE(value, 0);
-  return static_cast<uint32_t>(value);
-}
-
-uint32_t BytecodeArrayBuilder::UnsignedOperand(size_t value) {
-  DCHECK_LE(value, kMaxUInt32);
-  return static_cast<uint32_t>(value);
-}
-
 }  // namespace interpreter
 }  // namespace internal
 }  // namespace v8
diff --git a/src/interpreter/bytecode-array-builder.h b/src/interpreter/bytecode-array-builder.h
index 4446a63..8a10973 100644
--- a/src/interpreter/bytecode-array-builder.h
+++ b/src/interpreter/bytecode-array-builder.h
@@ -6,11 +6,11 @@
 #define V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
 
 #include "src/ast/ast.h"
+#include "src/interpreter/bytecode-array-writer.h"
 #include "src/interpreter/bytecode-register-allocator.h"
 #include "src/interpreter/bytecodes.h"
 #include "src/interpreter/constant-array-builder.h"
 #include "src/interpreter/handler-table-builder.h"
-#include "src/interpreter/source-position-table.h"
 #include "src/zone-containers.h"
 
 namespace v8 {
@@ -21,6 +21,8 @@
 namespace interpreter {
 
 class BytecodeLabel;
+class BytecodeNode;
+class BytecodePipelineStage;
 class Register;
 
 class BytecodeArrayBuilder final : public ZoneObject {
@@ -28,7 +30,6 @@
   BytecodeArrayBuilder(Isolate* isolate, Zone* zone, int parameter_count,
                        int context_count, int locals_count,
                        FunctionLiteral* literal = nullptr);
-  ~BytecodeArrayBuilder();
 
   Handle<BytecodeArray> ToBytecodeArray();
 
@@ -84,8 +85,7 @@
   BytecodeArrayBuilder& LoadFalse();
 
   // Global loads to the accumulator and stores from the accumulator.
-  BytecodeArrayBuilder& LoadGlobal(const Handle<String> name, int feedback_slot,
-                                   TypeofMode typeof_mode);
+  BytecodeArrayBuilder& LoadGlobal(int feedback_slot, TypeofMode typeof_mode);
   BytecodeArrayBuilder& StoreGlobal(const Handle<String> name,
                                     int feedback_slot,
                                     LanguageMode language_mode);
@@ -224,7 +224,7 @@
   BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label);
   BytecodeArrayBuilder& JumpIfUndefined(BytecodeLabel* label);
 
-  BytecodeArrayBuilder& StackCheck();
+  BytecodeArrayBuilder& StackCheck(int position);
 
   BytecodeArrayBuilder& Throw();
   BytecodeArrayBuilder& ReThrow();
@@ -241,6 +241,10 @@
                                   int feedback_slot);
   BytecodeArrayBuilder& ForInStep(Register index);
 
+  // Generators.
+  BytecodeArrayBuilder& SuspendGenerator(Register generator);
+  BytecodeArrayBuilder& ResumeGenerator(Register generator);
+
   // Exception handling.
   BytecodeArrayBuilder& MarkHandler(int handler_id, bool will_catch);
   BytecodeArrayBuilder& MarkTryBegin(int handler_id, Register context);
@@ -257,41 +261,42 @@
   void SetExpressionAsStatementPosition(Expression* expr);
 
   // Accessors
-  Zone* zone() const { return zone_; }
   TemporaryRegisterAllocator* temporary_register_allocator() {
     return &temporary_allocator_;
   }
   const TemporaryRegisterAllocator* temporary_register_allocator() const {
     return &temporary_allocator_;
   }
+  Zone* zone() const { return zone_; }
 
   void EnsureReturn();
 
-  static OperandScale OperandSizesToScale(
-      OperandSize size0, OperandSize size1 = OperandSize::kByte,
-      OperandSize size2 = OperandSize::kByte,
-      OperandSize size3 = OperandSize::kByte);
+  static uint32_t RegisterOperand(Register reg) {
+    return static_cast<uint32_t>(reg.ToOperand());
+  }
 
-  static OperandSize SizeForRegisterOperand(Register reg);
-  static OperandSize SizeForSignedOperand(int value);
-  static OperandSize SizeForUnsignedOperand(int value);
-  static OperandSize SizeForUnsignedOperand(size_t value);
+  static uint32_t SignedOperand(int value) {
+    return static_cast<uint32_t>(value);
+  }
 
-  static uint32_t RegisterOperand(Register reg);
-  static Register RegisterFromOperand(uint32_t operand);
-  static uint32_t SignedOperand(int value, OperandSize size);
-  static uint32_t UnsignedOperand(int value);
-  static uint32_t UnsignedOperand(size_t value);
+  static uint32_t UnsignedOperand(int value) {
+    DCHECK_GE(value, 0);
+    return static_cast<uint32_t>(value);
+  }
+
+  static uint32_t UnsignedOperand(size_t value) {
+    DCHECK_LE(value, kMaxUInt32);
+    return static_cast<uint32_t>(value);
+  }
 
  private:
-  class PreviousBytecodeHelper;
   friend class BytecodeRegisterAllocator;
 
   static Bytecode BytecodeForBinaryOperation(Token::Value op);
   static Bytecode BytecodeForCountOperation(Token::Value op);
   static Bytecode BytecodeForCompareOperation(Token::Value op);
-  static Bytecode BytecodeForStoreIC(LanguageMode language_mode);
-  static Bytecode BytecodeForKeyedStoreIC(LanguageMode language_mode);
+  static Bytecode BytecodeForStoreNamedProperty(LanguageMode language_mode);
+  static Bytecode BytecodeForStoreKeyedProperty(LanguageMode language_mode);
   static Bytecode BytecodeForLoadGlobal(TypeofMode typeof_mode);
   static Bytecode BytecodeForStoreGlobal(LanguageMode language_mode);
   static Bytecode BytecodeForStoreLookupSlot(LanguageMode language_mode);
@@ -299,43 +304,24 @@
   static Bytecode BytecodeForDelete(LanguageMode language_mode);
   static Bytecode BytecodeForCall(TailCallMode tail_call_mode);
 
-  static Bytecode GetJumpWithConstantOperand(Bytecode jump_smi8_operand);
-  static Bytecode GetJumpWithToBoolean(Bytecode jump_smi8_operand);
-
-  template <size_t N>
-  INLINE(void Output(Bytecode bytecode, uint32_t (&operands)[N],
-                     OperandScale operand_scale = OperandScale::kSingle));
+  void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
+              uint32_t operand2, uint32_t operand3);
+  void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
+              uint32_t operand2);
+  void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1);
+  void Output(Bytecode bytecode, uint32_t operand0);
   void Output(Bytecode bytecode);
-  void OutputScaled(Bytecode bytecode, OperandScale operand_scale,
-                    uint32_t operand0, uint32_t operand1, uint32_t operand2,
-                    uint32_t operand3);
-  void OutputScaled(Bytecode bytecode, OperandScale operand_scale,
-                    uint32_t operand0, uint32_t operand1, uint32_t operand2);
-  void OutputScaled(Bytecode bytecode, OperandScale operand_scale,
-                    uint32_t operand0, uint32_t operand1);
-  void OutputScaled(Bytecode bytecode, OperandScale operand_scale,
-                    uint32_t operand0);
 
   BytecodeArrayBuilder& OutputJump(Bytecode jump_bytecode,
                                    BytecodeLabel* label);
-  void PatchJump(const ZoneVector<uint8_t>::iterator& jump_target,
-                 const ZoneVector<uint8_t>::iterator& jump_location);
-  void PatchIndirectJumpWith8BitOperand(
-      const ZoneVector<uint8_t>::iterator& jump_location, int delta);
-  void PatchIndirectJumpWith16BitOperand(
-      const ZoneVector<uint8_t>::iterator& jump_location, int delta);
-  void PatchIndirectJumpWith32BitOperand(
-      const ZoneVector<uint8_t>::iterator& jump_location, int delta);
 
-  void LeaveBasicBlock();
+  bool RegisterIsValid(Register reg) const;
+  bool OperandsAreValid(Bytecode bytecode, int operand_count,
+                        uint32_t operand0 = 0, uint32_t operand1 = 0,
+                        uint32_t operand2 = 0, uint32_t operand3 = 0) const;
 
-  bool OperandIsValid(Bytecode bytecode, OperandScale operand_scale,
-                      int operand_index, uint32_t operand_value) const;
-  bool RegisterIsValid(Register reg, OperandSize reg_size) const;
-
-  bool LastBytecodeInSameBlock() const;
-  bool NeedToBooleanCast();
-  bool IsRegisterInAccumulator(Register reg);
+  // Attach latest source position to |node|.
+  void AttachSourceInfo(BytecodeNode* node);
 
   // Set position for return.
   void SetReturnPosition();
@@ -343,9 +329,18 @@
   // Gets a constant pool entry for the |object|.
   size_t GetConstantPoolEntry(Handle<Object> object);
 
-  ZoneVector<uint8_t>* bytecodes() { return &bytecodes_; }
-  const ZoneVector<uint8_t>* bytecodes() const { return &bytecodes_; }
+  // Not implemented as the illegal bytecode is used inside internally
+  // to indicate a bytecode field is not valid or an error has occured
+  // during bytecode generation.
+  BytecodeArrayBuilder& Illegal();
+
+  void LeaveBasicBlock() { return_seen_in_block_ = false; }
+
   Isolate* isolate() const { return isolate_; }
+  BytecodeArrayWriter* bytecode_array_writer() {
+    return &bytecode_array_writer_;
+  }
+  BytecodePipelineStage* pipeline() { return pipeline_; }
   ConstantArrayBuilder* constant_array_builder() {
     return &constant_array_builder_;
   }
@@ -355,71 +350,25 @@
   HandlerTableBuilder* handler_table_builder() {
     return &handler_table_builder_;
   }
-  SourcePositionTableBuilder* source_position_table_builder() {
-    return &source_position_table_builder_;
-  }
 
   Isolate* isolate_;
   Zone* zone_;
-  ZoneVector<uint8_t> bytecodes_;
   bool bytecode_generated_;
   ConstantArrayBuilder constant_array_builder_;
   HandlerTableBuilder handler_table_builder_;
-  SourcePositionTableBuilder source_position_table_builder_;
-  size_t last_block_end_;
-  size_t last_bytecode_start_;
-  bool exit_seen_in_block_;
-  int unbound_jumps_;
+  bool return_seen_in_block_;
   int parameter_count_;
   int local_register_count_;
   int context_register_count_;
   int return_position_;
   TemporaryRegisterAllocator temporary_allocator_;
+  BytecodeArrayWriter bytecode_array_writer_;
+  BytecodePipelineStage* pipeline_;
+  BytecodeSourceInfo latest_source_info_;
 
   DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder);
 };
 
-
-// A label representing a branch target in a bytecode array. When a
-// label is bound, it represents a known position in the bytecode
-// array. For labels that are forward references there can be at most
-// one reference whilst it is unbound.
-class BytecodeLabel final {
- public:
-  BytecodeLabel() : bound_(false), offset_(kInvalidOffset) {}
-
-  bool is_bound() const { return bound_; }
-  size_t offset() const { return offset_; }
-
- private:
-  static const size_t kInvalidOffset = static_cast<size_t>(-1);
-
-  void bind_to(size_t offset) {
-    DCHECK(!bound_ && offset != kInvalidOffset);
-    offset_ = offset;
-    bound_ = true;
-  }
-
-  void set_referrer(size_t offset) {
-    DCHECK(!bound_ && offset != kInvalidOffset && offset_ == kInvalidOffset);
-    offset_ = offset;
-  }
-
-  bool is_forward_target() const {
-    return offset() != kInvalidOffset && !is_bound();
-  }
-
-  // There are three states for a label:
-  //                    bound_   offset_
-  //  UNSET             false    kInvalidOffset
-  //  FORWARD_TARGET    false    Offset of referring jump
-  //  BACKWARD_TARGET    true    Offset of label in bytecode array when bound
-  bool bound_;
-  size_t offset_;
-
-  friend class BytecodeArrayBuilder;
-};
-
 }  // namespace interpreter
 }  // namespace internal
 }  // namespace v8
diff --git a/src/interpreter/bytecode-array-iterator.cc b/src/interpreter/bytecode-array-iterator.cc
index a17efcb..a4a8f79 100644
--- a/src/interpreter/bytecode-array-iterator.cc
+++ b/src/interpreter/bytecode-array-iterator.cc
@@ -4,6 +4,7 @@
 
 #include "src/interpreter/bytecode-array-iterator.h"
 
+#include "src/interpreter/interpreter-intrinsics.h"
 #include "src/objects-inl.h"
 
 namespace v8 {
@@ -128,34 +129,35 @@
 }
 
 int BytecodeArrayIterator::GetRegisterOperandRange(int operand_index) const {
-  interpreter::OperandType operand_type =
-      Bytecodes::GetOperandType(current_bytecode(), operand_index);
-  DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
-  switch (operand_type) {
-    case OperandType::kRegPair:
-    case OperandType::kRegOutPair:
-      return 2;
-    case OperandType::kRegOutTriple:
-      return 3;
-    default: {
-      if (operand_index + 1 !=
-          Bytecodes::NumberOfOperands(current_bytecode())) {
-        OperandType next_operand_type =
-            Bytecodes::GetOperandType(current_bytecode(), operand_index + 1);
-        if (OperandType::kRegCount == next_operand_type) {
-          return GetRegisterCountOperand(operand_index + 1);
-        }
-      }
-      return 1;
-    }
+  DCHECK_LE(operand_index, Bytecodes::NumberOfOperands(current_bytecode()));
+  const OperandType* operand_types =
+      Bytecodes::GetOperandTypes(current_bytecode());
+  DCHECK(Bytecodes::IsRegisterOperandType(operand_types[operand_index]));
+  if (operand_types[operand_index + 1] == OperandType::kRegCount) {
+    return GetRegisterCountOperand(operand_index + 1);
+  } else {
+    OperandType operand_type = operand_types[operand_index];
+    return Bytecodes::GetNumberOfRegistersRepresentedBy(operand_type);
   }
 }
 
-uint32_t BytecodeArrayIterator::GetRuntimeIdOperand(int operand_index) const {
+Runtime::FunctionId BytecodeArrayIterator::GetRuntimeIdOperand(
+    int operand_index) const {
   OperandType operand_type =
       Bytecodes::GetOperandType(current_bytecode(), operand_index);
   DCHECK(operand_type == OperandType::kRuntimeId);
-  return GetUnsignedOperand(operand_index, operand_type);
+  uint32_t raw_id = GetUnsignedOperand(operand_index, operand_type);
+  return static_cast<Runtime::FunctionId>(raw_id);
+}
+
+Runtime::FunctionId BytecodeArrayIterator::GetIntrinsicIdOperand(
+    int operand_index) const {
+  OperandType operand_type =
+      Bytecodes::GetOperandType(current_bytecode(), operand_index);
+  DCHECK(operand_type == OperandType::kIntrinsicId);
+  uint32_t raw_id = GetUnsignedOperand(operand_index, operand_type);
+  return IntrinsicsHelper::ToRuntimeId(
+      static_cast<IntrinsicsHelper::IntrinsicId>(raw_id));
 }
 
 Handle<Object> BytecodeArrayIterator::GetConstantForIndexOperand(
diff --git a/src/interpreter/bytecode-array-iterator.h b/src/interpreter/bytecode-array-iterator.h
index b372894..90001ef 100644
--- a/src/interpreter/bytecode-array-iterator.h
+++ b/src/interpreter/bytecode-array-iterator.h
@@ -8,6 +8,7 @@
 #include "src/handles.h"
 #include "src/interpreter/bytecodes.h"
 #include "src/objects.h"
+#include "src/runtime/runtime.h"
 
 namespace v8 {
 namespace internal {
@@ -34,7 +35,8 @@
   uint32_t GetRegisterCountOperand(int operand_index) const;
   Register GetRegisterOperand(int operand_index) const;
   int GetRegisterOperandRange(int operand_index) const;
-  uint32_t GetRuntimeIdOperand(int operand_index) const;
+  Runtime::FunctionId GetRuntimeIdOperand(int operand_index) const;
+  Runtime::FunctionId GetIntrinsicIdOperand(int operand_index) const;
   Handle<Object> GetConstantForIndexOperand(int operand_index) const;
 
   // Returns the absolute offset of the branch target at the current
diff --git a/src/interpreter/bytecode-array-writer.cc b/src/interpreter/bytecode-array-writer.cc
new file mode 100644
index 0000000..c476042
--- /dev/null
+++ b/src/interpreter/bytecode-array-writer.cc
@@ -0,0 +1,390 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/interpreter/bytecode-array-writer.h"
+
+#include "src/api.h"
+#include "src/interpreter/bytecode-label.h"
+#include "src/interpreter/constant-array-builder.h"
+#include "src/log.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+BytecodeArrayWriter::BytecodeArrayWriter(
+    Isolate* isolate, Zone* zone, ConstantArrayBuilder* constant_array_builder)
+    : isolate_(isolate),
+      bytecodes_(zone),
+      max_register_count_(0),
+      unbound_jumps_(0),
+      source_position_table_builder_(isolate, zone),
+      constant_array_builder_(constant_array_builder) {
+  LOG_CODE_EVENT(isolate_, CodeStartLinePosInfoRecordEvent(
+                               source_position_table_builder()));
+}
+
+// override
+BytecodeArrayWriter::~BytecodeArrayWriter() {}
+
+// override
+Handle<BytecodeArray> BytecodeArrayWriter::ToBytecodeArray(
+    int fixed_register_count, int parameter_count,
+    Handle<FixedArray> handler_table) {
+  DCHECK_EQ(0, unbound_jumps_);
+
+  int bytecode_size = static_cast<int>(bytecodes()->size());
+
+  // All locals need a frame slot for the debugger, but may not be
+  // present in generated code.
+  int frame_size_for_locals = fixed_register_count * kPointerSize;
+  int frame_size_used = max_register_count() * kPointerSize;
+  int frame_size = std::max(frame_size_for_locals, frame_size_used);
+  Handle<FixedArray> constant_pool = constant_array_builder()->ToFixedArray();
+  Handle<ByteArray> source_position_table =
+      source_position_table_builder()->ToSourcePositionTable();
+  Handle<BytecodeArray> bytecode_array = isolate_->factory()->NewBytecodeArray(
+      bytecode_size, &bytecodes()->front(), frame_size, parameter_count,
+      constant_pool);
+  bytecode_array->set_handler_table(*handler_table);
+  bytecode_array->set_source_position_table(*source_position_table);
+
+  void* line_info = source_position_table_builder()->DetachJITHandlerData();
+  LOG_CODE_EVENT(isolate_, CodeEndLinePosInfoRecordEvent(
+                               AbstractCode::cast(*bytecode_array), line_info));
+  return bytecode_array;
+}
+
+// override
+void BytecodeArrayWriter::Write(BytecodeNode* node) {
+  DCHECK(!Bytecodes::IsJump(node->bytecode()));
+  UpdateSourcePositionTable(node);
+  EmitBytecode(node);
+}
+
+// override
+void BytecodeArrayWriter::WriteJump(BytecodeNode* node, BytecodeLabel* label) {
+  DCHECK(Bytecodes::IsJump(node->bytecode()));
+  UpdateSourcePositionTable(node);
+  EmitJump(node, label);
+}
+
+// override
+void BytecodeArrayWriter::BindLabel(BytecodeLabel* label) {
+  size_t current_offset = bytecodes()->size();
+  if (label->is_forward_target()) {
+    // An earlier jump instruction refers to this label. Update it's location.
+    PatchJump(current_offset, label->offset());
+    // Now treat as if the label will only be back referred to.
+  }
+  label->bind_to(current_offset);
+}
+
+// override
+void BytecodeArrayWriter::BindLabel(const BytecodeLabel& target,
+                                    BytecodeLabel* label) {
+  DCHECK(!label->is_bound());
+  DCHECK(target.is_bound());
+  if (label->is_forward_target()) {
+    // An earlier jump instruction refers to this label. Update it's location.
+    PatchJump(target.offset(), label->offset());
+    // Now treat as if the label will only be back referred to.
+  }
+  label->bind_to(target.offset());
+}
+
+void BytecodeArrayWriter::UpdateSourcePositionTable(
+    const BytecodeNode* const node) {
+  int bytecode_offset = static_cast<int>(bytecodes()->size());
+  const BytecodeSourceInfo& source_info = node->source_info();
+  if (source_info.is_valid()) {
+    source_position_table_builder()->AddPosition(bytecode_offset,
+                                                 source_info.source_position(),
+                                                 source_info.is_statement());
+  }
+}
+
+namespace {
+
+OperandScale ScaleForScalableByteOperand(OperandSize operand_size) {
+  STATIC_ASSERT(static_cast<int>(OperandSize::kByte) ==
+                static_cast<int>(OperandScale::kSingle));
+  STATIC_ASSERT(static_cast<int>(OperandSize::kShort) ==
+                static_cast<int>(OperandScale::kDouble));
+  STATIC_ASSERT(static_cast<int>(OperandSize::kQuad) ==
+                static_cast<int>(OperandScale::kQuadruple));
+  return static_cast<OperandScale>(operand_size);
+}
+
+OperandScale OperandScaleForScalableSignedByte(uint32_t operand_value) {
+  int32_t signed_operand = static_cast<int32_t>(operand_value);
+  OperandSize bytes_required = Bytecodes::SizeForSignedOperand(signed_operand);
+  return ScaleForScalableByteOperand(bytes_required);
+}
+
+OperandScale OperandScaleForScalableUnsignedByte(uint32_t operand_value) {
+  OperandSize bytes_required = Bytecodes::SizeForUnsignedOperand(operand_value);
+  return ScaleForScalableByteOperand(bytes_required);
+}
+
+OperandScale GetOperandScale(const BytecodeNode* const node) {
+  const OperandTypeInfo* operand_type_infos =
+      Bytecodes::GetOperandTypeInfos(node->bytecode());
+  OperandScale operand_scale = OperandScale::kSingle;
+  for (int i = 0; i < node->operand_count(); ++i) {
+    switch (operand_type_infos[i]) {
+      case OperandTypeInfo::kScalableSignedByte: {
+        uint32_t operand = node->operand(i);
+        operand_scale =
+            std::max(operand_scale, OperandScaleForScalableSignedByte(operand));
+        break;
+      }
+      case OperandTypeInfo::kScalableUnsignedByte: {
+        uint32_t operand = node->operand(i);
+        operand_scale = std::max(operand_scale,
+                                 OperandScaleForScalableUnsignedByte(operand));
+        break;
+      }
+      case OperandTypeInfo::kFixedUnsignedByte:
+      case OperandTypeInfo::kFixedUnsignedShort:
+        break;
+      case OperandTypeInfo::kNone:
+        UNREACHABLE();
+        break;
+    }
+  }
+  return operand_scale;
+}
+
+}  // namespace
+
+void BytecodeArrayWriter::EmitBytecode(const BytecodeNode* const node) {
+  DCHECK_NE(node->bytecode(), Bytecode::kIllegal);
+
+  OperandScale operand_scale = GetOperandScale(node);
+  if (operand_scale != OperandScale::kSingle) {
+    Bytecode prefix = Bytecodes::OperandScaleToPrefixBytecode(operand_scale);
+    bytecodes()->push_back(Bytecodes::ToByte(prefix));
+  }
+
+  Bytecode bytecode = node->bytecode();
+  bytecodes()->push_back(Bytecodes::ToByte(bytecode));
+
+  int register_operand_bitmap = Bytecodes::GetRegisterOperandBitmap(bytecode);
+  const uint32_t* const operands = node->operands();
+  const OperandSize* operand_sizes =
+      Bytecodes::GetOperandSizes(bytecode, operand_scale);
+  const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode);
+  for (int i = 0; operand_types[i] != OperandType::kNone; ++i) {
+    OperandType operand_type = operand_types[i];
+    switch (operand_sizes[i]) {
+      case OperandSize::kNone:
+        UNREACHABLE();
+        break;
+      case OperandSize::kByte:
+        bytecodes()->push_back(static_cast<uint8_t>(operands[i]));
+        break;
+      case OperandSize::kShort: {
+        uint8_t operand_bytes[2];
+        WriteUnalignedUInt16(operand_bytes, operands[i]);
+        bytecodes()->insert(bytecodes()->end(), operand_bytes,
+                            operand_bytes + 2);
+        break;
+      }
+      case OperandSize::kQuad: {
+        uint8_t operand_bytes[4];
+        WriteUnalignedUInt32(operand_bytes, operands[i]);
+        bytecodes()->insert(bytecodes()->end(), operand_bytes,
+                            operand_bytes + 4);
+        break;
+      }
+    }
+
+    if ((register_operand_bitmap >> i) & 1) {
+      int count;
+      if (operand_types[i + 1] == OperandType::kRegCount) {
+        count = static_cast<int>(operands[i + 1]);
+      } else {
+        count = Bytecodes::GetNumberOfRegistersRepresentedBy(operand_type);
+      }
+      Register reg = Register::FromOperand(static_cast<int32_t>(operands[i]));
+      max_register_count_ = std::max(max_register_count_, reg.index() + count);
+    }
+  }
+}
+
+// static
+Bytecode GetJumpWithConstantOperand(Bytecode jump_bytecode) {
+  switch (jump_bytecode) {
+    case Bytecode::kJump:
+      return Bytecode::kJumpConstant;
+    case Bytecode::kJumpIfTrue:
+      return Bytecode::kJumpIfTrueConstant;
+    case Bytecode::kJumpIfFalse:
+      return Bytecode::kJumpIfFalseConstant;
+    case Bytecode::kJumpIfToBooleanTrue:
+      return Bytecode::kJumpIfToBooleanTrueConstant;
+    case Bytecode::kJumpIfToBooleanFalse:
+      return Bytecode::kJumpIfToBooleanFalseConstant;
+    case Bytecode::kJumpIfNotHole:
+      return Bytecode::kJumpIfNotHoleConstant;
+    case Bytecode::kJumpIfNull:
+      return Bytecode::kJumpIfNullConstant;
+    case Bytecode::kJumpIfUndefined:
+      return Bytecode::kJumpIfUndefinedConstant;
+    default:
+      UNREACHABLE();
+      return Bytecode::kIllegal;
+  }
+}
+
+void BytecodeArrayWriter::PatchJumpWith8BitOperand(size_t jump_location,
+                                                   int delta) {
+  Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location));
+  DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode));
+  size_t operand_location = jump_location + 1;
+  DCHECK_EQ(bytecodes()->at(operand_location), k8BitJumpPlaceholder);
+  if (Bytecodes::SizeForSignedOperand(delta) == OperandSize::kByte) {
+    // The jump fits within the range of an Imm operand, so cancel
+    // the reservation and jump directly.
+    constant_array_builder()->DiscardReservedEntry(OperandSize::kByte);
+    bytecodes()->at(operand_location) = static_cast<uint8_t>(delta);
+  } else {
+    // The jump does not fit within the range of an Imm operand, so
+    // commit reservation putting the offset into the constant pool,
+    // and update the jump instruction and operand.
+    size_t entry = constant_array_builder()->CommitReservedEntry(
+        OperandSize::kByte, handle(Smi::FromInt(delta), isolate()));
+    DCHECK_LE(entry, kMaxUInt32);
+    DCHECK_EQ(Bytecodes::SizeForUnsignedOperand(static_cast<uint32_t>(entry)),
+              OperandSize::kByte);
+    jump_bytecode = GetJumpWithConstantOperand(jump_bytecode);
+    bytecodes()->at(jump_location) = Bytecodes::ToByte(jump_bytecode);
+    bytecodes()->at(operand_location) = static_cast<uint8_t>(entry);
+  }
+}
+
+void BytecodeArrayWriter::PatchJumpWith16BitOperand(size_t jump_location,
+                                                    int delta) {
+  Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location));
+  DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode));
+  size_t operand_location = jump_location + 1;
+  uint8_t operand_bytes[2];
+  if (Bytecodes::SizeForSignedOperand(delta) <= OperandSize::kShort) {
+    constant_array_builder()->DiscardReservedEntry(OperandSize::kShort);
+    WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(delta));
+  } else {
+    jump_bytecode = GetJumpWithConstantOperand(jump_bytecode);
+    bytecodes()->at(jump_location) = Bytecodes::ToByte(jump_bytecode);
+    size_t entry = constant_array_builder()->CommitReservedEntry(
+        OperandSize::kShort, handle(Smi::FromInt(delta), isolate()));
+    WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry));
+  }
+  DCHECK(bytecodes()->at(operand_location) == k8BitJumpPlaceholder &&
+         bytecodes()->at(operand_location + 1) == k8BitJumpPlaceholder);
+  bytecodes()->at(operand_location++) = operand_bytes[0];
+  bytecodes()->at(operand_location) = operand_bytes[1];
+}
+
+void BytecodeArrayWriter::PatchJumpWith32BitOperand(size_t jump_location,
+                                                    int delta) {
+  DCHECK(Bytecodes::IsJumpImmediate(
+      Bytecodes::FromByte(bytecodes()->at(jump_location))));
+  constant_array_builder()->DiscardReservedEntry(OperandSize::kQuad);
+  uint8_t operand_bytes[4];
+  WriteUnalignedUInt32(operand_bytes, static_cast<uint32_t>(delta));
+  size_t operand_location = jump_location + 1;
+  DCHECK(bytecodes()->at(operand_location) == k8BitJumpPlaceholder &&
+         bytecodes()->at(operand_location + 1) == k8BitJumpPlaceholder &&
+         bytecodes()->at(operand_location + 2) == k8BitJumpPlaceholder &&
+         bytecodes()->at(operand_location + 3) == k8BitJumpPlaceholder);
+  bytecodes()->at(operand_location++) = operand_bytes[0];
+  bytecodes()->at(operand_location++) = operand_bytes[1];
+  bytecodes()->at(operand_location++) = operand_bytes[2];
+  bytecodes()->at(operand_location) = operand_bytes[3];
+}
+
+void BytecodeArrayWriter::PatchJump(size_t jump_target, size_t jump_location) {
+  Bytecode jump_bytecode = Bytecodes::FromByte(bytecodes()->at(jump_location));
+  int delta = static_cast<int>(jump_target - jump_location);
+  int prefix_offset = 0;
+  OperandScale operand_scale = OperandScale::kSingle;
+  if (Bytecodes::IsPrefixScalingBytecode(jump_bytecode)) {
+    // If a prefix scaling bytecode is emitted the target offset is one
+    // less than the case of no prefix scaling bytecode.
+    delta -= 1;
+    prefix_offset = 1;
+    operand_scale = Bytecodes::PrefixBytecodeToOperandScale(jump_bytecode);
+    jump_bytecode =
+        Bytecodes::FromByte(bytecodes()->at(jump_location + prefix_offset));
+  }
+
+  DCHECK(Bytecodes::IsJump(jump_bytecode));
+  switch (operand_scale) {
+    case OperandScale::kSingle:
+      PatchJumpWith8BitOperand(jump_location, delta);
+      break;
+    case OperandScale::kDouble:
+      PatchJumpWith16BitOperand(jump_location + prefix_offset, delta);
+      break;
+    case OperandScale::kQuadruple:
+      PatchJumpWith32BitOperand(jump_location + prefix_offset, delta);
+      break;
+    default:
+      UNREACHABLE();
+  }
+  unbound_jumps_--;
+}
+
+void BytecodeArrayWriter::EmitJump(BytecodeNode* node, BytecodeLabel* label) {
+  DCHECK(Bytecodes::IsJump(node->bytecode()));
+  DCHECK_EQ(0, node->operand(0));
+
+  size_t current_offset = bytecodes()->size();
+
+  if (label->is_bound()) {
+    CHECK_GE(current_offset, label->offset());
+    CHECK_LE(current_offset, static_cast<size_t>(kMaxInt));
+    // Label has been bound already so this is a backwards jump.
+    size_t abs_delta = current_offset - label->offset();
+    int delta = -static_cast<int>(abs_delta);
+    OperandSize operand_size = Bytecodes::SizeForSignedOperand(delta);
+    if (operand_size > OperandSize::kByte) {
+      // Adjust for scaling byte prefix for wide jump offset.
+      DCHECK_LE(delta, 0);
+      delta -= 1;
+    }
+    node->set_bytecode(node->bytecode(), delta);
+  } else {
+    // The label has not yet been bound so this is a forward reference
+    // that will be patched when the label is bound. We create a
+    // reservation in the constant pool so the jump can be patched
+    // when the label is bound. The reservation means the maximum size
+    // of the operand for the constant is known and the jump can
+    // be emitted into the bytecode stream with space for the operand.
+    unbound_jumps_++;
+    label->set_referrer(current_offset);
+    OperandSize reserved_operand_size =
+        constant_array_builder()->CreateReservedEntry();
+    switch (reserved_operand_size) {
+      case OperandSize::kNone:
+        UNREACHABLE();
+        break;
+      case OperandSize::kByte:
+        node->set_bytecode(node->bytecode(), k8BitJumpPlaceholder);
+        break;
+      case OperandSize::kShort:
+        node->set_bytecode(node->bytecode(), k16BitJumpPlaceholder);
+        break;
+      case OperandSize::kQuad:
+        node->set_bytecode(node->bytecode(), k32BitJumpPlaceholder);
+        break;
+    }
+  }
+  EmitBytecode(node);
+}
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
diff --git a/src/interpreter/bytecode-array-writer.h b/src/interpreter/bytecode-array-writer.h
new file mode 100644
index 0000000..76d881e
--- /dev/null
+++ b/src/interpreter/bytecode-array-writer.h
@@ -0,0 +1,80 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_INTERPRETER_BYTECODE_ARRAY_WRITER_H_
+#define V8_INTERPRETER_BYTECODE_ARRAY_WRITER_H_
+
+#include "src/interpreter/bytecode-pipeline.h"
+#include "src/interpreter/source-position-table.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+class BytecodeLabel;
+class SourcePositionTableBuilder;
+class ConstantArrayBuilder;
+
+// Class for emitting bytecode as the final stage of the bytecode
+// generation pipeline.
+class BytecodeArrayWriter final : public BytecodePipelineStage {
+ public:
+  BytecodeArrayWriter(Isolate* isolate, Zone* zone,
+                      ConstantArrayBuilder* constant_array_builder);
+  virtual ~BytecodeArrayWriter();
+
+  // BytecodePipelineStage interface.
+  void Write(BytecodeNode* node) override;
+  void WriteJump(BytecodeNode* node, BytecodeLabel* label) override;
+  void BindLabel(BytecodeLabel* label) override;
+  void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override;
+  Handle<BytecodeArray> ToBytecodeArray(
+      int fixed_register_count, int parameter_count,
+      Handle<FixedArray> handler_table) override;
+
+ private:
+  // Constants that act as placeholders for jump operands to be
+  // patched. These have operand sizes that match the sizes of
+  // reserved constant pool entries.
+  const uint32_t k8BitJumpPlaceholder = 0x7f;
+  const uint32_t k16BitJumpPlaceholder =
+      k8BitJumpPlaceholder | (k8BitJumpPlaceholder << 8);
+  const uint32_t k32BitJumpPlaceholder =
+      k16BitJumpPlaceholder | (k16BitJumpPlaceholder << 16);
+
+  void PatchJump(size_t jump_target, size_t jump_location);
+  void PatchJumpWith8BitOperand(size_t jump_location, int delta);
+  void PatchJumpWith16BitOperand(size_t jump_location, int delta);
+  void PatchJumpWith32BitOperand(size_t jump_location, int delta);
+
+  void EmitBytecode(const BytecodeNode* const node);
+  void EmitJump(BytecodeNode* node, BytecodeLabel* label);
+  void UpdateSourcePositionTable(const BytecodeNode* const node);
+
+  Isolate* isolate() { return isolate_; }
+  ZoneVector<uint8_t>* bytecodes() { return &bytecodes_; }
+  SourcePositionTableBuilder* source_position_table_builder() {
+    return &source_position_table_builder_;
+  }
+  ConstantArrayBuilder* constant_array_builder() {
+    return constant_array_builder_;
+  }
+  int max_register_count() { return max_register_count_; }
+
+  Isolate* isolate_;
+  ZoneVector<uint8_t> bytecodes_;
+  int max_register_count_;
+  int unbound_jumps_;
+  SourcePositionTableBuilder source_position_table_builder_;
+  ConstantArrayBuilder* constant_array_builder_;
+
+  friend class BytecodeArrayWriterUnittest;
+  DISALLOW_COPY_AND_ASSIGN(BytecodeArrayWriter);
+};
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_INTERPRETER_BYTECODE_ARRAY_WRITER_H_
diff --git a/src/interpreter/bytecode-dead-code-optimizer.cc b/src/interpreter/bytecode-dead-code-optimizer.cc
new file mode 100644
index 0000000..964d2a8
--- /dev/null
+++ b/src/interpreter/bytecode-dead-code-optimizer.cc
@@ -0,0 +1,77 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/interpreter/bytecode-dead-code-optimizer.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+BytecodeDeadCodeOptimizer::BytecodeDeadCodeOptimizer(
+    BytecodePipelineStage* next_stage)
+    : next_stage_(next_stage), exit_seen_in_block_(false) {}
+
+// override
+Handle<BytecodeArray> BytecodeDeadCodeOptimizer::ToBytecodeArray(
+    int fixed_register_count, int parameter_count,
+    Handle<FixedArray> handler_table) {
+  return next_stage_->ToBytecodeArray(fixed_register_count, parameter_count,
+                                      handler_table);
+}
+
+// override
+void BytecodeDeadCodeOptimizer::Write(BytecodeNode* node) {
+  // Don't emit dead code.
+  if (exit_seen_in_block_) return;
+
+  switch (node->bytecode()) {
+    case Bytecode::kReturn:
+    case Bytecode::kThrow:
+    case Bytecode::kReThrow:
+      exit_seen_in_block_ = true;
+      break;
+    default:
+      break;
+  }
+
+  next_stage_->Write(node);
+}
+
+// override
+void BytecodeDeadCodeOptimizer::WriteJump(BytecodeNode* node,
+                                          BytecodeLabel* label) {
+  // Don't emit dead code.
+  // TODO(rmcilroy): For forward jumps we could mark the label as dead, thereby
+  // avoiding emitting dead code when we bind the label.
+  if (exit_seen_in_block_) return;
+
+  switch (node->bytecode()) {
+    case Bytecode::kJump:
+    case Bytecode::kJumpConstant:
+      exit_seen_in_block_ = true;
+      break;
+    default:
+      break;
+  }
+
+  next_stage_->WriteJump(node, label);
+}
+
+// override
+void BytecodeDeadCodeOptimizer::BindLabel(BytecodeLabel* label) {
+  next_stage_->BindLabel(label);
+  exit_seen_in_block_ = false;
+}
+
+// override
+void BytecodeDeadCodeOptimizer::BindLabel(const BytecodeLabel& target,
+                                          BytecodeLabel* label) {
+  next_stage_->BindLabel(target, label);
+  // exit_seen_in_block_ was reset when target was bound, so shouldn't be
+  // changed here.
+}
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
diff --git a/src/interpreter/bytecode-dead-code-optimizer.h b/src/interpreter/bytecode-dead-code-optimizer.h
new file mode 100644
index 0000000..8d68e54
--- /dev/null
+++ b/src/interpreter/bytecode-dead-code-optimizer.h
@@ -0,0 +1,41 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_INTERPRETER_BYTECODE_DEAD_CODE_OPTIMIZER_H_
+#define V8_INTERPRETER_BYTECODE_DEAD_CODE_OPTIMIZER_H_
+
+#include "src/interpreter/bytecode-pipeline.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+// An optimization stage for eliminating obviously dead code in bytecode
+// generation.
+class BytecodeDeadCodeOptimizer final : public BytecodePipelineStage,
+                                        public ZoneObject {
+ public:
+  explicit BytecodeDeadCodeOptimizer(BytecodePipelineStage* next_stage);
+
+  // BytecodePipelineStage interface.
+  void Write(BytecodeNode* node) override;
+  void WriteJump(BytecodeNode* node, BytecodeLabel* label) override;
+  void BindLabel(BytecodeLabel* label) override;
+  void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override;
+  Handle<BytecodeArray> ToBytecodeArray(
+      int fixed_register_count, int parameter_count,
+      Handle<FixedArray> handler_table) override;
+
+ private:
+  BytecodePipelineStage* next_stage_;
+  bool exit_seen_in_block_;
+
+  DISALLOW_COPY_AND_ASSIGN(BytecodeDeadCodeOptimizer);
+};
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_INTERPRETER_BYTECODE_DEAD_CODE_OPTIMIZER_H_
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
index b0fa245..b7cfd49 100644
--- a/src/interpreter/bytecode-generator.cc
+++ b/src/interpreter/bytecode-generator.cc
@@ -5,6 +5,7 @@
 #include "src/interpreter/bytecode-generator.h"
 
 #include "src/ast/scopes.h"
+#include "src/code-stubs.h"
 #include "src/compiler.h"
 #include "src/interpreter/bytecode-register-allocator.h"
 #include "src/interpreter/control-flow-builders.h"
@@ -16,7 +17,6 @@
 namespace internal {
 namespace interpreter {
 
-
 // Scoped class tracking context objects created by the visitor. Represents
 // mutations of the context chain within the function body, allowing pushing and
 // popping of the current {context_register} during visitation.
@@ -87,7 +87,6 @@
   bool should_pop_context_;
 };
 
-
 // Scoped class for tracking control statements entered by the
 // visitor. The pattern derives AstGraphBuilder::ControlScope.
 class BytecodeGenerator::ControlScope BASE_EMBEDDED {
@@ -123,7 +122,6 @@
   DISALLOW_COPY_AND_ASSIGN(ControlScope);
 };
 
-
 // Helper class for a try-finally control scope. It can record intercepted
 // control-flow commands that cause entry into a finally-block, and re-apply
 // them after again leaving that block. Special tokens are used to identify
@@ -202,7 +200,6 @@
   Register result_register_;
 };
 
-
 // Scoped class for dealing with control flow reaching the function level.
 class BytecodeGenerator::ControlScopeForTopLevel final
     : public BytecodeGenerator::ControlScope {
@@ -227,7 +224,6 @@
   }
 };
 
-
 // Scoped class for enabling break inside blocks and switch blocks.
 class BytecodeGenerator::ControlScopeForBreakable final
     : public BytecodeGenerator::ControlScope {
@@ -259,7 +255,6 @@
   BreakableControlFlowBuilder* control_builder_;
 };
 
-
 // Scoped class for enabling 'break' and 'continue' in iteration
 // constructs, e.g. do...while, while..., for...
 class BytecodeGenerator::ControlScopeForIteration final
@@ -294,7 +289,6 @@
   LoopBuilder* loop_builder_;
 };
 
-
 // Scoped class for enabling 'throw' in try-catch constructs.
 class BytecodeGenerator::ControlScopeForTryCatch final
     : public BytecodeGenerator::ControlScope {
@@ -323,7 +317,6 @@
   }
 };
 
-
 // Scoped class for enabling control flow through try-finally constructs.
 class BytecodeGenerator::ControlScopeForTryFinally final
     : public BytecodeGenerator::ControlScope {
@@ -359,7 +352,6 @@
   DeferredCommands* commands_;
 };
 
-
 void BytecodeGenerator::ControlScope::PerformCommand(Command command,
                                                      Statement* statement) {
   ControlScope* current = this;
@@ -382,7 +374,6 @@
   UNREACHABLE();
 }
 
-
 class BytecodeGenerator::RegisterAllocationScope {
  public:
   explicit RegisterAllocationScope(BytecodeGenerator* generator)
@@ -440,7 +431,6 @@
   DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope);
 };
 
-
 // Scoped base class for determining where the result of an expression
 // is stored.
 class BytecodeGenerator::ExpressionResultScope {
@@ -488,7 +478,6 @@
   DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope);
 };
 
-
 // Scoped class used when the result of the current expression is not
 // expected to produce a result.
 class BytecodeGenerator::EffectResultScope final
@@ -503,7 +492,6 @@
   virtual void SetResultInRegister(Register reg) {}
 };
 
-
 // Scoped class used when the result of the current expression to be
 // evaluated should go into the interpreter's accumulator register.
 class BytecodeGenerator::AccumulatorResultScope final
@@ -520,7 +508,6 @@
   }
 };
 
-
 // Scoped class used when the result of the current expression to be
 // evaluated should go into an interpreter register.
 class BytecodeGenerator::RegisterResultScope final
@@ -554,38 +541,41 @@
   Register result_register_;
 };
 
-BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone)
-    : isolate_(isolate),
-      zone_(zone),
-      builder_(nullptr),
-      info_(nullptr),
-      scope_(nullptr),
-      globals_(0, zone),
+BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
+    : isolate_(info->isolate()),
+      zone_(info->zone()),
+      builder_(new (zone()) BytecodeArrayBuilder(
+          info->isolate(), info->zone(), info->num_parameters_including_this(),
+          info->scope()->MaxNestedContextChainLength(),
+          info->scope()->num_stack_slots(), info->literal())),
+      info_(info),
+      scope_(info->scope()),
+      globals_(0, info->zone()),
       execution_control_(nullptr),
       execution_context_(nullptr),
       execution_result_(nullptr),
       register_allocator_(nullptr),
+      generator_resume_points_(info->literal()->yield_count(), info->zone()),
+      generator_state_(),
       try_catch_nesting_level_(0),
       try_finally_nesting_level_(0) {
-  InitializeAstVisitor(isolate);
+  InitializeAstVisitor(isolate());
 }
 
-Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
-  set_info(info);
-  set_scope(info->scope());
-
-  // Initialize bytecode array builder.
-  set_builder(new (zone()) BytecodeArrayBuilder(
-      isolate(), zone(), info->num_parameters_including_this(),
-      scope()->MaxNestedContextChainLength(), scope()->num_stack_slots(),
-      info->literal()));
-
+Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() {
   // Initialize the incoming context.
   ContextScope incoming_context(this, scope(), false);
 
   // Initialize control scope.
   ControlScopeForTopLevel control(this);
 
+  RegisterAllocationScope register_scope(this);
+
+  if (IsResumableFunction(info()->literal()->kind())) {
+    generator_state_ = register_allocator()->NewRegister();
+    VisitGeneratorPrologue();
+  }
+
   // Build function context only if there are context allocated variables.
   if (scope()->NeedsContext()) {
     // Push a new inner context scope for the function.
@@ -597,13 +587,18 @@
     MakeBytecodeBody();
   }
 
+  // In generator functions, we may not have visited every yield in the AST
+  // since we skip some obviously dead code. Hence the generated bytecode may
+  // contain jumps to unbound labels (resume points that will never be used).
+  // We bind these now.
+  for (auto& label : generator_resume_points_) {
+    if (!label.is_bound()) builder()->Bind(&label);
+  }
+
   builder()->EnsureReturn();
-  set_scope(nullptr);
-  set_info(nullptr);
   return builder()->ToBytecodeArray();
 }
 
-
 void BytecodeGenerator::MakeBytecodeBody() {
   // Build the arguments object if it is used.
   VisitArgumentsObject(scope()->arguments());
@@ -628,12 +623,87 @@
   VisitDeclarations(scope()->declarations());
 
   // Perform a stack-check before the body.
-  builder()->StackCheck();
+  builder()->StackCheck(info()->literal()->start_position());
 
   // Visit statements in the function body.
   VisitStatements(info()->literal()->body());
 }
 
+void BytecodeGenerator::BuildIndexedJump(Register index, size_t start_index,
+                                         size_t size,
+                                         ZoneVector<BytecodeLabel>& targets) {
+  // TODO(neis): Optimize this by using a proper jump table.
+  for (size_t i = start_index; i < start_index + size; i++) {
+    DCHECK(0 <= i && i < targets.size());
+    builder()
+        ->LoadLiteral(Smi::FromInt(static_cast<int>(i)))
+        .CompareOperation(Token::Value::EQ_STRICT, index)
+        .JumpIfTrue(&(targets[i]));
+  }
+
+  BuildAbort(BailoutReason::kInvalidJumpTableIndex);
+}
+
+void BytecodeGenerator::VisitIterationHeader(IterationStatement* stmt,
+                                             LoopBuilder* loop_builder) {
+  // Recall that stmt->yield_count() is always zero inside ordinary
+  // (i.e. non-generator) functions.
+
+  // Collect all labels for generator resume points within the loop (if any) so
+  // that they can be bound to the loop header below. Also create fresh labels
+  // for these resume points, to be used inside the loop.
+  ZoneVector<BytecodeLabel> resume_points_in_loop(zone());
+  size_t first_yield = stmt->first_yield_id();
+  for (size_t id = first_yield; id < first_yield + stmt->yield_count(); id++) {
+    DCHECK(0 <= id && id < generator_resume_points_.size());
+    auto& label = generator_resume_points_[id];
+    resume_points_in_loop.push_back(label);
+    generator_resume_points_[id] = BytecodeLabel();
+  }
+
+  loop_builder->LoopHeader(&resume_points_in_loop);
+
+  if (stmt->yield_count() > 0) {
+    // If we are not resuming, fall through to loop body.
+    // If we are resuming, perform state dispatch.
+    BytecodeLabel not_resuming;
+    builder()
+        ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
+        .CompareOperation(Token::Value::EQ, generator_state_)
+        .JumpIfTrue(&not_resuming);
+    BuildIndexedJump(generator_state_, first_yield,
+        stmt->yield_count(), generator_resume_points_);
+    builder()->Bind(&not_resuming);
+  }
+}
+
+void BytecodeGenerator::VisitGeneratorPrologue() {
+  // The generator resume trampoline abuses the new.target register both to
+  // indicate that this is a resume call and to pass in the generator object.
+  // In ordinary calls, new.target is always undefined because generator
+  // functions are non-constructable.
+  Register generator_object = Register::new_target();
+  BytecodeLabel regular_call;
+  builder()
+      ->LoadAccumulatorWithRegister(generator_object)
+      .JumpIfUndefined(&regular_call);
+
+  // This is a resume call. Restore registers and perform state dispatch.
+  // (The current context has already been restored by the trampoline.)
+  builder()
+      ->ResumeGenerator(generator_object)
+      .StoreAccumulatorInRegister(generator_state_);
+  BuildIndexedJump(generator_state_, 0, generator_resume_points_.size(),
+                   generator_resume_points_);
+
+  builder()
+      ->Bind(&regular_call)
+      .LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
+      .StoreAccumulatorInRegister(generator_state_);
+  // This is a regular call. Fall through to the ordinary function prologue,
+  // after which we will run into the generator object creation and other extra
+  // code inserted by the parser.
+}
 
 void BytecodeGenerator::VisitBlock(Block* stmt) {
   // Visit declarations and statements.
@@ -646,7 +716,6 @@
   }
 }
 
-
 void BytecodeGenerator::VisitBlockDeclarationsAndStatements(Block* stmt) {
   BlockBuilder block_builder(builder());
   ControlScopeForBreakable execution_control(this, stmt, &block_builder);
@@ -657,23 +726,19 @@
   if (stmt->labels() != nullptr) block_builder.EndBlock();
 }
 
-
 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
   Variable* variable = decl->proxy()->var();
   VariableMode mode = decl->mode();
   // Const and let variables are initialized with the hole so that we can
   // check that they are only assigned once.
-  bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
+  bool hole_init = mode == CONST || mode == LET;
   switch (variable->location()) {
     case VariableLocation::GLOBAL:
-    case VariableLocation::UNALLOCATED: {
-      Handle<Oddball> value = variable->binding_needs_init()
-                                  ? isolate()->factory()->the_hole_value()
-                                  : isolate()->factory()->undefined_value();
+    case VariableLocation::UNALLOCATED:
+      DCHECK(!variable->binding_needs_init());
       globals()->push_back(variable->name());
-      globals()->push_back(value);
+      globals()->push_back(isolate()->factory()->undefined_value());
       break;
-    }
     case VariableLocation::LOCAL:
       if (hole_init) {
         Register destination(variable->index());
@@ -695,34 +760,20 @@
       }
       break;
     case VariableLocation::LOOKUP: {
-      DCHECK(IsDeclaredVariableMode(mode));
+      DCHECK_EQ(VAR, mode);
+      DCHECK(!hole_init);
 
-      register_allocator()->PrepareForConsecutiveAllocations(3);
-      Register name = register_allocator()->NextConsecutiveRegister();
-      Register init_value = register_allocator()->NextConsecutiveRegister();
-      Register attributes = register_allocator()->NextConsecutiveRegister();
+      Register name = register_allocator()->NewRegister();
 
-      builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name);
-      if (hole_init) {
-        builder()->LoadTheHole().StoreAccumulatorInRegister(init_value);
-      } else {
-        // For variables, we must not use an initial value (such as 'undefined')
-        // because we may have a (legal) redeclaration and we must not destroy
-        // the current value.
-        builder()
-            ->LoadLiteral(Smi::FromInt(0))
-            .StoreAccumulatorInRegister(init_value);
-      }
       builder()
-          ->LoadLiteral(Smi::FromInt(variable->DeclarationPropertyAttributes()))
-          .StoreAccumulatorInRegister(attributes)
-          .CallRuntime(Runtime::kDeclareLookupSlot, name, 3);
+          ->LoadLiteral(variable->name())
+          .StoreAccumulatorInRegister(name)
+          .CallRuntime(Runtime::kDeclareEvalVar, name, 1);
       break;
     }
   }
 }
 
-
 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
   Variable* variable = decl->proxy()->var();
   switch (variable->location()) {
@@ -753,33 +804,26 @@
       break;
     }
     case VariableLocation::LOOKUP: {
-      register_allocator()->PrepareForConsecutiveAllocations(3);
+      register_allocator()->PrepareForConsecutiveAllocations(2);
       Register name = register_allocator()->NextConsecutiveRegister();
       Register literal = register_allocator()->NextConsecutiveRegister();
-      Register attributes = register_allocator()->NextConsecutiveRegister();
       builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name);
 
       VisitForAccumulatorValue(decl->fun());
-      builder()
-          ->StoreAccumulatorInRegister(literal)
-          .LoadLiteral(Smi::FromInt(variable->DeclarationPropertyAttributes()))
-          .StoreAccumulatorInRegister(attributes)
-          .CallRuntime(Runtime::kDeclareLookupSlot, name, 3);
+      builder()->StoreAccumulatorInRegister(literal).CallRuntime(
+          Runtime::kDeclareEvalFunction, name, 2);
     }
   }
 }
 
-
 void BytecodeGenerator::VisitImportDeclaration(ImportDeclaration* decl) {
   UNIMPLEMENTED();
 }
 
-
 void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) {
   UNIMPLEMENTED();
 }
 
-
 void BytecodeGenerator::VisitDeclarations(
     ZoneList<Declaration*>* declarations) {
   RegisterAllocationScope register_scope(this);
@@ -793,9 +837,7 @@
   Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
       static_cast<int>(globals()->size()), TENURED);
   for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
-  int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
-                      DeclareGlobalsNativeFlag::encode(info()->is_native()) |
-                      DeclareGlobalsLanguageMode::encode(language_mode());
+  int encoded_flags = info()->GetDeclareGlobalsFlags();
 
   Register pairs = register_allocator()->NewRegister();
   builder()->LoadLiteral(data);
@@ -810,7 +852,6 @@
   globals()->clear();
 }
 
-
 void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
   for (int i = 0; i < statements->length(); i++) {
     // Allocate an outer register allocations scope for the statement.
@@ -821,17 +862,14 @@
   }
 }
 
-
 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
   builder()->SetStatementPosition(stmt);
   VisitForEffect(stmt->expression());
 }
 
-
 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
 }
 
-
 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
   builder()->SetStatementPosition(stmt);
   BytecodeLabel else_label, end_label;
@@ -861,32 +899,27 @@
   }
 }
 
-
 void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
     SloppyBlockFunctionStatement* stmt) {
   Visit(stmt->statement());
 }
 
-
 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
   builder()->SetStatementPosition(stmt);
   execution_control()->Continue(stmt->target());
 }
 
-
 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
   builder()->SetStatementPosition(stmt);
   execution_control()->Break(stmt->target());
 }
 
-
 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
   builder()->SetStatementPosition(stmt);
   VisitForAccumulatorValue(stmt->expression());
   execution_control()->ReturnAccumulator();
 }
 
-
 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
   builder()->SetStatementPosition(stmt);
   VisitForAccumulatorValue(stmt->expression());
@@ -895,7 +928,6 @@
   VisitInScope(stmt->statement(), stmt->scope());
 }
 
-
 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
   // We need this scope because we visit for register values. We have to
   // maintain a execution result scope where registers can be allocated.
@@ -946,7 +978,6 @@
   switch_builder.SetBreakTarget(done_label);
 }
 
-
 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) {
   // Handled entirely in VisitSwitchStatement.
   UNREACHABLE();
@@ -955,23 +986,21 @@
 void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt,
                                            LoopBuilder* loop_builder) {
   ControlScopeForIteration execution_control(this, stmt, loop_builder);
-  builder()->StackCheck();
+  builder()->StackCheck(stmt->position());
   Visit(stmt->body());
+  loop_builder->SetContinueTarget();
 }
 
 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
   LoopBuilder loop_builder(builder());
-  loop_builder.LoopHeader();
+  VisitIterationHeader(stmt, &loop_builder);
   if (stmt->cond()->ToBooleanIsFalse()) {
     VisitIterationBody(stmt, &loop_builder);
-    loop_builder.Condition();
   } else if (stmt->cond()->ToBooleanIsTrue()) {
-    loop_builder.Condition();
     VisitIterationBody(stmt, &loop_builder);
     loop_builder.JumpToHeader();
   } else {
     VisitIterationBody(stmt, &loop_builder);
-    loop_builder.Condition();
     builder()->SetExpressionAsStatementPosition(stmt->cond());
     VisitForAccumulatorValue(stmt->cond());
     loop_builder.JumpToHeaderIfTrue();
@@ -986,8 +1015,7 @@
   }
 
   LoopBuilder loop_builder(builder());
-  loop_builder.LoopHeader();
-  loop_builder.Condition();
+  VisitIterationHeader(stmt, &loop_builder);
   if (!stmt->cond()->ToBooleanIsTrue()) {
     builder()->SetExpressionAsStatementPosition(stmt->cond());
     VisitForAccumulatorValue(stmt->cond());
@@ -998,7 +1026,6 @@
   loop_builder.EndLoop();
 }
 
-
 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
   if (stmt->init() != nullptr) {
     Visit(stmt->init());
@@ -1010,8 +1037,7 @@
   }
 
   LoopBuilder loop_builder(builder());
-  loop_builder.LoopHeader();
-  loop_builder.Condition();
+  VisitIterationHeader(stmt, &loop_builder);
   if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) {
     builder()->SetExpressionAsStatementPosition(stmt->cond());
     VisitForAccumulatorValue(stmt->cond());
@@ -1019,7 +1045,6 @@
   }
   VisitIterationBody(stmt, &loop_builder);
   if (stmt->next() != nullptr) {
-    loop_builder.Next();
     builder()->SetStatementPosition(stmt->next());
     Visit(stmt->next());
   }
@@ -1027,7 +1052,6 @@
   loop_builder.EndLoop();
 }
 
-
 void BytecodeGenerator::VisitForInAssignment(Expression* expr,
                                              FeedbackVectorSlot slot) {
   DCHECK(expr->IsValidReferenceExpression());
@@ -1101,7 +1125,6 @@
   }
 }
 
-
 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
   if (stmt->subject()->IsNullLiteral() ||
       stmt->subject()->IsUndefinedLiteral()) {
@@ -1135,9 +1158,8 @@
   builder()->StoreAccumulatorInRegister(index);
 
   // The loop
-  loop_builder.LoopHeader();
+  VisitIterationHeader(stmt, &loop_builder);
   builder()->SetExpressionAsStatementPosition(stmt->each());
-  loop_builder.Condition();
   builder()->ForInDone(index, cache_length);
   loop_builder.BreakIfTrue();
   DCHECK(Register::AreContiguous(cache_type, cache_array));
@@ -1146,7 +1168,6 @@
   loop_builder.ContinueIfUndefined();
   VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot());
   VisitIterationBody(stmt, &loop_builder);
-  loop_builder.Next();
   builder()->ForInStep(index);
   builder()->StoreAccumulatorInRegister(index);
   loop_builder.JumpToHeader();
@@ -1155,15 +1176,14 @@
   builder()->Bind(&subject_undefined_label);
 }
 
-
 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
   LoopBuilder loop_builder(builder());
   ControlScopeForIteration control_scope(this, stmt, &loop_builder);
 
+  builder()->SetExpressionAsStatementPosition(stmt->assign_iterator());
   VisitForEffect(stmt->assign_iterator());
 
-  loop_builder.LoopHeader();
-  loop_builder.Next();
+  VisitIterationHeader(stmt, &loop_builder);
   builder()->SetExpressionAsStatementPosition(stmt->next_result());
   VisitForEffect(stmt->next_result());
   VisitForAccumulatorValue(stmt->result_done());
@@ -1175,7 +1195,6 @@
   loop_builder.EndLoop();
 }
 
-
 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
   TryCatchBuilder try_control_builder(builder());
   Register no_reg;
@@ -1212,7 +1231,6 @@
   try_control_builder.EndCatch();
 }
 
-
 void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
   TryFinallyBuilder try_control_builder(builder(), IsInsideTryCatch());
   Register no_reg;
@@ -1277,13 +1295,11 @@
   commands.ApplyDeferredCommands();
 }
 
-
 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
   builder()->SetStatementPosition(stmt);
   builder()->Debugger();
 }
 
-
 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
   // Find or build a shared function info.
   Handle<SharedFunctionInfo> shared_info =
@@ -1296,7 +1312,6 @@
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
   if (expr->scope()->ContextLocalCount() > 0) {
     VisitNewLocalBlockContext(expr->scope());
@@ -1324,7 +1339,7 @@
       .StoreAccumulatorInRegister(prototype);
 
   VisitClassLiteralProperties(expr, literal, prototype);
-  builder()->CallRuntime(Runtime::kFinalizeClassDefinition, literal, 2);
+  builder()->CallRuntime(Runtime::kToFastProperties, literal, 1);
   // Assign to class variable.
   if (expr->class_variable_proxy() != nullptr) {
     Variable* var = expr->class_variable_proxy()->var();
@@ -1454,13 +1469,11 @@
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) {
   VisitBlock(expr->block());
   VisitVariableProxy(expr->result());
 }
 
-
 void BytecodeGenerator::VisitConditional(Conditional* expr) {
   // TODO(rmcilroy): Spot easy cases where there code would not need to
   // emit the then block or the else block, e.g. condition is
@@ -1481,21 +1494,20 @@
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitLiteral(Literal* expr) {
   if (!execution_result()->IsEffect()) {
     Handle<Object> value = expr->value();
     if (value->IsSmi()) {
       builder()->LoadLiteral(Smi::cast(*value));
-    } else if (value->IsUndefined()) {
+    } else if (value->IsUndefined(isolate())) {
       builder()->LoadUndefined();
-    } else if (value->IsTrue()) {
+    } else if (value->IsTrue(isolate())) {
       builder()->LoadTrue();
-    } else if (value->IsFalse()) {
+    } else if (value->IsFalse(isolate())) {
       builder()->LoadFalse();
-    } else if (value->IsNull()) {
+    } else if (value->IsNull(isolate())) {
       builder()->LoadNull();
-    } else if (value->IsTheHole()) {
+    } else if (value->IsTheHole(isolate())) {
       builder()->LoadTheHole();
     } else {
       builder()->LoadLiteral(value);
@@ -1504,7 +1516,6 @@
   }
 }
 
-
 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
   // Materialize a regular expression literal.
   builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(),
@@ -1512,12 +1523,22 @@
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
-  // Deep-copy the literal boilerplate.
+  // Copy the literal boilerplate.
+  int fast_clone_properties_count = 0;
+  if (FastCloneShallowObjectStub::IsSupported(expr)) {
+    STATIC_ASSERT(
+        FastCloneShallowObjectStub::kMaximumClonedProperties <=
+        1 << CreateObjectLiteralFlags::FastClonePropertiesCountBits::kShift);
+    fast_clone_properties_count =
+        FastCloneShallowObjectStub::PropertiesCount(expr->properties_count());
+  }
+  uint8_t flags =
+      CreateObjectLiteralFlags::FlagsBits::encode(expr->ComputeFlags()) |
+      CreateObjectLiteralFlags::FastClonePropertiesCountBits::encode(
+          fast_clone_properties_count);
   builder()->CreateObjectLiteral(expr->constant_properties(),
-                                 expr->literal_index(),
-                                 expr->ComputeFlags(true));
+                                 expr->literal_index(), flags);
 
   // Allocate in the outer scope since this register is used to return the
   // expression's results to the caller.
@@ -1705,7 +1726,6 @@
   execution_result()->SetResultInRegister(literal);
 }
 
-
 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
   // Deep-copy the literal boilerplate.
   builder()->CreateArrayLiteral(expr->constant_elements(),
@@ -1745,7 +1765,6 @@
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
   builder()->SetExpressionPosition(proxy);
   VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
@@ -1753,10 +1772,7 @@
 
 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode,
                                                       Handle<String> name) {
-  if (mode == CONST_LEGACY) {
-    BytecodeLabel end_label;
-    builder()->JumpIfNotHole(&end_label).LoadUndefined().Bind(&end_label);
-  } else if (mode == LET || mode == CONST) {
+  if (mode == LET || mode == CONST) {
     BuildThrowIfHole(name);
   }
 }
@@ -1784,8 +1800,7 @@
     }
     case VariableLocation::GLOBAL:
     case VariableLocation::UNALLOCATED: {
-      builder()->LoadGlobal(variable->name(), feedback_index(slot),
-                            typeof_mode);
+      builder()->LoadGlobal(feedback_index(slot), typeof_mode);
       execution_result()->SetResultInAccumulator();
       break;
     }
@@ -1874,6 +1889,15 @@
   builder()->CallRuntime(function_id, receiver, 4);
 }
 
+void BytecodeGenerator::BuildAbort(BailoutReason bailout_reason) {
+  RegisterAllocationScope register_scope(this);
+  Register reason = register_allocator()->NewRegister();
+  builder()
+      ->LoadLiteral(Smi::FromInt(static_cast<int>(bailout_reason)))
+      .StoreAccumulatorInRegister(reason)
+      .CallRuntime(Runtime::kAbort, reason, 1);
+}
+
 void BytecodeGenerator::BuildThrowReferenceError(Handle<String> name) {
   RegisterAllocationScope register_scope(this);
   Register name_reg = register_allocator()->NewRegister();
@@ -1940,7 +1964,7 @@
   RegisterAllocationScope assignment_register_scope(this);
   BytecodeLabel end_label;
   bool hole_check_required =
-      (mode == CONST_LEGACY) || (mode == LET && op != Token::INIT) ||
+      (mode == LET && op != Token::INIT) ||
       (mode == CONST && op != Token::INIT) ||
       (mode == CONST && op == Token::INIT && variable->is_this());
   switch (variable->location()) {
@@ -1953,6 +1977,16 @@
         destination = Register(variable->index());
       }
 
+      if (mode == CONST_LEGACY && op != Token::INIT) {
+        if (is_strict(language_mode())) {
+          builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(),
+                                 0);
+        }
+        // Non-initializing assignments to legacy constants are ignored
+        // in sloppy mode. Break here to avoid storing into variable.
+        break;
+      }
+
       if (hole_check_required) {
         // Load destination to check for hole.
         Register value_temp = register_allocator()->NewRegister();
@@ -1960,28 +1994,9 @@
             ->StoreAccumulatorInRegister(value_temp)
             .LoadAccumulatorWithRegister(destination);
 
-        if (mode == CONST_LEGACY && op == Token::INIT) {
-          // Perform an intialization check for legacy constants.
-          builder()
-              ->JumpIfNotHole(&end_label)
-              .MoveRegister(value_temp, destination)
-              .Bind(&end_label)
-              .LoadAccumulatorWithRegister(value_temp);
-          // Break here because the value should not be stored unconditionally.
-          break;
-        } else if (mode == CONST_LEGACY && op != Token::INIT) {
-          DCHECK(!is_strict(language_mode()));
-          // Ensure accumulator is in the correct state.
-          builder()->LoadAccumulatorWithRegister(value_temp);
-          // Break here, non-initializing assignments to legacy constants are
-          // ignored.
-          break;
-        } else {
-          BuildHoleCheckForVariableAssignment(variable, op);
-          builder()->LoadAccumulatorWithRegister(value_temp);
-        }
+        BuildHoleCheckForVariableAssignment(variable, op);
+        builder()->LoadAccumulatorWithRegister(value_temp);
       }
-
       builder()->StoreAccumulatorInRegister(destination);
       break;
     }
@@ -2018,6 +2033,16 @@
         builder()->LoadAccumulatorWithRegister(value_temp);
       }
 
+      if (mode == CONST_LEGACY && op != Token::INIT) {
+        if (is_strict(language_mode())) {
+          builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(),
+                                 0);
+        }
+        // Non-initializing assignments to legacy constants are ignored
+        // in sloppy mode. Break here to avoid storing into variable.
+        break;
+      }
+
       if (hole_check_required) {
         // Load destination to check for hole.
         Register value_temp = register_allocator()->NewRegister();
@@ -2025,61 +2050,21 @@
             ->StoreAccumulatorInRegister(value_temp)
             .LoadContextSlot(context_reg, variable->index());
 
-        if (mode == CONST_LEGACY && op == Token::INIT) {
-          // Perform an intialization check for legacy constants.
-          builder()
-              ->JumpIfNotHole(&end_label)
-              .LoadAccumulatorWithRegister(value_temp)
-              .StoreContextSlot(context_reg, variable->index())
-              .Bind(&end_label);
-          builder()->LoadAccumulatorWithRegister(value_temp);
-          // Break here because the value should not be stored unconditionally.
-          // The above code performs the store conditionally.
-          break;
-        } else if (mode == CONST_LEGACY && op != Token::INIT) {
-          DCHECK(!is_strict(language_mode()));
-          // Ensure accumulator is in the correct state.
-          builder()->LoadAccumulatorWithRegister(value_temp);
-          // Break here, non-initializing assignments to legacy constants are
-          // ignored.
-          break;
-        } else {
-          BuildHoleCheckForVariableAssignment(variable, op);
-          builder()->LoadAccumulatorWithRegister(value_temp);
-        }
+        BuildHoleCheckForVariableAssignment(variable, op);
+        builder()->LoadAccumulatorWithRegister(value_temp);
       }
 
       builder()->StoreContextSlot(context_reg, variable->index());
       break;
     }
     case VariableLocation::LOOKUP: {
-      if (mode == CONST_LEGACY && op == Token::INIT) {
-        register_allocator()->PrepareForConsecutiveAllocations(3);
-        Register value = register_allocator()->NextConsecutiveRegister();
-        Register context = register_allocator()->NextConsecutiveRegister();
-        Register name = register_allocator()->NextConsecutiveRegister();
-
-        // InitializeLegacyConstLookupSlot runtime call returns the 'value'
-        // passed to it. So, accumulator will have its original contents when
-        // runtime call returns.
-        builder()
-            ->StoreAccumulatorInRegister(value)
-            .MoveRegister(execution_context()->reg(), context)
-            .LoadLiteral(variable->name())
-            .StoreAccumulatorInRegister(name)
-            .CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, value, 3);
-      } else if (mode == CONST_LEGACY && op != Token::INIT) {
-        // Non-intializing assignments to legacy constants are ignored.
-        DCHECK(!is_strict(language_mode()));
-      } else {
-        builder()->StoreLookupSlot(variable->name(), language_mode());
-      }
+      DCHECK_NE(CONST_LEGACY, variable->mode());
+      builder()->StoreLookupSlot(variable->name(), language_mode());
       break;
     }
   }
 }
 
-
 void BytecodeGenerator::VisitAssignment(Assignment* expr) {
   DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
   Register object, key, home_object, value;
@@ -2224,22 +2209,90 @@
   execution_result()->SetResultInAccumulator();
 }
 
+void BytecodeGenerator::VisitYield(Yield* expr) {
+  builder()->SetExpressionPosition(expr);
+  Register value = VisitForRegisterValue(expr->expression());
 
-void BytecodeGenerator::VisitYield(Yield* expr) { UNIMPLEMENTED(); }
+  Register generator = VisitForRegisterValue(expr->generator_object());
 
+  // Save context, registers, and state. Then return.
+  builder()
+      ->LoadLiteral(Smi::FromInt(expr->yield_id()))
+      .SuspendGenerator(generator)
+      .LoadAccumulatorWithRegister(value)
+      .Return();  // Hard return (ignore any finally blocks).
+
+  builder()->Bind(&(generator_resume_points_[expr->yield_id()]));
+  // Upon resume, we continue here.
+
+  {
+    RegisterAllocationScope register_scope(this);
+
+    // Update state to indicate that we have finished resuming. Loop headers
+    // rely on this.
+    builder()
+        ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
+        .StoreAccumulatorInRegister(generator_state_);
+
+    Register input = register_allocator()->NewRegister();
+    builder()
+        ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator, 1)
+        .StoreAccumulatorInRegister(input);
+
+    Register resume_mode = register_allocator()->NewRegister();
+    builder()
+        ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator, 1)
+        .StoreAccumulatorInRegister(resume_mode);
+
+    // Now dispatch on resume mode.
+
+    BytecodeLabel resume_with_next;
+    BytecodeLabel resume_with_return;
+    BytecodeLabel resume_with_throw;
+
+    builder()
+        ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext))
+        .CompareOperation(Token::EQ_STRICT, resume_mode)
+        .JumpIfTrue(&resume_with_next)
+        .LoadLiteral(Smi::FromInt(JSGeneratorObject::kThrow))
+        .CompareOperation(Token::EQ_STRICT, resume_mode)
+        .JumpIfTrue(&resume_with_throw)
+        .Jump(&resume_with_return);
+
+    builder()->Bind(&resume_with_return);
+    {
+      register_allocator()->PrepareForConsecutiveAllocations(2);
+      Register value = register_allocator()->NextConsecutiveRegister();
+      Register done = register_allocator()->NextConsecutiveRegister();
+      builder()
+          ->MoveRegister(input, value)
+          .LoadTrue()
+          .StoreAccumulatorInRegister(done)
+          .CallRuntime(Runtime::kInlineCreateIterResultObject, value, 2);
+      execution_control()->ReturnAccumulator();
+    }
+
+    builder()->Bind(&resume_with_throw);
+    builder()->SetExpressionPosition(expr);
+    builder()->LoadAccumulatorWithRegister(input).Throw();
+
+    builder()->Bind(&resume_with_next);
+    builder()->LoadAccumulatorWithRegister(input);
+  }
+  execution_result()->SetResultInAccumulator();
+}
 
 void BytecodeGenerator::VisitThrow(Throw* expr) {
   VisitForAccumulatorValue(expr->exception());
   builder()->SetExpressionPosition(expr);
   builder()->Throw();
-  // Throw statments are modeled as expression instead of statments. These are
-  // converted from assignment statements in Rewriter::ReWrite pass. An
+  // Throw statements are modeled as expressions instead of statements. These
+  // are converted from assignment statements in Rewriter::ReWrite pass. An
   // assignment statement expects a value in the accumulator. This is a hack to
   // avoid DCHECK fails assert accumulator has been set.
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
   LhsKind property_kind = Property::GetAssignType(expr);
   FeedbackVectorSlot slot = expr->PropertyFeedbackSlot();
@@ -2452,12 +2505,14 @@
   // callee value.
   if (call_type == Call::POSSIBLY_EVAL_CALL && args->length() > 0) {
     RegisterAllocationScope inner_register_scope(this);
-    register_allocator()->PrepareForConsecutiveAllocations(5);
+    register_allocator()->PrepareForConsecutiveAllocations(6);
     Register callee_for_eval = register_allocator()->NextConsecutiveRegister();
     Register source = register_allocator()->NextConsecutiveRegister();
     Register function = register_allocator()->NextConsecutiveRegister();
     Register language = register_allocator()->NextConsecutiveRegister();
-    Register position = register_allocator()->NextConsecutiveRegister();
+    Register eval_scope_position =
+        register_allocator()->NextConsecutiveRegister();
+    Register eval_position = register_allocator()->NextConsecutiveRegister();
 
     // Set up arguments for ResolvePossiblyDirectEval by copying callee, source
     // strings and function closure, and loading language and
@@ -2470,11 +2525,13 @@
         .StoreAccumulatorInRegister(language)
         .LoadLiteral(
             Smi::FromInt(execution_context()->scope()->start_position()))
-        .StoreAccumulatorInRegister(position);
+        .StoreAccumulatorInRegister(eval_scope_position)
+        .LoadLiteral(Smi::FromInt(expr->position()))
+        .StoreAccumulatorInRegister(eval_position);
 
     // Call ResolvePossiblyDirectEval and modify the callee.
     builder()
-        ->CallRuntime(Runtime::kResolvePossiblyDirectEval, callee_for_eval, 5)
+        ->CallRuntime(Runtime::kResolvePossiblyDirectEval, callee_for_eval, 6)
         .StoreAccumulatorInRegister(callee);
   }
 
@@ -2529,7 +2586,6 @@
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   if (expr->is_jsruntime()) {
@@ -2550,14 +2606,12 @@
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
   VisitForEffect(expr->expression());
   builder()->LoadUndefined();
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
   if (expr->expression()->IsVariableProxy()) {
     // Typeof does not throw a reference error on global variables, hence we
@@ -2572,14 +2626,12 @@
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
   VisitForAccumulatorValue(expr->expression());
   builder()->LogicalNot();
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
   switch (expr->op()) {
     case Token::Value::NOT:
@@ -2605,7 +2657,6 @@
   }
 }
 
-
 void BytecodeGenerator::VisitDelete(UnaryOperation* expr) {
   if (expr->expression()->IsProperty()) {
     // Delete of an object property is allowed both in sloppy
@@ -2667,7 +2718,6 @@
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
   DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
 
@@ -2739,13 +2789,12 @@
     }
   }
 
-  // Convert old value into a number.
-  builder()->CastAccumulatorToNumber();
-
   // Save result for postfix expressions.
   if (is_postfix) {
     old_value = register_allocator()->outer()->NewRegister();
-    builder()->StoreAccumulatorInRegister(old_value);
+
+    // Convert old value into a number before saving it.
+    builder()->CastAccumulatorToNumber().StoreAccumulatorInRegister(old_value);
   }
 
   // Perform +1/-1 operation.
@@ -2790,7 +2839,6 @@
   }
 }
 
-
 void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) {
   switch (binop->op()) {
     case Token::COMMA:
@@ -2808,7 +2856,6 @@
   }
 }
 
-
 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
   Register lhs = VisitForRegisterValue(expr->left());
   VisitForAccumulatorValue(expr->right());
@@ -2817,7 +2864,6 @@
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
   Register lhs = VisitForRegisterValue(expr->left());
   VisitForAccumulatorValue(expr->right());
@@ -2825,39 +2871,32 @@
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
 
-
 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
   UNREACHABLE();
 }
 
-
 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) {
   execution_result()->SetResultInRegister(Register::function_closure());
 }
 
-
 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {
   // Handled by VisitCall().
   UNREACHABLE();
 }
 
-
 void BytecodeGenerator::VisitSuperPropertyReference(
     SuperPropertyReference* expr) {
   builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError, Register(0), 0);
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
   VisitForEffect(binop->left());
   Visit(binop->right());
 }
 
-
 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
   Expression* left = binop->left();
   Expression* right = binop->right();
@@ -2876,7 +2915,6 @@
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
   Expression* left = binop->left();
   Expression* right = binop->right();
@@ -2895,12 +2933,10 @@
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) {
   Visit(expr->expression());
 }
 
-
 void BytecodeGenerator::VisitNewLocalFunctionContext() {
   AccumulatorResultScope accumulator_execution_result(this);
   Scope* scope = this->scope();
@@ -2924,7 +2960,6 @@
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitBuildLocalActivationContext() {
   Scope* scope = this->scope();
 
@@ -2953,7 +2988,6 @@
   }
 }
 
-
 void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) {
   AccumulatorResultScope accumulator_execution_result(this);
   DCHECK(scope->is_block_scope());
@@ -3007,7 +3041,6 @@
   execution_result()->SetResultInAccumulator();
 }
 
-
 void BytecodeGenerator::VisitObjectLiteralAccessor(
     Register home_object, ObjectLiteralProperty* property, Register value_out) {
   // TODO(rmcilroy): Replace value_out with VisitForRegister();
@@ -3033,7 +3066,6 @@
   }
 }
 
-
 void BytecodeGenerator::VisitArgumentsObject(Variable* variable) {
   if (variable == nullptr) return;
 
@@ -3068,7 +3100,6 @@
   VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
 }
 
-
 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
   if (variable == nullptr) return;
 
@@ -3077,7 +3108,6 @@
   VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
 }
 
-
 void BytecodeGenerator::VisitFunctionClosureForContext() {
   AccumulatorResultScope accumulator_execution_result(this);
   Scope* closure_scope = execution_context()->scope()->ClosureScope();
@@ -3104,7 +3134,6 @@
   execution_result()->SetResultInAccumulator();
 }
 
-
 // Visits the expression |expr| and places the result in the accumulator.
 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) {
   AccumulatorResultScope accumulator_scope(this);
@@ -3125,7 +3154,6 @@
   Visit(expr);
 }
 
-
 // Visits the expression |expr| and returns the register containing
 // the expression result.
 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) {
@@ -3149,14 +3177,12 @@
   Visit(stmt);
 }
 
-
 LanguageMode BytecodeGenerator::language_mode() const {
   return execution_context()->scope()->language_mode();
 }
 
-
 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
-  return info()->shared_info()->feedback_vector()->GetIndex(slot);
+  return TypeFeedbackVector::GetIndex(slot);
 }
 
 }  // namespace interpreter
diff --git a/src/interpreter/bytecode-generator.h b/src/interpreter/bytecode-generator.h
index 4ef1738..3adca6b 100644
--- a/src/interpreter/bytecode-generator.h
+++ b/src/interpreter/bytecode-generator.h
@@ -7,19 +7,23 @@
 
 #include "src/ast/ast.h"
 #include "src/interpreter/bytecode-array-builder.h"
+#include "src/interpreter/bytecode-label.h"
 #include "src/interpreter/bytecodes.h"
 
 namespace v8 {
 namespace internal {
+
+class CompilationInfo;
+
 namespace interpreter {
 
 class LoopBuilder;
 
 class BytecodeGenerator final : public AstVisitor {
  public:
-  BytecodeGenerator(Isolate* isolate, Zone* zone);
+  explicit BytecodeGenerator(CompilationInfo* info);
 
-  Handle<BytecodeArray> MakeBytecode(CompilationInfo* info);
+  Handle<BytecodeArray> MakeBytecode();
 
 #define DECLARE_VISIT(type) void Visit##type(type* node) override;
   AST_NODE_LIST(DECLARE_VISIT)
@@ -102,6 +106,7 @@
   void BuildKeyedSuperPropertyLoad(Register receiver, Register home_object,
                                    Register key);
 
+  void BuildAbort(BailoutReason bailout_reason);
   void BuildThrowIfHole(Handle<String> name);
   void BuildThrowIfNotHole(Handle<String> name);
   void BuildThrowReassignConstant(Handle<String> name);
@@ -109,6 +114,13 @@
   void BuildHoleCheckForVariableLoad(VariableMode mode, Handle<String> name);
   void BuildHoleCheckForVariableAssignment(Variable* variable, Token::Value op);
 
+  // Build jump to targets[value], where
+  // start_index <= value < start_index + size.
+  void BuildIndexedJump(Register value, size_t start_index, size_t size,
+                        ZoneVector<BytecodeLabel>& targets);
+
+  void VisitGeneratorPrologue();
+
   void VisitArgumentsObject(Variable* variable);
   void VisitRestArgumentsArray(Variable* rest);
   void VisitCallSuper(Call* call);
@@ -133,7 +145,9 @@
                                   Register value_out);
   void VisitForInAssignment(Expression* expr, FeedbackVectorSlot slot);
 
-  // Visit the body of a loop iteration.
+  // Visit the header/body of a loop iteration.
+  void VisitIterationHeader(IterationStatement* stmt,
+                            LoopBuilder* loop_builder);
   void VisitIterationBody(IterationStatement* stmt, LoopBuilder* loop_builder);
 
   // Visit a statement and switch scopes, the context is in the accumulator.
@@ -159,16 +173,11 @@
   template <size_t N>
   void InitializeWithConsecutiveRegisters(Register (&registers)[N]);
 
-  inline void set_builder(BytecodeArrayBuilder* builder) { builder_ = builder; }
   inline BytecodeArrayBuilder* builder() const { return builder_; }
-
   inline Isolate* isolate() const { return isolate_; }
   inline Zone* zone() const { return zone_; }
-
   inline Scope* scope() const { return scope_; }
-  inline void set_scope(Scope* scope) { scope_ = scope; }
   inline CompilationInfo* info() const { return info_; }
-  inline void set_info(CompilationInfo* info) { info_ = info; }
 
   inline ControlScope* execution_control() const { return execution_control_; }
   inline void set_execution_control(ControlScope* scope) {
@@ -204,6 +213,8 @@
   ContextScope* execution_context_;
   ExpressionResultScope* execution_result_;
   RegisterAllocationScope* register_allocator_;
+  ZoneVector<BytecodeLabel> generator_resume_points_;
+  Register generator_state_;
   int try_catch_nesting_level_;
   int try_finally_nesting_level_;
 };
diff --git a/src/interpreter/bytecode-label.h b/src/interpreter/bytecode-label.h
new file mode 100644
index 0000000..2f89c48
--- /dev/null
+++ b/src/interpreter/bytecode-label.h
@@ -0,0 +1,56 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_INTERPRETER_BYTECODE_LABEL_H_
+#define V8_INTERPRETER_BYTECODE_LABEL_H_
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+// A label representing a branch target in a bytecode array. When a
+// label is bound, it represents a known position in the bytecode
+// array. For labels that are forward references there can be at most
+// one reference whilst it is unbound.
+class BytecodeLabel final {
+ public:
+  BytecodeLabel() : bound_(false), offset_(kInvalidOffset) {}
+
+  bool is_bound() const { return bound_; }
+  size_t offset() const { return offset_; }
+
+ private:
+  static const size_t kInvalidOffset = static_cast<size_t>(-1);
+
+  void bind_to(size_t offset) {
+    DCHECK(!bound_ && offset != kInvalidOffset);
+    offset_ = offset;
+    bound_ = true;
+  }
+
+  void set_referrer(size_t offset) {
+    DCHECK(!bound_ && offset != kInvalidOffset && offset_ == kInvalidOffset);
+    offset_ = offset;
+  }
+
+  bool is_forward_target() const {
+    return offset() != kInvalidOffset && !is_bound();
+  }
+
+  // There are three states for a label:
+  //                    bound_   offset_
+  //  UNSET             false    kInvalidOffset
+  //  FORWARD_TARGET    false    Offset of referring jump
+  //  BACKWARD_TARGET    true    Offset of label in bytecode array when bound
+  bool bound_;
+  size_t offset_;
+
+  friend class BytecodeArrayWriter;
+};
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_INTERPRETER_BYTECODE_LABEL_H_
diff --git a/src/interpreter/bytecode-peephole-optimizer.cc b/src/interpreter/bytecode-peephole-optimizer.cc
new file mode 100644
index 0000000..1108d83
--- /dev/null
+++ b/src/interpreter/bytecode-peephole-optimizer.cc
@@ -0,0 +1,327 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/interpreter/bytecode-peephole-optimizer.h"
+
+#include "src/interpreter/constant-array-builder.h"
+#include "src/objects-inl.h"
+#include "src/objects.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+BytecodePeepholeOptimizer::BytecodePeepholeOptimizer(
+    ConstantArrayBuilder* constant_array_builder,
+    BytecodePipelineStage* next_stage)
+    : constant_array_builder_(constant_array_builder), next_stage_(next_stage) {
+  InvalidateLast();
+}
+
+// override
+Handle<BytecodeArray> BytecodePeepholeOptimizer::ToBytecodeArray(
+    int fixed_register_count, int parameter_count,
+    Handle<FixedArray> handler_table) {
+  Flush();
+  return next_stage_->ToBytecodeArray(fixed_register_count, parameter_count,
+                                      handler_table);
+}
+
+// override
+void BytecodePeepholeOptimizer::Write(BytecodeNode* node) {
+  node = OptimizeAndEmitLast(node);
+  if (node != nullptr) {
+    SetLast(node);
+  }
+}
+
+// override
+void BytecodePeepholeOptimizer::WriteJump(BytecodeNode* node,
+                                          BytecodeLabel* label) {
+  node = OptimizeAndEmitLast(node);
+  next_stage_->WriteJump(node, label);
+}
+
+// override
+void BytecodePeepholeOptimizer::BindLabel(BytecodeLabel* label) {
+  Flush();
+  next_stage_->BindLabel(label);
+}
+
+// override
+void BytecodePeepholeOptimizer::BindLabel(const BytecodeLabel& target,
+                                          BytecodeLabel* label) {
+  // There is no need to flush here, it will have been flushed when |target|
+  // was bound.
+  next_stage_->BindLabel(target, label);
+}
+
+void BytecodePeepholeOptimizer::Flush() {
+  // TODO(oth/rmcilroy): We could check CanElideLast() here to potentially
+  // eliminate last rather than writing it.
+  if (LastIsValid()) {
+    next_stage_->Write(&last_);
+    InvalidateLast();
+  }
+}
+
+void BytecodePeepholeOptimizer::InvalidateLast() {
+  last_.set_bytecode(Bytecode::kIllegal);
+}
+
+bool BytecodePeepholeOptimizer::LastIsValid() const {
+  return last_.bytecode() != Bytecode::kIllegal;
+}
+
+void BytecodePeepholeOptimizer::SetLast(const BytecodeNode* const node) {
+  last_.Clone(node);
+}
+
+Handle<Object> BytecodePeepholeOptimizer::GetConstantForIndexOperand(
+    const BytecodeNode* const node, int index) const {
+  DCHECK_LE(index, node->operand_count());
+  DCHECK_EQ(Bytecodes::GetOperandType(node->bytecode(), 0), OperandType::kIdx);
+  uint32_t index_operand = node->operand(0);
+  return constant_array_builder_->At(index_operand);
+}
+
+bool BytecodePeepholeOptimizer::LastBytecodePutsNameInAccumulator() const {
+  DCHECK(LastIsValid());
+  return (last_.bytecode() == Bytecode::kTypeOf ||
+          last_.bytecode() == Bytecode::kToName ||
+          (last_.bytecode() == Bytecode::kLdaConstant &&
+           GetConstantForIndexOperand(&last_, 0)->IsName()));
+}
+
+void BytecodePeepholeOptimizer::TryToRemoveLastExpressionPosition(
+    const BytecodeNode* const current) {
+  if (current->source_info().is_valid() &&
+      last_.source_info().is_expression() &&
+      Bytecodes::IsWithoutExternalSideEffects(last_.bytecode())) {
+    // The last bytecode has been marked as expression. It has no
+    // external effects so can't throw and the current bytecode is a
+    // source position. Remove the expression position on the last
+    // bytecode to open up potential peephole optimizations and to
+    // save the memory and perf cost of storing the unneeded
+    // expression position.
+    last_.source_info().set_invalid();
+  }
+}
+
+bool BytecodePeepholeOptimizer::CanElideCurrent(
+    const BytecodeNode* const current) const {
+  if (Bytecodes::IsLdarOrStar(last_.bytecode()) &&
+      Bytecodes::IsLdarOrStar(current->bytecode()) &&
+      current->operand(0) == last_.operand(0)) {
+    // Ldar and Star make the accumulator and register hold equivalent
+    // values. Only the first bytecode is needed if there's a sequence
+    // of back-to-back Ldar and Star bytecodes with the same operand.
+    return true;
+  } else if (current->bytecode() == Bytecode::kToName &&
+             LastBytecodePutsNameInAccumulator()) {
+    // If the previous bytecode ensured a name was in the accumulator,
+    // the type coercion ToName() can be elided.
+    return true;
+  } else {
+    // Additional candidates for eliding current:
+    // (i) ToNumber if the last puts a number in the accumulator.
+    return false;
+  }
+}
+
+bool BytecodePeepholeOptimizer::CanElideLastBasedOnSourcePosition(
+    const BytecodeNode* const current) const {
+  //
+  // The rules for allowing the elision of the last bytecode based
+  // on source position are:
+  //
+  //                     C U R R E N T
+  //              +--------+--------+--------+
+  //              |  None  |  Expr  |  Stmt  |
+  //  L  +--------+--------+--------+--------+
+  //     |  None  |  YES   |  YES   |  YES   |
+  //  A  +--------+--------+--------+--------+
+  //     |  Expr  |  YES   | MAYBE  |  MAYBE |
+  //  S  +--------+--------+--------+--------+
+  //     |  Stmt  |  YES   |   NO   |   NO   |
+  //  T  +--------+--------+--------+--------+
+  //
+  // The goal is not lose any statement positions and not lose useful
+  // expression positions. Whenever the last bytecode is elided it's
+  // source position information is applied to the current node
+  // updating it if necessary.
+  //
+  // The last bytecode can be elided for the MAYBE cases if the last
+  // bytecode is known not to throw. If it throws, the system would
+  // not have correct stack trace information. The appropriate check
+  // for this would be Bytecodes::IsWithoutExternalSideEffects(),
+  // which is checked in
+  // BytecodePeepholeOptimizer::TransformLastAndCurrentBytecodes() to
+  // keep the check here simple.
+  //
+  // In rare cases, bytecode generation produces consecutive bytecodes
+  // with the same expression positions. In principle, the latter of
+  // these can be elided, but would make this function more expensive.
+  //
+  return (!last_.source_info().is_valid() ||
+          !current->source_info().is_valid());
+}
+
+namespace {
+
+void TransformLdaStarToLdrLdar(Bytecode new_bytecode, BytecodeNode* const last,
+                               BytecodeNode* const current) {
+  DCHECK_EQ(current->bytecode(), Bytecode::kStar);
+
+  //
+  // An example transformation here would be:
+  //
+  //   LdaGlobal i0, i1  ____\  LdrGlobal i0, i1, R
+  //   Star R            ====/  Ldar R
+  //
+  // which loads a global value into both a register and the
+  // accumulator. However, in the second form the Ldar can often be
+  // peephole optimized away unlike the Star in the first form.
+  //
+  last->Transform(new_bytecode, current->operand(0));
+  current->set_bytecode(Bytecode::kLdar, current->operand(0));
+}
+
+}  // namespace
+
+bool BytecodePeepholeOptimizer::TransformLastAndCurrentBytecodes(
+    BytecodeNode* const current) {
+  if (current->bytecode() == Bytecode::kStar &&
+      !current->source_info().is_statement()) {
+    // Note: If the Star is tagged with a statement position, we can't
+    // perform this transform as the store to the register will
+    // have the wrong ordering for stepping in the debugger.
+    switch (last_.bytecode()) {
+      case Bytecode::kLdaNamedProperty:
+        TransformLdaStarToLdrLdar(Bytecode::kLdrNamedProperty, &last_, current);
+        return true;
+      case Bytecode::kLdaKeyedProperty:
+        TransformLdaStarToLdrLdar(Bytecode::kLdrKeyedProperty, &last_, current);
+        return true;
+      case Bytecode::kLdaGlobal:
+        TransformLdaStarToLdrLdar(Bytecode::kLdrGlobal, &last_, current);
+        return true;
+      case Bytecode::kLdaContextSlot:
+        TransformLdaStarToLdrLdar(Bytecode::kLdrContextSlot, &last_, current);
+        return true;
+      case Bytecode::kLdaUndefined:
+        TransformLdaStarToLdrLdar(Bytecode::kLdrUndefined, &last_, current);
+        return true;
+      default:
+        break;
+    }
+  }
+  return false;
+}
+
+bool BytecodePeepholeOptimizer::RemoveToBooleanFromJump(
+    BytecodeNode* const current) {
+  bool can_remove = Bytecodes::IsJumpIfToBoolean(current->bytecode()) &&
+                    Bytecodes::WritesBooleanToAccumulator(last_.bytecode());
+  if (can_remove) {
+    // Conditional jumps with boolean conditions are emiitted in
+    // ToBoolean form by the bytecode array builder,
+    // i.e. JumpIfToBooleanTrue rather JumpIfTrue. The ToBoolean
+    // element can be removed if the previous bytecode put a boolean
+    // value in the accumulator.
+    Bytecode jump = Bytecodes::GetJumpWithoutToBoolean(current->bytecode());
+    current->set_bytecode(jump, current->operand(0));
+  }
+  return can_remove;
+}
+
+bool BytecodePeepholeOptimizer::RemoveToBooleanFromLogicalNot(
+    BytecodeNode* const current) {
+  bool can_remove = current->bytecode() == Bytecode::kToBooleanLogicalNot &&
+                    Bytecodes::WritesBooleanToAccumulator(last_.bytecode());
+  if (can_remove) {
+    // Logical-nots are emitted in ToBoolean form by the bytecode array
+    // builder, The ToBoolean element can be removed if the previous bytecode
+    // put a boolean value in the accumulator.
+    current->set_bytecode(Bytecode::kLogicalNot);
+  }
+  return can_remove;
+}
+
+bool BytecodePeepholeOptimizer::TransformCurrentBytecode(
+    BytecodeNode* const current) {
+  return RemoveToBooleanFromJump(current) ||
+         RemoveToBooleanFromLogicalNot(current);
+}
+
+bool BytecodePeepholeOptimizer::CanElideLast(
+    const BytecodeNode* const current) const {
+  if (last_.bytecode() == Bytecode::kNop) {
+    // Nop are placeholders for holding source position information.
+    return true;
+  } else if (Bytecodes::IsAccumulatorLoadWithoutEffects(current->bytecode()) &&
+             Bytecodes::IsAccumulatorLoadWithoutEffects(last_.bytecode())) {
+    // The accumulator is invisible to the debugger. If there is a sequence of
+    // consecutive accumulator loads (that don't have side effects) then only
+    // the final load is potentially visible.
+    return true;
+  } else if (Bytecodes::GetAccumulatorUse(current->bytecode()) ==
+                 AccumulatorUse::kWrite &&
+             Bytecodes::IsAccumulatorLoadWithoutEffects(last_.bytecode())) {
+    // The current instruction clobbers the accumulator without reading it. The
+    // load in the last instruction can be elided as it has no effect.
+    return true;
+  } else {
+    return false;
+  }
+}
+
+BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) {
+  TryToRemoveLastExpressionPosition(current);
+
+  if (TransformCurrentBytecode(current) ||
+      TransformLastAndCurrentBytecodes(current)) {
+    return current;
+  }
+
+  if (CanElideCurrent(current)) {
+    if (current->source_info().is_valid()) {
+      // Preserve the source information by replacing the current bytecode
+      // with a no op bytecode.
+      current->set_bytecode(Bytecode::kNop);
+    } else {
+      current = nullptr;
+    }
+    return current;
+  }
+
+  if (CanElideLast(current) && CanElideLastBasedOnSourcePosition(current)) {
+    if (last_.source_info().is_valid()) {
+      // Current can not be valid per CanElideLastBasedOnSourcePosition().
+      current->source_info().Clone(last_.source_info());
+    }
+    InvalidateLast();
+    return current;
+  }
+
+  return current;
+}
+
+BytecodeNode* BytecodePeepholeOptimizer::OptimizeAndEmitLast(
+    BytecodeNode* current) {
+  // Attempt optimization if there is an earlier node to optimize with.
+  if (LastIsValid()) {
+    current = Optimize(current);
+    // Only output the last node if it wasn't invalidated by the optimization.
+    if (LastIsValid()) {
+      next_stage_->Write(&last_);
+      InvalidateLast();
+    }
+  }
+  return current;
+}
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
diff --git a/src/interpreter/bytecode-peephole-optimizer.h b/src/interpreter/bytecode-peephole-optimizer.h
new file mode 100644
index 0000000..e6ada2a
--- /dev/null
+++ b/src/interpreter/bytecode-peephole-optimizer.h
@@ -0,0 +1,71 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_INTERPRETER_BYTECODE_PEEPHOLE_OPTIMIZER_H_
+#define V8_INTERPRETER_BYTECODE_PEEPHOLE_OPTIMIZER_H_
+
+#include "src/interpreter/bytecode-pipeline.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+class ConstantArrayBuilder;
+
+// An optimization stage for performing peephole optimizations on
+// generated bytecode. The optimizer may buffer one bytecode
+// internally.
+class BytecodePeepholeOptimizer final : public BytecodePipelineStage,
+                                        public ZoneObject {
+ public:
+  BytecodePeepholeOptimizer(ConstantArrayBuilder* constant_array_builder,
+                            BytecodePipelineStage* next_stage);
+
+  // BytecodePipelineStage interface.
+  void Write(BytecodeNode* node) override;
+  void WriteJump(BytecodeNode* node, BytecodeLabel* label) override;
+  void BindLabel(BytecodeLabel* label) override;
+  void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override;
+  Handle<BytecodeArray> ToBytecodeArray(
+      int fixed_register_count, int parameter_count,
+      Handle<FixedArray> handler_table) override;
+
+ private:
+  BytecodeNode* OptimizeAndEmitLast(BytecodeNode* current);
+  BytecodeNode* Optimize(BytecodeNode* current);
+  void Flush();
+
+  void TryToRemoveLastExpressionPosition(const BytecodeNode* const current);
+  bool TransformCurrentBytecode(BytecodeNode* const current);
+  bool TransformLastAndCurrentBytecodes(BytecodeNode* const current);
+  bool CanElideCurrent(const BytecodeNode* const current) const;
+  bool CanElideLast(const BytecodeNode* const current) const;
+  bool CanElideLastBasedOnSourcePosition(
+      const BytecodeNode* const current) const;
+
+  // Simple substitution methods.
+  bool RemoveToBooleanFromJump(BytecodeNode* const current);
+  bool RemoveToBooleanFromLogicalNot(BytecodeNode* const current);
+
+  void InvalidateLast();
+  bool LastIsValid() const;
+  void SetLast(const BytecodeNode* const node);
+
+  bool LastBytecodePutsNameInAccumulator() const;
+
+  Handle<Object> GetConstantForIndexOperand(const BytecodeNode* const node,
+                                            int index) const;
+
+  ConstantArrayBuilder* constant_array_builder_;
+  BytecodePipelineStage* next_stage_;
+  BytecodeNode last_;
+
+  DISALLOW_COPY_AND_ASSIGN(BytecodePeepholeOptimizer);
+};
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_INTERPRETER_BYTECODE_PEEPHOLE_OPTIMIZER_H_
diff --git a/src/interpreter/bytecode-pipeline.cc b/src/interpreter/bytecode-pipeline.cc
new file mode 100644
index 0000000..58ade92
--- /dev/null
+++ b/src/interpreter/bytecode-pipeline.cc
@@ -0,0 +1,145 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/interpreter/bytecode-pipeline.h"
+
+#include <iomanip>
+#include "src/interpreter/source-position-table.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+BytecodeNode::BytecodeNode(Bytecode bytecode) {
+  DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0);
+  bytecode_ = bytecode;
+}
+
+BytecodeNode::BytecodeNode(Bytecode bytecode, uint32_t operand0) {
+  DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 1);
+  bytecode_ = bytecode;
+  operands_[0] = operand0;
+}
+
+BytecodeNode::BytecodeNode(Bytecode bytecode, uint32_t operand0,
+                           uint32_t operand1) {
+  DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 2);
+  bytecode_ = bytecode;
+  operands_[0] = operand0;
+  operands_[1] = operand1;
+}
+
+BytecodeNode::BytecodeNode(Bytecode bytecode, uint32_t operand0,
+                           uint32_t operand1, uint32_t operand2) {
+  DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 3);
+  bytecode_ = bytecode;
+  operands_[0] = operand0;
+  operands_[1] = operand1;
+  operands_[2] = operand2;
+}
+
+BytecodeNode::BytecodeNode(Bytecode bytecode, uint32_t operand0,
+                           uint32_t operand1, uint32_t operand2,
+                           uint32_t operand3) {
+  DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 4);
+  bytecode_ = bytecode;
+  operands_[0] = operand0;
+  operands_[1] = operand1;
+  operands_[2] = operand2;
+  operands_[3] = operand3;
+}
+
+BytecodeNode::BytecodeNode(const BytecodeNode& other) {
+  memcpy(this, &other, sizeof(other));
+}
+
+BytecodeNode& BytecodeNode::operator=(const BytecodeNode& other) {
+  memcpy(this, &other, sizeof(other));
+  return *this;
+}
+
+void BytecodeNode::set_bytecode(Bytecode bytecode) {
+  DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0);
+  bytecode_ = bytecode;
+}
+
+void BytecodeNode::set_bytecode(Bytecode bytecode, uint32_t operand0) {
+  DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 1);
+  bytecode_ = bytecode;
+  operands_[0] = operand0;
+}
+
+void BytecodeNode::Clone(const BytecodeNode* const other) {
+  memcpy(this, other, sizeof(*other));
+}
+
+void BytecodeNode::Print(std::ostream& os) const {
+#ifdef DEBUG
+  std::ios saved_state(nullptr);
+  saved_state.copyfmt(os);
+  os << Bytecodes::ToString(bytecode_);
+
+  for (int i = 0; i < operand_count(); ++i) {
+    os << ' ' << std::setw(8) << std::setfill('0') << std::hex << operands_[i];
+  }
+  os.copyfmt(saved_state);
+
+  if (source_info_.is_valid()) {
+    os << ' ' << source_info_;
+  }
+  os << '\n';
+#else
+  os << static_cast<const void*>(this);
+#endif  // DEBUG
+}
+
+void BytecodeNode::Transform(Bytecode new_bytecode, uint32_t extra_operand) {
+  DCHECK_EQ(Bytecodes::NumberOfOperands(new_bytecode),
+            Bytecodes::NumberOfOperands(bytecode()) + 1);
+  DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 1 ||
+         Bytecodes::GetOperandType(new_bytecode, 0) ==
+             Bytecodes::GetOperandType(bytecode(), 0));
+  DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 2 ||
+         Bytecodes::GetOperandType(new_bytecode, 1) ==
+             Bytecodes::GetOperandType(bytecode(), 1));
+  DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 3 ||
+         Bytecodes::GetOperandType(new_bytecode, 2) ==
+             Bytecodes::GetOperandType(bytecode(), 2));
+  DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 4);
+  operands_[operand_count()] = extra_operand;
+  bytecode_ = new_bytecode;
+}
+
+bool BytecodeNode::operator==(const BytecodeNode& other) const {
+  if (this == &other) {
+    return true;
+  } else if (this->bytecode() != other.bytecode() ||
+             this->source_info() != other.source_info()) {
+    return false;
+  } else {
+    for (int i = 0; i < this->operand_count(); ++i) {
+      if (this->operand(i) != other.operand(i)) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+std::ostream& operator<<(std::ostream& os, const BytecodeSourceInfo& info) {
+  if (info.is_valid()) {
+    char description = info.is_statement() ? 'S' : 'E';
+    os << info.source_position() << ' ' << description << '>';
+  }
+  return os;
+}
+
+std::ostream& operator<<(std::ostream& os, const BytecodeNode& node) {
+  node.Print(os);
+  return os;
+}
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
diff --git a/src/interpreter/bytecode-pipeline.h b/src/interpreter/bytecode-pipeline.h
new file mode 100644
index 0000000..e2beff2
--- /dev/null
+++ b/src/interpreter/bytecode-pipeline.h
@@ -0,0 +1,200 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_INTERPRETER_BYTECODE_PIPELINE_H_
+#define V8_INTERPRETER_BYTECODE_PIPELINE_H_
+
+#include "src/interpreter/bytecode-register-allocator.h"
+#include "src/interpreter/bytecodes.h"
+#include "src/zone-containers.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+class BytecodeLabel;
+class BytecodeNode;
+class BytecodeSourceInfo;
+
+// Interface for bytecode pipeline stages.
+class BytecodePipelineStage {
+ public:
+  virtual ~BytecodePipelineStage() {}
+
+  // Write bytecode node |node| into pipeline. The node is only valid
+  // for the duration of the call. Callee's should clone it if
+  // deferring Write() to the next stage.
+  virtual void Write(BytecodeNode* node) = 0;
+
+  // Write jump bytecode node |node| which jumps to |label| into pipeline.
+  // The node and label are only valid for the duration of the call. This call
+  // implicitly ends the current basic block so should always write to the next
+  // stage.
+  virtual void WriteJump(BytecodeNode* node, BytecodeLabel* label) = 0;
+
+  // Binds |label| to the current bytecode location. This call implicitly
+  // ends the current basic block and so any deferred bytecodes should be
+  // written to the next stage.
+  virtual void BindLabel(BytecodeLabel* label) = 0;
+
+  // Binds |label| to the location of |target|. This call implicitly
+  // ends the current basic block and so any deferred bytecodes should be
+  // written to the next stage.
+  virtual void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) = 0;
+
+  // Flush the pipeline and generate a bytecode array.
+  virtual Handle<BytecodeArray> ToBytecodeArray(
+      int fixed_register_count, int parameter_count,
+      Handle<FixedArray> handler_table) = 0;
+};
+
+// Source code position information.
+class BytecodeSourceInfo final {
+ public:
+  static const int kUninitializedPosition = -1;
+
+  BytecodeSourceInfo()
+      : position_type_(PositionType::kNone),
+        source_position_(kUninitializedPosition) {}
+
+  BytecodeSourceInfo(int source_position, bool is_statement)
+      : position_type_(is_statement ? PositionType::kStatement
+                                    : PositionType::kExpression),
+        source_position_(source_position) {
+    DCHECK_GE(source_position, 0);
+  }
+
+  // Makes instance into a statement position.
+  void MakeStatementPosition(int source_position) {
+    // Statement positions can be replaced by other statement
+    // positions. For example , "for (x = 0; x < 3; ++x) 7;" has a
+    // statement position associated with 7 but no bytecode associated
+    // with it. Then Next is emitted after the body and has
+    // statement position and overrides the existing one.
+    position_type_ = PositionType::kStatement;
+    source_position_ = source_position;
+  }
+
+  // Makes instance into an expression position. Instance should not
+  // be a statement position otherwise it could be lost and impair the
+  // debugging experience.
+  void MakeExpressionPosition(int source_position) {
+    DCHECK(!is_statement());
+    position_type_ = PositionType::kExpression;
+    source_position_ = source_position;
+  }
+
+  // Forces an instance into an expression position.
+  void ForceExpressionPosition(int source_position) {
+    position_type_ = PositionType::kExpression;
+    source_position_ = source_position;
+  }
+
+  // Clones a source position. The current instance is expected to be
+  // invalid.
+  void Clone(const BytecodeSourceInfo& other) {
+    DCHECK(!is_valid());
+    position_type_ = other.position_type_;
+    source_position_ = other.source_position_;
+  }
+
+  int source_position() const {
+    DCHECK(is_valid());
+    return source_position_;
+  }
+
+  bool is_statement() const {
+    return position_type_ == PositionType::kStatement;
+  }
+  bool is_expression() const {
+    return position_type_ == PositionType::kExpression;
+  }
+
+  bool is_valid() const { return position_type_ != PositionType::kNone; }
+  void set_invalid() {
+    position_type_ = PositionType::kNone;
+    source_position_ = kUninitializedPosition;
+  }
+
+  bool operator==(const BytecodeSourceInfo& other) const {
+    return position_type_ == other.position_type_ &&
+           source_position_ == other.source_position_;
+  }
+
+  bool operator!=(const BytecodeSourceInfo& other) const {
+    return position_type_ != other.position_type_ ||
+           source_position_ != other.source_position_;
+  }
+
+ private:
+  enum class PositionType : uint8_t { kNone, kExpression, kStatement };
+
+  PositionType position_type_;
+  int source_position_;
+
+  DISALLOW_COPY_AND_ASSIGN(BytecodeSourceInfo);
+};
+
+// A container for a generated bytecode, it's operands, and source information.
+// These must be allocated by a BytecodeNodeAllocator instance.
+class BytecodeNode final : ZoneObject {
+ public:
+  explicit BytecodeNode(Bytecode bytecode = Bytecode::kIllegal);
+  BytecodeNode(Bytecode bytecode, uint32_t operand0);
+  BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1);
+  BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
+               uint32_t operand2);
+  BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
+               uint32_t operand2, uint32_t operand3);
+
+  BytecodeNode(const BytecodeNode& other);
+  BytecodeNode& operator=(const BytecodeNode& other);
+
+  void set_bytecode(Bytecode bytecode);
+  void set_bytecode(Bytecode bytecode, uint32_t operand0);
+
+  // Clone |other|.
+  void Clone(const BytecodeNode* const other);
+
+  // Print to stream |os|.
+  void Print(std::ostream& os) const;
+
+  // Transform to a node representing |new_bytecode| which has one
+  // operand more than the current bytecode.
+  void Transform(Bytecode new_bytecode, uint32_t extra_operand);
+
+  Bytecode bytecode() const { return bytecode_; }
+
+  uint32_t operand(int i) const {
+    DCHECK_LT(i, operand_count());
+    return operands_[i];
+  }
+  uint32_t* operands() { return operands_; }
+  const uint32_t* operands() const { return operands_; }
+
+  int operand_count() const { return Bytecodes::NumberOfOperands(bytecode_); }
+
+  const BytecodeSourceInfo& source_info() const { return source_info_; }
+  BytecodeSourceInfo& source_info() { return source_info_; }
+
+  bool operator==(const BytecodeNode& other) const;
+  bool operator!=(const BytecodeNode& other) const { return !(*this == other); }
+
+ private:
+  static const int kInvalidPosition = kMinInt;
+  static const size_t kMaxOperands = 4;
+
+  Bytecode bytecode_;
+  uint32_t operands_[kMaxOperands];
+  BytecodeSourceInfo source_info_;
+};
+
+std::ostream& operator<<(std::ostream& os, const BytecodeSourceInfo& info);
+std::ostream& operator<<(std::ostream& os, const BytecodeNode& node);
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_INTERPRETER_BYTECODE_PIPELINE_H_
diff --git a/src/interpreter/bytecode-register-allocator.cc b/src/interpreter/bytecode-register-allocator.cc
index 9bdde9a..10afcdc 100644
--- a/src/interpreter/bytecode-register-allocator.cc
+++ b/src/interpreter/bytecode-register-allocator.cc
@@ -14,7 +14,8 @@
                                                        int allocation_base)
     : free_temporaries_(zone),
       allocation_base_(allocation_base),
-      allocation_count_(0) {}
+      allocation_count_(0),
+      observer_(nullptr) {}
 
 Register TemporaryRegisterAllocator::first_temporary_register() const {
   DCHECK(allocation_count() > 0);
@@ -26,6 +27,12 @@
   return Register(allocation_base() + allocation_count() - 1);
 }
 
+void TemporaryRegisterAllocator::set_observer(
+    TemporaryRegisterObserver* observer) {
+  DCHECK(observer_ == nullptr);
+  observer_ = observer;
+}
+
 int TemporaryRegisterAllocator::AllocateTemporaryRegister() {
   allocation_count_ += 1;
   return allocation_base() + allocation_count() - 1;
@@ -140,6 +147,9 @@
 void TemporaryRegisterAllocator::ReturnTemporaryRegister(int reg_index) {
   DCHECK(free_temporaries_.find(reg_index) == free_temporaries_.end());
   free_temporaries_.insert(reg_index);
+  if (observer_) {
+    observer_->TemporaryRegisterFreeEvent(Register(reg_index));
+  }
 }
 
 BytecodeRegisterAllocator::BytecodeRegisterAllocator(
@@ -156,7 +166,6 @@
   allocated_.clear();
 }
 
-
 Register BytecodeRegisterAllocator::NewRegister() {
   int allocated = -1;
   if (next_consecutive_count_ <= 0) {
@@ -170,7 +179,6 @@
   return Register(allocated);
 }
 
-
 bool BytecodeRegisterAllocator::RegisterIsAllocatedInThisScope(
     Register reg) const {
   for (auto i = allocated_.begin(); i != allocated_.end(); i++) {
@@ -179,7 +187,6 @@
   return false;
 }
 
-
 void BytecodeRegisterAllocator::PrepareForConsecutiveAllocations(size_t count) {
   if (static_cast<int>(count) > next_consecutive_count_) {
     next_consecutive_register_ =
@@ -188,7 +195,6 @@
   }
 }
 
-
 Register BytecodeRegisterAllocator::NextConsecutiveRegister() {
   DCHECK_GE(next_consecutive_register_, 0);
   DCHECK_GT(next_consecutive_count_, 0);
diff --git a/src/interpreter/bytecode-register-allocator.h b/src/interpreter/bytecode-register-allocator.h
index 696a3b1..b8f737b 100644
--- a/src/interpreter/bytecode-register-allocator.h
+++ b/src/interpreter/bytecode-register-allocator.h
@@ -14,6 +14,7 @@
 
 class BytecodeArrayBuilder;
 class Register;
+class TemporaryRegisterObserver;
 
 class TemporaryRegisterAllocator final {
  public:
@@ -54,6 +55,9 @@
   // Returns the number of temporary register allocations made.
   int allocation_count() const { return allocation_count_; }
 
+  // Sets an observer for temporary register events.
+  void set_observer(TemporaryRegisterObserver* observer);
+
  private:
   // Allocate a temporary register.
   int AllocateTemporaryRegister();
@@ -61,11 +65,18 @@
   ZoneSet<int> free_temporaries_;
   int allocation_base_;
   int allocation_count_;
+  TemporaryRegisterObserver* observer_;
 
   DISALLOW_COPY_AND_ASSIGN(TemporaryRegisterAllocator);
 };
 
-// A class than allows the instantiator to allocate temporary registers that are
+class TemporaryRegisterObserver {
+ public:
+  virtual ~TemporaryRegisterObserver() {}
+  virtual void TemporaryRegisterFreeEvent(Register reg) = 0;
+};
+
+// A class that allows the instantiator to allocate temporary registers that are
 // cleaned up when scope is closed.
 class BytecodeRegisterAllocator final {
  public:
diff --git a/src/interpreter/bytecode-register-optimizer.cc b/src/interpreter/bytecode-register-optimizer.cc
new file mode 100644
index 0000000..ab25f95
--- /dev/null
+++ b/src/interpreter/bytecode-register-optimizer.cc
@@ -0,0 +1,630 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/interpreter/bytecode-register-optimizer.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+const uint32_t BytecodeRegisterOptimizer::kInvalidEquivalenceId;
+
+// A class for tracking the state of a register. This class tracks
+// which equivalence set a register is a member of and also whether a
+// register is materialized in the bytecode stream.
+class BytecodeRegisterOptimizer::RegisterInfo final : public ZoneObject {
+ public:
+  RegisterInfo(Register reg, uint32_t equivalence_id, bool materialized)
+      : register_(reg),
+        equivalence_id_(equivalence_id),
+        materialized_(materialized),
+        next_(this),
+        prev_(this) {}
+
+  void AddToEquivalenceSetOf(RegisterInfo* info);
+  void MoveToNewEquivalenceSet(uint32_t equivalence_id, bool materialized);
+  bool IsOnlyMemberOfEquivalenceSet() const;
+  bool IsOnlyMaterializedMemberOfEquivalenceSet() const;
+  bool IsInSameEquivalenceSet(RegisterInfo* info) const;
+
+  // Get a member of this register's equivalence set that is
+  // materialized. The materialized equivalent will be this register
+  // if it is materialized. Returns nullptr if no materialized
+  // equivalent exists.
+  RegisterInfo* GetMaterializedEquivalent();
+
+  // Get a member of this register's equivalence set that is
+  // materialized and not register |reg|. The materialized equivalent
+  // will be this register if it is materialized. Returns nullptr if
+  // no materialized equivalent exists.
+  RegisterInfo* GetMaterializedEquivalentOtherThan(Register reg);
+
+  // Get a member of this register's equivalence set that is intended
+  // to be materialized in place of this register (which is currently
+  // materialized). The best candidate is deemed to be the register
+  // with the lowest index as this permits temporary registers to be
+  // removed from the bytecode stream. Returns nullptr if no candidate
+  // exists.
+  RegisterInfo* GetEquivalentToMaterialize();
+
+  // Get an equivalent register. Returns this if none exists.
+  RegisterInfo* GetEquivalent();
+
+  Register register_value() const { return register_; }
+  bool materialized() const { return materialized_; }
+  void set_materialized(bool materialized) { materialized_ = materialized; }
+  void set_equivalence_id(uint32_t equivalence_id) {
+    equivalence_id_ = equivalence_id;
+  }
+  uint32_t equivalence_id() const { return equivalence_id_; }
+
+ private:
+  Register register_;
+  uint32_t equivalence_id_;
+  bool materialized_;
+
+  // Equivalence set pointers.
+  RegisterInfo* next_;
+  RegisterInfo* prev_;
+
+  DISALLOW_COPY_AND_ASSIGN(RegisterInfo);
+};
+
+void BytecodeRegisterOptimizer::RegisterInfo::AddToEquivalenceSetOf(
+    RegisterInfo* info) {
+  DCHECK_NE(kInvalidEquivalenceId, info->equivalence_id());
+  // Fix old list
+  next_->prev_ = prev_;
+  prev_->next_ = next_;
+  // Add to new list.
+  next_ = info->next_;
+  prev_ = info;
+  prev_->next_ = this;
+  next_->prev_ = this;
+  set_equivalence_id(info->equivalence_id());
+  set_materialized(false);
+}
+
+void BytecodeRegisterOptimizer::RegisterInfo::MoveToNewEquivalenceSet(
+    uint32_t equivalence_id, bool materialized) {
+  next_->prev_ = prev_;
+  prev_->next_ = next_;
+  next_ = prev_ = this;
+  equivalence_id_ = equivalence_id;
+  materialized_ = materialized;
+}
+
+bool BytecodeRegisterOptimizer::RegisterInfo::IsOnlyMemberOfEquivalenceSet()
+    const {
+  return this->next_ == this;
+}
+
+bool BytecodeRegisterOptimizer::RegisterInfo::
+    IsOnlyMaterializedMemberOfEquivalenceSet() const {
+  DCHECK(materialized());
+
+  const RegisterInfo* visitor = this->next_;
+  while (visitor != this) {
+    if (visitor->materialized()) {
+      return false;
+    }
+    visitor = visitor->next_;
+  }
+  return true;
+}
+
+bool BytecodeRegisterOptimizer::RegisterInfo::IsInSameEquivalenceSet(
+    RegisterInfo* info) const {
+  return equivalence_id() == info->equivalence_id();
+}
+
+BytecodeRegisterOptimizer::RegisterInfo*
+BytecodeRegisterOptimizer::RegisterInfo::GetMaterializedEquivalent() {
+  RegisterInfo* visitor = this;
+  do {
+    if (visitor->materialized()) {
+      return visitor;
+    }
+    visitor = visitor->next_;
+  } while (visitor != this);
+
+  return nullptr;
+}
+
+BytecodeRegisterOptimizer::RegisterInfo*
+BytecodeRegisterOptimizer::RegisterInfo::GetMaterializedEquivalentOtherThan(
+    Register reg) {
+  RegisterInfo* visitor = this;
+  do {
+    if (visitor->materialized() && visitor->register_value() != reg) {
+      return visitor;
+    }
+    visitor = visitor->next_;
+  } while (visitor != this);
+
+  return nullptr;
+}
+
+BytecodeRegisterOptimizer::RegisterInfo*
+BytecodeRegisterOptimizer::RegisterInfo::GetEquivalentToMaterialize() {
+  DCHECK(this->materialized());
+  RegisterInfo* visitor = this->next_;
+  RegisterInfo* best_info = nullptr;
+  while (visitor != this) {
+    if (visitor->materialized()) {
+      return nullptr;
+    }
+    if (best_info == nullptr ||
+        visitor->register_value() < best_info->register_value()) {
+      best_info = visitor;
+    }
+    visitor = visitor->next_;
+  }
+  return best_info;
+}
+
+BytecodeRegisterOptimizer::RegisterInfo*
+BytecodeRegisterOptimizer::RegisterInfo::GetEquivalent() {
+  return next_;
+}
+
+BytecodeRegisterOptimizer::BytecodeRegisterOptimizer(
+    Zone* zone, TemporaryRegisterAllocator* register_allocator,
+    int parameter_count, BytecodePipelineStage* next_stage)
+    : accumulator_(Register::virtual_accumulator()),
+      temporary_base_(register_allocator->allocation_base()),
+      register_info_table_(zone),
+      equivalence_id_(0),
+      next_stage_(next_stage),
+      flush_required_(false),
+      zone_(zone) {
+  register_allocator->set_observer(this);
+
+  // Calculate offset so register index values can be mapped into
+  // a vector of register metadata.
+  if (parameter_count != 0) {
+    register_info_table_offset_ =
+        -Register::FromParameterIndex(0, parameter_count).index();
+  } else {
+    // TODO(oth): This path shouldn't be necessary in bytecode generated
+    // from Javascript, but a set of tests do not include the JS receiver.
+    register_info_table_offset_ = -accumulator_.index();
+  }
+
+  // Initialize register map for parameters, locals, and the
+  // accumulator.
+  register_info_table_.resize(register_info_table_offset_ +
+                              static_cast<size_t>(temporary_base_.index()));
+  for (size_t i = 0; i < register_info_table_.size(); ++i) {
+    register_info_table_[i] = new (zone) RegisterInfo(
+        RegisterFromRegisterInfoTableIndex(i), NextEquivalenceId(), true);
+    DCHECK_EQ(register_info_table_[i]->register_value().index(),
+              RegisterFromRegisterInfoTableIndex(i).index());
+  }
+  accumulator_info_ = GetRegisterInfo(accumulator_);
+  DCHECK(accumulator_info_->register_value() == accumulator_);
+}
+
+// override
+Handle<BytecodeArray> BytecodeRegisterOptimizer::ToBytecodeArray(
+    int fixed_register_count, int parameter_count,
+    Handle<FixedArray> handler_table) {
+  FlushState();
+  return next_stage_->ToBytecodeArray(fixed_register_count, parameter_count,
+                                      handler_table);
+}
+
+// override
+void BytecodeRegisterOptimizer::Write(BytecodeNode* node) {
+  //
+  // Transfers with observable registers as the destination will be
+  // immediately materialized so the source position information will
+  // be ordered correctly.
+  //
+  // Transfers without observable destination registers will initially
+  // be emitted as Nop's with the source position. They may, or may
+  // not, be materialized by the optimizer. However, the source
+  // position is not lost and being attached to a Nop is fine as the
+  // destination register is not observable in the debugger.
+  //
+  switch (node->bytecode()) {
+    case Bytecode::kLdar: {
+      DoLdar(node);
+      return;
+    }
+    case Bytecode::kStar: {
+      DoStar(node);
+      return;
+    }
+    case Bytecode::kMov: {
+      DoMov(node);
+      return;
+    }
+    default:
+      break;
+  }
+
+  if (Bytecodes::IsJump(node->bytecode()) ||
+      node->bytecode() == Bytecode::kDebugger ||
+      node->bytecode() == Bytecode::kSuspendGenerator) {
+    // All state must be flushed before emitting
+    // - a jump (due to how bytecode offsets for jumps are evaluated),
+    // - a call to the debugger (as it can manipulate locals and parameters),
+    // - a generator suspend (as this involves saving all registers).
+    FlushState();
+  }
+
+  PrepareOperands(node);
+  WriteToNextStage(node);
+}
+
+// override
+void BytecodeRegisterOptimizer::WriteJump(BytecodeNode* node,
+                                          BytecodeLabel* label) {
+  FlushState();
+  next_stage_->WriteJump(node, label);
+}
+
+// override
+void BytecodeRegisterOptimizer::BindLabel(BytecodeLabel* label) {
+  FlushState();
+  next_stage_->BindLabel(label);
+}
+
+// override
+void BytecodeRegisterOptimizer::BindLabel(const BytecodeLabel& target,
+                                          BytecodeLabel* label) {
+  // There is no need to flush here, it will have been flushed when |target|
+  // was bound.
+  next_stage_->BindLabel(target, label);
+}
+
+void BytecodeRegisterOptimizer::FlushState() {
+  if (!flush_required_) {
+    return;
+  }
+
+  // Materialize all live registers and break equivalences.
+  size_t count = register_info_table_.size();
+  for (size_t i = 0; i < count; ++i) {
+    RegisterInfo* reg_info = register_info_table_[i];
+    if (reg_info->materialized()) {
+      // Walk equivalents of materialized registers, materializing
+      // each equivalent register as necessary and placing in their
+      // own equivalence set.
+      RegisterInfo* equivalent;
+      while ((equivalent = reg_info->GetEquivalent()) != reg_info) {
+        if (!equivalent->materialized()) {
+          OutputRegisterTransfer(reg_info, equivalent);
+        }
+        equivalent->MoveToNewEquivalenceSet(NextEquivalenceId(), true);
+      }
+    }
+  }
+
+  flush_required_ = false;
+}
+
+void BytecodeRegisterOptimizer::WriteToNextStage(BytecodeNode* node) const {
+  next_stage_->Write(node);
+}
+
+void BytecodeRegisterOptimizer::WriteToNextStage(
+    BytecodeNode* node, const BytecodeSourceInfo& source_info) const {
+  if (source_info.is_valid()) {
+    node->source_info().Clone(source_info);
+  }
+  next_stage_->Write(node);
+}
+
+void BytecodeRegisterOptimizer::OutputRegisterTransfer(
+    RegisterInfo* input_info, RegisterInfo* output_info,
+    const BytecodeSourceInfo& source_info) {
+  Register input = input_info->register_value();
+  Register output = output_info->register_value();
+  DCHECK_NE(input.index(), output.index());
+
+  if (input == accumulator_) {
+    uint32_t operand = static_cast<uint32_t>(output.ToOperand());
+    BytecodeNode node(Bytecode::kStar, operand);
+    WriteToNextStage(&node, source_info);
+  } else if (output == accumulator_) {
+    uint32_t operand = static_cast<uint32_t>(input.ToOperand());
+    BytecodeNode node(Bytecode::kLdar, operand);
+    WriteToNextStage(&node, source_info);
+  } else {
+    uint32_t operand0 = static_cast<uint32_t>(input.ToOperand());
+    uint32_t operand1 = static_cast<uint32_t>(output.ToOperand());
+    BytecodeNode node(Bytecode::kMov, operand0, operand1);
+    WriteToNextStage(&node, source_info);
+  }
+  output_info->set_materialized(true);
+}
+
+void BytecodeRegisterOptimizer::CreateMaterializedEquivalent(
+    RegisterInfo* info) {
+  DCHECK(info->materialized());
+  RegisterInfo* unmaterialized = info->GetEquivalentToMaterialize();
+  if (unmaterialized) {
+    OutputRegisterTransfer(info, unmaterialized);
+  }
+}
+
+BytecodeRegisterOptimizer::RegisterInfo*
+BytecodeRegisterOptimizer::GetMaterializedEquivalent(RegisterInfo* info) {
+  return info->materialized() ? info : info->GetMaterializedEquivalent();
+}
+
+BytecodeRegisterOptimizer::RegisterInfo*
+BytecodeRegisterOptimizer::GetMaterializedEquivalentNotAccumulator(
+    RegisterInfo* info) {
+  if (info->materialized()) {
+    return info;
+  }
+
+  RegisterInfo* result = info->GetMaterializedEquivalentOtherThan(accumulator_);
+  if (result == nullptr) {
+    Materialize(info);
+    result = info;
+  }
+  DCHECK(result->register_value() != accumulator_);
+  return result;
+}
+
+void BytecodeRegisterOptimizer::Materialize(RegisterInfo* info) {
+  if (!info->materialized()) {
+    RegisterInfo* materialized = info->GetMaterializedEquivalent();
+    OutputRegisterTransfer(materialized, info);
+  }
+}
+
+void BytecodeRegisterOptimizer::AddToEquivalenceSet(
+    RegisterInfo* set_member, RegisterInfo* non_set_member) {
+  non_set_member->AddToEquivalenceSetOf(set_member);
+  // Flushing is only required when two or more registers are placed
+  // in the same equivalence set.
+  flush_required_ = true;
+}
+
+void BytecodeRegisterOptimizer::RegisterTransfer(
+    RegisterInfo* input_info, RegisterInfo* output_info,
+    const BytecodeSourceInfo& source_info) {
+  // Materialize an alternate in the equivalence set that
+  // |output_info| is leaving.
+  if (output_info->materialized()) {
+    CreateMaterializedEquivalent(output_info);
+  }
+
+  // Add |output_info| to new equivalence set.
+  if (!output_info->IsInSameEquivalenceSet(input_info)) {
+    AddToEquivalenceSet(input_info, output_info);
+  }
+
+  bool output_is_observable =
+      RegisterIsObservable(output_info->register_value());
+  if (output_is_observable) {
+    // Force store to be emitted when register is observable.
+    output_info->set_materialized(false);
+    RegisterInfo* materialized_info = input_info->GetMaterializedEquivalent();
+    OutputRegisterTransfer(materialized_info, output_info, source_info);
+  } else if (source_info.is_valid()) {
+    // Emit a placeholder nop to maintain source position info.
+    EmitNopForSourceInfo(source_info);
+  }
+}
+
+void BytecodeRegisterOptimizer::EmitNopForSourceInfo(
+    const BytecodeSourceInfo& source_info) const {
+  DCHECK(source_info.is_valid());
+  BytecodeNode nop(Bytecode::kNop);
+  nop.source_info().Clone(source_info);
+  WriteToNextStage(&nop);
+}
+
+void BytecodeRegisterOptimizer::DoLdar(const BytecodeNode* const node) {
+  Register input = GetRegisterInputOperand(
+      0, node->bytecode(), node->operands(), node->operand_count());
+  RegisterInfo* input_info = GetRegisterInfo(input);
+  RegisterTransfer(input_info, accumulator_info_, node->source_info());
+}
+
+void BytecodeRegisterOptimizer::DoMov(const BytecodeNode* const node) {
+  Register input = GetRegisterInputOperand(
+      0, node->bytecode(), node->operands(), node->operand_count());
+  RegisterInfo* input_info = GetRegisterInfo(input);
+  Register output = GetRegisterOutputOperand(
+      1, node->bytecode(), node->operands(), node->operand_count());
+  RegisterInfo* output_info = GetOrCreateRegisterInfo(output);
+  RegisterTransfer(input_info, output_info, node->source_info());
+}
+
+void BytecodeRegisterOptimizer::DoStar(const BytecodeNode* const node) {
+  Register output = GetRegisterOutputOperand(
+      0, node->bytecode(), node->operands(), node->operand_count());
+  RegisterInfo* output_info = GetOrCreateRegisterInfo(output);
+  RegisterTransfer(accumulator_info_, output_info, node->source_info());
+}
+
+void BytecodeRegisterOptimizer::PrepareRegisterOutputOperand(
+    RegisterInfo* reg_info) {
+  if (reg_info->materialized()) {
+    CreateMaterializedEquivalent(reg_info);
+  }
+  reg_info->MoveToNewEquivalenceSet(NextEquivalenceId(), true);
+}
+
+void BytecodeRegisterOptimizer::PrepareRegisterRangeOutputOperand(
+    Register start, int count) {
+  for (int i = 0; i < count; ++i) {
+    Register reg(start.index() + i);
+    RegisterInfo* reg_info = GetOrCreateRegisterInfo(reg);
+    PrepareRegisterOutputOperand(reg_info);
+  }
+}
+
+Register BytecodeRegisterOptimizer::GetEquivalentRegisterForInputOperand(
+    Register reg) {
+  // For a temporary register, RegInfo state may need be created. For
+  // locals and parameters, the RegInfo state is created in the
+  // BytecodeRegisterOptimizer constructor.
+  RegisterInfo* reg_info = GetOrCreateRegisterInfo(reg);
+  if (reg_info->materialized()) {
+    return reg;
+  } else {
+    RegisterInfo* equivalent_info =
+        GetMaterializedEquivalentNotAccumulator(reg_info);
+    return equivalent_info->register_value();
+  }
+}
+
+void BytecodeRegisterOptimizer::PrepareRegisterInputOperand(
+    BytecodeNode* const node, Register reg, int operand_index) {
+  Register equivalent = GetEquivalentRegisterForInputOperand(reg);
+  node->operands()[operand_index] =
+      static_cast<uint32_t>(equivalent.ToOperand());
+}
+
+void BytecodeRegisterOptimizer::PrepareRegisterRangeInputOperand(Register start,
+                                                                 int count) {
+  for (int i = 0; i < count; ++i) {
+    Register current(start.index() + i);
+    RegisterInfo* input_info = GetRegisterInfo(current);
+    Materialize(input_info);
+  }
+}
+
+void BytecodeRegisterOptimizer::PrepareRegisterOperands(
+    BytecodeNode* const node) {
+  //
+  // For each input operand, get a materialized equivalent if it is
+  // just a single register, otherwise materialize register range.
+  // Update operand_scale if necessary.
+  //
+  // For each output register about to be clobbered, materialize an
+  // equivalent if it exists. Put each register in it's own equivalence set.
+  //
+  int register_operand_bitmap =
+      Bytecodes::GetRegisterOperandBitmap(node->bytecode());
+  const OperandType* operand_types =
+      Bytecodes::GetOperandTypes(node->bytecode());
+  uint32_t* operands = node->operands();
+  for (int i = 0; register_operand_bitmap != 0;
+       ++i, register_operand_bitmap >>= 1) {
+    if ((register_operand_bitmap & 1) == 0) {
+      continue;
+    }
+    OperandType operand_type = operand_types[i];
+    int count = 0;
+    if (operand_types[i + 1] == OperandType::kRegCount) {
+      count = static_cast<int>(operands[i + 1]);
+      if (count == 0) {
+        continue;
+      }
+    } else {
+      count = Bytecodes::GetNumberOfRegistersRepresentedBy(operand_type);
+    }
+
+    Register reg = Register::FromOperand(static_cast<int32_t>(operands[i]));
+    if (Bytecodes::IsRegisterInputOperandType(operand_type)) {
+      if (count == 1) {
+        PrepareRegisterInputOperand(node, reg, i);
+      } else if (count > 1) {
+        PrepareRegisterRangeInputOperand(reg, count);
+      }
+    } else if (Bytecodes::IsRegisterOutputOperandType(operand_type)) {
+      PrepareRegisterRangeOutputOperand(reg, count);
+    }
+  }
+}
+
+void BytecodeRegisterOptimizer::PrepareAccumulator(BytecodeNode* const node) {
+  // Materialize the accumulator if it is read by the bytecode. The
+  // accumulator is special and no other register can be materialized
+  // in it's place.
+  if (Bytecodes::ReadsAccumulator(node->bytecode()) &&
+      !accumulator_info_->materialized()) {
+    Materialize(accumulator_info_);
+  }
+
+  // Materialize an equivalent to the accumulator if it will be
+  // clobbered when the bytecode is dispatched.
+  if (Bytecodes::WritesAccumulator(node->bytecode())) {
+    PrepareRegisterOutputOperand(accumulator_info_);
+  }
+}
+
+void BytecodeRegisterOptimizer::PrepareOperands(BytecodeNode* const node) {
+  PrepareAccumulator(node);
+  PrepareRegisterOperands(node);
+}
+
+// static
+Register BytecodeRegisterOptimizer::GetRegisterInputOperand(
+    int index, Bytecode bytecode, const uint32_t* operands, int operand_count) {
+  DCHECK_LT(index, operand_count);
+  DCHECK(Bytecodes::IsRegisterInputOperandType(
+      Bytecodes::GetOperandType(bytecode, index)));
+  return OperandToRegister(operands[index]);
+}
+
+// static
+Register BytecodeRegisterOptimizer::GetRegisterOutputOperand(
+    int index, Bytecode bytecode, const uint32_t* operands, int operand_count) {
+  DCHECK_LT(index, operand_count);
+  DCHECK(Bytecodes::IsRegisterOutputOperandType(
+      Bytecodes::GetOperandType(bytecode, index)));
+  return OperandToRegister(operands[index]);
+}
+
+BytecodeRegisterOptimizer::RegisterInfo*
+BytecodeRegisterOptimizer::GetRegisterInfo(Register reg) {
+  size_t index = GetRegisterInfoTableIndex(reg);
+  return (index < register_info_table_.size()) ? register_info_table_[index]
+                                               : nullptr;
+}
+
+BytecodeRegisterOptimizer::RegisterInfo*
+BytecodeRegisterOptimizer::GetOrCreateRegisterInfo(Register reg) {
+  size_t index = GetRegisterInfoTableIndex(reg);
+  return index < register_info_table_.size() ? register_info_table_[index]
+                                             : NewRegisterInfo(reg);
+}
+
+BytecodeRegisterOptimizer::RegisterInfo*
+BytecodeRegisterOptimizer::NewRegisterInfo(Register reg) {
+  size_t index = GetRegisterInfoTableIndex(reg);
+  DCHECK_GE(index, register_info_table_.size());
+  GrowRegisterMap(reg);
+  return register_info_table_[index];
+}
+
+void BytecodeRegisterOptimizer::GrowRegisterMap(Register reg) {
+  DCHECK(RegisterIsTemporary(reg));
+  size_t index = GetRegisterInfoTableIndex(reg);
+  DCHECK_GE(index, register_info_table_.size());
+  size_t new_size = index + 1;
+  size_t old_size = register_info_table_.size();
+  register_info_table_.resize(new_size);
+  for (size_t i = old_size; i < new_size; ++i) {
+    register_info_table_[i] = new (zone()) RegisterInfo(
+        RegisterFromRegisterInfoTableIndex(i), NextEquivalenceId(), false);
+  }
+}
+
+void BytecodeRegisterOptimizer::TemporaryRegisterFreeEvent(Register reg) {
+  RegisterInfo* info = GetRegisterInfo(reg);
+  if (info != nullptr) {
+    // If register is materialized and part of equivalence set, make
+    // sure another member of the set holds the value before the
+    // temporary register is removed.
+    if (info->materialized()) {
+      CreateMaterializedEquivalent(info);
+    }
+    info->MoveToNewEquivalenceSet(kInvalidEquivalenceId, false);
+  }
+}
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
diff --git a/src/interpreter/bytecode-register-optimizer.h b/src/interpreter/bytecode-register-optimizer.h
new file mode 100644
index 0000000..4229610
--- /dev/null
+++ b/src/interpreter/bytecode-register-optimizer.h
@@ -0,0 +1,155 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_INTERPRETER_BYTECODE_REGISTER_OPTIMIZER_H_
+#define V8_INTERPRETER_BYTECODE_REGISTER_OPTIMIZER_H_
+
+#include "src/interpreter/bytecode-pipeline.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+// An optimization stage for eliminating unnecessary transfers between
+// registers. The bytecode generator uses temporary registers
+// liberally for correctness and convenience and this stage removes
+// transfers that are not required and preserves correctness.
+class BytecodeRegisterOptimizer final : public BytecodePipelineStage,
+                                        public TemporaryRegisterObserver,
+                                        public ZoneObject {
+ public:
+  BytecodeRegisterOptimizer(Zone* zone,
+                            TemporaryRegisterAllocator* register_allocator,
+                            int parameter_count,
+                            BytecodePipelineStage* next_stage);
+  virtual ~BytecodeRegisterOptimizer() {}
+
+  // BytecodePipelineStage interface.
+  void Write(BytecodeNode* node) override;
+  void WriteJump(BytecodeNode* node, BytecodeLabel* label) override;
+  void BindLabel(BytecodeLabel* label) override;
+  void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override;
+  Handle<BytecodeArray> ToBytecodeArray(
+      int fixed_register_count, int parameter_count,
+      Handle<FixedArray> handler_table) override;
+
+ private:
+  static const uint32_t kInvalidEquivalenceId = kMaxUInt32;
+
+  class RegisterInfo;
+
+  // TemporaryRegisterObserver interface.
+  void TemporaryRegisterFreeEvent(Register reg) override;
+
+  // Helpers for BytecodePipelineStage interface.
+  void FlushState();
+  void WriteToNextStage(BytecodeNode* node) const;
+  void WriteToNextStage(BytecodeNode* node,
+                        const BytecodeSourceInfo& output_info) const;
+
+  // Update internal state for register transfer from |input| to
+  // |output| using |source_info| as source position information if
+  // any bytecodes are emitted due to transfer.
+  void RegisterTransfer(RegisterInfo* input, RegisterInfo* output,
+                        const BytecodeSourceInfo& source_info);
+
+  // Emit a register transfer bytecode from |input| to |output|.
+  void OutputRegisterTransfer(
+      RegisterInfo* input, RegisterInfo* output,
+      const BytecodeSourceInfo& source_info = BytecodeSourceInfo());
+
+  // Emits a Nop to preserve source position information in the
+  // bytecode pipeline.
+  void EmitNopForSourceInfo(const BytecodeSourceInfo& source_info) const;
+
+  // Handlers for bytecode nodes for register to register transfers.
+  void DoLdar(const BytecodeNode* const node);
+  void DoMov(const BytecodeNode* const node);
+  void DoStar(const BytecodeNode* const node);
+
+  // Operand processing methods for bytecodes other than those
+  // performing register to register transfers.
+  void PrepareOperands(BytecodeNode* const node);
+  void PrepareAccumulator(BytecodeNode* const node);
+  void PrepareRegisterOperands(BytecodeNode* const node);
+
+  void PrepareRegisterOutputOperand(RegisterInfo* reg_info);
+  void PrepareRegisterRangeOutputOperand(Register start, int count);
+  void PrepareRegisterInputOperand(BytecodeNode* const node, Register reg,
+                                   int operand_index);
+  void PrepareRegisterRangeInputOperand(Register start, int count);
+
+  Register GetEquivalentRegisterForInputOperand(Register reg);
+
+  static Register GetRegisterInputOperand(int index, Bytecode bytecode,
+                                          const uint32_t* operands,
+                                          int operand_count);
+  static Register GetRegisterOutputOperand(int index, Bytecode bytecode,
+                                           const uint32_t* operands,
+                                           int operand_count);
+
+  void CreateMaterializedEquivalent(RegisterInfo* info);
+  RegisterInfo* GetMaterializedEquivalent(RegisterInfo* info);
+  RegisterInfo* GetMaterializedEquivalentNotAccumulator(RegisterInfo* info);
+  void Materialize(RegisterInfo* info);
+  void AddToEquivalenceSet(RegisterInfo* set_member,
+                           RegisterInfo* non_set_member);
+
+  // Methods for finding and creating metadata for each register.
+  RegisterInfo* GetOrCreateRegisterInfo(Register reg);
+  RegisterInfo* GetRegisterInfo(Register reg);
+  RegisterInfo* NewRegisterInfo(Register reg);
+  void GrowRegisterMap(Register reg);
+
+  bool RegisterIsTemporary(Register reg) const {
+    return reg >= temporary_base_;
+  }
+
+  bool RegisterIsObservable(Register reg) const {
+    return reg != accumulator_ && !RegisterIsTemporary(reg);
+  }
+
+  static Register OperandToRegister(uint32_t operand) {
+    return Register::FromOperand(static_cast<int32_t>(operand));
+  }
+
+  size_t GetRegisterInfoTableIndex(Register reg) const {
+    return static_cast<size_t>(reg.index() + register_info_table_offset_);
+  }
+
+  Register RegisterFromRegisterInfoTableIndex(size_t index) const {
+    return Register(static_cast<int>(index) - register_info_table_offset_);
+  }
+
+  uint32_t NextEquivalenceId() {
+    equivalence_id_++;
+    CHECK_NE(equivalence_id_, kInvalidEquivalenceId);
+    return equivalence_id_;
+  }
+
+  Zone* zone() { return zone_; }
+
+  const Register accumulator_;
+  RegisterInfo* accumulator_info_;
+  const Register temporary_base_;
+
+  // Direct mapping to register info.
+  ZoneVector<RegisterInfo*> register_info_table_;
+  int register_info_table_offset_;
+
+  // Counter for equivalence sets identifiers.
+  int equivalence_id_;
+
+  BytecodePipelineStage* next_stage_;
+  bool flush_required_;
+  Zone* zone_;
+
+  DISALLOW_COPY_AND_ASSIGN(BytecodeRegisterOptimizer);
+};
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_INTERPRETER_BYTECODE_REGISTER_OPTIMIZER_H_
diff --git a/src/interpreter/bytecode-traits.h b/src/interpreter/bytecode-traits.h
index c724827..ea3d5d4 100644
--- a/src/interpreter/bytecode-traits.h
+++ b/src/interpreter/bytecode-traits.h
@@ -30,17 +30,41 @@
 
 template <OperandType>
 struct OperandTraits {
-  typedef OperandTypeInfoTraits<OperandTypeInfo::kNone> TypeInfo;
+  typedef OperandTypeInfoTraits<OperandTypeInfo::kNone> TypeInfoTraits;
+  static const OperandTypeInfo kOperandTypeInfo = OperandTypeInfo::kNone;
 };
 
-#define DECLARE_OPERAND_TYPE_TRAITS(Name, InfoType)   \
-  template <>                                         \
-  struct OperandTraits<OperandType::k##Name> {        \
-    typedef OperandTypeInfoTraits<InfoType> TypeInfo; \
+#define DECLARE_OPERAND_TYPE_TRAITS(Name, InfoType)           \
+  template <>                                                 \
+  struct OperandTraits<OperandType::k##Name> {                \
+    typedef OperandTypeInfoTraits<InfoType> TypeInfoTraits;   \
+    static const OperandTypeInfo kOperandTypeInfo = InfoType; \
   };
 OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE_TRAITS)
 #undef DECLARE_OPERAND_TYPE_TRAITS
 
+template <OperandType operand_type, OperandScale operand_scale>
+struct OperandScaler {
+  template <bool, OperandSize, OperandScale>
+  struct Helper {
+    static const int kSize = 0;
+  };
+  template <OperandSize size, OperandScale scale>
+  struct Helper<false, size, scale> {
+    static const int kSize = static_cast<int>(size);
+  };
+  template <OperandSize size, OperandScale scale>
+  struct Helper<true, size, scale> {
+    static const int kSize = static_cast<int>(size) * static_cast<int>(scale);
+  };
+
+  static const int kSize =
+      Helper<OperandTraits<operand_type>::TypeInfoTraits::kIsScalable,
+             OperandTraits<operand_type>::TypeInfoTraits::kUnscaledSize,
+             operand_scale>::kSize;
+  static const OperandSize kOperandSize = static_cast<OperandSize>(kSize);
+};
+
 template <OperandType>
 struct RegisterOperandTraits {
   static const int kIsRegisterOperand = 0;
@@ -61,11 +85,38 @@
           OperandType operand_1, OperandType operand_2, OperandType operand_3>
 struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2,
                       operand_3> {
-  static OperandType GetOperandType(int i) {
-    DCHECK(0 <= i && i < kOperandCount);
-    const OperandType kOperands[] = {operand_0, operand_1, operand_2,
-                                     operand_3};
-    return kOperands[i];
+  static const OperandType* GetOperandTypes() {
+    static const OperandType operand_types[] = {operand_0, operand_1, operand_2,
+                                                operand_3, OperandType::kNone};
+    return operand_types;
+  }
+
+  static const OperandTypeInfo* GetOperandTypeInfos() {
+    static const OperandTypeInfo operand_type_infos[] = {
+        OperandTraits<operand_0>::kOperandTypeInfo,
+        OperandTraits<operand_1>::kOperandTypeInfo,
+        OperandTraits<operand_2>::kOperandTypeInfo,
+        OperandTraits<operand_3>::kOperandTypeInfo, OperandTypeInfo::kNone};
+    return operand_type_infos;
+  }
+
+  static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
+    switch (operand_scale) {
+#define CASE(Name, _)                                                  \
+  case OperandScale::k##Name: {                                        \
+    static const OperandSize kOperandSizes[] = {                       \
+        OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \
+        OperandScaler<operand_1, OperandScale::k##Name>::kOperandSize, \
+        OperandScaler<operand_2, OperandScale::k##Name>::kOperandSize, \
+        OperandScaler<operand_3, OperandScale::k##Name>::kOperandSize, \
+    };                                                                 \
+    return kOperandSizes;                                              \
+  }
+      OPERAND_SCALE_LIST(CASE)
+#undef CASE
+    }
+    UNREACHABLE();
+    return nullptr;
   }
 
   template <OperandType ot>
@@ -75,10 +126,10 @@
   }
 
   static inline bool IsScalable() {
-    return (OperandTraits<operand_0>::TypeInfo::kIsScalable |
-            OperandTraits<operand_1>::TypeInfo::kIsScalable |
-            OperandTraits<operand_2>::TypeInfo::kIsScalable |
-            OperandTraits<operand_3>::TypeInfo::kIsScalable);
+    return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
+            OperandTraits<operand_1>::TypeInfoTraits::kIsScalable |
+            OperandTraits<operand_2>::TypeInfoTraits::kIsScalable |
+            OperandTraits<operand_3>::TypeInfoTraits::kIsScalable);
   }
 
   static const AccumulatorUse kAccumulatorUse = accumulator_use;
@@ -98,10 +149,36 @@
 template <AccumulatorUse accumulator_use, OperandType operand_0,
           OperandType operand_1, OperandType operand_2>
 struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2> {
-  static inline OperandType GetOperandType(int i) {
-    DCHECK(0 <= i && i <= 2);
-    const OperandType kOperands[] = {operand_0, operand_1, operand_2};
-    return kOperands[i];
+  static const OperandType* GetOperandTypes() {
+    static const OperandType operand_types[] = {operand_0, operand_1, operand_2,
+                                                OperandType::kNone};
+    return operand_types;
+  }
+
+  static const OperandTypeInfo* GetOperandTypeInfos() {
+    static const OperandTypeInfo operand_type_infos[] = {
+        OperandTraits<operand_0>::kOperandTypeInfo,
+        OperandTraits<operand_1>::kOperandTypeInfo,
+        OperandTraits<operand_2>::kOperandTypeInfo, OperandTypeInfo::kNone};
+    return operand_type_infos;
+  }
+
+  static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
+    switch (operand_scale) {
+#define CASE(Name, _)                                                  \
+  case OperandScale::k##Name: {                                        \
+    static const OperandSize kOperandSizes[] = {                       \
+        OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \
+        OperandScaler<operand_1, OperandScale::k##Name>::kOperandSize, \
+        OperandScaler<operand_2, OperandScale::k##Name>::kOperandSize, \
+    };                                                                 \
+    return kOperandSizes;                                              \
+  }
+      OPERAND_SCALE_LIST(CASE)
+#undef CASE
+    }
+    UNREACHABLE();
+    return nullptr;
   }
 
   template <OperandType ot>
@@ -110,9 +187,9 @@
   }
 
   static inline bool IsScalable() {
-    return (OperandTraits<operand_0>::TypeInfo::kIsScalable |
-            OperandTraits<operand_1>::TypeInfo::kIsScalable |
-            OperandTraits<operand_2>::TypeInfo::kIsScalable);
+    return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
+            OperandTraits<operand_1>::TypeInfoTraits::kIsScalable |
+            OperandTraits<operand_2>::TypeInfoTraits::kIsScalable);
   }
 
   static const AccumulatorUse kAccumulatorUse = accumulator_use;
@@ -130,10 +207,34 @@
 template <AccumulatorUse accumulator_use, OperandType operand_0,
           OperandType operand_1>
 struct BytecodeTraits<accumulator_use, operand_0, operand_1> {
-  static inline OperandType GetOperandType(int i) {
-    DCHECK(0 <= i && i < kOperandCount);
-    const OperandType kOperands[] = {operand_0, operand_1};
-    return kOperands[i];
+  static const OperandType* GetOperandTypes() {
+    static const OperandType operand_types[] = {operand_0, operand_1,
+                                                OperandType::kNone};
+    return operand_types;
+  }
+
+  static const OperandTypeInfo* GetOperandTypeInfos() {
+    static const OperandTypeInfo operand_type_infos[] = {
+        OperandTraits<operand_0>::kOperandTypeInfo,
+        OperandTraits<operand_1>::kOperandTypeInfo, OperandTypeInfo::kNone};
+    return operand_type_infos;
+  }
+
+  static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
+    switch (operand_scale) {
+#define CASE(Name, _)                                                  \
+  case OperandScale::k##Name: {                                        \
+    static const OperandSize kOperandSizes[] = {                       \
+        OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \
+        OperandScaler<operand_1, OperandScale::k##Name>::kOperandSize, \
+    };                                                                 \
+    return kOperandSizes;                                              \
+  }
+      OPERAND_SCALE_LIST(CASE)
+#undef CASE
+    }
+    UNREACHABLE();
+    return nullptr;
   }
 
   template <OperandType ot>
@@ -142,8 +243,8 @@
   }
 
   static inline bool IsScalable() {
-    return (OperandTraits<operand_0>::TypeInfo::kIsScalable |
-            OperandTraits<operand_1>::TypeInfo::kIsScalable);
+    return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
+            OperandTraits<operand_1>::TypeInfoTraits::kIsScalable);
   }
 
   static const AccumulatorUse kAccumulatorUse = accumulator_use;
@@ -158,9 +259,31 @@
 
 template <AccumulatorUse accumulator_use, OperandType operand_0>
 struct BytecodeTraits<accumulator_use, operand_0> {
-  static inline OperandType GetOperandType(int i) {
-    DCHECK(i == 0);
-    return operand_0;
+  static const OperandType* GetOperandTypes() {
+    static const OperandType operand_types[] = {operand_0, OperandType::kNone};
+    return operand_types;
+  }
+
+  static const OperandTypeInfo* GetOperandTypeInfos() {
+    static const OperandTypeInfo operand_type_infos[] = {
+        OperandTraits<operand_0>::kOperandTypeInfo, OperandTypeInfo::kNone};
+    return operand_type_infos;
+  }
+
+  static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
+    switch (operand_scale) {
+#define CASE(Name, _)                                                  \
+  case OperandScale::k##Name: {                                        \
+    static const OperandSize kOperandSizes[] = {                       \
+        OperandScaler<operand_0, OperandScale::k##Name>::kOperandSize, \
+    };                                                                 \
+    return kOperandSizes;                                              \
+  }
+      OPERAND_SCALE_LIST(CASE)
+#undef CASE
+    }
+    UNREACHABLE();
+    return nullptr;
   }
 
   template <OperandType ot>
@@ -169,7 +292,7 @@
   }
 
   static inline bool IsScalable() {
-    return OperandTraits<operand_0>::TypeInfo::kIsScalable;
+    return OperandTraits<operand_0>::TypeInfoTraits::kIsScalable;
   }
 
   static const AccumulatorUse kAccumulatorUse = accumulator_use;
@@ -182,9 +305,19 @@
 
 template <AccumulatorUse accumulator_use>
 struct BytecodeTraits<accumulator_use> {
-  static inline OperandType GetOperandType(int i) {
-    UNREACHABLE();
-    return OperandType::kNone;
+  static const OperandType* GetOperandTypes() {
+    static const OperandType operand_types[] = {OperandType::kNone};
+    return operand_types;
+  }
+
+  static const OperandTypeInfo* GetOperandTypeInfos() {
+    static const OperandTypeInfo operand_type_infos[] = {
+        OperandTypeInfo::kNone};
+    return operand_type_infos;
+  }
+
+  static const OperandSize* GetOperandSizes(OperandScale operand_scale) {
+    return nullptr;
   }
 
   template <OperandType ot>
@@ -200,37 +333,22 @@
   static const int kRegisterOperandBitmap = 0;
 };
 
-template <bool>
-struct OperandScaler {
-  static int Multiply(int size, int operand_scale) { return 0; }
-};
-
-template <>
-struct OperandScaler<false> {
-  static int Multiply(int size, int operand_scale) { return size; }
-};
-
-template <>
-struct OperandScaler<true> {
-  static int Multiply(int size, int operand_scale) {
-    return size * operand_scale;
-  }
-};
-
 static OperandSize ScaledOperandSize(OperandType operand_type,
                                      OperandScale operand_scale) {
+  STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 &&
+                OperandScale::kLast == OperandScale::kQuadruple);
+  int index = static_cast<int>(operand_scale) >> 1;
   switch (operand_type) {
-#define CASE(Name, TypeInfo)                                                   \
-  case OperandType::k##Name: {                                                 \
-    OperandSize base_size = OperandTypeInfoTraits<TypeInfo>::kUnscaledSize;    \
-    int size =                                                                 \
-        OperandScaler<OperandTypeInfoTraits<TypeInfo>::kIsScalable>::Multiply( \
-            static_cast<int>(base_size), static_cast<int>(operand_scale));     \
-    OperandSize operand_size = static_cast<OperandSize>(size);                 \
-    DCHECK(operand_size == OperandSize::kByte ||                               \
-           operand_size == OperandSize::kShort ||                              \
-           operand_size == OperandSize::kQuad);                                \
-    return operand_size;                                                       \
+#define CASE(Name, TypeInfo)                                    \
+  case OperandType::k##Name: {                                  \
+    static const OperandSize kOperandSizes[] = {                \
+        OperandScaler<OperandType::k##Name,                     \
+                      OperandScale::kSingle>::kOperandSize,     \
+        OperandScaler<OperandType::k##Name,                     \
+                      OperandScale::kDouble>::kOperandSize,     \
+        OperandScaler<OperandType::k##Name,                     \
+                      OperandScale::kQuadruple>::kOperandSize}; \
+    return kOperandSizes[index];                                \
   }
     OPERAND_TYPE_LIST(CASE)
 #undef CASE
diff --git a/src/interpreter/bytecodes.cc b/src/interpreter/bytecodes.cc
index fd27f39..44c5138 100644
--- a/src/interpreter/bytecodes.cc
+++ b/src/interpreter/bytecodes.cc
@@ -6,6 +6,7 @@
 
 #include <iomanip>
 
+#include "src/base/bits.h"
 #include "src/frames.h"
 #include "src/interpreter/bytecode-traits.h"
 #include "src/interpreter/interpreter.h"
@@ -74,15 +75,13 @@
 // static
 const char* Bytecodes::OperandScaleToString(OperandScale operand_scale) {
   switch (operand_scale) {
-    case OperandScale::kSingle:
-      return "Single";
-    case OperandScale::kDouble:
-      return "Double";
-    case OperandScale::kQuadruple:
-      return "Quadruple";
-    case OperandScale::kInvalid:
-      UNREACHABLE();
+#define CASE(Name, _)         \
+  case OperandScale::k##Name: \
+    return #Name;
+    OPERAND_SCALE_LIST(CASE)
+#undef CASE
   }
+  UNREACHABLE();
   return "";
 }
 
@@ -102,14 +101,6 @@
   return "";
 }
 
-
-// static
-uint8_t Bytecodes::ToByte(Bytecode bytecode) {
-  DCHECK(bytecode <= Bytecode::kLast);
-  return static_cast<uint8_t>(bytecode);
-}
-
-
 // static
 Bytecode Bytecodes::FromByte(uint8_t value) {
   Bytecode bytecode = static_cast<Bytecode>(value);
@@ -117,7 +108,6 @@
   return bytecode;
 }
 
-
 // static
 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) {
   DCHECK(!IsDebugBreak(bytecode));
@@ -150,6 +140,10 @@
   return size;
 }
 
+// static
+size_t Bytecodes::ReturnCount(Bytecode bytecode) {
+  return bytecode == Bytecode::kReturn ? 1 : 0;
+}
 
 // static
 int Bytecodes::NumberOfOperands(Bytecode bytecode) {
@@ -165,7 +159,6 @@
   return 0;
 }
 
-
 // static
 int Bytecodes::NumberOfRegisterOperands(Bytecode bytecode) {
   DCHECK(bytecode <= Bytecode::kLast);
@@ -241,24 +234,130 @@
 }
 
 // static
+bool Bytecodes::WritesBooleanToAccumulator(Bytecode bytecode) {
+  switch (bytecode) {
+    case Bytecode::kLdaTrue:
+    case Bytecode::kLdaFalse:
+    case Bytecode::kToBooleanLogicalNot:
+    case Bytecode::kLogicalNot:
+    case Bytecode::kTestEqual:
+    case Bytecode::kTestNotEqual:
+    case Bytecode::kTestEqualStrict:
+    case Bytecode::kTestLessThan:
+    case Bytecode::kTestLessThanOrEqual:
+    case Bytecode::kTestGreaterThan:
+    case Bytecode::kTestGreaterThanOrEqual:
+    case Bytecode::kTestInstanceOf:
+    case Bytecode::kTestIn:
+    case Bytecode::kForInDone:
+      return true;
+    default:
+      return false;
+  }
+}
+
+// static
+bool Bytecodes::IsAccumulatorLoadWithoutEffects(Bytecode bytecode) {
+  switch (bytecode) {
+    case Bytecode::kLdaZero:
+    case Bytecode::kLdaSmi:
+    case Bytecode::kLdaUndefined:
+    case Bytecode::kLdaNull:
+    case Bytecode::kLdaTheHole:
+    case Bytecode::kLdaTrue:
+    case Bytecode::kLdaFalse:
+    case Bytecode::kLdaConstant:
+    case Bytecode::kLdar:
+      return true;
+    default:
+      return false;
+  }
+}
+
+// static
+bool Bytecodes::IsJumpWithoutEffects(Bytecode bytecode) {
+  return IsJump(bytecode) && !IsJumpIfToBoolean(bytecode);
+}
+
+// static
+bool Bytecodes::IsRegisterLoadWithoutEffects(Bytecode bytecode) {
+  switch (bytecode) {
+    case Bytecode::kMov:
+    case Bytecode::kPopContext:
+    case Bytecode::kPushContext:
+    case Bytecode::kStar:
+    case Bytecode::kLdrUndefined:
+      return true;
+    default:
+      return false;
+  }
+}
+
+// static
+bool Bytecodes::IsWithoutExternalSideEffects(Bytecode bytecode) {
+  // These bytecodes only manipulate interpreter frame state and will
+  // never throw.
+  return (IsAccumulatorLoadWithoutEffects(bytecode) ||
+          IsRegisterLoadWithoutEffects(bytecode) ||
+          bytecode == Bytecode::kNop || IsJumpWithoutEffects(bytecode));
+}
+
+// static
 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) {
+  DCHECK_LE(bytecode, Bytecode::kLast);
+  DCHECK_LT(i, NumberOfOperands(bytecode));
+  DCHECK_GE(i, 0);
+  return GetOperandTypes(bytecode)[i];
+}
+
+// static
+const OperandType* Bytecodes::GetOperandTypes(Bytecode bytecode) {
   DCHECK(bytecode <= Bytecode::kLast);
   switch (bytecode) {
 #define CASE(Name, ...)   \
   case Bytecode::k##Name: \
-    return BytecodeTraits<__VA_ARGS__>::GetOperandType(i);
+    return BytecodeTraits<__VA_ARGS__>::GetOperandTypes();
     BYTECODE_LIST(CASE)
 #undef CASE
   }
   UNREACHABLE();
-  return OperandType::kNone;
+  return nullptr;
+}
+
+// static
+const OperandTypeInfo* Bytecodes::GetOperandTypeInfos(Bytecode bytecode) {
+  DCHECK(bytecode <= Bytecode::kLast);
+  switch (bytecode) {
+#define CASE(Name, ...)   \
+  case Bytecode::k##Name: \
+    return BytecodeTraits<__VA_ARGS__>::GetOperandTypeInfos();
+    BYTECODE_LIST(CASE)
+#undef CASE
+  }
+  UNREACHABLE();
+  return nullptr;
 }
 
 // static
 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i,
                                       OperandScale operand_scale) {
-  OperandType op_type = GetOperandType(bytecode, i);
-  return ScaledOperandSize(op_type, operand_scale);
+  DCHECK_LT(i, NumberOfOperands(bytecode));
+  return GetOperandSizes(bytecode, operand_scale)[i];
+}
+
+// static
+const OperandSize* Bytecodes::GetOperandSizes(Bytecode bytecode,
+                                              OperandScale operand_scale) {
+  DCHECK(bytecode <= Bytecode::kLast);
+  switch (bytecode) {
+#define CASE(Name, ...)   \
+  case Bytecode::k##Name: \
+    return BytecodeTraits<__VA_ARGS__>::GetOperandSizes(operand_scale);
+    BYTECODE_LIST(CASE)
+#undef CASE
+  }
+  UNREACHABLE();
+  return nullptr;
 }
 
 // static
@@ -279,6 +378,7 @@
 // static
 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i,
                                 OperandScale operand_scale) {
+  DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode));
   // TODO(oth): restore this to a statically determined constant.
   int offset = 1;
   for (int operand_index = 0; operand_index < i; ++operand_index) {
@@ -343,6 +443,31 @@
   return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode);
 }
 
+// static
+bool Bytecodes::IsJumpIfToBoolean(Bytecode bytecode) {
+  return bytecode == Bytecode::kJumpIfToBooleanTrue ||
+         bytecode == Bytecode::kJumpIfToBooleanFalse ||
+         bytecode == Bytecode::kJumpIfToBooleanTrueConstant ||
+         bytecode == Bytecode::kJumpIfToBooleanFalseConstant;
+}
+
+// static
+Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) {
+  switch (bytecode) {
+    case Bytecode::kJumpIfToBooleanTrue:
+      return Bytecode::kJumpIfTrue;
+    case Bytecode::kJumpIfToBooleanFalse:
+      return Bytecode::kJumpIfFalse;
+    case Bytecode::kJumpIfToBooleanTrueConstant:
+      return Bytecode::kJumpIfTrueConstant;
+    case Bytecode::kJumpIfToBooleanFalseConstant:
+      return Bytecode::kJumpIfFalseConstant;
+    default:
+      break;
+  }
+  UNREACHABLE();
+  return Bytecode::kIllegal;
+}
 
 // static
 bool Bytecodes::IsCallOrNew(Bytecode bytecode) {
@@ -371,6 +496,11 @@
 }
 
 // static
+bool Bytecodes::IsLdarOrStar(Bytecode bytecode) {
+  return bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar;
+}
+
+// static
 bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) {
   switch (bytecode) {
 #define CASE(Name, ...)                              \
@@ -461,11 +591,29 @@
 }
 
 // static
+int Bytecodes::GetNumberOfRegistersRepresentedBy(OperandType operand_type) {
+  switch (operand_type) {
+    case OperandType::kMaybeReg:
+    case OperandType::kReg:
+    case OperandType::kRegOut:
+      return 1;
+    case OperandType::kRegPair:
+    case OperandType::kRegOutPair:
+      return 2;
+    case OperandType::kRegOutTriple:
+      return 3;
+    default:
+      UNREACHABLE();
+  }
+  return 0;
+}
+
+// static
 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) {
   switch (operand_type) {
 #define CASE(Name, _)        \
   case OperandType::k##Name: \
-    return OperandTraits<OperandType::k##Name>::TypeInfo::kIsUnsigned;
+    return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned;
     OPERAND_TYPE_LIST(CASE)
 #undef CASE
   }
@@ -474,10 +622,25 @@
 }
 
 // static
-OperandScale Bytecodes::NextOperandScale(OperandScale operand_scale) {
-  DCHECK(operand_scale >= OperandScale::kSingle &&
-         operand_scale <= OperandScale::kMaxValid);
-  return static_cast<OperandScale>(2 * static_cast<int>(operand_scale));
+OperandSize Bytecodes::SizeForSignedOperand(int value) {
+  if (value >= kMinInt8 && value <= kMaxInt8) {
+    return OperandSize::kByte;
+  } else if (value >= kMinInt16 && value <= kMaxInt16) {
+    return OperandSize::kShort;
+  } else {
+    return OperandSize::kQuad;
+  }
+}
+
+// static
+OperandSize Bytecodes::SizeForUnsignedOperand(uint32_t value) {
+  if (value <= kMaxUInt8) {
+    return OperandSize::kByte;
+  } else if (value <= kMaxUInt16) {
+    return OperandSize::kShort;
+  } else {
+    return OperandSize::kQuad;
+  }
 }
 
 // static
@@ -574,6 +737,7 @@
         break;
       case interpreter::OperandType::kIdx:
       case interpreter::OperandType::kRuntimeId:
+      case interpreter::OperandType::kIntrinsicId:
         os << "["
            << DecodeUnsignedOperand(operand_start, op_type, operand_scale)
            << "]";
@@ -645,21 +809,33 @@
 }
 
 static const int kLastParamRegisterIndex =
-    -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize;
+    (InterpreterFrameConstants::kRegisterFileFromFp -
+     InterpreterFrameConstants::kLastParamFromFp) /
+    kPointerSize;
 static const int kFunctionClosureRegisterIndex =
-    -InterpreterFrameConstants::kFunctionFromRegisterPointer / kPointerSize;
+    (InterpreterFrameConstants::kRegisterFileFromFp -
+     StandardFrameConstants::kFunctionOffset) /
+    kPointerSize;
 static const int kCurrentContextRegisterIndex =
-    -InterpreterFrameConstants::kContextFromRegisterPointer / kPointerSize;
+    (InterpreterFrameConstants::kRegisterFileFromFp -
+     StandardFrameConstants::kContextOffset) /
+    kPointerSize;
 static const int kNewTargetRegisterIndex =
-    -InterpreterFrameConstants::kNewTargetFromRegisterPointer / kPointerSize;
-
-bool Register::is_byte_operand() const {
-  return index_ >= -kMaxInt8 && index_ <= -kMinInt8;
-}
-
-bool Register::is_short_operand() const {
-  return index_ >= -kMaxInt16 && index_ <= -kMinInt16;
-}
+    (InterpreterFrameConstants::kRegisterFileFromFp -
+     InterpreterFrameConstants::kNewTargetFromFp) /
+    kPointerSize;
+static const int kBytecodeArrayRegisterIndex =
+    (InterpreterFrameConstants::kRegisterFileFromFp -
+     InterpreterFrameConstants::kBytecodeArrayFromFp) /
+    kPointerSize;
+static const int kBytecodeOffsetRegisterIndex =
+    (InterpreterFrameConstants::kRegisterFileFromFp -
+     InterpreterFrameConstants::kBytecodeOffsetFromFp) /
+    kPointerSize;
+static const int kCallerPCOffsetRegisterIndex =
+    (InterpreterFrameConstants::kRegisterFileFromFp -
+     InterpreterFrameConstants::kCallerPCOffsetFromFp) /
+    kPointerSize;
 
 Register Register::FromParameterIndex(int index, int parameter_count) {
   DCHECK_GE(index, 0);
@@ -669,40 +845,65 @@
   return Register(register_index);
 }
 
-
 int Register::ToParameterIndex(int parameter_count) const {
   DCHECK(is_parameter());
   return index() - kLastParamRegisterIndex + parameter_count - 1;
 }
 
-
 Register Register::function_closure() {
   return Register(kFunctionClosureRegisterIndex);
 }
 
-
 bool Register::is_function_closure() const {
   return index() == kFunctionClosureRegisterIndex;
 }
 
-
 Register Register::current_context() {
   return Register(kCurrentContextRegisterIndex);
 }
 
-
 bool Register::is_current_context() const {
   return index() == kCurrentContextRegisterIndex;
 }
 
-
 Register Register::new_target() { return Register(kNewTargetRegisterIndex); }
 
-
 bool Register::is_new_target() const {
   return index() == kNewTargetRegisterIndex;
 }
 
+Register Register::bytecode_array() {
+  return Register(kBytecodeArrayRegisterIndex);
+}
+
+bool Register::is_bytecode_array() const {
+  return index() == kBytecodeArrayRegisterIndex;
+}
+
+Register Register::bytecode_offset() {
+  return Register(kBytecodeOffsetRegisterIndex);
+}
+
+bool Register::is_bytecode_offset() const {
+  return index() == kBytecodeOffsetRegisterIndex;
+}
+
+// static
+Register Register::virtual_accumulator() {
+  return Register(kCallerPCOffsetRegisterIndex);
+}
+
+OperandSize Register::SizeOfOperand() const {
+  int32_t operand = ToOperand();
+  if (operand >= kMinInt8 && operand <= kMaxInt8) {
+    return OperandSize::kByte;
+  } else if (operand >= kMinInt16 && operand <= kMaxInt16) {
+    return OperandSize::kShort;
+  } else {
+    return OperandSize::kQuad;
+  }
+}
+
 bool Register::AreContiguous(Register reg1, Register reg2, Register reg3,
                              Register reg4, Register reg5) {
   if (reg1.index() + 1 != reg2.index()) {
diff --git a/src/interpreter/bytecodes.h b/src/interpreter/bytecodes.h
index 2361271..63a69f1 100644
--- a/src/interpreter/bytecodes.h
+++ b/src/interpreter/bytecodes.h
@@ -9,6 +9,7 @@
 
 // Clients of this interface shouldn't depend on lots of interpreter internals.
 // Do not include anything from src/interpreter here!
+#include "src/frames.h"
 #include "src/utils.h"
 
 namespace v8 {
@@ -29,6 +30,7 @@
 
 #define SCALAR_OPERAND_TYPE_LIST(V)                   \
   V(Flag8, OperandTypeInfo::kFixedUnsignedByte)       \
+  V(IntrinsicId, OperandTypeInfo::kFixedUnsignedByte) \
   V(Idx, OperandTypeInfo::kScalableUnsignedByte)      \
   V(Imm, OperandTypeInfo::kScalableSignedByte)        \
   V(RegCount, OperandTypeInfo::kScalableUnsignedByte) \
@@ -72,180 +74,198 @@
   DEBUG_BREAK_PREFIX_BYTECODE_LIST(V)
 
 // The list of bytecodes which are interpreted by the interpreter.
-#define BYTECODE_LIST(V)                                                      \
-  /* Extended width operands */                                               \
-  V(Wide, AccumulatorUse::kNone)                                              \
-  V(ExtraWide, AccumulatorUse::kNone)                                         \
-                                                                              \
-  /* Loading the accumulator */                                               \
-  V(LdaZero, AccumulatorUse::kWrite)                                          \
-  V(LdaSmi, AccumulatorUse::kWrite, OperandType::kImm)                        \
-  V(LdaUndefined, AccumulatorUse::kWrite)                                     \
-  V(LdaNull, AccumulatorUse::kWrite)                                          \
-  V(LdaTheHole, AccumulatorUse::kWrite)                                       \
-  V(LdaTrue, AccumulatorUse::kWrite)                                          \
-  V(LdaFalse, AccumulatorUse::kWrite)                                         \
-  V(LdaConstant, AccumulatorUse::kWrite, OperandType::kIdx)                   \
-                                                                              \
-  /* Globals */                                                               \
-  V(LdaGlobal, AccumulatorUse::kWrite, OperandType::kIdx, OperandType::kIdx)  \
-  V(LdaGlobalInsideTypeof, AccumulatorUse::kWrite, OperandType::kIdx,         \
-    OperandType::kIdx)                                                        \
-  V(StaGlobalSloppy, AccumulatorUse::kRead, OperandType::kIdx,                \
-    OperandType::kIdx)                                                        \
-  V(StaGlobalStrict, AccumulatorUse::kRead, OperandType::kIdx,                \
-    OperandType::kIdx)                                                        \
-                                                                              \
-  /* Context operations */                                                    \
-  V(PushContext, AccumulatorUse::kRead, OperandType::kReg)                    \
-  V(PopContext, AccumulatorUse::kNone, OperandType::kReg)                     \
-  V(LdaContextSlot, AccumulatorUse::kWrite, OperandType::kReg,                \
-    OperandType::kIdx)                                                        \
-  V(StaContextSlot, AccumulatorUse::kRead, OperandType::kReg,                 \
-    OperandType::kIdx)                                                        \
-                                                                              \
-  /* Load-Store lookup slots */                                               \
-  V(LdaLookupSlot, AccumulatorUse::kWrite, OperandType::kIdx)                 \
-  V(LdaLookupSlotInsideTypeof, AccumulatorUse::kWrite, OperandType::kIdx)     \
-  V(StaLookupSlotSloppy, AccumulatorUse::kReadWrite, OperandType::kIdx)       \
-  V(StaLookupSlotStrict, AccumulatorUse::kReadWrite, OperandType::kIdx)       \
-                                                                              \
-  /* Register-accumulator transfers */                                        \
-  V(Ldar, AccumulatorUse::kWrite, OperandType::kReg)                          \
-  V(Star, AccumulatorUse::kRead, OperandType::kRegOut)                        \
-                                                                              \
-  /* Register-register transfers */                                           \
-  V(Mov, AccumulatorUse::kNone, OperandType::kReg, OperandType::kRegOut)      \
-                                                                              \
-  /* LoadIC operations */                                                     \
-  V(LoadIC, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kIdx,     \
-    OperandType::kIdx)                                                        \
-  V(KeyedLoadIC, AccumulatorUse::kReadWrite, OperandType::kReg,               \
-    OperandType::kIdx)                                                        \
-                                                                              \
-  /* StoreIC operations */                                                    \
-  V(StoreICSloppy, AccumulatorUse::kRead, OperandType::kReg,                  \
-    OperandType::kIdx, OperandType::kIdx)                                     \
-  V(StoreICStrict, AccumulatorUse::kRead, OperandType::kReg,                  \
-    OperandType::kIdx, OperandType::kIdx)                                     \
-  V(KeyedStoreICSloppy, AccumulatorUse::kRead, OperandType::kReg,             \
-    OperandType::kReg, OperandType::kIdx)                                     \
-  V(KeyedStoreICStrict, AccumulatorUse::kRead, OperandType::kReg,             \
-    OperandType::kReg, OperandType::kIdx)                                     \
-                                                                              \
-  /* Binary Operators */                                                      \
-  V(Add, AccumulatorUse::kReadWrite, OperandType::kReg)                       \
-  V(Sub, AccumulatorUse::kReadWrite, OperandType::kReg)                       \
-  V(Mul, AccumulatorUse::kReadWrite, OperandType::kReg)                       \
-  V(Div, AccumulatorUse::kReadWrite, OperandType::kReg)                       \
-  V(Mod, AccumulatorUse::kReadWrite, OperandType::kReg)                       \
-  V(BitwiseOr, AccumulatorUse::kReadWrite, OperandType::kReg)                 \
-  V(BitwiseXor, AccumulatorUse::kReadWrite, OperandType::kReg)                \
-  V(BitwiseAnd, AccumulatorUse::kReadWrite, OperandType::kReg)                \
-  V(ShiftLeft, AccumulatorUse::kReadWrite, OperandType::kReg)                 \
-  V(ShiftRight, AccumulatorUse::kReadWrite, OperandType::kReg)                \
-  V(ShiftRightLogical, AccumulatorUse::kReadWrite, OperandType::kReg)         \
-                                                                              \
-  /* Unary Operators */                                                       \
-  V(Inc, AccumulatorUse::kReadWrite)                                          \
-  V(Dec, AccumulatorUse::kReadWrite)                                          \
-  V(LogicalNot, AccumulatorUse::kReadWrite)                                   \
-  V(TypeOf, AccumulatorUse::kReadWrite)                                       \
-  V(DeletePropertyStrict, AccumulatorUse::kReadWrite, OperandType::kReg)      \
-  V(DeletePropertySloppy, AccumulatorUse::kReadWrite, OperandType::kReg)      \
-                                                                              \
-  /* Call operations */                                                       \
-  V(Call, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kReg,       \
-    OperandType::kRegCount, OperandType::kIdx)                                \
-  V(TailCall, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kReg,   \
-    OperandType::kRegCount, OperandType::kIdx)                                \
-  V(CallRuntime, AccumulatorUse::kWrite, OperandType::kRuntimeId,             \
-    OperandType::kMaybeReg, OperandType::kRegCount)                           \
-  V(CallRuntimeForPair, AccumulatorUse::kNone, OperandType::kRuntimeId,       \
-    OperandType::kMaybeReg, OperandType::kRegCount, OperandType::kRegOutPair) \
-  V(CallJSRuntime, AccumulatorUse::kWrite, OperandType::kIdx,                 \
-    OperandType::kReg, OperandType::kRegCount)                                \
-                                                                              \
-  /* Intrinsics */                                                            \
-  V(InvokeIntrinsic, AccumulatorUse::kWrite, OperandType::kRuntimeId,         \
-    OperandType::kMaybeReg, OperandType::kRegCount)                           \
-                                                                              \
-  /* New operator */                                                          \
-  V(New, AccumulatorUse::kReadWrite, OperandType::kReg,                       \
-    OperandType::kMaybeReg, OperandType::kRegCount)                           \
-                                                                              \
-  /* Test Operators */                                                        \
-  V(TestEqual, AccumulatorUse::kReadWrite, OperandType::kReg)                 \
-  V(TestNotEqual, AccumulatorUse::kReadWrite, OperandType::kReg)              \
-  V(TestEqualStrict, AccumulatorUse::kReadWrite, OperandType::kReg)           \
-  V(TestLessThan, AccumulatorUse::kReadWrite, OperandType::kReg)              \
-  V(TestGreaterThan, AccumulatorUse::kReadWrite, OperandType::kReg)           \
-  V(TestLessThanOrEqual, AccumulatorUse::kReadWrite, OperandType::kReg)       \
-  V(TestGreaterThanOrEqual, AccumulatorUse::kReadWrite, OperandType::kReg)    \
-  V(TestInstanceOf, AccumulatorUse::kReadWrite, OperandType::kReg)            \
-  V(TestIn, AccumulatorUse::kReadWrite, OperandType::kReg)                    \
-                                                                              \
-  /* Cast operators */                                                        \
-  V(ToName, AccumulatorUse::kReadWrite)                                       \
-  V(ToNumber, AccumulatorUse::kReadWrite)                                     \
-  V(ToObject, AccumulatorUse::kReadWrite)                                     \
-                                                                              \
-  /* Literals */                                                              \
-  V(CreateRegExpLiteral, AccumulatorUse::kWrite, OperandType::kIdx,           \
-    OperandType::kIdx, OperandType::kFlag8)                                   \
-  V(CreateArrayLiteral, AccumulatorUse::kWrite, OperandType::kIdx,            \
-    OperandType::kIdx, OperandType::kFlag8)                                   \
-  V(CreateObjectLiteral, AccumulatorUse::kWrite, OperandType::kIdx,           \
-    OperandType::kIdx, OperandType::kFlag8)                                   \
-                                                                              \
-  /* Closure allocation */                                                    \
-  V(CreateClosure, AccumulatorUse::kWrite, OperandType::kIdx,                 \
-    OperandType::kFlag8)                                                      \
-                                                                              \
-  /* Arguments allocation */                                                  \
-  V(CreateMappedArguments, AccumulatorUse::kWrite)                            \
-  V(CreateUnmappedArguments, AccumulatorUse::kWrite)                          \
-  V(CreateRestParameter, AccumulatorUse::kWrite)                              \
-                                                                              \
-  /* Control Flow */                                                          \
-  V(Jump, AccumulatorUse::kNone, OperandType::kImm)                           \
-  V(JumpConstant, AccumulatorUse::kNone, OperandType::kIdx)                   \
-  V(JumpIfTrue, AccumulatorUse::kRead, OperandType::kImm)                     \
-  V(JumpIfTrueConstant, AccumulatorUse::kRead, OperandType::kIdx)             \
-  V(JumpIfFalse, AccumulatorUse::kRead, OperandType::kImm)                    \
-  V(JumpIfFalseConstant, AccumulatorUse::kRead, OperandType::kIdx)            \
-  V(JumpIfToBooleanTrue, AccumulatorUse::kRead, OperandType::kImm)            \
-  V(JumpIfToBooleanTrueConstant, AccumulatorUse::kRead, OperandType::kIdx)    \
-  V(JumpIfToBooleanFalse, AccumulatorUse::kRead, OperandType::kImm)           \
-  V(JumpIfToBooleanFalseConstant, AccumulatorUse::kRead, OperandType::kIdx)   \
-  V(JumpIfNull, AccumulatorUse::kRead, OperandType::kImm)                     \
-  V(JumpIfNullConstant, AccumulatorUse::kRead, OperandType::kIdx)             \
-  V(JumpIfUndefined, AccumulatorUse::kRead, OperandType::kImm)                \
-  V(JumpIfUndefinedConstant, AccumulatorUse::kRead, OperandType::kIdx)        \
-  V(JumpIfNotHole, AccumulatorUse::kRead, OperandType::kImm)                  \
-  V(JumpIfNotHoleConstant, AccumulatorUse::kRead, OperandType::kIdx)          \
-                                                                              \
-  /* Complex flow control For..in */                                          \
-  V(ForInPrepare, AccumulatorUse::kRead, OperandType::kRegOutTriple)          \
-  V(ForInDone, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kReg)  \
-  V(ForInNext, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kReg,  \
-    OperandType::kRegPair, OperandType::kIdx)                                 \
-  V(ForInStep, AccumulatorUse::kWrite, OperandType::kReg)                     \
-                                                                              \
-  /* Perform a stack guard check */                                           \
-  V(StackCheck, AccumulatorUse::kNone)                                        \
-                                                                              \
-  /* Non-local flow control */                                                \
-  V(Throw, AccumulatorUse::kRead)                                             \
-  V(ReThrow, AccumulatorUse::kRead)                                           \
-  V(Return, AccumulatorUse::kNone)                                            \
-                                                                              \
-  /* Debugger */                                                              \
-  V(Debugger, AccumulatorUse::kNone)                                          \
-  DEBUG_BREAK_BYTECODE_LIST(V)                                                \
-                                                                              \
-  /* Illegal bytecode (terminates execution) */                               \
-  V(Illegal, AccumulatorUse::kNone)
+#define BYTECODE_LIST(V)                                                       \
+  /* Extended width operands */                                                \
+  V(Wide, AccumulatorUse::kNone)                                               \
+  V(ExtraWide, AccumulatorUse::kNone)                                          \
+                                                                               \
+  /* Loading the accumulator */                                                \
+  V(LdaZero, AccumulatorUse::kWrite)                                           \
+  V(LdaSmi, AccumulatorUse::kWrite, OperandType::kImm)                         \
+  V(LdaUndefined, AccumulatorUse::kWrite)                                      \
+  V(LdaNull, AccumulatorUse::kWrite)                                           \
+  V(LdaTheHole, AccumulatorUse::kWrite)                                        \
+  V(LdaTrue, AccumulatorUse::kWrite)                                           \
+  V(LdaFalse, AccumulatorUse::kWrite)                                          \
+  V(LdaConstant, AccumulatorUse::kWrite, OperandType::kIdx)                    \
+                                                                               \
+  /* Loading registers */                                                      \
+  V(LdrUndefined, AccumulatorUse::kNone, OperandType::kRegOut)                 \
+                                                                               \
+  /* Globals */                                                                \
+  V(LdaGlobal, AccumulatorUse::kWrite, OperandType::kIdx)                      \
+  V(LdrGlobal, AccumulatorUse::kNone, OperandType::kIdx, OperandType::kRegOut) \
+  V(LdaGlobalInsideTypeof, AccumulatorUse::kWrite, OperandType::kIdx)          \
+  V(StaGlobalSloppy, AccumulatorUse::kRead, OperandType::kIdx,                 \
+    OperandType::kIdx)                                                         \
+  V(StaGlobalStrict, AccumulatorUse::kRead, OperandType::kIdx,                 \
+    OperandType::kIdx)                                                         \
+                                                                               \
+  /* Context operations */                                                     \
+  V(PushContext, AccumulatorUse::kRead, OperandType::kRegOut)                  \
+  V(PopContext, AccumulatorUse::kNone, OperandType::kReg)                      \
+  V(LdaContextSlot, AccumulatorUse::kWrite, OperandType::kReg,                 \
+    OperandType::kIdx)                                                         \
+  V(LdrContextSlot, AccumulatorUse::kNone, OperandType::kReg,                  \
+    OperandType::kIdx, OperandType::kRegOut)                                   \
+  V(StaContextSlot, AccumulatorUse::kRead, OperandType::kReg,                  \
+    OperandType::kIdx)                                                         \
+                                                                               \
+  /* Load-Store lookup slots */                                                \
+  V(LdaLookupSlot, AccumulatorUse::kWrite, OperandType::kIdx)                  \
+  V(LdaLookupSlotInsideTypeof, AccumulatorUse::kWrite, OperandType::kIdx)      \
+  V(StaLookupSlotSloppy, AccumulatorUse::kReadWrite, OperandType::kIdx)        \
+  V(StaLookupSlotStrict, AccumulatorUse::kReadWrite, OperandType::kIdx)        \
+                                                                               \
+  /* Register-accumulator transfers */                                         \
+  V(Ldar, AccumulatorUse::kWrite, OperandType::kReg)                           \
+  V(Star, AccumulatorUse::kRead, OperandType::kRegOut)                         \
+                                                                               \
+  /* Register-register transfers */                                            \
+  V(Mov, AccumulatorUse::kNone, OperandType::kReg, OperandType::kRegOut)       \
+                                                                               \
+  /* Property loads (LoadIC) operations */                                     \
+  V(LdaNamedProperty, AccumulatorUse::kWrite, OperandType::kReg,               \
+    OperandType::kIdx, OperandType::kIdx)                                      \
+  V(LdrNamedProperty, AccumulatorUse::kNone, OperandType::kReg,                \
+    OperandType::kIdx, OperandType::kIdx, OperandType::kRegOut)                \
+  V(LdaKeyedProperty, AccumulatorUse::kReadWrite, OperandType::kReg,           \
+    OperandType::kIdx)                                                         \
+  V(LdrKeyedProperty, AccumulatorUse::kRead, OperandType::kReg,                \
+    OperandType::kIdx, OperandType::kRegOut)                                   \
+                                                                               \
+  /* Propery stores (StoreIC) operations */                                    \
+  V(StaNamedPropertySloppy, AccumulatorUse::kRead, OperandType::kReg,          \
+    OperandType::kIdx, OperandType::kIdx)                                      \
+  V(StaNamedPropertyStrict, AccumulatorUse::kRead, OperandType::kReg,          \
+    OperandType::kIdx, OperandType::kIdx)                                      \
+  V(StaKeyedPropertySloppy, AccumulatorUse::kRead, OperandType::kReg,          \
+    OperandType::kReg, OperandType::kIdx)                                      \
+  V(StaKeyedPropertyStrict, AccumulatorUse::kRead, OperandType::kReg,          \
+    OperandType::kReg, OperandType::kIdx)                                      \
+                                                                               \
+  /* Binary Operators */                                                       \
+  V(Add, AccumulatorUse::kReadWrite, OperandType::kReg)                        \
+  V(Sub, AccumulatorUse::kReadWrite, OperandType::kReg)                        \
+  V(Mul, AccumulatorUse::kReadWrite, OperandType::kReg)                        \
+  V(Div, AccumulatorUse::kReadWrite, OperandType::kReg)                        \
+  V(Mod, AccumulatorUse::kReadWrite, OperandType::kReg)                        \
+  V(BitwiseOr, AccumulatorUse::kReadWrite, OperandType::kReg)                  \
+  V(BitwiseXor, AccumulatorUse::kReadWrite, OperandType::kReg)                 \
+  V(BitwiseAnd, AccumulatorUse::kReadWrite, OperandType::kReg)                 \
+  V(ShiftLeft, AccumulatorUse::kReadWrite, OperandType::kReg)                  \
+  V(ShiftRight, AccumulatorUse::kReadWrite, OperandType::kReg)                 \
+  V(ShiftRightLogical, AccumulatorUse::kReadWrite, OperandType::kReg)          \
+                                                                               \
+  /* Unary Operators */                                                        \
+  V(Inc, AccumulatorUse::kReadWrite)                                           \
+  V(Dec, AccumulatorUse::kReadWrite)                                           \
+  V(ToBooleanLogicalNot, AccumulatorUse::kReadWrite)                           \
+  V(LogicalNot, AccumulatorUse::kReadWrite)                                    \
+  V(TypeOf, AccumulatorUse::kReadWrite)                                        \
+  V(DeletePropertyStrict, AccumulatorUse::kReadWrite, OperandType::kReg)       \
+  V(DeletePropertySloppy, AccumulatorUse::kReadWrite, OperandType::kReg)       \
+                                                                               \
+  /* Call operations */                                                        \
+  V(Call, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kReg,        \
+    OperandType::kRegCount, OperandType::kIdx)                                 \
+  V(TailCall, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kReg,    \
+    OperandType::kRegCount, OperandType::kIdx)                                 \
+  V(CallRuntime, AccumulatorUse::kWrite, OperandType::kRuntimeId,              \
+    OperandType::kMaybeReg, OperandType::kRegCount)                            \
+  V(CallRuntimeForPair, AccumulatorUse::kNone, OperandType::kRuntimeId,        \
+    OperandType::kMaybeReg, OperandType::kRegCount, OperandType::kRegOutPair)  \
+  V(CallJSRuntime, AccumulatorUse::kWrite, OperandType::kIdx,                  \
+    OperandType::kReg, OperandType::kRegCount)                                 \
+                                                                               \
+  /* Intrinsics */                                                             \
+  V(InvokeIntrinsic, AccumulatorUse::kWrite, OperandType::kIntrinsicId,        \
+    OperandType::kMaybeReg, OperandType::kRegCount)                            \
+                                                                               \
+  /* New operator */                                                           \
+  V(New, AccumulatorUse::kReadWrite, OperandType::kReg,                        \
+    OperandType::kMaybeReg, OperandType::kRegCount)                            \
+                                                                               \
+  /* Test Operators */                                                         \
+  V(TestEqual, AccumulatorUse::kReadWrite, OperandType::kReg)                  \
+  V(TestNotEqual, AccumulatorUse::kReadWrite, OperandType::kReg)               \
+  V(TestEqualStrict, AccumulatorUse::kReadWrite, OperandType::kReg)            \
+  V(TestLessThan, AccumulatorUse::kReadWrite, OperandType::kReg)               \
+  V(TestGreaterThan, AccumulatorUse::kReadWrite, OperandType::kReg)            \
+  V(TestLessThanOrEqual, AccumulatorUse::kReadWrite, OperandType::kReg)        \
+  V(TestGreaterThanOrEqual, AccumulatorUse::kReadWrite, OperandType::kReg)     \
+  V(TestInstanceOf, AccumulatorUse::kReadWrite, OperandType::kReg)             \
+  V(TestIn, AccumulatorUse::kReadWrite, OperandType::kReg)                     \
+                                                                               \
+  /* Cast operators */                                                         \
+  V(ToName, AccumulatorUse::kReadWrite)                                        \
+  V(ToNumber, AccumulatorUse::kReadWrite)                                      \
+  V(ToObject, AccumulatorUse::kReadWrite)                                      \
+                                                                               \
+  /* Literals */                                                               \
+  V(CreateRegExpLiteral, AccumulatorUse::kWrite, OperandType::kIdx,            \
+    OperandType::kIdx, OperandType::kFlag8)                                    \
+  V(CreateArrayLiteral, AccumulatorUse::kWrite, OperandType::kIdx,             \
+    OperandType::kIdx, OperandType::kFlag8)                                    \
+  V(CreateObjectLiteral, AccumulatorUse::kWrite, OperandType::kIdx,            \
+    OperandType::kIdx, OperandType::kFlag8)                                    \
+                                                                               \
+  /* Closure allocation */                                                     \
+  V(CreateClosure, AccumulatorUse::kWrite, OperandType::kIdx,                  \
+    OperandType::kFlag8)                                                       \
+                                                                               \
+  /* Arguments allocation */                                                   \
+  V(CreateMappedArguments, AccumulatorUse::kWrite)                             \
+  V(CreateUnmappedArguments, AccumulatorUse::kWrite)                           \
+  V(CreateRestParameter, AccumulatorUse::kWrite)                               \
+                                                                               \
+  /* Control Flow */                                                           \
+  V(Jump, AccumulatorUse::kNone, OperandType::kImm)                            \
+  V(JumpConstant, AccumulatorUse::kNone, OperandType::kIdx)                    \
+  V(JumpIfTrue, AccumulatorUse::kRead, OperandType::kImm)                      \
+  V(JumpIfTrueConstant, AccumulatorUse::kRead, OperandType::kIdx)              \
+  V(JumpIfFalse, AccumulatorUse::kRead, OperandType::kImm)                     \
+  V(JumpIfFalseConstant, AccumulatorUse::kRead, OperandType::kIdx)             \
+  V(JumpIfToBooleanTrue, AccumulatorUse::kRead, OperandType::kImm)             \
+  V(JumpIfToBooleanTrueConstant, AccumulatorUse::kRead, OperandType::kIdx)     \
+  V(JumpIfToBooleanFalse, AccumulatorUse::kRead, OperandType::kImm)            \
+  V(JumpIfToBooleanFalseConstant, AccumulatorUse::kRead, OperandType::kIdx)    \
+  V(JumpIfNull, AccumulatorUse::kRead, OperandType::kImm)                      \
+  V(JumpIfNullConstant, AccumulatorUse::kRead, OperandType::kIdx)              \
+  V(JumpIfUndefined, AccumulatorUse::kRead, OperandType::kImm)                 \
+  V(JumpIfUndefinedConstant, AccumulatorUse::kRead, OperandType::kIdx)         \
+  V(JumpIfNotHole, AccumulatorUse::kRead, OperandType::kImm)                   \
+  V(JumpIfNotHoleConstant, AccumulatorUse::kRead, OperandType::kIdx)           \
+                                                                               \
+  /* Complex flow control For..in */                                           \
+  V(ForInPrepare, AccumulatorUse::kRead, OperandType::kRegOutTriple)           \
+  V(ForInDone, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kReg)   \
+  V(ForInNext, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kReg,   \
+    OperandType::kRegPair, OperandType::kIdx)                                  \
+  V(ForInStep, AccumulatorUse::kWrite, OperandType::kReg)                      \
+                                                                               \
+  /* Perform a stack guard check */                                            \
+  V(StackCheck, AccumulatorUse::kNone)                                         \
+                                                                               \
+  /* Non-local flow control */                                                 \
+  V(Throw, AccumulatorUse::kRead)                                              \
+  V(ReThrow, AccumulatorUse::kRead)                                            \
+  V(Return, AccumulatorUse::kRead)                                             \
+                                                                               \
+  /* Generators */                                                             \
+  V(SuspendGenerator, AccumulatorUse::kRead, OperandType::kReg)                \
+  V(ResumeGenerator, AccumulatorUse::kWrite, OperandType::kReg)                \
+                                                                               \
+  /* Debugger */                                                               \
+  V(Debugger, AccumulatorUse::kNone)                                           \
+  DEBUG_BREAK_BYTECODE_LIST(V)                                                 \
+                                                                               \
+  /* Illegal bytecode (terminates execution) */                                \
+  V(Illegal, AccumulatorUse::kNone)                                            \
+                                                                               \
+  /* No operation (used to maintain source positions for peephole */           \
+  /* eliminated bytecodes). */                                                 \
+  V(Nop, AccumulatorUse::kNone)
 
 enum class AccumulatorUse : uint8_t {
   kNone = 0,
@@ -266,12 +286,16 @@
 
 // Enumeration of scaling factors applicable to scalable operands. Code
 // relies on being able to cast values to integer scaling values.
+#define OPERAND_SCALE_LIST(V) \
+  V(Single, 1)                \
+  V(Double, 2)                \
+  V(Quadruple, 4)
+
 enum class OperandScale : uint8_t {
-  kSingle = 1,
-  kDouble = 2,
-  kQuadruple = 4,
-  kMaxValid = kQuadruple,
-  kInvalid = 8,
+#define DECLARE_OPERAND_SCALE(Name, Scale) k##Name = Scale,
+  OPERAND_SCALE_LIST(DECLARE_OPERAND_SCALE)
+#undef DECLARE_OPERAND_SCALE
+      kLast = kQuadruple
 };
 
 // Enumeration of the size classes of operand types used by
@@ -328,15 +352,13 @@
 
 // An interpreter Register which is located in the function's Register file
 // in its stack-frame. Register hold parameters, this, and expression values.
-class Register {
+class Register final {
  public:
   explicit Register(int index = kInvalidIndex) : index_(index) {}
 
   int index() const { return index_; }
   bool is_parameter() const { return index() < 0; }
   bool is_valid() const { return index_ != kInvalidIndex; }
-  bool is_byte_operand() const;
-  bool is_short_operand() const;
 
   static Register FromParameterIndex(int index, int parameter_count);
   int ToParameterIndex(int parameter_count) const;
@@ -356,8 +378,25 @@
   static Register new_target();
   bool is_new_target() const;
 
-  int32_t ToOperand() const { return -index_; }
-  static Register FromOperand(int32_t operand) { return Register(-operand); }
+  // Returns the register for the bytecode array.
+  static Register bytecode_array();
+  bool is_bytecode_array() const;
+
+  // Returns the register for the saved bytecode offset.
+  static Register bytecode_offset();
+  bool is_bytecode_offset() const;
+
+  // Returns a register that can be used to represent the accumulator
+  // within code in the interpreter, but should never be emitted in
+  // bytecode.
+  static Register virtual_accumulator();
+
+  OperandSize SizeOfOperand() const;
+
+  int32_t ToOperand() const { return kRegisterFileStartOffset - index_; }
+  static Register FromOperand(int32_t operand) {
+    return Register(kRegisterFileStartOffset - operand);
+  }
 
   static bool AreContiguous(Register reg1, Register reg2,
                             Register reg3 = Register(),
@@ -387,6 +426,8 @@
 
  private:
   static const int kInvalidIndex = kMaxInt;
+  static const int kRegisterFileStartOffset =
+      InterpreterFrameConstants::kRegisterFileFromFp / kPointerSize;
 
   void* operator new(size_t size);
   void operator delete(void* p);
@@ -416,7 +457,10 @@
   static const char* OperandSizeToString(OperandSize operand_size);
 
   // Returns byte value of bytecode.
-  static uint8_t ToByte(Bytecode bytecode);
+  static uint8_t ToByte(Bytecode bytecode) {
+    DCHECK_LE(bytecode, Bytecode::kLast);
+    return static_cast<uint8_t>(bytecode);
+  }
 
   // Returns bytecode for |value|.
   static Bytecode FromByte(uint8_t value);
@@ -447,13 +491,44 @@
   // Returns true if |bytecode| writes the accumulator.
   static bool WritesAccumulator(Bytecode bytecode);
 
+  // Return true if |bytecode| writes the accumulator with a boolean value.
+  static bool WritesBooleanToAccumulator(Bytecode bytecode);
+
+  // Return true if |bytecode| is an accumulator load without effects,
+  // e.g. LdaConstant, LdaTrue, Ldar.
+  static bool IsAccumulatorLoadWithoutEffects(Bytecode bytecode);
+
+  // Return true if |bytecode| is a jump without effects,
+  // e.g.  any jump excluding those that include type coercion like
+  // JumpIfTrueToBoolean.
+  static bool IsJumpWithoutEffects(Bytecode bytecode);
+
+  // Return true if |bytecode| is a register load without effects,
+  // e.g. Mov, Star, LdrUndefined.
+  static bool IsRegisterLoadWithoutEffects(Bytecode bytecode);
+
+  // Returns true if |bytecode| has no effects.
+  static bool IsWithoutExternalSideEffects(Bytecode bytecode);
+
   // Returns the i-th operand of |bytecode|.
   static OperandType GetOperandType(Bytecode bytecode, int i);
 
+  // Returns a pointer to an array of operand types terminated in
+  // OperandType::kNone.
+  static const OperandType* GetOperandTypes(Bytecode bytecode);
+
+  // Returns a pointer to an array of operand type info terminated in
+  // OperandTypeInfo::kNone.
+  static const OperandTypeInfo* GetOperandTypeInfos(Bytecode bytecode);
+
   // Returns the size of the i-th operand of |bytecode|.
   static OperandSize GetOperandSize(Bytecode bytecode, int i,
                                     OperandScale operand_scale);
 
+  // Returns a pointer to an array of the operand sizes for |bytecode|.
+  static const OperandSize* GetOperandSizes(Bytecode bytecode,
+                                            OperandScale operand_scale);
+
   // Returns the offset of the i-th operand of |bytecode| relative to the start
   // of the bytecode.
   static int GetOperandOffset(Bytecode bytecode, int i,
@@ -473,6 +548,9 @@
   // Returns the size of |operand|.
   static OperandSize SizeOfOperand(OperandType operand, OperandScale scale);
 
+  // Returns the number of values which |bytecode| returns.
+  static size_t ReturnCount(Bytecode bytecode);
+
   // Returns true if the bytecode is a conditional jump taking
   // an immediate byte operand (OperandType::kImm).
   static bool IsConditionalJumpImmediate(Bytecode bytecode);
@@ -497,6 +575,13 @@
   // any kind of operand.
   static bool IsJump(Bytecode bytecode);
 
+  // Returns true if the bytecode is a jump that internally coerces the
+  // accumulator to a boolean.
+  static bool IsJumpIfToBoolean(Bytecode bytecode);
+
+  // Returns the equivalent jump bytecode without the accumulator coercion.
+  static Bytecode GetJumpWithoutToBoolean(Bytecode bytecode);
+
   // Returns true if the bytecode is a conditional jump, a jump, or a return.
   static bool IsJumpOrReturn(Bytecode bytecode);
 
@@ -509,6 +594,9 @@
   // Returns true if the bytecode is a debug break.
   static bool IsDebugBreak(Bytecode bytecode);
 
+  // Returns true if the bytecode is Ldar or Star.
+  static bool IsLdarOrStar(Bytecode bytecode);
+
   // Returns true if the bytecode has wider operand forms.
   static bool IsBytecodeWithScalableOperands(Bytecode bytecode);
 
@@ -524,6 +612,10 @@
   // Returns true if |operand_type| represents a register used as an output.
   static bool IsRegisterOutputOperandType(OperandType operand_type);
 
+  // Returns the number of registers represented by a register operand. For
+  // instance, a RegPair represents two registers.
+  static int GetNumberOfRegistersRepresentedBy(OperandType operand_type);
+
   // Returns true if |operand_type| is a maybe register operand
   // (kMaybeReg).
   static bool IsMaybeRegisterOperandType(OperandType operand_type);
@@ -559,13 +651,24 @@
   // OperandScale values.
   static bool BytecodeHasHandler(Bytecode bytecode, OperandScale operand_scale);
 
-  // Return the next larger operand scale.
-  static OperandScale NextOperandScale(OperandScale operand_scale);
+  // Return the operand size required to hold a signed operand.
+  static OperandSize SizeForSignedOperand(int value);
+
+  // Return the operand size required to hold an unsigned operand.
+  static OperandSize SizeForUnsignedOperand(uint32_t value);
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(Bytecodes);
 };
 
+class CreateObjectLiteralFlags {
+ public:
+  class FlagsBits : public BitField8<int, 0, 3> {};
+  class FastClonePropertiesCountBits
+      : public BitField8<int, FlagsBits::kNext, 3> {};
+  STATIC_ASSERT((FlagsBits::kMask & FastClonePropertiesCountBits::kMask) == 0);
+};
+
 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode);
 std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use);
 std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale);
diff --git a/src/interpreter/control-flow-builders.cc b/src/interpreter/control-flow-builders.cc
index 6510aa4..66d650c 100644
--- a/src/interpreter/control-flow-builders.cc
+++ b/src/interpreter/control-flow-builders.cc
@@ -90,13 +90,16 @@
 LoopBuilder::~LoopBuilder() { DCHECK(continue_sites_.empty()); }
 
 
-void LoopBuilder::LoopHeader() {
+void LoopBuilder::LoopHeader(ZoneVector<BytecodeLabel>* additional_labels) {
   // Jumps from before the loop header into the loop violate ordering
   // requirements of bytecode basic blocks. The only entry into a loop
   // must be the loop header. Surely breaks is okay? Not if nested
   // and misplaced between the headers.
   DCHECK(break_sites_.empty() && continue_sites_.empty());
   builder()->Bind(&loop_header_);
+  for (auto& label : *additional_labels) {
+    builder()->Bind(loop_header_, &label);
+  }
 }
 
 
@@ -106,19 +109,11 @@
   DCHECK(loop_header_.is_bound());
   builder()->Bind(&loop_end_);
   SetBreakTarget(loop_end_);
-  if (next_.is_bound()) {
-    DCHECK(!condition_.is_bound() || next_.offset() >= condition_.offset());
-    SetContinueTarget(next_);
-  } else {
-    DCHECK(condition_.is_bound());
-    DCHECK_GE(condition_.offset(), loop_header_.offset());
-    DCHECK_LE(condition_.offset(), loop_end_.offset());
-    SetContinueTarget(condition_);
-  }
 }
 
-
-void LoopBuilder::SetContinueTarget(const BytecodeLabel& target) {
+void LoopBuilder::SetContinueTarget() {
+  BytecodeLabel target;
+  builder()->Bind(&target);
   BindLabels(target, &continue_sites_);
 }
 
diff --git a/src/interpreter/control-flow-builders.h b/src/interpreter/control-flow-builders.h
index e4d376b..b72d6d5 100644
--- a/src/interpreter/control-flow-builders.h
+++ b/src/interpreter/control-flow-builders.h
@@ -7,6 +7,7 @@
 
 #include "src/interpreter/bytecode-array-builder.h"
 
+#include "src/interpreter/bytecode-label.h"
 #include "src/zone-containers.h"
 
 namespace v8 {
@@ -87,27 +88,22 @@
         continue_sites_(builder->zone()) {}
   ~LoopBuilder();
 
-  void LoopHeader();
-  void Condition() { builder()->Bind(&condition_); }
-  void Next() { builder()->Bind(&next_); }
+  void LoopHeader(ZoneVector<BytecodeLabel>* additional_labels);
   void JumpToHeader() { builder()->Jump(&loop_header_); }
   void JumpToHeaderIfTrue() { builder()->JumpIfTrue(&loop_header_); }
+  void SetContinueTarget();
   void EndLoop();
 
   // This method is called when visiting continue statements in the AST.
-  // Inserts a jump to a unbound label that is patched when the corresponding
-  // SetContinueTarget is called.
+  // Inserts a jump to an unbound label that is patched when SetContinueTarget
+  // is called.
   void Continue() { EmitJump(&continue_sites_); }
   void ContinueIfTrue() { EmitJumpIfTrue(&continue_sites_); }
   void ContinueIfUndefined() { EmitJumpIfUndefined(&continue_sites_); }
   void ContinueIfNull() { EmitJumpIfNull(&continue_sites_); }
 
  private:
-  void SetContinueTarget(const BytecodeLabel& continue_target);
-
   BytecodeLabel loop_header_;
-  BytecodeLabel condition_;
-  BytecodeLabel next_;
   BytecodeLabel loop_end_;
 
   // Unbound labels that identify jumps for continue statements in the code.
diff --git a/src/interpreter/interpreter-assembler.cc b/src/interpreter/interpreter-assembler.cc
index 2663e4a..ee5f8be 100644
--- a/src/interpreter/interpreter-assembler.cc
+++ b/src/interpreter/interpreter-assembler.cc
@@ -4,6 +4,7 @@
 
 #include "src/interpreter/interpreter-assembler.h"
 
+#include <limits>
 #include <ostream>
 
 #include "src/code-factory.h"
@@ -24,23 +25,20 @@
 InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone,
                                            Bytecode bytecode,
                                            OperandScale operand_scale)
-    : compiler::CodeStubAssembler(isolate, zone,
-                                  InterpreterDispatchDescriptor(isolate),
-                                  Code::ComputeFlags(Code::BYTECODE_HANDLER),
-                                  Bytecodes::ToString(bytecode), 0),
+    : CodeStubAssembler(isolate, zone, InterpreterDispatchDescriptor(isolate),
+                        Code::ComputeFlags(Code::BYTECODE_HANDLER),
+                        Bytecodes::ToString(bytecode),
+                        Bytecodes::ReturnCount(bytecode)),
       bytecode_(bytecode),
       operand_scale_(operand_scale),
+      interpreted_frame_pointer_(this, MachineType::PointerRepresentation()),
       accumulator_(this, MachineRepresentation::kTagged),
       accumulator_use_(AccumulatorUse::kNone),
-      context_(this, MachineRepresentation::kTagged),
-      bytecode_array_(this, MachineRepresentation::kTagged),
+      made_call_(false),
       disable_stack_check_across_call_(false),
       stack_pointer_before_call_(nullptr) {
   accumulator_.Bind(
       Parameter(InterpreterDispatchDescriptor::kAccumulatorParameter));
-  context_.Bind(Parameter(InterpreterDispatchDescriptor::kContextParameter));
-  bytecode_array_.Bind(
-      Parameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter));
   if (FLAG_trace_ignition) {
     TraceBytecode(Runtime::kInterpreterTraceBytecodeEntry);
   }
@@ -53,6 +51,13 @@
   DCHECK_EQ(accumulator_use_, Bytecodes::GetAccumulatorUse(bytecode_));
 }
 
+Node* InterpreterAssembler::GetInterpretedFramePointer() {
+  if (!interpreted_frame_pointer_.IsBound()) {
+    interpreted_frame_pointer_.Bind(LoadParentFramePointer());
+  }
+  return interpreted_frame_pointer_.value();
+}
+
 Node* InterpreterAssembler::GetAccumulatorUnchecked() {
   return accumulator_.value();
 }
@@ -69,23 +74,26 @@
   accumulator_.Bind(value);
 }
 
-Node* InterpreterAssembler::GetContext() { return context_.value(); }
+Node* InterpreterAssembler::GetContext() {
+  return LoadRegister(Register::current_context());
+}
 
 void InterpreterAssembler::SetContext(Node* value) {
   StoreRegister(value, Register::current_context());
-  context_.Bind(value);
 }
 
 Node* InterpreterAssembler::BytecodeOffset() {
   return Parameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter);
 }
 
-Node* InterpreterAssembler::RegisterFileRawPointer() {
-  return Parameter(InterpreterDispatchDescriptor::kRegisterFileParameter);
-}
-
 Node* InterpreterAssembler::BytecodeArrayTaggedPointer() {
-  return bytecode_array_.value();
+  if (made_call_) {
+    // If we have made a call, restore bytecode array from stack frame in case
+    // the debugger has swapped us to the patched debugger bytecode array.
+    return LoadRegister(Register::bytecode_array());
+  } else {
+    return Parameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter);
+  }
 }
 
 Node* InterpreterAssembler::DispatchTableRawPointer() {
@@ -93,40 +101,33 @@
 }
 
 Node* InterpreterAssembler::RegisterLocation(Node* reg_index) {
-  return IntPtrAdd(RegisterFileRawPointer(), RegisterFrameOffset(reg_index));
-}
-
-Node* InterpreterAssembler::LoadRegister(int offset) {
-  return Load(MachineType::AnyTagged(), RegisterFileRawPointer(),
-              IntPtrConstant(offset));
-}
-
-Node* InterpreterAssembler::LoadRegister(Register reg) {
-  return LoadRegister(IntPtrConstant(-reg.index()));
+  return IntPtrAdd(GetInterpretedFramePointer(),
+                   RegisterFrameOffset(reg_index));
 }
 
 Node* InterpreterAssembler::RegisterFrameOffset(Node* index) {
   return WordShl(index, kPointerSizeLog2);
 }
 
+Node* InterpreterAssembler::LoadRegister(Register reg) {
+  return Load(MachineType::AnyTagged(), GetInterpretedFramePointer(),
+              IntPtrConstant(reg.ToOperand() << kPointerSizeLog2));
+}
+
 Node* InterpreterAssembler::LoadRegister(Node* reg_index) {
-  return Load(MachineType::AnyTagged(), RegisterFileRawPointer(),
+  return Load(MachineType::AnyTagged(), GetInterpretedFramePointer(),
               RegisterFrameOffset(reg_index));
 }
 
-Node* InterpreterAssembler::StoreRegister(Node* value, int offset) {
-  return StoreNoWriteBarrier(MachineRepresentation::kTagged,
-                             RegisterFileRawPointer(), IntPtrConstant(offset),
-                             value);
-}
-
 Node* InterpreterAssembler::StoreRegister(Node* value, Register reg) {
-  return StoreRegister(value, IntPtrConstant(-reg.index()));
+  return StoreNoWriteBarrier(
+      MachineRepresentation::kTagged, GetInterpretedFramePointer(),
+      IntPtrConstant(reg.ToOperand() << kPointerSizeLog2), value);
 }
 
 Node* InterpreterAssembler::StoreRegister(Node* value, Node* reg_index) {
   return StoreNoWriteBarrier(MachineRepresentation::kTagged,
-                             RegisterFileRawPointer(),
+                             GetInterpretedFramePointer(),
                              RegisterFrameOffset(reg_index), value);
 }
 
@@ -371,6 +372,15 @@
   return BytecodeUnsignedOperand(operand_index, operand_size);
 }
 
+Node* InterpreterAssembler::BytecodeOperandIntrinsicId(int operand_index) {
+  DCHECK(OperandType::kIntrinsicId ==
+         Bytecodes::GetOperandType(bytecode_, operand_index));
+  OperandSize operand_size =
+      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
+  DCHECK_EQ(operand_size, OperandSize::kByte);
+  return BytecodeUnsignedOperand(operand_index, operand_size);
+}
+
 Node* InterpreterAssembler::LoadConstantPoolEntry(Node* index) {
   Node* constant_pool = LoadObjectField(BytecodeArrayTaggedPointer(),
                                         BytecodeArray::kConstantPoolOffset);
@@ -380,11 +390,6 @@
   return Load(MachineType::AnyTagged(), constant_pool, entry_offset);
 }
 
-Node* InterpreterAssembler::LoadObjectField(Node* object, int offset) {
-  return Load(MachineType::AnyTagged(), object,
-              IntPtrConstant(offset - kHeapObjectTag));
-}
-
 Node* InterpreterAssembler::LoadContextSlot(Node* context, int slot_index) {
   return Load(MachineType::AnyTagged(), context,
               IntPtrConstant(Context::SlotOffset(slot_index)));
@@ -406,24 +411,21 @@
 }
 
 Node* InterpreterAssembler::LoadTypeFeedbackVector() {
-  Node* function = Load(
-      MachineType::AnyTagged(), RegisterFileRawPointer(),
-      IntPtrConstant(InterpreterFrameConstants::kFunctionFromRegisterPointer));
-  Node* shared_info =
-      LoadObjectField(function, JSFunction::kSharedFunctionInfoOffset);
+  Node* function = LoadRegister(Register::function_closure());
+  Node* literals = LoadObjectField(function, JSFunction::kLiteralsOffset);
   Node* vector =
-      LoadObjectField(shared_info, SharedFunctionInfo::kFeedbackVectorOffset);
+      LoadObjectField(literals, LiteralsArray::kFeedbackVectorOffset);
   return vector;
 }
 
 void InterpreterAssembler::CallPrologue() {
-  StoreRegister(SmiTag(BytecodeOffset()),
-                InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer);
+  StoreRegister(SmiTag(BytecodeOffset()), Register::bytecode_offset());
 
   if (FLAG_debug_code && !disable_stack_check_across_call_) {
     DCHECK(stack_pointer_before_call_ == nullptr);
     stack_pointer_before_call_ = LoadStackPointer();
   }
+  made_call_ = true;
 }
 
 void InterpreterAssembler::CallEpilogue() {
@@ -434,11 +436,6 @@
     AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call,
                         kUnexpectedStackPointer);
   }
-
-  // Restore bytecode array from stack frame in case the debugger has swapped us
-  // to the patched debugger bytecode array.
-  bytecode_array_.Bind(LoadRegister(
-      InterpreterFrameConstants::kBytecodeArrayFromRegisterPointer));
 }
 
 Node* InterpreterAssembler::CallJS(Node* function, Node* context,
@@ -481,33 +478,32 @@
 }
 
 void InterpreterAssembler::UpdateInterruptBudget(Node* weight) {
-  CodeStubAssembler::Label ok(this);
-  CodeStubAssembler::Label interrupt_check(this);
-  CodeStubAssembler::Label end(this);
+  Label ok(this), interrupt_check(this, Label::kDeferred), end(this);
   Node* budget_offset =
       IntPtrConstant(BytecodeArray::kInterruptBudgetOffset - kHeapObjectTag);
 
   // Update budget by |weight| and check if it reaches zero.
+  Variable new_budget(this, MachineRepresentation::kWord32);
   Node* old_budget =
       Load(MachineType::Int32(), BytecodeArrayTaggedPointer(), budget_offset);
-  Node* new_budget = Int32Add(old_budget, weight);
-  Node* condition = Int32GreaterThanOrEqual(new_budget, Int32Constant(0));
+  new_budget.Bind(Int32Add(old_budget, weight));
+  Node* condition =
+      Int32GreaterThanOrEqual(new_budget.value(), Int32Constant(0));
   Branch(condition, &ok, &interrupt_check);
 
   // Perform interrupt and reset budget.
   Bind(&interrupt_check);
-  CallRuntime(Runtime::kInterrupt, GetContext());
-  StoreNoWriteBarrier(MachineRepresentation::kWord32,
-                      BytecodeArrayTaggedPointer(), budget_offset,
-                      Int32Constant(Interpreter::InterruptBudget()));
-  Goto(&end);
+  {
+    CallRuntime(Runtime::kInterrupt, GetContext());
+    new_budget.Bind(Int32Constant(Interpreter::InterruptBudget()));
+    Goto(&ok);
+  }
 
   // Update budget.
   Bind(&ok);
   StoreNoWriteBarrier(MachineRepresentation::kWord32,
-                      BytecodeArrayTaggedPointer(), budget_offset, new_budget);
-  Goto(&end);
-  Bind(&end);
+                      BytecodeArrayTaggedPointer(), budget_offset,
+                      new_budget.value());
 }
 
 Node* InterpreterAssembler::Advance(int delta) {
@@ -518,16 +514,15 @@
   return IntPtrAdd(BytecodeOffset(), delta);
 }
 
-void InterpreterAssembler::Jump(Node* delta) {
+Node* InterpreterAssembler::Jump(Node* delta) {
   UpdateInterruptBudget(delta);
-  DispatchTo(Advance(delta));
+  return DispatchTo(Advance(delta));
 }
 
 void InterpreterAssembler::JumpConditional(Node* condition, Node* delta) {
-  CodeStubAssembler::Label match(this);
-  CodeStubAssembler::Label no_match(this);
+  Label match(this), no_match(this);
 
-  Branch(condition, &match, &no_match);
+  BranchIf(condition, &match, &no_match);
   Bind(&match);
   Jump(delta);
   Bind(&no_match);
@@ -543,37 +538,45 @@
   JumpConditional(WordNotEqual(lhs, rhs), delta);
 }
 
-void InterpreterAssembler::Dispatch() {
-  DispatchTo(Advance(Bytecodes::Size(bytecode_, operand_scale_)));
+Node* InterpreterAssembler::Dispatch() {
+  return DispatchTo(Advance(Bytecodes::Size(bytecode_, operand_scale_)));
 }
 
-void InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) {
+Node* InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) {
   Node* target_bytecode = Load(
       MachineType::Uint8(), BytecodeArrayTaggedPointer(), new_bytecode_offset);
   if (kPointerSize == 8) {
     target_bytecode = ChangeUint32ToUint64(target_bytecode);
   }
 
-  // TODO(rmcilroy): Create a code target dispatch table to avoid conversion
-  // from code object on every dispatch.
-  Node* target_code_object =
+  if (FLAG_trace_ignition_dispatches) {
+    TraceBytecodeDispatch(target_bytecode);
+  }
+
+  Node* target_code_entry =
       Load(MachineType::Pointer(), DispatchTableRawPointer(),
            WordShl(target_bytecode, IntPtrConstant(kPointerSizeLog2)));
 
-  DispatchToBytecodeHandler(target_code_object, new_bytecode_offset);
+  return DispatchToBytecodeHandlerEntry(target_code_entry, new_bytecode_offset);
 }
 
-void InterpreterAssembler::DispatchToBytecodeHandler(Node* handler,
-                                                     Node* bytecode_offset) {
+Node* InterpreterAssembler::DispatchToBytecodeHandler(Node* handler,
+                                                      Node* bytecode_offset) {
+  Node* handler_entry =
+      IntPtrAdd(handler, IntPtrConstant(Code::kHeaderSize - kHeapObjectTag));
+  return DispatchToBytecodeHandlerEntry(handler_entry, bytecode_offset);
+}
+
+Node* InterpreterAssembler::DispatchToBytecodeHandlerEntry(
+    Node* handler_entry, Node* bytecode_offset) {
   if (FLAG_trace_ignition) {
     TraceBytecode(Runtime::kInterpreterTraceBytecodeExit);
   }
 
   InterpreterDispatchDescriptor descriptor(isolate());
-  Node* args[] = {GetAccumulatorUnchecked(), RegisterFileRawPointer(),
-                  bytecode_offset,           BytecodeArrayTaggedPointer(),
-                  DispatchTableRawPointer(), GetContext()};
-  TailCall(descriptor, handler, args, 0);
+  Node* args[] = {GetAccumulatorUnchecked(), bytecode_offset,
+                  BytecodeArrayTaggedPointer(), DispatchTableRawPointer()};
+  return TailCallBytecodeDispatch(descriptor, handler_entry, args);
 }
 
 void InterpreterAssembler::DispatchWide(OperandScale operand_scale) {
@@ -590,6 +593,11 @@
   if (kPointerSize == 8) {
     next_bytecode = ChangeUint32ToUint64(next_bytecode);
   }
+
+  if (FLAG_trace_ignition_dispatches) {
+    TraceBytecodeDispatch(next_bytecode);
+  }
+
   Node* base_index;
   switch (operand_scale) {
     case OperandScale::kDouble:
@@ -603,14 +611,14 @@
       base_index = nullptr;
   }
   Node* target_index = IntPtrAdd(base_index, next_bytecode);
-  Node* target_code_object =
+  Node* target_code_entry =
       Load(MachineType::Pointer(), DispatchTableRawPointer(),
            WordShl(target_index, kPointerSizeLog2));
 
-  DispatchToBytecodeHandler(target_code_object, next_bytecode_offset);
+  DispatchToBytecodeHandlerEntry(target_code_entry, next_bytecode_offset);
 }
 
-void InterpreterAssembler::InterpreterReturn() {
+void InterpreterAssembler::UpdateInterruptBudgetOnReturn() {
   // TODO(rmcilroy): Investigate whether it is worth supporting self
   // optimization of primitive functions like FullCodegen.
 
@@ -620,29 +628,14 @@
       Int32Sub(Int32Constant(kHeapObjectTag + BytecodeArray::kHeaderSize),
                BytecodeOffset());
   UpdateInterruptBudget(profiling_weight);
-
-  Node* exit_trampoline_code_object =
-      HeapConstant(isolate()->builtins()->InterpreterExitTrampoline());
-  DispatchToBytecodeHandler(exit_trampoline_code_object);
 }
 
-void InterpreterAssembler::StackCheck() {
-  CodeStubAssembler::Label end(this);
-  CodeStubAssembler::Label ok(this);
-  CodeStubAssembler::Label stack_guard(this);
-
+Node* InterpreterAssembler::StackCheckTriggeredInterrupt() {
   Node* sp = LoadStackPointer();
   Node* stack_limit = Load(
       MachineType::Pointer(),
       ExternalConstant(ExternalReference::address_of_stack_limit(isolate())));
-  Node* condition = UintPtrGreaterThanOrEqual(sp, stack_limit);
-  Branch(condition, &ok, &stack_guard);
-  Bind(&stack_guard);
-  CallRuntime(Runtime::kStackGuard, GetContext());
-  Goto(&end);
-  Bind(&ok);
-  Goto(&end);
-  Bind(&end);
+  return UintPtrLessThan(sp, stack_limit);
 }
 
 void InterpreterAssembler::Abort(BailoutReason bailout_reason) {
@@ -654,18 +647,14 @@
 
 void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs,
                                                BailoutReason bailout_reason) {
-  CodeStubAssembler::Label match(this);
-  CodeStubAssembler::Label no_match(this);
-  CodeStubAssembler::Label end(this);
+  Label ok(this), abort(this, Label::kDeferred);
+  BranchIfWordEqual(lhs, rhs, &ok, &abort);
 
-  Node* condition = WordEqual(lhs, rhs);
-  Branch(condition, &match, &no_match);
-  Bind(&no_match);
+  Bind(&abort);
   Abort(bailout_reason);
-  Goto(&end);
-  Bind(&match);
-  Goto(&end);
-  Bind(&end);
+  Goto(&ok);
+
+  Bind(&ok);
 }
 
 void InterpreterAssembler::TraceBytecode(Runtime::FunctionId function_id) {
@@ -673,6 +662,35 @@
               SmiTag(BytecodeOffset()), GetAccumulatorUnchecked());
 }
 
+void InterpreterAssembler::TraceBytecodeDispatch(Node* target_bytecode) {
+  Node* counters_table = ExternalConstant(
+      ExternalReference::interpreter_dispatch_counters(isolate()));
+  Node* source_bytecode_table_index = IntPtrConstant(
+      static_cast<int>(bytecode_) * (static_cast<int>(Bytecode::kLast) + 1));
+
+  Node* counter_offset =
+      WordShl(IntPtrAdd(source_bytecode_table_index, target_bytecode),
+              IntPtrConstant(kPointerSizeLog2));
+  Node* old_counter =
+      Load(MachineType::IntPtr(), counters_table, counter_offset);
+
+  Label counter_ok(this), counter_saturated(this, Label::kDeferred);
+
+  Node* counter_reached_max = WordEqual(
+      old_counter, IntPtrConstant(std::numeric_limits<uintptr_t>::max()));
+  BranchIf(counter_reached_max, &counter_saturated, &counter_ok);
+
+  Bind(&counter_ok);
+  {
+    Node* new_counter = IntPtrAdd(old_counter, IntPtrConstant(1));
+    StoreNoWriteBarrier(MachineType::PointerRepresentation(), counters_table,
+                        counter_offset, new_counter);
+    Goto(&counter_saturated);
+  }
+
+  Bind(&counter_saturated);
+}
+
 // static
 bool InterpreterAssembler::TargetSupportsUnalignedAccess() {
 #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
@@ -687,6 +705,84 @@
 #endif
 }
 
+Node* InterpreterAssembler::RegisterCount() {
+  Node* bytecode_array = LoadRegister(Register::bytecode_array());
+  Node* frame_size = LoadObjectField(
+      bytecode_array, BytecodeArray::kFrameSizeOffset, MachineType::Int32());
+  return Word32Sar(frame_size, Int32Constant(kPointerSizeLog2));
+}
+
+Node* InterpreterAssembler::ExportRegisterFile(Node* array) {
+  if (FLAG_debug_code) {
+    Node* array_size = SmiUntag(LoadFixedArrayBaseLength(array));
+    AbortIfWordNotEqual(
+        array_size, RegisterCount(), kInvalidRegisterFileInGenerator);
+  }
+
+  Variable var_index(this, MachineRepresentation::kWord32);
+  var_index.Bind(Int32Constant(0));
+
+  // Iterate over register file and write values into array.
+  // The mapping of register to array index must match that used in
+  // BytecodeGraphBuilder::VisitResumeGenerator.
+  Label loop(this, &var_index), done_loop(this);
+  Goto(&loop);
+  Bind(&loop);
+  {
+    Node* index = var_index.value();
+    Node* condition = Int32LessThan(index, RegisterCount());
+    GotoUnless(condition, &done_loop);
+
+    Node* reg_index =
+        Int32Sub(Int32Constant(Register(0).ToOperand()), index);
+    Node* value = LoadRegister(ChangeInt32ToIntPtr(reg_index));
+
+    StoreFixedArrayElement(array, index, value);
+
+    var_index.Bind(Int32Add(index, Int32Constant(1)));
+    Goto(&loop);
+  }
+  Bind(&done_loop);
+
+  return array;
+}
+
+Node* InterpreterAssembler::ImportRegisterFile(Node* array) {
+  if (FLAG_debug_code) {
+    Node* array_size = SmiUntag(LoadFixedArrayBaseLength(array));
+    AbortIfWordNotEqual(
+        array_size, RegisterCount(), kInvalidRegisterFileInGenerator);
+  }
+
+  Variable var_index(this, MachineRepresentation::kWord32);
+  var_index.Bind(Int32Constant(0));
+
+  // Iterate over array and write values into register file.  Also erase the
+  // array contents to not keep them alive artificially.
+  Label loop(this, &var_index), done_loop(this);
+  Goto(&loop);
+  Bind(&loop);
+  {
+    Node* index = var_index.value();
+    Node* condition = Int32LessThan(index, RegisterCount());
+    GotoUnless(condition, &done_loop);
+
+    Node* value = LoadFixedArrayElement(array, index);
+
+    Node* reg_index =
+        Int32Sub(Int32Constant(Register(0).ToOperand()), index);
+    StoreRegister(value, ChangeInt32ToIntPtr(reg_index));
+
+    StoreFixedArrayElement(array, index, StaleRegisterConstant());
+
+    var_index.Bind(Int32Add(index, Int32Constant(1)));
+    Goto(&loop);
+  }
+  Bind(&done_loop);
+
+  return array;
+}
+
 }  // namespace interpreter
 }  // namespace internal
 }  // namespace v8
diff --git a/src/interpreter/interpreter-assembler.h b/src/interpreter/interpreter-assembler.h
index 86ecea5..183d4dd 100644
--- a/src/interpreter/interpreter-assembler.h
+++ b/src/interpreter/interpreter-assembler.h
@@ -8,7 +8,7 @@
 #include "src/allocation.h"
 #include "src/base/smart-pointers.h"
 #include "src/builtins.h"
-#include "src/compiler/code-stub-assembler.h"
+#include "src/code-stub-assembler.h"
 #include "src/frames.h"
 #include "src/interpreter/bytecodes.h"
 #include "src/runtime/runtime.h"
@@ -17,7 +17,7 @@
 namespace internal {
 namespace interpreter {
 
-class InterpreterAssembler : public compiler::CodeStubAssembler {
+class InterpreterAssembler : public CodeStubAssembler {
  public:
   InterpreterAssembler(Isolate* isolate, Zone* zone, Bytecode bytecode,
                        OperandScale operand_scale);
@@ -41,6 +41,9 @@
   // Returns the runtime id immediate for bytecode operand
   // |operand_index| in the current bytecode.
   compiler::Node* BytecodeOperandRuntimeId(int operand_index);
+  // Returns the intrinsic id immediate for bytecode operand
+  // |operand_index| in the current bytecode.
+  compiler::Node* BytecodeOperandIntrinsicId(int operand_index);
 
   // Accumulator.
   compiler::Node* GetAccumulator();
@@ -50,11 +53,16 @@
   compiler::Node* GetContext();
   void SetContext(compiler::Node* value);
 
+  // Number of registers.
+  compiler::Node* RegisterCount();
+
+  // Backup/restore register file to/from a fixed array of the correct length.
+  compiler::Node* ExportRegisterFile(compiler::Node* array);
+  compiler::Node* ImportRegisterFile(compiler::Node* array);
+
   // Loads from and stores to the interpreter register file.
-  compiler::Node* LoadRegister(int offset);
   compiler::Node* LoadRegister(Register reg);
   compiler::Node* LoadRegister(compiler::Node* reg_index);
-  compiler::Node* StoreRegister(compiler::Node* value, int offset);
   compiler::Node* StoreRegister(compiler::Node* value, Register reg);
   compiler::Node* StoreRegister(compiler::Node* value,
                                 compiler::Node* reg_index);
@@ -69,9 +77,6 @@
   // Load constant at |index| in the constant pool.
   compiler::Node* LoadConstantPoolEntry(compiler::Node* index);
 
-  // Load a field from an object on the heap.
-  compiler::Node* LoadObjectField(compiler::Node* object, int offset);
-
   // Load |slot_index| from |context|.
   compiler::Node* LoadContextSlot(compiler::Node* context, int slot_index);
   compiler::Node* LoadContextSlot(compiler::Node* context,
@@ -110,12 +115,7 @@
                                compiler::Node* arg_count, int return_size = 1);
 
   // Jump relative to the current bytecode by |jump_offset|.
-  void Jump(compiler::Node* jump_offset);
-
-  // Jump relative to the current bytecode by |jump_offset| if the
-  // |condition| is true. Helper function for JumpIfWordEqual and
-  // JumpIfWordNotEqual.
-  void JumpConditional(compiler::Node* condition, compiler::Node* jump_offset);
+  compiler::Node* Jump(compiler::Node* jump_offset);
 
   // Jump relative to the current bytecode by |jump_offset| if the
   // word values |lhs| and |rhs| are equal.
@@ -127,20 +127,18 @@
   void JumpIfWordNotEqual(compiler::Node* lhs, compiler::Node* rhs,
                           compiler::Node* jump_offset);
 
-  // Perform a stack guard check.
-  void StackCheck();
+  // Returns true if the stack guard check triggers an interrupt.
+  compiler::Node* StackCheckTriggeredInterrupt();
 
-  // Returns from the function.
-  void InterpreterReturn();
+  // Updates the profiler interrupt budget for a return.
+  void UpdateInterruptBudgetOnReturn();
 
   // Dispatch to the bytecode.
-  void Dispatch();
+  compiler::Node* Dispatch();
 
   // Dispatch to bytecode handler.
-  void DispatchToBytecodeHandler(compiler::Node* handler,
-                                 compiler::Node* bytecode_offset);
-  void DispatchToBytecodeHandler(compiler::Node* handler) {
-    DispatchToBytecodeHandler(handler, BytecodeOffset());
+  compiler::Node* DispatchToBytecodeHandler(compiler::Node* handler) {
+    return DispatchToBytecodeHandler(handler, BytecodeOffset());
   }
 
   // Dispatch bytecode as wide operand variant.
@@ -148,18 +146,20 @@
 
   // Abort with the given bailout reason.
   void Abort(BailoutReason bailout_reason);
+  void AbortIfWordNotEqual(compiler::Node* lhs, compiler::Node* rhs,
+                           BailoutReason bailout_reason);
+
+  // Returns the offset from the BytecodeArrayPointer of the current bytecode.
+  compiler::Node* BytecodeOffset();
 
  protected:
   Bytecode bytecode() const { return bytecode_; }
   static bool TargetSupportsUnalignedAccess();
 
  private:
-  // Returns a raw pointer to start of the register file on the stack.
-  compiler::Node* RegisterFileRawPointer();
   // Returns a tagged pointer to the current function's BytecodeArray object.
   compiler::Node* BytecodeArrayTaggedPointer();
-  // Returns the offset from the BytecodeArrayPointer of the current bytecode.
-  compiler::Node* BytecodeOffset();
+
   // Returns a raw pointer to first entry in the interpreter dispatch table.
   compiler::Node* DispatchTableRawPointer();
 
@@ -168,11 +168,18 @@
   // tracing as these need to bypass accumulator use validity checks.
   compiler::Node* GetAccumulatorUnchecked();
 
+  // Returns the frame pointer for the interpreted frame of the function being
+  // interpreted.
+  compiler::Node* GetInterpretedFramePointer();
+
   // Saves and restores interpreter bytecode offset to the interpreter stack
   // frame when performing a call.
   void CallPrologue() override;
   void CallEpilogue() override;
 
+  // Increment the dispatch counter for the (current, next) bytecode pair.
+  void TraceBytecodeDispatch(compiler::Node* target_index);
+
   // Traces the current bytecode by calling |function_id|.
   void TraceBytecode(Runtime::FunctionId function_id);
 
@@ -206,26 +213,35 @@
   compiler::Node* BytecodeUnsignedOperand(int operand_index,
                                           OperandSize operand_size);
 
+  // Jump relative to the current bytecode by |jump_offset| if the
+  // |condition| is true. Helper function for JumpIfWordEqual and
+  // JumpIfWordNotEqual.
+  void JumpConditional(compiler::Node* condition, compiler::Node* jump_offset);
+
   // Returns BytecodeOffset() advanced by delta bytecodes. Note: this does not
   // update BytecodeOffset() itself.
   compiler::Node* Advance(int delta);
   compiler::Node* Advance(compiler::Node* delta);
 
   // Starts next instruction dispatch at |new_bytecode_offset|.
-  void DispatchTo(compiler::Node* new_bytecode_offset);
+  compiler::Node* DispatchTo(compiler::Node* new_bytecode_offset);
 
-  // Abort operations for debug code.
-  void AbortIfWordNotEqual(compiler::Node* lhs, compiler::Node* rhs,
-                           BailoutReason bailout_reason);
+  // Dispatch to the bytecode handler with code offset |handler|.
+  compiler::Node* DispatchToBytecodeHandler(compiler::Node* handler,
+                                            compiler::Node* bytecode_offset);
+
+  // Dispatch to the bytecode handler with code entry point |handler_entry|.
+  compiler::Node* DispatchToBytecodeHandlerEntry(
+      compiler::Node* handler_entry, compiler::Node* bytecode_offset);
 
   OperandScale operand_scale() const { return operand_scale_; }
 
   Bytecode bytecode_;
   OperandScale operand_scale_;
+  CodeStubAssembler::Variable interpreted_frame_pointer_;
   CodeStubAssembler::Variable accumulator_;
   AccumulatorUse accumulator_use_;
-  CodeStubAssembler::Variable context_;
-  CodeStubAssembler::Variable bytecode_array_;
+  bool made_call_;
 
   bool disable_stack_check_across_call_;
   compiler::Node* stack_pointer_before_call_;
diff --git a/src/interpreter/interpreter-intrinsics.cc b/src/interpreter/interpreter-intrinsics.cc
index 6d9917d..109bf8e 100644
--- a/src/interpreter/interpreter-intrinsics.cc
+++ b/src/interpreter/interpreter-intrinsics.cc
@@ -4,6 +4,8 @@
 
 #include "src/interpreter/interpreter-intrinsics.h"
 
+#include "src/code-factory.h"
+
 namespace v8 {
 namespace internal {
 namespace interpreter {
@@ -13,8 +15,11 @@
 #define __ assembler_->
 
 IntrinsicsHelper::IntrinsicsHelper(InterpreterAssembler* assembler)
-    : assembler_(assembler) {}
+    : isolate_(assembler->isolate()),
+      zone_(assembler->zone()),
+      assembler_(assembler) {}
 
+// static
 bool IntrinsicsHelper::IsSupported(Runtime::FunctionId function_id) {
   switch (function_id) {
 #define SUPPORTED(name, lower_case, count) case Runtime::kInline##name:
@@ -26,6 +31,36 @@
   }
 }
 
+// static
+IntrinsicsHelper::IntrinsicId IntrinsicsHelper::FromRuntimeId(
+    Runtime::FunctionId function_id) {
+  switch (function_id) {
+#define TO_RUNTIME_ID(name, lower_case, count) \
+  case Runtime::kInline##name:                 \
+    return IntrinsicId::k##name;
+    INTRINSICS_LIST(TO_RUNTIME_ID)
+#undef TO_RUNTIME_ID
+    default:
+      UNREACHABLE();
+      return static_cast<IntrinsicsHelper::IntrinsicId>(-1);
+  }
+}
+
+// static
+Runtime::FunctionId IntrinsicsHelper::ToRuntimeId(
+    IntrinsicsHelper::IntrinsicId intrinsic_id) {
+  switch (intrinsic_id) {
+#define TO_INTRINSIC_ID(name, lower_case, count) \
+  case IntrinsicId::k##name:                     \
+    return Runtime::kInline##name;
+    INTRINSICS_LIST(TO_INTRINSIC_ID)
+#undef TO_INTRINSIC_ID
+    default:
+      UNREACHABLE();
+      return static_cast<Runtime::FunctionId>(-1);
+  }
+}
+
 Node* IntrinsicsHelper::InvokeIntrinsic(Node* function_id, Node* context,
                                         Node* first_arg_reg, Node* arg_count) {
   InterpreterAssembler::Label abort(assembler_), end(assembler_);
@@ -42,25 +77,27 @@
 #undef LABEL_POINTER
 
 #define CASE(name, lower_case, count) \
-  static_cast<int32_t>(Runtime::kInline##name),
+  static_cast<int32_t>(IntrinsicId::k##name),
   int32_t cases[] = {INTRINSICS_LIST(CASE)};
 #undef CASE
 
   __ Switch(function_id, &abort, cases, labels, arraysize(cases));
 #define HANDLE_CASE(name, lower_case, expected_arg_count)   \
   __ Bind(&lower_case);                                     \
-  if (FLAG_debug_code) {                                    \
+  if (FLAG_debug_code && expected_arg_count >= 0) {         \
     AbortIfArgCountMismatch(expected_arg_count, arg_count); \
   }                                                         \
-  result.Bind(name(first_arg_reg));                         \
+  result.Bind(name(first_arg_reg, arg_count, context));     \
   __ Goto(&end);
   INTRINSICS_LIST(HANDLE_CASE)
 #undef HANDLE_CASE
 
   __ Bind(&abort);
-  __ Abort(BailoutReason::kUnexpectedFunctionIDForInvokeIntrinsic);
-  result.Bind(__ UndefinedConstant());
-  __ Goto(&end);
+  {
+    __ Abort(BailoutReason::kUnexpectedFunctionIDForInvokeIntrinsic);
+    result.Bind(__ UndefinedConstant());
+    __ Goto(&end);
+  }
 
   __ Bind(&end);
   return result.value();
@@ -74,84 +111,246 @@
 
   InterpreterAssembler::Label if_true(assembler_), if_false(assembler_),
       end(assembler_);
-  Node* condition;
   if (mode == kInstanceTypeEqual) {
-    condition = __ Word32Equal(instance_type, __ Int32Constant(type));
+    return __ Word32Equal(instance_type, __ Int32Constant(type));
   } else {
     DCHECK(mode == kInstanceTypeGreaterThanOrEqual);
-    condition =
-        __ Int32GreaterThanOrEqual(instance_type, __ Int32Constant(type));
+    return __ Int32GreaterThanOrEqual(instance_type, __ Int32Constant(type));
   }
-  __ Branch(condition, &if_true, &if_false);
+}
 
-  __ Bind(&if_true);
-  return_value.Bind(__ BooleanConstant(true));
-  __ Goto(&end);
+Node* IntrinsicsHelper::IsInstanceType(Node* input, int type) {
+  InterpreterAssembler::Variable return_value(assembler_,
+                                              MachineRepresentation::kTagged);
+  InterpreterAssembler::Label if_not_smi(assembler_), return_true(assembler_),
+      return_false(assembler_), end(assembler_);
+  Node* arg = __ LoadRegister(input);
+  __ GotoIf(__ WordIsSmi(arg), &return_false);
 
-  __ Bind(&if_false);
-  return_value.Bind(__ BooleanConstant(false));
-  __ Goto(&end);
+  Node* condition = CompareInstanceType(arg, type, kInstanceTypeEqual);
+  __ Branch(condition, &return_true, &return_false);
+
+  __ Bind(&return_true);
+  {
+    return_value.Bind(__ BooleanConstant(true));
+    __ Goto(&end);
+  }
+
+  __ Bind(&return_false);
+  {
+    return_value.Bind(__ BooleanConstant(false));
+    __ Goto(&end);
+  }
 
   __ Bind(&end);
   return return_value.value();
 }
 
-Node* IntrinsicsHelper::IsJSReceiver(Node* input) {
+Node* IntrinsicsHelper::IsJSReceiver(Node* input, Node* arg_count,
+                                     Node* context) {
   InterpreterAssembler::Variable return_value(assembler_,
                                               MachineRepresentation::kTagged);
-
-  InterpreterAssembler::Label if_smi(assembler_), if_not_smi(assembler_),
+  InterpreterAssembler::Label return_true(assembler_), return_false(assembler_),
       end(assembler_);
+
   Node* arg = __ LoadRegister(input);
+  __ GotoIf(__ WordIsSmi(arg), &return_false);
 
-  __ Branch(__ WordIsSmi(arg), &if_smi, &if_not_smi);
-  __ Bind(&if_smi);
-  return_value.Bind(__ BooleanConstant(false));
-  __ Goto(&end);
-
-  __ Bind(&if_not_smi);
   STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
-  return_value.Bind(CompareInstanceType(arg, FIRST_JS_RECEIVER_TYPE,
-                                        kInstanceTypeGreaterThanOrEqual));
-  __ Goto(&end);
+  Node* condition = CompareInstanceType(arg, FIRST_JS_RECEIVER_TYPE,
+                                        kInstanceTypeGreaterThanOrEqual);
+  __ Branch(condition, &return_true, &return_false);
+
+  __ Bind(&return_true);
+  {
+    return_value.Bind(__ BooleanConstant(true));
+    __ Goto(&end);
+  }
+
+  __ Bind(&return_false);
+  {
+    return_value.Bind(__ BooleanConstant(false));
+    __ Goto(&end);
+  }
 
   __ Bind(&end);
   return return_value.value();
 }
 
-Node* IntrinsicsHelper::IsArray(Node* input) {
+Node* IntrinsicsHelper::IsArray(Node* input, Node* arg_count, Node* context) {
+  return IsInstanceType(input, JS_ARRAY_TYPE);
+}
+
+Node* IntrinsicsHelper::IsJSProxy(Node* input, Node* arg_count, Node* context) {
+  return IsInstanceType(input, JS_PROXY_TYPE);
+}
+
+Node* IntrinsicsHelper::IsRegExp(Node* input, Node* arg_count, Node* context) {
+  return IsInstanceType(input, JS_REGEXP_TYPE);
+}
+
+Node* IntrinsicsHelper::IsTypedArray(Node* input, Node* arg_count,
+                                     Node* context) {
+  return IsInstanceType(input, JS_TYPED_ARRAY_TYPE);
+}
+
+Node* IntrinsicsHelper::IsSmi(Node* input, Node* arg_count, Node* context) {
   InterpreterAssembler::Variable return_value(assembler_,
                                               MachineRepresentation::kTagged);
-
   InterpreterAssembler::Label if_smi(assembler_), if_not_smi(assembler_),
       end(assembler_);
+
   Node* arg = __ LoadRegister(input);
 
   __ Branch(__ WordIsSmi(arg), &if_smi, &if_not_smi);
   __ Bind(&if_smi);
-  return_value.Bind(__ BooleanConstant(false));
-  __ Goto(&end);
+  {
+    return_value.Bind(__ BooleanConstant(true));
+    __ Goto(&end);
+  }
 
   __ Bind(&if_not_smi);
-  return_value.Bind(
-      CompareInstanceType(arg, JS_ARRAY_TYPE, kInstanceTypeEqual));
-  __ Goto(&end);
+  {
+    return_value.Bind(__ BooleanConstant(false));
+    __ Goto(&end);
+  }
 
   __ Bind(&end);
   return return_value.value();
 }
 
+Node* IntrinsicsHelper::IntrinsicAsStubCall(Node* args_reg, Node* context,
+                                            Callable const& callable) {
+  int param_count = callable.descriptor().GetParameterCount();
+  Node** args = zone()->NewArray<Node*>(param_count + 1);  // 1 for context
+  for (int i = 0; i < param_count; i++) {
+    args[i] = __ LoadRegister(args_reg);
+    args_reg = __ NextRegister(args_reg);
+  }
+  args[param_count] = context;
+
+  return __ CallStubN(callable, args);
+}
+
+Node* IntrinsicsHelper::HasProperty(Node* input, Node* arg_count,
+                                    Node* context) {
+  return IntrinsicAsStubCall(input, context,
+                             CodeFactory::HasProperty(isolate()));
+}
+
+Node* IntrinsicsHelper::MathPow(Node* input, Node* arg_count, Node* context) {
+  return IntrinsicAsStubCall(input, context, CodeFactory::MathPow(isolate()));
+}
+
+Node* IntrinsicsHelper::NewObject(Node* input, Node* arg_count, Node* context) {
+  return IntrinsicAsStubCall(input, context,
+                             CodeFactory::FastNewObject(isolate()));
+}
+
+Node* IntrinsicsHelper::NumberToString(Node* input, Node* arg_count,
+                                       Node* context) {
+  return IntrinsicAsStubCall(input, context,
+                             CodeFactory::NumberToString(isolate()));
+}
+
+Node* IntrinsicsHelper::RegExpConstructResult(Node* input, Node* arg_count,
+                                              Node* context) {
+  return IntrinsicAsStubCall(input, context,
+                             CodeFactory::RegExpConstructResult(isolate()));
+}
+
+Node* IntrinsicsHelper::RegExpExec(Node* input, Node* arg_count,
+                                   Node* context) {
+  return IntrinsicAsStubCall(input, context,
+                             CodeFactory::RegExpExec(isolate()));
+}
+
+Node* IntrinsicsHelper::SubString(Node* input, Node* arg_count, Node* context) {
+  return IntrinsicAsStubCall(input, context, CodeFactory::SubString(isolate()));
+}
+
+Node* IntrinsicsHelper::ToString(Node* input, Node* arg_count, Node* context) {
+  return IntrinsicAsStubCall(input, context, CodeFactory::ToString(isolate()));
+}
+
+Node* IntrinsicsHelper::ToName(Node* input, Node* arg_count, Node* context) {
+  return IntrinsicAsStubCall(input, context, CodeFactory::ToName(isolate()));
+}
+
+Node* IntrinsicsHelper::ToLength(Node* input, Node* arg_count, Node* context) {
+  return IntrinsicAsStubCall(input, context, CodeFactory::ToLength(isolate()));
+}
+
+Node* IntrinsicsHelper::ToInteger(Node* input, Node* arg_count, Node* context) {
+  return IntrinsicAsStubCall(input, context, CodeFactory::ToInteger(isolate()));
+}
+
+Node* IntrinsicsHelper::ToNumber(Node* input, Node* arg_count, Node* context) {
+  return IntrinsicAsStubCall(input, context, CodeFactory::ToNumber(isolate()));
+}
+
+Node* IntrinsicsHelper::ToObject(Node* input, Node* arg_count, Node* context) {
+  return IntrinsicAsStubCall(input, context, CodeFactory::ToObject(isolate()));
+}
+
+Node* IntrinsicsHelper::Call(Node* args_reg, Node* arg_count, Node* context) {
+  // First argument register contains the function target.
+  Node* function = __ LoadRegister(args_reg);
+
+  // Receiver is the second runtime call argument.
+  Node* receiver_reg = __ NextRegister(args_reg);
+  Node* receiver_arg = __ RegisterLocation(receiver_reg);
+
+  // Subtract function and receiver from arg count.
+  Node* function_and_receiver_count = __ Int32Constant(2);
+  Node* target_args_count = __ Int32Sub(arg_count, function_and_receiver_count);
+
+  if (FLAG_debug_code) {
+    InterpreterAssembler::Label arg_count_positive(assembler_);
+    Node* comparison = __ Int32LessThan(target_args_count, __ Int32Constant(0));
+    __ GotoUnless(comparison, &arg_count_positive);
+    __ Abort(kWrongArgumentCountForInvokeIntrinsic);
+    __ Goto(&arg_count_positive);
+    __ Bind(&arg_count_positive);
+  }
+
+  Node* result = __ CallJS(function, context, receiver_arg, target_args_count,
+                           TailCallMode::kDisallow);
+  return result;
+}
+
+Node* IntrinsicsHelper::ValueOf(Node* args_reg, Node* arg_count,
+                                Node* context) {
+  InterpreterAssembler::Variable return_value(assembler_,
+                                              MachineRepresentation::kTagged);
+  InterpreterAssembler::Label done(assembler_);
+
+  Node* object = __ LoadRegister(args_reg);
+  return_value.Bind(object);
+
+  // If the object is a smi return the object.
+  __ GotoIf(__ WordIsSmi(object), &done);
+
+  // If the object is not a value type, return the object.
+  Node* condition =
+      CompareInstanceType(object, JS_VALUE_TYPE, kInstanceTypeEqual);
+  __ GotoUnless(condition, &done);
+
+  // If the object is a value type, return the value field.
+  return_value.Bind(__ LoadObjectField(object, JSValue::kValueOffset));
+  __ Goto(&done);
+
+  __ Bind(&done);
+  return return_value.value();
+}
+
 void IntrinsicsHelper::AbortIfArgCountMismatch(int expected, Node* actual) {
-  InterpreterAssembler::Label match(assembler_), mismatch(assembler_),
-      end(assembler_);
+  InterpreterAssembler::Label match(assembler_);
   Node* comparison = __ Word32Equal(actual, __ Int32Constant(expected));
-  __ Branch(comparison, &match, &mismatch);
-  __ Bind(&mismatch);
+  __ GotoIf(comparison, &match);
   __ Abort(kWrongArgumentCountForInvokeIntrinsic);
-  __ Goto(&end);
+  __ Goto(&match);
   __ Bind(&match);
-  __ Goto(&end);
-  __ Bind(&end);
 }
 
 }  // namespace interpreter
diff --git a/src/interpreter/interpreter-intrinsics.h b/src/interpreter/interpreter-intrinsics.h
index e27c678..b1c0cdc 100644
--- a/src/interpreter/interpreter-intrinsics.h
+++ b/src/interpreter/interpreter-intrinsics.h
@@ -20,14 +20,43 @@
 class Node;
 }  // namespace compiler
 
-#define INTRINSICS_LIST(V)           \
-  V(IsJSReceiver, is_js_receiver, 1) \
-  V(IsArray, is_array, 1)
-
 namespace interpreter {
 
+// List of supported intrisics, with upper case name, lower case name and
+// expected number of arguments (-1 denoting argument count is variable).
+#define INTRINSICS_LIST(V)                              \
+  V(Call, call, -1)                                     \
+  V(HasProperty, has_property, 2)                       \
+  V(IsArray, is_array, 1)                               \
+  V(IsJSProxy, is_js_proxy, 1)                          \
+  V(IsJSReceiver, is_js_receiver, 1)                    \
+  V(IsRegExp, is_regexp, 1)                             \
+  V(IsSmi, is_smi, 1)                                   \
+  V(IsTypedArray, is_typed_array, 1)                    \
+  V(MathPow, math_pow, 2)                               \
+  V(NewObject, new_object, 2)                           \
+  V(NumberToString, number_to_string, 1)                \
+  V(RegExpConstructResult, reg_exp_construct_result, 3) \
+  V(RegExpExec, reg_exp_exec, 4)                        \
+  V(SubString, sub_string, 3)                           \
+  V(ToString, to_string, 1)                             \
+  V(ToName, to_name, 1)                                 \
+  V(ToLength, to_length, 1)                             \
+  V(ToInteger, to_integer, 1)                           \
+  V(ToNumber, to_number, 1)                             \
+  V(ToObject, to_object, 1)                             \
+  V(ValueOf, value_of, 1)
+
 class IntrinsicsHelper {
  public:
+  enum class IntrinsicId {
+#define DECLARE_INTRINSIC_ID(name, lower_case, count) k##name,
+    INTRINSICS_LIST(DECLARE_INTRINSIC_ID)
+#undef DECLARE_INTRINSIC_ID
+        kIdCount
+  };
+  STATIC_ASSERT(static_cast<uint32_t>(IntrinsicId::kIdCount) <= kMaxUInt8);
+
   explicit IntrinsicsHelper(InterpreterAssembler* assembler);
 
   compiler::Node* InvokeIntrinsic(compiler::Node* function_id,
@@ -36,22 +65,36 @@
                                   compiler::Node* arg_count);
 
   static bool IsSupported(Runtime::FunctionId function_id);
+  static IntrinsicId FromRuntimeId(Runtime::FunctionId function_id);
+  static Runtime::FunctionId ToRuntimeId(IntrinsicId intrinsic_id);
 
  private:
   enum InstanceTypeCompareMode {
     kInstanceTypeEqual,
     kInstanceTypeGreaterThanOrEqual
   };
+
+  compiler::Node* IsInstanceType(compiler::Node* input, int type);
   compiler::Node* CompareInstanceType(compiler::Node* map, int type,
                                       InstanceTypeCompareMode mode);
+  compiler::Node* IntrinsicAsStubCall(compiler::Node* input,
+                                      compiler::Node* context,
+                                      Callable const& callable);
   void AbortIfArgCountMismatch(int expected, compiler::Node* actual);
-  InterpreterAssembler* assembler_;
 
-#define DECLARE_INTRINSIC_HELPER(name, lower_case, count) \
-  compiler::Node* name(compiler::Node* input);
+#define DECLARE_INTRINSIC_HELPER(name, lower_case, count)                \
+  compiler::Node* name(compiler::Node* input, compiler::Node* arg_count, \
+                       compiler::Node* context);
   INTRINSICS_LIST(DECLARE_INTRINSIC_HELPER)
 #undef DECLARE_INTRINSIC_HELPER
 
+  Isolate* isolate() { return isolate_; }
+  Zone* zone() { return zone_; }
+
+  Isolate* isolate_;
+  Zone* zone_;
+  InterpreterAssembler* assembler_;
+
   DISALLOW_COPY_AND_ASSIGN(IntrinsicsHelper);
 };
 
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index 5084300..8a05777 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -4,6 +4,8 @@
 
 #include "src/interpreter/interpreter.h"
 
+#include <fstream>
+
 #include "src/ast/prettyprinter.h"
 #include "src/code-factory.h"
 #include "src/compiler.h"
@@ -20,6 +22,8 @@
 namespace interpreter {
 
 using compiler::Node;
+typedef CodeStubAssembler::Label Label;
+typedef CodeStubAssembler::Variable Variable;
 
 #define __ assembler->
 
@@ -28,15 +32,26 @@
 }
 
 void Interpreter::Initialize() {
-  DCHECK(FLAG_ignition);
   if (IsDispatchTableInitialized()) return;
   Zone zone(isolate_->allocator());
   HandleScope scope(isolate_);
 
+  if (FLAG_trace_ignition_dispatches) {
+    static const int kBytecodeCount = static_cast<int>(Bytecode::kLast) + 1;
+    bytecode_dispatch_counters_table_.Reset(
+        new uintptr_t[kBytecodeCount * kBytecodeCount]);
+    memset(bytecode_dispatch_counters_table_.get(), 0,
+           sizeof(uintptr_t) * kBytecodeCount * kBytecodeCount);
+  }
+
   // Generate bytecode handlers for all bytecodes and scales.
-  for (OperandScale operand_scale = OperandScale::kSingle;
-       operand_scale <= OperandScale::kMaxValid;
-       operand_scale = Bytecodes::NextOperandScale(operand_scale)) {
+  const OperandScale kOperandScales[] = {
+#define VALUE(Name, _) OperandScale::k##Name,
+      OPERAND_SCALE_LIST(VALUE)
+#undef VALUE
+  };
+
+  for (OperandScale operand_scale : kOperandScales) {
 #define GENERATE_CODE(Name, ...)                                               \
   {                                                                            \
     if (Bytecodes::BytecodeHasHandler(Bytecode::k##Name, operand_scale)) {     \
@@ -45,12 +60,13 @@
       Do##Name(&assembler);                                                    \
       Handle<Code> code = assembler.GenerateCode();                            \
       size_t index = GetDispatchTableIndex(Bytecode::k##Name, operand_scale);  \
-      dispatch_table_[index] = *code;                                          \
+      dispatch_table_[index] = code->entry();                                  \
       TraceCodegen(code);                                                      \
-      LOG_CODE_EVENT(                                                          \
+      PROFILE(                                                                 \
           isolate_,                                                            \
           CodeCreateEvent(                                                     \
-              Logger::BYTECODE_HANDLER_TAG, AbstractCode::cast(*code),         \
+              CodeEventListener::BYTECODE_HANDLER_TAG,                         \
+              AbstractCode::cast(*code),                                       \
               Bytecodes::ToString(Bytecode::k##Name, operand_scale).c_str())); \
     }                                                                          \
   }
@@ -73,7 +89,8 @@
   DCHECK(IsDispatchTableInitialized());
   DCHECK(Bytecodes::BytecodeHasHandler(bytecode, operand_scale));
   size_t index = GetDispatchTableIndex(bytecode, operand_scale);
-  return dispatch_table_[index];
+  Address code_entry = dispatch_table_[index];
+  return Code::GetCodeFromTargetAddress(code_entry);
 }
 
 // static
@@ -81,18 +98,30 @@
                                           OperandScale operand_scale) {
   static const size_t kEntriesPerOperandScale = 1u << kBitsPerByte;
   size_t index = static_cast<size_t>(bytecode);
-  OperandScale current_scale = OperandScale::kSingle;
-  while (current_scale != operand_scale) {
-    index += kEntriesPerOperandScale;
-    current_scale = Bytecodes::NextOperandScale(current_scale);
+  switch (operand_scale) {
+    case OperandScale::kSingle:
+      return index;
+    case OperandScale::kDouble:
+      return index + kEntriesPerOperandScale;
+    case OperandScale::kQuadruple:
+      return index + 2 * kEntriesPerOperandScale;
   }
-  return index;
+  UNREACHABLE();
+  return 0;
 }
 
 void Interpreter::IterateDispatchTable(ObjectVisitor* v) {
-  v->VisitPointers(
-      reinterpret_cast<Object**>(&dispatch_table_[0]),
-      reinterpret_cast<Object**>(&dispatch_table_[0] + kDispatchTableSize));
+  for (int i = 0; i < kDispatchTableSize; i++) {
+    Address code_entry = dispatch_table_[i];
+    Object* code = code_entry == nullptr
+                       ? nullptr
+                       : Code::GetCodeFromTargetAddress(code_entry);
+    Object* old_code = code;
+    v->VisitPointer(&code);
+    if (code != old_code) {
+      dispatch_table_[i] = reinterpret_cast<Code*>(code)->entry();
+    }
+  }
 }
 
 // static
@@ -103,6 +132,8 @@
 }
 
 bool Interpreter::MakeBytecode(CompilationInfo* info) {
+  RuntimeCallTimerScope runtimeTimer(info->isolate(),
+                                     &RuntimeCallStats::CompileIgnition);
   TimerEventScope<TimerEventCompileIgnition> timer(info->isolate());
   TRACE_EVENT0("v8", "V8.CompileIgnition");
 
@@ -131,8 +162,8 @@
   }
 #endif  // DEBUG
 
-  BytecodeGenerator generator(info->isolate(), info->zone());
-  Handle<BytecodeArray> bytecodes = generator.MakeBytecode(info);
+  BytecodeGenerator generator(info);
+  Handle<BytecodeArray> bytecodes = generator.MakeBytecode();
 
   if (generator.HasStackOverflow()) return false;
 
@@ -148,9 +179,10 @@
 }
 
 bool Interpreter::IsDispatchTableInitialized() {
-  if (FLAG_trace_ignition || FLAG_trace_ignition_codegen) {
-    // Regenerate table to add bytecode tracing operations
-    // or to print the assembly code generated by TurboFan.
+  if (FLAG_trace_ignition || FLAG_trace_ignition_codegen ||
+      FLAG_trace_ignition_dispatches) {
+    // Regenerate table to add bytecode tracing operations, print the assembly
+    // code generated by TurboFan or instrument handlers with dispatch counters.
     return false;
   }
   return dispatch_table_[0] != nullptr;
@@ -168,9 +200,10 @@
 
 const char* Interpreter::LookupNameOfBytecodeHandler(Code* code) {
 #ifdef ENABLE_DISASSEMBLER
-#define RETURN_NAME(Name, ...)                                         \
-  if (dispatch_table_[Bytecodes::ToByte(Bytecode::k##Name)] == code) { \
-    return #Name;                                                      \
+#define RETURN_NAME(Name, ...)                                 \
+  if (dispatch_table_[Bytecodes::ToByte(Bytecode::k##Name)] == \
+      code->entry()) {                                         \
+    return #Name;                                              \
   }
   BYTECODE_LIST(RETURN_NAME)
 #undef RETURN_NAME
@@ -178,6 +211,65 @@
   return nullptr;
 }
 
+uintptr_t Interpreter::GetDispatchCounter(Bytecode from, Bytecode to) const {
+  int from_index = Bytecodes::ToByte(from);
+  int to_index = Bytecodes::ToByte(to);
+  return bytecode_dispatch_counters_table_[from_index * kNumberOfBytecodes +
+                                           to_index];
+}
+
+Local<v8::Object> Interpreter::GetDispatchCountersObject() {
+  v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(isolate_);
+  Local<v8::Context> context = isolate->GetCurrentContext();
+
+  Local<v8::Object> counters_map = v8::Object::New(isolate);
+
+  // Output is a JSON-encoded object of objects.
+  //
+  // The keys on the top level object are source bytecodes,
+  // and corresponding value are objects. Keys on these last are the
+  // destinations of the dispatch and the value associated is a counter for
+  // the correspondent source-destination dispatch chain.
+  //
+  // Only non-zero counters are written to file, but an entry in the top-level
+  // object is always present, even if the value is empty because all counters
+  // for that source are zero.
+
+  for (int from_index = 0; from_index < kNumberOfBytecodes; ++from_index) {
+    Bytecode from_bytecode = Bytecodes::FromByte(from_index);
+    Local<v8::Object> counters_row = v8::Object::New(isolate);
+
+    for (int to_index = 0; to_index < kNumberOfBytecodes; ++to_index) {
+      Bytecode to_bytecode = Bytecodes::FromByte(to_index);
+      uintptr_t counter = GetDispatchCounter(from_bytecode, to_bytecode);
+
+      if (counter > 0) {
+        std::string to_name = Bytecodes::ToString(to_bytecode);
+        Local<v8::String> to_name_object =
+            v8::String::NewFromUtf8(isolate, to_name.c_str(),
+                                    NewStringType::kNormal)
+                .ToLocalChecked();
+        Local<v8::Number> counter_object = v8::Number::New(isolate, counter);
+        CHECK(counters_row
+                  ->DefineOwnProperty(context, to_name_object, counter_object)
+                  .IsJust());
+      }
+    }
+
+    std::string from_name = Bytecodes::ToString(from_bytecode);
+    Local<v8::String> from_name_object =
+        v8::String::NewFromUtf8(isolate, from_name.c_str(),
+                                NewStringType::kNormal)
+            .ToLocalChecked();
+
+    CHECK(
+        counters_map->DefineOwnProperty(context, from_name_object, counters_row)
+            .IsJust());
+  }
+
+  return counters_map;
+}
+
 // LdaZero
 //
 // Load literal '0' into the accumulator.
@@ -197,19 +289,14 @@
   __ Dispatch();
 }
 
-void Interpreter::DoLoadConstant(InterpreterAssembler* assembler) {
-  Node* index = __ BytecodeOperandIdx(0);
-  Node* constant = __ LoadConstantPoolEntry(index);
-  __ SetAccumulator(constant);
-  __ Dispatch();
-}
-
-
 // LdaConstant <idx>
 //
 // Load constant literal at |idx| in the constant pool into the accumulator.
 void Interpreter::DoLdaConstant(InterpreterAssembler* assembler) {
-  DoLoadConstant(assembler);
+  Node* index = __ BytecodeOperandIdx(0);
+  Node* constant = __ LoadConstantPoolEntry(index);
+  __ SetAccumulator(constant);
+  __ Dispatch();
 }
 
 // LdaUndefined
@@ -222,6 +309,16 @@
   __ Dispatch();
 }
 
+// LdrUndefined <reg>
+//
+// Loads undefined into the accumulator and |reg|.
+void Interpreter::DoLdrUndefined(InterpreterAssembler* assembler) {
+  Node* undefined_value =
+      __ HeapConstant(isolate_->factory()->undefined_value());
+  Node* destination = __ BytecodeOperandReg(0);
+  __ StoreRegister(undefined_value, destination);
+  __ Dispatch();
+}
 
 // LdaNull
 //
@@ -232,7 +329,6 @@
   __ Dispatch();
 }
 
-
 // LdaTheHole
 //
 // Load TheHole into the accumulator.
@@ -242,7 +338,6 @@
   __ Dispatch();
 }
 
-
 // LdaTrue
 //
 // Load True into the accumulator.
@@ -252,7 +347,6 @@
   __ Dispatch();
 }
 
-
 // LdaFalse
 //
 // Load False into the accumulator.
@@ -262,7 +356,6 @@
   __ Dispatch();
 }
 
-
 // Ldar <src>
 //
 // Load accumulator with value from register <src>.
@@ -273,7 +366,6 @@
   __ Dispatch();
 }
 
-
 // Star <dst>
 //
 // Store accumulator to register <dst>.
@@ -284,7 +376,6 @@
   __ Dispatch();
 }
 
-
 // Mov <src> <dst>
 //
 // Stores the value of register <src> to register <dst>.
@@ -296,48 +387,58 @@
   __ Dispatch();
 }
 
-
-void Interpreter::DoLoadGlobal(Callable ic, InterpreterAssembler* assembler) {
+Node* Interpreter::BuildLoadGlobal(Callable ic,
+                                   InterpreterAssembler* assembler) {
   // Get the global object.
   Node* context = __ GetContext();
-  Node* native_context =
-      __ LoadContextSlot(context, Context::NATIVE_CONTEXT_INDEX);
-  Node* global = __ LoadContextSlot(native_context, Context::EXTENSION_INDEX);
 
-  // Load the global via the LoadIC.
+  // Load the global via the LoadGlobalIC.
   Node* code_target = __ HeapConstant(ic.code());
-  Node* constant_index = __ BytecodeOperandIdx(0);
-  Node* name = __ LoadConstantPoolEntry(constant_index);
-  Node* raw_slot = __ BytecodeOperandIdx(1);
+  Node* raw_slot = __ BytecodeOperandIdx(0);
   Node* smi_slot = __ SmiTag(raw_slot);
   Node* type_feedback_vector = __ LoadTypeFeedbackVector();
-  Node* result = __ CallStub(ic.descriptor(), code_target, context, global,
-                             name, smi_slot, type_feedback_vector);
-  __ SetAccumulator(result);
-  __ Dispatch();
+  return __ CallStub(ic.descriptor(), code_target, context, smi_slot,
+                     type_feedback_vector);
 }
 
-// LdaGlobal <name_index> <slot>
+// LdaGlobal <slot>
 //
 // Load the global with name in constant pool entry <name_index> into the
 // accumulator using FeedBackVector slot <slot> outside of a typeof.
 void Interpreter::DoLdaGlobal(InterpreterAssembler* assembler) {
-  Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
-                                                   UNINITIALIZED);
-  DoLoadGlobal(ic, assembler);
+  Callable ic =
+      CodeFactory::LoadGlobalICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF);
+  Node* result = BuildLoadGlobal(ic, assembler);
+  __ SetAccumulator(result);
+  __ Dispatch();
 }
 
-// LdaGlobalInsideTypeof <name_index> <slot>
+// LdrGlobal <slot> <reg>
+//
+// Load the global with name in constant pool entry <name_index> into
+// register <reg> using FeedBackVector slot <slot> outside of a typeof.
+void Interpreter::DoLdrGlobal(InterpreterAssembler* assembler) {
+  Callable ic =
+      CodeFactory::LoadGlobalICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF);
+  Node* result = BuildLoadGlobal(ic, assembler);
+  Node* destination = __ BytecodeOperandReg(1);
+  __ StoreRegister(result, destination);
+  __ Dispatch();
+}
+
+// LdaGlobalInsideTypeof <slot>
 //
 // Load the global with name in constant pool entry <name_index> into the
 // accumulator using FeedBackVector slot <slot> inside of a typeof.
 void Interpreter::DoLdaGlobalInsideTypeof(InterpreterAssembler* assembler) {
-  Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, INSIDE_TYPEOF,
-                                                   UNINITIALIZED);
-  DoLoadGlobal(ic, assembler);
+  Callable ic =
+      CodeFactory::LoadGlobalICInOptimizedCode(isolate_, INSIDE_TYPEOF);
+  Node* result = BuildLoadGlobal(ic, assembler);
+  __ SetAccumulator(result);
+  __ Dispatch();
 }
 
-void Interpreter::DoStoreGlobal(Callable ic, InterpreterAssembler* assembler) {
+void Interpreter::DoStaGlobal(Callable ic, InterpreterAssembler* assembler) {
   // Get the global object.
   Node* context = __ GetContext();
   Node* native_context =
@@ -357,40 +458,51 @@
   __ Dispatch();
 }
 
-
 // StaGlobalSloppy <name_index> <slot>
 //
 // Store the value in the accumulator into the global with name in constant pool
 // entry <name_index> using FeedBackVector slot <slot> in sloppy mode.
 void Interpreter::DoStaGlobalSloppy(InterpreterAssembler* assembler) {
-  Callable ic =
-      CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
-  DoStoreGlobal(ic, assembler);
+  Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY);
+  DoStaGlobal(ic, assembler);
 }
 
-
 // StaGlobalStrict <name_index> <slot>
 //
 // Store the value in the accumulator into the global with name in constant pool
 // entry <name_index> using FeedBackVector slot <slot> in strict mode.
 void Interpreter::DoStaGlobalStrict(InterpreterAssembler* assembler) {
-  Callable ic =
-      CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
-  DoStoreGlobal(ic, assembler);
+  Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, STRICT);
+  DoStaGlobal(ic, assembler);
+}
+
+compiler::Node* Interpreter::BuildLoadContextSlot(
+    InterpreterAssembler* assembler) {
+  Node* reg_index = __ BytecodeOperandReg(0);
+  Node* context = __ LoadRegister(reg_index);
+  Node* slot_index = __ BytecodeOperandIdx(1);
+  return __ LoadContextSlot(context, slot_index);
 }
 
 // LdaContextSlot <context> <slot_index>
 //
 // Load the object in |slot_index| of |context| into the accumulator.
 void Interpreter::DoLdaContextSlot(InterpreterAssembler* assembler) {
-  Node* reg_index = __ BytecodeOperandReg(0);
-  Node* context = __ LoadRegister(reg_index);
-  Node* slot_index = __ BytecodeOperandIdx(1);
-  Node* result = __ LoadContextSlot(context, slot_index);
+  Node* result = BuildLoadContextSlot(assembler);
   __ SetAccumulator(result);
   __ Dispatch();
 }
 
+// LdrContextSlot <context> <slot_index> <reg>
+//
+// Load the object in <slot_index> of <context> into register <reg>.
+void Interpreter::DoLdrContextSlot(InterpreterAssembler* assembler) {
+  Node* result = BuildLoadContextSlot(assembler);
+  Node* destination = __ BytecodeOperandReg(2);
+  __ StoreRegister(result, destination);
+  __ Dispatch();
+}
+
 // StaContextSlot <context> <slot_index>
 //
 // Stores the object in the accumulator into |slot_index| of |context|.
@@ -403,8 +515,8 @@
   __ Dispatch();
 }
 
-void Interpreter::DoLoadLookupSlot(Runtime::FunctionId function_id,
-                                   InterpreterAssembler* assembler) {
+void Interpreter::DoLdaLookupSlot(Runtime::FunctionId function_id,
+                                  InterpreterAssembler* assembler) {
   Node* index = __ BytecodeOperandIdx(0);
   Node* name = __ LoadConstantPoolEntry(index);
   Node* context = __ GetContext();
@@ -418,7 +530,7 @@
 // Lookup the object with the name in constant pool entry |name_index|
 // dynamically.
 void Interpreter::DoLdaLookupSlot(InterpreterAssembler* assembler) {
-  DoLoadLookupSlot(Runtime::kLoadLookupSlot, assembler);
+  DoLdaLookupSlot(Runtime::kLoadLookupSlot, assembler);
 }
 
 // LdaLookupSlotInsideTypeof <name_index>
@@ -426,11 +538,11 @@
 // Lookup the object with the name in constant pool entry |name_index|
 // dynamically without causing a NoReferenceError.
 void Interpreter::DoLdaLookupSlotInsideTypeof(InterpreterAssembler* assembler) {
-  DoLoadLookupSlot(Runtime::kLoadLookupSlotInsideTypeof, assembler);
+  DoLdaLookupSlot(Runtime::kLoadLookupSlotInsideTypeof, assembler);
 }
 
-void Interpreter::DoStoreLookupSlot(LanguageMode language_mode,
-                                    InterpreterAssembler* assembler) {
+void Interpreter::DoStaLookupSlot(LanguageMode language_mode,
+                                  InterpreterAssembler* assembler) {
   Node* value = __ GetAccumulator();
   Node* index = __ BytecodeOperandIdx(0);
   Node* name = __ LoadConstantPoolEntry(index);
@@ -448,19 +560,19 @@
 // Store the object in accumulator to the object with the name in constant
 // pool entry |name_index| in sloppy mode.
 void Interpreter::DoStaLookupSlotSloppy(InterpreterAssembler* assembler) {
-  DoStoreLookupSlot(LanguageMode::SLOPPY, assembler);
+  DoStaLookupSlot(LanguageMode::SLOPPY, assembler);
 }
 
-
 // StaLookupSlotStrict <name_index>
 //
 // Store the object in accumulator to the object with the name in constant
 // pool entry |name_index| in strict mode.
 void Interpreter::DoStaLookupSlotStrict(InterpreterAssembler* assembler) {
-  DoStoreLookupSlot(LanguageMode::STRICT, assembler);
+  DoStaLookupSlot(LanguageMode::STRICT, assembler);
 }
 
-void Interpreter::DoLoadIC(Callable ic, InterpreterAssembler* assembler) {
+Node* Interpreter::BuildLoadNamedProperty(Callable ic,
+                                          InterpreterAssembler* assembler) {
   Node* code_target = __ HeapConstant(ic.code());
   Node* register_index = __ BytecodeOperandReg(0);
   Node* object = __ LoadRegister(register_index);
@@ -470,23 +582,35 @@
   Node* smi_slot = __ SmiTag(raw_slot);
   Node* type_feedback_vector = __ LoadTypeFeedbackVector();
   Node* context = __ GetContext();
-  Node* result = __ CallStub(ic.descriptor(), code_target, context, object,
-                             name, smi_slot, type_feedback_vector);
+  return __ CallStub(ic.descriptor(), code_target, context, object, name,
+                     smi_slot, type_feedback_vector);
+}
+
+// LdaNamedProperty <object> <name_index> <slot>
+//
+// Calls the LoadIC at FeedBackVector slot <slot> for <object> and the name at
+// constant pool entry <name_index>.
+void Interpreter::DoLdaNamedProperty(InterpreterAssembler* assembler) {
+  Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_);
+  Node* result = BuildLoadNamedProperty(ic, assembler);
   __ SetAccumulator(result);
   __ Dispatch();
 }
 
-// LoadIC <object> <name_index> <slot>
+// LdrNamedProperty <object> <name_index> <slot> <reg>
 //
 // Calls the LoadIC at FeedBackVector slot <slot> for <object> and the name at
-// constant pool entry <name_index>.
-void Interpreter::DoLoadIC(InterpreterAssembler* assembler) {
-  Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
-                                                   UNINITIALIZED);
-  DoLoadIC(ic, assembler);
+// constant pool entry <name_index> and puts the result into register <reg>.
+void Interpreter::DoLdrNamedProperty(InterpreterAssembler* assembler) {
+  Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_);
+  Node* result = BuildLoadNamedProperty(ic, assembler);
+  Node* destination = __ BytecodeOperandReg(3);
+  __ StoreRegister(result, destination);
+  __ Dispatch();
 }
 
-void Interpreter::DoKeyedLoadIC(Callable ic, InterpreterAssembler* assembler) {
+Node* Interpreter::BuildLoadKeyedProperty(Callable ic,
+                                          InterpreterAssembler* assembler) {
   Node* code_target = __ HeapConstant(ic.code());
   Node* reg_index = __ BytecodeOperandReg(0);
   Node* object = __ LoadRegister(reg_index);
@@ -495,20 +619,31 @@
   Node* smi_slot = __ SmiTag(raw_slot);
   Node* type_feedback_vector = __ LoadTypeFeedbackVector();
   Node* context = __ GetContext();
-  Node* result = __ CallStub(ic.descriptor(), code_target, context, object,
-                             name, smi_slot, type_feedback_vector);
-  __ SetAccumulator(result);
-  __ Dispatch();
+  return __ CallStub(ic.descriptor(), code_target, context, object, name,
+                     smi_slot, type_feedback_vector);
 }
 
 // KeyedLoadIC <object> <slot>
 //
 // Calls the KeyedLoadIC at FeedBackVector slot <slot> for <object> and the key
 // in the accumulator.
-void Interpreter::DoKeyedLoadIC(InterpreterAssembler* assembler) {
-  Callable ic =
-      CodeFactory::KeyedLoadICInOptimizedCode(isolate_, UNINITIALIZED);
-  DoKeyedLoadIC(ic, assembler);
+void Interpreter::DoLdaKeyedProperty(InterpreterAssembler* assembler) {
+  Callable ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate_);
+  Node* result = BuildLoadKeyedProperty(ic, assembler);
+  __ SetAccumulator(result);
+  __ Dispatch();
+}
+
+// LdrKeyedProperty <object> <slot> <reg>
+//
+// Calls the KeyedLoadIC at FeedBackVector slot <slot> for <object> and the key
+// in the accumulator and puts the result in register <reg>.
+void Interpreter::DoLdrKeyedProperty(InterpreterAssembler* assembler) {
+  Callable ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate_);
+  Node* result = BuildLoadKeyedProperty(ic, assembler);
+  Node* destination = __ BytecodeOperandReg(2);
+  __ StoreRegister(result, destination);
+  __ Dispatch();
 }
 
 void Interpreter::DoStoreIC(Callable ic, InterpreterAssembler* assembler) {
@@ -527,27 +662,23 @@
   __ Dispatch();
 }
 
-
-// StoreICSloppy <object> <name_index> <slot>
+// StaNamedPropertySloppy <object> <name_index> <slot>
 //
 // Calls the sloppy mode StoreIC at FeedBackVector slot <slot> for <object> and
 // the name in constant pool entry <name_index> with the value in the
 // accumulator.
-void Interpreter::DoStoreICSloppy(InterpreterAssembler* assembler) {
-  Callable ic =
-      CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
+void Interpreter::DoStaNamedPropertySloppy(InterpreterAssembler* assembler) {
+  Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY);
   DoStoreIC(ic, assembler);
 }
 
-
-// StoreICStrict <object> <name_index> <slot>
+// StaNamedPropertyStrict <object> <name_index> <slot>
 //
 // Calls the strict mode StoreIC at FeedBackVector slot <slot> for <object> and
 // the name in constant pool entry <name_index> with the value in the
 // accumulator.
-void Interpreter::DoStoreICStrict(InterpreterAssembler* assembler) {
-  Callable ic =
-      CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
+void Interpreter::DoStaNamedPropertyStrict(InterpreterAssembler* assembler) {
+  Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, STRICT);
   DoStoreIC(ic, assembler);
 }
 
@@ -567,25 +698,21 @@
   __ Dispatch();
 }
 
-
-// KeyedStoreICSloppy <object> <key> <slot>
+// StaKeyedPropertySloppy <object> <key> <slot>
 //
 // Calls the sloppy mode KeyStoreIC at FeedBackVector slot <slot> for <object>
 // and the key <key> with the value in the accumulator.
-void Interpreter::DoKeyedStoreICSloppy(InterpreterAssembler* assembler) {
-  Callable ic =
-      CodeFactory::KeyedStoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
+void Interpreter::DoStaKeyedPropertySloppy(InterpreterAssembler* assembler) {
+  Callable ic = CodeFactory::KeyedStoreICInOptimizedCode(isolate_, SLOPPY);
   DoKeyedStoreIC(ic, assembler);
 }
 
-
-// KeyedStoreICStore <object> <key> <slot>
+// StaKeyedPropertyStrict <object> <key> <slot>
 //
 // Calls the strict mode KeyStoreIC at FeedBackVector slot <slot> for <object>
 // and the key <key> with the value in the accumulator.
-void Interpreter::DoKeyedStoreICStrict(InterpreterAssembler* assembler) {
-  Callable ic =
-      CodeFactory::KeyedStoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
+void Interpreter::DoStaKeyedPropertyStrict(InterpreterAssembler* assembler) {
+  Callable ic = CodeFactory::KeyedStoreICInOptimizedCode(isolate_, STRICT);
   DoKeyedStoreIC(ic, assembler);
 }
 
@@ -602,7 +729,6 @@
   __ Dispatch();
 }
 
-
 // PopContext <context>
 //
 // Pops the current context and sets <context> as the new context.
@@ -613,98 +739,73 @@
   __ Dispatch();
 }
 
-void Interpreter::DoBinaryOp(Callable callable,
-                             InterpreterAssembler* assembler) {
-  // TODO(bmeurer): Collect definition side type feedback for various
-  // binary operations.
-  Node* target = __ HeapConstant(callable.code());
+template <class Generator>
+void Interpreter::DoBinaryOp(InterpreterAssembler* assembler) {
   Node* reg_index = __ BytecodeOperandReg(0);
   Node* lhs = __ LoadRegister(reg_index);
   Node* rhs = __ GetAccumulator();
   Node* context = __ GetContext();
-  Node* result = __ CallStub(callable.descriptor(), target, context, lhs, rhs);
+  Node* result = Generator::Generate(assembler, lhs, rhs, context);
   __ SetAccumulator(result);
   __ Dispatch();
 }
 
-void Interpreter::DoBinaryOp(Runtime::FunctionId function_id,
-                             InterpreterAssembler* assembler) {
-  // TODO(rmcilroy): Call ICs which back-patch bytecode with type specialized
-  // operations, instead of calling builtins directly.
-  Node* reg_index = __ BytecodeOperandReg(0);
-  Node* lhs = __ LoadRegister(reg_index);
-  Node* rhs = __ GetAccumulator();
-  Node* context = __ GetContext();
-  Node* result = __ CallRuntime(function_id, context, lhs, rhs);
-  __ SetAccumulator(result);
-  __ Dispatch();
-}
-
-
 // Add <src>
 //
 // Add register <src> to accumulator.
 void Interpreter::DoAdd(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::Add(isolate_), assembler);
+  DoBinaryOp<AddStub>(assembler);
 }
 
-
 // Sub <src>
 //
 // Subtract register <src> from accumulator.
 void Interpreter::DoSub(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::Subtract(isolate_), assembler);
+  DoBinaryOp<SubtractStub>(assembler);
 }
 
-
 // Mul <src>
 //
 // Multiply accumulator by register <src>.
 void Interpreter::DoMul(InterpreterAssembler* assembler) {
-  DoBinaryOp(Runtime::kMultiply, assembler);
+  DoBinaryOp<MultiplyStub>(assembler);
 }
 
-
 // Div <src>
 //
 // Divide register <src> by accumulator.
 void Interpreter::DoDiv(InterpreterAssembler* assembler) {
-  DoBinaryOp(Runtime::kDivide, assembler);
+  DoBinaryOp<DivideStub>(assembler);
 }
 
-
 // Mod <src>
 //
 // Modulo register <src> by accumulator.
 void Interpreter::DoMod(InterpreterAssembler* assembler) {
-  DoBinaryOp(Runtime::kModulus, assembler);
+  DoBinaryOp<ModulusStub>(assembler);
 }
 
-
 // BitwiseOr <src>
 //
 // BitwiseOr register <src> to accumulator.
 void Interpreter::DoBitwiseOr(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::BitwiseOr(isolate_), assembler);
+  DoBinaryOp<BitwiseOrStub>(assembler);
 }
 
-
 // BitwiseXor <src>
 //
 // BitwiseXor register <src> to accumulator.
 void Interpreter::DoBitwiseXor(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::BitwiseXor(isolate_), assembler);
+  DoBinaryOp<BitwiseXorStub>(assembler);
 }
 
-
 // BitwiseAnd <src>
 //
 // BitwiseAnd register <src> to accumulator.
 void Interpreter::DoBitwiseAnd(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::BitwiseAnd(isolate_), assembler);
+  DoBinaryOp<BitwiseAndStub>(assembler);
 }
 
-
 // ShiftLeft <src>
 //
 // Left shifts register <src> by the count specified in the accumulator.
@@ -712,10 +813,9 @@
 // before the operation. 5 lsb bits from the accumulator are used as count
 // i.e. <src> << (accumulator & 0x1F).
 void Interpreter::DoShiftLeft(InterpreterAssembler* assembler) {
-  DoBinaryOp(Runtime::kShiftLeft, assembler);
+  DoBinaryOp<ShiftLeftStub>(assembler);
 }
 
-
 // ShiftRight <src>
 //
 // Right shifts register <src> by the count specified in the accumulator.
@@ -723,10 +823,9 @@
 // accumulator to uint32 before the operation. 5 lsb bits from the accumulator
 // are used as count i.e. <src> >> (accumulator & 0x1F).
 void Interpreter::DoShiftRight(InterpreterAssembler* assembler) {
-  DoBinaryOp(Runtime::kShiftRight, assembler);
+  DoBinaryOp<ShiftRightStub>(assembler);
 }
 
-
 // ShiftRightLogical <src>
 //
 // Right Shifts register <src> by the count specified in the accumulator.
@@ -734,70 +833,11 @@
 // uint32 before the operation 5 lsb bits from the accumulator are used as
 // count i.e. <src> << (accumulator & 0x1F).
 void Interpreter::DoShiftRightLogical(InterpreterAssembler* assembler) {
-  DoBinaryOp(Runtime::kShiftRightLogical, assembler);
+  DoBinaryOp<ShiftRightLogicalStub>(assembler);
 }
 
-void Interpreter::DoCountOp(Runtime::FunctionId function_id,
+void Interpreter::DoUnaryOp(Callable callable,
                             InterpreterAssembler* assembler) {
-  Node* value = __ GetAccumulator();
-  Node* one = __ NumberConstant(1);
-  Node* context = __ GetContext();
-  Node* result = __ CallRuntime(function_id, context, value, one);
-  __ SetAccumulator(result);
-  __ Dispatch();
-}
-
-
-// Inc
-//
-// Increments value in the accumulator by one.
-void Interpreter::DoInc(InterpreterAssembler* assembler) {
-  DoCountOp(Runtime::kAdd, assembler);
-}
-
-
-// Dec
-//
-// Decrements value in the accumulator by one.
-void Interpreter::DoDec(InterpreterAssembler* assembler) {
-  DoCountOp(Runtime::kSubtract, assembler);
-}
-
-
-// LogicalNot
-//
-// Perform logical-not on the accumulator, first casting the
-// accumulator to a boolean value if required.
-void Interpreter::DoLogicalNot(InterpreterAssembler* assembler) {
-  Callable callable = CodeFactory::ToBoolean(isolate_);
-  Node* target = __ HeapConstant(callable.code());
-  Node* accumulator = __ GetAccumulator();
-  Node* context = __ GetContext();
-  Node* to_boolean_value =
-      __ CallStub(callable.descriptor(), target, context, accumulator);
-  InterpreterAssembler::Label if_true(assembler), if_false(assembler);
-  Node* true_value = __ BooleanConstant(true);
-  Node* false_value = __ BooleanConstant(false);
-  Node* condition = __ WordEqual(to_boolean_value, true_value);
-  __ Branch(condition, &if_true, &if_false);
-  __ Bind(&if_true);
-  {
-    __ SetAccumulator(false_value);
-    __ Dispatch();
-  }
-  __ Bind(&if_false);
-  {
-    __ SetAccumulator(true_value);
-    __ Dispatch();
-  }
-}
-
-// TypeOf
-//
-// Load the accumulator with the string representating type of the
-// object in the accumulator.
-void Interpreter::DoTypeOf(InterpreterAssembler* assembler) {
-  Callable callable = CodeFactory::Typeof(isolate_);
   Node* target = __ HeapConstant(callable.code());
   Node* accumulator = __ GetAccumulator();
   Node* context = __ GetContext();
@@ -807,6 +847,113 @@
   __ Dispatch();
 }
 
+template <class Generator>
+void Interpreter::DoUnaryOp(InterpreterAssembler* assembler) {
+  Node* value = __ GetAccumulator();
+  Node* context = __ GetContext();
+  Node* result = Generator::Generate(assembler, value, context);
+  __ SetAccumulator(result);
+  __ Dispatch();
+}
+
+// ToName
+//
+// Cast the object referenced by the accumulator to a name.
+void Interpreter::DoToName(InterpreterAssembler* assembler) {
+  DoUnaryOp(CodeFactory::ToName(isolate_), assembler);
+}
+
+// ToNumber
+//
+// Cast the object referenced by the accumulator to a number.
+void Interpreter::DoToNumber(InterpreterAssembler* assembler) {
+  DoUnaryOp(CodeFactory::ToNumber(isolate_), assembler);
+}
+
+// ToObject
+//
+// Cast the object referenced by the accumulator to a JSObject.
+void Interpreter::DoToObject(InterpreterAssembler* assembler) {
+  DoUnaryOp(CodeFactory::ToObject(isolate_), assembler);
+}
+
+// Inc
+//
+// Increments value in the accumulator by one.
+void Interpreter::DoInc(InterpreterAssembler* assembler) {
+  DoUnaryOp<IncStub>(assembler);
+}
+
+// Dec
+//
+// Decrements value in the accumulator by one.
+void Interpreter::DoDec(InterpreterAssembler* assembler) {
+  DoUnaryOp<DecStub>(assembler);
+}
+
+Node* Interpreter::BuildToBoolean(Node* value,
+                                  InterpreterAssembler* assembler) {
+  Node* context = __ GetContext();
+  return ToBooleanStub::Generate(assembler, value, context);
+}
+
+Node* Interpreter::BuildLogicalNot(Node* value,
+                                   InterpreterAssembler* assembler) {
+  Variable result(assembler, MachineRepresentation::kTagged);
+  Label if_true(assembler), if_false(assembler), end(assembler);
+  Node* true_value = __ BooleanConstant(true);
+  Node* false_value = __ BooleanConstant(false);
+  __ BranchIfWordEqual(value, true_value, &if_true, &if_false);
+  __ Bind(&if_true);
+  {
+    result.Bind(false_value);
+    __ Goto(&end);
+  }
+  __ Bind(&if_false);
+  {
+    if (FLAG_debug_code) {
+      __ AbortIfWordNotEqual(value, false_value,
+                             BailoutReason::kExpectedBooleanValue);
+    }
+    result.Bind(true_value);
+    __ Goto(&end);
+  }
+  __ Bind(&end);
+  return result.value();
+}
+
+// LogicalNot
+//
+// Perform logical-not on the accumulator, first casting the
+// accumulator to a boolean value if required.
+// ToBooleanLogicalNot
+void Interpreter::DoToBooleanLogicalNot(InterpreterAssembler* assembler) {
+  Node* value = __ GetAccumulator();
+  Node* to_boolean_value = BuildToBoolean(value, assembler);
+  Node* result = BuildLogicalNot(to_boolean_value, assembler);
+  __ SetAccumulator(result);
+  __ Dispatch();
+}
+
+// LogicalNot
+//
+// Perform logical-not on the accumulator, which must already be a boolean
+// value.
+void Interpreter::DoLogicalNot(InterpreterAssembler* assembler) {
+  Node* value = __ GetAccumulator();
+  Node* result = BuildLogicalNot(value, assembler);
+  __ SetAccumulator(result);
+  __ Dispatch();
+}
+
+// TypeOf
+//
+// Load the accumulator with the string representating type of the
+// object in the accumulator.
+void Interpreter::DoTypeOf(InterpreterAssembler* assembler) {
+  DoUnaryOp(CodeFactory::Typeof(isolate_), assembler);
+}
+
 void Interpreter::DoDelete(Runtime::FunctionId function_id,
                            InterpreterAssembler* assembler) {
   Node* reg_index = __ BytecodeOperandReg(0);
@@ -818,7 +965,6 @@
   __ Dispatch();
 }
 
-
 // DeletePropertyStrict
 //
 // Delete the property specified in the accumulator from the object
@@ -827,7 +973,6 @@
   DoDelete(Runtime::kDeleteProperty_Strict, assembler);
 }
 
-
 // DeletePropertySloppy
 //
 // Delete the property specified in the accumulator from the object
@@ -853,7 +998,6 @@
   __ Dispatch();
 }
 
-
 // Call <callable> <receiver> <arg_count>
 //
 // Call a JSfunction or Callable in |callable| with the |receiver| and
@@ -881,7 +1025,6 @@
   __ Dispatch();
 }
 
-
 // CallRuntime <function_id> <first_arg> <arg_count>
 //
 // Call the runtime function |function_id| with the first argument in
@@ -897,7 +1040,7 @@
 // |function_id| with the first argument in |first_arg| and |arg_count|
 // arguments in subsequent registers.
 void Interpreter::DoInvokeIntrinsic(InterpreterAssembler* assembler) {
-  Node* function_id = __ BytecodeOperandRuntimeId(0);
+  Node* function_id = __ BytecodeOperandIntrinsicId(0);
   Node* first_arg_reg = __ BytecodeOperandReg(1);
   Node* arg_count = __ BytecodeOperandCount(2);
   Node* context = __ GetContext();
@@ -928,7 +1071,6 @@
   __ Dispatch();
 }
 
-
 // CallRuntimeForPair <function_id> <first_arg> <arg_count> <first_return>
 //
 // Call the runtime function |function_id| which returns a pair, with the
@@ -960,7 +1102,6 @@
   __ Dispatch();
 }
 
-
 // CallJSRuntime <context_index> <receiver> <arg_count>
 //
 // Call the JS runtime function that has the |context_index| with the receiver
@@ -984,7 +1125,6 @@
   __ Dispatch();
 }
 
-
 // New <constructor> <first_arg> <arg_count>
 //
 // Call operator new with |constructor| and the first argument in
@@ -999,109 +1139,67 @@
 //
 // Test if the value in the <src> register equals the accumulator.
 void Interpreter::DoTestEqual(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::Equal(isolate_), assembler);
+  DoBinaryOp<EqualStub>(assembler);
 }
 
-
 // TestNotEqual <src>
 //
 // Test if the value in the <src> register is not equal to the accumulator.
 void Interpreter::DoTestNotEqual(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::NotEqual(isolate_), assembler);
+  DoBinaryOp<NotEqualStub>(assembler);
 }
 
-
 // TestEqualStrict <src>
 //
 // Test if the value in the <src> register is strictly equal to the accumulator.
 void Interpreter::DoTestEqualStrict(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::StrictEqual(isolate_), assembler);
+  DoBinaryOp<StrictEqualStub>(assembler);
 }
 
-
 // TestLessThan <src>
 //
 // Test if the value in the <src> register is less than the accumulator.
 void Interpreter::DoTestLessThan(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::LessThan(isolate_), assembler);
+  DoBinaryOp<LessThanStub>(assembler);
 }
 
-
 // TestGreaterThan <src>
 //
 // Test if the value in the <src> register is greater than the accumulator.
 void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::GreaterThan(isolate_), assembler);
+  DoBinaryOp<GreaterThanStub>(assembler);
 }
 
-
 // TestLessThanOrEqual <src>
 //
 // Test if the value in the <src> register is less than or equal to the
 // accumulator.
 void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::LessThanOrEqual(isolate_), assembler);
+  DoBinaryOp<LessThanOrEqualStub>(assembler);
 }
 
-
 // TestGreaterThanOrEqual <src>
 //
 // Test if the value in the <src> register is greater than or equal to the
 // accumulator.
 void Interpreter::DoTestGreaterThanOrEqual(InterpreterAssembler* assembler) {
-  DoBinaryOp(CodeFactory::GreaterThanOrEqual(isolate_), assembler);
+  DoBinaryOp<GreaterThanOrEqualStub>(assembler);
 }
 
-
 // TestIn <src>
 //
 // Test if the object referenced by the register operand is a property of the
 // object referenced by the accumulator.
 void Interpreter::DoTestIn(InterpreterAssembler* assembler) {
-  DoBinaryOp(Runtime::kHasProperty, assembler);
+  DoBinaryOp<HasPropertyStub>(assembler);
 }
 
-
 // TestInstanceOf <src>
 //
 // Test if the object referenced by the <src> register is an an instance of type
 // referenced by the accumulator.
 void Interpreter::DoTestInstanceOf(InterpreterAssembler* assembler) {
-  DoBinaryOp(Runtime::kInstanceOf, assembler);
-}
-
-void Interpreter::DoTypeConversionOp(Callable callable,
-                                     InterpreterAssembler* assembler) {
-  Node* target = __ HeapConstant(callable.code());
-  Node* accumulator = __ GetAccumulator();
-  Node* context = __ GetContext();
-  Node* result =
-      __ CallStub(callable.descriptor(), target, context, accumulator);
-  __ SetAccumulator(result);
-  __ Dispatch();
-}
-
-// ToName
-//
-// Cast the object referenced by the accumulator to a name.
-void Interpreter::DoToName(InterpreterAssembler* assembler) {
-  DoTypeConversionOp(CodeFactory::ToName(isolate_), assembler);
-}
-
-
-// ToNumber
-//
-// Cast the object referenced by the accumulator to a number.
-void Interpreter::DoToNumber(InterpreterAssembler* assembler) {
-  DoTypeConversionOp(CodeFactory::ToNumber(isolate_), assembler);
-}
-
-
-// ToObject
-//
-// Cast the object referenced by the accumulator to a JSObject.
-void Interpreter::DoToObject(InterpreterAssembler* assembler) {
-  DoTypeConversionOp(CodeFactory::ToObject(isolate_), assembler);
+  DoBinaryOp<InstanceOfStub>(assembler);
 }
 
 // Jump <imm>
@@ -1175,12 +1273,8 @@
 // Jump by number of bytes represented by an immediate operand if the object
 // referenced by the accumulator is true when the object is cast to boolean.
 void Interpreter::DoJumpIfToBooleanTrue(InterpreterAssembler* assembler) {
-  Callable callable = CodeFactory::ToBoolean(isolate_);
-  Node* target = __ HeapConstant(callable.code());
   Node* accumulator = __ GetAccumulator();
-  Node* context = __ GetContext();
-  Node* to_boolean_value =
-      __ CallStub(callable.descriptor(), target, context, accumulator);
+  Node* to_boolean_value = BuildToBoolean(accumulator, assembler);
   Node* relative_jump = __ BytecodeOperandImm(0);
   Node* true_value = __ BooleanConstant(true);
   __ JumpIfWordEqual(to_boolean_value, true_value, relative_jump);
@@ -1193,12 +1287,8 @@
 // to boolean.
 void Interpreter::DoJumpIfToBooleanTrueConstant(
     InterpreterAssembler* assembler) {
-  Callable callable = CodeFactory::ToBoolean(isolate_);
-  Node* target = __ HeapConstant(callable.code());
   Node* accumulator = __ GetAccumulator();
-  Node* context = __ GetContext();
-  Node* to_boolean_value =
-      __ CallStub(callable.descriptor(), target, context, accumulator);
+  Node* to_boolean_value = BuildToBoolean(accumulator, assembler);
   Node* index = __ BytecodeOperandIdx(0);
   Node* constant = __ LoadConstantPoolEntry(index);
   Node* relative_jump = __ SmiUntag(constant);
@@ -1211,12 +1301,8 @@
 // Jump by number of bytes represented by an immediate operand if the object
 // referenced by the accumulator is false when the object is cast to boolean.
 void Interpreter::DoJumpIfToBooleanFalse(InterpreterAssembler* assembler) {
-  Callable callable = CodeFactory::ToBoolean(isolate_);
-  Node* target = __ HeapConstant(callable.code());
   Node* accumulator = __ GetAccumulator();
-  Node* context = __ GetContext();
-  Node* to_boolean_value =
-      __ CallStub(callable.descriptor(), target, context, accumulator);
+  Node* to_boolean_value = BuildToBoolean(accumulator, assembler);
   Node* relative_jump = __ BytecodeOperandImm(0);
   Node* false_value = __ BooleanConstant(false);
   __ JumpIfWordEqual(to_boolean_value, false_value, relative_jump);
@@ -1229,12 +1315,8 @@
 // to boolean.
 void Interpreter::DoJumpIfToBooleanFalseConstant(
     InterpreterAssembler* assembler) {
-  Callable callable = CodeFactory::ToBoolean(isolate_);
-  Node* target = __ HeapConstant(callable.code());
   Node* accumulator = __ GetAccumulator();
-  Node* context = __ GetContext();
-  Node* to_boolean_value =
-      __ CallStub(callable.descriptor(), target, context, accumulator);
+  Node* to_boolean_value = BuildToBoolean(accumulator, assembler);
   Node* index = __ BytecodeOperandIdx(0);
   Node* constant = __ LoadConstantPoolEntry(index);
   Node* relative_jump = __ SmiUntag(constant);
@@ -1316,23 +1398,6 @@
   __ JumpIfWordNotEqual(accumulator, the_hole_value, relative_jump);
 }
 
-void Interpreter::DoCreateLiteral(Runtime::FunctionId function_id,
-                                  InterpreterAssembler* assembler) {
-  Node* index = __ BytecodeOperandIdx(0);
-  Node* constant_elements = __ LoadConstantPoolEntry(index);
-  Node* literal_index_raw = __ BytecodeOperandIdx(1);
-  Node* literal_index = __ SmiTag(literal_index_raw);
-  Node* flags_raw = __ BytecodeOperandFlag(2);
-  Node* flags = __ SmiTag(flags_raw);
-  Node* closure = __ LoadRegister(Register::function_closure());
-  Node* context = __ GetContext();
-  Node* result = __ CallRuntime(function_id, context, closure, literal_index,
-                                constant_elements, flags);
-  __ SetAccumulator(result);
-  __ Dispatch();
-}
-
-
 // CreateRegExpLiteral <pattern_idx> <literal_idx> <flags>
 //
 // Creates a regular expression literal for literal index <literal_idx> with
@@ -1359,15 +1424,67 @@
 // Creates an array literal for literal index <literal_idx> with flags <flags>
 // and constant elements in <element_idx>.
 void Interpreter::DoCreateArrayLiteral(InterpreterAssembler* assembler) {
-  DoCreateLiteral(Runtime::kCreateArrayLiteral, assembler);
+  Node* index = __ BytecodeOperandIdx(0);
+  Node* constant_elements = __ LoadConstantPoolEntry(index);
+  Node* literal_index_raw = __ BytecodeOperandIdx(1);
+  Node* literal_index = __ SmiTag(literal_index_raw);
+  Node* flags_raw = __ BytecodeOperandFlag(2);
+  Node* flags = __ SmiTag(flags_raw);
+  Node* closure = __ LoadRegister(Register::function_closure());
+  Node* context = __ GetContext();
+  Node* result = __ CallRuntime(Runtime::kCreateArrayLiteral, context, closure,
+                                literal_index, constant_elements, flags);
+  __ SetAccumulator(result);
+  __ Dispatch();
 }
 
 // CreateObjectLiteral <element_idx> <literal_idx> <flags>
 //
-// Creates an object literal for literal index <literal_idx> with flags <flags>
-// and constant elements in <element_idx>.
+// Creates an object literal for literal index <literal_idx> with
+// CreateObjectLiteralFlags <flags> and constant elements in <element_idx>.
 void Interpreter::DoCreateObjectLiteral(InterpreterAssembler* assembler) {
-  DoCreateLiteral(Runtime::kCreateObjectLiteral, assembler);
+  Node* literal_index_raw = __ BytecodeOperandIdx(1);
+  Node* literal_index = __ SmiTag(literal_index_raw);
+  Node* bytecode_flags = __ BytecodeOperandFlag(2);
+  Node* closure = __ LoadRegister(Register::function_closure());
+
+  // Check if we can do a fast clone or have to call the runtime.
+  Label if_fast_clone(assembler),
+      if_not_fast_clone(assembler, Label::kDeferred);
+  Node* fast_clone_properties_count =
+      __ BitFieldDecode<CreateObjectLiteralFlags::FastClonePropertiesCountBits>(
+          bytecode_flags);
+  __ BranchIf(fast_clone_properties_count, &if_fast_clone, &if_not_fast_clone);
+
+  __ Bind(&if_fast_clone);
+  {
+    // If we can do a fast clone do the fast-path in FastCloneShallowObjectStub.
+    Node* result = FastCloneShallowObjectStub::GenerateFastPath(
+        assembler, &if_not_fast_clone, closure, literal_index,
+        fast_clone_properties_count);
+    __ SetAccumulator(result);
+    __ Dispatch();
+  }
+
+  __ Bind(&if_not_fast_clone);
+  {
+    // If we can't do a fast clone, call into the runtime.
+    Node* index = __ BytecodeOperandIdx(0);
+    Node* constant_elements = __ LoadConstantPoolEntry(index);
+    Node* context = __ GetContext();
+
+    STATIC_ASSERT(CreateObjectLiteralFlags::FlagsBits::kShift == 0);
+    Node* flags_raw = __ Word32And(
+        bytecode_flags,
+        __ Int32Constant(CreateObjectLiteralFlags::FlagsBits::kMask));
+    Node* flags = __ SmiTag(flags_raw);
+
+    Node* result =
+        __ CallRuntime(Runtime::kCreateObjectLiteral, context, closure,
+                       literal_index, constant_elements, flags);
+    __ SetAccumulator(result);
+    __ Dispatch();
+  }
 }
 
 // CreateClosure <index> <tenured>
@@ -1394,18 +1511,48 @@
 void Interpreter::DoCreateMappedArguments(InterpreterAssembler* assembler) {
   Node* closure = __ LoadRegister(Register::function_closure());
   Node* context = __ GetContext();
-  Node* result =
-      __ CallRuntime(Runtime::kNewSloppyArguments_Generic, context, closure);
-  __ SetAccumulator(result);
-  __ Dispatch();
-}
 
+  Label if_duplicate_parameters(assembler, Label::kDeferred);
+  Label if_not_duplicate_parameters(assembler);
+
+  // Check if function has duplicate parameters.
+  // TODO(rmcilroy): Remove this check when FastNewSloppyArgumentsStub supports
+  // duplicate parameters.
+  Node* shared_info =
+      __ LoadObjectField(closure, JSFunction::kSharedFunctionInfoOffset);
+  Node* compiler_hints = __ LoadObjectField(
+      shared_info, SharedFunctionInfo::kHasDuplicateParametersByteOffset,
+      MachineType::Uint8());
+  Node* duplicate_parameters_bit = __ Int32Constant(
+      1 << SharedFunctionInfo::kHasDuplicateParametersBitWithinByte);
+  Node* compare = __ Word32And(compiler_hints, duplicate_parameters_bit);
+  __ BranchIf(compare, &if_duplicate_parameters, &if_not_duplicate_parameters);
+
+  __ Bind(&if_not_duplicate_parameters);
+  {
+    // TODO(rmcilroy): Inline FastNewSloppyArguments when it is a TurboFan stub.
+    Callable callable = CodeFactory::FastNewSloppyArguments(isolate_, true);
+    Node* target = __ HeapConstant(callable.code());
+    Node* result = __ CallStub(callable.descriptor(), target, context, closure);
+    __ SetAccumulator(result);
+    __ Dispatch();
+  }
+
+  __ Bind(&if_duplicate_parameters);
+  {
+    Node* result =
+        __ CallRuntime(Runtime::kNewSloppyArguments_Generic, context, closure);
+    __ SetAccumulator(result);
+    __ Dispatch();
+  }
+}
 
 // CreateUnmappedArguments
 //
 // Creates a new unmapped arguments object.
 void Interpreter::DoCreateUnmappedArguments(InterpreterAssembler* assembler) {
-  Callable callable = CodeFactory::FastNewStrictArguments(isolate_);
+  // TODO(rmcilroy): Inline FastNewStrictArguments when it is a TurboFan stub.
+  Callable callable = CodeFactory::FastNewStrictArguments(isolate_, true);
   Node* target = __ HeapConstant(callable.code());
   Node* context = __ GetContext();
   Node* closure = __ LoadRegister(Register::function_closure());
@@ -1418,7 +1565,8 @@
 //
 // Creates a new rest parameter array.
 void Interpreter::DoCreateRestParameter(InterpreterAssembler* assembler) {
-  Callable callable = CodeFactory::FastNewRestParameter(isolate_);
+  // TODO(rmcilroy): Inline FastNewRestArguments when it is a TurboFan stub.
+  Callable callable = CodeFactory::FastNewRestParameter(isolate_, true);
   Node* target = __ HeapConstant(callable.code());
   Node* closure = __ LoadRegister(Register::function_closure());
   Node* context = __ GetContext();
@@ -1431,8 +1579,20 @@
 //
 // Performs a stack guard check.
 void Interpreter::DoStackCheck(InterpreterAssembler* assembler) {
-  __ StackCheck();
+  Label ok(assembler), stack_check_interrupt(assembler, Label::kDeferred);
+
+  Node* interrupt = __ StackCheckTriggeredInterrupt();
+  __ BranchIf(interrupt, &stack_check_interrupt, &ok);
+
+  __ Bind(&ok);
   __ Dispatch();
+
+  __ Bind(&stack_check_interrupt);
+  {
+    Node* context = __ GetContext();
+    __ CallRuntime(Runtime::kStackGuard, context);
+    __ Dispatch();
+  }
 }
 
 // Throw
@@ -1446,7 +1606,6 @@
   __ Abort(kUnexpectedReturnFromThrow);
 }
 
-
 // ReThrow
 //
 // Re-throws the exception in the accumulator.
@@ -1458,12 +1617,13 @@
   __ Abort(kUnexpectedReturnFromThrow);
 }
 
-
 // Return
 //
 // Return the value in the accumulator.
 void Interpreter::DoReturn(InterpreterAssembler* assembler) {
-  __ InterpreterReturn();
+  __ UpdateInterruptBudgetOnReturn();
+  Node* accumulator = __ GetAccumulator();
+  __ Return(accumulator);
 }
 
 // Debugger
@@ -1525,13 +1685,14 @@
   Node* cache_array = __ LoadRegister(cache_array_reg);
 
   // Load the next key from the enumeration array.
-  Node* key = __ LoadFixedArrayElementSmiIndex(cache_array, index);
+  Node* key = __ LoadFixedArrayElement(cache_array, index, 0,
+                                       CodeStubAssembler::SMI_PARAMETERS);
 
   // Check if we can use the for-in fast path potentially using the enum cache.
-  InterpreterAssembler::Label if_fast(assembler), if_slow(assembler);
+  Label if_fast(assembler), if_slow(assembler, Label::kDeferred);
   Node* receiver_map = __ LoadObjectField(receiver, HeapObject::kMapOffset);
   Node* condition = __ WordEqual(receiver_map, cache_type);
-  __ Branch(condition, &if_fast, &if_slow);
+  __ BranchIf(condition, &if_fast, &if_slow);
   __ Bind(&if_fast);
   {
     // Enum cache in use for {receiver}, the {key} is definitely valid.
@@ -1545,8 +1706,8 @@
     Node* type_feedback_vector = __ LoadTypeFeedbackVector();
     Node* megamorphic_sentinel =
         __ HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate_));
-    __ StoreFixedArrayElementNoWriteBarrier(type_feedback_vector, vector_index,
-                                            megamorphic_sentinel);
+    __ StoreFixedArrayElement(type_feedback_vector, vector_index,
+                              megamorphic_sentinel, SKIP_WRITE_BARRIER);
 
     // Need to filter the {key} for the {receiver}.
     Node* context = __ GetContext();
@@ -1567,21 +1728,20 @@
   Node* cache_length = __ LoadRegister(cache_length_reg);
 
   // Check if {index} is at {cache_length} already.
-  InterpreterAssembler::Label if_true(assembler), if_false(assembler);
-  Node* condition = __ WordEqual(index, cache_length);
-  __ Branch(condition, &if_true, &if_false);
+  Label if_true(assembler), if_false(assembler), end(assembler);
+  __ BranchIfWordEqual(index, cache_length, &if_true, &if_false);
   __ Bind(&if_true);
   {
-    Node* result = __ BooleanConstant(true);
-    __ SetAccumulator(result);
-    __ Dispatch();
+    __ SetAccumulator(__ BooleanConstant(true));
+    __ Goto(&end);
   }
   __ Bind(&if_false);
   {
-    Node* result = __ BooleanConstant(false);
-    __ SetAccumulator(result);
-    __ Dispatch();
+    __ SetAccumulator(__ BooleanConstant(false));
+    __ Goto(&end);
   }
+  __ Bind(&end);
+  __ Dispatch();
 }
 
 // ForInStep <index>
@@ -1618,6 +1778,76 @@
   __ Abort(kInvalidBytecode);
 }
 
+// Nop
+//
+// No operation.
+void Interpreter::DoNop(InterpreterAssembler* assembler) { __ Dispatch(); }
+
+// SuspendGenerator <generator>
+//
+// Exports the register file and stores it into the generator.  Also stores the
+// current context, the state given in the accumulator, and the current bytecode
+// offset (for debugging purposes) into the generator.
+void Interpreter::DoSuspendGenerator(InterpreterAssembler* assembler) {
+  Node* generator_reg = __ BytecodeOperandReg(0);
+  Node* generator = __ LoadRegister(generator_reg);
+
+  Label if_stepping(assembler, Label::kDeferred), ok(assembler);
+  Node* step_action_address = __ ExternalConstant(
+      ExternalReference::debug_last_step_action_address(isolate_));
+  Node* step_action = __ Load(MachineType::Int8(), step_action_address);
+  STATIC_ASSERT(StepIn > StepNext);
+  STATIC_ASSERT(StepFrame > StepNext);
+  STATIC_ASSERT(LastStepAction == StepFrame);
+  Node* step_next = __ Int32Constant(StepNext);
+  __ BranchIfInt32LessThanOrEqual(step_next, step_action, &if_stepping, &ok);
+  __ Bind(&ok);
+
+  Node* array =
+      __ LoadObjectField(generator, JSGeneratorObject::kOperandStackOffset);
+  Node* context = __ GetContext();
+  Node* state = __ GetAccumulator();
+
+  __ ExportRegisterFile(array);
+  __ StoreObjectField(generator, JSGeneratorObject::kContextOffset, context);
+  __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, state);
+
+  Node* offset = __ SmiTag(__ BytecodeOffset());
+  __ StoreObjectField(generator, JSGeneratorObject::kInputOrDebugPosOffset,
+                      offset);
+
+  __ Dispatch();
+
+  __ Bind(&if_stepping);
+  {
+    Node* context = __ GetContext();
+    __ CallRuntime(Runtime::kDebugRecordAsyncFunction, context, generator);
+    __ Goto(&ok);
+  }
+}
+
+// ResumeGenerator <generator>
+//
+// Imports the register file stored in the generator. Also loads the
+// generator's state and stores it in the accumulator, before overwriting it
+// with kGeneratorExecuting.
+void Interpreter::DoResumeGenerator(InterpreterAssembler* assembler) {
+  Node* generator_reg = __ BytecodeOperandReg(0);
+  Node* generator = __ LoadRegister(generator_reg);
+
+  __ ImportRegisterFile(
+      __ LoadObjectField(generator, JSGeneratorObject::kOperandStackOffset));
+
+  Node* old_state =
+      __ LoadObjectField(generator, JSGeneratorObject::kContinuationOffset);
+  Node* new_state = __ Int32Constant(JSGeneratorObject::kGeneratorExecuting);
+  __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset,
+      __ SmiTag(new_state));
+  __ SetAccumulator(old_state);
+
+  __ Dispatch();
+}
+
 }  // namespace interpreter
 }  // namespace internal
 }  // namespace v8
diff --git a/src/interpreter/interpreter.h b/src/interpreter/interpreter.h
index ea50faa..468486c 100644
--- a/src/interpreter/interpreter.h
+++ b/src/interpreter/interpreter.h
@@ -21,6 +21,10 @@
 class Callable;
 class CompilationInfo;
 
+namespace compiler {
+class Node;
+}  // namespace compiler
+
 namespace interpreter {
 
 class InterpreterAssembler;
@@ -49,10 +53,16 @@
   void TraceCodegen(Handle<Code> code);
   const char* LookupNameOfBytecodeHandler(Code* code);
 
+  Local<v8::Object> GetDispatchCountersObject();
+
   Address dispatch_table_address() {
     return reinterpret_cast<Address>(&dispatch_table_[0]);
   }
 
+  Address bytecode_dispatch_counters_table() {
+    return reinterpret_cast<Address>(bytecode_dispatch_counters_table_.get());
+  }
+
  private:
 // Bytecode handler generator functions.
 #define DECLARE_BYTECODE_HANDLER_GENERATOR(Name, ...) \
@@ -60,37 +70,25 @@
   BYTECODE_LIST(DECLARE_BYTECODE_HANDLER_GENERATOR)
 #undef DECLARE_BYTECODE_HANDLER_GENERATOR
 
-  // Generates code to perform the binary operations via |callable|.
-  void DoBinaryOp(Callable callable, InterpreterAssembler* assembler);
+  // Generates code to perform the binary operation via |Generator|.
+  template <class Generator>
+  void DoBinaryOp(InterpreterAssembler* assembler);
 
-  // Generates code to perform the binary operations via |function_id|.
-  void DoBinaryOp(Runtime::FunctionId function_id,
-                  InterpreterAssembler* assembler);
+  // Generates code to perform the unary operation via |callable|.
+  void DoUnaryOp(Callable callable, InterpreterAssembler* assembler);
 
-  // Generates code to perform the count operations via |function_id|.
-  void DoCountOp(Runtime::FunctionId function_id,
-                 InterpreterAssembler* assembler);
+  // Generates code to perform the unary operation via |Generator|.
+  template <class Generator>
+  void DoUnaryOp(InterpreterAssembler* assembler);
 
   // Generates code to perform the comparison operation associated with
   // |compare_op|.
   void DoCompareOp(Token::Value compare_op, InterpreterAssembler* assembler);
 
-  // Generates code to load a constant from the constant pool.
-  void DoLoadConstant(InterpreterAssembler* assembler);
-
-  // Generates code to perform a global load via |ic|.
-  void DoLoadGlobal(Callable ic, InterpreterAssembler* assembler);
-
   // Generates code to perform a global store via |ic|.
-  void DoStoreGlobal(Callable ic, InterpreterAssembler* assembler);
+  void DoStaGlobal(Callable ic, InterpreterAssembler* assembler);
 
-  // Generates code to perform a named property load via |ic|.
-  void DoLoadIC(Callable ic, InterpreterAssembler* assembler);
-
-  // Generates code to perform a keyed property load via |ic|.
-  void DoKeyedLoadIC(Callable ic, InterpreterAssembler* assembler);
-
-  // Generates code to perform a namedproperty store via |ic|.
+  // Generates code to perform a named property store via |ic|.
   void DoStoreIC(Callable ic, InterpreterAssembler* assembler);
 
   // Generates code to perform a keyed property store via |ic|.
@@ -111,24 +109,46 @@
   // Generates code to perform a constructor call.
   void DoCallConstruct(InterpreterAssembler* assembler);
 
-  // Generates code to perform a type conversion.
-  void DoTypeConversionOp(Callable callable, InterpreterAssembler* assembler);
-
-  // Generates code ro create a literal via |function_id|.
-  void DoCreateLiteral(Runtime::FunctionId function_id,
-                       InterpreterAssembler* assembler);
-
   // Generates code to perform delete via function_id.
   void DoDelete(Runtime::FunctionId function_id,
                 InterpreterAssembler* assembler);
 
   // Generates code to perform a lookup slot load via |function_id|.
-  void DoLoadLookupSlot(Runtime::FunctionId function_id,
-                        InterpreterAssembler* assembler);
+  void DoLdaLookupSlot(Runtime::FunctionId function_id,
+                       InterpreterAssembler* assembler);
 
   // Generates code to perform a lookup slot store depending on |language_mode|.
-  void DoStoreLookupSlot(LanguageMode language_mode,
-                         InterpreterAssembler* assembler);
+  void DoStaLookupSlot(LanguageMode language_mode,
+                       InterpreterAssembler* assembler);
+
+  // Generates a node with the undefined constant.
+  compiler::Node* BuildLoadUndefined(InterpreterAssembler* assembler);
+
+  // Generates code to load a context slot.
+  compiler::Node* BuildLoadContextSlot(InterpreterAssembler* assembler);
+
+  // Generates code to load a global.
+  compiler::Node* BuildLoadGlobal(Callable ic, InterpreterAssembler* assembler);
+
+  // Generates code to load a named property.
+  compiler::Node* BuildLoadNamedProperty(Callable ic,
+                                         InterpreterAssembler* assembler);
+
+  // Generates code to load a keyed property.
+  compiler::Node* BuildLoadKeyedProperty(Callable ic,
+                                         InterpreterAssembler* assembler);
+
+  // Generates code to perform logical-not on boolean |value| and returns the
+  // result.
+  compiler::Node* BuildLogicalNot(compiler::Node* value,
+                                  InterpreterAssembler* assembler);
+
+  // Generates code to convert |value| to a boolean and returns the
+  // result.
+  compiler::Node* BuildToBoolean(compiler::Node* value,
+                                 InterpreterAssembler* assembler);
+
+  uintptr_t GetDispatchCounter(Bytecode from, Bytecode to) const;
 
   // Get dispatch table index of bytecode.
   static size_t GetDispatchTableIndex(Bytecode bytecode,
@@ -138,9 +158,11 @@
 
   static const int kNumberOfWideVariants = 3;
   static const int kDispatchTableSize = kNumberOfWideVariants * (kMaxUInt8 + 1);
+  static const int kNumberOfBytecodes = static_cast<int>(Bytecode::kLast) + 1;
 
   Isolate* isolate_;
-  Code* dispatch_table_[kDispatchTableSize];
+  Address dispatch_table_[kDispatchTableSize];
+  v8::base::SmartArrayPointer<uintptr_t> bytecode_dispatch_counters_table_;
 
   DISALLOW_COPY_AND_ASSIGN(Interpreter);
 };
diff --git a/src/interpreter/source-position-table.cc b/src/interpreter/source-position-table.cc
index 99a865b..579c6c4 100644
--- a/src/interpreter/source-position-table.cc
+++ b/src/interpreter/source-position-table.cc
@@ -23,19 +23,13 @@
 // - we record the difference from the previous position,
 // - we just stuff one bit for the type into the bytecode offset,
 // - we write least-significant bits first,
-// - negative numbers occur only rarely, so we use a denormalized
-//   most-significant byte (a byte with all zeros, which normally wouldn't
-//   make any sense) to encode a negative sign, so that we 'pay' nothing for
-//   positive numbers, but have to pay a full byte for negative integers.
+// - we use zig-zag encoding to encode both positive and negative numbers.
 
 namespace {
 
-// A zero-value in the most-significant byte is used to mark negative numbers.
-const int kNegativeSignMarker = 0;
-
 // Each byte is encoded as MoreBit | ValueBits.
 class MoreBit : public BitField8<bool, 7, 1> {};
-class ValueBits : public BitField8<int, 0, 7> {};
+class ValueBits : public BitField8<unsigned, 0, 7> {};
 
 // Helper: Add the offsets from 'other' to 'value'. Also set is_statement.
 void AddAndSetEntry(PositionTableEntry& value,
@@ -54,114 +48,90 @@
 
 // Helper: Encode an integer.
 void EncodeInt(ZoneVector<byte>& bytes, int value) {
-  bool sign = false;
-  if (value < 0) {
-    sign = true;
-    value = -value;
-  }
-
+  // Zig-zag encoding.
+  static const int kShift = kIntSize * kBitsPerByte - 1;
+  value = ((value << 1) ^ (value >> kShift));
+  DCHECK_GE(value, 0);
+  unsigned int encoded = static_cast<unsigned int>(value);
   bool more;
   do {
-    more = value > ValueBits::kMax;
-    bytes.push_back(MoreBit::encode(more || sign) |
-                    ValueBits::encode(value & ValueBits::kMax));
-    value >>= ValueBits::kSize;
+    more = encoded > ValueBits::kMax;
+    bytes.push_back(MoreBit::encode(more) |
+                    ValueBits::encode(encoded & ValueBits::kMask));
+    encoded >>= ValueBits::kSize;
   } while (more);
-
-  if (sign) {
-    bytes.push_back(MoreBit::encode(false) |
-                    ValueBits::encode(kNegativeSignMarker));
-  }
 }
 
 // Encode a PositionTableEntry.
 void EncodeEntry(ZoneVector<byte>& bytes, const PositionTableEntry& entry) {
-  // 1 bit for sign + is_statement each, which leaves 30b for the value.
-  DCHECK(abs(entry.bytecode_offset) < (1 << 30));
-  EncodeInt(bytes, (entry.is_statement ? 1 : 0) | (entry.bytecode_offset << 1));
+  // We only accept ascending bytecode offsets.
+  DCHECK(entry.bytecode_offset >= 0);
+  // Since bytecode_offset is not negative, we use sign to encode is_statement.
+  EncodeInt(bytes, entry.is_statement ? entry.bytecode_offset
+                                      : -entry.bytecode_offset - 1);
   EncodeInt(bytes, entry.source_position);
 }
 
 // Helper: Decode an integer.
 void DecodeInt(ByteArray* bytes, int* index, int* v) {
   byte current;
-  int n = 0;
-  int value = 0;
+  int shift = 0;
+  int decoded = 0;
   bool more;
   do {
     current = bytes->get((*index)++);
-    value |= ValueBits::decode(current) << (n * ValueBits::kSize);
-    n++;
+    decoded |= ValueBits::decode(current) << shift;
     more = MoreBit::decode(current);
+    shift += ValueBits::kSize;
   } while (more);
-
-  if (ValueBits::decode(current) == kNegativeSignMarker) {
-    value = -value;
-  }
-  *v = value;
+  DCHECK_GE(decoded, 0);
+  decoded = (decoded >> 1) ^ (-(decoded & 1));
+  *v = decoded;
 }
 
 void DecodeEntry(ByteArray* bytes, int* index, PositionTableEntry* entry) {
   int tmp;
   DecodeInt(bytes, index, &tmp);
-  entry->is_statement = (tmp & 1);
-
-  // Note that '>>' needs to be arithmetic shift in order to handle negative
-  // numbers properly.
-  entry->bytecode_offset = (tmp >> 1);
-
+  if (tmp >= 0) {
+    entry->is_statement = true;
+    entry->bytecode_offset = tmp;
+  } else {
+    entry->is_statement = false;
+    entry->bytecode_offset = -(tmp + 1);
+  }
   DecodeInt(bytes, index, &entry->source_position);
 }
 
 }  // namespace
 
-void SourcePositionTableBuilder::AddStatementPosition(size_t bytecode_offset,
-                                                      int source_position) {
+void SourcePositionTableBuilder::AddPosition(size_t bytecode_offset,
+                                             int source_position,
+                                             bool is_statement) {
   int offset = static_cast<int>(bytecode_offset);
-  AddEntry({offset, source_position, true});
-}
-
-void SourcePositionTableBuilder::AddExpressionPosition(size_t bytecode_offset,
-                                                       int source_position) {
-  int offset = static_cast<int>(bytecode_offset);
-  AddEntry({offset, source_position, false});
+  AddEntry({offset, source_position, is_statement});
 }
 
 void SourcePositionTableBuilder::AddEntry(const PositionTableEntry& entry) {
-  // Don't encode a new entry if this bytecode already has a source position
-  // assigned.
-  if (candidate_.bytecode_offset == entry.bytecode_offset) {
-    if (entry.is_statement) candidate_ = entry;
-    return;
-  }
-
-  CommitEntry();
-  candidate_ = entry;
-}
-
-void SourcePositionTableBuilder::CommitEntry() {
-  if (candidate_.bytecode_offset == kUninitializedCandidateOffset) return;
-  PositionTableEntry tmp(candidate_);
+  PositionTableEntry tmp(entry);
   SubtractFromEntry(tmp, previous_);
   EncodeEntry(bytes_, tmp);
-  previous_ = candidate_;
+  previous_ = entry;
 
-  if (candidate_.is_statement) {
+  if (entry.is_statement) {
     LOG_CODE_EVENT(isolate_, CodeLinePosInfoAddStatementPositionEvent(
-                                 jit_handler_data_, candidate_.bytecode_offset,
-                                 candidate_.source_position));
+                                 jit_handler_data_, entry.bytecode_offset,
+                                 entry.source_position));
   }
   LOG_CODE_EVENT(isolate_, CodeLinePosInfoAddPositionEvent(
-                               jit_handler_data_, candidate_.bytecode_offset,
-                               candidate_.source_position));
+                               jit_handler_data_, entry.bytecode_offset,
+                               entry.source_position));
 
 #ifdef ENABLE_SLOW_DCHECKS
-  raw_entries_.push_back(candidate_);
+  raw_entries_.push_back(entry);
 #endif
 }
 
 Handle<ByteArray> SourcePositionTableBuilder::ToSourcePositionTable() {
-  CommitEntry();
   if (bytes_.empty()) return isolate_->factory()->empty_byte_array();
 
   Handle<ByteArray> table = isolate_->factory()->NewByteArray(
diff --git a/src/interpreter/source-position-table.h b/src/interpreter/source-position-table.h
index 3ac58d6..220ef39 100644
--- a/src/interpreter/source-position-table.h
+++ b/src/interpreter/source-position-table.h
@@ -34,7 +34,7 @@
   bool is_statement;
 };
 
-class SourcePositionTableBuilder : public PositionsRecorder {
+class SourcePositionTableBuilder final : public PositionsRecorder {
  public:
   SourcePositionTableBuilder(Isolate* isolate, Zone* zone)
       : isolate_(isolate),
@@ -42,16 +42,14 @@
 #ifdef ENABLE_SLOW_DCHECKS
         raw_entries_(zone),
 #endif
-        candidate_(kUninitializedCandidateOffset, 0, false) {
+        previous_() {
   }
 
-  void AddStatementPosition(size_t bytecode_offset, int source_position);
-  void AddExpressionPosition(size_t bytecode_offset, int source_position);
+  void AddPosition(size_t bytecode_offset, int source_position,
+                   bool is_statement);
   Handle<ByteArray> ToSourcePositionTable();
 
  private:
-  static const int kUninitializedCandidateOffset = -1;
-
   void AddEntry(const PositionTableEntry& entry);
   void CommitEntry();
 
@@ -60,7 +58,6 @@
 #ifdef ENABLE_SLOW_DCHECKS
   ZoneVector<PositionTableEntry> raw_entries_;
 #endif
-  PositionTableEntry candidate_;  // Next entry to be written, if initialized.
   PositionTableEntry previous_;   // Previously written entry, to compute delta.
 };
 
diff --git a/src/isolate-inl.h b/src/isolate-inl.h
index da36f76..46f29b6 100644
--- a/src/isolate-inl.h
+++ b/src/isolate-inl.h
@@ -20,26 +20,26 @@
 
 Object* Isolate::pending_exception() {
   DCHECK(has_pending_exception());
-  DCHECK(!thread_local_top_.pending_exception_->IsException());
+  DCHECK(!thread_local_top_.pending_exception_->IsException(this));
   return thread_local_top_.pending_exception_;
 }
 
 
 void Isolate::set_pending_exception(Object* exception_obj) {
-  DCHECK(!exception_obj->IsException());
+  DCHECK(!exception_obj->IsException(this));
   thread_local_top_.pending_exception_ = exception_obj;
 }
 
 
 void Isolate::clear_pending_exception() {
-  DCHECK(!thread_local_top_.pending_exception_->IsException());
+  DCHECK(!thread_local_top_.pending_exception_->IsException(this));
   thread_local_top_.pending_exception_ = heap_.the_hole_value();
 }
 
 
 bool Isolate::has_pending_exception() {
-  DCHECK(!thread_local_top_.pending_exception_->IsException());
-  return !thread_local_top_.pending_exception_->IsTheHole();
+  DCHECK(!thread_local_top_.pending_exception_->IsException(this));
+  return !thread_local_top_.pending_exception_->IsTheHole(this);
 }
 
 
@@ -50,19 +50,19 @@
 
 Object* Isolate::scheduled_exception() {
   DCHECK(has_scheduled_exception());
-  DCHECK(!thread_local_top_.scheduled_exception_->IsException());
+  DCHECK(!thread_local_top_.scheduled_exception_->IsException(this));
   return thread_local_top_.scheduled_exception_;
 }
 
 
 bool Isolate::has_scheduled_exception() {
-  DCHECK(!thread_local_top_.scheduled_exception_->IsException());
+  DCHECK(!thread_local_top_.scheduled_exception_->IsException(this));
   return thread_local_top_.scheduled_exception_ != heap_.the_hole_value();
 }
 
 
 void Isolate::clear_scheduled_exception() {
-  DCHECK(!thread_local_top_.scheduled_exception_->IsException());
+  DCHECK(!thread_local_top_.scheduled_exception_->IsException(this));
   thread_local_top_.scheduled_exception_ = heap_.the_hole_value();
 }
 
@@ -73,7 +73,11 @@
 
 
 Handle<JSGlobalObject> Isolate::global_object() {
-  return Handle<JSGlobalObject>(context()->global_object(), this);
+  return handle(context()->global_object(), this);
+}
+
+Handle<JSObject> Isolate::global_proxy() {
+  return handle(context()->global_proxy(), this);
 }
 
 
@@ -98,7 +102,6 @@
 #undef NATIVE_CONTEXT_FIELD_ACCESSOR
 
 bool Isolate::IsArraySpeciesLookupChainIntact() {
-  if (!FLAG_harmony_species) return true;
   // Note: It would be nice to have debug checks to make sure that the
   // species protector is accurate, but this would be hard to do for most of
   // what the protector stands for:
@@ -111,11 +114,16 @@
   // done here. In place, there are mjsunit tests harmony/array-species* which
   // ensure that behavior is correct in various invalid protector cases.
 
-  PropertyCell* species_cell = heap()->species_protector();
+  Cell* species_cell = heap()->species_protector();
   return species_cell->value()->IsSmi() &&
          Smi::cast(species_cell->value())->value() == kArrayProtectorValid;
 }
 
+bool Isolate::IsHasInstanceLookupChainIntact() {
+  PropertyCell* has_instance_cell = heap()->has_instance_protector();
+  return has_instance_cell->value() == Smi::FromInt(kArrayProtectorValid);
+}
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/isolate.cc b/src/isolate.cc
index c9f0111..0075a41 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -27,10 +27,10 @@
 #include "src/ic/stub-cache.h"
 #include "src/interpreter/interpreter.h"
 #include "src/isolate-inl.h"
+#include "src/libsampler/v8-sampler.h"
 #include "src/log.h"
 #include "src/messages.h"
 #include "src/profiler/cpu-profiler.h"
-#include "src/profiler/sampler.h"
 #include "src/prototype.h"
 #include "src/regexp/regexp-stack.h"
 #include "src/runtime-profiler.h"
@@ -39,7 +39,7 @@
 #include "src/v8.h"
 #include "src/version.h"
 #include "src/vm-state-inl.h"
-
+#include "src/wasm/wasm-module.h"
 
 namespace v8 {
 namespace internal {
@@ -321,7 +321,6 @@
 // yet.
 static bool IsVisibleInStackTrace(JSFunction* fun,
                                   Object* caller,
-                                  Object* receiver,
                                   bool* seen_caller) {
   if ((fun == caller) && !(*seen_caller)) {
     *seen_caller = true;
@@ -387,7 +386,8 @@
     switch (frame->type()) {
       case StackFrame::JAVA_SCRIPT:
       case StackFrame::OPTIMIZED:
-      case StackFrame::INTERPRETED: {
+      case StackFrame::INTERPRETED:
+      case StackFrame::BUILTIN: {
         JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame);
         // Set initial size to the maximum inlining level + 1 for the outermost
         // function.
@@ -397,9 +397,7 @@
           Handle<JSFunction> fun = frames[i].function();
           Handle<Object> recv = frames[i].receiver();
           // Filter out internal frames that we do not want to show.
-          if (!IsVisibleInStackTrace(*fun, *caller, *recv, &seen_caller)) {
-            continue;
-          }
+          if (!IsVisibleInStackTrace(*fun, *caller, &seen_caller)) continue;
           // Filter out frames from other security contexts.
           if (!this->context()->HasSameSecurityTokenAs(fun->context())) {
             continue;
@@ -433,14 +431,13 @@
         Code* code = wasm_frame->unchecked_code();
         Handle<AbstractCode> abstract_code =
             Handle<AbstractCode>(AbstractCode::cast(code));
-        Handle<JSFunction> fun = factory()->NewFunction(
-            factory()->NewStringFromAsciiChecked("<WASM>"));
+        int offset =
+            static_cast<int>(wasm_frame->pc() - code->instruction_start());
         elements = MaybeGrow(this, elements, cursor, cursor + 4);
-        // TODO(jfb) Pass module object.
-        elements->set(cursor++, *factory()->undefined_value());
-        elements->set(cursor++, *fun);
+        elements->set(cursor++, wasm_frame->wasm_obj());
+        elements->set(cursor++, Smi::FromInt(wasm_frame->function_index()));
         elements->set(cursor++, *abstract_code);
-        elements->set(cursor++, Internals::IntToSmi(0));
+        elements->set(cursor++, Smi::FromInt(offset));
         frames_seen++;
       } break;
 
@@ -542,34 +539,30 @@
     }
   }
 
+  Handle<JSObject> NewStackFrameObject(FrameSummary& summ) {
+    int position = summ.abstract_code()->SourcePosition(summ.code_offset());
+    return NewStackFrameObject(summ.function(), position,
+                               summ.is_constructor());
+  }
+
   Handle<JSObject> NewStackFrameObject(Handle<JSFunction> fun, int position,
                                        bool is_constructor) {
     Handle<JSObject> stack_frame =
         factory()->NewJSObject(isolate_->object_function());
-
     Handle<Script> script(Script::cast(fun->shared()->script()));
 
     if (!line_key_.is_null()) {
-      int script_line_offset = script->line_offset();
-      int line_number = Script::GetLineNumber(script, position);
-      // line_number is already shifted by the script_line_offset.
-      int relative_line_number = line_number - script_line_offset;
-      if (!column_key_.is_null() && relative_line_number >= 0) {
-        Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
-        int start = (relative_line_number == 0) ? 0 :
-            Smi::cast(line_ends->get(relative_line_number - 1))->value() + 1;
-        int column_offset = position - start;
-        if (relative_line_number == 0) {
-          // For the case where the code is on the same line as the script
-          // tag.
-          column_offset += script->column_offset();
-        }
+      Script::PositionInfo info;
+      bool valid_pos =
+          script->GetPositionInfo(position, &info, Script::WITH_OFFSET);
+
+      if (!column_key_.is_null() && valid_pos) {
         JSObject::AddProperty(stack_frame, column_key_,
-                              handle(Smi::FromInt(column_offset + 1), isolate_),
+                              handle(Smi::FromInt(info.column + 1), isolate_),
                               NONE);
       }
       JSObject::AddProperty(stack_frame, line_key_,
-                            handle(Smi::FromInt(line_number + 1), isolate_),
+                            handle(Smi::FromInt(info.line + 1), isolate_),
                             NONE);
     }
 
@@ -589,22 +582,52 @@
                             NONE);
     }
 
-    if (!function_key_.is_null()) {
-      Handle<Object> fun_name = JSFunction::GetDebugName(fun);
-      JSObject::AddProperty(stack_frame, function_key_, fun_name, NONE);
-    }
-
     if (!eval_key_.is_null()) {
       Handle<Object> is_eval = factory()->ToBoolean(
           script->compilation_type() == Script::COMPILATION_TYPE_EVAL);
       JSObject::AddProperty(stack_frame, eval_key_, is_eval, NONE);
     }
 
+    if (!function_key_.is_null()) {
+      Handle<Object> fun_name = JSFunction::GetDebugName(fun);
+      JSObject::AddProperty(stack_frame, function_key_, fun_name, NONE);
+    }
+
     if (!constructor_key_.is_null()) {
       Handle<Object> is_constructor_obj = factory()->ToBoolean(is_constructor);
       JSObject::AddProperty(stack_frame, constructor_key_, is_constructor_obj,
                             NONE);
     }
+    return stack_frame;
+  }
+
+  Handle<JSObject> NewStackFrameObject(WasmFrame* frame) {
+    Handle<JSObject> stack_frame =
+        factory()->NewJSObject(isolate_->object_function());
+
+    if (!function_key_.is_null()) {
+      Handle<String> name = wasm::GetWasmFunctionName(
+          isolate_, handle(frame->wasm_obj(), isolate_),
+          frame->function_index());
+      JSObject::AddProperty(stack_frame, function_key_, name, NONE);
+    }
+    // Encode the function index as line number.
+    if (!line_key_.is_null()) {
+      JSObject::AddProperty(
+          stack_frame, line_key_,
+          isolate_->factory()->NewNumberFromInt(frame->function_index()), NONE);
+    }
+    // Encode the byte offset as column.
+    if (!column_key_.is_null()) {
+      Code* code = frame->LookupCode();
+      int offset = static_cast<int>(frame->pc() - code->instruction_start());
+      int position = code->SourcePosition(offset);
+      // Make position 1-based.
+      if (position >= 0) ++position;
+      JSObject::AddProperty(stack_frame, column_key_,
+                            isolate_->factory()->NewNumberFromInt(position),
+                            NONE);
+    }
 
     return stack_frame;
   }
@@ -683,29 +706,34 @@
   // Ensure no negative values.
   int limit = Max(frame_limit, 0);
   Handle<JSArray> stack_trace = factory()->NewJSArray(frame_limit);
+  Handle<FixedArray> stack_trace_elems(
+      FixedArray::cast(stack_trace->elements()), this);
 
-  StackTraceFrameIterator it(this);
   int frames_seen = 0;
-  while (!it.done() && (frames_seen < limit)) {
-    JavaScriptFrame* frame = it.frame();
-    // Set initial size to the maximum inlining level + 1 for the outermost
-    // function.
-    List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
-    frame->Summarize(&frames);
-    for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) {
-      Handle<JSFunction> fun = frames[i].function();
-      // Filter frames from other security contexts.
-      if (!(options & StackTrace::kExposeFramesAcrossSecurityOrigins) &&
-          !this->context()->HasSameSecurityTokenAs(fun->context())) continue;
-      int position =
-          frames[i].abstract_code()->SourcePosition(frames[i].code_offset());
-      Handle<JSObject> stack_frame =
-          helper.NewStackFrameObject(fun, position, frames[i].is_constructor());
-
-      FixedArray::cast(stack_trace->elements())->set(frames_seen, *stack_frame);
+  for (StackTraceFrameIterator it(this); !it.done() && (frames_seen < limit);
+       it.Advance()) {
+    StandardFrame* frame = it.frame();
+    if (frame->is_java_script()) {
+      // Set initial size to the maximum inlining level + 1 for the outermost
+      // function.
+      List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
+      JavaScriptFrame::cast(frame)->Summarize(&frames);
+      for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) {
+        Handle<JSFunction> fun = frames[i].function();
+        // Filter frames from other security contexts.
+        if (!(options & StackTrace::kExposeFramesAcrossSecurityOrigins) &&
+            !this->context()->HasSameSecurityTokenAs(fun->context()))
+          continue;
+        Handle<JSObject> new_frame_obj = helper.NewStackFrameObject(frames[i]);
+        stack_trace_elems->set(frames_seen, *new_frame_obj);
+        frames_seen++;
+      }
+    } else {
+      WasmFrame* wasm_frame = WasmFrame::cast(frame);
+      Handle<JSObject> new_frame_obj = helper.NewStackFrameObject(wasm_frame);
+      stack_trace_elems->set(frames_seen, *new_frame_obj);
       frames_seen++;
     }
-    it.Advance();
   }
 
   stack_trace->set_length(Smi::FromInt(frames_seen));
@@ -774,21 +802,6 @@
 }
 
 
-static inline AccessCheckInfo* GetAccessCheckInfo(Isolate* isolate,
-                                                  Handle<JSObject> receiver) {
-  Object* maybe_constructor = receiver->map()->GetConstructor();
-  if (!maybe_constructor->IsJSFunction()) return NULL;
-  JSFunction* constructor = JSFunction::cast(maybe_constructor);
-  if (!constructor->shared()->IsApiFunction()) return NULL;
-
-  Object* data_obj =
-     constructor->shared()->get_api_func_data()->access_check_info();
-  if (data_obj == isolate->heap()->undefined_value()) return NULL;
-
-  return AccessCheckInfo::cast(data_obj);
-}
-
-
 void Isolate::ReportFailedAccessCheck(Handle<JSObject> receiver) {
   if (!thread_local_top()->failed_access_check_callback_) {
     return ScheduleThrow(*factory()->NewTypeError(MessageTemplate::kNoAccess));
@@ -801,7 +814,7 @@
   HandleScope scope(this);
   Handle<Object> data;
   { DisallowHeapAllocation no_gc;
-    AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver);
+    AccessCheckInfo* access_check_info = AccessCheckInfo::Get(this, receiver);
     if (!access_check_info) {
       AllowHeapAllocation doesnt_matter_anymore;
       return ScheduleThrow(
@@ -849,18 +862,12 @@
   HandleScope scope(this);
   Handle<Object> data;
   v8::AccessCheckCallback callback = nullptr;
-  v8::NamedSecurityCallback named_callback = nullptr;
   { DisallowHeapAllocation no_gc;
-    AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver);
+    AccessCheckInfo* access_check_info = AccessCheckInfo::Get(this, receiver);
     if (!access_check_info) return false;
     Object* fun_obj = access_check_info->callback();
     callback = v8::ToCData<v8::AccessCheckCallback>(fun_obj);
     data = handle(access_check_info->data(), this);
-    if (!callback) {
-      fun_obj = access_check_info->named_callback();
-      named_callback = v8::ToCData<v8::NamedSecurityCallback>(fun_obj);
-      if (!named_callback) return false;
-    }
   }
 
   LOG(this, ApiSecurityCheck());
@@ -868,21 +875,12 @@
   {
     // Leaving JavaScript.
     VMState<EXTERNAL> state(this);
-    if (callback) {
-      return callback(v8::Utils::ToLocal(accessing_context),
-                      v8::Utils::ToLocal(receiver), v8::Utils::ToLocal(data));
-    }
-    Handle<Object> key = factory()->undefined_value();
-    return named_callback(v8::Utils::ToLocal(receiver), v8::Utils::ToLocal(key),
-                          v8::ACCESS_HAS, v8::Utils::ToLocal(data));
+    return callback(v8::Utils::ToLocal(accessing_context),
+                    v8::Utils::ToLocal(receiver), v8::Utils::ToLocal(data));
   }
 }
 
 
-const char* const Isolate::kStackOverflowMessage =
-  "Uncaught RangeError: Maximum call stack size exceeded";
-
-
 Object* Isolate::StackOverflow() {
   HandleScope scope(this);
   // At this point we cannot create an Error object using its javascript
@@ -1162,7 +1160,7 @@
         // position of the exception handler. The special builtin below will
         // take care of continuing to dispatch at that position. Also restore
         // the correct context for the handler from the interpreter register.
-        context = Context::cast(js_frame->GetInterpreterRegister(context_reg));
+        context = Context::cast(js_frame->ReadInterpreterRegister(context_reg));
         js_frame->PatchBytecodeOffset(static_cast<int>(offset));
         offset = 0;
 
@@ -1291,7 +1289,7 @@
   DCHECK(handler->rethrow_);
   DCHECK(handler->capture_message_);
   Object* message = reinterpret_cast<Object*>(handler->message_obj_);
-  DCHECK(message->IsJSMessageObject() || message->IsTheHole());
+  DCHECK(message->IsJSMessageObject() || message->IsTheHole(this));
   thread_local_top()->pending_message_obj_ = message;
 }
 
@@ -1318,14 +1316,26 @@
   while (!it.done()) {
     HandleScope scope(this);
     // Find code position if recorded in relocation info.
-    JavaScriptFrame* frame = it.frame();
-    Code* code = frame->LookupCode();
-    int offset = static_cast<int>(frame->pc() - code->instruction_start());
-    int pos = frame->LookupCode()->SourcePosition(offset);
+    StandardFrame* frame = it.frame();
+    int pos;
+    if (frame->is_interpreted()) {
+      InterpretedFrame* iframe = reinterpret_cast<InterpretedFrame*>(frame);
+      pos = iframe->GetBytecodeArray()->SourcePosition(
+          iframe->GetBytecodeOffset());
+    } else if (frame->is_java_script()) {
+      Code* code = frame->LookupCode();
+      int offset = static_cast<int>(frame->pc() - code->instruction_start());
+      pos = frame->LookupCode()->SourcePosition(offset);
+    } else {
+      DCHECK(frame->is_wasm());
+      // TODO(clemensh): include wasm frames here
+      continue;
+    }
+    JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame);
     Handle<Object> pos_obj(Smi::FromInt(pos), this);
     // Fetch function and receiver.
-    Handle<JSFunction> fun(frame->function());
-    Handle<Object> recv(frame->receiver(), this);
+    Handle<JSFunction> fun(js_frame->function());
+    Handle<Object> recv(js_frame->receiver(), this);
     // Advance to the next JavaScript frame and determine if the
     // current frame is the top-level frame.
     it.Advance();
@@ -1340,31 +1350,30 @@
   }
 }
 
-
 bool Isolate::ComputeLocation(MessageLocation* target) {
   StackTraceFrameIterator it(this);
-  if (!it.done()) {
-    JavaScriptFrame* frame = it.frame();
-    JSFunction* fun = frame->function();
-    Object* script = fun->shared()->script();
-    if (script->IsScript() &&
-        !(Script::cast(script)->source()->IsUndefined())) {
-      Handle<Script> casted_script(Script::cast(script));
-      // Compute the location from the function and the relocation info of the
-      // baseline code. For optimized code this will use the deoptimization
-      // information to get canonical location information.
-      List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
-      it.frame()->Summarize(&frames);
-      FrameSummary& summary = frames.last();
-      int pos = summary.abstract_code()->SourcePosition(summary.code_offset());
-      *target = MessageLocation(casted_script, pos, pos + 1, handle(fun));
-      return true;
-    }
+  if (it.done()) return false;
+  StandardFrame* frame = it.frame();
+  // TODO(clemensh): handle wasm frames
+  if (!frame->is_java_script()) return false;
+  JSFunction* fun = JavaScriptFrame::cast(frame)->function();
+  Object* script = fun->shared()->script();
+  if (!script->IsScript() ||
+      (Script::cast(script)->source()->IsUndefined(this))) {
+    return false;
   }
-  return false;
+  Handle<Script> casted_script(Script::cast(script));
+  // Compute the location from the function and the relocation info of the
+  // baseline code. For optimized code this will use the deoptimization
+  // information to get canonical location information.
+  List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
+  JavaScriptFrame::cast(frame)->Summarize(&frames);
+  FrameSummary& summary = frames.last();
+  int pos = summary.abstract_code()->SourcePosition(summary.code_offset());
+  *target = MessageLocation(casted_script, pos, pos + 1, handle(fun));
+  return true;
 }
 
-
 bool Isolate::ComputeLocationFromException(MessageLocation* target,
                                            Handle<Object> exception) {
   if (!exception->IsJSObject()) return false;
@@ -1405,13 +1414,17 @@
   int elements_limit = Smi::cast(simple_stack_trace->length())->value();
 
   for (int i = 1; i < elements_limit; i += 4) {
-    Handle<JSFunction> fun =
-        handle(JSFunction::cast(elements->get(i + 1)), this);
+    Handle<Object> fun_obj = handle(elements->get(i + 1), this);
+    if (fun_obj->IsSmi()) {
+      // TODO(clemensh): handle wasm frames
+      return false;
+    }
+    Handle<JSFunction> fun = Handle<JSFunction>::cast(fun_obj);
     if (!fun->shared()->IsSubjectToDebugging()) continue;
 
     Object* script = fun->shared()->script();
     if (script->IsScript() &&
-        !(Script::cast(script)->source()->IsUndefined())) {
+        !(Script::cast(script)->source()->IsUndefined(this))) {
       int pos = PositionFromStackTrace(elements, i);
       Handle<Script> casted_script(Script::cast(script));
       *target = MessageLocation(casted_script, pos, pos + 1);
@@ -1426,7 +1439,7 @@
                                                MessageLocation* location) {
   Handle<JSArray> stack_trace_object;
   if (capture_stack_trace_for_uncaught_exceptions_) {
-    if (Object::IsErrorObject(this, exception)) {
+    if (exception->IsJSError()) {
       // We fetch the stack trace that corresponds to this error object.
       // If the lookup fails, the exception is probably not a valid Error
       // object. In that case, we fall through and capture the stack trace
@@ -1535,7 +1548,7 @@
   }
 
   // Actually report the pending message to all message handlers.
-  if (!message_obj->IsTheHole() && should_report_exception) {
+  if (!message_obj->IsTheHole(this) && should_report_exception) {
     HandleScope scope(this);
     Handle<JSMessageObject> message(JSMessageObject::cast(message_obj));
     Handle<JSValue> script_wrapper(JSValue::cast(message->script()));
@@ -1552,7 +1565,7 @@
   DCHECK(has_pending_exception());
 
   if (thread_local_top_.pending_exception_ != heap()->termination_exception() &&
-      !thread_local_top_.pending_message_obj_->IsTheHole()) {
+      !thread_local_top_.pending_message_obj_->IsTheHole(this)) {
     Handle<JSMessageObject> message_obj(
         JSMessageObject::cast(thread_local_top_.pending_message_obj_));
     Handle<JSValue> script_wrapper(JSValue::cast(message_obj->script()));
@@ -1798,7 +1811,6 @@
       runtime_profiler_(NULL),
       compilation_cache_(NULL),
       counters_(NULL),
-      code_range_(NULL),
       logger_(NULL),
       stats_table_(NULL),
       stub_cache_(NULL),
@@ -1809,7 +1821,6 @@
       capture_stack_trace_for_uncaught_exceptions_(false),
       stack_trace_for_uncaught_exceptions_frame_limit_(0),
       stack_trace_for_uncaught_exceptions_options_(StackTrace::kOverview),
-      memory_allocator_(NULL),
       keyed_lookup_cache_(NULL),
       context_slot_cache_(NULL),
       descriptor_lookup_cache_(NULL),
@@ -1828,12 +1839,14 @@
       // TODO(bmeurer) Initialized lazily because it depends on flags; can
       // be fixed once the default isolate cleanup is done.
       random_number_generator_(NULL),
+      rail_mode_(PERFORMANCE_DEFAULT),
       serializer_enabled_(enable_serializer),
       has_fatal_error_(false),
       initialized_from_snapshot_(false),
       is_tail_call_elimination_enabled_(true),
       cpu_profiler_(NULL),
       heap_profiler_(NULL),
+      code_event_dispatcher_(new CodeEventDispatcher()),
       function_entry_hook_(NULL),
       deferred_handles_head_(NULL),
       optimizing_compile_dispatcher_(NULL),
@@ -1845,6 +1858,7 @@
 #if TRACE_MAPS
       next_unique_sfi_id_(0),
 #endif
+      is_running_microtasks_(false),
       use_counter_callback_(NULL),
       basic_block_profiler_(NULL),
       cancelable_task_manager_(new CancelableTaskManager()),
@@ -1960,7 +1974,7 @@
   }
 
   // We must stop the logger before we tear down other components.
-  Sampler* sampler = logger_->sampler();
+  sampler::Sampler* sampler = logger_->sampler();
   if (sampler && sampler->IsActive()) sampler->Stop();
 
   delete deoptimizer_data_;
@@ -1990,6 +2004,8 @@
   delete cpu_profiler_;
   cpu_profiler_ = NULL;
 
+  code_event_dispatcher_.reset();
+
   delete root_index_map_;
   root_index_map_ = NULL;
 
@@ -2067,10 +2083,6 @@
   delete thread_manager_;
   thread_manager_ = NULL;
 
-  delete memory_allocator_;
-  memory_allocator_ = NULL;
-  delete code_range_;
-  code_range_ = NULL;
   delete global_handles_;
   global_handles_ = NULL;
   delete eternal_handles_;
@@ -2123,12 +2135,12 @@
   } else {
     v8::TryCatch* handler = try_catch_handler();
     DCHECK(thread_local_top_.pending_message_obj_->IsJSMessageObject() ||
-           thread_local_top_.pending_message_obj_->IsTheHole());
+           thread_local_top_.pending_message_obj_->IsTheHole(this));
     handler->can_continue_ = true;
     handler->has_terminated_ = false;
     handler->exception_ = pending_exception();
     // Propagate to the external try-catch only if we got an actual message.
-    if (thread_local_top_.pending_message_obj_->IsTheHole()) return true;
+    if (thread_local_top_.pending_message_obj_->IsTheHole(this)) return true;
 
     handler->message_obj_ = thread_local_top_.pending_message_obj_;
   }
@@ -2164,9 +2176,6 @@
   // The initialization process does not handle memory exhaustion.
   AlwaysAllocateScope always_allocate(this);
 
-  memory_allocator_ = new MemoryAllocator(this);
-  code_range_ = new CodeRange(this);
-
   // Safe after setting Heap::isolate_, and initializing StackGuard
   heap_.SetStackLimits();
 
@@ -2225,7 +2234,7 @@
     return false;
   }
 
-  deoptimizer_data_ = new DeoptimizerData(memory_allocator_);
+  deoptimizer_data_ = new DeoptimizerData(heap()->memory_allocator());
 
   const bool create_heap_objects = (des == NULL);
   if (create_heap_objects && !heap_.CreateHeapObjects()) {
@@ -2247,7 +2256,8 @@
     set_event_logger(Logger::DefaultEventLoggerSentinel);
   }
 
-  if (FLAG_trace_hydrogen || FLAG_trace_hydrogen_stubs) {
+  if (FLAG_trace_hydrogen || FLAG_trace_hydrogen_stubs || FLAG_trace_turbo ||
+      FLAG_trace_turbo_graph) {
     PrintF("Concurrent recompilation has been disabled for tracing.\n");
   } else if (OptimizingCompileDispatcher::Enabled()) {
     optimizing_compile_dispatcher_ = new OptimizingCompileDispatcher(this);
@@ -2262,8 +2272,7 @@
     des->Deserialize(this);
   }
   stub_cache_->Initialize();
-
-  if (FLAG_ignition) {
+  if (FLAG_ignition || serializer_enabled()) {
     interpreter_->Initialize();
   }
 
@@ -2288,13 +2297,10 @@
            Internals::kIsolateEmbedderDataOffset);
   CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.roots_)),
            Internals::kIsolateRootsOffset);
-  CHECK_EQ(static_cast<int>(
-               OFFSET_OF(Isolate, heap_.amount_of_external_allocated_memory_)),
-           Internals::kAmountOfExternalAllocatedMemoryOffset);
-  CHECK_EQ(static_cast<int>(OFFSET_OF(
-               Isolate,
-               heap_.amount_of_external_allocated_memory_at_last_global_gc_)),
-           Internals::kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset);
+  CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.external_memory_)),
+           Internals::kExternalMemoryOffset);
+  CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.external_memory_limit_)),
+           Internals::kExternalMemoryLimitOffset);
 
   time_millis_at_init_ = heap_.MonotonicallyIncreasingTimeInMs();
 
@@ -2428,8 +2434,17 @@
 
 void Isolate::DumpAndResetCompilationStats() {
   if (turbo_statistics() != nullptr) {
+    DCHECK(FLAG_turbo_stats || FLAG_turbo_stats_nvp);
+
     OFStream os(stdout);
-    os << *turbo_statistics() << std::endl;
+    if (FLAG_turbo_stats) {
+      AsPrintableStatistics ps = {*turbo_statistics(), false};
+      os << ps << std::endl;
+    }
+    if (FLAG_turbo_stats_nvp) {
+      AsPrintableStatistics ps = {*turbo_statistics(), true};
+      os << ps << std::endl;
+    }
   }
   if (hstatistics() != nullptr) hstatistics()->Print();
   delete turbo_statistics_;
@@ -2473,7 +2488,7 @@
     DisallowHeapAllocation no_gc;
     Object* const initial_js_array_map =
         context()->native_context()->get(Context::ArrayMapIndex(kind));
-    if (!initial_js_array_map->IsUndefined()) {
+    if (!initial_js_array_map->IsUndefined(this)) {
       return Map::cast(initial_js_array_map);
     }
   }
@@ -2487,6 +2502,31 @@
          CpuFeatures::SupportsCrankshaft();
 }
 
+bool Isolate::IsArrayOrObjectPrototype(Object* object) {
+  Object* context = heap()->native_contexts_list();
+  while (!context->IsUndefined(this)) {
+    Context* current_context = Context::cast(context);
+    if (current_context->initial_object_prototype() == object ||
+        current_context->initial_array_prototype() == object) {
+      return true;
+    }
+    context = current_context->next_context_link();
+  }
+  return false;
+}
+
+bool Isolate::IsInAnyContext(Object* object, uint32_t index) {
+  DisallowHeapAllocation no_gc;
+  Object* context = heap()->native_contexts_list();
+  while (!context->IsUndefined(this)) {
+    Context* current_context = Context::cast(context);
+    if (current_context->get(index) == object) {
+      return true;
+    }
+    context = current_context->next_context_link();
+  }
+  return false;
+}
 
 bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
   PropertyCell* no_elements_cell = heap()->array_protector();
@@ -2547,52 +2587,71 @@
   return cell_reports_intact;
 }
 
-void Isolate::InvalidateArraySpeciesProtector() {
-  if (!FLAG_harmony_species) return;
-  DCHECK(factory()->species_protector()->value()->IsSmi());
-  DCHECK(IsArraySpeciesLookupChainIntact());
-  PropertyCell::SetValueWithInvalidation(
-      factory()->species_protector(),
-      handle(Smi::FromInt(kArrayProtectorInvalid), this));
-  DCHECK(!IsArraySpeciesLookupChainIntact());
+bool Isolate::IsIsConcatSpreadableLookupChainIntact() {
+  Cell* is_concat_spreadable_cell = heap()->is_concat_spreadable_protector();
+  bool is_is_concat_spreadable_set =
+      Smi::cast(is_concat_spreadable_cell->value())->value() ==
+      kArrayProtectorInvalid;
+#ifdef DEBUG
+  Map* root_array_map = get_initial_js_array_map(GetInitialFastElementsKind());
+  if (root_array_map == NULL) {
+    // Ignore the value of is_concat_spreadable during bootstrap.
+    return !is_is_concat_spreadable_set;
+  }
+  Handle<Object> array_prototype(array_function()->prototype(), this);
+  Handle<Symbol> key = factory()->is_concat_spreadable_symbol();
+  Handle<Object> value;
+  LookupIterator it(array_prototype, key);
+  if (it.IsFound() && !JSReceiver::GetDataProperty(&it)->IsUndefined(this)) {
+    // TODO(cbruni): Currently we do not revert if we unset the
+    // @@isConcatSpreadable property on Array.prototype or Object.prototype
+    // hence the reverse implication doesn't hold.
+    DCHECK(is_is_concat_spreadable_set);
+    return false;
+  }
+#endif  // DEBUG
+
+  return !is_is_concat_spreadable_set;
 }
 
 void Isolate::UpdateArrayProtectorOnSetElement(Handle<JSObject> object) {
   DisallowHeapAllocation no_gc;
-  if (IsFastArrayConstructorPrototypeChainIntact() &&
-      object->map()->is_prototype_map()) {
-    Object* context = heap()->native_contexts_list();
-    while (!context->IsUndefined()) {
-      Context* current_context = Context::cast(context);
-      if (current_context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX) ==
-              *object ||
-          current_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX) ==
-              *object) {
-        CountUsage(v8::Isolate::UseCounterFeature::kArrayProtectorDirtied);
-        PropertyCell::SetValueWithInvalidation(
-            factory()->array_protector(),
-            handle(Smi::FromInt(kArrayProtectorInvalid), this));
-        break;
-      }
-      context = current_context->get(Context::NEXT_CONTEXT_LINK);
-    }
-  }
+  if (!object->map()->is_prototype_map()) return;
+  if (!IsFastArrayConstructorPrototypeChainIntact()) return;
+  if (!IsArrayOrObjectPrototype(*object)) return;
+  PropertyCell::SetValueWithInvalidation(
+      factory()->array_protector(),
+      handle(Smi::FromInt(kArrayProtectorInvalid), this));
 }
 
+void Isolate::InvalidateHasInstanceProtector() {
+  DCHECK(factory()->has_instance_protector()->value()->IsSmi());
+  DCHECK(IsHasInstanceLookupChainIntact());
+  PropertyCell::SetValueWithInvalidation(
+      factory()->has_instance_protector(),
+      handle(Smi::FromInt(kArrayProtectorInvalid), this));
+  DCHECK(!IsHasInstanceLookupChainIntact());
+}
+
+void Isolate::InvalidateIsConcatSpreadableProtector() {
+  DCHECK(factory()->is_concat_spreadable_protector()->value()->IsSmi());
+  DCHECK(IsIsConcatSpreadableLookupChainIntact());
+  factory()->is_concat_spreadable_protector()->set_value(
+      Smi::FromInt(kArrayProtectorInvalid));
+  DCHECK(!IsIsConcatSpreadableLookupChainIntact());
+}
+
+void Isolate::InvalidateArraySpeciesProtector() {
+  DCHECK(factory()->species_protector()->value()->IsSmi());
+  DCHECK(IsArraySpeciesLookupChainIntact());
+  factory()->species_protector()->set_value(
+      Smi::FromInt(kArrayProtectorInvalid));
+  DCHECK(!IsArraySpeciesLookupChainIntact());
+}
 
 bool Isolate::IsAnyInitialArrayPrototype(Handle<JSArray> array) {
-  if (array->map()->is_prototype_map()) {
-    Object* context = heap()->native_contexts_list();
-    while (!context->IsUndefined()) {
-      Context* current_context = Context::cast(context);
-      if (current_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX) ==
-          *array) {
-        return true;
-      }
-      context = current_context->get(Context::NEXT_CONTEXT_LINK);
-    }
-  }
-  return false;
+  DisallowHeapAllocation no_gc;
+  return IsInAnyContext(*array, Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
 }
 
 
@@ -2698,16 +2757,19 @@
 
 
 void Isolate::FireCallCompletedCallback() {
-  bool has_call_completed_callbacks = !call_completed_callbacks_.is_empty();
+  if (!handle_scope_implementer()->CallDepthIsZero()) return;
+
   bool run_microtasks =
       pending_microtask_count() &&
       !handle_scope_implementer()->HasMicrotasksSuppressions() &&
       handle_scope_implementer()->microtasks_policy() ==
           v8::MicrotasksPolicy::kAuto;
-  if (!has_call_completed_callbacks && !run_microtasks) return;
 
-  if (!handle_scope_implementer()->CallDepthIsZero()) return;
   if (run_microtasks) RunMicrotasks();
+  // Prevent stepping from spilling into the next call made by the embedder.
+  if (debug()->is_active()) debug()->ClearStepping();
+
+  if (call_completed_callbacks_.is_empty()) return;
   // Fire callbacks.  Increase call depth to prevent recursive callbacks.
   v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this);
   v8::Isolate::SuppressMicrotaskExecutionScope suppress(isolate);
@@ -2748,7 +2810,7 @@
     queue = factory()->CopyFixedArrayAndGrow(queue, num_tasks);
     heap()->set_microtask_queue(*queue);
   }
-  DCHECK(queue->get(num_tasks)->IsUndefined());
+  DCHECK(queue->get(num_tasks)->IsUndefined(this));
   queue->set(num_tasks, *microtask);
   set_pending_microtask_count(num_tasks + 1);
 }
@@ -2758,7 +2820,9 @@
   // Increase call depth to prevent recursive callbacks.
   v8::Isolate::SuppressMicrotaskExecutionScope suppress(
       reinterpret_cast<v8::Isolate*>(this));
+  is_running_microtasks_ = true;
   RunMicrotasksInternal();
+  is_running_microtasks_ = false;
   FireMicrotasksCompletedCallback();
 }
 
@@ -2917,7 +2981,7 @@
       DCHECK(detached_contexts->get(i + 1)->IsWeakCell());
       WeakCell* cell = WeakCell::cast(detached_contexts->get(i + 1));
       if (mark_sweeps > 3) {
-        PrintF("detached context 0x%p\n survived %d GCs (leak?)\n",
+        PrintF("detached context %p\n survived %d GCs (leak?)\n",
                static_cast<void*>(cell->value()), mark_sweeps);
       }
     }
@@ -2930,6 +2994,12 @@
   }
 }
 
+void Isolate::SetRAILMode(RAILMode rail_mode) {
+  rail_mode_ = rail_mode;
+  if (FLAG_trace_rail) {
+    PrintIsolate(this, "RAIL mode: %s\n", RAILModeName(rail_mode_));
+  }
+}
 
 bool StackLimitCheck::JsHasOverflowed(uintptr_t gap) const {
   StackGuard* stack_guard = isolate_->stack_guard();
diff --git a/src/isolate.h b/src/isolate.h
index 8847164..4ca842e 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -5,6 +5,7 @@
 #ifndef V8_ISOLATE_H_
 #define V8_ISOLATE_H_
 
+#include <memory>
 #include <queue>
 #include <set>
 
@@ -13,6 +14,7 @@
 #include "src/assert-scope.h"
 #include "src/base/accounting-allocator.h"
 #include "src/base/atomicops.h"
+#include "src/base/hashmap.h"
 #include "src/builtins.h"
 #include "src/cancelable-task.h"
 #include "src/contexts.h"
@@ -22,7 +24,6 @@
 #include "src/futex-emulation.h"
 #include "src/global-handles.h"
 #include "src/handles.h"
-#include "src/hashmap.h"
 #include "src/heap/heap.h"
 #include "src/messages.h"
 #include "src/optimizing-compile-dispatcher.h"
@@ -42,6 +43,8 @@
 class BasicBlockProfiler;
 class Bootstrapper;
 class CallInterfaceDescriptorData;
+class CodeAgingHelper;
+class CodeEventDispatcher;
 class CodeGenerator;
 class CodeRange;
 class CodeStubDescriptor;
@@ -58,7 +61,6 @@
 class ExternalCallbackScope;
 class ExternalReferenceTable;
 class Factory;
-class FunctionInfoListener;
 class HandleScopeImplementer;
 class HeapProfiler;
 class HStatistics;
@@ -67,7 +69,7 @@
 class InnerPointerToCodeCache;
 class Logger;
 class MaterializedObjectStore;
-class CodeAgingHelper;
+class PositionsRecorder;
 class RegExpStack;
 class SaveContext;
 class StatsTable;
@@ -125,6 +127,17 @@
 #define RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, T) \
   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, MaybeHandle<T>())
 
+#define RETURN_RESULT_OR_FAILURE(isolate, call)     \
+  do {                                              \
+    Handle<Object> __result__;                      \
+    Isolate* __isolate__ = (isolate);               \
+    if (!(call).ToHandle(&__result__)) {            \
+      DCHECK(__isolate__->has_pending_exception()); \
+      return __isolate__->heap()->exception();      \
+    }                                               \
+    return *__result__;                             \
+  } while (false)
+
 #define ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value)  \
   do {                                                               \
     if (!(call).ToHandle(&dst)) {                                    \
@@ -133,21 +146,26 @@
     }                                                                \
   } while (false)
 
-#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)  \
-  ASSIGN_RETURN_ON_EXCEPTION_VALUE(                             \
-      isolate, dst, call, isolate->heap()->exception())
+#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)          \
+  do {                                                                  \
+    Isolate* __isolate__ = (isolate);                                   \
+    ASSIGN_RETURN_ON_EXCEPTION_VALUE(__isolate__, dst, call,            \
+                                     __isolate__->heap()->exception()); \
+  } while (false)
 
 #define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call, T)  \
   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, MaybeHandle<T>())
 
-#define THROW_NEW_ERROR(isolate, call, T)               \
-  do {                                                  \
-    return isolate->Throw<T>(isolate->factory()->call); \
+#define THROW_NEW_ERROR(isolate, call, T)                       \
+  do {                                                          \
+    Isolate* __isolate__ = (isolate);                           \
+    return __isolate__->Throw<T>(__isolate__->factory()->call); \
   } while (false)
 
-#define THROW_NEW_ERROR_RETURN_FAILURE(isolate, call) \
-  do {                                                \
-    return isolate->Throw(*isolate->factory()->call); \
+#define THROW_NEW_ERROR_RETURN_FAILURE(isolate, call)         \
+  do {                                                        \
+    Isolate* __isolate__ = (isolate);                         \
+    return __isolate__->Throw(*__isolate__->factory()->call); \
   } while (false)
 
 #define RETURN_ON_EXCEPTION_VALUE(isolate, call, value)            \
@@ -158,8 +176,12 @@
     }                                                              \
   } while (false)
 
-#define RETURN_FAILURE_ON_EXCEPTION(isolate, call)  \
-  RETURN_ON_EXCEPTION_VALUE(isolate, call, isolate->heap()->exception())
+#define RETURN_FAILURE_ON_EXCEPTION(isolate, call)               \
+  do {                                                           \
+    Isolate* __isolate__ = (isolate);                            \
+    RETURN_ON_EXCEPTION_VALUE(__isolate__, call,                 \
+                              __isolate__->heap()->exception()); \
+  } while (false);
 
 #define RETURN_ON_EXCEPTION(isolate, call, T)  \
   RETURN_ON_EXCEPTION_VALUE(isolate, call, MaybeHandle<T>())
@@ -340,9 +362,9 @@
 
 #if USE_SIMULATOR
 
-#define ISOLATE_INIT_SIMULATOR_LIST(V)                                         \
-  V(bool, simulator_initialized, false)                                        \
-  V(HashMap*, simulator_i_cache, NULL)                                         \
+#define ISOLATE_INIT_SIMULATOR_LIST(V)       \
+  V(bool, simulator_initialized, false)      \
+  V(base::HashMap*, simulator_i_cache, NULL) \
   V(Redirection*, simulator_redirection, NULL)
 #else
 
@@ -353,10 +375,10 @@
 
 #ifdef DEBUG
 
-#define ISOLATE_INIT_DEBUG_ARRAY_LIST(V)                                       \
-  V(CommentStatistic, paged_space_comments_statistics,                         \
-      CommentStatistic::kMaxComments + 1)                                      \
-  V(int, code_kind_statistics, Code::NUMBER_OF_KINDS)
+#define ISOLATE_INIT_DEBUG_ARRAY_LIST(V)               \
+  V(CommentStatistic, paged_space_comments_statistics, \
+    CommentStatistic::kMaxComments + 1)                \
+  V(int, code_kind_statistics, AbstractCode::NUMBER_OF_KINDS)
 #else
 
 #define ISOLATE_INIT_DEBUG_ARRAY_LIST(V)
@@ -374,33 +396,34 @@
 
 typedef List<HeapObject*> DebugObjectCache;
 
-#define ISOLATE_INIT_LIST(V)                                                   \
-  /* Assembler state. */                                                       \
-  V(FatalErrorCallback, exception_behavior, NULL)                              \
-  V(LogEventCallback, event_logger, NULL)                                      \
-  V(AllowCodeGenerationFromStringsCallback, allow_code_gen_callback, NULL)     \
-  /* To distinguish the function templates, so that we can find them in the */ \
-  /* function cache of the native context. */                                  \
-  V(int, next_serial_number, 0)                                                \
-  V(ExternalReferenceRedirectorPointer*, external_reference_redirector, NULL)  \
-  /* Part of the state of liveedit. */                                         \
-  V(FunctionInfoListener*, active_function_info_listener, NULL)                \
-  /* State for Relocatable. */                                                 \
-  V(Relocatable*, relocatable_top, NULL)                                       \
-  V(DebugObjectCache*, string_stream_debug_object_cache, NULL)                 \
-  V(Object*, string_stream_current_security_token, NULL)                       \
-  V(ExternalReferenceTable*, external_reference_table, NULL)                   \
-  V(HashMap*, external_reference_map, NULL)                                    \
-  V(HashMap*, root_index_map, NULL)                                            \
-  V(int, pending_microtask_count, 0)                                           \
-  V(HStatistics*, hstatistics, NULL)                                           \
-  V(CompilationStatistics*, turbo_statistics, NULL)                            \
-  V(HTracer*, htracer, NULL)                                                   \
-  V(CodeTracer*, code_tracer, NULL)                                            \
-  V(bool, fp_stubs_generated, false)                                           \
-  V(uint32_t, per_isolate_assert_data, 0xFFFFFFFFu)                            \
-  V(PromiseRejectCallback, promise_reject_callback, NULL)                      \
-  V(const v8::StartupData*, snapshot_blob, NULL)                               \
+#define ISOLATE_INIT_LIST(V)                                                  \
+  /* Assembler state. */                                                      \
+  V(FatalErrorCallback, exception_behavior, nullptr)                          \
+  V(LogEventCallback, event_logger, nullptr)                                  \
+  V(AllowCodeGenerationFromStringsCallback, allow_code_gen_callback, nullptr) \
+  V(ExternalReferenceRedirectorPointer*, external_reference_redirector,       \
+    nullptr)                                                                  \
+  /* State for Relocatable. */                                                \
+  V(Relocatable*, relocatable_top, nullptr)                                   \
+  V(DebugObjectCache*, string_stream_debug_object_cache, nullptr)             \
+  V(Object*, string_stream_current_security_token, nullptr)                   \
+  V(ExternalReferenceTable*, external_reference_table, nullptr)               \
+  V(intptr_t*, api_external_references, nullptr)                              \
+  V(base::HashMap*, external_reference_map, nullptr)                          \
+  V(base::HashMap*, root_index_map, nullptr)                                  \
+  V(int, pending_microtask_count, 0)                                          \
+  V(HStatistics*, hstatistics, nullptr)                                       \
+  V(CompilationStatistics*, turbo_statistics, nullptr)                        \
+  V(HTracer*, htracer, nullptr)                                               \
+  V(CodeTracer*, code_tracer, nullptr)                                        \
+  V(bool, fp_stubs_generated, false)                                          \
+  V(uint32_t, per_isolate_assert_data, 0xFFFFFFFFu)                           \
+  V(PromiseRejectCallback, promise_reject_callback, nullptr)                  \
+  V(const v8::StartupData*, snapshot_blob, nullptr)                           \
+  V(int, code_and_metadata_size, 0)                                           \
+  V(int, bytecode_and_metadata_size, 0)                                       \
+  /* true if being profiled. Causes collection of extra compile info. */      \
+  V(bool, is_profiling, false)                                                \
   ISOLATE_INIT_SIMULATOR_LIST(V)
 
 #define THREAD_LOCAL_TOP_ACCESSOR(type, name)                        \
@@ -495,14 +518,6 @@
     return isolate;
   }
 
-  // Like Current, but skips the check that |isolate_key_| was initialized.
-  // Callers have to ensure that themselves.
-  // DO NOT USE. The only remaining callsite will be deleted soon.
-  INLINE(static Isolate* UnsafeCurrent()) {
-    return reinterpret_cast<Isolate*>(
-        base::Thread::GetThreadLocal(isolate_key_));
-  }
-
   // Usually called by Init(), but can be called early e.g. to allow
   // testing components that require logging but not the whole
   // isolate.
@@ -633,9 +648,7 @@
   inline Handle<JSGlobalObject> global_object();
 
   // Returns the global proxy object of the current context.
-  JSObject* global_proxy() {
-    return context()->global_proxy();
-  }
+  inline Handle<JSObject> global_proxy();
 
   static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); }
   void FreeThreadResources() { thread_local_top_.Free(); }
@@ -701,7 +714,7 @@
   void ReportFailedAccessCheck(Handle<JSObject> receiver);
 
   // Exception throwing support. The caller should use the result
-  // of Throw() as its return value.
+  // of Throw() as its return vaue.
   Object* Throw(Object* exception, MessageLocation* location = NULL);
   Object* ThrowIllegalOperation();
 
@@ -778,8 +791,6 @@
   char* ArchiveThread(char* to);
   char* RestoreThread(char* from);
 
-  static const char* const kStackOverflowMessage;
-
   static const int kUC16AlphabetSize = 256;  // See StringSearchBase.
   static const int kBMMaxShift = 250;        // See StringSearchBase.
 
@@ -817,7 +828,6 @@
     DCHECK(counters_ != NULL);
     return counters_;
   }
-  CodeRange* code_range() { return code_range_; }
   RuntimeProfiler* runtime_profiler() { return runtime_profiler_; }
   CompilationCache* compilation_cache() { return compilation_cache_; }
   Logger* logger() {
@@ -841,10 +851,6 @@
     return materialized_object_store_;
   }
 
-  MemoryAllocator* memory_allocator() {
-    return memory_allocator_;
-  }
-
   KeyedLookupCache* keyed_lookup_cache() {
     return keyed_lookup_cache_;
   }
@@ -912,6 +918,10 @@
 
   Debug* debug() { return debug_; }
 
+  bool* is_profiling_address() { return &is_profiling_; }
+  CodeEventDispatcher* code_event_dispatcher() const {
+    return code_event_dispatcher_.get();
+  }
   CpuProfiler* cpu_profiler() const { return cpu_profiler_; }
   HeapProfiler* heap_profiler() const { return heap_profiler_; }
 
@@ -974,6 +984,8 @@
 
   bool IsFastArrayConstructorPrototypeChainIntact();
   inline bool IsArraySpeciesLookupChainIntact();
+  inline bool IsHasInstanceLookupChainIntact();
+  bool IsIsConcatSpreadableLookupChainIntact();
 
   // On intent to set an element in object, make sure that appropriate
   // notifications occur if the set is on the elements of the array or
@@ -990,6 +1002,8 @@
     UpdateArrayProtectorOnSetElement(object);
   }
   void InvalidateArraySpeciesProtector();
+  void InvalidateHasInstanceProtector();
+  void InvalidateIsConcatSpreadableProtector();
 
   // Returns true if array is the initial array prototype in any native context.
   bool IsAnyInitialArrayPrototype(Handle<JSArray> array);
@@ -1077,6 +1091,7 @@
 
   void EnqueueMicrotask(Handle<Object> microtask);
   void RunMicrotasks();
+  bool IsRunningMicrotasks() const { return is_running_microtasks_; }
 
   void SetUseCounterCallback(v8::Isolate::UseCounterCallback callback);
   void CountUsage(v8::Isolate::UseCounterFeature feature);
@@ -1121,8 +1136,13 @@
 
   base::AccountingAllocator* allocator() { return &allocator_; }
 
+  bool IsInAnyContext(Object* object, uint32_t index);
+
+  void SetRAILMode(RAILMode rail_mode);
+
  protected:
   explicit Isolate(bool enable_serializer);
+  bool IsArrayOrObjectPrototype(Object* object);
 
  private:
   friend struct GlobalState;
@@ -1231,6 +1251,24 @@
 
   void RunMicrotasksInternal();
 
+  const char* RAILModeName(RAILMode rail_mode) const {
+    switch (rail_mode) {
+      case PERFORMANCE_DEFAULT:
+        return "DEFAULT";
+      case PERFORMANCE_RESPONSE:
+        return "RESPONSE";
+      case PERFORMANCE_ANIMATION:
+        return "ANIMATION";
+      case PERFORMANCE_IDLE:
+        return "IDLE";
+      case PERFORMANCE_LOAD:
+        return "LOAD";
+      default:
+        UNREACHABLE();
+    }
+    return "";
+  }
+
   base::Atomic32 id_;
   EntryStackItem* entry_stack_;
   int stack_trace_nesting_level_;
@@ -1240,7 +1278,6 @@
   RuntimeProfiler* runtime_profiler_;
   CompilationCache* compilation_cache_;
   Counters* counters_;
-  CodeRange* code_range_;
   base::RecursiveMutex break_access_;
   Logger* logger_;
   StackGuard stack_guard_;
@@ -1254,7 +1291,6 @@
   bool capture_stack_trace_for_uncaught_exceptions_;
   int stack_trace_for_uncaught_exceptions_frame_limit_;
   StackTrace::StackTraceOptions stack_trace_for_uncaught_exceptions_options_;
-  MemoryAllocator* memory_allocator_;
   KeyedLookupCache* keyed_lookup_cache_;
   ContextSlotCache* context_slot_cache_;
   DescriptorLookupCache* descriptor_lookup_cache_;
@@ -1279,6 +1315,7 @@
   DateCache* date_cache_;
   CallInterfaceDescriptorData* call_descriptor_data_;
   base::RandomNumberGenerator* random_number_generator_;
+  RAILMode rail_mode_;
 
   // Whether the isolate has been created for snapshotting.
   bool serializer_enabled_;
@@ -1304,6 +1341,7 @@
   Debug* debug_;
   CpuProfiler* cpu_profiler_;
   HeapProfiler* heap_profiler_;
+  std::unique_ptr<CodeEventDispatcher> code_event_dispatcher_;
   FunctionEntryHook function_entry_hook_;
 
   interpreter::Interpreter* interpreter_;
@@ -1358,6 +1396,7 @@
 
   // List of callbacks after microtasks were run.
   List<MicrotasksCompletedCallback> microtasks_completed_callbacks_;
+  bool is_running_microtasks_;
 
   v8::Isolate::UseCounterCallback use_counter_callback_;
   BasicBlockProfiler* basic_block_profiler_;
@@ -1381,11 +1420,10 @@
   friend class Simulator;
   friend class StackGuard;
   friend class ThreadId;
-  friend class TestMemoryAllocatorScope;
-  friend class TestCodeRangeScope;
   friend class v8::Isolate;
   friend class v8::Locker;
   friend class v8::Unlocker;
+  friend class v8::SnapshotCreator;
   friend v8::StartupData v8::V8::CreateSnapshotDataBlob(const char*);
   friend v8::StartupData v8::V8::WarmUpSnapshotDataBlob(v8::StartupData,
                                                         const char*);
@@ -1499,6 +1537,15 @@
   Isolate* isolate_;
 };
 
+#define STACK_CHECK(isolate, result_value)               \
+  do {                                                   \
+    StackLimitCheck stack_check(isolate);                \
+    if (stack_check.HasOverflowed()) {                   \
+      isolate->Throw(*isolate->factory()->NewRangeError( \
+          MessageTemplate::kStackOverflow));             \
+      return result_value;                               \
+    }                                                    \
+  } while (false)
 
 // Support for temporarily postponing interrupts. When the outermost
 // postpone scope is left the interrupts will be re-enabled and any
diff --git a/src/js/array-iterator.js b/src/js/array-iterator.js
index b3e25e9..8203f1f 100644
--- a/src/js/array-iterator.js
+++ b/src/js/array-iterator.js
@@ -22,7 +22,7 @@
 var iteratorSymbol = utils.ImportNow("iterator_symbol");
 var MakeTypeError;
 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
-var GlobalTypedArray = global.Uint8Array.__proto__;
+var GlobalTypedArray = %object_get_prototype_of(global.Uint8Array);
 
 utils.Import(function(from) {
   MakeTypeError = from.MakeTypeError;
diff --git a/src/js/array.js b/src/js/array.js
index 1406df3..c29b8f7 100644
--- a/src/js/array.js
+++ b/src/js/array.js
@@ -11,8 +11,6 @@
 // -------------------------------------------------------------------
 // Imports
 
-var AddIndexedProperty;
-var FLAG_harmony_species;
 var GetIterator;
 var GetMethod;
 var GlobalArray = global.Array;
@@ -21,58 +19,31 @@
 var MakeTypeError;
 var MaxSimple;
 var MinSimple;
-var ObjectDefineProperty;
 var ObjectHasOwnProperty;
 var ObjectToString = utils.ImportNow("object_to_string");
-var ObserveBeginPerformSplice;
-var ObserveEndPerformSplice;
-var ObserveEnqueueSpliceRecord;
 var iteratorSymbol = utils.ImportNow("iterator_symbol");
+var speciesSymbol = utils.ImportNow("species_symbol");
 var unscopablesSymbol = utils.ImportNow("unscopables_symbol");
 
 utils.Import(function(from) {
-  AddIndexedProperty = from.AddIndexedProperty;
   GetIterator = from.GetIterator;
   GetMethod = from.GetMethod;
   MakeTypeError = from.MakeTypeError;
   MaxSimple = from.MaxSimple;
   MinSimple = from.MinSimple;
-  ObjectDefineProperty = from.ObjectDefineProperty;
   ObjectHasOwnProperty = from.ObjectHasOwnProperty;
-  ObserveBeginPerformSplice = from.ObserveBeginPerformSplice;
-  ObserveEndPerformSplice = from.ObserveEndPerformSplice;
-  ObserveEnqueueSpliceRecord = from.ObserveEnqueueSpliceRecord;
-});
-
-utils.ImportFromExperimental(function(from) {
-  FLAG_harmony_species = from.FLAG_harmony_species;
 });
 
 // -------------------------------------------------------------------
 
 
 function ArraySpeciesCreate(array, length) {
-  var constructor;
-  if (FLAG_harmony_species) {
-    constructor = %ArraySpeciesConstructor(array);
-  } else {
-    constructor = GlobalArray;
-  }
+  length = INVERT_NEG_ZERO(length);
+  var constructor = %ArraySpeciesConstructor(array);
   return new constructor(length);
 }
 
 
-function DefineIndexedProperty(array, i, value) {
-  if (FLAG_harmony_species) {
-    var result = ObjectDefineProperty(array, i, {
-      value: value, writable: true, configurable: true, enumerable: true
-    });
-    if (!result) throw MakeTypeError(kStrictCannotAssign, i);
-  } else {
-    AddIndexedProperty(array, i, value);
-  }
-}
-
 function KeySortCompare(a, b) {
   return a - b;
 }
@@ -123,8 +94,7 @@
   // Only use the sparse variant on arrays that are likely to be sparse and the
   // number of elements touched in the operation is relatively small compared to
   // the overall size of the array.
-  if (!is_array || length < 1000 || %IsObserved(array) ||
-      %HasComplexElements(array)) {
+  if (!is_array || length < 1000 || %HasComplexElements(array)) {
     return false;
   }
   if (!%_IsSmi(length)) {
@@ -265,7 +235,7 @@
     for (var i = start_i; i < limit; ++i) {
       var current = array[i];
       if (!IS_UNDEFINED(current) || i in array) {
-        DefineIndexedProperty(deleted_elements, i - start_i, current);
+        %CreateDataProperty(deleted_elements, i - start_i, current);
       }
     }
   } else {
@@ -275,7 +245,7 @@
       if (key >= start_i) {
         var current = array[key];
         if (!IS_UNDEFINED(current) || key in array) {
-          DefineIndexedProperty(deleted_elements, key - start_i, current);
+          %CreateDataProperty(deleted_elements, key - start_i, current);
         }
       }
     }
@@ -347,19 +317,17 @@
 // because the receiver is not an array (so we have no choice) or because we
 // know we are not deleting or moving a lot of elements.
 function SimpleSlice(array, start_i, del_count, len, deleted_elements) {
-  var is_array = IS_ARRAY(array);
   for (var i = 0; i < del_count; i++) {
     var index = start_i + i;
-    if (HAS_INDEX(array, index, is_array)) {
+    if (index in array) {
       var current = array[index];
-      DefineIndexedProperty(deleted_elements, i, current);
+      %CreateDataProperty(deleted_elements, i, current);
     }
   }
 }
 
 
 function SimpleMove(array, start_i, del_count, len, num_additional_args) {
-  var is_array = IS_ARRAY(array);
   if (num_additional_args !== del_count) {
     // Move the existing elements after the elements to be deleted
     // to the right position in the resulting array.
@@ -367,7 +335,7 @@
       for (var i = len - del_count; i > start_i; i--) {
         var from_index = i + del_count - 1;
         var to_index = i + num_additional_args - 1;
-        if (HAS_INDEX(array, from_index, is_array)) {
+        if (from_index in array) {
           array[to_index] = array[from_index];
         } else {
           delete array[to_index];
@@ -377,7 +345,7 @@
       for (var i = start_i; i < len - del_count; i++) {
         var from_index = i + del_count;
         var to_index = i + num_additional_args;
-        if (HAS_INDEX(array, from_index, is_array)) {
+        if (from_index in array) {
           array[to_index] = array[from_index];
         } else {
           delete array[to_index];
@@ -456,23 +424,6 @@
 }
 
 
-function ObservedArrayPop(n) {
-  n--;
-  var value = this[n];
-
-  try {
-    ObserveBeginPerformSplice(this);
-    delete this[n];
-    this.length = n;
-  } finally {
-    ObserveEndPerformSplice(this);
-    ObserveEnqueueSpliceRecord(this, n, [value], 0);
-  }
-
-  return value;
-}
-
-
 // Removes the last element from the array and returns it. See
 // ECMA-262, section 15.4.4.6.
 function ArrayPop() {
@@ -485,9 +436,6 @@
     return;
   }
 
-  if (%IsObserved(array))
-    return ObservedArrayPop.call(array, n);
-
   n--;
   var value = array[n];
   %DeleteProperty_Strict(array, n);
@@ -496,46 +444,19 @@
 }
 
 
-function ObservedArrayPush() {
-  var n = TO_LENGTH(this.length);
-  var m = arguments.length;
-
-  try {
-    ObserveBeginPerformSplice(this);
-    for (var i = 0; i < m; i++) {
-      this[i+n] = arguments[i];
-    }
-    var new_length = n + m;
-    this.length = new_length;
-  } finally {
-    ObserveEndPerformSplice(this);
-    ObserveEnqueueSpliceRecord(this, n, [], m);
-  }
-
-  return new_length;
-}
-
-
 // Appends the arguments to the end of the array and returns the new
 // length of the array. See ECMA-262, section 15.4.4.7.
 function ArrayPush() {
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.push");
 
-  if (%IsObserved(this))
-    return ObservedArrayPush.apply(this, arguments);
-
   var array = TO_OBJECT(this);
   var n = TO_LENGTH(array.length);
   var m = arguments.length;
 
-  // It appears that there is no enforced, absolute limit on the number of
-  // arguments, but it would surely blow the stack to use 2**30 or more.
-  // To avoid integer overflow, do the comparison to the max safe integer
-  // after subtracting 2**30 from both sides. (2**31 would seem like a
-  // natural value, but it is negative in JS, and 2**32 is 1.)
-  if (m > (1 << 30) || (n - (1 << 30)) + m > kMaxSafeInteger - (1 << 30)) {
-    throw MakeTypeError(kPushPastSafeLength, m, n);
-  }
+  // Subtract n from kMaxSafeInteger rather than testing m + n >
+  // kMaxSafeInteger. n may already be kMaxSafeInteger. In that case adding
+  // e.g., 1 would not be safe.
+  if (m > kMaxSafeInteger - n) throw MakeTypeError(kPushPastSafeLength, m, n);
 
   for (var i = 0; i < m; i++) {
     array[i+n] = arguments[i];
@@ -646,22 +567,6 @@
 }
 
 
-function ObservedArrayShift(len) {
-  var first = this[0];
-
-  try {
-    ObserveBeginPerformSplice(this);
-    SimpleMove(this, 0, 1, len, 0);
-    this.length = len - 1;
-  } finally {
-    ObserveEndPerformSplice(this);
-    ObserveEnqueueSpliceRecord(this, 0, [first], 0);
-  }
-
-  return first;
-}
-
-
 function ArrayShift() {
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.shift");
 
@@ -675,9 +580,6 @@
 
   if (%object_is_sealed(array)) throw MakeTypeError(kArrayFunctionsOnSealed);
 
-  if (%IsObserved(array))
-    return ObservedArrayShift.call(array, len);
-
   var first = array[0];
 
   if (UseSparseVariant(array, len, IS_ARRAY(array), len)) {
@@ -692,33 +594,9 @@
 }
 
 
-function ObservedArrayUnshift() {
-  var len = TO_LENGTH(this.length);
-  var num_arguments = arguments.length;
-
-  try {
-    ObserveBeginPerformSplice(this);
-    SimpleMove(this, 0, 0, len, num_arguments);
-    for (var i = 0; i < num_arguments; i++) {
-      this[i] = arguments[i];
-    }
-    var new_length = len + num_arguments;
-    this.length = new_length;
-  } finally {
-    ObserveEndPerformSplice(this);
-    ObserveEnqueueSpliceRecord(this, 0, [], num_arguments);
-  }
-
-  return new_length;
-}
-
-
 function ArrayUnshift(arg1) {  // length == 1
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.unshift");
 
-  if (%IsObserved(this))
-    return ObservedArrayUnshift.apply(this, arguments);
-
   var array = TO_OBJECT(this);
   var len = TO_LENGTH(array.length);
   var num_arguments = arguments.length;
@@ -770,7 +648,7 @@
 
   if (UseSparseVariant(array, len, IS_ARRAY(array), end_i - start_i)) {
     %NormalizeElements(array);
-    %NormalizeElements(result);
+    if (IS_ARRAY(result)) %NormalizeElements(result);
     SparseSlice(array, start_i, end_i - start_i, len, result);
   } else {
     SimpleSlice(array, start_i, end_i - start_i, len, result);
@@ -813,53 +691,9 @@
 }
 
 
-function ObservedArraySplice(start, delete_count) {
-  var num_arguments = arguments.length;
-  var len = TO_LENGTH(this.length);
-  var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
-  var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
-                                           start_i);
-  var deleted_elements = [];
-  deleted_elements.length = del_count;
-  var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;
-
-  try {
-    ObserveBeginPerformSplice(this);
-
-    SimpleSlice(this, start_i, del_count, len, deleted_elements);
-    SimpleMove(this, start_i, del_count, len, num_elements_to_add);
-
-    // Insert the arguments into the resulting array in
-    // place of the deleted elements.
-    var i = start_i;
-    var arguments_index = 2;
-    var arguments_length = arguments.length;
-    while (arguments_index < arguments_length) {
-      this[i++] = arguments[arguments_index++];
-    }
-    this.length = len - del_count + num_elements_to_add;
-
-  } finally {
-    ObserveEndPerformSplice(this);
-    if (deleted_elements.length || num_elements_to_add) {
-      ObserveEnqueueSpliceRecord(this,
-                                 start_i,
-                                 deleted_elements.slice(),
-                                 num_elements_to_add);
-    }
-  }
-
-  // Return the deleted elements.
-  return deleted_elements;
-}
-
-
 function ArraySplice(start, delete_count) {
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.splice");
 
-  if (%IsObserved(this))
-    return ObservedArraySplice.apply(this, arguments);
-
   var num_arguments = arguments.length;
   var array = TO_OBJECT(this);
   var len = TO_LENGTH(array.length);
@@ -884,7 +718,7 @@
   }
   if (UseSparseVariant(array, len, IS_ARRAY(array), changed_elements)) {
     %NormalizeElements(array);
-    %NormalizeElements(deleted_elements);
+    if (IS_ARRAY(deleted_elements)) %NormalizeElements(deleted_elements);
     SparseSlice(array, start_i, del_count, len, deleted_elements);
     SparseMove(array, start_i, del_count, len, num_elements_to_add);
   } else {
@@ -1048,7 +882,8 @@
   // of a prototype property.
   var CopyFromPrototype = function CopyFromPrototype(obj, length) {
     var max = 0;
-    for (var proto = %_GetPrototype(obj); proto; proto = %_GetPrototype(proto)) {
+    for (var proto = %object_get_prototype_of(obj); proto;
+         proto = %object_get_prototype_of(proto)) {
       var indices = IS_PROXY(proto) ? length : %GetArrayKeys(proto, length);
       if (IS_NUMBER(indices)) {
         // It's an interval.
@@ -1076,7 +911,8 @@
   // where a prototype of obj has an element. I.e., shadow all prototype
   // elements in that range.
   var ShadowPrototypeElements = function(obj, from, to) {
-    for (var proto = %_GetPrototype(obj); proto; proto = %_GetPrototype(proto)) {
+    for (var proto = %object_get_prototype_of(obj); proto;
+         proto = %object_get_prototype_of(proto)) {
       var indices = IS_PROXY(proto) ? to : %GetArrayKeys(proto, to);
       if (IS_NUMBER(indices)) {
         // It's an interval.
@@ -1143,7 +979,7 @@
     }
     for (i = length - num_holes; i < length; i++) {
       // For compatability with Webkit, do not expose elements in the prototype.
-      if (i in %_GetPrototype(obj)) {
+      if (i in %object_get_prototype_of(obj)) {
         obj[i] = UNDEFINED;
       } else {
         delete obj[i];
@@ -1174,9 +1010,9 @@
   var num_non_undefined = %RemoveArrayHoles(array, length);
 
   if (num_non_undefined == -1) {
-    // The array is observed, or there were indexed accessors in the array.
+    // There were indexed accessors in the array.
     // Move array holes and undefineds to the end using a Javascript function
-    // that is safe in the presence of accessors and is observable.
+    // that is safe in the presence of accessors.
     num_non_undefined = SafeRemoveArrayHoles(array);
   }
 
@@ -1206,12 +1042,11 @@
 // or delete elements from the array.
 function InnerArrayFilter(f, receiver, array, length, result) {
   var result_length = 0;
-  var is_array = IS_ARRAY(array);
   for (var i = 0; i < length; i++) {
-    if (HAS_INDEX(array, i, is_array)) {
+    if (i in array) {
       var element = array[i];
       if (%_Call(f, receiver, element, i, array)) {
-        DefineIndexedProperty(result, result_length, element);
+        %CreateDataProperty(result, result_length, element);
         result_length++;
       }
     }
@@ -1237,17 +1072,16 @@
 function InnerArrayForEach(f, receiver, array, length) {
   if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
 
-  var is_array = IS_ARRAY(array);
   if (IS_UNDEFINED(receiver)) {
     for (var i = 0; i < length; i++) {
-      if (HAS_INDEX(array, i, is_array)) {
+      if (i in array) {
         var element = array[i];
         f(element, i, array);
       }
     }
   } else {
     for (var i = 0; i < length; i++) {
-      if (HAS_INDEX(array, i, is_array)) {
+      if (i in array) {
         var element = array[i];
         %_Call(f, receiver, element, i, array);
       }
@@ -1270,9 +1104,8 @@
 function InnerArraySome(f, receiver, array, length) {
   if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
 
-  var is_array = IS_ARRAY(array);
   for (var i = 0; i < length; i++) {
-    if (HAS_INDEX(array, i, is_array)) {
+    if (i in array) {
       var element = array[i];
       if (%_Call(f, receiver, element, i, array)) return true;
     }
@@ -1297,9 +1130,8 @@
 function InnerArrayEvery(f, receiver, array, length) {
   if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
 
-  var is_array = IS_ARRAY(array);
   for (var i = 0; i < length; i++) {
-    if (HAS_INDEX(array, i, is_array)) {
+    if (i in array) {
       var element = array[i];
       if (!%_Call(f, receiver, element, i, array)) return false;
     }
@@ -1327,11 +1159,10 @@
   var length = TO_LENGTH(array.length);
   if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
   var result = ArraySpeciesCreate(array, length);
-  var is_array = IS_ARRAY(array);
   for (var i = 0; i < length; i++) {
-    if (HAS_INDEX(array, i, is_array)) {
+    if (i in array) {
       var element = array[i];
-      DefineIndexedProperty(result, i, %_Call(f, receiver, element, i, array));
+      %CreateDataProperty(result, i, %_Call(f, receiver, element, i, array));
     }
   }
   return result;
@@ -1347,7 +1178,7 @@
   if (IS_UNDEFINED(index)) {
     index = 0;
   } else {
-    index = TO_INTEGER(index) + 0;  // Add 0 to convert -0 to 0
+    index = INVERT_NEG_ZERO(TO_INTEGER(index));
     // If index is negative, index from the end of the array.
     if (index < 0) {
       index = length + index;
@@ -1409,7 +1240,7 @@
   if (argumentsLength < 2) {
     index = length - 1;
   } else {
-    index = TO_INTEGER(index) + 0;  // Add 0 to convert -0 to 0
+    index = INVERT_NEG_ZERO(TO_INTEGER(index));
     // If index is negative, index from end of the array.
     if (index < 0) index += length;
     // If index is still negative, do not search the array.
@@ -1468,11 +1299,10 @@
     throw MakeTypeError(kCalledNonCallable, callback);
   }
 
-  var is_array = IS_ARRAY(array);
   var i = 0;
   find_initial: if (argumentsLength < 2) {
     for (; i < length; i++) {
-      if (HAS_INDEX(array, i, is_array)) {
+      if (i in array) {
         current = array[i++];
         break find_initial;
       }
@@ -1481,7 +1311,7 @@
   }
 
   for (; i < length; i++) {
-    if (HAS_INDEX(array, i, is_array)) {
+    if (i in array) {
       var element = array[i];
       current = callback(current, element, i, array);
     }
@@ -1508,11 +1338,10 @@
     throw MakeTypeError(kCalledNonCallable, callback);
   }
 
-  var is_array = IS_ARRAY(array);
   var i = length - 1;
   find_initial: if (argumentsLength < 2) {
     for (; i >= 0; i--) {
-      if (HAS_INDEX(array, i, is_array)) {
+      if (i in array) {
         current = array[i--];
         break find_initial;
       }
@@ -1521,7 +1350,7 @@
   }
 
   for (; i >= 0; i--) {
-    if (HAS_INDEX(array, i, is_array)) {
+    if (i in array) {
       var element = array[i];
       current = callback(current, element, i, array);
     }
@@ -1736,17 +1565,6 @@
 }
 
 
-function AddArrayElement(constructor, array, i, value) {
-  if (constructor === GlobalArray) {
-    AddIndexedProperty(array, i, value);
-  } else {
-    ObjectDefineProperty(array, i, {
-      value: value, writable: true, configurable: true, enumerable: true
-    });
-  }
-}
-
-
 // ES6, draft 10-14-14, section 22.1.2.1
 function ArrayFrom(arrayLike, mapfn, receiver) {
   var items = TO_OBJECT(arrayLike);
@@ -1775,7 +1593,7 @@
       } else {
         mappedValue = nextValue;
       }
-      AddArrayElement(this, result, k, mappedValue);
+      %CreateDataProperty(result, k, mappedValue);
       k++;
     }
     result.length = k;
@@ -1791,7 +1609,7 @@
       } else {
         mappedValue = nextValue;
       }
-      AddArrayElement(this, result, k, mappedValue);
+      %CreateDataProperty(result, k, mappedValue);
     }
 
     result.length = k;
@@ -1807,12 +1625,18 @@
   // TODO: Implement IsConstructor (ES6 section 7.2.5)
   var array = %IsConstructor(constructor) ? new constructor(length) : [];
   for (var i = 0; i < length; i++) {
-    AddArrayElement(constructor, array, i, args[i]);
+    %CreateDataProperty(array, i, args[i]);
   }
   array.length = length;
   return array;
 }
 
+
+function ArraySpecies() {
+  return this;
+}
+
+
 // -------------------------------------------------------------------
 
 // Set up non-enumerable constructor property on the Array.prototype
@@ -1828,6 +1652,7 @@
   fill: true,
   find: true,
   findIndex: true,
+  includes: true,
   keys: true,
 };
 
@@ -1887,6 +1712,8 @@
   "includes", getFunction("includes", ArrayIncludes, 1),
 ]);
 
+utils.InstallGetter(GlobalArray, speciesSymbol, ArraySpecies);
+
 %FinishArrayPrototypeSetup(GlobalArray.prototype);
 
 // The internal Array prototype doesn't need to be fancy, since it's never
@@ -1946,10 +1773,6 @@
   to.InnerArraySort = InnerArraySort;
   to.InnerArrayToLocaleString = InnerArrayToLocaleString;
   to.PackedArrayReverse = PackedArrayReverse;
-  to.Stack = Stack;
-  to.StackHas = StackHas;
-  to.StackPush = StackPush;
-  to.StackPop = StackPop;
 });
 
 %InstallToContext([
diff --git a/src/js/arraybuffer.js b/src/js/arraybuffer.js
index f0273c7..b602dcb 100644
--- a/src/js/arraybuffer.js
+++ b/src/js/arraybuffer.js
@@ -16,6 +16,7 @@
 var MaxSimple;
 var MinSimple;
 var SpeciesConstructor;
+var speciesSymbol = utils.ImportNow("species_symbol");
 
 utils.Import(function(from) {
   MakeTypeError = from.MakeTypeError;
@@ -70,7 +71,9 @@
     throw MakeTypeError(kIncompatibleMethodReceiver,
                         'ArrayBuffer.prototype.slice', result);
   }
-  // TODO(littledan): Check for a detached ArrayBuffer
+  // Checks for detached source/target ArrayBuffers are done inside of
+  // %ArrayBufferSliceImpl; the reordering of checks does not violate
+  // the spec because all exceptions thrown are TypeErrors.
   if (result === this) {
     throw MakeTypeError(kArrayBufferSpeciesThis);
   }
@@ -82,6 +85,13 @@
   return result;
 }
 
+
+function ArrayBufferSpecies() {
+  return this;
+}
+
+utils.InstallGetter(GlobalArrayBuffer, speciesSymbol, ArrayBufferSpecies);
+
 utils.InstallGetter(GlobalArrayBuffer.prototype, "byteLength",
                     ArrayBufferGetByteLen);
 
diff --git a/src/js/collection.js b/src/js/collection.js
index 0d7195d..bbb7ed2 100644
--- a/src/js/collection.js
+++ b/src/js/collection.js
@@ -19,6 +19,7 @@
 var MapIterator;
 var NumberIsNaN;
 var SetIterator;
+var speciesSymbol = utils.ImportNow("species_symbol");
 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
 
 utils.Import(function(from) {
@@ -255,6 +256,12 @@
   }
 }
 
+
+function SetSpecies() {
+  return this;
+}
+
+
 // -------------------------------------------------------------------
 
 %SetCode(GlobalSet, SetConstructor);
@@ -266,6 +273,8 @@
 
 %FunctionSetLength(SetForEach, 1);
 
+utils.InstallGetter(GlobalSet, speciesSymbol, SetSpecies);
+
 // Set up the non-enumerable functions on the Set prototype object.
 utils.InstallGetter(GlobalSet.prototype, "size", SetGetSize);
 utils.InstallFunctions(GlobalSet.prototype, DONT_ENUM, [
@@ -435,6 +444,11 @@
   }
 }
 
+
+function MapSpecies() {
+  return this;
+}
+
 // -------------------------------------------------------------------
 
 %SetCode(GlobalMap, MapConstructor);
@@ -446,6 +460,8 @@
 
 %FunctionSetLength(MapForEach, 1);
 
+utils.InstallGetter(GlobalMap, speciesSymbol, MapSpecies);
+
 // Set up the non-enumerable functions on the Map prototype object.
 utils.InstallGetter(GlobalMap.prototype, "size", MapGetSize);
 utils.InstallFunctions(GlobalMap.prototype, DONT_ENUM, [
diff --git a/src/js/generator.js b/src/js/generator.js
deleted file mode 100644
index 3dcdcc0..0000000
--- a/src/js/generator.js
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(function(global, utils) {
-
-"use strict";
-
-%CheckIsBootstrapping();
-
-// -------------------------------------------------------------------
-// Imports
-
-var GeneratorFunctionPrototype = utils.ImportNow("GeneratorFunctionPrototype");
-var GeneratorFunction = utils.ImportNow("GeneratorFunction");
-var GlobalFunction = global.Function;
-var MakeTypeError;
-var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
-
-utils.Import(function(from) {
-  MakeTypeError = from.MakeTypeError;
-});
-
-// ----------------------------------------------------------------------------
-
-// Generator functions and objects are specified by ES6, sections 15.19.3 and
-// 15.19.4.
-
-function GeneratorObjectNext(value) {
-  if (!IS_GENERATOR(this)) {
-    throw MakeTypeError(kIncompatibleMethodReceiver,
-                        '[Generator].prototype.next', this);
-  }
-
-  var continuation = %GeneratorGetContinuation(this);
-  if (continuation > 0) {
-    // Generator is suspended.
-    DEBUG_PREPARE_STEP_IN_IF_STEPPING(this);
-    return %_GeneratorNext(this, value);
-  } else if (continuation == 0) {
-    // Generator is already closed.
-    return %_CreateIterResultObject(UNDEFINED, true);
-  } else {
-    // Generator is running.
-    throw MakeTypeError(kGeneratorRunning);
-  }
-}
-
-
-function GeneratorObjectReturn(value) {
-  if (!IS_GENERATOR(this)) {
-    throw MakeTypeError(kIncompatibleMethodReceiver,
-                        '[Generator].prototype.return', this);
-  }
-
-  var continuation = %GeneratorGetContinuation(this);
-  if (continuation > 0) {
-    // Generator is suspended.
-    DEBUG_PREPARE_STEP_IN_IF_STEPPING(this);
-    return %_GeneratorReturn(this, value);
-  } else if (continuation == 0) {
-    // Generator is already closed.
-    return %_CreateIterResultObject(value, true);
-  } else {
-    // Generator is running.
-    throw MakeTypeError(kGeneratorRunning);
-  }
-}
-
-
-function GeneratorObjectThrow(exn) {
-  if (!IS_GENERATOR(this)) {
-    throw MakeTypeError(kIncompatibleMethodReceiver,
-                        '[Generator].prototype.throw', this);
-  }
-
-  var continuation = %GeneratorGetContinuation(this);
-  if (continuation > 0) {
-    // Generator is suspended.
-    DEBUG_PREPARE_STEP_IN_IF_STEPPING(this);
-    return %_GeneratorThrow(this, exn);
-  } else if (continuation == 0) {
-    // Generator is already closed.
-    throw exn;
-  } else {
-    // Generator is running.
-    throw MakeTypeError(kGeneratorRunning);
-  }
-}
-
-// ----------------------------------------------------------------------------
-
-// None of the three resume operations (Runtime_GeneratorNext,
-// Runtime_GeneratorReturn, Runtime_GeneratorThrow) is supported by
-// Crankshaft or TurboFan.  Disable optimization of wrappers here.
-%NeverOptimizeFunction(GeneratorObjectNext);
-%NeverOptimizeFunction(GeneratorObjectReturn);
-%NeverOptimizeFunction(GeneratorObjectThrow);
-
-// Set up non-enumerable functions on the generator prototype object.
-var GeneratorObjectPrototype = GeneratorFunctionPrototype.prototype;
-utils.InstallFunctions(GeneratorObjectPrototype,
-                       DONT_ENUM,
-                      ["next", GeneratorObjectNext,
-                       "return", GeneratorObjectReturn,
-                       "throw", GeneratorObjectThrow]);
-
-%AddNamedProperty(GeneratorObjectPrototype, "constructor",
-    GeneratorFunctionPrototype, DONT_ENUM | READ_ONLY);
-%AddNamedProperty(GeneratorObjectPrototype,
-    toStringTagSymbol, "Generator", DONT_ENUM | READ_ONLY);
-%InternalSetPrototype(GeneratorFunctionPrototype, GlobalFunction.prototype);
-%AddNamedProperty(GeneratorFunctionPrototype,
-    toStringTagSymbol, "GeneratorFunction", DONT_ENUM | READ_ONLY);
-%AddNamedProperty(GeneratorFunctionPrototype, "constructor",
-    GeneratorFunction, DONT_ENUM | READ_ONLY);
-%InternalSetPrototype(GeneratorFunction, GlobalFunction);
-
-})
diff --git a/src/js/harmony-async-await.js b/src/js/harmony-async-await.js
new file mode 100644
index 0000000..c6705ef
--- /dev/null
+++ b/src/js/harmony-async-await.js
@@ -0,0 +1,43 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function(global, utils, extrasUtils) {
+
+"use strict";
+
+%CheckIsBootstrapping();
+
+// -------------------------------------------------------------------
+// Imports
+
+var AsyncFunctionNext;
+var AsyncFunctionThrow;
+var PromiseReject;
+var PromiseResolve;
+var PromiseThen;
+
+utils.Import(function(from) {
+  AsyncFunctionNext = from.AsyncFunctionNext;
+  AsyncFunctionThrow = from.AsyncFunctionThrow;
+  PromiseReject = from.PromiseCreateRejected;
+  PromiseResolve = from.PromiseCreateResolved;
+  PromiseThen = from.PromiseThen;
+});
+
+// -------------------------------------------------------------------
+
+function AsyncFunctionAwait(generator, value) {
+  return %_Call(
+      PromiseThen, PromiseResolve(value),
+      function(sentValue) {
+        return %_Call(AsyncFunctionNext, generator, sentValue);
+      },
+      function(sentError) {
+        return %_Call(AsyncFunctionThrow, generator, sentError);
+      });
+}
+
+%InstallToContext([ "async_function_await", AsyncFunctionAwait ]);
+
+})
diff --git a/src/js/harmony-atomics.js b/src/js/harmony-atomics.js
index 9f80227..8372903 100644
--- a/src/js/harmony-atomics.js
+++ b/src/js/harmony-atomics.js
@@ -62,19 +62,6 @@
   return %_AtomicsCompareExchange(sta, index, oldValue, newValue);
 }
 
-function AtomicsLoadJS(sta, index) {
-  CheckSharedIntegerTypedArray(sta);
-  index = ValidateIndex(index, %_TypedArrayGetLength(sta));
-  return %_AtomicsLoad(sta, index);
-}
-
-function AtomicsStoreJS(sta, index, value) {
-  CheckSharedIntegerTypedArray(sta);
-  index = ValidateIndex(index, %_TypedArrayGetLength(sta));
-  value = TO_NUMBER(value);
-  return %_AtomicsStore(sta, index, value);
-}
-
 function AtomicsAddJS(ia, index, value) {
   CheckSharedIntegerTypedArray(ia);
   index = ValidateIndex(index, %_TypedArrayGetLength(ia));
@@ -161,13 +148,9 @@
 
 // -------------------------------------------------------------------
 
-function AtomicsConstructor() {}
+var Atomics = global.Atomics;
 
-var Atomics = new AtomicsConstructor();
-
-%InternalSetPrototype(Atomics, GlobalObject.prototype);
-%AddNamedProperty(global, "Atomics", Atomics, DONT_ENUM);
-%FunctionSetInstanceClassName(AtomicsConstructor, 'Atomics');
+// The Atomics global is defined by the bootstrapper.
 
 %AddNamedProperty(Atomics, toStringTagSymbol, "Atomics", READ_ONLY | DONT_ENUM);
 
@@ -179,9 +162,9 @@
 ]);
 
 utils.InstallFunctions(Atomics, DONT_ENUM, [
+  // TODO(binji): remove the rest of the (non futex) Atomics functions as they
+  // become builtins.
   "compareExchange", AtomicsCompareExchangeJS,
-  "load", AtomicsLoadJS,
-  "store", AtomicsStoreJS,
   "add", AtomicsAddJS,
   "sub", AtomicsSubJS,
   "and", AtomicsAndJS,
diff --git a/src/js/harmony-object-observe.js b/src/js/harmony-object-observe.js
deleted file mode 100644
index 95dd298..0000000
--- a/src/js/harmony-object-observe.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(function(global, utils) {
-
-"use strict";
-
-%CheckIsBootstrapping();
-
-var ObserveArrayMethods = utils.ImportNow("ObserveArrayMethods");
-var ObserveObjectMethods = utils.ImportNow("ObserveObjectMethods");;
-
-utils.InstallFunctions(global.Object, DONT_ENUM, ObserveObjectMethods);
-utils.InstallFunctions(global.Array, DONT_ENUM, ObserveArrayMethods);
-
-})
diff --git a/src/js/harmony-regexp-exec.js b/src/js/harmony-regexp-exec.js
deleted file mode 100644
index e2eece9..0000000
--- a/src/js/harmony-regexp-exec.js
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(function(global, utils) {
-
-%CheckIsBootstrapping();
-
-// -------------------------------------------------------------------
-// Imports
-
-var GlobalRegExp = global.RegExp;
-var RegExpSubclassExecJS = utils.ImportNow("RegExpSubclassExecJS");
-var RegExpSubclassMatch = utils.ImportNow("RegExpSubclassMatch");
-var RegExpSubclassReplace = utils.ImportNow("RegExpSubclassReplace");
-var RegExpSubclassSearch = utils.ImportNow("RegExpSubclassSearch");
-var RegExpSubclassSplit = utils.ImportNow("RegExpSubclassSplit");
-var RegExpSubclassTest = utils.ImportNow("RegExpSubclassTest");
-var matchSymbol = utils.ImportNow("match_symbol");
-var replaceSymbol = utils.ImportNow("replace_symbol");
-var searchSymbol = utils.ImportNow("search_symbol");
-var splitSymbol = utils.ImportNow("split_symbol");
-
-utils.OverrideFunction(GlobalRegExp.prototype, "exec",
-                       RegExpSubclassExecJS, true);
-utils.OverrideFunction(GlobalRegExp.prototype, matchSymbol,
-                       RegExpSubclassMatch, true);
-utils.OverrideFunction(GlobalRegExp.prototype, replaceSymbol,
-                       RegExpSubclassReplace, true);
-utils.OverrideFunction(GlobalRegExp.prototype, searchSymbol,
-                       RegExpSubclassSearch, true);
-utils.OverrideFunction(GlobalRegExp.prototype, splitSymbol,
-                       RegExpSubclassSplit, true);
-utils.OverrideFunction(GlobalRegExp.prototype, "test",
-                       RegExpSubclassTest, true);
-
-})
diff --git a/src/js/harmony-species.js b/src/js/harmony-species.js
deleted file mode 100644
index 426ac46..0000000
--- a/src/js/harmony-species.js
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(function(global, utils, extrasUtils) {
-
-"use strict";
-
-%CheckIsBootstrapping();
-
-var GlobalArray = global.Array;
-// It is important that this file is run after src/js/typedarray.js,
-// otherwise GlobalTypedArray would be Object, and we would break
-// old versions of Zepto.
-var GlobalTypedArray = global.Uint8Array.__proto__;
-var GlobalMap = global.Map;
-var GlobalSet = global.Set;
-var GlobalArrayBuffer = global.ArrayBuffer;
-var GlobalPromise = global.Promise;
-var GlobalRegExp = global.RegExp;
-var speciesSymbol = utils.ImportNow("species_symbol");
-
-function ArraySpecies() {
-  return this;
-}
-
-function TypedArraySpecies() {
-  return this;
-}
-
-function MapSpecies() {
-  return this;
-}
-
-function SetSpecies() {
-  return this;
-}
-
-function ArrayBufferSpecies() {
-  return this;
-}
-
-function PromiseSpecies() {
-  return this;
-}
-
-function RegExpSpecies() {
-  return this;
-}
-
-utils.InstallGetter(GlobalArray, speciesSymbol, ArraySpecies, DONT_ENUM);
-utils.InstallGetter(GlobalTypedArray, speciesSymbol, TypedArraySpecies, DONT_ENUM);
-utils.InstallGetter(GlobalMap, speciesSymbol, MapSpecies, DONT_ENUM);
-utils.InstallGetter(GlobalSet, speciesSymbol, SetSpecies, DONT_ENUM);
-utils.InstallGetter(GlobalArrayBuffer, speciesSymbol, ArrayBufferSpecies,
-                    DONT_ENUM);
-utils.InstallGetter(GlobalPromise, speciesSymbol, PromiseSpecies, DONT_ENUM);
-utils.InstallGetter(GlobalRegExp, speciesSymbol, RegExpSpecies, DONT_ENUM);
-
-});
diff --git a/src/js/harmony-string-padding.js b/src/js/harmony-string-padding.js
index a6c6c47..dc59823 100644
--- a/src/js/harmony-string-padding.js
+++ b/src/js/harmony-string-padding.js
@@ -30,7 +30,8 @@
   } else {
     fillString = TO_STRING(fillString);
     if (fillString === "") {
-      fillString = " ";
+      // If filler is the empty String, return S.
+      return "";
     }
   }
 
diff --git a/src/js/harmony-unicode-regexps.js b/src/js/harmony-unicode-regexps.js
deleted file mode 100644
index 16d06ba..0000000
--- a/src/js/harmony-unicode-regexps.js
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(function(global, utils) {
-
-'use strict';
-
-%CheckIsBootstrapping();
-
-// -------------------------------------------------------------------
-// Imports
-
-var GlobalRegExp = global.RegExp;
-var GlobalRegExpPrototype = GlobalRegExp.prototype;
-var MakeTypeError;
-
-utils.Import(function(from) {
-  MakeTypeError = from.MakeTypeError;
-});
-
-// -------------------------------------------------------------------
-
-// ES6 21.2.5.15.
-function RegExpGetUnicode() {
-  if (!IS_REGEXP(this)) {
-    // TODO(littledan): Remove this RegExp compat workaround
-    if (this === GlobalRegExpPrototype) {
-      %IncrementUseCounter(kRegExpPrototypeUnicodeGetter);
-      return UNDEFINED;
-    }
-    throw MakeTypeError(kRegExpNonRegExp, "RegExp.prototype.unicode");
-  }
-  return TO_BOOLEAN(REGEXP_UNICODE(this));
-}
-%SetForceInlineFlag(RegExpGetUnicode);
-
-utils.InstallGetter(GlobalRegExp.prototype, 'unicode', RegExpGetUnicode);
-
-})
diff --git a/src/js/i18n.js b/src/js/i18n.js
index 845289a..6c769a7 100644
--- a/src/js/i18n.js
+++ b/src/js/i18n.js
@@ -20,23 +20,20 @@
 var ArrayIndexOf;
 var ArrayJoin;
 var ArrayPush;
-var GlobalBoolean = global.Boolean;
+var FLAG_intl_extra;
 var GlobalDate = global.Date;
 var GlobalNumber = global.Number;
 var GlobalRegExp = global.RegExp;
 var GlobalString = global.String;
 var InstallFunctions = utils.InstallFunctions;
 var InstallGetter = utils.InstallGetter;
-var InternalPackedArray = utils.InternalPackedArray;
+var InternalArray = utils.InternalArray;
 var InternalRegExpMatch;
 var InternalRegExpReplace
-var IsFinite;
 var IsNaN;
 var MakeError;
 var MakeRangeError;
 var MakeTypeError;
-var ObjectDefineProperties = utils.ImportNow("ObjectDefineProperties");
-var ObjectDefineProperty = utils.ImportNow("ObjectDefineProperty");
 var ObjectHasOwnProperty = utils.ImportNow("ObjectHasOwnProperty");
 var OverrideFunction = utils.OverrideFunction;
 var patternSymbol = utils.ImportNow("intl_pattern_symbol");
@@ -52,7 +49,6 @@
   ArrayIndexOf = from.ArrayIndexOf;
   ArrayJoin = from.ArrayJoin;
   ArrayPush = from.ArrayPush;
-  IsFinite = from.IsFinite;
   IsNaN = from.IsNaN;
   MakeError = from.MakeError;
   MakeRangeError = from.MakeRangeError;
@@ -66,6 +62,10 @@
   StringSubstring = from.StringSubstring;
 });
 
+utils.ImportFromExperimental(function(from) {
+  FLAG_intl_extra = from.FLAG_intl_extra;
+});
+
 // Utilities for definitions
 
 function InstallFunction(object, name, func) {
@@ -84,11 +84,11 @@
 /**
  * Adds bound method to the prototype of the given object.
  */
-function AddBoundMethod(obj, methodName, implementation, length) {
+function AddBoundMethod(obj, methodName, implementation, length, type) {
   %CheckIsBootstrapping();
   var internalName = %CreatePrivateSymbol(methodName);
   var getter = function() {
-    if (!%IsInitializedIntlObject(this)) {
+    if (!%IsInitializedIntlObjectOfType(this, type)) {
       throw MakeTypeError(kMethodCalledOnWrongObject, methodName);
     }
     if (IS_UNDEFINED(this[internalName])) {
@@ -144,6 +144,13 @@
  */
 var DEFAULT_ICU_LOCALE = UNDEFINED;
 
+function GetDefaultICULocaleJS() {
+  if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) {
+    DEFAULT_ICU_LOCALE = %GetDefaultICULocale();
+  }
+  return DEFAULT_ICU_LOCALE;
+}
+
 /**
  * Unicode extension regular expression.
  */
@@ -275,7 +282,7 @@
 
   var matcher = options.localeMatcher;
   if (!IS_UNDEFINED(matcher)) {
-    matcher = GlobalString(matcher);
+    matcher = TO_STRING(matcher);
     if (matcher !== 'lookup' && matcher !== 'best fit') {
       throw MakeRangeError(kLocaleMatcher, matcher);
     }
@@ -307,7 +314,7 @@
  * Locales appear in the same order in the returned list as in the input list.
  */
 function lookupSupportedLocalesOf(requestedLocales, availableLocales) {
-  var matchedLocales = [];
+  var matchedLocales = new InternalArray();
   for (var i = 0; i < requestedLocales.length; ++i) {
     // Remove -u- extension.
     var locale = InternalRegExpReplace(
@@ -356,13 +363,13 @@
       var value = options[property];
       switch (type) {
         case 'boolean':
-          value = GlobalBoolean(value);
+          value = TO_BOOLEAN(value);
           break;
         case 'string':
-          value = GlobalString(value);
+          value = TO_STRING(value);
           break;
         case 'number':
-          value = GlobalNumber(value);
+          value = TO_NUMBER(value);
           break;
         default:
           throw MakeError(kWrongValueType);
@@ -448,11 +455,7 @@
   }
 
   // Didn't find a match, return default.
-  if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) {
-    DEFAULT_ICU_LOCALE = %GetDefaultICULocale();
-  }
-
-  return {'locale': DEFAULT_ICU_LOCALE, 'extension': '', 'position': -1};
+  return {'locale': GetDefaultICULocaleJS(), 'extension': '', 'position': -1};
 }
 
 
@@ -517,7 +520,7 @@
   var extension = '';
 
   var updateExtension = function updateExtension(key, value) {
-    return '-' + key + '-' + GlobalString(value);
+    return '-' + key + '-' + TO_STRING(value);
   }
 
   var updateProperty = function updateProperty(property, type, value) {
@@ -567,21 +570,23 @@
 
 
 /**
- * Converts all OwnProperties into
+ * Given an array-like, outputs an Array with the numbered
+ * properties copied over and defined
  * configurable: false, writable: false, enumerable: true.
  */
-function freezeArray(array) {
-  var l = array.length;
+function freezeArray(input) {
+  var array = [];
+  var l = input.length;
   for (var i = 0; i < l; i++) {
-    if (i in array) {
-      ObjectDefineProperty(array, i, {value: array[i],
-                                      configurable: false,
-                                      writable: false,
-                                      enumerable: true});
+    if (i in input) {
+      %object_define_property(array, i, {value: input[i],
+                                         configurable: false,
+                                         writable: false,
+                                         enumerable: true});
     }
   }
 
-  ObjectDefineProperty(array, 'length', {value: l, writable: false});
+  %object_define_property(array, 'length', {value: l, writable: false});
   return array;
 }
 
@@ -643,8 +648,8 @@
  * Configurable is false by default.
  */
 function defineWEProperty(object, property, value) {
-  ObjectDefineProperty(object, property,
-                       {value: value, writable: true, enumerable: true});
+  %object_define_property(object, property,
+                          {value: value, writable: true, enumerable: true});
 }
 
 
@@ -663,10 +668,10 @@
  * Defines a property and sets writable, enumerable and configurable to true.
  */
 function defineWECProperty(object, property, value) {
-  ObjectDefineProperty(object, property, {value: value,
-                                          writable: true,
-                                          enumerable: true,
-                                          configurable: true});
+  %object_define_property(object, property, {value: value,
+                                             writable: true,
+                                             enumerable: true,
+                                             configurable: true});
 }
 
 
@@ -722,21 +727,24 @@
  */
 function canonicalizeLanguageTag(localeID) {
   // null is typeof 'object' so we have to do extra check.
-  if (typeof localeID !== 'string' && typeof localeID !== 'object' ||
+  if ((!IS_STRING(localeID) && !IS_RECEIVER(localeID)) ||
       IS_NULL(localeID)) {
     throw MakeTypeError(kLanguageID);
   }
 
-  var localeString = GlobalString(localeID);
+  // Optimize for the most common case; a language code alone in
+  // the canonical form/lowercase (e.g. "en", "fil").
+  if (IS_STRING(localeID) &&
+      !IS_NULL(InternalRegExpMatch(/^[a-z]{2,3}$/, localeID))) {
+    return localeID;
+  }
+
+  var localeString = TO_STRING(localeID);
 
   if (isValidLanguageTag(localeString) === false) {
     throw MakeRangeError(kInvalidLanguageTag, localeString);
   }
 
-  // This call will strip -kn but not -kn-true extensions.
-  // ICU bug filled - http://bugs.icu-project.org/trac/ticket/9265.
-  // TODO(cira): check if -u-kn-true-kc-true-kh-true still throws after
-  // upgrade to ICU 4.9.
   var tag = %CanonicalizeLanguageTag(localeString);
   if (tag === 'invalid-tag') {
     throw MakeRangeError(kInvalidLanguageTag, localeString);
@@ -751,11 +759,8 @@
  * Throws on locales that are not well formed BCP47 tags.
  */
 function initializeLocaleList(locales) {
-  var seen = [];
-  if (IS_UNDEFINED(locales)) {
-    // Constructor is called without arguments.
-    seen = [];
-  } else {
+  var seen = new InternalArray();
+  if (!IS_UNDEFINED(locales)) {
     // We allow single string localeID.
     if (typeof locales === 'string') {
       %_Call(ArrayPush, seen, canonicalizeLanguageTag(locales));
@@ -810,8 +815,8 @@
   // Skip language since it can match variant regex, so we start from 1.
   // We are matching i-klingon here, but that's ok, since i-klingon-klingon
   // is not valid and would fail LANGUAGE_TAG_RE test.
-  var variants = [];
-  var extensions = [];
+  var variants = new InternalArray();
+  var extensions = new InternalArray();
   var parts = %_Call(StringSplit, locale, '-');
   for (var i = 1; i < parts.length; i++) {
     var value = parts[i];
@@ -965,8 +970,8 @@
   // We define all properties C++ code may produce, to prevent security
   // problems. If malicious user decides to redefine Object.prototype.locale
   // we can't just use plain x.locale = 'us' or in C++ Set("locale", "us").
-  // ObjectDefineProperties will either succeed defining or throw an error.
-  var resolved = ObjectDefineProperties({}, {
+  // %object_define_properties will either succeed defining or throw an error.
+  var resolved = %object_define_properties({}, {
     caseFirst: {writable: true},
     collation: {value: internalOptions.collation, writable: true},
     ignorePunctuation: {writable: true},
@@ -985,7 +990,9 @@
   // Writable, configurable and enumerable are set to false by default.
   %MarkAsInitializedIntlObjectOfType(collator, 'collator', internalCollator);
   collator[resolvedSymbol] = resolved;
-  ObjectDefineProperty(collator, 'resolved', resolvedAccessor);
+  if (FLAG_intl_extra) {
+    %object_define_property(collator, 'resolved', resolvedAccessor);
+  }
 
   return collator;
 }
@@ -1068,11 +1075,11 @@
  */
 function compare(collator, x, y) {
   return %InternalCompare(%GetImplFromInitializedIntlObject(collator),
-                          GlobalString(x), GlobalString(y));
+                          TO_STRING(x), TO_STRING(y));
 };
 
 
-AddBoundMethod(Intl.Collator, 'compare', compare, 2);
+AddBoundMethod(Intl.Collator, 'compare', compare, 2, 'collator');
 
 /**
  * Verifies that the input is a well-formed ISO 4217 currency code.
@@ -1092,8 +1099,8 @@
 function getNumberOption(options, property, min, max, fallback) {
   var value = options[property];
   if (!IS_UNDEFINED(value)) {
-    value = GlobalNumber(value);
-    if (IsNaN(value) || value < min || value > max) {
+    value = TO_NUMBER(value);
+    if (NUMBER_IS_NAN(value) || value < min || value > max) {
       throw MakeRangeError(kPropertyValueOutOfRange, property);
     }
     return %math_floor(value);
@@ -1198,7 +1205,7 @@
                              getOption, internalOptions);
 
   var requestedLocale = locale.locale + extension;
-  var resolved = ObjectDefineProperties({}, {
+  var resolved = %object_define_properties({}, {
     currency: {writable: true},
     currencyDisplay: {writable: true},
     locale: {writable: true},
@@ -1206,7 +1213,6 @@
     minimumFractionDigits: {writable: true},
     minimumIntegerDigits: {writable: true},
     numberingSystem: {writable: true},
-    pattern: patternAccessor,
     requestedLocale: {value: requestedLocale, writable: true},
     style: {value: internalOptions.style, writable: true},
     useGrouping: {writable: true}
@@ -1222,13 +1228,16 @@
                                       resolved);
 
   if (internalOptions.style === 'currency') {
-    ObjectDefineProperty(resolved, 'currencyDisplay', {value: currencyDisplay,
-                                                       writable: true});
+    %object_define_property(resolved, 'currencyDisplay',
+        {value: currencyDisplay, writable: true});
   }
 
   %MarkAsInitializedIntlObjectOfType(numberFormat, 'numberformat', formatter);
   numberFormat[resolvedSymbol] = resolved;
-  ObjectDefineProperty(numberFormat, 'resolved', resolvedAccessor);
+  if (FLAG_intl_extra) {
+    %object_define_property(resolved, 'pattern', patternAccessor);
+    %object_define_property(numberFormat, 'resolved', resolvedAccessor);
+  }
 
   return numberFormat;
 }
@@ -1334,14 +1343,12 @@
 /**
  * Returns a Number that represents string value that was passed in.
  */
-function parseNumber(formatter, value) {
+function IntlParseNumber(formatter, value) {
   return %InternalNumberParse(%GetImplFromInitializedIntlObject(formatter),
-                              GlobalString(value));
+                              TO_STRING(value));
 }
 
-
-AddBoundMethod(Intl.NumberFormat, 'format', formatNumber, 1);
-AddBoundMethod(Intl.NumberFormat, 'v8Parse', parseNumber, 1);
+AddBoundMethod(Intl.NumberFormat, 'format', formatNumber, 1, 'numberformat');
 
 /**
  * Returns a string that matches LDML representation of the options object.
@@ -1508,33 +1515,33 @@
   }
 
   if (needsDefault && (defaults === 'date' || defaults === 'all')) {
-    ObjectDefineProperty(options, 'year', {value: 'numeric',
-                                           writable: true,
-                                           enumerable: true,
-                                           configurable: true});
-    ObjectDefineProperty(options, 'month', {value: 'numeric',
-                                            writable: true,
-                                            enumerable: true,
-                                            configurable: true});
-    ObjectDefineProperty(options, 'day', {value: 'numeric',
-                                          writable: true,
-                                          enumerable: true,
-                                          configurable: true});
+    %object_define_property(options, 'year', {value: 'numeric',
+                                              writable: true,
+                                              enumerable: true,
+                                              configurable: true});
+    %object_define_property(options, 'month', {value: 'numeric',
+                                               writable: true,
+                                               enumerable: true,
+                                               configurable: true});
+    %object_define_property(options, 'day', {value: 'numeric',
+                                             writable: true,
+                                             enumerable: true,
+                                             configurable: true});
   }
 
   if (needsDefault && (defaults === 'time' || defaults === 'all')) {
-    ObjectDefineProperty(options, 'hour', {value: 'numeric',
-                                           writable: true,
-                                           enumerable: true,
-                                           configurable: true});
-    ObjectDefineProperty(options, 'minute', {value: 'numeric',
-                                             writable: true,
-                                             enumerable: true,
-                                             configurable: true});
-    ObjectDefineProperty(options, 'second', {value: 'numeric',
-                                             writable: true,
-                                             enumerable: true,
-                                             configurable: true});
+    %object_define_property(options, 'hour', {value: 'numeric',
+                                              writable: true,
+                                              enumerable: true,
+                                              configurable: true});
+    %object_define_property(options, 'minute', {value: 'numeric',
+                                                writable: true,
+                                                enumerable: true,
+                                                configurable: true});
+    %object_define_property(options, 'second', {value: 'numeric',
+                                                writable: true,
+                                                enumerable: true,
+                                                configurable: true});
   }
 
   return options;
@@ -1592,7 +1599,7 @@
                              getOption, internalOptions);
 
   var requestedLocale = locale.locale + extension;
-  var resolved = ObjectDefineProperties({}, {
+  var resolved = %object_define_properties({}, {
     calendar: {writable: true},
     day: {writable: true},
     era: {writable: true},
@@ -1603,7 +1610,6 @@
     month: {writable: true},
     numberingSystem: {writable: true},
     [patternSymbol]: {writable: true},
-    pattern: patternAccessor,
     requestedLocale: {value: requestedLocale, writable: true},
     second: {writable: true},
     timeZone: {writable: true},
@@ -1622,7 +1628,10 @@
 
   %MarkAsInitializedIntlObjectOfType(dateFormat, 'dateformat', formatter);
   dateFormat[resolvedSymbol] = resolved;
-  ObjectDefineProperty(dateFormat, 'resolved', resolvedAccessor);
+  if (FLAG_intl_extra) {
+    %object_define_property(resolved, 'pattern', patternAccessor);
+    %object_define_property(dateFormat, 'resolved', resolvedAccessor);
+  }
 
   return dateFormat;
 }
@@ -1743,7 +1752,7 @@
     dateMs = TO_NUMBER(dateValue);
   }
 
-  if (!IsFinite(dateMs)) throw MakeRangeError(kDateRange);
+  if (!NUMBER_IS_FINITE(dateMs)) throw MakeRangeError(kDateRange);
 
   return %InternalDateFormat(%GetImplFromInitializedIntlObject(formatter),
                              new GlobalDate(dateMs));
@@ -1756,15 +1765,14 @@
  * DateTimeFormat.
  * Returns undefined if date string cannot be parsed.
  */
-function parseDate(formatter, value) {
+function IntlParseDate(formatter, value) {
   return %InternalDateParse(%GetImplFromInitializedIntlObject(formatter),
-                            GlobalString(value));
+                            TO_STRING(value));
 }
 
 
 // 0 because date is optional argument.
-AddBoundMethod(Intl.DateTimeFormat, 'format', formatDate, 0);
-AddBoundMethod(Intl.DateTimeFormat, 'v8Parse', parseDate, 1);
+AddBoundMethod(Intl.DateTimeFormat, 'format', formatDate, 0, 'dateformat');
 
 
 /**
@@ -1826,7 +1834,7 @@
     'type', 'string', ['character', 'word', 'sentence', 'line'], 'word'));
 
   var locale = resolveLocale('breakiterator', locales, options);
-  var resolved = ObjectDefineProperties({}, {
+  var resolved = %object_define_properties({}, {
     requestedLocale: {value: locale.locale, writable: true},
     type: {value: internalOptions.type, writable: true},
     locale: {writable: true}
@@ -1839,7 +1847,9 @@
   %MarkAsInitializedIntlObjectOfType(iterator, 'breakiterator',
                                      internalIterator);
   iterator[resolvedSymbol] = resolved;
-  ObjectDefineProperty(iterator, 'resolved', resolvedAccessor);
+  if (FLAG_intl_extra) {
+    %object_define_property(iterator, 'resolved', resolvedAccessor);
+  }
 
   return iterator;
 }
@@ -1914,7 +1924,7 @@
  */
 function adoptText(iterator, text) {
   %BreakIteratorAdoptText(%GetImplFromInitializedIntlObject(iterator),
-                          GlobalString(text));
+                          TO_STRING(text));
 }
 
 
@@ -1950,11 +1960,13 @@
 }
 
 
-AddBoundMethod(Intl.v8BreakIterator, 'adoptText', adoptText, 1);
-AddBoundMethod(Intl.v8BreakIterator, 'first', first, 0);
-AddBoundMethod(Intl.v8BreakIterator, 'next', next, 0);
-AddBoundMethod(Intl.v8BreakIterator, 'current', current, 0);
-AddBoundMethod(Intl.v8BreakIterator, 'breakType', breakType, 0);
+AddBoundMethod(Intl.v8BreakIterator, 'adoptText', adoptText, 1,
+               'breakiterator');
+AddBoundMethod(Intl.v8BreakIterator, 'first', first, 0, 'breakiterator');
+AddBoundMethod(Intl.v8BreakIterator, 'next', next, 0, 'breakiterator');
+AddBoundMethod(Intl.v8BreakIterator, 'current', current, 0, 'breakiterator');
+AddBoundMethod(Intl.v8BreakIterator, 'breakType', breakType, 0,
+               'breakiterator');
 
 // Save references to Intl objects and methods we use, for added security.
 var savedObjects = {
@@ -1976,6 +1988,23 @@
   'dateformattime': UNDEFINED,
 };
 
+function clearDefaultObjects() {
+  defaultObjects['dateformatall'] = UNDEFINED;
+  defaultObjects['dateformatdate'] = UNDEFINED;
+  defaultObjects['dateformattime'] = UNDEFINED;
+}
+
+var date_cache_version = 0;
+
+function checkDateCacheCurrent() {
+  var new_date_cache_version = %DateCacheVersion();
+  if (new_date_cache_version == date_cache_version) {
+    return;
+  }
+  date_cache_version = new_date_cache_version;
+
+  clearDefaultObjects();
+}
 
 /**
  * Returns cached or newly created instance of a given service.
@@ -1984,6 +2013,7 @@
 function cachedOrNewService(service, locales, options, defaults) {
   var useOptions = (IS_UNDEFINED(defaults)) ? options : defaults;
   if (IS_UNDEFINED(locales) && IS_UNDEFINED(options)) {
+    checkDateCacheCurrent();
     if (IS_UNDEFINED(defaultObjects[service])) {
       defaultObjects[service] = new savedObjects[service](locales, useOptions);
     }
@@ -1992,6 +2022,37 @@
   return new savedObjects[service](locales, useOptions);
 }
 
+function LocaleConvertCase(s, locales, isToUpper) {
+  // ECMA 402 section 13.1.2 steps 1 through 12.
+  var language;
+  // Optimize for the most common two cases. initializeLocaleList() can handle
+  // them as well, but it's rather slow accounting for over 60% of
+  // toLocale{U,L}Case() and about 40% of toLocale{U,L}Case("<locale>").
+  if (IS_UNDEFINED(locales)) {
+    language = GetDefaultICULocaleJS();
+  } else if (IS_STRING(locales)) {
+    language = canonicalizeLanguageTag(locales);
+  } else {
+    var locales = initializeLocaleList(locales);
+    language = locales.length > 0 ? locales[0] : GetDefaultICULocaleJS();
+  }
+
+  // StringSplit is slower than this.
+  var pos = %_Call(StringIndexOf, language, '-');
+  if (pos != -1) {
+    language = %_Call(StringSubstring, language, 0, pos);
+  }
+
+  var CUSTOM_CASE_LANGUAGES = ['az', 'el', 'lt', 'tr'];
+  var langIndex = %_Call(ArrayIndexOf, CUSTOM_CASE_LANGUAGES, language);
+  if (langIndex == -1) {
+    // language-independent case conversion.
+    return isToUpper ? %StringToUpperCaseI18N(s) : %StringToLowerCaseI18N(s);
+  }
+  return %StringLocaleConvertCase(s, isToUpper,
+                                  CUSTOM_CASE_LANGUAGES[langIndex]);
+}
+
 /**
  * Compares this and that, and returns less than 0, 0 or greater than 0 value.
  * Overrides the built-in method.
@@ -2044,6 +2105,56 @@
   }
 );
 
+function ToLowerCaseI18N() {
+  if (!IS_UNDEFINED(new.target)) {
+    throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor);
+  }
+  CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLowerCase");
+  var s = TO_STRING(this);
+  return %StringToLowerCaseI18N(s);
+}
+
+function ToUpperCaseI18N() {
+  if (!IS_UNDEFINED(new.target)) {
+    throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor);
+  }
+  CHECK_OBJECT_COERCIBLE(this, "String.prototype.toUpperCase");
+  var s = TO_STRING(this);
+  return %StringToUpperCaseI18N(s);
+}
+
+function ToLocaleLowerCaseI18N(locales) {
+  if (!IS_UNDEFINED(new.target)) {
+    throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor);
+  }
+  CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLocaleLowerCase");
+  return LocaleConvertCase(TO_STRING(this), locales, false);
+}
+
+%FunctionSetLength(ToLocaleLowerCaseI18N, 0);
+
+function ToLocaleUpperCaseI18N(locales) {
+  if (!IS_UNDEFINED(new.target)) {
+    throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor);
+  }
+  CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLocaleUpperCase");
+  return LocaleConvertCase(TO_STRING(this), locales, true);
+}
+
+%FunctionSetLength(ToLocaleUpperCaseI18N, 0);
+
+%FunctionRemovePrototype(ToLowerCaseI18N);
+%FunctionRemovePrototype(ToUpperCaseI18N);
+%FunctionRemovePrototype(ToLocaleLowerCaseI18N);
+%FunctionRemovePrototype(ToLocaleUpperCaseI18N);
+
+utils.Export(function(to) {
+  to.ToLowerCaseI18N = ToLowerCaseI18N;
+  to.ToUpperCaseI18N = ToUpperCaseI18N;
+  to.ToLocaleLowerCaseI18N = ToLocaleLowerCaseI18N;
+  to.ToLocaleUpperCaseI18N = ToLocaleUpperCaseI18N;
+});
+
 
 /**
  * Formats a Number object (this) using locale and options values.
@@ -2138,4 +2249,10 @@
   }
 );
 
+utils.Export(function(to) {
+  to.AddBoundMethod = AddBoundMethod;
+  to.IntlParseDate = IntlParseDate;
+  to.IntlParseNumber = IntlParseNumber;
+});
+
 })
diff --git a/src/js/icu-case-mapping.js b/src/js/icu-case-mapping.js
new file mode 100644
index 0000000..9806249
--- /dev/null
+++ b/src/js/icu-case-mapping.js
@@ -0,0 +1,24 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function(global, utils) {
+"use strict";
+
+%CheckIsBootstrapping();
+
+var GlobalString = global.String;
+var OverrideFunction = utils.OverrideFunction;
+var ToLowerCaseI18N = utils.ImportNow("ToLowerCaseI18N");
+var ToUpperCaseI18N = utils.ImportNow("ToUpperCaseI18N");
+var ToLocaleLowerCaseI18N = utils.ImportNow("ToLocaleLowerCaseI18N");
+var ToLocaleUpperCaseI18N = utils.ImportNow("ToLocaleUpperCaseI18N");
+
+OverrideFunction(GlobalString.prototype, 'toLowerCase', ToLowerCaseI18N, true);
+OverrideFunction(GlobalString.prototype, 'toUpperCase', ToUpperCaseI18N, true);
+OverrideFunction(GlobalString.prototype, 'toLocaleLowerCase',
+                 ToLocaleLowerCaseI18N, true);
+OverrideFunction(GlobalString.prototype, 'toLocaleUpperCase',
+                 ToLocaleUpperCaseI18N, true);
+
+})
diff --git a/src/js/intl-extra.js b/src/js/intl-extra.js
new file mode 100644
index 0000000..a4d2256
--- /dev/null
+++ b/src/js/intl-extra.js
@@ -0,0 +1,22 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function(global, utils) {
+
+"use strict";
+
+%CheckIsBootstrapping();
+
+var GlobalIntl = global.Intl;
+
+var AddBoundMethod = utils.ImportNow("AddBoundMethod");
+var IntlParseDate = utils.ImportNow("IntlParseDate");
+var IntlParseNumber = utils.ImportNow("IntlParseNumber");
+
+AddBoundMethod(GlobalIntl.DateTimeFormat, 'v8Parse', IntlParseDate, 1,
+               'dateformat');
+AddBoundMethod(GlobalIntl.NumberFormat, 'v8Parse', IntlParseNumber, 1,
+               'numberformat');
+
+})
diff --git a/src/js/json.js b/src/js/json.js
deleted file mode 100644
index c6dbed9..0000000
--- a/src/js/json.js
+++ /dev/null
@@ -1,297 +0,0 @@
-// Copyright 2009 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(function(global, utils) {
-
-"use strict";
-
-%CheckIsBootstrapping();
-
-// -------------------------------------------------------------------
-// Imports
-
-var GlobalDate = global.Date;
-var GlobalJSON = global.JSON;
-var GlobalSet = global.Set;
-var InternalArray = utils.InternalArray;
-var MakeTypeError;
-var MaxSimple;
-var MinSimple;
-var ObjectHasOwnProperty;
-var Stack;
-var StackHas;
-var StackPop;
-var StackPush;
-var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
-
-utils.Import(function(from) {
-  MakeTypeError = from.MakeTypeError;
-  MaxSimple = from.MaxSimple;
-  MinSimple = from.MinSimple;
-  ObjectHasOwnProperty = from.ObjectHasOwnProperty;
-  Stack = from.Stack;
-  StackHas = from.StackHas;
-  StackPop = from.StackPop;
-  StackPush = from.StackPush;
-});
-
-// -------------------------------------------------------------------
-
-function CreateDataProperty(o, p, v) {
-  var desc = {value: v, enumerable: true, writable: true, configurable: true};
-  return %reflect_define_property(o, p, desc);
-}
-
-
-function InternalizeJSONProperty(holder, name, reviver) {
-  var val = holder[name];
-  if (IS_RECEIVER(val)) {
-    if (%is_arraylike(val)) {
-      var length = TO_LENGTH(val.length);
-      for (var i = 0; i < length; i++) {
-        var newElement =
-            InternalizeJSONProperty(val, %_NumberToString(i), reviver);
-        if (IS_UNDEFINED(newElement)) {
-          %reflect_delete_property(val, i);
-        } else {
-          CreateDataProperty(val, i, newElement);
-        }
-      }
-    } else {
-      var keys = %object_keys(val);
-      for (var i = 0; i < keys.length; i++) {
-        var p = keys[i];
-        var newElement = InternalizeJSONProperty(val, p, reviver);
-        if (IS_UNDEFINED(newElement)) {
-          %reflect_delete_property(val, p);
-        } else {
-          CreateDataProperty(val, p, newElement);
-        }
-      }
-    }
-  }
-  return %_Call(reviver, holder, name, val);
-}
-
-
-function JSONParse(text, reviver) {
-  var unfiltered = %ParseJson(text);
-  if (IS_CALLABLE(reviver)) {
-    return InternalizeJSONProperty({'': unfiltered}, '', reviver);
-  } else {
-    return unfiltered;
-  }
-}
-
-
-function SerializeArray(value, replacer, stack, indent, gap) {
-  if (StackHas(stack, value)) throw MakeTypeError(kCircularStructure);
-  StackPush(stack, value);
-  var stepback = indent;
-  indent += gap;
-  var partial = new InternalArray();
-  var len = TO_LENGTH(value.length);
-  for (var i = 0; i < len; i++) {
-    var strP = JSONSerialize(%_NumberToString(i), value, replacer, stack,
-                             indent, gap);
-    if (IS_UNDEFINED(strP)) {
-      strP = "null";
-    }
-    partial.push(strP);
-  }
-  var final;
-  if (gap == "") {
-    final = "[" + partial.join(",") + "]";
-  } else if (partial.length > 0) {
-    var separator = ",\n" + indent;
-    final = "[\n" + indent + partial.join(separator) + "\n" +
-        stepback + "]";
-  } else {
-    final = "[]";
-  }
-  StackPop(stack);
-  return final;
-}
-
-
-function SerializeObject(value, replacer, stack, indent, gap) {
-  if (StackHas(stack, value)) throw MakeTypeError(kCircularStructure);
-  StackPush(stack, value);
-  var stepback = indent;
-  indent += gap;
-  var partial = new InternalArray();
-  if (IS_ARRAY(replacer)) {
-    var length = replacer.length;
-    for (var i = 0; i < length; i++) {
-      var p = replacer[i];
-      var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
-      if (!IS_UNDEFINED(strP)) {
-        var member = %QuoteJSONString(p) + ":";
-        if (gap != "") member += " ";
-        member += strP;
-        partial.push(member);
-      }
-    }
-  } else {
-    var keys = %object_keys(value);
-    for (var i = 0; i < keys.length; i++) {
-      var p = keys[i];
-      var strP = JSONSerialize(p, value, replacer, stack, indent, gap);
-      if (!IS_UNDEFINED(strP)) {
-        var member = %QuoteJSONString(p) + ":";
-        if (gap != "") member += " ";
-        member += strP;
-        partial.push(member);
-      }
-    }
-  }
-  var final;
-  if (gap == "") {
-    final = "{" + partial.join(",") + "}";
-  } else if (partial.length > 0) {
-    var separator = ",\n" + indent;
-    final = "{\n" + indent + partial.join(separator) + "\n" +
-        stepback + "}";
-  } else {
-    final = "{}";
-  }
-  StackPop(stack);
-  return final;
-}
-
-
-function JSONSerialize(key, holder, replacer, stack, indent, gap) {
-  var value = holder[key];
-  if (IS_RECEIVER(value)) {
-    var toJSON = value.toJSON;
-    if (IS_CALLABLE(toJSON)) {
-      value = %_Call(toJSON, value, key);
-    }
-  }
-  if (IS_CALLABLE(replacer)) {
-    value = %_Call(replacer, holder, key, value);
-  }
-  if (IS_STRING(value)) {
-    return %QuoteJSONString(value);
-  } else if (IS_NUMBER(value)) {
-    return JSON_NUMBER_TO_STRING(value);
-  } else if (IS_BOOLEAN(value)) {
-    return value ? "true" : "false";
-  } else if (IS_NULL(value)) {
-    return "null";
-  } else if (IS_RECEIVER(value) && !IS_CALLABLE(value)) {
-    // Non-callable object. If it's a primitive wrapper, it must be unwrapped.
-    if (%is_arraylike(value)) {
-      return SerializeArray(value, replacer, stack, indent, gap);
-    } else if (IS_NUMBER_WRAPPER(value)) {
-      value = TO_NUMBER(value);
-      return JSON_NUMBER_TO_STRING(value);
-    } else if (IS_STRING_WRAPPER(value)) {
-      return %QuoteJSONString(TO_STRING(value));
-    } else if (IS_BOOLEAN_WRAPPER(value)) {
-      return %_ValueOf(value) ? "true" : "false";
-    } else {
-      return SerializeObject(value, replacer, stack, indent, gap);
-    }
-  }
-  // Undefined or a callable object.
-  return UNDEFINED;
-}
-
-
-function JSONStringify(value, replacer, space) {
-  if (arguments.length === 1 && !IS_PROXY(value)) {
-    return %BasicJSONStringify(value);
-  }
-  if (!IS_CALLABLE(replacer) && %is_arraylike(replacer)) {
-    var property_list = new InternalArray();
-    var seen_properties = new GlobalSet();
-    var length = TO_LENGTH(replacer.length);
-    for (var i = 0; i < length; i++) {
-      var v = replacer[i];
-      var item;
-      if (IS_STRING(v)) {
-        item = v;
-      } else if (IS_NUMBER(v)) {
-        item = %_NumberToString(v);
-      } else if (IS_STRING_WRAPPER(v) || IS_NUMBER_WRAPPER(v)) {
-        item = TO_STRING(v);
-      } else {
-        continue;
-      }
-      if (!seen_properties.has(item)) {
-        property_list.push(item);
-        seen_properties.add(item);
-      }
-    }
-    replacer = property_list;
-  }
-  if (IS_OBJECT(space)) {
-    // Unwrap 'space' if it is wrapped
-    if (IS_NUMBER_WRAPPER(space)) {
-      space = TO_NUMBER(space);
-    } else if (IS_STRING_WRAPPER(space)) {
-      space = TO_STRING(space);
-    }
-  }
-  var gap;
-  if (IS_NUMBER(space)) {
-    space = MaxSimple(0, MinSimple(TO_INTEGER(space), 10));
-    gap = %_SubString("          ", 0, space);
-  } else if (IS_STRING(space)) {
-    if (space.length > 10) {
-      gap = %_SubString(space, 0, 10);
-    } else {
-      gap = space;
-    }
-  } else {
-    gap = "";
-  }
-  if (!IS_CALLABLE(replacer) && !property_list && !gap && !IS_PROXY(value)) {
-    return %BasicJSONStringify(value);
-  }
-  return JSONSerialize('', {'': value}, replacer, new Stack(), "", gap);
-}
-
-// -------------------------------------------------------------------
-
-%AddNamedProperty(GlobalJSON, toStringTagSymbol, "JSON", READ_ONLY | DONT_ENUM);
-
-// Set up non-enumerable properties of the JSON object.
-utils.InstallFunctions(GlobalJSON, DONT_ENUM, [
-  "parse", JSONParse,
-  "stringify", JSONStringify
-]);
-
-// -------------------------------------------------------------------
-// Date.toJSON
-
-// 20.3.4.37 Date.prototype.toJSON ( key )
-function DateToJSON(key) {
-  var o = TO_OBJECT(this);
-  var tv = TO_PRIMITIVE_NUMBER(o);
-  if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) {
-    return null;
-  }
-  return o.toISOString();
-}
-
-// Set up non-enumerable functions of the Date prototype object.
-utils.InstallFunctions(GlobalDate.prototype, DONT_ENUM, [
-  "toJSON", DateToJSON
-]);
-
-// -------------------------------------------------------------------
-// JSON Builtins
-
-function JsonSerializeAdapter(key, object) {
-  var holder = {};
-  holder[key] = object;
-  // No need to pass the actual holder since there is no replacer function.
-  return JSONSerialize(key, holder, UNDEFINED, new Stack(), "", "");
-}
-
-%InstallToContext(["json_serialize_adapter", JsonSerializeAdapter]);
-
-})
diff --git a/src/js/macros.py b/src/js/macros.py
index a4c7f53..c6ed019 100644
--- a/src/js/macros.py
+++ b/src/js/macros.py
@@ -110,9 +110,9 @@
 macro NUMBER_IS_FINITE(arg) = (%_IsSmi(%IS_VAR(arg)) || ((arg == arg) && (arg != 1/0) && (arg != -1/0)));
 macro TO_BOOLEAN(arg) = (!!(arg));
 macro TO_INTEGER(arg) = (%_ToInteger(arg));
-macro TO_INTEGER_MAP_MINUS_ZERO(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToIntegerMapMinusZero(arg));
 macro TO_INT32(arg) = ((arg) | 0);
 macro TO_UINT32(arg) = ((arg) >>> 0);
+macro INVERT_NEG_ZERO(arg) = ((arg) + 0);
 macro TO_LENGTH(arg) = (%_ToLength(arg));
 macro TO_STRING(arg) = (%_ToString(arg));
 macro TO_NUMBER(arg) = (%_ToNumber(arg));
@@ -123,7 +123,6 @@
 macro TO_NAME(arg) = (%_ToName(arg));
 macro JSON_NUMBER_TO_STRING(arg) = ((%_IsSmi(%IS_VAR(arg)) || arg - arg == 0) ? %_NumberToString(arg) : "null");
 macro HAS_OWN_PROPERTY(obj, key) = (%_Call(ObjectHasOwnProperty, obj, key));
-macro HAS_INDEX(array, index, is_array) = ((is_array && %_HasFastPackedElements(%IS_VAR(array)) && (index < array.length)) ||  (index in array));
 
 # Private names.
 macro IS_PRIVATE(sym) = (%SymbolIsPrivate(sym));
@@ -174,16 +173,6 @@
 # 1-based so index of 1 returns the first capture
 macro OVERRIDE_CAPTURE(override, index) = ((override)[(index)]);
 
-# PropertyDescriptor return value indices - must match
-# PropertyDescriptorIndices in runtime-object.cc.
-define IS_ACCESSOR_INDEX = 0;
-define VALUE_INDEX = 1;
-define GETTER_INDEX = 2;
-define SETTER_INDEX = 3;
-define WRITABLE_INDEX = 4;
-define ENUMERABLE_INDEX = 5;
-define CONFIGURABLE_INDEX = 6;
-
 # For messages.js
 # Matches Script::Type from objects.h
 define TYPE_NATIVE = 0;
@@ -238,7 +227,6 @@
 
 # Check whether debug is active.
 define DEBUG_IS_ACTIVE = (%_DebugIsActive() != 0);
-macro DEBUG_PREPARE_STEP_IN_IF_STEPPING(function) = if (%_DebugIsActive() != 0) %DebugPrepareStepInIfStepping(function);
 
 # SharedFlag equivalents
 define kNotShared = false;
@@ -251,7 +239,6 @@
 define kMarkDequeOverflow = 3;
 define kStoreBufferOverflow = 4;
 define kSlotsBufferOverflow = 5;
-define kObjectObserve = 6;
 define kForcedGC = 7;
 define kSloppyMode = 8;
 define kStrictMode = 9;
diff --git a/src/js/math.js b/src/js/math.js
index f8ad6b1..74d3aa6 100644
--- a/src/js/math.js
+++ b/src/js/math.js
@@ -16,7 +16,6 @@
 var GlobalFloat64Array = global.Float64Array;
 var GlobalMath = global.Math;
 var GlobalObject = global.Object;
-var InternalArray = utils.InternalArray;
 var NaN = %GetRootNaN();
 var nextRandomIndex = 0;
 var randomNumbers = UNDEFINED;
@@ -30,25 +29,6 @@
   return (x > 0) ? x : 0 - x;
 }
 
-// ECMA 262 - 15.8.2.5
-// The naming of y and x matches the spec, as does the order in which
-// ToNumber (valueOf) is called.
-function MathAtan2JS(y, x) {
-  y = +y;
-  x = +x;
-  return %MathAtan2(y, x);
-}
-
-// ECMA 262 - 15.8.2.8
-function MathExp(x) {
-  return %MathExpRT(TO_NUMBER(x));
-}
-
-// ECMA 262 - 15.8.2.10
-function MathLog(x) {
-  return %_MathLogRT(TO_NUMBER(x));
-}
-
 // ECMA 262 - 15.8.2.13
 function MathPowJS(x, y) {
   return %_MathPow(TO_NUMBER(x), TO_NUMBER(y));
@@ -63,7 +43,11 @@
   // first two elements are reserved for the PRNG state.
   if (nextRandomIndex <= kRandomNumberStart) {
     randomNumbers = %GenerateRandomNumbers(randomNumbers);
-    nextRandomIndex = randomNumbers.length;
+    if (%_IsTypedArray(randomNumbers)) {
+      nextRandomIndex = %_TypedArrayGetLength(randomNumbers);
+    } else {
+      nextRandomIndex = randomNumbers.length;
+    }
   }
   return randomNumbers[--nextRandomIndex];
 }
@@ -71,7 +55,7 @@
 function MathRandomRaw() {
   if (nextRandomIndex <= kRandomNumberStart) {
     randomNumbers = %GenerateRandomNumbers(randomNumbers);
-    nextRandomIndex = randomNumbers.length;
+    nextRandomIndex = %_TypedArrayGetLength(randomNumbers);
   }
   return %_DoubleLo(randomNumbers[--nextRandomIndex]) & 0x3FFFFFFF;
 }
@@ -90,9 +74,9 @@
   x = TO_NUMBER(x);
   // Idempotent for NaN, +/-0 and +/-Infinity.
   if (x === 0 || !NUMBER_IS_FINITE(x)) return x;
-  if (x > 0) return MathLog(x + %math_sqrt(x * x + 1));
+  if (x > 0) return %math_log(x + %math_sqrt(x * x + 1));
   // This is to prevent numerical errors caused by large negative x.
-  return -MathLog(-x + %math_sqrt(x * x + 1));
+  return -%math_log(-x + %math_sqrt(x * x + 1));
 }
 
 // ES6 draft 09-27-13, section 20.2.2.3.
@@ -101,17 +85,7 @@
   if (x < 1) return NaN;
   // Idempotent for NaN and +Infinity.
   if (!NUMBER_IS_FINITE(x)) return x;
-  return MathLog(x + %math_sqrt(x + 1) * %math_sqrt(x - 1));
-}
-
-// ES6 draft 09-27-13, section 20.2.2.7.
-function MathAtanh(x) {
-  x = TO_NUMBER(x);
-  // Idempotent for +/-0.
-  if (x === 0) return x;
-  // Returns NaN for NaN and +/- Infinity.
-  if (!NUMBER_IS_FINITE(x)) return NaN;
-  return 0.5 * MathLog((1 + x) / (1 - x));
+  return %math_log(x + %math_sqrt(x + 1) * %math_sqrt(x - 1));
 }
 
 // ES6 draft 09-27-13, section 20.2.2.17.
@@ -143,29 +117,6 @@
   return %math_sqrt(sum) * max;
 }
 
-// ES6 draft 09-27-13, section 20.2.2.9.
-// Cube root approximation, refer to: http://metamerist.com/cbrt/cbrt.htm
-// Using initial approximation adapted from Kahan's cbrt and 4 iterations
-// of Newton's method.
-function MathCbrt(x) {
-  x = TO_NUMBER(x);
-  if (x == 0 || !NUMBER_IS_FINITE(x)) return x;
-  return x >= 0 ? CubeRoot(x) : -CubeRoot(-x);
-}
-
-macro NEWTON_ITERATION_CBRT(x, approx)
-  (1.0 / 3.0) * (x / (approx * approx) + 2 * approx);
-endmacro
-
-function CubeRoot(x) {
-  var approx_hi = %math_floor(%_DoubleHi(x) / 3) + 0x2A9F7893;
-  var approx = %_ConstructDouble(approx_hi | 0, 0);
-  approx = NEWTON_ITERATION_CBRT(x, approx);
-  approx = NEWTON_ITERATION_CBRT(x, approx);
-  approx = NEWTON_ITERATION_CBRT(x, approx);
-  return NEWTON_ITERATION_CBRT(x, approx);
-}
-
 // -------------------------------------------------------------------
 
 %InstallToContext([
@@ -176,15 +127,6 @@
 
 // Set up math constants.
 utils.InstallConstants(GlobalMath, [
-  // ECMA-262, section 15.8.1.1.
-  "E", 2.7182818284590452354,
-  // ECMA-262, section 15.8.1.2.
-  "LN10", 2.302585092994046,
-  // ECMA-262, section 15.8.1.3.
-  "LN2", 0.6931471805599453,
-  // ECMA-262, section 15.8.1.4.
-  "LOG2E", 1.4426950408889634,
-  "LOG10E", 0.4342944819032518,
   "PI", 3.1415926535897932,
   "SQRT1_2", 0.7071067811865476,
   "SQRT2", 1.4142135623730951
@@ -195,20 +137,13 @@
 utils.InstallFunctions(GlobalMath, DONT_ENUM, [
   "random", MathRandom,
   "abs", MathAbs,
-  "exp", MathExp,
-  "log", MathLog,
-  "atan2", MathAtan2JS,
   "pow", MathPowJS,
   "sign", MathSign,
   "asinh", MathAsinh,
   "acosh", MathAcosh,
-  "atanh", MathAtanh,
   "hypot", MathHypot,
-  "cbrt", MathCbrt
 ]);
 
-%SetForceInlineFlag(MathAbs);
-%SetForceInlineFlag(MathAtan2JS);
 %SetForceInlineFlag(MathRandom);
 %SetForceInlineFlag(MathSign);
 
@@ -217,7 +152,6 @@
 
 utils.Export(function(to) {
   to.MathAbs = MathAbs;
-  to.MathExp = MathExp;
   to.IntRandom = MathRandomRaw;
 });
 
diff --git a/src/js/messages.js b/src/js/messages.js
index f8cb967..24d8d2b 100644
--- a/src/js/messages.js
+++ b/src/js/messages.js
@@ -23,6 +23,10 @@
     utils.ImportNow("call_site_position_symbol");
 var callSiteStrictSymbol =
     utils.ImportNow("call_site_strict_symbol");
+var callSiteWasmObjectSymbol =
+    utils.ImportNow("call_site_wasm_obj_symbol");
+var callSiteWasmFunctionIndexSymbol =
+    utils.ImportNow("call_site_wasm_func_index_symbol");
 var Float32x4ToString;
 var formattedStackTraceSymbol =
     utils.ImportNow("formatted_stack_trace_symbol");
@@ -32,14 +36,11 @@
 var Int8x16ToString;
 var InternalArray = utils.InternalArray;
 var internalErrorSymbol = utils.ImportNow("internal_error_symbol");
-var ObjectDefineProperty;
 var ObjectHasOwnProperty;
 var ObjectToString = utils.ImportNow("object_to_string");
 var Script = utils.ImportNow("Script");
 var stackTraceSymbol = utils.ImportNow("stack_trace_symbol");
-var StringCharAt;
 var StringIndexOf;
-var StringSubstring;
 var SymbolToString;
 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
 var Uint16x8ToString;
@@ -55,11 +56,8 @@
   Int16x8ToString = from.Int16x8ToString;
   Int32x4ToString = from.Int32x4ToString;
   Int8x16ToString = from.Int8x16ToString;
-  ObjectDefineProperty = from.ObjectDefineProperty;
   ObjectHasOwnProperty = from.ObjectHasOwnProperty;
-  StringCharAt = from.StringCharAt;
   StringIndexOf = from.StringIndexOf;
-  StringSubstring = from.StringSubstring;
   SymbolToString = from.SymbolToString;
   Uint16x8ToString = from.Uint16x8ToString;
   Uint32x4ToString = from.Uint32x4ToString;
@@ -214,209 +212,26 @@
   var start_position = %MessageGetStartPosition(message);
   var location = script.locationFromPosition(start_position, true);
   if (location == null) return "";
-  return location.sourceText();
+  return location.sourceText;
 }
 
 
 /**
- * Find a line number given a specific source position.
- * @param {number} position The source position.
- * @return {number} 0 if input too small, -1 if input too large,
-       else the line number.
- */
-function ScriptLineFromPosition(position) {
-  var lower = 0;
-  var upper = this.lineCount() - 1;
-  var line_ends = this.line_ends;
-
-  // We'll never find invalid positions so bail right away.
-  if (position > line_ends[upper]) {
-    return -1;
-  }
-
-  // This means we don't have to safe-guard indexing line_ends[i - 1].
-  if (position <= line_ends[0]) {
-    return 0;
-  }
-
-  // Binary search to find line # from position range.
-  while (upper >= 1) {
-    var i = (lower + upper) >> 1;
-
-    if (position > line_ends[i]) {
-      lower = i + 1;
-    } else if (position <= line_ends[i - 1]) {
-      upper = i - 1;
-    } else {
-      return i;
-    }
-  }
-
-  return -1;
-}
-
-/**
  * Get information on a specific source position.
+ * Returns an object with the following following properties:
+ *   script     : script object for the source
+ *   line       : source line number
+ *   column     : source column within the line
+ *   position   : position within the source
+ *   sourceText : a string containing the current line
  * @param {number} position The source position
  * @param {boolean} include_resource_offset Set to true to have the resource
  *     offset added to the location
- * @return {SourceLocation}
- *     If line is negative or not in the source null is returned.
+ * @return If line is negative or not in the source null is returned.
  */
 function ScriptLocationFromPosition(position,
                                     include_resource_offset) {
-  var line = this.lineFromPosition(position);
-  if (line == -1) return null;
-
-  // Determine start, end and column.
-  var line_ends = this.line_ends;
-  var start = line == 0 ? 0 : line_ends[line - 1] + 1;
-  var end = line_ends[line];
-  if (end > 0 && %_Call(StringCharAt, this.source, end - 1) == '\r') {
-    end--;
-  }
-  var column = position - start;
-
-  // Adjust according to the offset within the resource.
-  if (include_resource_offset) {
-    line += this.line_offset;
-    if (line == this.line_offset) {
-      column += this.column_offset;
-    }
-  }
-
-  return new SourceLocation(this, position, line, column, start, end);
-}
-
-
-/**
- * Get information on a specific source line and column possibly offset by a
- * fixed source position. This function is used to find a source position from
- * a line and column position. The fixed source position offset is typically
- * used to find a source position in a function based on a line and column in
- * the source for the function alone. The offset passed will then be the
- * start position of the source for the function within the full script source.
- * @param {number} opt_line The line within the source. Default value is 0
- * @param {number} opt_column The column in within the line. Default value is 0
- * @param {number} opt_offset_position The offset from the begining of the
- *     source from where the line and column calculation starts.
- *     Default value is 0
- * @return {SourceLocation}
- *     If line is negative or not in the source null is returned.
- */
-function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) {
-  // Default is the first line in the script. Lines in the script is relative
-  // to the offset within the resource.
-  var line = 0;
-  if (!IS_UNDEFINED(opt_line)) {
-    line = opt_line - this.line_offset;
-  }
-
-  // Default is first column. If on the first line add the offset within the
-  // resource.
-  var column = opt_column || 0;
-  if (line == 0) {
-    column -= this.column_offset;
-  }
-
-  var offset_position = opt_offset_position || 0;
-  if (line < 0 || column < 0 || offset_position < 0) return null;
-  if (line == 0) {
-    return this.locationFromPosition(offset_position + column, false);
-  } else {
-    // Find the line where the offset position is located.
-    var offset_line = this.lineFromPosition(offset_position);
-
-    if (offset_line == -1 || offset_line + line >= this.lineCount()) {
-      return null;
-    }
-
-    return this.locationFromPosition(
-        this.line_ends[offset_line + line - 1] + 1 + column);  // line > 0 here.
-  }
-}
-
-
-/**
- * Get a slice of source code from the script. The boundaries for the slice is
- * specified in lines.
- * @param {number} opt_from_line The first line (zero bound) in the slice.
- *     Default is 0
- * @param {number} opt_to_column The last line (zero bound) in the slice (non
- *     inclusive). Default is the number of lines in the script
- * @return {SourceSlice} The source slice or null of the parameters where
- *     invalid
- */
-function ScriptSourceSlice(opt_from_line, opt_to_line) {
-  var from_line = IS_UNDEFINED(opt_from_line) ? this.line_offset
-                                              : opt_from_line;
-  var to_line = IS_UNDEFINED(opt_to_line) ? this.line_offset + this.lineCount()
-                                          : opt_to_line;
-
-  // Adjust according to the offset within the resource.
-  from_line -= this.line_offset;
-  to_line -= this.line_offset;
-  if (from_line < 0) from_line = 0;
-  if (to_line > this.lineCount()) to_line = this.lineCount();
-
-  // Check parameters.
-  if (from_line >= this.lineCount() ||
-      to_line < 0 ||
-      from_line > to_line) {
-    return null;
-  }
-
-  var line_ends = this.line_ends;
-  var from_position = from_line == 0 ? 0 : line_ends[from_line - 1] + 1;
-  var to_position = to_line == 0 ? 0 : line_ends[to_line - 1] + 1;
-
-  // Return a source slice with line numbers re-adjusted to the resource.
-  return new SourceSlice(this,
-                         from_line + this.line_offset,
-                         to_line + this.line_offset,
-                          from_position, to_position);
-}
-
-
-function ScriptSourceLine(opt_line) {
-  // Default is the first line in the script. Lines in the script are relative
-  // to the offset within the resource.
-  var line = 0;
-  if (!IS_UNDEFINED(opt_line)) {
-    line = opt_line - this.line_offset;
-  }
-
-  // Check parameter.
-  if (line < 0 || this.lineCount() <= line) {
-    return null;
-  }
-
-  // Return the source line.
-  var line_ends = this.line_ends;
-  var start = line == 0 ? 0 : line_ends[line - 1] + 1;
-  var end = line_ends[line];
-  return %_Call(StringSubstring, this.source, start, end);
-}
-
-
-/**
- * Returns the number of source lines.
- * @return {number}
- *     Number of source lines.
- */
-function ScriptLineCount() {
-  // Return number of source lines.
-  return this.line_ends.length;
-}
-
-
-/**
- * Returns the position of the nth line end.
- * @return {number}
- *     Zero-based position of the nth line end in the script.
- */
-function ScriptLineEnd(n) {
-  return this.line_ends[n];
+  return %ScriptPositionInfo(this, position, !!include_resource_offset);
 }
 
 
@@ -441,113 +256,15 @@
     "name",
     "source_url",
     "source_mapping_url",
-    "line_ends",
     "line_offset",
     "column_offset"
   ], [
-    "lineFromPosition", ScriptLineFromPosition,
     "locationFromPosition", ScriptLocationFromPosition,
-    "locationFromLine", ScriptLocationFromLine,
-    "sourceSlice", ScriptSourceSlice,
-    "sourceLine", ScriptSourceLine,
-    "lineCount", ScriptLineCount,
     "nameOrSourceURL", ScriptNameOrSourceURL,
-    "lineEnd", ScriptLineEnd
   ]
 );
 
 
-/**
- * Class for source location. A source location is a position within some
- * source with the following properties:
- *   script   : script object for the source
- *   line     : source line number
- *   column   : source column within the line
- *   position : position within the source
- *   start    : position of start of source context (inclusive)
- *   end      : position of end of source context (not inclusive)
- * Source text for the source context is the character interval
- * [start, end[. In most cases end will point to a newline character.
- * It might point just past the final position of the source if the last
- * source line does not end with a newline character.
- * @param {Script} script The Script object for which this is a location
- * @param {number} position Source position for the location
- * @param {number} line The line number for the location
- * @param {number} column The column within the line for the location
- * @param {number} start Source position for start of source context
- * @param {number} end Source position for end of source context
- * @constructor
- */
-function SourceLocation(script, position, line, column, start, end) {
-  this.script = script;
-  this.position = position;
-  this.line = line;
-  this.column = column;
-  this.start = start;
-  this.end = end;
-}
-
-
-/**
- * Get the source text for a SourceLocation
- * @return {String}
- *     Source text for this location.
- */
-function SourceLocationSourceText() {
-  return %_Call(StringSubstring, this.script.source, this.start, this.end);
-}
-
-
-utils.SetUpLockedPrototype(SourceLocation,
-  ["script", "position", "line", "column", "start", "end"],
-  ["sourceText", SourceLocationSourceText]
-);
-
-
-/**
- * Class for a source slice. A source slice is a part of a script source with
- * the following properties:
- *   script        : script object for the source
- *   from_line     : line number for the first line in the slice
- *   to_line       : source line number for the last line in the slice
- *   from_position : position of the first character in the slice
- *   to_position   : position of the last character in the slice
- * The to_line and to_position are not included in the slice, that is the lines
- * in the slice are [from_line, to_line[. Likewise the characters in the slice
- * are [from_position, to_position[.
- * @param {Script} script The Script object for the source slice
- * @param {number} from_line
- * @param {number} to_line
- * @param {number} from_position
- * @param {number} to_position
- * @constructor
- */
-function SourceSlice(script, from_line, to_line, from_position, to_position) {
-  this.script = script;
-  this.from_line = from_line;
-  this.to_line = to_line;
-  this.from_position = from_position;
-  this.to_position = to_position;
-}
-
-/**
- * Get the source text for a SourceSlice
- * @return {String} Source text for this slice. The last line will include
- *     the line terminating characters (if any)
- */
-function SourceSliceSourceText() {
-  return %_Call(StringSubstring,
-                this.script.source,
-                this.from_position,
-                this.to_position);
-}
-
-utils.SetUpLockedPrototype(SourceSlice,
-  ["script", "from_line", "to_line", "from_position", "to_position"],
-  ["sourceText", SourceSliceSourceText]
-);
-
-
 function GetStackTraceLine(recv, fun, pos, isGlobal) {
   return new CallSite(recv, fun, pos, false).toString();
 }
@@ -556,22 +273,29 @@
 // Error implementation
 
 function CallSite(receiver, fun, pos, strict_mode) {
-  if (!IS_FUNCTION(fun)) {
-    throw MakeTypeError(kCallSiteExpectsFunction, typeof fun);
+  // For wasm frames, receiver is the wasm object and fun is the function index
+  // instead of an actual function.
+  if (!IS_FUNCTION(fun) && !%IsWasmObject(receiver)) {
+    throw MakeTypeError(kCallSiteExpectsFunction, typeof receiver, typeof fun);
   }
 
   if (IS_UNDEFINED(new.target)) {
     return new CallSite(receiver, fun, pos, strict_mode);
   }
 
-  SET_PRIVATE(this, callSiteReceiverSymbol, receiver);
-  SET_PRIVATE(this, callSiteFunctionSymbol, fun);
+  if (IS_FUNCTION(fun)) {
+    SET_PRIVATE(this, callSiteReceiverSymbol, receiver);
+    SET_PRIVATE(this, callSiteFunctionSymbol, fun);
+  } else {
+    SET_PRIVATE(this, callSiteWasmObjectSymbol, receiver);
+    SET_PRIVATE(this, callSiteWasmFunctionIndexSymbol, TO_UINT32(fun));
+  }
   SET_PRIVATE(this, callSitePositionSymbol, TO_INT32(pos));
   SET_PRIVATE(this, callSiteStrictSymbol, TO_BOOLEAN(strict_mode));
 }
 
 function CheckCallSite(obj, name) {
-  if (!IS_RECEIVER(obj) || !HAS_PRIVATE(obj, callSiteFunctionSymbol)) {
+  if (!IS_RECEIVER(obj) || !HAS_PRIVATE(obj, callSitePositionSymbol)) {
     throw MakeTypeError(kCallSiteMethod, name);
   }
 }
@@ -638,6 +362,9 @@
 }
 
 function CallSiteGetLineNumber() {
+  if (HAS_PRIVATE(this, callSiteWasmObjectSymbol)) {
+    return GET_PRIVATE(this, callSiteWasmFunctionIndexSymbol);
+  }
   CheckCallSite(this, "getLineNumber");
   return %CallSiteGetLineNumberRT(this);
 }
@@ -658,6 +385,14 @@
 }
 
 function CallSiteToString() {
+  if (HAS_PRIVATE(this, callSiteWasmObjectSymbol)) {
+    var funName = this.getFunctionName();
+    var funcIndex = GET_PRIVATE(this, callSiteWasmFunctionIndexSymbol);
+    var pos = this.getPosition();
+    if (IS_NULL(funName)) funName = "<WASM UNNAMED>";
+    return funName + " (<WASM>[" + funcIndex + "]+" + pos + ")";
+  }
+
   var fileName;
   var fileLocation = "";
   if (this.isNative()) {
@@ -795,14 +530,19 @@
 
 
 function GetStackFrames(raw_stack) {
+  var internal_raw_stack = new InternalArray();
+  %MoveArrayContents(raw_stack, internal_raw_stack);
   var frames = new InternalArray();
-  var sloppy_frames = raw_stack[0];
-  for (var i = 1; i < raw_stack.length; i += 4) {
-    var recv = raw_stack[i];
-    var fun = raw_stack[i + 1];
-    var code = raw_stack[i + 2];
-    var pc = raw_stack[i + 3];
-    var pos = %_IsSmi(code) ? code : %FunctionGetPositionForOffset(code, pc);
+  var sloppy_frames = internal_raw_stack[0];
+  for (var i = 1; i < internal_raw_stack.length; i += 4) {
+    var recv = internal_raw_stack[i];
+    var fun = internal_raw_stack[i + 1];
+    var code = internal_raw_stack[i + 2];
+    var pc = internal_raw_stack[i + 3];
+    // For traps in wasm, the bytecode offset is passed as (-1 - offset).
+    // Otherwise, lookup the position from the pc.
+    var pos = IS_NUMBER(fun) && pc < 0 ? (-1 - pc) :
+      %FunctionGetPositionForOffset(code, pc);
     sloppy_frames--;
     frames.push(new CallSite(recv, fun, pos, (sloppy_frames < 0)));
   }
@@ -879,7 +619,7 @@
       if (IS_UNDEFINED(stack_trace)) {
         // Neither formatted nor structured stack trace available.
         // Look further up the prototype chain.
-        holder = %_GetPrototype(holder);
+        holder = %object_get_prototype_of(holder);
         continue;
       }
       formatted_stack_trace = FormatStackTrace(holder, stack_trace);
@@ -995,9 +735,9 @@
 // Define actual captureStackTrace function after everything has been set up.
 captureStackTrace = function captureStackTrace(obj, cons_opt) {
   // Define accessors first, as this may fail and throw.
-  ObjectDefineProperty(obj, 'stack', { get: StackTraceGetter,
-                                       set: StackTraceSetter,
-                                       configurable: true });
+  %object_define_property(obj, 'stack', { get: StackTraceGetter,
+                                          set: StackTraceSetter,
+                                          configurable: true });
   %CollectStackTrace(obj, cons_opt ? cons_opt : captureStackTrace);
 };
 
diff --git a/src/js/object-observe.js b/src/js/object-observe.js
deleted file mode 100644
index 5e256bf..0000000
--- a/src/js/object-observe.js
+++ /dev/null
@@ -1,717 +0,0 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(function(global, utils) {
-
-"use strict";
-
-%CheckIsBootstrapping();
-
-// -------------------------------------------------------------------
-// Imports
-
-var GetHash;
-var GlobalArray = global.Array;
-var GlobalObject = global.Object;
-var InternalArray = utils.InternalArray;
-var MakeTypeError;
-
-utils.Import(function(from) {
-  GetHash = from.GetHash;
-  MakeTypeError = from.MakeTypeError;
-});
-
-// -------------------------------------------------------------------
-
-// Overview:
-//
-// This file contains all of the routing and accounting for Object.observe.
-// User code will interact with these mechanisms via the Object.observe APIs
-// and, as a side effect of mutation objects which are observed. The V8 runtime
-// (both C++ and JS) will interact with these mechanisms primarily by enqueuing
-// proper change records for objects which were mutated. The Object.observe
-// routing and accounting consists primarily of three participants
-//
-// 1) ObjectInfo. This represents the observed state of a given object. It
-//    records what callbacks are observing the object, with what options, and
-//    what "change types" are in progress on the object (i.e. via
-//    notifier.performChange).
-//
-// 2) CallbackInfo. This represents a callback used for observation. It holds
-//    the records which must be delivered to the callback, as well as the global
-//    priority of the callback (which determines delivery order between
-//    callbacks).
-//
-// 3) observationState.pendingObservers. This is the set of observers which
-//    have change records which must be delivered. During "normal" delivery
-//    (i.e. not Object.deliverChangeRecords), this is the mechanism by which
-//    callbacks are invoked in the proper order until there are no more
-//    change records pending to a callback.
-//
-// Note that in order to reduce allocation and processing costs, the
-// implementation of (1) and (2) have "optimized" states which represent
-// common cases which can be handled more efficiently.
-
-var observationState;
-
-var notifierPrototype = {};
-
-// We have to wait until after bootstrapping to grab a reference to the
-// observationState object, since it's not possible to serialize that
-// reference into the snapshot.
-function GetObservationStateJS() {
-  if (IS_UNDEFINED(observationState)) {
-    observationState = %GetObservationState();
-  }
-
-  // TODO(adamk): Consider moving this code into heap.cc
-  if (IS_UNDEFINED(observationState.callbackInfoMap)) {
-    observationState.callbackInfoMap = %ObservationWeakMapCreate();
-    observationState.objectInfoMap = %ObservationWeakMapCreate();
-    observationState.notifierObjectInfoMap = %ObservationWeakMapCreate();
-    observationState.pendingObservers = null;
-    observationState.nextCallbackPriority = 0;
-    observationState.lastMicrotaskId = 0;
-  }
-
-  return observationState;
-}
-
-
-function GetPendingObservers() {
-  return GetObservationStateJS().pendingObservers;
-}
-
-
-function SetPendingObservers(pendingObservers) {
-  GetObservationStateJS().pendingObservers = pendingObservers;
-}
-
-
-function GetNextCallbackPriority() {
-  return GetObservationStateJS().nextCallbackPriority++;
-}
-
-
-function nullProtoObject() {
-  return { __proto__: null };
-}
-
-
-function TypeMapCreate() {
-  return nullProtoObject();
-}
-
-
-function TypeMapAddType(typeMap, type, ignoreDuplicate) {
-  typeMap[type] = ignoreDuplicate ? 1 : (typeMap[type] || 0) + 1;
-}
-
-
-function TypeMapRemoveType(typeMap, type) {
-  typeMap[type]--;
-}
-
-
-function TypeMapCreateFromList(typeList, length) {
-  var typeMap = TypeMapCreate();
-  for (var i = 0; i < length; i++) {
-    TypeMapAddType(typeMap, typeList[i], true);
-  }
-  return typeMap;
-}
-
-
-function TypeMapHasType(typeMap, type) {
-  return !!typeMap[type];
-}
-
-
-function TypeMapIsDisjointFrom(typeMap1, typeMap2) {
-  if (!typeMap1 || !typeMap2)
-    return true;
-
-  for (var type in typeMap1) {
-    if (TypeMapHasType(typeMap1, type) && TypeMapHasType(typeMap2, type))
-      return false;
-  }
-
-  return true;
-}
-
-
-var defaultAcceptTypes = (function() {
-  var defaultTypes = [
-    'add',
-    'update',
-    'delete',
-    'setPrototype',
-    'reconfigure',
-    'preventExtensions'
-  ];
-  return TypeMapCreateFromList(defaultTypes, defaultTypes.length);
-})();
-
-
-// An Observer is a registration to observe an object by a callback with
-// a given set of accept types. If the set of accept types is the default
-// set for Object.observe, the observer is represented as a direct reference
-// to the callback. An observer never changes its accept types and thus never
-// needs to "normalize".
-function ObserverCreate(callback, acceptList) {
-  if (IS_UNDEFINED(acceptList))
-    return callback;
-  var observer = nullProtoObject();
-  observer.callback = callback;
-  observer.accept = acceptList;
-  return observer;
-}
-
-
-function ObserverGetCallback(observer) {
-  return IS_CALLABLE(observer) ? observer : observer.callback;
-}
-
-
-function ObserverGetAcceptTypes(observer) {
-  return IS_CALLABLE(observer) ? defaultAcceptTypes : observer.accept;
-}
-
-
-function ObserverIsActive(observer, objectInfo) {
-  return TypeMapIsDisjointFrom(ObjectInfoGetPerformingTypes(objectInfo),
-                               ObserverGetAcceptTypes(observer));
-}
-
-
-function ObjectInfoGetOrCreate(object) {
-  var objectInfo = ObjectInfoGet(object);
-  if (IS_UNDEFINED(objectInfo)) {
-    if (!IS_PROXY(object)) {
-      %SetIsObserved(object);
-    }
-    objectInfo = {
-      object: object,
-      changeObservers: null,
-      notifier: null,
-      performing: null,
-      performingCount: 0,
-    };
-    %WeakCollectionSet(GetObservationStateJS().objectInfoMap,
-                       object, objectInfo, GetHash(object));
-  }
-  return objectInfo;
-}
-
-
-function ObjectInfoGet(object) {
-  return %WeakCollectionGet(GetObservationStateJS().objectInfoMap, object,
-                            GetHash(object));
-}
-
-
-function ObjectInfoGetFromNotifier(notifier) {
-  return %WeakCollectionGet(GetObservationStateJS().notifierObjectInfoMap,
-                            notifier, GetHash(notifier));
-}
-
-
-function ObjectInfoGetNotifier(objectInfo) {
-  if (IS_NULL(objectInfo.notifier)) {
-    var notifier = { __proto__: notifierPrototype };
-    objectInfo.notifier = notifier;
-    %WeakCollectionSet(GetObservationStateJS().notifierObjectInfoMap,
-                       notifier, objectInfo, GetHash(notifier));
-  }
-
-  return objectInfo.notifier;
-}
-
-
-function ChangeObserversIsOptimized(changeObservers) {
-  return IS_CALLABLE(changeObservers) ||
-         IS_CALLABLE(changeObservers.callback);
-}
-
-
-// The set of observers on an object is called 'changeObservers'. The first
-// observer is referenced directly via objectInfo.changeObservers. When a second
-// is added, changeObservers "normalizes" to become a mapping of callback
-// priority -> observer and is then stored on objectInfo.changeObservers.
-function ObjectInfoNormalizeChangeObservers(objectInfo) {
-  if (ChangeObserversIsOptimized(objectInfo.changeObservers)) {
-    var observer = objectInfo.changeObservers;
-    var callback = ObserverGetCallback(observer);
-    var callbackInfo = CallbackInfoGet(callback);
-    var priority = CallbackInfoGetPriority(callbackInfo);
-    objectInfo.changeObservers = nullProtoObject();
-    objectInfo.changeObservers[priority] = observer;
-  }
-}
-
-
-function ObjectInfoAddObserver(objectInfo, callback, acceptList) {
-  var callbackInfo = CallbackInfoGetOrCreate(callback);
-  var observer = ObserverCreate(callback, acceptList);
-
-  if (!objectInfo.changeObservers) {
-    objectInfo.changeObservers = observer;
-    return;
-  }
-
-  ObjectInfoNormalizeChangeObservers(objectInfo);
-  var priority = CallbackInfoGetPriority(callbackInfo);
-  objectInfo.changeObservers[priority] = observer;
-}
-
-function ObjectInfoRemoveObserver(objectInfo, callback) {
-  if (!objectInfo.changeObservers)
-    return;
-
-  if (ChangeObserversIsOptimized(objectInfo.changeObservers)) {
-    if (callback === ObserverGetCallback(objectInfo.changeObservers))
-      objectInfo.changeObservers = null;
-    return;
-  }
-
-  var callbackInfo = CallbackInfoGet(callback);
-  var priority = CallbackInfoGetPriority(callbackInfo);
-  objectInfo.changeObservers[priority] = null;
-}
-
-function ObjectInfoHasActiveObservers(objectInfo) {
-  if (IS_UNDEFINED(objectInfo) || !objectInfo.changeObservers)
-    return false;
-
-  if (ChangeObserversIsOptimized(objectInfo.changeObservers))
-    return ObserverIsActive(objectInfo.changeObservers, objectInfo);
-
-  for (var priority in objectInfo.changeObservers) {
-    var observer = objectInfo.changeObservers[priority];
-    if (!IS_NULL(observer) && ObserverIsActive(observer, objectInfo))
-      return true;
-  }
-
-  return false;
-}
-
-
-function ObjectInfoAddPerformingType(objectInfo, type) {
-  objectInfo.performing = objectInfo.performing || TypeMapCreate();
-  TypeMapAddType(objectInfo.performing, type);
-  objectInfo.performingCount++;
-}
-
-
-function ObjectInfoRemovePerformingType(objectInfo, type) {
-  objectInfo.performingCount--;
-  TypeMapRemoveType(objectInfo.performing, type);
-}
-
-
-function ObjectInfoGetPerformingTypes(objectInfo) {
-  return objectInfo.performingCount > 0 ? objectInfo.performing : null;
-}
-
-
-function ConvertAcceptListToTypeMap(arg) {
-  // We use undefined as a sentinel for the default accept list.
-  if (IS_UNDEFINED(arg))
-    return arg;
-
-  if (!IS_RECEIVER(arg)) throw MakeTypeError(kObserveInvalidAccept);
-
-  var len = TO_INTEGER(arg.length);
-  if (len < 0) len = 0;
-
-  return TypeMapCreateFromList(arg, len);
-}
-
-
-// CallbackInfo's optimized state is just a number which represents its global
-// priority. When a change record must be enqueued for the callback, it
-// normalizes. When delivery clears any pending change records, it re-optimizes.
-function CallbackInfoGet(callback) {
-  return %WeakCollectionGet(GetObservationStateJS().callbackInfoMap, callback,
-                            GetHash(callback));
-}
-
-
-function CallbackInfoSet(callback, callbackInfo) {
-  %WeakCollectionSet(GetObservationStateJS().callbackInfoMap,
-                     callback, callbackInfo, GetHash(callback));
-}
-
-
-function CallbackInfoGetOrCreate(callback) {
-  var callbackInfo = CallbackInfoGet(callback);
-  if (!IS_UNDEFINED(callbackInfo))
-    return callbackInfo;
-
-  var priority = GetNextCallbackPriority();
-  CallbackInfoSet(callback, priority);
-  return priority;
-}
-
-
-function CallbackInfoGetPriority(callbackInfo) {
-  if (IS_NUMBER(callbackInfo))
-    return callbackInfo;
-  else
-    return callbackInfo.priority;
-}
-
-
-function CallbackInfoNormalize(callback) {
-  var callbackInfo = CallbackInfoGet(callback);
-  if (IS_NUMBER(callbackInfo)) {
-    var priority = callbackInfo;
-    callbackInfo = new InternalArray;
-    callbackInfo.priority = priority;
-    CallbackInfoSet(callback, callbackInfo);
-  }
-  return callbackInfo;
-}
-
-
-function ObjectObserve(object, callback, acceptList) {
-  if (!IS_RECEIVER(object))
-    throw MakeTypeError(kObserveNonObject, "observe", "observe");
-  if (%IsJSGlobalProxy(object))
-    throw MakeTypeError(kObserveGlobalProxy, "observe");
-  if (%IsAccessCheckNeeded(object))
-    throw MakeTypeError(kObserveAccessChecked, "observe");
-  if (!IS_CALLABLE(callback))
-    throw MakeTypeError(kObserveNonFunction, "observe");
-  if (%object_is_frozen(callback))
-    throw MakeTypeError(kObserveCallbackFrozen);
-
-  var objectObserveFn = %GetObjectContextObjectObserve(object);
-  return objectObserveFn(object, callback, acceptList);
-}
-
-
-function NativeObjectObserve(object, callback, acceptList) {
-  var objectInfo = ObjectInfoGetOrCreate(object);
-  var typeList = ConvertAcceptListToTypeMap(acceptList);
-  ObjectInfoAddObserver(objectInfo, callback, typeList);
-  return object;
-}
-
-
-function ObjectUnobserve(object, callback) {
-  if (!IS_RECEIVER(object))
-    throw MakeTypeError(kObserveNonObject, "unobserve", "unobserve");
-  if (%IsJSGlobalProxy(object))
-    throw MakeTypeError(kObserveGlobalProxy, "unobserve");
-  if (!IS_CALLABLE(callback))
-    throw MakeTypeError(kObserveNonFunction, "unobserve");
-
-  var objectInfo = ObjectInfoGet(object);
-  if (IS_UNDEFINED(objectInfo))
-    return object;
-
-  ObjectInfoRemoveObserver(objectInfo, callback);
-  return object;
-}
-
-
-function ArrayObserve(object, callback) {
-  return ObjectObserve(object, callback, ['add',
-                                          'update',
-                                          'delete',
-                                          'splice']);
-}
-
-
-function ArrayUnobserve(object, callback) {
-  return ObjectUnobserve(object, callback);
-}
-
-
-function ObserverEnqueueIfActive(observer, objectInfo, changeRecord) {
-  if (!ObserverIsActive(observer, objectInfo) ||
-      !TypeMapHasType(ObserverGetAcceptTypes(observer), changeRecord.type)) {
-    return;
-  }
-
-  var callback = ObserverGetCallback(observer);
-  if (!%ObserverObjectAndRecordHaveSameOrigin(callback, changeRecord.object,
-                                              changeRecord)) {
-    return;
-  }
-
-  var callbackInfo = CallbackInfoNormalize(callback);
-  if (IS_NULL(GetPendingObservers())) {
-    SetPendingObservers(nullProtoObject());
-    if (DEBUG_IS_ACTIVE) {
-      var id = ++GetObservationStateJS().lastMicrotaskId;
-      var name = "Object.observe";
-      %EnqueueMicrotask(function() {
-        %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name });
-        ObserveMicrotaskRunner();
-        %DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name });
-      });
-      %DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name });
-    } else {
-      %EnqueueMicrotask(ObserveMicrotaskRunner);
-    }
-  }
-  GetPendingObservers()[callbackInfo.priority] = callback;
-  callbackInfo.push(changeRecord);
-}
-
-
-function ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, type) {
-  if (!ObjectInfoHasActiveObservers(objectInfo))
-    return;
-
-  var hasType = !IS_UNDEFINED(type);
-  var newRecord = hasType ?
-      { object: objectInfo.object, type: type } :
-      { object: objectInfo.object };
-
-  for (var prop in changeRecord) {
-    if (prop === 'object' || (hasType && prop === 'type')) continue;
-    %DefineDataPropertyUnchecked(
-        newRecord, prop, changeRecord[prop], READ_ONLY + DONT_DELETE);
-  }
-  %object_freeze(newRecord);
-
-  ObjectInfoEnqueueInternalChangeRecord(objectInfo, newRecord);
-}
-
-
-function ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord) {
-  // TODO(rossberg): adjust once there is a story for symbols vs proxies.
-  if (IS_SYMBOL(changeRecord.name)) return;
-
-  if (ChangeObserversIsOptimized(objectInfo.changeObservers)) {
-    var observer = objectInfo.changeObservers;
-    ObserverEnqueueIfActive(observer, objectInfo, changeRecord);
-    return;
-  }
-
-  for (var priority in objectInfo.changeObservers) {
-    var observer = objectInfo.changeObservers[priority];
-    if (IS_NULL(observer))
-      continue;
-    ObserverEnqueueIfActive(observer, objectInfo, changeRecord);
-  }
-}
-
-
-function BeginPerformSplice(array) {
-  var objectInfo = ObjectInfoGet(array);
-  if (!IS_UNDEFINED(objectInfo))
-    ObjectInfoAddPerformingType(objectInfo, 'splice');
-}
-
-
-function EndPerformSplice(array) {
-  var objectInfo = ObjectInfoGet(array);
-  if (!IS_UNDEFINED(objectInfo))
-    ObjectInfoRemovePerformingType(objectInfo, 'splice');
-}
-
-
-function EnqueueSpliceRecord(array, index, removed, addedCount) {
-  var objectInfo = ObjectInfoGet(array);
-  if (!ObjectInfoHasActiveObservers(objectInfo))
-    return;
-
-  var changeRecord = {
-    type: 'splice',
-    object: array,
-    index: index,
-    removed: removed,
-    addedCount: addedCount
-  };
-
-  %object_freeze(changeRecord);
-  %object_freeze(changeRecord.removed);
-  ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord);
-}
-
-
-function NotifyChange(type, object, name, oldValue) {
-  var objectInfo = ObjectInfoGet(object);
-  if (!ObjectInfoHasActiveObservers(objectInfo))
-    return;
-
-  var changeRecord;
-  if (arguments.length == 2) {
-    changeRecord = { type: type, object: object };
-  } else if (arguments.length == 3) {
-    changeRecord = { type: type, object: object, name: name };
-  } else {
-    changeRecord = {
-      type: type,
-      object: object,
-      name: name,
-      oldValue: oldValue
-    };
-  }
-
-  %object_freeze(changeRecord);
-  ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord);
-}
-
-
-function ObjectNotifierNotify(changeRecord) {
-  if (!IS_RECEIVER(this))
-    throw MakeTypeError(kCalledOnNonObject, "notify");
-
-  var objectInfo = ObjectInfoGetFromNotifier(this);
-  if (IS_UNDEFINED(objectInfo))
-    throw MakeTypeError(kObserveNotifyNonNotifier);
-  if (!IS_STRING(changeRecord.type))
-    throw MakeTypeError(kObserveTypeNonString);
-
-  ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord);
-}
-
-
-function ObjectNotifierPerformChange(changeType, changeFn) {
-  if (!IS_RECEIVER(this))
-    throw MakeTypeError(kCalledOnNonObject, "performChange");
-
-  var objectInfo = ObjectInfoGetFromNotifier(this);
-  if (IS_UNDEFINED(objectInfo))
-    throw MakeTypeError(kObserveNotifyNonNotifier);
-  if (!IS_STRING(changeType))
-    throw MakeTypeError(kObservePerformNonString);
-  if (!IS_CALLABLE(changeFn))
-    throw MakeTypeError(kObservePerformNonFunction);
-
-  var performChangeFn = %GetObjectContextNotifierPerformChange(objectInfo);
-  performChangeFn(objectInfo, changeType, changeFn);
-}
-
-
-function NativeObjectNotifierPerformChange(objectInfo, changeType, changeFn) {
-  ObjectInfoAddPerformingType(objectInfo, changeType);
-
-  var changeRecord;
-  try {
-    changeRecord = changeFn();
-  } finally {
-    ObjectInfoRemovePerformingType(objectInfo, changeType);
-  }
-
-  if (IS_RECEIVER(changeRecord))
-    ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, changeType);
-}
-
-
-function ObjectGetNotifier(object) {
-  if (!IS_RECEIVER(object))
-    throw MakeTypeError(kObserveNonObject, "getNotifier", "getNotifier");
-  if (%IsJSGlobalProxy(object))
-    throw MakeTypeError(kObserveGlobalProxy, "getNotifier");
-  if (%IsAccessCheckNeeded(object))
-    throw MakeTypeError(kObserveAccessChecked, "getNotifier");
-
-  if (%object_is_frozen(object)) return null;
-
-  if (!%ObjectWasCreatedInCurrentOrigin(object)) return null;
-
-  var getNotifierFn = %GetObjectContextObjectGetNotifier(object);
-  return getNotifierFn(object);
-}
-
-
-function NativeObjectGetNotifier(object) {
-  var objectInfo = ObjectInfoGetOrCreate(object);
-  return ObjectInfoGetNotifier(objectInfo);
-}
-
-
-function CallbackDeliverPending(callback) {
-  var callbackInfo = CallbackInfoGet(callback);
-  if (IS_UNDEFINED(callbackInfo) || IS_NUMBER(callbackInfo))
-    return false;
-
-  // Clear the pending change records from callback and return it to its
-  // "optimized" state.
-  var priority = callbackInfo.priority;
-  CallbackInfoSet(callback, priority);
-
-  var pendingObservers = GetPendingObservers();
-  if (!IS_NULL(pendingObservers))
-    delete pendingObservers[priority];
-
-  // TODO: combine the following runtime calls for perf optimization.
-  var delivered = [];
-  %MoveArrayContents(callbackInfo, delivered);
-  %DeliverObservationChangeRecords(callback, delivered);
-
-  return true;
-}
-
-
-function ObjectDeliverChangeRecords(callback) {
-  if (!IS_CALLABLE(callback))
-    throw MakeTypeError(kObserveNonFunction, "deliverChangeRecords");
-
-  while (CallbackDeliverPending(callback)) {}
-}
-
-
-function ObserveMicrotaskRunner() {
-  var pendingObservers = GetPendingObservers();
-  if (!IS_NULL(pendingObservers)) {
-    SetPendingObservers(null);
-    for (var i in pendingObservers) {
-      CallbackDeliverPending(pendingObservers[i]);
-    }
-  }
-}
-
-// -------------------------------------------------------------------
-
-utils.InstallFunctions(notifierPrototype, DONT_ENUM, [
-  "notify", ObjectNotifierNotify,
-  "performChange", ObjectNotifierPerformChange
-]);
-
-var ObserveObjectMethods = [
-  "deliverChangeRecords", ObjectDeliverChangeRecords,
-  "getNotifier", ObjectGetNotifier,
-  "observe", ObjectObserve,
-  "unobserve", ObjectUnobserve
-];
-
-var ObserveArrayMethods = [
-  "observe", ArrayObserve,
-  "unobserve", ArrayUnobserve
-];
-
-// TODO(adamk): Figure out why this prototype removal has to
-// happen as part of initial snapshotting.
-var removePrototypeFn = function(f, i) {
-  if (i % 2 === 1) %FunctionRemovePrototype(f);
-};
-ObserveObjectMethods.forEach(removePrototypeFn);
-ObserveArrayMethods.forEach(removePrototypeFn);
-
-%InstallToContext([
-  "native_object_get_notifier", NativeObjectGetNotifier,
-  "native_object_notifier_perform_change", NativeObjectNotifierPerformChange,
-  "native_object_observe", NativeObjectObserve,
-  "observers_begin_perform_splice", BeginPerformSplice,
-  "observers_end_perform_splice", EndPerformSplice,
-  "observers_enqueue_splice", EnqueueSpliceRecord,
-  "observers_notify_change", NotifyChange,
-]);
-
-utils.Export(function(to) {
-  to.ObserveArrayMethods = ObserveArrayMethods;
-  to.ObserveBeginPerformSplice = BeginPerformSplice;
-  to.ObserveEndPerformSplice = EndPerformSplice;
-  to.ObserveEnqueueSpliceRecord = EnqueueSpliceRecord;
-  to.ObserveObjectMethods = ObserveObjectMethods;
-});
-
-})
diff --git a/src/js/prologue.js b/src/js/prologue.js
index f9589a5..79fe9b7 100644
--- a/src/js/prologue.js
+++ b/src/js/prologue.js
@@ -128,10 +128,10 @@
 
 function OverrideFunction(object, name, f, afterInitialBootstrap) {
   %CheckIsBootstrapping();
-  %ObjectDefineProperty(object, name, { value: f,
-                                        writeable: true,
-                                        configurable: true,
-                                        enumerable: false });
+  %object_define_property(object, name, { value: f,
+                                          writeable: true,
+                                          configurable: true,
+                                          enumerable: false });
   SetFunctionName(f, name);
   if (!afterInitialBootstrap) %FunctionRemovePrototype(f);
   %SetNativeFlag(f);
@@ -181,10 +181,15 @@
 
   // Whitelist of exports from normal natives to experimental natives and debug.
   var expose_list = [
+    "AddBoundMethod",
     "ArrayToString",
+    "AsyncFunctionNext",
+    "AsyncFunctionThrow",
     "ErrorToString",
     "GetIterator",
     "GetMethod",
+    "IntlParseDate",
+    "IntlParseNumber",
     "IsNaN",
     "MakeError",
     "MakeRangeError",
@@ -195,12 +200,12 @@
     "MaxSimple",
     "MinSimple",
     "NumberIsInteger",
-    "ObjectDefineProperty",
-    "ObserveArrayMethods",
-    "ObserveObjectMethods",
     "PromiseChain",
-    "PromiseDeferred",
-    "PromiseResolved",
+    "PromiseDefer",
+    "PromiseAccept",
+    "PromiseCreateRejected",
+    "PromiseCreateResolved",
+    "PromiseThen",
     "RegExpSubclassExecJS",
     "RegExpSubclassMatch",
     "RegExpSubclassReplace",
@@ -211,12 +216,16 @@
     "SetIteratorNext",
     "SetValues",
     "SymbolToString",
+    "ToLocaleLowerCaseI18N",
+    "ToLocaleUpperCaseI18N",
+    "ToLowerCaseI18N",
     "ToPositiveInteger",
+    "ToUpperCaseI18N",
     // From runtime:
     "is_concat_spreadable_symbol",
     "iterator_symbol",
-    "promise_status_symbol",
-    "promise_value_symbol",
+    "promise_result_symbol",
+    "promise_state_symbol",
     "object_freeze",
     "object_is_frozen",
     "object_is_sealed",
@@ -257,9 +266,6 @@
     imports_from_experimental(exports_container);
   }
 
-  utils.CreateDoubleResultArray();
-  utils.CreateDoubleResultArray = UNDEFINED;
-
   utils.Export = UNDEFINED;
   utils.PostDebug = UNDEFINED;
   utils.PostExperimentals = UNDEFINED;
@@ -272,9 +278,6 @@
     imports(exports_container);
   }
 
-  utils.CreateDoubleResultArray();
-  utils.CreateDoubleResultArray = UNDEFINED;
-
   exports_container = UNDEFINED;
 
   utils.Export = UNDEFINED;
diff --git a/src/js/promise-extra.js b/src/js/promise-extra.js
index f6f7959..34d7323 100644
--- a/src/js/promise-extra.js
+++ b/src/js/promise-extra.js
@@ -11,16 +11,16 @@
 var GlobalPromise = global.Promise;
 
 var PromiseChain = utils.ImportNow("PromiseChain");
-var PromiseDeferred = utils.ImportNow("PromiseDeferred");
-var PromiseResolved = utils.ImportNow("PromiseResolved");
+var PromiseDefer = utils.ImportNow("PromiseDefer");
+var PromiseAccept = utils.ImportNow("PromiseAccept");
 
 utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [
   "chain", PromiseChain,
 ]);
 
 utils.InstallFunctions(GlobalPromise, DONT_ENUM, [
-  "defer", PromiseDeferred,
-  "accept", PromiseResolved,
+  "defer", PromiseDefer,
+  "accept", PromiseAccept,
 ]);
 
 })
diff --git a/src/js/promise.js b/src/js/promise.js
index bcf826a..5e8c460 100644
--- a/src/js/promise.js
+++ b/src/js/promise.js
@@ -17,13 +17,17 @@
     utils.ImportNow("promise_combined_deferred_symbol");
 var promiseHasHandlerSymbol =
     utils.ImportNow("promise_has_handler_symbol");
-var promiseOnRejectSymbol = utils.ImportNow("promise_on_reject_symbol");
-var promiseOnResolveSymbol =
-    utils.ImportNow("promise_on_resolve_symbol");
+var promiseRejectReactionsSymbol =
+    utils.ImportNow("promise_reject_reactions_symbol");
+var promiseFulfillReactionsSymbol =
+    utils.ImportNow("promise_fulfill_reactions_symbol");
+var promiseDeferredReactionsSymbol =
+    utils.ImportNow("promise_deferred_reactions_symbol");
 var promiseRawSymbol = utils.ImportNow("promise_raw_symbol");
-var promiseStatusSymbol = utils.ImportNow("promise_status_symbol");
-var promiseValueSymbol = utils.ImportNow("promise_value_symbol");
+var promiseStateSymbol = utils.ImportNow("promise_state_symbol");
+var promiseResultSymbol = utils.ImportNow("promise_result_symbol");
 var SpeciesConstructor;
+var speciesSymbol = utils.ImportNow("species_symbol");
 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
 
 utils.Import(function(from) {
@@ -33,22 +37,32 @@
 
 // -------------------------------------------------------------------
 
-// Status values: 0 = pending, +1 = resolved, -1 = rejected
+// [[PromiseState]] values:
+const kPending = 0;
+const kFulfilled = +1;
+const kRejected = -1;
+
 var lastMicrotaskId = 0;
 
+// ES#sec-createresolvingfunctions
+// CreateResolvingFunctions ( promise )
 function CreateResolvingFunctions(promise) {
   var alreadyResolved = false;
 
+  // ES#sec-promise-resolve-functions
+  // Promise Resolve Functions
   var resolve = value => {
     if (alreadyResolved === true) return;
     alreadyResolved = true;
-    PromiseResolve(promise, value);
+    ResolvePromise(promise, value);
   };
 
+  // ES#sec-promise-reject-functions
+  // Promise Reject Functions
   var reject = reason => {
     if (alreadyResolved === true) return;
     alreadyResolved = true;
-    PromiseReject(promise, reason);
+    RejectPromise(promise, reason);
   };
 
   return {
@@ -59,24 +73,27 @@
 }
 
 
-var GlobalPromise = function Promise(resolver) {
-  if (resolver === promiseRawSymbol) {
+// ES#sec-promise-executor
+// Promise ( executor )
+var GlobalPromise = function Promise(executor) {
+  if (executor === promiseRawSymbol) {
     return %_NewObject(GlobalPromise, new.target);
   }
   if (IS_UNDEFINED(new.target)) throw MakeTypeError(kNotAPromise, this);
-  if (!IS_CALLABLE(resolver))
-    throw MakeTypeError(kResolverNotAFunction, resolver);
+  if (!IS_CALLABLE(executor)) {
+    throw MakeTypeError(kResolverNotAFunction, executor);
+  }
 
   var promise = PromiseInit(%_NewObject(GlobalPromise, new.target));
   var callbacks = CreateResolvingFunctions(promise);
-
+  var debug_is_active = DEBUG_IS_ACTIVE;
   try {
-    %DebugPushPromise(promise, Promise);
-    resolver(callbacks.resolve, callbacks.reject);
+    if (debug_is_active) %DebugPushPromise(promise, Promise);
+    executor(callbacks.resolve, callbacks.reject);
   } catch (e) {
     %_Call(callbacks.reject, UNDEFINED, e);
   } finally {
-    %DebugPopPromise();
+    if (debug_is_active) %DebugPopPromise();
   }
 
   return promise;
@@ -84,54 +101,84 @@
 
 // Core functionality.
 
-function PromiseSet(promise, status, value, onResolve, onReject) {
-  SET_PRIVATE(promise, promiseStatusSymbol, status);
-  SET_PRIVATE(promise, promiseValueSymbol, value);
-  SET_PRIVATE(promise, promiseOnResolveSymbol, onResolve);
-  SET_PRIVATE(promise, promiseOnRejectSymbol, onReject);
+function PromiseSet(promise, status, value) {
+  SET_PRIVATE(promise, promiseStateSymbol, status);
+  SET_PRIVATE(promise, promiseResultSymbol, value);
+
+  // There are 3 possible states for the resolve, reject symbols when we add
+  // a new callback --
+  // 1) UNDEFINED -- This is the zero state where there is no callback
+  // registered. When we see this state, we directly attach the callbacks to
+  // the symbol.
+  // 2) !IS_ARRAY -- There is a single callback directly attached to the
+  // symbols. We need to create a new array to store additional callbacks.
+  // 3) IS_ARRAY -- There are multiple callbacks already registered,
+  // therefore we can just push the new callback to the existing array.
+  SET_PRIVATE(promise, promiseFulfillReactionsSymbol, UNDEFINED);
+  SET_PRIVATE(promise, promiseRejectReactionsSymbol, UNDEFINED);
+
+  // There are 2 possible states for this symbol --
+  // 1) UNDEFINED -- This is the zero state, no deferred object is
+  // attached to this symbol. When we want to add a new deferred we
+  // directly attach it to this symbol.
+  // 2) symbol with attached deferred object -- New deferred objects
+  // are not attached to this symbol, but instead they are directly
+  // attached to the resolve, reject callback arrays. At this point,
+  // the deferred symbol's state is stale, and the deferreds should be
+  // read from the reject, resolve callbacks.
+  SET_PRIVATE(promise, promiseDeferredReactionsSymbol, UNDEFINED);
+
   return promise;
 }
 
 function PromiseCreateAndSet(status, value) {
   var promise = new GlobalPromise(promiseRawSymbol);
   // If debug is active, notify about the newly created promise first.
-  if (DEBUG_IS_ACTIVE) PromiseSet(promise, 0, UNDEFINED);
+  if (DEBUG_IS_ACTIVE) PromiseSet(promise, kPending, UNDEFINED);
   return PromiseSet(promise, status, value);
 }
 
 function PromiseInit(promise) {
-  return PromiseSet(
-      promise, 0, UNDEFINED, new InternalArray, new InternalArray)
+  return PromiseSet(promise, kPending, UNDEFINED);
 }
 
-function PromiseDone(promise, status, value, promiseQueue) {
-  if (GET_PRIVATE(promise, promiseStatusSymbol) === 0) {
+function FulfillPromise(promise, status, value, promiseQueue) {
+  if (GET_PRIVATE(promise, promiseStateSymbol) === kPending) {
     var tasks = GET_PRIVATE(promise, promiseQueue);
-    if (tasks.length) PromiseEnqueue(value, tasks, status);
+    if (!IS_UNDEFINED(tasks)) {
+      var tasks = GET_PRIVATE(promise, promiseQueue);
+      var deferreds = GET_PRIVATE(promise, promiseDeferredReactionsSymbol);
+      PromiseEnqueue(value, tasks, deferreds, status);
+    }
     PromiseSet(promise, status, value);
   }
 }
 
 function PromiseHandle(value, handler, deferred) {
+  var debug_is_active = DEBUG_IS_ACTIVE;
   try {
-    %DebugPushPromise(deferred.promise, PromiseHandle);
+    if (debug_is_active) %DebugPushPromise(deferred.promise, PromiseHandle);
     var result = handler(value);
     deferred.resolve(result);
   } catch (exception) {
     try { deferred.reject(exception); } catch (e) { }
   } finally {
-    %DebugPopPromise();
+    if (debug_is_active) %DebugPopPromise();
   }
 }
 
-function PromiseEnqueue(value, tasks, status) {
+function PromiseEnqueue(value, tasks, deferreds, status) {
   var id, name, instrumenting = DEBUG_IS_ACTIVE;
   %EnqueueMicrotask(function() {
     if (instrumenting) {
       %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name });
     }
-    for (var i = 0; i < tasks.length; i += 2) {
-      PromiseHandle(value, tasks[i], tasks[i + 1])
+    if (IS_ARRAY(tasks)) {
+      for (var i = 0; i < tasks.length; i += 2) {
+        PromiseHandle(value, tasks[i], tasks[i + 1]);
+      }
+    } else {
+      PromiseHandle(value, tasks, deferreds);
     }
     if (instrumenting) {
       %DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name });
@@ -139,11 +186,38 @@
   });
   if (instrumenting) {
     id = ++lastMicrotaskId;
-    name = status > 0 ? "Promise.resolve" : "Promise.reject";
+    name = status === kFulfilled ? "Promise.resolve" : "Promise.reject";
     %DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name });
   }
 }
 
+function PromiseAttachCallbacks(promise, deferred, onResolve, onReject) {
+  var maybeResolveCallbacks =
+      GET_PRIVATE(promise, promiseFulfillReactionsSymbol);
+  if (IS_UNDEFINED(maybeResolveCallbacks)) {
+    SET_PRIVATE(promise, promiseFulfillReactionsSymbol, onResolve);
+    SET_PRIVATE(promise, promiseRejectReactionsSymbol, onReject);
+    SET_PRIVATE(promise, promiseDeferredReactionsSymbol, deferred);
+  } else if (!IS_ARRAY(maybeResolveCallbacks)) {
+    var resolveCallbacks = new InternalArray();
+    var rejectCallbacks = new InternalArray();
+    var existingDeferred = GET_PRIVATE(promise, promiseDeferredReactionsSymbol);
+
+    resolveCallbacks.push(
+        maybeResolveCallbacks, existingDeferred, onResolve, deferred);
+    rejectCallbacks.push(GET_PRIVATE(promise, promiseRejectReactionsSymbol),
+                         existingDeferred,
+                         onReject,
+                         deferred);
+
+    SET_PRIVATE(promise, promiseFulfillReactionsSymbol, resolveCallbacks);
+    SET_PRIVATE(promise, promiseRejectReactionsSymbol, rejectCallbacks);
+  } else {
+    maybeResolveCallbacks.push(onResolve, deferred);
+    GET_PRIVATE(promise, promiseRejectReactionsSymbol).push(onReject, deferred);
+  }
+}
+
 function PromiseIdResolveHandler(x) { return x }
 function PromiseIdRejectHandler(r) { throw r }
 
@@ -154,35 +228,67 @@
 
 // For bootstrapper.
 
+// ES#sec-ispromise IsPromise ( x )
 function IsPromise(x) {
-  return IS_RECEIVER(x) && HAS_DEFINED_PRIVATE(x, promiseStatusSymbol);
+  return IS_RECEIVER(x) && HAS_DEFINED_PRIVATE(x, promiseStateSymbol);
 }
 
 function PromiseCreate() {
   return new GlobalPromise(PromiseNopResolver)
 }
 
-function PromiseResolve(promise, x) {
-  if (x === promise) {
-    return PromiseReject(promise, MakeTypeError(kPromiseCyclic, x));
+// ES#sec-promise-resolve-functions
+// Promise Resolve Functions, steps 6-13
+function ResolvePromise(promise, resolution) {
+  if (resolution === promise) {
+    return RejectPromise(promise, MakeTypeError(kPromiseCyclic, resolution));
   }
-  if (IS_RECEIVER(x)) {
+  if (IS_RECEIVER(resolution)) {
     // 25.4.1.3.2 steps 8-12
     try {
-      var then = x.then;
+      var then = resolution.then;
     } catch (e) {
-      return PromiseReject(promise, e);
+      return RejectPromise(promise, e);
     }
+
+    // Resolution is a native promise and if it's already resolved or
+    // rejected, shortcircuit the resolution procedure by directly
+    // reusing the value from the promise.
+    if (IsPromise(resolution) && then === PromiseThen) {
+      var thenableState = GET_PRIVATE(resolution, promiseStateSymbol);
+      if (thenableState === kFulfilled) {
+        // This goes inside the if-else to save one symbol lookup in
+        // the slow path.
+        var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol);
+        FulfillPromise(promise, kFulfilled, thenableValue,
+                       promiseFulfillReactionsSymbol);
+        SET_PRIVATE(promise, promiseHasHandlerSymbol, true);
+        return;
+      } else if (thenableState === kRejected) {
+        var thenableValue = GET_PRIVATE(resolution, promiseResultSymbol);
+        if (!HAS_DEFINED_PRIVATE(resolution, promiseHasHandlerSymbol)) {
+          // Promise has already been rejected, but had no handler.
+          // Revoke previously triggered reject event.
+          %PromiseRevokeReject(resolution);
+        }
+        RejectPromise(promise, thenableValue);
+        SET_PRIVATE(resolution, promiseHasHandlerSymbol, true);
+        return;
+      }
+    }
+
     if (IS_CALLABLE(then)) {
       // PromiseResolveThenableJob
-      var id, name, instrumenting = DEBUG_IS_ACTIVE;
+      var id;
+      var name = "PromiseResolveThenableJob";
+      var instrumenting = DEBUG_IS_ACTIVE;
       %EnqueueMicrotask(function() {
         if (instrumenting) {
           %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name });
         }
         var callbacks = CreateResolvingFunctions(promise);
         try {
-          %_Call(then, x, callbacks.resolve, callbacks.reject);
+          %_Call(then, resolution, callbacks.resolve, callbacks.reject);
         } catch (e) {
           %_Call(callbacks.reject, UNDEFINED, e);
         }
@@ -192,28 +298,31 @@
       });
       if (instrumenting) {
         id = ++lastMicrotaskId;
-        name = "PromseResolveThenableJob";
         %DebugAsyncTaskEvent({ type: "enqueue", id: id, name: name });
       }
       return;
     }
   }
-  PromiseDone(promise, +1, x, promiseOnResolveSymbol);
+  FulfillPromise(promise, kFulfilled, resolution, promiseFulfillReactionsSymbol);
 }
 
-function PromiseReject(promise, r) {
+// ES#sec-rejectpromise
+// RejectPromise ( promise, reason )
+function RejectPromise(promise, reason) {
   // Check promise status to confirm that this reject has an effect.
   // Call runtime for callbacks to the debugger or for unhandled reject.
-  if (GET_PRIVATE(promise, promiseStatusSymbol) == 0) {
+  if (GET_PRIVATE(promise, promiseStateSymbol) === kPending) {
     var debug_is_active = DEBUG_IS_ACTIVE;
     if (debug_is_active ||
         !HAS_DEFINED_PRIVATE(promise, promiseHasHandlerSymbol)) {
-      %PromiseRejectEvent(promise, r, debug_is_active);
+      %PromiseRejectEvent(promise, reason, debug_is_active);
     }
   }
-  PromiseDone(promise, -1, r, promiseOnRejectSymbol)
+  FulfillPromise(promise, kRejected, reason, promiseRejectReactionsSymbol)
 }
 
+// ES#sec-newpromisecapability
+// NewPromiseCapability ( C )
 function NewPromiseCapability(C) {
   if (C === GlobalPromise) {
     // Optimized case, avoid extra closure.
@@ -240,23 +349,27 @@
   return result;
 }
 
-function PromiseDeferred() {
+// Unspecified V8-specific legacy function
+function PromiseDefer() {
   %IncrementUseCounter(kPromiseDefer);
   return NewPromiseCapability(this);
 }
 
-function PromiseResolved(x) {
+// Unspecified V8-specific legacy function
+function PromiseAccept(x) {
   %IncrementUseCounter(kPromiseAccept);
-  return %_Call(PromiseCast, this, x);
+  return %_Call(PromiseResolve, this, x);
 }
 
-function PromiseRejected(r) {
+// ES#sec-promise.reject
+// Promise.reject ( x )
+function PromiseReject(r) {
   if (!IS_RECEIVER(this)) {
-    throw MakeTypeError(kCalledOnNonObject, PromiseRejected);
+    throw MakeTypeError(kCalledOnNonObject, PromiseResolve);
   }
   if (this === GlobalPromise) {
     // Optimized case, avoid extra closure.
-    var promise = PromiseCreateAndSet(-1, r);
+    var promise = PromiseCreateAndSet(kRejected, r);
     // The debug event for this would always be an uncaught promise reject,
     // which is usually simply noise. Do not trigger that debug event.
     %PromiseRejectEvent(promise, r, false);
@@ -268,10 +381,21 @@
   }
 }
 
-// Multi-unwrapped chaining with thenable coercion.
+// Shortcut Promise.reject and Promise.resolve() implementations, used by
+// Async Functions implementation.
+function PromiseCreateRejected(r) {
+  return %_Call(PromiseReject, GlobalPromise, r);
+}
 
+function PromiseCreateResolved(x) {
+  return %_Call(PromiseResolve, GlobalPromise, x);
+}
+
+// ES#sec-promise.prototype.then
+// Promise.prototype.then ( onFulfilled, onRejected )
+// Multi-unwrapped chaining with thenable coercion.
 function PromiseThen(onResolve, onReject) {
-  var status = GET_PRIVATE(this, promiseStatusSymbol);
+  var status = GET_PRIVATE(this, promiseStateSymbol);
   if (IS_UNDEFINED(status)) {
     throw MakeTypeError(kNotAPromise, this);
   }
@@ -281,24 +405,21 @@
   onReject = IS_CALLABLE(onReject) ? onReject : PromiseIdRejectHandler;
   var deferred = NewPromiseCapability(constructor);
   switch (status) {
-    case 0:  // Pending
-      GET_PRIVATE(this, promiseOnResolveSymbol).push(onResolve, deferred);
-      GET_PRIVATE(this, promiseOnRejectSymbol).push(onReject, deferred);
+    case kPending:
+      PromiseAttachCallbacks(this, deferred, onResolve, onReject);
       break;
-    case +1:  // Resolved
-      PromiseEnqueue(GET_PRIVATE(this, promiseValueSymbol),
-                     [onResolve, deferred],
-                     +1);
+    case kFulfilled:
+      PromiseEnqueue(GET_PRIVATE(this, promiseResultSymbol),
+                     onResolve, deferred, kFulfilled);
       break;
-    case -1:  // Rejected
+    case kRejected:
       if (!HAS_DEFINED_PRIVATE(this, promiseHasHandlerSymbol)) {
         // Promise has already been rejected, but had no handler.
         // Revoke previously triggered reject event.
         %PromiseRevokeReject(this);
       }
-      PromiseEnqueue(GET_PRIVATE(this, promiseValueSymbol),
-                     [onReject, deferred],
-                     -1);
+      PromiseEnqueue(GET_PRIVATE(this, promiseResultSymbol),
+                     onReject, deferred, kRejected);
       break;
   }
   // Mark this promise as having handler.
@@ -306,21 +427,26 @@
   return deferred.promise;
 }
 
+// Unspecified V8-specific legacy function
 // Chain is left around for now as an alias for then
 function PromiseChain(onResolve, onReject) {
   %IncrementUseCounter(kPromiseChain);
   return %_Call(PromiseThen, this, onResolve, onReject);
 }
 
+// ES#sec-promise.prototype.catch
+// Promise.prototype.catch ( onRejected )
 function PromiseCatch(onReject) {
   return this.then(UNDEFINED, onReject);
 }
 
 // Combinators.
 
-function PromiseCast(x) {
+// ES#sec-promise.resolve
+// Promise.resolve ( x )
+function PromiseResolve(x) {
   if (!IS_RECEIVER(this)) {
-    throw MakeTypeError(kCalledOnNonObject, PromiseCast);
+    throw MakeTypeError(kCalledOnNonObject, PromiseResolve);
   }
   if (IsPromise(x) && x.constructor === this) return x;
 
@@ -329,6 +455,8 @@
   return promiseCapability.promise;
 }
 
+// ES#sec-promise.all
+// Promise.all ( iterable )
 function PromiseAll(iterable) {
   if (!IS_RECEIVER(this)) {
     throw MakeTypeError(kCalledOnNonObject, "Promise.all");
@@ -378,6 +506,8 @@
   return deferred.promise;
 }
 
+// ES#sec-promise.race
+// Promise.race ( iterable )
 function PromiseRace(iterable) {
   if (!IS_RECEIVER(this)) {
     throw MakeTypeError(kCalledOnNonObject, PromiseRace);
@@ -398,20 +528,30 @@
 
 // Utility for debugger
 
+function PromiseHasUserDefinedRejectHandlerCheck(handler, deferred) {
+  if (handler !== PromiseIdRejectHandler) {
+    var combinedDeferred = GET_PRIVATE(handler, promiseCombinedDeferredSymbol);
+    if (IS_UNDEFINED(combinedDeferred)) return true;
+    if (PromiseHasUserDefinedRejectHandlerRecursive(combinedDeferred.promise)) {
+      return true;
+    }
+  } else if (PromiseHasUserDefinedRejectHandlerRecursive(deferred.promise)) {
+    return true;
+  }
+  return false;
+}
+
 function PromiseHasUserDefinedRejectHandlerRecursive(promise) {
-  var queue = GET_PRIVATE(promise, promiseOnRejectSymbol);
+  var queue = GET_PRIVATE(promise, promiseRejectReactionsSymbol);
+  var deferreds = GET_PRIVATE(promise, promiseDeferredReactionsSymbol);
   if (IS_UNDEFINED(queue)) return false;
-  for (var i = 0; i < queue.length; i += 2) {
-    var handler = queue[i];
-    if (handler !== PromiseIdRejectHandler) {
-      var deferred = GET_PRIVATE(handler, promiseCombinedDeferredSymbol);
-      if (IS_UNDEFINED(deferred)) return true;
-      if (PromiseHasUserDefinedRejectHandlerRecursive(deferred.promise)) {
+  if (!IS_ARRAY(queue)) {
+    return PromiseHasUserDefinedRejectHandlerCheck(queue, deferreds);
+  } else {
+    for (var i = 0; i < queue.length; i += 2) {
+      if (PromiseHasUserDefinedRejectHandlerCheck(queue[i], queue[i + 1])) {
         return true;
       }
-    } else if (PromiseHasUserDefinedRejectHandlerRecursive(
-                   queue[i + 1].promise)) {
-      return true;
     }
   }
   return false;
@@ -424,6 +564,11 @@
   return PromiseHasUserDefinedRejectHandlerRecursive(this);
 };
 
+
+function PromiseSpecies() {
+  return this;
+}
+
 // -------------------------------------------------------------------
 // Install exported functions.
 
@@ -432,12 +577,14 @@
                   DONT_ENUM | READ_ONLY);
 
 utils.InstallFunctions(GlobalPromise, DONT_ENUM, [
-  "reject", PromiseRejected,
+  "reject", PromiseReject,
   "all", PromiseAll,
   "race", PromiseRace,
-  "resolve", PromiseCast
+  "resolve", PromiseResolve
 ]);
 
+utils.InstallGetter(GlobalPromise, speciesSymbol, PromiseSpecies);
+
 utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [
   "then", PromiseThen,
   "catch", PromiseCatch
@@ -448,9 +595,11 @@
   "promise_chain", PromiseChain,
   "promise_create", PromiseCreate,
   "promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler,
-  "promise_reject", PromiseReject,
-  "promise_resolve", PromiseResolve,
+  "promise_reject", RejectPromise,
+  "promise_resolve", ResolvePromise,
   "promise_then", PromiseThen,
+  "promise_create_rejected", PromiseCreateRejected,
+  "promise_create_resolved", PromiseCreateResolved
 ]);
 
 // This allows extras to create promises quickly without building extra
@@ -458,18 +607,22 @@
 // promise without having to hold on to those closures forever.
 utils.InstallFunctions(extrasUtils, 0, [
   "createPromise", PromiseCreate,
-  "resolvePromise", PromiseResolve,
-  "rejectPromise", PromiseReject
+  "resolvePromise", ResolvePromise,
+  "rejectPromise", RejectPromise
 ]);
 
 // TODO(v8:4567): Allow experimental natives to remove function prototype
-[PromiseChain, PromiseDeferred, PromiseResolved].forEach(
+[PromiseChain, PromiseDefer, PromiseAccept].forEach(
     fn => %FunctionRemovePrototype(fn));
 
 utils.Export(function(to) {
   to.PromiseChain = PromiseChain;
-  to.PromiseDeferred = PromiseDeferred;
-  to.PromiseResolved = PromiseResolved;
+  to.PromiseDefer = PromiseDefer;
+  to.PromiseAccept = PromiseAccept;
+
+  to.PromiseCreateRejected = PromiseCreateRejected;
+  to.PromiseCreateResolved = PromiseCreateResolved;
+  to.PromiseThen = PromiseThen;
 });
 
 })
diff --git a/src/js/regexp.js b/src/js/regexp.js
index cc8cb41..6b7cf48 100644
--- a/src/js/regexp.js
+++ b/src/js/regexp.js
@@ -4,14 +4,11 @@
 
 (function(global, utils) {
 
-'use strict';
-
 %CheckIsBootstrapping();
 
 // -------------------------------------------------------------------
 // Imports
 
-var AddIndexedProperty;
 var ExpandReplacement;
 var GlobalArray = global.Array;
 var GlobalObject = global.Object;
@@ -25,11 +22,11 @@
 var matchSymbol = utils.ImportNow("match_symbol");
 var replaceSymbol = utils.ImportNow("replace_symbol");
 var searchSymbol = utils.ImportNow("search_symbol");
+var speciesSymbol = utils.ImportNow("species_symbol");
 var splitSymbol = utils.ImportNow("split_symbol");
 var SpeciesConstructor;
 
 utils.Import(function(from) {
-  AddIndexedProperty = from.AddIndexedProperty;
   ExpandReplacement = from.ExpandReplacement;
   MakeTypeError = from.MakeTypeError;
   MaxSimple = from.MaxSimple;
@@ -327,10 +324,10 @@
     // not a '?'.  But see https://code.google.com/p/v8/issues/detail?id=3560
     var regexp = this;
     var source = REGEXP_SOURCE(regexp);
-    if (regexp.length >= 3 &&
-        %_StringCharCodeAt(regexp, 0) == 46 &&  // '.'
-        %_StringCharCodeAt(regexp, 1) == 42 &&  // '*'
-        %_StringCharCodeAt(regexp, 2) != 63) {  // '?'
+    if (source.length >= 3 &&
+        %_StringCharCodeAt(source, 0) == 46 &&  // '.'
+        %_StringCharCodeAt(source, 1) == 42 &&  // '*'
+        %_StringCharCodeAt(source, 2) != 63) {  // '?'
       regexp = TrimRegExp(regexp);
     }
     // matchIndices is either null or the RegExpLastMatchInfo array.
@@ -502,7 +499,7 @@
   var result;
   if (size === 0) {
     result = RegExpSubclassExec(splitter, string);
-    if (IS_NULL(result)) AddIndexedProperty(array, 0, string);
+    if (IS_NULL(result)) %AddElement(array, 0, string);
     return array;
   }
   var stringIndex = prevStringIndex;
@@ -515,10 +512,10 @@
       stringIndex += AdvanceStringIndex(string, stringIndex, unicode);
     } else {
       var end = MinSimple(TO_LENGTH(splitter.lastIndex), size);
-      if (end === stringIndex) {
+      if (end === prevStringIndex) {
         stringIndex += AdvanceStringIndex(string, stringIndex, unicode);
       } else {
-        AddIndexedProperty(
+        %AddElement(
             array, arrayIndex,
             %_SubString(string, prevStringIndex, stringIndex));
         arrayIndex++;
@@ -526,7 +523,7 @@
         prevStringIndex = end;
         var numberOfCaptures = MaxSimple(TO_LENGTH(result.length), 0);
         for (var i = 1; i < numberOfCaptures; i++) {
-          AddIndexedProperty(array, arrayIndex, result[i]);
+          %AddElement(array, arrayIndex, result[i]);
           arrayIndex++;
           if (arrayIndex === lim) return array;
         }
@@ -534,29 +531,13 @@
       }
     }
   }
-  AddIndexedProperty(array, arrayIndex,
+  %AddElement(array, arrayIndex,
                      %_SubString(string, prevStringIndex, size));
   return array;
 }
 %FunctionRemovePrototype(RegExpSubclassSplit);
 
 
-// Legacy implementation of RegExp.prototype[Symbol.match] which
-// doesn't properly call the underlying exec method
-function RegExpMatch(string) {
-  if (!IS_REGEXP(this)) {
-    throw MakeTypeError(kIncompatibleMethodReceiver,
-                        "RegExp.prototype.@@match", this);
-  }
-  var subject = TO_STRING(string);
-
-  if (!REGEXP_GLOBAL(this)) return RegExpExecNoTests(this, subject, 0);
-  this.lastIndex = 0;
-  var result = %StringMatch(subject, this, RegExpLastMatchInfo);
-  return result;
-}
-
-
 // ES#sec-regexp.prototype-@@match
 // RegExp.prototype [ @@match ] ( string )
 function RegExpSubclassMatch(string) {
@@ -956,19 +937,6 @@
 %FunctionRemovePrototype(RegExpSubclassReplace);
 
 
-// Legacy implementation of RegExp.prototype[Symbol.search] which
-// doesn't properly use the overridden exec method
-function RegExpSearch(string) {
-  if (!IS_REGEXP(this)) {
-    throw MakeTypeError(kIncompatibleMethodReceiver,
-                        "RegExp.prototype.@@search", this);
-  }
-  var match = DoRegExpExec(this, TO_STRING(string), 0);
-  if (match) return match[CAPTURE0];
-  return -1;
-}
-
-
 // ES#sec-regexp.prototype-@@search
 // RegExp.prototype [ @@search ] ( string )
 function RegExpSubclassSearch(string) {
@@ -1136,6 +1104,27 @@
 }
 %SetForceInlineFlag(RegExpGetSticky);
 
+
+// ES6 21.2.5.15.
+function RegExpGetUnicode() {
+  if (!IS_REGEXP(this)) {
+    // TODO(littledan): Remove this RegExp compat workaround
+    if (this === GlobalRegExpPrototype) {
+      %IncrementUseCounter(kRegExpPrototypeUnicodeGetter);
+      return UNDEFINED;
+    }
+    throw MakeTypeError(kRegExpNonRegExp, "RegExp.prototype.unicode");
+  }
+  return TO_BOOLEAN(REGEXP_UNICODE(this));
+}
+%SetForceInlineFlag(RegExpGetUnicode);
+
+
+function RegExpSpecies() {
+  return this;
+}
+
+
 // -------------------------------------------------------------------
 
 %FunctionSetInstanceClassName(GlobalRegExp, 'RegExp');
@@ -1145,15 +1134,17 @@
     GlobalRegExp.prototype, 'constructor', GlobalRegExp, DONT_ENUM);
 %SetCode(GlobalRegExp, RegExpConstructor);
 
+utils.InstallGetter(GlobalRegExp, speciesSymbol, RegExpSpecies);
+
 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [
-  "exec", RegExpExecJS,
-  "test", RegExpTest,
+  "exec", RegExpSubclassExecJS,
+  "test", RegExpSubclassTest,
   "toString", RegExpToString,
   "compile", RegExpCompileJS,
-  matchSymbol, RegExpMatch,
-  replaceSymbol, RegExpReplace,
-  searchSymbol, RegExpSearch,
-  splitSymbol, RegExpSplit,
+  matchSymbol, RegExpSubclassMatch,
+  replaceSymbol, RegExpSubclassReplace,
+  searchSymbol, RegExpSubclassSearch,
+  splitSymbol, RegExpSubclassSplit,
 ]);
 
 utils.InstallGetter(GlobalRegExp.prototype, 'flags', RegExpGetFlags);
@@ -1162,6 +1153,7 @@
 utils.InstallGetter(GlobalRegExp.prototype, 'multiline', RegExpGetMultiline);
 utils.InstallGetter(GlobalRegExp.prototype, 'source', RegExpGetSource);
 utils.InstallGetter(GlobalRegExp.prototype, 'sticky', RegExpGetSticky);
+utils.InstallGetter(GlobalRegExp.prototype, 'unicode', RegExpGetUnicode);
 
 // The properties `input` and `$_` are aliases for each other.  When this
 // value is set the value it is set to is coerced to a string.
@@ -1236,12 +1228,6 @@
   to.RegExpExec = DoRegExpExec;
   to.RegExpInitialize = RegExpInitialize;
   to.RegExpLastMatchInfo = RegExpLastMatchInfo;
-  to.RegExpSubclassExecJS = RegExpSubclassExecJS;
-  to.RegExpSubclassMatch = RegExpSubclassMatch;
-  to.RegExpSubclassReplace = RegExpSubclassReplace;
-  to.RegExpSubclassSearch = RegExpSubclassSearch;
-  to.RegExpSubclassSplit = RegExpSubclassSplit;
-  to.RegExpSubclassTest = RegExpSubclassTest;
   to.RegExpTest = RegExpTest;
 });
 
diff --git a/src/js/runtime.js b/src/js/runtime.js
index 8e4f283..216685f 100644
--- a/src/js/runtime.js
+++ b/src/js/runtime.js
@@ -16,7 +16,6 @@
 
 %CheckIsBootstrapping();
 
-var FLAG_harmony_species;
 var GlobalArray = global.Array;
 var GlobalBoolean = global.Boolean;
 var GlobalString = global.String;
@@ -30,10 +29,6 @@
   speciesSymbol = from.species_symbol;
 });
 
-utils.ImportFromExperimental(function(from) {
-  FLAG_harmony_species = from.FLAG_harmony_species;
-});
-
 // ----------------------------------------------------------------------------
 
 
@@ -43,21 +38,8 @@
 */
 
 
-// This function should be called rather than %AddElement in contexts where the
-// argument might not be less than 2**32-1. ES2015 ToLength semantics mean that
-// this is a concern at basically all callsites.
-function AddIndexedProperty(obj, index, value) {
-  if (index === TO_UINT32(index) && index !== kMaxUint32) {
-    %AddElement(obj, index, value);
-  } else {
-    %AddNamedProperty(obj, TO_STRING(index), value, NONE);
-  }
-}
-%SetForceInlineFlag(AddIndexedProperty);
-
-
 function ToPositiveInteger(x, rangeErrorIndex) {
-  var i = TO_INTEGER_MAP_MINUS_ZERO(x);
+  var i = TO_INTEGER(x) + 0;
   if (i < 0) throw MakeRangeError(rangeErrorIndex);
   return i;
 }
@@ -78,35 +60,22 @@
 
 
 // ES2015 7.3.20
-// For the fallback with --harmony-species off, there are two possible choices:
-//  - "conservative": return defaultConstructor
-//  - "not conservative": return object.constructor
-// This fallback path is only needed in the transition to ES2015, and the
-// choice is made simply to preserve the previous behavior so that we don't
-// have a three-step upgrade: old behavior, unspecified intermediate behavior,
-// and ES2015.
-// In some cases, we were "conservative" (e.g., ArrayBuffer, RegExp), and in
-// other cases we were "not conservative (e.g., TypedArray, Promise).
-function SpeciesConstructor(object, defaultConstructor, conservative) {
-  if (FLAG_harmony_species) {
-    var constructor = object.constructor;
-    if (IS_UNDEFINED(constructor)) {
-      return defaultConstructor;
-    }
-    if (!IS_RECEIVER(constructor)) {
-      throw MakeTypeError(kConstructorNotReceiver);
-    }
-    var species = constructor[speciesSymbol];
-    if (IS_NULL_OR_UNDEFINED(species)) {
-      return defaultConstructor;
-    }
-    if (%IsConstructor(species)) {
-      return species;
-    }
-    throw MakeTypeError(kSpeciesNotConstructor);
-  } else {
-    return conservative ? defaultConstructor : object.constructor;
+function SpeciesConstructor(object, defaultConstructor) {
+  var constructor = object.constructor;
+  if (IS_UNDEFINED(constructor)) {
+    return defaultConstructor;
   }
+  if (!IS_RECEIVER(constructor)) {
+    throw MakeTypeError(kConstructorNotReceiver);
+  }
+  var species = constructor[speciesSymbol];
+  if (IS_NULL_OR_UNDEFINED(species)) {
+    return defaultConstructor;
+  }
+  if (%IsConstructor(species)) {
+    return species;
+  }
+  throw MakeTypeError(kSpeciesNotConstructor);
 }
 
 //----------------------------------------------------------------------------
@@ -122,7 +91,6 @@
 // Exports
 
 utils.Export(function(to) {
-  to.AddIndexedProperty = AddIndexedProperty;
   to.MaxSimple = MaxSimple;
   to.MinSimple = MinSimple;
   to.ToPositiveInteger = ToPositiveInteger;
diff --git a/src/js/string.js b/src/js/string.js
index 0eb394e..d2eaa32 100644
--- a/src/js/string.js
+++ b/src/js/string.js
@@ -13,8 +13,6 @@
 var ArrayJoin;
 var GlobalRegExp = global.RegExp;
 var GlobalString = global.String;
-var InternalArray = utils.InternalArray;
-var InternalPackedArray = utils.InternalPackedArray;
 var IsRegExp;
 var MakeRangeError;
 var MakeTypeError;
@@ -57,30 +55,6 @@
 }
 
 
-// ECMA-262, section 15.5.4.4
-function StringCharAtJS(pos) {
-  CHECK_OBJECT_COERCIBLE(this, "String.prototype.charAt");
-
-  var result = %_StringCharAt(this, pos);
-  if (%_IsSmi(result)) {
-    result = %_StringCharAt(TO_STRING(this), TO_INTEGER(pos));
-  }
-  return result;
-}
-
-
-// ECMA-262 section 15.5.4.5
-function StringCharCodeAtJS(pos) {
-  CHECK_OBJECT_COERCIBLE(this, "String.prototype.charCodeAt");
-
-  var result = %_StringCharCodeAt(this, pos);
-  if (!%_IsSmi(result)) {
-    result = %_StringCharCodeAt(TO_STRING(this), TO_INTEGER(pos));
-  }
-  return result;
-}
-
-
 // ECMA-262, section 15.5.4.6
 function StringConcat(other /* and more */) {  // length == 1
   "use strict";
@@ -544,25 +518,6 @@
   return %StringToUpperCase(TO_STRING(this));
 }
 
-// ES5, 15.5.4.20
-function StringTrimJS() {
-  CHECK_OBJECT_COERCIBLE(this, "String.prototype.trim");
-
-  return %StringTrim(TO_STRING(this), true, true);
-}
-
-function StringTrimLeft() {
-  CHECK_OBJECT_COERCIBLE(this, "String.prototype.trimLeft");
-
-  return %StringTrim(TO_STRING(this), true, false);
-}
-
-function StringTrimRight() {
-  CHECK_OBJECT_COERCIBLE(this, "String.prototype.trimRight");
-
-  return %StringTrim(TO_STRING(this), false, true);
-}
-
 
 // ES6 draft, revision 26 (2014-07-18), section B.2.3.2.1
 function HtmlEscape(str) {
@@ -792,33 +747,6 @@
 }
 
 
-// ES6 Draft 05-22-2014, section 21.1.2.2
-function StringFromCodePoint(_) {  // length = 1
-  "use strict";
-  var code;
-  var length = arguments.length;
-  var index;
-  var result = "";
-  for (index = 0; index < length; index++) {
-    code = arguments[index];
-    if (!%_IsSmi(code)) {
-      code = TO_NUMBER(code);
-    }
-    if (code < 0 || code > 0x10FFFF || code !== TO_INTEGER(code)) {
-      throw MakeRangeError(kInvalidCodePoint, code);
-    }
-    if (code <= 0xFFFF) {
-      result += %_StringCharFromCode(code);
-    } else {
-      code -= 0x10000;
-      result += %_StringCharFromCode((code >>> 10) & 0x3FF | 0xD800);
-      result += %_StringCharFromCode(code & 0x3FF | 0xDC00);
-    }
-  }
-  return result;
-}
-
-
 // -------------------------------------------------------------------
 // String methods related to templates
 
@@ -845,16 +773,8 @@
 
 // -------------------------------------------------------------------
 
-// Set the String function and constructor.
-%FunctionSetPrototype(GlobalString, new GlobalString());
-
-// Set up the constructor property on the String prototype object.
-%AddNamedProperty(
-    GlobalString.prototype, "constructor", GlobalString, DONT_ENUM);
-
 // Set up the non-enumerable functions on the String object.
 utils.InstallFunctions(GlobalString, DONT_ENUM, [
-  "fromCodePoint", StringFromCodePoint,
   "raw", StringRaw
 ]);
 
@@ -862,8 +782,6 @@
 utils.InstallFunctions(GlobalString.prototype, DONT_ENUM, [
   "valueOf", StringValueOf,
   "toString", StringToString,
-  "charAt", StringCharAtJS,
-  "charCodeAt", StringCharCodeAtJS,
   "codePointAt", StringCodePointAt,
   "concat", StringConcat,
   "endsWith", StringEndsWith,
@@ -885,9 +803,6 @@
   "toLocaleLowerCase", StringToLocaleLowerCase,
   "toUpperCase", StringToUpperCaseJS,
   "toLocaleUpperCase", StringToLocaleUpperCase,
-  "trim", StringTrimJS,
-  "trimLeft", StringTrimLeft,
-  "trimRight", StringTrimRight,
 
   "link", StringLink,
   "anchor", StringAnchor,
@@ -909,7 +824,6 @@
 
 utils.Export(function(to) {
   to.ExpandReplacement = ExpandReplacement;
-  to.StringCharAt = StringCharAtJS;
   to.StringIndexOf = StringIndexOf;
   to.StringLastIndexOf = StringLastIndexOf;
   to.StringMatch = StringMatchJS;
diff --git a/src/js/symbol.js b/src/js/symbol.js
index 7365655..2e7cc53 100644
--- a/src/js/symbol.js
+++ b/src/js/symbol.js
@@ -17,6 +17,11 @@
     utils.ImportNow("is_concat_spreadable_symbol");
 var iteratorSymbol = utils.ImportNow("iterator_symbol");
 var MakeTypeError;
+var matchSymbol = utils.ImportNow("match_symbol");
+var replaceSymbol = utils.ImportNow("replace_symbol");
+var searchSymbol = utils.ImportNow("search_symbol");
+var speciesSymbol = utils.ImportNow("species_symbol");
+var splitSymbol = utils.ImportNow("split_symbol");
 var toPrimitiveSymbol = utils.ImportNow("to_primitive_symbol");
 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
 var unscopablesSymbol = utils.ImportNow("unscopables_symbol");
@@ -78,11 +83,11 @@
   "hasInstance", hasInstanceSymbol,
   "isConcatSpreadable", isConcatSpreadableSymbol,
   "iterator", iteratorSymbol,
-  // TODO(yangguo): expose when implemented.
-  // "match", matchSymbol,
-  // "replace", replaceSymbol,
-  // "search", searchSymbol,
-  // "split, splitSymbol,
+  "match", matchSymbol,
+  "replace", replaceSymbol,
+  "search", searchSymbol,
+  "species", speciesSymbol,
+  "split", splitSymbol,
   "toPrimitive", toPrimitiveSymbol,
   "toStringTag", toStringTagSymbol,
   "unscopables", unscopablesSymbol,
diff --git a/src/js/typedarray.js b/src/js/typedarray.js
index 4fb174b..8e7d9ee 100644
--- a/src/js/typedarray.js
+++ b/src/js/typedarray.js
@@ -11,7 +11,6 @@
 // -------------------------------------------------------------------
 // Imports
 
-var AddIndexedProperty;
 // array.js has to come before typedarray.js for this to work
 var ArrayToString = utils.ImportNow("ArrayToString");
 var ArrayValues;
@@ -22,7 +21,6 @@
 var GlobalArrayBufferPrototype = GlobalArrayBuffer.prototype;
 var GlobalDataView = global.DataView;
 var GlobalObject = global.Object;
-var InternalArray = utils.InternalArray;
 var InnerArrayCopyWithin;
 var InnerArrayEvery;
 var InnerArrayFill;
@@ -49,6 +47,7 @@
 var SpeciesConstructor;
 var ToPositiveInteger;
 var iteratorSymbol = utils.ImportNow("iterator_symbol");
+var speciesSymbol = utils.ImportNow("species_symbol");
 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
 
 macro TYPED_ARRAYS(FUNCTION)
@@ -70,8 +69,9 @@
 
 TYPED_ARRAYS(DECLARE_GLOBALS)
 
+var GlobalTypedArray = %object_get_prototype_of(GlobalUint8Array);
+
 utils.Import(function(from) {
-  AddIndexedProperty = from.AddIndexedProperty;
   ArrayValues = from.ArrayValues;
   GetIterator = from.GetIterator;
   GetMethod = from.GetMethod;
@@ -332,42 +332,6 @@
 }
 %SetForceInlineFlag(TypedArraySubArray);
 
-function TypedArrayGetBuffer() {
-  if (!IS_TYPEDARRAY(this)) {
-    throw MakeTypeError(kIncompatibleMethodReceiver,
-                        "get TypedArray.prototype.buffer", this);
-  }
-  return %TypedArrayGetBuffer(this);
-}
-%SetForceInlineFlag(TypedArrayGetBuffer);
-
-function TypedArrayGetByteLength() {
-  if (!IS_TYPEDARRAY(this)) {
-    throw MakeTypeError(kIncompatibleMethodReceiver,
-                        "get TypedArray.prototype.byteLength", this);
-  }
-  return %_ArrayBufferViewGetByteLength(this);
-}
-%SetForceInlineFlag(TypedArrayGetByteLength);
-
-function TypedArrayGetByteOffset() {
-  if (!IS_TYPEDARRAY(this)) {
-    throw MakeTypeError(kIncompatibleMethodReceiver,
-                        "get TypedArray.prototype.byteOffset", this);
-  }
-  return %_ArrayBufferViewGetByteOffset(this);
-}
-%SetForceInlineFlag(TypedArrayGetByteOffset);
-
-function TypedArrayGetLength() {
-  if (!IS_TYPEDARRAY(this)) {
-    throw MakeTypeError(kIncompatibleMethodReceiver,
-                        "get TypedArray.prototype.length", this);
-  }
-  return %_TypedArrayGetLength(this);
-}
-%SetForceInlineFlag(TypedArrayGetLength);
-
 
 
 function TypedArraySetFromArrayLike(target, source, sourceLength, offset) {
@@ -386,7 +350,7 @@
 function TypedArraySetFromOverlappingTypedArray(target, source, offset) {
   var sourceElementSize = source.BYTES_PER_ELEMENT;
   var targetElementSize = target.BYTES_PER_ELEMENT;
-  var sourceLength = source.length;
+  var sourceLength = %_TypedArrayGetLength(source);
 
   // Copy left part.
   function CopyLeftPart() {
@@ -406,7 +370,7 @@
   }
   var leftIndex = CopyLeftPart();
 
-  // Copy rigth part;
+  // Copy right part;
   function CopyRightPart() {
     // First unmutated byte before the next write
     var targetPtr =
@@ -450,7 +414,8 @@
       TypedArraySetFromOverlappingTypedArray(this, obj, intOffset);
       return;
     case 2: // TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING
-      TypedArraySetFromArrayLike(this, obj, obj.length, intOffset);
+      TypedArraySetFromArrayLike(this,
+          obj, %_TypedArrayGetLength(obj), intOffset);
       return;
     case 3: // TYPED_ARRAY_SET_NON_TYPED_ARRAY
       var l = obj.length;
@@ -465,7 +430,7 @@
         return;
       }
       l = TO_LENGTH(l);
-      if (intOffset + l > this.length) {
+      if (intOffset + l > %_TypedArrayGetLength(this)) {
         throw MakeRangeError(kTypedArraySetSourceTooLarge);
       }
       TypedArraySetFromArrayLike(this, obj, l, intOffset);
@@ -811,34 +776,31 @@
 }
 %FunctionSetLength(TypedArrayFrom, 1);
 
-function TypedArray() {
+// TODO(bmeurer): Migrate this to a proper builtin.
+function TypedArrayConstructor() {
   if (IS_UNDEFINED(new.target)) {
     throw MakeTypeError(kConstructorNonCallable, "TypedArray");
   }
-  if (new.target === TypedArray) {
+  if (new.target === GlobalTypedArray) {
     throw MakeTypeError(kConstructAbstractClass, "TypedArray");
   }
 }
 
+function TypedArraySpecies() {
+  return this;
+}
+
 // -------------------------------------------------------------------
 
-%FunctionSetPrototype(TypedArray, new GlobalObject());
-%AddNamedProperty(TypedArray.prototype,
-                  "constructor", TypedArray, DONT_ENUM);
-utils.InstallFunctions(TypedArray, DONT_ENUM, [
+%SetCode(GlobalTypedArray, TypedArrayConstructor);
+utils.InstallFunctions(GlobalTypedArray, DONT_ENUM, [
   "from", TypedArrayFrom,
   "of", TypedArrayOf
 ]);
-utils.InstallGetter(TypedArray.prototype, "buffer", TypedArrayGetBuffer);
-utils.InstallGetter(TypedArray.prototype, "byteOffset", TypedArrayGetByteOffset,
-                    DONT_ENUM | DONT_DELETE);
-utils.InstallGetter(TypedArray.prototype, "byteLength",
-                    TypedArrayGetByteLength, DONT_ENUM | DONT_DELETE);
-utils.InstallGetter(TypedArray.prototype, "length", TypedArrayGetLength,
-                    DONT_ENUM | DONT_DELETE);
-utils.InstallGetter(TypedArray.prototype, toStringTagSymbol,
+utils.InstallGetter(GlobalTypedArray, speciesSymbol, TypedArraySpecies);
+utils.InstallGetter(GlobalTypedArray.prototype, toStringTagSymbol,
                     TypedArrayGetToStringTag);
-utils.InstallFunctions(TypedArray.prototype, DONT_ENUM, [
+utils.InstallFunctions(GlobalTypedArray.prototype, DONT_ENUM, [
   "subarray", TypedArraySubArray,
   "set", TypedArraySet,
   "copyWithin", TypedArrayCopyWithin,
@@ -862,15 +824,15 @@
   "toLocaleString", TypedArrayToLocaleString
 ]);
 
-%AddNamedProperty(TypedArray.prototype, "toString", ArrayToString,
+%AddNamedProperty(GlobalTypedArray.prototype, "toString", ArrayToString,
                   DONT_ENUM);
 
 
 macro SETUP_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE)
   %SetCode(GlobalNAME, NAMEConstructor);
   %FunctionSetPrototype(GlobalNAME, new GlobalObject());
-  %InternalSetPrototype(GlobalNAME, TypedArray);
-  %InternalSetPrototype(GlobalNAME.prototype, TypedArray.prototype);
+  %InternalSetPrototype(GlobalNAME, GlobalTypedArray);
+  %InternalSetPrototype(GlobalNAME.prototype, GlobalTypedArray.prototype);
 
   %AddNamedProperty(GlobalNAME, "BYTES_PER_ELEMENT", ELEMENT_SIZE,
                     READ_ONLY | DONT_ENUM | DONT_DELETE);
@@ -886,29 +848,6 @@
 
 // --------------------------- DataView -----------------------------
 
-function DataViewGetBufferJS() {
-  if (!IS_DATAVIEW(this)) {
-    throw MakeTypeError(kIncompatibleMethodReceiver, 'DataView.buffer', this);
-  }
-  return %DataViewGetBuffer(this);
-}
-
-function DataViewGetByteOffset() {
-  if (!IS_DATAVIEW(this)) {
-    throw MakeTypeError(kIncompatibleMethodReceiver,
-                        'DataView.byteOffset', this);
-  }
-  return %_ArrayBufferViewGetByteOffset(this);
-}
-
-function DataViewGetByteLength() {
-  if (!IS_DATAVIEW(this)) {
-    throw MakeTypeError(kIncompatibleMethodReceiver,
-                        'DataView.byteLength', this);
-  }
-  return %_ArrayBufferViewGetByteLength(this);
-}
-
 macro DATA_VIEW_TYPES(FUNCTION)
   FUNCTION(Int8)
   FUNCTION(Uint8)
@@ -947,21 +886,6 @@
 
 DATA_VIEW_TYPES(DATA_VIEW_GETTER_SETTER)
 
-// Setup the DataView constructor.
-%FunctionSetPrototype(GlobalDataView, new GlobalObject);
-
-// Set up constructor property on the DataView prototype.
-%AddNamedProperty(GlobalDataView.prototype, "constructor", GlobalDataView,
-                  DONT_ENUM);
-%AddNamedProperty(GlobalDataView.prototype, toStringTagSymbol, "DataView",
-                  READ_ONLY|DONT_ENUM);
-
-utils.InstallGetter(GlobalDataView.prototype, "buffer", DataViewGetBufferJS);
-utils.InstallGetter(GlobalDataView.prototype, "byteOffset",
-                    DataViewGetByteOffset);
-utils.InstallGetter(GlobalDataView.prototype, "byteLength",
-                    DataViewGetByteLength);
-
 utils.InstallFunctions(GlobalDataView.prototype, DONT_ENUM, [
   "getInt8", DataViewGetInt8JS,
   "setInt8", DataViewSetInt8JS,
diff --git a/src/js/uri.js b/src/js/uri.js
deleted file mode 100644
index dca83c9..0000000
--- a/src/js/uri.js
+++ /dev/null
@@ -1,379 +0,0 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file contains support for URI manipulations written in
-// JavaScript.
-
-(function(global, utils) {
-
-"use strict";
-
-%CheckIsBootstrapping();
-
-//- ------------------------------------------------------------------
-// Imports
-
-var GlobalObject = global.Object;
-var InternalArray = utils.InternalArray;
-var MakeURIError;
-
-utils.Import(function(from) {
-  MakeURIError = from.MakeURIError;
-});
-
-
-// -------------------------------------------------------------------
-// Define internal helper functions.
-
-function HexValueOf(code) {
-  // 0-9
-  if (code >= 48 && code <= 57) return code - 48;
-  // A-F
-  if (code >= 65 && code <= 70) return code - 55;
-  // a-f
-  if (code >= 97 && code <= 102) return code - 87;
-
-  return -1;
-}
-
-// Does the char code correspond to an alpha-numeric char.
-function isAlphaNumeric(cc) {
-  // a - z
-  if (97 <= cc && cc <= 122) return true;
-  // A - Z
-  if (65 <= cc && cc <= 90) return true;
-  // 0 - 9
-  if (48 <= cc && cc <= 57) return true;
-
-  return false;
-}
-
-// Lazily initialized.
-var hexCharCodeArray = 0;
-
-function URIAddEncodedOctetToBuffer(octet, result, index) {
-  result[index++] = 37; // Char code of '%'.
-  result[index++] = hexCharCodeArray[octet >> 4];
-  result[index++] = hexCharCodeArray[octet & 0x0F];
-  return index;
-}
-
-function URIEncodeOctets(octets, result, index) {
-  if (hexCharCodeArray === 0) {
-    hexCharCodeArray = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
-                        65, 66, 67, 68, 69, 70];
-  }
-  index = URIAddEncodedOctetToBuffer(octets[0], result, index);
-  if (octets[1]) index = URIAddEncodedOctetToBuffer(octets[1], result, index);
-  if (octets[2]) index = URIAddEncodedOctetToBuffer(octets[2], result, index);
-  if (octets[3]) index = URIAddEncodedOctetToBuffer(octets[3], result, index);
-  return index;
-}
-
-function URIEncodeSingle(cc, result, index) {
-  var x = (cc >> 12) & 0xF;
-  var y = (cc >> 6) & 63;
-  var z = cc & 63;
-  var octets = new InternalArray(3);
-  if (cc <= 0x007F) {
-    octets[0] = cc;
-  } else if (cc <= 0x07FF) {
-    octets[0] = y + 192;
-    octets[1] = z + 128;
-  } else {
-    octets[0] = x + 224;
-    octets[1] = y + 128;
-    octets[2] = z + 128;
-  }
-  return URIEncodeOctets(octets, result, index);
-}
-
-function URIEncodePair(cc1 , cc2, result, index) {
-  var u = ((cc1 >> 6) & 0xF) + 1;
-  var w = (cc1 >> 2) & 0xF;
-  var x = cc1 & 3;
-  var y = (cc2 >> 6) & 0xF;
-  var z = cc2 & 63;
-  var octets = new InternalArray(4);
-  octets[0] = (u >> 2) + 240;
-  octets[1] = (((u & 3) << 4) | w) + 128;
-  octets[2] = ((x << 4) | y) + 128;
-  octets[3] = z + 128;
-  return URIEncodeOctets(octets, result, index);
-}
-
-function URIHexCharsToCharCode(highChar, lowChar) {
-  var highCode = HexValueOf(highChar);
-  var lowCode = HexValueOf(lowChar);
-  if (highCode == -1 || lowCode == -1) throw MakeURIError();
-  return (highCode << 4) | lowCode;
-}
-
-// Callers must ensure that |result| is a sufficiently long sequential
-// two-byte string!
-function URIDecodeOctets(octets, result, index) {
-  var value;
-  var o0 = octets[0];
-  if (o0 < 0x80) {
-    value = o0;
-  } else if (o0 < 0xc2) {
-    throw MakeURIError();
-  } else {
-    var o1 = octets[1];
-    if (o0 < 0xe0) {
-      var a = o0 & 0x1f;
-      if ((o1 < 0x80) || (o1 > 0xbf)) throw MakeURIError();
-      var b = o1 & 0x3f;
-      value = (a << 6) + b;
-      if (value < 0x80 || value > 0x7ff) throw MakeURIError();
-    } else {
-      var o2 = octets[2];
-      if (o0 < 0xf0) {
-        var a = o0 & 0x0f;
-        if ((o1 < 0x80) || (o1 > 0xbf)) throw MakeURIError();
-        var b = o1 & 0x3f;
-        if ((o2 < 0x80) || (o2 > 0xbf)) throw MakeURIError();
-        var c = o2 & 0x3f;
-        value = (a << 12) + (b << 6) + c;
-        if ((value < 0x800) || (value > 0xffff)) throw MakeURIError();
-      } else {
-        var o3 = octets[3];
-        if (o0 < 0xf8) {
-          var a = (o0 & 0x07);
-          if ((o1 < 0x80) || (o1 > 0xbf)) throw MakeURIError();
-          var b = (o1 & 0x3f);
-          if ((o2 < 0x80) || (o2 > 0xbf)) {
-            throw MakeURIError();
-          }
-          var c = (o2 & 0x3f);
-          if ((o3 < 0x80) || (o3 > 0xbf)) throw MakeURIError();
-          var d = (o3 & 0x3f);
-          value = (a << 18) + (b << 12) + (c << 6) + d;
-          if ((value < 0x10000) || (value > 0x10ffff)) throw MakeURIError();
-        } else {
-          throw MakeURIError();
-        }
-      }
-    }
-  }
-  if (0xD800 <= value && value <= 0xDFFF) throw MakeURIError();
-  if (value < 0x10000) {
-    %_TwoByteSeqStringSetChar(index++, value, result);
-  } else {
-    %_TwoByteSeqStringSetChar(index++, (value >> 10) + 0xd7c0, result);
-    %_TwoByteSeqStringSetChar(index++, (value & 0x3ff) + 0xdc00, result);
-  }
-  return index;
-}
-
-// ECMA-262, section 15.1.3
-function Encode(uri, unescape) {
-  uri = TO_STRING(uri);
-  var uriLength = uri.length;
-  var array = new InternalArray(uriLength);
-  var index = 0;
-  for (var k = 0; k < uriLength; k++) {
-    var cc1 = %_StringCharCodeAt(uri, k);
-    if (unescape(cc1)) {
-      array[index++] = cc1;
-    } else {
-      if (cc1 >= 0xDC00 && cc1 <= 0xDFFF) throw MakeURIError();
-      if (cc1 < 0xD800 || cc1 > 0xDBFF) {
-        index = URIEncodeSingle(cc1, array, index);
-      } else {
-        k++;
-        if (k == uriLength) throw MakeURIError();
-        var cc2 = %_StringCharCodeAt(uri, k);
-        if (cc2 < 0xDC00 || cc2 > 0xDFFF) throw MakeURIError();
-        index = URIEncodePair(cc1, cc2, array, index);
-      }
-    }
-  }
-
-  var result = %NewString(array.length, NEW_ONE_BYTE_STRING);
-  for (var i = 0; i < array.length; i++) {
-    %_OneByteSeqStringSetChar(i, array[i], result);
-  }
-  return result;
-}
-
-// ECMA-262, section 15.1.3
-function Decode(uri, reserved) {
-  uri = TO_STRING(uri);
-  var uriLength = uri.length;
-  var one_byte = %NewString(uriLength, NEW_ONE_BYTE_STRING);
-  var index = 0;
-  var k = 0;
-
-  // Optimistically assume one-byte string.
-  for ( ; k < uriLength; k++) {
-    var code = %_StringCharCodeAt(uri, k);
-    if (code == 37) {  // '%'
-      if (k + 2 >= uriLength) throw MakeURIError();
-      var cc = URIHexCharsToCharCode(%_StringCharCodeAt(uri, k+1),
-                                     %_StringCharCodeAt(uri, k+2));
-      if (cc >> 7) break;  // Assumption wrong, two-byte string.
-      if (reserved(cc)) {
-        %_OneByteSeqStringSetChar(index++, 37, one_byte);  // '%'.
-        %_OneByteSeqStringSetChar(index++, %_StringCharCodeAt(uri, k+1),
-                                  one_byte);
-        %_OneByteSeqStringSetChar(index++, %_StringCharCodeAt(uri, k+2),
-                                  one_byte);
-      } else {
-        %_OneByteSeqStringSetChar(index++, cc, one_byte);
-      }
-      k += 2;
-    } else {
-      if (code > 0x7f) break;  // Assumption wrong, two-byte string.
-      %_OneByteSeqStringSetChar(index++, code, one_byte);
-    }
-  }
-
-  one_byte = %TruncateString(one_byte, index);
-  if (k == uriLength) return one_byte;
-
-  // Write into two byte string.
-  var two_byte = %NewString(uriLength - k, NEW_TWO_BYTE_STRING);
-  index = 0;
-
-  for ( ; k < uriLength; k++) {
-    var code = %_StringCharCodeAt(uri, k);
-    if (code == 37) {  // '%'
-      if (k + 2 >= uriLength) throw MakeURIError();
-      var cc = URIHexCharsToCharCode(%_StringCharCodeAt(uri, ++k),
-                                     %_StringCharCodeAt(uri, ++k));
-      if (cc >> 7) {
-        var n = 0;
-        while (((cc << ++n) & 0x80) != 0) { }
-        if (n == 1 || n > 4) throw MakeURIError();
-        var octets = new InternalArray(n);
-        octets[0] = cc;
-        if (k + 3 * (n - 1) >= uriLength) throw MakeURIError();
-        for (var i = 1; i < n; i++) {
-          if (uri[++k] != '%') throw MakeURIError();
-          octets[i] = URIHexCharsToCharCode(%_StringCharCodeAt(uri, ++k),
-                                            %_StringCharCodeAt(uri, ++k));
-        }
-        index = URIDecodeOctets(octets, two_byte, index);
-      } else  if (reserved(cc)) {
-        %_TwoByteSeqStringSetChar(index++, 37, two_byte);  // '%'.
-        %_TwoByteSeqStringSetChar(index++, %_StringCharCodeAt(uri, k - 1),
-                                  two_byte);
-        %_TwoByteSeqStringSetChar(index++, %_StringCharCodeAt(uri, k),
-                                  two_byte);
-      } else {
-        %_TwoByteSeqStringSetChar(index++, cc, two_byte);
-      }
-    } else {
-      %_TwoByteSeqStringSetChar(index++, code, two_byte);
-    }
-  }
-
-  two_byte = %TruncateString(two_byte, index);
-  return one_byte + two_byte;
-}
-
-// -------------------------------------------------------------------
-// Define exported functions.
-
-// ECMA-262 - B.2.1.
-function URIEscapeJS(s) {
-  return %URIEscape(s);
-}
-
-// ECMA-262 - B.2.2.
-function URIUnescapeJS(s) {
-  return %URIUnescape(s);
-}
-
-// ECMA-262 - 15.1.3.1.
-function URIDecode(uri) {
-  var reservedPredicate = function(cc) {
-    // #$
-    if (35 <= cc && cc <= 36) return true;
-    // &
-    if (cc == 38) return true;
-    // +,
-    if (43 <= cc && cc <= 44) return true;
-    // /
-    if (cc == 47) return true;
-    // :;
-    if (58 <= cc && cc <= 59) return true;
-    // =
-    if (cc == 61) return true;
-    // ?@
-    if (63 <= cc && cc <= 64) return true;
-
-    return false;
-  };
-  return Decode(uri, reservedPredicate);
-}
-
-// ECMA-262 - 15.1.3.2.
-function URIDecodeComponent(component) {
-  var reservedPredicate = function(cc) { return false; };
-  return Decode(component, reservedPredicate);
-}
-
-// ECMA-262 - 15.1.3.3.
-function URIEncode(uri) {
-  var unescapePredicate = function(cc) {
-    if (isAlphaNumeric(cc)) return true;
-    // !
-    if (cc == 33) return true;
-    // #$
-    if (35 <= cc && cc <= 36) return true;
-    // &'()*+,-./
-    if (38 <= cc && cc <= 47) return true;
-    // :;
-    if (58 <= cc && cc <= 59) return true;
-    // =
-    if (cc == 61) return true;
-    // ?@
-    if (63 <= cc && cc <= 64) return true;
-    // _
-    if (cc == 95) return true;
-    // ~
-    if (cc == 126) return true;
-
-    return false;
-  };
-  return Encode(uri, unescapePredicate);
-}
-
-// ECMA-262 - 15.1.3.4
-function URIEncodeComponent(component) {
-  var unescapePredicate = function(cc) {
-    if (isAlphaNumeric(cc)) return true;
-    // !
-    if (cc == 33) return true;
-    // '()*
-    if (39 <= cc && cc <= 42) return true;
-    // -.
-    if (45 <= cc && cc <= 46) return true;
-    // _
-    if (cc == 95) return true;
-    // ~
-    if (cc == 126) return true;
-
-    return false;
-  };
-  return Encode(component, unescapePredicate);
-}
-
-// -------------------------------------------------------------------
-// Install exported functions.
-
-// Set up non-enumerable URI functions on the global object and set
-// their names.
-utils.InstallFunctions(global, DONT_ENUM, [
-  "escape", URIEscapeJS,
-  "unescape", URIUnescapeJS,
-  "decodeURI", URIDecode,
-  "decodeURIComponent", URIDecodeComponent,
-  "encodeURI", URIEncode,
-  "encodeURIComponent", URIEncodeComponent
-]);
-
-})
diff --git a/src/js/v8natives.js b/src/js/v8natives.js
index 5185c62..9e437a3 100644
--- a/src/js/v8natives.js
+++ b/src/js/v8natives.js
@@ -12,7 +12,6 @@
 var GlobalArray = global.Array;
 var GlobalNumber = global.Number;
 var GlobalObject = global.Object;
-var InternalArray = utils.InternalArray;
 var iteratorSymbol = utils.ImportNow("iterator_symbol");
 var MakeRangeError;
 var MakeSyntaxError;
@@ -20,9 +19,6 @@
 var MathAbs;
 var NaN = %GetRootNaN();
 var ObjectToString = utils.ImportNow("object_to_string");
-var ObserveBeginPerformSplice;
-var ObserveEndPerformSplice;
-var ObserveEnqueueSpliceRecord;
 var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
 
 utils.Import(function(from) {
@@ -30,9 +26,6 @@
   MakeSyntaxError = from.MakeSyntaxError;
   MakeTypeError = from.MakeTypeError;
   MathAbs = from.MathAbs;
-  ObserveBeginPerformSplice = from.ObserveBeginPerformSplice;
-  ObserveEndPerformSplice = from.ObserveEndPerformSplice;
-  ObserveEnqueueSpliceRecord = from.ObserveEnqueueSpliceRecord;
 });
 
 // ----------------------------------------------------------------------------
@@ -148,348 +141,6 @@
   return %PropertyIsEnumerable(TO_OBJECT(this), P);
 }
 
-
-// Extensions for providing property getters and setters.
-function ObjectDefineGetter(name, fun) {
-  var receiver = this;
-  if (IS_NULL(receiver) || IS_UNDEFINED(receiver)) {
-    receiver = %GlobalProxy(ObjectDefineGetter);
-  }
-  if (!IS_CALLABLE(fun)) {
-    throw MakeTypeError(kObjectGetterExpectingFunction);
-  }
-  var desc = new PropertyDescriptor();
-  desc.setGet(fun);
-  desc.setEnumerable(true);
-  desc.setConfigurable(true);
-  DefineOwnProperty(TO_OBJECT(receiver), TO_NAME(name), desc, false);
-}
-
-
-function ObjectLookupGetter(name) {
-  var receiver = this;
-  if (IS_NULL(receiver) || IS_UNDEFINED(receiver)) {
-    receiver = %GlobalProxy(ObjectLookupGetter);
-  }
-  return %LookupAccessor(TO_OBJECT(receiver), TO_NAME(name), GETTER);
-}
-
-
-function ObjectDefineSetter(name, fun) {
-  var receiver = this;
-  if (IS_NULL(receiver) || IS_UNDEFINED(receiver)) {
-    receiver = %GlobalProxy(ObjectDefineSetter);
-  }
-  if (!IS_CALLABLE(fun)) {
-    throw MakeTypeError(kObjectSetterExpectingFunction);
-  }
-  var desc = new PropertyDescriptor();
-  desc.setSet(fun);
-  desc.setEnumerable(true);
-  desc.setConfigurable(true);
-  DefineOwnProperty(TO_OBJECT(receiver), TO_NAME(name), desc, false);
-}
-
-
-function ObjectLookupSetter(name) {
-  var receiver = this;
-  if (IS_NULL(receiver) || IS_UNDEFINED(receiver)) {
-    receiver = %GlobalProxy(ObjectLookupSetter);
-  }
-  return %LookupAccessor(TO_OBJECT(receiver), TO_NAME(name), SETTER);
-}
-
-
-// ES6 6.2.4.1
-function IsAccessorDescriptor(desc) {
-  if (IS_UNDEFINED(desc)) return false;
-  return desc.hasGetter() || desc.hasSetter();
-}
-
-
-// ES6 6.2.4.2
-function IsDataDescriptor(desc) {
-  if (IS_UNDEFINED(desc)) return false;
-  return desc.hasValue() || desc.hasWritable();
-}
-
-
-// ES6 6.2.4.3
-function IsGenericDescriptor(desc) {
-  if (IS_UNDEFINED(desc)) return false;
-  return !(IsAccessorDescriptor(desc) || IsDataDescriptor(desc));
-}
-
-
-function IsInconsistentDescriptor(desc) {
-  return IsAccessorDescriptor(desc) && IsDataDescriptor(desc);
-}
-
-
-// Harmony Proxies
-function FromGenericPropertyDescriptor(desc) {
-  if (IS_UNDEFINED(desc)) return desc;
-  var obj = new GlobalObject();
-
-  if (desc.hasValue()) {
-    %AddNamedProperty(obj, "value", desc.getValue(), NONE);
-  }
-  if (desc.hasWritable()) {
-    %AddNamedProperty(obj, "writable", desc.isWritable(), NONE);
-  }
-  if (desc.hasGetter()) {
-    %AddNamedProperty(obj, "get", desc.getGet(), NONE);
-  }
-  if (desc.hasSetter()) {
-    %AddNamedProperty(obj, "set", desc.getSet(), NONE);
-  }
-  if (desc.hasEnumerable()) {
-    %AddNamedProperty(obj, "enumerable", desc.isEnumerable(), NONE);
-  }
-  if (desc.hasConfigurable()) {
-    %AddNamedProperty(obj, "configurable", desc.isConfigurable(), NONE);
-  }
-  return obj;
-}
-
-
-// ES6 6.2.4.5
-function ToPropertyDescriptor(obj) {
-  if (!IS_RECEIVER(obj)) throw MakeTypeError(kPropertyDescObject, obj);
-
-  var desc = new PropertyDescriptor();
-
-  if ("enumerable" in obj) {
-    desc.setEnumerable(TO_BOOLEAN(obj.enumerable));
-  }
-
-  if ("configurable" in obj) {
-    desc.setConfigurable(TO_BOOLEAN(obj.configurable));
-  }
-
-  if ("value" in obj) {
-    desc.setValue(obj.value);
-  }
-
-  if ("writable" in obj) {
-    desc.setWritable(TO_BOOLEAN(obj.writable));
-  }
-
-  if ("get" in obj) {
-    var get = obj.get;
-    if (!IS_UNDEFINED(get) && !IS_CALLABLE(get)) {
-      throw MakeTypeError(kObjectGetterCallable, get);
-    }
-    desc.setGet(get);
-  }
-
-  if ("set" in obj) {
-    var set = obj.set;
-    if (!IS_UNDEFINED(set) && !IS_CALLABLE(set)) {
-      throw MakeTypeError(kObjectSetterCallable, set);
-    }
-    desc.setSet(set);
-  }
-
-  if (IsInconsistentDescriptor(desc)) {
-    throw MakeTypeError(kValueAndAccessor, obj);
-  }
-  return desc;
-}
-
-// TODO(cbruni): remove once callers have been removed
-function ToCompletePropertyDescriptor(obj) {
-  var desc = ToPropertyDescriptor(obj);
-  if (IsGenericDescriptor(desc) || IsDataDescriptor(desc)) {
-    if (!desc.hasValue()) desc.setValue(UNDEFINED);
-    if (!desc.hasWritable()) desc.setWritable(false);
-  } else {
-    // Is accessor descriptor.
-    if (!desc.hasGetter()) desc.setGet(UNDEFINED);
-    if (!desc.hasSetter()) desc.setSet(UNDEFINED);
-  }
-  if (!desc.hasEnumerable()) desc.setEnumerable(false);
-  if (!desc.hasConfigurable()) desc.setConfigurable(false);
-  return desc;
-}
-
-
-function PropertyDescriptor() {
-  // Initialize here so they are all in-object and have the same map.
-  // Default values from ES5 8.6.1.
-  this.value_ = UNDEFINED;
-  this.hasValue_ = false;
-  this.writable_ = false;
-  this.hasWritable_ = false;
-  this.enumerable_ = false;
-  this.hasEnumerable_ = false;
-  this.configurable_ = false;
-  this.hasConfigurable_ = false;
-  this.get_ = UNDEFINED;
-  this.hasGetter_ = false;
-  this.set_ = UNDEFINED;
-  this.hasSetter_ = false;
-}
-
-utils.SetUpLockedPrototype(PropertyDescriptor, [
-  "value_",
-  "hasValue_",
-  "writable_",
-  "hasWritable_",
-  "enumerable_",
-  "hasEnumerable_",
-  "configurable_",
-  "hasConfigurable_",
-  "get_",
-  "hasGetter_",
-  "set_",
-  "hasSetter_"
-], [
-  "toString", function PropertyDescriptor_ToString() {
-    return "[object PropertyDescriptor]";
-  },
-  "setValue", function PropertyDescriptor_SetValue(value) {
-    this.value_ = value;
-    this.hasValue_ = true;
-  },
-  "getValue", function PropertyDescriptor_GetValue() {
-    return this.value_;
-  },
-  "hasValue", function PropertyDescriptor_HasValue() {
-    return this.hasValue_;
-  },
-  "setEnumerable", function PropertyDescriptor_SetEnumerable(enumerable) {
-    this.enumerable_ = enumerable;
-      this.hasEnumerable_ = true;
-  },
-  "isEnumerable", function PropertyDescriptor_IsEnumerable() {
-    return this.enumerable_;
-  },
-  "hasEnumerable", function PropertyDescriptor_HasEnumerable() {
-    return this.hasEnumerable_;
-  },
-  "setWritable", function PropertyDescriptor_SetWritable(writable) {
-    this.writable_ = writable;
-    this.hasWritable_ = true;
-  },
-  "isWritable", function PropertyDescriptor_IsWritable() {
-    return this.writable_;
-  },
-  "hasWritable", function PropertyDescriptor_HasWritable() {
-    return this.hasWritable_;
-  },
-  "setConfigurable",
-  function PropertyDescriptor_SetConfigurable(configurable) {
-    this.configurable_ = configurable;
-    this.hasConfigurable_ = true;
-  },
-  "hasConfigurable", function PropertyDescriptor_HasConfigurable() {
-    return this.hasConfigurable_;
-  },
-  "isConfigurable", function PropertyDescriptor_IsConfigurable() {
-    return this.configurable_;
-  },
-  "setGet", function PropertyDescriptor_SetGetter(get) {
-    this.get_ = get;
-    this.hasGetter_ = true;
-  },
-  "getGet", function PropertyDescriptor_GetGetter() {
-    return this.get_;
-  },
-  "hasGetter", function PropertyDescriptor_HasGetter() {
-    return this.hasGetter_;
-  },
-  "setSet", function PropertyDescriptor_SetSetter(set) {
-    this.set_ = set;
-    this.hasSetter_ = true;
-  },
-  "getSet", function PropertyDescriptor_GetSetter() {
-    return this.set_;
-  },
-  "hasSetter", function PropertyDescriptor_HasSetter() {
-    return this.hasSetter_;
-  }
-]);
-
-
-// Converts an array returned from Runtime_GetOwnProperty to an actual
-// property descriptor. For a description of the array layout please
-// see the runtime.cc file.
-function ConvertDescriptorArrayToDescriptor(desc_array) {
-  if (IS_UNDEFINED(desc_array)) {
-    return UNDEFINED;
-  }
-
-  var desc = new PropertyDescriptor();
-  // This is an accessor.
-  if (desc_array[IS_ACCESSOR_INDEX]) {
-    desc.setGet(desc_array[GETTER_INDEX]);
-    desc.setSet(desc_array[SETTER_INDEX]);
-  } else {
-    desc.setValue(desc_array[VALUE_INDEX]);
-    desc.setWritable(desc_array[WRITABLE_INDEX]);
-  }
-  desc.setEnumerable(desc_array[ENUMERABLE_INDEX]);
-  desc.setConfigurable(desc_array[CONFIGURABLE_INDEX]);
-
-  return desc;
-}
-
-
-// For Harmony proxies.
-function GetTrap(handler, name, defaultTrap) {
-  var trap = handler[name];
-  if (IS_UNDEFINED(trap)) {
-    if (IS_UNDEFINED(defaultTrap)) {
-      throw MakeTypeError(kIllegalInvocation);
-    }
-    trap = defaultTrap;
-  } else if (!IS_CALLABLE(trap)) {
-    throw MakeTypeError(kIllegalInvocation);
-  }
-  return trap;
-}
-
-
-function CallTrap1(handler, name, defaultTrap, x) {
-  return %_Call(GetTrap(handler, name, defaultTrap), handler, x);
-}
-
-
-function CallTrap2(handler, name, defaultTrap, x, y) {
-  return %_Call(GetTrap(handler, name, defaultTrap), handler, x, y);
-}
-
-
-// ES5 section 8.12.1.
-// TODO(jkummerow): Deprecated. Migrate all callers to
-// ObjectGetOwnPropertyDescriptor and delete this.
-function GetOwnPropertyJS(obj, v) {
-  var p = TO_NAME(v);
-  if (IS_PROXY(obj)) {
-    // TODO(rossberg): adjust once there is a story for symbols vs proxies.
-    if (IS_SYMBOL(v)) return UNDEFINED;
-
-    var handler = %JSProxyGetHandler(obj);
-    var descriptor = CallTrap1(
-                         handler, "getOwnPropertyDescriptor", UNDEFINED, p);
-    if (IS_UNDEFINED(descriptor)) return descriptor;
-    var desc = ToCompletePropertyDescriptor(descriptor);
-    if (!desc.isConfigurable()) {
-      throw MakeTypeError(kIllegalInvocation);
-    }
-    return desc;
-  }
-
-  // GetOwnProperty returns an array indexed by the constants
-  // defined in macros.py.
-  // If p is not a property on obj undefined is returned.
-  var props = %GetOwnProperty_Legacy(TO_OBJECT(obj), p);
-
-  return ConvertDescriptorArrayToDescriptor(props);
-}
-
-
 // ES6 7.3.9
 function GetMethod(obj, p) {
   var func = obj[p];
@@ -498,252 +149,6 @@
   throw MakeTypeError(kCalledNonCallable, typeof func);
 }
 
-
-// Harmony proxies.
-function DefineProxyProperty(obj, p, attributes, should_throw) {
-  // TODO(rossberg): adjust once there is a story for symbols vs proxies.
-  if (IS_SYMBOL(p)) return false;
-
-  var handler = %JSProxyGetHandler(obj);
-  var result = CallTrap2(handler, "defineProperty", UNDEFINED, p, attributes);
-  if (!result) {
-    if (should_throw) {
-      throw MakeTypeError(kIllegalInvocation);
-    } else {
-      return false;
-    }
-  }
-  return true;
-}
-
-
-// ES6 9.1.6 [[DefineOwnProperty]](P, Desc)
-function DefineObjectProperty(obj, p, desc, should_throw) {
-  var current_array = %GetOwnProperty_Legacy(obj, TO_NAME(p));
-  var current = ConvertDescriptorArrayToDescriptor(current_array);
-  var extensible = %object_is_extensible(obj);
-
-  if (IS_UNDEFINED(current) && !extensible) {
-    if (should_throw) {
-      throw MakeTypeError(kDefineDisallowed, p);
-    } else {
-      return false;
-    }
-  }
-
-  if (!IS_UNDEFINED(current)) {
-    if ((IsGenericDescriptor(desc) ||
-         IsDataDescriptor(desc) == IsDataDescriptor(current)) &&
-        (!desc.hasEnumerable() ||
-         %SameValue(desc.isEnumerable(), current.isEnumerable())) &&
-        (!desc.hasConfigurable() ||
-         %SameValue(desc.isConfigurable(), current.isConfigurable())) &&
-        (!desc.hasWritable() ||
-         %SameValue(desc.isWritable(), current.isWritable())) &&
-        (!desc.hasValue() ||
-         %SameValue(desc.getValue(), current.getValue())) &&
-        (!desc.hasGetter() ||
-         %SameValue(desc.getGet(), current.getGet())) &&
-        (!desc.hasSetter() ||
-         %SameValue(desc.getSet(), current.getSet()))) {
-      return true;
-    }
-    if (!current.isConfigurable()) {
-      // Step 7
-      if (desc.isConfigurable() ||
-          (desc.hasEnumerable() &&
-           desc.isEnumerable() != current.isEnumerable())) {
-        if (should_throw) {
-          throw MakeTypeError(kRedefineDisallowed, p);
-        } else {
-          return false;
-        }
-      }
-      // Step 8
-      if (!IsGenericDescriptor(desc)) {
-        // Step 9a
-        if (IsDataDescriptor(current) != IsDataDescriptor(desc)) {
-          if (should_throw) {
-            throw MakeTypeError(kRedefineDisallowed, p);
-          } else {
-            return false;
-          }
-        }
-        // Step 10a
-        if (IsDataDescriptor(current) && IsDataDescriptor(desc)) {
-          var currentIsWritable = current.isWritable();
-          if (currentIsWritable != desc.isWritable()) {
-            if (!currentIsWritable) {
-              if (should_throw) {
-                throw MakeTypeError(kRedefineDisallowed, p);
-              } else {
-                return false;
-              }
-            }
-          }
-          if (!currentIsWritable && desc.hasValue() &&
-              !%SameValue(desc.getValue(), current.getValue())) {
-            if (should_throw) {
-              throw MakeTypeError(kRedefineDisallowed, p);
-            } else {
-              return false;
-            }
-          }
-        }
-        // Step 11
-        if (IsAccessorDescriptor(desc) && IsAccessorDescriptor(current)) {
-          if (desc.hasSetter() &&
-              !%SameValue(desc.getSet(), current.getSet())) {
-            if (should_throw) {
-              throw MakeTypeError(kRedefineDisallowed, p);
-            } else {
-              return false;
-            }
-          }
-          if (desc.hasGetter() && !%SameValue(desc.getGet(),current.getGet())) {
-            if (should_throw) {
-              throw MakeTypeError(kRedefineDisallowed, p);
-            } else {
-              return false;
-            }
-          }
-        }
-      }
-    }
-  }
-
-  // Send flags - enumerable and configurable are common - writable is
-  // only send to the data descriptor.
-  // Take special care if enumerable and configurable is not defined on
-  // desc (we need to preserve the existing values from current).
-  var flag = NONE;
-  if (desc.hasEnumerable()) {
-    flag |= desc.isEnumerable() ? 0 : DONT_ENUM;
-  } else if (!IS_UNDEFINED(current)) {
-    flag |= current.isEnumerable() ? 0 : DONT_ENUM;
-  } else {
-    flag |= DONT_ENUM;
-  }
-
-  if (desc.hasConfigurable()) {
-    flag |= desc.isConfigurable() ? 0 : DONT_DELETE;
-  } else if (!IS_UNDEFINED(current)) {
-    flag |= current.isConfigurable() ? 0 : DONT_DELETE;
-  } else
-    flag |= DONT_DELETE;
-
-  if (IsDataDescriptor(desc) ||
-      (IsGenericDescriptor(desc) &&
-       (IS_UNDEFINED(current) || IsDataDescriptor(current)))) {
-    // There are 3 cases that lead here:
-    // Step 4a - defining a new data property.
-    // Steps 9b & 12 - replacing an existing accessor property with a data
-    //                 property.
-    // Step 12 - updating an existing data property with a data or generic
-    //           descriptor.
-
-    if (desc.hasWritable()) {
-      flag |= desc.isWritable() ? 0 : READ_ONLY;
-    } else if (!IS_UNDEFINED(current)) {
-      flag |= current.isWritable() ? 0 : READ_ONLY;
-    } else {
-      flag |= READ_ONLY;
-    }
-
-    var value = UNDEFINED;  // Default value is undefined.
-    if (desc.hasValue()) {
-      value = desc.getValue();
-    } else if (!IS_UNDEFINED(current) && IsDataDescriptor(current)) {
-      value = current.getValue();
-    }
-
-    %DefineDataPropertyUnchecked(obj, p, value, flag);
-  } else {
-    // There are 3 cases that lead here:
-    // Step 4b - defining a new accessor property.
-    // Steps 9c & 12 - replacing an existing data property with an accessor
-    //                 property.
-    // Step 12 - updating an existing accessor property with an accessor
-    //           descriptor.
-    var getter = null;
-    if (desc.hasGetter()) {
-      getter = desc.getGet();
-    } else if (IsAccessorDescriptor(current) && current.hasGetter()) {
-      getter = current.getGet();
-    }
-    var setter = null;
-    if (desc.hasSetter()) {
-      setter = desc.getSet();
-    } else if (IsAccessorDescriptor(current) && current.hasSetter()) {
-      setter = current.getSet();
-    }
-    %DefineAccessorPropertyUnchecked(obj, p, getter, setter, flag);
-  }
-  return true;
-}
-
-
-// ES5 section 15.4.5.1.
-function DefineArrayProperty(obj, p, desc, should_throw) {
-  // Step 3 - Special handling for array index.
-  if (!IS_SYMBOL(p)) {
-    var index = TO_UINT32(p);
-    var emit_splice = false;
-    if (TO_STRING(index) == p && index != 4294967295) {
-      var length = obj.length;
-      if (index >= length && %IsObserved(obj)) {
-        emit_splice = true;
-        ObserveBeginPerformSplice(obj);
-      }
-
-      var length_desc = GetOwnPropertyJS(obj, "length");
-      if ((index >= length && !length_desc.isWritable()) ||
-          !DefineObjectProperty(obj, p, desc, true)) {
-        if (emit_splice)
-          ObserveEndPerformSplice(obj);
-        if (should_throw) {
-          throw MakeTypeError(kDefineDisallowed, p);
-        } else {
-          return false;
-        }
-      }
-      if (index >= length) {
-        obj.length = index + 1;
-      }
-      if (emit_splice) {
-        ObserveEndPerformSplice(obj);
-        ObserveEnqueueSpliceRecord(obj, length, [], index + 1 - length);
-      }
-      return true;
-    }
-  }
-
-  // Step 5 - Fallback to default implementation.
-  return DefineObjectProperty(obj, p, desc, should_throw);
-}
-
-
-// ES5 section 8.12.9, ES5 section 15.4.5.1 and Harmony proxies.
-function DefineOwnProperty(obj, p, desc, should_throw) {
-  if (IS_PROXY(obj)) {
-    // TODO(rossberg): adjust once there is a story for symbols vs proxies.
-    if (IS_SYMBOL(p)) return false;
-
-    var attributes = FromGenericPropertyDescriptor(desc);
-    return DefineProxyProperty(obj, p, attributes, should_throw);
-  } else if (IS_ARRAY(obj)) {
-    return DefineArrayProperty(obj, p, desc, should_throw);
-  } else {
-    return DefineObjectProperty(obj, p, desc, should_throw);
-  }
-}
-
-
-// ES6 section 19.1.2.9
-function ObjectGetPrototypeOf(obj) {
-  return %_GetPrototype(TO_OBJECT(obj));
-}
-
 // ES6 section 19.1.2.18.
 function ObjectSetPrototypeOf(obj, proto) {
   CHECK_OBJECT_COERCIBLE(obj, "Object.setPrototypeOf");
@@ -759,50 +164,9 @@
   return obj;
 }
 
-
-// ES5 section 15.2.3.6.
-function ObjectDefineProperty(obj, p, attributes) {
-  // The new pure-C++ implementation doesn't support O.o.
-  // TODO(jkummerow): Implement missing features and remove fallback path.
-  if (%IsObserved(obj)) {
-    if (!IS_RECEIVER(obj)) {
-      throw MakeTypeError(kCalledOnNonObject, "Object.defineProperty");
-    }
-    var name = TO_NAME(p);
-    var desc = ToPropertyDescriptor(attributes);
-    DefineOwnProperty(obj, name, desc, true);
-    return obj;
-  }
-  return %ObjectDefineProperty(obj, p, attributes);
-}
-
-
-// ES5 section 15.2.3.7.
-function ObjectDefineProperties(obj, properties) {
-  // The new pure-C++ implementation doesn't support O.o.
-  // TODO(jkummerow): Implement missing features and remove fallback path.
-  if (%IsObserved(obj)) {
-    if (!IS_RECEIVER(obj)) {
-      throw MakeTypeError(kCalledOnNonObject, "Object.defineProperties");
-    }
-    var props = TO_OBJECT(properties);
-    var names = %GetOwnPropertyKeys(props, PROPERTY_FILTER_ONLY_ENUMERABLE);
-    var descriptors = new InternalArray();
-    for (var i = 0; i < names.length; i++) {
-      descriptors.push(ToPropertyDescriptor(props[names[i]]));
-    }
-    for (var i = 0; i < names.length; i++) {
-      DefineOwnProperty(obj, names[i], descriptors[i], true);
-    }
-    return obj;
-  }
-  return %ObjectDefineProperties(obj, properties);
-}
-
-
 // ES6 B.2.2.1.1
 function ObjectGetProto() {
-  return %_GetPrototype(TO_OBJECT(this));
+  return %object_get_prototype_of(this);
 }
 
 
@@ -842,26 +206,19 @@
   "valueOf", ObjectValueOf,
   "isPrototypeOf", ObjectIsPrototypeOf,
   "propertyIsEnumerable", ObjectPropertyIsEnumerable,
-  "__defineGetter__", ObjectDefineGetter,
-  "__lookupGetter__", ObjectLookupGetter,
-  "__defineSetter__", ObjectDefineSetter,
-  "__lookupSetter__", ObjectLookupSetter
+  // __defineGetter__ is added in bootstrapper.cc.
+  // __lookupGetter__ is added in bootstrapper.cc.
+  // __defineSetter__ is added in bootstrapper.cc.
+  // __lookupSetter__ is added in bootstrapper.cc.
 ]);
-utils.InstallGetterSetter(GlobalObject.prototype, "__proto__", ObjectGetProto,
-                    ObjectSetProto);
+utils.InstallGetterSetter(
+    GlobalObject.prototype, "__proto__", ObjectGetProto, ObjectSetProto);
 
 // Set up non-enumerable functions in the Object object.
 utils.InstallFunctions(GlobalObject, DONT_ENUM, [
-  // assign is added in bootstrapper.cc.
-  // keys is added in bootstrapper.cc.
-  "defineProperty", ObjectDefineProperty,
-  "defineProperties", ObjectDefineProperties,
-  "getPrototypeOf", ObjectGetPrototypeOf,
   "setPrototypeOf", ObjectSetPrototypeOf,
   // getOwnPropertySymbols is added in symbol.js.
-  // is is added in bootstrapper.cc.
-  // deliverChangeRecords, getNotifier, observe and unobserve are added
-  // in object-observe.js.
+  // Others are added in bootstrapper.cc.
 ]);
 
 
@@ -1092,12 +449,9 @@
 utils.Export(function(to) {
   to.GetIterator = GetIterator;
   to.GetMethod = GetMethod;
-  to.IsFinite = GlobalIsFinite;
   to.IsNaN = GlobalIsNaN;
   to.NumberIsNaN = NumberIsNaN;
   to.NumberIsInteger = NumberIsInteger;
-  to.ObjectDefineProperties = ObjectDefineProperties;
-  to.ObjectDefineProperty = ObjectDefineProperty;
   to.ObjectHasOwnProperty = GlobalObject.prototype.hasOwnProperty;
 });
 
diff --git a/src/json-parser.cc b/src/json-parser.cc
new file mode 100644
index 0000000..bf2fd0d
--- /dev/null
+++ b/src/json-parser.cc
@@ -0,0 +1,812 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/json-parser.h"
+
+#include "src/char-predicates-inl.h"
+#include "src/conversions.h"
+#include "src/debug/debug.h"
+#include "src/factory.h"
+#include "src/field-type.h"
+#include "src/messages.h"
+#include "src/objects-inl.h"
+#include "src/parsing/scanner.h"
+#include "src/parsing/token.h"
+#include "src/property-descriptor.h"
+#include "src/transitions.h"
+
+namespace v8 {
+namespace internal {
+
+MaybeHandle<Object> JsonParseInternalizer::Internalize(Isolate* isolate,
+                                                       Handle<Object> object,
+                                                       Handle<Object> reviver) {
+  DCHECK(reviver->IsCallable());
+  JsonParseInternalizer internalizer(isolate,
+                                     Handle<JSReceiver>::cast(reviver));
+  Handle<JSObject> holder =
+      isolate->factory()->NewJSObject(isolate->object_function());
+  Handle<String> name = isolate->factory()->empty_string();
+  JSObject::AddProperty(holder, name, object, NONE);
+  return internalizer.InternalizeJsonProperty(holder, name);
+}
+
+MaybeHandle<Object> JsonParseInternalizer::InternalizeJsonProperty(
+    Handle<JSReceiver> holder, Handle<String> name) {
+  HandleScope outer_scope(isolate_);
+  Handle<Object> value;
+  ASSIGN_RETURN_ON_EXCEPTION(
+      isolate_, value, Object::GetPropertyOrElement(holder, name), Object);
+  if (value->IsJSReceiver()) {
+    Handle<JSReceiver> object = Handle<JSReceiver>::cast(value);
+    Maybe<bool> is_array = Object::IsArray(object);
+    if (is_array.IsNothing()) return MaybeHandle<Object>();
+    if (is_array.FromJust()) {
+      Handle<Object> length_object;
+      ASSIGN_RETURN_ON_EXCEPTION(
+          isolate_, length_object,
+          Object::GetLengthFromArrayLike(isolate_, object), Object);
+      double length = length_object->Number();
+      for (double i = 0; i < length; i++) {
+        HandleScope inner_scope(isolate_);
+        Handle<Object> index = isolate_->factory()->NewNumber(i);
+        Handle<String> name = isolate_->factory()->NumberToString(index);
+        if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
+      }
+    } else {
+      Handle<FixedArray> contents;
+      ASSIGN_RETURN_ON_EXCEPTION(
+          isolate_, contents,
+          KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
+                                  ENUMERABLE_STRINGS,
+                                  GetKeysConversion::kConvertToString),
+          Object);
+      for (int i = 0; i < contents->length(); i++) {
+        HandleScope inner_scope(isolate_);
+        Handle<String> name(String::cast(contents->get(i)), isolate_);
+        if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
+      }
+    }
+  }
+  Handle<Object> argv[] = {name, value};
+  Handle<Object> result;
+  ASSIGN_RETURN_ON_EXCEPTION(
+      isolate_, result, Execution::Call(isolate_, reviver_, holder, 2, argv),
+      Object);
+  return outer_scope.CloseAndEscape(result);
+}
+
+bool JsonParseInternalizer::RecurseAndApply(Handle<JSReceiver> holder,
+                                            Handle<String> name) {
+  Handle<Object> result;
+  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+      isolate_, result, InternalizeJsonProperty(holder, name), false);
+  Maybe<bool> change_result = Nothing<bool>();
+  if (result->IsUndefined(isolate_)) {
+    change_result = JSReceiver::DeletePropertyOrElement(holder, name, SLOPPY);
+  } else {
+    PropertyDescriptor desc;
+    desc.set_value(result);
+    desc.set_configurable(true);
+    desc.set_enumerable(true);
+    desc.set_writable(true);
+    change_result = JSReceiver::DefineOwnProperty(isolate_, holder, name, &desc,
+                                                  Object::DONT_THROW);
+  }
+  MAYBE_RETURN(change_result, false);
+  return true;
+}
+
+template <bool seq_one_byte>
+JsonParser<seq_one_byte>::JsonParser(Isolate* isolate, Handle<String> source)
+    : source_(source),
+      source_length_(source->length()),
+      isolate_(isolate),
+      factory_(isolate_->factory()),
+      zone_(isolate_->allocator()),
+      object_constructor_(isolate_->native_context()->object_function(),
+                          isolate_),
+      position_(-1) {
+  source_ = String::Flatten(source_);
+  pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED;
+
+  // Optimized fast case where we only have Latin1 characters.
+  if (seq_one_byte) {
+    seq_source_ = Handle<SeqOneByteString>::cast(source_);
+  }
+}
+
+template <bool seq_one_byte>
+MaybeHandle<Object> JsonParser<seq_one_byte>::ParseJson() {
+  // Advance to the first character (possibly EOS)
+  AdvanceSkipWhitespace();
+  Handle<Object> result = ParseJsonValue();
+  if (result.is_null() || c0_ != kEndOfString) {
+    // Some exception (for example stack overflow) is already pending.
+    if (isolate_->has_pending_exception()) return Handle<Object>::null();
+
+    // Parse failed. Current character is the unexpected token.
+    Factory* factory = this->factory();
+    MessageTemplate::Template message;
+    Handle<Object> arg1 = Handle<Smi>(Smi::FromInt(position_), isolate());
+    Handle<Object> arg2;
+
+    switch (c0_) {
+      case kEndOfString:
+        message = MessageTemplate::kJsonParseUnexpectedEOS;
+        break;
+      case '-':
+      case '0':
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+        message = MessageTemplate::kJsonParseUnexpectedTokenNumber;
+        break;
+      case '"':
+        message = MessageTemplate::kJsonParseUnexpectedTokenString;
+        break;
+      default:
+        message = MessageTemplate::kJsonParseUnexpectedToken;
+        arg2 = arg1;
+        arg1 = factory->LookupSingleCharacterStringFromCode(c0_);
+        break;
+    }
+
+    Handle<Script> script(factory->NewScript(source_));
+    // We should sent compile error event because we compile JSON object in
+    // separated source file.
+    isolate()->debug()->OnCompileError(script);
+    MessageLocation location(script, position_, position_ + 1);
+    Handle<Object> error = factory->NewSyntaxError(message, arg1, arg2);
+    return isolate()->template Throw<Object>(error, &location);
+  }
+  return result;
+}
+
+MaybeHandle<Object> InternalizeJsonProperty(Handle<JSObject> holder,
+                                            Handle<String> key);
+
+template <bool seq_one_byte>
+void JsonParser<seq_one_byte>::Advance() {
+  position_++;
+  if (position_ >= source_length_) {
+    c0_ = kEndOfString;
+  } else if (seq_one_byte) {
+    c0_ = seq_source_->SeqOneByteStringGet(position_);
+  } else {
+    c0_ = source_->Get(position_);
+  }
+}
+
+template <bool seq_one_byte>
+void JsonParser<seq_one_byte>::AdvanceSkipWhitespace() {
+  do {
+    Advance();
+  } while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r');
+}
+
+template <bool seq_one_byte>
+void JsonParser<seq_one_byte>::SkipWhitespace() {
+  while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r') {
+    Advance();
+  }
+}
+
+template <bool seq_one_byte>
+uc32 JsonParser<seq_one_byte>::AdvanceGetChar() {
+  Advance();
+  return c0_;
+}
+
+template <bool seq_one_byte>
+bool JsonParser<seq_one_byte>::MatchSkipWhiteSpace(uc32 c) {
+  if (c0_ == c) {
+    AdvanceSkipWhitespace();
+    return true;
+  }
+  return false;
+}
+
+template <bool seq_one_byte>
+bool JsonParser<seq_one_byte>::ParseJsonString(Handle<String> expected) {
+  int length = expected->length();
+  if (source_->length() - position_ - 1 > length) {
+    DisallowHeapAllocation no_gc;
+    String::FlatContent content = expected->GetFlatContent();
+    if (content.IsOneByte()) {
+      DCHECK_EQ('"', c0_);
+      const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1;
+      const uint8_t* expected_chars = content.ToOneByteVector().start();
+      for (int i = 0; i < length; i++) {
+        uint8_t c0 = input_chars[i];
+        if (c0 != expected_chars[i] || c0 == '"' || c0 < 0x20 || c0 == '\\') {
+          return false;
+        }
+      }
+      if (input_chars[length] == '"') {
+        position_ = position_ + length + 1;
+        AdvanceSkipWhitespace();
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+// Parse any JSON value.
+template <bool seq_one_byte>
+Handle<Object> JsonParser<seq_one_byte>::ParseJsonValue() {
+  StackLimitCheck stack_check(isolate_);
+  if (stack_check.HasOverflowed()) {
+    isolate_->StackOverflow();
+    return Handle<Object>::null();
+  }
+
+  if (stack_check.InterruptRequested() &&
+      isolate_->stack_guard()->HandleInterrupts()->IsException(isolate_)) {
+    return Handle<Object>::null();
+  }
+
+  if (c0_ == '"') return ParseJsonString();
+  if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber();
+  if (c0_ == '{') return ParseJsonObject();
+  if (c0_ == '[') return ParseJsonArray();
+  if (c0_ == 'f') {
+    if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
+        AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
+      AdvanceSkipWhitespace();
+      return factory()->false_value();
+    }
+    return ReportUnexpectedCharacter();
+  }
+  if (c0_ == 't') {
+    if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
+        AdvanceGetChar() == 'e') {
+      AdvanceSkipWhitespace();
+      return factory()->true_value();
+    }
+    return ReportUnexpectedCharacter();
+  }
+  if (c0_ == 'n') {
+    if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
+        AdvanceGetChar() == 'l') {
+      AdvanceSkipWhitespace();
+      return factory()->null_value();
+    }
+    return ReportUnexpectedCharacter();
+  }
+  return ReportUnexpectedCharacter();
+}
+
+template <bool seq_one_byte>
+ParseElementResult JsonParser<seq_one_byte>::ParseElement(
+    Handle<JSObject> json_object) {
+  uint32_t index = 0;
+  // Maybe an array index, try to parse it.
+  if (c0_ == '0') {
+    // With a leading zero, the string has to be "0" only to be an index.
+    Advance();
+  } else {
+    do {
+      int d = c0_ - '0';
+      if (index > 429496729U - ((d + 3) >> 3)) break;
+      index = (index * 10) + d;
+      Advance();
+    } while (IsDecimalDigit(c0_));
+  }
+
+  if (c0_ == '"') {
+    // Successfully parsed index, parse and store element.
+    AdvanceSkipWhitespace();
+
+    if (c0_ == ':') {
+      AdvanceSkipWhitespace();
+      Handle<Object> value = ParseJsonValue();
+      if (!value.is_null()) {
+        JSObject::SetOwnElementIgnoreAttributes(json_object, index, value, NONE)
+            .Assert();
+        return kElementFound;
+      } else {
+        return kNullHandle;
+      }
+    }
+  }
+  return kElementNotFound;
+}
+
+// Parse a JSON object. Position must be right at '{'.
+template <bool seq_one_byte>
+Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
+  HandleScope scope(isolate());
+  Handle<JSObject> json_object =
+      factory()->NewJSObject(object_constructor(), pretenure_);
+  Handle<Map> map(json_object->map());
+  int descriptor = 0;
+  ZoneList<Handle<Object> > properties(8, zone());
+  DCHECK_EQ(c0_, '{');
+
+  bool transitioning = true;
+
+  AdvanceSkipWhitespace();
+  if (c0_ != '}') {
+    do {
+      if (c0_ != '"') return ReportUnexpectedCharacter();
+
+      int start_position = position_;
+      Advance();
+
+      if (IsDecimalDigit(c0_)) {
+        ParseElementResult element_result = ParseElement(json_object);
+        if (element_result == kNullHandle) return Handle<Object>::null();
+        if (element_result == kElementFound) continue;
+      }
+      // Not an index, fallback to the slow path.
+
+      position_ = start_position;
+#ifdef DEBUG
+      c0_ = '"';
+#endif
+
+      Handle<String> key;
+      Handle<Object> value;
+
+      // Try to follow existing transitions as long as possible. Once we stop
+      // transitioning, no transition can be found anymore.
+      DCHECK(transitioning);
+      // First check whether there is a single expected transition. If so, try
+      // to parse it first.
+      bool follow_expected = false;
+      Handle<Map> target;
+      if (seq_one_byte) {
+        key = TransitionArray::ExpectedTransitionKey(map);
+        follow_expected = !key.is_null() && ParseJsonString(key);
+      }
+      // If the expected transition hits, follow it.
+      if (follow_expected) {
+        target = TransitionArray::ExpectedTransitionTarget(map);
+      } else {
+        // If the expected transition failed, parse an internalized string and
+        // try to find a matching transition.
+        key = ParseJsonInternalizedString();
+        if (key.is_null()) return ReportUnexpectedCharacter();
+
+        target = TransitionArray::FindTransitionToField(map, key);
+        // If a transition was found, follow it and continue.
+        transitioning = !target.is_null();
+      }
+      if (c0_ != ':') return ReportUnexpectedCharacter();
+
+      AdvanceSkipWhitespace();
+      value = ParseJsonValue();
+      if (value.is_null()) return ReportUnexpectedCharacter();
+
+      if (transitioning) {
+        PropertyDetails details =
+            target->instance_descriptors()->GetDetails(descriptor);
+        Representation expected_representation = details.representation();
+
+        if (value->FitsRepresentation(expected_representation)) {
+          if (expected_representation.IsHeapObject() &&
+              !target->instance_descriptors()
+                   ->GetFieldType(descriptor)
+                   ->NowContains(value)) {
+            Handle<FieldType> value_type(
+                value->OptimalType(isolate(), expected_representation));
+            Map::GeneralizeFieldType(target, descriptor,
+                                     expected_representation, value_type);
+          }
+          DCHECK(target->instance_descriptors()
+                     ->GetFieldType(descriptor)
+                     ->NowContains(value));
+          properties.Add(value, zone());
+          map = target;
+          descriptor++;
+          continue;
+        } else {
+          transitioning = false;
+        }
+      }
+
+      DCHECK(!transitioning);
+
+      // Commit the intermediate state to the object and stop transitioning.
+      CommitStateToJsonObject(json_object, map, &properties);
+
+      JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key, value)
+          .Check();
+    } while (transitioning && MatchSkipWhiteSpace(','));
+
+    // If we transitioned until the very end, transition the map now.
+    if (transitioning) {
+      CommitStateToJsonObject(json_object, map, &properties);
+    } else {
+      while (MatchSkipWhiteSpace(',')) {
+        HandleScope local_scope(isolate());
+        if (c0_ != '"') return ReportUnexpectedCharacter();
+
+        int start_position = position_;
+        Advance();
+
+        if (IsDecimalDigit(c0_)) {
+          ParseElementResult element_result = ParseElement(json_object);
+          if (element_result == kNullHandle) return Handle<Object>::null();
+          if (element_result == kElementFound) continue;
+        }
+        // Not an index, fallback to the slow path.
+
+        position_ = start_position;
+#ifdef DEBUG
+        c0_ = '"';
+#endif
+
+        Handle<String> key;
+        Handle<Object> value;
+
+        key = ParseJsonInternalizedString();
+        if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
+
+        AdvanceSkipWhitespace();
+        value = ParseJsonValue();
+        if (value.is_null()) return ReportUnexpectedCharacter();
+
+        JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key,
+                                                          value)
+            .Check();
+      }
+    }
+
+    if (c0_ != '}') {
+      return ReportUnexpectedCharacter();
+    }
+  }
+  AdvanceSkipWhitespace();
+  return scope.CloseAndEscape(json_object);
+}
+
+template <bool seq_one_byte>
+void JsonParser<seq_one_byte>::CommitStateToJsonObject(
+    Handle<JSObject> json_object, Handle<Map> map,
+    ZoneList<Handle<Object> >* properties) {
+  JSObject::AllocateStorageForMap(json_object, map);
+  DCHECK(!json_object->map()->is_dictionary_map());
+
+  DisallowHeapAllocation no_gc;
+
+  int length = properties->length();
+  for (int i = 0; i < length; i++) {
+    Handle<Object> value = (*properties)[i];
+    json_object->WriteToField(i, *value);
+  }
+}
+
+// Parse a JSON array. Position must be right at '['.
+template <bool seq_one_byte>
+Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() {
+  HandleScope scope(isolate());
+  ZoneList<Handle<Object> > elements(4, zone());
+  DCHECK_EQ(c0_, '[');
+
+  AdvanceSkipWhitespace();
+  if (c0_ != ']') {
+    do {
+      Handle<Object> element = ParseJsonValue();
+      if (element.is_null()) return ReportUnexpectedCharacter();
+      elements.Add(element, zone());
+    } while (MatchSkipWhiteSpace(','));
+    if (c0_ != ']') {
+      return ReportUnexpectedCharacter();
+    }
+  }
+  AdvanceSkipWhitespace();
+  // Allocate a fixed array with all the elements.
+  Handle<FixedArray> fast_elements =
+      factory()->NewFixedArray(elements.length(), pretenure_);
+  for (int i = 0, n = elements.length(); i < n; i++) {
+    fast_elements->set(i, *elements[i]);
+  }
+  Handle<Object> json_array = factory()->NewJSArrayWithElements(
+      fast_elements, FAST_ELEMENTS, pretenure_);
+  return scope.CloseAndEscape(json_array);
+}
+
+template <bool seq_one_byte>
+Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() {
+  bool negative = false;
+  int beg_pos = position_;
+  if (c0_ == '-') {
+    Advance();
+    negative = true;
+  }
+  if (c0_ == '0') {
+    Advance();
+    // Prefix zero is only allowed if it's the only digit before
+    // a decimal point or exponent.
+    if (IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
+  } else {
+    int i = 0;
+    int digits = 0;
+    if (c0_ < '1' || c0_ > '9') return ReportUnexpectedCharacter();
+    do {
+      i = i * 10 + c0_ - '0';
+      digits++;
+      Advance();
+    } while (IsDecimalDigit(c0_));
+    if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) {
+      SkipWhitespace();
+      return Handle<Smi>(Smi::FromInt((negative ? -i : i)), isolate());
+    }
+  }
+  if (c0_ == '.') {
+    Advance();
+    if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
+    do {
+      Advance();
+    } while (IsDecimalDigit(c0_));
+  }
+  if (AsciiAlphaToLower(c0_) == 'e') {
+    Advance();
+    if (c0_ == '-' || c0_ == '+') Advance();
+    if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
+    do {
+      Advance();
+    } while (IsDecimalDigit(c0_));
+  }
+  int length = position_ - beg_pos;
+  double number;
+  if (seq_one_byte) {
+    Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length);
+    number = StringToDouble(isolate()->unicode_cache(), chars,
+                            NO_FLAGS,  // Hex, octal or trailing junk.
+                            std::numeric_limits<double>::quiet_NaN());
+  } else {
+    Vector<uint8_t> buffer = Vector<uint8_t>::New(length);
+    String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
+    Vector<const uint8_t> result =
+        Vector<const uint8_t>(buffer.start(), length);
+    number = StringToDouble(isolate()->unicode_cache(), result,
+                            NO_FLAGS,  // Hex, octal or trailing junk.
+                            0.0);
+    buffer.Dispose();
+  }
+  SkipWhitespace();
+  return factory()->NewNumber(number, pretenure_);
+}
+
+template <typename StringType>
+inline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c);
+
+template <>
+inline void SeqStringSet(Handle<SeqTwoByteString> seq_str, int i, uc32 c) {
+  seq_str->SeqTwoByteStringSet(i, c);
+}
+
+template <>
+inline void SeqStringSet(Handle<SeqOneByteString> seq_str, int i, uc32 c) {
+  seq_str->SeqOneByteStringSet(i, c);
+}
+
+template <typename StringType>
+inline Handle<StringType> NewRawString(Factory* factory, int length,
+                                       PretenureFlag pretenure);
+
+template <>
+inline Handle<SeqTwoByteString> NewRawString(Factory* factory, int length,
+                                             PretenureFlag pretenure) {
+  return factory->NewRawTwoByteString(length, pretenure).ToHandleChecked();
+}
+
+template <>
+inline Handle<SeqOneByteString> NewRawString(Factory* factory, int length,
+                                             PretenureFlag pretenure) {
+  return factory->NewRawOneByteString(length, pretenure).ToHandleChecked();
+}
+
+// Scans the rest of a JSON string starting from position_ and writes
+// prefix[start..end] along with the scanned characters into a
+// sequential string of type StringType.
+template <bool seq_one_byte>
+template <typename StringType, typename SinkChar>
+Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString(
+    Handle<String> prefix, int start, int end) {
+  int count = end - start;
+  int max_length = count + source_length_ - position_;
+  int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
+  Handle<StringType> seq_string =
+      NewRawString<StringType>(factory(), length, pretenure_);
+  // Copy prefix into seq_str.
+  SinkChar* dest = seq_string->GetChars();
+  String::WriteToFlat(*prefix, dest, start, end);
+
+  while (c0_ != '"') {
+    // Check for control character (0x00-0x1f) or unterminated string (<0).
+    if (c0_ < 0x20) return Handle<String>::null();
+    if (count >= length) {
+      // We need to create a longer sequential string for the result.
+      return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
+    }
+    if (c0_ != '\\') {
+      // If the sink can contain UC16 characters, or source_ contains only
+      // Latin1 characters, there's no need to test whether we can store the
+      // character. Otherwise check whether the UC16 source character can fit
+      // in the Latin1 sink.
+      if (sizeof(SinkChar) == kUC16Size || seq_one_byte ||
+          c0_ <= String::kMaxOneByteCharCode) {
+        SeqStringSet(seq_string, count++, c0_);
+        Advance();
+      } else {
+        // StringType is SeqOneByteString and we just read a non-Latin1 char.
+        return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
+      }
+    } else {
+      Advance();  // Advance past the \.
+      switch (c0_) {
+        case '"':
+        case '\\':
+        case '/':
+          SeqStringSet(seq_string, count++, c0_);
+          break;
+        case 'b':
+          SeqStringSet(seq_string, count++, '\x08');
+          break;
+        case 'f':
+          SeqStringSet(seq_string, count++, '\x0c');
+          break;
+        case 'n':
+          SeqStringSet(seq_string, count++, '\x0a');
+          break;
+        case 'r':
+          SeqStringSet(seq_string, count++, '\x0d');
+          break;
+        case 't':
+          SeqStringSet(seq_string, count++, '\x09');
+          break;
+        case 'u': {
+          uc32 value = 0;
+          for (int i = 0; i < 4; i++) {
+            Advance();
+            int digit = HexValue(c0_);
+            if (digit < 0) {
+              return Handle<String>::null();
+            }
+            value = value * 16 + digit;
+          }
+          if (sizeof(SinkChar) == kUC16Size ||
+              value <= String::kMaxOneByteCharCode) {
+            SeqStringSet(seq_string, count++, value);
+            break;
+          } else {
+            // StringType is SeqOneByteString and we just read a non-Latin1
+            // char.
+            position_ -= 6;  // Rewind position_ to \ in \uxxxx.
+            Advance();
+            return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0,
+                                                              count);
+          }
+        }
+        default:
+          return Handle<String>::null();
+      }
+      Advance();
+    }
+  }
+
+  DCHECK_EQ('"', c0_);
+  // Advance past the last '"'.
+  AdvanceSkipWhitespace();
+
+  // Shrink seq_string length to count and return.
+  return SeqString::Truncate(seq_string, count);
+}
+
+template <bool seq_one_byte>
+template <bool is_internalized>
+Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
+  DCHECK_EQ('"', c0_);
+  Advance();
+  if (c0_ == '"') {
+    AdvanceSkipWhitespace();
+    return factory()->empty_string();
+  }
+
+  if (seq_one_byte && is_internalized) {
+    // Fast path for existing internalized strings.  If the the string being
+    // parsed is not a known internalized string, contains backslashes or
+    // unexpectedly reaches the end of string, return with an empty handle.
+    uint32_t running_hash = isolate()->heap()->HashSeed();
+    int position = position_;
+    uc32 c0 = c0_;
+    do {
+      if (c0 == '\\') {
+        c0_ = c0;
+        int beg_pos = position_;
+        position_ = position;
+        return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos,
+                                                             position_);
+      }
+      if (c0 < 0x20) return Handle<String>::null();
+      running_hash = StringHasher::AddCharacterCore(running_hash,
+                                                    static_cast<uint16_t>(c0));
+      position++;
+      if (position >= source_length_) return Handle<String>::null();
+      c0 = seq_source_->SeqOneByteStringGet(position);
+    } while (c0 != '"');
+    int length = position - position_;
+    uint32_t hash = (length <= String::kMaxHashCalcLength)
+                        ? StringHasher::GetHashCore(running_hash)
+                        : static_cast<uint32_t>(length);
+    Vector<const uint8_t> string_vector(seq_source_->GetChars() + position_,
+                                        length);
+    StringTable* string_table = isolate()->heap()->string_table();
+    uint32_t capacity = string_table->Capacity();
+    uint32_t entry = StringTable::FirstProbe(hash, capacity);
+    uint32_t count = 1;
+    Handle<String> result;
+    while (true) {
+      Object* element = string_table->KeyAt(entry);
+      if (element->IsUndefined(isolate())) {
+        // Lookup failure.
+        result =
+            factory()->InternalizeOneByteString(seq_source_, position_, length);
+        break;
+      }
+      if (!element->IsTheHole(isolate()) &&
+          String::cast(element)->IsOneByteEqualTo(string_vector)) {
+        result = Handle<String>(String::cast(element), isolate());
+#ifdef DEBUG
+        uint32_t hash_field =
+            (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
+        DCHECK_EQ(static_cast<int>(result->Hash()),
+                  static_cast<int>(hash_field >> String::kHashShift));
+#endif
+        break;
+      }
+      entry = StringTable::NextProbe(entry, count++, capacity);
+    }
+    position_ = position;
+    // Advance past the last '"'.
+    AdvanceSkipWhitespace();
+    return result;
+  }
+
+  int beg_pos = position_;
+  // Fast case for Latin1 only without escape characters.
+  do {
+    // Check for control character (0x00-0x1f) or unterminated string (<0).
+    if (c0_ < 0x20) return Handle<String>::null();
+    if (c0_ != '\\') {
+      if (seq_one_byte || c0_ <= String::kMaxOneByteCharCode) {
+        Advance();
+      } else {
+        return SlowScanJsonString<SeqTwoByteString, uc16>(source_, beg_pos,
+                                                          position_);
+      }
+    } else {
+      return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos,
+                                                           position_);
+    }
+  } while (c0_ != '"');
+  int length = position_ - beg_pos;
+  Handle<String> result =
+      factory()->NewRawOneByteString(length, pretenure_).ToHandleChecked();
+  uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
+  String::WriteToFlat(*source_, dest, beg_pos, position_);
+
+  DCHECK_EQ('"', c0_);
+  // Advance past the last '"'.
+  AdvanceSkipWhitespace();
+  return result;
+}
+
+// Explicit instantiation.
+template class JsonParser<true>;
+template class JsonParser<false>;
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/json-parser.h b/src/json-parser.h
index 1b9829f..2d08fef 100644
--- a/src/json-parser.h
+++ b/src/json-parser.h
@@ -5,95 +5,70 @@
 #ifndef V8_JSON_PARSER_H_
 #define V8_JSON_PARSER_H_
 
-#include "src/char-predicates.h"
-#include "src/conversions.h"
-#include "src/debug/debug.h"
 #include "src/factory.h"
-#include "src/field-type.h"
-#include "src/messages.h"
-#include "src/parsing/scanner.h"
-#include "src/parsing/token.h"
-#include "src/transitions.h"
+#include "src/objects.h"
 
 namespace v8 {
 namespace internal {
 
 enum ParseElementResult { kElementFound, kElementNotFound, kNullHandle };
 
+class JsonParseInternalizer BASE_EMBEDDED {
+ public:
+  static MaybeHandle<Object> Internalize(Isolate* isolate,
+                                         Handle<Object> object,
+                                         Handle<Object> reviver);
+
+ private:
+  JsonParseInternalizer(Isolate* isolate, Handle<JSReceiver> reviver)
+      : isolate_(isolate), reviver_(reviver) {}
+
+  MaybeHandle<Object> InternalizeJsonProperty(Handle<JSReceiver> holder,
+                                              Handle<String> key);
+
+  bool RecurseAndApply(Handle<JSReceiver> holder, Handle<String> name);
+
+  Isolate* isolate_;
+  Handle<JSReceiver> reviver_;
+};
 
 // A simple json parser.
 template <bool seq_one_byte>
 class JsonParser BASE_EMBEDDED {
  public:
-  MUST_USE_RESULT static MaybeHandle<Object> Parse(Handle<String> source) {
-    return JsonParser(source).ParseJson();
+  MUST_USE_RESULT static MaybeHandle<Object> Parse(Isolate* isolate,
+                                                   Handle<String> source,
+                                                   Handle<Object> reviver) {
+    Handle<Object> result;
+    ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
+                               JsonParser(isolate, source).ParseJson(), Object);
+    if (reviver->IsCallable()) {
+      return JsonParseInternalizer::Internalize(isolate, result, reviver);
+    }
+    return result;
   }
 
   static const int kEndOfString = -1;
 
  private:
-  explicit JsonParser(Handle<String> source)
-      : source_(source),
-        source_length_(source->length()),
-        isolate_(source->map()->GetHeap()->isolate()),
-        factory_(isolate_->factory()),
-        zone_(isolate_->allocator()),
-        object_constructor_(isolate_->native_context()->object_function(),
-                            isolate_),
-        position_(-1) {
-    source_ = String::Flatten(source_);
-    pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED;
-
-    // Optimized fast case where we only have Latin1 characters.
-    if (seq_one_byte) {
-      seq_source_ = Handle<SeqOneByteString>::cast(source_);
-    }
-  }
+  JsonParser(Isolate* isolate, Handle<String> source);
 
   // Parse a string containing a single JSON value.
   MaybeHandle<Object> ParseJson();
 
-  inline void Advance() {
-    position_++;
-    if (position_ >= source_length_) {
-      c0_ = kEndOfString;
-    } else if (seq_one_byte) {
-      c0_ = seq_source_->SeqOneByteStringGet(position_);
-    } else {
-      c0_ = source_->Get(position_);
-    }
-  }
+  INLINE(void Advance());
 
   // The JSON lexical grammar is specified in the ECMAScript 5 standard,
   // section 15.12.1.1. The only allowed whitespace characters between tokens
   // are tab, carriage-return, newline and space.
 
-  inline void AdvanceSkipWhitespace() {
-    do {
-      Advance();
-    } while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r');
-  }
-
-  inline void SkipWhitespace() {
-    while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r') {
-      Advance();
-    }
-  }
-
-  inline uc32 AdvanceGetChar() {
-    Advance();
-    return c0_;
-  }
+  INLINE(void AdvanceSkipWhitespace());
+  INLINE(void SkipWhitespace());
+  INLINE(uc32 AdvanceGetChar());
 
   // Checks that current charater is c.
   // If so, then consume c and skip whitespace.
-  inline bool MatchSkipWhiteSpace(uc32 c) {
-    if (c0_ == c) {
-      AdvanceSkipWhitespace();
-      return true;
-    }
-    return false;
-  }
+  INLINE(bool MatchSkipWhiteSpace(uc32 c));
 
   // A JSON string (production JSONString) is subset of valid JavaScript string
   // literals. The string must only be double-quoted (not single-quoted), and
@@ -103,30 +78,7 @@
     return ScanJsonString<false>();
   }
 
-  bool ParseJsonString(Handle<String> expected) {
-    int length = expected->length();
-    if (source_->length() - position_ - 1 > length) {
-      DisallowHeapAllocation no_gc;
-      String::FlatContent content = expected->GetFlatContent();
-      if (content.IsOneByte()) {
-        DCHECK_EQ('"', c0_);
-        const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1;
-        const uint8_t* expected_chars = content.ToOneByteVector().start();
-        for (int i = 0; i < length; i++) {
-          uint8_t c0 = input_chars[i];
-          if (c0 != expected_chars[i] || c0 == '"' || c0 < 0x20 || c0 == '\\') {
-            return false;
-          }
-        }
-        if (input_chars[length] == '"') {
-          position_ = position_ + length + 1;
-          AdvanceSkipWhitespace();
-          return true;
-        }
-      }
-    }
-    return false;
-  }
+  bool ParseJsonString(Handle<String> expected);
 
   Handle<String> ParseJsonInternalizedString() {
     Handle<String> result = ScanJsonString<true>();
@@ -188,7 +140,6 @@
   static const int kInitialSpecialStringLength = 32;
   static const int kPretenureTreshold = 100 * 1024;
 
-
  private:
   Zone* zone() { return &zone_; }
 
@@ -208,639 +159,6 @@
   int position_;
 };
 
-template <bool seq_one_byte>
-MaybeHandle<Object> JsonParser<seq_one_byte>::ParseJson() {
-  // Advance to the first character (possibly EOS)
-  AdvanceSkipWhitespace();
-  Handle<Object> result = ParseJsonValue();
-  if (result.is_null() || c0_ != kEndOfString) {
-    // Some exception (for example stack overflow) is already pending.
-    if (isolate_->has_pending_exception()) return Handle<Object>::null();
-
-    // Parse failed. Current character is the unexpected token.
-    Factory* factory = this->factory();
-    MessageTemplate::Template message;
-    Handle<Object> arg1 = Handle<Smi>(Smi::FromInt(position_), isolate());
-    Handle<Object> arg2;
-
-    switch (c0_) {
-      case kEndOfString:
-        message = MessageTemplate::kJsonParseUnexpectedEOS;
-        break;
-      case '-':
-      case '0':
-      case '1':
-      case '2':
-      case '3':
-      case '4':
-      case '5':
-      case '6':
-      case '7':
-      case '8':
-      case '9':
-        message = MessageTemplate::kJsonParseUnexpectedTokenNumber;
-        break;
-      case '"':
-        message = MessageTemplate::kJsonParseUnexpectedTokenString;
-        break;
-      default:
-        message = MessageTemplate::kJsonParseUnexpectedToken;
-        arg2 = arg1;
-        arg1 = factory->LookupSingleCharacterStringFromCode(c0_);
-        break;
-    }
-
-    Handle<Script> script(factory->NewScript(source_));
-    // We should sent compile error event because we compile JSON object in
-    // separated source file.
-    isolate()->debug()->OnCompileError(script);
-    MessageLocation location(script, position_, position_ + 1);
-    Handle<Object> error = factory->NewSyntaxError(message, arg1, arg2);
-    return isolate()->template Throw<Object>(error, &location);
-  }
-  return result;
-}
-
-
-// Parse any JSON value.
-template <bool seq_one_byte>
-Handle<Object> JsonParser<seq_one_byte>::ParseJsonValue() {
-  StackLimitCheck stack_check(isolate_);
-  if (stack_check.HasOverflowed()) {
-    isolate_->StackOverflow();
-    return Handle<Object>::null();
-  }
-
-  if (stack_check.InterruptRequested()) {
-    ExecutionAccess access(isolate_);
-    // Avoid blocking GC in long running parser (v8:3974).
-    isolate_->stack_guard()->HandleGCInterrupt();
-  }
-
-  if (c0_ == '"') return ParseJsonString();
-  if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber();
-  if (c0_ == '{') return ParseJsonObject();
-  if (c0_ == '[') return ParseJsonArray();
-  if (c0_ == 'f') {
-    if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
-        AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
-      AdvanceSkipWhitespace();
-      return factory()->false_value();
-    }
-    return ReportUnexpectedCharacter();
-  }
-  if (c0_ == 't') {
-    if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
-        AdvanceGetChar() == 'e') {
-      AdvanceSkipWhitespace();
-      return factory()->true_value();
-    }
-    return ReportUnexpectedCharacter();
-  }
-  if (c0_ == 'n') {
-    if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
-        AdvanceGetChar() == 'l') {
-      AdvanceSkipWhitespace();
-      return factory()->null_value();
-    }
-    return ReportUnexpectedCharacter();
-  }
-  return ReportUnexpectedCharacter();
-}
-
-
-template <bool seq_one_byte>
-ParseElementResult JsonParser<seq_one_byte>::ParseElement(
-    Handle<JSObject> json_object) {
-  uint32_t index = 0;
-  // Maybe an array index, try to parse it.
-  if (c0_ == '0') {
-    // With a leading zero, the string has to be "0" only to be an index.
-    Advance();
-  } else {
-    do {
-      int d = c0_ - '0';
-      if (index > 429496729U - ((d + 3) >> 3)) break;
-      index = (index * 10) + d;
-      Advance();
-    } while (IsDecimalDigit(c0_));
-  }
-
-  if (c0_ == '"') {
-    // Successfully parsed index, parse and store element.
-    AdvanceSkipWhitespace();
-
-    if (c0_ == ':') {
-      AdvanceSkipWhitespace();
-      Handle<Object> value = ParseJsonValue();
-      if (!value.is_null()) {
-        JSObject::SetOwnElementIgnoreAttributes(json_object, index, value, NONE)
-            .Assert();
-        return kElementFound;
-      } else {
-        return kNullHandle;
-      }
-    }
-  }
-  return kElementNotFound;
-}
-
-// Parse a JSON object. Position must be right at '{'.
-template <bool seq_one_byte>
-Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
-  HandleScope scope(isolate());
-  Handle<JSObject> json_object =
-      factory()->NewJSObject(object_constructor(), pretenure_);
-  Handle<Map> map(json_object->map());
-  int descriptor = 0;
-  ZoneList<Handle<Object> > properties(8, zone());
-  DCHECK_EQ(c0_, '{');
-
-  bool transitioning = true;
-
-  AdvanceSkipWhitespace();
-  if (c0_ != '}') {
-    do {
-      if (c0_ != '"') return ReportUnexpectedCharacter();
-
-      int start_position = position_;
-      Advance();
-
-      if (IsDecimalDigit(c0_)) {
-        ParseElementResult element_result = ParseElement(json_object);
-        if (element_result == kNullHandle) return Handle<Object>::null();
-        if (element_result == kElementFound) continue;
-      }
-      // Not an index, fallback to the slow path.
-
-      position_ = start_position;
-#ifdef DEBUG
-      c0_ = '"';
-#endif
-
-      Handle<String> key;
-      Handle<Object> value;
-
-      // Try to follow existing transitions as long as possible. Once we stop
-      // transitioning, no transition can be found anymore.
-      DCHECK(transitioning);
-      // First check whether there is a single expected transition. If so, try
-      // to parse it first.
-      bool follow_expected = false;
-      Handle<Map> target;
-      if (seq_one_byte) {
-        key = TransitionArray::ExpectedTransitionKey(map);
-        follow_expected = !key.is_null() && ParseJsonString(key);
-      }
-      // If the expected transition hits, follow it.
-      if (follow_expected) {
-        target = TransitionArray::ExpectedTransitionTarget(map);
-      } else {
-        // If the expected transition failed, parse an internalized string and
-        // try to find a matching transition.
-        key = ParseJsonInternalizedString();
-        if (key.is_null()) return ReportUnexpectedCharacter();
-
-        target = TransitionArray::FindTransitionToField(map, key);
-        // If a transition was found, follow it and continue.
-        transitioning = !target.is_null();
-      }
-      if (c0_ != ':') return ReportUnexpectedCharacter();
-
-      AdvanceSkipWhitespace();
-      value = ParseJsonValue();
-      if (value.is_null()) return ReportUnexpectedCharacter();
-
-      if (transitioning) {
-        PropertyDetails details =
-            target->instance_descriptors()->GetDetails(descriptor);
-        Representation expected_representation = details.representation();
-
-        if (value->FitsRepresentation(expected_representation)) {
-          if (expected_representation.IsHeapObject() &&
-              !target->instance_descriptors()
-                   ->GetFieldType(descriptor)
-                   ->NowContains(value)) {
-            Handle<FieldType> value_type(
-                value->OptimalType(isolate(), expected_representation));
-            Map::GeneralizeFieldType(target, descriptor,
-                                     expected_representation, value_type);
-          }
-          DCHECK(target->instance_descriptors()
-                     ->GetFieldType(descriptor)
-                     ->NowContains(value));
-          properties.Add(value, zone());
-          map = target;
-          descriptor++;
-          continue;
-        } else {
-          transitioning = false;
-        }
-      }
-
-      DCHECK(!transitioning);
-
-      // Commit the intermediate state to the object and stop transitioning.
-      CommitStateToJsonObject(json_object, map, &properties);
-
-      JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key, value)
-          .Check();
-    } while (transitioning && MatchSkipWhiteSpace(','));
-
-    // If we transitioned until the very end, transition the map now.
-    if (transitioning) {
-      CommitStateToJsonObject(json_object, map, &properties);
-    } else {
-      while (MatchSkipWhiteSpace(',')) {
-        HandleScope local_scope(isolate());
-        if (c0_ != '"') return ReportUnexpectedCharacter();
-
-        int start_position = position_;
-        Advance();
-
-        if (IsDecimalDigit(c0_)) {
-          ParseElementResult element_result = ParseElement(json_object);
-          if (element_result == kNullHandle) return Handle<Object>::null();
-          if (element_result == kElementFound) continue;
-        }
-        // Not an index, fallback to the slow path.
-
-        position_ = start_position;
-#ifdef DEBUG
-        c0_ = '"';
-#endif
-
-        Handle<String> key;
-        Handle<Object> value;
-
-        key = ParseJsonInternalizedString();
-        if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
-
-        AdvanceSkipWhitespace();
-        value = ParseJsonValue();
-        if (value.is_null()) return ReportUnexpectedCharacter();
-
-        JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key,
-                                                          value).Check();
-      }
-    }
-
-    if (c0_ != '}') {
-      return ReportUnexpectedCharacter();
-    }
-  }
-  AdvanceSkipWhitespace();
-  return scope.CloseAndEscape(json_object);
-}
-
-
-template <bool seq_one_byte>
-void JsonParser<seq_one_byte>::CommitStateToJsonObject(
-    Handle<JSObject> json_object, Handle<Map> map,
-    ZoneList<Handle<Object> >* properties) {
-  JSObject::AllocateStorageForMap(json_object, map);
-  DCHECK(!json_object->map()->is_dictionary_map());
-
-  DisallowHeapAllocation no_gc;
-
-  int length = properties->length();
-  for (int i = 0; i < length; i++) {
-    Handle<Object> value = (*properties)[i];
-    json_object->WriteToField(i, *value);
-  }
-}
-
-
-// Parse a JSON array. Position must be right at '['.
-template <bool seq_one_byte>
-Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() {
-  HandleScope scope(isolate());
-  ZoneList<Handle<Object> > elements(4, zone());
-  DCHECK_EQ(c0_, '[');
-
-  AdvanceSkipWhitespace();
-  if (c0_ != ']') {
-    do {
-      Handle<Object> element = ParseJsonValue();
-      if (element.is_null()) return ReportUnexpectedCharacter();
-      elements.Add(element, zone());
-    } while (MatchSkipWhiteSpace(','));
-    if (c0_ != ']') {
-      return ReportUnexpectedCharacter();
-    }
-  }
-  AdvanceSkipWhitespace();
-  // Allocate a fixed array with all the elements.
-  Handle<FixedArray> fast_elements =
-      factory()->NewFixedArray(elements.length(), pretenure_);
-  for (int i = 0, n = elements.length(); i < n; i++) {
-    fast_elements->set(i, *elements[i]);
-  }
-  Handle<Object> json_array = factory()->NewJSArrayWithElements(
-      fast_elements, FAST_ELEMENTS, pretenure_);
-  return scope.CloseAndEscape(json_array);
-}
-
-
-template <bool seq_one_byte>
-Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() {
-  bool negative = false;
-  int beg_pos = position_;
-  if (c0_ == '-') {
-    Advance();
-    negative = true;
-  }
-  if (c0_ == '0') {
-    Advance();
-    // Prefix zero is only allowed if it's the only digit before
-    // a decimal point or exponent.
-    if (IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
-  } else {
-    int i = 0;
-    int digits = 0;
-    if (c0_ < '1' || c0_ > '9') return ReportUnexpectedCharacter();
-    do {
-      i = i * 10 + c0_ - '0';
-      digits++;
-      Advance();
-    } while (IsDecimalDigit(c0_));
-    if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) {
-      SkipWhitespace();
-      return Handle<Smi>(Smi::FromInt((negative ? -i : i)), isolate());
-    }
-  }
-  if (c0_ == '.') {
-    Advance();
-    if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
-    do {
-      Advance();
-    } while (IsDecimalDigit(c0_));
-  }
-  if (AsciiAlphaToLower(c0_) == 'e') {
-    Advance();
-    if (c0_ == '-' || c0_ == '+') Advance();
-    if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
-    do {
-      Advance();
-    } while (IsDecimalDigit(c0_));
-  }
-  int length = position_ - beg_pos;
-  double number;
-  if (seq_one_byte) {
-    Vector<const uint8_t> chars(seq_source_->GetChars() +  beg_pos, length);
-    number = StringToDouble(isolate()->unicode_cache(), chars,
-                            NO_FLAGS,  // Hex, octal or trailing junk.
-                            std::numeric_limits<double>::quiet_NaN());
-  } else {
-    Vector<uint8_t> buffer = Vector<uint8_t>::New(length);
-    String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
-    Vector<const uint8_t> result =
-        Vector<const uint8_t>(buffer.start(), length);
-    number = StringToDouble(isolate()->unicode_cache(),
-                            result,
-                            NO_FLAGS,  // Hex, octal or trailing junk.
-                            0.0);
-    buffer.Dispose();
-  }
-  SkipWhitespace();
-  return factory()->NewNumber(number, pretenure_);
-}
-
-
-template <typename StringType>
-inline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c);
-
-template <>
-inline void SeqStringSet(Handle<SeqTwoByteString> seq_str, int i, uc32 c) {
-  seq_str->SeqTwoByteStringSet(i, c);
-}
-
-template <>
-inline void SeqStringSet(Handle<SeqOneByteString> seq_str, int i, uc32 c) {
-  seq_str->SeqOneByteStringSet(i, c);
-}
-
-template <typename StringType>
-inline Handle<StringType> NewRawString(Factory* factory,
-                                       int length,
-                                       PretenureFlag pretenure);
-
-template <>
-inline Handle<SeqTwoByteString> NewRawString(Factory* factory,
-                                             int length,
-                                             PretenureFlag pretenure) {
-  return factory->NewRawTwoByteString(length, pretenure).ToHandleChecked();
-}
-
-template <>
-inline Handle<SeqOneByteString> NewRawString(Factory* factory,
-                                           int length,
-                                           PretenureFlag pretenure) {
-  return factory->NewRawOneByteString(length, pretenure).ToHandleChecked();
-}
-
-
-// Scans the rest of a JSON string starting from position_ and writes
-// prefix[start..end] along with the scanned characters into a
-// sequential string of type StringType.
-template <bool seq_one_byte>
-template <typename StringType, typename SinkChar>
-Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString(
-    Handle<String> prefix, int start, int end) {
-  int count = end - start;
-  int max_length = count + source_length_ - position_;
-  int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
-  Handle<StringType> seq_string =
-      NewRawString<StringType>(factory(), length, pretenure_);
-  // Copy prefix into seq_str.
-  SinkChar* dest = seq_string->GetChars();
-  String::WriteToFlat(*prefix, dest, start, end);
-
-  while (c0_ != '"') {
-    // Check for control character (0x00-0x1f) or unterminated string (<0).
-    if (c0_ < 0x20) return Handle<String>::null();
-    if (count >= length) {
-      // We need to create a longer sequential string for the result.
-      return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
-    }
-    if (c0_ != '\\') {
-      // If the sink can contain UC16 characters, or source_ contains only
-      // Latin1 characters, there's no need to test whether we can store the
-      // character. Otherwise check whether the UC16 source character can fit
-      // in the Latin1 sink.
-      if (sizeof(SinkChar) == kUC16Size || seq_one_byte ||
-          c0_ <= String::kMaxOneByteCharCode) {
-        SeqStringSet(seq_string, count++, c0_);
-        Advance();
-      } else {
-        // StringType is SeqOneByteString and we just read a non-Latin1 char.
-        return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
-      }
-    } else {
-      Advance();  // Advance past the \.
-      switch (c0_) {
-        case '"':
-        case '\\':
-        case '/':
-          SeqStringSet(seq_string, count++, c0_);
-          break;
-        case 'b':
-          SeqStringSet(seq_string, count++, '\x08');
-          break;
-        case 'f':
-          SeqStringSet(seq_string, count++, '\x0c');
-          break;
-        case 'n':
-          SeqStringSet(seq_string, count++, '\x0a');
-          break;
-        case 'r':
-          SeqStringSet(seq_string, count++, '\x0d');
-          break;
-        case 't':
-          SeqStringSet(seq_string, count++, '\x09');
-          break;
-        case 'u': {
-          uc32 value = 0;
-          for (int i = 0; i < 4; i++) {
-            Advance();
-            int digit = HexValue(c0_);
-            if (digit < 0) {
-              return Handle<String>::null();
-            }
-            value = value * 16 + digit;
-          }
-          if (sizeof(SinkChar) == kUC16Size ||
-              value <= String::kMaxOneByteCharCode) {
-            SeqStringSet(seq_string, count++, value);
-            break;
-          } else {
-            // StringType is SeqOneByteString and we just read a non-Latin1
-            // char.
-            position_ -= 6;  // Rewind position_ to \ in \uxxxx.
-            Advance();
-            return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string,
-                                                              0,
-                                                              count);
-          }
-        }
-        default:
-          return Handle<String>::null();
-      }
-      Advance();
-    }
-  }
-
-  DCHECK_EQ('"', c0_);
-  // Advance past the last '"'.
-  AdvanceSkipWhitespace();
-
-  // Shrink seq_string length to count and return.
-  return SeqString::Truncate(seq_string, count);
-}
-
-
-template <bool seq_one_byte>
-template <bool is_internalized>
-Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
-  DCHECK_EQ('"', c0_);
-  Advance();
-  if (c0_ == '"') {
-    AdvanceSkipWhitespace();
-    return factory()->empty_string();
-  }
-
-  if (seq_one_byte && is_internalized) {
-    // Fast path for existing internalized strings.  If the the string being
-    // parsed is not a known internalized string, contains backslashes or
-    // unexpectedly reaches the end of string, return with an empty handle.
-    uint32_t running_hash = isolate()->heap()->HashSeed();
-    int position = position_;
-    uc32 c0 = c0_;
-    do {
-      if (c0 == '\\') {
-        c0_ = c0;
-        int beg_pos = position_;
-        position_ = position;
-        return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
-                                                             beg_pos,
-                                                             position_);
-      }
-      if (c0 < 0x20) return Handle<String>::null();
-      running_hash = StringHasher::AddCharacterCore(running_hash,
-                                                    static_cast<uint16_t>(c0));
-      position++;
-      if (position >= source_length_) return Handle<String>::null();
-      c0 = seq_source_->SeqOneByteStringGet(position);
-    } while (c0 != '"');
-    int length = position - position_;
-    uint32_t hash = (length <= String::kMaxHashCalcLength)
-                        ? StringHasher::GetHashCore(running_hash)
-                        : static_cast<uint32_t>(length);
-    Vector<const uint8_t> string_vector(
-        seq_source_->GetChars() + position_, length);
-    StringTable* string_table = isolate()->heap()->string_table();
-    uint32_t capacity = string_table->Capacity();
-    uint32_t entry = StringTable::FirstProbe(hash, capacity);
-    uint32_t count = 1;
-    Handle<String> result;
-    while (true) {
-      Object* element = string_table->KeyAt(entry);
-      if (element == isolate()->heap()->undefined_value()) {
-        // Lookup failure.
-        result = factory()->InternalizeOneByteString(
-            seq_source_, position_, length);
-        break;
-      }
-      if (element != isolate()->heap()->the_hole_value() &&
-          String::cast(element)->IsOneByteEqualTo(string_vector)) {
-        result = Handle<String>(String::cast(element), isolate());
-#ifdef DEBUG
-        uint32_t hash_field =
-            (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
-        DCHECK_EQ(static_cast<int>(result->Hash()),
-                  static_cast<int>(hash_field >> String::kHashShift));
-#endif
-        break;
-      }
-      entry = StringTable::NextProbe(entry, count++, capacity);
-    }
-    position_ = position;
-    // Advance past the last '"'.
-    AdvanceSkipWhitespace();
-    return result;
-  }
-
-  int beg_pos = position_;
-  // Fast case for Latin1 only without escape characters.
-  do {
-    // Check for control character (0x00-0x1f) or unterminated string (<0).
-    if (c0_ < 0x20) return Handle<String>::null();
-    if (c0_ != '\\') {
-      if (seq_one_byte || c0_ <= String::kMaxOneByteCharCode) {
-        Advance();
-      } else {
-        return SlowScanJsonString<SeqTwoByteString, uc16>(source_,
-                                                          beg_pos,
-                                                          position_);
-      }
-    } else {
-      return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
-                                                           beg_pos,
-                                                           position_);
-    }
-  } while (c0_ != '"');
-  int length = position_ - beg_pos;
-  Handle<String> result =
-      factory()->NewRawOneByteString(length, pretenure_).ToHandleChecked();
-  uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
-  String::WriteToFlat(*source_, dest, beg_pos, position_);
-
-  DCHECK_EQ('"', c0_);
-  // Advance past the last '"'.
-  AdvanceSkipWhitespace();
-  return result;
-}
-
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/json-stringifier.cc b/src/json-stringifier.cc
new file mode 100644
index 0000000..29685c2
--- /dev/null
+++ b/src/json-stringifier.cc
@@ -0,0 +1,722 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/json-stringifier.h"
+
+#include "src/conversions.h"
+#include "src/lookup.h"
+#include "src/messages.h"
+#include "src/objects-inl.h"
+#include "src/utils.h"
+
+namespace v8 {
+namespace internal {
+
+// Translation table to escape Latin1 characters.
+// Table entries start at a multiple of 8 and are null-terminated.
+const char* const JsonStringifier::JsonEscapeTable =
+    "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 "
+    "\\u0004\0 \\u0005\0 \\u0006\0 \\u0007\0 "
+    "\\b\0     \\t\0     \\n\0     \\u000b\0 "
+    "\\f\0     \\r\0     \\u000e\0 \\u000f\0 "
+    "\\u0010\0 \\u0011\0 \\u0012\0 \\u0013\0 "
+    "\\u0014\0 \\u0015\0 \\u0016\0 \\u0017\0 "
+    "\\u0018\0 \\u0019\0 \\u001a\0 \\u001b\0 "
+    "\\u001c\0 \\u001d\0 \\u001e\0 \\u001f\0 "
+    " \0      !\0      \\\"\0     #\0      "
+    "$\0      %\0      &\0      '\0      "
+    "(\0      )\0      *\0      +\0      "
+    ",\0      -\0      .\0      /\0      "
+    "0\0      1\0      2\0      3\0      "
+    "4\0      5\0      6\0      7\0      "
+    "8\0      9\0      :\0      ;\0      "
+    "<\0      =\0      >\0      ?\0      "
+    "@\0      A\0      B\0      C\0      "
+    "D\0      E\0      F\0      G\0      "
+    "H\0      I\0      J\0      K\0      "
+    "L\0      M\0      N\0      O\0      "
+    "P\0      Q\0      R\0      S\0      "
+    "T\0      U\0      V\0      W\0      "
+    "X\0      Y\0      Z\0      [\0      "
+    "\\\\\0     ]\0      ^\0      _\0      "
+    "`\0      a\0      b\0      c\0      "
+    "d\0      e\0      f\0      g\0      "
+    "h\0      i\0      j\0      k\0      "
+    "l\0      m\0      n\0      o\0      "
+    "p\0      q\0      r\0      s\0      "
+    "t\0      u\0      v\0      w\0      "
+    "x\0      y\0      z\0      {\0      "
+    "|\0      }\0      ~\0      \177\0      "
+    "\200\0      \201\0      \202\0      \203\0      "
+    "\204\0      \205\0      \206\0      \207\0      "
+    "\210\0      \211\0      \212\0      \213\0      "
+    "\214\0      \215\0      \216\0      \217\0      "
+    "\220\0      \221\0      \222\0      \223\0      "
+    "\224\0      \225\0      \226\0      \227\0      "
+    "\230\0      \231\0      \232\0      \233\0      "
+    "\234\0      \235\0      \236\0      \237\0      "
+    "\240\0      \241\0      \242\0      \243\0      "
+    "\244\0      \245\0      \246\0      \247\0      "
+    "\250\0      \251\0      \252\0      \253\0      "
+    "\254\0      \255\0      \256\0      \257\0      "
+    "\260\0      \261\0      \262\0      \263\0      "
+    "\264\0      \265\0      \266\0      \267\0      "
+    "\270\0      \271\0      \272\0      \273\0      "
+    "\274\0      \275\0      \276\0      \277\0      "
+    "\300\0      \301\0      \302\0      \303\0      "
+    "\304\0      \305\0      \306\0      \307\0      "
+    "\310\0      \311\0      \312\0      \313\0      "
+    "\314\0      \315\0      \316\0      \317\0      "
+    "\320\0      \321\0      \322\0      \323\0      "
+    "\324\0      \325\0      \326\0      \327\0      "
+    "\330\0      \331\0      \332\0      \333\0      "
+    "\334\0      \335\0      \336\0      \337\0      "
+    "\340\0      \341\0      \342\0      \343\0      "
+    "\344\0      \345\0      \346\0      \347\0      "
+    "\350\0      \351\0      \352\0      \353\0      "
+    "\354\0      \355\0      \356\0      \357\0      "
+    "\360\0      \361\0      \362\0      \363\0      "
+    "\364\0      \365\0      \366\0      \367\0      "
+    "\370\0      \371\0      \372\0      \373\0      "
+    "\374\0      \375\0      \376\0      \377\0      ";
+
+JsonStringifier::JsonStringifier(Isolate* isolate)
+    : isolate_(isolate), builder_(isolate), gap_(nullptr), indent_(0) {
+  tojson_string_ = factory()->toJSON_string();
+  stack_ = factory()->NewJSArray(8);
+}
+
+MaybeHandle<Object> JsonStringifier::Stringify(Handle<Object> object,
+                                               Handle<Object> replacer,
+                                               Handle<Object> gap) {
+  if (!InitializeReplacer(replacer)) return MaybeHandle<Object>();
+  if (!gap->IsUndefined(isolate_) && !InitializeGap(gap)) {
+    return MaybeHandle<Object>();
+  }
+  Result result = SerializeObject(object);
+  if (result == UNCHANGED) return factory()->undefined_value();
+  if (result == SUCCESS) return builder_.Finish();
+  DCHECK(result == EXCEPTION);
+  return MaybeHandle<Object>();
+}
+
+bool IsInList(Handle<String> key, List<Handle<String> >* list) {
+  // TODO(yangguo): This is O(n^2) for n properties in the list. Deal with this
+  // if this becomes an issue.
+  for (const Handle<String>& existing : *list) {
+    if (String::Equals(existing, key)) return true;
+  }
+  return false;
+}
+
+bool JsonStringifier::InitializeReplacer(Handle<Object> replacer) {
+  DCHECK(property_list_.is_null());
+  DCHECK(replacer_function_.is_null());
+  Maybe<bool> is_array = Object::IsArray(replacer);
+  if (is_array.IsNothing()) return false;
+  if (is_array.FromJust()) {
+    HandleScope handle_scope(isolate_);
+    List<Handle<String> > list;
+    Handle<Object> length_obj;
+    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+        isolate_, length_obj,
+        Object::GetLengthFromArrayLike(isolate_, replacer), false);
+    uint32_t length;
+    if (!length_obj->ToUint32(&length)) length = kMaxUInt32;
+    for (uint32_t i = 0; i < length; i++) {
+      Handle<Object> element;
+      Handle<String> key;
+      ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+          isolate_, element, Object::GetElement(isolate_, replacer, i), false);
+      if (element->IsNumber() || element->IsString()) {
+        ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+            isolate_, key, Object::ToString(isolate_, element), false);
+      } else if (element->IsJSValue()) {
+        Handle<Object> value(Handle<JSValue>::cast(element)->value(), isolate_);
+        if (value->IsNumber() || value->IsString()) {
+          ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+              isolate_, key, Object::ToString(isolate_, element), false);
+        }
+      }
+      if (key.is_null()) continue;
+      if (!IsInList(key, &list)) list.Add(key);
+    }
+    property_list_ = factory()->NewUninitializedFixedArray(list.length());
+    for (int i = 0; i < list.length(); i++) {
+      property_list_->set(i, *list[i]);
+    }
+    property_list_ = handle_scope.CloseAndEscape(property_list_);
+  } else if (replacer->IsCallable()) {
+    replacer_function_ = Handle<JSReceiver>::cast(replacer);
+  }
+  return true;
+}
+
+bool JsonStringifier::InitializeGap(Handle<Object> gap) {
+  DCHECK_NULL(gap_);
+  HandleScope scope(isolate_);
+  if (gap->IsJSValue()) {
+    Handle<Object> value(Handle<JSValue>::cast(gap)->value(), isolate_);
+    if (value->IsString()) {
+      ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap,
+                                       Object::ToString(isolate_, gap), false);
+    } else if (value->IsNumber()) {
+      ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap, Object::ToNumber(gap),
+                                       false);
+    }
+  }
+
+  if (gap->IsString()) {
+    Handle<String> gap_string = Handle<String>::cast(gap);
+    if (gap_string->length() > 0) {
+      int gap_length = std::min(gap_string->length(), 10);
+      gap_ = NewArray<uc16>(gap_length + 1);
+      String::WriteToFlat(*gap_string, gap_, 0, gap_length);
+      for (int i = 0; i < gap_length; i++) {
+        if (gap_[i] > String::kMaxOneByteCharCode) {
+          builder_.ChangeEncoding();
+          break;
+        }
+      }
+      gap_[gap_length] = '\0';
+    }
+  } else if (gap->IsNumber()) {
+    int num_value = DoubleToInt32(gap->Number());
+    if (num_value > 0) {
+      int gap_length = std::min(num_value, 10);
+      gap_ = NewArray<uc16>(gap_length + 1);
+      for (int i = 0; i < gap_length; i++) gap_[i] = ' ';
+      gap_[gap_length] = '\0';
+    }
+  }
+  return true;
+}
+
+MaybeHandle<Object> JsonStringifier::ApplyToJsonFunction(Handle<Object> object,
+                                                         Handle<Object> key) {
+  HandleScope scope(isolate_);
+  LookupIterator it(object, tojson_string_,
+                    LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
+  Handle<Object> fun;
+  ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object);
+  if (!fun->IsCallable()) return object;
+
+  // Call toJSON function.
+  if (key->IsSmi()) key = factory()->NumberToString(key);
+  Handle<Object> argv[] = {key};
+  ASSIGN_RETURN_ON_EXCEPTION(isolate_, object,
+                             Execution::Call(isolate_, fun, object, 1, argv),
+                             Object);
+  return scope.CloseAndEscape(object);
+}
+
+MaybeHandle<Object> JsonStringifier::ApplyReplacerFunction(
+    Handle<Object> value, Handle<Object> key, Handle<Object> initial_holder) {
+  HandleScope scope(isolate_);
+  if (key->IsSmi()) key = factory()->NumberToString(key);
+  Handle<Object> argv[] = {key, value};
+  Handle<JSReceiver> holder = CurrentHolder(value, initial_holder);
+  ASSIGN_RETURN_ON_EXCEPTION(
+      isolate_, value,
+      Execution::Call(isolate_, replacer_function_, holder, 2, argv), Object);
+  return scope.CloseAndEscape(value);
+}
+
+Handle<JSReceiver> JsonStringifier::CurrentHolder(
+    Handle<Object> value, Handle<Object> initial_holder) {
+  int length = Smi::cast(stack_->length())->value();
+  if (length == 0) {
+    Handle<JSObject> holder =
+        factory()->NewJSObject(isolate_->object_function());
+    JSObject::AddProperty(holder, factory()->empty_string(), initial_holder,
+                          NONE);
+    return holder;
+  } else {
+    FixedArray* elements = FixedArray::cast(stack_->elements());
+    return Handle<JSReceiver>(JSReceiver::cast(elements->get(length - 1)),
+                              isolate_);
+  }
+}
+
+JsonStringifier::Result JsonStringifier::StackPush(Handle<Object> object) {
+  StackLimitCheck check(isolate_);
+  if (check.HasOverflowed()) {
+    isolate_->StackOverflow();
+    return EXCEPTION;
+  }
+
+  int length = Smi::cast(stack_->length())->value();
+  {
+    DisallowHeapAllocation no_allocation;
+    FixedArray* elements = FixedArray::cast(stack_->elements());
+    for (int i = 0; i < length; i++) {
+      if (elements->get(i) == *object) {
+        AllowHeapAllocation allow_to_return_error;
+        Handle<Object> error =
+            factory()->NewTypeError(MessageTemplate::kCircularStructure);
+        isolate_->Throw(*error);
+        return EXCEPTION;
+      }
+    }
+  }
+  JSArray::SetLength(stack_, length + 1);
+  FixedArray::cast(stack_->elements())->set(length, *object);
+  return SUCCESS;
+}
+
+void JsonStringifier::StackPop() {
+  int length = Smi::cast(stack_->length())->value();
+  stack_->set_length(Smi::FromInt(length - 1));
+}
+
+template <bool deferred_string_key>
+JsonStringifier::Result JsonStringifier::Serialize_(Handle<Object> object,
+                                                    bool comma,
+                                                    Handle<Object> key) {
+  StackLimitCheck interrupt_check(isolate_);
+  Handle<Object> initial_value = object;
+  if (interrupt_check.InterruptRequested() &&
+      isolate_->stack_guard()->HandleInterrupts()->IsException(isolate_)) {
+    return EXCEPTION;
+  }
+  if (object->IsJSReceiver()) {
+    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+        isolate_, object, ApplyToJsonFunction(object, key), EXCEPTION);
+  }
+  if (!replacer_function_.is_null()) {
+    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+        isolate_, object, ApplyReplacerFunction(object, key, initial_value),
+        EXCEPTION);
+  }
+
+  if (object->IsSmi()) {
+    if (deferred_string_key) SerializeDeferredKey(comma, key);
+    return SerializeSmi(Smi::cast(*object));
+  }
+
+  switch (HeapObject::cast(*object)->map()->instance_type()) {
+    case HEAP_NUMBER_TYPE:
+    case MUTABLE_HEAP_NUMBER_TYPE:
+      if (deferred_string_key) SerializeDeferredKey(comma, key);
+      return SerializeHeapNumber(Handle<HeapNumber>::cast(object));
+    case ODDBALL_TYPE:
+      switch (Oddball::cast(*object)->kind()) {
+        case Oddball::kFalse:
+          if (deferred_string_key) SerializeDeferredKey(comma, key);
+          builder_.AppendCString("false");
+          return SUCCESS;
+        case Oddball::kTrue:
+          if (deferred_string_key) SerializeDeferredKey(comma, key);
+          builder_.AppendCString("true");
+          return SUCCESS;
+        case Oddball::kNull:
+          if (deferred_string_key) SerializeDeferredKey(comma, key);
+          builder_.AppendCString("null");
+          return SUCCESS;
+        default:
+          return UNCHANGED;
+      }
+    case JS_ARRAY_TYPE:
+      if (deferred_string_key) SerializeDeferredKey(comma, key);
+      return SerializeJSArray(Handle<JSArray>::cast(object));
+    case JS_VALUE_TYPE:
+      if (deferred_string_key) SerializeDeferredKey(comma, key);
+      return SerializeJSValue(Handle<JSValue>::cast(object));
+    case SIMD128_VALUE_TYPE:
+    case SYMBOL_TYPE:
+      return UNCHANGED;
+    default:
+      if (object->IsString()) {
+        if (deferred_string_key) SerializeDeferredKey(comma, key);
+        SerializeString(Handle<String>::cast(object));
+        return SUCCESS;
+      } else {
+        DCHECK(object->IsJSReceiver());
+        if (object->IsCallable()) return UNCHANGED;
+        // Go to slow path for global proxy and objects requiring access checks.
+        if (deferred_string_key) SerializeDeferredKey(comma, key);
+        if (object->IsJSProxy()) {
+          return SerializeJSProxy(Handle<JSProxy>::cast(object));
+        }
+        return SerializeJSObject(Handle<JSObject>::cast(object));
+      }
+  }
+
+  UNREACHABLE();
+  return UNCHANGED;
+}
+
+JsonStringifier::Result JsonStringifier::SerializeJSValue(
+    Handle<JSValue> object) {
+  String* class_name = object->class_name();
+  if (class_name == isolate_->heap()->String_string()) {
+    Handle<Object> value;
+    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+        isolate_, value, Object::ToString(isolate_, object), EXCEPTION);
+    SerializeString(Handle<String>::cast(value));
+  } else if (class_name == isolate_->heap()->Number_string()) {
+    Handle<Object> value;
+    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, value, Object::ToNumber(object),
+                                     EXCEPTION);
+    if (value->IsSmi()) return SerializeSmi(Smi::cast(*value));
+    SerializeHeapNumber(Handle<HeapNumber>::cast(value));
+  } else if (class_name == isolate_->heap()->Boolean_string()) {
+    Object* value = JSValue::cast(*object)->value();
+    DCHECK(value->IsBoolean());
+    builder_.AppendCString(value->IsTrue(isolate_) ? "true" : "false");
+  } else {
+    // ES6 24.3.2.1 step 10.c, serialize as an ordinary JSObject.
+    return SerializeJSObject(object);
+  }
+  return SUCCESS;
+}
+
+JsonStringifier::Result JsonStringifier::SerializeSmi(Smi* object) {
+  static const int kBufferSize = 100;
+  char chars[kBufferSize];
+  Vector<char> buffer(chars, kBufferSize);
+  builder_.AppendCString(IntToCString(object->value(), buffer));
+  return SUCCESS;
+}
+
+JsonStringifier::Result JsonStringifier::SerializeDouble(double number) {
+  if (std::isinf(number) || std::isnan(number)) {
+    builder_.AppendCString("null");
+    return SUCCESS;
+  }
+  static const int kBufferSize = 100;
+  char chars[kBufferSize];
+  Vector<char> buffer(chars, kBufferSize);
+  builder_.AppendCString(DoubleToCString(number, buffer));
+  return SUCCESS;
+}
+
+JsonStringifier::Result JsonStringifier::SerializeJSArray(
+    Handle<JSArray> object) {
+  HandleScope handle_scope(isolate_);
+  Result stack_push = StackPush(object);
+  if (stack_push != SUCCESS) return stack_push;
+  uint32_t length = 0;
+  CHECK(object->length()->ToArrayLength(&length));
+  DCHECK(!object->IsAccessCheckNeeded());
+  builder_.AppendCharacter('[');
+  Indent();
+  uint32_t i = 0;
+  if (replacer_function_.is_null()) {
+    switch (object->GetElementsKind()) {
+      case FAST_SMI_ELEMENTS: {
+        Handle<FixedArray> elements(FixedArray::cast(object->elements()),
+                                    isolate_);
+        StackLimitCheck interrupt_check(isolate_);
+        while (i < length) {
+          if (interrupt_check.InterruptRequested() &&
+              isolate_->stack_guard()->HandleInterrupts()->IsException(
+                  isolate_)) {
+            return EXCEPTION;
+          }
+          Separator(i == 0);
+          SerializeSmi(Smi::cast(elements->get(i)));
+          i++;
+        }
+        break;
+      }
+      case FAST_DOUBLE_ELEMENTS: {
+        // Empty array is FixedArray but not FixedDoubleArray.
+        if (length == 0) break;
+        Handle<FixedDoubleArray> elements(
+            FixedDoubleArray::cast(object->elements()), isolate_);
+        StackLimitCheck interrupt_check(isolate_);
+        while (i < length) {
+          if (interrupt_check.InterruptRequested() &&
+              isolate_->stack_guard()->HandleInterrupts()->IsException(
+                  isolate_)) {
+            return EXCEPTION;
+          }
+          Separator(i == 0);
+          SerializeDouble(elements->get_scalar(i));
+          i++;
+        }
+        break;
+      }
+      case FAST_ELEMENTS: {
+        Handle<Object> old_length(object->length(), isolate_);
+        while (i < length) {
+          if (object->length() != *old_length ||
+              object->GetElementsKind() != FAST_ELEMENTS) {
+            // Fall back to slow path.
+            break;
+          }
+          Separator(i == 0);
+          Result result = SerializeElement(
+              isolate_,
+              Handle<Object>(FixedArray::cast(object->elements())->get(i),
+                             isolate_),
+              i);
+          if (result == UNCHANGED) {
+            builder_.AppendCString("null");
+          } else if (result != SUCCESS) {
+            return result;
+          }
+          i++;
+        }
+        break;
+      }
+      // The FAST_HOLEY_* cases could be handled in a faster way. They resemble
+      // the non-holey cases except that a lookup is necessary for holes.
+      default:
+        break;
+    }
+  }
+  if (i < length) {
+    // Slow path for non-fast elements and fall-back in edge case.
+    Result result = SerializeArrayLikeSlow(object, i, length);
+    if (result != SUCCESS) return result;
+  }
+  Unindent();
+  if (length > 0) NewLine();
+  builder_.AppendCharacter(']');
+  StackPop();
+  return SUCCESS;
+}
+
+JsonStringifier::Result JsonStringifier::SerializeArrayLikeSlow(
+    Handle<JSReceiver> object, uint32_t start, uint32_t length) {
+  // We need to write out at least two characters per array element.
+  static const int kMaxSerializableArrayLength = String::kMaxLength / 2;
+  if (length > kMaxSerializableArrayLength) {
+    isolate_->Throw(*isolate_->factory()->NewInvalidStringLengthError());
+    return EXCEPTION;
+  }
+  for (uint32_t i = start; i < length; i++) {
+    Separator(i == 0);
+    Handle<Object> element;
+    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+        isolate_, element, JSReceiver::GetElement(isolate_, object, i),
+        EXCEPTION);
+    Result result = SerializeElement(isolate_, element, i);
+    if (result == SUCCESS) continue;
+    if (result == UNCHANGED) {
+      // Detect overflow sooner for large sparse arrays.
+      if (builder_.HasOverflowed()) return EXCEPTION;
+      builder_.AppendCString("null");
+    } else {
+      return result;
+    }
+  }
+  return SUCCESS;
+}
+
+JsonStringifier::Result JsonStringifier::SerializeJSObject(
+    Handle<JSObject> object) {
+  HandleScope handle_scope(isolate_);
+  Result stack_push = StackPush(object);
+  if (stack_push != SUCCESS) return stack_push;
+
+  if (property_list_.is_null() &&
+      object->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER &&
+      object->HasFastProperties() &&
+      Handle<JSObject>::cast(object)->elements()->length() == 0) {
+    DCHECK(object->IsJSObject());
+    DCHECK(!object->IsJSGlobalProxy());
+    Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
+    DCHECK(!js_obj->HasIndexedInterceptor());
+    DCHECK(!js_obj->HasNamedInterceptor());
+    Handle<Map> map(js_obj->map());
+    builder_.AppendCharacter('{');
+    Indent();
+    bool comma = false;
+    for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
+      Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_);
+      // TODO(rossberg): Should this throw?
+      if (!name->IsString()) continue;
+      Handle<String> key = Handle<String>::cast(name);
+      PropertyDetails details = map->instance_descriptors()->GetDetails(i);
+      if (details.IsDontEnum()) continue;
+      Handle<Object> property;
+      if (details.type() == DATA && *map == js_obj->map()) {
+        FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
+        property = JSObject::FastPropertyAt(js_obj, details.representation(),
+                                            field_index);
+      } else {
+        ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+            isolate_, property, Object::GetPropertyOrElement(js_obj, key),
+            EXCEPTION);
+      }
+      Result result = SerializeProperty(property, comma, key);
+      if (!comma && result == SUCCESS) comma = true;
+      if (result == EXCEPTION) return result;
+    }
+    Unindent();
+    if (comma) NewLine();
+    builder_.AppendCharacter('}');
+  } else {
+    Result result = SerializeJSReceiverSlow(object);
+    if (result != SUCCESS) return result;
+  }
+  StackPop();
+  return SUCCESS;
+}
+
+JsonStringifier::Result JsonStringifier::SerializeJSReceiverSlow(
+    Handle<JSReceiver> object) {
+  Handle<FixedArray> contents = property_list_;
+  if (contents.is_null()) {
+    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+        isolate_, contents,
+        KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
+                                ENUMERABLE_STRINGS,
+                                GetKeysConversion::kConvertToString),
+        EXCEPTION);
+  }
+  builder_.AppendCharacter('{');
+  Indent();
+  bool comma = false;
+  for (int i = 0; i < contents->length(); i++) {
+    Handle<String> key(String::cast(contents->get(i)), isolate_);
+    Handle<Object> property;
+    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, property,
+                                     Object::GetPropertyOrElement(object, key),
+                                     EXCEPTION);
+    Result result = SerializeProperty(property, comma, key);
+    if (!comma && result == SUCCESS) comma = true;
+    if (result == EXCEPTION) return result;
+  }
+  Unindent();
+  if (comma) NewLine();
+  builder_.AppendCharacter('}');
+  return SUCCESS;
+}
+
+JsonStringifier::Result JsonStringifier::SerializeJSProxy(
+    Handle<JSProxy> object) {
+  HandleScope scope(isolate_);
+  Result stack_push = StackPush(object);
+  if (stack_push != SUCCESS) return stack_push;
+  Maybe<bool> is_array = Object::IsArray(object);
+  if (is_array.IsNothing()) return EXCEPTION;
+  if (is_array.FromJust()) {
+    Handle<Object> length_object;
+    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+        isolate_, length_object,
+        Object::GetLengthFromArrayLike(isolate_, object), EXCEPTION);
+    uint32_t length;
+    if (!length_object->ToUint32(&length)) {
+      // Technically, we need to be able to handle lengths outside the
+      // uint32_t range. However, we would run into string size overflow
+      // if we tried to stringify such an array.
+      isolate_->Throw(*isolate_->factory()->NewInvalidStringLengthError());
+      return EXCEPTION;
+    }
+    builder_.AppendCharacter('[');
+    Indent();
+    Result result = SerializeArrayLikeSlow(object, 0, length);
+    if (result != SUCCESS) return result;
+    Unindent();
+    if (length > 0) NewLine();
+    builder_.AppendCharacter(']');
+  } else {
+    Result result = SerializeJSReceiverSlow(object);
+    if (result != SUCCESS) return result;
+  }
+  StackPop();
+  return SUCCESS;
+}
+
+template <typename SrcChar, typename DestChar>
+void JsonStringifier::SerializeStringUnchecked_(
+    Vector<const SrcChar> src,
+    IncrementalStringBuilder::NoExtend<DestChar>* dest) {
+  // Assert that uc16 character is not truncated down to 8 bit.
+  // The <uc16, char> version of this method must not be called.
+  DCHECK(sizeof(DestChar) >= sizeof(SrcChar));
+
+  for (int i = 0; i < src.length(); i++) {
+    SrcChar c = src[i];
+    if (DoNotEscape(c)) {
+      dest->Append(c);
+    } else {
+      dest->AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
+    }
+  }
+}
+
+template <typename SrcChar, typename DestChar>
+void JsonStringifier::SerializeString_(Handle<String> string) {
+  int length = string->length();
+  builder_.Append<uint8_t, DestChar>('"');
+  // We make a rough estimate to find out if the current string can be
+  // serialized without allocating a new string part. The worst case length of
+  // an escaped character is 6.  Shifting the remainin string length right by 3
+  // is a more pessimistic estimate, but faster to calculate.
+  int worst_case_length = length << 3;
+  if (builder_.CurrentPartCanFit(worst_case_length)) {
+    DisallowHeapAllocation no_gc;
+    Vector<const SrcChar> vector = string->GetCharVector<SrcChar>();
+    IncrementalStringBuilder::NoExtendBuilder<DestChar> no_extend(
+        &builder_, worst_case_length);
+    SerializeStringUnchecked_(vector, &no_extend);
+  } else {
+    FlatStringReader reader(isolate_, string);
+    for (int i = 0; i < reader.length(); i++) {
+      SrcChar c = reader.Get<SrcChar>(i);
+      if (DoNotEscape(c)) {
+        builder_.Append<SrcChar, DestChar>(c);
+      } else {
+        builder_.AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
+      }
+    }
+  }
+
+  builder_.Append<uint8_t, DestChar>('"');
+}
+
+template <>
+bool JsonStringifier::DoNotEscape(uint8_t c) {
+  return c >= '#' && c <= '~' && c != '\\';
+}
+
+template <>
+bool JsonStringifier::DoNotEscape(uint16_t c) {
+  return c >= '#' && c != '\\' && c != 0x7f;
+}
+
+void JsonStringifier::NewLine() {
+  if (gap_ == nullptr) return;
+  builder_.AppendCharacter('\n');
+  for (int i = 0; i < indent_; i++) builder_.AppendCString(gap_);
+}
+
+void JsonStringifier::Separator(bool first) {
+  if (!first) builder_.AppendCharacter(',');
+  NewLine();
+}
+
+void JsonStringifier::SerializeDeferredKey(bool deferred_comma,
+                                           Handle<Object> deferred_key) {
+  Separator(!deferred_comma);
+  SerializeString(Handle<String>::cast(deferred_key));
+  builder_.AppendCharacter(':');
+  if (gap_ != nullptr) builder_.AppendCharacter(' ');
+}
+
+void JsonStringifier::SerializeString(Handle<String> object) {
+  object = String::Flatten(object);
+  if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) {
+    if (object->IsOneByteRepresentationUnderneath()) {
+      SerializeString_<uint8_t, uint8_t>(object);
+    } else {
+      builder_.ChangeEncoding();
+      SerializeString(object);
+    }
+  } else {
+    if (object->IsOneByteRepresentationUnderneath()) {
+      SerializeString_<uint8_t, uc16>(object);
+    } else {
+      SerializeString_<uc16, uc16>(object);
+    }
+  }
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/json-stringifier.h b/src/json-stringifier.h
index b40a782..e72bd9d 100644
--- a/src/json-stringifier.h
+++ b/src/json-stringifier.h
@@ -5,36 +5,33 @@
 #ifndef V8_JSON_STRINGIFIER_H_
 #define V8_JSON_STRINGIFIER_H_
 
-#include "src/conversions.h"
-#include "src/lookup.h"
-#include "src/messages.h"
+#include "src/objects.h"
 #include "src/string-builder.h"
-#include "src/utils.h"
 
 namespace v8 {
 namespace internal {
 
-class BasicJsonStringifier BASE_EMBEDDED {
+class JsonStringifier BASE_EMBEDDED {
  public:
-  explicit BasicJsonStringifier(Isolate* isolate);
+  explicit JsonStringifier(Isolate* isolate);
 
-  MUST_USE_RESULT MaybeHandle<Object> Stringify(Handle<Object> object);
+  ~JsonStringifier() { DeleteArray(gap_); }
 
-  MUST_USE_RESULT INLINE(static MaybeHandle<Object> StringifyString(
-      Isolate* isolate,
-      Handle<String> object));
+  MUST_USE_RESULT MaybeHandle<Object> Stringify(Handle<Object> object,
+                                                Handle<Object> replacer,
+                                                Handle<Object> gap);
 
  private:
   enum Result { UNCHANGED, SUCCESS, EXCEPTION };
 
+  bool InitializeReplacer(Handle<Object> replacer);
+  bool InitializeGap(Handle<Object> gap);
+
   MUST_USE_RESULT MaybeHandle<Object> ApplyToJsonFunction(
       Handle<Object> object,
       Handle<Object> key);
-
-  Result SerializeGeneric(Handle<Object> object,
-                          Handle<Object> key,
-                          bool deferred_comma,
-                          bool deferred_key);
+  MUST_USE_RESULT MaybeHandle<Object> ApplyReplacerFunction(
+      Handle<Object> value, Handle<Object> key, Handle<Object> initial_holder);
 
   // Entry point to serialize the object.
   INLINE(Result SerializeObject(Handle<Object> obj)) {
@@ -64,11 +61,8 @@
   template <bool deferred_string_key>
   Result Serialize_(Handle<Object> object, bool comma, Handle<Object> key);
 
-  void SerializeDeferredKey(bool deferred_comma, Handle<Object> deferred_key) {
-    if (deferred_comma) builder_.AppendCharacter(',');
-    SerializeString(Handle<String>::cast(deferred_key));
-    builder_.AppendCharacter(':');
-  }
+  INLINE(void SerializeDeferredKey(bool deferred_comma,
+                                   Handle<Object> deferred_key));
 
   Result SerializeSmi(Smi* object);
 
@@ -82,8 +76,10 @@
   INLINE(Result SerializeJSArray(Handle<JSArray> object));
   INLINE(Result SerializeJSObject(Handle<JSObject> object));
 
-  Result SerializeJSArraySlow(Handle<JSArray> object, uint32_t start,
-                              uint32_t length);
+  Result SerializeJSProxy(Handle<JSProxy> object);
+  Result SerializeJSReceiverSlow(Handle<JSReceiver> object);
+  Result SerializeArrayLikeSlow(Handle<JSReceiver> object, uint32_t start,
+                                uint32_t length);
 
   void SerializeString(Handle<String> object);
 
@@ -98,6 +94,14 @@
   template <typename Char>
   INLINE(static bool DoNotEscape(Char c));
 
+  INLINE(void NewLine());
+  INLINE(void Indent() { indent_++; });
+  INLINE(void Unindent() { indent_--; });
+  INLINE(void Separator(bool first));
+
+  Handle<JSReceiver> CurrentHolder(Handle<Object> value,
+                                   Handle<Object> inital_holder);
+
   Result StackPush(Handle<Object> object);
   void StackPop();
 
@@ -107,579 +111,15 @@
   IncrementalStringBuilder builder_;
   Handle<String> tojson_string_;
   Handle<JSArray> stack_;
+  Handle<FixedArray> property_list_;
+  Handle<JSReceiver> replacer_function_;
+  uc16* gap_;
+  int indent_;
 
   static const int kJsonEscapeTableEntrySize = 8;
   static const char* const JsonEscapeTable;
 };
 
-
-// Translation table to escape Latin1 characters.
-// Table entries start at a multiple of 8 and are null-terminated.
-const char* const BasicJsonStringifier::JsonEscapeTable =
-    "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 "
-    "\\u0004\0 \\u0005\0 \\u0006\0 \\u0007\0 "
-    "\\b\0     \\t\0     \\n\0     \\u000b\0 "
-    "\\f\0     \\r\0     \\u000e\0 \\u000f\0 "
-    "\\u0010\0 \\u0011\0 \\u0012\0 \\u0013\0 "
-    "\\u0014\0 \\u0015\0 \\u0016\0 \\u0017\0 "
-    "\\u0018\0 \\u0019\0 \\u001a\0 \\u001b\0 "
-    "\\u001c\0 \\u001d\0 \\u001e\0 \\u001f\0 "
-    " \0      !\0      \\\"\0     #\0      "
-    "$\0      %\0      &\0      '\0      "
-    "(\0      )\0      *\0      +\0      "
-    ",\0      -\0      .\0      /\0      "
-    "0\0      1\0      2\0      3\0      "
-    "4\0      5\0      6\0      7\0      "
-    "8\0      9\0      :\0      ;\0      "
-    "<\0      =\0      >\0      ?\0      "
-    "@\0      A\0      B\0      C\0      "
-    "D\0      E\0      F\0      G\0      "
-    "H\0      I\0      J\0      K\0      "
-    "L\0      M\0      N\0      O\0      "
-    "P\0      Q\0      R\0      S\0      "
-    "T\0      U\0      V\0      W\0      "
-    "X\0      Y\0      Z\0      [\0      "
-    "\\\\\0     ]\0      ^\0      _\0      "
-    "`\0      a\0      b\0      c\0      "
-    "d\0      e\0      f\0      g\0      "
-    "h\0      i\0      j\0      k\0      "
-    "l\0      m\0      n\0      o\0      "
-    "p\0      q\0      r\0      s\0      "
-    "t\0      u\0      v\0      w\0      "
-    "x\0      y\0      z\0      {\0      "
-    "|\0      }\0      ~\0      \177\0      "
-    "\200\0      \201\0      \202\0      \203\0      "
-    "\204\0      \205\0      \206\0      \207\0      "
-    "\210\0      \211\0      \212\0      \213\0      "
-    "\214\0      \215\0      \216\0      \217\0      "
-    "\220\0      \221\0      \222\0      \223\0      "
-    "\224\0      \225\0      \226\0      \227\0      "
-    "\230\0      \231\0      \232\0      \233\0      "
-    "\234\0      \235\0      \236\0      \237\0      "
-    "\240\0      \241\0      \242\0      \243\0      "
-    "\244\0      \245\0      \246\0      \247\0      "
-    "\250\0      \251\0      \252\0      \253\0      "
-    "\254\0      \255\0      \256\0      \257\0      "
-    "\260\0      \261\0      \262\0      \263\0      "
-    "\264\0      \265\0      \266\0      \267\0      "
-    "\270\0      \271\0      \272\0      \273\0      "
-    "\274\0      \275\0      \276\0      \277\0      "
-    "\300\0      \301\0      \302\0      \303\0      "
-    "\304\0      \305\0      \306\0      \307\0      "
-    "\310\0      \311\0      \312\0      \313\0      "
-    "\314\0      \315\0      \316\0      \317\0      "
-    "\320\0      \321\0      \322\0      \323\0      "
-    "\324\0      \325\0      \326\0      \327\0      "
-    "\330\0      \331\0      \332\0      \333\0      "
-    "\334\0      \335\0      \336\0      \337\0      "
-    "\340\0      \341\0      \342\0      \343\0      "
-    "\344\0      \345\0      \346\0      \347\0      "
-    "\350\0      \351\0      \352\0      \353\0      "
-    "\354\0      \355\0      \356\0      \357\0      "
-    "\360\0      \361\0      \362\0      \363\0      "
-    "\364\0      \365\0      \366\0      \367\0      "
-    "\370\0      \371\0      \372\0      \373\0      "
-    "\374\0      \375\0      \376\0      \377\0      ";
-
-
-BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate)
-    : isolate_(isolate), builder_(isolate) {
-  tojson_string_ = factory()->toJSON_string();
-  stack_ = factory()->NewJSArray(8);
-}
-
-
-MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object) {
-  Result result = SerializeObject(object);
-  if (result == UNCHANGED) return factory()->undefined_value();
-  if (result == SUCCESS) return builder_.Finish();
-  DCHECK(result == EXCEPTION);
-  return MaybeHandle<Object>();
-}
-
-
-MaybeHandle<Object> BasicJsonStringifier::StringifyString(
-    Isolate* isolate,  Handle<String> object) {
-  static const int kJsonQuoteWorstCaseBlowup = 6;
-  static const int kSpaceForQuotes = 2;
-  int worst_case_length =
-      object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes;
-
-  if (worst_case_length > 32 * KB) {  // Slow path if too large.
-    BasicJsonStringifier stringifier(isolate);
-    return stringifier.Stringify(object);
-  }
-
-  object = String::Flatten(object);
-  DCHECK(object->IsFlat());
-  Handle<SeqString> result;
-  if (object->IsOneByteRepresentationUnderneath()) {
-    result = isolate->factory()
-                 ->NewRawOneByteString(worst_case_length)
-                 .ToHandleChecked();
-    IncrementalStringBuilder::NoExtendString<uint8_t> no_extend(
-        result, worst_case_length);
-    no_extend.Append('\"');
-    SerializeStringUnchecked_(object->GetFlatContent().ToOneByteVector(),
-                              &no_extend);
-    no_extend.Append('\"');
-    return no_extend.Finalize();
-  } else {
-    result = isolate->factory()
-                 ->NewRawTwoByteString(worst_case_length)
-                 .ToHandleChecked();
-    IncrementalStringBuilder::NoExtendString<uc16> no_extend(result,
-                                                             worst_case_length);
-    no_extend.Append('\"');
-    SerializeStringUnchecked_(object->GetFlatContent().ToUC16Vector(),
-                              &no_extend);
-    no_extend.Append('\"');
-    return no_extend.Finalize();
-  }
-}
-
-
-MaybeHandle<Object> BasicJsonStringifier::ApplyToJsonFunction(
-    Handle<Object> object, Handle<Object> key) {
-  LookupIterator it(object, tojson_string_,
-                    LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
-  Handle<Object> fun;
-  ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object);
-  if (!fun->IsCallable()) return object;
-
-  // Call toJSON function.
-  if (key->IsSmi()) key = factory()->NumberToString(key);
-  Handle<Object> argv[] = { key };
-  HandleScope scope(isolate_);
-  ASSIGN_RETURN_ON_EXCEPTION(
-      isolate_, object,
-      Execution::Call(isolate_, fun, object, 1, argv),
-      Object);
-  return scope.CloseAndEscape(object);
-}
-
-
-BasicJsonStringifier::Result BasicJsonStringifier::StackPush(
-    Handle<Object> object) {
-  StackLimitCheck check(isolate_);
-  if (check.HasOverflowed()) {
-    isolate_->StackOverflow();
-    return EXCEPTION;
-  }
-
-  int length = Smi::cast(stack_->length())->value();
-  {
-    DisallowHeapAllocation no_allocation;
-    FixedArray* elements = FixedArray::cast(stack_->elements());
-    for (int i = 0; i < length; i++) {
-      if (elements->get(i) == *object) {
-        AllowHeapAllocation allow_to_return_error;
-        Handle<Object> error =
-            factory()->NewTypeError(MessageTemplate::kCircularStructure);
-        isolate_->Throw(*error);
-        return EXCEPTION;
-      }
-    }
-  }
-  JSArray::SetLength(stack_, length + 1);
-  FixedArray::cast(stack_->elements())->set(length, *object);
-  return SUCCESS;
-}
-
-
-void BasicJsonStringifier::StackPop() {
-  int length = Smi::cast(stack_->length())->value();
-  stack_->set_length(Smi::FromInt(length - 1));
-}
-
-
-template <bool deferred_string_key>
-BasicJsonStringifier::Result BasicJsonStringifier::Serialize_(
-    Handle<Object> object, bool comma, Handle<Object> key) {
-  if (object->IsJSObject()) {
-    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-        isolate_, object,
-        ApplyToJsonFunction(object, key),
-        EXCEPTION);
-  }
-
-  if (object->IsSmi()) {
-    if (deferred_string_key) SerializeDeferredKey(comma, key);
-    return SerializeSmi(Smi::cast(*object));
-  }
-
-  switch (HeapObject::cast(*object)->map()->instance_type()) {
-    case HEAP_NUMBER_TYPE:
-    case MUTABLE_HEAP_NUMBER_TYPE:
-      if (deferred_string_key) SerializeDeferredKey(comma, key);
-      return SerializeHeapNumber(Handle<HeapNumber>::cast(object));
-    case ODDBALL_TYPE:
-      switch (Oddball::cast(*object)->kind()) {
-        case Oddball::kFalse:
-          if (deferred_string_key) SerializeDeferredKey(comma, key);
-          builder_.AppendCString("false");
-          return SUCCESS;
-        case Oddball::kTrue:
-          if (deferred_string_key) SerializeDeferredKey(comma, key);
-          builder_.AppendCString("true");
-          return SUCCESS;
-        case Oddball::kNull:
-          if (deferred_string_key) SerializeDeferredKey(comma, key);
-          builder_.AppendCString("null");
-          return SUCCESS;
-        default:
-          return UNCHANGED;
-      }
-    case JS_ARRAY_TYPE:
-      if (object->IsAccessCheckNeeded()) break;
-      if (deferred_string_key) SerializeDeferredKey(comma, key);
-      return SerializeJSArray(Handle<JSArray>::cast(object));
-    case JS_VALUE_TYPE:
-      if (deferred_string_key) SerializeDeferredKey(comma, key);
-      return SerializeJSValue(Handle<JSValue>::cast(object));
-    default:
-      if (object->IsString()) {
-        if (deferred_string_key) SerializeDeferredKey(comma, key);
-        SerializeString(Handle<String>::cast(object));
-        return SUCCESS;
-      } else if (object->IsJSObject()) {
-        if (object->IsCallable()) return UNCHANGED;
-        // Go to slow path for global proxy and objects requiring access checks.
-        if (object->IsAccessCheckNeeded() || object->IsJSGlobalProxy()) break;
-        if (deferred_string_key) SerializeDeferredKey(comma, key);
-        return SerializeJSObject(Handle<JSObject>::cast(object));
-      }
-  }
-
-  return SerializeGeneric(object, key, comma, deferred_string_key);
-}
-
-
-BasicJsonStringifier::Result BasicJsonStringifier::SerializeGeneric(
-    Handle<Object> object,
-    Handle<Object> key,
-    bool deferred_comma,
-    bool deferred_key) {
-  Handle<JSFunction> fun = isolate_->json_serialize_adapter();
-  Handle<Object> argv[] = { key, object };
-  Handle<Object> result;
-  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-      isolate_, result, Execution::Call(isolate_, fun, object, 2, argv),
-      EXCEPTION);
-  if (result->IsUndefined()) return UNCHANGED;
-  if (deferred_key) {
-    if (key->IsSmi()) key = factory()->NumberToString(key);
-    SerializeDeferredKey(deferred_comma, key);
-  }
-
-  builder_.AppendString(Handle<String>::cast(result));
-  return SUCCESS;
-}
-
-
-BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSValue(
-    Handle<JSValue> object) {
-  String* class_name = object->class_name();
-  if (class_name == isolate_->heap()->String_string()) {
-    Handle<Object> value;
-    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-        isolate_, value, Object::ToString(isolate_, object), EXCEPTION);
-    SerializeString(Handle<String>::cast(value));
-  } else if (class_name == isolate_->heap()->Number_string()) {
-    Handle<Object> value;
-    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, value, Object::ToNumber(object),
-                                     EXCEPTION);
-    if (value->IsSmi()) return SerializeSmi(Smi::cast(*value));
-    SerializeHeapNumber(Handle<HeapNumber>::cast(value));
-  } else if (class_name == isolate_->heap()->Boolean_string()) {
-    Object* value = JSValue::cast(*object)->value();
-    DCHECK(value->IsBoolean());
-    builder_.AppendCString(value->IsTrue() ? "true" : "false");
-  } else {
-    // ES6 24.3.2.1 step 10.c, serialize as an ordinary JSObject.
-    CHECK(!object->IsAccessCheckNeeded());
-    CHECK(!object->IsJSGlobalProxy());
-    return SerializeJSObject(object);
-  }
-  return SUCCESS;
-}
-
-
-BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) {
-  static const int kBufferSize = 100;
-  char chars[kBufferSize];
-  Vector<char> buffer(chars, kBufferSize);
-  builder_.AppendCString(IntToCString(object->value(), buffer));
-  return SUCCESS;
-}
-
-
-BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble(
-    double number) {
-  if (std::isinf(number) || std::isnan(number)) {
-    builder_.AppendCString("null");
-    return SUCCESS;
-  }
-  static const int kBufferSize = 100;
-  char chars[kBufferSize];
-  Vector<char> buffer(chars, kBufferSize);
-  builder_.AppendCString(DoubleToCString(number, buffer));
-  return SUCCESS;
-}
-
-
-BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray(
-    Handle<JSArray> object) {
-  HandleScope handle_scope(isolate_);
-  Result stack_push = StackPush(object);
-  if (stack_push != SUCCESS) return stack_push;
-  uint32_t length = 0;
-  CHECK(object->length()->ToArrayLength(&length));
-  builder_.AppendCharacter('[');
-  switch (object->GetElementsKind()) {
-    case FAST_SMI_ELEMENTS: {
-      Handle<FixedArray> elements(FixedArray::cast(object->elements()),
-                                  isolate_);
-      for (uint32_t i = 0; i < length; i++) {
-        if (i > 0) builder_.AppendCharacter(',');
-        SerializeSmi(Smi::cast(elements->get(i)));
-      }
-      break;
-    }
-    case FAST_DOUBLE_ELEMENTS: {
-      // Empty array is FixedArray but not FixedDoubleArray.
-      if (length == 0) break;
-      Handle<FixedDoubleArray> elements(
-          FixedDoubleArray::cast(object->elements()), isolate_);
-      for (uint32_t i = 0; i < length; i++) {
-        if (i > 0) builder_.AppendCharacter(',');
-        SerializeDouble(elements->get_scalar(i));
-      }
-      break;
-    }
-    case FAST_ELEMENTS: {
-      Handle<Object> old_length(object->length(), isolate_);
-      for (uint32_t i = 0; i < length; i++) {
-        if (object->length() != *old_length ||
-            object->GetElementsKind() != FAST_ELEMENTS) {
-          Result result = SerializeJSArraySlow(object, i, length);
-          if (result != SUCCESS) return result;
-          break;
-        }
-        if (i > 0) builder_.AppendCharacter(',');
-        Result result = SerializeElement(
-            isolate_,
-            Handle<Object>(FixedArray::cast(object->elements())->get(i),
-                           isolate_),
-            i);
-        if (result == SUCCESS) continue;
-        if (result == UNCHANGED) {
-          builder_.AppendCString("null");
-        } else {
-          return result;
-        }
-      }
-      break;
-    }
-    // The FAST_HOLEY_* cases could be handled in a faster way. They resemble
-    // the non-holey cases except that a lookup is necessary for holes.
-    default: {
-      Result result = SerializeJSArraySlow(object, 0, length);
-      if (result != SUCCESS) return result;
-      break;
-    }
-  }
-  builder_.AppendCharacter(']');
-  StackPop();
-  return SUCCESS;
-}
-
-
-BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow(
-    Handle<JSArray> object, uint32_t start, uint32_t length) {
-  for (uint32_t i = start; i < length; i++) {
-    if (i > 0) builder_.AppendCharacter(',');
-    Handle<Object> element;
-    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-        isolate_, element, JSReceiver::GetElement(isolate_, object, i),
-        EXCEPTION);
-    if (element->IsUndefined()) {
-      builder_.AppendCString("null");
-    } else {
-      Result result = SerializeElement(isolate_, element, i);
-      if (result == SUCCESS) continue;
-      if (result == UNCHANGED) {
-        builder_.AppendCString("null");
-      } else {
-        return result;
-      }
-    }
-  }
-  return SUCCESS;
-}
-
-
-BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject(
-    Handle<JSObject> object) {
-  HandleScope handle_scope(isolate_);
-  Result stack_push = StackPush(object);
-  if (stack_push != SUCCESS) return stack_push;
-  DCHECK(!object->IsJSGlobalProxy() && !object->IsJSGlobalObject());
-
-  builder_.AppendCharacter('{');
-  bool comma = false;
-
-  if (object->HasFastProperties() &&
-      !object->HasIndexedInterceptor() &&
-      !object->HasNamedInterceptor() &&
-      object->elements()->length() == 0) {
-    Handle<Map> map(object->map());
-    for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
-      Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_);
-      // TODO(rossberg): Should this throw?
-      if (!name->IsString()) continue;
-      Handle<String> key = Handle<String>::cast(name);
-      PropertyDetails details = map->instance_descriptors()->GetDetails(i);
-      if (details.IsDontEnum()) continue;
-      Handle<Object> property;
-      if (details.type() == DATA && *map == object->map()) {
-        FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
-        Isolate* isolate = object->GetIsolate();
-        if (object->IsUnboxedDoubleField(field_index)) {
-          double value = object->RawFastDoublePropertyAt(field_index);
-          property = isolate->factory()->NewHeapNumber(value);
-
-        } else {
-          property = handle(object->RawFastPropertyAt(field_index), isolate);
-        }
-      } else {
-        ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-            isolate_, property,
-            Object::GetPropertyOrElement(object, key),
-            EXCEPTION);
-      }
-      Result result = SerializeProperty(property, comma, key);
-      if (!comma && result == SUCCESS) comma = true;
-      if (result == EXCEPTION) return result;
-    }
-  } else {
-    Handle<FixedArray> contents;
-    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-        isolate_, contents,
-        JSReceiver::GetKeys(object, OWN_ONLY, ENUMERABLE_STRINGS), EXCEPTION);
-
-    for (int i = 0; i < contents->length(); i++) {
-      Object* key = contents->get(i);
-      Handle<String> key_handle;
-      MaybeHandle<Object> maybe_property;
-      if (key->IsString()) {
-        key_handle = Handle<String>(String::cast(key), isolate_);
-        maybe_property = Object::GetPropertyOrElement(object, key_handle);
-      } else {
-        DCHECK(key->IsNumber());
-        key_handle = factory()->NumberToString(Handle<Object>(key, isolate_));
-        if (key->IsSmi()) {
-          maybe_property =
-              JSReceiver::GetElement(isolate_, object, Smi::cast(key)->value());
-        } else {
-          maybe_property = Object::GetPropertyOrElement(object, key_handle);
-        }
-      }
-      Handle<Object> property;
-      ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-          isolate_, property, maybe_property, EXCEPTION);
-      Result result = SerializeProperty(property, comma, key_handle);
-      if (!comma && result == SUCCESS) comma = true;
-      if (result == EXCEPTION) return result;
-    }
-  }
-
-  builder_.AppendCharacter('}');
-  StackPop();
-  return SUCCESS;
-}
-
-
-template <typename SrcChar, typename DestChar>
-void BasicJsonStringifier::SerializeStringUnchecked_(
-    Vector<const SrcChar> src,
-    IncrementalStringBuilder::NoExtend<DestChar>* dest) {
-  // Assert that uc16 character is not truncated down to 8 bit.
-  // The <uc16, char> version of this method must not be called.
-  DCHECK(sizeof(DestChar) >= sizeof(SrcChar));
-
-  for (int i = 0; i < src.length(); i++) {
-    SrcChar c = src[i];
-    if (DoNotEscape(c)) {
-      dest->Append(c);
-    } else {
-      dest->AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
-    }
-  }
-}
-
-
-template <typename SrcChar, typename DestChar>
-void BasicJsonStringifier::SerializeString_(Handle<String> string) {
-  int length = string->length();
-  builder_.Append<uint8_t, DestChar>('"');
-  // We make a rough estimate to find out if the current string can be
-  // serialized without allocating a new string part. The worst case length of
-  // an escaped character is 6.  Shifting the remainin string length right by 3
-  // is a more pessimistic estimate, but faster to calculate.
-  int worst_case_length = length << 3;
-  if (builder_.CurrentPartCanFit(worst_case_length)) {
-    DisallowHeapAllocation no_gc;
-    Vector<const SrcChar> vector = string->GetCharVector<SrcChar>();
-    IncrementalStringBuilder::NoExtendBuilder<DestChar> no_extend(
-        &builder_, worst_case_length);
-    SerializeStringUnchecked_(vector, &no_extend);
-  } else {
-    FlatStringReader reader(isolate_, string);
-    for (int i = 0; i < reader.length(); i++) {
-      SrcChar c = reader.Get<SrcChar>(i);
-      if (DoNotEscape(c)) {
-        builder_.Append<SrcChar, DestChar>(c);
-      } else {
-        builder_.AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
-      }
-    }
-  }
-
-  builder_.Append<uint8_t, DestChar>('"');
-}
-
-
-template <>
-bool BasicJsonStringifier::DoNotEscape(uint8_t c) {
-  return c >= '#' && c <= '~' && c != '\\';
-}
-
-
-template <>
-bool BasicJsonStringifier::DoNotEscape(uint16_t c) {
-  return c >= '#' && c != '\\' && c != 0x7f;
-}
-
-
-void BasicJsonStringifier::SerializeString(Handle<String> object) {
-  object = String::Flatten(object);
-  if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) {
-    if (object->IsOneByteRepresentationUnderneath()) {
-      SerializeString_<uint8_t, uint8_t>(object);
-    } else {
-      builder_.ChangeEncoding();
-      SerializeString(object);
-    }
-  } else {
-    if (object->IsOneByteRepresentationUnderneath()) {
-      SerializeString_<uint8_t, uc16>(object);
-    } else {
-      SerializeString_<uc16, uc16>(object);
-    }
-  }
-}
-
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/keys.cc b/src/keys.cc
index f8b606c..75eb162 100644
--- a/src/keys.cc
+++ b/src/keys.cc
@@ -4,8 +4,10 @@
 
 #include "src/keys.h"
 
+#include "src/api-arguments.h"
 #include "src/elements.h"
 #include "src/factory.h"
+#include "src/identity-map.h"
 #include "src/isolate-inl.h"
 #include "src/objects-inl.h"
 #include "src/property-descriptor.h"
@@ -15,187 +17,72 @@
 namespace internal {
 
 KeyAccumulator::~KeyAccumulator() {
-  for (size_t i = 0; i < elements_.size(); i++) {
-    delete elements_[i];
-  }
-}
-
-Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) {
-  if (length_ == 0) {
-    return isolate_->factory()->empty_fixed_array();
-  }
-  // Make sure we have all the lengths collected.
-  NextPrototype();
-
-  if (type_ == OWN_ONLY && !ownProxyKeys_.is_null()) {
-    return ownProxyKeys_;
-  }
-  // Assemble the result array by first adding the element keys and then the
-  // property keys. We use the total number of String + Symbol keys per level in
-  // |level_lengths_| and the available element keys in the corresponding bucket
-  // in |elements_| to deduce the number of keys to take from the
-  // |string_properties_| and |symbol_properties_| set.
-  Handle<FixedArray> result = isolate_->factory()->NewFixedArray(length_);
-  int insertion_index = 0;
-  int string_properties_index = 0;
-  int symbol_properties_index = 0;
-  // String and Symbol lengths always come in pairs:
-  size_t max_level = level_lengths_.size() / 2;
-  for (size_t level = 0; level < max_level; level++) {
-    int num_string_properties = level_lengths_[level * 2];
-    int num_symbol_properties = level_lengths_[level * 2 + 1];
-    int num_elements = 0;
-    if (num_string_properties < 0) {
-      // If the |num_string_properties| is negative, the current level contains
-      // properties from a proxy, hence we skip the integer keys in |elements_|
-      // since proxies define the complete ordering.
-      num_string_properties = -num_string_properties;
-    } else if (level < elements_.size()) {
-      // Add the element indices for this prototype level.
-      std::vector<uint32_t>* elements = elements_[level];
-      num_elements = static_cast<int>(elements->size());
-      for (int i = 0; i < num_elements; i++) {
-        Handle<Object> key;
-        if (convert == KEEP_NUMBERS) {
-          key = isolate_->factory()->NewNumberFromUint(elements->at(i));
-        } else {
-          key = isolate_->factory()->Uint32ToString(elements->at(i));
-        }
-        result->set(insertion_index, *key);
-        insertion_index++;
-      }
-    }
-    // Add the string property keys for this prototype level.
-    for (int i = 0; i < num_string_properties; i++) {
-      Object* key = string_properties_->KeyAt(string_properties_index);
-      result->set(insertion_index, key);
-      insertion_index++;
-      string_properties_index++;
-    }
-    // Add the symbol property keys for this prototype level.
-    for (int i = 0; i < num_symbol_properties; i++) {
-      Object* key = symbol_properties_->KeyAt(symbol_properties_index);
-      result->set(insertion_index, key);
-      insertion_index++;
-      symbol_properties_index++;
-    }
-    if (FLAG_trace_for_in_enumerate) {
-      PrintF("| strings=%d symbols=%d elements=%i ", num_string_properties,
-             num_symbol_properties, num_elements);
-    }
-  }
-  if (FLAG_trace_for_in_enumerate) {
-    PrintF("|| prototypes=%zu ||\n", max_level);
-  }
-
-  DCHECK_EQ(insertion_index, length_);
-  return result;
 }
 
 namespace {
 
-bool AccumulatorHasKey(std::vector<uint32_t>* sub_elements, uint32_t key) {
-  return std::binary_search(sub_elements->begin(), sub_elements->end(), key);
-}
-
-}  // namespace
-
-bool KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) {
-  return AddKey(handle(key, isolate_), convert);
-}
-
-bool KeyAccumulator::AddKey(Handle<Object> key, AddKeyConversion convert) {
-  if (key->IsSymbol()) {
-    if (filter_ & SKIP_SYMBOLS) return false;
-    if (Handle<Symbol>::cast(key)->is_private()) return false;
-    return AddSymbolKey(key);
+static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
+  int len = array->length();
+  for (int i = 0; i < len; i++) {
+    Object* e = array->get(i);
+    if (!(e->IsName() || e->IsNumber())) return false;
   }
-  if (filter_ & SKIP_STRINGS) return false;
-  // Make sure we do not add keys to a proxy-level (see AddKeysFromProxy).
-  DCHECK_LE(0, level_string_length_);
-  // In some cases (e.g. proxies) we might get in String-converted ints which
-  // should be added to the elements list instead of the properties. For
-  // proxies we have to convert as well but also respect the original order.
-  // Therefore we add a converted key to both sides
-  if (convert == CONVERT_TO_ARRAY_INDEX || convert == PROXY_MAGIC) {
-    uint32_t index = 0;
-    int prev_length = length_;
-    int prev_proto = level_string_length_;
-    if ((key->IsString() && Handle<String>::cast(key)->AsArrayIndex(&index)) ||
-        key->ToArrayIndex(&index)) {
-      bool key_was_added = AddIntegerKey(index);
-      if (convert == CONVERT_TO_ARRAY_INDEX) return key_was_added;
-      if (convert == PROXY_MAGIC) {
-        // If we had an array index (number) and it wasn't added, the key
-        // already existed before, hence we cannot add it to the properties
-        // keys as it would lead to duplicate entries.
-        if (!key_was_added) {
-          return false;
-        }
-        length_ = prev_length;
-        level_string_length_ = prev_proto;
-      }
-    }
-  }
-  return AddStringKey(key, convert);
-}
-
-bool KeyAccumulator::AddKey(uint32_t key) { return AddIntegerKey(key); }
-
-bool KeyAccumulator::AddIntegerKey(uint32_t key) {
-  // Make sure we do not add keys to a proxy-level (see AddKeysFromProxy).
-  // We mark proxy-levels with a negative length
-  DCHECK_LE(0, level_string_length_);
-  // Binary search over all but the last level. The last one might not be
-  // sorted yet.
-  for (size_t i = 1; i < elements_.size(); i++) {
-    if (AccumulatorHasKey(elements_[i - 1], key)) return false;
-  }
-  elements_.back()->push_back(key);
-  length_++;
   return true;
 }
 
-bool KeyAccumulator::AddStringKey(Handle<Object> key,
-                                  AddKeyConversion convert) {
-  if (string_properties_.is_null()) {
-    string_properties_ = OrderedHashSet::Allocate(isolate_, 16);
-  }
-  // TODO(cbruni): remove this conversion once we throw the correct TypeError
-  // for non-string/symbol elements returned by proxies
-  if (convert == PROXY_MAGIC && key->IsNumber()) {
-    key = isolate_->factory()->NumberToString(key);
-  }
-  int prev_size = string_properties_->NumberOfElements();
-  string_properties_ = OrderedHashSet::Add(string_properties_, key);
-  if (prev_size < string_properties_->NumberOfElements()) {
-    length_++;
-    level_string_length_++;
-    return true;
-  } else {
-    return false;
-  }
+}  // namespace
+MaybeHandle<FixedArray> KeyAccumulator::GetKeys(
+    Handle<JSReceiver> object, KeyCollectionMode mode, PropertyFilter filter,
+    GetKeysConversion keys_conversion, bool filter_proxy_keys, bool is_for_in) {
+  Isolate* isolate = object->GetIsolate();
+  KeyAccumulator accumulator(isolate, mode, filter);
+  accumulator.set_filter_proxy_keys(filter_proxy_keys);
+  accumulator.set_is_for_in(is_for_in);
+  MAYBE_RETURN(accumulator.CollectKeys(object, object),
+               MaybeHandle<FixedArray>());
+  return accumulator.GetKeys(keys_conversion);
 }
 
-bool KeyAccumulator::AddSymbolKey(Handle<Object> key) {
-  if (symbol_properties_.is_null()) {
-    symbol_properties_ = OrderedHashSet::Allocate(isolate_, 16);
+Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) {
+  if (keys_.is_null()) {
+    return isolate_->factory()->empty_fixed_array();
   }
-  int prev_size = symbol_properties_->NumberOfElements();
-  symbol_properties_ = OrderedHashSet::Add(symbol_properties_, key);
-  if (prev_size < symbol_properties_->NumberOfElements()) {
-    length_++;
-    level_symbol_length_++;
-    return true;
-  } else {
-    return false;
+  if (mode_ == KeyCollectionMode::kOwnOnly &&
+      keys_->map() == isolate_->heap()->fixed_array_map()) {
+    return Handle<FixedArray>::cast(keys_);
   }
+  USE(ContainsOnlyValidKeys);
+  Handle<FixedArray> result =
+      OrderedHashSet::ConvertToKeysArray(keys(), convert);
+  DCHECK(ContainsOnlyValidKeys(result));
+  return result;
+}
+
+void KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) {
+  AddKey(handle(key, isolate_), convert);
+}
+
+void KeyAccumulator::AddKey(Handle<Object> key, AddKeyConversion convert) {
+  if (key->IsSymbol()) {
+    if (filter_ & SKIP_SYMBOLS) return;
+    if (Handle<Symbol>::cast(key)->is_private()) return;
+  } else if (filter_ & SKIP_STRINGS) {
+    return;
+  }
+  if (keys_.is_null()) {
+    keys_ = OrderedHashSet::Allocate(isolate_, 16);
+  }
+  uint32_t index;
+  if (convert == CONVERT_TO_ARRAY_INDEX && key->IsString() &&
+      Handle<String>::cast(key)->AsArrayIndex(&index)) {
+    key = isolate_->factory()->NewNumberFromUint(index);
+  }
+  keys_ = OrderedHashSet::Add(keys(), key);
 }
 
 void KeyAccumulator::AddKeys(Handle<FixedArray> array,
                              AddKeyConversion convert) {
   int add_length = array->length();
-  if (add_length == 0) return;
   for (int i = 0; i < add_length; i++) {
     Handle<Object> current(array->get(i), isolate_);
     AddKey(current, convert);
@@ -209,17 +96,6 @@
   accessor->AddElementsToKeyAccumulator(array_like, this, convert);
 }
 
-void KeyAccumulator::AddKeysFromProxy(Handle<JSObject> array_like) {
-  // Proxies define a complete list of keys with no distinction of
-  // elements and properties, which breaks the normal assumption for the
-  // KeyAccumulator.
-  AddKeys(array_like, PROXY_MAGIC);
-  // Invert the current length to indicate a present proxy, so we can ignore
-  // element keys for this level. Otherwise we would not fully respect the order
-  // given by the proxy.
-  level_string_length_ = -level_string_length_;
-}
-
 MaybeHandle<FixedArray> FilterProxyKeys(Isolate* isolate, Handle<JSProxy> owner,
                                         Handle<FixedArray> keys,
                                         PropertyFilter filter) {
@@ -250,66 +126,61 @@
 }
 
 // Returns "nothing" in case of exception, "true" on success.
-Maybe<bool> KeyAccumulator::AddKeysFromProxy(Handle<JSProxy> proxy,
-                                             Handle<FixedArray> keys) {
+Maybe<bool> KeyAccumulator::AddKeysFromJSProxy(Handle<JSProxy> proxy,
+                                               Handle<FixedArray> keys) {
   if (filter_proxy_keys_) {
+    DCHECK(!is_for_in_);
     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
         isolate_, keys, FilterProxyKeys(isolate_, proxy, keys, filter_),
         Nothing<bool>());
   }
-  // Proxies define a complete list of keys with no distinction of
-  // elements and properties, which breaks the normal assumption for the
-  // KeyAccumulator.
-  if (type_ == OWN_ONLY) {
-    ownProxyKeys_ = keys;
-    level_string_length_ = keys->length();
-    length_ = level_string_length_;
-  } else {
-    AddKeys(keys, PROXY_MAGIC);
+  if (mode_ == KeyCollectionMode::kOwnOnly && !is_for_in_) {
+    // If we collect only the keys from a JSProxy do not sort or deduplicate it.
+    keys_ = keys;
+    return Just(true);
   }
-  // Invert the current length to indicate a present proxy, so we can ignore
-  // element keys for this level. Otherwise we would not fully respect the order
-  // given by the proxy.
-  level_string_length_ = -level_string_length_;
+  AddKeys(keys, is_for_in_ ? CONVERT_TO_ARRAY_INDEX : DO_NOT_CONVERT);
   return Just(true);
 }
 
-void KeyAccumulator::AddElementKeysFromInterceptor(
-    Handle<JSObject> array_like) {
-  AddKeys(array_like, CONVERT_TO_ARRAY_INDEX);
-  // The interceptor might introduce duplicates for the current level, since
-  // these keys get added after the objects's normal element keys.
-  SortCurrentElementsListRemoveDuplicates();
-}
-
-void KeyAccumulator::SortCurrentElementsListRemoveDuplicates() {
-  // Sort and remove duplicates from the current elements level and adjust.
-  // the lengths accordingly.
-  auto last_level = elements_.back();
-  size_t nof_removed_keys = last_level->size();
-  std::sort(last_level->begin(), last_level->end());
-  last_level->erase(std::unique(last_level->begin(), last_level->end()),
-                    last_level->end());
-  // Adjust total length by the number of removed duplicates.
-  nof_removed_keys -= last_level->size();
-  length_ -= static_cast<int>(nof_removed_keys);
-}
-
-void KeyAccumulator::SortCurrentElementsList() {
-  if (elements_.empty()) return;
-  auto element_keys = elements_.back();
-  std::sort(element_keys->begin(), element_keys->end());
-}
-
-void KeyAccumulator::NextPrototype() {
-  // Store the protoLength on the first call of this method.
-  if (!elements_.empty()) {
-    level_lengths_.push_back(level_string_length_);
-    level_lengths_.push_back(level_symbol_length_);
+Maybe<bool> KeyAccumulator::CollectKeys(Handle<JSReceiver> receiver,
+                                        Handle<JSReceiver> object) {
+  // Proxies have no hidden prototype and we should not trigger the
+  // [[GetPrototypeOf]] trap on the last iteration when using
+  // AdvanceFollowingProxies.
+  if (mode_ == KeyCollectionMode::kOwnOnly && object->IsJSProxy()) {
+    MAYBE_RETURN(CollectOwnJSProxyKeys(receiver, Handle<JSProxy>::cast(object)),
+                 Nothing<bool>());
+    return Just(true);
   }
-  elements_.push_back(new std::vector<uint32_t>());
-  level_string_length_ = 0;
-  level_symbol_length_ = 0;
+
+  PrototypeIterator::WhereToEnd end = mode_ == KeyCollectionMode::kOwnOnly
+                                          ? PrototypeIterator::END_AT_NON_HIDDEN
+                                          : PrototypeIterator::END_AT_NULL;
+  for (PrototypeIterator iter(isolate_, object, kStartAtReceiver, end);
+       !iter.IsAtEnd();) {
+    Handle<JSReceiver> current =
+        PrototypeIterator::GetCurrent<JSReceiver>(iter);
+    Maybe<bool> result = Just(false);  // Dummy initialization.
+    if (current->IsJSProxy()) {
+      result = CollectOwnJSProxyKeys(receiver, Handle<JSProxy>::cast(current));
+    } else {
+      DCHECK(current->IsJSObject());
+      result = CollectOwnKeys(receiver, Handle<JSObject>::cast(current));
+    }
+    MAYBE_RETURN(result, Nothing<bool>());
+    if (!result.FromJust()) break;  // |false| means "stop iterating".
+    // Iterate through proxies but ignore access checks for the ALL_CAN_READ
+    // case on API objects for OWN_ONLY keys handled in CollectOwnKeys.
+    if (!iter.AdvanceFollowingProxiesIgnoringAccessChecks()) {
+      return Nothing<bool>();
+    }
+    if (!last_non_empty_prototype_.is_null() &&
+        *last_non_empty_prototype_ == *current) {
+      break;
+    }
+  }
+  return Just(true);
 }
 
 namespace {
@@ -341,28 +212,112 @@
 void FastKeyAccumulator::Prepare() {
   DisallowHeapAllocation no_gc;
   // Directly go for the fast path for OWN_ONLY keys.
-  if (type_ == OWN_ONLY) return;
+  if (mode_ == KeyCollectionMode::kOwnOnly) return;
   // Fully walk the prototype chain and find the last prototype with keys.
   is_receiver_simple_enum_ = false;
   has_empty_prototype_ = true;
-  JSReceiver* first_non_empty_prototype;
+  JSReceiver* last_prototype = nullptr;
   for (PrototypeIterator iter(isolate_, *receiver_); !iter.IsAtEnd();
        iter.Advance()) {
     JSReceiver* current = iter.GetCurrent<JSReceiver>();
-    if (CheckAndInitalizeSimpleEnumCache(current)) continue;
+    bool has_no_properties = CheckAndInitalizeSimpleEnumCache(current);
+    if (has_no_properties) continue;
+    last_prototype = current;
     has_empty_prototype_ = false;
-    first_non_empty_prototype = current;
-    // TODO(cbruni): use the first non-empty prototype.
-    USE(first_non_empty_prototype);
-    return;
   }
-  DCHECK(has_empty_prototype_);
-  is_receiver_simple_enum_ =
-      receiver_->map()->EnumLength() != kInvalidEnumCacheSentinel &&
-      !JSObject::cast(*receiver_)->HasEnumerableElements();
+  if (has_empty_prototype_) {
+    is_receiver_simple_enum_ =
+        receiver_->map()->EnumLength() != kInvalidEnumCacheSentinel &&
+        !JSObject::cast(*receiver_)->HasEnumerableElements();
+  } else if (last_prototype != nullptr) {
+    last_non_empty_prototype_ = handle(last_prototype, isolate_);
+  }
 }
 
 namespace {
+static Handle<FixedArray> ReduceFixedArrayTo(Isolate* isolate,
+                                             Handle<FixedArray> array,
+                                             int length) {
+  DCHECK_LE(length, array->length());
+  if (array->length() == length) return array;
+  return isolate->factory()->CopyFixedArrayUpTo(array, length);
+}
+
+Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate,
+                                           Handle<JSObject> object) {
+  Handle<Map> map(object->map());
+  bool cache_enum_length = map->OnlyHasSimpleProperties();
+
+  Handle<DescriptorArray> descs =
+      Handle<DescriptorArray>(map->instance_descriptors(), isolate);
+  int own_property_count = map->EnumLength();
+  // If the enum length of the given map is set to kInvalidEnumCache, this
+  // means that the map itself has never used the present enum cache. The
+  // first step to using the cache is to set the enum length of the map by
+  // counting the number of own descriptors that are ENUMERABLE_STRINGS.
+  if (own_property_count == kInvalidEnumCacheSentinel) {
+    own_property_count =
+        map->NumberOfDescribedProperties(OWN_DESCRIPTORS, ENUMERABLE_STRINGS);
+  } else {
+    DCHECK(
+        own_property_count ==
+        map->NumberOfDescribedProperties(OWN_DESCRIPTORS, ENUMERABLE_STRINGS));
+  }
+
+  if (descs->HasEnumCache()) {
+    Handle<FixedArray> keys(descs->GetEnumCache(), isolate);
+    // In case the number of properties required in the enum are actually
+    // present, we can reuse the enum cache. Otherwise, this means that the
+    // enum cache was generated for a previous (smaller) version of the
+    // Descriptor Array. In that case we regenerate the enum cache.
+    if (own_property_count <= keys->length()) {
+      isolate->counters()->enum_cache_hits()->Increment();
+      if (cache_enum_length) map->SetEnumLength(own_property_count);
+      return ReduceFixedArrayTo(isolate, keys, own_property_count);
+    }
+  }
+
+  if (descs->IsEmpty()) {
+    isolate->counters()->enum_cache_hits()->Increment();
+    if (cache_enum_length) map->SetEnumLength(0);
+    return isolate->factory()->empty_fixed_array();
+  }
+
+  isolate->counters()->enum_cache_misses()->Increment();
+
+  Handle<FixedArray> storage =
+      isolate->factory()->NewFixedArray(own_property_count);
+  Handle<FixedArray> indices =
+      isolate->factory()->NewFixedArray(own_property_count);
+
+  int size = map->NumberOfOwnDescriptors();
+  int index = 0;
+
+  for (int i = 0; i < size; i++) {
+    PropertyDetails details = descs->GetDetails(i);
+    if (details.IsDontEnum()) continue;
+    Object* key = descs->GetKey(i);
+    if (key->IsSymbol()) continue;
+    storage->set(index, key);
+    if (!indices.is_null()) {
+      if (details.type() != DATA) {
+        indices = Handle<FixedArray>();
+      } else {
+        FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
+        int load_by_field_index = field_index.GetLoadByFieldIndex();
+        indices->set(index, Smi::FromInt(load_by_field_index));
+      }
+    }
+    index++;
+  }
+  DCHECK(index == storage->length());
+
+  DescriptorArray::SetEnumCache(descs, isolate, storage, indices);
+  if (cache_enum_length) {
+    map->SetEnumLength(own_property_count);
+  }
+  return storage;
+}
 
 template <bool fast_properties>
 Handle<FixedArray> GetOwnKeysWithElements(Isolate* isolate,
@@ -371,10 +326,10 @@
   Handle<FixedArray> keys;
   ElementsAccessor* accessor = object->GetElementsAccessor();
   if (fast_properties) {
-    keys = JSObject::GetFastEnumPropertyKeys(isolate, object);
+    keys = GetFastEnumPropertyKeys(isolate, object);
   } else {
     // TODO(cbruni): preallocate big enough array to also hold elements.
-    keys = JSObject::GetEnumPropertyKeys(object);
+    keys = KeyAccumulator::GetEnumPropertyKeys(isolate, object);
   }
   Handle<FixedArray> result =
       accessor->PrependElementIndices(object, keys, convert, ONLY_ENUMERABLE);
@@ -402,7 +357,7 @@
   }
   // We have no elements but possibly enumerable property keys, hence we can
   // directly initialize the enum cache.
-  return JSObject::GetFastEnumPropertyKeys(isolate, object);
+  return GetFastEnumPropertyKeys(isolate, object);
 }
 
 bool OnlyHasSimpleProperties(Map* map) {
@@ -411,17 +366,19 @@
 
 }  // namespace
 
-MaybeHandle<FixedArray> FastKeyAccumulator::GetKeys(GetKeysConversion convert) {
+MaybeHandle<FixedArray> FastKeyAccumulator::GetKeys(
+    GetKeysConversion keys_conversion) {
   Handle<FixedArray> keys;
-  if (GetKeysFast(convert).ToHandle(&keys)) {
+  if (filter_ == ENUMERABLE_STRINGS &&
+      GetKeysFast(keys_conversion).ToHandle(&keys)) {
     return keys;
   }
-  return GetKeysSlow(convert);
+  return GetKeysSlow(keys_conversion);
 }
 
 MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysFast(
-    GetKeysConversion convert) {
-  bool own_only = has_empty_prototype_ || type_ == OWN_ONLY;
+    GetKeysConversion keys_conversion) {
+  bool own_only = has_empty_prototype_ || mode_ == KeyCollectionMode::kOwnOnly;
   Map* map = receiver_->map();
   if (!own_only || !OnlyHasSimpleProperties(map)) {
     return MaybeHandle<FixedArray>();
@@ -433,7 +390,7 @@
 
   // Do not try to use the enum-cache for dict-mode objects.
   if (map->is_dictionary_map()) {
-    return GetOwnKeysWithElements<false>(isolate_, object, convert);
+    return GetOwnKeysWithElements<false>(isolate_, object, keys_conversion);
   }
   int enum_length = receiver_->map()->EnumLength();
   if (enum_length == kInvalidEnumCacheSentinel) {
@@ -452,13 +409,392 @@
   }
   // The properties-only case failed because there were probably elements on the
   // receiver.
-  return GetOwnKeysWithElements<true>(isolate_, object, convert);
+  return GetOwnKeysWithElements<true>(isolate_, object, keys_conversion);
 }
 
 MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysSlow(
-    GetKeysConversion convert) {
-  return JSReceiver::GetKeys(receiver_, type_, ENUMERABLE_STRINGS, KEEP_NUMBERS,
-                             filter_proxy_keys_);
+    GetKeysConversion keys_conversion) {
+  KeyAccumulator accumulator(isolate_, mode_, filter_);
+  accumulator.set_filter_proxy_keys(filter_proxy_keys_);
+  accumulator.set_is_for_in(is_for_in_);
+  accumulator.set_last_non_empty_prototype(last_non_empty_prototype_);
+
+  MAYBE_RETURN(accumulator.CollectKeys(receiver_, receiver_),
+               MaybeHandle<FixedArray>());
+  return accumulator.GetKeys(keys_conversion);
+}
+
+namespace {
+
+enum IndexedOrNamed { kIndexed, kNamed };
+
+// Returns |true| on success, |nothing| on exception.
+template <class Callback, IndexedOrNamed type>
+Maybe<bool> CollectInterceptorKeysInternal(Handle<JSReceiver> receiver,
+                                           Handle<JSObject> object,
+                                           Handle<InterceptorInfo> interceptor,
+                                           KeyAccumulator* accumulator) {
+  Isolate* isolate = accumulator->isolate();
+  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
+                                 *object, Object::DONT_THROW);
+  Handle<JSObject> result;
+  if (!interceptor->enumerator()->IsUndefined(isolate)) {
+    Callback enum_fun = v8::ToCData<Callback>(interceptor->enumerator());
+    const char* log_tag = type == kIndexed ? "interceptor-indexed-enum"
+                                           : "interceptor-named-enum";
+    LOG(isolate, ApiObjectAccess(log_tag, *object));
+    result = args.Call(enum_fun);
+  }
+  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
+  if (result.is_null()) return Just(true);
+  accumulator->AddKeys(
+      result, type == kIndexed ? CONVERT_TO_ARRAY_INDEX : DO_NOT_CONVERT);
+  return Just(true);
+}
+
+template <class Callback, IndexedOrNamed type>
+Maybe<bool> CollectInterceptorKeys(Handle<JSReceiver> receiver,
+                                   Handle<JSObject> object,
+                                   KeyAccumulator* accumulator) {
+  Isolate* isolate = accumulator->isolate();
+  if (type == kIndexed) {
+    if (!object->HasIndexedInterceptor()) return Just(true);
+  } else {
+    if (!object->HasNamedInterceptor()) return Just(true);
+  }
+  Handle<InterceptorInfo> interceptor(type == kIndexed
+                                          ? object->GetIndexedInterceptor()
+                                          : object->GetNamedInterceptor(),
+                                      isolate);
+  if ((accumulator->filter() & ONLY_ALL_CAN_READ) &&
+      !interceptor->all_can_read()) {
+    return Just(true);
+  }
+  return CollectInterceptorKeysInternal<Callback, type>(
+      receiver, object, interceptor, accumulator);
+}
+
+}  // namespace
+
+Maybe<bool> KeyAccumulator::CollectOwnElementIndices(
+    Handle<JSReceiver> receiver, Handle<JSObject> object) {
+  if (filter_ & SKIP_STRINGS || skip_indices_) return Just(true);
+
+  ElementsAccessor* accessor = object->GetElementsAccessor();
+  accessor->CollectElementIndices(object, this);
+
+  return CollectInterceptorKeys<v8::IndexedPropertyEnumeratorCallback,
+                                kIndexed>(receiver, object, this);
+}
+
+namespace {
+
+template <bool skip_symbols>
+int CollectOwnPropertyNamesInternal(Handle<JSObject> object,
+                                    KeyAccumulator* keys,
+                                    Handle<DescriptorArray> descs,
+                                    int start_index, int limit) {
+  int first_skipped = -1;
+  for (int i = start_index; i < limit; i++) {
+    PropertyDetails details = descs->GetDetails(i);
+    if ((details.attributes() & keys->filter()) != 0) continue;
+    if (keys->filter() & ONLY_ALL_CAN_READ) {
+      if (details.kind() != kAccessor) continue;
+      Object* accessors = descs->GetValue(i);
+      if (!accessors->IsAccessorInfo()) continue;
+      if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
+    }
+    Name* key = descs->GetKey(i);
+    if (skip_symbols == key->IsSymbol()) {
+      if (first_skipped == -1) first_skipped = i;
+      continue;
+    }
+    if (key->FilterKey(keys->filter())) continue;
+    keys->AddKey(key, DO_NOT_CONVERT);
+  }
+  return first_skipped;
+}
+
+}  // namespace
+
+Maybe<bool> KeyAccumulator::CollectOwnPropertyNames(Handle<JSReceiver> receiver,
+                                                    Handle<JSObject> object) {
+  if (filter_ == ENUMERABLE_STRINGS) {
+    Handle<FixedArray> enum_keys =
+        KeyAccumulator::GetEnumPropertyKeys(isolate_, object);
+    AddKeys(enum_keys, DO_NOT_CONVERT);
+  } else {
+    if (object->HasFastProperties()) {
+      int limit = object->map()->NumberOfOwnDescriptors();
+      Handle<DescriptorArray> descs(object->map()->instance_descriptors(),
+                                    isolate_);
+      // First collect the strings,
+      int first_symbol =
+          CollectOwnPropertyNamesInternal<true>(object, this, descs, 0, limit);
+      // then the symbols.
+      if (first_symbol != -1) {
+        CollectOwnPropertyNamesInternal<false>(object, this, descs,
+                                               first_symbol, limit);
+      }
+    } else if (object->IsJSGlobalObject()) {
+      GlobalDictionary::CollectKeysTo(
+          handle(object->global_dictionary(), isolate_), this, filter_);
+    } else {
+      NameDictionary::CollectKeysTo(
+          handle(object->property_dictionary(), isolate_), this, filter_);
+    }
+  }
+  // Add the property keys from the interceptor.
+  return CollectInterceptorKeys<v8::GenericNamedPropertyEnumeratorCallback,
+                                kNamed>(receiver, object, this);
+}
+
+Maybe<bool> KeyAccumulator::CollectAccessCheckInterceptorKeys(
+    Handle<AccessCheckInfo> access_check_info, Handle<JSReceiver> receiver,
+    Handle<JSObject> object) {
+  MAYBE_RETURN(
+      (CollectInterceptorKeysInternal<v8::IndexedPropertyEnumeratorCallback,
+                                      kIndexed>(
+          receiver, object,
+          handle(
+              InterceptorInfo::cast(access_check_info->indexed_interceptor()),
+              isolate_),
+          this)),
+      Nothing<bool>());
+  MAYBE_RETURN(
+      (CollectInterceptorKeysInternal<
+          v8::GenericNamedPropertyEnumeratorCallback, kNamed>(
+          receiver, object,
+          handle(InterceptorInfo::cast(access_check_info->named_interceptor()),
+                 isolate_),
+          this)),
+      Nothing<bool>());
+  return Just(true);
+}
+
+// Returns |true| on success, |false| if prototype walking should be stopped,
+// |nothing| if an exception was thrown.
+Maybe<bool> KeyAccumulator::CollectOwnKeys(Handle<JSReceiver> receiver,
+                                           Handle<JSObject> object) {
+  // Check access rights if required.
+  if (object->IsAccessCheckNeeded() &&
+      !isolate_->MayAccess(handle(isolate_->context()), object)) {
+    // The cross-origin spec says that [[Enumerate]] shall return an empty
+    // iterator when it doesn't have access...
+    if (mode_ == KeyCollectionMode::kIncludePrototypes) {
+      return Just(false);
+    }
+    // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties.
+    DCHECK(KeyCollectionMode::kOwnOnly == mode_);
+    Handle<AccessCheckInfo> access_check_info;
+    {
+      DisallowHeapAllocation no_gc;
+      AccessCheckInfo* maybe_info = AccessCheckInfo::Get(isolate_, object);
+      if (maybe_info) access_check_info = handle(maybe_info, isolate_);
+    }
+    // We always have both kinds of interceptors or none.
+    if (!access_check_info.is_null() &&
+        access_check_info->named_interceptor()) {
+      MAYBE_RETURN(CollectAccessCheckInterceptorKeys(access_check_info,
+                                                     receiver, object),
+                   Nothing<bool>());
+      return Just(false);
+    }
+    filter_ = static_cast<PropertyFilter>(filter_ | ONLY_ALL_CAN_READ);
+  }
+  MAYBE_RETURN(CollectOwnElementIndices(receiver, object), Nothing<bool>());
+  MAYBE_RETURN(CollectOwnPropertyNames(receiver, object), Nothing<bool>());
+  return Just(true);
+}
+
+// static
+Handle<FixedArray> KeyAccumulator::GetEnumPropertyKeys(
+    Isolate* isolate, Handle<JSObject> object) {
+  if (object->HasFastProperties()) {
+    return GetFastEnumPropertyKeys(isolate, object);
+  } else if (object->IsJSGlobalObject()) {
+    Handle<GlobalDictionary> dictionary(object->global_dictionary(), isolate);
+    int length = dictionary->NumberOfEnumElements();
+    if (length == 0) {
+      return isolate->factory()->empty_fixed_array();
+    }
+    Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
+    dictionary->CopyEnumKeysTo(*storage);
+    return storage;
+  } else {
+    Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
+    int length = dictionary->NumberOfEnumElements();
+    if (length == 0) {
+      return isolate->factory()->empty_fixed_array();
+    }
+    Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
+    dictionary->CopyEnumKeysTo(*storage);
+    return storage;
+  }
+}
+
+// ES6 9.5.12
+// Returns |true| on success, |nothing| in case of exception.
+Maybe<bool> KeyAccumulator::CollectOwnJSProxyKeys(Handle<JSReceiver> receiver,
+                                                  Handle<JSProxy> proxy) {
+  STACK_CHECK(isolate_, Nothing<bool>());
+  // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
+  Handle<Object> handler(proxy->handler(), isolate_);
+  // 2. If handler is null, throw a TypeError exception.
+  // 3. Assert: Type(handler) is Object.
+  if (proxy->IsRevoked()) {
+    isolate_->Throw(*isolate_->factory()->NewTypeError(
+        MessageTemplate::kProxyRevoked, isolate_->factory()->ownKeys_string()));
+    return Nothing<bool>();
+  }
+  // 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
+  Handle<JSReceiver> target(proxy->target(), isolate_);
+  // 5. Let trap be ? GetMethod(handler, "ownKeys").
+  Handle<Object> trap;
+  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+      isolate_, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler),
+                                        isolate_->factory()->ownKeys_string()),
+      Nothing<bool>());
+  // 6. If trap is undefined, then
+  if (trap->IsUndefined(isolate_)) {
+    // 6a. Return target.[[OwnPropertyKeys]]().
+    return CollectOwnJSProxyTargetKeys(proxy, target);
+  }
+  // 7. Let trapResultArray be Call(trap, handler, «target»).
+  Handle<Object> trap_result_array;
+  Handle<Object> args[] = {target};
+  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+      isolate_, trap_result_array,
+      Execution::Call(isolate_, trap, handler, arraysize(args), args),
+      Nothing<bool>());
+  // 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray,
+  //    «String, Symbol»).
+  Handle<FixedArray> trap_result;
+  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+      isolate_, trap_result,
+      Object::CreateListFromArrayLike(isolate_, trap_result_array,
+                                      ElementTypes::kStringAndSymbol),
+      Nothing<bool>());
+  // 9. Let extensibleTarget be ? IsExtensible(target).
+  Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target);
+  MAYBE_RETURN(maybe_extensible, Nothing<bool>());
+  bool extensible_target = maybe_extensible.FromJust();
+  // 10. Let targetKeys be ? target.[[OwnPropertyKeys]]().
+  Handle<FixedArray> target_keys;
+  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, target_keys,
+                                   JSReceiver::OwnPropertyKeys(target),
+                                   Nothing<bool>());
+  // 11. (Assert)
+  // 12. Let targetConfigurableKeys be an empty List.
+  // To save memory, we're re-using target_keys and will modify it in-place.
+  Handle<FixedArray> target_configurable_keys = target_keys;
+  // 13. Let targetNonconfigurableKeys be an empty List.
+  Handle<FixedArray> target_nonconfigurable_keys =
+      isolate_->factory()->NewFixedArray(target_keys->length());
+  int nonconfigurable_keys_length = 0;
+  // 14. Repeat, for each element key of targetKeys:
+  for (int i = 0; i < target_keys->length(); ++i) {
+    // 14a. Let desc be ? target.[[GetOwnProperty]](key).
+    PropertyDescriptor desc;
+    Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor(
+        isolate_, target, handle(target_keys->get(i), isolate_), &desc);
+    MAYBE_RETURN(found, Nothing<bool>());
+    // 14b. If desc is not undefined and desc.[[Configurable]] is false, then
+    if (found.FromJust() && !desc.configurable()) {
+      // 14b i. Append key as an element of targetNonconfigurableKeys.
+      target_nonconfigurable_keys->set(nonconfigurable_keys_length,
+                                       target_keys->get(i));
+      nonconfigurable_keys_length++;
+      // The key was moved, null it out in the original list.
+      target_keys->set(i, Smi::FromInt(0));
+    } else {
+      // 14c. Else,
+      // 14c i. Append key as an element of targetConfigurableKeys.
+      // (No-op, just keep it in |target_keys|.)
+    }
+  }
+  // 15. If extensibleTarget is true and targetNonconfigurableKeys is empty,
+  //     then:
+  if (extensible_target && nonconfigurable_keys_length == 0) {
+    // 15a. Return trapResult.
+    return AddKeysFromJSProxy(proxy, trap_result);
+  }
+  // 16. Let uncheckedResultKeys be a new List which is a copy of trapResult.
+  Zone set_zone(isolate_->allocator());
+  const int kPresent = 1;
+  const int kGone = 0;
+  IdentityMap<int> unchecked_result_keys(isolate_->heap(), &set_zone);
+  int unchecked_result_keys_size = 0;
+  for (int i = 0; i < trap_result->length(); ++i) {
+    DCHECK(trap_result->get(i)->IsUniqueName());
+    Object* key = trap_result->get(i);
+    int* entry = unchecked_result_keys.Get(key);
+    if (*entry != kPresent) {
+      *entry = kPresent;
+      unchecked_result_keys_size++;
+    }
+  }
+  // 17. Repeat, for each key that is an element of targetNonconfigurableKeys:
+  for (int i = 0; i < nonconfigurable_keys_length; ++i) {
+    Object* key = target_nonconfigurable_keys->get(i);
+    // 17a. If key is not an element of uncheckedResultKeys, throw a
+    //      TypeError exception.
+    int* found = unchecked_result_keys.Find(key);
+    if (found == nullptr || *found == kGone) {
+      isolate_->Throw(*isolate_->factory()->NewTypeError(
+          MessageTemplate::kProxyOwnKeysMissing, handle(key, isolate_)));
+      return Nothing<bool>();
+    }
+    // 17b. Remove key from uncheckedResultKeys.
+    *found = kGone;
+    unchecked_result_keys_size--;
+  }
+  // 18. If extensibleTarget is true, return trapResult.
+  if (extensible_target) {
+    return AddKeysFromJSProxy(proxy, trap_result);
+  }
+  // 19. Repeat, for each key that is an element of targetConfigurableKeys:
+  for (int i = 0; i < target_configurable_keys->length(); ++i) {
+    Object* key = target_configurable_keys->get(i);
+    if (key->IsSmi()) continue;  // Zapped entry, was nonconfigurable.
+    // 19a. If key is not an element of uncheckedResultKeys, throw a
+    //      TypeError exception.
+    int* found = unchecked_result_keys.Find(key);
+    if (found == nullptr || *found == kGone) {
+      isolate_->Throw(*isolate_->factory()->NewTypeError(
+          MessageTemplate::kProxyOwnKeysMissing, handle(key, isolate_)));
+      return Nothing<bool>();
+    }
+    // 19b. Remove key from uncheckedResultKeys.
+    *found = kGone;
+    unchecked_result_keys_size--;
+  }
+  // 20. If uncheckedResultKeys is not empty, throw a TypeError exception.
+  if (unchecked_result_keys_size != 0) {
+    DCHECK_GT(unchecked_result_keys_size, 0);
+    isolate_->Throw(*isolate_->factory()->NewTypeError(
+        MessageTemplate::kProxyOwnKeysNonExtensible));
+    return Nothing<bool>();
+  }
+  // 21. Return trapResult.
+  return AddKeysFromJSProxy(proxy, trap_result);
+}
+
+Maybe<bool> KeyAccumulator::CollectOwnJSProxyTargetKeys(
+    Handle<JSProxy> proxy, Handle<JSReceiver> target) {
+  // TODO(cbruni): avoid creating another KeyAccumulator
+  Handle<FixedArray> keys;
+  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+      isolate_, keys,
+      KeyAccumulator::GetKeys(target, KeyCollectionMode::kOwnOnly, filter_,
+                              GetKeysConversion::kConvertToString,
+                              filter_proxy_keys_, is_for_in_),
+      Nothing<bool>());
+  bool prev_filter_proxy_keys_ = filter_proxy_keys_;
+  filter_proxy_keys_ = false;
+  Maybe<bool> result = AddKeysFromJSProxy(proxy, keys);
+  filter_proxy_keys_ = prev_filter_proxy_keys_;
+  return result;
 }
 
 }  // namespace internal
diff --git a/src/keys.h b/src/keys.h
index 1fd3fc0..502c834 100644
--- a/src/keys.h
+++ b/src/keys.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef V8_KEY_ACCUMULATOR_H_
-#define V8_KEY_ACCUMULATOR_H_
+#ifndef V8_KEYS_H_
+#define V8_KEYS_H_
 
 #include "src/isolate.h"
 #include "src/objects.h"
@@ -11,7 +11,7 @@
 namespace v8 {
 namespace internal {
 
-enum AddKeyConversion { DO_NOT_CONVERT, CONVERT_TO_ARRAY_INDEX, PROXY_MAGIC };
+enum AddKeyConversion { DO_NOT_CONVERT, CONVERT_TO_ARRAY_INDEX };
 
 // This is a helper class for JSReceiver::GetKeys which collects and sorts keys.
 // GetKeys needs to sort keys per prototype level, first showing the integer
@@ -31,59 +31,70 @@
 // are more compact and allow for reasonably fast includes check.
 class KeyAccumulator final BASE_EMBEDDED {
  public:
-  KeyAccumulator(Isolate* isolate, KeyCollectionType type,
+  KeyAccumulator(Isolate* isolate, KeyCollectionMode mode,
                  PropertyFilter filter)
-      : isolate_(isolate), type_(type), filter_(filter) {}
+      : isolate_(isolate), mode_(mode), filter_(filter) {}
   ~KeyAccumulator();
 
-  bool AddKey(uint32_t key);
-  bool AddKey(Object* key, AddKeyConversion convert);
-  bool AddKey(Handle<Object> key, AddKeyConversion convert);
+  static MaybeHandle<FixedArray> GetKeys(
+      Handle<JSReceiver> object, KeyCollectionMode mode, PropertyFilter filter,
+      GetKeysConversion keys_conversion = GetKeysConversion::kKeepNumbers,
+      bool filter_proxy_keys = true, bool is_for_in = false);
+
+  Handle<FixedArray> GetKeys(
+      GetKeysConversion convert = GetKeysConversion::kKeepNumbers);
+  Maybe<bool> CollectKeys(Handle<JSReceiver> receiver,
+                          Handle<JSReceiver> object);
+  Maybe<bool> CollectOwnElementIndices(Handle<JSReceiver> receiver,
+                                       Handle<JSObject> object);
+  Maybe<bool> CollectOwnPropertyNames(Handle<JSReceiver> receiver,
+                                      Handle<JSObject> object);
+  Maybe<bool> CollectAccessCheckInterceptorKeys(
+      Handle<AccessCheckInfo> access_check_info, Handle<JSReceiver> receiver,
+      Handle<JSObject> object);
+
+  static Handle<FixedArray> GetEnumPropertyKeys(Isolate* isolate,
+                                                Handle<JSObject> object);
+
+  void AddKey(Object* key, AddKeyConversion convert = DO_NOT_CONVERT);
+  void AddKey(Handle<Object> key, AddKeyConversion convert = DO_NOT_CONVERT);
   void AddKeys(Handle<FixedArray> array, AddKeyConversion convert);
-  void AddKeys(Handle<JSObject> array, AddKeyConversion convert);
-  void AddKeysFromProxy(Handle<JSObject> array);
-  Maybe<bool> AddKeysFromProxy(Handle<JSProxy> proxy, Handle<FixedArray> keys);
-  void AddElementKeysFromInterceptor(Handle<JSObject> array);
+  void AddKeys(Handle<JSObject> array_like, AddKeyConversion convert);
+
   // Jump to the next level, pushing the current |levelLength_| to
   // |levelLengths_| and adding a new list to |elements_|.
-  void NextPrototype();
-  // Sort the integer indices in the last list in |elements_|
-  void SortCurrentElementsList();
-  Handle<FixedArray> GetKeys(GetKeysConversion convert = KEEP_NUMBERS);
-  int length() { return length_; }
   Isolate* isolate() { return isolate_; }
+  PropertyFilter filter() { return filter_; }
   void set_filter_proxy_keys(bool filter) { filter_proxy_keys_ = filter; }
+  void set_is_for_in(bool value) { is_for_in_ = value; }
+  void set_skip_indices(bool value) { skip_indices_ = value; }
+  void set_last_non_empty_prototype(Handle<JSReceiver> object) {
+    last_non_empty_prototype_ = object;
+  }
 
  private:
-  bool AddIntegerKey(uint32_t key);
-  bool AddStringKey(Handle<Object> key, AddKeyConversion convert);
-  bool AddSymbolKey(Handle<Object> array);
-  void SortCurrentElementsListRemoveDuplicates();
+  Maybe<bool> CollectOwnKeys(Handle<JSReceiver> receiver,
+                             Handle<JSObject> object);
+  Maybe<bool> CollectOwnJSProxyKeys(Handle<JSReceiver> receiver,
+                                    Handle<JSProxy> proxy);
+  Maybe<bool> CollectOwnJSProxyTargetKeys(Handle<JSProxy> proxy,
+                                          Handle<JSReceiver> target);
+
+  Maybe<bool> AddKeysFromJSProxy(Handle<JSProxy> proxy,
+                                 Handle<FixedArray> keys);
+
+  Handle<OrderedHashSet> keys() { return Handle<OrderedHashSet>::cast(keys_); }
 
   Isolate* isolate_;
-  KeyCollectionType type_;
+  // keys_ is either an Handle<OrderedHashSet> or in the case of own JSProxy
+  // keys a Handle<FixedArray>.
+  Handle<FixedArray> keys_;
+  Handle<JSReceiver> last_non_empty_prototype_;
+  KeyCollectionMode mode_;
   PropertyFilter filter_;
   bool filter_proxy_keys_ = true;
-  // |elements_| contains the sorted element keys (indices) per level.
-  std::vector<std::vector<uint32_t>*> elements_;
-  // |protoLengths_| contains the total number of keys (elements + properties)
-  // per level. Negative values mark counts for a level with keys from a proxy.
-  std::vector<int> level_lengths_;
-  // |string_properties_| contains the unique String property keys for all
-  // levels in insertion order per level.
-  Handle<OrderedHashSet> string_properties_;
-  // |symbol_properties_| contains the unique Symbol property keys for all
-  // levels in insertion order per level.
-  Handle<OrderedHashSet> symbol_properties_;
-  Handle<FixedArray> ownProxyKeys_;
-  // |length_| keeps track of the total number of all element and property keys.
-  int length_ = 0;
-  // |levelLength_| keeps track of the number of String keys in the current
-  // level.
-  int level_string_length_ = 0;
-  // |levelSymbolLength_| keeps track of the number of Symbol keys in the
-  // current level.
-  int level_symbol_length_ = 0;
+  bool is_for_in_ = false;
+  bool skip_indices_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(KeyAccumulator);
 };
@@ -94,18 +105,18 @@
 class FastKeyAccumulator {
  public:
   FastKeyAccumulator(Isolate* isolate, Handle<JSReceiver> receiver,
-                     KeyCollectionType type, PropertyFilter filter)
-      : isolate_(isolate), receiver_(receiver), type_(type), filter_(filter) {
+                     KeyCollectionMode mode, PropertyFilter filter)
+      : isolate_(isolate), receiver_(receiver), mode_(mode), filter_(filter) {
     Prepare();
-    // TODO(cbruni): pass filter_ directly to the KeyAccumulator.
-    USE(filter_);
   }
 
   bool is_receiver_simple_enum() { return is_receiver_simple_enum_; }
   bool has_empty_prototype() { return has_empty_prototype_; }
   void set_filter_proxy_keys(bool filter) { filter_proxy_keys_ = filter; }
+  void set_is_for_in(bool value) { is_for_in_ = value; }
 
-  MaybeHandle<FixedArray> GetKeys(GetKeysConversion convert = KEEP_NUMBERS);
+  MaybeHandle<FixedArray> GetKeys(
+      GetKeysConversion convert = GetKeysConversion::kKeepNumbers);
 
  private:
   void Prepare();
@@ -114,11 +125,13 @@
 
   Isolate* isolate_;
   Handle<JSReceiver> receiver_;
-  KeyCollectionType type_;
+  Handle<JSReceiver> last_non_empty_prototype_;
+  KeyCollectionMode mode_;
   PropertyFilter filter_;
+  bool filter_proxy_keys_ = true;
+  bool is_for_in_ = false;
   bool is_receiver_simple_enum_ = false;
   bool has_empty_prototype_ = false;
-  bool filter_proxy_keys_ = true;
 
   DISALLOW_COPY_AND_ASSIGN(FastKeyAccumulator);
 };
@@ -126,4 +139,4 @@
 }  // namespace internal
 }  // namespace v8
 
-#endif  // V8_KEY_ACCUMULATOR_H_
+#endif  // V8_KEYS_H_
diff --git a/src/libplatform/task-queue.h b/src/libplatform/task-queue.h
index efe9e07..24b68da 100644
--- a/src/libplatform/task-queue.h
+++ b/src/libplatform/task-queue.h
@@ -33,8 +33,8 @@
   void Terminate();
 
  private:
-  base::Mutex lock_;
   base::Semaphore process_queue_semaphore_;
+  base::Mutex lock_;
   std::queue<Task*> task_queue_;
   bool terminated_;
 
diff --git a/src/libsampler/DEPS b/src/libsampler/DEPS
new file mode 100644
index 0000000..bdf1a82
--- /dev/null
+++ b/src/libsampler/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+  "+include",
+  "-src",
+  "+src/base",
+  "+src/libsampler",
+]
\ No newline at end of file
diff --git a/src/libsampler/v8-sampler.cc b/src/libsampler/v8-sampler.cc
new file mode 100644
index 0000000..edf6df1
--- /dev/null
+++ b/src/libsampler/v8-sampler.cc
@@ -0,0 +1,673 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/libsampler/v8-sampler.h"
+
+#if V8_OS_POSIX && !V8_OS_CYGWIN
+
+#define USE_SIGNALS
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <sys/time.h>
+
+#if !V8_OS_QNX && !V8_OS_NACL && !V8_OS_AIX
+#include <sys/syscall.h>  // NOLINT
+#endif
+
+#if V8_OS_MACOSX
+#include <mach/mach.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.
+#elif(!V8_OS_ANDROID || defined(__BIONIC_HAVE_UCONTEXT_T)) && \
+    !V8_OS_OPENBSD && !V8_OS_NACL
+#include <ucontext.h>
+#endif
+
+#include <unistd.h>
+
+// GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'.
+// Old versions of the C library <signal.h> didn't define the type.
+#if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) && \
+    (defined(__arm__) || defined(__aarch64__)) && \
+    !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
+#include <asm/sigcontext.h>  // NOLINT
+#endif
+
+#elif V8_OS_WIN || V8_OS_CYGWIN
+
+#include "src/base/win32-headers.h"
+
+#endif
+
+#include <algorithm>
+#include <vector>
+#include <map>
+
+#include "src/base/atomic-utils.h"
+#include "src/base/hashmap.h"
+#include "src/base/platform/platform.h"
+
+#if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
+
+// Not all versions of Android's C library provide ucontext_t.
+// Detect this and provide custom but compatible definitions. Note that these
+// follow the GLibc naming convention to access register values from
+// mcontext_t.
+//
+// See http://code.google.com/p/android/issues/detail?id=34784
+
+#if defined(__arm__)
+
+typedef struct sigcontext mcontext_t;
+
+typedef struct ucontext {
+  uint32_t uc_flags;
+  struct ucontext* uc_link;
+  stack_t uc_stack;
+  mcontext_t uc_mcontext;
+  // Other fields are not used by V8, don't define them here.
+} ucontext_t;
+
+#elif defined(__aarch64__)
+
+typedef struct sigcontext mcontext_t;
+
+typedef struct ucontext {
+  uint64_t uc_flags;
+  struct ucontext *uc_link;
+  stack_t uc_stack;
+  mcontext_t uc_mcontext;
+  // Other fields are not used by V8, don't define them here.
+} ucontext_t;
+
+#elif defined(__mips__)
+// MIPS version of sigcontext, for Android bionic.
+typedef struct {
+  uint32_t regmask;
+  uint32_t status;
+  uint64_t pc;
+  uint64_t gregs[32];
+  uint64_t fpregs[32];
+  uint32_t acx;
+  uint32_t fpc_csr;
+  uint32_t fpc_eir;
+  uint32_t used_math;
+  uint32_t dsp;
+  uint64_t mdhi;
+  uint64_t mdlo;
+  uint32_t hi1;
+  uint32_t lo1;
+  uint32_t hi2;
+  uint32_t lo2;
+  uint32_t hi3;
+  uint32_t lo3;
+} mcontext_t;
+
+typedef struct ucontext {
+  uint32_t uc_flags;
+  struct ucontext* uc_link;
+  stack_t uc_stack;
+  mcontext_t uc_mcontext;
+  // Other fields are not used by V8, don't define them here.
+} ucontext_t;
+
+#elif defined(__i386__)
+// x86 version for Android.
+typedef struct {
+  uint32_t gregs[19];
+  void* fpregs;
+  uint32_t oldmask;
+  uint32_t cr2;
+} mcontext_t;
+
+typedef uint32_t kernel_sigset_t[2];  // x86 kernel uses 64-bit signal masks
+typedef struct ucontext {
+  uint32_t uc_flags;
+  struct ucontext* uc_link;
+  stack_t uc_stack;
+  mcontext_t uc_mcontext;
+  // Other fields are not used by V8, don't define them here.
+} ucontext_t;
+enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 };
+
+#elif defined(__x86_64__)
+// x64 version for Android.
+typedef struct {
+  uint64_t gregs[23];
+  void* fpregs;
+  uint64_t __reserved1[8];
+} mcontext_t;
+
+typedef struct ucontext {
+  uint64_t uc_flags;
+  struct ucontext *uc_link;
+  stack_t uc_stack;
+  mcontext_t uc_mcontext;
+  // Other fields are not used by V8, don't define them here.
+} ucontext_t;
+enum { REG_RBP = 10, REG_RSP = 15, REG_RIP = 16 };
+#endif
+
+#endif  // V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
+
+
+namespace v8 {
+namespace sampler {
+
+namespace {
+
+#if defined(USE_SIGNALS)
+typedef std::vector<Sampler*> SamplerList;
+typedef SamplerList::iterator SamplerListIterator;
+typedef base::AtomicValue<bool> AtomicMutex;
+
+class AtomicGuard {
+ public:
+  explicit AtomicGuard(AtomicMutex* atomic, bool is_blocking = true)
+      : atomic_(atomic), is_success_(false) {
+    do {
+      // Use Acquire_Load to gain mutual exclusion.
+      USE(atomic_->Value());
+      is_success_ = atomic_->TrySetValue(false, true);
+    } while (is_blocking && !is_success_);
+  }
+
+  bool is_success() const { return is_success_; }
+
+  ~AtomicGuard() {
+    if (!is_success_) return;
+    atomic_->SetValue(false);
+  }
+
+ private:
+  AtomicMutex* const atomic_;
+  bool is_success_;
+};
+
+// Returns key for hash map.
+void* ThreadKey(pthread_t thread_id) {
+  return reinterpret_cast<void*>(thread_id);
+}
+
+// Returns hash value for hash map.
+uint32_t ThreadHash(pthread_t thread_id) {
+#if V8_OS_MACOSX
+  return static_cast<uint32_t>(reinterpret_cast<intptr_t>(thread_id));
+#else
+  return static_cast<uint32_t>(thread_id);
+#endif
+}
+
+#endif  // USE_SIGNALS
+
+}  // namespace
+
+#if defined(USE_SIGNALS)
+
+class Sampler::PlatformData {
+ public:
+  PlatformData() : vm_tid_(pthread_self()) {}
+  pthread_t vm_tid() const { return vm_tid_; }
+
+ private:
+  pthread_t vm_tid_;
+};
+
+class SamplerManager {
+ public:
+  SamplerManager() : sampler_map_(base::HashMap::PointersMatch) {}
+
+  void AddSampler(Sampler* sampler) {
+    AtomicGuard atomic_guard(&samplers_access_counter_);
+    DCHECK(sampler->IsActive() || !sampler->IsRegistered());
+    // Add sampler into map if needed.
+    pthread_t thread_id = sampler->platform_data()->vm_tid();
+    base::HashMap::Entry* entry =
+            sampler_map_.LookupOrInsert(ThreadKey(thread_id),
+                                        ThreadHash(thread_id));
+    DCHECK(entry != nullptr);
+    if (entry->value == nullptr) {
+      SamplerList* samplers = new SamplerList();
+      samplers->push_back(sampler);
+      entry->value = samplers;
+    } else {
+      SamplerList* samplers = reinterpret_cast<SamplerList*>(entry->value);
+      bool exists = false;
+      for (SamplerListIterator iter = samplers->begin();
+           iter != samplers->end(); ++iter) {
+        if (*iter == sampler) {
+          exists = true;
+          break;
+        }
+      }
+      if (!exists) {
+        samplers->push_back(sampler);
+      }
+    }
+  }
+
+  void RemoveSampler(Sampler* sampler) {
+    AtomicGuard atomic_guard(&samplers_access_counter_);
+    DCHECK(sampler->IsActive() || sampler->IsRegistered());
+    // Remove sampler from map.
+    pthread_t thread_id = sampler->platform_data()->vm_tid();
+    void* thread_key = ThreadKey(thread_id);
+    uint32_t thread_hash = ThreadHash(thread_id);
+    base::HashMap::Entry* entry = sampler_map_.Lookup(thread_key, thread_hash);
+    DCHECK(entry != nullptr);
+    SamplerList* samplers = reinterpret_cast<SamplerList*>(entry->value);
+    for (SamplerListIterator iter = samplers->begin(); iter != samplers->end();
+         ++iter) {
+      if (*iter == sampler) {
+        samplers->erase(iter);
+        break;
+      }
+    }
+    if (samplers->empty()) {
+      sampler_map_.Remove(thread_key, thread_hash);
+      delete samplers;
+    }
+  }
+
+#if defined(USE_SIGNALS)
+  void DoSample(const v8::RegisterState& state) {
+    AtomicGuard atomic_guard(&SamplerManager::samplers_access_counter_, false);
+    if (!atomic_guard.is_success()) return;
+    pthread_t thread_id = pthread_self();
+    base::HashMap::Entry* entry =
+        sampler_map_.Lookup(ThreadKey(thread_id), ThreadHash(thread_id));
+    if (!entry) return;
+    SamplerList& samplers = *static_cast<SamplerList*>(entry->value);
+
+    for (int i = 0; i < samplers.size(); ++i) {
+      Sampler* sampler = samplers[i];
+      Isolate* isolate = sampler->isolate();
+      // We require a fully initialized and entered isolate.
+      if (isolate == nullptr || !isolate->IsInUse()) continue;
+      if (v8::Locker::IsActive() && !Locker::IsLocked(isolate)) continue;
+      sampler->SampleStack(state);
+    }
+  }
+#endif
+
+  static SamplerManager* instance() { return instance_.Pointer(); }
+
+ private:
+  base::HashMap sampler_map_;
+  static AtomicMutex samplers_access_counter_;
+  static base::LazyInstance<SamplerManager>::type instance_;
+};
+
+AtomicMutex SamplerManager::samplers_access_counter_;
+base::LazyInstance<SamplerManager>::type SamplerManager::instance_ =
+    LAZY_INSTANCE_INITIALIZER;
+
+#elif V8_OS_WIN || V8_OS_CYGWIN
+
+// ----------------------------------------------------------------------------
+// Win32 profiler support. On Cygwin we use the same sampler implementation as
+// on Win32.
+
+class Sampler::PlatformData {
+ public:
+  // Get a handle to the calling thread. This is the thread that we are
+  // going to profile. We need to make a copy of the handle because we are
+  // going to use it in the sampler thread. Using GetThreadHandle() will
+  // not work in this case. We're using OpenThread because DuplicateHandle
+  // for some reason doesn't work in Chrome's sandbox.
+  PlatformData()
+      : profiled_thread_(OpenThread(THREAD_GET_CONTEXT |
+                                    THREAD_SUSPEND_RESUME |
+                                    THREAD_QUERY_INFORMATION,
+                                    false,
+                                    GetCurrentThreadId())) {}
+
+  ~PlatformData() {
+    if (profiled_thread_ != nullptr) {
+      CloseHandle(profiled_thread_);
+      profiled_thread_ = nullptr;
+    }
+  }
+
+  HANDLE profiled_thread() { return profiled_thread_; }
+
+ private:
+  HANDLE profiled_thread_;
+};
+#endif  // USE_SIGNALS
+
+
+#if defined(USE_SIGNALS)
+class SignalHandler {
+ public:
+  static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); }
+  static void TearDown() {
+    delete mutex_;
+    mutex_ = nullptr;
+  }
+
+  static void IncreaseSamplerCount() {
+    base::LockGuard<base::Mutex> lock_guard(mutex_);
+    if (++client_count_ == 1) Install();
+  }
+
+  static void DecreaseSamplerCount() {
+    base::LockGuard<base::Mutex> lock_guard(mutex_);
+    if (--client_count_ == 0) Restore();
+  }
+
+  static bool Installed() {
+    base::LockGuard<base::Mutex> lock_guard(mutex_);
+    return signal_handler_installed_;
+  }
+
+ private:
+  static void Install() {
+#if !V8_OS_NACL
+    struct sigaction sa;
+    sa.sa_sigaction = &HandleProfilerSignal;
+    sigemptyset(&sa.sa_mask);
+#if V8_OS_QNX
+    sa.sa_flags = SA_SIGINFO;
+#else
+    sa.sa_flags = SA_RESTART | SA_SIGINFO;
+#endif
+    signal_handler_installed_ =
+        (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
+#endif  // !V8_OS_NACL
+  }
+
+  static void Restore() {
+#if !V8_OS_NACL
+    if (signal_handler_installed_) {
+      sigaction(SIGPROF, &old_signal_handler_, 0);
+      signal_handler_installed_ = false;
+    }
+#endif
+  }
+
+#if !V8_OS_NACL
+  static void FillRegisterState(void* context, RegisterState* regs);
+  static void HandleProfilerSignal(int signal, siginfo_t* info, void* context);
+#endif
+  // Protects the process wide state below.
+  static base::Mutex* mutex_;
+  static int client_count_;
+  static bool signal_handler_installed_;
+  static struct sigaction old_signal_handler_;
+};
+
+base::Mutex* SignalHandler::mutex_ = nullptr;
+int SignalHandler::client_count_ = 0;
+struct sigaction SignalHandler::old_signal_handler_;
+bool SignalHandler::signal_handler_installed_ = false;
+
+
+// As Native Client does not support signal handling, profiling is disabled.
+#if !V8_OS_NACL
+void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
+                                         void* context) {
+  USE(info);
+  if (signal != SIGPROF) return;
+  v8::RegisterState state;
+  FillRegisterState(context, &state);
+  SamplerManager::instance()->DoSample(state);
+}
+
+void SignalHandler::FillRegisterState(void* context, RegisterState* state) {
+  // Extracting the sample from the context is extremely machine dependent.
+  ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
+#if !(V8_OS_OPENBSD || (V8_OS_LINUX && (V8_HOST_ARCH_PPC || V8_HOST_ARCH_S390)))
+  mcontext_t& mcontext = ucontext->uc_mcontext;
+#endif
+#if V8_OS_LINUX
+#if V8_HOST_ARCH_IA32
+  state->pc = reinterpret_cast<void*>(mcontext.gregs[REG_EIP]);
+  state->sp = reinterpret_cast<void*>(mcontext.gregs[REG_ESP]);
+  state->fp = reinterpret_cast<void*>(mcontext.gregs[REG_EBP]);
+#elif V8_HOST_ARCH_X64
+  state->pc = reinterpret_cast<void*>(mcontext.gregs[REG_RIP]);
+  state->sp = reinterpret_cast<void*>(mcontext.gregs[REG_RSP]);
+  state->fp = reinterpret_cast<void*>(mcontext.gregs[REG_RBP]);
+#elif V8_HOST_ARCH_ARM
+#if V8_LIBC_GLIBC && !V8_GLIBC_PREREQ(2, 4)
+  // Old GLibc ARM versions used a gregs[] array to access the register
+  // values from mcontext_t.
+  state->pc = reinterpret_cast<void*>(mcontext.gregs[R15]);
+  state->sp = reinterpret_cast<void*>(mcontext.gregs[R13]);
+  state->fp = reinterpret_cast<void*>(mcontext.gregs[R11]);
+#else
+  state->pc = reinterpret_cast<void*>(mcontext.arm_pc);
+  state->sp = reinterpret_cast<void*>(mcontext.arm_sp);
+  state->fp = reinterpret_cast<void*>(mcontext.arm_fp);
+#endif  // V8_LIBC_GLIBC && !V8_GLIBC_PREREQ(2, 4)
+#elif V8_HOST_ARCH_ARM64
+  state->pc = reinterpret_cast<void*>(mcontext.pc);
+  state->sp = reinterpret_cast<void*>(mcontext.sp);
+  // FP is an alias for x29.
+  state->fp = reinterpret_cast<void*>(mcontext.regs[29]);
+#elif V8_HOST_ARCH_MIPS
+  state->pc = reinterpret_cast<void*>(mcontext.pc);
+  state->sp = reinterpret_cast<void*>(mcontext.gregs[29]);
+  state->fp = reinterpret_cast<void*>(mcontext.gregs[30]);
+#elif V8_HOST_ARCH_MIPS64
+  state->pc = reinterpret_cast<void*>(mcontext.pc);
+  state->sp = reinterpret_cast<void*>(mcontext.gregs[29]);
+  state->fp = reinterpret_cast<void*>(mcontext.gregs[30]);
+#elif V8_HOST_ARCH_PPC
+  state->pc = reinterpret_cast<void*>(ucontext->uc_mcontext.regs->nip);
+  state->sp =
+      reinterpret_cast<void*>(ucontext->uc_mcontext.regs->gpr[PT_R1]);
+  state->fp =
+      reinterpret_cast<void*>(ucontext->uc_mcontext.regs->gpr[PT_R31]);
+#elif V8_HOST_ARCH_S390
+#if V8_TARGET_ARCH_32_BIT
+  // 31-bit target will have bit 0 (MSB) of the PSW set to denote addressing
+  // mode.  This bit needs to be masked out to resolve actual address.
+  state->pc =
+      reinterpret_cast<void*>(ucontext->uc_mcontext.psw.addr & 0x7FFFFFFF);
+#else
+  state->pc = reinterpret_cast<void*>(ucontext->uc_mcontext.psw.addr);
+#endif  // V8_TARGET_ARCH_32_BIT
+  state->sp = reinterpret_cast<void*>(ucontext->uc_mcontext.gregs[15]);
+  state->fp = reinterpret_cast<void*>(ucontext->uc_mcontext.gregs[11]);
+#endif  // V8_HOST_ARCH_*
+#elif V8_OS_MACOSX
+#if V8_HOST_ARCH_X64
+#if __DARWIN_UNIX03
+  state->pc = reinterpret_cast<void*>(mcontext->__ss.__rip);
+  state->sp = reinterpret_cast<void*>(mcontext->__ss.__rsp);
+  state->fp = reinterpret_cast<void*>(mcontext->__ss.__rbp);
+#else  // !__DARWIN_UNIX03
+  state->pc = reinterpret_cast<void*>(mcontext->ss.rip);
+  state->sp = reinterpret_cast<void*>(mcontext->ss.rsp);
+  state->fp = reinterpret_cast<void*>(mcontext->ss.rbp);
+#endif  // __DARWIN_UNIX03
+#elif V8_HOST_ARCH_IA32
+#if __DARWIN_UNIX03
+  state->pc = reinterpret_cast<void*>(mcontext->__ss.__eip);
+  state->sp = reinterpret_cast<void*>(mcontext->__ss.__esp);
+  state->fp = reinterpret_cast<void*>(mcontext->__ss.__ebp);
+#else  // !__DARWIN_UNIX03
+  state->pc = reinterpret_cast<void*>(mcontext->ss.eip);
+  state->sp = reinterpret_cast<void*>(mcontext->ss.esp);
+  state->fp = reinterpret_cast<void*>(mcontext->ss.ebp);
+#endif  // __DARWIN_UNIX03
+#endif  // V8_HOST_ARCH_IA32
+#elif V8_OS_FREEBSD
+#if V8_HOST_ARCH_IA32
+  state->pc = reinterpret_cast<void*>(mcontext.mc_eip);
+  state->sp = reinterpret_cast<void*>(mcontext.mc_esp);
+  state->fp = reinterpret_cast<void*>(mcontext.mc_ebp);
+#elif V8_HOST_ARCH_X64
+  state->pc = reinterpret_cast<void*>(mcontext.mc_rip);
+  state->sp = reinterpret_cast<void*>(mcontext.mc_rsp);
+  state->fp = reinterpret_cast<void*>(mcontext.mc_rbp);
+#elif V8_HOST_ARCH_ARM
+  state->pc = reinterpret_cast<void*>(mcontext.mc_r15);
+  state->sp = reinterpret_cast<void*>(mcontext.mc_r13);
+  state->fp = reinterpret_cast<void*>(mcontext.mc_r11);
+#endif  // V8_HOST_ARCH_*
+#elif V8_OS_NETBSD
+#if V8_HOST_ARCH_IA32
+  state->pc = reinterpret_cast<void*>(mcontext.__gregs[_REG_EIP]);
+  state->sp = reinterpret_cast<void*>(mcontext.__gregs[_REG_ESP]);
+  state->fp = reinterpret_cast<void*>(mcontext.__gregs[_REG_EBP]);
+#elif V8_HOST_ARCH_X64
+  state->pc = reinterpret_cast<void*>(mcontext.__gregs[_REG_RIP]);
+  state->sp = reinterpret_cast<void*>(mcontext.__gregs[_REG_RSP]);
+  state->fp = reinterpret_cast<void*>(mcontext.__gregs[_REG_RBP]);
+#endif  // V8_HOST_ARCH_*
+#elif V8_OS_OPENBSD
+#if V8_HOST_ARCH_IA32
+  state->pc = reinterpret_cast<void*>(ucontext->sc_eip);
+  state->sp = reinterpret_cast<void*>(ucontext->sc_esp);
+  state->fp = reinterpret_cast<void*>(ucontext->sc_ebp);
+#elif V8_HOST_ARCH_X64
+  state->pc = reinterpret_cast<void*>(ucontext->sc_rip);
+  state->sp = reinterpret_cast<void*>(ucontext->sc_rsp);
+  state->fp = reinterpret_cast<void*>(ucontext->sc_rbp);
+#endif  // V8_HOST_ARCH_*
+#elif V8_OS_SOLARIS
+  state->pc = reinterpret_cast<void*>(mcontext.gregs[REG_PC]);
+  state->sp = reinterpret_cast<void*>(mcontext.gregs[REG_SP]);
+  state->fp = reinterpret_cast<void*>(mcontext.gregs[REG_FP]);
+#elif V8_OS_QNX
+#if V8_HOST_ARCH_IA32
+  state->pc = reinterpret_cast<void*>(mcontext.cpu.eip);
+  state->sp = reinterpret_cast<void*>(mcontext.cpu.esp);
+  state->fp = reinterpret_cast<void*>(mcontext.cpu.ebp);
+#elif V8_HOST_ARCH_ARM
+  state->pc = reinterpret_cast<void*>(mcontext.cpu.gpr[ARM_REG_PC]);
+  state->sp = reinterpret_cast<void*>(mcontext.cpu.gpr[ARM_REG_SP]);
+  state->fp = reinterpret_cast<void*>(mcontext.cpu.gpr[ARM_REG_FP]);
+#endif  // V8_HOST_ARCH_*
+#elif V8_OS_AIX
+  state->pc = reinterpret_cast<void*>(mcontext.jmp_context.iar);
+  state->sp = reinterpret_cast<void*>(mcontext.jmp_context.gpr[1]);
+  state->fp = reinterpret_cast<void*>(mcontext.jmp_context.gpr[31]);
+#endif  // V8_OS_AIX
+}
+
+#endif  // !V8_OS_NACL
+
+#endif  // USE_SIGNALS
+
+
+void Sampler::SetUp() {
+#if defined(USE_SIGNALS)
+  SignalHandler::SetUp();
+#endif
+}
+
+
+void Sampler::TearDown() {
+#if defined(USE_SIGNALS)
+  SignalHandler::TearDown();
+#endif
+}
+
+Sampler::Sampler(Isolate* isolate)
+    : is_counting_samples_(false),
+      js_sample_count_(0),
+      external_sample_count_(0),
+      isolate_(isolate),
+      profiling_(false),
+      has_processing_thread_(false),
+      active_(false),
+      registered_(false) {
+  data_ = new PlatformData;
+}
+
+Sampler::~Sampler() {
+  DCHECK(!IsActive());
+#if defined(USE_SIGNALS)
+  if (IsRegistered()) {
+    SamplerManager::instance()->RemoveSampler(this);
+  }
+#endif
+  delete data_;
+}
+
+void Sampler::Start() {
+  DCHECK(!IsActive());
+  SetActive(true);
+#if defined(USE_SIGNALS)
+  SamplerManager::instance()->AddSampler(this);
+#endif
+}
+
+
+void Sampler::Stop() {
+#if defined(USE_SIGNALS)
+  SamplerManager::instance()->RemoveSampler(this);
+#endif
+  DCHECK(IsActive());
+  SetActive(false);
+  SetRegistered(false);
+}
+
+
+void Sampler::IncreaseProfilingDepth() {
+  base::NoBarrier_AtomicIncrement(&profiling_, 1);
+#if defined(USE_SIGNALS)
+  SignalHandler::IncreaseSamplerCount();
+#endif
+}
+
+
+void Sampler::DecreaseProfilingDepth() {
+#if defined(USE_SIGNALS)
+  SignalHandler::DecreaseSamplerCount();
+#endif
+  base::NoBarrier_AtomicIncrement(&profiling_, -1);
+}
+
+
+#if defined(USE_SIGNALS)
+
+void Sampler::DoSample() {
+  if (!SignalHandler::Installed()) return;
+  if (!IsActive() && !IsRegistered()) {
+    SamplerManager::instance()->AddSampler(this);
+    SetRegistered(true);
+  }
+  pthread_kill(platform_data()->vm_tid(), SIGPROF);
+}
+
+#elif V8_OS_WIN || V8_OS_CYGWIN
+
+void Sampler::DoSample() {
+  HANDLE profiled_thread = platform_data()->profiled_thread();
+  if (profiled_thread == nullptr) return;
+
+  const DWORD kSuspendFailed = static_cast<DWORD>(-1);
+  if (SuspendThread(profiled_thread) == kSuspendFailed) return;
+
+  // Context used for sampling the register state of the profiled thread.
+  CONTEXT context;
+  memset(&context, 0, sizeof(context));
+  context.ContextFlags = CONTEXT_FULL;
+  if (GetThreadContext(profiled_thread, &context) != 0) {
+    v8::RegisterState state;
+#if V8_HOST_ARCH_X64
+    state.pc = reinterpret_cast<void*>(context.Rip);
+    state.sp = reinterpret_cast<void*>(context.Rsp);
+    state.fp = reinterpret_cast<void*>(context.Rbp);
+#else
+    state.pc = reinterpret_cast<void*>(context.Eip);
+    state.sp = reinterpret_cast<void*>(context.Esp);
+    state.fp = reinterpret_cast<void*>(context.Ebp);
+#endif
+    SampleStack(state);
+  }
+  ResumeThread(profiled_thread);
+}
+
+#endif  // USE_SIGNALS
+
+}  // namespace sampler
+}  // namespace v8
diff --git a/src/libsampler/v8-sampler.h b/src/libsampler/v8-sampler.h
new file mode 100644
index 0000000..7ae3c8c
--- /dev/null
+++ b/src/libsampler/v8-sampler.h
@@ -0,0 +1,103 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_LIBSAMPLER_SAMPLER_H_
+#define V8_LIBSAMPLER_SAMPLER_H_
+
+#include "include/v8.h"
+
+#include "src/base/atomicops.h"
+#include "src/base/macros.h"
+
+namespace v8 {
+namespace sampler {
+
+// ----------------------------------------------------------------------------
+// Sampler
+//
+// A sampler periodically samples the state of the VM and optionally
+// (if used for profiling) the program counter and stack pointer for
+// the thread that created it.
+
+class Sampler {
+ public:
+  static const int kMaxFramesCountLog2 = 8;
+  static const unsigned kMaxFramesCount = (1u << kMaxFramesCountLog2) - 1;
+
+  // Initializes the Sampler support. Called once at VM startup.
+  static void SetUp();
+  static void TearDown();
+
+  // Initialize sampler.
+  explicit Sampler(Isolate* isolate);
+  virtual ~Sampler();
+
+  Isolate* isolate() const { return isolate_; }
+
+  // Performs stack sampling.
+  // Clients should override this method in order to do something on samples,
+  // for example buffer samples in a queue.
+  virtual void SampleStack(const v8::RegisterState& regs) = 0;
+
+  // Start and stop sampler.
+  void Start();
+  void Stop();
+
+  // Whether the sampling thread should use this Sampler for CPU profiling?
+  bool IsProfiling() const {
+    return base::NoBarrier_Load(&profiling_) > 0 &&
+        !base::NoBarrier_Load(&has_processing_thread_);
+  }
+  void IncreaseProfilingDepth();
+  void DecreaseProfilingDepth();
+
+  // Whether the sampler is running (that is, consumes resources).
+  bool IsActive() const { return base::NoBarrier_Load(&active_); }
+
+  // CpuProfiler collects samples by calling DoSample directly
+  // without calling Start. To keep it working, we register the sampler
+  // with the CpuProfiler.
+  bool IsRegistered() const { return base::NoBarrier_Load(&registered_); }
+
+  void DoSample();
+
+  void SetHasProcessingThread(bool value) {
+    base::NoBarrier_Store(&has_processing_thread_, value);
+  }
+
+  // Used in tests to make sure that stack sampling is performed.
+  unsigned js_sample_count() const { return js_sample_count_; }
+  unsigned external_sample_count() const { return external_sample_count_; }
+  void StartCountingSamples() {
+    js_sample_count_ = 0;
+    external_sample_count_ = 0;
+    is_counting_samples_ = true;
+  }
+
+  class PlatformData;
+  PlatformData* platform_data() const { return data_; }
+
+ protected:
+  // Counts stack samples taken in various VM states.
+  bool is_counting_samples_;
+  unsigned js_sample_count_;
+  unsigned external_sample_count_;
+
+ private:
+  void SetActive(bool value) { base::NoBarrier_Store(&active_, value); }
+  void SetRegistered(bool value) { base::NoBarrier_Store(&registered_, value); }
+
+  Isolate* isolate_;
+  base::Atomic32 profiling_;
+  base::Atomic32 has_processing_thread_;
+  base::Atomic32 active_;
+  base::Atomic32 registered_;
+  PlatformData* data_;  // Platform specific data.
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
+};
+
+}  // namespace sampler
+}  // namespace v8
+
+#endif  // V8_LIBSAMPLER_SAMPLER_H_
diff --git a/src/locked-queue-inl.h b/src/locked-queue-inl.h
index 8b3e9d0..eb18f64 100644
--- a/src/locked-queue-inl.h
+++ b/src/locked-queue-inl.h
@@ -5,7 +5,7 @@
 #ifndef V8_LOCKED_QUEUE_INL_
 #define V8_LOCKED_QUEUE_INL_
 
-#include "src/atomic-utils.h"
+#include "src/base/atomic-utils.h"
 #include "src/locked-queue.h"
 
 namespace v8 {
@@ -15,7 +15,7 @@
 struct LockedQueue<Record>::Node : Malloced {
   Node() : next(nullptr) {}
   Record value;
-  AtomicValue<Node*> next;
+  base::AtomicValue<Node*> next;
 };
 
 
diff --git a/src/log-inl.h b/src/log-inl.h
index 765398f..b986597 100644
--- a/src/log-inl.h
+++ b/src/log-inl.h
@@ -13,25 +13,24 @@
 namespace v8 {
 namespace internal {
 
-Logger::LogEventsAndTags Logger::ToNativeByScript(Logger::LogEventsAndTags tag,
-                                                  Script* script) {
-  if ((tag == FUNCTION_TAG || tag == LAZY_COMPILE_TAG || tag == SCRIPT_TAG) &&
-      script->type() == Script::TYPE_NATIVE) {
-    switch (tag) {
-      case FUNCTION_TAG: return NATIVE_FUNCTION_TAG;
-      case LAZY_COMPILE_TAG: return NATIVE_LAZY_COMPILE_TAG;
-      case SCRIPT_TAG: return NATIVE_SCRIPT_TAG;
-      default: return tag;
-    }
-  } else {
-    return tag;
+CodeEventListener::LogEventsAndTags Logger::ToNativeByScript(
+    CodeEventListener::LogEventsAndTags tag, Script* script) {
+  if (script->type() != Script::TYPE_NATIVE) return tag;
+  switch (tag) {
+    case CodeEventListener::FUNCTION_TAG:
+      return CodeEventListener::NATIVE_FUNCTION_TAG;
+    case CodeEventListener::LAZY_COMPILE_TAG:
+      return CodeEventListener::NATIVE_LAZY_COMPILE_TAG;
+    case CodeEventListener::SCRIPT_TAG:
+      return CodeEventListener::NATIVE_SCRIPT_TAG;
+    default:
+      return tag;
   }
 }
 
-
 void Logger::CallEventLogger(Isolate* isolate, const char* name, StartEnd se,
                              bool expose_to_api) {
-  if (isolate->event_logger() != NULL) {
+  if (isolate->event_logger()) {
     if (isolate->event_logger() == DefaultEventLoggerSentinel) {
       LOG(isolate, TimerEvent(se, name));
     } else if (expose_to_api) {
@@ -39,6 +38,7 @@
     }
   }
 }
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/log-utils.cc b/src/log-utils.cc
index ff9af68..22972ec 100644
--- a/src/log-utils.cc
+++ b/src/log-utils.cc
@@ -164,16 +164,14 @@
   }
 }
 
-
 void Log::MessageBuilder::AppendAddress(Address addr) {
-  Append("0x%" V8PRIxPTR, addr);
+  Append("%p", static_cast<void*>(addr));
 }
 
-
 void Log::MessageBuilder::AppendSymbolName(Symbol* symbol) {
   DCHECK(symbol);
   Append("symbol(");
-  if (!symbol->name()->IsUndefined()) {
+  if (!symbol->name()->IsUndefined(symbol->GetIsolate())) {
     Append("\"");
     AppendDetailed(String::cast(symbol->name()), false);
     Append("\" ");
diff --git a/src/log-utils.h b/src/log-utils.h
index 3e70a96..059e5a5 100644
--- a/src/log-utils.h
+++ b/src/log-utils.h
@@ -10,6 +10,7 @@
 #include <cstdarg>
 
 #include "src/allocation.h"
+#include "src/base/compiler-specific.h"
 #include "src/base/platform/mutex.h"
 #include "src/flags.h"
 
@@ -62,10 +63,10 @@
     ~MessageBuilder() { }
 
     // Append string data to the log message.
-    void Append(const char* format, ...);
+    void PRINTF_FORMAT(2, 3) Append(const char* format, ...);
 
     // Append string data to the log message.
-    void AppendVA(const char* format, va_list args);
+    void PRINTF_FORMAT(2, 0) AppendVA(const char* format, va_list args);
 
     // Append a character to the log message.
     void Append(const char c);
diff --git a/src/log.cc b/src/log.cc
index 93111a2..43c3981 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -11,15 +11,18 @@
 #include "src/base/platform/platform.h"
 #include "src/bootstrapper.h"
 #include "src/code-stubs.h"
+#include "src/counters.h"
 #include "src/deoptimizer.h"
 #include "src/global-handles.h"
 #include "src/interpreter/bytecodes.h"
 #include "src/interpreter/interpreter.h"
+#include "src/libsampler/v8-sampler.h"
 #include "src/log-inl.h"
 #include "src/log-utils.h"
 #include "src/macro-assembler.h"
 #include "src/perf-jit.h"
-#include "src/profiler/cpu-profiler.h"
+#include "src/profiler/cpu-profiler-inl.h"
+#include "src/profiler/profiler-listener.h"
 #include "src/runtime-profiler.h"
 #include "src/string-stream.h"
 #include "src/vm-state-inl.h"
@@ -29,25 +32,10 @@
 
 
 #define DECLARE_EVENT(ignore1, name) name,
-static const char* const kLogEventsNames[Logger::NUMBER_OF_LOG_EVENTS] = {
-  LOG_EVENTS_AND_TAGS_LIST(DECLARE_EVENT)
-};
+static const char* kLogEventsNames[CodeEventListener::NUMBER_OF_LOG_EVENTS] = {
+    LOG_EVENTS_AND_TAGS_LIST(DECLARE_EVENT)};
 #undef DECLARE_EVENT
 
-
-#define CALL_LISTENERS(Call)                    \
-for (int i = 0; i < listeners_.length(); ++i) { \
-  listeners_[i]->Call;                          \
-}
-
-#define PROFILER_LOG(Call)                                \
-  do {                                                    \
-    CpuProfiler* cpu_profiler = isolate_->cpu_profiler(); \
-    if (cpu_profiler->is_profiling()) {                   \
-      cpu_profiler->Call;                                 \
-    }                                                     \
-  } while (false);
-
 static const char* ComputeMarker(SharedFunctionInfo* shared,
                                  AbstractCode* code) {
   switch (code->kind()) {
@@ -70,7 +58,7 @@
     utf8_pos_ = 0;
   }
 
-  void Init(Logger::LogEventsAndTags tag) {
+  void Init(CodeEventListener::LogEventsAndTags tag) {
     Reset();
     AppendBytes(kLogEventsNames[tag]);
     AppendByte(':');
@@ -82,7 +70,7 @@
     } else {
       Symbol* symbol = Symbol::cast(name);
       AppendBytes("symbol(");
-      if (!symbol->name()->IsUndefined()) {
+      if (!symbol->name()->IsUndefined(symbol->GetIsolate())) {
         AppendBytes("\"");
         AppendString(String::cast(symbol->name()));
         AppendBytes("\" ");
@@ -164,34 +152,32 @@
 
 CodeEventLogger::~CodeEventLogger() { delete name_buffer_; }
 
-void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
+void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                                       AbstractCode* code, const char* comment) {
   name_buffer_->Init(tag);
   name_buffer_->AppendBytes(comment);
   LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
 }
 
-void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
+void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                                       AbstractCode* code, Name* name) {
   name_buffer_->Init(tag);
   name_buffer_->AppendName(name);
   LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
 }
 
-void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
+void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                                       AbstractCode* code,
-                                      SharedFunctionInfo* shared,
-                                      CompilationInfo* info, Name* name) {
+                                      SharedFunctionInfo* shared, Name* name) {
   name_buffer_->Init(tag);
   name_buffer_->AppendBytes(ComputeMarker(shared, code));
   name_buffer_->AppendName(name);
   LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
 }
 
-void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
+void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                                       AbstractCode* code,
-                                      SharedFunctionInfo* shared,
-                                      CompilationInfo* info, Name* source,
+                                      SharedFunctionInfo* shared, Name* source,
                                       int line, int column) {
   name_buffer_->Init(tag);
   name_buffer_->AppendBytes(ComputeMarker(shared, code));
@@ -209,7 +195,7 @@
   LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
 }
 
-void CodeEventLogger::CodeCreateEvent(Logger::LogEventsAndTags tag,
+void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
                                       AbstractCode* code, int args_count) {
   name_buffer_->Init(tag);
   name_buffer_->AppendInt(args_count);
@@ -218,7 +204,7 @@
 
 void CodeEventLogger::RegExpCodeCreateEvent(AbstractCode* code,
                                             String* source) {
-  name_buffer_->Init(Logger::REG_EXP_TAG);
+  name_buffer_->Init(CodeEventListener::REG_EXP_TAG);
   name_buffer_->AppendString(source);
   LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
 }
@@ -242,10 +228,6 @@
   static const char kFilenameFormatString[];
   static const int kFilenameBufferPadding;
 
-  // File buffer size of the low-level log. We don't use the default to
-  // minimize the associated overhead.
-  static const int kLogBufferSize = 2 * MB;
-
   FILE* perf_output_handle_;
 };
 
@@ -266,7 +248,7 @@
   perf_output_handle_ =
       base::OS::FOpen(perf_dump_name.start(), base::OS::LogFileOpenMode);
   CHECK_NOT_NULL(perf_output_handle_);
-  setvbuf(perf_output_handle_, NULL, _IOFBF, kLogBufferSize);
+  setvbuf(perf_output_handle_, NULL, _IOLBF, 0);
 }
 
 
@@ -284,12 +266,17 @@
     return;
   }
 
-  base::OS::FPrint(perf_output_handle_, "%llx %x %.*s\n",
-                   reinterpret_cast<uint64_t>(code->instruction_start()),
+  // Linux perf expects hex literals without a leading 0x, while some
+  // implementations of printf might prepend one when using the %p format
+  // for pointers, leading to wrongly formatted JIT symbols maps.
+  //
+  // Instead, we use V8PRIxPTR format string and cast pointer to uintpr_t,
+  // so that we have control over the exact output format.
+  base::OS::FPrint(perf_output_handle_, "%" V8PRIxPTR " %x %.*s\n",
+                   reinterpret_cast<uintptr_t>(code->instruction_start()),
                    code->instruction_size(), length, name);
 }
 
-
 // Low-level logging support.
 #define LL_LOG(Call) if (ll_logger_) ll_logger_->Call;
 
@@ -332,10 +319,6 @@
   // Extension added to V8 log file name to get the low-level log name.
   static const char kLogExt[];
 
-  // File buffer size of the low-level log. We don't use the default to
-  // minimize the associated overhead.
-  static const int kLogBufferSize = 2 * MB;
-
   void LogCodeInfo();
   void LogWriteBytes(const char* bytes, int size);
 
@@ -360,7 +343,7 @@
   MemCopy(ll_name.start() + len, kLogExt, sizeof(kLogExt));
   ll_output_handle_ =
       base::OS::FOpen(ll_name.start(), base::OS::LogFileOpenMode);
-  setvbuf(ll_output_handle_, NULL, _IOFBF, kLogBufferSize);
+  setvbuf(ll_output_handle_, NULL, _IOLBF, 0);
 
   LogCodeInfo();
 }
@@ -536,6 +519,31 @@
 }
 
 
+// TODO(lpy): Keeping sampling thread inside V8 is a workaround currently,
+// the reason is to reduce code duplication during migration to sampler library,
+// sampling thread, as well as the sampler, will be moved to D8 eventually.
+class SamplingThread : public base::Thread {
+ public:
+  static const int kSamplingThreadStackSize = 64 * KB;
+
+  SamplingThread(sampler::Sampler* sampler, int interval)
+      : base::Thread(base::Thread::Options("SamplingThread",
+                                           kSamplingThreadStackSize)),
+        sampler_(sampler),
+        interval_(interval) {}
+  void Run() override {
+    while (sampler_->IsProfiling()) {
+      sampler_->DoSample();
+      base::OS::Sleep(base::TimeDelta::FromMilliseconds(interval_));
+    }
+  }
+
+ private:
+  sampler::Sampler* sampler_;
+  const int interval_;
+};
+
+
 // The Profiler samples pc and sp values for the main thread.
 // Each sample is appended to a circular buffer.
 // An independent thread removes data and writes it to the log.
@@ -608,16 +616,16 @@
 // Ticker used to provide ticks to the profiler and the sliding state
 // window.
 //
-class Ticker: public Sampler {
+class Ticker: public sampler::Sampler {
  public:
   Ticker(Isolate* isolate, int interval):
-      Sampler(isolate, interval),
-      profiler_(NULL) {}
+      sampler::Sampler(reinterpret_cast<v8::Isolate*>(isolate)),
+      profiler_(NULL),
+      sampling_thread_(new SamplingThread(this, interval)) {}
 
-  ~Ticker() { if (IsActive()) Stop(); }
-
-  virtual void Tick(TickSample* sample) {
-    if (profiler_) profiler_->Insert(sample);
+  ~Ticker() {
+    if (IsActive()) Stop();
+    delete sampling_thread_;
   }
 
   void SetProfiler(Profiler* profiler) {
@@ -625,16 +633,40 @@
     profiler_ = profiler;
     IncreaseProfilingDepth();
     if (!IsActive()) Start();
+    sampling_thread_->StartSynchronously();
   }
 
   void ClearProfiler() {
     profiler_ = NULL;
     if (IsActive()) Stop();
     DecreaseProfilingDepth();
+    sampling_thread_->Join();
+  }
+
+  void SampleStack(const v8::RegisterState& state) override {
+    v8::Isolate* v8_isolate = isolate();
+    Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
+#if defined(USE_SIMULATOR)
+    SimulatorHelper::FillRegisters(isolate,
+                                   const_cast<v8::RegisterState*>(&state));
+#endif
+    TickSample* sample = isolate->cpu_profiler()->StartTickSample();
+    TickSample sample_obj;
+    if (sample == NULL) sample = &sample_obj;
+    sample->Init(isolate, state, TickSample::kIncludeCEntryFrame, true);
+    if (is_counting_samples_ && !sample->timestamp.IsNull()) {
+      if (sample->state == JS) ++js_sample_count_;
+      if (sample->state == EXTERNAL) ++external_sample_count_;
+    }
+    if (profiler_) profiler_->Insert(sample);
+    if (sample != &sample_obj) {
+      isolate->cpu_profiler()->FinishTickSample();
+    }
   }
 
  private:
   Profiler* profiler_;
+  SamplingThread* sampling_thread_;
 };
 
 
@@ -661,8 +693,9 @@
   std::vector<base::OS::SharedLibraryAddress> addresses =
       base::OS::GetSharedLibraryAddresses();
   for (size_t i = 0; i < addresses.size(); ++i) {
-    LOG(isolate_, SharedLibraryEvent(
-        addresses[i].library_path, addresses[i].start, addresses[i].end));
+    LOG(isolate_,
+        SharedLibraryEvent(addresses[i].library_path, addresses[i].start,
+                           addresses[i].end, addresses[i].aslr_slide));
   }
 
   // Start thread processing the profiler buffer.
@@ -729,24 +762,16 @@
   delete log_;
 }
 
-
 void Logger::addCodeEventListener(CodeEventListener* listener) {
-  DCHECK(!hasCodeEventListener(listener));
-  listeners_.Add(listener);
+  bool result = isolate_->code_event_dispatcher()->AddListener(listener);
+  USE(result);
+  DCHECK(result);
 }
 
-
 void Logger::removeCodeEventListener(CodeEventListener* listener) {
-  DCHECK(hasCodeEventListener(listener));
-  listeners_.RemoveElement(listener);
+  isolate_->code_event_dispatcher()->RemoveListener(listener);
 }
 
-
-bool Logger::hasCodeEventListener(CodeEventListener* listener) {
-  return listeners_.Contains(listener);
-}
-
-
 void Logger::ProfilerBeginEvent() {
   if (!log_->IsEnabled()) return;
   Log::MessageBuilder msg(log_);
@@ -789,7 +814,7 @@
 void Logger::UncheckedIntPtrTEvent(const char* name, intptr_t value) {
   if (!log_->IsEnabled()) return;
   Log::MessageBuilder msg(log_);
-  msg.Append("%s,%" V8_PTR_PREFIX "d", name, value);
+  msg.Append("%s,%" V8PRIdPTR, name, value);
   msg.WriteToLogFile();
 }
 
@@ -797,7 +822,7 @@
 void Logger::HandleEvent(const char* name, Object** location) {
   if (!log_->IsEnabled() || !FLAG_log_handles) return;
   Log::MessageBuilder msg(log_);
-  msg.Append("%s,0x%" V8PRIxPTR, name, location);
+  msg.Append("%s,%p", name, static_cast<void*>(location));
   msg.WriteToLogFile();
 }
 
@@ -821,24 +846,23 @@
   ApiEvent("api,check-security");
 }
 
-
 void Logger::SharedLibraryEvent(const std::string& library_path,
-                                uintptr_t start,
-                                uintptr_t end) {
+                                uintptr_t start, uintptr_t end,
+                                intptr_t aslr_slide) {
   if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
   Log::MessageBuilder msg(log_);
-  msg.Append("shared-library,\"%s\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR,
-             library_path.c_str(), start, end);
+  msg.Append("shared-library,\"%s\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR
+             ",%" V8PRIdPTR,
+             library_path.c_str(), start, end, aslr_slide);
   msg.WriteToLogFile();
 }
 
 
 void Logger::CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta) {
-  PROFILER_LOG(CodeDeoptEvent(code, pc, fp_to_sp_delta));
   if (!log_->IsEnabled() || !FLAG_log_internal_timer_events) return;
   Log::MessageBuilder msg(log_);
   int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
-  msg.Append("code-deopt,%ld,%d", since_epoch, code->CodeSize());
+  msg.Append("code-deopt,%d,%d", since_epoch, code->CodeSize());
   msg.WriteToLogFile();
 }
 
@@ -848,7 +872,7 @@
   DCHECK(FLAG_log_timer_events || FLAG_prof_cpp);
   Log::MessageBuilder msg(log_);
   int since_epoch = static_cast<int>(timer_.Elapsed().InMicroseconds());
-  msg.Append("current-time,%ld", since_epoch);
+  msg.Append("current-time,%d", since_epoch);
   msg.WriteToLogFile();
 }
 
@@ -922,19 +946,19 @@
   // global flag
   Handle<Object> global =
       JSReceiver::GetProperty(isolate, regexp, "global").ToHandleChecked();
-  if (global->IsTrue()) {
+  if (global->IsTrue(isolate)) {
     msg->Append('g');
   }
   // ignorecase flag
   Handle<Object> ignorecase =
       JSReceiver::GetProperty(isolate, regexp, "ignoreCase").ToHandleChecked();
-  if (ignorecase->IsTrue()) {
+  if (ignorecase->IsTrue(isolate)) {
     msg->Append('i');
   }
   // multiline flag
   Handle<Object> multiline =
       JSReceiver::GetProperty(isolate, regexp, "multiline").ToHandleChecked();
-  if (multiline->IsTrue()) {
+  if (multiline->IsTrue(isolate)) {
     msg->Append('m');
   }
 }
@@ -967,7 +991,7 @@
   } else {
     Symbol* symbol = Symbol::cast(name);
     uint32_t hash = symbol->Hash();
-    if (symbol->name()->IsUndefined()) {
+    if (symbol->name()->IsUndefined(symbol->GetIsolate())) {
       ApiEvent("api,%s,\"%s\",symbol(hash %x)", tag, class_name.get(), hash);
     } else {
       base::SmartArrayPointer<char> str =
@@ -1008,8 +1032,7 @@
 void Logger::NewEvent(const char* name, void* object, size_t size) {
   if (!log_->IsEnabled() || !FLAG_log) return;
   Log::MessageBuilder msg(log_);
-  msg.Append("new,%s,0x%" V8PRIxPTR ",%u", name, object,
-             static_cast<unsigned int>(size));
+  msg.Append("new,%s,%p,%u", name, object, static_cast<unsigned int>(size));
   msg.WriteToLogFile();
 }
 
@@ -1017,7 +1040,7 @@
 void Logger::DeleteEvent(const char* name, void* object) {
   if (!log_->IsEnabled() || !FLAG_log) return;
   Log::MessageBuilder msg(log_);
-  msg.Append("delete,%s,0x%" V8PRIxPTR, name, object);
+  msg.Append("delete,%s,%p", name, object);
   msg.WriteToLogFile();
 }
 
@@ -1027,8 +1050,8 @@
   if (!FLAG_log_code || !log_->IsEnabled()) return;
   Log::MessageBuilder msg(log_);
   msg.Append("%s,%s,-2,",
-             kLogEventsNames[CODE_CREATION_EVENT],
-             kLogEventsNames[CALLBACK_TAG]);
+             kLogEventsNames[CodeEventListener::CODE_CREATION_EVENT],
+             kLogEventsNames[CodeEventListener::CALLBACK_TAG]);
   msg.AppendAddress(entry_point);
   if (name->IsString()) {
     base::SmartArrayPointer<char> str =
@@ -1036,13 +1059,13 @@
     msg.Append(",1,\"%s%s\"", prefix, str.get());
   } else {
     Symbol* symbol = Symbol::cast(name);
-    if (symbol->name()->IsUndefined()) {
-      msg.Append(",1,symbol(hash %x)", prefix, symbol->Hash());
+    if (symbol->name()->IsUndefined(symbol->GetIsolate())) {
+      msg.Append(",1,symbol(hash %x)", symbol->Hash());
     } else {
       base::SmartArrayPointer<char> str =
           String::cast(symbol->name())
               ->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
-      msg.Append(",1,symbol(\"%s\" hash %x)", prefix, str.get(),
+      msg.Append(",1,symbol(\"%s%s\" hash %x)", prefix, str.get(),
                  symbol->Hash());
     }
   }
@@ -1051,41 +1074,33 @@
 
 
 void Logger::CallbackEvent(Name* name, Address entry_point) {
-  PROFILER_LOG(CallbackEvent(name, entry_point));
   CallbackEventInternal("", name, entry_point);
 }
 
 
 void Logger::GetterCallbackEvent(Name* name, Address entry_point) {
-  PROFILER_LOG(GetterCallbackEvent(name, entry_point));
   CallbackEventInternal("get ", name, entry_point);
 }
 
 
 void Logger::SetterCallbackEvent(Name* name, Address entry_point) {
-  PROFILER_LOG(SetterCallbackEvent(name, entry_point));
   CallbackEventInternal("set ", name, entry_point);
 }
 
 static void AppendCodeCreateHeader(Log::MessageBuilder* msg,
-                                   Logger::LogEventsAndTags tag,
+                                   CodeEventListener::LogEventsAndTags tag,
                                    AbstractCode* code) {
   DCHECK(msg);
   msg->Append("%s,%s,%d,",
-              kLogEventsNames[Logger::CODE_CREATION_EVENT],
-              kLogEventsNames[tag],
-              code->kind());
+              kLogEventsNames[CodeEventListener::CODE_CREATION_EVENT],
+              kLogEventsNames[tag], code->kind());
   msg->AppendAddress(code->address());
   msg->Append(",%d,", code->ExecutableSize());
 }
 
-void Logger::CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
-                             const char* comment) {
-  PROFILER_LOG(CodeCreateEvent(tag, code, comment));
-
+void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                             AbstractCode* code, const char* comment) {
   if (!is_logging_code_events()) return;
-  CALL_LISTENERS(CodeCreateEvent(tag, code, comment));
-
   if (!FLAG_log_code || !log_->IsEnabled()) return;
   Log::MessageBuilder msg(log_);
   AppendCodeCreateHeader(&msg, tag, code);
@@ -1093,13 +1108,9 @@
   msg.WriteToLogFile();
 }
 
-void Logger::CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
-                             Name* name) {
-  PROFILER_LOG(CodeCreateEvent(tag, code, name));
-
+void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                             AbstractCode* code, Name* name) {
   if (!is_logging_code_events()) return;
-  CALL_LISTENERS(CodeCreateEvent(tag, code, name));
-
   if (!FLAG_log_code || !log_->IsEnabled()) return;
   Log::MessageBuilder msg(log_);
   AppendCodeCreateHeader(&msg, tag, code);
@@ -1113,14 +1124,10 @@
   msg.WriteToLogFile();
 }
 
-void Logger::CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
-                             SharedFunctionInfo* shared, CompilationInfo* info,
+void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                             AbstractCode* code, SharedFunctionInfo* shared,
                              Name* name) {
-  PROFILER_LOG(CodeCreateEvent(tag, code, shared, info, name));
-
   if (!is_logging_code_events()) return;
-  CALL_LISTENERS(CodeCreateEvent(tag, code, shared, info, name));
-
   if (!FLAG_log_code || !log_->IsEnabled()) return;
   if (code == AbstractCode::cast(
                   isolate_->builtins()->builtin(Builtins::kCompileLazy))) {
@@ -1146,15 +1153,10 @@
 // Although, it is possible to extract source and line from
 // the SharedFunctionInfo object, we left it to caller
 // to leave logging functions free from heap allocations.
-void Logger::CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
-                             SharedFunctionInfo* shared, CompilationInfo* info,
+void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                             AbstractCode* code, SharedFunctionInfo* shared,
                              Name* source, int line, int column) {
-  PROFILER_LOG(CodeCreateEvent(tag, code, shared, info, source, line, column));
-
   if (!is_logging_code_events()) return;
-  CALL_LISTENERS(CodeCreateEvent(tag, code, shared, info, source, line,
-                                 column));
-
   if (!FLAG_log_code || !log_->IsEnabled()) return;
   Log::MessageBuilder msg(log_);
   AppendCodeCreateHeader(&msg, tag, code);
@@ -1174,13 +1176,9 @@
   msg.WriteToLogFile();
 }
 
-void Logger::CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
-                             int args_count) {
-  PROFILER_LOG(CodeCreateEvent(tag, code, args_count));
-
+void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                             AbstractCode* code, int args_count) {
   if (!is_logging_code_events()) return;
-  CALL_LISTENERS(CodeCreateEvent(tag, code, args_count));
-
   if (!FLAG_log_code || !log_->IsEnabled()) return;
   Log::MessageBuilder msg(log_);
   AppendCodeCreateHeader(&msg, tag, code);
@@ -1190,14 +1188,10 @@
 
 void Logger::CodeDisableOptEvent(AbstractCode* code,
                                  SharedFunctionInfo* shared) {
-  PROFILER_LOG(CodeDisableOptEvent(code, shared));
-
   if (!is_logging_code_events()) return;
-  CALL_LISTENERS(CodeDisableOptEvent(code, shared));
-
   if (!FLAG_log_code || !log_->IsEnabled()) return;
   Log::MessageBuilder msg(log_);
-  msg.Append("%s,", kLogEventsNames[CODE_DISABLE_OPT_EVENT]);
+  msg.Append("%s,", kLogEventsNames[CodeEventListener::CODE_DISABLE_OPT_EVENT]);
   base::SmartArrayPointer<char> name =
       shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
   msg.Append("\"%s\",", name.get());
@@ -1207,23 +1201,16 @@
 
 
 void Logger::CodeMovingGCEvent() {
-  PROFILER_LOG(CodeMovingGCEvent());
-
   if (!is_logging_code_events()) return;
   if (!log_->IsEnabled() || !FLAG_ll_prof) return;
-  CALL_LISTENERS(CodeMovingGCEvent());
   base::OS::SignalCodeMovingGC();
 }
 
 void Logger::RegExpCodeCreateEvent(AbstractCode* code, String* source) {
-  PROFILER_LOG(RegExpCodeCreateEvent(code, source));
-
   if (!is_logging_code_events()) return;
-  CALL_LISTENERS(RegExpCodeCreateEvent(code, source));
-
   if (!FLAG_log_code || !log_->IsEnabled()) return;
   Log::MessageBuilder msg(log_);
-  AppendCodeCreateHeader(&msg, REG_EXP_TAG, code);
+  AppendCodeCreateHeader(&msg, CodeEventListener::REG_EXP_TAG, code);
   msg.Append('"');
   msg.AppendDetailed(source, false);
   msg.Append('"');
@@ -1231,11 +1218,8 @@
 }
 
 void Logger::CodeMoveEvent(AbstractCode* from, Address to) {
-  PROFILER_LOG(CodeMoveEvent(from, to));
-
   if (!is_logging_code_events()) return;
-  CALL_LISTENERS(CodeMoveEvent(from, to));
-  MoveEventInternal(CODE_MOVE_EVENT, from->address(), to);
+  MoveEventInternal(CodeEventListener::CODE_MOVE_EVENT, from->address(), to);
 }
 
 void Logger::CodeLinePosInfoAddPositionEvent(void* jit_handler_data,
@@ -1272,7 +1256,8 @@
 void Logger::CodeNameEvent(Address addr, int pos, const char* code_name) {
   if (code_name == NULL) return;  // Not a code object.
   Log::MessageBuilder msg(log_);
-  msg.Append("%s,%d,", kLogEventsNames[SNAPSHOT_CODE_NAME_EVENT], pos);
+  msg.Append("%s,%d,",
+             kLogEventsNames[CodeEventListener::SNAPSHOT_CODE_NAME_EVENT], pos);
   msg.AppendDoubleQuotedString(code_name);
   msg.WriteToLogFile();
 }
@@ -1280,13 +1265,11 @@
 
 void Logger::SharedFunctionInfoMoveEvent(Address from, Address to) {
   if (!is_logging_code_events()) return;
-  MoveEventInternal(SHARED_FUNC_MOVE_EVENT, from, to);
+  MoveEventInternal(CodeEventListener::SHARED_FUNC_MOVE_EVENT, from, to);
 }
 
-
-void Logger::MoveEventInternal(LogEventsAndTags event,
-                               Address from,
-                               Address to) {
+void Logger::MoveEventInternal(CodeEventListener::LogEventsAndTags event,
+                               Address from, Address to) {
   if (!FLAG_log_code || !log_->IsEnabled()) return;
   Log::MessageBuilder msg(log_);
   msg.Append("%s,", kLogEventsNames[event]);
@@ -1380,13 +1363,27 @@
   msg.WriteToLogFile();
 }
 
+void Logger::RuntimeCallTimerEvent() {
+  RuntimeCallStats* stats = isolate_->counters()->runtime_call_stats();
+  RuntimeCallTimer* timer = stats->current_timer();
+  if (timer == nullptr) return;
+  RuntimeCallCounter* counter = timer->counter();
+  if (counter == nullptr) return;
+  Log::MessageBuilder msg(log_);
+  msg.Append("active-runtime-timer,");
+  msg.AppendDoubleQuotedString(counter->name);
+  msg.WriteToLogFile();
+}
 
 void Logger::TickEvent(TickSample* sample, bool overflow) {
   if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
+  if (FLAG_runtime_call_stats) {
+    RuntimeCallTimerEvent();
+  }
   Log::MessageBuilder msg(log_);
-  msg.Append("%s,", kLogEventsNames[TICK_EVENT]);
+  msg.Append("%s,", kLogEventsNames[CodeEventListener::TICK_EVENT]);
   msg.AppendAddress(sample->pc);
-  msg.Append(",%ld", static_cast<int>(timer_.Elapsed().InMicroseconds()));
+  msg.Append(",%d", static_cast<int>(timer_.Elapsed().InMicroseconds()));
   if (sample->has_external_callback) {
     msg.Append(",1,");
     msg.AppendAddress(sample->external_callback_entry);
@@ -1411,6 +1408,7 @@
   if (profiler_ != NULL) {
     profiler_->pause();
     is_logging_ = false;
+    removeCodeEventListener(this);
   }
 }
 
@@ -1492,7 +1490,7 @@
 
 void Logger::LogCodeObject(Object* object) {
   AbstractCode* code_object = AbstractCode::cast(object);
-  LogEventsAndTags tag = Logger::STUB_TAG;
+  CodeEventListener::LogEventsAndTags tag = CodeEventListener::STUB_TAG;
   const char* description = "Unknown code from the snapshot";
   switch (code_object->kind()) {
     case AbstractCode::FUNCTION:
@@ -1510,53 +1508,59 @@
           CodeStub::MajorName(CodeStub::GetMajorKey(code_object->GetCode()));
       if (description == NULL)
         description = "A stub from the snapshot";
-      tag = Logger::STUB_TAG;
+      tag = CodeEventListener::STUB_TAG;
       break;
     case AbstractCode::REGEXP:
       description = "Regular expression code";
-      tag = Logger::REG_EXP_TAG;
+      tag = CodeEventListener::REG_EXP_TAG;
       break;
     case AbstractCode::BUILTIN:
       description =
           isolate_->builtins()->name(code_object->GetCode()->builtin_index());
-      tag = Logger::BUILTIN_TAG;
+      tag = CodeEventListener::BUILTIN_TAG;
       break;
     case AbstractCode::HANDLER:
       description = "An IC handler from the snapshot";
-      tag = Logger::HANDLER_TAG;
+      tag = CodeEventListener::HANDLER_TAG;
       break;
     case AbstractCode::KEYED_LOAD_IC:
       description = "A keyed load IC from the snapshot";
-      tag = Logger::KEYED_LOAD_IC_TAG;
+      tag = CodeEventListener::KEYED_LOAD_IC_TAG;
       break;
     case AbstractCode::LOAD_IC:
       description = "A load IC from the snapshot";
-      tag = Logger::LOAD_IC_TAG;
+      tag = CodeEventListener::LOAD_IC_TAG;
+      break;
+    case AbstractCode::LOAD_GLOBAL_IC:
+      description = "A load global IC from the snapshot";
+      tag = Logger::LOAD_GLOBAL_IC_TAG;
       break;
     case AbstractCode::CALL_IC:
       description = "A call IC from the snapshot";
-      tag = Logger::CALL_IC_TAG;
+      tag = CodeEventListener::CALL_IC_TAG;
       break;
     case AbstractCode::STORE_IC:
       description = "A store IC from the snapshot";
-      tag = Logger::STORE_IC_TAG;
+      tag = CodeEventListener::STORE_IC_TAG;
       break;
     case AbstractCode::KEYED_STORE_IC:
       description = "A keyed store IC from the snapshot";
-      tag = Logger::KEYED_STORE_IC_TAG;
+      tag = CodeEventListener::KEYED_STORE_IC_TAG;
       break;
     case AbstractCode::WASM_FUNCTION:
       description = "A Wasm function";
-      tag = Logger::STUB_TAG;
+      tag = CodeEventListener::STUB_TAG;
       break;
     case AbstractCode::JS_TO_WASM_FUNCTION:
       description = "A JavaScript to Wasm adapter";
-      tag = Logger::STUB_TAG;
+      tag = CodeEventListener::STUB_TAG;
       break;
     case AbstractCode::WASM_TO_JS_FUNCTION:
       description = "A Wasm to JavaScript adapter";
-      tag = Logger::STUB_TAG;
+      tag = CodeEventListener::STUB_TAG;
       break;
+    case AbstractCode::NUMBER_OF_KINDS:
+      UNIMPLEMENTED();
   }
   PROFILE(isolate_, CodeCreateEvent(tag, code_object, description));
 }
@@ -1577,20 +1581,24 @@
 void Logger::LogBytecodeHandlers() {
   if (!FLAG_ignition) return;
 
-  interpreter::Interpreter* interpreter = isolate_->interpreter();
+  const interpreter::OperandScale kOperandScales[] = {
+#define VALUE(Name, _) interpreter::OperandScale::k##Name,
+      OPERAND_SCALE_LIST(VALUE)
+#undef VALUE
+  };
+
   const int last_index = static_cast<int>(interpreter::Bytecode::kLast);
-  for (auto operand_scale = interpreter::OperandScale::kSingle;
-       operand_scale <= interpreter::OperandScale::kMaxValid;
-       operand_scale =
-           interpreter::Bytecodes::NextOperandScale(operand_scale)) {
+  interpreter::Interpreter* interpreter = isolate_->interpreter();
+  for (auto operand_scale : kOperandScales) {
     for (int index = 0; index <= last_index; ++index) {
       interpreter::Bytecode bytecode = interpreter::Bytecodes::FromByte(index);
       if (interpreter::Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) {
         Code* code = interpreter->GetBytecodeHandler(bytecode, operand_scale);
         std::string bytecode_name =
             interpreter::Bytecodes::ToString(bytecode, operand_scale);
-        CodeCreateEvent(Logger::BYTECODE_HANDLER_TAG, AbstractCode::cast(code),
-                        bytecode_name.c_str());
+        PROFILE(isolate_, CodeCreateEvent(
+                              CodeEventListener::BYTECODE_HANDLER_TAG,
+                              AbstractCode::cast(code), bytecode_name.c_str()));
       }
     }
   }
@@ -1609,28 +1617,28 @@
       if (line_num > 0) {
         PROFILE(isolate_,
                 CodeCreateEvent(
-                    Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
-                    *code, *shared, NULL,
-                    *script_name, line_num, column_num));
+                    Logger::ToNativeByScript(
+                        CodeEventListener::LAZY_COMPILE_TAG, *script),
+                    *code, *shared, *script_name, line_num, column_num));
       } else {
         // Can't distinguish eval and script here, so always use Script.
         PROFILE(isolate_,
-                CodeCreateEvent(
-                    Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
-                    *code, *shared, NULL, *script_name));
+                CodeCreateEvent(Logger::ToNativeByScript(
+                                    CodeEventListener::SCRIPT_TAG, *script),
+                                *code, *shared, *script_name));
       }
     } else {
       PROFILE(isolate_,
-              CodeCreateEvent(
-                  Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
-                  *code, *shared, NULL,
-                  isolate_->heap()->empty_string(), line_num, column_num));
+              CodeCreateEvent(Logger::ToNativeByScript(
+                                  CodeEventListener::LAZY_COMPILE_TAG, *script),
+                              *code, *shared, isolate_->heap()->empty_string(),
+                              line_num, column_num));
     }
   } else if (shared->IsApiFunction()) {
     // API function.
     FunctionTemplateInfo* fun_data = shared->get_api_func_data();
     Object* raw_call_data = fun_data->call_code();
-    if (!raw_call_data->IsUndefined()) {
+    if (!raw_call_data->IsUndefined(isolate_)) {
       CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
       Object* callback_obj = call_data->callback();
       Address entry_point = v8::ToCData<Address>(callback_obj);
@@ -1640,9 +1648,8 @@
       PROFILE(isolate_, CallbackEvent(*func_name, entry_point));
     }
   } else {
-    PROFILE(isolate_,
-            CodeCreateEvent(
-                Logger::LAZY_COMPILE_TAG, *code, *shared, NULL, *func_name));
+    PROFILE(isolate_, CodeCreateEvent(CodeEventListener::LAZY_COMPILE_TAG,
+                                      *code, *shared, *func_name));
   }
 }
 
@@ -1755,7 +1762,6 @@
   PrepareLogFileName(log_file_name, isolate, FLAG_logfile);
   log_->Initialize(log_file_name.str().c_str());
 
-
   if (FLAG_perf_basic_prof) {
     perf_basic_logger_ = new PerfBasicLogger();
     addCodeEventListener(perf_basic_logger_);
@@ -1785,6 +1791,12 @@
     profiler_->Engage();
   }
 
+  profiler_listener_.reset();
+
+  if (is_logging_) {
+    addCodeEventListener(this);
+  }
+
   return true;
 }
 
@@ -1808,8 +1820,20 @@
   }
 }
 
+void Logger::SetUpProfilerListener() {
+  if (!is_initialized_) return;
+  if (profiler_listener_.get() == nullptr) {
+    profiler_listener_.reset(new ProfilerListener(isolate_));
+  }
+  addCodeEventListener(profiler_listener_.get());
+}
 
-Sampler* Logger::sampler() {
+void Logger::TearDownProfilerListener() {
+  if (profiler_listener_->HasObservers()) return;
+  removeCodeEventListener(profiler_listener_.get());
+}
+
+sampler::Sampler* Logger::sampler() {
   return ticker_;
 }
 
@@ -1852,6 +1876,10 @@
     jit_logger_ = NULL;
   }
 
+  if (profiler_listener_.get() != nullptr) {
+    removeCodeEventListener(profiler_listener_.get());
+  }
+
   return log_->Close();
 }
 
diff --git a/src/log.h b/src/log.h
index fdc5047..303e352 100644
--- a/src/log.h
+++ b/src/log.h
@@ -8,8 +8,11 @@
 #include <string>
 
 #include "src/allocation.h"
+#include "src/base/compiler-specific.h"
 #include "src/base/platform/elapsed-timer.h"
 #include "src/base/platform/platform.h"
+#include "src/code-events.h"
+#include "src/isolate.h"
 #include "src/objects.h"
 
 namespace v8 {
@@ -18,6 +21,10 @@
 class Semaphore;
 }
 
+namespace sampler {
+class Sampler;
+}
+
 namespace internal {
 
 // Logger is used for collecting logging information from V8 during
@@ -56,7 +63,6 @@
 
 // Forward declarations.
 class CodeEventListener;
-class CompilationInfo;
 class CpuProfiler;
 class Isolate;
 class Log;
@@ -64,100 +70,31 @@
 class Profiler;
 class Ticker;
 struct TickSample;
+class RuntimeCallTimer;
 
 #undef LOG
-#define LOG(isolate, Call)                          \
-  do {                                              \
-    v8::internal::Logger* logger =                  \
-        (isolate)->logger();                        \
-    if (logger->is_logging())                       \
-      logger->Call;                                 \
+#define LOG(isolate, Call)                              \
+  do {                                                  \
+    v8::internal::Logger* logger = (isolate)->logger(); \
+    if (logger->is_logging()) logger->Call;             \
   } while (false)
 
-#define LOG_CODE_EVENT(isolate, Call)               \
-  do {                                              \
-    v8::internal::Logger* logger =                  \
-        (isolate)->logger();                        \
-    if (logger->is_logging_code_events())           \
-      logger->Call;                                 \
+#define LOG_CODE_EVENT(isolate, Call)                   \
+  do {                                                  \
+    v8::internal::Logger* logger = (isolate)->logger(); \
+    if (logger->is_logging_code_events()) logger->Call; \
   } while (false)
 
-#define LOG_EVENTS_AND_TAGS_LIST(V)                                      \
-  V(CODE_CREATION_EVENT, "code-creation")                                \
-  V(CODE_DISABLE_OPT_EVENT, "code-disable-optimization")                 \
-  V(CODE_MOVE_EVENT, "code-move")                                        \
-  V(CODE_DELETE_EVENT, "code-delete")                                    \
-  V(CODE_MOVING_GC, "code-moving-gc")                                    \
-  V(SHARED_FUNC_MOVE_EVENT, "sfi-move")                                  \
-  V(SNAPSHOT_CODE_NAME_EVENT, "snapshot-code-name")                      \
-  V(TICK_EVENT, "tick")                                                  \
-  V(REPEAT_META_EVENT, "repeat")                                         \
-  V(BUILTIN_TAG, "Builtin")                                              \
-  V(CALL_DEBUG_BREAK_TAG, "CallDebugBreak")                              \
-  V(CALL_DEBUG_PREPARE_STEP_IN_TAG, "CallDebugPrepareStepIn")            \
-  V(CALL_INITIALIZE_TAG, "CallInitialize")                               \
-  V(CALL_MEGAMORPHIC_TAG, "CallMegamorphic")                             \
-  V(CALL_MISS_TAG, "CallMiss")                                           \
-  V(CALL_NORMAL_TAG, "CallNormal")                                       \
-  V(CALL_PRE_MONOMORPHIC_TAG, "CallPreMonomorphic")                      \
-  V(LOAD_INITIALIZE_TAG, "LoadInitialize")                               \
-  V(LOAD_PREMONOMORPHIC_TAG, "LoadPreMonomorphic")                       \
-  V(LOAD_MEGAMORPHIC_TAG, "LoadMegamorphic")                             \
-  V(STORE_INITIALIZE_TAG, "StoreInitialize")                             \
-  V(STORE_PREMONOMORPHIC_TAG, "StorePreMonomorphic")                     \
-  V(STORE_GENERIC_TAG, "StoreGeneric")                                   \
-  V(STORE_MEGAMORPHIC_TAG, "StoreMegamorphic")                           \
-  V(KEYED_CALL_DEBUG_BREAK_TAG, "KeyedCallDebugBreak")                   \
-  V(KEYED_CALL_DEBUG_PREPARE_STEP_IN_TAG, "KeyedCallDebugPrepareStepIn") \
-  V(KEYED_CALL_INITIALIZE_TAG, "KeyedCallInitialize")                    \
-  V(KEYED_CALL_MEGAMORPHIC_TAG, "KeyedCallMegamorphic")                  \
-  V(KEYED_CALL_MISS_TAG, "KeyedCallMiss")                                \
-  V(KEYED_CALL_NORMAL_TAG, "KeyedCallNormal")                            \
-  V(KEYED_CALL_PRE_MONOMORPHIC_TAG, "KeyedCallPreMonomorphic")           \
-  V(CALLBACK_TAG, "Callback")                                            \
-  V(EVAL_TAG, "Eval")                                                    \
-  V(FUNCTION_TAG, "Function")                                            \
-  V(HANDLER_TAG, "Handler")                                              \
-  V(BYTECODE_HANDLER_TAG, "BytecodeHandler")                             \
-  V(KEYED_LOAD_IC_TAG, "KeyedLoadIC")                                    \
-  V(KEYED_LOAD_POLYMORPHIC_IC_TAG, "KeyedLoadPolymorphicIC")             \
-  V(KEYED_EXTERNAL_ARRAY_LOAD_IC_TAG, "KeyedExternalArrayLoadIC")        \
-  V(KEYED_STORE_IC_TAG, "KeyedStoreIC")                                  \
-  V(KEYED_STORE_POLYMORPHIC_IC_TAG, "KeyedStorePolymorphicIC")           \
-  V(KEYED_EXTERNAL_ARRAY_STORE_IC_TAG, "KeyedExternalArrayStoreIC")      \
-  V(LAZY_COMPILE_TAG, "LazyCompile")                                     \
-  V(CALL_IC_TAG, "CallIC")                                               \
-  V(LOAD_IC_TAG, "LoadIC")                                               \
-  V(LOAD_POLYMORPHIC_IC_TAG, "LoadPolymorphicIC")                        \
-  V(REG_EXP_TAG, "RegExp")                                               \
-  V(SCRIPT_TAG, "Script")                                                \
-  V(STORE_IC_TAG, "StoreIC")                                             \
-  V(STORE_POLYMORPHIC_IC_TAG, "StorePolymorphicIC")                      \
-  V(STUB_TAG, "Stub")                                                    \
-  V(NATIVE_FUNCTION_TAG, "Function")                                     \
-  V(NATIVE_LAZY_COMPILE_TAG, "LazyCompile")                              \
-  V(NATIVE_SCRIPT_TAG, "Script")
-// Note that 'NATIVE_' cases for functions and scripts are mapped onto
-// original tags when writing to the log.
-
-
 class JitLogger;
 class PerfBasicLogger;
 class LowLevelLogger;
 class PerfJitLogger;
-class Sampler;
+class ProfilerListener;
 
-class Logger {
+class Logger : public CodeEventListener {
  public:
   enum StartEnd { START = 0, END = 1 };
 
-#define DECLARE_ENUM(enum_item, ignore) enum_item,
-  enum LogEventsAndTags {
-    LOG_EVENTS_AND_TAGS_LIST(DECLARE_ENUM)
-    NUMBER_OF_LOG_EVENTS
-  };
-#undef DECLARE_ENUM
-
   // Acquires resources for logging if the right flags are set.
   bool SetUp(Isolate* isolate);
 
@@ -165,7 +102,15 @@
   void SetCodeEventHandler(uint32_t options,
                            JitCodeEventHandler event_handler);
 
-  Sampler* sampler();
+  // Sets up ProfilerListener.
+  void SetUpProfilerListener();
+
+  // Tear down ProfilerListener if it has no observers.
+  void TearDownProfilerListener();
+
+  sampler::Sampler* sampler();
+
+  ProfilerListener* profiler_listener() { return profiler_listener_.get(); }
 
   // Frees resources acquired in SetUp.
   // When a temporary file is used for the log, returns its stream descriptor,
@@ -211,29 +156,27 @@
   void ApiObjectAccess(const char* tag, JSObject* obj);
   void ApiEntryCall(const char* name);
 
-
   // ==== Events logged by --log-code. ====
   void addCodeEventListener(CodeEventListener* listener);
   void removeCodeEventListener(CodeEventListener* listener);
-  bool hasCodeEventListener(CodeEventListener* listener);
-
 
   // Emits a code event for a callback function.
   void CallbackEvent(Name* name, Address entry_point);
   void GetterCallbackEvent(Name* name, Address entry_point);
   void SetterCallbackEvent(Name* name, Address entry_point);
   // Emits a code create event.
-  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
-                       const char* source);
-  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code, Name* name);
-  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
-                       SharedFunctionInfo* shared, CompilationInfo* info,
+  void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                       AbstractCode* code, const char* source);
+  void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                       AbstractCode* code, Name* name);
+  void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                       AbstractCode* code, SharedFunctionInfo* shared,
                        Name* name);
-  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
-                       SharedFunctionInfo* shared, CompilationInfo* info,
+  void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                       AbstractCode* code, SharedFunctionInfo* shared,
                        Name* source, int line, int column);
-  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
-                       int args_count);
+  void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                       AbstractCode* code, int args_count);
   // Emits a code deoptimization event.
   void CodeDisableOptEvent(AbstractCode* code, SharedFunctionInfo* shared);
   void CodeMovingGCEvent();
@@ -260,6 +203,8 @@
 
   void CodeNameEvent(Address addr, int pos, const char* code_name);
 
+  void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta);
+
   // ==== Events logged by --log-gc. ====
   // Heap sampling events: start, end, and individual types.
   void HeapSampleBeginEvent(const char* space, const char* kind);
@@ -274,11 +219,9 @@
   void HeapSampleStats(const char* space, const char* kind,
                        intptr_t capacity, intptr_t used);
 
-  void SharedLibraryEvent(const std::string& library_path,
-                          uintptr_t start,
-                          uintptr_t end);
+  void SharedLibraryEvent(const std::string& library_path, uintptr_t start,
+                          uintptr_t end, intptr_t aslr_slide);
 
-  void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta);
   void CurrentTimeEvent();
 
   void TimerEvent(StartEnd se, const char* name);
@@ -320,7 +263,8 @@
   void LogBytecodeHandlers();
 
   // Converts tag to a corresponding NATIVE_... if the script is native.
-  INLINE(static LogEventsAndTags ToNativeByScript(LogEventsAndTags, Script*));
+  INLINE(static CodeEventListener::LogEventsAndTags ToNativeByScript(
+      CodeEventListener::LogEventsAndTags, Script*));
 
   // Profiler's sampling interval (in milliseconds).
 #if defined(ANDROID)
@@ -347,18 +291,20 @@
                              Address entry_point);
 
   // Internal configurable move event.
-  void MoveEventInternal(LogEventsAndTags event, Address from, Address to);
+  void MoveEventInternal(CodeEventListener::LogEventsAndTags event,
+                         Address from, Address to);
 
   // Used for logging stubs found in the snapshot.
   void LogCodeObject(Object* code_object);
 
   // Helper method. It resets name_buffer_ and add tag name into it.
-  void InitNameBuffer(LogEventsAndTags tag);
+  void InitNameBuffer(CodeEventListener::LogEventsAndTags tag);
 
   // Emits a profiler tick event. Used by the profiler thread.
   void TickEvent(TickSample* sample, bool overflow);
+  void RuntimeCallTimerEvent();
 
-  void ApiEvent(const char* name, ...);
+  PRINTF_FORMAT(2, 3) void ApiEvent(const char* format, ...);
 
   // Logs a StringEvent regardless of whether FLAG_log is true.
   void UncheckedStringEvent(const char* name, const char* value);
@@ -395,6 +341,7 @@
   PerfJitLogger* perf_jit_logger_;
   LowLevelLogger* ll_logger_;
   JitLogger* jit_logger_;
+  std::unique_ptr<ProfilerListener> profiler_listener_;
   List<CodeEventListener*> listeners_;
 
   // Guards against multiple calls to TearDown() that can happen in some tests.
@@ -464,52 +411,22 @@
   DISALLOW_COPY_AND_ASSIGN(PositionsRecorder);
 };
 
-class CodeEventListener {
- public:
-  virtual ~CodeEventListener() {}
-
-  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
-                               const char* comment) = 0;
-  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
-                               Name* name) = 0;
-  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
-                               SharedFunctionInfo* shared,
-                               CompilationInfo* info, Name* name) = 0;
-  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
-                               SharedFunctionInfo* shared,
-                               CompilationInfo* info, Name* source, int line,
-                               int column) = 0;
-  virtual void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
-                               int args_count) = 0;
-  virtual void CallbackEvent(Name* name, Address entry_point) = 0;
-  virtual void GetterCallbackEvent(Name* name, Address entry_point) = 0;
-  virtual void SetterCallbackEvent(Name* name, Address entry_point) = 0;
-  virtual void RegExpCodeCreateEvent(AbstractCode* code, String* source) = 0;
-  virtual void CodeMoveEvent(AbstractCode* from, Address to) = 0;
-  virtual void SharedFunctionInfoMoveEvent(Address from, Address to) = 0;
-  virtual void CodeMovingGCEvent() = 0;
-  virtual void CodeDisableOptEvent(AbstractCode* code,
-                                   SharedFunctionInfo* shared) = 0;
-};
-
-
 class CodeEventLogger : public CodeEventListener {
  public:
   CodeEventLogger();
   ~CodeEventLogger() override;
 
-  void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
+  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
                        const char* comment) override;
-  void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
+  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
                        Name* name) override;
-  void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
+  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
                        int args_count) override;
-  void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
-                       SharedFunctionInfo* shared, CompilationInfo* info,
-                       Name* name) override;
-  void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
-                       SharedFunctionInfo* shared, CompilationInfo* info,
-                       Name* source, int line, int column) override;
+  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
+                       SharedFunctionInfo* shared, Name* name) override;
+  void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
+                       SharedFunctionInfo* shared, Name* source, int line,
+                       int column) override;
   void RegExpCodeCreateEvent(AbstractCode* code, String* source) override;
 
   void CallbackEvent(Name* name, Address entry_point) override {}
@@ -517,6 +434,7 @@
   void SetterCallbackEvent(Name* name, Address entry_point) override {}
   void SharedFunctionInfoMoveEvent(Address from, Address to) override {}
   void CodeMovingGCEvent() override {}
+  void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta) override {}
 
  private:
   class NameBuffer;
diff --git a/src/lookup.cc b/src/lookup.cc
index 3df8752..8e545f7 100644
--- a/src/lookup.cc
+++ b/src/lookup.cc
@@ -131,7 +131,7 @@
     return result;
   }
   auto root = handle(receiver->GetRootMap(isolate)->prototype(), isolate);
-  if (root->IsNull()) {
+  if (root->IsNull(isolate)) {
     unsigned int magic = 0xbbbbbbbb;
     isolate->PushStackTraceAndDie(magic, *receiver, NULL, magic);
   }
@@ -158,47 +158,42 @@
   DCHECK(IsFound() || !holder_->HasFastProperties());
 }
 
-bool LookupIterator::HolderIsInContextIndex(uint32_t index) const {
-  DisallowHeapAllocation no_gc;
-
-  Object* context = heap()->native_contexts_list();
-  while (!context->IsUndefined()) {
-    Context* current_context = Context::cast(context);
-    if (current_context->get(index) == *holder_) {
-      return true;
-    }
-    context = current_context->get(Context::NEXT_CONTEXT_LINK);
-  }
-  return false;
-}
-
 void LookupIterator::InternalUpdateProtector() {
   if (isolate_->bootstrapper()->IsActive()) return;
-  if (!isolate_->IsArraySpeciesLookupChainIntact()) return;
 
   if (*name_ == heap()->constructor_string()) {
+    if (!isolate_->IsArraySpeciesLookupChainIntact()) return;
     // Setting the constructor property could change an instance's @@species
     if (holder_->IsJSArray()) {
       isolate_->CountUsage(
           v8::Isolate::UseCounterFeature::kArrayInstanceConstructorModified);
       isolate_->InvalidateArraySpeciesProtector();
     } else if (holder_->map()->is_prototype_map()) {
+      DisallowHeapAllocation no_gc;
       // Setting the constructor of Array.prototype of any realm also needs
       // to invalidate the species protector
-      if (HolderIsInContextIndex(Context::INITIAL_ARRAY_PROTOTYPE_INDEX)) {
+      if (isolate_->IsInAnyContext(*holder_,
+                                   Context::INITIAL_ARRAY_PROTOTYPE_INDEX)) {
         isolate_->CountUsage(v8::Isolate::UseCounterFeature::
                                  kArrayPrototypeConstructorModified);
         isolate_->InvalidateArraySpeciesProtector();
       }
     }
   } else if (*name_ == heap()->species_symbol()) {
+    if (!isolate_->IsArraySpeciesLookupChainIntact()) return;
     // Setting the Symbol.species property of any Array constructor invalidates
     // the species protector
-    if (HolderIsInContextIndex(Context::ARRAY_FUNCTION_INDEX)) {
+    if (isolate_->IsInAnyContext(*holder_, Context::ARRAY_FUNCTION_INDEX)) {
       isolate_->CountUsage(
           v8::Isolate::UseCounterFeature::kArraySpeciesModified);
       isolate_->InvalidateArraySpeciesProtector();
     }
+  } else if (*name_ == heap()->is_concat_spreadable_symbol()) {
+    if (!isolate_->IsIsConcatSpreadableLookupChainIntact()) return;
+    isolate_->InvalidateIsConcatSpreadableProtector();
+  } else if (*name_ == heap()->has_instance_symbol()) {
+    if (!isolate_->IsHasInstanceLookupChainIntact()) return;
+    isolate_->InvalidateHasInstanceProtector();
   }
 }
 
@@ -304,7 +299,7 @@
       // Install a property cell.
       auto cell = JSGlobalObject::EnsurePropertyCell(
           Handle<JSGlobalObject>::cast(receiver), name());
-      DCHECK(cell->value()->IsTheHole());
+      DCHECK(cell->value()->IsTheHole(isolate_));
       transition_ = cell;
     } else {
       transition_ = map;
@@ -352,9 +347,14 @@
     ElementsAccessor* accessor = object->GetElementsAccessor();
     accessor->Delete(object, number_);
   } else {
-    PropertyNormalizationMode mode = holder->map()->is_prototype_map()
-                                         ? KEEP_INOBJECT_PROPERTIES
-                                         : CLEAR_INOBJECT_PROPERTIES;
+    bool is_prototype_map = holder->map()->is_prototype_map();
+    RuntimeCallTimerScope stats_scope(
+        isolate_, is_prototype_map
+                      ? &RuntimeCallStats::PrototypeObject_DeleteProperty
+                      : &RuntimeCallStats::Object_DeleteProperty);
+
+    PropertyNormalizationMode mode =
+        is_prototype_map ? KEEP_INOBJECT_PROPERTIES : CLEAR_INOBJECT_PROPERTIES;
 
     if (holder->HasFastProperties()) {
       JSObject::NormalizeProperties(Handle<JSObject>::cast(holder), mode, 0,
@@ -370,11 +370,10 @@
   state_ = NOT_FOUND;
 }
 
-
 void LookupIterator::TransitionToAccessorProperty(
-    AccessorComponent component, Handle<Object> accessor,
+    Handle<Object> getter, Handle<Object> setter,
     PropertyAttributes attributes) {
-  DCHECK(!accessor->IsNull());
+  DCHECK(!getter->IsNull(isolate_) || !setter->IsNull(isolate_));
   // Can only be called when the receiver is a JSObject. JSProxy has to be
   // handled via a trap. Adding properties to primitive values is not
   // observable.
@@ -393,7 +392,7 @@
         IsFound() ? static_cast<int>(number_) : DescriptorArray::kNotFound;
 
     Handle<Map> new_map = Map::TransitionToAccessorProperty(
-        old_map, name_, descriptor, component, accessor, attributes);
+        isolate_, old_map, name_, descriptor, getter, setter, attributes);
     bool simple_transition = new_map->GetBackPointer() == receiver->map();
     JSObject::MigrateToMap(receiver, new_map);
 
@@ -413,15 +412,18 @@
   if (state() == ACCESSOR && GetAccessors()->IsAccessorPair()) {
     pair = Handle<AccessorPair>::cast(GetAccessors());
     // If the component and attributes are identical, nothing has to be done.
-    if (pair->get(component) == *accessor) {
-      if (property_details().attributes() == attributes) return;
+    if (pair->Equals(*getter, *setter)) {
+      if (property_details().attributes() == attributes) {
+        if (!IsElement()) JSObject::ReoptimizeIfPrototype(receiver);
+        return;
+      }
     } else {
       pair = AccessorPair::Copy(pair);
-      pair->set(component, *accessor);
+      pair->SetComponents(*getter, *setter);
     }
   } else {
     pair = factory()->NewAccessorPair();
-    pair->set(component, *accessor);
+    pair->SetComponents(*getter, *setter);
   }
 
   TransitionToAccessorPair(pair, attributes);
@@ -494,8 +496,7 @@
   if (!current->map()->has_hidden_prototype()) return false;
   // JSProxy do not occur as hidden prototypes.
   if (object->IsJSProxy()) return false;
-  PrototypeIterator iter(isolate(), current,
-                         PrototypeIterator::START_AT_PROTOTYPE,
+  PrototypeIterator iter(isolate(), current, kStartAtPrototype,
                          PrototypeIterator::END_AT_NON_HIDDEN);
   while (!iter.IsAtEnd()) {
     if (iter.GetCurrent<JSReceiver>() == object) return true;
@@ -638,17 +639,7 @@
 JSReceiver* LookupIterator::NextHolder(Map* map) {
   DisallowHeapAllocation no_gc;
   if (map->prototype() == heap()->null_value()) return NULL;
-
-  DCHECK(!map->IsJSGlobalProxyMap() || map->has_hidden_prototype());
-
-  if (!check_prototype_chain() &&
-      !(check_hidden() && map->has_hidden_prototype()) &&
-      // Always lookup behind the JSGlobalProxy into the JSGlobalObject, even
-      // when not checking other hidden prototypes.
-      !map->IsJSGlobalProxyMap()) {
-    return NULL;
-  }
-
+  if (!check_prototype_chain() && !map->has_hidden_prototype()) return NULL;
   return JSReceiver::cast(map->prototype());
 }
 
@@ -701,7 +692,7 @@
         number_ = static_cast<uint32_t>(number);
         DCHECK(dict->ValueAt(number_)->IsPropertyCell());
         PropertyCell* cell = PropertyCell::cast(dict->ValueAt(number_));
-        if (cell->value()->IsTheHole()) return NOT_FOUND;
+        if (cell->value()->IsTheHole(isolate_)) return NOT_FOUND;
         property_details_ = cell->property_details();
         has_property_ = true;
         switch (property_details_.kind()) {
@@ -766,5 +757,21 @@
   return state_;
 }
 
+Handle<InterceptorInfo> LookupIterator::GetInterceptorForFailedAccessCheck()
+    const {
+  DCHECK_EQ(ACCESS_CHECK, state_);
+  DisallowHeapAllocation no_gc;
+  AccessCheckInfo* access_check_info =
+      AccessCheckInfo::Get(isolate_, Handle<JSObject>::cast(holder_));
+  if (access_check_info) {
+    Object* interceptor = IsElement() ? access_check_info->indexed_interceptor()
+                                      : access_check_info->named_interceptor();
+    if (interceptor) {
+      return handle(InterceptorInfo::cast(interceptor), isolate_);
+    }
+  }
+  return Handle<InterceptorInfo>();
+}
+
 }  // namespace internal
 }  // namespace v8
diff --git a/src/lookup.h b/src/lookup.h
index 8005f32..f1a1b7c 100644
--- a/src/lookup.h
+++ b/src/lookup.h
@@ -16,17 +16,14 @@
  public:
   enum Configuration {
     // Configuration bits.
-    kHidden = 1 << 0,
-    kInterceptor = 1 << 1,
-    kPrototypeChain = 1 << 2,
+    kInterceptor = 1 << 0,
+    kPrototypeChain = 1 << 1,
 
     // Convience combinations of bits.
     OWN_SKIP_INTERCEPTOR = 0,
     OWN = kInterceptor,
-    HIDDEN_SKIP_INTERCEPTOR = kHidden,
-    HIDDEN = kHidden | kInterceptor,
-    PROTOTYPE_CHAIN_SKIP_INTERCEPTOR = kHidden | kPrototypeChain,
-    PROTOTYPE_CHAIN = kHidden | kPrototypeChain | kInterceptor,
+    PROTOTYPE_CHAIN_SKIP_INTERCEPTOR = kPrototypeChain,
+    PROTOTYPE_CHAIN = kPrototypeChain | kInterceptor,
     DEFAULT = PROTOTYPE_CHAIN
   };
 
@@ -179,6 +176,7 @@
   Handle<Object> GetReceiver() const { return receiver_; }
 
   Handle<JSObject> GetStoreTarget() const {
+    DCHECK(receiver_->IsJSObject());
     if (receiver_->IsJSGlobalProxy()) {
       Map* map = JSGlobalProxy::cast(*receiver_)->map();
       if (map->has_hidden_prototype()) {
@@ -229,8 +227,8 @@
   void ReconfigureDataProperty(Handle<Object> value,
                                PropertyAttributes attributes);
   void Delete();
-  void TransitionToAccessorProperty(AccessorComponent component,
-                                    Handle<Object> accessor,
+  void TransitionToAccessorProperty(Handle<Object> getter,
+                                    Handle<Object> setter,
                                     PropertyAttributes attributes);
   void TransitionToAccessorPair(Handle<Object> pair,
                                 PropertyAttributes attributes);
@@ -260,12 +258,15 @@
                     : GetInterceptor<false>(JSObject::cast(*holder_));
     return handle(result, isolate_);
   }
+  Handle<InterceptorInfo> GetInterceptorForFailedAccessCheck() const;
   Handle<Object> GetDataValue() const;
   void WriteDataValue(Handle<Object> value);
   inline void UpdateProtector() {
-    if (FLAG_harmony_species && !IsElement() &&
-        (*name_ == heap()->constructor_string() ||
-         *name_ == heap()->species_symbol())) {
+    if (IsElement()) return;
+    if (*name_ == heap()->is_concat_spreadable_symbol() ||
+        *name_ == heap()->constructor_string() ||
+        *name_ == heap()->species_symbol() ||
+        *name_ == heap()->has_instance_symbol()) {
       InternalUpdateProtector();
     }
   }
@@ -315,7 +316,6 @@
                       : holder->GetNamedInterceptor();
   }
 
-  bool check_hidden() const { return (configuration_ & kHidden) != 0; }
   bool check_interceptor() const {
     return (configuration_ & kInterceptor) != 0;
   }
@@ -334,12 +334,7 @@
 
   static Configuration ComputeConfiguration(
       Configuration configuration, Handle<Name> name) {
-    if (name->IsPrivate()) {
-      return static_cast<Configuration>(configuration &
-                                        HIDDEN_SKIP_INTERCEPTOR);
-    } else {
-      return configuration;
-    }
+    return name->IsPrivate() ? OWN_SKIP_INTERCEPTOR : configuration;
   }
 
   static Handle<JSReceiver> GetRootForNonJSReceiver(
@@ -353,8 +348,6 @@
 
   State NotFound(JSReceiver* const holder) const;
 
-  bool HolderIsInContextIndex(uint32_t index) const;
-
   // If configuration_ becomes mutable, update
   // HolderIsReceiverOrHiddenPrototype.
   const Configuration configuration_;
diff --git a/src/machine-type.h b/src/machine-type.h
index 1085657..0878610 100644
--- a/src/machine-type.h
+++ b/src/machine-type.h
@@ -177,7 +177,8 @@
 
 inline bool IsFloatingPoint(MachineRepresentation rep) {
   return rep == MachineRepresentation::kFloat32 ||
-         rep == MachineRepresentation::kFloat64;
+         rep == MachineRepresentation::kFloat64 ||
+         rep == MachineRepresentation::kSimd128;
 }
 
 // Gets the log2 of the element size in bytes of the machine type.
diff --git a/src/macro-assembler.h b/src/macro-assembler.h
index 6338b2c..b683045 100644
--- a/src/macro-assembler.h
+++ b/src/macro-assembler.h
@@ -19,21 +19,22 @@
 enum AllocationFlags {
   // No special flags.
   NO_ALLOCATION_FLAGS = 0,
-  // Return the pointer to the allocated already tagged as a heap object.
-  TAG_OBJECT = 1 << 0,
   // The content of the result register already contains the allocation top in
   // new space.
-  RESULT_CONTAINS_TOP = 1 << 1,
+  RESULT_CONTAINS_TOP = 1 << 0,
   // Specify that the requested size of the space to allocate is specified in
   // words instead of bytes.
-  SIZE_IN_WORDS = 1 << 2,
+  SIZE_IN_WORDS = 1 << 1,
   // Align the allocation to a multiple of kDoubleSize
-  DOUBLE_ALIGNMENT = 1 << 3,
+  DOUBLE_ALIGNMENT = 1 << 2,
   // Directly allocate in old space
-  PRETENURE = 1 << 4,
+  PRETENURE = 1 << 3,
+  // Allocation folding dominator
+  ALLOCATION_FOLDING_DOMINATOR = 1 << 4,
+  // Folded allocation
+  ALLOCATION_FOLDED = 1 << 5
 };
 
-
 #if V8_TARGET_ARCH_IA32
 #include "src/ia32/assembler-ia32.h"
 #include "src/ia32/assembler-ia32-inl.h"
diff --git a/src/messages.cc b/src/messages.cc
index 67ab36f..0dffbb4 100644
--- a/src/messages.cc
+++ b/src/messages.cc
@@ -7,11 +7,23 @@
 #include "src/api.h"
 #include "src/execution.h"
 #include "src/isolate-inl.h"
+#include "src/keys.h"
 #include "src/string-builder.h"
+#include "src/wasm/wasm-module.h"
 
 namespace v8 {
 namespace internal {
 
+MessageLocation::MessageLocation(Handle<Script> script, int start_pos,
+                                 int end_pos)
+    : script_(script), start_pos_(start_pos), end_pos_(end_pos) {}
+MessageLocation::MessageLocation(Handle<Script> script, int start_pos,
+                                 int end_pos, Handle<JSFunction> function)
+    : script_(script),
+      start_pos_(start_pos),
+      end_pos_(end_pos),
+      function_(function) {}
+MessageLocation::MessageLocation() : start_pos_(-1), end_pos_(-1) {}
 
 // If no message listeners have been registered this one is called
 // by default.
@@ -86,7 +98,7 @@
     MaybeHandle<Object> maybe_stringified;
     Handle<Object> stringified;
     // Make sure we don't leak uncaught internally generated Error objects.
-    if (Object::IsErrorObject(isolate, argument)) {
+    if (argument->IsJSError()) {
       Handle<Object> args[] = {argument};
       maybe_stringified = Execution::TryCall(
           isolate, isolate->no_side_effects_to_string_fun(),
@@ -118,7 +130,7 @@
   } else {
     for (int i = 0; i < global_length; i++) {
       HandleScope scope(isolate);
-      if (global_listeners.get(i)->IsUndefined()) continue;
+      if (global_listeners.get(i)->IsUndefined(isolate)) continue;
       v8::NeanderObject listener(JSObject::cast(global_listeners.get(i)));
       Handle<Foreign> callback_obj(Foreign::cast(listener.get(0)));
       v8::MessageCallback callback =
@@ -127,7 +139,7 @@
       {
         // Do not allow exceptions to propagate.
         v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
-        callback(api_message_obj, callback_data->IsUndefined()
+        callback(api_message_obj, callback_data->IsUndefined(isolate)
                                       ? api_exception_obj
                                       : v8::Utils::ToLocal(callback_data));
       }
@@ -158,11 +170,25 @@
     : isolate_(isolate) {
   Handle<Object> maybe_function = JSObject::GetDataProperty(
       call_site_obj, isolate->factory()->call_site_function_symbol());
-  if (!maybe_function->IsJSFunction()) return;
+  if (maybe_function->IsJSFunction()) {
+    // javascript
+    fun_ = Handle<JSFunction>::cast(maybe_function);
+    receiver_ = JSObject::GetDataProperty(
+        call_site_obj, isolate->factory()->call_site_receiver_symbol());
+  } else {
+    Handle<Object> maybe_wasm_func_index = JSObject::GetDataProperty(
+        call_site_obj, isolate->factory()->call_site_wasm_func_index_symbol());
+    if (!maybe_wasm_func_index->IsSmi()) {
+      // invalid: neither javascript nor wasm
+      return;
+    }
+    // wasm
+    wasm_obj_ = Handle<JSObject>::cast(JSObject::GetDataProperty(
+        call_site_obj, isolate->factory()->call_site_wasm_obj_symbol()));
+    wasm_func_index_ = Smi::cast(*maybe_wasm_func_index)->value();
+    DCHECK(static_cast<int>(wasm_func_index_) >= 0);
+  }
 
-  fun_ = Handle<JSFunction>::cast(maybe_function);
-  receiver_ = JSObject::GetDataProperty(
-      call_site_obj, isolate->factory()->call_site_receiver_symbol());
   CHECK(JSObject::GetDataProperty(
             call_site_obj, isolate->factory()->call_site_position_symbol())
             ->ToInt32(&pos_));
@@ -170,15 +196,18 @@
 
 
 Handle<Object> CallSite::GetFileName() {
-  Handle<Object> script(fun_->shared()->script(), isolate_);
-  if (script->IsScript()) {
-    return Handle<Object>(Handle<Script>::cast(script)->name(), isolate_);
-  }
-  return isolate_->factory()->null_value();
+  if (!IsJavaScript()) return isolate_->factory()->null_value();
+  Object* script = fun_->shared()->script();
+  if (!script->IsScript()) return isolate_->factory()->null_value();
+  return Handle<Object>(Script::cast(script)->name(), isolate_);
 }
 
 
 Handle<Object> CallSite::GetFunctionName() {
+  if (IsWasm()) {
+    return wasm::GetWasmFunctionNameOrNull(isolate_, wasm_obj_,
+                                           wasm_func_index_);
+  }
   Handle<String> result = JSFunction::GetName(fun_);
   if (result->length() != 0) return result;
 
@@ -191,19 +220,16 @@
   return isolate_->factory()->null_value();
 }
 
-
 Handle<Object> CallSite::GetScriptNameOrSourceUrl() {
-  Handle<Object> script_obj(fun_->shared()->script(), isolate_);
-  if (script_obj->IsScript()) {
-    Handle<Script> script = Handle<Script>::cast(script_obj);
-    Object* source_url = script->source_url();
-    if (source_url->IsString()) return Handle<Object>(source_url, isolate_);
-    return Handle<Object>(script->name(), isolate_);
-  }
-  return isolate_->factory()->null_value();
+  if (!IsJavaScript()) return isolate_->factory()->null_value();
+  Object* script_obj = fun_->shared()->script();
+  if (!script_obj->IsScript()) return isolate_->factory()->null_value();
+  Handle<Script> script(Script::cast(script_obj), isolate_);
+  Object* source_url = script->source_url();
+  if (source_url->IsString()) return Handle<Object>(source_url, isolate_);
+  return Handle<Object>(script->name(), isolate_);
 }
 
-
 bool CheckMethodName(Isolate* isolate, Handle<JSObject> obj, Handle<Name> name,
                      Handle<JSFunction> fun,
                      LookupIterator::Configuration config) {
@@ -223,7 +249,8 @@
 
 
 Handle<Object> CallSite::GetMethodName() {
-  if (receiver_->IsNull() || receiver_->IsUndefined()) {
+  if (!IsJavaScript() || receiver_->IsNull(isolate_) ||
+      receiver_->IsUndefined(isolate_)) {
     return isolate_->factory()->null_value();
   }
   Handle<JSReceiver> receiver =
@@ -238,13 +265,11 @@
     Handle<Name> name = Handle<Name>::cast(function_name);
     // ES2015 gives getters and setters name prefixes which must
     // be stripped to find the property name.
-    if (name->IsString() && FLAG_harmony_function_name) {
-      Handle<String> name_string = Handle<String>::cast(name);
-      if (name_string->IsUtf8EqualTo(CStrVector("get "), true) ||
-          name_string->IsUtf8EqualTo(CStrVector("set "), true)) {
-        name = isolate_->factory()->NewProperSubString(name_string, 4,
-                                                       name_string->length());
-      }
+    Handle<String> name_string = Handle<String>::cast(name);
+    if (name_string->IsUtf8EqualTo(CStrVector("get "), true) ||
+        name_string->IsUtf8EqualTo(CStrVector("set "), true)) {
+      name = isolate_->factory()->NewProperSubString(name_string, 4,
+                                                     name_string->length());
     }
     if (CheckMethodName(isolate_, obj, name, fun_,
                         LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR)) {
@@ -254,14 +279,14 @@
 
   HandleScope outer_scope(isolate_);
   Handle<Object> result;
-  for (PrototypeIterator iter(isolate_, obj,
-                              PrototypeIterator::START_AT_RECEIVER);
-       !iter.IsAtEnd(); iter.Advance()) {
+  for (PrototypeIterator iter(isolate_, obj, kStartAtReceiver); !iter.IsAtEnd();
+       iter.Advance()) {
     Handle<Object> current = PrototypeIterator::GetCurrent(iter);
     if (!current->IsJSObject()) break;
     Handle<JSObject> current_obj = Handle<JSObject>::cast(current);
     if (current_obj->IsAccessCheckNeeded()) break;
-    Handle<FixedArray> keys = JSObject::GetEnumPropertyKeys(current_obj);
+    Handle<FixedArray> keys =
+        KeyAccumulator::GetEnumPropertyKeys(isolate_, current_obj);
     for (int i = 0; i < keys->length(); i++) {
       HandleScope inner_scope(isolate_);
       if (!keys->get(i)->IsName()) continue;
@@ -281,7 +306,7 @@
 
 
 int CallSite::GetLineNumber() {
-  if (pos_ >= 0) {
+  if (pos_ >= 0 && IsJavaScript()) {
     Handle<Object> script_obj(fun_->shared()->script(), isolate_);
     if (script_obj->IsScript()) {
       Handle<Script> script = Handle<Script>::cast(script_obj);
@@ -293,7 +318,7 @@
 
 
 int CallSite::GetColumnNumber() {
-  if (pos_ >= 0) {
+  if (pos_ >= 0 && IsJavaScript()) {
     Handle<Object> script_obj(fun_->shared()->script(), isolate_);
     if (script_obj->IsScript()) {
       Handle<Script> script = Handle<Script>::cast(script_obj);
@@ -305,6 +330,7 @@
 
 
 bool CallSite::IsNative() {
+  if (!IsJavaScript()) return false;
   Handle<Object> script(fun_->shared()->script(), isolate_);
   return script->IsScript() &&
          Handle<Script>::cast(script)->type() == Script::TYPE_NATIVE;
@@ -312,12 +338,14 @@
 
 
 bool CallSite::IsToplevel() {
-  return receiver_->IsJSGlobalProxy() || receiver_->IsNull() ||
-         receiver_->IsUndefined();
+  if (IsWasm()) return false;
+  return receiver_->IsJSGlobalProxy() || receiver_->IsNull(isolate_) ||
+         receiver_->IsUndefined(isolate_);
 }
 
 
 bool CallSite::IsEval() {
+  if (!IsJavaScript()) return false;
   Handle<Object> script(fun_->shared()->script(), isolate_);
   return script->IsScript() &&
          Handle<Script>::cast(script)->compilation_type() ==
@@ -326,7 +354,7 @@
 
 
 bool CallSite::IsConstructor() {
-  if (!receiver_->IsJSObject()) return false;
+  if (!IsJavaScript() || !receiver_->IsJSObject()) return false;
   Handle<Object> constructor =
       JSReceiver::GetDataProperty(Handle<JSObject>::cast(receiver_),
                                   isolate_->factory()->constructor_string());
diff --git a/src/messages.h b/src/messages.h
index 4aa0b73..682105d 100644
--- a/src/messages.h
+++ b/src/messages.h
@@ -24,13 +24,10 @@
 
 class MessageLocation {
  public:
+  MessageLocation(Handle<Script> script, int start_pos, int end_pos);
   MessageLocation(Handle<Script> script, int start_pos, int end_pos,
-                  Handle<JSFunction> function = Handle<JSFunction>())
-      : script_(script),
-        start_pos_(start_pos),
-        end_pos_(end_pos),
-        function_(function) {}
-  MessageLocation() : start_pos_(-1), end_pos_(-1) { }
+                  Handle<JSFunction> function);
+  MessageLocation();
 
   Handle<Script> script() const { return script_; }
   int start_pos() const { return start_pos_; }
@@ -62,13 +59,16 @@
   bool IsEval();
   bool IsConstructor();
 
-  bool IsValid() { return !fun_.is_null(); }
+  bool IsJavaScript() { return !fun_.is_null(); }
+  bool IsWasm() { return !wasm_obj_.is_null(); }
 
  private:
   Isolate* isolate_;
   Handle<Object> receiver_;
   Handle<JSFunction> fun_;
-  int32_t pos_;
+  int32_t pos_ = -1;
+  Handle<JSObject> wasm_obj_;
+  uint32_t wasm_func_index_ = static_cast<uint32_t>(-1);
 };
 
 #define MESSAGE_TEMPLATES(T)                                                   \
@@ -94,12 +94,11 @@
   T(ArrayFunctionsOnSealed, "Cannot add/remove sealed array elements")         \
   T(ArrayNotSubclassable, "Subclassing Arrays is not currently supported.")    \
   T(CalledNonCallable, "% is not a function")                                  \
-  T(CalledNonCallableInstanceOf,                                               \
-    "Right-hand side of 'instanceof' is not callable")                         \
   T(CalledOnNonObject, "% called on non-object")                               \
   T(CalledOnNullOrUndefined, "% called on null or undefined")                  \
   T(CallSiteExpectsFunction,                                                   \
-    "CallSite expects function as second argument, got %")                     \
+    "CallSite expects wasm object as first or function as second argument, "   \
+    "got <%, %>")                                                              \
   T(CallSiteMethod, "CallSite method % expects CallSite as receiver")          \
   T(CannotConvertToPrimitive, "Cannot convert object to primitive value")      \
   T(CannotPreventExt, "Cannot prevent extensions")                             \
@@ -120,19 +119,16 @@
   T(DebuggerType, "Debugger: Parameters have wrong types.")                    \
   T(DeclarationMissingInitializer, "Missing initializer in % declaration")     \
   T(DefineDisallowed, "Cannot define property:%, object is not extensible.")   \
+  T(DetachedOperation, "Cannot perform % on a detached ArrayBuffer")           \
   T(DuplicateTemplateProperty, "Object template has duplicate property '%'")   \
-  T(ExtendsValueGenerator,                                                     \
-    "Class extends value % may not be a generator function")                   \
-  T(ExtendsValueNotFunction,                                                   \
-    "Class extends value % is not a function or null")                         \
+  T(ExtendsValueNotConstructor,                                                \
+    "Class extends value % is not a constructor or null")                      \
   T(FirstArgumentNotRegExp,                                                    \
     "First argument to % must not be a regular expression")                    \
   T(FunctionBind, "Bind must be called on a function")                         \
   T(GeneratorRunning, "Generator is already running")                          \
   T(IllegalInvocation, "Illegal invocation")                                   \
   T(IncompatibleMethodReceiver, "Method % called on incompatible receiver %")  \
-  T(InstanceofFunctionExpected,                                                \
-    "Expecting a function in instanceof check, but got %")                     \
   T(InstanceofNonobjectProto,                                                  \
     "Function has non-object prototype '%' in instanceof check")               \
   T(InvalidArgument, "invalid_argument")                                       \
@@ -149,6 +145,8 @@
     "Method invoked on undefined or null value.")                              \
   T(MethodInvokedOnWrongType, "Method invoked on an object that is not %.")    \
   T(NoAccess, "no access")                                                     \
+  T(NonCallableInInstanceOfCheck,                                              \
+    "Right-hand side of 'instanceof' is not callable")                         \
   T(NonCoercible, "Cannot match against 'undefined' or 'null'.")               \
   T(NonExtensibleProto, "% is not extensible")                                 \
   T(NonObjectInInstanceOfCheck,                                                \
@@ -175,19 +173,6 @@
   T(ObjectSetterExpectingFunction,                                             \
     "Object.prototype.__defineSetter__: Expecting function")                   \
   T(ObjectSetterCallable, "Setter must be a function: %")                      \
-  T(ObserveCallbackFrozen,                                                     \
-    "Object.observe cannot deliver to a frozen function object")               \
-  T(ObserveGlobalProxy, "% cannot be called on the global proxy object")       \
-  T(ObserveAccessChecked, "% cannot be called on access-checked objects")      \
-  T(ObserveInvalidAccept,                                                      \
-    "Third argument to Object.observe must be an array of strings.")           \
-  T(ObserveNonFunction, "Object.% cannot deliver to non-function")             \
-  T(ObserveNonObject, "Object.% cannot % non-object")                          \
-  T(ObserveNotifyNonNotifier, "notify called on non-notifier object")          \
-  T(ObservePerformNonFunction, "Cannot perform non-function")                  \
-  T(ObservePerformNonString, "Invalid non-string changeType")                  \
-  T(ObserveTypeNonString,                                                      \
-    "Invalid changeRecord with non-string 'type' property")                    \
   T(OrdinaryFunctionCalledAsConstructor,                                       \
     "Function object that's not a constructor was created with new")           \
   T(PromiseCyclic, "Chaining cycle detected for promise %")                    \
@@ -353,6 +338,8 @@
   T(InvalidTypedArrayAlignment, "% of % should be a multiple of %")            \
   T(InvalidTypedArrayLength, "Invalid typed array length")                     \
   T(InvalidTypedArrayOffset, "Start offset is too large:")                     \
+  T(InvalidSimdIndex, "Index out of bounds for SIMD operation")                \
+  T(InvalidSimdLaneValue, "Lane value out of bounds for SIMD operation")       \
   T(LetInLexicalBinding, "let is disallowed as a lexically bound name")        \
   T(LocaleMatcher, "Illegal value for localeMatcher:%")                        \
   T(NormalizationForm, "The normalization form should be one of %.")           \
@@ -370,6 +357,7 @@
   T(BadSetterArity, "Setter must have exactly one formal parameter.")          \
   T(ConstructorIsAccessor, "Class constructor may not be an accessor")         \
   T(ConstructorIsGenerator, "Class constructor may not be a generator")        \
+  T(ConstructorIsAsync, "Class constructor may not be an async method")        \
   T(DerivedConstructorReturn,                                                  \
     "Derived constructors may only return object or undefined")                \
   T(DuplicateConstructor, "A class may only have one constructor")             \
@@ -380,6 +368,8 @@
     "% loop variable declaration may not have an initializer.")                \
   T(ForInOfLoopMultiBindings,                                                  \
     "Invalid left-hand side in % loop: Must have a single binding.")           \
+  T(GeneratorInLegacyContext,                                                  \
+    "Generator declarations are not allowed in legacy contexts.")              \
   T(IllegalBreak, "Illegal break statement")                                   \
   T(IllegalContinue, "Illegal continue statement")                             \
   T(IllegalLanguageModeDirective,                                              \
@@ -430,9 +420,6 @@
   T(SloppyFunction,                                                            \
     "In non-strict mode code, functions can only be declared at top level, "   \
     "inside a block, or as the body of an if statement.")                      \
-  T(SloppyLexical,                                                             \
-    "Block-scoped declarations (let, const, function, class) not yet "         \
-    "supported outside strict mode")                                           \
   T(SpeciesNotConstructor,                                                     \
     "object.constructor[Symbol.species] is not a constructor")                 \
   T(StrictDelete, "Delete of an unqualified identifier in strict mode.")       \
@@ -445,20 +432,35 @@
   T(TemplateOctalLiteral,                                                      \
     "Octal literals are not allowed in template strings.")                     \
   T(ThisFormalParameter, "'this' is not a valid formal parameter name")        \
+  T(AwaitBindingIdentifier,                                                    \
+    "'await' is not a valid identifier name in an async function")             \
+  T(AwaitExpressionFormalParameter,                                            \
+    "Illegal await-expression in formal parameters of async function")         \
   T(TooManyArguments,                                                          \
     "Too many arguments in function call (only 65535 allowed)")                \
   T(TooManyParameters,                                                         \
     "Too many parameters in function definition (only 65535 allowed)")         \
+  T(TooManySpreads,                                                            \
+    "Literal containing too many nested spreads (up to 65534 allowed)")        \
   T(TooManyVariables, "Too many variables declared (only 4194303 allowed)")    \
   T(TypedArrayTooShort,                                                        \
     "Derived TypedArray constructor created an array which was too small")     \
   T(UnexpectedEOS, "Unexpected end of input")                                  \
   T(UnexpectedFunctionSent,                                                    \
     "function.sent expression is not allowed outside a generator")             \
+  T(UnexpectedInsideTailCall, "Unexpected expression inside tail call")        \
   T(UnexpectedReserved, "Unexpected reserved word")                            \
   T(UnexpectedStrictReserved, "Unexpected strict mode reserved word")          \
   T(UnexpectedSuper, "'super' keyword unexpected here")                        \
+  T(UnexpectedSloppyTailCall,                                                  \
+    "Tail call expressions are not allowed in non-strict mode")                \
   T(UnexpectedNewTarget, "new.target expression is not allowed here")          \
+  T(UnexpectedTailCall, "Tail call expression is not allowed here")            \
+  T(UnexpectedTailCallInCatchBlock,                                            \
+    "Tail call expression in catch block when finally block is also present")  \
+  T(UnexpectedTailCallInForInOf, "Tail call expression in for-in/of body")     \
+  T(UnexpectedTailCallInTryBlock, "Tail call expression in try block")         \
+  T(UnexpectedTailCallOfEval, "Tail call of a direct eval is not allowed")     \
   T(UnexpectedTemplateString, "Unexpected template string")                    \
   T(UnexpectedToken, "Unexpected token %")                                     \
   T(UnexpectedTokenIdentifier, "Unexpected identifier")                        \
@@ -478,7 +480,16 @@
   /* EvalError */                                                              \
   T(CodeGenFromStrings, "%")                                                   \
   /* URIError */                                                               \
-  T(URIMalformed, "URI malformed")
+  T(URIMalformed, "URI malformed")                                             \
+  /* Wasm errors (currently Error) */                                          \
+  T(WasmTrapUnreachable, "unreachable")                                        \
+  T(WasmTrapMemOutOfBounds, "memory access out of bounds")                     \
+  T(WasmTrapDivByZero, "divide by zero")                                       \
+  T(WasmTrapDivUnrepresentable, "divide result unrepresentable")               \
+  T(WasmTrapRemByZero, "remainder by zero")                                    \
+  T(WasmTrapFloatUnrepresentable, "integer result unrepresentable")            \
+  T(WasmTrapFuncInvalid, "invalid function")                                   \
+  T(WasmTrapFuncSigMismatch, "function signature mismatch")
 
 class MessageTemplate {
  public:
diff --git a/src/mips/assembler-mips-inl.h b/src/mips/assembler-mips-inl.h
index 517d4ad..57aea38 100644
--- a/src/mips/assembler-mips-inl.h
+++ b/src/mips/assembler-mips-inl.h
@@ -102,11 +102,6 @@
   return Assembler::target_address_at(pc_, host_);
 }
 
-Address RelocInfo::wasm_memory_reference() {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  return Assembler::target_address_at(pc_, host_);
-}
-
 Address RelocInfo::target_address_address() {
   DCHECK(IsCodeTarget(rmode_) ||
          IsRuntimeEntry(rmode_) ||
@@ -156,19 +151,6 @@
   }
 }
 
-void RelocInfo::update_wasm_memory_reference(
-    Address old_base, Address new_base, size_t old_size, size_t new_size,
-    ICacheFlushMode icache_flush_mode) {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  DCHECK(old_base <= wasm_memory_reference() &&
-         wasm_memory_reference() < old_base + old_size);
-  Address updated_reference = new_base + (wasm_memory_reference() - old_base);
-  DCHECK(new_base <= updated_reference &&
-         updated_reference < new_base + new_size);
-  Assembler::set_target_address_at(isolate_, pc_, host_, updated_reference,
-                                   icache_flush_mode);
-}
-
 Address Assembler::target_address_from_return_address(Address pc) {
   return pc - kCallTargetAddressOffset;
 }
@@ -380,7 +362,7 @@
   }
 }
 
-
+template <typename ObjectVisitor>
 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
@@ -481,6 +463,8 @@
   CheckTrampolinePoolQuick();
 }
 
+template <>
+inline void Assembler::EmitHelper(uint8_t x);
 
 template <typename T>
 void Assembler::EmitHelper(T x) {
@@ -489,6 +473,14 @@
   CheckTrampolinePoolQuick();
 }
 
+template <>
+void Assembler::EmitHelper(uint8_t x) {
+  *reinterpret_cast<uint8_t*>(pc_) = x;
+  pc_ += sizeof(x);
+  if (reinterpret_cast<intptr_t>(pc_) % kInstrSize == 0) {
+    CheckTrampolinePoolQuick();
+  }
+}
 
 void Assembler::emit(Instr x, CompactBranchType is_compact_branch) {
   if (!is_buffer_growth_blocked()) {
diff --git a/src/mips/assembler-mips.cc b/src/mips/assembler-mips.cc
index bfa2328..8bda17c 100644
--- a/src/mips/assembler-mips.cc
+++ b/src/mips/assembler-mips.cc
@@ -189,6 +189,31 @@
   return false;
 }
 
+Address RelocInfo::wasm_memory_reference() {
+  DCHECK(IsWasmMemoryReference(rmode_));
+  return Assembler::target_address_at(pc_, host_);
+}
+
+Address RelocInfo::wasm_global_reference() {
+  DCHECK(IsWasmGlobalReference(rmode_));
+  return Assembler::target_address_at(pc_, host_);
+}
+
+uint32_t RelocInfo::wasm_memory_size_reference() {
+  DCHECK(IsWasmMemorySizeReference(rmode_));
+  return reinterpret_cast<uint32_t>(Assembler::target_address_at(pc_, host_));
+}
+
+void RelocInfo::unchecked_update_wasm_memory_reference(
+    Address address, ICacheFlushMode flush_mode) {
+  Assembler::set_target_address_at(isolate_, pc_, host_, address, flush_mode);
+}
+
+void RelocInfo::unchecked_update_wasm_memory_size(uint32_t size,
+                                                  ICacheFlushMode flush_mode) {
+  Assembler::set_target_address_at(isolate_, pc_, host_,
+                                   reinterpret_cast<Address>(size), flush_mode);
+}
 
 // -----------------------------------------------------------------------------
 // Implementation of Operand and MemOperand.
@@ -294,6 +319,8 @@
   desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
   desc->origin = this;
   desc->constant_pool_size = 0;
+  desc->unwinding_info_size = 0;
+  desc->unwinding_info = nullptr;
 }
 
 
@@ -1241,7 +1268,6 @@
 
 
 void Assembler::bal(int16_t offset) {
-  positions_recorder()->WriteRecordedPositions();
   bgezal(zero_reg, offset);
 }
 
@@ -1254,7 +1280,6 @@
 
 void Assembler::balc(int32_t offset) {
   DCHECK(IsMipsArchVariant(kMips32r6));
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(BALC, offset, CompactBranchType::COMPACT_BRANCH);
 }
 
@@ -1301,7 +1326,6 @@
 void Assembler::bgezal(Register rs, int16_t offset) {
   DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg));
   BlockTrampolinePoolScope block_trampoline_pool(this);
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
   BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
@@ -1372,7 +1396,6 @@
 void Assembler::bltzal(Register rs, int16_t offset) {
   DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg));
   BlockTrampolinePoolScope block_trampoline_pool(this);
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(REGIMM, rs, BLTZAL, offset);
   BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
@@ -1408,7 +1431,6 @@
 void Assembler::blezalc(Register rt, int16_t offset) {
   DCHECK(IsMipsArchVariant(kMips32r6));
   DCHECK(!(rt.is(zero_reg)));
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(BLEZ, zero_reg, rt, offset,
                     CompactBranchType::COMPACT_BRANCH);
 }
@@ -1417,7 +1439,6 @@
 void Assembler::bgezalc(Register rt, int16_t offset) {
   DCHECK(IsMipsArchVariant(kMips32r6));
   DCHECK(!(rt.is(zero_reg)));
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(BLEZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
 }
 
@@ -1426,7 +1447,6 @@
   DCHECK(!IsMipsArchVariant(kMips32r6));
   DCHECK(!(rs.is(zero_reg)));
   BlockTrampolinePoolScope block_trampoline_pool(this);
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(REGIMM, rs, BGEZALL, offset);
   BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
@@ -1435,7 +1455,6 @@
 void Assembler::bltzalc(Register rt, int16_t offset) {
   DCHECK(IsMipsArchVariant(kMips32r6));
   DCHECK(!(rt.is(zero_reg)));
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(BGTZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
 }
 
@@ -1443,7 +1462,6 @@
 void Assembler::bgtzalc(Register rt, int16_t offset) {
   DCHECK(IsMipsArchVariant(kMips32r6));
   DCHECK(!(rt.is(zero_reg)));
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(BGTZ, zero_reg, rt, offset,
                     CompactBranchType::COMPACT_BRANCH);
 }
@@ -1452,7 +1470,6 @@
 void Assembler::beqzalc(Register rt, int16_t offset) {
   DCHECK(IsMipsArchVariant(kMips32r6));
   DCHECK(!(rt.is(zero_reg)));
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(ADDI, zero_reg, rt, offset,
                     CompactBranchType::COMPACT_BRANCH);
 }
@@ -1461,7 +1478,6 @@
 void Assembler::bnezalc(Register rt, int16_t offset) {
   DCHECK(IsMipsArchVariant(kMips32r6));
   DCHECK(!(rt.is(zero_reg)));
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(DADDI, zero_reg, rt, offset,
                     CompactBranchType::COMPACT_BRANCH);
 }
@@ -1520,9 +1536,6 @@
 void Assembler::jr(Register rs) {
   if (!IsMipsArchVariant(kMips32r6)) {
     BlockTrampolinePoolScope block_trampoline_pool(this);
-    if (rs.is(ra)) {
-      positions_recorder()->WriteRecordedPositions();
-    }
     GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR);
     BlockTrampolinePoolFor(1);  // For associated delay slot.
   } else {
@@ -1540,7 +1553,6 @@
   DCHECK(in_range && ((target & 3) == 0));
 #endif
   BlockTrampolinePoolScope block_trampoline_pool(this);
-  positions_recorder()->WriteRecordedPositions();
   GenInstrJump(JAL, (target >> 2) & kImm26Mask);
   BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
@@ -1549,7 +1561,6 @@
 void Assembler::jalr(Register rs, Register rd) {
   DCHECK(rs.code() != rd.code());
   BlockTrampolinePoolScope block_trampoline_pool(this);
-  positions_recorder()->WriteRecordedPositions();
   GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
   BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
@@ -1563,7 +1574,6 @@
 
 void Assembler::jialc(Register rt, int16_t offset) {
   DCHECK(IsMipsArchVariant(kMips32r6));
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(POP76, zero_reg, rt, offset);
 }
 
@@ -1829,11 +1839,17 @@
 
 
 void Assembler::lwl(Register rd, const MemOperand& rs) {
+  DCHECK(is_int16(rs.offset_));
+  DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) ||
+         IsMipsArchVariant(kMips32r2));
   GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_);
 }
 
 
 void Assembler::lwr(Register rd, const MemOperand& rs) {
+  DCHECK(is_int16(rs.offset_));
+  DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) ||
+         IsMipsArchVariant(kMips32r2));
   GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_);
 }
 
@@ -1869,11 +1885,17 @@
 
 
 void Assembler::swl(Register rd, const MemOperand& rs) {
+  DCHECK(is_int16(rs.offset_));
+  DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) ||
+         IsMipsArchVariant(kMips32r2));
   GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_);
 }
 
 
 void Assembler::swr(Register rd, const MemOperand& rs) {
+  DCHECK(is_int16(rs.offset_));
+  DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) ||
+         IsMipsArchVariant(kMips32r2));
   GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_);
 }
 
@@ -1892,7 +1914,6 @@
   GenInstrImmediate(LUI, rs, rt, j);
 }
 
-
 // ---------PC-Relative instructions-----------
 
 void Assembler::addiupc(Register rs, int32_t imm19) {
@@ -2009,6 +2030,10 @@
   emit(instr);
 }
 
+void Assembler::sync() {
+  Instr sync_instr = SPECIAL | SYNC;
+  emit(sync_instr);
+}
 
 // Move from HI/LO register.
 
@@ -2123,6 +2148,21 @@
   GenInstrRegister(SPECIAL3, rs, rt, rd, sa, BSHFL);
 }
 
+// Byte swap.
+void Assembler::wsbh(Register rd, Register rt) {
+  DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
+  GenInstrRegister(SPECIAL3, zero_reg, rt, rd, WSBH, BSHFL);
+}
+
+void Assembler::seh(Register rd, Register rt) {
+  DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
+  GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEH, BSHFL);
+}
+
+void Assembler::seb(Register rd, Register rt) {
+  DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
+  GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEB, BSHFL);
+}
 
 // --------Coprocessor-instructions----------------
 
@@ -2955,6 +2995,7 @@
     data = reinterpret_cast<uint32_t>(buffer_ + label->pos());
   } else {
     data = jump_address(label);
+    unbound_labels_count_++;
     internal_reference_positions_.insert(label->pos());
   }
   RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
diff --git a/src/mips/assembler-mips.h b/src/mips/assembler-mips.h
index 886ac6c..8f4f9d9 100644
--- a/src/mips/assembler-mips.h
+++ b/src/mips/assembler-mips.h
@@ -63,6 +63,8 @@
   V(f16) V(f17) V(f18) V(f19) V(f20) V(f21) V(f22) V(f23) \
   V(f24) V(f25) V(f26) V(f27) V(f28) V(f29) V(f30) V(f31)
 
+#define FLOAT_REGISTERS DOUBLE_REGISTERS
+
 #define ALLOCATABLE_DOUBLE_REGISTERS(V)                   \
   V(f0)  V(f2)  V(f4)  V(f6)  V(f8)  V(f10) V(f12) V(f14) \
   V(f16) V(f18) V(f20) V(f22) V(f24) V(f26)
@@ -123,8 +125,6 @@
     Register r = {code};
     return r;
   }
-  const char* ToString();
-  bool IsAllocatable() const;
   bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
   bool is(Register reg) const { return reg_code == reg.reg_code; }
   int code() const {
@@ -153,8 +153,10 @@
 
 Register ToRegister(int num);
 
+static const bool kSimpleFPAliasing = true;
+
 // Coprocessor register.
-struct DoubleRegister {
+struct FPURegister {
   enum Code {
 #define REGISTER_CODE(R) kCode_##R,
     DOUBLE_REGISTERS(REGISTER_CODE)
@@ -171,22 +173,20 @@
   // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
   // number of Double regs (64-bit regs, or FPU-reg-pairs).
 
-  const char* ToString();
-  bool IsAllocatable() const;
   bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
-  bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
-  DoubleRegister low() const {
+  bool is(FPURegister reg) const { return reg_code == reg.reg_code; }
+  FPURegister low() const {
     // Find low reg of a Double-reg pair, which is the reg itself.
     DCHECK(reg_code % 2 == 0);  // Specified Double reg must be even.
-    DoubleRegister reg;
+    FPURegister reg;
     reg.reg_code = reg_code;
     DCHECK(reg.is_valid());
     return reg;
   }
-  DoubleRegister high() const {
+  FPURegister high() const {
     // Find high reg of a Doubel-reg pair, which is reg + 1.
     DCHECK(reg_code % 2 == 0);  // Specified Double reg must be even.
-    DoubleRegister reg;
+    FPURegister reg;
     reg.reg_code = reg_code + 1;
     DCHECK(reg.is_valid());
     return reg;
@@ -201,8 +201,8 @@
     return 1 << reg_code;
   }
 
-  static DoubleRegister from_code(int code) {
-    DoubleRegister r = {code};
+  static FPURegister from_code(int code) {
+    FPURegister r = {code};
     return r;
   }
   void setcode(int f) {
@@ -227,8 +227,12 @@
 // but it is not in common use. Someday we will want to support this in v8.)
 
 // For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers.
-typedef DoubleRegister FPURegister;
-typedef DoubleRegister FloatRegister;
+typedef FPURegister FloatRegister;
+
+typedef FPURegister DoubleRegister;
+
+// TODO(mips) Define SIMD registers.
+typedef FPURegister Simd128Register;
 
 const DoubleRegister no_freg = {-1};
 
@@ -304,9 +308,6 @@
 const FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister };
 const FPUControlRegister FCSR = { kFCSRRegister };
 
-// TODO(mips) Define SIMD registers.
-typedef DoubleRegister Simd128Register;
-
 // -----------------------------------------------------------------------------
 // Machine instruction Operands.
 
@@ -799,6 +800,9 @@
   void teq(Register rs, Register rt, uint16_t code);
   void tne(Register rs, Register rt, uint16_t code);
 
+  // Memory barrier instruction.
+  void sync();
+
   // Move from HI/LO register.
   void mfhi(Register rd);
   void mflo(Register rd);
@@ -844,6 +848,10 @@
   void bitswap(Register rd, Register rt);
   void align(Register rd, Register rs, Register rt, uint8_t bp);
 
+  void wsbh(Register rd, Register rt);
+  void seh(Register rd, Register rt);
+  void seb(Register rd, Register rt);
+
   // --------Coprocessor-instructions----------------
 
   // Load, store, and move.
@@ -1039,8 +1047,7 @@
 
   // Record a deoptimization reason that can be used by a log or cpu profiler.
   // Use --trace-deopt to enable.
-  void RecordDeoptReason(const int reason, int raw_position);
-
+  void RecordDeoptReason(const int reason, int raw_position, int id);
 
   static int RelocateInternalReference(RelocInfo::Mode rmode, byte* pc,
                                        intptr_t pc_delta);
@@ -1158,10 +1165,15 @@
 
   bool IsPrevInstrCompactBranch() { return prev_instr_compact_branch_; }
 
+  inline int UnboundLabelsCount() { return unbound_labels_count_; }
+
  protected:
   // Load Scaled Address instruction.
   void lsa(Register rd, Register rt, Register rs, uint8_t sa);
 
+  // Helpers.
+  void LoadRegPlusOffsetToAt(const MemOperand& src);
+
   // Relocation for a type-recording IC has the AST id added to it.  This
   // member variable is a way to pass the information from the call site to
   // the relocation info.
@@ -1359,8 +1371,6 @@
   void GenInstrJump(Opcode opcode,
                      uint32_t address);
 
-  // Helpers.
-  void LoadRegPlusOffsetToAt(const MemOperand& src);
 
   // Labels.
   void print(Label* L);
diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
index 9693a52..7d9d080 100644
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -17,10 +17,7 @@
 
 #define __ ACCESS_MASM(masm)
 
-
-void Builtins::Generate_Adaptor(MacroAssembler* masm,
-                                CFunctionId id,
-                                BuiltinExtraArguments extra_args) {
+void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
   // ----------- S t a t e -------------
   //  -- a0                 : number of arguments excluding receiver
   //  -- a1                 : target
@@ -39,23 +36,8 @@
   __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
 
   // Insert extra arguments.
-  int num_extra_args = 0;
-  switch (extra_args) {
-    case BuiltinExtraArguments::kTarget:
-      __ Push(a1);
-      ++num_extra_args;
-      break;
-    case BuiltinExtraArguments::kNewTarget:
-      __ Push(a3);
-      ++num_extra_args;
-      break;
-    case BuiltinExtraArguments::kTargetAndNewTarget:
-      __ Push(a1, a3);
-      num_extra_args += 2;
-      break;
-    case BuiltinExtraArguments::kNone:
-      break;
-  }
+  const int num_extra_args = 2;
+  __ Push(a1, a3);
 
   // JumpToExternalReference expects a0 to contain the number of arguments
   // including the receiver and the extra arguments.
@@ -145,6 +127,8 @@
 void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
   // ----------- S t a t e -------------
   //  -- a0                 : number of arguments
+  //  -- a1                 : function
+  //  -- cp                 : context
   //  -- ra                 : return address
   //  -- sp[(argc - n) * 8] : arg[n] (zero-based)
   //  -- sp[(argc + 1) * 8] : receiver
@@ -154,9 +138,9 @@
                                      : Heap::kMinusInfinityValueRootIndex;
 
   // Load the accumulator with the default return value (either -Infinity or
-  // +Infinity), with the tagged value in a1 and the double value in f0.
-  __ LoadRoot(a1, root_index);
-  __ ldc1(f0, FieldMemOperand(a1, HeapNumber::kValueOffset));
+  // +Infinity), with the tagged value in t2 and the double value in f0.
+  __ LoadRoot(t2, root_index);
+  __ ldc1(f0, FieldMemOperand(t2, HeapNumber::kValueOffset));
   __ Addu(a3, a0, Operand(1));
 
   Label done_loop, loop;
@@ -171,35 +155,39 @@
     __ lw(a2, MemOperand(at));
 
     // Load the double value of the parameter into f2, maybe converting the
-    // parameter to a number first using the ToNumberStub if necessary.
+    // parameter to a number first using the ToNumber builtin if necessary.
     Label convert, convert_smi, convert_number, done_convert;
     __ bind(&convert);
     __ JumpIfSmi(a2, &convert_smi);
     __ lw(t0, FieldMemOperand(a2, HeapObject::kMapOffset));
     __ JumpIfRoot(t0, Heap::kHeapNumberMapRootIndex, &convert_number);
     {
-      // Parameter is not a Number, use the ToNumberStub to convert it.
-      FrameScope scope(masm, StackFrame::INTERNAL);
+      // Parameter is not a Number, use the ToNumber builtin to convert it.
+      FrameScope scope(masm, StackFrame::MANUAL);
+      __ Push(ra, fp);
+      __ Move(fp, sp);
+      __ Push(cp, a1);
       __ SmiTag(a0);
       __ SmiTag(a3);
-      __ Push(a0, a1, a3);
+      __ Push(a0, t2, a3);
       __ mov(a0, a2);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
       __ mov(a2, v0);
-      __ Pop(a0, a1, a3);
+      __ Pop(a0, t2, a3);
       {
         // Restore the double accumulator value (f0).
         Label restore_smi, done_restore;
-        __ JumpIfSmi(a1, &restore_smi);
-        __ ldc1(f0, FieldMemOperand(a1, HeapNumber::kValueOffset));
+        __ JumpIfSmi(t2, &restore_smi);
+        __ ldc1(f0, FieldMemOperand(t2, HeapNumber::kValueOffset));
         __ jmp(&done_restore);
         __ bind(&restore_smi);
-        __ SmiToDoubleFPURegister(a1, f0, t0);
+        __ SmiToDoubleFPURegister(t2, f0, t0);
         __ bind(&done_restore);
       }
       __ SmiUntag(a3);
       __ SmiUntag(a0);
+      __ Pop(cp, a1);
+      __ Pop(ra, fp);
     }
     __ jmp(&convert);
     __ bind(&convert_number);
@@ -227,20 +215,20 @@
     __ Branch(&set_value, ne, t1, Operand(t8));
     __ jmp(&loop);
     __ bind(&set_value);
-    __ mov(a1, a2);
+    __ mov(t2, a2);
     __ jmp(&loop);
 
     // At least one side is NaN, which means that the result will be NaN too.
     __ bind(&compare_nan);
-    __ LoadRoot(a1, Heap::kNanValueRootIndex);
-    __ ldc1(f0, FieldMemOperand(a1, HeapNumber::kValueOffset));
+    __ LoadRoot(t2, Heap::kNanValueRootIndex);
+    __ ldc1(f0, FieldMemOperand(t2, HeapNumber::kValueOffset));
     __ jmp(&loop);
   }
 
   __ bind(&done_loop);
   __ Lsa(sp, sp, a3, kPointerSizeLog2);
   __ Ret(USE_DELAY_SLOT);
-  __ mov(v0, a1);  // In delay slot.
+  __ mov(v0, t2);  // In delay slot.
 }
 
 // static
@@ -265,8 +253,7 @@
   }
 
   // 2a. Convert first argument to number.
-  ToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
+  __ Jump(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
 
   // 2b. No arguments, return +0.
   __ bind(&no_arguments);
@@ -314,8 +301,7 @@
     {
       FrameScope scope(masm, StackFrame::INTERNAL);
       __ Push(a1, a3);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
       __ Move(a0, v0);
       __ Pop(a1, a3);
     }
@@ -603,16 +589,9 @@
     // a0: number of arguments
     // a1: constructor function
     // a3: new target
-    if (is_api_function) {
-      __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
-      Handle<Code> code =
-          masm->isolate()->builtins()->HandleApiCallConstruct();
-      __ Call(code, RelocInfo::CODE_TARGET);
-    } else {
-      ParameterCount actual(a0);
-      __ InvokeFunction(a1, a3, actual, CALL_FUNCTION,
-                        CheckDebugStepCallWrapper());
-    }
+    ParameterCount actual(a0);
+    __ InvokeFunction(a1, a3, actual, CALL_FUNCTION,
+                      CheckDebugStepCallWrapper());
 
     // Store offset of return address for deoptimizer.
     if (create_implicit_receiver && !is_api_function) {
@@ -825,6 +804,177 @@
   Generate_JSEntryTrampolineHelper(masm, true);
 }
 
+// static
+void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- v0 : the value to pass to the generator
+  //  -- a1 : the JSGeneratorObject to resume
+  //  -- a2 : the resume mode (tagged)
+  //  -- ra : return address
+  // -----------------------------------
+  __ AssertGeneratorObject(a1);
+
+  // Store input value into generator object.
+  __ sw(v0, FieldMemOperand(a1, JSGeneratorObject::kInputOrDebugPosOffset));
+  __ RecordWriteField(a1, JSGeneratorObject::kInputOrDebugPosOffset, v0, a3,
+                      kRAHasNotBeenSaved, kDontSaveFPRegs);
+
+  // Store resume mode into generator object.
+  __ sw(a2, FieldMemOperand(a1, JSGeneratorObject::kResumeModeOffset));
+
+  // Load suspended function and context.
+  __ lw(cp, FieldMemOperand(a1, JSGeneratorObject::kContextOffset));
+  __ lw(t0, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
+
+  // Flood function if we are stepping.
+  Label prepare_step_in_if_stepping, prepare_step_in_suspended_generator;
+  Label stepping_prepared;
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(masm->isolate());
+  STATIC_ASSERT(StepFrame > StepIn);
+  __ li(t1, Operand(last_step_action));
+  __ lb(t1, MemOperand(t1));
+  __ Branch(&prepare_step_in_if_stepping, ge, t1, Operand(StepIn));
+
+  // Flood function if we need to continue stepping in the suspended generator.
+  ExternalReference debug_suspended_generator =
+      ExternalReference::debug_suspended_generator_address(masm->isolate());
+  __ li(t1, Operand(debug_suspended_generator));
+  __ lw(t1, MemOperand(t1));
+  __ Branch(&prepare_step_in_suspended_generator, eq, a1, Operand(t1));
+  __ bind(&stepping_prepared);
+
+  // Push receiver.
+  __ lw(t1, FieldMemOperand(a1, JSGeneratorObject::kReceiverOffset));
+  __ Push(t1);
+
+  // ----------- S t a t e -------------
+  //  -- a1    : the JSGeneratorObject to resume
+  //  -- a2    : the resume mode (tagged)
+  //  -- t0    : generator function
+  //  -- cp    : generator context
+  //  -- ra    : return address
+  //  -- sp[0] : generator receiver
+  // -----------------------------------
+
+  // Push holes for arguments to generator function. Since the parser forced
+  // context allocation for any variables in generators, the actual argument
+  // values have already been copied into the context and these dummy values
+  // will never be used.
+  __ lw(a3, FieldMemOperand(t0, JSFunction::kSharedFunctionInfoOffset));
+  __ lw(a3,
+        FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
+  {
+    Label done_loop, loop;
+    __ bind(&loop);
+    __ Subu(a3, a3, Operand(Smi::FromInt(1)));
+    __ Branch(&done_loop, lt, a3, Operand(zero_reg));
+    __ PushRoot(Heap::kTheHoleValueRootIndex);
+    __ Branch(&loop);
+    __ bind(&done_loop);
+  }
+
+  // Dispatch on the kind of generator object.
+  Label old_generator;
+  __ lw(a3, FieldMemOperand(t0, JSFunction::kSharedFunctionInfoOffset));
+  __ lw(a3, FieldMemOperand(a3, SharedFunctionInfo::kFunctionDataOffset));
+  __ GetObjectType(a3, a3, a3);
+  __ Branch(&old_generator, ne, a3, Operand(BYTECODE_ARRAY_TYPE));
+
+  // New-style (ignition/turbofan) generator object.
+  {
+    __ lw(a0, FieldMemOperand(t0, JSFunction::kSharedFunctionInfoOffset));
+    __ lw(a0,
+         FieldMemOperand(a0, SharedFunctionInfo::kFormalParameterCountOffset));
+    __ SmiUntag(a0);
+    // We abuse new.target both to indicate that this is a resume call and to
+    // pass in the generator object.  In ordinary calls, new.target is always
+    // undefined because generator functions are non-constructable.
+    __ Move(a3, a1);
+    __ Move(a1, t0);
+    __ lw(a2, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
+    __ Jump(a2);
+  }
+
+  // Old-style (full-codegen) generator object
+  __ bind(&old_generator);
+  {
+    // Enter a new JavaScript frame, and initialize its slots as they were when
+    // the generator was suspended.
+    FrameScope scope(masm, StackFrame::MANUAL);
+    __ Push(ra, fp);
+    __ Move(fp, sp);
+    __ Push(cp, t0);
+
+    // Restore the operand stack.
+    __ lw(a0, FieldMemOperand(a1, JSGeneratorObject::kOperandStackOffset));
+    __ lw(a3, FieldMemOperand(a0, FixedArray::kLengthOffset));
+    __ Addu(a0, a0, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+    __ Lsa(a3, a0, a3, kPointerSizeLog2 - 1);
+    {
+      Label done_loop, loop;
+      __ bind(&loop);
+      __ Branch(&done_loop, eq, a0, Operand(a3));
+      __ lw(t1, MemOperand(a0));
+      __ Push(t1);
+      __ Branch(USE_DELAY_SLOT, &loop);
+      __ addiu(a0, a0, kPointerSize);  // In delay slot.
+      __ bind(&done_loop);
+    }
+
+    // Reset operand stack so we don't leak.
+    __ LoadRoot(t1, Heap::kEmptyFixedArrayRootIndex);
+    __ sw(t1, FieldMemOperand(a1, JSGeneratorObject::kOperandStackOffset));
+
+    // Resume the generator function at the continuation.
+    __ lw(a3, FieldMemOperand(t0, JSFunction::kSharedFunctionInfoOffset));
+    __ lw(a3, FieldMemOperand(a3, SharedFunctionInfo::kCodeOffset));
+    __ Addu(a3, a3, Operand(Code::kHeaderSize - kHeapObjectTag));
+    __ lw(a2, FieldMemOperand(a1, JSGeneratorObject::kContinuationOffset));
+    __ SmiUntag(a2);
+    __ Addu(a3, a3, Operand(a2));
+    __ li(a2, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
+    __ sw(a2, FieldMemOperand(a1, JSGeneratorObject::kContinuationOffset));
+    __ Move(v0, a1);  // Continuation expects generator object in v0.
+    __ Jump(a3);
+  }
+
+  __ bind(&prepare_step_in_if_stepping);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ Push(a1, a2, t0);
+    __ CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
+    __ Pop(a1, a2);
+  }
+  __ Branch(USE_DELAY_SLOT, &stepping_prepared);
+  __ lw(t0, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
+
+  __ bind(&prepare_step_in_suspended_generator);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ Push(a1, a2);
+    __ CallRuntime(Runtime::kDebugPrepareStepInSuspendedGenerator);
+    __ Pop(a1, a2);
+  }
+  __ Branch(USE_DELAY_SLOT, &stepping_prepared);
+  __ lw(t0, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
+}
+
+static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch) {
+  Register args_count = scratch;
+
+  // Get the arguments + receiver count.
+  __ lw(args_count,
+        MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
+  __ lw(args_count,
+        FieldMemOperand(args_count, BytecodeArray::kParameterSizeOffset));
+
+  // Leave the frame (also dropping the register file).
+  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+
+  // Drop receiver + arguments.
+  __ Addu(sp, sp, args_count);
+}
 
 // Generate code for entering a JS function with the interpreter.
 // On entry to the function the receiver and arguments have been pushed on the
@@ -842,14 +992,16 @@
 // The function builds an interpreter frame.  See InterpreterFrameConstants in
 // frames.h for its layout.
 void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
+  ProfileEntryHookStub::MaybeCallEntryHook(masm);
+
   // Open a frame scope to indicate that there is a frame on the stack.  The
   // MANUAL indicates that the scope shouldn't actually generate code to set up
   // the frame (that is done below).
   FrameScope frame_scope(masm, StackFrame::MANUAL);
   __ PushStandardFrame(a1);
 
-  // Get the bytecode array from the function object and load the pointer to the
-  // first entry into kInterpreterBytecodeRegister.
+  // Get the bytecode array from the function object (or from the DebugInfo if
+  // it is present) and load it into kInterpreterBytecodeArrayRegister.
   __ lw(a0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
   Label load_debug_bytecode_array, bytecode_array_loaded;
   Register debug_info = kInterpreterBytecodeArrayRegister;
@@ -861,8 +1013,11 @@
         FieldMemOperand(a0, SharedFunctionInfo::kFunctionDataOffset));
   __ bind(&bytecode_array_loaded);
 
+  // Check function data field is actually a BytecodeArray object.
+  Label bytecode_array_not_present;
+  __ JumpIfRoot(kInterpreterBytecodeArrayRegister,
+                Heap::kUndefinedValueRootIndex, &bytecode_array_not_present);
   if (FLAG_debug_code) {
-    // Check function data field is actually a BytecodeArray object.
     __ SmiTst(kInterpreterBytecodeArrayRegister, t0);
     __ Assert(ne, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry, t0,
               Operand(zero_reg));
@@ -871,8 +1026,13 @@
               Operand(BYTECODE_ARRAY_TYPE));
   }
 
-  // Push new.target, bytecode array and zero for bytecode array offset.
-  __ Push(a3, kInterpreterBytecodeArrayRegister, zero_reg);
+  // Load initial bytecode offset.
+  __ li(kInterpreterBytecodeOffsetRegister,
+        Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
+
+  // Push new.target, bytecode array and Smi tagged bytecode array offset.
+  __ SmiTag(t0, kInterpreterBytecodeOffsetRegister);
+  __ Push(a3, kInterpreterBytecodeArrayRegister, t0);
 
   // Allocate the local and temporary register file on the stack.
   {
@@ -902,17 +1062,8 @@
     __ Branch(&loop_header, ge, t0, Operand(zero_reg));
   }
 
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's prologue:
-  //  - Call ProfileEntryHookStub when isolate has a function_entry_hook.
-  //  - Code aging of the BytecodeArray object.
-
-  // Load bytecode offset and dispatch table into registers.
+  // Load accumulator and dispatch table into registers.
   __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
-  __ Addu(kInterpreterRegisterFileRegister, fp,
-          Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
-  __ li(kInterpreterBytecodeOffsetRegister,
-        Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
   __ li(kInterpreterDispatchTableRegister,
         Operand(ExternalReference::interpreter_dispatch_table_address(
             masm->isolate())));
@@ -923,42 +1074,57 @@
   __ lbu(a0, MemOperand(a0));
   __ Lsa(at, kInterpreterDispatchTableRegister, a0, kPointerSizeLog2);
   __ lw(at, MemOperand(at));
-  // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
-  // and header removal.
-  __ Addu(at, at, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Call(at);
+  masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
 
-  // Even though the first bytecode handler was called, we will never return.
-  __ Abort(kUnexpectedReturnFromBytecodeHandler);
+  // The return value is in v0.
+  LeaveInterpreterFrame(masm, t0);
+  __ Jump(ra);
 
   // Load debug copy of the bytecode array.
   __ bind(&load_debug_bytecode_array);
   __ lw(kInterpreterBytecodeArrayRegister,
         FieldMemOperand(debug_info, DebugInfo::kAbstractCodeIndex));
   __ Branch(&bytecode_array_loaded);
+
+  // If the bytecode array is no longer present, then the underlying function
+  // has been switched to a different kind of code and we heal the closure by
+  // switching the code entry field over to the new code object as well.
+  __ bind(&bytecode_array_not_present);
+  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+  __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
+  __ lw(t0, FieldMemOperand(t0, SharedFunctionInfo::kCodeOffset));
+  __ Addu(t0, t0, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ sw(t0, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
+  __ RecordWriteCodeEntryField(a1, t0, t1);
+  __ Jump(t0);
 }
 
+void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) {
+  // Save the function and context for call to CompileBaseline.
+  __ lw(a1, MemOperand(fp, StandardFrameConstants::kFunctionOffset));
+  __ lw(kContextRegister,
+        MemOperand(fp, StandardFrameConstants::kContextOffset));
 
-void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's EmitReturnSequence.
-  //  - Supporting FLAG_trace for Runtime::TraceExit.
-  //  - Support profiler (specifically decrementing profiling_counter
-  //    appropriately and calling out to HandleInterrupts if necessary).
+  // Leave the frame before recompiling for baseline so that we don't count as
+  // an activation on the stack.
+  LeaveInterpreterFrame(masm, t0);
 
-  // The return value is in accumulator, which is already in v0.
+  {
+    FrameScope frame_scope(masm, StackFrame::INTERNAL);
+    // Push return value.
+    __ push(v0);
 
-  // Leave the frame (also dropping the register file).
-  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+    // Push function as argument and compile for baseline.
+    __ push(a1);
+    __ CallRuntime(Runtime::kCompileBaseline);
 
-  // Drop receiver + arguments and return.
-  __ lw(at, FieldMemOperand(kInterpreterBytecodeArrayRegister,
-                            BytecodeArray::kParameterSizeOffset));
-  __ Addu(sp, sp, at);
+    // Restore return value.
+    __ pop(v0);
+  }
   __ Jump(ra);
 }
 
-
 // static
 void Builtins::Generate_InterpreterPushArgsAndCallImpl(
     MacroAssembler* masm, TailCallMode tail_call_mode) {
@@ -991,7 +1157,6 @@
           RelocInfo::CODE_TARGET);
 }
 
-
 // static
 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
   // ----------- S t a t e -------------
@@ -1022,25 +1187,24 @@
   __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
 }
 
+void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
+  // Set the return address to the correct point in the interpreter entry
+  // trampoline.
+  Smi* interpreter_entry_return_pc_offset(
+      masm->isolate()->heap()->interpreter_entry_return_pc_offset());
+  DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
+  __ li(t0, Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline()));
+  __ Addu(ra, t0, Operand(interpreter_entry_return_pc_offset->value() +
+                          Code::kHeaderSize - kHeapObjectTag));
 
-static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
-  // Initialize register file register and dispatch table register.
-  __ Addu(kInterpreterRegisterFileRegister, fp,
-          Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
+  // Initialize the dispatch table register.
   __ li(kInterpreterDispatchTableRegister,
         Operand(ExternalReference::interpreter_dispatch_table_address(
             masm->isolate())));
 
-  // Get the context from the frame.
-  __ lw(kContextRegister,
-        MemOperand(kInterpreterRegisterFileRegister,
-                   InterpreterFrameConstants::kContextFromRegisterPointer));
-
   // Get the bytecode array pointer from the frame.
-  __ lw(
-      kInterpreterBytecodeArrayRegister,
-      MemOperand(kInterpreterRegisterFileRegister,
-                 InterpreterFrameConstants::kBytecodeArrayFromRegisterPointer));
+  __ lw(kInterpreterBytecodeArrayRegister,
+        MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
 
   if (FLAG_debug_code) {
     // Check function data field is actually a BytecodeArray object.
@@ -1054,9 +1218,7 @@
 
   // Get the target bytecode offset from the frame.
   __ lw(kInterpreterBytecodeOffsetRegister,
-        MemOperand(
-            kInterpreterRegisterFileRegister,
-            InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
+        MemOperand(fp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
   __ SmiUntag(kInterpreterBytecodeOffsetRegister);
 
   // Dispatch to the target bytecode.
@@ -1065,63 +1227,179 @@
   __ lbu(a1, MemOperand(a1));
   __ Lsa(a1, kInterpreterDispatchTableRegister, a1, kPointerSizeLog2);
   __ lw(a1, MemOperand(a1));
-  __ Addu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Jump(a1);
 }
 
-
-static void Generate_InterpreterNotifyDeoptimizedHelper(
-    MacroAssembler* masm, Deoptimizer::BailoutType type) {
-  // Enter an internal frame.
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Pass the deoptimization type to the runtime system.
-    __ li(a1, Operand(Smi::FromInt(static_cast<int>(type))));
-    __ push(a1);
-    __ CallRuntime(Runtime::kNotifyDeoptimized);
-    // Tear down internal frame.
-  }
-
-  // Drop state (we don't use these for interpreter deopts) and and pop the
-  // accumulator value into the accumulator register.
-  __ Drop(1);
-  __ Pop(kInterpreterAccumulatorRegister);
-
-  // Enter the bytecode dispatch.
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-
-void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
-}
-
-
-void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
-}
-
-
-void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
-}
-
-void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
-  // Set the address of the interpreter entry trampoline as a return address.
-  // This simulates the initial call to bytecode handlers in interpreter entry
-  // trampoline. The return will never actually be taken, but our stack walker
-  // uses this address to determine whether a frame is interpreted.
-  __ li(ra, Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline()));
-
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-
 void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- a0 : argument count (preserved for callee)
+  //  -- a3 : new target (preserved for callee)
+  //  -- a1 : target function (preserved for callee)
+  // -----------------------------------
+  // First lookup code, maybe we don't need to compile!
+  Label gotta_call_runtime, gotta_call_runtime_no_stack;
+  Label maybe_call_runtime;
+  Label try_shared;
+  Label loop_top, loop_bottom;
+
+  Register argument_count = a0;
+  Register closure = a1;
+  Register new_target = a3;
+  __ push(argument_count);
+  __ push(new_target);
+  __ push(closure);
+
+  Register map = a0;
+  Register index = a2;
+  __ lw(map, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ lw(map, FieldMemOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset));
+  __ lw(index, FieldMemOperand(map, FixedArray::kLengthOffset));
+  __ Branch(&gotta_call_runtime, lt, index, Operand(Smi::FromInt(2)));
+
+  // Find literals.
+  // a3  : native context
+  // a2  : length / index
+  // a0  : optimized code map
+  // stack[0] : new target
+  // stack[4] : closure
+  Register native_context = a3;
+  __ lw(native_context, NativeContextMemOperand());
+
+  __ bind(&loop_top);
+  Register temp = a1;
+  Register array_pointer = t1;
+
+  // Does the native context match?
+  __ sll(at, index, kPointerSizeLog2 - kSmiTagSize);
+  __ Addu(array_pointer, map, Operand(at));
+  __ lw(temp, FieldMemOperand(array_pointer,
+                              SharedFunctionInfo::kOffsetToPreviousContext));
+  __ lw(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
+  __ Branch(&loop_bottom, ne, temp, Operand(native_context));
+  // OSR id set to none?
+  __ lw(temp, FieldMemOperand(array_pointer,
+                              SharedFunctionInfo::kOffsetToPreviousOsrAstId));
+  const int bailout_id = BailoutId::None().ToInt();
+  __ Branch(&loop_bottom, ne, temp, Operand(Smi::FromInt(bailout_id)));
+
+  // Literals available?
+  Label got_literals, maybe_cleared_weakcell;
+  __ lw(temp, FieldMemOperand(array_pointer,
+                              SharedFunctionInfo::kOffsetToPreviousLiterals));
+  // temp contains either a WeakCell pointing to the literals array or the
+  // literals array directly.
+  STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
+  __ lw(t0, FieldMemOperand(temp, WeakCell::kValueOffset));
+  __ JumpIfSmi(t0, &maybe_cleared_weakcell);
+  // t0 is a pointer, therefore temp is a WeakCell pointing to a literals array.
+  __ lw(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
+  __ jmp(&got_literals);
+
+  // t0 is a smi. If it's 0, then we are looking at a cleared WeakCell
+  // around the literals array, and we should visit the runtime. If it's > 0,
+  // then temp already contains the literals array.
+  __ bind(&maybe_cleared_weakcell);
+  __ Branch(&gotta_call_runtime, eq, t0, Operand(Smi::FromInt(0)));
+
+  // Save the literals in the closure.
+  __ bind(&got_literals);
+  __ lw(t0, MemOperand(sp, 0));
+  __ sw(temp, FieldMemOperand(t0, JSFunction::kLiteralsOffset));
+  __ push(index);
+  __ RecordWriteField(t0, JSFunction::kLiteralsOffset, temp, index,
+                      kRAHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  __ pop(index);
+
+  // Code available?
+  Register entry = t0;
+  __ lw(entry,
+        FieldMemOperand(array_pointer,
+                        SharedFunctionInfo::kOffsetToPreviousCachedCode));
+  __ lw(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &maybe_call_runtime);
+
+  // Found literals and code. Get them into the closure and return.
+  __ pop(closure);
+  // Store code entry in the closure.
+  __ Addu(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+
+  Label install_optimized_code_and_tailcall;
+  __ bind(&install_optimized_code_and_tailcall);
+  __ sw(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
+  __ RecordWriteCodeEntryField(closure, entry, t1);
+
+  // Link the closure into the optimized function list.
+  // t0 : code entry
+  // a3 : native context
+  // a1 : closure
+  __ lw(t1,
+        ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
+  __ sw(t1, FieldMemOperand(closure, JSFunction::kNextFunctionLinkOffset));
+  __ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, t1, a0,
+                      kRAHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  const int function_list_offset =
+      Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
+  __ sw(closure,
+        ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
+  // Save closure before the write barrier.
+  __ mov(t1, closure);
+  __ RecordWriteContextSlot(native_context, function_list_offset, closure, a0,
+                            kRAHasNotBeenSaved, kDontSaveFPRegs);
+  __ mov(closure, t1);
+  __ pop(new_target);
+  __ pop(argument_count);
+  __ Jump(entry);
+
+  __ bind(&loop_bottom);
+  __ Subu(index, index,
+          Operand(Smi::FromInt(SharedFunctionInfo::kEntryLength)));
+  __ Branch(&loop_top, gt, index, Operand(Smi::FromInt(1)));
+
+  // We found neither literals nor code.
+  __ jmp(&gotta_call_runtime);
+
+  __ bind(&maybe_call_runtime);
+  __ pop(closure);
+
+  // Last possibility. Check the context free optimized code map entry.
+  __ lw(entry, FieldMemOperand(map, FixedArray::kHeaderSize +
+                                        SharedFunctionInfo::kSharedCodeIndex));
+  __ lw(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &try_shared);
+
+  // Store code entry in the closure.
+  __ Addu(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ jmp(&install_optimized_code_and_tailcall);
+
+  __ bind(&try_shared);
+  __ pop(new_target);
+  __ pop(argument_count);
+  // Is the full code valid?
+  __ lw(entry, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ lw(entry, FieldMemOperand(entry, SharedFunctionInfo::kCodeOffset));
+  __ lw(t1, FieldMemOperand(entry, Code::kFlagsOffset));
+  __ And(t1, t1, Operand(Code::KindField::kMask));
+  __ srl(t1, t1, Code::KindField::kShift);
+  __ Branch(&gotta_call_runtime_no_stack, eq, t1, Operand(Code::BUILTIN));
+  // Yes, install the full code.
+  __ Addu(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ sw(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
+  __ RecordWriteCodeEntryField(closure, entry, t1);
+  __ Jump(entry);
+
+  __ bind(&gotta_call_runtime);
+  __ pop(closure);
+  __ pop(new_target);
+  __ pop(argument_count);
+  __ bind(&gotta_call_runtime_no_stack);
   GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
 }
 
+void Builtins::Generate_CompileBaseline(MacroAssembler* masm) {
+  GenerateTailCallToReturnedCode(masm, Runtime::kCompileBaseline);
+}
 
 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
   GenerateTailCallToReturnedCode(masm,
@@ -1264,15 +1542,17 @@
   __ SmiUntag(t2);
   // Switch on the state.
   Label with_tos_register, unknown_state;
-  __ Branch(&with_tos_register,
-            ne, t2, Operand(FullCodeGenerator::NO_REGISTERS));
+  __ Branch(&with_tos_register, ne, t2,
+            Operand(static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS)));
   __ Ret(USE_DELAY_SLOT);
   // Safe to fill delay slot Addu will emit one instruction.
   __ Addu(sp, sp, Operand(1 * kPointerSize));  // Remove state.
 
   __ bind(&with_tos_register);
+  DCHECK_EQ(kInterpreterAccumulatorRegister.code(), v0.code());
   __ lw(v0, MemOperand(sp, 1 * kPointerSize));
-  __ Branch(&unknown_state, ne, t2, Operand(FullCodeGenerator::TOS_REG));
+  __ Branch(&unknown_state, ne, t2,
+            Operand(static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER)));
 
   __ Ret(USE_DELAY_SLOT);
   // Safe to fill delay slot Addu will emit one instruction.
@@ -1435,6 +1715,9 @@
 void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
                                                int field_index) {
   // ----------- S t a t e -------------
+  //  -- a0    : number of arguments
+  //  -- a1    : function
+  //  -- cp    : context
   //  -- sp[0] : receiver
   // -----------------------------------
 
@@ -1474,29 +1757,14 @@
 
   // 3. Raise a TypeError if the receiver is not a date.
   __ bind(&receiver_not_date);
-  __ TailCallRuntime(Runtime::kThrowNotDateError);
-}
-
-// static
-void Builtins::Generate_FunctionHasInstance(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- a0    : argc
-  //  -- sp[0] : first argument (left-hand side)
-  //  -- sp[4] : receiver (right-hand side)
-  // -----------------------------------
-
   {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-    __ lw(InstanceOfDescriptor::LeftRegister(),
-          MemOperand(fp, 2 * kPointerSize));  // Load left-hand side.
-    __ lw(InstanceOfDescriptor::RightRegister(),
-          MemOperand(fp, 3 * kPointerSize));  // Load right-hand side.
-    InstanceOfStub stub(masm->isolate(), true);
-    __ CallStub(&stub);
+    FrameScope scope(masm, StackFrame::MANUAL);
+    __ Push(a0, ra, fp);
+    __ Move(fp, sp);
+    __ Push(cp, a1);
+    __ Push(Smi::FromInt(0));
+    __ CallRuntime(Runtime::kThrowNotDateError);
   }
-
-  // Pop the argument and the receiver.
-  __ DropAndRet(2);
 }
 
 // static
@@ -2469,6 +2737,107 @@
           RelocInfo::CODE_TARGET);
 }
 
+// static
+void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- a0 : requested object size (untagged)
+  //  -- ra : return address
+  // -----------------------------------
+  __ SmiTag(a0);
+  __ Push(a0);
+  __ Move(cp, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInNewSpace);
+}
+
+// static
+void Builtins::Generate_AllocateInOldSpace(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- a0 : requested object size (untagged)
+  //  -- ra : return address
+  // -----------------------------------
+  __ SmiTag(a0);
+  __ Move(a1, Smi::FromInt(AllocateTargetSpace::encode(OLD_SPACE)));
+  __ Push(a0, a1);
+  __ Move(cp, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInTargetSpace);
+}
+
+// static
+void Builtins::Generate_StringToNumber(MacroAssembler* masm) {
+  // The StringToNumber stub takes on argument in a0.
+  __ AssertString(a0);
+
+  // Check if string has a cached array index.
+  Label runtime;
+  __ lw(a2, FieldMemOperand(a0, String::kHashFieldOffset));
+  __ And(at, a2, Operand(String::kContainsCachedArrayIndexMask));
+  __ Branch(&runtime, ne, at, Operand(zero_reg));
+  __ IndexFromHash(a2, v0);
+  __ Ret();
+
+  __ bind(&runtime);
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ Push(a0);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kStringToNumber);
+  }
+  __ Ret();
+}
+
+// static
+void Builtins::Generate_ToNumber(MacroAssembler* masm) {
+  // The ToNumber stub takes one argument in a0.
+  Label not_smi;
+  __ JumpIfNotSmi(a0, &not_smi);
+  __ Ret(USE_DELAY_SLOT);
+  __ mov(v0, a0);
+  __ bind(&not_smi);
+
+  Label not_heap_number;
+  __ GetObjectType(a0, a1, a1);
+  // a0: receiver
+  // a1: receiver instance type
+  __ Branch(&not_heap_number, ne, a1, Operand(HEAP_NUMBER_TYPE));
+  __ Ret(USE_DELAY_SLOT);
+  __ mov(v0, a0);
+  __ bind(&not_heap_number);
+
+  __ Jump(masm->isolate()->builtins()->NonNumberToNumber(),
+          RelocInfo::CODE_TARGET);
+}
+
+// static
+void Builtins::Generate_NonNumberToNumber(MacroAssembler* masm) {
+  // The NonNumberToNumber stub takes on argument in a0.
+  __ AssertNotNumber(a0);
+
+  Label not_string;
+  __ GetObjectType(a0, a1, a1);
+  // a0: receiver
+  // a1: receiver instance type
+  __ Branch(&not_string, hs, a1, Operand(FIRST_NONSTRING_TYPE));
+  __ Jump(masm->isolate()->builtins()->StringToNumber(),
+          RelocInfo::CODE_TARGET);
+  __ bind(&not_string);
+
+  Label not_oddball;
+  __ Branch(&not_oddball, ne, a1, Operand(ODDBALL_TYPE));
+  __ Ret(USE_DELAY_SLOT);
+  __ lw(v0, FieldMemOperand(a0, Oddball::kToNumberOffset));  // In delay slot.
+  __ bind(&not_oddball);
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ Push(a0);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kToNumber);
+  }
+  __ Ret();
+}
 
 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
   // State setup as expected by MacroAssembler::InvokePrologue.
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index fd286fb..3213677 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -21,60 +21,16 @@
 namespace v8 {
 namespace internal {
 
+#define __ ACCESS_MASM(masm)
 
-static void InitializeArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  Address deopt_handler = Runtime::FunctionForId(
-      Runtime::kArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(a0, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-
-static void InitializeInternalArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  Address deopt_handler = Runtime::FunctionForId(
-      Runtime::kInternalArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(a0, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-
-void ArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 0);
-}
-
-
-void ArraySingleArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 1);
-}
-
-
-void ArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-void InternalArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0);
+void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
+  __ sll(t9, a0, kPointerSizeLog2);
+  __ Addu(t9, sp, t9);
+  __ sw(a1, MemOperand(t9, 0));
+  __ Push(a1);
+  __ Push(a2);
+  __ Addu(a0, a0, Operand(3));
+  __ TailCallRuntime(Runtime::kNewArray);
 }
 
 void FastArrayPushStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
@@ -82,20 +38,12 @@
   descriptor->Initialize(a0, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-void InternalArraySingleArgumentConstructorStub::InitializeDescriptor(
+void FastFunctionBindStub::InitializeDescriptor(
     CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1);
+  Address deopt_handler = Runtime::FunctionForId(Runtime::kFunctionBind)->entry;
+  descriptor->Initialize(a0, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-
-void InternalArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-#define __ ACCESS_MASM(masm)
-
 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
                                           Condition cc);
 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
@@ -1032,7 +980,7 @@
   CEntryStub::GenerateAheadOfTime(isolate);
   StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
   StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
-  ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
+  CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate);
   CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
   CreateWeakCellStub::GenerateAheadOfTime(isolate);
   BinaryOpICStub::GenerateAheadOfTime(isolate);
@@ -1451,7 +1399,6 @@
                                           &miss,  // When not a string.
                                           &miss,  // When not a number.
                                           &miss,  // When index out of range.
-                                          STRING_INDEX_IS_ARRAY_INDEX,
                                           RECEIVER_IS_STRING);
   char_at_generator.GenerateFast(masm);
   __ Ret();
@@ -1465,128 +1412,6 @@
 }
 
 
-void InstanceOfStub::Generate(MacroAssembler* masm) {
-  Register const object = a1;              // Object (lhs).
-  Register const function = a0;            // Function (rhs).
-  Register const object_map = a2;          // Map of {object}.
-  Register const function_map = a3;        // Map of {function}.
-  Register const function_prototype = t0;  // Prototype of {function}.
-  Register const scratch = t1;
-
-  DCHECK(object.is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(function.is(InstanceOfDescriptor::RightRegister()));
-
-  // Check if {object} is a smi.
-  Label object_is_smi;
-  __ JumpIfSmi(object, &object_is_smi);
-
-  // Lookup the {function} and the {object} map in the global instanceof cache.
-  // Note: This is safe because we clear the global instanceof cache whenever
-  // we change the prototype of any object.
-  Label fast_case, slow_case;
-  __ lw(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
-  __ LoadRoot(at, Heap::kInstanceofCacheFunctionRootIndex);
-  __ Branch(&fast_case, ne, function, Operand(at));
-  __ LoadRoot(at, Heap::kInstanceofCacheMapRootIndex);
-  __ Branch(&fast_case, ne, object_map, Operand(at));
-  __ Ret(USE_DELAY_SLOT);
-  __ LoadRoot(v0, Heap::kInstanceofCacheAnswerRootIndex);  // In delay slot.
-
-  // If {object} is a smi we can safely return false if {function} is a JS
-  // function, otherwise we have to miss to the runtime and throw an exception.
-  __ bind(&object_is_smi);
-  __ JumpIfSmi(function, &slow_case);
-  __ GetObjectType(function, function_map, scratch);
-  __ Branch(&slow_case, ne, scratch, Operand(JS_FUNCTION_TYPE));
-  __ Ret(USE_DELAY_SLOT);
-  __ LoadRoot(v0, Heap::kFalseValueRootIndex);  // In delay slot.
-
-  // Fast-case: The {function} must be a valid JSFunction.
-  __ bind(&fast_case);
-  __ JumpIfSmi(function, &slow_case);
-  __ GetObjectType(function, function_map, scratch);
-  __ Branch(&slow_case, ne, scratch, Operand(JS_FUNCTION_TYPE));
-
-  // Go to the runtime if the function is not a constructor.
-  __ lbu(scratch, FieldMemOperand(function_map, Map::kBitFieldOffset));
-  __ And(at, scratch, Operand(1 << Map::kIsConstructor));
-  __ Branch(&slow_case, eq, at, Operand(zero_reg));
-
-  // Ensure that {function} has an instance prototype.
-  __ And(at, scratch, Operand(1 << Map::kHasNonInstancePrototype));
-  __ Branch(&slow_case, ne, at, Operand(zero_reg));
-
-  // Get the "prototype" (or initial map) of the {function}.
-  __ lw(function_prototype,
-        FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
-  __ AssertNotSmi(function_prototype);
-
-  // Resolve the prototype if the {function} has an initial map.  Afterwards the
-  // {function_prototype} will be either the JSReceiver prototype object or the
-  // hole value, which means that no instances of the {function} were created so
-  // far and hence we should return false.
-  Label function_prototype_valid;
-  __ GetObjectType(function_prototype, scratch, scratch);
-  __ Branch(&function_prototype_valid, ne, scratch, Operand(MAP_TYPE));
-  __ lw(function_prototype,
-        FieldMemOperand(function_prototype, Map::kPrototypeOffset));
-  __ bind(&function_prototype_valid);
-  __ AssertNotSmi(function_prototype);
-
-  // Update the global instanceof cache with the current {object} map and
-  // {function}.  The cached answer will be set when it is known below.
-  __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
-  __ StoreRoot(object_map, Heap::kInstanceofCacheMapRootIndex);
-
-  // Loop through the prototype chain looking for the {function} prototype.
-  // Assume true, and change to false if not found.
-  Register const object_instance_type = function_map;
-  Register const map_bit_field = function_map;
-  Register const null = scratch;
-  Register const result = v0;
-
-  Label done, loop, fast_runtime_fallback;
-  __ LoadRoot(result, Heap::kTrueValueRootIndex);
-  __ LoadRoot(null, Heap::kNullValueRootIndex);
-  __ bind(&loop);
-
-  // Check if the object needs to be access checked.
-  __ lbu(map_bit_field, FieldMemOperand(object_map, Map::kBitFieldOffset));
-  __ And(map_bit_field, map_bit_field, Operand(1 << Map::kIsAccessCheckNeeded));
-  __ Branch(&fast_runtime_fallback, ne, map_bit_field, Operand(zero_reg));
-  // Check if the current object is a Proxy.
-  __ lbu(object_instance_type,
-         FieldMemOperand(object_map, Map::kInstanceTypeOffset));
-  __ Branch(&fast_runtime_fallback, eq, object_instance_type,
-            Operand(JS_PROXY_TYPE));
-
-  __ lw(object, FieldMemOperand(object_map, Map::kPrototypeOffset));
-  __ Branch(&done, eq, object, Operand(function_prototype));
-  __ Branch(USE_DELAY_SLOT, &loop, ne, object, Operand(null));
-  __ lw(object_map,
-        FieldMemOperand(object, HeapObject::kMapOffset));  // In delay slot.
-  __ LoadRoot(result, Heap::kFalseValueRootIndex);
-  __ bind(&done);
-  __ Ret(USE_DELAY_SLOT);
-  __ StoreRoot(result,
-               Heap::kInstanceofCacheAnswerRootIndex);  // In delay slot.
-
-  // Found Proxy or access check needed: Call the runtime
-  __ bind(&fast_runtime_fallback);
-  __ Push(object, function_prototype);
-  // Invalidate the instanceof cache.
-  DCHECK(Smi::FromInt(0) == 0);
-  __ StoreRoot(zero_reg, Heap::kInstanceofCacheFunctionRootIndex);
-  __ TailCallRuntime(Runtime::kHasInPrototypeChain);
-
-  // Slow-case: Call the %InstanceOf runtime function.
-  __ bind(&slow_case);
-  __ Push(object, function);
-  __ TailCallRuntime(is_es6_instanceof() ? Runtime::kOrdinaryHasInstance
-                                         : Runtime::kInstanceOf);
-}
-
-
 void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
   Label miss;
   Register receiver = LoadDescriptor::ReceiverRegister();
@@ -2053,6 +1878,7 @@
   // a2 : feedback vector
   // a3 : slot in feedback vector (Smi)
   Label initialize, done, miss, megamorphic, not_array_function;
+  Label done_initialize_count, done_increment_count;
 
   DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()),
             masm->isolate()->heap()->megamorphic_symbol());
@@ -2071,7 +1897,7 @@
   Register feedback_map = t1;
   Register weak_value = t4;
   __ lw(weak_value, FieldMemOperand(t2, WeakCell::kValueOffset));
-  __ Branch(&done, eq, a1, Operand(weak_value));
+  __ Branch(&done_increment_count, eq, a1, Operand(weak_value));
   __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
   __ Branch(&done, eq, t2, Operand(at));
   __ lw(feedback_map, FieldMemOperand(t2, HeapObject::kMapOffset));
@@ -2093,7 +1919,7 @@
   // Make sure the function is the Array() function
   __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, t2);
   __ Branch(&megamorphic, ne, a1, Operand(t2));
-  __ jmp(&done);
+  __ jmp(&done_increment_count);
 
   __ bind(&miss);
 
@@ -2120,11 +1946,27 @@
   // slot.
   CreateAllocationSiteStub create_stub(masm->isolate());
   CallStubInRecordCallTarget(masm, &create_stub);
-  __ Branch(&done);
+  __ Branch(&done_initialize_count);
 
   __ bind(&not_array_function);
   CreateWeakCellStub weak_cell_stub(masm->isolate());
   CallStubInRecordCallTarget(masm, &weak_cell_stub);
+
+  __ bind(&done_initialize_count);
+  // Initialize the call counter.
+  __ Lsa(at, a2, a3, kPointerSizeLog2 - kSmiTagSize);
+  __ li(t0, Operand(Smi::FromInt(1)));
+  __ Branch(USE_DELAY_SLOT, &done);
+  __ sw(t0, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
+
+  __ bind(&done_increment_count);
+
+  // Increment the call count for monomorphic function calls.
+  __ Lsa(at, a2, a3, kPointerSizeLog2 - kSmiTagSize);
+  __ lw(t0, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
+  __ Addu(t0, t0, Operand(Smi::FromInt(1)));
+  __ sw(t0, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
+
   __ bind(&done);
 }
 
@@ -2185,7 +2027,7 @@
   // Increment the call count for monomorphic function calls.
   __ Lsa(at, a2, a3, kPointerSizeLog2 - kSmiTagSize);
   __ lw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
-  __ Addu(a3, a3, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+  __ Addu(a3, a3, Operand(Smi::FromInt(1)));
   __ sw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
 
   __ mov(a2, t0);
@@ -2231,7 +2073,7 @@
   // Increment the call count for monomorphic function calls.
   __ Lsa(at, a2, a3, kPointerSizeLog2 - kSmiTagSize);
   __ lw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
-  __ Addu(a3, a3, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+  __ Addu(a3, a3, Operand(Smi::FromInt(1)));
   __ sw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
 
   __ bind(&call_function);
@@ -2302,7 +2144,7 @@
 
   // Initialize the call counter.
   __ Lsa(at, a2, a3, kPointerSizeLog2 - kSmiTagSize);
-  __ li(t0, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+  __ li(t0, Operand(Smi::FromInt(1)));
   __ sw(t0, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
 
   // Store the function. Use a stub since we need a frame for allocation.
@@ -2402,13 +2244,7 @@
   } else {
     __ Push(object_, index_);
   }
-  if (index_flags_ == STRING_INDEX_IS_NUMBER) {
-    __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero);
-  } else {
-    DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
-    // NumberToSmi discards numbers that are not exact integers.
-    __ CallRuntime(Runtime::kNumberToSmi);
-  }
+  __ CallRuntime(Runtime::kNumberToSmi);
 
   // Save the conversion result before the pop instructions below
   // have a chance to overwrite it.
@@ -2750,74 +2586,13 @@
   // a3: from index (untagged)
   __ SmiTag(a3, a3);
   StringCharAtGenerator generator(v0, a3, a2, v0, &runtime, &runtime, &runtime,
-                                  STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING);
+                                  RECEIVER_IS_STRING);
   generator.GenerateFast(masm);
   __ DropAndRet(3);
   generator.SkipSlow(masm, &runtime);
 }
 
 
-void ToNumberStub::Generate(MacroAssembler* masm) {
-  // The ToNumber stub takes one argument in a0.
-  Label not_smi;
-  __ JumpIfNotSmi(a0, &not_smi);
-  __ Ret(USE_DELAY_SLOT);
-  __ mov(v0, a0);
-  __ bind(&not_smi);
-
-  Label not_heap_number;
-  __ GetObjectType(a0, a1, a1);
-  // a0: receiver
-  // a1: receiver instance type
-  __ Branch(&not_heap_number, ne, a1, Operand(HEAP_NUMBER_TYPE));
-  __ Ret(USE_DELAY_SLOT);
-  __ mov(v0, a0);
-  __ bind(&not_heap_number);
-
-  NonNumberToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
-}
-
-void NonNumberToNumberStub::Generate(MacroAssembler* masm) {
-  // The NonNumberToNumber stub takes on argument in a0.
-  __ AssertNotNumber(a0);
-
-  Label not_string;
-  __ GetObjectType(a0, a1, a1);
-  // a0: receiver
-  // a1: receiver instance type
-  __ Branch(&not_string, hs, a1, Operand(FIRST_NONSTRING_TYPE));
-  StringToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
-  __ bind(&not_string);
-
-  Label not_oddball;
-  __ Branch(&not_oddball, ne, a1, Operand(ODDBALL_TYPE));
-  __ Ret(USE_DELAY_SLOT);
-  __ lw(v0, FieldMemOperand(a0, Oddball::kToNumberOffset));  // In delay slot.
-  __ bind(&not_oddball);
-
-  __ Push(a0);  // Push argument.
-  __ TailCallRuntime(Runtime::kToNumber);
-}
-
-void StringToNumberStub::Generate(MacroAssembler* masm) {
-  // The StringToNumber stub takes on argument in a0.
-  __ AssertString(a0);
-
-  // Check if string has a cached array index.
-  Label runtime;
-  __ lw(a2, FieldMemOperand(a0, String::kHashFieldOffset));
-  __ And(at, a2, Operand(String::kContainsCachedArrayIndexMask));
-  __ Branch(&runtime, ne, at, Operand(zero_reg));
-  __ IndexFromHash(a2, v0);
-  __ Ret();
-
-  __ bind(&runtime);
-  __ Push(a0);  // Push argument.
-  __ TailCallRuntime(Runtime::kStringToNumber);
-}
-
 void ToStringStub::Generate(MacroAssembler* masm) {
   // The ToString stub takes on argument in a0.
   Label is_number;
@@ -2998,7 +2773,7 @@
   // Load a2 with the allocation site. We stick an undefined dummy value here
   // and replace it with the real allocation site later when we instantiate this
   // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate().
-  __ li(a2, handle(isolate()->heap()->undefined_value()));
+  __ li(a2, isolate()->factory()->undefined_value());
 
   // Make sure that we actually patched the allocation site.
   if (FLAG_debug_code) {
@@ -3893,14 +3668,14 @@
 
 void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  LoadICStub stub(isolate(), state());
+  LoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate(), state());
+  KeyedLoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -4037,8 +3812,8 @@
   __ bind(&not_array);
   __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
   __ Branch(&miss, ne, at, Operand(feedback));
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::LOAD_IC, code_flags,
                                                receiver, name, feedback,
                                                receiver_map, scratch1, t5);
@@ -4179,8 +3954,8 @@
   __ bind(&not_array);
   __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
   __ Branch(&miss, ne, feedback, Operand(at));
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
   masm->isolate()->stub_cache()->GenerateProbe(
       masm, Code::STORE_IC, code_flags, receiver, key, feedback, receiver_map,
       scratch1, scratch2);
@@ -4517,19 +4292,13 @@
   }
 }
 
-
-void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
+void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
   ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
       isolate);
   ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
       isolate);
-  ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
-      isolate);
-}
-
-
-void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
-    Isolate* isolate) {
+  ArrayNArgumentsConstructorStub stub(isolate);
+  stub.GetCode();
   ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS };
   for (int i = 0; i < 2; i++) {
     // For internal arrays we only need a few things.
@@ -4537,8 +4306,6 @@
     stubh1.GetCode();
     InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]);
     stubh2.GetCode();
-    InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]);
-    stubh3.GetCode();
   }
 }
 
@@ -4557,13 +4324,15 @@
     CreateArrayDispatchOneArgument(masm, mode);
 
     __ bind(&not_one_case);
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else if (argument_count() == NONE) {
     CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
   } else if (argument_count() == ONE) {
     CreateArrayDispatchOneArgument(masm, mode);
   } else if (argument_count() == MORE_THAN_ONE) {
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else {
     UNREACHABLE();
   }
@@ -4647,7 +4416,7 @@
   InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
   __ TailCallStub(&stub0, lo, a0, Operand(1));
 
-  InternalArrayNArgumentsConstructorStub stubN(isolate(), kind);
+  ArrayNArgumentsConstructorStub stubN(isolate());
   __ TailCallStub(&stubN, hi, a0, Operand(1));
 
   if (IsFastPackedElementsKind(kind)) {
@@ -4748,15 +4517,15 @@
   __ bind(&done_allocate);
 
   // Initialize the JSObject fields.
-  __ sw(a2, MemOperand(v0, JSObject::kMapOffset));
+  __ sw(a2, FieldMemOperand(v0, JSObject::kMapOffset));
   __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex);
-  __ sw(a3, MemOperand(v0, JSObject::kPropertiesOffset));
-  __ sw(a3, MemOperand(v0, JSObject::kElementsOffset));
+  __ sw(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset));
+  __ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset));
   STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize);
-  __ Addu(a1, v0, Operand(JSObject::kHeaderSize));
+  __ Addu(a1, v0, Operand(JSObject::kHeaderSize - kHeapObjectTag));
 
   // ----------- S t a t e -------------
-  //  -- v0 : result (untagged)
+  //  -- v0 : result (tagged)
   //  -- a1 : result fields (untagged)
   //  -- t1 : result end (untagged)
   //  -- a2 : initial map
@@ -4774,11 +4543,7 @@
   {
     // Initialize all in-object fields with undefined.
     __ InitializeFieldsWithFiller(a1, t1, a0);
-
-    // Add the object tag to make the JSObject real.
-    STATIC_ASSERT(kHeapObjectTag == 1);
-    __ Ret(USE_DELAY_SLOT);
-    __ Addu(v0, v0, Operand(kHeapObjectTag));  // In delay slot.
+    __ Ret();
   }
   __ bind(&slack_tracking);
   {
@@ -4801,9 +4566,7 @@
     Label finalize;
     STATIC_ASSERT(Map::kSlackTrackingCounterEnd == 1);
     __ And(a3, a3, Operand(Map::ConstructionCounter::kMask));
-    __ Branch(USE_DELAY_SLOT, &finalize, eq, a3, Operand(zero_reg));
-    STATIC_ASSERT(kHeapObjectTag == 1);
-    __ Addu(v0, v0, Operand(kHeapObjectTag));  // In delay slot.
+    __ Branch(&finalize, eq, a3, Operand(zero_reg));
     __ Ret();
 
     // Finalize the instance size.
@@ -4828,10 +4591,10 @@
     __ CallRuntime(Runtime::kAllocateInNewSpace);
     __ Pop(a2);
   }
-  STATIC_ASSERT(kHeapObjectTag == 1);
-  __ Subu(v0, v0, Operand(kHeapObjectTag));
   __ lbu(t1, FieldMemOperand(a2, Map::kInstanceSizeOffset));
   __ Lsa(t1, v0, t1, kPointerSizeLog2);
+  STATIC_ASSERT(kHeapObjectTag == 1);
+  __ Subu(t1, t1, Operand(kHeapObjectTag));
   __ jmp(&done_allocate);
 
   // Fall back to %NewObject.
@@ -4850,19 +4613,19 @@
   // -----------------------------------
   __ AssertFunction(a1);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make a2 point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ Branch(USE_DELAY_SLOT, &loop_entry);
-    __ mov(a2, fp);  // In delay slot.
-    __ bind(&loop);
+  // Make a2 point to the JavaScript frame.
+  __ mov(a2, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ lw(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset));
-    __ bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ lw(a3, MemOperand(a2, StandardFrameConstants::kFunctionOffset));
-    __ Branch(&loop, ne, a1, Operand(a3));
+    __ Branch(&ok, eq, a1, Operand(a3));
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
   }
 
   // Check if we have rest parameters (only possible if we have an
@@ -4877,10 +4640,10 @@
   // specified by the function's internal formal parameter count.
   Label rest_parameters;
   __ lw(a0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset));
-  __ lw(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
-  __ lw(a1,
-        FieldMemOperand(a1, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ Subu(a0, a0, Operand(a1));
+  __ lw(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
+  __ lw(a3,
+        FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
+  __ Subu(a0, a0, Operand(a3));
   __ Branch(&rest_parameters, gt, a0, Operand(zero_reg));
 
   // Return an empty rest parameter array.
@@ -4893,7 +4656,7 @@
 
     // Allocate an empty rest parameter array.
     Label allocate, done_allocate;
-    __ Allocate(JSArray::kSize, v0, a0, a1, &allocate, TAG_OBJECT);
+    __ Allocate(JSArray::kSize, v0, a0, a1, &allocate, NO_ALLOCATION_FLAGS);
     __ bind(&done_allocate);
 
     // Setup the rest parameter array in v0.
@@ -4927,15 +4690,16 @@
     // ----------- S t a t e -------------
     //  -- cp : context
     //  -- a0 : number of rest parameters (tagged)
+    //  -- a1 : function
     //  -- a2 : pointer to first rest parameters
     //  -- ra : return address
     // -----------------------------------
 
     // Allocate space for the rest parameter array plus the backing store.
     Label allocate, done_allocate;
-    __ li(a1, Operand(JSArray::kSize + FixedArray::kHeaderSize));
-    __ Lsa(a1, a1, a0, kPointerSizeLog2 - 1);
-    __ Allocate(a1, v0, a3, t0, &allocate, TAG_OBJECT);
+    __ li(t0, Operand(JSArray::kSize + FixedArray::kHeaderSize));
+    __ Lsa(t0, t0, a0, kPointerSizeLog2 - 1);
+    __ Allocate(t0, v0, a3, t1, &allocate, NO_ALLOCATION_FLAGS);
     __ bind(&done_allocate);
 
     // Setup the elements array in v0.
@@ -4968,16 +4732,24 @@
     __ Ret(USE_DELAY_SLOT);
     __ mov(v0, a3);  // In delay slot
 
-    // Fall back to %AllocateInNewSpace.
+    // Fall back to %AllocateInNewSpace (if not too big).
+    Label too_big_for_new_space;
     __ bind(&allocate);
+    __ Branch(&too_big_for_new_space, gt, t0,
+              Operand(Page::kMaxRegularHeapObjectSize));
     {
       FrameScope scope(masm, StackFrame::INTERNAL);
-      __ SmiTag(a1);
-      __ Push(a0, a2, a1);
+      __ SmiTag(t0);
+      __ Push(a0, a2, t0);
       __ CallRuntime(Runtime::kAllocateInNewSpace);
       __ Pop(a0, a2);
     }
     __ jmp(&done_allocate);
+
+    // Fall back to %NewStrictArguments.
+    __ bind(&too_big_for_new_space);
+    __ Push(a1);
+    __ TailCallRuntime(Runtime::kNewStrictArguments);
   }
 }
 
@@ -4991,23 +4763,39 @@
   // -----------------------------------
   __ AssertFunction(a1);
 
+  // Make t0 point to the JavaScript frame.
+  __ mov(t0, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
+    __ lw(t0, MemOperand(t0, StandardFrameConstants::kCallerFPOffset));
+  }
+  if (FLAG_debug_code) {
+    Label ok;
+    __ lw(a3, MemOperand(t0, StandardFrameConstants::kFunctionOffset));
+    __ Branch(&ok, eq, a1, Operand(a3));
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
+  }
+
   // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub.
   __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
   __ lw(a2,
         FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ Lsa(a3, fp, a2, kPointerSizeLog2 - 1);
+  __ Lsa(a3, t0, a2, kPointerSizeLog2 - 1);
   __ Addu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset));
 
   // a1 : function
   // a2 : number of parameters (tagged)
   // a3 : parameters pointer
+  // t0 : Javascript frame pointer
   // Registers used over whole function:
   //  t1 : arguments count (tagged)
   //  t2 : mapped parameter count (tagged)
 
   // Check if the calling frame is an arguments adaptor frame.
   Label adaptor_frame, try_allocate, runtime;
-  __ lw(t0, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+  __ lw(t0, MemOperand(t0, StandardFrameConstants::kCallerFPOffset));
   __ lw(a0, MemOperand(t0, CommonFrameConstants::kContextOrFrameTypeOffset));
   __ Branch(&adaptor_frame, eq, a0,
             Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
@@ -5053,7 +4841,7 @@
   __ Addu(t5, t5, Operand(JSSloppyArgumentsObject::kSize));
 
   // Do the allocation of all three objects in one go.
-  __ Allocate(t5, v0, t5, t0, &runtime, TAG_OBJECT);
+  __ Allocate(t5, v0, t5, t0, &runtime, NO_ALLOCATION_FLAGS);
 
   // v0 = address of new object(s) (tagged)
   // a2 = argument count (smi-tagged)
@@ -5205,19 +4993,19 @@
   // -----------------------------------
   __ AssertFunction(a1);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make a2 point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ Branch(USE_DELAY_SLOT, &loop_entry);
-    __ mov(a2, fp);  // In delay slot.
-    __ bind(&loop);
+  // Make a2 point to the JavaScript frame.
+  __ mov(a2, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ lw(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset));
-    __ bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ lw(a3, MemOperand(a2, StandardFrameConstants::kFunctionOffset));
-    __ Branch(&loop, ne, a1, Operand(a3));
+    __ Branch(&ok, eq, a1, Operand(a3));
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
   }
 
   // Check if we have an arguments adaptor frame below the function frame.
@@ -5227,9 +5015,9 @@
   __ Branch(&arguments_adaptor, eq, a0,
             Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
   {
-    __ lw(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
+    __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
     __ lw(a0,
-          FieldMemOperand(a1, SharedFunctionInfo::kFormalParameterCountOffset));
+          FieldMemOperand(t0, SharedFunctionInfo::kFormalParameterCountOffset));
     __ Lsa(a2, a2, a0, kPointerSizeLog2 - 1);
     __ Addu(a2, a2, Operand(StandardFrameConstants::kCallerSPOffset -
                             1 * kPointerSize));
@@ -5247,15 +5035,16 @@
   // ----------- S t a t e -------------
   //  -- cp : context
   //  -- a0 : number of rest parameters (tagged)
+  //  -- a1 : function
   //  -- a2 : pointer to first rest parameters
   //  -- ra : return address
   // -----------------------------------
 
   // Allocate space for the strict arguments object plus the backing store.
   Label allocate, done_allocate;
-  __ li(a1, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
-  __ Lsa(a1, a1, a0, kPointerSizeLog2 - 1);
-  __ Allocate(a1, v0, a3, t0, &allocate, TAG_OBJECT);
+  __ li(t0, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
+  __ Lsa(t0, t0, a0, kPointerSizeLog2 - 1);
+  __ Allocate(t0, v0, a3, t1, &allocate, NO_ALLOCATION_FLAGS);
   __ bind(&done_allocate);
 
   // Setup the elements array in v0.
@@ -5288,46 +5077,24 @@
   __ Ret(USE_DELAY_SLOT);
   __ mov(v0, a3);  // In delay slot
 
-  // Fall back to %AllocateInNewSpace.
+  // Fall back to %AllocateInNewSpace (if not too big).
+  Label too_big_for_new_space;
   __ bind(&allocate);
+  __ Branch(&too_big_for_new_space, gt, t0,
+            Operand(Page::kMaxRegularHeapObjectSize));
   {
     FrameScope scope(masm, StackFrame::INTERNAL);
-    __ SmiTag(a1);
-    __ Push(a0, a2, a1);
+    __ SmiTag(t0);
+    __ Push(a0, a2, t0);
     __ CallRuntime(Runtime::kAllocateInNewSpace);
     __ Pop(a0, a2);
   }
   __ jmp(&done_allocate);
-}
 
-
-void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
-  Register context_reg = cp;
-  Register slot_reg = a2;
-  Register result_reg = v0;
-  Label slow_case;
-
-  // Go up context chain to the script context.
-  for (int i = 0; i < depth(); ++i) {
-    __ lw(result_reg, ContextMemOperand(context_reg, Context::PREVIOUS_INDEX));
-    context_reg = result_reg;
-  }
-
-  // Load the PropertyCell value at the specified slot.
-  __ Lsa(at, context_reg, slot_reg, kPointerSizeLog2);
-  __ lw(result_reg, ContextMemOperand(at, 0));
-  __ lw(result_reg, FieldMemOperand(result_reg, PropertyCell::kValueOffset));
-
-  // Check that value is not the_hole.
-  __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
-  __ Branch(&slow_case, eq, result_reg, Operand(at));
-  __ Ret();
-
-  // Fallback to the runtime.
-  __ bind(&slow_case);
-  __ SmiTag(slot_reg);
-  __ Push(slot_reg);
-  __ TailCallRuntime(Runtime::kLoadGlobalViaContext);
+  // Fall back to %NewStrictArguments.
+  __ bind(&too_big_for_new_space);
+  __ Push(a1);
+  __ TailCallRuntime(Runtime::kNewStrictArguments);
 }
 
 
@@ -5608,7 +5375,11 @@
   STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
   STATIC_ASSERT(FCA::kIsolateIndex == 1);
   STATIC_ASSERT(FCA::kHolderIndex == 0);
-  STATIC_ASSERT(FCA::kArgsLength == 7);
+  STATIC_ASSERT(FCA::kNewTargetIndex == 7);
+  STATIC_ASSERT(FCA::kArgsLength == 8);
+
+  // new target
+  __ PushRoot(Heap::kUndefinedValueRootIndex);
 
   // Save context, callee and call data.
   __ Push(context, callee, call_data);
@@ -5632,7 +5403,7 @@
 
   // Allocate the v8::Arguments structure in the arguments' space since
   // it's not controlled by GC.
-  const int kApiStackSpace = 4;
+  const int kApiStackSpace = 3;
 
   FrameScope frame_scope(masm, StackFrame::MANUAL);
   __ EnterExitFrame(false, kApiStackSpace);
@@ -5649,8 +5420,6 @@
   // FunctionCallbackInfo::length_ = argc
   __ li(at, Operand(argc()));
   __ sw(at, MemOperand(a0, 2 * kPointerSize));
-  // FunctionCallbackInfo::is_construct_call_ = 0
-  __ sw(zero_reg, MemOperand(a0, 3 * kPointerSize));
 
   ExternalReference thunk_ref =
       ExternalReference::invoke_function_callback(masm->isolate());
@@ -5667,8 +5436,9 @@
   }
   MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
   int stack_space = 0;
-  int32_t stack_space_offset = 4 * kPointerSize;
+  int32_t stack_space_offset = 3 * kPointerSize;
   stack_space = argc() + FCA::kArgsLength + 1;
+  // TODO(adamk): Why are we clobbering this immediately?
   stack_space_offset = kInvalidStackOffset;
   CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
                            stack_space_offset, return_value_operand,
@@ -5677,15 +5447,44 @@
 
 
 void CallApiGetterStub::Generate(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- sp[0]                        : name
-  //  -- sp[4 .. (4 + kArgsLength*4)] : v8::PropertyCallbackInfo::args_
-  //  -- ...
-  //  -- a2                           : api_function_address
-  // -----------------------------------
+  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
+  // name below the exit frame to make GC aware of them.
+  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
+  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
+  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
+  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
+  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
+  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
 
-  Register api_function_address = ApiGetterDescriptor::function_address();
-  DCHECK(api_function_address.is(a2));
+  Register receiver = ApiGetterDescriptor::ReceiverRegister();
+  Register holder = ApiGetterDescriptor::HolderRegister();
+  Register callback = ApiGetterDescriptor::CallbackRegister();
+  Register scratch = t0;
+  DCHECK(!AreAliased(receiver, holder, callback, scratch));
+
+  Register api_function_address = a2;
+
+  // Here and below +1 is for name() pushed after the args_ array.
+  typedef PropertyCallbackArguments PCA;
+  __ Subu(sp, sp, (PCA::kArgsLength + 1) * kPointerSize);
+  __ sw(receiver, MemOperand(sp, (PCA::kThisIndex + 1) * kPointerSize));
+  __ lw(scratch, FieldMemOperand(callback, AccessorInfo::kDataOffset));
+  __ sw(scratch, MemOperand(sp, (PCA::kDataIndex + 1) * kPointerSize));
+  __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
+  __ sw(scratch, MemOperand(sp, (PCA::kReturnValueOffset + 1) * kPointerSize));
+  __ sw(scratch, MemOperand(sp, (PCA::kReturnValueDefaultValueIndex + 1) *
+                                    kPointerSize));
+  __ li(scratch, Operand(ExternalReference::isolate_address(isolate())));
+  __ sw(scratch, MemOperand(sp, (PCA::kIsolateIndex + 1) * kPointerSize));
+  __ sw(holder, MemOperand(sp, (PCA::kHolderIndex + 1) * kPointerSize));
+  // should_throw_on_error -> false
+  DCHECK(Smi::FromInt(0) == nullptr);
+  __ sw(zero_reg,
+        MemOperand(sp, (PCA::kShouldThrowOnErrorIndex + 1) * kPointerSize));
+  __ lw(scratch, FieldMemOperand(callback, AccessorInfo::kNameOffset));
+  __ sw(scratch, MemOperand(sp, 0 * kPointerSize));
 
   // v8::PropertyCallbackInfo::args_ array and name handle.
   const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
@@ -5706,6 +5505,10 @@
   ExternalReference thunk_ref =
       ExternalReference::invoke_accessor_getter_callback(isolate());
 
+  __ lw(scratch, FieldMemOperand(callback, AccessorInfo::kJsGetterOffset));
+  __ lw(api_function_address,
+        FieldMemOperand(scratch, Foreign::kForeignAddressOffset));
+
   // +3 is to skip prolog, return address and name handle.
   MemOperand return_value_operand(
       fp, (PropertyCallbackArguments::kReturnValueOffset + 3) * kPointerSize);
@@ -5714,7 +5517,6 @@
                            return_value_operand, NULL);
 }
 
-
 #undef __
 
 }  // namespace internal
diff --git a/src/mips/codegen-mips.cc b/src/mips/codegen-mips.cc
index 1c6c169..07cab80 100644
--- a/src/mips/codegen-mips.cc
+++ b/src/mips/codegen-mips.cc
@@ -16,60 +16,6 @@
 
 #define __ masm.
 
-
-#if defined(USE_SIMULATOR)
-byte* fast_exp_mips_machine_code = nullptr;
-double fast_exp_simulator(double x, Isolate* isolate) {
-  return Simulator::current(isolate)->CallFP(fast_exp_mips_machine_code, x, 0);
-}
-#endif
-
-
-UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) {
-  size_t actual_size;
-  byte* buffer =
-      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
-  if (buffer == nullptr) return nullptr;
-  ExternalReference::InitializeMathExpData();
-
-  MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
-                      CodeObjectRequired::kNo);
-
-  {
-    DoubleRegister input = f12;
-    DoubleRegister result = f0;
-    DoubleRegister double_scratch1 = f4;
-    DoubleRegister double_scratch2 = f6;
-    Register temp1 = t0;
-    Register temp2 = t1;
-    Register temp3 = t2;
-
-    __ MovFromFloatParameter(input);
-    __ Push(temp3, temp2, temp1);
-    MathExpGenerator::EmitMathExp(
-        &masm, input, result, double_scratch1, double_scratch2,
-        temp1, temp2, temp3);
-    __ Pop(temp3, temp2, temp1);
-    __ MovToFloatResult(result);
-    __ Ret();
-  }
-
-  CodeDesc desc;
-  masm.GetCode(&desc);
-  DCHECK(!RelocInfo::RequiresRelocation(desc));
-
-  Assembler::FlushICache(isolate, buffer, actual_size);
-  base::OS::ProtectCode(buffer, actual_size);
-
-#if !defined(USE_SIMULATOR)
-  return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
-#else
-  fast_exp_mips_machine_code = buffer;
-  return &fast_exp_simulator;
-#endif
-}
-
-
 #if defined(V8_HOST_ARCH_MIPS)
 MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
                                                 MemCopyUint8Function stub) {
@@ -733,13 +679,13 @@
   __ sll(scratch, length, 2);
   __ Addu(scratch, scratch, FixedDoubleArray::kHeaderSize);
   __ Allocate(scratch, array, t3, scratch2, &gc_required, DOUBLE_ALIGNMENT);
-  // array: destination FixedDoubleArray, not tagged as heap object
+  // array: destination FixedDoubleArray, tagged as heap object
 
   // Set destination FixedDoubleArray's length and map.
   __ LoadRoot(scratch2, Heap::kFixedDoubleArrayMapRootIndex);
-  __ sw(length, MemOperand(array, FixedDoubleArray::kLengthOffset));
+  __ sw(length, FieldMemOperand(array, FixedDoubleArray::kLengthOffset));
   // Update receiver's map.
-  __ sw(scratch2, MemOperand(array, HeapObject::kMapOffset));
+  __ sw(scratch2, FieldMemOperand(array, HeapObject::kMapOffset));
 
   __ sw(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
   __ RecordWriteField(receiver,
@@ -751,7 +697,7 @@
                       OMIT_REMEMBERED_SET,
                       OMIT_SMI_CHECK);
   // Replace receiver's backing store with newly created FixedDoubleArray.
-  __ Addu(scratch1, array, Operand(kHeapObjectTag));
+  __ Addu(scratch1, array, Operand(kHeapObjectTag - kHeapObjectTag));
   __ sw(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset));
   __ RecordWriteField(receiver,
                       JSObject::kElementsOffset,
@@ -766,7 +712,8 @@
   // Prepare for conversion loop.
   __ Addu(scratch1, elements,
       Operand(FixedArray::kHeaderSize - kHeapObjectTag));
-  __ Addu(scratch3, array, Operand(FixedDoubleArray::kHeaderSize));
+  __ Addu(scratch3, array,
+          Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
   __ Lsa(array_end, scratch3, length, 2);
 
   // Repurpose registers no longer in use.
@@ -886,8 +833,8 @@
   // array: destination FixedArray, not tagged as heap object
   // Set destination FixedDoubleArray's length and map.
   __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
-  __ sw(length, MemOperand(array, FixedDoubleArray::kLengthOffset));
-  __ sw(scratch, MemOperand(array, HeapObject::kMapOffset));
+  __ sw(length, FieldMemOperand(array, FixedDoubleArray::kLengthOffset));
+  __ sw(scratch, FieldMemOperand(array, HeapObject::kMapOffset));
 
   // Prepare for conversion loop.
   Register src_elements = elements;
@@ -897,7 +844,8 @@
   __ Addu(src_elements, src_elements, Operand(
         FixedDoubleArray::kHeaderSize - kHeapObjectTag
         + Register::kExponentOffset));
-  __ Addu(dst_elements, array, Operand(FixedArray::kHeaderSize));
+  __ Addu(dst_elements, array,
+          Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   __ Lsa(dst_end, dst_elements, dst_end, 1);
 
   // Allocating heap numbers in the loop below can fail and cause a jump to
@@ -912,8 +860,8 @@
   __ bind(&initialization_loop_entry);
   __ Branch(&initialization_loop, lt, dst_elements, Operand(dst_end));
 
-  __ Addu(dst_elements, array, Operand(FixedArray::kHeaderSize));
-  __ Addu(array, array, Operand(kHeapObjectTag));
+  __ Addu(dst_elements, array,
+          Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
   // Using offsetted addresses.
   // dst_elements: begin of destination FixedArray element fields, not tagged
@@ -1090,95 +1038,6 @@
   __ bind(&done);
 }
 
-
-static MemOperand ExpConstant(int index, Register base) {
-  return MemOperand(base, index * kDoubleSize);
-}
-
-
-void MathExpGenerator::EmitMathExp(MacroAssembler* masm,
-                                   DoubleRegister input,
-                                   DoubleRegister result,
-                                   DoubleRegister double_scratch1,
-                                   DoubleRegister double_scratch2,
-                                   Register temp1,
-                                   Register temp2,
-                                   Register temp3) {
-  DCHECK(!input.is(result));
-  DCHECK(!input.is(double_scratch1));
-  DCHECK(!input.is(double_scratch2));
-  DCHECK(!result.is(double_scratch1));
-  DCHECK(!result.is(double_scratch2));
-  DCHECK(!double_scratch1.is(double_scratch2));
-  DCHECK(!temp1.is(temp2));
-  DCHECK(!temp1.is(temp3));
-  DCHECK(!temp2.is(temp3));
-  DCHECK(ExternalReference::math_exp_constants(0).address() != NULL);
-  DCHECK(!masm->serializer_enabled());  // External references not serializable.
-
-  Label zero, infinity, done;
-
-  __ li(temp3, Operand(ExternalReference::math_exp_constants(0)));
-
-  __ ldc1(double_scratch1, ExpConstant(0, temp3));
-  __ BranchF(&zero, NULL, ge, double_scratch1, input);
-
-  __ ldc1(double_scratch2, ExpConstant(1, temp3));
-  __ BranchF(&infinity, NULL, ge, input, double_scratch2);
-
-  __ ldc1(double_scratch1, ExpConstant(3, temp3));
-  __ ldc1(result, ExpConstant(4, temp3));
-  __ mul_d(double_scratch1, double_scratch1, input);
-  __ add_d(double_scratch1, double_scratch1, result);
-  __ FmoveLow(temp2, double_scratch1);
-  __ sub_d(double_scratch1, double_scratch1, result);
-  __ ldc1(result, ExpConstant(6, temp3));
-  __ ldc1(double_scratch2, ExpConstant(5, temp3));
-  __ mul_d(double_scratch1, double_scratch1, double_scratch2);
-  __ sub_d(double_scratch1, double_scratch1, input);
-  __ sub_d(result, result, double_scratch1);
-  __ mul_d(double_scratch2, double_scratch1, double_scratch1);
-  __ mul_d(result, result, double_scratch2);
-  __ ldc1(double_scratch2, ExpConstant(7, temp3));
-  __ mul_d(result, result, double_scratch2);
-  __ sub_d(result, result, double_scratch1);
-  // Mov 1 in double_scratch2 as math_exp_constants_array[8] == 1.
-  DCHECK(*reinterpret_cast<double*>
-         (ExternalReference::math_exp_constants(8).address()) == 1);
-  __ Move(double_scratch2, 1.);
-  __ add_d(result, result, double_scratch2);
-  __ srl(temp1, temp2, 11);
-  __ Ext(temp2, temp2, 0, 11);
-  __ Addu(temp1, temp1, Operand(0x3ff));
-
-  // Must not call ExpConstant() after overwriting temp3!
-  __ li(temp3, Operand(ExternalReference::math_exp_log_table()));
-  __ Lsa(temp3, temp3, temp2, 3);
-  __ lw(temp2, MemOperand(temp3, Register::kMantissaOffset));
-  __ lw(temp3, MemOperand(temp3, Register::kExponentOffset));
-  // The first word is loaded is the lower number register.
-  if (temp2.code() < temp3.code()) {
-    __ sll(at, temp1, 20);
-    __ Or(temp1, temp3, at);
-    __ Move(double_scratch1, temp2, temp1);
-  } else {
-    __ sll(at, temp1, 20);
-    __ Or(temp1, temp2, at);
-    __ Move(double_scratch1, temp3, temp1);
-  }
-  __ mul_d(result, result, double_scratch1);
-  __ BranchShort(&done);
-
-  __ bind(&zero);
-  __ Move(result, kDoubleRegZero);
-  __ BranchShort(&done);
-
-  __ bind(&infinity);
-  __ ldc1(result, ExpConstant(2, temp3));
-
-  __ bind(&done);
-}
-
 #ifdef DEBUG
 // nop(CODE_AGE_MARKER_NOP)
 static const uint32_t kCodeAgePatchFirstInstruction = 0x00010180;
diff --git a/src/mips/codegen-mips.h b/src/mips/codegen-mips.h
index ad7abb3..a4f8184 100644
--- a/src/mips/codegen-mips.h
+++ b/src/mips/codegen-mips.h
@@ -29,23 +29,6 @@
   DISALLOW_COPY_AND_ASSIGN(StringCharLoadGenerator);
 };
 
-
-class MathExpGenerator : public AllStatic {
- public:
-  // Register input isn't modified. All other registers are clobbered.
-  static void EmitMathExp(MacroAssembler* masm,
-                          DoubleRegister input,
-                          DoubleRegister result,
-                          DoubleRegister double_scratch1,
-                          DoubleRegister double_scratch2,
-                          Register temp1,
-                          Register temp2,
-                          Register temp3);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MathExpGenerator);
-};
-
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/mips/constants-mips.h b/src/mips/constants-mips.h
index 4914251..8301c5e 100644
--- a/src/mips/constants-mips.h
+++ b/src/mips/constants-mips.h
@@ -108,6 +108,19 @@
   (CpuFeatures::IsSupported(static_cast<CpuFeature>(check)))
 #endif
 
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+const uint32_t kMipsLwrOffset = 0;
+const uint32_t kMipsLwlOffset = 3;
+const uint32_t kMipsSwrOffset = 0;
+const uint32_t kMipsSwlOffset = 3;
+#elif defined(V8_TARGET_BIG_ENDIAN)
+const uint32_t kMipsLwrOffset = 3;
+const uint32_t kMipsLwlOffset = 0;
+const uint32_t kMipsSwrOffset = 3;
+const uint32_t kMipsSwlOffset = 0;
+#else
+#error Unknown endianness
+#endif
 
 #define __STDC_FORMAT_MACROS
 #include <inttypes.h>
@@ -409,6 +422,7 @@
   MOVZ = ((1U << 3) + 2),
   MOVN = ((1U << 3) + 3),
   BREAK = ((1U << 3) + 5),
+  SYNC = ((1U << 3) + 7),
 
   MFHI = ((2U << 3) + 0),
   CLZ_R6 = ((2U << 3) + 0),
@@ -620,7 +634,6 @@
   NULLSF = 0U
 };
 
-
 // ----- Emulated conditions.
 // On MIPS we use this enum to abstract from conditional branch instructions.
 // The 'U' prefix is used to specify unsigned comparisons.
@@ -928,8 +941,7 @@
       FunctionFieldToBitNumber(TEQ) | FunctionFieldToBitNumber(TNE) |
       FunctionFieldToBitNumber(MOVZ) | FunctionFieldToBitNumber(MOVN) |
       FunctionFieldToBitNumber(MOVCI) | FunctionFieldToBitNumber(SELEQZ_S) |
-      FunctionFieldToBitNumber(SELNEZ_S);
-
+      FunctionFieldToBitNumber(SELNEZ_S) | FunctionFieldToBitNumber(SYNC);
 
   // Get the encoding type of the instruction.
   inline Type InstructionType(TypeChecks checks = NORMAL) const;
@@ -1174,11 +1186,10 @@
           int sa = SaFieldRaw() >> kSaShift;
           switch (sa) {
             case BITSWAP:
-              return kRegisterType;
             case WSBH:
             case SEB:
             case SEH:
-              return kUnsupported;
+              return kRegisterType;
           }
           sa >>= kBp2Bits;
           switch (sa) {
diff --git a/src/mips/deoptimizer-mips.cc b/src/mips/deoptimizer-mips.cc
index e9caaad..478b9df 100644
--- a/src/mips/deoptimizer-mips.cc
+++ b/src/mips/deoptimizer-mips.cc
@@ -117,8 +117,7 @@
 
   // Save all FPU registers before messing with them.
   __ Subu(sp, sp, Operand(kDoubleRegsSize));
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
     int code = config->GetAllocatableDoubleCode(i);
     const DoubleRegister fpu_reg = DoubleRegister::from_code(code);
diff --git a/src/mips/disasm-mips.cc b/src/mips/disasm-mips.cc
index 7e0a480..bd07874 100644
--- a/src/mips/disasm-mips.cc
+++ b/src/mips/disasm-mips.cc
@@ -1191,6 +1191,9 @@
     case TNE:
       Format(instr, "tne     'rs, 'rt, code: 'code");
       break;
+    case SYNC:
+      Format(instr, "sync");
+      break;
     case MOVZ:
       Format(instr, "movz    'rd, 'rs, 'rt");
       break;
@@ -1261,11 +1264,30 @@
           }
           break;
         }
-        case SEB:
-        case SEH:
-        case WSBH:
-          UNREACHABLE();
+        case SEB: {
+          if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
+            Format(instr, "seb     'rd, 'rt");
+          } else {
+            Unknown(instr);
+          }
           break;
+        }
+        case SEH: {
+          if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
+            Format(instr, "seh     'rd, 'rt");
+          } else {
+            Unknown(instr);
+          }
+          break;
+        }
+        case WSBH: {
+          if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
+            Format(instr, "wsbh    'rd, 'rt");
+          } else {
+            Unknown(instr);
+          }
+          break;
+        }
         default: {
           sa >>= kBp2Bits;
           switch (sa) {
@@ -1696,7 +1718,7 @@
 namespace disasm {
 
 const char* NameConverter::NameOfAddress(byte* addr) const {
-  v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
+  v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
   return tmp_buffer_.start();
 }
 
@@ -1759,8 +1781,8 @@
     buffer[0] = '\0';
     byte* prev_pc = pc;
     pc += d.InstructionDecode(buffer, pc);
-    v8::internal::PrintF(f, "%p    %08x      %s\n",
-        prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
+    v8::internal::PrintF(f, "%p    %08x      %s\n", static_cast<void*>(prev_pc),
+                         *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
   }
 }
 
diff --git a/src/mips/interface-descriptors-mips.cc b/src/mips/interface-descriptors-mips.cc
index 06e3b77..a8e6e57 100644
--- a/src/mips/interface-descriptors-mips.cc
+++ b/src/mips/interface-descriptors-mips.cc
@@ -11,6 +11,14 @@
 
 const Register CallInterfaceDescriptor::ContextRegister() { return cp; }
 
+void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
+    CallInterfaceDescriptorData* data, int register_parameter_count) {
+  const Register default_stub_registers[] = {a0, a1, a2, a3, t0};
+  CHECK_LE(static_cast<size_t>(register_parameter_count),
+           arraysize(default_stub_registers));
+  data->InitializePlatformSpecific(register_parameter_count,
+                                   default_stub_registers);
+}
 
 const Register LoadDescriptor::ReceiverRegister() { return a1; }
 const Register LoadDescriptor::NameRegister() { return a2; }
@@ -39,23 +47,15 @@
 const Register StoreTransitionDescriptor::MapRegister() { return a3; }
 
 
-const Register LoadGlobalViaContextDescriptor::SlotRegister() { return a2; }
-
-
 const Register StoreGlobalViaContextDescriptor::SlotRegister() { return a2; }
 const Register StoreGlobalViaContextDescriptor::ValueRegister() { return a0; }
 
 
-const Register InstanceOfDescriptor::LeftRegister() { return a1; }
-const Register InstanceOfDescriptor::RightRegister() { return a0; }
-
-
 const Register StringCompareDescriptor::LeftRegister() { return a1; }
 const Register StringCompareDescriptor::RightRegister() { return a0; }
 
-
-const Register ApiGetterDescriptor::function_address() { return a2; }
-
+const Register ApiGetterDescriptor::HolderRegister() { return a0; }
+const Register ApiGetterDescriptor::CallbackRegister() { return a3; }
 
 const Register MathPowTaggedDescriptor::exponent() { return a2; }
 
@@ -247,50 +247,34 @@
 SIMD128_TYPES(SIMD128_ALLOC_DESC)
 #undef SIMD128_ALLOC_DESC
 
-void AllocateInNewSpaceDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  Register registers[] = {a0};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-void ArrayConstructorConstantArgCountDescriptor::InitializePlatformSpecific(
+void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // register state
   // a0 -- number of arguments
   // a1 -- function
   // a2 -- allocation site with elements kind
-  Register registers[] = {a1, a2};
+  Register registers[] = {a1, a2, a0};
   data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
+void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  // register state
+  // a0 -- number of arguments
+  // a1 -- function
+  // a2 -- allocation site with elements kind
+  Register registers[] = {a1, a2, a0};
+  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
+}
 
-void ArrayConstructorDescriptor::InitializePlatformSpecific(
+void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // stack param count needs (constructor pointer, and single argument)
   Register registers[] = {a1, a2, a0};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
-
-void InternalArrayConstructorConstantArgCountDescriptor::
-    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
-  // register state
-  // a0 -- number of arguments
-  // a1 -- constructor function
-  Register registers[] = {a1};
-  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
-}
-
-
-void InternalArrayConstructorDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  // stack param count needs (constructor pointer, and single argument)
-  Register registers[] = {a1, a0};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-void FastArrayPushDescriptor::InitializePlatformSpecific(
+void VarArgFunctionDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // stack param count needs (arg count)
   Register registers[] = {a0};
@@ -317,6 +301,11 @@
   data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
+void CountOpDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {a1};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
 
 void StringAddDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
@@ -377,9 +366,8 @@
 void InterpreterDispatchDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {
-      kInterpreterAccumulatorRegister, kInterpreterRegisterFileRegister,
-      kInterpreterBytecodeOffsetRegister, kInterpreterBytecodeArrayRegister,
-      kInterpreterDispatchTableRegister};
+      kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
+      kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
@@ -414,6 +402,16 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
+void ResumeGeneratorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {
+      v0,  // the value to pass to the generator
+      a1,  // the JSGeneratorObject to resume
+      a2   // the resume mode (tagged)
+  };
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index 7cbbd3a..86aef38 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -18,6 +18,19 @@
 namespace v8 {
 namespace internal {
 
+// Floating point constants.
+const uint32_t kDoubleSignMask = HeapNumber::kSignMask;
+const uint32_t kDoubleExponentShift = HeapNumber::kExponentShift;
+const uint32_t kDoubleNaNShift = kDoubleExponentShift - 1;
+const uint32_t kDoubleNaNMask =
+    HeapNumber::kExponentMask | (1 << kDoubleNaNShift);
+
+const uint32_t kSingleSignMask = kBinary32SignMask;
+const uint32_t kSingleExponentMask = kBinary32ExponentMask;
+const uint32_t kSingleExponentShift = kBinary32ExponentShift;
+const uint32_t kSingleNaNShift = kSingleExponentShift - 1;
+const uint32_t kSingleNaNMask = kSingleExponentMask | (1 << kSingleNaNShift);
+
 MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size,
                                CodeObjectRequired create_code_object)
     : Assembler(arg_isolate, buffer, size),
@@ -30,7 +43,6 @@
   }
 }
 
-
 void MacroAssembler::Load(Register dst,
                           const MemOperand& src,
                           Representation r) {
@@ -67,7 +79,6 @@
   }
 }
 
-
 void MacroAssembler::LoadRoot(Register destination,
                               Heap::RootListIndex index) {
   lw(destination, MemOperand(s6, index << kPointerSizeLog2));
@@ -1191,15 +1202,273 @@
 
 // ------------Pseudo-instructions-------------
 
+// Word Swap Byte
+void MacroAssembler::ByteSwapSigned(Register reg, int operand_size) {
+  DCHECK(operand_size == 1 || operand_size == 2 || operand_size == 4);
+  if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
+    if (operand_size == 2) {
+      seh(reg, reg);
+    } else if (operand_size == 1) {
+      seb(reg, reg);
+    }
+    // No need to do any preparation if operand_size is 4
+
+    wsbh(reg, reg);
+    rotr(reg, reg, 16);
+  } else if (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson)) {
+    if (operand_size == 1) {
+      sll(reg, reg, 24);
+      sra(reg, reg, 24);
+    } else if (operand_size == 2) {
+      sll(reg, reg, 16);
+      sra(reg, reg, 16);
+    }
+    // No need to do any preparation if operand_size is 4
+
+    Register tmp = t0;
+    Register tmp2 = t1;
+
+    andi(tmp2, reg, 0xFF);
+    sll(tmp2, tmp2, 24);
+    or_(tmp, zero_reg, tmp2);
+
+    andi(tmp2, reg, 0xFF00);
+    sll(tmp2, tmp2, 8);
+    or_(tmp, tmp, tmp2);
+
+    srl(reg, reg, 8);
+    andi(tmp2, reg, 0xFF00);
+    or_(tmp, tmp, tmp2);
+
+    srl(reg, reg, 16);
+    andi(tmp2, reg, 0xFF);
+    or_(tmp, tmp, tmp2);
+
+    or_(reg, tmp, zero_reg);
+  }
+}
+
+void MacroAssembler::ByteSwapUnsigned(Register reg, int operand_size) {
+  DCHECK(operand_size == 1 || operand_size == 2);
+
+  if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
+    if (operand_size == 1) {
+      andi(reg, reg, 0xFF);
+    } else {
+      andi(reg, reg, 0xFFFF);
+    }
+    // No need to do any preparation if operand_size is 4
+
+    wsbh(reg, reg);
+    rotr(reg, reg, 16);
+  } else if (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson)) {
+    if (operand_size == 1) {
+      sll(reg, reg, 24);
+    } else {
+      Register tmp = t0;
+
+      andi(tmp, reg, 0xFF00);
+      sll(reg, reg, 24);
+      sll(tmp, tmp, 8);
+      or_(reg, tmp, reg);
+    }
+  }
+}
+
 void MacroAssembler::Ulw(Register rd, const MemOperand& rs) {
-  lwr(rd, rs);
-  lwl(rd, MemOperand(rs.rm(), rs.offset() + 3));
+  DCHECK(!rd.is(at));
+  DCHECK(!rs.rm().is(at));
+  if (IsMipsArchVariant(kMips32r6)) {
+    lw(rd, rs);
+  } else {
+    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
+           IsMipsArchVariant(kLoongson));
+    if (is_int16(rs.offset() + kMipsLwrOffset) &&
+        is_int16(rs.offset() + kMipsLwlOffset)) {
+      if (!rd.is(rs.rm())) {
+        lwr(rd, MemOperand(rs.rm(), rs.offset() + kMipsLwrOffset));
+        lwl(rd, MemOperand(rs.rm(), rs.offset() + kMipsLwlOffset));
+      } else {
+        lwr(at, MemOperand(rs.rm(), rs.offset() + kMipsLwrOffset));
+        lwl(at, MemOperand(rs.rm(), rs.offset() + kMipsLwlOffset));
+        mov(rd, at);
+      }
+    } else {  // Offset > 16 bits, use multiple instructions to load.
+      LoadRegPlusOffsetToAt(rs);
+      lwr(rd, MemOperand(at, kMipsLwrOffset));
+      lwl(rd, MemOperand(at, kMipsLwlOffset));
+    }
+  }
 }
 
 
 void MacroAssembler::Usw(Register rd, const MemOperand& rs) {
-  swr(rd, rs);
-  swl(rd, MemOperand(rs.rm(), rs.offset() + 3));
+  DCHECK(!rd.is(at));
+  DCHECK(!rs.rm().is(at));
+  if (IsMipsArchVariant(kMips32r6)) {
+    sw(rd, rs);
+  } else {
+    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
+           IsMipsArchVariant(kLoongson));
+    if (is_int16(rs.offset() + kMipsSwrOffset) &&
+        is_int16(rs.offset() + kMipsSwlOffset)) {
+      swr(rd, MemOperand(rs.rm(), rs.offset() + kMipsSwrOffset));
+      swl(rd, MemOperand(rs.rm(), rs.offset() + kMipsSwlOffset));
+    } else {
+      LoadRegPlusOffsetToAt(rs);
+      swr(rd, MemOperand(at, kMipsSwrOffset));
+      swl(rd, MemOperand(at, kMipsSwlOffset));
+    }
+  }
+}
+
+void MacroAssembler::Ulh(Register rd, const MemOperand& rs) {
+  DCHECK(!rd.is(at));
+  DCHECK(!rs.rm().is(at));
+  if (IsMipsArchVariant(kMips32r6)) {
+    lh(rd, rs);
+  } else {
+    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
+           IsMipsArchVariant(kLoongson));
+    if (is_int16(rs.offset()) && is_int16(rs.offset() + 1)) {
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+      lbu(at, rs);
+      lb(rd, MemOperand(rs.rm(), rs.offset() + 1));
+#elif defined(V8_TARGET_BIG_ENDIAN)
+      lbu(at, MemOperand(rs.rm(), rs.offset() + 1));
+      lb(rd, rs);
+#endif
+    } else {  // Offset > 16 bits, use multiple instructions to load.
+      LoadRegPlusOffsetToAt(rs);
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+      lb(rd, MemOperand(at, 1));
+      lbu(at, MemOperand(at, 0));
+#elif defined(V8_TARGET_BIG_ENDIAN)
+      lb(rd, MemOperand(at, 0));
+      lbu(at, MemOperand(at, 1));
+#endif
+    }
+    sll(rd, rd, 8);
+    or_(rd, rd, at);
+  }
+}
+
+void MacroAssembler::Ulhu(Register rd, const MemOperand& rs) {
+  DCHECK(!rd.is(at));
+  DCHECK(!rs.rm().is(at));
+  if (IsMipsArchVariant(kMips32r6)) {
+    lhu(rd, rs);
+  } else {
+    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
+           IsMipsArchVariant(kLoongson));
+    if (is_int16(rs.offset()) && is_int16(rs.offset() + 1)) {
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+      lbu(at, rs);
+      lbu(rd, MemOperand(rs.rm(), rs.offset() + 1));
+#elif defined(V8_TARGET_BIG_ENDIAN)
+      lbu(at, MemOperand(rs.rm(), rs.offset() + 1));
+      lbu(rd, rs);
+#endif
+    } else {  // Offset > 16 bits, use multiple instructions to load.
+      LoadRegPlusOffsetToAt(rs);
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+      lbu(rd, MemOperand(at, 1));
+      lbu(at, MemOperand(at, 0));
+#elif defined(V8_TARGET_BIG_ENDIAN)
+      lbu(rd, MemOperand(at, 0));
+      lbu(at, MemOperand(at, 1));
+#endif
+    }
+    sll(rd, rd, 8);
+    or_(rd, rd, at);
+  }
+}
+
+void MacroAssembler::Ush(Register rd, const MemOperand& rs, Register scratch) {
+  DCHECK(!rd.is(at));
+  DCHECK(!rs.rm().is(at));
+  DCHECK(!rs.rm().is(scratch));
+  DCHECK(!scratch.is(at));
+  if (IsMipsArchVariant(kMips32r6)) {
+    sh(rd, rs);
+  } else {
+    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
+           IsMipsArchVariant(kLoongson));
+    MemOperand source = rs;
+    // If offset > 16 bits, load address to at with offset 0.
+    if (!is_int16(rs.offset()) || !is_int16(rs.offset() + 1)) {
+      LoadRegPlusOffsetToAt(rs);
+      source = MemOperand(at, 0);
+    }
+
+    if (!scratch.is(rd)) {
+      mov(scratch, rd);
+    }
+
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+    sb(scratch, source);
+    srl(scratch, scratch, 8);
+    sb(scratch, MemOperand(source.rm(), source.offset() + 1));
+#elif defined(V8_TARGET_BIG_ENDIAN)
+    sb(scratch, MemOperand(source.rm(), source.offset() + 1));
+    srl(scratch, scratch, 8);
+    sb(scratch, source);
+#endif
+  }
+}
+
+void MacroAssembler::Ulwc1(FPURegister fd, const MemOperand& rs,
+                           Register scratch) {
+  if (IsMipsArchVariant(kMips32r6)) {
+    lwc1(fd, rs);
+  } else {
+    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
+           IsMipsArchVariant(kLoongson));
+    Ulw(scratch, rs);
+    mtc1(scratch, fd);
+  }
+}
+
+void MacroAssembler::Uswc1(FPURegister fd, const MemOperand& rs,
+                           Register scratch) {
+  if (IsMipsArchVariant(kMips32r6)) {
+    swc1(fd, rs);
+  } else {
+    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
+           IsMipsArchVariant(kLoongson));
+    mfc1(scratch, fd);
+    Usw(scratch, rs);
+  }
+}
+
+void MacroAssembler::Uldc1(FPURegister fd, const MemOperand& rs,
+                           Register scratch) {
+  DCHECK(!scratch.is(at));
+  if (IsMipsArchVariant(kMips32r6)) {
+    ldc1(fd, rs);
+  } else {
+    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
+           IsMipsArchVariant(kLoongson));
+    Ulw(scratch, MemOperand(rs.rm(), rs.offset() + Register::kMantissaOffset));
+    mtc1(scratch, fd);
+    Ulw(scratch, MemOperand(rs.rm(), rs.offset() + Register::kExponentOffset));
+    Mthc1(scratch, fd);
+  }
+}
+
+void MacroAssembler::Usdc1(FPURegister fd, const MemOperand& rs,
+                           Register scratch) {
+  DCHECK(!scratch.is(at));
+  if (IsMipsArchVariant(kMips32r6)) {
+    sdc1(fd, rs);
+  } else {
+    DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1) ||
+           IsMipsArchVariant(kLoongson));
+    mfc1(scratch, fd);
+    Usw(scratch, MemOperand(rs.rm(), rs.offset() + Register::kMantissaOffset));
+    Mfhc1(scratch, fd);
+    Usw(scratch, MemOperand(rs.rm(), rs.offset() + Register::kExponentOffset));
+  }
 }
 
 
@@ -1354,6 +1623,252 @@
   addiu(sp, sp, stack_offset);
 }
 
+void MacroAssembler::AddPair(Register dst_low, Register dst_high,
+                             Register left_low, Register left_high,
+                             Register right_low, Register right_high) {
+  Label no_overflow;
+  Register kScratchReg = s3;
+  Register kScratchReg2 = s4;
+  // Add lower word
+  Addu(dst_low, left_low, right_low);
+  Addu(dst_high, left_high, right_high);
+  // Check for lower word unsigned overflow
+  Sltu(kScratchReg, dst_low, left_low);
+  Sltu(kScratchReg2, dst_low, right_low);
+  Or(kScratchReg, kScratchReg2, kScratchReg);
+  Branch(&no_overflow, eq, kScratchReg, Operand(zero_reg));
+  // Increment higher word if there was overflow
+  Addu(dst_high, dst_high, 0x1);
+  bind(&no_overflow);
+}
+
+void MacroAssembler::SubPair(Register dst_low, Register dst_high,
+                             Register left_low, Register left_high,
+                             Register right_low, Register right_high) {
+  Label no_overflow;
+  Register kScratchReg = s3;
+  // Subtract lower word
+  Subu(dst_low, left_low, right_low);
+  Subu(dst_high, left_high, right_high);
+  // Check for lower word unsigned underflow
+  Sltu(kScratchReg, left_low, right_low);
+  Branch(&no_overflow, eq, kScratchReg, Operand(zero_reg));
+  // Decrement higher word if there was underflow
+  Subu(dst_high, dst_high, 0x1);
+  bind(&no_overflow);
+}
+
+void MacroAssembler::ShlPair(Register dst_low, Register dst_high,
+                             Register src_low, Register src_high,
+                             Register shift) {
+  Label less_than_32;
+  Label zero_shift;
+  Label word_shift;
+  Label done;
+  Register kScratchReg = s3;
+  And(shift, shift, 0x3F);
+  li(kScratchReg, 0x20);
+  Branch(&less_than_32, lt, shift, Operand(kScratchReg));
+
+  Branch(&word_shift, eq, shift, Operand(kScratchReg));
+  // Shift more than 32
+  Subu(kScratchReg, shift, kScratchReg);
+  mov(dst_low, zero_reg);
+  sllv(dst_high, src_low, kScratchReg);
+  Branch(&done);
+  // Word shift
+  bind(&word_shift);
+  mov(dst_low, zero_reg);
+  mov(dst_high, src_low);
+  Branch(&done);
+
+  bind(&less_than_32);
+  // Check if zero shift
+  Branch(&zero_shift, eq, shift, Operand(zero_reg));
+  // Shift less than 32
+  Subu(kScratchReg, kScratchReg, shift);
+  sllv(dst_high, src_high, shift);
+  sllv(dst_low, src_low, shift);
+  srlv(kScratchReg, src_low, kScratchReg);
+  Or(dst_high, dst_high, kScratchReg);
+  Branch(&done);
+  // Zero shift
+  bind(&zero_shift);
+  mov(dst_low, src_low);
+  mov(dst_high, src_high);
+  bind(&done);
+}
+
+void MacroAssembler::ShlPair(Register dst_low, Register dst_high,
+                             Register src_low, Register src_high,
+                             uint32_t shift) {
+  Register kScratchReg = s3;
+  shift = shift & 0x3F;
+  if (shift < 32) {
+    if (shift == 0) {
+      mov(dst_low, src_low);
+      mov(dst_high, src_high);
+    } else {
+      sll(dst_high, src_high, shift);
+      sll(dst_low, src_low, shift);
+      shift = 32 - shift;
+      srl(kScratchReg, src_low, shift);
+      Or(dst_high, dst_high, kScratchReg);
+    }
+  } else {
+    if (shift == 32) {
+      mov(dst_low, zero_reg);
+      mov(dst_high, src_low);
+    } else {
+      shift = shift - 32;
+      mov(dst_low, zero_reg);
+      sll(dst_high, src_low, shift);
+    }
+  }
+}
+
+void MacroAssembler::ShrPair(Register dst_low, Register dst_high,
+                             Register src_low, Register src_high,
+                             Register shift) {
+  Label less_than_32;
+  Label zero_shift;
+  Label word_shift;
+  Label done;
+  Register kScratchReg = s3;
+  And(shift, shift, 0x3F);
+  li(kScratchReg, 0x20);
+  Branch(&less_than_32, lt, shift, Operand(kScratchReg));
+
+  Branch(&word_shift, eq, shift, Operand(kScratchReg));
+  // Shift more than 32
+  Subu(kScratchReg, shift, kScratchReg);
+  mov(dst_high, zero_reg);
+  srlv(dst_low, src_high, kScratchReg);
+  Branch(&done);
+  // Word shift
+  bind(&word_shift);
+  mov(dst_high, zero_reg);
+  mov(dst_low, src_high);
+  Branch(&done);
+
+  bind(&less_than_32);
+  // Check if zero shift
+  Branch(&zero_shift, eq, shift, Operand(zero_reg));
+  // Shift less than 32
+  Subu(kScratchReg, kScratchReg, shift);
+  srlv(dst_high, src_high, shift);
+  srlv(dst_low, src_low, shift);
+  sllv(kScratchReg, src_high, kScratchReg);
+  Or(dst_low, dst_low, kScratchReg);
+  Branch(&done);
+  // Zero shift
+  bind(&zero_shift);
+  mov(dst_low, src_low);
+  mov(dst_high, src_high);
+  bind(&done);
+}
+
+void MacroAssembler::ShrPair(Register dst_low, Register dst_high,
+                             Register src_low, Register src_high,
+                             uint32_t shift) {
+  Register kScratchReg = s3;
+  shift = shift & 0x3F;
+  if (shift < 32) {
+    if (shift == 0) {
+      mov(dst_low, src_low);
+      mov(dst_high, src_high);
+    } else {
+      srl(dst_high, src_high, shift);
+      srl(dst_low, src_low, shift);
+      shift = 32 - shift;
+      sll(kScratchReg, src_high, shift);
+      Or(dst_low, dst_low, kScratchReg);
+    }
+  } else {
+    if (shift == 32) {
+      mov(dst_high, zero_reg);
+      mov(dst_low, src_high);
+    } else {
+      shift = shift - 32;
+      mov(dst_high, zero_reg);
+      srl(dst_low, src_high, shift);
+    }
+  }
+}
+
+void MacroAssembler::SarPair(Register dst_low, Register dst_high,
+                             Register src_low, Register src_high,
+                             Register shift) {
+  Label less_than_32;
+  Label zero_shift;
+  Label word_shift;
+  Label done;
+  Register kScratchReg = s3;
+  Register kScratchReg2 = s4;
+  And(shift, shift, 0x3F);
+  li(kScratchReg, 0x20);
+  Branch(&less_than_32, lt, shift, Operand(kScratchReg));
+
+  Branch(&word_shift, eq, shift, Operand(kScratchReg));
+
+  // Shift more than 32
+  li(kScratchReg2, 0x1F);
+  Subu(kScratchReg, shift, kScratchReg);
+  srav(dst_high, src_high, kScratchReg2);
+  srav(dst_low, src_high, kScratchReg);
+  Branch(&done);
+  // Word shift
+  bind(&word_shift);
+  li(kScratchReg2, 0x1F);
+  srav(dst_high, src_high, kScratchReg2);
+  mov(dst_low, src_high);
+  Branch(&done);
+
+  bind(&less_than_32);
+  // Check if zero shift
+  Branch(&zero_shift, eq, shift, Operand(zero_reg));
+
+  // Shift less than 32
+  Subu(kScratchReg, kScratchReg, shift);
+  srav(dst_high, src_high, shift);
+  srlv(dst_low, src_low, shift);
+  sllv(kScratchReg, src_high, kScratchReg);
+  Or(dst_low, dst_low, kScratchReg);
+  Branch(&done);
+  // Zero shift
+  bind(&zero_shift);
+  mov(dst_low, src_low);
+  mov(dst_high, src_high);
+  bind(&done);
+}
+
+void MacroAssembler::SarPair(Register dst_low, Register dst_high,
+                             Register src_low, Register src_high,
+                             uint32_t shift) {
+  Register kScratchReg = s3;
+  shift = shift & 0x3F;
+  if (shift < 32) {
+    if (shift == 0) {
+      mov(dst_low, src_low);
+      mov(dst_high, src_high);
+    } else {
+      sra(dst_high, src_high, shift);
+      srl(dst_low, src_low, shift);
+      shift = 32 - shift;
+      sll(kScratchReg, src_high, shift);
+      Or(dst_low, dst_low, kScratchReg);
+    }
+  } else {
+    if (shift == 32) {
+      sra(dst_high, src_high, 31);
+      mov(dst_low, src_high);
+    } else {
+      shift = shift - 32;
+      sra(dst_high, src_high, 31);
+      sra(dst_low, src_high, shift);
+    }
+  }
+}
 
 void MacroAssembler::Ext(Register rt,
                          Register rs,
@@ -3401,9 +3916,6 @@
   Label start;
   bind(&start);
   int32_t target_int = reinterpret_cast<int32_t>(target);
-  // Must record previous source positions before the
-  // li() generates a new code target.
-  positions_recorder()->WriteRecordedPositions();
   li(t9, Operand(target_int, rmode), CONSTANT_SIZE);
   Call(t9, cond, rs, rt, bd);
   DCHECK_EQ(CallSize(target, rmode, cond, rs, rt, bd),
@@ -3654,6 +4166,7 @@
                               Label* gc_required,
                               AllocationFlags flags) {
   DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -3726,18 +4239,21 @@
   // to calculate the new top.
   Addu(result_end, result, Operand(object_size));
   Branch(gc_required, Ugreater, result_end, Operand(alloc_limit));
-  sw(result_end, MemOperand(top_address));
 
-  // Tag object if requested.
-  if ((flags & TAG_OBJECT) != 0) {
-    Addu(result, result, Operand(kHeapObjectTag));
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    sw(result_end, MemOperand(top_address));
   }
+
+  // Tag object.
+  Addu(result, result, Operand(kHeapObjectTag));
 }
 
 
 void MacroAssembler::Allocate(Register object_size, Register result,
                               Register result_end, Register scratch,
                               Label* gc_required, AllocationFlags flags) {
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -3810,6 +4326,7 @@
   } else {
     Addu(result_end, result, Operand(object_size));
   }
+
   Branch(gc_required, Ugreater, result_end, Operand(alloc_limit));
 
   // Update allocation top. result temporarily holds the new top.
@@ -3817,14 +4334,104 @@
     And(alloc_limit, result_end, Operand(kObjectAlignmentMask));
     Check(eq, kUnalignedAllocationInNewSpace, alloc_limit, Operand(zero_reg));
   }
-  sw(result_end, MemOperand(top_address));
 
-  // Tag object if requested.
-  if ((flags & TAG_OBJECT) != 0) {
-    Addu(result, result, Operand(kHeapObjectTag));
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    sw(result_end, MemOperand(top_address));
   }
+
+  // Tag object.
+  Addu(result, result, Operand(kHeapObjectTag));
 }
 
+void MacroAssembler::FastAllocate(int object_size, Register result,
+                                  Register scratch1, Register scratch2,
+                                  AllocationFlags flags) {
+  DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
+  DCHECK(!AreAliased(result, scratch1, scratch2, t9, at));
+
+  // Make object size into bytes.
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    object_size *= kPointerSize;
+  }
+  DCHECK_EQ(0, object_size & kObjectAlignmentMask);
+
+  ExternalReference allocation_top =
+      AllocationUtils::GetAllocationTopReference(isolate(), flags);
+
+  // Set up allocation top address and allocation limit registers.
+  Register top_address = scratch1;
+  // This code stores a temporary value in t9.
+  Register result_end = scratch2;
+  li(top_address, Operand(allocation_top));
+  lw(result, MemOperand(top_address));
+
+  if ((flags & DOUBLE_ALIGNMENT) != 0) {
+    // Align the next allocation. Storing the filler map without checking top is
+    // safe in new-space because the limit of the heap is aligned there.
+    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
+    And(result_end, result, Operand(kDoubleAlignmentMask));
+    Label aligned;
+    Branch(&aligned, eq, result_end, Operand(zero_reg));
+    li(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
+    sw(result_end, MemOperand(result));
+    Addu(result, result, Operand(kDoubleSize / 2));
+    bind(&aligned);
+  }
+
+  Addu(result_end, result, Operand(object_size));
+
+  // The top pointer is not updated for allocation folding dominators.
+  sw(result_end, MemOperand(top_address));
+
+  Addu(result, result, Operand(kHeapObjectTag));
+}
+
+void MacroAssembler::FastAllocate(Register object_size, Register result,
+                                  Register result_end, Register scratch,
+                                  AllocationFlags flags) {
+  // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag
+  // is not specified. Other registers must not overlap.
+  DCHECK(!AreAliased(object_size, result, scratch, t9, at));
+  DCHECK(!AreAliased(result_end, result, scratch, t9, at));
+  DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end));
+
+  ExternalReference allocation_top =
+      AllocationUtils::GetAllocationTopReference(isolate(), flags);
+
+  // Set up allocation top address and allocation limit registers.
+  Register top_address = scratch;
+  // This code stores a temporary value in t9.
+  li(top_address, Operand(allocation_top));
+  lw(result, MemOperand(top_address));
+
+  if ((flags & DOUBLE_ALIGNMENT) != 0) {
+    // Align the next allocation. Storing the filler map without checking top is
+    // safe in new-space because the limit of the heap is aligned there.
+    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
+    And(result_end, result, Operand(kDoubleAlignmentMask));
+    Label aligned;
+    Branch(&aligned, eq, result_end, Operand(zero_reg));
+    li(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
+    sw(result_end, MemOperand(result));
+    Addu(result, result, Operand(kDoubleSize / 2));
+    bind(&aligned);
+  }
+
+  // Calculate new top and bail out if new space is exhausted. Use result
+  // to calculate the new top. Object size may be in words so a shift is
+  // required to get the number of bytes.
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    Lsa(result_end, result, object_size, kPointerSizeLog2);
+  } else {
+    Addu(result_end, result, Operand(object_size));
+  }
+
+  // The top pointer is not updated for allocation folding dominators.
+  sw(result_end, MemOperand(top_address));
+
+  Addu(result, result, Operand(kHeapObjectTag));
+}
 
 void MacroAssembler::AllocateTwoByteString(Register result,
                                            Register length,
@@ -3841,12 +4448,8 @@
   And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
 
   // Allocate two-byte string in new space.
-  Allocate(scratch1,
-           result,
-           scratch2,
-           scratch3,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(scratch1, result, scratch2, scratch3, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   InitializeNewString(result,
@@ -3869,12 +4472,8 @@
   And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
 
   // Allocate one-byte string in new space.
-  Allocate(scratch1,
-           result,
-           scratch2,
-           scratch3,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(scratch1, result, scratch2, scratch3, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   InitializeNewString(result, length, Heap::kOneByteStringMapRootIndex,
@@ -3888,7 +4487,7 @@
                                                Register scratch2,
                                                Label* gc_required) {
   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
   InitializeNewString(result,
                       length,
                       Heap::kConsStringMapRootIndex,
@@ -3901,12 +4500,8 @@
                                                Register scratch1,
                                                Register scratch2,
                                                Label* gc_required) {
-  Allocate(ConsString::kSize,
-           result,
-           scratch1,
-           scratch2,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result, length, Heap::kConsOneByteStringMapRootIndex,
                       scratch1, scratch2);
@@ -3919,7 +4514,7 @@
                                                  Register scratch2,
                                                  Label* gc_required) {
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result,
                       length,
@@ -3935,7 +4530,7 @@
                                                  Register scratch2,
                                                  Label* gc_required) {
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result, length, Heap::kSlicedOneByteStringMapRootIndex,
                       scratch1, scratch2);
@@ -3961,12 +4556,11 @@
                                         Register scratch2,
                                         Register heap_number_map,
                                         Label* need_gc,
-                                        TaggingMode tagging_mode,
                                         MutableMode mode) {
   // Allocate an object in the heap for the heap number and tag it as a heap
   // object.
   Allocate(HeapNumber::kSize, result, scratch1, scratch2, need_gc,
-           tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS);
+           NO_ALLOCATION_FLAGS);
 
   Heap::RootListIndex map_index = mode == MUTABLE
       ? Heap::kMutableHeapNumberMapRootIndex
@@ -3974,11 +4568,7 @@
   AssertIsRoot(heap_number_map, map_index);
 
   // Store heap number map in the allocated object.
-  if (tagging_mode == TAG_RESULT) {
-    sw(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
-  } else {
-    sw(heap_number_map, MemOperand(result, HeapObject::kMapOffset));
-  }
+  sw(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
 }
 
 
@@ -4002,7 +4592,8 @@
   DCHECK(!result.is(value));
 
   // Allocate JSValue in new space.
-  Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required, TAG_OBJECT);
+  Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Initialize the JSValue.
   LoadGlobalFunctionInitialMap(constructor, scratch1, scratch2);
@@ -4145,9 +4736,7 @@
                                                  int elements_offset) {
   DCHECK(!AreAliased(value_reg, key_reg, elements_reg, scratch1, scratch2,
                      scratch3));
-  Label smi_value, maybe_nan, have_double_value, is_nan, done;
-  Register mantissa_reg = scratch2;
-  Register exponent_reg = scratch3;
+  Label smi_value, done;
 
   // Handle smi values specially.
   JumpIfSmi(value_reg, &smi_value);
@@ -4159,52 +4748,97 @@
            fail,
            DONT_DO_SMI_CHECK);
 
-  // Check for nan: all NaN values have a value greater (signed) than 0x7ff00000
-  // in the exponent.
-  li(scratch1, Operand(kHoleNanUpper32 & HeapNumber::kExponentMask));
-  lw(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset));
-  Branch(&maybe_nan, ge, exponent_reg, Operand(scratch1));
+  // Double value, turn potential sNaN into qNan.
+  DoubleRegister double_result = f0;
+  DoubleRegister double_scratch = f2;
 
-  lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
-
-  bind(&have_double_value);
-  Lsa(scratch1, elements_reg, key_reg, kDoubleSizeLog2 - kSmiTagSize);
-  sw(mantissa_reg,
-      FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize - elements_offset
-          + kHoleNanLower32Offset));
-  sw(exponent_reg,
-      FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize - elements_offset
-          + kHoleNanUpper32Offset));
-  jmp(&done);
-
-  bind(&maybe_nan);
-  // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
-  // it's an Infinity, and the non-NaN code path applies.
-  Branch(&is_nan, gt, exponent_reg, Operand(scratch1));
-  lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
-  Branch(&have_double_value, eq, mantissa_reg, Operand(zero_reg));
-  bind(&is_nan);
-  // Load canonical NaN for storing into the double array.
-  LoadRoot(at, Heap::kNanValueRootIndex);
-  lw(mantissa_reg, FieldMemOperand(at, HeapNumber::kMantissaOffset));
-  lw(exponent_reg, FieldMemOperand(at, HeapNumber::kExponentOffset));
-  jmp(&have_double_value);
+  ldc1(double_result, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
+  Branch(USE_DELAY_SLOT, &done);  // Canonicalization is one instruction.
+  FPUCanonicalizeNaN(double_result, double_result);
 
   bind(&smi_value);
+  Register untagged_value = scratch2;
+  SmiUntag(untagged_value, value_reg);
+  mtc1(untagged_value, double_scratch);
+  cvt_d_w(double_result, double_scratch);
+
+  bind(&done);
   Addu(scratch1, elements_reg,
       Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag -
               elements_offset));
   Lsa(scratch1, scratch1, key_reg, kDoubleSizeLog2 - kSmiTagSize);
   // scratch1 is now effective address of the double element
+  sdc1(double_result, MemOperand(scratch1, 0));
+}
 
-  Register untagged_value = scratch2;
-  SmiUntag(untagged_value, value_reg);
-  mtc1(untagged_value, f2);
-  cvt_d_w(f0, f2);
-  sdc1(f0, MemOperand(scratch1, 0));
+void MacroAssembler::SubNanPreservePayloadAndSign_s(FloatRegister fd,
+                                                    FloatRegister fs,
+                                                    FloatRegister ft) {
+  FloatRegister dest = fd.is(fs) || fd.is(ft) ? kLithiumScratchDouble : fd;
+  Label check_nan, save_payload, done;
+  Register scratch1 = t8;
+  Register scratch2 = t9;
+
+  sub_s(dest, fs, ft);
+  // Check if the result of subtraction is NaN.
+  BranchF32(nullptr, &check_nan, eq, fs, ft);
+  Branch(USE_DELAY_SLOT, &done);
+  dest.is(fd) ? nop() : mov_s(fd, dest);
+
+  bind(&check_nan);
+  // Check if first operand is a NaN.
+  mfc1(scratch1, fs);
+  BranchF32(nullptr, &save_payload, eq, fs, fs);
+  // Second operand must be a NaN.
+  mfc1(scratch1, ft);
+
+  bind(&save_payload);
+  // Reserve payload.
+  And(scratch1, scratch1,
+      Operand(kSingleSignMask | ((1 << kSingleNaNShift) - 1)));
+  mfc1(scratch2, dest);
+  And(scratch2, scratch2, Operand(kSingleNaNMask));
+  Or(scratch2, scratch2, scratch1);
+  mtc1(scratch2, fd);
+
   bind(&done);
 }
 
+void MacroAssembler::SubNanPreservePayloadAndSign_d(DoubleRegister fd,
+                                                    DoubleRegister fs,
+                                                    DoubleRegister ft) {
+  FloatRegister dest = fd.is(fs) || fd.is(ft) ? kLithiumScratchDouble : fd;
+  Label check_nan, save_payload, done;
+  Register scratch1 = t8;
+  Register scratch2 = t9;
+
+  sub_d(dest, fs, ft);
+  // Check if the result of subtraction is NaN.
+  BranchF64(nullptr, &check_nan, eq, fs, ft);
+  Branch(USE_DELAY_SLOT, &done);
+  dest.is(fd) ? nop() : mov_d(fd, dest);
+
+  bind(&check_nan);
+  // Check if first operand is a NaN.
+  Mfhc1(scratch1, fs);
+  mov_s(dest, fs);
+  BranchF64(nullptr, &save_payload, eq, fs, fs);
+  // Second operand must be a NaN.
+  Mfhc1(scratch1, ft);
+  mov_s(dest, ft);
+
+  bind(&save_payload);
+  // Reserve payload.
+  And(scratch1, scratch1,
+      Operand(kDoubleSignMask | ((1 << kDoubleNaNShift) - 1)));
+  Mfhc1(scratch2, dest);
+  And(scratch2, scratch2, Operand(kDoubleNaNMask));
+  Or(scratch2, scratch2, scratch1);
+  Move_s(fd, dest);
+  Mthc1(scratch2, fd);
+
+  bind(&done);
+}
 
 void MacroAssembler::CompareMapAndBranch(Register obj,
                                          Register scratch,
@@ -4268,6 +4902,10 @@
   Branch(fail, ne, scratch, Operand(at));
 }
 
+void MacroAssembler::FPUCanonicalizeNaN(const DoubleRegister dst,
+                                        const DoubleRegister src) {
+  sub_d(dst, src, kDoubleRegZero);
+}
 
 void MacroAssembler::GetWeakValue(Register value, Handle<WeakCell> cell) {
   li(value, Operand(cell));
@@ -4488,11 +5126,12 @@
                                              const ParameterCount& expected,
                                              const ParameterCount& actual) {
   Label skip_flooding;
-  ExternalReference step_in_enabled =
-      ExternalReference::debug_step_in_enabled_address(isolate());
-  li(t0, Operand(step_in_enabled));
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(isolate());
+  STATIC_ASSERT(StepFrame > StepIn);
+  li(t0, Operand(last_step_action));
   lb(t0, MemOperand(t0));
-  Branch(&skip_flooding, eq, t0, Operand(zero_reg));
+  Branch(&skip_flooding, lt, t0, Operand(StepIn));
   {
     FrameScope frame(this,
                      has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
@@ -5236,9 +5875,8 @@
 
 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
   lw(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  lw(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset));
-  lw(vector,
-     FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset));
+  lw(vector, FieldMemOperand(vector, JSFunction::kLiteralsOffset));
+  lw(vector, FieldMemOperand(vector, LiteralsArray::kFeedbackVectorOffset));
 }
 
 
@@ -5615,6 +6253,16 @@
   }
 }
 
+void MacroAssembler::AssertGeneratorObject(Register object) {
+  if (emit_debug_code()) {
+    STATIC_ASSERT(kSmiTag == 0);
+    SmiTst(object, t8);
+    Check(ne, kOperandIsASmiAndNotAGeneratorObject, t8, Operand(zero_reg));
+    GetObjectType(object, t8, t8);
+    Check(eq, kOperandIsNotAGeneratorObject, t8,
+          Operand(JS_GENERATOR_OBJECT_TYPE));
+  }
+}
 
 void MacroAssembler::AssertReceiver(Register object) {
   if (emit_debug_code()) {
@@ -6089,7 +6737,7 @@
                                                      Label* no_memento_found) {
   Label map_check;
   Label top_check;
-  ExternalReference new_space_allocation_top =
+  ExternalReference new_space_allocation_top_adr =
       ExternalReference::new_space_allocation_top_address(isolate());
   const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
   const int kMementoEndOffset = kMementoMapOffset + AllocationMemento::kSize;
@@ -6099,7 +6747,9 @@
   // If the object is in new space, we need to check whether it is on the same
   // page as the current top.
   Addu(scratch_reg, receiver_reg, Operand(kMementoEndOffset));
-  Xor(scratch_reg, scratch_reg, Operand(new_space_allocation_top));
+  li(at, Operand(new_space_allocation_top_adr));
+  lw(at, MemOperand(at));
+  Xor(scratch_reg, scratch_reg, Operand(at));
   And(scratch_reg, scratch_reg, Operand(~Page::kPageAlignmentMask));
   Branch(&top_check, eq, scratch_reg, Operand(zero_reg));
   // The object is on a different page than allocation top. Bail out if the
@@ -6115,7 +6765,7 @@
   // we are below top.
   bind(&top_check);
   Addu(scratch_reg, receiver_reg, Operand(kMementoEndOffset));
-  li(at, Operand(new_space_allocation_top));
+  li(at, Operand(new_space_allocation_top_adr));
   lw(at, MemOperand(at));
   Branch(no_memento_found, gt, scratch_reg, Operand(at));
   // Memento map check.
@@ -6140,8 +6790,7 @@
   if (reg5.is_valid()) regs |= reg5.bit();
   if (reg6.is_valid()) regs |= reg6.bit();
 
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
     int code = config->GetAllocatableGeneralCode(i);
     Register candidate = Register::from_code(code);
diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h
index 2f02865..8c6e5bd 100644
--- a/src/mips/macro-assembler-mips.h
+++ b/src/mips/macro-assembler-mips.h
@@ -18,8 +18,8 @@
 const Register kReturnRegister2 = {Register::kCode_a0};
 const Register kJSFunctionRegister = {Register::kCode_a1};
 const Register kContextRegister = {Register::kCpRegister};
+const Register kAllocateSizeRegister = {Register::kCode_a0};
 const Register kInterpreterAccumulatorRegister = {Register::kCode_v0};
-const Register kInterpreterRegisterFileRegister = {Register::kCode_t3};
 const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_t4};
 const Register kInterpreterBytecodeArrayRegister = {Register::kCode_t5};
 const Register kInterpreterDispatchTableRegister = {Register::kCode_t6};
@@ -555,6 +555,15 @@
   void Allocate(Register object_size, Register result, Register result_new,
                 Register scratch, Label* gc_required, AllocationFlags flags);
 
+  // FastAllocate is right now only used for folded allocations. It just
+  // increments the top pointer without checking against limit. This can only
+  // be done if it was proved earlier that the allocation will succeed.
+  void FastAllocate(int object_size, Register result, Register scratch1,
+                    Register scratch2, AllocationFlags flags);
+
+  void FastAllocate(Register object_size, Register result, Register result_new,
+                    Register scratch, AllocationFlags flags);
+
   void AllocateTwoByteString(Register result,
                              Register length,
                              Register scratch1,
@@ -589,7 +598,6 @@
                           Register scratch2,
                           Register heap_number_map,
                           Label* gc_required,
-                          TaggingMode tagging_mode = TAG_RESULT,
                           MutableMode mode = IMMUTABLE);
   void AllocateHeapNumberWithValue(Register result,
                                    FPURegister value,
@@ -679,11 +687,25 @@
   // ---------------------------------------------------------------------------
   // Pseudo-instructions.
 
+  // Change endianness
+  void ByteSwapSigned(Register reg, int operand_size);
+  void ByteSwapUnsigned(Register reg, int operand_size);
+
   void mov(Register rd, Register rt) { or_(rd, rt, zero_reg); }
 
+  void Ulh(Register rd, const MemOperand& rs);
+  void Ulhu(Register rd, const MemOperand& rs);
+  void Ush(Register rd, const MemOperand& rs, Register scratch);
+
   void Ulw(Register rd, const MemOperand& rs);
   void Usw(Register rd, const MemOperand& rs);
 
+  void Ulwc1(FPURegister fd, const MemOperand& rs, Register scratch);
+  void Uswc1(FPURegister fd, const MemOperand& rs, Register scratch);
+
+  void Uldc1(FPURegister fd, const MemOperand& rs, Register scratch);
+  void Usdc1(FPURegister fd, const MemOperand& rs, Register scratch);
+
   // Load int32 in the rd register.
   void li(Register rd, Operand j, LiFlags mode = OPTIMIZE_SIZE);
   inline void li(Register rd, int32_t j, LiFlags mode = OPTIMIZE_SIZE) {
@@ -809,6 +831,31 @@
   void Ins(Register rt, Register rs, uint16_t pos, uint16_t size);
   void Ext(Register rt, Register rs, uint16_t pos, uint16_t size);
 
+  // Int64Lowering instructions
+  void AddPair(Register dst_low, Register dst_high, Register left_low,
+               Register left_high, Register right_low, Register right_high);
+
+  void SubPair(Register dst_low, Register dst_high, Register left_low,
+               Register left_high, Register right_low, Register right_high);
+
+  void ShlPair(Register dst_low, Register dst_high, Register src_low,
+               Register src_high, Register shift);
+
+  void ShlPair(Register dst_low, Register dst_high, Register src_low,
+               Register src_high, uint32_t shift);
+
+  void ShrPair(Register dst_low, Register dst_high, Register src_low,
+               Register src_high, Register shift);
+
+  void ShrPair(Register dst_low, Register dst_high, Register src_low,
+               Register src_high, uint32_t shift);
+
+  void SarPair(Register dst_low, Register dst_high, Register src_low,
+               Register src_high, Register shift);
+
+  void SarPair(Register dst_low, Register dst_high, Register src_low,
+               Register src_high, uint32_t shift);
+
   // ---------------------------------------------------------------------------
   // FPU macros. These do not handle special cases like NaN or +- inf.
 
@@ -828,6 +875,12 @@
   void Floor_w_d(FPURegister fd, FPURegister fs);
   void Ceil_w_d(FPURegister fd, FPURegister fs);
 
+  // Preserve value of a NaN operand
+  void SubNanPreservePayloadAndSign_s(FPURegister fd, FPURegister fs,
+                                      FPURegister ft);
+  void SubNanPreservePayloadAndSign_d(FPURegister fd, FPURegister fs,
+                                      FPURegister ft);
+
   // FP32 mode: Move the general purpose register into
   // the high part of the double-register pair.
   // FP64 mode: Move the general-purpose register into
@@ -1188,6 +1241,9 @@
                        Handle<WeakCell> cell, Handle<Code> success,
                        SmiCheckType smi_check_type);
 
+  // If the value is a NaN, canonicalize the value else, do nothing.
+  void FPUCanonicalizeNaN(const DoubleRegister dst, const DoubleRegister src);
+
   // Get value of the weak cell.
   void GetWeakValue(Register value, Handle<WeakCell> cell);
 
@@ -1546,6 +1602,10 @@
   // enabled via --debug-code.
   void AssertBoundFunction(Register object);
 
+  // Abort execution if argument is not a JSGeneratorObject,
+  // enabled via --debug-code.
+  void AssertGeneratorObject(Register object);
+
   // Abort execution if argument is not a JSReceiver, enabled via --debug-code.
   void AssertReceiver(Register object);
 
diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
index e37b6e1..71dcda2 100644
--- a/src/mips/simulator-mips.cc
+++ b/src/mips/simulator-mips.cc
@@ -586,7 +586,7 @@
         }
 
         while (cur < end) {
-          PrintF("  0x%08x:  0x%08x %10d",
+          PrintF("  0x%08" PRIxPTR ":  0x%08x %10d",
                  reinterpret_cast<intptr_t>(cur), *cur, *cur);
           HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
           int value = *cur;
@@ -649,8 +649,8 @@
 
         while (cur < end) {
           dasm.InstructionDecode(buffer, cur);
-          PrintF("  0x%08x  %s\n",
-              reinterpret_cast<intptr_t>(cur), buffer.start());
+          PrintF("  0x%08" PRIxPTR "  %s\n", reinterpret_cast<intptr_t>(cur),
+                 buffer.start());
           cur += Instruction::kInstrSize;
         }
       } else if (strcmp(cmd, "gdb") == 0) {
@@ -771,8 +771,8 @@
 
         while (cur < end) {
           dasm.InstructionDecode(buffer, cur);
-          PrintF("  0x%08x  %s\n",
-                 reinterpret_cast<intptr_t>(cur), buffer.start());
+          PrintF("  0x%08" PRIxPTR "  %s\n", reinterpret_cast<intptr_t>(cur),
+                 buffer.start());
           cur += Instruction::kInstrSize;
         }
       } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
@@ -864,9 +864,7 @@
   last_debugger_input_ = input;
 }
 
-
-void Simulator::FlushICache(v8::internal::HashMap* i_cache,
-                            void* start_addr,
+void Simulator::FlushICache(base::HashMap* i_cache, void* start_addr,
                             size_t size) {
   intptr_t start = reinterpret_cast<intptr_t>(start_addr);
   int intra_line = (start & CachePage::kLineMask);
@@ -887,10 +885,8 @@
   }
 }
 
-
-CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
-  v8::internal::HashMap::Entry* entry =
-      i_cache->LookupOrInsert(page, ICacheHash(page));
+CachePage* Simulator::GetCachePage(base::HashMap* i_cache, void* page) {
+  base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page));
   if (entry->value == NULL) {
     CachePage* new_page = new CachePage();
     entry->value = new_page;
@@ -900,9 +896,7 @@
 
 
 // Flush from start up to and not including start + size.
-void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
-                             intptr_t start,
-                             int size) {
+void Simulator::FlushOnePage(base::HashMap* i_cache, intptr_t start, int size) {
   DCHECK(size <= CachePage::kPageSize);
   DCHECK(AllOnOnePage(start, size - 1));
   DCHECK((start & CachePage::kLineMask) == 0);
@@ -914,9 +908,7 @@
   memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
 }
 
-
-void Simulator::CheckICache(v8::internal::HashMap* i_cache,
-                            Instruction* instr) {
+void Simulator::CheckICache(base::HashMap* i_cache, Instruction* instr) {
   intptr_t address = reinterpret_cast<intptr_t>(instr);
   void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
   void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
@@ -949,7 +941,7 @@
 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
   i_cache_ = isolate_->simulator_i_cache();
   if (i_cache_ == NULL) {
-    i_cache_ = new v8::internal::HashMap(&ICacheMatch);
+    i_cache_ = new base::HashMap(&ICacheMatch);
     isolate_->set_simulator_i_cache(i_cache_);
   }
   Initialize(isolate);
@@ -1062,10 +1054,10 @@
 
 
 // static
-void Simulator::TearDown(HashMap* i_cache, Redirection* first) {
+void Simulator::TearDown(base::HashMap* i_cache, Redirection* first) {
   Redirection::DeleteChain(first);
   if (i_cache != nullptr) {
-    for (HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
+    for (base::HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
          entry = i_cache->Next(entry)) {
       delete static_cast<CachePage*>(entry->value);
     }
@@ -1786,12 +1778,12 @@
 int Simulator::ReadW(int32_t addr, Instruction* instr) {
   if (addr >=0 && addr < 0x400) {
     // This has to be a NULL-dereference, drop into debugger.
-    PrintF("Memory read from bad address: 0x%08x, pc=0x%08x\n",
-           addr, reinterpret_cast<intptr_t>(instr));
+    PrintF("Memory read from bad address: 0x%08x, pc=0x%08" PRIxPTR "\n", addr,
+           reinterpret_cast<intptr_t>(instr));
     MipsDebugger dbg(this);
     dbg.Debug();
   }
-  if ((addr & kPointerAlignmentMask) == 0) {
+  if ((addr & kPointerAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) {
     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
     TraceMemRd(addr, static_cast<int32_t>(*ptr));
     return *ptr;
@@ -1808,12 +1800,12 @@
 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
   if (addr >= 0 && addr < 0x400) {
     // This has to be a NULL-dereference, drop into debugger.
-    PrintF("Memory write to bad address: 0x%08x, pc=0x%08x\n",
-           addr, reinterpret_cast<intptr_t>(instr));
+    PrintF("Memory write to bad address: 0x%08x, pc=0x%08" PRIxPTR "\n", addr,
+           reinterpret_cast<intptr_t>(instr));
     MipsDebugger dbg(this);
     dbg.Debug();
   }
-  if ((addr & kPointerAlignmentMask) == 0) {
+  if ((addr & kPointerAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) {
     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
     TraceMemWr(addr, value, WORD);
     *ptr = value;
@@ -1828,7 +1820,7 @@
 
 
 double Simulator::ReadD(int32_t addr, Instruction* instr) {
-  if ((addr & kDoubleAlignmentMask) == 0) {
+  if ((addr & kDoubleAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) {
     double* ptr = reinterpret_cast<double*>(addr);
     return *ptr;
   }
@@ -1841,7 +1833,7 @@
 
 
 void Simulator::WriteD(int32_t addr, double value, Instruction* instr) {
-  if ((addr & kDoubleAlignmentMask) == 0) {
+  if ((addr & kDoubleAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) {
     double* ptr = reinterpret_cast<double*>(addr);
     *ptr = value;
     return;
@@ -1854,7 +1846,7 @@
 
 
 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
-  if ((addr & 1) == 0) {
+  if ((addr & 1) == 0 || IsMipsArchVariant(kMips32r6)) {
     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
     TraceMemRd(addr, static_cast<int32_t>(*ptr));
     return *ptr;
@@ -1868,7 +1860,7 @@
 
 
 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
-  if ((addr & 1) == 0) {
+  if ((addr & 1) == 0 || IsMipsArchVariant(kMips32r6)) {
     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
     TraceMemRd(addr, static_cast<int32_t>(*ptr));
     return *ptr;
@@ -1882,7 +1874,7 @@
 
 
 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
-  if ((addr & 1) == 0) {
+  if ((addr & 1) == 0 || IsMipsArchVariant(kMips32r6)) {
     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
     TraceMemWr(addr, value, HALF);
     *ptr = value;
@@ -1896,7 +1888,7 @@
 
 
 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
-  if ((addr & 1) == 0) {
+  if ((addr & 1) == 0 || IsMipsArchVariant(kMips32r6)) {
     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
     TraceMemWr(addr, value, HALF);
     *ptr = value;
@@ -1953,7 +1945,7 @@
 
 // Unsupported instructions use Format to print an error and stop execution.
 void Simulator::Format(Instruction* instr, const char* format) {
-  PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
+  PrintF("Simulator found unsupported instruction:\n 0x%08" PRIxPTR ": %s\n",
          reinterpret_cast<intptr_t>(instr), format);
   UNIMPLEMENTED_MIPS();
 }
@@ -2088,15 +2080,17 @@
           case ExternalReference::BUILTIN_FP_FP_CALL:
           case ExternalReference::BUILTIN_COMPARE_CALL:
             PrintF("Call to host function at %p with args %f, %f",
-                   FUNCTION_ADDR(generic_target), dval0, dval1);
+                   static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
+                   dval1);
             break;
           case ExternalReference::BUILTIN_FP_CALL:
             PrintF("Call to host function at %p with arg %f",
-                FUNCTION_ADDR(generic_target), dval0);
+                   static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0);
             break;
           case ExternalReference::BUILTIN_FP_INT_CALL:
             PrintF("Call to host function at %p with args %f, %d",
-                   FUNCTION_ADDR(generic_target), dval0, ival);
+                   static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
+                   ival);
             break;
           default:
             UNREACHABLE();
@@ -2195,13 +2189,15 @@
         PrintF(
             "Call to host triple returning runtime function %p "
             "args %08x, %08x, %08x, %08x, %08x\n",
-            FUNCTION_ADDR(target), arg1, arg2, arg3, arg4, arg5);
+            static_cast<void*>(FUNCTION_ADDR(target)), arg1, arg2, arg3, arg4,
+            arg5);
       }
       // arg0 is a hidden argument pointing to the return location, so don't
       // pass it to the target function.
       ObjectTriple result = target(arg1, arg2, arg3, arg4, arg5);
       if (::v8::internal::FLAG_trace_sim) {
-        PrintF("Returned { %p, %p, %p }\n", result.x, result.y, result.z);
+        PrintF("Returned { %p, %p, %p }\n", static_cast<void*>(result.x),
+               static_cast<void*>(result.y), static_cast<void*>(result.z));
       }
       // Return is passed back in address pointed to by hidden first argument.
       ObjectTriple* sim_result = reinterpret_cast<ObjectTriple*>(arg0);
@@ -2216,13 +2212,8 @@
         PrintF(
             "Call to host function at %p "
             "args %08x, %08x, %08x, %08x, %08x, %08x\n",
-            FUNCTION_ADDR(target),
-            arg0,
-            arg1,
-            arg2,
-            arg3,
-            arg4,
-            arg5);
+            static_cast<void*>(FUNCTION_ADDR(target)), arg0, arg1, arg2, arg3,
+            arg4, arg5);
       }
       int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
       set_register(v0, static_cast<int32_t>(result));
@@ -3731,6 +3722,9 @@
     case TNE:
       do_interrupt = rs() != rt();
       break;
+    case SYNC:
+      // TODO(palfia): Ignore sync instruction for now.
+      break;
     // Conditional moves.
     case MOVN:
       if (rt()) {
@@ -3839,12 +3833,51 @@
           alu_out = static_cast<int32_t>(output);
           break;
         }
-        case SEB:
-        case SEH:
-        case WSBH:
-          alu_out = 0x12345678;
-          UNREACHABLE();
+        case SEB: {
+          uint8_t input = static_cast<uint8_t>(rt());
+          uint32_t output = input;
+          uint32_t mask = 0x00000080;
+
+          // Extending sign
+          if (mask & input) {
+            output |= 0xFFFFFF00;
+          }
+
+          alu_out = static_cast<int32_t>(output);
           break;
+        }
+        case SEH: {
+          uint16_t input = static_cast<uint16_t>(rt());
+          uint32_t output = input;
+          uint32_t mask = 0x00008000;
+
+          // Extending sign
+          if (mask & input) {
+            output |= 0xFFFF0000;
+          }
+
+          alu_out = static_cast<int32_t>(output);
+          break;
+        }
+        case WSBH: {
+          uint32_t input = static_cast<uint32_t>(rt());
+          uint32_t output = 0;
+
+          uint32_t mask = 0xFF000000;
+          for (int i = 0; i < 4; i++) {
+            uint32_t tmp = mask & input;
+            if (i % 2 == 0) {
+              tmp = tmp >> 8;
+            } else {
+              tmp = tmp << 8;
+            }
+            output = output | tmp;
+            mask = mask >> 8;
+          }
+
+          alu_out = static_cast<int32_t>(output);
+          break;
+        }
         default: {
           const uint8_t bp = get_instr()->Bp2Value();
           sa >>= kBp2Bits;
@@ -4413,8 +4446,9 @@
       UNSUPPORTED();
   }
   if (::v8::internal::FLAG_trace_sim) {
-    PrintF("  0x%08x  %-44s   %s\n", reinterpret_cast<intptr_t>(instr),
-           buffer.start(), trace_buf_.start());
+    PrintF("  0x%08" PRIxPTR "  %-44s   %s\n",
+           reinterpret_cast<intptr_t>(instr), buffer.start(),
+           trace_buf_.start());
   }
   if (!pc_modified_) {
     set_register(pc, reinterpret_cast<int32_t>(instr) +
diff --git a/src/mips/simulator-mips.h b/src/mips/simulator-mips.h
index e1c42fd..5c77756 100644
--- a/src/mips/simulator-mips.h
+++ b/src/mips/simulator-mips.h
@@ -75,7 +75,7 @@
 // Running with a simulator.
 
 #include "src/assembler.h"
-#include "src/hashmap.h"
+#include "src/base/hashmap.h"
 
 namespace v8 {
 namespace internal {
@@ -216,7 +216,7 @@
   // Call on program start.
   static void Initialize(Isolate* isolate);
 
-  static void TearDown(HashMap* i_cache, Redirection* first);
+  static void TearDown(base::HashMap* i_cache, Redirection* first);
 
   // V8 generally calls into generated JS code with 5 parameters and into
   // generated RegExp code with 7 parameters. This is a convenience function,
@@ -236,8 +236,7 @@
   char* last_debugger_input() { return last_debugger_input_; }
 
   // ICache checking.
-  static void FlushICache(v8::internal::HashMap* i_cache, void* start,
-                          size_t size);
+  static void FlushICache(base::HashMap* i_cache, void* start, size_t size);
 
   // Returns true if pc register contains one of the 'special_values' defined
   // below (bad_ra, end_sim_pc).
@@ -401,10 +400,9 @@
   }
 
   // ICache.
-  static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr);
-  static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
-                           int size);
-  static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);
+  static void CheckICache(base::HashMap* i_cache, Instruction* instr);
+  static void FlushOnePage(base::HashMap* i_cache, intptr_t start, int size);
+  static CachePage* GetCachePage(base::HashMap* i_cache, void* page);
 
   enum Exception {
     none,
@@ -450,7 +448,7 @@
   char* last_debugger_input_;
 
   // Icache simulation.
-  v8::internal::HashMap* i_cache_;
+  base::HashMap* i_cache_;
 
   v8::internal::Isolate* isolate_;
 
diff --git a/src/mips64/assembler-mips64-inl.h b/src/mips64/assembler-mips64-inl.h
index dec58e8..82267ed 100644
--- a/src/mips64/assembler-mips64-inl.h
+++ b/src/mips64/assembler-mips64-inl.h
@@ -102,11 +102,6 @@
   return Assembler::target_address_at(pc_, host_);
 }
 
-Address RelocInfo::wasm_memory_reference() {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  return Assembler::target_address_at(pc_, host_);
-}
-
 Address RelocInfo::target_address_address() {
   DCHECK(IsCodeTarget(rmode_) ||
          IsRuntimeEntry(rmode_) ||
@@ -158,19 +153,6 @@
   }
 }
 
-void RelocInfo::update_wasm_memory_reference(
-    Address old_base, Address new_base, size_t old_size, size_t new_size,
-    ICacheFlushMode icache_flush_mode) {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  DCHECK(old_base <= wasm_memory_reference() &&
-         wasm_memory_reference() < old_base + old_size);
-  Address updated_reference = new_base + (wasm_memory_reference() - old_base);
-  DCHECK(new_base <= updated_reference &&
-         updated_reference < new_base + new_size);
-  Assembler::set_target_address_at(isolate_, pc_, host_, updated_reference,
-                                   icache_flush_mode);
-}
-
 Address Assembler::target_address_from_return_address(Address pc) {
   return pc - kCallTargetAddressOffset;
 }
@@ -362,7 +344,7 @@
   }
 }
 
-
+template <typename ObjectVisitor>
 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
@@ -463,6 +445,8 @@
   CheckTrampolinePoolQuick();
 }
 
+template <>
+inline void Assembler::EmitHelper(uint8_t x);
 
 template <typename T>
 void Assembler::EmitHelper(T x) {
@@ -471,6 +455,14 @@
   CheckTrampolinePoolQuick();
 }
 
+template <>
+void Assembler::EmitHelper(uint8_t x) {
+  *reinterpret_cast<uint8_t*>(pc_) = x;
+  pc_ += sizeof(x);
+  if (reinterpret_cast<intptr_t>(pc_) % kInstrSize == 0) {
+    CheckTrampolinePoolQuick();
+  }
+}
 
 void Assembler::emit(Instr x, CompactBranchType is_compact_branch) {
   if (!is_buffer_growth_blocked()) {
diff --git a/src/mips64/assembler-mips64.cc b/src/mips64/assembler-mips64.cc
index 5a8dd2c..1dece1c 100644
--- a/src/mips64/assembler-mips64.cc
+++ b/src/mips64/assembler-mips64.cc
@@ -167,6 +167,32 @@
   return false;
 }
 
+Address RelocInfo::wasm_memory_reference() {
+  DCHECK(IsWasmMemoryReference(rmode_));
+  return Assembler::target_address_at(pc_, host_);
+}
+
+Address RelocInfo::wasm_global_reference() {
+  DCHECK(IsWasmGlobalReference(rmode_));
+  return Assembler::target_address_at(pc_, host_);
+}
+
+uint32_t RelocInfo::wasm_memory_size_reference() {
+  DCHECK(IsWasmMemorySizeReference(rmode_));
+  return static_cast<uint32_t>(
+      reinterpret_cast<intptr_t>((Assembler::target_address_at(pc_, host_))));
+}
+
+void RelocInfo::unchecked_update_wasm_memory_reference(
+    Address address, ICacheFlushMode flush_mode) {
+  Assembler::set_target_address_at(isolate_, pc_, host_, address, flush_mode);
+}
+
+void RelocInfo::unchecked_update_wasm_memory_size(uint32_t size,
+                                                  ICacheFlushMode flush_mode) {
+  Assembler::set_target_address_at(isolate_, pc_, host_,
+                                   reinterpret_cast<Address>(size), flush_mode);
+}
 
 // -----------------------------------------------------------------------------
 // Implementation of Operand and MemOperand.
@@ -274,6 +300,8 @@
       static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos());
   desc->origin = this;
   desc->constant_pool_size = 0;
+  desc->unwinding_info_size = 0;
+  desc->unwinding_info = nullptr;
 }
 
 
@@ -1226,7 +1254,6 @@
 
 
 void Assembler::bal(int16_t offset) {
-  positions_recorder()->WriteRecordedPositions();
   bgezal(zero_reg, offset);
 }
 
@@ -1239,7 +1266,6 @@
 
 void Assembler::balc(int32_t offset) {
   DCHECK(kArchVariant == kMips64r6);
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(BALC, offset, CompactBranchType::COMPACT_BRANCH);
 }
 
@@ -1286,7 +1312,6 @@
 void Assembler::bgezal(Register rs, int16_t offset) {
   DCHECK(kArchVariant != kMips64r6 || rs.is(zero_reg));
   BlockTrampolinePoolScope block_trampoline_pool(this);
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(REGIMM, rs, BGEZAL, offset);
   BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
@@ -1357,7 +1382,6 @@
 void Assembler::bltzal(Register rs, int16_t offset) {
   DCHECK(kArchVariant != kMips64r6 || rs.is(zero_reg));
   BlockTrampolinePoolScope block_trampoline_pool(this);
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(REGIMM, rs, BLTZAL, offset);
   BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
@@ -1393,7 +1417,6 @@
 void Assembler::blezalc(Register rt, int16_t offset) {
   DCHECK(kArchVariant == kMips64r6);
   DCHECK(!(rt.is(zero_reg)));
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(BLEZ, zero_reg, rt, offset,
                     CompactBranchType::COMPACT_BRANCH);
 }
@@ -1402,7 +1425,6 @@
 void Assembler::bgezalc(Register rt, int16_t offset) {
   DCHECK(kArchVariant == kMips64r6);
   DCHECK(!(rt.is(zero_reg)));
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(BLEZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
 }
 
@@ -1411,7 +1433,6 @@
   DCHECK(kArchVariant != kMips64r6);
   DCHECK(!(rs.is(zero_reg)));
   BlockTrampolinePoolScope block_trampoline_pool(this);
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(REGIMM, rs, BGEZALL, offset);
   BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
@@ -1420,7 +1441,6 @@
 void Assembler::bltzalc(Register rt, int16_t offset) {
   DCHECK(kArchVariant == kMips64r6);
   DCHECK(!(rt.is(zero_reg)));
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(BGTZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH);
 }
 
@@ -1428,7 +1448,6 @@
 void Assembler::bgtzalc(Register rt, int16_t offset) {
   DCHECK(kArchVariant == kMips64r6);
   DCHECK(!(rt.is(zero_reg)));
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(BGTZ, zero_reg, rt, offset,
                     CompactBranchType::COMPACT_BRANCH);
 }
@@ -1437,7 +1456,6 @@
 void Assembler::beqzalc(Register rt, int16_t offset) {
   DCHECK(kArchVariant == kMips64r6);
   DCHECK(!(rt.is(zero_reg)));
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(ADDI, zero_reg, rt, offset,
                     CompactBranchType::COMPACT_BRANCH);
 }
@@ -1446,7 +1464,6 @@
 void Assembler::bnezalc(Register rt, int16_t offset) {
   DCHECK(kArchVariant == kMips64r6);
   DCHECK(!(rt.is(zero_reg)));
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(DADDI, zero_reg, rt, offset,
                     CompactBranchType::COMPACT_BRANCH);
 }
@@ -1512,7 +1529,6 @@
   uint64_t imm = jump_offset(target);
   if (target->is_bound()) {
     BlockTrampolinePoolScope block_trampoline_pool(this);
-    positions_recorder()->WriteRecordedPositions();
     GenInstrJump(static_cast<Opcode>(kJalRawMark),
                  static_cast<uint32_t>(imm >> 2) & kImm26Mask);
     BlockTrampolinePoolFor(1);  // For associated delay slot.
@@ -1525,9 +1541,6 @@
 void Assembler::jr(Register rs) {
   if (kArchVariant != kMips64r6) {
     BlockTrampolinePoolScope block_trampoline_pool(this);
-    if (rs.is(ra)) {
-      positions_recorder()->WriteRecordedPositions();
-    }
     GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR);
     BlockTrampolinePoolFor(1);  // For associated delay slot.
   } else {
@@ -1538,7 +1551,6 @@
 
 void Assembler::jal(int64_t target) {
   BlockTrampolinePoolScope block_trampoline_pool(this);
-  positions_recorder()->WriteRecordedPositions();
   GenInstrJump(JAL, static_cast<uint32_t>(target >> 2) & kImm26Mask);
   BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
@@ -1547,7 +1559,6 @@
 void Assembler::jalr(Register rs, Register rd) {
   DCHECK(rs.code() != rd.code());
   BlockTrampolinePoolScope block_trampoline_pool(this);
-  positions_recorder()->WriteRecordedPositions();
   GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR);
   BlockTrampolinePoolFor(1);  // For associated delay slot.
 }
@@ -1561,7 +1572,6 @@
 
 void Assembler::jialc(Register rt, int16_t offset) {
   DCHECK(kArchVariant == kMips64r6);
-  positions_recorder()->WriteRecordedPositions();
   GenInstrImmediate(POP76, zero_reg, rt, offset);
 }
 
@@ -2001,11 +2011,15 @@
 
 
 void Assembler::lwl(Register rd, const MemOperand& rs) {
+  DCHECK(is_int16(rs.offset_));
+  DCHECK(kArchVariant == kMips64r2);
   GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_);
 }
 
 
 void Assembler::lwr(Register rd, const MemOperand& rs) {
+  DCHECK(is_int16(rs.offset_));
+  DCHECK(kArchVariant == kMips64r2);
   GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_);
 }
 
@@ -2041,11 +2055,15 @@
 
 
 void Assembler::swl(Register rd, const MemOperand& rs) {
+  DCHECK(is_int16(rs.offset_));
+  DCHECK(kArchVariant == kMips64r2);
   GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_);
 }
 
 
 void Assembler::swr(Register rd, const MemOperand& rs) {
+  DCHECK(is_int16(rs.offset_));
+  DCHECK(kArchVariant == kMips64r2);
   GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_);
 }
 
@@ -2084,21 +2102,29 @@
 
 
 void Assembler::ldl(Register rd, const MemOperand& rs) {
+  DCHECK(is_int16(rs.offset_));
+  DCHECK(kArchVariant == kMips64r2);
   GenInstrImmediate(LDL, rs.rm(), rd, rs.offset_);
 }
 
 
 void Assembler::ldr(Register rd, const MemOperand& rs) {
+  DCHECK(is_int16(rs.offset_));
+  DCHECK(kArchVariant == kMips64r2);
   GenInstrImmediate(LDR, rs.rm(), rd, rs.offset_);
 }
 
 
 void Assembler::sdl(Register rd, const MemOperand& rs) {
+  DCHECK(is_int16(rs.offset_));
+  DCHECK(kArchVariant == kMips64r2);
   GenInstrImmediate(SDL, rs.rm(), rd, rs.offset_);
 }
 
 
 void Assembler::sdr(Register rd, const MemOperand& rs) {
+  DCHECK(is_int16(rs.offset_));
+  DCHECK(kArchVariant == kMips64r2);
   GenInstrImmediate(SDR, rs.rm(), rd, rs.offset_);
 }
 
@@ -2255,6 +2281,10 @@
   emit(instr);
 }
 
+void Assembler::sync() {
+  Instr sync_instr = SPECIAL | SYNC;
+  emit(sync_instr);
+}
 
 // Move from HI/LO register.
 
@@ -2488,6 +2518,30 @@
   GenInstrRegister(SPECIAL3, rs, rt, rd, sa, DBSHFL);
 }
 
+void Assembler::wsbh(Register rd, Register rt) {
+  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
+  GenInstrRegister(SPECIAL3, zero_reg, rt, rd, WSBH, BSHFL);
+}
+
+void Assembler::dsbh(Register rd, Register rt) {
+  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
+  GenInstrRegister(SPECIAL3, zero_reg, rt, rd, DSBH, DBSHFL);
+}
+
+void Assembler::dshd(Register rd, Register rt) {
+  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
+  GenInstrRegister(SPECIAL3, zero_reg, rt, rd, DSHD, DBSHFL);
+}
+
+void Assembler::seh(Register rd, Register rt) {
+  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
+  GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEH, BSHFL);
+}
+
+void Assembler::seb(Register rd, Register rt) {
+  DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
+  GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEB, BSHFL);
+}
 
 // --------Coprocessor-instructions----------------
 
@@ -3208,6 +3262,7 @@
     data = reinterpret_cast<uint64_t>(buffer_ + label->pos());
   } else {
     data = jump_address(label);
+    unbound_labels_count_++;
     internal_reference_positions_.insert(label->pos());
   }
   RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
@@ -3394,7 +3449,6 @@
   }
 }
 
-
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/mips64/assembler-mips64.h b/src/mips64/assembler-mips64.h
index de09366..ff3611d 100644
--- a/src/mips64/assembler-mips64.h
+++ b/src/mips64/assembler-mips64.h
@@ -63,6 +63,8 @@
   V(f16) V(f17) V(f18) V(f19) V(f20) V(f21) V(f22) V(f23) \
   V(f24) V(f25) V(f26) V(f27) V(f28) V(f29) V(f30) V(f31)
 
+#define FLOAT_REGISTERS DOUBLE_REGISTERS
+
 #define ALLOCATABLE_DOUBLE_REGISTERS(V)                   \
   V(f0)  V(f2)  V(f4)  V(f6)  V(f8)  V(f10) V(f12) V(f14) \
   V(f16) V(f18) V(f20) V(f22) V(f24) V(f26)
@@ -123,8 +125,6 @@
     return r;
   }
 
-  const char* ToString();
-  bool IsAllocatable() const;
   bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
   bool is(Register reg) const { return reg_code == reg.reg_code; }
   int code() const {
@@ -153,8 +153,10 @@
 
 Register ToRegister(int num);
 
+static const bool kSimpleFPAliasing = true;
+
 // Coprocessor register.
-struct DoubleRegister {
+struct FPURegister {
   enum Code {
 #define REGISTER_CODE(R) kCode_##R,
     DOUBLE_REGISTERS(REGISTER_CODE)
@@ -171,24 +173,22 @@
   // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
   // number of Double regs (64-bit regs, or FPU-reg-pairs).
 
-  const char* ToString();
-  bool IsAllocatable() const;
   bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
-  bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
-  DoubleRegister low() const {
+  bool is(FPURegister reg) const { return reg_code == reg.reg_code; }
+  FPURegister low() const {
     // TODO(plind): Create DCHECK for FR=0 mode. This usage suspect for FR=1.
     // Find low reg of a Double-reg pair, which is the reg itself.
     DCHECK(reg_code % 2 == 0);  // Specified Double reg must be even.
-    DoubleRegister reg;
+    FPURegister reg;
     reg.reg_code = reg_code;
     DCHECK(reg.is_valid());
     return reg;
   }
-  DoubleRegister high() const {
+  FPURegister high() const {
     // TODO(plind): Create DCHECK for FR=0 mode. This usage illegal in FR=1.
     // Find high reg of a Doubel-reg pair, which is reg + 1.
     DCHECK(reg_code % 2 == 0);  // Specified Double reg must be even.
-    DoubleRegister reg;
+    FPURegister reg;
     reg.reg_code = reg_code + 1;
     DCHECK(reg.is_valid());
     return reg;
@@ -203,8 +203,8 @@
     return 1 << reg_code;
   }
 
-  static DoubleRegister from_code(int code) {
-    DoubleRegister r = {code};
+  static FPURegister from_code(int code) {
+    FPURegister r = {code};
     return r;
   }
   void setcode(int f) {
@@ -229,8 +229,12 @@
 // but it is not in common use. Someday we will want to support this in v8.)
 
 // For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers.
-typedef DoubleRegister FPURegister;
-typedef DoubleRegister FloatRegister;
+typedef FPURegister FloatRegister;
+
+typedef FPURegister DoubleRegister;
+
+// TODO(mips64) Define SIMD registers.
+typedef FPURegister Simd128Register;
 
 const DoubleRegister no_freg = {-1};
 
@@ -306,9 +310,6 @@
 const FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister };
 const FPUControlRegister FCSR = { kFCSRRegister };
 
-// TODO(mips64) Define SIMD registers.
-typedef DoubleRegister Simd128Register;
-
 // -----------------------------------------------------------------------------
 // Machine instruction Operands.
 const int kSmiShift = kSmiTagSize + kSmiShiftSize;
@@ -849,6 +850,9 @@
   void teq(Register rs, Register rt, uint16_t code);
   void tne(Register rs, Register rt, uint16_t code);
 
+  // Memory barrier instruction.
+  void sync();
+
   // Move from HI/LO register.
   void mfhi(Register rd);
   void mflo(Register rd);
@@ -901,6 +905,12 @@
   void align(Register rd, Register rs, Register rt, uint8_t bp);
   void dalign(Register rd, Register rs, Register rt, uint8_t bp);
 
+  void wsbh(Register rd, Register rt);
+  void dsbh(Register rd, Register rt);
+  void dshd(Register rd, Register rt);
+  void seh(Register rd, Register rt);
+  void seb(Register rd, Register rt);
+
   // --------Coprocessor-instructions----------------
 
   // Load, store, and move.
@@ -1099,7 +1109,7 @@
 
   // Record a deoptimization reason that can be used by a log or cpu profiler.
   // Use --trace-deopt to enable.
-  void RecordDeoptReason(const int reason, int raw_position);
+  void RecordDeoptReason(const int reason, int raw_position, int id);
 
   static int RelocateInternalReference(RelocInfo::Mode rmode, byte* pc,
                                        intptr_t pc_delta);
@@ -1212,11 +1222,16 @@
 
   bool IsPrevInstrCompactBranch() { return prev_instr_compact_branch_; }
 
+  inline int UnboundLabelsCount() { return unbound_labels_count_; }
+
  protected:
   // Load Scaled Address instructions.
   void lsa(Register rd, Register rt, Register rs, uint8_t sa);
   void dlsa(Register rd, Register rt, Register rs, uint8_t sa);
 
+  // Helpers.
+  void LoadRegPlusOffsetToAt(const MemOperand& src);
+
   // Relocation for a type-recording IC has the AST id added to it.  This
   // member variable is a way to pass the information from the call site to
   // the relocation info.
@@ -1413,9 +1428,6 @@
   void GenInstrJump(Opcode opcode,
                      uint32_t address);
 
-  // Helpers.
-  void LoadRegPlusOffsetToAt(const MemOperand& src);
-
   // Labels.
   void print(Label* L);
   void bind_to(Label* L, int pos);
diff --git a/src/mips64/builtins-mips64.cc b/src/mips64/builtins-mips64.cc
index b55b77c..025093e 100644
--- a/src/mips64/builtins-mips64.cc
+++ b/src/mips64/builtins-mips64.cc
@@ -16,10 +16,7 @@
 
 #define __ ACCESS_MASM(masm)
 
-
-void Builtins::Generate_Adaptor(MacroAssembler* masm,
-                                CFunctionId id,
-                                BuiltinExtraArguments extra_args) {
+void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
   // ----------- S t a t e -------------
   //  -- a0                 : number of arguments excluding receiver
   //  -- a1                 : target
@@ -38,23 +35,8 @@
   __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
 
   // Insert extra arguments.
-  int num_extra_args = 0;
-  switch (extra_args) {
-    case BuiltinExtraArguments::kTarget:
-      __ Push(a1);
-      ++num_extra_args;
-      break;
-    case BuiltinExtraArguments::kNewTarget:
-      __ Push(a3);
-      ++num_extra_args;
-      break;
-    case BuiltinExtraArguments::kTargetAndNewTarget:
-      __ Push(a1, a3);
-      num_extra_args += 2;
-      break;
-    case BuiltinExtraArguments::kNone:
-      break;
-  }
+  const int num_extra_args = 2;
+  __ Push(a1, a3);
 
   // JumpToExternalReference expects a0 to contain the number of arguments
   // including the receiver and the extra arguments.
@@ -144,6 +126,8 @@
 void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
   // ----------- S t a t e -------------
   //  -- a0                 : number of arguments
+  //  -- a1                 : function
+  //  -- cp                 : context
   //  -- ra                 : return address
   //  -- sp[(argc - n) * 8] : arg[n] (zero-based)
   //  -- sp[(argc + 1) * 8] : receiver
@@ -153,9 +137,9 @@
                                      : Heap::kMinusInfinityValueRootIndex;
 
   // Load the accumulator with the default return value (either -Infinity or
-  // +Infinity), with the tagged value in a1 and the double value in f0.
-  __ LoadRoot(a1, root_index);
-  __ ldc1(f0, FieldMemOperand(a1, HeapNumber::kValueOffset));
+  // +Infinity), with the tagged value in t1 and the double value in f0.
+  __ LoadRoot(t1, root_index);
+  __ ldc1(f0, FieldMemOperand(t1, HeapNumber::kValueOffset));
   __ Addu(a3, a0, 1);
 
   Label done_loop, loop;
@@ -170,35 +154,39 @@
     __ ld(a2, MemOperand(at));
 
     // Load the double value of the parameter into f2, maybe converting the
-    // parameter to a number first using the ToNumberStub if necessary.
+    // parameter to a number first using the ToNumber builtin if necessary.
     Label convert, convert_smi, convert_number, done_convert;
     __ bind(&convert);
     __ JumpIfSmi(a2, &convert_smi);
     __ ld(a4, FieldMemOperand(a2, HeapObject::kMapOffset));
     __ JumpIfRoot(a4, Heap::kHeapNumberMapRootIndex, &convert_number);
     {
-      // Parameter is not a Number, use the ToNumberStub to convert it.
-      FrameScope scope(masm, StackFrame::INTERNAL);
+      // Parameter is not a Number, use the ToNumber builtin to convert it.
+      FrameScope scope(masm, StackFrame::MANUAL);
+      __ Push(ra, fp);
+      __ Move(fp, sp);
+      __ Push(cp, a1);
       __ SmiTag(a0);
       __ SmiTag(a3);
-      __ Push(a0, a1, a3);
+      __ Push(a0, t1, a3);
       __ mov(a0, a2);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
       __ mov(a2, v0);
-      __ Pop(a0, a1, a3);
+      __ Pop(a0, t1, a3);
       {
         // Restore the double accumulator value (f0).
         Label restore_smi, done_restore;
-        __ JumpIfSmi(a1, &restore_smi);
-        __ ldc1(f0, FieldMemOperand(a1, HeapNumber::kValueOffset));
+        __ JumpIfSmi(t1, &restore_smi);
+        __ ldc1(f0, FieldMemOperand(t1, HeapNumber::kValueOffset));
         __ jmp(&done_restore);
         __ bind(&restore_smi);
-        __ SmiToDoubleFPURegister(a1, f0, a4);
+        __ SmiToDoubleFPURegister(t1, f0, a4);
         __ bind(&done_restore);
       }
       __ SmiUntag(a3);
       __ SmiUntag(a0);
+      __ Pop(cp, a1);
+      __ Pop(ra, fp);
     }
     __ jmp(&convert);
     __ bind(&convert_number);
@@ -223,20 +211,20 @@
     }
     __ Move(at, f0);
     __ Branch(&loop, eq, a4, Operand(at));
-    __ mov(a1, a2);
+    __ mov(t1, a2);
     __ jmp(&loop);
 
     // At least one side is NaN, which means that the result will be NaN too.
     __ bind(&compare_nan);
-    __ LoadRoot(a1, Heap::kNanValueRootIndex);
-    __ ldc1(f0, FieldMemOperand(a1, HeapNumber::kValueOffset));
+    __ LoadRoot(t1, Heap::kNanValueRootIndex);
+    __ ldc1(f0, FieldMemOperand(t1, HeapNumber::kValueOffset));
     __ jmp(&loop);
   }
 
   __ bind(&done_loop);
   __ Dlsa(sp, sp, a3, kPointerSizeLog2);
   __ Ret(USE_DELAY_SLOT);
-  __ mov(v0, a1);  // In delay slot.
+  __ mov(v0, t1);  // In delay slot.
 }
 
 // static
@@ -261,8 +249,7 @@
   }
 
   // 2a. Convert first argument to number.
-  ToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
+  __ Jump(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
 
   // 2b. No arguments, return +0.
   __ bind(&no_arguments);
@@ -309,8 +296,7 @@
     {
       FrameScope scope(masm, StackFrame::INTERNAL);
       __ Push(a1, a3);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
       __ Move(a0, v0);
       __ Pop(a1, a3);
     }
@@ -592,16 +578,9 @@
     // a0: number of arguments
     // a1: constructor function
     // a3: new target
-    if (is_api_function) {
-      __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
-      Handle<Code> code =
-          masm->isolate()->builtins()->HandleApiCallConstruct();
-      __ Call(code, RelocInfo::CODE_TARGET);
-    } else {
-      ParameterCount actual(a0);
-      __ InvokeFunction(a1, a3, actual, CALL_FUNCTION,
-                        CheckDebugStepCallWrapper());
-    }
+    ParameterCount actual(a0);
+    __ InvokeFunction(a1, a3, actual, CALL_FUNCTION,
+                      CheckDebugStepCallWrapper());
 
     // Store offset of return address for deoptimizer.
     if (create_implicit_receiver && !is_api_function) {
@@ -690,6 +669,161 @@
   Generate_JSConstructStubHelper(masm, false, false, true);
 }
 
+// static
+void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- v0 : the value to pass to the generator
+  //  -- a1 : the JSGeneratorObject to resume
+  //  -- a2 : the resume mode (tagged)
+  //  -- ra : return address
+  // -----------------------------------
+  __ AssertGeneratorObject(a1);
+
+  // Store input value into generator object.
+  __ sd(v0, FieldMemOperand(a1, JSGeneratorObject::kInputOrDebugPosOffset));
+  __ RecordWriteField(a1, JSGeneratorObject::kInputOrDebugPosOffset, v0, a3,
+                      kRAHasNotBeenSaved, kDontSaveFPRegs);
+
+  // Store resume mode into generator object.
+  __ sd(a2, FieldMemOperand(a1, JSGeneratorObject::kResumeModeOffset));
+
+  // Load suspended function and context.
+  __ ld(cp, FieldMemOperand(a1, JSGeneratorObject::kContextOffset));
+  __ ld(a4, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
+
+  // Flood function if we are stepping.
+  Label prepare_step_in_if_stepping, prepare_step_in_suspended_generator;
+  Label stepping_prepared;
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(masm->isolate());
+  STATIC_ASSERT(StepFrame > StepIn);
+  __ li(a5, Operand(last_step_action));
+  __ lb(a5, MemOperand(a5));
+  __ Branch(&prepare_step_in_if_stepping, ge, a5, Operand(StepIn));
+
+  // Flood function if we need to continue stepping in the suspended generator.
+  ExternalReference debug_suspended_generator =
+      ExternalReference::debug_suspended_generator_address(masm->isolate());
+  __ li(a5, Operand(debug_suspended_generator));
+  __ ld(a5, MemOperand(a5));
+  __ Branch(&prepare_step_in_suspended_generator, eq, a1, Operand(a5));
+  __ bind(&stepping_prepared);
+
+  // Push receiver.
+  __ ld(a5, FieldMemOperand(a1, JSGeneratorObject::kReceiverOffset));
+  __ Push(a5);
+
+  // ----------- S t a t e -------------
+  //  -- a1    : the JSGeneratorObject to resume
+  //  -- a2    : the resume mode (tagged)
+  //  -- a4    : generator function
+  //  -- cp    : generator context
+  //  -- ra    : return address
+  //  -- sp[0] : generator receiver
+  // -----------------------------------
+
+  // Push holes for arguments to generator function. Since the parser forced
+  // context allocation for any variables in generators, the actual argument
+  // values have already been copied into the context and these dummy values
+  // will never be used.
+  __ ld(a3, FieldMemOperand(a4, JSFunction::kSharedFunctionInfoOffset));
+  __ lw(a3,
+        FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
+  {
+    Label done_loop, loop;
+    __ bind(&loop);
+    __ Dsubu(a3, a3, Operand(1));
+    __ Branch(&done_loop, lt, a3, Operand(zero_reg));
+    __ PushRoot(Heap::kTheHoleValueRootIndex);
+    __ Branch(&loop);
+    __ bind(&done_loop);
+  }
+
+  // Dispatch on the kind of generator object.
+  Label old_generator;
+  __ ld(a3, FieldMemOperand(a4, JSFunction::kSharedFunctionInfoOffset));
+  __ ld(a3, FieldMemOperand(a3, SharedFunctionInfo::kFunctionDataOffset));
+  __ GetObjectType(a3, a3, a3);
+  __ Branch(&old_generator, ne, a3, Operand(BYTECODE_ARRAY_TYPE));
+
+  // New-style (ignition/turbofan) generator object.
+  {
+    __ ld(a0, FieldMemOperand(a4, JSFunction::kSharedFunctionInfoOffset));
+    __ lw(a0,
+         FieldMemOperand(a0, SharedFunctionInfo::kFormalParameterCountOffset));
+    // We abuse new.target both to indicate that this is a resume call and to
+    // pass in the generator object.  In ordinary calls, new.target is always
+    // undefined because generator functions are non-constructable.
+    __ Move(a3, a1);
+    __ Move(a1, a4);
+    __ ld(a2, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
+    __ Jump(a2);
+  }
+
+  // Old-style (full-codegen) generator object
+  __ bind(&old_generator);
+  {
+    // Enter a new JavaScript frame, and initialize its slots as they were when
+    // the generator was suspended.
+    FrameScope scope(masm, StackFrame::MANUAL);
+    __ Push(ra, fp);
+    __ Move(fp, sp);
+    __ Push(cp, a4);
+
+    // Restore the operand stack.
+    __ ld(a0, FieldMemOperand(a1, JSGeneratorObject::kOperandStackOffset));
+    __ ld(a3, FieldMemOperand(a0, FixedArray::kLengthOffset));
+    __ SmiUntag(a3);
+    __ Daddu(a0, a0, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+    __ Dlsa(a3, a0, a3, kPointerSizeLog2);
+    {
+      Label done_loop, loop;
+      __ bind(&loop);
+      __ Branch(&done_loop, eq, a0, Operand(a3));
+      __ ld(a5, MemOperand(a0));
+      __ Push(a5);
+      __ Branch(USE_DELAY_SLOT, &loop);
+      __ daddiu(a0, a0, kPointerSize);  // In delay slot.
+      __ bind(&done_loop);
+    }
+
+    // Reset operand stack so we don't leak.
+    __ LoadRoot(a5, Heap::kEmptyFixedArrayRootIndex);
+    __ sd(a5, FieldMemOperand(a1, JSGeneratorObject::kOperandStackOffset));
+
+    // Resume the generator function at the continuation.
+    __ ld(a3, FieldMemOperand(a4, JSFunction::kSharedFunctionInfoOffset));
+    __ ld(a3, FieldMemOperand(a3, SharedFunctionInfo::kCodeOffset));
+    __ Daddu(a3, a3, Operand(Code::kHeaderSize - kHeapObjectTag));
+    __ ld(a2, FieldMemOperand(a1, JSGeneratorObject::kContinuationOffset));
+    __ SmiUntag(a2);
+    __ Daddu(a3, a3, Operand(a2));
+    __ li(a2, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
+    __ sd(a2, FieldMemOperand(a1, JSGeneratorObject::kContinuationOffset));
+    __ Move(v0, a1);  // Continuation expects generator object in v0.
+    __ Jump(a3);
+  }
+
+  __ bind(&prepare_step_in_if_stepping);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ Push(a1, a2, a4);
+    __ CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
+    __ Pop(a1, a2);
+  }
+  __ Branch(USE_DELAY_SLOT, &stepping_prepared);
+  __ ld(a4, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
+
+  __ bind(&prepare_step_in_suspended_generator);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ Push(a1, a2);
+    __ CallRuntime(Runtime::kDebugPrepareStepInSuspendedGenerator);
+    __ Pop(a1, a2);
+  }
+  __ Branch(USE_DELAY_SLOT, &stepping_prepared);
+  __ ld(a4, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
+}
 
 void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
   FrameScope scope(masm, StackFrame::INTERNAL);
@@ -813,6 +947,20 @@
   Generate_JSEntryTrampolineHelper(masm, true);
 }
 
+static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch) {
+  Register args_count = scratch;
+
+  // Get the arguments + receiver count.
+  __ ld(args_count,
+        MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
+  __ lw(t0, FieldMemOperand(args_count, BytecodeArray::kParameterSizeOffset));
+
+  // Leave the frame (also dropping the register file).
+  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+
+  // Drop receiver + arguments.
+  __ Daddu(sp, sp, args_count);
+}
 
 // Generate code for entering a JS function with the interpreter.
 // On entry to the function the receiver and arguments have been pushed on the
@@ -830,14 +978,16 @@
 // The function builds an interpreter frame.  See InterpreterFrameConstants in
 // frames.h for its layout.
 void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
+  ProfileEntryHookStub::MaybeCallEntryHook(masm);
+
   // Open a frame scope to indicate that there is a frame on the stack.  The
   // MANUAL indicates that the scope shouldn't actually generate code to set up
   // the frame (that is done below).
   FrameScope frame_scope(masm, StackFrame::MANUAL);
   __ PushStandardFrame(a1);
 
-  // Get the bytecode array from the function object and load the pointer to the
-  // first entry into kInterpreterBytecodeRegister.
+  // Get the bytecode array from the function object (or from the DebugInfo if
+  // it is present) and load it into kInterpreterBytecodeArrayRegister.
   __ ld(a0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
   Label load_debug_bytecode_array, bytecode_array_loaded;
   Register debug_info = kInterpreterBytecodeArrayRegister;
@@ -849,8 +999,11 @@
         FieldMemOperand(a0, SharedFunctionInfo::kFunctionDataOffset));
   __ bind(&bytecode_array_loaded);
 
+  // Check function data field is actually a BytecodeArray object.
+  Label bytecode_array_not_present;
+  __ JumpIfRoot(kInterpreterBytecodeArrayRegister,
+                Heap::kUndefinedValueRootIndex, &bytecode_array_not_present);
   if (FLAG_debug_code) {
-    // Check function data field is actually a BytecodeArray object.
     __ SmiTst(kInterpreterBytecodeArrayRegister, a4);
     __ Assert(ne, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry, a4,
               Operand(zero_reg));
@@ -859,8 +1012,13 @@
               Operand(BYTECODE_ARRAY_TYPE));
   }
 
-  // Push new.target, bytecode array and zero for bytecode array offset.
-  __ Push(a3, kInterpreterBytecodeArrayRegister, zero_reg);
+  // Load initial bytecode offset.
+  __ li(kInterpreterBytecodeOffsetRegister,
+        Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
+
+  // Push new.target, bytecode array and Smi tagged bytecode array offset.
+  __ SmiTag(a4, kInterpreterBytecodeOffsetRegister);
+  __ Push(a3, kInterpreterBytecodeArrayRegister, a4);
 
   // Allocate the local and temporary register file on the stack.
   {
@@ -890,17 +1048,8 @@
     __ Branch(&loop_header, ge, a4, Operand(zero_reg));
   }
 
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's prologue:
-  //  - Call ProfileEntryHookStub when isolate has a function_entry_hook.
-  //  - Code aging of the BytecodeArray object.
-
-  // Load bytecode offset and dispatch table into registers.
+  // Load accumulator and dispatch table into registers.
   __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
-  __ Daddu(kInterpreterRegisterFileRegister, fp,
-           Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
-  __ li(kInterpreterBytecodeOffsetRegister,
-        Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
   __ li(kInterpreterDispatchTableRegister,
         Operand(ExternalReference::interpreter_dispatch_table_address(
             masm->isolate())));
@@ -911,42 +1060,57 @@
   __ lbu(a0, MemOperand(a0));
   __ Dlsa(at, kInterpreterDispatchTableRegister, a0, kPointerSizeLog2);
   __ ld(at, MemOperand(at));
-  // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
-  // and header removal.
-  __ Daddu(at, at, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Call(at);
+  masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
 
-  // Even though the first bytecode handler was called, we will never return.
-  __ Abort(kUnexpectedReturnFromBytecodeHandler);
+  // The return value is in v0.
+  LeaveInterpreterFrame(masm, t0);
+  __ Jump(ra);
 
   // Load debug copy of the bytecode array.
   __ bind(&load_debug_bytecode_array);
   __ ld(kInterpreterBytecodeArrayRegister,
         FieldMemOperand(debug_info, DebugInfo::kAbstractCodeIndex));
   __ Branch(&bytecode_array_loaded);
+
+  // If the bytecode array is no longer present, then the underlying function
+  // has been switched to a different kind of code and we heal the closure by
+  // switching the code entry field over to the new code object as well.
+  __ bind(&bytecode_array_not_present);
+  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+  __ ld(a4, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
+  __ ld(a4, FieldMemOperand(a4, SharedFunctionInfo::kCodeOffset));
+  __ Daddu(a4, a4, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ sd(a4, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
+  __ RecordWriteCodeEntryField(a1, a4, a5);
+  __ Jump(a4);
 }
 
+void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) {
+  // Save the function and context for call to CompileBaseline.
+  __ ld(a1, MemOperand(fp, StandardFrameConstants::kFunctionOffset));
+  __ ld(kContextRegister,
+        MemOperand(fp, StandardFrameConstants::kContextOffset));
 
-void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's EmitReturnSequence.
-  //  - Supporting FLAG_trace for Runtime::TraceExit.
-  //  - Support profiler (specifically decrementing profiling_counter
-  //    appropriately and calling out to HandleInterrupts if necessary).
+  // Leave the frame before recompiling for baseline so that we don't count as
+  // an activation on the stack.
+  LeaveInterpreterFrame(masm, t0);
 
-  // The return value is in accumulator, which is already in v0.
+  {
+    FrameScope frame_scope(masm, StackFrame::INTERNAL);
+    // Push return value.
+    __ push(v0);
 
-  // Leave the frame (also dropping the register file).
-  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+    // Push function as argument and compile for baseline.
+    __ push(a1);
+    __ CallRuntime(Runtime::kCompileBaseline);
 
-  // Drop receiver + arguments and return.
-  __ lw(at, FieldMemOperand(kInterpreterBytecodeArrayRegister,
-                            BytecodeArray::kParameterSizeOffset));
-  __ Daddu(sp, sp, at);
+    // Restore return value.
+    __ pop(v0);
+  }
   __ Jump(ra);
 }
 
-
 // static
 void Builtins::Generate_InterpreterPushArgsAndCallImpl(
     MacroAssembler* masm, TailCallMode tail_call_mode) {
@@ -979,7 +1143,6 @@
           RelocInfo::CODE_TARGET);
 }
 
-
 // static
 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
   // ----------- S t a t e -------------
@@ -1010,25 +1173,24 @@
   __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
 }
 
+void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
+  // Set the return address to the correct point in the interpreter entry
+  // trampoline.
+  Smi* interpreter_entry_return_pc_offset(
+      masm->isolate()->heap()->interpreter_entry_return_pc_offset());
+  DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
+  __ li(t0, Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline()));
+  __ Daddu(ra, t0, Operand(interpreter_entry_return_pc_offset->value() +
+                           Code::kHeaderSize - kHeapObjectTag));
 
-static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
-  // Initialize register file register and dispatch table register.
-  __ Daddu(kInterpreterRegisterFileRegister, fp,
-           Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
+  // Initialize the dispatch table register.
   __ li(kInterpreterDispatchTableRegister,
         Operand(ExternalReference::interpreter_dispatch_table_address(
             masm->isolate())));
 
-  // Get the context from the frame.
-  __ ld(kContextRegister,
-        MemOperand(kInterpreterRegisterFileRegister,
-                   InterpreterFrameConstants::kContextFromRegisterPointer));
-
   // Get the bytecode array pointer from the frame.
-  __ ld(
-      kInterpreterBytecodeArrayRegister,
-      MemOperand(kInterpreterRegisterFileRegister,
-                 InterpreterFrameConstants::kBytecodeArrayFromRegisterPointer));
+  __ ld(kInterpreterBytecodeArrayRegister,
+        MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
 
   if (FLAG_debug_code) {
     // Check function data field is actually a BytecodeArray object.
@@ -1042,9 +1204,7 @@
 
   // Get the target bytecode offset from the frame.
   __ ld(kInterpreterBytecodeOffsetRegister,
-        MemOperand(
-            kInterpreterRegisterFileRegister,
-            InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
+        MemOperand(fp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
   __ SmiUntag(kInterpreterBytecodeOffsetRegister);
 
   // Dispatch to the target bytecode.
@@ -1053,70 +1213,184 @@
   __ lbu(a1, MemOperand(a1));
   __ Dlsa(a1, kInterpreterDispatchTableRegister, a1, kPointerSizeLog2);
   __ ld(a1, MemOperand(a1));
-  __ Daddu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Jump(a1);
 }
 
-
-static void Generate_InterpreterNotifyDeoptimizedHelper(
-    MacroAssembler* masm, Deoptimizer::BailoutType type) {
-  // Enter an internal frame.
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Pass the deoptimization type to the runtime system.
-    __ li(a1, Operand(Smi::FromInt(static_cast<int>(type))));
-    __ push(a1);
-    __ CallRuntime(Runtime::kNotifyDeoptimized);
-    // Tear down internal frame.
-  }
-
-  // Drop state (we don't use these for interpreter deopts) and and pop the
-  // accumulator value into the accumulator register.
-  __ Drop(1);
-  __ Pop(kInterpreterAccumulatorRegister);
-
-  // Enter the bytecode dispatch.
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-
-void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
-}
-
-
-void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
-}
-
-
-void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
-}
-
-void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
-  // Set the address of the interpreter entry trampoline as a return address.
-  // This simulates the initial call to bytecode handlers in interpreter entry
-  // trampoline. The return will never actually be taken, but our stack walker
-  // uses this address to determine whether a frame is interpreted.
-  __ li(ra, Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline()));
-
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-
 void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- a0 : argument count (preserved for callee)
+  //  -- a3 : new target (preserved for callee)
+  //  -- a1 : target function (preserved for callee)
+  // -----------------------------------
+  // First lookup code, maybe we don't need to compile!
+  Label gotta_call_runtime, gotta_call_runtime_no_stack;
+  Label maybe_call_runtime;
+  Label try_shared;
+  Label loop_top, loop_bottom;
+
+  Register argument_count = a0;
+  Register closure = a1;
+  Register new_target = a3;
+  __ push(argument_count);
+  __ push(new_target);
+  __ push(closure);
+
+  Register map = a0;
+  Register index = a2;
+  __ ld(map, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ ld(map, FieldMemOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset));
+  __ ld(index, FieldMemOperand(map, FixedArray::kLengthOffset));
+  __ Branch(&gotta_call_runtime, lt, index, Operand(Smi::FromInt(2)));
+
+  // Find literals.
+  // a3  : native context
+  // a2  : length / index
+  // a0  : optimized code map
+  // stack[0] : new target
+  // stack[4] : closure
+  Register native_context = a3;
+  __ ld(native_context, NativeContextMemOperand());
+
+  __ bind(&loop_top);
+  Register temp = a1;
+  Register array_pointer = a5;
+
+  // Does the native context match?
+  __ SmiScale(at, index, kPointerSizeLog2);
+  __ Daddu(array_pointer, map, Operand(at));
+  __ ld(temp, FieldMemOperand(array_pointer,
+                              SharedFunctionInfo::kOffsetToPreviousContext));
+  __ ld(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
+  __ Branch(&loop_bottom, ne, temp, Operand(native_context));
+  // OSR id set to none?
+  __ ld(temp, FieldMemOperand(array_pointer,
+                              SharedFunctionInfo::kOffsetToPreviousOsrAstId));
+  const int bailout_id = BailoutId::None().ToInt();
+  __ Branch(&loop_bottom, ne, temp, Operand(Smi::FromInt(bailout_id)));
+
+  // Literals available?
+  Label got_literals, maybe_cleared_weakcell;
+  __ ld(temp, FieldMemOperand(array_pointer,
+                              SharedFunctionInfo::kOffsetToPreviousLiterals));
+  // temp contains either a WeakCell pointing to the literals array or the
+  // literals array directly.
+  __ ld(a4, FieldMemOperand(temp, WeakCell::kValueOffset));
+  __ JumpIfSmi(a4, &maybe_cleared_weakcell);
+  // a4 is a pointer, therefore temp is a WeakCell pointing to a literals array.
+  __ ld(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
+  __ jmp(&got_literals);
+
+  // a4 is a smi. If it's 0, then we are looking at a cleared WeakCell
+  // around the literals array, and we should visit the runtime. If it's > 0,
+  // then temp already contains the literals array.
+  __ bind(&maybe_cleared_weakcell);
+  __ Branch(&gotta_call_runtime, eq, a4, Operand(Smi::FromInt(0)));
+
+  // Save the literals in the closure.
+  __ bind(&got_literals);
+  __ ld(a4, MemOperand(sp, 0));
+  __ sd(temp, FieldMemOperand(a4, JSFunction::kLiteralsOffset));
+  __ push(index);
+  __ RecordWriteField(a4, JSFunction::kLiteralsOffset, temp, index,
+                      kRAHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  __ pop(index);
+
+  // Code available?
+  Register entry = a4;
+  __ ld(entry,
+        FieldMemOperand(array_pointer,
+                        SharedFunctionInfo::kOffsetToPreviousCachedCode));
+  __ ld(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &maybe_call_runtime);
+
+  // Found literals and code. Get them into the closure and return.
+  __ pop(closure);
+  // Store code entry in the closure.
+  __ Daddu(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+
+  Label install_optimized_code_and_tailcall;
+  __ bind(&install_optimized_code_and_tailcall);
+  __ sd(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
+  __ RecordWriteCodeEntryField(closure, entry, a5);
+
+  // Link the closure into the optimized function list.
+  // a4 : code entry
+  // a3 : native context
+  // a1 : closure
+  __ ld(a5,
+        ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
+  __ sd(a5, FieldMemOperand(closure, JSFunction::kNextFunctionLinkOffset));
+  __ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, a5, a0,
+                      kRAHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  const int function_list_offset =
+      Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
+  __ sd(closure,
+        ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
+  // Save closure before the write barrier.
+  __ mov(a5, closure);
+  __ RecordWriteContextSlot(native_context, function_list_offset, closure, a0,
+                            kRAHasNotBeenSaved, kDontSaveFPRegs);
+  __ mov(closure, a5);
+  __ pop(new_target);
+  __ pop(argument_count);
+  __ Jump(entry);
+
+  __ bind(&loop_bottom);
+  __ Dsubu(index, index,
+           Operand(Smi::FromInt(SharedFunctionInfo::kEntryLength)));
+  __ Branch(&loop_top, gt, index, Operand(Smi::FromInt(1)));
+
+  // We found neither literals nor code.
+  __ jmp(&gotta_call_runtime);
+
+  __ bind(&maybe_call_runtime);
+  __ pop(closure);
+
+  // Last possibility. Check the context free optimized code map entry.
+  __ ld(entry, FieldMemOperand(map, FixedArray::kHeaderSize +
+                                        SharedFunctionInfo::kSharedCodeIndex));
+  __ ld(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &try_shared);
+
+  // Store code entry in the closure.
+  __ Daddu(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ jmp(&install_optimized_code_and_tailcall);
+
+  __ bind(&try_shared);
+  __ pop(new_target);
+  __ pop(argument_count);
+  // Is the full code valid?
+  __ ld(entry, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ ld(entry, FieldMemOperand(entry, SharedFunctionInfo::kCodeOffset));
+  __ lw(a5, FieldMemOperand(entry, Code::kFlagsOffset));
+  __ And(a5, a5, Operand(Code::KindField::kMask));
+  __ dsrl(a5, a5, Code::KindField::kShift);
+  __ Branch(&gotta_call_runtime_no_stack, eq, a5, Operand(Code::BUILTIN));
+  // Yes, install the full code.
+  __ Daddu(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ sd(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset));
+  __ RecordWriteCodeEntryField(closure, entry, a5);
+  __ Jump(entry);
+
+  __ bind(&gotta_call_runtime);
+  __ pop(closure);
+  __ pop(new_target);
+  __ pop(argument_count);
+  __ bind(&gotta_call_runtime_no_stack);
   GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
 }
 
+void Builtins::Generate_CompileBaseline(MacroAssembler* masm) {
+  GenerateTailCallToReturnedCode(masm, Runtime::kCompileBaseline);
+}
 
 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
   GenerateTailCallToReturnedCode(masm,
                                  Runtime::kCompileOptimized_NotConcurrent);
 }
 
-
 void Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) {
   GenerateTailCallToReturnedCode(masm, Runtime::kCompileOptimized_Concurrent);
 }
@@ -1252,15 +1526,19 @@
   __ SmiUntag(a6);
   // Switch on the state.
   Label with_tos_register, unknown_state;
-  __ Branch(&with_tos_register,
-            ne, a6, Operand(FullCodeGenerator::NO_REGISTERS));
+  __ Branch(
+      &with_tos_register, ne, a6,
+      Operand(static_cast<int64_t>(Deoptimizer::BailoutState::NO_REGISTERS)));
   __ Ret(USE_DELAY_SLOT);
   // Safe to fill delay slot Addu will emit one instruction.
   __ Daddu(sp, sp, Operand(1 * kPointerSize));  // Remove state.
 
   __ bind(&with_tos_register);
+  DCHECK_EQ(kInterpreterAccumulatorRegister.code(), v0.code());
   __ ld(v0, MemOperand(sp, 1 * kPointerSize));
-  __ Branch(&unknown_state, ne, a6, Operand(FullCodeGenerator::TOS_REG));
+  __ Branch(
+      &unknown_state, ne, a6,
+      Operand(static_cast<int64_t>(Deoptimizer::BailoutState::TOS_REGISTER)));
 
   __ Ret(USE_DELAY_SLOT);
   // Safe to fill delay slot Addu will emit one instruction.
@@ -1424,6 +1702,9 @@
 void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
                                                int field_index) {
   // ----------- S t a t e -------------
+  //  -- a0                 : number of arguments
+  //  -- a1                 : function
+  //  -- cp                 : context
   //  -- sp[0] : receiver
   // -----------------------------------
 
@@ -1463,29 +1744,14 @@
 
   // 3. Raise a TypeError if the receiver is not a date.
   __ bind(&receiver_not_date);
-  __ TailCallRuntime(Runtime::kThrowNotDateError);
-}
-
-// static
-void Builtins::Generate_FunctionHasInstance(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- a0    : argc
-  //  -- sp[0] : first argument (left-hand side)
-  //  -- sp[8] : receiver (right-hand side)
-  // -----------------------------------
-
   {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-    __ ld(InstanceOfDescriptor::LeftRegister(),
-          MemOperand(fp, 2 * kPointerSize));  // Load left-hand side.
-    __ ld(InstanceOfDescriptor::RightRegister(),
-          MemOperand(fp, 3 * kPointerSize));  // Load right-hand side.
-    InstanceOfStub stub(masm->isolate(), true);
-    __ CallStub(&stub);
+    FrameScope scope(masm, StackFrame::MANUAL);
+    __ Push(a0, ra, fp);
+    __ Move(fp, sp);
+    __ Push(cp, a1);
+    __ Push(Smi::FromInt(0));
+    __ CallRuntime(Runtime::kThrowNotDateError);
   }
-
-  // Pop the argument and the receiver.
-  __ DropAndRet(2);
 }
 
 // static
@@ -2457,6 +2723,107 @@
           RelocInfo::CODE_TARGET);
 }
 
+// static
+void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- a0 : requested object size (untagged)
+  //  -- ra : return address
+  // -----------------------------------
+  __ SmiTag(a0);
+  __ Push(a0);
+  __ Move(cp, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInNewSpace);
+}
+
+// static
+void Builtins::Generate_AllocateInOldSpace(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- a0 : requested object size (untagged)
+  //  -- ra : return address
+  // -----------------------------------
+  __ SmiTag(a0);
+  __ Move(a1, Smi::FromInt(AllocateTargetSpace::encode(OLD_SPACE)));
+  __ Push(a0, a1);
+  __ Move(cp, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInTargetSpace);
+}
+
+// static
+void Builtins::Generate_StringToNumber(MacroAssembler* masm) {
+  // The StringToNumber stub takes on argument in a0.
+  __ AssertString(a0);
+
+  // Check if string has a cached array index.
+  Label runtime;
+  __ lwu(a2, FieldMemOperand(a0, String::kHashFieldOffset));
+  __ And(at, a2, Operand(String::kContainsCachedArrayIndexMask));
+  __ Branch(&runtime, ne, at, Operand(zero_reg));
+  __ IndexFromHash(a2, v0);
+  __ Ret();
+
+  __ bind(&runtime);
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ Push(a0);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kStringToNumber);
+  }
+  __ Ret();
+}
+
+// static
+void Builtins::Generate_ToNumber(MacroAssembler* masm) {
+  // The ToNumber stub takes one argument in a0.
+  Label not_smi;
+  __ JumpIfNotSmi(a0, &not_smi);
+  __ Ret(USE_DELAY_SLOT);
+  __ mov(v0, a0);
+  __ bind(&not_smi);
+
+  Label not_heap_number;
+  __ GetObjectType(a0, a1, a1);
+  // a0: receiver
+  // a1: receiver instance type
+  __ Branch(&not_heap_number, ne, a1, Operand(HEAP_NUMBER_TYPE));
+  __ Ret(USE_DELAY_SLOT);
+  __ mov(v0, a0);
+  __ bind(&not_heap_number);
+
+  __ Jump(masm->isolate()->builtins()->NonNumberToNumber(),
+          RelocInfo::CODE_TARGET);
+}
+
+// static
+void Builtins::Generate_NonNumberToNumber(MacroAssembler* masm) {
+  // The NonNumberToNumber stub takes on argument in a0.
+  __ AssertNotNumber(a0);
+
+  Label not_string;
+  __ GetObjectType(a0, a1, a1);
+  // a0: receiver
+  // a1: receiver instance type
+  __ Branch(&not_string, hs, a1, Operand(FIRST_NONSTRING_TYPE));
+  __ Jump(masm->isolate()->builtins()->StringToNumber(),
+          RelocInfo::CODE_TARGET);
+  __ bind(&not_string);
+
+  Label not_oddball;
+  __ Branch(&not_oddball, ne, a1, Operand(ODDBALL_TYPE));
+  __ Ret(USE_DELAY_SLOT);
+  __ ld(v0, FieldMemOperand(a0, Oddball::kToNumberOffset));  // In delay slot.
+  __ bind(&not_oddball);
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ Push(a0);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kToNumber);
+  }
+  __ Ret();
+}
 
 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
   // State setup as expected by MacroAssembler::InvokePrologue.
diff --git a/src/mips64/code-stubs-mips64.cc b/src/mips64/code-stubs-mips64.cc
index fdb6c81..89eff90 100644
--- a/src/mips64/code-stubs-mips64.cc
+++ b/src/mips64/code-stubs-mips64.cc
@@ -20,60 +20,16 @@
 namespace v8 {
 namespace internal {
 
+#define __ ACCESS_MASM(masm)
 
-static void InitializeArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  Address deopt_handler = Runtime::FunctionForId(
-      Runtime::kArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(a0, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-
-static void InitializeInternalArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  Address deopt_handler = Runtime::FunctionForId(
-      Runtime::kInternalArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(a0, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-
-void ArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 0);
-}
-
-
-void ArraySingleArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 1);
-}
-
-
-void ArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-void InternalArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0);
+void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
+  __ dsll(t9, a0, kPointerSizeLog2);
+  __ Daddu(t9, sp, t9);
+  __ sd(a1, MemOperand(t9, 0));
+  __ Push(a1);
+  __ Push(a2);
+  __ Daddu(a0, a0, 3);
+  __ TailCallRuntime(Runtime::kNewArray);
 }
 
 void FastArrayPushStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
@@ -81,20 +37,12 @@
   descriptor->Initialize(a0, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-void InternalArraySingleArgumentConstructorStub::InitializeDescriptor(
+void FastFunctionBindStub::InitializeDescriptor(
     CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1);
+  Address deopt_handler = Runtime::FunctionForId(Runtime::kFunctionBind)->entry;
+  descriptor->Initialize(a0, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-
-void InternalArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-#define __ ACCESS_MASM(masm)
-
 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
                                           Condition cc);
 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
@@ -1030,7 +978,7 @@
   CEntryStub::GenerateAheadOfTime(isolate);
   StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
   StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
-  ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
+  CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate);
   CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
   CreateWeakCellStub::GenerateAheadOfTime(isolate);
   BinaryOpICStub::GenerateAheadOfTime(isolate);
@@ -1447,7 +1395,6 @@
                                           &miss,  // When not a string.
                                           &miss,  // When not a number.
                                           &miss,  // When index out of range.
-                                          STRING_INDEX_IS_ARRAY_INDEX,
                                           RECEIVER_IS_STRING);
   char_at_generator.GenerateFast(masm);
   __ Ret();
@@ -1461,128 +1408,6 @@
 }
 
 
-void InstanceOfStub::Generate(MacroAssembler* masm) {
-  Register const object = a1;              // Object (lhs).
-  Register const function = a0;            // Function (rhs).
-  Register const object_map = a2;          // Map of {object}.
-  Register const function_map = a3;        // Map of {function}.
-  Register const function_prototype = a4;  // Prototype of {function}.
-  Register const scratch = a5;
-
-  DCHECK(object.is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(function.is(InstanceOfDescriptor::RightRegister()));
-
-  // Check if {object} is a smi.
-  Label object_is_smi;
-  __ JumpIfSmi(object, &object_is_smi);
-
-  // Lookup the {function} and the {object} map in the global instanceof cache.
-  // Note: This is safe because we clear the global instanceof cache whenever
-  // we change the prototype of any object.
-  Label fast_case, slow_case;
-  __ ld(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
-  __ LoadRoot(at, Heap::kInstanceofCacheFunctionRootIndex);
-  __ Branch(&fast_case, ne, function, Operand(at));
-  __ LoadRoot(at, Heap::kInstanceofCacheMapRootIndex);
-  __ Branch(&fast_case, ne, object_map, Operand(at));
-  __ Ret(USE_DELAY_SLOT);
-  __ LoadRoot(v0, Heap::kInstanceofCacheAnswerRootIndex);  // In delay slot.
-
-  // If {object} is a smi we can safely return false if {function} is a JS
-  // function, otherwise we have to miss to the runtime and throw an exception.
-  __ bind(&object_is_smi);
-  __ JumpIfSmi(function, &slow_case);
-  __ GetObjectType(function, function_map, scratch);
-  __ Branch(&slow_case, ne, scratch, Operand(JS_FUNCTION_TYPE));
-  __ Ret(USE_DELAY_SLOT);
-  __ LoadRoot(v0, Heap::kFalseValueRootIndex);  // In delay slot.
-
-  // Fast-case: The {function} must be a valid JSFunction.
-  __ bind(&fast_case);
-  __ JumpIfSmi(function, &slow_case);
-  __ GetObjectType(function, function_map, scratch);
-  __ Branch(&slow_case, ne, scratch, Operand(JS_FUNCTION_TYPE));
-
-  // Go to the runtime if the function is not a constructor.
-  __ lbu(scratch, FieldMemOperand(function_map, Map::kBitFieldOffset));
-  __ And(at, scratch, Operand(1 << Map::kIsConstructor));
-  __ Branch(&slow_case, eq, at, Operand(zero_reg));
-
-  // Ensure that {function} has an instance prototype.
-  __ And(at, scratch, Operand(1 << Map::kHasNonInstancePrototype));
-  __ Branch(&slow_case, ne, at, Operand(zero_reg));
-
-  // Get the "prototype" (or initial map) of the {function}.
-  __ ld(function_prototype,
-        FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
-  __ AssertNotSmi(function_prototype);
-
-  // Resolve the prototype if the {function} has an initial map.  Afterwards the
-  // {function_prototype} will be either the JSReceiver prototype object or the
-  // hole value, which means that no instances of the {function} were created so
-  // far and hence we should return false.
-  Label function_prototype_valid;
-  __ GetObjectType(function_prototype, scratch, scratch);
-  __ Branch(&function_prototype_valid, ne, scratch, Operand(MAP_TYPE));
-  __ ld(function_prototype,
-        FieldMemOperand(function_prototype, Map::kPrototypeOffset));
-  __ bind(&function_prototype_valid);
-  __ AssertNotSmi(function_prototype);
-
-  // Update the global instanceof cache with the current {object} map and
-  // {function}.  The cached answer will be set when it is known below.
-  __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
-  __ StoreRoot(object_map, Heap::kInstanceofCacheMapRootIndex);
-
-  // Loop through the prototype chain looking for the {function} prototype.
-  // Assume true, and change to false if not found.
-  Register const object_instance_type = function_map;
-  Register const map_bit_field = function_map;
-  Register const null = scratch;
-  Register const result = v0;
-
-  Label done, loop, fast_runtime_fallback;
-  __ LoadRoot(result, Heap::kTrueValueRootIndex);
-  __ LoadRoot(null, Heap::kNullValueRootIndex);
-  __ bind(&loop);
-
-  // Check if the object needs to be access checked.
-  __ lbu(map_bit_field, FieldMemOperand(object_map, Map::kBitFieldOffset));
-  __ And(map_bit_field, map_bit_field, Operand(1 << Map::kIsAccessCheckNeeded));
-  __ Branch(&fast_runtime_fallback, ne, map_bit_field, Operand(zero_reg));
-  // Check if the current object is a Proxy.
-  __ lbu(object_instance_type,
-         FieldMemOperand(object_map, Map::kInstanceTypeOffset));
-  __ Branch(&fast_runtime_fallback, eq, object_instance_type,
-            Operand(JS_PROXY_TYPE));
-
-  __ ld(object, FieldMemOperand(object_map, Map::kPrototypeOffset));
-  __ Branch(&done, eq, object, Operand(function_prototype));
-  __ Branch(USE_DELAY_SLOT, &loop, ne, object, Operand(null));
-  __ ld(object_map,
-        FieldMemOperand(object, HeapObject::kMapOffset));  // In delay slot.
-  __ LoadRoot(result, Heap::kFalseValueRootIndex);
-  __ bind(&done);
-  __ Ret(USE_DELAY_SLOT);
-  __ StoreRoot(result,
-               Heap::kInstanceofCacheAnswerRootIndex);  // In delay slot.
-
-  // Found Proxy or access check needed: Call the runtime
-  __ bind(&fast_runtime_fallback);
-  __ Push(object, function_prototype);
-  // Invalidate the instanceof cache.
-  DCHECK(Smi::FromInt(0) == 0);
-  __ StoreRoot(zero_reg, Heap::kInstanceofCacheFunctionRootIndex);
-  __ TailCallRuntime(Runtime::kHasInPrototypeChain);
-
-  // Slow-case: Call the %InstanceOf runtime function.
-  __ bind(&slow_case);
-  __ Push(object, function);
-  __ TailCallRuntime(is_es6_instanceof() ? Runtime::kOrdinaryHasInstance
-                                         : Runtime::kInstanceOf);
-}
-
-
 void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
   Label miss;
   Register receiver = LoadDescriptor::ReceiverRegister();
@@ -2056,6 +1881,7 @@
   // a2 : feedback vector
   // a3 : slot in feedback vector (Smi)
   Label initialize, done, miss, megamorphic, not_array_function;
+  Label done_initialize_count, done_increment_count;
 
   DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()),
             masm->isolate()->heap()->megamorphic_symbol());
@@ -2075,7 +1901,7 @@
   Register feedback_map = a6;
   Register weak_value = t0;
   __ ld(weak_value, FieldMemOperand(a5, WeakCell::kValueOffset));
-  __ Branch(&done, eq, a1, Operand(weak_value));
+  __ Branch(&done_increment_count, eq, a1, Operand(weak_value));
   __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
   __ Branch(&done, eq, a5, Operand(at));
   __ ld(feedback_map, FieldMemOperand(a5, HeapObject::kMapOffset));
@@ -2097,7 +1923,7 @@
   // Make sure the function is the Array() function
   __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, a5);
   __ Branch(&megamorphic, ne, a1, Operand(a5));
-  __ jmp(&done);
+  __ jmp(&done_increment_count);
 
   __ bind(&miss);
 
@@ -2125,12 +1951,31 @@
   // slot.
   CreateAllocationSiteStub create_stub(masm->isolate());
   CallStubInRecordCallTarget(masm, &create_stub);
-  __ Branch(&done);
+  __ Branch(&done_initialize_count);
 
   __ bind(&not_array_function);
 
   CreateWeakCellStub weak_cell_stub(masm->isolate());
   CallStubInRecordCallTarget(masm, &weak_cell_stub);
+
+  __ bind(&done_initialize_count);
+  // Initialize the call counter.
+
+  __ SmiScale(a4, a3, kPointerSizeLog2);
+  __ Daddu(a4, a2, Operand(a4));
+  __ li(a5, Operand(Smi::FromInt(1)));
+  __ Branch(USE_DELAY_SLOT, &done);
+  __ sd(a5, FieldMemOperand(a4, FixedArray::kHeaderSize + kPointerSize));
+
+  __ bind(&done_increment_count);
+
+  // Increment the call count for monomorphic function calls.
+  __ SmiScale(a4, a3, kPointerSizeLog2);
+  __ Daddu(a5, a2, Operand(a4));
+  __ ld(a4, FieldMemOperand(a5, FixedArray::kHeaderSize + kPointerSize));
+  __ Daddu(a4, a4, Operand(Smi::FromInt(1)));
+  __ sd(a4, FieldMemOperand(a5, FixedArray::kHeaderSize + kPointerSize));
+
   __ bind(&done);
 }
 
@@ -2233,7 +2078,7 @@
   __ dsrl(t0, a3, 32 - kPointerSizeLog2);
   __ Daddu(a3, a2, Operand(t0));
   __ ld(t0, FieldMemOperand(a3, FixedArray::kHeaderSize + kPointerSize));
-  __ Daddu(t0, t0, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+  __ Daddu(t0, t0, Operand(Smi::FromInt(1)));
   __ sd(t0, FieldMemOperand(a3, FixedArray::kHeaderSize + kPointerSize));
 
   __ mov(a2, a4);
@@ -2281,7 +2126,7 @@
   __ dsrl(t0, a3, 32 - kPointerSizeLog2);
   __ Daddu(a3, a2, Operand(t0));
   __ ld(t0, FieldMemOperand(a3, FixedArray::kHeaderSize + kPointerSize));
-  __ Daddu(t0, t0, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+  __ Daddu(t0, t0, Operand(Smi::FromInt(1)));
   __ sd(t0, FieldMemOperand(a3, FixedArray::kHeaderSize + kPointerSize));
 
   __ bind(&call_function);
@@ -2354,7 +2199,7 @@
   // Initialize the call counter.
   __ dsrl(at, a3, 32 - kPointerSizeLog2);
   __ Daddu(at, a2, Operand(at));
-  __ li(t0, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+  __ li(t0, Operand(Smi::FromInt(1)));
   __ sd(t0, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
 
   // Store the function. Use a stub since we need a frame for allocation.
@@ -2415,13 +2260,7 @@
   } else {
     __ Push(object_, index_);
   }
-  if (index_flags_ == STRING_INDEX_IS_NUMBER) {
-    __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero);
-  } else {
-    DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
-    // NumberToSmi discards numbers that are not exact integers.
-    __ CallRuntime(Runtime::kNumberToSmi);
-  }
+  __ CallRuntime(Runtime::kNumberToSmi);
 
   // Save the conversion result before the pop instructions below
   // have a chance to overwrite it.
@@ -2758,74 +2597,12 @@
   // a3: from index (untagged)
   __ SmiTag(a3);
   StringCharAtGenerator generator(v0, a3, a2, v0, &runtime, &runtime, &runtime,
-                                  STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING);
+                                  RECEIVER_IS_STRING);
   generator.GenerateFast(masm);
   __ DropAndRet(3);
   generator.SkipSlow(masm, &runtime);
 }
 
-
-void ToNumberStub::Generate(MacroAssembler* masm) {
-  // The ToNumber stub takes one argument in a0.
-  Label not_smi;
-  __ JumpIfNotSmi(a0, &not_smi);
-  __ Ret(USE_DELAY_SLOT);
-  __ mov(v0, a0);
-  __ bind(&not_smi);
-
-  Label not_heap_number;
-  __ GetObjectType(a0, a1, a1);
-  // a0: receiver
-  // a1: receiver instance type
-  __ Branch(&not_heap_number, ne, a1, Operand(HEAP_NUMBER_TYPE));
-  __ Ret(USE_DELAY_SLOT);
-  __ mov(v0, a0);
-  __ bind(&not_heap_number);
-
-  NonNumberToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
-}
-
-void NonNumberToNumberStub::Generate(MacroAssembler* masm) {
-  // The NonNumberToNumber stub takes on argument in a0.
-  __ AssertNotNumber(a0);
-
-  Label not_string;
-  __ GetObjectType(a0, a1, a1);
-  // a0: receiver
-  // a1: receiver instance type
-  __ Branch(&not_string, hs, a1, Operand(FIRST_NONSTRING_TYPE));
-  StringToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
-  __ bind(&not_string);
-
-  Label not_oddball;
-  __ Branch(&not_oddball, ne, a1, Operand(ODDBALL_TYPE));
-  __ Ret(USE_DELAY_SLOT);
-  __ ld(v0, FieldMemOperand(a0, Oddball::kToNumberOffset));  // In delay slot.
-  __ bind(&not_oddball);
-
-  __ Push(a0);  // Push argument.
-  __ TailCallRuntime(Runtime::kToNumber);
-}
-
-void StringToNumberStub::Generate(MacroAssembler* masm) {
-  // The StringToNumber stub takes on argument in a0.
-  __ AssertString(a0);
-
-  // Check if string has a cached array index.
-  Label runtime;
-  __ lwu(a2, FieldMemOperand(a0, String::kHashFieldOffset));
-  __ And(at, a2, Operand(String::kContainsCachedArrayIndexMask));
-  __ Branch(&runtime, ne, at, Operand(zero_reg));
-  __ IndexFromHash(a2, v0);
-  __ Ret();
-
-  __ bind(&runtime);
-  __ Push(a0);  // Push argument.
-  __ TailCallRuntime(Runtime::kStringToNumber);
-}
-
 void ToStringStub::Generate(MacroAssembler* masm) {
   // The ToString stub takes on argument in a0.
   Label is_number;
@@ -3006,7 +2783,7 @@
   // Load a2 with the allocation site. We stick an undefined dummy value here
   // and replace it with the real allocation site later when we instantiate this
   // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate().
-  __ li(a2, handle(isolate()->heap()->undefined_value()));
+  __ li(a2, isolate()->factory()->undefined_value());
 
   // Make sure that we actually patched the allocation site.
   if (FLAG_debug_code) {
@@ -3901,14 +3678,14 @@
 
 void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  LoadICStub stub(isolate(), state());
+  LoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate(), state());
+  KeyedLoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -4046,8 +3823,8 @@
   __ bind(&not_array);
   __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
   __ Branch(&miss, ne, feedback, Operand(at));
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::LOAD_IC, code_flags,
                                                receiver, name, feedback,
                                                receiver_map, scratch1, a7);
@@ -4189,8 +3966,8 @@
 
   __ bind(&not_array);
   __ Branch(&miss, ne, feedback, Heap::kmegamorphic_symbolRootIndex);
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
   masm->isolate()->stub_cache()->GenerateProbe(
       masm, Code::STORE_IC, code_flags, receiver, key, feedback, receiver_map,
       scratch1, scratch2);
@@ -4527,19 +4304,13 @@
   }
 }
 
-
-void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
+void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
   ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
       isolate);
   ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
       isolate);
-  ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
-      isolate);
-}
-
-
-void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
-    Isolate* isolate) {
+  ArrayNArgumentsConstructorStub stub(isolate);
+  stub.GetCode();
   ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS };
   for (int i = 0; i < 2; i++) {
     // For internal arrays we only need a few things.
@@ -4547,8 +4318,6 @@
     stubh1.GetCode();
     InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]);
     stubh2.GetCode();
-    InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]);
-    stubh3.GetCode();
   }
 }
 
@@ -4567,13 +4336,15 @@
     CreateArrayDispatchOneArgument(masm, mode);
 
     __ bind(&not_one_case);
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else if (argument_count() == NONE) {
     CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
   } else if (argument_count() == ONE) {
     CreateArrayDispatchOneArgument(masm, mode);
   } else if (argument_count() == MORE_THAN_ONE) {
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else {
     UNREACHABLE();
   }
@@ -4657,7 +4428,7 @@
   InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
   __ TailCallStub(&stub0, lo, a0, Operand(1));
 
-  InternalArrayNArgumentsConstructorStub stubN(isolate(), kind);
+  ArrayNArgumentsConstructorStub stubN(isolate());
   __ TailCallStub(&stubN, hi, a0, Operand(1));
 
   if (IsFastPackedElementsKind(kind)) {
@@ -4758,15 +4529,15 @@
   __ bind(&done_allocate);
 
   // Initialize the JSObject fields.
-  __ sd(a2, MemOperand(v0, JSObject::kMapOffset));
+  __ sd(a2, FieldMemOperand(v0, JSObject::kMapOffset));
   __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex);
-  __ sd(a3, MemOperand(v0, JSObject::kPropertiesOffset));
-  __ sd(a3, MemOperand(v0, JSObject::kElementsOffset));
+  __ sd(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset));
+  __ sd(a3, FieldMemOperand(v0, JSObject::kElementsOffset));
   STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize);
-  __ Daddu(a1, v0, Operand(JSObject::kHeaderSize));
+  __ Daddu(a1, v0, Operand(JSObject::kHeaderSize - kHeapObjectTag));
 
   // ----------- S t a t e -------------
-  //  -- v0 : result (untagged)
+  //  -- v0 : result (tagged)
   //  -- a1 : result fields (untagged)
   //  -- a5 : result end (untagged)
   //  -- a2 : initial map
@@ -4784,11 +4555,7 @@
   {
     // Initialize all in-object fields with undefined.
     __ InitializeFieldsWithFiller(a1, a5, a0);
-
-    // Add the object tag to make the JSObject real.
-    STATIC_ASSERT(kHeapObjectTag == 1);
-    __ Ret(USE_DELAY_SLOT);
-    __ Daddu(v0, v0, Operand(kHeapObjectTag));  // In delay slot.
+    __ Ret();
   }
   __ bind(&slack_tracking);
   {
@@ -4811,9 +4578,7 @@
     Label finalize;
     STATIC_ASSERT(Map::kSlackTrackingCounterEnd == 1);
     __ And(a3, a3, Operand(Map::ConstructionCounter::kMask));
-    __ Branch(USE_DELAY_SLOT, &finalize, eq, a3, Operand(zero_reg));
-    STATIC_ASSERT(kHeapObjectTag == 1);
-    __ Daddu(v0, v0, Operand(kHeapObjectTag));  // In delay slot.
+    __ Branch(&finalize, eq, a3, Operand(zero_reg));
     __ Ret();
 
     // Finalize the instance size.
@@ -4839,10 +4604,10 @@
     __ CallRuntime(Runtime::kAllocateInNewSpace);
     __ Pop(a2);
   }
-  STATIC_ASSERT(kHeapObjectTag == 1);
-  __ Dsubu(v0, v0, Operand(kHeapObjectTag));
   __ lbu(a5, FieldMemOperand(a2, Map::kInstanceSizeOffset));
   __ Dlsa(a5, v0, a5, kPointerSizeLog2);
+  STATIC_ASSERT(kHeapObjectTag == 1);
+  __ Dsubu(a5, a5, Operand(kHeapObjectTag));
   __ jmp(&done_allocate);
 
   // Fall back to %NewObject.
@@ -4861,19 +4626,19 @@
   // -----------------------------------
   __ AssertFunction(a1);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make a2 point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ Branch(USE_DELAY_SLOT, &loop_entry);
-    __ mov(a2, fp);  // In delay slot.
-    __ bind(&loop);
+  // Make a2 point to the JavaScript frame.
+  __ mov(a2, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ ld(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset));
-    __ bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ ld(a3, MemOperand(a2, StandardFrameConstants::kFunctionOffset));
-    __ Branch(&loop, ne, a1, Operand(a3));
+    __ Branch(&ok, eq, a1, Operand(a3));
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
   }
 
   // Check if we have rest parameters (only possible if we have an
@@ -4889,10 +4654,10 @@
   Label rest_parameters;
   __ SmiLoadUntag(
       a0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset));
-  __ ld(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
-  __ lw(a1,
-        FieldMemOperand(a1, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ Dsubu(a0, a0, Operand(a1));
+  __ ld(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
+  __ lw(a3,
+        FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
+  __ Dsubu(a0, a0, Operand(a3));
   __ Branch(&rest_parameters, gt, a0, Operand(zero_reg));
 
   // Return an empty rest parameter array.
@@ -4905,7 +4670,7 @@
 
     // Allocate an empty rest parameter array.
     Label allocate, done_allocate;
-    __ Allocate(JSArray::kSize, v0, a0, a1, &allocate, TAG_OBJECT);
+    __ Allocate(JSArray::kSize, v0, a0, a1, &allocate, NO_ALLOCATION_FLAGS);
     __ bind(&done_allocate);
 
     // Setup the rest parameter array in v0.
@@ -4939,15 +4704,16 @@
     // ----------- S t a t e -------------
     //  -- cp : context
     //  -- a0 : number of rest parameters
+    //  -- a1 : function
     //  -- a2 : pointer to first rest parameters
     //  -- ra : return address
     // -----------------------------------
 
     // Allocate space for the rest parameter array plus the backing store.
     Label allocate, done_allocate;
-    __ li(a1, Operand(JSArray::kSize + FixedArray::kHeaderSize));
-    __ Dlsa(a1, a1, a0, kPointerSizeLog2);
-    __ Allocate(a1, v0, a3, a4, &allocate, TAG_OBJECT);
+    __ li(a5, Operand(JSArray::kSize + FixedArray::kHeaderSize));
+    __ Dlsa(a5, a5, a0, kPointerSizeLog2);
+    __ Allocate(a5, v0, a3, a4, &allocate, NO_ALLOCATION_FLAGS);
     __ bind(&done_allocate);
 
     // Compute arguments.length in a4.
@@ -4982,18 +4748,26 @@
     __ Ret(USE_DELAY_SLOT);
     __ mov(v0, a3);  // In delay slot
 
-    // Fall back to %AllocateInNewSpace.
+    // Fall back to %AllocateInNewSpace (if not too big).
+    Label too_big_for_new_space;
     __ bind(&allocate);
+    __ Branch(&too_big_for_new_space, gt, a5,
+              Operand(Page::kMaxRegularHeapObjectSize));
     {
       FrameScope scope(masm, StackFrame::INTERNAL);
       __ SmiTag(a0);
-      __ SmiTag(a1);
-      __ Push(a0, a2, a1);
+      __ SmiTag(a5);
+      __ Push(a0, a2, a5);
       __ CallRuntime(Runtime::kAllocateInNewSpace);
       __ Pop(a0, a2);
       __ SmiUntag(a0);
     }
     __ jmp(&done_allocate);
+
+    // Fall back to %NewStrictArguments.
+    __ bind(&too_big_for_new_space);
+    __ Push(a1);
+    __ TailCallRuntime(Runtime::kNewStrictArguments);
   }
 }
 
@@ -5007,24 +4781,40 @@
   // -----------------------------------
   __ AssertFunction(a1);
 
+  // Make t0 point to the JavaScript frame.
+  __ mov(t0, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
+    __ ld(t0, MemOperand(t0, StandardFrameConstants::kCallerFPOffset));
+  }
+  if (FLAG_debug_code) {
+    Label ok;
+    __ ld(a3, MemOperand(t0, StandardFrameConstants::kFunctionOffset));
+    __ Branch(&ok, eq, a1, Operand(a3));
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
+  }
+
   // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub.
   __ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
   __ lw(a2,
          FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ Lsa(a3, fp, a2, kPointerSizeLog2);
+  __ Lsa(a3, t0, a2, kPointerSizeLog2);
   __ Addu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset));
   __ SmiTag(a2);
 
   // a1 : function
   // a2 : number of parameters (tagged)
   // a3 : parameters pointer
+  // t0 : Javascript frame pointer
   // Registers used over whole function:
   //  a5 : arguments count (tagged)
   //  a6 : mapped parameter count (tagged)
 
   // Check if the calling frame is an arguments adaptor frame.
   Label adaptor_frame, try_allocate, runtime;
-  __ ld(a4, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+  __ ld(a4, MemOperand(t0, StandardFrameConstants::kCallerFPOffset));
   __ ld(a0, MemOperand(a4, CommonFrameConstants::kContextOrFrameTypeOffset));
   __ Branch(&adaptor_frame, eq, a0,
             Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
@@ -5072,7 +4862,7 @@
   __ Daddu(t1, t1, Operand(JSSloppyArgumentsObject::kSize));
 
   // Do the allocation of all three objects in one go.
-  __ Allocate(t1, v0, t1, a4, &runtime, TAG_OBJECT);
+  __ Allocate(t1, v0, t1, a4, &runtime, NO_ALLOCATION_FLAGS);
 
   // v0 = address of new object(s) (tagged)
   // a2 = argument count (smi-tagged)
@@ -5227,19 +5017,19 @@
   // -----------------------------------
   __ AssertFunction(a1);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make a2 point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ Branch(USE_DELAY_SLOT, &loop_entry);
-    __ mov(a2, fp);  // In delay slot.
-    __ bind(&loop);
+  // Make a2 point to the JavaScript frame.
+  __ mov(a2, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ ld(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset));
-    __ bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ ld(a3, MemOperand(a2, StandardFrameConstants::kFunctionOffset));
-    __ Branch(&loop, ne, a1, Operand(a3));
+    __ Branch(&ok, eq, a1, Operand(a3));
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
   }
 
   // Check if we have an arguments adaptor frame below the function frame.
@@ -5249,9 +5039,9 @@
   __ Branch(&arguments_adaptor, eq, a0,
             Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
   {
-    __ ld(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
+    __ ld(a4, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
     __ lw(a0,
-          FieldMemOperand(a1, SharedFunctionInfo::kFormalParameterCountOffset));
+          FieldMemOperand(a4, SharedFunctionInfo::kFormalParameterCountOffset));
     __ Dlsa(a2, a2, a0, kPointerSizeLog2);
     __ Daddu(a2, a2, Operand(StandardFrameConstants::kCallerSPOffset -
                              1 * kPointerSize));
@@ -5270,15 +5060,16 @@
   // ----------- S t a t e -------------
   //  -- cp : context
   //  -- a0 : number of rest parameters
+  //  -- a1 : function
   //  -- a2 : pointer to first rest parameters
   //  -- ra : return address
   // -----------------------------------
 
   // Allocate space for the rest parameter array plus the backing store.
   Label allocate, done_allocate;
-  __ li(a1, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
-  __ Dlsa(a1, a1, a0, kPointerSizeLog2);
-  __ Allocate(a1, v0, a3, a4, &allocate, TAG_OBJECT);
+  __ li(a5, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
+  __ Dlsa(a5, a5, a0, kPointerSizeLog2);
+  __ Allocate(a5, v0, a3, a4, &allocate, NO_ALLOCATION_FLAGS);
   __ bind(&done_allocate);
 
   // Compute arguments.length in a4.
@@ -5313,48 +5104,26 @@
   __ Ret(USE_DELAY_SLOT);
   __ mov(v0, a3);  // In delay slot
 
-  // Fall back to %AllocateInNewSpace.
+  // Fall back to %AllocateInNewSpace (if not too big).
+  Label too_big_for_new_space;
   __ bind(&allocate);
+  __ Branch(&too_big_for_new_space, gt, a5,
+            Operand(Page::kMaxRegularHeapObjectSize));
   {
     FrameScope scope(masm, StackFrame::INTERNAL);
     __ SmiTag(a0);
-    __ SmiTag(a1);
-    __ Push(a0, a2, a1);
+    __ SmiTag(a5);
+    __ Push(a0, a2, a5);
     __ CallRuntime(Runtime::kAllocateInNewSpace);
     __ Pop(a0, a2);
     __ SmiUntag(a0);
   }
   __ jmp(&done_allocate);
-}
 
-
-void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
-  Register context_reg = cp;
-  Register slot_reg = a2;
-  Register result_reg = v0;
-  Label slow_case;
-
-  // Go up context chain to the script context.
-  for (int i = 0; i < depth(); ++i) {
-    __ ld(result_reg, ContextMemOperand(context_reg, Context::PREVIOUS_INDEX));
-    context_reg = result_reg;
-  }
-
-  // Load the PropertyCell value at the specified slot.
-  __ Dlsa(at, context_reg, slot_reg, kPointerSizeLog2);
-  __ ld(result_reg, ContextMemOperand(at, 0));
-  __ ld(result_reg, FieldMemOperand(result_reg, PropertyCell::kValueOffset));
-
-  // Check that value is not the_hole.
-  __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
-  __ Branch(&slow_case, eq, result_reg, Operand(at));
-  __ Ret();
-
-  // Fallback to the runtime.
-  __ bind(&slow_case);
-  __ SmiTag(slot_reg);
-  __ Push(slot_reg);
-  __ TailCallRuntime(Runtime::kLoadGlobalViaContext);
+  // Fall back to %NewStrictArguments.
+  __ bind(&too_big_for_new_space);
+  __ Push(a1);
+  __ TailCallRuntime(Runtime::kNewStrictArguments);
 }
 
 
@@ -5636,7 +5405,11 @@
   STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
   STATIC_ASSERT(FCA::kIsolateIndex == 1);
   STATIC_ASSERT(FCA::kHolderIndex == 0);
-  STATIC_ASSERT(FCA::kArgsLength == 7);
+  STATIC_ASSERT(FCA::kNewTargetIndex == 7);
+  STATIC_ASSERT(FCA::kArgsLength == 8);
+
+  // new target
+  __ PushRoot(Heap::kUndefinedValueRootIndex);
 
   // Save context, callee and call data.
   __ Push(context, callee, call_data);
@@ -5660,7 +5433,7 @@
 
   // Allocate the v8::Arguments structure in the arguments' space since
   // it's not controlled by GC.
-  const int kApiStackSpace = 4;
+  const int kApiStackSpace = 3;
 
   FrameScope frame_scope(masm, StackFrame::MANUAL);
   __ EnterExitFrame(false, kApiStackSpace);
@@ -5680,8 +5453,6 @@
   // justified by n64 ABI.
   __ li(at, Operand(argc()));
   __ sw(at, MemOperand(a0, 2 * kPointerSize));
-  // FunctionCallbackInfo::is_construct_call_ = 0
-  __ sw(zero_reg, MemOperand(a0, 2 * kPointerSize + kIntSize));
 
   ExternalReference thunk_ref =
       ExternalReference::invoke_function_callback(masm->isolate());
@@ -5698,8 +5469,9 @@
   }
   MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
   int stack_space = 0;
-  int32_t stack_space_offset = 4 * kPointerSize;
+  int32_t stack_space_offset = 3 * kPointerSize;
   stack_space = argc() + FCA::kArgsLength + 1;
+  // TODO(adamk): Why are we clobbering this immediately?
   stack_space_offset = kInvalidStackOffset;
   CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
                            stack_space_offset, return_value_operand,
@@ -5708,15 +5480,44 @@
 
 
 void CallApiGetterStub::Generate(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- sp[0]                        : name
-  //  -- sp[8 .. (8 + kArgsLength*8)] : v8::PropertyCallbackInfo::args_
-  //  -- ...
-  //  -- a2                           : api_function_address
-  // -----------------------------------
+  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
+  // name below the exit frame to make GC aware of them.
+  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
+  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
+  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
+  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
+  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
+  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
 
-  Register api_function_address = ApiGetterDescriptor::function_address();
-  DCHECK(api_function_address.is(a2));
+  Register receiver = ApiGetterDescriptor::ReceiverRegister();
+  Register holder = ApiGetterDescriptor::HolderRegister();
+  Register callback = ApiGetterDescriptor::CallbackRegister();
+  Register scratch = a4;
+  DCHECK(!AreAliased(receiver, holder, callback, scratch));
+
+  Register api_function_address = a2;
+
+  // Here and below +1 is for name() pushed after the args_ array.
+  typedef PropertyCallbackArguments PCA;
+  __ Dsubu(sp, sp, (PCA::kArgsLength + 1) * kPointerSize);
+  __ sd(receiver, MemOperand(sp, (PCA::kThisIndex + 1) * kPointerSize));
+  __ ld(scratch, FieldMemOperand(callback, AccessorInfo::kDataOffset));
+  __ sd(scratch, MemOperand(sp, (PCA::kDataIndex + 1) * kPointerSize));
+  __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
+  __ sd(scratch, MemOperand(sp, (PCA::kReturnValueOffset + 1) * kPointerSize));
+  __ sd(scratch, MemOperand(sp, (PCA::kReturnValueDefaultValueIndex + 1) *
+                                    kPointerSize));
+  __ li(scratch, Operand(ExternalReference::isolate_address(isolate())));
+  __ sd(scratch, MemOperand(sp, (PCA::kIsolateIndex + 1) * kPointerSize));
+  __ sd(holder, MemOperand(sp, (PCA::kHolderIndex + 1) * kPointerSize));
+  // should_throw_on_error -> false
+  DCHECK(Smi::FromInt(0) == nullptr);
+  __ sd(zero_reg,
+        MemOperand(sp, (PCA::kShouldThrowOnErrorIndex + 1) * kPointerSize));
+  __ ld(scratch, FieldMemOperand(callback, AccessorInfo::kNameOffset));
+  __ sd(scratch, MemOperand(sp, 0 * kPointerSize));
 
   // v8::PropertyCallbackInfo::args_ array and name handle.
   const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
@@ -5738,6 +5539,10 @@
   ExternalReference thunk_ref =
       ExternalReference::invoke_accessor_getter_callback(isolate());
 
+  __ ld(scratch, FieldMemOperand(callback, AccessorInfo::kJsGetterOffset));
+  __ ld(api_function_address,
+        FieldMemOperand(scratch, Foreign::kForeignAddressOffset));
+
   // +3 is to skip prolog, return address and name handle.
   MemOperand return_value_operand(
       fp, (PropertyCallbackArguments::kReturnValueOffset + 3) * kPointerSize);
@@ -5746,7 +5551,6 @@
                            return_value_operand, NULL);
 }
 
-
 #undef __
 
 }  // namespace internal
diff --git a/src/mips64/codegen-mips64.cc b/src/mips64/codegen-mips64.cc
index 44d822b..a8f5890 100644
--- a/src/mips64/codegen-mips64.cc
+++ b/src/mips64/codegen-mips64.cc
@@ -17,59 +17,6 @@
 #define __ masm.
 
 
-#if defined(USE_SIMULATOR)
-byte* fast_exp_mips_machine_code = nullptr;
-double fast_exp_simulator(double x, Isolate* isolate) {
-  return Simulator::current(isolate)->CallFP(fast_exp_mips_machine_code, x, 0);
-}
-#endif
-
-
-UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) {
-  size_t actual_size;
-  byte* buffer =
-      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
-  if (buffer == nullptr) return nullptr;
-  ExternalReference::InitializeMathExpData();
-
-  MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
-                      CodeObjectRequired::kNo);
-
-  {
-    DoubleRegister input = f12;
-    DoubleRegister result = f0;
-    DoubleRegister double_scratch1 = f4;
-    DoubleRegister double_scratch2 = f6;
-    Register temp1 = a4;
-    Register temp2 = a5;
-    Register temp3 = a6;
-
-    __ MovFromFloatParameter(input);
-    __ Push(temp3, temp2, temp1);
-    MathExpGenerator::EmitMathExp(
-        &masm, input, result, double_scratch1, double_scratch2,
-        temp1, temp2, temp3);
-    __ Pop(temp3, temp2, temp1);
-    __ MovToFloatResult(result);
-    __ Ret();
-  }
-
-  CodeDesc desc;
-  masm.GetCode(&desc);
-  DCHECK(!RelocInfo::RequiresRelocation(desc));
-
-  Assembler::FlushICache(isolate, buffer, actual_size);
-  base::OS::ProtectCode(buffer, actual_size);
-
-#if !defined(USE_SIMULATOR)
-  return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
-#else
-  fast_exp_mips_machine_code = buffer;
-  return &fast_exp_simulator;
-#endif
-}
-
-
 #if defined(V8_HOST_ARCH_MIPS)
 MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
                                                 MemCopyUint8Function stub) {
@@ -732,6 +679,7 @@
   __ SmiScale(scratch, length, kDoubleSizeLog2);
   __ Daddu(scratch, scratch, FixedDoubleArray::kHeaderSize);
   __ Allocate(scratch, array, t3, scratch2, &gc_required, DOUBLE_ALIGNMENT);
+  __ Dsubu(array, array, kHeapObjectTag);
   // array: destination FixedDoubleArray, not tagged as heap object
 
   // Set destination FixedDoubleArray's length and map.
@@ -882,6 +830,7 @@
   __ Daddu(array_size, array_size, FixedDoubleArray::kHeaderSize);
   __ Allocate(array_size, array, allocate_scratch, scratch, &gc_required,
               NO_ALLOCATION_FLAGS);
+  __ Dsubu(array, array, kHeapObjectTag);
   // array: destination FixedArray, not tagged as heap object
   // Set destination FixedDoubleArray's length and map.
   __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
@@ -1088,94 +1037,6 @@
   __ bind(&done);
 }
 
-
-static MemOperand ExpConstant(int index, Register base) {
-  return MemOperand(base, index * kDoubleSize);
-}
-
-
-void MathExpGenerator::EmitMathExp(MacroAssembler* masm,
-                                   DoubleRegister input,
-                                   DoubleRegister result,
-                                   DoubleRegister double_scratch1,
-                                   DoubleRegister double_scratch2,
-                                   Register temp1,
-                                   Register temp2,
-                                   Register temp3) {
-  DCHECK(!input.is(result));
-  DCHECK(!input.is(double_scratch1));
-  DCHECK(!input.is(double_scratch2));
-  DCHECK(!result.is(double_scratch1));
-  DCHECK(!result.is(double_scratch2));
-  DCHECK(!double_scratch1.is(double_scratch2));
-  DCHECK(!temp1.is(temp2));
-  DCHECK(!temp1.is(temp3));
-  DCHECK(!temp2.is(temp3));
-  DCHECK(ExternalReference::math_exp_constants(0).address() != NULL);
-  DCHECK(!masm->serializer_enabled());  // External references not serializable.
-
-  Label zero, infinity, done;
-  __ li(temp3, Operand(ExternalReference::math_exp_constants(0)));
-
-  __ ldc1(double_scratch1, ExpConstant(0, temp3));
-  __ BranchF(&zero, NULL, ge, double_scratch1, input);
-
-  __ ldc1(double_scratch2, ExpConstant(1, temp3));
-  __ BranchF(&infinity, NULL, ge, input, double_scratch2);
-
-  __ ldc1(double_scratch1, ExpConstant(3, temp3));
-  __ ldc1(result, ExpConstant(4, temp3));
-  __ mul_d(double_scratch1, double_scratch1, input);
-  __ add_d(double_scratch1, double_scratch1, result);
-  __ FmoveLow(temp2, double_scratch1);
-  __ sub_d(double_scratch1, double_scratch1, result);
-  __ ldc1(result, ExpConstant(6, temp3));
-  __ ldc1(double_scratch2, ExpConstant(5, temp3));
-  __ mul_d(double_scratch1, double_scratch1, double_scratch2);
-  __ sub_d(double_scratch1, double_scratch1, input);
-  __ sub_d(result, result, double_scratch1);
-  __ mul_d(double_scratch2, double_scratch1, double_scratch1);
-  __ mul_d(result, result, double_scratch2);
-  __ ldc1(double_scratch2, ExpConstant(7, temp3));
-  __ mul_d(result, result, double_scratch2);
-  __ sub_d(result, result, double_scratch1);
-  // Mov 1 in double_scratch2 as math_exp_constants_array[8] == 1.
-  DCHECK(*reinterpret_cast<double*>
-         (ExternalReference::math_exp_constants(8).address()) == 1);
-  __ Move(double_scratch2, 1.);
-  __ add_d(result, result, double_scratch2);
-  __ dsrl(temp1, temp2, 11);
-  __ Ext(temp2, temp2, 0, 11);
-  __ Daddu(temp1, temp1, Operand(0x3ff));
-
-  // Must not call ExpConstant() after overwriting temp3!
-  __ li(temp3, Operand(ExternalReference::math_exp_log_table()));
-  __ Dlsa(temp3, temp3, temp2, 3);
-  __ lwu(temp2, MemOperand(temp3, Register::kMantissaOffset));
-  __ lwu(temp3, MemOperand(temp3, Register::kExponentOffset));
-  // The first word is loaded is the lower number register.
-  if (temp2.code() < temp3.code()) {
-    __ dsll(at, temp1, 20);
-    __ Or(temp1, temp3, at);
-    __ Move(double_scratch1, temp2, temp1);
-  } else {
-    __ dsll(at, temp1, 20);
-    __ Or(temp1, temp2, at);
-    __ Move(double_scratch1, temp3, temp1);
-  }
-  __ mul_d(result, result, double_scratch1);
-  __ BranchShort(&done);
-
-  __ bind(&zero);
-  __ Move(result, kDoubleRegZero);
-  __ BranchShort(&done);
-
-  __ bind(&infinity);
-  __ ldc1(result, ExpConstant(2, temp3));
-
-  __ bind(&done);
-}
-
 #ifdef DEBUG
 // nop(CODE_AGE_MARKER_NOP)
 static const uint32_t kCodeAgePatchFirstInstruction = 0x00010180;
diff --git a/src/mips64/codegen-mips64.h b/src/mips64/codegen-mips64.h
index ad7abb3..a4f8184 100644
--- a/src/mips64/codegen-mips64.h
+++ b/src/mips64/codegen-mips64.h
@@ -29,23 +29,6 @@
   DISALLOW_COPY_AND_ASSIGN(StringCharLoadGenerator);
 };
 
-
-class MathExpGenerator : public AllStatic {
- public:
-  // Register input isn't modified. All other registers are clobbered.
-  static void EmitMathExp(MacroAssembler* masm,
-                          DoubleRegister input,
-                          DoubleRegister result,
-                          DoubleRegister double_scratch1,
-                          DoubleRegister double_scratch2,
-                          Register temp1,
-                          Register temp2,
-                          Register temp3);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MathExpGenerator);
-};
-
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/mips64/constants-mips64.h b/src/mips64/constants-mips64.h
index 57e947b..d2b1e92 100644
--- a/src/mips64/constants-mips64.h
+++ b/src/mips64/constants-mips64.h
@@ -60,6 +60,27 @@
 const bool IsMipsSoftFloatABI = true;
 #endif
 
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+const uint32_t kMipsLwrOffset = 0;
+const uint32_t kMipsLwlOffset = 3;
+const uint32_t kMipsSwrOffset = 0;
+const uint32_t kMipsSwlOffset = 3;
+const uint32_t kMipsLdrOffset = 0;
+const uint32_t kMipsLdlOffset = 7;
+const uint32_t kMipsSdrOffset = 0;
+const uint32_t kMipsSdlOffset = 7;
+#elif defined(V8_TARGET_BIG_ENDIAN)
+const uint32_t kMipsLwrOffset = 3;
+const uint32_t kMipsLwlOffset = 0;
+const uint32_t kMipsSwrOffset = 3;
+const uint32_t kMipsSwlOffset = 0;
+const uint32_t kMipsLdrOffset = 7;
+const uint32_t kMipsLdlOffset = 0;
+const uint32_t kMipsSdrOffset = 7;
+const uint32_t kMipsSdlOffset = 0;
+#else
+#error Unknown endianness
+#endif
 
 #ifndef __STDC_FORMAT_MACROS
 #define __STDC_FORMAT_MACROS
@@ -384,6 +405,7 @@
   MOVZ = ((1U << 3) + 2),
   MOVN = ((1U << 3) + 3),
   BREAK = ((1U << 3) + 5),
+  SYNC = ((1U << 3) + 7),
 
   MFHI = ((2U << 3) + 0),
   CLZ_R6 = ((2U << 3) + 0),
@@ -645,7 +667,6 @@
   NULLSF = 0U
 };
 
-
 // ----- Emulated conditions.
 // On MIPS we use this enum to abstract from conditional branch instructions.
 // The 'U' prefix is used to specify unsigned comparisons.
@@ -911,7 +932,6 @@
 
   enum TypeChecks { NORMAL, EXTRA };
 
-
   static constexpr uint64_t kOpcodeImmediateTypeMask =
       OpcodeToBitNumber(REGIMM) | OpcodeToBitNumber(BEQ) |
       OpcodeToBitNumber(BNE) | OpcodeToBitNumber(BLEZ) |
@@ -926,12 +946,14 @@
       OpcodeToBitNumber(POP76) | OpcodeToBitNumber(LB) | OpcodeToBitNumber(LH) |
       OpcodeToBitNumber(LWL) | OpcodeToBitNumber(LW) | OpcodeToBitNumber(LWU) |
       OpcodeToBitNumber(LD) | OpcodeToBitNumber(LBU) | OpcodeToBitNumber(LHU) |
-      OpcodeToBitNumber(LWR) | OpcodeToBitNumber(SB) | OpcodeToBitNumber(SH) |
+      OpcodeToBitNumber(LDL) | OpcodeToBitNumber(LDR) | OpcodeToBitNumber(LWR) |
+      OpcodeToBitNumber(SDL) | OpcodeToBitNumber(SB) | OpcodeToBitNumber(SH) |
       OpcodeToBitNumber(SWL) | OpcodeToBitNumber(SW) | OpcodeToBitNumber(SD) |
-      OpcodeToBitNumber(SWR) | OpcodeToBitNumber(LWC1) |
-      OpcodeToBitNumber(LDC1) | OpcodeToBitNumber(SWC1) |
-      OpcodeToBitNumber(SDC1) | OpcodeToBitNumber(PCREL) |
-      OpcodeToBitNumber(DAUI) | OpcodeToBitNumber(BC) | OpcodeToBitNumber(BALC);
+      OpcodeToBitNumber(SWR) | OpcodeToBitNumber(SDR) |
+      OpcodeToBitNumber(LWC1) | OpcodeToBitNumber(LDC1) |
+      OpcodeToBitNumber(SWC1) | OpcodeToBitNumber(SDC1) |
+      OpcodeToBitNumber(PCREL) | OpcodeToBitNumber(DAUI) |
+      OpcodeToBitNumber(BC) | OpcodeToBitNumber(BALC);
 
 #define FunctionFieldToBitNumber(function) (1ULL << function)
 
@@ -964,8 +986,7 @@
       FunctionFieldToBitNumber(TEQ) | FunctionFieldToBitNumber(TNE) |
       FunctionFieldToBitNumber(MOVZ) | FunctionFieldToBitNumber(MOVN) |
       FunctionFieldToBitNumber(MOVCI) | FunctionFieldToBitNumber(SELEQZ_S) |
-      FunctionFieldToBitNumber(SELNEZ_S);
-
+      FunctionFieldToBitNumber(SELNEZ_S) | FunctionFieldToBitNumber(SYNC);
 
   // Get the encoding type of the instruction.
   inline Type InstructionType(TypeChecks checks = NORMAL) const;
@@ -1216,11 +1237,10 @@
           int sa = SaFieldRaw() >> kSaShift;
           switch (sa) {
             case BITSWAP:
-              return kRegisterType;
             case WSBH:
             case SEB:
             case SEH:
-              return kUnsupported;
+              return kRegisterType;
           }
           sa >>= kBp2Bits;
           switch (sa) {
@@ -1234,10 +1254,9 @@
           int sa = SaFieldRaw() >> kSaShift;
           switch (sa) {
             case DBITSWAP:
-              return kRegisterType;
             case DSBH:
             case DSHD:
-              return kUnsupported;
+              return kRegisterType;
           }
           sa = SaFieldRaw() >> kSaShift;
           sa >>= kBp3Bits;
diff --git a/src/mips64/deoptimizer-mips64.cc b/src/mips64/deoptimizer-mips64.cc
index 90bd11e..ea17124 100644
--- a/src/mips64/deoptimizer-mips64.cc
+++ b/src/mips64/deoptimizer-mips64.cc
@@ -117,8 +117,7 @@
 
   // Save all FPU registers before messing with them.
   __ Dsubu(sp, sp, Operand(kDoubleRegsSize));
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
     int code = config->GetAllocatableDoubleCode(i);
     const DoubleRegister fpu_reg = DoubleRegister::from_code(code);
diff --git a/src/mips64/disasm-mips64.cc b/src/mips64/disasm-mips64.cc
index 3d0e10c..1917526 100644
--- a/src/mips64/disasm-mips64.cc
+++ b/src/mips64/disasm-mips64.cc
@@ -375,7 +375,8 @@
   uint64_t target = static_cast<uint64_t>(instr->Imm26Value())
                     << kImmFieldShift;
   target = (reinterpret_cast<uint64_t>(instr) & ~0xfffffff) | target;
-  out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%lx", target);
+  out_buffer_pos_ +=
+      SNPrintF(out_buffer_ + out_buffer_pos_, "0x%" PRIx64, target);
 }
 
 
@@ -801,16 +802,14 @@
   if (instr->Bits(25, 6) == static_cast<int>(kMaxStopCode)) {
     // This is stop(msg).
     Format(instr, "break, code: 'code");
-    out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
-                                "\n%p       %08lx       stop msg: %s",
-                                static_cast<void*>
-                                      (reinterpret_cast<int32_t*>(instr
-                                              + Instruction::kInstrSize)),
-                                reinterpret_cast<uint64_t>
-                                (*reinterpret_cast<char**>(instr
-                                              + Instruction::kInstrSize)),
-                                *reinterpret_cast<char**>(instr
-                                              + Instruction::kInstrSize));
+    out_buffer_pos_ += SNPrintF(
+        out_buffer_ + out_buffer_pos_,
+        "\n%p       %08" PRIx64 "       stop msg: %s",
+        static_cast<void*>(
+            reinterpret_cast<int32_t*>(instr + Instruction::kInstrSize)),
+        reinterpret_cast<uint64_t>(
+            *reinterpret_cast<char**>(instr + Instruction::kInstrSize)),
+        *reinterpret_cast<char**>(instr + Instruction::kInstrSize));
     // Size 3: the break_ instr, plus embedded 64-bit char pointer.
     return 3 * Instruction::kInstrSize;
   } else {
@@ -1162,26 +1161,22 @@
       if (instr->RsValue() == 0) {
         Format(instr, "srl     'rd, 'rt, 'sa");
       } else {
-        if (kArchVariant == kMips64r2) {
-          Format(instr, "rotr    'rd, 'rt, 'sa");
-        } else {
-          Unknown(instr);
-        }
+        Format(instr, "rotr    'rd, 'rt, 'sa");
       }
       break;
     case DSRL:
       if (instr->RsValue() == 0) {
         Format(instr, "dsrl    'rd, 'rt, 'sa");
       } else {
-        if (kArchVariant == kMips64r2) {
-          Format(instr, "drotr   'rd, 'rt, 'sa");
-        } else {
-          Unknown(instr);
-        }
+        Format(instr, "drotr   'rd, 'rt, 'sa");
       }
       break;
     case DSRL32:
-      Format(instr, "dsrl32  'rd, 'rt, 'sa");
+      if (instr->RsValue() == 0) {
+        Format(instr, "dsrl32  'rd, 'rt, 'sa");
+      } else {
+        Format(instr, "drotr32 'rd, 'rt, 'sa");
+      }
       break;
     case SRA:
       Format(instr, "sra     'rd, 'rt, 'sa");
@@ -1202,22 +1197,14 @@
       if (instr->SaValue() == 0) {
         Format(instr, "srlv    'rd, 'rt, 'rs");
       } else {
-        if (kArchVariant == kMips64r2) {
-          Format(instr, "rotrv   'rd, 'rt, 'rs");
-        } else {
-          Unknown(instr);
-        }
+        Format(instr, "rotrv   'rd, 'rt, 'rs");
       }
       break;
     case DSRLV:
       if (instr->SaValue() == 0) {
         Format(instr, "dsrlv   'rd, 'rt, 'rs");
       } else {
-        if (kArchVariant == kMips64r2) {
-          Format(instr, "drotrv  'rd, 'rt, 'rs");
-        } else {
-          Unknown(instr);
-        }
+        Format(instr, "drotrv  'rd, 'rt, 'rs");
       }
       break;
     case SRAV:
@@ -1400,6 +1387,9 @@
     case TNE:
       Format(instr, "tne     'rs, 'rt, code: 'code");
       break;
+    case SYNC:
+      Format(instr, "sync");
+      break;
     case MOVZ:
       Format(instr, "movz    'rd, 'rs, 'rt");
       break;
@@ -1467,11 +1457,18 @@
           Format(instr, "bitswap 'rd, 'rt");
           break;
         }
-        case SEB:
-        case SEH:
-        case WSBH:
-          UNREACHABLE();
+        case SEB: {
+          Format(instr, "seb     'rd, 'rt");
           break;
+        }
+        case SEH: {
+          Format(instr, "seh     'rd, 'rt");
+          break;
+        }
+        case WSBH: {
+          Format(instr, "wsbh    'rd, 'rt");
+          break;
+        }
         default: {
           sa >>= kBp2Bits;
           switch (sa) {
@@ -1502,10 +1499,14 @@
           }
           break;
         }
-        case DSBH:
-        case DSHD:
-          UNREACHABLE();
+        case DSBH: {
+          Format(instr, "dsbh    'rd, 'rt");
           break;
+        }
+        case DSHD: {
+          Format(instr, "dshd    'rd, 'rt");
+          break;
+        }
         default: {
           sa >>= kBp3Bits;
           switch (sa) {
@@ -1948,7 +1949,7 @@
 namespace disasm {
 
 const char* NameConverter::NameOfAddress(byte* addr) const {
-  v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
+  v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
   return tmp_buffer_.start();
 }
 
@@ -2011,8 +2012,8 @@
     buffer[0] = '\0';
     byte* prev_pc = pc;
     pc += d.InstructionDecode(buffer, pc);
-    v8::internal::PrintF(f, "%p    %08x      %s\n",
-        prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
+    v8::internal::PrintF(f, "%p    %08x      %s\n", static_cast<void*>(prev_pc),
+                         *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
   }
 }
 
diff --git a/src/mips64/interface-descriptors-mips64.cc b/src/mips64/interface-descriptors-mips64.cc
index 7695d0b..684dca5 100644
--- a/src/mips64/interface-descriptors-mips64.cc
+++ b/src/mips64/interface-descriptors-mips64.cc
@@ -11,6 +11,14 @@
 
 const Register CallInterfaceDescriptor::ContextRegister() { return cp; }
 
+void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
+    CallInterfaceDescriptorData* data, int register_parameter_count) {
+  const Register default_stub_registers[] = {a0, a1, a2, a3, a4};
+  CHECK_LE(static_cast<size_t>(register_parameter_count),
+           arraysize(default_stub_registers));
+  data->InitializePlatformSpecific(register_parameter_count,
+                                   default_stub_registers);
+}
 
 const Register LoadDescriptor::ReceiverRegister() { return a1; }
 const Register LoadDescriptor::NameRegister() { return a2; }
@@ -39,23 +47,15 @@
 const Register StoreTransitionDescriptor::MapRegister() { return a3; }
 
 
-const Register LoadGlobalViaContextDescriptor::SlotRegister() { return a2; }
-
-
 const Register StoreGlobalViaContextDescriptor::SlotRegister() { return a2; }
 const Register StoreGlobalViaContextDescriptor::ValueRegister() { return a0; }
 
 
-const Register InstanceOfDescriptor::LeftRegister() { return a1; }
-const Register InstanceOfDescriptor::RightRegister() { return a0; }
-
-
 const Register StringCompareDescriptor::LeftRegister() { return a1; }
 const Register StringCompareDescriptor::RightRegister() { return a0; }
 
-
-const Register ApiGetterDescriptor::function_address() { return a2; }
-
+const Register ApiGetterDescriptor::HolderRegister() { return a0; }
+const Register ApiGetterDescriptor::CallbackRegister() { return a3; }
 
 const Register MathPowTaggedDescriptor::exponent() { return a2; }
 
@@ -247,50 +247,34 @@
 SIMD128_TYPES(SIMD128_ALLOC_DESC)
 #undef SIMD128_ALLOC_DESC
 
-void AllocateInNewSpaceDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  Register registers[] = {a0};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-void ArrayConstructorConstantArgCountDescriptor::InitializePlatformSpecific(
+void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // register state
   // a0 -- number of arguments
   // a1 -- function
   // a2 -- allocation site with elements kind
-  Register registers[] = {a1, a2};
+  Register registers[] = {a1, a2, a0};
   data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
+void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  // register state
+  // a0 -- number of arguments
+  // a1 -- function
+  // a2 -- allocation site with elements kind
+  Register registers[] = {a1, a2, a0};
+  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
+}
 
-void ArrayConstructorDescriptor::InitializePlatformSpecific(
+void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // stack param count needs (constructor pointer, and single argument)
   Register registers[] = {a1, a2, a0};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
-
-void InternalArrayConstructorConstantArgCountDescriptor::
-    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
-  // register state
-  // a0 -- number of arguments
-  // a1 -- constructor function
-  Register registers[] = {a1};
-  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
-}
-
-
-void InternalArrayConstructorDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  // stack param count needs (constructor pointer, and single argument)
-  Register registers[] = {a1, a0};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-void FastArrayPushDescriptor::InitializePlatformSpecific(
+void VarArgFunctionDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // stack param count needs (arg count)
   Register registers[] = {a0};
@@ -316,6 +300,11 @@
   data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
+void CountOpDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {a1};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
 
 void StringAddDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
@@ -376,9 +365,8 @@
 void InterpreterDispatchDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {
-      kInterpreterAccumulatorRegister, kInterpreterRegisterFileRegister,
-      kInterpreterBytecodeOffsetRegister, kInterpreterBytecodeArrayRegister,
-      kInterpreterDispatchTableRegister};
+      kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
+      kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
@@ -413,6 +401,16 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
+void ResumeGeneratorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {
+      v0,  // the value to pass to the generator
+      a1,  // the JSGeneratorObject to resume
+      a2   // the resume mode (tagged)
+  };
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/mips64/macro-assembler-mips64.cc b/src/mips64/macro-assembler-mips64.cc
index fb83fe9..f8e7e1f 100644
--- a/src/mips64/macro-assembler-mips64.cc
+++ b/src/mips64/macro-assembler-mips64.cc
@@ -17,6 +17,18 @@
 namespace v8 {
 namespace internal {
 
+// Floating point constants.
+const uint64_t kDoubleSignMask = Double::kSignMask;
+const uint32_t kDoubleExponentShift = HeapNumber::kMantissaBits;
+const uint32_t kDoubleNaNShift = kDoubleExponentShift - 1;
+const uint64_t kDoubleNaNMask = Double::kExponentMask | (1L << kDoubleNaNShift);
+
+const uint32_t kSingleSignMask = kBinary32SignMask;
+const uint32_t kSingleExponentMask = kBinary32ExponentMask;
+const uint32_t kSingleExponentShift = kBinary32ExponentShift;
+const uint32_t kSingleNaNShift = kSingleExponentShift - 1;
+const uint32_t kSingleNaNMask = kSingleExponentMask | (1 << kSingleNaNShift);
+
 MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size,
                                CodeObjectRequired create_code_object)
     : Assembler(arg_isolate, buffer, size),
@@ -29,7 +41,6 @@
   }
 }
 
-
 void MacroAssembler::Load(Register dst,
                           const MemOperand& src,
                           Representation r) {
@@ -1324,34 +1335,219 @@
 
 // ------------Pseudo-instructions-------------
 
+// Change endianness
+void MacroAssembler::ByteSwapSigned(Register reg, int operand_size) {
+  DCHECK(operand_size == 1 || operand_size == 2 || operand_size == 4 ||
+         operand_size == 8);
+  DCHECK(kArchVariant == kMips64r6 || kArchVariant == kMips64r2);
+  if (operand_size == 1) {
+    seb(reg, reg);
+    sll(reg, reg, 0);
+    dsbh(reg, reg);
+    dshd(reg, reg);
+  } else if (operand_size == 2) {
+    seh(reg, reg);
+    sll(reg, reg, 0);
+    dsbh(reg, reg);
+    dshd(reg, reg);
+  } else if (operand_size == 4) {
+    sll(reg, reg, 0);
+    dsbh(reg, reg);
+    dshd(reg, reg);
+  } else {
+    dsbh(reg, reg);
+    dshd(reg, reg);
+  }
+}
+
+void MacroAssembler::ByteSwapUnsigned(Register reg, int operand_size) {
+  DCHECK(operand_size == 1 || operand_size == 2 || operand_size == 4);
+  if (operand_size == 1) {
+    andi(reg, reg, 0xFF);
+    dsbh(reg, reg);
+    dshd(reg, reg);
+  } else if (operand_size == 2) {
+    andi(reg, reg, 0xFFFF);
+    dsbh(reg, reg);
+    dshd(reg, reg);
+  } else {
+    dsll32(reg, reg, 0);
+    dsrl32(reg, reg, 0);
+    dsbh(reg, reg);
+    dshd(reg, reg);
+  }
+}
+
 void MacroAssembler::Ulw(Register rd, const MemOperand& rs) {
-  lwr(rd, rs);
-  lwl(rd, MemOperand(rs.rm(), rs.offset() + 3));
+  DCHECK(!rd.is(at));
+  DCHECK(!rs.rm().is(at));
+  if (kArchVariant == kMips64r6) {
+    lw(rd, rs);
+  } else {
+    DCHECK(kArchVariant == kMips64r2);
+    if (is_int16(rs.offset() + kMipsLwrOffset) &&
+        is_int16(rs.offset() + kMipsLwlOffset)) {
+      if (!rd.is(rs.rm())) {
+        lwr(rd, MemOperand(rs.rm(), rs.offset() + kMipsLwrOffset));
+        lwl(rd, MemOperand(rs.rm(), rs.offset() + kMipsLwlOffset));
+      } else {
+        lwr(at, MemOperand(rs.rm(), rs.offset() + kMipsLwrOffset));
+        lwl(at, MemOperand(rs.rm(), rs.offset() + kMipsLwlOffset));
+        mov(rd, at);
+      }
+    } else {  // Offset > 16 bits, use multiple instructions to load.
+      LoadRegPlusOffsetToAt(rs);
+      lwr(rd, MemOperand(at, kMipsLwrOffset));
+      lwl(rd, MemOperand(at, kMipsLwlOffset));
+    }
+  }
+}
+
+void MacroAssembler::Ulwu(Register rd, const MemOperand& rs) {
+  if (kArchVariant == kMips64r6) {
+    lwu(rd, rs);
+  } else {
+    DCHECK(kArchVariant == kMips64r2);
+    Ulw(rd, rs);
+    Dext(rd, rd, 0, 32);
+  }
 }
 
 
 void MacroAssembler::Usw(Register rd, const MemOperand& rs) {
-  swr(rd, rs);
-  swl(rd, MemOperand(rs.rm(), rs.offset() + 3));
+  DCHECK(!rd.is(at));
+  DCHECK(!rs.rm().is(at));
+  if (kArchVariant == kMips64r6) {
+    sw(rd, rs);
+  } else {
+    DCHECK(kArchVariant == kMips64r2);
+    if (is_int16(rs.offset() + kMipsSwrOffset) &&
+        is_int16(rs.offset() + kMipsSwlOffset)) {
+      swr(rd, MemOperand(rs.rm(), rs.offset() + kMipsSwrOffset));
+      swl(rd, MemOperand(rs.rm(), rs.offset() + kMipsSwlOffset));
+    } else {
+      LoadRegPlusOffsetToAt(rs);
+      swr(rd, MemOperand(at, kMipsSwrOffset));
+      swl(rd, MemOperand(at, kMipsSwlOffset));
+    }
+  }
 }
 
-
-// Do 64-bit load from unaligned address. Note this only handles
-// the specific case of 32-bit aligned, but not 64-bit aligned.
-void MacroAssembler::Uld(Register rd, const MemOperand& rs, Register scratch) {
-  // Assert fail if the offset from start of object IS actually aligned.
-  // ONLY use with known misalignment, since there is performance cost.
-  DCHECK((rs.offset() + kHeapObjectTag) & (kPointerSize - 1));
-  if (kArchEndian == kLittle) {
-    lwu(rd, rs);
-    lw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2));
-    dsll32(scratch, scratch, 0);
+void MacroAssembler::Ulh(Register rd, const MemOperand& rs) {
+  DCHECK(!rd.is(at));
+  DCHECK(!rs.rm().is(at));
+  if (kArchVariant == kMips64r6) {
+    lh(rd, rs);
   } else {
-    lw(rd, rs);
-    lwu(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2));
-    dsll32(rd, rd, 0);
+    DCHECK(kArchVariant == kMips64r2);
+    if (is_int16(rs.offset()) && is_int16(rs.offset() + 1)) {
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+      lbu(at, rs);
+      lb(rd, MemOperand(rs.rm(), rs.offset() + 1));
+#elif defined(V8_TARGET_BIG_ENDIAN)
+      lbu(at, MemOperand(rs.rm(), rs.offset() + 1));
+      lb(rd, rs);
+#endif
+    } else {  // Offset > 16 bits, use multiple instructions to load.
+      LoadRegPlusOffsetToAt(rs);
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+      lb(rd, MemOperand(at, 1));
+      lbu(at, MemOperand(at, 0));
+#elif defined(V8_TARGET_BIG_ENDIAN)
+      lb(rd, MemOperand(at, 0));
+      lbu(at, MemOperand(at, 1));
+#endif
+    }
+    dsll(rd, rd, 8);
+    or_(rd, rd, at);
   }
-  Daddu(rd, rd, scratch);
+}
+
+void MacroAssembler::Ulhu(Register rd, const MemOperand& rs) {
+  DCHECK(!rd.is(at));
+  DCHECK(!rs.rm().is(at));
+  if (kArchVariant == kMips64r6) {
+    lhu(rd, rs);
+  } else {
+    DCHECK(kArchVariant == kMips64r2);
+    if (is_int16(rs.offset()) && is_int16(rs.offset() + 1)) {
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+      lbu(at, rs);
+      lbu(rd, MemOperand(rs.rm(), rs.offset() + 1));
+#elif defined(V8_TARGET_BIG_ENDIAN)
+      lbu(at, MemOperand(rs.rm(), rs.offset() + 1));
+      lbu(rd, rs);
+#endif
+    } else {  // Offset > 16 bits, use multiple instructions to load.
+      LoadRegPlusOffsetToAt(rs);
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+      lbu(rd, MemOperand(at, 1));
+      lbu(at, MemOperand(at, 0));
+#elif defined(V8_TARGET_BIG_ENDIAN)
+      lbu(rd, MemOperand(at, 0));
+      lbu(at, MemOperand(at, 1));
+#endif
+    }
+    dsll(rd, rd, 8);
+    or_(rd, rd, at);
+  }
+}
+
+void MacroAssembler::Ush(Register rd, const MemOperand& rs, Register scratch) {
+  DCHECK(!rd.is(at));
+  DCHECK(!rs.rm().is(at));
+  DCHECK(!rs.rm().is(scratch));
+  DCHECK(!scratch.is(at));
+  if (kArchVariant == kMips64r6) {
+    sh(rd, rs);
+  } else {
+    DCHECK(kArchVariant == kMips64r2);
+    MemOperand source = rs;
+    // If offset > 16 bits, load address to at with offset 0.
+    if (!is_int16(rs.offset()) || !is_int16(rs.offset() + 1)) {
+      LoadRegPlusOffsetToAt(rs);
+      source = MemOperand(at, 0);
+    }
+
+    if (!scratch.is(rd)) {
+      mov(scratch, rd);
+    }
+
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+    sb(scratch, source);
+    srl(scratch, scratch, 8);
+    sb(scratch, MemOperand(source.rm(), source.offset() + 1));
+#elif defined(V8_TARGET_BIG_ENDIAN)
+    sb(scratch, MemOperand(source.rm(), source.offset() + 1));
+    srl(scratch, scratch, 8);
+    sb(scratch, source);
+#endif
+  }
+}
+
+void MacroAssembler::Uld(Register rd, const MemOperand& rs) {
+  DCHECK(!rd.is(at));
+  DCHECK(!rs.rm().is(at));
+  if (kArchVariant == kMips64r6) {
+    ld(rd, rs);
+  } else {
+    DCHECK(kArchVariant == kMips64r2);
+    if (is_int16(rs.offset() + kMipsLdrOffset) &&
+        is_int16(rs.offset() + kMipsLdlOffset)) {
+      if (!rd.is(rs.rm())) {
+        ldr(rd, MemOperand(rs.rm(), rs.offset() + kMipsLdrOffset));
+        ldl(rd, MemOperand(rs.rm(), rs.offset() + kMipsLdlOffset));
+      } else {
+        ldr(at, MemOperand(rs.rm(), rs.offset() + kMipsLdrOffset));
+        ldl(at, MemOperand(rs.rm(), rs.offset() + kMipsLdlOffset));
+        mov(rd, at);
+      }
+    } else {  // Offset > 16 bits, use multiple instructions to load.
+      LoadRegPlusOffsetToAt(rs);
+      ldr(rd, MemOperand(at, kMipsLdrOffset));
+      ldl(rd, MemOperand(at, kMipsLdlOffset));
+    }
+  }
 }
 
 
@@ -1366,21 +1562,22 @@
   Daddu(rd, rd, scratch);
 }
 
-
-// Do 64-bit store to unaligned address. Note this only handles
-// the specific case of 32-bit aligned, but not 64-bit aligned.
-void MacroAssembler::Usd(Register rd, const MemOperand& rs, Register scratch) {
-  // Assert fail if the offset from start of object IS actually aligned.
-  // ONLY use with known misalignment, since there is performance cost.
-  DCHECK((rs.offset() + kHeapObjectTag) & (kPointerSize - 1));
-  if (kArchEndian == kLittle) {
-    sw(rd, rs);
-    dsrl32(scratch, rd, 0);
-    sw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2));
+void MacroAssembler::Usd(Register rd, const MemOperand& rs) {
+  DCHECK(!rd.is(at));
+  DCHECK(!rs.rm().is(at));
+  if (kArchVariant == kMips64r6) {
+    sd(rd, rs);
   } else {
-    sw(rd, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2));
-    dsrl32(scratch, rd, 0);
-    sw(scratch, rs);
+    DCHECK(kArchVariant == kMips64r2);
+    if (is_int16(rs.offset() + kMipsSdrOffset) &&
+        is_int16(rs.offset() + kMipsSdlOffset)) {
+      sdr(rd, MemOperand(rs.rm(), rs.offset() + kMipsSdrOffset));
+      sdl(rd, MemOperand(rs.rm(), rs.offset() + kMipsSdlOffset));
+    } else {
+      LoadRegPlusOffsetToAt(rs);
+      sdr(rd, MemOperand(at, kMipsSdrOffset));
+      sdl(rd, MemOperand(at, kMipsSdlOffset));
+    }
   }
 }
 
@@ -1393,6 +1590,51 @@
   sw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2));
 }
 
+void MacroAssembler::Ulwc1(FPURegister fd, const MemOperand& rs,
+                           Register scratch) {
+  if (kArchVariant == kMips64r6) {
+    lwc1(fd, rs);
+  } else {
+    DCHECK(kArchVariant == kMips64r2);
+    Ulw(scratch, rs);
+    mtc1(scratch, fd);
+  }
+}
+
+void MacroAssembler::Uswc1(FPURegister fd, const MemOperand& rs,
+                           Register scratch) {
+  if (kArchVariant == kMips64r6) {
+    swc1(fd, rs);
+  } else {
+    DCHECK(kArchVariant == kMips64r2);
+    mfc1(scratch, fd);
+    Usw(scratch, rs);
+  }
+}
+
+void MacroAssembler::Uldc1(FPURegister fd, const MemOperand& rs,
+                           Register scratch) {
+  DCHECK(!scratch.is(at));
+  if (kArchVariant == kMips64r6) {
+    ldc1(fd, rs);
+  } else {
+    DCHECK(kArchVariant == kMips64r2);
+    Uld(scratch, rs);
+    dmtc1(scratch, fd);
+  }
+}
+
+void MacroAssembler::Usdc1(FPURegister fd, const MemOperand& rs,
+                           Register scratch) {
+  DCHECK(!scratch.is(at));
+  if (kArchVariant == kMips64r6) {
+    sdc1(fd, rs);
+  } else {
+    DCHECK(kArchVariant == kMips64r2);
+    dmfc1(scratch, fd);
+    Usd(scratch, rs);
+  }
+}
 
 void MacroAssembler::li(Register dst, Handle<Object> value, LiFlags mode) {
   AllowDeferredHandleDereference smi_check;
@@ -3843,9 +4085,6 @@
   Label start;
   bind(&start);
   int64_t target_int = reinterpret_cast<int64_t>(target);
-  // Must record previous source positions before the
-  // li() generates a new code target.
-  positions_recorder()->WriteRecordedPositions();
   li(t9, Operand(target_int, rmode), ADDRESS_LOAD);
   Call(t9, cond, rs, rt, bd);
   DCHECK_EQ(CallSize(target, rmode, cond, rs, rt, bd),
@@ -4142,12 +4381,14 @@
   // to calculate the new top.
   Daddu(result_end, result, Operand(object_size));
   Branch(gc_required, Ugreater, result_end, Operand(alloc_limit));
-  sd(result_end, MemOperand(top_address));
 
-  // Tag object if requested.
-  if ((flags & TAG_OBJECT) != 0) {
-    Daddu(result, result, Operand(kHeapObjectTag));
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    sd(result_end, MemOperand(top_address));
   }
+
+  // Tag object.
+  Daddu(result, result, Operand(kHeapObjectTag));
 }
 
 
@@ -4217,6 +4458,7 @@
   } else {
     Daddu(result_end, result, Operand(object_size));
   }
+
   Branch(gc_required, Ugreater, result_end, Operand(alloc_limit));
 
   // Update allocation top. result temporarily holds the new top.
@@ -4224,14 +4466,91 @@
     And(at, result_end, Operand(kObjectAlignmentMask));
     Check(eq, kUnalignedAllocationInNewSpace, at, Operand(zero_reg));
   }
-  sd(result_end, MemOperand(top_address));
 
-  // Tag object if requested.
-  if ((flags & TAG_OBJECT) != 0) {
-    Daddu(result, result, Operand(kHeapObjectTag));
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    sd(result_end, MemOperand(top_address));
   }
+
+  // Tag object if.
+  Daddu(result, result, Operand(kHeapObjectTag));
 }
 
+void MacroAssembler::FastAllocate(int object_size, Register result,
+                                  Register scratch1, Register scratch2,
+                                  AllocationFlags flags) {
+  DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
+  DCHECK(!AreAliased(result, scratch1, scratch2, at));
+
+  // Make object size into bytes.
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    object_size *= kPointerSize;
+  }
+  DCHECK(0 == (object_size & kObjectAlignmentMask));
+
+  ExternalReference allocation_top =
+      AllocationUtils::GetAllocationTopReference(isolate(), flags);
+
+  Register top_address = scratch1;
+  Register result_end = scratch2;
+  li(top_address, Operand(allocation_top));
+  ld(result, MemOperand(top_address));
+
+  // We can ignore DOUBLE_ALIGNMENT flags here because doubles and pointers have
+  // the same alignment on MIPS64.
+  STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
+
+  if (emit_debug_code()) {
+    And(at, result, Operand(kDoubleAlignmentMask));
+    Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg));
+  }
+
+  // Calculate new top and write it back.
+  Daddu(result_end, result, Operand(object_size));
+  sd(result_end, MemOperand(top_address));
+
+  Daddu(result, result, Operand(kHeapObjectTag));
+}
+
+void MacroAssembler::FastAllocate(Register object_size, Register result,
+                                  Register result_end, Register scratch,
+                                  AllocationFlags flags) {
+  // |object_size| and |result_end| may overlap, other registers must not.
+  DCHECK(!AreAliased(object_size, result, scratch, at));
+  DCHECK(!AreAliased(result_end, result, scratch, at));
+
+  ExternalReference allocation_top =
+      AllocationUtils::GetAllocationTopReference(isolate(), flags);
+
+  // Set up allocation top address and object size registers.
+  Register top_address = scratch;
+  li(top_address, Operand(allocation_top));
+  ld(result, MemOperand(top_address));
+
+  // We can ignore DOUBLE_ALIGNMENT flags here because doubles and pointers have
+  // the same alignment on MIPS64.
+  STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
+
+  if (emit_debug_code()) {
+    And(at, result, Operand(kDoubleAlignmentMask));
+    Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg));
+  }
+
+  // Calculate new top and write it back
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    Dlsa(result_end, result, object_size, kPointerSizeLog2);
+  } else {
+    Daddu(result_end, result, Operand(object_size));
+  }
+
+  // Update allocation top. result temporarily holds the new top.
+  if (emit_debug_code()) {
+    And(at, result_end, Operand(kObjectAlignmentMask));
+    Check(eq, kUnalignedAllocationInNewSpace, at, Operand(zero_reg));
+  }
+
+  Daddu(result, result, Operand(kHeapObjectTag));
+}
 
 void MacroAssembler::AllocateTwoByteString(Register result,
                                            Register length,
@@ -4248,12 +4567,8 @@
   And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
 
   // Allocate two-byte string in new space.
-  Allocate(scratch1,
-           result,
-           scratch2,
-           scratch3,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(scratch1, result, scratch2, scratch3, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   InitializeNewString(result,
@@ -4277,12 +4592,8 @@
   And(scratch1, scratch1, Operand(~kObjectAlignmentMask));
 
   // Allocate one-byte string in new space.
-  Allocate(scratch1,
-           result,
-           scratch2,
-           scratch3,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(scratch1, result, scratch2, scratch3, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   InitializeNewString(result, length, Heap::kOneByteStringMapRootIndex,
@@ -4296,7 +4607,7 @@
                                                Register scratch2,
                                                Label* gc_required) {
   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
   InitializeNewString(result,
                       length,
                       Heap::kConsStringMapRootIndex,
@@ -4309,12 +4620,8 @@
                                                Register scratch1,
                                                Register scratch2,
                                                Label* gc_required) {
-  Allocate(ConsString::kSize,
-           result,
-           scratch1,
-           scratch2,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result, length, Heap::kConsOneByteStringMapRootIndex,
                       scratch1, scratch2);
@@ -4327,7 +4634,7 @@
                                                  Register scratch2,
                                                  Label* gc_required) {
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result,
                       length,
@@ -4343,7 +4650,7 @@
                                                  Register scratch2,
                                                  Label* gc_required) {
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result, length, Heap::kSlicedOneByteStringMapRootIndex,
                       scratch1, scratch2);
@@ -4369,12 +4676,11 @@
                                         Register scratch2,
                                         Register heap_number_map,
                                         Label* need_gc,
-                                        TaggingMode tagging_mode,
                                         MutableMode mode) {
   // Allocate an object in the heap for the heap number and tag it as a heap
   // object.
   Allocate(HeapNumber::kSize, result, scratch1, scratch2, need_gc,
-           tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS);
+           NO_ALLOCATION_FLAGS);
 
   Heap::RootListIndex map_index = mode == MUTABLE
       ? Heap::kMutableHeapNumberMapRootIndex
@@ -4382,11 +4688,7 @@
   AssertIsRoot(heap_number_map, map_index);
 
   // Store heap number map in the allocated object.
-  if (tagging_mode == TAG_RESULT) {
-    sd(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
-  } else {
-    sd(heap_number_map, MemOperand(result, HeapObject::kMapOffset));
-  }
+  sd(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
 }
 
 
@@ -4410,7 +4712,8 @@
   DCHECK(!result.is(value));
 
   // Allocate JSValue in new space.
-  Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required, TAG_OBJECT);
+  Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Initialize the JSValue.
   LoadGlobalFunctionInitialMap(constructor, scratch1, scratch2);
@@ -4602,6 +4905,72 @@
   sdc1(double_result, MemOperand(scratch1, 0));
 }
 
+void MacroAssembler::SubNanPreservePayloadAndSign_s(FPURegister fd,
+                                                    FPURegister fs,
+                                                    FPURegister ft) {
+  FloatRegister dest = fd.is(fs) || fd.is(ft) ? kLithiumScratchDouble : fd;
+  Label check_nan, save_payload, done;
+  Register scratch1 = t8;
+  Register scratch2 = t9;
+
+  sub_s(dest, fs, ft);
+  // Check if the result of subtraction is NaN.
+  BranchF32(nullptr, &check_nan, eq, fs, ft);
+  Branch(USE_DELAY_SLOT, &done);
+  dest.is(fd) ? nop() : mov_s(fd, dest);
+
+  bind(&check_nan);
+  // Check if first operand is a NaN.
+  mfc1(scratch1, fs);
+  BranchF32(nullptr, &save_payload, eq, fs, fs);
+  // Second operand must be a NaN.
+  mfc1(scratch1, ft);
+
+  bind(&save_payload);
+  // Reserve payload.
+  And(scratch1, scratch1,
+      Operand(kSingleSignMask | ((1 << kSingleNaNShift) - 1)));
+  mfc1(scratch2, dest);
+  And(scratch2, scratch2, Operand(kSingleNaNMask));
+  Or(scratch2, scratch2, scratch1);
+  mtc1(scratch2, fd);
+
+  bind(&done);
+}
+
+void MacroAssembler::SubNanPreservePayloadAndSign_d(FPURegister fd,
+                                                    FPURegister fs,
+                                                    FPURegister ft) {
+  FloatRegister dest = fd.is(fs) || fd.is(ft) ? kLithiumScratchDouble : fd;
+  Label check_nan, save_payload, done;
+  Register scratch1 = t8;
+  Register scratch2 = t9;
+
+  sub_d(dest, fs, ft);
+  // Check if the result of subtraction is NaN.
+  BranchF64(nullptr, &check_nan, eq, fs, ft);
+  Branch(USE_DELAY_SLOT, &done);
+  dest.is(fd) ? nop() : mov_d(fd, dest);
+
+  bind(&check_nan);
+  // Check if first operand is a NaN.
+  dmfc1(scratch1, fs);
+  BranchF64(nullptr, &save_payload, eq, fs, fs);
+  // Second operand must be a NaN.
+  dmfc1(scratch1, ft);
+
+  bind(&save_payload);
+  // Reserve payload.
+  li(at, Operand(kDoubleSignMask | (1L << kDoubleNaNShift)));
+  Dsubu(at, at, Operand(1));
+  And(scratch1, scratch1, at);
+  dmfc1(scratch2, dest);
+  And(scratch2, scratch2, Operand(kDoubleNaNMask));
+  Or(scratch2, scratch2, scratch1);
+  dmtc1(scratch2, fd);
+
+  bind(&done);
+}
 
 void MacroAssembler::CompareMapAndBranch(Register obj,
                                          Register scratch,
@@ -4890,11 +5259,12 @@
                                              const ParameterCount& expected,
                                              const ParameterCount& actual) {
   Label skip_flooding;
-  ExternalReference step_in_enabled =
-      ExternalReference::debug_step_in_enabled_address(isolate());
-  li(t0, Operand(step_in_enabled));
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(isolate());
+  STATIC_ASSERT(StepFrame > StepIn);
+  li(t0, Operand(last_step_action));
   lb(t0, MemOperand(t0));
-  Branch(&skip_flooding, eq, t0, Operand(zero_reg));
+  Branch(&skip_flooding, lt, t0, Operand(StepIn));
   {
     FrameScope frame(this,
                      has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
@@ -5779,9 +6149,8 @@
 
 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
   ld(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  ld(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset));
-  ld(vector,
-     FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset));
+  ld(vector, FieldMemOperand(vector, JSFunction::kLiteralsOffset));
+  ld(vector, FieldMemOperand(vector, LiteralsArray::kFeedbackVectorOffset));
 }
 
 
@@ -6225,6 +6594,16 @@
   }
 }
 
+void MacroAssembler::AssertGeneratorObject(Register object) {
+  if (emit_debug_code()) {
+    STATIC_ASSERT(kSmiTag == 0);
+    SmiTst(object, t8);
+    Check(ne, kOperandIsASmiAndNotAGeneratorObject, t8, Operand(zero_reg));
+    GetObjectType(object, t8, t8);
+    Check(eq, kOperandIsNotAGeneratorObject, t8,
+          Operand(JS_GENERATOR_OBJECT_TYPE));
+  }
+}
 
 void MacroAssembler::AssertReceiver(Register object) {
   if (emit_debug_code()) {
@@ -6696,7 +7075,7 @@
                                                      Label* no_memento_found) {
   Label map_check;
   Label top_check;
-  ExternalReference new_space_allocation_top =
+  ExternalReference new_space_allocation_top_adr =
       ExternalReference::new_space_allocation_top_address(isolate());
   const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
   const int kMementoEndOffset = kMementoMapOffset + AllocationMemento::kSize;
@@ -6705,14 +7084,16 @@
   JumpIfNotInNewSpace(receiver_reg, scratch_reg, no_memento_found);
   // If the object is in new space, we need to check whether it is on the same
   // page as the current top.
-  Addu(scratch_reg, receiver_reg, Operand(kMementoEndOffset));
-  Xor(scratch_reg, scratch_reg, Operand(new_space_allocation_top));
+  Daddu(scratch_reg, receiver_reg, Operand(kMementoEndOffset));
+  li(at, Operand(new_space_allocation_top_adr));
+  ld(at, MemOperand(at));
+  Xor(scratch_reg, scratch_reg, Operand(at));
   And(scratch_reg, scratch_reg, Operand(~Page::kPageAlignmentMask));
   Branch(&top_check, eq, scratch_reg, Operand(zero_reg));
   // The object is on a different page than allocation top. Bail out if the
   // object sits on the page boundary as no memento can follow and we cannot
   // touch the memory following it.
-  Addu(scratch_reg, receiver_reg, Operand(kMementoEndOffset));
+  Daddu(scratch_reg, receiver_reg, Operand(kMementoEndOffset));
   Xor(scratch_reg, scratch_reg, Operand(receiver_reg));
   And(scratch_reg, scratch_reg, Operand(~Page::kPageAlignmentMask));
   Branch(no_memento_found, ne, scratch_reg, Operand(zero_reg));
@@ -6721,13 +7102,13 @@
   // If top is on the same page as the current object, we need to check whether
   // we are below top.
   bind(&top_check);
-  Addu(scratch_reg, receiver_reg, Operand(kMementoEndOffset));
-  li(at, Operand(new_space_allocation_top));
-  lw(at, MemOperand(at));
+  Daddu(scratch_reg, receiver_reg, Operand(kMementoEndOffset));
+  li(at, Operand(new_space_allocation_top_adr));
+  ld(at, MemOperand(at));
   Branch(no_memento_found, gt, scratch_reg, Operand(at));
   // Memento map check.
   bind(&map_check);
-  lw(scratch_reg, MemOperand(receiver_reg, kMementoMapOffset));
+  ld(scratch_reg, MemOperand(receiver_reg, kMementoMapOffset));
   Branch(no_memento_found, ne, scratch_reg,
          Operand(isolate()->factory()->allocation_memento_map()));
 }
@@ -6747,8 +7128,7 @@
   if (reg5.is_valid()) regs |= reg5.bit();
   if (reg6.is_valid()) regs |= reg6.bit();
 
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
     int code = config->GetAllocatableGeneralCode(i);
     Register candidate = Register::from_code(code);
diff --git a/src/mips64/macro-assembler-mips64.h b/src/mips64/macro-assembler-mips64.h
index 401112d..576d30a 100644
--- a/src/mips64/macro-assembler-mips64.h
+++ b/src/mips64/macro-assembler-mips64.h
@@ -18,8 +18,8 @@
 const Register kReturnRegister2 = {Register::kCode_a0};
 const Register kJSFunctionRegister = {Register::kCode_a1};
 const Register kContextRegister = {Register::kCpRegister};
+const Register kAllocateSizeRegister = {Register::kCode_a0};
 const Register kInterpreterAccumulatorRegister = {Register::kCode_v0};
-const Register kInterpreterRegisterFileRegister = {Register::kCode_a7};
 const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_t0};
 const Register kInterpreterBytecodeArrayRegister = {Register::kCode_t1};
 const Register kInterpreterDispatchTableRegister = {Register::kCode_t2};
@@ -587,6 +587,15 @@
   void Allocate(Register object_size, Register result, Register result_end,
                 Register scratch, Label* gc_required, AllocationFlags flags);
 
+  // FastAllocate is right now only used for folded allocations. It just
+  // increments the top pointer without checking against limit. This can only
+  // be done if it was proved earlier that the allocation will succeed.
+  void FastAllocate(int object_size, Register result, Register scratch1,
+                    Register scratch2, AllocationFlags flags);
+
+  void FastAllocate(Register object_size, Register result, Register result_new,
+                    Register scratch, AllocationFlags flags);
+
   void AllocateTwoByteString(Register result,
                              Register length,
                              Register scratch1,
@@ -621,7 +630,6 @@
                           Register scratch2,
                           Register heap_number_map,
                           Label* gc_required,
-                          TaggingMode tagging_mode = TAG_RESULT,
                           MutableMode mode = IMMUTABLE);
 
   void AllocateHeapNumberWithValue(Register result,
@@ -714,12 +722,28 @@
   // ---------------------------------------------------------------------------
   // Pseudo-instructions.
 
+  // Change endianness
+  void ByteSwapSigned(Register reg, int operand_size);
+  void ByteSwapUnsigned(Register reg, int operand_size);
+
   void mov(Register rd, Register rt) { or_(rd, rt, zero_reg); }
 
+  void Ulh(Register rd, const MemOperand& rs);
+  void Ulhu(Register rd, const MemOperand& rs);
+  void Ush(Register rd, const MemOperand& rs, Register scratch);
+
   void Ulw(Register rd, const MemOperand& rs);
+  void Ulwu(Register rd, const MemOperand& rs);
   void Usw(Register rd, const MemOperand& rs);
-  void Uld(Register rd, const MemOperand& rs, Register scratch = at);
-  void Usd(Register rd, const MemOperand& rs, Register scratch = at);
+
+  void Uld(Register rd, const MemOperand& rs);
+  void Usd(Register rd, const MemOperand& rs);
+
+  void Ulwc1(FPURegister fd, const MemOperand& rs, Register scratch);
+  void Uswc1(FPURegister fd, const MemOperand& rs, Register scratch);
+
+  void Uldc1(FPURegister fd, const MemOperand& rs, Register scratch);
+  void Usdc1(FPURegister fd, const MemOperand& rs, Register scratch);
 
   void LoadWordPair(Register rd, const MemOperand& rs, Register scratch = at);
   void StoreWordPair(Register rd, const MemOperand& rs, Register scratch = at);
@@ -909,6 +933,12 @@
   void Floor_w_d(FPURegister fd, FPURegister fs);
   void Ceil_w_d(FPURegister fd, FPURegister fs);
 
+  // Preserve value of a NaN operand
+  void SubNanPreservePayloadAndSign_s(FPURegister fd, FPURegister fs,
+                                      FPURegister ft);
+  void SubNanPreservePayloadAndSign_d(FPURegister fd, FPURegister fs,
+                                      FPURegister ft);
+
   void Madd_d(FPURegister fd,
               FPURegister fr,
               FPURegister fs,
@@ -1714,6 +1744,10 @@
   // enabled via --debug-code.
   void AssertBoundFunction(Register object);
 
+  // Abort execution if argument is not a JSGeneratorObject,
+  // enabled via --debug-code.
+  void AssertGeneratorObject(Register object);
+
   // Abort execution if argument is not a JSReceiver, enabled via --debug-code.
   void AssertReceiver(Register object);
 
diff --git a/src/mips64/simulator-mips64.cc b/src/mips64/simulator-mips64.cc
index 9519865..ed484ef 100644
--- a/src/mips64/simulator-mips64.cc
+++ b/src/mips64/simulator-mips64.cc
@@ -268,33 +268,42 @@
 
   PrintF("\n");
   // at, v0, a0.
-  PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
+  PrintF("%3s: 0x%016" PRIx64 " %14" PRId64 "\t%3s: 0x%016" PRIx64 " %14" PRId64
+         "\t%3s: 0x%016" PRIx64 " %14" PRId64 "\n",
          REG_INFO(1), REG_INFO(2), REG_INFO(4));
   // v1, a1.
-  PrintF("%34s\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
+  PrintF("%34s\t%3s: 0x%016" PRIx64 "  %14" PRId64 " \t%3s: 0x%016" PRIx64
+         "  %14" PRId64 " \n",
          "", REG_INFO(3), REG_INFO(5));
   // a2.
-  PrintF("%34s\t%34s\t%3s: 0x%016lx %14ld\n", "", "", REG_INFO(6));
+  PrintF("%34s\t%34s\t%3s: 0x%016" PRIx64 "  %14" PRId64 " \n", "", "",
+         REG_INFO(6));
   // a3.
-  PrintF("%34s\t%34s\t%3s: 0x%016lx %14ld\n", "", "", REG_INFO(7));
+  PrintF("%34s\t%34s\t%3s: 0x%016" PRIx64 "  %14" PRId64 " \n", "", "",
+         REG_INFO(7));
   PrintF("\n");
   // a4-t3, s0-s7
   for (int i = 0; i < 8; i++) {
-    PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
-           REG_INFO(8+i), REG_INFO(16+i));
+    PrintF("%3s: 0x%016" PRIx64 "  %14" PRId64 " \t%3s: 0x%016" PRIx64
+           "  %14" PRId64 " \n",
+           REG_INFO(8 + i), REG_INFO(16 + i));
   }
   PrintF("\n");
   // t8, k0, LO.
-  PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
+  PrintF("%3s: 0x%016" PRIx64 "  %14" PRId64 " \t%3s: 0x%016" PRIx64
+         "  %14" PRId64 " \t%3s: 0x%016" PRIx64 "  %14" PRId64 " \n",
          REG_INFO(24), REG_INFO(26), REG_INFO(32));
   // t9, k1, HI.
-  PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
+  PrintF("%3s: 0x%016" PRIx64 "  %14" PRId64 " \t%3s: 0x%016" PRIx64
+         "  %14" PRId64 " \t%3s: 0x%016" PRIx64 "  %14" PRId64 " \n",
          REG_INFO(25), REG_INFO(27), REG_INFO(33));
   // sp, fp, gp.
-  PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
+  PrintF("%3s: 0x%016" PRIx64 "  %14" PRId64 " \t%3s: 0x%016" PRIx64
+         "  %14" PRId64 " \t%3s: 0x%016" PRIx64 "  %14" PRId64 " \n",
          REG_INFO(29), REG_INFO(30), REG_INFO(28));
   // pc.
-  PrintF("%3s: 0x%016lx %14ld\t%3s: 0x%016lx %14ld\n",
+  PrintF("%3s: 0x%016" PRIx64 "  %14" PRId64 " \t%3s: 0x%016" PRIx64
+         "  %14" PRId64 " \n",
          REG_INFO(31), REG_INFO(34));
 
 #undef REG_INFO
@@ -312,38 +321,38 @@
   PrintF("\n\n");
   // f0, f1, f2, ... f31.
   // TODO(plind): consider printing 2 columns for space efficiency.
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(0) );
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(1) );
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(2) );
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(3) );
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(4) );
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(5) );
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(6) );
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(7) );
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(8) );
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(9) );
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(10));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(11));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(12));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(13));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(14));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(15));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(16));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(17));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(18));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(19));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(20));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(21));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(22));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(23));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(24));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(25));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(26));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(27));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(28));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(29));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(30));
-  PrintF("%3s: 0x%016lx %16.4e\n", FPU_REG_INFO(31));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(0));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(1));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(2));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(3));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(4));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(5));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(6));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(7));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(8));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(9));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(10));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(11));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(12));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(13));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(14));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(15));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(16));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(17));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(18));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(19));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(20));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(21));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(22));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(23));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(24));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(25));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(26));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(27));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(28));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(29));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(30));
+  PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n", FPU_REG_INFO(31));
 
 #undef REG_INFO
 #undef FPU_REG_INFO
@@ -382,7 +391,7 @@
       v8::internal::EmbeddedVector<char, 256> buffer;
       dasm.InstructionDecode(buffer,
                              reinterpret_cast<byte*>(sim_->get_pc()));
-      PrintF("  0x%016lx  %s\n", sim_->get_pc(), buffer.start());
+      PrintF("  0x%016" PRIx64 "   %s\n", sim_->get_pc(), buffer.start());
       last_pc = sim_->get_pc();
     }
     char* line = ReadLine("sim> ");
@@ -433,11 +442,12 @@
 
             if (regnum != kInvalidRegister) {
               value = GetRegisterValue(regnum);
-              PrintF("%s: 0x%08lx %ld \n", arg1, value, value);
+              PrintF("%s: 0x%08" PRIx64 "  %" PRId64 "  \n", arg1, value,
+                     value);
             } else if (fpuregnum != kInvalidFPURegister) {
               value = GetFPURegisterValue(fpuregnum);
               dvalue = GetFPURegisterValueDouble(fpuregnum);
-              PrintF("%3s: 0x%016lx %16.4e\n",
+              PrintF("%3s: 0x%016" PRIx64 "  %16.4e\n",
                      FPURegisters::Name(fpuregnum), value, dvalue);
             } else {
               PrintF("%s unrecognized\n", arg1);
@@ -454,7 +464,7 @@
                 value = GetFPURegisterValue(fpuregnum);
                 value &= 0xffffffffUL;
                 fvalue = GetFPURegisterValueFloat(fpuregnum);
-                PrintF("%s: 0x%08lx %11.4e\n", arg1, value, fvalue);
+                PrintF("%s: 0x%08" PRIx64 "  %11.4e\n", arg1, value, fvalue);
               } else {
                 PrintF("%s unrecognized\n", arg1);
               }
@@ -513,7 +523,7 @@
         end = cur + words;
 
         while (cur < end) {
-          PrintF("  0x%012lx:  0x%016lx %14ld",
+          PrintF("  0x%012" PRIxPTR " :  0x%016" PRIx64 "  %14" PRId64 " ",
                  reinterpret_cast<intptr_t>(cur), *cur, *cur);
           HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
           int64_t value = *cur;
@@ -576,8 +586,8 @@
 
         while (cur < end) {
           dasm.InstructionDecode(buffer, cur);
-          PrintF("  0x%08lx  %s\n",
-              reinterpret_cast<intptr_t>(cur), buffer.start());
+          PrintF("  0x%08" PRIxPTR "   %s\n", reinterpret_cast<intptr_t>(cur),
+                 buffer.start());
           cur += Instruction::kInstrSize;
         }
       } else if (strcmp(cmd, "gdb") == 0) {
@@ -698,8 +708,8 @@
 
         while (cur < end) {
           dasm.InstructionDecode(buffer, cur);
-          PrintF("  0x%08lx  %s\n",
-                 reinterpret_cast<intptr_t>(cur), buffer.start());
+          PrintF("  0x%08" PRIxPTR "   %s\n", reinterpret_cast<intptr_t>(cur),
+                 buffer.start());
           cur += Instruction::kInstrSize;
         }
       } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
@@ -791,9 +801,7 @@
   last_debugger_input_ = input;
 }
 
-
-void Simulator::FlushICache(v8::internal::HashMap* i_cache,
-                            void* start_addr,
+void Simulator::FlushICache(base::HashMap* i_cache, void* start_addr,
                             size_t size) {
   int64_t start = reinterpret_cast<int64_t>(start_addr);
   int64_t intra_line = (start & CachePage::kLineMask);
@@ -814,10 +822,8 @@
   }
 }
 
-
-CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
-  v8::internal::HashMap::Entry* entry =
-      i_cache->LookupOrInsert(page, ICacheHash(page));
+CachePage* Simulator::GetCachePage(base::HashMap* i_cache, void* page) {
+  base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page));
   if (entry->value == NULL) {
     CachePage* new_page = new CachePage();
     entry->value = new_page;
@@ -827,7 +833,7 @@
 
 
 // Flush from start up to and not including start + size.
-void Simulator::FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
+void Simulator::FlushOnePage(base::HashMap* i_cache, intptr_t start,
                              size_t size) {
   DCHECK(size <= CachePage::kPageSize);
   DCHECK(AllOnOnePage(start, size - 1));
@@ -840,9 +846,7 @@
   memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
 }
 
-
-void Simulator::CheckICache(v8::internal::HashMap* i_cache,
-                            Instruction* instr) {
+void Simulator::CheckICache(base::HashMap* i_cache, Instruction* instr) {
   int64_t address = reinterpret_cast<int64_t>(instr);
   void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
   void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
@@ -875,7 +879,7 @@
 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
   i_cache_ = isolate_->simulator_i_cache();
   if (i_cache_ == NULL) {
-    i_cache_ = new v8::internal::HashMap(&ICacheMatch);
+    i_cache_ = new base::HashMap(&ICacheMatch);
     isolate_->set_simulator_i_cache(i_cache_);
   }
   Initialize(isolate);
@@ -990,10 +994,10 @@
 
 
 // static
-void Simulator::TearDown(HashMap* i_cache, Redirection* first) {
+void Simulator::TearDown(base::HashMap* i_cache, Redirection* first) {
   Redirection::DeleteChain(first);
   if (i_cache != nullptr) {
-    for (HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
+    for (base::HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
          entry = i_cache->Next(entry)) {
       delete static_cast<CachePage*>(entry->value);
     }
@@ -1683,7 +1687,7 @@
 
 void Simulator::TraceRegWr(int64_t value) {
   if (::v8::internal::FLAG_trace_sim) {
-    SNPrintF(trace_buf_, "%016lx", value);
+    SNPrintF(trace_buf_, "%016" PRIx64 " ", value);
   }
 }
 
@@ -1691,8 +1695,9 @@
 // TODO(plind): consider making icount_ printing a flag option.
 void Simulator::TraceMemRd(int64_t addr, int64_t value) {
   if (::v8::internal::FLAG_trace_sim) {
-    SNPrintF(trace_buf_, "%016lx <-- [%016lx]    (%ld)",
-             value, addr, icount_);
+    SNPrintF(trace_buf_,
+             "%016" PRIx64 "  <-- [%016" PRIx64 " ]    (%" PRId64 " )", value,
+             addr, icount_);
   }
 }
 
@@ -1701,19 +1706,20 @@
   if (::v8::internal::FLAG_trace_sim) {
     switch (t) {
       case BYTE:
-        SNPrintF(trace_buf_, "               %02x --> [%016lx]",
+        SNPrintF(trace_buf_, "               %02x --> [%016" PRIx64 " ]",
                  static_cast<int8_t>(value), addr);
         break;
       case HALF:
-        SNPrintF(trace_buf_, "            %04x --> [%016lx]",
+        SNPrintF(trace_buf_, "            %04x --> [%016" PRIx64 " ]",
                  static_cast<int16_t>(value), addr);
         break;
       case WORD:
-        SNPrintF(trace_buf_, "        %08x --> [%016lx]",
+        SNPrintF(trace_buf_, "        %08x --> [%016" PRIx64 " ]",
                  static_cast<int32_t>(value), addr);
         break;
       case DWORD:
-        SNPrintF(trace_buf_, "%016lx --> [%016lx]    (%ld)",
+        SNPrintF(trace_buf_,
+                 "%016" PRIx64 "  --> [%016" PRIx64 " ]    (%" PRId64 " )",
                  value, addr, icount_);
         break;
     }
@@ -1726,17 +1732,17 @@
 int32_t Simulator::ReadW(int64_t addr, Instruction* instr) {
   if (addr >=0 && addr < 0x400) {
     // This has to be a NULL-dereference, drop into debugger.
-    PrintF("Memory read from bad address: 0x%08lx, pc=0x%08lx\n",
+    PrintF("Memory read from bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR
+           " \n",
            addr, reinterpret_cast<intptr_t>(instr));
     DieOrDebug();
   }
-  if ((addr & 0x3) == 0) {
+  if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) {
     int32_t* ptr = reinterpret_cast<int32_t*>(addr);
     TraceMemRd(addr, static_cast<int64_t>(*ptr));
     return *ptr;
   }
-  PrintF("Unaligned read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
-         addr,
+  PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
          reinterpret_cast<intptr_t>(instr));
   DieOrDebug();
   return 0;
@@ -1746,17 +1752,17 @@
 uint32_t Simulator::ReadWU(int64_t addr, Instruction* instr) {
   if (addr >=0 && addr < 0x400) {
     // This has to be a NULL-dereference, drop into debugger.
-    PrintF("Memory read from bad address: 0x%08lx, pc=0x%08lx\n",
+    PrintF("Memory read from bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR
+           " \n",
            addr, reinterpret_cast<intptr_t>(instr));
     DieOrDebug();
   }
-  if ((addr & 0x3) == 0) {
+  if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) {
     uint32_t* ptr = reinterpret_cast<uint32_t*>(addr);
     TraceMemRd(addr, static_cast<int64_t>(*ptr));
     return *ptr;
   }
-  PrintF("Unaligned read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
-         addr,
+  PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
          reinterpret_cast<intptr_t>(instr));
   DieOrDebug();
   return 0;
@@ -1766,18 +1772,18 @@
 void Simulator::WriteW(int64_t addr, int32_t value, Instruction* instr) {
   if (addr >= 0 && addr < 0x400) {
     // This has to be a NULL-dereference, drop into debugger.
-    PrintF("Memory write to bad address: 0x%08lx, pc=0x%08lx\n",
+    PrintF("Memory write to bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR
+           " \n",
            addr, reinterpret_cast<intptr_t>(instr));
     DieOrDebug();
   }
-  if ((addr & 0x3) == 0) {
+  if ((addr & 0x3) == 0 || kArchVariant == kMips64r6) {
     TraceMemWr(addr, value, WORD);
     int* ptr = reinterpret_cast<int*>(addr);
     *ptr = value;
     return;
   }
-  PrintF("Unaligned write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
-         addr,
+  PrintF("Unaligned write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
          reinterpret_cast<intptr_t>(instr));
   DieOrDebug();
 }
@@ -1786,17 +1792,17 @@
 int64_t Simulator::Read2W(int64_t addr, Instruction* instr) {
   if (addr >=0 && addr < 0x400) {
     // This has to be a NULL-dereference, drop into debugger.
-    PrintF("Memory read from bad address: 0x%08lx, pc=0x%08lx\n",
+    PrintF("Memory read from bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR
+           " \n",
            addr, reinterpret_cast<intptr_t>(instr));
     DieOrDebug();
   }
-  if ((addr & kPointerAlignmentMask) == 0) {
+  if ((addr & kPointerAlignmentMask) == 0 || kArchVariant == kMips64r6) {
     int64_t* ptr = reinterpret_cast<int64_t*>(addr);
     TraceMemRd(addr, *ptr);
     return *ptr;
   }
-  PrintF("Unaligned read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
-         addr,
+  PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
          reinterpret_cast<intptr_t>(instr));
   DieOrDebug();
   return 0;
@@ -1806,102 +1812,100 @@
 void Simulator::Write2W(int64_t addr, int64_t value, Instruction* instr) {
   if (addr >= 0 && addr < 0x400) {
     // This has to be a NULL-dereference, drop into debugger.
-    PrintF("Memory write to bad address: 0x%08lx, pc=0x%08lx\n",
+    PrintF("Memory write to bad address: 0x%08" PRIx64 " , pc=0x%08" PRIxPTR
+           "\n",
            addr, reinterpret_cast<intptr_t>(instr));
     DieOrDebug();
   }
-  if ((addr & kPointerAlignmentMask) == 0) {
+  if ((addr & kPointerAlignmentMask) == 0 || kArchVariant == kMips64r6) {
     TraceMemWr(addr, value, DWORD);
     int64_t* ptr = reinterpret_cast<int64_t*>(addr);
     *ptr = value;
     return;
   }
-  PrintF("Unaligned write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
-         addr,
+  PrintF("Unaligned write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
          reinterpret_cast<intptr_t>(instr));
   DieOrDebug();
 }
 
 
 double Simulator::ReadD(int64_t addr, Instruction* instr) {
-  if ((addr & kDoubleAlignmentMask) == 0) {
+  if ((addr & kDoubleAlignmentMask) == 0 || kArchVariant == kMips64r6) {
     double* ptr = reinterpret_cast<double*>(addr);
     return *ptr;
   }
-  PrintF("Unaligned (double) read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
-         addr,
-         reinterpret_cast<intptr_t>(instr));
+  PrintF("Unaligned (double) read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n",
+         addr, reinterpret_cast<intptr_t>(instr));
   base::OS::Abort();
   return 0;
 }
 
 
 void Simulator::WriteD(int64_t addr, double value, Instruction* instr) {
-  if ((addr & kDoubleAlignmentMask) == 0) {
+  if ((addr & kDoubleAlignmentMask) == 0 || kArchVariant == kMips64r6) {
     double* ptr = reinterpret_cast<double*>(addr);
     *ptr = value;
     return;
   }
-  PrintF("Unaligned (double) write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
-         addr,
-         reinterpret_cast<intptr_t>(instr));
+  PrintF("Unaligned (double) write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR
+         "\n",
+         addr, reinterpret_cast<intptr_t>(instr));
   DieOrDebug();
 }
 
 
 uint16_t Simulator::ReadHU(int64_t addr, Instruction* instr) {
-  if ((addr & 1) == 0) {
+  if ((addr & 1) == 0 || kArchVariant == kMips64r6) {
     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
     TraceMemRd(addr, static_cast<int64_t>(*ptr));
     return *ptr;
   }
-  PrintF("Unaligned unsigned halfword read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
-         addr,
-         reinterpret_cast<intptr_t>(instr));
+  PrintF("Unaligned unsigned halfword read at 0x%08" PRIx64
+         " , pc=0x%08" V8PRIxPTR "\n",
+         addr, reinterpret_cast<intptr_t>(instr));
   DieOrDebug();
   return 0;
 }
 
 
 int16_t Simulator::ReadH(int64_t addr, Instruction* instr) {
-  if ((addr & 1) == 0) {
+  if ((addr & 1) == 0 || kArchVariant == kMips64r6) {
     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
     TraceMemRd(addr, static_cast<int64_t>(*ptr));
     return *ptr;
   }
-  PrintF("Unaligned signed halfword read at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
-         addr,
-         reinterpret_cast<intptr_t>(instr));
+  PrintF("Unaligned signed halfword read at 0x%08" PRIx64
+         " , pc=0x%08" V8PRIxPTR "\n",
+         addr, reinterpret_cast<intptr_t>(instr));
   DieOrDebug();
   return 0;
 }
 
 
 void Simulator::WriteH(int64_t addr, uint16_t value, Instruction* instr) {
-  if ((addr & 1) == 0) {
+  if ((addr & 1) == 0 || kArchVariant == kMips64r6) {
     TraceMemWr(addr, value, HALF);
     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
     *ptr = value;
     return;
   }
-  PrintF(
-      "Unaligned unsigned halfword write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
-      addr,
-      reinterpret_cast<intptr_t>(instr));
+  PrintF("Unaligned unsigned halfword write at 0x%08" PRIx64
+         " , pc=0x%08" V8PRIxPTR "\n",
+         addr, reinterpret_cast<intptr_t>(instr));
   DieOrDebug();
 }
 
 
 void Simulator::WriteH(int64_t addr, int16_t value, Instruction* instr) {
-  if ((addr & 1) == 0) {
+  if ((addr & 1) == 0 || kArchVariant == kMips64r6) {
     TraceMemWr(addr, value, HALF);
     int16_t* ptr = reinterpret_cast<int16_t*>(addr);
     *ptr = value;
     return;
   }
-  PrintF("Unaligned halfword write at 0x%08lx, pc=0x%08" V8PRIxPTR "\n",
-         addr,
-         reinterpret_cast<intptr_t>(instr));
+  PrintF("Unaligned halfword write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR
+         "\n",
+         addr, reinterpret_cast<intptr_t>(instr));
   DieOrDebug();
 }
 
@@ -1950,7 +1954,7 @@
 
 // Unsupported instructions use Format to print an error and stop execution.
 void Simulator::Format(Instruction* instr, const char* format) {
-  PrintF("Simulator found unsupported instruction:\n 0x%08lx: %s\n",
+  PrintF("Simulator found unsupported instruction:\n 0x%08" PRIxPTR " : %s\n",
          reinterpret_cast<intptr_t>(instr), format);
   UNIMPLEMENTED_MIPS();
 }
@@ -2067,15 +2071,17 @@
           case ExternalReference::BUILTIN_FP_FP_CALL:
           case ExternalReference::BUILTIN_COMPARE_CALL:
             PrintF("Call to host function at %p with args %f, %f",
-                   FUNCTION_ADDR(generic_target), dval0, dval1);
+                   static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
+                   dval1);
             break;
           case ExternalReference::BUILTIN_FP_CALL:
             PrintF("Call to host function at %p with arg %f",
-                FUNCTION_ADDR(generic_target), dval0);
+                   static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0);
             break;
           case ExternalReference::BUILTIN_FP_INT_CALL:
             PrintF("Call to host function at %p with args %f, %d",
-                   FUNCTION_ADDR(generic_target), dval0, ival);
+                   static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
+                   ival);
             break;
           default:
             UNREACHABLE();
@@ -2133,8 +2139,8 @@
       }
     } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
       if (::v8::internal::FLAG_trace_sim) {
-        PrintF("Call to host function at %p args %08lx\n",
-            reinterpret_cast<void*>(external), arg0);
+        PrintF("Call to host function at %p args %08" PRIx64 " \n",
+               reinterpret_cast<void*>(external), arg0);
       }
       SimulatorRuntimeDirectApiCall target =
           reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
@@ -2142,8 +2148,9 @@
     } else if (
         redirection->type() == ExternalReference::PROFILING_API_CALL) {
       if (::v8::internal::FLAG_trace_sim) {
-        PrintF("Call to host function at %p args %08lx %08lx\n",
-            reinterpret_cast<void*>(external), arg0, arg1);
+        PrintF("Call to host function at %p args %08" PRIx64 "  %08" PRIx64
+               " \n",
+               reinterpret_cast<void*>(external), arg0, arg1);
       }
       SimulatorRuntimeProfilingApiCall target =
           reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
@@ -2151,8 +2158,9 @@
     } else if (
         redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
       if (::v8::internal::FLAG_trace_sim) {
-        PrintF("Call to host function at %p args %08lx %08lx\n",
-            reinterpret_cast<void*>(external), arg0, arg1);
+        PrintF("Call to host function at %p args %08" PRIx64 "  %08" PRIx64
+               " \n",
+               reinterpret_cast<void*>(external), arg0, arg1);
       }
       SimulatorRuntimeDirectGetterCall target =
           reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
@@ -2160,8 +2168,9 @@
     } else if (
         redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
       if (::v8::internal::FLAG_trace_sim) {
-        PrintF("Call to host function at %p args %08lx %08lx %08lx\n",
-            reinterpret_cast<void*>(external), arg0, arg1, arg2);
+        PrintF("Call to host function at %p args %08" PRIx64 "  %08" PRIx64
+               "  %08" PRIx64 " \n",
+               reinterpret_cast<void*>(external), arg0, arg1, arg2);
       }
       SimulatorRuntimeProfilingGetterCall target =
           reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
@@ -2175,13 +2184,15 @@
             "Call to host triple returning runtime function %p "
             "args %016" PRIx64 ", %016" PRIx64 ", %016" PRIx64 ", %016" PRIx64
             ", %016" PRIx64 "\n",
-            FUNCTION_ADDR(target), arg1, arg2, arg3, arg4, arg5);
+            static_cast<void*>(FUNCTION_ADDR(target)), arg1, arg2, arg3, arg4,
+            arg5);
       }
       // arg0 is a hidden argument pointing to the return location, so don't
       // pass it to the target function.
       ObjectTriple result = target(arg1, arg2, arg3, arg4, arg5);
       if (::v8::internal::FLAG_trace_sim) {
-        PrintF("Returned { %p, %p, %p }\n", result.x, result.y, result.z);
+        PrintF("Returned { %p, %p, %p }\n", static_cast<void*>(result.x),
+               static_cast<void*>(result.y), static_cast<void*>(result.z));
       }
       // Return is passed back in address pointed to by hidden first argument.
       ObjectTriple* sim_result = reinterpret_cast<ObjectTriple*>(arg0);
@@ -2195,14 +2206,10 @@
       if (::v8::internal::FLAG_trace_sim) {
         PrintF(
             "Call to host function at %p "
-            "args %08lx, %08lx, %08lx, %08lx, %08lx, %08lx\n",
-            FUNCTION_ADDR(target),
-            arg0,
-            arg1,
-            arg2,
-            arg3,
-            arg4,
-            arg5);
+            "args %08" PRIx64 " , %08" PRIx64 " , %08" PRIx64 " , %08" PRIx64
+            " , %08" PRIx64 " , %08" PRIx64 " \n",
+            static_cast<void*>(FUNCTION_ADDR(target)), arg0, arg1, arg2, arg3,
+            arg4, arg5);
       }
       // int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
       // set_register(v0, static_cast<int32_t>(result));
@@ -2212,7 +2219,8 @@
       set_register(v1, (int64_t)(result.y));
     }
      if (::v8::internal::FLAG_trace_sim) {
-      PrintF("Returned %08lx : %08lx\n", get_register(v1), get_register(v0));
+       PrintF("Returned %08" PRIx64 "  : %08" PRIx64 " \n", get_register(v1),
+              get_register(v0));
     }
     set_register(ra, saved_ra);
     set_pc(get_register(ra));
@@ -2241,7 +2249,8 @@
 void Simulator::PrintWatchpoint(uint64_t code) {
   MipsDebugger dbg(this);
   ++break_count_;
-  PrintF("\n---- break %ld marker: %3d  (instr count: %8ld) ----------"
+  PrintF("\n---- break %" PRId64 "  marker: %3d  (instr count: %8" PRId64
+         " ) ----------"
          "----------------------------------",
          code, break_count_, icount_);
   dbg.PrintAllRegs();  // Print registers and continue running.
@@ -2291,8 +2300,10 @@
 void Simulator::IncreaseStopCounter(uint64_t code) {
   DCHECK(code <= kMaxStopCode);
   if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
-    PrintF("Stop counter for code %ld has overflowed.\n"
-           "Enabling this code and reseting the counter to 0.\n", code);
+    PrintF("Stop counter for code %" PRId64
+           "  has overflowed.\n"
+           "Enabling this code and reseting the counter to 0.\n",
+           code);
     watched_stops_[code].count = 0;
     EnableStop(code);
   } else {
@@ -2315,11 +2326,11 @@
   // Don't print the state of unused breakpoints.
   if (count != 0) {
     if (watched_stops_[code].desc) {
-      PrintF("stop %ld - 0x%lx: \t%s, \tcounter = %i, \t%s\n",
+      PrintF("stop %" PRId64 "  - 0x%" PRIx64 " : \t%s, \tcounter = %i, \t%s\n",
              code, code, state, count, watched_stops_[code].desc);
     } else {
-      PrintF("stop %ld - 0x%lx: \t%s, \tcounter = %i\n",
-             code, code, state, count);
+      PrintF("stop %" PRId64 "  - 0x%" PRIx64 " : \t%s, \tcounter = %i\n", code,
+             code, state, count);
     }
   }
 }
@@ -3420,21 +3431,50 @@
         // bits instruction. RS field is always equal to 0.
         // Sign-extend the 32-bit result.
         alu_out = static_cast<int32_t>(static_cast<uint32_t>(rt_u()) >> sa());
-      } else {
+      } else if (rs_reg() == 1) {
         // Logical right-rotate of a word by a fixed number of bits. This
         // is special case of SRL instruction, added in MIPS32 Release 2.
         // RS field is equal to 00001.
         alu_out = static_cast<int32_t>(
             base::bits::RotateRight32(static_cast<const uint32_t>(rt_u()),
                                       static_cast<const uint32_t>(sa())));
+      } else {
+        UNREACHABLE();
       }
       SetResult(rd_reg(), alu_out);
       break;
     case DSRL:
-      SetResult(rd_reg(), rt_u() >> sa());
+      if (rs_reg() == 0) {
+        // Regular logical right shift of a word by a fixed number of
+        // bits instruction. RS field is always equal to 0.
+        // Sign-extend the 64-bit result.
+        alu_out = static_cast<int64_t>(rt_u() >> sa());
+      } else if (rs_reg() == 1) {
+        // Logical right-rotate of a word by a fixed number of bits. This
+        // is special case of SRL instruction, added in MIPS32 Release 2.
+        // RS field is equal to 00001.
+        alu_out = static_cast<int64_t>(base::bits::RotateRight64(rt_u(), sa()));
+      } else {
+        UNREACHABLE();
+      }
+      SetResult(rd_reg(), alu_out);
       break;
     case DSRL32:
-      SetResult(rd_reg(), rt_u() >> sa() >> 32);
+      if (rs_reg() == 0) {
+        // Regular logical right shift of a word by a fixed number of
+        // bits instruction. RS field is always equal to 0.
+        // Sign-extend the 64-bit result.
+        alu_out = static_cast<int64_t>(rt_u() >> sa() >> 32);
+      } else if (rs_reg() == 1) {
+        // Logical right-rotate of a word by a fixed number of bits. This
+        // is special case of SRL instruction, added in MIPS32 Release 2.
+        // RS field is equal to 00001.
+        alu_out =
+            static_cast<int64_t>(base::bits::RotateRight64(rt_u(), sa() + 32));
+      } else {
+        UNREACHABLE();
+      }
+      SetResult(rd_reg(), alu_out);
       break;
     case SRA:
       SetResult(rd_reg(), (int32_t)rt() >> sa());
@@ -3470,12 +3510,13 @@
       if (sa() == 0) {
         // Regular logical right-shift of a word by a variable number of
         // bits instruction. SA field is always equal to 0.
-        alu_out = rt_u() >> rs();
+        alu_out = static_cast<int64_t>(rt_u() >> rs());
       } else {
         // Logical right-rotate of a word by a variable number of bits.
         // This is special case od SRLV instruction, added in MIPS32
         // Release 2. SA field is equal to 00001.
-        alu_out = base::bits::RotateRight64(rt_u(), rs_u());
+        alu_out =
+            static_cast<int64_t>(base::bits::RotateRight64(rt_u(), rs_u()));
       }
       SetResult(rd_reg(), alu_out);
       break;
@@ -3777,6 +3818,9 @@
     case TNE:
       do_interrupt = rs() != rt();
       break;
+    case SYNC:
+      // TODO(palfia): Ignore sync instruction for now.
+      break;
     // Conditional moves.
     case MOVN:
       if (rt()) {
@@ -3933,12 +3977,57 @@
           alu_out = static_cast<int64_t>(static_cast<int32_t>(output));
           break;
         }
-        case SEB:
-        case SEH:
-        case WSBH:
-          alu_out = 0x12345678;
-          UNREACHABLE();
+        case SEB: {
+          uint8_t input = static_cast<uint8_t>(rt());
+          uint32_t output = input;
+          uint32_t mask = 0x00000080;
+
+          // Extending sign
+          if (mask & input) {
+            output |= 0xFFFFFF00;
+          }
+
+          alu_out = static_cast<int32_t>(output);
           break;
+        }
+        case SEH: {
+          uint16_t input = static_cast<uint16_t>(rt());
+          uint32_t output = input;
+          uint32_t mask = 0x00008000;
+
+          // Extending sign
+          if (mask & input) {
+            output |= 0xFFFF0000;
+          }
+
+          alu_out = static_cast<int32_t>(output);
+          break;
+        }
+        case WSBH: {
+          uint32_t input = static_cast<uint32_t>(rt());
+          uint64_t output = 0;
+
+          uint32_t mask = 0xFF000000;
+          for (int i = 0; i < 4; i++) {
+            uint32_t tmp = mask & input;
+            if (i % 2 == 0) {
+              tmp = tmp >> 8;
+            } else {
+              tmp = tmp << 8;
+            }
+            output = output | tmp;
+            mask = mask >> 8;
+          }
+          mask = 0x80000000;
+
+          // Extending sign
+          if (mask & output) {
+            output |= 0xFFFFFFFF00000000;
+          }
+
+          alu_out = static_cast<int64_t>(output);
+          break;
+        }
         default: {
           const uint8_t bp2 = get_instr()->Bp2Value();
           sa >>= kBp2Bits;
@@ -3997,11 +4086,47 @@
           }
           break;
         }
-        case DSBH:
-        case DSHD:
-          alu_out = 0x12345678;
-          UNREACHABLE();
+        case DSBH: {
+          uint64_t input = static_cast<uint64_t>(rt());
+          uint64_t output = 0;
+
+          uint64_t mask = 0xFF00000000000000;
+          for (int i = 0; i < 8; i++) {
+            uint64_t tmp = mask & input;
+            if (i % 2 == 0)
+              tmp = tmp >> 8;
+            else
+              tmp = tmp << 8;
+
+            output = output | tmp;
+            mask = mask >> 8;
+          }
+
+          alu_out = static_cast<int64_t>(output);
           break;
+        }
+        case DSHD: {
+          uint64_t input = static_cast<uint64_t>(rt());
+          uint64_t output = 0;
+
+          uint64_t mask = 0xFFFF000000000000;
+          for (int i = 0; i < 4; i++) {
+            uint64_t tmp = mask & input;
+            if (i == 0)
+              tmp = tmp >> 48;
+            else if (i == 1)
+              tmp = tmp >> 16;
+            else if (i == 2)
+              tmp = tmp << 16;
+            else
+              tmp = tmp << 48;
+            output = output | tmp;
+            mask = mask >> 16;
+          }
+
+          alu_out = static_cast<int64_t>(output);
+          break;
+        }
         default: {
           const uint8_t bp3 = get_instr()->Bp3Value();
           sa >>= kBp3Bits;
@@ -4051,31 +4176,7 @@
       DecodeTypeRegisterSPECIAL2();
       break;
     case SPECIAL3:
-      switch (instr->FunctionFieldRaw()) {
-        case BSHFL: {
-          int32_t saVal = sa();
-          saVal >>= kBp2Bits;
-          switch (saVal) {
-            case ALIGN: {
-              DecodeTypeRegisterSPECIAL3();
-              break;
-            }
-          }
-        }
-        case DBSHFL: {
-          int32_t saVal = sa();
-          saVal >>= kBp2Bits;
-          switch (saVal) {
-            case DALIGN: {
-              DecodeTypeRegisterSPECIAL3();
-              break;
-            }
-          }
-        }
-        default:
-          DecodeTypeRegisterSPECIAL3();
-          break;
-      }
+      DecodeTypeRegisterSPECIAL3();
       break;
     // Unimplemented opcodes raised an error in the configuration step before,
     // so we can use the default here to set the destination register in common
@@ -4119,6 +4220,8 @@
   int64_t addr = 0x0;
   // Alignment for 32-bit integers used in LWL, LWR, etc.
   const int kInt32AlignmentMask = sizeof(uint32_t) - 1;
+  // Alignment for 64-bit integers used in LDL, LDR, etc.
+  const int kInt64AlignmentMask = sizeof(uint64_t) - 1;
 
   // Branch instructions common part.
   auto BranchAndLinkHelper = [this, instr, &next_pc,
@@ -4366,6 +4469,7 @@
       break;
     // ------------- Arithmetic instructions.
     case ADDIU: {
+      DCHECK(is_int32(rs));
       int32_t alu32_out = static_cast<int32_t>(rs + se_imm16);
       // Sign-extend result of 32bit operation into 64bit register.
       SetResult(rt_reg, static_cast<int64_t>(alu32_out));
@@ -4420,10 +4524,10 @@
       uint8_t byte_shift = kInt32AlignmentMask - al_offset;
       uint32_t mask = (1 << byte_shift * 8) - 1;
       addr = rs + se_imm16 - al_offset;
-      alu_out = ReadW(addr, instr);
-      alu_out <<= byte_shift * 8;
-      alu_out |= rt & mask;
-      set_register(rt_reg, alu_out);
+      int32_t val = ReadW(addr, instr);
+      val <<= byte_shift * 8;
+      val |= rt & mask;
+      set_register(rt_reg, static_cast<int64_t>(val));
       break;
     }
     case LW:
@@ -4453,6 +4557,30 @@
       set_register(rt_reg, alu_out);
       break;
     }
+    case LDL: {
+      // al_offset is offset of the effective address within an aligned word.
+      uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
+      uint8_t byte_shift = kInt64AlignmentMask - al_offset;
+      uint64_t mask = (1UL << byte_shift * 8) - 1;
+      addr = rs + se_imm16 - al_offset;
+      alu_out = Read2W(addr, instr);
+      alu_out <<= byte_shift * 8;
+      alu_out |= rt & mask;
+      set_register(rt_reg, alu_out);
+      break;
+    }
+    case LDR: {
+      // al_offset is offset of the effective address within an aligned word.
+      uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
+      uint8_t byte_shift = kInt64AlignmentMask - al_offset;
+      uint64_t mask = al_offset ? (~0UL << (byte_shift + 1) * 8) : 0UL;
+      addr = rs + se_imm16 - al_offset;
+      alu_out = Read2W(addr, instr);
+      alu_out = alu_out >> al_offset * 8;
+      alu_out |= rt & mask;
+      set_register(rt_reg, alu_out);
+      break;
+    }
     case SB:
       WriteB(rs + se_imm16, static_cast<int8_t>(rt));
       break;
@@ -4484,6 +4612,25 @@
       WriteW(addr, static_cast<int32_t>(mem_value), instr);
       break;
     }
+    case SDL: {
+      uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
+      uint8_t byte_shift = kInt64AlignmentMask - al_offset;
+      uint64_t mask = byte_shift ? (~0UL << (al_offset + 1) * 8) : 0;
+      addr = rs + se_imm16 - al_offset;
+      uint64_t mem_value = Read2W(addr, instr) & mask;
+      mem_value |= rt >> byte_shift * 8;
+      Write2W(addr, mem_value, instr);
+      break;
+    }
+    case SDR: {
+      uint8_t al_offset = (rs + se_imm16) & kInt64AlignmentMask;
+      uint64_t mask = (1UL << al_offset * 8) - 1;
+      addr = rs + se_imm16 - al_offset;
+      uint64_t mem_value = Read2W(addr, instr);
+      mem_value = (rt << al_offset * 8) | (mem_value & mask);
+      Write2W(addr, mem_value, instr);
+      break;
+    }
     case LWC1:
       set_fpu_register(ft_reg, kFPUInvalidResult);  // Trash upper 32 bits.
       set_fpu_register_word(ft_reg, ReadW(rs + se_imm16, instr));
@@ -4642,8 +4789,9 @@
   }
 
   if (::v8::internal::FLAG_trace_sim) {
-    PrintF("  0x%08lx  %-44s   %s\n", reinterpret_cast<intptr_t>(instr),
-        buffer.start(), trace_buf_.start());
+    PrintF("  0x%08" PRIxPTR "   %-44s   %s\n",
+           reinterpret_cast<intptr_t>(instr), buffer.start(),
+           trace_buf_.start());
   }
 
   if (!pc_modified_) {
diff --git a/src/mips64/simulator-mips64.h b/src/mips64/simulator-mips64.h
index 7f60a74..cd606e2 100644
--- a/src/mips64/simulator-mips64.h
+++ b/src/mips64/simulator-mips64.h
@@ -84,7 +84,7 @@
 // Running with a simulator.
 
 #include "src/assembler.h"
-#include "src/hashmap.h"
+#include "src/base/hashmap.h"
 
 namespace v8 {
 namespace internal {
@@ -226,7 +226,7 @@
   // Call on program start.
   static void Initialize(Isolate* isolate);
 
-  static void TearDown(HashMap* i_cache, Redirection* first);
+  static void TearDown(base::HashMap* i_cache, Redirection* first);
 
   // V8 generally calls into generated JS code with 5 parameters and into
   // generated RegExp code with 7 parameters. This is a convenience function,
@@ -246,8 +246,7 @@
   char* last_debugger_input() { return last_debugger_input_; }
 
   // ICache checking.
-  static void FlushICache(v8::internal::HashMap* i_cache, void* start,
-                          size_t size);
+  static void FlushICache(base::HashMap* i_cache, void* start, size_t size);
 
   // Returns true if pc register contains one of the 'special_values' defined
   // below (bad_ra, end_sim_pc).
@@ -415,10 +414,9 @@
   }
 
   // ICache.
-  static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr);
-  static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
-                           size_t size);
-  static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);
+  static void CheckICache(base::HashMap* i_cache, Instruction* instr);
+  static void FlushOnePage(base::HashMap* i_cache, intptr_t start, size_t size);
+  static CachePage* GetCachePage(base::HashMap* i_cache, void* page);
 
   enum Exception {
     none,
@@ -463,7 +461,7 @@
   char* last_debugger_input_;
 
   // Icache simulation.
-  v8::internal::HashMap* i_cache_;
+  base::HashMap* i_cache_;
 
   v8::internal::Isolate* isolate_;
 
diff --git a/src/objects-body-descriptors-inl.h b/src/objects-body-descriptors-inl.h
index bfc1895..cfa945d 100644
--- a/src/objects-body-descriptors-inl.h
+++ b/src/objects-body-descriptors-inl.h
@@ -456,6 +456,8 @@
     case TRANSITION_ARRAY_TYPE:
       return Op::template apply<TransitionArray::BodyDescriptor>(p1, p2, p3);
     case JS_OBJECT_TYPE:
+    case JS_ERROR_TYPE:
+    case JS_ARGUMENTS_TYPE:
     case JS_PROMISE_TYPE:
     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
     case JS_GENERATOR_OBJECT_TYPE:
@@ -472,6 +474,7 @@
     case JS_REGEXP_TYPE:
     case JS_GLOBAL_PROXY_TYPE:
     case JS_GLOBAL_OBJECT_TYPE:
+    case JS_API_OBJECT_TYPE:
     case JS_SPECIAL_API_OBJECT_TYPE:
     case JS_MESSAGE_OBJECT_TYPE:
     case JS_BOUND_FUNCTION_TYPE:
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index b023b03..d3d13d4 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -99,6 +99,9 @@
       Oddball::cast(this)->OddballVerify();
       break;
     case JS_OBJECT_TYPE:
+    case JS_ERROR_TYPE:
+    case JS_ARGUMENTS_TYPE:
+    case JS_API_OBJECT_TYPE:
     case JS_SPECIAL_API_OBJECT_TYPE:
     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
     case JS_PROMISE_TYPE:
@@ -209,8 +212,8 @@
 void Symbol::SymbolVerify() {
   CHECK(IsSymbol());
   CHECK(HasHashCode());
-  CHECK(GetHeap()->hidden_properties_symbol() == this || Hash() > 0u);
-  CHECK(name()->IsUndefined() || name()->IsString());
+  CHECK(Hash() > 0u);
+  CHECK(name()->IsUndefined(GetIsolate()) || name()->IsString());
 }
 
 
@@ -288,6 +291,7 @@
                actual_unused_property_fields - JSObject::kFieldsAdded);
     }
     DescriptorArray* descriptors = map()->instance_descriptors();
+    Isolate* isolate = GetIsolate();
     for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) {
       if (descriptors->GetDetails(i).type() == DATA) {
         Representation r = descriptors->GetDetails(i).representation();
@@ -298,7 +302,7 @@
         }
         Object* value = RawFastPropertyAt(index);
         if (r.IsDouble()) DCHECK(value->IsMutableHeapNumber());
-        if (value->IsUninitialized()) continue;
+        if (value->IsUninitialized(isolate)) continue;
         if (r.IsSmi()) DCHECK(value->IsSmi());
         if (r.IsHeapObject()) DCHECK(value->IsHeapObject());
         FieldType* field_type = descriptors->GetFieldType(i);
@@ -311,7 +315,7 @@
           // object literal creation and we will end up having and undefined
           // value that does not match the field type.
           CHECK(!field_type->NowStable() || field_type->NowContains(value) ||
-                (!FLAG_use_allocation_folding && value->IsUndefined()));
+                (!FLAG_use_allocation_folding && value->IsUndefined(isolate)));
         }
       }
     }
@@ -337,7 +341,7 @@
   CHECK(instance_size() == kVariableSizeSentinel ||
          (kPointerSize <= instance_size() &&
           instance_size() < heap->Capacity()));
-  CHECK(GetBackPointer()->IsUndefined() ||
+  CHECK(GetBackPointer()->IsUndefined(heap->isolate()) ||
         !Map::cast(GetBackPointer())->is_stable());
   VerifyHeapPointer(prototype());
   VerifyHeapPointer(instance_descriptors());
@@ -369,21 +373,6 @@
 }
 
 
-void CodeCache::CodeCacheVerify() {
-  VerifyHeapPointer(default_cache());
-  VerifyHeapPointer(normal_type_cache());
-  CHECK(default_cache()->IsFixedArray());
-  CHECK(normal_type_cache()->IsUndefined()
-         || normal_type_cache()->IsCodeCacheHashTable());
-}
-
-
-void PolymorphicCodeCache::PolymorphicCodeCacheVerify() {
-  VerifyHeapPointer(cache());
-  CHECK(cache()->IsUndefined() || cache()->IsPolymorphicCodeCacheHashTable());
-}
-
-
 void TypeFeedbackInfo::TypeFeedbackInfoVerify() {
   VerifyObjectField(kStorage1Offset);
   VerifyObjectField(kStorage2Offset);
@@ -426,7 +415,7 @@
     VerifyPointer(e);
   }
   CHECK_LE(LengthFor(number_of_transitions()), length());
-  CHECK(next_link()->IsUndefined() || next_link()->IsSmi() ||
+  CHECK(next_link()->IsUndefined(GetIsolate()) || next_link()->IsSmi() ||
         next_link()->IsTransitionArray());
 }
 
@@ -446,7 +435,7 @@
 void JSModule::JSModuleVerify() {
   VerifyObjectField(kContextOffset);
   VerifyObjectField(kScopeInfoOffset);
-  CHECK(context()->IsUndefined() ||
+  CHECK(context()->IsUndefined(GetIsolate()) ||
         Context::cast(context())->IsModuleContext());
 }
 
@@ -463,16 +452,18 @@
   if (value()->IsHeapObject()) {
     VerifyHeapPointer(value());
   }
-  CHECK(value()->IsUndefined() || value()->IsSmi() || value()->IsHeapNumber());
-  CHECK(year()->IsUndefined() || year()->IsSmi() || year()->IsNaN());
-  CHECK(month()->IsUndefined() || month()->IsSmi() || month()->IsNaN());
-  CHECK(day()->IsUndefined() || day()->IsSmi() || day()->IsNaN());
-  CHECK(weekday()->IsUndefined() || weekday()->IsSmi() || weekday()->IsNaN());
-  CHECK(hour()->IsUndefined() || hour()->IsSmi() || hour()->IsNaN());
-  CHECK(min()->IsUndefined() || min()->IsSmi() || min()->IsNaN());
-  CHECK(sec()->IsUndefined() || sec()->IsSmi() || sec()->IsNaN());
-  CHECK(cache_stamp()->IsUndefined() ||
-        cache_stamp()->IsSmi() ||
+  Isolate* isolate = GetIsolate();
+  CHECK(value()->IsUndefined(isolate) || value()->IsSmi() ||
+        value()->IsHeapNumber());
+  CHECK(year()->IsUndefined(isolate) || year()->IsSmi() || year()->IsNaN());
+  CHECK(month()->IsUndefined(isolate) || month()->IsSmi() || month()->IsNaN());
+  CHECK(day()->IsUndefined(isolate) || day()->IsSmi() || day()->IsNaN());
+  CHECK(weekday()->IsUndefined(isolate) || weekday()->IsSmi() ||
+        weekday()->IsNaN());
+  CHECK(hour()->IsUndefined(isolate) || hour()->IsSmi() || hour()->IsNaN());
+  CHECK(min()->IsUndefined(isolate) || min()->IsSmi() || min()->IsNaN());
+  CHECK(sec()->IsUndefined(isolate) || sec()->IsSmi() || sec()->IsNaN());
+  CHECK(cache_stamp()->IsUndefined(isolate) || cache_stamp()->IsSmi() ||
         cache_stamp()->IsNaN());
 
   if (month()->IsSmi()) {
@@ -501,7 +492,7 @@
   }
   if (cache_stamp()->IsSmi()) {
     CHECK(Smi::cast(cache_stamp())->value() <=
-          Smi::cast(GetIsolate()->date_cache()->stamp())->value());
+          Smi::cast(isolate->date_cache()->stamp())->value());
   }
 }
 
@@ -569,7 +560,7 @@
   VerifyObjectField(kNextFunctionLinkOffset);
   CHECK(code()->IsCode());
   CHECK(next_function_link() == NULL ||
-        next_function_link()->IsUndefined() ||
+        next_function_link()->IsUndefined(GetIsolate()) ||
         next_function_link()->IsJSFunction());
   CHECK(map()->is_callable());
 }
@@ -580,14 +571,17 @@
   VerifyObjectField(kNameOffset);
   VerifyObjectField(kCodeOffset);
   VerifyObjectField(kOptimizedCodeMapOffset);
-  VerifyObjectField(kFeedbackVectorOffset);
+  VerifyObjectField(kFeedbackMetadataOffset);
   VerifyObjectField(kScopeInfoOffset);
   VerifyObjectField(kInstanceClassNameOffset);
-  CHECK(function_data()->IsUndefined() || IsApiFunction() ||
-        HasBuiltinFunctionId() || HasBytecodeArray());
+  CHECK(function_data()->IsUndefined(GetIsolate()) || IsApiFunction() ||
+        HasBytecodeArray());
   VerifyObjectField(kFunctionDataOffset);
   VerifyObjectField(kScriptOffset);
   VerifyObjectField(kDebugInfoOffset);
+  CHECK(function_identifier()->IsUndefined(GetIsolate()) ||
+        HasBuiltinFunctionId() || HasInferredName());
+  VerifyObjectField(kFunctionIdentifierOffset);
 }
 
 
@@ -623,7 +617,7 @@
     CHECK(number->IsSmi());
     int value = Smi::cast(number)->value();
     // Hidden oddballs have negative smis.
-    const int kLeastHiddenOddballNumber = -6;
+    const int kLeastHiddenOddballNumber = -7;
     CHECK_LE(value, 1);
     CHECK(value >= kLeastHiddenOddballNumber);
   }
@@ -648,6 +642,8 @@
     CHECK(this == heap->exception());
   } else if (map() == heap->optimized_out_map()) {
     CHECK(this == heap->optimized_out());
+  } else if (map() == heap->stale_register_map()) {
+    CHECK(this == heap->stale_register());
   } else {
     UNREACHABLE();
   }
@@ -720,12 +716,12 @@
 
 void JSArray::JSArrayVerify() {
   JSObjectVerify();
-  CHECK(length()->IsNumber() || length()->IsUndefined());
+  Isolate* isolate = GetIsolate();
+  CHECK(length()->IsNumber() || length()->IsUndefined(isolate));
   // If a GC was caused while constructing this array, the elements
   // pointer may point to a one pointer filler map.
   if (ElementsAreSafeToExamine()) {
-    CHECK(elements()->IsUndefined() ||
-          elements()->IsFixedArray() ||
+    CHECK(elements()->IsUndefined(isolate) || elements()->IsFixedArray() ||
           elements()->IsFixedDoubleArray());
   }
 }
@@ -735,7 +731,7 @@
   CHECK(IsJSSet());
   JSObjectVerify();
   VerifyHeapPointer(table());
-  CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
+  CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(GetIsolate()));
   // TODO(arv): Verify OrderedHashTable too.
 }
 
@@ -744,7 +740,7 @@
   CHECK(IsJSMap());
   JSObjectVerify();
   VerifyHeapPointer(table());
-  CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
+  CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(GetIsolate()));
   // TODO(arv): Verify OrderedHashTable too.
 }
 
@@ -753,9 +749,10 @@
   CHECK(IsJSSetIterator());
   JSObjectVerify();
   VerifyHeapPointer(table());
-  CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
-  CHECK(index()->IsSmi() || index()->IsUndefined());
-  CHECK(kind()->IsSmi() || kind()->IsUndefined());
+  Isolate* isolate = GetIsolate();
+  CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(isolate));
+  CHECK(index()->IsSmi() || index()->IsUndefined(isolate));
+  CHECK(kind()->IsSmi() || kind()->IsUndefined(isolate));
 }
 
 
@@ -763,9 +760,10 @@
   CHECK(IsJSMapIterator());
   JSObjectVerify();
   VerifyHeapPointer(table());
-  CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
-  CHECK(index()->IsSmi() || index()->IsUndefined());
-  CHECK(kind()->IsSmi() || kind()->IsUndefined());
+  Isolate* isolate = GetIsolate();
+  CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(isolate));
+  CHECK(index()->IsSmi() || index()->IsUndefined(isolate));
+  CHECK(kind()->IsSmi() || kind()->IsUndefined(isolate));
 }
 
 
@@ -773,7 +771,7 @@
   CHECK(IsJSWeakMap());
   JSObjectVerify();
   VerifyHeapPointer(table());
-  CHECK(table()->IsHashTable() || table()->IsUndefined());
+  CHECK(table()->IsHashTable() || table()->IsUndefined(GetIsolate()));
 }
 
 
@@ -781,13 +779,14 @@
   CHECK(IsJSWeakSet());
   JSObjectVerify();
   VerifyHeapPointer(table());
-  CHECK(table()->IsHashTable() || table()->IsUndefined());
+  CHECK(table()->IsHashTable() || table()->IsUndefined(GetIsolate()));
 }
 
 
 void JSRegExp::JSRegExpVerify() {
   JSObjectVerify();
-  CHECK(data()->IsUndefined() || data()->IsFixedArray());
+  Isolate* isolate = GetIsolate();
+  CHECK(data()->IsUndefined(isolate) || data()->IsFixedArray());
   switch (TypeTag()) {
     case JSRegExp::ATOM: {
       FixedArray* arr = FixedArray::cast(data());
@@ -823,7 +822,7 @@
     }
     default:
       CHECK_EQ(JSRegExp::NOT_COMPILED, TypeTag());
-      CHECK(data()->IsUndefined());
+      CHECK(data()->IsUndefined(isolate));
       break;
   }
 }
@@ -833,10 +832,11 @@
   CHECK(IsJSProxy());
   VerifyPointer(target());
   VerifyPointer(handler());
+  Isolate* isolate = GetIsolate();
   CHECK_EQ(target()->IsCallable(), map()->is_callable());
   CHECK_EQ(target()->IsConstructor(), map()->is_constructor());
-  CHECK(hash()->IsSmi() || hash()->IsUndefined());
-  CHECK(map()->prototype()->IsNull());
+  CHECK(hash()->IsSmi() || hash()->IsUndefined(isolate));
+  CHECK(map()->prototype()->IsNull(isolate));
   // There should be no properties on a Proxy.
   CHECK_EQ(0, map()->NumberOfOwnDescriptors());
 }
@@ -846,8 +846,8 @@
   CHECK(IsJSArrayBuffer());
   JSObjectVerify();
   VerifyPointer(byte_length());
-  CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber()
-        || byte_length()->IsUndefined());
+  CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber() ||
+        byte_length()->IsUndefined(GetIsolate()));
 }
 
 
@@ -855,16 +855,17 @@
   CHECK(IsJSArrayBufferView());
   JSObjectVerify();
   VerifyPointer(buffer());
-  CHECK(buffer()->IsJSArrayBuffer() || buffer()->IsUndefined()
-        || buffer() == Smi::FromInt(0));
+  Isolate* isolate = GetIsolate();
+  CHECK(buffer()->IsJSArrayBuffer() || buffer()->IsUndefined(isolate) ||
+        buffer() == Smi::FromInt(0));
 
   VerifyPointer(raw_byte_offset());
   CHECK(raw_byte_offset()->IsSmi() || raw_byte_offset()->IsHeapNumber() ||
-        raw_byte_offset()->IsUndefined());
+        raw_byte_offset()->IsUndefined(isolate));
 
   VerifyPointer(raw_byte_length());
   CHECK(raw_byte_length()->IsSmi() || raw_byte_length()->IsHeapNumber() ||
-        raw_byte_length()->IsUndefined());
+        raw_byte_length()->IsUndefined(isolate));
 }
 
 
@@ -873,7 +874,7 @@
   JSArrayBufferViewVerify();
   VerifyPointer(raw_length());
   CHECK(raw_length()->IsSmi() || raw_length()->IsHeapNumber() ||
-        raw_length()->IsUndefined());
+        raw_length()->IsUndefined(GetIsolate()));
 
   VerifyPointer(elements());
 }
@@ -921,6 +922,7 @@
   VerifyPointer(expected_receiver_type());
   VerifyPointer(getter());
   VerifyPointer(setter());
+  VerifyPointer(js_getter());
   VerifyPointer(data());
 }
 
@@ -934,9 +936,9 @@
 
 void AccessCheckInfo::AccessCheckInfoVerify() {
   CHECK(IsAccessCheckInfo());
-  VerifyPointer(named_callback());
-  VerifyPointer(indexed_callback());
   VerifyPointer(callback());
+  VerifyPointer(named_interceptor());
+  VerifyPointer(indexed_interceptor());
   VerifyPointer(data());
 }
 
@@ -1014,12 +1016,13 @@
 void NormalizedMapCache::NormalizedMapCacheVerify() {
   FixedArray::cast(this)->FixedArrayVerify();
   if (FLAG_enable_slow_asserts) {
+    Isolate* isolate = GetIsolate();
     for (int i = 0; i < length(); i++) {
       Object* e = FixedArray::get(i);
       if (e->IsMap()) {
         Map::cast(e)->DictionaryMapVerify();
       } else {
-        CHECK(e->IsUndefined());
+        CHECK(e->IsUndefined(isolate));
       }
     }
   }
@@ -1073,9 +1076,9 @@
       int holes = 0;
       FixedArray* e = FixedArray::cast(elements());
       int len = e->length();
-      Heap* heap = GetHeap();
+      Isolate* isolate = GetIsolate();
       for (int i = 0; i < len; i++) {
-        if (e->get(i) == heap->the_hole_value()) holes++;
+        if (e->get(i)->IsTheHole(isolate)) holes++;
       }
       info->number_of_fast_used_elements_   += len - holes;
       info->number_of_fast_unused_elements_ += holes;
diff --git a/src/objects-inl.h b/src/objects-inl.h
index f4d7fb9..e1df2b6 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -14,15 +14,18 @@
 
 #include "src/base/atomicops.h"
 #include "src/base/bits.h"
+#include "src/builtins.h"
 #include "src/contexts-inl.h"
 #include "src/conversions-inl.h"
 #include "src/factory.h"
 #include "src/field-index-inl.h"
+#include "src/field-type.h"
 #include "src/handles-inl.h"
 #include "src/heap/heap-inl.h"
 #include "src/heap/heap.h"
-#include "src/isolate.h"
 #include "src/isolate-inl.h"
+#include "src/isolate.h"
+#include "src/keys.h"
 #include "src/layout-descriptor-inl.h"
 #include "src/lookup.h"
 #include "src/objects.h"
@@ -158,6 +161,15 @@
     return IsHeapObject() && HeapObject::cast(this)->Is##type_(); \
   }
 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DEF)
+#undef IS_TYPE_FUNCTION_DEF
+
+#define IS_TYPE_FUNCTION_DEF(Type, Value)             \
+  bool Object::Is##Type(Isolate* isolate) const {     \
+    return this == isolate->heap()->Value();          \
+  }                                                   \
+  bool HeapObject::Is##Type(Isolate* isolate) const { \
+    return this == isolate->heap()->Value();          \
+  }
 ODDBALL_LIST(IS_TYPE_FUNCTION_DEF)
 #undef IS_TYPE_FUNCTION_DEF
 
@@ -243,7 +255,6 @@
          String::cast(this)->IsTwoByteRepresentation();
 }
 
-
 bool Object::HasValidElements() {
   // Dictionary is covered under FixedArray.
   return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase();
@@ -282,12 +293,12 @@
 Handle<Object> Object::NewStorageFor(Isolate* isolate,
                                      Handle<Object> object,
                                      Representation representation) {
-  if (representation.IsSmi() && object->IsUninitialized()) {
+  if (representation.IsSmi() && object->IsUninitialized(isolate)) {
     return handle(Smi::FromInt(0), isolate);
   }
   if (!representation.IsDouble()) return object;
   double value;
-  if (object->IsUninitialized()) {
+  if (object->IsUninitialized(isolate)) {
     value = 0;
   } else if (object->IsMutableHeapNumber()) {
     value = HeapNumber::cast(*object)->value();
@@ -301,7 +312,7 @@
 Handle<Object> Object::WrapForRead(Isolate* isolate,
                                    Handle<Object> object,
                                    Representation representation) {
-  DCHECK(!object->IsUninitialized());
+  DCHECK(!object->IsUninitialized(isolate));
   if (!representation.IsDouble()) {
     DCHECK(object->FitsRepresentation(representation));
     return object;
@@ -775,11 +786,13 @@
 TYPE_CHECKER(PropertyCell, PROPERTY_CELL_TYPE)
 TYPE_CHECKER(WeakCell, WEAK_CELL_TYPE)
 TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
-TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE)
-TYPE_CHECKER(JSModule, JS_MODULE_TYPE)
-TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
 TYPE_CHECKER(JSDate, JS_DATE_TYPE)
+TYPE_CHECKER(JSError, JS_ERROR_TYPE)
+TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE)
 TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
+TYPE_CHECKER(JSModule, JS_MODULE_TYPE)
+TYPE_CHECKER(JSPromise, JS_PROMISE_TYPE)
+TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
 
 bool HeapObject::IsAbstractCode() const {
   return IsBytecodeArray() || IsCode();
@@ -874,10 +887,6 @@
 
 bool HeapObject::IsCodeCacheHashTable() const { return IsHashTable(); }
 
-bool HeapObject::IsPolymorphicCodeCacheHashTable() const {
-  return IsHashTable();
-}
-
 bool HeapObject::IsMapCache() const { return IsHashTable(); }
 
 bool HeapObject::IsObjectHashTable() const { return IsHashTable(); }
@@ -940,13 +949,6 @@
 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
 #undef MAKE_STRUCT_PREDICATE
 
-#define MAKE_ODDBALL_PREDICATE(Name)                                       \
-  bool HeapObject::Is##Name() const {                                      \
-    return IsOddball() && Oddball::cast(this)->kind() == Oddball::k##Name; \
-  }
-ODDBALL_LIST(MAKE_ODDBALL_PREDICATE)
-
-#undef MAKE_ODDBALL_PREDICATE
 double Object::Number() const {
   DCHECK(IsNumber());
   return IsSmi()
@@ -972,7 +974,8 @@
     return Representation::Smi();
   } else if (FLAG_track_double_fields && IsHeapNumber()) {
     return Representation::Double();
-  } else if (FLAG_track_computed_fields && IsUninitialized()) {
+  } else if (FLAG_track_computed_fields &&
+             IsUninitialized(HeapObject::cast(this)->GetIsolate())) {
     return Representation::None();
   } else if (FLAG_track_heap_object_fields) {
     DCHECK(IsHeapObject());
@@ -1098,8 +1101,7 @@
                                              Handle<JSReceiver> receiver) {
   // We don't expect access checks to be needed on JSProxy objects.
   DCHECK(!receiver->IsAccessCheckNeeded() || receiver->IsJSObject());
-  PrototypeIterator iter(isolate, receiver,
-                         PrototypeIterator::START_AT_RECEIVER,
+  PrototypeIterator iter(isolate, receiver, kStartAtReceiver,
                          PrototypeIterator::END_AT_NON_HIDDEN);
   do {
     if (!iter.AdvanceFollowingProxies()) return MaybeHandle<Object>();
@@ -1114,6 +1116,13 @@
   return GetProperty(receiver, str);
 }
 
+// static
+MUST_USE_RESULT MaybeHandle<FixedArray> JSReceiver::OwnPropertyKeys(
+    Handle<JSReceiver> object) {
+  return KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
+                                 ALL_PROPERTIES,
+                                 GetKeysConversion::kConvertToString);
+}
 
 #define FIELD_ADDR(p, offset) \
   (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
@@ -1150,6 +1159,12 @@
       object, HeapObject::RawField(object, offset), value); \
   heap->RecordWrite(object, offset, value);
 
+#define FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(heap, array, start, length) \
+  do {                                                                 \
+    heap->RecordFixedArrayElements(array, start, length);              \
+    heap->incremental_marking()->IterateBlackObject(array);            \
+  } while (false)
+
 #define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode) \
   if (mode != SKIP_WRITE_BARRIER) {                                  \
     if (mode == UPDATE_WRITE_BARRIER) {                              \
@@ -1260,8 +1275,7 @@
   return reinterpret_cast<Map*>(value_);
 }
 
-
-bool MapWord::IsForwardingAddress() {
+bool MapWord::IsForwardingAddress() const {
   return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
 }
 
@@ -1740,7 +1754,7 @@
     PrintIsolate(GetIsolate(),
                  "pretenuring: AllocationSite(%p): (created, found, ratio) "
                  "(%d, %d, %f) %s => %s\n",
-                 this, create_count, found_count, ratio,
+                 static_cast<void*>(this), create_count, found_count, ratio,
                  PretenureDecisionName(current_decision),
                  PretenureDecisionName(pretenure_decision()));
   }
@@ -1784,15 +1798,14 @@
                                         Object** objects,
                                         uint32_t count,
                                         EnsureElementsMode mode) {
-  ElementsKind current_kind = object->map()->elements_kind();
+  ElementsKind current_kind = object->GetElementsKind();
   ElementsKind target_kind = current_kind;
   {
     DisallowHeapAllocation no_allocation;
     DCHECK(mode != ALLOW_COPIED_DOUBLE_ELEMENTS);
     bool is_holey = IsFastHoleyElementsKind(current_kind);
     if (current_kind == FAST_HOLEY_ELEMENTS) return;
-    Heap* heap = object->GetHeap();
-    Object* the_hole = heap->the_hole_value();
+    Object* the_hole = object->GetHeap()->the_hole_value();
     for (uint32_t i = 0; i < count; ++i) {
       Object* current = *objects++;
       if (current == the_hole) {
@@ -1908,6 +1921,13 @@
       constructor->shared()->get_api_func_data()->indexed_property_handler());
 }
 
+double Oddball::to_number_raw() const {
+  return READ_DOUBLE_FIELD(this, kToNumberRawOffset);
+}
+
+void Oddball::set_to_number_raw(double value) {
+  WRITE_DOUBLE_FIELD(this, kToNumberRawOffset, value);
+}
 
 ACCESSORS(Oddball, to_string, String, kToStringOffset)
 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
@@ -1991,9 +2011,7 @@
   set_next(the_hole_value, SKIP_WRITE_BARRIER);
 }
 
-
-bool WeakCell::next_cleared() { return next()->IsTheHole(); }
-
+bool WeakCell::next_cleared() { return next()->IsTheHole(GetIsolate()); }
 
 int JSObject::GetHeaderSize() { return GetHeaderSize(map()->instance_type()); }
 
@@ -2004,6 +2022,7 @@
   // field operations considerably on average.
   if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
   switch (type) {
+    case JS_API_OBJECT_TYPE:
     case JS_SPECIAL_API_OBJECT_TYPE:
       return JSObject::kHeaderSize;
     case JS_GENERATOR_OBJECT_TYPE:
@@ -2050,6 +2069,10 @@
       return JSObject::kHeaderSize;
     case JS_MESSAGE_OBJECT_TYPE:
       return JSMessageObject::kSize;
+    case JS_ARGUMENTS_TYPE:
+      return JSArgumentsObject::kHeaderSize;
+    case JS_ERROR_TYPE:
+      return JSObject::kHeaderSize;
     default:
       UNREACHABLE();
       return 0;
@@ -2169,7 +2192,9 @@
   FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor);
   if (details.representation().IsDouble()) {
     // Nothing more to be done.
-    if (value->IsUninitialized()) return;
+    if (value->IsUninitialized(this->GetIsolate())) {
+      return;
+    }
     if (IsUnboxedDoubleField(index)) {
       RawFastDoublePropertyAtPut(index, value->Number());
     } else {
@@ -2262,9 +2287,12 @@
 
 void Object::VerifyApiCallResultType() {
 #if DEBUG
-  if (!(IsSmi() || IsString() || IsSymbol() || IsJSReceiver() ||
-        IsHeapNumber() || IsSimd128Value() || IsUndefined() || IsTrue() ||
-        IsFalse() || IsNull())) {
+  if (IsSmi()) return;
+  DCHECK(IsHeapObject());
+  Isolate* isolate = HeapObject::cast(this)->GetIsolate();
+  if (!(IsString() || IsSymbol() || IsJSReceiver() || IsHeapNumber() ||
+        IsSimd128Value() || IsUndefined(isolate) || IsTrue(isolate) ||
+        IsFalse(isolate) || IsNull(isolate))) {
     FATAL("API call returned invalid object");
   }
 #endif  // DEBUG
@@ -2447,7 +2475,7 @@
 
 
 void ArrayList::Clear(int index, Object* undefined) {
-  DCHECK(undefined->IsUndefined());
+  DCHECK(undefined->IsUndefined(GetIsolate()));
   FixedArray::cast(this)
       ->set(kFirstIndex + index, undefined, SKIP_WRITE_BARRIER);
 }
@@ -2779,20 +2807,39 @@
 
 
 FixedArrayBase* Map::GetInitialElements() {
+  FixedArrayBase* result = nullptr;
   if (has_fast_elements() || has_fast_string_wrapper_elements()) {
-    DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
-    return GetHeap()->empty_fixed_array();
+    result = GetHeap()->empty_fixed_array();
+  } else if (has_fast_sloppy_arguments_elements()) {
+    result = GetHeap()->empty_sloppy_arguments_elements();
   } else if (has_fixed_typed_array_elements()) {
-    FixedTypedArrayBase* empty_array =
-        GetHeap()->EmptyFixedTypedArrayForMap(this);
-    DCHECK(!GetHeap()->InNewSpace(empty_array));
-    return empty_array;
+    result = GetHeap()->EmptyFixedTypedArrayForMap(this);
   } else {
     UNREACHABLE();
   }
-  return NULL;
+  DCHECK(!GetHeap()->InNewSpace(result));
+  return result;
 }
 
+// static
+Handle<Map> Map::ReconfigureProperty(Handle<Map> map, int modify_index,
+                                     PropertyKind new_kind,
+                                     PropertyAttributes new_attributes,
+                                     Representation new_representation,
+                                     Handle<FieldType> new_field_type,
+                                     StoreMode store_mode) {
+  return Reconfigure(map, map->elements_kind(), modify_index, new_kind,
+                     new_attributes, new_representation, new_field_type,
+                     store_mode);
+}
+
+// static
+Handle<Map> Map::ReconfigureElementsKind(Handle<Map> map,
+                                         ElementsKind new_elements_kind) {
+  return Reconfigure(map, new_elements_kind, -1, kData, NONE,
+                     Representation::None(), FieldType::None(map->GetIsolate()),
+                     ALLOW_IN_DESCRIPTOR);
+}
 
 Object** DescriptorArray::GetKeySlot(int descriptor_number) {
   DCHECK(descriptor_number < number_of_descriptors());
@@ -2998,12 +3045,14 @@
   return Max(capacity, kMinCapacity);
 }
 
-bool HashTableBase::IsKey(Heap* heap, Object* k) {
+bool HashTableBase::IsKey(Isolate* isolate, Object* k) {
+  Heap* heap = isolate->heap();
   return k != heap->the_hole_value() && k != heap->undefined_value();
 }
 
 bool HashTableBase::IsKey(Object* k) {
-  return !k->IsTheHole() && !k->IsUndefined();
+  Isolate* isolate = this->GetIsolate();
+  return !k->IsTheHole(isolate) && !k->IsUndefined(isolate);
 }
 
 
@@ -3037,13 +3086,14 @@
   uint32_t entry = FirstProbe(hash, capacity);
   uint32_t count = 1;
   // EnsureCapacity will guarantee the hash table is never full.
+  Object* undefined = isolate->heap()->undefined_value();
+  Object* the_hole = isolate->heap()->the_hole_value();
   while (true) {
     Object* element = KeyAt(entry);
     // Empty entry. Uses raw unchecked accessors because it is called by the
     // string table during bootstrapping.
-    if (element == isolate->heap()->root(Heap::kUndefinedValueRootIndex)) break;
-    if (element != isolate->heap()->root(Heap::kTheHoleValueRootIndex) &&
-        Shape::IsMatch(key, element)) return entry;
+    if (element == undefined) break;
+    if (element != the_hole && Shape::IsMatch(key, element)) return entry;
     entry = NextProbe(entry, count++, capacity);
   }
   return kNotFound;
@@ -3149,7 +3199,6 @@
 CAST_ACCESSOR(Oddball)
 CAST_ACCESSOR(OrderedHashMap)
 CAST_ACCESSOR(OrderedHashSet)
-CAST_ACCESSOR(PolymorphicCodeCacheHashTable)
 CAST_ACCESSOR(PropertyCell)
 CAST_ACCESSOR(ScopeInfo)
 CAST_ACCESSOR(SeededNumberDictionary)
@@ -3298,11 +3347,19 @@
 
 
 TypeFeedbackVector* LiteralsArray::feedback_vector() const {
+  if (length() == 0) {
+    return TypeFeedbackVector::cast(
+        const_cast<FixedArray*>(FixedArray::cast(this)));
+  }
   return TypeFeedbackVector::cast(get(kVectorIndex));
 }
 
 
 void LiteralsArray::set_feedback_vector(TypeFeedbackVector* vector) {
+  if (length() <= kVectorIndex) {
+    DCHECK(vector->length() == 0);
+    return;
+  }
   set(kVectorIndex, vector);
 }
 
@@ -3316,6 +3373,9 @@
   set(kFirstLiteralIndex + literal_index, literal);
 }
 
+void LiteralsArray::set_literal_undefined(int literal_index) {
+  set_undefined(kFirstLiteralIndex + literal_index);
+}
 
 int LiteralsArray::literals_count() const {
   return length() - kFirstLiteralIndex;
@@ -3896,7 +3956,6 @@
 
 int ByteArray::Size() { return RoundUp(length() + kHeaderSize, kPointerSize); }
 
-
 byte ByteArray::get(int index) {
   DCHECK(index >= 0 && index < this->length());
   return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
@@ -3908,12 +3967,29 @@
   WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
 }
 
+void ByteArray::copy_in(int index, const byte* buffer, int length) {
+  DCHECK(index >= 0 && length >= 0 && index + length >= index &&
+         index + length <= this->length());
+  byte* dst_addr = FIELD_ADDR(this, kHeaderSize + index * kCharSize);
+  memcpy(dst_addr, buffer, length);
+}
+
+void ByteArray::copy_out(int index, byte* buffer, int length) {
+  DCHECK(index >= 0 && length >= 0 && index + length >= index &&
+         index + length <= this->length());
+  const byte* src_addr = FIELD_ADDR(this, kHeaderSize + index * kCharSize);
+  memcpy(buffer, src_addr, length);
+}
 
 int ByteArray::get_int(int index) {
-  DCHECK(index >= 0 && (index * kIntSize) < this->length());
+  DCHECK(index >= 0 && index < this->length() / kIntSize);
   return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
 }
 
+void ByteArray::set_int(int index, int value) {
+  DCHECK(index >= 0 && index < this->length() / kIntSize);
+  WRITE_INT_FIELD(this, kHeaderSize + index * kIntSize, value);
+}
 
 ByteArray* ByteArray::FromDataStartAddress(Address address) {
   DCHECK_TAG_ALIGNED(address);
@@ -3994,6 +4070,13 @@
 
 int BytecodeArray::BytecodeArraySize() { return SizeFor(this->length()); }
 
+int BytecodeArray::SizeIncludingMetadata() {
+  int size = BytecodeArraySize();
+  size += constant_pool()->Size();
+  size += handler_table()->Size();
+  size += source_position_table()->Size();
+  return size;
+}
 
 ACCESSORS(FixedTypedArrayBase, base_pointer, Object, kBasePointerOffset)
 
@@ -4169,7 +4252,7 @@
   } else {
     // Clamp undefined to the default value. All other types have been
     // converted to a number type further up in the call chain.
-    DCHECK(value->IsUndefined());
+    DCHECK(value->IsUndefined(GetIsolate()));
   }
   set(index, cast_value);
 }
@@ -4441,11 +4524,6 @@
 }
 
 
-void Map::set_is_observed() { set_bit_field(bit_field() | (1 << kIsObserved)); }
-
-bool Map::is_observed() { return ((1 << kIsObserved) & bit_field()) != 0; }
-
-
 void Map::set_has_named_interceptor() {
   set_bit_field(bit_field() | (1 << kHasNamedInterceptor));
 }
@@ -4491,6 +4569,10 @@
   return IsPrototypeMapBits::decode(bit_field2());
 }
 
+bool Map::should_be_fast_prototype_map() const {
+  if (!prototype_info()->IsPrototypeInfo()) return false;
+  return PrototypeInfo::cast(prototype_info())->should_be_fast_map();
+}
 
 void Map::set_elements_kind(ElementsKind elements_kind) {
   DCHECK(static_cast<int>(elements_kind) < kElementsKindCount);
@@ -4527,6 +4609,10 @@
   return IsSloppyArgumentsElements(elements_kind());
 }
 
+bool Map::has_fast_sloppy_arguments_elements() {
+  return elements_kind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS;
+}
+
 bool Map::has_fast_string_wrapper_elements() {
   return elements_kind() == FAST_STRING_WRAPPER_ELEMENTS;
 }
@@ -4624,7 +4710,9 @@
 
 
 bool Map::has_code_cache() {
-  return code_cache() != GetIsolate()->heap()->empty_fixed_array();
+  // Code caches are always fixed arrays. The empty fixed array is used as a
+  // sentinel for an absent code cache.
+  return code_cache()->length() != 0;
 }
 
 
@@ -4756,43 +4844,25 @@
   return ExtractKindFromFlags(flags());
 }
 
-
 bool Code::IsCodeStubOrIC() {
-  return kind() == STUB || kind() == HANDLER || kind() == LOAD_IC ||
-         kind() == KEYED_LOAD_IC || kind() == CALL_IC || kind() == STORE_IC ||
-         kind() == KEYED_STORE_IC || kind() == BINARY_OP_IC ||
-         kind() == COMPARE_IC || kind() == TO_BOOLEAN_IC;
+  switch (kind()) {
+    case STUB:
+    case HANDLER:
+#define CASE_KIND(kind) case kind:
+      IC_KIND_LIST(CASE_KIND)
+#undef CASE_KIND
+      return true;
+    default:
+      return false;
+  }
 }
 
-
-bool Code::IsJavaScriptCode() {
-  return kind() == FUNCTION || kind() == OPTIMIZED_FUNCTION ||
-         is_interpreter_entry_trampoline();
-}
-
-
-InlineCacheState Code::ic_state() {
-  InlineCacheState result = ExtractICStateFromFlags(flags());
-  // Only allow uninitialized or debugger states for non-IC code
-  // objects. This is used in the debugger to determine whether or not
-  // a call to code object has been replaced with a debug break call.
-  DCHECK(is_inline_cache_stub() ||
-         result == UNINITIALIZED ||
-         result == DEBUG_STUB);
-  return result;
-}
-
-
 ExtraICState Code::extra_ic_state() {
-  DCHECK(is_inline_cache_stub() || ic_state() == DEBUG_STUB);
+  DCHECK(is_inline_cache_stub() || is_debug_stub());
   return ExtractExtraICStateFromFlags(flags());
 }
 
 
-Code::StubType Code::type() {
-  return ExtractTypeFromFlags(flags());
-}
-
 // For initialization.
 void Code::set_raw_kind_specific_flags1(int value) {
   WRITE_INT_FIELD(this, kKindSpecificFlags1Offset, value);
@@ -4814,18 +4884,21 @@
   return is_crankshafted() && kind() != OPTIMIZED_FUNCTION;
 }
 
-
-inline bool Code::is_interpreter_entry_trampoline() {
-  Handle<Code> interpreter_entry =
-      GetIsolate()->builtins()->InterpreterEntryTrampoline();
-  return interpreter_entry.location() != nullptr && *interpreter_entry == this;
+inline bool Code::is_interpreter_trampoline_builtin() {
+  Builtins* builtins = GetIsolate()->builtins();
+  return this == *builtins->InterpreterEntryTrampoline() ||
+         this == *builtins->InterpreterEnterBytecodeDispatch() ||
+         this == *builtins->InterpreterMarkBaselineOnReturn();
 }
 
-inline bool Code::is_interpreter_enter_bytecode_dispatch() {
-  Handle<Code> interpreter_handler =
-      GetIsolate()->builtins()->InterpreterEnterBytecodeDispatch();
-  return interpreter_handler.location() != nullptr &&
-         *interpreter_handler == this;
+inline bool Code::has_unwinding_info() const {
+  return HasUnwindingInfoField::decode(READ_UINT32_FIELD(this, kFlagsOffset));
+}
+
+inline void Code::set_has_unwinding_info(bool state) {
+  uint32_t previous = READ_UINT32_FIELD(this, kFlagsOffset);
+  uint32_t updated_value = HasUnwindingInfoField::update(previous, state);
+  WRITE_UINT32_FIELD(this, kFlagsOffset, updated_value);
 }
 
 inline void Code::set_is_crankshafted(bool value) {
@@ -5031,18 +5104,19 @@
   }
 }
 
-
-bool Code::is_keyed_stub() {
-  return is_keyed_load_stub() || is_keyed_store_stub();
+bool Code::is_debug_stub() {
+  if (kind() != BUILTIN) return false;
+  switch (builtin_index()) {
+#define CASE_DEBUG_BUILTIN(name, kind, extra) case Builtins::k##name:
+    BUILTIN_LIST_DEBUG_A(CASE_DEBUG_BUILTIN)
+#undef CASE_DEBUG_BUILTIN
+      return true;
+    default:
+      return false;
+  }
+  return false;
 }
-
-
-bool Code::is_debug_stub() { return ic_state() == DEBUG_STUB; }
 bool Code::is_handler() { return kind() == HANDLER; }
-bool Code::is_load_stub() { return kind() == LOAD_IC; }
-bool Code::is_keyed_load_stub() { return kind() == KEYED_LOAD_IC; }
-bool Code::is_store_stub() { return kind() == STORE_IC; }
-bool Code::is_keyed_store_stub() { return kind() == KEYED_STORE_IC; }
 bool Code::is_call_stub() { return kind() == CALL_IC; }
 bool Code::is_binary_op_stub() { return kind() == BINARY_OP_IC; }
 bool Code::is_compare_ic_stub() { return kind() == COMPARE_IC; }
@@ -5050,14 +5124,6 @@
 bool Code::is_optimized_code() { return kind() == OPTIMIZED_FUNCTION; }
 bool Code::is_wasm_code() { return kind() == WASM_FUNCTION; }
 
-bool Code::embeds_maps_weakly() {
-  Kind k = kind();
-  return (k == LOAD_IC || k == STORE_IC || k == KEYED_LOAD_IC ||
-          k == KEYED_STORE_IC) &&
-         ic_state() == MONOMORPHIC;
-}
-
-
 Address Code::constant_pool() {
   Address constant_pool = NULL;
   if (FLAG_enable_embedded_constant_pool) {
@@ -5069,28 +5135,20 @@
   return constant_pool;
 }
 
-Code::Flags Code::ComputeFlags(Kind kind, InlineCacheState ic_state,
-                               ExtraICState extra_ic_state, StubType type,
+Code::Flags Code::ComputeFlags(Kind kind, ExtraICState extra_ic_state,
                                CacheHolderFlag holder) {
+  // TODO(ishell): remove ICStateField.
   // Compute the bit mask.
-  unsigned int bits = KindField::encode(kind) | ICStateField::encode(ic_state) |
-                      TypeField::encode(type) |
+  unsigned int bits = KindField::encode(kind) |
+                      ICStateField::encode(MONOMORPHIC) |
                       ExtraICStateField::encode(extra_ic_state) |
                       CacheHolderField::encode(holder);
   return static_cast<Flags>(bits);
 }
 
-Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
-                                          ExtraICState extra_ic_state,
-                                          CacheHolderFlag holder,
-                                          StubType type) {
-  return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, holder);
-}
-
-
-Code::Flags Code::ComputeHandlerFlags(Kind handler_kind, StubType type,
+Code::Flags Code::ComputeHandlerFlags(Kind handler_kind,
                                       CacheHolderFlag holder) {
-  return ComputeFlags(Code::HANDLER, MONOMORPHIC, handler_kind, type, holder);
+  return ComputeFlags(Code::HANDLER, handler_kind, holder);
 }
 
 
@@ -5099,33 +5157,17 @@
 }
 
 
-InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
-  return ICStateField::decode(flags);
-}
-
-
 ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
   return ExtraICStateField::decode(flags);
 }
 
 
-Code::StubType Code::ExtractTypeFromFlags(Flags flags) {
-  return TypeField::decode(flags);
-}
-
 CacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
   return CacheHolderField::decode(flags);
 }
 
-
-Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
-  int bits = flags & ~TypeField::kMask;
-  return static_cast<Flags>(bits);
-}
-
-
-Code::Flags Code::RemoveTypeAndHolderFromFlags(Flags flags) {
-  int bits = flags & ~TypeField::kMask & ~CacheHolderField::kMask;
+Code::Flags Code::RemoveHolderFromFlags(Flags flags) {
+  int bits = flags & ~CacheHolderField::kMask;
   return static_cast<Flags>(bits);
 }
 
@@ -5203,6 +5245,13 @@
   }
 }
 
+int AbstractCode::SizeIncludingMetadata() {
+  if (IsCode()) {
+    return GetCode()->SizeIncludingMetadata();
+  } else {
+    return GetBytecodeArray()->SizeIncludingMetadata();
+  }
+}
 int AbstractCode::ExecutableSize() {
   if (IsCode()) {
     return GetCode()->ExecutableSize();
@@ -5254,7 +5303,7 @@
 
 
 void Map::set_prototype(Object* value, WriteBarrierMode mode) {
-  DCHECK(value->IsNull() || value->IsJSReceiver());
+  DCHECK(value->IsNull(GetIsolate()) || value->IsJSReceiver());
   WRITE_FIELD(this, kPrototypeOffset, value);
   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode);
 }
@@ -5387,14 +5436,14 @@
 
 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) {
   DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE);
-  DCHECK((value->IsMap() && GetBackPointer()->IsUndefined()));
+  DCHECK(value->IsMap());
+  DCHECK(GetBackPointer()->IsUndefined(GetIsolate()));
   DCHECK(!value->IsMap() ||
          Map::cast(value)->GetConstructor() == constructor_or_backpointer());
   set_constructor_or_backpointer(value, mode);
 }
 
-
-ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
+ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
 ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset)
 ACCESSORS(Map, weak_cell_cache, Object, kWeakCellCacheOffset)
 ACCESSORS(Map, constructor_or_backpointer, Object,
@@ -5425,8 +5474,6 @@
 }
 
 
-ACCESSORS(JSBoundFunction, length, Object, kLengthOffset)
-ACCESSORS(JSBoundFunction, name, Object, kNameOffset)
 ACCESSORS(JSBoundFunction, bound_target_function, JSReceiver,
           kBoundTargetFunctionOffset)
 ACCESSORS(JSBoundFunction, bound_this, Object, kBoundThisOffset)
@@ -5449,13 +5496,37 @@
 
 ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
 ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
+ACCESSORS(AccessorInfo, js_getter, Object, kJsGetterOffset)
 ACCESSORS(AccessorInfo, data, Object, kDataOffset)
 
 ACCESSORS(Box, value, Object, kValueOffset)
 
+Map* PrototypeInfo::ObjectCreateMap() {
+  return Map::cast(WeakCell::cast(object_create_map())->value());
+}
+
+// static
+void PrototypeInfo::SetObjectCreateMap(Handle<PrototypeInfo> info,
+                                       Handle<Map> map) {
+  Handle<WeakCell> cell = Map::WeakCellForMap(map);
+  info->set_object_create_map(*cell);
+}
+
+bool PrototypeInfo::HasObjectCreateMap() {
+  Object* cache = object_create_map();
+  return cache->IsWeakCell() && !WeakCell::cast(cache)->cleared();
+}
+
+bool FunctionTemplateInfo::instantiated() {
+  return shared_function_info()->IsSharedFunctionInfo();
+}
+
 ACCESSORS(PrototypeInfo, prototype_users, Object, kPrototypeUsersOffset)
+ACCESSORS(PrototypeInfo, object_create_map, Object, kObjectCreateMap)
 SMI_ACCESSORS(PrototypeInfo, registry_slot, kRegistrySlotOffset)
 ACCESSORS(PrototypeInfo, validity_cell, Object, kValidityCellOffset)
+SMI_ACCESSORS(PrototypeInfo, bit_field, kBitFieldOffset)
+BOOL_ACCESSORS(PrototypeInfo, bit_field, should_be_fast_map, kShouldBeFastBit)
 
 ACCESSORS(SloppyBlockWithEvalContextExtension, scope_info, ScopeInfo,
           kScopeInfoOffset)
@@ -5465,9 +5536,10 @@
 ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
 ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
 
-ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
-ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
 ACCESSORS(AccessCheckInfo, callback, Object, kCallbackOffset)
+ACCESSORS(AccessCheckInfo, named_interceptor, Object, kNamedInterceptorOffset)
+ACCESSORS(AccessCheckInfo, indexed_interceptor, Object,
+          kIndexedInterceptorOffset)
 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
 
 ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
@@ -5508,6 +5580,9 @@
           kInstanceCallHandlerOffset)
 ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
           kAccessCheckInfoOffset)
+ACCESSORS(FunctionTemplateInfo, shared_function_info, Object,
+          kSharedFunctionInfoOffset)
+
 SMI_ACCESSORS(FunctionTemplateInfo, flag, kFlagOffset)
 
 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
@@ -5534,8 +5609,7 @@
 SMI_ACCESSORS(Script, type, kTypeOffset)
 ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
 ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
-SMI_ACCESSORS(Script, eval_from_instructions_offset,
-              kEvalFrominstructionsOffsetOffset)
+SMI_ACCESSORS(Script, eval_from_position, kEvalFromPositionOffset)
 ACCESSORS(Script, shared_function_infos, Object, kSharedFunctionInfosOffset)
 SMI_ACCESSORS(Script, flags, kFlagsOffset)
 ACCESSORS(Script, source_url, Object, kSourceUrlOffset)
@@ -5589,8 +5663,8 @@
 ACCESSORS(SharedFunctionInfo, optimized_code_map, FixedArray,
           kOptimizedCodeMapOffset)
 ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
-ACCESSORS(SharedFunctionInfo, feedback_vector, TypeFeedbackVector,
-          kFeedbackVectorOffset)
+ACCESSORS(SharedFunctionInfo, feedback_metadata, TypeFeedbackMetadata,
+          kFeedbackMetadataOffset)
 #if TRACE_MAPS
 SMI_ACCESSORS(SharedFunctionInfo, unique_id, kUniqueIdOffset)
 #endif
@@ -5614,7 +5688,6 @@
                kRemovePrototypeBit)
 BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache,
                kDoNotCacheBit)
-BOOL_ACCESSORS(FunctionTemplateInfo, flag, instantiated, kInstantiatedBit)
 BOOL_ACCESSORS(FunctionTemplateInfo, flag, accept_any_receiver,
                kAcceptAnyReceiver)
 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_named_expression,
@@ -5778,7 +5851,6 @@
   set_compiler_hints(hints);
 }
 
-
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, needs_home_object,
                kNeedsHomeObject)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
@@ -5794,6 +5866,7 @@
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_flush, kDontFlush)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_arrow, kIsArrow)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_generator, kIsGenerator)
+BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_async, kIsAsyncFunction)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_concise_method,
                kIsConciseMethod)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_getter_function,
@@ -5803,10 +5876,9 @@
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_default_constructor,
                kIsDefaultConstructor)
 
-ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
-ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
-
-ACCESSORS(PolymorphicCodeCache, cache, Object, kCacheOffset)
+inline bool SharedFunctionInfo::is_resumable() const {
+  return is_generator() || is_async();
+}
 
 bool Script::HasValidSource() {
   Object* src = this->source();
@@ -5890,6 +5962,7 @@
   Builtins* builtins = GetIsolate()->builtins();
   DCHECK(code() != builtins->builtin(Builtins::kCompileOptimizedConcurrent));
   DCHECK(code() != builtins->builtin(Builtins::kCompileOptimized));
+  DCHECK(code() != builtins->builtin(Builtins::kCompileBaseline));
   return code() != builtins->builtin(Builtins::kCompileLazy);
 }
 
@@ -5929,7 +6002,7 @@
 }
 
 void SharedFunctionInfo::set_api_func_data(FunctionTemplateInfo* data) {
-  DCHECK(function_data()->IsUndefined());
+  DCHECK(function_data()->IsUndefined(GetIsolate()));
   set_function_data(data);
 }
 
@@ -5937,19 +6010,18 @@
   return function_data()->IsBytecodeArray();
 }
 
-
 BytecodeArray* SharedFunctionInfo::bytecode_array() {
   DCHECK(HasBytecodeArray());
   return BytecodeArray::cast(function_data());
 }
 
 void SharedFunctionInfo::set_bytecode_array(BytecodeArray* bytecode) {
-  DCHECK(function_data()->IsUndefined());
+  DCHECK(function_data()->IsUndefined(GetIsolate()));
   set_function_data(bytecode);
 }
 
 void SharedFunctionInfo::ClearBytecodeArray() {
-  DCHECK(function_data()->IsUndefined() || HasBytecodeArray());
+  DCHECK(function_data()->IsUndefined(GetIsolate()) || HasBytecodeArray());
   set_function_data(GetHeap()->undefined_value());
 }
 
@@ -5975,12 +6047,13 @@
   if (HasInferredName()) {
     return String::cast(function_identifier());
   }
-  DCHECK(function_identifier()->IsUndefined() || HasBuiltinFunctionId());
-  return GetIsolate()->heap()->empty_string();
+  Isolate* isolate = GetIsolate();
+  DCHECK(function_identifier()->IsUndefined(isolate) || HasBuiltinFunctionId());
+  return isolate->heap()->empty_string();
 }
 
 void SharedFunctionInfo::set_inferred_name(String* inferred_name) {
-  DCHECK(function_identifier()->IsUndefined() || HasInferredName());
+  DCHECK(function_identifier()->IsUndefined(GetIsolate()) || HasInferredName());
   set_function_identifier(inferred_name);
 }
 
@@ -6066,7 +6139,7 @@
 
 bool SharedFunctionInfo::IsBuiltin() {
   Object* script_obj = script();
-  if (script_obj->IsUndefined()) return true;
+  if (script_obj->IsUndefined(GetIsolate())) return true;
   Script* script = Script::cast(script_obj);
   Script::Type type = static_cast<Script::Type>(script->type());
   return type != Script::TYPE_NORMAL;
@@ -6085,6 +6158,10 @@
   return code()->kind() == Code::OPTIMIZED_FUNCTION;
 }
 
+bool JSFunction::IsMarkedForBaseline() {
+  return code() ==
+         GetIsolate()->builtins()->builtin(Builtins::kCompileBaseline);
+}
 
 bool JSFunction::IsMarkedForOptimization() {
   return code() == GetIsolate()->builtins()->builtin(
@@ -6127,7 +6204,7 @@
 
 AbstractCode* JSFunction::abstract_code() {
   Code* code = this->code();
-  if (code->is_interpreter_entry_trampoline()) {
+  if (code->is_interpreter_trampoline_builtin()) {
     return AbstractCode::cast(shared()->bytecode_array());
   } else {
     return AbstractCode::cast(code);
@@ -6195,7 +6272,7 @@
 
 
 void JSFunction::set_context(Object* value) {
-  DCHECK(value->IsUndefined() || value->IsContext());
+  DCHECK(value->IsUndefined(GetIsolate()) || value->IsContext());
   WRITE_FIELD(this, kContextOffset, value);
   WRITE_BARRIER(GetHeap(), this, kContextOffset, value);
 }
@@ -6215,7 +6292,8 @@
 
 
 bool JSFunction::has_instance_prototype() {
-  return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
+  return has_initial_map() ||
+         !prototype_or_initial_map()->IsTheHole(GetIsolate());
 }
 
 
@@ -6250,16 +6328,16 @@
 bool JSFunction::is_compiled() {
   Builtins* builtins = GetIsolate()->builtins();
   return code() != builtins->builtin(Builtins::kCompileLazy) &&
+         code() != builtins->builtin(Builtins::kCompileBaseline) &&
          code() != builtins->builtin(Builtins::kCompileOptimized) &&
          code() != builtins->builtin(Builtins::kCompileOptimizedConcurrent);
 }
 
-
-int JSFunction::NumberOfLiterals() {
-  return literals()->length();
+TypeFeedbackVector* JSFunction::feedback_vector() {
+  LiteralsArray* array = literals();
+  return array->feedback_vector();
 }
 
-
 ACCESSORS(JSProxy, target, JSReceiver, kTargetOffset)
 ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
 ACCESSORS(JSProxy, hash, Object, kHashOffset)
@@ -6305,21 +6383,22 @@
 ACCESSORS(JSGeneratorObject, function, JSFunction, kFunctionOffset)
 ACCESSORS(JSGeneratorObject, context, Context, kContextOffset)
 ACCESSORS(JSGeneratorObject, receiver, Object, kReceiverOffset)
-ACCESSORS(JSGeneratorObject, input, Object, kInputOffset)
+ACCESSORS(JSGeneratorObject, input_or_debug_pos, Object, kInputOrDebugPosOffset)
+SMI_ACCESSORS(JSGeneratorObject, resume_mode, kResumeModeOffset)
 SMI_ACCESSORS(JSGeneratorObject, continuation, kContinuationOffset)
 ACCESSORS(JSGeneratorObject, operand_stack, FixedArray, kOperandStackOffset)
 
-bool JSGeneratorObject::is_suspended() {
-  DCHECK_LT(kGeneratorExecuting, kGeneratorClosed);
-  DCHECK_EQ(kGeneratorClosed, 0);
-  return continuation() > 0;
+bool JSGeneratorObject::is_suspended() const {
+  DCHECK_LT(kGeneratorExecuting, 0);
+  DCHECK_LT(kGeneratorClosed, 0);
+  return continuation() >= 0;
 }
 
-bool JSGeneratorObject::is_closed() {
+bool JSGeneratorObject::is_closed() const {
   return continuation() == kGeneratorClosed;
 }
 
-bool JSGeneratorObject::is_executing() {
+bool JSGeneratorObject::is_executing() const {
   return continuation() == kGeneratorExecuting;
 }
 
@@ -6370,7 +6449,6 @@
 ACCESSORS(Code, raw_type_feedback_info, Object, kTypeFeedbackInfoOffset)
 ACCESSORS(Code, next_code_link, Object, kNextCodeLinkOffset)
 
-
 void Code::WipeOutHeader() {
   WRITE_FIELD(this, kRelocationInfoOffset, NULL);
   WRITE_FIELD(this, kHandlerTableOffset, NULL);
@@ -6424,11 +6502,47 @@
   return instruction_start() + instruction_size();
 }
 
-
-int Code::body_size() {
-  return RoundUp(instruction_size(), kObjectAlignment);
+int Code::GetUnwindingInfoSizeOffset() const {
+  DCHECK(has_unwinding_info());
+  return RoundUp(kHeaderSize + instruction_size(), kInt64Size);
 }
 
+int Code::unwinding_info_size() const {
+  DCHECK(has_unwinding_info());
+  return static_cast<int>(
+      READ_UINT64_FIELD(this, GetUnwindingInfoSizeOffset()));
+}
+
+void Code::set_unwinding_info_size(int value) {
+  DCHECK(has_unwinding_info());
+  WRITE_UINT64_FIELD(this, GetUnwindingInfoSizeOffset(), value);
+}
+
+byte* Code::unwinding_info_start() {
+  DCHECK(has_unwinding_info());
+  return FIELD_ADDR(this, GetUnwindingInfoSizeOffset()) + kInt64Size;
+}
+
+byte* Code::unwinding_info_end() {
+  DCHECK(has_unwinding_info());
+  return unwinding_info_start() + unwinding_info_size();
+}
+
+int Code::body_size() {
+  int unpadded_body_size =
+      has_unwinding_info()
+          ? static_cast<int>(unwinding_info_end() - instruction_start())
+          : instruction_size();
+  return RoundUp(unpadded_body_size, kObjectAlignment);
+}
+
+int Code::SizeIncludingMetadata() {
+  int size = CodeSize();
+  size += relocation_info()->Size();
+  size += deoptimization_data()->Size();
+  size += handler_table()->Size();
+  return size;
+}
 
 ByteArray* Code::unchecked_relocation_info() {
   return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
@@ -6603,7 +6717,7 @@
 
 JSRegExp::Type JSRegExp::TypeTag() {
   Object* data = this->data();
-  if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
+  if (data->IsUndefined(GetIsolate())) return JSRegExp::NOT_COMPILED;
   Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
   return static_cast<JSRegExp::Type>(smi->value());
 }
@@ -6661,16 +6775,18 @@
   // pointer may point to a one pointer filler map.
   if (ElementsAreSafeToExamine()) {
     Map* map = fixed_array->map();
-    DCHECK((IsFastSmiOrObjectElementsKind(kind) &&
-            (map == GetHeap()->fixed_array_map() ||
-             map == GetHeap()->fixed_cow_array_map())) ||
-           (IsFastDoubleElementsKind(kind) &&
-            (fixed_array->IsFixedDoubleArray() ||
-             fixed_array == GetHeap()->empty_fixed_array())) ||
-           (kind == DICTIONARY_ELEMENTS &&
-            fixed_array->IsFixedArray() &&
-            fixed_array->IsDictionary()) ||
-           (kind > DICTIONARY_ELEMENTS));
+    if (IsFastSmiOrObjectElementsKind(kind)) {
+      DCHECK(map == GetHeap()->fixed_array_map() ||
+             map == GetHeap()->fixed_cow_array_map());
+    } else if (IsFastDoubleElementsKind(kind)) {
+      DCHECK(fixed_array->IsFixedDoubleArray() ||
+             fixed_array == GetHeap()->empty_fixed_array());
+    } else if (kind == DICTIONARY_ELEMENTS) {
+      DCHECK(fixed_array->IsFixedArray());
+      DCHECK(fixed_array->IsDictionary());
+    } else {
+      DCHECK(kind > DICTIONARY_ELEMENTS);
+    }
     DCHECK(!IsSloppyArgumentsElements(kind) ||
            (elements()->IsFixedArray() && elements()->length() >= 2));
   }
@@ -7120,7 +7236,7 @@
                                        Handle<Name> name) {
   if (object->IsJSObject()) {  // Shortcut
     LookupIterator it = LookupIterator::PropertyOrElement(
-        object->GetIsolate(), object, name, object, LookupIterator::HIDDEN);
+        object->GetIsolate(), object, name, object, LookupIterator::OWN);
     return HasProperty(&it);
   }
 
@@ -7130,6 +7246,19 @@
   return Just(attributes.FromJust() != ABSENT);
 }
 
+Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object,
+                                       uint32_t index) {
+  if (object->IsJSObject()) {  // Shortcut
+    LookupIterator it(object->GetIsolate(), object, index, object,
+                      LookupIterator::OWN);
+    return HasProperty(&it);
+  }
+
+  Maybe<PropertyAttributes> attributes =
+      JSReceiver::GetOwnPropertyAttributes(object, index);
+  MAYBE_RETURN(attributes, Nothing<bool>());
+  return Just(attributes.FromJust() != ABSENT);
+}
 
 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
     Handle<JSReceiver> object, Handle<Name> name) {
@@ -7142,10 +7271,16 @@
 Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes(
     Handle<JSReceiver> object, Handle<Name> name) {
   LookupIterator it = LookupIterator::PropertyOrElement(
-      name->GetIsolate(), object, name, object, LookupIterator::HIDDEN);
+      name->GetIsolate(), object, name, object, LookupIterator::OWN);
   return GetPropertyAttributes(&it);
 }
 
+Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes(
+    Handle<JSReceiver> object, uint32_t index) {
+  LookupIterator it(object->GetIsolate(), object, index, object,
+                    LookupIterator::OWN);
+  return GetPropertyAttributes(&it);
+}
 
 Maybe<bool> JSReceiver::HasElement(Handle<JSReceiver> object, uint32_t index) {
   LookupIterator it(object->GetIsolate(), object, index, object);
@@ -7164,7 +7299,7 @@
 Maybe<PropertyAttributes> JSReceiver::GetOwnElementAttributes(
     Handle<JSReceiver> object, uint32_t index) {
   Isolate* isolate = object->GetIsolate();
-  LookupIterator it(isolate, object, index, object, LookupIterator::HIDDEN);
+  LookupIterator it(isolate, object, index, object, LookupIterator::OWN);
   return GetPropertyAttributes(&it);
 }
 
@@ -7180,19 +7315,20 @@
   return iter.GetCurrent() != global;
 }
 
-
-Handle<Smi> JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver> object) {
-  return object->IsJSProxy()
-      ? JSProxy::GetOrCreateIdentityHash(Handle<JSProxy>::cast(object))
-      : JSObject::GetOrCreateIdentityHash(Handle<JSObject>::cast(object));
+Smi* JSReceiver::GetOrCreateIdentityHash(Isolate* isolate,
+                                         Handle<JSReceiver> object) {
+  return object->IsJSProxy() ? JSProxy::GetOrCreateIdentityHash(
+                                   isolate, Handle<JSProxy>::cast(object))
+                             : JSObject::GetOrCreateIdentityHash(
+                                   isolate, Handle<JSObject>::cast(object));
 }
 
-Handle<Object> JSReceiver::GetIdentityHash(Isolate* isolate,
-                                           Handle<JSReceiver> receiver) {
-  return receiver->IsJSProxy() ? JSProxy::GetIdentityHash(
-                                     isolate, Handle<JSProxy>::cast(receiver))
-                               : JSObject::GetIdentityHash(
-                                     isolate, Handle<JSObject>::cast(receiver));
+Object* JSReceiver::GetIdentityHash(Isolate* isolate,
+                                    Handle<JSReceiver> receiver) {
+  return receiver->IsJSProxy()
+             ? JSProxy::GetIdentityHash(Handle<JSProxy>::cast(receiver))
+             : JSObject::GetIdentityHash(isolate,
+                                         Handle<JSObject>::cast(receiver));
 }
 
 
@@ -7240,6 +7376,9 @@
   set_flag(AttributesField::update(flag(), attributes));
 }
 
+bool FunctionTemplateInfo::IsTemplateFor(JSObject* object) {
+  return IsTemplateFor(object->map());
+}
 
 bool AccessorInfo::IsCompatibleReceiver(Object* receiver) {
   if (!HasExpectedReceiverType()) return true;
@@ -7269,8 +7408,9 @@
 
 
 void AccessorPair::SetComponents(Object* getter, Object* setter) {
-  if (!getter->IsNull()) set_getter(getter);
-  if (!setter->IsNull()) set_setter(setter);
+  Isolate* isolate = GetIsolate();
+  if (!getter->IsNull(isolate)) set_getter(getter);
+  if (!setter->IsNull(isolate)) set_setter(setter);
 }
 
 
@@ -7290,7 +7430,7 @@
 
 
 bool AccessorPair::IsJSAccessor(Object* obj) {
-  return obj->IsCallable() || obj->IsUndefined();
+  return obj->IsCallable() || obj->IsUndefined(GetIsolate());
 }
 
 
@@ -7322,9 +7462,9 @@
   int index = dict->EntryToIndex(entry);
   DisallowHeapAllocation no_gc;
   WriteBarrierMode mode = dict->GetWriteBarrierMode(no_gc);
-  dict->set(index, *key, mode);
-  dict->set(index + 1, *value, mode);
-  dict->set(index + 2, details.AsSmi());
+  dict->set(index + Dictionary::kEntryKeyIndex, *key, mode);
+  dict->set(index + Dictionary::kEntryValueIndex, *value, mode);
+  dict->set(index + Dictionary::kEntryDetailsIndex, details.AsSmi());
 }
 
 
@@ -7338,8 +7478,8 @@
   int index = dict->EntryToIndex(entry);
   DisallowHeapAllocation no_gc;
   WriteBarrierMode mode = dict->GetWriteBarrierMode(no_gc);
-  dict->set(index, *key, mode);
-  dict->set(index + 1, *value, mode);
+  dict->set(index + Dictionary::kEntryKeyIndex, *key, mode);
+  dict->set(index + Dictionary::kEntryValueIndex, *value, mode);
   PropertyCell::cast(*value)->set_property_details(details);
 }
 
@@ -7435,7 +7575,8 @@
 template <typename Dictionary>
 bool GlobalDictionaryShape::IsDeleted(Dictionary* dict, int entry) {
   DCHECK(dict->ValueAt(entry)->IsPropertyCell());
-  return PropertyCell::cast(dict->ValueAt(entry))->value()->IsTheHole();
+  Isolate* isolate = dict->GetIsolate();
+  return PropertyCell::cast(dict->ValueAt(entry))->value()->IsTheHole(isolate);
 }
 
 
@@ -7535,7 +7676,6 @@
   // Please note this function is used during marking:
   //  - MarkCompactCollector::MarkUnmarkedObject
   //  - IncrementalMarking::Step
-  DCHECK(!heap->InNewSpace(heap->empty_fixed_array()));
   WRITE_FIELD(this, kCodeCacheOffset, heap->empty_fixed_array());
 }
 
@@ -7710,7 +7850,7 @@
   TableType* table(TableType::cast(this->table()));
   int index = Smi::cast(this->index())->value();
   Object* key = table->KeyAt(index);
-  DCHECK(!key->IsTheHole());
+  DCHECK(!key->IsTheHole(table->GetIsolate()));
   return key;
 }
 
@@ -7730,7 +7870,7 @@
   OrderedHashMap* table(OrderedHashMap::cast(this->table()));
   int index = Smi::cast(this->index())->value();
   Object* value = table->ValueAt(index);
-  DCHECK(!value->IsTheHole());
+  DCHECK(!value->IsTheHole(table->GetIsolate()));
   return value;
 }
 
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 58092a4..464177b 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -33,7 +33,13 @@
 
 
 void HeapObject::PrintHeader(std::ostream& os, const char* id) {  // NOLINT
-  os << reinterpret_cast<void*>(this) << ": [" << id << "]";
+  os << reinterpret_cast<void*>(this) << ": [";
+  if (id != nullptr) {
+    os << id;
+  } else {
+    os << map()->instance_type();
+  }
+  os << "]";
 }
 
 
@@ -95,13 +101,18 @@
       os << "filler";
       break;
     case JS_OBJECT_TYPE:  // fall through
+    case JS_API_OBJECT_TYPE:
     case JS_SPECIAL_API_OBJECT_TYPE:
     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
-    case JS_ARRAY_TYPE:
     case JS_GENERATOR_OBJECT_TYPE:
     case JS_PROMISE_TYPE:
+    case JS_ARGUMENTS_TYPE:
+    case JS_ERROR_TYPE:
       JSObject::cast(this)->JSObjectPrint(os);
       break;
+    case JS_ARRAY_TYPE:
+      JSArray::cast(this)->JSArrayPrint(os);
+      break;
     case JS_REGEXP_TYPE:
       JSRegExp::cast(this)->JSRegExpPrint(os);
       break;
@@ -371,8 +382,7 @@
 
     case DICTIONARY_ELEMENTS:
     case SLOW_STRING_WRAPPER_ELEMENTS:
-      os << "\n - elements: ";
-      elements()->Print(os);
+      SeededNumberDictionary::cast(elements())->Print(os);
       break;
     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
@@ -396,31 +406,44 @@
   obj->PrintHeader(os, id);
   // Don't call GetElementsKind, its validation code can cause the printer to
   // fail when debugging.
-  os << "\n - map = " << reinterpret_cast<void*>(obj->map()) << " ["
+  os << "\n - map = " << reinterpret_cast<void*>(obj->map()) << " [";
+  if (obj->HasFastProperties()) {
+    os << "FastProperties";
+  } else {
+    os << "DictionaryProperties";
+  }
+  PrototypeIterator iter(obj->GetIsolate(), obj);
+  os << "]\n - prototype = " << reinterpret_cast<void*>(iter.GetCurrent());
+  os << "\n - elements = " << Brief(obj->elements()) << " ["
      << ElementsKindToString(obj->map()->elements_kind());
   if (obj->elements()->map() == obj->GetHeap()->fixed_cow_array_map()) {
     os << " (COW)";
   }
-  PrototypeIterator iter(obj->GetIsolate(), obj);
-  os << "]\n - prototype = " << reinterpret_cast<void*>(iter.GetCurrent());
-  if (obj->elements()->length() > 0) {
-    os << "\n - elements = " << Brief(obj->elements());
-  }
+  os << "]";
 }
 
 
 static void JSObjectPrintBody(std::ostream& os, JSObject* obj,  // NOLINT
                               bool print_elements = true) {
-  os << "\n {";
+  os << "\n - properties = {";
   obj->PrintProperties(os);
-  obj->PrintTransitions(os);
-  if (print_elements) obj->PrintElements(os);
   os << "\n }\n";
+  if (print_elements && obj->elements()->length() > 0) {
+    os << " - elements = {";
+    obj->PrintElements(os);
+    os << "\n }\n";
+  }
 }
 
 
 void JSObject::JSObjectPrint(std::ostream& os) {  // NOLINT
-  JSObjectPrintHeader(os, this, "JSObject");
+  JSObjectPrintHeader(os, this, nullptr);
+  JSObjectPrintBody(os, this);
+}
+
+void JSArray::JSArrayPrint(std::ostream& os) {  // NOLINT
+  JSObjectPrintHeader(os, this, "JSArray");
+  os << "\n - length = " << Brief(this->length());
   JSObjectPrintBody(os, this);
 }
 
@@ -444,7 +467,7 @@
   HeapObject::PrintHeader(os, "Symbol");
   os << "\n - hash: " << Hash();
   os << "\n - name: " << Brief(name());
-  if (name()->IsUndefined()) {
+  if (name()->IsUndefined(GetIsolate())) {
     os << " (" << PrivateSymbolToName() << ")";
   }
   os << "\n - private: " << is_private();
@@ -478,7 +501,6 @@
   if (is_constructor()) os << "\n - constructor";
   if (is_access_check_needed()) os << "\n - access_check_needed";
   if (!is_extensible()) os << "\n - non-extensible";
-  if (is_observed()) os << "\n - observed";
   if (is_prototype_map()) {
     os << "\n - prototype_map";
     os << "\n - prototype info: " << Brief(prototype_info());
@@ -506,20 +528,6 @@
 }
 
 
-void CodeCache::CodeCachePrint(std::ostream& os) {  // NOLINT
-  HeapObject::PrintHeader(os, "CodeCache");
-  os << "\n - default_cache: " << Brief(default_cache());
-  os << "\n - normal_type_cache: " << Brief(normal_type_cache());
-}
-
-
-void PolymorphicCodeCache::PolymorphicCodeCachePrint(
-    std::ostream& os) {  // NOLINT
-  HeapObject::PrintHeader(os, "PolymorphicCodeCache");
-  os << "\n - cache: " << Brief(cache());
-}
-
-
 void TypeFeedbackInfo::TypeFeedbackInfoPrint(std::ostream& os) {  // NOLINT
   HeapObject::PrintHeader(os, "TypeFeedbackInfo");
   os << "\n - ic_total_count: " << ic_total_count()
@@ -572,6 +580,40 @@
   os << "\n";
 }
 
+template void FeedbackVectorSpecBase<StaticFeedbackVectorSpec>::Print();
+template void FeedbackVectorSpecBase<FeedbackVectorSpec>::Print();
+
+template <typename Derived>
+void FeedbackVectorSpecBase<Derived>::Print() {
+  OFStream os(stdout);
+  FeedbackVectorSpecPrint(os);
+  os << std::flush;
+}
+
+template <typename Derived>
+void FeedbackVectorSpecBase<Derived>::FeedbackVectorSpecPrint(
+    std::ostream& os) {  // NOLINT
+  int slot_count = This()->slots();
+  os << " - slot_count: " << slot_count;
+  if (slot_count == 0) {
+    os << " (empty)\n";
+    return;
+  }
+
+  for (int slot = 0, name_index = 0; slot < slot_count;) {
+    FeedbackVectorSlotKind kind = This()->GetKind(slot);
+    int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
+    DCHECK_LT(0, entry_size);
+
+    os << "\n Slot #" << slot << " " << kind;
+    if (TypeFeedbackMetadata::SlotRequiresName(kind)) {
+      os << ", " << Brief(*This()->GetName(name_index++));
+    }
+
+    slot += entry_size;
+  }
+  os << "\n";
+}
 
 void TypeFeedbackMetadata::Print() {
   OFStream os(stdout);
@@ -588,12 +630,16 @@
     os << " (empty)\n";
     return;
   }
+  os << "\n - slot_count: " << slot_count();
 
   TypeFeedbackMetadataIterator iter(this);
   while (iter.HasNext()) {
     FeedbackVectorSlot slot = iter.Next();
     FeedbackVectorSlotKind kind = iter.kind();
     os << "\n Slot " << slot << " " << kind;
+    if (TypeFeedbackMetadata::SlotRequiresName(kind)) {
+      os << ", " << Brief(iter.name());
+    }
   }
   os << "\n";
 }
@@ -619,13 +665,22 @@
     FeedbackVectorSlot slot = iter.Next();
     FeedbackVectorSlotKind kind = iter.kind();
 
-    os << "\n Slot " << slot << " " << kind << " ";
+    os << "\n Slot " << slot << " " << kind;
+    if (TypeFeedbackMetadata::SlotRequiresName(kind)) {
+      os << ", " << Brief(iter.name());
+    }
+    os << " ";
     switch (kind) {
       case FeedbackVectorSlotKind::LOAD_IC: {
         LoadICNexus nexus(this, slot);
         os << Code::ICState2String(nexus.StateFromFeedback());
         break;
       }
+      case FeedbackVectorSlotKind::LOAD_GLOBAL_IC: {
+        LoadGlobalICNexus nexus(this, slot);
+        os << Code::ICState2String(nexus.StateFromFeedback());
+        break;
+      }
       case FeedbackVectorSlotKind::KEYED_LOAD_IC: {
         KeyedLoadICNexus nexus(this, slot);
         os << Code::ICState2String(nexus.StateFromFeedback());
@@ -713,8 +768,6 @@
 void Name::NamePrint(std::ostream& os) {  // NOLINT
   if (IsString()) {
     String::cast(this)->StringPrint(os);
-  } else if (IsSymbol()) {
-    Symbol::cast(this)->name()->Print(os);
   } else {
     os << Brief(this);
   }
@@ -872,6 +925,8 @@
      << shared()->internal_formal_parameter_count();
   if (shared()->is_generator()) {
     os << "\n   - generator";
+  } else if (shared()->is_async()) {
+    os << "\n   - async";
   }
   os << "\n - context = " << Brief(context());
   os << "\n - literals = " << Brief(literals());
@@ -913,9 +968,10 @@
   os << "\n - end position = " << end_position();
   os << "\n - debug info = " << Brief(debug_info());
   os << "\n - length = " << length();
+  os << "\n - num_literals = " << num_literals();
   os << "\n - optimized_code_map = " << Brief(optimized_code_map());
-  os << "\n - feedback_vector = ";
-  feedback_vector()->TypeFeedbackVectorPrint(os);
+  os << "\n - feedback_metadata = ";
+  feedback_metadata()->TypeFeedbackMetadataPrint(os);
   if (HasBytecodeArray()) {
     os << "\n - bytecode_array = " << bytecode_array();
   }
@@ -988,6 +1044,7 @@
   os << "\n - flag: " << flag();
   os << "\n - getter: " << Brief(getter());
   os << "\n - setter: " << Brief(setter());
+  os << "\n - js_getter: " << Brief(js_getter());
   os << "\n - data: " << Brief(data());
   os << "\n";
 }
@@ -1028,9 +1085,9 @@
 
 void AccessCheckInfo::AccessCheckInfoPrint(std::ostream& os) {  // NOLINT
   HeapObject::PrintHeader(os, "AccessCheckInfo");
-  os << "\n - named_callback: " << Brief(named_callback());
-  os << "\n - indexed_callback: " << Brief(indexed_callback());
   os << "\n - callback: " << Brief(callback());
+  os << "\n - named_interceptor: " << Brief(named_interceptor());
+  os << "\n - indexed_interceptor: " << Brief(indexed_interceptor());
   os << "\n - data: " << Brief(data());
   os << "\n";
 }
@@ -1140,8 +1197,7 @@
   os << "\n - compilation type: " << compilation_type();
   os << "\n - line ends: " << Brief(line_ends());
   os << "\n - eval from shared: " << Brief(eval_from_shared());
-  os << "\n - eval from instructions offset: "
-     << eval_from_instructions_offset();
+  os << "\n - eval from position: " << eval_from_position();
   os << "\n - shared function infos: " << Brief(shared_function_infos());
   os << "\n";
 }
@@ -1184,7 +1240,7 @@
 
 void LayoutDescriptor::Print(std::ostream& os) {  // NOLINT
   os << "Layout descriptor: ";
-  if (IsUninitialized()) {
+  if (IsOddball() && IsUninitialized(HeapObject::cast(this)->GetIsolate())) {
     os << "<uninitialized>";
   } else if (IsFastPointerLayout()) {
     os << "<all tagged>";
@@ -1215,7 +1271,7 @@
   } else {
     DCHECK(this->IsSymbol());
     Symbol* s = Symbol::cast(this);
-    if (s->name()->IsUndefined()) {
+    if (s->name()->IsUndefined(GetIsolate())) {
       PrintF("#<%s>", s->PrivateSymbolToName());
     } else {
       PrintF("<%s>", String::cast(s->name())->ToCString().get());
@@ -1230,7 +1286,7 @@
   } else {
     DCHECK(this->IsSymbol());
     Symbol* s = Symbol::cast(this);
-    if (s->name()->IsUndefined()) {
+    if (s->name()->IsUndefined(GetIsolate())) {
       return SNPrintF(str, "#<%s>", s->PrivateSymbolToName());
     } else {
       return SNPrintF(str, "<%s>", String::cast(s->name())->ToCString().get());
@@ -1293,7 +1349,7 @@
   for (int i = 0; i < num_transitions; i++) {
     Name* key = GetKey(transitions, i);
     Map* target = GetTarget(transitions, i);
-    os << "\n   ";
+    os << "\n     ";
 #ifdef OBJECT_PRINT
     key->NamePrint(os);
 #else
@@ -1312,8 +1368,6 @@
          << ")";
     } else if (key == heap->strict_function_transition_symbol()) {
       os << " (transition to strict function)";
-    } else if (key == heap->observed_symbol()) {
-      os << " (transition to Object.observe)";
     } else {
       PropertyDetails details = GetTargetDetails(key, target);
       os << "(transition to ";
diff --git a/src/objects.cc b/src/objects.cc
index 1a82c3c..fb5bb5e 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -12,9 +12,9 @@
 
 #include "src/accessors.h"
 #include "src/allocation-site-scopes.h"
-#include "src/api.h"
-#include "src/api-arguments.h"
+#include "src/api-arguments-inl.h"
 #include "src/api-natives.h"
+#include "src/api.h"
 #include "src/base/bits.h"
 #include "src/base/utils/random-number-generator.h"
 #include "src/bootstrapper.h"
@@ -22,6 +22,8 @@
 #include "src/codegen.h"
 #include "src/compilation-dependencies.h"
 #include "src/compiler.h"
+#include "src/counters-inl.h"
+#include "src/counters.h"
 #include "src/date.h"
 #include "src/debug/debug.h"
 #include "src/deoptimizer.h"
@@ -30,6 +32,7 @@
 #include "src/field-index-inl.h"
 #include "src/field-index.h"
 #include "src/field-type.h"
+#include "src/frames-inl.h"
 #include "src/full-codegen/full-codegen.h"
 #include "src/ic/ic.h"
 #include "src/identity-map.h"
@@ -44,7 +47,6 @@
 #include "src/macro-assembler.h"
 #include "src/messages.h"
 #include "src/objects-body-descriptors-inl.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/property-descriptor.h"
 #include "src/prototype.h"
 #include "src/regexp/jsregexp.h"
@@ -121,8 +123,8 @@
                                                 Handle<Object> object) {
   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
   if (*object == isolate->heap()->null_value() ||
-      *object == isolate->heap()->undefined_value()) {
-    return handle(isolate->global_proxy(), isolate);
+      object->IsUndefined(isolate)) {
+    return isolate->global_proxy();
   }
   return Object::ToObject(isolate, object);
 }
@@ -228,9 +230,11 @@
 
 
 bool Object::BooleanValue() {
-  if (IsBoolean()) return IsTrue();
   if (IsSmi()) return Smi::cast(this)->value() != 0;
-  if (IsUndefined() || IsNull()) return false;
+  DCHECK(IsHeapObject());
+  Isolate* isolate = HeapObject::cast(this)->GetIsolate();
+  if (IsBoolean()) return IsTrue(isolate);
+  if (IsUndefined(isolate) || IsNull(isolate)) return false;
   if (IsUndetectable()) return false;  // Undetectable object is false.
   if (IsString()) return String::cast(this)->length() != 0;
   if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
@@ -568,6 +572,86 @@
                                               NumberToInt32(*rhs));
 }
 
+// static
+MaybeHandle<Object> Object::OrdinaryHasInstance(Isolate* isolate,
+                                                Handle<Object> callable,
+                                                Handle<Object> object) {
+  // The {callable} must have a [[Call]] internal method.
+  if (!callable->IsCallable()) return isolate->factory()->false_value();
+
+  // Check if {callable} is a bound function, and if so retrieve its
+  // [[BoundTargetFunction]] and use that instead of {callable}.
+  if (callable->IsJSBoundFunction()) {
+    Handle<Object> bound_callable(
+        Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
+        isolate);
+    return Object::InstanceOf(isolate, object, bound_callable);
+  }
+
+  // If {object} is not a receiver, return false.
+  if (!object->IsJSReceiver()) return isolate->factory()->false_value();
+
+  // Get the "prototype" of {callable}; raise an error if it's not a receiver.
+  Handle<Object> prototype;
+  ASSIGN_RETURN_ON_EXCEPTION(
+      isolate, prototype,
+      Object::GetProperty(callable, isolate->factory()->prototype_string()),
+      Object);
+  if (!prototype->IsJSReceiver()) {
+    THROW_NEW_ERROR(
+        isolate,
+        NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype),
+        Object);
+  }
+
+  // Return whether or not {prototype} is in the prototype chain of {object}.
+  Maybe<bool> result = JSReceiver::HasInPrototypeChain(
+      isolate, Handle<JSReceiver>::cast(object), prototype);
+  if (result.IsNothing()) return MaybeHandle<Object>();
+  return isolate->factory()->ToBoolean(result.FromJust());
+}
+
+// static
+MaybeHandle<Object> Object::InstanceOf(Isolate* isolate, Handle<Object> object,
+                                       Handle<Object> callable) {
+  // The {callable} must be a receiver.
+  if (!callable->IsJSReceiver()) {
+    THROW_NEW_ERROR(isolate,
+                    NewTypeError(MessageTemplate::kNonObjectInInstanceOfCheck),
+                    Object);
+  }
+
+  // Lookup the @@hasInstance method on {callable}.
+  Handle<Object> inst_of_handler;
+  ASSIGN_RETURN_ON_EXCEPTION(
+      isolate, inst_of_handler,
+      JSReceiver::GetMethod(Handle<JSReceiver>::cast(callable),
+                            isolate->factory()->has_instance_symbol()),
+      Object);
+  if (!inst_of_handler->IsUndefined(isolate)) {
+    // Call the {inst_of_handler} on the {callable}.
+    Handle<Object> result;
+    ASSIGN_RETURN_ON_EXCEPTION(
+        isolate, result,
+        Execution::Call(isolate, inst_of_handler, callable, 1, &object),
+        Object);
+    return isolate->factory()->ToBoolean(result->BooleanValue());
+  }
+
+  // The {callable} must have a [[Call]] internal method.
+  if (!callable->IsCallable()) {
+    THROW_NEW_ERROR(
+        isolate, NewTypeError(MessageTemplate::kNonCallableInInstanceOfCheck),
+        Object);
+  }
+
+  // Fall back to OrdinaryHasInstance with {callable} and {object}.
+  Handle<Object> result;
+  ASSIGN_RETURN_ON_EXCEPTION(
+      isolate, result,
+      JSReceiver::OrdinaryHasInstance(isolate, callable, object), Object);
+  return result;
+}
 
 Maybe<bool> Object::IsArray(Handle<Object> object) {
   if (object->IsJSArray()) return Just(true);
@@ -586,20 +670,6 @@
 }
 
 
-bool Object::IsPromise(Handle<Object> object) {
-  if (!object->IsJSObject()) return false;
-  auto js_object = Handle<JSObject>::cast(object);
-  // Promises can't have access checks.
-  if (js_object->map()->is_access_check_needed()) return false;
-  auto isolate = js_object->GetIsolate();
-  // TODO(dcarney): this should just be read from the symbol registry so as not
-  // to be context dependent.
-  auto key = isolate->factory()->promise_status_symbol();
-  // Shouldn't be possible to throw here.
-  return JSObject::HasRealNamedProperty(js_object, key).FromJust();
-}
-
-
 // static
 MaybeHandle<Object> Object::GetMethod(Handle<JSReceiver> receiver,
                                       Handle<Name> name) {
@@ -607,7 +677,7 @@
   Isolate* isolate = receiver->GetIsolate();
   ASSIGN_RETURN_ON_EXCEPTION(isolate, func,
                              JSReceiver::GetProperty(receiver, name), Object);
-  if (func->IsNull() || func->IsUndefined()) {
+  if (func->IsNull(isolate) || func->IsUndefined(isolate)) {
     return isolate->factory()->undefined_value();
   }
   if (!func->IsCallable()) {
@@ -634,14 +704,9 @@
   }
   // 4. Let len be ? ToLength(? Get(obj, "length")).
   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
-  Handle<Object> raw_length_obj;
-  ASSIGN_RETURN_ON_EXCEPTION(
-      isolate, raw_length_obj,
-      JSReceiver::GetProperty(receiver, isolate->factory()->length_string()),
-      FixedArray);
   Handle<Object> raw_length_number;
   ASSIGN_RETURN_ON_EXCEPTION(isolate, raw_length_number,
-                             Object::ToLength(isolate, raw_length_obj),
+                             Object::GetLengthFromArrayLike(isolate, receiver),
                              FixedArray);
   uint32_t len;
   if (!raw_length_number->ToUint32(&len) ||
@@ -688,6 +753,16 @@
 
 
 // static
+MaybeHandle<Object> Object::GetLengthFromArrayLike(Isolate* isolate,
+                                                   Handle<Object> object) {
+  Handle<Object> val;
+  Handle<Object> key = isolate->factory()->length_string();
+  ASSIGN_RETURN_ON_EXCEPTION(
+      isolate, val, Runtime::GetObjectProperty(isolate, object, key), Object);
+  return Object::ToLength(isolate, val);
+}
+
+// static
 Maybe<bool> JSReceiver::HasProperty(LookupIterator* it) {
   for (; it->IsFound(); it->Next()) {
     switch (it->state()) {
@@ -762,17 +837,6 @@
 }
 
 
-#define STACK_CHECK(result_value)                        \
-  do {                                                   \
-    StackLimitCheck stack_check(isolate);                \
-    if (stack_check.HasOverflowed()) {                   \
-      isolate->Throw(*isolate->factory()->NewRangeError( \
-          MessageTemplate::kStackOverflow));             \
-      return result_value;                               \
-    }                                                    \
-  } while (false)
-
-
 // static
 MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate,
                                          Handle<JSProxy> proxy,
@@ -788,7 +852,7 @@
   }
 
   DCHECK(!name->IsPrivate());
-  STACK_CHECK(MaybeHandle<Object>());
+  STACK_CHECK(isolate, MaybeHandle<Object>());
   Handle<Name> trap_name = isolate->factory()->get_string();
   // 1. Assert: IsPropertyKey(P) is true.
   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
@@ -808,7 +872,7 @@
       isolate, trap,
       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), Object);
   // 7. If trap is undefined, then
-  if (trap->IsUndefined()) {
+  if (trap->IsUndefined(isolate)) {
     // 7.a Return target.[[Get]](P, Receiver).
     LookupIterator it =
         LookupIterator::PropertyOrElement(isolate, receiver, name, target);
@@ -848,8 +912,8 @@
     // 10.b.i. If trapResult is not undefined, throw a TypeError exception.
     inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
                    !target_desc.configurable() &&
-                   target_desc.get()->IsUndefined() &&
-                   !trap_result->IsUndefined();
+                   target_desc.get()->IsUndefined(isolate) &&
+                   !trap_result->IsUndefined(isolate);
     if (inconsistent) {
       THROW_NEW_ERROR(
           isolate,
@@ -908,13 +972,41 @@
   return false;
 }
 
+Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
+    Isolate* isolate, Handle<FunctionTemplateInfo> info) {
+  Object* current_info = info->shared_function_info();
+  if (current_info->IsSharedFunctionInfo()) {
+    return handle(SharedFunctionInfo::cast(current_info), isolate);
+  }
 
-bool FunctionTemplateInfo::IsTemplateFor(Object* object) {
-  if (!object->IsHeapObject()) return false;
-  return IsTemplateFor(HeapObject::cast(object)->map());
+  Handle<Object> class_name(info->class_name(), isolate);
+  Handle<String> name = class_name->IsString()
+                            ? Handle<String>::cast(class_name)
+                            : isolate->factory()->empty_string();
+  Handle<Code> code;
+  if (info->call_code()->IsCallHandlerInfo() &&
+      CallHandlerInfo::cast(info->call_code())->fast_handler()->IsCode()) {
+    code = isolate->builtins()->HandleFastApiCall();
+  } else {
+    code = isolate->builtins()->HandleApiCall();
+  }
+  bool is_constructor = !info->remove_prototype();
+  Handle<SharedFunctionInfo> result =
+      isolate->factory()->NewSharedFunctionInfo(name, code, is_constructor);
+  if (is_constructor) {
+    result->set_construct_stub(*isolate->builtins()->JSConstructStubApi());
+  }
+
+  result->set_length(info->length());
+  if (class_name->IsString()) result->set_instance_class_name(*class_name);
+  result->set_api_func_data(*info);
+  result->DontAdaptArguments();
+  DCHECK(result->IsApiFunction());
+
+  info->set_shared_function_info(*result);
+  return result;
 }
 
-
 bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
   // There is a constraint on the object; check.
   if (!map->IsJSObjectMap()) return false;
@@ -934,26 +1026,6 @@
 }
 
 
-// TODO(dcarney): CallOptimization duplicates this logic, merge.
-Object* FunctionTemplateInfo::GetCompatibleReceiver(Isolate* isolate,
-                                                    Object* receiver) {
-  // API calls are only supported with JSObject receivers.
-  if (!receiver->IsJSObject()) return isolate->heap()->null_value();
-  Object* recv_type = this->signature();
-  // No signature, return holder.
-  if (recv_type->IsUndefined()) return receiver;
-  FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type);
-  // Check the receiver.
-  for (PrototypeIterator iter(isolate, JSObject::cast(receiver),
-                              PrototypeIterator::START_AT_RECEIVER,
-                              PrototypeIterator::END_AT_NON_HIDDEN);
-       !iter.IsAtEnd(); iter.Advance()) {
-    if (signature->IsTemplateFor(iter.GetCurrent())) return iter.GetCurrent();
-  }
-  return isolate->heap()->null_value();
-}
-
-
 // static
 MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor,
                                     Handle<JSReceiver> new_target,
@@ -1001,7 +1073,7 @@
   Isolate* isolate = proxy->GetIsolate();
   Handle<String> trap_name = isolate->factory()->getPrototypeOf_string();
 
-  STACK_CHECK(MaybeHandle<Object>());
+  STACK_CHECK(isolate, MaybeHandle<Object>());
 
   // 1. Let handler be the value of the [[ProxyHandler]] internal slot.
   // 2. If handler is null, throw a TypeError exception.
@@ -1020,7 +1092,7 @@
   ASSIGN_RETURN_ON_EXCEPTION(isolate, trap, GetMethod(handler, trap_name),
                              Object);
   // 6. If trap is undefined, then return target.[[GetPrototypeOf]]().
-  if (trap->IsUndefined()) {
+  if (trap->IsUndefined(isolate)) {
     return JSReceiver::GetPrototype(isolate, target);
   }
   // 7. Let handlerProto be ? Call(trap, handler, «target»).
@@ -1030,7 +1102,7 @@
       isolate, handler_proto,
       Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object);
   // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError.
-  if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull())) {
+  if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull(isolate))) {
     THROW_NEW_ERROR(isolate,
                     NewTypeError(MessageTemplate::kProxyGetPrototypeOfInvalid),
                     Object);
@@ -1098,16 +1170,9 @@
   // Regular accessor.
   Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
   if (getter->IsFunctionTemplateInfo()) {
-    auto result = Builtins::InvokeApiFunction(
-        Handle<FunctionTemplateInfo>::cast(getter), receiver, 0, nullptr);
-    if (isolate->has_pending_exception()) {
-      return MaybeHandle<Object>();
-    }
-    Handle<Object> return_value;
-    if (result.ToHandle(&return_value)) {
-      return_value->VerifyApiCallResultType();
-      return handle(*return_value, isolate);
-    }
+    return Builtins::InvokeApiFunction(
+        isolate, Handle<FunctionTemplateInfo>::cast(getter), receiver, 0,
+        nullptr);
   } else if (getter->IsCallable()) {
     // TODO(rossberg): nicer would be to cast to some JSCallable here...
     return Object::GetPropertyWithDefinedGetter(
@@ -1117,6 +1182,20 @@
   return ReadAbsentProperty(isolate, receiver, it->GetName());
 }
 
+// static
+Address AccessorInfo::redirect(Isolate* isolate, Address address,
+                               AccessorComponent component) {
+  ApiFunction fun(address);
+  DCHECK_EQ(ACCESSOR_GETTER, component);
+  ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
+  return ExternalReference(&fun, type, isolate).address();
+}
+
+Address AccessorInfo::redirected_getter() const {
+  Address accessor = v8::ToCData<Address>(getter());
+  if (accessor == nullptr) return nullptr;
+  return redirect(GetIsolate(), accessor, ACCESSOR_GETTER);
+}
 
 bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate,
                                            Handle<AccessorInfo> info,
@@ -1173,12 +1252,11 @@
   Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
   if (setter->IsFunctionTemplateInfo()) {
     Handle<Object> argv[] = {value};
-    auto result =
-        Builtins::InvokeApiFunction(Handle<FunctionTemplateInfo>::cast(setter),
-                                    receiver, arraysize(argv), argv);
-    if (isolate->has_pending_exception()) {
-      return Nothing<bool>();
-    }
+    RETURN_ON_EXCEPTION_VALUE(
+        isolate, Builtins::InvokeApiFunction(
+                     isolate, Handle<FunctionTemplateInfo>::cast(setter),
+                     receiver, arraysize(argv), argv),
+        Nothing<bool>());
     return Just(true);
   } else if (setter->IsCallable()) {
     // TODO(rossberg): nicer would be to cast to some JSCallable here...
@@ -1230,18 +1308,6 @@
 
 
 // static
-bool Object::IsErrorObject(Isolate* isolate, Handle<Object> object) {
-  if (!object->IsJSObject()) return false;
-  // Use stack_trace_symbol as proxy for [[ErrorData]].
-  Handle<Name> symbol = isolate->factory()->stack_trace_symbol();
-  Maybe<bool> has_stack_trace =
-      JSReceiver::HasOwnProperty(Handle<JSReceiver>::cast(object), symbol);
-  DCHECK(!has_stack_trace.IsNothing());
-  return has_stack_trace.FromJust();
-}
-
-
-// static
 bool JSObject::AllCanRead(LookupIterator* it) {
   // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
   // which have already been checked.
@@ -1263,19 +1329,191 @@
   return false;
 }
 
+namespace {
+
+MaybeHandle<Object> GetPropertyWithInterceptorInternal(
+    LookupIterator* it, Handle<InterceptorInfo> interceptor, bool* done) {
+  *done = false;
+  Isolate* isolate = it->isolate();
+  // Make sure that the top context does not change when doing callbacks or
+  // interceptor calls.
+  AssertNoContextChange ncc(isolate);
+
+  if (interceptor->getter()->IsUndefined(isolate)) {
+    return isolate->factory()->undefined_value();
+  }
+
+  Handle<JSObject> holder = it->GetHolder<JSObject>();
+  Handle<Object> result;
+  Handle<Object> receiver = it->GetReceiver();
+  if (!receiver->IsJSReceiver()) {
+    ASSIGN_RETURN_ON_EXCEPTION(
+        isolate, receiver, Object::ConvertReceiver(isolate, receiver), Object);
+  }
+  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
+                                 *holder, Object::DONT_THROW);
+
+  if (it->IsElement()) {
+    uint32_t index = it->index();
+    v8::IndexedPropertyGetterCallback getter =
+        v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
+    result = args.Call(getter, index);
+  } else {
+    Handle<Name> name = it->name();
+    DCHECK(!name->IsPrivate());
+
+    if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
+      return isolate->factory()->undefined_value();
+    }
+
+    v8::GenericNamedPropertyGetterCallback getter =
+        v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
+            interceptor->getter());
+    result = args.Call(getter, name);
+  }
+
+  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
+  if (result.is_null()) return isolate->factory()->undefined_value();
+  *done = true;
+  // Rebox handle before return
+  return handle(*result, isolate);
+}
+
+Maybe<PropertyAttributes> GetPropertyAttributesWithInterceptorInternal(
+    LookupIterator* it, Handle<InterceptorInfo> interceptor) {
+  Isolate* isolate = it->isolate();
+  // Make sure that the top context does not change when doing
+  // callbacks or interceptor calls.
+  AssertNoContextChange ncc(isolate);
+  HandleScope scope(isolate);
+
+  Handle<JSObject> holder = it->GetHolder<JSObject>();
+  if (!it->IsElement() && it->name()->IsSymbol() &&
+      !interceptor->can_intercept_symbols()) {
+    return Just(ABSENT);
+  }
+  Handle<Object> receiver = it->GetReceiver();
+  if (!receiver->IsJSReceiver()) {
+    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
+                                     Object::ConvertReceiver(isolate, receiver),
+                                     Nothing<PropertyAttributes>());
+  }
+  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
+                                 *holder, Object::DONT_THROW);
+  if (!interceptor->query()->IsUndefined(isolate)) {
+    Handle<Object> result;
+    if (it->IsElement()) {
+      uint32_t index = it->index();
+      v8::IndexedPropertyQueryCallback query =
+          v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
+      result = args.Call(query, index);
+    } else {
+      Handle<Name> name = it->name();
+      DCHECK(!name->IsPrivate());
+      v8::GenericNamedPropertyQueryCallback query =
+          v8::ToCData<v8::GenericNamedPropertyQueryCallback>(
+              interceptor->query());
+      result = args.Call(query, name);
+    }
+    if (!result.is_null()) {
+      int32_t value;
+      CHECK(result->ToInt32(&value));
+      return Just(static_cast<PropertyAttributes>(value));
+    }
+  } else if (!interceptor->getter()->IsUndefined(isolate)) {
+    // TODO(verwaest): Use GetPropertyWithInterceptor?
+    Handle<Object> result;
+    if (it->IsElement()) {
+      uint32_t index = it->index();
+      v8::IndexedPropertyGetterCallback getter =
+          v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
+      result = args.Call(getter, index);
+    } else {
+      Handle<Name> name = it->name();
+      DCHECK(!name->IsPrivate());
+      v8::GenericNamedPropertyGetterCallback getter =
+          v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
+              interceptor->getter());
+      result = args.Call(getter, name);
+    }
+    if (!result.is_null()) return Just(DONT_ENUM);
+  }
+
+  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
+  return Just(ABSENT);
+}
+
+Maybe<bool> SetPropertyWithInterceptorInternal(
+    LookupIterator* it, Handle<InterceptorInfo> interceptor,
+    Object::ShouldThrow should_throw, Handle<Object> value) {
+  Isolate* isolate = it->isolate();
+  // Make sure that the top context does not change when doing callbacks or
+  // interceptor calls.
+  AssertNoContextChange ncc(isolate);
+
+  if (interceptor->setter()->IsUndefined(isolate)) return Just(false);
+
+  Handle<JSObject> holder = it->GetHolder<JSObject>();
+  bool result;
+  Handle<Object> receiver = it->GetReceiver();
+  if (!receiver->IsJSReceiver()) {
+    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
+                                     Object::ConvertReceiver(isolate, receiver),
+                                     Nothing<bool>());
+  }
+  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
+                                 *holder, should_throw);
+
+  if (it->IsElement()) {
+    uint32_t index = it->index();
+    v8::IndexedPropertySetterCallback setter =
+        v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
+    // TODO(neis): In the future, we may want to actually return the
+    // interceptor's result, which then should be a boolean.
+    result = !args.Call(setter, index, value).is_null();
+  } else {
+    Handle<Name> name = it->name();
+    DCHECK(!name->IsPrivate());
+
+    if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
+      return Just(false);
+    }
+
+    v8::GenericNamedPropertySetterCallback setter =
+        v8::ToCData<v8::GenericNamedPropertySetterCallback>(
+            interceptor->setter());
+    result = !args.Call(setter, name, value).is_null();
+  }
+
+  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
+  return Just(result);
+}
+
+}  // namespace
 
 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
     LookupIterator* it) {
+  Isolate* isolate = it->isolate();
   Handle<JSObject> checked = it->GetHolder<JSObject>();
-  while (AllCanRead(it)) {
-    if (it->state() == LookupIterator::ACCESSOR) {
-      return GetPropertyWithAccessor(it);
+  Handle<InterceptorInfo> interceptor =
+      it->GetInterceptorForFailedAccessCheck();
+  if (interceptor.is_null()) {
+    while (AllCanRead(it)) {
+      if (it->state() == LookupIterator::ACCESSOR) {
+        return GetPropertyWithAccessor(it);
+      }
+      DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
+      bool done;
+      Handle<Object> result;
+      ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
+                                 GetPropertyWithInterceptor(it, &done), Object);
+      if (done) return result;
     }
-    DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
+  } else {
+    MaybeHandle<Object> result;
     bool done;
-    Handle<Object> result;
-    ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), result,
-                               GetPropertyWithInterceptor(it, &done), Object);
+    result = GetPropertyWithInterceptorInternal(it, interceptor, &done);
+    RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
     if (done) return result;
   }
 
@@ -1286,27 +1524,36 @@
     return it->factory()->undefined_value();
   }
 
-  it->isolate()->ReportFailedAccessCheck(checked);
-  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
+  isolate->ReportFailedAccessCheck(checked);
+  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   return it->factory()->undefined_value();
 }
 
 
 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
     LookupIterator* it) {
+  Isolate* isolate = it->isolate();
   Handle<JSObject> checked = it->GetHolder<JSObject>();
-  while (AllCanRead(it)) {
-    if (it->state() == LookupIterator::ACCESSOR) {
-      return Just(it->property_attributes());
+  Handle<InterceptorInfo> interceptor =
+      it->GetInterceptorForFailedAccessCheck();
+  if (interceptor.is_null()) {
+    while (AllCanRead(it)) {
+      if (it->state() == LookupIterator::ACCESSOR) {
+        return Just(it->property_attributes());
+      }
+      DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
+      auto result = GetPropertyAttributesWithInterceptor(it);
+      if (isolate->has_scheduled_exception()) break;
+      if (result.IsJust() && result.FromJust() != ABSENT) return result;
     }
-    DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
-    auto result = GetPropertyAttributesWithInterceptor(it);
-    if (it->isolate()->has_scheduled_exception()) break;
-    if (result.IsJust() && result.FromJust() != ABSENT) return result;
+  } else {
+    Maybe<PropertyAttributes> result =
+        GetPropertyAttributesWithInterceptorInternal(it, interceptor);
+    RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
+    if (result.FromMaybe(ABSENT) != ABSENT) return result;
   }
-  it->isolate()->ReportFailedAccessCheck(checked);
-  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(),
-                                      Nothing<PropertyAttributes>());
+  isolate->ReportFailedAccessCheck(checked);
+  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
   return Just(ABSENT);
 }
 
@@ -1327,13 +1574,23 @@
 
 Maybe<bool> JSObject::SetPropertyWithFailedAccessCheck(
     LookupIterator* it, Handle<Object> value, ShouldThrow should_throw) {
+  Isolate* isolate = it->isolate();
   Handle<JSObject> checked = it->GetHolder<JSObject>();
-  if (AllCanWrite(it)) {
-    return SetPropertyWithAccessor(it, value, should_throw);
+  Handle<InterceptorInfo> interceptor =
+      it->GetInterceptorForFailedAccessCheck();
+  if (interceptor.is_null()) {
+    if (AllCanWrite(it)) {
+      return SetPropertyWithAccessor(it, value, should_throw);
+    }
+  } else {
+    Maybe<bool> result = SetPropertyWithInterceptorInternal(
+        it, interceptor, should_throw, value);
+    RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
+    if (result.IsJust()) return result;
   }
 
-  it->isolate()->ReportFailedAccessCheck(checked);
-  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
+  isolate->ReportFailedAccessCheck(checked);
+  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   return Just(true);
 }
 
@@ -1353,10 +1610,12 @@
 
     int entry = property_dictionary->FindEntry(name);
     if (entry == GlobalDictionary::kNotFound) {
-      auto cell = object->GetIsolate()->factory()->NewPropertyCell();
+      Isolate* isolate = object->GetIsolate();
+      auto cell = isolate->factory()->NewPropertyCell();
       cell->set_value(*value);
-      auto cell_type = value->IsUndefined() ? PropertyCellType::kUndefined
-                                            : PropertyCellType::kConstant;
+      auto cell_type = value->IsUndefined(isolate)
+                           ? PropertyCellType::kUndefined
+                           : PropertyCellType::kConstant;
       details = details.set_cell_type(cell_type);
       value = cell;
       property_dictionary =
@@ -1383,10 +1642,11 @@
   }
 }
 
+// static
 Maybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate,
                                             Handle<JSReceiver> object,
                                             Handle<Object> proto) {
-  PrototypeIterator iter(isolate, object, PrototypeIterator::START_AT_RECEIVER);
+  PrototypeIterator iter(isolate, object, kStartAtReceiver);
   while (true) {
     if (!iter.AdvanceFollowingProxies()) return Nothing<bool>();
     if (iter.IsAtEnd()) return Just(false);
@@ -1396,7 +1656,6 @@
   }
 }
 
-
 Map* Object::GetRootMap(Isolate* isolate) {
   DisallowHeapAllocation no_alloc;
   if (IsSmi()) {
@@ -1421,28 +1680,21 @@
   return isolate->heap()->null_value()->map();
 }
 
+namespace {
 
-Object* Object::GetHash() {
-  Object* hash = GetSimpleHash();
-  if (hash->IsSmi()) return hash;
-
-  DisallowHeapAllocation no_gc;
-  DCHECK(IsJSReceiver());
-  JSReceiver* receiver = JSReceiver::cast(this);
-  Isolate* isolate = receiver->GetIsolate();
-  return *JSReceiver::GetIdentityHash(isolate, handle(receiver, isolate));
-}
-
-
-Object* Object::GetSimpleHash() {
+// Returns a non-SMI for JSObjects, but returns the hash code for simple
+// objects.  This avoids a double lookup in the cases where we know we will
+// add the hash to the JSObject if it does not already exist.
+Object* GetSimpleHash(Object* object) {
   // The object is either a Smi, a HeapNumber, a name, an odd-ball,
   // a SIMD value type, a real JS object, or a Harmony proxy.
-  if (IsSmi()) {
-    uint32_t hash = ComputeIntegerHash(Smi::cast(this)->value(), kZeroHashSeed);
+  if (object->IsSmi()) {
+    uint32_t hash =
+        ComputeIntegerHash(Smi::cast(object)->value(), kZeroHashSeed);
     return Smi::FromInt(hash & Smi::kMaxValue);
   }
-  if (IsHeapNumber()) {
-    double num = HeapNumber::cast(this)->value();
+  if (object->IsHeapNumber()) {
+    double num = HeapNumber::cast(object)->value();
     if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
     if (i::IsMinusZero(num)) num = 0;
     if (IsSmiDouble(num)) {
@@ -1451,30 +1703,43 @@
     uint32_t hash = ComputeLongHash(double_to_uint64(num));
     return Smi::FromInt(hash & Smi::kMaxValue);
   }
-  if (IsName()) {
-    uint32_t hash = Name::cast(this)->Hash();
+  if (object->IsName()) {
+    uint32_t hash = Name::cast(object)->Hash();
     return Smi::FromInt(hash);
   }
-  if (IsOddball()) {
-    uint32_t hash = Oddball::cast(this)->to_string()->Hash();
+  if (object->IsOddball()) {
+    uint32_t hash = Oddball::cast(object)->to_string()->Hash();
     return Smi::FromInt(hash);
   }
-  if (IsSimd128Value()) {
-    uint32_t hash = Simd128Value::cast(this)->Hash();
+  if (object->IsSimd128Value()) {
+    uint32_t hash = Simd128Value::cast(object)->Hash();
     return Smi::FromInt(hash & Smi::kMaxValue);
   }
-  DCHECK(IsJSReceiver());
-  JSReceiver* receiver = JSReceiver::cast(this);
-  return receiver->GetHeap()->undefined_value();
+  DCHECK(object->IsJSReceiver());
+  // Simply return the receiver as it is guaranteed to not be a SMI.
+  return object;
 }
 
+}  // namespace
 
-Handle<Smi> Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) {
-  Handle<Object> hash(object->GetSimpleHash(), isolate);
-  if (hash->IsSmi()) return Handle<Smi>::cast(hash);
+Object* Object::GetHash() {
+  Object* hash = GetSimpleHash(this);
+  if (hash->IsSmi()) return hash;
+
+  DisallowHeapAllocation no_gc;
+  DCHECK(IsJSReceiver());
+  JSReceiver* receiver = JSReceiver::cast(this);
+  Isolate* isolate = receiver->GetIsolate();
+  return JSReceiver::GetIdentityHash(isolate, handle(receiver, isolate));
+}
+
+Smi* Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) {
+  Object* hash = GetSimpleHash(*object);
+  if (hash->IsSmi()) return Smi::cast(hash);
 
   DCHECK(object->IsJSReceiver());
-  return JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver>::cast(object));
+  return JSReceiver::GetOrCreateIdentityHash(isolate,
+                                             Handle<JSReceiver>::cast(object));
 }
 
 
@@ -1555,11 +1820,7 @@
 
 MaybeHandle<Object> Object::ArraySpeciesConstructor(
     Isolate* isolate, Handle<Object> original_array) {
-  Handle<Context> native_context = isolate->native_context();
   Handle<Object> default_species = isolate->array_function();
-  if (!FLAG_harmony_species) {
-    return default_species;
-  }
   if (original_array->IsJSArray() &&
       Handle<JSArray>::cast(original_array)->HasArrayPrototype(isolate) &&
       isolate->IsArraySpeciesLookupChainIntact()) {
@@ -1580,7 +1841,7 @@
           isolate, constructor_context,
           JSReceiver::GetFunctionRealm(Handle<JSReceiver>::cast(constructor)),
           Object);
-      if (*constructor_context != *native_context &&
+      if (*constructor_context != *isolate->native_context() &&
           *constructor == constructor_context->array_function()) {
         constructor = isolate->factory()->undefined_value();
       }
@@ -1591,12 +1852,12 @@
           JSReceiver::GetProperty(Handle<JSReceiver>::cast(constructor),
                                   isolate->factory()->species_symbol()),
           Object);
-      if (constructor->IsNull()) {
+      if (constructor->IsNull(isolate)) {
         constructor = isolate->factory()->undefined_value();
       }
     }
   }
-  if (constructor->IsUndefined()) {
+  if (constructor->IsUndefined(isolate)) {
     return default_species;
   } else {
     if (!constructor->IsConstructor()) {
@@ -1821,8 +2082,7 @@
   return true;
 }
 
-
-void String::StringShortPrint(StringStream* accumulator) {
+void String::StringShortPrint(StringStream* accumulator, bool show_details) {
   int len = length();
   if (len > kMaxShortPrintLength) {
     accumulator->Add("<Very long string[%u]>", len);
@@ -1851,15 +2111,15 @@
   }
   stream.Reset(this);
   if (one_byte) {
-    accumulator->Add("<String[%u]: ", length());
+    if (show_details) accumulator->Add("<String[%u]: ", length());
     for (int i = 0; i < len; i++) {
       accumulator->Put(static_cast<char>(stream.GetNext()));
     }
-    accumulator->Put('>');
+    if (show_details) accumulator->Put('>');
   } else {
     // Backslash indicates that the string contains control
     // characters and that backslashes are therefore escaped.
-    accumulator->Add("<String[%u]\\: ", length());
+    if (show_details) accumulator->Add("<String[%u]\\: ", length());
     for (int i = 0; i < len; i++) {
       uint16_t c = stream.GetNext();
       if (c == '\n') {
@@ -1879,7 +2139,7 @@
       accumulator->Put('.');
       accumulator->Put('.');
     }
-    accumulator->Put('>');
+    if (show_details) accumulator->Put('>');
   }
   return;
 }
@@ -1897,23 +2157,15 @@
 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
   switch (map()->instance_type()) {
     case JS_ARRAY_TYPE: {
-      double length = JSArray::cast(this)->length()->IsUndefined()
-          ? 0
-          : JSArray::cast(this)->length()->Number();
+      double length = JSArray::cast(this)->length()->IsUndefined(GetIsolate())
+                          ? 0
+                          : JSArray::cast(this)->length()->Number();
       accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
       break;
     }
     case JS_BOUND_FUNCTION_TYPE: {
       JSBoundFunction* bound_function = JSBoundFunction::cast(this);
-      Object* name = bound_function->name();
       accumulator->Add("<JS BoundFunction");
-      if (name->IsString()) {
-        String* str = String::cast(name);
-        if (str->length() > 0) {
-          accumulator->Add(" ");
-          accumulator->Put(str);
-        }
-      }
       accumulator->Add(
           " (BoundTargetFunction %p)>",
           reinterpret_cast<void*>(bound_function->bound_target_function()));
@@ -1946,6 +2198,18 @@
       if (!printed) {
         accumulator->Add("<JS Function");
       }
+      if (FLAG_trace_file_names) {
+        Object* source_name =
+            Script::cast(function->shared()->script())->name();
+        if (source_name->IsString()) {
+          String* str = String::cast(source_name);
+          if (str->length() > 0) {
+            accumulator->Add(" <");
+            accumulator->Put(str);
+            accumulator->Add(">");
+          }
+        }
+      }
       accumulator->Add(" (SharedFunctionInfo %p)",
                        reinterpret_cast<void*>(function->shared()));
       accumulator->Put('>');
@@ -2131,6 +2395,7 @@
 
 void HeapObject::HeapObjectShortPrint(std::ostream& os) {  // NOLINT
   Heap* heap = GetHeap();
+  Isolate* isolate = heap->isolate();
   if (!heap->Contains(this)) {
     os << "!!!INVALID POINTER!!!";
     return;
@@ -2216,18 +2481,20 @@
       break;
     }
     case ODDBALL_TYPE: {
-      if (IsUndefined()) {
+      if (IsUndefined(isolate)) {
         os << "<undefined>";
-      } else if (IsTheHole()) {
+      } else if (IsTheHole(isolate)) {
         os << "<the hole>";
-      } else if (IsNull()) {
+      } else if (IsNull(isolate)) {
         os << "<null>";
-      } else if (IsTrue()) {
+      } else if (IsTrue(isolate)) {
         os << "<true>";
-      } else if (IsFalse()) {
+      } else if (IsFalse(isolate)) {
         os << "<false>";
       } else {
-        os << "<Odd Oddball>";
+        os << "<Odd Oddball: ";
+        os << Oddball::cast(this)->to_string()->ToCString().get();
+        os << ">";
       }
       break;
     }
@@ -2458,25 +2725,6 @@
 }
 
 
-MaybeHandle<String> JSReceiver::BuiltinStringTag(Handle<JSReceiver> object) {
-  Maybe<bool> is_array = Object::IsArray(object);
-  MAYBE_RETURN(is_array, MaybeHandle<String>());
-  Isolate* const isolate = object->GetIsolate();
-  if (is_array.FromJust()) {
-    return isolate->factory()->Array_string();
-  }
-  // TODO(adamk): According to ES2015, we should return "Function" when
-  // object has a [[Call]] internal method (corresponds to IsCallable).
-  // But this is well cemented in layout tests and might cause webbreakage.
-  // if (object->IsCallable()) {
-  //   return isolate->factory()->Function_string();
-  // }
-  // TODO(adamk): class_name() is expensive, replace with instance type
-  // checks where possible.
-  return handle(object->class_name(), isolate);
-}
-
-
 // static
 Handle<String> JSReceiver::GetConstructorName(Handle<JSReceiver> receiver) {
   Isolate* isolate = receiver->GetIsolate();
@@ -2625,8 +2873,9 @@
     } else {
       auto cell = isolate->factory()->NewPropertyCell();
       cell->set_value(*value);
-      auto cell_type = value->IsUndefined() ? PropertyCellType::kUndefined
-                                            : PropertyCellType::kConstant;
+      auto cell_type = value->IsUndefined(isolate)
+                           ? PropertyCellType::kUndefined
+                           : PropertyCellType::kConstant;
       details = details.set_cell_type(cell_type);
       value = cell;
 
@@ -2644,24 +2893,6 @@
 }
 
 
-MaybeHandle<Object> JSObject::EnqueueChangeRecord(Handle<JSObject> object,
-                                                  const char* type_str,
-                                                  Handle<Name> name,
-                                                  Handle<Object> old_value) {
-  DCHECK(!object->IsJSGlobalProxy());
-  DCHECK(!object->IsJSGlobalObject());
-  Isolate* isolate = object->GetIsolate();
-  HandleScope scope(isolate);
-  Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str);
-  Handle<Object> args[] = { type, object, name, old_value };
-  int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;
-
-  return Execution::Call(isolate,
-                         Handle<JSFunction>(isolate->observers_notify_change()),
-                         isolate->factory()->undefined_value(), argc, args);
-}
-
-
 const char* Representation::Mnemonic() const {
   switch (kind_) {
     case kNone: return "v";
@@ -2677,6 +2908,16 @@
   }
 }
 
+bool Map::InstancesNeedRewriting(Map* target) {
+  int target_number_of_fields = target->NumberOfFields();
+  int target_inobject = target->GetInObjectProperties();
+  int target_unused = target->unused_property_fields();
+  int old_number_of_fields;
+
+  return InstancesNeedRewriting(target, target_number_of_fields,
+                                target_inobject, target_unused,
+                                &old_number_of_fields);
+}
 
 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
                                  int target_inobject, int target_unused,
@@ -2717,7 +2958,6 @@
 void JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map,
                                                Handle<Map> new_map,
                                                Isolate* isolate) {
-  if (!FLAG_track_prototype_users) return;
   if (!old_map->is_prototype_map()) return;
   DCHECK(new_map->is_prototype_map());
   bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate);
@@ -3114,7 +3354,7 @@
       // Ensure that no transition was inserted for prototype migrations.
       DCHECK_EQ(
           0, TransitionArray::NumberOfTransitions(old_map->raw_transitions()));
-      DCHECK(new_map->GetBackPointer()->IsUndefined());
+      DCHECK(new_map->GetBackPointer()->IsUndefined(new_map->GetIsolate()));
     }
   } else {
     MigrateFastToSlow(object, new_map, expected_additional_properties);
@@ -3137,10 +3377,10 @@
   return result;
 }
 
-
 Handle<Map> Map::CopyGeneralizeAllRepresentations(
-    Handle<Map> map, int modify_index, StoreMode store_mode, PropertyKind kind,
-    PropertyAttributes attributes, const char* reason) {
+    Handle<Map> map, ElementsKind elements_kind, int modify_index,
+    StoreMode store_mode, PropertyKind kind, PropertyAttributes attributes,
+    const char* reason) {
   Isolate* isolate = map->GetIsolate();
   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
@@ -3196,6 +3436,7 @@
           MaybeHandle<Object>());
     }
   }
+  new_map->set_elements_kind(elements_kind);
   return new_map;
 }
 
@@ -3225,17 +3466,18 @@
 // proper sharing of descriptor arrays.
 void Map::ReplaceDescriptors(DescriptorArray* new_descriptors,
                              LayoutDescriptor* new_layout_descriptor) {
+  Isolate* isolate = GetIsolate();
   // Don't overwrite the empty descriptor array or initial map's descriptors.
-  if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined()) {
+  if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined(isolate)) {
     return;
   }
 
   DescriptorArray* to_replace = instance_descriptors();
-  GetHeap()->incremental_marking()->IterateBlackObject(to_replace);
+  isolate->heap()->incremental_marking()->IterateBlackObject(to_replace);
   Map* current = this;
   while (current->instance_descriptors() == to_replace) {
     Object* next = current->GetBackPointer();
-    if (next->IsUndefined()) break;  // Stop overwriting at initial map.
+    if (next->IsUndefined(isolate)) break;  // Stop overwriting at initial map.
     current->SetEnumLength(kInvalidEnumCacheSentinel);
     current->UpdateDescriptors(new_descriptors, new_layout_descriptor);
     current = Map::cast(next);
@@ -3246,9 +3488,10 @@
 
 Map* Map::FindRootMap() {
   Map* result = this;
+  Isolate* isolate = GetIsolate();
   while (true) {
     Object* back = result->GetBackPointer();
-    if (back->IsUndefined()) {
+    if (back->IsUndefined(isolate)) {
       // Initial map always owns descriptors and doesn't have unused entries
       // in the descriptor array.
       DCHECK(result->owns_descriptors());
@@ -3306,9 +3549,10 @@
   DisallowHeapAllocation no_allocation;
   DCHECK_EQ(DATA, instance_descriptors()->GetDetails(descriptor).type());
   Map* result = this;
+  Isolate* isolate = GetIsolate();
   while (true) {
     Object* back = result->GetBackPointer();
-    if (back->IsUndefined()) break;
+    if (back->IsUndefined(isolate)) break;
     Map* parent = Map::cast(back);
     if (parent->NumberOfOwnDescriptors() <= descriptor) break;
     result = parent;
@@ -3448,9 +3692,9 @@
   }
 }
 
-
-// Reconfigures property at |modify_index| with |new_kind|, |new_attributes|,
-// |store_mode| and/or |new_representation|/|new_field_type|.
+// Reconfigures elements kind to |new_elements_kind| and/or property at
+// |modify_index| with |new_kind|, |new_attributes|, |store_mode| and/or
+// |new_representation|/|new_field_type|.
 // If |modify_index| is negative then no properties are reconfigured but the
 // map is migrated to the up-to-date non-deprecated state.
 //
@@ -3460,6 +3704,7 @@
 // any potential new (partial) version of the type in the transition tree.
 // To do this, on each rewrite:
 // - Search the root of the transition tree using FindRootMap.
+// - Find/create a |root_map| with requested |new_elements_kind|.
 // - Find |target_map|, the newest matching version of this map using the
 //   virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at
 //   |modify_index| is considered to be of |new_kind| and having
@@ -3475,12 +3720,13 @@
 //   Return it.
 // - Otherwise, invalidate the outdated transition target from |target_map|, and
 //   replace its transition tree with a new branch for the updated descriptors.
-Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index,
-                                     PropertyKind new_kind,
-                                     PropertyAttributes new_attributes,
-                                     Representation new_representation,
-                                     Handle<FieldType> new_field_type,
-                                     StoreMode store_mode) {
+Handle<Map> Map::Reconfigure(Handle<Map> old_map,
+                             ElementsKind new_elements_kind, int modify_index,
+                             PropertyKind new_kind,
+                             PropertyAttributes new_attributes,
+                             Representation new_representation,
+                             Handle<FieldType> new_field_type,
+                             StoreMode store_mode) {
   DCHECK_NE(kAccessor, new_kind);  // TODO(ishell): not supported yet.
   DCHECK(store_mode != FORCE_FIELD || modify_index >= 0);
   Isolate* isolate = old_map->GetIsolate();
@@ -3495,7 +3741,8 @@
   // uninitialized value for representation None can be overwritten by both
   // smi and tagged values. Doubles, however, would require a box allocation.
   if (modify_index >= 0 && !new_representation.IsNone() &&
-      !new_representation.IsDouble()) {
+      !new_representation.IsDouble() &&
+      old_map->elements_kind() == new_elements_kind) {
     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
     Representation old_representation = old_details.representation();
 
@@ -3528,38 +3775,39 @@
   // Check the state of the root map.
   Handle<Map> root_map(old_map->FindRootMap(), isolate);
   if (!old_map->EquivalentToForTransition(*root_map)) {
-    return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
-                                            new_kind, new_attributes,
-                                            "GenAll_NotEquivalent");
+    return CopyGeneralizeAllRepresentations(
+        old_map, new_elements_kind, modify_index, store_mode, new_kind,
+        new_attributes, "GenAll_NotEquivalent");
   }
 
   ElementsKind from_kind = root_map->elements_kind();
-  ElementsKind to_kind = old_map->elements_kind();
+  ElementsKind to_kind = new_elements_kind;
   // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
   if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
+      to_kind != SLOW_STRING_WRAPPER_ELEMENTS &&
       to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS &&
       !(IsTransitionableFastElementsKind(from_kind) &&
         IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
-    return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
-                                            new_kind, new_attributes,
-                                            "GenAll_InvalidElementsTransition");
+    return CopyGeneralizeAllRepresentations(
+        old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
+        "GenAll_InvalidElementsTransition");
   }
   int root_nof = root_map->NumberOfOwnDescriptors();
   if (modify_index >= 0 && modify_index < root_nof) {
     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
     if (old_details.kind() != new_kind ||
         old_details.attributes() != new_attributes) {
-      return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
-                                              new_kind, new_attributes,
-                                              "GenAll_RootModification1");
+      return CopyGeneralizeAllRepresentations(
+          old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
+          "GenAll_RootModification1");
     }
     if ((old_details.type() != DATA && store_mode == FORCE_FIELD) ||
         (old_details.type() == DATA &&
          (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
           !new_representation.fits_into(old_details.representation())))) {
-      return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
-                                              new_kind, new_attributes,
-                                              "GenAll_RootModification2");
+      return CopyGeneralizeAllRepresentations(
+          old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
+          "GenAll_RootModification2");
     }
   }
 
@@ -3613,9 +3861,9 @@
     if (next_kind == kAccessor &&
         !EqualImmutableValues(old_descriptors->GetValue(i),
                               tmp_descriptors->GetValue(i))) {
-      return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
-                                              new_kind, new_attributes,
-                                              "GenAll_Incompatible");
+      return CopyGeneralizeAllRepresentations(
+          old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
+          "GenAll_Incompatible");
     }
     if (next_location == kField && tmp_details.location() == kDescriptor) break;
 
@@ -3708,9 +3956,9 @@
     if (next_kind == kAccessor &&
         !EqualImmutableValues(old_descriptors->GetValue(i),
                               tmp_descriptors->GetValue(i))) {
-      return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
-                                              new_kind, new_attributes,
-                                              "GenAll_Incompatible");
+      return CopyGeneralizeAllRepresentations(
+          old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
+          "GenAll_Incompatible");
     }
     DCHECK(!tmp_map->is_deprecated());
     target_map = tmp_map;
@@ -3941,9 +4189,9 @@
   // could be inserted regardless of whether transitions array is full or not.
   if (maybe_transition == NULL &&
       !TransitionArray::CanHaveMoreTransitions(split_map)) {
-    return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
-                                            new_kind, new_attributes,
-                                            "GenAll_CantHaveMoreTransitions");
+    return CopyGeneralizeAllRepresentations(
+        old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
+        "GenAll_CantHaveMoreTransitions");
   }
 
   old_map->NotifyLeafMapLayoutChange();
@@ -4024,18 +4272,27 @@
     if (root_map == NULL) return MaybeHandle<Map>();
     // From here on, use the map with correct elements kind as root map.
   }
-  int root_nof = root_map->NumberOfOwnDescriptors();
+  Map* new_map = root_map->TryReplayPropertyTransitions(*old_map);
+  if (new_map == nullptr) return MaybeHandle<Map>();
+  return handle(new_map);
+}
+
+Map* Map::TryReplayPropertyTransitions(Map* old_map) {
+  DisallowHeapAllocation no_allocation;
+  DisallowDeoptimization no_deoptimization(GetIsolate());
+
+  int root_nof = NumberOfOwnDescriptors();
 
   int old_nof = old_map->NumberOfOwnDescriptors();
   DescriptorArray* old_descriptors = old_map->instance_descriptors();
 
-  Map* new_map = root_map;
+  Map* new_map = this;
   for (int i = root_nof; i < old_nof; ++i) {
     PropertyDetails old_details = old_descriptors->GetDetails(i);
     Map* transition = TransitionArray::SearchTransition(
         new_map, old_details.kind(), old_descriptors->GetKey(i),
         old_details.attributes());
-    if (transition == NULL) return MaybeHandle<Map>();
+    if (transition == NULL) return nullptr;
     new_map = transition;
     DescriptorArray* new_descriptors = new_map->instance_descriptors();
 
@@ -4043,7 +4300,7 @@
     DCHECK_EQ(old_details.kind(), new_details.kind());
     DCHECK_EQ(old_details.attributes(), new_details.attributes());
     if (!old_details.representation().fits_into(new_details.representation())) {
-      return MaybeHandle<Map>();
+      return nullptr;
     }
     switch (new_details.type()) {
       case DATA: {
@@ -4051,20 +4308,20 @@
         // Cleared field types need special treatment. They represent lost
         // knowledge, so we must first generalize the new_type to "Any".
         if (FieldTypeIsCleared(new_details.representation(), new_type)) {
-          return MaybeHandle<Map>();
+          return nullptr;
         }
         PropertyType old_property_type = old_details.type();
         if (old_property_type == DATA) {
           FieldType* old_type = old_descriptors->GetFieldType(i);
           if (FieldTypeIsCleared(old_details.representation(), old_type) ||
               !old_type->NowIs(new_type)) {
-            return MaybeHandle<Map>();
+            return nullptr;
           }
         } else {
           DCHECK(old_property_type == DATA_CONSTANT);
           Object* old_value = old_descriptors->GetValue(i);
           if (!new_type->NowContains(old_value)) {
-            return MaybeHandle<Map>();
+            return nullptr;
           }
         }
         break;
@@ -4082,14 +4339,14 @@
         Object* old_value = old_descriptors->GetValue(i);
         Object* new_value = new_descriptors->GetValue(i);
         if (old_details.location() == kField || old_value != new_value) {
-          return MaybeHandle<Map>();
+          return nullptr;
         }
         break;
       }
     }
   }
-  if (new_map->NumberOfOwnDescriptors() != old_nof) return MaybeHandle<Map>();
-  return handle(new_map);
+  if (new_map->NumberOfOwnDescriptors() != old_nof) return nullptr;
+  return new_map;
 }
 
 
@@ -4101,56 +4358,14 @@
                              ALLOW_IN_DESCRIPTOR);
 }
 
-
 Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
                                                  ShouldThrow should_throw,
                                                  Handle<Object> value) {
-  Isolate* isolate = it->isolate();
-  // Make sure that the top context does not change when doing callbacks or
-  // interceptor calls.
-  AssertNoContextChange ncc(isolate);
-
   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
-  Handle<InterceptorInfo> interceptor(it->GetInterceptor());
-  if (interceptor->setter()->IsUndefined()) return Just(false);
-
-  Handle<JSObject> holder = it->GetHolder<JSObject>();
-  bool result;
-  Handle<Object> receiver = it->GetReceiver();
-  if (!receiver->IsJSReceiver()) {
-    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
-                                     Object::ConvertReceiver(isolate, receiver),
-                                     Nothing<bool>());
-  }
-  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
-                                 *holder, should_throw);
-
-  if (it->IsElement()) {
-    uint32_t index = it->index();
-    v8::IndexedPropertySetterCallback setter =
-        v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
-    // TODO(neis): In the future, we may want to actually return the
-    // interceptor's result, which then should be a boolean.
-    result = !args.Call(setter, index, value).is_null();
-  } else {
-    Handle<Name> name = it->name();
-    DCHECK(!name->IsPrivate());
-
-    if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
-      return Just(false);
-    }
-
-    v8::GenericNamedPropertySetterCallback setter =
-        v8::ToCData<v8::GenericNamedPropertySetterCallback>(
-            interceptor->setter());
-    result = !args.Call(setter, name, value).is_null();
-  }
-
-  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
-  return Just(result);
+  return SetPropertyWithInterceptorInternal(it, it->GetInterceptor(),
+                                            should_throw, value);
 }
 
-
 MaybeHandle<Object> Object::SetProperty(Handle<Object> object,
                                         Handle<Name> name, Handle<Object> value,
                                         LanguageMode language_mode,
@@ -4166,6 +4381,7 @@
                                         LanguageMode language_mode,
                                         StoreFromKeyed store_mode,
                                         bool* found) {
+  it->UpdateProtector();
   DCHECK(it->IsFound());
   ShouldThrow should_throw =
       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
@@ -4190,23 +4406,42 @@
         return JSProxy::SetProperty(it->GetHolder<JSProxy>(), it->GetName(),
                                     value, it->GetReceiver(), language_mode);
 
-      case LookupIterator::INTERCEPTOR:
+      case LookupIterator::INTERCEPTOR: {
+        Handle<Map> store_target_map;
+        if (it->GetReceiver()->IsJSObject()) {
+          store_target_map = handle(it->GetStoreTarget()->map(), it->isolate());
+        }
         if (it->HolderIsReceiverOrHiddenPrototype()) {
           Maybe<bool> result =
               JSObject::SetPropertyWithInterceptor(it, should_throw, value);
           if (result.IsNothing() || result.FromJust()) return result;
+          // Interceptor modified the store target but failed to set the
+          // property.
+          Utils::ApiCheck(store_target_map.is_null() ||
+                              *store_target_map == it->GetStoreTarget()->map(),
+                          it->IsElement() ? "v8::IndexedPropertySetterCallback"
+                                          : "v8::NamedPropertySetterCallback",
+                          "Interceptor silently changed store target.");
         } else {
           Maybe<PropertyAttributes> maybe_attributes =
               JSObject::GetPropertyAttributesWithInterceptor(it);
           if (!maybe_attributes.IsJust()) return Nothing<bool>();
-          if (maybe_attributes.FromJust() == ABSENT) break;
           if ((maybe_attributes.FromJust() & READ_ONLY) != 0) {
             return WriteToReadOnlyProperty(it, value, should_throw);
           }
+          // Interceptor modified the store target but failed to set the
+          // property.
+          Utils::ApiCheck(store_target_map.is_null() ||
+                              *store_target_map == it->GetStoreTarget()->map(),
+                          it->IsElement() ? "v8::IndexedPropertySetterCallback"
+                                          : "v8::NamedPropertySetterCallback",
+                          "Interceptor silently changed store target.");
+          if (maybe_attributes.FromJust() == ABSENT) break;
           *found = false;
           return Nothing<bool>();
         }
         break;
+      }
 
       case LookupIterator::ACCESSOR: {
         if (it->IsReadOnly()) {
@@ -4248,7 +4483,6 @@
 Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value,
                                 LanguageMode language_mode,
                                 StoreFromKeyed store_mode) {
-  it->UpdateProtector();
   if (it->IsFound()) {
     bool found = true;
     Maybe<bool> result =
@@ -4276,7 +4510,6 @@
                                      StoreFromKeyed store_mode) {
   Isolate* isolate = it->isolate();
 
-  it->UpdateProtector();
   if (it->IsFound()) {
     bool found = true;
     Maybe<bool> result =
@@ -4284,6 +4517,8 @@
     if (found) return result;
   }
 
+  it->UpdateProtector();
+
   // The property either doesn't exist on the holder or exists there as a data
   // property.
 
@@ -4295,7 +4530,7 @@
   }
   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
 
-  LookupIterator::Configuration c = LookupIterator::HIDDEN;
+  LookupIterator::Configuration c = LookupIterator::OWN;
   LookupIterator own_lookup =
       it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c)
                       : LookupIterator(receiver, it->name(), c);
@@ -4419,18 +4654,10 @@
   // Store on the holder which may be hidden behind the receiver.
   DCHECK(it->HolderIsReceiverOrHiddenPrototype());
 
-  // Old value for the observation change record.
-  // Fetch before transforming the object since the encoding may become
-  // incompatible with what's cached in |it|.
-  bool is_observed = receiver->map()->is_observed() &&
-                     (it->IsElement() || !it->name()->IsPrivate());
-  MaybeHandle<Object> maybe_old;
-  if (is_observed) maybe_old = it->GetDataValue();
-
   Handle<Object> to_assign = value;
   // Convert the incoming value to a number for storing into typed arrays.
   if (it->IsElement() && receiver->HasFixedTypedArrayElements()) {
-    if (!value->IsNumber() && !value->IsUndefined()) {
+    if (!value->IsNumber() && !value->IsUndefined(it->isolate())) {
       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
           it->isolate(), to_assign, Object::ToNumber(value), Nothing<bool>());
       // We have to recheck the length. However, it can only change if the
@@ -4449,15 +4676,6 @@
   // Write the property value.
   it->WriteDataValue(to_assign);
 
-  // Send the change record if there are observers.
-  if (is_observed && !value->SameValue(*maybe_old.ToHandleChecked())) {
-    RETURN_ON_EXCEPTION_VALUE(
-        it->isolate(),
-        JSObject::EnqueueChangeRecord(receiver, "update", it->GetName(),
-                                      maybe_old.ToHandleChecked()),
-        Nothing<bool>());
-  }
-
 #if VERIFY_HEAP
   if (FLAG_verify_heap) {
     receiver->JSObjectVerify();
@@ -4467,47 +4685,6 @@
 }
 
 
-MUST_USE_RESULT static MaybeHandle<Object> BeginPerformSplice(
-    Handle<JSArray> object) {
-  Isolate* isolate = object->GetIsolate();
-  HandleScope scope(isolate);
-  Handle<Object> args[] = {object};
-
-  return Execution::Call(
-      isolate, Handle<JSFunction>(isolate->observers_begin_perform_splice()),
-      isolate->factory()->undefined_value(), arraysize(args), args);
-}
-
-
-MUST_USE_RESULT static MaybeHandle<Object> EndPerformSplice(
-    Handle<JSArray> object) {
-  Isolate* isolate = object->GetIsolate();
-  HandleScope scope(isolate);
-  Handle<Object> args[] = {object};
-
-  return Execution::Call(
-      isolate, Handle<JSFunction>(isolate->observers_end_perform_splice()),
-      isolate->factory()->undefined_value(), arraysize(args), args);
-}
-
-
-MUST_USE_RESULT static MaybeHandle<Object> EnqueueSpliceRecord(
-    Handle<JSArray> object, uint32_t index, Handle<JSArray> deleted,
-    uint32_t add_count) {
-  Isolate* isolate = object->GetIsolate();
-  HandleScope scope(isolate);
-  Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
-  Handle<Object> add_count_object =
-      isolate->factory()->NewNumberFromUint(add_count);
-
-  Handle<Object> args[] = {object, index_object, deleted, add_count_object};
-
-  return Execution::Call(
-      isolate, Handle<JSFunction>(isolate->observers_enqueue_splice()),
-      isolate->factory()->undefined_value(), arraysize(args), args);
-}
-
-
 Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
                                     PropertyAttributes attributes,
                                     ShouldThrow should_throw,
@@ -4562,6 +4739,7 @@
     JSObject::ValidateElements(receiver);
     return result;
   } else {
+    it->UpdateProtector();
     // Migrate to the most up-to-date map that will be able to store |value|
     // under it->name() with |attributes|.
     it->PrepareTransitionToDataProperty(receiver, value, attributes,
@@ -4578,13 +4756,6 @@
       it->WriteDataValue(value);
     }
 
-    // Send the change record if there are observers.
-    if (receiver->map()->is_observed() && !it->name()->IsPrivate()) {
-      RETURN_ON_EXCEPTION_VALUE(isolate, JSObject::EnqueueChangeRecord(
-                                             receiver, "add", it->name(),
-                                             it->factory()->the_hole_value()),
-                                Nothing<bool>());
-    }
 #if VERIFY_HEAP
     if (FLAG_verify_heap) {
       receiver->JSObjectVerify();
@@ -4625,13 +4796,14 @@
     new_descriptors->CopyEnumCacheFrom(*descriptors);
   }
 
+  Isolate* isolate = map->GetIsolate();
   // Replace descriptors by new_descriptors in all maps that share it.
-  map->GetHeap()->incremental_marking()->IterateBlackObject(*descriptors);
+  isolate->heap()->incremental_marking()->IterateBlackObject(*descriptors);
 
   Map* current = *map;
   while (current->instance_descriptors() == *descriptors) {
     Object* next = current->GetBackPointer();
-    if (next->IsUndefined()) break;  // Stop overwriting at initial map.
+    if (next->IsUndefined(isolate)) break;  // Stop overwriting at initial map.
     current->UpdateDescriptors(*new_descriptors, layout_descriptor);
     current = Map::cast(next);
   }
@@ -4745,17 +4917,30 @@
   return false;
 }
 
+Map* Map::FindElementsKindTransitionedMap(MapHandleList* candidates) {
+  DisallowHeapAllocation no_allocation;
+  DisallowDeoptimization no_deoptimization(GetIsolate());
 
-Handle<Map> Map::FindTransitionedMap(Handle<Map> map,
-                                     MapHandleList* candidates) {
-  ElementsKind kind = map->elements_kind();
+  ElementsKind kind = elements_kind();
   bool packed = IsFastPackedElementsKind(kind);
 
   Map* transition = nullptr;
   if (IsTransitionableFastElementsKind(kind)) {
-    for (Map* current = map->ElementsTransitionMap();
-         current != nullptr && current->has_fast_elements();
-         current = current->ElementsTransitionMap()) {
+    // Check the state of the root map.
+    Map* root_map = FindRootMap();
+    if (!EquivalentToForTransition(root_map)) return nullptr;
+    root_map = root_map->LookupElementsTransitionMap(kind);
+    DCHECK_NOT_NULL(root_map);
+    // Starting from the next existing elements kind transition try to
+    // replay the property transitions that does not involve instance rewriting
+    // (ElementsTransitionAndStoreStub does not support that).
+    for (root_map = root_map->ElementsTransitionMap();
+         root_map != nullptr && root_map->has_fast_elements();
+         root_map = root_map->ElementsTransitionMap()) {
+      Map* current = root_map->TryReplayPropertyTransitions(this);
+      if (current == nullptr) continue;
+      if (InstancesNeedRewriting(current)) continue;
+
       if (ContainsMap(candidates, current) &&
           (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
         transition = current;
@@ -4763,11 +4948,14 @@
       }
     }
   }
-  return transition == nullptr ? Handle<Map>() : handle(transition);
+  return transition;
 }
 
 
 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
+  // Ensure we are requested to search elements kind transition "near the root".
+  DCHECK_EQ(map->FindRootMap()->NumberOfOwnDescriptors(),
+            map->NumberOfOwnDescriptors());
   Map* current_map = map;
 
   ElementsKind kind = map->elements_kind();
@@ -4875,7 +5063,7 @@
     }
   }
 
-  DCHECK(!map->IsUndefined());
+  DCHECK(!map->IsUndefined(isolate));
   // Check if we can go back in the elements kind transition chain.
   if (IsHoleyElementsKind(from_kind) &&
       to_kind == GetPackedElementsKind(from_kind) &&
@@ -4896,7 +5084,7 @@
     return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
   }
 
-  return Map::AsElementsKind(map, to_kind);
+  return Map::ReconfigureElementsKind(map, to_kind);
 }
 
 
@@ -4929,7 +5117,7 @@
 Maybe<bool> JSProxy::HasProperty(Isolate* isolate, Handle<JSProxy> proxy,
                                  Handle<Name> name) {
   DCHECK(!name->IsPrivate());
-  STACK_CHECK(Nothing<bool>());
+  STACK_CHECK(isolate, Nothing<bool>());
   // 1. (Assert)
   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   Handle<Object> handler(proxy->handler(), isolate);
@@ -4949,7 +5137,7 @@
                                        isolate->factory()->has_string()),
       Nothing<bool>());
   // 7. If trap is undefined, then
-  if (trap->IsUndefined()) {
+  if (trap->IsUndefined(isolate)) {
     // 7a. Return target.[[HasProperty]](P).
     return JSReceiver::HasProperty(target, name);
   }
@@ -4998,7 +5186,7 @@
                                  LanguageMode language_mode) {
   DCHECK(!name->IsPrivate());
   Isolate* isolate = proxy->GetIsolate();
-  STACK_CHECK(Nothing<bool>());
+  STACK_CHECK(isolate, Nothing<bool>());
   Factory* factory = isolate->factory();
   Handle<String> trap_name = factory->set_string();
   ShouldThrow should_throw =
@@ -5015,7 +5203,7 @@
   Handle<Object> trap;
   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
-  if (trap->IsUndefined()) {
+  if (trap->IsUndefined(isolate)) {
     LookupIterator it =
         LookupIterator::PropertyOrElement(isolate, receiver, name, target);
     return Object::SetSuperProperty(&it, value, language_mode,
@@ -5051,7 +5239,7 @@
     }
     inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
                    !target_desc.configurable() &&
-                   target_desc.set()->IsUndefined();
+                   target_desc.set()->IsUndefined(isolate);
     if (inconsistent) {
       isolate->Throw(*isolate->factory()->NewTypeError(
           MessageTemplate::kProxySetFrozenAccessor, name));
@@ -5069,7 +5257,7 @@
   ShouldThrow should_throw =
       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   Isolate* isolate = proxy->GetIsolate();
-  STACK_CHECK(Nothing<bool>());
+  STACK_CHECK(isolate, Nothing<bool>());
   Factory* factory = isolate->factory();
   Handle<String> trap_name = factory->deleteProperty_string();
 
@@ -5084,7 +5272,7 @@
   Handle<Object> trap;
   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
-  if (trap->IsUndefined()) {
+  if (trap->IsUndefined(isolate)) {
     return JSReceiver::DeletePropertyOrElement(target, name, language_mode);
   }
 
@@ -5160,6 +5348,44 @@
       handle(function->bound_target_function()));
 }
 
+// static
+MaybeHandle<String> JSBoundFunction::GetName(Isolate* isolate,
+                                             Handle<JSBoundFunction> function) {
+  Handle<String> prefix = isolate->factory()->bound__string();
+  if (!function->bound_target_function()->IsJSFunction()) return prefix;
+  Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()),
+                            isolate);
+  Handle<Object> target_name = JSFunction::GetName(isolate, target);
+  if (!target_name->IsString()) return prefix;
+  Factory* factory = isolate->factory();
+  return factory->NewConsString(prefix, Handle<String>::cast(target_name));
+}
+
+// static
+Handle<Object> JSFunction::GetName(Isolate* isolate,
+                                   Handle<JSFunction> function) {
+  if (function->shared()->name_should_print_as_anonymous()) {
+    return isolate->factory()->anonymous_string();
+  }
+  return handle(function->shared()->name(), isolate);
+}
+
+// static
+MaybeHandle<Smi> JSFunction::GetLength(Isolate* isolate,
+                                       Handle<JSFunction> function) {
+  int length = 0;
+  if (function->shared()->is_compiled()) {
+    length = function->shared()->length();
+  } else {
+    // If the function isn't compiled yet, the length is not computed
+    // correctly yet. Compile it now and return the right length.
+    if (Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) {
+      length = function->shared()->length();
+    }
+    if (isolate->has_pending_exception()) return MaybeHandle<Smi>();
+  }
+  return handle(Smi::FromInt(length), isolate);
+}
 
 // static
 Handle<Context> JSFunction::GetFunctionRealm(Handle<JSFunction> function) {
@@ -5220,7 +5446,7 @@
     } else {
       TransitionElementsKind(object, to_kind);
     }
-    map = Map::AsElementsKind(map, to_kind);
+    map = Map::ReconfigureElementsKind(map, to_kind);
   }
   JSObject::MigrateToMap(object, map);
 }
@@ -5302,8 +5528,6 @@
     ShouldThrow should_throw, AccessorInfoHandling handling) {
   it->UpdateProtector();
   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
-  bool is_observed = object->map()->is_observed() &&
-                     (it->IsElement() || !it->name()->IsPrivate());
 
   for (; it->IsFound(); it->Next()) {
     switch (it->state()) {
@@ -5363,14 +5587,6 @@
           it->ReconfigureDataProperty(value, attributes);
         }
 
-        if (is_observed) {
-          RETURN_ON_EXCEPTION_VALUE(
-              it->isolate(),
-              EnqueueChangeRecord(object, "reconfigure", it->GetName(),
-                                  it->factory()->the_hole_value()),
-              Nothing<bool>());
-        }
-
         return Just(true);
       }
       case LookupIterator::INTEGER_INDEXED_EXOTIC:
@@ -5391,20 +5607,8 @@
         }
 
         // Reconfigure the data property if the attributes mismatch.
-        Handle<Object> old_value = it->factory()->the_hole_value();
-        if (is_observed) old_value = it->GetDataValue();
-
         it->ReconfigureDataProperty(value, attributes);
 
-        if (is_observed) {
-          if (old_value->SameValue(*value)) {
-            old_value = it->factory()->the_hole_value();
-          }
-          RETURN_ON_EXCEPTION_VALUE(
-              it->isolate(), EnqueueChangeRecord(object, "reconfigure",
-                                                 it->GetName(), old_value),
-              Nothing<bool>());
-        }
         return Just(true);
       }
     }
@@ -5417,7 +5621,7 @@
 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
     Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
     PropertyAttributes attributes) {
-  DCHECK(!value->IsTheHole());
+  DCHECK(!value->IsTheHole(object->GetIsolate()));
   LookupIterator it(object, name, object, LookupIterator::OWN);
   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
 }
@@ -5439,73 +5643,11 @@
   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
 }
 
-
 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
     LookupIterator* it) {
-  Isolate* isolate = it->isolate();
-  // Make sure that the top context does not change when doing
-  // callbacks or interceptor calls.
-  AssertNoContextChange ncc(isolate);
-  HandleScope scope(isolate);
-
-  Handle<JSObject> holder = it->GetHolder<JSObject>();
-  Handle<InterceptorInfo> interceptor(it->GetInterceptor());
-  if (!it->IsElement() && it->name()->IsSymbol() &&
-      !interceptor->can_intercept_symbols()) {
-    return Just(ABSENT);
-  }
-  Handle<Object> receiver = it->GetReceiver();
-  if (!receiver->IsJSReceiver()) {
-    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
-                                     Object::ConvertReceiver(isolate, receiver),
-                                     Nothing<PropertyAttributes>());
-  }
-  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
-                                 *holder, Object::DONT_THROW);
-  if (!interceptor->query()->IsUndefined()) {
-    Handle<Object> result;
-    if (it->IsElement()) {
-      uint32_t index = it->index();
-      v8::IndexedPropertyQueryCallback query =
-          v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
-      result = args.Call(query, index);
-    } else {
-      Handle<Name> name = it->name();
-      DCHECK(!name->IsPrivate());
-      v8::GenericNamedPropertyQueryCallback query =
-          v8::ToCData<v8::GenericNamedPropertyQueryCallback>(
-              interceptor->query());
-      result = args.Call(query, name);
-    }
-    if (!result.is_null()) {
-      int32_t value;
-      CHECK(result->ToInt32(&value));
-      return Just(static_cast<PropertyAttributes>(value));
-    }
-  } else if (!interceptor->getter()->IsUndefined()) {
-    // TODO(verwaest): Use GetPropertyWithInterceptor?
-    Handle<Object> result;
-    if (it->IsElement()) {
-      uint32_t index = it->index();
-      v8::IndexedPropertyGetterCallback getter =
-          v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
-      result = args.Call(getter, index);
-    } else {
-      Handle<Name> name = it->name();
-      DCHECK(!name->IsPrivate());
-      v8::GenericNamedPropertyGetterCallback getter =
-          v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
-              interceptor->getter());
-      result = args.Call(getter, name);
-    }
-    if (!result.is_null()) return Just(DONT_ENUM);
-  }
-
-  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
-  return Just(ABSENT);
+  return GetPropertyAttributesWithInterceptorInternal(it, it->GetInterceptor());
 }
 
-
 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
     LookupIterator* it) {
   for (; it->IsFound(); it->Next()) {
@@ -5620,7 +5762,7 @@
   // Compute the length of the instance descriptor.
   for (int i = 0; i < instance_descriptor_length; i++) {
     int index = Smi::cast(iteration_order->get(i))->value();
-    DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
+    DCHECK(dictionary->IsKey(isolate, dictionary->KeyAt(index)));
 
     Object* value = dictionary->ValueAt(index);
     PropertyType type = dictionary->DetailsAt(index).type();
@@ -5836,216 +5978,56 @@
   return Smi::FromInt(hash_value);
 }
 
+template <typename ProxyType>
+static Smi* GetOrCreateIdentityHashHelper(Isolate* isolate,
+                                          Handle<ProxyType> proxy) {
+  Object* maybe_hash = proxy->hash();
+  if (maybe_hash->IsSmi()) return Smi::cast(maybe_hash);
 
-template<typename ProxyType>
-static Handle<Smi> GetOrCreateIdentityHashHelper(Handle<ProxyType> proxy) {
-  Isolate* isolate = proxy->GetIsolate();
-
-  Handle<Object> maybe_hash(proxy->hash(), isolate);
-  if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
-
-  Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
-  proxy->set_hash(*hash);
+  Smi* hash = GenerateIdentityHash(isolate);
+  proxy->set_hash(hash);
   return hash;
 }
 
 // static
-Handle<Object> JSObject::GetIdentityHash(Isolate* isolate,
-                                         Handle<JSObject> object) {
+Object* JSObject::GetIdentityHash(Isolate* isolate, Handle<JSObject> object) {
   if (object->IsJSGlobalProxy()) {
-    return handle(JSGlobalProxy::cast(*object)->hash(), isolate);
+    return JSGlobalProxy::cast(*object)->hash();
   }
   Handle<Name> hash_code_symbol = isolate->factory()->hash_code_symbol();
-  return JSReceiver::GetDataProperty(object, hash_code_symbol);
+  return *JSReceiver::GetDataProperty(object, hash_code_symbol);
 }
 
 // static
-Handle<Smi> JSObject::GetOrCreateIdentityHash(Handle<JSObject> object) {
+Smi* JSObject::GetOrCreateIdentityHash(Isolate* isolate,
+                                       Handle<JSObject> object) {
   if (object->IsJSGlobalProxy()) {
-    return GetOrCreateIdentityHashHelper(Handle<JSGlobalProxy>::cast(object));
+    return GetOrCreateIdentityHashHelper(isolate,
+                                         Handle<JSGlobalProxy>::cast(object));
   }
-  Isolate* isolate = object->GetIsolate();
 
   Handle<Name> hash_code_symbol = isolate->factory()->hash_code_symbol();
   LookupIterator it(object, hash_code_symbol, object, LookupIterator::OWN);
   if (it.IsFound()) {
     DCHECK_EQ(LookupIterator::DATA, it.state());
-    Handle<Object> maybe_hash = it.GetDataValue();
-    if (maybe_hash->IsSmi()) return Handle<Smi>::cast(maybe_hash);
+    Object* maybe_hash = *it.GetDataValue();
+    if (maybe_hash->IsSmi()) return Smi::cast(maybe_hash);
   }
 
-  Handle<Smi> hash(GenerateIdentityHash(isolate), isolate);
-  CHECK(AddDataProperty(&it, hash, NONE, THROW_ON_ERROR,
+  Smi* hash = GenerateIdentityHash(isolate);
+  CHECK(AddDataProperty(&it, handle(hash, isolate), NONE, THROW_ON_ERROR,
                         CERTAINLY_NOT_STORE_FROM_KEYED)
             .IsJust());
   return hash;
 }
 
 // static
-Handle<Object> JSProxy::GetIdentityHash(Isolate* isolate,
-                                        Handle<JSProxy> proxy) {
-  return handle(proxy->hash(), isolate);
+Object* JSProxy::GetIdentityHash(Handle<JSProxy> proxy) {
+  return proxy->hash();
 }
 
-
-Handle<Smi> JSProxy::GetOrCreateIdentityHash(Handle<JSProxy> proxy) {
-  return GetOrCreateIdentityHashHelper(proxy);
-}
-
-
-Object* JSObject::GetHiddenProperty(Handle<Name> key) {
-  DisallowHeapAllocation no_gc;
-  DCHECK(key->IsUniqueName());
-  if (IsJSGlobalProxy()) {
-    // For a proxy, use the prototype as target object.
-    PrototypeIterator iter(GetIsolate(), this);
-    // If the proxy is detached, return undefined.
-    if (iter.IsAtEnd()) return GetHeap()->the_hole_value();
-    DCHECK(iter.GetCurrent()->IsJSGlobalObject());
-    return iter.GetCurrent<JSObject>()->GetHiddenProperty(key);
-  }
-  DCHECK(!IsJSGlobalProxy());
-  Object* inline_value = GetHiddenPropertiesHashTable();
-
-  if (inline_value->IsUndefined()) return GetHeap()->the_hole_value();
-
-  ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
-  Object* entry = hashtable->Lookup(key);
-  return entry;
-}
-
-
-Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object,
-                                           Handle<Name> key,
-                                           Handle<Object> value) {
-  Isolate* isolate = object->GetIsolate();
-
-  DCHECK(key->IsUniqueName());
-  if (object->IsJSGlobalProxy()) {
-    // For a proxy, use the prototype as target object.
-    PrototypeIterator iter(isolate, object);
-    // If the proxy is detached, return undefined.
-    if (iter.IsAtEnd()) return isolate->factory()->undefined_value();
-    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
-    return SetHiddenProperty(PrototypeIterator::GetCurrent<JSObject>(iter), key,
-                             value);
-  }
-  DCHECK(!object->IsJSGlobalProxy());
-
-  Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
-
-  Handle<ObjectHashTable> hashtable =
-      GetOrCreateHiddenPropertiesHashtable(object);
-
-  // If it was found, check if the key is already in the dictionary.
-  Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key,
-                                                           value);
-  if (*new_table != *hashtable) {
-    // If adding the key expanded the dictionary (i.e., Add returned a new
-    // dictionary), store it back to the object.
-    SetHiddenPropertiesHashTable(object, new_table);
-  }
-
-  // Return this to mark success.
-  return object;
-}
-
-
-void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) {
-  Isolate* isolate = object->GetIsolate();
-  DCHECK(key->IsUniqueName());
-
-  if (object->IsJSGlobalProxy()) {
-    PrototypeIterator iter(isolate, object);
-    if (iter.IsAtEnd()) return;
-    DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
-    return DeleteHiddenProperty(PrototypeIterator::GetCurrent<JSObject>(iter),
-                                key);
-  }
-
-  Object* inline_value = object->GetHiddenPropertiesHashTable();
-
-  if (inline_value->IsUndefined()) return;
-
-  Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value));
-  bool was_present = false;
-  ObjectHashTable::Remove(hashtable, key, &was_present);
-}
-
-
-bool JSObject::HasHiddenProperties(Handle<JSObject> object) {
-  Isolate* isolate = object->GetIsolate();
-  Handle<Symbol> hidden = isolate->factory()->hidden_properties_symbol();
-  LookupIterator it(object, hidden, object);
-  Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
-  // Cannot get an exception since the hidden_properties_symbol isn't exposed to
-  // JS.
-  DCHECK(maybe.IsJust());
-  return maybe.FromJust() != ABSENT;
-}
-
-
-Object* JSObject::GetHiddenPropertiesHashTable() {
-  DCHECK(!IsJSGlobalProxy());
-  if (HasFastProperties()) {
-    // If the object has fast properties, check whether the first slot
-    // in the descriptor array matches the hidden string. Since the
-    // hidden strings hash code is zero (and no other name has hash
-    // code zero) it will always occupy the first entry if present.
-    DescriptorArray* descriptors = this->map()->instance_descriptors();
-    if (descriptors->number_of_descriptors() > 0) {
-      int sorted_index = descriptors->GetSortedKeyIndex(0);
-      if (descriptors->GetKey(sorted_index) ==
-              GetHeap()->hidden_properties_symbol() &&
-          sorted_index < map()->NumberOfOwnDescriptors()) {
-        DCHECK(descriptors->GetType(sorted_index) == DATA);
-        DCHECK(descriptors->GetDetails(sorted_index).representation().
-               IsCompatibleForLoad(Representation::Tagged()));
-        FieldIndex index = FieldIndex::ForDescriptor(this->map(),
-                                                     sorted_index);
-        return this->RawFastPropertyAt(index);
-      } else {
-        return GetHeap()->undefined_value();
-      }
-    } else {
-      return GetHeap()->undefined_value();
-    }
-  } else {
-    Isolate* isolate = GetIsolate();
-    Handle<Symbol> hidden = isolate->factory()->hidden_properties_symbol();
-    Handle<JSObject> receiver(this, isolate);
-    LookupIterator it(receiver, hidden, receiver);
-    // Access check is always skipped for the hidden string anyways.
-    return *GetDataProperty(&it);
-  }
-}
-
-Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable(
-    Handle<JSObject> object) {
-  Isolate* isolate = object->GetIsolate();
-
-  static const int kInitialCapacity = 4;
-  Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
-  if (inline_value->IsHashTable()) {
-    return Handle<ObjectHashTable>::cast(inline_value);
-  }
-
-  Handle<ObjectHashTable> hashtable = ObjectHashTable::New(
-      isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY);
-
-  DCHECK(inline_value->IsUndefined());
-  SetHiddenPropertiesHashTable(object, hashtable);
-  return hashtable;
-}
-
-
-Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object,
-                                                      Handle<Object> value) {
-  DCHECK(!object->IsJSGlobalProxy());
-  Isolate* isolate = object->GetIsolate();
-  Handle<Symbol> name = isolate->factory()->hidden_properties_symbol();
-  SetOwnPropertyIgnoreAttributes(object, name, value, DONT_ENUM).Assert();
-  return object;
+Smi* JSProxy::GetOrCreateIdentityHash(Isolate* isolate, Handle<JSProxy> proxy) {
+  return GetOrCreateIdentityHashHelper(isolate, proxy);
 }
 
 
@@ -6058,7 +6040,7 @@
 
   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   Handle<InterceptorInfo> interceptor(it->GetInterceptor());
-  if (interceptor->deleter()->IsUndefined()) return Nothing<bool>();
+  if (interceptor->deleter()->IsUndefined(isolate)) return Nothing<bool>();
 
   Handle<JSObject> holder = it->GetHolder<JSObject>();
   Handle<Object> receiver = it->GetReceiver();
@@ -6092,7 +6074,7 @@
 
   DCHECK(result->IsBoolean());
   // Rebox CustomArguments::kReturnValueOffset before returning.
-  return Just(result->IsTrue());
+  return Just(result->IsTrue(isolate));
 }
 
 
@@ -6145,11 +6127,6 @@
   }
   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
 
-  bool is_observed = receiver->map()->is_observed() &&
-                     (it->IsElement() || !it->name()->IsPrivate());
-
-  Handle<Object> old_value = it->factory()->the_hole_value();
-
   for (; it->IsFound(); it->Next()) {
     switch (it->state()) {
       case LookupIterator::JSPROXY:
@@ -6177,10 +6154,6 @@
       case LookupIterator::INTEGER_INDEXED_EXOTIC:
         return Just(true);
       case LookupIterator::DATA:
-        if (is_observed) {
-          old_value = it->GetDataValue();
-        }
-      // Fall through.
       case LookupIterator::ACCESSOR: {
         if (!it->IsConfigurable()) {
           // Fail if the property is not configurable.
@@ -6195,13 +6168,6 @@
 
         it->Delete();
 
-        if (is_observed) {
-          RETURN_ON_EXCEPTION_VALUE(
-              isolate, JSObject::EnqueueChangeRecord(receiver, "delete",
-                                                     it->GetName(), old_value),
-              Nothing<bool>());
-        }
-
         return Just(true);
       }
     }
@@ -6214,7 +6180,7 @@
 Maybe<bool> JSReceiver::DeleteElement(Handle<JSReceiver> object, uint32_t index,
                                       LanguageMode language_mode) {
   LookupIterator it(object->GetIsolate(), object, index, object,
-                    LookupIterator::HIDDEN);
+                    LookupIterator::OWN);
   return DeleteProperty(&it, language_mode);
 }
 
@@ -6222,7 +6188,7 @@
 Maybe<bool> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
                                        Handle<Name> name,
                                        LanguageMode language_mode) {
-  LookupIterator it(object, name, object, LookupIterator::HIDDEN);
+  LookupIterator it(object, name, object, LookupIterator::OWN);
   return DeleteProperty(&it, language_mode);
 }
 
@@ -6231,13 +6197,15 @@
                                                 Handle<Name> name,
                                                 LanguageMode language_mode) {
   LookupIterator it = LookupIterator::PropertyOrElement(
-      name->GetIsolate(), object, name, object, LookupIterator::HIDDEN);
+      name->GetIsolate(), object, name, object, LookupIterator::OWN);
   return DeleteProperty(&it, language_mode);
 }
 
 
 // ES6 7.1.14
-MaybeHandle<Object> ToPropertyKey(Isolate* isolate, Handle<Object> value) {
+// static
+MaybeHandle<Object> Object::ToPropertyKey(Isolate* isolate,
+                                          Handle<Object> value) {
   // 1. Let key be ToPrimitive(argument, hint String).
   MaybeHandle<Object> maybe_key =
       Object::ToPrimitive(value, ToPrimitiveHint::kString);
@@ -6317,7 +6285,8 @@
   // 5. ReturnIfAbrupt(keys).
   Handle<FixedArray> keys;
   ASSIGN_RETURN_ON_EXCEPTION(
-      isolate, keys, JSReceiver::GetKeys(props, OWN_ONLY, ALL_PROPERTIES),
+      isolate, keys, KeyAccumulator::GetKeys(props, KeyCollectionMode::kOwnOnly,
+                                             ALL_PROPERTIES),
       Object);
   // 6. Let descriptors be an empty List.
   int capacity = keys->length();
@@ -6330,7 +6299,7 @@
     // 7b. ReturnIfAbrupt(propDesc).
     bool success = false;
     LookupIterator it = LookupIterator::PropertyOrElement(
-        isolate, props, next_key, &success, LookupIterator::HIDDEN);
+        isolate, props, next_key, &success, LookupIterator::OWN);
     DCHECK(success);
     Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
     if (!maybe.IsJust()) return MaybeHandle<Object>();
@@ -6405,7 +6374,7 @@
   bool success = false;
   DCHECK(key->IsName() || key->IsNumber());  // |key| is a PropertyKey...
   LookupIterator it = LookupIterator::PropertyOrElement(
-      isolate, object, key, &success, LookupIterator::HIDDEN);
+      isolate, object, key, &success, LookupIterator::OWN);
   DCHECK(success);  // ...so creating a LookupIterator can't fail.
 
   // Deal with access checks first.
@@ -6950,10 +6919,7 @@
     // (Not needed.)
   }
   // Most of steps 16 through 19 is implemented by JSArray::SetLength.
-  if (JSArray::ObservableSetLength(a, new_len).is_null()) {
-    DCHECK(isolate->has_pending_exception());
-    return Nothing<bool>();
-  }
+  JSArray::SetLength(a, new_len);
   // Steps 19d-ii, 20.
   if (!new_writable) {
     PropertyDescriptor readonly;
@@ -6985,7 +6951,7 @@
                                        Handle<Object> key,
                                        PropertyDescriptor* desc,
                                        ShouldThrow should_throw) {
-  STACK_CHECK(Nothing<bool>());
+  STACK_CHECK(isolate, Nothing<bool>());
   if (key->IsSymbol() && Handle<Symbol>::cast(key)->IsPrivate()) {
     return SetPrivateProperty(isolate, proxy, Handle<Symbol>::cast(key), desc,
                               should_throw);
@@ -7011,7 +6977,7 @@
       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
       Nothing<bool>());
   // 7. If trap is undefined, then:
-  if (trap->IsUndefined()) {
+  if (trap->IsUndefined(isolate)) {
     // 7a. Return target.[[DefineOwnProperty]](P, Desc).
     return JSReceiver::DefineOwnProperty(isolate, target, key, desc,
                                          should_throw);
@@ -7135,7 +7101,7 @@
   bool success = false;
   DCHECK(key->IsName() || key->IsNumber());  // |key| is a PropertyKey...
   LookupIterator it = LookupIterator::PropertyOrElement(
-      isolate, object, key, &success, LookupIterator::HIDDEN);
+      isolate, object, key, &success, LookupIterator::OWN);
   DCHECK(success);  // ...so creating a LookupIterator can't fail.
   return GetOwnPropertyDescriptor(&it, desc);
 }
@@ -7206,7 +7172,7 @@
                                               Handle<Name> name,
                                               PropertyDescriptor* desc) {
   DCHECK(!name->IsPrivate());
-  STACK_CHECK(Nothing<bool>());
+  STACK_CHECK(isolate, Nothing<bool>());
 
   Handle<String> trap_name =
       isolate->factory()->getOwnPropertyDescriptor_string();
@@ -7229,7 +7195,7 @@
       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
       Nothing<bool>());
   // 7. If trap is undefined, then
-  if (trap->IsUndefined()) {
+  if (trap->IsUndefined(isolate)) {
     // 7a. Return target.[[GetOwnProperty]](P).
     return JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, desc);
   }
@@ -7242,7 +7208,8 @@
       Nothing<bool>());
   // 9. If Type(trapResultObj) is neither Object nor Undefined, throw a
   //    TypeError exception.
-  if (!trap_result_obj->IsJSReceiver() && !trap_result_obj->IsUndefined()) {
+  if (!trap_result_obj->IsJSReceiver() &&
+      !trap_result_obj->IsUndefined(isolate)) {
     isolate->Throw(*isolate->factory()->NewTypeError(
         MessageTemplate::kProxyGetOwnPropertyDescriptorInvalid, name));
     return Nothing<bool>();
@@ -7253,7 +7220,7 @@
       JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
   MAYBE_RETURN(found, Nothing<bool>());
   // 11. If trapResultObj is undefined, then
-  if (trap_result_obj->IsUndefined()) {
+  if (trap_result_obj->IsUndefined(isolate)) {
     // 11a. If targetDesc is undefined, return undefined.
     if (!found.FromJust()) return Just(false);
     // 11b. If targetDesc.[[Configurable]] is false, throw a TypeError
@@ -7318,19 +7285,20 @@
 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
                                             ElementsKind kind,
                                             Object* object) {
+  Isolate* isolate = elements->GetIsolate();
   if (IsFastObjectElementsKind(kind) || kind == FAST_STRING_WRAPPER_ELEMENTS) {
     int length = IsJSArray()
         ? Smi::cast(JSArray::cast(this)->length())->value()
         : elements->length();
     for (int i = 0; i < length; ++i) {
       Object* element = elements->get(i);
-      if (!element->IsTheHole() && element == object) return true;
+      if (!element->IsTheHole(isolate) && element == object) return true;
     }
   } else {
     DCHECK(kind == DICTIONARY_ELEMENTS || kind == SLOW_STRING_WRAPPER_ELEMENTS);
     Object* key =
         SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
-    if (!key->IsUndefined()) return true;
+    if (!key->IsUndefined(isolate)) return true;
   }
   return false;
 }
@@ -7354,7 +7322,7 @@
 
   // Check if the object is among the named properties.
   Object* key = SlowReverseLookup(obj);
-  if (!key->IsUndefined()) {
+  if (!key->IsUndefined(heap->isolate())) {
     return true;
   }
 
@@ -7392,7 +7360,7 @@
       int length = parameter_map->length();
       for (int i = 2; i < length; ++i) {
         Object* value = parameter_map->get(i);
-        if (!value->IsTheHole() && value == obj) return true;
+        if (!value->IsTheHole(heap->isolate()) && value == obj) return true;
       }
       // Check the arguments.
       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
@@ -7460,8 +7428,7 @@
 
   if (receiver->IsJSObject()) {
     Handle<JSObject> object = Handle<JSObject>::cast(receiver);
-    if (!object->HasSloppyArgumentsElements() &&
-        !object->map()->is_observed()) {  // Fast path.
+    if (!object->HasSloppyArgumentsElements()) {  // Fast path.
       if (level == SEALED) {
         return JSObject::PreventExtensionsWithTransition<SEALED>(object,
                                                                  should_throw);
@@ -7565,7 +7532,7 @@
 Maybe<bool> JSProxy::PreventExtensions(Handle<JSProxy> proxy,
                                        ShouldThrow should_throw) {
   Isolate* isolate = proxy->GetIsolate();
-  STACK_CHECK(Nothing<bool>());
+  STACK_CHECK(isolate, Nothing<bool>());
   Factory* factory = isolate->factory();
   Handle<String> trap_name = factory->preventExtensions_string();
 
@@ -7580,7 +7547,7 @@
   Handle<Object> trap;
   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
-  if (trap->IsUndefined()) {
+  if (trap->IsUndefined(isolate)) {
     return JSReceiver::PreventExtensions(target, should_throw);
   }
 
@@ -7612,7 +7579,7 @@
                                         ShouldThrow should_throw) {
   Isolate* isolate = object->GetIsolate();
 
-  if (!object->HasSloppyArgumentsElements() && !object->map()->is_observed()) {
+  if (!object->HasSloppyArgumentsElements()) {
     return PreventExtensionsWithTransition<NONE>(object, should_throw);
   }
 
@@ -7653,13 +7620,6 @@
   JSObject::MigrateToMap(object, new_map);
   DCHECK(!object->map()->is_extensible());
 
-  if (object->map()->is_observed()) {
-    RETURN_ON_EXCEPTION_VALUE(
-        isolate,
-        EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
-                            isolate->factory()->the_hole_value()),
-        Nothing<bool>());
-  }
   return Just(true);
 }
 
@@ -7674,7 +7634,7 @@
 
 Maybe<bool> JSProxy::IsExtensible(Handle<JSProxy> proxy) {
   Isolate* isolate = proxy->GetIsolate();
-  STACK_CHECK(Nothing<bool>());
+  STACK_CHECK(isolate, Nothing<bool>());
   Factory* factory = isolate->factory();
   Handle<String> trap_name = factory->isExtensible_string();
 
@@ -7689,7 +7649,7 @@
   Handle<Object> trap;
   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
-  if (trap->IsUndefined()) {
+  if (trap->IsUndefined(isolate)) {
     return JSReceiver::IsExtensible(target);
   }
 
@@ -7733,9 +7693,10 @@
 static void ApplyAttributesToDictionary(Dictionary* dictionary,
                                         const PropertyAttributes attributes) {
   int capacity = dictionary->Capacity();
+  Isolate* isolate = dictionary->GetIsolate();
   for (int i = 0; i < capacity; i++) {
     Object* k = dictionary->KeyAt(i);
-    if (dictionary->IsKey(k) &&
+    if (dictionary->IsKey(isolate, k) &&
         !(k->IsSymbol() && Symbol::cast(k)->is_private())) {
       PropertyDetails details = dictionary->DetailsAt(i);
       int attrs = attributes;
@@ -7760,7 +7721,6 @@
 
   // Sealing/freezing sloppy arguments should be handled elsewhere.
   DCHECK(!object->HasSloppyArgumentsElements());
-  DCHECK(!object->map()->is_observed());
 
   Isolate* isolate = object->GetIsolate();
   if (object->IsAccessCheckNeeded() &&
@@ -7879,28 +7839,6 @@
 }
 
 
-void JSObject::SetObserved(Handle<JSObject> object) {
-  DCHECK(!object->IsJSGlobalProxy());
-  DCHECK(!object->IsJSGlobalObject());
-  Isolate* isolate = object->GetIsolate();
-  Handle<Map> new_map;
-  Handle<Map> old_map(object->map(), isolate);
-  DCHECK(!old_map->is_observed());
-  Map* transition = TransitionArray::SearchSpecial(
-      *old_map, isolate->heap()->observed_symbol());
-  if (transition != NULL) {
-    new_map = handle(transition, isolate);
-    DCHECK(new_map->is_observed());
-  } else if (TransitionArray::CanHaveMoreTransitions(old_map)) {
-    new_map = Map::CopyForObserved(old_map);
-  } else {
-    new_map = Map::Copy(old_map, "SlowObserved");
-    new_map->set_is_observed();
-  }
-  JSObject::MigrateToMap(object, new_map);
-}
-
-
 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
                                         Representation representation,
                                         FieldIndex index) {
@@ -8029,9 +7967,8 @@
       // an array.
       PropertyFilter filter = static_cast<PropertyFilter>(
           ONLY_WRITABLE | ONLY_ENUMERABLE | ONLY_CONFIGURABLE);
-      KeyAccumulator accumulator(isolate, OWN_ONLY, filter);
-      accumulator.NextPrototype();
-      copy->CollectOwnPropertyNames(&accumulator, filter);
+      KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly, filter);
+      accumulator.CollectOwnPropertyNames(copy, copy);
       Handle<FixedArray> names = accumulator.GetKeys();
       for (int i = 0; i < names->length(); i++) {
         DCHECK(names->get(i)->IsName());
@@ -8086,7 +8023,7 @@
         int capacity = element_dictionary->Capacity();
         for (int i = 0; i < capacity; i++) {
           Object* k = element_dictionary->KeyAt(i);
-          if (element_dictionary->IsKey(k)) {
+          if (element_dictionary->IsKey(isolate, k)) {
             Handle<Object> value(element_dictionary->ValueAt(i), isolate);
             if (value->IsJSObject()) {
               Handle<JSObject> result;
@@ -8165,7 +8102,7 @@
   ASSIGN_RETURN_ON_EXCEPTION(
       isolate, exotic_to_prim,
       GetMethod(receiver, isolate->factory()->to_primitive_symbol()), Object);
-  if (!exotic_to_prim->IsUndefined()) {
+  if (!exotic_to_prim->IsUndefined(isolate)) {
     Handle<Object> hint_string;
     switch (hint) {
       case ToPrimitiveHint::kDefault:
@@ -8295,28 +8232,6 @@
   return true;
 }
 
-// Tests for the fast common case for property enumeration:
-// - This object and all prototypes has an enum cache (which means that
-//   it is no proxy, has no interceptors and needs no access checks).
-// - This object has no elements.
-// - No prototype has enumerable properties/elements.
-bool JSReceiver::IsSimpleEnum() {
-  for (PrototypeIterator iter(GetIsolate(), this,
-                              PrototypeIterator::START_AT_RECEIVER);
-       !iter.IsAtEnd(); iter.Advance()) {
-    if (!iter.GetCurrent()->IsJSObject()) return false;
-    JSObject* current = iter.GetCurrent<JSObject>();
-    int enum_length = current->map()->EnumLength();
-    if (enum_length == kInvalidEnumCacheSentinel) return false;
-    if (current->IsAccessCheckNeeded()) return false;
-    DCHECK(!current->HasNamedInterceptor());
-    DCHECK(!current->HasIndexedInterceptor());
-    if (current->HasEnumerableElements()) return false;
-    if (current != this && enum_length != 0) return false;
-  }
-  return true;
-}
-
 
 int Map::NumberOfDescribedProperties(DescriptorFlag which,
                                      PropertyFilter filter) {
@@ -8350,23 +8265,6 @@
 }
 
 
-static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
-  int len = array->length();
-  for (int i = 0; i < len; i++) {
-    Object* e = array->get(i);
-    if (!(e->IsName() || e->IsNumber())) return false;
-  }
-  return true;
-}
-
-
-static Handle<FixedArray> ReduceFixedArrayTo(
-    Handle<FixedArray> array, int length) {
-  DCHECK_LE(length, array->length());
-  if (array->length() == length) return array;
-  return array->GetIsolate()->factory()->CopyFixedArrayUpTo(array, length);
-}
-
 bool Map::OnlyHasSimpleProperties() {
   // Wrapped string elements aren't explicitly stored in the elements backing
   // store, but are loaded indirectly from the underlying string.
@@ -8375,421 +8273,6 @@
          !has_hidden_prototype() && !is_dictionary_map();
 }
 
-// static
-Handle<FixedArray> JSObject::GetFastEnumPropertyKeys(Isolate* isolate,
-                                                     Handle<JSObject> object) {
-  Handle<Map> map(object->map());
-  bool cache_enum_length = map->OnlyHasSimpleProperties();
-
-  Handle<DescriptorArray> descs =
-      Handle<DescriptorArray>(map->instance_descriptors(), isolate);
-  int own_property_count = map->EnumLength();
-  // If the enum length of the given map is set to kInvalidEnumCache, this
-  // means that the map itself has never used the present enum cache. The
-  // first step to using the cache is to set the enum length of the map by
-  // counting the number of own descriptors that are ENUMERABLE_STRINGS.
-  if (own_property_count == kInvalidEnumCacheSentinel) {
-    own_property_count =
-        map->NumberOfDescribedProperties(OWN_DESCRIPTORS, ENUMERABLE_STRINGS);
-  } else {
-    DCHECK(
-        own_property_count ==
-        map->NumberOfDescribedProperties(OWN_DESCRIPTORS, ENUMERABLE_STRINGS));
-  }
-
-  if (descs->HasEnumCache()) {
-    Handle<FixedArray> keys(descs->GetEnumCache(), isolate);
-    // In case the number of properties required in the enum are actually
-    // present, we can reuse the enum cache. Otherwise, this means that the
-    // enum cache was generated for a previous (smaller) version of the
-    // Descriptor Array. In that case we regenerate the enum cache.
-    if (own_property_count <= keys->length()) {
-      isolate->counters()->enum_cache_hits()->Increment();
-      if (cache_enum_length) map->SetEnumLength(own_property_count);
-      return ReduceFixedArrayTo(keys, own_property_count);
-    }
-  }
-
-  if (descs->IsEmpty()) {
-    isolate->counters()->enum_cache_hits()->Increment();
-    if (cache_enum_length) map->SetEnumLength(0);
-    return isolate->factory()->empty_fixed_array();
-  }
-
-  isolate->counters()->enum_cache_misses()->Increment();
-
-  Handle<FixedArray> storage =
-      isolate->factory()->NewFixedArray(own_property_count);
-  Handle<FixedArray> indices =
-      isolate->factory()->NewFixedArray(own_property_count);
-
-  int size = map->NumberOfOwnDescriptors();
-  int index = 0;
-
-  for (int i = 0; i < size; i++) {
-    PropertyDetails details = descs->GetDetails(i);
-    if (details.IsDontEnum()) continue;
-    Object* key = descs->GetKey(i);
-    if (key->IsSymbol()) continue;
-    storage->set(index, key);
-    if (!indices.is_null()) {
-      if (details.type() != DATA) {
-        indices = Handle<FixedArray>();
-      } else {
-        FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
-        int load_by_field_index = field_index.GetLoadByFieldIndex();
-        indices->set(index, Smi::FromInt(load_by_field_index));
-      }
-    }
-    index++;
-  }
-  DCHECK(index == storage->length());
-
-  DescriptorArray::SetEnumCache(descs, isolate, storage, indices);
-  if (cache_enum_length) {
-    map->SetEnumLength(own_property_count);
-  }
-  return storage;
-}
-
-
-Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object) {
-  Isolate* isolate = object->GetIsolate();
-  if (object->HasFastProperties()) {
-    return GetFastEnumPropertyKeys(isolate, object);
-  } else if (object->IsJSGlobalObject()) {
-    Handle<GlobalDictionary> dictionary(object->global_dictionary());
-    int length = dictionary->NumberOfEnumElements();
-    if (length == 0) {
-      return isolate->factory()->empty_fixed_array();
-    }
-    Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
-    dictionary->CopyEnumKeysTo(*storage);
-    return storage;
-  } else {
-    Handle<NameDictionary> dictionary(object->property_dictionary());
-    int length = dictionary->NumberOfEnumElements();
-    if (length == 0) {
-      return isolate->factory()->empty_fixed_array();
-    }
-    Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
-    dictionary->CopyEnumKeysTo(*storage);
-    return storage;
-  }
-}
-
-
-enum IndexedOrNamed { kIndexed, kNamed };
-
-
-// Returns |true| on success, |nothing| on exception.
-template <class Callback, IndexedOrNamed type>
-static Maybe<bool> GetKeysFromInterceptor(Isolate* isolate,
-                                          Handle<JSReceiver> receiver,
-                                          Handle<JSObject> object,
-                                          PropertyFilter filter,
-                                          KeyAccumulator* accumulator) {
-  if (type == kIndexed) {
-    if (!object->HasIndexedInterceptor()) return Just(true);
-  } else {
-    if (!object->HasNamedInterceptor()) return Just(true);
-  }
-  Handle<InterceptorInfo> interceptor(type == kIndexed
-                                          ? object->GetIndexedInterceptor()
-                                          : object->GetNamedInterceptor(),
-                                      isolate);
-  if ((filter & ONLY_ALL_CAN_READ) && !interceptor->all_can_read()) {
-    return Just(true);
-  }
-  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
-                                 *object, Object::DONT_THROW);
-  Handle<JSObject> result;
-  if (!interceptor->enumerator()->IsUndefined()) {
-    Callback enum_fun = v8::ToCData<Callback>(interceptor->enumerator());
-    const char* log_tag = type == kIndexed ? "interceptor-indexed-enum"
-                                           : "interceptor-named-enum";
-    LOG(isolate, ApiObjectAccess(log_tag, *object));
-    result = args.Call(enum_fun);
-  }
-  RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
-  if (result.is_null()) return Just(true);
-  DCHECK(result->IsJSArray() || result->HasSloppyArgumentsElements());
-  // The accumulator takes care of string/symbol filtering.
-  if (type == kIndexed) {
-    accumulator->AddElementKeysFromInterceptor(result);
-  } else {
-    accumulator->AddKeys(result, DO_NOT_CONVERT);
-  }
-  return Just(true);
-}
-
-
-// Returns |true| on success, |false| if prototype walking should be stopped,
-// |nothing| if an exception was thrown.
-static Maybe<bool> GetKeysFromJSObject(Isolate* isolate,
-                                       Handle<JSReceiver> receiver,
-                                       Handle<JSObject> object,
-                                       PropertyFilter* filter,
-                                       KeyCollectionType type,
-                                       KeyAccumulator* accumulator) {
-  accumulator->NextPrototype();
-  // Check access rights if required.
-  if (object->IsAccessCheckNeeded() &&
-      !isolate->MayAccess(handle(isolate->context()), object)) {
-    // The cross-origin spec says that [[Enumerate]] shall return an empty
-    // iterator when it doesn't have access...
-    if (type == INCLUDE_PROTOS) {
-      return Just(false);
-    }
-    // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties.
-    DCHECK_EQ(OWN_ONLY, type);
-    *filter = static_cast<PropertyFilter>(*filter | ONLY_ALL_CAN_READ);
-  }
-
-  JSObject::CollectOwnElementKeys(object, accumulator, *filter);
-
-  // Add the element keys from the interceptor.
-  Maybe<bool> success =
-      GetKeysFromInterceptor<v8::IndexedPropertyEnumeratorCallback, kIndexed>(
-          isolate, receiver, object, *filter, accumulator);
-  MAYBE_RETURN(success, Nothing<bool>());
-
-  if (*filter == ENUMERABLE_STRINGS) {
-    Handle<FixedArray> enum_keys = JSObject::GetEnumPropertyKeys(object);
-    accumulator->AddKeys(enum_keys, DO_NOT_CONVERT);
-  } else {
-    object->CollectOwnPropertyNames(accumulator, *filter);
-  }
-
-  // Add the property keys from the interceptor.
-  success = GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback,
-                                   kNamed>(isolate, receiver, object, *filter,
-                                           accumulator);
-  MAYBE_RETURN(success, Nothing<bool>());
-  return Just(true);
-}
-
-
-// Helper function for JSReceiver::GetKeys() below. Can be called recursively.
-// Returns |true| or |nothing|.
-static Maybe<bool> GetKeys_Internal(Isolate* isolate,
-                                    Handle<JSReceiver> receiver,
-                                    Handle<JSReceiver> object,
-                                    KeyCollectionType type,
-                                    PropertyFilter filter,
-                                    KeyAccumulator* accumulator) {
-  // Proxies have no hidden prototype and we should not trigger the
-  // [[GetPrototypeOf]] trap on the last iteration when using
-  // AdvanceFollowingProxies.
-  if (type == OWN_ONLY && object->IsJSProxy()) {
-    MAYBE_RETURN(JSProxy::OwnPropertyKeys(isolate, receiver,
-                                          Handle<JSProxy>::cast(object), filter,
-                                          accumulator),
-                 Nothing<bool>());
-    return Just(true);
-  }
-
-  PrototypeIterator::WhereToEnd end = type == OWN_ONLY
-                                          ? PrototypeIterator::END_AT_NON_HIDDEN
-                                          : PrototypeIterator::END_AT_NULL;
-  for (PrototypeIterator iter(isolate, object,
-                              PrototypeIterator::START_AT_RECEIVER, end);
-       !iter.IsAtEnd();) {
-    Handle<JSReceiver> current =
-        PrototypeIterator::GetCurrent<JSReceiver>(iter);
-    Maybe<bool> result = Just(false);  // Dummy initialization.
-    if (current->IsJSProxy()) {
-      result = JSProxy::OwnPropertyKeys(isolate, receiver,
-                                        Handle<JSProxy>::cast(current), filter,
-                                        accumulator);
-    } else {
-      DCHECK(current->IsJSObject());
-      result = GetKeysFromJSObject(isolate, receiver,
-                                   Handle<JSObject>::cast(current), &filter,
-                                   type, accumulator);
-    }
-    MAYBE_RETURN(result, Nothing<bool>());
-    if (!result.FromJust()) break;  // |false| means "stop iterating".
-    // Iterate through proxies but ignore access checks for the ALL_CAN_READ
-    // case on API objects for OWN_ONLY keys handlede in GgetKeysFromJSObject.
-    if (!iter.AdvanceFollowingProxiesIgnoringAccessChecks()) {
-      return Nothing<bool>();
-    }
-  }
-  return Just(true);
-}
-
-
-// ES6 9.5.12
-// Returns |true| on success, |nothing| in case of exception.
-// static
-Maybe<bool> JSProxy::OwnPropertyKeys(Isolate* isolate,
-                                     Handle<JSReceiver> receiver,
-                                     Handle<JSProxy> proxy,
-                                     PropertyFilter filter,
-                                     KeyAccumulator* accumulator) {
-  STACK_CHECK(Nothing<bool>());
-  // 1. Let handler be the value of the [[ProxyHandler]] internal slot of O.
-  Handle<Object> handler(proxy->handler(), isolate);
-  // 2. If handler is null, throw a TypeError exception.
-  // 3. Assert: Type(handler) is Object.
-  if (proxy->IsRevoked()) {
-    isolate->Throw(*isolate->factory()->NewTypeError(
-        MessageTemplate::kProxyRevoked, isolate->factory()->ownKeys_string()));
-    return Nothing<bool>();
-  }
-  // 4. Let target be the value of the [[ProxyTarget]] internal slot of O.
-  Handle<JSReceiver> target(proxy->target(), isolate);
-  // 5. Let trap be ? GetMethod(handler, "ownKeys").
-  Handle<Object> trap;
-  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-      isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler),
-                                       isolate->factory()->ownKeys_string()),
-      Nothing<bool>());
-  // 6. If trap is undefined, then
-  if (trap->IsUndefined()) {
-    // 6a. Return target.[[OwnPropertyKeys]]().
-    return GetKeys_Internal(isolate, receiver, target, OWN_ONLY, filter,
-                            accumulator);
-  }
-  // 7. Let trapResultArray be Call(trap, handler, «target»).
-  Handle<Object> trap_result_array;
-  Handle<Object> args[] = {target};
-  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-      isolate, trap_result_array,
-      Execution::Call(isolate, trap, handler, arraysize(args), args),
-      Nothing<bool>());
-  // 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray,
-  //    «String, Symbol»).
-  Handle<FixedArray> trap_result;
-  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-      isolate, trap_result,
-      Object::CreateListFromArrayLike(isolate, trap_result_array,
-                                      ElementTypes::kStringAndSymbol),
-      Nothing<bool>());
-  // 9. Let extensibleTarget be ? IsExtensible(target).
-  Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target);
-  MAYBE_RETURN(maybe_extensible, Nothing<bool>());
-  bool extensible_target = maybe_extensible.FromJust();
-  // 10. Let targetKeys be ? target.[[OwnPropertyKeys]]().
-  Handle<FixedArray> target_keys;
-  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_keys,
-                                   JSReceiver::OwnPropertyKeys(target),
-                                   Nothing<bool>());
-  // 11. (Assert)
-  // 12. Let targetConfigurableKeys be an empty List.
-  // To save memory, we're re-using target_keys and will modify it in-place.
-  Handle<FixedArray> target_configurable_keys = target_keys;
-  // 13. Let targetNonconfigurableKeys be an empty List.
-  Handle<FixedArray> target_nonconfigurable_keys =
-      isolate->factory()->NewFixedArray(target_keys->length());
-  int nonconfigurable_keys_length = 0;
-  // 14. Repeat, for each element key of targetKeys:
-  for (int i = 0; i < target_keys->length(); ++i) {
-    // 14a. Let desc be ? target.[[GetOwnProperty]](key).
-    PropertyDescriptor desc;
-    Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor(
-        isolate, target, handle(target_keys->get(i), isolate), &desc);
-    MAYBE_RETURN(found, Nothing<bool>());
-    // 14b. If desc is not undefined and desc.[[Configurable]] is false, then
-    if (found.FromJust() && !desc.configurable()) {
-      // 14b i. Append key as an element of targetNonconfigurableKeys.
-      target_nonconfigurable_keys->set(nonconfigurable_keys_length,
-                                       target_keys->get(i));
-      nonconfigurable_keys_length++;
-      // The key was moved, null it out in the original list.
-      target_keys->set(i, Smi::FromInt(0));
-    } else {
-      // 14c. Else,
-      // 14c i. Append key as an element of targetConfigurableKeys.
-      // (No-op, just keep it in |target_keys|.)
-    }
-  }
-  accumulator->NextPrototype();  // Prepare for accumulating keys.
-  // 15. If extensibleTarget is true and targetNonconfigurableKeys is empty,
-  //     then:
-  if (extensible_target && nonconfigurable_keys_length == 0) {
-    // 15a. Return trapResult.
-    return accumulator->AddKeysFromProxy(proxy, trap_result);
-  }
-  // 16. Let uncheckedResultKeys be a new List which is a copy of trapResult.
-  Zone set_zone(isolate->allocator());
-  const int kPresent = 1;
-  const int kGone = 0;
-  IdentityMap<int> unchecked_result_keys(isolate->heap(), &set_zone);
-  int unchecked_result_keys_size = 0;
-  for (int i = 0; i < trap_result->length(); ++i) {
-    DCHECK(trap_result->get(i)->IsUniqueName());
-    Object* key = trap_result->get(i);
-    int* entry = unchecked_result_keys.Get(key);
-    if (*entry != kPresent) {
-      *entry = kPresent;
-      unchecked_result_keys_size++;
-    }
-  }
-  // 17. Repeat, for each key that is an element of targetNonconfigurableKeys:
-  for (int i = 0; i < nonconfigurable_keys_length; ++i) {
-    Object* key = target_nonconfigurable_keys->get(i);
-    // 17a. If key is not an element of uncheckedResultKeys, throw a
-    //      TypeError exception.
-    int* found = unchecked_result_keys.Find(key);
-    if (found == nullptr || *found == kGone) {
-      isolate->Throw(*isolate->factory()->NewTypeError(
-          MessageTemplate::kProxyOwnKeysMissing, handle(key, isolate)));
-      return Nothing<bool>();
-    }
-    // 17b. Remove key from uncheckedResultKeys.
-    *found = kGone;
-    unchecked_result_keys_size--;
-  }
-  // 18. If extensibleTarget is true, return trapResult.
-  if (extensible_target) {
-    return accumulator->AddKeysFromProxy(proxy, trap_result);
-  }
-  // 19. Repeat, for each key that is an element of targetConfigurableKeys:
-  for (int i = 0; i < target_configurable_keys->length(); ++i) {
-    Object* key = target_configurable_keys->get(i);
-    if (key->IsSmi()) continue;  // Zapped entry, was nonconfigurable.
-    // 19a. If key is not an element of uncheckedResultKeys, throw a
-    //      TypeError exception.
-    int* found = unchecked_result_keys.Find(key);
-    if (found == nullptr || *found == kGone) {
-      isolate->Throw(*isolate->factory()->NewTypeError(
-          MessageTemplate::kProxyOwnKeysMissing, handle(key, isolate)));
-      return Nothing<bool>();
-    }
-    // 19b. Remove key from uncheckedResultKeys.
-    *found = kGone;
-    unchecked_result_keys_size--;
-  }
-  // 20. If uncheckedResultKeys is not empty, throw a TypeError exception.
-  if (unchecked_result_keys_size != 0) {
-    DCHECK_GT(unchecked_result_keys_size, 0);
-    isolate->Throw(*isolate->factory()->NewTypeError(
-        MessageTemplate::kProxyOwnKeysNonExtensible));
-    return Nothing<bool>();
-  }
-  // 21. Return trapResult.
-  return accumulator->AddKeysFromProxy(proxy, trap_result);
-}
-
-MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
-                                            KeyCollectionType type,
-                                            PropertyFilter filter,
-                                            GetKeysConversion keys_conversion,
-                                            bool filter_proxy_keys) {
-  USE(ContainsOnlyValidKeys);
-  Isolate* isolate = object->GetIsolate();
-  KeyAccumulator accumulator(isolate, type, filter);
-  accumulator.set_filter_proxy_keys(filter_proxy_keys);
-  MAYBE_RETURN(
-      GetKeys_Internal(isolate, object, object, type, filter, &accumulator),
-      MaybeHandle<FixedArray>());
-  Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion);
-  DCHECK(ContainsOnlyValidKeys(keys));
-  return keys;
-}
-
 MUST_USE_RESULT Maybe<bool> FastGetOwnValuesOrEntries(
     Isolate* isolate, Handle<JSReceiver> receiver, bool get_entries,
     Handle<FixedArray>* result) {
@@ -8880,12 +8363,13 @@
 
   PropertyFilter key_filter =
       static_cast<PropertyFilter>(filter & ~ONLY_ENUMERABLE);
-  KeyAccumulator accumulator(isolate, OWN_ONLY, key_filter);
-  MAYBE_RETURN(GetKeys_Internal(isolate, object, object, OWN_ONLY, key_filter,
-                                &accumulator),
-               MaybeHandle<FixedArray>());
-  Handle<FixedArray> keys = accumulator.GetKeys(CONVERT_TO_STRING);
-  DCHECK(ContainsOnlyValidKeys(keys));
+
+  Handle<FixedArray> keys;
+  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+      isolate, keys,
+      KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, key_filter,
+                              GetKeysConversion::kConvertToString),
+      MaybeHandle<FixedArray>());
 
   values_or_entries = isolate->factory()->NewFixedArray(keys->length());
   int length = 0;
@@ -8970,7 +8454,7 @@
   Isolate* isolate = object->GetIsolate();
 
   LookupIterator it = LookupIterator::PropertyOrElement(
-      isolate, object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
+      isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
   return DefineAccessor(&it, getter, setter, attributes);
 }
 
@@ -8998,40 +8482,11 @@
     return it->factory()->undefined_value();
   }
 
-  Handle<Object> old_value = isolate->factory()->the_hole_value();
-  bool is_observed = object->map()->is_observed() &&
-                     (it->IsElement() || !it->name()->IsPrivate());
-  bool preexists = false;
-  if (is_observed) {
-    CHECK(GetPropertyAttributes(it).IsJust());
-    preexists = it->IsFound();
-    if (preexists && (it->state() == LookupIterator::DATA ||
-                      it->GetAccessors()->IsAccessorInfo())) {
-      old_value = Object::GetProperty(it).ToHandleChecked();
-    }
-  }
-
-  DCHECK(getter->IsCallable() || getter->IsUndefined() || getter->IsNull() ||
-         getter->IsFunctionTemplateInfo());
-  DCHECK(setter->IsCallable() || setter->IsUndefined() || setter->IsNull() ||
-         getter->IsFunctionTemplateInfo());
-  // At least one of the accessors needs to be a new value.
-  DCHECK(!getter->IsNull() || !setter->IsNull());
-  if (!getter->IsNull()) {
-    it->TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes);
-  }
-  if (!setter->IsNull()) {
-    it->TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes);
-  }
-
-  if (is_observed) {
-    // Make sure the top context isn't changed.
-    AssertNoContextChange ncc(isolate);
-    const char* type = preexists ? "reconfigure" : "add";
-    RETURN_ON_EXCEPTION(
-        isolate, EnqueueChangeRecord(object, type, it->GetName(), old_value),
-        Object);
-  }
+  DCHECK(getter->IsCallable() || getter->IsUndefined(isolate) ||
+         getter->IsNull(isolate) || getter->IsFunctionTemplateInfo());
+  DCHECK(setter->IsCallable() || setter->IsUndefined(isolate) ||
+         setter->IsNull(isolate) || getter->IsFunctionTemplateInfo());
+  it->TransitionToAccessorProperty(getter, setter, attributes);
 
   return isolate->factory()->undefined_value();
 }
@@ -9043,7 +8498,7 @@
   Handle<Name> name(Name::cast(info->name()), isolate);
 
   LookupIterator it = LookupIterator::PropertyOrElement(
-      isolate, object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
+      isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
 
   // Duplicate ACCESS_CHECK outside of GetPropertyAttributes for the case that
   // the FailedAccessCheckCallbackFunction doesn't throw an exception.
@@ -9077,53 +8532,6 @@
   return object;
 }
 
-
-MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object,
-                                          Handle<Name> name,
-                                          AccessorComponent component) {
-  Isolate* isolate = object->GetIsolate();
-
-  // Make sure that the top context does not change when doing callbacks or
-  // interceptor calls.
-  AssertNoContextChange ncc(isolate);
-
-  LookupIterator it = LookupIterator::PropertyOrElement(
-      isolate, object, name, LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
-
-  for (; it.IsFound(); it.Next()) {
-    switch (it.state()) {
-      case LookupIterator::INTERCEPTOR:
-      case LookupIterator::NOT_FOUND:
-      case LookupIterator::TRANSITION:
-        UNREACHABLE();
-
-      case LookupIterator::ACCESS_CHECK:
-        if (it.HasAccess()) continue;
-        isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
-        RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
-        return isolate->factory()->undefined_value();
-
-      case LookupIterator::JSPROXY:
-        return isolate->factory()->undefined_value();
-
-      case LookupIterator::INTEGER_INDEXED_EXOTIC:
-        return isolate->factory()->undefined_value();
-      case LookupIterator::DATA:
-        continue;
-      case LookupIterator::ACCESSOR: {
-        Handle<Object> maybe_pair = it.GetAccessors();
-        if (maybe_pair->IsAccessorPair()) {
-          return AccessorPair::GetComponent(
-              Handle<AccessorPair>::cast(maybe_pair), component);
-        }
-      }
-    }
-  }
-
-  return isolate->factory()->undefined_value();
-}
-
-
 Object* JSObject::SlowReverseLookup(Object* value) {
   if (HasFastProperties()) {
     int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
@@ -9195,7 +8603,8 @@
   Isolate* isolate = fast_map->GetIsolate();
   Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
                              isolate);
-  bool use_cache = !fast_map->is_prototype_map() && !maybe_cache->IsUndefined();
+  bool use_cache =
+      !fast_map->is_prototype_map() && !maybe_cache->IsUndefined(isolate);
   Handle<NormalizedMapCache> cache;
   if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
 
@@ -9406,7 +8815,7 @@
 
 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
                             Handle<Name> name, SimpleTransitionFlag flag) {
-  if (!parent->GetBackPointer()->IsUndefined()) {
+  if (!parent->GetBackPointer()->IsUndefined(parent->GetIsolate())) {
     parent->set_owns_descriptors(false);
   } else {
     // |parent| is initial map and it must keep the ownership, there must be no
@@ -9562,6 +8971,10 @@
                                     TransitionFlag flag) {
   Map* maybe_elements_transition_map = NULL;
   if (flag == INSERT_TRANSITION) {
+    // Ensure we are requested to add elements kind transition "near the root".
+    DCHECK_EQ(map->FindRootMap()->NumberOfOwnDescriptors(),
+              map->NumberOfOwnDescriptors());
+
     maybe_elements_transition_map = map->ElementsTransitionMap();
     DCHECK(maybe_elements_transition_map == NULL ||
            (maybe_elements_transition_map->elements_kind() ==
@@ -9641,30 +9054,6 @@
 }
 
 
-Handle<Map> Map::CopyForObserved(Handle<Map> map) {
-  DCHECK(!map->is_observed());
-
-  Isolate* isolate = map->GetIsolate();
-
-  bool insert_transition =
-      TransitionArray::CanHaveMoreTransitions(map) && !map->is_prototype_map();
-
-  if (insert_transition) {
-    Handle<Map> new_map = CopyForTransition(map, "CopyForObserved");
-    new_map->set_is_observed();
-
-    Handle<Name> name = isolate->factory()->observed_symbol();
-    ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
-    return new_map;
-  }
-
-  // Create a new free-floating map only if we are not allowed to store it.
-  Handle<Map> new_map = Map::Copy(map, "CopyForObserved");
-  new_map->set_is_observed();
-  return new_map;
-}
-
-
 Handle<Map> Map::CopyForTransition(Handle<Map> map, const char* reason) {
   DCHECK(!map->is_prototype_map());
   Handle<Map> new_map = CopyDropDescriptors(map);
@@ -9825,6 +9214,11 @@
                                           Handle<Object> value,
                                           PropertyAttributes attributes,
                                           StoreFromKeyed store_mode) {
+  RuntimeCallTimerScope stats_scope(
+      *map, map->is_prototype_map()
+                ? &RuntimeCallStats::PrototypeMap_TransitionToDataProperty
+                : &RuntimeCallStats::Map_TransitionToDataProperty);
+
   DCHECK(name->IsUniqueName());
   DCHECK(!map->is_dictionary_map());
 
@@ -9885,7 +9279,7 @@
     // There is no benefit from reconstructing transition tree for maps without
     // back pointers.
     return CopyGeneralizeAllRepresentations(
-        map, descriptor, FORCE_FIELD, kind, attributes,
+        map, map->elements_kind(), descriptor, FORCE_FIELD, kind, attributes,
         "GenAll_AttributesMismatchProtoMap");
   }
 
@@ -9900,13 +9294,20 @@
   return new_map;
 }
 
-Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map,
+Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map,
                                               Handle<Name> name, int descriptor,
-                                              AccessorComponent component,
-                                              Handle<Object> accessor,
+                                              Handle<Object> getter,
+                                              Handle<Object> setter,
                                               PropertyAttributes attributes) {
+  RuntimeCallTimerScope stats_scope(
+      isolate,
+      map->is_prototype_map()
+          ? &RuntimeCallStats::PrototypeMap_TransitionToAccessorProperty
+          : &RuntimeCallStats::Map_TransitionToAccessorProperty);
+
+  // At least one of the accessors needs to be a new value.
+  DCHECK(!getter->IsNull(isolate) || !setter->IsNull(isolate));
   DCHECK(name->IsUniqueName());
-  Isolate* isolate = name->GetIsolate();
 
   // Dictionary maps can always have additional data properties.
   if (map->is_dictionary_map()) return map;
@@ -9935,7 +9336,7 @@
     }
 
     Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair);
-    if (pair->get(component) != *accessor) {
+    if (!pair->Equals(*getter, *setter)) {
       return Map::Normalize(map, mode, "TransitionToDifferentAccessor");
     }
 
@@ -9962,10 +9363,21 @@
       return Map::Normalize(map, mode, "AccessorsOverwritingNonPair");
     }
 
-    Object* current = Handle<AccessorPair>::cast(maybe_pair)->get(component);
-    if (current == *accessor) return map;
+    Handle<AccessorPair> current_pair = Handle<AccessorPair>::cast(maybe_pair);
+    if (current_pair->Equals(*getter, *setter)) return map;
 
-    if (!current->IsTheHole()) {
+    bool overwriting_accessor = false;
+    if (!getter->IsNull(isolate) &&
+        !current_pair->get(ACCESSOR_GETTER)->IsNull(isolate) &&
+        current_pair->get(ACCESSOR_GETTER) != *getter) {
+      overwriting_accessor = true;
+    }
+    if (!setter->IsNull(isolate) &&
+        !current_pair->get(ACCESSOR_SETTER)->IsNull(isolate) &&
+        current_pair->get(ACCESSOR_SETTER) != *setter) {
+      overwriting_accessor = true;
+    }
+    if (overwriting_accessor) {
       return Map::Normalize(map, mode, "AccessorsOverwritingAccessors");
     }
 
@@ -9977,7 +9389,8 @@
     pair = isolate->factory()->NewAccessorPair();
   }
 
-  pair->set(component, *accessor);
+  pair->SetComponents(*getter, *setter);
+
   TransitionFlag flag = INSERT_TRANSITION;
   AccessorConstantDescriptor new_desc(name, pair, attributes);
   return Map::CopyInsertDescriptor(map, &new_desc, flag);
@@ -9991,7 +9404,7 @@
 
   // Share descriptors only if map owns descriptors and it not an initial map.
   if (flag == INSERT_TRANSITION && map->owns_descriptors() &&
-      !map->GetBackPointer()->IsUndefined() &&
+      !map->GetBackPointer()->IsUndefined(map->GetIsolate()) &&
       TransitionArray::CanHaveMoreTransitions(map)) {
     return ShareDescriptor(map, descriptors, descriptor);
   }
@@ -10121,222 +9534,186 @@
                                 simple_flag);
 }
 
+// Helper class to manage a Map's code cache. The layout depends on the number
+// of entries; this is worthwhile because most code caches are very small,
+// but some are huge (thousands of entries).
+// For zero entries, the EmptyFixedArray is used.
+// For one entry, we use a 2-element FixedArray containing [name, code].
+// For 2..100 entries, we use a FixedArray with linear lookups, the layout is:
+//   [0] - number of slots that are currently in use
+//   [1] - first name
+//   [2] - first code
+//   [3] - second name
+//   [4] - second code
+//   etc.
+// For more than 128 entries, we use a CodeCacheHashTable.
+class CodeCache : public AllStatic {
+ public:
+  // Returns the new cache, to be stored on the map.
+  static Handle<FixedArray> Put(Isolate* isolate, Handle<FixedArray> cache,
+                                Handle<Name> name, Handle<Code> code) {
+    int length = cache->length();
+    if (length == 0) return PutFirstElement(isolate, name, code);
+    if (length == kEntrySize) {
+      return PutSecondElement(isolate, cache, name, code);
+    }
+    if (length <= kLinearMaxSize) {
+      Handle<FixedArray> result = PutLinearElement(isolate, cache, name, code);
+      if (!result.is_null()) return result;
+      // Fall through if linear storage is getting too large.
+    }
+    return PutHashTableElement(isolate, cache, name, code);
+  }
+
+  static Code* Lookup(FixedArray* cache, Name* name, Code::Flags flags) {
+    int length = cache->length();
+    if (length == 0) return nullptr;
+    if (length == kEntrySize) return OneElementLookup(cache, name, flags);
+    if (!cache->IsCodeCacheHashTable()) {
+      return LinearLookup(cache, name, flags);
+    } else {
+      return CodeCacheHashTable::cast(cache)->Lookup(name, flags);
+    }
+  }
+
+ private:
+  static const int kNameIndex = 0;
+  static const int kCodeIndex = 1;
+  static const int kEntrySize = 2;
+
+  static const int kLinearUsageIndex = 0;
+  static const int kLinearReservedSlots = 1;
+  static const int kLinearInitialCapacity = 2;
+  static const int kLinearMaxSize = 257;  // == LinearSizeFor(128);
+
+  static const int kHashTableInitialCapacity = 200;  // Number of entries.
+
+  static int LinearSizeFor(int entries) {
+    return kLinearReservedSlots + kEntrySize * entries;
+  }
+
+  static int LinearNewSize(int old_size) {
+    int old_entries = (old_size - kLinearReservedSlots) / kEntrySize;
+    return LinearSizeFor(old_entries * 2);
+  }
+
+  static Code* OneElementLookup(FixedArray* cache, Name* name,
+                                Code::Flags flags) {
+    DCHECK_EQ(cache->length(), kEntrySize);
+    if (cache->get(kNameIndex) != name) return nullptr;
+    Code* maybe_code = Code::cast(cache->get(kCodeIndex));
+    if (maybe_code->flags() != flags) return nullptr;
+    return maybe_code;
+  }
+
+  static Code* LinearLookup(FixedArray* cache, Name* name, Code::Flags flags) {
+    DCHECK_GE(cache->length(), kEntrySize);
+    DCHECK(!cache->IsCodeCacheHashTable());
+    int usage = GetLinearUsage(cache);
+    for (int i = kLinearReservedSlots; i < usage; i += kEntrySize) {
+      if (cache->get(i + kNameIndex) != name) continue;
+      Code* code = Code::cast(cache->get(i + kCodeIndex));
+      if (code->flags() == flags) return code;
+    }
+    return nullptr;
+  }
+
+  static Handle<FixedArray> PutFirstElement(Isolate* isolate, Handle<Name> name,
+                                            Handle<Code> code) {
+    Handle<FixedArray> cache = isolate->factory()->NewFixedArray(kEntrySize);
+    cache->set(kNameIndex, *name);
+    cache->set(kCodeIndex, *code);
+    return cache;
+  }
+
+  static Handle<FixedArray> PutSecondElement(Isolate* isolate,
+                                             Handle<FixedArray> cache,
+                                             Handle<Name> name,
+                                             Handle<Code> code) {
+    DCHECK_EQ(cache->length(), kEntrySize);
+    Handle<FixedArray> new_cache = isolate->factory()->NewFixedArray(
+        LinearSizeFor(kLinearInitialCapacity));
+    new_cache->set(kLinearReservedSlots + kNameIndex, cache->get(kNameIndex));
+    new_cache->set(kLinearReservedSlots + kCodeIndex, cache->get(kCodeIndex));
+    new_cache->set(LinearSizeFor(1) + kNameIndex, *name);
+    new_cache->set(LinearSizeFor(1) + kCodeIndex, *code);
+    new_cache->set(kLinearUsageIndex, Smi::FromInt(LinearSizeFor(2)));
+    return new_cache;
+  }
+
+  static Handle<FixedArray> PutLinearElement(Isolate* isolate,
+                                             Handle<FixedArray> cache,
+                                             Handle<Name> name,
+                                             Handle<Code> code) {
+    int length = cache->length();
+    int usage = GetLinearUsage(*cache);
+    DCHECK_LE(usage, length);
+    // Check if we need to grow.
+    if (usage == length) {
+      int new_length = LinearNewSize(length);
+      if (new_length > kLinearMaxSize) return Handle<FixedArray>::null();
+      Handle<FixedArray> new_cache =
+          isolate->factory()->NewFixedArray(new_length);
+      for (int i = kLinearReservedSlots; i < length; i++) {
+        new_cache->set(i, cache->get(i));
+      }
+      cache = new_cache;
+    }
+    // Store new entry.
+    DCHECK_GE(cache->length(), usage + kEntrySize);
+    cache->set(usage + kNameIndex, *name);
+    cache->set(usage + kCodeIndex, *code);
+    cache->set(kLinearUsageIndex, Smi::FromInt(usage + kEntrySize));
+    return cache;
+  }
+
+  static Handle<FixedArray> PutHashTableElement(Isolate* isolate,
+                                                Handle<FixedArray> cache,
+                                                Handle<Name> name,
+                                                Handle<Code> code) {
+    // Check if we need to transition from linear to hash table storage.
+    if (!cache->IsCodeCacheHashTable()) {
+      // Check that the initial hash table capacity is large enough.
+      DCHECK_EQ(kLinearMaxSize, LinearSizeFor(128));
+      STATIC_ASSERT(kHashTableInitialCapacity > 128);
+
+      int length = cache->length();
+      // Only migrate from linear storage when it's full.
+      DCHECK_EQ(length, GetLinearUsage(*cache));
+      DCHECK_EQ(length, kLinearMaxSize);
+      Handle<CodeCacheHashTable> table =
+          CodeCacheHashTable::New(isolate, kHashTableInitialCapacity);
+      HandleScope scope(isolate);
+      for (int i = kLinearReservedSlots; i < length; i += kEntrySize) {
+        Handle<Name> old_name(Name::cast(cache->get(i + kNameIndex)), isolate);
+        Handle<Code> old_code(Code::cast(cache->get(i + kCodeIndex)), isolate);
+        CodeCacheHashTable::Put(table, old_name, old_code);
+      }
+      cache = table;
+    }
+    // Store new entry.
+    DCHECK(cache->IsCodeCacheHashTable());
+    return CodeCacheHashTable::Put(Handle<CodeCacheHashTable>::cast(cache),
+                                   name, code);
+  }
+
+  static inline int GetLinearUsage(FixedArray* linear_cache) {
+    DCHECK_GT(linear_cache->length(), kEntrySize);
+    return Smi::cast(linear_cache->get(kLinearUsageIndex))->value();
+  }
+};
 
 void Map::UpdateCodeCache(Handle<Map> map,
                           Handle<Name> name,
                           Handle<Code> code) {
   Isolate* isolate = map->GetIsolate();
-  HandleScope scope(isolate);
-  // Allocate the code cache if not present.
-  if (map->code_cache()->IsFixedArray()) {
-    Handle<Object> result = isolate->factory()->NewCodeCache();
-    map->set_code_cache(*result);
-  }
-
-  // Update the code cache.
-  Handle<CodeCache> code_cache(CodeCache::cast(map->code_cache()), isolate);
-  CodeCache::Update(code_cache, name, code);
+  Handle<FixedArray> cache(map->code_cache(), isolate);
+  Handle<FixedArray> new_cache = CodeCache::Put(isolate, cache, name, code);
+  map->set_code_cache(*new_cache);
 }
 
-
-Object* Map::FindInCodeCache(Name* name, Code::Flags flags) {
-  // Do a lookup if a code cache exists.
-  if (!code_cache()->IsFixedArray()) {
-    return CodeCache::cast(code_cache())->Lookup(name, flags);
-  } else {
-    return GetHeap()->undefined_value();
-  }
-}
-
-
-int Map::IndexInCodeCache(Object* name, Code* code) {
-  // Get the internal index if a code cache exists.
-  if (!code_cache()->IsFixedArray()) {
-    return CodeCache::cast(code_cache())->GetIndex(name, code);
-  }
-  return -1;
-}
-
-
-void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
-  // No GC is supposed to happen between a call to IndexInCodeCache and
-  // RemoveFromCodeCache so the code cache must be there.
-  DCHECK(!code_cache()->IsFixedArray());
-  CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
-}
-
-
-void CodeCache::Update(
-    Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
-  // The number of monomorphic stubs for normal load/store/call IC's can grow to
-  // a large number and therefore they need to go into a hash table. They are
-  // used to load global properties from cells.
-  if (code->type() == Code::NORMAL) {
-    // Make sure that a hash table is allocated for the normal load code cache.
-    if (code_cache->normal_type_cache()->IsUndefined()) {
-      Handle<Object> result =
-          CodeCacheHashTable::New(code_cache->GetIsolate(),
-                                  CodeCacheHashTable::kInitialSize);
-      code_cache->set_normal_type_cache(*result);
-    }
-    UpdateNormalTypeCache(code_cache, name, code);
-  } else {
-    DCHECK(code_cache->default_cache()->IsFixedArray());
-    UpdateDefaultCache(code_cache, name, code);
-  }
-}
-
-
-void CodeCache::UpdateDefaultCache(
-    Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
-  Isolate* isolate = code_cache->GetIsolate();
-  // When updating the default code cache we disregard the type encoded in the
-  // flags. This allows call constant stubs to overwrite call field
-  // stubs, etc.
-  Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
-
-  // First check whether we can update existing code cache without
-  // extending it.
-  Handle<FixedArray> cache = handle(code_cache->default_cache());
-  int length = cache->length();
-  {
-    DisallowHeapAllocation no_alloc;
-    int deleted_index = -1;
-    Object* null = isolate->heap()->null_value();
-    Object* undefined = isolate->heap()->undefined_value();
-    DCHECK(name->IsUniqueName());
-    for (int i = 0; i < length; i += kCodeCacheEntrySize) {
-      Object* key = cache->get(i);
-      if (key == null) {
-        if (deleted_index < 0) deleted_index = i;
-        continue;
-      }
-      if (key == undefined) {
-        if (deleted_index >= 0) i = deleted_index;
-        cache->set(i + kCodeCacheEntryNameOffset, *name);
-        cache->set(i + kCodeCacheEntryCodeOffset, *code);
-        return;
-      }
-      DCHECK(key->IsUniqueName());
-      if (*name == key) {
-        Code::Flags found =
-            Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
-        if (Code::RemoveTypeFromFlags(found) == flags) {
-          cache->set(i + kCodeCacheEntryCodeOffset, *code);
-          return;
-        }
-      }
-    }
-
-    // Reached the end of the code cache.  If there were deleted
-    // elements, reuse the space for the first of them.
-    if (deleted_index >= 0) {
-      cache->set(deleted_index + kCodeCacheEntryNameOffset, *name);
-      cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code);
-      return;
-    }
-  }
-
-  // Extend the code cache with some new entries (at least one). Must be a
-  // multiple of the entry size.
-  int new_length = length + (length >> 1) + kCodeCacheEntrySize;
-  new_length = new_length - new_length % kCodeCacheEntrySize;
-  DCHECK((new_length % kCodeCacheEntrySize) == 0);
-  cache = isolate->factory()->CopyFixedArrayAndGrow(cache, new_length - length);
-
-  // Add the (name, code) pair to the new cache.
-  cache->set(length + kCodeCacheEntryNameOffset, *name);
-  cache->set(length + kCodeCacheEntryCodeOffset, *code);
-  code_cache->set_default_cache(*cache);
-}
-
-
-void CodeCache::UpdateNormalTypeCache(
-    Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
-  // Adding a new entry can cause a new cache to be allocated.
-  Handle<CodeCacheHashTable> cache(
-      CodeCacheHashTable::cast(code_cache->normal_type_cache()));
-  Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code);
-  code_cache->set_normal_type_cache(*new_cache);
-}
-
-
-Object* CodeCache::Lookup(Name* name, Code::Flags flags) {
-  Object* result = LookupDefaultCache(name, Code::RemoveTypeFromFlags(flags));
-  if (result->IsCode()) {
-    if (Code::cast(result)->flags() == flags) return result;
-    return GetHeap()->undefined_value();
-  }
-  return LookupNormalTypeCache(name, flags);
-}
-
-
-Object* CodeCache::LookupDefaultCache(Name* name, Code::Flags flags) {
-  FixedArray* cache = default_cache();
-  Heap* heap = GetHeap();
-  Object* null = heap->null_value();
-  Object* undefined = heap->undefined_value();
-  int length = cache->length();
-  DCHECK(name->IsUniqueName());
-  for (int i = 0; i < length; i += kCodeCacheEntrySize) {
-    Object* key = cache->get(i + kCodeCacheEntryNameOffset);
-    // Skip deleted elements.
-    if (key == null) continue;
-    if (key == undefined) return key;
-    DCHECK(key->IsUniqueName());
-    if (name == key) {
-      Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
-      if (Code::RemoveTypeFromFlags(code->flags()) == flags) {
-        return code;
-      }
-    }
-  }
-  return GetHeap()->undefined_value();
-}
-
-
-Object* CodeCache::LookupNormalTypeCache(Name* name, Code::Flags flags) {
-  if (!normal_type_cache()->IsUndefined()) {
-    CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
-    return cache->Lookup(name, flags);
-  } else {
-    return GetHeap()->undefined_value();
-  }
-}
-
-
-int CodeCache::GetIndex(Object* name, Code* code) {
-  if (code->type() == Code::NORMAL) {
-    if (normal_type_cache()->IsUndefined()) return -1;
-    CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
-    return cache->GetIndex(Name::cast(name), code->flags());
-  }
-
-  FixedArray* array = default_cache();
-  int len = array->length();
-  for (int i = 0; i < len; i += kCodeCacheEntrySize) {
-    if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
-  }
-  return -1;
-}
-
-
-void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
-  if (code->type() == Code::NORMAL) {
-    DCHECK(!normal_type_cache()->IsUndefined());
-    CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
-    DCHECK(cache->GetIndex(Name::cast(name), code->flags()) == index);
-    cache->RemoveByIndex(index);
-  } else {
-    FixedArray* array = default_cache();
-    DCHECK(array->length() >= index && array->get(index)->IsCode());
-    // Use null instead of undefined for deleted elements to distinguish
-    // deleted elements from unused elements.  This distinction is used
-    // when looking up in the cache and when updating the cache.
-    DCHECK_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
-    array->set_null(index - 1);  // Name.
-    array->set_null(index);  // Code.
-  }
+Code* Map::LookupInCodeCache(Name* name, Code::Flags flags) {
+  return CodeCache::Lookup(code_cache(), name, flags);
 }
 
 
@@ -10347,20 +9724,23 @@
 class CodeCacheHashTableKey : public HashTableKey {
  public:
   CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
-      : name_(name), flags_(flags), code_() { }
+      : name_(name), flags_(flags), code_() {
+    DCHECK(name_->IsUniqueName());
+  }
 
   CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
-      : name_(name), flags_(code->flags()), code_(code) { }
+      : name_(name), flags_(code->flags()), code_(code) {
+    DCHECK(name_->IsUniqueName());
+  }
 
   bool IsMatch(Object* other) override {
-    if (!other->IsFixedArray()) return false;
+    DCHECK(other->IsFixedArray());
     FixedArray* pair = FixedArray::cast(other);
     Name* name = Name::cast(pair->get(0));
     Code::Flags flags = Code::cast(pair->get(1))->flags();
-    if (flags != flags_) {
-      return false;
-    }
-    return name_->Equals(name);
+    if (flags != flags_) return false;
+    DCHECK(name->IsUniqueName());
+    return *name_ == name;
   }
 
   static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
@@ -10392,15 +9772,6 @@
 };
 
 
-Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
-  DisallowHeapAllocation no_alloc;
-  CodeCacheHashTableKey key(handle(name), flags);
-  int entry = FindEntry(&key);
-  if (entry == kNotFound) return GetHeap()->undefined_value();
-  return get(EntryToIndex(entry) + 1);
-}
-
-
 Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
     Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
   CodeCacheHashTableKey key(name, code);
@@ -10411,179 +9782,18 @@
   Handle<Object> k = key.AsHandle(cache->GetIsolate());
 
   new_cache->set(EntryToIndex(entry), *k);
-  new_cache->set(EntryToIndex(entry) + 1, *code);
   new_cache->ElementAdded();
   return new_cache;
 }
 
-
-int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
+Code* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
   DisallowHeapAllocation no_alloc;
   CodeCacheHashTableKey key(handle(name), flags);
   int entry = FindEntry(&key);
-  return (entry == kNotFound) ? -1 : entry;
+  if (entry == kNotFound) return nullptr;
+  return Code::cast(FixedArray::cast(get(EntryToIndex(entry)))->get(1));
 }
 
-
-void CodeCacheHashTable::RemoveByIndex(int index) {
-  DCHECK(index >= 0);
-  Heap* heap = GetHeap();
-  set(EntryToIndex(index), heap->the_hole_value());
-  set(EntryToIndex(index) + 1, heap->the_hole_value());
-  ElementRemoved();
-}
-
-
-void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> code_cache,
-                                  MapHandleList* maps,
-                                  Code::Flags flags,
-                                  Handle<Code> code) {
-  Isolate* isolate = code_cache->GetIsolate();
-  if (code_cache->cache()->IsUndefined()) {
-    Handle<PolymorphicCodeCacheHashTable> result =
-        PolymorphicCodeCacheHashTable::New(
-            isolate,
-            PolymorphicCodeCacheHashTable::kInitialSize);
-    code_cache->set_cache(*result);
-  } else {
-    // This entry shouldn't be contained in the cache yet.
-    DCHECK(PolymorphicCodeCacheHashTable::cast(code_cache->cache())
-               ->Lookup(maps, flags)->IsUndefined());
-  }
-  Handle<PolymorphicCodeCacheHashTable> hash_table =
-      handle(PolymorphicCodeCacheHashTable::cast(code_cache->cache()));
-  Handle<PolymorphicCodeCacheHashTable> new_cache =
-      PolymorphicCodeCacheHashTable::Put(hash_table, maps, flags, code);
-  code_cache->set_cache(*new_cache);
-}
-
-
-Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
-                                            Code::Flags flags) {
-  if (!cache()->IsUndefined()) {
-    PolymorphicCodeCacheHashTable* hash_table =
-        PolymorphicCodeCacheHashTable::cast(cache());
-    return Handle<Object>(hash_table->Lookup(maps, flags), GetIsolate());
-  } else {
-    return GetIsolate()->factory()->undefined_value();
-  }
-}
-
-
-// Despite their name, object of this class are not stored in the actual
-// hash table; instead they're temporarily used for lookups. It is therefore
-// safe to have a weak (non-owning) pointer to a MapList as a member field.
-class PolymorphicCodeCacheHashTableKey : public HashTableKey {
- public:
-  // Callers must ensure that |maps| outlives the newly constructed object.
-  PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
-      : maps_(maps),
-        code_flags_(code_flags) {}
-
-  bool IsMatch(Object* other) override {
-    MapHandleList other_maps(kDefaultListAllocationSize);
-    int other_flags;
-    FromObject(other, &other_flags, &other_maps);
-    if (code_flags_ != other_flags) return false;
-    if (maps_->length() != other_maps.length()) return false;
-    // Compare just the hashes first because it's faster.
-    int this_hash = MapsHashHelper(maps_, code_flags_);
-    int other_hash = MapsHashHelper(&other_maps, other_flags);
-    if (this_hash != other_hash) return false;
-
-    // Full comparison: for each map in maps_, look for an equivalent map in
-    // other_maps. This implementation is slow, but probably good enough for
-    // now because the lists are short (<= 4 elements currently).
-    for (int i = 0; i < maps_->length(); ++i) {
-      bool match_found = false;
-      for (int j = 0; j < other_maps.length(); ++j) {
-        if (*(maps_->at(i)) == *(other_maps.at(j))) {
-          match_found = true;
-          break;
-        }
-      }
-      if (!match_found) return false;
-    }
-    return true;
-  }
-
-  static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
-    uint32_t hash = code_flags;
-    for (int i = 0; i < maps->length(); ++i) {
-      hash ^= maps->at(i)->Hash();
-    }
-    return hash;
-  }
-
-  uint32_t Hash() override { return MapsHashHelper(maps_, code_flags_); }
-
-  uint32_t HashForObject(Object* obj) override {
-    MapHandleList other_maps(kDefaultListAllocationSize);
-    int other_flags;
-    FromObject(obj, &other_flags, &other_maps);
-    return MapsHashHelper(&other_maps, other_flags);
-  }
-
-  MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
-    // The maps in |maps_| must be copied to a newly allocated FixedArray,
-    // both because the referenced MapList is short-lived, and because C++
-    // objects can't be stored in the heap anyway.
-    Handle<FixedArray> list =
-        isolate->factory()->NewUninitializedFixedArray(maps_->length() + 1);
-    list->set(0, Smi::FromInt(code_flags_));
-    for (int i = 0; i < maps_->length(); ++i) {
-      list->set(i + 1, *maps_->at(i));
-    }
-    return list;
-  }
-
- private:
-  static MapHandleList* FromObject(Object* obj,
-                                   int* code_flags,
-                                   MapHandleList* maps) {
-    FixedArray* list = FixedArray::cast(obj);
-    maps->Rewind(0);
-    *code_flags = Smi::cast(list->get(0))->value();
-    for (int i = 1; i < list->length(); ++i) {
-      maps->Add(Handle<Map>(Map::cast(list->get(i))));
-    }
-    return maps;
-  }
-
-  MapHandleList* maps_;  // weak.
-  int code_flags_;
-  static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
-};
-
-
-Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
-                                              int code_kind) {
-  DisallowHeapAllocation no_alloc;
-  PolymorphicCodeCacheHashTableKey key(maps, code_kind);
-  int entry = FindEntry(&key);
-  if (entry == kNotFound) return GetHeap()->undefined_value();
-  return get(EntryToIndex(entry) + 1);
-}
-
-
-Handle<PolymorphicCodeCacheHashTable> PolymorphicCodeCacheHashTable::Put(
-      Handle<PolymorphicCodeCacheHashTable> hash_table,
-      MapHandleList* maps,
-      int code_kind,
-      Handle<Code> code) {
-  PolymorphicCodeCacheHashTableKey key(maps, code_kind);
-  Handle<PolymorphicCodeCacheHashTable> cache =
-      EnsureCapacity(hash_table, 1, &key);
-  int entry = cache->FindInsertionEntry(key.Hash());
-
-  Handle<Object> obj = key.AsHandle(hash_table->GetIsolate());
-  cache->set(EntryToIndex(entry), *obj);
-  cache->set(EntryToIndex(entry) + 1, *code);
-  cache->ElementAdded();
-  return cache;
-}
-
-
 void FixedArray::Shrink(int new_length) {
   DCHECK(0 <= new_length && new_length <= length());
   if (new_length < length()) {
@@ -10939,7 +10149,7 @@
         .ToHandleChecked();
   }
   Isolate* isolate = accessor_pair->GetIsolate();
-  if (accessor->IsTheHole()) {
+  if (accessor->IsNull(isolate)) {
     return isolate->factory()->undefined_value();
   }
   return handle(accessor, isolate);
@@ -10967,12 +10177,21 @@
   return Handle<DeoptimizationOutputData>::cast(result);
 }
 
+const int LiteralsArray::kFeedbackVectorOffset =
+    LiteralsArray::OffsetOfElementAt(LiteralsArray::kVectorIndex);
+
+const int LiteralsArray::kOffsetToFirstLiteral =
+    LiteralsArray::OffsetOfElementAt(LiteralsArray::kFirstLiteralIndex);
 
 // static
 Handle<LiteralsArray> LiteralsArray::New(Isolate* isolate,
                                          Handle<TypeFeedbackVector> vector,
                                          int number_of_literals,
                                          PretenureFlag pretenure) {
+  if (vector->is_empty() && number_of_literals == 0) {
+    return Handle<LiteralsArray>::cast(
+        isolate->factory()->empty_literals_array());
+  }
   Handle<FixedArray> literals = isolate->factory()->NewFixedArray(
       number_of_literals + kFirstLiteralIndex, pretenure);
   Handle<LiteralsArray> casted_literals = Handle<LiteralsArray>::cast(literals);
@@ -11040,6 +10259,34 @@
 }
 #endif
 
+// static
+Handle<String> String::Trim(Handle<String> string, TrimMode mode) {
+  Isolate* const isolate = string->GetIsolate();
+  string = String::Flatten(string);
+  int const length = string->length();
+
+  // Perform left trimming if requested.
+  int left = 0;
+  UnicodeCache* unicode_cache = isolate->unicode_cache();
+  if (mode == kTrim || mode == kTrimLeft) {
+    while (left < length &&
+           unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(left))) {
+      left++;
+    }
+  }
+
+  // Perform right trimming if requested.
+  int right = length;
+  if (mode == kTrim || mode == kTrimRight) {
+    while (
+        right > left &&
+        unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) {
+      right--;
+    }
+  }
+
+  return isolate->factory()->NewSubString(string, left, right);
+}
 
 bool String::LooksValid() {
   if (!GetIsolate()->heap()->Contains(this)) return false;
@@ -11053,7 +10300,9 @@
   // ES6 section 9.2.11 SetFunctionName, step 4.
   Isolate* const isolate = name->GetIsolate();
   Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate);
-  if (description->IsUndefined()) return isolate->factory()->empty_string();
+  if (description->IsUndefined(isolate)) {
+    return isolate->factory()->empty_string();
+  }
   IncrementalStringBuilder builder(isolate);
   builder.AppendCharacter('[');
   builder.AppendString(Handle<String>::cast(description));
@@ -11061,6 +10310,19 @@
   return builder.Finish();
 }
 
+// static
+MaybeHandle<String> Name::ToFunctionName(Handle<Name> name,
+                                         Handle<String> prefix) {
+  Handle<String> name_string;
+  Isolate* const isolate = name->GetIsolate();
+  ASSIGN_RETURN_ON_EXCEPTION(isolate, name_string, ToFunctionName(name),
+                             String);
+  IncrementalStringBuilder builder(isolate);
+  builder.AppendString(prefix);
+  builder.AppendCharacter(' ');
+  builder.AppendString(name_string);
+  return builder.Finish();
+}
 
 namespace {
 
@@ -11268,25 +10530,6 @@
 }
 
 
-base::SmartArrayPointer<uc16> String::ToWideCString(
-    RobustnessFlag robust_flag) {
-  if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
-    return base::SmartArrayPointer<uc16>();
-  }
-  StringCharacterStream stream(this);
-
-  uc16* result = NewArray<uc16>(length() + 1);
-
-  int i = 0;
-  while (stream.HasMore()) {
-    uint16_t character = stream.GetNext();
-    result[i++] = character;
-  }
-  result[i] = 0;
-  return base::SmartArrayPointer<uc16>(result);
-}
-
-
 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
   return reinterpret_cast<uc16*>(
       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
@@ -12155,8 +11398,8 @@
   value |= length << String::ArrayIndexLengthBits::kShift;
 
   DCHECK((value & String::kIsNotArrayIndexMask) == 0);
-  DCHECK((length > String::kMaxCachedArrayIndexLength) ||
-         (value & String::kContainsCachedArrayIndexMask) == 0);
+  DCHECK_EQ(length <= String::kMaxCachedArrayIndexLength,
+            (value & String::kContainsCachedArrayIndexMask) == 0);
   return value;
 }
 
@@ -12332,15 +11575,18 @@
   return false;
 }
 
+void JSFunction::MarkForBaseline() {
+  Isolate* isolate = GetIsolate();
+  set_code_no_write_barrier(
+      isolate->builtins()->builtin(Builtins::kCompileBaseline));
+  // No write barrier required, since the builtin is part of the root set.
+}
 
 void JSFunction::MarkForOptimization() {
   Isolate* isolate = GetIsolate();
-  // Do not optimize if function contains break points.
-  if (shared()->HasDebugInfo()) return;
   DCHECK(!IsOptimized());
   DCHECK(shared()->allows_lazy_compilation() ||
          !shared()->optimization_disabled());
-  DCHECK(!shared()->HasDebugInfo());
   set_code_no_write_barrier(
       isolate->builtins()->builtin(Builtins::kCompileOptimized));
   // No write barrier required, since the builtin is part of the root set.
@@ -12369,6 +11615,30 @@
   // No write barrier required, since the builtin is part of the root set.
 }
 
+// static
+Handle<LiteralsArray> SharedFunctionInfo::FindOrCreateLiterals(
+    Handle<SharedFunctionInfo> shared, Handle<Context> native_context) {
+  Isolate* isolate = shared->GetIsolate();
+  CodeAndLiterals result =
+      shared->SearchOptimizedCodeMap(*native_context, BailoutId::None());
+  if (result.literals != nullptr) {
+    DCHECK(shared->feedback_metadata()->is_empty() ||
+           !result.literals->feedback_vector()->is_empty());
+    return handle(result.literals, isolate);
+  }
+
+  Handle<TypeFeedbackVector> feedback_vector =
+      TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata()));
+  Handle<LiteralsArray> literals = LiteralsArray::New(
+      isolate, feedback_vector, shared->num_literals(), TENURED);
+  Handle<Code> code;
+  if (result.code != nullptr) {
+    code = Handle<Code>(result.code, isolate);
+  }
+  AddToOptimizedCodeMap(shared, native_context, code, literals,
+                        BailoutId::None());
+  return literals;
+}
 
 void SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(
     Handle<SharedFunctionInfo> shared, Handle<Code> code) {
@@ -12415,9 +11685,13 @@
             isolate->factory()->NewWeakCell(code.ToHandleChecked());
         old_code_map->set(entry + kCachedCodeOffset, *code_cell);
       }
-      Handle<WeakCell> literals_cell =
-          isolate->factory()->NewWeakCell(literals);
-      old_code_map->set(entry + kLiteralsOffset, *literals_cell);
+      if (literals->literals_count() == 0) {
+        old_code_map->set(entry + kLiteralsOffset, *literals);
+      } else {
+        Handle<WeakCell> literals_cell =
+            isolate->factory()->NewWeakCell(literals);
+        old_code_map->set(entry + kLiteralsOffset, *literals_cell);
+      }
       return;
     }
 
@@ -12448,12 +11722,18 @@
   Handle<WeakCell> code_cell =
       code.is_null() ? isolate->factory()->empty_weak_cell()
                      : isolate->factory()->NewWeakCell(code.ToHandleChecked());
-  Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals);
   WeakCell* context_cell = native_context->self_weak_cell();
 
   new_code_map->set(entry + kContextOffset, context_cell);
   new_code_map->set(entry + kCachedCodeOffset, *code_cell);
-  new_code_map->set(entry + kLiteralsOffset, *literals_cell);
+
+  if (literals->literals_count() == 0) {
+    new_code_map->set(entry + kLiteralsOffset, *literals);
+  } else {
+    Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals);
+    new_code_map->set(entry + kLiteralsOffset, *literals_cell);
+  }
+
   new_code_map->set(entry + kOsrAstIdOffset, Smi::FromInt(osr_ast_id.ToInt()));
 
 #ifdef DEBUG
@@ -12464,8 +11744,16 @@
     DCHECK(cell->cleared() ||
            (cell->value()->IsCode() &&
             Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION));
-    cell = WeakCell::cast(new_code_map->get(i + kLiteralsOffset));
-    DCHECK(cell->cleared() || cell->value()->IsFixedArray());
+    Object* lits = new_code_map->get(i + kLiteralsOffset);
+    if (lits->IsWeakCell()) {
+      cell = WeakCell::cast(lits);
+      DCHECK(cell->cleared() ||
+             (cell->value()->IsLiteralsArray() &&
+              LiteralsArray::cast(cell->value())->literals_count() > 0));
+    } else {
+      DCHECK(lits->IsLiteralsArray() &&
+             LiteralsArray::cast(lits)->literals_count() == 0);
+    }
     DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
   }
 #endif
@@ -12565,6 +11853,17 @@
   }
 }
 
+// static
+void JSFunction::EnsureLiterals(Handle<JSFunction> function) {
+  Handle<SharedFunctionInfo> shared(function->shared());
+  Handle<Context> native_context(function->context()->native_context());
+  if (function->literals() ==
+      function->GetIsolate()->heap()->empty_literals_array()) {
+    Handle<LiteralsArray> literals =
+        SharedFunctionInfo::FindOrCreateLiterals(shared, native_context);
+    function->set_literals(*literals);
+  }
+}
 
 static void GetMinInobjectSlack(Map* map, void* data) {
   int slack = map->unused_property_fields();
@@ -12591,7 +11890,7 @@
 
 void Map::CompleteInobjectSlackTracking() {
   // Has to be an initial map.
-  DCHECK(GetBackPointer()->IsUndefined());
+  DCHECK(GetBackPointer()->IsUndefined(GetIsolate()));
 
   int slack = unused_property_fields();
   TransitionArray::TraverseTransitionTree(this, &GetMinInobjectSlack, &slack);
@@ -12622,6 +11921,26 @@
   return false;
 }
 
+// static
+void JSObject::MakePrototypesFast(Handle<Object> receiver,
+                                  WhereToStart where_to_start,
+                                  Isolate* isolate) {
+  if (!receiver->IsJSReceiver()) return;
+  for (PrototypeIterator iter(isolate, Handle<JSReceiver>::cast(receiver),
+                              where_to_start);
+       !iter.IsAtEnd(); iter.Advance()) {
+    Handle<Object> current = PrototypeIterator::GetCurrent(iter);
+    if (!current->IsJSObject()) return;
+    Handle<JSObject> current_obj = Handle<JSObject>::cast(current);
+    Map* current_map = current_obj->map();
+    if (current_map->is_prototype_map() &&
+        !current_map->should_be_fast_prototype_map()) {
+      Handle<Map> map(current_map);
+      Map::SetShouldBeFastPrototypeMap(map, true, isolate);
+      JSObject::OptimizeAsPrototype(current_obj, FAST_PROTOTYPE);
+    }
+  }
+}
 
 // static
 void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
@@ -12633,10 +11952,12 @@
                                   "NormalizeAsPrototype");
   }
   Handle<Map> previous_map(object->map());
-  if (!object->HasFastProperties()) {
-    JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
-  }
-  if (!object->map()->is_prototype_map()) {
+  if (object->map()->is_prototype_map()) {
+    if (object->map()->should_be_fast_prototype_map() &&
+        !object->HasFastProperties()) {
+      JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
+    }
+  } else {
     if (object->map() == *previous_map) {
       Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype");
       JSObject::MigrateToMap(object, new_map);
@@ -12664,13 +11985,13 @@
 // static
 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
   if (!object->map()->is_prototype_map()) return;
+  if (!object->map()->should_be_fast_prototype_map()) return;
   OptimizeAsPrototype(object, FAST_PROTOTYPE);
 }
 
 
 // static
 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
-  DCHECK(FLAG_track_prototype_users);
   // Contract: In line with InvalidatePrototypeChains()'s requirements,
   // leaf maps don't need to register as users, only prototypes do.
   DCHECK(user->is_prototype_map());
@@ -12776,7 +12097,6 @@
 
 // static
 void JSObject::InvalidatePrototypeChains(Map* map) {
-  if (!FLAG_eliminate_prototype_chain_checks) return;
   DisallowHeapAllocation no_gc;
   InvalidatePrototypeChainsInternal(map);
 }
@@ -12807,6 +12127,15 @@
   return proto_info;
 }
 
+// static
+void Map::SetShouldBeFastPrototypeMap(Handle<Map> map, bool value,
+                                      Isolate* isolate) {
+  if (value == false && !map->prototype_info()->IsPrototypeInfo()) {
+    // "False" is the implicit default value, so there's nothing to do.
+    return;
+  }
+  GetOrCreatePrototypeInfo(map, isolate)->set_should_be_fast_map(value);
+}
 
 // static
 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
@@ -12839,6 +12168,8 @@
 // static
 void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype,
                        PrototypeOptimizationMode proto_mode) {
+  RuntimeCallTimerScope stats_scope(*map, &RuntimeCallStats::Map_SetPrototype);
+
   bool is_hidden = false;
   if (prototype->IsJSObject()) {
     Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
@@ -12855,8 +12186,9 @@
   }
   map->set_has_hidden_prototype(is_hidden);
 
-  WriteBarrierMode wb_mode =
-      prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
+  WriteBarrierMode wb_mode = prototype->IsNull(map->GetIsolate())
+                                 ? SKIP_WRITE_BARRIER
+                                 : UPDATE_WRITE_BARRIER;
   map->set_prototype(*prototype, wb_mode);
 }
 
@@ -12964,8 +12296,13 @@
     new_map->SetConstructor(*value);
     new_map->set_non_instance_prototype(true);
     Isolate* isolate = new_map->GetIsolate();
+
     construct_prototype = handle(
-        function->context()->native_context()->initial_object_prototype(),
+        IsGeneratorFunction(function->shared()->kind())
+            ? function->context()
+                  ->native_context()
+                  ->initial_generator_prototype()
+            : function->context()->native_context()->initial_object_prototype(),
         isolate);
   } else {
     function->map()->set_non_instance_prototype(false);
@@ -13020,50 +12357,54 @@
 
 bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
   switch (instance_type) {
-    case JS_OBJECT_TYPE:
-    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
-    case JS_GENERATOR_OBJECT_TYPE:
-    case JS_MODULE_TYPE:
-    case JS_VALUE_TYPE:
-    case JS_DATE_TYPE:
-    case JS_ARRAY_TYPE:
-    case JS_MESSAGE_OBJECT_TYPE:
+    case JS_API_OBJECT_TYPE:
     case JS_ARRAY_BUFFER_TYPE:
-    case JS_TYPED_ARRAY_TYPE:
+    case JS_ARRAY_TYPE:
+    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
     case JS_DATA_VIEW_TYPE:
-    case JS_SET_TYPE:
-    case JS_MAP_TYPE:
-    case JS_SET_ITERATOR_TYPE:
+    case JS_DATE_TYPE:
+    case JS_FUNCTION_TYPE:
+    case JS_GENERATOR_OBJECT_TYPE:
     case JS_MAP_ITERATOR_TYPE:
-    case JS_WEAK_MAP_TYPE:
-    case JS_WEAK_SET_TYPE:
+    case JS_MAP_TYPE:
+    case JS_MESSAGE_OBJECT_TYPE:
+    case JS_MODULE_TYPE:
+    case JS_OBJECT_TYPE:
+    case JS_ERROR_TYPE:
+    case JS_ARGUMENTS_TYPE:
     case JS_PROMISE_TYPE:
     case JS_REGEXP_TYPE:
-    case JS_FUNCTION_TYPE:
+    case JS_SET_ITERATOR_TYPE:
+    case JS_SET_TYPE:
+    case JS_SPECIAL_API_OBJECT_TYPE:
+    case JS_TYPED_ARRAY_TYPE:
+    case JS_VALUE_TYPE:
+    case JS_WEAK_MAP_TYPE:
+    case JS_WEAK_SET_TYPE:
       return true;
 
-    case JS_BOUND_FUNCTION_TYPE:
-    case JS_PROXY_TYPE:
-    case JS_GLOBAL_PROXY_TYPE:
-    case JS_GLOBAL_OBJECT_TYPE:
+    case BYTECODE_ARRAY_TYPE:
+    case BYTE_ARRAY_TYPE:
+    case CELL_TYPE:
+    case CODE_TYPE:
+    case FILLER_TYPE:
     case FIXED_ARRAY_TYPE:
     case FIXED_DOUBLE_ARRAY_TYPE:
-    case ODDBALL_TYPE:
     case FOREIGN_TYPE:
-    case MAP_TYPE:
-    case CODE_TYPE:
-    case CELL_TYPE:
-    case PROPERTY_CELL_TYPE:
-    case WEAK_CELL_TYPE:
-    case SYMBOL_TYPE:
-    case BYTECODE_ARRAY_TYPE:
-    case HEAP_NUMBER_TYPE:
-    case MUTABLE_HEAP_NUMBER_TYPE:
-    case SIMD128_VALUE_TYPE:
-    case FILLER_TYPE:
-    case BYTE_ARRAY_TYPE:
     case FREE_SPACE_TYPE:
+    case HEAP_NUMBER_TYPE:
+    case JS_BOUND_FUNCTION_TYPE:
+    case JS_GLOBAL_OBJECT_TYPE:
+    case JS_GLOBAL_PROXY_TYPE:
+    case JS_PROXY_TYPE:
+    case MAP_TYPE:
+    case MUTABLE_HEAP_NUMBER_TYPE:
+    case ODDBALL_TYPE:
+    case PROPERTY_CELL_TYPE:
     case SHARED_FUNCTION_INFO_TYPE:
+    case SIMD128_VALUE_TYPE:
+    case SYMBOL_TYPE:
+    case WEAK_CELL_TYPE:
 
 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
   case FIXED_##TYPE##_ARRAY_TYPE:
@@ -13085,7 +12426,7 @@
 
 
 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
-  DCHECK(function->IsConstructor() || function->shared()->is_generator());
+  DCHECK(function->IsConstructor() || function->shared()->is_resumable());
   if (function->has_initial_map()) return;
   Isolate* isolate = function->GetIsolate();
 
@@ -13096,7 +12437,7 @@
   // First create a new map with the size and number of in-object properties
   // suggested by the function.
   InstanceType instance_type;
-  if (function->shared()->is_generator()) {
+  if (function->shared()->is_resumable()) {
     instance_type = JS_GENERATOR_OBJECT_TYPE;
   } else {
     instance_type = JS_OBJECT_TYPE;
@@ -13296,18 +12637,6 @@
   return isolate->factory()->NewStringFromAsciiChecked(kNativeCodeSource);
 }
 
-// static
-MaybeHandle<String> JSBoundFunction::GetName(Isolate* isolate,
-                                             Handle<JSBoundFunction> function) {
-  Handle<String> prefix = isolate->factory()->bound__string();
-  if (!function->bound_target_function()->IsJSFunction()) return prefix;
-  Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()),
-                            isolate);
-  Handle<Object> target_name = JSFunction::GetName(target);
-  if (!target_name->IsString()) return prefix;
-  Factory* factory = isolate->factory();
-  return factory->NewConsString(prefix, Handle<String>::cast(target_name));
-}
 
 // static
 Handle<String> JSFunction::ToString(Handle<JSFunction> function) {
@@ -13341,10 +12670,16 @@
   IncrementalStringBuilder builder(isolate);
   if (!shared_info->is_arrow()) {
     if (shared_info->is_concise_method()) {
-      if (shared_info->is_generator()) builder.AppendCharacter('*');
+      if (shared_info->is_generator()) {
+        builder.AppendCharacter('*');
+      } else if (shared_info->is_async()) {
+        builder.AppendCString("async ");
+      }
     } else {
       if (shared_info->is_generator()) {
         builder.AppendCString("function* ");
+      } else if (shared_info->is_async()) {
+        builder.AppendCString("async function ");
       } else {
         builder.AppendCString("function ");
       }
@@ -13366,6 +12701,7 @@
       isolate->factory()->InternalizeUtf8String(to_string);
   Handle<String> internalized_type_of =
       isolate->factory()->InternalizeUtf8String(type_of);
+  oddball->set_to_number_raw(to_number->Number());
   oddball->set_to_boolean(isolate->heap()->ToBoolean(to_boolean));
   oddball->set_to_number(*to_number);
   oddball->set_to_string(*internalized_to_string);
@@ -13373,14 +12709,52 @@
   oddball->set_kind(kind);
 }
 
+void Script::SetEvalOrigin(Handle<Script> script,
+                           Handle<SharedFunctionInfo> outer_info,
+                           int eval_position) {
+  if (eval_position == RelocInfo::kNoPosition) {
+    // If the position is missing, attempt to get the code offset from the
+    // current activation.  Do not translate the code offset into source
+    // position, but store it as negative value for lazy translation.
+    StackTraceFrameIterator it(script->GetIsolate());
+    if (!it.done() && it.is_javascript()) {
+      FrameSummary summary = FrameSummary::GetFirst(it.javascript_frame());
+      script->set_eval_from_shared(summary.function()->shared());
+      script->set_eval_from_position(-summary.code_offset());
+      return;
+    }
+    eval_position = 0;
+  }
+  script->set_eval_from_shared(*outer_info);
+  script->set_eval_from_position(eval_position);
+}
+
+int Script::GetEvalPosition() {
+  DisallowHeapAllocation no_gc;
+  DCHECK(compilation_type() == Script::COMPILATION_TYPE_EVAL);
+  int position = eval_from_position();
+  if (position < 0) {
+    // Due to laziness, the position may not have been translated from code
+    // offset yet, which would be encoded as negative integer. In that case,
+    // translate and set the position.
+    if (eval_from_shared()->IsUndefined(GetIsolate())) {
+      position = 0;
+    } else {
+      SharedFunctionInfo* shared = SharedFunctionInfo::cast(eval_from_shared());
+      position = shared->abstract_code()->SourcePosition(-position);
+    }
+    DCHECK(position >= 0);
+    set_eval_from_position(position);
+  }
+  return position;
+}
 
 void Script::InitLineEnds(Handle<Script> script) {
-  if (!script->line_ends()->IsUndefined()) return;
-
   Isolate* isolate = script->GetIsolate();
+  if (!script->line_ends()->IsUndefined(isolate)) return;
 
   if (!script->source()->IsString()) {
-    DCHECK(script->source()->IsUndefined());
+    DCHECK(script->source()->IsUndefined(isolate));
     Handle<FixedArray> empty = isolate->factory()->NewFixedArray(0);
     script->set_line_ends(*empty);
     DCHECK(script->line_ends()->IsFixedArray());
@@ -13399,42 +12773,93 @@
   DCHECK(script->line_ends()->IsFixedArray());
 }
 
-
-int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
-  int line_number = GetLineNumber(script, code_pos);
-  if (line_number == -1) return -1;
+#define SMI_VALUE(x) (Smi::cast(x)->value())
+bool Script::GetPositionInfo(int position, PositionInfo* info,
+                             OffsetFlag offset_flag) {
+  Handle<Script> script(this);
+  InitLineEnds(script);
 
   DisallowHeapAllocation no_allocation;
-  FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
-  line_number = line_number - script->line_offset();
-  if (line_number == 0) return code_pos + script->column_offset();
-  int prev_line_end_pos =
-      Smi::cast(line_ends_array->get(line_number - 1))->value();
-  return code_pos - (prev_line_end_pos + 1);
-}
 
+  DCHECK(script->line_ends()->IsFixedArray());
+  FixedArray* ends = FixedArray::cast(script->line_ends());
 
-int Script::GetLineNumberWithArray(int code_pos) {
-  DisallowHeapAllocation no_allocation;
-  DCHECK(line_ends()->IsFixedArray());
-  FixedArray* line_ends_array = FixedArray::cast(line_ends());
-  int line_ends_len = line_ends_array->length();
-  if (line_ends_len == 0) return -1;
+  const int ends_len = ends->length();
+  if (ends_len == 0) return false;
 
-  if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) {
-    return line_offset();
+  // Return early on invalid positions. Negative positions behave as if 0 was
+  // passed, and positions beyond the end of the script return as failure.
+  if (position < 0) {
+    position = 0;
+  } else if (position > SMI_VALUE(ends->get(ends_len - 1))) {
+    return false;
   }
 
-  int left = 0;
-  int right = line_ends_len;
-  while (int half = (right - left) / 2) {
-    if ((Smi::cast(line_ends_array->get(left + half)))->value() > code_pos) {
-      right -= half;
-    } else {
-      left += half;
+  // Determine line number by doing a binary search on the line ends array.
+  if (SMI_VALUE(ends->get(0)) >= position) {
+    info->line = 0;
+    info->line_start = 0;
+    info->column = position;
+  } else {
+    int left = 0;
+    int right = ends_len - 1;
+
+    while (right > 0) {
+      DCHECK_LE(left, right);
+      const int mid = (left + right) / 2;
+      if (position > SMI_VALUE(ends->get(mid))) {
+        left = mid + 1;
+      } else if (position <= SMI_VALUE(ends->get(mid - 1))) {
+        right = mid - 1;
+      } else {
+        info->line = mid;
+        break;
+      }
+    }
+    DCHECK(SMI_VALUE(ends->get(info->line)) >= position &&
+           SMI_VALUE(ends->get(info->line - 1)) < position);
+    info->line_start = SMI_VALUE(ends->get(info->line - 1)) + 1;
+    info->column = position - info->line_start;
+  }
+
+  // Line end is position of the linebreak character.
+  info->line_end = SMI_VALUE(ends->get(info->line));
+  if (info->line_end > 0) {
+    DCHECK(script->source()->IsString());
+    Handle<String> src(String::cast(script->source()));
+    if (src->Get(info->line_end - 1) == '\r') {
+      info->line_end--;
     }
   }
-  return right + line_offset();
+
+  // Add offsets if requested.
+  if (offset_flag == WITH_OFFSET) {
+    if (info->line == 0) {
+      info->column += script->column_offset();
+    }
+    info->line += script->line_offset();
+  }
+
+  return true;
+}
+#undef SMI_VALUE
+
+int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
+  PositionInfo info;
+  if (!script->GetPositionInfo(code_pos, &info, WITH_OFFSET)) {
+    return -1;
+  }
+
+  return info.column;
+}
+
+int Script::GetLineNumberWithArray(int code_pos) {
+  PositionInfo info;
+  if (!GetPositionInfo(code_pos, &info, WITH_OFFSET)) {
+    return -1;
+  }
+
+  return info.line;
 }
 
 
@@ -13446,7 +12871,9 @@
 
 int Script::GetLineNumber(int code_pos) {
   DisallowHeapAllocation no_allocation;
-  if (!line_ends()->IsUndefined()) return GetLineNumberWithArray(code_pos);
+  if (!line_ends()->IsUndefined(GetIsolate())) {
+    return GetLineNumberWithArray(code_pos);
+  }
 
   // Slow mode: we do not have line_ends. We have to iterate through source.
   if (!source()->IsString()) return -1;
@@ -13485,7 +12912,7 @@
 
 Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
   Isolate* isolate = script->GetIsolate();
-  if (!script->wrapper()->IsUndefined()) {
+  if (!script->wrapper()->IsUndefined(isolate)) {
     DCHECK(script->wrapper()->IsWeakCell());
     Handle<WeakCell> cell(WeakCell::cast(script->wrapper()));
     if (!cell->cleared()) {
@@ -13515,7 +12942,8 @@
   SharedFunctionInfo* shared;
   while ((shared = iterator.Next<SharedFunctionInfo>())) {
     if (fun->function_token_position() == shared->function_token_position() &&
-        fun->start_position() == shared->start_position()) {
+        fun->start_position() == shared->start_position() &&
+        fun->end_position() == shared->end_position()) {
       return Handle<SharedFunctionInfo>(shared);
     }
   }
@@ -13649,8 +13077,9 @@
 }
 
 bool SharedFunctionInfo::HasSourceCode() const {
-  return !script()->IsUndefined() &&
-         !reinterpret_cast<Script*>(script())->source()->IsUndefined();
+  Isolate* isolate = GetIsolate();
+  return !script()->IsUndefined(isolate) &&
+         !reinterpret_cast<Script*>(script())->source()->IsUndefined(isolate);
 }
 
 
@@ -13706,9 +13135,8 @@
     int* instance_size, int* in_object_properties) {
   Isolate* isolate = GetIsolate();
   int expected_nof_properties = 0;
-  for (PrototypeIterator iter(isolate, this,
-                              PrototypeIterator::START_AT_RECEIVER);
-       !iter.IsAtEnd(); iter.Advance()) {
+  for (PrototypeIterator iter(isolate, this, kStartAtReceiver); !iter.IsAtEnd();
+       iter.Advance()) {
     JSReceiver* current = iter.GetCurrent<JSReceiver>();
     if (!current->IsJSFunction()) break;
     JSFunction* func = JSFunction::cast(current);
@@ -13813,6 +13241,32 @@
   }
 }
 
+namespace {
+
+// Sets the expected number of properties based on estimate from parser.
+void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
+                                          FunctionLiteral* literal) {
+  int estimate = literal->expected_property_count();
+
+  // If no properties are added in the constructor, they are more likely
+  // to be added later.
+  if (estimate == 0) estimate = 2;
+
+  // TODO(yangguo): check whether those heuristics are still up-to-date.
+  // We do not shrink objects that go into a snapshot (yet), so we adjust
+  // the estimate conservatively.
+  if (shared->GetIsolate()->serializer_enabled()) {
+    estimate += 2;
+  } else {
+    // Inobject slack tracking will reclaim redundant inobject space later,
+    // so we can afford to adjust the estimate generously.
+    estimate += 8;
+  }
+
+  shared->set_expected_nof_properties(estimate);
+}
+
+}  // namespace
 
 void SharedFunctionInfo::InitFromFunctionLiteral(
     Handle<SharedFunctionInfo> shared_info, FunctionLiteral* lit) {
@@ -13831,13 +13285,8 @@
   shared_info->set_language_mode(lit->language_mode());
   shared_info->set_uses_arguments(lit->scope()->arguments() != NULL);
   shared_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
-  shared_info->set_ast_node_count(lit->ast_node_count());
   shared_info->set_is_function(lit->is_function());
-  if (lit->dont_optimize_reason() != kNoReason) {
-    shared_info->DisableOptimization(lit->dont_optimize_reason());
-  }
-  shared_info->set_dont_crankshaft(lit->flags() &
-                                   AstProperties::kDontCrankshaft);
+  shared_info->set_never_compiled(true);
   shared_info->set_kind(lit->kind());
   if (!IsConstructable(lit->kind(), lit->language_mode())) {
     shared_info->set_construct_stub(
@@ -13845,6 +13294,7 @@
   }
   shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
   shared_info->set_asm_function(lit->scope()->asm_function());
+  SetExpectedNofPropertiesFromEstimate(shared_info, lit);
 }
 
 
@@ -13874,14 +13324,18 @@
 
 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
   code()->ClearInlineCaches();
-  // If we clear ICs, we need to clear the type feedback vector too, since
-  // CallICs are synced with a feedback vector slot.
-  ClearTypeFeedbackInfo();
   set_ic_age(new_ic_age);
   if (code()->kind() == Code::FUNCTION) {
     code()->set_profiler_ticks(0);
-    if (optimization_disabled() &&
-        opt_count() >= FLAG_max_opt_count) {
+    if (optimization_disabled() && opt_count() >= FLAG_max_opt_count) {
+      // Re-enable optimizations if they were disabled due to opt_count limit.
+      set_optimization_disabled(false);
+    }
+    set_opt_count(0);
+    set_deopt_count(0);
+  } else if (code()->is_interpreter_trampoline_builtin()) {
+    set_profiler_ticks(0);
+    if (optimization_disabled() && opt_count() >= FLAG_max_opt_count) {
       // Re-enable optimizations if they were disabled due to opt_count limit.
       set_optimization_disabled(false);
     }
@@ -13915,6 +13369,19 @@
   return -1;
 }
 
+void SharedFunctionInfo::ClearCodeFromOptimizedCodeMap() {
+  if (!OptimizedCodeMapIsCleared()) {
+    FixedArray* optimized_code_map = this->optimized_code_map();
+    int length = optimized_code_map->length();
+    WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell();
+    for (int i = kEntriesStart; i < length; i += kEntryLength) {
+      optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell,
+                              SKIP_WRITE_BARRIER);
+    }
+    optimized_code_map->set(kSharedCodeIndex, empty_weak_cell,
+                            SKIP_WRITE_BARRIER);
+  }
+}
 
 CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap(
     Context* native_context, BailoutId osr_ast_id) {
@@ -13932,21 +13399,20 @@
     } else {
       DCHECK_LE(entry + kEntryLength, code_map->length());
       WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset));
-      WeakCell* literals_cell =
-          WeakCell::cast(code_map->get(entry + kLiteralsOffset));
-
+      Object* lits = code_map->get(entry + kLiteralsOffset);
+      LiteralsArray* literals = nullptr;
+      if (lits->IsWeakCell()) {
+        WeakCell* literal_cell = WeakCell::cast(lits);
+        if (!literal_cell->cleared()) {
+          literals = LiteralsArray::cast(literal_cell->value());
+        }
+      } else {
+        literals = LiteralsArray::cast(lits);
+      }
       result = {cell->cleared() ? nullptr : Code::cast(cell->value()),
-                literals_cell->cleared()
-                    ? nullptr
-                    : LiteralsArray::cast(literals_cell->value())};
+                literals};
     }
   }
-  if (FLAG_trace_opt && !OptimizedCodeMapIsCleared() &&
-      result.code == nullptr) {
-    PrintF("[didn't find optimized code in optimized code map for ");
-    ShortPrint();
-    PrintF("]\n");
-  }
   return result;
 }
 
@@ -13969,63 +13435,66 @@
 
 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
   DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
-  Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
-  Object* old_target = target;
-  VisitPointer(&target);
-  CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
+  Object* old_pointer = Code::GetCodeFromTargetAddress(rinfo->target_address());
+  Object* new_pointer = old_pointer;
+  VisitPointer(&new_pointer);
+  DCHECK_EQ(old_pointer, new_pointer);
 }
 
 
 void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) {
   DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
-  Object* stub = rinfo->code_age_stub();
-  if (stub) {
-    VisitPointer(&stub);
+  Object* old_pointer = rinfo->code_age_stub();
+  Object* new_pointer = old_pointer;
+  if (old_pointer != nullptr) {
+    VisitPointer(&new_pointer);
+    DCHECK_EQ(old_pointer, new_pointer);
   }
 }
 
 
 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
-  Object* code = Code::GetObjectFromEntryAddress(entry_address);
-  Object* old_code = code;
-  VisitPointer(&code);
-  if (code != old_code) {
-    Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
-  }
+  Object* old_pointer = Code::GetObjectFromEntryAddress(entry_address);
+  Object* new_pointer = old_pointer;
+  VisitPointer(&new_pointer);
+  DCHECK_EQ(old_pointer, new_pointer);
 }
 
 
 void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
   DCHECK(rinfo->rmode() == RelocInfo::CELL);
-  Object* cell = rinfo->target_cell();
-  Object* old_cell = cell;
-  VisitPointer(&cell);
-  if (cell != old_cell) {
-    rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
-  }
+  Object* old_pointer = rinfo->target_cell();
+  Object* new_pointer = old_pointer;
+  VisitPointer(&new_pointer);
+  DCHECK_EQ(old_pointer, new_pointer);
 }
 
 
 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
   DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
          rinfo->IsPatchedDebugBreakSlotSequence());
-  Object* target = Code::GetCodeFromTargetAddress(rinfo->debug_call_address());
-  Object* old_target = target;
-  VisitPointer(&target);
-  CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
+  Object* old_pointer =
+      Code::GetCodeFromTargetAddress(rinfo->debug_call_address());
+  Object* new_pointer = old_pointer;
+  VisitPointer(&new_pointer);
+  DCHECK_EQ(old_pointer, new_pointer);
 }
 
 
 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
   DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
-  Object* p = rinfo->target_object();
-  VisitPointer(&p);
+  Object* old_pointer = rinfo->target_object();
+  Object* new_pointer = old_pointer;
+  VisitPointer(&new_pointer);
+  DCHECK_EQ(old_pointer, new_pointer);
 }
 
 
 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
-  Address p = rinfo->target_external_reference();
-  VisitExternalReference(&p);
+  Address old_reference = rinfo->target_external_reference();
+  Address new_reference = old_reference;
+  VisitExternalReference(&new_reference);
+  DCHECK_EQ(old_reference, new_reference);
 }
 
 
@@ -14064,6 +13533,14 @@
   CopyBytes(instruction_start(), desc.buffer,
             static_cast<size_t>(desc.instr_size));
 
+  // copy unwinding info, if any
+  if (desc.unwinding_info) {
+    DCHECK_GT(desc.unwinding_info_size, 0);
+    set_unwinding_info_size(desc.unwinding_info_size);
+    CopyBytes(unwinding_info_start(), desc.unwinding_info,
+              static_cast<size_t>(desc.unwinding_info_size));
+  }
+
   // copy reloc info
   CopyBytes(relocation_start(),
             desc.buffer + desc.buffer_size - desc.reloc_size,
@@ -14116,31 +13593,14 @@
 // The position returned is relative to the beginning of the script where the
 // source for this function is found.
 int Code::SourcePosition(int code_offset) {
-  Address pc = instruction_start() + code_offset;
-  int distance = kMaxInt;
+  // Subtract one because the current PC is one instruction after the call site.
+  Address pc = instruction_start() + code_offset - 1;
   int position = RelocInfo::kNoPosition;  // Initially no position found.
-  // Run through all the relocation info to find the best matching source
-  // position. All the code needs to be considered as the sequence of the
-  // instructions in the code does not necessarily follow the same order as the
-  // source.
-  RelocIterator it(this, RelocInfo::kPositionMask);
-  while (!it.done()) {
-    // Only look at positions after the current pc.
-    if (it.rinfo()->pc() < pc) {
-      // Get position and distance.
-
-      int dist = static_cast<int>(pc - it.rinfo()->pc());
-      int pos = static_cast<int>(it.rinfo()->data());
-      // If this position is closer than the current candidate or if it has the
-      // same distance as the current candidate and the position is higher then
-      // this position is the new candidate.
-      if ((dist < distance) ||
-          (dist == distance && pos > position)) {
-        position = pos;
-        distance = dist;
-      }
-    }
-    it.next();
+  // Find the closest position attached to a pc lower or equal to the current.
+  // Note that the pc of reloc infos grow monotonically.
+  for (RelocIterator it(this, RelocInfo::kPositionMask);
+       !it.done() && it.rinfo()->pc() <= pc; it.next()) {
+    position = static_cast<int>(it.rinfo()->data());
   }
   DCHECK(kind() == FUNCTION || (is_optimized_code() && is_turbofanned()) ||
          is_wasm_code() || position == RelocInfo::kNoPosition);
@@ -14151,20 +13611,18 @@
 // Same as Code::SourcePosition above except it only looks for statement
 // positions.
 int Code::SourceStatementPosition(int code_offset) {
-  // First find the position as close as possible using all position
-  // information.
+  // First find the closest position.
   int position = SourcePosition(code_offset);
   // Now find the closest statement position before the position.
   int statement_position = 0;
-  RelocIterator it(this, RelocInfo::kPositionMask);
-  while (!it.done()) {
+  for (RelocIterator it(this, RelocInfo::kPositionMask); !it.done();
+       it.next()) {
     if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
       int p = static_cast<int>(it.rinfo()->data());
       if (statement_position < p && p <= position) {
         statement_position = p;
       }
     }
-    it.next();
   }
   return statement_position;
 }
@@ -14230,126 +13688,14 @@
 }
 
 
-void Code::FindAllMaps(MapHandleList* maps) {
-  DCHECK(is_inline_cache_stub());
-  DisallowHeapAllocation no_allocation;
-  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
-  for (RelocIterator it(this, mask); !it.done(); it.next()) {
-    RelocInfo* info = it.rinfo();
-    Object* object = info->target_object();
-    if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
-    if (object->IsMap()) maps->Add(handle(Map::cast(object)));
-  }
-}
-
-
-Code* Code::FindFirstHandler() {
-  DCHECK(is_inline_cache_stub());
-  DisallowHeapAllocation no_allocation;
-  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
-             RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
-  bool skip_next_handler = false;
-  for (RelocIterator it(this, mask); !it.done(); it.next()) {
-    RelocInfo* info = it.rinfo();
-    if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
-      Object* obj = info->target_object();
-      skip_next_handler |= obj->IsWeakCell() && WeakCell::cast(obj)->cleared();
-    } else {
-      Code* code = Code::GetCodeFromTargetAddress(info->target_address());
-      if (code->kind() == Code::HANDLER) {
-        if (!skip_next_handler) return code;
-        skip_next_handler = false;
-      }
-    }
-  }
-  return NULL;
-}
-
-
-bool Code::FindHandlers(CodeHandleList* code_list, int length) {
-  DCHECK(is_inline_cache_stub());
-  DisallowHeapAllocation no_allocation;
-  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
-             RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
-  bool skip_next_handler = false;
-  int i = 0;
-  for (RelocIterator it(this, mask); !it.done(); it.next()) {
-    if (i == length) return true;
-    RelocInfo* info = it.rinfo();
-    if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
-      Object* obj = info->target_object();
-      skip_next_handler |= obj->IsWeakCell() && WeakCell::cast(obj)->cleared();
-    } else {
-      Code* code = Code::GetCodeFromTargetAddress(info->target_address());
-      // IC stubs with handlers never contain non-handler code objects before
-      // handler targets.
-      if (code->kind() != Code::HANDLER) break;
-      if (!skip_next_handler) {
-        code_list->Add(Handle<Code>(code));
-        i++;
-      }
-      skip_next_handler = false;
-    }
-  }
-  return i == length;
-}
-
-
-MaybeHandle<Code> Code::FindHandlerForMap(Map* map) {
-  DCHECK(is_inline_cache_stub());
-  int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
-             RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
-  bool return_next = false;
-  for (RelocIterator it(this, mask); !it.done(); it.next()) {
-    RelocInfo* info = it.rinfo();
-    if (info->rmode() == RelocInfo::EMBEDDED_OBJECT) {
-      Object* object = info->target_object();
-      if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
-      if (object == map) return_next = true;
-    } else if (return_next) {
-      Code* code = Code::GetCodeFromTargetAddress(info->target_address());
-      DCHECK(code->kind() == Code::HANDLER);
-      return handle(code);
-    }
-  }
-  return MaybeHandle<Code>();
-}
-
-
-Name* Code::FindFirstName() {
-  DCHECK(is_inline_cache_stub());
-  DisallowHeapAllocation no_allocation;
-  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
-  for (RelocIterator it(this, mask); !it.done(); it.next()) {
-    RelocInfo* info = it.rinfo();
-    Object* object = info->target_object();
-    if (object->IsName()) return Name::cast(object);
-  }
-  return NULL;
-}
-
-
 void Code::ClearInlineCaches() {
-  ClearInlineCaches(NULL);
-}
-
-
-void Code::ClearInlineCaches(Code::Kind kind) {
-  ClearInlineCaches(&kind);
-}
-
-
-void Code::ClearInlineCaches(Code::Kind* kind) {
   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
   for (RelocIterator it(this, mask); !it.done(); it.next()) {
     RelocInfo* info = it.rinfo();
     Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
     if (target->is_inline_cache_stub()) {
-      if (kind == NULL || *kind == target->kind()) {
-        IC::Clear(this->GetIsolate(), info->pc(),
-                  info->host()->constant_pool());
-      }
+      IC::Clear(this->GetIsolate(), info->pc(), info->host()->constant_pool());
     }
   }
 }
@@ -14364,16 +13710,14 @@
                            : GetCode()->SourceStatementPosition(offset);
 }
 
-void SharedFunctionInfo::ClearTypeFeedbackInfo() {
-  feedback_vector()->ClearSlots(this);
+void JSFunction::ClearTypeFeedbackInfo() {
+  feedback_vector()->ClearSlots(shared());
 }
 
-
-void SharedFunctionInfo::ClearTypeFeedbackInfoAtGCTime() {
-  feedback_vector()->ClearSlotsAtGCTime(this);
+void JSFunction::ClearTypeFeedbackInfoAtGCTime() {
+  feedback_vector()->ClearSlotsAtGCTime(shared());
 }
 
-
 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) {
   DisallowHeapAllocation no_gc;
   DCHECK(kind() == FUNCTION);
@@ -14609,6 +13953,14 @@
   return NULL;
 }
 
+// Identify kind of code.
+const char* AbstractCode::Kind2String(Kind kind) {
+  if (kind < AbstractCode::INTERPRETED_FUNCTION)
+    return Code::Kind2String((Code::Kind)kind);
+  if (kind == AbstractCode::INTERPRETED_FUNCTION) return "INTERPRETED_FUNCTION";
+  UNREACHABLE();
+  return NULL;
+}
 
 Handle<WeakCell> Code::WeakCellFor(Handle<Code> code) {
   DCHECK(code->kind() == OPTIMIZED_FUNCTION);
@@ -14632,7 +13984,6 @@
   return NULL;
 }
 
-
 #ifdef ENABLE_DISASSEMBLER
 
 void DeoptimizationInputData::DeoptimizationInputDataPrint(
@@ -14766,9 +14117,20 @@
           break;
         }
 
+        case Translation::FLOAT_REGISTER: {
+          int reg_code = iterator.Next();
+          os << "{input="
+             << RegisterConfiguration::Crankshaft()->GetFloatRegisterName(
+                    reg_code)
+             << "}";
+          break;
+        }
+
         case Translation::DOUBLE_REGISTER: {
           int reg_code = iterator.Next();
-          os << "{input=" << DoubleRegister::from_code(reg_code).ToString()
+          os << "{input="
+             << RegisterConfiguration::Crankshaft()->GetDoubleRegisterName(
+                    reg_code)
              << "}";
           break;
         }
@@ -14797,6 +14159,7 @@
           break;
         }
 
+        case Translation::FLOAT_STACK_SLOT:
         case Translation::DOUBLE_STACK_SLOT: {
           int input_slot_index = iterator.Next();
           os << "{input=" << input_slot_index << "}";
@@ -14841,8 +14204,9 @@
     int pc_and_state = this->PcAndState(i)->value();
     os << std::setw(6) << this->AstId(i).ToInt() << "  " << std::setw(8)
        << FullCodeGenerator::PcField::decode(pc_and_state) << "  "
-       << FullCodeGenerator::State2String(
-              FullCodeGenerator::StateField::decode(pc_and_state)) << "\n";
+       << Deoptimizer::BailoutStateToString(
+              FullCodeGenerator::BailoutStateField::decode(pc_and_state))
+       << "\n";
   }
 }
 
@@ -14881,28 +14245,17 @@
     case UNINITIALIZED: return "UNINITIALIZED";
     case PREMONOMORPHIC: return "PREMONOMORPHIC";
     case MONOMORPHIC: return "MONOMORPHIC";
-    case PROTOTYPE_FAILURE:
-      return "PROTOTYPE_FAILURE";
+    case RECOMPUTE_HANDLER:
+      return "RECOMPUTE_HANDLER";
     case POLYMORPHIC: return "POLYMORPHIC";
     case MEGAMORPHIC: return "MEGAMORPHIC";
     case GENERIC: return "GENERIC";
-    case DEBUG_STUB: return "DEBUG_STUB";
   }
   UNREACHABLE();
   return NULL;
 }
 
 
-const char* Code::StubType2String(StubType type) {
-  switch (type) {
-    case NORMAL: return "NORMAL";
-    case FAST: return "FAST";
-  }
-  UNREACHABLE();  // keep the compiler happy
-  return NULL;
-}
-
-
 void Code::PrintExtraICState(std::ostream& os,  // NOLINT
                              Kind kind, ExtraICState extra) {
   os << "extra_ic_state = ";
@@ -14922,11 +14275,11 @@
     os << "major_key = " << (n == NULL ? "null" : n) << "\n";
   }
   if (is_inline_cache_stub()) {
-    os << "ic_state = " << ICState2String(ic_state()) << "\n";
-    PrintExtraICState(os, kind(), extra_ic_state());
-    if (ic_state() == MONOMORPHIC) {
-      os << "type = " << StubType2String(type()) << "\n";
+    if (!IC::ICUseVector(kind())) {
+      InlineCacheState ic_state = IC::StateFromCode(this);
+      os << "ic_state = " << ICState2String(ic_state) << "\n";
     }
+    PrintExtraICState(os, kind(), extra_ic_state());
     if (is_compare_ic_stub()) {
       DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC);
       CompareICStub stub(stub_key(), GetIsolate());
@@ -15045,7 +14398,7 @@
       os << "\n";
     }
 #ifdef OBJECT_PRINT
-    if (!type_feedback_info()->IsUndefined()) {
+    if (!type_feedback_info()->IsUndefined(GetIsolate())) {
       TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(os);
       os << "\n";
     }
@@ -15082,20 +14435,18 @@
 }
 
 int BytecodeArray::SourceStatementPosition(int offset) {
-  // First find the position as close as possible using all position
-  // information.
+  // First find the closest position.
   int position = SourcePosition(offset);
   // Now find the closest statement position before the position.
   int statement_position = 0;
-  interpreter::SourcePositionTableIterator iterator(source_position_table());
-  while (!iterator.done()) {
-    if (iterator.is_statement()) {
-      int p = iterator.source_position();
+  for (interpreter::SourcePositionTableIterator it(source_position_table());
+       !it.done(); it.Advance()) {
+    if (it.is_statement()) {
+      int p = it.source_position();
       if (statement_position < p && p <= position) {
         statement_position = p;
       }
     }
-    iterator.Advance();
   }
   return statement_position;
 }
@@ -15103,7 +14454,6 @@
 void BytecodeArray::Disassemble(std::ostream& os) {
   os << "Parameter count " << parameter_count() << "\n";
   os << "Frame size " << frame_size() << "\n";
-  Vector<char> buf = Vector<char>::New(50);
 
   const uint8_t* base_address = GetFirstBytecodeAddress();
   interpreter::SourcePositionTableIterator source_positions(
@@ -15120,12 +14470,13 @@
       os << "         ";
     }
     const uint8_t* current_address = base_address + iterator.current_offset();
-    SNPrintF(buf, "%p", current_address);
-    os << buf.start() << " : ";
+    os << reinterpret_cast<const void*>(current_address) << " @ "
+       << std::setw(4) << iterator.current_offset() << " : ";
     interpreter::Bytecodes::Decode(os, current_address, parameter_count());
     if (interpreter::Bytecodes::IsJump(iterator.current_bytecode())) {
-      SNPrintF(buf, " (%p)", base_address + iterator.GetJumpTargetOffset());
-      os << buf.start();
+      const void* jump_target = base_address + iterator.GetJumpTargetOffset();
+      os << " (" << jump_target << " @ " << iterator.GetJumpTargetOffset()
+         << ")";
     }
     os << std::endl;
     iterator.Advance();
@@ -15158,29 +14509,6 @@
       array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
 }
 
-
-// Returns false if the passed-in index is marked non-configurable, which will
-// cause the truncation operation to halt, and thus no further old values need
-// be collected.
-static bool GetOldValue(Isolate* isolate,
-                        Handle<JSObject> object,
-                        uint32_t index,
-                        List<Handle<Object> >* old_values,
-                        List<uint32_t>* indices) {
-  LookupIterator it(isolate, object, index, object, LookupIterator::HIDDEN);
-  CHECK(JSReceiver::GetPropertyAttributes(&it).IsJust());
-  DCHECK(it.IsFound());
-  if (!it.IsConfigurable()) return false;
-  Handle<Object> value =
-      it.state() == LookupIterator::ACCESSOR
-          ? Handle<Object>::cast(isolate->factory()->the_hole_value())
-          : JSReceiver::GetDataProperty(&it);
-  old_values->Add(value);
-  indices->Add(index);
-  return true;
-}
-
-
 void JSArray::SetLength(Handle<JSArray> array, uint32_t new_length) {
   // We should never end in here with a pixel or external array.
   DCHECK(array->AllowsSetLength());
@@ -15191,91 +14519,6 @@
 }
 
 
-MaybeHandle<Object> JSArray::ObservableSetLength(Handle<JSArray> array,
-                                                 uint32_t new_length) {
-  if (!array->map()->is_observed()) {
-    SetLength(array, new_length);
-    return array;
-  }
-
-  Isolate* isolate = array->GetIsolate();
-  List<uint32_t> indices;
-  List<Handle<Object> > old_values;
-  Handle<Object> old_length_handle(array->length(), isolate);
-  uint32_t old_length = 0;
-  CHECK(old_length_handle->ToArrayLength(&old_length));
-
-  int num_elements = array->NumberOfOwnElements(ALL_PROPERTIES);
-  if (num_elements > 0) {
-    if (old_length == static_cast<uint32_t>(num_elements)) {
-      // Simple case for arrays without holes.
-      for (uint32_t i = old_length - 1; i + 1 > new_length; --i) {
-        if (!GetOldValue(isolate, array, i, &old_values, &indices)) break;
-      }
-    } else {
-      // For sparse arrays, only iterate over existing elements.
-      // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over
-      // the to-be-removed indices twice.
-      Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements);
-      array->GetOwnElementKeys(*keys, ALL_PROPERTIES);
-      while (num_elements-- > 0) {
-        uint32_t index = NumberToUint32(keys->get(num_elements));
-        if (index < new_length) break;
-        if (!GetOldValue(isolate, array, index, &old_values, &indices)) break;
-      }
-    }
-  }
-
-  SetLength(array, new_length);
-
-  CHECK(array->length()->ToArrayLength(&new_length));
-  if (old_length == new_length) return array;
-
-  RETURN_ON_EXCEPTION(isolate, BeginPerformSplice(array), Object);
-
-  for (int i = 0; i < indices.length(); ++i) {
-    // For deletions where the property was an accessor, old_values[i]
-    // will be the hole, which instructs EnqueueChangeRecord to elide
-    // the "oldValue" property.
-    RETURN_ON_EXCEPTION(
-        isolate,
-        JSObject::EnqueueChangeRecord(
-            array, "delete", isolate->factory()->Uint32ToString(indices[i]),
-            old_values[i]),
-        Object);
-  }
-
-  RETURN_ON_EXCEPTION(isolate,
-                      JSObject::EnqueueChangeRecord(
-                          array, "update", isolate->factory()->length_string(),
-                          old_length_handle),
-                      Object);
-
-  RETURN_ON_EXCEPTION(isolate, EndPerformSplice(array), Object);
-
-  uint32_t index = Min(old_length, new_length);
-  uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
-  uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
-  Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
-  if (delete_count > 0) {
-    for (int i = indices.length() - 1; i >= 0; i--) {
-      // Skip deletions where the property was an accessor, leaving holes
-      // in the array of old values.
-      if (old_values[i]->IsTheHole()) continue;
-      JSObject::AddDataElement(deleted, indices[i] - index, old_values[i], NONE)
-          .Assert();
-    }
-
-    JSArray::SetLength(deleted, delete_count);
-  }
-
-  RETURN_ON_EXCEPTION(
-      isolate, EnqueueSpliceRecord(array, index, deleted, add_count), Object);
-
-  return array;
-}
-
-
 // static
 void Map::AddDependentCode(Handle<Map> map,
                            DependentCode::DependencyGroup group,
@@ -15603,10 +14846,10 @@
                                   bool from_javascript,
                                   ShouldThrow should_throw) {
   Isolate* isolate = proxy->GetIsolate();
-  STACK_CHECK(Nothing<bool>());
+  STACK_CHECK(isolate, Nothing<bool>());
   Handle<Name> trap_name = isolate->factory()->setPrototypeOf_string();
   // 1. Assert: Either Type(V) is Object or Type(V) is Null.
-  DCHECK(value->IsJSReceiver() || value->IsNull());
+  DCHECK(value->IsJSReceiver() || value->IsNull(isolate));
   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   Handle<Object> handler(proxy->handler(), isolate);
   // 3. If handler is null, throw a TypeError exception.
@@ -15625,7 +14868,7 @@
       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
       Nothing<bool>());
   // 7. If trap is undefined, then return target.[[SetPrototypeOf]]().
-  if (trap->IsUndefined()) {
+  if (trap->IsUndefined(isolate)) {
     return JSReceiver::SetPrototype(target, value, from_javascript,
                                     should_throw);
   }
@@ -15674,46 +14917,10 @@
                                    ShouldThrow should_throw) {
   Isolate* isolate = object->GetIsolate();
 
-  const bool observed = from_javascript && object->map()->is_observed();
-  Handle<Object> old_value;
-  if (observed) {
-    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, old_value,
-                                     JSReceiver::GetPrototype(isolate, object),
-                                     Nothing<bool>());
-  }
-
-  Maybe<bool> result =
-      SetPrototypeUnobserved(object, value, from_javascript, should_throw);
-  MAYBE_RETURN(result, Nothing<bool>());
-
-  if (result.FromJust() && observed) {
-    Handle<Object> new_value;
-    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, new_value,
-                                     JSReceiver::GetPrototype(isolate, object),
-                                     Nothing<bool>());
-    if (!new_value->SameValue(*old_value)) {
-      RETURN_ON_EXCEPTION_VALUE(
-          isolate, JSObject::EnqueueChangeRecord(
-                       object, "setPrototype",
-                       isolate->factory()->proto_string(), old_value),
-          Nothing<bool>());
-    }
-  }
-
-  return result;
-}
-
-
-Maybe<bool> JSObject::SetPrototypeUnobserved(Handle<JSObject> object,
-                                             Handle<Object> value,
-                                             bool from_javascript,
-                                             ShouldThrow should_throw) {
 #ifdef DEBUG
   int size = object->Size();
 #endif
 
-  Isolate* isolate = object->GetIsolate();
-
   if (from_javascript) {
     if (object->IsAccessCheckNeeded() &&
         !isolate->MayAccess(handle(isolate->context()), object)) {
@@ -15729,7 +14936,7 @@
   Heap* heap = isolate->heap();
   // Silently ignore the change if value is not a JSObject or null.
   // SpiderMonkey behaves this way.
-  if (!value->IsJSReceiver() && !value->IsNull()) return Just(true);
+  if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true);
 
   bool dictionary_elements_in_chain =
       object->map()->DictionaryElementsInPrototypeChainOnly();
@@ -15739,8 +14946,7 @@
   if (from_javascript) {
     // Find the first object in the chain whose prototype object is not
     // hidden.
-    PrototypeIterator iter(isolate, real_receiver,
-                           PrototypeIterator::START_AT_PROTOTYPE,
+    PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype,
                            PrototypeIterator::END_AT_NON_HIDDEN);
     while (!iter.IsAtEnd()) {
       // Casting to JSObject is fine because hidden prototypes are never
@@ -15773,7 +14979,7 @@
   // new prototype chain.
   if (value->IsJSReceiver()) {
     for (PrototypeIterator iter(isolate, JSReceiver::cast(*value),
-                                PrototypeIterator::START_AT_RECEIVER);
+                                kStartAtReceiver);
          !iter.IsAtEnd(); iter.Advance()) {
       if (iter.GetCurrent<JSReceiver>() == *object) {
         // Cycle detected.
@@ -15949,12 +15155,8 @@
   uint32_t old_length = 0;
   uint32_t new_capacity = 0;
 
-  Handle<Object> old_length_handle;
   if (object->IsJSArray()) {
     CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length));
-    if (object->map()->is_observed()) {
-      old_length_handle = handle(JSArray::cast(*object)->length(), isolate);
-    }
   }
 
   ElementsKind kind = object->GetElementsKind();
@@ -15998,38 +15200,6 @@
     JSArray::cast(*object)->set_length(*new_length_handle);
   }
 
-  if (!old_length_handle.is_null() && new_length != old_length) {
-    // |old_length_handle| is kept null above unless the object is observed.
-    DCHECK(object->map()->is_observed());
-    Handle<JSArray> array = Handle<JSArray>::cast(object);
-    Handle<String> name = isolate->factory()->Uint32ToString(index);
-
-    RETURN_ON_EXCEPTION_VALUE(isolate, BeginPerformSplice(array),
-                              Nothing<bool>());
-    RETURN_ON_EXCEPTION_VALUE(
-        isolate, EnqueueChangeRecord(array, "add", name,
-                                     isolate->factory()->the_hole_value()),
-        Nothing<bool>());
-    RETURN_ON_EXCEPTION_VALUE(
-        isolate, EnqueueChangeRecord(array, "update",
-                                     isolate->factory()->length_string(),
-                                     old_length_handle),
-        Nothing<bool>());
-    RETURN_ON_EXCEPTION_VALUE(isolate, EndPerformSplice(array),
-                              Nothing<bool>());
-    Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
-    RETURN_ON_EXCEPTION_VALUE(isolate,
-                              EnqueueSpliceRecord(array, old_length, deleted,
-                                                  new_length - old_length),
-                              Nothing<bool>());
-  } else if (object->map()->is_observed()) {
-    Handle<String> name = isolate->factory()->Uint32ToString(index);
-    RETURN_ON_EXCEPTION_VALUE(
-        isolate, EnqueueChangeRecord(object, "add", name,
-                                     isolate->factory()->the_hole_value()),
-        Nothing<bool>());
-  }
-
   return Just(true);
 }
 
@@ -16297,10 +15467,11 @@
 #ifdef OBJECT_PRINT
 template <typename Derived, typename Shape, typename Key>
 void Dictionary<Derived, Shape, Key>::Print(std::ostream& os) {  // NOLINT
+  Isolate* isolate = this->GetIsolate();
   int capacity = this->Capacity();
   for (int i = 0; i < capacity; i++) {
     Object* k = this->KeyAt(i);
-    if (this->IsKey(k)) {
+    if (this->IsKey(isolate, k)) {
       os << "\n   ";
       if (k->IsString()) {
         String::cast(k)->StringPrint(os);
@@ -16311,18 +15482,24 @@
     }
   }
 }
+template <typename Derived, typename Shape, typename Key>
+void Dictionary<Derived, Shape, Key>::Print() {
+  OFStream os(stdout);
+  Print(os);
+}
 #endif
 
 
 template<typename Derived, typename Shape, typename Key>
 void Dictionary<Derived, Shape, Key>::CopyValuesTo(FixedArray* elements) {
+  Isolate* isolate = this->GetIsolate();
   int pos = 0;
   int capacity = this->Capacity();
   DisallowHeapAllocation no_gc;
   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
   for (int i = 0; i < capacity; i++) {
     Object* k = this->KeyAt(i);
-    if (this->IsKey(k)) {
+    if (this->IsKey(isolate, k)) {
       elements->set(pos++, this->ValueAt(i), mode);
     }
   }
@@ -16332,55 +15509,10 @@
 
 MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(LookupIterator* it,
                                                          bool* done) {
-  *done = false;
-  Isolate* isolate = it->isolate();
-  // Make sure that the top context does not change when doing callbacks or
-  // interceptor calls.
-  AssertNoContextChange ncc(isolate);
-
   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
-  Handle<InterceptorInfo> interceptor = it->GetInterceptor();
-  if (interceptor->getter()->IsUndefined()) {
-    return isolate->factory()->undefined_value();
-  }
-
-  Handle<JSObject> holder = it->GetHolder<JSObject>();
-  Handle<Object> result;
-  Handle<Object> receiver = it->GetReceiver();
-  if (!receiver->IsJSReceiver()) {
-    ASSIGN_RETURN_ON_EXCEPTION(
-        isolate, receiver, Object::ConvertReceiver(isolate, receiver), Object);
-  }
-  PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
-                                 *holder, Object::DONT_THROW);
-
-  if (it->IsElement()) {
-    uint32_t index = it->index();
-    v8::IndexedPropertyGetterCallback getter =
-        v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
-    result = args.Call(getter, index);
-  } else {
-    Handle<Name> name = it->name();
-    DCHECK(!name->IsPrivate());
-
-    if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
-      return isolate->factory()->undefined_value();
-    }
-
-    v8::GenericNamedPropertyGetterCallback getter =
-        v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
-            interceptor->getter());
-    result = args.Call(getter, name);
-  }
-
-  RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
-  if (result.is_null()) return isolate->factory()->undefined_value();
-  *done = true;
-  // Rebox handle before return
-  return handle(*result, isolate);
+  return GetPropertyWithInterceptorInternal(it, it->GetInterceptor(), done);
 }
 
-
 Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
                                            Handle<Name> name) {
   LookupIterator it = LookupIterator::PropertyOrElement(
@@ -16520,196 +15652,46 @@
   }
 }
 
-void JSObject::CollectOwnPropertyNames(KeyAccumulator* keys,
-                                       PropertyFilter filter) {
-  if (HasFastProperties()) {
-    int real_size = map()->NumberOfOwnDescriptors();
-    Handle<DescriptorArray> descs(map()->instance_descriptors());
-    for (int i = 0; i < real_size; i++) {
-      PropertyDetails details = descs->GetDetails(i);
-      if ((details.attributes() & filter) != 0) continue;
-      if (filter & ONLY_ALL_CAN_READ) {
-        if (details.kind() != kAccessor) continue;
-        Object* accessors = descs->GetValue(i);
-        if (!accessors->IsAccessorInfo()) continue;
-        if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
-      }
-      Name* key = descs->GetKey(i);
-      if (key->FilterKey(filter)) continue;
-      keys->AddKey(key, DO_NOT_CONVERT);
-    }
-  } else if (IsJSGlobalObject()) {
-    GlobalDictionary::CollectKeysTo(handle(global_dictionary()), keys, filter);
-  } else {
-    NameDictionary::CollectKeysTo(handle(property_dictionary()), keys, filter);
-  }
-}
-
-
-int JSObject::NumberOfOwnElements(PropertyFilter filter) {
-  // Fast case for objects with no elements.
-  if (!IsJSValue() && HasFastElements()) {
-    uint32_t length =
-        IsJSArray()
-            ? static_cast<uint32_t>(
-                  Smi::cast(JSArray::cast(this)->length())->value())
-            : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length());
-    if (length == 0) return 0;
-  }
-  // Compute the number of enumerable elements.
-  return GetOwnElementKeys(NULL, filter);
-}
-
-void JSObject::CollectOwnElementKeys(Handle<JSObject> object,
-                                     KeyAccumulator* keys,
-                                     PropertyFilter filter) {
-  if (filter & SKIP_STRINGS) return;
-  ElementsAccessor* accessor = object->GetElementsAccessor();
-  accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0);
-}
-
-
-int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) {
-  int counter = 0;
-
-  // If this is a String wrapper, add the string indices first,
-  // as they're guaranteed to precede the elements in numerical order
-  // and ascending order is required by ECMA-262, 6th, 9.1.12.
-  if (IsJSValue()) {
-    Object* val = JSValue::cast(this)->value();
-    if (val->IsString()) {
-      String* str = String::cast(val);
-      if (storage) {
-        for (int i = 0; i < str->length(); i++) {
-          storage->set(counter + i, Smi::FromInt(i));
-        }
-      }
-      counter += str->length();
+bool JSObject::WasConstructedFromApiFunction() {
+  auto instance_type = map()->instance_type();
+  bool is_api_object = instance_type == JS_API_OBJECT_TYPE ||
+                       instance_type == JS_SPECIAL_API_OBJECT_TYPE;
+#ifdef ENABLE_SLOW_DCHECKS
+  if (FLAG_enable_slow_asserts) {
+    Object* maybe_constructor = map()->GetConstructor();
+    if (!maybe_constructor->IsJSFunction()) return false;
+    JSFunction* constructor = JSFunction::cast(maybe_constructor);
+    if (constructor->shared()->IsApiFunction()) {
+      DCHECK(is_api_object);
+    } else {
+      DCHECK(!is_api_object);
     }
   }
-
-  switch (GetElementsKind()) {
-    case FAST_SMI_ELEMENTS:
-    case FAST_ELEMENTS:
-    case FAST_HOLEY_SMI_ELEMENTS:
-    case FAST_HOLEY_ELEMENTS:
-    case FAST_STRING_WRAPPER_ELEMENTS: {
-      int length = IsJSArray() ?
-          Smi::cast(JSArray::cast(this)->length())->value() :
-          FixedArray::cast(elements())->length();
-      for (int i = 0; i < length; i++) {
-        if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
-          if (storage != NULL) {
-            storage->set(counter, Smi::FromInt(i));
-          }
-          counter++;
-        }
-      }
-      DCHECK(!storage || storage->length() >= counter);
-      break;
-    }
-    case FAST_DOUBLE_ELEMENTS:
-    case FAST_HOLEY_DOUBLE_ELEMENTS: {
-      int length = IsJSArray() ?
-          Smi::cast(JSArray::cast(this)->length())->value() :
-          FixedArrayBase::cast(elements())->length();
-      for (int i = 0; i < length; i++) {
-        if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
-          if (storage != NULL) {
-            storage->set(counter, Smi::FromInt(i));
-          }
-          counter++;
-        }
-      }
-      DCHECK(!storage || storage->length() >= counter);
-      break;
-    }
-
-#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
-    case TYPE##_ELEMENTS:                                                    \
-
-    TYPED_ARRAYS(TYPED_ARRAY_CASE)
-#undef TYPED_ARRAY_CASE
-    {
-      int length = FixedArrayBase::cast(elements())->length();
-      while (counter < length) {
-        if (storage != NULL) {
-          storage->set(counter, Smi::FromInt(counter));
-        }
-        counter++;
-      }
-      DCHECK(!storage || storage->length() >= counter);
-      break;
-    }
-
-    case DICTIONARY_ELEMENTS:
-    case SLOW_STRING_WRAPPER_ELEMENTS: {
-      if (storage != NULL) {
-        element_dictionary()->CopyKeysTo(storage, counter, filter,
-                                         SeededNumberDictionary::SORTED);
-      }
-      counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
-      break;
-    }
-    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
-    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
-      FixedArray* parameter_map = FixedArray::cast(elements());
-      int mapped_length = parameter_map->length() - 2;
-      FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
-      if (arguments->IsDictionary()) {
-        // Copy the keys from arguments first, because Dictionary::CopyKeysTo
-        // will insert in storage starting at index 0.
-        SeededNumberDictionary* dictionary =
-            SeededNumberDictionary::cast(arguments);
-        if (storage != NULL) {
-          dictionary->CopyKeysTo(storage, counter, filter,
-                                 SeededNumberDictionary::UNSORTED);
-        }
-        counter += dictionary->NumberOfElementsFilterAttributes(filter);
-        for (int i = 0; i < mapped_length; ++i) {
-          if (!parameter_map->get(i + 2)->IsTheHole()) {
-            if (storage != NULL) storage->set(counter, Smi::FromInt(i));
-            ++counter;
-          }
-        }
-        if (storage != NULL) storage->SortPairs(storage, counter);
-
-      } else {
-        int backing_length = arguments->length();
-        int i = 0;
-        for (; i < mapped_length; ++i) {
-          if (!parameter_map->get(i + 2)->IsTheHole()) {
-            if (storage != NULL) storage->set(counter, Smi::FromInt(i));
-            ++counter;
-          } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
-            if (storage != NULL) storage->set(counter, Smi::FromInt(i));
-            ++counter;
-          }
-        }
-        for (; i < backing_length; ++i) {
-          if (storage != NULL) storage->set(counter, Smi::FromInt(i));
-          ++counter;
-        }
-      }
-      break;
-    }
-    case NO_ELEMENTS:
-      break;
-  }
-
-  DCHECK(!storage || storage->length() == counter);
-  return counter;
+#endif
+  return is_api_object;
 }
 
-
 MaybeHandle<String> Object::ObjectProtoToString(Isolate* isolate,
                                                 Handle<Object> object) {
-  if (object->IsUndefined()) return isolate->factory()->undefined_to_string();
-  if (object->IsNull()) return isolate->factory()->null_to_string();
+  if (*object == isolate->heap()->undefined_value()) {
+    return isolate->factory()->undefined_to_string();
+  }
+  if (*object == isolate->heap()->null_value()) {
+    return isolate->factory()->null_to_string();
+  }
 
   Handle<JSReceiver> receiver =
       Object::ToObject(isolate, object).ToHandleChecked();
 
+  // For proxies, we must check IsArray() before get(toStringTag) to comply
+  // with the specification
+  Maybe<bool> is_array = Nothing<bool>();
+  InstanceType instance_type = receiver->map()->instance_type();
+  if (instance_type == JS_PROXY_TYPE) {
+    is_array = Object::IsArray(receiver);
+    MAYBE_RETURN(is_array, MaybeHandle<String>());
+  }
+
   Handle<String> tag;
   Handle<Object> to_string_tag;
   ASSIGN_RETURN_ON_EXCEPTION(
@@ -16719,11 +15701,55 @@
       String);
   if (to_string_tag->IsString()) {
     tag = Handle<String>::cast(to_string_tag);
-  }
-
-  if (tag.is_null()) {
-    ASSIGN_RETURN_ON_EXCEPTION(isolate, tag,
-                               JSReceiver::BuiltinStringTag(receiver), String);
+  } else {
+    switch (instance_type) {
+      case JS_API_OBJECT_TYPE:
+      case JS_SPECIAL_API_OBJECT_TYPE:
+        tag = handle(receiver->class_name(), isolate);
+        break;
+      case JS_ARGUMENTS_TYPE:
+        return isolate->factory()->arguments_to_string();
+      case JS_ARRAY_TYPE:
+        return isolate->factory()->array_to_string();
+      case JS_BOUND_FUNCTION_TYPE:
+      case JS_FUNCTION_TYPE:
+        return isolate->factory()->function_to_string();
+      case JS_ERROR_TYPE:
+        return isolate->factory()->error_to_string();
+      case JS_DATE_TYPE:
+        return isolate->factory()->date_to_string();
+      case JS_REGEXP_TYPE:
+        return isolate->factory()->regexp_to_string();
+      case JS_PROXY_TYPE: {
+        if (is_array.FromJust()) {
+          return isolate->factory()->array_to_string();
+        }
+        if (receiver->IsCallable()) {
+          return isolate->factory()->function_to_string();
+        }
+        return isolate->factory()->object_to_string();
+      }
+      case JS_VALUE_TYPE: {
+        Object* value = JSValue::cast(*receiver)->value();
+        if (value->IsString()) {
+          return isolate->factory()->string_to_string();
+        }
+        if (value->IsNumber()) {
+          return isolate->factory()->number_to_string();
+        }
+        if (value->IsBoolean()) {
+          return isolate->factory()->boolean_to_string();
+        }
+        if (value->IsSymbol()) {
+          return isolate->factory()->object_to_string();
+        }
+        UNREACHABLE();
+        tag = handle(receiver->class_name(), isolate);
+        break;
+      }
+      default:
+        return isolate->factory()->object_to_string();
+    }
   }
 
   IncrementalStringBuilder builder(isolate);
@@ -16733,7 +15759,6 @@
   return builder.Finish();
 }
 
-
 const char* Symbol::PrivateSymbolToName() const {
   Heap* heap = GetIsolate()->heap();
 #define SYMBOL_CHECK_AND_PRINT(name) \
@@ -16745,12 +15770,12 @@
 
 
 void Symbol::SymbolShortPrint(std::ostream& os) {
-  os << "<Symbol: " << Hash();
-  if (!name()->IsUndefined()) {
+  os << "<Symbol:";
+  if (!name()->IsUndefined(GetIsolate())) {
     os << " ";
     HeapStringAllocator allocator;
     StringStream accumulator(&allocator);
-    String::cast(name())->StringShortPrint(&accumulator);
+    String::cast(name())->StringShortPrint(&accumulator, false);
     os << accumulator.ToCString().get();
   } else {
     os << " (" << PrivateSymbolToName() << ")";
@@ -16868,7 +15893,6 @@
         flag = JSRegExp::kMultiline;
         break;
       case 'u':
-        if (!FLAG_harmony_unicode_regexps) return JSRegExp::Flags(0);
         flag = JSRegExp::kUnicode;
         break;
       case 'y':
@@ -16900,22 +15924,6 @@
 
 
 // static
-MaybeHandle<JSRegExp> JSRegExp::New(Handle<String> pattern,
-                                    Handle<String> flags_string) {
-  Isolate* isolate = pattern->GetIsolate();
-  bool success = false;
-  Flags flags = RegExpFlagsFromString(flags_string, &success);
-  if (!success) {
-    THROW_NEW_ERROR(
-        isolate,
-        NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string),
-        JSRegExp);
-  }
-  return New(pattern, flags);
-}
-
-
-// static
 Handle<JSRegExp> JSRegExp::Copy(Handle<JSRegExp> regexp) {
   Isolate* const isolate = regexp->GetIsolate();
   return Handle<JSRegExp>::cast(isolate->factory()->CopyJSObject(regexp));
@@ -17006,6 +16014,9 @@
   ASSIGN_RETURN_ON_EXCEPTION(isolate, escaped_source,
                              EscapeRegExpSource(isolate, source), JSRegExp);
 
+  RETURN_ON_EXCEPTION(isolate, RegExpImpl::Compile(regexp, source, flags),
+                      JSRegExp);
+
   regexp->set_source(*escaped_source);
   regexp->set_flags(Smi::FromInt(flags));
 
@@ -17026,9 +16037,6 @@
         .Check();
   }
 
-  RETURN_ON_EXCEPTION(isolate, RegExpImpl::Compile(regexp, source, flags),
-                      JSRegExp);
-
   return regexp;
 }
 
@@ -17199,21 +16207,12 @@
   uint32_t capacity = this->Capacity();
   uint32_t entry = Derived::FirstProbe(key->Hash(), capacity);
   uint32_t count = 1;
-
+  Isolate* isolate = this->GetIsolate();
   while (true) {
-    int index = Derived::EntryToIndex(entry);
-    Object* element = this->get(index);
-    if (element->IsUndefined()) break;  // Empty entry.
+    Object* element = this->KeyAt(entry);
+    if (element->IsUndefined(isolate)) break;  // Empty entry.
     if (*key == element) return entry;
-    if (!element->IsUniqueName() &&
-        !element->IsTheHole() &&
-        Name::cast(element)->Equals(*key)) {
-      // Replace a key that is a non-internalized string by the equivalent
-      // internalized string for faster further lookups.
-      this->set(index, *key);
-      return entry;
-    }
-    DCHECK(element->IsTheHole() || !Name::cast(element)->Equals(*key));
+    DCHECK(element->IsTheHole(isolate) || element->IsUniqueName());
     entry = Derived::NextProbe(entry, count++, capacity);
   }
   return Derived::kNotFound;
@@ -17238,10 +16237,13 @@
 
   // Rehash the elements.
   int capacity = this->Capacity();
+  Heap* heap = new_table->GetHeap();
+  Object* the_hole = heap->the_hole_value();
+  Object* undefined = heap->undefined_value();
   for (int i = 0; i < capacity; i++) {
     uint32_t from_index = EntryToIndex(i);
     Object* k = this->get(from_index);
-    if (IsKey(k)) {
+    if (k != the_hole && k != undefined) {
       uint32_t hash = this->HashForObject(key, k);
       uint32_t insertion_index =
           EntryToIndex(new_table->FindInsertionEntry(hash));
@@ -17295,6 +16297,7 @@
 void HashTable<Derived, Shape, Key>::Rehash(Key key) {
   DisallowHeapAllocation no_gc;
   WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
+  Isolate* isolate = GetIsolate();
   uint32_t capacity = Capacity();
   bool done = false;
   for (int probe = 1; !done; probe++) {
@@ -17302,11 +16305,11 @@
     // are placed correctly. Other elements might need to be moved.
     done = true;
     for (uint32_t current = 0; current < capacity; current++) {
-      Object* current_key = get(EntryToIndex(current));
-      if (IsKey(current_key)) {
+      Object* current_key = KeyAt(current);
+      if (IsKey(isolate, current_key)) {
         uint32_t target = EntryForProbe(key, current_key, probe, current);
         if (current == target) continue;
-        Object* target_key = get(EntryToIndex(target));
+        Object* target_key = KeyAt(target);
         if (!IsKey(target_key) ||
             EntryForProbe(key, target_key, probe, target) != target) {
           // Put the current element into the correct position.
@@ -17322,12 +16325,11 @@
     }
   }
   // Wipe deleted entries.
-  Heap* heap = GetHeap();
-  Object* the_hole = heap->the_hole_value();
-  Object* undefined = heap->undefined_value();
+  Object* the_hole = isolate->heap()->the_hole_value();
+  Object* undefined = isolate->heap()->undefined_value();
   for (uint32_t current = 0; current < capacity; current++) {
-    if (get(EntryToIndex(current)) == the_hole) {
-      set(EntryToIndex(current), undefined);
+    if (KeyAt(current) == the_hole) {
+      set(EntryToIndex(current) + Derived::kEntryKeyIndex, undefined);
     }
   }
   SetNumberOfDeletedElements(0);
@@ -17344,7 +16346,7 @@
   int capacity = table->Capacity();
   int nof = table->NumberOfElements() + n;
 
-  if (table->HasSufficientCapacity(n)) return table;
+  if (table->HasSufficientCapacityToAdd(n)) return table;
 
   const int kMinCapacityForPretenure = 256;
   bool should_pretenure = pretenure == TENURED ||
@@ -17360,16 +16362,16 @@
   return new_table;
 }
 
-
 template <typename Derived, typename Shape, typename Key>
-bool HashTable<Derived, Shape, Key>::HasSufficientCapacity(int n) {
+bool HashTable<Derived, Shape, Key>::HasSufficientCapacityToAdd(
+    int number_of_additional_elements) {
   int capacity = Capacity();
-  int nof = NumberOfElements() + n;
+  int nof = NumberOfElements() + number_of_additional_elements;
   int nod = NumberOfDeletedElements();
   // Return true if:
-  //   50% is still free after adding n elements and
+  //   50% is still free after adding number_of_additional_elements elements and
   //   at most 50% of the free elements are deleted elements.
-  if (nod <= (capacity - nof) >> 1) {
+  if ((nof < capacity) && ((nod <= (capacity - nof) >> 1))) {
     int needed_free = nof >> 1;
     if (nof + needed_free <= capacity) return true;
   }
@@ -17415,9 +16417,10 @@
   uint32_t entry = FirstProbe(hash, capacity);
   uint32_t count = 1;
   // EnsureCapacity will guarantee the hash table is never full.
+  Isolate* isolate = GetIsolate();
   while (true) {
     Object* element = KeyAt(entry);
-    if (element->IsUndefined() || element->IsTheHole()) break;
+    if (!IsKey(isolate, element)) break;
     entry = NextProbe(entry, count++, capacity);
   }
   return entry;
@@ -17564,6 +16567,30 @@
 template int NameDictionaryBase<NameDictionary, NameDictionaryShape>::FindEntry(
     Handle<Name>);
 
+template int Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>::
+    NumberOfElementsFilterAttributes(PropertyFilter filter);
+
+template int Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::
+    NumberOfElementsFilterAttributes(PropertyFilter filter);
+
+template void Dictionary<GlobalDictionary, GlobalDictionaryShape,
+                         Handle<Name>>::CopyEnumKeysTo(FixedArray* storage);
+
+template void Dictionary<NameDictionary, NameDictionaryShape,
+                         Handle<Name>>::CopyEnumKeysTo(FixedArray* storage);
+
+template void
+Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>::
+    CollectKeysTo(Handle<Dictionary<GlobalDictionary, GlobalDictionaryShape,
+                                    Handle<Name>>>
+                      dictionary,
+                  KeyAccumulator* keys, PropertyFilter filter);
+
+template void
+Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::CollectKeysTo(
+    Handle<Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>>
+        dictionary,
+    KeyAccumulator* keys, PropertyFilter filter);
 
 Handle<Object> JSObject::PrepareSlowElementsForSort(
     Handle<JSObject> object, uint32_t limit) {
@@ -17585,7 +16612,7 @@
   DisallowHeapAllocation no_gc;
   for (int i = 0; i < capacity; i++) {
     Object* k = dict->KeyAt(i);
-    if (!dict->IsKey(k)) continue;
+    if (!dict->IsKey(isolate, k)) continue;
 
     DCHECK(k->IsNumber());
     DCHECK(!k->IsSmi() || Smi::cast(k)->value() >= 0);
@@ -17603,7 +16630,7 @@
 
     uint32_t key = NumberToUint32(k);
     if (key < limit) {
-      if (value->IsUndefined()) {
+      if (value->IsUndefined(isolate)) {
         undefs++;
       } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
         // Adding an entry with the key beyond smi-range requires
@@ -17660,8 +16687,7 @@
 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
                                                 uint32_t limit) {
   Isolate* isolate = object->GetIsolate();
-  if (object->HasSloppyArgumentsElements() ||
-      object->map()->is_observed()) {
+  if (object->HasSloppyArgumentsElements()) {
     return handle(Smi::FromInt(-1), isolate);
   }
 
@@ -17754,10 +16780,10 @@
     // number of stores of non-undefined, non-the-hole values.
     for (unsigned int i = 0; i < undefs; i++) {
       Object* current = elements->get(i);
-      if (current->IsTheHole()) {
+      if (current->IsTheHole(isolate)) {
         holes--;
         undefs--;
-      } else if (current->IsUndefined()) {
+      } else if (current->IsUndefined(isolate)) {
         undefs--;
       } else {
         continue;
@@ -17765,10 +16791,10 @@
       // Position i needs to be filled.
       while (undefs > i) {
         current = elements->get(undefs);
-        if (current->IsTheHole()) {
+        if (current->IsTheHole(isolate)) {
           holes--;
           undefs--;
-        } else if (current->IsUndefined()) {
+        } else if (current->IsUndefined(isolate)) {
           undefs--;
         } else {
           elements->set(i, current, write_barrier);
@@ -17836,8 +16862,9 @@
 // TODO(ishell): rename to EnsureEmptyPropertyCell or something.
 Handle<PropertyCell> JSGlobalObject::EnsurePropertyCell(
     Handle<JSGlobalObject> global, Handle<Name> name) {
+  Isolate* isolate = global->GetIsolate();
   DCHECK(!global->HasFastProperties());
-  auto dictionary = handle(global->global_dictionary());
+  auto dictionary = handle(global->global_dictionary(), isolate);
   int entry = dictionary->FindEntry(name);
   Handle<PropertyCell> cell;
   if (entry != GlobalDictionary::kNotFound) {
@@ -17848,10 +16875,9 @@
                PropertyCellType::kUninitialized ||
            cell->property_details().cell_type() ==
                PropertyCellType::kInvalidated);
-    DCHECK(cell->value()->IsTheHole());
+    DCHECK(cell->value()->IsTheHole(isolate));
     return cell;
   }
-  Isolate* isolate = global->GetIsolate();
   cell = isolate->factory()->NewPropertyCell();
   PropertyDetails details(NONE, DATA, 0, PropertyCellType::kUninitialized);
   dictionary = GlobalDictionary::Add(dictionary, name, cell, details);
@@ -17991,6 +17017,16 @@
     Handle<ConsString> cons = Handle<ConsString>::cast(string);
     cons->set_first(*result);
     cons->set_second(isolate->heap()->empty_string());
+  } else if (string->IsSlicedString()) {
+    STATIC_ASSERT(ConsString::kSize == SlicedString::kSize);
+    DisallowHeapAllocation no_gc;
+    bool one_byte = result->IsOneByteRepresentation();
+    Handle<Map> map = one_byte ? isolate->factory()->cons_one_byte_string_map()
+                               : isolate->factory()->cons_string_map();
+    string->set_map(*map);
+    Handle<ConsString> cons = Handle<ConsString>::cast(string);
+    cons->set_first(*result);
+    cons->set_second(isolate->heap()->empty_string());
   }
   return result;
 }
@@ -18097,23 +17133,11 @@
   Isolate* isolate = cache->GetIsolate();
   Handle<SharedFunctionInfo> shared(context->closure()->shared());
   StringSharedKey key(src, shared, language_mode, RelocInfo::kNoPosition);
-  {
-    Handle<Object> k = key.AsHandle(isolate);
-    DisallowHeapAllocation no_allocation_scope;
-    int entry = cache->FindEntry(&key);
-    if (entry != kNotFound) {
-      cache->set(EntryToIndex(entry), *k);
-      cache->set(EntryToIndex(entry) + 1, *value);
-      return cache;
-    }
-  }
-
+  Handle<Object> k = key.AsHandle(isolate);
   cache = EnsureCapacity(cache, 1, &key);
   int entry = cache->FindInsertionEntry(key.Hash());
-  Handle<Object> k =
-      isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
   cache->set(EntryToIndex(entry), *k);
-  cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
+  cache->set(EntryToIndex(entry) + 1, *value);
   cache->ElementAdded();
   return cache;
 }
@@ -18165,7 +17189,8 @@
 void CompilationCacheTable::Age() {
   DisallowHeapAllocation no_allocation;
   Object* the_hole_value = GetHeap()->the_hole_value();
-  for (int entry = 0, size = Capacity(); entry < size; entry++) {
+  uint32_t capacity = Capacity();
+  for (int entry = 0, size = capacity; entry < size; entry++) {
     int entry_index = EntryToIndex(entry);
     int value_index = entry_index + 1;
 
@@ -18188,6 +17213,16 @@
       }
     }
   }
+  // Wipe deleted entries.
+  Heap* heap = GetHeap();
+  Object* the_hole = heap->the_hole_value();
+  Object* undefined = heap->undefined_value();
+  for (uint32_t current = 0; current < capacity; current++) {
+    if (get(EntryToIndex(current)) == the_hole) {
+      set(EntryToIndex(current), undefined);
+    }
+  }
+  SetNumberOfDeletedElements(0);
 }
 
 
@@ -18227,7 +17262,8 @@
 template <typename Derived, typename Shape, typename Key>
 Handle<FixedArray> Dictionary<Derived, Shape, Key>::BuildIterationIndicesArray(
     Handle<Derived> dictionary) {
-  Factory* factory = dictionary->GetIsolate()->factory();
+  Isolate* isolate = dictionary->GetIsolate();
+  Factory* factory = isolate->factory();
   int length = dictionary->NumberOfElements();
 
   Handle<FixedArray> iteration_order = factory->NewFixedArray(length);
@@ -18238,7 +17274,7 @@
   int capacity = dictionary->Capacity();
   int pos = 0;
   for (int i = 0; i < capacity; i++) {
-    if (dictionary->IsKey(dictionary->KeyAt(i))) {
+    if (dictionary->IsKey(isolate, dictionary->KeyAt(i))) {
       int index = dictionary->DetailsAt(i).dictionary_index();
       iteration_order->set(pos, Smi::FromInt(i));
       enumeration_order->set(pos, Smi::FromInt(index));
@@ -18287,7 +17323,7 @@
   DCHECK_EQ(0, DerivedHashTable::NumberOfDeletedElements());
   // Make sure that HashTable::EnsureCapacity will create a copy.
   DerivedHashTable::SetNumberOfDeletedElements(DerivedHashTable::Capacity());
-  DCHECK(!DerivedHashTable::HasSufficientCapacity(1));
+  DCHECK(!DerivedHashTable::HasSufficientCapacityToAdd(1));
 }
 
 
@@ -18385,16 +17421,16 @@
 
 bool SeededNumberDictionary::HasComplexElements() {
   if (!requires_slow_elements()) return false;
+  Isolate* isolate = this->GetIsolate();
   int capacity = this->Capacity();
   for (int i = 0; i < capacity; i++) {
     Object* k = this->KeyAt(i);
-    if (this->IsKey(k)) {
-      DCHECK(!IsDeleted(i));
-      PropertyDetails details = this->DetailsAt(i);
-      if (details.type() == ACCESSOR_CONSTANT) return true;
-      PropertyAttributes attr = details.attributes();
-      if (attr & ALL_ATTRIBUTES_MASK) return true;
-    }
+    if (!this->IsKey(isolate, k)) continue;
+    DCHECK(!IsDeleted(i));
+    PropertyDetails details = this->DetailsAt(i);
+    if (details.type() == ACCESSOR_CONSTANT) return true;
+    PropertyAttributes attr = details.attributes();
+    if (attr & ALL_ATTRIBUTES_MASK) return true;
   }
   return false;
 }
@@ -18490,11 +17526,12 @@
 template <typename Derived, typename Shape, typename Key>
 int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes(
     PropertyFilter filter) {
+  Isolate* isolate = this->GetIsolate();
   int capacity = this->Capacity();
   int result = 0;
   for (int i = 0; i < capacity; i++) {
     Object* k = this->KeyAt(i);
-    if (this->IsKey(k) && !k->FilterKey(filter)) {
+    if (this->IsKey(isolate, k) && !k->FilterKey(filter)) {
       if (this->IsDeleted(i)) continue;
       PropertyDetails details = this->DetailsAt(i);
       PropertyAttributes attr = details.attributes();
@@ -18519,12 +17556,13 @@
 
 template <typename Derived, typename Shape, typename Key>
 void Dictionary<Derived, Shape, Key>::CopyEnumKeysTo(FixedArray* storage) {
+  Isolate* isolate = this->GetIsolate();
   int length = storage->length();
   int capacity = this->Capacity();
   int properties = 0;
   for (int i = 0; i < capacity; i++) {
     Object* k = this->KeyAt(i);
-    if (this->IsKey(k) && !k->IsSymbol()) {
+    if (this->IsKey(isolate, k) && !k->IsSymbol()) {
       PropertyDetails details = this->DetailsAt(i);
       if (details.IsDontEnum() || this->IsDeleted(i)) continue;
       storage->set(properties, Smi::FromInt(i));
@@ -18542,37 +17580,14 @@
   }
 }
 
-
-template <typename Derived, typename Shape, typename Key>
-int Dictionary<Derived, Shape, Key>::CopyKeysTo(
-    FixedArray* storage, int index, PropertyFilter filter,
-    typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
-  DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter));
-  int start_index = index;
-  int capacity = this->Capacity();
-  for (int i = 0; i < capacity; i++) {
-    Object* k = this->KeyAt(i);
-    if (!this->IsKey(k) || k->FilterKey(filter)) continue;
-    if (this->IsDeleted(i)) continue;
-    PropertyDetails details = this->DetailsAt(i);
-    PropertyAttributes attr = details.attributes();
-    if ((attr & filter) != 0) continue;
-    storage->set(index++, k);
-  }
-  if (sort_mode == Dictionary::SORTED) {
-    storage->SortPairs(storage, index);
-  }
-  DCHECK(storage->length() >= index);
-  return index - start_index;
-}
-
 template <typename Derived, typename Shape, typename Key>
 void Dictionary<Derived, Shape, Key>::CollectKeysTo(
     Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys,
     PropertyFilter filter) {
+  Isolate* isolate = keys->isolate();
   int capacity = dictionary->Capacity();
   Handle<FixedArray> array =
-      keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements());
+      isolate->factory()->NewFixedArray(dictionary->NumberOfElements());
   int array_size = 0;
 
   {
@@ -18580,7 +17595,7 @@
     Dictionary<Derived, Shape, Key>* raw_dict = *dictionary;
     for (int i = 0; i < capacity; i++) {
       Object* k = raw_dict->KeyAt(i);
-      if (!raw_dict->IsKey(k) || k->FilterKey(filter)) continue;
+      if (!raw_dict->IsKey(isolate, k) || k->FilterKey(filter)) continue;
       if (raw_dict->IsDeleted(i)) continue;
       PropertyDetails details = raw_dict->DetailsAt(i);
       if ((details.attributes() & filter) != 0) continue;
@@ -18601,9 +17616,23 @@
     std::sort(start, start + array_size, cmp);
   }
 
+  bool has_seen_symbol = false;
   for (int i = 0; i < array_size; i++) {
     int index = Smi::cast(array->get(i))->value();
-    keys->AddKey(dictionary->KeyAt(index), DO_NOT_CONVERT);
+    Object* key = dictionary->KeyAt(index);
+    if (key->IsSymbol()) {
+      has_seen_symbol = true;
+      continue;
+    }
+    keys->AddKey(key, DO_NOT_CONVERT);
+  }
+  if (has_seen_symbol) {
+    for (int i = 0; i < array_size; i++) {
+      int index = Smi::cast(array->get(i))->value();
+      Object* key = dictionary->KeyAt(index);
+      if (!key->IsSymbol()) continue;
+      keys->AddKey(key, DO_NOT_CONVERT);
+    }
   }
 }
 
@@ -18611,27 +17640,26 @@
 // Backwards lookup (slow).
 template<typename Derived, typename Shape, typename Key>
 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
+  Isolate* isolate = this->GetIsolate();
   int capacity = this->Capacity();
   for (int i = 0; i < capacity; i++) {
     Object* k = this->KeyAt(i);
-    if (this->IsKey(k)) {
-      Object* e = this->ValueAt(i);
-      // TODO(dcarney): this should be templatized.
-      if (e->IsPropertyCell()) {
-        e = PropertyCell::cast(e)->value();
-      }
-      if (e == value) return k;
+    if (!this->IsKey(isolate, k)) continue;
+    Object* e = this->ValueAt(i);
+    // TODO(dcarney): this should be templatized.
+    if (e->IsPropertyCell()) {
+      e = PropertyCell::cast(e)->value();
     }
+    if (e == value) return k;
   }
-  Heap* heap = Dictionary::GetHeap();
-  return heap->undefined_value();
+  return isolate->heap()->undefined_value();
 }
 
 
 Object* ObjectHashTable::Lookup(Isolate* isolate, Handle<Object> key,
                                 int32_t hash) {
   DisallowHeapAllocation no_gc;
-  DCHECK(IsKey(*key));
+  DCHECK(IsKey(isolate, *key));
 
   int entry = FindEntry(isolate, key, hash);
   if (entry == kNotFound) return isolate->heap()->the_hole_value();
@@ -18641,13 +17669,13 @@
 
 Object* ObjectHashTable::Lookup(Handle<Object> key) {
   DisallowHeapAllocation no_gc;
-  DCHECK(IsKey(*key));
 
   Isolate* isolate = GetIsolate();
+  DCHECK(IsKey(isolate, *key));
 
   // If the object does not have an identity hash, it was never used as a key.
   Object* hash = key->GetHash();
-  if (hash->IsUndefined()) {
+  if (hash->IsUndefined(isolate)) {
     return isolate->heap()->the_hole_value();
   }
   return Lookup(isolate, key, Smi::cast(hash)->value());
@@ -18662,10 +17690,10 @@
 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
                                              Handle<Object> key,
                                              Handle<Object> value) {
-  DCHECK(table->IsKey(*key));
-  DCHECK(!value->IsTheHole());
-
   Isolate* isolate = table->GetIsolate();
+  DCHECK(table->IsKey(isolate, *key));
+  DCHECK(!value->IsTheHole(isolate));
+
   // Make sure the key object has an identity hash code.
   int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
 
@@ -18677,10 +17705,9 @@
                                              Handle<Object> key,
                                              Handle<Object> value,
                                              int32_t hash) {
-  DCHECK(table->IsKey(*key));
-  DCHECK(!value->IsTheHole());
-
   Isolate* isolate = table->GetIsolate();
+  DCHECK(table->IsKey(isolate, *key));
+  DCHECK(!value->IsTheHole(isolate));
 
   int entry = table->FindEntry(isolate, key, hash);
 
@@ -18695,6 +17722,19 @@
   if ((table->NumberOfDeletedElements() << 1) > table->NumberOfElements()) {
     table->Rehash(isolate->factory()->undefined_value());
   }
+  // If we're out of luck, we didn't get a GC recently, and so rehashing
+  // isn't enough to avoid a crash.
+  if (!table->HasSufficientCapacityToAdd(1)) {
+    int nof = table->NumberOfElements() + 1;
+    int capacity = ObjectHashTable::ComputeCapacity(nof * 2);
+    if (capacity > ObjectHashTable::kMaxCapacity) {
+      for (size_t i = 0; i < 2; ++i) {
+        isolate->heap()->CollectAllGarbage(
+            Heap::kFinalizeIncrementalMarkingMask, "full object hash table");
+      }
+      table->Rehash(isolate->factory()->undefined_value());
+    }
+  }
 
   // Check whether the hash table should be extended.
   table = EnsureCapacity(table, 1, key);
@@ -18706,10 +17746,10 @@
 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
                                                 Handle<Object> key,
                                                 bool* was_present) {
-  DCHECK(table->IsKey(*key));
+  DCHECK(table->IsKey(table->GetIsolate(), *key));
 
   Object* hash = key->GetHash();
-  if (hash->IsUndefined()) {
+  if (hash->IsUndefined(table->GetIsolate())) {
     *was_present = false;
     return table;
   }
@@ -18722,9 +17762,10 @@
                                                 Handle<Object> key,
                                                 bool* was_present,
                                                 int32_t hash) {
-  DCHECK(table->IsKey(*key));
+  Isolate* isolate = table->GetIsolate();
+  DCHECK(table->IsKey(isolate, *key));
 
-  int entry = table->FindEntry(table->GetIsolate(), key, hash);
+  int entry = table->FindEntry(isolate, key, hash);
   if (entry == kNotFound) {
     *was_present = false;
     return table;
@@ -18752,9 +17793,10 @@
 
 Object* WeakHashTable::Lookup(Handle<HeapObject> key) {
   DisallowHeapAllocation no_gc;
-  DCHECK(IsKey(*key));
+  Isolate* isolate = GetIsolate();
+  DCHECK(IsKey(isolate, *key));
   int entry = FindEntry(key);
-  if (entry == kNotFound) return GetHeap()->the_hole_value();
+  if (entry == kNotFound) return isolate->heap()->the_hole_value();
   return get(EntryToValueIndex(entry));
 }
 
@@ -18762,7 +17804,8 @@
 Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
                                          Handle<HeapObject> key,
                                          Handle<HeapObject> value) {
-  DCHECK(table->IsKey(*key));
+  Isolate* isolate = key->GetIsolate();
+  DCHECK(table->IsKey(isolate, *key));
   int entry = table->FindEntry(key);
   // Key is already in table, just overwrite value.
   if (entry != kNotFound) {
@@ -18770,7 +17813,7 @@
     return table;
   }
 
-  Handle<WeakCell> key_cell = key->GetIsolate()->factory()->NewWeakCell(key);
+  Handle<WeakCell> key_cell = isolate->factory()->NewWeakCell(key);
 
   // Check whether the hash table should be extended.
   table = EnsureCapacity(table, 1, key, TENURED);
@@ -18864,11 +17907,14 @@
 template <class Derived, class Iterator, int entrysize>
 bool OrderedHashTable<Derived, Iterator, entrysize>::HasKey(
     Handle<Derived> table, Handle<Object> key) {
-  int entry = table->KeyToFirstEntry(*key);
+  DisallowHeapAllocation no_gc;
+  Isolate* isolate = table->GetIsolate();
+  Object* raw_key = *key;
+  int entry = table->KeyToFirstEntry(isolate, raw_key);
   // Walk the chain in the bucket to find the key.
   while (entry != kNotFound) {
     Object* candidate_key = table->KeyAt(entry);
-    if (candidate_key->SameValueZero(*key)) return true;
+    if (candidate_key->SameValueZero(raw_key)) return true;
     entry = table->NextChainEntry(entry);
   }
   return false;
@@ -18903,25 +17949,46 @@
   return table;
 }
 
+Handle<FixedArray> OrderedHashSet::ConvertToKeysArray(
+    Handle<OrderedHashSet> table, GetKeysConversion convert) {
+  Isolate* isolate = table->GetIsolate();
+  int length = table->NumberOfElements();
+  int nof_buckets = table->NumberOfBuckets();
+  // Convert the dictionary to a linear list.
+  Handle<FixedArray> result = Handle<FixedArray>::cast(table);
+  // From this point on table is no longer a valid OrderedHashSet.
+  result->set_map(isolate->heap()->fixed_array_map());
+  for (int i = 0; i < length; i++) {
+    int index = kHashTableStartIndex + nof_buckets + (i * kEntrySize);
+    Object* key = table->get(index);
+    if (convert == GetKeysConversion::kConvertToString && key->IsNumber()) {
+      key = *isolate->factory()->NumberToString(handle(key, isolate));
+    }
+    result->set(i, key);
+  }
+  result->Shrink(length);
+  return result;
+}
 
 template<class Derived, class Iterator, int entrysize>
 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
     Handle<Derived> table, int new_capacity) {
+  Isolate* isolate = table->GetIsolate();
   DCHECK(!table->IsObsolete());
 
   Handle<Derived> new_table =
-      Allocate(table->GetIsolate(),
-               new_capacity,
-               table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
+      Allocate(isolate, new_capacity,
+               isolate->heap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
   int nof = table->NumberOfElements();
   int nod = table->NumberOfDeletedElements();
   int new_buckets = new_table->NumberOfBuckets();
   int new_entry = 0;
   int removed_holes_index = 0;
 
+  DisallowHeapAllocation no_gc;
   for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) {
     Object* key = table->KeyAt(old_entry);
-    if (key->IsTheHole()) {
+    if (key->IsTheHole(isolate)) {
       table->SetRemovedIndexAt(removed_holes_index++, old_entry);
       continue;
     }
@@ -19025,7 +18092,8 @@
 template<class Derived, class TableType>
 bool OrderedHashTableIterator<Derived, TableType>::HasMore() {
   DisallowHeapAllocation no_allocation;
-  if (this->table()->IsUndefined()) return false;
+  Isolate* isolate = this->GetIsolate();
+  if (this->table()->IsUndefined(isolate)) return false;
 
   Transition();
 
@@ -19033,7 +18101,7 @@
   int index = Smi::cast(this->index())->value();
   int used_capacity = table->UsedCapacity();
 
-  while (index < used_capacity && table->KeyAt(index)->IsTheHole()) {
+  while (index < used_capacity && table->KeyAt(index)->IsTheHole(isolate)) {
     index++;
   }
 
@@ -19041,7 +18109,7 @@
 
   if (index < used_capacity) return true;
 
-  set_table(GetHeap()->undefined_value());
+  set_table(isolate->heap()->undefined_value());
   return false;
 }
 
@@ -19167,7 +18235,7 @@
 
   // If there is no break point info object or no break points in the break
   // point info object there is no break point at this code offset.
-  if (break_point_info->IsUndefined()) return false;
+  if (break_point_info->IsUndefined(GetIsolate())) return false;
   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
 }
 
@@ -19184,9 +18252,10 @@
 // Clear a break point at the specified code offset.
 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info, int code_offset,
                                 Handle<Object> break_point_object) {
+  Isolate* isolate = debug_info->GetIsolate();
   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_offset),
-                                  debug_info->GetIsolate());
-  if (break_point_info->IsUndefined()) return;
+                                  isolate);
+  if (break_point_info->IsUndefined(isolate)) return;
   BreakPointInfo::ClearBreakPoint(
       Handle<BreakPointInfo>::cast(break_point_info),
       break_point_object);
@@ -19198,7 +18267,7 @@
   Isolate* isolate = debug_info->GetIsolate();
   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_offset),
                                   isolate);
-  if (!break_point_info->IsUndefined()) {
+  if (!break_point_info->IsUndefined(isolate)) {
     BreakPointInfo::SetBreakPoint(
         Handle<BreakPointInfo>::cast(break_point_info),
         break_point_object);
@@ -19209,15 +18278,15 @@
   // break points before. Try to find a free slot.
   int index = kNoBreakPointInfo;
   for (int i = 0; i < debug_info->break_points()->length(); i++) {
-    if (debug_info->break_points()->get(i)->IsUndefined()) {
+    if (debug_info->break_points()->get(i)->IsUndefined(isolate)) {
       index = i;
       break;
     }
   }
   if (index == kNoBreakPointInfo) {
     // No free slot - extend break point info array.
-    Handle<FixedArray> old_break_points =
-        Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
+    Handle<FixedArray> old_break_points = Handle<FixedArray>(
+        FixedArray::cast(debug_info->break_points()), isolate);
     Handle<FixedArray> new_break_points =
         isolate->factory()->NewFixedArray(
             old_break_points->length() +
@@ -19246,21 +18315,22 @@
 // Get the break point objects for a code offset.
 Handle<Object> DebugInfo::GetBreakPointObjects(int code_offset) {
   Object* break_point_info = GetBreakPointInfo(code_offset);
-  if (break_point_info->IsUndefined()) {
-    return GetIsolate()->factory()->undefined_value();
+  Isolate* isolate = GetIsolate();
+  if (break_point_info->IsUndefined(isolate)) {
+    return isolate->factory()->undefined_value();
   }
   return Handle<Object>(
-      BreakPointInfo::cast(break_point_info)->break_point_objects(),
-      GetIsolate());
+      BreakPointInfo::cast(break_point_info)->break_point_objects(), isolate);
 }
 
 
 // Get the total number of break points.
 int DebugInfo::GetBreakPointCount() {
-  if (break_points()->IsUndefined()) return 0;
+  Isolate* isolate = GetIsolate();
+  if (break_points()->IsUndefined(isolate)) return 0;
   int count = 0;
   for (int i = 0; i < break_points()->length(); i++) {
-    if (!break_points()->get(i)->IsUndefined()) {
+    if (!break_points()->get(i)->IsUndefined(isolate)) {
       BreakPointInfo* break_point_info =
           BreakPointInfo::cast(break_points()->get(i));
       count += break_point_info->GetBreakPointCount();
@@ -19273,9 +18343,9 @@
 Handle<Object> DebugInfo::FindBreakPointInfo(
     Handle<DebugInfo> debug_info, Handle<Object> break_point_object) {
   Isolate* isolate = debug_info->GetIsolate();
-  if (!debug_info->break_points()->IsUndefined()) {
+  if (!debug_info->break_points()->IsUndefined(isolate)) {
     for (int i = 0; i < debug_info->break_points()->length(); i++) {
-      if (!debug_info->break_points()->get(i)->IsUndefined()) {
+      if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
         Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
             BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
         if (BreakPointInfo::HasBreakPointObject(break_point_info,
@@ -19292,9 +18362,10 @@
 // Find the index of the break point info object for the specified code
 // position.
 int DebugInfo::GetBreakPointInfoIndex(int code_offset) {
-  if (break_points()->IsUndefined()) return kNoBreakPointInfo;
+  Isolate* isolate = GetIsolate();
+  if (break_points()->IsUndefined(isolate)) return kNoBreakPointInfo;
   for (int i = 0; i < break_points()->length(); i++) {
-    if (!break_points()->get(i)->IsUndefined()) {
+    if (!break_points()->get(i)->IsUndefined(isolate)) {
       BreakPointInfo* break_point_info =
           BreakPointInfo::cast(break_points()->get(i));
       if (break_point_info->code_offset() == code_offset) {
@@ -19311,7 +18382,7 @@
                                      Handle<Object> break_point_object) {
   Isolate* isolate = break_point_info->GetIsolate();
   // If there are no break points just ignore.
-  if (break_point_info->break_point_objects()->IsUndefined()) return;
+  if (break_point_info->break_point_objects()->IsUndefined(isolate)) return;
   // If there is a single break point clear it if it is the same.
   if (!break_point_info->break_point_objects()->IsFixedArray()) {
     if (break_point_info->break_point_objects() == *break_point_object) {
@@ -19347,7 +18418,7 @@
   Isolate* isolate = break_point_info->GetIsolate();
 
   // If there was no break point objects before just set it.
-  if (break_point_info->break_point_objects()->IsUndefined()) {
+  if (break_point_info->break_point_objects()->IsUndefined(isolate)) {
     break_point_info->set_break_point_objects(*break_point_object);
     return;
   }
@@ -19382,7 +18453,10 @@
     Handle<BreakPointInfo> break_point_info,
     Handle<Object> break_point_object) {
   // No break point.
-  if (break_point_info->break_point_objects()->IsUndefined()) return false;
+  Isolate* isolate = break_point_info->GetIsolate();
+  if (break_point_info->break_point_objects()->IsUndefined(isolate)) {
+    return false;
+  }
   // Single break point.
   if (!break_point_info->break_point_objects()->IsFixedArray()) {
     return break_point_info->break_point_objects() == *break_point_object;
@@ -19401,7 +18475,7 @@
 // Get the number of break points.
 int BreakPointInfo::GetBreakPointCount() {
   // No break point.
-  if (break_point_objects()->IsUndefined()) return 0;
+  if (break_point_objects()->IsUndefined(GetIsolate())) return 0;
   // Single break point.
   if (!break_point_objects()->IsFixedArray()) return 1;
   // Multiple break points.
@@ -19728,7 +18802,7 @@
   auto new_cell = isolate->factory()->NewPropertyCell();
   new_cell->set_value(cell->value());
   dictionary->ValueAtPut(entry, *new_cell);
-  bool is_the_hole = cell->value()->IsTheHole();
+  bool is_the_hole = cell->value()->IsTheHole(isolate);
   // Cell is officially mutable henceforth.
   PropertyDetails details = cell->property_details();
   details = details.set_cell_type(is_the_hole ? PropertyCellType::kInvalidated
@@ -19772,12 +18846,13 @@
                                            Handle<Object> value,
                                            PropertyDetails details) {
   PropertyCellType type = details.cell_type();
-  DCHECK(!value->IsTheHole());
-  if (cell->value()->IsTheHole()) {
+  Isolate* isolate = cell->GetIsolate();
+  DCHECK(!value->IsTheHole(isolate));
+  if (cell->value()->IsTheHole(isolate)) {
     switch (type) {
       // Only allow a cell to transition once into constant state.
       case PropertyCellType::kUninitialized:
-        if (value->IsUndefined()) return PropertyCellType::kUndefined;
+        if (value->IsUndefined(isolate)) return PropertyCellType::kUndefined;
         return PropertyCellType::kConstant;
       case PropertyCellType::kInvalidated:
         return PropertyCellType::kMutable;
@@ -19807,7 +18882,8 @@
 
 void PropertyCell::UpdateCell(Handle<GlobalDictionary> dictionary, int entry,
                               Handle<Object> value, PropertyDetails details) {
-  DCHECK(!value->IsTheHole());
+  Isolate* isolate = dictionary->GetIsolate();
+  DCHECK(!value->IsTheHole(isolate));
   DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
   Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
   const PropertyDetails original_details = cell->property_details();
@@ -19818,7 +18894,7 @@
   PropertyCellType old_type = original_details.cell_type();
   // Preserve the enumeration index unless the property was deleted or never
   // initialized.
-  if (cell->value()->IsTheHole()) {
+  if (cell->value()->IsTheHole(isolate)) {
     index = dictionary->NextEnumerationIndex();
     dictionary->SetNextEnumerationIndex(index + 1);
     // Negative lookup cells must be invalidated.
@@ -19838,7 +18914,6 @@
   // Deopt when transitioning from a constant type.
   if (!invalidate && (old_type != new_type ||
                       original_details.IsReadOnly() != details.IsReadOnly())) {
-    Isolate* isolate = dictionary->GetIsolate();
     cell->dependent_code()->DeoptimizeDependentCodeGroup(
         isolate, DependentCode::kPropertyCellChangedGroup);
   }
@@ -19856,5 +18931,41 @@
   }
 }
 
+int JSGeneratorObject::source_position() const {
+  CHECK(is_suspended());
+  if (function()->shared()->HasBytecodeArray()) {
+    // New-style generators.
+    int offset = Smi::cast(input_or_debug_pos())->value();
+    // The stored bytecode offset is relative to a different base than what
+    // is used in the source position table, hence the subtraction.
+    offset -= BytecodeArray::kHeaderSize - kHeapObjectTag;
+    return function()->shared()->bytecode_array()->SourcePosition(offset);
+  } else {
+    // Old-style generators.
+    int offset = continuation();
+    CHECK(0 <= offset && offset < function()->code()->instruction_size());
+    return function()->code()->SourcePosition(offset);
+  }
+}
+
+// static
+AccessCheckInfo* AccessCheckInfo::Get(Isolate* isolate,
+                                      Handle<JSObject> receiver) {
+  DisallowHeapAllocation no_gc;
+  DCHECK(receiver->map()->is_access_check_needed());
+  Object* maybe_constructor = receiver->map()->GetConstructor();
+  // Might happen for a detached context.
+  if (!maybe_constructor->IsJSFunction()) return nullptr;
+  JSFunction* constructor = JSFunction::cast(maybe_constructor);
+  // Might happen for the debug context.
+  if (!constructor->shared()->IsApiFunction()) return nullptr;
+
+  Object* data_obj =
+      constructor->shared()->get_api_func_data()->access_check_info();
+  if (data_obj->IsUndefined(isolate)) return nullptr;
+
+  return AccessCheckInfo::cast(data_obj);
+}
+
 }  // namespace internal
 }  // namespace v8
diff --git a/src/objects.h b/src/objects.h
index cbc9c04..e37b9bd 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -309,7 +309,7 @@
 
 // We may store the unsigned bit field as signed Smi value and do not
 // use the sign bit.
-const int kStubMajorKeyBits = 7;
+const int kStubMajorKeyBits = 8;
 const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
 
 // All Maps have a field instance_type containing a InstanceType.
@@ -398,8 +398,6 @@
   V(ALLOCATION_MEMENTO_TYPE)                                    \
   V(ALLOCATION_SITE_TYPE)                                       \
   V(SCRIPT_TYPE)                                                \
-  V(CODE_CACHE_TYPE)                                            \
-  V(POLYMORPHIC_CODE_CACHE_TYPE)                                \
   V(TYPE_FEEDBACK_INFO_TYPE)                                    \
   V(ALIASED_ARGUMENTS_ENTRY_TYPE)                               \
   V(BOX_TYPE)                                                   \
@@ -417,11 +415,13 @@
   V(JS_VALUE_TYPE)                                              \
   V(JS_DATE_TYPE)                                               \
   V(JS_OBJECT_TYPE)                                             \
+  V(JS_ARGUMENTS_TYPE)                                          \
   V(JS_CONTEXT_EXTENSION_OBJECT_TYPE)                           \
   V(JS_GENERATOR_OBJECT_TYPE)                                   \
   V(JS_MODULE_TYPE)                                             \
   V(JS_GLOBAL_OBJECT_TYPE)                                      \
   V(JS_GLOBAL_PROXY_TYPE)                                       \
+  V(JS_API_OBJECT_TYPE)                                         \
   V(JS_SPECIAL_API_OBJECT_TYPE)                                 \
   V(JS_ARRAY_TYPE)                                              \
   V(JS_ARRAY_BUFFER_TYPE)                                       \
@@ -436,6 +436,7 @@
   V(JS_WEAK_SET_TYPE)                                           \
   V(JS_PROMISE_TYPE)                                            \
   V(JS_REGEXP_TYPE)                                             \
+  V(JS_ERROR_TYPE)                                              \
                                                                 \
   V(JS_BOUND_FUNCTION_TYPE)                                     \
   V(JS_FUNCTION_TYPE)                                           \
@@ -514,8 +515,6 @@
   V(SCRIPT, Script, script)                                                  \
   V(ALLOCATION_SITE, AllocationSite, allocation_site)                        \
   V(ALLOCATION_MEMENTO, AllocationMemento, allocation_memento)               \
-  V(CODE_CACHE, CodeCache, code_cache)                                       \
-  V(POLYMORPHIC_CODE_CACHE, PolymorphicCodeCache, polymorphic_code_cache)    \
   V(TYPE_FEEDBACK_INFO, TypeFeedbackInfo, type_feedback_info)                \
   V(ALIASED_ARGUMENTS_ENTRY, AliasedArgumentsEntry, aliased_arguments_entry) \
   V(DEBUG_INFO, DebugInfo, debug_info)                                       \
@@ -685,8 +684,6 @@
   ALLOCATION_SITE_TYPE,
   ALLOCATION_MEMENTO_TYPE,
   SCRIPT_TYPE,
-  CODE_CACHE_TYPE,
-  POLYMORPHIC_CODE_CACHE_TYPE,
   TYPE_FEEDBACK_INFO_TYPE,
   ALIASED_ARGUMENTS_ENTRY_TYPE,
   BOX_TYPE,
@@ -708,12 +705,16 @@
   JS_PROXY_TYPE,          // FIRST_JS_RECEIVER_TYPE
   JS_GLOBAL_OBJECT_TYPE,  // FIRST_JS_OBJECT_TYPE
   JS_GLOBAL_PROXY_TYPE,
-  // Like JS_OBJECT_TYPE, but requires access checks and/or has interceptors.
+  // Like JS_API_OBJECT_TYPE, but requires access checks and/or has
+  // interceptors.
   JS_SPECIAL_API_OBJECT_TYPE,  // LAST_SPECIAL_RECEIVER_TYPE
   JS_VALUE_TYPE,               // LAST_CUSTOM_ELEMENTS_RECEIVER
   JS_MESSAGE_OBJECT_TYPE,
   JS_DATE_TYPE,
+  // Like JS_OBJECT_TYPE, but created from API function.
+  JS_API_OBJECT_TYPE,
   JS_OBJECT_TYPE,
+  JS_ARGUMENTS_TYPE,
   JS_CONTEXT_EXTENSION_OBJECT_TYPE,
   JS_GENERATOR_OBJECT_TYPE,
   JS_MODULE_TYPE,
@@ -729,6 +730,7 @@
   JS_WEAK_SET_TYPE,
   JS_PROMISE_TYPE,
   JS_REGEXP_TYPE,
+  JS_ERROR_TYPE,
   JS_BOUND_FUNCTION_TYPE,
   JS_FUNCTION_TYPE,  // LAST_JS_OBJECT_TYPE, LAST_JS_RECEIVER_TYPE
 
@@ -768,6 +770,7 @@
 };
 
 STATIC_ASSERT(JS_OBJECT_TYPE == Internals::kJSObjectType);
+STATIC_ASSERT(JS_API_OBJECT_TYPE == Internals::kJSApiObjectType);
 STATIC_ASSERT(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType);
 STATIC_ASSERT(ODDBALL_TYPE == Internals::kOddballType);
 STATIC_ASSERT(FOREIGN_TYPE == Internals::kForeignType);
@@ -857,6 +860,7 @@
 class SharedFunctionInfo;
 class StringStream;
 class TypeFeedbackInfo;
+class TypeFeedbackMetadata;
 class TypeFeedbackVector;
 class WeakCell;
 class TransitionArray;
@@ -884,134 +888,136 @@
   V(Primitive)              \
   V(Number)
 
-#define HEAP_OBJECT_TYPE_LIST(V)   \
-  V(HeapNumber)                    \
-  V(MutableHeapNumber)             \
-  V(Simd128Value)                  \
-  V(Float32x4)                     \
-  V(Int32x4)                       \
-  V(Uint32x4)                      \
-  V(Bool32x4)                      \
-  V(Int16x8)                       \
-  V(Uint16x8)                      \
-  V(Bool16x8)                      \
-  V(Int8x16)                       \
-  V(Uint8x16)                      \
-  V(Bool8x16)                      \
-  V(Name)                          \
-  V(UniqueName)                    \
-  V(String)                        \
-  V(SeqString)                     \
-  V(ExternalString)                \
-  V(ConsString)                    \
-  V(SlicedString)                  \
-  V(ExternalTwoByteString)         \
-  V(ExternalOneByteString)         \
-  V(SeqTwoByteString)              \
-  V(SeqOneByteString)              \
-  V(InternalizedString)            \
-  V(Symbol)                        \
-                                   \
-  V(FixedTypedArrayBase)           \
-  V(FixedUint8Array)               \
-  V(FixedInt8Array)                \
-  V(FixedUint16Array)              \
-  V(FixedInt16Array)               \
-  V(FixedUint32Array)              \
-  V(FixedInt32Array)               \
-  V(FixedFloat32Array)             \
-  V(FixedFloat64Array)             \
-  V(FixedUint8ClampedArray)        \
-  V(ByteArray)                     \
-  V(BytecodeArray)                 \
-  V(FreeSpace)                     \
-  V(JSReceiver)                    \
-  V(JSObject)                      \
-  V(JSContextExtensionObject)      \
-  V(JSGeneratorObject)             \
-  V(JSModule)                      \
-  V(Map)                           \
-  V(DescriptorArray)               \
-  V(TransitionArray)               \
-  V(LiteralsArray)                 \
-  V(TypeFeedbackMetadata)          \
-  V(TypeFeedbackVector)            \
-  V(DeoptimizationInputData)       \
-  V(DeoptimizationOutputData)      \
-  V(DependentCode)                 \
-  V(HandlerTable)                  \
-  V(FixedArray)                    \
-  V(FixedDoubleArray)              \
-  V(WeakFixedArray)                \
-  V(ArrayList)                     \
-  V(Context)                       \
-  V(ScriptContextTable)            \
-  V(NativeContext)                 \
-  V(ScopeInfo)                     \
-  V(JSBoundFunction)               \
-  V(JSFunction)                    \
-  V(Code)                          \
-  V(AbstractCode)                  \
-  V(Oddball)                       \
-  V(SharedFunctionInfo)            \
-  V(JSValue)                       \
-  V(JSDate)                        \
-  V(JSMessageObject)               \
-  V(StringWrapper)                 \
-  V(Foreign)                       \
-  V(Boolean)                       \
-  V(JSArray)                       \
-  V(JSArrayBuffer)                 \
-  V(JSArrayBufferView)             \
-  V(JSTypedArray)                  \
-  V(JSDataView)                    \
-  V(JSProxy)                       \
-  V(JSSet)                         \
-  V(JSMap)                         \
-  V(JSSetIterator)                 \
-  V(JSMapIterator)                 \
-  V(JSWeakCollection)              \
-  V(JSWeakMap)                     \
-  V(JSWeakSet)                     \
-  V(JSRegExp)                      \
-  V(HashTable)                     \
-  V(Dictionary)                    \
-  V(StringTable)                   \
-  V(StringSet)                     \
-  V(NormalizedMapCache)            \
-  V(CompilationCacheTable)         \
-  V(CodeCacheHashTable)            \
-  V(PolymorphicCodeCacheHashTable) \
-  V(MapCache)                      \
-  V(JSGlobalObject)                \
-  V(JSGlobalProxy)                 \
-  V(Undetectable)                  \
-  V(AccessCheckNeeded)             \
-  V(Callable)                      \
-  V(Function)                      \
-  V(Constructor)                   \
-  V(TemplateInfo)                  \
-  V(Filler)                        \
-  V(FixedArrayBase)                \
-  V(External)                      \
-  V(Struct)                        \
-  V(Cell)                          \
-  V(PropertyCell)                  \
-  V(WeakCell)                      \
-  V(ObjectHashTable)               \
-  V(WeakHashTable)                 \
+#define HEAP_OBJECT_TYPE_LIST(V) \
+  V(HeapNumber)                  \
+  V(MutableHeapNumber)           \
+  V(Simd128Value)                \
+  V(Float32x4)                   \
+  V(Int32x4)                     \
+  V(Uint32x4)                    \
+  V(Bool32x4)                    \
+  V(Int16x8)                     \
+  V(Uint16x8)                    \
+  V(Bool16x8)                    \
+  V(Int8x16)                     \
+  V(Uint8x16)                    \
+  V(Bool8x16)                    \
+  V(Name)                        \
+  V(UniqueName)                  \
+  V(String)                      \
+  V(SeqString)                   \
+  V(ExternalString)              \
+  V(ConsString)                  \
+  V(SlicedString)                \
+  V(ExternalTwoByteString)       \
+  V(ExternalOneByteString)       \
+  V(SeqTwoByteString)            \
+  V(SeqOneByteString)            \
+  V(InternalizedString)          \
+  V(Symbol)                      \
+                                 \
+  V(FixedTypedArrayBase)         \
+  V(FixedUint8Array)             \
+  V(FixedInt8Array)              \
+  V(FixedUint16Array)            \
+  V(FixedInt16Array)             \
+  V(FixedUint32Array)            \
+  V(FixedInt32Array)             \
+  V(FixedFloat32Array)           \
+  V(FixedFloat64Array)           \
+  V(FixedUint8ClampedArray)      \
+  V(ByteArray)                   \
+  V(BytecodeArray)               \
+  V(FreeSpace)                   \
+  V(JSReceiver)                  \
+  V(JSObject)                    \
+  V(JSContextExtensionObject)    \
+  V(JSGeneratorObject)           \
+  V(JSModule)                    \
+  V(Map)                         \
+  V(DescriptorArray)             \
+  V(TransitionArray)             \
+  V(LiteralsArray)               \
+  V(TypeFeedbackMetadata)        \
+  V(TypeFeedbackVector)          \
+  V(DeoptimizationInputData)     \
+  V(DeoptimizationOutputData)    \
+  V(DependentCode)               \
+  V(HandlerTable)                \
+  V(FixedArray)                  \
+  V(FixedDoubleArray)            \
+  V(WeakFixedArray)              \
+  V(ArrayList)                   \
+  V(Context)                     \
+  V(ScriptContextTable)          \
+  V(NativeContext)               \
+  V(ScopeInfo)                   \
+  V(JSBoundFunction)             \
+  V(JSFunction)                  \
+  V(Code)                        \
+  V(AbstractCode)                \
+  V(Oddball)                     \
+  V(SharedFunctionInfo)          \
+  V(JSValue)                     \
+  V(JSDate)                      \
+  V(JSMessageObject)             \
+  V(StringWrapper)               \
+  V(Foreign)                     \
+  V(Boolean)                     \
+  V(JSArray)                     \
+  V(JSArrayBuffer)               \
+  V(JSArrayBufferView)           \
+  V(JSTypedArray)                \
+  V(JSDataView)                  \
+  V(JSProxy)                     \
+  V(JSError)                     \
+  V(JSPromise)                   \
+  V(JSSet)                       \
+  V(JSMap)                       \
+  V(JSSetIterator)               \
+  V(JSMapIterator)               \
+  V(JSWeakCollection)            \
+  V(JSWeakMap)                   \
+  V(JSWeakSet)                   \
+  V(JSRegExp)                    \
+  V(HashTable)                   \
+  V(Dictionary)                  \
+  V(StringTable)                 \
+  V(StringSet)                   \
+  V(NormalizedMapCache)          \
+  V(CompilationCacheTable)       \
+  V(CodeCacheHashTable)          \
+  V(MapCache)                    \
+  V(JSGlobalObject)              \
+  V(JSGlobalProxy)               \
+  V(Undetectable)                \
+  V(AccessCheckNeeded)           \
+  V(Callable)                    \
+  V(Function)                    \
+  V(Constructor)                 \
+  V(TemplateInfo)                \
+  V(Filler)                      \
+  V(FixedArrayBase)              \
+  V(External)                    \
+  V(Struct)                      \
+  V(Cell)                        \
+  V(PropertyCell)                \
+  V(WeakCell)                    \
+  V(ObjectHashTable)             \
+  V(WeakHashTable)               \
   V(OrderedHashTable)
 
-#define ODDBALL_LIST(V) \
-  V(Undefined)          \
-  V(Null)               \
-  V(TheHole)            \
-  V(Exception)          \
-  V(Uninitialized)      \
-  V(True)               \
-  V(False)              \
-  V(ArgumentsMarker)    \
-  V(OptimizedOut)
+#define ODDBALL_LIST(V)                 \
+  V(Undefined, undefined_value)         \
+  V(Null, null_value)                   \
+  V(TheHole, the_hole_value)            \
+  V(Exception, exception)               \
+  V(Uninitialized, uninitialized_value) \
+  V(True, true_value)                   \
+  V(False, false_value)                 \
+  V(ArgumentsMarker, arguments_marker)  \
+  V(OptimizedOut, optimized_out)        \
+  V(StaleRegister, stale_register)
 
 // The element types selection for CreateListFromArrayLike.
 enum class ElementTypes { kAll, kStringAndSymbol };
@@ -1027,9 +1033,12 @@
   // Type testing.
   bool IsObject() const { return true; }
 
-#define IS_TYPE_FUNCTION_DECL(type_)  INLINE(bool Is##type_() const);
+#define IS_TYPE_FUNCTION_DECL(Type) INLINE(bool Is##Type() const);
   OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
   HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
+#undef IS_TYPE_FUNCTION_DECL
+#define IS_TYPE_FUNCTION_DECL(Type, Value) \
+  INLINE(bool Is##Type(Isolate* isolate) const);
   ODDBALL_LIST(IS_TYPE_FUNCTION_DECL)
 #undef IS_TYPE_FUNCTION_DECL
 
@@ -1073,7 +1082,6 @@
   INLINE(bool IsUnseededNumberDictionary() const);
   INLINE(bool IsOrderedHashSet() const);
   INLINE(bool IsOrderedHashMap() const);
-  static bool IsPromise(Handle<Object> object);
 
   // Extract the number.
   inline double Number() const;
@@ -1162,6 +1170,10 @@
   MUST_USE_RESULT static MaybeHandle<String> ToString(Isolate* isolate,
                                                       Handle<Object> input);
 
+  // ES6 section 7.1.14 ToPropertyKey
+  MUST_USE_RESULT static MaybeHandle<Object> ToPropertyKey(
+      Isolate* isolate, Handle<Object> value);
+
   // ES6 section 7.1.15 ToLength
   MUST_USE_RESULT static MaybeHandle<Object> ToLength(Isolate* isolate,
                                                       Handle<Object> input);
@@ -1174,8 +1186,9 @@
   MUST_USE_RESULT static MaybeHandle<FixedArray> CreateListFromArrayLike(
       Isolate* isolate, Handle<Object> object, ElementTypes element_types);
 
-  // Check whether |object| is an instance of Error or NativeError.
-  static bool IsErrorObject(Isolate* isolate, Handle<Object> object);
+  // Get length property and apply ToLength.
+  MUST_USE_RESULT static MaybeHandle<Object> GetLengthFromArrayLike(
+      Isolate* isolate, Handle<Object> object);
 
   // ES6 section 12.5.6 The typeof Operator
   static Handle<String> TypeOf(Isolate* isolate, Handle<Object> object);
@@ -1230,6 +1243,14 @@
                                                         Handle<Object> lhs,
                                                         Handle<Object> rhs);
 
+  // ES6 section 7.3.19 OrdinaryHasInstance (C, O).
+  MUST_USE_RESULT static MaybeHandle<Object> OrdinaryHasInstance(
+      Isolate* isolate, Handle<Object> callable, Handle<Object> object);
+
+  // ES6 section 12.10.4 Runtime Semantics: InstanceofOperator(O, C)
+  MUST_USE_RESULT static MaybeHandle<Object> InstanceOf(
+      Isolate* isolate, Handle<Object> object, Handle<Object> callable);
+
   MUST_USE_RESULT static MaybeHandle<Object> GetProperty(LookupIterator* it);
 
   // ES6 [[Set]] (when passed DONT_THROW)
@@ -1306,15 +1327,10 @@
   // undefined if not yet created.
   Object* GetHash();
 
-  // Returns undefined for JSObjects, but returns the hash code for simple
-  // objects.  This avoids a double lookup in the cases where we know we will
-  // add the hash to the JSObject if it does not already exist.
-  Object* GetSimpleHash();
-
   // Returns the permanent hash code associated with this object depending on
   // the actual object type. May create and store a hash code if needed and none
   // exists.
-  static Handle<Smi> GetOrCreateHash(Isolate* isolate, Handle<Object> object);
+  static Smi* GetOrCreateHash(Isolate* isolate, Handle<Object> object);
 
   // Checks whether this object has the same value as the given one.  This
   // function is implemented according to ES5, section 9.12 and can be used
@@ -1476,7 +1492,7 @@
   // True if this map word is a forwarding address for a scavenge
   // collection.  Only valid during a scavenge collection (specifically,
   // when all map words are heap object pointers, i.e. not during a full GC).
-  inline bool IsForwardingAddress();
+  inline bool IsForwardingAddress() const;
 
   // Create a map word from a forwarding address.
   static inline MapWord FromForwardingAddress(HeapObject* object);
@@ -1535,10 +1551,15 @@
   // Convenience method to get current isolate.
   inline Isolate* GetIsolate() const;
 
-#define IS_TYPE_FUNCTION_DECL(type_) INLINE(bool Is##type_() const);
+#define IS_TYPE_FUNCTION_DECL(Type) INLINE(bool Is##Type() const);
   HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
+#undef IS_TYPE_FUNCTION_DECL
+
+#define IS_TYPE_FUNCTION_DECL(Type, Value) \
+  INLINE(bool Is##Type(Isolate* isolate) const);
   ODDBALL_LIST(IS_TYPE_FUNCTION_DECL)
 #undef IS_TYPE_FUNCTION_DECL
+
 #define DECLARE_STRUCT_PREDICATE(NAME, Name, name) \
   INLINE(bool Is##Name() const);
   STRUCT_LIST(DECLARE_STRUCT_PREDICATE)
@@ -1783,10 +1804,13 @@
   ACCESSOR_SETTER
 };
 
+enum class GetKeysConversion { kKeepNumbers, kConvertToString };
 
-enum GetKeysConversion { KEEP_NUMBERS, CONVERT_TO_STRING };
-
-enum KeyCollectionType { OWN_ONLY, INCLUDE_PROTOS };
+enum class KeyCollectionMode {
+  kOwnOnly = static_cast<int>(v8::KeyCollectionMode::kOwnOnly),
+  kIncludePrototypes =
+      static_cast<int>(v8::KeyCollectionMode::kIncludePrototypes)
+};
 
 // JSReceiver includes types on which properties can be defined, i.e.,
 // JSObject and JSProxy.
@@ -1832,6 +1856,8 @@
 
   MUST_USE_RESULT static inline Maybe<bool> HasOwnProperty(
       Handle<JSReceiver> object, Handle<Name> name);
+  MUST_USE_RESULT static inline Maybe<bool> HasOwnProperty(
+      Handle<JSReceiver> object, uint32_t index);
 
   MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty(
       Isolate* isolate, Handle<JSReceiver> receiver, const char* key);
@@ -1912,16 +1938,9 @@
 
   MUST_USE_RESULT static Maybe<bool> IsExtensible(Handle<JSReceiver> object);
 
-  // Tests for the fast common case for property enumeration.
-  bool IsSimpleEnum();
-
   // Returns the class name ([[Class]] property in the specification).
   String* class_name();
 
-  // Returns the builtin string tag used in Object.prototype.toString.
-  MUST_USE_RESULT static MaybeHandle<String> BuiltinStringTag(
-      Handle<JSReceiver> object);
-
   // Returns the constructor name (the name (possibly, inferred name) of the
   // function that was used to instantiate the object).
   static Handle<String> GetConstructorName(Handle<JSReceiver> receiver);
@@ -1932,6 +1951,8 @@
       Handle<JSReceiver> object, Handle<Name> name);
   MUST_USE_RESULT static inline Maybe<PropertyAttributes>
   GetOwnPropertyAttributes(Handle<JSReceiver> object, Handle<Name> name);
+  MUST_USE_RESULT static inline Maybe<PropertyAttributes>
+  GetOwnPropertyAttributes(Handle<JSReceiver> object, uint32_t index);
 
   MUST_USE_RESULT static inline Maybe<PropertyAttributes> GetElementAttributes(
       Handle<JSReceiver> object, uint32_t index);
@@ -1954,26 +1975,17 @@
 
   // Retrieves a permanent object identity hash code. The undefined value might
   // be returned in case no hash was created yet.
-  static inline Handle<Object> GetIdentityHash(Isolate* isolate,
-                                               Handle<JSReceiver> object);
+  static inline Object* GetIdentityHash(Isolate* isolate,
+                                        Handle<JSReceiver> object);
 
   // Retrieves a permanent object identity hash code. May create and store a
   // hash code if needed and none exists.
-  inline static Handle<Smi> GetOrCreateIdentityHash(
-      Handle<JSReceiver> object);
+  inline static Smi* GetOrCreateIdentityHash(Isolate* isolate,
+                                             Handle<JSReceiver> object);
 
   // ES6 [[OwnPropertyKeys]] (modulo return type)
-  MUST_USE_RESULT static MaybeHandle<FixedArray> OwnPropertyKeys(
-      Handle<JSReceiver> object) {
-    return GetKeys(object, OWN_ONLY, ALL_PROPERTIES, CONVERT_TO_STRING);
-  }
-
-  // Computes the enumerable keys for a JSObject. Used for implementing
-  // "for (n in object) { }".
-  MUST_USE_RESULT static MaybeHandle<FixedArray> GetKeys(
-      Handle<JSReceiver> object, KeyCollectionType type, PropertyFilter filter,
-      GetKeysConversion keys_conversion = KEEP_NUMBERS,
-      bool filter_proxy_keys_ = true);
+  MUST_USE_RESULT static inline MaybeHandle<FixedArray> OwnPropertyKeys(
+      Handle<JSReceiver> object);
 
   MUST_USE_RESULT static MaybeHandle<FixedArray> GetOwnValues(
       Handle<JSReceiver> object, PropertyFilter filter);
@@ -2161,6 +2173,8 @@
   static void OptimizeAsPrototype(Handle<JSObject> object,
                                   PrototypeOptimizationMode mode);
   static void ReoptimizeIfPrototype(Handle<JSObject> object);
+  static void MakePrototypesFast(Handle<Object> receiver,
+                                 WhereToStart where_to_start, Isolate* isolate);
   static void LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate);
   static void UpdatePrototypeUserRegistration(Handle<Map> old_map,
                                               Handle<Map> new_map,
@@ -2184,13 +2198,6 @@
   MUST_USE_RESULT static Maybe<PropertyAttributes>
       GetPropertyAttributesWithFailedAccessCheck(LookupIterator* it);
 
-  // Retrieves an AccessorPair property from the given object. Might return
-  // undefined if the property doesn't exist or is of a different kind.
-  MUST_USE_RESULT static MaybeHandle<Object> GetAccessor(
-      Handle<JSObject> object,
-      Handle<Name> name,
-      AccessorComponent component);
-
   // Defines an AccessorPair property on the given object.
   // TODO(mstarzinger): Rename to SetAccessor().
   static MaybeHandle<Object> DefineAccessor(Handle<JSObject> object,
@@ -2214,30 +2221,6 @@
   MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithInterceptor(
       LookupIterator* it, bool* done);
 
-  // Accessors for hidden properties object.
-  //
-  // Hidden properties are not own properties of the object itself.  Instead
-  // they are stored in an auxiliary structure kept as an own property with a
-  // special name Heap::hidden_properties_symbol(). But if the receiver is a
-  // JSGlobalProxy then the auxiliary object is a property of its prototype, and
-  // if it's a detached proxy, then you can't have hidden properties.
-
-  // Sets a hidden property on this object. Returns this object if successful,
-  // undefined if called on a detached proxy.
-  static Handle<Object> SetHiddenProperty(Handle<JSObject> object,
-                                          Handle<Name> key,
-                                          Handle<Object> value);
-  // Gets the value of a hidden property with the given key. Returns the hole
-  // if the property doesn't exist (or if called on a detached proxy),
-  // otherwise returns the value set for the key.
-  Object* GetHiddenProperty(Handle<Name> key);
-  // Deletes a hidden property. Deleting a non-existing property is
-  // considered successful.
-  static void DeleteHiddenProperty(Handle<JSObject> object,
-                                   Handle<Name> key);
-  // Returns true if the object has a property with the hidden string as name.
-  static bool HasHiddenProperties(Handle<JSObject> object);
-
   static void ValidateElements(Handle<JSObject> object);
 
   // Makes sure that this object can contain HeapObject as elements.
@@ -2299,27 +2282,7 @@
   inline Object* GetInternalField(int index);
   inline void SetInternalField(int index, Object* value);
   inline void SetInternalField(int index, Smi* value);
-
-  void CollectOwnPropertyNames(KeyAccumulator* keys,
-                               PropertyFilter filter = ALL_PROPERTIES);
-
-  // Returns the number of properties on this object filtering out properties
-  // with the specified attributes (ignoring interceptors).
-  // TODO(jkummerow): Deprecated, only used by Object.observe.
-  int NumberOfOwnElements(PropertyFilter filter);
-  // Returns the number of elements on this object filtering out elements
-  // with the specified attributes (ignoring interceptors).
-  // TODO(jkummerow): Deprecated, only used by Object.observe.
-  int GetOwnElementKeys(FixedArray* storage, PropertyFilter filter);
-
-  static void CollectOwnElementKeys(Handle<JSObject> object,
-                                    KeyAccumulator* keys,
-                                    PropertyFilter filter);
-
-  static Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object);
-
-  static Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate,
-                                                    Handle<JSObject> object);
+  bool WasConstructedFromApiFunction();
 
   // Returns a new map with all transitions dropped from the object's current
   // map and the ElementsKind set.
@@ -2400,9 +2363,6 @@
 
   static bool IsExtensible(Handle<JSObject> object);
 
-  // Called the first time an object is observed with ES7 Object.observe.
-  static void SetObserved(Handle<JSObject> object);
-
   // Copy object.
   enum DeepCopyHints { kNoHints = 0, kObjectIsShallow = 1 };
 
@@ -2503,11 +2463,6 @@
 
   typedef FlexibleBodyDescriptor<JSReceiver::kPropertiesOffset> BodyDescriptor;
 
-  // Enqueue change record for Object.observe. May cause GC.
-  MUST_USE_RESULT static MaybeHandle<Object> EnqueueChangeRecord(
-      Handle<JSObject> object, const char* type, Handle<Name> name,
-      Handle<Object> old_value);
-
   // Gets the number of currently used elements.
   int GetFastElementsUsage();
 
@@ -2538,25 +2493,10 @@
                                     ElementsKind kind,
                                     Object* object);
 
-  // Return the hash table backing store or the inline stored identity hash,
-  // whatever is found.
-  MUST_USE_RESULT Object* GetHiddenPropertiesHashTable();
+  static Object* GetIdentityHash(Isolate* isolate, Handle<JSObject> object);
 
-  // Return the hash table backing store for hidden properties.  If there is no
-  // backing store, allocate one.
-  static Handle<ObjectHashTable> GetOrCreateHiddenPropertiesHashtable(
-      Handle<JSObject> object);
-
-  // Set the hidden property backing store to either a hash table or
-  // the inline-stored identity hash.
-  static Handle<Object> SetHiddenPropertiesHashTable(
-      Handle<JSObject> object,
-      Handle<Object> value);
-
-  static Handle<Object> GetIdentityHash(Isolate* isolate,
-                                        Handle<JSObject> object);
-
-  static Handle<Smi> GetOrCreateIdentityHash(Handle<JSObject> object);
+  static Smi* GetOrCreateIdentityHash(Isolate* isolate,
+                                      Handle<JSObject> object);
 
   // Helper for fast versions of preventExtensions, seal, and freeze.
   // attrs is one of NONE, SEALED, or FROZEN (depending on the operation).
@@ -2564,10 +2504,6 @@
   MUST_USE_RESULT static Maybe<bool> PreventExtensionsWithTransition(
       Handle<JSObject> object, ShouldThrow should_throw);
 
-  MUST_USE_RESULT static Maybe<bool> SetPrototypeUnobserved(
-      Handle<JSObject> object, Handle<Object> value, bool from_javascript,
-      ShouldThrow should_throw);
-
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject);
 };
 
@@ -3101,6 +3037,11 @@
     return kFirstIndex + (descriptor_number * kDescriptorSize) + kDescriptorKey;
   }
 
+  static int ToValueIndex(int descriptor_number) {
+    return kFirstIndex + (descriptor_number * kDescriptorSize) +
+           kDescriptorValue;
+  }
+
  private:
   // An entry in a DescriptorArray, represented as an (array, index) pair.
   class Entry {
@@ -3116,12 +3057,6 @@
     int index_;
   };
 
-  static int ToValueIndex(int descriptor_number) {
-    return kFirstIndex +
-           (descriptor_number * kDescriptorSize) +
-           kDescriptorValue;
-  }
-
   // Transfer a complete descriptor from the src descriptor array to this
   // descriptor array.
   void CopyFrom(int index, DescriptorArray* src);
@@ -3219,7 +3154,7 @@
   // Tells whether k is a real key.  The hole and undefined are not allowed
   // as keys and can be used to indicate missing or deleted elements.
   inline bool IsKey(Object* k);
-  inline bool IsKey(Heap* heap, Object* k);
+  inline bool IsKey(Isolate* isolate, Object* k);
 
   // Compute the probe offset (quadratic probing).
   INLINE(static uint32_t GetProbeOffset(uint32_t n)) {
@@ -3261,6 +3196,8 @@
 template <typename Derived, typename Shape, typename Key>
 class HashTable : public HashTableBase {
  public:
+  typedef Shape ShapeT;
+
   // Wrapper methods
   inline uint32_t Hash(Key key) {
     if (Shape::UsesSeed) {
@@ -3299,10 +3236,12 @@
   void Rehash(Key key);
 
   // Returns the key at entry.
-  Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
+  Object* KeyAt(int entry) { return get(EntryToIndex(entry) + kEntryKeyIndex); }
 
   static const int kElementsStartIndex = kPrefixStartIndex + Shape::kPrefixSize;
   static const int kEntrySize = Shape::kEntrySize;
+  STATIC_ASSERT(kEntrySize > 0);
+  static const int kEntryKeyIndex = 0;
   static const int kElementsStartOffset =
       kHeaderSize + kElementsStartIndex * kPointerSize;
   static const int kCapacityOffset =
@@ -3331,7 +3270,7 @@
       PretenureFlag pretenure = NOT_TENURED);
 
   // Returns true if this table has sufficient capacity for adding n elements.
-  bool HasSufficientCapacity(int n);
+  bool HasSufficientCapacityToAdd(int number_of_additional_elements);
 
   // Sets the capacity of the hash table.
   void SetCapacity(int capacity) {
@@ -3507,22 +3446,15 @@
 
   // Returns the number of elements in the dictionary filtering out properties
   // with the specified attributes.
-  // TODO(jkummerow): Deprecated, only used by Object.observe.
   int NumberOfElementsFilterAttributes(PropertyFilter filter);
 
   // Returns the number of enumerable elements in the dictionary.
-  // TODO(jkummerow): Deprecated, only used by Object.observe.
   int NumberOfEnumElements() {
     return NumberOfElementsFilterAttributes(ENUMERABLE_STRINGS);
   }
 
   enum SortMode { UNSORTED, SORTED };
 
-  // Fill in details for properties into storage.
-  // Returns the number of properties added.
-  // TODO(jkummerow): Deprecated, only used by Object.observe.
-  int CopyKeysTo(FixedArray* storage, int index, PropertyFilter filter,
-                 SortMode sort_mode);
   // Collect the keys into the given KeyAccumulator, in ascending chronological
   // order of property creation.
   static void CollectKeysTo(Handle<Dictionary<Derived, Shape, Key> > dictionary,
@@ -3554,6 +3486,9 @@
   static Handle<Derived> EnsureCapacity(Handle<Derived> obj, int n, Key key);
 
 #ifdef OBJECT_PRINT
+  // For our gdb macros, we should perhaps change these in the future.
+  void Print();
+
   void Print(std::ostream& os);  // NOLINT
 #endif
   // Returns the key (slow).
@@ -3621,15 +3556,16 @@
   static inline PropertyDetails DetailsAt(Dictionary* dict, int entry) {
     STATIC_ASSERT(Dictionary::kEntrySize == 3);
     DCHECK(entry >= 0);  // Not found is -1, which is not caught by get().
-    return PropertyDetails(
-        Smi::cast(dict->get(Dictionary::EntryToIndex(entry) + 2)));
+    return PropertyDetails(Smi::cast(dict->get(
+        Dictionary::EntryToIndex(entry) + Dictionary::kEntryDetailsIndex)));
   }
 
   template <typename Dictionary>
   static inline void DetailsAtPut(Dictionary* dict, int entry,
                                   PropertyDetails value) {
     STATIC_ASSERT(Dictionary::kEntrySize == 3);
-    dict->set(Dictionary::EntryToIndex(entry) + 2, value.AsSmi());
+    dict->set(Dictionary::EntryToIndex(entry) + Dictionary::kEntryDetailsIndex,
+              value.AsSmi());
   }
 
   template <typename Dictionary>
@@ -3651,6 +3587,8 @@
   static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Name> key);
   static const int kPrefixSize = 2;
   static const int kEntrySize = 3;
+  static const int kEntryValueIndex = 1;
+  static const int kEntryDetailsIndex = 2;
   static const bool kIsEnumerable = true;
 };
 
@@ -3665,6 +3603,9 @@
 
   inline static Handle<FixedArray> DoGenerateNewEnumerationIndices(
       Handle<NameDictionary> dictionary);
+
+  static const int kEntryValueIndex = 1;
+  static const int kEntryDetailsIndex = 2;
 };
 
 
@@ -3692,6 +3633,8 @@
     : public NameDictionaryBase<GlobalDictionary, GlobalDictionaryShape> {
  public:
   DECLARE_CAST(GlobalDictionary)
+
+  static const int kEntryValueIndex = 1;
 };
 
 
@@ -3765,6 +3708,9 @@
   // requires_slow_elements returns false.
   inline uint32_t max_number_key();
 
+  static const int kEntryValueIndex = 1;
+  static const int kEntryDetailsIndex = 2;
+
   // Bit masks.
   static const int kRequiresSlowElementsMask = 1;
   static const int kRequiresSlowElementsTagSize = 1;
@@ -3795,6 +3741,9 @@
       Handle<UnseededNumberDictionary> dictionary,
       uint32_t key,
       Handle<Object> value);
+
+  static const int kEntryValueIndex = 1;
+  static const int kEntryDetailsIndex = 2;
 };
 
 
@@ -3911,7 +3860,7 @@
   static Handle<Derived> Shrink(Handle<Derived> table);
 
   // Returns a new empty OrderedHashTable and records the clearing so that
-  // exisiting iterators can be updated.
+  // existing iterators can be updated.
   static Handle<Derived> Clear(Handle<Derived> table);
 
   // Returns a true if the OrderedHashTable contains the key
@@ -3925,6 +3874,8 @@
     return Smi::cast(get(kNumberOfDeletedElementsIndex))->value();
   }
 
+  // Returns the number of contiguous entries in the data table, starting at 0,
+  // that either are real entries or have been deleted.
   int UsedCapacity() { return NumberOfElements() + NumberOfDeletedElements(); }
 
   int NumberOfBuckets() {
@@ -3944,10 +3895,10 @@
     return Smi::cast(entry)->value();
   }
 
-  int KeyToFirstEntry(Object* key) {
+  int KeyToFirstEntry(Isolate* isolate, Object* key) {
     Object* hash = key->GetHash();
     // If the object does not have an identity hash, it was never used as a key
-    if (hash->IsUndefined()) return kNotFound;
+    if (hash->IsUndefined(isolate)) return kNotFound;
     return HashToEntry(Smi::cast(hash)->value());
   }
 
@@ -3956,7 +3907,11 @@
     return Smi::cast(next_entry)->value();
   }
 
-  Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
+  // use KeyAt(i)->IsTheHole(isolate) to determine if this is a deleted entry.
+  Object* KeyAt(int entry) {
+    DCHECK_LT(entry, this->UsedCapacity());
+    return get(EntryToIndex(entry));
+  }
 
   bool IsObsolete() {
     return !get(kNextTableIndex)->IsSmi();
@@ -4017,6 +3972,7 @@
     set(kNumberOfDeletedElementsIndex, Smi::FromInt(num));
   }
 
+  // Returns the number elements that can fit into the allocated buffer.
   int Capacity() {
     return NumberOfBuckets() * kLoadFactor;
   }
@@ -4047,6 +4003,8 @@
 
   static Handle<OrderedHashSet> Add(Handle<OrderedHashSet> table,
                                     Handle<Object> value);
+  static Handle<FixedArray> ConvertToKeysArray(Handle<OrderedHashSet> table,
+                                               GetKeysConversion convert);
 };
 
 
@@ -4212,7 +4170,7 @@
 
   // Return true if this local was introduced by the compiler, and should not be
   // exposed to the user in a debugger.
-  bool LocalIsSynthetic(int var);
+  static bool VariableIsSynthetic(String* name);
 
   // Lookup support for serialized scope info. Returns the
   // the stack slot index for a given slot name if the slot is
@@ -4374,7 +4332,7 @@
   class HasSimpleParametersField
       : public BitField<bool, AsmFunctionField::kNext, 1> {};
   class FunctionKindField
-      : public BitField<FunctionKind, HasSimpleParametersField::kNext, 8> {};
+      : public BitField<FunctionKind, HasSimpleParametersField::kNext, 9> {};
 
   // BitFields representing the encoded information for context locals in the
   // ContextLocalInfoEntries part.
@@ -4426,8 +4384,13 @@
   inline byte get(int index);
   inline void set(int index, byte value);
 
+  // Copy in / copy out whole byte slices.
+  inline void copy_out(int index, byte* buffer, int length);
+  inline void copy_in(int index, const byte* buffer, int length);
+
   // Treat contents as an int array.
   inline int get_int(int index);
+  inline void set_int(int index, int value);
 
   static int SizeFor(int length) {
     return OBJECT_POINTER_ALIGN(kHeaderSize + length);
@@ -4514,6 +4477,10 @@
 
   inline int instruction_size();
 
+  // Returns the size of bytecode and its metadata. This includes the size of
+  // bytecode, constant pool, source position table, and handler table.
+  inline int SizeIncludingMetadata();
+
   int SourcePosition(int offset);
   int SourceStatementPosition(int offset);
 
@@ -4801,17 +4768,18 @@
  public:
   static const int kVectorIndex = 0;
   static const int kFirstLiteralIndex = 1;
-  static const int kOffsetToFirstLiteral =
-      FixedArray::kHeaderSize + kPointerSize;
+  static const int kFeedbackVectorOffset;
+  static const int kOffsetToFirstLiteral;
 
   static int OffsetOfLiteralAt(int index) {
-    return SizeFor(index + kFirstLiteralIndex);
+    return OffsetOfElementAt(index + kFirstLiteralIndex);
   }
 
   inline TypeFeedbackVector* feedback_vector() const;
   inline void set_feedback_vector(TypeFeedbackVector* vector);
   inline Object* literal(int literal_index) const;
   inline void set_literal(int literal_index, Object* literal);
+  inline void set_literal_undefined(int literal_index);
   inline int literals_count() const;
 
   static Handle<LiteralsArray> New(Isolate* isolate,
@@ -4924,6 +4892,7 @@
 
 #define IC_KIND_LIST(V) \
   V(LOAD_IC)            \
+  V(LOAD_GLOBAL_IC)     \
   V(KEYED_LOAD_IC)      \
   V(CALL_IC)            \
   V(STORE_IC)           \
@@ -4943,24 +4912,13 @@
     NUMBER_OF_KINDS
   };
 
-  // No more than 32 kinds. The value is currently encoded in five bits in
-  // Flags.
-  STATIC_ASSERT(NUMBER_OF_KINDS <= 32);
-
   static const char* Kind2String(Kind kind);
 
-  // Types of stubs.
-  enum StubType {
-    NORMAL,
-    FAST
-  };
-
   static const int kPrologueOffsetNotSet = -1;
 
 #ifdef ENABLE_DISASSEMBLER
   // Printing
   static const char* ICState2String(InlineCacheState state);
-  static const char* StubType2String(StubType type);
   static void PrintExtraICState(std::ostream& os,  // NOLINT
                                 Kind kind, ExtraICState extra);
   void Disassemble(const char* name, std::ostream& os);  // NOLINT
@@ -5027,37 +4985,26 @@
 
   // [flags]: Access to specific code flags.
   inline Kind kind();
-  inline InlineCacheState ic_state();  // Only valid for IC stubs.
   inline ExtraICState extra_ic_state();  // Only valid for IC stubs.
 
-  inline StubType type();  // Only valid for monomorphic IC stubs.
-
   // Testers for IC stub kinds.
   inline bool is_inline_cache_stub();
   inline bool is_debug_stub();
   inline bool is_handler();
-  inline bool is_load_stub();
-  inline bool is_keyed_load_stub();
-  inline bool is_store_stub();
-  inline bool is_keyed_store_stub();
   inline bool is_call_stub();
   inline bool is_binary_op_stub();
   inline bool is_compare_ic_stub();
   inline bool is_to_boolean_ic_stub();
-  inline bool is_keyed_stub();
   inline bool is_optimized_code();
   inline bool is_wasm_code();
-  inline bool embeds_maps_weakly();
 
   inline bool IsCodeStubOrIC();
-  inline bool IsJavaScriptCode();
 
   inline void set_raw_kind_specific_flags1(int value);
   inline void set_raw_kind_specific_flags2(int value);
 
   // Testers for interpreter builtins.
-  inline bool is_interpreter_entry_trampoline();
-  inline bool is_interpreter_enter_bytecode_dispatch();
+  inline bool is_interpreter_trampoline_builtin();
 
   // [is_crankshafted]: For kind STUB or ICs, tells whether or not a code
   // object was generated by either the hydrogen or the TurboFan optimizing
@@ -5151,20 +5098,6 @@
 
   // Find the first map in an IC stub.
   Map* FindFirstMap();
-  void FindAllMaps(MapHandleList* maps);
-
-  // Find the first handler in an IC stub.
-  Code* FindFirstHandler();
-
-  // Find |length| handlers and put them into |code_list|. Returns false if not
-  // enough handlers can be found.
-  bool FindHandlers(CodeHandleList* code_list, int length = -1);
-
-  // Find the handler for |map|.
-  MaybeHandle<Code> FindHandlerForMap(Map* map);
-
-  // Find the first name in an IC stub.
-  Name* FindFirstName();
 
   class FindAndReplacePattern;
   // For each (map-to-find, object-to-replace) pair in the pattern, this
@@ -5186,26 +5119,17 @@
 
   // Flags operations.
   static inline Flags ComputeFlags(
-      Kind kind, InlineCacheState ic_state = UNINITIALIZED,
-      ExtraICState extra_ic_state = kNoExtraICState, StubType type = NORMAL,
-      CacheHolderFlag holder = kCacheOnReceiver);
-
-  static inline Flags ComputeMonomorphicFlags(
       Kind kind, ExtraICState extra_ic_state = kNoExtraICState,
-      CacheHolderFlag holder = kCacheOnReceiver, StubType type = NORMAL);
+      CacheHolderFlag holder = kCacheOnReceiver);
 
   static inline Flags ComputeHandlerFlags(
-      Kind handler_kind, StubType type = NORMAL,
-      CacheHolderFlag holder = kCacheOnReceiver);
+      Kind handler_kind, CacheHolderFlag holder = kCacheOnReceiver);
 
-  static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
-  static inline StubType ExtractTypeFromFlags(Flags flags);
   static inline CacheHolderFlag ExtractCacheHolderFromFlags(Flags flags);
   static inline Kind ExtractKindFromFlags(Flags flags);
   static inline ExtraICState ExtractExtraICStateFromFlags(Flags flags);
 
-  static inline Flags RemoveTypeFromFlags(Flags flags);
-  static inline Flags RemoveTypeAndHolderFromFlags(Flags flags);
+  static inline Flags RemoveHolderFromFlags(Flags flags);
 
   // Convert a target address into a code object.
   static inline Code* GetCodeFromTargetAddress(Address address);
@@ -5219,12 +5143,60 @@
   // Returns the address right after the last instruction.
   inline byte* instruction_end();
 
-  // Returns the size of the instructions, padding, and relocation information.
+  // Returns the size of the instructions, padding, relocation and unwinding
+  // information.
   inline int body_size();
 
+  // Returns the size of code and its metadata. This includes the size of code
+  // relocation information, deoptimization data and handler table.
+  inline int SizeIncludingMetadata();
+
   // Returns the address of the first relocation info (read backwards!).
   inline byte* relocation_start();
 
+  // [has_unwinding_info]: Whether this code object has unwinding information.
+  // If it doesn't, unwinding_information_start() will point to invalid data.
+  //
+  // The body of all code objects has the following layout.
+  //
+  //  +--------------------------+  <-- instruction_start()
+  //  |       instructions       |
+  //  |           ...            |
+  //  +--------------------------+
+  //  |      relocation info     |
+  //  |           ...            |
+  //  +--------------------------+  <-- instruction_end()
+  //
+  // If has_unwinding_info() is false, instruction_end() points to the first
+  // memory location after the end of the code object. Otherwise, the body
+  // continues as follows:
+  //
+  //  +--------------------------+
+  //  |    padding to the next   |
+  //  |  8-byte aligned address  |
+  //  +--------------------------+  <-- instruction_end()
+  //  |   [unwinding_info_size]  |
+  //  |        as uint64_t       |
+  //  +--------------------------+  <-- unwinding_info_start()
+  //  |       unwinding info     |
+  //  |            ...           |
+  //  +--------------------------+  <-- unwinding_info_end()
+  //
+  // and unwinding_info_end() points to the first memory location after the end
+  // of the code object.
+  //
+  DECL_BOOLEAN_ACCESSORS(has_unwinding_info)
+
+  // [unwinding_info_size]: Size of the unwinding information.
+  inline int unwinding_info_size() const;
+  inline void set_unwinding_info_size(int value);
+
+  // Returns the address of the unwinding information, if any.
+  inline byte* unwinding_info_start();
+
+  // Returns the address right after the end of the unwinding information.
+  inline byte* unwinding_info_end();
+
   // Code entry point.
   inline byte* entry();
 
@@ -5261,7 +5233,6 @@
   DECLARE_VERIFIER(Code)
 
   void ClearInlineCaches();
-  void ClearInlineCaches(Kind kind);
 
   BailoutId TranslatePcOffsetToAstId(uint32_t pc_offset);
   uint32_t TranslateAstIdToPcOffset(BailoutId ast_id);
@@ -5356,6 +5327,8 @@
   static const int kHeaderSize =
       (kHeaderPaddingStart + kCodeAlignmentMask) & ~kCodeAlignmentMask;
 
+  inline int GetUnwindingInfoSizeOffset() const;
+
   class BodyDescriptor;
 
   // Byte offsets within kKindSpecificFlags1Offset.
@@ -5369,13 +5342,16 @@
   class ProfilerTicksField : public BitField<int, 4, 28> {};
 
   // Flags layout.  BitField<type, shift, size>.
-  class ICStateField : public BitField<InlineCacheState, 0, 3> {};
-  class TypeField : public BitField<StubType, 3, 1> {};
-  class CacheHolderField : public BitField<CacheHolderFlag, 4, 2> {};
-  class KindField : public BitField<Kind, 6, 5> {};
-  class ExtraICStateField
-      : public BitField<ExtraICState, 11, PlatformSmiTagging::kSmiValueSize -
-                                              11 + 1> {};  // NOLINT
+  class ICStateField : public BitField<InlineCacheState, 0, 2> {};
+  class HasUnwindingInfoField : public BitField<bool, ICStateField::kNext, 1> {
+  };
+  class CacheHolderField
+      : public BitField<CacheHolderFlag, HasUnwindingInfoField::kNext, 2> {};
+  class KindField : public BitField<Kind, CacheHolderField::kNext, 5> {};
+  STATIC_ASSERT(NUMBER_OF_KINDS <= KindField::kMax);
+  class ExtraICStateField : public BitField<ExtraICState, KindField::kNext,
+                                            PlatformSmiTagging::kSmiValueSize -
+                                                KindField::kNext + 1> {};
 
   // KindSpecificFlags1 layout (STUB, BUILTIN and OPTIMIZED_FUNCTION)
   static const int kStackSlotsFirstBit = 0;
@@ -5425,15 +5401,12 @@
   static const int kMaxArguments = (1 << kArgumentsBits) - 1;
 
   // This constant should be encodable in an ARM instruction.
-  static const int kFlagsNotUsedInLookup =
-      TypeField::kMask | CacheHolderField::kMask;
+  static const int kFlagsNotUsedInLookup = CacheHolderField::kMask;
 
  private:
   friend class RelocIterator;
   friend class Deoptimizer;  // For FindCodeAgeSequence.
 
-  void ClearInlineCaches(Kind* kind);
-
   // Code aging
   byte* FindCodeAgeSequence();
   static void GetCodeAgeAndParity(Code* code, Age* age,
@@ -5458,8 +5431,11 @@
     CODE_KIND_LIST(DEFINE_CODE_KIND_ENUM)
 #undef DEFINE_CODE_KIND_ENUM
         INTERPRETED_FUNCTION,
+    NUMBER_OF_KINDS
   };
 
+  static const char* Kind2String(Kind kind);
+
   int SourcePosition(int offset);
   int SourceStatementPosition(int offset);
 
@@ -5469,9 +5445,12 @@
   // Returns the address right after the last instruction.
   inline Address instruction_end();
 
-  // Returns the of the code instructions.
+  // Returns the size of the code instructions.
   inline int instruction_size();
 
+  // Returns the size of instructions and the metadata.
+  inline int SizeIncludingMetadata();
+
   // Returns true if pc is inside this object's instructions.
   inline bool contains(byte* pc);
 
@@ -5775,10 +5754,6 @@
   inline void set_is_undetectable();
   inline bool is_undetectable();
 
-  // Tells whether the instance has a call-as-function handler.
-  inline void set_is_observed();
-  inline bool is_observed();
-
   // Tells whether the instance has a [[Call]] internal method.
   // This property is implemented according to ES6, section 7.2.3.
   inline void set_is_callable();
@@ -5803,6 +5778,7 @@
   inline bool has_fast_double_elements();
   inline bool has_fast_elements();
   inline bool has_sloppy_arguments_elements();
+  inline bool has_fast_sloppy_arguments_elements();
   inline bool has_fast_string_wrapper_elements();
   inline bool has_fixed_typed_array_elements();
   inline bool has_dictionary_elements();
@@ -5831,6 +5807,9 @@
       Handle<JSObject> prototype, Isolate* isolate);
   static Handle<PrototypeInfo> GetOrCreatePrototypeInfo(
       Handle<Map> prototype_map, Isolate* isolate);
+  inline bool should_be_fast_prototype_map() const;
+  static void SetShouldBeFastPrototypeMap(Handle<Map> map, bool value,
+                                          Isolate* isolate);
 
   // [prototype chain validity cell]: Associated with a prototype object,
   // stored in that object's map's PrototypeInfo, indicates that prototype
@@ -5849,6 +5828,7 @@
   int NumberOfFields();
 
   // TODO(ishell): candidate with JSObject::MigrateToMap().
+  bool InstancesNeedRewriting(Map* target);
   bool InstancesNeedRewriting(Map* target, int target_number_of_fields,
                               int target_inobject, int target_unused,
                               int* old_number_of_fields);
@@ -5860,15 +5840,14 @@
   static void GeneralizeFieldType(Handle<Map> map, int modify_index,
                                   Representation new_representation,
                                   Handle<FieldType> new_field_type);
-  static Handle<Map> ReconfigureProperty(Handle<Map> map, int modify_index,
-                                         PropertyKind new_kind,
-                                         PropertyAttributes new_attributes,
-                                         Representation new_representation,
-                                         Handle<FieldType> new_field_type,
-                                         StoreMode store_mode);
-  static Handle<Map> CopyGeneralizeAllRepresentations(
-      Handle<Map> map, int modify_index, StoreMode store_mode,
-      PropertyKind kind, PropertyAttributes attributes, const char* reason);
+
+  static inline Handle<Map> ReconfigureProperty(
+      Handle<Map> map, int modify_index, PropertyKind new_kind,
+      PropertyAttributes new_attributes, Representation new_representation,
+      Handle<FieldType> new_field_type, StoreMode store_mode);
+
+  static inline Handle<Map> ReconfigureElementsKind(
+      Handle<Map> map, ElementsKind new_elements_kind);
 
   static Handle<Map> PrepareForDataProperty(Handle<Map> old_map,
                                             int descriptor_number,
@@ -5933,7 +5912,7 @@
                                     LayoutDescriptor* layout_descriptor);
 
   // [stub cache]: contains stubs compiled for this map.
-  DECL_ACCESSORS(code_cache, Object)
+  DECL_ACCESSORS(code_cache, FixedArray)
 
   // [dependent code]: list of optimized codes that weakly embed this map.
   DECL_ACCESSORS(dependent_code, DependentCode)
@@ -6017,8 +5996,6 @@
                                     FunctionKind kind);
 
 
-  static Handle<Map> CopyForObserved(Handle<Map> map);
-
   static Handle<Map> CopyForPreventExtensions(Handle<Map> map,
                                               PropertyAttributes attrs_to_add,
                                               Handle<Symbol> transition_marker,
@@ -6037,8 +6014,8 @@
                                               PropertyAttributes attributes,
                                               StoreFromKeyed store_mode);
   static Handle<Map> TransitionToAccessorProperty(
-      Handle<Map> map, Handle<Name> name, int descriptor,
-      AccessorComponent component, Handle<Object> accessor,
+      Isolate* isolate, Handle<Map> map, Handle<Name> name, int descriptor,
+      Handle<Object> getter, Handle<Object> setter,
       PropertyAttributes attributes);
   static Handle<Map> ReconfigureExistingProperty(Handle<Map> map,
                                                  int descriptor,
@@ -6086,30 +6063,15 @@
 
   static void EnsureDescriptorSlack(Handle<Map> map, int slack);
 
-  // Returns the found code or undefined if absent.
-  Object* FindInCodeCache(Name* name, Code::Flags flags);
-
-  // Returns the non-negative index of the code object if it is in the
-  // cache and -1 otherwise.
-  int IndexInCodeCache(Object* name, Code* code);
-
-  // Removes a code object from the code cache at the given index.
-  void RemoveFromCodeCache(Name* name, Code* code, int index);
+  Code* LookupInCodeCache(Name* name, Code::Flags code);
 
   // Computes a hash value for this map, to be used in HashTables and such.
   int Hash();
 
-  // Returns the map that this map transitions to if its elements_kind
-  // is changed to |elements_kind|, or NULL if no such map is cached yet.
-  // |safe_to_add_transitions| is set to false if adding transitions is not
-  // allowed.
-  Map* LookupElementsTransitionMap(ElementsKind elements_kind);
-
   // Returns the transitioned map for this map with the most generic
-  // elements_kind that's found in |candidates|, or null handle if no match is
+  // elements_kind that's found in |candidates|, or |nullptr| if no match is
   // found at all.
-  static Handle<Map> FindTransitionedMap(Handle<Map> map,
-                                         MapHandleList* candidates);
+  Map* FindElementsKindTransitionedMap(MapHandleList* candidates);
 
   inline bool CanTransition();
 
@@ -6222,9 +6184,9 @@
   static const int kHasNamedInterceptor = 2;
   static const int kHasIndexedInterceptor = 3;
   static const int kIsUndetectable = 4;
-  static const int kIsObserved = 5;
-  static const int kIsAccessCheckNeeded = 6;
-  static const int kIsConstructor = 7;
+  static const int kIsAccessCheckNeeded = 5;
+  static const int kIsConstructor = 6;
+  // Bit 7 is free.
 
   // Bit positions for bit field 2
   static const int kIsExtensible = 0;
@@ -6268,6 +6230,17 @@
       Handle<LayoutDescriptor> full_layout_descriptor);
 
  private:
+  // Returns the map that this (root) map transitions to if its elements_kind
+  // is changed to |elements_kind|, or |nullptr| if no such map is cached yet.
+  Map* LookupElementsTransitionMap(ElementsKind elements_kind);
+
+  // Tries to replay property transitions starting from this (root) map using
+  // the descriptor array of the |map|. The |root_map| is expected to have
+  // proper elements kind and therefore elements kinds transitions are not
+  // taken by this function. Returns |nullptr| if matching transition map is
+  // not found.
+  Map* TryReplayPropertyTransitions(Map* map);
+
   static void ConnectTransition(Handle<Map> parent, Handle<Map> child,
                                 Handle<Name> name, SimpleTransitionFlag flag);
 
@@ -6304,6 +6277,19 @@
   static Handle<Map> CopyNormalized(Handle<Map> map,
                                     PropertyNormalizationMode mode);
 
+  static Handle<Map> Reconfigure(Handle<Map> map,
+                                 ElementsKind new_elements_kind,
+                                 int modify_index, PropertyKind new_kind,
+                                 PropertyAttributes new_attributes,
+                                 Representation new_representation,
+                                 Handle<FieldType> new_field_type,
+                                 StoreMode store_mode);
+
+  static Handle<Map> CopyGeneralizeAllRepresentations(
+      Handle<Map> map, ElementsKind elements_kind, int modify_index,
+      StoreMode store_mode, PropertyKind kind, PropertyAttributes attributes,
+      const char* reason);
+
   // Fires when the layout of an object with a leaf map changes.
   // This includes adding transitions to the leaf map or changing
   // the descriptor array.
@@ -6380,6 +6366,13 @@
   // [prototype_users]: WeakFixedArray containing maps using this prototype,
   // or Smi(0) if uninitialized.
   DECL_ACCESSORS(prototype_users, Object)
+
+  // [object_create_map]: A field caching the map for Object.create(prototype).
+  static inline void SetObjectCreateMap(Handle<PrototypeInfo> info,
+                                        Handle<Map> map);
+  inline Map* ObjectCreateMap();
+  inline bool HasObjectCreateMap();
+
   // [registry_slot]: Slot in prototype's user registry where this user
   // is stored. Returns UNREGISTERED if this prototype has not been registered.
   inline int registry_slot() const;
@@ -6391,6 +6384,11 @@
   // given receiver embed the currently valid cell for that receiver's prototype
   // during their compilation and check it on execution.
   DECL_ACCESSORS(validity_cell, Object)
+  // [bit_field]
+  inline int bit_field() const;
+  inline void set_bit_field(int bit_field);
+
+  DECL_BOOLEAN_ACCESSORS(should_be_fast_map)
 
   DECLARE_CAST(PrototypeInfo)
 
@@ -6401,10 +6399,16 @@
   static const int kPrototypeUsersOffset = HeapObject::kHeaderSize;
   static const int kRegistrySlotOffset = kPrototypeUsersOffset + kPointerSize;
   static const int kValidityCellOffset = kRegistrySlotOffset + kPointerSize;
-  static const int kConstructorNameOffset = kValidityCellOffset + kPointerSize;
-  static const int kSize = kConstructorNameOffset + kPointerSize;
+  static const int kObjectCreateMap = kValidityCellOffset + kPointerSize;
+  static const int kBitFieldOffset = kObjectCreateMap + kPointerSize;
+  static const int kSize = kBitFieldOffset + kPointerSize;
+
+  // Bit field usage.
+  static const int kShouldBeFastBit = 0;
 
  private:
+  DECL_ACCESSORS(object_create_map, Object)
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(PrototypeInfo);
 };
 
@@ -6489,9 +6493,10 @@
   // function from which eval was called.
   DECL_ACCESSORS(eval_from_shared, Object)
 
-  // [eval_from_instructions_offset]: the instruction offset in the code for the
-  // function from which eval was called where eval was called.
-  DECL_INT_ACCESSORS(eval_from_instructions_offset)
+  // [eval_from_position]: the source position in the code for the function
+  // from which eval was called, as positive integer. Or the code offset in the
+  // code from which eval was called, as negative integer.
+  DECL_INT_ACCESSORS(eval_from_position)
 
   // [shared_function_infos]: weak fixed array containing all shared
   // function infos created from this script.
@@ -6533,6 +6538,18 @@
   // resource is accessible. Otherwise, always return true.
   inline bool HasValidSource();
 
+  static Handle<Object> GetNameOrSourceURL(Handle<Script> script);
+
+  // Set eval origin for stack trace formatting.
+  static void SetEvalOrigin(Handle<Script> script,
+                            Handle<SharedFunctionInfo> outer,
+                            int eval_position);
+  // Retrieve source position from where eval was called.
+  int GetEvalPosition();
+
+  // Init line_ends array with source code positions of line ends.
+  static void InitLineEnds(Handle<Script> script);
+
   // Convert code offset into column number.
   static int GetColumnNumber(Handle<Script> script, int code_offset);
 
@@ -6541,10 +6558,24 @@
   static int GetLineNumber(Handle<Script> script, int code_offset);
   int GetLineNumber(int code_pos);
 
-  static Handle<Object> GetNameOrSourceURL(Handle<Script> script);
+  // Carries information about a source position.
+  struct PositionInfo {
+    PositionInfo() : line(-1), column(-1), line_start(-1), line_end(-1) {}
 
-  // Init line_ends array with source code positions of line ends.
-  static void InitLineEnds(Handle<Script> script);
+    int line;        // Zero-based line number.
+    int column;      // Zero-based column number.
+    int line_start;  // Position of first character in line.
+    int line_end;    // Position of last (non-linebreak) character in line.
+  };
+
+  // Specifies whether to add offsets to position infos.
+  enum OffsetFlag { NO_OFFSET = 0, WITH_OFFSET = 1 };
+
+  // Retrieves information about the given position, optionally with an offset.
+  // Returns false on failure, and otherwise writes into the given info object
+  // on success.
+  bool GetPositionInfo(int position, PositionInfo* info,
+                       OffsetFlag offset_flag);
 
   // Get the JS object wrapping the given script; create it if none exists.
   static Handle<JSObject> GetWrapper(Handle<Script> script);
@@ -6578,10 +6609,10 @@
   static const int kLineEndsOffset = kTypeOffset + kPointerSize;
   static const int kIdOffset = kLineEndsOffset + kPointerSize;
   static const int kEvalFromSharedOffset = kIdOffset + kPointerSize;
-  static const int kEvalFrominstructionsOffsetOffset =
+  static const int kEvalFromPositionOffset =
       kEvalFromSharedOffset + kPointerSize;
   static const int kSharedFunctionInfosOffset =
-      kEvalFrominstructionsOffsetOffset + kPointerSize;
+      kEvalFromPositionOffset + kPointerSize;
   static const int kFlagsOffset = kSharedFunctionInfosOffset + kPointerSize;
   static const int kSourceUrlOffset = kFlagsOffset + kPointerSize;
   static const int kSourceMappingUrlOffset = kSourceUrlOffset + kPointerSize;
@@ -6633,7 +6664,12 @@
   V(Math, ceil, MathCeil)                                   \
   V(Math, abs, MathAbs)                                     \
   V(Math, log, MathLog)                                     \
+  V(Math, log1p, MathLog1p)                                 \
+  V(Math, log2, MathLog2)                                   \
+  V(Math, log10, MathLog10)                                 \
+  V(Math, cbrt, MathCbrt)                                   \
   V(Math, exp, MathExp)                                     \
+  V(Math, expm1, MathExpm1)                                 \
   V(Math, sqrt, MathSqrt)                                   \
   V(Math, pow, MathPow)                                     \
   V(Math, max, MathMax)                                     \
@@ -6645,6 +6681,7 @@
   V(Math, asin, MathAsin)                                   \
   V(Math, atan, MathAtan)                                   \
   V(Math, atan2, MathAtan2)                                 \
+  V(Math, atanh, MathAtanh)                                 \
   V(Math, imul, MathImul)                                   \
   V(Math, clz32, MathClz32)                                 \
   V(Math, fround, MathFround)                               \
@@ -6656,9 +6693,6 @@
 
 enum BuiltinFunctionId {
   kArrayCode,
-  kGeneratorObjectNext,
-  kGeneratorObjectReturn,
-  kGeneratorObjectThrow,
 #define DECLARE_FUNCTION_ID(ignored1, ignore2, name)    \
   k##name,
   FUNCTIONS_WITH_ID_LIST(DECLARE_FUNCTION_ID)
@@ -6666,7 +6700,14 @@
 #undef DECLARE_FUNCTION_ID
   // Fake id for a special case of Math.pow. Note, it continues the
   // list of math functions.
-  kMathPowHalf
+  kMathPowHalf,
+  // These are manually assigned to special getters during bootstrapping.
+  kDataViewBuffer,
+  kDataViewByteLength,
+  kDataViewByteOffset,
+  kTypedArrayByteLength,
+  kTypedArrayByteOffset,
+  kTypedArrayLength,
 };
 
 
@@ -6708,6 +6749,9 @@
   // Clear optimized code map.
   void ClearOptimizedCodeMap();
 
+  // Like ClearOptimizedCodeMap, but preserves literals.
+  void ClearCodeFromOptimizedCodeMap();
+
   // We have a special root FixedArray with the right shape and values
   // to represent the cleared optimized code map. This predicate checks
   // if that root is installed.
@@ -6721,6 +6765,9 @@
   // Trims the optimized code map after entries have been removed.
   void TrimOptimizedCodeMap(int shrink_by);
 
+  static Handle<LiteralsArray> FindOrCreateLiterals(
+      Handle<SharedFunctionInfo> shared, Handle<Context> native_context);
+
   // Add or update entry in the optimized code map for context-independent code.
   static void AddSharedCodeToOptimizedCodeMap(Handle<SharedFunctionInfo> shared,
                                               Handle<Code> code);
@@ -6750,6 +6797,18 @@
 
   static const int kNotFound = -1;
 
+  // Helpers for assembly code that does a backwards walk of the optimized code
+  // map.
+  static const int kOffsetToPreviousContext =
+      FixedArray::kHeaderSize + kPointerSize * (kContextOffset - kEntryLength);
+  static const int kOffsetToPreviousCachedCode =
+      FixedArray::kHeaderSize +
+      kPointerSize * (kCachedCodeOffset - kEntryLength);
+  static const int kOffsetToPreviousLiterals =
+      FixedArray::kHeaderSize + kPointerSize * (kLiteralsOffset - kEntryLength);
+  static const int kOffsetToPreviousOsrAstId =
+      FixedArray::kHeaderSize + kPointerSize * (kOsrAstIdOffset - kEntryLength);
+
   // [scope_info]: Scope info.
   DECL_ACCESSORS(scope_info, ScopeInfo)
 
@@ -6778,16 +6837,10 @@
   inline int expected_nof_properties() const;
   inline void set_expected_nof_properties(int value);
 
-  // [feedback_vector] - accumulates ast node feedback from full-codegen and
+  // [feedback_metadata] - describes ast node feedback from full-codegen and
   // (increasingly) from crankshafted code where sufficient feedback isn't
   // available.
-  DECL_ACCESSORS(feedback_vector, TypeFeedbackVector)
-
-  // Unconditionally clear the type feedback vector (including vector ICs).
-  void ClearTypeFeedbackInfo();
-
-  // Clear the type feedback vector with a more subtle policy at GC time.
-  void ClearTypeFeedbackInfoAtGCTime();
+  DECL_ACCESSORS(feedback_metadata, TypeFeedbackMetadata)
 
 #if TRACE_MAPS
   // [unique_id] - For --trace-maps purposes, an identifier that's persistent
@@ -6960,6 +7013,13 @@
   // Indicates that this function is a generator.
   DECL_BOOLEAN_ACCESSORS(is_generator)
 
+  // Indicates that this function is an async function.
+  DECL_BOOLEAN_ACCESSORS(is_async)
+
+  // Indicates that this function can be suspended, either via YieldExpressions
+  // or AwaitExpressions.
+  inline bool is_resumable() const;
+
   // Indicates that this function is an arrow function.
   DECL_BOOLEAN_ACCESSORS(is_arrow)
 
@@ -7099,15 +7159,15 @@
   static const int kScriptOffset = kFunctionDataOffset + kPointerSize;
   static const int kDebugInfoOffset = kScriptOffset + kPointerSize;
   static const int kFunctionIdentifierOffset = kDebugInfoOffset + kPointerSize;
-  static const int kFeedbackVectorOffset =
+  static const int kFeedbackMetadataOffset =
       kFunctionIdentifierOffset + kPointerSize;
 #if TRACE_MAPS
-  static const int kUniqueIdOffset = kFeedbackVectorOffset + kPointerSize;
+  static const int kUniqueIdOffset = kFeedbackMetadataOffset + kPointerSize;
   static const int kLastPointerFieldOffset = kUniqueIdOffset;
 #else
   // Just to not break the postmortrem support with conditional offsets
-  static const int kUniqueIdOffset = kFeedbackVectorOffset;
-  static const int kLastPointerFieldOffset = kFeedbackVectorOffset;
+  static const int kUniqueIdOffset = kFeedbackMetadataOffset;
+  static const int kLastPointerFieldOffset = kFeedbackMetadataOffset;
 #endif
 
 #if V8_HOST_ARCH_32_BIT
@@ -7256,6 +7316,7 @@
     kIsGetterFunction,
     kIsSetterFunction,
     // byte 3
+    kIsAsyncFunction,
     kDeserialized,
     kIsDeclaration,
     kCompilerHintsCount,  // Pseudo entry
@@ -7278,7 +7339,7 @@
   ASSERT_FUNCTION_KIND_ORDER(kSetterFunction, kIsSetterFunction);
 #undef ASSERT_FUNCTION_KIND_ORDER
 
-  class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 8> {};
+  class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 9> {};
 
   class DeoptCountBits : public BitField<int, 0, 4> {};
   class OptReenableTriesBits : public BitField<int, 4, 18> {};
@@ -7307,6 +7368,8 @@
   static const int kStrictModeBit =
       kStrictModeFunction + kCompilerHintsSmiTagSize;
   static const int kNativeBit = kNative + kCompilerHintsSmiTagSize;
+  static const int kHasDuplicateParametersBit =
+      kHasDuplicateParameters + kCompilerHintsSmiTagSize;
 
   static const int kClassConstructorBits =
       FunctionKind::kClassConstructor
@@ -7317,6 +7380,8 @@
   // Allows to use byte-width instructions.
   static const int kStrictModeBitWithinByte = kStrictModeBit % kBitsPerByte;
   static const int kNativeBitWithinByte = kNativeBit % kBitsPerByte;
+  static const int kHasDuplicateParametersBitWithinByte =
+      kHasDuplicateParametersBit % kBitsPerByte;
 
   static const int kClassConstructorBitsWithinByte =
       FunctionKind::kClassConstructor << kCompilerHintsSmiTagSize;
@@ -7336,6 +7401,8 @@
   static const int kStrictModeByteOffset = BYTE_OFFSET(kStrictModeFunction);
   static const int kNativeByteOffset = BYTE_OFFSET(kNative);
   static const int kFunctionKindByteOffset = BYTE_OFFSET(kFunctionKind);
+  static const int kHasDuplicateParametersByteOffset =
+      BYTE_OFFSET(kHasDuplicateParameters);
 #undef BYTE_OFFSET
 
  private:
@@ -7372,19 +7439,32 @@
   // [receiver]: The receiver of the suspended computation.
   DECL_ACCESSORS(receiver, Object)
 
-  // [input]: The most recent input value.
-  DECL_ACCESSORS(input, Object)
+  // [input_or_debug_pos]
+  // For executing generators: the most recent input value.
+  // For suspended new-style generators: debug information (bytecode offset).
+  // For suspended old-style generators: unused.
+  // There is currently no need to remember the most recent input value for a
+  // suspended generator.
+  DECL_ACCESSORS(input_or_debug_pos, Object)
 
-  // [continuation]: Offset into code of continuation.
+  // [resume_mode]: The most recent resume mode.
+  enum ResumeMode { kNext, kReturn, kThrow };
+  DECL_INT_ACCESSORS(resume_mode)
+
+  // [continuation]
   //
-  // A positive offset indicates a suspended generator.  The special
+  // A positive value indicates a suspended generator.  The special
   // kGeneratorExecuting and kGeneratorClosed values indicate that a generator
   // cannot be resumed.
   inline int continuation() const;
   inline void set_continuation(int continuation);
-  inline bool is_closed();
-  inline bool is_executing();
-  inline bool is_suspended();
+  inline bool is_closed() const;
+  inline bool is_executing() const;
+  inline bool is_suspended() const;
+
+  // For suspended generators: the source position at which the generator
+  // is suspended.
+  int source_position() const;
 
   // [operand_stack]: Saved operand stack.
   DECL_ACCESSORS(operand_stack, FixedArray)
@@ -7392,25 +7472,22 @@
   DECLARE_CAST(JSGeneratorObject)
 
   // Dispatched behavior.
-  DECLARE_PRINTER(JSGeneratorObject)
   DECLARE_VERIFIER(JSGeneratorObject)
 
   // Magic sentinel values for the continuation.
-  static const int kGeneratorExecuting = -1;
-  static const int kGeneratorClosed = 0;
+  static const int kGeneratorExecuting = -2;
+  static const int kGeneratorClosed = -1;
 
   // Layout description.
   static const int kFunctionOffset = JSObject::kHeaderSize;
   static const int kContextOffset = kFunctionOffset + kPointerSize;
   static const int kReceiverOffset = kContextOffset + kPointerSize;
-  static const int kInputOffset = kReceiverOffset + kPointerSize;
-  static const int kContinuationOffset = kInputOffset + kPointerSize;
+  static const int kInputOrDebugPosOffset = kReceiverOffset + kPointerSize;
+  static const int kResumeModeOffset = kInputOrDebugPosOffset + kPointerSize;
+  static const int kContinuationOffset = kResumeModeOffset + kPointerSize;
   static const int kOperandStackOffset = kContinuationOffset + kPointerSize;
   static const int kSize = kOperandStackOffset + kPointerSize;
 
-  // Resume mode, for use by runtime functions.
-  enum ResumeMode { NEXT, RETURN, THROW };
-
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSGeneratorObject);
 };
@@ -7444,12 +7521,6 @@
 // JSBoundFunction describes a bound function exotic object.
 class JSBoundFunction : public JSObject {
  public:
-  // [length]: The bound function "length" property.
-  DECL_ACCESSORS(length, Object)
-
-  // [name]: The bound function "name" property.
-  DECL_ACCESSORS(name, Object)
-
   // [bound_target_function]: The wrapped function object.
   DECL_ACCESSORS(bound_target_function, JSReceiver)
 
@@ -7461,6 +7532,8 @@
   // arguments to any call to the wrapped function.
   DECL_ACCESSORS(bound_arguments, FixedArray)
 
+  static MaybeHandle<String> GetName(Isolate* isolate,
+                                     Handle<JSBoundFunction> function);
   static MaybeHandle<Context> GetFunctionRealm(
       Handle<JSBoundFunction> function);
 
@@ -7474,20 +7547,11 @@
   // to ES6 section 19.2.3.5 Function.prototype.toString ( ).
   static Handle<String> ToString(Handle<JSBoundFunction> function);
 
-  static MaybeHandle<String> GetName(Isolate* isolate,
-                                     Handle<JSBoundFunction> function);
-
   // Layout description.
   static const int kBoundTargetFunctionOffset = JSObject::kHeaderSize;
   static const int kBoundThisOffset = kBoundTargetFunctionOffset + kPointerSize;
   static const int kBoundArgumentsOffset = kBoundThisOffset + kPointerSize;
-  static const int kLengthOffset = kBoundArgumentsOffset + kPointerSize;
-  static const int kNameOffset = kLengthOffset + kPointerSize;
-  static const int kSize = kNameOffset + kPointerSize;
-
-  // Indices of in-object properties.
-  static const int kLengthIndex = 0;
-  static const int kNameIndex = 1;
+  static const int kSize = kBoundArgumentsOffset + kPointerSize;
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSBoundFunction);
@@ -7504,12 +7568,18 @@
   // can be shared by instances.
   DECL_ACCESSORS(shared, SharedFunctionInfo)
 
+  static const int kLengthDescriptorIndex = 0;
+  static const int kNameDescriptorIndex = 1;
+
   // [context]: The context for this function.
   inline Context* context();
   inline void set_context(Object* context);
   inline JSObject* global_proxy();
   inline Context* native_context();
 
+  static Handle<Object> GetName(Isolate* isolate, Handle<JSFunction> function);
+  static MaybeHandle<Smi> GetLength(Isolate* isolate,
+                                    Handle<JSFunction> function);
   static Handle<Context> GetFunctionRealm(Handle<JSFunction> function);
 
   // [code]: The generated code object for this function.  Executed
@@ -7531,13 +7601,14 @@
   // Tells whether or not this function has been optimized.
   inline bool IsOptimized();
 
-  // Mark this function for lazy recompilation. The function will be
-  // recompiled the next time it is executed.
+  // Mark this function for lazy recompilation. The function will be recompiled
+  // the next time it is executed.
+  void MarkForBaseline();
   void MarkForOptimization();
   void AttemptConcurrentOptimization();
 
-  // Tells whether or not the function is already marked for lazy
-  // recompilation.
+  // Tells whether or not the function is already marked for lazy recompilation.
+  inline bool IsMarkedForBaseline();
   inline bool IsMarkedForOptimization();
   inline bool IsMarkedForConcurrentOptimization();
 
@@ -7558,6 +7629,15 @@
   // access to.
   DECL_ACCESSORS(literals, LiteralsArray)
 
+  static void EnsureLiterals(Handle<JSFunction> function);
+  inline TypeFeedbackVector* feedback_vector();
+
+  // Unconditionally clear the type feedback vector (including vector ICs).
+  void ClearTypeFeedbackInfo();
+
+  // Clear the type feedback vector with a more subtle policy at GC time.
+  void ClearTypeFeedbackInfoAtGCTime();
+
   // The initial map for an object created by this constructor.
   inline Map* initial_map();
   static void SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
@@ -7641,9 +7721,6 @@
   DECLARE_PRINTER(JSFunction)
   DECLARE_VERIFIER(JSFunction)
 
-  // Returns the number of allocated literals.
-  inline int NumberOfLiterals();
-
   // The function's name if it is configured, otherwise shared function info
   // debug name.
   static Handle<String> GetName(Handle<JSFunction> function);
@@ -7948,7 +8025,6 @@
   // NOT_COMPILED: Initial value. No data has been stored in the JSRegExp yet.
   // ATOM: A simple string to match against using an indexOf operation.
   // IRREGEXP: Compiled with Irregexp.
-  // IRREGEXP_NATIVE: Compiled to native code with Irregexp.
   enum Type { NOT_COMPILED, ATOM, IRREGEXP };
   enum Flag {
     kNone = 0,
@@ -7965,7 +8041,6 @@
   DECL_ACCESSORS(source, Object)
 
   static MaybeHandle<JSRegExp> New(Handle<String> source, Flags flags);
-  static MaybeHandle<JSRegExp> New(Handle<String> source, Handle<String> flags);
   static Handle<JSRegExp> Copy(Handle<JSRegExp> regexp);
 
   static MaybeHandle<JSRegExp> Initialize(Handle<JSRegExp> regexp,
@@ -8042,8 +8117,11 @@
   static const int kIrregexpMaxRegisterCountIndex = kDataIndex + 4;
   // Number of captures in the compiled regexp.
   static const int kIrregexpCaptureCountIndex = kDataIndex + 5;
+  // Maps names of named capture groups (at indices 2i) to their corresponding
+  // capture group indices (at indices 2i + 1).
+  static const int kIrregexpCaptureNameMapIndex = kDataIndex + 6;
 
-  static const int kIrregexpDataSize = kIrregexpCaptureCountIndex + 1;
+  static const int kIrregexpDataSize = kIrregexpCaptureNameMapIndex + 1;
 
   // Offsets directly into the data fixed array.
   static const int kDataTagOffset =
@@ -8140,57 +8218,6 @@
 };
 
 
-class CodeCache: public Struct {
- public:
-  DECL_ACCESSORS(default_cache, FixedArray)
-  DECL_ACCESSORS(normal_type_cache, Object)
-
-  // Add the code object to the cache.
-  static void Update(
-      Handle<CodeCache> cache, Handle<Name> name, Handle<Code> code);
-
-  // Lookup code object in the cache. Returns code object if found and undefined
-  // if not.
-  Object* Lookup(Name* name, Code::Flags flags);
-
-  // Get the internal index of a code object in the cache. Returns -1 if the
-  // code object is not in that cache. This index can be used to later call
-  // RemoveByIndex. The cache cannot be modified between a call to GetIndex and
-  // RemoveByIndex.
-  int GetIndex(Object* name, Code* code);
-
-  // Remove an object from the cache with the provided internal index.
-  void RemoveByIndex(Object* name, Code* code, int index);
-
-  DECLARE_CAST(CodeCache)
-
-  // Dispatched behavior.
-  DECLARE_PRINTER(CodeCache)
-  DECLARE_VERIFIER(CodeCache)
-
-  static const int kDefaultCacheOffset = HeapObject::kHeaderSize;
-  static const int kNormalTypeCacheOffset =
-      kDefaultCacheOffset + kPointerSize;
-  static const int kSize = kNormalTypeCacheOffset + kPointerSize;
-
- private:
-  static void UpdateDefaultCache(
-      Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code);
-  static void UpdateNormalTypeCache(
-      Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code);
-  Object* LookupDefaultCache(Name* name, Code::Flags flags);
-  Object* LookupNormalTypeCache(Name* name, Code::Flags flags);
-
-  // Code cache layout of the default cache. Elements are alternating name and
-  // code objects for non normal load/store/call IC's.
-  static const int kCodeCacheEntrySize = 2;
-  static const int kCodeCacheEntryNameOffset = 0;
-  static const int kCodeCacheEntryCodeOffset = 1;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCache);
-};
-
-
 class CodeCacheHashTableShape : public BaseShape<HashTableKey*> {
  public:
   static inline bool IsMatch(HashTableKey* key, Object* value) {
@@ -8208,7 +8235,11 @@
   static inline Handle<Object> AsHandle(Isolate* isolate, HashTableKey* key);
 
   static const int kPrefixSize = 0;
-  static const int kEntrySize = 2;
+  // The both the key (name + flags) and value (code object) can be derived from
+  // the fixed array that stores both the name and code.
+  // TODO(verwaest): Don't allocate a fixed array but inline name and code.
+  // Rewrite IsMatch to get table + index as input rather than just the raw key.
+  static const int kEntrySize = 1;
 };
 
 
@@ -8216,73 +8247,20 @@
                                            CodeCacheHashTableShape,
                                            HashTableKey*> {
  public:
-  Object* Lookup(Name* name, Code::Flags flags);
   static Handle<CodeCacheHashTable> Put(
       Handle<CodeCacheHashTable> table,
       Handle<Name> name,
       Handle<Code> code);
 
-  int GetIndex(Name* name, Code::Flags flags);
-  void RemoveByIndex(int index);
+  Code* Lookup(Name* name, Code::Flags flags);
 
   DECLARE_CAST(CodeCacheHashTable)
 
-  // Initial size of the fixed array backing the hash table.
-  static const int kInitialSize = 64;
-
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCacheHashTable);
 };
 
 
-class PolymorphicCodeCache: public Struct {
- public:
-  DECL_ACCESSORS(cache, Object)
-
-  static void Update(Handle<PolymorphicCodeCache> cache,
-                     MapHandleList* maps,
-                     Code::Flags flags,
-                     Handle<Code> code);
-
-
-  // Returns an undefined value if the entry is not found.
-  Handle<Object> Lookup(MapHandleList* maps, Code::Flags flags);
-
-  DECLARE_CAST(PolymorphicCodeCache)
-
-  // Dispatched behavior.
-  DECLARE_PRINTER(PolymorphicCodeCache)
-  DECLARE_VERIFIER(PolymorphicCodeCache)
-
-  static const int kCacheOffset = HeapObject::kHeaderSize;
-  static const int kSize = kCacheOffset + kPointerSize;
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(PolymorphicCodeCache);
-};
-
-
-class PolymorphicCodeCacheHashTable
-    : public HashTable<PolymorphicCodeCacheHashTable,
-                       CodeCacheHashTableShape,
-                       HashTableKey*> {
- public:
-  Object* Lookup(MapHandleList* maps, int code_kind);
-
-  static Handle<PolymorphicCodeCacheHashTable> Put(
-      Handle<PolymorphicCodeCacheHashTable> hash_table,
-      MapHandleList* maps,
-      int code_kind,
-      Handle<Code> code);
-
-  DECLARE_CAST(PolymorphicCodeCacheHashTable)
-
-  static const int kInitialSize = 64;
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(PolymorphicCodeCacheHashTable);
-};
-
-
 class TypeFeedbackInfo: public Struct {
  public:
   inline int ic_total_count();
@@ -8668,6 +8646,8 @@
   // Return a string version of this name that is converted according to the
   // rules described in ES6 section 9.2.11.
   MUST_USE_RESULT static MaybeHandle<String> ToFunctionName(Handle<Name> name);
+  MUST_USE_RESULT static MaybeHandle<String> ToFunctionName(
+      Handle<Name> name, Handle<String> prefix);
 
   DECLARE_CAST(Name)
 
@@ -8705,6 +8685,10 @@
   // Array index strings this short can keep their index in the hash field.
   static const int kMaxCachedArrayIndexLength = 7;
 
+  // Maximum number of characters to consider when trying to convert a string
+  // value into an array index.
+  static const int kMaxArrayIndexSize = 10;
+
   // For strings which are array indexes the hash value has the string length
   // mixed into the hash, mainly to avoid a hash value of zero which would be
   // the case for the string '0'. 24 bits are used for the array index value.
@@ -8712,7 +8696,8 @@
   static const int kArrayIndexLengthBits =
       kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields;
 
-  STATIC_ASSERT((kArrayIndexLengthBits > 0));
+  STATIC_ASSERT(kArrayIndexLengthBits > 0);
+  STATIC_ASSERT(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));
 
   class ArrayIndexValueBits : public BitField<unsigned int, kNofHashBitFields,
       kArrayIndexValueBits> {};  // NOLINT
@@ -8802,34 +8787,6 @@
  public:
   enum Encoding { ONE_BYTE_ENCODING, TWO_BYTE_ENCODING };
 
-  // Array index strings this short can keep their index in the hash field.
-  static const int kMaxCachedArrayIndexLength = 7;
-
-  // For strings which are array indexes the hash value has the string length
-  // mixed into the hash, mainly to avoid a hash value of zero which would be
-  // the case for the string '0'. 24 bits are used for the array index value.
-  static const int kArrayIndexValueBits = 24;
-  static const int kArrayIndexLengthBits =
-      kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields;
-
-  STATIC_ASSERT((kArrayIndexLengthBits > 0));
-
-  class ArrayIndexValueBits : public BitField<unsigned int, kNofHashBitFields,
-      kArrayIndexValueBits> {};  // NOLINT
-  class ArrayIndexLengthBits : public BitField<unsigned int,
-      kNofHashBitFields + kArrayIndexValueBits,
-      kArrayIndexLengthBits> {};  // NOLINT
-
-  // Check that kMaxCachedArrayIndexLength + 1 is a power of two so we
-  // could use a mask to test if the length of string is less than or equal to
-  // kMaxCachedArrayIndexLength.
-  STATIC_ASSERT(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1));
-
-  static const unsigned int kContainsCachedArrayIndexMask =
-      (~static_cast<unsigned>(kMaxCachedArrayIndexLength)
-       << ArrayIndexLengthBits::kShift) |
-      kIsNotArrayIndexMask;
-
   class SubStringRange {
    public:
     explicit inline SubStringRange(String* string, int first = 0,
@@ -8852,26 +8809,26 @@
   class FlatContent {
    public:
     // Returns true if the string is flat and this structure contains content.
-    bool IsFlat() { return state_ != NON_FLAT; }
+    bool IsFlat() const { return state_ != NON_FLAT; }
     // Returns true if the structure contains one-byte content.
-    bool IsOneByte() { return state_ == ONE_BYTE; }
+    bool IsOneByte() const { return state_ == ONE_BYTE; }
     // Returns true if the structure contains two-byte content.
-    bool IsTwoByte() { return state_ == TWO_BYTE; }
+    bool IsTwoByte() const { return state_ == TWO_BYTE; }
 
     // Return the one byte content of the string. Only use if IsOneByte()
     // returns true.
-    Vector<const uint8_t> ToOneByteVector() {
+    Vector<const uint8_t> ToOneByteVector() const {
       DCHECK_EQ(ONE_BYTE, state_);
       return Vector<const uint8_t>(onebyte_start, length_);
     }
     // Return the two-byte content of the string. Only use if IsTwoByte()
     // returns true.
-    Vector<const uc16> ToUC16Vector() {
+    Vector<const uc16> ToUC16Vector() const {
       DCHECK_EQ(TWO_BYTE, state_);
       return Vector<const uc16>(twobyte_start, length_);
     }
 
-    uc16 Get(int i) {
+    uc16 Get(int i) const {
       DCHECK(i < length_);
       DCHECK(state_ != NON_FLAT);
       if (state_ == ONE_BYTE) return onebyte_start[i];
@@ -9006,15 +8963,6 @@
       RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL,
       int* length_output = 0);
 
-  // Return a 16 bit Unicode representation of the string.
-  // The string should be nearly flat, otherwise the performance of
-  // of this method may be very bad.  Setting robustness_flag to
-  // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust  This means it
-  // handles unexpected data without causing assert failures and it does not
-  // do any heap allocations.  This is useful when printing stack traces.
-  base::SmartArrayPointer<uc16> ToWideCString(
-      RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL);
-
   bool ComputeArrayIndex(uint32_t* index);
 
   // Externalization.
@@ -9024,6 +8972,10 @@
   // Conversion.
   inline bool AsArrayIndex(uint32_t* index);
 
+  // Trimming.
+  enum TrimMode { kTrim, kTrimLeft, kTrimRight };
+  static Handle<String> Trim(Handle<String> string, TrimMode mode);
+
   DECLARE_CAST(String)
 
   void PrintOn(FILE* out);
@@ -9032,7 +8984,7 @@
   bool LooksValid();
 
   // Dispatched behavior.
-  void StringShortPrint(StringStream* accumulator);
+  void StringShortPrint(StringStream* accumulator, bool show_details = true);
   void PrintUC16(std::ostream& os, int start = 0, int end = -1);  // NOLINT
 #if defined(DEBUG) || defined(OBJECT_PRINT)
   char* ToAsciiArray();
@@ -9046,11 +8998,6 @@
   static const int kLengthOffset = Name::kSize;
   static const int kSize = kLengthOffset + kPointerSize;
 
-  // Maximum number of characters to consider when trying to convert a string
-  // value into an array index.
-  static const int kMaxArrayIndexSize = 10;
-  STATIC_ASSERT(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));
-
   // Max char codes.
   static const int32_t kMaxOneByteCharCode = unibrow::Latin1::kMaxChar;
   static const uint32_t kMaxOneByteCharCodeU = unibrow::Latin1::kMaxChar;
@@ -9589,6 +9536,10 @@
 // The Oddball describes objects null, undefined, true, and false.
 class Oddball: public HeapObject {
  public:
+  // [to_number_raw]: Cached raw to_number computed at startup.
+  inline double to_number_raw() const;
+  inline void set_to_number_raw(double value);
+
   // [to_string]: Cached to_string computed at startup.
   DECL_ACCESSORS(to_string, String)
 
@@ -9618,7 +9569,8 @@
                          bool to_boolean, const char* type_of, byte kind);
 
   // Layout description.
-  static const int kToStringOffset = HeapObject::kHeaderSize;
+  static const int kToNumberRawOffset = HeapObject::kHeaderSize;
+  static const int kToStringOffset = kToNumberRawOffset + kDoubleSize;
   static const int kToNumberOffset = kToStringOffset + kPointerSize;
   static const int kToBooleanOffset = kToNumberOffset + kPointerSize;
   static const int kTypeOfOffset = kToBooleanOffset + kPointerSize;
@@ -9636,10 +9588,12 @@
   static const byte kOther = 7;
   static const byte kException = 8;
   static const byte kOptimizedOut = 9;
+  static const byte kStaleRegister = 10;
 
   typedef FixedBodyDescriptor<kToStringOffset, kTypeOfOffset + kPointerSize,
                               kSize> BodyDescriptor;
 
+  STATIC_ASSERT(kToNumberRawOffset == HeapNumber::kValueOffset);
   STATIC_ASSERT(kKindOffset == Internals::kOddballKindOffset);
   STATIC_ASSERT(kNull == Internals::kNullOddballKind);
   STATIC_ASSERT(kUndefined == Internals::kUndefinedOddballKind);
@@ -9858,10 +9812,9 @@
   typedef FixedBodyDescriptor<JSReceiver::kPropertiesOffset, kSize, kSize>
       BodyDescriptor;
 
-  static Handle<Object> GetIdentityHash(Isolate* isolate,
-                                        Handle<JSProxy> receiver);
+  static Object* GetIdentityHash(Handle<JSProxy> receiver);
 
-  static Handle<Smi> GetOrCreateIdentityHash(Handle<JSProxy> proxy);
+  static Smi* GetOrCreateIdentityHash(Isolate* isolate, Handle<JSProxy> proxy);
 
   static Maybe<bool> SetPrivateProperty(Isolate* isolate, Handle<JSProxy> proxy,
                                         Handle<Symbol> private_name,
@@ -10305,9 +10258,6 @@
   inline bool AllowsSetLength();
 
   static void SetLength(Handle<JSArray> array, uint32_t length);
-  // Same as above but will also queue splice records if |array| is observed.
-  static MaybeHandle<Object> ObservableSetLength(Handle<JSArray> array,
-                                                 uint32_t length);
 
   // Set the content of the array to the content of storage.
   static inline void SetContent(Handle<JSArray> array,
@@ -10396,10 +10346,18 @@
   DECL_ACCESSORS(name, Object)
   DECL_INT_ACCESSORS(flag)
   DECL_ACCESSORS(expected_receiver_type, Object)
+  // This directly points at a foreign C function to be used from the runtime.
   DECL_ACCESSORS(getter, Object)
   DECL_ACCESSORS(setter, Object)
+  // This either points at the same as above, or a trampoline in case we are
+  // running with the simulator. Use these entries from generated code.
+  DECL_ACCESSORS(js_getter, Object)
   DECL_ACCESSORS(data, Object)
 
+  static Address redirect(Isolate* isolate, Address address,
+                          AccessorComponent component);
+  Address redirected_getter() const;
+
   // Dispatched behavior.
   DECLARE_PRINTER(AccessorInfo)
 
@@ -10438,9 +10396,10 @@
   static const int kNameOffset = HeapObject::kHeaderSize;
   static const int kFlagOffset = kNameOffset + kPointerSize;
   static const int kExpectedReceiverTypeOffset = kFlagOffset + kPointerSize;
-  static const int kGetterOffset = kExpectedReceiverTypeOffset + kPointerSize;
-  static const int kSetterOffset = kGetterOffset + kPointerSize;
-  static const int kDataOffset = kSetterOffset + kPointerSize;
+  static const int kSetterOffset = kExpectedReceiverTypeOffset + kPointerSize;
+  static const int kGetterOffset = kSetterOffset + kPointerSize;
+  static const int kJsGetterOffset = kGetterOffset + kPointerSize;
+  static const int kDataOffset = kJsGetterOffset + kPointerSize;
   static const int kSize = kDataOffset + kPointerSize;
 
 
@@ -10510,9 +10469,9 @@
 
 class AccessCheckInfo: public Struct {
  public:
-  DECL_ACCESSORS(named_callback, Object)
-  DECL_ACCESSORS(indexed_callback, Object)
   DECL_ACCESSORS(callback, Object)
+  DECL_ACCESSORS(named_interceptor, Object)
+  DECL_ACCESSORS(indexed_interceptor, Object)
   DECL_ACCESSORS(data, Object)
 
   DECLARE_CAST(AccessCheckInfo)
@@ -10521,10 +10480,13 @@
   DECLARE_PRINTER(AccessCheckInfo)
   DECLARE_VERIFIER(AccessCheckInfo)
 
-  static const int kNamedCallbackOffset   = HeapObject::kHeaderSize;
-  static const int kIndexedCallbackOffset = kNamedCallbackOffset + kPointerSize;
-  static const int kCallbackOffset = kIndexedCallbackOffset + kPointerSize;
-  static const int kDataOffset = kCallbackOffset + kPointerSize;
+  static AccessCheckInfo* Get(Isolate* isolate, Handle<JSObject> receiver);
+
+  static const int kCallbackOffset = HeapObject::kHeaderSize;
+  static const int kNamedInterceptorOffset = kCallbackOffset + kPointerSize;
+  static const int kIndexedInterceptorOffset =
+      kNamedInterceptorOffset + kPointerSize;
+  static const int kDataOffset = kIndexedInterceptorOffset + kPointerSize;
   static const int kSize = kDataOffset + kPointerSize;
 
  private:
@@ -10630,6 +10592,7 @@
   DECL_ACCESSORS(signature, Object)
   DECL_ACCESSORS(instance_call_handler, Object)
   DECL_ACCESSORS(access_check_info, Object)
+  DECL_ACCESSORS(shared_function_info, Object)
   DECL_INT_ACCESSORS(flag)
 
   inline int length() const;
@@ -10644,7 +10607,6 @@
   DECL_BOOLEAN_ACCESSORS(read_only_prototype)
   DECL_BOOLEAN_ACCESSORS(remove_prototype)
   DECL_BOOLEAN_ACCESSORS(do_not_cache)
-  DECL_BOOLEAN_ACCESSORS(instantiated)
   DECL_BOOLEAN_ACCESSORS(accept_any_receiver)
 
   DECLARE_CAST(FunctionTemplateInfo)
@@ -10669,17 +10631,18 @@
   static const int kInstanceCallHandlerOffset = kSignatureOffset + kPointerSize;
   static const int kAccessCheckInfoOffset =
       kInstanceCallHandlerOffset + kPointerSize;
-  static const int kFlagOffset = kAccessCheckInfoOffset + kPointerSize;
+  static const int kSharedFunctionInfoOffset =
+      kAccessCheckInfoOffset + kPointerSize;
+  static const int kFlagOffset = kSharedFunctionInfoOffset + kPointerSize;
   static const int kLengthOffset = kFlagOffset + kPointerSize;
   static const int kSize = kLengthOffset + kPointerSize;
 
+  static Handle<SharedFunctionInfo> GetOrCreateSharedFunctionInfo(
+      Isolate* isolate, Handle<FunctionTemplateInfo> info);
   // Returns true if |object| is an instance of this function template.
-  bool IsTemplateFor(Object* object);
+  inline bool IsTemplateFor(JSObject* object);
   bool IsTemplateFor(Map* map);
-
-  // Returns the holder JSObject if the function can legally be called with this
-  // receiver.  Returns Heap::null_value() if the call is illegal.
-  Object* GetCompatibleReceiver(Isolate* isolate, Object* receiver);
+  inline bool instantiated();
 
  private:
   // Bit position in the flag, from least significant bit position.
@@ -10689,8 +10652,7 @@
   static const int kReadOnlyPrototypeBit = 3;
   static const int kRemovePrototypeBit   = 4;
   static const int kDoNotCacheBit        = 5;
-  static const int kInstantiatedBit      = 6;
-  static const int kAcceptAnyReceiver = 7;
+  static const int kAcceptAnyReceiver = 6;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
 };
diff --git a/src/optimizing-compile-dispatcher.cc b/src/optimizing-compile-dispatcher.cc
index ed20224..c3ec835 100644
--- a/src/optimizing-compile-dispatcher.cc
+++ b/src/optimizing-compile-dispatcher.cc
@@ -15,15 +15,16 @@
 
 namespace {
 
-void DisposeOptimizedCompileJob(OptimizedCompileJob* job,
-                                bool restore_function_code) {
-  // The recompile job is allocated in the CompilationInfo's zone.
-  CompilationInfo* info = job->info();
+void DisposeCompilationJob(CompilationJob* job, bool restore_function_code) {
   if (restore_function_code) {
-    Handle<JSFunction> function = info->closure();
+    Handle<JSFunction> function = job->info()->closure();
     function->ReplaceCode(function->shared()->code());
+    // TODO(mvstanton): We can't call ensureliterals here due to allocation,
+    // but we probably shouldn't call ReplaceCode either, as this
+    // sometimes runs on the worker thread!
+    // JSFunction::EnsureLiterals(function);
   }
-  delete info;
+  delete job;
 }
 
 }  // namespace
@@ -85,35 +86,29 @@
   DeleteArray(input_queue_);
 }
 
-
-OptimizedCompileJob* OptimizingCompileDispatcher::NextInput(
-    bool check_if_flushing) {
+CompilationJob* OptimizingCompileDispatcher::NextInput(bool check_if_flushing) {
   base::LockGuard<base::Mutex> access_input_queue_(&input_queue_mutex_);
   if (input_queue_length_ == 0) return NULL;
-  OptimizedCompileJob* job = input_queue_[InputQueueIndex(0)];
+  CompilationJob* job = input_queue_[InputQueueIndex(0)];
   DCHECK_NOT_NULL(job);
   input_queue_shift_ = InputQueueIndex(1);
   input_queue_length_--;
   if (check_if_flushing) {
     if (static_cast<ModeFlag>(base::Acquire_Load(&mode_)) == FLUSH) {
-      if (!job->info()->is_osr()) {
-        AllowHandleDereference allow_handle_dereference;
-        DisposeOptimizedCompileJob(job, true);
-      }
+      AllowHandleDereference allow_handle_dereference;
+      DisposeCompilationJob(job, true);
       return NULL;
     }
   }
   return job;
 }
 
-
-void OptimizingCompileDispatcher::CompileNext(OptimizedCompileJob* job) {
+void OptimizingCompileDispatcher::CompileNext(CompilationJob* job) {
   if (!job) return;
 
   // The function may have already been optimized by OSR.  Simply continue.
-  OptimizedCompileJob::Status status = job->OptimizeGraph();
-  USE(status);  // Prevent an unused-variable error in release mode.
-  DCHECK(status != OptimizedCompileJob::FAILED);
+  CompilationJob::Status status = job->OptimizeGraph();
+  USE(status);  // Prevent an unused-variable error.
 
   // The function may have already been optimized by OSR.  Simply continue.
   // Use a mutex to make sure that functions marked for install
@@ -126,7 +121,7 @@
 
 void OptimizingCompileDispatcher::FlushOutputQueue(bool restore_function_code) {
   for (;;) {
-    OptimizedCompileJob* job = NULL;
+    CompilationJob* job = NULL;
     {
       base::LockGuard<base::Mutex> access_output_queue_(&output_queue_mutex_);
       if (output_queue_.empty()) return;
@@ -134,10 +129,7 @@
       output_queue_.pop();
     }
 
-    // OSR jobs are dealt with separately.
-    if (!job->info()->is_osr()) {
-      DisposeOptimizedCompileJob(job, restore_function_code);
-    }
+    DisposeCompilationJob(job, restore_function_code);
   }
 }
 
@@ -181,7 +173,7 @@
   HandleScope handle_scope(isolate_);
 
   for (;;) {
-    OptimizedCompileJob* job = NULL;
+    CompilationJob* job = NULL;
     {
       base::LockGuard<base::Mutex> access_output_queue_(&output_queue_mutex_);
       if (output_queue_.empty()) return;
@@ -196,16 +188,14 @@
         function->ShortPrint();
         PrintF(" as it has already been optimized.\n");
       }
-      DisposeOptimizedCompileJob(job, false);
+      DisposeCompilationJob(job, false);
     } else {
-      Compiler::FinalizeOptimizedCompileJob(job);
+      Compiler::FinalizeCompilationJob(job);
     }
   }
 }
 
-
-void OptimizingCompileDispatcher::QueueForOptimization(
-    OptimizedCompileJob* job) {
+void OptimizingCompileDispatcher::QueueForOptimization(CompilationJob* job) {
   DCHECK(IsQueueAvailable());
   {
     // Add job to the back of the input queue.
diff --git a/src/optimizing-compile-dispatcher.h b/src/optimizing-compile-dispatcher.h
index e14e8aa..2b20a53 100644
--- a/src/optimizing-compile-dispatcher.h
+++ b/src/optimizing-compile-dispatcher.h
@@ -17,8 +17,7 @@
 namespace v8 {
 namespace internal {
 
-class HOptimizedGraphBuilder;
-class OptimizedCompileJob;
+class CompilationJob;
 class SharedFunctionInfo;
 
 class OptimizingCompileDispatcher {
@@ -32,7 +31,7 @@
         ref_count_(0),
         recompilation_delay_(FLAG_concurrent_recompilation_delay) {
     base::NoBarrier_Store(&mode_, static_cast<base::AtomicWord>(COMPILE));
-    input_queue_ = NewArray<OptimizedCompileJob*>(input_queue_capacity_);
+    input_queue_ = NewArray<CompilationJob*>(input_queue_capacity_);
   }
 
   ~OptimizingCompileDispatcher();
@@ -40,7 +39,7 @@
   void Run();
   void Stop();
   void Flush();
-  void QueueForOptimization(OptimizedCompileJob* optimizing_compiler);
+  void QueueForOptimization(CompilationJob* job);
   void Unblock();
   void InstallOptimizedFunctions();
 
@@ -57,8 +56,8 @@
   enum ModeFlag { COMPILE, FLUSH };
 
   void FlushOutputQueue(bool restore_function_code);
-  void CompileNext(OptimizedCompileJob* job);
-  OptimizedCompileJob* NextInput(bool check_if_flushing = false);
+  void CompileNext(CompilationJob* job);
+  CompilationJob* NextInput(bool check_if_flushing = false);
 
   inline int InputQueueIndex(int i) {
     int result = (i + input_queue_shift_) % input_queue_capacity_;
@@ -70,14 +69,14 @@
   Isolate* isolate_;
 
   // Circular queue of incoming recompilation tasks (including OSR).
-  OptimizedCompileJob** input_queue_;
+  CompilationJob** input_queue_;
   int input_queue_capacity_;
   int input_queue_length_;
   int input_queue_shift_;
   base::Mutex input_queue_mutex_;
 
   // Queue of recompilation tasks ready to be installed (excluding OSR).
-  std::queue<OptimizedCompileJob*> output_queue_;
+  std::queue<CompilationJob*> output_queue_;
   // Used for job based recompilation which has multiple producers on
   // different threads.
   base::Mutex output_queue_mutex_;
diff --git a/src/ostreams.cc b/src/ostreams.cc
index 120db25..45f41bb 100644
--- a/src/ostreams.cc
+++ b/src/ostreams.cc
@@ -97,5 +97,11 @@
   return PrintUC32(os, c.value, IsPrint);
 }
 
+std::ostream& operator<<(std::ostream& os, const AsHex& hex) {
+  char buf[20];
+  snprintf(buf, sizeof(buf), "%.*" PRIx64, hex.min_width, hex.value);
+  return os << buf;
+}
+
 }  // namespace internal
 }  // namespace v8
diff --git a/src/ostreams.h b/src/ostreams.h
index 1c2f38a..977b5c6 100644
--- a/src/ostreams.h
+++ b/src/ostreams.h
@@ -66,6 +66,12 @@
   uint16_t value;
 };
 
+struct AsHex {
+  explicit AsHex(uint64_t v, uint8_t min_width = 0)
+      : value(v), min_width(min_width) {}
+  uint64_t value;
+  uint8_t min_width;
+};
 
 // Writes the given character to the output escaping everything outside of
 // printable/space ASCII range. Additionally escapes '\' making escaping
@@ -83,6 +89,9 @@
 // of printable ASCII range.
 std::ostream& operator<<(std::ostream& os, const AsUC32& c);
 
+// Writes the given number to the output in hexadecimal notation.
+std::ostream& operator<<(std::ostream& os, const AsHex& v);
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/parsing/OWNERS b/src/parsing/OWNERS
index a5daeb3..44cc4ed 100644
--- a/src/parsing/OWNERS
+++ b/src/parsing/OWNERS
@@ -4,4 +4,4 @@
 littledan@chromium.org
 marja@chromium.org
 rossberg@chromium.org
-
+vogelheim@chromium.org
diff --git a/src/parsing/expression-classifier.h b/src/parsing/expression-classifier.h
index 71fa3d3..8e13d0e 100644
--- a/src/parsing/expression-classifier.h
+++ b/src/parsing/expression-classifier.h
@@ -13,141 +13,208 @@
 namespace internal {
 
 
+#define ERROR_CODES(T)                          \
+  T(ExpressionProduction, 0)                    \
+  T(FormalParameterInitializerProduction, 1)    \
+  T(BindingPatternProduction, 2)                \
+  T(AssignmentPatternProduction, 3)             \
+  T(DistinctFormalParametersProduction, 4)      \
+  T(StrictModeFormalParametersProduction, 5)    \
+  T(ArrowFormalParametersProduction, 6)         \
+  T(LetPatternProduction, 7)                    \
+  T(CoverInitializedNameProduction, 8)          \
+  T(TailCallExpressionProduction, 9)            \
+  T(AsyncArrowFormalParametersProduction, 10)   \
+  T(AsyncBindingPatternProduction, 11)
+
+
 template <typename Traits>
 class ExpressionClassifier {
  public:
+  enum ErrorKind : unsigned {
+#define DEFINE_ERROR_KIND(NAME, CODE) k##NAME = CODE,
+    ERROR_CODES(DEFINE_ERROR_KIND)
+#undef DEFINE_ERROR_KIND
+    kUnusedError = 15  // Larger than error codes; should fit in 4 bits
+  };
+
   struct Error {
-    Error()
+    V8_INLINE Error()
         : location(Scanner::Location::invalid()),
           message(MessageTemplate::kNone),
+          kind(kUnusedError),
           type(kSyntaxError),
           arg(nullptr) {}
+    V8_INLINE explicit Error(Scanner::Location loc,
+                             MessageTemplate::Template msg, ErrorKind k,
+                             const char* a = nullptr,
+                             ParseErrorType t = kSyntaxError)
+        : location(loc), message(msg), kind(k), type(t), arg(a) {}
 
     Scanner::Location location;
-    MessageTemplate::Template message : 30;
+    MessageTemplate::Template message : 26;
+    unsigned kind : 4;
     ParseErrorType type : 2;
     const char* arg;
   };
 
-  enum TargetProduction {
-    ExpressionProduction = 1 << 0,
-    FormalParameterInitializerProduction = 1 << 1,
-    BindingPatternProduction = 1 << 2,
-    AssignmentPatternProduction = 1 << 3,
-    DistinctFormalParametersProduction = 1 << 4,
-    StrictModeFormalParametersProduction = 1 << 5,
-    ArrowFormalParametersProduction = 1 << 6,
-    LetPatternProduction = 1 << 7,
-    CoverInitializedNameProduction = 1 << 8,
+  enum TargetProduction : unsigned {
+#define DEFINE_PRODUCTION(NAME, CODE) NAME = 1 << CODE,
+    ERROR_CODES(DEFINE_PRODUCTION)
+#undef DEFINE_PRODUCTION
 
     ExpressionProductions =
-        (ExpressionProduction | FormalParameterInitializerProduction),
-    PatternProductions = (BindingPatternProduction |
-                          AssignmentPatternProduction | LetPatternProduction),
+        (ExpressionProduction | FormalParameterInitializerProduction |
+         TailCallExpressionProduction),
+    PatternProductions =
+        (BindingPatternProduction | AssignmentPatternProduction |
+         LetPatternProduction | AsyncBindingPatternProduction),
     FormalParametersProductions = (DistinctFormalParametersProduction |
                                    StrictModeFormalParametersProduction),
     StandardProductions = ExpressionProductions | PatternProductions,
     AllProductions =
         (StandardProductions | FormalParametersProductions |
-         ArrowFormalParametersProduction | CoverInitializedNameProduction)
+         ArrowFormalParametersProduction | CoverInitializedNameProduction |
+         AsyncArrowFormalParametersProduction | AsyncBindingPatternProduction)
   };
 
-  enum FunctionProperties { NonSimpleParameter = 1 << 0 };
+  enum FunctionProperties : unsigned {
+    NonSimpleParameter = 1 << 0
+  };
 
   explicit ExpressionClassifier(const Traits* t)
       : zone_(t->zone()),
         non_patterns_to_rewrite_(t->GetNonPatternList()),
+        reported_errors_(t->GetReportedErrorList()),
+        duplicate_finder_(nullptr),
         invalid_productions_(0),
-        function_properties_(0),
-        duplicate_finder_(nullptr) {
+        function_properties_(0) {
+    reported_errors_begin_ = reported_errors_end_ = reported_errors_->length();
     non_pattern_begin_ = non_patterns_to_rewrite_->length();
   }
 
   ExpressionClassifier(const Traits* t, DuplicateFinder* duplicate_finder)
       : zone_(t->zone()),
         non_patterns_to_rewrite_(t->GetNonPatternList()),
+        reported_errors_(t->GetReportedErrorList()),
+        duplicate_finder_(duplicate_finder),
         invalid_productions_(0),
-        function_properties_(0),
-        duplicate_finder_(duplicate_finder) {
+        function_properties_(0) {
+    reported_errors_begin_ = reported_errors_end_ = reported_errors_->length();
     non_pattern_begin_ = non_patterns_to_rewrite_->length();
   }
 
   ~ExpressionClassifier() { Discard(); }
 
-  bool is_valid(unsigned productions) const {
+  V8_INLINE bool is_valid(unsigned productions) const {
     return (invalid_productions_ & productions) == 0;
   }
 
-  DuplicateFinder* duplicate_finder() const { return duplicate_finder_; }
+  V8_INLINE DuplicateFinder* duplicate_finder() const {
+    return duplicate_finder_;
+  }
 
-  bool is_valid_expression() const { return is_valid(ExpressionProduction); }
+  V8_INLINE bool is_valid_expression() const {
+    return is_valid(ExpressionProduction);
+  }
 
-  bool is_valid_formal_parameter_initializer() const {
+  V8_INLINE bool is_valid_formal_parameter_initializer() const {
     return is_valid(FormalParameterInitializerProduction);
   }
 
-  bool is_valid_binding_pattern() const {
+  V8_INLINE bool is_valid_binding_pattern() const {
     return is_valid(BindingPatternProduction);
   }
 
-  bool is_valid_assignment_pattern() const {
+  V8_INLINE bool is_valid_assignment_pattern() const {
     return is_valid(AssignmentPatternProduction);
   }
 
-  bool is_valid_arrow_formal_parameters() const {
+  V8_INLINE bool is_valid_arrow_formal_parameters() const {
     return is_valid(ArrowFormalParametersProduction);
   }
 
-  bool is_valid_formal_parameter_list_without_duplicates() const {
+  V8_INLINE bool is_valid_formal_parameter_list_without_duplicates() const {
     return is_valid(DistinctFormalParametersProduction);
   }
 
   // Note: callers should also check
   // is_valid_formal_parameter_list_without_duplicates().
-  bool is_valid_strict_mode_formal_parameters() const {
+  V8_INLINE bool is_valid_strict_mode_formal_parameters() const {
     return is_valid(StrictModeFormalParametersProduction);
   }
 
-  bool is_valid_let_pattern() const { return is_valid(LetPatternProduction); }
-
-  const Error& expression_error() const { return expression_error_; }
-
-  const Error& formal_parameter_initializer_error() const {
-    return formal_parameter_initializer_error_;
+  V8_INLINE bool is_valid_let_pattern() const {
+    return is_valid(LetPatternProduction);
   }
 
-  const Error& binding_pattern_error() const { return binding_pattern_error_; }
-
-  const Error& assignment_pattern_error() const {
-    return assignment_pattern_error_;
+  bool is_valid_async_arrow_formal_parameters() const {
+    return is_valid(AsyncArrowFormalParametersProduction);
   }
 
-  const Error& arrow_formal_parameters_error() const {
-    return arrow_formal_parameters_error_;
+  bool is_valid_async_binding_pattern() const {
+    return is_valid(AsyncBindingPatternProduction);
   }
 
-  const Error& duplicate_formal_parameter_error() const {
-    return duplicate_formal_parameter_error_;
+  V8_INLINE const Error& expression_error() const {
+    return reported_error(kExpressionProduction);
   }
 
-  const Error& strict_mode_formal_parameter_error() const {
-    return strict_mode_formal_parameter_error_;
+  V8_INLINE const Error& formal_parameter_initializer_error() const {
+    return reported_error(kFormalParameterInitializerProduction);
   }
 
-  const Error& let_pattern_error() const { return let_pattern_error_; }
+  V8_INLINE const Error& binding_pattern_error() const {
+    return reported_error(kBindingPatternProduction);
+  }
 
-  bool has_cover_initialized_name() const {
+  V8_INLINE const Error& assignment_pattern_error() const {
+    return reported_error(kAssignmentPatternProduction);
+  }
+
+  V8_INLINE const Error& arrow_formal_parameters_error() const {
+    return reported_error(kArrowFormalParametersProduction);
+  }
+
+  V8_INLINE const Error& duplicate_formal_parameter_error() const {
+    return reported_error(kDistinctFormalParametersProduction);
+  }
+
+  V8_INLINE const Error& strict_mode_formal_parameter_error() const {
+    return reported_error(kStrictModeFormalParametersProduction);
+  }
+
+  V8_INLINE const Error& let_pattern_error() const {
+    return reported_error(kLetPatternProduction);
+  }
+
+  V8_INLINE bool has_cover_initialized_name() const {
     return !is_valid(CoverInitializedNameProduction);
   }
-  const Error& cover_initialized_name_error() const {
-    return cover_initialized_name_error_;
+
+  V8_INLINE const Error& cover_initialized_name_error() const {
+    return reported_error(kCoverInitializedNameProduction);
   }
 
-  bool is_simple_parameter_list() const {
+  V8_INLINE bool has_tail_call_expression() const {
+    return !is_valid(TailCallExpressionProduction);
+  }
+  V8_INLINE const Error& tail_call_expression_error() const {
+    return reported_error(kTailCallExpressionProduction);
+  }
+  V8_INLINE const Error& async_arrow_formal_parameters_error() const {
+    return reported_error(kAsyncArrowFormalParametersProduction);
+  }
+
+  V8_INLINE const Error& async_binding_pattern_error() const {
+    return reported_error(kAsyncBindingPatternProduction);
+  }
+
+  V8_INLINE bool is_simple_parameter_list() const {
     return !(function_properties_ & NonSimpleParameter);
   }
 
-  void RecordNonSimpleParameter() {
+  V8_INLINE void RecordNonSimpleParameter() {
     function_properties_ |= NonSimpleParameter;
   }
 
@@ -156,9 +223,7 @@
                              const char* arg = nullptr) {
     if (!is_valid_expression()) return;
     invalid_productions_ |= ExpressionProduction;
-    expression_error_.location = loc;
-    expression_error_.message = message;
-    expression_error_.arg = arg;
+    Add(Error(loc, message, kExpressionProduction, arg));
   }
 
   void RecordExpressionError(const Scanner::Location& loc,
@@ -166,10 +231,7 @@
                              ParseErrorType type, const char* arg = nullptr) {
     if (!is_valid_expression()) return;
     invalid_productions_ |= ExpressionProduction;
-    expression_error_.location = loc;
-    expression_error_.message = message;
-    expression_error_.arg = arg;
-    expression_error_.type = type;
+    Add(Error(loc, message, kExpressionProduction, arg, type));
   }
 
   void RecordFormalParameterInitializerError(const Scanner::Location& loc,
@@ -177,9 +239,7 @@
                                              const char* arg = nullptr) {
     if (!is_valid_formal_parameter_initializer()) return;
     invalid_productions_ |= FormalParameterInitializerProduction;
-    formal_parameter_initializer_error_.location = loc;
-    formal_parameter_initializer_error_.message = message;
-    formal_parameter_initializer_error_.arg = arg;
+    Add(Error(loc, message, kFormalParameterInitializerProduction, arg));
   }
 
   void RecordBindingPatternError(const Scanner::Location& loc,
@@ -187,9 +247,7 @@
                                  const char* arg = nullptr) {
     if (!is_valid_binding_pattern()) return;
     invalid_productions_ |= BindingPatternProduction;
-    binding_pattern_error_.location = loc;
-    binding_pattern_error_.message = message;
-    binding_pattern_error_.arg = arg;
+    Add(Error(loc, message, kBindingPatternProduction, arg));
   }
 
   void RecordAssignmentPatternError(const Scanner::Location& loc,
@@ -197,9 +255,7 @@
                                     const char* arg = nullptr) {
     if (!is_valid_assignment_pattern()) return;
     invalid_productions_ |= AssignmentPatternProduction;
-    assignment_pattern_error_.location = loc;
-    assignment_pattern_error_.message = message;
-    assignment_pattern_error_.arg = arg;
+    Add(Error(loc, message, kAssignmentPatternProduction, arg));
   }
 
   void RecordPatternError(const Scanner::Location& loc,
@@ -214,17 +270,30 @@
                                         const char* arg = nullptr) {
     if (!is_valid_arrow_formal_parameters()) return;
     invalid_productions_ |= ArrowFormalParametersProduction;
-    arrow_formal_parameters_error_.location = loc;
-    arrow_formal_parameters_error_.message = message;
-    arrow_formal_parameters_error_.arg = arg;
+    Add(Error(loc, message, kArrowFormalParametersProduction, arg));
+  }
+
+  void RecordAsyncArrowFormalParametersError(const Scanner::Location& loc,
+                                             MessageTemplate::Template message,
+                                             const char* arg = nullptr) {
+    if (!is_valid_async_arrow_formal_parameters()) return;
+    invalid_productions_ |= AsyncArrowFormalParametersProduction;
+    Add(Error(loc, message, kAsyncArrowFormalParametersProduction, arg));
+  }
+
+  void RecordAsyncBindingPatternError(const Scanner::Location& loc,
+                                      MessageTemplate::Template message,
+                                      const char* arg = nullptr) {
+    if (!is_valid_async_binding_pattern()) return;
+    invalid_productions_ |= AsyncBindingPatternProduction;
+    Add(Error(loc, message, kAsyncBindingPatternProduction, arg));
   }
 
   void RecordDuplicateFormalParameterError(const Scanner::Location& loc) {
     if (!is_valid_formal_parameter_list_without_duplicates()) return;
     invalid_productions_ |= DistinctFormalParametersProduction;
-    duplicate_formal_parameter_error_.location = loc;
-    duplicate_formal_parameter_error_.message = MessageTemplate::kParamDupe;
-    duplicate_formal_parameter_error_.arg = nullptr;
+    Add(Error(loc, MessageTemplate::kParamDupe,
+              kDistinctFormalParametersProduction));
   }
 
   // Record a binding that would be invalid in strict mode.  Confusingly this
@@ -235,9 +304,7 @@
                                             const char* arg = nullptr) {
     if (!is_valid_strict_mode_formal_parameters()) return;
     invalid_productions_ |= StrictModeFormalParametersProduction;
-    strict_mode_formal_parameter_error_.location = loc;
-    strict_mode_formal_parameter_error_.message = message;
-    strict_mode_formal_parameter_error_.arg = arg;
+    Add(Error(loc, message, kStrictModeFormalParametersProduction, arg));
   }
 
   void RecordLetPatternError(const Scanner::Location& loc,
@@ -245,9 +312,7 @@
                              const char* arg = nullptr) {
     if (!is_valid_let_pattern()) return;
     invalid_productions_ |= LetPatternProduction;
-    let_pattern_error_.location = loc;
-    let_pattern_error_.message = message;
-    let_pattern_error_.arg = arg;
+    Add(Error(loc, message, kLetPatternProduction, arg));
   }
 
   void RecordCoverInitializedNameError(const Scanner::Location& loc,
@@ -255,76 +320,110 @@
                                        const char* arg = nullptr) {
     if (has_cover_initialized_name()) return;
     invalid_productions_ |= CoverInitializedNameProduction;
-    cover_initialized_name_error_.location = loc;
-    cover_initialized_name_error_.message = message;
-    cover_initialized_name_error_.arg = arg;
+    Add(Error(loc, message, kCoverInitializedNameProduction, arg));
+  }
+
+  void RecordTailCallExpressionError(const Scanner::Location& loc,
+                                     MessageTemplate::Template message,
+                                     const char* arg = nullptr) {
+    if (has_tail_call_expression()) return;
+    invalid_productions_ |= TailCallExpressionProduction;
+    Add(Error(loc, message, kTailCallExpressionProduction, arg));
   }
 
   void ForgiveCoverInitializedNameError() {
+    if (!(invalid_productions_ & CoverInitializedNameProduction)) return;
+    Error& e = reported_error(kCoverInitializedNameProduction);
+    e.kind = kUnusedError;
     invalid_productions_ &= ~CoverInitializedNameProduction;
-    cover_initialized_name_error_ = Error();
   }
 
   void ForgiveAssignmentPatternError() {
+    if (!(invalid_productions_ & AssignmentPatternProduction)) return;
+    Error& e = reported_error(kAssignmentPatternProduction);
+    e.kind = kUnusedError;
     invalid_productions_ &= ~AssignmentPatternProduction;
-    assignment_pattern_error_ = Error();
   }
 
   void Accumulate(ExpressionClassifier* inner,
                   unsigned productions = StandardProductions,
                   bool merge_non_patterns = true) {
+    DCHECK_EQ(inner->reported_errors_, reported_errors_);
+    DCHECK_EQ(inner->reported_errors_begin_, reported_errors_end_);
+    DCHECK_EQ(inner->reported_errors_end_, reported_errors_->length());
     if (merge_non_patterns) MergeNonPatterns(inner);
     // Propagate errors from inner, but don't overwrite already recorded
     // errors.
     unsigned non_arrow_inner_invalid_productions =
         inner->invalid_productions_ & ~ArrowFormalParametersProduction;
-    if (non_arrow_inner_invalid_productions == 0) return;
-    unsigned non_arrow_productions =
-        productions & ~ArrowFormalParametersProduction;
-    unsigned errors =
-        non_arrow_productions & non_arrow_inner_invalid_productions;
-    errors &= ~invalid_productions_;
-    if (errors != 0) {
-      invalid_productions_ |= errors;
-      if (errors & ExpressionProduction)
-        expression_error_ = inner->expression_error_;
-      if (errors & FormalParameterInitializerProduction)
-        formal_parameter_initializer_error_ =
-            inner->formal_parameter_initializer_error_;
-      if (errors & BindingPatternProduction)
-        binding_pattern_error_ = inner->binding_pattern_error_;
-      if (errors & AssignmentPatternProduction)
-        assignment_pattern_error_ = inner->assignment_pattern_error_;
-      if (errors & DistinctFormalParametersProduction)
-        duplicate_formal_parameter_error_ =
-            inner->duplicate_formal_parameter_error_;
-      if (errors & StrictModeFormalParametersProduction)
-        strict_mode_formal_parameter_error_ =
-            inner->strict_mode_formal_parameter_error_;
-      if (errors & LetPatternProduction)
-        let_pattern_error_ = inner->let_pattern_error_;
-      if (errors & CoverInitializedNameProduction)
-        cover_initialized_name_error_ = inner->cover_initialized_name_error_;
-    }
-
-    // As an exception to the above, the result continues to be a valid arrow
-    // formal parameters if the inner expression is a valid binding pattern.
-    if (productions & ArrowFormalParametersProduction &&
-        is_valid_arrow_formal_parameters()) {
-      // Also copy function properties if expecting an arrow function
-      // parameter.
-      function_properties_ |= inner->function_properties_;
-
-      if (!inner->is_valid_binding_pattern()) {
-        invalid_productions_ |= ArrowFormalParametersProduction;
-        arrow_formal_parameters_error_ = inner->binding_pattern_error_;
+    if (non_arrow_inner_invalid_productions) {
+      unsigned errors = non_arrow_inner_invalid_productions & productions &
+                        ~invalid_productions_;
+      // The result will continue to be a valid arrow formal parameters if the
+      // inner expression is a valid binding pattern.
+      bool copy_BP_to_AFP = false;
+      if (productions & ArrowFormalParametersProduction &&
+          is_valid_arrow_formal_parameters()) {
+        // Also copy function properties if expecting an arrow function
+        // parameter.
+        function_properties_ |= inner->function_properties_;
+        if (!inner->is_valid_binding_pattern()) {
+          copy_BP_to_AFP = true;
+          invalid_productions_ |= ArrowFormalParametersProduction;
+        }
+      }
+      // Traverse the list of errors reported by the inner classifier
+      // to copy what's necessary.
+      if (errors != 0 || copy_BP_to_AFP) {
+        invalid_productions_ |= errors;
+        int binding_pattern_index = inner->reported_errors_end_;
+        for (int i = inner->reported_errors_begin_;
+             i < inner->reported_errors_end_; i++) {
+          int k = reported_errors_->at(i).kind;
+          if (errors & (1 << k)) Copy(i);
+          // Check if it's a BP error that has to be copied to an AFP error.
+          if (k == kBindingPatternProduction && copy_BP_to_AFP) {
+            if (reported_errors_end_ <= i) {
+              // If the BP error itself has not already been copied,
+              // copy it now and change it to an AFP error.
+              Copy(i);
+              reported_errors_->at(reported_errors_end_-1).kind =
+                  kArrowFormalParametersProduction;
+            } else {
+              // Otherwise, if the BP error was already copied, keep its
+              // position and wait until the end of the traversal.
+              DCHECK_EQ(reported_errors_end_, i+1);
+              binding_pattern_index = i;
+            }
+          }
+        }
+        // Do we still have to copy the BP error to an AFP error?
+        if (binding_pattern_index < inner->reported_errors_end_) {
+          // If there's still unused space in the list of the inner
+          // classifier, copy it there, otherwise add it to the end
+          // of the list.
+          if (reported_errors_end_ < inner->reported_errors_end_)
+            Copy(binding_pattern_index);
+          else
+            Add(reported_errors_->at(binding_pattern_index));
+          reported_errors_->at(reported_errors_end_-1).kind =
+              kArrowFormalParametersProduction;
+        }
       }
     }
+    reported_errors_->Rewind(reported_errors_end_);
+    inner->reported_errors_begin_ = inner->reported_errors_end_ =
+        reported_errors_end_;
   }
 
   V8_INLINE int GetNonPatternBegin() const { return non_pattern_begin_; }
 
   V8_INLINE void Discard() {
+    if (reported_errors_end_ == reported_errors_->length()) {
+      reported_errors_->Rewind(reported_errors_begin_);
+      reported_errors_end_ = reported_errors_begin_;
+    }
+    DCHECK_EQ(reported_errors_begin_, reported_errors_end_);
     DCHECK_LE(non_pattern_begin_, non_patterns_to_rewrite_->length());
     non_patterns_to_rewrite_->Rewind(non_pattern_begin_);
   }
@@ -335,24 +434,69 @@
   }
 
  private:
+  V8_INLINE Error& reported_error(ErrorKind kind) const {
+    if (invalid_productions_ & (1 << kind)) {
+      for (int i = reported_errors_begin_; i < reported_errors_end_; i++) {
+        if (reported_errors_->at(i).kind == kind)
+          return reported_errors_->at(i);
+      }
+      UNREACHABLE();
+    }
+    // We should only be looking for an error when we know that one has
+    // been reported.  But we're not...  So this is to make sure we have
+    // the same behaviour.
+    static Error none;
+    return none;
+  }
+
+  // Adds e to the end of the list of reported errors for this classifier.
+  // It is expected that this classifier is the last one in the stack.
+  V8_INLINE void Add(const Error& e) {
+    DCHECK_EQ(reported_errors_end_, reported_errors_->length());
+    reported_errors_->Add(e, zone_);
+    reported_errors_end_++;
+  }
+
+  // Copies the error at position i of the list of reported errors, so that
+  // it becomes the last error reported for this classifier.  Position i
+  // could be either after the existing errors of this classifier (i.e.,
+  // in an inner classifier) or it could be an existing error (in case a
+  // copy is needed).
+  V8_INLINE void Copy(int i) {
+    DCHECK_LT(i, reported_errors_->length());
+    if (reported_errors_end_ != i)
+      reported_errors_->at(reported_errors_end_) = reported_errors_->at(i);
+    reported_errors_end_++;
+  }
+
   Zone* zone_;
   ZoneList<typename Traits::Type::Expression>* non_patterns_to_rewrite_;
-  int non_pattern_begin_;
-  unsigned invalid_productions_;
-  unsigned function_properties_;
-  Error expression_error_;
-  Error formal_parameter_initializer_error_;
-  Error binding_pattern_error_;
-  Error assignment_pattern_error_;
-  Error arrow_formal_parameters_error_;
-  Error duplicate_formal_parameter_error_;
-  Error strict_mode_formal_parameter_error_;
-  Error let_pattern_error_;
-  Error cover_initialized_name_error_;
+  ZoneList<Error>* reported_errors_;
   DuplicateFinder* duplicate_finder_;
+  // The uint16_t for non_pattern_begin_ will not be enough in the case,
+  // e.g., of an array literal containing more than 64K inner array
+  // literals with spreads, as in:
+  // var N=65536; eval("var x=[];" + "[" + "[...x],".repeat(N) + "].length");
+  // An implementation limit error in ParserBase::AddNonPatternForRewriting
+  // will be triggered in this case.
+  uint16_t non_pattern_begin_;
+  unsigned invalid_productions_ : 14;
+  unsigned function_properties_ : 2;
+  // The uint16_t for reported_errors_begin_ and reported_errors_end_ will
+  // not be enough in the case of a long series of expressions using nested
+  // classifiers, e.g., a long sequence of assignments, as in:
+  // literals with spreads, as in:
+  // var N=65536; eval("var x;" + "x=".repeat(N) + "42");
+  // This should not be a problem, as such things currently fail with a
+  // stack overflow while parsing.
+  uint16_t reported_errors_begin_;
+  uint16_t reported_errors_end_;
 };
 
 
+#undef ERROR_CODES
+
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/parsing/parameter-initializer-rewriter.cc b/src/parsing/parameter-initializer-rewriter.cc
index 3e3587b..4bb367d 100644
--- a/src/parsing/parameter-initializer-rewriter.cc
+++ b/src/parsing/parameter-initializer-rewriter.cc
@@ -4,6 +4,10 @@
 
 #include "src/parsing/parameter-initializer-rewriter.h"
 
+#include <algorithm>
+#include <utility>
+#include <vector>
+
 #include "src/ast/ast.h"
 #include "src/ast/ast-expression-visitor.h"
 #include "src/ast/scopes.h"
@@ -20,7 +24,10 @@
            Scope* new_scope)
       : AstExpressionVisitor(stack_limit, initializer),
         old_scope_(old_scope),
-        new_scope_(new_scope) {}
+        new_scope_(new_scope),
+        old_scope_closure_(old_scope->ClosureScope()),
+        new_scope_closure_(new_scope->ClosureScope()) {}
+  ~Rewriter();
 
  private:
   void VisitExpression(Expression* expr) override {}
@@ -29,10 +36,34 @@
   void VisitClassLiteral(ClassLiteral* expr) override;
   void VisitVariableProxy(VariableProxy* expr) override;
 
+  void VisitBlock(Block* stmt) override;
+  void VisitTryCatchStatement(TryCatchStatement* stmt) override;
+  void VisitWithStatement(WithStatement* stmt) override;
+
   Scope* old_scope_;
   Scope* new_scope_;
+  Scope* old_scope_closure_;
+  Scope* new_scope_closure_;
+  std::vector<std::pair<Variable*, int>> temps_;
 };
 
+struct LessThanSecond {
+  bool operator()(const std::pair<Variable*, int>& left,
+                  const std::pair<Variable*, int>& right) {
+    return left.second < right.second;
+  }
+};
+
+Rewriter::~Rewriter() {
+  if (!temps_.empty()) {
+    // Ensure that we add temporaries in the order they appeared in old_scope_.
+    std::sort(temps_.begin(), temps_.end(), LessThanSecond());
+    for (auto var_and_index : temps_) {
+      var_and_index.first->set_scope(new_scope_closure_);
+      new_scope_closure_->AddTemporary(var_and_index.first);
+    }
+  }
+}
 
 void Rewriter::VisitFunctionLiteral(FunctionLiteral* function_literal) {
   function_literal->scope()->ReplaceOuterScope(new_scope_);
@@ -63,9 +94,13 @@
   if (proxy->is_resolved()) {
     Variable* var = proxy->var();
     if (var->mode() != TEMPORARY) return;
-    if (old_scope_->RemoveTemporary(var)) {
-      var->set_scope(new_scope_);
-      new_scope_->AddTemporary(var);
+    // Temporaries are only placed in ClosureScopes.
+    DCHECK_EQ(var->scope(), var->scope()->ClosureScope());
+    // If the temporary is already where it should be, return quickly.
+    if (var->scope() == new_scope_closure_) return;
+    int index = old_scope_closure_->RemoveTemporary(var);
+    if (index >= 0) {
+      temps_.push_back(std::make_pair(var, index));
     }
   } else if (old_scope_->RemoveUnresolved(proxy)) {
     new_scope_->AddUnresolved(proxy);
@@ -73,6 +108,26 @@
 }
 
 
+void Rewriter::VisitBlock(Block* stmt) {
+  if (stmt->scope() != nullptr)
+    stmt->scope()->ReplaceOuterScope(new_scope_);
+  else
+    VisitStatements(stmt->statements());
+}
+
+
+void Rewriter::VisitTryCatchStatement(TryCatchStatement* stmt) {
+  Visit(stmt->try_block());
+  stmt->scope()->ReplaceOuterScope(new_scope_);
+}
+
+
+void Rewriter::VisitWithStatement(WithStatement* stmt) {
+  Visit(stmt->expression());
+  stmt->scope()->ReplaceOuterScope(new_scope_);
+}
+
+
 }  // anonymous namespace
 
 
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h
index dde6b1d..669defa 100644
--- a/src/parsing/parser-base.h
+++ b/src/parsing/parser-base.h
@@ -7,7 +7,7 @@
 
 #include "src/ast/scopes.h"
 #include "src/bailout-reason.h"
-#include "src/hashmap.h"
+#include "src/base/hashmap.h"
 #include "src/messages.h"
 #include "src/parsing/expression-classifier.h"
 #include "src/parsing/func-name-inferrer.h"
@@ -29,6 +29,86 @@
   kDisallowLabelledFunctionStatement,
 };
 
+enum class FunctionBody { Normal, SingleExpression };
+
+enum class ParseFunctionFlags {
+  kIsNormal = 0,
+  kIsGenerator = 1,
+  kIsAsync = 2,
+  kIsDefault = 4
+};
+
+static inline ParseFunctionFlags operator|(ParseFunctionFlags lhs,
+                                           ParseFunctionFlags rhs) {
+  typedef unsigned char T;
+  return static_cast<ParseFunctionFlags>(static_cast<T>(lhs) |
+                                         static_cast<T>(rhs));
+}
+
+static inline ParseFunctionFlags& operator|=(ParseFunctionFlags& lhs,
+                                             const ParseFunctionFlags& rhs) {
+  lhs = lhs | rhs;
+  return lhs;
+}
+
+static inline bool operator&(ParseFunctionFlags bitfield,
+                             ParseFunctionFlags mask) {
+  typedef unsigned char T;
+  return static_cast<T>(bitfield) & static_cast<T>(mask);
+}
+
+enum class MethodKind {
+  Normal = 0,
+  Static = 1 << 0,
+  Generator = 1 << 1,
+  StaticGenerator = Static | Generator,
+  Async = 1 << 2,
+  StaticAsync = Static | Async,
+
+  /* Any non-ordinary method kinds */
+  SpecialMask = Generator | Async
+};
+
+inline bool IsValidMethodKind(MethodKind kind) {
+  return kind == MethodKind::Normal || kind == MethodKind::Static ||
+         kind == MethodKind::Generator || kind == MethodKind::StaticGenerator ||
+         kind == MethodKind::Async || kind == MethodKind::StaticAsync;
+}
+
+static inline MethodKind operator|(MethodKind lhs, MethodKind rhs) {
+  typedef unsigned char T;
+  return static_cast<MethodKind>(static_cast<T>(lhs) | static_cast<T>(rhs));
+}
+
+static inline MethodKind& operator|=(MethodKind& lhs, const MethodKind& rhs) {
+  lhs = lhs | rhs;
+  DCHECK(IsValidMethodKind(lhs));
+  return lhs;
+}
+
+static inline bool operator&(MethodKind bitfield, MethodKind mask) {
+  typedef unsigned char T;
+  return static_cast<T>(bitfield) & static_cast<T>(mask);
+}
+
+inline bool IsNormalMethod(MethodKind kind) {
+  return kind == MethodKind::Normal;
+}
+
+inline bool IsSpecialMethod(MethodKind kind) {
+  return kind & MethodKind::SpecialMask;
+}
+
+inline bool IsStaticMethod(MethodKind kind) {
+  return kind & MethodKind::Static;
+}
+
+inline bool IsGeneratorMethod(MethodKind kind) {
+  return kind & MethodKind::Generator;
+}
+
+inline bool IsAsyncMethod(MethodKind kind) { return kind & MethodKind::Async; }
+
 struct FormalParametersBase {
   explicit FormalParametersBase(Scope* scope) : scope(scope) {}
   Scope* scope;
@@ -98,7 +178,6 @@
              v8::Extension* extension, AstValueFactory* ast_value_factory,
              ParserRecorder* log, typename Traits::Type::Parser this_object)
       : Traits(this_object),
-        parenthesized_function_(false),
         scope_(NULL),
         function_state_(NULL),
         extension_(extension),
@@ -106,6 +185,7 @@
         ast_value_factory_(ast_value_factory),
         log_(log),
         mode_(PARSE_EAGERLY),  // Lazy mode must be set explicitly.
+        parsing_module_(false),
         stack_limit_(stack_limit),
         zone_(zone),
         scanner_(scanner),
@@ -113,13 +193,12 @@
         allow_lazy_(false),
         allow_natives_(false),
         allow_tailcalls_(false),
-        allow_harmony_sloppy_(false),
-        allow_harmony_sloppy_function_(false),
-        allow_harmony_sloppy_let_(false),
         allow_harmony_restrictive_declarations_(false),
         allow_harmony_do_expressions_(false),
-        allow_harmony_function_name_(false),
-        allow_harmony_function_sent_(false) {}
+        allow_harmony_for_in_(false),
+        allow_harmony_function_sent_(false),
+        allow_harmony_async_await_(false),
+        allow_harmony_restrictive_generators_(false) {}
 
 #define ALLOW_ACCESSORS(name)                           \
   bool allow_##name() const { return allow_##name##_; } \
@@ -134,13 +213,12 @@
   ALLOW_ACCESSORS(lazy);
   ALLOW_ACCESSORS(natives);
   ALLOW_ACCESSORS(tailcalls);
-  ALLOW_ACCESSORS(harmony_sloppy);
-  ALLOW_ACCESSORS(harmony_sloppy_function);
-  ALLOW_ACCESSORS(harmony_sloppy_let);
   ALLOW_ACCESSORS(harmony_restrictive_declarations);
   ALLOW_ACCESSORS(harmony_do_expressions);
-  ALLOW_ACCESSORS(harmony_function_name);
+  ALLOW_ACCESSORS(harmony_for_in);
   ALLOW_ACCESSORS(harmony_function_sent);
+  ALLOW_ACCESSORS(harmony_async_await);
+  ALLOW_ACCESSORS(harmony_restrictive_generators);
   SCANNER_ACCESSORS(harmony_exponentiation_operator);
 
 #undef SCANNER_ACCESSORS
@@ -195,6 +273,64 @@
     Scope* scope;
   };
 
+  class TailCallExpressionList {
+   public:
+    explicit TailCallExpressionList(Zone* zone)
+        : zone_(zone), expressions_(0, zone), has_explicit_tail_calls_(false) {}
+
+    const ZoneList<ExpressionT>& expressions() const { return expressions_; }
+    const Scanner::Location& location() const { return loc_; }
+
+    bool has_explicit_tail_calls() const { return has_explicit_tail_calls_; }
+
+    void Swap(TailCallExpressionList& other) {
+      expressions_.Swap(&other.expressions_);
+      std::swap(loc_, other.loc_);
+      std::swap(has_explicit_tail_calls_, other.has_explicit_tail_calls_);
+    }
+
+    void AddImplicitTailCall(ExpressionT expr) {
+      expressions_.Add(expr, zone_);
+    }
+
+    void AddExplicitTailCall(ExpressionT expr, const Scanner::Location& loc) {
+      if (!has_explicit_tail_calls()) {
+        loc_ = loc;
+        has_explicit_tail_calls_ = true;
+      }
+      expressions_.Add(expr, zone_);
+    }
+
+    void Append(const TailCallExpressionList& other) {
+      if (!has_explicit_tail_calls()) {
+        loc_ = other.loc_;
+        has_explicit_tail_calls_ = other.has_explicit_tail_calls_;
+      }
+      expressions_.AddAll(other.expressions_, zone_);
+    }
+
+   private:
+    Zone* zone_;
+    ZoneList<ExpressionT> expressions_;
+    Scanner::Location loc_;
+    bool has_explicit_tail_calls_;
+  };
+
+  // Defines whether tail call expressions are allowed or not.
+  enum class ReturnExprContext {
+    // We are inside return statement which is allowed to contain tail call
+    // expressions. Tail call expressions are allowed.
+    kInsideValidReturnStatement,
+
+    // We are inside a block in which tail call expressions are allowed but
+    // not yet inside a return statement.
+    kInsideValidBlock,
+
+    // Tail call expressions are not allowed in the following blocks.
+    kInsideTryBlock,
+    kInsideForInOfBody,
+  };
+
   class FunctionState BASE_EMBEDDED {
    public:
     FunctionState(FunctionState** function_state_stack, Scope** scope_stack,
@@ -230,6 +366,8 @@
     }
 
     bool is_generator() const { return IsGeneratorFunction(kind_); }
+    bool is_async_function() const { return IsAsyncFunction(kind_); }
+    bool is_resumable() const { return is_generator() || is_async_function(); }
 
     FunctionKind kind() const { return kind_; }
     FunctionState* outer() const { return outer_function_state_; }
@@ -237,7 +375,7 @@
     void set_generator_object_variable(
         typename Traits::Type::GeneratorVariable* variable) {
       DCHECK(variable != NULL);
-      DCHECK(is_generator());
+      DCHECK(is_resumable());
       generator_object_variable_ = variable;
     }
     typename Traits::Type::GeneratorVariable* generator_object_variable()
@@ -247,40 +385,64 @@
 
     typename Traits::Type::Factory* factory() { return factory_; }
 
-    const List<DestructuringAssignment>& destructuring_assignments_to_rewrite()
-        const {
+    const ZoneList<DestructuringAssignment>&
+        destructuring_assignments_to_rewrite() const {
       return destructuring_assignments_to_rewrite_;
     }
 
-    List<ExpressionT>& expressions_in_tail_position() {
-      return expressions_in_tail_position_;
+    TailCallExpressionList& tail_call_expressions() {
+      return tail_call_expressions_;
     }
-    void AddExpressionInTailPosition(ExpressionT expression) {
-      if (collect_expressions_in_tail_position_) {
-        expressions_in_tail_position_.Add(expression);
+    void AddImplicitTailCallExpression(ExpressionT expression) {
+      if (return_expr_context() ==
+          ReturnExprContext::kInsideValidReturnStatement) {
+        tail_call_expressions_.AddImplicitTailCall(expression);
+      }
+    }
+    void AddExplicitTailCallExpression(ExpressionT expression,
+                                       const Scanner::Location& loc) {
+      DCHECK(expression->IsCall());
+      if (return_expr_context() ==
+          ReturnExprContext::kInsideValidReturnStatement) {
+        tail_call_expressions_.AddExplicitTailCall(expression, loc);
       }
     }
 
-    bool collect_expressions_in_tail_position() const {
-      return collect_expressions_in_tail_position_;
+    ZoneList<typename ExpressionClassifier::Error>* GetReportedErrorList() {
+      return &reported_errors_;
     }
-    void set_collect_expressions_in_tail_position(bool collect) {
-      collect_expressions_in_tail_position_ = collect;
+
+    ReturnExprContext return_expr_context() const {
+      return return_expr_context_;
+    }
+    void set_return_expr_context(ReturnExprContext context) {
+      return_expr_context_ = context;
     }
 
     ZoneList<ExpressionT>* non_patterns_to_rewrite() {
       return &non_patterns_to_rewrite_;
     }
 
+    void next_function_is_parenthesized(bool parenthesized) {
+      next_function_is_parenthesized_ = parenthesized;
+    }
+
+    bool this_function_is_parenthesized() const {
+      return this_function_is_parenthesized_;
+    }
+
    private:
     void AddDestructuringAssignment(DestructuringAssignment pair) {
-      destructuring_assignments_to_rewrite_.Add(pair);
+      destructuring_assignments_to_rewrite_.Add(pair, (*scope_stack_)->zone());
     }
 
     V8_INLINE Scope* scope() { return *scope_stack_; }
 
-    void AddNonPatternForRewriting(ExpressionT expr) {
+    void AddNonPatternForRewriting(ExpressionT expr, bool* ok) {
       non_patterns_to_rewrite_.Add(expr, (*scope_stack_)->zone());
+      if (non_patterns_to_rewrite_.length() >=
+          std::numeric_limits<uint16_t>::max())
+        *ok = false;
     }
 
     // Used to assign an index to each literal that needs materialization in
@@ -311,18 +473,70 @@
     Scope** scope_stack_;
     Scope* outer_scope_;
 
-    List<DestructuringAssignment> destructuring_assignments_to_rewrite_;
-    List<ExpressionT> expressions_in_tail_position_;
-    bool collect_expressions_in_tail_position_;
+    ZoneList<DestructuringAssignment> destructuring_assignments_to_rewrite_;
+    TailCallExpressionList tail_call_expressions_;
+    ReturnExprContext return_expr_context_;
     ZoneList<ExpressionT> non_patterns_to_rewrite_;
 
+    ZoneList<typename ExpressionClassifier::Error> reported_errors_;
+
     typename Traits::Type::Factory* factory_;
 
+    // If true, the next (and immediately following) function literal is
+    // preceded by a parenthesis.
+    bool next_function_is_parenthesized_;
+
+    // The value of the parents' next_function_is_parenthesized_, as it applies
+    // to this function. Filled in by constructor.
+    bool this_function_is_parenthesized_;
+
     friend class ParserTraits;
     friend class PreParserTraits;
     friend class Checkpoint;
   };
 
+  // This scope sets current ReturnExprContext to given value.
+  class ReturnExprScope {
+   public:
+    explicit ReturnExprScope(FunctionState* function_state,
+                             ReturnExprContext return_expr_context)
+        : function_state_(function_state),
+          sav_return_expr_context_(function_state->return_expr_context()) {
+      // Don't update context if we are requested to enable tail call
+      // expressions but current block does not allow them.
+      if (return_expr_context !=
+              ReturnExprContext::kInsideValidReturnStatement ||
+          sav_return_expr_context_ == ReturnExprContext::kInsideValidBlock) {
+        function_state->set_return_expr_context(return_expr_context);
+      }
+    }
+    ~ReturnExprScope() {
+      function_state_->set_return_expr_context(sav_return_expr_context_);
+    }
+
+   private:
+    FunctionState* function_state_;
+    ReturnExprContext sav_return_expr_context_;
+  };
+
+  // Collects all return expressions at tail call position in this scope
+  // to a separate list.
+  class CollectExpressionsInTailPositionToListScope {
+   public:
+    CollectExpressionsInTailPositionToListScope(FunctionState* function_state,
+                                                TailCallExpressionList* list)
+        : function_state_(function_state), list_(list) {
+      function_state->tail_call_expressions().Swap(*list_);
+    }
+    ~CollectExpressionsInTailPositionToListScope() {
+      function_state_->tail_call_expressions().Swap(*list_);
+    }
+
+   private:
+    FunctionState* function_state_;
+    TailCallExpressionList* list_;
+  };
+
   // Annoyingly, arrow functions first parse as comma expressions, then when we
   // see the => we have to go back and reinterpret the arguments as being formal
   // parameters.  To do so we need to reset some of the parser state back to
@@ -453,12 +667,13 @@
     Expect(Token::SEMICOLON, ok);
   }
 
-  bool peek_any_identifier() {
-    Token::Value next = peek();
-    return next == Token::IDENTIFIER || next == Token::FUTURE_RESERVED_WORD ||
-           next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET ||
-           next == Token::STATIC || next == Token::YIELD;
+  bool is_any_identifier(Token::Value token) {
+    return token == Token::IDENTIFIER || token == Token::ENUM ||
+           token == Token::AWAIT || token == Token::ASYNC ||
+           token == Token::FUTURE_STRICT_RESERVED_WORD || token == Token::LET ||
+           token == Token::STATIC || token == Token::YIELD;
   }
+  bool peek_any_identifier() { return is_any_identifier(peek()); }
 
   bool CheckContextualKeyword(Vector<const char> keyword) {
     if (PeekContextualKeyword(keyword)) {
@@ -512,6 +727,18 @@
       *ok = false;
     }
   }
+  // for now, this check just collects statistics.
+  void CheckDecimalLiteralWithLeadingZero(int* use_counts, int beg_pos,
+                                          int end_pos) {
+    Scanner::Location token_location =
+        scanner()->decimal_with_leading_zero_position();
+    if (token_location.IsValid() && beg_pos <= token_location.beg_pos &&
+        token_location.end_pos <= end_pos) {
+      scanner()->clear_decimal_with_leading_zero_position();
+      if (use_counts != nullptr)
+        ++use_counts[v8::Isolate::kDecimalWithLeadingZeroInStrictMode];
+    }
+  }
 
   inline void CheckStrictOctalLiteral(int beg_pos, int end_pos, bool* ok) {
     CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kStrictOctalLiteral,
@@ -563,14 +790,10 @@
 
   LanguageMode language_mode() { return scope_->language_mode(); }
   bool is_generator() const { return function_state_->is_generator(); }
-
-  bool allow_const() {
-    return is_strict(language_mode()) || allow_harmony_sloppy();
+  bool is_async_function() const {
+    return function_state_->is_async_function();
   }
-
-  bool allow_let() {
-    return is_strict(language_mode()) || allow_harmony_sloppy_let();
-  }
+  bool is_resumable() const { return function_state_->is_resumable(); }
 
   // Report syntax errors.
   void ReportMessage(MessageTemplate::Template message, const char* arg = NULL,
@@ -627,8 +850,16 @@
 
   void ValidateBindingPattern(const ExpressionClassifier* classifier,
                               bool* ok) {
-    if (!classifier->is_valid_binding_pattern()) {
-      ReportClassifierError(classifier->binding_pattern_error());
+    if (!classifier->is_valid_binding_pattern() ||
+        !classifier->is_valid_async_binding_pattern()) {
+      const Scanner::Location& a = classifier->binding_pattern_error().location;
+      const Scanner::Location& b =
+          classifier->async_binding_pattern_error().location;
+      if (a.beg_pos < 0 || (b.beg_pos >= 0 && a.beg_pos > b.beg_pos)) {
+        ReportClassifierError(classifier->async_binding_pattern_error());
+      } else {
+        ReportClassifierError(classifier->binding_pattern_error());
+      }
       *ok = false;
     }
   }
@@ -655,9 +886,14 @@
     }
   }
 
+  bool IsValidArrowFormalParametersStart(Token::Value token) {
+    return is_any_identifier(token) || token == Token::LPAREN;
+  }
+
   void ValidateArrowFormalParameters(const ExpressionClassifier* classifier,
                                      ExpressionT expr,
-                                     bool parenthesized_formals, bool* ok) {
+                                     bool parenthesized_formals, bool is_async,
+                                     bool* ok) {
     if (classifier->is_valid_binding_pattern()) {
       // A simple arrow formal parameter: IDENTIFIER => BODY.
       if (!this->IsIdentifier(expr)) {
@@ -677,6 +913,12 @@
       ReportClassifierError(error);
       *ok = false;
     }
+    if (is_async && !classifier->is_valid_async_arrow_formal_parameters()) {
+      const typename ExpressionClassifier::Error& error =
+          classifier->async_arrow_formal_parameters_error();
+      ReportClassifierError(error);
+      *ok = false;
+    }
   }
 
   void ValidateLetPattern(const ExpressionClassifier* classifier, bool* ok) {
@@ -686,6 +928,15 @@
     }
   }
 
+  void CheckNoTailCallExpressions(const ExpressionClassifier* classifier,
+                                  bool* ok) {
+    if (FLAG_harmony_explicit_tailcalls &&
+        classifier->has_tail_call_expression()) {
+      ReportClassifierError(classifier->tail_call_expression_error());
+      *ok = false;
+    }
+  }
+
   void ExpressionUnexpectedToken(ExpressionClassifier* classifier) {
     MessageTemplate::Template message = MessageTemplate::kUnexpectedToken;
     const char* arg;
@@ -741,27 +992,40 @@
                                  ExpressionClassifier* classifier, bool* ok);
 
   ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier,
-                                     bool* ok);
+                                     bool* is_async, bool* ok);
+  ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier,
+                                     bool* ok) {
+    bool is_async;
+    return ParsePrimaryExpression(classifier, &is_async, ok);
+  }
   ExpressionT ParseExpression(bool accept_IN, bool* ok);
   ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier,
                               bool* ok);
   ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok);
   ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set,
-                                bool* is_computed_name,
+                                bool* is_await, bool* is_computed_name,
                                 ExpressionClassifier* classifier, bool* ok);
   ExpressionT ParseObjectLiteral(ExpressionClassifier* classifier, bool* ok);
   ObjectLiteralPropertyT ParsePropertyDefinition(
       ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends,
-      bool is_static, bool* is_computed_name, bool* has_seen_constructor,
+      MethodKind kind, bool* is_computed_name, bool* has_seen_constructor,
       ExpressionClassifier* classifier, IdentifierT* name, bool* ok);
   typename Traits::Type::ExpressionList ParseArguments(
+      Scanner::Location* first_spread_pos, bool maybe_arrow,
+      ExpressionClassifier* classifier, bool* ok);
+  typename Traits::Type::ExpressionList ParseArguments(
       Scanner::Location* first_spread_pos, ExpressionClassifier* classifier,
-      bool* ok);
+      bool* ok) {
+    return ParseArguments(first_spread_pos, false, classifier, ok);
+  }
 
   ExpressionT ParseAssignmentExpression(bool accept_IN,
                                         ExpressionClassifier* classifier,
                                         bool* ok);
-  ExpressionT ParseYieldExpression(ExpressionClassifier* classifier, bool* ok);
+  ExpressionT ParseYieldExpression(bool accept_IN,
+                                   ExpressionClassifier* classifier, bool* ok);
+  ExpressionT ParseTailCallExpression(ExpressionClassifier* classifier,
+                                      bool* ok);
   ExpressionT ParseConditionalExpression(bool accept_IN,
                                          ExpressionClassifier* classifier,
                                          bool* ok);
@@ -773,12 +1037,15 @@
   ExpressionT ParseLeftHandSideExpression(ExpressionClassifier* classifier,
                                           bool* ok);
   ExpressionT ParseMemberWithNewPrefixesExpression(
-      ExpressionClassifier* classifier, bool* ok);
-  ExpressionT ParseMemberExpression(ExpressionClassifier* classifier, bool* ok);
+      ExpressionClassifier* classifier, bool* is_async, bool* ok);
+  ExpressionT ParseMemberExpression(ExpressionClassifier* classifier,
+                                    bool* is_async, bool* ok);
   ExpressionT ParseMemberExpressionContinuation(
-      ExpressionT expression, ExpressionClassifier* classifier, bool* ok);
+      ExpressionT expression, bool* is_async, ExpressionClassifier* classifier,
+      bool* ok);
   ExpressionT ParseArrowFunctionLiteral(bool accept_IN,
                                         const FormalParametersT& parameters,
+                                        bool is_async,
                                         const ExpressionClassifier& classifier,
                                         bool* ok);
   ExpressionT ParseTemplateLiteral(ExpressionT tag, int start,
@@ -850,7 +1117,7 @@
     explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {}
 
     virtual void CheckProperty(Token::Value property, PropertyKind type,
-                               bool is_static, bool is_generator, bool* ok) = 0;
+                               MethodKind method_type, bool* ok) = 0;
 
     virtual ~ObjectLiteralCheckerBase() {}
 
@@ -868,8 +1135,8 @@
     explicit ObjectLiteralChecker(ParserBase* parser)
         : ObjectLiteralCheckerBase(parser), has_seen_proto_(false) {}
 
-    void CheckProperty(Token::Value property, PropertyKind type, bool is_static,
-                       bool is_generator, bool* ok) override;
+    void CheckProperty(Token::Value property, PropertyKind type,
+                       MethodKind method_type, bool* ok) override;
 
    private:
     bool IsProto() { return this->scanner()->LiteralMatches("__proto__", 9); }
@@ -883,8 +1150,8 @@
     explicit ClassLiteralChecker(ParserBase* parser)
         : ObjectLiteralCheckerBase(parser), has_seen_constructor_(false) {}
 
-    void CheckProperty(Token::Value property, PropertyKind type, bool is_static,
-                       bool is_generator, bool* ok) override;
+    void CheckProperty(Token::Value property, PropertyKind type,
+                       MethodKind method_type, bool* ok) override;
 
    private:
     bool IsConstructor() {
@@ -897,12 +1164,6 @@
     bool has_seen_constructor_;
   };
 
-  // If true, the next (and immediately following) function literal is
-  // preceded by a parenthesis.
-  // Heuristically that means that the function will be called immediately,
-  // so never lazily compile it.
-  bool parenthesized_function_;
-
   Scope* scope_;                   // Scope stack.
   FunctionState* function_state_;  // Function state stack.
   v8::Extension* extension_;
@@ -910,6 +1171,7 @@
   AstValueFactory* ast_value_factory_;  // Not owned.
   ParserRecorder* log_;
   Mode mode_;
+  bool parsing_module_;
   uintptr_t stack_limit_;
 
  private:
@@ -921,13 +1183,12 @@
   bool allow_lazy_;
   bool allow_natives_;
   bool allow_tailcalls_;
-  bool allow_harmony_sloppy_;
-  bool allow_harmony_sloppy_function_;
-  bool allow_harmony_sloppy_let_;
   bool allow_harmony_restrictive_declarations_;
   bool allow_harmony_do_expressions_;
-  bool allow_harmony_function_name_;
+  bool allow_harmony_for_in_;
   bool allow_harmony_function_sent_;
+  bool allow_harmony_async_await_;
+  bool allow_harmony_restrictive_generators_;
 };
 
 template <class Traits>
@@ -945,11 +1206,21 @@
       outer_function_state_(*function_state_stack),
       scope_stack_(scope_stack),
       outer_scope_(*scope_stack),
-      collect_expressions_in_tail_position_(true),
+      destructuring_assignments_to_rewrite_(16, scope->zone()),
+      tail_call_expressions_(scope->zone()),
+      return_expr_context_(ReturnExprContext::kInsideValidBlock),
       non_patterns_to_rewrite_(0, scope->zone()),
-      factory_(factory) {
+      reported_errors_(16, scope->zone()),
+      factory_(factory),
+      next_function_is_parenthesized_(false),
+      this_function_is_parenthesized_(false) {
   *scope_stack_ = scope;
   *function_state_stack = this;
+  if (outer_function_state_) {
+    this_function_is_parenthesized_ =
+        outer_function_state_->next_function_is_parenthesized_;
+    outer_function_state_->next_function_is_parenthesized_ = false;
+  }
 }
 
 
@@ -979,7 +1250,8 @@
     case Token::IDENTIFIER:
       *message = MessageTemplate::kUnexpectedTokenIdentifier;
       break;
-    case Token::FUTURE_RESERVED_WORD:
+    case Token::AWAIT:
+    case Token::ENUM:
       *message = MessageTemplate::kUnexpectedReserved;
       break;
     case Token::LET:
@@ -1054,7 +1326,8 @@
 ParserBase<Traits>::ParseAndClassifyIdentifier(ExpressionClassifier* classifier,
                                                bool* ok) {
   Token::Value next = Next();
-  if (next == Token::IDENTIFIER) {
+  if (next == Token::IDENTIFIER || next == Token::ASYNC ||
+      (next == Token::AWAIT && !parsing_module_)) {
     IdentifierT name = this->GetSymbol(scanner());
     // When this function is used to read a formal parameter, we don't always
     // know whether the function is going to be strict or sloppy.  Indeed for
@@ -1079,6 +1352,14 @@
             scanner()->location(), MessageTemplate::kStrictEvalArguments);
       }
     }
+    if (this->IsAwait(name)) {
+      if (is_async_function()) {
+        classifier->RecordPatternError(
+            scanner()->location(), MessageTemplate::kAwaitBindingIdentifier);
+      }
+      classifier->RecordAsyncArrowFormalParametersError(
+          scanner()->location(), MessageTemplate::kAwaitBindingIdentifier);
+    }
 
     if (classifier->duplicate_finder() != nullptr &&
         scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) {
@@ -1118,7 +1399,8 @@
 ParserBase<Traits>::ParseIdentifierOrStrictReservedWord(
     bool is_generator, bool* is_strict_reserved, bool* ok) {
   Token::Value next = Next();
-  if (next == Token::IDENTIFIER) {
+  if (next == Token::IDENTIFIER || (next == Token::AWAIT && !parsing_module_) ||
+      next == Token::ASYNC) {
     *is_strict_reserved = false;
   } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET ||
              next == Token::STATIC || (next == Token::YIELD && !is_generator)) {
@@ -1134,13 +1416,13 @@
   return name;
 }
 
-
 template <class Traits>
 typename ParserBase<Traits>::IdentifierT
 ParserBase<Traits>::ParseIdentifierName(bool* ok) {
   Token::Value next = Next();
-  if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD &&
-      next != Token::LET && next != Token::STATIC && next != Token::YIELD &&
+  if (next != Token::IDENTIFIER && next != Token::ASYNC &&
+      next != Token::ENUM && next != Token::AWAIT && next != Token::LET &&
+      next != Token::STATIC && next != Token::YIELD &&
       next != Token::FUTURE_STRICT_RESERVED_WORD &&
       next != Token::ESCAPED_KEYWORD &&
       next != Token::ESCAPED_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) {
@@ -1195,11 +1477,10 @@
 #define DUMMY )  // to make indentation work
 #undef DUMMY
 
-
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
 ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
-                                           bool* ok) {
+                                           bool* is_async, bool* ok) {
   // PrimaryExpression ::
   //   'this'
   //   'null'
@@ -1215,6 +1496,7 @@
   //   '(' Expression ')'
   //   TemplateLiteral
   //   do Block
+  //   AsyncFunctionExpression
 
   int beg_pos = peek_position();
   switch (peek()) {
@@ -1234,10 +1516,21 @@
       BindingPatternUnexpectedToken(classifier);
       return this->ExpressionFromLiteral(Next(), beg_pos, scanner(), factory());
 
+    case Token::ASYNC:
+      if (allow_harmony_async_await() &&
+          !scanner()->HasAnyLineTerminatorAfterNext() &&
+          PeekAhead() == Token::FUNCTION) {
+        Consume(Token::ASYNC);
+        return this->ParseAsyncFunctionExpression(CHECK_OK);
+      }
+      // CoverCallExpressionAndAsyncArrowHead
+      *is_async = true;
+    /* falls through */
     case Token::IDENTIFIER:
     case Token::LET:
     case Token::STATIC:
     case Token::YIELD:
+    case Token::AWAIT:
     case Token::ESCAPED_STRICT_RESERVED_WORD:
     case Token::FUTURE_STRICT_RESERVED_WORD: {
       // Using eval or arguments in this context is OK even in strict mode.
@@ -1274,12 +1567,11 @@
       // Parentheses are not valid on the LHS of a BindingPattern, so we use the
       // is_valid_binding_pattern() check to detect multiple levels of
       // parenthesization.
-      if (!classifier->is_valid_binding_pattern()) {
-        ArrowFormalParametersUnexpectedToken(classifier);
-      }
+      bool pattern_error = !classifier->is_valid_binding_pattern();
       classifier->RecordPatternError(scanner()->peek_location(),
                                      MessageTemplate::kUnexpectedToken,
                                      Token::String(Token::LPAREN));
+      if (pattern_error) ArrowFormalParametersUnexpectedToken(classifier);
       Consume(Token::LPAREN);
       if (Check(Token::RPAREN)) {
         // ()=>x.  The continuation that looks for the => is in
@@ -1297,8 +1589,11 @@
                                           MessageTemplate::kUnexpectedToken,
                                           Token::String(Token::ELLIPSIS));
         classifier->RecordNonSimpleParameter();
-        ExpressionT expr =
-            this->ParseAssignmentExpression(true, classifier, CHECK_OK);
+        ExpressionClassifier binding_classifier(this);
+        ExpressionT expr = this->ParseAssignmentExpression(
+            true, &binding_classifier, CHECK_OK);
+        classifier->Accumulate(&binding_classifier,
+                               ExpressionClassifier::AllProductions);
         if (!this->IsIdentifier(expr) && !IsValidPattern(expr)) {
           classifier->RecordArrowFormalParametersError(
               Scanner::Location(ellipsis_pos, scanner()->location().end_pos),
@@ -1315,7 +1610,8 @@
       }
       // Heuristically try to detect immediately called functions before
       // seeing the call parentheses.
-      parenthesized_function_ = (peek() == Token::FUNCTION);
+      function_state_->next_function_is_parenthesized(peek() ==
+                                                      Token::FUNCTION);
       ExpressionT expr = this->ParseExpression(true, classifier, CHECK_OK);
       Expect(Token::RPAREN, CHECK_OK);
       return expr;
@@ -1324,11 +1620,6 @@
     case Token::CLASS: {
       BindingPatternUnexpectedToken(classifier);
       Consume(Token::CLASS);
-      if (!allow_harmony_sloppy() && is_sloppy(language_mode())) {
-        ReportMessage(MessageTemplate::kSloppyLexical);
-        *ok = false;
-        return this->EmptyExpression();
-      }
       int class_token_position = position();
       IdentifierT name = this->EmptyIdentifier();
       bool is_strict_reserved_name = false;
@@ -1382,7 +1673,6 @@
   return result;
 }
 
-
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression(
     bool accept_IN, ExpressionClassifier* classifier, bool* ok) {
@@ -1390,14 +1680,18 @@
   //   AssignmentExpression
   //   Expression ',' AssignmentExpression
 
-  ExpressionClassifier binding_classifier(this);
-  ExpressionT result =
-      this->ParseAssignmentExpression(accept_IN, &binding_classifier, CHECK_OK);
-  classifier->Accumulate(&binding_classifier,
-                         ExpressionClassifier::AllProductions);
+  ExpressionT result = this->EmptyExpression();
+  {
+    ExpressionClassifier binding_classifier(this);
+    result = this->ParseAssignmentExpression(accept_IN, &binding_classifier,
+                                             CHECK_OK);
+    classifier->Accumulate(&binding_classifier,
+                           ExpressionClassifier::AllProductions);
+  }
   bool is_simple_parameter_list = this->IsIdentifier(result);
   bool seen_rest = false;
   while (peek() == Token::COMMA) {
+    CheckNoTailCallExpressions(classifier, CHECK_OK);
     if (seen_rest) {
       // At this point the production can't possibly be valid, but we don't know
       // which error to signal.
@@ -1416,6 +1710,7 @@
       seen_rest = is_rest = true;
     }
     int pos = position(), expr_pos = peek_position();
+    ExpressionClassifier binding_classifier(this);
     ExpressionT right = this->ParseAssignmentExpression(
         accept_IN, &binding_classifier, CHECK_OK);
     classifier->Accumulate(&binding_classifier,
@@ -1461,6 +1756,7 @@
       int expr_pos = peek_position();
       ExpressionT argument =
           this->ParseAssignmentExpression(true, classifier, CHECK_OK);
+      CheckNoTailCallExpressions(classifier, CHECK_OK);
       elem = factory()->NewSpread(argument, start_pos, expr_pos);
 
       if (first_spread_index < 0) {
@@ -1484,6 +1780,7 @@
     } else {
       int beg_pos = peek_position();
       elem = this->ParseAssignmentExpression(true, classifier, CHECK_OK);
+      CheckNoTailCallExpressions(classifier, CHECK_OK);
       CheckDestructuringElement(elem, classifier, beg_pos,
                                 scanner()->location().end_pos);
     }
@@ -1501,16 +1798,23 @@
                                                   literal_index, pos);
   if (first_spread_index >= 0) {
     result = factory()->NewRewritableExpression(result);
-    Traits::QueueNonPatternForRewriting(result);
+    Traits::QueueNonPatternForRewriting(result, ok);
+    if (!*ok) {
+      // If the non-pattern rewriting mechanism is used in the future for
+      // rewriting other things than spreads, this error message will have
+      // to change.  Also, this error message will never appear while pre-
+      // parsing (this is OK, as it is an implementation limitation).
+      ReportMessage(MessageTemplate::kTooManySpreads);
+      return this->EmptyExpression();
+    }
   }
   return result;
 }
 
-
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParsePropertyName(
-    IdentifierT* name, bool* is_get, bool* is_set, bool* is_computed_name,
-    ExpressionClassifier* classifier, bool* ok) {
+    IdentifierT* name, bool* is_get, bool* is_set, bool* is_await,
+    bool* is_computed_name, ExpressionClassifier* classifier, bool* ok) {
   Token::Value token = peek();
   int pos = peek_position();
 
@@ -1555,6 +1859,9 @@
     default:
       *name = ParseIdentifierName(CHECK_OK);
       scanner()->IsGetOrSet(is_get, is_set);
+      if (this->IsAwait(*name)) {
+        *is_await = true;
+      }
       break;
   }
 
@@ -1564,38 +1871,50 @@
              : factory()->NewStringLiteral(*name, pos);
 }
 
-
 template <class Traits>
 typename ParserBase<Traits>::ObjectLiteralPropertyT
 ParserBase<Traits>::ParsePropertyDefinition(
     ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends,
-    bool is_static, bool* is_computed_name, bool* has_seen_constructor,
+    MethodKind method_kind, bool* is_computed_name, bool* has_seen_constructor,
     ExpressionClassifier* classifier, IdentifierT* name, bool* ok) {
-  DCHECK(!in_class || is_static || has_seen_constructor != nullptr);
+  DCHECK(!in_class || IsStaticMethod(method_kind) ||
+         has_seen_constructor != nullptr);
   ExpressionT value = this->EmptyExpression();
   bool is_get = false;
   bool is_set = false;
+  bool is_await = false;
   bool is_generator = Check(Token::MUL);
+  bool is_async = false;
+  const bool is_static = IsStaticMethod(method_kind);
 
   Token::Value name_token = peek();
+
+  if (is_generator) {
+    method_kind |= MethodKind::Generator;
+  } else if (allow_harmony_async_await() && name_token == Token::ASYNC &&
+             !scanner()->HasAnyLineTerminatorAfterNext() &&
+             PeekAhead() != Token::LPAREN && PeekAhead()) {
+    is_async = true;
+  }
+
   int next_beg_pos = scanner()->peek_location().beg_pos;
   int next_end_pos = scanner()->peek_location().end_pos;
-  ExpressionT name_expression =
-      ParsePropertyName(name, &is_get, &is_set, is_computed_name, classifier,
-                        CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+  ExpressionT name_expression = ParsePropertyName(
+      name, &is_get, &is_set, &is_await, is_computed_name, classifier,
+      CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
 
   if (fni_ != nullptr && !*is_computed_name) {
     this->PushLiteralName(fni_, *name);
   }
 
   if (!in_class && !is_generator) {
-    DCHECK(!is_static);
+    DCHECK(!IsStaticMethod(method_kind));
 
     if (peek() == Token::COLON) {
       // PropertyDefinition
       //    PropertyName ':' AssignmentExpression
       if (!*is_computed_name) {
-        checker->CheckProperty(name_token, kValueProperty, false, false,
+        checker->CheckProperty(name_token, kValueProperty, MethodKind::Normal,
                                CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
       }
       Consume(Token::COLON);
@@ -1605,12 +1924,12 @@
       CheckDestructuringElement(value, classifier, beg_pos,
                                 scanner()->location().end_pos);
 
-      return factory()->NewObjectLiteralProperty(name_expression, value, false,
-                                                 *is_computed_name);
+      return factory()->NewObjectLiteralProperty(name_expression, value,
+                                                 is_static, *is_computed_name);
     }
 
-    if (Token::IsIdentifier(name_token, language_mode(),
-                            this->is_generator()) &&
+    if (Token::IsIdentifier(name_token, language_mode(), this->is_generator(),
+                            parsing_module_) &&
         (peek() == Token::COMMA || peek() == Token::RBRACE ||
          peek() == Token::ASSIGN)) {
       // PropertyDefinition
@@ -1627,7 +1946,17 @@
         classifier->RecordLetPatternError(
             scanner()->location(), MessageTemplate::kLetInLexicalBinding);
       }
-
+      if (is_await) {
+        if (is_async_function()) {
+          classifier->RecordPatternError(
+              Scanner::Location(next_beg_pos, next_end_pos),
+              MessageTemplate::kAwaitBindingIdentifier);
+        } else {
+          classifier->RecordAsyncArrowFormalParametersError(
+              Scanner::Location(next_beg_pos, next_end_pos),
+              MessageTemplate::kAwaitBindingIdentifier);
+        }
+      }
       ExpressionT lhs = this->ExpressionFromIdentifier(
           *name, next_beg_pos, next_end_pos, scope_, factory());
       CheckDestructuringElement(lhs, classifier, next_beg_pos, next_end_pos);
@@ -1647,15 +1976,13 @@
             Scanner::Location(next_beg_pos, scanner()->location().end_pos),
             MessageTemplate::kInvalidCoverInitializedName);
 
-        if (allow_harmony_function_name()) {
-          Traits::SetFunctionNameFromIdentifierRef(rhs, lhs);
-        }
+        Traits::SetFunctionNameFromIdentifierRef(rhs, lhs);
       } else {
         value = lhs;
       }
 
       return factory()->NewObjectLiteralProperty(
-          name_expression, value, ObjectLiteralProperty::COMPUTED, false,
+          name_expression, value, ObjectLiteralProperty::COMPUTED, is_static,
           false);
     }
   }
@@ -1665,20 +1992,32 @@
       Scanner::Location(next_beg_pos, scanner()->location().end_pos),
       MessageTemplate::kInvalidDestructuringTarget);
 
+  if (is_async && !IsSpecialMethod(method_kind)) {
+    DCHECK(!is_get);
+    DCHECK(!is_set);
+    bool dont_care;
+    name_expression = ParsePropertyName(
+        name, &dont_care, &dont_care, &dont_care, is_computed_name, classifier,
+        CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+    method_kind |= MethodKind::Async;
+  }
+
   if (is_generator || peek() == Token::LPAREN) {
     // MethodDefinition
     //    PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
     //    '*' PropertyName '(' StrictFormalParameters ')' '{' FunctionBody '}'
     if (!*is_computed_name) {
-      checker->CheckProperty(name_token, kMethodProperty, is_static,
-                             is_generator,
+      checker->CheckProperty(name_token, kMethodProperty, method_kind,
                              CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
     }
 
-    FunctionKind kind = is_generator ? FunctionKind::kConciseGeneratorMethod
-                                     : FunctionKind::kConciseMethod;
+    FunctionKind kind = is_generator
+                            ? FunctionKind::kConciseGeneratorMethod
+                            : is_async ? FunctionKind::kAsyncConciseMethod
+                                       : FunctionKind::kConciseMethod;
 
-    if (in_class && !is_static && this->IsConstructor(*name)) {
+    if (in_class && !IsStaticMethod(method_kind) &&
+        this->IsConstructor(*name)) {
       *has_seen_constructor = true;
       kind = has_extends ? FunctionKind::kSubclassConstructor
                          : FunctionKind::kBaseConstructor;
@@ -1694,13 +2033,13 @@
                                                is_static, *is_computed_name);
   }
 
-  if (in_class && name_token == Token::STATIC && !is_static) {
+  if (in_class && name_token == Token::STATIC && IsNormalMethod(method_kind)) {
     // ClassElement (static)
     //    'static' MethodDefinition
     *name = this->EmptyIdentifier();
     ObjectLiteralPropertyT property = ParsePropertyDefinition(
-        checker, true, has_extends, true, is_computed_name, nullptr, classifier,
-        name, ok);
+        checker, true, has_extends, MethodKind::Static, is_computed_name,
+        nullptr, classifier, name, ok);
     Traits::RewriteNonPattern(classifier, ok);
     return property;
   }
@@ -1714,12 +2053,11 @@
     name_token = peek();
 
     name_expression = ParsePropertyName(
-        name, &dont_care, &dont_care, is_computed_name, classifier,
+        name, &dont_care, &dont_care, &dont_care, is_computed_name, classifier,
         CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
 
     if (!*is_computed_name) {
-      checker->CheckProperty(name_token, kAccessorProperty, is_static,
-                             is_generator,
+      checker->CheckProperty(name_token, kAccessorProperty, method_kind,
                              CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
     }
 
@@ -1769,13 +2107,12 @@
     FuncNameInferrer::State fni_state(fni_);
 
     const bool in_class = false;
-    const bool is_static = false;
     const bool has_extends = false;
     bool is_computed_name = false;
     IdentifierT name = this->EmptyIdentifier();
     ObjectLiteralPropertyT property = this->ParsePropertyDefinition(
-        &checker, in_class, has_extends, is_static, &is_computed_name, NULL,
-        classifier, &name, CHECK_OK);
+        &checker, in_class, has_extends, MethodKind::Normal, &is_computed_name,
+        NULL, classifier, &name, CHECK_OK);
 
     if (is_computed_name) {
       has_computed_names = true;
@@ -1794,9 +2131,7 @@
 
     if (fni_ != nullptr) fni_->Infer();
 
-    if (allow_harmony_function_name()) {
-      Traits::SetFunctionNameFromPropertyName(property, name);
-    }
+    Traits::SetFunctionNameFromPropertyName(property, name);
   }
   Expect(Token::RBRACE, CHECK_OK);
 
@@ -1809,11 +2144,10 @@
                                      pos);
 }
 
-
 template <class Traits>
 typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments(
-    Scanner::Location* first_spread_arg_loc, ExpressionClassifier* classifier,
-    bool* ok) {
+    Scanner::Location* first_spread_arg_loc, bool maybe_arrow,
+    ExpressionClassifier* classifier, bool* ok) {
   // Arguments ::
   //   '(' (AssignmentExpression)*[','] ')'
 
@@ -1831,7 +2165,11 @@
 
     ExpressionT argument = this->ParseAssignmentExpression(
         true, classifier, CHECK_OK_CUSTOM(NullExpressionList));
-    Traits::RewriteNonPattern(classifier, CHECK_OK_CUSTOM(NullExpressionList));
+    CheckNoTailCallExpressions(classifier, CHECK_OK_CUSTOM(NullExpressionList));
+    if (!maybe_arrow) {
+      Traits::RewriteNonPattern(classifier,
+                                CHECK_OK_CUSTOM(NullExpressionList));
+    }
     if (is_spread) {
       if (!spread_arg.IsValid()) {
         spread_arg.beg_pos = start_pos;
@@ -1868,11 +2206,17 @@
   }
   *first_spread_arg_loc = spread_arg;
 
-  if (spread_arg.IsValid()) {
-    // Unspread parameter sequences are translated into array literals in the
-    // parser. Ensure that the number of materialized literals matches between
-    // the parser and preparser
-    Traits::MaterializeUnspreadArgumentsLiterals(unspread_sequences_count);
+  if (!maybe_arrow || peek() != Token::ARROW) {
+    if (maybe_arrow) {
+      Traits::RewriteNonPattern(classifier,
+                                CHECK_OK_CUSTOM(NullExpressionList));
+    }
+    if (spread_arg.IsValid()) {
+      // Unspread parameter sequences are translated into array literals in the
+      // parser. Ensure that the number of materialized literals matches between
+      // the parser and preparser
+      Traits::MaterializeUnspreadArgumentsLiterals(unspread_sequences_count);
+    }
   }
 
   return result;
@@ -1893,25 +2237,37 @@
   int lhs_beg_pos = peek_position();
 
   if (peek() == Token::YIELD && is_generator()) {
-    return this->ParseYieldExpression(classifier, ok);
+    return this->ParseYieldExpression(accept_IN, classifier, ok);
   }
 
   FuncNameInferrer::State fni_state(fni_);
   ParserBase<Traits>::Checkpoint checkpoint(this);
   ExpressionClassifier arrow_formals_classifier(this,
                                                 classifier->duplicate_finder());
+
+  bool is_async = allow_harmony_async_await() && peek() == Token::ASYNC &&
+                  !scanner()->HasAnyLineTerminatorAfterNext() &&
+                  IsValidArrowFormalParametersStart(PeekAhead());
+
   bool parenthesized_formals = peek() == Token::LPAREN;
-  if (!parenthesized_formals) {
+  if (!is_async && !parenthesized_formals) {
     ArrowFormalParametersUnexpectedToken(&arrow_formals_classifier);
   }
   ExpressionT expression = this->ParseConditionalExpression(
       accept_IN, &arrow_formals_classifier, CHECK_OK);
+
+  if (is_async && peek_any_identifier() && PeekAhead() == Token::ARROW) {
+    // async Identifier => AsyncConciseBody
+    IdentifierT name =
+        ParseAndClassifyIdentifier(&arrow_formals_classifier, CHECK_OK);
+    expression = this->ExpressionFromIdentifier(
+        name, position(), scanner()->location().end_pos, scope_, factory());
+  }
+
   if (peek() == Token::ARROW) {
-    classifier->RecordPatternError(scanner()->peek_location(),
-                                   MessageTemplate::kUnexpectedToken,
-                                   Token::String(Token::ARROW));
+    Scanner::Location arrow_loc = scanner()->peek_location();
     ValidateArrowFormalParameters(&arrow_formals_classifier, expression,
-                                  parenthesized_formals, CHECK_OK);
+                                  parenthesized_formals, is_async, CHECK_OK);
     // This reads strangely, but is correct: it checks whether any
     // sub-expression of the parameter list failed to be a valid formal
     // parameter initializer. Since YieldExpressions are banned anywhere
@@ -1919,9 +2275,11 @@
     // TODO(adamk): Rename "FormalParameterInitializerError" to refer to
     // "YieldExpression", which is its only use.
     ValidateFormalParameterInitializer(&arrow_formals_classifier, ok);
+
     Scanner::Location loc(lhs_beg_pos, scanner()->location().end_pos);
-    Scope* scope =
-        this->NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction);
+    Scope* scope = this->NewScope(scope_, FUNCTION_SCOPE,
+                                  is_async ? FunctionKind::kAsyncArrowFunction
+                                           : FunctionKind::kArrowFunction);
     // Because the arrow's parameters were parsed in the outer scope, any
     // usage flags that might have been triggered there need to be copied
     // to the arrow scope.
@@ -1943,7 +2301,11 @@
           duplicate_loc);
     }
     expression = this->ParseArrowFunctionLiteral(
-        accept_IN, parameters, arrow_formals_classifier, CHECK_OK);
+        accept_IN, parameters, is_async, arrow_formals_classifier, CHECK_OK);
+    arrow_formals_classifier.Discard();
+    classifier->RecordPatternError(arrow_loc,
+                                   MessageTemplate::kUnexpectedToken,
+                                   Token::String(Token::ARROW));
 
     if (fni_ != nullptr) fni_->Infer();
 
@@ -1960,8 +2322,10 @@
   classifier->Accumulate(
       &arrow_formals_classifier,
       ExpressionClassifier::StandardProductions |
-      ExpressionClassifier::FormalParametersProductions |
-      ExpressionClassifier::CoverInitializedNameProduction,
+          ExpressionClassifier::FormalParametersProductions |
+          ExpressionClassifier::CoverInitializedNameProduction |
+          ExpressionClassifier::AsyncArrowFormalParametersProduction |
+          ExpressionClassifier::AsyncBindingPatternProduction,
       false);
 
   if (!Token::IsAssignmentOp(peek())) {
@@ -1974,6 +2338,8 @@
   // Now pending non-pattern expressions must be discarded.
   arrow_formals_classifier.Discard();
 
+  CheckNoTailCallExpressions(classifier, CHECK_OK);
+
   if (IsValidPattern(expression) && peek() == Token::ASSIGN) {
     classifier->ForgiveCoverInitializedNameError();
     ValidateAssignmentPattern(classifier, CHECK_OK);
@@ -1998,10 +2364,13 @@
 
   ExpressionT right =
       this->ParseAssignmentExpression(accept_IN, &rhs_classifier, CHECK_OK);
+  CheckNoTailCallExpressions(&rhs_classifier, CHECK_OK);
   Traits::RewriteNonPattern(&rhs_classifier, CHECK_OK);
   classifier->Accumulate(
-      &rhs_classifier, ExpressionClassifier::ExpressionProductions |
-                       ExpressionClassifier::CoverInitializedNameProduction);
+      &rhs_classifier,
+      ExpressionClassifier::ExpressionProductions |
+          ExpressionClassifier::CoverInitializedNameProduction |
+          ExpressionClassifier::AsyncArrowFormalParametersProduction);
 
   // TODO(1231235): We try to estimate the set of properties set by
   // constructors. We define a new property whenever there is an
@@ -2026,7 +2395,7 @@
     }
   }
 
-  if (op == Token::ASSIGN && allow_harmony_function_name()) {
+  if (op == Token::ASSIGN) {
     Traits::SetFunctionNameFromIdentifierRef(right, expression);
   }
 
@@ -2047,7 +2416,8 @@
 
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
-ParserBase<Traits>::ParseYieldExpression(ExpressionClassifier* classifier,
+ParserBase<Traits>::ParseYieldExpression(bool accept_IN,
+                                         ExpressionClassifier* classifier,
                                          bool* ok) {
   // YieldExpression ::
   //   'yield' ([no line terminator] '*'? AssignmentExpression)?
@@ -2078,7 +2448,7 @@
         if (!delegating) break;
         // Delegating yields require an RHS; fall through.
       default:
-        expression = ParseAssignmentExpression(false, classifier, CHECK_OK);
+        expression = ParseAssignmentExpression(accept_IN, classifier, CHECK_OK);
         Traits::RewriteNonPattern(classifier, CHECK_OK);
         break;
     }
@@ -2096,6 +2466,73 @@
   return yield;
 }
 
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseTailCallExpression(ExpressionClassifier* classifier,
+                                            bool* ok) {
+  // TailCallExpression::
+  //   'continue' MemberExpression  Arguments
+  //   'continue' CallExpression  Arguments
+  //   'continue' MemberExpression  TemplateLiteral
+  //   'continue' CallExpression  TemplateLiteral
+  Expect(Token::CONTINUE, CHECK_OK);
+  int pos = position();
+  int sub_expression_pos = peek_position();
+  ExpressionT expression =
+      this->ParseLeftHandSideExpression(classifier, CHECK_OK);
+  CheckNoTailCallExpressions(classifier, CHECK_OK);
+
+  Scanner::Location loc(pos, scanner()->location().end_pos);
+  if (!expression->IsCall()) {
+    Scanner::Location sub_loc(sub_expression_pos, loc.end_pos);
+    ReportMessageAt(sub_loc, MessageTemplate::kUnexpectedInsideTailCall);
+    *ok = false;
+    return Traits::EmptyExpression();
+  }
+  if (Traits::IsDirectEvalCall(expression)) {
+    Scanner::Location sub_loc(sub_expression_pos, loc.end_pos);
+    ReportMessageAt(sub_loc, MessageTemplate::kUnexpectedTailCallOfEval);
+    *ok = false;
+    return Traits::EmptyExpression();
+  }
+  if (!is_strict(language_mode())) {
+    ReportMessageAt(loc, MessageTemplate::kUnexpectedSloppyTailCall);
+    *ok = false;
+    return Traits::EmptyExpression();
+  }
+  if (is_resumable()) {
+    Scanner::Location sub_loc(sub_expression_pos, loc.end_pos);
+    ReportMessageAt(sub_loc, MessageTemplate::kUnexpectedTailCall);
+    *ok = false;
+    return Traits::EmptyExpression();
+  }
+  ReturnExprContext return_expr_context =
+      function_state_->return_expr_context();
+  if (return_expr_context != ReturnExprContext::kInsideValidReturnStatement) {
+    MessageTemplate::Template msg = MessageTemplate::kNone;
+    switch (return_expr_context) {
+      case ReturnExprContext::kInsideValidReturnStatement:
+        UNREACHABLE();
+        return Traits::EmptyExpression();
+      case ReturnExprContext::kInsideValidBlock:
+        msg = MessageTemplate::kUnexpectedTailCall;
+        break;
+      case ReturnExprContext::kInsideTryBlock:
+        msg = MessageTemplate::kUnexpectedTailCallInTryBlock;
+        break;
+      case ReturnExprContext::kInsideForInOfBody:
+        msg = MessageTemplate::kUnexpectedTailCallInForInOf;
+        break;
+    }
+    ReportMessageAt(loc, msg);
+    *ok = false;
+    return Traits::EmptyExpression();
+  }
+  classifier->RecordTailCallExpressionError(
+      loc, MessageTemplate::kUnexpectedTailCall);
+  function_state_->AddExplicitTailCallExpression(expression, loc);
+  return expression;
+}
 
 // Precedence = 3
 template <class Traits>
@@ -2112,9 +2549,10 @@
   ExpressionT expression =
       this->ParseBinaryExpression(4, accept_IN, classifier, CHECK_OK);
   if (peek() != Token::CONDITIONAL) return expression;
+  CheckNoTailCallExpressions(classifier, CHECK_OK);
   Traits::RewriteNonPattern(classifier, CHECK_OK);
-  ArrowFormalParametersUnexpectedToken(classifier);
   BindingPatternUnexpectedToken(classifier);
+  ArrowFormalParametersUnexpectedToken(classifier);
   Consume(Token::CONDITIONAL);
   // In parsing the first assignment expression in conditional
   // expressions we always accept the 'in' keyword; see ECMA-262,
@@ -2140,6 +2578,7 @@
   for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
     // prec1 >= 4
     while (Precedence(peek(), accept_IN) == prec1) {
+      CheckNoTailCallExpressions(classifier, CHECK_OK);
       Traits::RewriteNonPattern(classifier, CHECK_OK);
       BindingPatternUnexpectedToken(classifier);
       ArrowFormalParametersUnexpectedToken(classifier);
@@ -2150,6 +2589,9 @@
       const int next_prec = is_right_associative ? prec1 : prec1 + 1;
       ExpressionT y =
           ParseBinaryExpression(next_prec, accept_IN, classifier, CHECK_OK);
+      if (op != Token::OR && op != Token::AND) {
+        CheckNoTailCallExpressions(classifier, CHECK_OK);
+      }
       Traits::RewriteNonPattern(classifier, CHECK_OK);
 
       if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos,
@@ -2168,16 +2610,11 @@
           case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
           default: break;
         }
-        if (FLAG_harmony_instanceof && cmp == Token::INSTANCEOF) {
-          x = Traits::RewriteInstanceof(x, y, pos);
-        } else {
-          x = factory()->NewCompareOperation(cmp, x, y, pos);
-          if (cmp != op) {
-            // The comparison was negated - add a NOT.
-            x = factory()->NewUnaryOperation(Token::NOT, x, pos);
-          }
+        x = factory()->NewCompareOperation(cmp, x, y, pos);
+        if (cmp != op) {
+          // The comparison was negated - add a NOT.
+          x = factory()->NewUnaryOperation(Token::NOT, x, pos);
         }
-
       } else if (op == Token::EXP) {
         x = Traits::RewriteExponentiation(x, y, pos);
       } else {
@@ -2205,6 +2642,7 @@
   //   '-' UnaryExpression
   //   '~' UnaryExpression
   //   '!' UnaryExpression
+  //   [+Await] AwaitExpression[?Yield]
 
   Token::Value op = peek();
   if (Token::IsUnaryOp(op)) {
@@ -2214,6 +2652,7 @@
     op = Next();
     int pos = position();
     ExpressionT expression = ParseUnaryExpression(classifier, CHECK_OK);
+    CheckNoTailCallExpressions(classifier, CHECK_OK);
     Traits::RewriteNonPattern(classifier, CHECK_OK);
 
     if (op == Token::DELETE && is_strict(language_mode())) {
@@ -2239,6 +2678,7 @@
     op = Next();
     int beg_pos = peek_position();
     ExpressionT expression = this->ParseUnaryExpression(classifier, CHECK_OK);
+    CheckNoTailCallExpressions(classifier, CHECK_OK);
     expression = this->CheckAndRewriteReferenceExpression(
         expression, beg_pos, scanner()->location().end_pos,
         MessageTemplate::kInvalidLhsInPrefixOp, CHECK_OK);
@@ -2250,6 +2690,42 @@
                                         expression,
                                         position());
 
+  } else if (is_async_function() && peek() == Token::AWAIT) {
+    int beg_pos = peek_position();
+    switch (PeekAhead()) {
+      case Token::RPAREN:
+      case Token::RBRACK:
+      case Token::RBRACE:
+      case Token::ASSIGN:
+      case Token::COMMA: {
+        Next();
+        IdentifierT name = this->GetSymbol(scanner());
+
+        // Possibly async arrow formals --- record ExpressionError just in case.
+        ExpressionUnexpectedToken(classifier);
+        classifier->RecordAsyncBindingPatternError(
+            Scanner::Location(beg_pos, scanner()->location().end_pos),
+            MessageTemplate::kAwaitBindingIdentifier);
+        classifier->RecordAsyncArrowFormalParametersError(
+            Scanner::Location(beg_pos, scanner()->location().end_pos),
+            MessageTemplate::kAwaitBindingIdentifier);
+
+        return this->ExpressionFromIdentifier(
+            name, beg_pos, scanner()->location().end_pos, scope_, factory());
+      }
+      default:
+        break;
+    }
+
+    int await_pos = peek_position();
+    Consume(Token::AWAIT);
+
+    ExpressionT value = ParseUnaryExpression(classifier, CHECK_OK);
+
+    classifier->RecordFormalParameterInitializerError(
+        Scanner::Location(beg_pos, scanner()->location().end_pos),
+        MessageTemplate::kAwaitExpressionFormalParameter);
+    return Traits::RewriteAwaitExpression(value, await_pos);
   } else {
     return this->ParsePostfixExpression(classifier, ok);
   }
@@ -2268,6 +2744,7 @@
       this->ParseLeftHandSideExpression(classifier, CHECK_OK);
   if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
       Token::IsCountOp(peek())) {
+    CheckNoTailCallExpressions(classifier, CHECK_OK);
     BindingPatternUnexpectedToken(classifier);
     ArrowFormalParametersUnexpectedToken(classifier);
 
@@ -2287,7 +2764,6 @@
   return expression;
 }
 
-
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
 ParserBase<Traits>::ParseLeftHandSideExpression(
@@ -2295,12 +2771,18 @@
   // LeftHandSideExpression ::
   //   (NewExpression | MemberExpression) ...
 
-  ExpressionT result =
-      this->ParseMemberWithNewPrefixesExpression(classifier, CHECK_OK);
+  if (FLAG_harmony_explicit_tailcalls && peek() == Token::CONTINUE) {
+    return this->ParseTailCallExpression(classifier, ok);
+  }
+
+  bool is_async = false;
+  ExpressionT result = this->ParseMemberWithNewPrefixesExpression(
+      classifier, &is_async, CHECK_OK);
 
   while (true) {
     switch (peek()) {
       case Token::LBRACK: {
+        CheckNoTailCallExpressions(classifier, CHECK_OK);
         Traits::RewriteNonPattern(classifier, CHECK_OK);
         BindingPatternUnexpectedToken(classifier);
         ArrowFormalParametersUnexpectedToken(classifier);
@@ -2314,13 +2796,13 @@
       }
 
       case Token::LPAREN: {
+        CheckNoTailCallExpressions(classifier, CHECK_OK);
+        int pos;
         Traits::RewriteNonPattern(classifier, CHECK_OK);
         BindingPatternUnexpectedToken(classifier);
-        ArrowFormalParametersUnexpectedToken(classifier);
-
-        int pos;
         if (scanner()->current_token() == Token::IDENTIFIER ||
-            scanner()->current_token() == Token::SUPER) {
+            scanner()->current_token() == Token::SUPER ||
+            scanner()->current_token() == Token::ASYNC) {
           // For call of an identifier we want to report position of
           // the identifier as position of the call in the stack trace.
           pos = position();
@@ -2340,7 +2822,18 @@
         }
         Scanner::Location spread_pos;
         typename Traits::Type::ExpressionList args =
-            ParseArguments(&spread_pos, classifier, CHECK_OK);
+            ParseArguments(&spread_pos, is_async, classifier, CHECK_OK);
+
+        if (V8_UNLIKELY(is_async && peek() == Token::ARROW)) {
+          if (args->length()) {
+            // async ( Arguments ) => ...
+            return Traits::ExpressionListToExpression(args);
+          }
+          // async () => ...
+          return factory()->NewEmptyParentheses(pos);
+        }
+
+        ArrowFormalParametersUnexpectedToken(classifier);
 
         // Keep track of eval() calls since they disable all local variable
         // optimizations.
@@ -2372,6 +2865,7 @@
       }
 
       case Token::PERIOD: {
+        CheckNoTailCallExpressions(classifier, CHECK_OK);
         Traits::RewriteNonPattern(classifier, CHECK_OK);
         BindingPatternUnexpectedToken(classifier);
         ArrowFormalParametersUnexpectedToken(classifier);
@@ -2386,6 +2880,7 @@
 
       case Token::TEMPLATE_SPAN:
       case Token::TEMPLATE_TAIL: {
+        CheckNoTailCallExpressions(classifier, CHECK_OK);
         Traits::RewriteNonPattern(classifier, CHECK_OK);
         BindingPatternUnexpectedToken(classifier);
         ArrowFormalParametersUnexpectedToken(classifier);
@@ -2399,11 +2894,10 @@
   }
 }
 
-
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
 ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(
-    ExpressionClassifier* classifier, bool* ok) {
+    ExpressionClassifier* classifier, bool* is_async, bool* ok) {
   // NewExpression ::
   //   ('new')+ MemberExpression
   //
@@ -2436,7 +2930,8 @@
     } else if (peek() == Token::PERIOD) {
       return ParseNewTargetExpression(CHECK_OK);
     } else {
-      result = this->ParseMemberWithNewPrefixesExpression(classifier, CHECK_OK);
+      result = this->ParseMemberWithNewPrefixesExpression(classifier, is_async,
+                                                          CHECK_OK);
     }
     Traits::RewriteNonPattern(classifier, CHECK_OK);
     if (peek() == Token::LPAREN) {
@@ -2452,8 +2947,8 @@
         result = factory()->NewCallNew(result, args, new_pos);
       }
       // The expression can still continue with . or [ after the arguments.
-      result =
-          this->ParseMemberExpressionContinuation(result, classifier, CHECK_OK);
+      result = this->ParseMemberExpressionContinuation(result, is_async,
+                                                       classifier, CHECK_OK);
       return result;
     }
     // NewExpression without arguments.
@@ -2461,14 +2956,13 @@
                                  new_pos);
   }
   // No 'new' or 'super' keyword.
-  return this->ParseMemberExpression(classifier, ok);
+  return this->ParseMemberExpression(classifier, is_async, ok);
 }
 
-
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
 ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier,
-                                          bool* ok) {
+                                          bool* is_async, bool* ok) {
   // MemberExpression ::
   //   (PrimaryExpression | FunctionLiteral | ClassLiteral)
   //     ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)*
@@ -2525,10 +3019,11 @@
     const bool is_new = false;
     result = ParseSuperExpression(is_new, classifier, CHECK_OK);
   } else {
-    result = ParsePrimaryExpression(classifier, CHECK_OK);
+    result = ParsePrimaryExpression(classifier, is_async, CHECK_OK);
   }
 
-  result = ParseMemberExpressionContinuation(result, classifier, CHECK_OK);
+  result =
+      ParseMemberExpressionContinuation(result, is_async, classifier, CHECK_OK);
   return result;
 }
 
@@ -2595,16 +3090,17 @@
   return this->NewTargetExpression(scope_, factory(), pos);
 }
 
-
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
 ParserBase<Traits>::ParseMemberExpressionContinuation(
-    ExpressionT expression, ExpressionClassifier* classifier, bool* ok) {
+    ExpressionT expression, bool* is_async, ExpressionClassifier* classifier,
+    bool* ok) {
   // Parses this part of MemberExpression:
   // ('[' Expression ']' | '.' Identifier | TemplateLiteral)*
   while (true) {
     switch (peek()) {
       case Token::LBRACK: {
+        *is_async = false;
         Traits::RewriteNonPattern(classifier, CHECK_OK);
         BindingPatternUnexpectedToken(classifier);
         ArrowFormalParametersUnexpectedToken(classifier);
@@ -2621,6 +3117,7 @@
         break;
       }
       case Token::PERIOD: {
+        *is_async = false;
         Traits::RewriteNonPattern(classifier, CHECK_OK);
         BindingPatternUnexpectedToken(classifier);
         ArrowFormalParametersUnexpectedToken(classifier);
@@ -2637,6 +3134,7 @@
       }
       case Token::TEMPLATE_SPAN:
       case Token::TEMPLATE_TAIL: {
+        *is_async = false;
         Traits::RewriteNonPattern(classifier, CHECK_OK);
         BindingPatternUnexpectedToken(classifier);
         ArrowFormalParametersUnexpectedToken(classifier);
@@ -2701,9 +3199,7 @@
     init_classifier.Discard();
     classifier->RecordNonSimpleParameter();
 
-    if (allow_harmony_function_name()) {
-      Traits::SetFunctionNameFromIdentifierRef(initializer, pattern);
-    }
+    Traits::SetFunctionNameFromIdentifierRef(initializer, pattern);
   }
 
   Traits::AddFormalParameter(parameters, pattern, initializer,
@@ -2790,28 +3286,32 @@
 template <class Traits>
 bool ParserBase<Traits>::IsNextLetKeyword() {
   DCHECK(peek() == Token::LET);
-  if (!allow_let()) {
-    return false;
-  }
   Token::Value next_next = PeekAhead();
   switch (next_next) {
     case Token::LBRACE:
     case Token::LBRACK:
     case Token::IDENTIFIER:
     case Token::STATIC:
-    case Token::LET:  // Yes, you can do let let = ... in sloppy mode
+    case Token::LET:  // `let let;` is disallowed by static semantics, but the
+                      // token must be first interpreted as a keyword in order
+                      // for those semantics to apply. This ensures that ASI is
+                      // not honored when a LineTerminator separates the
+                      // tokens.
     case Token::YIELD:
+    case Token::AWAIT:
+    case Token::ASYNC:
       return true;
+    case Token::FUTURE_STRICT_RESERVED_WORD:
+      return is_sloppy(language_mode());
     default:
       return false;
   }
 }
 
-
 template <class Traits>
 typename ParserBase<Traits>::ExpressionT
 ParserBase<Traits>::ParseArrowFunctionLiteral(
-    bool accept_IN, const FormalParametersT& formal_parameters,
+    bool accept_IN, const FormalParametersT& formal_parameters, bool is_async,
     const ExpressionClassifier& formals_classifier, bool* ok) {
   if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) {
     // ASI inserts `;` after arrow parameters if a line terminator is found.
@@ -2828,10 +3328,11 @@
   int expected_property_count = -1;
   Scanner::Location super_loc;
 
+  FunctionKind arrow_kind = is_async ? kAsyncArrowFunction : kArrowFunction;
   {
     typename Traits::Type::Factory function_factory(ast_value_factory());
     FunctionState function_state(&function_state_, &scope_,
-                                 formal_parameters.scope, kArrowFunction,
+                                 formal_parameters.scope, arrow_kind,
                                  &function_factory);
 
     function_state.SkipMaterializedLiterals(
@@ -2857,7 +3358,7 @@
       } else {
         body = this->ParseEagerFunctionBody(
             this->EmptyIdentifier(), RelocInfo::kNoPosition, formal_parameters,
-            kArrowFunction, FunctionLiteral::kAnonymousExpression, CHECK_OK);
+            arrow_kind, FunctionLiteral::kAnonymousExpression, CHECK_OK);
         materialized_literal_count =
             function_state.materialized_literal_count();
         expected_property_count = function_state.expected_property_count();
@@ -2865,20 +3366,31 @@
     } else {
       // Single-expression body
       int pos = position();
-      parenthesized_function_ = false;
-      ExpressionClassifier classifier(this);
-      ExpressionT expression =
-          ParseAssignmentExpression(accept_IN, &classifier, CHECK_OK);
-      Traits::RewriteNonPattern(&classifier, CHECK_OK);
+      DCHECK(ReturnExprContext::kInsideValidBlock ==
+             function_state_->return_expr_context());
+      ReturnExprScope allow_tail_calls(
+          function_state_, ReturnExprContext::kInsideValidReturnStatement);
       body = this->NewStatementList(1, zone());
-      this->AddParameterInitializationBlock(formal_parameters, body, CHECK_OK);
-      body->Add(factory()->NewReturnStatement(expression, pos), zone());
+      this->AddParameterInitializationBlock(formal_parameters, body, is_async,
+                                            CHECK_OK);
+      ExpressionClassifier classifier(this);
+      if (is_async) {
+        this->ParseAsyncArrowSingleExpressionBody(body, accept_IN, &classifier,
+                                                  pos, CHECK_OK);
+        Traits::RewriteNonPattern(&classifier, CHECK_OK);
+      } else {
+        ExpressionT expression =
+            ParseAssignmentExpression(accept_IN, &classifier, CHECK_OK);
+        Traits::RewriteNonPattern(&classifier, CHECK_OK);
+        body->Add(factory()->NewReturnStatement(expression, pos), zone());
+        if (allow_tailcalls() && !is_sloppy(language_mode())) {
+          // ES6 14.6.1 Static Semantics: IsInTailPosition
+          this->MarkTailPosition(expression);
+        }
+      }
       materialized_literal_count = function_state.materialized_literal_count();
       expected_property_count = function_state.expected_property_count();
-      // ES6 14.6.1 Static Semantics: IsInTailPosition
-      if (allow_tailcalls() && !is_sloppy(language_mode())) {
-        this->MarkTailPosition(expression);
-      }
+      this->MarkCollectedTailCallExpressions();
     }
     super_loc = function_state.super_location();
 
@@ -2897,9 +3409,7 @@
       CheckStrictOctalLiteral(formal_parameters.scope->start_position(),
                               scanner()->location().end_pos, CHECK_OK);
     }
-    if (is_strict(language_mode()) || allow_harmony_sloppy()) {
-      this->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK);
-    }
+    this->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK);
 
     Traits::RewriteDestructuringAssignments();
   }
@@ -2909,7 +3419,7 @@
       materialized_literal_count, expected_property_count, num_parameters,
       FunctionLiteral::kNoDuplicateParameters,
       FunctionLiteral::kAnonymousExpression,
-      FunctionLiteral::kShouldLazyCompile, FunctionKind::kArrowFunction,
+      FunctionLiteral::kShouldLazyCompile, arrow_kind,
       formal_parameters.scope->start_position());
 
   function_literal->set_function_token_position(
@@ -2979,6 +3489,7 @@
 
     int expr_pos = peek_position();
     ExpressionT expression = this->ParseExpression(true, classifier, CHECK_OK);
+    CheckNoTailCallExpressions(classifier, CHECK_OK);
     Traits::RewriteNonPattern(classifier, CHECK_OK);
     Traits::AddTemplateExpression(&ts, expression);
 
@@ -3077,13 +3588,12 @@
 #undef CHECK_OK
 #undef CHECK_OK_CUSTOM
 
-
 template <typename Traits>
 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
-    Token::Value property, PropertyKind type, bool is_static, bool is_generator,
+    Token::Value property, PropertyKind type, MethodKind method_type,
     bool* ok) {
-  DCHECK(!is_static);
-  DCHECK(!is_generator || type == kMethodProperty);
+  DCHECK(!IsStaticMethod(method_type));
+  DCHECK(!IsSpecialMethod(method_type) || type == kMethodProperty);
 
   if (property == Token::SMI || property == Token::NUMBER) return;
 
@@ -3098,26 +3608,28 @@
   }
 }
 
-
 template <typename Traits>
 void ParserBase<Traits>::ClassLiteralChecker::CheckProperty(
-    Token::Value property, PropertyKind type, bool is_static, bool is_generator,
+    Token::Value property, PropertyKind type, MethodKind method_type,
     bool* ok) {
   DCHECK(type == kMethodProperty || type == kAccessorProperty);
 
   if (property == Token::SMI || property == Token::NUMBER) return;
 
-  if (is_static) {
+  if (IsStaticMethod(method_type)) {
     if (IsPrototype()) {
       this->parser()->ReportMessage(MessageTemplate::kStaticPrototype);
       *ok = false;
       return;
     }
   } else if (IsConstructor()) {
-    if (is_generator || type == kAccessorProperty) {
+    const bool is_generator = IsGeneratorMethod(method_type);
+    const bool is_async = IsAsyncMethod(method_type);
+    if (is_generator || is_async || type == kAccessorProperty) {
       MessageTemplate::Template msg =
           is_generator ? MessageTemplate::kConstructorIsGenerator
-                       : MessageTemplate::kConstructorIsAccessor;
+                       : is_async ? MessageTemplate::kConstructorIsAsync
+                                  : MessageTemplate::kConstructorIsAccessor;
       this->parser()->ReportMessage(msg);
       *ok = false;
       return;
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
index fa2893b..a39d0ee 100644
--- a/src/parsing/parser.cc
+++ b/src/parsing/parser.cc
@@ -39,7 +39,6 @@
   }
 }
 
-
 ParseInfo::ParseInfo(Zone* zone)
     : zone_(zone),
       flags_(0),
@@ -51,15 +50,14 @@
       unicode_cache_(nullptr),
       stack_limit_(0),
       hash_seed_(0),
+      isolate_(nullptr),
       cached_data_(nullptr),
       ast_value_factory_(nullptr),
       literal_(nullptr),
       scope_(nullptr) {}
 
-
 ParseInfo::ParseInfo(Zone* zone, Handle<JSFunction> function)
     : ParseInfo(zone, Handle<SharedFunctionInfo>(function->shared())) {
-  set_closure(function);
   set_context(Handle<Context>(function->context()));
 }
 
@@ -207,7 +205,16 @@
     body = new (zone()) ZoneList<Statement*>(call_super ? 2 : 1, zone());
     if (call_super) {
       // $super_constructor = %_GetSuperConstructor(<this-function>)
-      // %reflect_construct($super_constructor, arguments, new.target)
+      // %reflect_construct(
+      //     $super_constructor, InternalArray(...args), new.target)
+      auto constructor_args_name = ast_value_factory()->empty_string();
+      bool is_duplicate;
+      bool is_rest = true;
+      bool is_optional = false;
+      Variable* constructor_args =
+          function_scope->DeclareParameter(constructor_args_name, TEMPORARY,
+                                           is_optional, is_rest, &is_duplicate);
+
       ZoneList<Expression*>* args =
           new (zone()) ZoneList<Expression*>(2, zone());
       VariableProxy* this_function_proxy = scope_->NewUnresolved(
@@ -219,10 +226,12 @@
       Expression* super_constructor = factory()->NewCallRuntime(
           Runtime::kInlineGetSuperConstructor, tmp, pos);
       args->Add(super_constructor, zone());
-      VariableProxy* arguments_proxy = scope_->NewUnresolved(
-          factory(), ast_value_factory()->arguments_string(), Variable::NORMAL,
-          pos);
-      args->Add(arguments_proxy, zone());
+      Spread* spread_args = factory()->NewSpread(
+          factory()->NewVariableProxy(constructor_args), pos, pos);
+      ZoneList<Expression*>* spread_args_expr =
+          new (zone()) ZoneList<Expression*>(1, zone());
+      spread_args_expr->Add(spread_args, zone());
+      args->AddAll(*PrepareSpreadArguments(spread_args_expr), zone());
       VariableProxy* new_target_proxy = scope_->NewUnresolved(
           factory(), ast_value_factory()->new_target_string(), Variable::NORMAL,
           pos);
@@ -332,6 +341,10 @@
   return identifier == parser_->ast_value_factory()->undefined_string();
 }
 
+bool ParserTraits::IsAwait(const AstRawString* identifier) const {
+  return identifier == parser_->ast_value_factory()->await_string();
+}
+
 bool ParserTraits::IsPrototype(const AstRawString* identifier) const {
   return identifier == parser_->ast_value_factory()->prototype_string();
 }
@@ -604,8 +617,7 @@
 const AstRawString* ParserTraits::GetNumberAsSymbol(Scanner* scanner) {
   double double_value = parser_->scanner()->DoubleValue();
   char array[100];
-  const char* string =
-      DoubleToCString(double_value, Vector<char>(array, arraysize(array)));
+  const char* string = DoubleToCString(double_value, ArrayVector(array));
   return parser_->ast_value_factory()->GetOneByteString(string);
 }
 
@@ -668,13 +680,14 @@
 Expression* ParserTraits::FunctionSentExpression(Scope* scope,
                                                  AstNodeFactory* factory,
                                                  int pos) {
-  // We desugar function.sent into %GeneratorGetInput(generator).
+  // We desugar function.sent into %_GeneratorGetInputOrDebugPos(generator).
   Zone* zone = parser_->zone();
   ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(1, zone);
   VariableProxy* generator = factory->NewVariableProxy(
       parser_->function_state_->generator_object_variable());
   args->Add(generator, zone);
-  return factory->NewCallRuntime(Runtime::kGeneratorGetInput, args, pos);
+  return factory->NewCallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos,
+                                 args, pos);
 }
 
 
@@ -768,6 +781,10 @@
   expression->MarkTail();
 }
 
+void ParserTraits::MarkCollectedTailCallExpressions() {
+  parser_->MarkCollectedTailCallExpressions();
+}
+
 Parser::Parser(ParseInfo* info)
     : ParserBase<ParserTraits>(info->zone(), &scanner_, info->stack_limit(),
                                info->extension(), info->ast_value_factory(),
@@ -789,16 +806,15 @@
   set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
   set_allow_tailcalls(FLAG_harmony_tailcalls && !info->is_native() &&
                       info->isolate()->is_tail_call_elimination_enabled());
-  set_allow_harmony_sloppy(FLAG_harmony_sloppy);
-  set_allow_harmony_sloppy_function(FLAG_harmony_sloppy_function);
-  set_allow_harmony_sloppy_let(FLAG_harmony_sloppy_let);
   set_allow_harmony_do_expressions(FLAG_harmony_do_expressions);
-  set_allow_harmony_function_name(FLAG_harmony_function_name);
+  set_allow_harmony_for_in(FLAG_harmony_for_in);
   set_allow_harmony_function_sent(FLAG_harmony_function_sent);
   set_allow_harmony_restrictive_declarations(
       FLAG_harmony_restrictive_declarations);
   set_allow_harmony_exponentiation_operator(
       FLAG_harmony_exponentiation_operator);
+  set_allow_harmony_async_await(FLAG_harmony_async_await);
+  set_allow_harmony_restrictive_generators(FLAG_harmony_restrictive_generators);
   for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
        ++feature) {
     use_counts_[feature] = 0;
@@ -821,6 +837,7 @@
   DCHECK(parsing_on_main_thread_);
 
   HistogramTimerScope timer_scope(isolate->counters()->parse(), true);
+  RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::Parse);
   TRACE_EVENT0("v8", "V8.Parse");
   Handle<String> source(String::cast(info->script()->source()));
   isolate->counters()->total_parse_size()->Increment(source->length());
@@ -925,15 +942,16 @@
     FunctionState function_state(&function_state_, &scope_, scope,
                                  kNormalFunction, &function_factory);
 
-    // Don't count the mode in the use counters--give the program a chance
-    // to enable script/module-wide strict mode below.
-    scope_->SetLanguageMode(info->language_mode());
     ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
     bool ok = true;
     int beg_pos = scanner()->location().beg_pos;
-    if (info->is_module()) {
+    parsing_module_ = info->is_module();
+    if (parsing_module_) {
       ParseModuleItemList(body, &ok);
     } else {
+      // Don't count the mode in the use counters--give the program a chance
+      // to enable script-wide strict mode below.
+      scope_->SetLanguageMode(info->language_mode());
       ParseStatementList(body, Token::EOS, &ok);
     }
 
@@ -943,8 +961,10 @@
 
     if (ok && is_strict(language_mode())) {
       CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
+      CheckDecimalLiteralWithLeadingZero(use_counts_, beg_pos,
+                                         scanner()->location().end_pos);
     }
-    if (ok && is_sloppy(language_mode()) && allow_harmony_sloppy_function()) {
+    if (ok && is_sloppy(language_mode())) {
       // TODO(littledan): Function bindings on the global object that modify
       // pre-existing bindings should be made writable, enumerable and
       // nonconfigurable if possible, whereas this code will leave attributes
@@ -984,6 +1004,7 @@
   // It's OK to use the Isolate & counters here, since this function is only
   // called in the main thread.
   DCHECK(parsing_on_main_thread_);
+  RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::ParseLazy);
   HistogramTimerScope timer_scope(isolate->counters()->parse_lazy());
   TRACE_EVENT0("v8", "V8.ParseLazy");
   Handle<String> source(String::cast(info->script()->source()));
@@ -1054,12 +1075,12 @@
     // Parse the function literal.
     Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
     info->set_script_scope(scope);
-    if (!info->closure().is_null()) {
+    if (!info->context().is_null()) {
       // Ok to use Isolate here, since lazy function parsing is only done in the
       // main thread.
       DCHECK(parsing_on_main_thread_);
-      scope = Scope::DeserializeScopeChain(isolate, zone(),
-                                           info->closure()->context(), scope);
+      scope = Scope::DeserializeScopeChain(isolate, zone(), *info->context(),
+                                           scope);
     }
     original_scope_ = scope;
     AstNodeFactory function_factory(ast_value_factory());
@@ -1073,6 +1094,13 @@
     bool ok = true;
 
     if (shared_info->is_arrow()) {
+      bool is_async = allow_harmony_async_await() && shared_info->is_async();
+      if (is_async) {
+        DCHECK(!scanner()->HasAnyLineTerminatorAfterNext());
+        Consume(Token::ASYNC);
+        DCHECK(peek_any_identifier() || peek() == Token::LPAREN);
+      }
+
       // TODO(adamk): We should construct this scope from the ScopeInfo.
       Scope* scope =
           NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction);
@@ -1113,8 +1141,8 @@
         checkpoint.Restore(&formals.materialized_literals_count);
         // Pass `accept_IN=true` to ParseArrowFunctionLiteral --- This should
         // not be observable, or else the preparser would have failed.
-        Expression* expression =
-            ParseArrowFunctionLiteral(true, formals, formals_classifier, &ok);
+        Expression* expression = ParseArrowFunctionLiteral(
+            true, formals, is_async, formals_classifier, &ok);
         if (ok) {
           // Scanning must end at the same position that was recorded
           // previously. If not, parsing has been interrupted due to a stack
@@ -1253,18 +1281,15 @@
   // StatementListItem:
   //    Statement
   //    Declaration
-
-  switch (peek()) {
+  const Token::Value peeked = peek();
+  switch (peeked) {
     case Token::FUNCTION:
-      return ParseFunctionDeclaration(NULL, ok);
+      return ParseHoistableDeclaration(NULL, ok);
     case Token::CLASS:
       Consume(Token::CLASS);
       return ParseClassDeclaration(NULL, ok);
     case Token::CONST:
-      if (allow_const()) {
-        return ParseVariableStatement(kStatementListItem, NULL, ok);
-      }
-      break;
+      return ParseVariableStatement(kStatementListItem, NULL, ok);
     case Token::VAR:
       return ParseVariableStatement(kStatementListItem, NULL, ok);
     case Token::LET:
@@ -1272,6 +1297,13 @@
         return ParseVariableStatement(kStatementListItem, NULL, ok);
       }
       break;
+    case Token::ASYNC:
+      if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION &&
+          !scanner()->HasAnyLineTerminatorAfterNext()) {
+        Consume(Token::ASYNC);
+        return ParseAsyncFunctionDeclaration(NULL, ok);
+      }
+    /* falls through */
     default:
       break;
   }
@@ -1306,7 +1338,6 @@
   //    ModuleItem*
 
   DCHECK(scope_->is_module_scope());
-  RaiseLanguageMode(STRICT);
 
   while (peek() != Token::EOS) {
     Statement* stat = ParseModuleItem(CHECK_OK);
@@ -1367,7 +1398,7 @@
     // Keep track of the first reserved word encountered in case our
     // caller needs to report an error.
     if (!reserved_loc->IsValid() &&
-        !Token::IsIdentifier(name_tok, STRICT, false)) {
+        !Token::IsIdentifier(name_tok, STRICT, false, parsing_module_)) {
       *reserved_loc = scanner()->location();
     }
     const AstRawString* local_name = ParseIdentifierName(CHECK_OK);
@@ -1418,7 +1449,8 @@
     if (CheckContextualKeyword(CStrVector("as"))) {
       local_name = ParseIdentifierName(CHECK_OK);
     }
-    if (!Token::IsIdentifier(scanner()->current_token(), STRICT, false)) {
+    if (!Token::IsIdentifier(scanner()->current_token(), STRICT, false,
+                             parsing_module_)) {
       *ok = false;
       ReportMessage(MessageTemplate::kUnexpectedReserved);
       return NULL;
@@ -1427,7 +1459,7 @@
       ReportMessage(MessageTemplate::kStrictEvalArguments);
       return NULL;
     }
-    VariableProxy* proxy = NewUnresolved(local_name, IMPORT);
+    VariableProxy* proxy = NewUnresolved(local_name, CONST);
     ImportDeclaration* declaration =
         factory()->NewImportDeclaration(proxy, import_name, NULL, scope_, pos);
     Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
@@ -1475,7 +1507,7 @@
   if (tok != Token::MUL && tok != Token::LBRACE) {
     const AstRawString* local_name =
         ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
-    VariableProxy* proxy = NewUnresolved(local_name, IMPORT);
+    VariableProxy* proxy = NewUnresolved(local_name, CONST);
     import_default_declaration = factory()->NewImportDeclaration(
         proxy, ast_value_factory()->default_string(), NULL, scope_, pos);
     Declare(import_default_declaration, DeclarationDescriptor::NORMAL, true,
@@ -1561,7 +1593,10 @@
             pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK);
         result = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
       } else {
-        result = ParseFunctionDeclaration(pos, is_generator, &names, CHECK_OK);
+        result = ParseHoistableDeclaration(
+            pos, is_generator ? ParseFunctionFlags::kIsGenerator
+                              : ParseFunctionFlags::kIsNormal,
+            &names, CHECK_OK);
       }
       break;
     }
@@ -1580,6 +1615,30 @@
       }
       break;
 
+    case Token::ASYNC:
+      if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION &&
+          !scanner()->HasAnyLineTerminatorAfterNext()) {
+        Consume(Token::ASYNC);
+        Consume(Token::FUNCTION);
+        int pos = position();
+        if (peek() == Token::LPAREN) {
+          // AsyncFunctionDeclaration[+Default] ::
+          //   async [no LineTerminator here] function ( FormalParameters ) {
+          //      AsyncFunctionBody
+          //   }
+          default_export = ParseFunctionLiteral(
+              default_string, Scanner::Location::invalid(),
+              kSkipFunctionNameCheck, FunctionKind::kAsyncFunction, pos,
+              FunctionLiteral::kDeclaration, language_mode(), CHECK_OK);
+          result = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
+        } else {
+          result = ParseHoistableDeclaration(pos, ParseFunctionFlags::kIsAsync,
+                                             &names, CHECK_OK);
+        }
+        break;
+      }
+    /* falls through */
+
     default: {
       int pos = peek_position();
       ExpressionClassifier classifier(this);
@@ -1690,7 +1749,7 @@
     }
 
     case Token::FUNCTION:
-      result = ParseFunctionDeclaration(&names, CHECK_OK);
+      result = ParseHoistableDeclaration(&names, CHECK_OK);
       break;
 
     case Token::CLASS:
@@ -1704,6 +1763,14 @@
       result = ParseVariableStatement(kStatementListItem, &names, CHECK_OK);
       break;
 
+    case Token::ASYNC:
+      if (allow_harmony_async_await()) {
+        Consume(Token::ASYNC);
+        result = ParseAsyncFunctionDeclaration(&names, CHECK_OK);
+        break;
+      }
+    /* falls through */
+
     default:
       *ok = false;
       ReportUnexpectedToken(scanner()->current_token());
@@ -1881,6 +1948,7 @@
   DCHECK(proxy->raw_name() != NULL);
   const AstRawString* name = proxy->raw_name();
   VariableMode mode = declaration->mode();
+  DCHECK(IsDeclaredVariableMode(mode) && mode != CONST_LEGACY);
   bool is_function_declaration = declaration->IsFunctionDeclaration();
   if (scope == nullptr) scope = scope_;
   Scope* declaration_scope =
@@ -1912,16 +1980,27 @@
       }
       var = declaration_scope->DeclareLocal(
           name, mode, declaration->initialization(), kind, kNotAssigned);
-    } else if ((IsLexicalVariableMode(mode) ||
-                IsLexicalVariableMode(var->mode())) &&
-               // Lexical bindings may appear for some parameters in sloppy
-               // mode even with --harmony-sloppy off.
-               (is_strict(language_mode()) || allow_harmony_sloppy())) {
+    } else if (IsLexicalVariableMode(mode) ||
+               IsLexicalVariableMode(var->mode())) {
       // Allow duplicate function decls for web compat, see bug 4693.
+      bool duplicate_allowed = false;
       if (is_sloppy(language_mode()) && is_function_declaration &&
           var->is_function()) {
         DCHECK(IsLexicalVariableMode(mode) &&
                IsLexicalVariableMode(var->mode()));
+        // If the duplication is allowed, then the var will show up
+        // in the SloppyBlockFunctionMap and the new FunctionKind
+        // will be a permitted duplicate.
+        FunctionKind function_kind =
+            declaration->AsFunctionDeclaration()->fun()->kind();
+        duplicate_allowed =
+            scope->DeclarationScope()->sloppy_block_function_map()->Lookup(
+                const_cast<AstRawString*>(name), name->hash()) != nullptr &&
+            !IsAsyncFunction(function_kind) &&
+            !(allow_harmony_restrictive_generators() &&
+              IsGeneratorFunction(function_kind));
+      }
+      if (duplicate_allowed) {
         ++use_counts_[v8::Isolate::kSloppyModeBlockScopedFunctionRedefinition];
       } else {
         // The name was declared in this scope before; check for conflicting
@@ -1957,13 +2036,12 @@
     // In a var binding in a sloppy direct eval, pollute the enclosing scope
     // with this new binding by doing the following:
     // The proxy is bound to a lookup variable to force a dynamic declaration
-    // using the DeclareLookupSlot runtime function.
+    // using the DeclareEvalVar or DeclareEvalFunction runtime functions.
     Variable::Kind kind = Variable::NORMAL;
     // TODO(sigurds) figure out if kNotAssigned is OK here
     var = new (zone()) Variable(declaration_scope, name, mode, kind,
                                 declaration->initialization(), kNotAssigned);
     var->AllocateTo(VariableLocation::LOOKUP, -1);
-    var->SetFromEval();
     resolve = true;
   }
 
@@ -1983,17 +2061,9 @@
   // same variable if it is declared several times. This is not a
   // semantic issue as long as we keep the source order, but it may be
   // a performance issue since it may lead to repeated
-  // RuntimeHidden_DeclareLookupSlot calls.
+  // DeclareEvalVar or DeclareEvalFunction calls.
   declaration_scope->AddDeclaration(declaration);
 
-  if (mode == CONST_LEGACY && declaration_scope->is_script_scope()) {
-    // For global const variables we bind the proxy to a variable.
-    DCHECK(resolve);  // should be set by all callers
-    Variable::Kind kind = Variable::NORMAL;
-    var = new (zone()) Variable(declaration_scope, name, mode, kind,
-                                kNeedsInitialization, kNotAssigned);
-  }
-
   // If requested and we have a local variable, bind the proxy to the variable
   // at parse-time. This is used for functions (and consts) declared inside
   // statements: the corresponding function (or const) variable must be in the
@@ -2069,17 +2139,33 @@
 }
 
 
-Statement* Parser::ParseFunctionDeclaration(
+Statement* Parser::ParseHoistableDeclaration(
     ZoneList<const AstRawString*>* names, bool* ok) {
   Expect(Token::FUNCTION, CHECK_OK);
   int pos = position();
-  bool is_generator = Check(Token::MUL);
-  return ParseFunctionDeclaration(pos, is_generator, names, ok);
+  ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
+  if (Check(Token::MUL)) {
+    flags |= ParseFunctionFlags::kIsGenerator;
+  }
+  return ParseHoistableDeclaration(pos, flags, names, ok);
 }
 
+Statement* Parser::ParseAsyncFunctionDeclaration(
+    ZoneList<const AstRawString*>* names, bool* ok) {
+  DCHECK_EQ(scanner()->current_token(), Token::ASYNC);
+  int pos = position();
+  if (scanner()->HasAnyLineTerminatorBeforeNext()) {
+    *ok = false;
+    ReportUnexpectedToken(scanner()->current_token());
+    return nullptr;
+  }
+  Expect(Token::FUNCTION, CHECK_OK);
+  ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync;
+  return ParseHoistableDeclaration(pos, flags, names, ok);
+}
 
-Statement* Parser::ParseFunctionDeclaration(
-    int pos, bool is_generator, ZoneList<const AstRawString*>* names,
+Statement* Parser::ParseHoistableDeclaration(
+    int pos, ParseFunctionFlags flags, ZoneList<const AstRawString*>* names,
     bool* ok) {
   // FunctionDeclaration ::
   //   'function' Identifier '(' FormalParameters ')' '{' FunctionBody '}'
@@ -2087,10 +2173,21 @@
   //   'function' '*' Identifier '(' FormalParameters ')' '{' FunctionBody '}'
   //
   // 'function' and '*' (if present) have been consumed by the caller.
+  const bool is_generator = flags & ParseFunctionFlags::kIsGenerator;
+  const bool is_async = flags & ParseFunctionFlags::kIsAsync;
+  DCHECK(!is_generator || !is_async);
+
   bool is_strict_reserved = false;
   const AstRawString* name = ParseIdentifierOrStrictReservedWord(
       &is_strict_reserved, CHECK_OK);
 
+  if (V8_UNLIKELY(is_async_function() && this->IsAwait(name))) {
+    ReportMessageAt(scanner()->location(),
+                    MessageTemplate::kAwaitBindingIdentifier);
+    *ok = false;
+    return nullptr;
+  }
+
   FuncNameInferrer::State fni_state(fni_);
   if (fni_ != NULL) fni_->PushEnclosingName(name);
   FunctionLiteral* fun = ParseFunctionLiteral(
@@ -2098,7 +2195,8 @@
       is_strict_reserved ? kFunctionNameIsStrictReserved
                          : kFunctionNameValidityUnknown,
       is_generator ? FunctionKind::kGeneratorFunction
-                   : FunctionKind::kNormalFunction,
+                   : is_async ? FunctionKind::kAsyncFunction
+                              : FunctionKind::kNormalFunction,
       pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK);
 
   // Even if we're not at the top-level of the global or a function
@@ -2107,18 +2205,21 @@
   // In ES6, a function behaves as a lexical binding, except in
   // a script scope, or the initial scope of eval or another function.
   VariableMode mode =
-      (is_strict(language_mode()) || allow_harmony_sloppy_function()) &&
-      !scope_->is_declaration_scope()
-          ? LET
-          : VAR;
+      (!scope_->is_declaration_scope() || scope_->is_module_scope()) ? LET
+                                                                     : VAR;
   VariableProxy* proxy = NewUnresolved(name, mode);
   Declaration* declaration =
       factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
   Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
   if (names) names->Add(name, zone());
   EmptyStatement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
-  if (is_sloppy(language_mode()) && allow_harmony_sloppy_function() &&
-      !scope_->is_declaration_scope()) {
+  // Async functions don't undergo sloppy mode block scoped hoisting, and don't
+  // allow duplicates in a block. Both are represented by the
+  // sloppy_block_function_map. Don't add them to the map for async functions.
+  // Generators are also supposed to be prohibited; currently doing this behind
+  // a flag and UseCounting violations to assess web compatibility.
+  if (is_sloppy(language_mode()) && !scope_->is_declaration_scope() &&
+      !is_async && !(allow_harmony_restrictive_generators() && is_generator)) {
     SloppyBlockFunctionStatement* delegate =
         factory()->NewSloppyBlockFunctionStatement(empty, scope_);
     scope_->DeclarationScope()->sloppy_block_function_map()->Declare(name,
@@ -2146,12 +2247,6 @@
   //
   // so rewrite it as such.
 
-  if (!allow_harmony_sloppy() && is_sloppy(language_mode())) {
-    ReportMessage(MessageTemplate::kSloppyLexical);
-    *ok = false;
-    return NULL;
-  }
-
   int pos = position();
   bool is_strict_reserved = false;
   const AstRawString* name =
@@ -2282,12 +2377,11 @@
 
   if (peek() == Token::VAR) {
     Consume(Token::VAR);
-  } else if (peek() == Token::CONST && allow_const()) {
+  } else if (peek() == Token::CONST) {
     Consume(Token::CONST);
-    DCHECK(is_strict(language_mode()) || allow_harmony_sloppy());
     DCHECK(var_context != kStatement);
     parsing_result->descriptor.mode = CONST;
-  } else if (peek() == Token::LET && allow_let()) {
+  } else if (peek() == Token::LET) {
     Consume(Token::LET);
     DCHECK(var_context != kStatement);
     parsing_result->descriptor.mode = LET;
@@ -2349,9 +2443,7 @@
         }
       }
 
-      if (allow_harmony_function_name()) {
-        ParserTraits::SetFunctionNameFromIdentifierRef(value, pattern);
-      }
+      ParserTraits::SetFunctionNameFromIdentifierRef(value, pattern);
 
       // End position of the initializer is after the assignment expression.
       initializer_position = scanner()->location().end_pos;
@@ -2370,9 +2462,8 @@
           return nullptr;
         }
 
-        // 'let x' and (legacy) 'const x' initialize 'x' to undefined.
-        if (parsing_result->descriptor.mode == LET ||
-            parsing_result->descriptor.mode == CONST_LEGACY) {
+        // 'let x' initializes 'x' to undefined.
+        if (parsing_result->descriptor.mode == LET) {
           value = GetLiteralUndefined(position());
         }
       }
@@ -2419,6 +2510,23 @@
   return false;
 }
 
+Statement* Parser::ParseFunctionDeclaration(bool* ok) {
+  Consume(Token::FUNCTION);
+  int pos = position();
+  ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
+  if (Check(Token::MUL)) {
+    flags |= ParseFunctionFlags::kIsGenerator;
+    if (allow_harmony_restrictive_declarations()) {
+      ParserTraits::ReportMessageAt(scanner()->location(),
+                                    MessageTemplate::kGeneratorInLegacyContext);
+      *ok = false;
+      return nullptr;
+    }
+  }
+
+  return ParseHoistableDeclaration(pos, flags, nullptr, CHECK_OK);
+}
+
 Statement* Parser::ParseExpressionOrLabelledStatement(
     ZoneList<const AstRawString*>* labels,
     AllowLabelledFunctionStatement allow_function, bool* ok) {
@@ -2439,7 +2547,6 @@
       ReportUnexpectedToken(Next());
       *ok = false;
       return nullptr;
-
     default:
       break;
   }
@@ -2475,7 +2582,7 @@
     // ES#sec-labelled-function-declarations Labelled Function Declarations
     if (peek() == Token::FUNCTION && is_sloppy(language_mode())) {
       if (allow_function == kAllowLabelledFunctionStatement) {
-        return ParseFunctionDeclaration(labels, ok);
+        return ParseFunctionDeclaration(ok);
       } else {
         return ParseScopedStatement(labels, true, ok);
       }
@@ -2496,15 +2603,6 @@
   }
 
   // Parsed expression statement, followed by semicolon.
-  // Detect attempts at 'let' declarations in sloppy mode.
-  if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER &&
-      expr->AsVariableProxy() != NULL &&
-      expr->AsVariableProxy()->raw_name() ==
-          ast_value_factory()->let_string()) {
-    ReportMessage(MessageTemplate::kSloppyLexical, NULL);
-    *ok = false;
-    return NULL;
-  }
   ExpectSemicolon(CHECK_OK);
   return factory()->NewExpressionStatement(expr, pos);
 }
@@ -2624,9 +2722,13 @@
     }
   } else {
     int pos = peek_position();
-    return_value = ParseExpression(true, CHECK_OK);
 
     if (IsSubclassConstructor(function_state_->kind())) {
+      // Because of the return code rewriting that happens in case of a subclass
+      // constructor we don't want to accept tail calls, therefore we don't set
+      // ReturnExprScope to kInsideValidReturnStatement here.
+      return_value = ParseExpression(true, CHECK_OK);
+
       // For subclass constructors we need to return this in case of undefined
       // return a Smi (transformed into an exception in the ConstructStub)
       // for a non object.
@@ -2651,7 +2753,7 @@
       Expression* is_spec_object_call = factory()->NewCallRuntime(
           Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);
 
-      // %_IsJSReceiver(temp) ? temp : throw_expression
+      // %_IsJSReceiver(temp) ? temp : 1;
       Expression* is_object_conditional = factory()->NewConditional(
           is_spec_object_call, factory()->NewVariableProxy(temp),
           factory()->NewSmiLiteral(1, pos), pos);
@@ -2665,17 +2767,23 @@
       return_value = factory()->NewConditional(
           is_undefined, ThisExpression(scope_, factory(), pos),
           is_object_conditional, pos);
-    }
+    } else {
+      ReturnExprScope maybe_allow_tail_calls(
+          function_state_, ReturnExprContext::kInsideValidReturnStatement);
+      return_value = ParseExpression(true, CHECK_OK);
 
-    // ES6 14.6.1 Static Semantics: IsInTailPosition
-    if (allow_tailcalls() && !is_sloppy(language_mode())) {
-      function_state_->AddExpressionInTailPosition(return_value);
+      if (allow_tailcalls() && !is_sloppy(language_mode()) && !is_resumable()) {
+        // ES6 14.6.1 Static Semantics: IsInTailPosition
+        function_state_->AddImplicitTailCallExpression(return_value);
+      }
     }
   }
   ExpectSemicolon(CHECK_OK);
 
   if (is_generator()) {
     return_value = BuildIteratorResult(return_value, true);
+  } else if (is_async_function()) {
+    return_value = BuildPromiseResolve(return_value, return_value->position());
   }
 
   result = factory()->NewReturnStatement(return_value, loc.beg_pos);
@@ -2849,40 +2957,6 @@
       factory()->NewThrow(exception, pos), pos);
 }
 
-class Parser::DontCollectExpressionsInTailPositionScope {
- public:
-  DontCollectExpressionsInTailPositionScope(
-      Parser::FunctionState* function_state)
-      : function_state_(function_state),
-        old_value_(function_state->collect_expressions_in_tail_position()) {
-    function_state->set_collect_expressions_in_tail_position(false);
-  }
-  ~DontCollectExpressionsInTailPositionScope() {
-    function_state_->set_collect_expressions_in_tail_position(old_value_);
-  }
-
- private:
-  Parser::FunctionState* function_state_;
-  bool old_value_;
-};
-
-// Collects all return expressions at tail call position in this scope
-// to a separate list.
-class Parser::CollectExpressionsInTailPositionToListScope {
- public:
-  CollectExpressionsInTailPositionToListScope(
-      Parser::FunctionState* function_state, List<Expression*>* list)
-      : function_state_(function_state), list_(list) {
-    function_state->expressions_in_tail_position().Swap(list_);
-  }
-  ~CollectExpressionsInTailPositionToListScope() {
-    function_state_->expressions_in_tail_position().Swap(list_);
-  }
-
- private:
-  Parser::FunctionState* function_state_;
-  List<Expression*>* list_;
-};
 
 TryStatement* Parser::ParseTryStatement(bool* ok) {
   // TryStatement ::
@@ -2901,7 +2975,8 @@
 
   Block* try_block;
   {
-    DontCollectExpressionsInTailPositionScope no_tail_calls(function_state_);
+    ReturnExprScope no_tail_calls(function_state_,
+                                  ReturnExprContext::kInsideTryBlock);
     try_block = ParseBlock(NULL, CHECK_OK);
   }
 
@@ -2915,7 +2990,7 @@
   Scope* catch_scope = NULL;
   Variable* catch_variable = NULL;
   Block* catch_block = NULL;
-  List<Expression*> expressions_in_tail_position_in_catch_block;
+  TailCallExpressionList tail_call_expressions_in_catch_block(zone());
   if (tok == Token::CATCH) {
     Consume(Token::CATCH);
 
@@ -2923,40 +2998,40 @@
     catch_scope = NewScope(scope_, CATCH_SCOPE);
     catch_scope->set_start_position(scanner()->location().beg_pos);
 
-    ExpressionClassifier pattern_classifier(this);
-    Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
-    ValidateBindingPattern(&pattern_classifier, CHECK_OK);
-
-    const AstRawString* name = ast_value_factory()->dot_catch_string();
-    bool is_simple = pattern->IsVariableProxy();
-    if (is_simple) {
-      auto proxy = pattern->AsVariableProxy();
-      scope_->RemoveUnresolved(proxy);
-      name = proxy->raw_name();
-    }
-
-    catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized,
-                                               Variable::NORMAL);
-
-    Expect(Token::RPAREN, CHECK_OK);
-
     {
       CollectExpressionsInTailPositionToListScope
-          collect_expressions_in_tail_position_scope(
-              function_state_, &expressions_in_tail_position_in_catch_block);
+          collect_tail_call_expressions_scope(
+              function_state_, &tail_call_expressions_in_catch_block);
       BlockState block_state(&scope_, catch_scope);
 
-      // TODO(adamk): Make a version of ParseBlock that takes a scope and
-      // a block.
       catch_block =
           factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition);
-      Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
 
+      // Create a block scope to hold any lexical declarations created
+      // as part of destructuring the catch parameter.
+      Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
       block_scope->set_start_position(scanner()->location().beg_pos);
       {
         BlockState block_state(&scope_, block_scope);
         Target target(&this->target_stack_, catch_block);
 
+        ExpressionClassifier pattern_classifier(this);
+        Expression* pattern =
+            ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
+        ValidateBindingPattern(&pattern_classifier, CHECK_OK);
+
+        const AstRawString* name = ast_value_factory()->dot_catch_string();
+        bool is_simple = pattern->IsVariableProxy();
+        if (is_simple) {
+          auto proxy = pattern->AsVariableProxy();
+          scope_->RemoveUnresolved(proxy);
+          name = proxy->raw_name();
+        }
+        catch_variable = catch_scope->DeclareLocal(
+            name, VAR, kCreatedInitialized, Variable::NORMAL);
+
+        Expect(Token::RPAREN, CHECK_OK);
+
         if (!is_simple) {
           DeclarationDescriptor descriptor;
           descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
@@ -2967,8 +3042,11 @@
           descriptor.declaration_pos = pattern->position();
           descriptor.initialization_pos = pattern->position();
 
+          // Initializer position for variables declared by the pattern.
+          const int initializer_position = position();
+
           DeclarationParsingResult::Declaration decl(
-              pattern, pattern->position(),
+              pattern, initializer_position,
               factory()->NewVariableProxy(catch_variable));
 
           Block* init_block =
@@ -2978,6 +3056,8 @@
           catch_block->statements()->Add(init_block, zone());
         }
 
+        // TODO(adamk): This should call ParseBlock in order to properly
+        // add an additional block scope for the catch body.
         Expect(Token::LBRACE, CHECK_OK);
         while (peek() != Token::RBRACE) {
           Statement* stat = ParseStatementListItem(CHECK_OK);
@@ -3023,14 +3103,23 @@
   if (catch_block != NULL) {
     // For a try-catch construct append return expressions from the catch block
     // to the list of return expressions.
-    function_state_->expressions_in_tail_position().AddAll(
-        expressions_in_tail_position_in_catch_block);
+    function_state_->tail_call_expressions().Append(
+        tail_call_expressions_in_catch_block);
 
     DCHECK(finally_block == NULL);
     DCHECK(catch_scope != NULL && catch_variable != NULL);
     result = factory()->NewTryCatchStatement(try_block, catch_scope,
                                              catch_variable, catch_block, pos);
   } else {
+    if (FLAG_harmony_explicit_tailcalls &&
+        tail_call_expressions_in_catch_block.has_explicit_tail_calls()) {
+      // TODO(ishell): update chapter number.
+      // ES8 XX.YY.ZZ
+      ReportMessageAt(tail_call_expressions_in_catch_block.location(),
+                      MessageTemplate::kUnexpectedTailCallInCatchBlock);
+      *ok = false;
+      return NULL;
+    }
     DCHECK(finally_block != NULL);
     result = factory()->NewTryFinallyStatement(try_block, finally_block, pos);
   }
@@ -3125,11 +3214,10 @@
 
 void Parser::InitializeForEachStatement(ForEachStatement* stmt,
                                         Expression* each, Expression* subject,
-                                        Statement* body) {
+                                        Statement* body, int each_keyword_pos) {
   ForOfStatement* for_of = stmt->AsForOfStatement();
   if (for_of != NULL) {
-    InitializeForOfStatement(for_of, each, subject, body,
-                             RelocInfo::kNoPosition);
+    InitializeForOfStatement(for_of, each, subject, body, each_keyword_pos);
   } else {
     if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
       Variable* temp =
@@ -3148,13 +3236,13 @@
       body = block;
       each = factory()->NewVariableProxy(temp);
     }
-    stmt->Initialize(each, subject, body);
+    stmt->AsForInStatement()->Initialize(each, subject, body);
   }
 }
 
 void Parser::InitializeForOfStatement(ForOfStatement* for_of, Expression* each,
                                       Expression* iterable, Statement* body,
-                                      int iterable_pos) {
+                                      int next_result_pos) {
   Variable* iterator =
       scope_->NewTemporary(ast_value_factory()->dot_iterator_string());
   Variable* result =
@@ -3165,14 +3253,7 @@
   Expression* result_done;
   Expression* assign_each;
 
-  // Hackily disambiguate o from o.next and o [Symbol.iterator]().
-  // TODO(verwaest): Come up with a better solution.
-  int get_iterator_pos = iterable_pos != RelocInfo::kNoPosition
-                             ? iterable_pos
-                             : iterable->position() - 2;
-  int next_result_pos = iterable_pos != RelocInfo::kNoPosition
-                            ? iterable_pos
-                            : iterable->position() - 1;
+  int get_iterator_pos = iterable->position();
 
   // iterator = iterable[Symbol.iterator]()
   assign_iterator = factory()->NewAssignment(
@@ -3212,8 +3293,8 @@
     }
   }
 
-  for_of->Initialize(each, iterable, body, iterator, assign_iterator,
-                     next_result, result_done, assign_each);
+  for_of->Initialize(body, iterator, assign_iterator, next_result, result_done,
+                     assign_each);
 }
 
 Statement* Parser::DesugarLexicalBindingsInForStatement(
@@ -3476,9 +3557,10 @@
     // Make a block around the statement for a lexical binding
     // is introduced by a FunctionDeclaration.
     Scope* body_scope = NewScope(scope_, BLOCK_SCOPE);
+    body_scope->set_start_position(scanner()->location().beg_pos);
     BlockState block_state(&scope_, body_scope);
     Block* block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
-    Statement* body = ParseFunctionDeclaration(NULL, CHECK_OK);
+    Statement* body = ParseFunctionDeclaration(CHECK_OK);
     block->statements()->Add(body, zone());
     body_scope->set_end_position(scanner()->location().end_pos);
     body_scope = body_scope->FinalizeBlockScope();
@@ -3500,10 +3582,10 @@
   Expect(Token::FOR, CHECK_OK);
   Expect(Token::LPAREN, CHECK_OK);
   for_scope->set_start_position(scanner()->location().beg_pos);
-  bool is_let_identifier_expression = false;
+  for_scope->set_is_hidden();
   DeclarationParsingResult parsing_result;
   if (peek() != Token::SEMICOLON) {
-    if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) ||
+    if (peek() == Token::VAR || peek() == Token::CONST ||
         (peek() == Token::LET && IsNextLetKeyword())) {
       ParseVariableDeclarations(kForStatement, &parsing_result, nullptr,
                                 CHECK_OK);
@@ -3527,7 +3609,12 @@
         if (parsing_result.first_initializer_loc.IsValid() &&
             (is_strict(language_mode()) || mode == ForEachStatement::ITERATE ||
              IsLexicalVariableMode(parsing_result.descriptor.mode) ||
-             !decl.pattern->IsVariableProxy())) {
+             !decl.pattern->IsVariableProxy() || allow_harmony_for_in())) {
+          // Only increment the use count if we would have let this through
+          // without the flag.
+          if (allow_harmony_for_in()) {
+            ++use_counts_[v8::Isolate::kForInInitializer];
+          }
           ParserTraits::ReportMessageAt(
               parsing_result.first_initializer_loc,
               MessageTemplate::kForInOfLoopInitializer,
@@ -3541,6 +3628,7 @@
         // special case for legacy for (var/const x =.... in)
         if (!IsLexicalVariableMode(parsing_result.descriptor.mode) &&
             decl.pattern->IsVariableProxy() && decl.initializer != nullptr) {
+          DCHECK(!allow_harmony_for_in());
           ++use_counts_[v8::Isolate::kForInInitializer];
           const AstRawString* name =
               decl.pattern->AsVariableProxy()->raw_name();
@@ -3579,6 +3667,8 @@
             factory()->NewForEachStatement(mode, labels, stmt_pos);
         Target target(&this->target_stack_, loop);
 
+        int each_keyword_position = scanner()->location().beg_pos;
+
         Expression* enumerable;
         if (mode == ForEachStatement::ITERATE) {
           ExpressionClassifier classifier(this);
@@ -3597,8 +3687,8 @@
             factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
 
         {
-          DontCollectExpressionsInTailPositionScope no_tail_calls(
-              function_state_);
+          ReturnExprScope no_tail_calls(function_state_,
+                                        ReturnExprContext::kInsideForInOfBody);
           BlockState block_state(&scope_, body_scope);
 
           Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
@@ -3622,7 +3712,8 @@
           body_block->statements()->Add(body, zone());
           VariableProxy* temp_proxy =
               factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
-          InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
+          InitializeForEachStatement(loop, temp_proxy, enumerable, body_block,
+                                     each_keyword_position);
         }
         body_scope->set_end_position(scanner()->location().end_pos);
         body_scope = body_scope->FinalizeBlockScope();
@@ -3678,10 +3769,6 @@
       Expression* expression = ParseExpression(false, &classifier, CHECK_OK);
       int lhs_end_pos = scanner()->location().end_pos;
       ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE;
-      is_let_identifier_expression =
-          expression->IsVariableProxy() &&
-          expression->AsVariableProxy()->raw_name() ==
-              ast_value_factory()->let_string();
 
       bool is_for_each = CheckInOrOf(&mode, ok);
       if (!*ok) return nullptr;
@@ -3705,6 +3792,8 @@
             factory()->NewForEachStatement(mode, labels, stmt_pos);
         Target target(&this->target_stack_, loop);
 
+        int each_keyword_position = scanner()->location().beg_pos;
+
         Expression* enumerable;
         if (mode == ForEachStatement::ITERATE) {
           ExpressionClassifier classifier(this);
@@ -3719,7 +3808,8 @@
         // For legacy compat reasons, give for loops similar treatment to
         // if statements in allowing a function declaration for a body
         Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
-        InitializeForEachStatement(loop, expression, enumerable, body);
+        InitializeForEachStatement(loop, expression, enumerable, body,
+                                   each_keyword_position);
 
         Statement* final_loop = loop->IsForOfStatement()
             ? FinalizeForOfStatement(
@@ -3742,13 +3832,6 @@
   Target target(&this->target_stack_, loop);
 
   // Parsed initializer at this point.
-  // Detect attempts at 'let' declarations in sloppy mode.
-  if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER &&
-      is_sloppy(language_mode()) && is_let_identifier_expression) {
-    ReportMessage(MessageTemplate::kSloppyLexical, NULL);
-    *ok = false;
-    return NULL;
-  }
   Expect(Token::SEMICOLON, CHECK_OK);
 
   Expression* cond = NULL;
@@ -3882,16 +3965,9 @@
   return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
 }
 
-
 void ParserTraits::ParseArrowFunctionFormalParameters(
-    ParserFormalParameters* parameters, Expression* expr,
-    const Scanner::Location& params_loc, bool* ok) {
-  if (parameters->Arity() >= Code::kMaxArguments) {
-    ReportMessageAt(params_loc, MessageTemplate::kMalformedArrowFunParamList);
-    *ok = false;
-    return;
-  }
-
+    ParserFormalParameters* parameters, Expression* expr, int end_pos,
+    bool* ok) {
   // ArrowFunctionFormals ::
   //    Binary(Token::COMMA, NonTailArrowFunctionFormals, Tail)
   //    Tail
@@ -3912,7 +3988,8 @@
     DCHECK_EQ(binop->op(), Token::COMMA);
     Expression* left = binop->left();
     Expression* right = binop->right();
-    ParseArrowFunctionFormalParameters(parameters, left, params_loc, ok);
+    int comma_pos = binop->position();
+    ParseArrowFunctionFormalParameters(parameters, left, comma_pos, ok);
     if (!*ok) return;
     // LHS of comma expression should be unparenthesized.
     expr = right;
@@ -3949,13 +4026,66 @@
                                      parser_->scope_, parameters->scope);
   }
 
-  // TODO(adamk): params_loc.end_pos is not the correct initializer position,
-  // but it should be conservative enough to trigger hole checks for variables
-  // referenced in the initializer (if any).
-  AddFormalParameter(parameters, expr, initializer, params_loc.end_pos,
-                     is_rest);
+  AddFormalParameter(parameters, expr, initializer, end_pos, is_rest);
 }
 
+void ParserTraits::ParseAsyncArrowSingleExpressionBody(
+    ZoneList<Statement*>* body, bool accept_IN,
+    Type::ExpressionClassifier* classifier, int pos, bool* ok) {
+  parser_->DesugarAsyncFunctionBody(
+      parser_->ast_value_factory()->empty_string(), parser_->scope_, body,
+      classifier, kAsyncArrowFunction, FunctionBody::SingleExpression,
+      accept_IN, pos, ok);
+}
+
+void Parser::DesugarAsyncFunctionBody(const AstRawString* function_name,
+                                      Scope* scope, ZoneList<Statement*>* body,
+                                      ExpressionClassifier* classifier,
+                                      FunctionKind kind, FunctionBody body_type,
+                                      bool accept_IN, int pos, bool* ok) {
+  // function async_function() {
+  //   try {
+  //     .generator_object = %CreateGeneratorObject();
+  //     ... function body ...
+  //   } catch (e) {
+  //     return Promise.reject(e);
+  //   }
+  // }
+  scope->ForceContextAllocation();
+  Variable* temp =
+      scope_->NewTemporary(ast_value_factory()->dot_generator_object_string());
+  function_state_->set_generator_object_variable(temp);
+
+  Expression* init_generator_variable = factory()->NewAssignment(
+      Token::INIT, factory()->NewVariableProxy(temp),
+      BuildCreateJSGeneratorObject(pos, kind), RelocInfo::kNoPosition);
+  body->Add(factory()->NewExpressionStatement(init_generator_variable,
+                                              RelocInfo::kNoPosition),
+            zone());
+
+  Block* try_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
+
+  ZoneList<Statement*>* inner_body = try_block->statements();
+
+  Expression* return_value = nullptr;
+  if (body_type == FunctionBody::Normal) {
+    ParseStatementList(inner_body, Token::RBRACE, ok);
+    if (!*ok) return;
+    return_value = factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
+  } else {
+    return_value = ParseAssignmentExpression(accept_IN, classifier, ok);
+    if (!*ok) return;
+    ParserTraits::RewriteNonPattern(classifier, ok);
+    if (!*ok) return;
+  }
+
+  return_value = BuildPromiseResolve(return_value, return_value->position());
+  inner_body->Add(
+      factory()->NewReturnStatement(return_value, return_value->position()),
+      zone());
+  body->Add(BuildRejectPromiseOnException(try_block), zone());
+  scope->set_end_position(scanner()->location().end_pos);
+}
 
 DoExpression* Parser::ParseDoExpression(bool* ok) {
   // AssignmentExpression ::
@@ -3982,9 +4112,15 @@
     Scanner::Location* duplicate_loc, bool* ok) {
   if (expr->IsEmptyParentheses()) return;
 
-  ParseArrowFunctionFormalParameters(parameters, expr, params_loc, ok);
+  ParseArrowFunctionFormalParameters(parameters, expr, params_loc.end_pos, ok);
   if (!*ok) return;
 
+  if (parameters->Arity() > Code::kMaxArguments) {
+    ReportMessageAt(params_loc, MessageTemplate::kMalformedArrowFunParamList);
+    *ok = false;
+    return;
+  }
+
   Type::ExpressionClassifier classifier(parser_);
   if (!parameters->is_simple) {
     classifier.RecordNonSimpleParameter();
@@ -4044,53 +4180,17 @@
     function_name = ast_value_factory()->empty_string();
   }
 
-  // Function declarations are function scoped in normal mode, so they are
-  // hoisted. In harmony block scoping mode they are block scoped, so they
-  // are not hoisted.
-  //
-  // One tricky case are function declarations in a local sloppy-mode eval:
-  // their declaration is hoisted, but they still see the local scope. E.g.,
-  //
-  // function() {
-  //   var x = 0
-  //   try { throw 1 } catch (x) { eval("function g() { return x }") }
-  //   return g()
-  // }
-  //
-  // needs to return 1. To distinguish such cases, we need to detect
-  // (1) whether a function stems from a sloppy eval, and
-  // (2) whether it actually hoists across the eval.
-  // Unfortunately, we do not represent sloppy eval scopes, so we do not have
-  // either information available directly, especially not when lazily compiling
-  // a function like 'g'. We hence rely on the following invariants:
-  // - (1) is the case iff the innermost scope of the deserialized scope chain
-  //   under which we compile is _not_ a declaration scope. This holds because
-  //   in all normal cases, function declarations are fully hoisted to a
-  //   declaration scope and compiled relative to that.
-  // - (2) is the case iff the current declaration scope is still the original
-  //   one relative to the deserialized scope chain. Otherwise we must be
-  //   compiling a function in an inner declaration scope in the eval, e.g. a
-  //   nested function, and hoisting works normally relative to that.
-  Scope* declaration_scope = scope_->DeclarationScope();
-  Scope* original_declaration_scope = original_scope_->DeclarationScope();
-  Scope* scope = function_type == FunctionLiteral::kDeclaration &&
-                         is_sloppy(language_mode) &&
-                         !allow_harmony_sloppy_function() &&
-                         (original_scope_ == original_declaration_scope ||
-                          declaration_scope != original_declaration_scope)
-                     ? NewScope(declaration_scope, FUNCTION_SCOPE, kind)
-                     : NewScope(scope_, FUNCTION_SCOPE, kind);
+  Scope* scope = NewScope(scope_, FUNCTION_SCOPE, kind);
   SetLanguageMode(scope, language_mode);
   ZoneList<Statement*>* body = NULL;
   int arity = -1;
   int materialized_literal_count = -1;
   int expected_property_count = -1;
   DuplicateFinder duplicate_finder(scanner()->unicode_cache());
-  FunctionLiteral::EagerCompileHint eager_compile_hint =
-      parenthesized_function_ ? FunctionLiteral::kShouldEagerCompile
-                              : FunctionLiteral::kShouldLazyCompile;
   bool should_be_used_once_hint = false;
   bool has_duplicate_parameters;
+  FunctionLiteral::EagerCompileHint eager_compile_hint;
+
   // Parse function.
   {
     AstNodeFactory function_factory(ast_value_factory());
@@ -4099,6 +4199,10 @@
     scope_->SetScopeName(function_name);
     ExpressionClassifier formals_classifier(this, &duplicate_finder);
 
+    eager_compile_hint = function_state_->this_function_is_parenthesized()
+                             ? FunctionLiteral::kShouldEagerCompile
+                             : FunctionLiteral::kShouldLazyCompile;
+
     if (is_generator) {
       // For generators, allocating variables in contexts is currently a win
       // because it minimizes the work needed to suspend and resume an
@@ -4126,7 +4230,6 @@
     CheckArityRestrictions(arity, kind, formals.has_rest, start_position,
                            formals_end_position, CHECK_OK);
     Expect(Token::LBRACE, CHECK_OK);
-
     // Don't include the rest parameter into the function's formal parameter
     // count (esp. the SharedFunctionInfo::internal_formal_parameter_count,
     // which says whether we need to create an arguments adaptor frame).
@@ -4167,8 +4270,7 @@
     // logic where only top-level functions will be parsed lazily.
     bool is_lazily_parsed = mode() == PARSE_LAZILY &&
                             scope_->AllowsLazyParsing() &&
-                            !parenthesized_function_;
-    parenthesized_function_ = false;  // The bit was set for this function only.
+                            !function_state_->this_function_is_parenthesized();
 
     // Eager or lazy parse?
     // If is_lazily_parsed, we'll parse lazy. If we can set a bookmark, we'll
@@ -4211,10 +4313,13 @@
       //   FunctionExpression; even without enclosing parentheses it might be
       //   immediately invoked.
       // - The function literal shouldn't be hinted to eagerly compile.
+      // - For asm.js functions the body needs to be available when module
+      //   validation is active, because we examine the entire module at once.
       bool use_temp_zone =
           FLAG_lazy && !allow_natives() && extension_ == NULL && allow_lazy() &&
           function_type == FunctionLiteral::kDeclaration &&
-          eager_compile_hint != FunctionLiteral::kShouldEagerCompile;
+          eager_compile_hint != FunctionLiteral::kShouldEagerCompile &&
+          !(FLAG_validate_asm && scope->asm_function());
       // Open a new BodyScope, which sets our AstNodeFactory to allocate in the
       // new temporary zone if the preconditions are satisfied, and ensures that
       // the previous zone is always restored after parsing the body.
@@ -4253,8 +4358,10 @@
     if (is_strict(language_mode)) {
       CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
                               CHECK_OK);
+      CheckDecimalLiteralWithLeadingZero(use_counts_, scope->start_position(),
+                                         scope->end_position());
     }
-    if (is_sloppy(language_mode) && allow_harmony_sloppy_function()) {
+    if (is_sloppy(language_mode)) {
       InsertSloppyBlockFunctionVarBindings(scope, CHECK_OK);
     }
     CheckConflictingVarDeclarations(scope, CHECK_OK);
@@ -4283,6 +4390,36 @@
   return function_literal;
 }
 
+Expression* Parser::ParseAsyncFunctionExpression(bool* ok) {
+  // AsyncFunctionDeclaration ::
+  //   async [no LineTerminator here] function ( FormalParameters[Await] )
+  //       { AsyncFunctionBody }
+  //
+  //   async [no LineTerminator here] function BindingIdentifier[Await]
+  //       ( FormalParameters[Await] ) { AsyncFunctionBody }
+  DCHECK_EQ(scanner()->current_token(), Token::ASYNC);
+  int pos = position();
+  Expect(Token::FUNCTION, CHECK_OK);
+  bool is_strict_reserved = false;
+  const AstRawString* name = nullptr;
+  FunctionLiteral::FunctionType type = FunctionLiteral::kAnonymousExpression;
+
+  if (peek_any_identifier()) {
+    type = FunctionLiteral::kNamedExpression;
+    name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
+    if (this->IsAwait(name)) {
+      ReportMessageAt(scanner()->location(),
+                      MessageTemplate::kAwaitBindingIdentifier);
+      *ok = false;
+      return nullptr;
+    }
+  }
+  return ParseFunctionLiteral(name, scanner()->location(),
+                              is_strict_reserved ? kFunctionNameIsStrictReserved
+                                                 : kFunctionNameValidityUnknown,
+                              FunctionKind::kAsyncFunction, pos, type,
+                              language_mode(), CHECK_OK);
+}
 
 void Parser::SkipLazyFunctionBody(int* materialized_literal_count,
                                   int* expected_property_count, bool* ok,
@@ -4473,12 +4610,18 @@
     if (!parameter.is_simple() && scope_->calls_sloppy_eval()) {
       param_scope = NewScope(scope_, BLOCK_SCOPE);
       param_scope->set_is_declaration_scope();
-      param_scope->set_start_position(parameter.pattern->position());
-      param_scope->set_end_position(RelocInfo::kNoPosition);
+      param_scope->set_start_position(descriptor.initialization_pos);
+      param_scope->set_end_position(parameter.initializer_end_position);
       param_scope->RecordEvalCall();
       param_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
       param_block->set_scope(param_scope);
       descriptor.hoist_scope = scope_;
+      // Pass the appropriate scope in so that PatternRewriter can appropriately
+      // rewrite inner initializers of the pattern to param_scope
+      descriptor.scope = param_scope;
+      // Rewrite the outer initializer to point to param_scope
+      RewriteParameterInitializerScope(stack_limit(), initial_value, scope_,
+                                       param_scope);
     }
 
     {
@@ -4500,6 +4643,57 @@
   return init_block;
 }
 
+Block* Parser::BuildRejectPromiseOnException(Block* block) {
+  // try { <block> } catch (error) { return Promise.reject(error); }
+  Block* try_block = block;
+  Scope* catch_scope = NewScope(scope_, CATCH_SCOPE);
+  catch_scope->set_is_hidden();
+  Variable* catch_variable =
+      catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR,
+                                kCreatedInitialized, Variable::NORMAL);
+  Block* catch_block =
+      factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
+
+  Expression* promise_reject = BuildPromiseReject(
+      factory()->NewVariableProxy(catch_variable), RelocInfo::kNoPosition);
+
+  ReturnStatement* return_promise_reject =
+      factory()->NewReturnStatement(promise_reject, RelocInfo::kNoPosition);
+  catch_block->statements()->Add(return_promise_reject, zone());
+  TryStatement* try_catch_statement =
+      factory()->NewTryCatchStatement(try_block, catch_scope, catch_variable,
+                                      catch_block, RelocInfo::kNoPosition);
+
+  block = factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
+  block->statements()->Add(try_catch_statement, zone());
+  return block;
+}
+
+Expression* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) {
+  DCHECK_NOT_NULL(function_state_->generator_object_variable());
+  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
+  args->Add(factory()->NewThisFunction(pos), zone());
+  args->Add(IsArrowFunction(kind)
+                ? GetLiteralUndefined(pos)
+                : ThisExpression(scope_, factory(), RelocInfo::kNoPosition),
+            zone());
+  return factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args,
+                                   pos);
+}
+
+Expression* Parser::BuildPromiseResolve(Expression* value, int pos) {
+  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
+  args->Add(value, zone());
+  return factory()->NewCallRuntime(Context::PROMISE_CREATE_RESOLVED_INDEX, args,
+                                   pos);
+}
+
+Expression* Parser::BuildPromiseReject(Expression* value, int pos) {
+  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
+  args->Add(value, zone());
+  return factory()->NewCallRuntime(Context::PROMISE_CREATE_REJECTED_INDEX, args,
+                                   pos);
+}
 
 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
     const AstRawString* function_name, int pos,
@@ -4541,7 +4735,7 @@
       // We produce:
       //
       // try { InitialYield; ...body...; return {value: undefined, done: true} }
-      // finally { %GeneratorClose(generator) }
+      // finally { %_GeneratorClose(generator) }
       //
       // - InitialYield yields the actual generator object.
       // - Any return statement inside the body will have its argument wrapped
@@ -4553,18 +4747,18 @@
           factory()->NewBlock(nullptr, 3, false, RelocInfo::kNoPosition);
 
       {
-        ZoneList<Expression*>* arguments =
-            new (zone()) ZoneList<Expression*>(0, zone());
-        CallRuntime* allocation = factory()->NewCallRuntime(
-            Runtime::kCreateJSGeneratorObject, arguments, pos);
+        Expression* allocation = BuildCreateJSGeneratorObject(pos, kind);
         VariableProxy* init_proxy = factory()->NewVariableProxy(
             function_state_->generator_object_variable());
         Assignment* assignment = factory()->NewAssignment(
             Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition);
         VariableProxy* get_proxy = factory()->NewVariableProxy(
             function_state_->generator_object_variable());
-        Yield* yield =
-            factory()->NewYield(get_proxy, assignment, RelocInfo::kNoPosition);
+        // The position of the yield is important for reporting the exception
+        // caused by calling the .throw method on a generator suspended at the
+        // initial yield (i.e. right after generator instantiation).
+        Yield* yield = factory()->NewYield(get_proxy, assignment,
+                                           scope_->start_position());
         try_block->statements()->Add(
             factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition),
             zone());
@@ -4584,7 +4778,7 @@
           function_state_->generator_object_variable());
       args->Add(call_proxy, zone());
       Expression* call = factory()->NewCallRuntime(
-          Runtime::kGeneratorClose, args, RelocInfo::kNoPosition);
+          Runtime::kInlineGeneratorClose, args, RelocInfo::kNoPosition);
       finally_block->statements()->Add(
           factory()->NewExpressionStatement(call, RelocInfo::kNoPosition),
           zone());
@@ -4592,6 +4786,10 @@
       body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
                                                   RelocInfo::kNoPosition),
                 zone());
+    } else if (IsAsyncFunction(kind)) {
+      const bool accept_IN = true;
+      DesugarAsyncFunctionBody(function_name, inner_scope, body, nullptr, kind,
+                               FunctionBody::Normal, accept_IN, pos, CHECK_OK);
     } else {
       ParseStatementList(body, Token::RBRACE, CHECK_OK);
     }
@@ -4613,6 +4811,11 @@
     DCHECK_EQ(body, inner_block->statements());
     SetLanguageMode(scope_, inner_scope->language_mode());
     Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
+
+    if (IsAsyncFunction(kind)) {
+      init_block = BuildRejectPromiseOnException(init_block);
+    }
+
     DCHECK_NOT_NULL(init_block);
 
     inner_scope->set_end_position(scanner()->location().end_pos);
@@ -4650,13 +4853,7 @@
                     RelocInfo::kNoPosition));
   }
 
-  // ES6 14.6.1 Static Semantics: IsInTailPosition
-  // Mark collected return expressions that are in tail call position.
-  const List<Expression*>& expressions_in_tail_position =
-      function_state_->expressions_in_tail_position();
-  for (int i = 0; i < expressions_in_tail_position.length(); ++i) {
-    MarkTailPosition(expressions_in_tail_position[i]);
-  }
+  MarkCollectedTailCallExpressions();
   return result;
 }
 
@@ -4678,19 +4875,17 @@
     reusable_preparser_->set_allow_lazy(true);
 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
     SET_ALLOW(natives);
-    SET_ALLOW(harmony_sloppy);
-    SET_ALLOW(harmony_sloppy_function);
-    SET_ALLOW(harmony_sloppy_let);
     SET_ALLOW(harmony_do_expressions);
-    SET_ALLOW(harmony_function_name);
+    SET_ALLOW(harmony_for_in);
     SET_ALLOW(harmony_function_sent);
     SET_ALLOW(harmony_exponentiation_operator);
     SET_ALLOW(harmony_restrictive_declarations);
+    SET_ALLOW(harmony_async_await);
 #undef SET_ALLOW
   }
   PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
       language_mode(), function_state_->kind(), scope_->has_simple_parameters(),
-      logger, bookmark);
+      parsing_module_, logger, bookmark, use_counts_);
   if (pre_parse_timer_ != NULL) {
     pre_parse_timer_->Stop();
   }
@@ -4733,6 +4928,7 @@
     block_scope->set_start_position(scanner()->location().end_pos);
     ExpressionClassifier extends_classifier(this);
     extends = ParseLeftHandSideExpression(&extends_classifier, CHECK_OK);
+    CheckNoTailCallExpressions(&extends_classifier, CHECK_OK);
     RewriteNonPattern(&extends_classifier, CHECK_OK);
     if (classifier != nullptr) {
       classifier->Accumulate(&extends_classifier,
@@ -4755,13 +4951,12 @@
     if (Check(Token::SEMICOLON)) continue;
     FuncNameInferrer::State fni_state(fni_);
     const bool in_class = true;
-    const bool is_static = false;
     bool is_computed_name = false;  // Classes do not care about computed
                                     // property names here.
     ExpressionClassifier property_classifier(this);
     const AstRawString* property_name = nullptr;
     ObjectLiteral::Property* property = ParsePropertyDefinition(
-        &checker, in_class, has_extends, is_static, &is_computed_name,
+        &checker, in_class, has_extends, MethodKind::Normal, &is_computed_name,
         &has_seen_constructor, &property_classifier, &property_name, CHECK_OK);
     RewriteNonPattern(&property_classifier, CHECK_OK);
     if (classifier != nullptr) {
@@ -4780,8 +4975,7 @@
 
     if (fni_ != NULL) fni_->Infer();
 
-    if (allow_harmony_function_name() &&
-        property_name != ast_value_factory()->constructor_string()) {
+    if (property_name != ast_value_factory()->constructor_string()) {
       SetFunctionNameFromPropertyName(property, property_name);
     }
   }
@@ -4790,7 +4984,7 @@
   int end_pos = scanner()->location().end_pos;
 
   if (constructor == NULL) {
-    constructor = DefaultConstructor(name, extends != NULL, block_scope, pos,
+    constructor = DefaultConstructor(name, has_extends, block_scope, pos,
                                      end_pos, block_scope->language_mode());
   }
 
@@ -5026,7 +5220,7 @@
   // Move statistics to Isolate.
   for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
        ++feature) {
-    for (int i = 0; i < use_counts_[feature]; ++i) {
+    if (use_counts_[feature] > 0) {
       isolate->CountUsage(v8::Isolate::UseCounterFeature(feature));
     }
   }
@@ -5379,6 +5573,29 @@
   SetLanguageMode(scope_, old > mode ? old : mode);
 }
 
+void Parser::MarkCollectedTailCallExpressions() {
+  const ZoneList<Expression*>& tail_call_expressions =
+      function_state_->tail_call_expressions().expressions();
+  for (int i = 0; i < tail_call_expressions.length(); ++i) {
+    Expression* expression = tail_call_expressions[i];
+    // If only FLAG_harmony_explicit_tailcalls is enabled then expression
+    // must be a Call expression.
+    DCHECK(FLAG_harmony_tailcalls || !FLAG_harmony_explicit_tailcalls ||
+           expression->IsCall());
+    MarkTailPosition(expression);
+  }
+}
+
+Expression* ParserTraits::ExpressionListToExpression(
+    ZoneList<Expression*>* args) {
+  AstNodeFactory* factory = parser_->factory();
+  Expression* expr = args->at(0);
+  for (int i = 1; i < args->length(); ++i) {
+    expr = factory->NewBinaryOperation(Token::COMMA, expr, args->at(i),
+                                       expr->position());
+  }
+  return expr;
+}
 
 void ParserTraits::RewriteDestructuringAssignments() {
   parser_->RewriteDestructuringAssignments();
@@ -5400,17 +5617,65 @@
   parser_->RewriteNonPattern(classifier, ok);
 }
 
+Expression* ParserTraits::RewriteAwaitExpression(Expression* value,
+                                                 int await_pos) {
+  // yield %AsyncFunctionAwait(.generator_object, <operand>)
+  Variable* generator_object_variable =
+      parser_->function_state_->generator_object_variable();
 
-Zone* ParserTraits::zone() const {
-  return parser_->function_state_->scope()->zone();
+  // If generator_object_variable is null,
+  if (!generator_object_variable) return value;
+
+  auto factory = parser_->factory();
+  const int nopos = RelocInfo::kNoPosition;
+
+  Variable* temp_var = parser_->scope_->NewTemporary(
+      parser_->ast_value_factory()->empty_string());
+  VariableProxy* temp_proxy = factory->NewVariableProxy(temp_var);
+  Block* do_block = factory->NewBlock(nullptr, 2, false, nopos);
+
+  // Wrap value evaluation to provide a break location.
+  Expression* value_assignment =
+      factory->NewAssignment(Token::ASSIGN, temp_proxy, value, nopos);
+  do_block->statements()->Add(
+      factory->NewExpressionStatement(value_assignment, value->position()),
+      zone());
+
+  ZoneList<Expression*>* async_function_await_args =
+      new (zone()) ZoneList<Expression*>(2, zone());
+  Expression* generator_object =
+      factory->NewVariableProxy(generator_object_variable);
+  async_function_await_args->Add(generator_object, zone());
+  async_function_await_args->Add(temp_proxy, zone());
+  Expression* async_function_await = parser_->factory()->NewCallRuntime(
+      Context::ASYNC_FUNCTION_AWAIT_INDEX, async_function_await_args, nopos);
+  // Wrap await to provide a break location between value evaluation and yield.
+  Expression* await_assignment = factory->NewAssignment(
+      Token::ASSIGN, temp_proxy, async_function_await, nopos);
+  do_block->statements()->Add(
+      factory->NewExpressionStatement(await_assignment, await_pos), zone());
+  Expression* do_expr = factory->NewDoExpression(do_block, temp_var, nopos);
+
+  generator_object = factory->NewVariableProxy(generator_object_variable);
+  return factory->NewYield(generator_object, do_expr, nopos);
 }
 
-
 ZoneList<Expression*>* ParserTraits::GetNonPatternList() const {
   return parser_->function_state_->non_patterns_to_rewrite();
 }
 
 
+ZoneList<typename ParserTraits::Type::ExpressionClassifier::Error>*
+ParserTraits::GetReportedErrorList() const {
+  return parser_->function_state_->GetReportedErrorList();
+}
+
+
+Zone* ParserTraits::zone() const {
+  return parser_->function_state_->scope()->zone();
+}
+
+
 class NonPatternRewriter : public AstExpressionRewriter {
  public:
   NonPatternRewriter(uintptr_t stack_limit, Parser* parser)
@@ -5606,7 +5871,7 @@
           ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition);
       InitializeForOfStatement(loop->AsForOfStatement(),
                                factory()->NewVariableProxy(each), subject,
-                               append_body, spread->expression_position());
+                               append_body);
       do_block->statements()->Add(loop, zone());
     }
   }
@@ -5624,9 +5889,9 @@
 }
 
 
-void ParserTraits::QueueNonPatternForRewriting(Expression* expr) {
+void ParserTraits::QueueNonPatternForRewriting(Expression* expr, bool* ok) {
   DCHECK(expr->IsRewritableExpression());
-  parser_->function_state_->AddNonPatternForRewriting(expr);
+  parser_->function_state_->AddNonPatternForRewriting(expr, ok);
 }
 
 
@@ -5749,15 +6014,19 @@
 //       }
 //     }
 //
-//     output.value;
+//     if (mode === kReturn) {
+//       return {value: output.value, done: true};
+//     }
+//     output.value
 //   }
 //
 // IteratorClose(iterator) expands to the following:
 //
 //   let iteratorReturn = iterator.return;
-//   if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return;
-//   let output = %_Call(iteratorReturn, iterator);
-//   if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
+//   if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
+//     let output = %_Call(iteratorReturn, iterator);
+//     if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
+//   }
 //
 // IteratorClose(iterator, input, output) expands to the following:
 //
@@ -5766,7 +6035,6 @@
 //   output = %_Call(iteratorReturn, iterator, input);
 //   if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
 
-
 Expression* ParserTraits::RewriteYieldStar(
     Expression* generator, Expression* iterable, int pos) {
 
@@ -5798,7 +6066,7 @@
   Statement* initialize_mode;
   {
     Expression* mode_proxy = factory->NewVariableProxy(var_mode);
-    Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::NEXT, nopos);
+    Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::kNext, nopos);
     Expression* assignment =
         factory->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos);
     initialize_mode = factory->NewExpressionStatement(assignment, nopos);
@@ -5929,9 +6197,9 @@
     Statement* throw_call = factory->NewExpressionStatement(call, nopos);
 
     Block* then = factory->NewBlock(nullptr, 4+1, false, nopos);
-    Variable* var_tmp = scope->NewTemporary(avfactory->empty_string());
-    BuildIteratorClose(then->statements(), var_iterator, Nothing<Variable*>(),
-                       var_tmp);
+    parser_->BuildIteratorCloseForCompletion(
+        then->statements(), var_iterator,
+        factory->NewSmiLiteral(Parser::kNormalCompletion, nopos));
     then->statements()->Add(throw_call, zone);
     check_throw = factory->NewIfStatement(
         condition, then, factory->NewEmptyStatement(nopos), nopos);
@@ -5996,7 +6264,7 @@
   {
     Expression* mode_proxy = factory->NewVariableProxy(var_mode);
     Expression* kreturn =
-        factory->NewSmiLiteral(JSGeneratorObject::RETURN, nopos);
+        factory->NewSmiLiteral(JSGeneratorObject::kReturn, nopos);
     Expression* assignment =
         factory->NewAssignment(Token::ASSIGN, mode_proxy, kreturn, nopos);
     set_mode_return = factory->NewExpressionStatement(assignment, nopos);
@@ -6015,7 +6283,7 @@
   Statement* set_mode_next;
   {
     Expression* mode_proxy = factory->NewVariableProxy(var_mode);
-    Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::NEXT, nopos);
+    Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::kNext, nopos);
     Expression* assignment =
         factory->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos);
     set_mode_next = factory->NewExpressionStatement(assignment, nopos);
@@ -6027,7 +6295,7 @@
   {
     Expression* mode_proxy = factory->NewVariableProxy(var_mode);
     Expression* kthrow =
-        factory->NewSmiLiteral(JSGeneratorObject::THROW, nopos);
+        factory->NewSmiLiteral(JSGeneratorObject::kThrow, nopos);
     Expression* assignment =
         factory->NewAssignment(Token::ASSIGN, mode_proxy, kthrow, nopos);
     set_mode_throw = factory->NewExpressionStatement(assignment, nopos);
@@ -6045,7 +6313,30 @@
   }
 
 
-  // output.value;
+  // if (mode === kReturn) {
+  //   return {value: output.value, done: true};
+  // }
+  Statement* maybe_return_value;
+  {
+    Expression* mode_proxy = factory->NewVariableProxy(var_mode);
+    Expression* kreturn =
+        factory->NewSmiLiteral(JSGeneratorObject::kReturn, nopos);
+    Expression* condition = factory->NewCompareOperation(
+        Token::EQ_STRICT, mode_proxy, kreturn, nopos);
+
+    Expression* output_proxy = factory->NewVariableProxy(var_output);
+    Expression* literal =
+        factory->NewStringLiteral(avfactory->value_string(), nopos);
+    Expression* property = factory->NewProperty(output_proxy, literal, nopos);
+    Statement* return_value =
+        factory->NewReturnStatement(BuildIteratorResult(property, true), nopos);
+
+    maybe_return_value = factory->NewIfStatement(
+        condition, return_value, factory->NewEmptyStatement(nopos), nopos);
+  }
+
+
+  // output.value
   Statement* get_value;
   {
     Expression* output_proxy = factory->NewVariableProxy(var_output);
@@ -6070,6 +6361,7 @@
     catch_block->statements()->Add(set_mode_throw, zone);
 
     Scope* catch_scope = NewScope(scope, CATCH_SCOPE);
+    catch_scope->set_is_hidden();
     const AstRawString* name = avfactory->dot_catch_string();
     Variable* catch_variable =
         catch_scope->DeclareLocal(name, VAR, kCreatedInitialized,
@@ -6104,7 +6396,7 @@
     case_next->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
 
     auto case_return = new (zone) ZoneList<Statement*>(5, zone);
-    BuildIteratorClose(case_return, var_iterator, Just(var_input), var_output);
+    BuildIteratorClose(case_return, var_iterator, var_input, var_output);
     case_return->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
 
     auto case_throw = new (zone) ZoneList<Statement*>(5, zone);
@@ -6115,11 +6407,11 @@
     case_throw->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
 
     auto cases = new (zone) ZoneList<CaseClause*>(3, zone);
-    Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::NEXT, nopos);
+    Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::kNext, nopos);
     Expression* kreturn =
-        factory->NewSmiLiteral(JSGeneratorObject::RETURN, nopos);
+        factory->NewSmiLiteral(JSGeneratorObject::kReturn, nopos);
     Expression* kthrow =
-        factory->NewSmiLiteral(JSGeneratorObject::THROW, nopos);
+        factory->NewSmiLiteral(JSGeneratorObject::kThrow, nopos);
     cases->Add(factory->NewCaseClause(knext, case_next, nopos), zone);
     cases->Add(factory->NewCaseClause(kreturn, case_return, nopos), zone);
     cases->Add(factory->NewCaseClause(kthrow, case_throw, nopos), zone);
@@ -6147,13 +6439,14 @@
     // The rewriter needs to process the get_value statement only, hence we
     // put the preceding statements into an init block.
 
-    Block* do_block_ = factory->NewBlock(nullptr, 6, true, nopos);
+    Block* do_block_ = factory->NewBlock(nullptr, 7, true, nopos);
     do_block_->statements()->Add(initialize_input, zone);
     do_block_->statements()->Add(initialize_mode, zone);
     do_block_->statements()->Add(initialize_output, zone);
     do_block_->statements()->Add(get_iterator, zone);
     do_block_->statements()->Add(validate_iterator, zone);
     do_block_->statements()->Add(loop, zone);
+    do_block_->statements()->Add(maybe_return_value, zone);
 
     Block* do_block = factory->NewBlock(nullptr, 2, false, nopos);
     do_block->statements()->Add(do_block_, zone);
@@ -6167,180 +6460,6 @@
   return yield_star;
 }
 
-// Desugaring of (lhs) instanceof (rhs)
-// ====================================
-//
-// We desugar instanceof into a load of property @@hasInstance on the rhs.
-// We end up with roughly the following code (O, C):
-//
-//   do {
-//     let O = lhs;
-//     let C = rhs;
-//     if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck);
-//     let handler_result = C[Symbol.hasInstance];
-//     if (handler_result === undefined) {
-//       if (!IS_CALLABLE(C)) {
-//         throw MakeTypeError(kCalledNonCallableInstanceOf);
-//       }
-//       handler_result = %_GetOrdinaryHasInstance()
-//       handler_result = %_Call(handler_result, C, O);
-//     } else {
-//       handler_result = !!(%_Call(handler_result, C, O));
-//     }
-//     handler_result;
-//   }
-//
-Expression* ParserTraits::RewriteInstanceof(Expression* lhs, Expression* rhs,
-                                            int pos) {
-  const int nopos = RelocInfo::kNoPosition;
-
-  auto factory = parser_->factory();
-  auto avfactory = parser_->ast_value_factory();
-  auto scope = parser_->scope_;
-  auto zone = parser_->zone();
-
-  // let O = lhs;
-  Variable* var_O = scope->NewTemporary(avfactory->empty_string());
-  Statement* get_O;
-  {
-    Expression* O_proxy = factory->NewVariableProxy(var_O);
-    Expression* assignment =
-        factory->NewAssignment(Token::ASSIGN, O_proxy, lhs, nopos);
-    get_O = factory->NewExpressionStatement(assignment, nopos);
-  }
-
-  // let C = lhs;
-  Variable* var_C = scope->NewTemporary(avfactory->empty_string());
-  Statement* get_C;
-  {
-    Expression* C_proxy = factory->NewVariableProxy(var_C);
-    Expression* assignment =
-        factory->NewAssignment(Token::ASSIGN, C_proxy, rhs, nopos);
-    get_C = factory->NewExpressionStatement(assignment, nopos);
-  }
-
-  // if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck);
-  Statement* validate_C;
-  {
-    auto args = new (zone) ZoneList<Expression*>(1, zone);
-    args->Add(factory->NewVariableProxy(var_C), zone);
-    Expression* is_receiver_call =
-        factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
-    Expression* call =
-        NewThrowTypeError(MessageTemplate::kNonObjectInInstanceOfCheck,
-                          avfactory->empty_string(), pos);
-    Statement* throw_call = factory->NewExpressionStatement(call, pos);
-
-    validate_C =
-        factory->NewIfStatement(is_receiver_call,
-                                factory->NewEmptyStatement(nopos),
-                                throw_call,
-                                nopos);
-  }
-
-  // let handler_result = C[Symbol.hasInstance];
-  Variable* var_handler_result = scope->NewTemporary(avfactory->empty_string());
-  Statement* initialize_handler;
-  {
-    Expression* hasInstance_symbol_literal =
-        factory->NewSymbolLiteral("hasInstance_symbol", RelocInfo::kNoPosition);
-    Expression* prop = factory->NewProperty(factory->NewVariableProxy(var_C),
-                                            hasInstance_symbol_literal, pos);
-    Expression* handler_proxy = factory->NewVariableProxy(var_handler_result);
-    Expression* assignment =
-        factory->NewAssignment(Token::ASSIGN, handler_proxy, prop, nopos);
-    initialize_handler = factory->NewExpressionStatement(assignment, nopos);
-  }
-
-  // if (handler_result === undefined) {
-  //   if (!IS_CALLABLE(C)) {
-  //     throw MakeTypeError(kCalledNonCallableInstanceOf);
-  //   }
-  //   handler_result = %_GetOrdinaryHasInstance()
-  //   handler_result = %_Call(handler_result, C, O);
-  // } else {
-  //   handler_result = !!%_Call(handler_result, C, O);
-  // }
-  Statement* call_handler;
-  {
-    Expression* condition = factory->NewCompareOperation(
-        Token::EQ_STRICT, factory->NewVariableProxy(var_handler_result),
-        factory->NewUndefinedLiteral(nopos), nopos);
-
-    Block* then_side = factory->NewBlock(nullptr, 3, false, nopos);
-    {
-      Expression* throw_expr =
-          NewThrowTypeError(MessageTemplate::kCalledNonCallableInstanceOf,
-                            avfactory->empty_string(), pos);
-      Statement* validate_C = CheckCallable(var_C, throw_expr, pos);
-
-      ZoneList<Expression*>* empty_args =
-          new (zone) ZoneList<Expression*>(0, zone);
-      Expression* ordinary_has_instance = factory->NewCallRuntime(
-          Runtime::kInlineGetOrdinaryHasInstance, empty_args, pos);
-      Expression* handler_proxy = factory->NewVariableProxy(var_handler_result);
-      Expression* assignment_handler = factory->NewAssignment(
-          Token::ASSIGN, handler_proxy, ordinary_has_instance, nopos);
-      Statement* assignment_get_handler =
-          factory->NewExpressionStatement(assignment_handler, nopos);
-
-      ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(3, zone);
-      args->Add(factory->NewVariableProxy(var_handler_result), zone);
-      args->Add(factory->NewVariableProxy(var_C), zone);
-      args->Add(factory->NewVariableProxy(var_O), zone);
-      Expression* call =
-          factory->NewCallRuntime(Runtime::kInlineCall, args, pos);
-      Expression* result_proxy = factory->NewVariableProxy(var_handler_result);
-      Expression* assignment =
-          factory->NewAssignment(Token::ASSIGN, result_proxy, call, nopos);
-      Statement* assignment_return =
-          factory->NewExpressionStatement(assignment, nopos);
-
-      then_side->statements()->Add(validate_C, zone);
-      then_side->statements()->Add(assignment_get_handler, zone);
-      then_side->statements()->Add(assignment_return, zone);
-    }
-
-    Statement* else_side;
-    {
-      auto args = new (zone) ZoneList<Expression*>(3, zone);
-      args->Add(factory->NewVariableProxy(var_handler_result), zone);
-      args->Add(factory->NewVariableProxy(var_C), zone);
-      args->Add(factory->NewVariableProxy(var_O), zone);
-      Expression* call =
-          factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
-      Expression* inner_not =
-          factory->NewUnaryOperation(Token::NOT, call, nopos);
-      Expression* outer_not =
-          factory->NewUnaryOperation(Token::NOT, inner_not, nopos);
-      Expression* result_proxy = factory->NewVariableProxy(var_handler_result);
-      Expression* assignment =
-          factory->NewAssignment(Token::ASSIGN, result_proxy, outer_not, nopos);
-
-      else_side = factory->NewExpressionStatement(assignment, nopos);
-    }
-    call_handler =
-        factory->NewIfStatement(condition, then_side, else_side, nopos);
-  }
-
-  // do { ... }
-  DoExpression* instanceof;
-  {
-    Block* block = factory->NewBlock(nullptr, 5, true, nopos);
-    block->statements()->Add(get_O, zone);
-    block->statements()->Add(get_C, zone);
-    block->statements()->Add(validate_C, zone);
-    block->statements()->Add(initialize_handler, zone);
-    block->statements()->Add(call_handler, zone);
-
-    // Here is the desugared instanceof.
-    instanceof = factory->NewDoExpression(block, var_handler_result, nopos);
-    Rewriter::Rewrite(parser_, instanceof, avfactory);
-  }
-
-  return instanceof;
-}
-
 Statement* ParserTraits::CheckCallable(Variable* var, Expression* error,
                                        int pos) {
   auto factory = parser_->factory();
@@ -6364,22 +6483,19 @@
 }
 
 void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements,
-                                      Variable* iterator,
-                                      Maybe<Variable*> input,
+                                      Variable* iterator, Variable* input,
                                       Variable* var_output) {
   //
   // This function adds four statements to [statements], corresponding to the
   // following code:
   //
   //   let iteratorReturn = iterator.return;
-  //   if (IS_NULL_OR_UNDEFINED(iteratorReturn) return |input|;
-  //   output = %_Call(iteratorReturn, iterator|, input|);
+  //   if (IS_NULL_OR_UNDEFINED(iteratorReturn) {
+  //     return {value: input, done: true};
+  //   }
+  //   output = %_Call(iteratorReturn, iterator, input);
   //   if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
   //
-  // Here, |...| denotes optional parts, depending on the presence of the
-  // input variable.  The reason for allowing input is that BuildIteratorClose
-  // can then be reused to handle the return case in yield*.
-  //
 
   const int nopos = RelocInfo::kNoPosition;
   auto factory = parser_->factory();
@@ -6401,33 +6517,31 @@
     get_return = factory->NewExpressionStatement(assignment, nopos);
   }
 
-  // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return |input|;
+  // if (IS_NULL_OR_UNDEFINED(iteratorReturn) {
+  //   return {value: input, done: true};
+  // }
   Statement* check_return;
   {
     Expression* condition = factory->NewCompareOperation(
         Token::EQ, factory->NewVariableProxy(var_return),
         factory->NewNullLiteral(nopos), nopos);
 
-    Expression* value = input.IsJust()
-                            ? static_cast<Expression*>(
-                                  factory->NewVariableProxy(input.FromJust()))
-                            : factory->NewUndefinedLiteral(nopos);
+    Expression* value = factory->NewVariableProxy(input);
 
-    Statement* return_input = factory->NewReturnStatement(value, nopos);
+    Statement* return_input =
+        factory->NewReturnStatement(BuildIteratorResult(value, true), nopos);
 
     check_return = factory->NewIfStatement(
         condition, return_input, factory->NewEmptyStatement(nopos), nopos);
   }
 
-  // output = %_Call(iteratorReturn, iterator, |input|);
+  // output = %_Call(iteratorReturn, iterator, input);
   Statement* call_return;
   {
     auto args = new (zone) ZoneList<Expression*>(3, zone);
     args->Add(factory->NewVariableProxy(var_return), zone);
     args->Add(factory->NewVariableProxy(iterator), zone);
-    if (input.IsJust()) {
-      args->Add(factory->NewVariableProxy(input.FromJust()), zone);
-    }
+    args->Add(factory->NewVariableProxy(input), zone);
 
     Expression* call =
         factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
@@ -6470,8 +6584,6 @@
 void ParserTraits::FinalizeIteratorUse(Variable* completion,
                                        Expression* condition, Variable* iter,
                                        Block* iterator_use, Block* target) {
-  if (!FLAG_harmony_iterator_close) return;
-
   //
   // This function adds two statements to [target], corresponding to the
   // following code:
@@ -6529,8 +6641,8 @@
   Block* maybe_close;
   {
     Block* block = factory->NewBlock(nullptr, 2, true, nopos);
-    parser_->BuildIteratorCloseForCompletion(block->statements(), iter,
-                                             completion);
+    Expression* proxy = factory->NewVariableProxy(completion);
+    parser_->BuildIteratorCloseForCompletion(block->statements(), iter, proxy);
     DCHECK(block->statements()->length() == 2);
 
     maybe_close = factory->NewBlock(nullptr, 1, true, nopos);
@@ -6551,6 +6663,7 @@
     Variable* catch_variable =
         catch_scope->DeclareLocal(avfactory->dot_catch_string(), VAR,
                                   kCreatedInitialized, Variable::NORMAL);
+    catch_scope->set_is_hidden();
 
     Statement* rethrow;
     // We use %ReThrow rather than the ordinary throw because we want to
@@ -6588,7 +6701,7 @@
 
 void ParserTraits::BuildIteratorCloseForCompletion(
     ZoneList<Statement*>* statements, Variable* iterator,
-    Variable* completion) {
+    Expression* completion) {
   //
   // This function adds two statements to [statements], corresponding to the
   // following code:
@@ -6662,6 +6775,7 @@
     Variable* catch_variable = catch_scope->DeclareLocal(
         avfactory->dot_catch_string(), VAR, kCreatedInitialized,
         Variable::NORMAL);
+    catch_scope->set_is_hidden();
 
     try_call_return = factory->NewTryCatchStatement(
         try_block, catch_scope, catch_variable, catch_block, nopos);
@@ -6722,7 +6836,7 @@
   Statement* call_return_carefully;
   {
     Expression* condition = factory->NewCompareOperation(
-        Token::EQ_STRICT, factory->NewVariableProxy(completion),
+        Token::EQ_STRICT, completion,
         factory->NewSmiLiteral(Parser::kThrowCompletion, nopos), nopos);
 
     Block* then_block = factory->NewBlock(nullptr, 2, false, nopos);
@@ -6752,8 +6866,6 @@
 
 
 Statement* ParserTraits::FinalizeForOfStatement(ForOfStatement* loop, int pos) {
-  if (!FLAG_harmony_iterator_close) return loop;
-
   //
   // This function replaces the loop with the following wrapping:
   //
diff --git a/src/parsing/parser.h b/src/parsing/parser.h
index c82682e..472dab9 100644
--- a/src/parsing/parser.h
+++ b/src/parsing/parser.h
@@ -125,7 +125,6 @@
   // TODO(titzer): these should not be part of ParseInfo.
   //--------------------------------------------------------------------------
   Isolate* isolate() { return isolate_; }
-  Handle<JSFunction> closure() { return closure_; }
   Handle<SharedFunctionInfo> shared_info() { return shared_; }
   Handle<Script> script() { return script_; }
   Handle<Context> context() { return context_; }
@@ -145,7 +144,6 @@
   }
 
   void ReopenHandlesInNewHandleScope() {
-    closure_ = Handle<JSFunction>(*closure_);
     shared_ = Handle<SharedFunctionInfo>(*shared_);
     script_ = Handle<Script>(*script_);
     context_ = Handle<Context>(*context_);
@@ -186,7 +184,6 @@
 
   // TODO(titzer): Move handles and isolate out of ParseInfo.
   Isolate* isolate_;
-  Handle<JSFunction> closure_;
   Handle<SharedFunctionInfo> shared_;
   Handle<Script> script_;
   Handle<Context> context_;
@@ -202,8 +199,6 @@
   void SetFlag(Flag f) { flags_ |= f; }
   void SetFlag(Flag f, bool v) { flags_ = v ? flags_ | f : flags_ & ~f; }
   bool GetFlag(Flag f) const { return (flags_ & f) != 0; }
-
-  void set_closure(Handle<JSFunction> closure) { closure_ = closure; }
 };
 
 class FunctionEntry BASE_EMBEDDED {
@@ -360,6 +355,7 @@
   bool IsArguments(const AstRawString* identifier) const;
   bool IsEvalOrArguments(const AstRawString* identifier) const;
   bool IsUndefined(const AstRawString* identifier) const;
+  bool IsAwait(const AstRawString* identifier) const;
   V8_INLINE bool IsFutureStrictReserved(const AstRawString* identifier) const;
 
   // Returns true if the expression is of type "this.foo".
@@ -376,6 +372,12 @@
     return expression->AsVariableProxy()->raw_name();
   }
 
+  bool IsDirectEvalCall(Expression* expression) {
+    if (!expression->IsCall()) return false;
+    expression = expression->AsCall()->expression();
+    return IsIdentifier(expression) && IsEval(AsIdentifier(expression));
+  }
+
   static bool IsBoilerplateProperty(ObjectLiteral::Property* property) {
     return ObjectLiteral::IsBoilerplateProperty(property);
   }
@@ -533,7 +535,11 @@
 
   V8_INLINE void AddParameterInitializationBlock(
       const ParserFormalParameters& parameters,
-      ZoneList<v8::internal::Statement*>* body, bool* ok);
+      ZoneList<v8::internal::Statement*>* body, bool is_async, bool* ok);
+
+  void ParseAsyncArrowSingleExpressionBody(
+      ZoneList<Statement*>* body, bool accept_IN,
+      Type::ExpressionClassifier* classifier, int pos, bool* ok);
 
   V8_INLINE Scope* NewScope(Scope* parent_scope, ScopeType scope_type,
                             FunctionKind kind = kNormalFunction);
@@ -546,14 +552,15 @@
       Scope* scope, const ParserFormalParameters::Parameter& parameter,
       Type::ExpressionClassifier* classifier);
   void ParseArrowFunctionFormalParameters(ParserFormalParameters* parameters,
-                                          Expression* params,
-                                          const Scanner::Location& params_loc,
+                                          Expression* params, int end_pos,
                                           bool* ok);
   void ParseArrowFunctionFormalParameterList(
       ParserFormalParameters* parameters, Expression* params,
       const Scanner::Location& params_loc,
       Scanner::Location* duplicate_loc, bool* ok);
 
+  V8_INLINE Expression* ParseAsyncFunctionExpression(bool* ok);
+
   V8_INLINE DoExpression* ParseDoExpression(bool* ok);
 
   void ReindexLiterals(const ParserFormalParameters& parameters);
@@ -579,6 +586,7 @@
                                   bool name_is_strict_reserved, int pos,
                                   bool* ok);
 
+  V8_INLINE void MarkCollectedTailCallExpressions();
   V8_INLINE void MarkTailPosition(Expression* expression);
 
   V8_INLINE void CheckConflictingVarDeclarations(v8::internal::Scope* scope,
@@ -636,6 +644,8 @@
                                       ZoneList<v8::internal::Expression*>* args,
                                       int pos);
 
+  Expression* ExpressionListToExpression(ZoneList<Expression*>* args);
+
   // Rewrite all DestructuringAssignments in the current FunctionState.
   V8_INLINE void RewriteDestructuringAssignments();
 
@@ -644,9 +654,11 @@
   V8_INLINE Expression* RewriteAssignExponentiation(Expression* left,
                                                     Expression* right, int pos);
 
+  V8_INLINE Expression* RewriteAwaitExpression(Expression* value, int pos);
+
   V8_INLINE void QueueDestructuringAssignmentForRewriting(
       Expression* assignment);
-  V8_INLINE void QueueNonPatternForRewriting(Expression* expr);
+  V8_INLINE void QueueNonPatternForRewriting(Expression* expr, bool* ok);
 
   void SetFunctionNameFromPropertyName(ObjectLiteralProperty* property,
                                        const AstRawString* name);
@@ -658,6 +670,8 @@
   V8_INLINE void RewriteNonPattern(Type::ExpressionClassifier* classifier,
                                    bool* ok);
 
+  V8_INLINE ZoneList<typename Type::ExpressionClassifier::Error>*
+      GetReportedErrorList() const;
   V8_INLINE Zone* zone() const;
 
   V8_INLINE ZoneList<Expression*>* GetNonPatternList() const;
@@ -665,16 +679,14 @@
   Expression* RewriteYieldStar(
       Expression* generator, Expression* expression, int pos);
 
-  Expression* RewriteInstanceof(Expression* lhs, Expression* rhs, int pos);
-
  private:
   Parser* parser_;
 
   void BuildIteratorClose(ZoneList<Statement*>* statements, Variable* iterator,
-                          Maybe<Variable*> input, Variable* output);
-  void BuildIteratorCloseForCompletion(
-      ZoneList<Statement*>* statements, Variable* iterator,
-      Variable* body_threw);
+                          Variable* input, Variable* output);
+  void BuildIteratorCloseForCompletion(ZoneList<Statement*>* statements,
+                                       Variable* iterator,
+                                       Expression* completion);
   Statement* CheckCallable(Variable* var, Expression* error, int pos);
 };
 
@@ -768,8 +780,15 @@
                                bool* ok);
   Statement* ParseStatementAsUnlabelled(ZoneList<const AstRawString*>* labels,
                                    bool* ok);
-  Statement* ParseFunctionDeclaration(ZoneList<const AstRawString*>* names,
+  Statement* ParseFunctionDeclaration(bool* ok);
+  Statement* ParseHoistableDeclaration(ZoneList<const AstRawString*>* names,
                                       bool* ok);
+  Statement* ParseHoistableDeclaration(int pos, ParseFunctionFlags flags,
+                                       ZoneList<const AstRawString*>* names,
+                                       bool* ok);
+  Statement* ParseAsyncFunctionDeclaration(ZoneList<const AstRawString*>* names,
+                                           bool* ok);
+  Expression* ParseAsyncFunctionExpression(bool* ok);
   Statement* ParseFunctionDeclaration(int pos, bool is_generator,
                                       ZoneList<const AstRawString*>* names,
                                       bool* ok);
@@ -838,8 +857,6 @@
                                                       Assignment* assignment,
                                                       Scope* scope);
 
-    void set_initializer_position(int pos) { initializer_position_ = pos; }
-
    private:
     PatternRewriter() {}
 
@@ -880,6 +897,8 @@
     PatternContext SetAssignmentContextIfNeeded(Expression* node);
     PatternContext SetInitializerContextIfNeeded(Expression* node);
 
+    void RewriteParameterScopes(Expression* expr);
+
     Variable* CreateTempVar(Expression* value = nullptr);
 
     AstNodeFactory* factory() const { return parser_->factory(); }
@@ -927,8 +946,6 @@
   Statement* ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok);
   Statement* ParseThrowStatement(bool* ok);
   Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
-  class DontCollectExpressionsInTailPositionScope;
-  class CollectExpressionsInTailPositionToListScope;
   TryStatement* ParseTryStatement(bool* ok);
   DebuggerStatement* ParseDebuggerStatement(bool* ok);
   // Parse a SubStatement in strict mode, or with an extra block scope in
@@ -948,15 +965,22 @@
 
   // Initialize the components of a for-in / for-of statement.
   void InitializeForEachStatement(ForEachStatement* stmt, Expression* each,
-                                  Expression* subject, Statement* body);
+                                  Expression* subject, Statement* body,
+                                  int each_keyword_pos);
   void InitializeForOfStatement(ForOfStatement* stmt, Expression* each,
                                 Expression* iterable, Statement* body,
-                                int iterable_pos);
+                                int next_result_pos = RelocInfo::kNoPosition);
   Statement* DesugarLexicalBindingsInForStatement(
       Scope* inner_scope, VariableMode mode,
       ZoneList<const AstRawString*>* names, ForStatement* loop, Statement* init,
       Expression* cond, Statement* next, Statement* body, bool* ok);
 
+  void DesugarAsyncFunctionBody(const AstRawString* function_name, Scope* scope,
+                                ZoneList<Statement*>* body,
+                                Type::ExpressionClassifier* classifier,
+                                FunctionKind kind, FunctionBody type,
+                                bool accept_IN, int pos, bool* ok);
+
   void RewriteDoExpression(Expression* expr, bool* ok);
 
   FunctionLiteral* ParseFunctionLiteral(
@@ -1027,6 +1051,7 @@
 
   Block* BuildParameterInitializationBlock(
       const ParserFormalParameters& parameters, bool* ok);
+  Block* BuildRejectPromiseOnException(Block* block);
 
   // Consumes the ending }.
   ZoneList<Statement*>* ParseEagerFunctionBody(
@@ -1054,6 +1079,8 @@
   void SetLanguageMode(Scope* scope, LanguageMode mode);
   void RaiseLanguageMode(LanguageMode mode);
 
+  V8_INLINE void MarkCollectedTailCallExpressions();
+
   V8_INLINE void RewriteDestructuringAssignments();
 
   V8_INLINE Expression* RewriteExponentiation(Expression* left,
@@ -1069,6 +1096,10 @@
   friend class InitializerRewriter;
   void RewriteParameterInitializer(Expression* expr, Scope* scope);
 
+  Expression* BuildCreateJSGeneratorObject(int pos, FunctionKind kind);
+  Expression* BuildPromiseResolve(Expression* value, int pos);
+  Expression* BuildPromiseReject(Expression* value, int pos);
+
   Scanner scanner_;
   PreParser* reusable_preparser_;
   Scope* original_scope_;  // for ES5 function declarations in sloppy eval
@@ -1238,20 +1269,27 @@
   }
 }
 
-
 void ParserTraits::AddParameterInitializationBlock(
     const ParserFormalParameters& parameters,
-    ZoneList<v8::internal::Statement*>* body, bool* ok) {
+    ZoneList<v8::internal::Statement*>* body, bool is_async, bool* ok) {
   if (!parameters.is_simple) {
     auto* init_block =
         parser_->BuildParameterInitializationBlock(parameters, ok);
     if (!*ok) return;
+
+    if (is_async) {
+      init_block = parser_->BuildRejectPromiseOnException(init_block);
+    }
+
     if (init_block != nullptr) {
       body->Add(init_block, parser_->zone());
     }
   }
 }
 
+Expression* ParserTraits::ParseAsyncFunctionExpression(bool* ok) {
+  return parser_->ParseAsyncFunctionExpression(ok);
+}
 
 DoExpression* ParserTraits::ParseDoExpression(bool* ok) {
   return parser_->ParseDoExpression(ok);
diff --git a/src/parsing/pattern-rewriter.cc b/src/parsing/pattern-rewriter.cc
index e699255..970231b 100644
--- a/src/parsing/pattern-rewriter.cc
+++ b/src/parsing/pattern-rewriter.cc
@@ -272,15 +272,9 @@
           factory()->NewExpressionStatement(initialize, initialize->position()),
           zone());
     }
-  } else if (value != nullptr && (descriptor_->mode == CONST_LEGACY ||
-                                  IsLexicalVariableMode(descriptor_->mode))) {
-    // Constant initializations always assign to the declared constant which
-    // is always at the function scope level. This is only relevant for
-    // dynamically looked-up variables and constants (the
-    // start context for constant lookups is always the function context,
-    // while it is the top context for var declared variables). Sigh...
-    // For 'let' and 'const' declared variables in harmony mode the
-    // initialization also always assigns to the declared variable.
+  } else if (value != nullptr && IsLexicalVariableMode(descriptor_->mode)) {
+    // For 'let' and 'const' declared variables the initialization always
+    // assigns to the declared variable.
     DCHECK_NOT_NULL(proxy);
     DCHECK_NOT_NULL(proxy->var());
     DCHECK_NOT_NULL(value);
@@ -387,6 +381,37 @@
   return set_context(old_context);
 }
 
+// Two cases for scope rewriting the scope of default parameters:
+// - Eagerly parsed arrow functions are initially parsed as having
+//   expressions in the enclosing scope, but when the arrow is encountered,
+//   need to be in the scope of the function.
+// - When an extra declaration scope needs to be inserted to account for
+//   a sloppy eval in a default parameter or function body, the expressions
+//   needs to be in that new inner scope which was added after initial
+//   parsing.
+// Each of these cases can be handled by rewriting the contents of the
+// expression to the current scope. The source scope is typically the outer
+// scope when one case occurs; when both cases occur, both scopes need to
+// be included as the outer scope. (Both rewritings still need to be done
+// to account for lazily parsed arrow functions which hit the second case.)
+// TODO(littledan): Remove the outer_scope parameter of
+//                  RewriteParameterInitializerScope
+void Parser::PatternRewriter::RewriteParameterScopes(Expression* expr) {
+  if (!IsBindingContext()) return;
+  if (descriptor_->declaration_kind != DeclarationDescriptor::PARAMETER) return;
+  if (!scope()->is_arrow_scope() && !scope()->is_block_scope()) return;
+
+  // Either this scope is an arrow scope or a declaration block scope.
+  DCHECK(scope()->is_declaration_scope());
+
+  if (scope()->outer_scope()->is_arrow_scope() && scope()->is_block_scope()) {
+    RewriteParameterInitializerScope(parser_->stack_limit(), expr,
+                                     scope()->outer_scope()->outer_scope(),
+                                     scope());
+  }
+  RewriteParameterInitializerScope(parser_->stack_limit(), expr,
+                                   scope()->outer_scope(), scope());
+}
 
 void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern,
                                                  Variable** temp_var) {
@@ -396,6 +421,11 @@
 
   for (ObjectLiteralProperty* property : *pattern->properties()) {
     PatternContext context = SetInitializerContextIfNeeded(property->value());
+
+    // Computed property names contain expressions which might require
+    // scope rewriting.
+    if (!property->key()->IsLiteral()) RewriteParameterScopes(property->key());
+
     RecurseIntoSubpattern(
         property->value(),
         factory()->NewProperty(factory()->NewVariableProxy(temp),
@@ -431,9 +461,7 @@
   // wrap this new block in a try-finally statement, restore block_ to its
   // original value, and add the try-finally statement to block_.
   auto target = block_;
-  if (FLAG_harmony_iterator_close) {
-    block_ = factory()->NewBlock(nullptr, 8, true, nopos);
-  }
+  block_ = factory()->NewBlock(nullptr, 8, true, nopos);
 
   Spread* spread = nullptr;
   for (Expression* value : *node->values()) {
@@ -521,7 +549,7 @@
     block_->statements()->Add(if_not_done, zone());
 
     if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
-      if (FLAG_harmony_iterator_close) {
+      {
         // completion = kAbruptCompletion;
         Expression* proxy = factory()->NewVariableProxy(completion);
         Expression* assignment = factory()->NewAssignment(
@@ -533,7 +561,7 @@
 
       RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
 
-      if (FLAG_harmony_iterator_close) {
+      {
         // completion = kNormalCompletion;
         Expression* proxy = factory()->NewVariableProxy(completion);
         Expression* assignment = factory()->NewAssignment(
@@ -552,11 +580,11 @@
 
     // let array = [];
     // while (!done) {
+    //   done = true;  // If .next, .done or .value throws, don't close.
     //   result = IteratorNext(iterator);
-    //   if (result.done) {
-    //     done = true;
-    //   } else {
+    //   if (!result.done) {
     //     %AppendElement(array, result.value);
+    //     done = false;
     //   }
     // }
 
@@ -571,12 +599,6 @@
           node->literal_index(), RelocInfo::kNoPosition));
     }
 
-    // result = IteratorNext(iterator);
-    Statement* get_next = factory()->NewExpressionStatement(
-        parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator),
-                                         result, nopos),
-        nopos);
-
     // done = true;
     Statement* set_done = factory()->NewExpressionStatement(
         factory()->NewAssignment(
@@ -584,6 +606,12 @@
             factory()->NewBooleanLiteral(true, nopos), nopos),
         nopos);
 
+    // result = IteratorNext(iterator);
+    Statement* get_next = factory()->NewExpressionStatement(
+        parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator),
+                                         result, nopos),
+        nopos);
+
     // %AppendElement(array, result.value);
     Statement* append_element;
     {
@@ -600,29 +628,44 @@
           nopos);
     }
 
-    // if (result.done) { #set_done } else { #append_element }
-    Statement* set_done_or_append;
+    // done = false;
+    Statement* unset_done = factory()->NewExpressionStatement(
+        factory()->NewAssignment(
+            Token::ASSIGN, factory()->NewVariableProxy(done),
+            factory()->NewBooleanLiteral(false, nopos), nopos),
+        nopos);
+
+    // if (!result.done) { #append_element; #unset_done }
+    Statement* maybe_append_and_unset_done;
     {
       Expression* result_done =
           factory()->NewProperty(factory()->NewVariableProxy(result),
                                  factory()->NewStringLiteral(
                                      ast_value_factory()->done_string(), nopos),
                                  nopos);
-      set_done_or_append = factory()->NewIfStatement(result_done, set_done,
-                                                     append_element, nopos);
+
+      Block* then = factory()->NewBlock(nullptr, 2, true, nopos);
+      then->statements()->Add(append_element, zone());
+      then->statements()->Add(unset_done, zone());
+
+      maybe_append_and_unset_done = factory()->NewIfStatement(
+          factory()->NewUnaryOperation(Token::NOT, result_done, nopos), then,
+          factory()->NewEmptyStatement(nopos), nopos);
     }
 
     // while (!done) {
+    //   #set_done;
     //   #get_next;
-    //   #set_done_or_append;
+    //   #maybe_append_and_unset_done;
     // }
     WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos);
     {
       Expression* condition = factory()->NewUnaryOperation(
           Token::NOT, factory()->NewVariableProxy(done), nopos);
-      Block* body = factory()->NewBlock(nullptr, 2, true, nopos);
+      Block* body = factory()->NewBlock(nullptr, 3, true, nopos);
+      body->statements()->Add(set_done, zone());
       body->statements()->Add(get_next, zone());
-      body->statements()->Add(set_done_or_append, zone());
+      body->statements()->Add(maybe_append_and_unset_done, zone());
       loop->Initialize(condition, body);
     }
 
@@ -631,13 +674,11 @@
                           factory()->NewVariableProxy(array));
   }
 
-  if (FLAG_harmony_iterator_close) {
-    Expression* closing_condition = factory()->NewUnaryOperation(
-        Token::NOT, factory()->NewVariableProxy(done), nopos);
-    parser_->FinalizeIteratorUse(completion, closing_condition, iterator,
-                                 block_, target);
-    block_ = target;
-  }
+  Expression* closing_condition = factory()->NewUnaryOperation(
+      Token::NOT, factory()->NewVariableProxy(done), nopos);
+  parser_->FinalizeIteratorUse(completion, closing_condition, iterator, block_,
+                               target);
+  block_ = target;
 }
 
 
@@ -668,12 +709,8 @@
                                       RelocInfo::kNoPosition);
   }
 
-  if (IsBindingContext() &&
-      descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER &&
-      scope()->is_arrow_scope()) {
-    RewriteParameterInitializerScope(parser_->stack_limit(), initializer,
-                                     scope()->outer_scope(), scope());
-  }
+  // Initializer may have been parsed in the wrong scope.
+  RewriteParameterScopes(initializer);
 
   PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
   RecurseIntoSubpattern(node->target(), value);
diff --git a/src/parsing/preparse-data.cc b/src/parsing/preparse-data.cc
index d02cd63..e1ef74c 100644
--- a/src/parsing/preparse-data.cc
+++ b/src/parsing/preparse-data.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "src/parsing/preparse-data.h"
+#include "src/base/hashmap.h"
 #include "src/base/logging.h"
 #include "src/globals.h"
-#include "src/hashmap.h"
 #include "src/parsing/parser.h"
-#include "src/parsing/preparse-data.h"
 #include "src/parsing/preparse-data-format.h"
 
 namespace v8 {
diff --git a/src/parsing/preparse-data.h b/src/parsing/preparse-data.h
index 1c99450..ddc4d03 100644
--- a/src/parsing/preparse-data.h
+++ b/src/parsing/preparse-data.h
@@ -6,8 +6,8 @@
 #define V8_PARSING_PREPARSE_DATA_H_
 
 #include "src/allocation.h"
+#include "src/base/hashmap.h"
 #include "src/collector.h"
-#include "src/hashmap.h"
 #include "src/messages.h"
 #include "src/parsing/preparse-data-format.h"
 
diff --git a/src/parsing/preparser.cc b/src/parsing/preparser.cc
index da1c35b..08d5eaf 100644
--- a/src/parsing/preparser.cc
+++ b/src/parsing/preparser.cc
@@ -9,11 +9,10 @@
 #include "src/conversions-inl.h"
 #include "src/conversions.h"
 #include "src/globals.h"
-#include "src/hashmap.h"
 #include "src/list.h"
 #include "src/parsing/parser-base.h"
-#include "src/parsing/preparse-data.h"
 #include "src/parsing/preparse-data-format.h"
+#include "src/parsing/preparse-data.h"
 #include "src/parsing/preparser.h"
 #include "src/unicode.h"
 #include "src/utils.h"
@@ -38,8 +37,10 @@
 
 
 PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) {
-  if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) {
-    return PreParserIdentifier::FutureReserved();
+  if (scanner->current_token() == Token::ENUM) {
+    return PreParserIdentifier::Enum();
+  } else if (scanner->current_token() == Token::AWAIT) {
+    return PreParserIdentifier::Await();
   } else if (scanner->current_token() ==
              Token::FUTURE_STRICT_RESERVED_WORD) {
     return PreParserIdentifier::FutureStrictReserved();
@@ -49,6 +50,8 @@
     return PreParserIdentifier::Static();
   } else if (scanner->current_token() == Token::YIELD) {
     return PreParserIdentifier::Yield();
+  } else if (scanner->current_token() == Token::ASYNC) {
+    return PreParserIdentifier::Async();
   }
   if (scanner->UnescapedLiteralMatches("eval", 4)) {
     return PreParserIdentifier::Eval();
@@ -98,11 +101,13 @@
       function_token_position, type, language_mode, ok);
 }
 
-
 PreParser::PreParseResult PreParser::PreParseLazyFunction(
     LanguageMode language_mode, FunctionKind kind, bool has_simple_parameters,
-    ParserRecorder* log, Scanner::BookmarkScope* bookmark) {
+    bool parsing_module, ParserRecorder* log, Scanner::BookmarkScope* bookmark,
+    int* use_counts) {
+  parsing_module_ = parsing_module;
   log_ = log;
+  use_counts_ = use_counts;
   // Lazy functions always have trivial outer scopes (no with/catch scopes).
   Scope* top_scope = NewScope(scope_, SCRIPT_SCOPE);
   PreParserFactory top_factory(NULL);
@@ -118,6 +123,7 @@
   bool ok = true;
   int start_position = peek_position();
   ParseLazyFunctionLiteralBody(&ok, bookmark);
+  use_counts_ = nullptr;
   if (bookmark && bookmark->HasBeenReset()) {
     // Do nothing, as we've just aborted scanning this function.
   } else if (stack_overflow()) {
@@ -129,6 +135,7 @@
     if (is_strict(scope_->language_mode())) {
       int end_pos = scanner()->location().end_pos;
       CheckStrictOctalLiteral(start_position, end_pos, &ok);
+      CheckDecimalLiteralWithLeadingZero(use_counts, start_position, end_pos);
       if (!ok) return kPreParseSuccess;
     }
   }
@@ -178,19 +185,23 @@
 
   switch (peek()) {
     case Token::FUNCTION:
-      return ParseFunctionDeclaration(ok);
+      return ParseHoistableDeclaration(ok);
     case Token::CLASS:
       return ParseClassDeclaration(ok);
     case Token::CONST:
-      if (allow_const()) {
-        return ParseVariableStatement(kStatementListItem, ok);
-      }
-      break;
+      return ParseVariableStatement(kStatementListItem, ok);
     case Token::LET:
       if (IsNextLetKeyword()) {
         return ParseVariableStatement(kStatementListItem, ok);
       }
       break;
+    case Token::ASYNC:
+      if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION &&
+          !scanner()->HasAnyLineTerminatorAfterNext()) {
+        Consume(Token::ASYNC);
+        return ParseAsyncFunctionDeclaration(ok);
+      }
+    /* falls through */
     default:
       break;
   }
@@ -281,7 +292,9 @@
       (legacy && allow_harmony_restrictive_declarations())) {
     return ParseSubStatement(kDisallowLabelledFunctionStatement, ok);
   } else {
-    return ParseFunctionDeclaration(CHECK_OK);
+    Scope* body_scope = NewScope(scope_, BLOCK_SCOPE);
+    BlockState block_state(&scope_, body_scope);
+    return ParseFunctionDeclaration(ok);
   }
 }
 
@@ -377,37 +390,64 @@
   }
 }
 
+PreParser::Statement PreParser::ParseHoistableDeclaration(
+    int pos, ParseFunctionFlags flags, bool* ok) {
+  const bool is_generator = flags & ParseFunctionFlags::kIsGenerator;
+  const bool is_async = flags & ParseFunctionFlags::kIsAsync;
+  DCHECK(!is_generator || !is_async);
 
-PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
-  // FunctionDeclaration ::
-  //   'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
-  // GeneratorDeclaration ::
-  //   'function' '*' Identifier '(' FormalParameterListopt ')'
-  //      '{' FunctionBody '}'
-  Expect(Token::FUNCTION, CHECK_OK);
-  int pos = position();
-  bool is_generator = Check(Token::MUL);
   bool is_strict_reserved = false;
   Identifier name = ParseIdentifierOrStrictReservedWord(
       &is_strict_reserved, CHECK_OK);
+
+  if (V8_UNLIKELY(is_async_function() && this->IsAwait(name))) {
+    ReportMessageAt(scanner()->location(),
+                    MessageTemplate::kAwaitBindingIdentifier);
+    *ok = false;
+    return Statement::Default();
+  }
+
   ParseFunctionLiteral(name, scanner()->location(),
                        is_strict_reserved ? kFunctionNameIsStrictReserved
                                           : kFunctionNameValidityUnknown,
                        is_generator ? FunctionKind::kGeneratorFunction
-                                    : FunctionKind::kNormalFunction,
+                                    : is_async ? FunctionKind::kAsyncFunction
+                                               : FunctionKind::kNormalFunction,
                        pos, FunctionLiteral::kDeclaration, language_mode(),
                        CHECK_OK);
   return Statement::FunctionDeclaration();
 }
 
+PreParser::Statement PreParser::ParseAsyncFunctionDeclaration(bool* ok) {
+  // AsyncFunctionDeclaration ::
+  //   async [no LineTerminator here] function BindingIdentifier[Await]
+  //       ( FormalParameters[Await] ) { AsyncFunctionBody }
+  DCHECK_EQ(scanner()->current_token(), Token::ASYNC);
+  int pos = position();
+  Expect(Token::FUNCTION, CHECK_OK);
+  ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync;
+  return ParseHoistableDeclaration(pos, flags, ok);
+}
+
+PreParser::Statement PreParser::ParseHoistableDeclaration(bool* ok) {
+  // FunctionDeclaration ::
+  //   'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
+  // GeneratorDeclaration ::
+  //   'function' '*' Identifier '(' FormalParameterListopt ')'
+  //      '{' FunctionBody '}'
+
+  Expect(Token::FUNCTION, CHECK_OK);
+  int pos = position();
+  ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
+  if (Check(Token::MUL)) {
+    flags |= ParseFunctionFlags::kIsGenerator;
+  }
+  return ParseHoistableDeclaration(pos, flags, ok);
+}
+
 
 PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) {
   Expect(Token::CLASS, CHECK_OK);
-  if (!allow_harmony_sloppy() && is_sloppy(language_mode())) {
-    ReportMessage(MessageTemplate::kSloppyLexical);
-    *ok = false;
-    return Statement::Default();
-  }
 
   int pos = position();
   bool is_strict_reserved = false;
@@ -423,10 +463,14 @@
   // Block ::
   //   '{' StatementList '}'
 
+  Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
   Expect(Token::LBRACE, CHECK_OK);
   Statement final = Statement::Default();
-  while (peek() != Token::RBRACE) {
-    final = ParseStatementListItem(CHECK_OK);
+  {
+    BlockState block_state(&scope_, block_scope);
+    while (peek() != Token::RBRACE) {
+      final = ParseStatementListItem(CHECK_OK);
+    }
   }
   Expect(Token::RBRACE, ok);
   return final;
@@ -473,7 +517,7 @@
   bool is_pattern = false;
   if (peek() == Token::VAR) {
     Consume(Token::VAR);
-  } else if (peek() == Token::CONST && allow_const()) {
+  } else if (peek() == Token::CONST) {
     // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
     //
     // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
@@ -485,12 +529,10 @@
     // existing pages. Therefore we keep allowing const with the old
     // non-harmony semantics in sloppy mode.
     Consume(Token::CONST);
-    if (is_strict(language_mode()) || allow_harmony_sloppy()) {
-      DCHECK(var_context != kStatement);
-      require_initializer = true;
-      lexical = true;
-    }
-  } else if (peek() == Token::LET && allow_let()) {
+    DCHECK(var_context != kStatement);
+    require_initializer = true;
+    lexical = true;
+  } else if (peek() == Token::LET) {
     Consume(Token::LET);
     DCHECK(var_context != kStatement);
     lexical = true;
@@ -556,6 +598,22 @@
   return Statement::Default();
 }
 
+PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
+  Consume(Token::FUNCTION);
+  int pos = position();
+  ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
+  if (Check(Token::MUL)) {
+    flags |= ParseFunctionFlags::kIsGenerator;
+    if (allow_harmony_restrictive_declarations()) {
+      PreParserTraits::ReportMessageAt(
+          scanner()->location(), MessageTemplate::kGeneratorInLegacyContext);
+      *ok = false;
+      return Statement::Default();
+    }
+  }
+  return ParseHoistableDeclaration(pos, flags, ok);
+}
+
 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(
     AllowLabelledFunctionStatement allow_function, bool* ok) {
   // ExpressionStatement | LabelledStatement ::
@@ -586,7 +644,8 @@
   if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) {
     // Expression is a single identifier, and not, e.g., a parenthesized
     // identifier.
-    DCHECK(!expr.AsIdentifier().IsFutureReserved());
+    DCHECK(!expr.AsIdentifier().IsEnum());
+    DCHECK(!parsing_module_ || !expr.AsIdentifier().IsAwait());
     DCHECK(is_sloppy(language_mode()) ||
            !IsFutureStrictReserved(expr.AsIdentifier()));
     Consume(Token::COLON);
@@ -606,14 +665,6 @@
     // accept "native function" in the preparser.
   }
   // Parsed expression statement.
-  // Detect attempts at 'let' declarations in sloppy mode.
-  if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER &&
-      is_sloppy(language_mode()) && expr.IsIdentifier() &&
-      expr.AsIdentifier().IsLet()) {
-    ReportMessage(MessageTemplate::kSloppyLexical, NULL);
-    *ok = false;
-    return Statement::Default();
-  }
   ExpectSemicolon(CHECK_OK);
   return Statement::ExpressionStatement(expr);
 }
@@ -696,6 +747,16 @@
       tok != Token::SEMICOLON &&
       tok != Token::RBRACE &&
       tok != Token::EOS) {
+    // Because of the return code rewriting that happens in case of a subclass
+    // constructor we don't want to accept tail calls, therefore we don't set
+    // ReturnExprScope to kInsideValidReturnStatement here.
+    ReturnExprContext return_expr_context =
+        IsSubclassConstructor(function_state_->kind())
+            ? function_state_->return_expr_context()
+            : ReturnExprContext::kInsideValidReturnStatement;
+
+    ReturnExprScope maybe_allow_tail_calls(function_state_,
+                                           return_expr_context);
     ParseExpression(true, CHECK_OK);
   }
   ExpectSemicolon(CHECK_OK);
@@ -732,23 +793,27 @@
   ParseExpression(true, CHECK_OK);
   Expect(Token::RPAREN, CHECK_OK);
 
-  Expect(Token::LBRACE, CHECK_OK);
-  Token::Value token = peek();
-  while (token != Token::RBRACE) {
-    if (token == Token::CASE) {
-      Expect(Token::CASE, CHECK_OK);
-      ParseExpression(true, CHECK_OK);
-    } else {
-      Expect(Token::DEFAULT, CHECK_OK);
-    }
-    Expect(Token::COLON, CHECK_OK);
-    token = peek();
-    Statement statement = Statement::Jump();
-    while (token != Token::CASE &&
-           token != Token::DEFAULT &&
-           token != Token::RBRACE) {
-      statement = ParseStatementListItem(CHECK_OK);
+  Scope* cases_scope = NewScope(scope_, BLOCK_SCOPE);
+  {
+    BlockState cases_block_state(&scope_, cases_scope);
+    Expect(Token::LBRACE, CHECK_OK);
+    Token::Value token = peek();
+    while (token != Token::RBRACE) {
+      if (token == Token::CASE) {
+        Expect(Token::CASE, CHECK_OK);
+        ParseExpression(true, CHECK_OK);
+      } else {
+        Expect(Token::DEFAULT, CHECK_OK);
+      }
+      Expect(Token::COLON, CHECK_OK);
       token = peek();
+      Statement statement = Statement::Jump();
+      while (token != Token::CASE &&
+             token != Token::DEFAULT &&
+             token != Token::RBRACE) {
+        statement = ParseStatementListItem(CHECK_OK);
+        token = peek();
+      }
     }
   }
   Expect(Token::RBRACE, ok);
@@ -788,12 +853,16 @@
   // ForStatement ::
   //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
 
+  // Create an in-between scope for let-bound iteration variables.
+  Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
+  bool has_lexical = false;
+
+  BlockState block_state(&scope_, for_scope);
   Expect(Token::FOR, CHECK_OK);
   Expect(Token::LPAREN, CHECK_OK);
-  bool is_let_identifier_expression = false;
   if (peek() != Token::SEMICOLON) {
     ForEachStatement::VisitMode mode;
-    if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) ||
+    if (peek() == Token::VAR || peek() == Token::CONST ||
         (peek() == Token::LET && IsNextLetKeyword())) {
       int decl_count;
       bool is_lexical;
@@ -803,6 +872,7 @@
       ParseVariableDeclarations(kForStatement, &decl_count, &is_lexical,
                                 &is_binding_pattern, &first_initializer_loc,
                                 &bindings_loc, CHECK_OK);
+      if (is_lexical) has_lexical = true;
       if (CheckInOrOf(&mode, ok)) {
         if (!*ok) return Statement::Default();
         if (decl_count != 1) {
@@ -814,7 +884,12 @@
         }
         if (first_initializer_loc.IsValid() &&
             (is_strict(language_mode()) || mode == ForEachStatement::ITERATE ||
-             is_lexical || is_binding_pattern)) {
+             is_lexical || is_binding_pattern || allow_harmony_for_in())) {
+          // Only increment the use count if we would have let this through
+          // without the flag.
+          if (use_counts_ != nullptr && allow_harmony_for_in()) {
+            ++use_counts_[v8::Isolate::kForInInitializer];
+          }
           PreParserTraits::ReportMessageAt(
               first_initializer_loc, MessageTemplate::kForInOfLoopInitializer,
               ForEachStatement::VisitModeString(mode));
@@ -831,7 +906,11 @@
         }
 
         Expect(Token::RPAREN, CHECK_OK);
-        ParseScopedStatement(true, CHECK_OK);
+        {
+          ReturnExprScope no_tail_calls(function_state_,
+                                        ReturnExprContext::kInsideForInOfBody);
+          ParseScopedStatement(true, CHECK_OK);
+        }
         return Statement::Default();
       }
     } else {
@@ -839,8 +918,6 @@
       ExpressionClassifier classifier(this);
       Expression lhs = ParseExpression(false, &classifier, CHECK_OK);
       int lhs_end_pos = scanner()->location().end_pos;
-      is_let_identifier_expression =
-          lhs.IsIdentifier() && lhs.AsIdentifier().IsLet();
       bool is_for_each = CheckInOrOf(&mode, ok);
       if (!*ok) return Statement::Default();
       bool is_destructuring = is_for_each &&
@@ -868,33 +945,39 @@
         }
 
         Expect(Token::RPAREN, CHECK_OK);
-        ParseScopedStatement(true, CHECK_OK);
+        Scope* body_scope = NewScope(scope_, BLOCK_SCOPE);
+        {
+          BlockState block_state(&scope_, body_scope);
+          ParseScopedStatement(true, CHECK_OK);
+        }
         return Statement::Default();
       }
     }
   }
 
   // Parsed initializer at this point.
-  // Detect attempts at 'let' declarations in sloppy mode.
-  if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER &&
-      is_sloppy(language_mode()) && is_let_identifier_expression) {
-    ReportMessage(MessageTemplate::kSloppyLexical, NULL);
-    *ok = false;
-    return Statement::Default();
-  }
   Expect(Token::SEMICOLON, CHECK_OK);
 
-  if (peek() != Token::SEMICOLON) {
-    ParseExpression(true, CHECK_OK);
-  }
-  Expect(Token::SEMICOLON, CHECK_OK);
+  // If there are let bindings, then condition and the next statement of the
+  // for loop must be parsed in a new scope.
+  Scope* inner_scope = scope_;
+  if (has_lexical) inner_scope = NewScope(for_scope, BLOCK_SCOPE);
 
-  if (peek() != Token::RPAREN) {
-    ParseExpression(true, CHECK_OK);
-  }
-  Expect(Token::RPAREN, CHECK_OK);
+  {
+    BlockState block_state(&scope_, inner_scope);
 
-  ParseScopedStatement(true, ok);
+    if (peek() != Token::SEMICOLON) {
+      ParseExpression(true, CHECK_OK);
+    }
+    Expect(Token::SEMICOLON, CHECK_OK);
+
+    if (peek() != Token::RPAREN) {
+      ParseExpression(true, CHECK_OK);
+    }
+    Expect(Token::RPAREN, CHECK_OK);
+
+    ParseScopedStatement(true, ok);
+  }
   return Statement::Default();
 }
 
@@ -929,7 +1012,11 @@
 
   Expect(Token::TRY, CHECK_OK);
 
-  ParseBlock(CHECK_OK);
+  {
+    ReturnExprScope no_tail_calls(function_state_,
+                                  ReturnExprContext::kInsideTryBlock);
+    ParseBlock(CHECK_OK);
+  }
 
   Token::Value tok = peek();
   if (tok != Token::CATCH && tok != Token::FINALLY) {
@@ -937,24 +1024,42 @@
     *ok = false;
     return Statement::Default();
   }
+  TailCallExpressionList tail_call_expressions_in_catch_block(zone());
+  bool catch_block_exists = false;
   if (tok == Token::CATCH) {
     Consume(Token::CATCH);
     Expect(Token::LPAREN, CHECK_OK);
+    Scope* catch_scope = NewScope(scope_, CATCH_SCOPE);
     ExpressionClassifier pattern_classifier(this);
     ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
     ValidateBindingPattern(&pattern_classifier, CHECK_OK);
     Expect(Token::RPAREN, CHECK_OK);
     {
-      // TODO(adamk): Make this CATCH_SCOPE
-      Scope* with_scope = NewScope(scope_, WITH_SCOPE);
-      BlockState block_state(&scope_, with_scope);
-      ParseBlock(CHECK_OK);
+      CollectExpressionsInTailPositionToListScope
+          collect_tail_call_expressions_scope(
+              function_state_, &tail_call_expressions_in_catch_block);
+      BlockState block_state(&scope_, catch_scope);
+      Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
+      {
+        BlockState block_state(&scope_, block_scope);
+        ParseBlock(CHECK_OK);
+      }
     }
+    catch_block_exists = true;
     tok = peek();
   }
   if (tok == Token::FINALLY) {
     Consume(Token::FINALLY);
     ParseBlock(CHECK_OK);
+    if (FLAG_harmony_explicit_tailcalls && catch_block_exists &&
+        tail_call_expressions_in_catch_block.has_explicit_tail_calls()) {
+      // TODO(ishell): update chapter number.
+      // ES8 XX.YY.ZZ
+      ReportMessageAt(tail_call_expressions_in_catch_block.location(),
+                      MessageTemplate::kUnexpectedTailCallInCatchBlock);
+      *ok = false;
+      return Statement::Default();
+    }
   }
   return Statement::Default();
 }
@@ -1012,9 +1117,8 @@
 
   // See Parser::ParseFunctionLiteral for more information about lazy parsing
   // and lazy compilation.
-  bool is_lazily_parsed =
-      (outer_is_script_scope && allow_lazy() && !parenthesized_function_);
-  parenthesized_function_ = false;
+  bool is_lazily_parsed = (outer_is_script_scope && allow_lazy() &&
+                           !function_state_->this_function_is_parenthesized());
 
   Expect(Token::LBRACE, CHECK_OK);
   if (is_lazily_parsed) {
@@ -1039,11 +1143,44 @@
   if (is_strict(language_mode)) {
     int end_position = scanner()->location().end_pos;
     CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
+    CheckDecimalLiteralWithLeadingZero(use_counts_, start_position,
+                                       end_position);
   }
 
   return Expression::Default();
 }
 
+PreParser::Expression PreParser::ParseAsyncFunctionExpression(bool* ok) {
+  // AsyncFunctionDeclaration ::
+  //   async [no LineTerminator here] function ( FormalParameters[Await] )
+  //       { AsyncFunctionBody }
+  //
+  //   async [no LineTerminator here] function BindingIdentifier[Await]
+  //       ( FormalParameters[Await] ) { AsyncFunctionBody }
+  int pos = position();
+  Expect(Token::FUNCTION, CHECK_OK);
+  bool is_strict_reserved = false;
+  Identifier name;
+  FunctionLiteral::FunctionType type = FunctionLiteral::kAnonymousExpression;
+
+  if (peek_any_identifier()) {
+    type = FunctionLiteral::kNamedExpression;
+    name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
+    if (this->IsAwait(name)) {
+      ReportMessageAt(scanner()->location(),
+                      MessageTemplate::kAwaitBindingIdentifier);
+      *ok = false;
+      return Expression::Default();
+    }
+  }
+
+  ParseFunctionLiteral(name, scanner()->location(),
+                       is_strict_reserved ? kFunctionNameIsStrictReserved
+                                          : kFunctionNameValidityUnknown,
+                       FunctionKind::kAsyncFunction, pos, type, language_mode(),
+                       CHECK_OK);
+  return Expression::Default();
+}
 
 void PreParser::ParseLazyFunctionLiteralBody(bool* ok,
                                              Scanner::BookmarkScope* bookmark) {
@@ -1090,6 +1227,7 @@
   if (has_extends) {
     ExpressionClassifier extends_classifier(this);
     ParseLeftHandSideExpression(&extends_classifier, CHECK_OK);
+    CheckNoTailCallExpressions(&extends_classifier, CHECK_OK);
     ValidateExpression(&extends_classifier, CHECK_OK);
     if (classifier != nullptr) {
       classifier->Accumulate(&extends_classifier,
@@ -1104,12 +1242,11 @@
   while (peek() != Token::RBRACE) {
     if (Check(Token::SEMICOLON)) continue;
     const bool in_class = true;
-    const bool is_static = false;
     bool is_computed_name = false;  // Classes do not care about computed
                                     // property names here.
     Identifier name;
     ExpressionClassifier property_classifier(this);
-    ParsePropertyDefinition(&checker, in_class, has_extends, is_static,
+    ParsePropertyDefinition(&checker, in_class, has_extends, MethodKind::Normal,
                             &is_computed_name, &has_seen_constructor,
                             &property_classifier, &name, CHECK_OK);
     ValidateExpression(&property_classifier, CHECK_OK);
@@ -1151,15 +1288,24 @@
   //     do '{' StatementList '}'
   Expect(Token::DO, CHECK_OK);
   Expect(Token::LBRACE, CHECK_OK);
-  Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
-  {
-    BlockState block_state(&scope_, block_scope);
-    while (peek() != Token::RBRACE) {
-      ParseStatementListItem(CHECK_OK);
-    }
-    Expect(Token::RBRACE, CHECK_OK);
-    return PreParserExpression::Default();
+  while (peek() != Token::RBRACE) {
+    ParseStatementListItem(CHECK_OK);
   }
+  Expect(Token::RBRACE, CHECK_OK);
+  return PreParserExpression::Default();
+}
+
+void PreParserTraits::ParseAsyncArrowSingleExpressionBody(
+    PreParserStatementList body, bool accept_IN,
+    Type::ExpressionClassifier* classifier, int pos, bool* ok) {
+  Scope* scope = pre_parser_->scope_;
+  scope->ForceContextAllocation();
+
+  PreParserExpression return_value =
+      pre_parser_->ParseAssignmentExpression(accept_IN, classifier, ok);
+  if (!*ok) return;
+
+  body->Add(PreParserStatement::ExpressionStatement(return_value), zone());
 }
 
 #undef CHECK_OK
diff --git a/src/parsing/preparser.h b/src/parsing/preparser.h
index f2f6951..8eb95e7 100644
--- a/src/parsing/preparser.h
+++ b/src/parsing/preparser.h
@@ -7,7 +7,7 @@
 
 #include "src/ast/scopes.h"
 #include "src/bailout-reason.h"
-#include "src/hashmap.h"
+#include "src/base/hashmap.h"
 #include "src/messages.h"
 #include "src/parsing/expression-classifier.h"
 #include "src/parsing/func-name-inferrer.h"
@@ -55,6 +55,15 @@
   static PreParserIdentifier Constructor() {
     return PreParserIdentifier(kConstructorIdentifier);
   }
+  static PreParserIdentifier Enum() {
+    return PreParserIdentifier(kEnumIdentifier);
+  }
+  static PreParserIdentifier Await() {
+    return PreParserIdentifier(kAwaitIdentifier);
+  }
+  static PreParserIdentifier Async() {
+    return PreParserIdentifier(kAsyncIdentifier);
+  }
   bool IsEval() const { return type_ == kEvalIdentifier; }
   bool IsArguments() const { return type_ == kArgumentsIdentifier; }
   bool IsEvalOrArguments() const { return IsEval() || IsArguments(); }
@@ -64,7 +73,9 @@
   bool IsYield() const { return type_ == kYieldIdentifier; }
   bool IsPrototype() const { return type_ == kPrototypeIdentifier; }
   bool IsConstructor() const { return type_ == kConstructorIdentifier; }
-  bool IsFutureReserved() const { return type_ == kFutureReservedIdentifier; }
+  bool IsEnum() const { return type_ == kEnumIdentifier; }
+  bool IsAwait() const { return type_ == kAwaitIdentifier; }
+  bool IsAsync() const { return type_ == kAsyncIdentifier; }
   bool IsFutureStrictReserved() const {
     return type_ == kFutureStrictReservedIdentifier ||
            type_ == kLetIdentifier || type_ == kStaticIdentifier ||
@@ -91,7 +102,10 @@
     kArgumentsIdentifier,
     kUndefinedIdentifier,
     kPrototypeIdentifier,
-    kConstructorIdentifier
+    kConstructorIdentifier,
+    kEnumIdentifier,
+    kAwaitIdentifier,
+    kAsyncIdentifier
   };
 
   explicit PreParserIdentifier(Type type) : type_(type) {}
@@ -166,6 +180,12 @@
                                ExpressionTypeField::encode(kCallExpression));
   }
 
+  static PreParserExpression CallEval() {
+    return PreParserExpression(
+        TypeField::encode(kExpression) |
+        ExpressionTypeField::encode(kCallEvalExpression));
+  }
+
   static PreParserExpression SuperCallReference() {
     return PreParserExpression(
         TypeField::encode(kExpression) |
@@ -227,7 +247,13 @@
 
   bool IsCall() const {
     return TypeField::decode(code_) == kExpression &&
-           ExpressionTypeField::decode(code_) == kCallExpression;
+           (ExpressionTypeField::decode(code_) == kCallExpression ||
+            ExpressionTypeField::decode(code_) == kCallEvalExpression);
+  }
+
+  bool IsDirectEvalCall() const {
+    return TypeField::decode(code_) == kExpression &&
+           ExpressionTypeField::decode(code_) == kCallEvalExpression;
   }
 
   bool IsSuperCallReference() const {
@@ -285,6 +311,7 @@
     kThisPropertyExpression,
     kPropertyExpression,
     kCallExpression,
+    kCallEvalExpression,
     kSuperCallReference,
     kNoTemplateTagExpression,
     kAssignment
@@ -494,6 +521,9 @@
   PreParserExpression NewCall(PreParserExpression expression,
                               PreParserExpressionList arguments,
                               int pos) {
+    if (expression.IsIdentifier() && expression.AsIdentifier().IsEval()) {
+      return PreParserExpression::CallEval();
+    }
     return PreParserExpression::Call();
   }
   PreParserExpression NewCallNew(PreParserExpression expression,
@@ -597,6 +627,14 @@
     return identifier.IsArguments();
   }
 
+  static bool IsAwait(PreParserIdentifier identifier) {
+    return identifier.IsAwait();
+  }
+
+  static bool IsAsync(PreParserIdentifier identifier) {
+    return identifier.IsAsync();
+  }
+
   static bool IsEvalOrArguments(PreParserIdentifier identifier) {
     return identifier.IsEvalOrArguments();
   }
@@ -626,6 +664,14 @@
     return expression.AsIdentifier();
   }
 
+  static bool IsEvalIdentifier(PreParserExpression expression) {
+    return IsIdentifier(expression) && IsEval(AsIdentifier(expression));
+  }
+
+  static bool IsDirectEvalCall(PreParserExpression expression) {
+    return expression.IsDirectEvalCall();
+  }
+
   static bool IsFutureStrictReserved(PreParserIdentifier identifier) {
     return identifier.IsFutureStrictReserved();
   }
@@ -814,8 +860,8 @@
   }
 
   static void AddParameterInitializationBlock(
-      const PreParserFormalParameters& parameters,
-      PreParserStatementList list, bool* ok) {}
+      const PreParserFormalParameters& parameters, PreParserStatementList list,
+      bool is_async, bool* ok) {}
 
   V8_INLINE void SkipLazyFunctionBody(int* materialized_literal_count,
                                       int* expected_property_count, bool* ok) {
@@ -832,6 +878,12 @@
       PreParserExpression expression, const Scanner::Location& params_loc,
       Scanner::Location* duplicate_loc, bool* ok);
 
+  void ParseAsyncArrowSingleExpressionBody(
+      PreParserStatementList body, bool accept_IN,
+      Type::ExpressionClassifier* classifier, int pos, bool* ok);
+
+  V8_INLINE PreParserExpression ParseAsyncFunctionExpression(bool* ok);
+
   void ReindexLiterals(const PreParserFormalParameters& paramaters) {}
 
   struct TemplateLiteralState {};
@@ -888,6 +940,7 @@
                                         bool name_is_strict_reserved, int pos,
                                         bool* ok);
 
+  V8_INLINE void MarkCollectedTailCallExpressions() {}
   V8_INLINE void MarkTailPosition(PreParserExpression) {}
 
   PreParserExpressionList PrepareSpreadArguments(PreParserExpressionList list) {
@@ -903,6 +956,11 @@
                                            PreParserExpressionList args,
                                            int pos);
 
+  inline PreParserExpression ExpressionListToExpression(
+      PreParserExpressionList args) {
+    return PreParserExpression::Default();
+  }
+
   inline void RewriteDestructuringAssignments() {}
 
   inline PreParserExpression RewriteExponentiation(PreParserExpression left,
@@ -916,7 +974,7 @@
   }
 
   inline void QueueDestructuringAssignmentForRewriting(PreParserExpression) {}
-  inline void QueueNonPatternForRewriting(PreParserExpression) {}
+  inline void QueueNonPatternForRewriting(PreParserExpression, bool* ok) {}
 
   void SetFunctionNameFromPropertyName(PreParserExpression,
                                        PreParserIdentifier) {}
@@ -926,14 +984,16 @@
   inline void RewriteNonPattern(Type::ExpressionClassifier* classifier,
                                 bool* ok);
 
+  inline PreParserExpression RewriteAwaitExpression(PreParserExpression value,
+                                                    int pos);
+
+  V8_INLINE ZoneList<typename Type::ExpressionClassifier::Error>*
+      GetReportedErrorList() const;
   V8_INLINE Zone* zone() const;
   V8_INLINE ZoneList<PreParserExpression>* GetNonPatternList() const;
 
   inline PreParserExpression RewriteYieldStar(
       PreParserExpression generator, PreParserExpression expr, int pos);
-  inline PreParserExpression RewriteInstanceof(PreParserExpression lhs,
-                                               PreParserExpression rhs,
-                                               int pos);
 
  private:
   PreParser* pre_parser_;
@@ -966,19 +1026,30 @@
   PreParser(Zone* zone, Scanner* scanner, AstValueFactory* ast_value_factory,
             ParserRecorder* log, uintptr_t stack_limit)
       : ParserBase<PreParserTraits>(zone, scanner, stack_limit, NULL,
-                                    ast_value_factory, log, this) {}
+                                    ast_value_factory, log, this),
+        use_counts_(nullptr) {}
 
   // Pre-parse the program from the character stream; returns true on
   // success (even if parsing failed, the pre-parse data successfully
   // captured the syntax error), and false if a stack-overflow happened
   // during parsing.
-  PreParseResult PreParseProgram(int* materialized_literals = 0) {
+  PreParseResult PreParseProgram(int* materialized_literals = 0,
+                                 bool is_module = false) {
     Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
+
+    // ModuleDeclarationInstantiation for Source Text Module Records creates a
+    // new Module Environment Record whose outer lexical environment record is
+    // the global scope.
+    if (is_module) {
+      scope = NewScope(scope, MODULE_SCOPE);
+    }
+
     PreParserFactory factory(NULL);
     FunctionState top_scope(&function_state_, &scope_, scope, kNormalFunction,
                             &factory);
     bool ok = true;
     int start_position = scanner()->peek_location().beg_pos;
+    parsing_module_ = is_module;
     ParseStatementList(Token::EOS, &ok);
     if (stack_overflow()) return kPreParseStackOverflow;
     if (!ok) {
@@ -986,6 +1057,8 @@
     } else if (is_strict(scope_->language_mode())) {
       CheckStrictOctalLiteral(start_position, scanner()->location().end_pos,
                               &ok);
+      CheckDecimalLiteralWithLeadingZero(use_counts_, start_position,
+                                         scanner()->location().end_pos);
     }
     if (materialized_literals) {
       *materialized_literals = function_state_->materialized_literal_count();
@@ -1001,9 +1074,12 @@
   // keyword and parameters, and have consumed the initial '{'.
   // At return, unless an error occurred, the scanner is positioned before the
   // the final '}'.
-  PreParseResult PreParseLazyFunction(
-      LanguageMode language_mode, FunctionKind kind, bool has_simple_parameters,
-      ParserRecorder* log, Scanner::BookmarkScope* bookmark = nullptr);
+  PreParseResult PreParseLazyFunction(LanguageMode language_mode,
+                                      FunctionKind kind,
+                                      bool has_simple_parameters,
+                                      bool parsing_module, ParserRecorder* log,
+                                      Scanner::BookmarkScope* bookmark,
+                                      int* use_counts);
 
  private:
   friend class PreParserTraits;
@@ -1027,7 +1103,12 @@
   Statement ParseSubStatement(AllowLabelledFunctionStatement allow_function,
                               bool* ok);
   Statement ParseScopedStatement(bool legacy, bool* ok);
+  Statement ParseHoistableDeclaration(bool* ok);
+  Statement ParseHoistableDeclaration(int pos, ParseFunctionFlags flags,
+                                      bool* ok);
   Statement ParseFunctionDeclaration(bool* ok);
+  Statement ParseAsyncFunctionDeclaration(bool* ok);
+  Expression ParseAsyncFunctionExpression(bool* ok);
   Statement ParseClassDeclaration(bool* ok);
   Statement ParseBlock(bool* ok);
   Statement ParseVariableStatement(VariableDeclarationContext var_context,
@@ -1077,6 +1158,8 @@
                                         Scanner::Location class_name_location,
                                         bool name_is_strict_reserved, int pos,
                                         bool* ok);
+
+  int* use_counts_;
 };
 
 
@@ -1114,6 +1197,9 @@
   // lists that are too long.
 }
 
+PreParserExpression PreParserTraits::ParseAsyncFunctionExpression(bool* ok) {
+  return pre_parser_->ParseAsyncFunctionExpression(ok);
+}
 
 PreParserExpression PreParserTraits::ParseDoExpression(bool* ok) {
   return pre_parser_->ParseDoExpression(ok);
@@ -1125,25 +1211,29 @@
   pre_parser_->ValidateExpression(classifier, ok);
 }
 
-
-Zone* PreParserTraits::zone() const {
-  return pre_parser_->function_state_->scope()->zone();
+PreParserExpression PreParserTraits::RewriteAwaitExpression(
+    PreParserExpression value, int pos) {
+  return value;
 }
 
-
 ZoneList<PreParserExpression>* PreParserTraits::GetNonPatternList() const {
   return pre_parser_->function_state_->non_patterns_to_rewrite();
 }
 
 
-PreParserExpression PreParserTraits::RewriteYieldStar(
-    PreParserExpression generator, PreParserExpression expression, int pos) {
-  return PreParserExpression::Default();
+ZoneList<typename PreParserTraits::Type::ExpressionClassifier::Error>*
+PreParserTraits::GetReportedErrorList() const {
+  return pre_parser_->function_state_->GetReportedErrorList();
 }
 
-PreParserExpression PreParserTraits::RewriteInstanceof(PreParserExpression lhs,
-                                                       PreParserExpression rhs,
-                                                       int pos) {
+
+Zone* PreParserTraits::zone() const {
+  return pre_parser_->function_state_->scope()->zone();
+}
+
+
+PreParserExpression PreParserTraits::RewriteYieldStar(
+    PreParserExpression generator, PreParserExpression expression, int pos) {
   return PreParserExpression::Default();
 }
 
@@ -1153,8 +1243,14 @@
     FunctionLiteral::FunctionType function_type, bool* ok) {
   ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
 
-  ParseStatementList(Token::RBRACE, ok);
-  if (!*ok) return PreParserStatementList();
+  Scope* inner_scope = scope_;
+  if (!parameters.is_simple) inner_scope = NewScope(scope_, BLOCK_SCOPE);
+
+  {
+    BlockState block_state(&scope_, inner_scope);
+    ParseStatementList(Token::RBRACE, ok);
+    if (!*ok) return PreParserStatementList();
+  }
 
   Expect(Token::RBRACE, ok);
   return PreParserStatementList();
diff --git a/src/parsing/scanner-character-streams.h b/src/parsing/scanner-character-streams.h
index 603db93..7e065cf 100644
--- a/src/parsing/scanner-character-streams.h
+++ b/src/parsing/scanner-character-streams.h
@@ -158,8 +158,10 @@
 
   void PushBack(uc32 character) override {
     DCHECK(buffer_cursor_ > raw_data_);
-    buffer_cursor_--;
     pos_--;
+    if (character != kEndOfInput) {
+      buffer_cursor_--;
+    }
   }
 
   bool SetBookmark() override;
diff --git a/src/parsing/scanner.cc b/src/parsing/scanner.cc
index 698cb5e..5fc848f 100644
--- a/src/parsing/scanner.cc
+++ b/src/parsing/scanner.cc
@@ -40,6 +40,7 @@
     : unicode_cache_(unicode_cache),
       bookmark_c0_(kNoBookmark),
       octal_pos_(Location::invalid()),
+      decimal_with_leading_zero_pos_(Location::invalid()),
       found_html_comment_(false),
       allow_harmony_exponentiation_operator_(false) {
   bookmark_current_.literal_chars = &bookmark_current_literal_;
@@ -249,6 +250,7 @@
   if (V8_UNLIKELY(next_next_.token != Token::UNINITIALIZED)) {
     next_ = next_next_;
     next_next_.token = Token::UNINITIALIZED;
+    has_line_terminator_before_next_ = has_line_terminator_after_next_;
     return current_.token;
   }
   has_line_terminator_before_next_ = false;
@@ -274,7 +276,12 @@
     return next_next_.token;
   }
   TokenDesc prev = current_;
+  bool has_line_terminator_before_next =
+      has_line_terminator_before_next_ || has_multiline_comment_before_next_;
   Next();
+  has_line_terminator_after_next_ =
+      has_line_terminator_before_next_ || has_multiline_comment_before_next_;
+  has_line_terminator_before_next_ = has_line_terminator_before_next;
   Token::Value ret = next_.token;
   next_next_ = next_;
   next_ = current_;
@@ -832,9 +839,6 @@
 }
 
 
-const int kMaxAscii = 127;
-
-
 Token::Value Scanner::ScanString() {
   uc32 quote = c0_;
   Advance<false, false>();  // consume quote
@@ -851,7 +855,7 @@
       Advance<false, false>();
       return Token::STRING;
     }
-    uc32 c = c0_;
+    char c = static_cast<char>(c0_);
     if (c == '\\') break;
     Advance<false, false>();
     AddLiteralChar(c);
@@ -975,10 +979,18 @@
 Token::Value Scanner::ScanNumber(bool seen_period) {
   DCHECK(IsDecimalDigit(c0_));  // the first digit of the number or the fraction
 
-  enum { DECIMAL, HEX, OCTAL, IMPLICIT_OCTAL, BINARY } kind = DECIMAL;
+  enum {
+    DECIMAL,
+    DECIMAL_WITH_LEADING_ZERO,
+    HEX,
+    OCTAL,
+    IMPLICIT_OCTAL,
+    BINARY
+  } kind = DECIMAL;
 
   LiteralScope literal(this);
   bool at_start = !seen_period;
+  int start_pos = source_pos();  // For reporting octal positions.
   if (seen_period) {
     // we have already seen a decimal point of the float
     AddLiteralChar('.');
@@ -987,7 +999,6 @@
   } else {
     // if the first character is '0' we must check for octals and hex
     if (c0_ == '0') {
-      int start_pos = source_pos();  // For reporting octal positions.
       AddLiteralCharAdvance();
 
       // either 0, 0exxx, 0Exxx, 0.xxx, a hex number, a binary number or
@@ -1029,7 +1040,7 @@
         while (true) {
           if (c0_ == '8' || c0_ == '9') {
             at_start = false;
-            kind = DECIMAL;
+            kind = DECIMAL_WITH_LEADING_ZERO;
             break;
           }
           if (c0_  < '0' || '7'  < c0_) {
@@ -1039,11 +1050,13 @@
           }
           AddLiteralCharAdvance();
         }
+      } else if (c0_ == '8' || c0_ == '9') {
+        kind = DECIMAL_WITH_LEADING_ZERO;
       }
     }
 
     // Parse decimal digits and allow trailing fractional part.
-    if (kind == DECIMAL) {
+    if (kind == DECIMAL || kind == DECIMAL_WITH_LEADING_ZERO) {
       if (at_start) {
         uint64_t value = 0;
         while (IsDecimalDigit(c0_)) {
@@ -1060,6 +1073,8 @@
           literal.Complete();
           HandleLeadSurrogate();
 
+          if (kind == DECIMAL_WITH_LEADING_ZERO)
+            decimal_with_leading_zero_pos_ = Location(start_pos, source_pos());
           return Token::SMI;
         }
         HandleLeadSurrogate();
@@ -1076,7 +1091,8 @@
   // scan exponent, if any
   if (c0_ == 'e' || c0_ == 'E') {
     DCHECK(kind != HEX);  // 'e'/'E' must be scanned as part of the hex number
-    if (kind != DECIMAL) return Token::ILLEGAL;
+    if (!(kind == DECIMAL || kind == DECIMAL_WITH_LEADING_ZERO))
+      return Token::ILLEGAL;
     // scan exponent
     AddLiteralCharAdvance();
     if (c0_ == '+' || c0_ == '-')
@@ -1098,6 +1114,8 @@
 
   literal.Complete();
 
+  if (kind == DECIMAL_WITH_LEADING_ZERO)
+    decimal_with_leading_zero_pos_ = Location(start_pos, source_pos());
   return Token::NUMBER;
 }
 
@@ -1135,6 +1153,9 @@
 // Keyword Matcher
 
 #define KEYWORDS(KEYWORD_GROUP, KEYWORD)                    \
+  KEYWORD_GROUP('a')                                        \
+  KEYWORD("async", Token::ASYNC)                            \
+  KEYWORD("await", Token::AWAIT)                            \
   KEYWORD_GROUP('b')                                        \
   KEYWORD("break", Token::BREAK)                            \
   KEYWORD_GROUP('c')                                        \
@@ -1150,7 +1171,7 @@
   KEYWORD("do", Token::DO)                                  \
   KEYWORD_GROUP('e')                                        \
   KEYWORD("else", Token::ELSE)                              \
-  KEYWORD("enum", Token::FUTURE_RESERVED_WORD)              \
+  KEYWORD("enum", Token::ENUM)                              \
   KEYWORD("export", Token::EXPORT)                          \
   KEYWORD("extends", Token::EXTENDS)                        \
   KEYWORD_GROUP('f')                                        \
@@ -1196,7 +1217,6 @@
   KEYWORD_GROUP('y')                                        \
   KEYWORD("yield", Token::YIELD)
 
-
 static Token::Value KeywordOrIdentifierToken(const uint8_t* input,
                                              int input_length, bool escaped) {
   DCHECK(input_length >= 1);
@@ -1260,7 +1280,7 @@
   LiteralScope literal(this);
   if (IsInRange(c0_, 'a', 'z')) {
     do {
-      uc32 first_char = c0_;
+      char first_char = static_cast<char>(c0_);
       Advance<false, false>();
       AddLiteralChar(first_char);
     } while (IsInRange(c0_, 'a', 'z'));
@@ -1268,11 +1288,11 @@
     if (IsDecimalDigit(c0_) || IsInRange(c0_, 'A', 'Z') || c0_ == '_' ||
         c0_ == '$') {
       // Identifier starting with lowercase.
-      uc32 first_char = c0_;
+      char first_char = static_cast<char>(c0_);
       Advance<false, false>();
       AddLiteralChar(first_char);
       while (IsAsciiIdentifier(c0_)) {
-        uc32 first_char = c0_;
+        char first_char = static_cast<char>(c0_);
         Advance<false, false>();
         AddLiteralChar(first_char);
       }
@@ -1290,7 +1310,7 @@
     HandleLeadSurrogate();
   } else if (IsInRange(c0_, 'A', 'Z') || c0_ == '_' || c0_ == '$') {
     do {
-      uc32 first_char = c0_;
+      char first_char = static_cast<char>(c0_);
       Advance<false, false>();
       AddLiteralChar(first_char);
     } while (IsAsciiIdentifier(c0_));
@@ -1433,7 +1453,6 @@
         flag = RegExp::kMultiline;
         break;
       case 'u':
-        if (!FLAG_harmony_unicode_regexps) return Nothing<RegExp::Flags>();
         flag = RegExp::kUnicode;
         break;
       case 'y':
@@ -1567,7 +1586,7 @@
                                int value) {
   uint32_t hash = Hash(key, is_one_byte);
   byte* encoding = BackupKey(key, is_one_byte);
-  HashMap::Entry* entry = map_.LookupOrInsert(encoding, hash);
+  base::HashMap::Entry* entry = map_.LookupOrInsert(encoding, hash);
   int old_value = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
   entry->value =
     reinterpret_cast<void*>(static_cast<intptr_t>(value | old_value));
diff --git a/src/parsing/scanner.h b/src/parsing/scanner.h
index 22c504c..610091c 100644
--- a/src/parsing/scanner.h
+++ b/src/parsing/scanner.h
@@ -8,16 +8,16 @@
 #define V8_PARSING_SCANNER_H_
 
 #include "src/allocation.h"
+#include "src/base/hashmap.h"
 #include "src/base/logging.h"
 #include "src/char-predicates.h"
 #include "src/collector.h"
 #include "src/globals.h"
-#include "src/hashmap.h"
 #include "src/list.h"
 #include "src/messages.h"
 #include "src/parsing/token.h"
-#include "src/unicode.h"
 #include "src/unicode-decoder.h"
+#include "src/unicode.h"
 
 namespace v8 {
 namespace internal {
@@ -143,22 +143,32 @@
   UnicodeCache* unicode_constants_;
   // Backing store used to store strings used as hashmap keys.
   SequenceCollector<unsigned char> backing_store_;
-  HashMap map_;
+  base::HashMap map_;
   // Buffer used for string->number->canonical string conversions.
   char number_buffer_[kBufferSize];
 };
 
-
 // ----------------------------------------------------------------------------
 // LiteralBuffer -  Collector of chars of literals.
 
+const int kMaxAscii = 127;
+
 class LiteralBuffer {
  public:
   LiteralBuffer() : is_one_byte_(true), position_(0), backing_store_() { }
 
   ~LiteralBuffer() { backing_store_.Dispose(); }
 
-  INLINE(void AddChar(uint32_t code_unit)) {
+  INLINE(void AddChar(char code_unit)) {
+    if (position_ >= backing_store_.length()) ExpandBuffer();
+    DCHECK(is_one_byte_);
+    DCHECK(0 <= code_unit && code_unit <= kMaxAscii);
+    backing_store_[position_] = static_cast<byte>(code_unit);
+    position_ += kOneByteSize;
+    return;
+  }
+
+  INLINE(void AddChar(uc32 code_unit)) {
     if (position_ >= backing_store_.length()) ExpandBuffer();
     if (is_one_byte_) {
       if (code_unit <= unibrow::Latin1::kMaxChar) {
@@ -225,8 +235,14 @@
     } else {
       is_one_byte_ = other->is_one_byte_;
       position_ = other->position_;
-      backing_store_.Dispose();
-      backing_store_ = other->backing_store_.Clone();
+      if (position_ < backing_store_.length()) {
+        std::copy(other->backing_store_.begin(),
+                  other->backing_store_.begin() + position_,
+                  backing_store_.begin());
+      } else {
+        backing_store_.Dispose();
+        backing_store_ = other->backing_store_.Clone();
+      }
     }
   }
 
@@ -419,6 +435,13 @@
   // Returns the location of the last seen octal literal.
   Location octal_position() const { return octal_pos_; }
   void clear_octal_position() { octal_pos_ = Location::invalid(); }
+  // Returns the location of the last seen decimal literal with a leading zero.
+  Location decimal_with_leading_zero_position() const {
+    return decimal_with_leading_zero_pos_;
+  }
+  void clear_decimal_with_leading_zero_position() {
+    decimal_with_leading_zero_pos_ = Location::invalid();
+  }
 
   // Returns the value of the last smi that was scanned.
   int smi_value() const { return current_.smi_value_; }
@@ -436,6 +459,12 @@
            has_multiline_comment_before_next_;
   }
 
+  bool HasAnyLineTerminatorAfterNext() {
+    Token::Value ensure_next_next = PeekAhead();
+    USE(ensure_next_next);
+    return has_line_terminator_after_next_;
+  }
+
   // Scans the input as a regular expression pattern, previous
   // character(s) must be /(=). Returns true if a pattern is scanned.
   bool ScanRegExpPattern(bool seen_equal);
@@ -538,6 +567,11 @@
     next_.literal_chars->AddChar(c);
   }
 
+  INLINE(void AddLiteralChar(char c)) {
+    DCHECK_NOT_NULL(next_.literal_chars);
+    next_.literal_chars->AddChar(c);
+  }
+
   INLINE(void AddRawLiteralChar(uc32 c)) {
     DCHECK_NOT_NULL(next_.raw_literal_chars);
     next_.raw_literal_chars->AddChar(c);
@@ -582,7 +616,7 @@
   }
 
   void PushBack(uc32 ch) {
-    if (ch > static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
+    if (c0_ > static_cast<uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
       source_->PushBack(unibrow::Utf16::TrailSurrogate(c0_));
       source_->PushBack(unibrow::Utf16::LeadSurrogate(c0_));
     } else {
@@ -766,9 +800,9 @@
   // Input stream. Must be initialized to an Utf16CharacterStream.
   Utf16CharacterStream* source_;
 
-
-  // Start position of the octal literal last scanned.
+  // Last-seen positions of potentially problematic tokens.
   Location octal_pos_;
+  Location decimal_with_leading_zero_pos_;
 
   // One Unicode character look-ahead; c0_ < 0 at the end of the input.
   uc32 c0_;
@@ -780,6 +814,7 @@
   // Whether there is a multi-line comment that contains a
   // line-terminator after the current token, and before the next.
   bool has_multiline_comment_before_next_;
+  bool has_line_terminator_after_next_;
 
   // Whether this scanner encountered an HTML comment.
   bool found_html_comment_;
diff --git a/src/parsing/token.h b/src/parsing/token.h
index fae9ea8..8b44cda 100644
--- a/src/parsing/token.h
+++ b/src/parsing/token.h
@@ -148,10 +148,13 @@
   T(IDENTIFIER, NULL, 0)                                             \
                                                                      \
   /* Future reserved words (ECMA-262, section 7.6.1.2). */           \
-  T(FUTURE_RESERVED_WORD, NULL, 0)                                   \
   T(FUTURE_STRICT_RESERVED_WORD, NULL, 0)                            \
+  K(ASYNC, "async", 0)                                               \
+  /* `await` is a reserved word in module code only */               \
+  K(AWAIT, "await", 0)                                               \
   K(CLASS, "class", 0)                                               \
   K(CONST, "const", 0)                                               \
+  K(ENUM, "enum", 0)                                                 \
   K(EXPORT, "export", 0)                                             \
   K(EXTENDS, "extends", 0)                                           \
   K(IMPORT, "import", 0)                                             \
@@ -173,7 +176,6 @@
   T(TEMPLATE_SPAN, NULL, 0)                                          \
   T(TEMPLATE_TAIL, NULL, 0)
 
-
 class Token {
  public:
   // All token values.
@@ -197,9 +199,10 @@
   }
 
   static bool IsIdentifier(Value tok, LanguageMode language_mode,
-                           bool is_generator) {
+                           bool is_generator, bool is_module) {
     switch (tok) {
       case IDENTIFIER:
+      case ASYNC:
         return true;
       case ESCAPED_STRICT_RESERVED_WORD:
       case FUTURE_STRICT_RESERVED_WORD:
@@ -208,6 +211,8 @@
         return is_sloppy(language_mode);
       case YIELD:
         return !is_generator && is_sloppy(language_mode);
+      case AWAIT:
+        return !is_module;
       default:
         return false;
     }
diff --git a/src/perf-jit.cc b/src/perf-jit.cc
index 6f35514..df251fd 100644
--- a/src/perf-jit.cc
+++ b/src/perf-jit.cc
@@ -28,6 +28,7 @@
 #include "src/perf-jit.h"
 
 #include "src/assembler.h"
+#include "src/eh-frame.h"
 #include "src/objects-inl.h"
 
 #if V8_OS_LINUX
@@ -56,7 +57,13 @@
 };
 
 struct PerfJitBase {
-  enum PerfJitEvent { kLoad = 0, kMove = 1, kDebugInfo = 2, kClose = 3 };
+  enum PerfJitEvent {
+    kLoad = 0,
+    kMove = 1,
+    kDebugInfo = 2,
+    kClose = 3,
+    kUnwindingInfo = 4
+  };
 
   uint32_t event_;
   uint32_t size_;
@@ -85,6 +92,13 @@
   // Followed by entry_count_ instances of PerfJitDebugEntry.
 };
 
+struct PerfJitCodeUnwindingInfo : PerfJitBase {
+  uint64_t unwinding_size_;
+  uint64_t eh_frame_hdr_size_;
+  uint64_t mapped_size_;
+  // Followed by size_ - sizeof(PerfJitCodeUnwindingInfo) bytes of data.
+};
+
 const char PerfJitLogger::kFilenameFormatString[] = "./jit-%d.dump";
 
 // Extra padding for the PID in the filename
@@ -204,6 +218,9 @@
   uint32_t code_size = code->is_crankshafted() ? code->safepoint_table_offset()
                                                : code->instruction_size();
 
+  // Unwinding info comes right after debug info.
+  if (FLAG_perf_prof_unwinding_info) LogWriteUnwindingInfo(code);
+
   static const char string_terminator[] = "\0";
 
   PerfJitCodeLoad code_load;
@@ -303,6 +320,46 @@
   LogWriteBytes(padding_bytes, padding);
 }
 
+void PerfJitLogger::LogWriteUnwindingInfo(Code* code) {
+  EhFrameHdr eh_frame_hdr(code);
+
+  PerfJitCodeUnwindingInfo unwinding_info_header;
+  unwinding_info_header.event_ = PerfJitCodeLoad::kUnwindingInfo;
+  unwinding_info_header.time_stamp_ = GetTimestamp();
+  unwinding_info_header.eh_frame_hdr_size_ = EhFrameHdr::kRecordSize;
+
+  if (code->has_unwinding_info()) {
+    unwinding_info_header.unwinding_size_ = code->unwinding_info_size();
+    unwinding_info_header.mapped_size_ = unwinding_info_header.unwinding_size_;
+  } else {
+    unwinding_info_header.unwinding_size_ = EhFrameHdr::kRecordSize;
+    unwinding_info_header.mapped_size_ = 0;
+  }
+
+  int content_size = static_cast<int>(sizeof(unwinding_info_header) +
+                                      unwinding_info_header.unwinding_size_);
+  int padding_size = RoundUp(content_size, 8) - content_size;
+  unwinding_info_header.size_ = content_size + padding_size;
+
+  LogWriteBytes(reinterpret_cast<const char*>(&unwinding_info_header),
+                sizeof(unwinding_info_header));
+
+  if (code->has_unwinding_info()) {
+    // The last EhFrameHdr::kRecordSize bytes were a placeholder for the header.
+    // Discard them and write the actual eh_frame_hdr (below).
+    DCHECK_GE(code->unwinding_info_size(), EhFrameHdr::kRecordSize);
+    LogWriteBytes(reinterpret_cast<const char*>(code->unwinding_info_start()),
+                  code->unwinding_info_size() - EhFrameHdr::kRecordSize);
+  }
+
+  LogWriteBytes(reinterpret_cast<const char*>(&eh_frame_hdr),
+                EhFrameHdr::kRecordSize);
+
+  char padding_bytes[] = "\0\0\0\0\0\0\0\0";
+  DCHECK_LT(padding_size, sizeof(padding_bytes));
+  LogWriteBytes(padding_bytes, padding_size);
+}
+
 void PerfJitLogger::CodeMoveEvent(AbstractCode* from, Address to) {
   // Code relocation not supported.
   UNREACHABLE();
diff --git a/src/perf-jit.h b/src/perf-jit.h
index 25cc3b3..6efa4bb 100644
--- a/src/perf-jit.h
+++ b/src/perf-jit.h
@@ -66,11 +66,13 @@
   void LogWriteBytes(const char* bytes, int size);
   void LogWriteHeader();
   void LogWriteDebugInfo(Code* code, SharedFunctionInfo* shared);
+  void LogWriteUnwindingInfo(Code* code);
 
   static const uint32_t kElfMachIA32 = 3;
   static const uint32_t kElfMachX64 = 62;
   static const uint32_t kElfMachARM = 40;
   static const uint32_t kElfMachMIPS = 10;
+  static const uint32_t kElfMachARM64 = 183;
 
   uint32_t GetElfMach() {
 #if V8_TARGET_ARCH_IA32
@@ -81,6 +83,8 @@
     return kElfMachARM;
 #elif V8_TARGET_ARCH_MIPS
     return kElfMachMIPS;
+#elif V8_TARGET_ARCH_ARM64
+    return kElfMachARM64;
 #else
     UNIMPLEMENTED();
     return 0;
diff --git a/src/ppc/OWNERS b/src/ppc/OWNERS
index eb007cb..752e8e3 100644
--- a/src/ppc/OWNERS
+++ b/src/ppc/OWNERS
@@ -3,3 +3,4 @@
 joransiu@ca.ibm.com
 mbrandy@us.ibm.com
 michael_dawson@ca.ibm.com
+bjaideep@ca.ibm.com
diff --git a/src/ppc/assembler-ppc-inl.h b/src/ppc/assembler-ppc-inl.h
index c495fee..59d3248 100644
--- a/src/ppc/assembler-ppc-inl.h
+++ b/src/ppc/assembler-ppc-inl.h
@@ -89,11 +89,6 @@
   return Assembler::target_address_at(pc_, host_);
 }
 
-Address RelocInfo::wasm_memory_reference() {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  return Assembler::target_address_at(pc_, host_);
-}
-
 Address RelocInfo::target_address_address() {
   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) ||
          rmode_ == EMBEDDED_OBJECT || rmode_ == EXTERNAL_REFERENCE);
@@ -183,19 +178,6 @@
   return pc + (len + 2) * kInstrSize;
 }
 
-void RelocInfo::update_wasm_memory_reference(
-    Address old_base, Address new_base, size_t old_size, size_t new_size,
-    ICacheFlushMode icache_flush_mode) {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  DCHECK(old_base <= wasm_memory_reference() &&
-         wasm_memory_reference() < old_base + old_size);
-  Address updated_reference = new_base + (wasm_memory_reference() - old_base);
-  DCHECK(new_base <= updated_reference &&
-         updated_reference < new_base + new_size);
-  Assembler::set_target_address_at(isolate_, pc_, host_, updated_reference,
-                                   icache_flush_mode);
-}
-
 Object* RelocInfo::target_object() {
   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
   return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_));
@@ -343,7 +325,7 @@
   }
 }
 
-
+template <typename ObjectVisitor>
 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
diff --git a/src/ppc/assembler-ppc.cc b/src/ppc/assembler-ppc.cc
index 507eec1..2ce601e 100644
--- a/src/ppc/assembler-ppc.cc
+++ b/src/ppc/assembler-ppc.cc
@@ -155,6 +155,33 @@
   return false;
 }
 
+Address RelocInfo::wasm_memory_reference() {
+  DCHECK(IsWasmMemoryReference(rmode_));
+  return Assembler::target_address_at(pc_, host_);
+}
+
+uint32_t RelocInfo::wasm_memory_size_reference() {
+  DCHECK(IsWasmMemorySizeReference(rmode_));
+  return static_cast<uint32_t>(
+     reinterpret_cast<intptr_t>(Assembler::target_address_at(pc_, host_)));
+}
+
+Address RelocInfo::wasm_global_reference() {
+  DCHECK(IsWasmGlobalReference(rmode_));
+  return Assembler::target_address_at(pc_, host_);
+}
+
+
+void RelocInfo::unchecked_update_wasm_memory_reference(
+    Address address, ICacheFlushMode flush_mode) {
+  Assembler::set_target_address_at(isolate_, pc_, host_, address, flush_mode);
+}
+
+void RelocInfo::unchecked_update_wasm_memory_size(uint32_t size,
+                                                  ICacheFlushMode flush_mode) {
+  Assembler::set_target_address_at(isolate_, pc_, host_,
+                                   reinterpret_cast<Address>(size), flush_mode);
+}
 
 // -----------------------------------------------------------------------------
 // Implementation of Operand and MemOperand
@@ -230,6 +257,8 @@
   desc->constant_pool_size =
       (constant_pool_offset ? desc->instr_size - constant_pool_offset : 0);
   desc->origin = this;
+  desc->unwinding_info_size = 0;
+  desc->unwinding_info = nullptr;
 }
 
 
@@ -678,13 +707,11 @@
 
 
 void Assembler::bclr(BOfield bo, int condition_bit, LKBit lk) {
-  positions_recorder()->WriteRecordedPositions();
   emit(EXT1 | bo | condition_bit * B16 | BCLRX | lk);
 }
 
 
 void Assembler::bcctr(BOfield bo, int condition_bit, LKBit lk) {
-  positions_recorder()->WriteRecordedPositions();
   emit(EXT1 | bo | condition_bit * B16 | BCCTRX | lk);
 }
 
@@ -701,9 +728,6 @@
 
 
 void Assembler::bc(int branch_offset, BOfield bo, int condition_bit, LKBit lk) {
-  if (lk == SetLK) {
-    positions_recorder()->WriteRecordedPositions();
-  }
   int imm16 = branch_offset;
   CHECK(is_int16(imm16) && (imm16 & (kAAMask | kLKMask)) == 0);
   emit(BCX | bo | condition_bit * B16 | (imm16 & kImm16Mask) | lk);
@@ -711,9 +735,6 @@
 
 
 void Assembler::b(int branch_offset, LKBit lk) {
-  if (lk == SetLK) {
-    positions_recorder()->WriteRecordedPositions();
-  }
   int imm26 = branch_offset;
   CHECK(is_int26(imm26) && (imm26 & (kAAMask | kLKMask)) == 0);
   emit(BX | (imm26 & kImm26Mask) | lk);
diff --git a/src/ppc/assembler-ppc.h b/src/ppc/assembler-ppc.h
index 3e8be7d..24166e3 100644
--- a/src/ppc/assembler-ppc.h
+++ b/src/ppc/assembler-ppc.h
@@ -109,6 +109,8 @@
   V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
   V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
 
+#define FLOAT_REGISTERS DOUBLE_REGISTERS
+
 #define ALLOCATABLE_DOUBLE_REGISTERS(V)                   \
   V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)         \
   V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d15)               \
@@ -164,8 +166,6 @@
     Register r = {code};
     return r;
   }
-  const char* ToString();
-  bool IsAllocatable() const;
   bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
   bool is(Register reg) const { return reg_code == reg.reg_code; }
   int code() const {
@@ -204,6 +204,8 @@
 const Register kRootRegister = r29;          // Roots array pointer.
 const Register cp = r30;                     // JavaScript context pointer.
 
+static const bool kSimpleFPAliasing = true;
+
 // Double word FP register.
 struct DoubleRegister {
   enum Code {
@@ -217,8 +219,6 @@
   static const int kNumRegisters = Code::kAfterLast;
   static const int kMaxNumRegisters = kNumRegisters;
 
-  const char* ToString();
-  bool IsAllocatable() const;
   bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
   bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
   int code() const {
@@ -238,6 +238,11 @@
   int reg_code;
 };
 
+typedef DoubleRegister FloatRegister;
+
+// TODO(ppc) Define SIMD registers.
+typedef DoubleRegister Simd128Register;
+
 #define DECLARE_REGISTER(R) \
   const DoubleRegister R = {DoubleRegister::kCode_##R};
 DOUBLE_REGISTERS(DECLARE_REGISTER)
@@ -283,9 +288,6 @@
 const CRegister cr6 = {6};
 const CRegister cr7 = {7};
 
-// TODO(ppc) Define SIMD registers.
-typedef DoubleRegister Simd128Register;
-
 // -----------------------------------------------------------------------------
 // Machine instruction Operands
 
@@ -1210,7 +1212,7 @@
 
   // Record a deoptimization reason that can be used by a log or cpu profiler.
   // Use --trace-deopt to enable.
-  void RecordDeoptReason(const int reason, int raw_position);
+  void RecordDeoptReason(const int reason, int raw_position, int id);
 
   // Writes a single byte or word of data in the code stream.  Used
   // for inline tables, e.g., jump-tables.
diff --git a/src/ppc/builtins-ppc.cc b/src/ppc/builtins-ppc.cc
index 884afed..c3c2b84 100644
--- a/src/ppc/builtins-ppc.cc
+++ b/src/ppc/builtins-ppc.cc
@@ -17,8 +17,7 @@
 #define __ ACCESS_MASM(masm)
 
 
-void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
-                                BuiltinExtraArguments extra_args) {
+void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
   // ----------- S t a t e -------------
   //  -- r3                 : number of arguments excluding receiver
   //  -- r4                 : target
@@ -37,23 +36,8 @@
   __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
 
   // Insert extra arguments.
-  int num_extra_args = 0;
-  switch (extra_args) {
-    case BuiltinExtraArguments::kTarget:
-      __ Push(r4);
-      ++num_extra_args;
-      break;
-    case BuiltinExtraArguments::kNewTarget:
-      __ Push(r6);
-      ++num_extra_args;
-      break;
-    case BuiltinExtraArguments::kTargetAndNewTarget:
-      __ Push(r4, r6);
-      num_extra_args += 2;
-      break;
-    case BuiltinExtraArguments::kNone:
-      break;
-  }
+  const int num_extra_args = 2;
+  __ Push(r4, r6);
 
   // JumpToExternalReference expects r3 to contain the number of arguments
   // including the receiver and the extra arguments.
@@ -139,6 +123,8 @@
 void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
   // ----------- S t a t e -------------
   //  -- r3                 : number of arguments
+  //  -- r4                 : function
+  //  -- cp                 : context
   //  -- lr                 : return address
   //  -- sp[(argc - n) * 8] : arg[n] (zero-based)
   //  -- sp[(argc + 1) * 8] : receiver
@@ -150,58 +136,69 @@
   DoubleRegister const reg = (kind == MathMaxMinKind::kMin) ? d2 : d1;
 
   // Load the accumulator with the default return value (either -Infinity or
-  // +Infinity), with the tagged value in r4 and the double value in d1.
-  __ LoadRoot(r4, root_index);
-  __ lfd(d1, FieldMemOperand(r4, HeapNumber::kValueOffset));
+  // +Infinity), with the tagged value in r8 and the double value in d1.
+  __ LoadRoot(r8, root_index);
+  __ lfd(d1, FieldMemOperand(r8, HeapNumber::kValueOffset));
 
   // Setup state for loop
   // r5: address of arg[0] + kPointerSize
   // r6: number of slots to drop at exit (arguments + receiver)
-  __ ShiftLeftImm(r5, r3, Operand(kPointerSizeLog2));
-  __ add(r5, sp, r5);
-  __ addi(r6, r3, Operand(1));
+  __ addi(r7, r3, Operand(1));
 
   Label done_loop, loop;
   __ bind(&loop);
   {
     // Check if all parameters done.
-    __ cmpl(r5, sp);
-    __ ble(&done_loop);
+    __ subi(r3, r3, Operand(1));
+    __ cmpi(r3, Operand::Zero());
+    __ blt(&done_loop);
 
-    // Load the next parameter tagged value into r3.
-    __ LoadPU(r3, MemOperand(r5, -kPointerSize));
+    // Load the next parameter tagged value into r5.
+    __ ShiftLeftImm(r5, r3, Operand(kPointerSizeLog2));
+    __ LoadPX(r5, MemOperand(sp, r5));
 
     // Load the double value of the parameter into d2, maybe converting the
-    // parameter to a number first using the ToNumberStub if necessary.
+    // parameter to a number first using the ToNumber builtin if necessary.
     Label convert, convert_smi, convert_number, done_convert;
     __ bind(&convert);
-    __ JumpIfSmi(r3, &convert_smi);
-    __ LoadP(r7, FieldMemOperand(r3, HeapObject::kMapOffset));
-    __ JumpIfRoot(r7, Heap::kHeapNumberMapRootIndex, &convert_number);
+    __ JumpIfSmi(r5, &convert_smi);
+    __ LoadP(r6, FieldMemOperand(r5, HeapObject::kMapOffset));
+    __ JumpIfRoot(r6, Heap::kHeapNumberMapRootIndex, &convert_number);
     {
-      // Parameter is not a Number, use the ToNumberStub to convert it.
-      FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
-      __ SmiTag(r6);
-      __ Push(r4, r5, r6);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
-      __ Pop(r4, r5, r6);
-      __ SmiUntag(r6);
+      // Parameter is not a Number, use the ToNumber builtin to convert it.
+      FrameScope scope(masm, StackFrame::MANUAL);
+      __ PushStandardFrame(r4);
+      __ SmiTag(r3);
+      __ SmiTag(r7);
+      __ Push(r3, r7, r8);
+      __ mr(r3, r5);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
+      __ mr(r5, r3);
+      __ Pop(r3, r7, r8);
       {
         // Restore the double accumulator value (d1).
         Label done_restore;
-        __ SmiToDouble(d1, r4);
-        __ JumpIfSmi(r4, &done_restore);
-        __ lfd(d1, FieldMemOperand(r4, HeapNumber::kValueOffset));
+        __ SmiToDouble(d1, r8);
+        __ JumpIfSmi(r8, &done_restore);
+        __ lfd(d1, FieldMemOperand(r8, HeapNumber::kValueOffset));
         __ bind(&done_restore);
       }
+      __ SmiUntag(r7);
+      __ SmiUntag(r3);
+      // TODO(Jaideep): Add macro furtion for PopStandardFrame
+      if (FLAG_enable_embedded_constant_pool) {
+        __ Pop(r0, fp, kConstantPoolRegister, cp, r4);
+      } else {
+        __ Pop(r0, fp, cp, r4);
+      }
+      __ mtlr(r0);
     }
     __ b(&convert);
     __ bind(&convert_number);
-    __ lfd(d2, FieldMemOperand(r3, HeapNumber::kValueOffset));
+    __ lfd(d2, FieldMemOperand(r5, HeapNumber::kValueOffset));
     __ b(&done_convert);
     __ bind(&convert_smi);
-    __ SmiToDouble(d2, r3);
+    __ SmiToDouble(d2, r5);
     __ bind(&done_convert);
 
     // Perform the actual comparison with the accumulator value on the left hand
@@ -213,26 +210,26 @@
     __ b(CommuteCondition(cond_done), &compare_swap);
 
     // Left and right hand side are equal, check for -0 vs. +0.
-    __ TestDoubleIsMinusZero(reg, r7, r8);
+    __ TestDoubleIsMinusZero(reg, r9, r0);
     __ bne(&loop);
 
     // Update accumulator. Result is on the right hand side.
     __ bind(&compare_swap);
     __ fmr(d1, d2);
-    __ mr(r4, r3);
+    __ mr(r8, r5);
     __ b(&loop);
 
     // At least one side is NaN, which means that the result will be NaN too.
     // We still need to visit the rest of the arguments.
     __ bind(&compare_nan);
-    __ LoadRoot(r4, Heap::kNanValueRootIndex);
-    __ lfd(d1, FieldMemOperand(r4, HeapNumber::kValueOffset));
+    __ LoadRoot(r8, Heap::kNanValueRootIndex);
+    __ lfd(d1, FieldMemOperand(r8, HeapNumber::kValueOffset));
     __ b(&loop);
   }
 
   __ bind(&done_loop);
-  __ mr(r3, r4);
-  __ Drop(r6);
+  __ mr(r3, r8);
+  __ Drop(r7);
   __ Ret();
 }
 
@@ -259,8 +256,7 @@
   }
 
   // 2a. Convert the first argument to a number.
-  ToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
+  __ Jump(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
 
   // 2b. No arguments, return +0.
   __ bind(&no_arguments);
@@ -310,8 +306,7 @@
       FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
       __ Push(r4, r6);
       __ mr(r3, r5);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
       __ mr(r5, r3);
       __ Pop(r4, r6);
     }
@@ -605,15 +600,10 @@
     // r3: number of arguments
     // r4: constructor function
     // r6: new target
-    if (is_api_function) {
-      __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
-      Handle<Code> code = masm->isolate()->builtins()->HandleApiCallConstruct();
-      __ Call(code, RelocInfo::CODE_TARGET);
-    } else {
-      ParameterCount actual(r3);
-      __ InvokeFunction(r4, r6, actual, CALL_FUNCTION,
-                        CheckDebugStepCallWrapper());
-    }
+
+    ParameterCount actual(r3);
+    __ InvokeFunction(r4, r6, actual, CALL_FUNCTION,
+                      CheckDebugStepCallWrapper());
 
     // Store offset of return address for deoptimizer.
     if (create_implicit_receiver && !is_api_function) {
@@ -705,6 +695,177 @@
   Generate_JSConstructStubHelper(masm, false, false, true);
 }
 
+// static
+void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r3 : the value to pass to the generator
+  //  -- r4 : the JSGeneratorObject to resume
+  //  -- r5 : the resume mode (tagged)
+  //  -- lr : return address
+  // -----------------------------------
+  __ AssertGeneratorObject(r4);
+
+  // Store input value into generator object.
+  __ StoreP(r3, FieldMemOperand(r4, JSGeneratorObject::kInputOrDebugPosOffset),
+            r0);
+  __ RecordWriteField(r4, JSGeneratorObject::kInputOrDebugPosOffset, r3, r6,
+                      kLRHasNotBeenSaved, kDontSaveFPRegs);
+
+  // Store resume mode into generator object.
+  __ StoreP(r5, FieldMemOperand(r4, JSGeneratorObject::kResumeModeOffset), r0);
+
+  // Load suspended function and context.
+  __ LoadP(cp, FieldMemOperand(r4, JSGeneratorObject::kContextOffset));
+  __ LoadP(r7, FieldMemOperand(r4, JSGeneratorObject::kFunctionOffset));
+
+  // Flood function if we are stepping.
+  Label prepare_step_in_if_stepping, prepare_step_in_suspended_generator;
+  Label stepping_prepared;
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(masm->isolate());
+  STATIC_ASSERT(StepFrame > StepIn);
+  __ mov(ip, Operand(last_step_action));
+  __ LoadByte(ip, MemOperand(ip), r0);
+  __ extsb(ip, ip);
+  __ cmpi(ip, Operand(StepIn));
+  __ bge(&prepare_step_in_if_stepping);
+
+  // Flood function if we need to continue stepping in the suspended generator.
+
+  ExternalReference debug_suspended_generator =
+      ExternalReference::debug_suspended_generator_address(masm->isolate());
+
+  __ mov(ip, Operand(debug_suspended_generator));
+  __ LoadP(ip, MemOperand(ip));
+  __ cmp(ip, r4);
+  __ beq(&prepare_step_in_suspended_generator);
+  __ bind(&stepping_prepared);
+
+  // Push receiver.
+  __ LoadP(ip, FieldMemOperand(r4, JSGeneratorObject::kReceiverOffset));
+  __ Push(ip);
+
+  // ----------- S t a t e -------------
+  //  -- r4    : the JSGeneratorObject to resume
+  //  -- r5    : the resume mode (tagged)
+  //  -- r7    : generator function
+  //  -- cp    : generator context
+  //  -- lr    : return address
+  //  -- sp[0] : generator receiver
+  // -----------------------------------
+
+  // Push holes for arguments to generator function. Since the parser forced
+  // context allocation for any variables in generators, the actual argument
+  // values have already been copied into the context and these dummy values
+  // will never be used.
+  __ LoadP(r6, FieldMemOperand(r7, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadWordArith(
+      r3, FieldMemOperand(r6, SharedFunctionInfo::kFormalParameterCountOffset));
+  {
+    Label loop, done_loop;
+    __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+#if V8_TARGET_ARCH_PPC64
+    __ cmpi(r3, Operand::Zero());
+    __ beq(&done_loop);
+#else
+    __ SmiUntag(r3, SetRC);
+    __ beq(&done_loop, cr0);
+#endif
+    __ mtctr(r3);
+    __ bind(&loop);
+    __ push(ip);
+    __ bdnz(&loop);
+    __ bind(&done_loop);
+  }
+
+  // Dispatch on the kind of generator object.
+  Label old_generator;
+  __ LoadP(r6, FieldMemOperand(r6, SharedFunctionInfo::kFunctionDataOffset));
+  __ CompareObjectType(r6, r6, r6, BYTECODE_ARRAY_TYPE);
+  __ bne(&old_generator);
+
+  // New-style (ignition/turbofan) generator object
+  {
+    // We abuse new.target both to indicate that this is a resume call and to
+    // pass in the generator object.  In ordinary calls, new.target is always
+    // undefined because generator functions are non-constructable.
+    __ mr(r6, r4);
+    __ mr(r4, r7);
+    __ LoadP(ip, FieldMemOperand(r4, JSFunction::kCodeEntryOffset));
+    __ JumpToJSEntry(ip);
+  }
+
+  // Old-style (full-codegen) generator object
+  __ bind(&old_generator);
+  {
+    // Enter a new JavaScript frame, and initialize its slots as they were when
+    // the generator was suspended.
+    FrameScope scope(masm, StackFrame::MANUAL);
+    __ PushStandardFrame(r7);
+
+    // Restore the operand stack.
+    __ LoadP(r3, FieldMemOperand(r4, JSGeneratorObject::kOperandStackOffset));
+    __ LoadP(r6, FieldMemOperand(r3, FixedArray::kLengthOffset));
+    __ addi(r3, r3,
+            Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize));
+    {
+      Label loop, done_loop;
+      __ SmiUntag(r6, SetRC);
+      __ beq(&done_loop, cr0);
+      __ mtctr(r6);
+      __ bind(&loop);
+      __ LoadPU(ip, MemOperand(r3, kPointerSize));
+      __ Push(ip);
+      __ bdnz(&loop);
+      __ bind(&done_loop);
+    }
+
+    // Reset operand stack so we don't leak.
+    __ LoadRoot(ip, Heap::kEmptyFixedArrayRootIndex);
+    __ StoreP(ip, FieldMemOperand(r4, JSGeneratorObject::kOperandStackOffset),
+              r0);
+
+    // Resume the generator function at the continuation.
+    __ LoadP(r6, FieldMemOperand(r7, JSFunction::kSharedFunctionInfoOffset));
+    __ LoadP(r6, FieldMemOperand(r6, SharedFunctionInfo::kCodeOffset));
+    __ addi(r6, r6, Operand(Code::kHeaderSize - kHeapObjectTag));
+    {
+      ConstantPoolUnavailableScope constant_pool_unavailable(masm);
+      if (FLAG_enable_embedded_constant_pool) {
+        __ LoadConstantPoolPointerRegisterFromCodeTargetAddress(r6);
+      }
+      __ LoadP(r5, FieldMemOperand(r4, JSGeneratorObject::kContinuationOffset));
+      __ SmiUntag(r5);
+      __ add(r6, r6, r5);
+      __ LoadSmiLiteral(r5,
+                        Smi::FromInt(JSGeneratorObject::kGeneratorExecuting));
+      __ StoreP(r5, FieldMemOperand(r4, JSGeneratorObject::kContinuationOffset),
+                r0);
+      __ mr(r3, r4);  // Continuation expects generator object in r3.
+      __ Jump(r6);
+    }
+  }
+
+  __ bind(&prepare_step_in_if_stepping);
+  {
+    FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
+    __ Push(r4, r5, r7);
+    __ CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
+    __ Pop(r4, r5);
+    __ LoadP(r7, FieldMemOperand(r4, JSGeneratorObject::kFunctionOffset));
+  }
+  __ b(&stepping_prepared);
+
+  __ bind(&prepare_step_in_suspended_generator);
+  {
+    FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
+    __ Push(r4, r5);
+    __ CallRuntime(Runtime::kDebugPrepareStepInSuspendedGenerator);
+    __ Pop(r4, r5);
+    __ LoadP(r7, FieldMemOperand(r4, JSGeneratorObject::kFunctionOffset));
+  }
+  __ b(&stepping_prepared);
+}
 
 void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
   FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
@@ -829,6 +990,20 @@
   Generate_JSEntryTrampolineHelper(masm, true);
 }
 
+static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch) {
+  Register args_count = scratch;
+
+  // Get the arguments + receiver count.
+  __ LoadP(args_count,
+           MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
+  __ lwz(args_count,
+         FieldMemOperand(args_count, BytecodeArray::kParameterSizeOffset));
+
+  // Leave the frame (also dropping the register file).
+  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+
+  __ add(sp, sp, args_count);
+}
 
 // Generate code for entering a JS function with the interpreter.
 // On entry to the function the receiver and arguments have been pushed on the
@@ -847,14 +1022,16 @@
 // The function builds an interpreter frame.  See InterpreterFrameConstants in
 // frames.h for its layout.
 void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
+  ProfileEntryHookStub::MaybeCallEntryHook(masm);
+
   // Open a frame scope to indicate that there is a frame on the stack.  The
   // MANUAL indicates that the scope shouldn't actually generate code to set up
   // the frame (that is done below).
   FrameScope frame_scope(masm, StackFrame::MANUAL);
   __ PushStandardFrame(r4);
 
-  // Get the bytecode array from the function object and load the pointer to the
-  // first entry into kInterpreterBytecodeRegister.
+  // Get the bytecode array from the function object (or from the DebugInfo if
+  // it is present) and load it into kInterpreterBytecodeArrayRegister.
   __ LoadP(r3, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
   Label array_done;
   Register debug_info = r5;
@@ -870,8 +1047,13 @@
            FieldMemOperand(debug_info, DebugInfo::kAbstractCodeIndex));
   __ bind(&array_done);
 
+  // Check function data field is actually a BytecodeArray object.
+  Label bytecode_array_not_present;
+  __ CompareRoot(kInterpreterBytecodeArrayRegister,
+                 Heap::kUndefinedValueRootIndex);
+  __ beq(&bytecode_array_not_present);
+
   if (FLAG_debug_code) {
-    // Check function data field is actually a BytecodeArray object.
     __ TestIfSmi(kInterpreterBytecodeArrayRegister, r0);
     __ Assert(ne, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
     __ CompareObjectType(kInterpreterBytecodeArrayRegister, r3, no_reg,
@@ -879,8 +1061,12 @@
     __ Assert(eq, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
   }
 
-  // Push new.target, bytecode array and zero for bytecode array offset.
-  __ li(r3, Operand::Zero());
+  // Load initial bytecode offset.
+  __ mov(kInterpreterBytecodeOffsetRegister,
+         Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
+
+  // Push new.target, bytecode array and Smi tagged bytecode array offset.
+  __ SmiTag(r3, kInterpreterBytecodeOffsetRegister);
   __ Push(r6, kInterpreterBytecodeArrayRegister, r3);
 
   // Allocate the local and temporary register file on the stack.
@@ -911,18 +1097,8 @@
     __ bind(&no_args);
   }
 
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's prologue:
-  //  - Call ProfileEntryHookStub when isolate has a function_entry_hook.
-  //  - Code aging of the BytecodeArray object.
-
-  // Load accumulator, register file, bytecode offset, dispatch table into
-  // registers.
+  // Load accumulator and dispatch table into registers.
   __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
-  __ addi(kInterpreterRegisterFileRegister, fp,
-          Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
-  __ mov(kInterpreterBytecodeOffsetRegister,
-         Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
   __ mov(kInterpreterDispatchTableRegister,
          Operand(ExternalReference::interpreter_dispatch_table_address(
              masm->isolate())));
@@ -932,36 +1108,52 @@
                          kInterpreterBytecodeOffsetRegister));
   __ ShiftLeftImm(ip, r4, Operand(kPointerSizeLog2));
   __ LoadPX(ip, MemOperand(kInterpreterDispatchTableRegister, ip));
-  // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
-  // and header removal.
-  __ addi(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Call(ip);
 
-  // Even though the first bytecode handler was called, we will never return.
-  __ Abort(kUnexpectedReturnFromBytecodeHandler);
+  masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
+
+  // The return value is in r3.
+  LeaveInterpreterFrame(masm, r5);
+  __ blr();
+
+  // If the bytecode array is no longer present, then the underlying function
+  // has been switched to a different kind of code and we heal the closure by
+  // switching the code entry field over to the new code object as well.
+  __ bind(&bytecode_array_not_present);
+  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+  __ LoadP(r7, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadP(r7, FieldMemOperand(r7, SharedFunctionInfo::kCodeOffset));
+  __ addi(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ StoreP(r7, FieldMemOperand(r4, JSFunction::kCodeEntryOffset), r0);
+  __ RecordWriteCodeEntryField(r4, r7, r8);
+  __ JumpToJSEntry(r7);
 }
 
+void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) {
+  // Save the function and context for call to CompileBaseline.
+  __ LoadP(r4, MemOperand(fp, StandardFrameConstants::kFunctionOffset));
+  __ LoadP(kContextRegister,
+           MemOperand(fp, StandardFrameConstants::kContextOffset));
 
-void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's EmitReturnSequence.
-  //  - Supporting FLAG_trace for Runtime::TraceExit.
-  //  - Support profiler (specifically decrementing profiling_counter
-  //    appropriately and calling out to HandleInterrupts if necessary).
+  // Leave the frame before recompiling for baseline so that we don't count as
+  // an activation on the stack.
+  LeaveInterpreterFrame(masm, r5);
 
-  // The return value is in accumulator, which is already in r3.
+  {
+    FrameScope frame_scope(masm, StackFrame::INTERNAL);
+    // Push return value.
+    __ push(r3);
 
-  // Leave the frame (also dropping the register file).
-  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+    // Push function as argument and compile for baseline.
+    __ push(r4);
+    __ CallRuntime(Runtime::kCompileBaseline);
 
-  // Drop receiver + arguments and return.
-  __ lwz(r0, FieldMemOperand(kInterpreterBytecodeArrayRegister,
-                             BytecodeArray::kParameterSizeOffset));
-  __ add(sp, sp, r0);
+    // Restore return value.
+    __ pop(r3);
+  }
   __ blr();
 }
 
-
 static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register index,
                                          Register count, Register scratch) {
   Label loop;
@@ -973,7 +1165,6 @@
   __ bdnz(&loop);
 }
 
-
 // static
 void Builtins::Generate_InterpreterPushArgsAndCallImpl(
     MacroAssembler* masm, TailCallMode tail_call_mode) {
@@ -997,7 +1188,6 @@
           RelocInfo::CODE_TARGET);
 }
 
-
 // static
 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
   // ----------- S t a t e -------------
@@ -1022,25 +1212,25 @@
   __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
 }
 
+void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
+  // Set the return address to the correct point in the interpreter entry
+  // trampoline.
+  Smi* interpreter_entry_return_pc_offset(
+      masm->isolate()->heap()->interpreter_entry_return_pc_offset());
+  DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
+  __ Move(r5, masm->isolate()->builtins()->InterpreterEntryTrampoline());
+  __ addi(r0, r5, Operand(interpreter_entry_return_pc_offset->value() +
+                          Code::kHeaderSize - kHeapObjectTag));
+  __ mtlr(r0);
 
-static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
-  // Initialize register file register and dispatch table register.
-  __ addi(kInterpreterRegisterFileRegister, fp,
-          Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
+  // Initialize the dispatch table register.
   __ mov(kInterpreterDispatchTableRegister,
          Operand(ExternalReference::interpreter_dispatch_table_address(
              masm->isolate())));
 
-  // Get the context from the frame.
-  __ LoadP(kContextRegister,
-           MemOperand(kInterpreterRegisterFileRegister,
-                      InterpreterFrameConstants::kContextFromRegisterPointer));
-
   // Get the bytecode array pointer from the frame.
-  __ LoadP(
-      kInterpreterBytecodeArrayRegister,
-      MemOperand(kInterpreterRegisterFileRegister,
-                 InterpreterFrameConstants::kBytecodeArrayFromRegisterPointer));
+  __ LoadP(kInterpreterBytecodeArrayRegister,
+          MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
 
   if (FLAG_debug_code) {
     // Check function data field is actually a BytecodeArray object.
@@ -1053,9 +1243,7 @@
 
   // Get the target bytecode offset from the frame.
   __ LoadP(kInterpreterBytecodeOffsetRegister,
-           MemOperand(
-               kInterpreterRegisterFileRegister,
-               InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
+          MemOperand(fp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
   __ SmiUntag(kInterpreterBytecodeOffsetRegister);
 
   // Dispatch to the target bytecode.
@@ -1063,65 +1251,157 @@
                          kInterpreterBytecodeOffsetRegister));
   __ ShiftLeftImm(ip, r4, Operand(kPointerSizeLog2));
   __ LoadPX(ip, MemOperand(kInterpreterDispatchTableRegister, ip));
-  __ addi(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Jump(ip);
 }
 
 
-static void Generate_InterpreterNotifyDeoptimizedHelper(
-    MacroAssembler* masm, Deoptimizer::BailoutType type) {
-  // Enter an internal frame.
-  {
-    FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
-
-    // Pass the deoptimization type to the runtime system.
-    __ LoadSmiLiteral(r4, Smi::FromInt(static_cast<int>(type)));
-    __ Push(r4);
-    __ CallRuntime(Runtime::kNotifyDeoptimized);
-    // Tear down internal frame.
-  }
-
-  // Drop state (we don't use these for interpreter deopts) and and pop the
-  // accumulator value into the accumulator register.
-  __ Drop(1);
-  __ Pop(kInterpreterAccumulatorRegister);
-
-  // Enter the bytecode dispatch.
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-
-void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
-}
-
-
-void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
-}
-
-
-void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
-}
-
-void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
-  // Set the address of the interpreter entry trampoline as a return address.
-  // This simulates the initial call to bytecode handlers in interpreter entry
-  // trampoline. The return will never actually be taken, but our stack walker
-  // uses this address to determine whether a frame is interpreted.
-  __ mov(r0,
-         Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline()));
-  __ mtlr(r0);
-
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-
 void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r3 : argument count (preserved for callee)
+  //  -- r6 : new target (preserved for callee)
+  //  -- r4 : target function (preserved for callee)
+  // -----------------------------------
+  // First lookup code, maybe we don't need to compile!
+  Label gotta_call_runtime;
+  Label maybe_call_runtime;
+  Label try_shared;
+  Label loop_top, loop_bottom;
+
+  Register closure = r4;
+  Register map = r9;
+  Register index = r5;
+  __ LoadP(map,
+           FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadP(map,
+           FieldMemOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset));
+  __ LoadP(index, FieldMemOperand(map, FixedArray::kLengthOffset));
+  __ CmpSmiLiteral(index, Smi::FromInt(2), r0);
+  __ blt(&gotta_call_runtime);
+
+  // Find literals.
+  // r10 : native context
+  // r5  : length / index
+  // r9  : optimized code map
+  // r6  : new target
+  // r4  : closure
+  Register native_context = r10;
+  __ LoadP(native_context, NativeContextMemOperand());
+
+  __ bind(&loop_top);
+  Register temp = r11;
+  Register array_pointer = r8;
+
+  // Does the native context match?
+  __ SmiToPtrArrayOffset(array_pointer, index);
+  __ add(array_pointer, map, array_pointer);
+  __ LoadP(temp, FieldMemOperand(array_pointer,
+                                 SharedFunctionInfo::kOffsetToPreviousContext));
+  __ LoadP(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
+  __ cmp(temp, native_context);
+  __ bne(&loop_bottom);
+  // OSR id set to none?
+  __ LoadP(temp,
+           FieldMemOperand(array_pointer,
+                           SharedFunctionInfo::kOffsetToPreviousOsrAstId));
+  const int bailout_id = BailoutId::None().ToInt();
+  __ CmpSmiLiteral(temp, Smi::FromInt(bailout_id), r0);
+  __ bne(&loop_bottom);
+  // Literals available?
+  __ LoadP(temp,
+           FieldMemOperand(array_pointer,
+                           SharedFunctionInfo::kOffsetToPreviousLiterals));
+  __ LoadP(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
+  __ JumpIfSmi(temp, &gotta_call_runtime);
+
+  // Save the literals in the closure.
+  __ StoreP(temp, FieldMemOperand(closure, JSFunction::kLiteralsOffset), r0);
+  __ RecordWriteField(closure, JSFunction::kLiteralsOffset, temp, r7,
+                      kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+
+  // Code available?
+  Register entry = r7;
+  __ LoadP(entry,
+           FieldMemOperand(array_pointer,
+                           SharedFunctionInfo::kOffsetToPreviousCachedCode));
+  __ LoadP(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &maybe_call_runtime);
+
+  // Found literals and code. Get them into the closure and return.
+  // Store code entry in the closure.
+  __ addi(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+
+  Label install_optimized_code_and_tailcall;
+  __ bind(&install_optimized_code_and_tailcall);
+  __ StoreP(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset), r0);
+  __ RecordWriteCodeEntryField(closure, entry, r8);
+
+  // Link the closure into the optimized function list.
+  // r7 : code entry
+  // r10: native context
+  // r4 : closure
+  __ LoadP(
+      r8, ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
+  __ StoreP(r8, FieldMemOperand(closure, JSFunction::kNextFunctionLinkOffset),
+            r0);
+  __ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, r8, temp,
+                      kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  const int function_list_offset =
+      Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
+  __ StoreP(
+      closure,
+      ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST), r0);
+  // Save closure before the write barrier.
+  __ mr(r8, closure);
+  __ RecordWriteContextSlot(native_context, function_list_offset, r8, temp,
+                            kLRHasNotBeenSaved, kDontSaveFPRegs);
+  __ JumpToJSEntry(entry);
+
+  __ bind(&loop_bottom);
+  __ SubSmiLiteral(index, index, Smi::FromInt(SharedFunctionInfo::kEntryLength),
+                   r0);
+  __ CmpSmiLiteral(index, Smi::FromInt(1), r0);
+  __ bgt(&loop_top);
+
+  // We found neither literals nor code.
+  __ b(&gotta_call_runtime);
+
+  __ bind(&maybe_call_runtime);
+
+  // Last possibility. Check the context free optimized code map entry.
+  __ LoadP(entry,
+           FieldMemOperand(map, FixedArray::kHeaderSize +
+                                    SharedFunctionInfo::kSharedCodeIndex));
+  __ LoadP(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &try_shared);
+
+  // Store code entry in the closure.
+  __ addi(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ b(&install_optimized_code_and_tailcall);
+
+  __ bind(&try_shared);
+  // Is the full code valid?
+  __ LoadP(entry,
+           FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadP(entry, FieldMemOperand(entry, SharedFunctionInfo::kCodeOffset));
+  __ lwz(r8, FieldMemOperand(entry, Code::kFlagsOffset));
+  __ DecodeField<Code::KindField>(r8);
+  __ cmpi(r8, Operand(Code::BUILTIN));
+  __ beq(&gotta_call_runtime);
+  // Yes, install the full code.
+  __ addi(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ StoreP(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset), r0);
+  __ RecordWriteCodeEntryField(closure, entry, r8);
+  __ JumpToJSEntry(entry);
+
+  __ bind(&gotta_call_runtime);
   GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
 }
 
+void Builtins::Generate_CompileBaseline(MacroAssembler* masm) {
+  GenerateTailCallToReturnedCode(masm, Runtime::kCompileBaseline);
+}
 
 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
   GenerateTailCallToReturnedCode(masm,
@@ -1267,14 +1547,19 @@
   __ SmiUntag(r9);
   // Switch on the state.
   Label with_tos_register, unknown_state;
-  __ cmpi(r9, Operand(FullCodeGenerator::NO_REGISTERS));
+  __ cmpi(
+      r9,
+      Operand(static_cast<intptr_t>(Deoptimizer::BailoutState::NO_REGISTERS)));
   __ bne(&with_tos_register);
   __ addi(sp, sp, Operand(1 * kPointerSize));  // Remove state.
   __ Ret();
 
   __ bind(&with_tos_register);
+  DCHECK_EQ(kInterpreterAccumulatorRegister.code(), r3.code());
   __ LoadP(r3, MemOperand(sp, 1 * kPointerSize));
-  __ cmpi(r9, Operand(FullCodeGenerator::TOS_REG));
+  __ cmpi(
+      r9,
+      Operand(static_cast<intptr_t>(Deoptimizer::BailoutState::TOS_REGISTER)));
   __ bne(&unknown_state);
   __ addi(sp, sp, Operand(2 * kPointerSize));  // Remove state.
   __ Ret();
@@ -1454,6 +1739,9 @@
 void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
                                                int field_index) {
   // ----------- S t a t e -------------
+  //  -- r3    : number of arguments
+  //  -- r4    : function
+  //  -- cp    : context
   //  -- lr    : return address
   //  -- sp[0] : receiver
   // -----------------------------------
@@ -1463,7 +1751,7 @@
   {
     __ Pop(r3);
     __ JumpIfSmi(r3, &receiver_not_date);
-    __ CompareObjectType(r3, r4, r5, JS_DATE_TYPE);
+    __ CompareObjectType(r3, r5, r6, JS_DATE_TYPE);
     __ bne(&receiver_not_date);
   }
 
@@ -1493,29 +1781,14 @@
 
   // 3. Raise a TypeError if the receiver is not a date.
   __ bind(&receiver_not_date);
-  __ TailCallRuntime(Runtime::kThrowNotDateError);
-}
-
-// static
-void Builtins::Generate_FunctionHasInstance(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- r3    : argc
-  //  -- sp[0] : first argument (left-hand side)
-  //  -- sp[4] : receiver (right-hand side)
-  // -----------------------------------
-
   {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-    __ LoadP(InstanceOfDescriptor::LeftRegister(),
-             MemOperand(fp, 2 * kPointerSize));  // Load left-hand side.
-    __ LoadP(InstanceOfDescriptor::RightRegister(),
-             MemOperand(fp, 3 * kPointerSize));  // Load right-hand side.
-    InstanceOfStub stub(masm->isolate(), true);
-    __ CallStub(&stub);
+    FrameScope scope(masm, StackFrame::MANUAL);
+    __ push(r3);
+    __ PushStandardFrame(r4);
+    __ LoadSmiLiteral(r7, Smi::FromInt(0));
+    __ push(r7);
+    __ CallRuntime(Runtime::kThrowNotDateError);
   }
-
-  // Pop the argument and the receiver.
-  __ Ret(2);
 }
 
 // static
@@ -2460,6 +2733,100 @@
           RelocInfo::CODE_TARGET);
 }
 
+// static
+void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r4 : requested object size (untagged)
+  //  -- lr : return address
+  // -----------------------------------
+  __ SmiTag(r4);
+  __ Push(r4);
+  __ LoadSmiLiteral(cp, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInNewSpace);
+}
+
+// static
+void Builtins::Generate_AllocateInOldSpace(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r4 : requested object size (untagged)
+  //  -- lr : return address
+  // -----------------------------------
+  __ SmiTag(r4);
+  __ LoadSmiLiteral(r5, Smi::FromInt(AllocateTargetSpace::encode(OLD_SPACE)));
+  __ Push(r4, r5);
+  __ LoadSmiLiteral(cp, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInTargetSpace);
+}
+
+// static
+void Builtins::Generate_StringToNumber(MacroAssembler* masm) {
+  // The StringToNumber stub takes one argument in r3.
+  __ AssertString(r3);
+
+  // Check if string has a cached array index.
+  Label runtime;
+  __ lwz(r5, FieldMemOperand(r3, String::kHashFieldOffset));
+  __ And(r0, r5, Operand(String::kContainsCachedArrayIndexMask), SetRC);
+  __ bne(&runtime, cr0);
+  __ IndexFromHash(r5, r3);
+  __ blr();
+
+  __ bind(&runtime);
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ push(r3);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kStringToNumber);
+  }
+  __ Ret();
+}
+
+// static
+void Builtins::Generate_ToNumber(MacroAssembler* masm) {
+  // The ToNumber stub takes one argument in r3.
+  STATIC_ASSERT(kSmiTag == 0);
+  __ TestIfSmi(r3, r0);
+  __ Ret(eq, cr0);
+
+  __ CompareObjectType(r3, r4, r4, HEAP_NUMBER_TYPE);
+  // r3: receiver
+  // r4: receiver instance type
+  __ Ret(eq);
+
+  __ Jump(masm->isolate()->builtins()->NonNumberToNumber(),
+          RelocInfo::CODE_TARGET);
+}
+
+// static
+void Builtins::Generate_NonNumberToNumber(MacroAssembler* masm) {
+  // The NonNumberToNumber stub takes one argument in r3.
+  __ AssertNotNumber(r3);
+
+  __ CompareObjectType(r3, r4, r4, FIRST_NONSTRING_TYPE);
+  // r3: receiver
+  // r4: receiver instance type
+  __ Jump(masm->isolate()->builtins()->StringToNumber(), RelocInfo::CODE_TARGET,
+          lt);
+
+  Label not_oddball;
+  __ cmpi(r4, Operand(ODDBALL_TYPE));
+  __ bne(&not_oddball);
+  __ LoadP(r3, FieldMemOperand(r3, Oddball::kToNumberOffset));
+  __ blr();
+  __ bind(&not_oddball);
+
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ push(r3);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kToNumber);
+  }
+  __ Ret();
+}
 
 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
   // ----------- S t a t e -------------
diff --git a/src/ppc/code-stubs-ppc.cc b/src/ppc/code-stubs-ppc.cc
index 0671f99..6065d02 100644
--- a/src/ppc/code-stubs-ppc.cc
+++ b/src/ppc/code-stubs-ppc.cc
@@ -21,60 +21,15 @@
 namespace v8 {
 namespace internal {
 
+#define __ ACCESS_MASM(masm)
 
-static void InitializeArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  Address deopt_handler =
-      Runtime::FunctionForId(Runtime::kArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(r3, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-
-static void InitializeInternalArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  Address deopt_handler =
-      Runtime::FunctionForId(Runtime::kInternalArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(r3, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-
-void ArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 0);
-}
-
-
-void ArraySingleArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 1);
-}
-
-
-void ArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-void InternalArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0);
+void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
+  __ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2));
+  __ StorePX(r4, MemOperand(sp, r0));
+  __ push(r4);
+  __ push(r5);
+  __ addi(r3, r3, Operand(3));
+  __ TailCallRuntime(Runtime::kNewArray);
 }
 
 void FastArrayPushStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
@@ -82,20 +37,12 @@
   descriptor->Initialize(r3, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-void InternalArraySingleArgumentConstructorStub::InitializeDescriptor(
+void FastFunctionBindStub::InitializeDescriptor(
     CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1);
+  Address deopt_handler = Runtime::FunctionForId(Runtime::kFunctionBind)->entry;
+  descriptor->Initialize(r3, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-
-void InternalArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-#define __ ACCESS_MASM(masm)
-
 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
                                           Condition cond);
 static void EmitSmiNonsmiComparison(MacroAssembler* masm, Register lhs,
@@ -999,7 +946,7 @@
   CEntryStub::GenerateAheadOfTime(isolate);
   StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
   StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
-  ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
+  CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate);
   CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
   CreateWeakCellStub::GenerateAheadOfTime(isolate);
   BinaryOpICStub::GenerateAheadOfTime(isolate);
@@ -1383,126 +1330,6 @@
 }
 
 
-void InstanceOfStub::Generate(MacroAssembler* masm) {
-  Register const object = r4;              // Object (lhs).
-  Register const function = r3;            // Function (rhs).
-  Register const object_map = r5;          // Map of {object}.
-  Register const function_map = r6;        // Map of {function}.
-  Register const function_prototype = r7;  // Prototype of {function}.
-  Register const scratch = r8;
-
-  DCHECK(object.is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(function.is(InstanceOfDescriptor::RightRegister()));
-
-  // Check if {object} is a smi.
-  Label object_is_smi;
-  __ JumpIfSmi(object, &object_is_smi);
-
-  // Lookup the {function} and the {object} map in the global instanceof cache.
-  // Note: This is safe because we clear the global instanceof cache whenever
-  // we change the prototype of any object.
-  Label fast_case, slow_case;
-  __ LoadP(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
-  __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
-  __ bne(&fast_case);
-  __ CompareRoot(object_map, Heap::kInstanceofCacheMapRootIndex);
-  __ bne(&fast_case);
-  __ LoadRoot(r3, Heap::kInstanceofCacheAnswerRootIndex);
-  __ Ret();
-
-  // If {object} is a smi we can safely return false if {function} is a JS
-  // function, otherwise we have to miss to the runtime and throw an exception.
-  __ bind(&object_is_smi);
-  __ JumpIfSmi(function, &slow_case);
-  __ CompareObjectType(function, function_map, scratch, JS_FUNCTION_TYPE);
-  __ bne(&slow_case);
-  __ LoadRoot(r3, Heap::kFalseValueRootIndex);
-  __ Ret();
-
-  // Fast-case: The {function} must be a valid JSFunction.
-  __ bind(&fast_case);
-  __ JumpIfSmi(function, &slow_case);
-  __ CompareObjectType(function, function_map, scratch, JS_FUNCTION_TYPE);
-  __ bne(&slow_case);
-
-  // Go to the runtime if the function is not a constructor.
-  __ lbz(scratch, FieldMemOperand(function_map, Map::kBitFieldOffset));
-  __ TestBit(scratch, Map::kIsConstructor, r0);
-  __ beq(&slow_case, cr0);
-
-  // Ensure that {function} has an instance prototype.
-  __ TestBit(scratch, Map::kHasNonInstancePrototype, r0);
-  __ bne(&slow_case, cr0);
-
-  // Get the "prototype" (or initial map) of the {function}.
-  __ LoadP(function_prototype,
-           FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
-  __ AssertNotSmi(function_prototype);
-
-  // Resolve the prototype if the {function} has an initial map.  Afterwards the
-  // {function_prototype} will be either the JSReceiver prototype object or the
-  // hole value, which means that no instances of the {function} were created so
-  // far and hence we should return false.
-  Label function_prototype_valid;
-  __ CompareObjectType(function_prototype, scratch, scratch, MAP_TYPE);
-  __ bne(&function_prototype_valid);
-  __ LoadP(function_prototype,
-           FieldMemOperand(function_prototype, Map::kPrototypeOffset));
-  __ bind(&function_prototype_valid);
-  __ AssertNotSmi(function_prototype);
-
-  // Update the global instanceof cache with the current {object} map and
-  // {function}.  The cached answer will be set when it is known below.
-  __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
-  __ StoreRoot(object_map, Heap::kInstanceofCacheMapRootIndex);
-
-  // Loop through the prototype chain looking for the {function} prototype.
-  // Assume true, and change to false if not found.
-  Register const object_instance_type = function_map;
-  Register const map_bit_field = function_map;
-  Register const null = scratch;
-  Register const result = r3;
-
-  Label done, loop, fast_runtime_fallback;
-  __ LoadRoot(result, Heap::kTrueValueRootIndex);
-  __ LoadRoot(null, Heap::kNullValueRootIndex);
-  __ bind(&loop);
-
-  // Check if the object needs to be access checked.
-  __ lbz(map_bit_field, FieldMemOperand(object_map, Map::kBitFieldOffset));
-  __ TestBit(map_bit_field, Map::kIsAccessCheckNeeded, r0);
-  __ bne(&fast_runtime_fallback, cr0);
-  // Check if the current object is a Proxy.
-  __ CompareInstanceType(object_map, object_instance_type, JS_PROXY_TYPE);
-  __ beq(&fast_runtime_fallback);
-
-  __ LoadP(object, FieldMemOperand(object_map, Map::kPrototypeOffset));
-  __ cmp(object, function_prototype);
-  __ beq(&done);
-  __ cmp(object, null);
-  __ LoadP(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
-  __ bne(&loop);
-  __ LoadRoot(result, Heap::kFalseValueRootIndex);
-  __ bind(&done);
-  __ StoreRoot(result, Heap::kInstanceofCacheAnswerRootIndex);
-  __ Ret();
-
-  // Found Proxy or access check needed: Call the runtime
-  __ bind(&fast_runtime_fallback);
-  __ Push(object, function_prototype);
-  // Invalidate the instanceof cache.
-  __ LoadSmiLiteral(scratch, Smi::FromInt(0));
-  __ StoreRoot(scratch, Heap::kInstanceofCacheFunctionRootIndex);
-  __ TailCallRuntime(Runtime::kHasInPrototypeChain);
-
-  // Slow-case: Call the %InstanceOf runtime function.
-  __ bind(&slow_case);
-  __ Push(object, function);
-  __ TailCallRuntime(is_es6_instanceof() ? Runtime::kOrdinaryHasInstance
-                                         : Runtime::kInstanceOf);
-}
-
-
 void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
   Label miss;
   Register receiver = LoadDescriptor::ReceiverRegister();
@@ -1538,7 +1365,6 @@
                                           &miss,  // When not a string.
                                           &miss,  // When not a number.
                                           &miss,  // When index out of range.
-                                          STRING_INDEX_IS_ARRAY_INDEX,
                                           RECEIVER_IS_STRING);
   char_at_generator.GenerateFast(masm);
   __ Ret();
@@ -1991,12 +1817,15 @@
   // r5 : feedback vector
   // r6 : slot in feedback vector (Smi)
   Label initialize, done, miss, megamorphic, not_array_function;
+  Label done_initialize_count, done_increment_count;
 
   DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()),
             masm->isolate()->heap()->megamorphic_symbol());
   DCHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(masm->isolate()),
             masm->isolate()->heap()->uninitialized_symbol());
 
+  const int count_offset = FixedArray::kHeaderSize + kPointerSize;
+
   // Load the cache state into r8.
   __ SmiToPtrArrayOffset(r8, r6);
   __ add(r8, r5, r8);
@@ -2011,7 +1840,7 @@
   Register weak_value = r10;
   __ LoadP(weak_value, FieldMemOperand(r8, WeakCell::kValueOffset));
   __ cmp(r4, weak_value);
-  __ beq(&done);
+  __ beq(&done_increment_count);
   __ CompareRoot(r8, Heap::kmegamorphic_symbolRootIndex);
   __ beq(&done);
   __ LoadP(feedback_map, FieldMemOperand(r8, HeapObject::kMapOffset));
@@ -2034,7 +1863,7 @@
   __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r8);
   __ cmp(r4, r8);
   __ bne(&megamorphic);
-  __ b(&done);
+  __ b(&done_increment_count);
 
   __ bind(&miss);
 
@@ -2064,12 +1893,31 @@
   // slot.
   CreateAllocationSiteStub create_stub(masm->isolate());
   CallStubInRecordCallTarget(masm, &create_stub);
-  __ b(&done);
+  __ b(&done_initialize_count);
 
   __ bind(&not_array_function);
 
   CreateWeakCellStub weak_cell_stub(masm->isolate());
   CallStubInRecordCallTarget(masm, &weak_cell_stub);
+
+  __ bind(&done_initialize_count);
+  // Initialize the call counter.
+  __ LoadSmiLiteral(r8, Smi::FromInt(1));
+  __ SmiToPtrArrayOffset(r7, r6);
+  __ add(r7, r5, r7);
+  __ StoreP(r8, FieldMemOperand(r7, count_offset), r0);
+  __ b(&done);
+
+  __ bind(&done_increment_count);
+
+  // Increment the call count for monomorphic function calls.
+  __ SmiToPtrArrayOffset(r8, r6);
+  __ add(r8, r5, r8);
+
+  __ LoadP(r7, FieldMemOperand(r8, count_offset));
+  __ AddSmiLiteral(r7, r7, Smi::FromInt(1), r0);
+  __ StoreP(r7, FieldMemOperand(r8, count_offset), r0);
+
   __ bind(&done);
 }
 
@@ -2139,7 +1987,7 @@
   __ SmiToPtrArrayOffset(r8, r6);
   __ add(r5, r5, r8);
   __ LoadP(r6, FieldMemOperand(r5, count_offset));
-  __ AddSmiLiteral(r6, r6, Smi::FromInt(CallICNexus::kCallCountIncrement), r0);
+  __ AddSmiLiteral(r6, r6, Smi::FromInt(1), r0);
   __ StoreP(r6, FieldMemOperand(r5, count_offset), r0);
 
   __ mr(r5, r7);
@@ -2187,7 +2035,7 @@
   // Increment the call count for monomorphic function calls.
   const int count_offset = FixedArray::kHeaderSize + kPointerSize;
   __ LoadP(r6, FieldMemOperand(r9, count_offset));
-  __ AddSmiLiteral(r6, r6, Smi::FromInt(CallICNexus::kCallCountIncrement), r0);
+  __ AddSmiLiteral(r6, r6, Smi::FromInt(1), r0);
   __ StoreP(r6, FieldMemOperand(r9, count_offset), r0);
 
   __ bind(&call_function);
@@ -2257,7 +2105,7 @@
   __ bne(&miss);
 
   // Initialize the call counter.
-  __ LoadSmiLiteral(r8, Smi::FromInt(CallICNexus::kCallCountIncrement));
+  __ LoadSmiLiteral(r8, Smi::FromInt(1));
   __ StoreP(r8, FieldMemOperand(r9, count_offset), r0);
 
   // Store the function. Use a stub since we need a frame for allocation.
@@ -2348,13 +2196,7 @@
     // index_ is consumed by runtime conversion function.
     __ Push(object_, index_);
   }
-  if (index_flags_ == STRING_INDEX_IS_NUMBER) {
-    __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero);
-  } else {
-    DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
-    // NumberToSmi discards numbers that are not exact integers.
-    __ CallRuntime(Runtime::kNumberToSmi);
-  }
+  __ CallRuntime(Runtime::kNumberToSmi);
   // Save the conversion result before the pop instructions below
   // have a chance to overwrite it.
   __ Move(index_, r3);
@@ -2683,67 +2525,13 @@
   // r6: from index (untagged)
   __ SmiTag(r6, r6);
   StringCharAtGenerator generator(r3, r6, r5, r3, &runtime, &runtime, &runtime,
-                                  STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING);
+                                  RECEIVER_IS_STRING);
   generator.GenerateFast(masm);
   __ Drop(3);
   __ Ret();
   generator.SkipSlow(masm, &runtime);
 }
 
-
-void ToNumberStub::Generate(MacroAssembler* masm) {
-  // The ToNumber stub takes one argument in r3.
-  STATIC_ASSERT(kSmiTag == 0);
-  __ TestIfSmi(r3, r0);
-  __ Ret(eq, cr0);
-
-  __ CompareObjectType(r3, r4, r4, HEAP_NUMBER_TYPE);
-  // r3: receiver
-  // r4: receiver instance type
-  __ Ret(eq);
-
-  NonNumberToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
-}
-
-void NonNumberToNumberStub::Generate(MacroAssembler* masm) {
-  // The NonNumberToNumber stub takes one argument in r3.
-  __ AssertNotNumber(r3);
-
-  __ CompareObjectType(r3, r4, r4, FIRST_NONSTRING_TYPE);
-  // r3: receiver
-  // r4: receiver instance type
-  StringToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub, lt);
-
-  Label not_oddball;
-  __ cmpi(r4, Operand(ODDBALL_TYPE));
-  __ bne(&not_oddball);
-  __ LoadP(r3, FieldMemOperand(r3, Oddball::kToNumberOffset));
-  __ blr();
-  __ bind(&not_oddball);
-
-  __ push(r3);  // Push argument.
-  __ TailCallRuntime(Runtime::kToNumber);
-}
-
-void StringToNumberStub::Generate(MacroAssembler* masm) {
-  // The StringToNumber stub takes one argument in r3.
-  __ AssertString(r3);
-
-  // Check if string has a cached array index.
-  Label runtime;
-  __ lwz(r5, FieldMemOperand(r3, String::kHashFieldOffset));
-  __ And(r0, r5, Operand(String::kContainsCachedArrayIndexMask), SetRC);
-  __ bne(&runtime, cr0);
-  __ IndexFromHash(r5, r3);
-  __ blr();
-
-  __ bind(&runtime);
-  __ push(r3);  // Push argument.
-  __ TailCallRuntime(Runtime::kStringToNumber);
-}
-
 void ToStringStub::Generate(MacroAssembler* masm) {
   // The ToString stub takes one argument in r3.
   Label is_number;
@@ -2934,7 +2722,7 @@
   // Load r5 with the allocation site.  We stick an undefined dummy value here
   // and replace it with the real allocation site later when we instantiate this
   // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate().
-  __ Move(r5, handle(isolate()->heap()->undefined_value()));
+  __ Move(r5, isolate()->factory()->undefined_value());
 
   // Make sure that we actually patched the allocation site.
   if (FLAG_debug_code) {
@@ -3808,14 +3596,14 @@
 
 void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  LoadICStub stub(isolate(), state());
+  LoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate(), state());
+  KeyedLoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -3960,8 +3748,8 @@
   __ bind(&not_array);
   __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
   __ bne(&miss);
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::LOAD_IC, code_flags,
                                                receiver, name, feedback,
                                                receiver_map, scratch1, r10);
@@ -4105,8 +3893,8 @@
   __ bind(&not_array);
   __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
   __ bne(&miss);
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
   masm->isolate()->stub_cache()->GenerateProbe(
       masm, Code::STORE_IC, code_flags, receiver, key, feedback, receiver_map,
       scratch1, scratch2);
@@ -4470,18 +4258,11 @@
 }
 
 
-void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
+void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
   ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
       isolate);
-  ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
-      isolate);
-  ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
-      isolate);
-}
-
-
-void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
-    Isolate* isolate) {
+  ArrayNArgumentsConstructorStub stub(isolate);
+  stub.GetCode();
   ElementsKind kinds[2] = {FAST_ELEMENTS, FAST_HOLEY_ELEMENTS};
   for (int i = 0; i < 2; i++) {
     // For internal arrays we only need a few things
@@ -4489,8 +4270,6 @@
     stubh1.GetCode();
     InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]);
     stubh2.GetCode();
-    InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]);
-    stubh3.GetCode();
   }
 }
 
@@ -4509,13 +4288,15 @@
     CreateArrayDispatchOneArgument(masm, mode);
 
     __ bind(&not_one_case);
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else if (argument_count() == NONE) {
     CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
   } else if (argument_count() == ONE) {
     CreateArrayDispatchOneArgument(masm, mode);
   } else if (argument_count() == MORE_THAN_ONE) {
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else {
     UNREACHABLE();
   }
@@ -4599,7 +4380,7 @@
   InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
   __ TailCallStub(&stub0, lt);
 
-  InternalArrayNArgumentsConstructorStub stubN(isolate(), kind);
+  ArrayNArgumentsConstructorStub stubN(isolate());
   __ TailCallStub(&stubN, gt);
 
   if (IsFastPackedElementsKind(kind)) {
@@ -4698,15 +4479,15 @@
   __ bind(&done_allocate);
 
   // Initialize the JSObject fields.
-  __ StoreP(r5, MemOperand(r3, JSObject::kMapOffset));
+  __ StoreP(r5, FieldMemOperand(r3, JSObject::kMapOffset), r0);
   __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
-  __ StoreP(r6, MemOperand(r3, JSObject::kPropertiesOffset));
-  __ StoreP(r6, MemOperand(r3, JSObject::kElementsOffset));
+  __ StoreP(r6, FieldMemOperand(r3, JSObject::kPropertiesOffset), r0);
+  __ StoreP(r6, FieldMemOperand(r3, JSObject::kElementsOffset), r0);
   STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize);
-  __ addi(r4, r3, Operand(JSObject::kHeaderSize));
+  __ addi(r4, r3, Operand(JSObject::kHeaderSize - kHeapObjectTag));
 
   // ----------- S t a t e -------------
-  //  -- r3 : result (untagged)
+  //  -- r3 : result (tagged)
   //  -- r4 : result fields (untagged)
   //  -- r8 : result end (untagged)
   //  -- r5 : initial map
@@ -4724,9 +4505,6 @@
   {
     // Initialize all in-object fields with undefined.
     __ InitializeFieldsWithFiller(r4, r8, r9);
-
-    // Add the object tag to make the JSObject real.
-    __ addi(r3, r3, Operand(kHeapObjectTag));
     __ Ret();
   }
   __ bind(&slack_tracking);
@@ -4746,9 +4524,6 @@
     __ LoadRoot(r9, Heap::kOnePointerFillerMapRootIndex);
     __ InitializeFieldsWithFiller(r4, r8, r9);
 
-    // Add the object tag to make the JSObject real.
-    __ addi(r3, r3, Operand(kHeapObjectTag));
-
     // Check if we can finalize the instance size.
     __ cmpi(r10, Operand(Map::kSlackTrackingCounterEnd));
     __ Ret(ne);
@@ -4774,10 +4549,10 @@
     __ CallRuntime(Runtime::kAllocateInNewSpace);
     __ Pop(r5);
   }
-  __ subi(r3, r3, Operand(kHeapObjectTag));
   __ lbz(r8, FieldMemOperand(r5, Map::kInstanceSizeOffset));
   __ ShiftLeftImm(r8, r8, Operand(kPointerSizeLog2));
   __ add(r8, r3, r8);
+  __ subi(r8, r8, Operand(kHeapObjectTag));
   __ b(&done_allocate);
 
   // Fall back to %NewObject.
@@ -4795,20 +4570,20 @@
   // -----------------------------------
   __ AssertFunction(r4);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make r5 point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ mr(r5, fp);
-    __ b(&loop_entry);
-    __ bind(&loop);
+  // Make r5 point to the JavaScript frame.
+  __ mr(r5, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ LoadP(r5, MemOperand(r5, StandardFrameConstants::kCallerFPOffset));
-    __ bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ LoadP(ip, MemOperand(r5, StandardFrameConstants::kFunctionOffset));
     __ cmp(ip, r4);
-    __ bne(&loop);
+    __ beq(&ok);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
   }
 
   // Check if we have rest parameters (only possible if we have an
@@ -4823,13 +4598,13 @@
   // specified by the function's internal formal parameter count.
   Label rest_parameters;
   __ LoadP(r3, MemOperand(r5, ArgumentsAdaptorFrameConstants::kLengthOffset));
-  __ LoadP(r4, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadP(r6, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
   __ LoadWordArith(
-      r4, FieldMemOperand(r4, SharedFunctionInfo::kFormalParameterCountOffset));
+      r6, FieldMemOperand(r6, SharedFunctionInfo::kFormalParameterCountOffset));
 #if V8_TARGET_ARCH_PPC64
-  __ SmiTag(r4);
+  __ SmiTag(r6);
 #endif
-  __ sub(r3, r3, r4, LeaveOE, SetRC);
+  __ sub(r3, r3, r6, LeaveOE, SetRC);
   __ bgt(&rest_parameters, cr0);
 
   // Return an empty rest parameter array.
@@ -4842,7 +4617,7 @@
 
     // Allocate an empty rest parameter array.
     Label allocate, done_allocate;
-    __ Allocate(JSArray::kSize, r3, r4, r5, &allocate, TAG_OBJECT);
+    __ Allocate(JSArray::kSize, r3, r4, r5, &allocate, NO_ALLOCATION_FLAGS);
     __ bind(&done_allocate);
 
     // Setup the rest parameter array in r0.
@@ -4876,6 +4651,7 @@
     // ----------- S t a t e -------------
     //  -- cp : context
     //  -- r3 : number of rest parameters (tagged)
+    //  -- r4 : function
     //  -- r5 : pointer just past first rest parameters
     //  -- r9 : size of rest parameters
     //  -- lr : return address
@@ -4883,9 +4659,9 @@
 
     // Allocate space for the rest parameter array plus the backing store.
     Label allocate, done_allocate;
-    __ mov(r4, Operand(JSArray::kSize + FixedArray::kHeaderSize));
-    __ add(r4, r4, r9);
-    __ Allocate(r4, r6, r7, r8, &allocate, TAG_OBJECT);
+    __ mov(r10, Operand(JSArray::kSize + FixedArray::kHeaderSize));
+    __ add(r10, r10, r9);
+    __ Allocate(r10, r6, r7, r8, &allocate, NO_ALLOCATION_FLAGS);
     __ bind(&done_allocate);
 
     // Setup the elements array in r6.
@@ -4916,17 +4692,25 @@
     __ addi(r3, r7, Operand(kHeapObjectTag));
     __ Ret();
 
-    // Fall back to %AllocateInNewSpace.
+    // Fall back to %AllocateInNewSpace (if not too big).
+    Label too_big_for_new_space;
     __ bind(&allocate);
+    __ Cmpi(r10, Operand(Page::kMaxRegularHeapObjectSize), r0);
+    __ bgt(&too_big_for_new_space);
     {
       FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
-      __ SmiTag(r4);
-      __ Push(r3, r5, r4);
+      __ SmiTag(r10);
+      __ Push(r3, r5, r10);
       __ CallRuntime(Runtime::kAllocateInNewSpace);
       __ mr(r6, r3);
       __ Pop(r3, r5);
     }
     __ b(&done_allocate);
+
+    // Fall back to %NewRestParameter.
+    __ bind(&too_big_for_new_space);
+    __ push(r4);
+    __ TailCallRuntime(Runtime::kNewRestParameter);
   }
 }
 
@@ -4939,6 +4723,23 @@
   // -----------------------------------
   __ AssertFunction(r4);
 
+  // Make r10 point to the JavaScript frame.
+  __ mr(r10, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
+    __ LoadP(r10, MemOperand(r10, StandardFrameConstants::kCallerFPOffset));
+  }
+  if (FLAG_debug_code) {
+    Label ok;
+    __ LoadP(ip, MemOperand(r10, StandardFrameConstants::kFunctionOffset));
+    __ cmp(ip, r4);
+    __ beq(&ok);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
+  }
+
+
   // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub.
   __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
   __ LoadWordArith(
@@ -4947,19 +4748,20 @@
   __ SmiTag(r5);
 #endif
   __ SmiToPtrArrayOffset(r6, r5);
-  __ add(r6, fp, r6);
+  __ add(r6, r10, r6);
   __ addi(r6, r6, Operand(StandardFrameConstants::kCallerSPOffset));
 
   // r4 : function
   // r5 : number of parameters (tagged)
   // r6 : parameters pointer
+  // r10 : JavaScript frame pointer
   // Registers used over whole function:
   // r8 : arguments count (tagged)
   // r9 : mapped parameter count (tagged)
 
   // Check if the calling frame is an arguments adaptor frame.
   Label adaptor_frame, try_allocate, runtime;
-  __ LoadP(r7, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+  __ LoadP(r7, MemOperand(r10, StandardFrameConstants::kCallerFPOffset));
   __ LoadP(r3, MemOperand(r7, CommonFrameConstants::kContextOrFrameTypeOffset));
   __ CmpSmiLiteral(r3, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
   __ beq(&adaptor_frame);
@@ -5022,7 +4824,7 @@
   __ addi(r11, r11, Operand(JSSloppyArgumentsObject::kSize));
 
   // Do the allocation of all three objects in one go.
-  __ Allocate(r11, r3, r11, r7, &runtime, TAG_OBJECT);
+  __ Allocate(r11, r3, r11, r7, &runtime, NO_ALLOCATION_FLAGS);
 
   // r3 = address of new object(s) (tagged)
   // r5 = argument count (smi-tagged)
@@ -5191,20 +4993,20 @@
   // -----------------------------------
   __ AssertFunction(r4);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make r5 point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ mr(r5, fp);
-    __ b(&loop_entry);
-    __ bind(&loop);
+  // Make r5 point to the JavaScript frame.
+  __ mr(r5, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ LoadP(r5, MemOperand(r5, StandardFrameConstants::kCallerFPOffset));
-    __ bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ LoadP(ip, MemOperand(r5, StandardFrameConstants::kFunctionOffset));
     __ cmp(ip, r4);
-    __ bne(&loop);
+    __ b(&ok);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
   }
 
   // Check if we have an arguments adaptor frame below the function frame.
@@ -5214,10 +5016,10 @@
   __ CmpSmiLiteral(ip, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
   __ beq(&arguments_adaptor);
   {
-    __ LoadP(r4, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
+    __ LoadP(r7, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
     __ LoadWordArith(
         r3,
-        FieldMemOperand(r4, SharedFunctionInfo::kFormalParameterCountOffset));
+        FieldMemOperand(r7, SharedFunctionInfo::kFormalParameterCountOffset));
 #if V8_TARGET_ARCH_PPC64
     __ SmiTag(r3);
 #endif
@@ -5237,6 +5039,7 @@
   // ----------- S t a t e -------------
   //  -- cp : context
   //  -- r3 : number of rest parameters (tagged)
+  //  -- r4 : function
   //  -- r5 : pointer just past first rest parameters
   //  -- r9 : size of rest parameters
   //  -- lr : return address
@@ -5244,9 +5047,10 @@
 
   // Allocate space for the strict arguments object plus the backing store.
   Label allocate, done_allocate;
-  __ mov(r4, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
-  __ add(r4, r4, r9);
-  __ Allocate(r4, r6, r7, r8, &allocate, TAG_OBJECT);
+  __ mov(r10,
+         Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
+  __ add(r10, r10, r9);
+  __ Allocate(r10, r6, r7, r8, &allocate, NO_ALLOCATION_FLAGS);
   __ bind(&done_allocate);
 
   // Setup the elements array in r6.
@@ -5279,47 +5083,27 @@
   __ addi(r3, r7, Operand(kHeapObjectTag));
   __ Ret();
 
-  // Fall back to %AllocateInNewSpace.
+  // Fall back to %AllocateInNewSpace (if not too big).
+  Label too_big_for_new_space;
   __ bind(&allocate);
+  __ Cmpi(r10, Operand(Page::kMaxRegularHeapObjectSize), r0);
+  __ bgt(&too_big_for_new_space);
   {
     FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
-    __ SmiTag(r4);
-    __ Push(r3, r5, r4);
+    __ SmiTag(r10);
+    __ Push(r3, r5, r10);
     __ CallRuntime(Runtime::kAllocateInNewSpace);
     __ mr(r6, r3);
     __ Pop(r3, r5);
   }
   __ b(&done_allocate);
+
+  // Fall back to %NewStrictArguments.
+  __ bind(&too_big_for_new_space);
+  __ push(r4);
+  __ TailCallRuntime(Runtime::kNewStrictArguments);
 }
 
-void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
-  Register context = cp;
-  Register result = r3;
-  Register slot = r5;
-
-  // Go up the context chain to the script context.
-  for (int i = 0; i < depth(); ++i) {
-    __ LoadP(result, ContextMemOperand(context, Context::PREVIOUS_INDEX));
-    context = result;
-  }
-
-  // Load the PropertyCell value at the specified slot.
-  __ ShiftLeftImm(r0, slot, Operand(kPointerSizeLog2));
-  __ add(result, context, r0);
-  __ LoadP(result, ContextMemOperand(result));
-  __ LoadP(result, FieldMemOperand(result, PropertyCell::kValueOffset));
-
-  // If the result is not the_hole, return. Otherwise, handle in the runtime.
-  __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
-  __ Ret(ne);
-
-  // Fallback to runtime.
-  __ SmiTag(slot);
-  __ Push(slot);
-  __ TailCallRuntime(Runtime::kLoadGlobalViaContext);
-}
-
-
 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) {
   Register value = r3;
   Register slot = r5;
@@ -5623,7 +5407,11 @@
   STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
   STATIC_ASSERT(FCA::kIsolateIndex == 1);
   STATIC_ASSERT(FCA::kHolderIndex == 0);
-  STATIC_ASSERT(FCA::kArgsLength == 7);
+  STATIC_ASSERT(FCA::kNewTargetIndex == 7);
+  STATIC_ASSERT(FCA::kArgsLength == 8);
+
+  // new target
+  __ PushRoot(Heap::kUndefinedValueRootIndex);
 
   // context save
   __ push(context);
@@ -5659,10 +5447,10 @@
   // it's not controlled by GC.
   // PPC LINUX ABI:
   //
-  // Create 5 extra slots on stack:
+  // Create 4 extra slots on stack:
   //    [0] space for DirectCEntryStub's LR save
-  //    [1-4] FunctionCallbackInfo
-  const int kApiStackSpace = 5;
+  //    [1-3] FunctionCallbackInfo
+  const int kApiStackSpace = 4;
   const int kFunctionCallbackInfoOffset =
       (kStackFrameExtraParamSlot + 1) * kPointerSize;
 
@@ -5681,9 +5469,6 @@
   // FunctionCallbackInfo::length_ = argc
   __ li(ip, Operand(argc()));
   __ stw(ip, MemOperand(r3, 2 * kPointerSize));
-  // FunctionCallbackInfo::is_construct_call_ = 0
-  __ li(ip, Operand::Zero());
-  __ stw(ip, MemOperand(r3, 2 * kPointerSize + kIntSize));
 
   ExternalReference thunk_ref =
       ExternalReference::invoke_function_callback(masm->isolate());
@@ -5700,9 +5485,9 @@
   }
   MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
   int stack_space = 0;
-  MemOperand is_construct_call_operand =
-      MemOperand(sp, kFunctionCallbackInfoOffset + 2 * kPointerSize + kIntSize);
-  MemOperand* stack_space_operand = &is_construct_call_operand;
+  MemOperand length_operand =
+      MemOperand(sp, kFunctionCallbackInfoOffset + 2 * kPointerSize);
+  MemOperand* stack_space_operand = &length_operand;
   stack_space = argc() + FCA::kArgsLength + 1;
   stack_space_operand = NULL;
   CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
@@ -5712,18 +5497,39 @@
 
 
 void CallApiGetterStub::Generate(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- sp[0]                        : name
-  //  -- sp[4 .. (4 + kArgsLength*4)] : v8::PropertyCallbackInfo::args_
-  //  -- ...
-  //  -- r5                           : api_function_address
-  // -----------------------------------
-
-  Register api_function_address = ApiGetterDescriptor::function_address();
   int arg0Slot = 0;
   int accessorInfoSlot = 0;
   int apiStackSpace = 0;
-  DCHECK(api_function_address.is(r5));
+  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
+  // name below the exit frame to make GC aware of them.
+  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
+  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
+  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
+  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
+  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
+  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
+
+  Register receiver = ApiGetterDescriptor::ReceiverRegister();
+  Register holder = ApiGetterDescriptor::HolderRegister();
+  Register callback = ApiGetterDescriptor::CallbackRegister();
+  Register scratch = r7;
+  DCHECK(!AreAliased(receiver, holder, callback, scratch));
+
+  Register api_function_address = r5;
+
+  __ push(receiver);
+  // Push data from AccessorInfo.
+  __ LoadP(scratch, FieldMemOperand(callback, AccessorInfo::kDataOffset));
+  __ push(scratch);
+  __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
+  __ Push(scratch, scratch);
+  __ mov(scratch, Operand(ExternalReference::isolate_address(isolate())));
+  __ Push(scratch, holder);
+  __ Push(Smi::FromInt(0));  // should_throw_on_error -> false
+  __ LoadP(scratch, FieldMemOperand(callback, AccessorInfo::kNameOffset));
+  __ push(scratch);
 
   // v8::PropertyCallbackInfo::args_ array and name handle.
   const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
@@ -5771,6 +5577,10 @@
   ExternalReference thunk_ref =
       ExternalReference::invoke_accessor_getter_callback(isolate());
 
+  __ LoadP(scratch, FieldMemOperand(callback, AccessorInfo::kJsGetterOffset));
+  __ LoadP(api_function_address,
+        FieldMemOperand(scratch, Foreign::kForeignAddressOffset));
+
   // +3 is to skip prolog, return address and name handle.
   MemOperand return_value_operand(
       fp, (PropertyCallbackArguments::kReturnValueOffset + 3) * kPointerSize);
@@ -5778,7 +5588,6 @@
                            kStackUnwindSpace, NULL, return_value_operand, NULL);
 }
 
-
 #undef __
 }  // namespace internal
 }  // namespace v8
diff --git a/src/ppc/codegen-ppc.cc b/src/ppc/codegen-ppc.cc
index 5642e91..8f2f1cd 100644
--- a/src/ppc/codegen-ppc.cc
+++ b/src/ppc/codegen-ppc.cc
@@ -16,62 +16,6 @@
 
 #define __ masm.
 
-
-#if defined(USE_SIMULATOR)
-byte* fast_exp_ppc_machine_code = nullptr;
-double fast_exp_simulator(double x, Isolate* isolate) {
-  return Simulator::current(isolate)
-      ->CallFPReturnsDouble(fast_exp_ppc_machine_code, x, 0);
-}
-#endif
-
-
-UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) {
-  size_t actual_size;
-  byte* buffer =
-      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
-  if (buffer == nullptr) return nullptr;
-  ExternalReference::InitializeMathExpData();
-
-  MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
-                      CodeObjectRequired::kNo);
-
-  {
-    DoubleRegister input = d1;
-    DoubleRegister result = d2;
-    DoubleRegister double_scratch1 = d3;
-    DoubleRegister double_scratch2 = d4;
-    Register temp1 = r7;
-    Register temp2 = r8;
-    Register temp3 = r9;
-
-// Called from C
-    __ function_descriptor();
-
-    __ Push(temp3, temp2, temp1);
-    MathExpGenerator::EmitMathExp(&masm, input, result, double_scratch1,
-                                  double_scratch2, temp1, temp2, temp3);
-    __ Pop(temp3, temp2, temp1);
-    __ fmr(d1, result);
-    __ Ret();
-  }
-
-  CodeDesc desc;
-  masm.GetCode(&desc);
-  DCHECK(ABI_USES_FUNCTION_DESCRIPTORS || !RelocInfo::RequiresRelocation(desc));
-
-  Assembler::FlushICache(isolate, buffer, actual_size);
-  base::OS::ProtectCode(buffer, actual_size);
-
-#if !defined(USE_SIMULATOR)
-  return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
-#else
-  fast_exp_ppc_machine_code = buffer;
-  return &fast_exp_simulator;
-#endif
-}
-
-
 UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
 #if defined(USE_SIMULATOR)
   return nullptr;
@@ -185,6 +129,7 @@
   __ SmiToDoubleArrayOffset(scratch3, length);
   __ addi(scratch3, scratch3, Operand(FixedDoubleArray::kHeaderSize));
   __ Allocate(scratch3, array, scratch4, scratch2, fail, DOUBLE_ALIGNMENT);
+  __ subi(array, array, Operand(kHeapObjectTag));
   // array: destination FixedDoubleArray, not tagged as heap object.
   // elements: source FixedArray.
 
@@ -313,12 +258,12 @@
   __ add(array_size, array_size, r0);
   __ Allocate(array_size, array, allocate_scratch, scratch, &gc_required,
               NO_ALLOCATION_FLAGS);
-  // array: destination FixedArray, not tagged as heap object
+  // array: destination FixedArray, tagged as heap object
   // Set destination FixedDoubleArray's length and map.
   __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
-  __ StoreP(length, MemOperand(array, FixedDoubleArray::kLengthOffset));
-  __ StoreP(scratch, MemOperand(array, HeapObject::kMapOffset));
-  __ addi(array, array, Operand(kHeapObjectTag));
+  __ StoreP(length, FieldMemOperand(array,
+            FixedDoubleArray::kLengthOffset), r0);
+  __ StoreP(scratch, FieldMemOperand(array, HeapObject::kMapOffset), r0);
 
   // Prepare for conversion loop.
   Register src_elements = elements;
@@ -512,96 +457,6 @@
   __ bind(&done);
 }
 
-
-static MemOperand ExpConstant(int index, Register base) {
-  return MemOperand(base, index * kDoubleSize);
-}
-
-
-void MathExpGenerator::EmitMathExp(MacroAssembler* masm, DoubleRegister input,
-                                   DoubleRegister result,
-                                   DoubleRegister double_scratch1,
-                                   DoubleRegister double_scratch2,
-                                   Register temp1, Register temp2,
-                                   Register temp3) {
-  DCHECK(!input.is(result));
-  DCHECK(!input.is(double_scratch1));
-  DCHECK(!input.is(double_scratch2));
-  DCHECK(!result.is(double_scratch1));
-  DCHECK(!result.is(double_scratch2));
-  DCHECK(!double_scratch1.is(double_scratch2));
-  DCHECK(!temp1.is(temp2));
-  DCHECK(!temp1.is(temp3));
-  DCHECK(!temp2.is(temp3));
-  DCHECK(ExternalReference::math_exp_constants(0).address() != NULL);
-  DCHECK(!masm->serializer_enabled());  // External references not serializable.
-
-  Label zero, infinity, done;
-
-  __ mov(temp3, Operand(ExternalReference::math_exp_constants(0)));
-
-  __ lfd(double_scratch1, ExpConstant(0, temp3));
-  __ fcmpu(double_scratch1, input);
-  __ fmr(result, input);
-  __ bunordered(&done);
-  __ bge(&zero);
-
-  __ lfd(double_scratch2, ExpConstant(1, temp3));
-  __ fcmpu(input, double_scratch2);
-  __ bge(&infinity);
-
-  __ lfd(double_scratch1, ExpConstant(3, temp3));
-  __ lfd(result, ExpConstant(4, temp3));
-  __ fmul(double_scratch1, double_scratch1, input);
-  __ fadd(double_scratch1, double_scratch1, result);
-  __ MovDoubleLowToInt(temp2, double_scratch1);
-  __ fsub(double_scratch1, double_scratch1, result);
-  __ lfd(result, ExpConstant(6, temp3));
-  __ lfd(double_scratch2, ExpConstant(5, temp3));
-  __ fmul(double_scratch1, double_scratch1, double_scratch2);
-  __ fsub(double_scratch1, double_scratch1, input);
-  __ fsub(result, result, double_scratch1);
-  __ fmul(double_scratch2, double_scratch1, double_scratch1);
-  __ fmul(result, result, double_scratch2);
-  __ lfd(double_scratch2, ExpConstant(7, temp3));
-  __ fmul(result, result, double_scratch2);
-  __ fsub(result, result, double_scratch1);
-  __ lfd(double_scratch2, ExpConstant(8, temp3));
-  __ fadd(result, result, double_scratch2);
-  __ srwi(temp1, temp2, Operand(11));
-  __ andi(temp2, temp2, Operand(0x7ff));
-  __ addi(temp1, temp1, Operand(0x3ff));
-
-  // Must not call ExpConstant() after overwriting temp3!
-  __ mov(temp3, Operand(ExternalReference::math_exp_log_table()));
-  __ slwi(temp2, temp2, Operand(3));
-#if V8_TARGET_ARCH_PPC64
-  __ ldx(temp2, MemOperand(temp3, temp2));
-  __ sldi(temp1, temp1, Operand(52));
-  __ orx(temp2, temp1, temp2);
-  __ MovInt64ToDouble(double_scratch1, temp2);
-#else
-  __ add(ip, temp3, temp2);
-  __ lwz(temp3, MemOperand(ip, Register::kExponentOffset));
-  __ lwz(temp2, MemOperand(ip, Register::kMantissaOffset));
-  __ slwi(temp1, temp1, Operand(20));
-  __ orx(temp3, temp1, temp3);
-  __ MovInt64ToDouble(double_scratch1, temp3, temp2);
-#endif
-
-  __ fmul(result, result, double_scratch1);
-  __ b(&done);
-
-  __ bind(&zero);
-  __ fmr(result, kDoubleRegZero);
-  __ b(&done);
-
-  __ bind(&infinity);
-  __ lfd(result, ExpConstant(2, temp3));
-
-  __ bind(&done);
-}
-
 #undef __
 
 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) {
diff --git a/src/ppc/codegen-ppc.h b/src/ppc/codegen-ppc.h
index c3cd9b3..ff487c3 100644
--- a/src/ppc/codegen-ppc.h
+++ b/src/ppc/codegen-ppc.h
@@ -23,18 +23,6 @@
  private:
   DISALLOW_COPY_AND_ASSIGN(StringCharLoadGenerator);
 };
-
-class MathExpGenerator : public AllStatic {
- public:
-  // Register input isn't modified. All other registers are clobbered.
-  static void EmitMathExp(MacroAssembler* masm, DoubleRegister input,
-                          DoubleRegister result, DoubleRegister double_scratch1,
-                          DoubleRegister double_scratch2, Register temp1,
-                          Register temp2, Register temp3);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MathExpGenerator);
-};
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/ppc/deoptimizer-ppc.cc b/src/ppc/deoptimizer-ppc.cc
index ead877e..39102a1 100644
--- a/src/ppc/deoptimizer-ppc.cc
+++ b/src/ppc/deoptimizer-ppc.cc
@@ -124,8 +124,7 @@
 
   // Save all double registers before messing with them.
   __ subi(sp, sp, Operand(kDoubleRegsSize));
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
     int code = config->GetAllocatableDoubleCode(i);
     const DoubleRegister dreg = DoubleRegister::from_code(code);
diff --git a/src/ppc/disasm-ppc.cc b/src/ppc/disasm-ppc.cc
index baba146..c0a02a8 100644
--- a/src/ppc/disasm-ppc.cc
+++ b/src/ppc/disasm-ppc.cc
@@ -39,6 +39,7 @@
 namespace v8 {
 namespace internal {
 
+const auto GetRegConfig = RegisterConfiguration::Crankshaft;
 
 //------------------------------------------------------------------------------
 
@@ -118,7 +119,7 @@
 
 // Print the double FP register name according to the active name converter.
 void Decoder::PrintDRegister(int reg) {
-  Print(DoubleRegister::from_code(reg).ToString());
+  Print(GetRegConfig()->GetDoubleRegisterName(reg));
 }
 
 
@@ -1401,7 +1402,7 @@
 
 
 const char* NameConverter::NameOfAddress(byte* addr) const {
-  v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
+  v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
   return tmp_buffer_.start();
 }
 
@@ -1412,7 +1413,7 @@
 
 
 const char* NameConverter::NameOfCPURegister(int reg) const {
-  return v8::internal::Register::from_code(reg).ToString();
+  return v8::internal::GetRegConfig()->GetGeneralRegisterName(reg);
 }
 
 const char* NameConverter::NameOfByteCPURegister(int reg) const {
@@ -1461,7 +1462,7 @@
     buffer[0] = '\0';
     byte* prev_pc = pc;
     pc += d.InstructionDecode(buffer, pc);
-    v8::internal::PrintF(f, "%p    %08x      %s\n", prev_pc,
+    v8::internal::PrintF(f, "%p    %08x      %s\n", static_cast<void*>(prev_pc),
                          *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
   }
 }
diff --git a/src/ppc/interface-descriptors-ppc.cc b/src/ppc/interface-descriptors-ppc.cc
index 48b6cdc..21fe1ef 100644
--- a/src/ppc/interface-descriptors-ppc.cc
+++ b/src/ppc/interface-descriptors-ppc.cc
@@ -11,6 +11,14 @@
 
 const Register CallInterfaceDescriptor::ContextRegister() { return cp; }
 
+void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
+    CallInterfaceDescriptorData* data, int register_parameter_count) {
+  const Register default_stub_registers[] = {r3, r4, r5, r6, r7};
+  CHECK_LE(static_cast<size_t>(register_parameter_count),
+           arraysize(default_stub_registers));
+  data->InitializePlatformSpecific(register_parameter_count,
+                                   default_stub_registers);
+}
 
 const Register LoadDescriptor::ReceiverRegister() { return r4; }
 const Register LoadDescriptor::NameRegister() { return r5; }
@@ -39,23 +47,15 @@
 const Register StoreTransitionDescriptor::MapRegister() { return r6; }
 
 
-const Register LoadGlobalViaContextDescriptor::SlotRegister() { return r5; }
-
-
 const Register StoreGlobalViaContextDescriptor::SlotRegister() { return r5; }
 const Register StoreGlobalViaContextDescriptor::ValueRegister() { return r3; }
 
 
-const Register InstanceOfDescriptor::LeftRegister() { return r4; }
-const Register InstanceOfDescriptor::RightRegister() { return r3; }
-
-
 const Register StringCompareDescriptor::LeftRegister() { return r4; }
 const Register StringCompareDescriptor::RightRegister() { return r3; }
 
-
-const Register ApiGetterDescriptor::function_address() { return r5; }
-
+const Register ApiGetterDescriptor::HolderRegister() { return r3; }
+const Register ApiGetterDescriptor::CallbackRegister() { return r6; }
 
 const Register MathPowTaggedDescriptor::exponent() { return r5; }
 
@@ -68,7 +68,6 @@
 const Register GrowArrayElementsDescriptor::ObjectRegister() { return r3; }
 const Register GrowArrayElementsDescriptor::KeyRegister() { return r6; }
 
-
 void FastNewClosureDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {r5};
@@ -244,25 +243,28 @@
 SIMD128_TYPES(SIMD128_ALLOC_DESC)
 #undef SIMD128_ALLOC_DESC
 
-void AllocateInNewSpaceDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  Register registers[] = {r3};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-void ArrayConstructorConstantArgCountDescriptor::InitializePlatformSpecific(
+void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // register state
   // r3 -- number of arguments
   // r4 -- function
   // r5 -- allocation site with elements kind
-  Register registers[] = {r4, r5};
+  Register registers[] = {r4, r5, r3};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
+void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  // register state
+  // r3 -- number of arguments
+  // r4 -- function
+  // r5 -- allocation site with elements kind
+  Register registers[] = {r4, r5, r3};
+  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
+}
 
-void ArrayConstructorDescriptor::InitializePlatformSpecific(
+
+void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // stack param count needs (constructor pointer, and single argument)
   Register registers[] = {r4, r5, r3};
@@ -270,24 +272,7 @@
 }
 
 
-void InternalArrayConstructorConstantArgCountDescriptor::
-    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
-  // register state
-  // r3 -- number of arguments
-  // r4 -- constructor function
-  Register registers[] = {r4};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-void InternalArrayConstructorDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  // stack param count needs (constructor pointer, and single argument)
-  Register registers[] = {r4, r3};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-void FastArrayPushDescriptor::InitializePlatformSpecific(
+void VarArgFunctionDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // stack param count needs (arg count)
   Register registers[] = {r3};
@@ -314,6 +299,11 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
+void CountOpDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {r4};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
 
 void StringAddDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
@@ -374,9 +364,8 @@
 void InterpreterDispatchDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {
-      kInterpreterAccumulatorRegister, kInterpreterRegisterFileRegister,
-      kInterpreterBytecodeOffsetRegister, kInterpreterBytecodeArrayRegister,
-      kInterpreterDispatchTableRegister};
+  kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
+  kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
@@ -410,6 +399,16 @@
   };
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
+
+void ResumeGeneratorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {
+      r3,  // the value to pass to the generator
+      r4,  // the JSGeneratorObject to resume
+      r5   // the resume mode (tagged)
+  };
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/ppc/macro-assembler-ppc.cc b/src/ppc/macro-assembler-ppc.cc
index 42e5a13..bda6541 100644
--- a/src/ppc/macro-assembler-ppc.cc
+++ b/src/ppc/macro-assembler-ppc.cc
@@ -84,10 +84,6 @@
   Label start;
   bind(&start);
 
-  // Statement positions are expected to be recorded when the target
-  // address is loaded.
-  positions_recorder()->WriteRecordedPositions();
-
   // branch via link register and set LK bit for return point
   mtctr(target);
   bctrl();
@@ -128,11 +124,6 @@
   Label start;
   bind(&start);
 #endif
-
-  // Statement positions are expected to be recorded when the target
-  // address is loaded.
-  positions_recorder()->WriteRecordedPositions();
-
   // This can likely be optimized to make use of bc() with 24bit relative
   //
   // RecordRelocInfo(x.rmode_, x.imm_);
@@ -725,8 +716,7 @@
 
 MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
   // General purpose registers are pushed last on the stack.
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   int doubles_size = config->num_allocatable_double_registers() * kDoubleSize;
   int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
   return MemOperand(sp, doubles_size + register_offset);
@@ -1047,9 +1037,8 @@
 
 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
   LoadP(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  LoadP(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset));
-  LoadP(vector,
-        FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset));
+  LoadP(vector, FieldMemOperand(vector, JSFunction::kLiteralsOffset));
+  LoadP(vector, FieldMemOperand(vector, LiteralsArray::kFeedbackVectorOffset));
 }
 
 
@@ -1387,12 +1376,14 @@
                                              const ParameterCount& expected,
                                              const ParameterCount& actual) {
   Label skip_flooding;
-  ExternalReference step_in_enabled =
-      ExternalReference::debug_step_in_enabled_address(isolate());
-  mov(r7, Operand(step_in_enabled));
-  lbz(r7, MemOperand(r7));
-  cmpi(r7, Operand::Zero());
-  beq(&skip_flooding);
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(isolate());
+  STATIC_ASSERT(StepFrame > StepIn);
+  mov(r7, Operand(last_step_action));
+  LoadByte(r7, MemOperand(r7), r0);
+  extsb(r7, r7);
+  cmpi(r7, Operand(StepIn));
+  blt(&skip_flooding);
   {
     FrameScope frame(this,
                      has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
@@ -1790,6 +1781,7 @@
                               Register scratch1, Register scratch2,
                               Label* gc_required, AllocationFlags flags) {
   DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -1875,18 +1867,21 @@
     blt(gc_required);
     add(result_end, result, result_end);
   }
-  StoreP(result_end, MemOperand(top_address));
 
-  // Tag object if requested.
-  if ((flags & TAG_OBJECT) != 0) {
-    addi(result, result, Operand(kHeapObjectTag));
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    StoreP(result_end, MemOperand(top_address));
   }
+
+  // Tag object.
+  addi(result, result, Operand(kHeapObjectTag));
 }
 
 
 void MacroAssembler::Allocate(Register object_size, Register result,
                               Register result_end, Register scratch,
                               Label* gc_required, AllocationFlags flags) {
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -1976,12 +1971,114 @@
     andi(r0, result_end, Operand(kObjectAlignmentMask));
     Check(eq, kUnalignedAllocationInNewSpace, cr0);
   }
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    StoreP(result_end, MemOperand(top_address));
+  }
+
+  // Tag object.
+  addi(result, result, Operand(kHeapObjectTag));
+}
+
+void MacroAssembler::FastAllocate(Register object_size, Register result,
+                                  Register result_end, Register scratch,
+                                  AllocationFlags flags) {
+  // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag
+  // is not specified. Other registers must not overlap.
+  DCHECK(!AreAliased(object_size, result, scratch, ip));
+  DCHECK(!AreAliased(result_end, result, scratch, ip));
+  DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end));
+
+  ExternalReference allocation_top =
+      AllocationUtils::GetAllocationTopReference(isolate(), flags);
+
+  Register top_address = scratch;
+  mov(top_address, Operand(allocation_top));
+  LoadP(result, MemOperand(top_address));
+
+  if ((flags & DOUBLE_ALIGNMENT) != 0) {
+    // Align the next allocation. Storing the filler map without checking top is
+    // safe in new-space because the limit of the heap is aligned there.
+#if V8_TARGET_ARCH_PPC64
+    STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
+#else
+    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
+    andi(result_end, result, Operand(kDoubleAlignmentMask));
+    Label aligned;
+    beq(&aligned);
+    mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
+    stw(result_end, MemOperand(result));
+    addi(result, result, Operand(kDoubleSize / 2));
+    bind(&aligned);
+#endif
+  }
+
+  // Calculate new top using result. Object size may be in words so a shift is
+  // required to get the number of bytes.
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    ShiftLeftImm(result_end, object_size, Operand(kPointerSizeLog2));
+    add(result_end, result, result_end);
+  } else {
+    add(result_end, result, object_size);
+  }
+
+  // Update allocation top. result temporarily holds the new top.
+  if (emit_debug_code()) {
+    andi(r0, result_end, Operand(kObjectAlignmentMask));
+    Check(eq, kUnalignedAllocationInNewSpace, cr0);
+  }
   StoreP(result_end, MemOperand(top_address));
 
-  // Tag object if requested.
-  if ((flags & TAG_OBJECT) != 0) {
-    addi(result, result, Operand(kHeapObjectTag));
+  // Tag object.
+  addi(result, result, Operand(kHeapObjectTag));
+}
+
+void MacroAssembler::FastAllocate(int object_size, Register result,
+                                  Register scratch1, Register scratch2,
+                                  AllocationFlags flags) {
+  DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
+  DCHECK(!AreAliased(result, scratch1, scratch2, ip));
+
+  // Make object size into bytes.
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    object_size *= kPointerSize;
   }
+  DCHECK_EQ(0, object_size & kObjectAlignmentMask);
+
+  ExternalReference allocation_top =
+      AllocationUtils::GetAllocationTopReference(isolate(), flags);
+
+  // Set up allocation top address register.
+  Register top_address = scratch1;
+  Register result_end = scratch2;
+  mov(top_address, Operand(allocation_top));
+  LoadP(result, MemOperand(top_address));
+
+  if ((flags & DOUBLE_ALIGNMENT) != 0) {
+    // Align the next allocation. Storing the filler map without checking top is
+    // safe in new-space because the limit of the heap is aligned there.
+#if V8_TARGET_ARCH_PPC64
+    STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
+#else
+    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
+    andi(result_end, result, Operand(kDoubleAlignmentMask));
+    Label aligned;
+    beq(&aligned);
+    mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
+    stw(result_end, MemOperand(result));
+    addi(result, result, Operand(kDoubleSize / 2));
+    bind(&aligned);
+#endif
+  }
+
+  // Calculate new top using result.
+  Add(result_end, result, object_size, r0);
+
+  // The top pointer is not updated for allocation folding dominators.
+  StoreP(result_end, MemOperand(top_address));
+
+  // Tag object.
+  addi(result, result, Operand(kHeapObjectTag));
 }
 
 
@@ -1999,7 +2096,8 @@
   and_(scratch1, scratch1, r0);
 
   // Allocate two-byte string in new space.
-  Allocate(scratch1, result, scratch2, scratch3, gc_required, TAG_OBJECT);
+  Allocate(scratch1, result, scratch2, scratch3, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   InitializeNewString(result, length, Heap::kStringMapRootIndex, scratch1,
@@ -2021,7 +2119,8 @@
   and_(scratch1, scratch1, r0);
 
   // Allocate one-byte string in new space.
-  Allocate(scratch1, result, scratch2, scratch3, gc_required, TAG_OBJECT);
+  Allocate(scratch1, result, scratch2, scratch3, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   InitializeNewString(result, length, Heap::kOneByteStringMapRootIndex,
@@ -2034,7 +2133,7 @@
                                                Register scratch2,
                                                Label* gc_required) {
   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result, length, Heap::kConsStringMapRootIndex, scratch1,
                       scratch2);
@@ -2046,7 +2145,7 @@
                                                Register scratch2,
                                                Label* gc_required) {
   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result, length, Heap::kConsOneByteStringMapRootIndex,
                       scratch1, scratch2);
@@ -2059,7 +2158,7 @@
                                                  Register scratch2,
                                                  Label* gc_required) {
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result, length, Heap::kSlicedStringMapRootIndex, scratch1,
                       scratch2);
@@ -2072,7 +2171,7 @@
                                                  Register scratch2,
                                                  Label* gc_required) {
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result, length, Heap::kSlicedOneByteStringMapRootIndex,
                       scratch1, scratch2);
@@ -2994,6 +3093,18 @@
   }
 }
 
+void MacroAssembler::AssertGeneratorObject(Register object) {
+  if (emit_debug_code()) {
+    STATIC_ASSERT(kSmiTag == 0);
+    TestIfSmi(object, r0);
+    Check(ne, kOperandIsASmiAndNotAGeneratorObject, cr0);
+    push(object);
+    CompareObjectType(object, object, object, JS_GENERATOR_OBJECT_TYPE);
+    pop(object);
+    Check(eq, kOperandIsNotAGeneratorObject);
+  }
+}
+
 void MacroAssembler::AssertReceiver(Register object) {
   if (emit_debug_code()) {
     STATIC_ASSERT(kSmiTag == 0);
@@ -3087,12 +3198,11 @@
                                         Register scratch2,
                                         Register heap_number_map,
                                         Label* gc_required,
-                                        TaggingMode tagging_mode,
                                         MutableMode mode) {
   // Allocate an object in the heap for the heap number and tag it as a heap
   // object.
   Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
-           tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS);
+           NO_ALLOCATION_FLAGS);
 
   Heap::RootListIndex map_index = mode == MUTABLE
                                       ? Heap::kMutableHeapNumberMapRootIndex
@@ -3100,12 +3210,8 @@
   AssertIsRoot(heap_number_map, map_index);
 
   // Store heap number map in the allocated object.
-  if (tagging_mode == TAG_RESULT) {
-    StoreP(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset),
-           r0);
-  } else {
-    StoreP(heap_number_map, MemOperand(result, HeapObject::kMapOffset));
-  }
+  StoreP(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset),
+        r0);
 }
 
 
@@ -3126,7 +3232,8 @@
   DCHECK(!result.is(value));
 
   // Allocate JSValue in new space.
-  Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required, TAG_OBJECT);
+  Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Initialize the JSValue.
   LoadGlobalFunctionInitialMap(constructor, scratch1, scratch2);
@@ -4202,11 +4309,7 @@
     /* cannot use d-form */
     DCHECK(!scratch.is(no_reg));
     mov(scratch, Operand(offset));
-#if V8_TARGET_ARCH_PPC64
-    ldx(dst, MemOperand(mem.ra(), scratch));
-#else
-    lwzx(dst, MemOperand(mem.ra(), scratch));
-#endif
+    LoadPX(dst, MemOperand(mem.ra(), scratch));
   } else {
 #if V8_TARGET_ARCH_PPC64
     int misaligned = (offset & 3);
@@ -4225,6 +4328,23 @@
   }
 }
 
+void MacroAssembler::LoadPU(Register dst, const MemOperand& mem,
+                            Register scratch) {
+  int offset = mem.offset();
+
+  if (!is_int16(offset)) {
+    /* cannot use d-form */
+    DCHECK(!scratch.is(no_reg));
+    mov(scratch, Operand(offset));
+    LoadPUX(dst, MemOperand(mem.ra(), scratch));
+  } else {
+#if V8_TARGET_ARCH_PPC64
+    ldu(dst, mem);
+#else
+    lwzu(dst, mem);
+#endif
+  }
+}
 
 // Store a "pointer" sized value to the memory location
 void MacroAssembler::StoreP(Register src, const MemOperand& mem,
@@ -4235,11 +4355,7 @@
     /* cannot use d-form */
     DCHECK(!scratch.is(no_reg));
     mov(scratch, Operand(offset));
-#if V8_TARGET_ARCH_PPC64
-    stdx(src, MemOperand(mem.ra(), scratch));
-#else
-    stwx(src, MemOperand(mem.ra(), scratch));
-#endif
+    StorePX(src, MemOperand(mem.ra(), scratch));
   } else {
 #if V8_TARGET_ARCH_PPC64
     int misaligned = (offset & 3);
@@ -4263,6 +4379,24 @@
   }
 }
 
+void MacroAssembler::StorePU(Register src, const MemOperand& mem,
+                             Register scratch) {
+  int offset = mem.offset();
+
+  if (!is_int16(offset)) {
+    /* cannot use d-form */
+    DCHECK(!scratch.is(no_reg));
+    mov(scratch, Operand(offset));
+    StorePUX(src, MemOperand(mem.ra(), scratch));
+  } else {
+#if V8_TARGET_ARCH_PPC64
+    stdu(src, mem);
+#else
+    stwu(src, mem);
+#endif
+  }
+}
+
 void MacroAssembler::LoadWordArith(Register dst, const MemOperand& mem,
                                    Register scratch) {
   int offset = mem.offset();
@@ -4457,6 +4591,44 @@
   }
 }
 
+void MacroAssembler::LoadDoubleU(DoubleRegister dst, const MemOperand& mem,
+                                Register scratch) {
+  Register base = mem.ra();
+  int offset = mem.offset();
+
+  if (!is_int16(offset)) {
+    mov(scratch, Operand(offset));
+    lfdux(dst, MemOperand(base, scratch));
+  } else {
+    lfdu(dst, mem);
+  }
+}
+
+void MacroAssembler::LoadSingle(DoubleRegister dst, const MemOperand& mem,
+                                Register scratch) {
+  Register base = mem.ra();
+  int offset = mem.offset();
+
+  if (!is_int16(offset)) {
+    mov(scratch, Operand(offset));
+    lfsx(dst, MemOperand(base, scratch));
+  } else {
+    lfs(dst, mem);
+  }
+}
+
+void MacroAssembler::LoadSingleU(DoubleRegister dst, const MemOperand& mem,
+                                Register scratch) {
+  Register base = mem.ra();
+  int offset = mem.offset();
+
+  if (!is_int16(offset)) {
+    mov(scratch, Operand(offset));
+    lfsux(dst, MemOperand(base, scratch));
+  } else {
+    lfsu(dst, mem);
+  }
+}
 
 void MacroAssembler::StoreDouble(DoubleRegister src, const MemOperand& mem,
                                  Register scratch) {
@@ -4471,13 +4643,52 @@
   }
 }
 
+void MacroAssembler::StoreDoubleU(DoubleRegister src, const MemOperand& mem,
+                                 Register scratch) {
+  Register base = mem.ra();
+  int offset = mem.offset();
+
+  if (!is_int16(offset)) {
+    mov(scratch, Operand(offset));
+    stfdux(src, MemOperand(base, scratch));
+  } else {
+    stfdu(src, mem);
+  }
+}
+
+void MacroAssembler::StoreSingle(DoubleRegister src, const MemOperand& mem,
+                                 Register scratch) {
+  Register base = mem.ra();
+  int offset = mem.offset();
+
+  if (!is_int16(offset)) {
+    mov(scratch, Operand(offset));
+    stfsx(src, MemOperand(base, scratch));
+  } else {
+    stfs(src, mem);
+  }
+}
+
+void MacroAssembler::StoreSingleU(DoubleRegister src, const MemOperand& mem,
+                                 Register scratch) {
+  Register base = mem.ra();
+  int offset = mem.offset();
+
+  if (!is_int16(offset)) {
+    mov(scratch, Operand(offset));
+    stfsux(src, MemOperand(base, scratch));
+  } else {
+    stfsu(src, mem);
+  }
+}
+
 void MacroAssembler::TestJSArrayForAllocationMemento(Register receiver_reg,
                                                      Register scratch_reg,
                                                      Register scratch2_reg,
                                                      Label* no_memento_found) {
   Label map_check;
   Label top_check;
-  ExternalReference new_space_allocation_top =
+  ExternalReference new_space_allocation_top_adr =
       ExternalReference::new_space_allocation_top_address(isolate());
   const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
   const int kMementoEndOffset = kMementoMapOffset + AllocationMemento::kSize;
@@ -4494,7 +4705,9 @@
 
   // If the object is in new space, we need to check whether it is on the same
   // page as the current top.
-  Xor(r0, scratch_reg, Operand(new_space_allocation_top));
+  mov(ip, Operand(new_space_allocation_top_adr));
+  LoadP(ip, MemOperand(ip));
+  Xor(r0, scratch_reg, Operand(ip));
   and_(r0, r0, mask, SetRC);
   beq(&top_check, cr0);
   // The object is on a different page than allocation top. Bail out if the
@@ -4508,7 +4721,7 @@
   // If top is on the same page as the current object, we need to check whether
   // we are below top.
   bind(&top_check);
-  Cmpi(scratch_reg, Operand(new_space_allocation_top), r0);
+  cmp(scratch_reg, ip);
   bgt(no_memento_found);
   // Memento map check.
   bind(&map_check);
@@ -4528,8 +4741,7 @@
   if (reg5.is_valid()) regs |= reg5.bit();
   if (reg6.is_valid()) regs |= reg6.bit();
 
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
     int code = config->GetAllocatableGeneralCode(i);
     Register candidate = Register::from_code(code);
diff --git a/src/ppc/macro-assembler-ppc.h b/src/ppc/macro-assembler-ppc.h
index a529b62..0d5df2f 100644
--- a/src/ppc/macro-assembler-ppc.h
+++ b/src/ppc/macro-assembler-ppc.h
@@ -19,8 +19,8 @@
 const Register kReturnRegister2 = {Register::kCode_r5};
 const Register kJSFunctionRegister = {Register::kCode_r4};
 const Register kContextRegister = {Register::kCode_r30};
+const Register kAllocateSizeRegister = {Register::kCode_r4};
 const Register kInterpreterAccumulatorRegister = {Register::kCode_r3};
-const Register kInterpreterRegisterFileRegister = {Register::kCode_r14};
 const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_r15};
 const Register kInterpreterBytecodeArrayRegister = {Register::kCode_r16};
 const Register kInterpreterDispatchTableRegister = {Register::kCode_r17};
@@ -73,10 +73,8 @@
 
 // These exist to provide portability between 32 and 64bit
 #if V8_TARGET_ARCH_PPC64
-#define LoadPU ldu
 #define LoadPX ldx
 #define LoadPUX ldux
-#define StorePU stdu
 #define StorePX stdx
 #define StorePUX stdux
 #define ShiftLeftImm sldi
@@ -90,10 +88,8 @@
 #define Mul mulld
 #define Div divd
 #else
-#define LoadPU lwzu
 #define LoadPX lwzx
 #define LoadPUX lwzux
-#define StorePU stwu
 #define StorePX stwx
 #define StorePUX stwux
 #define ShiftLeftImm slwi
@@ -515,8 +511,25 @@
   void StoreRepresentation(Register src, const MemOperand& mem,
                            Representation r, Register scratch = no_reg);
 
-  void LoadDouble(DoubleRegister dst, const MemOperand& mem, Register scratch);
-  void StoreDouble(DoubleRegister src, const MemOperand& mem, Register scratch);
+  void LoadDouble(DoubleRegister dst, const MemOperand& mem,
+                  Register scratch = no_reg);
+  void LoadDoubleU(DoubleRegister dst, const MemOperand& mem,
+                  Register scratch = no_reg);
+
+  void LoadSingle(DoubleRegister dst, const MemOperand& mem,
+                  Register scratch = no_reg);
+  void LoadSingleU(DoubleRegister dst, const MemOperand& mem,
+                   Register scratch = no_reg);
+
+  void StoreDouble(DoubleRegister src, const MemOperand& mem,
+                   Register scratch = no_reg);
+  void StoreDoubleU(DoubleRegister src, const MemOperand& mem,
+                   Register scratch = no_reg);
+
+  void StoreSingle(DoubleRegister src, const MemOperand& mem,
+                   Register scratch = no_reg);
+  void StoreSingleU(DoubleRegister src, const MemOperand& mem,
+                    Register scratch = no_reg);
 
   // Move values between integer and floating point registers.
   void MovIntToDouble(DoubleRegister dst, Register src, Register scratch);
@@ -573,7 +586,9 @@
 
   // These exist to provide portability between 32 and 64bit
   void LoadP(Register dst, const MemOperand& mem, Register scratch = no_reg);
+  void LoadPU(Register dst, const MemOperand& mem, Register scratch = no_reg);
   void StoreP(Register src, const MemOperand& mem, Register scratch = no_reg);
+  void StorePU(Register src, const MemOperand& mem, Register scratch = no_reg);
 
   // ---------------------------------------------------------------------------
   // JavaScript invokes
@@ -696,6 +711,15 @@
   void Allocate(Register object_size, Register result, Register result_end,
                 Register scratch, Label* gc_required, AllocationFlags flags);
 
+  // FastAllocate is right now only used for folded allocations. It just
+  // increments the top pointer without checking against limit. This can only
+  // be done if it was proved earlier that the allocation will succeed.
+  void FastAllocate(int object_size, Register result, Register scratch1,
+                    Register scratch2, AllocationFlags flags);
+
+  void FastAllocate(Register object_size, Register result, Register result_end,
+                    Register scratch, AllocationFlags flags);
+
   void AllocateTwoByteString(Register result, Register length,
                              Register scratch1, Register scratch2,
                              Register scratch3, Label* gc_required);
@@ -720,7 +744,6 @@
   // when control continues at the gc_required label.
   void AllocateHeapNumber(Register result, Register scratch1, Register scratch2,
                           Register heap_number_map, Label* gc_required,
-                          TaggingMode tagging_mode = TAG_RESULT,
                           MutableMode mode = IMMUTABLE);
   void AllocateHeapNumberWithValue(Register result, DoubleRegister value,
                                    Register scratch1, Register scratch2,
@@ -1380,6 +1403,10 @@
   // enabled via --debug-code.
   void AssertBoundFunction(Register object);
 
+  // Abort execution if argument is not a JSGeneratorObject,
+  // enabled via --debug-code.
+  void AssertGeneratorObject(Register object);
+
   // Abort execution if argument is not a JSReceiver, enabled via --debug-code.
   void AssertReceiver(Register object);
 
diff --git a/src/ppc/simulator-ppc.cc b/src/ppc/simulator-ppc.cc
index 79dc825..1585845 100644
--- a/src/ppc/simulator-ppc.cc
+++ b/src/ppc/simulator-ppc.cc
@@ -23,6 +23,8 @@
 namespace v8 {
 namespace internal {
 
+const auto GetRegConfig = RegisterConfiguration::Crankshaft;
+
 // This macro provides a platform independent use of sscanf. The reason for
 // SScanF not being implemented in a platform independent way through
 // ::v8::internal::OS in the same way as SNPrintF is that the
@@ -315,7 +317,7 @@
             for (int i = 0; i < kNumRegisters; i++) {
               value = GetRegisterValue(i);
               PrintF("    %3s: %08" V8PRIxPTR,
-                     Register::from_code(i).ToString(), value);
+                     GetRegConfig()->GetGeneralRegisterName(i), value);
               if ((argc == 3 && strcmp(arg2, "fp") == 0) && i < 8 &&
                   (i % 2) == 0) {
                 dvalue = GetRegisterPairDoubleValue(i);
@@ -334,7 +336,7 @@
             for (int i = 0; i < kNumRegisters; i++) {
               value = GetRegisterValue(i);
               PrintF("     %3s: %08" V8PRIxPTR " %11" V8PRIdPTR,
-                     Register::from_code(i).ToString(), value, value);
+                     GetRegConfig()->GetGeneralRegisterName(i), value, value);
               if ((argc == 3 && strcmp(arg2, "fp") == 0) && i < 8 &&
                   (i % 2) == 0) {
                 dvalue = GetRegisterPairDoubleValue(i);
@@ -354,7 +356,7 @@
               dvalue = GetFPDoubleRegisterValue(i);
               uint64_t as_words = bit_cast<uint64_t>(dvalue);
               PrintF("%3s: %f 0x%08x %08x\n",
-                     DoubleRegister::from_code(i).ToString(), dvalue,
+                     GetRegConfig()->GetDoubleRegisterName(i), dvalue,
                      static_cast<uint32_t>(as_words >> 32),
                      static_cast<uint32_t>(as_words & 0xffffffff));
             }
@@ -707,7 +709,7 @@
 }
 
 
-void Simulator::FlushICache(v8::internal::HashMap* i_cache, void* start_addr,
+void Simulator::FlushICache(base::HashMap* i_cache, void* start_addr,
                             size_t size) {
   intptr_t start = reinterpret_cast<intptr_t>(start_addr);
   int intra_line = (start & CachePage::kLineMask);
@@ -729,9 +731,8 @@
 }
 
 
-CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
-  v8::internal::HashMap::Entry* entry =
-      i_cache->LookupOrInsert(page, ICacheHash(page));
+CachePage* Simulator::GetCachePage(base::HashMap* i_cache, void* page) {
+  base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page));
   if (entry->value == NULL) {
     CachePage* new_page = new CachePage();
     entry->value = new_page;
@@ -741,8 +742,7 @@
 
 
 // Flush from start up to and not including start + size.
-void Simulator::FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
-                             int size) {
+void Simulator::FlushOnePage(base::HashMap* i_cache, intptr_t start, int size) {
   DCHECK(size <= CachePage::kPageSize);
   DCHECK(AllOnOnePage(start, size - 1));
   DCHECK((start & CachePage::kLineMask) == 0);
@@ -754,9 +754,7 @@
   memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
 }
 
-
-void Simulator::CheckICache(v8::internal::HashMap* i_cache,
-                            Instruction* instr) {
+void Simulator::CheckICache(base::HashMap* i_cache, Instruction* instr) {
   intptr_t address = reinterpret_cast<intptr_t>(instr);
   void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
   void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
@@ -789,7 +787,7 @@
 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
   i_cache_ = isolate_->simulator_i_cache();
   if (i_cache_ == NULL) {
-    i_cache_ = new v8::internal::HashMap(&ICacheMatch);
+    i_cache_ = new base::HashMap(&ICacheMatch);
     isolate_->set_simulator_i_cache(i_cache_);
   }
   Initialize(isolate);
@@ -925,10 +923,10 @@
 
 
 // static
-void Simulator::TearDown(HashMap* i_cache, Redirection* first) {
+void Simulator::TearDown(base::HashMap* i_cache, Redirection* first) {
   Redirection::DeleteChain(first);
   if (i_cache != nullptr) {
-    for (HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
+    for (base::HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
          entry = i_cache->Next(entry)) {
       delete static_cast<CachePage*>(entry->value);
     }
@@ -1284,15 +1282,18 @@
             case ExternalReference::BUILTIN_FP_FP_CALL:
             case ExternalReference::BUILTIN_COMPARE_CALL:
               PrintF("Call to host function at %p with args %f, %f",
-                     FUNCTION_ADDR(generic_target), dval0, dval1);
+                     static_cast<void*>(FUNCTION_ADDR(generic_target)),
+                     dval0, dval1);
               break;
             case ExternalReference::BUILTIN_FP_CALL:
               PrintF("Call to host function at %p with arg %f",
-                     FUNCTION_ADDR(generic_target), dval0);
+                     static_cast<void*>(FUNCTION_ADDR(generic_target)),
+                     dval0);
               break;
             case ExternalReference::BUILTIN_FP_INT_CALL:
               PrintF("Call to host function at %p with args %f, %" V8PRIdPTR,
-                     FUNCTION_ADDR(generic_target), dval0, ival);
+                     static_cast<void*>(FUNCTION_ADDR(generic_target)),
+                     dval0, ival);
               break;
             default:
               UNREACHABLE();
@@ -1434,8 +1435,8 @@
               "Call to host function at %p,\n"
               "\t\t\t\targs %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
               ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR,
-              FUNCTION_ADDR(target), arg[0], arg[1], arg[2], arg[3], arg[4],
-              arg[5]);
+              static_cast<void*>(FUNCTION_ADDR(target)), arg[0], arg[1],
+              arg[2], arg[3], arg[4], arg[5]);
           if (!stack_aligned) {
             PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
                    get_register(sp));
diff --git a/src/ppc/simulator-ppc.h b/src/ppc/simulator-ppc.h
index a3b03dc..d3163e8 100644
--- a/src/ppc/simulator-ppc.h
+++ b/src/ppc/simulator-ppc.h
@@ -66,7 +66,7 @@
 // Running with a simulator.
 
 #include "src/assembler.h"
-#include "src/hashmap.h"
+#include "src/base/hashmap.h"
 #include "src/ppc/constants-ppc.h"
 
 namespace v8 {
@@ -217,7 +217,7 @@
   // Call on program start.
   static void Initialize(Isolate* isolate);
 
-  static void TearDown(HashMap* i_cache, Redirection* first);
+  static void TearDown(base::HashMap* i_cache, Redirection* first);
 
   // V8 generally calls into generated JS code with 5 parameters and into
   // generated RegExp code with 7 parameters. This is a convenience function,
@@ -239,8 +239,7 @@
   char* last_debugger_input() { return last_debugger_input_; }
 
   // ICache checking.
-  static void FlushICache(v8::internal::HashMap* i_cache, void* start,
-                          size_t size);
+  static void FlushICache(base::HashMap* i_cache, void* start, size_t size);
 
   // Returns true if pc register contains one of the 'special_values' defined
   // below (bad_lr, end_sim_pc).
@@ -330,10 +329,9 @@
   void ExecuteInstruction(Instruction* instr);
 
   // ICache.
-  static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr);
-  static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
-                           int size);
-  static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);
+  static void CheckICache(base::HashMap* i_cache, Instruction* instr);
+  static void FlushOnePage(base::HashMap* i_cache, intptr_t start, int size);
+  static CachePage* GetCachePage(base::HashMap* i_cache, void* page);
 
   // Runtime call support.
   static void* RedirectExternalReference(
@@ -371,7 +369,7 @@
   char* last_debugger_input_;
 
   // Icache simulation
-  v8::internal::HashMap* i_cache_;
+  base::HashMap* i_cache_;
 
   // Registered breakpoints.
   Instruction* break_pc_;
diff --git a/src/profiler/allocation-tracker.cc b/src/profiler/allocation-tracker.cc
index 791cdf0..d094d0e 100644
--- a/src/profiler/allocation-tracker.cc
+++ b/src/profiler/allocation-tracker.cc
@@ -149,11 +149,10 @@
 
 
 void AddressToTraceMap::Print() {
-  PrintF("[AddressToTraceMap (%" V8_SIZET_PREFIX V8PRIuPTR "): \n",
-         ranges_.size());
+  PrintF("[AddressToTraceMap (%" PRIuS "): \n", ranges_.size());
   for (RangeMap::iterator it = ranges_.begin(); it != ranges_.end(); ++it) {
-    PrintF("[%p - %p] => %u\n", it->second.start, it->first,
-        it->second.trace_node_id);
+    PrintF("[%p - %p] => %u\n", static_cast<void*>(it->second.start),
+           static_cast<void*>(it->first), it->second.trace_node_id);
   }
   PrintF("]\n");
 }
@@ -191,12 +190,10 @@
     delete *info;
 }
 
-
-AllocationTracker::AllocationTracker(
-    HeapObjectsMap* ids, StringsStorage* names)
+AllocationTracker::AllocationTracker(HeapObjectsMap* ids, StringsStorage* names)
     : ids_(ids),
       names_(names),
-      id_to_function_info_index_(HashMap::PointersMatch),
+      id_to_function_info_index_(base::HashMap::PointersMatch),
       info_index_for_other_state_(0) {
   FunctionInfo* info = new FunctionInfo();
   info->name = "(root)";
@@ -231,7 +228,7 @@
 
   Isolate* isolate = heap->isolate();
   int length = 0;
-  StackTraceFrameIterator it(isolate);
+  JavaScriptFrameIterator it(isolate);
   while (!it.done() && length < kMaxAllocationTraceLength) {
     JavaScriptFrame* frame = it.frame();
     SharedFunctionInfo* shared = frame->function()->shared();
@@ -262,7 +259,7 @@
 
 unsigned AllocationTracker::AddFunctionInfo(SharedFunctionInfo* shared,
                                             SnapshotObjectId id) {
-  HashMap::Entry* entry = id_to_function_info_index_.LookupOrInsert(
+  base::HashMap::Entry* entry = id_to_function_info_index_.LookupOrInsert(
       reinterpret_cast<void*>(id), SnapshotObjectIdHash(id));
   if (entry->value == NULL) {
     FunctionInfo* info = new FunctionInfo();
@@ -307,9 +304,8 @@
       info_(info) {
   script_ = Handle<Script>::cast(
       script->GetIsolate()->global_handles()->Create(script));
-  GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()),
-                          this,
-                          &HandleWeakScript);
+  GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()), this,
+                          &HandleWeakScript, v8::WeakCallbackType::kParameter);
 }
 
 
@@ -327,9 +323,8 @@
   info_->column = Script::GetColumnNumber(script_, start_position_);
 }
 
-
 void AllocationTracker::UnresolvedLocation::HandleWeakScript(
-    const v8::WeakCallbackData<v8::Value, void>& data) {
+    const v8::WeakCallbackInfo<void>& data) {
   UnresolvedLocation* loc =
       reinterpret_cast<UnresolvedLocation*>(data.GetParameter());
   GlobalHandles::Destroy(reinterpret_cast<Object**>(loc->script_.location()));
diff --git a/src/profiler/allocation-tracker.h b/src/profiler/allocation-tracker.h
index 03802a5..45bd446 100644
--- a/src/profiler/allocation-tracker.h
+++ b/src/profiler/allocation-tracker.h
@@ -8,8 +8,8 @@
 #include <map>
 
 #include "include/v8-profiler.h"
+#include "src/base/hashmap.h"
 #include "src/handles.h"
-#include "src/hashmap.h"
 #include "src/list.h"
 #include "src/vector.h"
 
@@ -129,8 +129,7 @@
     void Resolve();
 
    private:
-    static void HandleWeakScript(
-        const v8::WeakCallbackData<v8::Value, void>& data);
+    static void HandleWeakScript(const v8::WeakCallbackInfo<void>& data);
 
     Handle<Script> script_;
     int start_position_;
@@ -144,7 +143,7 @@
   AllocationTraceTree trace_tree_;
   unsigned allocation_trace_buffer_[kMaxAllocationTraceLength];
   List<FunctionInfo*> function_info_list_;
-  HashMap id_to_function_info_index_;
+  base::HashMap id_to_function_info_index_;
   List<UnresolvedLocation*> unresolved_locations_;
   unsigned info_index_for_other_state_;
   AddressToTraceMap address_to_trace_;
diff --git a/src/profiler/cpu-profiler-inl.h b/src/profiler/cpu-profiler-inl.h
index 45e4ccf..d8c9c90 100644
--- a/src/profiler/cpu-profiler-inl.h
+++ b/src/profiler/cpu-profiler-inl.h
@@ -35,7 +35,7 @@
 
 void CodeDeoptEventRecord::UpdateCodeMap(CodeMap* code_map) {
   CodeEntry* entry = code_map->FindEntry(start);
-  if (entry != NULL) entry->set_deopt_info(deopt_reason, position, pc_offset);
+  if (entry != NULL) entry->set_deopt_info(deopt_reason, position, deopt_id);
 }
 
 
diff --git a/src/profiler/cpu-profiler.cc b/src/profiler/cpu-profiler.cc
index 47585b7..42b5fdf 100644
--- a/src/profiler/cpu-profiler.cc
+++ b/src/profiler/cpu-profiler.cc
@@ -21,7 +21,7 @@
 
 
 ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator,
-                                                 Sampler* sampler,
+                                                 sampler::Sampler* sampler,
                                                  base::TimeDelta period)
     : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)),
       generator_(generator),
@@ -199,257 +199,23 @@
   }
 }
 
-
-void CpuProfiler::CallbackEvent(Name* name, Address entry_point) {
-  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
-  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
-  rec->start = entry_point;
-  rec->entry = profiles_->NewCodeEntry(
-      Logger::CALLBACK_TAG,
-      profiles_->GetName(name));
-  rec->size = 1;
-  processor_->Enqueue(evt_rec);
-}
-
-void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
-                                  AbstractCode* code, const char* name) {
-  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
-  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
-  rec->start = code->address();
-  rec->entry = profiles_->NewCodeEntry(
-      tag, profiles_->GetFunctionName(name), CodeEntry::kEmptyNamePrefix,
-      CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
-      CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
-  RecordInliningInfo(rec->entry, code);
-  rec->size = code->ExecutableSize();
-  processor_->Enqueue(evt_rec);
-}
-
-void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
-                                  AbstractCode* code, Name* name) {
-  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
-  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
-  rec->start = code->address();
-  rec->entry = profiles_->NewCodeEntry(
-      tag, profiles_->GetFunctionName(name), CodeEntry::kEmptyNamePrefix,
-      CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
-      CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
-  RecordInliningInfo(rec->entry, code);
-  rec->size = code->ExecutableSize();
-  processor_->Enqueue(evt_rec);
-}
-
-void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
-                                  AbstractCode* code,
-                                  SharedFunctionInfo* shared,
-                                  CompilationInfo* info, Name* script_name) {
-  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
-  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
-  rec->start = code->address();
-  rec->entry = profiles_->NewCodeEntry(
-      tag, profiles_->GetFunctionName(shared->DebugName()),
-      CodeEntry::kEmptyNamePrefix,
-      profiles_->GetName(InferScriptName(script_name, shared)),
-      CpuProfileNode::kNoLineNumberInfo, CpuProfileNode::kNoColumnNumberInfo,
-      NULL, code->instruction_start());
-  RecordInliningInfo(rec->entry, code);
-  if (info) {
-    rec->entry->set_inlined_function_infos(info->inlined_function_infos());
-  }
-  rec->entry->FillFunctionInfo(shared);
-  rec->size = code->ExecutableSize();
-  processor_->Enqueue(evt_rec);
-}
-
-void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
-                                  AbstractCode* abstract_code,
-                                  SharedFunctionInfo* shared,
-                                  CompilationInfo* info, Name* script_name,
-                                  int line, int column) {
-  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
-  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
-  rec->start = abstract_code->address();
-  Script* script = Script::cast(shared->script());
-  JITLineInfoTable* line_table = NULL;
-  if (script) {
-    if (abstract_code->IsCode()) {
-      Code* code = abstract_code->GetCode();
-      int start_position = shared->start_position();
-      int end_position = shared->end_position();
-      line_table = new JITLineInfoTable();
-      for (RelocIterator it(code); !it.done(); it.next()) {
-        RelocInfo* reloc_info = it.rinfo();
-        if (!RelocInfo::IsPosition(reloc_info->rmode())) continue;
-        int position = static_cast<int>(reloc_info->data());
-        // TODO(alph): in case of inlining the position may correspond
-        // to an inlined function source code. Do not collect positions
-        // that fall beyond the function source code. There's however a
-        // chance the inlined function has similar positions but in another
-        // script. So the proper fix is to store script_id in some form
-        // along with the inlined function positions.
-        if (position < start_position || position >= end_position) continue;
-        int pc_offset = static_cast<int>(reloc_info->pc() - code->address());
-        int line_number = script->GetLineNumber(position) + 1;
-        line_table->SetPosition(pc_offset, line_number);
-      }
-    } else {
-      BytecodeArray* bytecode = abstract_code->GetBytecodeArray();
-      line_table = new JITLineInfoTable();
-      interpreter::SourcePositionTableIterator it(
-          bytecode->source_position_table());
-      for (; !it.done(); it.Advance()) {
-        int line_number = script->GetLineNumber(it.source_position()) + 1;
-        int pc_offset = it.bytecode_offset() + BytecodeArray::kHeaderSize;
-        line_table->SetPosition(pc_offset, line_number);
-      }
+void CpuProfiler::CodeEventHandler(const CodeEventsContainer& evt_rec) {
+  switch (evt_rec.generic.type) {
+    case CodeEventRecord::CODE_CREATION:
+    case CodeEventRecord::CODE_MOVE:
+    case CodeEventRecord::CODE_DISABLE_OPT:
+      processor_->Enqueue(evt_rec);
+      break;
+    case CodeEventRecord::CODE_DEOPT: {
+      const CodeDeoptEventRecord* rec = &evt_rec.CodeDeoptEventRecord_;
+      Address pc = reinterpret_cast<Address>(rec->pc);
+      int fp_to_sp_delta = rec->fp_to_sp_delta;
+      processor_->Enqueue(evt_rec);
+      processor_->AddDeoptStack(isolate_, pc, fp_to_sp_delta);
+      break;
     }
-  }
-  rec->entry = profiles_->NewCodeEntry(
-      tag, profiles_->GetFunctionName(shared->DebugName()),
-      CodeEntry::kEmptyNamePrefix,
-      profiles_->GetName(InferScriptName(script_name, shared)), line, column,
-      line_table, abstract_code->instruction_start());
-  RecordInliningInfo(rec->entry, abstract_code);
-  if (info) {
-    rec->entry->set_inlined_function_infos(info->inlined_function_infos());
-  }
-  rec->entry->FillFunctionInfo(shared);
-  rec->size = abstract_code->ExecutableSize();
-  processor_->Enqueue(evt_rec);
-}
-
-void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
-                                  AbstractCode* code, int args_count) {
-  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
-  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
-  rec->start = code->address();
-  rec->entry = profiles_->NewCodeEntry(
-      tag, profiles_->GetName(args_count), "args_count: ",
-      CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
-      CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
-  RecordInliningInfo(rec->entry, code);
-  rec->size = code->ExecutableSize();
-  processor_->Enqueue(evt_rec);
-}
-
-void CpuProfiler::CodeMoveEvent(AbstractCode* from, Address to) {
-  CodeEventsContainer evt_rec(CodeEventRecord::CODE_MOVE);
-  CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
-  rec->from = from->address();
-  rec->to = to;
-  processor_->Enqueue(evt_rec);
-}
-
-void CpuProfiler::CodeDisableOptEvent(AbstractCode* code,
-                                      SharedFunctionInfo* shared) {
-  CodeEventsContainer evt_rec(CodeEventRecord::CODE_DISABLE_OPT);
-  CodeDisableOptEventRecord* rec = &evt_rec.CodeDisableOptEventRecord_;
-  rec->start = code->address();
-  rec->bailout_reason = GetBailoutReason(shared->disable_optimization_reason());
-  processor_->Enqueue(evt_rec);
-}
-
-void CpuProfiler::CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta) {
-  CodeEventsContainer evt_rec(CodeEventRecord::CODE_DEOPT);
-  CodeDeoptEventRecord* rec = &evt_rec.CodeDeoptEventRecord_;
-  Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(code, pc);
-  rec->start = code->address();
-  rec->deopt_reason = Deoptimizer::GetDeoptReason(info.deopt_reason);
-  rec->position = info.position;
-  rec->pc_offset = pc - code->instruction_start();
-  processor_->Enqueue(evt_rec);
-  processor_->AddDeoptStack(isolate_, pc, fp_to_sp_delta);
-}
-
-void CpuProfiler::GetterCallbackEvent(Name* name, Address entry_point) {
-  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
-  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
-  rec->start = entry_point;
-  rec->entry = profiles_->NewCodeEntry(
-      Logger::CALLBACK_TAG,
-      profiles_->GetName(name),
-      "get ");
-  rec->size = 1;
-  processor_->Enqueue(evt_rec);
-}
-
-void CpuProfiler::RegExpCodeCreateEvent(AbstractCode* code, String* source) {
-  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
-  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
-  rec->start = code->address();
-  rec->entry = profiles_->NewCodeEntry(
-      Logger::REG_EXP_TAG, profiles_->GetName(source), "RegExp: ",
-      CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
-      CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
-  rec->size = code->ExecutableSize();
-  processor_->Enqueue(evt_rec);
-}
-
-
-void CpuProfiler::SetterCallbackEvent(Name* name, Address entry_point) {
-  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
-  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
-  rec->start = entry_point;
-  rec->entry = profiles_->NewCodeEntry(
-      Logger::CALLBACK_TAG,
-      profiles_->GetName(name),
-      "set ");
-  rec->size = 1;
-  processor_->Enqueue(evt_rec);
-}
-
-Name* CpuProfiler::InferScriptName(Name* name, SharedFunctionInfo* info) {
-  if (name->IsString() && String::cast(name)->length()) return name;
-  if (!info->script()->IsScript()) return name;
-  Object* source_url = Script::cast(info->script())->source_url();
-  return source_url->IsName() ? Name::cast(source_url) : name;
-}
-
-void CpuProfiler::RecordInliningInfo(CodeEntry* entry,
-                                     AbstractCode* abstract_code) {
-  if (!abstract_code->IsCode()) return;
-  Code* code = abstract_code->GetCode();
-  if (code->kind() != Code::OPTIMIZED_FUNCTION) return;
-  DeoptimizationInputData* deopt_input_data =
-      DeoptimizationInputData::cast(code->deoptimization_data());
-  int deopt_count = deopt_input_data->DeoptCount();
-  for (int i = 0; i < deopt_count; i++) {
-    int pc_offset = deopt_input_data->Pc(i)->value();
-    if (pc_offset == -1) continue;
-    int translation_index = deopt_input_data->TranslationIndex(i)->value();
-    TranslationIterator it(deopt_input_data->TranslationByteArray(),
-                           translation_index);
-    Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
-    DCHECK_EQ(Translation::BEGIN, opcode);
-    it.Skip(Translation::NumberOfOperandsFor(opcode));
-    int depth = 0;
-    std::vector<CodeEntry*> inline_stack;
-    while (it.HasNext() &&
-           Translation::BEGIN !=
-               (opcode = static_cast<Translation::Opcode>(it.Next()))) {
-      if (opcode != Translation::JS_FRAME &&
-          opcode != Translation::INTERPRETED_FRAME) {
-        it.Skip(Translation::NumberOfOperandsFor(opcode));
-        continue;
-      }
-      it.Next();  // Skip ast_id
-      int shared_info_id = it.Next();
-      it.Next();  // Skip height
-      SharedFunctionInfo* shared_info = SharedFunctionInfo::cast(
-          deopt_input_data->LiteralArray()->get(shared_info_id));
-      if (!depth++) continue;  // Skip the current function itself.
-      CodeEntry* inline_entry = new CodeEntry(
-          entry->tag(), profiles_->GetFunctionName(shared_info->DebugName()),
-          CodeEntry::kEmptyNamePrefix, entry->resource_name(),
-          CpuProfileNode::kNoLineNumberInfo,
-          CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
-      inline_entry->FillFunctionInfo(shared_info);
-      inline_stack.push_back(inline_entry);
-    }
-    if (!inline_stack.empty()) {
-      entry->AddInlineStack(pc_offset, inline_stack);
-      DCHECK(inline_stack.empty());
-    }
+    default:
+      UNREACHABLE();
   }
 }
 
@@ -457,15 +223,12 @@
     : isolate_(isolate),
       sampling_interval_(base::TimeDelta::FromMicroseconds(
           FLAG_cpu_profiler_sampling_interval)),
-      profiles_(new CpuProfilesCollection(isolate->heap())),
-      generator_(NULL),
-      processor_(NULL),
+      profiles_(new CpuProfilesCollection(isolate)),
       is_profiling_(false) {
+  profiles_->set_cpu_profiler(this);
 }
 
-
-CpuProfiler::CpuProfiler(Isolate* isolate,
-                         CpuProfilesCollection* test_profiles,
+CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilesCollection* test_profiles,
                          ProfileGenerator* test_generator,
                          ProfilerEventsProcessor* test_processor)
     : isolate_(isolate),
@@ -475,28 +238,25 @@
       generator_(test_generator),
       processor_(test_processor),
       is_profiling_(false) {
+  profiles_->set_cpu_profiler(this);
 }
 
-
 CpuProfiler::~CpuProfiler() {
   DCHECK(!is_profiling_);
-  delete profiles_;
 }
 
-
 void CpuProfiler::set_sampling_interval(base::TimeDelta value) {
   DCHECK(!is_profiling_);
   sampling_interval_ = value;
 }
 
-
 void CpuProfiler::ResetProfiles() {
-  delete profiles_;
-  profiles_ = new CpuProfilesCollection(isolate()->heap());
+  profiles_.reset(new CpuProfilesCollection(isolate_));
+  profiles_->set_cpu_profiler(this);
 }
 
 void CpuProfiler::CollectSample() {
-  if (processor_ != NULL) {
+  if (processor_) {
     processor_->AddCurrentStack(isolate_);
   }
 }
@@ -515,7 +275,7 @@
 
 
 void CpuProfiler::StartProcessorIfNotStarted() {
-  if (processor_ != NULL) {
+  if (processor_) {
     processor_->AddCurrentStack(isolate_);
     return;
   }
@@ -523,11 +283,15 @@
   // Disable logging when using the new implementation.
   saved_is_logging_ = logger->is_logging_;
   logger->is_logging_ = false;
-  generator_ = new ProfileGenerator(profiles_);
-  Sampler* sampler = logger->sampler();
-  processor_ = new ProfilerEventsProcessor(
-      generator_, sampler, sampling_interval_);
+  sampler::Sampler* sampler = logger->sampler();
+  generator_.reset(new ProfileGenerator(profiles_.get()));
+  processor_.reset(new ProfilerEventsProcessor(generator_.get(), sampler,
+                                               sampling_interval_));
+  logger->SetUpProfilerListener();
+  ProfilerListener* profiler_listener = logger->profiler_listener();
+  profiler_listener->AddObserver(this);
   is_profiling_ = true;
+  isolate_->set_is_profiling(true);
   // Enumerate stuff we already have in the heap.
   DCHECK(isolate_->heap()->HasBeenSetUp());
   if (!FLAG_prof_browser_mode) {
@@ -545,10 +309,10 @@
 
 
 CpuProfile* CpuProfiler::StopProfiling(const char* title) {
-  if (!is_profiling_) return NULL;
+  if (!is_profiling_) return nullptr;
   StopProcessorIfLastProfile(title);
   CpuProfile* result = profiles_->StopProfiling(title);
-  if (result != NULL) {
+  if (result) {
     result->Print();
   }
   return result;
@@ -556,7 +320,7 @@
 
 
 CpuProfile* CpuProfiler::StopProfiling(String* title) {
-  if (!is_profiling_) return NULL;
+  if (!is_profiling_) return nullptr;
   const char* profile_title = profiles_->GetName(title);
   StopProcessorIfLastProfile(profile_title);
   return profiles_->StopProfiling(profile_title);
@@ -564,19 +328,24 @@
 
 
 void CpuProfiler::StopProcessorIfLastProfile(const char* title) {
-  if (profiles_->IsLastProfile(title)) StopProcessor();
+  if (profiles_->IsLastProfile(title)) {
+    StopProcessor();
+  }
 }
 
 
 void CpuProfiler::StopProcessor() {
   Logger* logger = isolate_->logger();
-  Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
+  sampler::Sampler* sampler =
+      reinterpret_cast<sampler::Sampler*>(logger->ticker_);
   is_profiling_ = false;
+  isolate_->set_is_profiling(false);
+  ProfilerListener* profiler_listener = logger->profiler_listener();
+  profiler_listener->RemoveObserver(this);
   processor_->StopSynchronously();
-  delete processor_;
-  delete generator_;
-  processor_ = NULL;
-  generator_ = NULL;
+  logger->TearDownProfilerListener();
+  processor_.reset();
+  generator_.reset();
   sampler->SetHasProcessingThread(false);
   sampler->DecreaseProfilingDepth();
   logger->is_logging_ = saved_is_logging_;
@@ -596,6 +365,5 @@
   }
 }
 
-
 }  // namespace internal
 }  // namespace v8
diff --git a/src/profiler/cpu-profiler.h b/src/profiler/cpu-profiler.h
index a04ee3c..d354aeb 100644
--- a/src/profiler/cpu-profiler.h
+++ b/src/profiler/cpu-profiler.h
@@ -5,14 +5,19 @@
 #ifndef V8_PROFILER_CPU_PROFILER_H_
 #define V8_PROFILER_CPU_PROFILER_H_
 
+#include <memory>
+
 #include "src/allocation.h"
-#include "src/atomic-utils.h"
+#include "src/base/atomic-utils.h"
 #include "src/base/atomicops.h"
 #include "src/base/platform/time.h"
 #include "src/compiler.h"
+#include "src/isolate.h"
+#include "src/libsampler/v8-sampler.h"
 #include "src/locked-queue.h"
 #include "src/profiler/circular-queue.h"
-#include "src/profiler/sampler.h"
+#include "src/profiler/profiler-listener.h"
+#include "src/profiler/tick-sample.h"
 
 namespace v8 {
 namespace internal {
@@ -20,7 +25,6 @@
 // Forward declarations.
 class CodeEntry;
 class CodeMap;
-class CompilationInfo;
 class CpuProfile;
 class CpuProfilesCollection;
 class ProfileGenerator;
@@ -81,7 +85,9 @@
   Address start;
   const char* deopt_reason;
   SourcePosition position;
-  size_t pc_offset;
+  int deopt_id;
+  void* pc;
+  int fp_to_sp_delta;
 
   INLINE(void UpdateCodeMap(CodeMap* code_map));
 };
@@ -128,7 +134,7 @@
 class ProfilerEventsProcessor : public base::Thread {
  public:
   ProfilerEventsProcessor(ProfileGenerator* generator,
-                          Sampler* sampler,
+                          sampler::Sampler* sampler,
                           base::TimeDelta period);
   virtual ~ProfilerEventsProcessor();
 
@@ -166,7 +172,7 @@
   SampleProcessingResult ProcessOneSample();
 
   ProfileGenerator* generator_;
-  Sampler* sampler_;
+  sampler::Sampler* sampler_;
   base::Atomic32 running_;
   const base::TimeDelta period_;  // Samples & code events processing period.
   LockedQueue<CodeEventsContainer> events_buffer_;
@@ -176,28 +182,15 @@
   SamplingCircularQueue<TickSampleEventRecord,
                         kTickSampleQueueLength> ticks_buffer_;
   LockedQueue<TickSampleEventRecord> ticks_from_vm_buffer_;
-  AtomicNumber<unsigned> last_code_event_id_;
+  base::AtomicNumber<unsigned> last_code_event_id_;
   unsigned last_processed_code_event_id_;
 };
 
-
-#define PROFILE(IsolateGetter, Call)                                        \
-  do {                                                                      \
-    Isolate* cpu_profiler_isolate = (IsolateGetter);                        \
-    v8::internal::Logger* logger = cpu_profiler_isolate->logger();          \
-    CpuProfiler* cpu_profiler = cpu_profiler_isolate->cpu_profiler();       \
-    if (logger->is_logging_code_events() || cpu_profiler->is_profiling()) { \
-      logger->Call;                                                         \
-    }                                                                       \
-  } while (false)
-
-
-class CpuProfiler : public CodeEventListener {
+class CpuProfiler : public CodeEventObserver {
  public:
   explicit CpuProfiler(Isolate* isolate);
 
-  CpuProfiler(Isolate* isolate,
-              CpuProfilesCollection* test_collection,
+  CpuProfiler(Isolate* isolate, CpuProfilesCollection* profiles,
               ProfileGenerator* test_generator,
               ProfilerEventsProcessor* test_processor);
 
@@ -214,42 +207,16 @@
   void DeleteAllProfiles();
   void DeleteProfile(CpuProfile* profile);
 
+  void CodeEventHandler(const CodeEventsContainer& evt_rec) override;
+
   // Invoked from stack sampler (thread or signal handler.)
   inline TickSample* StartTickSample();
   inline void FinishTickSample();
 
-  // Must be called via PROFILE macro, otherwise will crash when
-  // profiling is not enabled.
-  void CallbackEvent(Name* name, Address entry_point) override;
-  void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
-                       const char* comment) override;
-  void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
-                       Name* name) override;
-  void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
-                       SharedFunctionInfo* shared, CompilationInfo* info,
-                       Name* script_name) override;
-  void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
-                       SharedFunctionInfo* shared, CompilationInfo* info,
-                       Name* script_name, int line, int column) override;
-  void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
-                       int args_count) override;
-  void CodeMovingGCEvent() override {}
-  void CodeMoveEvent(AbstractCode* from, Address to) override;
-  void CodeDisableOptEvent(AbstractCode* code,
-                           SharedFunctionInfo* shared) override;
-  void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta);
-  void GetterCallbackEvent(Name* name, Address entry_point) override;
-  void RegExpCodeCreateEvent(AbstractCode* code, String* source) override;
-  void SetterCallbackEvent(Name* name, Address entry_point) override;
-  void SharedFunctionInfoMoveEvent(Address from, Address to) override {}
+  bool is_profiling() const { return is_profiling_; }
 
-  INLINE(bool is_profiling() const) { return is_profiling_; }
-  bool* is_profiling_address() {
-    return &is_profiling_;
-  }
-
-  ProfileGenerator* generator() const { return generator_; }
-  ProfilerEventsProcessor* processor() const { return processor_; }
+  ProfileGenerator* generator() const { return generator_.get(); }
+  ProfilerEventsProcessor* processor() const { return processor_.get(); }
   Isolate* isolate() const { return isolate_; }
 
  private:
@@ -258,14 +225,12 @@
   void StopProcessor();
   void ResetProfiles();
   void LogBuiltins();
-  void RecordInliningInfo(CodeEntry* entry, AbstractCode* abstract_code);
-  Name* InferScriptName(Name* name, SharedFunctionInfo* info);
 
-  Isolate* isolate_;
+  Isolate* const isolate_;
   base::TimeDelta sampling_interval_;
-  CpuProfilesCollection* profiles_;
-  ProfileGenerator* generator_;
-  ProfilerEventsProcessor* processor_;
+  std::unique_ptr<CpuProfilesCollection> profiles_;
+  std::unique_ptr<ProfileGenerator> generator_;
+  std::unique_ptr<ProfilerEventsProcessor> processor_;
   bool saved_is_logging_;
   bool is_profiling_;
 
diff --git a/src/profiler/heap-profiler.cc b/src/profiler/heap-profiler.cc
index 1305cae..e048fae 100644
--- a/src/profiler/heap-profiler.cc
+++ b/src/profiler/heap-profiler.cc
@@ -84,14 +84,14 @@
   return result;
 }
 
-
-bool HeapProfiler::StartSamplingHeapProfiler(uint64_t sample_interval,
-                                             int stack_depth) {
+bool HeapProfiler::StartSamplingHeapProfiler(
+    uint64_t sample_interval, int stack_depth,
+    v8::HeapProfiler::SamplingFlags flags) {
   if (sampling_heap_profiler_.get()) {
     return false;
   }
   sampling_heap_profiler_.Reset(new SamplingHeapProfiler(
-      heap(), names_.get(), sample_interval, stack_depth));
+      heap(), names_.get(), sample_interval, stack_depth, flags));
   return true;
 }
 
diff --git a/src/profiler/heap-profiler.h b/src/profiler/heap-profiler.h
index 32e143c..93cb57a 100644
--- a/src/profiler/heap-profiler.h
+++ b/src/profiler/heap-profiler.h
@@ -30,7 +30,8 @@
       v8::ActivityControl* control,
       v8::HeapProfiler::ObjectNameResolver* resolver);
 
-  bool StartSamplingHeapProfiler(uint64_t sample_interval, int stack_depth);
+  bool StartSamplingHeapProfiler(uint64_t sample_interval, int stack_depth,
+                                 v8::HeapProfiler::SamplingFlags);
   void StopSamplingHeapProfiler();
   bool is_sampling_allocations() { return !sampling_heap_profiler_.is_empty(); }
   AllocationProfile* GetAllocationProfile();
diff --git a/src/profiler/heap-snapshot-generator.cc b/src/profiler/heap-snapshot-generator.cc
index 748f307..c80877f 100644
--- a/src/profiler/heap-snapshot-generator.cc
+++ b/src/profiler/heap-snapshot-generator.cc
@@ -80,8 +80,8 @@
 void HeapEntry::Print(
     const char* prefix, const char* edge_name, int max_depth, int indent) {
   STATIC_ASSERT(sizeof(unsigned) == sizeof(id()));
-  base::OS::Print("%6" V8PRIuPTR " @%6u %*c %s%s: ", self_size(), id(), indent,
-                  ' ', prefix, edge_name);
+  base::OS::Print("%6" PRIuS " @%6u %*c %s%s: ", self_size(), id(), indent, ' ',
+                  prefix, edge_name);
   if (type() != kString) {
     base::OS::Print("%s %.40s\n", TypeAsString(), name_);
   } else {
@@ -392,7 +392,7 @@
       entries_.at(to_entry_info_index).addr = NULL;
     }
   } else {
-    HashMap::Entry* to_entry =
+    base::HashMap::Entry* to_entry =
         entries_map_.LookupOrInsert(to, ComputePointerHash(to));
     if (to_entry->value != NULL) {
       // We found the existing entry with to address for an old object.
@@ -412,10 +412,8 @@
     // object is migrated.
     if (FLAG_heap_profiler_trace_objects) {
       PrintF("Move object from %p to %p old size %6d new size %6d\n",
-             from,
-             to,
-             entries_.at(from_entry_info_index).size,
-             object_size);
+             static_cast<void*>(from), static_cast<void*>(to),
+             entries_.at(from_entry_info_index).size, object_size);
     }
     entries_.at(from_entry_info_index).size = object_size;
     to_entry->value = from_value;
@@ -430,7 +428,8 @@
 
 
 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) {
-  HashMap::Entry* entry = entries_map_.Lookup(addr, ComputePointerHash(addr));
+  base::HashMap::Entry* entry =
+      entries_map_.Lookup(addr, ComputePointerHash(addr));
   if (entry == NULL) return 0;
   int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
   EntryInfo& entry_info = entries_.at(entry_index);
@@ -443,7 +442,7 @@
                                                 unsigned int size,
                                                 bool accessed) {
   DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy());
-  HashMap::Entry* entry =
+  base::HashMap::Entry* entry =
       entries_map_.LookupOrInsert(addr, ComputePointerHash(addr));
   if (entry->value != NULL) {
     int entry_index =
@@ -452,9 +451,7 @@
     entry_info.accessed = accessed;
     if (FLAG_heap_profiler_trace_objects) {
       PrintF("Update object size : %p with old size %d and new size %d\n",
-             addr,
-             entry_info.size,
-             size);
+             static_cast<void*>(addr), entry_info.size, size);
     }
     entry_info.size = size;
     return entry_info.id;
@@ -487,9 +484,8 @@
     FindOrAddEntry(obj->address(), obj->Size());
     if (FLAG_heap_profiler_trace_objects) {
       PrintF("Update object      : %p %6d. Next address is %p\n",
-             obj->address(),
-             obj->Size(),
-             obj->address() + obj->Size());
+             static_cast<void*>(obj->address()), obj->Size(),
+             static_cast<void*>(obj->address() + obj->Size()));
     }
   }
   RemoveDeadEntries();
@@ -517,20 +513,16 @@
   void Print() const {
     if (expected_size == 0) {
       PrintF("Untracked object   : %p %6d. Next address is %p\n",
-             obj->address(),
-             obj->Size(),
-             obj->address() + obj->Size());
+             static_cast<void*>(obj->address()), obj->Size(),
+             static_cast<void*>(obj->address() + obj->Size()));
     } else if (obj->Size() != expected_size) {
-      PrintF("Wrong size %6d: %p %6d. Next address is %p\n",
-             expected_size,
-             obj->address(),
-             obj->Size(),
-             obj->address() + obj->Size());
+      PrintF("Wrong size %6d: %p %6d. Next address is %p\n", expected_size,
+             static_cast<void*>(obj->address()), obj->Size(),
+             static_cast<void*>(obj->address() + obj->Size()));
     } else {
       PrintF("Good object      : %p %6d. Next address is %p\n",
-             obj->address(),
-             expected_size,
-             obj->address() + obj->Size());
+             static_cast<void*>(obj->address()), expected_size,
+             static_cast<void*>(obj->address() + obj->Size()));
     }
   }
 };
@@ -554,7 +546,7 @@
   for (HeapObject* obj = iterator.next();
        obj != NULL;
        obj = iterator.next()) {
-    HashMap::Entry* entry =
+    base::HashMap::Entry* entry =
         entries_map_.Lookup(obj->address(), ComputePointerHash(obj->address()));
     if (entry == NULL) {
       ++untracked;
@@ -674,7 +666,7 @@
         entries_.at(first_free_entry) = entry_info;
       }
       entries_.at(first_free_entry).accessed = false;
-      HashMap::Entry* entry = entries_map_.Lookup(
+      base::HashMap::Entry* entry = entries_map_.Lookup(
           entry_info.addr, ComputePointerHash(entry_info.addr));
       DCHECK(entry);
       entry->value = reinterpret_cast<void*>(first_free_entry);
@@ -707,37 +699,28 @@
 
 
 size_t HeapObjectsMap::GetUsedMemorySize() const {
-  return
-      sizeof(*this) +
-      sizeof(HashMap::Entry) * entries_map_.capacity() +
-      GetMemoryUsedByList(entries_) +
-      GetMemoryUsedByList(time_intervals_);
+  return sizeof(*this) +
+         sizeof(base::HashMap::Entry) * entries_map_.capacity() +
+         GetMemoryUsedByList(entries_) + GetMemoryUsedByList(time_intervals_);
 }
 
-
-HeapEntriesMap::HeapEntriesMap()
-    : entries_(HashMap::PointersMatch) {
-}
-
+HeapEntriesMap::HeapEntriesMap() : entries_(base::HashMap::PointersMatch) {}
 
 int HeapEntriesMap::Map(HeapThing thing) {
-  HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing));
+  base::HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing));
   if (cache_entry == NULL) return HeapEntry::kNoEntry;
   return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value));
 }
 
 
 void HeapEntriesMap::Pair(HeapThing thing, int entry) {
-  HashMap::Entry* cache_entry = entries_.LookupOrInsert(thing, Hash(thing));
+  base::HashMap::Entry* cache_entry =
+      entries_.LookupOrInsert(thing, Hash(thing));
   DCHECK(cache_entry->value == NULL);
   cache_entry->value = reinterpret_cast<void*>(static_cast<intptr_t>(entry));
 }
 
-
-HeapObjectsSet::HeapObjectsSet()
-    : entries_(HashMap::PointersMatch) {
-}
-
+HeapObjectsSet::HeapObjectsSet() : entries_(base::HashMap::PointersMatch) {}
 
 void HeapObjectsSet::Clear() {
   entries_.Clear();
@@ -760,7 +743,7 @@
 
 const char* HeapObjectsSet::GetTag(Object* obj) {
   HeapObject* object = HeapObject::cast(obj);
-  HashMap::Entry* cache_entry =
+  base::HashMap::Entry* cache_entry =
       entries_.Lookup(object, HeapEntriesMap::Hash(object));
   return cache_entry != NULL
       ? reinterpret_cast<const char*>(cache_entry->value)
@@ -771,7 +754,7 @@
 void HeapObjectsSet::SetTag(Object* obj, const char* tag) {
   if (!obj->IsHeapObject()) return;
   HeapObject* object = HeapObject::cast(obj);
-  HashMap::Entry* cache_entry =
+  base::HashMap::Entry* cache_entry =
       entries_.LookupOrInsert(object, HeapEntriesMap::Hash(object));
   cache_entry->value = const_cast<char*>(tag);
 }
@@ -1058,8 +1041,6 @@
     ExtractAccessorInfoReferences(entry, AccessorInfo::cast(obj));
   } else if (obj->IsAccessorPair()) {
     ExtractAccessorPairReferences(entry, AccessorPair::cast(obj));
-  } else if (obj->IsCodeCache()) {
-    ExtractCodeCacheReferences(entry, CodeCache::cast(obj));
   } else if (obj->IsCode()) {
     ExtractCodeReferences(entry, Code::cast(obj));
   } else if (obj->IsBox()) {
@@ -1119,7 +1100,7 @@
   } else if (obj->IsJSFunction()) {
     JSFunction* js_fun = JSFunction::cast(js_obj);
     Object* proto_or_map = js_fun->prototype_or_initial_map();
-    if (!proto_or_map->IsTheHole()) {
+    if (!proto_or_map->IsTheHole(heap_->isolate())) {
       if (!proto_or_map->IsMap()) {
         SetPropertyReference(
             obj, entry,
@@ -1389,9 +1370,9 @@
   SetInternalReference(obj, entry,
                        "optimized_code_map", shared->optimized_code_map(),
                        SharedFunctionInfo::kOptimizedCodeMapOffset);
-  SetInternalReference(obj, entry,
-                       "feedback_vector", shared->feedback_vector(),
-                       SharedFunctionInfo::kFeedbackVectorOffset);
+  SetInternalReference(obj, entry, "feedback_metadata",
+                       shared->feedback_metadata(),
+                       SharedFunctionInfo::kFeedbackMetadataOffset);
 }
 
 
@@ -1444,19 +1425,6 @@
 }
 
 
-void V8HeapExplorer::ExtractCodeCacheReferences(
-    int entry, CodeCache* code_cache) {
-  TagObject(code_cache->default_cache(), "(default code cache)");
-  SetInternalReference(code_cache, entry,
-                       "default_cache", code_cache->default_cache(),
-                       CodeCache::kDefaultCacheOffset);
-  TagObject(code_cache->normal_type_cache(), "(code type cache)");
-  SetInternalReference(code_cache, entry,
-                       "type_cache", code_cache->normal_type_cache(),
-                       CodeCache::kNormalTypeCacheOffset);
-}
-
-
 void V8HeapExplorer::TagBuiltinCodeObject(Code* code, const char* name) {
   TagObject(code, names_->GetFormatted("(%s builtin)", name));
 }
@@ -1582,6 +1550,7 @@
 
 
 void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
+  Isolate* isolate = js_obj->GetIsolate();
   if (js_obj->HasFastProperties()) {
     DescriptorArray* descs = js_obj->map()->instance_descriptors();
     int real_size = js_obj->map()->NumberOfOwnDescriptors();
@@ -1598,14 +1567,8 @@
           int field_offset =
               field_index.is_inobject() ? field_index.offset() : -1;
 
-          if (k != heap_->hidden_properties_symbol()) {
-            SetDataOrAccessorPropertyReference(details.kind(), js_obj, entry, k,
-                                               value, NULL, field_offset);
-          } else {
-            TagObject(value, "(hidden properties)");
-            SetInternalReference(js_obj, entry, "hidden_properties", value,
-                                 field_offset);
-          }
+          SetDataOrAccessorPropertyReference(details.kind(), js_obj, entry, k,
+                                             value, NULL, field_offset);
           break;
         }
         case kDescriptor:
@@ -1621,15 +1584,10 @@
     int length = dictionary->Capacity();
     for (int i = 0; i < length; ++i) {
       Object* k = dictionary->KeyAt(i);
-      if (dictionary->IsKey(k)) {
+      if (dictionary->IsKey(isolate, k)) {
         DCHECK(dictionary->ValueAt(i)->IsPropertyCell());
         PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(i));
         Object* value = cell->value();
-        if (k == heap_->hidden_properties_symbol()) {
-          TagObject(value, "(hidden properties)");
-          SetInternalReference(js_obj, entry, "hidden_properties", value);
-          continue;
-        }
         PropertyDetails details = cell->property_details();
         SetDataOrAccessorPropertyReference(details.kind(), js_obj, entry,
                                            Name::cast(k), value);
@@ -1640,13 +1598,8 @@
     int length = dictionary->Capacity();
     for (int i = 0; i < length; ++i) {
       Object* k = dictionary->KeyAt(i);
-      if (dictionary->IsKey(k)) {
+      if (dictionary->IsKey(isolate, k)) {
         Object* value = dictionary->ValueAt(i);
-        if (k == heap_->hidden_properties_symbol()) {
-          TagObject(value, "(hidden properties)");
-          SetInternalReference(js_obj, entry, "hidden_properties", value);
-          continue;
-        }
         PropertyDetails details = dictionary->DetailsAt(i);
         SetDataOrAccessorPropertyReference(details.kind(), js_obj, entry,
                                            Name::cast(k), value);
@@ -1675,13 +1628,14 @@
 
 
 void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, int entry) {
+  Isolate* isolate = js_obj->GetIsolate();
   if (js_obj->HasFastObjectElements()) {
     FixedArray* elements = FixedArray::cast(js_obj->elements());
     int length = js_obj->IsJSArray() ?
         Smi::cast(JSArray::cast(js_obj)->length())->value() :
         elements->length();
     for (int i = 0; i < length; ++i) {
-      if (!elements->get(i)->IsTheHole()) {
+      if (!elements->get(i)->IsTheHole(isolate)) {
         SetElementReference(js_obj, entry, i, elements->get(i));
       }
     }
@@ -1690,7 +1644,7 @@
     int length = dictionary->Capacity();
     for (int i = 0; i < length; ++i) {
       Object* k = dictionary->KeyAt(i);
-      if (dictionary->IsKey(k)) {
+      if (dictionary->IsKey(isolate, k)) {
         DCHECK(k->IsNumber());
         uint32_t index = static_cast<uint32_t>(k->Number());
         SetElementReference(js_obj, entry, index, dictionary->ValueAt(i));
@@ -2262,9 +2216,9 @@
   intptr_t elements = info->GetElementCount();
   intptr_t size = info->GetSizeInBytes();
   const char* name = elements != -1
-      ? names_->GetFormatted(
-            "%s / %" V8_PTR_PREFIX "d entries", info->GetLabel(), elements)
-      : names_->GetCopy(info->GetLabel());
+                         ? names_->GetFormatted("%s / %" V8PRIdPTR " entries",
+                                                info->GetLabel(), elements)
+                         : names_->GetCopy(info->GetLabel());
   return snapshot_->AddEntry(
       entries_type_,
       name,
@@ -2292,8 +2246,7 @@
 
 
 NativeObjectsExplorer::~NativeObjectsExplorer() {
-  for (HashMap::Entry* p = objects_by_info_.Start();
-       p != NULL;
+  for (base::HashMap::Entry* p = objects_by_info_.Start(); p != NULL;
        p = objects_by_info_.Next(p)) {
     v8::RetainedObjectInfo* info =
         reinterpret_cast<v8::RetainedObjectInfo*>(p->key);
@@ -2302,8 +2255,7 @@
         reinterpret_cast<List<HeapObject*>* >(p->value);
     delete objects;
   }
-  for (HashMap::Entry* p = native_groups_.Start();
-       p != NULL;
+  for (base::HashMap::Entry* p = native_groups_.Start(); p != NULL;
        p = native_groups_.Next(p)) {
     v8::RetainedObjectInfo* info =
         reinterpret_cast<v8::RetainedObjectInfo*>(p->value);
@@ -2375,7 +2327,8 @@
 
 List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo(
     v8::RetainedObjectInfo* info) {
-  HashMap::Entry* entry = objects_by_info_.LookupOrInsert(info, InfoHash(info));
+  base::HashMap::Entry* entry =
+      objects_by_info_.LookupOrInsert(info, InfoHash(info));
   if (entry->value != NULL) {
     info->Dispose();
   } else {
@@ -2391,8 +2344,7 @@
   FillRetainedObjects();
   FillImplicitReferences();
   if (EstimateObjectsCount() > 0) {
-    for (HashMap::Entry* p = objects_by_info_.Start();
-         p != NULL;
+    for (base::HashMap::Entry* p = objects_by_info_.Start(); p != NULL;
          p = objects_by_info_.Next(p)) {
       v8::RetainedObjectInfo* info =
           reinterpret_cast<v8::RetainedObjectInfo*>(p->key);
@@ -2444,7 +2396,7 @@
       label_copy,
       static_cast<int>(strlen(label_copy)),
       isolate_->heap()->HashSeed());
-  HashMap::Entry* entry =
+  base::HashMap::Entry* entry =
       native_groups_.LookupOrInsert(const_cast<char*>(label_copy), hash);
   if (entry->value == NULL) {
     entry->value = new NativeGroupRetainedObjectInfo(label);
@@ -2490,8 +2442,7 @@
 
 
 void NativeObjectsExplorer::SetRootNativeRootsReference() {
-  for (HashMap::Entry* entry = native_groups_.Start();
-       entry;
+  for (base::HashMap::Entry* entry = native_groups_.Start(); entry;
        entry = native_groups_.Next(entry)) {
     NativeGroupRetainedObjectInfo* group_info =
         static_cast<NativeGroupRetainedObjectInfo*>(entry->value);
@@ -2759,7 +2710,7 @@
 
 
 int HeapSnapshotJSONSerializer::GetStringId(const char* s) {
-  HashMap::Entry* cache_entry =
+  base::HashMap::Entry* cache_entry =
       strings_.LookupOrInsert(const_cast<char*>(s), StringHash(s));
   if (cache_entry->value == NULL) {
     cache_entry->value = reinterpret_cast<void*>(next_string_id_++);
@@ -3144,8 +3095,7 @@
 void HeapSnapshotJSONSerializer::SerializeStrings() {
   ScopedVector<const unsigned char*> sorted_strings(
       strings_.occupancy() + 1);
-  for (HashMap::Entry* entry = strings_.Start();
-       entry != NULL;
+  for (base::HashMap::Entry* entry = strings_.Start(); entry != NULL;
        entry = strings_.Next(entry)) {
     int index = static_cast<int>(reinterpret_cast<uintptr_t>(entry->value));
     sorted_strings[index] = reinterpret_cast<const unsigned char*>(entry->key);
diff --git a/src/profiler/heap-snapshot-generator.h b/src/profiler/heap-snapshot-generator.h
index 857f240..a6bc385 100644
--- a/src/profiler/heap-snapshot-generator.h
+++ b/src/profiler/heap-snapshot-generator.h
@@ -259,7 +259,7 @@
   };
 
   SnapshotObjectId next_id_;
-  HashMap entries_map_;
+  base::HashMap entries_map_;
   List<EntryInfo> entries_;
   List<TimeInterval> time_intervals_;
   Heap* heap_;
@@ -297,7 +297,7 @@
         v8::internal::kZeroHashSeed);
   }
 
-  HashMap entries_;
+  base::HashMap entries_;
 
   friend class HeapObjectsSet;
 
@@ -316,7 +316,7 @@
   bool is_empty() const { return entries_.occupancy() == 0; }
 
  private:
-  HashMap entries_;
+  base::HashMap entries_;
 
   DISALLOW_COPY_AND_ASSIGN(HeapObjectsSet);
 };
@@ -382,7 +382,6 @@
   void ExtractScriptReferences(int entry, Script* script);
   void ExtractAccessorInfoReferences(int entry, AccessorInfo* accessor_info);
   void ExtractAccessorPairReferences(int entry, AccessorPair* accessors);
-  void ExtractCodeCacheReferences(int entry, CodeCache* code_cache);
   void ExtractCodeReferences(int entry, Code* code);
   void ExtractBoxReferences(int entry, Box* box);
   void ExtractCellReferences(int entry, Cell* cell);
@@ -522,8 +521,8 @@
   bool embedder_queried_;
   HeapObjectsSet in_groups_;
   // RetainedObjectInfo* -> List<HeapObject*>*
-  HashMap objects_by_info_;
-  HashMap native_groups_;
+  base::HashMap objects_by_info_;
+  base::HashMap native_groups_;
   HeapEntriesAllocator* synthetic_entries_allocator_;
   HeapEntriesAllocator* native_entries_allocator_;
   // Used during references extraction.
@@ -610,7 +609,7 @@
   static const int kNodeFieldsCount;
 
   HeapSnapshot* snapshot_;
-  HashMap strings_;
+  base::HashMap strings_;
   int next_node_id_;
   int next_string_id_;
   OutputStreamWriter* writer_;
diff --git a/src/profiler/profile-generator-inl.h b/src/profiler/profile-generator-inl.h
index 85edce2..0bb17e2 100644
--- a/src/profiler/profile-generator-inl.h
+++ b/src/profiler/profile-generator-inl.h
@@ -10,7 +10,7 @@
 namespace v8 {
 namespace internal {
 
-CodeEntry::CodeEntry(Logger::LogEventsAndTags tag, const char* name,
+CodeEntry::CodeEntry(CodeEventListener::LogEventsAndTags tag, const char* name,
                      const char* name_prefix, const char* resource_name,
                      int line_number, int column_number,
                      JITLineInfoTable* line_info, Address instruction_start)
@@ -29,7 +29,6 @@
       line_info_(line_info),
       instruction_start_(instruction_start) {}
 
-
 ProfileNode::ProfileNode(ProfileTree* tree, CodeEntry* entry)
     : tree_(tree),
       entry_(entry),
diff --git a/src/profiler/profile-generator.cc b/src/profiler/profile-generator.cc
index abcd9e5..d40cf2a 100644
--- a/src/profiler/profile-generator.cc
+++ b/src/profiler/profile-generator.cc
@@ -5,12 +5,13 @@
 #include "src/profiler/profile-generator.h"
 
 #include "src/ast/scopeinfo.h"
+#include "src/base/adapters.h"
 #include "src/debug/debug.h"
 #include "src/deoptimizer.h"
 #include "src/global-handles.h"
+#include "src/profiler/cpu-profiler.h"
 #include "src/profiler/profile-generator-inl.h"
-#include "src/profiler/sampler.h"
-#include "src/splay-tree-inl.h"
+#include "src/profiler/tick-sample.h"
 #include "src/unicode.h"
 
 namespace v8 {
@@ -47,6 +48,41 @@
 const char* const CodeEntry::kEmptyBailoutReason = "";
 const char* const CodeEntry::kNoDeoptReason = "";
 
+const char* const CodeEntry::kProgramEntryName = "(program)";
+const char* const CodeEntry::kIdleEntryName = "(idle)";
+const char* const CodeEntry::kGarbageCollectorEntryName = "(garbage collector)";
+const char* const CodeEntry::kUnresolvedFunctionName = "(unresolved function)";
+
+base::LazyDynamicInstance<CodeEntry, CodeEntry::ProgramEntryCreateTrait>::type
+    CodeEntry::kProgramEntry = LAZY_DYNAMIC_INSTANCE_INITIALIZER;
+
+base::LazyDynamicInstance<CodeEntry, CodeEntry::IdleEntryCreateTrait>::type
+    CodeEntry::kIdleEntry = LAZY_DYNAMIC_INSTANCE_INITIALIZER;
+
+base::LazyDynamicInstance<CodeEntry, CodeEntry::GCEntryCreateTrait>::type
+    CodeEntry::kGCEntry = LAZY_DYNAMIC_INSTANCE_INITIALIZER;
+
+base::LazyDynamicInstance<CodeEntry,
+                          CodeEntry::UnresolvedEntryCreateTrait>::type
+    CodeEntry::kUnresolvedEntry = LAZY_DYNAMIC_INSTANCE_INITIALIZER;
+
+CodeEntry* CodeEntry::ProgramEntryCreateTrait::Create() {
+  return new CodeEntry(Logger::FUNCTION_TAG, CodeEntry::kProgramEntryName);
+}
+
+CodeEntry* CodeEntry::IdleEntryCreateTrait::Create() {
+  return new CodeEntry(Logger::FUNCTION_TAG, CodeEntry::kIdleEntryName);
+}
+
+CodeEntry* CodeEntry::GCEntryCreateTrait::Create() {
+  return new CodeEntry(Logger::BUILTIN_TAG,
+                       CodeEntry::kGarbageCollectorEntryName);
+}
+
+CodeEntry* CodeEntry::UnresolvedEntryCreateTrait::Create() {
+  return new CodeEntry(Logger::FUNCTION_TAG,
+                       CodeEntry::kUnresolvedFunctionName);
+}
 
 CodeEntry::~CodeEntry() {
   delete line_info_;
@@ -93,7 +129,7 @@
 
 
 void CodeEntry::SetBuiltinId(Builtins::Name id) {
-  bit_field_ = TagField::update(bit_field_, Logger::BUILTIN_TAG);
+  bit_field_ = TagField::update(bit_field_, CodeEventListener::BUILTIN_TAG);
   bit_field_ = BuiltinIdField::update(bit_field_, id);
 }
 
@@ -118,6 +154,19 @@
   return it != inline_locations_.end() ? &it->second : NULL;
 }
 
+void CodeEntry::AddDeoptInlinedFrames(
+    int deopt_id, std::vector<DeoptInlinedFrame>& inlined_frames) {
+  // It's better to use std::move to place the vector into the map,
+  // but it's not supported by the current stdlibc++ on MacOS.
+  deopt_inlined_frames_
+      .insert(std::make_pair(deopt_id, std::vector<DeoptInlinedFrame>()))
+      .first->second.swap(inlined_frames);
+}
+
+bool CodeEntry::HasDeoptInlinedFramesFor(int deopt_id) const {
+  return deopt_inlined_frames_.find(deopt_id) != deopt_inlined_frames_.end();
+}
+
 void CodeEntry::FillFunctionInfo(SharedFunctionInfo* shared) {
   if (!shared->script()->IsScript()) return;
   Script* script = Script::cast(shared->script());
@@ -131,30 +180,20 @@
 
   CpuProfileDeoptInfo info;
   info.deopt_reason = deopt_reason_;
-  if (inlined_function_infos_.empty()) {
+  DCHECK_NE(Deoptimizer::DeoptInfo::kNoDeoptId, deopt_id_);
+  if (deopt_inlined_frames_.find(deopt_id_) == deopt_inlined_frames_.end()) {
     info.stack.push_back(CpuProfileDeoptFrame(
         {script_id_, position_ + deopt_position_.position()}));
-    return info;
-  }
-  // Copy the only branch from the inlining tree where the deopt happened.
-  SourcePosition position = deopt_position_;
-  int inlining_id = InlinedFunctionInfo::kNoParentId;
-  for (size_t i = 0; i < inlined_function_infos_.size(); ++i) {
-    InlinedFunctionInfo& current_info = inlined_function_infos_.at(i);
-    if (std::binary_search(current_info.deopt_pc_offsets.begin(),
-                           current_info.deopt_pc_offsets.end(), pc_offset_)) {
-      inlining_id = static_cast<int>(i);
-      break;
+  } else {
+    size_t deopt_position = deopt_position_.raw();
+    // Copy stack of inlined frames where the deopt happened.
+    std::vector<DeoptInlinedFrame>& frames = deopt_inlined_frames_[deopt_id_];
+    for (DeoptInlinedFrame& inlined_frame : base::Reversed(frames)) {
+      info.stack.push_back(CpuProfileDeoptFrame(
+          {inlined_frame.script_id, deopt_position + inlined_frame.position}));
+      deopt_position = 0;  // Done with innermost frame.
     }
   }
-  while (inlining_id != InlinedFunctionInfo::kNoParentId) {
-    InlinedFunctionInfo& inlined_info = inlined_function_infos_.at(inlining_id);
-    info.stack.push_back(
-        CpuProfileDeoptFrame({inlined_info.script_id,
-                              inlined_info.start_position + position.raw()}));
-    position = inlined_info.inline_position;
-    inlining_id = inlined_info.parent_id;
-  }
   return info;
 }
 
@@ -166,14 +205,15 @@
 
 
 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) {
-  HashMap::Entry* map_entry = children_.Lookup(entry, CodeEntryHash(entry));
+  base::HashMap::Entry* map_entry =
+      children_.Lookup(entry, CodeEntryHash(entry));
   return map_entry != NULL ?
       reinterpret_cast<ProfileNode*>(map_entry->value) : NULL;
 }
 
 
 ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) {
-  HashMap::Entry* map_entry =
+  base::HashMap::Entry* map_entry =
       children_.LookupOrInsert(entry, CodeEntryHash(entry));
   ProfileNode* node = reinterpret_cast<ProfileNode*>(map_entry->value);
   if (node == NULL) {
@@ -190,7 +230,7 @@
   if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) return;
   // Increment a hit counter of a certain source line.
   // Add a new source line if not found.
-  HashMap::Entry* e =
+  base::HashMap::Entry* e =
       line_ticks_.LookupOrInsert(reinterpret_cast<void*>(src_line), src_line);
   DCHECK(e);
   e->value = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(e->value) + 1);
@@ -208,7 +248,7 @@
 
   v8::CpuProfileNode::LineTick* entry = entries;
 
-  for (HashMap::Entry* p = line_ticks_.Start(); p != NULL;
+  for (base::HashMap::Entry *p = line_ticks_.Start(); p != NULL;
        p = line_ticks_.Next(p), entry++) {
     entry->line =
         static_cast<unsigned int>(reinterpret_cast<uintptr_t>(p->key));
@@ -229,12 +269,13 @@
   base::OS::Print("\n");
   for (size_t i = 0; i < deopt_infos_.size(); ++i) {
     CpuProfileDeoptInfo& info = deopt_infos_[i];
-    base::OS::Print(
-        "%*s;;; deopted at script_id: %d position: %d with reason '%s'.\n",
-        indent + 10, "", info.stack[0].script_id, info.stack[0].position,
-        info.deopt_reason);
+    base::OS::Print("%*s;;; deopted at script_id: %d position: %" PRIuS
+                    " with reason '%s'.\n",
+                    indent + 10, "", info.stack[0].script_id,
+                    info.stack[0].position, info.deopt_reason);
     for (size_t index = 1; index < info.stack.size(); ++index) {
-      base::OS::Print("%*s;;;     Inline point: script_id %d position: %d.\n",
+      base::OS::Print("%*s;;;     Inline point: script_id %d position: %" PRIuS
+                      ".\n",
                       indent + 10, "", info.stack[index].script_id,
                       info.stack[index].position);
     }
@@ -245,8 +286,7 @@
     base::OS::Print("%*s bailed out due to '%s'\n", indent + 10, "",
                     bailout_reason);
   }
-  for (HashMap::Entry* p = children_.Start();
-       p != NULL;
+  for (base::HashMap::Entry* p = children_.Start(); p != NULL;
        p = children_.Next(p)) {
     reinterpret_cast<ProfileNode*>(p->value)->Print(indent + 2);
   }
@@ -264,16 +304,14 @@
   void AfterChildTraversed(ProfileNode*, ProfileNode*) { }
 };
 
-
 ProfileTree::ProfileTree(Isolate* isolate)
-    : root_entry_(Logger::FUNCTION_TAG, "(root)"),
+    : root_entry_(CodeEventListener::FUNCTION_TAG, "(root)"),
       next_node_id_(1),
       root_(new ProfileNode(this, &root_entry_)),
       isolate_(isolate),
       next_function_id_(1),
       function_ids_(ProfileNode::CodeEntriesMatch) {}
 
-
 ProfileTree::~ProfileTree() {
   DeleteNodesCallback cb;
   TraverseDepthFirst(&cb);
@@ -282,7 +320,7 @@
 
 unsigned ProfileTree::GetFunctionId(const ProfileNode* node) {
   CodeEntry* code_entry = node->entry();
-  HashMap::Entry* entry =
+  base::HashMap::Entry* entry =
       function_ids_.LookupOrInsert(code_entry, code_entry->GetHash());
   if (!entry->value) {
     entry->value = reinterpret_cast<void*>(next_function_id_++);
@@ -361,12 +399,13 @@
   }
 }
 
-
-CpuProfile::CpuProfile(Isolate* isolate, const char* title, bool record_samples)
+CpuProfile::CpuProfile(CpuProfiler* profiler, const char* title,
+                       bool record_samples)
     : title_(title),
       record_samples_(record_samples),
       start_time_(base::TimeTicks::HighResolutionNow()),
-      top_down_(isolate) {}
+      top_down_(profiler->isolate()),
+      profiler_(profiler) {}
 
 void CpuProfile::AddPath(base::TimeTicks timestamp,
                          const std::vector<CodeEntry*>& path, int src_line,
@@ -379,92 +418,60 @@
   }
 }
 
-
 void CpuProfile::CalculateTotalTicksAndSamplingRate() {
   end_time_ = base::TimeTicks::HighResolutionNow();
 }
 
-
 void CpuProfile::Print() {
   base::OS::Print("[Top down]:\n");
   top_down_.Print();
 }
 
-
-CodeMap::~CodeMap() {}
-
-
-const CodeMap::CodeTreeConfig::Key CodeMap::CodeTreeConfig::kNoKey = NULL;
-
-
 void CodeMap::AddCode(Address addr, CodeEntry* entry, unsigned size) {
   DeleteAllCoveredCode(addr, addr + size);
-  CodeTree::Locator locator;
-  tree_.Insert(addr, &locator);
-  locator.set_value(CodeEntryInfo(entry, size));
+  code_map_.insert({addr, CodeEntryInfo(entry, size)});
 }
 
-
 void CodeMap::DeleteAllCoveredCode(Address start, Address end) {
-  List<Address> to_delete;
-  Address addr = end - 1;
-  while (addr >= start) {
-    CodeTree::Locator locator;
-    if (!tree_.FindGreatestLessThan(addr, &locator)) break;
-    Address start2 = locator.key(), end2 = start2 + locator.value().size;
-    if (start2 < end && start < end2) to_delete.Add(start2);
-    addr = start2 - 1;
+  auto left = code_map_.upper_bound(start);
+  if (left != code_map_.begin()) {
+    --left;
+    if (left->first + left->second.size <= start) ++left;
   }
-  for (int i = 0; i < to_delete.length(); ++i) tree_.Remove(to_delete[i]);
+  auto right = left;
+  while (right != code_map_.end() && right->first < end) ++right;
+  code_map_.erase(left, right);
 }
 
-
 CodeEntry* CodeMap::FindEntry(Address addr) {
-  CodeTree::Locator locator;
-  if (tree_.FindGreatestLessThan(addr, &locator)) {
-    // locator.key() <= addr. Need to check that addr is within entry.
-    const CodeEntryInfo& entry = locator.value();
-    if (addr < (locator.key() + entry.size)) {
-      return entry.entry;
-    }
-  }
-  return NULL;
+  auto it = code_map_.upper_bound(addr);
+  if (it == code_map_.begin()) return nullptr;
+  --it;
+  Address end_address = it->first + it->second.size;
+  return addr < end_address ? it->second.entry : nullptr;
 }
 
-
 void CodeMap::MoveCode(Address from, Address to) {
   if (from == to) return;
-  CodeTree::Locator locator;
-  if (!tree_.Find(from, &locator)) return;
-  CodeEntryInfo entry = locator.value();
-  tree_.Remove(from);
-  AddCode(to, entry.entry, entry.size);
+  auto it = code_map_.find(from);
+  if (it == code_map_.end()) return;
+  CodeEntryInfo info = it->second;
+  code_map_.erase(it);
+  AddCode(to, info.entry, info.size);
 }
 
-
-void CodeMap::CodeTreePrinter::Call(
-    const Address& key, const CodeMap::CodeEntryInfo& value) {
-  base::OS::Print("%p %5d %s\n", key, value.size, value.entry->name());
-}
-
-
 void CodeMap::Print() {
-  CodeTreePrinter printer;
-  tree_.ForEach(&printer);
+  for (auto it = code_map_.begin(); it != code_map_.end(); ++it) {
+    base::OS::Print("%p %5d %s\n", static_cast<void*>(it->first),
+                    it->second.size, it->second.entry->name());
+  }
 }
 
-
-CpuProfilesCollection::CpuProfilesCollection(Heap* heap)
-    : function_and_resource_names_(heap),
-      isolate_(heap->isolate()),
+CpuProfilesCollection::CpuProfilesCollection(Isolate* isolate)
+    : resource_names_(isolate->heap()),
+      profiler_(nullptr),
       current_profiles_semaphore_(1) {}
 
-
-static void DeleteCodeEntry(CodeEntry** entry_ptr) {
-  delete *entry_ptr;
-}
-
-
 static void DeleteCpuProfile(CpuProfile** profile_ptr) {
   delete *profile_ptr;
 }
@@ -473,7 +480,6 @@
 CpuProfilesCollection::~CpuProfilesCollection() {
   finished_profiles_.Iterate(DeleteCpuProfile);
   current_profiles_.Iterate(DeleteCpuProfile);
-  code_entries_.Iterate(DeleteCodeEntry);
 }
 
 
@@ -492,7 +498,7 @@
       return true;
     }
   }
-  current_profiles_.Add(new CpuProfile(isolate_, title, record_samples));
+  current_profiles_.Add(new CpuProfile(profiler_, title, record_samples));
   current_profiles_semaphore_.Signal();
   return true;
 }
@@ -550,43 +556,8 @@
   current_profiles_semaphore_.Signal();
 }
 
-
-CodeEntry* CpuProfilesCollection::NewCodeEntry(
-    Logger::LogEventsAndTags tag, const char* name, const char* name_prefix,
-    const char* resource_name, int line_number, int column_number,
-    JITLineInfoTable* line_info, Address instruction_start) {
-  CodeEntry* code_entry =
-      new CodeEntry(tag, name, name_prefix, resource_name, line_number,
-                    column_number, line_info, instruction_start);
-  code_entries_.Add(code_entry);
-  return code_entry;
-}
-
-
-const char* const ProfileGenerator::kProgramEntryName =
-    "(program)";
-const char* const ProfileGenerator::kIdleEntryName =
-    "(idle)";
-const char* const ProfileGenerator::kGarbageCollectorEntryName =
-    "(garbage collector)";
-const char* const ProfileGenerator::kUnresolvedFunctionName =
-    "(unresolved function)";
-
-
 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
-    : profiles_(profiles),
-      program_entry_(
-          profiles->NewCodeEntry(Logger::FUNCTION_TAG, kProgramEntryName)),
-      idle_entry_(
-          profiles->NewCodeEntry(Logger::FUNCTION_TAG, kIdleEntryName)),
-      gc_entry_(
-          profiles->NewCodeEntry(Logger::BUILTIN_TAG,
-                                 kGarbageCollectorEntryName)),
-      unresolved_entry_(
-          profiles->NewCodeEntry(Logger::FUNCTION_TAG,
-                                 kUnresolvedFunctionName)) {
-}
-
+    : profiles_(profiles) {}
 
 void ProfileGenerator::RecordTickSample(const TickSample& sample) {
   std::vector<CodeEntry*> entries;
@@ -602,9 +573,8 @@
   int src_line = v8::CpuProfileNode::kNoLineNumberInfo;
   bool src_line_not_found = true;
 
-  if (sample.pc != NULL) {
-    if (sample.has_external_callback && sample.state == EXTERNAL &&
-        sample.top_frame_type == StackFrame::EXIT) {
+  if (sample.pc != nullptr) {
+    if (sample.has_external_callback && sample.state == EXTERNAL) {
       // Don't use PC when in external callback code, as it can point
       // inside callback's code, and we will erroneously report
       // that a callback calls itself.
@@ -614,9 +584,7 @@
       // If there is no pc_entry we're likely in native code.
       // Find out, if top of stack was pointing inside a JS function
       // meaning that we have encountered a frameless invocation.
-      if (!pc_entry && (sample.top_frame_type == StackFrame::JAVA_SCRIPT ||
-                        sample.top_frame_type == StackFrame::INTERPRETED ||
-                        sample.top_frame_type == StackFrame::OPTIMIZED)) {
+      if (!pc_entry && !sample.has_external_callback) {
         pc_entry = code_map_.FindEntry(sample.tos);
       }
       // If pc is in the function code before it set up stack frame or after the
@@ -641,8 +609,8 @@
           // In the latter case we know the caller for sure but in the
           // former case we don't so we simply replace the frame with
           // 'unresolved' entry.
-          if (sample.top_frame_type == StackFrame::JAVA_SCRIPT) {
-            entries.push_back(unresolved_entry_);
+          if (!sample.has_external_callback) {
+            entries.push_back(CodeEntry::unresolved_entry());
           }
         }
       }
@@ -699,7 +667,7 @@
 CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) {
   switch (tag) {
     case GC:
-      return gc_entry_;
+      return CodeEntry::gc_entry();
     case JS:
     case COMPILER:
     // DOM events handlers are reported as OTHER / EXTERNAL entries.
@@ -707,9 +675,9 @@
     // one bucket.
     case OTHER:
     case EXTERNAL:
-      return program_entry_;
+      return CodeEntry::program_entry();
     case IDLE:
-      return idle_entry_;
+      return CodeEntry::idle_entry();
     default: return NULL;
   }
 }
diff --git a/src/profiler/profile-generator.h b/src/profiler/profile-generator.h
index 194b490..fdd87f3 100644
--- a/src/profiler/profile-generator.h
+++ b/src/profiler/profile-generator.h
@@ -8,8 +8,8 @@
 #include <map>
 #include "include/v8-profiler.h"
 #include "src/allocation.h"
+#include "src/base/hashmap.h"
 #include "src/compiler.h"
-#include "src/hashmap.h"
 #include "src/profiler/strings-storage.h"
 
 namespace v8 {
@@ -38,7 +38,7 @@
 class CodeEntry {
  public:
   // CodeEntry doesn't own name strings, just references them.
-  inline CodeEntry(Logger::LogEventsAndTags tag, const char* name,
+  inline CodeEntry(CodeEventListener::LogEventsAndTags tag, const char* name,
                    const char* name_prefix = CodeEntry::kEmptyNamePrefix,
                    const char* resource_name = CodeEntry::kEmptyResourceName,
                    int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
@@ -47,6 +47,13 @@
                    Address instruction_start = NULL);
   ~CodeEntry();
 
+  // Container describing inlined frames at eager deopt points. Is eventually
+  // being translated into v8::CpuProfileDeoptFrame by the profiler.
+  struct DeoptInlinedFrame {
+    int position;
+    int script_id;
+  };
+
   const char* name_prefix() const { return name_prefix_; }
   bool has_name_prefix() const { return name_prefix_[0] != '\0'; }
   const char* name() const { return name_; }
@@ -64,11 +71,11 @@
   const char* bailout_reason() const { return bailout_reason_; }
 
   void set_deopt_info(const char* deopt_reason, SourcePosition position,
-                      size_t pc_offset) {
+                      int deopt_id) {
     DCHECK(deopt_position_.IsUnknown());
     deopt_reason_ = deopt_reason;
     deopt_position_ = position;
-    pc_offset_ = pc_offset;
+    deopt_id_ = deopt_id;
   }
   CpuProfileDeoptInfo GetDeoptInfo();
   const char* deopt_reason() const { return deopt_reason_; }
@@ -81,14 +88,6 @@
 
   void FillFunctionInfo(SharedFunctionInfo* shared);
 
-  void set_inlined_function_infos(
-      const std::vector<InlinedFunctionInfo>& infos) {
-    inlined_function_infos_ = infos;
-  }
-  const std::vector<InlinedFunctionInfo> inlined_function_infos() {
-    return inlined_function_infos_;
-  }
-
   void SetBuiltinId(Builtins::Name id);
   Builtins::Name builtin_id() const {
     return BuiltinIdField::decode(bit_field_);
@@ -102,17 +101,60 @@
   void AddInlineStack(int pc_offset, std::vector<CodeEntry*>& inline_stack);
   const std::vector<CodeEntry*>* GetInlineStack(int pc_offset) const;
 
+  void AddDeoptInlinedFrames(int deopt_id, std::vector<DeoptInlinedFrame>&);
+  bool HasDeoptInlinedFramesFor(int deopt_id) const;
+
   Address instruction_start() const { return instruction_start_; }
-  Logger::LogEventsAndTags tag() const { return TagField::decode(bit_field_); }
+  CodeEventListener::LogEventsAndTags tag() const {
+    return TagField::decode(bit_field_);
+  }
 
   static const char* const kEmptyNamePrefix;
   static const char* const kEmptyResourceName;
   static const char* const kEmptyBailoutReason;
   static const char* const kNoDeoptReason;
 
+  static const char* const kProgramEntryName;
+  static const char* const kIdleEntryName;
+  static const char* const kGarbageCollectorEntryName;
+  // Used to represent frames for which we have no reliable way to
+  // detect function.
+  static const char* const kUnresolvedFunctionName;
+
+  V8_INLINE static CodeEntry* program_entry() {
+    return kProgramEntry.Pointer();
+  }
+  V8_INLINE static CodeEntry* idle_entry() { return kIdleEntry.Pointer(); }
+  V8_INLINE static CodeEntry* gc_entry() { return kGCEntry.Pointer(); }
+  V8_INLINE static CodeEntry* unresolved_entry() {
+    return kUnresolvedEntry.Pointer();
+  }
+
  private:
+  struct ProgramEntryCreateTrait {
+    static CodeEntry* Create();
+  };
+  struct IdleEntryCreateTrait {
+    static CodeEntry* Create();
+  };
+  struct GCEntryCreateTrait {
+    static CodeEntry* Create();
+  };
+  struct UnresolvedEntryCreateTrait {
+    static CodeEntry* Create();
+  };
+
+  static base::LazyDynamicInstance<CodeEntry, ProgramEntryCreateTrait>::type
+      kProgramEntry;
+  static base::LazyDynamicInstance<CodeEntry, IdleEntryCreateTrait>::type
+      kIdleEntry;
+  static base::LazyDynamicInstance<CodeEntry, GCEntryCreateTrait>::type
+      kGCEntry;
+  static base::LazyDynamicInstance<CodeEntry, UnresolvedEntryCreateTrait>::type
+      kUnresolvedEntry;
+
   class TagField : public BitField<Logger::LogEventsAndTags, 0, 8> {};
-  class BuiltinIdField : public BitField<Builtins::Name, 8, 8> {};
+  class BuiltinIdField : public BitField<Builtins::Name, 8, 24> {};
 
   uint32_t bit_field_;
   const char* name_prefix_;
@@ -125,13 +167,12 @@
   const char* bailout_reason_;
   const char* deopt_reason_;
   SourcePosition deopt_position_;
-  size_t pc_offset_;
+  int deopt_id_;
   JITLineInfoTable* line_info_;
   Address instruction_start_;
   // Should be an unordered_map, but it doesn't currently work on Win & MacOS.
   std::map<int, std::vector<CodeEntry*>> inline_locations_;
-
-  std::vector<InlinedFunctionInfo> inlined_function_infos_;
+  std::map<int, std::vector<DeoptInlinedFrame>> deopt_inlined_frames_;
 
   DISALLOW_COPY_AND_ASSIGN(CodeEntry);
 };
@@ -179,10 +220,10 @@
   CodeEntry* entry_;
   unsigned self_ticks_;
   // Mapping from CodeEntry* to ProfileNode*
-  HashMap children_;
+  base::HashMap children_;
   List<ProfileNode*> children_list_;
   unsigned id_;
-  HashMap line_ticks_;
+  base::HashMap line_ticks_;
 
   std::vector<CpuProfileDeoptInfo> deopt_infos_;
 
@@ -219,7 +260,7 @@
   Isolate* isolate_;
 
   unsigned next_function_id_;
-  HashMap function_ids_;
+  base::HashMap function_ids_;
 
   DISALLOW_COPY_AND_ASSIGN(ProfileTree);
 };
@@ -227,7 +268,7 @@
 
 class CpuProfile {
  public:
-  CpuProfile(Isolate* isolate, const char* title, bool record_samples);
+  CpuProfile(CpuProfiler* profiler, const char* title, bool record_samples);
 
   // Add pc -> ... -> main() call path to the profile.
   void AddPath(base::TimeTicks timestamp, const std::vector<CodeEntry*>& path,
@@ -245,6 +286,7 @@
 
   base::TimeTicks start_time() const { return start_time_; }
   base::TimeTicks end_time() const { return end_time_; }
+  CpuProfiler* cpu_profiler() const { return profiler_; }
 
   void UpdateTicksScale();
 
@@ -258,20 +300,18 @@
   List<ProfileNode*> samples_;
   List<base::TimeTicks> timestamps_;
   ProfileTree top_down_;
+  CpuProfiler* const profiler_;
 
   DISALLOW_COPY_AND_ASSIGN(CpuProfile);
 };
 
-
 class CodeMap {
  public:
   CodeMap() {}
-  ~CodeMap();
+
   void AddCode(Address addr, CodeEntry* entry, unsigned size);
   void MoveCode(Address from, Address to);
   CodeEntry* FindEntry(Address addr);
-  int GetSharedId(Address addr);
-
   void Print();
 
  private:
@@ -282,61 +322,26 @@
     unsigned size;
   };
 
-  struct CodeTreeConfig {
-    typedef Address Key;
-    typedef CodeEntryInfo Value;
-    static const Key kNoKey;
-    static const Value NoValue() { return CodeEntryInfo(NULL, 0); }
-    static int Compare(const Key& a, const Key& b) {
-      return a < b ? -1 : (a > b ? 1 : 0);
-    }
-  };
-  typedef SplayTree<CodeTreeConfig> CodeTree;
-
-  class CodeTreePrinter {
-   public:
-    void Call(const Address& key, const CodeEntryInfo& value);
-  };
-
   void DeleteAllCoveredCode(Address start, Address end);
 
-  CodeTree tree_;
+  std::map<Address, CodeEntryInfo> code_map_;
 
   DISALLOW_COPY_AND_ASSIGN(CodeMap);
 };
 
-
 class CpuProfilesCollection {
  public:
-  explicit CpuProfilesCollection(Heap* heap);
+  explicit CpuProfilesCollection(Isolate* isolate);
   ~CpuProfilesCollection();
 
+  void set_cpu_profiler(CpuProfiler* profiler) { profiler_ = profiler; }
   bool StartProfiling(const char* title, bool record_samples);
   CpuProfile* StopProfiling(const char* title);
   List<CpuProfile*>* profiles() { return &finished_profiles_; }
-  const char* GetName(Name* name) {
-    return function_and_resource_names_.GetName(name);
-  }
-  const char* GetName(int args_count) {
-    return function_and_resource_names_.GetName(args_count);
-  }
-  const char* GetFunctionName(Name* name) {
-    return function_and_resource_names_.GetFunctionName(name);
-  }
-  const char* GetFunctionName(const char* name) {
-    return function_and_resource_names_.GetFunctionName(name);
-  }
+  const char* GetName(Name* name) { return resource_names_.GetName(name); }
   bool IsLastProfile(const char* title);
   void RemoveProfile(CpuProfile* profile);
 
-  CodeEntry* NewCodeEntry(
-      Logger::LogEventsAndTags tag, const char* name,
-      const char* name_prefix = CodeEntry::kEmptyNamePrefix,
-      const char* resource_name = CodeEntry::kEmptyResourceName,
-      int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
-      int column_number = v8::CpuProfileNode::kNoColumnNumberInfo,
-      JITLineInfoTable* line_info = NULL, Address instruction_start = NULL);
-
   // Called from profile generator thread.
   void AddPathToCurrentProfiles(base::TimeTicks timestamp,
                                 const std::vector<CodeEntry*>& path,
@@ -346,11 +351,9 @@
   static const int kMaxSimultaneousProfiles = 100;
 
  private:
-  StringsStorage function_and_resource_names_;
-  List<CodeEntry*> code_entries_;
+  StringsStorage resource_names_;
   List<CpuProfile*> finished_profiles_;
-
-  Isolate* isolate_;
+  CpuProfiler* profiler_;
 
   // Accessed by VM thread and profile generator thread.
   List<CpuProfile*> current_profiles_;
@@ -368,22 +371,11 @@
 
   CodeMap* code_map() { return &code_map_; }
 
-  static const char* const kProgramEntryName;
-  static const char* const kIdleEntryName;
-  static const char* const kGarbageCollectorEntryName;
-  // Used to represent frames for which we have no reliable way to
-  // detect function.
-  static const char* const kUnresolvedFunctionName;
-
  private:
   CodeEntry* EntryForVMState(StateTag tag);
 
   CpuProfilesCollection* profiles_;
   CodeMap code_map_;
-  CodeEntry* program_entry_;
-  CodeEntry* idle_entry_;
-  CodeEntry* gc_entry_;
-  CodeEntry* unresolved_entry_;
 
   DISALLOW_COPY_AND_ASSIGN(ProfileGenerator);
 };
diff --git a/src/profiler/profiler-listener.cc b/src/profiler/profiler-listener.cc
new file mode 100644
index 0000000..2b353e7
--- /dev/null
+++ b/src/profiler/profiler-listener.cc
@@ -0,0 +1,339 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/profiler/profiler-listener.h"
+
+#include "src/deoptimizer.h"
+#include "src/interpreter/source-position-table.h"
+#include "src/profiler/cpu-profiler.h"
+#include "src/profiler/profile-generator-inl.h"
+
+namespace v8 {
+namespace internal {
+
+ProfilerListener::ProfilerListener(Isolate* isolate)
+    : function_and_resource_names_(isolate->heap()) {}
+
+ProfilerListener::~ProfilerListener() {
+  for (auto code_entry : code_entries_) {
+    delete code_entry;
+  }
+}
+
+void ProfilerListener::CallbackEvent(Name* name, Address entry_point) {
+  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+  rec->start = entry_point;
+  rec->entry = NewCodeEntry(CodeEventListener::CALLBACK_TAG, GetName(name));
+  rec->size = 1;
+  DispatchCodeEvent(evt_rec);
+}
+
+void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                                       AbstractCode* code, const char* name) {
+  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+  rec->start = code->address();
+  rec->entry = NewCodeEntry(
+      tag, GetFunctionName(name), CodeEntry::kEmptyNamePrefix,
+      CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
+      CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
+  RecordInliningInfo(rec->entry, code);
+  rec->size = code->ExecutableSize();
+  DispatchCodeEvent(evt_rec);
+}
+
+void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                                       AbstractCode* code, Name* name) {
+  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+  rec->start = code->address();
+  rec->entry = NewCodeEntry(
+      tag, GetFunctionName(name), CodeEntry::kEmptyNamePrefix,
+      CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
+      CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
+  RecordInliningInfo(rec->entry, code);
+  rec->size = code->ExecutableSize();
+  DispatchCodeEvent(evt_rec);
+}
+
+void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                                       AbstractCode* code,
+                                       SharedFunctionInfo* shared,
+                                       Name* script_name) {
+  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+  rec->start = code->address();
+  rec->entry = NewCodeEntry(
+      tag, GetFunctionName(shared->DebugName()), CodeEntry::kEmptyNamePrefix,
+      GetName(InferScriptName(script_name, shared)),
+      CpuProfileNode::kNoLineNumberInfo, CpuProfileNode::kNoColumnNumberInfo,
+      NULL, code->instruction_start());
+  RecordInliningInfo(rec->entry, code);
+  rec->entry->FillFunctionInfo(shared);
+  rec->size = code->ExecutableSize();
+  DispatchCodeEvent(evt_rec);
+}
+
+void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                                       AbstractCode* abstract_code,
+                                       SharedFunctionInfo* shared,
+                                       Name* script_name, int line,
+                                       int column) {
+  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+  rec->start = abstract_code->address();
+  Script* script = Script::cast(shared->script());
+  JITLineInfoTable* line_table = NULL;
+  if (script) {
+    if (abstract_code->IsCode()) {
+      Code* code = abstract_code->GetCode();
+      int start_position = shared->start_position();
+      int end_position = shared->end_position();
+      line_table = new JITLineInfoTable();
+      for (RelocIterator it(code); !it.done(); it.next()) {
+        RelocInfo* reloc_info = it.rinfo();
+        if (!RelocInfo::IsPosition(reloc_info->rmode())) continue;
+        int position = static_cast<int>(reloc_info->data());
+        // TODO(alph): in case of inlining the position may correspond
+        // to an inlined function source code. Do not collect positions
+        // that fall beyond the function source code. There's however a
+        // chance the inlined function has similar positions but in another
+        // script. So the proper fix is to store script_id in some form
+        // along with the inlined function positions.
+        if (position < start_position || position >= end_position) continue;
+        int pc_offset = static_cast<int>(reloc_info->pc() - code->address());
+        int line_number = script->GetLineNumber(position) + 1;
+        line_table->SetPosition(pc_offset, line_number);
+      }
+    } else {
+      BytecodeArray* bytecode = abstract_code->GetBytecodeArray();
+      line_table = new JITLineInfoTable();
+      interpreter::SourcePositionTableIterator it(
+          bytecode->source_position_table());
+      for (; !it.done(); it.Advance()) {
+        int line_number = script->GetLineNumber(it.source_position()) + 1;
+        int pc_offset = it.bytecode_offset() + BytecodeArray::kHeaderSize;
+        line_table->SetPosition(pc_offset, line_number);
+      }
+    }
+  }
+  rec->entry = NewCodeEntry(
+      tag, GetFunctionName(shared->DebugName()), CodeEntry::kEmptyNamePrefix,
+      GetName(InferScriptName(script_name, shared)), line, column, line_table,
+      abstract_code->instruction_start());
+  RecordInliningInfo(rec->entry, abstract_code);
+  RecordDeoptInlinedFrames(rec->entry, abstract_code);
+  rec->entry->FillFunctionInfo(shared);
+  rec->size = abstract_code->ExecutableSize();
+  DispatchCodeEvent(evt_rec);
+}
+
+void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                                       AbstractCode* code, int args_count) {
+  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+  rec->start = code->address();
+  rec->entry = NewCodeEntry(
+      tag, GetName(args_count), "args_count: ", CodeEntry::kEmptyResourceName,
+      CpuProfileNode::kNoLineNumberInfo, CpuProfileNode::kNoColumnNumberInfo,
+      NULL, code->instruction_start());
+  RecordInliningInfo(rec->entry, code);
+  rec->size = code->ExecutableSize();
+  DispatchCodeEvent(evt_rec);
+}
+
+void ProfilerListener::CodeMoveEvent(AbstractCode* from, Address to) {
+  CodeEventsContainer evt_rec(CodeEventRecord::CODE_MOVE);
+  CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
+  rec->from = from->address();
+  rec->to = to;
+  DispatchCodeEvent(evt_rec);
+}
+
+void ProfilerListener::CodeDisableOptEvent(AbstractCode* code,
+                                           SharedFunctionInfo* shared) {
+  CodeEventsContainer evt_rec(CodeEventRecord::CODE_DISABLE_OPT);
+  CodeDisableOptEventRecord* rec = &evt_rec.CodeDisableOptEventRecord_;
+  rec->start = code->address();
+  rec->bailout_reason = GetBailoutReason(shared->disable_optimization_reason());
+  DispatchCodeEvent(evt_rec);
+}
+
+void ProfilerListener::CodeDeoptEvent(Code* code, Address pc,
+                                      int fp_to_sp_delta) {
+  CodeEventsContainer evt_rec(CodeEventRecord::CODE_DEOPT);
+  CodeDeoptEventRecord* rec = &evt_rec.CodeDeoptEventRecord_;
+  Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(code, pc);
+  rec->start = code->address();
+  rec->deopt_reason = Deoptimizer::GetDeoptReason(info.deopt_reason);
+  rec->position = info.position;
+  rec->deopt_id = info.deopt_id;
+  rec->pc = reinterpret_cast<void*>(pc);
+  rec->fp_to_sp_delta = fp_to_sp_delta;
+  DispatchCodeEvent(evt_rec);
+}
+
+void ProfilerListener::GetterCallbackEvent(Name* name, Address entry_point) {
+  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+  rec->start = entry_point;
+  rec->entry =
+      NewCodeEntry(CodeEventListener::CALLBACK_TAG, GetName(name), "get ");
+  rec->size = 1;
+  DispatchCodeEvent(evt_rec);
+}
+
+void ProfilerListener::RegExpCodeCreateEvent(AbstractCode* code,
+                                             String* source) {
+  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+  rec->start = code->address();
+  rec->entry = NewCodeEntry(
+      CodeEventListener::REG_EXP_TAG, GetName(source), "RegExp: ",
+      CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
+      CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
+  rec->size = code->ExecutableSize();
+  DispatchCodeEvent(evt_rec);
+}
+
+void ProfilerListener::SetterCallbackEvent(Name* name, Address entry_point) {
+  CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+  rec->start = entry_point;
+  rec->entry =
+      NewCodeEntry(CodeEventListener::CALLBACK_TAG, GetName(name), "set ");
+  rec->size = 1;
+  DispatchCodeEvent(evt_rec);
+}
+
+Name* ProfilerListener::InferScriptName(Name* name, SharedFunctionInfo* info) {
+  if (name->IsString() && String::cast(name)->length()) return name;
+  if (!info->script()->IsScript()) return name;
+  Object* source_url = Script::cast(info->script())->source_url();
+  return source_url->IsName() ? Name::cast(source_url) : name;
+}
+
+void ProfilerListener::RecordInliningInfo(CodeEntry* entry,
+                                          AbstractCode* abstract_code) {
+  if (!abstract_code->IsCode()) return;
+  Code* code = abstract_code->GetCode();
+  if (code->kind() != Code::OPTIMIZED_FUNCTION) return;
+  DeoptimizationInputData* deopt_input_data =
+      DeoptimizationInputData::cast(code->deoptimization_data());
+  int deopt_count = deopt_input_data->DeoptCount();
+  for (int i = 0; i < deopt_count; i++) {
+    int pc_offset = deopt_input_data->Pc(i)->value();
+    if (pc_offset == -1) continue;
+    int translation_index = deopt_input_data->TranslationIndex(i)->value();
+    TranslationIterator it(deopt_input_data->TranslationByteArray(),
+                           translation_index);
+    Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
+    DCHECK_EQ(Translation::BEGIN, opcode);
+    it.Skip(Translation::NumberOfOperandsFor(opcode));
+    int depth = 0;
+    std::vector<CodeEntry*> inline_stack;
+    while (it.HasNext() &&
+           Translation::BEGIN !=
+               (opcode = static_cast<Translation::Opcode>(it.Next()))) {
+      if (opcode != Translation::JS_FRAME &&
+          opcode != Translation::INTERPRETED_FRAME) {
+        it.Skip(Translation::NumberOfOperandsFor(opcode));
+        continue;
+      }
+      it.Next();  // Skip ast_id
+      int shared_info_id = it.Next();
+      it.Next();  // Skip height
+      SharedFunctionInfo* shared_info = SharedFunctionInfo::cast(
+          deopt_input_data->LiteralArray()->get(shared_info_id));
+      if (!depth++) continue;  // Skip the current function itself.
+      CodeEntry* inline_entry = new CodeEntry(
+          entry->tag(), GetFunctionName(shared_info->DebugName()),
+          CodeEntry::kEmptyNamePrefix, entry->resource_name(),
+          CpuProfileNode::kNoLineNumberInfo,
+          CpuProfileNode::kNoColumnNumberInfo, NULL, code->instruction_start());
+      inline_entry->FillFunctionInfo(shared_info);
+      inline_stack.push_back(inline_entry);
+    }
+    if (!inline_stack.empty()) {
+      entry->AddInlineStack(pc_offset, inline_stack);
+      DCHECK(inline_stack.empty());
+    }
+  }
+}
+
+void ProfilerListener::RecordDeoptInlinedFrames(CodeEntry* entry,
+                                                AbstractCode* abstract_code) {
+  if (abstract_code->kind() != AbstractCode::OPTIMIZED_FUNCTION) return;
+  Code* code = abstract_code->GetCode();
+  DeoptimizationInputData* deopt_input_data =
+      DeoptimizationInputData::cast(code->deoptimization_data());
+  int const mask = RelocInfo::ModeMask(RelocInfo::DEOPT_ID);
+  for (RelocIterator rit(code, mask); !rit.done(); rit.next()) {
+    RelocInfo* reloc_info = rit.rinfo();
+    DCHECK(RelocInfo::IsDeoptId(reloc_info->rmode()));
+    int deopt_id = static_cast<int>(reloc_info->data());
+    int translation_index =
+        deopt_input_data->TranslationIndex(deopt_id)->value();
+    TranslationIterator it(deopt_input_data->TranslationByteArray(),
+                           translation_index);
+    Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
+    DCHECK_EQ(Translation::BEGIN, opcode);
+    it.Skip(Translation::NumberOfOperandsFor(opcode));
+    std::vector<CodeEntry::DeoptInlinedFrame> inlined_frames;
+    while (it.HasNext() &&
+           Translation::BEGIN !=
+               (opcode = static_cast<Translation::Opcode>(it.Next()))) {
+      if (opcode != Translation::JS_FRAME &&
+          opcode != Translation::INTERPRETED_FRAME) {
+        it.Skip(Translation::NumberOfOperandsFor(opcode));
+        continue;
+      }
+      BailoutId ast_id = BailoutId(it.Next());
+      int shared_info_id = it.Next();
+      it.Next();  // Skip height
+      SharedFunctionInfo* shared = SharedFunctionInfo::cast(
+          deopt_input_data->LiteralArray()->get(shared_info_id));
+      int source_position = Deoptimizer::ComputeSourcePosition(shared, ast_id);
+      int script_id = v8::UnboundScript::kNoScriptId;
+      if (shared->script()->IsScript()) {
+        Script* script = Script::cast(shared->script());
+        script_id = script->id();
+      }
+      CodeEntry::DeoptInlinedFrame frame = {source_position, script_id};
+      inlined_frames.push_back(frame);
+    }
+    if (!inlined_frames.empty() && !entry->HasDeoptInlinedFramesFor(deopt_id)) {
+      entry->AddDeoptInlinedFrames(deopt_id, inlined_frames);
+      DCHECK(inlined_frames.empty());
+    }
+  }
+}
+
+CodeEntry* ProfilerListener::NewCodeEntry(
+    CodeEventListener::LogEventsAndTags tag, const char* name,
+    const char* name_prefix, const char* resource_name, int line_number,
+    int column_number, JITLineInfoTable* line_info, Address instruction_start) {
+  CodeEntry* code_entry =
+      new CodeEntry(tag, name, name_prefix, resource_name, line_number,
+                    column_number, line_info, instruction_start);
+  code_entries_.push_back(code_entry);
+  return code_entry;
+}
+
+void ProfilerListener::AddObserver(CodeEventObserver* observer) {
+  if (std::find(observers_.begin(), observers_.end(), observer) !=
+      observers_.end())
+    return;
+  observers_.push_back(observer);
+}
+
+void ProfilerListener::RemoveObserver(CodeEventObserver* observer) {
+  auto it = std::find(observers_.begin(), observers_.end(), observer);
+  if (it == observers_.end()) return;
+  observers_.erase(it);
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/profiler/profiler-listener.h b/src/profiler/profiler-listener.h
new file mode 100644
index 0000000..7e24cea
--- /dev/null
+++ b/src/profiler/profiler-listener.h
@@ -0,0 +1,97 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_PROFILER_PROFILER_LISTENER_H_
+#define V8_PROFILER_PROFILER_LISTENER_H_
+
+#include <vector>
+
+#include "src/code-events.h"
+#include "src/profiler/profile-generator.h"
+
+namespace v8 {
+namespace internal {
+
+class CodeEventsContainer;
+
+class CodeEventObserver {
+ public:
+  virtual void CodeEventHandler(const CodeEventsContainer& evt_rec) = 0;
+  virtual ~CodeEventObserver() {}
+};
+
+class ProfilerListener : public CodeEventListener {
+ public:
+  explicit ProfilerListener(Isolate* isolate);
+  ~ProfilerListener() override;
+
+  void CallbackEvent(Name* name, Address entry_point) override;
+  void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                       AbstractCode* code, const char* comment) override;
+  void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                       AbstractCode* code, Name* name) override;
+  void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                       AbstractCode* code, SharedFunctionInfo* shared,
+                       Name* script_name) override;
+  void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                       AbstractCode* code, SharedFunctionInfo* shared,
+                       Name* script_name, int line, int column) override;
+  void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
+                       AbstractCode* code, int args_count) override;
+  void CodeMovingGCEvent() override {}
+  void CodeMoveEvent(AbstractCode* from, Address to) override;
+  void CodeDisableOptEvent(AbstractCode* code,
+                           SharedFunctionInfo* shared) override;
+  void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta) override;
+  void GetterCallbackEvent(Name* name, Address entry_point) override;
+  void RegExpCodeCreateEvent(AbstractCode* code, String* source) override;
+  void SetterCallbackEvent(Name* name, Address entry_point) override;
+  void SharedFunctionInfoMoveEvent(Address from, Address to) override {}
+
+  CodeEntry* NewCodeEntry(
+      CodeEventListener::LogEventsAndTags tag, const char* name,
+      const char* name_prefix = CodeEntry::kEmptyNamePrefix,
+      const char* resource_name = CodeEntry::kEmptyResourceName,
+      int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
+      int column_number = v8::CpuProfileNode::kNoColumnNumberInfo,
+      JITLineInfoTable* line_info = NULL, Address instruction_start = NULL);
+
+  void AddObserver(CodeEventObserver* observer);
+  void RemoveObserver(CodeEventObserver* observer);
+  V8_INLINE bool HasObservers() { return !observers_.empty(); }
+
+  const char* GetName(Name* name) {
+    return function_and_resource_names_.GetName(name);
+  }
+  const char* GetName(int args_count) {
+    return function_and_resource_names_.GetName(args_count);
+  }
+  const char* GetFunctionName(Name* name) {
+    return function_and_resource_names_.GetFunctionName(name);
+  }
+  const char* GetFunctionName(const char* name) {
+    return function_and_resource_names_.GetFunctionName(name);
+  }
+
+ private:
+  void RecordInliningInfo(CodeEntry* entry, AbstractCode* abstract_code);
+  void RecordDeoptInlinedFrames(CodeEntry* entry, AbstractCode* abstract_code);
+  Name* InferScriptName(Name* name, SharedFunctionInfo* info);
+  V8_INLINE void DispatchCodeEvent(const CodeEventsContainer& evt_rec) {
+    for (auto observer : observers_) {
+      observer->CodeEventHandler(evt_rec);
+    }
+  }
+
+  StringsStorage function_and_resource_names_;
+  std::vector<CodeEntry*> code_entries_;
+  std::vector<CodeEventObserver*> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProfilerListener);
+};
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_PROFILER_PROFILER_LISTENER_H_
diff --git a/src/profiler/sampler.cc b/src/profiler/sampler.cc
deleted file mode 100644
index a340424..0000000
--- a/src/profiler/sampler.cc
+++ /dev/null
@@ -1,898 +0,0 @@
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/profiler/sampler.h"
-
-#if V8_OS_POSIX && !V8_OS_CYGWIN
-
-#define USE_SIGNALS
-
-#include <errno.h>
-#include <pthread.h>
-#include <signal.h>
-#include <sys/time.h>
-
-#if !V8_OS_QNX && !V8_OS_NACL && !V8_OS_AIX
-#include <sys/syscall.h>  // NOLINT
-#endif
-
-#if V8_OS_MACOSX
-#include <mach/mach.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.
-#elif(!V8_OS_ANDROID || defined(__BIONIC_HAVE_UCONTEXT_T)) && \
-    !V8_OS_OPENBSD && !V8_OS_NACL
-#include <ucontext.h>
-#endif
-
-#include <unistd.h>
-
-// GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'.
-// Old versions of the C library <signal.h> didn't define the type.
-#if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) && \
-    (defined(__arm__) || defined(__aarch64__)) && \
-    !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
-#include <asm/sigcontext.h>  // NOLINT
-#endif
-
-#elif V8_OS_WIN || V8_OS_CYGWIN
-
-#include "src/base/win32-headers.h"
-
-#endif
-
-#include "src/base/platform/platform.h"
-#include "src/flags.h"
-#include "src/frames-inl.h"
-#include "src/log.h"
-#include "src/profiler/cpu-profiler-inl.h"
-#include "src/simulator.h"
-#include "src/v8threads.h"
-#include "src/vm-state-inl.h"
-
-
-#if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
-
-// Not all versions of Android's C library provide ucontext_t.
-// Detect this and provide custom but compatible definitions. Note that these
-// follow the GLibc naming convention to access register values from
-// mcontext_t.
-//
-// See http://code.google.com/p/android/issues/detail?id=34784
-
-#if defined(__arm__)
-
-typedef struct sigcontext mcontext_t;
-
-typedef struct ucontext {
-  uint32_t uc_flags;
-  struct ucontext* uc_link;
-  stack_t uc_stack;
-  mcontext_t uc_mcontext;
-  // Other fields are not used by V8, don't define them here.
-} ucontext_t;
-
-#elif defined(__aarch64__)
-
-typedef struct sigcontext mcontext_t;
-
-typedef struct ucontext {
-  uint64_t uc_flags;
-  struct ucontext *uc_link;
-  stack_t uc_stack;
-  mcontext_t uc_mcontext;
-  // Other fields are not used by V8, don't define them here.
-} ucontext_t;
-
-#elif defined(__mips__)
-// MIPS version of sigcontext, for Android bionic.
-typedef struct {
-  uint32_t regmask;
-  uint32_t status;
-  uint64_t pc;
-  uint64_t gregs[32];
-  uint64_t fpregs[32];
-  uint32_t acx;
-  uint32_t fpc_csr;
-  uint32_t fpc_eir;
-  uint32_t used_math;
-  uint32_t dsp;
-  uint64_t mdhi;
-  uint64_t mdlo;
-  uint32_t hi1;
-  uint32_t lo1;
-  uint32_t hi2;
-  uint32_t lo2;
-  uint32_t hi3;
-  uint32_t lo3;
-} mcontext_t;
-
-typedef struct ucontext {
-  uint32_t uc_flags;
-  struct ucontext* uc_link;
-  stack_t uc_stack;
-  mcontext_t uc_mcontext;
-  // Other fields are not used by V8, don't define them here.
-} ucontext_t;
-
-#elif defined(__i386__)
-// x86 version for Android.
-typedef struct {
-  uint32_t gregs[19];
-  void* fpregs;
-  uint32_t oldmask;
-  uint32_t cr2;
-} mcontext_t;
-
-typedef uint32_t kernel_sigset_t[2];  // x86 kernel uses 64-bit signal masks
-typedef struct ucontext {
-  uint32_t uc_flags;
-  struct ucontext* uc_link;
-  stack_t uc_stack;
-  mcontext_t uc_mcontext;
-  // Other fields are not used by V8, don't define them here.
-} ucontext_t;
-enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 };
-
-#elif defined(__x86_64__)
-// x64 version for Android.
-typedef struct {
-  uint64_t gregs[23];
-  void* fpregs;
-  uint64_t __reserved1[8];
-} mcontext_t;
-
-typedef struct ucontext {
-  uint64_t uc_flags;
-  struct ucontext *uc_link;
-  stack_t uc_stack;
-  mcontext_t uc_mcontext;
-  // Other fields are not used by V8, don't define them here.
-} ucontext_t;
-enum { REG_RBP = 10, REG_RSP = 15, REG_RIP = 16 };
-#endif
-
-#endif  // V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T)
-
-
-namespace v8 {
-namespace internal {
-
-namespace {
-
-class PlatformDataCommon : public Malloced {
- public:
-  PlatformDataCommon() : profiled_thread_id_(ThreadId::Current()) {}
-  ThreadId profiled_thread_id() { return profiled_thread_id_; }
-
- protected:
-  ~PlatformDataCommon() {}
-
- private:
-  ThreadId profiled_thread_id_;
-};
-
-
-bool IsSamePage(byte* ptr1, byte* ptr2) {
-  const uint32_t kPageSize = 4096;
-  uintptr_t mask = ~static_cast<uintptr_t>(kPageSize - 1);
-  return (reinterpret_cast<uintptr_t>(ptr1) & mask) ==
-         (reinterpret_cast<uintptr_t>(ptr2) & mask);
-}
-
-
-// Check if the code at specified address could potentially be a
-// frame setup code.
-bool IsNoFrameRegion(Address address) {
-  struct Pattern {
-    int bytes_count;
-    byte bytes[8];
-    int offsets[4];
-  };
-  byte* pc = reinterpret_cast<byte*>(address);
-  static Pattern patterns[] = {
-#if V8_HOST_ARCH_IA32
-    // push %ebp
-    // mov %esp,%ebp
-    {3, {0x55, 0x89, 0xe5}, {0, 1, -1}},
-    // pop %ebp
-    // ret N
-    {2, {0x5d, 0xc2}, {0, 1, -1}},
-    // pop %ebp
-    // ret
-    {2, {0x5d, 0xc3}, {0, 1, -1}},
-#elif V8_HOST_ARCH_X64
-    // pushq %rbp
-    // movq %rsp,%rbp
-    {4, {0x55, 0x48, 0x89, 0xe5}, {0, 1, -1}},
-    // popq %rbp
-    // ret N
-    {2, {0x5d, 0xc2}, {0, 1, -1}},
-    // popq %rbp
-    // ret
-    {2, {0x5d, 0xc3}, {0, 1, -1}},
-#endif
-    {0, {}, {}}
-  };
-  for (Pattern* pattern = patterns; pattern->bytes_count; ++pattern) {
-    for (int* offset_ptr = pattern->offsets; *offset_ptr != -1; ++offset_ptr) {
-      int offset = *offset_ptr;
-      if (!offset || IsSamePage(pc, pc - offset)) {
-        MSAN_MEMORY_IS_INITIALIZED(pc - offset, pattern->bytes_count);
-        if (!memcmp(pc - offset, pattern->bytes, pattern->bytes_count))
-          return true;
-      } else {
-        // It is not safe to examine bytes on another page as it might not be
-        // allocated thus causing a SEGFAULT.
-        // Check the pattern part that's on the same page and
-        // pessimistically assume it could be the entire pattern match.
-        MSAN_MEMORY_IS_INITIALIZED(pc, pattern->bytes_count - offset);
-        if (!memcmp(pc, pattern->bytes + offset, pattern->bytes_count - offset))
-          return true;
-      }
-    }
-  }
-  return false;
-}
-
-}  // namespace
-
-#if defined(USE_SIGNALS)
-
-class Sampler::PlatformData : public PlatformDataCommon {
- public:
-  PlatformData() : vm_tid_(pthread_self()) {}
-  pthread_t vm_tid() const { return vm_tid_; }
-
- private:
-  pthread_t vm_tid_;
-};
-
-#elif V8_OS_WIN || V8_OS_CYGWIN
-
-// ----------------------------------------------------------------------------
-// Win32 profiler support. On Cygwin we use the same sampler implementation as
-// on Win32.
-
-class Sampler::PlatformData : public PlatformDataCommon {
- public:
-  // Get a handle to the calling thread. This is the thread that we are
-  // going to profile. We need to make a copy of the handle because we are
-  // going to use it in the sampler thread. Using GetThreadHandle() will
-  // not work in this case. We're using OpenThread because DuplicateHandle
-  // for some reason doesn't work in Chrome's sandbox.
-  PlatformData()
-      : profiled_thread_(OpenThread(THREAD_GET_CONTEXT |
-                                    THREAD_SUSPEND_RESUME |
-                                    THREAD_QUERY_INFORMATION,
-                                    false,
-                                    GetCurrentThreadId())) {}
-
-  ~PlatformData() {
-    if (profiled_thread_ != NULL) {
-      CloseHandle(profiled_thread_);
-      profiled_thread_ = NULL;
-    }
-  }
-
-  HANDLE profiled_thread() { return profiled_thread_; }
-
- private:
-  HANDLE profiled_thread_;
-};
-#endif
-
-
-#if defined(USE_SIMULATOR)
-class SimulatorHelper {
- public:
-  inline bool Init(Isolate* isolate) {
-    simulator_ = isolate->thread_local_top()->simulator_;
-    // Check if there is active simulator.
-    return simulator_ != NULL;
-  }
-
-  inline void FillRegisters(v8::RegisterState* state) {
-#if V8_TARGET_ARCH_ARM
-    if (!simulator_->has_bad_pc()) {
-      state->pc = reinterpret_cast<Address>(simulator_->get_pc());
-    }
-    state->sp = reinterpret_cast<Address>(simulator_->get_register(
-        Simulator::sp));
-    state->fp = reinterpret_cast<Address>(simulator_->get_register(
-        Simulator::r11));
-#elif V8_TARGET_ARCH_ARM64
-    if (simulator_->sp() == 0 || simulator_->fp() == 0) {
-      // It's possible that the simulator is interrupted while it is updating
-      // the sp or fp register. ARM64 simulator does this in two steps:
-      // first setting it to zero and then setting it to a new value.
-      // Bailout if sp/fp doesn't contain the new value.
-      //
-      // FIXME: The above doesn't really solve the issue.
-      // If a 64-bit target is executed on a 32-bit host even the final
-      // write is non-atomic, so it might obtain a half of the result.
-      // Moreover as long as the register set code uses memcpy (as of now),
-      // it is not guaranteed to be atomic even when both host and target
-      // are of same bitness.
-      return;
-    }
-    state->pc = reinterpret_cast<Address>(simulator_->pc());
-    state->sp = reinterpret_cast<Address>(simulator_->sp());
-    state->fp = reinterpret_cast<Address>(simulator_->fp());
-#elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
-    if (!simulator_->has_bad_pc()) {
-      state->pc = reinterpret_cast<Address>(simulator_->get_pc());
-    }
-    state->sp = reinterpret_cast<Address>(simulator_->get_register(
-        Simulator::sp));
-    state->fp = reinterpret_cast<Address>(simulator_->get_register(
-        Simulator::fp));
-#elif V8_TARGET_ARCH_PPC
-    if (!simulator_->has_bad_pc()) {
-      state->pc = reinterpret_cast<Address>(simulator_->get_pc());
-    }
-    state->sp =
-        reinterpret_cast<Address>(simulator_->get_register(Simulator::sp));
-    state->fp =
-        reinterpret_cast<Address>(simulator_->get_register(Simulator::fp));
-#elif V8_TARGET_ARCH_S390
-    if (!simulator_->has_bad_pc()) {
-      state->pc = reinterpret_cast<Address>(simulator_->get_pc());
-    }
-    state->sp =
-        reinterpret_cast<Address>(simulator_->get_register(Simulator::sp));
-    state->fp =
-        reinterpret_cast<Address>(simulator_->get_register(Simulator::fp));
-#endif
-  }
-
- private:
-  Simulator* simulator_;
-};
-#endif  // USE_SIMULATOR
-
-
-#if defined(USE_SIGNALS)
-
-class SignalHandler : public AllStatic {
- public:
-  static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); }
-  static void TearDown() { delete mutex_; mutex_ = NULL; }
-
-  static void IncreaseSamplerCount() {
-    base::LockGuard<base::Mutex> lock_guard(mutex_);
-    if (++client_count_ == 1) Install();
-  }
-
-  static void DecreaseSamplerCount() {
-    base::LockGuard<base::Mutex> lock_guard(mutex_);
-    if (--client_count_ == 0) Restore();
-  }
-
-  static bool Installed() {
-    return signal_handler_installed_;
-  }
-
- private:
-  static void Install() {
-#if !V8_OS_NACL
-    struct sigaction sa;
-    sa.sa_sigaction = &HandleProfilerSignal;
-    sigemptyset(&sa.sa_mask);
-#if V8_OS_QNX
-    sa.sa_flags = SA_SIGINFO;
-#else
-    sa.sa_flags = SA_RESTART | SA_SIGINFO;
-#endif
-    signal_handler_installed_ =
-        (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
-#endif
-  }
-
-  static void Restore() {
-#if !V8_OS_NACL
-    if (signal_handler_installed_) {
-      sigaction(SIGPROF, &old_signal_handler_, 0);
-      signal_handler_installed_ = false;
-    }
-#endif
-  }
-
-#if !V8_OS_NACL
-  static void HandleProfilerSignal(int signal, siginfo_t* info, void* context);
-#endif
-  // Protects the process wide state below.
-  static base::Mutex* mutex_;
-  static int client_count_;
-  static bool signal_handler_installed_;
-  static struct sigaction old_signal_handler_;
-};
-
-
-base::Mutex* SignalHandler::mutex_ = NULL;
-int SignalHandler::client_count_ = 0;
-struct sigaction SignalHandler::old_signal_handler_;
-bool SignalHandler::signal_handler_installed_ = false;
-
-
-// As Native Client does not support signal handling, profiling is disabled.
-#if !V8_OS_NACL
-void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
-                                         void* context) {
-  USE(info);
-  if (signal != SIGPROF) return;
-  Isolate* isolate = Isolate::UnsafeCurrent();
-  if (isolate == NULL || !isolate->IsInUse()) {
-    // We require a fully initialized and entered isolate.
-    return;
-  }
-  if (v8::Locker::IsActive() &&
-      !isolate->thread_manager()->IsLockedByCurrentThread()) {
-    return;
-  }
-
-  Sampler* sampler = isolate->logger()->sampler();
-  if (sampler == NULL) return;
-
-  v8::RegisterState state;
-
-#if defined(USE_SIMULATOR)
-  SimulatorHelper helper;
-  if (!helper.Init(isolate)) return;
-  helper.FillRegisters(&state);
-  // It possible that the simulator is interrupted while it is updating
-  // the sp or fp register. ARM64 simulator does this in two steps:
-  // first setting it to zero and then setting it to the new value.
-  // Bailout if sp/fp doesn't contain the new value.
-  if (state.sp == 0 || state.fp == 0) return;
-#else
-  // Extracting the sample from the context is extremely machine dependent.
-  ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
-#if !(V8_OS_OPENBSD || (V8_OS_LINUX && (V8_HOST_ARCH_PPC || V8_HOST_ARCH_S390)))
-  mcontext_t& mcontext = ucontext->uc_mcontext;
-#endif
-#if V8_OS_LINUX
-#if V8_HOST_ARCH_IA32
-  state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
-  state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
-  state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
-#elif V8_HOST_ARCH_X64
-  state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
-  state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
-  state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
-#elif V8_HOST_ARCH_ARM
-#if V8_LIBC_GLIBC && !V8_GLIBC_PREREQ(2, 4)
-  // Old GLibc ARM versions used a gregs[] array to access the register
-  // values from mcontext_t.
-  state.pc = reinterpret_cast<Address>(mcontext.gregs[R15]);
-  state.sp = reinterpret_cast<Address>(mcontext.gregs[R13]);
-  state.fp = reinterpret_cast<Address>(mcontext.gregs[R11]);
-#else
-  state.pc = reinterpret_cast<Address>(mcontext.arm_pc);
-  state.sp = reinterpret_cast<Address>(mcontext.arm_sp);
-  state.fp = reinterpret_cast<Address>(mcontext.arm_fp);
-#endif  // V8_LIBC_GLIBC && !V8_GLIBC_PREREQ(2, 4)
-#elif V8_HOST_ARCH_ARM64
-  state.pc = reinterpret_cast<Address>(mcontext.pc);
-  state.sp = reinterpret_cast<Address>(mcontext.sp);
-  // FP is an alias for x29.
-  state.fp = reinterpret_cast<Address>(mcontext.regs[29]);
-#elif V8_HOST_ARCH_MIPS
-  state.pc = reinterpret_cast<Address>(mcontext.pc);
-  state.sp = reinterpret_cast<Address>(mcontext.gregs[29]);
-  state.fp = reinterpret_cast<Address>(mcontext.gregs[30]);
-#elif V8_HOST_ARCH_MIPS64
-  state.pc = reinterpret_cast<Address>(mcontext.pc);
-  state.sp = reinterpret_cast<Address>(mcontext.gregs[29]);
-  state.fp = reinterpret_cast<Address>(mcontext.gregs[30]);
-#elif V8_HOST_ARCH_PPC
-  state.pc = reinterpret_cast<Address>(ucontext->uc_mcontext.regs->nip);
-  state.sp = reinterpret_cast<Address>(ucontext->uc_mcontext.regs->gpr[PT_R1]);
-  state.fp = reinterpret_cast<Address>(ucontext->uc_mcontext.regs->gpr[PT_R31]);
-#elif V8_HOST_ARCH_S390
-#if V8_TARGET_ARCH_32_BIT
-  // 31-bit target will have bit 0 (MSB) of the PSW set to denote addressing
-  // mode.  This bit needs to be masked out to resolve actual address.
-  state.pc =
-      reinterpret_cast<Address>(ucontext->uc_mcontext.psw.addr & 0x7FFFFFFF);
-#else
-  state.pc = reinterpret_cast<Address>(ucontext->uc_mcontext.psw.addr);
-#endif  // V8_TARGET_ARCH_32_BIT
-  state.sp = reinterpret_cast<Address>(ucontext->uc_mcontext.gregs[15]);
-  state.fp = reinterpret_cast<Address>(ucontext->uc_mcontext.gregs[11]);
-#endif  // V8_HOST_ARCH_*
-#elif V8_OS_MACOSX
-#if V8_HOST_ARCH_X64
-#if __DARWIN_UNIX03
-  state.pc = reinterpret_cast<Address>(mcontext->__ss.__rip);
-  state.sp = reinterpret_cast<Address>(mcontext->__ss.__rsp);
-  state.fp = reinterpret_cast<Address>(mcontext->__ss.__rbp);
-#else  // !__DARWIN_UNIX03
-  state.pc = reinterpret_cast<Address>(mcontext->ss.rip);
-  state.sp = reinterpret_cast<Address>(mcontext->ss.rsp);
-  state.fp = reinterpret_cast<Address>(mcontext->ss.rbp);
-#endif  // __DARWIN_UNIX03
-#elif V8_HOST_ARCH_IA32
-#if __DARWIN_UNIX03
-  state.pc = reinterpret_cast<Address>(mcontext->__ss.__eip);
-  state.sp = reinterpret_cast<Address>(mcontext->__ss.__esp);
-  state.fp = reinterpret_cast<Address>(mcontext->__ss.__ebp);
-#else  // !__DARWIN_UNIX03
-  state.pc = reinterpret_cast<Address>(mcontext->ss.eip);
-  state.sp = reinterpret_cast<Address>(mcontext->ss.esp);
-  state.fp = reinterpret_cast<Address>(mcontext->ss.ebp);
-#endif  // __DARWIN_UNIX03
-#endif  // V8_HOST_ARCH_IA32
-#elif V8_OS_FREEBSD
-#if V8_HOST_ARCH_IA32
-  state.pc = reinterpret_cast<Address>(mcontext.mc_eip);
-  state.sp = reinterpret_cast<Address>(mcontext.mc_esp);
-  state.fp = reinterpret_cast<Address>(mcontext.mc_ebp);
-#elif V8_HOST_ARCH_X64
-  state.pc = reinterpret_cast<Address>(mcontext.mc_rip);
-  state.sp = reinterpret_cast<Address>(mcontext.mc_rsp);
-  state.fp = reinterpret_cast<Address>(mcontext.mc_rbp);
-#elif V8_HOST_ARCH_ARM
-  state.pc = reinterpret_cast<Address>(mcontext.mc_r15);
-  state.sp = reinterpret_cast<Address>(mcontext.mc_r13);
-  state.fp = reinterpret_cast<Address>(mcontext.mc_r11);
-#endif  // V8_HOST_ARCH_*
-#elif V8_OS_NETBSD
-#if V8_HOST_ARCH_IA32
-  state.pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_EIP]);
-  state.sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_ESP]);
-  state.fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_EBP]);
-#elif V8_HOST_ARCH_X64
-  state.pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_RIP]);
-  state.sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RSP]);
-  state.fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]);
-#endif  // V8_HOST_ARCH_*
-#elif V8_OS_OPENBSD
-#if V8_HOST_ARCH_IA32
-  state.pc = reinterpret_cast<Address>(ucontext->sc_eip);
-  state.sp = reinterpret_cast<Address>(ucontext->sc_esp);
-  state.fp = reinterpret_cast<Address>(ucontext->sc_ebp);
-#elif V8_HOST_ARCH_X64
-  state.pc = reinterpret_cast<Address>(ucontext->sc_rip);
-  state.sp = reinterpret_cast<Address>(ucontext->sc_rsp);
-  state.fp = reinterpret_cast<Address>(ucontext->sc_rbp);
-#endif  // V8_HOST_ARCH_*
-#elif V8_OS_SOLARIS
-  state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]);
-  state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]);
-  state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]);
-#elif V8_OS_QNX
-#if V8_HOST_ARCH_IA32
-  state.pc = reinterpret_cast<Address>(mcontext.cpu.eip);
-  state.sp = reinterpret_cast<Address>(mcontext.cpu.esp);
-  state.fp = reinterpret_cast<Address>(mcontext.cpu.ebp);
-#elif V8_HOST_ARCH_ARM
-  state.pc = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_PC]);
-  state.sp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_SP]);
-  state.fp = reinterpret_cast<Address>(mcontext.cpu.gpr[ARM_REG_FP]);
-#endif  // V8_HOST_ARCH_*
-#elif V8_OS_AIX
-  state.pc = reinterpret_cast<Address>(mcontext.jmp_context.iar);
-  state.sp = reinterpret_cast<Address>(mcontext.jmp_context.gpr[1]);
-  state.fp = reinterpret_cast<Address>(mcontext.jmp_context.gpr[31]);
-#endif  // V8_OS_AIX
-#endif  // USE_SIMULATOR
-  sampler->SampleStack(state);
-}
-#endif  // V8_OS_NACL
-
-#endif
-
-
-class SamplerThread : public base::Thread {
- public:
-  static const int kSamplerThreadStackSize = 64 * KB;
-
-  explicit SamplerThread(int interval)
-      : Thread(base::Thread::Options("SamplerThread", kSamplerThreadStackSize)),
-        interval_(interval) {}
-
-  static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); }
-  static void TearDown() { delete mutex_; mutex_ = NULL; }
-
-  static void AddActiveSampler(Sampler* sampler) {
-    bool need_to_start = false;
-    base::LockGuard<base::Mutex> lock_guard(mutex_);
-    if (instance_ == NULL) {
-      // Start a thread that will send SIGPROF signal to VM threads,
-      // when CPU profiling will be enabled.
-      instance_ = new SamplerThread(sampler->interval());
-      need_to_start = true;
-    }
-
-    DCHECK(sampler->IsActive());
-    DCHECK(!instance_->active_samplers_.Contains(sampler));
-    DCHECK(instance_->interval_ == sampler->interval());
-    instance_->active_samplers_.Add(sampler);
-
-    if (need_to_start) instance_->StartSynchronously();
-  }
-
-  static void RemoveActiveSampler(Sampler* sampler) {
-    SamplerThread* instance_to_remove = NULL;
-    {
-      base::LockGuard<base::Mutex> lock_guard(mutex_);
-
-      DCHECK(sampler->IsActive());
-      bool removed = instance_->active_samplers_.RemoveElement(sampler);
-      DCHECK(removed);
-      USE(removed);
-
-      // We cannot delete the instance immediately as we need to Join() the
-      // thread but we are holding mutex_ and the thread may try to acquire it.
-      if (instance_->active_samplers_.is_empty()) {
-        instance_to_remove = instance_;
-        instance_ = NULL;
-      }
-    }
-
-    if (!instance_to_remove) return;
-    instance_to_remove->Join();
-    delete instance_to_remove;
-  }
-
-  // Implement Thread::Run().
-  virtual void Run() {
-    while (true) {
-      {
-        base::LockGuard<base::Mutex> lock_guard(mutex_);
-        if (active_samplers_.is_empty()) break;
-        // When CPU profiling is enabled both JavaScript and C++ code is
-        // profiled. We must not suspend.
-        for (int i = 0; i < active_samplers_.length(); ++i) {
-          Sampler* sampler = active_samplers_.at(i);
-          if (!sampler->IsProfiling()) continue;
-          sampler->DoSample();
-        }
-      }
-      base::OS::Sleep(base::TimeDelta::FromMilliseconds(interval_));
-    }
-  }
-
- private:
-  // Protects the process wide state below.
-  static base::Mutex* mutex_;
-  static SamplerThread* instance_;
-
-  const int interval_;
-  List<Sampler*> active_samplers_;
-
-  DISALLOW_COPY_AND_ASSIGN(SamplerThread);
-};
-
-
-base::Mutex* SamplerThread::mutex_ = NULL;
-SamplerThread* SamplerThread::instance_ = NULL;
-
-
-//
-// StackTracer implementation
-//
-DISABLE_ASAN void TickSample::Init(Isolate* isolate,
-                                   const v8::RegisterState& regs,
-                                   RecordCEntryFrame record_c_entry_frame,
-                                   bool update_stats) {
-  timestamp = base::TimeTicks::HighResolutionNow();
-  pc = reinterpret_cast<Address>(regs.pc);
-  state = isolate->current_vm_state();
-  this->update_stats = update_stats;
-
-  // Avoid collecting traces while doing GC.
-  if (state == GC) return;
-
-  Address js_entry_sp = isolate->js_entry_sp();
-  if (js_entry_sp == 0) return;  // Not executing JS now.
-
-  if (pc && IsNoFrameRegion(pc)) {
-    // Can't collect stack. Mark the sample as spoiled.
-    timestamp = base::TimeTicks();
-    pc = 0;
-    return;
-  }
-
-  ExternalCallbackScope* scope = isolate->external_callback_scope();
-  Address handler = Isolate::handler(isolate->thread_local_top());
-  // If there is a handler on top of the external callback scope then
-  // we have already entrered JavaScript again and the external callback
-  // is not the top function.
-  if (scope && scope->scope_address() < handler) {
-    external_callback_entry = *scope->callback_entrypoint_address();
-    has_external_callback = true;
-  } else {
-    // sp register may point at an arbitrary place in memory, make
-    // sure MSAN doesn't complain about it.
-    MSAN_MEMORY_IS_INITIALIZED(regs.sp, sizeof(Address));
-    // Sample potential return address value for frameless invocation of
-    // stubs (we'll figure out later, if this value makes sense).
-    tos = Memory::Address_at(reinterpret_cast<Address>(regs.sp));
-    has_external_callback = false;
-  }
-
-  SafeStackFrameIterator it(isolate, reinterpret_cast<Address>(regs.fp),
-                            reinterpret_cast<Address>(regs.sp), js_entry_sp);
-  top_frame_type = it.top_frame_type();
-
-  SampleInfo info;
-  GetStackSample(isolate, regs, record_c_entry_frame,
-                 reinterpret_cast<void**>(&stack[0]), kMaxFramesCount, &info);
-  frames_count = static_cast<unsigned>(info.frames_count);
-  if (!frames_count) {
-    // It is executing JS but failed to collect a stack trace.
-    // Mark the sample as spoiled.
-    timestamp = base::TimeTicks();
-    pc = 0;
-  }
-}
-
-
-void TickSample::GetStackSample(Isolate* isolate, const v8::RegisterState& regs,
-                                RecordCEntryFrame record_c_entry_frame,
-                                void** frames, size_t frames_limit,
-                                v8::SampleInfo* sample_info) {
-  sample_info->frames_count = 0;
-  sample_info->vm_state = isolate->current_vm_state();
-  if (sample_info->vm_state == GC) return;
-
-  Address js_entry_sp = isolate->js_entry_sp();
-  if (js_entry_sp == 0) return;  // Not executing JS now.
-
-  SafeStackFrameIterator it(isolate, reinterpret_cast<Address>(regs.fp),
-                            reinterpret_cast<Address>(regs.sp), js_entry_sp);
-  size_t i = 0;
-  if (record_c_entry_frame == kIncludeCEntryFrame && !it.done() &&
-      it.top_frame_type() == StackFrame::EXIT) {
-    frames[i++] = isolate->c_function();
-  }
-  while (!it.done() && i < frames_limit) {
-    if (it.frame()->is_interpreted()) {
-      // For interpreted frames use the bytecode array pointer as the pc.
-      InterpretedFrame* frame = static_cast<InterpretedFrame*>(it.frame());
-      // Since the sampler can interrupt execution at any point the
-      // bytecode_array might be garbage, so don't dereference it.
-      Address bytecode_array =
-          reinterpret_cast<Address>(frame->GetBytecodeArray()) - kHeapObjectTag;
-      frames[i++] = bytecode_array + BytecodeArray::kHeaderSize +
-                    frame->GetBytecodeOffset();
-    } else {
-      frames[i++] = it.frame()->pc();
-    }
-    it.Advance();
-  }
-  sample_info->frames_count = i;
-}
-
-
-void Sampler::SetUp() {
-#if defined(USE_SIGNALS)
-  SignalHandler::SetUp();
-#endif
-  SamplerThread::SetUp();
-}
-
-
-void Sampler::TearDown() {
-  SamplerThread::TearDown();
-#if defined(USE_SIGNALS)
-  SignalHandler::TearDown();
-#endif
-}
-
-Sampler::Sampler(Isolate* isolate, int interval)
-    : isolate_(isolate),
-      interval_(interval),
-      profiling_(false),
-      has_processing_thread_(false),
-      active_(false),
-      is_counting_samples_(false),
-      js_sample_count_(0),
-      external_sample_count_(0) {
-  data_ = new PlatformData;
-}
-
-Sampler::~Sampler() {
-  DCHECK(!IsActive());
-  delete data_;
-}
-
-void Sampler::Start() {
-  DCHECK(!IsActive());
-  SetActive(true);
-  SamplerThread::AddActiveSampler(this);
-}
-
-
-void Sampler::Stop() {
-  DCHECK(IsActive());
-  SamplerThread::RemoveActiveSampler(this);
-  SetActive(false);
-}
-
-
-void Sampler::IncreaseProfilingDepth() {
-  base::NoBarrier_AtomicIncrement(&profiling_, 1);
-#if defined(USE_SIGNALS)
-  SignalHandler::IncreaseSamplerCount();
-#endif
-}
-
-
-void Sampler::DecreaseProfilingDepth() {
-#if defined(USE_SIGNALS)
-  SignalHandler::DecreaseSamplerCount();
-#endif
-  base::NoBarrier_AtomicIncrement(&profiling_, -1);
-}
-
-
-void Sampler::SampleStack(const v8::RegisterState& state) {
-  TickSample* sample = isolate_->cpu_profiler()->StartTickSample();
-  TickSample sample_obj;
-  if (sample == NULL) sample = &sample_obj;
-  sample->Init(isolate_, state, TickSample::kIncludeCEntryFrame, true);
-  if (is_counting_samples_ && !sample->timestamp.IsNull()) {
-    if (sample->state == JS) ++js_sample_count_;
-    if (sample->state == EXTERNAL) ++external_sample_count_;
-  }
-  Tick(sample);
-  if (sample != &sample_obj) {
-    isolate_->cpu_profiler()->FinishTickSample();
-  }
-}
-
-
-#if defined(USE_SIGNALS)
-
-void Sampler::DoSample() {
-  if (!SignalHandler::Installed()) return;
-  pthread_kill(platform_data()->vm_tid(), SIGPROF);
-}
-
-#elif V8_OS_WIN || V8_OS_CYGWIN
-
-void Sampler::DoSample() {
-  HANDLE profiled_thread = platform_data()->profiled_thread();
-  if (profiled_thread == NULL) return;
-
-#if defined(USE_SIMULATOR)
-  SimulatorHelper helper;
-  if (!helper.Init(isolate())) return;
-#endif
-
-  const DWORD kSuspendFailed = static_cast<DWORD>(-1);
-  if (SuspendThread(profiled_thread) == kSuspendFailed) return;
-
-  // Context used for sampling the register state of the profiled thread.
-  CONTEXT context;
-  memset(&context, 0, sizeof(context));
-  context.ContextFlags = CONTEXT_FULL;
-  if (GetThreadContext(profiled_thread, &context) != 0) {
-    v8::RegisterState state;
-#if defined(USE_SIMULATOR)
-    helper.FillRegisters(&state);
-#else
-#if V8_HOST_ARCH_X64
-    state.pc = reinterpret_cast<Address>(context.Rip);
-    state.sp = reinterpret_cast<Address>(context.Rsp);
-    state.fp = reinterpret_cast<Address>(context.Rbp);
-#else
-    state.pc = reinterpret_cast<Address>(context.Eip);
-    state.sp = reinterpret_cast<Address>(context.Esp);
-    state.fp = reinterpret_cast<Address>(context.Ebp);
-#endif
-#endif  // USE_SIMULATOR
-    SampleStack(state);
-  }
-  ResumeThread(profiled_thread);
-}
-
-#endif  // USE_SIGNALS
-
-
-}  // namespace internal
-}  // namespace v8
diff --git a/src/profiler/sampler.h b/src/profiler/sampler.h
deleted file mode 100644
index dcd1255..0000000
--- a/src/profiler/sampler.h
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_PROFILER_SAMPLER_H_
-#define V8_PROFILER_SAMPLER_H_
-
-#include "include/v8.h"
-
-#include "src/base/atomicops.h"
-#include "src/base/platform/time.h"
-#include "src/frames.h"
-#include "src/globals.h"
-
-namespace v8 {
-namespace internal {
-
-class Isolate;
-
-// ----------------------------------------------------------------------------
-// Sampler
-//
-// A sampler periodically samples the state of the VM and optionally
-// (if used for profiling) the program counter and stack pointer for
-// the thread that created it.
-
-// TickSample captures the information collected for each sample.
-struct TickSample {
-  // Internal profiling (with --prof + tools/$OS-tick-processor) wants to
-  // include the runtime function we're calling. Externally exposed tick
-  // samples don't care.
-  enum RecordCEntryFrame { kIncludeCEntryFrame, kSkipCEntryFrame };
-
-  TickSample()
-      : state(OTHER),
-        pc(NULL),
-        external_callback_entry(NULL),
-        frames_count(0),
-        has_external_callback(false),
-        update_stats(true),
-        top_frame_type(StackFrame::NONE) {}
-  void Init(Isolate* isolate, const v8::RegisterState& state,
-            RecordCEntryFrame record_c_entry_frame, bool update_stats);
-  static void GetStackSample(Isolate* isolate, const v8::RegisterState& state,
-                             RecordCEntryFrame record_c_entry_frame,
-                             void** frames, size_t frames_limit,
-                             v8::SampleInfo* sample_info);
-  StateTag state;  // The state of the VM.
-  Address pc;      // Instruction pointer.
-  union {
-    Address tos;   // Top stack value (*sp).
-    Address external_callback_entry;
-  };
-  static const unsigned kMaxFramesCountLog2 = 8;
-  static const unsigned kMaxFramesCount = (1 << kMaxFramesCountLog2) - 1;
-  Address stack[kMaxFramesCount];  // Call stack.
-  base::TimeTicks timestamp;
-  unsigned frames_count : kMaxFramesCountLog2;  // Number of captured frames.
-  bool has_external_callback : 1;
-  bool update_stats : 1;  // Whether the sample should update aggregated stats.
-  StackFrame::Type top_frame_type : 5;
-};
-
-class Sampler {
- public:
-  // Initializes the Sampler support. Called once at VM startup.
-  static void SetUp();
-  static void TearDown();
-
-  // Initialize sampler.
-  Sampler(Isolate* isolate, int interval);
-  virtual ~Sampler();
-
-  Isolate* isolate() const { return isolate_; }
-  int interval() const { return interval_; }
-
-  // Performs stack sampling.
-  void SampleStack(const v8::RegisterState& regs);
-
-  // Start and stop sampler.
-  void Start();
-  void Stop();
-
-  // Whether the sampling thread should use this Sampler for CPU profiling?
-  bool IsProfiling() const {
-    return base::NoBarrier_Load(&profiling_) > 0 &&
-        !base::NoBarrier_Load(&has_processing_thread_);
-  }
-  void IncreaseProfilingDepth();
-  void DecreaseProfilingDepth();
-
-  // Whether the sampler is running (that is, consumes resources).
-  bool IsActive() const { return base::NoBarrier_Load(&active_); }
-
-  void DoSample();
-  // If true next sample must be initiated on the profiler event processor
-  // thread right after latest sample is processed.
-  void SetHasProcessingThread(bool value) {
-    base::NoBarrier_Store(&has_processing_thread_, value);
-  }
-
-  // Used in tests to make sure that stack sampling is performed.
-  unsigned js_sample_count() const { return js_sample_count_; }
-  unsigned external_sample_count() const { return external_sample_count_; }
-  void StartCountingSamples() {
-    js_sample_count_ = 0;
-    external_sample_count_ = 0;
-    is_counting_samples_ = true;
-  }
-
-  class PlatformData;
-  PlatformData* platform_data() const { return data_; }
-
- protected:
-  // This method is called for each sampling period with the current
-  // program counter.
-  virtual void Tick(TickSample* sample) = 0;
-
- private:
-  void SetActive(bool value) { base::NoBarrier_Store(&active_, value); }
-
-  Isolate* isolate_;
-  const int interval_;
-  base::Atomic32 profiling_;
-  base::Atomic32 has_processing_thread_;
-  base::Atomic32 active_;
-  PlatformData* data_;  // Platform specific data.
-  // Counts stack samples taken in various VM states.
-  bool is_counting_samples_;
-  unsigned js_sample_count_;
-  unsigned external_sample_count_;
-  DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
-};
-
-
-}  // namespace internal
-}  // namespace v8
-
-#endif  // V8_PROFILER_SAMPLER_H_
diff --git a/src/profiler/sampling-heap-profiler.cc b/src/profiler/sampling-heap-profiler.cc
index a32cae3..b4361ee 100644
--- a/src/profiler/sampling-heap-profiler.cc
+++ b/src/profiler/sampling-heap-profiler.cc
@@ -7,6 +7,7 @@
 #include <stdint.h>
 #include <memory>
 #include "src/api.h"
+#include "src/base/ieee754.h"
 #include "src/base/utils/random-number-generator.h"
 #include "src/frames-inl.h"
 #include "src/heap/heap.h"
@@ -27,7 +28,7 @@
     return static_cast<intptr_t>(rate);
   }
   double u = random_->NextDouble();
-  double next = (-std::log(u)) * rate;
+  double next = (-base::ieee754::log(u)) * rate;
   return next < kPointerSize
              ? kPointerSize
              : (next > INT_MAX ? INT_MAX : static_cast<intptr_t>(next));
@@ -47,8 +48,9 @@
   return {size, static_cast<unsigned int>(count * scale + 0.5)};
 }
 
-SamplingHeapProfiler::SamplingHeapProfiler(Heap* heap, StringsStorage* names,
-                                           uint64_t rate, int stack_depth)
+SamplingHeapProfiler::SamplingHeapProfiler(
+    Heap* heap, StringsStorage* names, uint64_t rate, int stack_depth,
+    v8::HeapProfiler::SamplingFlags flags)
     : isolate_(heap->isolate()),
       heap_(heap),
       new_space_observer_(new SamplingAllocationObserver(
@@ -58,14 +60,15 @@
           heap_, static_cast<intptr_t>(rate), rate, this,
           heap->isolate()->random_number_generator())),
       names_(names),
-      profile_root_("(root)", v8::UnboundScript::kNoScriptId, 0),
+      profile_root_(nullptr, "(root)", v8::UnboundScript::kNoScriptId, 0),
       samples_(),
       stack_depth_(stack_depth),
-      rate_(rate) {
+      rate_(rate),
+      flags_(flags) {
   CHECK_GT(rate_, 0);
   heap->new_space()->AddAllocationObserver(new_space_observer_.get());
   AllSpaces spaces(heap);
-  for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
+  for (Space* space = spaces.next(); space != nullptr; space = spaces.next()) {
     if (space != heap->new_space()) {
       space->AddAllocationObserver(other_spaces_observer_.get());
     }
@@ -76,7 +79,7 @@
 SamplingHeapProfiler::~SamplingHeapProfiler() {
   heap_->new_space()->RemoveAllocationObserver(new_space_observer_.get());
   AllSpaces spaces(heap_);
-  for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
+  for (Space* space = spaces.next(); space != nullptr; space = spaces.next()) {
     if (space != heap_->new_space()) {
       space->RemoveAllocationObserver(other_spaces_observer_.get());
     }
@@ -109,6 +112,7 @@
   Sample* sample = new Sample(size, node, loc, this);
   samples_.insert(sample);
   sample->global.SetWeak(sample, OnWeakCallback, WeakCallbackType::kParameter);
+  sample->global.MarkIndependent();
 }
 
 void SamplingHeapProfiler::OnWeakCallback(
@@ -117,22 +121,34 @@
   AllocationNode* node = sample->owner;
   DCHECK(node->allocations_[sample->size] > 0);
   node->allocations_[sample->size]--;
+  if (node->allocations_[sample->size] == 0) {
+    node->allocations_.erase(sample->size);
+    while (node->allocations_.empty() && node->children_.empty() &&
+           node->parent_ && !node->parent_->pinned_) {
+      AllocationNode* parent = node->parent_;
+      AllocationNode::FunctionId id = AllocationNode::function_id(
+          node->script_id_, node->script_position_, node->name_);
+      parent->children_.erase(id);
+      delete node;
+      node = parent;
+    }
+  }
   sample->profiler->samples_.erase(sample);
   delete sample;
 }
 
-SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::FindOrAddChildNode(
-    AllocationNode* parent, const char* name, int script_id,
-    int start_position) {
-  for (AllocationNode* child : parent->children_) {
-    if (child->script_id_ == script_id &&
-        child->script_position_ == start_position &&
-        strcmp(child->name_, name) == 0) {
-      return child;
-    }
+SamplingHeapProfiler::AllocationNode*
+SamplingHeapProfiler::AllocationNode::FindOrAddChildNode(const char* name,
+                                                         int script_id,
+                                                         int start_position) {
+  FunctionId id = function_id(script_id, start_position, name);
+  auto it = children_.find(id);
+  if (it != children_.end()) {
+    DCHECK(strcmp(it->second->name_, name) == 0);
+    return it->second;
   }
-  AllocationNode* child = new AllocationNode(name, script_id, start_position);
-  parent->children_.push_back(child);
+  auto child = new AllocationNode(this, name, script_id, start_position);
+  children_.insert(std::make_pair(id, child));
   return child;
 }
 
@@ -140,7 +156,7 @@
   AllocationNode* node = &profile_root_;
 
   std::vector<SharedFunctionInfo*> stack;
-  StackTraceFrameIterator it(isolate_);
+  JavaScriptFrameIterator it(isolate_);
   int frames_captured = 0;
   while (!it.done() && frames_captured < stack_depth_) {
     JavaScriptFrame* frame = it.frame();
@@ -173,7 +189,7 @@
         name = "(JS)";
         break;
     }
-    return FindOrAddChildNode(node, name, v8::UnboundScript::kNoScriptId, 0);
+    return node->FindOrAddChildNode(name, v8::UnboundScript::kNoScriptId, 0);
   }
 
   // We need to process the stack in reverse order as the top of the stack is
@@ -186,14 +202,17 @@
       Script* script = Script::cast(shared->script());
       script_id = script->id();
     }
-    node = FindOrAddChildNode(node, name, script_id, shared->start_position());
+    node = node->FindOrAddChildNode(name, script_id, shared->start_position());
   }
   return node;
 }
 
 v8::AllocationProfile::Node* SamplingHeapProfiler::TranslateAllocationNode(
     AllocationProfile* profile, SamplingHeapProfiler::AllocationNode* node,
-    const std::map<int, Script*>& scripts) {
+    const std::map<int, Handle<Script>>& scripts) {
+  // By pinning the node we make sure its children won't get disposed if
+  // a GC kicks in during the tree retrieval.
+  node->pinned_ = true;
   Local<v8::String> script_name =
       ToApiHandle<v8::String>(isolate_->factory()->InternalizeUtf8String(""));
   int line = v8::AllocationProfile::kNoLineNumberInfo;
@@ -203,22 +222,21 @@
   if (node->script_id_ != v8::UnboundScript::kNoScriptId &&
       scripts.find(node->script_id_) != scripts.end()) {
     // Cannot use std::map<T>::at because it is not available on android.
-    auto non_const_scripts = const_cast<std::map<int, Script*>&>(scripts);
-    Script* script = non_const_scripts[node->script_id_];
-    if (script) {
+    auto non_const_scripts =
+        const_cast<std::map<int, Handle<Script>>&>(scripts);
+    Handle<Script> script = non_const_scripts[node->script_id_];
+    if (!script.is_null()) {
       if (script->name()->IsName()) {
         Name* name = Name::cast(script->name());
         script_name = ToApiHandle<v8::String>(
             isolate_->factory()->InternalizeUtf8String(names_->GetName(name)));
       }
-      Handle<Script> script_handle(script);
-      line = 1 + Script::GetLineNumber(script_handle, node->script_position_);
-      column =
-          1 + Script::GetColumnNumber(script_handle, node->script_position_);
+      line = 1 + Script::GetLineNumber(script, node->script_position_);
+      column = 1 + Script::GetColumnNumber(script, node->script_position_);
     }
-    for (auto alloc : node->allocations_) {
-      allocations.push_back(ScaleSample(alloc.first, alloc.second));
-    }
+  }
+  for (auto alloc : node->allocations_) {
+    allocations.push_back(ScaleSample(alloc.first, alloc.second));
   }
 
   profile->nodes().push_back(v8::AllocationProfile::Node(
@@ -227,35 +245,34 @@
        script_name, node->script_id_, node->script_position_, line, column,
        std::vector<v8::AllocationProfile::Node*>(), allocations}));
   v8::AllocationProfile::Node* current = &profile->nodes().back();
-  size_t child_len = node->children_.size();
-  // The children vector may have nodes appended to it during translation
+  // The children map may have nodes inserted into it during translation
   // because the translation may allocate strings on the JS heap that have
-  // the potential to be sampled. We cache the length of the vector before
-  // iteration so that nodes appended to the vector during iteration are
-  // not processed.
-  for (size_t i = 0; i < child_len; i++) {
+  // the potential to be sampled. That's ok since map iterators are not
+  // invalidated upon std::map insertion.
+  for (auto it : node->children_) {
     current->children.push_back(
-        TranslateAllocationNode(profile, node->children_[i], scripts));
+        TranslateAllocationNode(profile, it.second, scripts));
   }
+  node->pinned_ = false;
   return current;
 }
 
 v8::AllocationProfile* SamplingHeapProfiler::GetAllocationProfile() {
+  if (flags_ & v8::HeapProfiler::kSamplingForceGC) {
+    isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags,
+                                        "SamplingHeapProfiler");
+  }
   // To resolve positions to line/column numbers, we will need to look up
   // scripts. Build a map to allow fast mapping from script id to script.
-  std::map<int, Script*> scripts;
+  std::map<int, Handle<Script>> scripts;
   {
     Script::Iterator iterator(isolate_);
-    Script* script;
-    while ((script = iterator.Next())) {
-      scripts[script->id()] = script;
+    while (Script* script = iterator.Next()) {
+      scripts[script->id()] = handle(script);
     }
   }
-
   auto profile = new v8::internal::AllocationProfile();
-
   TranslateAllocationNode(profile, &profile_root_, scripts);
-
   return profile;
 }
 
diff --git a/src/profiler/sampling-heap-profiler.h b/src/profiler/sampling-heap-profiler.h
index 0b538b0..4b7c366 100644
--- a/src/profiler/sampling-heap-profiler.h
+++ b/src/profiler/sampling-heap-profiler.h
@@ -41,7 +41,7 @@
 class SamplingHeapProfiler {
  public:
   SamplingHeapProfiler(Heap* heap, StringsStorage* names, uint64_t rate,
-                       int stack_depth);
+                       int stack_depth, v8::HeapProfiler::SamplingFlags flags);
   ~SamplingHeapProfiler();
 
   v8::AllocationProfile* GetAllocationProfile();
@@ -71,23 +71,47 @@
 
   class AllocationNode {
    public:
-    AllocationNode(const char* const name, int script_id,
-                   const int start_position)
-        : script_id_(script_id),
+    AllocationNode(AllocationNode* parent, const char* name, int script_id,
+                   int start_position)
+        : parent_(parent),
+          script_id_(script_id),
           script_position_(start_position),
-          name_(name) {}
+          name_(name),
+          pinned_(false) {}
     ~AllocationNode() {
       for (auto child : children_) {
-        delete child;
+        delete child.second;
       }
     }
 
    private:
+    typedef uint64_t FunctionId;
+    static FunctionId function_id(int script_id, int start_position,
+                                  const char* name) {
+      // script_id == kNoScriptId case:
+      //   Use function name pointer as an id. Names derived from VM state
+      //   must not collide with the builtin names. The least significant bit
+      //   of the id is set to 1.
+      if (script_id == v8::UnboundScript::kNoScriptId) {
+        return reinterpret_cast<intptr_t>(name) | 1;
+      }
+      // script_id != kNoScriptId case:
+      //   Use script_id, start_position pair to uniquelly identify the node.
+      //   The least significant bit of the id is set to 0.
+      DCHECK(static_cast<unsigned>(start_position) < (1u << 31));
+      return (static_cast<uint64_t>(script_id) << 32) + (start_position << 1);
+    }
+    AllocationNode* FindOrAddChildNode(const char* name, int script_id,
+                                       int start_position);
+    // TODO(alph): make use of unordered_map's here. Pay attention to
+    // iterator invalidation during TranslateAllocationNode.
     std::map<size_t, unsigned int> allocations_;
-    std::vector<AllocationNode*> children_;
+    std::map<FunctionId, AllocationNode*> children_;
+    AllocationNode* const parent_;
     const int script_id_;
     const int script_position_;
     const char* const name_;
+    bool pinned_;
 
     friend class SamplingHeapProfiler;
 
@@ -110,12 +134,10 @@
   // loaded scripts keyed by their script id.
   v8::AllocationProfile::Node* TranslateAllocationNode(
       AllocationProfile* profile, SamplingHeapProfiler::AllocationNode* node,
-      const std::map<int, Script*>& scripts);
+      const std::map<int, Handle<Script>>& scripts);
   v8::AllocationProfile::Allocation ScaleSample(size_t size,
                                                 unsigned int count);
   AllocationNode* AddStack();
-  AllocationNode* FindOrAddChildNode(AllocationNode* parent, const char* name,
-                                     int script_id, int start_position);
 
   Isolate* const isolate_;
   Heap* const heap_;
@@ -126,6 +148,7 @@
   std::set<Sample*> samples_;
   const int stack_depth_;
   const uint64_t rate_;
+  v8::HeapProfiler::SamplingFlags flags_;
 
   friend class SamplingAllocationObserver;
 };
diff --git a/src/profiler/strings-storage.cc b/src/profiler/strings-storage.cc
index 9f095b8..634b6ee 100644
--- a/src/profiler/strings-storage.cc
+++ b/src/profiler/strings-storage.cc
@@ -22,7 +22,8 @@
 
 
 StringsStorage::~StringsStorage() {
-  for (HashMap::Entry* p = names_.Start(); p != NULL; p = names_.Next(p)) {
+  for (base::HashMap::Entry* p = names_.Start(); p != NULL;
+       p = names_.Next(p)) {
     DeleteArray(reinterpret_cast<const char*>(p->value));
   }
 }
@@ -30,7 +31,7 @@
 
 const char* StringsStorage::GetCopy(const char* src) {
   int len = static_cast<int>(strlen(src));
-  HashMap::Entry* entry = GetEntry(src, len);
+  base::HashMap::Entry* entry = GetEntry(src, len);
   if (entry->value == NULL) {
     Vector<char> dst = Vector<char>::New(len + 1);
     StrNCpy(dst, src, len);
@@ -52,7 +53,7 @@
 
 
 const char* StringsStorage::AddOrDisposeString(char* str, int len) {
-  HashMap::Entry* entry = GetEntry(str, len);
+  base::HashMap::Entry* entry = GetEntry(str, len);
   if (entry->value == NULL) {
     // New entry added.
     entry->key = str;
@@ -107,15 +108,15 @@
 
 size_t StringsStorage::GetUsedMemorySize() const {
   size_t size = sizeof(*this);
-  size += sizeof(HashMap::Entry) * names_.capacity();
-  for (HashMap::Entry* p = names_.Start(); p != NULL; p = names_.Next(p)) {
+  size += sizeof(base::HashMap::Entry) * names_.capacity();
+  for (base::HashMap::Entry* p = names_.Start(); p != NULL;
+       p = names_.Next(p)) {
     size += strlen(reinterpret_cast<const char*>(p->value)) + 1;
   }
   return size;
 }
 
-
-HashMap::Entry* StringsStorage::GetEntry(const char* str, int len) {
+base::HashMap::Entry* StringsStorage::GetEntry(const char* str, int len) {
   uint32_t hash = StringHasher::HashSequentialString(str, len, hash_seed_);
   return names_.LookupOrInsert(const_cast<char*>(str), hash);
 }
diff --git a/src/profiler/strings-storage.h b/src/profiler/strings-storage.h
index 7164cae..f98aa5e 100644
--- a/src/profiler/strings-storage.h
+++ b/src/profiler/strings-storage.h
@@ -5,8 +5,11 @@
 #ifndef V8_PROFILER_STRINGS_STORAGE_H_
 #define V8_PROFILER_STRINGS_STORAGE_H_
 
+#include <stdarg.h>
+
 #include "src/allocation.h"
-#include "src/hashmap.h"
+#include "src/base/compiler-specific.h"
+#include "src/base/hashmap.h"
 
 namespace v8 {
 namespace internal {
@@ -19,7 +22,8 @@
   ~StringsStorage();
 
   const char* GetCopy(const char* src);
-  const char* GetFormatted(const char* format, ...);
+  PRINTF_FORMAT(2, 3) const char* GetFormatted(const char* format, ...);
+  PRINTF_FORMAT(2, 0)
   const char* GetVFormatted(const char* format, va_list args);
   const char* GetName(Name* name);
   const char* GetName(int index);
@@ -32,10 +36,10 @@
 
   static bool StringsMatch(void* key1, void* key2);
   const char* AddOrDisposeString(char* str, int len);
-  HashMap::Entry* GetEntry(const char* str, int len);
+  base::HashMap::Entry* GetEntry(const char* str, int len);
 
   uint32_t hash_seed_;
-  HashMap names_;
+  base::HashMap names_;
 
   DISALLOW_COPY_AND_ASSIGN(StringsStorage);
 };
diff --git a/src/profiler/tick-sample.cc b/src/profiler/tick-sample.cc
new file mode 100644
index 0000000..4b48132
--- /dev/null
+++ b/src/profiler/tick-sample.cc
@@ -0,0 +1,226 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/profiler/tick-sample.h"
+
+#include "src/frames-inl.h"
+#include "src/vm-state-inl.h"
+
+
+namespace v8 {
+namespace internal {
+
+namespace {
+
+bool IsSamePage(byte* ptr1, byte* ptr2) {
+  const uint32_t kPageSize = 4096;
+  uintptr_t mask = ~static_cast<uintptr_t>(kPageSize - 1);
+  return (reinterpret_cast<uintptr_t>(ptr1) & mask) ==
+         (reinterpret_cast<uintptr_t>(ptr2) & mask);
+}
+
+// Check if the code at specified address could potentially be a
+// frame setup code.
+bool IsNoFrameRegion(Address address) {
+  struct Pattern {
+    int bytes_count;
+    byte bytes[8];
+    int offsets[4];
+  };
+  byte* pc = reinterpret_cast<byte*>(address);
+  static Pattern patterns[] = {
+#if V8_HOST_ARCH_IA32
+    // push %ebp
+    // mov %esp,%ebp
+    {3, {0x55, 0x89, 0xe5}, {0, 1, -1}},
+    // pop %ebp
+    // ret N
+    {2, {0x5d, 0xc2}, {0, 1, -1}},
+    // pop %ebp
+    // ret
+    {2, {0x5d, 0xc3}, {0, 1, -1}},
+#elif V8_HOST_ARCH_X64
+    // pushq %rbp
+    // movq %rsp,%rbp
+    {4, {0x55, 0x48, 0x89, 0xe5}, {0, 1, -1}},
+    // popq %rbp
+    // ret N
+    {2, {0x5d, 0xc2}, {0, 1, -1}},
+    // popq %rbp
+    // ret
+    {2, {0x5d, 0xc3}, {0, 1, -1}},
+#endif
+    {0, {}, {}}
+  };
+  for (Pattern* pattern = patterns; pattern->bytes_count; ++pattern) {
+    for (int* offset_ptr = pattern->offsets; *offset_ptr != -1; ++offset_ptr) {
+      int offset = *offset_ptr;
+      if (!offset || IsSamePage(pc, pc - offset)) {
+        MSAN_MEMORY_IS_INITIALIZED(pc - offset, pattern->bytes_count);
+        if (!memcmp(pc - offset, pattern->bytes, pattern->bytes_count))
+          return true;
+      } else {
+        // It is not safe to examine bytes on another page as it might not be
+        // allocated thus causing a SEGFAULT.
+        // Check the pattern part that's on the same page and
+        // pessimistically assume it could be the entire pattern match.
+        MSAN_MEMORY_IS_INITIALIZED(pc, pattern->bytes_count - offset);
+        if (!memcmp(pc, pattern->bytes + offset, pattern->bytes_count - offset))
+          return true;
+      }
+    }
+  }
+  return false;
+}
+
+}  // namespace
+
+//
+// StackTracer implementation
+//
+DISABLE_ASAN void TickSample::Init(Isolate* isolate,
+                                   const v8::RegisterState& regs,
+                                   RecordCEntryFrame record_c_entry_frame,
+                                   bool update_stats) {
+  timestamp = base::TimeTicks::HighResolutionNow();
+  this->update_stats = update_stats;
+
+  SampleInfo info;
+  if (GetStackSample(isolate, regs, record_c_entry_frame,
+                     reinterpret_cast<void**>(&stack[0]), kMaxFramesCount,
+                     &info)) {
+    state = info.vm_state;
+    pc = static_cast<Address>(regs.pc);
+    frames_count = static_cast<unsigned>(info.frames_count);
+    has_external_callback = info.external_callback_entry != nullptr;
+    if (has_external_callback) {
+      external_callback_entry =
+          static_cast<Address>(info.external_callback_entry);
+    } else if (frames_count) {
+      // sp register may point at an arbitrary place in memory, make
+      // sure MSAN doesn't complain about it.
+      MSAN_MEMORY_IS_INITIALIZED(regs.sp, sizeof(Address));
+      // Sample potential return address value for frameless invocation of
+      // stubs (we'll figure out later, if this value makes sense).
+      tos = Memory::Address_at(reinterpret_cast<Address>(regs.sp));
+    } else {
+      tos = nullptr;
+    }
+  } else {
+    // It is executing JS but failed to collect a stack trace.
+    // Mark the sample as spoiled.
+    timestamp = base::TimeTicks();
+    pc = nullptr;
+  }
+}
+
+bool TickSample::GetStackSample(Isolate* isolate, const v8::RegisterState& regs,
+                                RecordCEntryFrame record_c_entry_frame,
+                                void** frames, size_t frames_limit,
+                                v8::SampleInfo* sample_info) {
+  sample_info->frames_count = 0;
+  sample_info->vm_state = isolate->current_vm_state();
+  sample_info->external_callback_entry = nullptr;
+  if (sample_info->vm_state == GC) return true;
+
+  Address js_entry_sp = isolate->js_entry_sp();
+  if (js_entry_sp == 0) return true;  // Not executing JS now.
+
+  if (regs.pc && IsNoFrameRegion(static_cast<Address>(regs.pc))) {
+    // Can't collect stack.
+    return false;
+  }
+
+  ExternalCallbackScope* scope = isolate->external_callback_scope();
+  Address handler = Isolate::handler(isolate->thread_local_top());
+  // If there is a handler on top of the external callback scope then
+  // we have already entrered JavaScript again and the external callback
+  // is not the top function.
+  if (scope && scope->scope_address() < handler) {
+    sample_info->external_callback_entry =
+        *scope->callback_entrypoint_address();
+  }
+
+  SafeStackFrameIterator it(isolate, reinterpret_cast<Address>(regs.fp),
+                            reinterpret_cast<Address>(regs.sp), js_entry_sp);
+  size_t i = 0;
+  if (record_c_entry_frame == kIncludeCEntryFrame && !it.done() &&
+      it.top_frame_type() == StackFrame::EXIT) {
+    frames[i++] = isolate->c_function();
+  }
+  while (!it.done() && i < frames_limit) {
+    if (it.frame()->is_interpreted()) {
+      // For interpreted frames use the bytecode array pointer as the pc.
+      InterpretedFrame* frame = static_cast<InterpretedFrame*>(it.frame());
+      // Since the sampler can interrupt execution at any point the
+      // bytecode_array might be garbage, so don't dereference it.
+      Address bytecode_array =
+          reinterpret_cast<Address>(frame->GetBytecodeArray()) - kHeapObjectTag;
+      frames[i++] = bytecode_array + BytecodeArray::kHeaderSize +
+                    frame->GetBytecodeOffset();
+    } else {
+      frames[i++] = it.frame()->pc();
+    }
+    it.Advance();
+  }
+  sample_info->frames_count = i;
+  return true;
+}
+
+#if defined(USE_SIMULATOR)
+bool SimulatorHelper::FillRegisters(Isolate* isolate,
+                                    v8::RegisterState* state) {
+  Simulator *simulator = isolate->thread_local_top()->simulator_;
+  // Check if there is active simulator.
+  if (simulator == NULL) return false;
+#if V8_TARGET_ARCH_ARM
+  if (!simulator->has_bad_pc()) {
+    state->pc = reinterpret_cast<Address>(simulator->get_pc());
+  }
+  state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
+  state->fp = reinterpret_cast<Address>(simulator->get_register(
+      Simulator::r11));
+#elif V8_TARGET_ARCH_ARM64
+  state->pc = reinterpret_cast<Address>(simulator->pc());
+  state->sp = reinterpret_cast<Address>(simulator->sp());
+  state->fp = reinterpret_cast<Address>(simulator->fp());
+#elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
+  if (!simulator->has_bad_pc()) {
+    state->pc = reinterpret_cast<Address>(simulator->get_pc());
+  }
+  state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
+  state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
+#elif V8_TARGET_ARCH_PPC
+  if (!simulator->has_bad_pc()) {
+    state->pc = reinterpret_cast<Address>(simulator->get_pc());
+  }
+  state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
+  state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
+#elif V8_TARGET_ARCH_S390
+  if (!simulator->has_bad_pc()) {
+    state->pc = reinterpret_cast<Address>(simulator->get_pc());
+  }
+  state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
+  state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
+#endif
+  if (state->sp == 0 || state->fp == 0) {
+    // It possible that the simulator is interrupted while it is updating
+    // the sp or fp register. ARM64 simulator does this in two steps:
+    // first setting it to zero and then setting it to the new value.
+    // Bailout if sp/fp doesn't contain the new value.
+    //
+    // FIXME: The above doesn't really solve the issue.
+    // If a 64-bit target is executed on a 32-bit host even the final
+    // write is non-atomic, so it might obtain a half of the result.
+    // Moreover as long as the register set code uses memcpy (as of now),
+    // it is not guaranteed to be atomic even when both host and target
+    // are of same bitness.
+    return false;
+  }
+  return true;
+}
+#endif  // USE_SIMULATOR
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/profiler/tick-sample.h b/src/profiler/tick-sample.h
new file mode 100644
index 0000000..0a651af
--- /dev/null
+++ b/src/profiler/tick-sample.h
@@ -0,0 +1,74 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_PROFILER_TICK_SAMPLE_H_
+#define V8_PROFILER_TICK_SAMPLE_H_
+
+#include "include/v8.h"
+
+#include "src/base/platform/time.h"
+#include "src/frames.h"
+#include "src/globals.h"
+
+namespace v8 {
+namespace internal {
+
+class Isolate;
+
+// ----------------------------------------------------------------------------
+// Sampler
+//
+// A sampler periodically samples the state of the VM and optionally
+// (if used for profiling) the program counter and stack pointer for
+// the thread that created it.
+
+// TickSample captures the information collected for each sample.
+struct TickSample {
+  // Internal profiling (with --prof + tools/$OS-tick-processor) wants to
+  // include the runtime function we're calling. Externally exposed tick
+  // samples don't care.
+  enum RecordCEntryFrame { kIncludeCEntryFrame, kSkipCEntryFrame };
+
+  TickSample()
+      : state(OTHER),
+        pc(NULL),
+        external_callback_entry(NULL),
+        frames_count(0),
+        has_external_callback(false),
+        update_stats(true) {}
+  void Init(Isolate* isolate, const v8::RegisterState& state,
+            RecordCEntryFrame record_c_entry_frame, bool update_stats);
+  static bool GetStackSample(Isolate* isolate, const v8::RegisterState& state,
+                             RecordCEntryFrame record_c_entry_frame,
+                             void** frames, size_t frames_limit,
+                             v8::SampleInfo* sample_info);
+  StateTag state;  // The state of the VM.
+  Address pc;      // Instruction pointer.
+  union {
+    Address tos;   // Top stack value (*sp).
+    Address external_callback_entry;
+  };
+  static const unsigned kMaxFramesCountLog2 = 8;
+  static const unsigned kMaxFramesCount = (1 << kMaxFramesCountLog2) - 1;
+  Address stack[kMaxFramesCount];  // Call stack.
+  base::TimeTicks timestamp;
+  unsigned frames_count : kMaxFramesCountLog2;  // Number of captured frames.
+  bool has_external_callback : 1;
+  bool update_stats : 1;  // Whether the sample should update aggregated stats.
+};
+
+
+#if defined(USE_SIMULATOR)
+class SimulatorHelper {
+ public:
+  // Returns true if register values were successfully retrieved
+  // from the simulator, otherwise returns false.
+  static bool FillRegisters(Isolate* isolate, v8::RegisterState* state);
+};
+#endif  // USE_SIMULATOR
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_PROFILER_TICK_SAMPLE_H_
diff --git a/src/property-descriptor.cc b/src/property-descriptor.cc
index 31efb41..f22a263 100644
--- a/src/property-descriptor.cc
+++ b/src/property-descriptor.cc
@@ -249,7 +249,7 @@
   if (!getter.is_null()) {
     // 18c. If IsCallable(getter) is false and getter is not undefined,
     // throw a TypeError exception.
-    if (!getter->IsCallable() && !getter->IsUndefined()) {
+    if (!getter->IsCallable() && !getter->IsUndefined(isolate)) {
       isolate->Throw(*isolate->factory()->NewTypeError(
           MessageTemplate::kObjectGetterCallable, getter));
       return false;
@@ -267,7 +267,7 @@
   if (!setter.is_null()) {
     // 21c. If IsCallable(setter) is false and setter is not undefined,
     // throw a TypeError exception.
-    if (!setter->IsCallable() && !setter->IsUndefined()) {
+    if (!setter->IsCallable() && !setter->IsUndefined(isolate)) {
       isolate->Throw(*isolate->factory()->NewTypeError(
           MessageTemplate::kObjectSetterCallable, setter));
       return false;
diff --git a/src/property-details.h b/src/property-details.h
index fdf2c6c..e30d668 100644
--- a/src/property-details.h
+++ b/src/property-details.h
@@ -28,11 +28,6 @@
   // ABSENT can never be stored in or returned from a descriptor's attributes
   // bitfield.  It is only used as a return value meaning the attributes of
   // a non-existent property.
-
-  // When creating a property, EVAL_DECLARED used to indicate that the property
-  // came from a sloppy-mode direct eval, and certain checks need to be done.
-  // Cannot be stored in or returned from a descriptor's attributes bitfield.
-  EVAL_DECLARED = 128
 };
 
 
@@ -53,7 +48,18 @@
 STATIC_ASSERT(ONLY_CONFIGURABLE == static_cast<PropertyFilter>(DONT_DELETE));
 STATIC_ASSERT(((SKIP_STRINGS | SKIP_SYMBOLS | ONLY_ALL_CAN_READ) &
                ALL_ATTRIBUTES_MASK) == 0);
-
+STATIC_ASSERT(ALL_PROPERTIES ==
+              static_cast<PropertyFilter>(v8::PropertyFilter::ALL_PROPERTIES));
+STATIC_ASSERT(ONLY_WRITABLE ==
+              static_cast<PropertyFilter>(v8::PropertyFilter::ONLY_WRITABLE));
+STATIC_ASSERT(ONLY_ENUMERABLE ==
+              static_cast<PropertyFilter>(v8::PropertyFilter::ONLY_ENUMERABLE));
+STATIC_ASSERT(ONLY_CONFIGURABLE == static_cast<PropertyFilter>(
+                                       v8::PropertyFilter::ONLY_CONFIGURABLE));
+STATIC_ASSERT(SKIP_STRINGS ==
+              static_cast<PropertyFilter>(v8::PropertyFilter::SKIP_STRINGS));
+STATIC_ASSERT(SKIP_SYMBOLS ==
+              static_cast<PropertyFilter>(v8::PropertyFilter::SKIP_SYMBOLS));
 
 class Smi;
 class Type;
diff --git a/src/prototype.h b/src/prototype.h
index e09ff0f..032d9b6 100644
--- a/src/prototype.h
+++ b/src/prototype.h
@@ -25,14 +25,12 @@
 
 class PrototypeIterator {
  public:
-  enum WhereToStart { START_AT_RECEIVER, START_AT_PROTOTYPE };
-
   enum WhereToEnd { END_AT_NULL, END_AT_NON_HIDDEN };
 
   const int kProxyPrototypeLimit = 100 * 1000;
 
   PrototypeIterator(Isolate* isolate, Handle<JSReceiver> receiver,
-                    WhereToStart where_to_start = START_AT_PROTOTYPE,
+                    WhereToStart where_to_start = kStartAtPrototype,
                     WhereToEnd where_to_end = END_AT_NULL)
       : object_(NULL),
         handle_(receiver),
@@ -41,32 +39,34 @@
         is_at_end_(false),
         seen_proxies_(0) {
     CHECK(!handle_.is_null());
-    if (where_to_start == START_AT_PROTOTYPE) Advance();
+    if (where_to_start == kStartAtPrototype) Advance();
   }
 
   PrototypeIterator(Isolate* isolate, JSReceiver* receiver,
-                    WhereToStart where_to_start = START_AT_PROTOTYPE,
+                    WhereToStart where_to_start = kStartAtPrototype,
                     WhereToEnd where_to_end = END_AT_NULL)
       : object_(receiver),
         isolate_(isolate),
         where_to_end_(where_to_end),
         is_at_end_(false),
         seen_proxies_(0) {
-    if (where_to_start == START_AT_PROTOTYPE) Advance();
+    if (where_to_start == kStartAtPrototype) Advance();
   }
 
   explicit PrototypeIterator(Map* receiver_map)
       : object_(receiver_map->prototype()),
         isolate_(receiver_map->GetIsolate()),
         where_to_end_(END_AT_NULL),
-        is_at_end_(object_->IsNull()) {}
+        is_at_end_(object_->IsNull(isolate_)),
+        seen_proxies_(0) {}
 
   explicit PrototypeIterator(Handle<Map> receiver_map)
       : object_(NULL),
         handle_(handle(receiver_map->prototype(), receiver_map->GetIsolate())),
         isolate_(receiver_map->GetIsolate()),
         where_to_end_(END_AT_NULL),
-        is_at_end_(handle_->IsNull()) {}
+        is_at_end_(handle_->IsNull(isolate_)),
+        seen_proxies_(0) {}
 
   ~PrototypeIterator() {}
 
@@ -114,7 +114,7 @@
     Object* prototype = map->prototype();
     is_at_end_ = where_to_end_ == END_AT_NON_HIDDEN
                      ? !map->has_hidden_prototype()
-                     : prototype->IsNull();
+                     : prototype->IsNull(isolate_);
 
     if (handle_.is_null()) {
       object_ = prototype;
@@ -153,7 +153,8 @@
     MaybeHandle<Object> proto =
         JSProxy::GetPrototype(Handle<JSProxy>::cast(handle_));
     if (!proto.ToHandle(&handle_)) return false;
-    is_at_end_ = where_to_end_ == END_AT_NON_HIDDEN || handle_->IsNull();
+    is_at_end_ =
+        where_to_end_ == END_AT_NON_HIDDEN || handle_->IsNull(isolate_);
     return true;
   }
 
diff --git a/src/regexp/arm/regexp-macro-assembler-arm.cc b/src/regexp/arm/regexp-macro-assembler-arm.cc
index f8dfc97..bf762b5 100644
--- a/src/regexp/arm/regexp-macro-assembler-arm.cc
+++ b/src/regexp/arm/regexp-macro-assembler-arm.cc
@@ -9,7 +9,6 @@
 #include "src/code-stubs.h"
 #include "src/log.h"
 #include "src/macro-assembler.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/regexp/regexp-macro-assembler.h"
 #include "src/regexp/regexp-stack.h"
 #include "src/unicode.h"
diff --git a/src/regexp/arm64/regexp-macro-assembler-arm64.cc b/src/regexp/arm64/regexp-macro-assembler-arm64.cc
index e8bdad8..96d0c25 100644
--- a/src/regexp/arm64/regexp-macro-assembler-arm64.cc
+++ b/src/regexp/arm64/regexp-macro-assembler-arm64.cc
@@ -9,7 +9,6 @@
 #include "src/code-stubs.h"
 #include "src/log.h"
 #include "src/macro-assembler.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/regexp/regexp-macro-assembler.h"
 #include "src/regexp/regexp-stack.h"
 #include "src/unicode.h"
diff --git a/src/regexp/ia32/regexp-macro-assembler-ia32.cc b/src/regexp/ia32/regexp-macro-assembler-ia32.cc
index 9c55af6..6b4ea24 100644
--- a/src/regexp/ia32/regexp-macro-assembler-ia32.cc
+++ b/src/regexp/ia32/regexp-macro-assembler-ia32.cc
@@ -8,7 +8,6 @@
 
 #include "src/log.h"
 #include "src/macro-assembler.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/regexp/regexp-macro-assembler.h"
 #include "src/regexp/regexp-stack.h"
 #include "src/unicode.h"
diff --git a/src/regexp/jsregexp.cc b/src/regexp/jsregexp.cc
index ddb4a16..c3b670b 100644
--- a/src/regexp/jsregexp.cc
+++ b/src/regexp/jsregexp.cc
@@ -397,6 +397,7 @@
 
   Handle<FixedArray> data = Handle<FixedArray>(FixedArray::cast(re->data()));
   data->set(JSRegExp::code_index(is_one_byte), result.code);
+  SetIrregexpCaptureNameMap(*data, compile_data.capture_name_map);
   int register_max = IrregexpMaxRegisterCount(*data);
   if (result.num_registers > register_max) {
     SetIrregexpMaxRegisterCount(*data, result.num_registers);
@@ -416,6 +417,14 @@
   re->set(JSRegExp::kIrregexpMaxRegisterCountIndex, Smi::FromInt(value));
 }
 
+void RegExpImpl::SetIrregexpCaptureNameMap(FixedArray* re,
+                                           Handle<FixedArray> value) {
+  if (value.is_null()) {
+    re->set(JSRegExp::kIrregexpCaptureNameMapIndex, Smi::FromInt(0));
+  } else {
+    re->set(JSRegExp::kIrregexpCaptureNameMapIndex, *value);
+  }
+}
 
 int RegExpImpl::IrregexpNumberOfCaptures(FixedArray* re) {
   return Smi::cast(re->get(JSRegExp::kIrregexpCaptureCountIndex))->value();
@@ -5159,8 +5168,10 @@
       ranges = negated;
     }
     if (ranges->length() == 0) {
-      // No matches possible.
-      return new (zone) EndNode(EndNode::BACKTRACK, zone);
+      ranges->Add(CharacterRange::Everything(), zone);
+      RegExpCharacterClass* fail =
+          new (zone) RegExpCharacterClass(ranges, true);
+      return new (zone) TextNode(fail, compiler->read_backward(), on_success);
     }
     if (standard_type() == '*') {
       return UnanchoredAdvance(compiler, on_success);
@@ -5879,6 +5890,7 @@
 void CharacterRange::AddCaseEquivalents(Isolate* isolate, Zone* zone,
                                         ZoneList<CharacterRange>* ranges,
                                         bool is_one_byte) {
+  CharacterRange::Canonicalize(ranges);
   int range_count = ranges->length();
   for (int i = 0; i < range_count; i++) {
     CharacterRange range = ranges->at(i);
@@ -6762,7 +6774,7 @@
   Heap* heap = pattern->GetHeap();
   bool too_much = pattern->length() > RegExpImpl::kRegExpTooLargeToOptimize;
   if (heap->total_regexp_code_generated() > RegExpImpl::kRegExpCompiledLimit &&
-      heap->isolate()->memory_allocator()->SizeExecutable() >
+      heap->memory_allocator()->SizeExecutable() >
           RegExpImpl::kRegExpExecutableMemoryLimit) {
     too_much = true;
   }
diff --git a/src/regexp/jsregexp.h b/src/regexp/jsregexp.h
index e55d650..dc8aee1 100644
--- a/src/regexp/jsregexp.h
+++ b/src/regexp/jsregexp.h
@@ -196,6 +196,8 @@
   // For acting on the JSRegExp data FixedArray.
   static int IrregexpMaxRegisterCount(FixedArray* re);
   static void SetIrregexpMaxRegisterCount(FixedArray* re, int value);
+  static void SetIrregexpCaptureNameMap(FixedArray* re,
+                                        Handle<FixedArray> value);
   static int IrregexpNumberOfCaptures(FixedArray* re);
   static int IrregexpNumberOfRegisters(FixedArray* re);
   static ByteArray* IrregexpByteCode(FixedArray* re, bool is_one_byte);
@@ -1530,6 +1532,7 @@
   RegExpNode* node;
   bool simple;
   bool contains_anchor;
+  Handle<FixedArray> capture_name_map;
   Handle<String> error;
   int capture_count;
 };
diff --git a/src/regexp/ppc/OWNERS b/src/regexp/ppc/OWNERS
index eb007cb..752e8e3 100644
--- a/src/regexp/ppc/OWNERS
+++ b/src/regexp/ppc/OWNERS
@@ -3,3 +3,4 @@
 joransiu@ca.ibm.com
 mbrandy@us.ibm.com
 michael_dawson@ca.ibm.com
+bjaideep@ca.ibm.com
diff --git a/src/regexp/ppc/regexp-macro-assembler-ppc.cc b/src/regexp/ppc/regexp-macro-assembler-ppc.cc
index 70842f5..a7418dd 100644
--- a/src/regexp/ppc/regexp-macro-assembler-ppc.cc
+++ b/src/regexp/ppc/regexp-macro-assembler-ppc.cc
@@ -10,7 +10,6 @@
 #include "src/code-stubs.h"
 #include "src/log.h"
 #include "src/macro-assembler.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/regexp/regexp-macro-assembler.h"
 #include "src/regexp/regexp-stack.h"
 #include "src/unicode.h"
diff --git a/src/regexp/regexp-ast.h b/src/regexp/regexp-ast.h
index 0e718d3..406bf84 100644
--- a/src/regexp/regexp-ast.h
+++ b/src/regexp/regexp-ast.h
@@ -7,6 +7,7 @@
 
 #include "src/objects.h"
 #include "src/utils.h"
+#include "src/zone-containers.h"
 #include "src/zone.h"
 
 namespace v8 {
@@ -296,7 +297,10 @@
   bool IsCharacterClass() override;
   bool IsTextElement() override { return true; }
   int min_match() override { return 1; }
-  int max_match() override { return 1; }
+  // The character class may match two code units for unicode regexps.
+  // TODO(yangguo): we should split this class for usage in TextElement, and
+  //                make max_match() dependent on the character class content.
+  int max_match() override { return 2; }
   void AppendToText(RegExpText* text, Zone* zone) override;
   CharacterSet character_set() { return set_; }
   // TODO(lrn): Remove need for complex version if is_standard that
@@ -409,7 +413,8 @@
 
 class RegExpCapture final : public RegExpTree {
  public:
-  explicit RegExpCapture(int index) : body_(NULL), index_(index) {}
+  explicit RegExpCapture(int index)
+      : body_(NULL), index_(index), name_(nullptr) {}
   void* Accept(RegExpVisitor* visitor, void* data) override;
   RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
   static RegExpNode* ToNode(RegExpTree* body, int index,
@@ -424,12 +429,15 @@
   RegExpTree* body() { return body_; }
   void set_body(RegExpTree* body) { body_ = body; }
   int index() { return index_; }
+  const ZoneVector<uc16>* name() const { return name_; }
+  void set_name(const ZoneVector<uc16>* name) { name_ = name; }
   static int StartRegister(int index) { return index * 2; }
   static int EndRegister(int index) { return index * 2 + 1; }
 
  private:
   RegExpTree* body_;
   int index_;
+  const ZoneVector<uc16>* name_;
 };
 
 
@@ -486,7 +494,9 @@
 
 class RegExpBackReference final : public RegExpTree {
  public:
-  explicit RegExpBackReference(RegExpCapture* capture) : capture_(capture) {}
+  RegExpBackReference() : capture_(nullptr), name_(nullptr) {}
+  explicit RegExpBackReference(RegExpCapture* capture)
+      : capture_(capture), name_(nullptr) {}
   void* Accept(RegExpVisitor* visitor, void* data) override;
   RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
   RegExpBackReference* AsBackReference() override;
@@ -497,9 +507,13 @@
   int max_match() override { return kInfinity; }
   int index() { return capture_->index(); }
   RegExpCapture* capture() { return capture_; }
+  void set_capture(RegExpCapture* capture) { capture_ = capture; }
+  const ZoneVector<uc16>* name() const { return name_; }
+  void set_name(const ZoneVector<uc16>* name) { name_ = name; }
 
  private:
   RegExpCapture* capture_;
+  const ZoneVector<uc16>* name_;
 };
 
 
diff --git a/src/regexp/regexp-macro-assembler.cc b/src/regexp/regexp-macro-assembler.cc
index 9bb5073..19ecaed 100644
--- a/src/regexp/regexp-macro-assembler.cc
+++ b/src/regexp/regexp-macro-assembler.cc
@@ -100,6 +100,15 @@
   Bind(&ok);
 }
 
+void RegExpMacroAssembler::CheckPosition(int cp_offset,
+                                         Label* on_outside_input) {
+  LoadCurrentCharacter(cp_offset, on_outside_input, true);
+}
+
+bool RegExpMacroAssembler::CheckSpecialCharacterClass(uc16 type,
+                                                      Label* on_no_match) {
+  return false;
+}
 
 #ifndef V8_INTERPRETED_REGEXP  // Avoid unused code, e.g., on ARM.
 
@@ -168,7 +177,7 @@
     return_value = RETRY;
   } else {
     Object* result = isolate->stack_guard()->HandleInterrupts();
-    if (result->IsException()) return_value = EXCEPTION;
+    if (result->IsException(isolate)) return_value = EXCEPTION;
   }
 
   DisallowHeapAllocation no_gc;
diff --git a/src/regexp/regexp-macro-assembler.h b/src/regexp/regexp-macro-assembler.h
index 2aa439e..76efdf9 100644
--- a/src/regexp/regexp-macro-assembler.h
+++ b/src/regexp/regexp-macro-assembler.h
@@ -113,12 +113,12 @@
 
   // Checks whether the given offset from the current position is before
   // the end of the string.  May overwrite the current character.
-  virtual void CheckPosition(int cp_offset, Label* on_outside_input) = 0;
+  virtual void CheckPosition(int cp_offset, Label* on_outside_input);
   // Check whether a standard/default character class matches the current
   // character. Returns false if the type of special character class does
   // not have custom support.
   // May clobber the current loaded character.
-  virtual bool CheckSpecialCharacterClass(uc16 type, Label* on_no_match) = 0;
+  virtual bool CheckSpecialCharacterClass(uc16 type, Label* on_no_match);
   virtual void Fail() = 0;
   virtual Handle<HeapObject> GetCode(Handle<String> source) = 0;
   virtual void GoTo(Label* label) = 0;
diff --git a/src/regexp/regexp-parser.cc b/src/regexp/regexp-parser.cc
index d433fc8..dba81ae 100644
--- a/src/regexp/regexp-parser.cc
+++ b/src/regexp/regexp-parser.cc
@@ -25,6 +25,8 @@
       zone_(zone),
       error_(error),
       captures_(NULL),
+      named_captures_(NULL),
+      named_back_references_(NULL),
       in_(in),
       current_(kEndMarker),
       ignore_case_(flags & JSRegExp::kIgnoreCase),
@@ -73,7 +75,8 @@
   if (has_next()) {
     StackLimitCheck check(isolate());
     if (check.HasOverflowed()) {
-      ReportError(CStrVector(Isolate::kStackOverflowMessage));
+      ReportError(CStrVector(
+          MessageTemplate::TemplateString(MessageTemplate::kStackOverflow)));
     } else if (zone()->excess_allocation()) {
       ReportError(CStrVector("Regular expression too large"));
     } else {
@@ -130,6 +133,7 @@
 
 
 RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
+  if (failed_) return NULL;  // Do not overwrite any existing error.
   failed_ = true;
   *error_ = isolate()->factory()->NewStringFromAscii(message).ToHandleChecked();
   // Zip to the end to make sure the no more input is read.
@@ -148,6 +152,7 @@
 //   Disjunction
 RegExpTree* RegExpParser::ParsePattern() {
   RegExpTree* result = ParseDisjunction(CHECK_FAILED);
+  PatchNamedBackReferences(CHECK_FAILED);
   DCHECK(!has_more());
   // If the result of parsing is a literal string atom, and it has the
   // same length as the input, then the atom is identical to the input.
@@ -171,7 +176,7 @@
 RegExpTree* RegExpParser::ParseDisjunction() {
   // Used to store current state while parsing subexpressions.
   RegExpParserState initial_state(NULL, INITIAL, RegExpLookaround::LOOKAHEAD, 0,
-                                  ignore_case(), unicode(), zone());
+                                  nullptr, ignore_case(), unicode(), zone());
   RegExpParserState* state = &initial_state;
   // Cache the builder in a local variable for quick access.
   RegExpBuilder* builder = initial_state.builder();
@@ -203,6 +208,10 @@
 
         // Build result of subexpression.
         if (group_type == CAPTURE) {
+          if (state->IsNamedCapture()) {
+            CreateNamedCaptureAtIndex(state->capture_name(),
+                                      capture_index CHECK_FAILED);
+          }
           RegExpCapture* capture = GetCapture(capture_index);
           capture->set_body(body);
           body = capture;
@@ -267,47 +276,65 @@
       case '(': {
         SubexpressionType subexpr_type = CAPTURE;
         RegExpLookaround::Type lookaround_type = state->lookaround_type();
+        bool is_named_capture = false;
         Advance();
         if (current() == '?') {
           switch (Next()) {
             case ':':
               subexpr_type = GROUPING;
+              Advance(2);
               break;
             case '=':
               lookaround_type = RegExpLookaround::LOOKAHEAD;
               subexpr_type = POSITIVE_LOOKAROUND;
+              Advance(2);
               break;
             case '!':
               lookaround_type = RegExpLookaround::LOOKAHEAD;
               subexpr_type = NEGATIVE_LOOKAROUND;
+              Advance(2);
               break;
             case '<':
+              Advance();
               if (FLAG_harmony_regexp_lookbehind) {
-                Advance();
-                lookaround_type = RegExpLookaround::LOOKBEHIND;
                 if (Next() == '=') {
                   subexpr_type = POSITIVE_LOOKAROUND;
+                  lookaround_type = RegExpLookaround::LOOKBEHIND;
+                  Advance(2);
                   break;
                 } else if (Next() == '!') {
                   subexpr_type = NEGATIVE_LOOKAROUND;
+                  lookaround_type = RegExpLookaround::LOOKBEHIND;
+                  Advance(2);
                   break;
                 }
               }
+              if (FLAG_harmony_regexp_named_captures && unicode()) {
+                is_named_capture = true;
+                Advance();
+                break;
+              }
             // Fall through.
             default:
               return ReportError(CStrVector("Invalid group"));
           }
-          Advance(2);
-        } else {
+        }
+
+        const ZoneVector<uc16>* capture_name = nullptr;
+        if (subexpr_type == CAPTURE) {
           if (captures_started_ >= kMaxCaptures) {
             return ReportError(CStrVector("Too many captures"));
           }
           captures_started_++;
+
+          if (is_named_capture) {
+            capture_name = ParseCaptureGroupName(CHECK_FAILED);
+          }
         }
         // Store current state and begin new disjunction parsing.
         state = new (zone()) RegExpParserState(
             state, subexpr_type, lookaround_type, captures_started_,
-            ignore_case(), unicode(), zone());
+            capture_name, ignore_case(), unicode(), zone());
         builder = state->builder();
         continue;
       }
@@ -361,11 +388,11 @@
               if (FLAG_harmony_regexp_property) {
                 ZoneList<CharacterRange>* ranges =
                     new (zone()) ZoneList<CharacterRange>(2, zone());
-                if (!ParsePropertyClass(ranges)) {
+                if (!ParsePropertyClass(ranges, p == 'P')) {
                   return ReportError(CStrVector("Invalid property name"));
                 }
                 RegExpCharacterClass* cc =
-                    new (zone()) RegExpCharacterClass(ranges, p == 'P');
+                    new (zone()) RegExpCharacterClass(ranges, false);
                 builder->AddCharacterClass(cc);
               } else {
                 // With /u, no identity escapes except for syntax characters
@@ -415,7 +442,7 @@
               break;
             }
           }
-          // FALLTHROUGH
+          // Fall through.
           case '0': {
             Advance();
             if (unicode() && Next() >= '0' && Next() <= '9') {
@@ -496,6 +523,13 @@
             }
             break;
           }
+          case 'k':
+            if (FLAG_harmony_regexp_named_captures && unicode()) {
+              Advance(2);
+              ParseNamedBackReference(builder, state CHECK_FAILED);
+              break;
+            }
+          // Fall through.
           default:
             Advance();
             // With /u, no identity escapes except for syntax characters
@@ -511,17 +545,16 @@
         break;
       case '{': {
         int dummy;
-        if (ParseIntervalQuantifier(&dummy, &dummy)) {
-          return ReportError(CStrVector("Nothing to repeat"));
-        }
-        // fallthrough
+        bool parsed = ParseIntervalQuantifier(&dummy, &dummy CHECK_FAILED);
+        if (parsed) return ReportError(CStrVector("Nothing to repeat"));
+        // Fall through.
       }
       case '}':
       case ']':
         if (unicode()) {
           return ReportError(CStrVector("Lone quantifier brackets"));
         }
-      // fallthrough
+      // Fall through.
       default:
         builder->AddUnicodeCharacter(current());
         Advance();
@@ -675,6 +708,148 @@
   return true;
 }
 
+static void push_code_unit(ZoneVector<uc16>* v, uint32_t code_unit) {
+  if (code_unit <= unibrow::Utf16::kMaxNonSurrogateCharCode) {
+    v->push_back(code_unit);
+  } else {
+    v->push_back(unibrow::Utf16::LeadSurrogate(code_unit));
+    v->push_back(unibrow::Utf16::TrailSurrogate(code_unit));
+  }
+}
+
+const ZoneVector<uc16>* RegExpParser::ParseCaptureGroupName() {
+  DCHECK(FLAG_harmony_regexp_named_captures);
+  DCHECK(unicode());
+
+  ZoneVector<uc16>* name =
+      new (zone()->New(sizeof(ZoneVector<uc16>))) ZoneVector<uc16>(zone());
+
+  bool at_start = true;
+  while (true) {
+    uc32 c = current();
+    Advance();
+
+    // Convert unicode escapes.
+    if (c == '\\' && current() == 'u') {
+      Advance();
+      if (!ParseUnicodeEscape(&c)) {
+        ReportError(CStrVector("Invalid Unicode escape sequence"));
+        return nullptr;
+      }
+    }
+
+    if (at_start) {
+      if (!IdentifierStart::Is(c)) {
+        ReportError(CStrVector("Invalid capture group name"));
+        return nullptr;
+      }
+      push_code_unit(name, c);
+      at_start = false;
+    } else {
+      if (c == '>') {
+        break;
+      } else if (IdentifierPart::Is(c)) {
+        push_code_unit(name, c);
+      } else {
+        ReportError(CStrVector("Invalid capture group name"));
+        return nullptr;
+      }
+    }
+  }
+
+  return name;
+}
+
+bool RegExpParser::CreateNamedCaptureAtIndex(const ZoneVector<uc16>* name,
+                                             int index) {
+  DCHECK(FLAG_harmony_regexp_named_captures);
+  DCHECK(unicode());
+  DCHECK(0 < index && index <= captures_started_);
+  DCHECK_NOT_NULL(name);
+
+  if (named_captures_ == nullptr) {
+    named_captures_ = new (zone()) ZoneList<RegExpCapture*>(1, zone());
+  } else {
+    // Check for duplicates and bail if we find any.
+    for (const auto& named_capture : *named_captures_) {
+      if (*named_capture->name() == *name) {
+        ReportError(CStrVector("Duplicate capture group name"));
+        return false;
+      }
+    }
+  }
+
+  RegExpCapture* capture = GetCapture(index);
+  DCHECK(capture->name() == nullptr);
+
+  capture->set_name(name);
+  named_captures_->Add(capture, zone());
+
+  return true;
+}
+
+bool RegExpParser::ParseNamedBackReference(RegExpBuilder* builder,
+                                           RegExpParserState* state) {
+  // The parser is assumed to be on the '<' in \k<name>.
+  if (current() != '<') {
+    ReportError(CStrVector("Invalid named reference"));
+    return false;
+  }
+
+  Advance();
+  const ZoneVector<uc16>* name = ParseCaptureGroupName();
+  if (name == nullptr) {
+    return false;
+  }
+
+  if (state->IsInsideCaptureGroup(name)) {
+    builder->AddEmpty();
+  } else {
+    RegExpBackReference* atom = new (zone()) RegExpBackReference();
+    atom->set_name(name);
+
+    builder->AddAtom(atom);
+
+    if (named_back_references_ == nullptr) {
+      named_back_references_ =
+          new (zone()) ZoneList<RegExpBackReference*>(1, zone());
+    }
+    named_back_references_->Add(atom, zone());
+  }
+
+  return true;
+}
+
+void RegExpParser::PatchNamedBackReferences() {
+  if (named_back_references_ == nullptr) return;
+
+  if (named_captures_ == nullptr) {
+    ReportError(CStrVector("Invalid named capture referenced"));
+    return;
+  }
+
+  // Look up and patch the actual capture for each named back reference.
+  // TODO(jgruber): O(n^2), optimize if necessary.
+
+  for (int i = 0; i < named_back_references_->length(); i++) {
+    RegExpBackReference* ref = named_back_references_->at(i);
+
+    int index = -1;
+    for (const auto& capture : *named_captures_) {
+      if (*capture->name() == *ref->name()) {
+        index = capture->index();
+        break;
+      }
+    }
+
+    if (index == -1) {
+      ReportError(CStrVector("Invalid named capture referenced"));
+      return;
+    }
+
+    ref->set_capture(GetCapture(index));
+  }
+}
 
 RegExpCapture* RegExpParser::GetCapture(int index) {
   // The index for the capture groups are one-based. Its index in the list is
@@ -691,6 +866,24 @@
   return captures_->at(index - 1);
 }
 
+Handle<FixedArray> RegExpParser::CreateCaptureNameMap() {
+  if (named_captures_ == nullptr || named_captures_->is_empty())
+    return Handle<FixedArray>();
+
+  Factory* factory = isolate()->factory();
+
+  int len = named_captures_->length() * 2;
+  Handle<FixedArray> array = factory->NewFixedArray(len);
+
+  for (int i = 0; i < named_captures_->length(); i++) {
+    RegExpCapture* capture = named_captures_->at(i);
+    MaybeHandle<String> name = factory->NewStringFromTwoByte(capture->name());
+    array->set(i * 2, *name.ToHandleChecked());
+    array->set(i * 2 + 1, Smi::FromInt(capture->index()));
+  }
+
+  return array;
+}
 
 bool RegExpParser::RegExpParserState::IsInsideCaptureGroup(int index) {
   for (RegExpParserState* s = this; s != NULL; s = s->previous_state()) {
@@ -703,6 +896,15 @@
   return false;
 }
 
+bool RegExpParser::RegExpParserState::IsInsideCaptureGroup(
+    const ZoneVector<uc16>* name) {
+  DCHECK_NOT_NULL(name);
+  for (RegExpParserState* s = this; s != NULL; s = s->previous_state()) {
+    if (s->capture_name() == nullptr) continue;
+    if (*s->capture_name() == *name) return true;
+  }
+  return false;
+}
 
 // QuantifierPrefix ::
 //   { DecimalDigits }
@@ -845,29 +1047,49 @@
 }
 
 #ifdef V8_I18N_SUPPORT
-bool IsExactPropertyValueAlias(const char* property_name, UProperty property,
-                               int32_t property_value) {
-  const char* short_name =
-      u_getPropertyValueName(property, property_value, U_SHORT_PROPERTY_NAME);
+
+namespace {
+
+bool IsExactPropertyAlias(const char* property_name, UProperty property) {
+  const char* short_name = u_getPropertyName(property, U_SHORT_PROPERTY_NAME);
   if (short_name != NULL && strcmp(property_name, short_name) == 0) return true;
   for (int i = 0;; i++) {
-    const char* long_name = u_getPropertyValueName(
-        property, property_value,
-        static_cast<UPropertyNameChoice>(U_LONG_PROPERTY_NAME + i));
+    const char* long_name = u_getPropertyName(
+        property, static_cast<UPropertyNameChoice>(U_LONG_PROPERTY_NAME + i));
     if (long_name == NULL) break;
     if (strcmp(property_name, long_name) == 0) return true;
   }
   return false;
 }
 
-bool LookupPropertyClass(UProperty property, const char* property_name,
-                         ZoneList<CharacterRange>* result, Zone* zone) {
-  int32_t property_value = u_getPropertyValueEnum(property, property_name);
+bool IsExactPropertyValueAlias(const char* property_value_name,
+                               UProperty property, int32_t property_value) {
+  const char* short_name =
+      u_getPropertyValueName(property, property_value, U_SHORT_PROPERTY_NAME);
+  if (short_name != NULL && strcmp(property_value_name, short_name) == 0) {
+    return true;
+  }
+  for (int i = 0;; i++) {
+    const char* long_name = u_getPropertyValueName(
+        property, property_value,
+        static_cast<UPropertyNameChoice>(U_LONG_PROPERTY_NAME + i));
+    if (long_name == NULL) break;
+    if (strcmp(property_value_name, long_name) == 0) return true;
+  }
+  return false;
+}
+
+bool LookupPropertyValueName(UProperty property,
+                             const char* property_value_name, bool negate,
+                             ZoneList<CharacterRange>* result, Zone* zone) {
+  int32_t property_value =
+      u_getPropertyValueEnum(property, property_value_name);
   if (property_value == UCHAR_INVALID_CODE) return false;
 
   // We require the property name to match exactly to one of the property value
   // aliases. However, u_getPropertyValueEnum uses loose matching.
-  if (!IsExactPropertyValueAlias(property_name, property, property_value)) {
+  if (!IsExactPropertyValueAlias(property_value_name, property,
+                                 property_value)) {
     return false;
   }
 
@@ -878,6 +1100,7 @@
 
   if (success) {
     uset_removeAllStrings(set);
+    if (negate) uset_complement(set);
     int item_count = uset_getItemCount(set);
     int item_result = 0;
     for (int i = 0; i < item_count; i++) {
@@ -892,49 +1115,104 @@
   uset_close(set);
   return success;
 }
-#endif  // V8_I18N_SUPPORT
 
-bool RegExpParser::ParsePropertyClass(ZoneList<CharacterRange>* result) {
-#ifdef V8_I18N_SUPPORT
-  List<char> property_name_list;
+template <size_t N>
+inline bool NameEquals(const char* name, const char (&literal)[N]) {
+  return strncmp(name, literal, N + 1) == 0;
+}
+
+bool LookupSpecialPropertyValueName(const char* name,
+                                    ZoneList<CharacterRange>* result,
+                                    bool negate, Zone* zone) {
+  if (NameEquals(name, "Any")) {
+    if (!negate) result->Add(CharacterRange::Everything(), zone);
+  } else if (NameEquals(name, "ASCII")) {
+    result->Add(negate ? CharacterRange::Range(0x80, String::kMaxCodePoint)
+                       : CharacterRange::Range(0x0, 0x7f),
+                zone);
+  } else if (NameEquals(name, "Assigned")) {
+    return LookupPropertyValueName(UCHAR_GENERAL_CATEGORY, "Unassigned",
+                                   !negate, result, zone);
+  } else {
+    return false;
+  }
+  return true;
+}
+
+}  // anonymous namespace
+
+bool RegExpParser::ParsePropertyClass(ZoneList<CharacterRange>* result,
+                                      bool negate) {
+  // Parse the property class as follows:
+  // - In \p{name}, 'name' is interpreted
+  //   - either as a general category property value name.
+  //   - or as a binary property name.
+  // - In \p{name=value}, 'name' is interpreted as an enumerated property name,
+  //   and 'value' is interpreted as one of the available property value names.
+  // - Aliases in PropertyAlias.txt and PropertyValueAlias.txt can be used.
+  // - Loose matching is not applied.
+  List<char> first_part;
+  List<char> second_part;
   if (current() == '{') {
-    for (Advance(); current() != '}'; Advance()) {
+    // Parse \p{[PropertyName=]PropertyNameValue}
+    for (Advance(); current() != '}' && current() != '='; Advance()) {
       if (!has_next()) return false;
-      property_name_list.Add(static_cast<char>(current()));
+      first_part.Add(static_cast<char>(current()));
     }
-  } else if (current() != kEndMarker) {
-    property_name_list.Add(static_cast<char>(current()));
+    if (current() == '=') {
+      for (Advance(); current() != '}'; Advance()) {
+        if (!has_next()) return false;
+        second_part.Add(static_cast<char>(current()));
+      }
+      second_part.Add(0);  // null-terminate string.
+    }
   } else {
     return false;
   }
   Advance();
-  property_name_list.Add(0);  // null-terminate string.
+  first_part.Add(0);  // null-terminate string.
 
-  const char* property_name = property_name_list.ToConstVector().start();
-
-#define PROPERTY_NAME_LOOKUP(PROPERTY)                                  \
-  do {                                                                  \
-    if (LookupPropertyClass(PROPERTY, property_name, result, zone())) { \
-      return true;                                                      \
-    }                                                                   \
-  } while (false)
-
-  // General_Category (gc) found in PropertyValueAliases.txt
-  PROPERTY_NAME_LOOKUP(UCHAR_GENERAL_CATEGORY_MASK);
-  // Script (sc) found in Scripts.txt
-  PROPERTY_NAME_LOOKUP(UCHAR_SCRIPT);
-  // To disambiguate from script names, block names have an "In"-prefix.
-  if (property_name_list.length() > 3 && property_name[0] == 'I' &&
-      property_name[1] == 'n') {
-    // Block (blk) found in Blocks.txt
-    property_name += 2;
-    PROPERTY_NAME_LOOKUP(UCHAR_BLOCK);
+  if (second_part.is_empty()) {
+    // First attempt to interpret as general category property value name.
+    const char* name = first_part.ToConstVector().start();
+    if (LookupPropertyValueName(UCHAR_GENERAL_CATEGORY_MASK, name, negate,
+                                result, zone())) {
+      return true;
+    }
+    // Interpret "Any", "ASCII", and "Assigned".
+    if (LookupSpecialPropertyValueName(name, result, negate, zone())) {
+      return true;
+    }
+    // Then attempt to interpret as binary property name with value name 'Y'.
+    UProperty property = u_getPropertyEnum(name);
+    if (property < UCHAR_BINARY_START) return false;
+    if (property >= UCHAR_BINARY_LIMIT) return false;
+    if (!IsExactPropertyAlias(name, property)) return false;
+    return LookupPropertyValueName(property, negate ? "N" : "Y", false, result,
+                                   zone());
+  } else {
+    // Both property name and value name are specified. Attempt to interpret
+    // the property name as enumerated property.
+    const char* property_name = first_part.ToConstVector().start();
+    const char* value_name = second_part.ToConstVector().start();
+    UProperty property = u_getPropertyEnum(property_name);
+    if (property < UCHAR_INT_START) return false;
+    if (property >= UCHAR_INT_LIMIT) return false;
+    if (!IsExactPropertyAlias(property_name, property)) return false;
+    return LookupPropertyValueName(property, value_name, negate, result,
+                                   zone());
   }
-#undef PROPERTY_NAME_LOOKUP
-#endif  // V8_I18N_SUPPORT
+}
+
+#else  // V8_I18N_SUPPORT
+
+bool RegExpParser::ParsePropertyClass(ZoneList<CharacterRange>* result,
+                                      bool negate) {
   return false;
 }
 
+#endif  // V8_I18N_SUPPORT
+
 bool RegExpParser::ParseUnlimitedLengthHexNumber(int max_value, uc32* value) {
   uc32 x = 0;
   int d = HexValue(current());
@@ -1096,7 +1374,6 @@
   return CharacterRange::Singleton(first);
 }
 
-
 static const uc16 kNoCharClass = 0;
 
 // Adds range or pre-defined character class to character ranges.
@@ -1120,19 +1397,10 @@
   bool parse_success = false;
   if (next == 'p') {
     Advance(2);
-    parse_success = ParsePropertyClass(ranges);
+    parse_success = ParsePropertyClass(ranges, false);
   } else if (next == 'P') {
     Advance(2);
-    ZoneList<CharacterRange>* property_class =
-        new (zone()) ZoneList<CharacterRange>(2, zone());
-    parse_success = ParsePropertyClass(property_class);
-    if (parse_success) {
-      ZoneList<CharacterRange>* negated =
-          new (zone()) ZoneList<CharacterRange>(2, zone());
-      CharacterRange::Negate(property_class, negated, zone());
-      const Vector<CharacterRange> negated_vector = negated->ToVector();
-      ranges->AddAll(negated_vector, zone());
-    }
+    parse_success = ParsePropertyClass(ranges, true);
   } else {
     return false;
   }
@@ -1229,6 +1497,7 @@
     int capture_count = parser.captures_started();
     result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
     result->contains_anchor = parser.contains_anchor();
+    result->capture_name_map = parser.CreateCaptureNameMap();
     result->capture_count = capture_count;
   }
   return !parser.failed();
diff --git a/src/regexp/regexp-parser.h b/src/regexp/regexp-parser.h
index 6142a9e..a0b975d 100644
--- a/src/regexp/regexp-parser.h
+++ b/src/regexp/regexp-parser.h
@@ -174,7 +174,7 @@
   bool ParseHexEscape(int length, uc32* value);
   bool ParseUnicodeEscape(uc32* value);
   bool ParseUnlimitedLengthHexNumber(int max_value, uc32* value);
-  bool ParsePropertyClass(ZoneList<CharacterRange>* result);
+  bool ParsePropertyClass(ZoneList<CharacterRange>* result, bool negate);
 
   uc32 ParseOctalLiteral();
 
@@ -222,13 +222,15 @@
     RegExpParserState(RegExpParserState* previous_state,
                       SubexpressionType group_type,
                       RegExpLookaround::Type lookaround_type,
-                      int disjunction_capture_index, bool ignore_case,
+                      int disjunction_capture_index,
+                      const ZoneVector<uc16>* capture_name, bool ignore_case,
                       bool unicode, Zone* zone)
         : previous_state_(previous_state),
           builder_(new (zone) RegExpBuilder(zone, ignore_case, unicode)),
           group_type_(group_type),
           lookaround_type_(lookaround_type),
-          disjunction_capture_index_(disjunction_capture_index) {}
+          disjunction_capture_index_(disjunction_capture_index),
+          capture_name_(capture_name) {}
     // Parser state of containing expression, if any.
     RegExpParserState* previous_state() { return previous_state_; }
     bool IsSubexpression() { return previous_state_ != NULL; }
@@ -242,9 +244,16 @@
     // Also the capture index of this sub-expression itself, if group_type
     // is CAPTURE.
     int capture_index() { return disjunction_capture_index_; }
+    // The name of the current sub-expression, if group_type is CAPTURE. Only
+    // used for named captures.
+    const ZoneVector<uc16>* capture_name() { return capture_name_; }
+
+    bool IsNamedCapture() const { return capture_name_ != nullptr; }
 
     // Check whether the parser is inside a capture group with the given index.
     bool IsInsideCaptureGroup(int index);
+    // Check whether the parser is inside a capture group with the given name.
+    bool IsInsideCaptureGroup(const ZoneVector<uc16>* name);
 
    private:
     // Linked list implementation of stack of states.
@@ -257,11 +266,32 @@
     RegExpLookaround::Type lookaround_type_;
     // Stored disjunction's capture index (if any).
     int disjunction_capture_index_;
+    // Stored capture name (if any).
+    const ZoneVector<uc16>* capture_name_;
   };
 
   // Return the 1-indexed RegExpCapture object, allocate if necessary.
   RegExpCapture* GetCapture(int index);
 
+  // Creates a new named capture at the specified index. Must be called exactly
+  // once for each named capture. Fails if a capture with the same name is
+  // encountered.
+  bool CreateNamedCaptureAtIndex(const ZoneVector<uc16>* name, int index);
+
+  // Parses the name of a capture group (?<name>pattern). The name must adhere
+  // to IdentifierName in the ECMAScript standard.
+  const ZoneVector<uc16>* ParseCaptureGroupName();
+
+  bool ParseNamedBackReference(RegExpBuilder* builder,
+                               RegExpParserState* state);
+
+  // After the initial parsing pass, patch corresponding RegExpCapture objects
+  // into all RegExpBackReferences. This is done after initial parsing in order
+  // to avoid complicating cases in which references comes before the capture.
+  void PatchNamedBackReferences();
+
+  Handle<FixedArray> CreateCaptureNameMap();
+
   Isolate* isolate() { return isolate_; }
   Zone* zone() const { return zone_; }
 
@@ -278,6 +308,8 @@
   Zone* zone_;
   Handle<String>* error_;
   ZoneList<RegExpCapture*>* captures_;
+  ZoneList<RegExpCapture*>* named_captures_;
+  ZoneList<RegExpBackReference*>* named_back_references_;
   FlatStringReader* in_;
   uc32 current_;
   bool ignore_case_;
diff --git a/src/regexp/s390/OWNERS b/src/regexp/s390/OWNERS
index eb007cb..752e8e3 100644
--- a/src/regexp/s390/OWNERS
+++ b/src/regexp/s390/OWNERS
@@ -3,3 +3,4 @@
 joransiu@ca.ibm.com
 mbrandy@us.ibm.com
 michael_dawson@ca.ibm.com
+bjaideep@ca.ibm.com
diff --git a/src/regexp/s390/regexp-macro-assembler-s390.cc b/src/regexp/s390/regexp-macro-assembler-s390.cc
index 9dac534..d9ca1df 100644
--- a/src/regexp/s390/regexp-macro-assembler-s390.cc
+++ b/src/regexp/s390/regexp-macro-assembler-s390.cc
@@ -10,7 +10,6 @@
 #include "src/code-stubs.h"
 #include "src/log.h"
 #include "src/macro-assembler.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/regexp/regexp-macro-assembler.h"
 #include "src/regexp/regexp-stack.h"
 #include "src/regexp/s390/regexp-macro-assembler-s390.h"
diff --git a/src/regexp/x64/regexp-macro-assembler-x64.cc b/src/regexp/x64/regexp-macro-assembler-x64.cc
index 5d73b43..aafc840 100644
--- a/src/regexp/x64/regexp-macro-assembler-x64.cc
+++ b/src/regexp/x64/regexp-macro-assembler-x64.cc
@@ -8,7 +8,6 @@
 
 #include "src/log.h"
 #include "src/macro-assembler.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/regexp/regexp-macro-assembler.h"
 #include "src/regexp/regexp-stack.h"
 #include "src/unicode.h"
diff --git a/src/regexp/x87/regexp-macro-assembler-x87.cc b/src/regexp/x87/regexp-macro-assembler-x87.cc
index 9f15b1c..4a1c3a8 100644
--- a/src/regexp/x87/regexp-macro-assembler-x87.cc
+++ b/src/regexp/x87/regexp-macro-assembler-x87.cc
@@ -8,7 +8,6 @@
 
 #include "src/log.h"
 #include "src/macro-assembler.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/regexp/regexp-macro-assembler.h"
 #include "src/regexp/regexp-stack.h"
 #include "src/unicode.h"
diff --git a/src/register-configuration.cc b/src/register-configuration.cc
index 2df825a..148c3fc 100644
--- a/src/register-configuration.cc
+++ b/src/register-configuration.cc
@@ -33,6 +33,12 @@
 #undef REGISTER_NAME
 };
 
+static const char* const kFloatRegisterNames[] = {
+#define REGISTER_NAME(R) #R,
+    FLOAT_REGISTERS(REGISTER_NAME)
+#undef REGISTER_NAME
+};
+
 static const char* const kDoubleRegisterNames[] = {
 #define REGISTER_NAME(R) #R,
     DOUBLE_REGISTERS(REGISTER_NAME)
@@ -41,123 +47,186 @@
 
 STATIC_ASSERT(RegisterConfiguration::kMaxGeneralRegisters >=
               Register::kNumRegisters);
-STATIC_ASSERT(RegisterConfiguration::kMaxDoubleRegisters >=
+STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
               DoubleRegister::kMaxNumRegisters);
 
+enum CompilerSelector { CRANKSHAFT, TURBOFAN };
+
 class ArchDefaultRegisterConfiguration : public RegisterConfiguration {
  public:
   explicit ArchDefaultRegisterConfiguration(CompilerSelector compiler)
-      : RegisterConfiguration(Register::kNumRegisters,
-                              DoubleRegister::kMaxNumRegisters,
+      : RegisterConfiguration(
+            Register::kNumRegisters, DoubleRegister::kMaxNumRegisters,
 #if V8_TARGET_ARCH_IA32
-                              kMaxAllocatableGeneralRegisterCount,
-                              kMaxAllocatableDoubleRegisterCount,
-                              kMaxAllocatableDoubleRegisterCount,
+            kMaxAllocatableGeneralRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
 #elif V8_TARGET_ARCH_X87
-                              kMaxAllocatableGeneralRegisterCount,
-                              compiler == TURBOFAN
-                                  ? 1
-                                  : kMaxAllocatableDoubleRegisterCount,
-                              compiler == TURBOFAN
-                                  ? 1
-                                  : kMaxAllocatableDoubleRegisterCount,
+            kMaxAllocatableGeneralRegisterCount,
+            compiler == TURBOFAN ? 1 : kMaxAllocatableDoubleRegisterCount,
 #elif V8_TARGET_ARCH_X64
-                              kMaxAllocatableGeneralRegisterCount,
-                              kMaxAllocatableDoubleRegisterCount,
-                              kMaxAllocatableDoubleRegisterCount,
+            kMaxAllocatableGeneralRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
 #elif V8_TARGET_ARCH_ARM
-                              FLAG_enable_embedded_constant_pool
-                                  ? (kMaxAllocatableGeneralRegisterCount - 1)
-                                  : kMaxAllocatableGeneralRegisterCount,
-                              CpuFeatures::IsSupported(VFP32DREGS)
-                                  ? kMaxAllocatableDoubleRegisterCount
-                                  : (ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(
-                                        REGISTER_COUNT)0),
-                              ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(
-                                  REGISTER_COUNT)0,
+            FLAG_enable_embedded_constant_pool
+                ? (kMaxAllocatableGeneralRegisterCount - 1)
+                : kMaxAllocatableGeneralRegisterCount,
+            CpuFeatures::IsSupported(VFP32DREGS)
+                ? kMaxAllocatableDoubleRegisterCount
+                : (ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(REGISTER_COUNT) 0),
 #elif V8_TARGET_ARCH_ARM64
-                              kMaxAllocatableGeneralRegisterCount,
-                              kMaxAllocatableDoubleRegisterCount,
-                              kMaxAllocatableDoubleRegisterCount,
+            kMaxAllocatableGeneralRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
 #elif V8_TARGET_ARCH_MIPS
-                              kMaxAllocatableGeneralRegisterCount,
-                              kMaxAllocatableDoubleRegisterCount,
-                              kMaxAllocatableDoubleRegisterCount,
+            kMaxAllocatableGeneralRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
 #elif V8_TARGET_ARCH_MIPS64
-                              kMaxAllocatableGeneralRegisterCount,
-                              kMaxAllocatableDoubleRegisterCount,
-                              kMaxAllocatableDoubleRegisterCount,
+            kMaxAllocatableGeneralRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
 #elif V8_TARGET_ARCH_PPC
-                              kMaxAllocatableGeneralRegisterCount,
-                              kMaxAllocatableDoubleRegisterCount,
-                              kMaxAllocatableDoubleRegisterCount,
+            kMaxAllocatableGeneralRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
 #elif V8_TARGET_ARCH_S390
-                              kMaxAllocatableGeneralRegisterCount,
-                              kMaxAllocatableDoubleRegisterCount,
-                              kMaxAllocatableDoubleRegisterCount,
+            kMaxAllocatableGeneralRegisterCount,
+            kMaxAllocatableDoubleRegisterCount,
 #else
 #error Unsupported target architecture.
 #endif
-                              kAllocatableGeneralCodes, kAllocatableDoubleCodes,
-                              kGeneralRegisterNames, kDoubleRegisterNames) {
+            kAllocatableGeneralCodes, kAllocatableDoubleCodes,
+            kSimpleFPAliasing ? AliasingKind::OVERLAP : AliasingKind::COMBINE,
+            kGeneralRegisterNames, kFloatRegisterNames, kDoubleRegisterNames) {
   }
 };
 
-
-template <RegisterConfiguration::CompilerSelector compiler>
+template <CompilerSelector compiler>
 struct RegisterConfigurationInitializer {
   static void Construct(ArchDefaultRegisterConfiguration* config) {
     new (config) ArchDefaultRegisterConfiguration(compiler);
   }
 };
 
-static base::LazyInstance<
-    ArchDefaultRegisterConfiguration,
-    RegisterConfigurationInitializer<RegisterConfiguration::CRANKSHAFT>>::type
+static base::LazyInstance<ArchDefaultRegisterConfiguration,
+                          RegisterConfigurationInitializer<CRANKSHAFT>>::type
     kDefaultRegisterConfigurationForCrankshaft = LAZY_INSTANCE_INITIALIZER;
 
-
-static base::LazyInstance<
-    ArchDefaultRegisterConfiguration,
-    RegisterConfigurationInitializer<RegisterConfiguration::TURBOFAN>>::type
+static base::LazyInstance<ArchDefaultRegisterConfiguration,
+                          RegisterConfigurationInitializer<TURBOFAN>>::type
     kDefaultRegisterConfigurationForTurboFan = LAZY_INSTANCE_INITIALIZER;
 
 }  // namespace
 
-
-const RegisterConfiguration* RegisterConfiguration::ArchDefault(
-    CompilerSelector compiler) {
-  return compiler == TURBOFAN
-             ? &kDefaultRegisterConfigurationForTurboFan.Get()
-             : &kDefaultRegisterConfigurationForCrankshaft.Get();
+const RegisterConfiguration* RegisterConfiguration::Crankshaft() {
+  return &kDefaultRegisterConfigurationForCrankshaft.Get();
 }
 
+const RegisterConfiguration* RegisterConfiguration::Turbofan() {
+  return &kDefaultRegisterConfigurationForTurboFan.Get();
+}
 
 RegisterConfiguration::RegisterConfiguration(
     int num_general_registers, int num_double_registers,
     int num_allocatable_general_registers, int num_allocatable_double_registers,
-    int num_allocatable_aliased_double_registers,
     const int* allocatable_general_codes, const int* allocatable_double_codes,
-    const char* const* general_register_names,
+    AliasingKind fp_aliasing_kind, const char* const* general_register_names,
+    const char* const* float_register_names,
     const char* const* double_register_names)
     : num_general_registers_(num_general_registers),
+      num_float_registers_(0),
       num_double_registers_(num_double_registers),
       num_allocatable_general_registers_(num_allocatable_general_registers),
       num_allocatable_double_registers_(num_allocatable_double_registers),
-      num_allocatable_aliased_double_registers_(
-          num_allocatable_aliased_double_registers),
+      num_allocatable_float_registers_(0),
       allocatable_general_codes_mask_(0),
       allocatable_double_codes_mask_(0),
+      allocatable_float_codes_mask_(0),
       allocatable_general_codes_(allocatable_general_codes),
       allocatable_double_codes_(allocatable_double_codes),
+      fp_aliasing_kind_(fp_aliasing_kind),
       general_register_names_(general_register_names),
+      float_register_names_(float_register_names),
       double_register_names_(double_register_names) {
+  DCHECK(num_general_registers_ <= RegisterConfiguration::kMaxGeneralRegisters);
+  DCHECK(num_double_registers_ <= RegisterConfiguration::kMaxFPRegisters);
   for (int i = 0; i < num_allocatable_general_registers_; ++i) {
     allocatable_general_codes_mask_ |= (1 << allocatable_general_codes_[i]);
   }
   for (int i = 0; i < num_allocatable_double_registers_; ++i) {
     allocatable_double_codes_mask_ |= (1 << allocatable_double_codes_[i]);
   }
+
+  if (fp_aliasing_kind_ == COMBINE) {
+    num_float_registers_ = num_double_registers_ * 2 <= kMaxFPRegisters
+                               ? num_double_registers_ * 2
+                               : kMaxFPRegisters;
+    num_allocatable_float_registers_ = 0;
+    for (int i = 0; i < num_allocatable_double_registers_; i++) {
+      int base_code = allocatable_double_codes_[i] * 2;
+      if (base_code >= kMaxFPRegisters) continue;
+      allocatable_float_codes_[num_allocatable_float_registers_++] = base_code;
+      allocatable_float_codes_[num_allocatable_float_registers_++] =
+          base_code + 1;
+      allocatable_float_codes_mask_ |= (0x3 << base_code);
+    }
+  } else {
+    DCHECK(fp_aliasing_kind_ == OVERLAP);
+    num_float_registers_ = num_double_registers_;
+    num_allocatable_float_registers_ = num_allocatable_double_registers_;
+    for (int i = 0; i < num_allocatable_float_registers_; ++i) {
+      allocatable_float_codes_[i] = allocatable_double_codes_[i];
+    }
+    allocatable_float_codes_mask_ = allocatable_double_codes_mask_;
+  }
+}
+
+int RegisterConfiguration::GetAliases(MachineRepresentation rep, int index,
+                                      MachineRepresentation other_rep,
+                                      int* alias_base_index) const {
+  DCHECK(fp_aliasing_kind_ == COMBINE);
+  DCHECK(rep == MachineRepresentation::kFloat32 ||
+         rep == MachineRepresentation::kFloat64);
+  DCHECK(other_rep == MachineRepresentation::kFloat32 ||
+         other_rep == MachineRepresentation::kFloat64);
+  if (rep == other_rep) {
+    *alias_base_index = index;
+    return 1;
+  }
+  if (rep == MachineRepresentation::kFloat32) {
+    DCHECK(other_rep == MachineRepresentation::kFloat64);
+    DCHECK(index < num_allocatable_float_registers_);
+    *alias_base_index = index / 2;
+    return 1;
+  }
+  DCHECK(rep == MachineRepresentation::kFloat64);
+  DCHECK(other_rep == MachineRepresentation::kFloat32);
+  if (index * 2 >= kMaxFPRegisters) {
+    // Alias indices are out of float register range.
+    return 0;
+  }
+  *alias_base_index = index * 2;
+  return 2;
+}
+
+bool RegisterConfiguration::AreAliases(MachineRepresentation rep, int index,
+                                       MachineRepresentation other_rep,
+                                       int other_index) const {
+  DCHECK(fp_aliasing_kind_ == COMBINE);
+  DCHECK(rep == MachineRepresentation::kFloat32 ||
+         rep == MachineRepresentation::kFloat64);
+  DCHECK(other_rep == MachineRepresentation::kFloat32 ||
+         other_rep == MachineRepresentation::kFloat64);
+  if (rep == other_rep) {
+    return index == other_index;
+  }
+  if (rep == MachineRepresentation::kFloat32) {
+    DCHECK(other_rep == MachineRepresentation::kFloat64);
+    return index / 2 == other_index;
+  }
+  DCHECK(rep == MachineRepresentation::kFloat64);
+  DCHECK(other_rep == MachineRepresentation::kFloat32);
+  if (index * 2 >= kMaxFPRegisters) {
+    // Alias indices are out of float register range.
+    return false;
+  }
+  return index == other_index / 2;
 }
 
 #undef REGISTER_COUNT
diff --git a/src/register-configuration.h b/src/register-configuration.h
index 8ad1d78..25f3ef5 100644
--- a/src/register-configuration.h
+++ b/src/register-configuration.h
@@ -6,6 +6,7 @@
 #define V8_COMPILER_REGISTER_CONFIGURATION_H_
 
 #include "src/base/macros.h"
+#include "src/machine-type.h"
 
 namespace v8 {
 namespace internal {
@@ -14,29 +15,35 @@
 // for instruction creation.
 class RegisterConfiguration {
  public:
-  // Define the optimized compiler selector for register configuration
-  // selection.
-  //
-  // TODO(X87): This distinction in RegisterConfigurations is temporary
-  // until x87 TF supports all of the registers that Crankshaft does.
-  enum CompilerSelector { CRANKSHAFT, TURBOFAN };
+  enum AliasingKind {
+    // Registers alias a single register of every other size (e.g. Intel).
+    OVERLAP,
+    // Registers alias two registers of the next smaller size (e.g. ARM).
+    COMBINE
+  };
 
   // Architecture independent maxes.
   static const int kMaxGeneralRegisters = 32;
-  static const int kMaxDoubleRegisters = 32;
+  static const int kMaxFPRegisters = 32;
 
-  static const RegisterConfiguration* ArchDefault(CompilerSelector compiler);
+  // Default RegisterConfigurations for the target architecture.
+  // TODO(X87): This distinction in RegisterConfigurations is temporary
+  // until x87 TF supports all of the registers that Crankshaft does.
+  static const RegisterConfiguration* Crankshaft();
+  static const RegisterConfiguration* Turbofan();
 
   RegisterConfiguration(int num_general_registers, int num_double_registers,
                         int num_allocatable_general_registers,
                         int num_allocatable_double_registers,
-                        int num_allocatable_aliased_double_registers,
                         const int* allocatable_general_codes,
                         const int* allocatable_double_codes,
+                        AliasingKind fp_aliasing_kind,
                         char const* const* general_names,
+                        char const* const* float_names,
                         char const* const* double_names);
 
   int num_general_registers() const { return num_general_registers_; }
+  int num_float_registers() const { return num_float_registers_; }
   int num_double_registers() const { return num_double_registers_; }
   int num_allocatable_general_registers() const {
     return num_allocatable_general_registers_;
@@ -44,12 +51,10 @@
   int num_allocatable_double_registers() const {
     return num_allocatable_double_registers_;
   }
-  // TODO(turbofan): This is a temporary work-around required because our
-  // register allocator does not yet support the aliasing of single/double
-  // registers on ARM.
-  int num_allocatable_aliased_double_registers() const {
-    return num_allocatable_aliased_double_registers_;
+  int num_allocatable_float_registers() const {
+    return num_allocatable_float_registers_;
   }
+  AliasingKind fp_aliasing_kind() const { return fp_aliasing_kind_; }
   int32_t allocatable_general_codes_mask() const {
     return allocatable_general_codes_mask_;
   }
@@ -59,12 +64,27 @@
   int GetAllocatableGeneralCode(int index) const {
     return allocatable_general_codes_[index];
   }
+  bool IsAllocatableGeneralCode(int index) const {
+    return ((1 << index) & allocatable_general_codes_mask_) != 0;
+  }
   int GetAllocatableDoubleCode(int index) const {
     return allocatable_double_codes_[index];
   }
+  bool IsAllocatableDoubleCode(int index) const {
+    return ((1 << index) & allocatable_double_codes_mask_) != 0;
+  }
+  int GetAllocatableFloatCode(int index) const {
+    return allocatable_float_codes_[index];
+  }
+  bool IsAllocatableFloatCode(int index) const {
+    return ((1 << index) & allocatable_float_codes_mask_) != 0;
+  }
   const char* GetGeneralRegisterName(int code) const {
     return general_register_names_[code];
   }
+  const char* GetFloatRegisterName(int code) const {
+    return float_register_names_[code];
+  }
   const char* GetDoubleRegisterName(int code) const {
     return double_register_names_[code];
   }
@@ -74,18 +94,38 @@
   const int* allocatable_double_codes() const {
     return allocatable_double_codes_;
   }
+  const int* allocatable_float_codes() const {
+    return allocatable_float_codes_;
+  }
+
+  // Aliasing calculations for floating point registers, when fp_aliasing_kind()
+  // is COMBINE. Currently only implemented for kFloat32, or kFloat64 reps.
+  // Returns the number of aliases, and if > 0, alias_base_index is set to the
+  // index of the first alias.
+  int GetAliases(MachineRepresentation rep, int index,
+                 MachineRepresentation other_rep, int* alias_base_index) const;
+  // Returns a value indicating whether two registers alias each other, when
+  // fp_aliasing_kind() is COMBINE. Currently only implemented for kFloat32, or
+  // kFloat64 reps.
+  bool AreAliases(MachineRepresentation rep, int index,
+                  MachineRepresentation other_rep, int other_index) const;
 
  private:
   const int num_general_registers_;
+  int num_float_registers_;
   const int num_double_registers_;
   int num_allocatable_general_registers_;
   int num_allocatable_double_registers_;
-  int num_allocatable_aliased_double_registers_;
+  int num_allocatable_float_registers_;
   int32_t allocatable_general_codes_mask_;
   int32_t allocatable_double_codes_mask_;
+  int32_t allocatable_float_codes_mask_;
   const int* allocatable_general_codes_;
   const int* allocatable_double_codes_;
+  int allocatable_float_codes_[kMaxFPRegisters];
+  AliasingKind fp_aliasing_kind_;
   char const* const* general_register_names_;
+  char const* const* float_register_names_;
   char const* const* double_register_names_;
 };
 
diff --git a/src/runtime-profiler.cc b/src/runtime-profiler.cc
index b76785d..6500b9a 100644
--- a/src/runtime-profiler.cc
+++ b/src/runtime-profiler.cc
@@ -20,6 +20,9 @@
 
 
 // Number of times a function has to be seen on the stack before it is
+// compiled for baseline.
+static const int kProfilerTicksBeforeBaseline = 1;
+// Number of times a function has to be seen on the stack before it is
 // optimized.
 static const int kProfilerTicksBeforeOptimization = 2;
 // If the function optimization was disabled due to high deoptimization count,
@@ -53,16 +56,14 @@
       any_ic_changed_(false) {
 }
 
-
-static void GetICCounts(SharedFunctionInfo* shared,
-                        int* ic_with_type_info_count, int* ic_generic_count,
-                        int* ic_total_count, int* type_info_percentage,
-                        int* generic_percentage) {
+static void GetICCounts(JSFunction* function, int* ic_with_type_info_count,
+                        int* ic_generic_count, int* ic_total_count,
+                        int* type_info_percentage, int* generic_percentage) {
   *ic_total_count = 0;
   *ic_generic_count = 0;
   *ic_with_type_info_count = 0;
-  if (shared->code()->kind() == Code::FUNCTION) {
-    Code* shared_code = shared->code();
+  if (function->code()->kind() == Code::FUNCTION) {
+    Code* shared_code = function->shared()->code();
     Object* raw_info = shared_code->type_feedback_info();
     if (raw_info->IsTypeFeedbackInfo()) {
       TypeFeedbackInfo* info = TypeFeedbackInfo::cast(raw_info);
@@ -73,7 +74,7 @@
   }
 
   // Harvest vector-ics as well
-  TypeFeedbackVector* vector = shared->feedback_vector();
+  TypeFeedbackVector* vector = function->feedback_vector();
   int with = 0, gen = 0;
   vector->ComputeCounts(&with, &gen);
   *ic_with_type_info_count += with;
@@ -88,27 +89,44 @@
   }
 }
 
-
-void RuntimeProfiler::Optimize(JSFunction* function, const char* reason) {
+static void TraceRecompile(JSFunction* function, const char* reason,
+                           const char* type) {
   if (FLAG_trace_opt &&
       function->shared()->PassesFilter(FLAG_hydrogen_filter)) {
     PrintF("[marking ");
     function->ShortPrint();
-    PrintF(" for recompilation, reason: %s", reason);
+    PrintF(" for %s recompilation, reason: %s", type, reason);
     if (FLAG_type_info_threshold > 0) {
       int typeinfo, generic, total, type_percentage, generic_percentage;
-      GetICCounts(function->shared(), &typeinfo, &generic, &total,
-                  &type_percentage, &generic_percentage);
+      GetICCounts(function, &typeinfo, &generic, &total, &type_percentage,
+                  &generic_percentage);
       PrintF(", ICs with typeinfo: %d/%d (%d%%)", typeinfo, total,
              type_percentage);
       PrintF(", generic ICs: %d/%d (%d%%)", generic, total, generic_percentage);
     }
     PrintF("]\n");
   }
+}
 
+void RuntimeProfiler::Optimize(JSFunction* function, const char* reason) {
+  TraceRecompile(function, reason, "optimized");
+
+  // TODO(4280): Fix this to check function is compiled to baseline once we
+  // have a standard way to check that. For now, if baseline code doesn't have
+  // a bytecode array.
+  DCHECK(!function->shared()->HasBytecodeArray());
   function->AttemptConcurrentOptimization();
 }
 
+void RuntimeProfiler::Baseline(JSFunction* function, const char* reason) {
+  TraceRecompile(function, reason, "baseline");
+
+  // TODO(4280): Fix this to check function is compiled for the interpreter
+  // once we have a standard way to check that. For now function will only
+  // have a bytecode array if compiled for the interpreter.
+  DCHECK(function->shared()->HasBytecodeArray());
+  function->MarkForBaseline();
+}
 
 void RuntimeProfiler::AttemptOnStackReplacement(JSFunction* function,
                                                 int loop_nesting_levels) {
@@ -199,7 +217,7 @@
 
   if (ticks >= kProfilerTicksBeforeOptimization) {
     int typeinfo, generic, total, type_percentage, generic_percentage;
-    GetICCounts(shared, &typeinfo, &generic, &total, &type_percentage,
+    GetICCounts(function, &typeinfo, &generic, &total, &type_percentage,
                 &generic_percentage);
     if (type_percentage >= FLAG_type_info_threshold &&
         generic_percentage <= FLAG_generic_ic_threshold) {
@@ -222,7 +240,7 @@
     // If no IC was patched since the last tick and this function is very
     // small, optimistically optimize it now.
     int typeinfo, generic, total, type_percentage, generic_percentage;
-    GetICCounts(shared, &typeinfo, &generic, &total, &type_percentage,
+    GetICCounts(function, &typeinfo, &generic, &total, &type_percentage,
                 &generic_percentage);
     if (type_percentage >= FLAG_type_info_threshold &&
         generic_percentage <= FLAG_generic_ic_threshold) {
@@ -235,8 +253,7 @@
   }
 }
 
-void RuntimeProfiler::MaybeOptimizeIgnition(JSFunction* function,
-                                            bool frame_optimized) {
+void RuntimeProfiler::MaybeOptimizeIgnition(JSFunction* function) {
   if (function->IsInOptimizationQueue()) return;
 
   SharedFunctionInfo* shared = function->shared();
@@ -247,48 +264,22 @@
   // TODO(rmcilroy): Consider whether we should optimize small functions when
   // they are first seen on the stack (e.g., kMaxSizeEarlyOpt).
 
-  if (!frame_optimized && (function->IsMarkedForOptimization() ||
-                           function->IsMarkedForConcurrentOptimization() ||
-                           function->IsOptimized())) {
+  if (function->IsMarkedForBaseline() || function->IsMarkedForOptimization() ||
+      function->IsMarkedForConcurrentOptimization() ||
+      function->IsOptimized()) {
     // TODO(rmcilroy): Support OSR in these cases.
-
     return;
   }
 
-  // Do not optimize non-optimizable functions.
-  if (shared->optimization_disabled()) {
-    if (shared->deopt_count() >= FLAG_max_opt_count) {
-      // If optimization was disabled due to many deoptimizations,
-      // then check if the function is hot and try to reenable optimization.
-      if (ticks >= kProfilerTicksBeforeReenablingOptimization) {
-        shared->set_profiler_ticks(0);
-        shared->TryReenableOptimization();
-      }
-    }
+  if (shared->optimization_disabled() &&
+      shared->disable_optimization_reason() == kOptimizationDisabledForTest) {
+    // Don't baseline functions which have been marked by NeverOptimizeFunction
+    // in a test.
     return;
   }
 
-  if (function->IsOptimized()) return;
-
-  if (ticks >= kProfilerTicksBeforeOptimization) {
-    int typeinfo, generic, total, type_percentage, generic_percentage;
-    GetICCounts(shared, &typeinfo, &generic, &total, &type_percentage,
-                &generic_percentage);
-    if (type_percentage >= FLAG_type_info_threshold &&
-        generic_percentage <= FLAG_generic_ic_threshold) {
-      // If this particular function hasn't had any ICs patched for enough
-      // ticks, optimize it now.
-      Optimize(function, "hot and stable");
-    } else if (ticks >= kTicksWhenNotEnoughTypeInfo) {
-      Optimize(function, "not much type info but very hot");
-    } else {
-      if (FLAG_trace_opt_verbose) {
-        PrintF("[not yet optimizing ");
-        function->PrintName();
-        PrintF(", not enough type info: %d/%d (%d%%)]\n", typeinfo, total,
-               type_percentage);
-      }
-    }
+  if (ticks >= kProfilerTicksBeforeBaseline) {
+    Baseline(function, "hot enough for baseline");
   }
 }
 
@@ -320,8 +311,9 @@
       }
     }
 
-    if (FLAG_ignition) {
-      MaybeOptimizeIgnition(function, frame->is_optimized());
+    if (frame->is_interpreted()) {
+      DCHECK(!frame->is_optimized());
+      MaybeOptimizeIgnition(function);
     } else {
       MaybeOptimizeFullCodegen(function, frame_count, frame->is_optimized());
     }
diff --git a/src/runtime-profiler.h b/src/runtime-profiler.h
index aa2f65e..499f0be 100644
--- a/src/runtime-profiler.h
+++ b/src/runtime-profiler.h
@@ -8,16 +8,10 @@
 #include "src/allocation.h"
 
 namespace v8 {
-
-namespace base {
-class Semaphore;
-}
-
 namespace internal {
 
 class Isolate;
 class JSFunction;
-class Object;
 
 class RuntimeProfiler {
  public:
@@ -32,8 +26,9 @@
  private:
   void MaybeOptimizeFullCodegen(JSFunction* function, int frame_count,
                                 bool frame_optimized);
-  void MaybeOptimizeIgnition(JSFunction* function, bool frame_optimized);
+  void MaybeOptimizeIgnition(JSFunction* function);
   void Optimize(JSFunction* function, const char* reason);
+  void Baseline(JSFunction* function, const char* reason);
 
   bool CodeSizeOKForOSR(Code* shared_code);
 
diff --git a/src/runtime/runtime-array.cc b/src/runtime/runtime-array.cc
index ab436c2..a92215c 100644
--- a/src/runtime/runtime-array.cc
+++ b/src/runtime/runtime-array.cc
@@ -22,8 +22,9 @@
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
   Object* length = prototype->length();
-  RUNTIME_ASSERT(length->IsSmi() && Smi::cast(length)->value() == 0);
-  RUNTIME_ASSERT(prototype->HasFastSmiOrObjectElements());
+  CHECK(length->IsSmi());
+  CHECK(Smi::cast(length)->value() == 0);
+  CHECK(prototype->HasFastSmiOrObjectElements());
   // This is necessary to enable fast checks for absence of elements
   // on Array.prototype and below.
   prototype->set_elements(isolate->heap()->empty_fixed_array());
@@ -85,7 +86,7 @@
 
 RUNTIME_FUNCTION(Runtime_TransitionElementsKind) {
   HandleScope scope(isolate);
-  RUNTIME_ASSERT(args.length() == 2);
+  DCHECK(args.length() == 2);
   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
   CONVERT_ARG_HANDLE_CHECKED(Map, map, 1);
   JSObject::TransitionElementsKind(array, map->elements_kind());
@@ -182,8 +183,14 @@
   DCHECK(args.length() == 2);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
   CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
+  ElementsKind kind = array->GetElementsKind();
 
-  if (array->HasFastStringWrapperElements()) {
+  if (IsFastElementsKind(kind) || IsFixedTypedArrayElementsKind(kind)) {
+    uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
+    return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
+  }
+
+  if (kind == FAST_STRING_WRAPPER_ELEMENTS) {
     int string_length =
         String::cast(Handle<JSValue>::cast(array)->value())->length();
     int backing_store_length = array->elements()->length();
@@ -192,17 +199,9 @@
             static_cast<uint32_t>(Max(string_length, backing_store_length))));
   }
 
-  if (!array->elements()->IsDictionary()) {
-    RUNTIME_ASSERT(array->HasFastSmiOrObjectElements() ||
-                   array->HasFastDoubleElements());
-    uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
-    return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
-  }
-
-  KeyAccumulator accumulator(isolate, OWN_ONLY, ALL_PROPERTIES);
-  // No need to separate prototype levels since we only get element keys.
-  for (PrototypeIterator iter(isolate, array,
-                              PrototypeIterator::START_AT_RECEIVER);
+  KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly,
+                             ALL_PROPERTIES);
+  for (PrototypeIterator iter(isolate, array, kStartAtReceiver);
        !iter.IsAtEnd(); iter.Advance()) {
     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy() ||
         PrototypeIterator::GetCurrent<JSObject>(iter)
@@ -211,12 +210,12 @@
       // collecting keys in that case.
       return *isolate->factory()->NewNumberFromUint(length);
     }
-    accumulator.NextPrototype();
     Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
-    JSObject::CollectOwnElementKeys(current, &accumulator, ALL_PROPERTIES);
+    accumulator.CollectOwnElementIndices(array, current);
   }
   // Erase any keys >= length.
-  Handle<FixedArray> keys = accumulator.GetKeys(KEEP_NUMBERS);
+  Handle<FixedArray> keys =
+      accumulator.GetKeys(GetKeysConversion::kKeepNumbers);
   int j = 0;
   for (int i = 0; i < keys->length(); i++) {
     if (NumberToUint32(keys->get(i)) >= length) continue;
@@ -321,7 +320,6 @@
 
 }  // namespace
 
-
 RUNTIME_FUNCTION(Runtime_NewArray) {
   HandleScope scope(isolate);
   DCHECK_LE(3, args.length());
@@ -338,66 +336,12 @@
   return ArrayConstructorCommon(isolate, constructor, new_target, site, &argv);
 }
 
-
-RUNTIME_FUNCTION(Runtime_ArrayConstructor) {
-  HandleScope scope(isolate);
-  // If we get 2 arguments then they are the stub parameters (constructor, type
-  // info).  If we get 4, then the first one is a pointer to the arguments
-  // passed by the caller, and the last one is the length of the arguments
-  // passed to the caller (redundant, but useful to check on the deoptimizer
-  // with an assert).
-  Arguments empty_args(0, NULL);
-  bool no_caller_args = args.length() == 2;
-  DCHECK(no_caller_args || args.length() == 4);
-  int parameters_start = no_caller_args ? 0 : 1;
-  Arguments* caller_args =
-      no_caller_args ? &empty_args : reinterpret_cast<Arguments*>(args[0]);
-  CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
-  CONVERT_ARG_HANDLE_CHECKED(Object, type_info, parameters_start + 1);
-#ifdef DEBUG
-  if (!no_caller_args) {
-    CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 2);
-    DCHECK(arg_count == caller_args->length());
-  }
-#endif
-
-  Handle<AllocationSite> site;
-  if (!type_info.is_null() &&
-      *type_info != isolate->heap()->undefined_value()) {
-    site = Handle<AllocationSite>::cast(type_info);
-    DCHECK(!site->SitePointsToLiteral());
-  }
-
-  return ArrayConstructorCommon(isolate, constructor, constructor, site,
-                                caller_args);
-}
-
-RUNTIME_FUNCTION(Runtime_InternalArrayConstructor) {
-  HandleScope scope(isolate);
-  Arguments empty_args(0, NULL);
-  bool no_caller_args = args.length() == 1;
-  DCHECK(no_caller_args || args.length() == 3);
-  int parameters_start = no_caller_args ? 0 : 1;
-  Arguments* caller_args =
-      no_caller_args ? &empty_args : reinterpret_cast<Arguments*>(args[0]);
-  CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
-#ifdef DEBUG
-  if (!no_caller_args) {
-    CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 1);
-    DCHECK(arg_count == caller_args->length());
-  }
-#endif
-  return ArrayConstructorCommon(isolate, constructor, constructor,
-                                Handle<AllocationSite>::null(), caller_args);
-}
-
-
 RUNTIME_FUNCTION(Runtime_NormalizeElements) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
-  RUNTIME_ASSERT(!array->HasFixedTypedArrayElements() &&
-                 !array->IsJSGlobalProxy());
+  CHECK(!array->HasFixedTypedArrayElements());
+  CHECK(!array->IsJSGlobalProxy());
   JSObject::NormalizeElements(array);
   return *array;
 }
@@ -437,8 +381,7 @@
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
-  for (PrototypeIterator iter(isolate, array,
-                              PrototypeIterator::START_AT_RECEIVER);
+  for (PrototypeIterator iter(isolate, array, kStartAtReceiver);
        !iter.IsAtEnd(); iter.Advance()) {
     if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
       return isolate->heap()->true_value();
@@ -455,6 +398,15 @@
   return isolate->heap()->false_value();
 }
 
+// ES6 22.1.2.2 Array.isArray
+RUNTIME_FUNCTION(Runtime_ArrayIsArray) {
+  HandleScope shs(isolate);
+  DCHECK(args.length() == 1);
+  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
+  Maybe<bool> result = Object::IsArray(object);
+  MAYBE_RETURN(result, isolate->heap()->exception());
+  return isolate->heap()->ToBoolean(result.FromJust());
+}
 
 RUNTIME_FUNCTION(Runtime_IsArray) {
   SealHandleScope shs(isolate);
@@ -463,7 +415,6 @@
   return isolate->heap()->ToBoolean(obj->IsJSArray());
 }
 
-
 RUNTIME_FUNCTION(Runtime_HasCachedArrayIndex) {
   SealHandleScope shs(isolate);
   DCHECK(args.length() == 1);
@@ -483,11 +434,8 @@
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, original_array, 0);
-  Handle<Object> constructor;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, constructor,
-      Object::ArraySpeciesConstructor(isolate, original_array));
-  return *constructor;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, Object::ArraySpeciesConstructor(isolate, original_array));
 }
 
 }  // namespace internal
diff --git a/src/runtime/runtime-atomics.cc b/src/runtime/runtime-atomics.cc
index 94d98d4..28a8741 100644
--- a/src/runtime/runtime-atomics.cc
+++ b/src/runtime/runtime-atomics.cc
@@ -33,18 +33,6 @@
 }
 
 template <typename T>
-inline T LoadSeqCst(T* p) {
-  T result;
-  __atomic_load(p, &result, __ATOMIC_SEQ_CST);
-  return result;
-}
-
-template <typename T>
-inline void StoreSeqCst(T* p, T value) {
-  __atomic_store_n(p, value, __ATOMIC_SEQ_CST);
-}
-
-template <typename T>
 inline T AddSeqCst(T* p, T value) {
   return __atomic_fetch_add(p, value, __ATOMIC_SEQ_CST);
 }
@@ -116,11 +104,6 @@
     return InterlockedCompareExchange##suffix(reinterpret_cast<vctype*>(p), \
                                               bit_cast<vctype>(newval),     \
                                               bit_cast<vctype>(oldval));    \
-  }                                                                         \
-  inline type LoadSeqCst(type* p) { return *p; }                            \
-  inline void StoreSeqCst(type* p, type value) {                            \
-    InterlockedExchange##suffix(reinterpret_cast<vctype*>(p),               \
-                                bit_cast<vctype>(value));                   \
   }
 
 ATOMIC_OPS(int8_t, 8, char)
@@ -216,22 +199,6 @@
 
 
 template <typename T>
-inline Object* DoLoad(Isolate* isolate, void* buffer, size_t index) {
-  T result = LoadSeqCst(static_cast<T*>(buffer) + index);
-  return ToObject(isolate, result);
-}
-
-
-template <typename T>
-inline Object* DoStore(Isolate* isolate, void* buffer, size_t index,
-                       Handle<Object> obj) {
-  T value = FromObject<T>(obj);
-  StoreSeqCst(static_cast<T*>(buffer) + index, value);
-  return *obj;
-}
-
-
-template <typename T>
 inline Object* DoAdd(Isolate* isolate, void* buffer, size_t index,
                      Handle<Object> obj) {
   T value = FromObject<T>(obj);
@@ -307,15 +274,6 @@
 }
 
 
-inline Object* DoStoreUint8Clamped(Isolate* isolate, void* buffer, size_t index,
-                                   Handle<Object> obj) {
-  typedef int32_t convert_type;
-  uint8_t value = ClampToUint8(FromObject<convert_type>(obj));
-  StoreSeqCst(static_cast<uint8_t*>(buffer) + index, value);
-  return *obj;
-}
-
-
 #define DO_UINT8_CLAMPED_OP(name, op)                                        \
   inline Object* Do##name##Uint8Clamped(Isolate* isolate, void* buffer,      \
                                         size_t index, Handle<Object> obj) {  \
@@ -365,6 +323,29 @@
   V(Uint32, uint32, UINT32, uint32_t, 4) \
   V(Int32, int32, INT32, int32_t, 4)
 
+RUNTIME_FUNCTION(Runtime_ThrowNotIntegerSharedTypedArrayError) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(1, args.length());
+  CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
+  THROW_NEW_ERROR_RETURN_FAILURE(
+      isolate,
+      NewTypeError(MessageTemplate::kNotIntegerSharedTypedArray, value));
+}
+
+RUNTIME_FUNCTION(Runtime_ThrowNotInt32SharedTypedArrayError) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(1, args.length());
+  CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
+  THROW_NEW_ERROR_RETURN_FAILURE(
+      isolate, NewTypeError(MessageTemplate::kNotInt32SharedTypedArray, value));
+}
+
+RUNTIME_FUNCTION(Runtime_ThrowInvalidAtomicAccessIndexError) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(0, args.length());
+  THROW_NEW_ERROR_RETURN_FAILURE(
+      isolate, NewRangeError(MessageTemplate::kInvalidAtomicAccessIndex));
+}
 
 RUNTIME_FUNCTION(Runtime_AtomicsCompareExchange) {
   HandleScope scope(isolate);
@@ -373,8 +354,8 @@
   CONVERT_SIZE_ARG_CHECKED(index, 1);
   CONVERT_NUMBER_ARG_HANDLE_CHECKED(oldobj, 2);
   CONVERT_NUMBER_ARG_HANDLE_CHECKED(newobj, 3);
-  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
-  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
+  CHECK(sta->GetBuffer()->is_shared());
+  CHECK_LT(index, NumberToSize(isolate, sta->length()));
 
   uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
                     NumberToSize(isolate, sta->byte_offset());
@@ -400,77 +381,14 @@
 }
 
 
-RUNTIME_FUNCTION(Runtime_AtomicsLoad) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 2);
-  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
-  CONVERT_SIZE_ARG_CHECKED(index, 1);
-  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
-  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
-
-  uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
-                    NumberToSize(isolate, sta->byte_offset());
-
-  switch (sta->type()) {
-#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
-  case kExternal##Type##Array:                              \
-    return DoLoad<ctype>(isolate, source, index);
-
-    INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
-#undef TYPED_ARRAY_CASE
-
-    case kExternalUint8ClampedArray:
-      return DoLoad<uint8_t>(isolate, source, index);
-
-    default:
-      break;
-  }
-
-  UNREACHABLE();
-  return isolate->heap()->undefined_value();
-}
-
-
-RUNTIME_FUNCTION(Runtime_AtomicsStore) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 3);
-  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
-  CONVERT_SIZE_ARG_CHECKED(index, 1);
-  CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
-  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
-  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
-
-  uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
-                    NumberToSize(isolate, sta->byte_offset());
-
-  switch (sta->type()) {
-#define TYPED_ARRAY_CASE(Type, typeName, TYPE, ctype, size) \
-  case kExternal##Type##Array:                              \
-    return DoStore<ctype>(isolate, source, index, value);
-
-    INTEGER_TYPED_ARRAYS(TYPED_ARRAY_CASE)
-#undef TYPED_ARRAY_CASE
-
-    case kExternalUint8ClampedArray:
-      return DoStoreUint8Clamped(isolate, source, index, value);
-
-    default:
-      break;
-  }
-
-  UNREACHABLE();
-  return isolate->heap()->undefined_value();
-}
-
-
 RUNTIME_FUNCTION(Runtime_AtomicsAdd) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 3);
   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
   CONVERT_SIZE_ARG_CHECKED(index, 1);
   CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
-  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
-  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
+  CHECK(sta->GetBuffer()->is_shared());
+  CHECK_LT(index, NumberToSize(isolate, sta->length()));
 
   uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
                     NumberToSize(isolate, sta->byte_offset());
@@ -501,8 +419,8 @@
   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
   CONVERT_SIZE_ARG_CHECKED(index, 1);
   CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
-  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
-  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
+  CHECK(sta->GetBuffer()->is_shared());
+  CHECK_LT(index, NumberToSize(isolate, sta->length()));
 
   uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
                     NumberToSize(isolate, sta->byte_offset());
@@ -533,8 +451,8 @@
   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
   CONVERT_SIZE_ARG_CHECKED(index, 1);
   CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
-  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
-  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
+  CHECK(sta->GetBuffer()->is_shared());
+  CHECK_LT(index, NumberToSize(isolate, sta->length()));
 
   uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
                     NumberToSize(isolate, sta->byte_offset());
@@ -565,8 +483,8 @@
   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
   CONVERT_SIZE_ARG_CHECKED(index, 1);
   CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
-  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
-  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
+  CHECK(sta->GetBuffer()->is_shared());
+  CHECK_LT(index, NumberToSize(isolate, sta->length()));
 
   uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
                     NumberToSize(isolate, sta->byte_offset());
@@ -597,8 +515,8 @@
   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
   CONVERT_SIZE_ARG_CHECKED(index, 1);
   CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
-  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
-  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
+  CHECK(sta->GetBuffer()->is_shared());
+  CHECK_LT(index, NumberToSize(isolate, sta->length()));
 
   uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
                     NumberToSize(isolate, sta->byte_offset());
@@ -629,8 +547,8 @@
   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
   CONVERT_SIZE_ARG_CHECKED(index, 1);
   CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);
-  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
-  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
+  CHECK(sta->GetBuffer()->is_shared());
+  CHECK_LT(index, NumberToSize(isolate, sta->length()));
 
   uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
                     NumberToSize(isolate, sta->byte_offset());
diff --git a/src/runtime/runtime-classes.cc b/src/runtime/runtime-classes.cc
index 3f10225..303122f 100644
--- a/src/runtime/runtime-classes.cc
+++ b/src/runtime/runtime-classes.cc
@@ -88,25 +88,21 @@
   Handle<Object> prototype_parent;
   Handle<Object> constructor_parent;
 
-  if (super_class->IsTheHole()) {
+  if (super_class->IsTheHole(isolate)) {
     prototype_parent = isolate->initial_object_prototype();
   } else {
-    if (super_class->IsNull()) {
+    if (super_class->IsNull(isolate)) {
       prototype_parent = isolate->factory()->null_value();
     } else if (super_class->IsConstructor()) {
-      if (super_class->IsJSFunction() &&
-          Handle<JSFunction>::cast(super_class)->shared()->is_generator()) {
-        THROW_NEW_ERROR(
-            isolate,
-            NewTypeError(MessageTemplate::kExtendsValueGenerator, super_class),
-            Object);
-      }
+      DCHECK(!super_class->IsJSFunction() ||
+             !Handle<JSFunction>::cast(super_class)->shared()->is_resumable());
       ASSIGN_RETURN_ON_EXCEPTION(
           isolate, prototype_parent,
           Runtime::GetObjectProperty(isolate, super_class,
                                      isolate->factory()->prototype_string()),
           Object);
-      if (!prototype_parent->IsNull() && !prototype_parent->IsJSReceiver()) {
+      if (!prototype_parent->IsNull(isolate) &&
+          !prototype_parent->IsJSReceiver()) {
         THROW_NEW_ERROR(
             isolate, NewTypeError(MessageTemplate::kPrototypeParentNotAnObject,
                                   prototype_parent),
@@ -114,10 +110,10 @@
       }
       constructor_parent = super_class;
     } else {
-      THROW_NEW_ERROR(
-          isolate,
-          NewTypeError(MessageTemplate::kExtendsValueNotFunction, super_class),
-          Object);
+      THROW_NEW_ERROR(isolate,
+                      NewTypeError(MessageTemplate::kExtendsValueNotConstructor,
+                                   super_class),
+                      Object);
     }
   }
 
@@ -128,7 +124,7 @@
   map->SetConstructor(*constructor);
   Handle<JSObject> prototype = isolate->factory()->NewJSObjectFromMap(map);
 
-  if (!super_class->IsTheHole()) {
+  if (!super_class->IsTheHole(isolate)) {
     // Derived classes, just like builtins, don't create implicit receivers in
     // [[construct]]. Instead they just set up new.target and call into the
     // constructor. Hence we can reuse the builtins construct stub for derived
@@ -186,22 +182,12 @@
   CONVERT_SMI_ARG_CHECKED(start_position, 2);
   CONVERT_SMI_ARG_CHECKED(end_position, 3);
 
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, DefineClass(isolate, super_class, constructor,
-                                   start_position, end_position));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, DefineClass(isolate, super_class, constructor, start_position,
+                           end_position));
 }
 
 
-RUNTIME_FUNCTION(Runtime_FinalizeClassDefinition) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 2);
-  CONVERT_ARG_HANDLE_CHECKED(JSObject, constructor, 0);
-  JSObject::MigrateSlowToFast(constructor, 0, "RuntimeToFastProperties");
-  return *constructor;
-}
-
 static MaybeHandle<Object> LoadFromSuper(Isolate* isolate,
                                          Handle<Object> receiver,
                                          Handle<JSObject> home_object,
@@ -255,10 +241,8 @@
   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
 
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, LoadFromSuper(isolate, receiver, home_object, name));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate,
+                           LoadFromSuper(isolate, receiver, home_object, name));
 }
 
 
@@ -270,13 +254,10 @@
   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
 
   uint32_t index = 0;
-  Handle<Object> result;
 
   if (key->ToArrayIndex(&index)) {
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-        isolate, result,
-        LoadElementFromSuper(isolate, receiver, home_object, index));
-    return *result;
+    RETURN_RESULT_OR_FAILURE(
+        isolate, LoadElementFromSuper(isolate, receiver, home_object, index));
   }
 
   Handle<Name> name;
@@ -284,14 +265,11 @@
                                      Object::ToName(isolate, key));
   // TODO(verwaest): Unify using LookupIterator.
   if (name->AsArrayIndex(&index)) {
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-        isolate, result,
-        LoadElementFromSuper(isolate, receiver, home_object, index));
-    return *result;
+    RETURN_RESULT_OR_FAILURE(
+        isolate, LoadElementFromSuper(isolate, receiver, home_object, index));
   }
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, LoadFromSuper(isolate, receiver, home_object, name));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate,
+                           LoadFromSuper(isolate, receiver, home_object, name));
 }
 
 
diff --git a/src/runtime/runtime-collections.cc b/src/runtime/runtime-collections.cc
index 32340e5..b25a5ef 100644
--- a/src/runtime/runtime-collections.cc
+++ b/src/runtime/runtime-collections.cc
@@ -31,7 +31,7 @@
   SealHandleScope shs(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_CHECKED(JSObject, object, 0);
-  RUNTIME_ASSERT(object->IsJSSet() || object->IsJSMap());
+  CHECK(object->IsJSSet() || object->IsJSMap());
   return static_cast<JSCollection*>(object)->table();
 }
 
@@ -40,8 +40,8 @@
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
-  Handle<Smi> hash = Object::GetOrCreateHash(isolate, object);
-  return *hash;
+  Smi* hash = Object::GetOrCreateHash(isolate, object);
+  return hash;
 }
 
 
@@ -91,8 +91,8 @@
   CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
   CONVERT_ARG_HANDLE_CHECKED(JSSet, set, 1);
   CONVERT_SMI_ARG_CHECKED(kind, 2)
-  RUNTIME_ASSERT(kind == JSSetIterator::kKindValues ||
-                 kind == JSSetIterator::kKindEntries);
+  CHECK(kind == JSSetIterator::kKindValues ||
+        kind == JSSetIterator::kKindEntries);
   Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()));
   holder->set_table(*table);
   holder->set_index(Smi::FromInt(0));
@@ -186,9 +186,9 @@
   CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
   CONVERT_ARG_HANDLE_CHECKED(JSMap, map, 1);
   CONVERT_SMI_ARG_CHECKED(kind, 2)
-  RUNTIME_ASSERT(kind == JSMapIterator::kKindKeys ||
-                 kind == JSMapIterator::kKindValues ||
-                 kind == JSMapIterator::kKindEntries);
+  CHECK(kind == JSMapIterator::kKindKeys ||
+        kind == JSMapIterator::kKindValues ||
+        kind == JSMapIterator::kKindEntries);
   Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()));
   holder->set_table(*table);
   holder->set_index(Smi::FromInt(0));
@@ -232,7 +232,7 @@
   DCHECK(args.length() == 2);
   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0);
   CONVERT_NUMBER_CHECKED(int, max_entries, Int32, args[1]);
-  RUNTIME_ASSERT(max_entries >= 0);
+  CHECK(max_entries >= 0);
 
   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
   if (max_entries == 0 || max_entries > table->NumberOfElements()) {
@@ -250,7 +250,7 @@
     int count = 0;
     for (int i = 0; count / 2 < max_entries && i < table->Capacity(); i++) {
       Handle<Object> key(table->KeyAt(i), isolate);
-      if (table->IsKey(*key)) {
+      if (table->IsKey(isolate, *key)) {
         entries->set(count++, *key);
         Object* value = table->Lookup(key);
         entries->set(count++, value);
@@ -286,12 +286,13 @@
   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
   CONVERT_SMI_ARG_CHECKED(hash, 2)
-  RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
+  CHECK(key->IsJSReceiver() || key->IsSymbol());
   Handle<ObjectHashTable> table(
       ObjectHashTable::cast(weak_collection->table()));
-  RUNTIME_ASSERT(table->IsKey(*key));
+  CHECK(table->IsKey(isolate, *key));
   Handle<Object> lookup(table->Lookup(key, hash), isolate);
-  return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
+  return lookup->IsTheHole(isolate) ? isolate->heap()->undefined_value()
+                                    : *lookup;
 }
 
 
@@ -301,12 +302,12 @@
   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
   CONVERT_SMI_ARG_CHECKED(hash, 2)
-  RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
+  CHECK(key->IsJSReceiver() || key->IsSymbol());
   Handle<ObjectHashTable> table(
       ObjectHashTable::cast(weak_collection->table()));
-  RUNTIME_ASSERT(table->IsKey(*key));
+  CHECK(table->IsKey(isolate, *key));
   Handle<Object> lookup(table->Lookup(key, hash), isolate);
-  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
+  return isolate->heap()->ToBoolean(!lookup->IsTheHole(isolate));
 }
 
 
@@ -316,10 +317,10 @@
   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
   CONVERT_SMI_ARG_CHECKED(hash, 2)
-  RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
+  CHECK(key->IsJSReceiver() || key->IsSymbol());
   Handle<ObjectHashTable> table(
       ObjectHashTable::cast(weak_collection->table()));
-  RUNTIME_ASSERT(table->IsKey(*key));
+  CHECK(table->IsKey(isolate, *key));
   bool was_present = JSWeakCollection::Delete(weak_collection, key, hash);
   return isolate->heap()->ToBoolean(was_present);
 }
@@ -330,12 +331,12 @@
   DCHECK(args.length() == 4);
   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
-  RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
+  CHECK(key->IsJSReceiver() || key->IsSymbol());
   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
   CONVERT_SMI_ARG_CHECKED(hash, 3)
   Handle<ObjectHashTable> table(
       ObjectHashTable::cast(weak_collection->table()));
-  RUNTIME_ASSERT(table->IsKey(*key));
+  CHECK(table->IsKey(isolate, *key));
   JSWeakCollection::Set(weak_collection, key, value, hash);
   return *weak_collection;
 }
@@ -346,7 +347,7 @@
   DCHECK(args.length() == 2);
   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, holder, 0);
   CONVERT_NUMBER_CHECKED(int, max_values, Int32, args[1]);
-  RUNTIME_ASSERT(max_values >= 0);
+  CHECK(max_values >= 0);
 
   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
   if (max_values == 0 || max_values > table->NumberOfElements()) {
@@ -361,21 +362,12 @@
     DisallowHeapAllocation no_gc;
     int count = 0;
     for (int i = 0; count < max_values && i < table->Capacity(); i++) {
-      Handle<Object> key(table->KeyAt(i), isolate);
-      if (table->IsKey(*key)) values->set(count++, *key);
+      Object* key = table->KeyAt(i);
+      if (table->IsKey(isolate, key)) values->set(count++, key);
     }
     DCHECK_EQ(max_values, count);
   }
   return *isolate->factory()->NewJSArrayWithElements(values);
 }
-
-
-RUNTIME_FUNCTION(Runtime_ObservationWeakMapCreate) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 0);
-  Handle<JSWeakMap> weakmap = isolate->factory()->NewJSWeakMap();
-  JSWeakCollection::Initialize(weakmap, isolate);
-  return *weakmap;
-}
 }  // namespace internal
 }  // namespace v8
diff --git a/src/runtime/runtime-compiler.cc b/src/runtime/runtime-compiler.cc
index 89a6fa1..c095045 100644
--- a/src/runtime/runtime-compiler.cc
+++ b/src/runtime/runtime-compiler.cc
@@ -19,7 +19,7 @@
 
 RUNTIME_FUNCTION(Runtime_CompileLazy) {
   HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
+  DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
 
 #ifdef DEBUG
@@ -39,10 +39,22 @@
   return function->code();
 }
 
+RUNTIME_FUNCTION(Runtime_CompileBaseline) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(1, args.length());
+  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+  StackLimitCheck check(isolate);
+  if (check.JsHasOverflowed(1 * KB)) return isolate->StackOverflow();
+  if (!Compiler::CompileBaseline(function)) {
+    return isolate->heap()->exception();
+  }
+  DCHECK(function->is_compiled());
+  return function->code();
+}
 
 RUNTIME_FUNCTION(Runtime_CompileOptimized_Concurrent) {
   HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
+  DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
   StackLimitCheck check(isolate);
   if (check.JsHasOverflowed(1 * KB)) return isolate->StackOverflow();
@@ -56,7 +68,7 @@
 
 RUNTIME_FUNCTION(Runtime_CompileOptimized_NotConcurrent) {
   HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
+  DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
   StackLimitCheck check(isolate);
   if (check.JsHasOverflowed(1 * KB)) return isolate->StackOverflow();
@@ -190,7 +202,7 @@
   // We're not prepared to handle a function with arguments object.
   DCHECK(!function->shared()->uses_arguments());
 
-  RUNTIME_ASSERT(FLAG_use_osr);
+  CHECK(FLAG_use_osr);
 
   // Passing the PC in the javascript frame from the caller directly is
   // not GC safe, so we walk the stack to get it.
@@ -291,7 +303,7 @@
 
 bool CodeGenerationFromStringsAllowed(Isolate* isolate,
                                       Handle<Context> context) {
-  DCHECK(context->allow_code_gen_from_strings()->IsFalse());
+  DCHECK(context->allow_code_gen_from_strings()->IsFalse(isolate));
   // Check with callback if set.
   AllowCodeGenerationFromStringsCallback callback =
       isolate->allow_code_gen_callback();
@@ -305,17 +317,16 @@
   }
 }
 
-
 static Object* CompileGlobalEval(Isolate* isolate, Handle<String> source,
                                  Handle<SharedFunctionInfo> outer_info,
                                  LanguageMode language_mode,
-                                 int scope_position) {
+                                 int eval_scope_position, int eval_position) {
   Handle<Context> context = Handle<Context>(isolate->context());
   Handle<Context> native_context = Handle<Context>(context->native_context());
 
   // Check if native context allows code generation from
   // strings. Throw an exception if it doesn't.
-  if (native_context->allow_code_gen_from_strings()->IsFalse() &&
+  if (native_context->allow_code_gen_from_strings()->IsFalse(isolate) &&
       !CodeGenerationFromStringsAllowed(isolate, native_context)) {
     Handle<Object> error_message =
         native_context->ErrorMessageForCodeGenerationFromStrings();
@@ -331,9 +342,9 @@
   static const ParseRestriction restriction = NO_PARSE_RESTRICTION;
   Handle<JSFunction> compiled;
   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-      isolate, compiled,
-      Compiler::GetFunctionFromEval(source, outer_info, context, language_mode,
-                                    restriction, scope_position),
+      isolate, compiled, Compiler::GetFunctionFromEval(
+                             source, outer_info, context, language_mode,
+                             restriction, eval_scope_position, eval_position),
       isolate->heap()->exception());
   return *compiled;
 }
@@ -341,7 +352,7 @@
 
 RUNTIME_FUNCTION(Runtime_ResolvePossiblyDirectEval) {
   HandleScope scope(isolate);
-  DCHECK(args.length() == 5);
+  DCHECK(args.length() == 6);
 
   Handle<Object> callee = args.at<Object>(0);
 
@@ -362,7 +373,7 @@
   Handle<SharedFunctionInfo> outer_info(args.at<JSFunction>(2)->shared(),
                                         isolate);
   return CompileGlobalEval(isolate, args.at<String>(1), outer_info,
-                           language_mode, args.smi_at(4));
+                           language_mode, args.smi_at(4), args.smi_at(5));
 }
 }  // namespace internal
 }  // namespace v8
diff --git a/src/runtime/runtime-debug.cc b/src/runtime/runtime-debug.cc
index ad8375a..b3be8f7 100644
--- a/src/runtime/runtime-debug.cc
+++ b/src/runtime/runtime-debug.cc
@@ -42,6 +42,9 @@
   JavaScriptFrameIterator it(isolate);
   isolate->debug()->Break(it.frame());
 
+  // If live-edit has dropped frames, we are not going back to dispatch.
+  if (LiveEdit::SetAfterBreakTarget(isolate->debug())) return Smi::FromInt(0);
+
   // Return the handler from the original bytecode array.
   DCHECK(it.frame()->is_interpreted());
   InterpretedFrame* interpreted_frame =
@@ -73,8 +76,8 @@
 RUNTIME_FUNCTION(Runtime_SetDebugEventListener) {
   SealHandleScope shs(isolate);
   DCHECK(args.length() == 2);
-  RUNTIME_ASSERT(args[0]->IsJSFunction() || args[0]->IsUndefined() ||
-                 args[0]->IsNull());
+  RUNTIME_ASSERT(args[0]->IsJSFunction() || args[0]->IsUndefined(isolate) ||
+                 args[0]->IsNull(isolate));
   CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, data, 1);
   isolate->debug()->SetEventListener(callback, data);
@@ -142,7 +145,7 @@
     Isolate* isolate, Handle<IteratorType> object) {
   Factory* factory = isolate->factory();
   Handle<IteratorType> iterator = Handle<IteratorType>::cast(object);
-  RUNTIME_ASSERT_HANDLIFIED(iterator->kind()->IsSmi(), JSArray);
+  CHECK(iterator->kind()->IsSmi());
   const char* kind = NULL;
   switch (Smi::cast(iterator->kind())->value()) {
     case IteratorType::kKindKeys:
@@ -155,7 +158,7 @@
       kind = "entries";
       break;
     default:
-      RUNTIME_ASSERT_HANDLIFIED(false, JSArray);
+      UNREACHABLE();
   }
 
   Handle<FixedArray> result = factory->NewFixedArray(2 * 3);
@@ -240,12 +243,12 @@
     result->set(4, *receiver);
     result->set(5, generator->receiver());
     return factory->NewJSArrayWithElements(result);
-  } else if (Object::IsPromise(object)) {
+  } else if (object->IsJSPromise()) {
     Handle<JSObject> promise = Handle<JSObject>::cast(object);
 
     Handle<Object> status_obj =
-        DebugGetProperty(promise, isolate->factory()->promise_status_symbol());
-    RUNTIME_ASSERT_HANDLIFIED(status_obj->IsSmi(), JSArray);
+        DebugGetProperty(promise, isolate->factory()->promise_state_symbol());
+    CHECK(status_obj->IsSmi());
     const char* status = "rejected";
     int status_val = Handle<Smi>::cast(status_obj)->value();
     switch (status_val) {
@@ -267,12 +270,31 @@
     result->set(1, *status_str);
 
     Handle<Object> value_obj =
-        DebugGetProperty(promise, isolate->factory()->promise_value_symbol());
+        DebugGetProperty(promise, isolate->factory()->promise_result_symbol());
     Handle<String> promise_value =
         factory->NewStringFromAsciiChecked("[[PromiseValue]]");
     result->set(2, *promise_value);
     result->set(3, *value_obj);
     return factory->NewJSArrayWithElements(result);
+  } else if (object->IsJSProxy()) {
+    Handle<JSProxy> js_proxy = Handle<JSProxy>::cast(object);
+    Handle<FixedArray> result = factory->NewFixedArray(3 * 2);
+
+    Handle<String> handler_str =
+        factory->NewStringFromAsciiChecked("[[Handler]]");
+    result->set(0, *handler_str);
+    result->set(1, js_proxy->handler());
+
+    Handle<String> target_str =
+        factory->NewStringFromAsciiChecked("[[Target]]");
+    result->set(2, *target_str);
+    result->set(3, js_proxy->target());
+
+    Handle<String> is_revoked_str =
+        factory->NewStringFromAsciiChecked("[[IsRevoked]]");
+    result->set(4, *is_revoked_str);
+    result->set(5, isolate->heap()->ToBoolean(js_proxy->IsRevoked()));
+    return factory->NewJSArrayWithElements(result);
   } else if (object->IsJSValue()) {
     Handle<JSValue> js_value = Handle<JSValue>::cast(object);
 
@@ -291,10 +313,8 @@
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
-  Handle<JSArray> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, Runtime::GetInternalProperties(isolate, obj));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate,
+                           Runtime::GetInternalProperties(isolate, obj));
 }
 
 
@@ -339,7 +359,7 @@
     return *isolate->factory()->NewJSArrayWithElements(details);
   }
 
-  LookupIterator it(obj, name, LookupIterator::HIDDEN);
+  LookupIterator it(obj, name, LookupIterator::OWN);
   bool has_caught = false;
   Handle<Object> value = DebugGetProperty(&it, &has_caught);
   if (!it.IsFound()) return isolate->heap()->undefined_value();
@@ -410,50 +430,6 @@
 }
 
 
-// Return the property insertion index calculated from the property details.
-// args[0]: smi with property details.
-RUNTIME_FUNCTION(Runtime_DebugPropertyIndexFromDetails) {
-  SealHandleScope shs(isolate);
-  DCHECK(args.length() == 1);
-  CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
-  // TODO(verwaest): Works only for dictionary mode holders.
-  return Smi::FromInt(details.dictionary_index());
-}
-
-
-// Return property value from named interceptor.
-// args[0]: object
-// args[1]: property name
-RUNTIME_FUNCTION(Runtime_DebugNamedInterceptorPropertyValue) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 2);
-  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
-  RUNTIME_ASSERT(obj->HasNamedInterceptor());
-  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
-
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     JSObject::GetProperty(obj, name));
-  return *result;
-}
-
-
-// Return element value from indexed interceptor.
-// args[0]: object
-// args[1]: index
-RUNTIME_FUNCTION(Runtime_DebugIndexedInterceptorElementValue) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 2);
-  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
-  RUNTIME_ASSERT(obj->HasIndexedInterceptor());
-  CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, JSReceiver::GetElement(isolate, obj, index));
-  return *result;
-}
-
-
 RUNTIME_FUNCTION(Runtime_CheckExecutionState) {
   SealHandleScope shs(isolate);
   DCHECK(args.length() == 1);
@@ -571,7 +547,9 @@
   for (int slot = 0; slot < scope_info->LocalCount(); ++slot) {
     // Hide compiler-introduced temporary variables, whether on the stack or on
     // the context.
-    if (scope_info->LocalIsSynthetic(slot)) local_count--;
+    if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(slot))) {
+      local_count--;
+    }
   }
 
   Handle<FixedArray> locals =
@@ -582,12 +560,15 @@
   int i = 0;
   for (; i < scope_info->StackLocalCount(); ++i) {
     // Use the value from the stack.
-    if (scope_info->LocalIsSynthetic(i)) continue;
+    if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(i))) continue;
     locals->set(local * 2, scope_info->LocalName(i));
-    Handle<Object> value = frame_inspector.GetExpression(i);
+    Handle<Object> value =
+        frame_inspector.GetExpression(scope_info->StackLocalIndex(i));
     // TODO(yangguo): We convert optimized out values to {undefined} when they
     // are passed to the debugger. Eventually we should handle them somehow.
-    if (value->IsOptimizedOut()) value = isolate->factory()->undefined_value();
+    if (value->IsOptimizedOut(isolate)) {
+      value = isolate->factory()->undefined_value();
+    }
     locals->set(local * 2 + 1, *value);
     local++;
   }
@@ -596,8 +577,8 @@
     Handle<Context> context(
         Handle<Context>::cast(frame_inspector.GetContext())->closure_context());
     for (; i < scope_info->LocalCount(); ++i) {
-      if (scope_info->LocalIsSynthetic(i)) continue;
       Handle<String> name(scope_info->LocalName(i));
+      if (ScopeInfo::VariableIsSynthetic(*name)) continue;
       VariableMode mode;
       InitializationFlag init_flag;
       MaybeAssignedFlag maybe_assigned_flag;
@@ -784,10 +765,7 @@
   if (it.Done()) {
     return isolate->heap()->undefined_value();
   }
-  Handle<JSObject> details;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
-                                     it.MaterializeScopeDetails());
-  return *details;
+  RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
 }
 
 
@@ -876,10 +854,7 @@
     return isolate->heap()->undefined_value();
   }
 
-  Handle<JSObject> details;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, details,
-                                     it.MaterializeScopeDetails());
-  return *details;
+  RETURN_RESULT_OR_FAILURE(isolate, it.MaterializeScopeDetails());
 }
 
 
@@ -958,78 +933,6 @@
 }
 
 
-RUNTIME_FUNCTION(Runtime_GetThreadCount) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
-  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
-  RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
-
-  // Count all archived V8 threads.
-  int n = 0;
-  for (ThreadState* thread = isolate->thread_manager()->FirstThreadStateInUse();
-       thread != NULL; thread = thread->Next()) {
-    n++;
-  }
-
-  // Total number of threads is current thread and archived threads.
-  return Smi::FromInt(n + 1);
-}
-
-
-static const int kThreadDetailsCurrentThreadIndex = 0;
-static const int kThreadDetailsThreadIdIndex = 1;
-static const int kThreadDetailsSize = 2;
-
-// Return an array with thread details
-// args[0]: number: break id
-// args[1]: number: thread index
-//
-// The array returned contains the following information:
-// 0: Is current thread?
-// 1: Thread id
-RUNTIME_FUNCTION(Runtime_GetThreadDetails) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 2);
-  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
-  RUNTIME_ASSERT(isolate->debug()->CheckExecutionState(break_id));
-
-  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
-
-  // Allocate array for result.
-  Handle<FixedArray> details =
-      isolate->factory()->NewFixedArray(kThreadDetailsSize);
-
-  // Thread index 0 is current thread.
-  if (index == 0) {
-    // Fill the details.
-    details->set(kThreadDetailsCurrentThreadIndex,
-                 isolate->heap()->true_value());
-    details->set(kThreadDetailsThreadIdIndex,
-                 Smi::FromInt(ThreadId::Current().ToInteger()));
-  } else {
-    // Find the thread with the requested index.
-    int n = 1;
-    ThreadState* thread = isolate->thread_manager()->FirstThreadStateInUse();
-    while (index != n && thread != NULL) {
-      thread = thread->Next();
-      n++;
-    }
-    if (thread == NULL) {
-      return isolate->heap()->undefined_value();
-    }
-
-    // Fill the details.
-    details->set(kThreadDetailsCurrentThreadIndex,
-                 isolate->heap()->false_value());
-    details->set(kThreadDetailsThreadIdIndex,
-                 Smi::FromInt(thread->id().ToInteger()));
-  }
-
-  // Convert to JS array and return.
-  return *isolate->factory()->NewJSArrayWithElements(details);
-}
-
-
 // Sets the disable break state
 // args[0]: disable break state
 RUNTIME_FUNCTION(Runtime_SetBreakPointsActive) {
@@ -1063,7 +966,9 @@
   // Find the number of break points
   Handle<Object> break_locations =
       Debug::GetSourceBreakLocations(shared, alignment);
-  if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
+  if (break_locations->IsUndefined(isolate)) {
+    return isolate->heap()->undefined_value();
+  }
   // Return array as JS array
   return *isolate->factory()->NewJSArrayWithElements(
       Handle<FixedArray>::cast(break_locations));
@@ -1233,12 +1138,9 @@
 
   StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
 
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      DebugEvaluate::Local(isolate, id, inlined_jsframe_index, source,
-                           disable_break, context_extension));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, DebugEvaluate::Local(isolate, id, inlined_jsframe_index, source,
+                                    disable_break, context_extension));
 }
 
 
@@ -1255,11 +1157,9 @@
   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
   CONVERT_ARG_HANDLE_CHECKED(HeapObject, context_extension, 3);
 
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
+  RETURN_RESULT_OR_FAILURE(
+      isolate,
       DebugEvaluate::Global(isolate, source, disable_break, context_extension));
-  return *result;
 }
 
 
@@ -1292,16 +1192,13 @@
   }
 
   // Return result as a JS array.
-  Handle<JSObject> result =
-      isolate->factory()->NewJSObject(isolate->array_function());
-  JSArray::SetContent(Handle<JSArray>::cast(result), instances);
-  return *result;
+  return *isolate->factory()->NewJSArrayWithElements(instances);
 }
 
 static bool HasInPrototypeChainIgnoringProxies(Isolate* isolate,
                                                JSObject* object,
                                                Object* proto) {
-  PrototypeIterator iter(isolate, object, PrototypeIterator::START_AT_RECEIVER);
+  PrototypeIterator iter(isolate, object, kStartAtReceiver);
   while (true) {
     iter.AdvanceIgnoringProxies();
     if (iter.IsAtEnd()) return false;
@@ -1319,7 +1216,7 @@
   DCHECK(args.length() == 3);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, filter, 1);
-  RUNTIME_ASSERT(filter->IsUndefined() || filter->IsJSObject());
+  RUNTIME_ASSERT(filter->IsUndefined(isolate) || filter->IsJSObject());
   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
   RUNTIME_ASSERT(max_references >= 0);
 
@@ -1338,7 +1235,7 @@
       if (!obj->ReferencesObject(*target)) continue;
       // Check filter if supplied. This is normally used to avoid
       // references from mirror objects.
-      if (!filter->IsUndefined() &&
+      if (!filter->IsUndefined(isolate) &&
           HasInPrototypeChainIgnoringProxies(isolate, obj, *filter)) {
         continue;
       }
@@ -1408,12 +1305,9 @@
   HandleScope shs(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
-  Handle<Object> prototype;
   // TODO(1543): Come up with a solution for clients to handle potential errors
   // thrown by an intermediate proxy.
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, prototype,
-                                     JSReceiver::GetPrototype(isolate, obj));
-  return *prototype;
+  RETURN_RESULT_OR_FAILURE(isolate, JSReceiver::GetPrototype(isolate, obj));
 }
 
 
@@ -1455,11 +1349,12 @@
   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
 
   if (function->IsJSBoundFunction()) {
-    return Handle<JSBoundFunction>::cast(function)->name();
+    RETURN_RESULT_OR_FAILURE(
+        isolate, JSBoundFunction::GetName(
+                     isolate, Handle<JSBoundFunction>::cast(function)));
+  } else {
+    return *JSFunction::GetDebugName(Handle<JSFunction>::cast(function));
   }
-  Handle<Object> name =
-      JSFunction::GetDebugName(Handle<JSFunction>::cast(function));
-  return *name;
 }
 
 
@@ -1515,12 +1410,9 @@
     return isolate->heap()->exception();
   }
 
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      Execution::Call(isolate, function, handle(function->global_proxy()), 0,
-                      NULL));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, Execution::Call(isolate, function,
+                               handle(function->global_proxy()), 0, NULL));
 }
 
 
@@ -1593,27 +1485,240 @@
   return *Script::GetWrapper(found);
 }
 
+RUNTIME_FUNCTION(Runtime_ScriptLineCount) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 1);
+  CONVERT_ARG_CHECKED(JSValue, script, 0);
+
+  RUNTIME_ASSERT(script->value()->IsScript());
+  Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
+
+  Script::InitLineEnds(script_handle);
+
+  FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
+  return Smi::FromInt(line_ends_array->length());
+}
+
+RUNTIME_FUNCTION(Runtime_ScriptLineStartPosition) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 2);
+  CONVERT_ARG_CHECKED(JSValue, script, 0);
+  CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
+
+  RUNTIME_ASSERT(script->value()->IsScript());
+  Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
+
+  Script::InitLineEnds(script_handle);
+
+  FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
+  const int line_count = line_ends_array->length();
+
+  // If line == line_count, we return the first position beyond the last line.
+  if (line < 0 || line > line_count) {
+    return Smi::FromInt(-1);
+  } else if (line == 0) {
+    return Smi::FromInt(0);
+  } else {
+    DCHECK(0 < line && line <= line_count);
+    const int pos = Smi::cast(line_ends_array->get(line - 1))->value() + 1;
+    return Smi::FromInt(pos);
+  }
+}
+
+RUNTIME_FUNCTION(Runtime_ScriptLineEndPosition) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 2);
+  CONVERT_ARG_CHECKED(JSValue, script, 0);
+  CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
+
+  RUNTIME_ASSERT(script->value()->IsScript());
+  Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
+
+  Script::InitLineEnds(script_handle);
+
+  FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
+  const int line_count = line_ends_array->length();
+
+  if (line < 0 || line >= line_count) {
+    return Smi::FromInt(-1);
+  } else {
+    return Smi::cast(line_ends_array->get(line));
+  }
+}
+
+static Handle<Object> GetJSPositionInfo(Handle<Script> script, int position,
+                                        Script::OffsetFlag offset_flag,
+                                        Isolate* isolate) {
+  Script::PositionInfo info;
+  if (!script->GetPositionInfo(position, &info, offset_flag)) {
+    return handle(isolate->heap()->null_value(), isolate);
+  }
+
+  Handle<String> source = handle(String::cast(script->source()), isolate);
+  Handle<String> sourceText =
+      isolate->factory()->NewSubString(source, info.line_start, info.line_end);
+
+  Handle<JSObject> jsinfo =
+      isolate->factory()->NewJSObject(isolate->object_function());
+
+  JSObject::AddProperty(jsinfo, isolate->factory()->script_string(), script,
+                        NONE);
+  JSObject::AddProperty(jsinfo, isolate->factory()->position_string(),
+                        handle(Smi::FromInt(position), isolate), NONE);
+  JSObject::AddProperty(jsinfo, isolate->factory()->line_string(),
+                        handle(Smi::FromInt(info.line), isolate), NONE);
+  JSObject::AddProperty(jsinfo, isolate->factory()->column_string(),
+                        handle(Smi::FromInt(info.column), isolate), NONE);
+  JSObject::AddProperty(jsinfo, isolate->factory()->sourceText_string(),
+                        sourceText, NONE);
+
+  return jsinfo;
+}
+
+// Get information on a specific source line and column possibly offset by a
+// fixed source position. This function is used to find a source position from
+// a line and column position. The fixed source position offset is typically
+// used to find a source position in a function based on a line and column in
+// the source for the function alone. The offset passed will then be the
+// start position of the source for the function within the full script source.
+// Note that incoming line and column parameters may be undefined, and are
+// assumed to be passed *with* offsets.
+RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 4);
+  CONVERT_ARG_CHECKED(JSValue, script, 0);
+
+  RUNTIME_ASSERT(script->value()->IsScript());
+  Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
+
+  // Line and column are possibly undefined and we need to handle these cases,
+  // additionally subtracting corresponding offsets.
+
+  int32_t line;
+  if (args[1]->IsNull(isolate) || args[1]->IsUndefined(isolate)) {
+    line = 0;
+  } else {
+    RUNTIME_ASSERT(args[1]->IsNumber());
+    line = NumberToInt32(args[1]) - script_handle->line_offset();
+  }
+
+  int32_t column;
+  if (args[2]->IsNull(isolate) || args[2]->IsUndefined(isolate)) {
+    column = 0;
+  } else {
+    RUNTIME_ASSERT(args[2]->IsNumber());
+    column = NumberToInt32(args[2]);
+    if (line == 0) column -= script_handle->column_offset();
+  }
+
+  CONVERT_NUMBER_CHECKED(int32_t, offset_position, Int32, args[3]);
+
+  if (line < 0 || column < 0 || offset_position < 0) {
+    return isolate->heap()->null_value();
+  }
+
+  Script::InitLineEnds(script_handle);
+
+  FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
+  const int line_count = line_ends_array->length();
+
+  int position;
+  if (line == 0) {
+    position = offset_position + column;
+  } else {
+    Script::PositionInfo info;
+    if (!script_handle->GetPositionInfo(offset_position, &info,
+                                        Script::NO_OFFSET) ||
+        info.line + line >= line_count) {
+      return isolate->heap()->null_value();
+    }
+
+    const int offset_line = info.line + line;
+    const int offset_line_position =
+        (offset_line == 0)
+            ? 0
+            : Smi::cast(line_ends_array->get(offset_line - 1))->value() + 1;
+    position = offset_line_position + column;
+  }
+
+  return *GetJSPositionInfo(script_handle, position, Script::NO_OFFSET,
+                            isolate);
+}
+
+RUNTIME_FUNCTION(Runtime_ScriptPositionInfo) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 3);
+  CONVERT_ARG_CHECKED(JSValue, script, 0);
+  CONVERT_NUMBER_CHECKED(int32_t, position, Int32, args[1]);
+  CONVERT_BOOLEAN_ARG_CHECKED(with_offset, 2);
+
+  RUNTIME_ASSERT(script->value()->IsScript());
+  Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
+
+  const Script::OffsetFlag offset_flag =
+      with_offset ? Script::WITH_OFFSET : Script::NO_OFFSET;
+  return *GetJSPositionInfo(script_handle, position, offset_flag, isolate);
+}
+
+// Returns the given line as a string, or null if line is out of bounds.
+// The parameter line is expected to include the script's line offset.
+RUNTIME_FUNCTION(Runtime_ScriptSourceLine) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 2);
+  CONVERT_ARG_CHECKED(JSValue, script, 0);
+  CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
+
+  RUNTIME_ASSERT(script->value()->IsScript());
+  Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
+
+  Script::InitLineEnds(script_handle);
+
+  FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
+  const int line_count = line_ends_array->length();
+
+  line -= script_handle->line_offset();
+  if (line < 0 || line_count <= line) {
+    return isolate->heap()->null_value();
+  }
+
+  const int start =
+      (line == 0) ? 0 : Smi::cast(line_ends_array->get(line - 1))->value() + 1;
+  const int end = Smi::cast(line_ends_array->get(line))->value();
+
+  Handle<String> source =
+      handle(String::cast(script_handle->source()), isolate);
+  Handle<String> str = isolate->factory()->NewSubString(source, start, end);
+
+  return *str;
+}
 
 // Set one shot breakpoints for the callback function that is passed to a
 // built-in function such as Array.forEach to enable stepping into the callback,
 // if we are indeed stepping and the callback is subject to debugging.
 RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) {
-  DCHECK(args.length() == 1);
   HandleScope scope(isolate);
-  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
-  RUNTIME_ASSERT(object->IsJSFunction() || object->IsJSGeneratorObject());
-  Handle<JSFunction> fun;
-  if (object->IsJSFunction()) {
-    fun = Handle<JSFunction>::cast(object);
-  } else {
-    fun = Handle<JSFunction>(
-        Handle<JSGeneratorObject>::cast(object)->function(), isolate);
-  }
-
+  DCHECK_EQ(1, args.length());
+  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
   isolate->debug()->PrepareStepIn(fun);
   return isolate->heap()->undefined_value();
 }
 
+// Set one shot breakpoints for the suspended generator object.
+RUNTIME_FUNCTION(Runtime_DebugPrepareStepInSuspendedGenerator) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(0, args.length());
+  isolate->debug()->PrepareStepInSuspendedGenerator();
+  return isolate->heap()->undefined_value();
+}
+
+RUNTIME_FUNCTION(Runtime_DebugRecordAsyncFunction) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(1, args.length());
+  CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
+  CHECK(isolate->debug()->last_step_action() >= StepNext);
+  isolate->debug()->RecordAsyncFunction(generator);
+  return isolate->heap()->undefined_value();
+}
 
 RUNTIME_FUNCTION(Runtime_DebugPushPromise) {
   DCHECK(args.length() == 2);
@@ -1621,8 +1726,6 @@
   CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
   isolate->PushPromise(promise, function);
-  // If we are in step-in mode, flood the handler.
-  isolate->debug()->EnableStepIn();
   return isolate->heap()->undefined_value();
 }
 
diff --git a/src/runtime/runtime-forin.cc b/src/runtime/runtime-forin.cc
index 4b558d1..e57016a 100644
--- a/src/runtime/runtime-forin.cc
+++ b/src/runtime/runtime-forin.cc
@@ -22,14 +22,18 @@
 // deletions during a for-in.
 MaybeHandle<HeapObject> Enumerate(Handle<JSReceiver> receiver) {
   Isolate* const isolate = receiver->GetIsolate();
-  FastKeyAccumulator accumulator(isolate, receiver, INCLUDE_PROTOS,
+  JSObject::MakePrototypesFast(receiver, kStartAtReceiver, isolate);
+  FastKeyAccumulator accumulator(isolate, receiver,
+                                 KeyCollectionMode::kIncludePrototypes,
                                  ENUMERABLE_STRINGS);
   accumulator.set_filter_proxy_keys(false);
+  accumulator.set_is_for_in(true);
   // Test if we have an enum cache for {receiver}.
   if (!accumulator.is_receiver_simple_enum()) {
     Handle<FixedArray> keys;
-    ASSIGN_RETURN_ON_EXCEPTION(isolate, keys, accumulator.GetKeys(KEEP_NUMBERS),
-                               HeapObject);
+    ASSIGN_RETURN_ON_EXCEPTION(
+        isolate, keys, accumulator.GetKeys(GetKeysConversion::kKeepNumbers),
+        HeapObject);
     // Test again, since cache may have been built by GetKeys() calls above.
     if (!accumulator.is_receiver_simple_enum()) return keys;
   }
@@ -61,7 +65,7 @@
           Handle<Object> prototype;
           ASSIGN_RETURN_ON_EXCEPTION(isolate, prototype,
                                      JSProxy::GetPrototype(proxy), Object);
-          if (prototype->IsNull()) break;
+          if (prototype->IsNull(isolate)) break;
           // We already have a stack-check in JSProxy::GetPrototype.
           return HasEnumerableProperty(
               isolate, Handle<JSReceiver>::cast(prototype), key);
@@ -107,9 +111,7 @@
   HandleScope scope(isolate);
   DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
-  Handle<HeapObject> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Enumerate(receiver));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Enumerate(receiver));
 }
 
 
@@ -159,9 +161,7 @@
   DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Filter(receiver, key));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Filter(receiver, key));
 }
 
 
@@ -177,9 +177,7 @@
   if (receiver->map() == *cache_type) {
     return *key;
   }
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Filter(receiver, key));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Filter(receiver, key));
 }
 
 
diff --git a/src/runtime/runtime-function.cc b/src/runtime/runtime-function.cc
index 011f9ff..3a66869 100644
--- a/src/runtime/runtime-function.cc
+++ b/src/runtime/runtime-function.cc
@@ -10,7 +10,7 @@
 #include "src/frames-inl.h"
 #include "src/isolate-inl.h"
 #include "src/messages.h"
-#include "src/profiler/cpu-profiler.h"
+#include "src/wasm/wasm-module.h"
 
 namespace v8 {
 namespace internal {
@@ -21,14 +21,11 @@
 
   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
   if (function->IsJSBoundFunction()) {
-  Handle<Object> result;
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-        isolate, result, JSBoundFunction::GetName(
-                             isolate, Handle<JSBoundFunction>::cast(function)));
-    return *result;
+    RETURN_RESULT_OR_FAILURE(
+        isolate, JSBoundFunction::GetName(
+                     isolate, Handle<JSBoundFunction>::cast(function)));
   } else {
-    RUNTIME_ASSERT(function->IsJSFunction());
-    return Handle<JSFunction>::cast(function)->shared()->name();
+    return *JSFunction::GetName(isolate, Handle<JSFunction>::cast(function));
   }
 }
 
@@ -51,7 +48,7 @@
   DCHECK(args.length() == 1);
 
   CONVERT_ARG_CHECKED(JSFunction, f, 0);
-  RUNTIME_ASSERT(f->RemovePrototype());
+  CHECK(f->RemovePrototype());
   f->shared()->set_construct_stub(
       *isolate->builtins()->ConstructedNonConstructable());
 
@@ -131,8 +128,7 @@
 
   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
   CONVERT_SMI_ARG_CHECKED(length, 1);
-  RUNTIME_ASSERT((length & 0xC0000000) == 0xC0000000 ||
-                 (length & 0xC0000000) == 0x0);
+  CHECK((length & 0xC0000000) == 0xC0000000 || (length & 0xC0000000) == 0x0);
   fun->shared()->set_length(length);
   return isolate->heap()->undefined_value();
 }
@@ -144,7 +140,7 @@
 
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
-  RUNTIME_ASSERT(fun->IsConstructor());
+  CHECK(fun->IsConstructor());
   RETURN_FAILURE_ON_EXCEPTION(isolate,
                               Accessors::FunctionSetPrototype(fun, value));
   return args[0];  // return TOS
@@ -189,7 +185,8 @@
   }
   target_shared->set_scope_info(source_shared->scope_info());
   target_shared->set_length(source_shared->length());
-  target_shared->set_feedback_vector(source_shared->feedback_vector());
+  target_shared->set_num_literals(source_shared->num_literals());
+  target_shared->set_feedback_metadata(source_shared->feedback_metadata());
   target_shared->set_internal_formal_parameter_count(
       source_shared->internal_formal_parameter_count());
   target_shared->set_start_position_and_type(
@@ -206,21 +203,17 @@
 
   // Set the code of the target function.
   target->ReplaceCode(source_shared->code());
-  DCHECK(target->next_function_link()->IsUndefined());
+  DCHECK(target->next_function_link()->IsUndefined(isolate));
 
-  // Make sure we get a fresh copy of the literal vector to avoid cross
-  // context contamination.
   Handle<Context> context(source->context());
   target->set_context(*context);
 
-  int number_of_literals = source->NumberOfLiterals();
-  Handle<LiteralsArray> literals =
-      LiteralsArray::New(isolate, handle(target_shared->feedback_vector()),
-                         number_of_literals, TENURED);
-  target->set_literals(*literals);
+  // Make sure we get a fresh copy of the literal vector to avoid cross
+  // context contamination, and that the literal vector makes it's way into
+  // the target_shared optimized code map.
+  JSFunction::EnsureLiterals(target);
 
-  if (isolate->logger()->is_logging_code_events() ||
-      isolate->cpu_profiler()->is_profiling()) {
+  if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) {
     isolate->logger()->LogExistingFunction(
         source_shared, Handle<AbstractCode>(source_shared->abstract_code()));
   }
@@ -234,7 +227,7 @@
 // into the global object when doing call and apply.
 RUNTIME_FUNCTION(Runtime_SetNativeFlag) {
   SealHandleScope shs(isolate);
-  RUNTIME_ASSERT(args.length() == 1);
+  DCHECK_EQ(1, args.length());
 
   CONVERT_ARG_CHECKED(Object, object, 0);
 
@@ -255,7 +248,7 @@
 
 RUNTIME_FUNCTION(Runtime_SetForceInlineFlag) {
   SealHandleScope shs(isolate);
-  RUNTIME_ASSERT(args.length() == 1);
+  DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
 
   if (object->IsJSFunction()) {
@@ -276,11 +269,8 @@
   for (int i = 0; i < argc; ++i) {
     argv[i] = args.at<Object>(2 + i);
   }
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      Execution::Call(isolate, target, receiver, argc, argv.start()));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, Execution::Call(isolate, target, receiver, argc, argv.start()));
 }
 
 
@@ -289,10 +279,7 @@
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
-  if (receiver->IsNull() || receiver->IsUndefined()) {
-    return isolate->global_proxy();
-  }
-  return *Object::ToObject(isolate, receiver).ToHandleChecked();
+  return *Object::ConvertReceiver(isolate, receiver).ToHandleChecked();
 }
 
 
diff --git a/src/runtime/runtime-futex.cc b/src/runtime/runtime-futex.cc
index f4ef679..a966412 100644
--- a/src/runtime/runtime-futex.cc
+++ b/src/runtime/runtime-futex.cc
@@ -24,10 +24,10 @@
   CONVERT_SIZE_ARG_CHECKED(index, 1);
   CONVERT_INT32_ARG_CHECKED(value, 2);
   CONVERT_DOUBLE_ARG_CHECKED(timeout, 3);
-  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
-  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
-  RUNTIME_ASSERT(sta->type() == kExternalInt32Array);
-  RUNTIME_ASSERT(timeout == V8_INFINITY || !std::isnan(timeout));
+  CHECK(sta->GetBuffer()->is_shared());
+  CHECK_LT(index, NumberToSize(isolate, sta->length()));
+  CHECK_EQ(sta->type(), kExternalInt32Array);
+  CHECK(timeout == V8_INFINITY || !std::isnan(timeout));
 
   Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
   size_t addr = (index << 2) + NumberToSize(isolate, sta->byte_offset());
@@ -42,9 +42,9 @@
   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
   CONVERT_SIZE_ARG_CHECKED(index, 1);
   CONVERT_INT32_ARG_CHECKED(count, 2);
-  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
-  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
-  RUNTIME_ASSERT(sta->type() == kExternalInt32Array);
+  CHECK(sta->GetBuffer()->is_shared());
+  CHECK_LT(index, NumberToSize(isolate, sta->length()));
+  CHECK_EQ(sta->type(), kExternalInt32Array);
 
   Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
   size_t addr = (index << 2) + NumberToSize(isolate, sta->byte_offset());
@@ -61,10 +61,10 @@
   CONVERT_INT32_ARG_CHECKED(count, 2);
   CONVERT_INT32_ARG_CHECKED(value, 3);
   CONVERT_SIZE_ARG_CHECKED(index2, 4);
-  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
-  RUNTIME_ASSERT(index1 < NumberToSize(isolate, sta->length()));
-  RUNTIME_ASSERT(index2 < NumberToSize(isolate, sta->length()));
-  RUNTIME_ASSERT(sta->type() == kExternalInt32Array);
+  CHECK(sta->GetBuffer()->is_shared());
+  CHECK_LT(index1, NumberToSize(isolate, sta->length()));
+  CHECK_LT(index2, NumberToSize(isolate, sta->length()));
+  CHECK_EQ(sta->type(), kExternalInt32Array);
 
   Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
   size_t addr1 = (index1 << 2) + NumberToSize(isolate, sta->byte_offset());
@@ -80,9 +80,9 @@
   DCHECK(args.length() == 2);
   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
   CONVERT_SIZE_ARG_CHECKED(index, 1);
-  RUNTIME_ASSERT(sta->GetBuffer()->is_shared());
-  RUNTIME_ASSERT(index < NumberToSize(isolate, sta->length()));
-  RUNTIME_ASSERT(sta->type() == kExternalInt32Array);
+  CHECK(sta->GetBuffer()->is_shared());
+  CHECK_LT(index, NumberToSize(isolate, sta->length()));
+  CHECK_EQ(sta->type(), kExternalInt32Array);
 
   Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
   size_t addr = (index << 2) + NumberToSize(isolate, sta->byte_offset());
diff --git a/src/runtime/runtime-generator.cc b/src/runtime/runtime-generator.cc
index 181b5f9..3b65682 100644
--- a/src/runtime/runtime-generator.cc
+++ b/src/runtime/runtime-generator.cc
@@ -5,6 +5,7 @@
 #include "src/runtime/runtime-utils.h"
 
 #include "src/arguments.h"
+#include "src/debug/debug.h"
 #include "src/factory.h"
 #include "src/frames-inl.h"
 #include "src/objects-inl.h"
@@ -14,26 +15,31 @@
 
 RUNTIME_FUNCTION(Runtime_CreateJSGeneratorObject) {
   HandleScope scope(isolate);
-  DCHECK(args.length() == 0);
+  DCHECK(args.length() == 2);
+  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+  CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
+  CHECK(function->shared()->is_resumable());
 
-  JavaScriptFrameIterator it(isolate);
-  JavaScriptFrame* frame = it.frame();
-  Handle<JSFunction> function(frame->function());
-  RUNTIME_ASSERT(function->shared()->is_generator());
+  Handle<FixedArray> operand_stack;
+  if (function->shared()->HasBytecodeArray()) {
+    // New-style generators.
+    int size = function->shared()->bytecode_array()->register_count();
+    operand_stack = isolate->factory()->NewFixedArray(size);
+  } else {
+    // Old-style generators.
+    operand_stack = handle(isolate->heap()->empty_fixed_array());
+  }
 
-  Handle<JSGeneratorObject> generator;
-  DCHECK(!frame->IsConstructor());
-  generator = isolate->factory()->NewJSGeneratorObject(function);
+  Handle<JSGeneratorObject> generator =
+      isolate->factory()->NewJSGeneratorObject(function);
   generator->set_function(*function);
-  generator->set_context(Context::cast(frame->context()));
-  generator->set_receiver(frame->receiver());
-  generator->set_continuation(0);
-  generator->set_operand_stack(isolate->heap()->empty_fixed_array());
-
+  generator->set_context(isolate->context());
+  generator->set_receiver(*receiver);
+  generator->set_operand_stack(*operand_stack);
+  generator->set_continuation(JSGeneratorObject::kGeneratorExecuting);
   return *generator;
 }
 
-
 RUNTIME_FUNCTION(Runtime_SuspendJSGeneratorObject) {
   HandleScope handle_scope(isolate);
   DCHECK(args.length() == 1);
@@ -41,11 +47,13 @@
 
   JavaScriptFrameIterator stack_iterator(isolate);
   JavaScriptFrame* frame = stack_iterator.frame();
-  RUNTIME_ASSERT(frame->function()->shared()->is_generator());
+  CHECK(frame->function()->shared()->is_resumable());
   DCHECK_EQ(frame->function(), generator_object->function());
   DCHECK(frame->function()->shared()->is_compiled());
   DCHECK(!frame->function()->IsOptimized());
 
+  isolate->debug()->RecordAsyncFunction(generator_object);
+
   // The caller should have saved the context and continuation already.
   DCHECK_EQ(generator_object->context(), Context::cast(frame->context()));
   DCHECK_LT(0, generator_object->continuation());
@@ -72,63 +80,6 @@
   return isolate->heap()->undefined_value();
 }
 
-
-// Note that this function is the slow path for resuming generators.  It is only
-// called if the suspended activation had operands on the stack, stack handlers
-// needing rewinding, or if the resume should throw an exception.  The fast path
-// is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is
-// inlined into GeneratorNext, GeneratorReturn, and GeneratorThrow.
-// EmitGeneratorResume is called in any case, as it needs to reconstruct the
-// stack frame and make space for arguments and operands.
-RUNTIME_FUNCTION(Runtime_ResumeJSGeneratorObject) {
-  SealHandleScope shs(isolate);
-  DCHECK(args.length() == 3);
-  CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
-  CONVERT_ARG_CHECKED(Object, value, 1);
-  CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2);
-  JavaScriptFrameIterator stack_iterator(isolate);
-  JavaScriptFrame* frame = stack_iterator.frame();
-
-  DCHECK_EQ(frame->function(), generator_object->function());
-  DCHECK(frame->function()->shared()->is_compiled());
-  DCHECK(!frame->function()->IsOptimized());
-
-  STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0);
-  STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0);
-
-  Code* code = generator_object->function()->shared()->code();
-  int offset = generator_object->continuation();
-  DCHECK_GT(offset, 0);
-  frame->set_pc(code->instruction_start() + offset);
-  if (FLAG_enable_embedded_constant_pool) {
-    frame->set_constant_pool(code->constant_pool());
-  }
-  generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting);
-
-  FixedArray* operand_stack = generator_object->operand_stack();
-  int operands_count = operand_stack->length();
-  if (operands_count != 0) {
-    frame->RestoreOperandStack(operand_stack);
-    generator_object->set_operand_stack(isolate->heap()->empty_fixed_array());
-  }
-
-  JSGeneratorObject::ResumeMode resume_mode =
-      static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int);
-  switch (resume_mode) {
-    // Note: this looks like NEXT and RETURN are the same but RETURN receives
-    // special treatment in the generator code (to which we return here).
-    case JSGeneratorObject::NEXT:
-    case JSGeneratorObject::RETURN:
-      return value;
-    case JSGeneratorObject::THROW:
-      return isolate->Throw(value);
-  }
-
-  UNREACHABLE();
-  return isolate->ThrowIllegalOperation();
-}
-
-
 RUNTIME_FUNCTION(Runtime_GeneratorClose) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
@@ -139,8 +90,6 @@
   return isolate->heap()->undefined_value();
 }
 
-
-// Returns function of generator activation.
 RUNTIME_FUNCTION(Runtime_GeneratorGetFunction) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
@@ -149,8 +98,6 @@
   return generator->function();
 }
 
-
-// Returns receiver of generator activation.
 RUNTIME_FUNCTION(Runtime_GeneratorGetReceiver) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
@@ -159,18 +106,22 @@
   return generator->receiver();
 }
 
-
-// Returns input of generator activation.
-RUNTIME_FUNCTION(Runtime_GeneratorGetInput) {
+RUNTIME_FUNCTION(Runtime_GeneratorGetInputOrDebugPos) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
 
-  return generator->input();
+  return generator->input_or_debug_pos();
 }
 
+RUNTIME_FUNCTION(Runtime_GeneratorGetResumeMode) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 1);
+  CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
 
-// Returns generator continuation as a PC offset, or the magic -1 or 0 values.
+  return Smi::FromInt(generator->resume_mode());
+}
+
 RUNTIME_FUNCTION(Runtime_GeneratorGetContinuation) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
@@ -179,38 +130,13 @@
   return Smi::FromInt(generator->continuation());
 }
 
-
 RUNTIME_FUNCTION(Runtime_GeneratorGetSourcePosition) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
 
-  if (generator->is_suspended()) {
-    Handle<Code> code(generator->function()->code(), isolate);
-    int offset = generator->continuation();
-    RUNTIME_ASSERT(0 <= offset && offset < code->instruction_size());
-    return Smi::FromInt(code->SourcePosition(offset));
-  }
-
-  return isolate->heap()->undefined_value();
-}
-
-// Optimization for builtins calling any of the following three functions is
-// disabled in js/generator.js and compiler.cc, hence they are unreachable.
-
-RUNTIME_FUNCTION(Runtime_GeneratorNext) {
-  UNREACHABLE();
-  return nullptr;
-}
-
-RUNTIME_FUNCTION(Runtime_GeneratorReturn) {
-  UNREACHABLE();
-  return nullptr;
-}
-
-RUNTIME_FUNCTION(Runtime_GeneratorThrow) {
-  UNREACHABLE();
-  return nullptr;
+  if (!generator->is_suspended()) return isolate->heap()->undefined_value();
+  return Smi::FromInt(generator->source_position());
 }
 
 }  // namespace internal
diff --git a/src/runtime/runtime-i18n.cc b/src/runtime/runtime-i18n.cc
index 27f970b..d4c6034 100644
--- a/src/runtime/runtime-i18n.cc
+++ b/src/runtime/runtime-i18n.cc
@@ -24,21 +24,42 @@
 #include "unicode/dtfmtsym.h"
 #include "unicode/dtptngen.h"
 #include "unicode/locid.h"
+#include "unicode/normalizer2.h"
 #include "unicode/numfmt.h"
 #include "unicode/numsys.h"
 #include "unicode/rbbi.h"
 #include "unicode/smpdtfmt.h"
 #include "unicode/timezone.h"
+#include "unicode/translit.h"
 #include "unicode/uchar.h"
 #include "unicode/ucol.h"
 #include "unicode/ucurr.h"
 #include "unicode/uloc.h"
+#include "unicode/unistr.h"
 #include "unicode/unum.h"
 #include "unicode/uversion.h"
 
 
 namespace v8 {
 namespace internal {
+namespace {
+
+const UChar* GetUCharBufferFromFlat(const String::FlatContent& flat,
+                                    base::SmartArrayPointer<uc16>* dest,
+                                    int32_t length) {
+  DCHECK(flat.IsFlat());
+  if (flat.IsOneByte()) {
+    if (dest->is_empty()) {
+      dest->Reset(NewArray<uc16>(length));
+      CopyChars(dest->get(), flat.ToOneByteVector().start(), length);
+    }
+    return reinterpret_cast<const UChar*>(dest->get());
+  } else {
+    return reinterpret_cast<const UChar*>(flat.ToUC16Vector().start());
+  }
+}
+
+}  // namespace
 
 RUNTIME_FUNCTION(Runtime_CanonicalizeLanguageTag) {
   HandleScope scope(isolate);
@@ -238,7 +259,7 @@
 
   Handle<Symbol> marker = isolate->factory()->intl_initialized_marker_symbol();
   Handle<Object> tag = JSReceiver::GetDataProperty(obj, marker);
-  return isolate->heap()->ToBoolean(!tag->IsUndefined());
+  return isolate->heap()->ToBoolean(!tag->IsUndefined(isolate));
 }
 
 
@@ -296,7 +317,7 @@
   Handle<Symbol> marker = isolate->factory()->intl_impl_object_symbol();
 
   Handle<Object> impl = JSReceiver::GetDataProperty(obj, marker);
-  if (impl->IsTheHole()) {
+  if (impl->IsTheHole(isolate)) {
     THROW_NEW_ERROR_RETURN_FAILURE(
         isolate, NewTypeError(MessageTemplate::kNotIntlObject, obj));
   }
@@ -336,9 +357,9 @@
 
   // Make object handle weak so we can delete the data format once GC kicks in.
   Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
-  GlobalHandles::MakeWeak(wrapper.location(),
-                          reinterpret_cast<void*>(wrapper.location()),
-                          DateFormat::DeleteDateFormat);
+  GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(),
+                          DateFormat::DeleteDateFormat,
+                          WeakCallbackType::kInternalFields);
   return *local_object;
 }
 
@@ -361,13 +382,10 @@
   icu::UnicodeString result;
   date_format->format(value->Number(), result);
 
-  Handle<String> result_str;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result_str,
-      isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
-          reinterpret_cast<const uint16_t*>(result.getBuffer()),
-          result.length())));
-  return *result_str;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
+                   reinterpret_cast<const uint16_t*>(result.getBuffer()),
+                   result.length())));
 }
 
 
@@ -389,12 +407,9 @@
   UDate date = date_format->parse(u_date, status);
   if (U_FAILURE(status)) return isolate->heap()->undefined_value();
 
-  Handle<JSDate> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      JSDate::New(isolate->date_function(), isolate->date_function(),
-                  static_cast<double>(date)));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, JSDate::New(isolate->date_function(), isolate->date_function(),
+                           static_cast<double>(date)));
 }
 
 
@@ -430,9 +445,9 @@
   JSObject::AddProperty(local_object, key, value, NONE);
 
   Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
-  GlobalHandles::MakeWeak(wrapper.location(),
-                          reinterpret_cast<void*>(wrapper.location()),
-                          NumberFormat::DeleteNumberFormat);
+  GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(),
+                          NumberFormat::DeleteNumberFormat,
+                          WeakCallbackType::kInternalFields);
   return *local_object;
 }
 
@@ -455,13 +470,10 @@
   icu::UnicodeString result;
   number_format->format(value->Number(), result);
 
-  Handle<String> result_str;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result_str,
-      isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
-          reinterpret_cast<const uint16_t*>(result.getBuffer()),
-          result.length())));
-  return *result_str;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
+                   reinterpret_cast<const uint16_t*>(result.getBuffer()),
+                   result.length())));
 }
 
 
@@ -536,9 +548,9 @@
   JSObject::AddProperty(local_object, key, value, NONE);
 
   Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
-  GlobalHandles::MakeWeak(wrapper.location(),
-                          reinterpret_cast<void*>(wrapper.location()),
-                          Collator::DeleteCollator);
+  GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(),
+                          Collator::DeleteCollator,
+                          WeakCallbackType::kInternalFields);
   return *local_object;
 }
 
@@ -555,14 +567,20 @@
   icu::Collator* collator = Collator::UnpackCollator(isolate, collator_holder);
   if (!collator) return isolate->ThrowIllegalOperation();
 
-  v8::String::Value string_value1(v8::Utils::ToLocal(string1));
-  v8::String::Value string_value2(v8::Utils::ToLocal(string2));
-  const UChar* u_string1 = reinterpret_cast<const UChar*>(*string_value1);
-  const UChar* u_string2 = reinterpret_cast<const UChar*>(*string_value2);
+  string1 = String::Flatten(string1);
+  string2 = String::Flatten(string2);
+  DisallowHeapAllocation no_gc;
+  int32_t length1 = string1->length();
+  int32_t length2 = string2->length();
+  String::FlatContent flat1 = string1->GetFlatContent();
+  String::FlatContent flat2 = string2->GetFlatContent();
+  base::SmartArrayPointer<uc16> sap1;
+  base::SmartArrayPointer<uc16> sap2;
+  const UChar* string_val1 = GetUCharBufferFromFlat(flat1, &sap1, length1);
+  const UChar* string_val2 = GetUCharBufferFromFlat(flat2, &sap2, length2);
   UErrorCode status = U_ZERO_ERROR;
   UCollationResult result =
-      collator->compare(u_string1, string_value1.length(), u_string2,
-                        string_value2.length(), status);
+      collator->compare(string_val1, length1, string_val2, length2, status);
   if (U_FAILURE(status)) return isolate->ThrowIllegalOperation();
 
   return *isolate->factory()->NewNumberFromInt(result);
@@ -571,36 +589,59 @@
 
 RUNTIME_FUNCTION(Runtime_StringNormalize) {
   HandleScope scope(isolate);
-  static const UNormalizationMode normalizationForms[] = {
-      UNORM_NFC, UNORM_NFD, UNORM_NFKC, UNORM_NFKD};
+  static const struct {
+    const char* name;
+    UNormalization2Mode mode;
+  } normalizationForms[] = {
+      {"nfc", UNORM2_COMPOSE},
+      {"nfc", UNORM2_DECOMPOSE},
+      {"nfkc", UNORM2_COMPOSE},
+      {"nfkc", UNORM2_DECOMPOSE},
+  };
 
   DCHECK(args.length() == 2);
 
-  CONVERT_ARG_HANDLE_CHECKED(String, stringValue, 0);
+  CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
   CONVERT_NUMBER_CHECKED(int, form_id, Int32, args[1]);
   RUNTIME_ASSERT(form_id >= 0 &&
                  static_cast<size_t>(form_id) < arraysize(normalizationForms));
 
-  v8::String::Value string_value(v8::Utils::ToLocal(stringValue));
-  const UChar* u_value = reinterpret_cast<const UChar*>(*string_value);
-
-  // TODO(mnita): check Normalizer2 (not available in ICU 46)
-  UErrorCode status = U_ZERO_ERROR;
-  icu::UnicodeString input(false, u_value, string_value.length());
+  int length = s->length();
+  s = String::Flatten(s);
   icu::UnicodeString result;
-  icu::Normalizer::normalize(input, normalizationForms[form_id], 0, result,
-                             status);
+  base::SmartArrayPointer<uc16> sap;
+  UErrorCode status = U_ZERO_ERROR;
+  {
+    DisallowHeapAllocation no_gc;
+    String::FlatContent flat = s->GetFlatContent();
+    const UChar* src = GetUCharBufferFromFlat(flat, &sap, length);
+    icu::UnicodeString input(false, src, length);
+    // Getting a singleton. Should not free it.
+    const icu::Normalizer2* normalizer =
+        icu::Normalizer2::getInstance(nullptr, normalizationForms[form_id].name,
+                                      normalizationForms[form_id].mode, status);
+    DCHECK(U_SUCCESS(status));
+    RUNTIME_ASSERT(normalizer != nullptr);
+    int32_t normalized_prefix_length =
+        normalizer->spanQuickCheckYes(input, status);
+    // Quick return if the input is already normalized.
+    if (length == normalized_prefix_length) return *s;
+    icu::UnicodeString unnormalized =
+        input.tempSubString(normalized_prefix_length);
+    // Read-only alias of the normalized prefix.
+    result.setTo(false, input.getBuffer(), normalized_prefix_length);
+    // copy-on-write; normalize the suffix and append to |result|.
+    normalizer->normalizeSecondAndAppend(result, unnormalized, status);
+  }
+
   if (U_FAILURE(status)) {
     return isolate->heap()->undefined_value();
   }
 
-  Handle<String> result_str;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result_str,
-      isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
-          reinterpret_cast<const uint16_t*>(result.getBuffer()),
-          result.length())));
-  return *result_str;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
+                   reinterpret_cast<const uint16_t*>(result.getBuffer()),
+                   result.length())));
 }
 
 
@@ -640,9 +681,9 @@
   // Make object handle weak so we can delete the break iterator once GC kicks
   // in.
   Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
-  GlobalHandles::MakeWeak(wrapper.location(),
-                          reinterpret_cast<void*>(wrapper.location()),
-                          BreakIterator::DeleteBreakIterator);
+  GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(),
+                          BreakIterator::DeleteBreakIterator,
+                          WeakCallbackType::kInternalFields);
   return *local_object;
 }
 
@@ -663,9 +704,13 @@
       break_iterator_holder->GetInternalField(1));
   delete u_text;
 
-  v8::String::Value text_value(v8::Utils::ToLocal(text));
-  u_text = new icu::UnicodeString(reinterpret_cast<const UChar*>(*text_value),
-                                  text_value.length());
+  int length = text->length();
+  text = String::Flatten(text);
+  DisallowHeapAllocation no_gc;
+  String::FlatContent flat = text->GetFlatContent();
+  base::SmartArrayPointer<uc16> sap;
+  const UChar* text_value = GetUCharBufferFromFlat(flat, &sap, length);
+  u_text = new icu::UnicodeString(text_value, length);
   break_iterator_holder->SetInternalField(1, reinterpret_cast<Smi*>(u_text));
 
   break_iterator->setText(*u_text);
@@ -749,6 +794,360 @@
     return *isolate->factory()->NewStringFromStaticChars("unknown");
   }
 }
+
+namespace {
+void ConvertCaseWithTransliterator(icu::UnicodeString* input,
+                                   const char* transliterator_id) {
+  UErrorCode status = U_ZERO_ERROR;
+  base::SmartPointer<icu::Transliterator> translit(
+      icu::Transliterator::createInstance(
+          icu::UnicodeString(transliterator_id, -1, US_INV), UTRANS_FORWARD,
+          status));
+  if (U_FAILURE(status)) return;
+  translit->transliterate(*input);
+}
+
+MUST_USE_RESULT Object* LocaleConvertCase(Handle<String> s, Isolate* isolate,
+                                          bool is_to_upper, const char* lang) {
+  int32_t src_length = s->length();
+
+  // Greek uppercasing has to be done via transliteration.
+  // TODO(jshin): Drop this special-casing once ICU's regular case conversion
+  // API supports Greek uppercasing. See
+  // http://bugs.icu-project.org/trac/ticket/10582 .
+  // In the meantime, if there's no Greek character in |s|, call this
+  // function again with the root locale (lang="").
+  // ICU's C API for transliteration is nasty and we just use C++ API.
+  if (V8_UNLIKELY(is_to_upper && lang[0] == 'e' && lang[1] == 'l')) {
+    icu::UnicodeString converted;
+    base::SmartArrayPointer<uc16> sap;
+    {
+      DisallowHeapAllocation no_gc;
+      String::FlatContent flat = s->GetFlatContent();
+      const UChar* src = GetUCharBufferFromFlat(flat, &sap, src_length);
+      // Starts with the source string (read-only alias with copy-on-write
+      // semantics) and will be modified to contain the converted result.
+      // Using read-only alias at first saves one copy operation if
+      // transliteration does not change the input, which is rather rare.
+      // Moreover, transliteration takes rather long so that saving one copy
+      // helps only a little bit.
+      converted.setTo(false, src, src_length);
+      ConvertCaseWithTransliterator(&converted, "el-Upper");
+      // If no change is made, just return |s|.
+      if (converted.getBuffer() == src) return *s;
+    }
+    RETURN_RESULT_OR_FAILURE(
+        isolate,
+        isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
+            reinterpret_cast<const uint16_t*>(converted.getBuffer()),
+            converted.length())));
+  }
+
+  auto case_converter = is_to_upper ? u_strToUpper : u_strToLower;
+
+  int32_t dest_length = src_length;
+  UErrorCode status;
+  Handle<SeqTwoByteString> result;
+  base::SmartArrayPointer<uc16> sap;
+
+  // This is not a real loop. It'll be executed only once (no overflow) or
+  // twice (overflow).
+  for (int i = 0; i < 2; ++i) {
+    result =
+        isolate->factory()->NewRawTwoByteString(dest_length).ToHandleChecked();
+    DisallowHeapAllocation no_gc;
+    String::FlatContent flat = s->GetFlatContent();
+    const UChar* src = GetUCharBufferFromFlat(flat, &sap, src_length);
+    status = U_ZERO_ERROR;
+    dest_length = case_converter(reinterpret_cast<UChar*>(result->GetChars()),
+                                 dest_length, src, src_length, lang, &status);
+    if (status != U_BUFFER_OVERFLOW_ERROR) break;
+  }
+
+  // In most cases, the output will fill the destination buffer completely
+  // leading to an unterminated string (U_STRING_NOT_TERMINATED_WARNING).
+  // Only in rare cases, it'll be shorter than the destination buffer and
+  // |result| has to be truncated.
+  DCHECK(U_SUCCESS(status));
+  if (V8_LIKELY(status == U_STRING_NOT_TERMINATED_WARNING)) {
+    DCHECK(dest_length == result->length());
+    return *result;
+  }
+  if (U_SUCCESS(status)) {
+    DCHECK(dest_length < result->length());
+    return *Handle<SeqTwoByteString>::cast(
+        SeqString::Truncate(result, dest_length));
+  }
+  return *s;
+}
+
+inline bool IsASCIIUpper(uint16_t ch) { return ch >= 'A' && ch <= 'Z'; }
+
+const uint8_t kToLower[256] = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+    0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+    0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
+    0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
+    0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73,
+    0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
+    0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+    0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83,
+    0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B,
+    0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
+    0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
+    0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
+    0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB,
+    0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xD7,
+    0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3,
+    0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
+    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB,
+    0xFC, 0xFD, 0xFE, 0xFF,
+};
+
+inline uint16_t ToLatin1Lower(uint16_t ch) {
+  return static_cast<uint16_t>(kToLower[ch]);
+}
+
+inline uint16_t ToASCIIUpper(uint16_t ch) {
+  return ch & ~((ch >= 'a' && ch <= 'z') << 5);
+}
+
+// Does not work for U+00DF (sharp-s), U+00B5 (micron), U+00FF.
+inline uint16_t ToLatin1Upper(uint16_t ch) {
+  DCHECK(ch != 0xDF && ch != 0xB5 && ch != 0xFF);
+  return ch &
+         ~(((ch >= 'a' && ch <= 'z') || (((ch & 0xE0) == 0xE0) && ch != 0xE7))
+           << 5);
+}
+
+template <typename Char>
+bool ToUpperFastASCII(const Vector<const Char>& src,
+                      Handle<SeqOneByteString> result) {
+  // Do a faster loop for the case where all the characters are ASCII.
+  uint16_t ored = 0;
+  int32_t index = 0;
+  for (auto it = src.begin(); it != src.end(); ++it) {
+    uint16_t ch = static_cast<uint16_t>(*it);
+    ored |= ch;
+    result->SeqOneByteStringSet(index++, ToASCIIUpper(ch));
+  }
+  return !(ored & ~0x7F);
+}
+
+const uint16_t sharp_s = 0xDF;
+
+template <typename Char>
+bool ToUpperOneByte(const Vector<const Char>& src,
+                    Handle<SeqOneByteString> result, int* sharp_s_count) {
+  // Still pretty-fast path for the input with non-ASCII Latin-1 characters.
+
+  // There are two special cases.
+  //  1. U+00B5 and U+00FF are mapped to a character beyond U+00FF.
+  //  2. Lower case sharp-S converts to "SS" (two characters)
+  *sharp_s_count = 0;
+  int32_t index = 0;
+  for (auto it = src.begin(); it != src.end(); ++it) {
+    uint16_t ch = static_cast<uint16_t>(*it);
+    if (V8_UNLIKELY(ch == sharp_s)) {
+      ++(*sharp_s_count);
+      continue;
+    }
+    if (V8_UNLIKELY(ch == 0xB5 || ch == 0xFF)) {
+      // Since this upper-cased character does not fit in an 8-bit string, we
+      // need to take the 16-bit path.
+      return false;
+    }
+    result->SeqOneByteStringSet(index++, ToLatin1Upper(ch));
+  }
+
+  return true;
+}
+
+template <typename Char>
+void ToUpperWithSharpS(const Vector<const Char>& src,
+                       Handle<SeqOneByteString> result) {
+  int32_t dest_index = 0;
+  for (auto it = src.begin(); it != src.end(); ++it) {
+    uint16_t ch = static_cast<uint16_t>(*it);
+    if (ch == sharp_s) {
+      result->SeqOneByteStringSet(dest_index++, 'S');
+      result->SeqOneByteStringSet(dest_index++, 'S');
+    } else {
+      result->SeqOneByteStringSet(dest_index++, ToLatin1Upper(ch));
+    }
+  }
+}
+
+}  // namespace
+
+RUNTIME_FUNCTION(Runtime_StringToLowerCaseI18N) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(args.length(), 1);
+  CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
+
+  int length = s->length();
+  s = String::Flatten(s);
+  // First scan the string for uppercase and non-ASCII characters:
+  if (s->HasOnlyOneByteChars()) {
+    unsigned first_index_to_lower = length;
+    for (int index = 0; index < length; ++index) {
+      // Blink specializes this path for one-byte strings, so it
+      // does not need to do a generic get, but can do the equivalent
+      // of SeqOneByteStringGet.
+      uint16_t ch = s->Get(index);
+      if (V8_UNLIKELY(IsASCIIUpper(ch) || ch & ~0x7F)) {
+        first_index_to_lower = index;
+        break;
+      }
+    }
+
+    // Nothing to do if the string is all ASCII with no uppercase.
+    if (first_index_to_lower == length) return *s;
+
+    // We depend here on the invariant that the length of a Latin1
+    // string is invariant under ToLowerCase, and the result always
+    // fits in the Latin1 range in the *root locale*. It does not hold
+    // for ToUpperCase even in the root locale.
+    Handle<SeqOneByteString> result;
+    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+        isolate, result, isolate->factory()->NewRawOneByteString(length));
+
+    DisallowHeapAllocation no_gc;
+    String::FlatContent flat = s->GetFlatContent();
+    if (flat.IsOneByte()) {
+      const uint8_t* src = flat.ToOneByteVector().start();
+      CopyChars(result->GetChars(), src, first_index_to_lower);
+      for (int index = first_index_to_lower; index < length; ++index) {
+        uint16_t ch = static_cast<uint16_t>(src[index]);
+        result->SeqOneByteStringSet(index, ToLatin1Lower(ch));
+      }
+    } else {
+      const uint16_t* src = flat.ToUC16Vector().start();
+      CopyChars(result->GetChars(), src, first_index_to_lower);
+      for (int index = first_index_to_lower; index < length; ++index) {
+        uint16_t ch = src[index];
+        result->SeqOneByteStringSet(index, ToLatin1Lower(ch));
+      }
+    }
+
+    return *result;
+  }
+
+  // Blink had an additional case here for ASCII 2-byte strings, but
+  // that is subsumed by the above code (assuming there isn't a false
+  // negative for HasOnlyOneByteChars).
+
+  // Do a slower implementation for cases that include non-ASCII characters.
+  return LocaleConvertCase(s, isolate, false, "");
+}
+
+RUNTIME_FUNCTION(Runtime_StringToUpperCaseI18N) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(args.length(), 1);
+  CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
+
+  // This function could be optimized for no-op cases the way lowercase
+  // counterpart is, but in empirical testing, few actual calls to upper()
+  // are no-ops. So, it wouldn't be worth the extra time for pre-scanning.
+
+  int32_t length = s->length();
+  s = String::Flatten(s);
+
+  if (s->HasOnlyOneByteChars()) {
+    Handle<SeqOneByteString> result;
+    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+        isolate, result, isolate->factory()->NewRawOneByteString(length));
+
+    int sharp_s_count;
+    bool is_result_single_byte;
+    {
+      DisallowHeapAllocation no_gc;
+      String::FlatContent flat = s->GetFlatContent();
+      // If it was ok to slow down ASCII-only input slightly, ToUpperFastASCII
+      // could be removed  because ToUpperOneByte is pretty fast now (it
+      // does not call ICU API any more.).
+      if (flat.IsOneByte()) {
+        Vector<const uint8_t> src = flat.ToOneByteVector();
+        if (ToUpperFastASCII(src, result)) return *result;
+        is_result_single_byte = ToUpperOneByte(src, result, &sharp_s_count);
+      } else {
+        DCHECK(flat.IsTwoByte());
+        Vector<const uint16_t> src = flat.ToUC16Vector();
+        if (ToUpperFastASCII(src, result)) return *result;
+        is_result_single_byte = ToUpperOneByte(src, result, &sharp_s_count);
+      }
+    }
+
+    // Go to the full Unicode path if there are characters whose uppercase
+    // is beyond the Latin-1 range (cannot be represented in OneByteString).
+    if (V8_UNLIKELY(!is_result_single_byte)) {
+      return LocaleConvertCase(s, isolate, true, "");
+    }
+
+    if (sharp_s_count == 0) return *result;
+
+    // We have sharp_s_count sharp-s characters, but the result is still
+    // in the Latin-1 range.
+    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+        isolate, result,
+        isolate->factory()->NewRawOneByteString(length + sharp_s_count));
+    DisallowHeapAllocation no_gc;
+    String::FlatContent flat = s->GetFlatContent();
+    if (flat.IsOneByte()) {
+      ToUpperWithSharpS(flat.ToOneByteVector(), result);
+    } else {
+      ToUpperWithSharpS(flat.ToUC16Vector(), result);
+    }
+
+    return *result;
+  }
+
+  return LocaleConvertCase(s, isolate, true, "");
+}
+
+RUNTIME_FUNCTION(Runtime_StringLocaleConvertCase) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(args.length(), 3);
+  CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
+  CONVERT_BOOLEAN_ARG_CHECKED(is_upper, 1);
+  CONVERT_ARG_HANDLE_CHECKED(SeqOneByteString, lang, 2);
+
+  // All the languages requiring special handling ("az", "el", "lt", "tr")
+  // have a 2-letter language code.
+  DCHECK(lang->length() == 2);
+  uint8_t lang_str[3];
+  memcpy(lang_str, lang->GetChars(), 2);
+  lang_str[2] = 0;
+  s = String::Flatten(s);
+  // TODO(jshin): Consider adding a fast path for ASCII or Latin-1. The fastpath
+  // in the root locale needs to be adjusted for az, lt and tr because even case
+  // mapping of ASCII range characters are different in those locales.
+  // Greek (el) does not require any adjustment, though.
+  return LocaleConvertCase(s, isolate, is_upper,
+                           reinterpret_cast<const char*>(lang_str));
+}
+
+RUNTIME_FUNCTION(Runtime_DateCacheVersion) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(0, args.length());
+  if (isolate->serializer_enabled()) return isolate->heap()->undefined_value();
+  if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) {
+    Handle<FixedArray> date_cache_version =
+        isolate->factory()->NewFixedArray(1, TENURED);
+    date_cache_version->set(0, Smi::FromInt(0));
+    isolate->eternal_handles()->CreateSingleton(
+        isolate, *date_cache_version, EternalHandles::DATE_CACHE_VERSION);
+  }
+  Handle<FixedArray> date_cache_version =
+      Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton(
+          EternalHandles::DATE_CACHE_VERSION));
+  return date_cache_version->get(0);
+}
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/runtime/runtime-internal.cc b/src/runtime/runtime-internal.cc
index d871fc7..e7491ba 100644
--- a/src/runtime/runtime-internal.cc
+++ b/src/runtime/runtime-internal.cc
@@ -13,6 +13,7 @@
 #include "src/isolate-inl.h"
 #include "src/messages.h"
 #include "src/parsing/parser.h"
+#include "src/wasm/wasm-module.h"
 
 namespace v8 {
 namespace internal {
@@ -20,7 +21,7 @@
 RUNTIME_FUNCTION(Runtime_CheckIsBootstrapping) {
   SealHandleScope shs(isolate);
   DCHECK(args.length() == 0);
-  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
+  CHECK(isolate->bootstrapper()->IsActive());
   return isolate->heap()->undefined_value();
 }
 
@@ -29,7 +30,7 @@
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, container, 0);
-  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
+  CHECK(isolate->bootstrapper()->IsActive());
   JSObject::NormalizeProperties(container, KEEP_INOBJECT_PROPERTIES, 10,
                                 "ExportFromRuntime");
   Bootstrapper::ExportFromRuntime(isolate, container);
@@ -42,7 +43,7 @@
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, container, 0);
-  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
+  CHECK(isolate->bootstrapper()->IsActive());
   JSObject::NormalizeProperties(container, KEEP_INOBJECT_PROPERTIES, 10,
                                 "ExportExperimentalFromRuntime");
   Bootstrapper::ExportExperimentalFromRuntime(isolate, container);
@@ -55,21 +56,21 @@
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
-  RUNTIME_ASSERT(array->HasFastElements());
-  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
+  CHECK(array->HasFastElements());
+  CHECK(isolate->bootstrapper()->IsActive());
   Handle<Context> native_context = isolate->native_context();
   Handle<FixedArray> fixed_array(FixedArray::cast(array->elements()));
   int length = Smi::cast(array->length())->value();
   for (int i = 0; i < length; i += 2) {
-    RUNTIME_ASSERT(fixed_array->get(i)->IsString());
+    CHECK(fixed_array->get(i)->IsString());
     Handle<String> name(String::cast(fixed_array->get(i)));
-    RUNTIME_ASSERT(fixed_array->get(i + 1)->IsJSObject());
+    CHECK(fixed_array->get(i + 1)->IsJSObject());
     Handle<JSObject> object(JSObject::cast(fixed_array->get(i + 1)));
     int index = Context::ImportedFieldIndexForName(name);
     if (index == Context::kNotFound) {
       index = Context::IntrinsicIndexForName(name);
     }
-    RUNTIME_ASSERT(index != Context::kNotFound);
+    CHECK(index != Context::kNotFound);
     native_context->set(index, *object);
   }
   return isolate->heap()->undefined_value();
@@ -96,6 +97,60 @@
   return isolate->StackOverflow();
 }
 
+RUNTIME_FUNCTION(Runtime_ThrowWasmError) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(2, args.length());
+  CONVERT_SMI_ARG_CHECKED(message_id, 0);
+  CONVERT_SMI_ARG_CHECKED(byte_offset, 1);
+  Handle<Object> error_obj = isolate->factory()->NewError(
+      static_cast<MessageTemplate::Template>(message_id));
+
+  // For wasm traps, the byte offset (a.k.a source position) can not be
+  // determined from relocation info, since the explicit checks for traps
+  // converge in one singe block which calls this runtime function.
+  // We hence pass the byte offset explicitely, and patch it into the top-most
+  // frame (a wasm frame) on the collected stack trace.
+  // TODO(wasm): This implementation is temporary, see bug #5007:
+  // https://bugs.chromium.org/p/v8/issues/detail?id=5007
+  Handle<JSObject> error = Handle<JSObject>::cast(error_obj);
+  Handle<Object> stack_trace_obj = JSReceiver::GetDataProperty(
+      error, isolate->factory()->stack_trace_symbol());
+  // Patch the stack trace (array of <receiver, function, code, position>).
+  if (stack_trace_obj->IsJSArray()) {
+    Handle<FixedArray> stack_elements(
+        FixedArray::cast(JSArray::cast(*stack_trace_obj)->elements()));
+    DCHECK_EQ(1, stack_elements->length() % 4);
+    DCHECK(Code::cast(stack_elements->get(3))->kind() == Code::WASM_FUNCTION);
+    DCHECK(stack_elements->get(4)->IsSmi() &&
+           Smi::cast(stack_elements->get(4))->value() >= 0);
+    stack_elements->set(4, Smi::FromInt(-1 - byte_offset));
+  }
+  Handle<Object> detailed_stack_trace_obj = JSReceiver::GetDataProperty(
+      error, isolate->factory()->detailed_stack_trace_symbol());
+  // Patch the detailed stack trace (array of JSObjects with various
+  // properties).
+  if (detailed_stack_trace_obj->IsJSArray()) {
+    Handle<FixedArray> stack_elements(
+        FixedArray::cast(JSArray::cast(*detailed_stack_trace_obj)->elements()));
+    DCHECK_GE(stack_elements->length(), 1);
+    Handle<JSObject> top_frame(JSObject::cast(stack_elements->get(0)));
+    Handle<String> wasm_offset_key =
+        isolate->factory()->InternalizeOneByteString(
+            STATIC_CHAR_VECTOR("column"));
+    LookupIterator it(top_frame, wasm_offset_key, top_frame,
+                      LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
+    if (it.IsFound()) {
+      DCHECK(JSReceiver::GetDataProperty(&it)->IsSmi());
+      // Make column number 1-based here.
+      Maybe<bool> data_set = JSReceiver::SetDataProperty(
+          &it, handle(Smi::FromInt(byte_offset + 1), isolate));
+      DCHECK(data_set.IsJust() && data_set.FromJust() == true);
+      USE(data_set);
+    }
+  }
+
+  return isolate->Throw(*error_obj);
+}
 
 RUNTIME_FUNCTION(Runtime_UnwindAndFindExceptionHandler) {
   SealHandleScope shs(isolate);
@@ -160,6 +215,15 @@
       isolate, NewTypeError(MessageTemplate::kIllegalInvocation));
 }
 
+RUNTIME_FUNCTION(Runtime_ThrowIncompatibleMethodReceiver) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(2, args.length());
+  CONVERT_ARG_HANDLE_CHECKED(Object, arg0, 0);
+  CONVERT_ARG_HANDLE_CHECKED(Object, arg1, 1);
+  THROW_NEW_ERROR_RETURN_FAILURE(
+      isolate,
+      NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, arg0, arg1));
+}
 
 RUNTIME_FUNCTION(Runtime_ThrowIteratorResultNotAnObject) {
   HandleScope scope(isolate);
@@ -170,6 +234,12 @@
       NewTypeError(MessageTemplate::kIteratorResultNotAnObject, value));
 }
 
+RUNTIME_FUNCTION(Runtime_ThrowGeneratorRunning) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(0, args.length());
+  THROW_NEW_ERROR_RETURN_FAILURE(
+      isolate, NewTypeError(MessageTemplate::kGeneratorRunning));
+}
 
 RUNTIME_FUNCTION(Runtime_ThrowApplyNonFunction) {
   HandleScope scope(isolate);
@@ -190,7 +260,7 @@
   if (debug_event) isolate->debug()->OnPromiseReject(promise, value);
   Handle<Symbol> key = isolate->factory()->promise_has_handler_symbol();
   // Do not report if we actually have a handler.
-  if (JSReceiver::GetDataProperty(promise, key)->IsUndefined()) {
+  if (JSReceiver::GetDataProperty(promise, key)->IsUndefined(isolate)) {
     isolate->ReportPromiseReject(promise, value,
                                  v8::kPromiseRejectWithNoHandler);
   }
@@ -204,7 +274,7 @@
   CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
   Handle<Symbol> key = isolate->factory()->promise_has_handler_symbol();
   // At this point, no revocation has been issued before
-  RUNTIME_ASSERT(JSReceiver::GetDataProperty(promise, key)->IsUndefined());
+  CHECK(JSReceiver::GetDataProperty(promise, key)->IsUndefined(isolate));
   isolate->ReportPromiseReject(promise, Handle<Object>(),
                                v8::kPromiseHandlerAddedAfterReject);
   return isolate->heap()->undefined_value();
@@ -236,9 +306,9 @@
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_SMI_ARG_CHECKED(size, 0);
-  RUNTIME_ASSERT(IsAligned(size, kPointerSize));
-  RUNTIME_ASSERT(size > 0);
-  RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize);
+  CHECK(IsAligned(size, kPointerSize));
+  CHECK(size > 0);
+  CHECK(size <= Page::kMaxRegularHeapObjectSize);
   return *isolate->factory()->NewFillerObject(size, false, NEW_SPACE);
 }
 
@@ -248,14 +318,33 @@
   DCHECK(args.length() == 2);
   CONVERT_SMI_ARG_CHECKED(size, 0);
   CONVERT_SMI_ARG_CHECKED(flags, 1);
-  RUNTIME_ASSERT(IsAligned(size, kPointerSize));
-  RUNTIME_ASSERT(size > 0);
-  RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize);
+  CHECK(IsAligned(size, kPointerSize));
+  CHECK(size > 0);
+  CHECK(size <= Page::kMaxRegularHeapObjectSize);
   bool double_align = AllocateDoubleAlignFlag::decode(flags);
   AllocationSpace space = AllocateTargetSpace::decode(flags);
   return *isolate->factory()->NewFillerObject(size, double_align, space);
 }
 
+RUNTIME_FUNCTION(Runtime_AllocateSeqOneByteString) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(1, args.length());
+  CONVERT_SMI_ARG_CHECKED(length, 0);
+  Handle<SeqOneByteString> result;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, result, isolate->factory()->NewRawOneByteString(length));
+  return *result;
+}
+
+RUNTIME_FUNCTION(Runtime_AllocateSeqTwoByteString) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(1, args.length());
+  CONVERT_SMI_ARG_CHECKED(length, 0);
+  Handle<SeqTwoByteString> result;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, result, isolate->factory()->NewRawTwoByteString(length));
+  return *result;
+}
 
 // Collect the raw data for a stack trace.  Returns an array of 4
 // element segments each containing a receiver, function, code and
@@ -301,12 +390,9 @@
   CONVERT_ARG_HANDLE_CHECKED(String, arg0, 1);
   CONVERT_ARG_HANDLE_CHECKED(String, arg1, 2);
   CONVERT_ARG_HANDLE_CHECKED(String, arg2, 3);
-  Handle<String> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      MessageTemplate::FormatMessage(template_index, arg0, arg1, arg2));
   isolate->native_context()->IncrementErrorsThrown();
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, MessageTemplate::FormatMessage(
+                                        template_index, arg0, arg1, arg2));
 }
 
 #define CALLSITE_GET(NAME, RETURN)                          \
@@ -316,7 +402,7 @@
     CONVERT_ARG_HANDLE_CHECKED(JSObject, call_site_obj, 0); \
     Handle<String> result;                                  \
     CallSite call_site(isolate, call_site_obj);             \
-    RUNTIME_ASSERT(call_site.IsValid());                    \
+    CHECK(call_site.IsJavaScript() || call_site.IsWasm());  \
     return RETURN(call_site.NAME(), isolate);               \
   }
 
@@ -366,8 +452,8 @@
     JSFunction* fun = frame->function();
     Object* script = fun->shared()->script();
     if (script->IsScript() &&
-        !(Script::cast(script)->source()->IsUndefined())) {
-      Handle<Script> casted_script(Script::cast(script));
+        !(Script::cast(script)->source()->IsUndefined(isolate))) {
+      Handle<Script> casted_script(Script::cast(script), isolate);
       // Compute the location from the function and the relocation info of the
       // baseline code. For optimized code this will use the deoptimization
       // information to get canonical location information.
@@ -416,6 +502,13 @@
       isolate, NewTypeError(MessageTemplate::kCalledNonCallable, callsite));
 }
 
+RUNTIME_FUNCTION(Runtime_ThrowCalledOnNullOrUndefined) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(1, args.length());
+  CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
+  THROW_NEW_ERROR_RETURN_FAILURE(
+      isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined, name));
+}
 
 RUNTIME_FUNCTION(Runtime_ThrowConstructedNonConstructable) {
   HandleScope scope(isolate);
@@ -440,11 +533,8 @@
   HandleScope scope(isolate);
   DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
-  Handle<FixedArray> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      Object::CreateListFromArrayLike(isolate, object, ElementTypes::kAll));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::CreateListFromArrayLike(
+                                        isolate, object, ElementTypes::kAll));
 }
 
 
@@ -456,22 +546,83 @@
   return isolate->heap()->undefined_value();
 }
 
-RUNTIME_FUNCTION(Runtime_GetOrdinaryHasInstance) {
-  HandleScope scope(isolate);
-  DCHECK_EQ(0, args.length());
-
-  return isolate->native_context()->ordinary_has_instance();
-}
-
 RUNTIME_FUNCTION(Runtime_GetAndResetRuntimeCallStats) {
   HandleScope scope(isolate);
-  DCHECK_EQ(0, args.length());
-  std::stringstream stats_stream;
-  isolate->counters()->runtime_call_stats()->Print(stats_stream);
-  Handle<String> result =
-      isolate->factory()->NewStringFromAsciiChecked(stats_stream.str().c_str());
-  isolate->counters()->runtime_call_stats()->Reset();
-  return *result;
+  if (args.length() == 0) {
+    // Without arguments, the result is returned as a string.
+    DCHECK_EQ(0, args.length());
+    std::stringstream stats_stream;
+    isolate->counters()->runtime_call_stats()->Print(stats_stream);
+    Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(
+        stats_stream.str().c_str());
+    isolate->counters()->runtime_call_stats()->Reset();
+    return *result;
+  } else {
+    DCHECK_LE(args.length(), 2);
+    std::FILE* f;
+    if (args[0]->IsString()) {
+      // With a string argument, the results are appended to that file.
+      CONVERT_ARG_HANDLE_CHECKED(String, arg0, 0);
+      String::FlatContent flat = arg0->GetFlatContent();
+      const char* filename =
+          reinterpret_cast<const char*>(&(flat.ToOneByteVector()[0]));
+      f = std::fopen(filename, "a");
+      DCHECK_NOT_NULL(f);
+    } else {
+      // With an integer argument, the results are written to stdout/stderr.
+      CONVERT_SMI_ARG_CHECKED(fd, 0);
+      DCHECK(fd == 1 || fd == 2);
+      f = fd == 1 ? stdout : stderr;
+    }
+    // The second argument (if any) is a message header to be printed.
+    if (args.length() >= 2) {
+      CONVERT_ARG_HANDLE_CHECKED(String, arg1, 1);
+      arg1->PrintOn(f);
+      std::fputc('\n', f);
+      std::fflush(f);
+    }
+    OFStream stats_stream(f);
+    isolate->counters()->runtime_call_stats()->Print(stats_stream);
+    isolate->counters()->runtime_call_stats()->Reset();
+    if (args[0]->IsString())
+      std::fclose(f);
+    else
+      std::fflush(f);
+    return isolate->heap()->undefined_value();
+  }
+}
+
+RUNTIME_FUNCTION(Runtime_EnqueueMicrotask) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 1);
+  CONVERT_ARG_HANDLE_CHECKED(JSFunction, microtask, 0);
+  isolate->EnqueueMicrotask(microtask);
+  return isolate->heap()->undefined_value();
+}
+
+RUNTIME_FUNCTION(Runtime_RunMicrotasks) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 0);
+  isolate->RunMicrotasks();
+  return isolate->heap()->undefined_value();
+}
+
+RUNTIME_FUNCTION(Runtime_OrdinaryHasInstance) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(2, args.length());
+  CONVERT_ARG_HANDLE_CHECKED(Object, callable, 0);
+  CONVERT_ARG_HANDLE_CHECKED(Object, object, 1);
+  RETURN_RESULT_OR_FAILURE(
+      isolate, Object::OrdinaryHasInstance(isolate, callable, object));
+}
+
+RUNTIME_FUNCTION(Runtime_IsWasmObject) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(1, args.length());
+  CONVERT_ARG_CHECKED(Object, object, 0);
+  bool is_wasm_object =
+      object->IsJSObject() && wasm::IsWasmObject(JSObject::cast(object));
+  return *isolate->factory()->ToBoolean(is_wasm_object);
 }
 
 }  // namespace internal
diff --git a/src/runtime/runtime-interpreter.cc b/src/runtime/runtime-interpreter.cc
index 22ae911..f870d23 100644
--- a/src/runtime/runtime-interpreter.cc
+++ b/src/runtime/runtime-interpreter.cc
@@ -64,14 +64,11 @@
     os << " ]" << std::endl;
   }
 
-  // Find the location of the register file.
+  // Print the registers.
   JavaScriptFrameIterator frame_iterator(
       bytecode_iterator.bytecode_array()->GetIsolate());
-  JavaScriptFrame* frame = frame_iterator.frame();
-  Address register_file =
-      frame->fp() + InterpreterFrameConstants::kRegisterFilePointerFromFp;
-
-  // Print the registers.
+  InterpretedFrame* frame =
+      reinterpret_cast<InterpretedFrame*>(frame_iterator.frame());
   int operand_count = interpreter::Bytecodes::NumberOfOperands(bytecode);
   for (int operand_index = 0; operand_index < operand_count; operand_index++) {
     interpreter::OperandType operand_type =
@@ -86,8 +83,7 @@
       int range = bytecode_iterator.GetRegisterOperandRange(operand_index);
       for (int reg_index = first_reg.index();
            reg_index < first_reg.index() + range; reg_index++) {
-        Address reg_location = register_file - reg_index * kPointerSize;
-        Object* reg_object = Memory::Object_at(reg_location);
+        Object* reg_object = frame->ReadInterpreterRegister(reg_index);
         os << "      [ " << std::setw(kRegFieldWidth)
            << interpreter::Register(reg_index).ToString(
                   bytecode_iterator.bytecode_array()->parameter_count())
@@ -117,10 +113,10 @@
   AdvanceToOffsetForTracing(bytecode_iterator, offset);
   if (offset == bytecode_iterator.current_offset()) {
     // Print bytecode.
-    const uint8_t* bytecode_address =
-        reinterpret_cast<const uint8_t*>(*bytecode_array) + bytecode_offset;
-    os << " -> " << static_cast<const void*>(bytecode_address)
-       << " (" << bytecode_offset << ") : ";
+    const uint8_t* base_address = bytecode_array->GetFirstBytecodeAddress();
+    const uint8_t* bytecode_address = base_address + offset;
+    os << " -> " << static_cast<const void*>(bytecode_address) << " @ "
+       << std::setw(4) << offset << " : ";
     interpreter::Bytecodes::Decode(os, bytecode_address,
                                    bytecode_array->parameter_count());
     os << std::endl;
diff --git a/src/runtime/runtime-json.cc b/src/runtime/runtime-json.cc
deleted file mode 100644
index 07232d5..0000000
--- a/src/runtime/runtime-json.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/runtime/runtime-utils.h"
-
-#include "src/arguments.h"
-#include "src/char-predicates-inl.h"
-#include "src/isolate-inl.h"
-#include "src/json-parser.h"
-#include "src/json-stringifier.h"
-#include "src/objects-inl.h"
-
-namespace v8 {
-namespace internal {
-
-RUNTIME_FUNCTION(Runtime_QuoteJSONString) {
-  HandleScope scope(isolate);
-  CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
-  DCHECK(args.length() == 1);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, BasicJsonStringifier::StringifyString(isolate, string));
-  return *result;
-}
-
-
-RUNTIME_FUNCTION(Runtime_BasicJSONStringify) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
-  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
-  BasicJsonStringifier stringifier(isolate);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     stringifier.Stringify(object));
-  return *result;
-}
-
-
-RUNTIME_FUNCTION(Runtime_ParseJson) {
-  HandleScope scope(isolate);
-  DCHECK_EQ(1, args.length());
-  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
-  Handle<String> source;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, source,
-                                     Object::ToString(isolate, object));
-  source = String::Flatten(source);
-  // Optimized fast case where we only have Latin1 characters.
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     source->IsSeqOneByteString()
-                                         ? JsonParser<true>::Parse(source)
-                                         : JsonParser<false>::Parse(source));
-  return *result;
-}
-
-}  // namespace internal
-}  // namespace v8
diff --git a/src/runtime/runtime-literals.cc b/src/runtime/runtime-literals.cc
index f14a7cf..9c43b40 100644
--- a/src/runtime/runtime-literals.cc
+++ b/src/runtime/runtime-literals.cc
@@ -85,7 +85,9 @@
     uint32_t element_index = 0;
     if (key->ToArrayIndex(&element_index)) {
       // Array index (uint32).
-      if (value->IsUninitialized()) value = handle(Smi::FromInt(0), isolate);
+      if (value->IsUninitialized(isolate)) {
+        value = handle(Smi::FromInt(0), isolate);
+      }
       maybe_result = JSObject::SetOwnElementIgnoreAttributes(
           boilerplate, element_index, value, NONE);
     } else {
@@ -109,7 +111,7 @@
   return boilerplate;
 }
 
-MaybeHandle<Object> Runtime::CreateArrayLiteralBoilerplate(
+static MaybeHandle<Object> CreateArrayLiteralBoilerplate(
     Isolate* isolate, Handle<LiteralsArray> literals,
     Handle<FixedArray> elements) {
   // Create the JSArray.
@@ -191,8 +193,7 @@
     case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
       return CreateObjectLiteralBoilerplate(isolate, literals, elements, false);
     case CompileTimeValue::ARRAY_LITERAL:
-      return Runtime::CreateArrayLiteralBoilerplate(isolate, literals,
-                                                    elements);
+      return CreateArrayLiteralBoilerplate(isolate, literals, elements);
     default:
       UNREACHABLE();
       return MaybeHandle<Object>();
@@ -210,7 +211,7 @@
 
   // Check if boilerplate exists. If not, create it first.
   Handle<Object> boilerplate(closure->literals()->literal(index), isolate);
-  if (boilerplate->IsUndefined()) {
+  if (boilerplate->IsUndefined(isolate)) {
     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
         isolate, boilerplate, JSRegExp::New(pattern, JSRegExp::Flags(flags)));
     closure->literals()->set_literal(index, *boilerplate);
@@ -230,14 +231,14 @@
   bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
   bool enable_mementos = (flags & ObjectLiteral::kDisableMementos) == 0;
 
-  RUNTIME_ASSERT(literals_index >= 0 &&
-                 literals_index < literals->literals_count());
+  CHECK(literals_index >= 0);
+  CHECK(literals_index < literals->literals_count());
 
   // Check if boilerplate exists. If not, create it first.
   Handle<Object> literal_site(literals->literal(literals_index), isolate);
   Handle<AllocationSite> site;
   Handle<JSObject> boilerplate;
-  if (*literal_site == isolate->heap()->undefined_value()) {
+  if (literal_site->IsUndefined(isolate)) {
     Handle<Object> raw_boilerplate;
     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
         isolate, raw_boilerplate,
@@ -264,9 +265,7 @@
   MaybeHandle<Object> maybe_copy =
       JSObject::DeepCopy(boilerplate, &usage_context);
   usage_context.ExitScope(site, boilerplate);
-  Handle<Object> copy;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, copy, maybe_copy);
-  return *copy;
+  RETURN_RESULT_OR_FAILURE(isolate, maybe_copy);
 }
 
 MUST_USE_RESULT static MaybeHandle<AllocationSite> GetLiteralAllocationSite(
@@ -275,12 +274,12 @@
   // Check if boilerplate exists. If not, create it first.
   Handle<Object> literal_site(literals->literal(literals_index), isolate);
   Handle<AllocationSite> site;
-  if (*literal_site == isolate->heap()->undefined_value()) {
+  if (literal_site->IsUndefined(isolate)) {
     DCHECK(*elements != isolate->heap()->empty_fixed_array());
     Handle<Object> boilerplate;
     ASSIGN_RETURN_ON_EXCEPTION(
         isolate, boilerplate,
-        Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements),
+        CreateArrayLiteralBoilerplate(isolate, literals, elements),
         AllocationSite);
 
     AllocationSiteCreationContext creation_context(isolate);
@@ -303,9 +302,7 @@
 static MaybeHandle<JSObject> CreateArrayLiteralImpl(
     Isolate* isolate, Handle<LiteralsArray> literals, int literals_index,
     Handle<FixedArray> elements, int flags) {
-  RUNTIME_ASSERT_HANDLIFIED(
-      literals_index >= 0 && literals_index < literals->literals_count(),
-      JSObject);
+  CHECK(literals_index >= 0 && literals_index < literals->literals_count());
   Handle<AllocationSite> site;
   ASSIGN_RETURN_ON_EXCEPTION(
       isolate, site,
@@ -334,12 +331,10 @@
   CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
   CONVERT_SMI_ARG_CHECKED(flags, 3);
 
-  Handle<JSObject> result;
   Handle<LiteralsArray> literals(closure->literals(), isolate);
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, CreateArrayLiteralImpl(isolate, literals, literals_index,
-                                              elements, flags));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, CreateArrayLiteralImpl(isolate, literals, literals_index,
+                                      elements, flags));
 }
 
 
@@ -350,13 +345,11 @@
   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
   CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
 
-  Handle<JSObject> result;
   Handle<LiteralsArray> literals(closure->literals(), isolate);
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
+  RETURN_RESULT_OR_FAILURE(
+      isolate,
       CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
                              ArrayLiteral::kShallowElements));
-  return *result;
 }
 
 }  // namespace internal
diff --git a/src/runtime/runtime-liveedit.cc b/src/runtime/runtime-liveedit.cc
index da342de..72e8648 100644
--- a/src/runtime/runtime-liveedit.cc
+++ b/src/runtime/runtime-liveedit.cc
@@ -70,10 +70,8 @@
   RUNTIME_ASSERT(script->value()->IsScript());
   Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
 
-  Handle<JSArray> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, LiveEdit::GatherCompileInfo(script_handle, source));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate,
+                           LiveEdit::GatherCompileInfo(script_handle, source));
 }
 
 
@@ -223,7 +221,7 @@
         isolate, new_element,
         JSReceiver::GetElement(isolate, new_shared_array, i));
     RUNTIME_ASSERT(
-        new_element->IsUndefined() ||
+        new_element->IsUndefined(isolate) ||
         (new_element->IsJSValue() &&
          Handle<JSValue>::cast(new_element)->value()->IsSharedFunctionInfo()));
   }
diff --git a/src/runtime/runtime-maths.cc b/src/runtime/runtime-maths.cc
index 91b6181..1a923bf 100644
--- a/src/runtime/runtime-maths.cc
+++ b/src/runtime/runtime-maths.cc
@@ -9,24 +9,10 @@
 #include "src/base/utils/random-number-generator.h"
 #include "src/bootstrapper.h"
 #include "src/codegen.h"
-#include "src/third_party/fdlibm/fdlibm.h"
 
 namespace v8 {
 namespace internal {
 
-#define RUNTIME_UNARY_MATH(Name, name)                         \
-  RUNTIME_FUNCTION(Runtime_Math##Name) {                       \
-    HandleScope scope(isolate);                                \
-    DCHECK(args.length() == 1);                                \
-    isolate->counters()->math_##name##_runtime()->Increment(); \
-    CONVERT_DOUBLE_ARG_CHECKED(x, 0);                          \
-    return *isolate->factory()->NewHeapNumber(std::name(x));   \
-  }
-
-RUNTIME_UNARY_MATH(LogRT, log)
-#undef RUNTIME_UNARY_MATH
-
-
 RUNTIME_FUNCTION(Runtime_DoubleHi) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
@@ -49,65 +35,6 @@
 }
 
 
-RUNTIME_FUNCTION(Runtime_ConstructDouble) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 2);
-  CONVERT_NUMBER_CHECKED(uint32_t, hi, Uint32, args[0]);
-  CONVERT_NUMBER_CHECKED(uint32_t, lo, Uint32, args[1]);
-  uint64_t result = (static_cast<uint64_t>(hi) << 32) | lo;
-  return *isolate->factory()->NewNumber(uint64_to_double(result));
-}
-
-
-RUNTIME_FUNCTION(Runtime_RemPiO2) {
-  SealHandleScope shs(isolate);
-  DisallowHeapAllocation no_gc;
-  DCHECK(args.length() == 2);
-  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
-  CONVERT_ARG_CHECKED(JSTypedArray, result, 1);
-  RUNTIME_ASSERT(result->byte_length() == Smi::FromInt(2 * sizeof(double)));
-  FixedFloat64Array* array = FixedFloat64Array::cast(result->elements());
-  double* y = static_cast<double*>(array->DataPtr());
-  return Smi::FromInt(fdlibm::rempio2(x, y));
-}
-
-
-static const double kPiDividedBy4 = 0.78539816339744830962;
-
-
-RUNTIME_FUNCTION(Runtime_MathAtan2) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 2);
-  isolate->counters()->math_atan2_runtime()->Increment();
-  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
-  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
-  double result;
-  if (std::isinf(x) && std::isinf(y)) {
-    // Make sure that the result in case of two infinite arguments
-    // is a multiple of Pi / 4. The sign of the result is determined
-    // by the first argument (x) and the sign of the second argument
-    // determines the multiplier: one or three.
-    int multiplier = (x < 0) ? -1 : 1;
-    if (y < 0) multiplier *= 3;
-    result = multiplier * kPiDividedBy4;
-  } else {
-    result = std::atan2(x, y);
-  }
-  return *isolate->factory()->NewNumber(result);
-}
-
-
-RUNTIME_FUNCTION(Runtime_MathExpRT) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
-  isolate->counters()->math_exp_runtime()->Increment();
-
-  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
-  lazily_initialize_fast_exp(isolate);
-  return *isolate->factory()->NewNumber(fast_exp(x, isolate));
-}
-
-
 // Slow version of Math.pow.  We check for fast paths for special cases.
 // Used if VFP3 is not available.
 RUNTIME_FUNCTION(Runtime_MathPow) {
diff --git a/src/runtime/runtime-numbers.cc b/src/runtime/runtime-numbers.cc
index efbdeb2..edd83bc 100644
--- a/src/runtime/runtime-numbers.cc
+++ b/src/runtime/runtime-numbers.cc
@@ -17,7 +17,7 @@
   HandleScope scope(isolate);
   DCHECK(args.length() == 2);
   CONVERT_SMI_ARG_CHECKED(radix, 1);
-  RUNTIME_ASSERT(2 <= radix && radix <= 36);
+  CHECK(2 <= radix && radix <= 36);
 
   // Fast case where the result is a one character string.
   if (args[0]->IsSmi()) {
@@ -56,8 +56,8 @@
   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
   int f = FastD2IChecked(f_number);
   // See DoubleToFixedCString for these constants:
-  RUNTIME_ASSERT(f >= 0 && f <= 20);
-  RUNTIME_ASSERT(!Double(value).IsSpecial());
+  CHECK(f >= 0 && f <= 20);
+  CHECK(!Double(value).IsSpecial());
   char* str = DoubleToFixedCString(value, f);
   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
   DeleteArray(str);
@@ -72,8 +72,8 @@
   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
   int f = FastD2IChecked(f_number);
-  RUNTIME_ASSERT(f >= -1 && f <= 20);
-  RUNTIME_ASSERT(!Double(value).IsSpecial());
+  CHECK(f >= -1 && f <= 20);
+  CHECK(!Double(value).IsSpecial());
   char* str = DoubleToExponentialCString(value, f);
   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
   DeleteArray(str);
@@ -88,8 +88,8 @@
   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
   int f = FastD2IChecked(f_number);
-  RUNTIME_ASSERT(f >= 1 && f <= 21);
-  RUNTIME_ASSERT(!Double(value).IsSpecial());
+  CHECK(f >= 1 && f <= 21);
+  CHECK(!Double(value).IsSpecial());
   char* str = DoubleToPrecisionCString(value, f);
   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
   DeleteArray(str);
@@ -121,7 +121,7 @@
   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
   CONVERT_NUMBER_CHECKED(int, radix, Int32, args[1]);
   // Step 8.a. is already handled in the JS function.
-  RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
+  CHECK(radix == 0 || (2 <= radix && radix <= 36));
 
   subject = String::Flatten(subject);
   double value;
@@ -174,20 +174,6 @@
 }
 
 
-// TODO(bmeurer): Kill this runtime entry. Uses in date.js are wrong anyway.
-RUNTIME_FUNCTION(Runtime_NumberToIntegerMapMinusZero) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
-  CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, input, Object::ToNumber(input));
-  double double_value = DoubleToInteger(input->Number());
-  // Map both -0 and +0 to +0.
-  if (double_value == 0) double_value = 0;
-
-  return *isolate->factory()->NewNumber(double_value);
-}
-
-
 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
 // a small integer.
 RUNTIME_FUNCTION(Runtime_NumberToSmi) {
diff --git a/src/runtime/runtime-object.cc b/src/runtime/runtime-object.cc
index 5bdb085..c7f2398 100644
--- a/src/runtime/runtime-object.cc
+++ b/src/runtime/runtime-object.cc
@@ -17,8 +17,9 @@
 
 MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
                                                Handle<Object> object,
-                                               Handle<Object> key) {
-  if (object->IsUndefined() || object->IsNull()) {
+                                               Handle<Object> key,
+                                               bool* is_found_out) {
+  if (object->IsUndefined(isolate) || object->IsNull(isolate)) {
     THROW_NEW_ERROR(
         isolate,
         NewTypeError(MessageTemplate::kNonObjectPropertyLoad, key, object),
@@ -30,7 +31,9 @@
       LookupIterator::PropertyOrElement(isolate, object, key, &success);
   if (!success) return MaybeHandle<Object>();
 
-  return Object::GetProperty(&it);
+  MaybeHandle<Object> result = Object::GetProperty(&it);
+  if (is_found_out) *is_found_out = it.IsFound();
+  return result;
 }
 
 static MaybeHandle<Object> KeyedGetObjectProperty(Isolate* isolate,
@@ -62,7 +65,9 @@
           PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
           if (cell->property_details().type() == DATA) {
             Object* value = cell->value();
-            if (!value->IsTheHole()) return Handle<Object>(value, isolate);
+            if (!value->IsTheHole(isolate)) {
+              return Handle<Object>(value, isolate);
+            }
             // If value is the hole (meaning, absent) do the general lookup.
           }
         }
@@ -119,7 +124,7 @@
                                           LanguageMode language_mode) {
   bool success = false;
   LookupIterator it = LookupIterator::PropertyOrElement(
-      isolate, receiver, key, &success, LookupIterator::HIDDEN);
+      isolate, receiver, key, &success, LookupIterator::OWN);
   if (!success) return Nothing<bool>();
 
   return JSReceiver::DeleteProperty(&it, language_mode);
@@ -168,7 +173,7 @@
     }
 
     // Slow case.
-    LookupIterator::Configuration c = LookupIterator::HIDDEN;
+    LookupIterator::Configuration c = LookupIterator::OWN;
     LookupIterator it = key_is_array_index
                             ? LookupIterator(isolate, js_obj, index, js_obj, c)
                             : LookupIterator(js_obj, key, js_obj, c);
@@ -194,7 +199,7 @@
         key_is_array_index
             ? index < static_cast<uint32_t>(String::cast(*object)->length())
             : key->Equals(isolate->heap()->length_string()));
-  } else if (object->IsNull() || object->IsUndefined()) {
+  } else if (object->IsNull(isolate) || object->IsUndefined(isolate)) {
     THROW_NEW_ERROR_RETURN_FAILURE(
         isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject));
   }
@@ -207,7 +212,7 @@
                                                Handle<Object> key,
                                                Handle<Object> value,
                                                LanguageMode language_mode) {
-  if (object->IsUndefined() || object->IsNull()) {
+  if (object->IsUndefined(isolate) || object->IsNull(isolate)) {
     THROW_NEW_ERROR(
         isolate,
         NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
@@ -230,10 +235,7 @@
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
-  Handle<Object> prototype;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, prototype,
-                                     JSReceiver::GetPrototype(isolate, obj));
-  return *prototype;
+  RETURN_RESULT_OR_FAILURE(isolate, JSReceiver::GetPrototype(isolate, obj));
 }
 
 
@@ -260,85 +262,6 @@
   return *obj;
 }
 
-
-// Enumerator used as indices into the array returned from GetOwnProperty
-enum PropertyDescriptorIndices {
-  IS_ACCESSOR_INDEX,
-  VALUE_INDEX,
-  GETTER_INDEX,
-  SETTER_INDEX,
-  WRITABLE_INDEX,
-  ENUMERABLE_INDEX,
-  CONFIGURABLE_INDEX,
-  DESCRIPTOR_SIZE
-};
-
-
-MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
-                                                          Handle<JSObject> obj,
-                                                          Handle<Name> name) {
-  Heap* heap = isolate->heap();
-  Factory* factory = isolate->factory();
-
-  // Get attributes.
-  LookupIterator it = LookupIterator::PropertyOrElement(isolate, obj, name, obj,
-                                                        LookupIterator::HIDDEN);
-  Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it);
-
-  if (!maybe.IsJust()) return MaybeHandle<Object>();
-  PropertyAttributes attrs = maybe.FromJust();
-  if (attrs == ABSENT) return factory->undefined_value();
-
-  DCHECK(!isolate->has_pending_exception());
-  Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE);
-  elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
-  elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
-
-  bool is_accessor_pair = it.state() == LookupIterator::ACCESSOR &&
-                          it.GetAccessors()->IsAccessorPair();
-  elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(is_accessor_pair));
-
-  if (is_accessor_pair) {
-    Handle<AccessorPair> accessors =
-        Handle<AccessorPair>::cast(it.GetAccessors());
-    Handle<Object> getter =
-        AccessorPair::GetComponent(accessors, ACCESSOR_GETTER);
-    Handle<Object> setter =
-        AccessorPair::GetComponent(accessors, ACCESSOR_SETTER);
-    elms->set(GETTER_INDEX, *getter);
-    elms->set(SETTER_INDEX, *setter);
-  } else {
-    Handle<Object> value;
-    ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::GetProperty(&it),
-                               Object);
-    elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
-    elms->set(VALUE_INDEX, *value);
-  }
-
-  return factory->NewJSArrayWithElements(elms);
-}
-
-
-// Returns an array with the property description:
-//  if args[1] is not a property on args[0]
-//          returns undefined
-//  if args[1] is a data property on args[0]
-//         [false, value, Writeable, Enumerable, Configurable]
-//  if args[1] is an accessor on args[0]
-//         [true, GetFunction, SetFunction, Enumerable, Configurable]
-// TODO(jkummerow): Deprecated. Remove all callers and delete.
-RUNTIME_FUNCTION(Runtime_GetOwnProperty_Legacy) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 2);
-  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
-  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     GetOwnProperty(isolate, obj, name));
-  return *result;
-}
-
-
 RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 2);
@@ -354,42 +277,6 @@
 }
 
 
-RUNTIME_FUNCTION(Runtime_LoadGlobalViaContext) {
-  HandleScope scope(isolate);
-  DCHECK_EQ(1, args.length());
-  CONVERT_SMI_ARG_CHECKED(slot, 0);
-
-  // Go up context chain to the script context.
-  Handle<Context> script_context(isolate->context()->script_context(), isolate);
-  DCHECK(script_context->IsScriptContext());
-  DCHECK(script_context->get(slot)->IsPropertyCell());
-
-  // Lookup the named property on the global object.
-  Handle<ScopeInfo> scope_info(script_context->scope_info(), isolate);
-  Handle<Name> name(scope_info->ContextSlotName(slot), isolate);
-  Handle<JSGlobalObject> global_object(script_context->global_object(),
-                                       isolate);
-  LookupIterator it(global_object, name, global_object, LookupIterator::HIDDEN);
-
-  // Switch to fast mode only if there is a data property and it's not on
-  // a hidden prototype.
-  if (it.state() == LookupIterator::DATA &&
-      it.GetHolder<Object>().is_identical_to(global_object)) {
-    // Now update the cell in the script context.
-    Handle<PropertyCell> cell = it.GetPropertyCell();
-    script_context->set(slot, *cell);
-  } else {
-    // This is not a fast case, so keep this access in a slow mode.
-    // Store empty_property_cell here to release the outdated property cell.
-    script_context->set(slot, isolate->heap()->empty_property_cell());
-  }
-
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
-  return *result;
-}
-
-
 namespace {
 
 Object* StoreGlobalViaContext(Isolate* isolate, int slot, Handle<Object> value,
@@ -404,7 +291,7 @@
   Handle<Name> name(scope_info->ContextSlotName(slot), isolate);
   Handle<JSGlobalObject> global_object(script_context->global_object(),
                                        isolate);
-  LookupIterator it(global_object, name, global_object, LookupIterator::HIDDEN);
+  LookupIterator it(global_object, name, global_object, LookupIterator::OWN);
 
   // Switch to fast mode only if there is a data property and it's not on
   // a hidden prototype.
@@ -455,13 +342,10 @@
   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
 
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, Runtime::GetObjectProperty(isolate, object, key));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate,
+                           Runtime::GetObjectProperty(isolate, object, key));
 }
 
-
 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
   HandleScope scope(isolate);
@@ -470,16 +354,14 @@
   CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
 
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, KeyedGetObjectProperty(isolate, receiver_obj, key_obj));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, KeyedGetObjectProperty(isolate, receiver_obj, key_obj));
 }
 
 
 RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
   HandleScope scope(isolate);
-  RUNTIME_ASSERT(args.length() == 4);
+  DCHECK_EQ(4, args.length());
 
   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
@@ -492,14 +374,11 @@
   LookupIterator it(object, name, object, LookupIterator::OWN_SKIP_INTERCEPTOR);
   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
   if (!maybe.IsJust()) return isolate->heap()->exception();
-  RUNTIME_ASSERT(!it.IsFound());
+  CHECK(!it.IsFound());
 #endif
 
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      JSObject::SetOwnPropertyIgnoreAttributes(object, name, value, attrs));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
+                                        object, name, value, attrs));
 }
 
 
@@ -507,7 +386,7 @@
 // This is used to create an indexed data property into an array.
 RUNTIME_FUNCTION(Runtime_AddElement) {
   HandleScope scope(isolate);
-  RUNTIME_ASSERT(args.length() == 3);
+  DCHECK_EQ(3, args.length());
 
   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
@@ -521,25 +400,22 @@
                     LookupIterator::OWN_SKIP_INTERCEPTOR);
   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
   if (!maybe.IsJust()) return isolate->heap()->exception();
-  RUNTIME_ASSERT(!it.IsFound());
+  CHECK(!it.IsFound());
 
   if (object->IsJSArray()) {
     Handle<JSArray> array = Handle<JSArray>::cast(object);
-    RUNTIME_ASSERT(!JSArray::WouldChangeReadOnlyLength(array, index));
+    CHECK(!JSArray::WouldChangeReadOnlyLength(array, index));
   }
 #endif
 
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      JSObject::SetOwnElementIgnoreAttributes(object, index, value, NONE));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, JSObject::SetOwnElementIgnoreAttributes(
+                                        object, index, value, NONE));
 }
 
 
 RUNTIME_FUNCTION(Runtime_AppendElement) {
   HandleScope scope(isolate);
-  RUNTIME_ASSERT(args.length() == 2);
+  DCHECK_EQ(2, args.length());
 
   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
@@ -547,9 +423,8 @@
   uint32_t index;
   CHECK(array->length()->ToArrayIndex(&index));
 
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, JSObject::AddDataElement(array, index, value, NONE));
+  RETURN_FAILURE_ON_EXCEPTION(
+      isolate, JSObject::AddDataElement(array, index, value, NONE));
   JSObject::ValidateElements(array);
   return *array;
 }
@@ -557,7 +432,7 @@
 
 RUNTIME_FUNCTION(Runtime_SetProperty) {
   HandleScope scope(isolate);
-  RUNTIME_ASSERT(args.length() == 4);
+  DCHECK_EQ(4, args.length());
 
   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
@@ -565,11 +440,9 @@
   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode_arg, 3);
   LanguageMode language_mode = language_mode_arg;
 
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
+  RETURN_RESULT_OR_FAILURE(
+      isolate,
       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
-  return *result;
 }
 
 
@@ -660,7 +533,8 @@
   Handle<FixedArray> keys;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
       isolate, keys,
-      JSReceiver::GetKeys(object, OWN_ONLY, filter, CONVERT_TO_STRING));
+      KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, filter,
+                              GetKeysConversion::kConvertToString));
 
   return *isolate->factory()->NewJSArrayWithElements(keys);
 }
@@ -708,10 +582,7 @@
   DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, new_target, 1);
-  Handle<JSObject> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     JSObject::New(target, new_target));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, JSObject::New(target, new_target));
 }
 
 
@@ -726,44 +597,19 @@
 }
 
 
-RUNTIME_FUNCTION(Runtime_GlobalProxy) {
-  SealHandleScope shs(isolate);
-  DCHECK(args.length() == 1);
-  CONVERT_ARG_CHECKED(JSFunction, function, 0);
-  return function->context()->global_proxy();
-}
-
-
-RUNTIME_FUNCTION(Runtime_LookupAccessor) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 3);
-  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
-  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
-  CONVERT_SMI_ARG_CHECKED(flag, 2);
-  AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
-  if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component));
-  return *result;
-}
-
-
 RUNTIME_FUNCTION(Runtime_LoadMutableDouble) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 2);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
   CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1);
-  RUNTIME_ASSERT((index->value() & 1) == 1);
+  CHECK((index->value() & 1) == 1);
   FieldIndex field_index =
       FieldIndex::ForLoadByFieldIndex(object->map(), index->value());
   if (field_index.is_inobject()) {
-    RUNTIME_ASSERT(field_index.property_index() <
-                   object->map()->GetInObjectProperties());
+    CHECK(field_index.property_index() <
+          object->map()->GetInObjectProperties());
   } else {
-    RUNTIME_ASSERT(field_index.outobject_array_index() <
-                   object->properties()->length());
+    CHECK(field_index.outobject_array_index() < object->properties()->length());
   }
   return *JSObject::FastPropertyAt(object, Representation::Double(),
                                    field_index);
@@ -793,9 +639,8 @@
   return isolate->heap()->ToBoolean(obj->IsJSGlobalProxy());
 }
 
-
-static bool IsValidAccessor(Handle<Object> obj) {
-  return obj->IsUndefined() || obj->IsCallable() || obj->IsNull();
+static bool IsValidAccessor(Isolate* isolate, Handle<Object> obj) {
+  return obj->IsUndefined(isolate) || obj->IsCallable() || obj->IsNull(isolate);
 }
 
 
@@ -809,12 +654,12 @@
   HandleScope scope(isolate);
   DCHECK(args.length() == 5);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
-  RUNTIME_ASSERT(!obj->IsNull());
+  CHECK(!obj->IsNull(isolate));
   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
-  RUNTIME_ASSERT(IsValidAccessor(getter));
+  CHECK(IsValidAccessor(isolate, getter));
   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
-  RUNTIME_ASSERT(IsValidAccessor(setter));
+  CHECK(IsValidAccessor(isolate, setter));
   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 4);
 
   RETURN_FAILURE_ON_EXCEPTION(
@@ -823,34 +668,6 @@
 }
 
 
-// Implements part of 8.12.9 DefineOwnProperty.
-// There are 3 cases that lead here:
-// Step 4a - define a new data property.
-// Steps 9b & 12 - replace an existing accessor property with a data property.
-// Step 12 - update an existing data property with a data or generic
-//           descriptor.
-RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 4);
-  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
-  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
-  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
-  CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
-
-  LookupIterator it = LookupIterator::PropertyOrElement(
-      isolate, object, name, object, LookupIterator::OWN);
-  if (it.state() == LookupIterator::ACCESS_CHECK && !it.HasAccess()) {
-    return isolate->heap()->undefined_value();
-  }
-
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, JSObject::DefineOwnPropertyIgnoreAttributes(
-                           &it, value, attrs, JSObject::DONT_FORCE_FIELD));
-
-  return *result;
-}
-
 RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 5);
@@ -860,7 +677,7 @@
   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
   CONVERT_SMI_ARG_CHECKED(set_function_name, 4);
 
-  if (FLAG_harmony_function_name && set_function_name) {
+  if (set_function_name) {
     DCHECK(value->IsJSFunction());
     JSFunction::SetName(Handle<JSFunction>::cast(value), name,
                         isolate->factory()->empty_string());
@@ -929,8 +746,7 @@
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, getter, 2);
   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
 
-  if (FLAG_harmony_function_name &&
-      String::cast(getter->shared()->name())->length() == 0) {
+  if (String::cast(getter->shared()->name())->length() == 0) {
     JSFunction::SetName(getter, name, isolate->factory()->get_string());
   }
 
@@ -950,8 +766,7 @@
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, setter, 2);
   CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
 
-  if (FLAG_harmony_function_name &&
-      String::cast(setter->shared()->name())->length() == 0) {
+  if (String::cast(setter->shared()->name())->length() == 0) {
     JSFunction::SetName(setter, name, isolate->factory()->set_string());
   }
 
@@ -967,10 +782,7 @@
   HandleScope scope(isolate);
   DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
-  Handle<JSReceiver> receiver;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
-                                     Object::ToObject(isolate, object));
-  return *receiver;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::ToObject(isolate, object));
 }
 
 
@@ -978,10 +790,7 @@
   HandleScope scope(isolate);
   DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     Object::ToPrimitive(input));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::ToPrimitive(input));
 }
 
 
@@ -989,10 +798,8 @@
   HandleScope scope(isolate);
   DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, Object::ToPrimitive(input, ToPrimitiveHint::kNumber));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, Object::ToPrimitive(input, ToPrimitiveHint::kNumber));
 }
 
 
@@ -1000,10 +807,8 @@
   HandleScope scope(isolate);
   DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, Object::ToPrimitive(input, ToPrimitiveHint::kString));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, Object::ToPrimitive(input, ToPrimitiveHint::kString));
 }
 
 
@@ -1011,9 +816,7 @@
   HandleScope scope(isolate);
   DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::ToNumber(input));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::ToNumber(input));
 }
 
 
@@ -1021,10 +824,7 @@
   HandleScope scope(isolate);
   DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     Object::ToInteger(isolate, input));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::ToInteger(isolate, input));
 }
 
 
@@ -1032,10 +832,7 @@
   HandleScope scope(isolate);
   DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     Object::ToLength(isolate, input));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::ToLength(isolate, input));
 }
 
 
@@ -1043,10 +840,7 @@
   HandleScope scope(isolate);
   DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     Object::ToString(isolate, input));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::ToString(isolate, input));
 }
 
 
@@ -1054,10 +848,7 @@
   HandleScope scope(isolate);
   DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     Object::ToName(isolate, input));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::ToName(isolate, input));
 }
 
 
@@ -1104,97 +895,6 @@
   return isolate->heap()->exception();
 }
 
-
-RUNTIME_FUNCTION(Runtime_InstanceOf) {
-  // TODO(4447): Remove this function when ES6 instanceof ships for good.
-  DCHECK(!FLAG_harmony_instanceof);
-
-  // ECMA-262, section 11.8.6, page 54.
-  HandleScope shs(isolate);
-  DCHECK_EQ(2, args.length());
-  DCHECK(args.length() == 2);
-  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
-  CONVERT_ARG_HANDLE_CHECKED(Object, callable, 1);
-  // {callable} must have a [[Call]] internal method.
-  if (!callable->IsCallable()) {
-    THROW_NEW_ERROR_RETURN_FAILURE(
-        isolate,
-        NewTypeError(MessageTemplate::kInstanceofFunctionExpected, callable));
-  }
-  // If {object} is not a receiver, return false.
-  if (!object->IsJSReceiver()) {
-    return isolate->heap()->false_value();
-  }
-  // Check if {callable} is bound, if so, get [[BoundTargetFunction]] from it
-  // and use that instead of {callable}.
-  while (callable->IsJSBoundFunction()) {
-    callable =
-        handle(Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
-               isolate);
-  }
-  DCHECK(callable->IsCallable());
-  // Get the "prototype" of {callable}; raise an error if it's not a receiver.
-  Handle<Object> prototype;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, prototype,
-      JSReceiver::GetProperty(Handle<JSReceiver>::cast(callable),
-                              isolate->factory()->prototype_string()));
-  if (!prototype->IsJSReceiver()) {
-    THROW_NEW_ERROR_RETURN_FAILURE(
-        isolate,
-        NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype));
-  }
-  // Return whether or not {prototype} is in the prototype chain of {object}.
-  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
-  Maybe<bool> result =
-      JSReceiver::HasInPrototypeChain(isolate, receiver, prototype);
-  MAYBE_RETURN(result, isolate->heap()->exception());
-  return isolate->heap()->ToBoolean(result.FromJust());
-}
-
-RUNTIME_FUNCTION(Runtime_OrdinaryHasInstance) {
-  // ES6 section 19.2.3.6 Function.prototype[@@hasInstance](V)
-  HandleScope shs(isolate);
-  DCHECK_EQ(2, args.length());
-  DCHECK(args.length() == 2);
-  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
-  CONVERT_ARG_HANDLE_CHECKED(Object, callable, 1);
-  // {callable} must have a [[Call]] internal method.
-  if (!callable->IsCallable()) {
-    return isolate->heap()->false_value();
-  }
-  // If {object} is not a receiver, return false.
-  if (!object->IsJSReceiver()) {
-    return isolate->heap()->false_value();
-  }
-  // Check if {callable} is bound, if so, get [[BoundTargetFunction]] from it
-  // and use that instead of {callable}.
-  while (callable->IsJSBoundFunction()) {
-    callable =
-        handle(Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
-               isolate);
-  }
-  DCHECK(callable->IsCallable());
-  // Get the "prototype" of {callable}; raise an error if it's not a receiver.
-  Handle<Object> prototype;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, prototype,
-      JSReceiver::GetProperty(Handle<JSReceiver>::cast(callable),
-                              isolate->factory()->prototype_string()));
-  if (!prototype->IsJSReceiver()) {
-    THROW_NEW_ERROR_RETURN_FAILURE(
-        isolate,
-        NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype));
-  }
-  // Return whether or not {prototype} is in the prototype chain of {object}.
-  Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
-  Maybe<bool> result =
-      JSReceiver::HasInPrototypeChain(isolate, receiver, prototype);
-  MAYBE_RETURN(result, isolate->heap()->exception());
-  return isolate->heap()->ToBoolean(result.FromJust());
-}
-
-
 RUNTIME_FUNCTION(Runtime_HasInPrototypeChain) {
   HandleScope scope(isolate);
   DCHECK_EQ(2, args.length());
@@ -1229,24 +929,20 @@
 }
 
 
-RUNTIME_FUNCTION(Runtime_ObjectDefineProperty) {
+RUNTIME_FUNCTION(Runtime_CreateDataProperty) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 3);
-  CONVERT_ARG_HANDLE_CHECKED(Object, o, 0);
-  CONVERT_ARG_HANDLE_CHECKED(Object, name, 1);
-  CONVERT_ARG_HANDLE_CHECKED(Object, attributes, 2);
-  return JSReceiver::DefineProperty(isolate, o, name, attributes);
-}
-
-
-RUNTIME_FUNCTION(Runtime_ObjectDefineProperties) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 2);
-  CONVERT_ARG_HANDLE_CHECKED(Object, o, 0);
-  CONVERT_ARG_HANDLE_CHECKED(Object, properties, 1);
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, o, JSReceiver::DefineProperties(isolate, o, properties));
-  return *o;
+  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, o, 0);
+  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
+  bool success;
+  LookupIterator it = LookupIterator::PropertyOrElement(
+      isolate, o, key, &success, LookupIterator::OWN);
+  if (!success) return isolate->heap()->exception();
+  MAYBE_RETURN(
+      JSReceiver::CreateDataProperty(&it, value, Object::THROW_ON_ERROR),
+      isolate->heap()->exception());
+  return *value;
 }
 
 }  // namespace internal
diff --git a/src/runtime/runtime-observe.cc b/src/runtime/runtime-observe.cc
deleted file mode 100644
index 0407b8a..0000000
--- a/src/runtime/runtime-observe.cc
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/runtime/runtime-utils.h"
-
-#include "src/arguments.h"
-#include "src/debug/debug.h"
-#include "src/isolate-inl.h"
-
-namespace v8 {
-namespace internal {
-
-RUNTIME_FUNCTION(Runtime_IsObserved) {
-  SealHandleScope shs(isolate);
-  DCHECK(args.length() == 1);
-
-  if (!args[0]->IsJSReceiver()) return isolate->heap()->false_value();
-  CONVERT_ARG_CHECKED(JSReceiver, obj, 0);
-  DCHECK(!obj->IsJSGlobalProxy() || !obj->map()->is_observed());
-  return isolate->heap()->ToBoolean(obj->map()->is_observed());
-}
-
-
-RUNTIME_FUNCTION(Runtime_SetIsObserved) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
-  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
-  RUNTIME_ASSERT(!obj->IsJSGlobalProxy());
-  if (obj->IsJSProxy()) return isolate->heap()->undefined_value();
-  RUNTIME_ASSERT(!obj->map()->is_observed());
-
-  DCHECK(obj->IsJSObject());
-  JSObject::SetObserved(Handle<JSObject>::cast(obj));
-  return isolate->heap()->undefined_value();
-}
-
-
-RUNTIME_FUNCTION(Runtime_EnqueueMicrotask) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
-  CONVERT_ARG_HANDLE_CHECKED(JSFunction, microtask, 0);
-  isolate->EnqueueMicrotask(microtask);
-  return isolate->heap()->undefined_value();
-}
-
-
-RUNTIME_FUNCTION(Runtime_RunMicrotasks) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 0);
-  isolate->RunMicrotasks();
-  return isolate->heap()->undefined_value();
-}
-
-
-RUNTIME_FUNCTION(Runtime_DeliverObservationChangeRecords) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 2);
-  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callback, 0);
-  CONVERT_ARG_HANDLE_CHECKED(Object, argument, 1);
-  v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
-  // We should send a message on uncaught exception thrown during
-  // Object.observe delivery while not interrupting further delivery, thus
-  // we make a call inside a verbose TryCatch.
-  catcher.SetVerbose(true);
-  Handle<Object> argv[] = {argument};
-
-  // If we are in step-in mode, flood the handler.
-  isolate->debug()->EnableStepIn();
-
-  USE(Execution::Call(isolate, callback, isolate->factory()->undefined_value(),
-                      arraysize(argv), argv));
-  if (isolate->has_pending_exception()) {
-    isolate->ReportPendingMessages();
-    isolate->clear_pending_exception();
-    isolate->set_external_caught_exception(false);
-  }
-  return isolate->heap()->undefined_value();
-}
-
-
-RUNTIME_FUNCTION(Runtime_GetObservationState) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 0);
-  isolate->CountUsage(v8::Isolate::kObjectObserve);
-  return isolate->heap()->observation_state();
-}
-
-
-static bool ContextsHaveSameOrigin(Handle<Context> context1,
-                                   Handle<Context> context2) {
-  return context1->security_token() == context2->security_token();
-}
-
-
-RUNTIME_FUNCTION(Runtime_ObserverObjectAndRecordHaveSameOrigin) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 3);
-  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, observer, 0);
-  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 1);
-  CONVERT_ARG_HANDLE_CHECKED(JSObject, record, 2);
-
-  while (observer->IsJSBoundFunction()) {
-    observer = handle(
-        Handle<JSBoundFunction>::cast(observer)->bound_target_function());
-  }
-  if (!observer->IsJSFunction()) return isolate->heap()->false_value();
-
-  Handle<Context> observer_context(
-      Handle<JSFunction>::cast(observer)->context()->native_context());
-  Handle<Context> object_context(object->GetCreationContext());
-  Handle<Context> record_context(record->GetCreationContext());
-
-  return isolate->heap()->ToBoolean(
-      ContextsHaveSameOrigin(object_context, observer_context) &&
-      ContextsHaveSameOrigin(object_context, record_context));
-}
-
-
-RUNTIME_FUNCTION(Runtime_ObjectWasCreatedInCurrentOrigin) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
-  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
-
-  Handle<Context> creation_context(object->GetCreationContext(), isolate);
-  return isolate->heap()->ToBoolean(
-      ContextsHaveSameOrigin(creation_context, isolate->native_context()));
-}
-
-
-RUNTIME_FUNCTION(Runtime_GetObjectContextObjectObserve) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
-  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
-
-  Handle<Context> context(object->GetCreationContext(), isolate);
-  return context->native_object_observe();
-}
-
-
-RUNTIME_FUNCTION(Runtime_GetObjectContextObjectGetNotifier) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
-  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
-
-  Handle<Context> context(object->GetCreationContext(), isolate);
-  return context->native_object_get_notifier();
-}
-
-
-RUNTIME_FUNCTION(Runtime_GetObjectContextNotifierPerformChange) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
-  CONVERT_ARG_HANDLE_CHECKED(JSObject, object_info, 0);
-
-  Handle<Context> context(object_info->GetCreationContext(), isolate);
-  return context->native_object_notifier_perform_change();
-}
-}  // namespace internal
-}  // namespace v8
diff --git a/src/runtime/runtime-operators.cc b/src/runtime/runtime-operators.cc
index e55ab7c..2a9255b 100644
--- a/src/runtime/runtime-operators.cc
+++ b/src/runtime/runtime-operators.cc
@@ -14,10 +14,7 @@
   DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     Object::Multiply(isolate, lhs, rhs));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::Multiply(isolate, lhs, rhs));
 }
 
 
@@ -26,10 +23,7 @@
   DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     Object::Divide(isolate, lhs, rhs));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::Divide(isolate, lhs, rhs));
 }
 
 
@@ -38,10 +32,7 @@
   DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     Object::Modulus(isolate, lhs, rhs));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::Modulus(isolate, lhs, rhs));
 }
 
 
@@ -50,10 +41,7 @@
   DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     Object::Add(isolate, lhs, rhs));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::Add(isolate, lhs, rhs));
 }
 
 
@@ -62,10 +50,7 @@
   DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     Object::Subtract(isolate, lhs, rhs));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::Subtract(isolate, lhs, rhs));
 }
 
 
@@ -74,10 +59,7 @@
   DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     Object::ShiftLeft(isolate, lhs, rhs));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::ShiftLeft(isolate, lhs, rhs));
 }
 
 
@@ -86,10 +68,7 @@
   DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     Object::ShiftRight(isolate, lhs, rhs));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::ShiftRight(isolate, lhs, rhs));
 }
 
 
@@ -98,10 +77,8 @@
   DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, Object::ShiftRightLogical(isolate, lhs, rhs));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate,
+                           Object::ShiftRightLogical(isolate, lhs, rhs));
 }
 
 
@@ -110,10 +87,7 @@
   DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     Object::BitwiseAnd(isolate, lhs, rhs));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::BitwiseAnd(isolate, lhs, rhs));
 }
 
 
@@ -122,10 +96,7 @@
   DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     Object::BitwiseOr(isolate, lhs, rhs));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::BitwiseOr(isolate, lhs, rhs));
 }
 
 
@@ -134,10 +105,7 @@
   DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
-                                     Object::BitwiseXor(isolate, lhs, rhs));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, Object::BitwiseXor(isolate, lhs, rhs));
 }
 
 RUNTIME_FUNCTION(Runtime_Equal) {
@@ -216,5 +184,14 @@
   return isolate->heap()->ToBoolean(result.FromJust());
 }
 
+RUNTIME_FUNCTION(Runtime_InstanceOf) {
+  HandleScope shs(isolate);
+  DCHECK_EQ(2, args.length());
+  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
+  CONVERT_ARG_HANDLE_CHECKED(Object, callable, 1);
+  RETURN_RESULT_OR_FAILURE(isolate,
+                           Object::InstanceOf(isolate, object, callable));
+}
+
 }  // namespace internal
 }  // namespace v8
diff --git a/src/runtime/runtime-proxy.cc b/src/runtime/runtime-proxy.cc
index 7764d25..87c7c91 100644
--- a/src/runtime/runtime-proxy.cc
+++ b/src/runtime/runtime-proxy.cc
@@ -40,17 +40,15 @@
       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name));
   // 6. If trap is undefined, then
   int const arguments_length = args.length() - 2;
-  if (trap->IsUndefined()) {
+  if (trap->IsUndefined(isolate)) {
     // 6.a. Return Call(target, thisArgument, argumentsList).
     ScopedVector<Handle<Object>> argv(arguments_length);
     for (int i = 0; i < arguments_length; ++i) {
       argv[i] = args.at<Object>(i + 1);
     }
-    Handle<Object> result;
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-        isolate, result, Execution::Call(isolate, target, receiver,
-                                         arguments_length, argv.start()));
-    return *result;
+    RETURN_RESULT_OR_FAILURE(
+        isolate, Execution::Call(isolate, target, receiver, arguments_length,
+                                 argv.start()));
   }
   // 7. Let argArray be CreateArrayFromList(argumentsList).
   Handle<JSArray> arg_array = isolate->factory()->NewJSArray(
@@ -63,12 +61,10 @@
     }
   }
   // 8. Return Call(trap, handler, «target, thisArgument, argArray»).
-  Handle<Object> trap_result;
   Handle<Object> trap_args[] = {target, receiver, arg_array};
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, trap_result,
+  RETURN_RESULT_OR_FAILURE(
+      isolate,
       Execution::Call(isolate, trap, handler, arraysize(trap_args), trap_args));
-  return *trap_result;
 }
 
 
@@ -98,7 +94,7 @@
       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name));
   // 6. If trap is undefined, then
   int const arguments_length = args.length() - 3;
-  if (trap->IsUndefined()) {
+  if (trap->IsUndefined(isolate)) {
     // 6.a. Assert: target has a [[Construct]] internal method.
     DCHECK(target->IsConstructor());
     // 6.b. Return Construct(target, argumentsList, newTarget).
@@ -106,11 +102,9 @@
     for (int i = 0; i < arguments_length; ++i) {
       argv[i] = args.at<Object>(i + 1);
     }
-    Handle<Object> result;
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-        isolate, result, Execution::New(isolate, target, new_target,
-                                        arguments_length, argv.start()));
-    return *result;
+    RETURN_RESULT_OR_FAILURE(
+        isolate, Execution::New(isolate, target, new_target, arguments_length,
+                                argv.start()));
   }
   // 7. Let argArray be CreateArrayFromList(argumentsList).
   Handle<JSArray> arg_array = isolate->factory()->NewJSArray(
diff --git a/src/runtime/runtime-regexp.cc b/src/runtime/runtime-regexp.cc
index aead017..a8133d3 100644
--- a/src/runtime/runtime-regexp.cc
+++ b/src/runtime/runtime-regexp.cc
@@ -544,9 +544,7 @@
   RegExpImpl::SetLastMatchInfo(last_match_info, subject, capture_count,
                                global_cache.LastSuccessfulMatch());
 
-  Handle<String> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, builder.ToString());
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, builder.ToString());
 }
 
 
@@ -658,8 +656,8 @@
   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
 
-  RUNTIME_ASSERT(regexp->GetFlags() & JSRegExp::kGlobal);
-  RUNTIME_ASSERT(last_match_info->HasFastObjectElements());
+  CHECK(regexp->GetFlags() & JSRegExp::kGlobal);
+  CHECK(last_match_info->HasFastObjectElements());
 
   subject = String::Flatten(subject);
 
@@ -686,11 +684,11 @@
   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
-  RUNTIME_ASSERT(limit > 0);
+  CHECK(limit > 0);
 
   int subject_length = subject->length();
   int pattern_length = pattern->length();
-  RUNTIME_ASSERT(pattern_length > 0);
+  CHECK(pattern_length > 0);
 
   if (limit == 0xffffffffu) {
     FixedArray* last_match_cache_unused;
@@ -776,14 +774,11 @@
   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
   // Due to the way the JS calls are constructed this must be less than the
   // length of a string, i.e. it is always a Smi.  We check anyway for security.
-  RUNTIME_ASSERT(index >= 0);
-  RUNTIME_ASSERT(index <= subject->length());
+  CHECK(index >= 0);
+  CHECK(index <= subject->length());
   isolate->counters()->regexp_entry_runtime()->Increment();
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result,
-      RegExpImpl::Exec(regexp, subject, index, last_match_info));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, RegExpImpl::Exec(regexp, subject, index, last_match_info));
 }
 
 
@@ -807,7 +802,7 @@
   HandleScope handle_scope(isolate);
   DCHECK(args.length() == 3);
   CONVERT_SMI_ARG_CHECKED(size, 0);
-  RUNTIME_ASSERT(size >= 0 && size <= FixedArray::kMaxLength);
+  CHECK(size >= 0 && size <= FixedArray::kMaxLength);
   CONVERT_ARG_HANDLE_CHECKED(Object, index, 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, input, 2);
   Handle<FixedArray> elements = isolate->factory()->NewFixedArray(size);
@@ -995,11 +990,11 @@
   CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
   CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
-  RUNTIME_ASSERT(last_match_info->HasFastObjectElements());
-  RUNTIME_ASSERT(result_array->HasFastObjectElements());
+  CHECK(last_match_info->HasFastObjectElements());
+  CHECK(result_array->HasFastObjectElements());
 
   subject = String::Flatten(subject);
-  RUNTIME_ASSERT(regexp->GetFlags() & JSRegExp::kGlobal);
+  CHECK(regexp->GetFlags() & JSRegExp::kGlobal);
 
   if (regexp->CaptureCount() == 0) {
     return SearchRegExpMultiple<false>(isolate, subject, regexp,
diff --git a/src/runtime/runtime-scopes.cc b/src/runtime/runtime-scopes.cc
index de0d66a..0bdbe2e 100644
--- a/src/runtime/runtime-scopes.cc
+++ b/src/runtime/runtime-scopes.cc
@@ -16,10 +16,18 @@
 namespace v8 {
 namespace internal {
 
-static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) {
+enum class RedeclarationType { kSyntaxError = 0, kTypeError = 1 };
+
+static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name,
+                                       RedeclarationType redeclaration_type) {
   HandleScope scope(isolate);
-  THROW_NEW_ERROR_RETURN_FAILURE(
-      isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name));
+  if (redeclaration_type == RedeclarationType::kSyntaxError) {
+    THROW_NEW_ERROR_RETURN_FAILURE(
+        isolate, NewSyntaxError(MessageTemplate::kVarRedeclaration, name));
+  } else {
+    THROW_NEW_ERROR_RETURN_FAILURE(
+        isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name));
+  }
 }
 
 
@@ -34,25 +42,28 @@
 static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global,
                               Handle<String> name, Handle<Object> value,
                               PropertyAttributes attr, bool is_var,
-                              bool is_const, bool is_function) {
+                              bool is_function,
+                              RedeclarationType redeclaration_type) {
   Handle<ScriptContextTable> script_contexts(
       global->native_context()->script_context_table());
   ScriptContextTable::LookupResult lookup;
   if (ScriptContextTable::Lookup(script_contexts, name, &lookup) &&
       IsLexicalVariableMode(lookup.mode)) {
-    return ThrowRedeclarationError(isolate, name);
+    // ES#sec-globaldeclarationinstantiation 6.a:
+    // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
+    // exception.
+    return ThrowRedeclarationError(isolate, name,
+                                   RedeclarationType::kSyntaxError);
   }
 
   // Do the lookup own properties only, see ES5 erratum.
-  LookupIterator it(global, name, global,
-                    LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
+  LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR);
   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
   if (!maybe.IsJust()) return isolate->heap()->exception();
 
   if (it.IsFound()) {
     PropertyAttributes old_attributes = maybe.FromJust();
     // The name was declared before; check for conflicting re-declarations.
-    if (is_const) return ThrowRedeclarationError(isolate, name);
 
     // Skip var re-declarations.
     if (is_var) return isolate->heap()->undefined_value();
@@ -69,7 +80,11 @@
       if (old_details.IsReadOnly() || old_details.IsDontEnum() ||
           (it.state() == LookupIterator::ACCESSOR &&
            it.GetAccessors()->IsAccessorPair())) {
-        return ThrowRedeclarationError(isolate, name);
+        // ES#sec-globaldeclarationinstantiation 5.d:
+        // If hasRestrictedGlobal is true, throw a SyntaxError exception.
+        // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b:
+        // If fnDefinable is false, throw a TypeError exception.
+        return ThrowRedeclarationError(isolate, name, redeclaration_type);
       }
       // If the existing property is not configurable, keep its attributes. Do
       attr = old_attributes;
@@ -107,14 +122,9 @@
     Handle<String> name(String::cast(pairs->get(i)));
     Handle<Object> initial_value(pairs->get(i + 1), isolate);
 
-    // We have to declare a global const property. To capture we only
-    // assign to it when evaluating the assignment for "const x =
-    // <expr>" the initial value is the hole.
-    bool is_var = initial_value->IsUndefined();
-    bool is_const = initial_value->IsTheHole();
+    bool is_var = initial_value->IsUndefined(isolate);
     bool is_function = initial_value->IsSharedFunctionInfo();
-    DCHECK_EQ(1,
-              BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function));
+    DCHECK_EQ(1, BoolToInt(is_var) + BoolToInt(is_function));
 
     Handle<Object> value;
     if (is_function) {
@@ -134,13 +144,14 @@
     bool is_native = DeclareGlobalsNativeFlag::decode(flags);
     bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
     int attr = NONE;
-    if (is_const) attr |= READ_ONLY;
     if (is_function && is_native) attr |= READ_ONLY;
-    if (!is_const && !is_eval) attr |= DONT_DELETE;
+    if (!is_eval) attr |= DONT_DELETE;
 
-    Object* result = DeclareGlobals(isolate, global, name, value,
-                                    static_cast<PropertyAttributes>(attr),
-                                    is_var, is_const, is_function);
+    // ES#sec-globaldeclarationinstantiation 5.d:
+    // If hasRestrictedGlobal is true, throw a SyntaxError exception.
+    Object* result = DeclareGlobals(
+        isolate, global, name, value, static_cast<PropertyAttributes>(attr),
+        is_var, is_function, RedeclarationType::kSyntaxError);
     if (isolate->has_pending_exception()) return result;
   });
 
@@ -150,40 +161,27 @@
 
 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) {
   HandleScope scope(isolate);
-  // args[0] == name
-  // args[1] == language_mode
-  // args[2] == value (optional)
-
-  // Determine if we need to assign to the variable if it already
-  // exists (based on the number of arguments).
-  RUNTIME_ASSERT(args.length() == 3);
-
+  DCHECK_EQ(3, args.length());
   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
 
   Handle<JSGlobalObject> global(isolate->context()->global_object());
-  Handle<Object> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, Object::SetProperty(global, name, value, language_mode));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(
+      isolate, Object::SetProperty(global, name, value, language_mode));
 }
 
 
 RUNTIME_FUNCTION(Runtime_InitializeConstGlobal) {
   HandleScope handle_scope(isolate);
-  // All constants are declared with an initial value. The name
-  // of the constant is the first argument and the initial value
-  // is the second.
-  RUNTIME_ASSERT(args.length() == 2);
+  DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
 
   Handle<JSGlobalObject> global = isolate->global_object();
 
   // Lookup the property as own on the global object.
-  LookupIterator it(global, name, global,
-                    LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
+  LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR);
   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
   DCHECK(maybe.IsJust());
   PropertyAttributes old_attributes = maybe.FromJust();
@@ -209,79 +207,69 @@
   return *value;
 }
 
-
 namespace {
 
-Object* DeclareLookupSlot(Isolate* isolate, Handle<String> name,
-                          Handle<Object> initial_value,
-                          PropertyAttributes attr) {
-  // Declarations are always made in a function, eval or script context, or
-  // a declaration block scope.
-  // In the case of eval code, the context passed is the context of the caller,
-  // which may be some nested context and not the declaration context.
+Object* DeclareEvalHelper(Isolate* isolate, Handle<String> name,
+                          Handle<Object> value) {
+  // Declarations are always made in a function, native, or script context, or
+  // a declaration block scope. Since this is called from eval, the context
+  // passed is the context of the caller, which may be some nested context and
+  // not the declaration context.
   Handle<Context> context_arg(isolate->context(), isolate);
   Handle<Context> context(context_arg->declaration_context(), isolate);
 
-  // TODO(verwaest): Unify the encoding indicating "var" with DeclareGlobals.
-  bool is_var = *initial_value == NULL;
-  bool is_const = initial_value->IsTheHole();
-  bool is_function = initial_value->IsJSFunction();
-  DCHECK_EQ(1,
-            BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function));
+  DCHECK(context->IsFunctionContext() || context->IsNativeContext() ||
+         context->IsScriptContext() ||
+         (context->IsBlockContext() && context->has_extension()));
+
+  bool is_function = value->IsJSFunction();
+  bool is_var = !is_function;
+  DCHECK(!is_var || value->IsUndefined(isolate));
 
   int index;
   PropertyAttributes attributes;
   BindingFlags binding_flags;
 
-  if ((attr & EVAL_DECLARED) != 0) {
-    // Check for a conflict with a lexically scoped variable
-    context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes,
-                        &binding_flags);
-    if (attributes != ABSENT &&
-        (binding_flags == MUTABLE_CHECK_INITIALIZED ||
-         binding_flags == IMMUTABLE_CHECK_INITIALIZED ||
-         binding_flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY)) {
-      return ThrowRedeclarationError(isolate, name);
-    }
-    attr = static_cast<PropertyAttributes>(attr & ~EVAL_DECLARED);
+  // Check for a conflict with a lexically scoped variable
+  context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, &binding_flags);
+  if (attributes != ABSENT && binding_flags == BINDING_CHECK_INITIALIZED) {
+    // ES#sec-evaldeclarationinstantiation 5.a.i.1:
+    // If varEnvRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
+    // exception.
+    // ES#sec-evaldeclarationinstantiation 5.d.ii.2.a.i:
+    // Throw a SyntaxError exception.
+    return ThrowRedeclarationError(isolate, name,
+                                   RedeclarationType::kSyntaxError);
   }
 
   Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index,
                                           &attributes, &binding_flags);
-  if (holder.is_null()) {
-    // In case of JSProxy, an exception might have been thrown.
-    if (isolate->has_pending_exception()) return isolate->heap()->exception();
-  }
+  DCHECK(!isolate->has_pending_exception());
 
   Handle<JSObject> object;
-  Handle<Object> value =
-      is_function ? initial_value
-                  : Handle<Object>::cast(isolate->factory()->undefined_value());
 
-  // TODO(verwaest): This case should probably not be covered by this function,
-  // but by DeclareGlobals instead.
   if (attributes != ABSENT && holder->IsJSGlobalObject()) {
+    // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b:
+    // If fnDefinable is false, throw a TypeError exception.
     return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name,
-                          value, attr, is_var, is_const, is_function);
+                          value, NONE, is_var, is_function,
+                          RedeclarationType::kTypeError);
   }
   if (context_arg->extension()->IsJSGlobalObject()) {
     Handle<JSGlobalObject> global(
         JSGlobalObject::cast(context_arg->extension()), isolate);
-    return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const,
-                          is_function);
+    return DeclareGlobals(isolate, global, name, value, NONE, is_var,
+                          is_function, RedeclarationType::kTypeError);
   } else if (context->IsScriptContext()) {
     DCHECK(context->global_object()->IsJSGlobalObject());
     Handle<JSGlobalObject> global(
         JSGlobalObject::cast(context->global_object()), isolate);
-    return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const,
-                          is_function);
+    return DeclareGlobals(isolate, global, name, value, NONE, is_var,
+                          is_function, RedeclarationType::kTypeError);
   }
 
   if (attributes != ABSENT) {
-    // The name was declared before; check for conflicting re-declarations.
-    if (is_const || (attributes & READ_ONLY) != 0) {
-      return ThrowRedeclarationError(isolate, name);
-    }
+    DCHECK_EQ(NONE, attributes);
 
     // Skip var re-declarations.
     if (is_var) return isolate->heap()->undefined_value();
@@ -289,7 +277,7 @@
     DCHECK(is_function);
     if (index != Context::kNotFound) {
       DCHECK(holder.is_identical_to(context));
-      context->set(index, *initial_value);
+      context->set(index, *value);
       return isolate->heap()->undefined_value();
     }
 
@@ -318,107 +306,29 @@
   }
 
   RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
-                                           object, name, value, attr));
+                                           object, name, value, NONE));
 
   return isolate->heap()->undefined_value();
 }
 
 }  // namespace
 
-
-RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) {
+RUNTIME_FUNCTION(Runtime_DeclareEvalFunction) {
   HandleScope scope(isolate);
-  DCHECK_EQ(3, args.length());
+  DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
-  CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 1);
-  CONVERT_ARG_HANDLE_CHECKED(Smi, property_attributes, 2);
-
-  PropertyAttributes attributes =
-      static_cast<PropertyAttributes>(property_attributes->value());
-  return DeclareLookupSlot(isolate, name, initial_value, attributes);
+  CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
+  return DeclareEvalHelper(isolate, name, value);
 }
 
-
-RUNTIME_FUNCTION(Runtime_InitializeLegacyConstLookupSlot) {
+RUNTIME_FUNCTION(Runtime_DeclareEvalVar) {
   HandleScope scope(isolate);
-  DCHECK(args.length() == 3);
-
-  CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
-  DCHECK(!value->IsTheHole());
-  // Initializations are always done in a function or native context.
-  CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 1);
-  Handle<Context> context(context_arg->declaration_context());
-  CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
-
-  int index;
-  PropertyAttributes attributes;
-  ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
-  BindingFlags binding_flags;
-  Handle<Object> holder =
-      context->Lookup(name, flags, &index, &attributes, &binding_flags);
-  if (holder.is_null()) {
-    // In case of JSProxy, an exception might have been thrown.
-    if (isolate->has_pending_exception()) return isolate->heap()->exception();
-  }
-
-  if (index != Context::kNotFound) {
-    DCHECK(holder->IsContext());
-    // Property was found in a context.  Perform the assignment if the constant
-    // was uninitialized.
-    Handle<Context> context = Handle<Context>::cast(holder);
-    DCHECK((attributes & READ_ONLY) != 0);
-    if (context->get(index)->IsTheHole()) context->set(index, *value);
-    return *value;
-  }
-
-  PropertyAttributes attr =
-      static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
-
-  // Strict mode handling not needed (legacy const is disallowed in strict
-  // mode).
-
-  // The declared const was configurable, and may have been deleted in the
-  // meanwhile. If so, re-introduce the variable in the context extension.
-  if (attributes == ABSENT) {
-    Handle<Context> declaration_context(context_arg->declaration_context());
-    if (declaration_context->IsScriptContext()) {
-      holder = handle(declaration_context->global_object(), isolate);
-    } else {
-      holder = handle(declaration_context->extension_object(), isolate);
-      DCHECK(!holder.is_null());
-    }
-    CHECK(holder->IsJSObject());
-  } else {
-    // For JSContextExtensionObjects, the initializer can be run multiple times
-    // if in a for loop: for (var i = 0; i < 2; i++) { const x = i; }. Only the
-    // first assignment should go through. For JSGlobalObjects, additionally any
-    // code can run in between that modifies the declared property.
-    DCHECK(holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject());
-
-    LookupIterator it(holder, name, Handle<JSReceiver>::cast(holder),
-                      LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
-    Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
-    if (!maybe.IsJust()) return isolate->heap()->exception();
-    PropertyAttributes old_attributes = maybe.FromJust();
-
-    // Ignore if we can't reconfigure the value.
-    if ((old_attributes & DONT_DELETE) != 0) {
-      if ((old_attributes & READ_ONLY) != 0 ||
-          it.state() == LookupIterator::ACCESSOR) {
-        return *value;
-      }
-      attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
-    }
-  }
-
-  RETURN_FAILURE_ON_EXCEPTION(
-      isolate, JSObject::SetOwnPropertyIgnoreAttributes(
-                   Handle<JSObject>::cast(holder), name, value, attr));
-
-  return *value;
+  DCHECK_EQ(1, args.length());
+  CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
+  return DeclareEvalHelper(isolate, name,
+                           isolate->factory()->undefined_value());
 }
 
-
 namespace {
 
 // Find the arguments of the JavaScript function invocation that called
@@ -663,12 +573,6 @@
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
   Object** parameters = reinterpret_cast<Object**>(args[1]);
   CONVERT_SMI_ARG_CHECKED(argument_count, 2);
-#ifdef DEBUG
-  // This runtime function does not materialize the correct arguments when the
-  // caller has been inlined, better make sure we are not hitting that case.
-  JavaScriptFrameIterator it(isolate);
-  DCHECK(!it.frame()->HasInlinedFrames());
-#endif  // DEBUG
   ParameterArguments argument_getter(parameters);
   return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
 }
@@ -705,17 +609,27 @@
     ScriptContextTable::LookupResult lookup;
     if (ScriptContextTable::Lookup(script_context, name, &lookup)) {
       if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) {
-        return ThrowRedeclarationError(isolate, name);
+        // ES#sec-globaldeclarationinstantiation 5.b:
+        // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
+        // exception.
+        return ThrowRedeclarationError(isolate, name,
+                                       RedeclarationType::kSyntaxError);
       }
     }
 
     if (IsLexicalVariableMode(mode)) {
       LookupIterator it(global_object, name, global_object,
-                        LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
+                        LookupIterator::OWN_SKIP_INTERCEPTOR);
       Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
       if (!maybe.IsJust()) return isolate->heap()->exception();
       if ((maybe.FromJust() & DONT_DELETE) != 0) {
-        return ThrowRedeclarationError(isolate, name);
+        // ES#sec-globaldeclarationinstantiation 5.a:
+        // If envRec.HasVarDeclaration(name) is true, throw a SyntaxError
+        // exception.
+        // ES#sec-globaldeclarationinstantiation 5.d:
+        // If hasRestrictedGlobal is true, throw a SyntaxError exception.
+        return ThrowRedeclarationError(isolate, name,
+                                       RedeclarationType::kSyntaxError);
       }
 
       JSGlobalObject::InvalidatePropertyCell(global_object, name);
@@ -868,22 +782,21 @@
     Handle<JSModule> module(context->module());
 
     for (int j = 0; j < description->length(); ++j) {
-      Handle<String> name(description->name(j));
+      Handle<String> name(description->name(j), isolate);
       VariableMode mode = description->mode(j);
       int index = description->index(j);
       switch (mode) {
         case VAR:
         case LET:
         case CONST:
-        case CONST_LEGACY:
-        case IMPORT: {
+        case CONST_LEGACY: {
           PropertyAttributes attr =
               IsImmutableVariableMode(mode) ? FROZEN : SEALED;
           Handle<AccessorInfo> info =
               Accessors::MakeModuleExport(name, index, attr);
           Handle<Object> result =
               JSObject::SetAccessor(module, info).ToHandleChecked();
-          DCHECK(!result->IsUndefined());
+          DCHECK(!result->IsUndefined(isolate));
           USE(result);
           break;
         }
@@ -961,24 +874,15 @@
     Handle<Object> value = handle(Context::cast(*holder)->get(index), isolate);
     // Check for uninitialized bindings.
     switch (flags) {
-      case MUTABLE_CHECK_INITIALIZED:
-      case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
-        if (value->IsTheHole()) {
+      case BINDING_CHECK_INITIALIZED:
+        if (value->IsTheHole(isolate)) {
           THROW_NEW_ERROR(isolate,
                           NewReferenceError(MessageTemplate::kNotDefined, name),
                           Object);
         }
       // FALLTHROUGH
-      case IMMUTABLE_CHECK_INITIALIZED:
-        if (value->IsTheHole()) {
-          DCHECK(attributes & READ_ONLY);
-          value = isolate->factory()->undefined_value();
-        }
-      // FALLTHROUGH
-      case MUTABLE_IS_INITIALIZED:
-      case IMMUTABLE_IS_INITIALIZED:
-      case IMMUTABLE_IS_INITIALIZED_HARMONY:
-        DCHECK(!value->IsTheHole());
+      case BINDING_IS_INITIALIZED:
+        DCHECK(!value->IsTheHole(isolate));
         if (receiver_return) *receiver_return = receiver;
         return value;
       case MISSING_BINDING:
@@ -1024,10 +928,8 @@
   HandleScope scope(isolate);
   DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
-  Handle<Object> value;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, value, LoadLookupSlot(name, Object::THROW_ON_ERROR));
-  return *value;
+  RETURN_RESULT_OR_FAILURE(isolate,
+                           LoadLookupSlot(name, Object::THROW_ON_ERROR));
 }
 
 
@@ -1035,10 +937,7 @@
   HandleScope scope(isolate);
   DCHECK_EQ(1, args.length());
   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
-  Handle<Object> value;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, value, LoadLookupSlot(name, Object::DONT_THROW));
-  return *value;
+  RETURN_RESULT_OR_FAILURE(isolate, LoadLookupSlot(name, Object::DONT_THROW));
 }
 
 
@@ -1075,8 +974,7 @@
 
   // The property was found in a context slot.
   if (index != Context::kNotFound) {
-    if ((flags == MUTABLE_CHECK_INITIALIZED ||
-         flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY) &&
+    if (flags == BINDING_CHECK_INITIALIZED &&
         Handle<Context>::cast(holder)->is_the_hole(index)) {
       THROW_NEW_ERROR(isolate,
                       NewReferenceError(MessageTemplate::kNotDefined, name),
@@ -1123,9 +1021,7 @@
   DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
-                                     StoreLookupSlot(name, value, SLOPPY));
-  return *value;
+  RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, SLOPPY));
 }
 
 
@@ -1134,9 +1030,7 @@
   DCHECK_EQ(2, args.length());
   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
-                                     StoreLookupSlot(name, value, STRICT));
-  return *value;
+  RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT));
 }
 
 }  // namespace internal
diff --git a/src/runtime/runtime-simd.cc b/src/runtime/runtime-simd.cc
index 9e56142..70bc950 100644
--- a/src/runtime/runtime-simd.cc
+++ b/src/runtime/runtime-simd.cc
@@ -26,6 +26,7 @@
   // A float can't represent 2^31 - 1 or 2^32 - 1 exactly, so promote the limits
   // to double. Otherwise, the limit is truncated and numbers like 2^31 or 2^32
   // get through, causing any static_cast to be undefined.
+  from = trunc(from);
   return from >= static_cast<double>(std::numeric_limits<T>::min()) &&
          from <= static_cast<double>(std::numeric_limits<T>::max());
 }
@@ -168,9 +169,19 @@
 
 // Utility macros.
 
-#define CONVERT_SIMD_LANE_ARG_CHECKED(name, index, lanes) \
-  CONVERT_INT32_ARG_CHECKED(name, index);                 \
-  RUNTIME_ASSERT(name >= 0 && name < lanes);
+// TODO(gdeepti): Fix to use ToNumber conversion once polyfill is updated.
+#define CONVERT_SIMD_LANE_ARG_CHECKED(name, index, lanes)            \
+  Handle<Object> name_object = args.at<Object>(index);               \
+  if (!name_object->IsNumber()) {                                    \
+    THROW_NEW_ERROR_RETURN_FAILURE(                                  \
+        isolate, NewTypeError(MessageTemplate::kInvalidSimdIndex));  \
+  }                                                                  \
+  double number = name_object->Number();                             \
+  if (number < 0 || number >= lanes || !IsInt32Double(number)) {     \
+    THROW_NEW_ERROR_RETURN_FAILURE(                                  \
+        isolate, NewRangeError(MessageTemplate::kInvalidSimdIndex)); \
+  }                                                                  \
+  uint32_t name = static_cast<uint32_t>(number);
 
 #define CONVERT_SIMD_ARG_HANDLE_THROW(Type, name, index)                \
   Handle<Type> name;                                                    \
@@ -217,8 +228,10 @@
 
 // Common functions.
 
-#define GET_NUMERIC_ARG(lane_type, name, index) \
-  CONVERT_NUMBER_ARG_HANDLE_CHECKED(a, index);  \
+#define GET_NUMERIC_ARG(lane_type, name, index)              \
+  Handle<Object> a;                                          \
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(                        \
+      isolate, a, Object::ToNumber(args.at<Object>(index))); \
   name = ConvertNumber<lane_type>(a->Number());
 
 #define GET_BOOLEAN_ARG(lane_type, name, index) \
@@ -395,10 +408,14 @@
   FUNCTION(Uint16x8, uint16_t, 16, 8) \
   FUNCTION(Uint8x16, uint8_t, 8, 16)
 
-#define CONVERT_SHIFT_ARG_CHECKED(name, index)         \
-  RUNTIME_ASSERT(args[index]->IsNumber());             \
-  int32_t signed_shift = 0;                            \
-  RUNTIME_ASSERT(args[index]->ToInt32(&signed_shift)); \
+#define CONVERT_SHIFT_ARG_CHECKED(name, index)                          \
+  Handle<Object> name_object = args.at<Object>(index);                  \
+  if (!name_object->IsNumber()) {                                       \
+    THROW_NEW_ERROR_RETURN_FAILURE(                                     \
+        isolate, NewTypeError(MessageTemplate::kInvalidSimdOperation)); \
+  }                                                                     \
+  int32_t signed_shift = 0;                                             \
+  args[index]->ToInt32(&signed_shift);                                  \
   uint32_t name = bit_cast<uint32_t>(signed_shift);
 
 #define SIMD_LSL_FUNCTION(type, lane_type, lane_bits, lane_count) \
@@ -409,31 +426,29 @@
     CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 0);                    \
     CONVERT_SHIFT_ARG_CHECKED(shift, 1);                          \
     lane_type lanes[kLaneCount] = {0};                            \
-    if (shift < lane_bits) {                                      \
-      for (int i = 0; i < kLaneCount; i++) {                      \
-        lanes[i] = a->get_lane(i) << shift;                       \
-      }                                                           \
+    shift &= lane_bits - 1;                                       \
+    for (int i = 0; i < kLaneCount; i++) {                        \
+      lanes[i] = a->get_lane(i) << shift;                         \
     }                                                             \
     Handle<type> result = isolate->factory()->New##type(lanes);   \
     return *result;                                               \
   }
 
-#define SIMD_LSR_FUNCTION(type, lane_type, lane_bits, lane_count) \
-  RUNTIME_FUNCTION(Runtime_##type##ShiftRightByScalar) {          \
-    static const int kLaneCount = lane_count;                     \
-    HandleScope scope(isolate);                                   \
-    DCHECK(args.length() == 2);                                   \
-    CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 0);                    \
-    CONVERT_SHIFT_ARG_CHECKED(shift, 1);                          \
-    lane_type lanes[kLaneCount] = {0};                            \
-    if (shift < lane_bits) {                                      \
-      for (int i = 0; i < kLaneCount; i++) {                      \
-        lanes[i] = static_cast<lane_type>(                        \
-            bit_cast<lane_type>(a->get_lane(i)) >> shift);        \
-      }                                                           \
-    }                                                             \
-    Handle<type> result = isolate->factory()->New##type(lanes);   \
-    return *result;                                               \
+#define SIMD_LSR_FUNCTION(type, lane_type, lane_bits, lane_count)              \
+  RUNTIME_FUNCTION(Runtime_##type##ShiftRightByScalar) {                       \
+    static const int kLaneCount = lane_count;                                  \
+    HandleScope scope(isolate);                                                \
+    DCHECK(args.length() == 2);                                                \
+    CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 0);                                 \
+    CONVERT_SHIFT_ARG_CHECKED(shift, 1);                                       \
+    lane_type lanes[kLaneCount] = {0};                                         \
+    shift &= lane_bits - 1;                                                    \
+    for (int i = 0; i < kLaneCount; i++) {                                     \
+      lanes[i] = static_cast<lane_type>(bit_cast<lane_type>(a->get_lane(i)) >> \
+                                        shift);                                \
+    }                                                                          \
+    Handle<type> result = isolate->factory()->New##type(lanes);                \
+    return *result;                                                            \
   }
 
 #define SIMD_ASR_FUNCTION(type, lane_type, lane_bits, lane_count)      \
@@ -443,7 +458,7 @@
     DCHECK(args.length() == 2);                                        \
     CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 0);                         \
     CONVERT_SHIFT_ARG_CHECKED(shift, 1);                               \
-    if (shift >= lane_bits) shift = lane_bits - 1;                     \
+    shift &= lane_bits - 1;                                            \
     lane_type lanes[kLaneCount];                                       \
     for (int i = 0; i < kLaneCount; i++) {                             \
       int64_t shifted = static_cast<int64_t>(a->get_lane(i)) >> shift; \
@@ -785,8 +800,10 @@
     lane_type lanes[kLaneCount];                                               \
     for (int i = 0; i < kLaneCount; i++) {                                     \
       from_ctype a_value = a->get_lane(i);                                     \
-      if (a_value != a_value) a_value = 0;                                     \
-      RUNTIME_ASSERT(CanCast<lane_type>(a_value));                             \
+      if (a_value != a_value || !CanCast<lane_type>(a_value)) {                \
+        THROW_NEW_ERROR_RETURN_FAILURE(                                        \
+            isolate, NewRangeError(MessageTemplate::kInvalidSimdLaneValue));   \
+      }                                                                        \
       lanes[i] = static_cast<lane_type>(a_value);                              \
     }                                                                          \
     Handle<type> result = isolate->factory()->New##type(lanes);                \
@@ -863,6 +880,17 @@
   FUNCTION(Int32x4, int32_t, 4)           \
   FUNCTION(Uint32x4, uint32_t, 4)
 
+#define SIMD_COERCE_INDEX(name, i)                                            \
+  Handle<Object> length_object, number_object;                                \
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(                                         \
+      isolate, length_object, Object::ToLength(isolate, args.at<Object>(i))); \
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_object,                  \
+                                     Object::ToNumber(args.at<Object>(i)));   \
+  if (number_object->Number() != length_object->Number()) {                   \
+    THROW_NEW_ERROR_RETURN_FAILURE(                                           \
+        isolate, NewTypeError(MessageTemplate::kInvalidSimdIndex));           \
+  }                                                                           \
+  int32_t name = number_object->Number();
 
 // Common Load and Store Functions
 
@@ -870,11 +898,14 @@
   static const int kLaneCount = lane_count;                            \
   DCHECK(args.length() == 2);                                          \
   CONVERT_SIMD_ARG_HANDLE_THROW(JSTypedArray, tarray, 0);              \
-  CONVERT_INT32_ARG_CHECKED(index, 1)                                  \
+  SIMD_COERCE_INDEX(index, 1);                                         \
   size_t bpe = tarray->element_size();                                 \
   uint32_t bytes = count * sizeof(lane_type);                          \
   size_t byte_length = NumberToSize(isolate, tarray->byte_length());   \
-  RUNTIME_ASSERT(index >= 0 && index * bpe + bytes <= byte_length);    \
+  if (index < 0 || index * bpe + bytes > byte_length) {                \
+    THROW_NEW_ERROR_RETURN_FAILURE(                                    \
+        isolate, NewRangeError(MessageTemplate::kInvalidSimdIndex));   \
+  }                                                                    \
   size_t tarray_offset = NumberToSize(isolate, tarray->byte_offset()); \
   uint8_t* tarray_base =                                               \
       static_cast<uint8_t*>(tarray->GetBuffer()->backing_store()) +    \
@@ -883,17 +914,19 @@
   memcpy(lanes, tarray_base + index * bpe, bytes);                     \
   Handle<type> result = isolate->factory()->New##type(lanes);
 
-
 #define SIMD_STORE(type, lane_type, lane_count, count, a)              \
   static const int kLaneCount = lane_count;                            \
   DCHECK(args.length() == 3);                                          \
   CONVERT_SIMD_ARG_HANDLE_THROW(JSTypedArray, tarray, 0);              \
   CONVERT_SIMD_ARG_HANDLE_THROW(type, a, 2);                           \
-  CONVERT_INT32_ARG_CHECKED(index, 1)                                  \
+  SIMD_COERCE_INDEX(index, 1);                                         \
   size_t bpe = tarray->element_size();                                 \
   uint32_t bytes = count * sizeof(lane_type);                          \
   size_t byte_length = NumberToSize(isolate, tarray->byte_length());   \
-  RUNTIME_ASSERT(index >= 0 && index * bpe + bytes <= byte_length);    \
+  if (index < 0 || byte_length < index * bpe + bytes) {                \
+    THROW_NEW_ERROR_RETURN_FAILURE(                                    \
+        isolate, NewRangeError(MessageTemplate::kInvalidSimdIndex));   \
+  }                                                                    \
   size_t tarray_offset = NumberToSize(isolate, tarray->byte_offset()); \
   uint8_t* tarray_base =                                               \
       static_cast<uint8_t*>(tarray->GetBuffer()->backing_store()) +    \
@@ -904,7 +937,6 @@
   }                                                                    \
   memcpy(tarray_base + index * bpe, lanes, bytes);
 
-
 #define SIMD_LOAD_FUNCTION(type, lane_type, lane_count)         \
   RUNTIME_FUNCTION(Runtime_##type##Load) {                      \
     HandleScope scope(isolate);                                 \
diff --git a/src/runtime/runtime-strings.cc b/src/runtime/runtime-strings.cc
index 6786fa9..c1f14ad 100644
--- a/src/runtime/runtime-strings.cc
+++ b/src/runtime/runtime-strings.cc
@@ -5,10 +5,7 @@
 #include "src/runtime/runtime-utils.h"
 
 #include "src/arguments.h"
-#include "src/conversions-inl.h"
-#include "src/isolate-inl.h"
 #include "src/regexp/jsregexp-inl.h"
-#include "src/regexp/jsregexp.h"
 #include "src/string-builder.h"
 #include "src/string-search.h"
 
@@ -143,7 +140,7 @@
   uint32_t start_index = 0;
   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
 
-  RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
+  CHECK(start_index <= static_cast<uint32_t>(sub->length()));
   int position = StringMatch(isolate, sub, pat, start_index);
   return Smi::FromInt(position);
 }
@@ -316,16 +313,14 @@
   CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
   CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
   isolate->counters()->string_add_runtime()->Increment();
-  Handle<String> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, isolate->factory()->NewConsString(str1, str2));
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate,
+                           isolate->factory()->NewConsString(str1, str2));
 }
 
 
 RUNTIME_FUNCTION(Runtime_InternalizeString) {
   HandleScope handles(isolate);
-  RUNTIME_ASSERT(args.length() == 1);
+  DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
   return *isolate->factory()->InternalizeString(string);
 }
@@ -339,7 +334,7 @@
   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
   CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
 
-  RUNTIME_ASSERT(regexp_info->HasFastObjectElements());
+  CHECK(regexp_info->HasFastObjectElements());
 
   RegExpImpl::GlobalCache global_cache(regexp, subject, isolate);
   if (global_cache.HasException()) return isolate->heap()->exception();
@@ -436,15 +431,14 @@
   CONVERT_ARG_HANDLE_CHECKED(String, special, 2);
 
   size_t actual_array_length = 0;
-  RUNTIME_ASSERT(
-      TryNumberToSize(isolate, array->length(), &actual_array_length));
-  RUNTIME_ASSERT(array_length >= 0);
-  RUNTIME_ASSERT(static_cast<size_t>(array_length) <= actual_array_length);
+  CHECK(TryNumberToSize(isolate, array->length(), &actual_array_length));
+  CHECK(array_length >= 0);
+  CHECK(static_cast<size_t>(array_length) <= actual_array_length);
 
   // This assumption is used by the slice encoding in one or two smis.
   DCHECK(Smi::kMaxValue >= String::kMaxLength);
 
-  RUNTIME_ASSERT(array->HasFastElements());
+  CHECK(array->HasFastElements());
   JSObject::EnsureCanContainHeapObjectElements(array);
 
   int special_length = special->length();
@@ -505,8 +499,8 @@
     THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError());
   }
   CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
-  RUNTIME_ASSERT(array->HasFastObjectElements());
-  RUNTIME_ASSERT(array_length >= 0);
+  CHECK(array->HasFastObjectElements());
+  CHECK(array_length >= 0);
 
   Handle<FixedArray> fixed_array(FixedArray::cast(array->elements()));
   if (fixed_array->length() < array_length) {
@@ -517,12 +511,12 @@
     return isolate->heap()->empty_string();
   } else if (array_length == 1) {
     Object* first = fixed_array->get(0);
-    RUNTIME_ASSERT(first->IsString());
+    CHECK(first->IsString());
     return first;
   }
 
   int separator_length = separator->length();
-  RUNTIME_ASSERT(separator_length > 0);
+  CHECK(separator_length > 0);
   int max_nof_separators =
       (String::kMaxLength + separator_length - 1) / separator_length;
   if (max_nof_separators < (array_length - 1)) {
@@ -531,7 +525,7 @@
   int length = (array_length - 1) * separator_length;
   for (int i = 0; i < array_length; i++) {
     Object* element_obj = fixed_array->get(i);
-    RUNTIME_ASSERT(element_obj->IsString());
+    CHECK(element_obj->IsString());
     String* element = String::cast(element_obj);
     int increment = element->length();
     if (increment > String::kMaxLength - length) {
@@ -553,7 +547,7 @@
   uc16* end = sink + length;
 #endif
 
-  RUNTIME_ASSERT(fixed_array->get(0)->IsString());
+  CHECK(fixed_array->get(0)->IsString());
   String* first = String::cast(fixed_array->get(0));
   String* separator_raw = *separator;
 
@@ -566,7 +560,7 @@
     String::WriteToFlat(separator_raw, sink, 0, separator_length);
     sink += separator_length;
 
-    RUNTIME_ASSERT(fixed_array->get(i)->IsString());
+    CHECK(fixed_array->get(i)->IsString());
     String* element = String::cast(fixed_array->get(i));
     int element_length = element->length();
     DCHECK(sink + element_length <= end);
@@ -645,18 +639,18 @@
   CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
   // elements_array is fast-mode JSarray of alternating positions
   // (increasing order) and strings.
-  RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements());
+  CHECK(elements_array->HasFastSmiOrObjectElements());
   // array_length is length of original array (used to add separators);
   // separator is string to put between elements. Assumed to be non-empty.
-  RUNTIME_ASSERT(array_length > 0);
+  CHECK(array_length > 0);
 
   // Find total length of join result.
   int string_length = 0;
   bool is_one_byte = separator->IsOneByteRepresentation();
   bool overflow = false;
   CONVERT_NUMBER_CHECKED(int, elements_length, Int32, elements_array->length());
-  RUNTIME_ASSERT(elements_length <= elements_array->elements()->length());
-  RUNTIME_ASSERT((elements_length & 1) == 0);  // Even length.
+  CHECK(elements_length <= elements_array->elements()->length());
+  CHECK((elements_length & 1) == 0);  // Even length.
   FixedArray* elements = FixedArray::cast(elements_array->elements());
   {
     DisallowHeapAllocation no_gc;
@@ -1062,7 +1056,7 @@
   }
 
   Object* answer = ConvertCaseHelper(isolate, *s, *result, length, mapping);
-  if (answer->IsException() || answer->IsString()) return answer;
+  if (answer->IsException(isolate) || answer->IsString()) return answer;
 
   DCHECK(answer->IsSmi());
   length = Smi::cast(answer)->value();
@@ -1080,7 +1074,7 @@
 
 RUNTIME_FUNCTION(Runtime_StringToLowerCase) {
   HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
+  DCHECK_EQ(args.length(), 1);
   CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
   return ConvertCase(s, isolate, isolate->runtime_state()->to_lower_mapping());
 }
@@ -1088,72 +1082,11 @@
 
 RUNTIME_FUNCTION(Runtime_StringToUpperCase) {
   HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
+  DCHECK_EQ(args.length(), 1);
   CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
   return ConvertCase(s, isolate, isolate->runtime_state()->to_upper_mapping());
 }
 
-
-RUNTIME_FUNCTION(Runtime_StringTrim) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 3);
-
-  CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
-  CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
-  CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
-
-  string = String::Flatten(string);
-  int length = string->length();
-
-  int left = 0;
-  UnicodeCache* unicode_cache = isolate->unicode_cache();
-  if (trimLeft) {
-    while (left < length &&
-           unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(left))) {
-      left++;
-    }
-  }
-
-  int right = length;
-  if (trimRight) {
-    while (
-        right > left &&
-        unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) {
-      right--;
-    }
-  }
-
-  return *isolate->factory()->NewSubString(string, left, right);
-}
-
-
-RUNTIME_FUNCTION(Runtime_TruncateString) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 2);
-  CONVERT_ARG_HANDLE_CHECKED(SeqString, string, 0);
-  CONVERT_INT32_ARG_CHECKED(new_length, 1);
-  RUNTIME_ASSERT(new_length >= 0);
-  return *SeqString::Truncate(string, new_length);
-}
-
-
-RUNTIME_FUNCTION(Runtime_NewString) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 2);
-  CONVERT_INT32_ARG_CHECKED(length, 0);
-  CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1);
-  if (length == 0) return isolate->heap()->empty_string();
-  Handle<String> result;
-  if (is_one_byte) {
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-        isolate, result, isolate->factory()->NewRawOneByteString(length));
-  } else {
-    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-        isolate, result, isolate->factory()->NewRawTwoByteString(length));
-  }
-  return *result;
-}
-
 RUNTIME_FUNCTION(Runtime_StringLessThan) {
   HandleScope handle_scope(isolate);
   DCHECK_EQ(2, args.length());
@@ -1261,59 +1194,14 @@
   return isolate->heap()->empty_string();
 }
 
-
-RUNTIME_FUNCTION(Runtime_StringCharAt) {
+RUNTIME_FUNCTION(Runtime_ExternalStringGetChar) {
   SealHandleScope shs(isolate);
-  DCHECK(args.length() == 2);
-  if (!args[0]->IsString()) return Smi::FromInt(0);
-  if (!args[1]->IsNumber()) return Smi::FromInt(0);
-  if (std::isinf(args.number_at(1))) return isolate->heap()->empty_string();
-  Object* code = __RT_impl_Runtime_StringCharCodeAtRT(args, isolate);
-  if (code->IsNaN()) return isolate->heap()->empty_string();
-  return __RT_impl_Runtime_StringCharFromCode(Arguments(1, &code), isolate);
-}
-
-
-RUNTIME_FUNCTION(Runtime_OneByteSeqStringGetChar) {
-  SealHandleScope shs(isolate);
-  DCHECK(args.length() == 2);
-  CONVERT_ARG_CHECKED(SeqOneByteString, string, 0);
+  DCHECK_EQ(2, args.length());
+  CONVERT_ARG_CHECKED(ExternalString, string, 0);
   CONVERT_INT32_ARG_CHECKED(index, 1);
-  return Smi::FromInt(string->SeqOneByteStringGet(index));
+  return Smi::FromInt(string->Get(index));
 }
 
-
-RUNTIME_FUNCTION(Runtime_OneByteSeqStringSetChar) {
-  SealHandleScope shs(isolate);
-  DCHECK(args.length() == 3);
-  CONVERT_INT32_ARG_CHECKED(index, 0);
-  CONVERT_INT32_ARG_CHECKED(value, 1);
-  CONVERT_ARG_CHECKED(SeqOneByteString, string, 2);
-  string->SeqOneByteStringSet(index, value);
-  return string;
-}
-
-
-RUNTIME_FUNCTION(Runtime_TwoByteSeqStringGetChar) {
-  SealHandleScope shs(isolate);
-  DCHECK(args.length() == 2);
-  CONVERT_ARG_CHECKED(SeqTwoByteString, string, 0);
-  CONVERT_INT32_ARG_CHECKED(index, 1);
-  return Smi::FromInt(string->SeqTwoByteStringGet(index));
-}
-
-
-RUNTIME_FUNCTION(Runtime_TwoByteSeqStringSetChar) {
-  SealHandleScope shs(isolate);
-  DCHECK(args.length() == 3);
-  CONVERT_INT32_ARG_CHECKED(index, 0);
-  CONVERT_INT32_ARG_CHECKED(value, 1);
-  CONVERT_ARG_CHECKED(SeqTwoByteString, string, 2);
-  string->SeqTwoByteStringSet(index, value);
-  return string;
-}
-
-
 RUNTIME_FUNCTION(Runtime_StringCharCodeAt) {
   SealHandleScope shs(isolate);
   DCHECK(args.length() == 2);
diff --git a/src/runtime/runtime-symbol.cc b/src/runtime/runtime-symbol.cc
index 234b456..300a643 100644
--- a/src/runtime/runtime-symbol.cc
+++ b/src/runtime/runtime-symbol.cc
@@ -16,7 +16,7 @@
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
-  RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
+  CHECK(name->IsString() || name->IsUndefined(isolate));
   Handle<Symbol> symbol = isolate->factory()->NewSymbol();
   if (name->IsString()) symbol->set_name(*name);
   return *symbol;
@@ -27,7 +27,7 @@
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
-  RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
+  CHECK(name->IsString() || name->IsUndefined(isolate));
   Handle<Symbol> symbol = isolate->factory()->NewPrivateSymbol();
   if (name->IsString()) symbol->set_name(*name);
   return *symbol;
@@ -52,9 +52,7 @@
     builder.AppendString(handle(String::cast(symbol->name()), isolate));
   }
   builder.AppendCharacter(')');
-  Handle<String> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, builder.Finish());
-  return *result;
+  RETURN_RESULT_OR_FAILURE(isolate, builder.Finish());
 }
 
 
diff --git a/src/runtime/runtime-test.cc b/src/runtime/runtime-test.cc
index a0f0566..9ec29b9 100644
--- a/src/runtime/runtime-test.cc
+++ b/src/runtime/runtime-test.cc
@@ -8,15 +8,34 @@
 #include "src/deoptimizer.h"
 #include "src/frames-inl.h"
 #include "src/full-codegen/full-codegen.h"
+#include "src/isolate-inl.h"
 #include "src/snapshot/natives.h"
 
 namespace v8 {
 namespace internal {
 
+RUNTIME_FUNCTION(Runtime_ConstructDouble) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 2);
+  CONVERT_NUMBER_CHECKED(uint32_t, hi, Uint32, args[0]);
+  CONVERT_NUMBER_CHECKED(uint32_t, lo, Uint32, args[1]);
+  uint64_t result = (static_cast<uint64_t>(hi) << 32) | lo;
+  return *isolate->factory()->NewNumber(uint64_to_double(result));
+}
+
 RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
-  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+
+  // This function is used by fuzzers to get coverage in compiler.
+  // Ignore calls on non-function objects to avoid runtime errors.
+  CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
+  // If it is not a JSFunction, just return.
+  if (!function_object->IsJSFunction()) {
+    return isolate->heap()->undefined_value();
+  }
+  Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
+
   if (!function->IsOptimized()) return isolate->heap()->undefined_value();
 
   // TODO(turbofan): Deoptimization is not supported yet.
@@ -84,7 +103,16 @@
 RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
   HandleScope scope(isolate);
   RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
-  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+
+  // This function is used by fuzzers to get coverage for optimizations
+  // in compiler. Ignore calls on non-function objects to avoid runtime errors.
+  CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
+  // If it is not a JSFunction, just return.
+  if (!function_object->IsJSFunction()) {
+    return isolate->heap()->undefined_value();
+  }
+  Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
+
   // The following assertion was lifted from the DCHECK inside
   // JSFunction::MarkForOptimization().
   RUNTIME_ASSERT(function->shared()->allows_lazy_compilation() ||
@@ -135,6 +163,12 @@
   RUNTIME_ASSERT(function->shared()->allows_lazy_compilation() ||
                  !function->shared()->optimization_disabled());
 
+  // If function is interpreted, just return. OSR is not supported.
+  // TODO(4764): Remove this check when OSR is enabled in the interpreter.
+  if (function->shared()->HasBytecodeArray()) {
+    return isolate->heap()->undefined_value();
+  }
+
   // If the function is already optimized, just return.
   if (function->IsOptimized()) return isolate->heap()->undefined_value();
 
@@ -153,7 +187,8 @@
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_CHECKED(JSFunction, function, 0);
-  function->shared()->set_disable_optimization_reason(kOptimizationDisabled);
+  function->shared()->set_disable_optimization_reason(
+      kOptimizationDisabledForTest);
   function->shared()->set_optimization_disabled(true);
   return isolate->heap()->undefined_value();
 }
@@ -232,7 +267,7 @@
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
-  function->shared()->ClearTypeFeedbackInfo();
+  function->ClearTypeFeedbackInfo();
   Code* unoptimized = function->shared()->code();
   if (unoptimized->kind() == Code::FUNCTION) {
     unoptimized->ClearInlineCaches();
@@ -457,6 +492,31 @@
   return isolate->heap()->undefined_value();
 }
 
+RUNTIME_FUNCTION(Runtime_GetExceptionDetails) {
+  HandleScope shs(isolate);
+  DCHECK(args.length() == 1);
+  CONVERT_ARG_HANDLE_CHECKED(JSObject, exception_obj, 0);
+
+  Factory* factory = isolate->factory();
+  Handle<JSMessageObject> message_obj =
+      isolate->CreateMessage(exception_obj, nullptr);
+
+  Handle<JSObject> message = factory->NewJSObject(isolate->object_function());
+
+  Handle<String> key;
+  Handle<Object> value;
+
+  key = factory->NewStringFromAsciiChecked("start_pos");
+  value = handle(Smi::FromInt(message_obj->start_position()), isolate);
+  JSObject::SetProperty(message, key, value, STRICT).Assert();
+
+  key = factory->NewStringFromAsciiChecked("end_pos");
+  value = handle(Smi::FromInt(message_obj->end_position()), isolate);
+  JSObject::SetProperty(message, key, value, STRICT).Assert();
+
+  return *message;
+}
+
 RUNTIME_FUNCTION(Runtime_HaveSameMap) {
   SealHandleScope shs(isolate);
   DCHECK(args.length() == 2);
diff --git a/src/runtime/runtime-typedarray.cc b/src/runtime/runtime-typedarray.cc
index bf0ee9f..37b612d 100644
--- a/src/runtime/runtime-typedarray.cc
+++ b/src/runtime/runtime-typedarray.cc
@@ -28,17 +28,25 @@
   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
   CONVERT_NUMBER_ARG_HANDLE_CHECKED(first, 2);
   CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3);
-  RUNTIME_ASSERT(!source.is_identical_to(target));
+
+  if (source->was_neutered() || target->was_neutered()) {
+    THROW_NEW_ERROR_RETURN_FAILURE(
+        isolate, NewTypeError(MessageTemplate::kDetachedOperation,
+                              isolate->factory()->NewStringFromAsciiChecked(
+                                  "ArrayBuffer.prototype.slice")));
+  }
+
+  CHECK(!source.is_identical_to(target));
   size_t start = 0, target_length = 0;
-  RUNTIME_ASSERT(TryNumberToSize(isolate, *first, &start));
-  RUNTIME_ASSERT(TryNumberToSize(isolate, *new_length, &target_length));
-  RUNTIME_ASSERT(NumberToSize(isolate, target->byte_length()) >= target_length);
+  CHECK(TryNumberToSize(isolate, *first, &start));
+  CHECK(TryNumberToSize(isolate, *new_length, &target_length));
+  CHECK(NumberToSize(isolate, target->byte_length()) >= target_length);
 
   if (target_length == 0) return isolate->heap()->undefined_value();
 
   size_t source_byte_length = NumberToSize(isolate, source->byte_length());
-  RUNTIME_ASSERT(start <= source_byte_length);
-  RUNTIME_ASSERT(source_byte_length - start >= target_length);
+  CHECK(start <= source_byte_length);
+  CHECK(source_byte_length - start >= target_length);
   uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store());
   uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store());
   CopyBytes(target_data, source_data + start, target_length);
@@ -55,7 +63,7 @@
     return isolate->heap()->undefined_value();
   }
   // Shared array buffers should never be neutered.
-  RUNTIME_ASSERT(!array_buffer->is_shared());
+  CHECK(!array_buffer->is_shared());
   DCHECK(!array_buffer->is_external());
   void* backing_store = array_buffer->backing_store();
   size_t byte_length = NumberToSize(isolate, array_buffer->byte_length());
@@ -97,32 +105,32 @@
   CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_length_object, 4);
   CONVERT_BOOLEAN_ARG_CHECKED(initialize, 5);
 
-  RUNTIME_ASSERT(arrayId >= Runtime::ARRAY_ID_FIRST &&
-                 arrayId <= Runtime::ARRAY_ID_LAST);
+  CHECK(arrayId >= Runtime::ARRAY_ID_FIRST &&
+        arrayId <= Runtime::ARRAY_ID_LAST);
 
   ExternalArrayType array_type = kExternalInt8Array;  // Bogus initialization.
   size_t element_size = 1;                            // Bogus initialization.
   ElementsKind fixed_elements_kind = INT8_ELEMENTS;  // Bogus initialization.
   Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &fixed_elements_kind,
                                 &element_size);
-  RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind);
+  CHECK(holder->map()->elements_kind() == fixed_elements_kind);
 
   size_t byte_offset = 0;
   size_t byte_length = 0;
-  RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_offset_object, &byte_offset));
-  RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_length_object, &byte_length));
+  CHECK(TryNumberToSize(isolate, *byte_offset_object, &byte_offset));
+  CHECK(TryNumberToSize(isolate, *byte_length_object, &byte_length));
 
   if (maybe_buffer->IsJSArrayBuffer()) {
     Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer);
     size_t array_buffer_byte_length =
         NumberToSize(isolate, buffer->byte_length());
-    RUNTIME_ASSERT(byte_offset <= array_buffer_byte_length);
-    RUNTIME_ASSERT(array_buffer_byte_length - byte_offset >= byte_length);
+    CHECK(byte_offset <= array_buffer_byte_length);
+    CHECK(array_buffer_byte_length - byte_offset >= byte_length);
   } else {
-    RUNTIME_ASSERT(maybe_buffer->IsNull());
+    CHECK(maybe_buffer->IsNull(isolate));
   }
 
-  RUNTIME_ASSERT(byte_length % element_size == 0);
+  CHECK(byte_length % element_size == 0);
   size_t length = byte_length / element_size;
 
   if (length > static_cast<unsigned>(Smi::kMaxValue)) {
@@ -142,7 +150,7 @@
   holder->set_byte_offset(*byte_offset_object);
   holder->set_byte_length(*byte_length_object);
 
-  if (!maybe_buffer->IsNull()) {
+  if (!maybe_buffer->IsNull(isolate)) {
     Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer);
     holder->set_buffer(*buffer);
 
@@ -178,8 +186,8 @@
   CONVERT_ARG_HANDLE_CHECKED(Object, source, 2);
   CONVERT_NUMBER_ARG_HANDLE_CHECKED(length_obj, 3);
 
-  RUNTIME_ASSERT(arrayId >= Runtime::ARRAY_ID_FIRST &&
-                 arrayId <= Runtime::ARRAY_ID_LAST);
+  CHECK(arrayId >= Runtime::ARRAY_ID_FIRST &&
+        arrayId <= Runtime::ARRAY_ID_LAST);
 
   ExternalArrayType array_type = kExternalInt8Array;  // Bogus initialization.
   size_t element_size = 1;                            // Bogus initialization.
@@ -187,7 +195,7 @@
   Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &fixed_elements_kind,
                                 &element_size);
 
-  RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind);
+  CHECK(holder->map()->elements_kind() == fixed_elements_kind);
 
   Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
   size_t length = 0;
@@ -196,7 +204,7 @@
     length_obj = handle(JSTypedArray::cast(*source)->length(), isolate);
     length = JSTypedArray::cast(*source)->length_value();
   } else {
-    RUNTIME_ASSERT(TryNumberToSize(isolate, *length_obj, &length));
+    CHECK(TryNumberToSize(isolate, *length_obj, &length));
   }
 
   if ((length > static_cast<unsigned>(Smi::kMaxValue)) ||
@@ -276,7 +284,6 @@
 BUFFER_VIEW_GETTER(ArrayBufferView, ByteLength, byte_length)
 BUFFER_VIEW_GETTER(ArrayBufferView, ByteOffset, byte_offset)
 BUFFER_VIEW_GETTER(TypedArray, Length, length)
-BUFFER_VIEW_GETTER(DataView, Buffer, buffer)
 
 #undef BUFFER_VIEW_GETTER
 
@@ -321,7 +328,7 @@
   Handle<JSTypedArray> target(JSTypedArray::cast(*target_obj));
   Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj));
   size_t offset = 0;
-  RUNTIME_ASSERT(TryNumberToSize(isolate, *offset_obj, &offset));
+  CHECK(TryNumberToSize(isolate, *offset_obj, &offset));
   size_t target_length = target->length_value();
   size_t source_length = source->length_value();
   size_t target_byte_length = NumberToSize(isolate, target->byte_length());
@@ -397,7 +404,8 @@
   Handle<JSTypedArray> obj(JSTypedArray::cast(args[0]));
   return isolate->heap()->ToBoolean(obj->GetBuffer()->is_shared() &&
                                     obj->type() != kExternalFloat32Array &&
-                                    obj->type() != kExternalFloat64Array);
+                                    obj->type() != kExternalFloat64Array &&
+                                    obj->type() != kExternalUint8ClampedArray);
 }
 
 
diff --git a/src/runtime/runtime-uri.cc b/src/runtime/runtime-uri.cc
deleted file mode 100644
index e64e9dc..0000000
--- a/src/runtime/runtime-uri.cc
+++ /dev/null
@@ -1,293 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/runtime/runtime-utils.h"
-
-#include "src/arguments.h"
-#include "src/conversions.h"
-#include "src/isolate-inl.h"
-#include "src/objects-inl.h"
-#include "src/string-search.h"
-#include "src/utils.h"
-
-namespace v8 {
-namespace internal {
-
-class URIUnescape : public AllStatic {
- public:
-  template <typename Char>
-  MUST_USE_RESULT static MaybeHandle<String> Unescape(Isolate* isolate,
-                                                      Handle<String> source);
-
- private:
-  static const signed char kHexValue['g'];
-
-  template <typename Char>
-  MUST_USE_RESULT static MaybeHandle<String> UnescapeSlow(Isolate* isolate,
-                                                          Handle<String> string,
-                                                          int start_index);
-
-  static INLINE(int TwoDigitHex(uint16_t character1, uint16_t character2));
-
-  template <typename Char>
-  static INLINE(int UnescapeChar(Vector<const Char> vector, int i, int length,
-                                 int* step));
-};
-
-
-const signed char URIUnescape::kHexValue[] = {
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -0, 1,  2,  3,  4,  5,
-    6,  7,  8,  9,  -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15};
-
-
-template <typename Char>
-MaybeHandle<String> URIUnescape::Unescape(Isolate* isolate,
-                                          Handle<String> source) {
-  int index;
-  {
-    DisallowHeapAllocation no_allocation;
-    StringSearch<uint8_t, Char> search(isolate, STATIC_CHAR_VECTOR("%"));
-    index = search.Search(source->GetCharVector<Char>(), 0);
-    if (index < 0) return source;
-  }
-  return UnescapeSlow<Char>(isolate, source, index);
-}
-
-
-template <typename Char>
-MaybeHandle<String> URIUnescape::UnescapeSlow(Isolate* isolate,
-                                              Handle<String> string,
-                                              int start_index) {
-  bool one_byte = true;
-  int length = string->length();
-
-  int unescaped_length = 0;
-  {
-    DisallowHeapAllocation no_allocation;
-    Vector<const Char> vector = string->GetCharVector<Char>();
-    for (int i = start_index; i < length; unescaped_length++) {
-      int step;
-      if (UnescapeChar(vector, i, length, &step) >
-          String::kMaxOneByteCharCode) {
-        one_byte = false;
-      }
-      i += step;
-    }
-  }
-
-  DCHECK(start_index < length);
-  Handle<String> first_part =
-      isolate->factory()->NewProperSubString(string, 0, start_index);
-
-  int dest_position = 0;
-  Handle<String> second_part;
-  DCHECK(unescaped_length <= String::kMaxLength);
-  if (one_byte) {
-    Handle<SeqOneByteString> dest = isolate->factory()
-                                        ->NewRawOneByteString(unescaped_length)
-                                        .ToHandleChecked();
-    DisallowHeapAllocation no_allocation;
-    Vector<const Char> vector = string->GetCharVector<Char>();
-    for (int i = start_index; i < length; dest_position++) {
-      int step;
-      dest->SeqOneByteStringSet(dest_position,
-                                UnescapeChar(vector, i, length, &step));
-      i += step;
-    }
-    second_part = dest;
-  } else {
-    Handle<SeqTwoByteString> dest = isolate->factory()
-                                        ->NewRawTwoByteString(unescaped_length)
-                                        .ToHandleChecked();
-    DisallowHeapAllocation no_allocation;
-    Vector<const Char> vector = string->GetCharVector<Char>();
-    for (int i = start_index; i < length; dest_position++) {
-      int step;
-      dest->SeqTwoByteStringSet(dest_position,
-                                UnescapeChar(vector, i, length, &step));
-      i += step;
-    }
-    second_part = dest;
-  }
-  return isolate->factory()->NewConsString(first_part, second_part);
-}
-
-
-int URIUnescape::TwoDigitHex(uint16_t character1, uint16_t character2) {
-  if (character1 > 'f') return -1;
-  int hi = kHexValue[character1];
-  if (hi == -1) return -1;
-  if (character2 > 'f') return -1;
-  int lo = kHexValue[character2];
-  if (lo == -1) return -1;
-  return (hi << 4) + lo;
-}
-
-
-template <typename Char>
-int URIUnescape::UnescapeChar(Vector<const Char> vector, int i, int length,
-                              int* step) {
-  uint16_t character = vector[i];
-  int32_t hi = 0;
-  int32_t lo = 0;
-  if (character == '%' && i <= length - 6 && vector[i + 1] == 'u' &&
-      (hi = TwoDigitHex(vector[i + 2], vector[i + 3])) != -1 &&
-      (lo = TwoDigitHex(vector[i + 4], vector[i + 5])) != -1) {
-    *step = 6;
-    return (hi << 8) + lo;
-  } else if (character == '%' && i <= length - 3 &&
-             (lo = TwoDigitHex(vector[i + 1], vector[i + 2])) != -1) {
-    *step = 3;
-    return lo;
-  } else {
-    *step = 1;
-    return character;
-  }
-}
-
-
-class URIEscape : public AllStatic {
- public:
-  template <typename Char>
-  MUST_USE_RESULT static MaybeHandle<String> Escape(Isolate* isolate,
-                                                    Handle<String> string);
-
- private:
-  static const char kHexChars[17];
-  static const char kNotEscaped[256];
-
-  static bool IsNotEscaped(uint16_t c) { return kNotEscaped[c] != 0; }
-};
-
-
-const char URIEscape::kHexChars[] = "0123456789ABCDEF";
-
-
-// kNotEscaped is generated by the following:
-//
-// #!/bin/perl
-// for (my $i = 0; $i < 256; $i++) {
-//   print "\n" if $i % 16 == 0;
-//   my $c = chr($i);
-//   my $escaped = 1;
-//   $escaped = 0 if $c =~ m#[A-Za-z0-9@*_+./-]#;
-//   print $escaped ? "0, " : "1, ";
-// }
-
-const char URIEscape::kNotEscaped[] = {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
-    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
-
-template <typename Char>
-MaybeHandle<String> URIEscape::Escape(Isolate* isolate, Handle<String> string) {
-  DCHECK(string->IsFlat());
-  int escaped_length = 0;
-  int length = string->length();
-
-  {
-    DisallowHeapAllocation no_allocation;
-    Vector<const Char> vector = string->GetCharVector<Char>();
-    for (int i = 0; i < length; i++) {
-      uint16_t c = vector[i];
-      if (c >= 256) {
-        escaped_length += 6;
-      } else if (IsNotEscaped(c)) {
-        escaped_length++;
-      } else {
-        escaped_length += 3;
-      }
-
-      // We don't allow strings that are longer than a maximal length.
-      DCHECK(String::kMaxLength < 0x7fffffff - 6);     // Cannot overflow.
-      if (escaped_length > String::kMaxLength) break;  // Provoke exception.
-    }
-  }
-
-  // No length change implies no change.  Return original string if no change.
-  if (escaped_length == length) return string;
-
-  Handle<SeqOneByteString> dest;
-  ASSIGN_RETURN_ON_EXCEPTION(
-      isolate, dest, isolate->factory()->NewRawOneByteString(escaped_length),
-      String);
-  int dest_position = 0;
-
-  {
-    DisallowHeapAllocation no_allocation;
-    Vector<const Char> vector = string->GetCharVector<Char>();
-    for (int i = 0; i < length; i++) {
-      uint16_t c = vector[i];
-      if (c >= 256) {
-        dest->SeqOneByteStringSet(dest_position, '%');
-        dest->SeqOneByteStringSet(dest_position + 1, 'u');
-        dest->SeqOneByteStringSet(dest_position + 2, kHexChars[c >> 12]);
-        dest->SeqOneByteStringSet(dest_position + 3, kHexChars[(c >> 8) & 0xf]);
-        dest->SeqOneByteStringSet(dest_position + 4, kHexChars[(c >> 4) & 0xf]);
-        dest->SeqOneByteStringSet(dest_position + 5, kHexChars[c & 0xf]);
-        dest_position += 6;
-      } else if (IsNotEscaped(c)) {
-        dest->SeqOneByteStringSet(dest_position, c);
-        dest_position++;
-      } else {
-        dest->SeqOneByteStringSet(dest_position, '%');
-        dest->SeqOneByteStringSet(dest_position + 1, kHexChars[c >> 4]);
-        dest->SeqOneByteStringSet(dest_position + 2, kHexChars[c & 0xf]);
-        dest_position += 3;
-      }
-    }
-  }
-
-  return dest;
-}
-
-
-RUNTIME_FUNCTION(Runtime_URIEscape) {
-  HandleScope scope(isolate);
-  DCHECK_EQ(1, args.length());
-  CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
-  Handle<String> source;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, source,
-                                     Object::ToString(isolate, input));
-  source = String::Flatten(source);
-  Handle<String> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, source->IsOneByteRepresentationUnderneath()
-                           ? URIEscape::Escape<uint8_t>(isolate, source)
-                           : URIEscape::Escape<uc16>(isolate, source));
-  return *result;
-}
-
-
-RUNTIME_FUNCTION(Runtime_URIUnescape) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
-  CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
-  Handle<String> source;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, source,
-                                     Object::ToString(isolate, input));
-  source = String::Flatten(source);
-  Handle<String> result;
-  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
-      isolate, result, source->IsOneByteRepresentationUnderneath()
-                           ? URIUnescape::Unescape<uint8_t>(isolate, source)
-                           : URIUnescape::Unescape<uc16>(isolate, source));
-  return *result;
-}
-
-}  // namespace internal
-}  // namespace v8
diff --git a/src/runtime/runtime-utils.h b/src/runtime/runtime-utils.h
index 17c78d5..5cdf043 100644
--- a/src/runtime/runtime-utils.h
+++ b/src/runtime/runtime-utils.h
@@ -21,15 +21,6 @@
     }                                              \
   } while (0)
 
-#define RUNTIME_ASSERT_HANDLIFIED(value, T)        \
-  do {                                             \
-    if (!(value)) {                                \
-      V8_RuntimeError(__FILE__, __LINE__, #value); \
-      isolate->ThrowIllegalOperation();            \
-      return MaybeHandle<T>();                     \
-    }                                              \
-  } while (0)
-
 #else
 
 #define RUNTIME_ASSERT(value)                  \
@@ -39,14 +30,6 @@
     }                                          \
   } while (0)
 
-#define RUNTIME_ASSERT_HANDLIFIED(value, T) \
-  do {                                      \
-    if (!(value)) {                         \
-      isolate->ThrowIllegalOperation();     \
-      return MaybeHandle<T>();              \
-    }                                       \
-  } while (0)
-
 #endif
 
 // Cast the given object to a value of the specified type and store
@@ -69,7 +52,7 @@
 // and return.
 #define CONVERT_BOOLEAN_ARG_CHECKED(name, index) \
   RUNTIME_ASSERT(args[index]->IsBoolean());      \
-  bool name = args[index]->IsTrue();
+  bool name = args[index]->IsTrue(isolate);
 
 // Cast the given argument to a Smi and store its value in an int variable
 // with the given name.  If the argument is not a Smi call IllegalOperation
diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h
index dc1678b..e325d4f 100644
--- a/src/runtime/runtime.h
+++ b/src/runtime/runtime.h
@@ -39,33 +39,33 @@
   F(MoveArrayContents, 2, 1)         \
   F(EstimateNumberOfElements, 1, 1)  \
   F(GetArrayKeys, 2, 1)              \
-  F(ArrayConstructor, -1, 1)         \
   F(NewArray, -1 /* >= 3 */, 1)      \
-  F(InternalArrayConstructor, -1, 1) \
   F(ArrayPush, -1, 1)                \
+  F(FunctionBind, -1, 1)             \
   F(NormalizeElements, 1, 1)         \
   F(GrowArrayElements, 2, 1)         \
   F(HasComplexElements, 1, 1)        \
   F(IsArray, 1, 1)                   \
+  F(ArrayIsArray, 1, 1)              \
   F(HasCachedArrayIndex, 1, 1)       \
   F(GetCachedArrayIndex, 1, 1)       \
   F(FixedArrayGet, 2, 1)             \
   F(FixedArraySet, 3, 1)             \
   F(ArraySpeciesConstructor, 1, 1)
 
-#define FOR_EACH_INTRINSIC_ATOMICS(F) \
-  F(AtomicsCompareExchange, 4, 1)     \
-  F(AtomicsLoad, 2, 1)                \
-  F(AtomicsStore, 3, 1)               \
-  F(AtomicsAdd, 3, 1)                 \
-  F(AtomicsSub, 3, 1)                 \
-  F(AtomicsAnd, 3, 1)                 \
-  F(AtomicsOr, 3, 1)                  \
-  F(AtomicsXor, 3, 1)                 \
-  F(AtomicsExchange, 3, 1)            \
+#define FOR_EACH_INTRINSIC_ATOMICS(F)           \
+  F(ThrowNotIntegerSharedTypedArrayError, 1, 1) \
+  F(ThrowNotInt32SharedTypedArrayError, 1, 1)   \
+  F(ThrowInvalidAtomicAccessIndexError, 0, 1)   \
+  F(AtomicsCompareExchange, 4, 1)               \
+  F(AtomicsAdd, 3, 1)                           \
+  F(AtomicsSub, 3, 1)                           \
+  F(AtomicsAnd, 3, 1)                           \
+  F(AtomicsOr, 3, 1)                            \
+  F(AtomicsXor, 3, 1)                           \
+  F(AtomicsExchange, 3, 1)                      \
   F(AtomicsIsLockFree, 1, 1)
 
-
 #define FOR_EACH_INTRINSIC_FUTEX(F)  \
   F(AtomicsFutexWait, 4, 1)          \
   F(AtomicsFutexWake, 3, 1)          \
@@ -81,7 +81,6 @@
   F(ThrowIfStaticPrototype, 1, 1)           \
   F(HomeObjectSymbol, 0, 1)                 \
   F(DefineClass, 4, 1)                      \
-  F(FinalizeClassDefinition, 2, 1)          \
   F(LoadFromSuper, 3, 1)                    \
   F(LoadKeyedFromSuper, 3, 1)               \
   F(StoreToSuper_Strict, 4, 1)              \
@@ -117,81 +116,82 @@
   F(WeakCollectionHas, 3, 1)              \
   F(WeakCollectionDelete, 3, 1)           \
   F(WeakCollectionSet, 4, 1)              \
-  F(GetWeakSetValues, 2, 1)               \
-  F(ObservationWeakMapCreate, 0, 1)
-
+  F(GetWeakSetValues, 2, 1)
 
 #define FOR_EACH_INTRINSIC_COMPILER(F)    \
   F(CompileLazy, 1, 1)                    \
+  F(CompileBaseline, 1, 1)                \
   F(CompileOptimized_Concurrent, 1, 1)    \
   F(CompileOptimized_NotConcurrent, 1, 1) \
   F(NotifyStubFailure, 0, 1)              \
   F(NotifyDeoptimized, 1, 1)              \
   F(CompileForOnStackReplacement, 1, 1)   \
   F(TryInstallOptimizedCode, 1, 1)        \
-  F(ResolvePossiblyDirectEval, 5, 1)
-
+  F(ResolvePossiblyDirectEval, 6, 1)
 
 #define FOR_EACH_INTRINSIC_DATE(F) \
   F(IsDate, 1, 1)                  \
   F(DateCurrentTime, 0, 1)         \
   F(ThrowNotDateError, 0, 1)
 
-#define FOR_EACH_INTRINSIC_DEBUG(F)            \
-  F(HandleDebuggerStatement, 0, 1)             \
-  F(DebugBreak, 1, 1)                          \
-  F(DebugBreakOnBytecode, 1, 1)                \
-  F(SetDebugEventListener, 2, 1)               \
-  F(ScheduleBreak, 0, 1)                       \
-  F(DebugGetInternalProperties, 1, 1)          \
-  F(DebugGetPropertyDetails, 2, 1)             \
-  F(DebugGetProperty, 2, 1)                    \
-  F(DebugPropertyTypeFromDetails, 1, 1)        \
-  F(DebugPropertyAttributesFromDetails, 1, 1)  \
-  F(DebugPropertyIndexFromDetails, 1, 1)       \
-  F(DebugNamedInterceptorPropertyValue, 2, 1)  \
-  F(DebugIndexedInterceptorElementValue, 2, 1) \
-  F(CheckExecutionState, 1, 1)                 \
-  F(GetFrameCount, 1, 1)                       \
-  F(GetFrameDetails, 2, 1)                     \
-  F(GetScopeCount, 2, 1)                       \
-  F(GetScopeDetails, 4, 1)                     \
-  F(GetAllScopesDetails, 4, 1)                 \
-  F(GetFunctionScopeCount, 1, 1)               \
-  F(GetFunctionScopeDetails, 2, 1)             \
-  F(SetScopeVariableValue, 6, 1)               \
-  F(DebugPrintScopes, 0, 1)                    \
-  F(GetThreadCount, 1, 1)                      \
-  F(GetThreadDetails, 2, 1)                    \
-  F(SetBreakPointsActive, 1, 1)                \
-  F(GetBreakLocations, 2, 1)                   \
-  F(SetFunctionBreakPoint, 3, 1)               \
-  F(SetScriptBreakPoint, 4, 1)                 \
-  F(ClearBreakPoint, 1, 1)                     \
-  F(ChangeBreakOnException, 2, 1)              \
-  F(IsBreakOnException, 1, 1)                  \
-  F(PrepareStep, 2, 1)                         \
-  F(ClearStepping, 0, 1)                       \
-  F(DebugEvaluate, 6, 1)                       \
-  F(DebugEvaluateGlobal, 4, 1)                 \
-  F(DebugGetLoadedScripts, 0, 1)               \
-  F(DebugReferencedBy, 3, 1)                   \
-  F(DebugConstructedBy, 2, 1)                  \
-  F(DebugGetPrototype, 1, 1)                   \
-  F(DebugSetScriptSource, 2, 1)                \
-  F(FunctionGetInferredName, 1, 1)             \
-  F(FunctionGetDebugName, 1, 1)                \
-  F(GetFunctionCodePositionFromSource, 2, 1)   \
-  F(ExecuteInDebugContext, 1, 1)               \
-  F(GetDebugContext, 0, 1)                     \
-  F(CollectGarbage, 1, 1)                      \
-  F(GetHeapUsage, 0, 1)                        \
-  F(GetScript, 1, 1)                           \
-  F(DebugPrepareStepInIfStepping, 1, 1)        \
-  F(DebugPushPromise, 2, 1)                    \
-  F(DebugPopPromise, 0, 1)                     \
-  F(DebugAsyncTaskEvent, 1, 1)                 \
-  F(DebugIsActive, 0, 1)                       \
+#define FOR_EACH_INTRINSIC_DEBUG(F)             \
+  F(HandleDebuggerStatement, 0, 1)              \
+  F(DebugBreak, 1, 1)                           \
+  F(DebugBreakOnBytecode, 1, 1)                 \
+  F(SetDebugEventListener, 2, 1)                \
+  F(ScheduleBreak, 0, 1)                        \
+  F(DebugGetInternalProperties, 1, 1)           \
+  F(DebugGetPropertyDetails, 2, 1)              \
+  F(DebugGetProperty, 2, 1)                     \
+  F(DebugPropertyTypeFromDetails, 1, 1)         \
+  F(DebugPropertyAttributesFromDetails, 1, 1)   \
+  F(CheckExecutionState, 1, 1)                  \
+  F(GetFrameCount, 1, 1)                        \
+  F(GetFrameDetails, 2, 1)                      \
+  F(GetScopeCount, 2, 1)                        \
+  F(GetScopeDetails, 4, 1)                      \
+  F(GetAllScopesDetails, 4, 1)                  \
+  F(GetFunctionScopeCount, 1, 1)                \
+  F(GetFunctionScopeDetails, 2, 1)              \
+  F(SetScopeVariableValue, 6, 1)                \
+  F(DebugPrintScopes, 0, 1)                     \
+  F(SetBreakPointsActive, 1, 1)                 \
+  F(GetBreakLocations, 2, 1)                    \
+  F(SetFunctionBreakPoint, 3, 1)                \
+  F(SetScriptBreakPoint, 4, 1)                  \
+  F(ClearBreakPoint, 1, 1)                      \
+  F(ChangeBreakOnException, 2, 1)               \
+  F(IsBreakOnException, 1, 1)                   \
+  F(PrepareStep, 2, 1)                          \
+  F(ClearStepping, 0, 1)                        \
+  F(DebugEvaluate, 6, 1)                        \
+  F(DebugEvaluateGlobal, 4, 1)                  \
+  F(DebugGetLoadedScripts, 0, 1)                \
+  F(DebugReferencedBy, 3, 1)                    \
+  F(DebugConstructedBy, 2, 1)                   \
+  F(DebugGetPrototype, 1, 1)                    \
+  F(DebugSetScriptSource, 2, 1)                 \
+  F(FunctionGetInferredName, 1, 1)              \
+  F(FunctionGetDebugName, 1, 1)                 \
+  F(GetFunctionCodePositionFromSource, 2, 1)    \
+  F(ExecuteInDebugContext, 1, 1)                \
+  F(GetDebugContext, 0, 1)                      \
+  F(CollectGarbage, 1, 1)                       \
+  F(GetHeapUsage, 0, 1)                         \
+  F(GetScript, 1, 1)                            \
+  F(ScriptLineCount, 1, 1)                      \
+  F(ScriptLineStartPosition, 2, 1)              \
+  F(ScriptLineEndPosition, 2, 1)                \
+  F(ScriptLocationFromLine, 4, 1)               \
+  F(ScriptPositionInfo, 3, 1)                   \
+  F(ScriptSourceLine, 2, 1)                     \
+  F(DebugPrepareStepInIfStepping, 1, 1)         \
+  F(DebugPrepareStepInSuspendedGenerator, 0, 1) \
+  F(DebugRecordAsyncFunction, 1, 1)             \
+  F(DebugPushPromise, 2, 1)                     \
+  F(DebugPopPromise, 0, 1)                      \
+  F(DebugAsyncTaskEvent, 1, 1)                  \
+  F(DebugIsActive, 0, 1)                        \
   F(DebugBreakInOptimizedCode, 0, 1)
 
 #define FOR_EACH_INTRINSIC_FORIN(F) \
@@ -231,19 +231,15 @@
   F(FunctionToString, 1, 1)
 
 #define FOR_EACH_INTRINSIC_GENERATOR(F) \
-  F(CreateJSGeneratorObject, 0, 1)      \
+  F(CreateJSGeneratorObject, 2, 1)      \
   F(SuspendJSGeneratorObject, 1, 1)     \
-  F(ResumeJSGeneratorObject, 3, 1)      \
   F(GeneratorClose, 1, 1)               \
   F(GeneratorGetFunction, 1, 1)         \
   F(GeneratorGetReceiver, 1, 1)         \
-  F(GeneratorGetInput, 1, 1)            \
+  F(GeneratorGetInputOrDebugPos, 1, 1)  \
   F(GeneratorGetContinuation, 1, 1)     \
   F(GeneratorGetSourcePosition, 1, 1)   \
-  F(GeneratorNext, 2, 1)                \
-  F(GeneratorReturn, 2, 1)              \
-  F(GeneratorThrow, 2, 1)
-
+  F(GeneratorGetResumeMode, 1, 1)
 
 #ifdef V8_I18N_SUPPORT
 #define FOR_EACH_INTRINSIC_I18N(F)           \
@@ -269,7 +265,11 @@
   F(BreakIteratorFirst, 1, 1)                \
   F(BreakIteratorNext, 1, 1)                 \
   F(BreakIteratorCurrent, 1, 1)              \
-  F(BreakIteratorBreakType, 1, 1)
+  F(BreakIteratorBreakType, 1, 1)            \
+  F(StringToLowerCaseI18N, 1, 1)             \
+  F(StringToUpperCaseI18N, 1, 1)             \
+  F(StringLocaleConvertCase, 3, 1)           \
+  F(DateCacheVersion, 0, 1)
 #else
 #define FOR_EACH_INTRINSIC_I18N(F)
 #endif
@@ -289,14 +289,19 @@
   F(NewSyntaxError, 2, 1)                           \
   F(NewReferenceError, 2, 1)                        \
   F(ThrowIllegalInvocation, 0, 1)                   \
+  F(ThrowIncompatibleMethodReceiver, 2, 1)          \
   F(ThrowIteratorResultNotAnObject, 1, 1)           \
+  F(ThrowGeneratorRunning, 0, 1)                    \
   F(ThrowStackOverflow, 0, 1)                       \
+  F(ThrowWasmError, 2, 1)                           \
   F(PromiseRejectEvent, 3, 1)                       \
   F(PromiseRevokeReject, 1, 1)                      \
   F(StackGuard, 0, 1)                               \
   F(Interrupt, 0, 1)                                \
   F(AllocateInNewSpace, 1, 1)                       \
   F(AllocateInTargetSpace, 2, 1)                    \
+  F(AllocateSeqOneByteString, 1, 1)                 \
+  F(AllocateSeqTwoByteString, 1, 1)                 \
   F(CollectStackTrace, 2, 1)                        \
   F(MessageGetStartPosition, 1, 1)                  \
   F(MessageGetScript, 1, 1)                         \
@@ -315,16 +320,14 @@
   F(ThrowConstructedNonConstructable, 1, 1)         \
   F(ThrowDerivedConstructorReturnedNonObject, 0, 1) \
   F(ThrowCalledNonCallable, 1, 1)                   \
+  F(ThrowCalledOnNullOrUndefined, 1, 1)             \
   F(CreateListFromArrayLike, 1, 1)                  \
   F(IncrementUseCounter, 1, 1)                      \
-  F(GetOrdinaryHasInstance, 0, 1)                   \
-  F(GetAndResetRuntimeCallStats, 0, 1)
-
-#define FOR_EACH_INTRINSIC_JSON(F) \
-  F(QuoteJSONString, 1, 1)         \
-  F(BasicJSONStringify, 1, 1)      \
-  F(ParseJson, 1, 1)
-
+  F(GetAndResetRuntimeCallStats, -1 /* <= 2 */, 1)  \
+  F(EnqueueMicrotask, 1, 1)                         \
+  F(RunMicrotasks, 0, 1)                            \
+  F(OrdinaryHasInstance, 2, 1)                      \
+  F(IsWasmObject, 1, 1)
 
 #define FOR_EACH_INTRINSIC_LITERALS(F) \
   F(CreateRegExpLiteral, 4, 1)         \
@@ -348,13 +351,8 @@
 
 
 #define FOR_EACH_INTRINSIC_MATHS(F) \
-  F(MathLogRT, 1, 1)                \
   F(DoubleHi, 1, 1)                 \
   F(DoubleLo, 1, 1)                 \
-  F(ConstructDouble, 2, 1)          \
-  F(RemPiO2, 2, 1)                  \
-  F(MathAtan2, 2, 1)                \
-  F(MathExpRT, 1, 1)                \
   F(MathPow, 2, 1)                  \
   F(MathPowRT, 2, 1)                \
   F(GenerateRandomNumbers, 1, 1)
@@ -371,7 +369,6 @@
   F(StringParseFloat, 1, 1)            \
   F(NumberToString, 1, 1)              \
   F(NumberToStringSkipCache, 1, 1)     \
-  F(NumberToIntegerMapMinusZero, 1, 1) \
   F(NumberToSmi, 1, 1)                 \
   F(SmiLexicographicCompare, 2, 1)     \
   F(MaxSmi, 0, 1)                      \
@@ -385,11 +382,9 @@
   F(ObjectHasOwnProperty, 2, 1)                      \
   F(InternalSetPrototype, 2, 1)                      \
   F(SetPrototype, 2, 1)                              \
-  F(GetOwnProperty_Legacy, 2, 1)                     \
   F(OptimizeObjectForAddingMultipleProperties, 2, 1) \
   F(GetProperty, 2, 1)                               \
   F(KeyedGetProperty, 2, 1)                          \
-  F(LoadGlobalViaContext, 1, 1)                      \
   F(StoreGlobalViaContext_Sloppy, 2, 1)              \
   F(StoreGlobalViaContext_Strict, 2, 1)              \
   F(AddNamedProperty, 4, 1)                          \
@@ -406,13 +401,10 @@
   F(AllocateHeapNumber, 0, 1)                        \
   F(NewObject, 2, 1)                                 \
   F(FinalizeInstanceSize, 1, 1)                      \
-  F(GlobalProxy, 1, 1)                               \
-  F(LookupAccessor, 3, 1)                            \
   F(LoadMutableDouble, 2, 1)                         \
   F(TryMigrateInstance, 1, 1)                        \
   F(IsJSGlobalProxy, 1, 1)                           \
   F(DefineAccessorPropertyUnchecked, 5, 1)           \
-  F(DefineDataPropertyUnchecked, 4, 1)               \
   F(DefineDataPropertyInLiteral, 5, 1)               \
   F(GetDataProperty, 2, 1)                           \
   F(HasFastPackedElements, 1, 1)                     \
@@ -433,26 +425,10 @@
   F(SameValue, 2, 1)                                 \
   F(SameValueZero, 2, 1)                             \
   F(Compare, 3, 1)                                   \
-  F(InstanceOf, 2, 1)                                \
-  F(OrdinaryHasInstance, 2, 1)                       \
   F(HasInPrototypeChain, 2, 1)                       \
   F(CreateIterResultObject, 2, 1)                    \
   F(IsAccessCheckNeeded, 1, 1)                       \
-  F(ObjectDefineProperties, 2, 1)                    \
-  F(ObjectDefineProperty, 3, 1)
-
-#define FOR_EACH_INTRINSIC_OBSERVE(F)            \
-  F(IsObserved, 1, 1)                            \
-  F(SetIsObserved, 1, 1)                         \
-  F(EnqueueMicrotask, 1, 1)                      \
-  F(RunMicrotasks, 0, 1)                         \
-  F(DeliverObservationChangeRecords, 2, 1)       \
-  F(GetObservationState, 0, 1)                   \
-  F(ObserverObjectAndRecordHaveSameOrigin, 3, 1) \
-  F(ObjectWasCreatedInCurrentOrigin, 1, 1)       \
-  F(GetObjectContextObjectObserve, 1, 1)         \
-  F(GetObjectContextObjectGetNotifier, 1, 1)     \
-  F(GetObjectContextNotifierPerformChange, 1, 1)
+  F(CreateDataProperty, 3, 1)
 
 #define FOR_EACH_INTRINSIC_OPERATORS(F) \
   F(Multiply, 2, 1)                     \
@@ -473,7 +449,8 @@
   F(LessThan, 2, 1)                     \
   F(GreaterThan, 2, 1)                  \
   F(LessThanOrEqual, 2, 1)              \
-  F(GreaterThanOrEqual, 2, 1)
+  F(GreaterThanOrEqual, 2, 1)           \
+  F(InstanceOf, 2, 1)
 
 #define FOR_EACH_INTRINSIC_PROXY(F)     \
   F(IsJSProxy, 1, 1)                    \
@@ -495,31 +472,31 @@
   F(RegExpExecReThrow, 4, 1)                   \
   F(IsRegExp, 1, 1)
 
-#define FOR_EACH_INTRINSIC_SCOPES(F)       \
-  F(ThrowConstAssignError, 0, 1)           \
-  F(DeclareGlobals, 2, 1)                  \
-  F(InitializeVarGlobal, 3, 1)             \
-  F(InitializeConstGlobal, 2, 1)           \
-  F(DeclareLookupSlot, 3, 1)               \
-  F(InitializeLegacyConstLookupSlot, 3, 1) \
-  F(NewSloppyArguments_Generic, 1, 1)      \
-  F(NewStrictArguments, 1, 1)              \
-  F(NewRestParameter, 1, 1)                \
-  F(NewSloppyArguments, 3, 1)              \
-  F(NewClosure, 1, 1)                      \
-  F(NewClosure_Tenured, 1, 1)              \
-  F(NewScriptContext, 2, 1)                \
-  F(NewFunctionContext, 1, 1)              \
-  F(PushWithContext, 2, 1)                 \
-  F(PushCatchContext, 3, 1)                \
-  F(PushBlockContext, 2, 1)                \
-  F(IsJSModule, 1, 1)                      \
-  F(PushModuleContext, 2, 1)               \
-  F(DeclareModules, 1, 1)                  \
-  F(DeleteLookupSlot, 1, 1)                \
-  F(LoadLookupSlot, 1, 1)                  \
-  F(LoadLookupSlotInsideTypeof, 1, 1)      \
-  F(StoreLookupSlot_Sloppy, 2, 1)          \
+#define FOR_EACH_INTRINSIC_SCOPES(F)  \
+  F(ThrowConstAssignError, 0, 1)      \
+  F(DeclareGlobals, 2, 1)             \
+  F(InitializeVarGlobal, 3, 1)        \
+  F(InitializeConstGlobal, 2, 1)      \
+  F(DeclareEvalFunction, 2, 1)        \
+  F(DeclareEvalVar, 1, 1)             \
+  F(NewSloppyArguments_Generic, 1, 1) \
+  F(NewStrictArguments, 1, 1)         \
+  F(NewRestParameter, 1, 1)           \
+  F(NewSloppyArguments, 3, 1)         \
+  F(NewClosure, 1, 1)                 \
+  F(NewClosure_Tenured, 1, 1)         \
+  F(NewScriptContext, 2, 1)           \
+  F(NewFunctionContext, 1, 1)         \
+  F(PushWithContext, 2, 1)            \
+  F(PushCatchContext, 3, 1)           \
+  F(PushBlockContext, 2, 1)           \
+  F(IsJSModule, 1, 1)                 \
+  F(PushModuleContext, 2, 1)          \
+  F(DeclareModules, 1, 1)             \
+  F(DeleteLookupSlot, 1, 1)           \
+  F(LoadLookupSlot, 1, 1)             \
+  F(LoadLookupSlotInsideTypeof, 1, 1) \
+  F(StoreLookupSlot_Sloppy, 2, 1)     \
   F(StoreLookupSlot_Strict, 2, 1)
 
 #define FOR_EACH_INTRINSIC_SIMD(F)     \
@@ -849,9 +826,6 @@
   F(StringToArray, 2, 1)                  \
   F(StringToLowerCase, 1, 1)              \
   F(StringToUpperCase, 1, 1)              \
-  F(StringTrim, 3, 1)                     \
-  F(TruncateString, 2, 1)                 \
-  F(NewString, 2, 1)                      \
   F(StringLessThan, 2, 1)                 \
   F(StringLessThanOrEqual, 2, 1)          \
   F(StringGreaterThan, 2, 1)              \
@@ -860,11 +834,7 @@
   F(StringNotEqual, 2, 1)                 \
   F(FlattenString, 1, 1)                  \
   F(StringCharFromCode, 1, 1)             \
-  F(StringCharAt, 2, 1)                   \
-  F(OneByteSeqStringGetChar, 2, 1)        \
-  F(OneByteSeqStringSetChar, 3, 1)        \
-  F(TwoByteSeqStringGetChar, 2, 1)        \
-  F(TwoByteSeqStringSetChar, 3, 1)        \
+  F(ExternalStringGetChar, 2, 1)          \
   F(StringCharCodeAt, 2, 1)
 
 #define FOR_EACH_INTRINSIC_SYMBOL(F) \
@@ -876,6 +846,7 @@
   F(SymbolIsPrivate, 1, 1)
 
 #define FOR_EACH_INTRINSIC_TEST(F)            \
+  F(ConstructDouble, 2, 1)                    \
   F(DeoptimizeFunction, 1, 1)                 \
   F(DeoptimizeNow, 0, 1)                      \
   F(RunningInSimulator, 0, 1)                 \
@@ -892,6 +863,7 @@
   F(SetAllocationTimeout, -1 /* 2 || 3 */, 1) \
   F(DebugPrint, 1, 1)                         \
   F(DebugTrace, 0, 1)                         \
+  F(GetExceptionDetails, 1, 1)                \
   F(GlobalPrint, 1, 1)                        \
   F(SystemBreak, 0, 1)                        \
   F(SetFlags, 1, 1)                           \
@@ -934,7 +906,6 @@
   F(ArrayBufferViewGetByteLength, 1, 1)      \
   F(ArrayBufferViewGetByteOffset, 1, 1)      \
   F(TypedArrayGetLength, 1, 1)               \
-  F(DataViewGetBuffer, 1, 1)                 \
   F(TypedArrayGetBuffer, 1, 1)               \
   F(TypedArraySetFastCases, 3, 1)            \
   F(TypedArrayMaxSizeInHeap, 0, 1)           \
@@ -960,10 +931,6 @@
   F(DataViewSetFloat64, 4, 1)
 
 
-#define FOR_EACH_INTRINSIC_URI(F) \
-  F(URIEscape, 1, 1)              \
-  F(URIUnescape, 1, 1)
-
 #define FOR_EACH_INTRINSIC_RETURN_PAIR(F) \
   F(LoadLookupSlotForCall, 1, 2)
 
@@ -984,6 +951,8 @@
   F(KeyedStoreIC_MissFromStubFailure, 5, 1)  \
   F(KeyedStoreIC_Slow, 5, 1)                 \
   F(LoadElementWithInterceptor, 2, 1)        \
+  F(LoadGlobalIC_Miss, 2, 1)                 \
+  F(LoadGlobalIC_Slow, 2, 1)                 \
   F(LoadIC_Miss, 4, 1)                       \
   F(LoadIC_MissFromStubFailure, 4, 1)        \
   F(LoadPropertyWithInterceptor, 3, 1)       \
@@ -996,7 +965,6 @@
   F(ToBooleanIC_Miss, 1, 1)                  \
   F(Unreachable, 0, 1)
 
-
 #define FOR_EACH_INTRINSIC_RETURN_OBJECT(F) \
   FOR_EACH_INTRINSIC_IC(F)                  \
   FOR_EACH_INTRINSIC_ARRAY(F)               \
@@ -1013,13 +981,11 @@
   FOR_EACH_INTRINSIC_GENERATOR(F)           \
   FOR_EACH_INTRINSIC_I18N(F)                \
   FOR_EACH_INTRINSIC_INTERNAL(F)            \
-  FOR_EACH_INTRINSIC_JSON(F)                \
   FOR_EACH_INTRINSIC_LITERALS(F)            \
   FOR_EACH_INTRINSIC_LIVEEDIT(F)            \
   FOR_EACH_INTRINSIC_MATHS(F)               \
   FOR_EACH_INTRINSIC_NUMBERS(F)             \
   FOR_EACH_INTRINSIC_OBJECT(F)              \
-  FOR_EACH_INTRINSIC_OBSERVE(F)             \
   FOR_EACH_INTRINSIC_OPERATORS(F)           \
   FOR_EACH_INTRINSIC_PROXY(F)               \
   FOR_EACH_INTRINSIC_REGEXP(F)              \
@@ -1028,8 +994,7 @@
   FOR_EACH_INTRINSIC_STRINGS(F)             \
   FOR_EACH_INTRINSIC_SYMBOL(F)              \
   FOR_EACH_INTRINSIC_TEST(F)                \
-  FOR_EACH_INTRINSIC_TYPEDARRAY(F)          \
-  FOR_EACH_INTRINSIC_URI(F)
+  FOR_EACH_INTRINSIC_TYPEDARRAY(F)
 
 // FOR_EACH_INTRINSIC defines the list of all intrinsics, coming in 2 flavors,
 // either returning an object or a pair.
@@ -1108,7 +1073,8 @@
       Handle<Object> value, LanguageMode language_mode);
 
   MUST_USE_RESULT static MaybeHandle<Object> GetObjectProperty(
-      Isolate* isolate, Handle<Object> object, Handle<Object> key);
+      Isolate* isolate, Handle<Object> object, Handle<Object> key,
+      bool* is_found_out = nullptr);
 
   enum TypedArrayId {
     // arrayIds below should be synchronized with typedarray.js natives.
@@ -1129,11 +1095,6 @@
                                    ElementsKind* fixed_elements_kind,
                                    size_t* element_size);
 
-  // Used in runtime.cc and hydrogen's VisitArrayLiteral.
-  MUST_USE_RESULT static MaybeHandle<Object> CreateArrayLiteralBoilerplate(
-      Isolate* isolate, Handle<LiteralsArray> literals,
-      Handle<FixedArray> elements);
-
   static MaybeHandle<JSArray> GetInternalProperties(Isolate* isolate,
                                                     Handle<Object>);
 };
diff --git a/src/s390/OWNERS b/src/s390/OWNERS
index eb007cb..752e8e3 100644
--- a/src/s390/OWNERS
+++ b/src/s390/OWNERS
@@ -3,3 +3,4 @@
 joransiu@ca.ibm.com
 mbrandy@us.ibm.com
 michael_dawson@ca.ibm.com
+bjaideep@ca.ibm.com
diff --git a/src/s390/assembler-s390-inl.h b/src/s390/assembler-s390-inl.h
index 400d543..b5ace13 100644
--- a/src/s390/assembler-s390-inl.h
+++ b/src/s390/assembler-s390-inl.h
@@ -93,11 +93,6 @@
   return Assembler::target_address_at(pc_, host_);
 }
 
-Address RelocInfo::wasm_memory_reference() {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  return Assembler::target_address_at(pc_, host_);
-}
-
 Address RelocInfo::target_address_address() {
   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) ||
          rmode_ == EMBEDDED_OBJECT || rmode_ == EXTERNAL_REFERENCE);
@@ -156,19 +151,6 @@
   return code_targets_[index];
 }
 
-void RelocInfo::update_wasm_memory_reference(
-    Address old_base, Address new_base, size_t old_size, size_t new_size,
-    ICacheFlushMode icache_flush_mode) {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  DCHECK(old_base <= wasm_memory_reference() &&
-         wasm_memory_reference() < old_base + old_size);
-  Address updated_reference = new_base + (wasm_memory_reference() - old_base);
-  DCHECK(new_base <= updated_reference &&
-         updated_reference < new_base + new_size);
-  Assembler::set_target_address_at(isolate_, pc_, host_, updated_reference,
-                                   icache_flush_mode);
-}
-
 Object* RelocInfo::target_object() {
   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
   return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_));
@@ -312,6 +294,7 @@
   }
 }
 
+template <typename ObjectVisitor>
 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
diff --git a/src/s390/assembler-s390.cc b/src/s390/assembler-s390.cc
index 35ba431..07ef6c0 100644
--- a/src/s390/assembler-s390.cc
+++ b/src/s390/assembler-s390.cc
@@ -217,6 +217,33 @@
 
 bool RelocInfo::IsInConstantPool() { return false; }
 
+Address RelocInfo::wasm_memory_reference() {
+  DCHECK(IsWasmMemoryReference(rmode_));
+  return Assembler::target_address_at(pc_, host_);
+}
+
+uint32_t RelocInfo::wasm_memory_size_reference() {
+  DCHECK(IsWasmMemorySizeReference(rmode_));
+  return static_cast<uint32_t>(
+      reinterpret_cast<intptr_t>(Assembler::target_address_at(pc_, host_)));
+}
+
+Address RelocInfo::wasm_global_reference() {
+  DCHECK(IsWasmGlobalReference(rmode_));
+  return Assembler::target_address_at(pc_, host_);
+}
+
+void RelocInfo::unchecked_update_wasm_memory_reference(
+    Address address, ICacheFlushMode flush_mode) {
+  Assembler::set_target_address_at(isolate_, pc_, host_, address, flush_mode);
+}
+
+void RelocInfo::unchecked_update_wasm_memory_size(uint32_t size,
+                                                  ICacheFlushMode flush_mode) {
+  Assembler::set_target_address_at(isolate_, pc_, host_,
+                                   reinterpret_cast<Address>(size), flush_mode);
+}
+
 // -----------------------------------------------------------------------------
 // Implementation of Operand and MemOperand
 // See assembler-s390-inl.h for inlined constructors
@@ -273,6 +300,8 @@
   desc->instr_size = pc_offset();
   desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
   desc->origin = this;
+  desc->unwinding_info_size = 0;
+  desc->unwinding_info = nullptr;
 }
 
 void Assembler::Align(int m) {
@@ -2466,7 +2495,6 @@
 
 void Assembler::call(Handle<Code> target, RelocInfo::Mode rmode,
                      TypeFeedbackId ast_id) {
-  positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
 
   int32_t target_index = emit_code_target(target, rmode, ast_id);
diff --git a/src/s390/assembler-s390.h b/src/s390/assembler-s390.h
index 0b9fa38..391a5d4 100644
--- a/src/s390/assembler-s390.h
+++ b/src/s390/assembler-s390.h
@@ -90,6 +90,8 @@
   V(d0)  V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)  \
   V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d13) V(d14) V(d15)
 
+#define FLOAT_REGISTERS DOUBLE_REGISTERS
+
 #define ALLOCATABLE_DOUBLE_REGISTERS(V)                   \
   V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)         \
   V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d15) V(d0)
@@ -143,8 +145,6 @@
     return r;
   }
 
-  const char* ToString();
-  bool IsAllocatable() const;
   bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
   bool is(Register reg) const { return reg_code == reg.reg_code; }
   int code() const {
@@ -185,6 +185,8 @@
 const Register kRootRegister = r10;   // Roots array pointer.
 const Register cp = r13;              // JavaScript context pointer.
 
+static const bool kSimpleFPAliasing = true;
+
 // Double word FP register.
 struct DoubleRegister {
   enum Code {
@@ -198,8 +200,6 @@
   static const int kNumRegisters = Code::kAfterLast;
   static const int kMaxNumRegisters = kNumRegisters;
 
-  const char* ToString();
-  bool IsAllocatable() const;
   bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
   bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
 
@@ -221,7 +221,10 @@
   int reg_code;
 };
 
-typedef DoubleRegister DoubleRegister;
+typedef DoubleRegister FloatRegister;
+
+// TODO(john.yan) Define SIMD registers.
+typedef DoubleRegister Simd128Register;
 
 #define DECLARE_REGISTER(R) \
   const DoubleRegister R = {DoubleRegister::kCode_##R};
@@ -265,9 +268,6 @@
 const CRegister cr6 = {6};
 const CRegister cr7 = {7};
 
-// TODO(john.yan) Define SIMD registers.
-typedef DoubleRegister Simd128Register;
-
 // -----------------------------------------------------------------------------
 // Machine instruction Operands
 
@@ -546,7 +546,6 @@
 
   // Helper for unconditional branch to Label with update to save register
   void b(Register r, Label* l) {
-    positions_recorder()->WriteRecordedPositions();
     int32_t halfwords = branch_offset(l) / 2;
     brasl(r, Operand(halfwords));
   }
@@ -607,7 +606,7 @@
 
   void breakpoint(bool do_print) {
     if (do_print) {
-      printf("DebugBreak is inserted to %p\n", pc_);
+      PrintF("DebugBreak is inserted to %p\n", static_cast<void*>(pc_));
     }
 #if V8_HOST_ARCH_64_BIT
     int64_t value = reinterpret_cast<uint64_t>(&v8::base::OS::DebugBreak);
@@ -1241,7 +1240,7 @@
 
   // Record a deoptimization reason that can be used by a log or cpu profiler.
   // Use --trace-deopt to enable.
-  void RecordDeoptReason(const int reason, int raw_position);
+  void RecordDeoptReason(const int reason, int raw_position, int id);
 
   // Writes a single byte or word of data in the code stream.  Used
   // for inline tables, e.g., jump-tables.
diff --git a/src/s390/builtins-s390.cc b/src/s390/builtins-s390.cc
index 12b52c1..f0059bc 100644
--- a/src/s390/builtins-s390.cc
+++ b/src/s390/builtins-s390.cc
@@ -15,8 +15,7 @@
 
 #define __ ACCESS_MASM(masm)
 
-void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
-                                BuiltinExtraArguments extra_args) {
+void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
   // ----------- S t a t e -------------
   //  -- r2                 : number of arguments excluding receiver
   //  -- r3                 : target
@@ -35,24 +34,8 @@
   __ LoadP(cp, FieldMemOperand(r3, JSFunction::kContextOffset));
 
   // Insert extra arguments.
-  int num_extra_args = 0;
-  switch (extra_args) {
-    case BuiltinExtraArguments::kTarget:
-      __ Push(r3);
-      ++num_extra_args;
-      break;
-    case BuiltinExtraArguments::kNewTarget:
-      __ Push(r5);
-      ++num_extra_args;
-      break;
-    case BuiltinExtraArguments::kTargetAndNewTarget:
-      __ Push(r3, r5);
-      num_extra_args += 2;
-      break;
-    case BuiltinExtraArguments::kNone:
-      break;
-  }
-
+  const int num_extra_args = 2;
+  __ Push(r3, r5);
   // JumpToExternalReference expects r2 to contain the number of arguments
   // including the receiver and the extra arguments.
   __ AddP(r2, r2, Operand(num_extra_args + 1));
@@ -132,6 +115,8 @@
 void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
   // ----------- S t a t e -------------
   //  -- r2                 : number of arguments
+  //  -- r3                 : function
+  //  -- cp                 : context
   //  -- lr                 : return address
   //  -- sp[(argc - n) * 8] : arg[n] (zero-based)
   //  -- sp[(argc + 1) * 8] : receiver
@@ -143,59 +128,63 @@
   DoubleRegister const reg = (kind == MathMaxMinKind::kMin) ? d2 : d1;
 
   // Load the accumulator with the default return value (either -Infinity or
-  // +Infinity), with the tagged value in r3 and the double value in d1.
-  __ LoadRoot(r3, root_index);
-  __ LoadDouble(d1, FieldMemOperand(r3, HeapNumber::kValueOffset));
+  // +Infinity), with the tagged value in r7 and the double value in d1.
+  __ LoadRoot(r7, root_index);
+  __ LoadDouble(d1, FieldMemOperand(r7, HeapNumber::kValueOffset));
 
   // Setup state for loop
   // r4: address of arg[0] + kPointerSize
   // r5: number of slots to drop at exit (arguments + receiver)
-  __ ShiftLeftP(r4, r2, Operand(kPointerSizeLog2));
-  __ AddP(r4, sp, r4);
-  __ AddP(r5, r2, Operand(1));
+  __ AddP(r6, r2, Operand(1));
 
   Label done_loop, loop;
   __ bind(&loop);
   {
     // Check if all parameters done.
-    __ CmpLogicalP(r4, sp);
-    __ ble(&done_loop);
+    __ SubP(r2, Operand(1));
+    __ blt(&done_loop);
 
     // Load the next parameter tagged value into r2.
-    __ lay(r4, MemOperand(r4, -kPointerSize));
-    __ LoadP(r2, MemOperand(r4));
+    __ ShiftLeftP(r1, r2, Operand(kPointerSizeLog2));
+    __ LoadP(r4, MemOperand(sp, r1));
 
     // Load the double value of the parameter into d2, maybe converting the
-    // parameter to a number first using the ToNumberStub if necessary.
+    // parameter to a number first using the ToNumber builtin if necessary.
     Label convert, convert_smi, convert_number, done_convert;
     __ bind(&convert);
-    __ JumpIfSmi(r2, &convert_smi);
-    __ LoadP(r6, FieldMemOperand(r2, HeapObject::kMapOffset));
-    __ JumpIfRoot(r6, Heap::kHeapNumberMapRootIndex, &convert_number);
+    __ JumpIfSmi(r4, &convert_smi);
+    __ LoadP(r5, FieldMemOperand(r4, HeapObject::kMapOffset));
+    __ JumpIfRoot(r5, Heap::kHeapNumberMapRootIndex, &convert_number);
     {
-      // Parameter is not a Number, use the ToNumberStub to convert it.
-      FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
-      __ SmiTag(r5);
-      __ Push(r3, r4, r5);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
-      __ Pop(r3, r4, r5);
-      __ SmiUntag(r5);
+      // Parameter is not a Number, use the ToNumber builtin to convert it.
+      DCHECK(!FLAG_enable_embedded_constant_pool);
+      FrameScope scope(masm, StackFrame::MANUAL);
+      __ PushStandardFrame(r3);
+      __ SmiTag(r2);
+      __ SmiTag(r6);
+      __ Push(r2, r6, r7);
+      __ LoadRR(r2, r4);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
+      __ LoadRR(r4, r2);
+      __ Pop(r2, r6, r7);
       {
         // Restore the double accumulator value (d1).
         Label done_restore;
-        __ SmiToDouble(d1, r3);
-        __ JumpIfSmi(r3, &done_restore);
-        __ LoadDouble(d1, FieldMemOperand(r3, HeapNumber::kValueOffset));
+        __ SmiToDouble(d1, r7);
+        __ JumpIfSmi(r7, &done_restore);
+        __ LoadDouble(d1, FieldMemOperand(r7, HeapNumber::kValueOffset));
         __ bind(&done_restore);
       }
+      __ SmiUntag(r6);
+      __ SmiUntag(r2);
+      __ Pop(r14, fp, cp, r3);
     }
     __ b(&convert);
     __ bind(&convert_number);
-    __ LoadDouble(d2, FieldMemOperand(r2, HeapNumber::kValueOffset));
+    __ LoadDouble(d2, FieldMemOperand(r4, HeapNumber::kValueOffset));
     __ b(&done_convert);
     __ bind(&convert_smi);
-    __ SmiToDouble(d2, r2);
+    __ SmiToDouble(d2, r4);
     __ bind(&done_convert);
 
     // Perform the actual comparison with the accumulator value on the left hand
@@ -207,26 +196,26 @@
     __ b(CommuteCondition(cond_done), &compare_swap);
 
     // Left and right hand side are equal, check for -0 vs. +0.
-    __ TestDoubleIsMinusZero(reg, r6, r7);
+    __ TestDoubleIsMinusZero(reg, r1, r0);
     __ bne(&loop);
 
     // Update accumulator. Result is on the right hand side.
     __ bind(&compare_swap);
     __ ldr(d1, d2);
-    __ LoadRR(r3, r2);
+    __ LoadRR(r7, r4);
     __ b(&loop);
 
     // At least one side is NaN, which means that the result will be NaN too.
     // We still need to visit the rest of the arguments.
     __ bind(&compare_nan);
-    __ LoadRoot(r3, Heap::kNanValueRootIndex);
-    __ LoadDouble(d1, FieldMemOperand(r3, HeapNumber::kValueOffset));
+    __ LoadRoot(r7, Heap::kNanValueRootIndex);
+    __ LoadDouble(d1, FieldMemOperand(r7, HeapNumber::kValueOffset));
     __ b(&loop);
   }
 
   __ bind(&done_loop);
-  __ LoadRR(r2, r3);
-  __ Drop(r5);
+  __ LoadRR(r2, r7);
+  __ Drop(r6);
   __ Ret();
 }
 
@@ -254,8 +243,7 @@
   }
 
   // 2a. Convert the first argument to a number.
-  ToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
+  __ Jump(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
 
   // 2b. No arguments, return +0.
   __ bind(&no_arguments);
@@ -305,8 +293,7 @@
       FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
       __ Push(r3, r5);
       __ LoadRR(r2, r4);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
       __ LoadRR(r4, r2);
       __ Pop(r3, r5);
     }
@@ -596,15 +583,10 @@
     // r2: number of arguments
     // r3: constructor function
     // r5: new target
-    if (is_api_function) {
-      __ LoadP(cp, FieldMemOperand(r3, JSFunction::kContextOffset));
-      Handle<Code> code = masm->isolate()->builtins()->HandleApiCallConstruct();
-      __ Call(code, RelocInfo::CODE_TARGET);
-    } else {
-      ParameterCount actual(r2);
-      __ InvokeFunction(r3, r5, actual, CALL_FUNCTION,
-                        CheckDebugStepCallWrapper());
-    }
+
+    ParameterCount actual(r2);
+    __ InvokeFunction(r3, r5, actual, CALL_FUNCTION,
+                      CheckDebugStepCallWrapper());
 
     // Store offset of return address for deoptimizer.
     if (create_implicit_receiver && !is_api_function) {
@@ -693,6 +675,176 @@
   Generate_JSConstructStubHelper(masm, false, false, true);
 }
 
+// static
+void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r2 : the value to pass to the generator
+  //  -- r3 : the JSGeneratorObject to resume
+  //  -- r4 : the resume mode (tagged)
+  //  -- lr : return address
+  // -----------------------------------
+  __ AssertGeneratorObject(r3);
+
+  // Store input value into generator object.
+  __ StoreP(r2, FieldMemOperand(r3, JSGeneratorObject::kInputOrDebugPosOffset),
+            r0);
+  __ RecordWriteField(r3, JSGeneratorObject::kInputOrDebugPosOffset, r2, r5,
+                      kLRHasNotBeenSaved, kDontSaveFPRegs);
+
+  // Store resume mode into generator object.
+  __ StoreP(r4, FieldMemOperand(r3, JSGeneratorObject::kResumeModeOffset));
+
+  // Load suspended function and context.
+  __ LoadP(cp, FieldMemOperand(r3, JSGeneratorObject::kContextOffset));
+  __ LoadP(r6, FieldMemOperand(r3, JSGeneratorObject::kFunctionOffset));
+
+  // Flood function if we are stepping.
+  Label prepare_step_in_if_stepping, prepare_step_in_suspended_generator;
+  Label stepping_prepared;
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(masm->isolate());
+  STATIC_ASSERT(StepFrame > StepIn);
+  __ mov(ip, Operand(last_step_action));
+  __ LoadB(ip, MemOperand(ip));
+  __ CmpP(ip, Operand(StepIn));
+  __ bge(&prepare_step_in_if_stepping);
+
+  // Flood function if we need to continue stepping in the suspended generator.
+
+  ExternalReference debug_suspended_generator =
+      ExternalReference::debug_suspended_generator_address(masm->isolate());
+
+  __ mov(ip, Operand(debug_suspended_generator));
+  __ LoadP(ip, MemOperand(ip));
+  __ CmpP(ip, r3);
+  __ beq(&prepare_step_in_suspended_generator);
+  __ bind(&stepping_prepared);
+
+  // Push receiver.
+  __ LoadP(ip, FieldMemOperand(r3, JSGeneratorObject::kReceiverOffset));
+  __ Push(ip);
+
+  // ----------- S t a t e -------------
+  //  -- r3    : the JSGeneratorObject to resume
+  //  -- r4    : the resume mode (tagged)
+  //  -- r6    : generator function
+  //  -- cp    : generator context
+  //  -- lr    : return address
+  //  -- sp[0] : generator receiver
+  // -----------------------------------
+
+  // Push holes for arguments to generator function. Since the parser forced
+  // context allocation for any variables in generators, the actual argument
+  // values have already been copied into the context and these dummy values
+  // will never be used.
+  __ LoadP(r5, FieldMemOperand(r6, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadW(
+      r2, FieldMemOperand(r5, SharedFunctionInfo::kFormalParameterCountOffset));
+  {
+    Label loop, done_loop;
+    __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+#if V8_TARGET_ARCH_S390X
+    __ CmpP(r2, Operand::Zero());
+    __ beq(&done_loop);
+#else
+    __ SmiUntag(r2);
+    __ LoadAndTestP(r2, r2);
+    __ beq(&done_loop);
+#endif
+    __ LoadRR(r1, r2);
+    __ bind(&loop);
+    __ push(ip);
+    __ BranchOnCount(r1, &loop);
+    __ bind(&done_loop);
+  }
+
+  // Dispatch on the kind of generator object.
+  Label old_generator;
+  __ LoadP(r5, FieldMemOperand(r5, SharedFunctionInfo::kFunctionDataOffset));
+  __ CompareObjectType(r5, r5, r5, BYTECODE_ARRAY_TYPE);
+  __ bne(&old_generator, Label::kNear);
+
+  // New-style (ignition/turbofan) generator object
+  {
+    // We abuse new.target both to indicate that this is a resume call and to
+    // pass in the generator object.  In ordinary calls, new.target is always
+    // undefined because generator functions are non-constructable.
+    __ LoadRR(r5, r3);
+    __ LoadRR(r3, r6);
+    __ LoadP(ip, FieldMemOperand(r3, JSFunction::kCodeEntryOffset));
+    __ JumpToJSEntry(ip);
+  }
+  // Old-style (full-codegen) generator object
+  __ bind(&old_generator);
+  {
+    // Enter a new JavaScript frame, and initialize its slots as they were when
+    // the generator was suspended.
+    FrameScope scope(masm, StackFrame::MANUAL);
+    __ PushStandardFrame(r6);
+
+    // Restore the operand stack.
+    __ LoadP(r2, FieldMemOperand(r3, JSGeneratorObject::kOperandStackOffset));
+    __ LoadP(r5, FieldMemOperand(r2, FixedArray::kLengthOffset));
+    __ AddP(r2, r2,
+            Operand(FixedArray::kHeaderSize - kHeapObjectTag - kPointerSize));
+    {
+      Label loop, done_loop;
+      __ SmiUntag(r5);
+      __ LoadAndTestP(r5, r5);
+      __ beq(&done_loop);
+      __ LoadRR(r1, r5);
+      __ bind(&loop);
+      __ LoadP(ip, MemOperand(r2, kPointerSize));
+      __ la(r2, MemOperand(r2, kPointerSize));
+      __ Push(ip);
+      __ BranchOnCount(r1, &loop);
+      __ bind(&done_loop);
+    }
+
+    // Reset operand stack so we don't leak.
+    __ LoadRoot(ip, Heap::kEmptyFixedArrayRootIndex);
+    __ StoreP(ip, FieldMemOperand(r3, JSGeneratorObject::kOperandStackOffset),
+              r0);
+
+    // Resume the generator function at the continuation.
+    __ LoadP(r5, FieldMemOperand(r6, JSFunction::kSharedFunctionInfoOffset));
+    __ LoadP(r5, FieldMemOperand(r5, SharedFunctionInfo::kCodeOffset));
+    __ AddP(r5, r5, Operand(Code::kHeaderSize - kHeapObjectTag));
+    {
+      ConstantPoolUnavailableScope constant_pool_unavailable(masm);
+      __ LoadP(r4, FieldMemOperand(r3, JSGeneratorObject::kContinuationOffset));
+      __ SmiUntag(r4);
+      __ AddP(r5, r5, r4);
+      __ LoadSmiLiteral(r4,
+                        Smi::FromInt(JSGeneratorObject::kGeneratorExecuting));
+      __ StoreP(r4, FieldMemOperand(r3, JSGeneratorObject::kContinuationOffset),
+                r0);
+      __ LoadRR(r2, r3);  // Continuation expects generator object in r2.
+      __ Jump(r5);
+    }
+  }
+
+  __ bind(&prepare_step_in_if_stepping);
+  {
+    FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
+    __ Push(r3, r4, r6);
+    __ CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
+    __ Pop(r3, r4);
+    __ LoadP(r6, FieldMemOperand(r3, JSGeneratorObject::kFunctionOffset));
+  }
+  __ b(&stepping_prepared);
+
+  __ bind(&prepare_step_in_suspended_generator);
+  {
+    FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
+    __ Push(r3, r4);
+    __ CallRuntime(Runtime::kDebugPrepareStepInSuspendedGenerator);
+    __ Pop(r3, r4);
+    __ LoadP(r6, FieldMemOperand(r3, JSGeneratorObject::kFunctionOffset));
+  }
+  __ b(&stepping_prepared);
+}
+
 void Builtins::Generate_ConstructedNonConstructable(MacroAssembler* masm) {
   FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
   __ push(r3);
@@ -818,6 +970,21 @@
   Generate_JSEntryTrampolineHelper(masm, true);
 }
 
+static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch) {
+  Register args_count = scratch;
+
+  // Get the arguments + receiver count.
+  __ LoadP(args_count,
+           MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
+  __ LoadlW(args_count,
+            FieldMemOperand(args_count, BytecodeArray::kParameterSizeOffset));
+
+  // Leave the frame (also dropping the register file).
+  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+
+  __ AddP(sp, sp, args_count);
+}
+
 // Generate code for entering a JS function with the interpreter.
 // On entry to the function the receiver and arguments have been pushed on the
 // stack left to right.  The actual argument count matches the formal parameter
@@ -835,14 +1002,16 @@
 // The function builds an interpreter frame.  See InterpreterFrameConstants in
 // frames.h for its layout.
 void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
+  ProfileEntryHookStub::MaybeCallEntryHook(masm);
+
   // Open a frame scope to indicate that there is a frame on the stack.  The
   // MANUAL indicates that the scope shouldn't actually generate code to set up
   // the frame (that is done below).
   FrameScope frame_scope(masm, StackFrame::MANUAL);
   __ PushStandardFrame(r3);
 
-  // Get the bytecode array from the function object and load the pointer to the
-  // first entry into kInterpreterBytecodeRegister.
+  // Get the bytecode array from the function object (or from the DebugInfo if
+  // it is present) and load it into kInterpreterBytecodeArrayRegister.
   __ LoadP(r2, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
   Label array_done;
   Register debug_info = r4;
@@ -858,8 +1027,13 @@
            FieldMemOperand(debug_info, DebugInfo::kAbstractCodeIndex));
   __ bind(&array_done);
 
+  // Check function data field is actually a BytecodeArray object.
+  Label bytecode_array_not_present;
+  __ CompareRoot(kInterpreterBytecodeArrayRegister,
+                 Heap::kUndefinedValueRootIndex);
+  __ beq(&bytecode_array_not_present);
+
   if (FLAG_debug_code) {
-    // Check function data field is actually a BytecodeArray object.
     __ TestIfSmi(kInterpreterBytecodeArrayRegister);
     __ Assert(ne, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
     __ CompareObjectType(kInterpreterBytecodeArrayRegister, r2, no_reg,
@@ -867,9 +1041,13 @@
     __ Assert(eq, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
   }
 
-  // Push new.target, bytecode array and zero for bytecode array offset.
-  __ LoadImmP(r2, Operand::Zero());
-  __ Push(r5, kInterpreterBytecodeArrayRegister, r2);
+  // Load the initial bytecode offset.
+  __ mov(kInterpreterBytecodeOffsetRegister,
+         Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
+
+  // Push new.target, bytecode array and Smi tagged bytecode array offset.
+  __ SmiTag(r4, kInterpreterBytecodeOffsetRegister);
+  __ Push(r5, kInterpreterBytecodeArrayRegister, r4);
 
   // Allocate the local and temporary register file on the stack.
   {
@@ -901,18 +1079,8 @@
     __ bind(&no_args);
   }
 
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's prologue:
-  //  - Call ProfileEntryHookStub when isolate has a function_entry_hook.
-  //  - Code aging of the BytecodeArray object.
-
-  // Load accumulator, register file, bytecode offset, dispatch table into
-  // registers.
+  // Load accumulator and dispatch table into registers.
   __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
-  __ AddP(kInterpreterRegisterFileRegister, fp,
-          Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
-  __ mov(kInterpreterBytecodeOffsetRegister,
-         Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
   __ mov(kInterpreterDispatchTableRegister,
          Operand(ExternalReference::interpreter_dispatch_table_address(
              masm->isolate())));
@@ -922,31 +1090,49 @@
                            kInterpreterBytecodeOffsetRegister));
   __ ShiftLeftP(ip, r3, Operand(kPointerSizeLog2));
   __ LoadP(ip, MemOperand(kInterpreterDispatchTableRegister, ip));
-  // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
-  // and header removal.
-  __ AddP(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Call(ip);
 
-  // Even though the first bytecode handler was called, we will never return.
-  __ Abort(kUnexpectedReturnFromBytecodeHandler);
+  masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
+
+  // The return value is in r2.
+  LeaveInterpreterFrame(masm, r4);
+  __ Ret();
+
+  // If the bytecode array is no longer present, then the underlying function
+  // has been switched to a different kind of code and we heal the closure by
+  // switching the code entry field over to the new code object as well.
+  __ bind(&bytecode_array_not_present);
+  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+  __ LoadP(r6, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadP(r6, FieldMemOperand(r6, SharedFunctionInfo::kCodeOffset));
+  __ AddP(r6, r6, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ StoreP(r6, FieldMemOperand(r3, JSFunction::kCodeEntryOffset), r0);
+  __ RecordWriteCodeEntryField(r3, r6, r7);
+  __ JumpToJSEntry(r6);
 }
 
-void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's EmitReturnSequence.
-  //  - Supporting FLAG_trace for Runtime::TraceExit.
-  //  - Support profiler (specifically decrementing profiling_counter
-  //    appropriately and calling out to HandleInterrupts if necessary).
+void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) {
+  // Save the function and context for call to CompileBaseline.
+  __ LoadP(r3, MemOperand(fp, StandardFrameConstants::kFunctionOffset));
+  __ LoadP(kContextRegister,
+           MemOperand(fp, StandardFrameConstants::kContextOffset));
 
-  // The return value is in accumulator, which is already in r2.
+  // Leave the frame before recompiling for baseline so that we don't count as
+  // an activation on the stack.
+  LeaveInterpreterFrame(masm, r4);
 
-  // Leave the frame (also dropping the register file).
-  __ LeaveFrame(StackFrame::JAVA_SCRIPT);
+  {
+    FrameScope frame_scope(masm, StackFrame::INTERNAL);
+    // Push return value.
+    __ push(r2);
 
-  // Drop receiver + arguments and return.
-  __ LoadlW(r0, FieldMemOperand(kInterpreterBytecodeArrayRegister,
-                                BytecodeArray::kParameterSizeOffset));
-  __ AddP(sp, sp, r0);
+    // Push function as argument and compile for baseline.
+    __ push(r3);
+    __ CallRuntime(Runtime::kCompileBaseline);
+
+    // Restore return value.
+    __ pop(r2);
+  }
   __ Ret();
 }
 
@@ -1010,24 +1196,24 @@
   __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
 }
 
-static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
-  // Initialize register file register and dispatch table register.
-  __ AddP(kInterpreterRegisterFileRegister, fp,
-          Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
+void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
+  // Set the return address to the correct point in the interpreter entry
+  // trampoline.
+  Smi* interpreter_entry_return_pc_offset(
+      masm->isolate()->heap()->interpreter_entry_return_pc_offset());
+  DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
+  __ Move(r4, masm->isolate()->builtins()->InterpreterEntryTrampoline());
+  __ AddP(r14, r4, Operand(interpreter_entry_return_pc_offset->value() +
+                           Code::kHeaderSize - kHeapObjectTag));
+
+  // Initialize the dispatch table register.
   __ mov(kInterpreterDispatchTableRegister,
          Operand(ExternalReference::interpreter_dispatch_table_address(
              masm->isolate())));
 
-  // Get the context from the frame.
-  __ LoadP(kContextRegister,
-           MemOperand(kInterpreterRegisterFileRegister,
-                      InterpreterFrameConstants::kContextFromRegisterPointer));
-
   // Get the bytecode array pointer from the frame.
-  __ LoadP(
-      kInterpreterBytecodeArrayRegister,
-      MemOperand(kInterpreterRegisterFileRegister,
-                 InterpreterFrameConstants::kBytecodeArrayFromRegisterPointer));
+  __ LoadP(kInterpreterBytecodeArrayRegister,
+           MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
 
   if (FLAG_debug_code) {
     // Check function data field is actually a BytecodeArray object.
@@ -1040,9 +1226,7 @@
 
   // Get the target bytecode offset from the frame.
   __ LoadP(kInterpreterBytecodeOffsetRegister,
-           MemOperand(
-               kInterpreterRegisterFileRegister,
-               InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
+           MemOperand(fp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
   __ SmiUntag(kInterpreterBytecodeOffsetRegister);
 
   // Dispatch to the target bytecode.
@@ -1050,59 +1234,157 @@
                            kInterpreterBytecodeOffsetRegister));
   __ ShiftLeftP(ip, r3, Operand(kPointerSizeLog2));
   __ LoadP(ip, MemOperand(kInterpreterDispatchTableRegister, ip));
-  __ AddP(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Jump(ip);
 }
 
-static void Generate_InterpreterNotifyDeoptimizedHelper(
-    MacroAssembler* masm, Deoptimizer::BailoutType type) {
-  // Enter an internal frame.
-  {
-    FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
-
-    // Pass the deoptimization type to the runtime system.
-    __ LoadSmiLiteral(r3, Smi::FromInt(static_cast<int>(type)));
-    __ Push(r3);
-    __ CallRuntime(Runtime::kNotifyDeoptimized);
-    // Tear down internal frame.
-  }
-
-  // Drop state (we don't use these for interpreter deopts) and and pop the
-  // accumulator value into the accumulator register.
-  __ Drop(1);
-  __ Pop(kInterpreterAccumulatorRegister);
-
-  // Enter the bytecode dispatch.
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
-}
-
-void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
-}
-
-void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
-}
-
-void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
-  // Set the address of the interpreter entry trampoline as a return address.
-  // This simulates the initial call to bytecode handlers in interpreter entry
-  // trampoline. The return will never actually be taken, but our stack walker
-  // uses this address to determine whether a frame is interpreted.
-  __ mov(r14,
-         Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline()));
-
-  Generate_EnterBytecodeDispatch(masm);
-}
-
 void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r2 : argument count (preserved for callee)
+  //  -- r5 : new target (preserved for callee)
+  //  -- r3 : target function (preserved for callee)
+  // -----------------------------------
+  // First lookup code, maybe we don't need to compile!
+  Label gotta_call_runtime;
+  Label maybe_call_runtime;
+  Label try_shared;
+  Label loop_top, loop_bottom;
+
+  Register closure = r3;
+  Register map = r8;
+  Register index = r4;
+  __ LoadP(map,
+           FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadP(map,
+           FieldMemOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset));
+  __ LoadP(index, FieldMemOperand(map, FixedArray::kLengthOffset));
+  __ CmpSmiLiteral(index, Smi::FromInt(2), r0);
+  __ blt(&gotta_call_runtime);
+
+  // Find literals.
+  // r9 : native context
+  // r4  : length / index
+  // r8  : optimized code map
+  // r5  : new target
+  // r3  : closure
+  Register native_context = r9;
+  __ LoadP(native_context, NativeContextMemOperand());
+
+  __ bind(&loop_top);
+  Register temp = r1;
+  Register array_pointer = r7;
+
+  // Does the native context match?
+  __ SmiToPtrArrayOffset(array_pointer, index);
+  __ AddP(array_pointer, map, array_pointer);
+  __ LoadP(temp, FieldMemOperand(array_pointer,
+                                 SharedFunctionInfo::kOffsetToPreviousContext));
+  __ LoadP(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
+  __ CmpP(temp, native_context);
+  __ bne(&loop_bottom, Label::kNear);
+  // OSR id set to none?
+  __ LoadP(temp,
+           FieldMemOperand(array_pointer,
+                           SharedFunctionInfo::kOffsetToPreviousOsrAstId));
+  const int bailout_id = BailoutId::None().ToInt();
+  __ CmpSmiLiteral(temp, Smi::FromInt(bailout_id), r0);
+  __ bne(&loop_bottom, Label::kNear);
+  // Literals available?
+  __ LoadP(temp,
+           FieldMemOperand(array_pointer,
+                           SharedFunctionInfo::kOffsetToPreviousLiterals));
+  __ LoadP(temp, FieldMemOperand(temp, WeakCell::kValueOffset));
+  __ JumpIfSmi(temp, &gotta_call_runtime);
+
+  // Save the literals in the closure.
+  __ StoreP(temp, FieldMemOperand(closure, JSFunction::kLiteralsOffset), r0);
+  __ RecordWriteField(closure, JSFunction::kLiteralsOffset, temp, r6,
+                      kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+
+  // Code available?
+  Register entry = r6;
+  __ LoadP(entry,
+           FieldMemOperand(array_pointer,
+                           SharedFunctionInfo::kOffsetToPreviousCachedCode));
+  __ LoadP(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &maybe_call_runtime);
+
+  // Found literals and code. Get them into the closure and return.
+  // Store code entry in the closure.
+  __ AddP(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+
+  Label install_optimized_code_and_tailcall;
+  __ bind(&install_optimized_code_and_tailcall);
+  __ StoreP(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset), r0);
+  __ RecordWriteCodeEntryField(closure, entry, r7);
+
+  // Link the closure into the optimized function list.
+  // r6 : code entry
+  // r9: native context
+  // r3 : closure
+  __ LoadP(
+      r7, ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
+  __ StoreP(r7, FieldMemOperand(closure, JSFunction::kNextFunctionLinkOffset),
+            r0);
+  __ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, r7, temp,
+                      kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  const int function_list_offset =
+      Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
+  __ StoreP(
+      closure,
+      ContextMemOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST), r0);
+  // Save closure before the write barrier.
+  __ LoadRR(r7, closure);
+  __ RecordWriteContextSlot(native_context, function_list_offset, r7, temp,
+                            kLRHasNotBeenSaved, kDontSaveFPRegs);
+  __ JumpToJSEntry(entry);
+
+  __ bind(&loop_bottom);
+  __ SubSmiLiteral(index, index, Smi::FromInt(SharedFunctionInfo::kEntryLength),
+                   r0);
+  __ CmpSmiLiteral(index, Smi::FromInt(1), r0);
+  __ bgt(&loop_top);
+
+  // We found neither literals nor code.
+  __ b(&gotta_call_runtime);
+
+  __ bind(&maybe_call_runtime);
+
+  // Last possibility. Check the context free optimized code map entry.
+  __ LoadP(entry,
+           FieldMemOperand(map, FixedArray::kHeaderSize +
+                                    SharedFunctionInfo::kSharedCodeIndex));
+  __ LoadP(entry, FieldMemOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &try_shared);
+
+  // Store code entry in the closure.
+  __ AddP(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ b(&install_optimized_code_and_tailcall);
+
+  __ bind(&try_shared);
+  // Is the full code valid?
+  __ LoadP(entry,
+           FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadP(entry, FieldMemOperand(entry, SharedFunctionInfo::kCodeOffset));
+  __ LoadlW(r7, FieldMemOperand(entry, Code::kFlagsOffset));
+  __ DecodeField<Code::KindField>(r7);
+  __ CmpP(r7, Operand(Code::BUILTIN));
+  __ beq(&gotta_call_runtime);
+  // Yes, install the full code.
+  __ AddP(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ StoreP(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset), r0);
+  __ RecordWriteCodeEntryField(closure, entry, r7);
+  __ JumpToJSEntry(entry);
+
+  __ bind(&gotta_call_runtime);
   GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
 }
 
+void Builtins::Generate_CompileBaseline(MacroAssembler* masm) {
+  GenerateTailCallToReturnedCode(masm, Runtime::kCompileBaseline);
+}
+
 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
   GenerateTailCallToReturnedCode(masm,
                                  Runtime::kCompileOptimized_NotConcurrent);
@@ -1242,14 +1524,19 @@
   __ SmiUntag(r8);
   // Switch on the state.
   Label with_tos_register, unknown_state;
-  __ CmpP(r8, Operand(FullCodeGenerator::NO_REGISTERS));
+  __ CmpP(
+      r8,
+      Operand(static_cast<intptr_t>(Deoptimizer::BailoutState::NO_REGISTERS)));
   __ bne(&with_tos_register);
   __ la(sp, MemOperand(sp, 1 * kPointerSize));  // Remove state.
   __ Ret();
 
   __ bind(&with_tos_register);
+  DCHECK_EQ(kInterpreterAccumulatorRegister.code(), r2.code());
   __ LoadP(r2, MemOperand(sp, 1 * kPointerSize));
-  __ CmpP(r8, Operand(FullCodeGenerator::TOS_REG));
+  __ CmpP(
+      r8,
+      Operand(static_cast<intptr_t>(Deoptimizer::BailoutState::TOS_REGISTER)));
   __ bne(&unknown_state);
   __ la(sp, MemOperand(sp, 2 * kPointerSize));  // Remove state.
   __ Ret();
@@ -1414,6 +1701,10 @@
 void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
                                                int field_index) {
   // ----------- S t a t e -------------
+  //  -- r2    : number of arguments
+  //  -- r3    : function
+  //  -- cp    : context
+
   //  -- lr    : return address
   //  -- sp[0] : receiver
   // -----------------------------------
@@ -1423,7 +1714,7 @@
   {
     __ Pop(r2);
     __ JumpIfSmi(r2, &receiver_not_date);
-    __ CompareObjectType(r2, r3, r4, JS_DATE_TYPE);
+    __ CompareObjectType(r2, r4, r5, JS_DATE_TYPE);
     __ bne(&receiver_not_date);
   }
 
@@ -1453,29 +1744,14 @@
 
   // 3. Raise a TypeError if the receiver is not a date.
   __ bind(&receiver_not_date);
-  __ TailCallRuntime(Runtime::kThrowNotDateError);
-}
-
-// static
-void Builtins::Generate_FunctionHasInstance(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- r2    : argc
-  //  -- sp[0] : first argument (left-hand side)
-  //  -- sp[4] : receiver (right-hand side)
-  // -----------------------------------
-
   {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-    __ LoadP(InstanceOfDescriptor::LeftRegister(),
-             MemOperand(fp, 2 * kPointerSize));  // Load left-hand side.
-    __ LoadP(InstanceOfDescriptor::RightRegister(),
-             MemOperand(fp, 3 * kPointerSize));  // Load right-hand side.
-    InstanceOfStub stub(masm->isolate(), true);
-    __ CallStub(&stub);
+    FrameScope scope(masm, StackFrame::MANUAL);
+    __ push(r2);
+    __ PushStandardFrame(r3);
+    __ LoadSmiLiteral(r6, Smi::FromInt(0));
+    __ push(r6);
+    __ CallRuntime(Runtime::kThrowNotDateError);
   }
-
-  // Pop the argument and the receiver.
-  __ Ret(2);
 }
 
 // static
@@ -2416,6 +2692,101 @@
           RelocInfo::CODE_TARGET);
 }
 
+// static
+void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r3 : requested object size (untagged)
+  //  -- lr : return address
+  // -----------------------------------
+  __ SmiTag(r3);
+  __ Push(r3);
+  __ LoadSmiLiteral(cp, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInNewSpace);
+}
+
+// static
+void Builtins::Generate_AllocateInOldSpace(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r3 : requested object size (untagged)
+  //  -- lr : return address
+  // -----------------------------------
+  __ SmiTag(r3);
+  __ LoadSmiLiteral(r4, Smi::FromInt(AllocateTargetSpace::encode(OLD_SPACE)));
+  __ Push(r3, r4);
+  __ LoadSmiLiteral(cp, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInTargetSpace);
+}
+
+// static
+void Builtins::Generate_StringToNumber(MacroAssembler* masm) {
+  // The StringToNumber stub takes one argument in r2.
+  __ AssertString(r2);
+
+  // Check if string has a cached array index.
+  Label runtime;
+  __ LoadlW(r4, FieldMemOperand(r2, String::kHashFieldOffset));
+  __ And(r0, r4, Operand(String::kContainsCachedArrayIndexMask));
+  __ bne(&runtime);
+  __ IndexFromHash(r4, r2);
+  __ Ret();
+
+  __ bind(&runtime);
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ push(r2);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kStringToNumber);
+  }
+  __ Ret();
+}
+
+// static
+void Builtins::Generate_ToNumber(MacroAssembler* masm) {
+  // The ToNumber stub takes one argument in r2.
+  STATIC_ASSERT(kSmiTag == 0);
+  __ TestIfSmi(r2);
+  __ Ret(eq);
+
+  __ CompareObjectType(r2, r3, r3, HEAP_NUMBER_TYPE);
+  // r2: receiver
+  // r3: receiver instance type
+  __ Ret(eq);
+
+  __ Jump(masm->isolate()->builtins()->NonNumberToNumber(),
+          RelocInfo::CODE_TARGET);
+}
+
+// static
+void Builtins::Generate_NonNumberToNumber(MacroAssembler* masm) {
+  // The NonNumberToNumber stub takes one argument in r2.
+  __ AssertNotNumber(r2);
+
+  __ CompareObjectType(r2, r3, r3, FIRST_NONSTRING_TYPE);
+  // r2: receiver
+  // r3: receiver instance type
+  __ Jump(masm->isolate()->builtins()->StringToNumber(), RelocInfo::CODE_TARGET,
+          lt);
+
+  Label not_oddball;
+  __ CmpP(r3, Operand(ODDBALL_TYPE));
+  __ bne(&not_oddball);
+  __ LoadP(r2, FieldMemOperand(r2, Oddball::kToNumberOffset));
+  __ Ret();
+  __ bind(&not_oddball);
+
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ push(r2);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kToNumber);
+  }
+  __ Ret();
+}
+
 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
   // ----------- S t a t e -------------
   //  -- r2 : actual number of arguments
diff --git a/src/s390/code-stubs-s390.cc b/src/s390/code-stubs-s390.cc
index 1c7d27b..6098c37 100644
--- a/src/s390/code-stubs-s390.cc
+++ b/src/s390/code-stubs-s390.cc
@@ -21,54 +21,15 @@
 namespace v8 {
 namespace internal {
 
-static void InitializeArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  Address deopt_handler =
-      Runtime::FunctionForId(Runtime::kArrayConstructor)->entry;
+#define __ ACCESS_MASM(masm)
 
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(r2, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-static void InitializeInternalArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  Address deopt_handler =
-      Runtime::FunctionForId(Runtime::kInternalArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(r2, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-void ArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 0);
-}
-
-void ArraySingleArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 1);
-}
-
-void ArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-void InternalArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0);
+void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
+  __ ShiftLeftP(r1, r2, Operand(kPointerSizeLog2));
+  __ StoreP(r3, MemOperand(sp, r1));
+  __ push(r3);
+  __ push(r4);
+  __ AddP(r2, r2, Operand(3));
+  __ TailCallRuntime(Runtime::kNewArray);
 }
 
 void FastArrayPushStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
@@ -76,18 +37,12 @@
   descriptor->Initialize(r2, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-void InternalArraySingleArgumentConstructorStub::InitializeDescriptor(
+void FastFunctionBindStub::InitializeDescriptor(
     CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1);
+  Address deopt_handler = Runtime::FunctionForId(Runtime::kFunctionBind)->entry;
+  descriptor->Initialize(r2, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-void InternalArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-#define __ ACCESS_MASM(masm)
-
 static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
                                           Condition cond);
 static void EmitSmiNonsmiComparison(MacroAssembler* masm, Register lhs,
@@ -966,7 +921,7 @@
   CEntryStub::GenerateAheadOfTime(isolate);
   StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
   StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
-  ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
+  CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate);
   CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
   CreateWeakCellStub::GenerateAheadOfTime(isolate);
   BinaryOpICStub::GenerateAheadOfTime(isolate);
@@ -1080,7 +1035,6 @@
     // zLinux ABI requires caller's frame to have sufficient space for callee
     // preserved regsiter save area.
     // __ lay(sp, MemOperand(sp, -kCalleeRegisterSaveAreaSize));
-    __ positions_recorder()->WriteRecordedPositions();
     __ b(target);
     __ bind(&return_label);
     // __ la(sp, MemOperand(sp, +kCalleeRegisterSaveAreaSize));
@@ -1377,125 +1331,6 @@
   __ b(r14);
 }
 
-void InstanceOfStub::Generate(MacroAssembler* masm) {
-  Register const object = r3;              // Object (lhs).
-  Register const function = r2;            // Function (rhs).
-  Register const object_map = r4;          // Map of {object}.
-  Register const function_map = r5;        // Map of {function}.
-  Register const function_prototype = r6;  // Prototype of {function}.
-  Register const scratch = r7;
-
-  DCHECK(object.is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(function.is(InstanceOfDescriptor::RightRegister()));
-
-  // Check if {object} is a smi.
-  Label object_is_smi;
-  __ JumpIfSmi(object, &object_is_smi);
-
-  // Lookup the {function} and the {object} map in the global instanceof cache.
-  // Note: This is safe because we clear the global instanceof cache whenever
-  // we change the prototype of any object.
-  Label fast_case, slow_case;
-  __ LoadP(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
-  __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
-  __ bne(&fast_case);
-  __ CompareRoot(object_map, Heap::kInstanceofCacheMapRootIndex);
-  __ bne(&fast_case);
-  __ LoadRoot(r2, Heap::kInstanceofCacheAnswerRootIndex);
-  __ Ret();
-
-  // If {object} is a smi we can safely return false if {function} is a JS
-  // function, otherwise we have to miss to the runtime and throw an exception.
-  __ bind(&object_is_smi);
-  __ JumpIfSmi(function, &slow_case);
-  __ CompareObjectType(function, function_map, scratch, JS_FUNCTION_TYPE);
-  __ bne(&slow_case);
-  __ LoadRoot(r2, Heap::kFalseValueRootIndex);
-  __ Ret();
-
-  // Fast-case: The {function} must be a valid JSFunction.
-  __ bind(&fast_case);
-  __ JumpIfSmi(function, &slow_case);
-  __ CompareObjectType(function, function_map, scratch, JS_FUNCTION_TYPE);
-  __ bne(&slow_case);
-
-  // Go to the runtime if the function is not a constructor.
-  __ LoadlB(scratch, FieldMemOperand(function_map, Map::kBitFieldOffset));
-  __ TestBit(scratch, Map::kIsConstructor, r0);
-  __ beq(&slow_case);
-
-  // Ensure that {function} has an instance prototype.
-  __ TestBit(scratch, Map::kHasNonInstancePrototype, r0);
-  __ bne(&slow_case);
-
-  // Get the "prototype" (or initial map) of the {function}.
-  __ LoadP(function_prototype,
-           FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
-  __ AssertNotSmi(function_prototype);
-
-  // Resolve the prototype if the {function} has an initial map.  Afterwards the
-  // {function_prototype} will be either the JSReceiver prototype object or the
-  // hole value, which means that no instances of the {function} were created so
-  // far and hence we should return false.
-  Label function_prototype_valid;
-  __ CompareObjectType(function_prototype, scratch, scratch, MAP_TYPE);
-  __ bne(&function_prototype_valid);
-  __ LoadP(function_prototype,
-           FieldMemOperand(function_prototype, Map::kPrototypeOffset));
-  __ bind(&function_prototype_valid);
-  __ AssertNotSmi(function_prototype);
-
-  // Update the global instanceof cache with the current {object} map and
-  // {function}.  The cached answer will be set when it is known below.
-  __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
-  __ StoreRoot(object_map, Heap::kInstanceofCacheMapRootIndex);
-
-  // Loop through the prototype chain looking for the {function} prototype.
-  // Assume true, and change to false if not found.
-  Register const object_instance_type = function_map;
-  Register const map_bit_field = function_map;
-  Register const null = scratch;
-  Register const result = r2;
-
-  Label done, loop, fast_runtime_fallback;
-  __ LoadRoot(result, Heap::kTrueValueRootIndex);
-  __ LoadRoot(null, Heap::kNullValueRootIndex);
-  __ bind(&loop);
-
-  // Check if the object needs to be access checked.
-  __ LoadlB(map_bit_field, FieldMemOperand(object_map, Map::kBitFieldOffset));
-  __ TestBit(map_bit_field, Map::kIsAccessCheckNeeded, r0);
-  __ bne(&fast_runtime_fallback);
-  // Check if the current object is a Proxy.
-  __ CompareInstanceType(object_map, object_instance_type, JS_PROXY_TYPE);
-  __ beq(&fast_runtime_fallback);
-
-  __ LoadP(object, FieldMemOperand(object_map, Map::kPrototypeOffset));
-  __ CmpP(object, function_prototype);
-  __ beq(&done);
-  __ CmpP(object, null);
-  __ LoadP(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
-  __ bne(&loop);
-  __ LoadRoot(result, Heap::kFalseValueRootIndex);
-  __ bind(&done);
-  __ StoreRoot(result, Heap::kInstanceofCacheAnswerRootIndex);
-  __ Ret();
-
-  // Found Proxy or access check needed: Call the runtime
-  __ bind(&fast_runtime_fallback);
-  __ Push(object, function_prototype);
-  // Invalidate the instanceof cache.
-  __ LoadSmiLiteral(scratch, Smi::FromInt(0));
-  __ StoreRoot(scratch, Heap::kInstanceofCacheFunctionRootIndex);
-  __ TailCallRuntime(Runtime::kHasInPrototypeChain);
-
-  // Slow-case: Call the %InstanceOf runtime function.
-  __ bind(&slow_case);
-  __ Push(object, function);
-  __ TailCallRuntime(is_es6_instanceof() ? Runtime::kOrdinaryHasInstance
-                                         : Runtime::kInstanceOf);
-}
-
 void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
   Label miss;
   Register receiver = LoadDescriptor::ReceiverRegister();
@@ -1530,7 +1365,6 @@
                                           &miss,  // When not a string.
                                           &miss,  // When not a number.
                                           &miss,  // When index out of range.
-                                          STRING_INDEX_IS_ARRAY_INDEX,
                                           RECEIVER_IS_STRING);
   char_at_generator.GenerateFast(masm);
   __ Ret();
@@ -1993,12 +1827,15 @@
   // r4 : feedback vector
   // r5 : slot in feedback vector (Smi)
   Label initialize, done, miss, megamorphic, not_array_function;
+  Label done_initialize_count, done_increment_count;
 
   DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()),
             masm->isolate()->heap()->megamorphic_symbol());
   DCHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(masm->isolate()),
             masm->isolate()->heap()->uninitialized_symbol());
 
+  const int count_offset = FixedArray::kHeaderSize + kPointerSize;
+
   // Load the cache state into r7.
   __ SmiToPtrArrayOffset(r7, r5);
   __ AddP(r7, r4, r7);
@@ -2013,9 +1850,9 @@
   Register weak_value = r9;
   __ LoadP(weak_value, FieldMemOperand(r7, WeakCell::kValueOffset));
   __ CmpP(r3, weak_value);
-  __ beq(&done);
+  __ beq(&done_increment_count, Label::kNear);
   __ CompareRoot(r7, Heap::kmegamorphic_symbolRootIndex);
-  __ beq(&done);
+  __ beq(&done, Label::kNear);
   __ LoadP(feedback_map, FieldMemOperand(r7, HeapObject::kMapOffset));
   __ CompareRoot(feedback_map, Heap::kWeakCellMapRootIndex);
   __ bne(&check_allocation_site);
@@ -2036,7 +1873,7 @@
   __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r7);
   __ CmpP(r3, r7);
   __ bne(&megamorphic);
-  __ b(&done);
+  __ b(&done_increment_count, Label::kNear);
 
   __ bind(&miss);
 
@@ -2066,12 +1903,31 @@
   // slot.
   CreateAllocationSiteStub create_stub(masm->isolate());
   CallStubInRecordCallTarget(masm, &create_stub);
-  __ b(&done);
+  __ b(&done_initialize_count, Label::kNear);
 
   __ bind(&not_array_function);
 
   CreateWeakCellStub weak_cell_stub(masm->isolate());
   CallStubInRecordCallTarget(masm, &weak_cell_stub);
+
+  __ bind(&done_initialize_count);
+  // Initialize the call counter.
+  __ LoadSmiLiteral(r7, Smi::FromInt(1));
+  __ SmiToPtrArrayOffset(r6, r5);
+  __ AddP(r6, r4, r6);
+  __ StoreP(r7, FieldMemOperand(r6, count_offset), r0);
+  __ b(&done, Label::kNear);
+
+  __ bind(&done_increment_count);
+
+  // Increment the call count for monomorphic function calls.
+  __ SmiToPtrArrayOffset(r7, r5);
+  __ AddP(r7, r4, r7);
+
+  __ LoadP(r6, FieldMemOperand(r7, count_offset));
+  __ AddSmiLiteral(r6, r6, Smi::FromInt(1), r0);
+  __ StoreP(r6, FieldMemOperand(r7, count_offset), r0);
+
   __ bind(&done);
 }
 
@@ -2134,7 +1990,7 @@
   __ SmiToPtrArrayOffset(r7, r5);
   __ AddP(r4, r4, r7);
   __ LoadP(r5, FieldMemOperand(r4, count_offset));
-  __ AddSmiLiteral(r5, r5, Smi::FromInt(CallICNexus::kCallCountIncrement), r0);
+  __ AddSmiLiteral(r5, r5, Smi::FromInt(1), r0);
   __ StoreP(r5, FieldMemOperand(r4, count_offset), r0);
 
   __ LoadRR(r4, r6);
@@ -2181,7 +2037,7 @@
   // Increment the call count for monomorphic function calls.
   const int count_offset = FixedArray::kHeaderSize + kPointerSize;
   __ LoadP(r5, FieldMemOperand(r8, count_offset));
-  __ AddSmiLiteral(r5, r5, Smi::FromInt(CallICNexus::kCallCountIncrement), r0);
+  __ AddSmiLiteral(r5, r5, Smi::FromInt(1), r0);
   __ StoreP(r5, FieldMemOperand(r8, count_offset), r0);
 
   __ bind(&call_function);
@@ -2251,7 +2107,7 @@
   __ bne(&miss);
 
   // Initialize the call counter.
-  __ LoadSmiLiteral(r7, Smi::FromInt(CallICNexus::kCallCountIncrement));
+  __ LoadSmiLiteral(r7, Smi::FromInt(1));
   __ StoreP(r7, FieldMemOperand(r8, count_offset), r0);
 
   // Store the function. Use a stub since we need a frame for allocation.
@@ -2340,13 +2196,7 @@
     // index_ is consumed by runtime conversion function.
     __ Push(object_, index_);
   }
-  if (index_flags_ == STRING_INDEX_IS_NUMBER) {
-    __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero);
-  } else {
-    DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
-    // NumberToSmi discards numbers that are not exact integers.
-    __ CallRuntime(Runtime::kNumberToSmi);
-  }
+  __ CallRuntime(Runtime::kNumberToSmi);
   // Save the conversion result before the pop instructions below
   // have a chance to overwrite it.
   __ Move(index_, r2);
@@ -2677,69 +2527,13 @@
   // r5: from index (untagged)
   __ SmiTag(r5, r5);
   StringCharAtGenerator generator(r2, r5, r4, r2, &runtime, &runtime, &runtime,
-                                  STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING);
+                                  RECEIVER_IS_STRING);
   generator.GenerateFast(masm);
   __ Drop(3);
   __ Ret();
   generator.SkipSlow(masm, &runtime);
 }
 
-void ToNumberStub::Generate(MacroAssembler* masm) {
-  // The ToNumber stub takes one argument in r2.
-  STATIC_ASSERT(kSmiTag == 0);
-  __ TestIfSmi(r2);
-  __ Ret(eq);
-
-  __ CompareObjectType(r2, r3, r3, HEAP_NUMBER_TYPE);
-  // r2: receiver
-  // r3: receiver instance type
-  Label not_heap_number;
-  __ bne(&not_heap_number);
-  __ Ret();
-  __ bind(&not_heap_number);
-
-  NonNumberToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
-}
-
-void NonNumberToNumberStub::Generate(MacroAssembler* masm) {
-  // The NonNumberToNumber stub takes one argument in r2.
-  __ AssertNotNumber(r2);
-
-  __ CompareObjectType(r2, r3, r3, FIRST_NONSTRING_TYPE);
-  // r2: receiver
-  // r3: receiver instance type
-  StringToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub, lt);
-
-  Label not_oddball;
-  __ CmpP(r3, Operand(ODDBALL_TYPE));
-  __ bne(&not_oddball, Label::kNear);
-  __ LoadP(r2, FieldMemOperand(r2, Oddball::kToNumberOffset));
-  __ b(r14);
-  __ bind(&not_oddball);
-
-  __ push(r2);  // Push argument.
-  __ TailCallRuntime(Runtime::kToNumber);
-}
-
-void StringToNumberStub::Generate(MacroAssembler* masm) {
-  // The StringToNumber stub takes one argument in r2.
-  __ AssertString(r2);
-
-  // Check if string has a cached array index.
-  Label runtime;
-  __ LoadlW(r4, FieldMemOperand(r2, String::kHashFieldOffset));
-  __ And(r0, r4, Operand(String::kContainsCachedArrayIndexMask));
-  __ bne(&runtime);
-  __ IndexFromHash(r4, r2);
-  __ Ret();
-
-  __ bind(&runtime);
-  __ push(r2);  // Push argument.
-  __ TailCallRuntime(Runtime::kStringToNumber);
-}
-
 void ToStringStub::Generate(MacroAssembler* masm) {
   // The ToString stub takes one argument in r2.
   Label done;
@@ -2917,7 +2711,7 @@
   // Load r4 with the allocation site.  We stick an undefined dummy value here
   // and replace it with the real allocation site later when we instantiate this
   // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate().
-  __ Move(r4, handle(isolate()->heap()->undefined_value()));
+  __ Move(r4, isolate()->factory()->undefined_value());
 
   // Make sure that we actually patched the allocation site.
   if (FLAG_debug_code) {
@@ -3299,10 +3093,6 @@
 void DirectCEntryStub::Generate(MacroAssembler* masm) {
   __ CleanseP(r14);
 
-  // Statement positions are expected to be recorded when the target
-  // address is loaded.
-  __ positions_recorder()->WriteRecordedPositions();
-
   __ b(ip);  // Callee will return to R14 directly
 }
 
@@ -3756,13 +3546,13 @@
 
 void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  LoadICStub stub(isolate(), state());
+  LoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate(), state());
+  KeyedLoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -3898,8 +3688,8 @@
   __ bind(&not_array);
   __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
   __ bne(&miss);
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::LOAD_IC, code_flags,
                                                receiver, name, feedback,
                                                receiver_map, scratch1, r9);
@@ -4033,8 +3823,8 @@
   __ bind(&not_array);
   __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
   __ bne(&miss);
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
   masm->isolate()->stub_cache()->GenerateProbe(
       masm, Code::STORE_IC, code_flags, receiver, key, feedback, receiver_map,
       scratch1, scratch2);
@@ -4402,17 +4192,11 @@
   }
 }
 
-void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
+void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
   ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
       isolate);
-  ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
-      isolate);
-  ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
-      isolate);
-}
-
-void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
-    Isolate* isolate) {
+  ArrayNArgumentsConstructorStub stub(isolate);
+  stub.GetCode();
   ElementsKind kinds[2] = {FAST_ELEMENTS, FAST_HOLEY_ELEMENTS};
   for (int i = 0; i < 2; i++) {
     // For internal arrays we only need a few things
@@ -4420,8 +4204,6 @@
     stubh1.GetCode();
     InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]);
     stubh2.GetCode();
-    InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]);
-    stubh3.GetCode();
   }
 }
 
@@ -4439,13 +4221,15 @@
     CreateArrayDispatchOneArgument(masm, mode);
 
     __ bind(&not_one_case);
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else if (argument_count() == NONE) {
     CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
   } else if (argument_count() == ONE) {
     CreateArrayDispatchOneArgument(masm, mode);
   } else if (argument_count() == MORE_THAN_ONE) {
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else {
     UNREACHABLE();
   }
@@ -4527,7 +4311,7 @@
   InternalArrayNoArgumentConstructorStub stub0(isolate(), kind);
   __ TailCallStub(&stub0, lt);
 
-  InternalArrayNArgumentsConstructorStub stubN(isolate(), kind);
+  ArrayNArgumentsConstructorStub stubN(isolate());
   __ TailCallStub(&stubN, gt);
 
   if (IsFastPackedElementsKind(kind)) {
@@ -4625,15 +4409,15 @@
   __ bind(&done_allocate);
 
   // Initialize the JSObject fields.
-  __ StoreP(r4, MemOperand(r2, JSObject::kMapOffset));
+  __ StoreP(r4, FieldMemOperand(r2, JSObject::kMapOffset));
   __ LoadRoot(r5, Heap::kEmptyFixedArrayRootIndex);
-  __ StoreP(r5, MemOperand(r2, JSObject::kPropertiesOffset));
-  __ StoreP(r5, MemOperand(r2, JSObject::kElementsOffset));
+  __ StoreP(r5, FieldMemOperand(r2, JSObject::kPropertiesOffset));
+  __ StoreP(r5, FieldMemOperand(r2, JSObject::kElementsOffset));
   STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize);
-  __ AddP(r3, r2, Operand(JSObject::kHeaderSize));
+  __ AddP(r3, r2, Operand(JSObject::kHeaderSize - kHeapObjectTag));
 
   // ----------- S t a t e -------------
-  //  -- r2 : result (untagged)
+  //  -- r2 : result (tagged)
   //  -- r3 : result fields (untagged)
   //  -- r7 : result end (untagged)
   //  -- r4 : initial map
@@ -4653,8 +4437,6 @@
     // Initialize all in-object fields with undefined.
     __ InitializeFieldsWithFiller(r3, r7, r8);
 
-    // Add the object tag to make the JSObject real.
-    __ AddP(r2, r2, Operand(kHeapObjectTag));
     __ Ret();
   }
   __ bind(&slack_tracking);
@@ -4674,9 +4456,6 @@
     __ LoadRoot(r8, Heap::kOnePointerFillerMapRootIndex);
     __ InitializeFieldsWithFiller(r3, r7, r8);
 
-    // Add the object tag to make the JSObject real.
-    __ AddP(r2, r2, Operand(kHeapObjectTag));
-
     // Check if we can finalize the instance size.
     __ CmpP(r9, Operand(Map::kSlackTrackingCounterEnd));
     __ Ret(ne);
@@ -4702,10 +4481,10 @@
     __ CallRuntime(Runtime::kAllocateInNewSpace);
     __ Pop(r4);
   }
-  __ SubP(r2, r2, Operand(kHeapObjectTag));
   __ LoadlB(r7, FieldMemOperand(r4, Map::kInstanceSizeOffset));
   __ ShiftLeftP(r7, r7, Operand(kPointerSizeLog2));
   __ AddP(r7, r2, r7);
+  __ SubP(r7, r7, Operand(kHeapObjectTag));
   __ b(&done_allocate);
 
   // Fall back to %NewObject.
@@ -4723,20 +4502,20 @@
   // -----------------------------------
   __ AssertFunction(r3);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make r4 point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ LoadRR(r4, fp);
-    __ b(&loop_entry);
-    __ bind(&loop);
+  // Make r4 point to the JavaScript frame.
+  __ LoadRR(r4, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ LoadP(r4, MemOperand(r4, StandardFrameConstants::kCallerFPOffset));
-    __ bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ LoadP(ip, MemOperand(r4, StandardFrameConstants::kFunctionOffset));
     __ CmpP(ip, r3);
-    __ bne(&loop);
+    __ b(&ok, Label::kNear);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
   }
 
   // Check if we have rest parameters (only possible if we have an
@@ -4751,13 +4530,13 @@
   // specified by the function's internal formal parameter count.
   Label rest_parameters;
   __ LoadP(r2, MemOperand(r4, ArgumentsAdaptorFrameConstants::kLengthOffset));
-  __ LoadP(r3, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadP(r5, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
   __ LoadW(
-      r3, FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
+      r5, FieldMemOperand(r5, SharedFunctionInfo::kFormalParameterCountOffset));
 #if V8_TARGET_ARCH_S390X
-  __ SmiTag(r3);
+  __ SmiTag(r5);
 #endif
-  __ SubP(r2, r2, r3);
+  __ SubP(r2, r2, r5);
   __ bgt(&rest_parameters);
 
   // Return an empty rest parameter array.
@@ -4770,7 +4549,7 @@
 
     // Allocate an empty rest parameter array.
     Label allocate, done_allocate;
-    __ Allocate(JSArray::kSize, r2, r3, r4, &allocate, TAG_OBJECT);
+    __ Allocate(JSArray::kSize, r2, r3, r4, &allocate, NO_ALLOCATION_FLAGS);
     __ bind(&done_allocate);
 
     // Setup the rest parameter array in r0.
@@ -4804,6 +4583,7 @@
     // ----------- S t a t e -------------
     //  -- cp : context
     //  -- r2 : number of rest parameters (tagged)
+    //  -- r3 : function
     //  -- r4 : pointer just past first rest parameters
     //  -- r8 : size of rest parameters
     //  -- lr : return address
@@ -4811,9 +4591,9 @@
 
     // Allocate space for the rest parameter array plus the backing store.
     Label allocate, done_allocate;
-    __ mov(r3, Operand(JSArray::kSize + FixedArray::kHeaderSize));
-    __ AddP(r3, r3, r8);
-    __ Allocate(r3, r5, r6, r7, &allocate, TAG_OBJECT);
+    __ mov(r9, Operand(JSArray::kSize + FixedArray::kHeaderSize));
+    __ AddP(r9, r9, r8);
+    __ Allocate(r9, r5, r6, r7, &allocate, NO_ALLOCATION_FLAGS);
     __ bind(&done_allocate);
 
     // Setup the elements array in r5.
@@ -4847,17 +4627,25 @@
     __ AddP(r2, r6, Operand(kHeapObjectTag));
     __ Ret();
 
-    // Fall back to %AllocateInNewSpace.
+    // Fall back to %AllocateInNewSpace (if not too big).
+    Label too_big_for_new_space;
     __ bind(&allocate);
+    __ CmpP(r9, Operand(Page::kMaxRegularHeapObjectSize));
+    __ bgt(&too_big_for_new_space);
     {
       FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
-      __ SmiTag(r3);
-      __ Push(r2, r4, r3);
+      __ SmiTag(r9);
+      __ Push(r2, r4, r9);
       __ CallRuntime(Runtime::kAllocateInNewSpace);
       __ LoadRR(r5, r2);
       __ Pop(r2, r4);
     }
     __ b(&done_allocate);
+
+    // Fall back to %NewRestParameter.
+    __ bind(&too_big_for_new_space);
+    __ push(r3);
+    __ TailCallRuntime(Runtime::kNewRestParameter);
   }
 }
 
@@ -4870,6 +4658,22 @@
   // -----------------------------------
   __ AssertFunction(r3);
 
+  // Make r9 point to the JavaScript frame.
+  __ LoadRR(r9, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
+    __ LoadP(r9, MemOperand(r9, StandardFrameConstants::kCallerFPOffset));
+  }
+  if (FLAG_debug_code) {
+    Label ok;
+    __ LoadP(ip, MemOperand(r9, StandardFrameConstants::kFunctionOffset));
+    __ CmpP(ip, r3);
+    __ beq(&ok, Label::kNear);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
+  }
+
   // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub.
   __ LoadP(r4, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
   __ LoadW(
@@ -4878,19 +4682,20 @@
   __ SmiTag(r4);
 #endif
   __ SmiToPtrArrayOffset(r5, r4);
-  __ AddP(r5, fp, r5);
+  __ AddP(r5, r9, r5);
   __ AddP(r5, r5, Operand(StandardFrameConstants::kCallerSPOffset));
 
   // r3 : function
   // r4 : number of parameters (tagged)
   // r5 : parameters pointer
+  // r9 : JavaScript frame pointer
   // Registers used over whole function:
   // r7 : arguments count (tagged)
   // r8 : mapped parameter count (tagged)
 
   // Check if the calling frame is an arguments adaptor frame.
   Label adaptor_frame, try_allocate, runtime;
-  __ LoadP(r6, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+  __ LoadP(r6, MemOperand(r9, StandardFrameConstants::kCallerFPOffset));
   __ LoadP(r2, MemOperand(r6, CommonFrameConstants::kContextOrFrameTypeOffset));
   __ CmpSmiLiteral(r2, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
   __ beq(&adaptor_frame);
@@ -4943,7 +4748,7 @@
   __ AddP(r1, r1, Operand(JSSloppyArgumentsObject::kSize));
 
   // Do the allocation of all three objects in one go.
-  __ Allocate(r1, r2, r1, r6, &runtime, TAG_OBJECT);
+  __ Allocate(r1, r2, r1, r6, &runtime, NO_ALLOCATION_FLAGS);
 
   // r2 = address of new object(s) (tagged)
   // r4 = argument count (smi-tagged)
@@ -5107,20 +4912,20 @@
   // -----------------------------------
   __ AssertFunction(r3);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make r4 point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ LoadRR(r4, fp);
-    __ b(&loop_entry);
-    __ bind(&loop);
+  // Make r4 point to the JavaScript frame.
+  __ LoadRR(r4, fp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ LoadP(r4, MemOperand(r4, StandardFrameConstants::kCallerFPOffset));
-    __ bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ LoadP(ip, MemOperand(r4, StandardFrameConstants::kFunctionOffset));
     __ CmpP(ip, r3);
-    __ bne(&loop);
+    __ beq(&ok, Label::kNear);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
   }
 
   // Check if we have an arguments adaptor frame below the function frame.
@@ -5130,9 +4935,9 @@
   __ CmpSmiLiteral(ip, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
   __ beq(&arguments_adaptor);
   {
-    __ LoadP(r3, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
+    __ LoadP(r6, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset));
     __ LoadW(r2, FieldMemOperand(
-                     r3, SharedFunctionInfo::kFormalParameterCountOffset));
+                     r6, SharedFunctionInfo::kFormalParameterCountOffset));
 #if V8_TARGET_ARCH_S390X
     __ SmiTag(r2);
 #endif
@@ -5152,6 +4957,7 @@
   // ----------- S t a t e -------------
   //  -- cp : context
   //  -- r2 : number of rest parameters (tagged)
+  //  -- r3 : function
   //  -- r4 : pointer just past first rest parameters
   //  -- r8 : size of rest parameters
   //  -- lr : return address
@@ -5159,9 +4965,9 @@
 
   // Allocate space for the strict arguments object plus the backing store.
   Label allocate, done_allocate;
-  __ mov(r3, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
-  __ AddP(r3, r3, r8);
-  __ Allocate(r3, r5, r6, r7, &allocate, TAG_OBJECT);
+  __ mov(r9, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
+  __ AddP(r9, r9, r8);
+  __ Allocate(r9, r5, r6, r7, &allocate, NO_ALLOCATION_FLAGS);
   __ bind(&done_allocate);
 
   // Setup the elements array in r5.
@@ -5196,47 +5002,25 @@
   __ AddP(r2, r6, Operand(kHeapObjectTag));
   __ Ret();
 
-  // Fall back to %AllocateInNewSpace.
+  // Fall back to %AllocateInNewSpace (if not too big).
+  Label too_big_for_new_space;
   __ bind(&allocate);
+  __ CmpP(r9, Operand(Page::kMaxRegularHeapObjectSize));
+  __ bgt(&too_big_for_new_space);
   {
     FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
-    __ SmiTag(r3);
-    __ Push(r2, r4, r3);
+    __ SmiTag(r9);
+    __ Push(r2, r4, r9);
     __ CallRuntime(Runtime::kAllocateInNewSpace);
     __ LoadRR(r5, r2);
     __ Pop(r2, r4);
   }
   __ b(&done_allocate);
-}
 
-void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
-  Register context = cp;
-  Register result = r2;
-  Register slot = r4;
-
-  // Go up the context chain to the script context.
-  for (int i = 0; i < depth(); ++i) {
-    __ LoadP(result, ContextMemOperand(context, Context::PREVIOUS_INDEX));
-    context = result;
-  }
-
-  // Load the PropertyCell value at the specified slot.
-  __ ShiftLeftP(r0, slot, Operand(kPointerSizeLog2));
-  __ AddP(result, context, r0);
-  __ LoadP(result, ContextMemOperand(result));
-  __ LoadP(result, FieldMemOperand(result, PropertyCell::kValueOffset));
-
-  // If the result is not the_hole, return. Otherwise, handle in the runtime.
-  __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
-  Label runtime;
-  __ beq(&runtime);
-  __ Ret();
-  __ bind(&runtime);
-
-  // Fallback to runtime.
-  __ SmiTag(slot);
-  __ Push(slot);
-  __ TailCallRuntime(Runtime::kLoadGlobalViaContext);
+  // Fall back to %NewStrictArguments.
+  __ bind(&too_big_for_new_space);
+  __ push(r3);
+  __ TailCallRuntime(Runtime::kNewStrictArguments);
 }
 
 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) {
@@ -5533,7 +5317,11 @@
   STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
   STATIC_ASSERT(FCA::kIsolateIndex == 1);
   STATIC_ASSERT(FCA::kHolderIndex == 0);
-  STATIC_ASSERT(FCA::kArgsLength == 7);
+  STATIC_ASSERT(FCA::kNewTargetIndex == 7);
+  STATIC_ASSERT(FCA::kArgsLength == 8);
+
+  // new target
+  __ PushRoot(Heap::kUndefinedValueRootIndex);
 
   // context save
   __ push(context);
@@ -5569,10 +5357,10 @@
   // it's not controlled by GC.
   // S390 LINUX ABI:
   //
-  // Create 5 extra slots on stack:
+  // Create 4 extra slots on stack:
   //    [0] space for DirectCEntryStub's LR save
-  //    [1-4] FunctionCallbackInfo
-  const int kApiStackSpace = 5;
+  //    [1-3] FunctionCallbackInfo
+  const int kApiStackSpace = 4;
   const int kFunctionCallbackInfoOffset =
       (kStackFrameExtraParamSlot + 1) * kPointerSize;
 
@@ -5591,9 +5379,6 @@
   // FunctionCallbackInfo::length_ = argc
   __ LoadImmP(ip, Operand(argc()));
   __ StoreW(ip, MemOperand(r2, 2 * kPointerSize));
-  // FunctionCallbackInfo::is_construct_call_ = 0
-  __ LoadImmP(ip, Operand::Zero());
-  __ StoreW(ip, MemOperand(r2, 2 * kPointerSize + kIntSize));
 
   ExternalReference thunk_ref =
       ExternalReference::invoke_function_callback(masm->isolate());
@@ -5610,9 +5395,9 @@
   }
   MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
   int stack_space = 0;
-  MemOperand is_construct_call_operand =
-      MemOperand(sp, kFunctionCallbackInfoOffset + 2 * kPointerSize + kIntSize);
-  MemOperand* stack_space_operand = &is_construct_call_operand;
+  MemOperand length_operand =
+      MemOperand(sp, kFunctionCallbackInfoOffset + 2 * kPointerSize);
+  MemOperand* stack_space_operand = &length_operand;
   stack_space = argc() + FCA::kArgsLength + 1;
   stack_space_operand = NULL;
   CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
@@ -5621,18 +5406,39 @@
 }
 
 void CallApiGetterStub::Generate(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- sp[0]                        : name
-  //  -- sp[4 .. (4 + kArgsLength*4)] : v8::PropertyCallbackInfo::args_
-  //  -- ...
-  //  -- r4                           : api_function_address
-  // -----------------------------------
-
-  Register api_function_address = ApiGetterDescriptor::function_address();
   int arg0Slot = 0;
   int accessorInfoSlot = 0;
   int apiStackSpace = 0;
-  DCHECK(api_function_address.is(r4));
+  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
+  // name below the exit frame to make GC aware of them.
+  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
+  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
+  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
+  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
+  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
+  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
+
+  Register receiver = ApiGetterDescriptor::ReceiverRegister();
+  Register holder = ApiGetterDescriptor::HolderRegister();
+  Register callback = ApiGetterDescriptor::CallbackRegister();
+  Register scratch = r6;
+  DCHECK(!AreAliased(receiver, holder, callback, scratch));
+
+  Register api_function_address = r4;
+
+  __ push(receiver);
+  // Push data from AccessorInfo.
+  __ LoadP(scratch, FieldMemOperand(callback, AccessorInfo::kDataOffset));
+  __ push(scratch);
+  __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
+  __ Push(scratch, scratch);
+  __ mov(scratch, Operand(ExternalReference::isolate_address(isolate())));
+  __ Push(scratch, holder);
+  __ Push(Smi::FromInt(0));  // should_throw_on_error -> false
+  __ LoadP(scratch, FieldMemOperand(callback, AccessorInfo::kNameOffset));
+  __ push(scratch);
 
   // v8::PropertyCallbackInfo::args_ array and name handle.
   const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
@@ -5680,6 +5486,10 @@
   ExternalReference thunk_ref =
       ExternalReference::invoke_accessor_getter_callback(isolate());
 
+  __ LoadP(scratch, FieldMemOperand(callback, AccessorInfo::kJsGetterOffset));
+  __ LoadP(api_function_address,
+           FieldMemOperand(scratch, Foreign::kForeignAddressOffset));
+
   // +3 is to skip prolog, return address and name handle.
   MemOperand return_value_operand(
       fp, (PropertyCallbackArguments::kReturnValueOffset + 3) * kPointerSize);
diff --git a/src/s390/codegen-s390.cc b/src/s390/codegen-s390.cc
index 6636a7c..5728e45 100644
--- a/src/s390/codegen-s390.cc
+++ b/src/s390/codegen-s390.cc
@@ -15,56 +15,6 @@
 
 #define __ masm.
 
-#if defined(USE_SIMULATOR)
-byte* fast_exp_s390_machine_code = nullptr;
-double fast_exp_simulator(double x, Isolate* isolate) {
-  return Simulator::current(isolate)->CallFPReturnsDouble(
-      fast_exp_s390_machine_code, x, 0);
-}
-#endif
-
-UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) {
-  size_t actual_size;
-  byte* buffer =
-      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
-  if (buffer == nullptr) return nullptr;
-  ExternalReference::InitializeMathExpData();
-
-  MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
-                      CodeObjectRequired::kNo);
-
-  {
-    DoubleRegister input = d0;
-    DoubleRegister result = d2;
-    DoubleRegister double_scratch1 = d3;
-    DoubleRegister double_scratch2 = d4;
-    Register temp1 = r6;
-    Register temp2 = r7;
-    Register temp3 = r8;
-
-    __ Push(temp3, temp2, temp1);
-    MathExpGenerator::EmitMathExp(&masm, input, result, double_scratch1,
-                                  double_scratch2, temp1, temp2, temp3);
-    __ Pop(temp3, temp2, temp1);
-    __ ldr(d0, result);
-    __ Ret();
-  }
-
-  CodeDesc desc;
-  masm.GetCode(&desc);
-  DCHECK(ABI_USES_FUNCTION_DESCRIPTORS || !RelocInfo::RequiresRelocation(desc));
-
-  Assembler::FlushICache(isolate, buffer, actual_size);
-  base::OS::ProtectCode(buffer, actual_size);
-
-#if !defined(USE_SIMULATOR)
-  return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
-#else
-  fast_exp_s390_machine_code = buffer;
-  return &fast_exp_simulator;
-#endif
-}
-
 UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
 #if defined(USE_SIMULATOR)
   return nullptr;
@@ -172,7 +122,7 @@
   __ SmiToDoubleArrayOffset(r14, length);
   __ AddP(r14, Operand(FixedDoubleArray::kHeaderSize));
   __ Allocate(r14, array, r9, scratch2, &gc_required, DOUBLE_ALIGNMENT);
-
+  __ SubP(array, array, Operand(kHeapObjectTag));
   // Set destination FixedDoubleArray's length and map.
   __ LoadRoot(scratch2, Heap::kFixedDoubleArrayMapRootIndex);
   __ StoreP(length, MemOperand(array, FixedDoubleArray::kLengthOffset));
@@ -302,12 +252,12 @@
   __ AddP(array_size, r0);
   __ Allocate(array_size, array, allocate_scratch, scratch, &gc_required,
               NO_ALLOCATION_FLAGS);
-  // array: destination FixedArray, not tagged as heap object
+  // array: destination FixedArray, tagged as heap object
   // Set destination FixedDoubleArray's length and map.
   __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
-  __ StoreP(length, MemOperand(array, FixedDoubleArray::kLengthOffset));
-  __ StoreP(scratch, MemOperand(array, HeapObject::kMapOffset));
-  __ AddP(array, Operand(kHeapObjectTag));
+  __ StoreP(length, FieldMemOperand(array, FixedDoubleArray::kLengthOffset),
+            r0);
+  __ StoreP(scratch, FieldMemOperand(array, HeapObject::kMapOffset), r0);
 
   // Prepare for conversion loop.
   Register src_elements = elements;
@@ -507,95 +457,6 @@
   __ bind(&done);
 }
 
-static MemOperand ExpConstant(int index, Register base) {
-  return MemOperand(base, index * kDoubleSize);
-}
-
-void MathExpGenerator::EmitMathExp(MacroAssembler* masm, DoubleRegister input,
-                                   DoubleRegister result,
-                                   DoubleRegister double_scratch1,
-                                   DoubleRegister double_scratch2,
-                                   Register temp1, Register temp2,
-                                   Register temp3) {
-  DCHECK(!input.is(result));
-  DCHECK(!input.is(double_scratch1));
-  DCHECK(!input.is(double_scratch2));
-  DCHECK(!result.is(double_scratch1));
-  DCHECK(!result.is(double_scratch2));
-  DCHECK(!double_scratch1.is(double_scratch2));
-  DCHECK(!temp1.is(temp2));
-  DCHECK(!temp1.is(temp3));
-  DCHECK(!temp2.is(temp3));
-  DCHECK(ExternalReference::math_exp_constants(0).address() != NULL);
-  DCHECK(!masm->serializer_enabled());  // External references not serializable.
-
-  Label zero, infinity, done;
-
-  __ mov(temp3, Operand(ExternalReference::math_exp_constants(0)));
-
-  __ LoadDouble(double_scratch1, ExpConstant(0, temp3));
-  __ cdbr(double_scratch1, input);
-  __ ldr(result, input);
-  __ bunordered(&done, Label::kNear);
-  __ bge(&zero, Label::kNear);
-
-  __ LoadDouble(double_scratch2, ExpConstant(1, temp3));
-  __ cdbr(input, double_scratch2);
-  __ bge(&infinity, Label::kNear);
-
-  __ LoadDouble(double_scratch1, ExpConstant(3, temp3));
-  __ LoadDouble(result, ExpConstant(4, temp3));
-
-  // Do not generate madbr, as intermediate result are not
-  // rounded properly
-  __ mdbr(double_scratch1, input);
-  __ adbr(double_scratch1, result);
-
-  // Move low word of double_scratch1 to temp2
-  __ lgdr(temp2, double_scratch1);
-  __ nihf(temp2, Operand::Zero());
-
-  __ sdbr(double_scratch1, result);
-  __ LoadDouble(result, ExpConstant(6, temp3));
-  __ LoadDouble(double_scratch2, ExpConstant(5, temp3));
-  __ mdbr(double_scratch1, double_scratch2);
-  __ sdbr(double_scratch1, input);
-  __ sdbr(result, double_scratch1);
-  __ ldr(double_scratch2, double_scratch1);
-  __ mdbr(double_scratch2, double_scratch2);
-  __ mdbr(result, double_scratch2);
-  __ LoadDouble(double_scratch2, ExpConstant(7, temp3));
-  __ mdbr(result, double_scratch2);
-  __ sdbr(result, double_scratch1);
-  __ LoadDouble(double_scratch2, ExpConstant(8, temp3));
-  __ adbr(result, double_scratch2);
-  __ ShiftRight(temp1, temp2, Operand(11));
-  __ AndP(temp2, Operand(0x7ff));
-  __ AddP(temp1, Operand(0x3ff));
-
-  // Must not call ExpConstant() after overwriting temp3!
-  __ mov(temp3, Operand(ExternalReference::math_exp_log_table()));
-  __ ShiftLeft(temp2, temp2, Operand(3));
-
-  __ lg(temp2, MemOperand(temp2, temp3));
-  __ sllg(temp1, temp1, Operand(52));
-  __ ogr(temp2, temp1);
-  __ ldgr(double_scratch1, temp2);
-
-  __ mdbr(result, double_scratch1);
-  __ b(&done, Label::kNear);
-
-  __ bind(&zero);
-  __ lzdr(kDoubleRegZero);
-  __ ldr(result, kDoubleRegZero);
-  __ b(&done, Label::kNear);
-
-  __ bind(&infinity);
-  __ LoadDouble(result, ExpConstant(2, temp3));
-
-  __ bind(&done);
-}
-
 #undef __
 
 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) {
diff --git a/src/s390/codegen-s390.h b/src/s390/codegen-s390.h
index 18cf8e2..aaedb01 100644
--- a/src/s390/codegen-s390.h
+++ b/src/s390/codegen-s390.h
@@ -25,19 +25,6 @@
  private:
   DISALLOW_COPY_AND_ASSIGN(StringCharLoadGenerator);
 };
-
-class MathExpGenerator : public AllStatic {
- public:
-  // Register input isn't modified. All other registers are clobbered.
-  static void EmitMathExp(MacroAssembler* masm, DoubleRegister input,
-                          DoubleRegister result, DoubleRegister double_scratch1,
-                          DoubleRegister double_scratch2, Register temp1,
-                          Register temp2, Register temp3);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MathExpGenerator);
-};
-
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/s390/constants-s390.cc b/src/s390/constants-s390.cc
index a958082..da53613 100644
--- a/src/s390/constants-s390.cc
+++ b/src/s390/constants-s390.cc
@@ -9,6 +9,267 @@
 namespace v8 {
 namespace internal {
 
+Instruction::OpcodeFormatType Instruction::OpcodeFormatTable[] = {
+    // Based on Figure B-3 in z/Architecture Principles of
+    // Operation.
+    TWO_BYTE_OPCODE,           // 0x00
+    TWO_BYTE_OPCODE,           // 0x01
+    TWO_BYTE_DISJOINT_OPCODE,  // 0x02
+    TWO_BYTE_DISJOINT_OPCODE,  // 0x03
+    ONE_BYTE_OPCODE,           // 0x04
+    ONE_BYTE_OPCODE,           // 0x05
+    ONE_BYTE_OPCODE,           // 0x06
+    ONE_BYTE_OPCODE,           // 0x07
+    ONE_BYTE_OPCODE,           // 0x08
+    ONE_BYTE_OPCODE,           // 0x09
+    ONE_BYTE_OPCODE,           // 0x0a
+    ONE_BYTE_OPCODE,           // 0x0b
+    ONE_BYTE_OPCODE,           // 0x0c
+    ONE_BYTE_OPCODE,           // 0x0d
+    ONE_BYTE_OPCODE,           // 0x0e
+    ONE_BYTE_OPCODE,           // 0x0f
+    ONE_BYTE_OPCODE,           // 0x10
+    ONE_BYTE_OPCODE,           // 0x11
+    ONE_BYTE_OPCODE,           // 0x12
+    ONE_BYTE_OPCODE,           // 0x13
+    ONE_BYTE_OPCODE,           // 0x14
+    ONE_BYTE_OPCODE,           // 0x15
+    ONE_BYTE_OPCODE,           // 0x16
+    ONE_BYTE_OPCODE,           // 0x17
+    ONE_BYTE_OPCODE,           // 0x18
+    ONE_BYTE_OPCODE,           // 0x19
+    ONE_BYTE_OPCODE,           // 0x1a
+    ONE_BYTE_OPCODE,           // 0x1b
+    ONE_BYTE_OPCODE,           // 0x1c
+    ONE_BYTE_OPCODE,           // 0x1d
+    ONE_BYTE_OPCODE,           // 0x1e
+    ONE_BYTE_OPCODE,           // 0x1f
+    ONE_BYTE_OPCODE,           // 0x20
+    ONE_BYTE_OPCODE,           // 0x21
+    ONE_BYTE_OPCODE,           // 0x22
+    ONE_BYTE_OPCODE,           // 0x23
+    ONE_BYTE_OPCODE,           // 0x24
+    ONE_BYTE_OPCODE,           // 0x25
+    ONE_BYTE_OPCODE,           // 0x26
+    ONE_BYTE_OPCODE,           // 0x27
+    ONE_BYTE_OPCODE,           // 0x28
+    ONE_BYTE_OPCODE,           // 0x29
+    ONE_BYTE_OPCODE,           // 0x2a
+    ONE_BYTE_OPCODE,           // 0x2b
+    ONE_BYTE_OPCODE,           // 0x2c
+    ONE_BYTE_OPCODE,           // 0x2d
+    ONE_BYTE_OPCODE,           // 0x2e
+    ONE_BYTE_OPCODE,           // 0x2f
+    ONE_BYTE_OPCODE,           // 0x30
+    ONE_BYTE_OPCODE,           // 0x31
+    ONE_BYTE_OPCODE,           // 0x32
+    ONE_BYTE_OPCODE,           // 0x33
+    ONE_BYTE_OPCODE,           // 0x34
+    ONE_BYTE_OPCODE,           // 0x35
+    ONE_BYTE_OPCODE,           // 0x36
+    ONE_BYTE_OPCODE,           // 0x37
+    ONE_BYTE_OPCODE,           // 0x38
+    ONE_BYTE_OPCODE,           // 0x39
+    ONE_BYTE_OPCODE,           // 0x3a
+    ONE_BYTE_OPCODE,           // 0x3b
+    ONE_BYTE_OPCODE,           // 0x3c
+    ONE_BYTE_OPCODE,           // 0x3d
+    ONE_BYTE_OPCODE,           // 0x3e
+    ONE_BYTE_OPCODE,           // 0x3f
+    ONE_BYTE_OPCODE,           // 0x40
+    ONE_BYTE_OPCODE,           // 0x41
+    ONE_BYTE_OPCODE,           // 0x42
+    ONE_BYTE_OPCODE,           // 0x43
+    ONE_BYTE_OPCODE,           // 0x44
+    ONE_BYTE_OPCODE,           // 0x45
+    ONE_BYTE_OPCODE,           // 0x46
+    ONE_BYTE_OPCODE,           // 0x47
+    ONE_BYTE_OPCODE,           // 0x48
+    ONE_BYTE_OPCODE,           // 0x49
+    ONE_BYTE_OPCODE,           // 0x4a
+    ONE_BYTE_OPCODE,           // 0x4b
+    ONE_BYTE_OPCODE,           // 0x4c
+    ONE_BYTE_OPCODE,           // 0x4d
+    ONE_BYTE_OPCODE,           // 0x4e
+    ONE_BYTE_OPCODE,           // 0x4f
+    ONE_BYTE_OPCODE,           // 0x50
+    ONE_BYTE_OPCODE,           // 0x51
+    ONE_BYTE_OPCODE,           // 0x52
+    ONE_BYTE_OPCODE,           // 0x53
+    ONE_BYTE_OPCODE,           // 0x54
+    ONE_BYTE_OPCODE,           // 0x55
+    ONE_BYTE_OPCODE,           // 0x56
+    ONE_BYTE_OPCODE,           // 0x57
+    ONE_BYTE_OPCODE,           // 0x58
+    ONE_BYTE_OPCODE,           // 0x59
+    ONE_BYTE_OPCODE,           // 0x5a
+    ONE_BYTE_OPCODE,           // 0x5b
+    ONE_BYTE_OPCODE,           // 0x5c
+    ONE_BYTE_OPCODE,           // 0x5d
+    ONE_BYTE_OPCODE,           // 0x5e
+    ONE_BYTE_OPCODE,           // 0x5f
+    ONE_BYTE_OPCODE,           // 0x60
+    ONE_BYTE_OPCODE,           // 0x61
+    ONE_BYTE_OPCODE,           // 0x62
+    ONE_BYTE_OPCODE,           // 0x63
+    ONE_BYTE_OPCODE,           // 0x64
+    ONE_BYTE_OPCODE,           // 0x65
+    ONE_BYTE_OPCODE,           // 0x66
+    ONE_BYTE_OPCODE,           // 0x67
+    ONE_BYTE_OPCODE,           // 0x68
+    ONE_BYTE_OPCODE,           // 0x69
+    ONE_BYTE_OPCODE,           // 0x6a
+    ONE_BYTE_OPCODE,           // 0x6b
+    ONE_BYTE_OPCODE,           // 0x6c
+    ONE_BYTE_OPCODE,           // 0x6d
+    ONE_BYTE_OPCODE,           // 0x6e
+    ONE_BYTE_OPCODE,           // 0x6f
+    ONE_BYTE_OPCODE,           // 0x70
+    ONE_BYTE_OPCODE,           // 0x71
+    ONE_BYTE_OPCODE,           // 0x72
+    ONE_BYTE_OPCODE,           // 0x73
+    ONE_BYTE_OPCODE,           // 0x74
+    ONE_BYTE_OPCODE,           // 0x75
+    ONE_BYTE_OPCODE,           // 0x76
+    ONE_BYTE_OPCODE,           // 0x77
+    ONE_BYTE_OPCODE,           // 0x78
+    ONE_BYTE_OPCODE,           // 0x79
+    ONE_BYTE_OPCODE,           // 0x7a
+    ONE_BYTE_OPCODE,           // 0x7b
+    ONE_BYTE_OPCODE,           // 0x7c
+    ONE_BYTE_OPCODE,           // 0x7d
+    ONE_BYTE_OPCODE,           // 0x7e
+    ONE_BYTE_OPCODE,           // 0x7f
+    ONE_BYTE_OPCODE,           // 0x80
+    ONE_BYTE_OPCODE,           // 0x81
+    ONE_BYTE_OPCODE,           // 0x82
+    ONE_BYTE_OPCODE,           // 0x83
+    ONE_BYTE_OPCODE,           // 0x84
+    ONE_BYTE_OPCODE,           // 0x85
+    ONE_BYTE_OPCODE,           // 0x86
+    ONE_BYTE_OPCODE,           // 0x87
+    ONE_BYTE_OPCODE,           // 0x88
+    ONE_BYTE_OPCODE,           // 0x89
+    ONE_BYTE_OPCODE,           // 0x8a
+    ONE_BYTE_OPCODE,           // 0x8b
+    ONE_BYTE_OPCODE,           // 0x8c
+    ONE_BYTE_OPCODE,           // 0x8d
+    ONE_BYTE_OPCODE,           // 0x8e
+    ONE_BYTE_OPCODE,           // 0x8f
+    ONE_BYTE_OPCODE,           // 0x90
+    ONE_BYTE_OPCODE,           // 0x91
+    ONE_BYTE_OPCODE,           // 0x92
+    ONE_BYTE_OPCODE,           // 0x93
+    ONE_BYTE_OPCODE,           // 0x94
+    ONE_BYTE_OPCODE,           // 0x95
+    ONE_BYTE_OPCODE,           // 0x96
+    ONE_BYTE_OPCODE,           // 0x97
+    ONE_BYTE_OPCODE,           // 0x98
+    ONE_BYTE_OPCODE,           // 0x99
+    ONE_BYTE_OPCODE,           // 0x9a
+    ONE_BYTE_OPCODE,           // 0x9b
+    TWO_BYTE_DISJOINT_OPCODE,  // 0x9c
+    TWO_BYTE_DISJOINT_OPCODE,  // 0x9d
+    TWO_BYTE_DISJOINT_OPCODE,  // 0x9e
+    TWO_BYTE_DISJOINT_OPCODE,  // 0x9f
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xa0
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xa1
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xa2
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xa3
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xa4
+    THREE_NIBBLE_OPCODE,       // 0xa5
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xa6
+    THREE_NIBBLE_OPCODE,       // 0xa7
+    ONE_BYTE_OPCODE,           // 0xa8
+    ONE_BYTE_OPCODE,           // 0xa9
+    ONE_BYTE_OPCODE,           // 0xaa
+    ONE_BYTE_OPCODE,           // 0xab
+    ONE_BYTE_OPCODE,           // 0xac
+    ONE_BYTE_OPCODE,           // 0xad
+    ONE_BYTE_OPCODE,           // 0xae
+    ONE_BYTE_OPCODE,           // 0xaf
+    ONE_BYTE_OPCODE,           // 0xb0
+    ONE_BYTE_OPCODE,           // 0xb1
+    TWO_BYTE_OPCODE,           // 0xb2
+    TWO_BYTE_OPCODE,           // 0xb3
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xb4
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xb5
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xb6
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xb7
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xb8
+    TWO_BYTE_OPCODE,           // 0xb9
+    ONE_BYTE_OPCODE,           // 0xba
+    ONE_BYTE_OPCODE,           // 0xbb
+    ONE_BYTE_OPCODE,           // 0xbc
+    ONE_BYTE_OPCODE,           // 0xbd
+    ONE_BYTE_OPCODE,           // 0xbe
+    ONE_BYTE_OPCODE,           // 0xbf
+    THREE_NIBBLE_OPCODE,       // 0xc0
+    THREE_NIBBLE_OPCODE,       // 0xc1
+    THREE_NIBBLE_OPCODE,       // 0xc2
+    THREE_NIBBLE_OPCODE,       // 0xc3
+    THREE_NIBBLE_OPCODE,       // 0xc4
+    THREE_NIBBLE_OPCODE,       // 0xc5
+    THREE_NIBBLE_OPCODE,       // 0xc6
+    ONE_BYTE_OPCODE,           // 0xc7
+    THREE_NIBBLE_OPCODE,       // 0xc8
+    THREE_NIBBLE_OPCODE,       // 0xc9
+    THREE_NIBBLE_OPCODE,       // 0xca
+    THREE_NIBBLE_OPCODE,       // 0xcb
+    THREE_NIBBLE_OPCODE,       // 0xcc
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xcd
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xce
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xcf
+    ONE_BYTE_OPCODE,           // 0xd0
+    ONE_BYTE_OPCODE,           // 0xd1
+    ONE_BYTE_OPCODE,           // 0xd2
+    ONE_BYTE_OPCODE,           // 0xd3
+    ONE_BYTE_OPCODE,           // 0xd4
+    ONE_BYTE_OPCODE,           // 0xd5
+    ONE_BYTE_OPCODE,           // 0xd6
+    ONE_BYTE_OPCODE,           // 0xd7
+    ONE_BYTE_OPCODE,           // 0xd8
+    ONE_BYTE_OPCODE,           // 0xd9
+    ONE_BYTE_OPCODE,           // 0xda
+    ONE_BYTE_OPCODE,           // 0xdb
+    ONE_BYTE_OPCODE,           // 0xdc
+    ONE_BYTE_OPCODE,           // 0xdd
+    ONE_BYTE_OPCODE,           // 0xde
+    ONE_BYTE_OPCODE,           // 0xdf
+    ONE_BYTE_OPCODE,           // 0xe0
+    ONE_BYTE_OPCODE,           // 0xe1
+    ONE_BYTE_OPCODE,           // 0xe2
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xe3
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xe4
+    TWO_BYTE_OPCODE,           // 0xe5
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xe6
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xe7
+    ONE_BYTE_OPCODE,           // 0xe8
+    ONE_BYTE_OPCODE,           // 0xe9
+    ONE_BYTE_OPCODE,           // 0xea
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xeb
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xec
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xed
+    ONE_BYTE_OPCODE,           // 0xee
+    ONE_BYTE_OPCODE,           // 0xef
+    ONE_BYTE_OPCODE,           // 0xf0
+    ONE_BYTE_OPCODE,           // 0xf1
+    ONE_BYTE_OPCODE,           // 0xf2
+    ONE_BYTE_OPCODE,           // 0xf3
+    ONE_BYTE_OPCODE,           // 0xf4
+    ONE_BYTE_OPCODE,           // 0xf5
+    ONE_BYTE_OPCODE,           // 0xf6
+    ONE_BYTE_OPCODE,           // 0xf7
+    ONE_BYTE_OPCODE,           // 0xf8
+    ONE_BYTE_OPCODE,           // 0xf9
+    ONE_BYTE_OPCODE,           // 0xfa
+    ONE_BYTE_OPCODE,           // 0xfb
+    ONE_BYTE_OPCODE,           // 0xfc
+    ONE_BYTE_OPCODE,           // 0xfd
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xfe
+    TWO_BYTE_DISJOINT_OPCODE,  // 0xff
+};
+
 // These register names are defined in a way to match the native disassembler
 // formatting. See for example the command "objdump -d <binary file>".
 const char* Registers::names_[kNumRegisters] = {
diff --git a/src/s390/constants-s390.h b/src/s390/constants-s390.h
index c313c92..9dfb32c 100644
--- a/src/s390/constants-s390.h
+++ b/src/s390/constants-s390.h
@@ -1080,6 +1080,7 @@
     THREE_NIBBLE_OPCODE        // Three Nibbles - Bits 0 to 7, 12 to 15
   };
 
+  static OpcodeFormatType OpcodeFormatTable[256];
 // Helper macro to define static accessors.
 // We use the cast to char* trick to bypass the strict anti-aliasing rules.
 #define DECLARE_STATIC_TYPED_ACCESSOR(return_type, Name) \
@@ -1254,37 +1255,7 @@
   // Get Instruction Format Type
   static OpcodeFormatType getOpcodeFormatType(const byte* instr) {
     const byte firstByte = *instr;
-    // Based on Figure B-3 in z/Architecture Principles of
-    // Operation.
-
-    // 1-byte opcodes
-    //   I, RR, RS, RSI, RX, SS Formats
-    if ((0x04 <= firstByte && 0x9B >= firstByte) ||
-        (0xA8 <= firstByte && 0xB1 >= firstByte) ||
-        (0xBA <= firstByte && 0xBF >= firstByte) || (0xC5 == firstByte) ||
-        (0xC7 == firstByte) || (0xD0 <= firstByte && 0xE2 >= firstByte) ||
-        (0xE8 <= firstByte && 0xEA >= firstByte) ||
-        (0xEE <= firstByte && 0xFD >= firstByte)) {
-      return ONE_BYTE_OPCODE;
-    }
-
-    // 2-byte opcodes
-    //   E, IE, RRD, RRE, RRF, SIL, S, SSE Formats
-    if ((0x00 == firstByte) ||  // Software breakpoint 0x0001
-        (0x01 == firstByte) || (0xB2 == firstByte) || (0xB3 == firstByte) ||
-        (0xB9 == firstByte) || (0xE5 == firstByte)) {
-      return TWO_BYTE_OPCODE;
-    }
-
-    // 3-nibble opcodes
-    //   RI, RIL, SSF Formats
-    if ((0xA5 == firstByte) || (0xA7 == firstByte) ||
-        (0xC0 <= firstByte && 0xCC >= firstByte)) {  // C5,C7 handled above
-      return THREE_NIBBLE_OPCODE;
-    }
-    // Remaining ones are all TWO_BYTE_DISJOINT OPCODES.
-    DCHECK(InstructionLength(instr) == 6);
-    return TWO_BYTE_DISJOINT_OPCODE;
+    return OpcodeFormatTable[firstByte];
   }
 
   // Extract the full opcode from the instruction.
@@ -1304,11 +1275,10 @@
       case TWO_BYTE_DISJOINT_OPCODE:
         // Two Bytes - Bits 0 to 7, 40 to 47
         return static_cast<Opcode>((*instr << 8) | (*(instr + 5) & 0xFF));
-      case THREE_NIBBLE_OPCODE:
+      default:
+        // case THREE_NIBBLE_OPCODE:
         // Three Nibbles - Bits 0 to 7, 12 to 15
         return static_cast<Opcode>((*instr << 4) | (*(instr + 1) & 0xF));
-      default:
-        break;
     }
 
     UNREACHABLE();
diff --git a/src/s390/deoptimizer-s390.cc b/src/s390/deoptimizer-s390.cc
index 44062d6..6ee8c74 100644
--- a/src/s390/deoptimizer-s390.cc
+++ b/src/s390/deoptimizer-s390.cc
@@ -116,8 +116,7 @@
 
   // Save all double registers before messing with them.
   __ lay(sp, MemOperand(sp, -kDoubleRegsSize));
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
     int code = config->GetAllocatableDoubleCode(i);
     const DoubleRegister dreg = DoubleRegister::from_code(code);
diff --git a/src/s390/disasm-s390.cc b/src/s390/disasm-s390.cc
index 5bab604..d9cf2d3 100644
--- a/src/s390/disasm-s390.cc
+++ b/src/s390/disasm-s390.cc
@@ -37,6 +37,8 @@
 namespace v8 {
 namespace internal {
 
+const auto GetRegConfig = RegisterConfiguration::Crankshaft;
+
 //------------------------------------------------------------------------------
 
 // Decoder decodes and disassembles instructions into an output buffer.
@@ -111,7 +113,7 @@
 
 // Print the double FP register name according to the active name converter.
 void Decoder::PrintDRegister(int reg) {
-  Print(DoubleRegister::from_code(reg).ToString());
+  Print(GetRegConfig()->GetDoubleRegisterName(reg));
 }
 
 // Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
@@ -1357,7 +1359,7 @@
 namespace disasm {
 
 const char* NameConverter::NameOfAddress(byte* addr) const {
-  v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
+  v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
   return tmp_buffer_.start();
 }
 
@@ -1366,7 +1368,7 @@
 }
 
 const char* NameConverter::NameOfCPURegister(int reg) const {
-  return v8::internal::Register::from_code(reg).ToString();
+  return v8::internal::GetRegConfig()->GetGeneralRegisterName(reg);
 }
 
 const char* NameConverter::NameOfByteCPURegister(int reg) const {
@@ -1411,7 +1413,7 @@
     buffer[0] = '\0';
     byte* prev_pc = pc;
     pc += d.InstructionDecode(buffer, pc);
-    v8::internal::PrintF(f, "%p    %08x      %s\n", prev_pc,
+    v8::internal::PrintF(f, "%p    %08x      %s\n", static_cast<void*>(prev_pc),
                          *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
   }
 }
diff --git a/src/s390/interface-descriptors-s390.cc b/src/s390/interface-descriptors-s390.cc
index 63afca8..d588fbe 100644
--- a/src/s390/interface-descriptors-s390.cc
+++ b/src/s390/interface-descriptors-s390.cc
@@ -11,6 +11,15 @@
 
 const Register CallInterfaceDescriptor::ContextRegister() { return cp; }
 
+void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
+    CallInterfaceDescriptorData* data, int register_parameter_count) {
+  const Register default_stub_registers[] = {r2, r3, r4, r5, r6};
+  CHECK_LE(static_cast<size_t>(register_parameter_count),
+           arraysize(default_stub_registers));
+  data->InitializePlatformSpecific(register_parameter_count,
+                                   default_stub_registers);
+}
+
 const Register LoadDescriptor::ReceiverRegister() { return r3; }
 const Register LoadDescriptor::NameRegister() { return r4; }
 const Register LoadDescriptor::SlotRegister() { return r2; }
@@ -31,18 +40,14 @@
 
 const Register StoreTransitionDescriptor::MapRegister() { return r5; }
 
-const Register LoadGlobalViaContextDescriptor::SlotRegister() { return r4; }
-
 const Register StoreGlobalViaContextDescriptor::SlotRegister() { return r4; }
 const Register StoreGlobalViaContextDescriptor::ValueRegister() { return r2; }
 
-const Register InstanceOfDescriptor::LeftRegister() { return r3; }
-const Register InstanceOfDescriptor::RightRegister() { return r2; }
-
 const Register StringCompareDescriptor::LeftRegister() { return r3; }
 const Register StringCompareDescriptor::RightRegister() { return r2; }
 
-const Register ApiGetterDescriptor::function_address() { return r4; }
+const Register ApiGetterDescriptor::HolderRegister() { return r2; }
+const Register ApiGetterDescriptor::CallbackRegister() { return r5; }
 
 const Register MathPowTaggedDescriptor::exponent() { return r4; }
 
@@ -211,46 +216,34 @@
 SIMD128_TYPES(SIMD128_ALLOC_DESC)
 #undef SIMD128_ALLOC_DESC
 
-void AllocateInNewSpaceDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  Register registers[] = {r2};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-void ArrayConstructorConstantArgCountDescriptor::InitializePlatformSpecific(
+void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // register state
   // r2 -- number of arguments
   // r3 -- function
   // r4 -- allocation site with elements kind
-  Register registers[] = {r3, r4};
+  Register registers[] = {r3, r4, r2};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
-void ArrayConstructorDescriptor::InitializePlatformSpecific(
+void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  // register state
+  // r2 -- number of arguments
+  // r3 -- function
+  // r4 -- allocation site with elements kind
+  Register registers[] = {r3, r4, r2};
+  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
+}
+
+void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // stack param count needs (constructor pointer, and single argument)
   Register registers[] = {r3, r4, r2};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
-void InternalArrayConstructorConstantArgCountDescriptor::
-    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
-  // register state
-  // r2 -- number of arguments
-  // r3 -- constructor function
-  Register registers[] = {r3};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-void InternalArrayConstructorDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  // stack param count needs (constructor pointer, and single argument)
-  Register registers[] = {r3, r2};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-void FastArrayPushDescriptor::InitializePlatformSpecific(
+void VarArgFunctionDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // stack param count needs (arg count)
   Register registers[] = {r2};
@@ -275,6 +268,12 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
+void CountOpDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {r4};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
 void StringAddDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {r3, r2};
@@ -330,9 +329,8 @@
 void InterpreterDispatchDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {
-      kInterpreterAccumulatorRegister, kInterpreterRegisterFileRegister,
-      kInterpreterBytecodeOffsetRegister, kInterpreterBytecodeArrayRegister,
-      kInterpreterDispatchTableRegister};
+      kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
+      kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
@@ -367,6 +365,16 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
+void ResumeGeneratorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {
+      r2,  // the value to pass to the generator
+      r3,  // the JSGeneratorObject to resume
+      r4   // the resume mode (tagged)
+  };
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/s390/macro-assembler-s390.cc b/src/s390/macro-assembler-s390.cc
index 21058f4..ca48614 100644
--- a/src/s390/macro-assembler-s390.cc
+++ b/src/s390/macro-assembler-s390.cc
@@ -70,10 +70,6 @@
   Label start;
   bind(&start);
 
-  // Statement positions are expected to be recorded when the target
-  // address is loaded.
-  positions_recorder()->WriteRecordedPositions();
-
   // Branch to target via indirect branch
   basr(r14, target);
 
@@ -122,10 +118,6 @@
   bind(&start);
 #endif
 
-  // Statement positions are expected to be recorded when the target
-  // address is loaded.
-  positions_recorder()->WriteRecordedPositions();
-
   mov(ip, Operand(reinterpret_cast<intptr_t>(target), rmode));
   basr(r14, ip);
 
@@ -480,8 +472,8 @@
   // Save caller-saved registers.  js_function and code_entry are in the
   // caller-saved register list.
   DCHECK(kJSCallerSaved & js_function.bit());
-  DCHECK(kJSCallerSaved & code_entry.bit());
-  MultiPush(kJSCallerSaved | r14.bit());
+  // DCHECK(kJSCallerSaved & code_entry.bit());
+  MultiPush(kJSCallerSaved | code_entry.bit() | r14.bit());
 
   int argument_count = 3;
   PrepareCallCFunction(argument_count, code_entry);
@@ -499,7 +491,7 @@
   }
 
   // Restore caller-saved registers (including js_function and code_entry).
-  MultiPop(kJSCallerSaved | r14.bit());
+  MultiPop(kJSCallerSaved | code_entry.bit() | r14.bit());
 
   bind(&done);
 }
@@ -645,8 +637,7 @@
 
 MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
   // General purpose registers are pushed last on the stack.
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   int doubles_size = config->num_allocatable_double_registers() * kDoubleSize;
   int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
   return MemOperand(sp, doubles_size + register_offset);
@@ -987,9 +978,8 @@
 
 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
   LoadP(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
-  LoadP(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset));
-  LoadP(vector,
-        FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset));
+  LoadP(vector, FieldMemOperand(vector, JSFunction::kLiteralsOffset));
+  LoadP(vector, FieldMemOperand(vector, LiteralsArray::kFeedbackVectorOffset));
 }
 
 void MacroAssembler::EnterFrame(StackFrame::Type type,
@@ -1310,12 +1300,13 @@
                                              const ParameterCount& expected,
                                              const ParameterCount& actual) {
   Label skip_flooding;
-  ExternalReference step_in_enabled =
-      ExternalReference::debug_step_in_enabled_address(isolate());
-  mov(r6, Operand(step_in_enabled));
-  LoadlB(r6, MemOperand(r6));
-  CmpP(r6, Operand::Zero());
-  beq(&skip_flooding);
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(isolate());
+  STATIC_ASSERT(StepFrame > StepIn);
+  mov(r6, Operand(last_step_action));
+  LoadB(r6, MemOperand(r6));
+  CmpP(r6, Operand(StepIn));
+  blt(&skip_flooding);
   {
     FrameScope frame(this,
                      has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
@@ -1706,6 +1697,7 @@
                               Register scratch1, Register scratch2,
                               Label* gc_required, AllocationFlags flags) {
   DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -1767,7 +1759,7 @@
     STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
     AndP(result_end, result, Operand(kDoubleAlignmentMask));
     Label aligned;
-    beq(&aligned);
+    beq(&aligned, Label::kNear);
     if ((flags & PRETENURE) != 0) {
       CmpLogicalP(result, alloc_limit);
       bge(gc_required);
@@ -1792,17 +1784,20 @@
     blt(gc_required);
     AddP(result_end, result, result_end);
   }
-  StoreP(result_end, MemOperand(top_address));
 
-  // Tag object if requested.
-  if ((flags & TAG_OBJECT) != 0) {
-    AddP(result, result, Operand(kHeapObjectTag));
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    StoreP(result_end, MemOperand(top_address));
   }
+
+  // Tag object.
+  AddP(result, result, Operand(kHeapObjectTag));
 }
 
 void MacroAssembler::Allocate(Register object_size, Register result,
                               Register result_end, Register scratch,
                               Label* gc_required, AllocationFlags flags) {
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -1860,7 +1855,7 @@
     STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
     AndP(result_end, result, Operand(kDoubleAlignmentMask));
     Label aligned;
-    beq(&aligned);
+    beq(&aligned, Label::kNear);
     if ((flags & PRETENURE) != 0) {
       CmpLogicalP(result, alloc_limit);
       bge(gc_required);
@@ -1892,12 +1887,114 @@
     AndP(r0, result_end, Operand(kObjectAlignmentMask));
     Check(eq, kUnalignedAllocationInNewSpace, cr0);
   }
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    StoreP(result_end, MemOperand(top_address));
+  }
+
+  // Tag object.
+  AddP(result, result, Operand(kHeapObjectTag));
+}
+
+void MacroAssembler::FastAllocate(Register object_size, Register result,
+                                  Register result_end, Register scratch,
+                                  AllocationFlags flags) {
+  // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag
+  // is not specified. Other registers must not overlap.
+  DCHECK(!AreAliased(object_size, result, scratch, ip));
+  DCHECK(!AreAliased(result_end, result, scratch, ip));
+  DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end));
+
+  ExternalReference allocation_top =
+      AllocationUtils::GetAllocationTopReference(isolate(), flags);
+
+  Register top_address = scratch;
+  mov(top_address, Operand(allocation_top));
+  LoadP(result, MemOperand(top_address));
+
+  if ((flags & DOUBLE_ALIGNMENT) != 0) {
+// Align the next allocation. Storing the filler map without checking top is
+// safe in new-space because the limit of the heap is aligned there.
+#if V8_TARGET_ARCH_S390X
+    STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
+#else
+    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
+    AndP(result_end, result, Operand(kDoubleAlignmentMask));
+    Label aligned;
+    beq(&aligned, Label::kNear);
+    mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
+    StoreW(result_end, MemOperand(result));
+    AddP(result, result, Operand(kDoubleSize / 2));
+    bind(&aligned);
+#endif
+  }
+
+  // Calculate new top using result. Object size may be in words so a shift is
+  // required to get the number of bytes.
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    ShiftLeftP(result_end, object_size, Operand(kPointerSizeLog2));
+    AddP(result_end, result, result_end);
+  } else {
+    AddP(result_end, result, object_size);
+  }
+
+  // Update allocation top. result temporarily holds the new top.
+  if (emit_debug_code()) {
+    AndP(r0, result_end, Operand(kObjectAlignmentMask));
+    Check(eq, kUnalignedAllocationInNewSpace, cr0);
+  }
   StoreP(result_end, MemOperand(top_address));
 
-  // Tag object if requested.
-  if ((flags & TAG_OBJECT) != 0) {
-    AddP(result, result, Operand(kHeapObjectTag));
+  // Tag object.
+  AddP(result, result, Operand(kHeapObjectTag));
+}
+
+void MacroAssembler::FastAllocate(int object_size, Register result,
+                                  Register scratch1, Register scratch2,
+                                  AllocationFlags flags) {
+  DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
+  DCHECK(!AreAliased(result, scratch1, scratch2, ip));
+
+  // Make object size into bytes.
+  if ((flags & SIZE_IN_WORDS) != 0) {
+    object_size *= kPointerSize;
   }
+  DCHECK_EQ(0, object_size & kObjectAlignmentMask);
+
+  ExternalReference allocation_top =
+      AllocationUtils::GetAllocationTopReference(isolate(), flags);
+
+  // Set up allocation top address register.
+  Register top_address = scratch1;
+  Register result_end = scratch2;
+  mov(top_address, Operand(allocation_top));
+  LoadP(result, MemOperand(top_address));
+
+  if ((flags & DOUBLE_ALIGNMENT) != 0) {
+// Align the next allocation. Storing the filler map without checking top is
+// safe in new-space because the limit of the heap is aligned there.
+#if V8_TARGET_ARCH_S390X
+    STATIC_ASSERT(kPointerAlignment == kDoubleAlignment);
+#else
+    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
+    AndP(result_end, result, Operand(kDoubleAlignmentMask));
+    Label aligned;
+    beq(&aligned, Label::kNear);
+    mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
+    StoreW(result_end, MemOperand(result));
+    AddP(result, result, Operand(kDoubleSize / 2));
+    bind(&aligned);
+#endif
+  }
+
+  // Calculate new top using result.
+  AddP(result_end, result, Operand(object_size));
+
+  // The top pointer is not updated for allocation folding dominators.
+  StoreP(result_end, MemOperand(top_address));
+
+  // Tag object.
+  AddP(result, result, Operand(kHeapObjectTag));
 }
 
 void MacroAssembler::AllocateTwoByteString(Register result, Register length,
@@ -1914,7 +2011,8 @@
   AndP(scratch1, Operand(~kObjectAlignmentMask));
 
   // Allocate two-byte string in new space.
-  Allocate(scratch1, result, scratch2, scratch3, gc_required, TAG_OBJECT);
+  Allocate(scratch1, result, scratch2, scratch3, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   InitializeNewString(result, length, Heap::kStringMapRootIndex, scratch1,
@@ -1934,7 +2032,8 @@
   AndP(scratch1, Operand(~kObjectAlignmentMask));
 
   // Allocate one-byte string in new space.
-  Allocate(scratch1, result, scratch2, scratch3, gc_required, TAG_OBJECT);
+  Allocate(scratch1, result, scratch2, scratch3, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   InitializeNewString(result, length, Heap::kOneByteStringMapRootIndex,
@@ -1946,7 +2045,7 @@
                                                Register scratch2,
                                                Label* gc_required) {
   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result, length, Heap::kConsStringMapRootIndex, scratch1,
                       scratch2);
@@ -1957,7 +2056,7 @@
                                                Register scratch2,
                                                Label* gc_required) {
   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result, length, Heap::kConsOneByteStringMapRootIndex,
                       scratch1, scratch2);
@@ -1969,7 +2068,7 @@
                                                  Register scratch2,
                                                  Label* gc_required) {
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result, length, Heap::kSlicedStringMapRootIndex, scratch1,
                       scratch2);
@@ -1981,7 +2080,7 @@
                                                  Register scratch2,
                                                  Label* gc_required) {
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   InitializeNewString(result, length, Heap::kSlicedOneByteStringMapRootIndex,
                       scratch1, scratch2);
@@ -2847,6 +2946,18 @@
   }
 }
 
+void MacroAssembler::AssertGeneratorObject(Register object) {
+  if (emit_debug_code()) {
+    STATIC_ASSERT(kSmiTag == 0);
+    TestIfSmi(object);
+    Check(ne, kOperandIsASmiAndNotAGeneratorObject, cr0);
+    push(object);
+    CompareObjectType(object, object, object, JS_GENERATOR_OBJECT_TYPE);
+    pop(object);
+    Check(eq, kOperandIsNotAGeneratorObject);
+  }
+}
+
 void MacroAssembler::AssertReceiver(Register object) {
   if (emit_debug_code()) {
     STATIC_ASSERT(kSmiTag == 0);
@@ -2935,12 +3046,11 @@
                                         Register scratch2,
                                         Register heap_number_map,
                                         Label* gc_required,
-                                        TaggingMode tagging_mode,
                                         MutableMode mode) {
   // Allocate an object in the heap for the heap number and tag it as a heap
   // object.
   Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
-           tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS);
+           NO_ALLOCATION_FLAGS);
 
   Heap::RootListIndex map_index = mode == MUTABLE
                                       ? Heap::kMutableHeapNumberMapRootIndex
@@ -2948,11 +3058,7 @@
   AssertIsRoot(heap_number_map, map_index);
 
   // Store heap number map in the allocated object.
-  if (tagging_mode == TAG_RESULT) {
     StoreP(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
-  } else {
-    StoreP(heap_number_map, MemOperand(result, HeapObject::kMapOffset));
-  }
 }
 
 void MacroAssembler::AllocateHeapNumberWithValue(
@@ -2971,7 +3077,8 @@
   DCHECK(!result.is(value));
 
   // Allocate JSValue in new space.
-  Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required, TAG_OBJECT);
+  Allocate(JSValue::kSize, result, scratch1, scratch2, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Initialize the JSValue.
   LoadGlobalFunctionInitialMap(constructor, scratch1, scratch2);
@@ -3539,7 +3646,7 @@
                                                      Label* no_memento_found) {
   Label map_check;
   Label top_check;
-  ExternalReference new_space_allocation_top =
+  ExternalReference new_space_allocation_top_adr =
       ExternalReference::new_space_allocation_top_address(isolate());
   const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
   const int kMementoEndOffset = kMementoMapOffset + AllocationMemento::kSize;
@@ -3550,11 +3657,13 @@
   JumpIfNotInNewSpace(receiver_reg, scratch_reg, no_memento_found);
 
   DCHECK((~Page::kPageAlignmentMask & 0xffff) == 0);
-  AddP(scratch_reg, receiver_reg, Operand(kMementoEndOffset));
 
   // If the object is in new space, we need to check whether it is on the same
   // page as the current top.
-  XorP(r0, scratch_reg, Operand(new_space_allocation_top));
+  AddP(scratch_reg, receiver_reg, Operand(kMementoEndOffset));
+  mov(ip, Operand(new_space_allocation_top_adr));
+  LoadP(ip, MemOperand(ip));
+  XorP(r0, scratch_reg, ip);
   AndP(r0, r0, Operand(~Page::kPageAlignmentMask));
   beq(&top_check, Label::kNear);
   // The object is on a different page than allocation top. Bail out if the
@@ -3568,7 +3677,7 @@
   // If top is on the same page as the current object, we need to check whether
   // we are below top.
   bind(&top_check);
-  CmpP(scratch_reg, Operand(new_space_allocation_top));
+  CmpP(scratch_reg, ip);
   bgt(no_memento_found);
   // Memento map check.
   bind(&map_check);
@@ -3587,8 +3696,7 @@
   if (reg5.is_valid()) regs |= reg5.bit();
   if (reg6.is_valid()) regs |= reg6.bit();
 
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
     int code = config->GetAllocatableGeneralCode(i);
     Register candidate = Register::from_code(code);
@@ -4639,7 +4747,6 @@
 // Branch On Count.  Decrement R1, and branch if R1 != 0.
 void MacroAssembler::BranchOnCount(Register r1, Label* l) {
   int32_t offset = branch_offset(l);
-  positions_recorder()->WriteRecordedPositions();
   if (is_int16(offset)) {
 #if V8_TARGET_ARCH_S390X
     brctg(r1, Operand(offset));
@@ -4961,6 +5068,14 @@
 #endif
 }
 
+void MacroAssembler::LoadB(Register dst, Register src) {
+#if V8_TARGET_ARCH_S390X
+  lgbr(dst, src);
+#else
+  lbr(dst, src);
+#endif
+}
+
 void MacroAssembler::LoadlB(Register dst, const MemOperand& mem) {
 #if V8_TARGET_ARCH_S390X
   llgc(dst, mem);
@@ -5300,7 +5415,7 @@
   ar(dst, r0);
   ShiftRight(r0, dst, Operand(8));
   ar(dst, r0);
-  lbr(dst, dst);
+  LoadB(dst, dst);
 }
 
 #ifdef V8_TARGET_ARCH_S390X
@@ -5315,7 +5430,7 @@
   AddP(dst, r0);
   ShiftRightP(r0, dst, Operand(8));
   AddP(dst, r0);
-  lbr(dst, dst);
+  LoadB(dst, dst);
 }
 #endif
 
diff --git a/src/s390/macro-assembler-s390.h b/src/s390/macro-assembler-s390.h
index 77fcccb..23b353e 100644
--- a/src/s390/macro-assembler-s390.h
+++ b/src/s390/macro-assembler-s390.h
@@ -19,10 +19,10 @@
 const Register kReturnRegister2 = {Register::kCode_r4};
 const Register kJSFunctionRegister = {Register::kCode_r3};
 const Register kContextRegister = {Register::kCode_r13};
+const Register kAllocateSizeRegister = {Register::kCode_r3};
 const Register kInterpreterAccumulatorRegister = {Register::kCode_r2};
-const Register kInterpreterRegisterFileRegister = {Register::kCode_r4};
-const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_r5};
-const Register kInterpreterBytecodeArrayRegister = {Register::kCode_r6};
+const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_r6};
+const Register kInterpreterBytecodeArrayRegister = {Register::kCode_r7};
 const Register kInterpreterDispatchTableRegister = {Register::kCode_r8};
 const Register kJavaScriptCallArgCountRegister = {Register::kCode_r2};
 const Register kJavaScriptCallNewTargetRegister = {Register::kCode_r5};
@@ -334,6 +334,7 @@
   void LoadlW(Register dst, const MemOperand& opnd, Register scratch = no_reg);
   void LoadlW(Register dst, Register src);
   void LoadB(Register dst, const MemOperand& opnd);
+  void LoadB(Register dst, Register src);
   void LoadlB(Register dst, const MemOperand& opnd);
 
   // Load And Test
@@ -411,6 +412,12 @@
 
   void mov(Register dst, const Operand& src);
 
+  void CleanUInt32(Register x) {
+#ifdef V8_TARGET_ARCH_S390X
+    llgfr(x, x);
+#endif
+  }
+
   // ---------------------------------------------------------------------------
   // GC Support
 
@@ -958,6 +965,15 @@
   void Allocate(Register object_size, Register result, Register result_end,
                 Register scratch, Label* gc_required, AllocationFlags flags);
 
+  // FastAllocate is right now only used for folded allocations. It just
+  // increments the top pointer without checking against limit. This can only
+  // be done if it was proved earlier that the allocation will succeed.
+  void FastAllocate(int object_size, Register result, Register scratch1,
+                    Register scratch2, AllocationFlags flags);
+
+  void FastAllocate(Register object_size, Register result, Register result_end,
+                    Register scratch, AllocationFlags flags);
+
   void AllocateTwoByteString(Register result, Register length,
                              Register scratch1, Register scratch2,
                              Register scratch3, Label* gc_required);
@@ -982,7 +998,6 @@
   // when control continues at the gc_required label.
   void AllocateHeapNumber(Register result, Register scratch1, Register scratch2,
                           Register heap_number_map, Label* gc_required,
-                          TaggingMode tagging_mode = TAG_RESULT,
                           MutableMode mode = IMMUTABLE);
   void AllocateHeapNumberWithValue(Register result, DoubleRegister value,
                                    Register scratch1, Register scratch2,
@@ -1567,17 +1582,29 @@
   }
 
   void IndexToArrayOffset(Register dst, Register src, int elementSizeLog2,
-                          bool isSmi) {
+                          bool isSmi, bool keyMaybeNegative) {
     if (isSmi) {
       SmiToArrayOffset(dst, src, elementSizeLog2);
-    } else {
+    } else if (keyMaybeNegative ||
+          !CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) {
 #if V8_TARGET_ARCH_S390X
+      // If array access is dehoisted, the key, being an int32, can contain
+      // a negative value, as needs to be sign-extended to 64-bit for
+      // memory access.
+      //
       // src (key) is a 32-bit integer.  Sign extension ensures
       // upper 32-bit does not contain garbage before being used to
       // reference memory.
       lgfr(src, src);
 #endif
       ShiftLeftP(dst, src, Operand(elementSizeLog2));
+    } else {
+      // Small optimization to reduce pathlength.  After Bounds Check,
+      // the key is guaranteed to be non-negative.  Leverage RISBG,
+      // which also performs zero-extension.
+      risbg(dst, src, Operand(32 - elementSizeLog2),
+            Operand(63 - elementSizeLog2), Operand(elementSizeLog2),
+            true);
     }
   }
 
@@ -1659,6 +1686,10 @@
   // enabled via --debug-code.
   void AssertBoundFunction(Register object);
 
+  // Abort execution if argument is not a JSGeneratorObject,
+  // enabled via --debug-code.
+  void AssertGeneratorObject(Register object);
+
   // Abort execution if argument is not a JSReceiver, enabled via --debug-code.
   void AssertReceiver(Register object);
 
diff --git a/src/s390/simulator-s390.cc b/src/s390/simulator-s390.cc
index 06e52a7..434fbff 100644
--- a/src/s390/simulator-s390.cc
+++ b/src/s390/simulator-s390.cc
@@ -10,6 +10,7 @@
 
 #include "src/assembler.h"
 #include "src/base/bits.h"
+#include "src/base/once.h"
 #include "src/codegen.h"
 #include "src/disasm.h"
 #include "src/runtime/runtime-utils.h"
@@ -22,6 +23,8 @@
 namespace v8 {
 namespace internal {
 
+const auto GetRegConfig = RegisterConfiguration::Crankshaft;
+
 // This macro provides a platform independent use of sscanf. The reason for
 // SScanF not being implemented in a platform independent way through
 // ::v8::internal::OS in the same way as SNPrintF is that the
@@ -274,18 +277,40 @@
               reinterpret_cast<Instruction*>(sim_->get_pc()));
         }
 
-        if (argc == 2 && last_pc != sim_->get_pc() && GetValue(arg1, &value)) {
-          for (int i = 1; (!sim_->has_bad_pc()) && i < value; i++) {
-            disasm::NameConverter converter;
-            disasm::Disassembler dasm(converter);
-            // use a reasonably large buffer
-            v8::internal::EmbeddedVector<char, 256> buffer;
-            dasm.InstructionDecode(buffer,
-                                   reinterpret_cast<byte*>(sim_->get_pc()));
-            PrintF("  0x%08" V8PRIxPTR "  %s\n", sim_->get_pc(),
-                   buffer.start());
-            sim_->ExecuteInstruction(
-                reinterpret_cast<Instruction*>(sim_->get_pc()));
+        if (argc == 2 && last_pc != sim_->get_pc()) {
+          disasm::NameConverter converter;
+          disasm::Disassembler dasm(converter);
+          // use a reasonably large buffer
+          v8::internal::EmbeddedVector<char, 256> buffer;
+
+          if (GetValue(arg1, &value)) {
+            // Interpret a numeric argument as the number of instructions to
+            // step past.
+            for (int i = 1; (!sim_->has_bad_pc()) &&  i < value; i++) {
+              dasm.InstructionDecode(buffer,
+                                    reinterpret_cast<byte*>(sim_->get_pc()));
+              PrintF("  0x%08" V8PRIxPTR "  %s\n", sim_->get_pc(),
+                    buffer.start());
+              sim_->ExecuteInstruction(
+                      reinterpret_cast<Instruction*>(sim_->get_pc()));
+            }
+          } else {
+            // Otherwise treat it as the mnemonic of the opcode to stop at.
+            char mnemonic[256];
+            while (!sim_->has_bad_pc()) {
+              dasm.InstructionDecode(buffer,
+                                    reinterpret_cast<byte*>(sim_->get_pc()));
+              char* mnemonicStart = buffer.start();
+              while (*mnemonicStart != 0 && *mnemonicStart != ' ')
+                mnemonicStart++;
+              SScanF(mnemonicStart, "%s", mnemonic);
+              if (!strcmp(arg1, mnemonic)) break;
+
+              PrintF("  0x%08" V8PRIxPTR "  %s\n", sim_->get_pc(),
+                    buffer.start());
+              sim_->ExecuteInstruction(
+                      reinterpret_cast<Instruction*>(sim_->get_pc()));
+            }
           }
         }
       } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
@@ -308,7 +333,7 @@
             for (int i = 0; i < kNumRegisters; i++) {
               value = GetRegisterValue(i);
               PrintF("    %3s: %08" V8PRIxPTR,
-                     Register::from_code(i).ToString(), value);
+                     GetRegConfig()->GetGeneralRegisterName(i), value);
               if ((argc == 3 && strcmp(arg2, "fp") == 0) && i < 8 &&
                   (i % 2) == 0) {
                 dvalue = GetRegisterPairDoubleValue(i);
@@ -323,7 +348,7 @@
             for (int i = 0; i < kNumRegisters; i++) {
               value = GetRegisterValue(i);
               PrintF("     %3s: %08" V8PRIxPTR " %11" V8PRIdPTR,
-                     Register::from_code(i).ToString(), value, value);
+                     GetRegConfig()->GetGeneralRegisterName(i), value, value);
               if ((argc == 3 && strcmp(arg2, "fp") == 0) && i < 8 &&
                   (i % 2) == 0) {
                 dvalue = GetRegisterPairDoubleValue(i);
@@ -339,14 +364,15 @@
               float fvalue = GetFPFloatRegisterValue(i);
               uint32_t as_words = bit_cast<uint32_t>(fvalue);
               PrintF("%3s: %f 0x%08x\n",
-                     DoubleRegister::from_code(i).ToString(), fvalue, as_words);
+                     GetRegConfig()->GetDoubleRegisterName(i), fvalue,
+                     as_words);
             }
           } else if (strcmp(arg1, "alld") == 0) {
             for (int i = 0; i < DoubleRegister::kNumRegisters; i++) {
               dvalue = GetFPDoubleRegisterValue(i);
               uint64_t as_words = bit_cast<uint64_t>(dvalue);
               PrintF("%3s: %f 0x%08x %08x\n",
-                     DoubleRegister::from_code(i).ToString(), dvalue,
+                     GetRegConfig()->GetDoubleRegisterName(i), dvalue,
                      static_cast<uint32_t>(as_words >> 32),
                      static_cast<uint32_t>(as_words & 0xffffffff));
             }
@@ -574,6 +600,8 @@
         } else {
           PrintF("Wrong usage. Use help command for more information.\n");
         }
+      } else if (strcmp(cmd, "icount") == 0) {
+        PrintF("%05" PRId64 "\n", sim_->icount_);
       } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) {
         ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
         PrintF("Trace of executed instructions is %s\n",
@@ -676,7 +704,7 @@
   last_debugger_input_ = input;
 }
 
-void Simulator::FlushICache(v8::internal::HashMap* i_cache, void* start_addr,
+void Simulator::FlushICache(base::HashMap* i_cache, void* start_addr,
                             size_t size) {
   intptr_t start = reinterpret_cast<intptr_t>(start_addr);
   int intra_line = (start & CachePage::kLineMask);
@@ -697,9 +725,8 @@
   }
 }
 
-CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
-  v8::internal::HashMap::Entry* entry =
-      i_cache->LookupOrInsert(page, ICacheHash(page));
+CachePage* Simulator::GetCachePage(base::HashMap* i_cache, void* page) {
+  base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page));
   if (entry->value == NULL) {
     CachePage* new_page = new CachePage();
     entry->value = new_page;
@@ -708,8 +735,7 @@
 }
 
 // Flush from start up to and not including start + size.
-void Simulator::FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
-                             int size) {
+void Simulator::FlushOnePage(base::HashMap* i_cache, intptr_t start, int size) {
   DCHECK(size <= CachePage::kPageSize);
   DCHECK(AllOnOnePage(start, size - 1));
   DCHECK((start & CachePage::kLineMask) == 0);
@@ -721,8 +747,7 @@
   memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
 }
 
-void Simulator::CheckICache(v8::internal::HashMap* i_cache,
-                            Instruction* instr) {
+void Simulator::CheckICache(base::HashMap* i_cache, Instruction* instr) {
   intptr_t address = reinterpret_cast<intptr_t>(instr);
   void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
   void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
@@ -748,12 +773,747 @@
   isolate->set_simulator_initialized(true);
   ::v8::internal::ExternalReference::set_redirector(isolate,
                                                     &RedirectExternalReference);
+  static base::OnceType once = V8_ONCE_INIT;
+  base::CallOnce(&once, &Simulator::EvalTableInit);
 }
 
+Simulator::EvaluateFuncType Simulator::EvalTable[] = {NULL};
+
+void Simulator::EvalTableInit() {
+  for (int i = 0; i < MAX_NUM_OPCODES; i++) {
+    EvalTable[i] = &Simulator::Evaluate_Unknown;
+  }
+
+  EvalTable[BKPT] = &Simulator::Evaluate_BKPT;
+  EvalTable[SPM] = &Simulator::Evaluate_SPM;
+  EvalTable[BALR] = &Simulator::Evaluate_BALR;
+  EvalTable[BCTR] = &Simulator::Evaluate_BCTR;
+  EvalTable[BCR] = &Simulator::Evaluate_BCR;
+  EvalTable[SVC] = &Simulator::Evaluate_SVC;
+  EvalTable[BSM] = &Simulator::Evaluate_BSM;
+  EvalTable[BASSM] = &Simulator::Evaluate_BASSM;
+  EvalTable[BASR] = &Simulator::Evaluate_BASR;
+  EvalTable[MVCL] = &Simulator::Evaluate_MVCL;
+  EvalTable[CLCL] = &Simulator::Evaluate_CLCL;
+  EvalTable[LPR] = &Simulator::Evaluate_LPR;
+  EvalTable[LNR] = &Simulator::Evaluate_LNR;
+  EvalTable[LTR] = &Simulator::Evaluate_LTR;
+  EvalTable[LCR] = &Simulator::Evaluate_LCR;
+  EvalTable[NR] = &Simulator::Evaluate_NR;
+  EvalTable[CLR] = &Simulator::Evaluate_CLR;
+  EvalTable[OR] = &Simulator::Evaluate_OR;
+  EvalTable[XR] = &Simulator::Evaluate_XR;
+  EvalTable[LR] = &Simulator::Evaluate_LR;
+  EvalTable[CR] = &Simulator::Evaluate_CR;
+  EvalTable[AR] = &Simulator::Evaluate_AR;
+  EvalTable[SR] = &Simulator::Evaluate_SR;
+  EvalTable[MR] = &Simulator::Evaluate_MR;
+  EvalTable[DR] = &Simulator::Evaluate_DR;
+  EvalTable[ALR] = &Simulator::Evaluate_ALR;
+  EvalTable[SLR] = &Simulator::Evaluate_SLR;
+  EvalTable[LDR] = &Simulator::Evaluate_LDR;
+  EvalTable[CDR] = &Simulator::Evaluate_CDR;
+  EvalTable[LER] = &Simulator::Evaluate_LER;
+  EvalTable[STH] = &Simulator::Evaluate_STH;
+  EvalTable[LA] = &Simulator::Evaluate_LA;
+  EvalTable[STC] = &Simulator::Evaluate_STC;
+  EvalTable[IC_z] = &Simulator::Evaluate_IC_z;
+  EvalTable[EX] = &Simulator::Evaluate_EX;
+  EvalTable[BAL] = &Simulator::Evaluate_BAL;
+  EvalTable[BCT] = &Simulator::Evaluate_BCT;
+  EvalTable[BC] = &Simulator::Evaluate_BC;
+  EvalTable[LH] = &Simulator::Evaluate_LH;
+  EvalTable[CH] = &Simulator::Evaluate_CH;
+  EvalTable[AH] = &Simulator::Evaluate_AH;
+  EvalTable[SH] = &Simulator::Evaluate_SH;
+  EvalTable[MH] = &Simulator::Evaluate_MH;
+  EvalTable[BAS] = &Simulator::Evaluate_BAS;
+  EvalTable[CVD] = &Simulator::Evaluate_CVD;
+  EvalTable[CVB] = &Simulator::Evaluate_CVB;
+  EvalTable[ST] = &Simulator::Evaluate_ST;
+  EvalTable[LAE] = &Simulator::Evaluate_LAE;
+  EvalTable[N] = &Simulator::Evaluate_N;
+  EvalTable[CL] = &Simulator::Evaluate_CL;
+  EvalTable[O] = &Simulator::Evaluate_O;
+  EvalTable[X] = &Simulator::Evaluate_X;
+  EvalTable[L] = &Simulator::Evaluate_L;
+  EvalTable[C] = &Simulator::Evaluate_C;
+  EvalTable[A] = &Simulator::Evaluate_A;
+  EvalTable[S] = &Simulator::Evaluate_S;
+  EvalTable[M] = &Simulator::Evaluate_M;
+  EvalTable[D] = &Simulator::Evaluate_D;
+  EvalTable[AL] = &Simulator::Evaluate_AL;
+  EvalTable[SL] = &Simulator::Evaluate_SL;
+  EvalTable[STD] = &Simulator::Evaluate_STD;
+  EvalTable[LD] = &Simulator::Evaluate_LD;
+  EvalTable[CD] = &Simulator::Evaluate_CD;
+  EvalTable[STE] = &Simulator::Evaluate_STE;
+  EvalTable[MS] = &Simulator::Evaluate_MS;
+  EvalTable[LE] = &Simulator::Evaluate_LE;
+  EvalTable[BRXH] = &Simulator::Evaluate_BRXH;
+  EvalTable[BRXLE] = &Simulator::Evaluate_BRXLE;
+  EvalTable[BXH] = &Simulator::Evaluate_BXH;
+  EvalTable[BXLE] = &Simulator::Evaluate_BXLE;
+  EvalTable[SRL] = &Simulator::Evaluate_SRL;
+  EvalTable[SLL] = &Simulator::Evaluate_SLL;
+  EvalTable[SRA] = &Simulator::Evaluate_SRA;
+  EvalTable[SLA] = &Simulator::Evaluate_SLA;
+  EvalTable[SRDL] = &Simulator::Evaluate_SRDL;
+  EvalTable[SLDL] = &Simulator::Evaluate_SLDL;
+  EvalTable[SRDA] = &Simulator::Evaluate_SRDA;
+  EvalTable[SLDA] = &Simulator::Evaluate_SLDA;
+  EvalTable[STM] = &Simulator::Evaluate_STM;
+  EvalTable[TM] = &Simulator::Evaluate_TM;
+  EvalTable[MVI] = &Simulator::Evaluate_MVI;
+  EvalTable[TS] = &Simulator::Evaluate_TS;
+  EvalTable[NI] = &Simulator::Evaluate_NI;
+  EvalTable[CLI] = &Simulator::Evaluate_CLI;
+  EvalTable[OI] = &Simulator::Evaluate_OI;
+  EvalTable[XI] = &Simulator::Evaluate_XI;
+  EvalTable[LM] = &Simulator::Evaluate_LM;
+  EvalTable[MVCLE] = &Simulator::Evaluate_MVCLE;
+  EvalTable[CLCLE] = &Simulator::Evaluate_CLCLE;
+  EvalTable[MC] = &Simulator::Evaluate_MC;
+  EvalTable[CDS] = &Simulator::Evaluate_CDS;
+  EvalTable[STCM] = &Simulator::Evaluate_STCM;
+  EvalTable[ICM] = &Simulator::Evaluate_ICM;
+  EvalTable[BPRP] = &Simulator::Evaluate_BPRP;
+  EvalTable[BPP] = &Simulator::Evaluate_BPP;
+  EvalTable[TRTR] = &Simulator::Evaluate_TRTR;
+  EvalTable[MVN] = &Simulator::Evaluate_MVN;
+  EvalTable[MVC] = &Simulator::Evaluate_MVC;
+  EvalTable[MVZ] = &Simulator::Evaluate_MVZ;
+  EvalTable[NC] = &Simulator::Evaluate_NC;
+  EvalTable[CLC] = &Simulator::Evaluate_CLC;
+  EvalTable[OC] = &Simulator::Evaluate_OC;
+  EvalTable[XC] = &Simulator::Evaluate_XC;
+  EvalTable[MVCP] = &Simulator::Evaluate_MVCP;
+  EvalTable[TR] = &Simulator::Evaluate_TR;
+  EvalTable[TRT] = &Simulator::Evaluate_TRT;
+  EvalTable[ED] = &Simulator::Evaluate_ED;
+  EvalTable[EDMK] = &Simulator::Evaluate_EDMK;
+  EvalTable[PKU] = &Simulator::Evaluate_PKU;
+  EvalTable[UNPKU] = &Simulator::Evaluate_UNPKU;
+  EvalTable[MVCIN] = &Simulator::Evaluate_MVCIN;
+  EvalTable[PKA] = &Simulator::Evaluate_PKA;
+  EvalTable[UNPKA] = &Simulator::Evaluate_UNPKA;
+  EvalTable[PLO] = &Simulator::Evaluate_PLO;
+  EvalTable[LMD] = &Simulator::Evaluate_LMD;
+  EvalTable[SRP] = &Simulator::Evaluate_SRP;
+  EvalTable[MVO] = &Simulator::Evaluate_MVO;
+  EvalTable[PACK] = &Simulator::Evaluate_PACK;
+  EvalTable[UNPK] = &Simulator::Evaluate_UNPK;
+  EvalTable[ZAP] = &Simulator::Evaluate_ZAP;
+  EvalTable[AP] = &Simulator::Evaluate_AP;
+  EvalTable[SP] = &Simulator::Evaluate_SP;
+  EvalTable[MP] = &Simulator::Evaluate_MP;
+  EvalTable[DP] = &Simulator::Evaluate_DP;
+  EvalTable[UPT] = &Simulator::Evaluate_UPT;
+  EvalTable[PFPO] = &Simulator::Evaluate_PFPO;
+  EvalTable[IIHH] = &Simulator::Evaluate_IIHH;
+  EvalTable[IIHL] = &Simulator::Evaluate_IIHL;
+  EvalTable[IILH] = &Simulator::Evaluate_IILH;
+  EvalTable[IILL] = &Simulator::Evaluate_IILL;
+  EvalTable[NIHH] = &Simulator::Evaluate_NIHH;
+  EvalTable[NIHL] = &Simulator::Evaluate_NIHL;
+  EvalTable[NILH] = &Simulator::Evaluate_NILH;
+  EvalTable[NILL] = &Simulator::Evaluate_NILL;
+  EvalTable[OIHH] = &Simulator::Evaluate_OIHH;
+  EvalTable[OIHL] = &Simulator::Evaluate_OIHL;
+  EvalTable[OILH] = &Simulator::Evaluate_OILH;
+  EvalTable[OILL] = &Simulator::Evaluate_OILL;
+  EvalTable[LLIHH] = &Simulator::Evaluate_LLIHH;
+  EvalTable[LLIHL] = &Simulator::Evaluate_LLIHL;
+  EvalTable[LLILH] = &Simulator::Evaluate_LLILH;
+  EvalTable[LLILL] = &Simulator::Evaluate_LLILL;
+  EvalTable[TMLH] = &Simulator::Evaluate_TMLH;
+  EvalTable[TMLL] = &Simulator::Evaluate_TMLL;
+  EvalTable[TMHH] = &Simulator::Evaluate_TMHH;
+  EvalTable[TMHL] = &Simulator::Evaluate_TMHL;
+  EvalTable[BRC] = &Simulator::Evaluate_BRC;
+  EvalTable[BRAS] = &Simulator::Evaluate_BRAS;
+  EvalTable[BRCT] = &Simulator::Evaluate_BRCT;
+  EvalTable[BRCTG] = &Simulator::Evaluate_BRCTG;
+  EvalTable[LHI] = &Simulator::Evaluate_LHI;
+  EvalTable[LGHI] = &Simulator::Evaluate_LGHI;
+  EvalTable[AHI] = &Simulator::Evaluate_AHI;
+  EvalTable[AGHI] = &Simulator::Evaluate_AGHI;
+  EvalTable[MHI] = &Simulator::Evaluate_MHI;
+  EvalTable[MGHI] = &Simulator::Evaluate_MGHI;
+  EvalTable[CHI] = &Simulator::Evaluate_CHI;
+  EvalTable[CGHI] = &Simulator::Evaluate_CGHI;
+  EvalTable[LARL] = &Simulator::Evaluate_LARL;
+  EvalTable[LGFI] = &Simulator::Evaluate_LGFI;
+  EvalTable[BRCL] = &Simulator::Evaluate_BRCL;
+  EvalTable[BRASL] = &Simulator::Evaluate_BRASL;
+  EvalTable[XIHF] = &Simulator::Evaluate_XIHF;
+  EvalTable[XILF] = &Simulator::Evaluate_XILF;
+  EvalTable[IIHF] = &Simulator::Evaluate_IIHF;
+  EvalTable[IILF] = &Simulator::Evaluate_IILF;
+  EvalTable[NIHF] = &Simulator::Evaluate_NIHF;
+  EvalTable[NILF] = &Simulator::Evaluate_NILF;
+  EvalTable[OIHF] = &Simulator::Evaluate_OIHF;
+  EvalTable[OILF] = &Simulator::Evaluate_OILF;
+  EvalTable[LLIHF] = &Simulator::Evaluate_LLIHF;
+  EvalTable[LLILF] = &Simulator::Evaluate_LLILF;
+  EvalTable[MSGFI] = &Simulator::Evaluate_MSGFI;
+  EvalTable[MSFI] = &Simulator::Evaluate_MSFI;
+  EvalTable[SLGFI] = &Simulator::Evaluate_SLGFI;
+  EvalTable[SLFI] = &Simulator::Evaluate_SLFI;
+  EvalTable[AGFI] = &Simulator::Evaluate_AGFI;
+  EvalTable[AFI] = &Simulator::Evaluate_AFI;
+  EvalTable[ALGFI] = &Simulator::Evaluate_ALGFI;
+  EvalTable[ALFI] = &Simulator::Evaluate_ALFI;
+  EvalTable[CGFI] = &Simulator::Evaluate_CGFI;
+  EvalTable[CFI] = &Simulator::Evaluate_CFI;
+  EvalTable[CLGFI] = &Simulator::Evaluate_CLGFI;
+  EvalTable[CLFI] = &Simulator::Evaluate_CLFI;
+  EvalTable[LLHRL] = &Simulator::Evaluate_LLHRL;
+  EvalTable[LGHRL] = &Simulator::Evaluate_LGHRL;
+  EvalTable[LHRL] = &Simulator::Evaluate_LHRL;
+  EvalTable[LLGHRL] = &Simulator::Evaluate_LLGHRL;
+  EvalTable[STHRL] = &Simulator::Evaluate_STHRL;
+  EvalTable[LGRL] = &Simulator::Evaluate_LGRL;
+  EvalTable[STGRL] = &Simulator::Evaluate_STGRL;
+  EvalTable[LGFRL] = &Simulator::Evaluate_LGFRL;
+  EvalTable[LRL] = &Simulator::Evaluate_LRL;
+  EvalTable[LLGFRL] = &Simulator::Evaluate_LLGFRL;
+  EvalTable[STRL] = &Simulator::Evaluate_STRL;
+  EvalTable[EXRL] = &Simulator::Evaluate_EXRL;
+  EvalTable[PFDRL] = &Simulator::Evaluate_PFDRL;
+  EvalTable[CGHRL] = &Simulator::Evaluate_CGHRL;
+  EvalTable[CHRL] = &Simulator::Evaluate_CHRL;
+  EvalTable[CGRL] = &Simulator::Evaluate_CGRL;
+  EvalTable[CGFRL] = &Simulator::Evaluate_CGFRL;
+  EvalTable[ECTG] = &Simulator::Evaluate_ECTG;
+  EvalTable[CSST] = &Simulator::Evaluate_CSST;
+  EvalTable[LPD] = &Simulator::Evaluate_LPD;
+  EvalTable[LPDG] = &Simulator::Evaluate_LPDG;
+  EvalTable[BRCTH] = &Simulator::Evaluate_BRCTH;
+  EvalTable[AIH] = &Simulator::Evaluate_AIH;
+  EvalTable[ALSIH] = &Simulator::Evaluate_ALSIH;
+  EvalTable[ALSIHN] = &Simulator::Evaluate_ALSIHN;
+  EvalTable[CIH] = &Simulator::Evaluate_CIH;
+  EvalTable[STCK] = &Simulator::Evaluate_STCK;
+  EvalTable[CFC] = &Simulator::Evaluate_CFC;
+  EvalTable[IPM] = &Simulator::Evaluate_IPM;
+  EvalTable[HSCH] = &Simulator::Evaluate_HSCH;
+  EvalTable[MSCH] = &Simulator::Evaluate_MSCH;
+  EvalTable[SSCH] = &Simulator::Evaluate_SSCH;
+  EvalTable[STSCH] = &Simulator::Evaluate_STSCH;
+  EvalTable[TSCH] = &Simulator::Evaluate_TSCH;
+  EvalTable[TPI] = &Simulator::Evaluate_TPI;
+  EvalTable[SAL] = &Simulator::Evaluate_SAL;
+  EvalTable[RSCH] = &Simulator::Evaluate_RSCH;
+  EvalTable[STCRW] = &Simulator::Evaluate_STCRW;
+  EvalTable[STCPS] = &Simulator::Evaluate_STCPS;
+  EvalTable[RCHP] = &Simulator::Evaluate_RCHP;
+  EvalTable[SCHM] = &Simulator::Evaluate_SCHM;
+  EvalTable[CKSM] = &Simulator::Evaluate_CKSM;
+  EvalTable[SAR] = &Simulator::Evaluate_SAR;
+  EvalTable[EAR] = &Simulator::Evaluate_EAR;
+  EvalTable[MSR] = &Simulator::Evaluate_MSR;
+  EvalTable[MVST] = &Simulator::Evaluate_MVST;
+  EvalTable[CUSE] = &Simulator::Evaluate_CUSE;
+  EvalTable[SRST] = &Simulator::Evaluate_SRST;
+  EvalTable[XSCH] = &Simulator::Evaluate_XSCH;
+  EvalTable[STCKE] = &Simulator::Evaluate_STCKE;
+  EvalTable[STCKF] = &Simulator::Evaluate_STCKF;
+  EvalTable[SRNM] = &Simulator::Evaluate_SRNM;
+  EvalTable[STFPC] = &Simulator::Evaluate_STFPC;
+  EvalTable[LFPC] = &Simulator::Evaluate_LFPC;
+  EvalTable[TRE] = &Simulator::Evaluate_TRE;
+  EvalTable[CUUTF] = &Simulator::Evaluate_CUUTF;
+  EvalTable[CUTFU] = &Simulator::Evaluate_CUTFU;
+  EvalTable[STFLE] = &Simulator::Evaluate_STFLE;
+  EvalTable[SRNMB] = &Simulator::Evaluate_SRNMB;
+  EvalTable[SRNMT] = &Simulator::Evaluate_SRNMT;
+  EvalTable[LFAS] = &Simulator::Evaluate_LFAS;
+  EvalTable[PPA] = &Simulator::Evaluate_PPA;
+  EvalTable[ETND] = &Simulator::Evaluate_ETND;
+  EvalTable[TEND] = &Simulator::Evaluate_TEND;
+  EvalTable[NIAI] = &Simulator::Evaluate_NIAI;
+  EvalTable[TABORT] = &Simulator::Evaluate_TABORT;
+  EvalTable[TRAP4] = &Simulator::Evaluate_TRAP4;
+  EvalTable[LPEBR] = &Simulator::Evaluate_LPEBR;
+  EvalTable[LNEBR] = &Simulator::Evaluate_LNEBR;
+  EvalTable[LTEBR] = &Simulator::Evaluate_LTEBR;
+  EvalTable[LCEBR] = &Simulator::Evaluate_LCEBR;
+  EvalTable[LDEBR] = &Simulator::Evaluate_LDEBR;
+  EvalTable[LXDBR] = &Simulator::Evaluate_LXDBR;
+  EvalTable[LXEBR] = &Simulator::Evaluate_LXEBR;
+  EvalTable[MXDBR] = &Simulator::Evaluate_MXDBR;
+  EvalTable[KEBR] = &Simulator::Evaluate_KEBR;
+  EvalTable[CEBR] = &Simulator::Evaluate_CEBR;
+  EvalTable[AEBR] = &Simulator::Evaluate_AEBR;
+  EvalTable[SEBR] = &Simulator::Evaluate_SEBR;
+  EvalTable[MDEBR] = &Simulator::Evaluate_MDEBR;
+  EvalTable[DEBR] = &Simulator::Evaluate_DEBR;
+  EvalTable[MAEBR] = &Simulator::Evaluate_MAEBR;
+  EvalTable[MSEBR] = &Simulator::Evaluate_MSEBR;
+  EvalTable[LPDBR] = &Simulator::Evaluate_LPDBR;
+  EvalTable[LNDBR] = &Simulator::Evaluate_LNDBR;
+  EvalTable[LTDBR] = &Simulator::Evaluate_LTDBR;
+  EvalTable[LCDBR] = &Simulator::Evaluate_LCDBR;
+  EvalTable[SQEBR] = &Simulator::Evaluate_SQEBR;
+  EvalTable[SQDBR] = &Simulator::Evaluate_SQDBR;
+  EvalTable[SQXBR] = &Simulator::Evaluate_SQXBR;
+  EvalTable[MEEBR] = &Simulator::Evaluate_MEEBR;
+  EvalTable[KDBR] = &Simulator::Evaluate_KDBR;
+  EvalTable[CDBR] = &Simulator::Evaluate_CDBR;
+  EvalTable[ADBR] = &Simulator::Evaluate_ADBR;
+  EvalTable[SDBR] = &Simulator::Evaluate_SDBR;
+  EvalTable[MDBR] = &Simulator::Evaluate_MDBR;
+  EvalTable[DDBR] = &Simulator::Evaluate_DDBR;
+  EvalTable[MADBR] = &Simulator::Evaluate_MADBR;
+  EvalTable[MSDBR] = &Simulator::Evaluate_MSDBR;
+  EvalTable[LPXBR] = &Simulator::Evaluate_LPXBR;
+  EvalTable[LNXBR] = &Simulator::Evaluate_LNXBR;
+  EvalTable[LTXBR] = &Simulator::Evaluate_LTXBR;
+  EvalTable[LCXBR] = &Simulator::Evaluate_LCXBR;
+  EvalTable[LEDBRA] = &Simulator::Evaluate_LEDBRA;
+  EvalTable[LDXBRA] = &Simulator::Evaluate_LDXBRA;
+  EvalTable[LEXBRA] = &Simulator::Evaluate_LEXBRA;
+  EvalTable[FIXBRA] = &Simulator::Evaluate_FIXBRA;
+  EvalTable[KXBR] = &Simulator::Evaluate_KXBR;
+  EvalTable[CXBR] = &Simulator::Evaluate_CXBR;
+  EvalTable[AXBR] = &Simulator::Evaluate_AXBR;
+  EvalTable[SXBR] = &Simulator::Evaluate_SXBR;
+  EvalTable[MXBR] = &Simulator::Evaluate_MXBR;
+  EvalTable[DXBR] = &Simulator::Evaluate_DXBR;
+  EvalTable[TBEDR] = &Simulator::Evaluate_TBEDR;
+  EvalTable[TBDR] = &Simulator::Evaluate_TBDR;
+  EvalTable[DIEBR] = &Simulator::Evaluate_DIEBR;
+  EvalTable[FIEBRA] = &Simulator::Evaluate_FIEBRA;
+  EvalTable[THDER] = &Simulator::Evaluate_THDER;
+  EvalTable[THDR] = &Simulator::Evaluate_THDR;
+  EvalTable[DIDBR] = &Simulator::Evaluate_DIDBR;
+  EvalTable[FIDBRA] = &Simulator::Evaluate_FIDBRA;
+  EvalTable[LXR] = &Simulator::Evaluate_LXR;
+  EvalTable[LPDFR] = &Simulator::Evaluate_LPDFR;
+  EvalTable[LNDFR] = &Simulator::Evaluate_LNDFR;
+  EvalTable[LCDFR] = &Simulator::Evaluate_LCDFR;
+  EvalTable[LZER] = &Simulator::Evaluate_LZER;
+  EvalTable[LZDR] = &Simulator::Evaluate_LZDR;
+  EvalTable[LZXR] = &Simulator::Evaluate_LZXR;
+  EvalTable[SFPC] = &Simulator::Evaluate_SFPC;
+  EvalTable[SFASR] = &Simulator::Evaluate_SFASR;
+  EvalTable[EFPC] = &Simulator::Evaluate_EFPC;
+  EvalTable[CELFBR] = &Simulator::Evaluate_CELFBR;
+  EvalTable[CDLFBR] = &Simulator::Evaluate_CDLFBR;
+  EvalTable[CXLFBR] = &Simulator::Evaluate_CXLFBR;
+  EvalTable[CEFBRA] = &Simulator::Evaluate_CEFBRA;
+  EvalTable[CDFBRA] = &Simulator::Evaluate_CDFBRA;
+  EvalTable[CXFBRA] = &Simulator::Evaluate_CXFBRA;
+  EvalTable[CFEBRA] = &Simulator::Evaluate_CFEBRA;
+  EvalTable[CFDBRA] = &Simulator::Evaluate_CFDBRA;
+  EvalTable[CFXBRA] = &Simulator::Evaluate_CFXBRA;
+  EvalTable[CLFEBR] = &Simulator::Evaluate_CLFEBR;
+  EvalTable[CLFDBR] = &Simulator::Evaluate_CLFDBR;
+  EvalTable[CLFXBR] = &Simulator::Evaluate_CLFXBR;
+  EvalTable[CELGBR] = &Simulator::Evaluate_CELGBR;
+  EvalTable[CDLGBR] = &Simulator::Evaluate_CDLGBR;
+  EvalTable[CXLGBR] = &Simulator::Evaluate_CXLGBR;
+  EvalTable[CEGBRA] = &Simulator::Evaluate_CEGBRA;
+  EvalTable[CDGBRA] = &Simulator::Evaluate_CDGBRA;
+  EvalTable[CXGBRA] = &Simulator::Evaluate_CXGBRA;
+  EvalTable[CGEBRA] = &Simulator::Evaluate_CGEBRA;
+  EvalTable[CGDBRA] = &Simulator::Evaluate_CGDBRA;
+  EvalTable[CGXBRA] = &Simulator::Evaluate_CGXBRA;
+  EvalTable[CLGEBR] = &Simulator::Evaluate_CLGEBR;
+  EvalTable[CLGDBR] = &Simulator::Evaluate_CLGDBR;
+  EvalTable[CFER] = &Simulator::Evaluate_CFER;
+  EvalTable[CFDR] = &Simulator::Evaluate_CFDR;
+  EvalTable[CFXR] = &Simulator::Evaluate_CFXR;
+  EvalTable[LDGR] = &Simulator::Evaluate_LDGR;
+  EvalTable[CGER] = &Simulator::Evaluate_CGER;
+  EvalTable[CGDR] = &Simulator::Evaluate_CGDR;
+  EvalTable[CGXR] = &Simulator::Evaluate_CGXR;
+  EvalTable[LGDR] = &Simulator::Evaluate_LGDR;
+  EvalTable[MDTR] = &Simulator::Evaluate_MDTR;
+  EvalTable[MDTRA] = &Simulator::Evaluate_MDTRA;
+  EvalTable[DDTRA] = &Simulator::Evaluate_DDTRA;
+  EvalTable[ADTRA] = &Simulator::Evaluate_ADTRA;
+  EvalTable[SDTRA] = &Simulator::Evaluate_SDTRA;
+  EvalTable[LDETR] = &Simulator::Evaluate_LDETR;
+  EvalTable[LEDTR] = &Simulator::Evaluate_LEDTR;
+  EvalTable[LTDTR] = &Simulator::Evaluate_LTDTR;
+  EvalTable[FIDTR] = &Simulator::Evaluate_FIDTR;
+  EvalTable[MXTRA] = &Simulator::Evaluate_MXTRA;
+  EvalTable[DXTRA] = &Simulator::Evaluate_DXTRA;
+  EvalTable[AXTRA] = &Simulator::Evaluate_AXTRA;
+  EvalTable[SXTRA] = &Simulator::Evaluate_SXTRA;
+  EvalTable[LXDTR] = &Simulator::Evaluate_LXDTR;
+  EvalTable[LDXTR] = &Simulator::Evaluate_LDXTR;
+  EvalTable[LTXTR] = &Simulator::Evaluate_LTXTR;
+  EvalTable[FIXTR] = &Simulator::Evaluate_FIXTR;
+  EvalTable[KDTR] = &Simulator::Evaluate_KDTR;
+  EvalTable[CGDTRA] = &Simulator::Evaluate_CGDTRA;
+  EvalTable[CUDTR] = &Simulator::Evaluate_CUDTR;
+  EvalTable[CDTR] = &Simulator::Evaluate_CDTR;
+  EvalTable[EEDTR] = &Simulator::Evaluate_EEDTR;
+  EvalTable[ESDTR] = &Simulator::Evaluate_ESDTR;
+  EvalTable[KXTR] = &Simulator::Evaluate_KXTR;
+  EvalTable[CGXTRA] = &Simulator::Evaluate_CGXTRA;
+  EvalTable[CUXTR] = &Simulator::Evaluate_CUXTR;
+  EvalTable[CSXTR] = &Simulator::Evaluate_CSXTR;
+  EvalTable[CXTR] = &Simulator::Evaluate_CXTR;
+  EvalTable[EEXTR] = &Simulator::Evaluate_EEXTR;
+  EvalTable[ESXTR] = &Simulator::Evaluate_ESXTR;
+  EvalTable[CDGTRA] = &Simulator::Evaluate_CDGTRA;
+  EvalTable[CDUTR] = &Simulator::Evaluate_CDUTR;
+  EvalTable[CDSTR] = &Simulator::Evaluate_CDSTR;
+  EvalTable[CEDTR] = &Simulator::Evaluate_CEDTR;
+  EvalTable[QADTR] = &Simulator::Evaluate_QADTR;
+  EvalTable[IEDTR] = &Simulator::Evaluate_IEDTR;
+  EvalTable[RRDTR] = &Simulator::Evaluate_RRDTR;
+  EvalTable[CXGTRA] = &Simulator::Evaluate_CXGTRA;
+  EvalTable[CXUTR] = &Simulator::Evaluate_CXUTR;
+  EvalTable[CXSTR] = &Simulator::Evaluate_CXSTR;
+  EvalTable[CEXTR] = &Simulator::Evaluate_CEXTR;
+  EvalTable[QAXTR] = &Simulator::Evaluate_QAXTR;
+  EvalTable[IEXTR] = &Simulator::Evaluate_IEXTR;
+  EvalTable[RRXTR] = &Simulator::Evaluate_RRXTR;
+  EvalTable[LPGR] = &Simulator::Evaluate_LPGR;
+  EvalTable[LNGR] = &Simulator::Evaluate_LNGR;
+  EvalTable[LTGR] = &Simulator::Evaluate_LTGR;
+  EvalTable[LCGR] = &Simulator::Evaluate_LCGR;
+  EvalTable[LGR] = &Simulator::Evaluate_LGR;
+  EvalTable[LGBR] = &Simulator::Evaluate_LGBR;
+  EvalTable[LGHR] = &Simulator::Evaluate_LGHR;
+  EvalTable[AGR] = &Simulator::Evaluate_AGR;
+  EvalTable[SGR] = &Simulator::Evaluate_SGR;
+  EvalTable[ALGR] = &Simulator::Evaluate_ALGR;
+  EvalTable[SLGR] = &Simulator::Evaluate_SLGR;
+  EvalTable[MSGR] = &Simulator::Evaluate_MSGR;
+  EvalTable[DSGR] = &Simulator::Evaluate_DSGR;
+  EvalTable[LRVGR] = &Simulator::Evaluate_LRVGR;
+  EvalTable[LPGFR] = &Simulator::Evaluate_LPGFR;
+  EvalTable[LNGFR] = &Simulator::Evaluate_LNGFR;
+  EvalTable[LTGFR] = &Simulator::Evaluate_LTGFR;
+  EvalTable[LCGFR] = &Simulator::Evaluate_LCGFR;
+  EvalTable[LGFR] = &Simulator::Evaluate_LGFR;
+  EvalTable[LLGFR] = &Simulator::Evaluate_LLGFR;
+  EvalTable[LLGTR] = &Simulator::Evaluate_LLGTR;
+  EvalTable[AGFR] = &Simulator::Evaluate_AGFR;
+  EvalTable[SGFR] = &Simulator::Evaluate_SGFR;
+  EvalTable[ALGFR] = &Simulator::Evaluate_ALGFR;
+  EvalTable[SLGFR] = &Simulator::Evaluate_SLGFR;
+  EvalTable[MSGFR] = &Simulator::Evaluate_MSGFR;
+  EvalTable[DSGFR] = &Simulator::Evaluate_DSGFR;
+  EvalTable[KMAC] = &Simulator::Evaluate_KMAC;
+  EvalTable[LRVR] = &Simulator::Evaluate_LRVR;
+  EvalTable[CGR] = &Simulator::Evaluate_CGR;
+  EvalTable[CLGR] = &Simulator::Evaluate_CLGR;
+  EvalTable[LBR] = &Simulator::Evaluate_LBR;
+  EvalTable[LHR] = &Simulator::Evaluate_LHR;
+  EvalTable[KMF] = &Simulator::Evaluate_KMF;
+  EvalTable[KMO] = &Simulator::Evaluate_KMO;
+  EvalTable[PCC] = &Simulator::Evaluate_PCC;
+  EvalTable[KMCTR] = &Simulator::Evaluate_KMCTR;
+  EvalTable[KM] = &Simulator::Evaluate_KM;
+  EvalTable[KMC] = &Simulator::Evaluate_KMC;
+  EvalTable[CGFR] = &Simulator::Evaluate_CGFR;
+  EvalTable[KIMD] = &Simulator::Evaluate_KIMD;
+  EvalTable[KLMD] = &Simulator::Evaluate_KLMD;
+  EvalTable[CFDTR] = &Simulator::Evaluate_CFDTR;
+  EvalTable[CLGDTR] = &Simulator::Evaluate_CLGDTR;
+  EvalTable[CLFDTR] = &Simulator::Evaluate_CLFDTR;
+  EvalTable[BCTGR] = &Simulator::Evaluate_BCTGR;
+  EvalTable[CFXTR] = &Simulator::Evaluate_CFXTR;
+  EvalTable[CLFXTR] = &Simulator::Evaluate_CLFXTR;
+  EvalTable[CDFTR] = &Simulator::Evaluate_CDFTR;
+  EvalTable[CDLGTR] = &Simulator::Evaluate_CDLGTR;
+  EvalTable[CDLFTR] = &Simulator::Evaluate_CDLFTR;
+  EvalTable[CXFTR] = &Simulator::Evaluate_CXFTR;
+  EvalTable[CXLGTR] = &Simulator::Evaluate_CXLGTR;
+  EvalTable[CXLFTR] = &Simulator::Evaluate_CXLFTR;
+  EvalTable[CGRT] = &Simulator::Evaluate_CGRT;
+  EvalTable[NGR] = &Simulator::Evaluate_NGR;
+  EvalTable[OGR] = &Simulator::Evaluate_OGR;
+  EvalTable[XGR] = &Simulator::Evaluate_XGR;
+  EvalTable[FLOGR] = &Simulator::Evaluate_FLOGR;
+  EvalTable[LLGCR] = &Simulator::Evaluate_LLGCR;
+  EvalTable[LLGHR] = &Simulator::Evaluate_LLGHR;
+  EvalTable[MLGR] = &Simulator::Evaluate_MLGR;
+  EvalTable[DLGR] = &Simulator::Evaluate_DLGR;
+  EvalTable[ALCGR] = &Simulator::Evaluate_ALCGR;
+  EvalTable[SLBGR] = &Simulator::Evaluate_SLBGR;
+  EvalTable[EPSW] = &Simulator::Evaluate_EPSW;
+  EvalTable[TRTT] = &Simulator::Evaluate_TRTT;
+  EvalTable[TRTO] = &Simulator::Evaluate_TRTO;
+  EvalTable[TROT] = &Simulator::Evaluate_TROT;
+  EvalTable[TROO] = &Simulator::Evaluate_TROO;
+  EvalTable[LLCR] = &Simulator::Evaluate_LLCR;
+  EvalTable[LLHR] = &Simulator::Evaluate_LLHR;
+  EvalTable[MLR] = &Simulator::Evaluate_MLR;
+  EvalTable[DLR] = &Simulator::Evaluate_DLR;
+  EvalTable[ALCR] = &Simulator::Evaluate_ALCR;
+  EvalTable[SLBR] = &Simulator::Evaluate_SLBR;
+  EvalTable[CU14] = &Simulator::Evaluate_CU14;
+  EvalTable[CU24] = &Simulator::Evaluate_CU24;
+  EvalTable[CU41] = &Simulator::Evaluate_CU41;
+  EvalTable[CU42] = &Simulator::Evaluate_CU42;
+  EvalTable[TRTRE] = &Simulator::Evaluate_TRTRE;
+  EvalTable[SRSTU] = &Simulator::Evaluate_SRSTU;
+  EvalTable[TRTE] = &Simulator::Evaluate_TRTE;
+  EvalTable[AHHHR] = &Simulator::Evaluate_AHHHR;
+  EvalTable[SHHHR] = &Simulator::Evaluate_SHHHR;
+  EvalTable[ALHHHR] = &Simulator::Evaluate_ALHHHR;
+  EvalTable[SLHHHR] = &Simulator::Evaluate_SLHHHR;
+  EvalTable[CHHR] = &Simulator::Evaluate_CHHR;
+  EvalTable[AHHLR] = &Simulator::Evaluate_AHHLR;
+  EvalTable[SHHLR] = &Simulator::Evaluate_SHHLR;
+  EvalTable[ALHHLR] = &Simulator::Evaluate_ALHHLR;
+  EvalTable[SLHHLR] = &Simulator::Evaluate_SLHHLR;
+  EvalTable[CHLR] = &Simulator::Evaluate_CHLR;
+  EvalTable[POPCNT_Z] = &Simulator::Evaluate_POPCNT_Z;
+  EvalTable[LOCGR] = &Simulator::Evaluate_LOCGR;
+  EvalTable[NGRK] = &Simulator::Evaluate_NGRK;
+  EvalTable[OGRK] = &Simulator::Evaluate_OGRK;
+  EvalTable[XGRK] = &Simulator::Evaluate_XGRK;
+  EvalTable[AGRK] = &Simulator::Evaluate_AGRK;
+  EvalTable[SGRK] = &Simulator::Evaluate_SGRK;
+  EvalTable[ALGRK] = &Simulator::Evaluate_ALGRK;
+  EvalTable[SLGRK] = &Simulator::Evaluate_SLGRK;
+  EvalTable[LOCR] = &Simulator::Evaluate_LOCR;
+  EvalTable[NRK] = &Simulator::Evaluate_NRK;
+  EvalTable[ORK] = &Simulator::Evaluate_ORK;
+  EvalTable[XRK] = &Simulator::Evaluate_XRK;
+  EvalTable[ARK] = &Simulator::Evaluate_ARK;
+  EvalTable[SRK] = &Simulator::Evaluate_SRK;
+  EvalTable[ALRK] = &Simulator::Evaluate_ALRK;
+  EvalTable[SLRK] = &Simulator::Evaluate_SLRK;
+  EvalTable[LTG] = &Simulator::Evaluate_LTG;
+  EvalTable[LG] = &Simulator::Evaluate_LG;
+  EvalTable[CVBY] = &Simulator::Evaluate_CVBY;
+  EvalTable[AG] = &Simulator::Evaluate_AG;
+  EvalTable[SG] = &Simulator::Evaluate_SG;
+  EvalTable[ALG] = &Simulator::Evaluate_ALG;
+  EvalTable[SLG] = &Simulator::Evaluate_SLG;
+  EvalTable[MSG] = &Simulator::Evaluate_MSG;
+  EvalTable[DSG] = &Simulator::Evaluate_DSG;
+  EvalTable[CVBG] = &Simulator::Evaluate_CVBG;
+  EvalTable[LRVG] = &Simulator::Evaluate_LRVG;
+  EvalTable[LT] = &Simulator::Evaluate_LT;
+  EvalTable[LGF] = &Simulator::Evaluate_LGF;
+  EvalTable[LGH] = &Simulator::Evaluate_LGH;
+  EvalTable[LLGF] = &Simulator::Evaluate_LLGF;
+  EvalTable[LLGT] = &Simulator::Evaluate_LLGT;
+  EvalTable[AGF] = &Simulator::Evaluate_AGF;
+  EvalTable[SGF] = &Simulator::Evaluate_SGF;
+  EvalTable[ALGF] = &Simulator::Evaluate_ALGF;
+  EvalTable[SLGF] = &Simulator::Evaluate_SLGF;
+  EvalTable[MSGF] = &Simulator::Evaluate_MSGF;
+  EvalTable[DSGF] = &Simulator::Evaluate_DSGF;
+  EvalTable[LRV] = &Simulator::Evaluate_LRV;
+  EvalTable[LRVH] = &Simulator::Evaluate_LRVH;
+  EvalTable[CG] = &Simulator::Evaluate_CG;
+  EvalTable[CLG] = &Simulator::Evaluate_CLG;
+  EvalTable[STG] = &Simulator::Evaluate_STG;
+  EvalTable[NTSTG] = &Simulator::Evaluate_NTSTG;
+  EvalTable[CVDY] = &Simulator::Evaluate_CVDY;
+  EvalTable[CVDG] = &Simulator::Evaluate_CVDG;
+  EvalTable[STRVG] = &Simulator::Evaluate_STRVG;
+  EvalTable[CGF] = &Simulator::Evaluate_CGF;
+  EvalTable[CLGF] = &Simulator::Evaluate_CLGF;
+  EvalTable[LTGF] = &Simulator::Evaluate_LTGF;
+  EvalTable[CGH] = &Simulator::Evaluate_CGH;
+  EvalTable[PFD] = &Simulator::Evaluate_PFD;
+  EvalTable[STRV] = &Simulator::Evaluate_STRV;
+  EvalTable[STRVH] = &Simulator::Evaluate_STRVH;
+  EvalTable[BCTG] = &Simulator::Evaluate_BCTG;
+  EvalTable[STY] = &Simulator::Evaluate_STY;
+  EvalTable[MSY] = &Simulator::Evaluate_MSY;
+  EvalTable[NY] = &Simulator::Evaluate_NY;
+  EvalTable[CLY] = &Simulator::Evaluate_CLY;
+  EvalTable[OY] = &Simulator::Evaluate_OY;
+  EvalTable[XY] = &Simulator::Evaluate_XY;
+  EvalTable[LY] = &Simulator::Evaluate_LY;
+  EvalTable[CY] = &Simulator::Evaluate_CY;
+  EvalTable[AY] = &Simulator::Evaluate_AY;
+  EvalTable[SY] = &Simulator::Evaluate_SY;
+  EvalTable[MFY] = &Simulator::Evaluate_MFY;
+  EvalTable[ALY] = &Simulator::Evaluate_ALY;
+  EvalTable[SLY] = &Simulator::Evaluate_SLY;
+  EvalTable[STHY] = &Simulator::Evaluate_STHY;
+  EvalTable[LAY] = &Simulator::Evaluate_LAY;
+  EvalTable[STCY] = &Simulator::Evaluate_STCY;
+  EvalTable[ICY] = &Simulator::Evaluate_ICY;
+  EvalTable[LAEY] = &Simulator::Evaluate_LAEY;
+  EvalTable[LB] = &Simulator::Evaluate_LB;
+  EvalTable[LGB] = &Simulator::Evaluate_LGB;
+  EvalTable[LHY] = &Simulator::Evaluate_LHY;
+  EvalTable[CHY] = &Simulator::Evaluate_CHY;
+  EvalTable[AHY] = &Simulator::Evaluate_AHY;
+  EvalTable[SHY] = &Simulator::Evaluate_SHY;
+  EvalTable[MHY] = &Simulator::Evaluate_MHY;
+  EvalTable[NG] = &Simulator::Evaluate_NG;
+  EvalTable[OG] = &Simulator::Evaluate_OG;
+  EvalTable[XG] = &Simulator::Evaluate_XG;
+  EvalTable[LGAT] = &Simulator::Evaluate_LGAT;
+  EvalTable[MLG] = &Simulator::Evaluate_MLG;
+  EvalTable[DLG] = &Simulator::Evaluate_DLG;
+  EvalTable[ALCG] = &Simulator::Evaluate_ALCG;
+  EvalTable[SLBG] = &Simulator::Evaluate_SLBG;
+  EvalTable[STPQ] = &Simulator::Evaluate_STPQ;
+  EvalTable[LPQ] = &Simulator::Evaluate_LPQ;
+  EvalTable[LLGC] = &Simulator::Evaluate_LLGC;
+  EvalTable[LLGH] = &Simulator::Evaluate_LLGH;
+  EvalTable[LLC] = &Simulator::Evaluate_LLC;
+  EvalTable[LLH] = &Simulator::Evaluate_LLH;
+  EvalTable[ML] = &Simulator::Evaluate_ML;
+  EvalTable[DL] = &Simulator::Evaluate_DL;
+  EvalTable[ALC] = &Simulator::Evaluate_ALC;
+  EvalTable[SLB] = &Simulator::Evaluate_SLB;
+  EvalTable[LLGTAT] = &Simulator::Evaluate_LLGTAT;
+  EvalTable[LLGFAT] = &Simulator::Evaluate_LLGFAT;
+  EvalTable[LAT] = &Simulator::Evaluate_LAT;
+  EvalTable[LBH] = &Simulator::Evaluate_LBH;
+  EvalTable[LLCH] = &Simulator::Evaluate_LLCH;
+  EvalTable[STCH] = &Simulator::Evaluate_STCH;
+  EvalTable[LHH] = &Simulator::Evaluate_LHH;
+  EvalTable[LLHH] = &Simulator::Evaluate_LLHH;
+  EvalTable[STHH] = &Simulator::Evaluate_STHH;
+  EvalTable[LFHAT] = &Simulator::Evaluate_LFHAT;
+  EvalTable[LFH] = &Simulator::Evaluate_LFH;
+  EvalTable[STFH] = &Simulator::Evaluate_STFH;
+  EvalTable[CHF] = &Simulator::Evaluate_CHF;
+  EvalTable[MVCDK] = &Simulator::Evaluate_MVCDK;
+  EvalTable[MVHHI] = &Simulator::Evaluate_MVHHI;
+  EvalTable[MVGHI] = &Simulator::Evaluate_MVGHI;
+  EvalTable[MVHI] = &Simulator::Evaluate_MVHI;
+  EvalTable[CHHSI] = &Simulator::Evaluate_CHHSI;
+  EvalTable[CGHSI] = &Simulator::Evaluate_CGHSI;
+  EvalTable[CHSI] = &Simulator::Evaluate_CHSI;
+  EvalTable[CLFHSI] = &Simulator::Evaluate_CLFHSI;
+  EvalTable[TBEGIN] = &Simulator::Evaluate_TBEGIN;
+  EvalTable[TBEGINC] = &Simulator::Evaluate_TBEGINC;
+  EvalTable[LMG] = &Simulator::Evaluate_LMG;
+  EvalTable[SRAG] = &Simulator::Evaluate_SRAG;
+  EvalTable[SLAG] = &Simulator::Evaluate_SLAG;
+  EvalTable[SRLG] = &Simulator::Evaluate_SRLG;
+  EvalTable[SLLG] = &Simulator::Evaluate_SLLG;
+  EvalTable[CSY] = &Simulator::Evaluate_CSY;
+  EvalTable[RLLG] = &Simulator::Evaluate_RLLG;
+  EvalTable[RLL] = &Simulator::Evaluate_RLL;
+  EvalTable[STMG] = &Simulator::Evaluate_STMG;
+  EvalTable[STMH] = &Simulator::Evaluate_STMH;
+  EvalTable[STCMH] = &Simulator::Evaluate_STCMH;
+  EvalTable[STCMY] = &Simulator::Evaluate_STCMY;
+  EvalTable[CDSY] = &Simulator::Evaluate_CDSY;
+  EvalTable[CDSG] = &Simulator::Evaluate_CDSG;
+  EvalTable[BXHG] = &Simulator::Evaluate_BXHG;
+  EvalTable[BXLEG] = &Simulator::Evaluate_BXLEG;
+  EvalTable[ECAG] = &Simulator::Evaluate_ECAG;
+  EvalTable[TMY] = &Simulator::Evaluate_TMY;
+  EvalTable[MVIY] = &Simulator::Evaluate_MVIY;
+  EvalTable[NIY] = &Simulator::Evaluate_NIY;
+  EvalTable[CLIY] = &Simulator::Evaluate_CLIY;
+  EvalTable[OIY] = &Simulator::Evaluate_OIY;
+  EvalTable[XIY] = &Simulator::Evaluate_XIY;
+  EvalTable[ASI] = &Simulator::Evaluate_ASI;
+  EvalTable[ALSI] = &Simulator::Evaluate_ALSI;
+  EvalTable[AGSI] = &Simulator::Evaluate_AGSI;
+  EvalTable[ALGSI] = &Simulator::Evaluate_ALGSI;
+  EvalTable[ICMH] = &Simulator::Evaluate_ICMH;
+  EvalTable[ICMY] = &Simulator::Evaluate_ICMY;
+  EvalTable[MVCLU] = &Simulator::Evaluate_MVCLU;
+  EvalTable[CLCLU] = &Simulator::Evaluate_CLCLU;
+  EvalTable[STMY] = &Simulator::Evaluate_STMY;
+  EvalTable[LMH] = &Simulator::Evaluate_LMH;
+  EvalTable[LMY] = &Simulator::Evaluate_LMY;
+  EvalTable[TP] = &Simulator::Evaluate_TP;
+  EvalTable[SRAK] = &Simulator::Evaluate_SRAK;
+  EvalTable[SLAK] = &Simulator::Evaluate_SLAK;
+  EvalTable[SRLK] = &Simulator::Evaluate_SRLK;
+  EvalTable[SLLK] = &Simulator::Evaluate_SLLK;
+  EvalTable[LOCG] = &Simulator::Evaluate_LOCG;
+  EvalTable[STOCG] = &Simulator::Evaluate_STOCG;
+  EvalTable[LANG] = &Simulator::Evaluate_LANG;
+  EvalTable[LAOG] = &Simulator::Evaluate_LAOG;
+  EvalTable[LAXG] = &Simulator::Evaluate_LAXG;
+  EvalTable[LAAG] = &Simulator::Evaluate_LAAG;
+  EvalTable[LAALG] = &Simulator::Evaluate_LAALG;
+  EvalTable[LOC] = &Simulator::Evaluate_LOC;
+  EvalTable[STOC] = &Simulator::Evaluate_STOC;
+  EvalTable[LAN] = &Simulator::Evaluate_LAN;
+  EvalTable[LAO] = &Simulator::Evaluate_LAO;
+  EvalTable[LAX] = &Simulator::Evaluate_LAX;
+  EvalTable[LAA] = &Simulator::Evaluate_LAA;
+  EvalTable[LAAL] = &Simulator::Evaluate_LAAL;
+  EvalTable[BRXHG] = &Simulator::Evaluate_BRXHG;
+  EvalTable[BRXLG] = &Simulator::Evaluate_BRXLG;
+  EvalTable[RISBLG] = &Simulator::Evaluate_RISBLG;
+  EvalTable[RNSBG] = &Simulator::Evaluate_RNSBG;
+  EvalTable[RISBG] = &Simulator::Evaluate_RISBG;
+  EvalTable[ROSBG] = &Simulator::Evaluate_ROSBG;
+  EvalTable[RXSBG] = &Simulator::Evaluate_RXSBG;
+  EvalTable[RISBGN] = &Simulator::Evaluate_RISBGN;
+  EvalTable[RISBHG] = &Simulator::Evaluate_RISBHG;
+  EvalTable[CGRJ] = &Simulator::Evaluate_CGRJ;
+  EvalTable[CGIT] = &Simulator::Evaluate_CGIT;
+  EvalTable[CIT] = &Simulator::Evaluate_CIT;
+  EvalTable[CLFIT] = &Simulator::Evaluate_CLFIT;
+  EvalTable[CGIJ] = &Simulator::Evaluate_CGIJ;
+  EvalTable[CIJ] = &Simulator::Evaluate_CIJ;
+  EvalTable[AHIK] = &Simulator::Evaluate_AHIK;
+  EvalTable[AGHIK] = &Simulator::Evaluate_AGHIK;
+  EvalTable[ALHSIK] = &Simulator::Evaluate_ALHSIK;
+  EvalTable[ALGHSIK] = &Simulator::Evaluate_ALGHSIK;
+  EvalTable[CGRB] = &Simulator::Evaluate_CGRB;
+  EvalTable[CGIB] = &Simulator::Evaluate_CGIB;
+  EvalTable[CIB] = &Simulator::Evaluate_CIB;
+  EvalTable[LDEB] = &Simulator::Evaluate_LDEB;
+  EvalTable[LXDB] = &Simulator::Evaluate_LXDB;
+  EvalTable[LXEB] = &Simulator::Evaluate_LXEB;
+  EvalTable[MXDB] = &Simulator::Evaluate_MXDB;
+  EvalTable[KEB] = &Simulator::Evaluate_KEB;
+  EvalTable[CEB] = &Simulator::Evaluate_CEB;
+  EvalTable[AEB] = &Simulator::Evaluate_AEB;
+  EvalTable[SEB] = &Simulator::Evaluate_SEB;
+  EvalTable[MDEB] = &Simulator::Evaluate_MDEB;
+  EvalTable[DEB] = &Simulator::Evaluate_DEB;
+  EvalTable[MAEB] = &Simulator::Evaluate_MAEB;
+  EvalTable[MSEB] = &Simulator::Evaluate_MSEB;
+  EvalTable[TCEB] = &Simulator::Evaluate_TCEB;
+  EvalTable[TCDB] = &Simulator::Evaluate_TCDB;
+  EvalTable[TCXB] = &Simulator::Evaluate_TCXB;
+  EvalTable[SQEB] = &Simulator::Evaluate_SQEB;
+  EvalTable[SQDB] = &Simulator::Evaluate_SQDB;
+  EvalTable[MEEB] = &Simulator::Evaluate_MEEB;
+  EvalTable[KDB] = &Simulator::Evaluate_KDB;
+  EvalTable[CDB] = &Simulator::Evaluate_CDB;
+  EvalTable[ADB] = &Simulator::Evaluate_ADB;
+  EvalTable[SDB] = &Simulator::Evaluate_SDB;
+  EvalTable[MDB] = &Simulator::Evaluate_MDB;
+  EvalTable[DDB] = &Simulator::Evaluate_DDB;
+  EvalTable[MADB] = &Simulator::Evaluate_MADB;
+  EvalTable[MSDB] = &Simulator::Evaluate_MSDB;
+  EvalTable[SLDT] = &Simulator::Evaluate_SLDT;
+  EvalTable[SRDT] = &Simulator::Evaluate_SRDT;
+  EvalTable[SLXT] = &Simulator::Evaluate_SLXT;
+  EvalTable[SRXT] = &Simulator::Evaluate_SRXT;
+  EvalTable[TDCET] = &Simulator::Evaluate_TDCET;
+  EvalTable[TDGET] = &Simulator::Evaluate_TDGET;
+  EvalTable[TDCDT] = &Simulator::Evaluate_TDCDT;
+  EvalTable[TDGDT] = &Simulator::Evaluate_TDGDT;
+  EvalTable[TDCXT] = &Simulator::Evaluate_TDCXT;
+  EvalTable[TDGXT] = &Simulator::Evaluate_TDGXT;
+  EvalTable[LEY] = &Simulator::Evaluate_LEY;
+  EvalTable[LDY] = &Simulator::Evaluate_LDY;
+  EvalTable[STEY] = &Simulator::Evaluate_STEY;
+  EvalTable[STDY] = &Simulator::Evaluate_STDY;
+  EvalTable[CZDT] = &Simulator::Evaluate_CZDT;
+  EvalTable[CZXT] = &Simulator::Evaluate_CZXT;
+  EvalTable[CDZT] = &Simulator::Evaluate_CDZT;
+  EvalTable[CXZT] = &Simulator::Evaluate_CXZT;
+}  // NOLINT
+
 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
   i_cache_ = isolate_->simulator_i_cache();
   if (i_cache_ == NULL) {
-    i_cache_ = new v8::internal::HashMap(&ICacheMatch);
+    i_cache_ = new base::HashMap(&ICacheMatch);
     isolate_->set_simulator_i_cache(i_cache_);
   }
   Initialize(isolate);
@@ -894,10 +1654,10 @@
 };
 
 // static
-void Simulator::TearDown(HashMap* i_cache, Redirection* first) {
+void Simulator::TearDown(base::HashMap* i_cache, Redirection* first) {
   Redirection::DeleteChain(first);
   if (i_cache != nullptr) {
-    for (HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
+    for (base::HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
          entry = i_cache->Next(entry)) {
       delete static_cast<CachePage*>(entry->value);
     }
@@ -1268,15 +2028,17 @@
             case ExternalReference::BUILTIN_FP_FP_CALL:
             case ExternalReference::BUILTIN_COMPARE_CALL:
               PrintF("Call to host function at %p with args %f, %f",
-                     FUNCTION_ADDR(generic_target), dval0, dval1);
+                     static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
+                     dval1);
               break;
             case ExternalReference::BUILTIN_FP_CALL:
               PrintF("Call to host function at %p with arg %f",
-                     FUNCTION_ADDR(generic_target), dval0);
+                     static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0);
               break;
             case ExternalReference::BUILTIN_FP_INT_CALL:
               PrintF("Call to host function at %p with args %f, %" V8PRIdPTR,
-                     FUNCTION_ADDR(generic_target), dval0, ival);
+                     static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
+                     ival);
               break;
             default:
               UNREACHABLE();
@@ -1418,8 +2180,8 @@
               "Call to host function at %p,\n"
               "\t\t\t\targs %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR
               ", %08" V8PRIxPTR ", %08" V8PRIxPTR ", %08" V8PRIxPTR,
-              FUNCTION_ADDR(target), arg[0], arg[1], arg[2], arg[3], arg[4],
-              arg[5]);
+              static_cast<void*>(FUNCTION_ADDR(target)), arg[0], arg[1], arg[2],
+              arg[3], arg[4], arg[5]);
           if (!stack_aligned) {
             PrintF(" with unaligned stack %08" V8PRIxPTR "\n",
                    static_cast<intptr_t>(get_register(sp)));
@@ -2587,6 +3349,7 @@
         SetS390OverflowCode(isOF);
         set_register(r1, r2_val - r3_val);
       }
+      break;
     }
     case AGHI:
     case MGHI: {
@@ -2987,17 +3750,19 @@
       RREInstruction* rrinst = reinterpret_cast<RREInstruction*>(instr);
       int r1 = rrinst->R1Value();
       int r2 = rrinst->R2Value();
-#ifdef V8_TARGET_ARCH_S390X
+      if (op == LGBR) {
       int64_t r2_val = get_low_register<int64_t>(r2);
       r2_val <<= 56;
       r2_val >>= 56;
       set_register(r1, r2_val);
-#else
+      } else if (op == LBR) {
       int32_t r2_val = get_low_register<int32_t>(r2);
       r2_val <<= 24;
       r2_val >>= 24;
       set_low_register(r1, r2_val);
-#endif
+      } else {
+        UNREACHABLE();
+      }
       break;
     }
     case LGHR:
@@ -3005,17 +3770,19 @@
       RREInstruction* rrinst = reinterpret_cast<RREInstruction*>(instr);
       int r1 = rrinst->R1Value();
       int r2 = rrinst->R2Value();
-#ifdef V8_TARGET_ARCH_S390X
+      if (op == LGHR) {
       int64_t r2_val = get_low_register<int64_t>(r2);
       r2_val <<= 48;
       r2_val >>= 48;
       set_register(r1, r2_val);
-#else
+      } else if (op == LHR) {
       int32_t r2_val = get_low_register<int32_t>(r2);
       r2_val <<= 16;
       r2_val >>= 16;
       set_low_register(r1, r2_val);
-#endif
+      } else {
+        UNREACHABLE();
+      }
       break;
     }
     case ALCR: {
@@ -4802,47 +5569,56 @@
   return result;
 }
 
-// Executes the current instruction.
-void Simulator::ExecuteInstruction(Instruction* instr, bool auto_incr_pc) {
-  if (v8::internal::FLAG_check_icache) {
-    CheckICache(isolate_->simulator_i_cache(), instr);
-  }
-  pc_modified_ = false;
-  if (::v8::internal::FLAG_trace_sim) {
-    disasm::NameConverter converter;
-    disasm::Disassembler dasm(converter);
-    // use a reasonably large buffer
-    v8::internal::EmbeddedVector<char, 256> buffer;
-    dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
-#ifdef V8_TARGET_ARCH_S390X
-    PrintF("%05ld  %08" V8PRIxPTR "  %s\n", icount_,
-           reinterpret_cast<intptr_t>(instr), buffer.start());
-#else
-    PrintF("%05lld  %08" V8PRIxPTR "  %s\n", icount_,
-           reinterpret_cast<intptr_t>(instr), buffer.start());
-#endif
-    // Flush stdout to prevent incomplete file output during abnormal exits
-    // This is caused by the output being buffered before being written to file
-    fflush(stdout);
-  }
-
-  // Try to simulate as S390 Instruction first.
-  bool processed = true;
-
+int Simulator::DecodeInstructionOriginal(Instruction* instr) {
   int instrLength = instr->InstructionLength();
+  bool processed = true;
   if (instrLength == 2)
     processed = DecodeTwoByte(instr);
   else if (instrLength == 4)
     processed = DecodeFourByte(instr);
   else if (instrLength == 6)
     processed = DecodeSixByte(instr);
+  return instrLength;
+}
 
-  if (processed) {
-    if (!pc_modified_ && auto_incr_pc) {
-      set_pc(reinterpret_cast<intptr_t>(instr) + instrLength);
-    }
-    return;
+int Simulator::DecodeInstruction(Instruction* instr) {
+  Opcode op = instr->S390OpcodeValue();
+  DCHECK(EvalTable[op] != NULL);
+  return (this->*EvalTable[op])(instr);
+}
+
+// Executes the current instruction.
+void Simulator::ExecuteInstruction(Instruction* instr, bool auto_incr_pc) {
+  icount_++;
+
+  if (v8::internal::FLAG_check_icache) {
+    CheckICache(isolate_->simulator_i_cache(), instr);
   }
+
+  pc_modified_ = false;
+
+  if (::v8::internal::FLAG_trace_sim) {
+    disasm::NameConverter converter;
+    disasm::Disassembler dasm(converter);
+    // use a reasonably large buffer
+    v8::internal::EmbeddedVector<char, 256> buffer;
+    dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
+    PrintF("%05" PRId64 "  %08" V8PRIxPTR "  %s\n", icount_,
+           reinterpret_cast<intptr_t>(instr), buffer.start());
+
+    // Flush stdout to prevent incomplete file output during abnormal exits
+    // This is caused by the output being buffered before being written to file
+    fflush(stdout);
+  }
+
+  // Try to simulate as S390 Instruction first.
+  int length = DecodeInstruction(instr);
+
+  if (!pc_modified_ && auto_incr_pc) {
+    DCHECK(length == instr->InstructionLength());
+    set_pc(reinterpret_cast<intptr_t>(instr) + length);
+  }
+  return;
 }
 
 void Simulator::DebugStart() {
@@ -4860,7 +5636,6 @@
     // should be stopping at a particular executed instruction.
     while (program_counter != end_sim_pc) {
       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
-      icount_++;
       ExecuteInstruction(instr);
       program_counter = get_pc();
     }
@@ -4869,7 +5644,6 @@
     // we reach the particular instuction count.
     while (program_counter != end_sim_pc) {
       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
-      icount_++;
       if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
         S390Debugger dbg(this);
         dbg.Debug();
@@ -4882,6 +5656,9 @@
 }
 
 void Simulator::CallInternal(byte* entry, int reg_arg_count) {
+  // Adjust JS-based stack limit to C-based stack limit.
+  isolate_->stack_guard()->AdjustStackLimitForSimulator();
+
   // Prepare to execute the code at entry
   if (ABI_USES_FUNCTION_DESCRIPTORS) {
     // entry is the function descriptor
@@ -4964,6 +5741,9 @@
 }
 
 intptr_t Simulator::Call(byte* entry, int argument_count, ...) {
+  // Adjust JS-based stack limit to C-based stack limit.
+  isolate_->stack_guard()->AdjustStackLimitForSimulator();
+
   // Remember the values of non-volatile registers.
   int64_t r6_val = get_register(r6);
   int64_t r7_val = get_register(r7);
@@ -5121,6 +5901,6672 @@
   return address;
 }
 
+#define EVALUATE(name) \
+  int Simulator::Evaluate_##name(Instruction* instr)
+
+#define DCHECK_OPCODE(op) DCHECK(instr->S390OpcodeValue() == op)
+
+#define AS(type) reinterpret_cast<type*>(instr)
+
+#define DECODE_RIL_A_INSTRUCTION(r1, i2)               \
+  int r1 = AS(RILInstruction)->R1Value();              \
+  uint32_t i2 = AS(RILInstruction)->I2UnsignedValue(); \
+  int length = 6;
+
+#define DECODE_RIL_B_INSTRUCTION(r1, i2)      \
+  int r1 = AS(RILInstruction)->R1Value();     \
+  int32_t i2 = AS(RILInstruction)->I2Value(); \
+  int length = 6;
+
+#define DECODE_RIL_C_INSTRUCTION(m1, ri2)                               \
+  Condition m1 = static_cast<Condition>(AS(RILInstruction)->R1Value()); \
+  uint64_t ri2 = AS(RILInstruction)->I2Value();                         \
+  int length = 6;
+
+#define DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2) \
+  int r1 = AS(RXYInstruction)->R1Value();        \
+  int x2 = AS(RXYInstruction)->X2Value();        \
+  int b2 = AS(RXYInstruction)->B2Value();        \
+  int d2 = AS(RXYInstruction)->D2Value();        \
+  int length = 6;
+
+#define DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val) \
+  int x2 = AS(RXInstruction)->X2Value();            \
+  int b2 = AS(RXInstruction)->B2Value();            \
+  int r1 = AS(RXInstruction)->R1Value();            \
+  intptr_t d2_val = AS(RXInstruction)->D2Value();   \
+  int length = 4;
+
+#define DECODE_RS_A_INSTRUCTION(r1, r3, b2, d2) \
+  int r3 = AS(RSInstruction)->R3Value();        \
+  int b2 = AS(RSInstruction)->B2Value();        \
+  int r1 = AS(RSInstruction)->R1Value();        \
+  intptr_t d2 = AS(RSInstruction)->D2Value();   \
+  int length = 4;
+
+#define DECODE_RS_A_INSTRUCTION_NO_R3(r1, b2, d2) \
+  int b2 = AS(RSInstruction)->B2Value();          \
+  int r1 = AS(RSInstruction)->R1Value();          \
+  int d2 = AS(RSInstruction)->D2Value();          \
+  int length = 4;
+
+#define DECODE_SI_INSTRUCTION_I_UINT8(b1, d1_val, imm_val) \
+  int b1 = AS(SIInstruction)->B1Value();                   \
+  intptr_t d1_val = AS(SIInstruction)->D1Value();          \
+  uint8_t imm_val = AS(SIInstruction)->I2Value();          \
+  int length = 4;
+
+#define DECODE_SIL_INSTRUCTION(b1, d1, i2)     \
+  int b1 = AS(SILInstruction)->B1Value();      \
+  intptr_t d1 = AS(SILInstruction)->D1Value(); \
+  int16_t i2 = AS(SILInstruction)->I2Value();  \
+  int length = 6;
+
+#define DECODE_SIY_INSTRUCTION(b1, d1, i2)     \
+  int b1 = AS(SIYInstruction)->B1Value();      \
+  intptr_t d1 = AS(SIYInstruction)->D1Value(); \
+  uint8_t i2 = AS(SIYInstruction)->I2Value();  \
+  int length = 6;
+
+#define DECODE_RRE_INSTRUCTION(r1, r2)    \
+  int r1 = AS(RREInstruction)->R1Value(); \
+  int r2 = AS(RREInstruction)->R2Value(); \
+  int length = 4;
+
+#define DECODE_RRE_INSTRUCTION_M3(r1, r2, m3) \
+  int r1 = AS(RREInstruction)->R1Value();     \
+  int r2 = AS(RREInstruction)->R2Value();     \
+  int m3 = AS(RREInstruction)->M3Value();     \
+  int length = 4;
+
+#define DECODE_RRE_INSTRUCTION_NO_R2(r1)  \
+  int r1 = AS(RREInstruction)->R1Value(); \
+  int length = 4;
+
+#define DECODE_RRD_INSTRUCTION(r1, r2, r3) \
+  int r1 = AS(RRDInstruction)->R1Value();  \
+  int r2 = AS(RRDInstruction)->R2Value();  \
+  int r3 = AS(RRDInstruction)->R3Value();  \
+  int length = 4;
+
+#define DECODE_RRF_E_INSTRUCTION(r1, r2, m3, m4) \
+  int r1 = AS(RRFInstruction)->R1Value();        \
+  int r2 = AS(RRFInstruction)->R2Value();        \
+  int m3 = AS(RRFInstruction)->M3Value();        \
+  int m4 = AS(RRFInstruction)->M4Value();        \
+  int length = 4;
+
+#define DECODE_RRF_A_INSTRUCTION(r1, r2, r3) \
+  int r1 = AS(RRFInstruction)->R1Value();    \
+  int r2 = AS(RRFInstruction)->R2Value();    \
+  int r3 = AS(RRFInstruction)->R3Value();    \
+  int length = 4;
+
+#define DECODE_RR_INSTRUCTION(r1, r2)    \
+  int r1 = AS(RRInstruction)->R1Value(); \
+  int r2 = AS(RRInstruction)->R2Value(); \
+  int length = 2;
+
+#define DECODE_RIE_D_INSTRUCTION(r1, r2, i2)  \
+  int r1 = AS(RIEInstruction)->R1Value();     \
+  int r2 = AS(RIEInstruction)->R2Value();     \
+  int32_t i2 = AS(RIEInstruction)->I6Value(); \
+  int length = 6;
+
+#define DECODE_RIE_F_INSTRUCTION(r1, r2, i3, i4, i5) \
+  int r1 = AS(RIEInstruction)->R1Value();            \
+  int r2 = AS(RIEInstruction)->R2Value();            \
+  uint32_t i3 = AS(RIEInstruction)->I3Value();       \
+  uint32_t i4 = AS(RIEInstruction)->I4Value();       \
+  uint32_t i5 = AS(RIEInstruction)->I5Value();       \
+  int length = 6;
+
+#define DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2) \
+  int r1 = AS(RSYInstruction)->R1Value();        \
+  int r3 = AS(RSYInstruction)->R3Value();        \
+  int b2 = AS(RSYInstruction)->B2Value();        \
+  intptr_t d2 = AS(RSYInstruction)->D2Value();   \
+  int length = 6;
+
+#define DECODE_RI_A_INSTRUCTION(instr, r1, i2) \
+  int32_t r1 = AS(RIInstruction)->R1Value();   \
+  int16_t i2 = AS(RIInstruction)->I2Value();   \
+  int length = 4;
+
+#define DECODE_RI_B_INSTRUCTION(instr, r1, i2) \
+  int32_t r1 = AS(RILInstruction)->R1Value();  \
+  int16_t i2 = AS(RILInstruction)->I2Value();  \
+  int length = 4;
+
+#define DECODE_RI_C_INSTRUCTION(instr, m1, i2)                         \
+  Condition m1 = static_cast<Condition>(AS(RIInstruction)->R1Value()); \
+  int16_t i2 = AS(RIInstruction)->I2Value();                           \
+  int length = 4;
+
+#define DECODE_RXE_INSTRUCTION(r1, b2, x2, d2) \
+  int r1 = AS(RXEInstruction)->R1Value();      \
+  int b2 = AS(RXEInstruction)->B2Value();      \
+  int x2 = AS(RXEInstruction)->X2Value();      \
+  int d2 = AS(RXEInstruction)->D2Value();      \
+  int length = 6;
+
+#define GET_ADDRESS(index_reg, base_reg, offset)       \
+  (((index_reg) == 0) ? 0 : get_register(index_reg)) + \
+      (((base_reg) == 0) ? 0 : get_register(base_reg)) + offset
+
+int Simulator::Evaluate_Unknown(Instruction* instr) {
+  UNREACHABLE();
+  return 0;
+}
+
+EVALUATE(CLR) {
+  DCHECK_OPCODE(CLR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  uint32_t r1_val = get_low_register<uint32_t>(r1);
+  uint32_t r2_val = get_low_register<uint32_t>(r2);
+  SetS390ConditionCode<uint32_t>(r1_val, r2_val);
+  return length;
+}
+
+EVALUATE(LR) {
+  DCHECK_OPCODE(LR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  set_low_register(r1, get_low_register<int32_t>(r2));
+  return length;
+}
+
+EVALUATE(AR) {
+  DCHECK_OPCODE(AR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  bool isOF = CheckOverflowForIntAdd(r1_val, r2_val, int32_t);
+  r1_val += r2_val;
+  SetS390ConditionCode<int32_t>(r1_val, 0);
+  SetS390OverflowCode(isOF);
+  set_low_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(L) {
+  DCHECK_OPCODE(L);
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t addr = b2_val + x2_val + d2_val;
+  int32_t mem_val = ReadW(addr, instr);
+  set_low_register(r1, mem_val);
+  return length;
+}
+
+EVALUATE(BRC) {
+  DCHECK_OPCODE(BRC);
+  DECODE_RI_C_INSTRUCTION(instr, m1, i2);
+
+  if (TestConditionCode(m1)) {
+    intptr_t offset = 2 * i2;
+    set_pc(get_pc() + offset);
+  }
+  return length;
+}
+
+EVALUATE(AHI) {
+  DCHECK_OPCODE(AHI);
+  DECODE_RI_A_INSTRUCTION(instr, r1, i2);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  bool isOF = CheckOverflowForIntAdd(r1_val, i2, int32_t);
+  r1_val += i2;
+  set_low_register(r1, r1_val);
+  SetS390ConditionCode<int32_t>(r1_val, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(AGHI) {
+  DCHECK_OPCODE(AGHI);
+  DECODE_RI_A_INSTRUCTION(instr, r1, i2);
+  int64_t r1_val = get_register(r1);
+  bool isOF = false;
+  isOF = CheckOverflowForIntAdd(r1_val, i2, int64_t);
+  r1_val += i2;
+  set_register(r1, r1_val);
+  SetS390ConditionCode<int64_t>(r1_val, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(BRCL) {
+  DCHECK_OPCODE(BRCL);
+  DECODE_RIL_C_INSTRUCTION(m1, ri2);
+
+  if (TestConditionCode(m1)) {
+    intptr_t offset = 2 * ri2;
+    set_pc(get_pc() + offset);
+  }
+  return length;
+}
+
+EVALUATE(IIHF) {
+  DCHECK_OPCODE(IIHF);
+  DECODE_RIL_A_INSTRUCTION(r1, imm);
+  set_high_register(r1, imm);
+  return length;
+}
+
+EVALUATE(IILF) {
+  DCHECK_OPCODE(IILF);
+  DECODE_RIL_A_INSTRUCTION(r1, imm);
+  set_low_register(r1, imm);
+  return length;
+}
+
+EVALUATE(LGR) {
+  DCHECK_OPCODE(LGR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  set_register(r1, get_register(r2));
+  return length;
+}
+
+EVALUATE(LG) {
+  DCHECK_OPCODE(LG);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  intptr_t addr = GET_ADDRESS(x2, b2, d2);
+  int64_t mem_val = ReadDW(addr);
+  set_register(r1, mem_val);
+  return length;
+}
+
+EVALUATE(AGR) {
+  DCHECK_OPCODE(AGR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int64_t r1_val = get_register(r1);
+  int64_t r2_val = get_register(r2);
+  bool isOF = CheckOverflowForIntAdd(r1_val, r2_val, int64_t);
+  r1_val += r2_val;
+  set_register(r1, r1_val);
+  SetS390ConditionCode<int64_t>(r1_val, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(LGFR) {
+  DCHECK_OPCODE(LGFR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  int64_t result = static_cast<int64_t>(r2_val);
+  set_register(r1, result);
+
+  return length;
+}
+
+EVALUATE(LBR) {
+  DCHECK_OPCODE(LBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  r2_val <<= 24;
+  r2_val >>= 24;
+  set_low_register(r1, r2_val);
+  return length;
+}
+
+EVALUATE(LGBR) {
+  DCHECK_OPCODE(LGBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int64_t r2_val = get_low_register<int64_t>(r2);
+  r2_val <<= 56;
+  r2_val >>= 56;
+  set_register(r1, r2_val);
+  return length;
+}
+
+EVALUATE(LHR) {
+  DCHECK_OPCODE(LHR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  r2_val <<= 16;
+  r2_val >>= 16;
+  set_low_register(r1, r2_val);
+  return length;
+}
+
+EVALUATE(LGHR) {
+  DCHECK_OPCODE(LGHR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int64_t r2_val = get_low_register<int64_t>(r2);
+  r2_val <<= 48;
+  r2_val >>= 48;
+  set_register(r1, r2_val);
+  return length;
+}
+
+EVALUATE(LGF) {
+  DCHECK_OPCODE(LGF);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  intptr_t addr = GET_ADDRESS(x2, b2, d2);
+  int64_t mem_val = static_cast<int64_t>(ReadW(addr, instr));
+  set_register(r1, mem_val);
+  return length;
+}
+
+EVALUATE(ST) {
+  DCHECK_OPCODE(ST);
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t addr = b2_val + x2_val + d2_val;
+  WriteW(addr, r1_val, instr);
+  return length;
+}
+
+EVALUATE(STG) {
+  DCHECK_OPCODE(STG);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  intptr_t addr = GET_ADDRESS(x2, b2, d2);
+  uint64_t value = get_register(r1);
+  WriteDW(addr, value);
+  return length;
+}
+
+EVALUATE(STY) {
+  DCHECK_OPCODE(STY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  intptr_t addr = GET_ADDRESS(x2, b2, d2);
+  uint32_t value = get_low_register<uint32_t>(r1);
+  WriteW(addr, value, instr);
+  return length;
+}
+
+EVALUATE(LY) {
+  DCHECK_OPCODE(LY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  intptr_t addr = GET_ADDRESS(x2, b2, d2);
+  uint32_t mem_val = ReadWU(addr, instr);
+  set_low_register(r1, mem_val);
+  return length;
+}
+
+EVALUATE(LLGC) {
+  DCHECK_OPCODE(LLGC);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  uint8_t mem_val = ReadBU(GET_ADDRESS(x2, b2, d2));
+  set_register(r1, static_cast<uint64_t>(mem_val));
+  return length;
+}
+
+EVALUATE(LLC) {
+  DCHECK_OPCODE(LLC);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  uint8_t mem_val = ReadBU(GET_ADDRESS(x2, b2, d2));
+  set_low_register(r1, static_cast<uint32_t>(mem_val));
+  return length;
+}
+
+EVALUATE(RLL) {
+  DCHECK_OPCODE(RLL);
+  DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
+  // only takes rightmost 6 bits
+  int shiftBits = GET_ADDRESS(0, b2, d2) & 0x3F;
+  // unsigned
+  uint32_t r3_val = get_low_register<uint32_t>(r3);
+  uint32_t alu_out = 0;
+  uint32_t rotateBits = r3_val >> (32 - shiftBits);
+  alu_out = (r3_val << shiftBits) | (rotateBits);
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(RISBG) {
+  DCHECK_OPCODE(RISBG);
+  DECODE_RIE_F_INSTRUCTION(r1, r2, i3, i4, i5);
+  // Starting Bit Position is Bits 2-7 of I3 field
+  uint32_t start_bit = i3 & 0x3F;
+  // Ending Bit Position is Bits 2-7 of I4 field
+  uint32_t end_bit = i4 & 0x3F;
+  // Shift Amount is Bits 2-7 of I5 field
+  uint32_t shift_amount = i5 & 0x3F;
+  // Zero out Remaining (unslected) bits if Bit 0 of I4 is 1.
+  bool zero_remaining = (0 != (i4 & 0x80));
+
+  uint64_t src_val = get_register(r2);
+
+  // Rotate Left by Shift Amount first
+  uint64_t rotated_val =
+      (src_val << shift_amount) | (src_val >> (64 - shift_amount));
+  int32_t width = end_bit - start_bit + 1;
+
+  uint64_t selection_mask = 0;
+  if (width < 64) {
+    selection_mask = (static_cast<uint64_t>(1) << width) - 1;
+  } else {
+    selection_mask = static_cast<uint64_t>(static_cast<int64_t>(-1));
+  }
+  selection_mask = selection_mask << (63 - end_bit);
+
+  uint64_t selected_val = rotated_val & selection_mask;
+
+  if (!zero_remaining) {
+    // Merged the unselected bits from the original value
+    selected_val = (src_val & ~selection_mask) | selected_val;
+  }
+
+  // Condition code is set by treating result as 64-bit signed int
+  SetS390ConditionCode<int64_t>(selected_val, 0);
+  set_register(r1, selected_val);
+  return length;
+}
+
+EVALUATE(AHIK) {
+  DCHECK_OPCODE(AHIK);
+  DECODE_RIE_D_INSTRUCTION(r1, r2, i2);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  int32_t imm = static_cast<int32_t>(i2);
+  bool isOF = CheckOverflowForIntAdd(r2_val, imm, int32_t);
+  set_low_register(r1, r2_val + imm);
+  SetS390ConditionCode<int32_t>(r2_val + imm, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(AGHIK) {
+  // 64-bit Add
+  DCHECK_OPCODE(AGHIK);
+  DECODE_RIE_D_INSTRUCTION(r1, r2, i2);
+  int64_t r2_val = get_register(r2);
+  int64_t imm = static_cast<int64_t>(i2);
+  bool isOF = CheckOverflowForIntAdd(r2_val, imm, int64_t);
+  set_register(r1, r2_val + imm);
+  SetS390ConditionCode<int64_t>(r2_val + imm, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(BKPT) {
+  DCHECK_OPCODE(BKPT);
+  set_pc(get_pc() + 2);
+  S390Debugger dbg(this);
+  dbg.Debug();
+  int length = 2;
+  return length;
+}
+
+EVALUATE(SPM) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BALR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BCTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BCR) {
+  DCHECK_OPCODE(BCR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  if (TestConditionCode(Condition(r1))) {
+    intptr_t r2_val = get_register(r2);
+#if (!V8_TARGET_ARCH_S390X && V8_HOST_ARCH_S390)
+    // On 31-bit, the top most bit may be 0 or 1, but is ignored by the
+    // hardware.  Cleanse the top bit before jumping to it, unless it's one
+    // of the special PCs
+    if (r2_val != bad_lr && r2_val != end_sim_pc) r2_val &= 0x7FFFFFFF;
+#endif
+    set_pc(r2_val);
+  }
+
+  return length;
+}
+
+EVALUATE(SVC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BSM) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BASSM) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BASR) {
+  DCHECK_OPCODE(BASR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  intptr_t link_addr = get_pc() + 2;
+  // If R2 is zero, the BASR does not branch.
+  int64_t r2_val = (r2 == 0) ? link_addr : get_register(r2);
+#if (!V8_TARGET_ARCH_S390X && V8_HOST_ARCH_S390)
+  // On 31-bit, the top most bit may be 0 or 1, which can cause issues
+  // for stackwalker.  The top bit should either be cleanse before being
+  // pushed onto the stack, or during stack walking when dereferenced.
+  // For simulator, we'll take the worst case scenario and always tag
+  // the high bit, to flush out more problems.
+  link_addr |= 0x80000000;
+#endif
+  set_register(r1, link_addr);
+  set_pc(r2_val);
+  return length;
+}
+
+EVALUATE(MVCL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CLCL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LPR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LNR) {
+  DCHECK_OPCODE(LNR);
+  // Load Negative (32)
+  DECODE_RR_INSTRUCTION(r1, r2);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  r2_val = (r2_val >= 0) ? -r2_val : r2_val;  // If pos, then negate it.
+  set_low_register(r1, r2_val);
+  condition_reg_ = (r2_val == 0) ? CC_EQ : CC_LT;  // CC0 - result is zero
+  // CC1 - result is negative
+  return length;
+}
+
+EVALUATE(LTR) {
+  DCHECK_OPCODE(LTR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  SetS390ConditionCode<int32_t>(r2_val, 0);
+  set_low_register(r1, r2_val);
+  return length;
+}
+
+EVALUATE(LCR) {
+  DCHECK_OPCODE(LCR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  int32_t original_r2_val = r2_val;
+  r2_val = ~r2_val;
+  r2_val = r2_val + 1;
+  set_low_register(r1, r2_val);
+  SetS390ConditionCode<int32_t>(r2_val, 0);
+  // Checks for overflow where r2_val = -2147483648.
+  // Cannot do int comparison due to GCC 4.8 bug on x86.
+  // Detect INT_MIN alternatively, as it is the only value where both
+  // original and result are negative due to overflow.
+  if (r2_val < 0 && original_r2_val < 0) {
+    SetS390OverflowCode(true);
+  }
+  return length;
+}
+
+EVALUATE(NR) {
+  DCHECK_OPCODE(NR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  r1_val &= r2_val;
+  SetS390BitWiseConditionCode<uint32_t>(r1_val);
+  set_low_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(OR) {
+  DCHECK_OPCODE(OR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  r1_val |= r2_val;
+  SetS390BitWiseConditionCode<uint32_t>(r1_val);
+  set_low_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(XR) {
+  DCHECK_OPCODE(XR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  r1_val ^= r2_val;
+  SetS390BitWiseConditionCode<uint32_t>(r1_val);
+  set_low_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(CR) {
+  DCHECK_OPCODE(CR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  SetS390ConditionCode<int32_t>(r1_val, r2_val);
+  return length;
+}
+
+EVALUATE(SR) {
+  DCHECK_OPCODE(SR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  bool isOF = false;
+  isOF = CheckOverflowForIntSub(r1_val, r2_val, int32_t);
+  r1_val -= r2_val;
+  SetS390ConditionCode<int32_t>(r1_val, 0);
+  SetS390OverflowCode(isOF);
+  set_low_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(MR) {
+  DCHECK_OPCODE(MR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  DCHECK(r1 % 2 == 0);
+  r1_val = get_low_register<int32_t>(r1 + 1);
+  int64_t product = static_cast<int64_t>(r1_val) * static_cast<int64_t>(r2_val);
+  int32_t high_bits = product >> 32;
+  r1_val = high_bits;
+  int32_t low_bits = product & 0x00000000FFFFFFFF;
+  set_low_register(r1, high_bits);
+  set_low_register(r1 + 1, low_bits);
+  set_low_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(DR) {
+  DCHECK_OPCODE(DR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  // reg-reg pair should be even-odd pair, assert r1 is an even register
+  DCHECK(r1 % 2 == 0);
+  // leftmost 32 bits of the dividend are in r1
+  // rightmost 32 bits of the dividend are in r1+1
+  // get the signed value from r1
+  int64_t dividend = static_cast<int64_t>(r1_val) << 32;
+  // get unsigned value from r1+1
+  // avoid addition with sign-extended r1+1 value
+  dividend += get_low_register<uint32_t>(r1 + 1);
+  int32_t remainder = dividend % r2_val;
+  int32_t quotient = dividend / r2_val;
+  r1_val = remainder;
+  set_low_register(r1, remainder);
+  set_low_register(r1 + 1, quotient);
+  set_low_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(ALR) {
+  DCHECK_OPCODE(ALR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  uint32_t r1_val = get_low_register<uint32_t>(r1);
+  uint32_t r2_val = get_low_register<uint32_t>(r2);
+  uint32_t alu_out = 0;
+  bool isOF = false;
+  alu_out = r1_val + r2_val;
+  isOF = CheckOverflowForUIntAdd(r1_val, r2_val);
+  set_low_register(r1, alu_out);
+  SetS390ConditionCodeCarry<uint32_t>(alu_out, isOF);
+  return length;
+}
+
+EVALUATE(SLR) {
+  DCHECK_OPCODE(SLR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  uint32_t r1_val = get_low_register<uint32_t>(r1);
+  uint32_t r2_val = get_low_register<uint32_t>(r2);
+  uint32_t alu_out = 0;
+  bool isOF = false;
+  alu_out = r1_val - r2_val;
+  isOF = CheckOverflowForUIntSub(r1_val, r2_val);
+  set_low_register(r1, alu_out);
+  SetS390ConditionCodeCarry<uint32_t>(alu_out, isOF);
+  return length;
+}
+
+EVALUATE(LDR) {
+  DCHECK_OPCODE(LDR);
+  DECODE_RR_INSTRUCTION(r1, r2);
+  int64_t r2_val = get_d_register(r2);
+  set_d_register(r1, r2_val);
+  return length;
+}
+
+EVALUATE(CDR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LER) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STH) {
+  DCHECK_OPCODE(STH);
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int16_t r1_val = get_low_register<int32_t>(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t mem_addr = b2_val + x2_val + d2_val;
+  WriteH(mem_addr, r1_val, instr);
+
+  return length;
+}
+
+EVALUATE(LA) {
+  DCHECK_OPCODE(LA);
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t addr = b2_val + x2_val + d2_val;
+  set_register(r1, addr);
+  return length;
+}
+
+EVALUATE(STC) {
+  DCHECK_OPCODE(STC);
+  // Store Character/Byte
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  uint8_t r1_val = get_low_register<int32_t>(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t mem_addr = b2_val + x2_val + d2_val;
+  WriteB(mem_addr, r1_val);
+  return length;
+}
+
+EVALUATE(IC_z) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(EX) {
+  DCHECK_OPCODE(EX);
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+
+  SixByteInstr the_instr = Instruction::InstructionBits(
+      reinterpret_cast<const byte*>(b2_val + x2_val + d2_val));
+  int inst_length = Instruction::InstructionLength(
+      reinterpret_cast<const byte*>(b2_val + x2_val + d2_val));
+
+  char new_instr_buf[8];
+  char* addr = reinterpret_cast<char*>(&new_instr_buf[0]);
+  the_instr |= static_cast<SixByteInstr>(r1_val & 0xff)
+               << (8 * inst_length - 16);
+  Instruction::SetInstructionBits<SixByteInstr>(
+      reinterpret_cast<byte*>(addr), static_cast<SixByteInstr>(the_instr));
+  ExecuteInstruction(reinterpret_cast<Instruction*>(addr), false);
+  return length;
+}
+
+EVALUATE(BAL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BCT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LH) {
+  DCHECK_OPCODE(LH);
+  // Load Halfword
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t mem_addr = x2_val + b2_val + d2_val;
+
+  int32_t result = static_cast<int32_t>(ReadH(mem_addr, instr));
+  set_low_register(r1, result);
+  return length;
+}
+
+EVALUATE(CH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(AH) {
+  DCHECK_OPCODE(AH);
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t addr = b2_val + x2_val + d2_val;
+  int32_t mem_val = static_cast<int32_t>(ReadH(addr, instr));
+  int32_t alu_out = 0;
+  bool isOF = false;
+  isOF = CheckOverflowForIntAdd(r1_val, mem_val, int32_t);
+  alu_out = r1_val + mem_val;
+  set_low_register(r1, alu_out);
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+
+  return length;
+}
+
+EVALUATE(SH) {
+  DCHECK_OPCODE(SH);
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t addr = b2_val + x2_val + d2_val;
+  int32_t mem_val = static_cast<int32_t>(ReadH(addr, instr));
+  int32_t alu_out = 0;
+  bool isOF = false;
+  isOF = CheckOverflowForIntSub(r1_val, mem_val, int32_t);
+  alu_out = r1_val - mem_val;
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+
+  return length;
+}
+
+EVALUATE(MH) {
+  DCHECK_OPCODE(MH);
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t addr = b2_val + x2_val + d2_val;
+  int32_t mem_val = static_cast<int32_t>(ReadH(addr, instr));
+  int32_t alu_out = 0;
+  alu_out = r1_val * mem_val;
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(BAS) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CVD) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CVB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LAE) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(N) {
+  DCHECK_OPCODE(N);
+  // 32-bit Reg-Mem instructions
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr);
+  int32_t alu_out = 0;
+  alu_out = r1_val & mem_val;
+  SetS390BitWiseConditionCode<uint32_t>(alu_out);
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(CL) {
+  DCHECK_OPCODE(CL);
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t addr = b2_val + x2_val + d2_val;
+  int32_t mem_val = ReadW(addr, instr);
+  SetS390ConditionCode<uint32_t>(r1_val, mem_val);
+  return length;
+}
+
+EVALUATE(O) {
+  DCHECK_OPCODE(O);
+  // 32-bit Reg-Mem instructions
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr);
+  int32_t alu_out = 0;
+  alu_out = r1_val | mem_val;
+  SetS390BitWiseConditionCode<uint32_t>(alu_out);
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(X) {
+  DCHECK_OPCODE(X);
+  // 32-bit Reg-Mem instructions
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr);
+  int32_t alu_out = 0;
+  alu_out = r1_val ^ mem_val;
+  SetS390BitWiseConditionCode<uint32_t>(alu_out);
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(C) {
+  DCHECK_OPCODE(C);
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t addr = b2_val + x2_val + d2_val;
+  int32_t mem_val = ReadW(addr, instr);
+  SetS390ConditionCode<int32_t>(r1_val, mem_val);
+  return length;
+}
+
+EVALUATE(A) {
+  DCHECK_OPCODE(A);
+  // 32-bit Reg-Mem instructions
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr);
+  int32_t alu_out = 0;
+  bool isOF = false;
+  isOF = CheckOverflowForIntAdd(r1_val, mem_val, int32_t);
+  alu_out = r1_val + mem_val;
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(S) {
+  DCHECK_OPCODE(S);
+  // 32-bit Reg-Mem instructions
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr);
+  int32_t alu_out = 0;
+  bool isOF = false;
+  isOF = CheckOverflowForIntSub(r1_val, mem_val, int32_t);
+  alu_out = r1_val - mem_val;
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(M) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(D) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(AL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STD) {
+  DCHECK_OPCODE(STD);
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t addr = b2_val + x2_val + d2_val;
+  int64_t frs_val = get_d_register(r1);
+  WriteDW(addr, frs_val);
+  return length;
+}
+
+EVALUATE(LD) {
+  DCHECK_OPCODE(LD);
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t addr = b2_val + x2_val + d2_val;
+  int64_t dbl_val = *reinterpret_cast<int64_t*>(addr);
+  set_d_register(r1, dbl_val);
+  return length;
+}
+
+EVALUATE(CD) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STE) {
+  DCHECK_OPCODE(STE);
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t addr = b2_val + x2_val + d2_val;
+  int64_t frs_val = get_d_register(r1) >> 32;
+  WriteW(addr, static_cast<int32_t>(frs_val), instr);
+  return length;
+}
+
+EVALUATE(MS) {
+  DCHECK_OPCODE(MS);
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int32_t mem_val = ReadW(b2_val + x2_val + d2_val, instr);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  set_low_register(r1, r1_val * mem_val);
+  return length;
+}
+
+EVALUATE(LE) {
+  DCHECK_OPCODE(LE);
+  DECODE_RX_A_INSTRUCTION(x2, b2, r1, d2_val);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t addr = b2_val + x2_val + d2_val;
+  float float_val = *reinterpret_cast<float*>(addr);
+  set_d_register_from_float32(r1, float_val);
+  return length;
+}
+
+EVALUATE(BRXH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BRXLE) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BXH) {
+  DCHECK_OPCODE(BXH);
+  DECODE_RS_A_INSTRUCTION(r1, r3, b2, d2);
+
+  // r1_val is the first operand, r3_val is the increment
+  int32_t r1_val = r1 == 0 ? 0 : get_register(r1);
+  int32_t r3_val = r2 == 0 ? 0 : get_register(r3);
+  intptr_t b2_val = b2 == 0 ? 0 : get_register(b2);
+  intptr_t branch_address = b2_val + d2;
+  // increment r1_val
+  r1_val += r3_val;
+
+  // if the increment is even, then it designates a pair of registers
+  // and the contents of the even and odd registers of the pair are used as
+  // the increment and compare value respectively. If the increment is odd,
+  // the increment itself is used as both the increment and compare value
+  int32_t compare_val = r3 % 2 == 0 ? get_register(r3 + 1) : r3_val;
+  if (r1_val > compare_val) {
+    // branch to address if r1_val is greater than compare value
+    set_pc(branch_address);
+  }
+
+  // update contents of register in r1 with the new incremented value
+  set_register(r1, r1_val);
+
+  return length;
+}
+
+EVALUATE(BXLE) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SRL) {
+  DCHECK_OPCODE(SRL);
+  DECODE_RS_A_INSTRUCTION_NO_R3(r1, b2, d2);
+  // only takes rightmost 6bits
+  int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
+  int shiftBits = (b2_val + d2) & 0x3F;
+  uint32_t r1_val = get_low_register<uint32_t>(r1);
+  uint32_t alu_out = 0;
+  alu_out = r1_val >> shiftBits;
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(SLL) {
+  DCHECK_OPCODE(SLL);
+  DECODE_RS_A_INSTRUCTION_NO_R3(r1, b2, d2)
+  // only takes rightmost 6bits
+  int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
+  int shiftBits = (b2_val + d2) & 0x3F;
+  uint32_t r1_val = get_low_register<uint32_t>(r1);
+  uint32_t alu_out = 0;
+  alu_out = r1_val << shiftBits;
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(SRA) {
+  DCHECK_OPCODE(SRA);
+  DECODE_RS_A_INSTRUCTION_NO_R3(r1, b2, d2);
+  // only takes rightmost 6bits
+  int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
+  int shiftBits = (b2_val + d2) & 0x3F;
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int32_t alu_out = 0;
+  bool isOF = false;
+  alu_out = r1_val >> shiftBits;
+  set_low_register(r1, alu_out);
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(SLA) {
+  DCHECK_OPCODE(SLA);
+  DECODE_RS_A_INSTRUCTION_NO_R3(r1, b2, d2);
+  // only takes rightmost 6bits
+  int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
+  int shiftBits = (b2_val + d2) & 0x3F;
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int32_t alu_out = 0;
+  bool isOF = false;
+  isOF = CheckOverflowForShiftLeft(r1_val, shiftBits);
+  alu_out = r1_val << shiftBits;
+  set_low_register(r1, alu_out);
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(SRDL) {
+  DCHECK_OPCODE(SRDL);
+  DECODE_RS_A_INSTRUCTION_NO_R3(r1, b2, d2);
+  DCHECK(r1 % 2 == 0);  // must be a reg pair
+  // only takes rightmost 6bits
+  int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
+  int shiftBits = (b2_val + d2) & 0x3F;
+  uint64_t opnd1 = static_cast<uint64_t>(get_low_register<uint32_t>(r1)) << 32;
+  uint64_t opnd2 = static_cast<uint64_t>(get_low_register<uint32_t>(r1 + 1));
+  uint64_t r1_val = opnd1 | opnd2;
+  uint64_t alu_out = r1_val >> shiftBits;
+  set_low_register(r1, alu_out >> 32);
+  set_low_register(r1 + 1, alu_out & 0x00000000FFFFFFFF);
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  return length;
+}
+
+EVALUATE(SLDL) {
+  DCHECK_OPCODE(SLDL);
+  DECODE_RS_A_INSTRUCTION_NO_R3(r1, b2, d2);
+  // only takes rightmost 6bits
+  int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
+  int shiftBits = (b2_val + d2) & 0x3F;
+
+  DCHECK(r1 % 2 == 0);
+  uint32_t r1_val = get_low_register<uint32_t>(r1);
+  uint32_t r1_next_val = get_low_register<uint32_t>(r1 + 1);
+  uint64_t alu_out = (static_cast<uint64_t>(r1_val) << 32) |
+                     (static_cast<uint64_t>(r1_next_val));
+  alu_out <<= shiftBits;
+  set_low_register(r1 + 1, static_cast<uint32_t>(alu_out));
+  set_low_register(r1, static_cast<uint32_t>(alu_out >> 32));
+  return length;
+}
+
+EVALUATE(SRDA) {
+  DCHECK_OPCODE(SRDA);
+  DECODE_RS_A_INSTRUCTION_NO_R3(r1, b2, d2);
+  DCHECK(r1 % 2 == 0);  // must be a reg pair
+  // only takes rightmost 6bits
+  int64_t b2_val = b2 == 0 ? 0 : get_register(b2);
+  int shiftBits = (b2_val + d2) & 0x3F;
+  int64_t opnd1 = static_cast<int64_t>(get_low_register<int32_t>(r1)) << 32;
+  int64_t opnd2 = static_cast<uint64_t>(get_low_register<uint32_t>(r1 + 1));
+  int64_t r1_val = opnd1 + opnd2;
+  int64_t alu_out = r1_val >> shiftBits;
+  set_low_register(r1, alu_out >> 32);
+  set_low_register(r1 + 1, alu_out & 0x00000000FFFFFFFF);
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  return length;
+}
+
+EVALUATE(SLDA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STM) {
+  DCHECK_OPCODE(STM);
+  DECODE_RS_A_INSTRUCTION(r1, r3, rb, d2);
+  // Store Multiple 32-bits.
+  int offset = d2;
+  // Regs roll around if r3 is less than r1.
+  // Artifically increase r3 by 16 so we can calculate
+  // the number of regs stored properly.
+  if (r3 < r1) r3 += 16;
+
+  int32_t rb_val = (rb == 0) ? 0 : get_low_register<int32_t>(rb);
+
+  // Store each register in ascending order.
+  for (int i = 0; i <= r3 - r1; i++) {
+    int32_t value = get_low_register<int32_t>((r1 + i) % 16);
+    WriteW(rb_val + offset + 4 * i, value, instr);
+  }
+  return length;
+}
+
+EVALUATE(TM) {
+  DCHECK_OPCODE(TM);
+  // Test Under Mask (Mem - Imm) (8)
+  DECODE_SI_INSTRUCTION_I_UINT8(b1, d1_val, imm_val)
+  int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
+  intptr_t addr = b1_val + d1_val;
+  uint8_t mem_val = ReadB(addr);
+  uint8_t selected_bits = mem_val & imm_val;
+  // CC0: Selected bits are zero
+  // CC1: Selected bits mixed zeros and ones
+  // CC3: Selected bits all ones
+  if (0 == selected_bits) {
+    condition_reg_ = CC_EQ;  // CC0
+  } else if (selected_bits == imm_val) {
+    condition_reg_ = 0x1;  // CC3
+  } else {
+    condition_reg_ = 0x4;  // CC1
+  }
+  return length;
+}
+
+EVALUATE(MVI) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TS) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(NI) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CLI) {
+  DCHECK_OPCODE(CLI);
+  // Compare Immediate (Mem - Imm) (8)
+  DECODE_SI_INSTRUCTION_I_UINT8(b1, d1_val, imm_val)
+  int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
+  intptr_t addr = b1_val + d1_val;
+  uint8_t mem_val = ReadB(addr);
+  SetS390ConditionCode<uint8_t>(mem_val, imm_val);
+  return length;
+}
+
+EVALUATE(OI) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(XI) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LM) {
+  DCHECK_OPCODE(LM);
+  DECODE_RS_A_INSTRUCTION(r1, r3, rb, d2);
+  // Store Multiple 32-bits.
+  int offset = d2;
+  // Regs roll around if r3 is less than r1.
+  // Artifically increase r3 by 16 so we can calculate
+  // the number of regs stored properly.
+  if (r3 < r1) r3 += 16;
+
+  int32_t rb_val = (rb == 0) ? 0 : get_low_register<int32_t>(rb);
+
+  // Store each register in ascending order.
+  for (int i = 0; i <= r3 - r1; i++) {
+    int32_t value = ReadW(rb_val + offset + 4 * i, instr);
+    set_low_register((r1 + i) % 16, value);
+  }
+  return length;
+}
+
+EVALUATE(MVCLE) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CLCLE) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CDS) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STCM) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ICM) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BPRP) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BPP) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TRTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MVN) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MVC) {
+  DCHECK_OPCODE(MVC);
+  // Move Character
+  SSInstruction* ssInstr = reinterpret_cast<SSInstruction*>(instr);
+  int b1 = ssInstr->B1Value();
+  intptr_t d1 = ssInstr->D1Value();
+  int b2 = ssInstr->B2Value();
+  intptr_t d2 = ssInstr->D2Value();
+  int length = ssInstr->Length();
+  int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t src_addr = b2_val + d2;
+  intptr_t dst_addr = b1_val + d1;
+  // remember that the length is the actual length - 1
+  for (int i = 0; i < length + 1; ++i) {
+    WriteB(dst_addr++, ReadB(src_addr++));
+  }
+  length = 6;
+  return length;
+}
+
+EVALUATE(MVZ) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(NC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CLC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(OC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(XC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MVCP) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TRT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ED) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(EDMK) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(PKU) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(UNPKU) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MVCIN) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(PKA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(UNPKA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(PLO) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LMD) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SRP) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MVO) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(PACK) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(UNPK) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ZAP) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(AP) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SP) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MP) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(DP) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(UPT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(PFPO) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(IIHH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(IIHL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(IILH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(IILL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(NIHH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(NIHL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(NILH) {
+  DCHECK_OPCODE(NILH);
+  DECODE_RI_A_INSTRUCTION(instr, r1, i);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  // CC is set based on the 16 bits that are AND'd
+  SetS390BitWiseConditionCode<uint16_t>((r1_val >> 16) & i);
+  i = (i << 16) | 0x0000FFFF;
+  set_low_register(r1, r1_val & i);
+  return length;
+}
+
+EVALUATE(NILL) {
+  DCHECK_OPCODE(NILL);
+  DECODE_RI_A_INSTRUCTION(instr, r1, i);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  // CC is set based on the 16 bits that are AND'd
+  SetS390BitWiseConditionCode<uint16_t>(r1_val & i);
+  i |= 0xFFFF0000;
+  set_low_register(r1, r1_val & i);
+  return length;
+}
+
+EVALUATE(OIHH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(OIHL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(OILH) {
+  DCHECK_OPCODE(OILH);
+  DECODE_RI_A_INSTRUCTION(instr, r1, i);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  // CC is set based on the 16 bits that are AND'd
+  SetS390BitWiseConditionCode<uint16_t>((r1_val >> 16) | i);
+  i = i << 16;
+  set_low_register(r1, r1_val | i);
+  return length;
+}
+
+EVALUATE(OILL) {
+  DCHECK_OPCODE(OILL);
+  DECODE_RI_A_INSTRUCTION(instr, r1, i);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  // CC is set based on the 16 bits that are AND'd
+  SetS390BitWiseConditionCode<uint16_t>(r1_val | i);
+  set_low_register(r1, r1_val | i);
+  return length;
+}
+
+EVALUATE(LLIHH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LLIHL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LLILH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LLILL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TMLH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TMLL) {
+  DCHECK_OPCODE(TMLL);
+  DECODE_RI_A_INSTRUCTION(instr, r1, i2);
+  int mask = i2 & 0x0000FFFF;
+  if (mask == 0) {
+    condition_reg_ = 0x0;
+    return length;
+  }
+  uint32_t r1_val = get_low_register<uint32_t>(r1);
+  r1_val = r1_val & 0x0000FFFF;  // uses only the last 16bits
+
+  // Test if all selected bits are Zero
+  bool allSelectedBitsAreZeros = true;
+  for (int i = 0; i < 15; i++) {
+    if (mask & (1 << i)) {
+      if (r1_val & (1 << i)) {
+        allSelectedBitsAreZeros = false;
+        break;
+      }
+    }
+  }
+  if (allSelectedBitsAreZeros) {
+    condition_reg_ = 0x8;
+    return length;  // Done!
+  }
+
+  // Test if all selected bits are one
+  bool allSelectedBitsAreOnes = true;
+  for (int i = 0; i < 15; i++) {
+    if (mask & (1 << i)) {
+      if (!(r1_val & (1 << i))) {
+        allSelectedBitsAreOnes = false;
+        break;
+      }
+    }
+  }
+  if (allSelectedBitsAreOnes) {
+    condition_reg_ = 0x1;
+    return length;  // Done!
+  }
+
+  // Now we know selected bits mixed zeros and ones
+  // Test if the leftmost bit is zero or one
+  for (int i = 14; i >= 0; i--) {
+    if (mask & (1 << i)) {
+      if (r1_val & (1 << i)) {
+        // leftmost bit is one
+        condition_reg_ = 0x2;
+      } else {
+        // leftmost bit is zero
+        condition_reg_ = 0x4;
+      }
+      return length;  // Done!
+    }
+  }
+  return length;
+}
+
+EVALUATE(TMHH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TMHL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BRAS) {
+  DCHECK_OPCODE(BRAS);
+  // Branch Relative and Save
+  DECODE_RI_B_INSTRUCTION(instr, r1, d2)
+  intptr_t pc = get_pc();
+  // Set PC of next instruction to register
+  set_register(r1, pc + sizeof(FourByteInstr));
+  // Update PC to branch target
+  set_pc(pc + d2 * 2);
+  return length;
+}
+
+EVALUATE(BRCT) {
+  DCHECK_OPCODE(BRCT);
+  // Branch On Count (32/64).
+  DECODE_RI_A_INSTRUCTION(instr, r1, i2);
+  int64_t value = get_low_register<int32_t>(r1);
+  set_low_register(r1, --value);
+  // Branch if value != 0
+  if (value != 0) {
+    intptr_t offset = i2 * 2;
+    set_pc(get_pc() + offset);
+  }
+  return length;
+}
+
+EVALUATE(BRCTG) {
+  DCHECK_OPCODE(BRCTG);
+  // Branch On Count (32/64).
+  DECODE_RI_A_INSTRUCTION(instr, r1, i2);
+  int64_t value = get_register(r1);
+  set_register(r1, --value);
+  // Branch if value != 0
+  if (value != 0) {
+    intptr_t offset = i2 * 2;
+    set_pc(get_pc() + offset);
+  }
+  return length;
+}
+
+EVALUATE(LHI) {
+  DCHECK_OPCODE(LHI);
+  DECODE_RI_A_INSTRUCTION(instr, r1, i);
+  set_low_register(r1, i);
+  return length;
+}
+
+EVALUATE(LGHI) {
+  DCHECK_OPCODE(LGHI);
+  DECODE_RI_A_INSTRUCTION(instr, r1, i2);
+  int64_t i = static_cast<int64_t>(i2);
+  set_register(r1, i);
+  return length;
+}
+
+EVALUATE(MHI) {
+  DCHECK_OPCODE(MHI);
+  DECODE_RI_A_INSTRUCTION(instr, r1, i);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  bool isOF = false;
+  isOF = CheckOverflowForMul(r1_val, i);
+  r1_val *= i;
+  set_low_register(r1, r1_val);
+  SetS390ConditionCode<int32_t>(r1_val, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(MGHI) {
+  DCHECK_OPCODE(MGHI);
+  DECODE_RI_A_INSTRUCTION(instr, r1, i2);
+  int64_t i = static_cast<int64_t>(i2);
+  int64_t r1_val = get_register(r1);
+  bool isOF = false;
+  isOF = CheckOverflowForMul(r1_val, i);
+  r1_val *= i;
+  set_register(r1, r1_val);
+  SetS390ConditionCode<int32_t>(r1_val, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(CHI) {
+  DCHECK_OPCODE(CHI);
+  DECODE_RI_A_INSTRUCTION(instr, r1, i);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  SetS390ConditionCode<int32_t>(r1_val, i);
+  return length;
+}
+
+EVALUATE(CGHI) {
+  DCHECK_OPCODE(CGHI);
+  DECODE_RI_A_INSTRUCTION(instr, r1, i2);
+  int64_t i = static_cast<int64_t>(i2);
+  int64_t r1_val = get_register(r1);
+  SetS390ConditionCode<int64_t>(r1_val, i);
+  return length;
+}
+
+EVALUATE(LARL) {
+  DCHECK_OPCODE(LARL);
+  DECODE_RIL_B_INSTRUCTION(r1, i2);
+  intptr_t offset = i2 * 2;
+  set_register(r1, get_pc() + offset);
+  return length;
+}
+
+EVALUATE(LGFI) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BRASL) {
+  DCHECK_OPCODE(BRASL);
+  // Branch and Save Relative Long
+  DECODE_RIL_B_INSTRUCTION(r1, i2);
+  intptr_t d2 = i2;
+  intptr_t pc = get_pc();
+  set_register(r1, pc + 6);  // save next instruction to register
+  set_pc(pc + d2 * 2);       // update register
+  return length;
+}
+
+EVALUATE(XIHF) {
+  DCHECK_OPCODE(XIHF);
+  DECODE_RIL_A_INSTRUCTION(r1, imm);
+  uint32_t alu_out = 0;
+  alu_out = get_high_register<uint32_t>(r1);
+  alu_out = alu_out ^ imm;
+  set_high_register(r1, alu_out);
+  SetS390BitWiseConditionCode<uint32_t>(alu_out);
+  return length;
+}
+
+EVALUATE(XILF) {
+  DCHECK_OPCODE(XILF);
+  DECODE_RIL_A_INSTRUCTION(r1, imm);
+  uint32_t alu_out = 0;
+  alu_out = get_low_register<uint32_t>(r1);
+  alu_out = alu_out ^ imm;
+  set_low_register(r1, alu_out);
+  SetS390BitWiseConditionCode<uint32_t>(alu_out);
+  return length;
+}
+
+EVALUATE(NIHF) {
+  DCHECK_OPCODE(NIHF);
+  // Bitwise Op on upper 32-bits
+  DECODE_RIL_A_INSTRUCTION(r1, imm);
+  uint32_t alu_out = get_high_register<uint32_t>(r1);
+  alu_out &= imm;
+  SetS390BitWiseConditionCode<uint32_t>(alu_out);
+  set_high_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(NILF) {
+  DCHECK_OPCODE(NILF);
+  // Bitwise Op on lower 32-bits
+  DECODE_RIL_A_INSTRUCTION(r1, imm);
+  uint32_t alu_out = get_low_register<uint32_t>(r1);
+  alu_out &= imm;
+  SetS390BitWiseConditionCode<uint32_t>(alu_out);
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(OIHF) {
+  DCHECK_OPCODE(OIHF);
+  // Bitwise Op on upper 32-bits
+  DECODE_RIL_B_INSTRUCTION(r1, imm);
+  uint32_t alu_out = get_high_register<uint32_t>(r1);
+  alu_out |= imm;
+  SetS390BitWiseConditionCode<uint32_t>(alu_out);
+  set_high_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(OILF) {
+  DCHECK_OPCODE(OILF);
+  // Bitwise Op on lower 32-bits
+  DECODE_RIL_B_INSTRUCTION(r1, imm);
+  uint32_t alu_out = get_low_register<uint32_t>(r1);
+  alu_out |= imm;
+  SetS390BitWiseConditionCode<uint32_t>(alu_out);
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(LLIHF) {
+  DCHECK_OPCODE(LLIHF);
+  // Load Logical Immediate into high word
+  DECODE_RIL_A_INSTRUCTION(r1, i2);
+  uint64_t imm = static_cast<uint64_t>(i2);
+  set_register(r1, imm << 32);
+  return length;
+}
+
+EVALUATE(LLILF) {
+  DCHECK_OPCODE(LLILF);
+  // Load Logical into lower 32-bits (zero extend upper 32-bits)
+  DECODE_RIL_A_INSTRUCTION(r1, i2);
+  uint64_t imm = static_cast<uint64_t>(i2);
+  set_register(r1, imm);
+  return length;
+}
+
+EVALUATE(MSGFI) {
+  DCHECK_OPCODE(MSGFI);
+  DECODE_RIL_B_INSTRUCTION(r1, i2);
+  int64_t alu_out = get_register(r1);
+  alu_out = alu_out * i2;
+  set_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(MSFI) {
+  DCHECK_OPCODE(MSFI);
+  DECODE_RIL_B_INSTRUCTION(r1, i2);
+  int32_t alu_out = get_low_register<int32_t>(r1);
+  alu_out = alu_out * i2;
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(SLGFI) {
+  DCHECK_OPCODE(SLGFI);
+#ifndef V8_TARGET_ARCH_S390X
+  // should only be called on 64bit
+  DCHECK(false);
+#endif
+  DECODE_RIL_A_INSTRUCTION(r1, i2);
+  uint64_t r1_val = (uint64_t)(get_register(r1));
+  uint64_t alu_out;
+  alu_out = r1_val - i2;
+  set_register(r1, (intptr_t)alu_out);
+  SetS390ConditionCode<uint64_t>(alu_out, 0);
+  return length;
+}
+
+EVALUATE(SLFI) {
+  DCHECK_OPCODE(SLFI);
+  DECODE_RIL_A_INSTRUCTION(r1, imm);
+  uint32_t alu_out = get_low_register<uint32_t>(r1);
+  alu_out -= imm;
+  SetS390ConditionCode<uint32_t>(alu_out, 0);
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(AGFI) {
+  DCHECK_OPCODE(AGFI);
+  // Clobbering Add Word Immediate
+  DECODE_RIL_B_INSTRUCTION(r1, i2_val);
+  bool isOF = false;
+  // 64-bit Add (Register + 32-bit Imm)
+  int64_t r1_val = get_register(r1);
+  int64_t i2 = static_cast<int64_t>(i2_val);
+  isOF = CheckOverflowForIntAdd(r1_val, i2, int64_t);
+  int64_t alu_out = r1_val + i2;
+  set_register(r1, alu_out);
+  SetS390ConditionCode<int64_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(AFI) {
+  DCHECK_OPCODE(AFI);
+  // Clobbering Add Word Immediate
+  DECODE_RIL_B_INSTRUCTION(r1, i2);
+  bool isOF = false;
+  // 32-bit Add (Register + 32-bit Immediate)
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  isOF = CheckOverflowForIntAdd(r1_val, i2, int32_t);
+  int32_t alu_out = r1_val + i2;
+  set_low_register(r1, alu_out);
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(ALGFI) {
+  DCHECK_OPCODE(ALGFI);
+#ifndef V8_TARGET_ARCH_S390X
+  // should only be called on 64bit
+  DCHECK(false);
+#endif
+  DECODE_RIL_A_INSTRUCTION(r1, i2);
+  uint64_t r1_val = (uint64_t)(get_register(r1));
+  uint64_t alu_out;
+  alu_out = r1_val + i2;
+  set_register(r1, (intptr_t)alu_out);
+  SetS390ConditionCode<uint64_t>(alu_out, 0);
+
+  return length;
+}
+
+EVALUATE(ALFI) {
+  DCHECK_OPCODE(ALFI);
+  DECODE_RIL_A_INSTRUCTION(r1, imm);
+  uint32_t alu_out = get_low_register<uint32_t>(r1);
+  alu_out += imm;
+  SetS390ConditionCode<uint32_t>(alu_out, 0);
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(CGFI) {
+  DCHECK_OPCODE(CGFI);
+  // Compare with Immediate (64)
+  DECODE_RIL_B_INSTRUCTION(r1, i2);
+  int64_t imm = static_cast<int64_t>(i2);
+  SetS390ConditionCode<int64_t>(get_register(r1), imm);
+  return length;
+}
+
+EVALUATE(CFI) {
+  DCHECK_OPCODE(CFI);
+  // Compare with Immediate (32)
+  DECODE_RIL_B_INSTRUCTION(r1, imm);
+  SetS390ConditionCode<int32_t>(get_low_register<int32_t>(r1), imm);
+  return length;
+}
+
+EVALUATE(CLGFI) {
+  DCHECK_OPCODE(CLGFI);
+  // Compare Logical with Immediate (64)
+  DECODE_RIL_A_INSTRUCTION(r1, i2);
+  uint64_t imm = static_cast<uint64_t>(i2);
+  SetS390ConditionCode<uint64_t>(get_register(r1), imm);
+  return length;
+}
+
+EVALUATE(CLFI) {
+  DCHECK_OPCODE(CLFI);
+  // Compare Logical with Immediate (32)
+  DECODE_RIL_A_INSTRUCTION(r1, imm);
+  SetS390ConditionCode<uint32_t>(get_low_register<uint32_t>(r1), imm);
+  return length;
+}
+
+EVALUATE(LLHRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LGHRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LHRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LLGHRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STHRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LGRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STGRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LGFRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LLGFRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(EXRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(PFDRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGHRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CHRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGFRL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ECTG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CSST) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LPD) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LPDG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BRCTH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(AIH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ALSIH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ALSIHN) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CIH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STCK) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CFC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(IPM) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(HSCH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MSCH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SSCH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STSCH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TSCH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TPI) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SAL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(RSCH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STCRW) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STCPS) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(RCHP) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SCHM) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CKSM) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SAR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(EAR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MSR) {
+  DCHECK_OPCODE(MSR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  set_low_register(r1, r1_val * r2_val);
+  return length;
+}
+
+EVALUATE(MVST) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CUSE) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SRST) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(XSCH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STCKE) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STCKF) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SRNM) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STFPC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LFPC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TRE) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CUUTF) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CUTFU) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STFLE) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SRNMB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SRNMT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LFAS) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(PPA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ETND) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TEND) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(NIAI) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TABORT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TRAP4) {
+  DCHECK_OPCODE(TRAP4);
+  int length = 4;
+  // whack the space of the caller allocated stack
+  int64_t sp_addr = get_register(sp);
+  for (int i = 0; i < kCalleeRegisterSaveAreaSize / kPointerSize; ++i) {
+    // we dont want to whack the RA (r14)
+    if (i != 14) (reinterpret_cast<intptr_t*>(sp_addr))[i] = 0xdeadbabe;
+  }
+  SoftwareInterrupt(instr);
+  return length;
+}
+
+EVALUATE(LPEBR) {
+  DCHECK_OPCODE(LPEBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  float fr1_val = get_float32_from_d_register(r1);
+  float fr2_val = get_float32_from_d_register(r2);
+  fr1_val = std::fabs(fr2_val);
+  set_d_register_from_float32(r1, fr1_val);
+  if (fr2_val != fr2_val) {  // input is NaN
+    condition_reg_ = CC_OF;
+  } else if (fr2_val == 0) {
+    condition_reg_ = CC_EQ;
+  } else {
+    condition_reg_ = CC_GT;
+  }
+
+  return length;
+}
+
+EVALUATE(LNEBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LTEBR) {
+  DCHECK_OPCODE(LTEBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int64_t r2_val = get_d_register(r2);
+  float fr2_val = get_float32_from_d_register(r2);
+  SetS390ConditionCode<float>(fr2_val, 0.0);
+  set_d_register(r1, r2_val);
+  return length;
+}
+
+EVALUATE(LCEBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LDEBR) {
+  DCHECK_OPCODE(LDEBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  float fp_val = get_float32_from_d_register(r2);
+  double db_val = static_cast<double>(fp_val);
+  set_d_register_from_double(r1, db_val);
+  return length;
+}
+
+EVALUATE(LXDBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LXEBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MXDBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(KEBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CEBR) {
+  DCHECK_OPCODE(CEBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  float fr1_val = get_float32_from_d_register(r1);
+  float fr2_val = get_float32_from_d_register(r2);
+  if (isNaN(fr1_val) || isNaN(fr2_val)) {
+    condition_reg_ = CC_OF;
+  } else {
+    SetS390ConditionCode<float>(fr1_val, fr2_val);
+  }
+
+  return length;
+}
+
+EVALUATE(AEBR) {
+  DCHECK_OPCODE(AEBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  float fr1_val = get_float32_from_d_register(r1);
+  float fr2_val = get_float32_from_d_register(r2);
+  fr1_val += fr2_val;
+  set_d_register_from_float32(r1, fr1_val);
+  SetS390ConditionCode<float>(fr1_val, 0);
+
+  return length;
+}
+
+EVALUATE(SEBR) {
+  DCHECK_OPCODE(SEBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  float fr1_val = get_float32_from_d_register(r1);
+  float fr2_val = get_float32_from_d_register(r2);
+  fr1_val -= fr2_val;
+  set_d_register_from_float32(r1, fr1_val);
+  SetS390ConditionCode<float>(fr1_val, 0);
+
+  return length;
+}
+
+EVALUATE(MDEBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(DEBR) {
+  DCHECK_OPCODE(DEBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  float fr1_val = get_float32_from_d_register(r1);
+  float fr2_val = get_float32_from_d_register(r2);
+  fr1_val /= fr2_val;
+  set_d_register_from_float32(r1, fr1_val);
+  SetS390ConditionCode<float>(fr1_val, 0);
+
+  return length;
+}
+
+EVALUATE(MAEBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MSEBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LPDBR) {
+  DCHECK_OPCODE(LPDBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  double r1_val = get_double_from_d_register(r1);
+  double r2_val = get_double_from_d_register(r2);
+  r1_val = std::fabs(r2_val);
+  set_d_register_from_double(r1, r1_val);
+  if (r2_val != r2_val) {  // input is NaN
+    condition_reg_ = CC_OF;
+  } else if (r2_val == 0) {
+    condition_reg_ = CC_EQ;
+  } else {
+    condition_reg_ = CC_GT;
+  }
+  return length;
+}
+
+EVALUATE(LNDBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LTDBR) {
+  DCHECK_OPCODE(LTDBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int64_t r2_val = get_d_register(r2);
+  SetS390ConditionCode<double>(bit_cast<double, int64_t>(r2_val), 0.0);
+  set_d_register(r1, r2_val);
+  return length;
+}
+
+EVALUATE(LCDBR) {
+  DCHECK_OPCODE(LCDBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  double r1_val = get_double_from_d_register(r1);
+  double r2_val = get_double_from_d_register(r2);
+  r1_val = -r2_val;
+  set_d_register_from_double(r1, r1_val);
+  if (r2_val != r2_val) {  // input is NaN
+    condition_reg_ = CC_OF;
+  } else if (r2_val == 0) {
+    condition_reg_ = CC_EQ;
+  } else if (r2_val < 0) {
+    condition_reg_ = CC_LT;
+  } else if (r2_val > 0) {
+    condition_reg_ = CC_GT;
+  }
+  return length;
+}
+
+EVALUATE(SQEBR) {
+  DCHECK_OPCODE(SQEBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  float fr1_val = get_float32_from_d_register(r1);
+  float fr2_val = get_float32_from_d_register(r2);
+  fr1_val = std::sqrt(fr2_val);
+  set_d_register_from_float32(r1, fr1_val);
+  return length;
+}
+
+EVALUATE(SQDBR) {
+  DCHECK_OPCODE(SQDBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  double r1_val = get_double_from_d_register(r1);
+  double r2_val = get_double_from_d_register(r2);
+  r1_val = std::sqrt(r2_val);
+  set_d_register_from_double(r1, r1_val);
+  return length;
+}
+
+EVALUATE(SQXBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MEEBR) {
+  DCHECK_OPCODE(MEEBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  float fr1_val = get_float32_from_d_register(r1);
+  float fr2_val = get_float32_from_d_register(r2);
+  fr1_val *= fr2_val;
+  set_d_register_from_float32(r1, fr1_val);
+  SetS390ConditionCode<float>(fr1_val, 0);
+  return length;
+}
+
+EVALUATE(KDBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CDBR) {
+  DCHECK_OPCODE(CDBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  double r1_val = get_double_from_d_register(r1);
+  double r2_val = get_double_from_d_register(r2);
+  if (isNaN(r1_val) || isNaN(r2_val)) {
+    condition_reg_ = CC_OF;
+  } else {
+    SetS390ConditionCode<double>(r1_val, r2_val);
+  }
+  return length;
+}
+
+EVALUATE(ADBR) {
+  DCHECK_OPCODE(ADBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  double r1_val = get_double_from_d_register(r1);
+  double r2_val = get_double_from_d_register(r2);
+  r1_val += r2_val;
+  set_d_register_from_double(r1, r1_val);
+  SetS390ConditionCode<double>(r1_val, 0);
+  return length;
+}
+
+EVALUATE(SDBR) {
+  DCHECK_OPCODE(SDBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  double r1_val = get_double_from_d_register(r1);
+  double r2_val = get_double_from_d_register(r2);
+  r1_val -= r2_val;
+  set_d_register_from_double(r1, r1_val);
+  SetS390ConditionCode<double>(r1_val, 0);
+  return length;
+}
+
+EVALUATE(MDBR) {
+  DCHECK_OPCODE(MDBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  double r1_val = get_double_from_d_register(r1);
+  double r2_val = get_double_from_d_register(r2);
+  r1_val *= r2_val;
+  set_d_register_from_double(r1, r1_val);
+  SetS390ConditionCode<double>(r1_val, 0);
+  return length;
+}
+
+EVALUATE(DDBR) {
+  DCHECK_OPCODE(DDBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  double r1_val = get_double_from_d_register(r1);
+  double r2_val = get_double_from_d_register(r2);
+  r1_val /= r2_val;
+  set_d_register_from_double(r1, r1_val);
+  SetS390ConditionCode<double>(r1_val, 0);
+  return length;
+}
+
+EVALUATE(MADBR) {
+  DCHECK_OPCODE(MADBR);
+  DECODE_RRD_INSTRUCTION(r1, r2, r3);
+  double r1_val = get_double_from_d_register(r1);
+  double r2_val = get_double_from_d_register(r2);
+  double r3_val = get_double_from_d_register(r3);
+  r1_val += r2_val * r3_val;
+  set_d_register_from_double(r1, r1_val);
+  SetS390ConditionCode<double>(r1_val, 0);
+  return length;
+}
+
+EVALUATE(MSDBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LPXBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LNXBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LTXBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LCXBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LEDBRA) {
+  DCHECK_OPCODE(LEDBRA);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  double r2_val = get_double_from_d_register(r2);
+  set_d_register_from_float32(r1, static_cast<float>(r2_val));
+  return length;
+}
+
+EVALUATE(LDXBRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LEXBRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(FIXBRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(KXBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CXBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(AXBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SXBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MXBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(DXBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TBEDR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TBDR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(DIEBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(FIEBRA) {
+  DCHECK_OPCODE(FIEBRA);
+  DECODE_RRF_E_INSTRUCTION(r1, r2, m3, m4);
+  float r2_val = get_float32_from_d_register(r2);
+  CHECK(m4 == 0);
+  switch (m3) {
+    case Assembler::FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0:
+      set_d_register_from_float32(r1, round(r2_val));
+      break;
+    case Assembler::FIDBRA_ROUND_TOWARD_0:
+      set_d_register_from_float32(r1, trunc(r2_val));
+      break;
+    case Assembler::FIDBRA_ROUND_TOWARD_POS_INF:
+      set_d_register_from_float32(r1, std::ceil(r2_val));
+      break;
+    case Assembler::FIDBRA_ROUND_TOWARD_NEG_INF:
+      set_d_register_from_float32(r1, std::floor(r2_val));
+      break;
+    default:
+      UNIMPLEMENTED();
+      break;
+  }
+  return length;
+}
+
+EVALUATE(THDER) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(THDR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(DIDBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(FIDBRA) {
+  DCHECK_OPCODE(FIDBRA);
+  DECODE_RRF_E_INSTRUCTION(r1, r2, m3, m4);
+  double r2_val = get_double_from_d_register(r2);
+  CHECK(m4 == 0);
+  switch (m3) {
+    case Assembler::FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0:
+      set_d_register_from_double(r1, round(r2_val));
+      break;
+    case Assembler::FIDBRA_ROUND_TOWARD_0:
+      set_d_register_from_double(r1, trunc(r2_val));
+      break;
+    case Assembler::FIDBRA_ROUND_TOWARD_POS_INF:
+      set_d_register_from_double(r1, std::ceil(r2_val));
+      break;
+    case Assembler::FIDBRA_ROUND_TOWARD_NEG_INF:
+      set_d_register_from_double(r1, std::floor(r2_val));
+      break;
+    default:
+      UNIMPLEMENTED();
+      break;
+  }
+  return length;
+}
+
+EVALUATE(LXR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LPDFR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LNDFR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LCDFR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LZER) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LZDR) {
+  DCHECK_OPCODE(LZDR);
+  DECODE_RRE_INSTRUCTION_NO_R2(r1);
+  set_d_register_from_double(r1, 0.0);
+  return length;
+}
+
+EVALUATE(LZXR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SFPC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SFASR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(EFPC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CELFBR) {
+  DCHECK_OPCODE(CELFBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  uint32_t r2_val = get_low_register<uint32_t>(r2);
+  float r1_val = static_cast<float>(r2_val);
+  set_d_register_from_float32(r1, r1_val);
+  return length;
+}
+
+EVALUATE(CDLFBR) {
+  DCHECK_OPCODE(CDLFBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  uint32_t r2_val = get_low_register<uint32_t>(r2);
+  double r1_val = static_cast<double>(r2_val);
+  set_d_register_from_double(r1, r1_val);
+  return length;
+}
+
+EVALUATE(CXLFBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CEFBRA) {
+  DCHECK_OPCODE(CEFBRA);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int32_t fr2_val = get_low_register<int32_t>(r2);
+  float fr1_val = static_cast<float>(fr2_val);
+  set_d_register_from_float32(r1, fr1_val);
+  return length;
+}
+
+EVALUATE(CDFBRA) {
+  DCHECK_OPCODE(CDFBRA);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  double r1_val = static_cast<double>(r2_val);
+  set_d_register_from_double(r1, r1_val);
+  return length;
+}
+
+EVALUATE(CXFBRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CFEBRA) {
+  DCHECK_OPCODE(CFEBRA);
+  DECODE_RRE_INSTRUCTION_M3(r1, r2, mask_val);
+  float r2_fval = get_float32_from_d_register(r2);
+  int32_t r1_val = 0;
+
+  SetS390RoundConditionCode(r2_fval, INT32_MAX, INT32_MIN);
+
+  switch (mask_val) {
+    case CURRENT_ROUNDING_MODE:
+    case ROUND_TO_PREPARE_FOR_SHORTER_PRECISION: {
+      r1_val = static_cast<int32_t>(r2_fval);
+      break;
+    }
+    case ROUND_TO_NEAREST_WITH_TIES_AWAY_FROM_0: {
+      float ceil_val = std::ceil(r2_fval);
+      float floor_val = std::floor(r2_fval);
+      float sub_val1 = std::fabs(r2_fval - floor_val);
+      float sub_val2 = std::fabs(r2_fval - ceil_val);
+      if (sub_val1 > sub_val2) {
+        r1_val = static_cast<int32_t>(ceil_val);
+      } else if (sub_val1 < sub_val2) {
+        r1_val = static_cast<int32_t>(floor_val);
+      } else {  // round away from zero:
+        if (r2_fval > 0.0) {
+          r1_val = static_cast<int32_t>(ceil_val);
+        } else {
+          r1_val = static_cast<int32_t>(floor_val);
+        }
+      }
+      break;
+    }
+    case ROUND_TO_NEAREST_WITH_TIES_TO_EVEN: {
+      float ceil_val = std::ceil(r2_fval);
+      float floor_val = std::floor(r2_fval);
+      float sub_val1 = std::fabs(r2_fval - floor_val);
+      float sub_val2 = std::fabs(r2_fval - ceil_val);
+      if (sub_val1 > sub_val2) {
+        r1_val = static_cast<int32_t>(ceil_val);
+      } else if (sub_val1 < sub_val2) {
+        r1_val = static_cast<int32_t>(floor_val);
+      } else {  // check which one is even:
+        int32_t c_v = static_cast<int32_t>(ceil_val);
+        int32_t f_v = static_cast<int32_t>(floor_val);
+        if (f_v % 2 == 0)
+          r1_val = f_v;
+        else
+          r1_val = c_v;
+      }
+      break;
+    }
+    case ROUND_TOWARD_0: {
+      // check for overflow, cast r2_fval to 64bit integer
+      // then check value within the range of INT_MIN and INT_MAX
+      // and set condition code accordingly
+      int64_t temp = static_cast<int64_t>(r2_fval);
+      if (temp < INT_MIN || temp > INT_MAX) {
+        condition_reg_ = CC_OF;
+      }
+      r1_val = static_cast<int32_t>(r2_fval);
+      break;
+    }
+    case ROUND_TOWARD_PLUS_INFINITE: {
+      r1_val = static_cast<int32_t>(std::ceil(r2_fval));
+      break;
+    }
+    case ROUND_TOWARD_MINUS_INFINITE: {
+      // check for overflow, cast r2_fval to 64bit integer
+      // then check value within the range of INT_MIN and INT_MAX
+      // and set condition code accordingly
+      int64_t temp = static_cast<int64_t>(std::floor(r2_fval));
+      if (temp < INT_MIN || temp > INT_MAX) {
+        condition_reg_ = CC_OF;
+      }
+      r1_val = static_cast<int32_t>(std::floor(r2_fval));
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+  set_low_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(CFDBRA) {
+  DCHECK_OPCODE(CFDBRA);
+  DECODE_RRE_INSTRUCTION_M3(r1, r2, mask_val);
+  double r2_val = get_double_from_d_register(r2);
+  int32_t r1_val = 0;
+
+  SetS390RoundConditionCode(r2_val, INT32_MAX, INT32_MIN);
+
+  switch (mask_val) {
+    case CURRENT_ROUNDING_MODE:
+    case ROUND_TO_PREPARE_FOR_SHORTER_PRECISION: {
+      r1_val = static_cast<int32_t>(r2_val);
+      break;
+    }
+    case ROUND_TO_NEAREST_WITH_TIES_AWAY_FROM_0: {
+      double ceil_val = std::ceil(r2_val);
+      double floor_val = std::floor(r2_val);
+      double sub_val1 = std::fabs(r2_val - floor_val);
+      double sub_val2 = std::fabs(r2_val - ceil_val);
+      if (sub_val1 > sub_val2) {
+        r1_val = static_cast<int32_t>(ceil_val);
+      } else if (sub_val1 < sub_val2) {
+        r1_val = static_cast<int32_t>(floor_val);
+      } else {  // round away from zero:
+        if (r2_val > 0.0) {
+          r1_val = static_cast<int32_t>(ceil_val);
+        } else {
+          r1_val = static_cast<int32_t>(floor_val);
+        }
+      }
+      break;
+    }
+    case ROUND_TO_NEAREST_WITH_TIES_TO_EVEN: {
+      double ceil_val = std::ceil(r2_val);
+      double floor_val = std::floor(r2_val);
+      double sub_val1 = std::fabs(r2_val - floor_val);
+      double sub_val2 = std::fabs(r2_val - ceil_val);
+      if (sub_val1 > sub_val2) {
+        r1_val = static_cast<int32_t>(ceil_val);
+      } else if (sub_val1 < sub_val2) {
+        r1_val = static_cast<int32_t>(floor_val);
+      } else {  // check which one is even:
+        int32_t c_v = static_cast<int32_t>(ceil_val);
+        int32_t f_v = static_cast<int32_t>(floor_val);
+        if (f_v % 2 == 0)
+          r1_val = f_v;
+        else
+          r1_val = c_v;
+      }
+      break;
+    }
+    case ROUND_TOWARD_0: {
+      // check for overflow, cast r2_val to 64bit integer
+      // then check value within the range of INT_MIN and INT_MAX
+      // and set condition code accordingly
+      int64_t temp = static_cast<int64_t>(r2_val);
+      if (temp < INT_MIN || temp > INT_MAX) {
+        condition_reg_ = CC_OF;
+      }
+      r1_val = static_cast<int32_t>(r2_val);
+      break;
+    }
+    case ROUND_TOWARD_PLUS_INFINITE: {
+      r1_val = static_cast<int32_t>(std::ceil(r2_val));
+      break;
+    }
+    case ROUND_TOWARD_MINUS_INFINITE: {
+      // check for overflow, cast r2_val to 64bit integer
+      // then check value within the range of INT_MIN and INT_MAX
+      // and set condition code accordingly
+      int64_t temp = static_cast<int64_t>(std::floor(r2_val));
+      if (temp < INT_MIN || temp > INT_MAX) {
+        condition_reg_ = CC_OF;
+      }
+      r1_val = static_cast<int32_t>(std::floor(r2_val));
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+  set_low_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(CFXBRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CLFEBR) {
+  DCHECK_OPCODE(CLFEBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  float r2_val = get_float32_from_d_register(r2);
+  uint32_t r1_val = static_cast<uint32_t>(r2_val);
+  set_low_register(r1, r1_val);
+  SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT32_MAX);
+  return length;
+}
+
+EVALUATE(CLFDBR) {
+  DCHECK_OPCODE(CLFDBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  double r2_val = get_double_from_d_register(r2);
+  uint32_t r1_val = static_cast<uint32_t>(r2_val);
+  set_low_register(r1, r1_val);
+  SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT32_MAX);
+  return length;
+}
+
+EVALUATE(CLFXBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CELGBR) {
+  DCHECK_OPCODE(CELGBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  uint64_t r2_val = get_register(r2);
+  float r1_val = static_cast<float>(r2_val);
+  set_d_register_from_float32(r1, r1_val);
+  return length;
+}
+
+EVALUATE(CDLGBR) {
+  DCHECK_OPCODE(CDLGBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  uint64_t r2_val = get_register(r2);
+  double r1_val = static_cast<double>(r2_val);
+  set_d_register_from_double(r1, r1_val);
+  return length;
+}
+
+EVALUATE(CXLGBR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CEGBRA) {
+  DCHECK_OPCODE(CEGBRA);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int64_t fr2_val = get_register(r2);
+  float fr1_val = static_cast<float>(fr2_val);
+  set_d_register_from_float32(r1, fr1_val);
+  return length;
+}
+
+EVALUATE(CDGBRA) {
+  DCHECK_OPCODE(CDGBRA);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int64_t r2_val = get_register(r2);
+  double r1_val = static_cast<double>(r2_val);
+  set_d_register_from_double(r1, r1_val);
+  return length;
+}
+
+EVALUATE(CXGBRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGEBRA) {
+  DCHECK_OPCODE(CGEBRA);
+  DECODE_RRE_INSTRUCTION_M3(r1, r2, mask_val);
+  float r2_fval = get_float32_from_d_register(r2);
+  int64_t r1_val = 0;
+
+  SetS390RoundConditionCode(r2_fval, INT64_MAX, INT64_MIN);
+
+  switch (mask_val) {
+    case CURRENT_ROUNDING_MODE:
+    case ROUND_TO_NEAREST_WITH_TIES_AWAY_FROM_0:
+    case ROUND_TO_PREPARE_FOR_SHORTER_PRECISION: {
+      UNIMPLEMENTED();
+      break;
+    }
+    case ROUND_TO_NEAREST_WITH_TIES_TO_EVEN: {
+      float ceil_val = std::ceil(r2_fval);
+      float floor_val = std::floor(r2_fval);
+      if (std::abs(r2_fval - floor_val) > std::abs(r2_fval - ceil_val)) {
+        r1_val = static_cast<int64_t>(ceil_val);
+      } else if (std::abs(r2_fval - floor_val) < std::abs(r2_fval - ceil_val)) {
+        r1_val = static_cast<int64_t>(floor_val);
+      } else {  // check which one is even:
+        int64_t c_v = static_cast<int64_t>(ceil_val);
+        int64_t f_v = static_cast<int64_t>(floor_val);
+        if (f_v % 2 == 0)
+          r1_val = f_v;
+        else
+          r1_val = c_v;
+      }
+      break;
+    }
+    case ROUND_TOWARD_0: {
+      r1_val = static_cast<int64_t>(r2_fval);
+      break;
+    }
+    case ROUND_TOWARD_PLUS_INFINITE: {
+      r1_val = static_cast<int64_t>(std::ceil(r2_fval));
+      break;
+    }
+    case ROUND_TOWARD_MINUS_INFINITE: {
+      r1_val = static_cast<int64_t>(std::floor(r2_fval));
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+  set_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(CGDBRA) {
+  DCHECK_OPCODE(CGDBRA);
+  DECODE_RRE_INSTRUCTION_M3(r1, r2, mask_val);
+  double r2_val = get_double_from_d_register(r2);
+  int64_t r1_val = 0;
+
+  SetS390RoundConditionCode(r2_val, INT64_MAX, INT64_MIN);
+
+  switch (mask_val) {
+    case CURRENT_ROUNDING_MODE:
+    case ROUND_TO_NEAREST_WITH_TIES_AWAY_FROM_0:
+    case ROUND_TO_PREPARE_FOR_SHORTER_PRECISION: {
+      UNIMPLEMENTED();
+      break;
+    }
+    case ROUND_TO_NEAREST_WITH_TIES_TO_EVEN: {
+      double ceil_val = std::ceil(r2_val);
+      double floor_val = std::floor(r2_val);
+      if (std::abs(r2_val - floor_val) > std::abs(r2_val - ceil_val)) {
+        r1_val = static_cast<int64_t>(ceil_val);
+      } else if (std::abs(r2_val - floor_val) < std::abs(r2_val - ceil_val)) {
+        r1_val = static_cast<int64_t>(floor_val);
+      } else {  // check which one is even:
+        int64_t c_v = static_cast<int64_t>(ceil_val);
+        int64_t f_v = static_cast<int64_t>(floor_val);
+        if (f_v % 2 == 0)
+          r1_val = f_v;
+        else
+          r1_val = c_v;
+      }
+      break;
+    }
+    case ROUND_TOWARD_0: {
+      r1_val = static_cast<int64_t>(r2_val);
+      break;
+    }
+    case ROUND_TOWARD_PLUS_INFINITE: {
+      r1_val = static_cast<int64_t>(std::ceil(r2_val));
+      break;
+    }
+    case ROUND_TOWARD_MINUS_INFINITE: {
+      r1_val = static_cast<int64_t>(std::floor(r2_val));
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+  set_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(CGXBRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CLGEBR) {
+  DCHECK_OPCODE(CLGEBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  float r2_val = get_float32_from_d_register(r2);
+  uint64_t r1_val = static_cast<uint64_t>(r2_val);
+  set_register(r1, r1_val);
+  SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT64_MAX);
+  return length;
+}
+
+EVALUATE(CLGDBR) {
+  DCHECK_OPCODE(CLGDBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  double r2_val = get_double_from_d_register(r2);
+  uint64_t r1_val = static_cast<uint64_t>(r2_val);
+  set_register(r1, r1_val);
+  SetS390ConvertConditionCode<double>(r2_val, r1_val, UINT64_MAX);
+  return length;
+}
+
+EVALUATE(CFER) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CFDR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CFXR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LDGR) {
+  DCHECK_OPCODE(LDGR);
+  // Load FPR from GPR (L <- 64)
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  uint64_t int_val = get_register(r2);
+  // double double_val = bit_cast<double, uint64_t>(int_val);
+  // set_d_register_from_double(rreInst->R1Value(), double_val);
+  set_d_register(r1, int_val);
+  return length;
+}
+
+EVALUATE(CGER) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGDR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGXR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LGDR) {
+  DCHECK_OPCODE(LGDR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  // Load GPR from FPR (64 <- L)
+  int64_t double_val = get_d_register(r2);
+  set_register(r1, double_val);
+  return length;
+}
+
+EVALUATE(MDTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MDTRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(DDTRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ADTRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SDTRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LDETR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LEDTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LTDTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(FIDTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MXTRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(DXTRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(AXTRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SXTRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LXDTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LDXTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LTXTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(FIXTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(KDTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGDTRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CUDTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CDTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(EEDTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ESDTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(KXTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGXTRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CUXTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CSXTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CXTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(EEXTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ESXTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CDGTRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CDUTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CDSTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CEDTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(QADTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(IEDTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(RRDTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CXGTRA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CXUTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CXSTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CEXTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(QAXTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(IEXTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(RRXTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LPGR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LNGR) {
+  DCHECK_OPCODE(LNGR);
+  // Load Negative (64)
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int64_t r2_val = get_register(r2);
+  r2_val = (r2_val >= 0) ? -r2_val : r2_val;  // If pos, then negate it.
+  set_register(r1, r2_val);
+  condition_reg_ = (r2_val == 0) ? CC_EQ : CC_LT;  // CC0 - result is zero
+  // CC1 - result is negative
+  return length;
+}
+
+EVALUATE(LTGR) {
+  DCHECK_OPCODE(LTGR);
+  // Load Register (64)
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int64_t r2_val = get_register(r2);
+  SetS390ConditionCode<int64_t>(r2_val, 0);
+  set_register(r1, get_register(r2));
+  return length;
+}
+
+EVALUATE(LCGR) {
+  DCHECK_OPCODE(LCGR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int64_t r2_val = get_register(r2);
+  r2_val = ~r2_val;
+  r2_val = r2_val + 1;
+  set_register(r1, r2_val);
+  SetS390ConditionCode<int64_t>(r2_val, 0);
+  // if the input is INT_MIN, loading its compliment would be overflowing
+  if (r2_val < 0 && (r2_val + 1) > 0) {
+    SetS390OverflowCode(true);
+  }
+  return length;
+}
+
+EVALUATE(SGR) {
+  DCHECK_OPCODE(SGR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int64_t r1_val = get_register(r1);
+  int64_t r2_val = get_register(r2);
+  bool isOF = false;
+  isOF = CheckOverflowForIntSub(r1_val, r2_val, int64_t);
+  r1_val -= r2_val;
+  SetS390ConditionCode<int64_t>(r1_val, 0);
+  SetS390OverflowCode(isOF);
+  set_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(ALGR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SLGR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MSGR) {
+  DCHECK_OPCODE(MSGR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int64_t r1_val = get_register(r1);
+  int64_t r2_val = get_register(r2);
+  set_register(r1, r1_val * r2_val);
+  return length;
+}
+
+EVALUATE(DSGR) {
+  DCHECK_OPCODE(DSGR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+
+  DCHECK(r1 % 2 == 0);
+
+  int64_t dividend = get_register(r1 + 1);
+  int64_t divisor = get_register(r2);
+  set_register(r1, dividend % divisor);
+  set_register(r1 + 1, dividend / divisor);
+  return length;
+}
+
+EVALUATE(LRVGR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LPGFR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LNGFR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LTGFR) {
+  DCHECK_OPCODE(LTGFR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  // Load and Test Register (64 <- 32)  (Sign Extends 32-bit val)
+  // Load Register (64 <- 32)  (Sign Extends 32-bit val)
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  int64_t result = static_cast<int64_t>(r2_val);
+  set_register(r1, result);
+  SetS390ConditionCode<int64_t>(result, 0);
+  return length;
+}
+
+EVALUATE(LCGFR) {
+  DCHECK_OPCODE(LCGFR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  // Load and Test Register (64 <- 32)  (Sign Extends 32-bit val)
+  // Load Register (64 <- 32)  (Sign Extends 32-bit val)
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  int64_t result = static_cast<int64_t>(r2_val);
+  set_register(r1, result);
+  return length;
+}
+
+EVALUATE(LLGFR) {
+  DCHECK_OPCODE(LLGFR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  uint64_t r2_finalval = (static_cast<uint64_t>(r2_val) & 0x00000000ffffffff);
+  set_register(r1, r2_finalval);
+  return length;
+}
+
+EVALUATE(LLGTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(AGFR) {
+  DCHECK_OPCODE(AGFR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  // Add Register (64 <- 32)  (Sign Extends 32-bit val)
+  int64_t r1_val = get_register(r1);
+  int64_t r2_val = static_cast<int64_t>(get_low_register<int32_t>(r2));
+  bool isOF = CheckOverflowForIntAdd(r1_val, r2_val, int64_t);
+  r1_val += r2_val;
+  SetS390ConditionCode<int64_t>(r1_val, 0);
+  SetS390OverflowCode(isOF);
+  set_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(SGFR) {
+  DCHECK_OPCODE(SGFR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  // Sub Reg (64 <- 32)
+  int64_t r1_val = get_register(r1);
+  int64_t r2_val = static_cast<int64_t>(get_low_register<int32_t>(r2));
+  bool isOF = false;
+  isOF = CheckOverflowForIntSub(r1_val, r2_val, int64_t);
+  r1_val -= r2_val;
+  SetS390ConditionCode<int64_t>(r1_val, 0);
+  SetS390OverflowCode(isOF);
+  set_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(ALGFR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SLGFR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MSGFR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(DSGFR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(KMAC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LRVR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGR) {
+  DCHECK_OPCODE(CGR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  // Compare (64)
+  int64_t r1_val = get_register(r1);
+  int64_t r2_val = get_register(r2);
+  SetS390ConditionCode<int64_t>(r1_val, r2_val);
+  return length;
+}
+
+EVALUATE(CLGR) {
+  DCHECK_OPCODE(CLGR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  // Compare Logical (64)
+  uint64_t r1_val = static_cast<uint64_t>(get_register(r1));
+  uint64_t r2_val = static_cast<uint64_t>(get_register(r2));
+  SetS390ConditionCode<uint64_t>(r1_val, r2_val);
+  return length;
+}
+
+EVALUATE(KMF) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(KMO) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(PCC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(KMCTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(KM) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(KMC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGFR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(KIMD) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(KLMD) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CFDTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CLGDTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CLFDTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BCTGR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CFXTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CLFXTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CDFTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CDLGTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CDLFTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CXFTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CXLGTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CXLFTR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGRT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(NGR) {
+  DCHECK_OPCODE(NGR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int64_t r1_val = get_register(r1);
+  int64_t r2_val = get_register(r2);
+  r1_val &= r2_val;
+  SetS390BitWiseConditionCode<uint64_t>(r1_val);
+  set_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(OGR) {
+  DCHECK_OPCODE(OGR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int64_t r1_val = get_register(r1);
+  int64_t r2_val = get_register(r2);
+  r1_val |= r2_val;
+  SetS390BitWiseConditionCode<uint64_t>(r1_val);
+  set_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(XGR) {
+  DCHECK_OPCODE(XGR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int64_t r1_val = get_register(r1);
+  int64_t r2_val = get_register(r2);
+  r1_val ^= r2_val;
+  SetS390BitWiseConditionCode<uint64_t>(r1_val);
+  set_register(r1, r1_val);
+  return length;
+}
+
+EVALUATE(FLOGR) {
+  DCHECK_OPCODE(FLOGR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+
+  DCHECK(r1 % 2 == 0);
+
+  int64_t r2_val = get_register(r2);
+
+  int i = 0;
+  for (; i < 64; i++) {
+    if (r2_val < 0) break;
+    r2_val <<= 1;
+  }
+
+  r2_val = get_register(r2);
+
+  int64_t mask = ~(1 << (63 - i));
+  set_register(r1, i);
+  set_register(r1 + 1, r2_val & mask);
+  return length;
+}
+
+EVALUATE(LLGCR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LLGHR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MLGR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(DLGR) {
+  DCHECK_OPCODE(DLGR);
+#ifdef V8_TARGET_ARCH_S390X
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  uint64_t r1_val = get_register(r1);
+  uint64_t r2_val = get_register(r2);
+  DCHECK(r1 % 2 == 0);
+  unsigned __int128 dividend = static_cast<unsigned __int128>(r1_val) << 64;
+  dividend += get_register(r1 + 1);
+  uint64_t remainder = dividend % r2_val;
+  uint64_t quotient = dividend / r2_val;
+  r1_val = remainder;
+  set_register(r1, remainder);
+  set_register(r1 + 1, quotient);
+  return length;
+#else
+  UNREACHABLE();
+#endif
+}
+
+EVALUATE(ALCGR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SLBGR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(EPSW) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TRTT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TRTO) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TROT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TROO) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LLCR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LLHR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MLR) {
+  DCHECK_OPCODE(MLR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  DCHECK(r1 % 2 == 0);
+
+  uint32_t r1_val = get_low_register<uint32_t>(r1 + 1);
+  uint32_t r2_val = get_low_register<uint32_t>(r2);
+  uint64_t product =
+      static_cast<uint64_t>(r1_val) * static_cast<uint64_t>(r2_val);
+  int32_t high_bits = product >> 32;
+  int32_t low_bits = product & 0x00000000FFFFFFFF;
+  set_low_register(r1, high_bits);
+  set_low_register(r1 + 1, low_bits);
+  return length;
+}
+
+EVALUATE(DLR) {
+  DCHECK_OPCODE(DLR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  uint32_t r1_val = get_low_register<uint32_t>(r1);
+  uint32_t r2_val = get_low_register<uint32_t>(r2);
+  DCHECK(r1 % 2 == 0);
+  uint64_t dividend = static_cast<uint64_t>(r1_val) << 32;
+  dividend += get_low_register<uint32_t>(r1 + 1);
+  uint32_t remainder = dividend % r2_val;
+  uint32_t quotient = dividend / r2_val;
+  r1_val = remainder;
+  set_low_register(r1, remainder);
+  set_low_register(r1 + 1, quotient);
+  return length;
+}
+
+EVALUATE(ALCR) {
+  DCHECK_OPCODE(ALCR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  uint32_t r1_val = get_low_register<uint32_t>(r1);
+  uint32_t r2_val = get_low_register<uint32_t>(r2);
+  uint32_t alu_out = 0;
+  bool isOF = false;
+
+  alu_out = r1_val + r2_val;
+  bool isOF_original = CheckOverflowForUIntAdd(r1_val, r2_val);
+  if (TestConditionCode((Condition)2) || TestConditionCode((Condition)3)) {
+    alu_out = alu_out + 1;
+    isOF = isOF_original || CheckOverflowForUIntAdd(alu_out, 1);
+  } else {
+    isOF = isOF_original;
+  }
+  set_low_register(r1, alu_out);
+  SetS390ConditionCodeCarry<uint32_t>(alu_out, isOF);
+  return length;
+}
+
+EVALUATE(SLBR) {
+  DCHECK_OPCODE(SLBR);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  uint32_t r1_val = get_low_register<uint32_t>(r1);
+  uint32_t r2_val = get_low_register<uint32_t>(r2);
+  uint32_t alu_out = 0;
+  bool isOF = false;
+
+  alu_out = r1_val - r2_val;
+  bool isOF_original = CheckOverflowForUIntSub(r1_val, r2_val);
+  if (TestConditionCode((Condition)2) || TestConditionCode((Condition)3)) {
+    alu_out = alu_out - 1;
+    isOF = isOF_original || CheckOverflowForUIntSub(alu_out, 1);
+  } else {
+    isOF = isOF_original;
+  }
+  set_low_register(r1, alu_out);
+  SetS390ConditionCodeCarry<uint32_t>(alu_out, isOF);
+  return length;
+}
+
+EVALUATE(CU14) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CU24) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CU41) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CU42) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TRTRE) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SRSTU) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TRTE) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(AHHHR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SHHHR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ALHHHR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SLHHHR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CHHR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(AHHLR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SHHLR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ALHHLR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SLHHLR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CHLR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(POPCNT_Z) {
+  DCHECK_OPCODE(POPCNT_Z);
+  DECODE_RRE_INSTRUCTION(r1, r2);
+  int64_t r2_val = get_register(r2);
+  int64_t r1_val = 0;
+
+  uint8_t* r2_val_ptr = reinterpret_cast<uint8_t*>(&r2_val);
+  uint8_t* r1_val_ptr = reinterpret_cast<uint8_t*>(&r1_val);
+  for (int i = 0; i < 8; i++) {
+    uint32_t x = static_cast<uint32_t>(r2_val_ptr[i]);
+#if defined(__GNUC__)
+    r1_val_ptr[i] = __builtin_popcount(x);
+#else
+#error unsupport __builtin_popcount
+#endif
+  }
+  set_register(r1, static_cast<uint64_t>(r1_val));
+  return length;
+}
+
+EVALUATE(LOCGR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(NGRK) {
+  DCHECK_OPCODE(NGRK);
+  DECODE_RRF_A_INSTRUCTION(r1, r2, r3);
+  // 64-bit Non-clobbering arithmetics / bitwise ops.
+  int64_t r2_val = get_register(r2);
+  int64_t r3_val = get_register(r3);
+  uint64_t bitwise_result = 0;
+  bitwise_result = r2_val & r3_val;
+  SetS390BitWiseConditionCode<uint64_t>(bitwise_result);
+  set_register(r1, bitwise_result);
+  return length;
+}
+
+EVALUATE(OGRK) {
+  DCHECK_OPCODE(OGRK);
+  DECODE_RRF_A_INSTRUCTION(r1, r2, r3);
+  // 64-bit Non-clobbering arithmetics / bitwise ops.
+  int64_t r2_val = get_register(r2);
+  int64_t r3_val = get_register(r3);
+  uint64_t bitwise_result = 0;
+  bitwise_result = r2_val | r3_val;
+  SetS390BitWiseConditionCode<uint64_t>(bitwise_result);
+  set_register(r1, bitwise_result);
+  return length;
+}
+
+EVALUATE(XGRK) {
+  DCHECK_OPCODE(XGRK);
+  DECODE_RRF_A_INSTRUCTION(r1, r2, r3);
+  // 64-bit Non-clobbering arithmetics / bitwise ops.
+  int64_t r2_val = get_register(r2);
+  int64_t r3_val = get_register(r3);
+  uint64_t bitwise_result = 0;
+  bitwise_result = r2_val ^ r3_val;
+  SetS390BitWiseConditionCode<uint64_t>(bitwise_result);
+  set_register(r1, bitwise_result);
+  return length;
+}
+
+EVALUATE(AGRK) {
+  DCHECK_OPCODE(AGRK);
+  DECODE_RRF_A_INSTRUCTION(r1, r2, r3);
+  // 64-bit Non-clobbering arithmetics / bitwise ops.
+  int64_t r2_val = get_register(r2);
+  int64_t r3_val = get_register(r3);
+  bool isOF = CheckOverflowForIntAdd(r2_val, r3_val, int64_t);
+  SetS390ConditionCode<int64_t>(r2_val + r3_val, 0);
+  SetS390OverflowCode(isOF);
+  set_register(r1, r2_val + r3_val);
+  return length;
+}
+
+EVALUATE(SGRK) {
+  DCHECK_OPCODE(SGRK);
+  DECODE_RRF_A_INSTRUCTION(r1, r2, r3);
+  // 64-bit Non-clobbering arithmetics / bitwise ops.
+  int64_t r2_val = get_register(r2);
+  int64_t r3_val = get_register(r3);
+  bool isOF = CheckOverflowForIntSub(r2_val, r3_val, int64_t);
+  SetS390ConditionCode<int64_t>(r2_val - r3_val, 0);
+  SetS390OverflowCode(isOF);
+  set_register(r1, r2_val - r3_val);
+  return length;
+}
+
+EVALUATE(ALGRK) {
+  DCHECK_OPCODE(ALGRK);
+  DECODE_RRF_A_INSTRUCTION(r1, r2, r3);
+  // 64-bit Non-clobbering unsigned arithmetics
+  uint64_t r2_val = get_register(r2);
+  uint64_t r3_val = get_register(r3);
+  bool isOF = CheckOverflowForUIntAdd(r2_val, r3_val);
+  SetS390ConditionCode<uint64_t>(r2_val + r3_val, 0);
+  SetS390OverflowCode(isOF);
+  set_register(r1, r2_val + r3_val);
+  return length;
+}
+
+EVALUATE(SLGRK) {
+  DCHECK_OPCODE(SLGRK);
+  DECODE_RRF_A_INSTRUCTION(r1, r2, r3);
+  // 64-bit Non-clobbering unsigned arithmetics
+  uint64_t r2_val = get_register(r2);
+  uint64_t r3_val = get_register(r3);
+  bool isOF = CheckOverflowForUIntSub(r2_val, r3_val);
+  SetS390ConditionCode<uint64_t>(r2_val - r3_val, 0);
+  SetS390OverflowCode(isOF);
+  set_register(r1, r2_val - r3_val);
+  return length;
+}
+
+EVALUATE(LOCR) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(NRK) {
+  DCHECK_OPCODE(NRK);
+  DECODE_RRF_A_INSTRUCTION(r1, r2, r3);
+  // 32-bit Non-clobbering arithmetics / bitwise ops
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  int32_t r3_val = get_low_register<int32_t>(r3);
+  // Assume bitwise operation here
+  uint32_t bitwise_result = 0;
+  bitwise_result = r2_val & r3_val;
+  SetS390BitWiseConditionCode<uint32_t>(bitwise_result);
+  set_low_register(r1, bitwise_result);
+  return length;
+}
+
+EVALUATE(ORK) {
+  DCHECK_OPCODE(ORK);
+  DECODE_RRF_A_INSTRUCTION(r1, r2, r3);
+  // 32-bit Non-clobbering arithmetics / bitwise ops
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  int32_t r3_val = get_low_register<int32_t>(r3);
+  // Assume bitwise operation here
+  uint32_t bitwise_result = 0;
+  bitwise_result = r2_val | r3_val;
+  SetS390BitWiseConditionCode<uint32_t>(bitwise_result);
+  set_low_register(r1, bitwise_result);
+  return length;
+}
+
+EVALUATE(XRK) {
+  DCHECK_OPCODE(XRK);
+  DECODE_RRF_A_INSTRUCTION(r1, r2, r3);
+  // 32-bit Non-clobbering arithmetics / bitwise ops
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  int32_t r3_val = get_low_register<int32_t>(r3);
+  // Assume bitwise operation here
+  uint32_t bitwise_result = 0;
+  bitwise_result = r2_val ^ r3_val;
+  SetS390BitWiseConditionCode<uint32_t>(bitwise_result);
+  set_low_register(r1, bitwise_result);
+  return length;
+}
+
+EVALUATE(ARK) {
+  DCHECK_OPCODE(ARK);
+  DECODE_RRF_A_INSTRUCTION(r1, r2, r3);
+  // 32-bit Non-clobbering arithmetics / bitwise ops
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  int32_t r3_val = get_low_register<int32_t>(r3);
+  bool isOF = CheckOverflowForIntAdd(r2_val, r3_val, int32_t);
+  SetS390ConditionCode<int32_t>(r2_val + r3_val, 0);
+  SetS390OverflowCode(isOF);
+  set_low_register(r1, r2_val + r3_val);
+  return length;
+}
+
+EVALUATE(SRK) {
+  DCHECK_OPCODE(SRK);
+  DECODE_RRF_A_INSTRUCTION(r1, r2, r3);
+  // 32-bit Non-clobbering arithmetics / bitwise ops
+  int32_t r2_val = get_low_register<int32_t>(r2);
+  int32_t r3_val = get_low_register<int32_t>(r3);
+  bool isOF = CheckOverflowForIntSub(r2_val, r3_val, int32_t);
+  SetS390ConditionCode<int32_t>(r2_val - r3_val, 0);
+  SetS390OverflowCode(isOF);
+  set_low_register(r1, r2_val - r3_val);
+  return length;
+}
+
+EVALUATE(ALRK) {
+  DCHECK_OPCODE(ALRK);
+  DECODE_RRF_A_INSTRUCTION(r1, r2, r3);
+  // 32-bit Non-clobbering unsigned arithmetics
+  uint32_t r2_val = get_low_register<uint32_t>(r2);
+  uint32_t r3_val = get_low_register<uint32_t>(r3);
+  bool isOF = CheckOverflowForUIntAdd(r2_val, r3_val);
+  SetS390ConditionCode<uint32_t>(r2_val + r3_val, 0);
+  SetS390OverflowCode(isOF);
+  set_low_register(r1, r2_val + r3_val);
+  return length;
+}
+
+EVALUATE(SLRK) {
+  DCHECK_OPCODE(SLRK);
+  DECODE_RRF_A_INSTRUCTION(r1, r2, r3);
+  // 32-bit Non-clobbering unsigned arithmetics
+  uint32_t r2_val = get_low_register<uint32_t>(r2);
+  uint32_t r3_val = get_low_register<uint32_t>(r3);
+  bool isOF = CheckOverflowForUIntSub(r2_val, r3_val);
+  SetS390ConditionCode<uint32_t>(r2_val - r3_val, 0);
+  SetS390OverflowCode(isOF);
+  set_low_register(r1, r2_val - r3_val);
+  return length;
+}
+
+EVALUATE(LTG) {
+  DCHECK_OPCODE(LTG);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t addr = x2_val + b2_val + d2;
+  int64_t value = ReadDW(addr);
+  set_register(r1, value);
+  SetS390ConditionCode<int64_t>(value, 0);
+  return length;
+}
+
+EVALUATE(CVBY) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(AG) {
+  DCHECK_OPCODE(AG);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t alu_out = get_register(r1);
+  int64_t mem_val = ReadDW(b2_val + x2_val + d2);
+  alu_out += mem_val;
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  set_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(SG) {
+  DCHECK_OPCODE(SG);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t alu_out = get_register(r1);
+  int64_t mem_val = ReadDW(b2_val + x2_val + d2);
+  alu_out -= mem_val;
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  set_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(ALG) {
+  DCHECK_OPCODE(ALG);
+#ifndef V8_TARGET_ARCH_S390X
+  DCHECK(false);
+#endif
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  uint64_t r1_val = get_register(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t d2_val = d2;
+  uint64_t alu_out = r1_val;
+  uint64_t mem_val = static_cast<uint64_t>(ReadDW(b2_val + d2_val + x2_val));
+  alu_out += mem_val;
+  SetS390ConditionCode<uint64_t>(alu_out, 0);
+  set_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(SLG) {
+  DCHECK_OPCODE(SLG);
+#ifndef V8_TARGET_ARCH_S390X
+  DCHECK(false);
+#endif
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  uint64_t r1_val = get_register(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t d2_val = d2;
+  uint64_t alu_out = r1_val;
+  uint64_t mem_val = static_cast<uint64_t>(ReadDW(b2_val + d2_val + x2_val));
+  alu_out -= mem_val;
+  SetS390ConditionCode<uint64_t>(alu_out, 0);
+  set_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(MSG) {
+  DCHECK_OPCODE(MSG);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t d2_val = d2;
+  int64_t mem_val = ReadDW(b2_val + d2_val + x2_val);
+  int64_t r1_val = get_register(r1);
+  set_register(r1, mem_val * r1_val);
+  return length;
+}
+
+EVALUATE(DSG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CVBG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LRVG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LT) {
+  DCHECK_OPCODE(LT);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t addr = x2_val + b2_val + d2;
+  int32_t value = ReadW(addr, instr);
+  set_low_register(r1, value);
+  SetS390ConditionCode<int32_t>(value, 0);
+  return length;
+}
+
+EVALUATE(LGH) {
+  DCHECK_OPCODE(LGH);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  // Miscellaneous Loads and Stores
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t addr = x2_val + b2_val + d2;
+  int64_t mem_val = static_cast<int64_t>(ReadH(addr, instr));
+  set_register(r1, mem_val);
+  return length;
+}
+
+EVALUATE(LLGF) {
+  DCHECK_OPCODE(LLGF);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  // Miscellaneous Loads and Stores
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t addr = x2_val + b2_val + d2;
+  uint64_t mem_val = static_cast<uint64_t>(ReadWU(addr, instr));
+  set_register(r1, mem_val);
+  return length;
+}
+
+EVALUATE(LLGT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(AGF) {
+  DCHECK_OPCODE(AGF);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  uint64_t r1_val = get_register(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t d2_val = d2;
+  uint64_t alu_out = r1_val;
+  uint32_t mem_val = ReadW(b2_val + d2_val + x2_val, instr);
+  alu_out += mem_val;
+  SetS390ConditionCode<int64_t>(alu_out, 0);
+  set_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(SGF) {
+  DCHECK_OPCODE(SGF);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  uint64_t r1_val = get_register(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t d2_val = d2;
+  uint64_t alu_out = r1_val;
+  uint32_t mem_val = ReadW(b2_val + d2_val + x2_val, instr);
+  alu_out -= mem_val;
+  SetS390ConditionCode<int64_t>(alu_out, 0);
+  set_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(ALGF) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SLGF) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MSGF) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(DSGF) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LRV) {
+  DCHECK_OPCODE(LRV);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t mem_addr = b2_val + x2_val + d2;
+  int32_t mem_val = ReadW(mem_addr, instr);
+  set_low_register(r1, ByteReverse(mem_val));
+  return length;
+}
+
+EVALUATE(LRVH) {
+  DCHECK_OPCODE(LRVH);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t mem_addr = b2_val + x2_val + d2;
+  int16_t mem_val = ReadH(mem_addr, instr);
+  int32_t result = ByteReverse(mem_val) & 0x0000ffff;
+  result |= r1_val & 0xffff0000;
+  set_low_register(r1, result);
+  return length;
+}
+
+EVALUATE(CG) {
+  DCHECK_OPCODE(CG);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t alu_out = get_register(r1);
+  int64_t mem_val = ReadDW(b2_val + x2_val + d2);
+  SetS390ConditionCode<int64_t>(alu_out, mem_val);
+  set_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(CLG) {
+  DCHECK_OPCODE(CLG);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t alu_out = get_register(r1);
+  int64_t mem_val = ReadDW(b2_val + x2_val + d2);
+  SetS390ConditionCode<uint64_t>(alu_out, mem_val);
+  set_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(NTSTG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CVDY) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CVDG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STRVG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGF) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CLGF) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LTGF) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(PFD) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STRV) {
+  DCHECK_OPCODE(STRV);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t mem_addr = b2_val + x2_val + d2;
+  WriteW(mem_addr, ByteReverse(r1_val), instr);
+  return length;
+}
+
+EVALUATE(STRVH) {
+  DCHECK_OPCODE(STRVH);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t mem_addr = b2_val + x2_val + d2;
+  int16_t result = static_cast<int16_t>(r1_val >> 16);
+  WriteH(mem_addr, ByteReverse(result), instr);
+  return length;
+}
+
+EVALUATE(BCTG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MSY) {
+  DCHECK_OPCODE(MSY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t d2_val = d2;
+  int32_t mem_val = ReadW(b2_val + d2_val + x2_val, instr);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  set_low_register(r1, mem_val * r1_val);
+  return length;
+}
+
+EVALUATE(NY) {
+  DCHECK_OPCODE(NY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int32_t alu_out = get_low_register<int32_t>(r1);
+  int32_t mem_val = ReadW(b2_val + x2_val + d2, instr);
+  alu_out &= mem_val;
+  SetS390BitWiseConditionCode<uint32_t>(alu_out);
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(CLY) {
+  DCHECK_OPCODE(CLY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  uint32_t alu_out = get_low_register<uint32_t>(r1);
+  uint32_t mem_val = ReadWU(b2_val + x2_val + d2, instr);
+  SetS390ConditionCode<uint32_t>(alu_out, mem_val);
+  return length;
+}
+
+EVALUATE(OY) {
+  DCHECK_OPCODE(OY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int32_t alu_out = get_low_register<int32_t>(r1);
+  int32_t mem_val = ReadW(b2_val + x2_val + d2, instr);
+  alu_out |= mem_val;
+  SetS390BitWiseConditionCode<uint32_t>(alu_out);
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(XY) {
+  DCHECK_OPCODE(XY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int32_t alu_out = get_low_register<int32_t>(r1);
+  int32_t mem_val = ReadW(b2_val + x2_val + d2, instr);
+  alu_out ^= mem_val;
+  SetS390BitWiseConditionCode<uint32_t>(alu_out);
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(CY) {
+  DCHECK_OPCODE(CY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int32_t alu_out = get_low_register<int32_t>(r1);
+  int32_t mem_val = ReadW(b2_val + x2_val + d2, instr);
+  SetS390ConditionCode<int32_t>(alu_out, mem_val);
+  return length;
+}
+
+EVALUATE(AY) {
+  DCHECK_OPCODE(AY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int32_t alu_out = get_low_register<int32_t>(r1);
+  int32_t mem_val = ReadW(b2_val + x2_val + d2, instr);
+  bool isOF = false;
+  isOF = CheckOverflowForIntAdd(alu_out, mem_val, int32_t);
+  alu_out += mem_val;
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(SY) {
+  DCHECK_OPCODE(SY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int32_t alu_out = get_low_register<int32_t>(r1);
+  int32_t mem_val = ReadW(b2_val + x2_val + d2, instr);
+  bool isOF = false;
+  isOF = CheckOverflowForIntSub(alu_out, mem_val, int32_t);
+  alu_out -= mem_val;
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(MFY) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ALY) {
+  DCHECK_OPCODE(ALY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  uint32_t alu_out = get_low_register<uint32_t>(r1);
+  uint32_t mem_val = ReadWU(b2_val + x2_val + d2, instr);
+  alu_out += mem_val;
+  set_low_register(r1, alu_out);
+  SetS390ConditionCode<uint32_t>(alu_out, 0);
+  return length;
+}
+
+EVALUATE(SLY) {
+  DCHECK_OPCODE(SLY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  uint32_t alu_out = get_low_register<uint32_t>(r1);
+  uint32_t mem_val = ReadWU(b2_val + x2_val + d2, instr);
+  alu_out -= mem_val;
+  set_low_register(r1, alu_out);
+  SetS390ConditionCode<uint32_t>(alu_out, 0);
+  return length;
+}
+
+EVALUATE(STHY) {
+  DCHECK_OPCODE(STHY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  // Miscellaneous Loads and Stores
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t addr = x2_val + b2_val + d2;
+  uint16_t value = get_low_register<uint32_t>(r1);
+  WriteH(addr, value, instr);
+  return length;
+}
+
+EVALUATE(LAY) {
+  DCHECK_OPCODE(LAY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  // Load Address
+  int rb = b2;
+  int rx = x2;
+  int offset = d2;
+  int64_t rb_val = (rb == 0) ? 0 : get_register(rb);
+  int64_t rx_val = (rx == 0) ? 0 : get_register(rx);
+  set_register(r1, rx_val + rb_val + offset);
+  return length;
+}
+
+EVALUATE(STCY) {
+  DCHECK_OPCODE(STCY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  // Miscellaneous Loads and Stores
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t addr = x2_val + b2_val + d2;
+  uint8_t value = get_low_register<uint32_t>(r1);
+  WriteB(addr, value);
+  return length;
+}
+
+EVALUATE(ICY) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LAEY) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LB) {
+  DCHECK_OPCODE(LB);
+  // Miscellaneous Loads and Stores
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t addr = x2_val + b2_val + d2;
+  int32_t mem_val = ReadB(addr);
+  set_low_register(r1, mem_val);
+  return length;
+}
+
+EVALUATE(LGB) {
+  DCHECK_OPCODE(LGB);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  // Miscellaneous Loads and Stores
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t addr = x2_val + b2_val + d2;
+  int64_t mem_val = ReadB(addr);
+  set_register(r1, mem_val);
+  return length;
+}
+
+EVALUATE(LHY) {
+  DCHECK_OPCODE(LHY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  // Miscellaneous Loads and Stores
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t addr = x2_val + b2_val + d2;
+  int32_t result = static_cast<int32_t>(ReadH(addr, instr));
+  set_low_register(r1, result);
+  return length;
+}
+
+EVALUATE(CHY) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(AHY) {
+  DCHECK_OPCODE(AHY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t d2_val = d2;
+  int32_t mem_val =
+      static_cast<int32_t>(ReadH(b2_val + d2_val + x2_val, instr));
+  int32_t alu_out = 0;
+  bool isOF = false;
+  alu_out = r1_val + mem_val;
+  isOF = CheckOverflowForIntAdd(r1_val, mem_val, int32_t);
+  set_low_register(r1, alu_out);
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(SHY) {
+  DCHECK_OPCODE(SHY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int32_t r1_val = get_low_register<int32_t>(r1);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t d2_val = d2;
+  int32_t mem_val =
+      static_cast<int32_t>(ReadH(b2_val + d2_val + x2_val, instr));
+  int32_t alu_out = 0;
+  bool isOF = false;
+  alu_out = r1_val - mem_val;
+  isOF = CheckOverflowForIntSub(r1_val, mem_val, int64_t);
+  set_low_register(r1, alu_out);
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(MHY) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(NG) {
+  DCHECK_OPCODE(NG);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t alu_out = get_register(r1);
+  int64_t mem_val = ReadDW(b2_val + x2_val + d2);
+  alu_out &= mem_val;
+  SetS390BitWiseConditionCode<uint32_t>(alu_out);
+  set_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(OG) {
+  DCHECK_OPCODE(OG);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t alu_out = get_register(r1);
+  int64_t mem_val = ReadDW(b2_val + x2_val + d2);
+  alu_out |= mem_val;
+  SetS390BitWiseConditionCode<uint32_t>(alu_out);
+  set_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(XG) {
+  DCHECK_OPCODE(XG);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t alu_out = get_register(r1);
+  int64_t mem_val = ReadDW(b2_val + x2_val + d2);
+  alu_out ^= mem_val;
+  SetS390BitWiseConditionCode<uint32_t>(alu_out);
+  set_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(LGAT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MLG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(DLG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ALCG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SLBG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STPQ) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LPQ) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LLGH) {
+  DCHECK_OPCODE(LLGH);
+  // Load Logical Halfword
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t d2_val = d2;
+  uint16_t mem_val = ReadHU(b2_val + d2_val + x2_val, instr);
+  set_register(r1, mem_val);
+  return length;
+}
+
+EVALUATE(LLH) {
+  DCHECK_OPCODE(LLH);
+  // Load Logical Halfword
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t d2_val = d2;
+  uint16_t mem_val = ReadHU(b2_val + d2_val + x2_val, instr);
+  set_low_register(r1, mem_val);
+  return length;
+}
+
+EVALUATE(ML) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(DL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ALC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SLB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LLGTAT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LLGFAT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LAT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LBH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LLCH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STCH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LHH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LLHH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STHH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LFHAT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LFH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STFH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CHF) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MVCDK) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MVHHI) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MVGHI) {
+  DCHECK_OPCODE(MVGHI);
+  // Move Integer (64)
+  DECODE_SIL_INSTRUCTION(b1, d1, i2);
+  int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
+  intptr_t src_addr = b1_val + d1;
+  WriteDW(src_addr, i2);
+  return length;
+}
+
+EVALUATE(MVHI) {
+  DCHECK_OPCODE(MVHI);
+  // Move Integer (32)
+  DECODE_SIL_INSTRUCTION(b1, d1, i2);
+  int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
+  intptr_t src_addr = b1_val + d1;
+  WriteW(src_addr, i2, instr);
+  return length;
+}
+
+EVALUATE(CHHSI) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGHSI) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CHSI) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CLFHSI) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TBEGIN) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TBEGINC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LMG) {
+  DCHECK_OPCODE(LMG);
+  // Store Multiple 64-bits.
+  DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
+  int rb = b2;
+  int offset = d2;
+
+  // Regs roll around if r3 is less than r1.
+  // Artifically increase r3 by 16 so we can calculate
+  // the number of regs stored properly.
+  if (r3 < r1) r3 += 16;
+
+  int64_t rb_val = (rb == 0) ? 0 : get_register(rb);
+
+  // Store each register in ascending order.
+  for (int i = 0; i <= r3 - r1; i++) {
+    int64_t value = ReadDW(rb_val + offset + 8 * i);
+    set_register((r1 + i) % 16, value);
+  }
+  return length;
+}
+
+EVALUATE(SRAG) {
+  DCHECK_OPCODE(SRAG);
+  // 64-bit non-clobbering shift-left/right arithmetic
+  DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
+  // only takes rightmost 6 bits
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int shiftBits = (b2_val + d2) & 0x3F;
+  int64_t r3_val = get_register(r3);
+  intptr_t alu_out = 0;
+  bool isOF = false;
+  alu_out = r3_val >> shiftBits;
+  set_register(r1, alu_out);
+  SetS390ConditionCode<intptr_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(SLAG) {
+  DCHECK_OPCODE(SLAG);
+  // 64-bit non-clobbering shift-left/right arithmetic
+  DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
+  // only takes rightmost 6 bits
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int shiftBits = (b2_val + d2) & 0x3F;
+  int64_t r3_val = get_register(r3);
+  intptr_t alu_out = 0;
+  bool isOF = false;
+  isOF = CheckOverflowForShiftLeft(r3_val, shiftBits);
+  alu_out = r3_val << shiftBits;
+  set_register(r1, alu_out);
+  SetS390ConditionCode<intptr_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(SRLG) {
+  DCHECK_OPCODE(SRLG);
+  // For SLLG/SRLG, the 64-bit third operand is shifted the number
+  // of bits specified by the second-operand address, and the result is
+  // placed at the first-operand location. Except for when the R1 and R3
+  // fields designate the same register, the third operand remains
+  // unchanged in general register R3.
+  DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
+  // only takes rightmost 6 bits
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int shiftBits = (b2_val + d2) & 0x3F;
+  // unsigned
+  uint64_t r3_val = get_register(r3);
+  uint64_t alu_out = 0;
+  alu_out = r3_val >> shiftBits;
+  set_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(SLLG) {
+  DCHECK_OPCODE(SLLG);
+  // For SLLG/SRLG, the 64-bit third operand is shifted the number
+  // of bits specified by the second-operand address, and the result is
+  // placed at the first-operand location. Except for when the R1 and R3
+  // fields designate the same register, the third operand remains
+  // unchanged in general register R3.
+  DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
+  // only takes rightmost 6 bits
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int shiftBits = (b2_val + d2) & 0x3F;
+  // unsigned
+  uint64_t r3_val = get_register(r3);
+  uint64_t alu_out = 0;
+  alu_out = r3_val << shiftBits;
+  set_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(CSY) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(RLLG) {
+  DCHECK_OPCODE(RLLG);
+  // For SLLG/SRLG, the 64-bit third operand is shifted the number
+  // of bits specified by the second-operand address, and the result is
+  // placed at the first-operand location. Except for when the R1 and R3
+  // fields designate the same register, the third operand remains
+  // unchanged in general register R3.
+  DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
+  // only takes rightmost 6 bits
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int shiftBits = (b2_val + d2) & 0x3F;
+  // unsigned
+  uint64_t r3_val = get_register(r3);
+  uint64_t alu_out = 0;
+  uint64_t rotateBits = r3_val >> (64 - shiftBits);
+  alu_out = (r3_val << shiftBits) | (rotateBits);
+  set_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(STMG) {
+  DCHECK_OPCODE(STMG);
+  DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
+  int rb = b2;
+  int offset = d2;
+
+  // Regs roll around if r3 is less than r1.
+  // Artifically increase r3 by 16 so we can calculate
+  // the number of regs stored properly.
+  if (r3 < r1) r3 += 16;
+
+  int64_t rb_val = (rb == 0) ? 0 : get_register(rb);
+
+  // Store each register in ascending order.
+  for (int i = 0; i <= r3 - r1; i++) {
+    int64_t value = get_register((r1 + i) % 16);
+    WriteDW(rb_val + offset + 8 * i, value);
+  }
+  return length;
+}
+
+EVALUATE(STMH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STCMH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STCMY) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CDSY) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CDSG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BXHG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BXLEG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ECAG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TMY) {
+  DCHECK_OPCODE(TMY);
+  // Test Under Mask (Mem - Imm) (8)
+  DECODE_SIY_INSTRUCTION(b1, d1, i2);
+  int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
+  intptr_t d1_val = d1;
+  intptr_t addr = b1_val + d1_val;
+  uint8_t mem_val = ReadB(addr);
+  uint8_t imm_val = i2;
+  uint8_t selected_bits = mem_val & imm_val;
+  // CC0: Selected bits are zero
+  // CC1: Selected bits mixed zeros and ones
+  // CC3: Selected bits all ones
+  if (0 == selected_bits) {
+    condition_reg_ = CC_EQ;  // CC0
+  } else if (selected_bits == imm_val) {
+    condition_reg_ = 0x1;  // CC3
+  } else {
+    condition_reg_ = 0x4;  // CC1
+  }
+  return length;
+}
+
+EVALUATE(MVIY) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(NIY) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CLIY) {
+  DCHECK_OPCODE(CLIY);
+  DECODE_SIY_INSTRUCTION(b1, d1, i2);
+  // Compare Immediate (Mem - Imm) (8)
+  int64_t b1_val = (b1 == 0) ? 0 : get_register(b1);
+  intptr_t d1_val = d1;
+  intptr_t addr = b1_val + d1_val;
+  uint8_t mem_val = ReadB(addr);
+  uint8_t imm_val = i2;
+  SetS390ConditionCode<uint8_t>(mem_val, imm_val);
+  return length;
+}
+
+EVALUATE(OIY) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(XIY) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ASI) {
+  DCHECK_OPCODE(ASI);
+  // TODO(bcleung): Change all fooInstr->I2Value() to template functions.
+  // The below static cast to 8 bit and then to 32 bit is necessary
+  // because siyInstr->I2Value() returns a uint8_t, which a direct
+  // cast to int32_t could incorrectly interpret.
+  DECODE_SIY_INSTRUCTION(b1, d1, i2_unsigned);
+  int8_t i2_8bit = static_cast<int8_t>(i2_unsigned);
+  int32_t i2 = static_cast<int32_t>(i2_8bit);
+  intptr_t b1_val = (b1 == 0) ? 0 : get_register(b1);
+
+  int d1_val = d1;
+  intptr_t addr = b1_val + d1_val;
+
+  int32_t mem_val = ReadW(addr, instr);
+  bool isOF = CheckOverflowForIntAdd(mem_val, i2, int32_t);
+  int32_t alu_out = mem_val + i2;
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+  WriteW(addr, alu_out, instr);
+  return length;
+}
+
+EVALUATE(ALSI) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(AGSI) {
+  DCHECK_OPCODE(AGSI);
+  // TODO(bcleung): Change all fooInstr->I2Value() to template functions.
+  // The below static cast to 8 bit and then to 32 bit is necessary
+  // because siyInstr->I2Value() returns a uint8_t, which a direct
+  // cast to int32_t could incorrectly interpret.
+  DECODE_SIY_INSTRUCTION(b1, d1, i2_unsigned);
+  int8_t i2_8bit = static_cast<int8_t>(i2_unsigned);
+  int64_t i2 = static_cast<int64_t>(i2_8bit);
+  intptr_t b1_val = (b1 == 0) ? 0 : get_register(b1);
+
+  int d1_val = d1;
+  intptr_t addr = b1_val + d1_val;
+
+  int64_t mem_val = ReadDW(addr);
+  int isOF = CheckOverflowForIntAdd(mem_val, i2, int64_t);
+  int64_t alu_out = mem_val + i2;
+  SetS390ConditionCode<uint64_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+  WriteDW(addr, alu_out);
+  return length;
+}
+
+EVALUATE(ALGSI) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ICMH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ICMY) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MVCLU) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CLCLU) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STMY) {
+  DCHECK_OPCODE(STMY);
+  DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
+  // Load/Store Multiple (32)
+  int offset = d2;
+
+  // Regs roll around if r3 is less than r1.
+  // Artifically increase r3 by 16 so we can calculate
+  // the number of regs stored properly.
+  if (r3 < r1) r3 += 16;
+
+  int32_t b2_val = (b2 == 0) ? 0 : get_low_register<int32_t>(b2);
+
+  // Store each register in ascending order.
+  for (int i = 0; i <= r3 - r1; i++) {
+    int32_t value = get_low_register<int32_t>((r1 + i) % 16);
+    WriteW(b2_val + offset + 4 * i, value, instr);
+  }
+  return length;
+}
+
+EVALUATE(LMH) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LMY) {
+  DCHECK_OPCODE(LMY);
+  DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
+  // Load/Store Multiple (32)
+  int offset = d2;
+
+  // Regs roll around if r3 is less than r1.
+  // Artifically increase r3 by 16 so we can calculate
+  // the number of regs stored properly.
+  if (r3 < r1) r3 += 16;
+
+  int32_t b2_val = (b2 == 0) ? 0 : get_low_register<int32_t>(b2);
+
+  // Store each register in ascending order.
+  for (int i = 0; i <= r3 - r1; i++) {
+    int32_t value = ReadW(b2_val + offset + 4 * i, instr);
+    set_low_register((r1 + i) % 16, value);
+  }
+  return length;
+}
+
+EVALUATE(TP) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SRAK) {
+  DCHECK_OPCODE(SRAK);
+  DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
+  // 32-bit non-clobbering shift-left/right arithmetic
+  // only takes rightmost 6 bits
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int shiftBits = (b2_val + d2) & 0x3F;
+  int32_t r3_val = get_low_register<int32_t>(r3);
+  int32_t alu_out = 0;
+  bool isOF = false;
+  alu_out = r3_val >> shiftBits;
+  set_low_register(r1, alu_out);
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(SLAK) {
+  DCHECK_OPCODE(SLAK);
+  DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
+  // 32-bit non-clobbering shift-left/right arithmetic
+  // only takes rightmost 6 bits
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int shiftBits = (b2_val + d2) & 0x3F;
+  int32_t r3_val = get_low_register<int32_t>(r3);
+  int32_t alu_out = 0;
+  bool isOF = false;
+  isOF = CheckOverflowForShiftLeft(r3_val, shiftBits);
+  alu_out = r3_val << shiftBits;
+  set_low_register(r1, alu_out);
+  SetS390ConditionCode<int32_t>(alu_out, 0);
+  SetS390OverflowCode(isOF);
+  return length;
+}
+
+EVALUATE(SRLK) {
+  DCHECK_OPCODE(SRLK);
+  // For SLLK/SRLL, the 32-bit third operand is shifted the number
+  // of bits specified by the second-operand address, and the result is
+  // placed at the first-operand location. Except for when the R1 and R3
+  // fields designate the same register, the third operand remains
+  // unchanged in general register R3.
+  DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
+  // only takes rightmost 6 bits
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int shiftBits = (b2_val + d2) & 0x3F;
+  // unsigned
+  uint32_t r3_val = get_low_register<uint32_t>(r3);
+  uint32_t alu_out = 0;
+  alu_out = r3_val >> shiftBits;
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(SLLK) {
+  DCHECK_OPCODE(SLLK);
+  // For SLLK/SRLL, the 32-bit third operand is shifted the number
+  // of bits specified by the second-operand address, and the result is
+  // placed at the first-operand location. Except for when the R1 and R3
+  // fields designate the same register, the third operand remains
+  // unchanged in general register R3.
+  DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2);
+  // only takes rightmost 6 bits
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int shiftBits = (b2_val + d2) & 0x3F;
+  // unsigned
+  uint32_t r3_val = get_low_register<uint32_t>(r3);
+  uint32_t alu_out = 0;
+  alu_out = r3_val << shiftBits;
+  set_low_register(r1, alu_out);
+  return length;
+}
+
+EVALUATE(LOCG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STOCG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LANG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LAOG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LAXG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LAAG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LAALG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LOC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(STOC) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LAN) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LAO) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LAX) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LAA) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LAAL) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BRXHG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(BRXLG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(RISBLG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(RNSBG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ROSBG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(RXSBG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(RISBGN) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(RISBHG) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGRJ) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGIT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CIT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CLFIT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGIJ) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CIJ) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ALHSIK) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(ALGHSIK) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGRB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CGIB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CIB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LDEB) {
+  DCHECK_OPCODE(LDEB);
+  // Load Float
+  DECODE_RXE_INSTRUCTION(r1, b2, x2, d2);
+  int rb = b2;
+  int rx = x2;
+  int offset = d2;
+  int64_t rb_val = (rb == 0) ? 0 : get_register(rb);
+  int64_t rx_val = (rx == 0) ? 0 : get_register(rx);
+  double ret =
+      static_cast<double>(*reinterpret_cast<float*>(rx_val + rb_val + offset));
+  set_d_register_from_double(r1, ret);
+  return length;
+}
+
+EVALUATE(LXDB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LXEB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MXDB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(KEB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CEB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(AEB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SEB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MDEB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(DEB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MAEB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MSEB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TCEB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TCDB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TCXB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SQEB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SQDB) {
+  DCHECK_OPCODE(SQDB);
+  DECODE_RXE_INSTRUCTION(r1, b2, x2, d2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t d2_val = d2;
+  double r1_val = get_double_from_d_register(r1);
+  double dbl_val = ReadDouble(b2_val + x2_val + d2_val);
+  r1_val = std::sqrt(dbl_val);
+  set_d_register_from_double(r1, r1_val);
+  return length;
+}
+
+EVALUATE(MEEB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(KDB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CDB) {
+  DCHECK_OPCODE(CDB);
+
+  DECODE_RXE_INSTRUCTION(r1, b2, x2, d2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t d2_val = d2;
+  double r1_val = get_double_from_d_register(r1);
+  double dbl_val = ReadDouble(b2_val + x2_val + d2_val);
+  SetS390ConditionCode<double>(r1_val, dbl_val);
+  return length;
+}
+
+EVALUATE(ADB) {
+  DCHECK_OPCODE(ADB);
+
+  DECODE_RXE_INSTRUCTION(r1, b2, x2, d2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t d2_val = d2;
+  double r1_val = get_double_from_d_register(r1);
+  double dbl_val = ReadDouble(b2_val + x2_val + d2_val);
+  r1_val += dbl_val;
+  set_d_register_from_double(r1, r1_val);
+  SetS390ConditionCode<double>(r1_val, 0);
+  return length;
+}
+
+EVALUATE(SDB) {
+  DCHECK_OPCODE(SDB);
+  DECODE_RXE_INSTRUCTION(r1, b2, x2, d2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t d2_val = d2;
+  double r1_val = get_double_from_d_register(r1);
+  double dbl_val = ReadDouble(b2_val + x2_val + d2_val);
+  r1_val -= dbl_val;
+  set_d_register_from_double(r1, r1_val);
+  SetS390ConditionCode<double>(r1_val, 0);
+  return length;
+}
+
+EVALUATE(MDB) {
+  DCHECK_OPCODE(MDB);
+  DECODE_RXE_INSTRUCTION(r1, b2, x2, d2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t d2_val = d2;
+  double r1_val = get_double_from_d_register(r1);
+  double dbl_val = ReadDouble(b2_val + x2_val + d2_val);
+  r1_val *= dbl_val;
+  set_d_register_from_double(r1, r1_val);
+  SetS390ConditionCode<double>(r1_val, 0);
+  return length;
+}
+
+EVALUATE(DDB) {
+  DCHECK_OPCODE(DDB);
+  DECODE_RXE_INSTRUCTION(r1, b2, x2, d2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  intptr_t d2_val = d2;
+  double r1_val = get_double_from_d_register(r1);
+  double dbl_val = ReadDouble(b2_val + x2_val + d2_val);
+  r1_val /= dbl_val;
+  set_d_register_from_double(r1, r1_val);
+  SetS390ConditionCode<double>(r1_val, 0);
+  return length;
+}
+
+EVALUATE(MADB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(MSDB) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SLDT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SRDT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SLXT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(SRXT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TDCET) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TDGET) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TDCDT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TDGDT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TDCXT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(TDGXT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(LEY) {
+  DCHECK_OPCODE(LEY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  // Miscellaneous Loads and Stores
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t addr = x2_val + b2_val + d2;
+  float float_val = *reinterpret_cast<float*>(addr);
+  set_d_register_from_float32(r1, float_val);
+  return length;
+}
+
+EVALUATE(LDY) {
+  DCHECK_OPCODE(LDY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  // Miscellaneous Loads and Stores
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t addr = x2_val + b2_val + d2;
+  uint64_t dbl_val = *reinterpret_cast<uint64_t*>(addr);
+  set_d_register(r1, dbl_val);
+  return length;
+}
+
+EVALUATE(STEY) {
+  DCHECK_OPCODE(STEY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  // Miscellaneous Loads and Stores
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t addr = x2_val + b2_val + d2;
+  int64_t frs_val = get_d_register(r1) >> 32;
+  WriteW(addr, static_cast<int32_t>(frs_val), instr);
+  return length;
+}
+
+EVALUATE(STDY) {
+  DCHECK_OPCODE(STDY);
+  DECODE_RXY_A_INSTRUCTION(r1, x2, b2, d2);
+  // Miscellaneous Loads and Stores
+  int64_t x2_val = (x2 == 0) ? 0 : get_register(x2);
+  int64_t b2_val = (b2 == 0) ? 0 : get_register(b2);
+  intptr_t addr = x2_val + b2_val + d2;
+  int64_t frs_val = get_d_register(r1);
+  WriteDW(addr, frs_val);
+  return length;
+}
+
+EVALUATE(CZDT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CZXT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CDZT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+EVALUATE(CXZT) {
+  UNIMPLEMENTED();
+  USE(instr);
+  return 0;
+}
+
+#undef EVALUATE
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/s390/simulator-s390.h b/src/s390/simulator-s390.h
index ae3dd58..b9ee25d 100644
--- a/src/s390/simulator-s390.h
+++ b/src/s390/simulator-s390.h
@@ -64,7 +64,7 @@
 // Running with a simulator.
 
 #include "src/assembler.h"
-#include "src/hashmap.h"
+#include "src/base/hashmap.h"
 #include "src/s390/constants-s390.h"
 
 namespace v8 {
@@ -211,7 +211,7 @@
   // Call on program start.
   static void Initialize(Isolate* isolate);
 
-  static void TearDown(HashMap* i_cache, Redirection* first);
+  static void TearDown(base::HashMap* i_cache, Redirection* first);
 
   // V8 generally calls into generated JS code with 5 parameters and into
   // generated RegExp code with 7 parameters. This is a convenience function,
@@ -233,8 +233,7 @@
   char* last_debugger_input() { return last_debugger_input_; }
 
   // ICache checking.
-  static void FlushICache(v8::internal::HashMap* i_cache, void* start,
-                          size_t size);
+  static void FlushICache(base::HashMap* i_cache, void* start, size_t size);
 
   // Returns true if pc register contains one of the 'special_values' defined
   // below (bad_lr, end_sim_pc).
@@ -444,10 +443,9 @@
   void ExecuteInstruction(Instruction* instr, bool auto_incr_pc = true);
 
   // ICache.
-  static void CheckICache(v8::internal::HashMap* i_cache, Instruction* instr);
-  static void FlushOnePage(v8::internal::HashMap* i_cache, intptr_t start,
-                           int size);
-  static CachePage* GetCachePage(v8::internal::HashMap* i_cache, void* page);
+  static void CheckICache(base::HashMap* i_cache, Instruction* instr);
+  static void FlushOnePage(base::HashMap* i_cache, intptr_t start, int size);
+  static CachePage* GetCachePage(base::HashMap* i_cache, void* page);
 
   // Runtime call support.
   static void* RedirectExternalReference(
@@ -482,7 +480,7 @@
   char* last_debugger_input_;
 
   // Icache simulation
-  v8::internal::HashMap* i_cache_;
+  base::HashMap* i_cache_;
 
   // Registered breakpoints.
   Instruction* break_pc_;
@@ -507,6 +505,742 @@
   };
   StopCountAndDesc watched_stops_[kNumOfWatchedStops];
   void DebugStart();
+
+  int DecodeInstructionOriginal(Instruction* instr);
+  int DecodeInstruction(Instruction* instr);
+  int Evaluate_Unknown(Instruction* instr);
+#define MAX_NUM_OPCODES (1 << 16)
+  typedef int (Simulator::*EvaluateFuncType)(Instruction*);
+
+  static EvaluateFuncType EvalTable[MAX_NUM_OPCODES];
+  static void EvalTableInit();
+
+#define EVALUATE(name) int Evaluate_##name(Instruction* instr)
+  EVALUATE(BKPT);
+  EVALUATE(SPM);
+  EVALUATE(BALR);
+  EVALUATE(BCTR);
+  EVALUATE(BCR);
+  EVALUATE(SVC);
+  EVALUATE(BSM);
+  EVALUATE(BASSM);
+  EVALUATE(BASR);
+  EVALUATE(MVCL);
+  EVALUATE(CLCL);
+  EVALUATE(LPR);
+  EVALUATE(LNR);
+  EVALUATE(LTR);
+  EVALUATE(LCR);
+  EVALUATE(NR);
+  EVALUATE(CLR);
+  EVALUATE(OR);
+  EVALUATE(XR);
+  EVALUATE(LR);
+  EVALUATE(CR);
+  EVALUATE(AR);
+  EVALUATE(SR);
+  EVALUATE(MR);
+  EVALUATE(DR);
+  EVALUATE(ALR);
+  EVALUATE(SLR);
+  EVALUATE(LDR);
+  EVALUATE(CDR);
+  EVALUATE(LER);
+  EVALUATE(STH);
+  EVALUATE(LA);
+  EVALUATE(STC);
+  EVALUATE(IC_z);
+  EVALUATE(EX);
+  EVALUATE(BAL);
+  EVALUATE(BCT);
+  EVALUATE(BC);
+  EVALUATE(LH);
+  EVALUATE(CH);
+  EVALUATE(AH);
+  EVALUATE(SH);
+  EVALUATE(MH);
+  EVALUATE(BAS);
+  EVALUATE(CVD);
+  EVALUATE(CVB);
+  EVALUATE(ST);
+  EVALUATE(LAE);
+  EVALUATE(N);
+  EVALUATE(CL);
+  EVALUATE(O);
+  EVALUATE(X);
+  EVALUATE(L);
+  EVALUATE(C);
+  EVALUATE(A);
+  EVALUATE(S);
+  EVALUATE(M);
+  EVALUATE(D);
+  EVALUATE(AL);
+  EVALUATE(SL);
+  EVALUATE(STD);
+  EVALUATE(LD);
+  EVALUATE(CD);
+  EVALUATE(STE);
+  EVALUATE(MS);
+  EVALUATE(LE);
+  EVALUATE(BRXH);
+  EVALUATE(BRXLE);
+  EVALUATE(BXH);
+  EVALUATE(BXLE);
+  EVALUATE(SRL);
+  EVALUATE(SLL);
+  EVALUATE(SRA);
+  EVALUATE(SLA);
+  EVALUATE(SRDL);
+  EVALUATE(SLDL);
+  EVALUATE(SRDA);
+  EVALUATE(SLDA);
+  EVALUATE(STM);
+  EVALUATE(TM);
+  EVALUATE(MVI);
+  EVALUATE(TS);
+  EVALUATE(NI);
+  EVALUATE(CLI);
+  EVALUATE(OI);
+  EVALUATE(XI);
+  EVALUATE(LM);
+  EVALUATE(MVCLE);
+  EVALUATE(CLCLE);
+  EVALUATE(MC);
+  EVALUATE(CDS);
+  EVALUATE(STCM);
+  EVALUATE(ICM);
+  EVALUATE(BPRP);
+  EVALUATE(BPP);
+  EVALUATE(TRTR);
+  EVALUATE(MVN);
+  EVALUATE(MVC);
+  EVALUATE(MVZ);
+  EVALUATE(NC);
+  EVALUATE(CLC);
+  EVALUATE(OC);
+  EVALUATE(XC);
+  EVALUATE(MVCP);
+  EVALUATE(TR);
+  EVALUATE(TRT);
+  EVALUATE(ED);
+  EVALUATE(EDMK);
+  EVALUATE(PKU);
+  EVALUATE(UNPKU);
+  EVALUATE(MVCIN);
+  EVALUATE(PKA);
+  EVALUATE(UNPKA);
+  EVALUATE(PLO);
+  EVALUATE(LMD);
+  EVALUATE(SRP);
+  EVALUATE(MVO);
+  EVALUATE(PACK);
+  EVALUATE(UNPK);
+  EVALUATE(ZAP);
+  EVALUATE(AP);
+  EVALUATE(SP);
+  EVALUATE(MP);
+  EVALUATE(DP);
+  EVALUATE(UPT);
+  EVALUATE(PFPO);
+  EVALUATE(IIHH);
+  EVALUATE(IIHL);
+  EVALUATE(IILH);
+  EVALUATE(IILL);
+  EVALUATE(NIHH);
+  EVALUATE(NIHL);
+  EVALUATE(NILH);
+  EVALUATE(NILL);
+  EVALUATE(OIHH);
+  EVALUATE(OIHL);
+  EVALUATE(OILH);
+  EVALUATE(OILL);
+  EVALUATE(LLIHH);
+  EVALUATE(LLIHL);
+  EVALUATE(LLILH);
+  EVALUATE(LLILL);
+  EVALUATE(TMLH);
+  EVALUATE(TMLL);
+  EVALUATE(TMHH);
+  EVALUATE(TMHL);
+  EVALUATE(BRC);
+  EVALUATE(BRAS);
+  EVALUATE(BRCT);
+  EVALUATE(BRCTG);
+  EVALUATE(LHI);
+  EVALUATE(LGHI);
+  EVALUATE(AHI);
+  EVALUATE(AGHI);
+  EVALUATE(MHI);
+  EVALUATE(MGHI);
+  EVALUATE(CHI);
+  EVALUATE(CGHI);
+  EVALUATE(LARL);
+  EVALUATE(LGFI);
+  EVALUATE(BRCL);
+  EVALUATE(BRASL);
+  EVALUATE(XIHF);
+  EVALUATE(XILF);
+  EVALUATE(IIHF);
+  EVALUATE(IILF);
+  EVALUATE(NIHF);
+  EVALUATE(NILF);
+  EVALUATE(OIHF);
+  EVALUATE(OILF);
+  EVALUATE(LLIHF);
+  EVALUATE(LLILF);
+  EVALUATE(MSGFI);
+  EVALUATE(MSFI);
+  EVALUATE(SLGFI);
+  EVALUATE(SLFI);
+  EVALUATE(AGFI);
+  EVALUATE(AFI);
+  EVALUATE(ALGFI);
+  EVALUATE(ALFI);
+  EVALUATE(CGFI);
+  EVALUATE(CFI);
+  EVALUATE(CLGFI);
+  EVALUATE(CLFI);
+  EVALUATE(LLHRL);
+  EVALUATE(LGHRL);
+  EVALUATE(LHRL);
+  EVALUATE(LLGHRL);
+  EVALUATE(STHRL);
+  EVALUATE(LGRL);
+  EVALUATE(STGRL);
+  EVALUATE(LGFRL);
+  EVALUATE(LRL);
+  EVALUATE(LLGFRL);
+  EVALUATE(STRL);
+  EVALUATE(EXRL);
+  EVALUATE(PFDRL);
+  EVALUATE(CGHRL);
+  EVALUATE(CHRL);
+  EVALUATE(CGRL);
+  EVALUATE(CGFRL);
+  EVALUATE(ECTG);
+  EVALUATE(CSST);
+  EVALUATE(LPD);
+  EVALUATE(LPDG);
+  EVALUATE(BRCTH);
+  EVALUATE(AIH);
+  EVALUATE(ALSIH);
+  EVALUATE(ALSIHN);
+  EVALUATE(CIH);
+  EVALUATE(STCK);
+  EVALUATE(CFC);
+  EVALUATE(IPM);
+  EVALUATE(HSCH);
+  EVALUATE(MSCH);
+  EVALUATE(SSCH);
+  EVALUATE(STSCH);
+  EVALUATE(TSCH);
+  EVALUATE(TPI);
+  EVALUATE(SAL);
+  EVALUATE(RSCH);
+  EVALUATE(STCRW);
+  EVALUATE(STCPS);
+  EVALUATE(RCHP);
+  EVALUATE(SCHM);
+  EVALUATE(CKSM);
+  EVALUATE(SAR);
+  EVALUATE(EAR);
+  EVALUATE(MSR);
+  EVALUATE(MVST);
+  EVALUATE(CUSE);
+  EVALUATE(SRST);
+  EVALUATE(XSCH);
+  EVALUATE(STCKE);
+  EVALUATE(STCKF);
+  EVALUATE(SRNM);
+  EVALUATE(STFPC);
+  EVALUATE(LFPC);
+  EVALUATE(TRE);
+  EVALUATE(CUUTF);
+  EVALUATE(CUTFU);
+  EVALUATE(STFLE);
+  EVALUATE(SRNMB);
+  EVALUATE(SRNMT);
+  EVALUATE(LFAS);
+  EVALUATE(PPA);
+  EVALUATE(ETND);
+  EVALUATE(TEND);
+  EVALUATE(NIAI);
+  EVALUATE(TABORT);
+  EVALUATE(TRAP4);
+  EVALUATE(LPEBR);
+  EVALUATE(LNEBR);
+  EVALUATE(LTEBR);
+  EVALUATE(LCEBR);
+  EVALUATE(LDEBR);
+  EVALUATE(LXDBR);
+  EVALUATE(LXEBR);
+  EVALUATE(MXDBR);
+  EVALUATE(KEBR);
+  EVALUATE(CEBR);
+  EVALUATE(AEBR);
+  EVALUATE(SEBR);
+  EVALUATE(MDEBR);
+  EVALUATE(DEBR);
+  EVALUATE(MAEBR);
+  EVALUATE(MSEBR);
+  EVALUATE(LPDBR);
+  EVALUATE(LNDBR);
+  EVALUATE(LTDBR);
+  EVALUATE(LCDBR);
+  EVALUATE(SQEBR);
+  EVALUATE(SQDBR);
+  EVALUATE(SQXBR);
+  EVALUATE(MEEBR);
+  EVALUATE(KDBR);
+  EVALUATE(CDBR);
+  EVALUATE(ADBR);
+  EVALUATE(SDBR);
+  EVALUATE(MDBR);
+  EVALUATE(DDBR);
+  EVALUATE(MADBR);
+  EVALUATE(MSDBR);
+  EVALUATE(LPXBR);
+  EVALUATE(LNXBR);
+  EVALUATE(LTXBR);
+  EVALUATE(LCXBR);
+  EVALUATE(LEDBRA);
+  EVALUATE(LDXBRA);
+  EVALUATE(LEXBRA);
+  EVALUATE(FIXBRA);
+  EVALUATE(KXBR);
+  EVALUATE(CXBR);
+  EVALUATE(AXBR);
+  EVALUATE(SXBR);
+  EVALUATE(MXBR);
+  EVALUATE(DXBR);
+  EVALUATE(TBEDR);
+  EVALUATE(TBDR);
+  EVALUATE(DIEBR);
+  EVALUATE(FIEBRA);
+  EVALUATE(THDER);
+  EVALUATE(THDR);
+  EVALUATE(DIDBR);
+  EVALUATE(FIDBRA);
+  EVALUATE(LXR);
+  EVALUATE(LPDFR);
+  EVALUATE(LNDFR);
+  EVALUATE(LCDFR);
+  EVALUATE(LZER);
+  EVALUATE(LZDR);
+  EVALUATE(LZXR);
+  EVALUATE(SFPC);
+  EVALUATE(SFASR);
+  EVALUATE(EFPC);
+  EVALUATE(CELFBR);
+  EVALUATE(CDLFBR);
+  EVALUATE(CXLFBR);
+  EVALUATE(CEFBRA);
+  EVALUATE(CDFBRA);
+  EVALUATE(CXFBRA);
+  EVALUATE(CFEBRA);
+  EVALUATE(CFDBRA);
+  EVALUATE(CFXBRA);
+  EVALUATE(CLFEBR);
+  EVALUATE(CLFDBR);
+  EVALUATE(CLFXBR);
+  EVALUATE(CELGBR);
+  EVALUATE(CDLGBR);
+  EVALUATE(CXLGBR);
+  EVALUATE(CEGBRA);
+  EVALUATE(CDGBRA);
+  EVALUATE(CXGBRA);
+  EVALUATE(CGEBRA);
+  EVALUATE(CGDBRA);
+  EVALUATE(CGXBRA);
+  EVALUATE(CLGEBR);
+  EVALUATE(CLGDBR);
+  EVALUATE(CFER);
+  EVALUATE(CFDR);
+  EVALUATE(CFXR);
+  EVALUATE(LDGR);
+  EVALUATE(CGER);
+  EVALUATE(CGDR);
+  EVALUATE(CGXR);
+  EVALUATE(LGDR);
+  EVALUATE(MDTR);
+  EVALUATE(MDTRA);
+  EVALUATE(DDTRA);
+  EVALUATE(ADTRA);
+  EVALUATE(SDTRA);
+  EVALUATE(LDETR);
+  EVALUATE(LEDTR);
+  EVALUATE(LTDTR);
+  EVALUATE(FIDTR);
+  EVALUATE(MXTRA);
+  EVALUATE(DXTRA);
+  EVALUATE(AXTRA);
+  EVALUATE(SXTRA);
+  EVALUATE(LXDTR);
+  EVALUATE(LDXTR);
+  EVALUATE(LTXTR);
+  EVALUATE(FIXTR);
+  EVALUATE(KDTR);
+  EVALUATE(CGDTRA);
+  EVALUATE(CUDTR);
+  EVALUATE(CDTR);
+  EVALUATE(EEDTR);
+  EVALUATE(ESDTR);
+  EVALUATE(KXTR);
+  EVALUATE(CGXTRA);
+  EVALUATE(CUXTR);
+  EVALUATE(CSXTR);
+  EVALUATE(CXTR);
+  EVALUATE(EEXTR);
+  EVALUATE(ESXTR);
+  EVALUATE(CDGTRA);
+  EVALUATE(CDUTR);
+  EVALUATE(CDSTR);
+  EVALUATE(CEDTR);
+  EVALUATE(QADTR);
+  EVALUATE(IEDTR);
+  EVALUATE(RRDTR);
+  EVALUATE(CXGTRA);
+  EVALUATE(CXUTR);
+  EVALUATE(CXSTR);
+  EVALUATE(CEXTR);
+  EVALUATE(QAXTR);
+  EVALUATE(IEXTR);
+  EVALUATE(RRXTR);
+  EVALUATE(LPGR);
+  EVALUATE(LNGR);
+  EVALUATE(LTGR);
+  EVALUATE(LCGR);
+  EVALUATE(LGR);
+  EVALUATE(LGBR);
+  EVALUATE(LGHR);
+  EVALUATE(AGR);
+  EVALUATE(SGR);
+  EVALUATE(ALGR);
+  EVALUATE(SLGR);
+  EVALUATE(MSGR);
+  EVALUATE(DSGR);
+  EVALUATE(LRVGR);
+  EVALUATE(LPGFR);
+  EVALUATE(LNGFR);
+  EVALUATE(LTGFR);
+  EVALUATE(LCGFR);
+  EVALUATE(LGFR);
+  EVALUATE(LLGFR);
+  EVALUATE(LLGTR);
+  EVALUATE(AGFR);
+  EVALUATE(SGFR);
+  EVALUATE(ALGFR);
+  EVALUATE(SLGFR);
+  EVALUATE(MSGFR);
+  EVALUATE(DSGFR);
+  EVALUATE(KMAC);
+  EVALUATE(LRVR);
+  EVALUATE(CGR);
+  EVALUATE(CLGR);
+  EVALUATE(LBR);
+  EVALUATE(LHR);
+  EVALUATE(KMF);
+  EVALUATE(KMO);
+  EVALUATE(PCC);
+  EVALUATE(KMCTR);
+  EVALUATE(KM);
+  EVALUATE(KMC);
+  EVALUATE(CGFR);
+  EVALUATE(KIMD);
+  EVALUATE(KLMD);
+  EVALUATE(CFDTR);
+  EVALUATE(CLGDTR);
+  EVALUATE(CLFDTR);
+  EVALUATE(BCTGR);
+  EVALUATE(CFXTR);
+  EVALUATE(CLFXTR);
+  EVALUATE(CDFTR);
+  EVALUATE(CDLGTR);
+  EVALUATE(CDLFTR);
+  EVALUATE(CXFTR);
+  EVALUATE(CXLGTR);
+  EVALUATE(CXLFTR);
+  EVALUATE(CGRT);
+  EVALUATE(NGR);
+  EVALUATE(OGR);
+  EVALUATE(XGR);
+  EVALUATE(FLOGR);
+  EVALUATE(LLGCR);
+  EVALUATE(LLGHR);
+  EVALUATE(MLGR);
+  EVALUATE(DLGR);
+  EVALUATE(ALCGR);
+  EVALUATE(SLBGR);
+  EVALUATE(EPSW);
+  EVALUATE(TRTT);
+  EVALUATE(TRTO);
+  EVALUATE(TROT);
+  EVALUATE(TROO);
+  EVALUATE(LLCR);
+  EVALUATE(LLHR);
+  EVALUATE(MLR);
+  EVALUATE(DLR);
+  EVALUATE(ALCR);
+  EVALUATE(SLBR);
+  EVALUATE(CU14);
+  EVALUATE(CU24);
+  EVALUATE(CU41);
+  EVALUATE(CU42);
+  EVALUATE(TRTRE);
+  EVALUATE(SRSTU);
+  EVALUATE(TRTE);
+  EVALUATE(AHHHR);
+  EVALUATE(SHHHR);
+  EVALUATE(ALHHHR);
+  EVALUATE(SLHHHR);
+  EVALUATE(CHHR);
+  EVALUATE(AHHLR);
+  EVALUATE(SHHLR);
+  EVALUATE(ALHHLR);
+  EVALUATE(SLHHLR);
+  EVALUATE(CHLR);
+  EVALUATE(POPCNT_Z);
+  EVALUATE(LOCGR);
+  EVALUATE(NGRK);
+  EVALUATE(OGRK);
+  EVALUATE(XGRK);
+  EVALUATE(AGRK);
+  EVALUATE(SGRK);
+  EVALUATE(ALGRK);
+  EVALUATE(SLGRK);
+  EVALUATE(LOCR);
+  EVALUATE(NRK);
+  EVALUATE(ORK);
+  EVALUATE(XRK);
+  EVALUATE(ARK);
+  EVALUATE(SRK);
+  EVALUATE(ALRK);
+  EVALUATE(SLRK);
+  EVALUATE(LTG);
+  EVALUATE(LG);
+  EVALUATE(CVBY);
+  EVALUATE(AG);
+  EVALUATE(SG);
+  EVALUATE(ALG);
+  EVALUATE(SLG);
+  EVALUATE(MSG);
+  EVALUATE(DSG);
+  EVALUATE(CVBG);
+  EVALUATE(LRVG);
+  EVALUATE(LT);
+  EVALUATE(LGF);
+  EVALUATE(LGH);
+  EVALUATE(LLGF);
+  EVALUATE(LLGT);
+  EVALUATE(AGF);
+  EVALUATE(SGF);
+  EVALUATE(ALGF);
+  EVALUATE(SLGF);
+  EVALUATE(MSGF);
+  EVALUATE(DSGF);
+  EVALUATE(LRV);
+  EVALUATE(LRVH);
+  EVALUATE(CG);
+  EVALUATE(CLG);
+  EVALUATE(STG);
+  EVALUATE(NTSTG);
+  EVALUATE(CVDY);
+  EVALUATE(CVDG);
+  EVALUATE(STRVG);
+  EVALUATE(CGF);
+  EVALUATE(CLGF);
+  EVALUATE(LTGF);
+  EVALUATE(CGH);
+  EVALUATE(PFD);
+  EVALUATE(STRV);
+  EVALUATE(STRVH);
+  EVALUATE(BCTG);
+  EVALUATE(STY);
+  EVALUATE(MSY);
+  EVALUATE(NY);
+  EVALUATE(CLY);
+  EVALUATE(OY);
+  EVALUATE(XY);
+  EVALUATE(LY);
+  EVALUATE(CY);
+  EVALUATE(AY);
+  EVALUATE(SY);
+  EVALUATE(MFY);
+  EVALUATE(ALY);
+  EVALUATE(SLY);
+  EVALUATE(STHY);
+  EVALUATE(LAY);
+  EVALUATE(STCY);
+  EVALUATE(ICY);
+  EVALUATE(LAEY);
+  EVALUATE(LB);
+  EVALUATE(LGB);
+  EVALUATE(LHY);
+  EVALUATE(CHY);
+  EVALUATE(AHY);
+  EVALUATE(SHY);
+  EVALUATE(MHY);
+  EVALUATE(NG);
+  EVALUATE(OG);
+  EVALUATE(XG);
+  EVALUATE(LGAT);
+  EVALUATE(MLG);
+  EVALUATE(DLG);
+  EVALUATE(ALCG);
+  EVALUATE(SLBG);
+  EVALUATE(STPQ);
+  EVALUATE(LPQ);
+  EVALUATE(LLGC);
+  EVALUATE(LLGH);
+  EVALUATE(LLC);
+  EVALUATE(LLH);
+  EVALUATE(ML);
+  EVALUATE(DL);
+  EVALUATE(ALC);
+  EVALUATE(SLB);
+  EVALUATE(LLGTAT);
+  EVALUATE(LLGFAT);
+  EVALUATE(LAT);
+  EVALUATE(LBH);
+  EVALUATE(LLCH);
+  EVALUATE(STCH);
+  EVALUATE(LHH);
+  EVALUATE(LLHH);
+  EVALUATE(STHH);
+  EVALUATE(LFHAT);
+  EVALUATE(LFH);
+  EVALUATE(STFH);
+  EVALUATE(CHF);
+  EVALUATE(MVCDK);
+  EVALUATE(MVHHI);
+  EVALUATE(MVGHI);
+  EVALUATE(MVHI);
+  EVALUATE(CHHSI);
+  EVALUATE(CGHSI);
+  EVALUATE(CHSI);
+  EVALUATE(CLFHSI);
+  EVALUATE(TBEGIN);
+  EVALUATE(TBEGINC);
+  EVALUATE(LMG);
+  EVALUATE(SRAG);
+  EVALUATE(SLAG);
+  EVALUATE(SRLG);
+  EVALUATE(SLLG);
+  EVALUATE(CSY);
+  EVALUATE(RLLG);
+  EVALUATE(RLL);
+  EVALUATE(STMG);
+  EVALUATE(STMH);
+  EVALUATE(STCMH);
+  EVALUATE(STCMY);
+  EVALUATE(CDSY);
+  EVALUATE(CDSG);
+  EVALUATE(BXHG);
+  EVALUATE(BXLEG);
+  EVALUATE(ECAG);
+  EVALUATE(TMY);
+  EVALUATE(MVIY);
+  EVALUATE(NIY);
+  EVALUATE(CLIY);
+  EVALUATE(OIY);
+  EVALUATE(XIY);
+  EVALUATE(ASI);
+  EVALUATE(ALSI);
+  EVALUATE(AGSI);
+  EVALUATE(ALGSI);
+  EVALUATE(ICMH);
+  EVALUATE(ICMY);
+  EVALUATE(MVCLU);
+  EVALUATE(CLCLU);
+  EVALUATE(STMY);
+  EVALUATE(LMH);
+  EVALUATE(LMY);
+  EVALUATE(TP);
+  EVALUATE(SRAK);
+  EVALUATE(SLAK);
+  EVALUATE(SRLK);
+  EVALUATE(SLLK);
+  EVALUATE(LOCG);
+  EVALUATE(STOCG);
+  EVALUATE(LANG);
+  EVALUATE(LAOG);
+  EVALUATE(LAXG);
+  EVALUATE(LAAG);
+  EVALUATE(LAALG);
+  EVALUATE(LOC);
+  EVALUATE(STOC);
+  EVALUATE(LAN);
+  EVALUATE(LAO);
+  EVALUATE(LAX);
+  EVALUATE(LAA);
+  EVALUATE(LAAL);
+  EVALUATE(BRXHG);
+  EVALUATE(BRXLG);
+  EVALUATE(RISBLG);
+  EVALUATE(RNSBG);
+  EVALUATE(RISBG);
+  EVALUATE(ROSBG);
+  EVALUATE(RXSBG);
+  EVALUATE(RISBGN);
+  EVALUATE(RISBHG);
+  EVALUATE(CGRJ);
+  EVALUATE(CGIT);
+  EVALUATE(CIT);
+  EVALUATE(CLFIT);
+  EVALUATE(CGIJ);
+  EVALUATE(CIJ);
+  EVALUATE(AHIK);
+  EVALUATE(AGHIK);
+  EVALUATE(ALHSIK);
+  EVALUATE(ALGHSIK);
+  EVALUATE(CGRB);
+  EVALUATE(CGIB);
+  EVALUATE(CIB);
+  EVALUATE(LDEB);
+  EVALUATE(LXDB);
+  EVALUATE(LXEB);
+  EVALUATE(MXDB);
+  EVALUATE(KEB);
+  EVALUATE(CEB);
+  EVALUATE(AEB);
+  EVALUATE(SEB);
+  EVALUATE(MDEB);
+  EVALUATE(DEB);
+  EVALUATE(MAEB);
+  EVALUATE(MSEB);
+  EVALUATE(TCEB);
+  EVALUATE(TCDB);
+  EVALUATE(TCXB);
+  EVALUATE(SQEB);
+  EVALUATE(SQDB);
+  EVALUATE(MEEB);
+  EVALUATE(KDB);
+  EVALUATE(CDB);
+  EVALUATE(ADB);
+  EVALUATE(SDB);
+  EVALUATE(MDB);
+  EVALUATE(DDB);
+  EVALUATE(MADB);
+  EVALUATE(MSDB);
+  EVALUATE(SLDT);
+  EVALUATE(SRDT);
+  EVALUATE(SLXT);
+  EVALUATE(SRXT);
+  EVALUATE(TDCET);
+  EVALUATE(TDGET);
+  EVALUATE(TDCDT);
+  EVALUATE(TDGDT);
+  EVALUATE(TDCXT);
+  EVALUATE(TDGXT);
+  EVALUATE(LEY);
+  EVALUATE(LDY);
+  EVALUATE(STEY);
+  EVALUATE(STDY);
+  EVALUATE(CZDT);
+  EVALUATE(CZXT);
+  EVALUATE(CDZT);
+  EVALUATE(CXZT);
+#undef EVALUATE
 };
 
 // When running with the simulator transition into simulated execution at this
diff --git a/src/snapshot/code-serializer.cc b/src/snapshot/code-serializer.cc
index 84a08c1..4229607 100644
--- a/src/snapshot/code-serializer.cc
+++ b/src/snapshot/code-serializer.cc
@@ -7,7 +7,6 @@
 #include "src/code-stubs.h"
 #include "src/log.h"
 #include "src/macro-assembler.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/snapshot/deserializer.h"
 #include "src/version.h"
 
@@ -27,15 +26,14 @@
   }
 
   // Serialize code object.
-  SnapshotByteSink sink(info->code()->CodeSize() * 2);
-  CodeSerializer cs(isolate, &sink, *source);
+  CodeSerializer cs(isolate, *source);
   DisallowHeapAllocation no_gc;
   Object** location = Handle<Object>::cast(info).location();
   cs.VisitPointer(location);
   cs.SerializeDeferredObjects();
   cs.Pad();
 
-  SerializedCodeData data(sink.data(), cs);
+  SerializedCodeData data(cs.sink()->data(), &cs);
   ScriptData* script_data = data.GetScriptData();
 
   if (FLAG_profile_deserialization) {
@@ -49,13 +47,15 @@
 
 void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
                                      WhereToPoint where_to_point, int skip) {
+  if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return;
+
   int root_index = root_index_map_.Lookup(obj);
   if (root_index != RootIndexMap::kInvalidRootIndex) {
     PutRoot(root_index, obj, how_to_code, where_to_point, skip);
     return;
   }
 
-  if (SerializeKnownObject(obj, how_to_code, where_to_point, skip)) return;
+  if (SerializeBackReference(obj, how_to_code, where_to_point, skip)) return;
 
   FlushSkip(skip);
 
@@ -73,12 +73,10 @@
                          where_to_point);
         return;
       case Code::STUB:
-        SerializeCodeStub(code_object->stub_key(), how_to_code, where_to_point);
-        return;
 #define IC_KIND_CASE(KIND) case Code::KIND:
         IC_KIND_LIST(IC_KIND_CASE)
 #undef IC_KIND_CASE
-        SerializeIC(code_object, how_to_code, where_to_point);
+        SerializeCodeStub(code_object, how_to_code, where_to_point);
         return;
       case Code::FUNCTION:
         DCHECK(code_object->has_reloc_info_for_serialization());
@@ -108,7 +106,7 @@
                                       HowToCode how_to_code,
                                       WhereToPoint where_to_point) {
   // Object has not yet been serialized.  Serialize it here.
-  ObjectSerializer serializer(this, heap_object, sink_, how_to_code,
+  ObjectSerializer serializer(this, heap_object, &sink_, how_to_code,
                               where_to_point);
   serializer.Serialize();
 }
@@ -126,75 +124,27 @@
            isolate()->builtins()->name(builtin_index));
   }
 
-  sink_->Put(kBuiltin + how_to_code + where_to_point, "Builtin");
-  sink_->PutInt(builtin_index, "builtin_index");
+  sink_.Put(kBuiltin + how_to_code + where_to_point, "Builtin");
+  sink_.PutInt(builtin_index, "builtin_index");
 }
 
-void CodeSerializer::SerializeCodeStub(uint32_t stub_key, HowToCode how_to_code,
+void CodeSerializer::SerializeCodeStub(Code* code_stub, HowToCode how_to_code,
                                        WhereToPoint where_to_point) {
-  DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) ||
-         (how_to_code == kPlain && where_to_point == kInnerPointer) ||
-         (how_to_code == kFromCode && where_to_point == kInnerPointer));
+  // We only arrive here if we have not encountered this code stub before.
+  DCHECK(!reference_map()->Lookup(code_stub).is_valid());
+  uint32_t stub_key = code_stub->stub_key();
   DCHECK(CodeStub::MajorKeyFromKey(stub_key) != CodeStub::NoCache);
   DCHECK(!CodeStub::GetCode(isolate(), stub_key).is_null());
-
-  int index = AddCodeStubKey(stub_key) + kCodeStubsBaseIndex;
-
-  if (FLAG_trace_serializer) {
-    PrintF(" Encoding code stub %s as %d\n",
-           CodeStub::MajorName(CodeStub::MajorKeyFromKey(stub_key)), index);
-  }
-
-  sink_->Put(kAttachedReference + how_to_code + where_to_point, "CodeStub");
-  sink_->PutInt(index, "CodeStub key");
-}
-
-void CodeSerializer::SerializeIC(Code* ic, HowToCode how_to_code,
-                                 WhereToPoint where_to_point) {
-  // The IC may be implemented as a stub.
-  uint32_t stub_key = ic->stub_key();
-  if (stub_key != CodeStub::NoCacheKey()) {
-    if (FLAG_trace_serializer) {
-      PrintF(" %s is a code stub\n", Code::Kind2String(ic->kind()));
-    }
-    SerializeCodeStub(stub_key, how_to_code, where_to_point);
-    return;
-  }
-  // The IC may be implemented as builtin. Only real builtins have an
-  // actual builtin_index value attached (otherwise it's just garbage).
-  // Compare to make sure we are really dealing with a builtin.
-  int builtin_index = ic->builtin_index();
-  if (builtin_index < Builtins::builtin_count) {
-    Builtins::Name name = static_cast<Builtins::Name>(builtin_index);
-    Code* builtin = isolate()->builtins()->builtin(name);
-    if (builtin == ic) {
-      if (FLAG_trace_serializer) {
-        PrintF(" %s is a builtin\n", Code::Kind2String(ic->kind()));
-      }
-      DCHECK(ic->kind() == Code::KEYED_LOAD_IC ||
-             ic->kind() == Code::KEYED_STORE_IC);
-      SerializeBuiltin(builtin_index, how_to_code, where_to_point);
-      return;
-    }
-  }
-  // The IC may also just be a piece of code kept in the non_monomorphic_cache.
-  // In that case, just serialize as a normal code object.
-  if (FLAG_trace_serializer) {
-    PrintF(" %s has no special handling\n", Code::Kind2String(ic->kind()));
-  }
-  DCHECK(ic->kind() == Code::LOAD_IC || ic->kind() == Code::STORE_IC);
-  SerializeGeneric(ic, how_to_code, where_to_point);
-}
-
-int CodeSerializer::AddCodeStubKey(uint32_t stub_key) {
-  // TODO(yangguo) Maybe we need a hash table for a faster lookup than O(n^2).
-  int index = 0;
-  while (index < stub_keys_.length()) {
-    if (stub_keys_[index] == stub_key) return index;
-    index++;
-  }
   stub_keys_.Add(stub_key);
-  return index;
+
+  SerializerReference reference =
+      reference_map()->AddAttachedReference(code_stub);
+  if (FLAG_trace_serializer) {
+    PrintF(" Encoding code stub %s as attached reference %d\n",
+           CodeStub::MajorName(CodeStub::MajorKeyFromKey(stub_key)),
+           reference.attached_reference_index());
+  }
+  PutAttachedReference(reference, how_to_code, where_to_point);
 }
 
 MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
@@ -212,18 +162,13 @@
     return MaybeHandle<SharedFunctionInfo>();
   }
 
-  // Prepare and register list of attached objects.
-  Vector<const uint32_t> code_stub_keys = scd->CodeStubKeys();
-  Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New(
-      code_stub_keys.length() + kCodeStubsBaseIndex);
-  attached_objects[kSourceObjectIndex] = source;
-  for (int i = 0; i < code_stub_keys.length(); i++) {
-    attached_objects[i + kCodeStubsBaseIndex] =
-        CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked();
-  }
-
   Deserializer deserializer(scd.get());
-  deserializer.SetAttachedObjects(attached_objects);
+  deserializer.AddAttachedObject(source);
+  Vector<const uint32_t> code_stub_keys = scd->CodeStubKeys();
+  for (int i = 0; i < code_stub_keys.length(); i++) {
+    deserializer.AddAttachedObject(
+        CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked());
+  }
 
   // Deserialize.
   Handle<SharedFunctionInfo> result;
@@ -240,15 +185,14 @@
   }
   result->set_deserialized(true);
 
-  if (isolate->logger()->is_logging_code_events() ||
-      isolate->cpu_profiler()->is_profiling()) {
+  if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) {
     String* name = isolate->heap()->empty_string();
     if (result->script()->IsScript()) {
       Script* script = Script::cast(result->script());
       if (script->name()->IsString()) name = String::cast(script->name());
     }
-    isolate->logger()->CodeCreateEvent(
-        Logger::SCRIPT_TAG, result->abstract_code(), *result, NULL, name);
+    PROFILE(isolate, CodeCreateEvent(CodeEventListener::SCRIPT_TAG,
+                                     result->abstract_code(), *result, name));
   }
   return scope.CloseAndEscape(result);
 }
@@ -292,13 +236,13 @@
   DISALLOW_COPY_AND_ASSIGN(Checksum);
 };
 
-SerializedCodeData::SerializedCodeData(const List<byte>& payload,
-                                       const CodeSerializer& cs) {
+SerializedCodeData::SerializedCodeData(const List<byte>* payload,
+                                       const CodeSerializer* cs) {
   DisallowHeapAllocation no_gc;
-  const List<uint32_t>* stub_keys = cs.stub_keys();
+  const List<uint32_t>* stub_keys = cs->stub_keys();
 
   List<Reservation> reservations;
-  cs.EncodeReservations(&reservations);
+  cs->EncodeReservations(&reservations);
 
   // Calculate sizes.
   int reservation_size = reservations.length() * kInt32Size;
@@ -306,23 +250,23 @@
   int stub_keys_size = stub_keys->length() * kInt32Size;
   int payload_offset = kHeaderSize + reservation_size + stub_keys_size;
   int padded_payload_offset = POINTER_SIZE_ALIGN(payload_offset);
-  int size = padded_payload_offset + payload.length();
+  int size = padded_payload_offset + payload->length();
 
   // Allocate backing store and create result data.
   AllocateData(size);
 
   // Set header values.
-  SetMagicNumber(cs.isolate());
+  SetMagicNumber(cs->isolate());
   SetHeaderValue(kVersionHashOffset, Version::Hash());
-  SetHeaderValue(kSourceHashOffset, SourceHash(cs.source()));
+  SetHeaderValue(kSourceHashOffset, SourceHash(cs->source()));
   SetHeaderValue(kCpuFeaturesOffset,
                  static_cast<uint32_t>(CpuFeatures::SupportedFeatures()));
   SetHeaderValue(kFlagHashOffset, FlagList::Hash());
   SetHeaderValue(kNumReservationsOffset, reservations.length());
   SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys);
-  SetHeaderValue(kPayloadLengthOffset, payload.length());
+  SetHeaderValue(kPayloadLengthOffset, payload->length());
 
-  Checksum checksum(payload.ToConstVector());
+  Checksum checksum(payload->ToConstVector());
   SetHeaderValue(kChecksum1Offset, checksum.a());
   SetHeaderValue(kChecksum2Offset, checksum.b());
 
@@ -337,8 +281,8 @@
   memset(data_ + payload_offset, 0, padded_payload_offset - payload_offset);
 
   // Copy serialized data.
-  CopyBytes(data_ + padded_payload_offset, payload.begin(),
-            static_cast<size_t>(payload.length()));
+  CopyBytes(data_ + padded_payload_offset, payload->begin(),
+            static_cast<size_t>(payload->length()));
 }
 
 SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
diff --git a/src/snapshot/code-serializer.h b/src/snapshot/code-serializer.h
index b217fff..1948939 100644
--- a/src/snapshot/code-serializer.h
+++ b/src/snapshot/code-serializer.h
@@ -20,11 +20,6 @@
   MUST_USE_RESULT static MaybeHandle<SharedFunctionInfo> Deserialize(
       Isolate* isolate, ScriptData* cached_data, Handle<String> source);
 
-  static const int kSourceObjectIndex = 0;
-  STATIC_ASSERT(kSourceObjectReference == kSourceObjectIndex);
-
-  static const int kCodeStubsBaseIndex = 1;
-
   String* source() const {
     DCHECK(!AllowHeapAllocation::IsAllowed());
     return source_;
@@ -33,9 +28,9 @@
   const List<uint32_t>* stub_keys() const { return &stub_keys_; }
 
  private:
-  CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source)
-      : Serializer(isolate, sink), source_(source) {
-    back_reference_map_.AddSourceString(source);
+  CodeSerializer(Isolate* isolate, String* source)
+      : Serializer(isolate), source_(source) {
+    reference_map_.AddAttachedReference(source);
   }
 
   ~CodeSerializer() override { OutputStatistics("CodeSerializer"); }
@@ -45,13 +40,10 @@
 
   void SerializeBuiltin(int builtin_index, HowToCode how_to_code,
                         WhereToPoint where_to_point);
-  void SerializeIC(Code* ic, HowToCode how_to_code,
-                   WhereToPoint where_to_point);
-  void SerializeCodeStub(uint32_t stub_key, HowToCode how_to_code,
+  void SerializeCodeStub(Code* code_stub, HowToCode how_to_code,
                          WhereToPoint where_to_point);
   void SerializeGeneric(HeapObject* heap_object, HowToCode how_to_code,
                         WhereToPoint where_to_point);
-  int AddCodeStubKey(uint32_t stub_key);
 
   DisallowHeapAllocation no_gc_;
   String* source_;
@@ -68,7 +60,7 @@
                                             String* source);
 
   // Used when producing.
-  SerializedCodeData(const List<byte>& payload, const CodeSerializer& cs);
+  SerializedCodeData(const List<byte>* payload, const CodeSerializer* cs);
 
   // Return ScriptData object and relinquish ownership over it to the caller.
   ScriptData* GetScriptData();
diff --git a/src/snapshot/deserializer.cc b/src/snapshot/deserializer.cc
index 0a21fef..68d3489 100644
--- a/src/snapshot/deserializer.cc
+++ b/src/snapshot/deserializer.cc
@@ -31,9 +31,7 @@
 void Deserializer::FlushICacheForNewIsolate() {
   DCHECK(!deserializing_user_code_);
   // The entire isolate is newly deserialized. Simply flush all code pages.
-  PageIterator it(isolate_->heap()->code_space());
-  while (it.has_next()) {
-    Page* p = it.next();
+  for (Page* p : *isolate_->heap()->code_space()) {
     Assembler::FlushICache(isolate_, p->area_start(),
                            p->area_end() - p->area_start());
   }
@@ -101,10 +99,6 @@
         isolate_->heap()->undefined_value());
   }
 
-  // Update data pointers to the external strings containing natives sources.
-  Natives::UpdateSourceCache(isolate_->heap());
-  ExtraNatives::UpdateSourceCache(isolate_->heap());
-
   // Issue code events for newly deserialized code objects.
   LOG_CODE_EVENT(isolate_, LogCodeObjects());
   LOG_CODE_EVENT(isolate_, LogBytecodeHandlers());
@@ -119,9 +113,7 @@
     return MaybeHandle<Object>();
   }
 
-  Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New(1);
-  attached_objects[kGlobalProxyReference] = global_proxy;
-  SetAttachedObjects(attached_objects);
+  AddAttachedObject(global_proxy);
 
   DisallowHeapAllocation no_gc;
   // Keep track of the code space start and end pointers in case new
@@ -167,7 +159,6 @@
 Deserializer::~Deserializer() {
   // TODO(svenpanne) Re-enable this assertion when v8 initialization is fixed.
   // DCHECK(source_.AtEOF());
-  attached_objects_.Dispose();
 }
 
 // This is called on the roots.  It is the driver of the deserialization
@@ -315,7 +306,8 @@
 
 HeapObject* Deserializer::GetBackReferencedObject(int space) {
   HeapObject* obj;
-  BackReference back_reference(source_.GetInt());
+  SerializerReference back_reference =
+      SerializerReference::FromBitfield(source_.GetInt());
   if (space == LO_SPACE) {
     CHECK(back_reference.chunk_index() == 0);
     uint32_t index = back_reference.large_object_index();
@@ -483,6 +475,7 @@
         Heap::RootListIndex root_index = static_cast<Heap::RootListIndex>(id); \
         new_object = isolate->heap()->root(root_index);                        \
         emit_write_barrier = isolate->heap()->InNewSpace(new_object);          \
+        hot_objects_.Add(HeapObject::cast(new_object));                        \
       } else if (where == kPartialSnapshotCache) {                             \
         int cache_index = source_.GetInt();                                    \
         new_object = isolate->partial_snapshot_cache()->at(cache_index);       \
@@ -496,7 +489,6 @@
         new_object = reinterpret_cast<Object*>(address);                       \
       } else if (where == kAttachedReference) {                                \
         int index = source_.GetInt();                                          \
-        DCHECK(deserializing_user_code() || index == kGlobalProxyReference);   \
         new_object = *attached_objects_[index];                                \
         emit_write_barrier = isolate->heap()->InNewSpace(new_object);          \
       } else {                                                                 \
@@ -510,12 +502,11 @@
         emit_write_barrier = false;                                            \
       }                                                                        \
       if (within == kInnerPointer) {                                           \
-        if (space_number != CODE_SPACE || new_object->IsCode()) {              \
-          Code* new_code_object = reinterpret_cast<Code*>(new_object);         \
+        if (new_object->IsCode()) {                                            \
+          Code* new_code_object = Code::cast(new_object);                      \
           new_object =                                                         \
               reinterpret_cast<Object*>(new_code_object->instruction_start()); \
         } else {                                                               \
-          DCHECK(space_number == CODE_SPACE);                                  \
           Cell* cell = Cell::cast(new_object);                                 \
           new_object = reinterpret_cast<Object*>(cell->ValueAddress());        \
         }                                                                      \
@@ -582,6 +573,9 @@
       // pointer because it points at the entry point, not at the start of the
       // code object.
       SINGLE_CASE(kNewObject, kPlain, kInnerPointer, CODE_SPACE)
+      // Support for pointers into a cell. It's an inner pointer because it
+      // points directly at the value field, not the start of the cell object.
+      SINGLE_CASE(kNewObject, kPlain, kInnerPointer, OLD_SPACE)
       // Deserialize a new code object and write a pointer to its first
       // instruction to the current code object.
       ALL_SPACES(kNewObject, kFromCode, kInnerPointer)
@@ -608,8 +602,12 @@
       // object.
       ALL_SPACES(kBackref, kFromCode, kInnerPointer)
       ALL_SPACES(kBackrefWithSkip, kFromCode, kInnerPointer)
-      ALL_SPACES(kBackref, kPlain, kInnerPointer)
-      ALL_SPACES(kBackrefWithSkip, kPlain, kInnerPointer)
+      // Support for direct instruction pointers in functions.
+      SINGLE_CASE(kBackref, kPlain, kInnerPointer, CODE_SPACE)
+      SINGLE_CASE(kBackrefWithSkip, kPlain, kInnerPointer, CODE_SPACE)
+      // Support for pointers into a cell.
+      SINGLE_CASE(kBackref, kPlain, kInnerPointer, OLD_SPACE)
+      SINGLE_CASE(kBackrefWithSkip, kPlain, kInnerPointer, OLD_SPACE)
       // Find an object in the roots array and write a pointer to it to the
       // current object.
       SINGLE_CASE(kRootArray, kPlain, kStartOfObject, 0)
@@ -770,9 +768,8 @@
         int index = data & kHotObjectMask;
         Object* hot_object = hot_objects_.Get(index);
         UnalignedCopy(current, &hot_object);
-        if (write_barrier_needed) {
+        if (write_barrier_needed && isolate->heap()->InNewSpace(hot_object)) {
           Address current_address = reinterpret_cast<Address>(current);
-          SLOW_DCHECK(isolate->heap()->ContainsSlow(current_object_address));
           isolate->heap()->RecordWrite(
               HeapObject::FromAddress(current_object_address),
               static_cast<int>(current_address - current_object_address),
diff --git a/src/snapshot/deserializer.h b/src/snapshot/deserializer.h
index 58c481c..08b3444 100644
--- a/src/snapshot/deserializer.h
+++ b/src/snapshot/deserializer.h
@@ -53,10 +53,10 @@
   // Deserialize a shared function info. Fail gracefully.
   MaybeHandle<SharedFunctionInfo> DeserializeCode(Isolate* isolate);
 
-  // Pass a vector of externally-provided objects referenced by the snapshot.
-  // The ownership to its backing store is handed over as well.
-  void SetAttachedObjects(Vector<Handle<Object> > attached_objects) {
-    attached_objects_ = attached_objects;
+  // Add an object to back an attached reference. The order to add objects must
+  // mirror the order they are added in the serializer.
+  void AddAttachedObject(Handle<HeapObject> attached_object) {
+    attached_objects_.Add(attached_object);
   }
 
  private:
@@ -117,7 +117,7 @@
   Isolate* isolate_;
 
   // Objects from the attached object descriptions in the serialized user code.
-  Vector<Handle<Object> > attached_objects_;
+  List<Handle<HeapObject> > attached_objects_;
 
   SnapshotByteSource source_;
   uint32_t magic_number_;
diff --git a/src/snapshot/mksnapshot.cc b/src/snapshot/mksnapshot.cc
index 9fe611a..f4362e5 100644
--- a/src/snapshot/mksnapshot.cc
+++ b/src/snapshot/mksnapshot.cc
@@ -79,7 +79,7 @@
   }
 
   void WriteData(const i::Vector<const i::byte>& blob) const {
-    fprintf(fp_, "static const byte blob_data[] __attribute__((aligned(8))) = {\n");
+    fprintf(fp_, "static const byte blob_data[] = {\n");
     WriteSnapshotData(blob);
     fprintf(fp_, "};\n");
     fprintf(fp_, "static const int blob_size = %d;\n", blob.length());
@@ -150,7 +150,7 @@
   }
 
   i::CpuFeatures::Probe(true);
-  V8::InitializeICU();
+  V8::InitializeICUDefaultLocation(argv[0]);
   v8::Platform* platform = v8::platform::CreateDefaultPlatform();
   v8::V8::InitializePlatform(platform);
   v8::V8::Initialize();
diff --git a/src/snapshot/natives-common.cc b/src/snapshot/natives-common.cc
index f30e794..338b92b 100644
--- a/src/snapshot/natives-common.cc
+++ b/src/snapshot/natives-common.cc
@@ -34,24 +34,5 @@
   return heap->experimental_extra_natives_source_cache();
 }
 
-
-template <NativeType type>
-void NativesCollection<type>::UpdateSourceCache(Heap* heap) {
-  for (int i = 0; i < GetBuiltinsCount(); i++) {
-    Object* source = GetSourceCache(heap)->get(i);
-    if (!source->IsUndefined()) {
-      ExternalOneByteString::cast(source)->update_data_cache();
-    }
-  }
-}
-
-
-// Explicit template instantiations.
-template void NativesCollection<CORE>::UpdateSourceCache(Heap* heap);
-template void NativesCollection<EXPERIMENTAL>::UpdateSourceCache(Heap* heap);
-template void NativesCollection<EXTRAS>::UpdateSourceCache(Heap* heap);
-template void NativesCollection<EXPERIMENTAL_EXTRAS>::UpdateSourceCache(
-    Heap* heap);
-
 }  // namespace internal
 }  // namespace v8
diff --git a/src/snapshot/natives.h b/src/snapshot/natives.h
index 07f6b1a..e447515 100644
--- a/src/snapshot/natives.h
+++ b/src/snapshot/natives.h
@@ -44,7 +44,6 @@
   // The following methods are implemented in natives-common.cc:
 
   static FixedArray* GetSourceCache(Heap* heap);
-  static void UpdateSourceCache(Heap* heap);
 };
 
 typedef NativesCollection<CORE> Natives;
diff --git a/src/snapshot/partial-serializer.cc b/src/snapshot/partial-serializer.cc
index 0f1f133..b46f675 100644
--- a/src/snapshot/partial-serializer.cc
+++ b/src/snapshot/partial-serializer.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "src/snapshot/partial-serializer.h"
+#include "src/snapshot/startup-serializer.h"
 
 #include "src/objects-inl.h"
 
@@ -10,12 +11,8 @@
 namespace internal {
 
 PartialSerializer::PartialSerializer(Isolate* isolate,
-                                     Serializer* startup_snapshot_serializer,
-                                     SnapshotByteSink* sink)
-    : Serializer(isolate, sink),
-      startup_serializer_(startup_snapshot_serializer),
-      global_object_(NULL),
-      next_partial_cache_index_(0) {
+                                     StartupSerializer* startup_serializer)
+    : Serializer(isolate), startup_serializer_(startup_serializer) {
   InitializeCodeAddressMap();
 }
 
@@ -26,8 +23,7 @@
 void PartialSerializer::Serialize(Object** o) {
   if ((*o)->IsContext()) {
     Context* context = Context::cast(*o);
-    global_object_ = context->global_object();
-    back_reference_map()->AddGlobalProxy(context->global_proxy());
+    reference_map()->AddAttachedReference(context->global_proxy());
     // The bootstrap snapshot has a code-stub context. When serializing the
     // partial snapshot, it is chained into the weak context list on the isolate
     // and it's next context pointer may point to the code-stub context.  Clear
@@ -36,7 +32,7 @@
     if (context->IsNativeContext()) {
       context->set(Context::NEXT_CONTEXT_LINK,
                    isolate_->heap()->undefined_value());
-      DCHECK(!context->global_object()->IsUndefined());
+      DCHECK(!context->global_object()->IsUndefined(context->GetIsolate()));
     }
   }
   VisitPointer(o);
@@ -55,58 +51,53 @@
   // Replace typed arrays by undefined.
   if (obj->IsJSTypedArray()) obj = isolate_->heap()->undefined_value();
 
+  if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return;
+
   int root_index = root_index_map_.Lookup(obj);
   if (root_index != RootIndexMap::kInvalidRootIndex) {
     PutRoot(root_index, obj, how_to_code, where_to_point, skip);
     return;
   }
 
+  if (SerializeBackReference(obj, how_to_code, where_to_point, skip)) return;
+
   if (ShouldBeInThePartialSnapshotCache(obj)) {
     FlushSkip(skip);
 
-    int cache_index = PartialSnapshotCacheIndex(obj);
-    sink_->Put(kPartialSnapshotCache + how_to_code + where_to_point,
-               "PartialSnapshotCache");
-    sink_->PutInt(cache_index, "partial_snapshot_cache_index");
+    int cache_index = startup_serializer_->PartialSnapshotCacheIndex(obj);
+    sink_.Put(kPartialSnapshotCache + how_to_code + where_to_point,
+              "PartialSnapshotCache");
+    sink_.PutInt(cache_index, "partial_snapshot_cache_index");
     return;
   }
 
   // Pointers from the partial snapshot to the objects in the startup snapshot
   // should go through the root array or through the partial snapshot cache.
   // If this is not the case you may have to add something to the root array.
-  DCHECK(!startup_serializer_->back_reference_map()->Lookup(obj).is_valid());
+  DCHECK(!startup_serializer_->reference_map()->Lookup(obj).is_valid());
   // All the internalized strings that the partial snapshot needs should be
   // either in the root table or in the partial snapshot cache.
   DCHECK(!obj->IsInternalizedString());
-
-  if (SerializeKnownObject(obj, how_to_code, where_to_point, skip)) return;
+  // Function and object templates are not context specific.
+  DCHECK(!obj->IsTemplateInfo());
 
   FlushSkip(skip);
 
   // Clear literal boilerplates.
   if (obj->IsJSFunction()) {
-    FixedArray* literals = JSFunction::cast(obj)->literals();
-    for (int i = 0; i < literals->length(); i++) literals->set_undefined(i);
+    JSFunction* function = JSFunction::cast(obj);
+    LiteralsArray* literals = function->literals();
+    for (int i = 0; i < literals->literals_count(); i++) {
+      literals->set_literal_undefined(i);
+    }
+    function->ClearTypeFeedbackInfo();
   }
 
   // Object has not yet been serialized.  Serialize it here.
-  ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point);
+  ObjectSerializer serializer(this, obj, &sink_, how_to_code, where_to_point);
   serializer.Serialize();
 }
 
-int PartialSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) {
-  int index = partial_cache_index_map_.LookupOrInsert(
-      heap_object, next_partial_cache_index_);
-  if (index == PartialCacheIndexMap::kInvalidIndex) {
-    // This object is not part of the partial snapshot cache yet. Add it to the
-    // startup snapshot so we can refer to it via partial snapshot index from
-    // the partial snapshot.
-    startup_serializer_->VisitPointer(reinterpret_cast<Object**>(&heap_object));
-    return next_partial_cache_index_++;
-  }
-  return index;
-}
-
 bool PartialSerializer::ShouldBeInThePartialSnapshotCache(HeapObject* o) {
   // Scripts should be referred only through shared function infos.  We can't
   // allow them to be part of the partial snapshot because they contain a
diff --git a/src/snapshot/partial-serializer.h b/src/snapshot/partial-serializer.h
index 0bf61dd..282f76e 100644
--- a/src/snapshot/partial-serializer.h
+++ b/src/snapshot/partial-serializer.h
@@ -11,10 +11,11 @@
 namespace v8 {
 namespace internal {
 
+class StartupSerializer;
+
 class PartialSerializer : public Serializer {
  public:
-  PartialSerializer(Isolate* isolate, Serializer* startup_snapshot_serializer,
-                    SnapshotByteSink* sink);
+  PartialSerializer(Isolate* isolate, StartupSerializer* startup_serializer);
 
   ~PartialSerializer() override;
 
@@ -22,37 +23,12 @@
   void Serialize(Object** o);
 
  private:
-  class PartialCacheIndexMap : public AddressMapBase {
-   public:
-    PartialCacheIndexMap() : map_(HashMap::PointersMatch) {}
-
-    static const int kInvalidIndex = -1;
-
-    // Lookup object in the map. Return its index if found, or create
-    // a new entry with new_index as value, and return kInvalidIndex.
-    int LookupOrInsert(HeapObject* obj, int new_index) {
-      HashMap::Entry* entry = LookupEntry(&map_, obj, false);
-      if (entry != NULL) return GetValue(entry);
-      SetValue(LookupEntry(&map_, obj, true), static_cast<uint32_t>(new_index));
-      return kInvalidIndex;
-    }
-
-   private:
-    HashMap map_;
-
-    DISALLOW_COPY_AND_ASSIGN(PartialCacheIndexMap);
-  };
-
   void SerializeObject(HeapObject* o, HowToCode how_to_code,
                        WhereToPoint where_to_point, int skip) override;
 
-  int PartialSnapshotCacheIndex(HeapObject* o);
   bool ShouldBeInThePartialSnapshotCache(HeapObject* o);
 
-  Serializer* startup_serializer_;
-  Object* global_object_;
-  PartialCacheIndexMap partial_cache_index_map_;
-  int next_partial_cache_index_;
+  StartupSerializer* startup_serializer_;
   DISALLOW_COPY_AND_ASSIGN(PartialSerializer);
 };
 
diff --git a/src/snapshot/serializer-common.cc b/src/snapshot/serializer-common.cc
index eeb7eb7..41c68e8 100644
--- a/src/snapshot/serializer-common.cc
+++ b/src/snapshot/serializer-common.cc
@@ -14,13 +14,16 @@
 ExternalReferenceEncoder::ExternalReferenceEncoder(Isolate* isolate) {
   map_ = isolate->external_reference_map();
   if (map_ != NULL) return;
-  map_ = new HashMap(HashMap::PointersMatch);
+  map_ = new base::HashMap(base::HashMap::PointersMatch);
   ExternalReferenceTable* table = ExternalReferenceTable::instance(isolate);
   for (int i = 0; i < table->size(); ++i) {
     Address addr = table->address(i);
     if (addr == ExternalReferenceTable::NotAvailable()) continue;
     // We expect no duplicate external references entries in the table.
-    DCHECK_NULL(map_->Lookup(addr, Hash(addr)));
+    // AccessorRefTable getter may have duplicates, indicated by an empty string
+    // as name.
+    DCHECK(table->name(i)[0] == '\0' ||
+           map_->Lookup(addr, Hash(addr)) == nullptr);
     map_->LookupOrInsert(addr, Hash(addr))->value = reinterpret_cast<void*>(i);
   }
   isolate->set_external_reference_map(map_);
@@ -28,16 +31,16 @@
 
 uint32_t ExternalReferenceEncoder::Encode(Address address) const {
   DCHECK_NOT_NULL(address);
-  HashMap::Entry* entry =
-      const_cast<HashMap*>(map_)->Lookup(address, Hash(address));
+  base::HashMap::Entry* entry =
+      const_cast<base::HashMap*>(map_)->Lookup(address, Hash(address));
   DCHECK_NOT_NULL(entry);
   return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry->value));
 }
 
 const char* ExternalReferenceEncoder::NameOfAddress(Isolate* isolate,
                                                     Address address) const {
-  HashMap::Entry* entry =
-      const_cast<HashMap*>(map_)->Lookup(address, Hash(address));
+  base::HashMap::Entry* entry =
+      const_cast<base::HashMap*>(map_)->Lookup(address, Hash(address));
   if (entry == NULL) return "<unknown>";
   uint32_t i = static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry->value));
   return ExternalReferenceTable::instance(isolate)->name(i);
@@ -64,7 +67,7 @@
     // During deserialization, the visitor populates the partial snapshot cache
     // and eventually terminates the cache with undefined.
     visitor->VisitPointer(&cache->at(i));
-    if (cache->at(i)->IsUndefined()) break;
+    if (cache->at(i)->IsUndefined(isolate)) break;
   }
 }
 
diff --git a/src/snapshot/serializer-common.h b/src/snapshot/serializer-common.h
index 645a9af..bdd2b51 100644
--- a/src/snapshot/serializer-common.h
+++ b/src/snapshot/serializer-common.h
@@ -28,7 +28,7 @@
                                  kPointerSizeLog2);
   }
 
-  HashMap* map_;
+  base::HashMap* map_;
 
   DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder);
 };
@@ -40,11 +40,13 @@
   }
 
   void Add(HeapObject* object) {
+    DCHECK(!AllowHeapAllocation::IsAllowed());
     circular_queue_[index_] = object;
     index_ = (index_ + 1) & kSizeMask;
   }
 
   HeapObject* Get(int index) {
+    DCHECK(!AllowHeapAllocation::IsAllowed());
     DCHECK_NOT_NULL(circular_queue_[index]);
     return circular_queue_[index];
   }
@@ -52,6 +54,7 @@
   static const int kNotFound = -1;
 
   int Find(HeapObject* object) {
+    DCHECK(!AllowHeapAllocation::IsAllowed());
     for (int i = 0; i < kSize; i++) {
       if (circular_queue_[i] == object) return i;
     }
@@ -91,31 +94,26 @@
   STATIC_ASSERT(5 == kNumberOfSpaces);
   enum Where {
     // 0x00..0x04  Allocate new object, in specified space.
-    kNewObject = 0,
-    // 0x05        Unused (including 0x25, 0x45, 0x65).
-    // 0x06        Unused (including 0x26, 0x46, 0x66).
-    // 0x07        Unused (including 0x27, 0x47, 0x67).
+    kNewObject = 0x00,
     // 0x08..0x0c  Reference to previous object from space.
     kBackref = 0x08,
-    // 0x0d        Unused (including 0x2d, 0x4d, 0x6d).
-    // 0x0e        Unused (including 0x2e, 0x4e, 0x6e).
-    // 0x0f        Unused (including 0x2f, 0x4f, 0x6f).
     // 0x10..0x14  Reference to previous object from space after skip.
     kBackrefWithSkip = 0x10,
-    // 0x15        Unused (including 0x35, 0x55, 0x75).
-    // 0x16        Unused (including 0x36, 0x56, 0x76).
-    // 0x17        Misc (including 0x37, 0x57, 0x77).
-    // 0x18        Root array item.
-    kRootArray = 0x18,
-    // 0x19        Object in the partial snapshot cache.
-    kPartialSnapshotCache = 0x19,
-    // 0x1a        External reference referenced by id.
-    kExternalReference = 0x1a,
-    // 0x1b        Object provided in the attached list.
-    kAttachedReference = 0x1b,
-    // 0x1c        Builtin code referenced by index.
-    kBuiltin = 0x1c
-    // 0x1d..0x1f  Misc (including 0x3d..0x3f, 0x5d..0x5f, 0x7d..0x7f)
+
+    // 0x05       Root array item.
+    kRootArray = 0x05,
+    // 0x06        Object in the partial snapshot cache.
+    kPartialSnapshotCache = 0x06,
+    // 0x07        External reference referenced by id.
+    kExternalReference = 0x07,
+
+    // 0x0d        Object provided in the attached list.
+    kAttachedReference = 0x0d,
+    // 0x0e        Builtin code referenced by index.
+    kBuiltin = 0x0e,
+
+    // 0x0f        Misc, see below (incl. 0x2f, 0x4f, 0x6f).
+    // 0x15..0x1f  Misc, see below (incl. 0x35..0x3f, 0x55..0x5f, 0x75..0x7f).
   };
 
   static const int kWhereMask = 0x1f;
@@ -144,36 +142,45 @@
 
   // ---------- Misc ----------
   // Skip.
-  static const int kSkip = 0x1d;
-  // Internal reference encoded as offsets of pc and target from code entry.
-  static const int kInternalReference = 0x1e;
-  static const int kInternalReferenceEncoded = 0x1f;
+  static const int kSkip = 0x0f;
   // Do nothing, used for padding.
-  static const int kNop = 0x3d;
+  static const int kNop = 0x2f;
   // Move to next reserved chunk.
-  static const int kNextChunk = 0x3e;
+  static const int kNextChunk = 0x4f;
   // Deferring object content.
-  static const int kDeferred = 0x3f;
-  // Used for the source code of the natives, which is in the executable, but
-  // is referred to from external strings in the snapshot.
-  static const int kNativesStringResource = 0x5d;
-  // Used for the source code for compiled stubs, which is in the executable,
-  // but is referred to from external strings in the snapshot.
-  static const int kExtraNativesStringResource = 0x5e;
+  static const int kDeferred = 0x6f;
+  // Alignment prefixes 0x15..0x17
+  static const int kAlignmentPrefix = 0x15;
   // A tag emitted at strategic points in the snapshot to delineate sections.
   // If the deserializer does not find these at the expected moments then it
   // is an indication that the snapshot and the VM do not fit together.
   // Examine the build process for architecture, version or configuration
   // mismatches.
-  static const int kSynchronize = 0x17;
+  static const int kSynchronize = 0x18;
   // Repeats of variable length.
-  static const int kVariableRepeat = 0x37;
+  static const int kVariableRepeat = 0x19;
   // Raw data of variable length.
-  static const int kVariableRawData = 0x57;
-  // Alignment prefixes 0x7d..0x7f
-  static const int kAlignmentPrefix = 0x7d;
+  static const int kVariableRawData = 0x1a;
+  // Internal reference encoded as offsets of pc and target from code entry.
+  static const int kInternalReference = 0x1b;
+  static const int kInternalReferenceEncoded = 0x1c;
+  // Used for the source code of the natives, which is in the executable, but
+  // is referred to from external strings in the snapshot.
+  static const int kNativesStringResource = 0x1d;
+  // Used for the source code for compiled stubs, which is in the executable,
+  // but is referred to from external strings in the snapshot.
+  static const int kExtraNativesStringResource = 0x1e;
 
-  // 0x77 unused
+  // 8 hot (recently seen or back-referenced) objects with optional skip.
+  static const int kNumberOfHotObjects = 8;
+  STATIC_ASSERT(kNumberOfHotObjects == HotObjectsList::kSize);
+  // 0x38..0x3f
+  static const int kHotObject = 0x38;
+  // 0x58..0x5f
+  static const int kHotObjectWithSkip = 0x58;
+  static const int kHotObjectMask = 0x07;
+
+  // 0x1f, 0x35..0x37, 0x55..0x57, 0x75..0x7f unused.
 
   // ---------- byte code range 0x80..0xff ----------
   // First 32 root array items.
@@ -184,39 +191,27 @@
   static const int kRootArrayConstantsWithSkip = 0xa0;
   static const int kRootArrayConstantsMask = 0x1f;
 
-  // 8 hot (recently seen or back-referenced) objects with optional skip.
-  static const int kNumberOfHotObjects = 0x08;
-  // 0xc0..0xc7
-  static const int kHotObject = 0xc0;
-  // 0xc8..0xcf
-  static const int kHotObjectWithSkip = 0xc8;
-  static const int kHotObjectMask = 0x07;
-
   // 32 common raw data lengths.
   static const int kNumberOfFixedRawData = 0x20;
-  // 0xd0..0xef
-  static const int kFixedRawData = 0xd0;
+  // 0xc0..0xdf
+  static const int kFixedRawData = 0xc0;
   static const int kOnePointerRawData = kFixedRawData;
   static const int kFixedRawDataStart = kFixedRawData - 1;
 
   // 16 repeats lengths.
   static const int kNumberOfFixedRepeat = 0x10;
-  // 0xf0..0xff
-  static const int kFixedRepeat = 0xf0;
+  // 0xe0..0xef
+  static const int kFixedRepeat = 0xe0;
   static const int kFixedRepeatStart = kFixedRepeat - 1;
 
+  // 0xf0..0xff unused.
+
   // ---------- special values ----------
   static const int kAnyOldSpace = -1;
 
   // Sentinel after a new object to indicate that double alignment is needed.
   static const int kDoubleAlignmentSentinel = 0;
 
-  // Used as index for the attached reference representing the source object.
-  static const int kSourceObjectReference = 0;
-
-  // Used as index for the attached reference representing the global proxy.
-  static const int kGlobalProxyReference = 0;
-
   // ---------- member variable ----------
   HotObjectsList hot_objects_;
 };
diff --git a/src/snapshot/serializer.cc b/src/snapshot/serializer.cc
index 4169338..b6a75ff 100644
--- a/src/snapshot/serializer.cc
+++ b/src/snapshot/serializer.cc
@@ -10,9 +10,8 @@
 namespace v8 {
 namespace internal {
 
-Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink)
+Serializer::Serializer(Isolate* isolate)
     : isolate_(isolate),
-      sink_(sink),
       external_reference_encoder_(isolate),
       root_index_map_(isolate),
       recursion_depth_(0),
@@ -71,15 +70,15 @@
   for (int space = 0; space < kNumberOfPreallocatedSpaces; space++) {
     size_t s = pending_chunk_[space];
     for (uint32_t chunk_size : completed_chunks_[space]) s += chunk_size;
-    PrintF("%16" V8_SIZET_PREFIX V8_PTR_PREFIX "d", s);
+    PrintF("%16" PRIuS, s);
   }
   PrintF("%16d\n", large_objects_total_size_);
 #ifdef OBJECT_PRINT
   PrintF("  Instance types (count and bytes):\n");
-#define PRINT_INSTANCE_TYPE(Name)                                         \
-  if (instance_type_count_[Name]) {                                       \
-    PrintF("%10d %10" V8_SIZET_PREFIX V8_PTR_PREFIX "d  %s\n",            \
-           instance_type_count_[Name], instance_type_size_[Name], #Name); \
+#define PRINT_INSTANCE_TYPE(Name)                                 \
+  if (instance_type_count_[Name]) {                               \
+    PrintF("%10d %10" PRIuS "  %s\n", instance_type_count_[Name], \
+           instance_type_size_[Name], #Name);                     \
   }
   INSTANCE_TYPE_LIST(PRINT_INSTANCE_TYPE)
 #undef PRINT_INSTANCE_TYPE
@@ -90,10 +89,10 @@
 void Serializer::SerializeDeferredObjects() {
   while (deferred_objects_.length() > 0) {
     HeapObject* obj = deferred_objects_.RemoveLast();
-    ObjectSerializer obj_serializer(this, obj, sink_, kPlain, kStartOfObject);
+    ObjectSerializer obj_serializer(this, obj, &sink_, kPlain, kStartOfObject);
     obj_serializer.SerializeDeferred();
   }
-  sink_->Put(kSynchronize, "Finished with deferred objects");
+  sink_.Put(kSynchronize, "Finished with deferred objects");
 }
 
 void Serializer::VisitPointers(Object** start, Object** end) {
@@ -124,10 +123,9 @@
 }
 
 #ifdef DEBUG
-bool Serializer::BackReferenceIsAlreadyAllocated(BackReference reference) {
-  DCHECK(reference.is_valid());
-  DCHECK(!reference.is_source());
-  DCHECK(!reference.is_global_proxy());
+bool Serializer::BackReferenceIsAlreadyAllocated(
+    SerializerReference reference) {
+  DCHECK(reference.is_back_reference());
   AllocationSpace space = reference.space();
   int chunk_index = reference.chunk_index();
   if (space == LO_SPACE) {
@@ -142,66 +140,61 @@
 }
 #endif  // DEBUG
 
-bool Serializer::SerializeKnownObject(HeapObject* obj, HowToCode how_to_code,
-                                      WhereToPoint where_to_point, int skip) {
-  if (how_to_code == kPlain && where_to_point == kStartOfObject) {
-    // Encode a reference to a hot object by its index in the working set.
-    int index = hot_objects_.Find(obj);
-    if (index != HotObjectsList::kNotFound) {
-      DCHECK(index >= 0 && index < kNumberOfHotObjects);
-      if (FLAG_trace_serializer) {
-        PrintF(" Encoding hot object %d:", index);
-        obj->ShortPrint();
-        PrintF("\n");
-      }
-      if (skip != 0) {
-        sink_->Put(kHotObjectWithSkip + index, "HotObjectWithSkip");
-        sink_->PutInt(skip, "HotObjectSkipDistance");
-      } else {
-        sink_->Put(kHotObject + index, "HotObject");
-      }
-      return true;
-    }
+bool Serializer::SerializeHotObject(HeapObject* obj, HowToCode how_to_code,
+                                    WhereToPoint where_to_point, int skip) {
+  if (how_to_code != kPlain || where_to_point != kStartOfObject) return false;
+  // Encode a reference to a hot object by its index in the working set.
+  int index = hot_objects_.Find(obj);
+  if (index == HotObjectsList::kNotFound) return false;
+  DCHECK(index >= 0 && index < kNumberOfHotObjects);
+  if (FLAG_trace_serializer) {
+    PrintF(" Encoding hot object %d:", index);
+    obj->ShortPrint();
+    PrintF("\n");
   }
-  BackReference back_reference = back_reference_map_.Lookup(obj);
-  if (back_reference.is_valid()) {
-    // Encode the location of an already deserialized object in order to write
-    // its location into a later object.  We can encode the location as an
-    // offset fromthe start of the deserialized objects or as an offset
-    // backwards from thecurrent allocation pointer.
-    if (back_reference.is_source()) {
-      FlushSkip(skip);
-      if (FLAG_trace_serializer) PrintF(" Encoding source object\n");
-      DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject);
-      sink_->Put(kAttachedReference + kPlain + kStartOfObject, "Source");
-      sink_->PutInt(kSourceObjectReference, "kSourceObjectReference");
-    } else if (back_reference.is_global_proxy()) {
-      FlushSkip(skip);
-      if (FLAG_trace_serializer) PrintF(" Encoding global proxy\n");
-      DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject);
-      sink_->Put(kAttachedReference + kPlain + kStartOfObject, "Global Proxy");
-      sink_->PutInt(kGlobalProxyReference, "kGlobalProxyReference");
-    } else {
-      if (FLAG_trace_serializer) {
-        PrintF(" Encoding back reference to: ");
-        obj->ShortPrint();
-        PrintF("\n");
-      }
+  if (skip != 0) {
+    sink_.Put(kHotObjectWithSkip + index, "HotObjectWithSkip");
+    sink_.PutInt(skip, "HotObjectSkipDistance");
+  } else {
+    sink_.Put(kHotObject + index, "HotObject");
+  }
+  return true;
+}
+bool Serializer::SerializeBackReference(HeapObject* obj, HowToCode how_to_code,
+                                        WhereToPoint where_to_point, int skip) {
+  SerializerReference reference = reference_map_.Lookup(obj);
+  if (!reference.is_valid()) return false;
+  // Encode the location of an already deserialized object in order to write
+  // its location into a later object.  We can encode the location as an
+  // offset fromthe start of the deserialized objects or as an offset
+  // backwards from thecurrent allocation pointer.
+  if (reference.is_attached_reference()) {
+    FlushSkip(skip);
+    if (FLAG_trace_serializer) {
+      PrintF(" Encoding attached reference %d\n",
+             reference.attached_reference_index());
+    }
+    PutAttachedReference(reference, how_to_code, where_to_point);
+  } else {
+    DCHECK(reference.is_back_reference());
+    if (FLAG_trace_serializer) {
+      PrintF(" Encoding back reference to: ");
+      obj->ShortPrint();
+      PrintF("\n");
+    }
 
-      PutAlignmentPrefix(obj);
-      AllocationSpace space = back_reference.space();
-      if (skip == 0) {
-        sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRef");
-      } else {
-        sink_->Put(kBackrefWithSkip + how_to_code + where_to_point + space,
-                   "BackRefWithSkip");
-        sink_->PutInt(skip, "BackRefSkipDistance");
-      }
-      PutBackReference(obj, back_reference);
+    PutAlignmentPrefix(obj);
+    AllocationSpace space = reference.space();
+    if (skip == 0) {
+      sink_.Put(kBackref + how_to_code + where_to_point + space, "BackRef");
+    } else {
+      sink_.Put(kBackrefWithSkip + how_to_code + where_to_point + space,
+                "BackRefWithSkip");
+      sink_.PutInt(skip, "BackRefSkipDistance");
     }
-    return true;
+    PutBackReference(obj, reference);
   }
-  return false;
+  return true;
 }
 
 void Serializer::PutRoot(int root_index, HeapObject* object,
@@ -218,77 +211,89 @@
       root_index < kNumberOfRootArrayConstants &&
       !isolate()->heap()->InNewSpace(object)) {
     if (skip == 0) {
-      sink_->Put(kRootArrayConstants + root_index, "RootConstant");
+      sink_.Put(kRootArrayConstants + root_index, "RootConstant");
     } else {
-      sink_->Put(kRootArrayConstantsWithSkip + root_index, "RootConstant");
-      sink_->PutInt(skip, "SkipInPutRoot");
+      sink_.Put(kRootArrayConstantsWithSkip + root_index, "RootConstant");
+      sink_.PutInt(skip, "SkipInPutRoot");
     }
   } else {
     FlushSkip(skip);
-    sink_->Put(kRootArray + how_to_code + where_to_point, "RootSerialization");
-    sink_->PutInt(root_index, "root_index");
+    sink_.Put(kRootArray + how_to_code + where_to_point, "RootSerialization");
+    sink_.PutInt(root_index, "root_index");
+    hot_objects_.Add(object);
   }
 }
 
 void Serializer::PutSmi(Smi* smi) {
-  sink_->Put(kOnePointerRawData, "Smi");
+  sink_.Put(kOnePointerRawData, "Smi");
   byte* bytes = reinterpret_cast<byte*>(&smi);
-  for (int i = 0; i < kPointerSize; i++) sink_->Put(bytes[i], "Byte");
+  for (int i = 0; i < kPointerSize; i++) sink_.Put(bytes[i], "Byte");
 }
 
-void Serializer::PutBackReference(HeapObject* object, BackReference reference) {
+void Serializer::PutBackReference(HeapObject* object,
+                                  SerializerReference reference) {
   DCHECK(BackReferenceIsAlreadyAllocated(reference));
-  sink_->PutInt(reference.reference(), "BackRefValue");
+  sink_.PutInt(reference.back_reference(), "BackRefValue");
   hot_objects_.Add(object);
 }
 
+void Serializer::PutAttachedReference(SerializerReference reference,
+                                      HowToCode how_to_code,
+                                      WhereToPoint where_to_point) {
+  DCHECK(reference.is_attached_reference());
+  DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) ||
+         (how_to_code == kPlain && where_to_point == kInnerPointer) ||
+         (how_to_code == kFromCode && where_to_point == kInnerPointer));
+  sink_.Put(kAttachedReference + how_to_code + where_to_point, "AttachedRef");
+  sink_.PutInt(reference.attached_reference_index(), "AttachedRefIndex");
+}
+
 int Serializer::PutAlignmentPrefix(HeapObject* object) {
   AllocationAlignment alignment = object->RequiredAlignment();
   if (alignment != kWordAligned) {
     DCHECK(1 <= alignment && alignment <= 3);
     byte prefix = (kAlignmentPrefix - 1) + alignment;
-    sink_->Put(prefix, "Alignment");
+    sink_.Put(prefix, "Alignment");
     return Heap::GetMaximumFillToAlign(alignment);
   }
   return 0;
 }
 
-BackReference Serializer::AllocateLargeObject(int size) {
+SerializerReference Serializer::AllocateLargeObject(int size) {
   // Large objects are allocated one-by-one when deserializing. We do not
   // have to keep track of multiple chunks.
   large_objects_total_size_ += size;
-  return BackReference::LargeObjectReference(seen_large_objects_index_++);
+  return SerializerReference::LargeObjectReference(seen_large_objects_index_++);
 }
 
-BackReference Serializer::Allocate(AllocationSpace space, int size) {
+SerializerReference Serializer::Allocate(AllocationSpace space, int size) {
   DCHECK(space >= 0 && space < kNumberOfPreallocatedSpaces);
   DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space)));
   uint32_t new_chunk_size = pending_chunk_[space] + size;
   if (new_chunk_size > max_chunk_size(space)) {
     // The new chunk size would not fit onto a single page. Complete the
     // current chunk and start a new one.
-    sink_->Put(kNextChunk, "NextChunk");
-    sink_->Put(space, "NextChunkSpace");
+    sink_.Put(kNextChunk, "NextChunk");
+    sink_.Put(space, "NextChunkSpace");
     completed_chunks_[space].Add(pending_chunk_[space]);
-    DCHECK_LE(completed_chunks_[space].length(), BackReference::kMaxChunkIndex);
     pending_chunk_[space] = 0;
     new_chunk_size = size;
   }
   uint32_t offset = pending_chunk_[space];
   pending_chunk_[space] = new_chunk_size;
-  return BackReference::Reference(space, completed_chunks_[space].length(),
-                                  offset);
+  return SerializerReference::BackReference(
+      space, completed_chunks_[space].length(), offset);
 }
 
 void Serializer::Pad() {
   // The non-branching GetInt will read up to 3 bytes too far, so we need
   // to pad the snapshot to make sure we don't read over the end.
   for (unsigned i = 0; i < sizeof(int32_t) - 1; i++) {
-    sink_->Put(kNop, "Padding");
+    sink_.Put(kNop, "Padding");
   }
   // Pad up to pointer size for checksum.
-  while (!IsAligned(sink_->Position(), kPointerAlignment)) {
-    sink_->Put(kNop, "Padding");
+  while (!IsAligned(sink_.Position(), kPointerAlignment)) {
+    sink_.Put(kNop, "Padding");
   }
 }
 
@@ -320,7 +325,7 @@
         CodeNameEvent(object_->address(), sink_->Position(), code_name));
   }
 
-  BackReference back_reference;
+  SerializerReference back_reference;
   if (space == LO_SPACE) {
     sink_->Put(kNewObject + reference_representation_ + space,
                "NewLargeObject");
@@ -345,7 +350,7 @@
 #endif  // OBJECT_PRINT
 
   // Mark this object as already serialized.
-  serializer_->back_reference_map()->Add(object_, back_reference);
+  serializer_->reference_map()->Add(object_, back_reference);
 
   // Serialize the map (first word of the object).
   serializer_->SerializeObject(map, kPlain, kStartOfObject, 0);
@@ -513,15 +518,17 @@
 
   int size = object_->Size();
   Map* map = object_->map();
-  BackReference reference = serializer_->back_reference_map()->Lookup(object_);
+  SerializerReference back_reference =
+      serializer_->reference_map()->Lookup(object_);
+  DCHECK(back_reference.is_back_reference());
 
   // Serialize the rest of the object.
   CHECK_EQ(0, bytes_processed_so_far_);
   bytes_processed_so_far_ = kPointerSize;
 
   serializer_->PutAlignmentPrefix(object_);
-  sink_->Put(kNewObject + reference.space(), "deferred object");
-  serializer_->PutBackReference(object_, reference);
+  sink_->Put(kNewObject + back_reference.space(), "deferred object");
+  serializer_->PutBackReference(object_, back_reference);
   sink_->PutInt(size >> kPointerSizeLog2, "deferred object size");
 
   UnlinkWeakNextScope unlink_weak_next(object_);
@@ -660,9 +667,10 @@
     int builtin_count,
     v8::String::ExternalOneByteStringResource** resource_pointer,
     FixedArray* source_cache, int resource_index) {
+  Isolate* isolate = serializer_->isolate();
   for (int i = 0; i < builtin_count; i++) {
     Object* source = source_cache->get(i);
-    if (!source->IsUndefined()) {
+    if (!source->IsUndefined(isolate)) {
       ExternalOneByteString* string = ExternalOneByteString::cast(source);
       typedef v8::String::ExternalOneByteStringResource Resource;
       const Resource* resource = string->resource();
@@ -679,6 +687,9 @@
 
 void Serializer::ObjectSerializer::VisitExternalOneByteString(
     v8::String::ExternalOneByteStringResource** resource_pointer) {
+  DCHECK_EQ(serializer_->isolate()->heap()->native_source_string_map(),
+            object_->map());
+  DCHECK(ExternalOneByteString::cast(object_)->is_short());
   Address references_start = reinterpret_cast<Address>(resource_pointer);
   OutputRawData(references_start);
   if (SerializeExternalNativeSourceString(
@@ -699,25 +710,27 @@
 }
 
 Address Serializer::ObjectSerializer::PrepareCode() {
-  // To make snapshots reproducible, we make a copy of the code object
-  // and wipe all pointers in the copy, which we then serialize.
-  Code* original = Code::cast(object_);
-  Code* code = serializer_->CopyCode(original);
+  Code* code = Code::cast(object_);
+  if (FLAG_predictable) {
+    // To make snapshots reproducible, we make a copy of the code object
+    // and wipe all pointers in the copy, which we then serialize.
+    code = serializer_->CopyCode(code);
+    int mode_mask = RelocInfo::kCodeTargetMask |
+                    RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
+                    RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
+                    RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
+                    RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
+                    RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
+    for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
+      RelocInfo* rinfo = it.rinfo();
+      rinfo->WipeOut();
+    }
+    // We need to wipe out the header fields *after* wiping out the
+    // relocations, because some of these fields are needed for the latter.
+    code->WipeOutHeader();
+  }
   // Code age headers are not serializable.
   code->MakeYoung(serializer_->isolate());
-  int mode_mask = RelocInfo::kCodeTargetMask |
-                  RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
-                  RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
-                  RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
-                  RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
-                  RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
-  for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
-    RelocInfo* rinfo = it.rinfo();
-    rinfo->WipeOut();
-  }
-  // We need to wipe out the header fields *after* wiping out the
-  // relocations, because some of these fields are needed for the latter.
-  code->WipeOutHeader();
   return code->address();
 }
 
diff --git a/src/snapshot/serializer.h b/src/snapshot/serializer.h
index eccbaab..45f891e 100644
--- a/src/snapshot/serializer.h
+++ b/src/snapshot/serializer.h
@@ -38,28 +38,29 @@
  private:
   class NameMap {
    public:
-    NameMap() : impl_(HashMap::PointersMatch) {}
+    NameMap() : impl_(base::HashMap::PointersMatch) {}
 
     ~NameMap() {
-      for (HashMap::Entry* p = impl_.Start(); p != NULL; p = impl_.Next(p)) {
+      for (base::HashMap::Entry* p = impl_.Start(); p != NULL;
+           p = impl_.Next(p)) {
         DeleteArray(static_cast<const char*>(p->value));
       }
     }
 
     void Insert(Address code_address, const char* name, int name_size) {
-      HashMap::Entry* entry = FindOrCreateEntry(code_address);
+      base::HashMap::Entry* entry = FindOrCreateEntry(code_address);
       if (entry->value == NULL) {
         entry->value = CopyName(name, name_size);
       }
     }
 
     const char* Lookup(Address code_address) {
-      HashMap::Entry* entry = FindEntry(code_address);
+      base::HashMap::Entry* entry = FindEntry(code_address);
       return (entry != NULL) ? static_cast<const char*>(entry->value) : NULL;
     }
 
     void Remove(Address code_address) {
-      HashMap::Entry* entry = FindEntry(code_address);
+      base::HashMap::Entry* entry = FindEntry(code_address);
       if (entry != NULL) {
         DeleteArray(static_cast<char*>(entry->value));
         RemoveEntry(entry);
@@ -68,11 +69,11 @@
 
     void Move(Address from, Address to) {
       if (from == to) return;
-      HashMap::Entry* from_entry = FindEntry(from);
+      base::HashMap::Entry* from_entry = FindEntry(from);
       DCHECK(from_entry != NULL);
       void* value = from_entry->value;
       RemoveEntry(from_entry);
-      HashMap::Entry* to_entry = FindOrCreateEntry(to);
+      base::HashMap::Entry* to_entry = FindOrCreateEntry(to);
       DCHECK(to_entry->value == NULL);
       to_entry->value = value;
     }
@@ -89,20 +90,20 @@
       return result;
     }
 
-    HashMap::Entry* FindOrCreateEntry(Address code_address) {
+    base::HashMap::Entry* FindOrCreateEntry(Address code_address) {
       return impl_.LookupOrInsert(code_address,
                                   ComputePointerHash(code_address));
     }
 
-    HashMap::Entry* FindEntry(Address code_address) {
+    base::HashMap::Entry* FindEntry(Address code_address) {
       return impl_.Lookup(code_address, ComputePointerHash(code_address));
     }
 
-    void RemoveEntry(HashMap::Entry* entry) {
+    void RemoveEntry(base::HashMap::Entry* entry) {
       impl_.Remove(entry->key, entry->hash);
     }
 
-    HashMap impl_;
+    base::HashMap impl_;
 
     DISALLOW_COPY_AND_ASSIGN(NameMap);
   };
@@ -119,7 +120,7 @@
 // There can be only one serializer per V8 process.
 class Serializer : public SerializerDeserializer {
  public:
-  Serializer(Isolate* isolate, SnapshotByteSink* sink);
+  explicit Serializer(Isolate* isolate);
   ~Serializer() override;
 
   void EncodeReservations(List<SerializedData::Reservation>* out) const;
@@ -128,7 +129,7 @@
 
   Isolate* isolate() const { return isolate_; }
 
-  BackReferenceMap* back_reference_map() { return &back_reference_map_; }
+  SerializerReferenceMap* reference_map() { return &reference_map_; }
   RootIndexMap* root_index_map() { return &root_index_map_; }
 
 #ifdef OBJECT_PRINT
@@ -162,27 +163,34 @@
 
   void PutSmi(Smi* smi);
 
-  void PutBackReference(HeapObject* object, BackReference reference);
+  void PutBackReference(HeapObject* object, SerializerReference reference);
+
+  void PutAttachedReference(SerializerReference reference,
+                            HowToCode how_to_code, WhereToPoint where_to_point);
 
   // Emit alignment prefix if necessary, return required padding space in bytes.
   int PutAlignmentPrefix(HeapObject* object);
 
-  // Returns true if the object was successfully serialized.
-  bool SerializeKnownObject(HeapObject* obj, HowToCode how_to_code,
-                            WhereToPoint where_to_point, int skip);
+  // Returns true if the object was successfully serialized as hot object.
+  bool SerializeHotObject(HeapObject* obj, HowToCode how_to_code,
+                          WhereToPoint where_to_point, int skip);
+
+  // Returns true if the object was successfully serialized as back reference.
+  bool SerializeBackReference(HeapObject* obj, HowToCode how_to_code,
+                              WhereToPoint where_to_point, int skip);
 
   inline void FlushSkip(int skip) {
     if (skip != 0) {
-      sink_->Put(kSkip, "SkipFromSerializeObject");
-      sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
+      sink_.Put(kSkip, "SkipFromSerializeObject");
+      sink_.PutInt(skip, "SkipDistanceFromSerializeObject");
     }
   }
 
-  bool BackReferenceIsAlreadyAllocated(BackReference back_reference);
+  bool BackReferenceIsAlreadyAllocated(SerializerReference back_reference);
 
   // This will return the space for an object.
-  BackReference AllocateLargeObject(int size);
-  BackReference Allocate(AllocationSpace space, int size);
+  SerializerReference AllocateLargeObject(int size);
+  SerializerReference Allocate(AllocationSpace space, int size);
   int EncodeExternalReference(Address addr) {
     return external_reference_encoder_.Encode(addr);
   }
@@ -204,10 +212,10 @@
     return max_chunk_size_[space];
   }
 
-  SnapshotByteSink* sink() const { return sink_; }
+  const SnapshotByteSink* sink() const { return &sink_; }
 
   void QueueDeferredObject(HeapObject* obj) {
-    DCHECK(back_reference_map_.Lookup(obj).is_valid());
+    DCHECK(reference_map_.Lookup(obj).is_back_reference());
     deferred_objects_.Add(obj);
   }
 
@@ -215,10 +223,10 @@
 
   Isolate* isolate_;
 
-  SnapshotByteSink* sink_;
+  SnapshotByteSink sink_;
   ExternalReferenceEncoder external_reference_encoder_;
 
-  BackReferenceMap back_reference_map_;
+  SerializerReferenceMap reference_map_;
   RootIndexMap root_index_map_;
 
   int recursion_depth_;
diff --git a/src/snapshot/snapshot-common.cc b/src/snapshot/snapshot-common.cc
index eb3bdb5..5eac4af 100644
--- a/src/snapshot/snapshot-common.cc
+++ b/src/snapshot/snapshot-common.cc
@@ -18,8 +18,7 @@
 
 #ifdef DEBUG
 bool Snapshot::SnapshotIsValid(v8::StartupData* snapshot_blob) {
-  return !Snapshot::ExtractStartupData(snapshot_blob).is_empty() &&
-         !Snapshot::ExtractContextData(snapshot_blob).is_empty();
+  return Snapshot::ExtractNumContexts(snapshot_blob) > 0;
 }
 #endif  // DEBUG
 
@@ -31,12 +30,6 @@
 }
 
 
-bool Snapshot::EmbedsScript(Isolate* isolate) {
-  if (!isolate->snapshot_available()) return false;
-  return ExtractMetadata(isolate->snapshot_blob()).embeds_script();
-}
-
-
 uint32_t Snapshot::SizeOfFirstPage(Isolate* isolate, AllocationSpace space) {
   DCHECK(space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE);
   if (!isolate->snapshot_available()) {
@@ -67,15 +60,16 @@
   return success;
 }
 
-
 MaybeHandle<Context> Snapshot::NewContextFromSnapshot(
-    Isolate* isolate, Handle<JSGlobalProxy> global_proxy) {
+    Isolate* isolate, Handle<JSGlobalProxy> global_proxy,
+    size_t context_index) {
   if (!isolate->snapshot_available()) return Handle<Context>();
   base::ElapsedTimer timer;
   if (FLAG_profile_deserialization) timer.Start();
 
   const v8::StartupData* blob = isolate->snapshot_blob();
-  Vector<const byte> context_data = ExtractContextData(blob);
+  Vector<const byte> context_data =
+      ExtractContextData(blob, static_cast<int>(context_index));
   SnapshotData snapshot_data(context_data);
   Deserializer deserializer(&snapshot_data);
 
@@ -87,177 +81,192 @@
   if (FLAG_profile_deserialization) {
     double ms = timer.Elapsed().InMillisecondsF();
     int bytes = context_data.length();
-    PrintF("[Deserializing context (%d bytes) took %0.3f ms]\n", bytes, ms);
+    PrintF("[Deserializing context #%zu (%d bytes) took %0.3f ms]\n",
+           context_index, bytes, ms);
   }
   return Handle<Context>::cast(result);
 }
 
+void UpdateMaxRequirementPerPage(
+    uint32_t* requirements,
+    Vector<const SerializedData::Reservation> reservations) {
+  int space = 0;
+  uint32_t current_requirement = 0;
+  for (const auto& reservation : reservations) {
+    current_requirement += reservation.chunk_size();
+    if (reservation.is_last()) {
+      requirements[space] = std::max(requirements[space], current_requirement);
+      current_requirement = 0;
+      space++;
+    }
+  }
+  DCHECK_EQ(i::Serializer::kNumberOfSpaces, space);
+}
 
-void CalculateFirstPageSizes(bool is_default_snapshot,
-                             const SnapshotData& startup_snapshot,
-                             const SnapshotData& context_snapshot,
+void CalculateFirstPageSizes(const SnapshotData* startup_snapshot,
+                             const List<SnapshotData*>* context_snapshots,
                              uint32_t* sizes_out) {
-  Vector<const SerializedData::Reservation> startup_reservations =
-      startup_snapshot.Reservations();
-  Vector<const SerializedData::Reservation> context_reservations =
-      context_snapshot.Reservations();
-  int startup_index = 0;
-  int context_index = 0;
-
   if (FLAG_profile_deserialization) {
     int startup_total = 0;
-    int context_total = 0;
-    for (auto& reservation : startup_reservations) {
+    PrintF("Deserialization will reserve:\n");
+    for (const auto& reservation : startup_snapshot->Reservations()) {
       startup_total += reservation.chunk_size();
     }
-    for (auto& reservation : context_reservations) {
-      context_total += reservation.chunk_size();
+    PrintF("%10d bytes per isolate\n", startup_total);
+    for (int i = 0; i < context_snapshots->length(); i++) {
+      int context_total = 0;
+      for (const auto& reservation : context_snapshots->at(i)->Reservations()) {
+        context_total += reservation.chunk_size();
+      }
+      PrintF("%10d bytes per context #%d\n", context_total, i);
     }
-    PrintF(
-        "Deserialization will reserve:\n"
-        "%10d bytes per isolate\n"
-        "%10d bytes per context\n",
-        startup_total, context_total);
+  }
+
+  uint32_t startup_requirements[i::Serializer::kNumberOfSpaces];
+  uint32_t context_requirements[i::Serializer::kNumberOfSpaces];
+  for (int space = 0; space < i::Serializer::kNumberOfSpaces; space++) {
+    startup_requirements[space] = 0;
+    context_requirements[space] = 0;
+  }
+
+  UpdateMaxRequirementPerPage(startup_requirements,
+                              startup_snapshot->Reservations());
+  for (const auto& context_snapshot : *context_snapshots) {
+    UpdateMaxRequirementPerPage(context_requirements,
+                                context_snapshot->Reservations());
   }
 
   for (int space = 0; space < i::Serializer::kNumberOfSpaces; space++) {
-    bool single_chunk = true;
-    while (!startup_reservations[startup_index].is_last()) {
-      single_chunk = false;
-      startup_index++;
-    }
-    while (!context_reservations[context_index].is_last()) {
-      single_chunk = false;
-      context_index++;
-    }
-
-    uint32_t required = kMaxUInt32;
-    if (single_chunk) {
-      // If both the startup snapshot data and the context snapshot data on
-      // this space fit in a single page, then we consider limiting the size
-      // of the first page. For this, we add the chunk sizes and some extra
-      // allowance. This way we achieve a smaller startup memory footprint.
-      required = (startup_reservations[startup_index].chunk_size() +
-                  2 * context_reservations[context_index].chunk_size()) +
-                 Page::kObjectStartOffset;
-      // Add a small allowance to the code space for small scripts.
-      if (space == CODE_SPACE) required += 32 * KB;
-    } else {
-      // We expect the vanilla snapshot to only require on page per space.
-      DCHECK(!is_default_snapshot);
-    }
+    // If the space requirement for a page is less than a page size, we consider
+    // limiting the size of the first page in order to save memory on startup.
+    uint32_t required = startup_requirements[space] +
+                        2 * context_requirements[space] +
+                        Page::kObjectStartOffset;
+    // Add a small allowance to the code space for small scripts.
+    if (space == CODE_SPACE) required += 32 * KB;
 
     if (space >= FIRST_PAGED_SPACE && space <= LAST_PAGED_SPACE) {
       uint32_t max_size =
           MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(space));
-      sizes_out[space - FIRST_PAGED_SPACE] = Min(required, max_size);
-    } else {
-      DCHECK(single_chunk);
+      sizes_out[space - FIRST_PAGED_SPACE] = std::min(required, max_size);
     }
-    startup_index++;
-    context_index++;
   }
-
-  DCHECK_EQ(startup_reservations.length(), startup_index);
-  DCHECK_EQ(context_reservations.length(), context_index);
 }
 
-
 v8::StartupData Snapshot::CreateSnapshotBlob(
-    const i::StartupSerializer& startup_ser,
-    const i::PartialSerializer& context_ser, Snapshot::Metadata metadata) {
-  SnapshotData startup_snapshot(startup_ser);
-  SnapshotData context_snapshot(context_ser);
-  Vector<const byte> startup_data = startup_snapshot.RawData();
-  Vector<const byte> context_data = context_snapshot.RawData();
+    const SnapshotData* startup_snapshot,
+    const List<SnapshotData*>* context_snapshots) {
+  int num_contexts = context_snapshots->length();
+  int startup_snapshot_offset = StartupSnapshotOffset(num_contexts);
+  int total_length = startup_snapshot_offset;
+  total_length += startup_snapshot->RawData().length();
+  for (const auto& context_snapshot : *context_snapshots) {
+    total_length += context_snapshot->RawData().length();
+  }
 
   uint32_t first_page_sizes[kNumPagedSpaces];
+  CalculateFirstPageSizes(startup_snapshot, context_snapshots,
+                          first_page_sizes);
 
-  CalculateFirstPageSizes(!metadata.embeds_script(), startup_snapshot,
-                          context_snapshot, first_page_sizes);
-
-  int startup_length = startup_data.length();
-  int context_length = context_data.length();
-  int context_offset = ContextOffset(startup_length);
-
-  int length = context_offset + context_length;
-  char* data = new char[length];
-
-  memcpy(data + kMetadataOffset, &metadata.RawValue(), kInt32Size);
+  char* data = new char[total_length];
   memcpy(data + kFirstPageSizesOffset, first_page_sizes,
          kNumPagedSpaces * kInt32Size);
-  memcpy(data + kStartupLengthOffset, &startup_length, kInt32Size);
-  memcpy(data + kStartupDataOffset, startup_data.begin(), startup_length);
-  memcpy(data + context_offset, context_data.begin(), context_length);
-  v8::StartupData result = {data, length};
-
+  memcpy(data + kNumberOfContextsOffset, &num_contexts, kInt32Size);
+  int payload_offset = StartupSnapshotOffset(num_contexts);
+  int payload_length = startup_snapshot->RawData().length();
+  memcpy(data + payload_offset, startup_snapshot->RawData().start(),
+         payload_length);
   if (FLAG_profile_deserialization) {
-    PrintF(
-        "Snapshot blob consists of:\n"
-        "%10d bytes for startup\n"
-        "%10d bytes for context\n",
-        startup_length, context_length);
+    PrintF("Snapshot blob consists of:\n%10d bytes for startup\n",
+           payload_length);
   }
+  payload_offset += payload_length;
+  for (int i = 0; i < num_contexts; i++) {
+    memcpy(data + ContextSnapshotOffsetOffset(i), &payload_offset, kInt32Size);
+    SnapshotData* context_snapshot = context_snapshots->at(i);
+    payload_length = context_snapshot->RawData().length();
+    memcpy(data + payload_offset, context_snapshot->RawData().start(),
+           payload_length);
+    if (FLAG_profile_deserialization) {
+      PrintF("%10d bytes for context #%d\n", payload_length, i);
+    }
+    payload_offset += payload_length;
+  }
+
+  v8::StartupData result = {data, total_length};
   return result;
 }
 
-
-Snapshot::Metadata Snapshot::ExtractMetadata(const v8::StartupData* data) {
-  uint32_t raw;
-  memcpy(&raw, data->data + kMetadataOffset, kInt32Size);
-  return Metadata(raw);
+int Snapshot::ExtractNumContexts(const v8::StartupData* data) {
+  CHECK_LT(kNumberOfContextsOffset, data->raw_size);
+  int num_contexts;
+  memcpy(&num_contexts, data->data + kNumberOfContextsOffset, kInt32Size);
+  return num_contexts;
 }
 
-
 Vector<const byte> Snapshot::ExtractStartupData(const v8::StartupData* data) {
-  DCHECK_LT(kIntSize, data->raw_size);
-  int startup_length;
-  memcpy(&startup_length, data->data + kStartupLengthOffset, kInt32Size);
-  DCHECK_LT(startup_length, data->raw_size);
+  int num_contexts = ExtractNumContexts(data);
+  int startup_offset = StartupSnapshotOffset(num_contexts);
+  CHECK_LT(startup_offset, data->raw_size);
+  int first_context_offset;
+  memcpy(&first_context_offset, data->data + ContextSnapshotOffsetOffset(0),
+         kInt32Size);
+  CHECK_LT(first_context_offset, data->raw_size);
+  int startup_length = first_context_offset - startup_offset;
   const byte* startup_data =
-      reinterpret_cast<const byte*>(data->data + kStartupDataOffset);
+      reinterpret_cast<const byte*>(data->data + startup_offset);
   return Vector<const byte>(startup_data, startup_length);
 }
 
+Vector<const byte> Snapshot::ExtractContextData(const v8::StartupData* data,
+                                                int index) {
+  int num_contexts = ExtractNumContexts(data);
+  CHECK_LT(index, num_contexts);
 
-Vector<const byte> Snapshot::ExtractContextData(const v8::StartupData* data) {
-  DCHECK_LT(kIntSize, data->raw_size);
-  int startup_length;
-  memcpy(&startup_length, data->data + kStartupLengthOffset, kIntSize);
-  int context_offset = ContextOffset(startup_length);
+  int context_offset;
+  memcpy(&context_offset, data->data + ContextSnapshotOffsetOffset(index),
+         kInt32Size);
+  int next_context_offset;
+  if (index == num_contexts - 1) {
+    next_context_offset = data->raw_size;
+  } else {
+    memcpy(&next_context_offset,
+           data->data + ContextSnapshotOffsetOffset(index + 1), kInt32Size);
+    CHECK_LT(next_context_offset, data->raw_size);
+  }
+
   const byte* context_data =
       reinterpret_cast<const byte*>(data->data + context_offset);
-  DCHECK_LT(context_offset, data->raw_size);
-  int context_length = data->raw_size - context_offset;
+  int context_length = next_context_offset - context_offset;
   return Vector<const byte>(context_data, context_length);
 }
 
-SnapshotData::SnapshotData(const Serializer& ser) {
+SnapshotData::SnapshotData(const Serializer* serializer) {
   DisallowHeapAllocation no_gc;
   List<Reservation> reservations;
-  ser.EncodeReservations(&reservations);
-  const List<byte>& payload = ser.sink()->data();
+  serializer->EncodeReservations(&reservations);
+  const List<byte>* payload = serializer->sink()->data();
 
   // Calculate sizes.
   int reservation_size = reservations.length() * kInt32Size;
-  int size = kHeaderSize + reservation_size + payload.length();
+  int size = kHeaderSize + reservation_size + payload->length();
 
   // Allocate backing store and create result data.
   AllocateData(size);
 
   // Set header values.
-  SetMagicNumber(ser.isolate());
+  SetMagicNumber(serializer->isolate());
   SetHeaderValue(kCheckSumOffset, Version::Hash());
   SetHeaderValue(kNumReservationsOffset, reservations.length());
-  SetHeaderValue(kPayloadLengthOffset, payload.length());
+  SetHeaderValue(kPayloadLengthOffset, payload->length());
 
   // Copy reservation chunk sizes.
   CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()),
             reservation_size);
 
   // Copy serialized data.
-  CopyBytes(data_ + kHeaderSize + reservation_size, payload.begin(),
-            static_cast<size_t>(payload.length()));
+  CopyBytes(data_ + kHeaderSize + reservation_size, payload->begin(),
+            static_cast<size_t>(payload->length()));
 }
 
 bool SnapshotData::IsSane() {
diff --git a/src/snapshot/snapshot-source-sink.h b/src/snapshot/snapshot-source-sink.h
index 360ec76..5d4c08d 100644
--- a/src/snapshot/snapshot-source-sink.h
+++ b/src/snapshot/snapshot-source-sink.h
@@ -94,7 +94,7 @@
   void PutRaw(const byte* data, int number_of_bytes, const char* description);
   int Position() { return data_.length(); }
 
-  const List<byte>& data() const { return data_; }
+  const List<byte>* data() const { return &data_; }
 
  private:
   List<byte> data_;
diff --git a/src/snapshot/snapshot.h b/src/snapshot/snapshot.h
index c648d75..e332967 100644
--- a/src/snapshot/snapshot.h
+++ b/src/snapshot/snapshot.h
@@ -16,84 +16,11 @@
 class PartialSerializer;
 class StartupSerializer;
 
-class Snapshot : public AllStatic {
- public:
-  class Metadata {
-   public:
-    explicit Metadata(uint32_t data = 0) : data_(data) {}
-    bool embeds_script() { return EmbedsScriptBits::decode(data_); }
-    void set_embeds_script(bool v) {
-      data_ = EmbedsScriptBits::update(data_, v);
-    }
-
-    uint32_t& RawValue() { return data_; }
-
-   private:
-    class EmbedsScriptBits : public BitField<bool, 0, 1> {};
-    uint32_t data_;
-  };
-
-  // Initialize the Isolate from the internal snapshot. Returns false if no
-  // snapshot could be found.
-  static bool Initialize(Isolate* isolate);
-  // Create a new context using the internal partial snapshot.
-  static MaybeHandle<Context> NewContextFromSnapshot(
-      Isolate* isolate, Handle<JSGlobalProxy> global_proxy);
-
-  static bool HaveASnapshotToStartFrom(Isolate* isolate);
-
-  static bool EmbedsScript(Isolate* isolate);
-
-  static uint32_t SizeOfFirstPage(Isolate* isolate, AllocationSpace space);
-
-
-  // To be implemented by the snapshot source.
-  static const v8::StartupData* DefaultSnapshotBlob();
-
-  static v8::StartupData CreateSnapshotBlob(
-      const StartupSerializer& startup_ser,
-      const PartialSerializer& context_ser, Snapshot::Metadata metadata);
-
-#ifdef DEBUG
-  static bool SnapshotIsValid(v8::StartupData* snapshot_blob);
-#endif  // DEBUG
-
- private:
-  static Vector<const byte> ExtractStartupData(const v8::StartupData* data);
-  static Vector<const byte> ExtractContextData(const v8::StartupData* data);
-  static Metadata ExtractMetadata(const v8::StartupData* data);
-
-  // Snapshot blob layout:
-  // [0] metadata
-  // [1 - 6] pre-calculated first page sizes for paged spaces
-  // [7] serialized start up data length
-  // ... serialized start up data
-  // ... serialized context data
-
-  static const int kNumPagedSpaces = LAST_PAGED_SPACE - FIRST_PAGED_SPACE + 1;
-
-  static const int kMetadataOffset = 0;
-  static const int kFirstPageSizesOffset = kMetadataOffset + kInt32Size;
-  static const int kStartupLengthOffset =
-      kFirstPageSizesOffset + kNumPagedSpaces * kInt32Size;
-  static const int kStartupDataOffset = kStartupLengthOffset + kInt32Size;
-
-  static int ContextOffset(int startup_length) {
-    return kStartupDataOffset + startup_length;
-  }
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(Snapshot);
-};
-
-#ifdef V8_USE_EXTERNAL_STARTUP_DATA
-void SetSnapshotFromFile(StartupData* snapshot_blob);
-#endif
-
 // Wrapper around reservation sizes and the serialization payload.
 class SnapshotData : public SerializedData {
  public:
   // Used when producing.
-  explicit SnapshotData(const Serializer& ser);
+  explicit SnapshotData(const Serializer* serializer);
 
   // Used when consuming.
   explicit SnapshotData(const Vector<const byte> snapshot)
@@ -124,6 +51,74 @@
   static const int kHeaderSize = kPayloadLengthOffset + kInt32Size;
 };
 
+class Snapshot : public AllStatic {
+ public:
+  // Initialize the Isolate from the internal snapshot. Returns false if no
+  // snapshot could be found.
+  static bool Initialize(Isolate* isolate);
+  // Create a new context using the internal partial snapshot.
+  static MaybeHandle<Context> NewContextFromSnapshot(
+      Isolate* isolate, Handle<JSGlobalProxy> global_proxy,
+      size_t context_index);
+
+  static bool HaveASnapshotToStartFrom(Isolate* isolate);
+
+  static bool EmbedsScript(Isolate* isolate);
+
+  static uint32_t SizeOfFirstPage(Isolate* isolate, AllocationSpace space);
+
+
+  // To be implemented by the snapshot source.
+  static const v8::StartupData* DefaultSnapshotBlob();
+
+  static v8::StartupData CreateSnapshotBlob(
+      const SnapshotData* startup_snapshot,
+      const List<SnapshotData*>* context_snapshots);
+
+#ifdef DEBUG
+  static bool SnapshotIsValid(v8::StartupData* snapshot_blob);
+#endif  // DEBUG
+
+ private:
+  static int ExtractNumContexts(const v8::StartupData* data);
+  static Vector<const byte> ExtractStartupData(const v8::StartupData* data);
+  static Vector<const byte> ExtractContextData(const v8::StartupData* data,
+                                               int index);
+
+  // Snapshot blob layout:
+  // [0 - 5] pre-calculated first page sizes for paged spaces
+  // [6] number of contexts N
+  // [7] offset to context 0
+  // [8] offset to context 1
+  // ...
+  // ... offset to context N - 1
+  // ... startup snapshot data
+  // ... context 0 snapshot data
+  // ... context 1 snapshot data
+
+  static const int kNumPagedSpaces = LAST_PAGED_SPACE - FIRST_PAGED_SPACE + 1;
+
+  static const int kFirstPageSizesOffset = 0;
+  static const int kNumberOfContextsOffset =
+      kFirstPageSizesOffset + kNumPagedSpaces * kInt32Size;
+  static const int kFirstContextOffsetOffset =
+      kNumberOfContextsOffset + kInt32Size;
+
+  static int StartupSnapshotOffset(int num_contexts) {
+    return kFirstContextOffsetOffset + num_contexts * kInt32Size;
+  }
+
+  static int ContextSnapshotOffsetOffset(int index) {
+    return kFirstContextOffsetOffset + index * kInt32Size;
+  }
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Snapshot);
+};
+
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+void SetSnapshotFromFile(StartupData* snapshot_blob);
+#endif
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/snapshot/startup-serializer.cc b/src/snapshot/startup-serializer.cc
index fab01f5..80598e8 100644
--- a/src/snapshot/startup-serializer.cc
+++ b/src/snapshot/startup-serializer.cc
@@ -11,10 +11,11 @@
 namespace internal {
 
 StartupSerializer::StartupSerializer(
-    Isolate* isolate, SnapshotByteSink* sink,
-    FunctionCodeHandling function_code_handling)
-    : Serializer(isolate, sink),
-      function_code_handling_(function_code_handling),
+    Isolate* isolate,
+    v8::SnapshotCreator::FunctionCodeHandling function_code_handling)
+    : Serializer(isolate),
+      clear_function_code_(function_code_handling ==
+                           v8::SnapshotCreator::FunctionCodeHandling::kClear),
       serializing_builtins_(false) {
   InitializeCodeAddressMap();
 }
@@ -27,21 +28,21 @@
                                         WhereToPoint where_to_point, int skip) {
   DCHECK(!obj->IsJSFunction());
 
-  if (function_code_handling_ == CLEAR_FUNCTION_CODE) {
+  if (clear_function_code_) {
     if (obj->IsCode()) {
       Code* code = Code::cast(obj);
       // If the function code is compiled (either as native code or bytecode),
       // replace it with lazy-compile builtin. Only exception is when we are
       // serializing the canonical interpreter-entry-trampoline builtin.
       if (code->kind() == Code::FUNCTION ||
-          (!serializing_builtins_ && code->is_interpreter_entry_trampoline())) {
+          (!serializing_builtins_ &&
+           code->is_interpreter_trampoline_builtin())) {
         obj = isolate()->builtins()->builtin(Builtins::kCompileLazy);
       }
     } else if (obj->IsBytecodeArray()) {
       obj = isolate()->heap()->undefined_value();
     }
   } else if (obj->IsCode()) {
-    DCHECK_EQ(KEEP_FUNCTION_CODE, function_code_handling_);
     Code* code = Code::cast(obj);
     if (code->kind() == Code::FUNCTION) {
       code->ClearInlineCaches();
@@ -49,6 +50,8 @@
     }
   }
 
+  if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return;
+
   int root_index = root_index_map_.Lookup(obj);
   // We can only encode roots as such if it has already been serialized.
   // That applies to root indices below the wave front.
@@ -59,12 +62,12 @@
     }
   }
 
-  if (SerializeKnownObject(obj, how_to_code, where_to_point, skip)) return;
+  if (SerializeBackReference(obj, how_to_code, where_to_point, skip)) return;
 
   FlushSkip(skip);
 
   // Object has not yet been serialized.  Serialize it here.
-  ObjectSerializer object_serializer(this, obj, sink_, how_to_code,
+  ObjectSerializer object_serializer(this, obj, &sink_, how_to_code,
                                      where_to_point);
   object_serializer.Serialize();
 
@@ -73,8 +76,8 @@
     // Make sure that the immortal immovable root has been included in the first
     // chunk of its reserved space , so that it is deserialized onto the first
     // page of its space and stays immortal immovable.
-    BackReference ref = back_reference_map_.Lookup(obj);
-    CHECK(ref.is_valid() && ref.chunk_index() == 0);
+    SerializerReference ref = reference_map_.Lookup(obj);
+    CHECK(ref.is_back_reference() && ref.chunk_index() == 0);
   }
 }
 
@@ -89,11 +92,22 @@
   Pad();
 }
 
+int StartupSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) {
+  int index;
+  if (!partial_cache_index_map_.LookupOrInsert(heap_object, &index)) {
+    // This object is not part of the partial snapshot cache yet. Add it to the
+    // startup snapshot so we can refer to it via partial snapshot index from
+    // the partial snapshot.
+    VisitPointer(reinterpret_cast<Object**>(&heap_object));
+  }
+  return index;
+}
+
 void StartupSerializer::Synchronize(VisitorSynchronization::SyncTag tag) {
   // We expect the builtins tag after builtins have been serialized.
   DCHECK(!serializing_builtins_ || tag == VisitorSynchronization::kBuiltins);
   serializing_builtins_ = (tag == VisitorSynchronization::kHandleScope);
-  sink_->Put(kSynchronize, "Synchronize");
+  sink_.Put(kSynchronize, "Synchronize");
 }
 
 void StartupSerializer::SerializeStrongReferences() {
diff --git a/src/snapshot/startup-serializer.h b/src/snapshot/startup-serializer.h
index 71b8475..cc66f71 100644
--- a/src/snapshot/startup-serializer.h
+++ b/src/snapshot/startup-serializer.h
@@ -6,6 +6,7 @@
 #define V8_SNAPSHOT_STARTUP_SERIALIZER_H_
 
 #include <bitset>
+#include "include/v8.h"
 #include "src/snapshot/serializer.h"
 
 namespace v8 {
@@ -13,11 +14,9 @@
 
 class StartupSerializer : public Serializer {
  public:
-  enum FunctionCodeHandling { CLEAR_FUNCTION_CODE, KEEP_FUNCTION_CODE };
-
   StartupSerializer(
-      Isolate* isolate, SnapshotByteSink* sink,
-      FunctionCodeHandling function_code_handling = CLEAR_FUNCTION_CODE);
+      Isolate* isolate,
+      v8::SnapshotCreator::FunctionCodeHandling function_code_handling);
   ~StartupSerializer() override;
 
   // Serialize the current state of the heap.  The order is:
@@ -28,7 +27,34 @@
   void SerializeStrongReferences();
   void SerializeWeakReferencesAndDeferred();
 
+  int PartialSnapshotCacheIndex(HeapObject* o);
+
  private:
+  class PartialCacheIndexMap : public AddressMapBase {
+   public:
+    PartialCacheIndexMap()
+        : map_(base::HashMap::PointersMatch), next_index_(0) {}
+
+    // Lookup object in the map. Return its index if found, or create
+    // a new entry with new_index as value, and return kInvalidIndex.
+    bool LookupOrInsert(HeapObject* obj, int* index_out) {
+      base::HashMap::Entry* entry = LookupEntry(&map_, obj, false);
+      if (entry != NULL) {
+        *index_out = GetValue(entry);
+        return true;
+      }
+      *index_out = next_index_;
+      SetValue(LookupEntry(&map_, obj, true), next_index_++);
+      return false;
+    }
+
+   private:
+    base::HashMap map_;
+    int next_index_;
+
+    DISALLOW_COPY_AND_ASSIGN(PartialCacheIndexMap);
+  };
+
   // The StartupSerializer has to serialize the root array, which is slightly
   // different.
   void VisitPointers(Object** start, Object** end) override;
@@ -42,10 +68,11 @@
   // roots. In the second pass, we serialize the rest.
   bool RootShouldBeSkipped(int root_index);
 
-  FunctionCodeHandling function_code_handling_;
+  bool clear_function_code_;
   bool serializing_builtins_;
   bool serializing_immortal_immovables_roots_;
   std::bitset<Heap::kStrongRootListLength> root_has_been_serialized_;
+  PartialCacheIndexMap partial_cache_index_map_;
   DISALLOW_COPY_AND_ASSIGN(StartupSerializer);
 };
 
diff --git a/src/startup-data-util.cc b/src/startup-data-util.cc
index e20ec21..7c6d9eb 100644
--- a/src/startup-data-util.cc
+++ b/src/startup-data-util.cc
@@ -7,9 +7,9 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "src/base/file-utils.h"
 #include "src/base/logging.h"
 #include "src/base/platform/platform.h"
-#include "src/flags.h"
 #include "src/utils.h"
 
 
@@ -78,27 +78,6 @@
   atexit(&FreeStartupData);
 }
 
-
-char* RelativePath(char** buffer, const char* exec_path, const char* name) {
-  DCHECK(exec_path);
-  int path_separator = static_cast<int>(strlen(exec_path)) - 1;
-  while (path_separator >= 0 &&
-         !base::OS::isDirectorySeparator(exec_path[path_separator])) {
-    path_separator--;
-  }
-  if (path_separator >= 0) {
-    int name_length = static_cast<int>(strlen(name));
-    *buffer =
-        reinterpret_cast<char*>(calloc(path_separator + name_length + 2, 1));
-    *buffer[0] = '\0';
-    strncat(*buffer, exec_path, path_separator + 1);
-    strncat(*buffer, name, name_length);
-  } else {
-    *buffer = strdup(name);
-  }
-  return *buffer;
-}
-
 }  // namespace
 #endif  // V8_USE_EXTERNAL_STARTUP_DATA
 
@@ -108,9 +87,7 @@
   char* natives;
   char* snapshot;
   LoadFromFiles(RelativePath(&natives, directory_path, "natives_blob.bin"),
-                RelativePath(&snapshot, directory_path,
-                             FLAG_ignition ? "snapshot_blob_ignition.bin"
-                                           : "snapshot_blob.bin"));
+                RelativePath(&snapshot, directory_path, "snapshot_blob.bin"));
   free(natives);
   free(snapshot);
 #endif  // V8_USE_EXTERNAL_STARTUP_DATA
diff --git a/src/string-builder.h b/src/string-builder.h
index 98bd82b..192603f 100644
--- a/src/string-builder.h
+++ b/src/string-builder.h
@@ -293,6 +293,14 @@
     }
   }
 
+  INLINE(void AppendCString(const uc16* s)) {
+    if (encoding_ == String::ONE_BYTE_ENCODING) {
+      while (*s != '\0') Append<uc16, uint8_t>(*(s++));
+    } else {
+      while (*s != '\0') Append<uc16, uc16>(*(s++));
+    }
+  }
+
   INLINE(bool CurrentPartCanFit(int length)) {
     return part_length_ - current_index_ > length;
   }
@@ -301,6 +309,8 @@
 
   MaybeHandle<String> Finish();
 
+  INLINE(bool HasOverflowed()) const { return overflowed_; }
+
   // Change encoding to two-byte.
   void ChangeEncoding() {
     DCHECK_EQ(String::ONE_BYTE_ENCODING, encoding_);
diff --git a/src/string-stream.cc b/src/string-stream.cc
index 02f6f1c..781f8cd 100644
--- a/src/string-stream.cc
+++ b/src/string-stream.cc
@@ -378,14 +378,14 @@
 
 
 void StringStream::PrintFixedArray(FixedArray* array, unsigned int limit) {
-  Heap* heap = array->GetHeap();
+  Isolate* isolate = array->GetIsolate();
   for (unsigned int i = 0; i < 10 && i < limit; i++) {
     Object* element = array->get(i);
-    if (element != heap->the_hole_value()) {
-      for (int len = 1; len < 18; len++)
-        Put(' ');
-      Add("%d: %o\n", i, array->get(i));
+    if (element->IsTheHole(isolate)) continue;
+    for (int len = 1; len < 18; len++) {
+      Put(' ');
     }
+    Add("%d: %o\n", i, array->get(i));
   }
   if (limit >= 10) {
     Add("                  ...\n");
@@ -527,19 +527,20 @@
   Object* name = fun->shared()->name();
   bool print_name = false;
   Isolate* isolate = fun->GetIsolate();
-  if (receiver->IsNull() || receiver->IsUndefined() || receiver->IsJSProxy()) {
+  if (receiver->IsNull(isolate) || receiver->IsUndefined(isolate) ||
+      receiver->IsTheHole(isolate) || receiver->IsJSProxy()) {
     print_name = true;
-  } else {
+  } else if (isolate->context() != nullptr) {
     if (!receiver->IsJSObject()) {
       receiver = receiver->GetRootMap(isolate)->prototype();
     }
 
     for (PrototypeIterator iter(isolate, JSObject::cast(receiver),
-                                PrototypeIterator::START_AT_RECEIVER);
+                                kStartAtReceiver);
          !iter.IsAtEnd(); iter.Advance()) {
       if (iter.GetCurrent()->IsJSProxy()) break;
       Object* key = iter.GetCurrent<JSObject>()->SlowReverseLookup(fun);
-      if (!key->IsUndefined()) {
+      if (!key->IsUndefined(isolate)) {
         if (!name->IsString() ||
             !key->IsString() ||
             !String::cast(name)->Equals(String::cast(key))) {
diff --git a/src/third_party/fdlibm/fdlibm.cc b/src/third_party/fdlibm/fdlibm.cc
deleted file mode 100644
index 0ef2301..0000000
--- a/src/third_party/fdlibm/fdlibm.cc
+++ /dev/null
@@ -1,228 +0,0 @@
-// The following is adapted from fdlibm (http://www.netlib.org/fdlibm).
-//
-// ====================================================
-// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-//
-// Developed at SunSoft, a Sun Microsystems, Inc. business.
-// Permission to use, copy, modify, and distribute this
-// software is freely granted, provided that this notice
-// is preserved.
-// ====================================================
-//
-// The original source code covered by the above license above has been
-// modified significantly by Google Inc.
-// Copyright 2014 the V8 project authors. All rights reserved.
-
-#include "src/third_party/fdlibm/fdlibm.h"
-
-#include <stdint.h>
-#include <cmath>
-#include <limits>
-
-#include "src/base/macros.h"
-#include "src/double.h"
-
-namespace v8 {
-namespace fdlibm {
-
-#ifdef _MSC_VER
-inline double scalbn(double x, int y) { return _scalb(x, y); }
-#endif  // _MSC_VER
-
-
-// Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
-static const int two_over_pi[] = {
-    0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C,
-    0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649,
-    0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, 0xA73EE8, 0x8235F5, 0x2EBB44,
-    0x84E99C, 0x7026B4, 0x5F7E41, 0x3991D6, 0x398353, 0x39F49C, 0x845F8B,
-    0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D,
-    0x367ECF, 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
-    0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, 0x560330,
-    0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 0x91615E, 0xE61B08,
-    0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA,
-    0x73A8C9, 0x60E27B, 0xC08C6B};
-
-static const double zero = 0.0;
-static const double two24 = 1.6777216e+07;
-static const double one = 1.0;
-static const double twon24 = 5.9604644775390625e-08;
-
-static const double PIo2[] = {
-    1.57079625129699707031e+00,  // 0x3FF921FB, 0x40000000
-    7.54978941586159635335e-08,  // 0x3E74442D, 0x00000000
-    5.39030252995776476554e-15,  // 0x3CF84698, 0x80000000
-    3.28200341580791294123e-22,  // 0x3B78CC51, 0x60000000
-    1.27065575308067607349e-29,  // 0x39F01B83, 0x80000000
-    1.22933308981111328932e-36,  // 0x387A2520, 0x40000000
-    2.73370053816464559624e-44,  // 0x36E38222, 0x80000000
-    2.16741683877804819444e-51   // 0x3569F31D, 0x00000000
-};
-
-
-INLINE(int __kernel_rem_pio2(double* x, double* y, int e0, int nx)) {
-  static const int32_t jk = 3;
-  double fw;
-  int32_t jx = nx - 1;
-  int32_t jv = (e0 - 3) / 24;
-  if (jv < 0) jv = 0;
-  int32_t q0 = e0 - 24 * (jv + 1);
-  int32_t m = jx + jk;
-
-  double f[20];
-  for (int i = 0, j = jv - jx; i <= m; i++, j++) {
-    f[i] = (j < 0) ? zero : static_cast<double>(two_over_pi[j]);
-  }
-
-  double q[20];
-  for (int i = 0; i <= jk; i++) {
-    fw = 0.0;
-    for (int j = 0; j <= jx; j++) fw += x[j] * f[jx + i - j];
-    q[i] = fw;
-  }
-
-  int32_t jz = jk;
-
-recompute:
-
-  int32_t iq[20];
-  double z = q[jz];
-  for (int i = 0, j = jz; j > 0; i++, j--) {
-    fw = static_cast<double>(static_cast<int32_t>(twon24 * z));
-    iq[i] = static_cast<int32_t>(z - two24 * fw);
-    z = q[j - 1] + fw;
-  }
-
-  z = scalbn(z, q0);
-  z -= 8.0 * std::floor(z * 0.125);
-  int32_t n = static_cast<int32_t>(z);
-  z -= static_cast<double>(n);
-  int32_t ih = 0;
-  if (q0 > 0) {
-    int32_t i = (iq[jz - 1] >> (24 - q0));
-    n += i;
-    iq[jz - 1] -= i << (24 - q0);
-    ih = iq[jz - 1] >> (23 - q0);
-  } else if (q0 == 0) {
-    ih = iq[jz - 1] >> 23;
-  } else if (z >= 0.5) {
-    ih = 2;
-  }
-
-  if (ih > 0) {
-    n += 1;
-    int32_t carry = 0;
-    for (int i = 0; i < jz; i++) {
-      int32_t j = iq[i];
-      if (carry == 0) {
-        if (j != 0) {
-          carry = 1;
-          iq[i] = 0x1000000 - j;
-        }
-      } else {
-        iq[i] = 0xffffff - j;
-      }
-    }
-    if (q0 == 1) {
-      iq[jz - 1] &= 0x7fffff;
-    } else if (q0 == 2) {
-      iq[jz - 1] &= 0x3fffff;
-    }
-    if (ih == 2) {
-      z = one - z;
-      if (carry != 0) z -= scalbn(one, q0);
-    }
-  }
-
-  if (z == zero) {
-    int32_t j = 0;
-    for (int i = jz - 1; i >= jk; i--) j |= iq[i];
-    if (j == 0) {
-      int32_t k = 1;
-      while (iq[jk - k] == 0) k++;
-      for (int i = jz + 1; i <= jz + k; i++) {
-        f[jx + i] = static_cast<double>(two_over_pi[jv + i]);
-        for (j = 0, fw = 0.0; j <= jx; j++) fw += x[j] * f[jx + i - j];
-        q[i] = fw;
-      }
-      jz += k;
-      goto recompute;
-    }
-  }
-
-  if (z == 0.0) {
-    jz -= 1;
-    q0 -= 24;
-    while (iq[jz] == 0) {
-      jz--;
-      q0 -= 24;
-    }
-  } else {
-    z = scalbn(z, -q0);
-    if (z >= two24) {
-      fw = static_cast<double>(static_cast<int32_t>(twon24 * z));
-      iq[jz] = static_cast<int32_t>(z - two24 * fw);
-      jz += 1;
-      q0 += 24;
-      iq[jz] = static_cast<int32_t>(fw);
-    } else {
-      iq[jz] = static_cast<int32_t>(z);
-    }
-  }
-
-  fw = scalbn(one, q0);
-  for (int i = jz; i >= 0; i--) {
-    q[i] = fw * static_cast<double>(iq[i]);
-    fw *= twon24;
-  }
-
-  double fq[20];
-  for (int i = jz; i >= 0; i--) {
-    fw = 0.0;
-    for (int k = 0; k <= jk && k <= jz - i; k++) fw += PIo2[k] * q[i + k];
-    fq[jz - i] = fw;
-  }
-
-  fw = 0.0;
-  for (int i = jz; i >= 0; i--) fw += fq[i];
-  y[0] = (ih == 0) ? fw : -fw;
-  fw = fq[0] - fw;
-  for (int i = 1; i <= jz; i++) fw += fq[i];
-  y[1] = (ih == 0) ? fw : -fw;
-  return n & 7;
-}
-
-
-int rempio2(double x, double* y) {
-  int32_t hx = static_cast<int32_t>(internal::double_to_uint64(x) >> 32);
-  int32_t ix = hx & 0x7fffffff;
-
-  if (ix >= 0x7ff00000) {
-    *y = std::numeric_limits<double>::quiet_NaN();
-    return 0;
-  }
-
-  int32_t e0 = (ix >> 20) - 1046;
-  uint64_t zi = internal::double_to_uint64(x) & 0xFFFFFFFFu;
-  zi |= static_cast<uint64_t>(ix - (e0 << 20)) << 32;
-  double z = internal::uint64_to_double(zi);
-
-  double tx[3];
-  for (int i = 0; i < 2; i++) {
-    tx[i] = static_cast<double>(static_cast<int32_t>(z));
-    z = (z - tx[i]) * two24;
-  }
-  tx[2] = z;
-
-  int nx = 3;
-  while (tx[nx - 1] == zero) nx--;
-  int n = __kernel_rem_pio2(tx, y, e0, nx);
-  if (hx < 0) {
-    y[0] = -y[0];
-    y[1] = -y[1];
-    return -n;
-  }
-  return n;
-}
-}  // namespace internal
-}  // namespace v8
diff --git a/src/third_party/fdlibm/fdlibm.h b/src/third_party/fdlibm/fdlibm.h
deleted file mode 100644
index e417c8c..0000000
--- a/src/third_party/fdlibm/fdlibm.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// The following is adapted from fdlibm (http://www.netlib.org/fdlibm).
-//
-// ====================================================
-// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-//
-// Developed at SunSoft, a Sun Microsystems, Inc. business.
-// Permission to use, copy, modify, and distribute this
-// software is freely granted, provided that this notice
-// is preserved.
-// ====================================================
-//
-// The original source code covered by the above license above has been
-// modified significantly by Google Inc.
-// Copyright 2014 the V8 project authors. All rights reserved.
-
-#ifndef V8_FDLIBM_H_
-#define V8_FDLIBM_H_
-
-namespace v8 {
-namespace fdlibm {
-
-int rempio2(double x, double* y);
-
-}  // namespace internal
-}  // namespace v8
-
-#endif  // V8_FDLIBM_H_
diff --git a/src/third_party/fdlibm/fdlibm.js b/src/third_party/fdlibm/fdlibm.js
index a5e789f..26ef126 100644
--- a/src/third_party/fdlibm/fdlibm.js
+++ b/src/third_party/fdlibm/fdlibm.js
@@ -16,9 +16,6 @@
 // The following is a straightforward translation of fdlibm routines
 // by Raymond Toy (rtoy@google.com).
 
-// rempio2result is used as a container for return values of %RemPiO2. It is
-// initialized to a two-element Float64Array during genesis.
-
 (function(global, utils) {
   
 "use strict";
@@ -28,735 +25,15 @@
 // -------------------------------------------------------------------
 // Imports
 
-var GlobalFloat64Array = global.Float64Array;
 var GlobalMath = global.Math;
 var MathAbs;
-var MathExp;
-var NaN = %GetRootNaN();
-var rempio2result;
+var MathExpm1;
 
 utils.Import(function(from) {
   MathAbs = from.MathAbs;
-  MathExp = from.MathExp;
+  MathExpm1 = from.MathExpm1;
 });
 
-utils.CreateDoubleResultArray = function(global) {
-  rempio2result = new GlobalFloat64Array(2);
-};
-
-// -------------------------------------------------------------------
-
-define INVPIO2 = 6.36619772367581382433e-01;
-define PIO2_1  = 1.57079632673412561417;
-define PIO2_1T = 6.07710050650619224932e-11;
-define PIO2_2  = 6.07710050630396597660e-11;
-define PIO2_2T = 2.02226624879595063154e-21;
-define PIO2_3  = 2.02226624871116645580e-21;
-define PIO2_3T = 8.47842766036889956997e-32;
-define PIO4    = 7.85398163397448278999e-01;
-define PIO4LO  = 3.06161699786838301793e-17;
-
-// Compute k and r such that x - k*pi/2 = r where |r| < pi/4. For
-// precision, r is returned as two values y0 and y1 such that r = y0 + y1
-// to more than double precision.
-
-macro REMPIO2(X)
-  var n, y0, y1;
-  var hx = %_DoubleHi(X);
-  var ix = hx & 0x7fffffff;
-
-  if (ix < 0x4002d97c) {
-    // |X| ~< 3*pi/4, special case with n = +/- 1
-    if (hx > 0) {
-      var z = X - PIO2_1;
-      if (ix != 0x3ff921fb) {
-        // 33+53 bit pi is good enough
-        y0 = z - PIO2_1T;
-        y1 = (z - y0) - PIO2_1T;
-      } else {
-        // near pi/2, use 33+33+53 bit pi
-        z -= PIO2_2;
-        y0 = z - PIO2_2T;
-        y1 = (z - y0) - PIO2_2T;
-      }
-      n = 1;
-    } else {
-      // Negative X
-      var z = X + PIO2_1;
-      if (ix != 0x3ff921fb) {
-        // 33+53 bit pi is good enough
-        y0 = z + PIO2_1T;
-        y1 = (z - y0) + PIO2_1T;
-      } else {
-        // near pi/2, use 33+33+53 bit pi
-        z += PIO2_2;
-        y0 = z + PIO2_2T;
-        y1 = (z - y0) + PIO2_2T;
-      }
-      n = -1;
-    }
-  } else if (ix <= 0x413921fb) {
-    // |X| ~<= 2^19*(pi/2), medium size
-    var t = MathAbs(X);
-    n = (t * INVPIO2 + 0.5) | 0;
-    var r = t - n * PIO2_1;
-    var w = n * PIO2_1T;
-    // First round good to 85 bit
-    y0 = r - w;
-    if (ix - (%_DoubleHi(y0) & 0x7ff00000) > 0x1000000) {
-      // 2nd iteration needed, good to 118
-      t = r;
-      w = n * PIO2_2;
-      r = t - w;
-      w = n * PIO2_2T - ((t - r) - w);
-      y0 = r - w;
-      if (ix - (%_DoubleHi(y0) & 0x7ff00000) > 0x3100000) {
-        // 3rd iteration needed. 151 bits accuracy
-        t = r;
-        w = n * PIO2_3;
-        r = t - w;
-        w = n * PIO2_3T - ((t - r) - w);
-        y0 = r - w;
-      }
-    }
-    y1 = (r - y0) - w;
-    if (hx < 0) {
-      n = -n;
-      y0 = -y0;
-      y1 = -y1;
-    }
-  } else {
-    // Need to do full Payne-Hanek reduction here.
-    n = %RemPiO2(X, rempio2result);
-    y0 = rempio2result[0];
-    y1 = rempio2result[1];
-  }
-endmacro
-
-
-// __kernel_sin(X, Y, IY)
-// kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854
-// Input X is assumed to be bounded by ~pi/4 in magnitude.
-// Input Y is the tail of X so that x = X + Y.
-//
-// Algorithm
-//  1. Since ieee_sin(-x) = -ieee_sin(x), we need only to consider positive x.
-//  2. ieee_sin(x) is approximated by a polynomial of degree 13 on
-//     [0,pi/4]
-//                           3            13
-//          sin(x) ~ x + S1*x + ... + S6*x
-//     where
-//
-//    |ieee_sin(x)    2     4     6     8     10     12  |     -58
-//    |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x  +S6*x   )| <= 2
-//    |  x                                               |
-//
-//  3. ieee_sin(X+Y) = ieee_sin(X) + sin'(X')*Y
-//              ~ ieee_sin(X) + (1-X*X/2)*Y
-//     For better accuracy, let
-//               3      2      2      2      2
-//          r = X *(S2+X *(S3+X *(S4+X *(S5+X *S6))))
-//     then                   3    2
-//          sin(x) = X + (S1*X + (X *(r-Y/2)+Y))
-//
-define S1 = -1.66666666666666324348e-01;
-define S2 = 8.33333333332248946124e-03;
-define S3 = -1.98412698298579493134e-04;
-define S4 = 2.75573137070700676789e-06;
-define S5 = -2.50507602534068634195e-08;
-define S6 = 1.58969099521155010221e-10;
-
-macro RETURN_KERNELSIN(X, Y, SIGN)
-  var z = X * X;
-  var v = z * X;
-  var r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6)));
-  return (X - ((z * (0.5 * Y - v * r) - Y) - v * S1)) SIGN;
-endmacro
-
-// __kernel_cos(X, Y)
-// kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
-// Input X is assumed to be bounded by ~pi/4 in magnitude.
-// Input Y is the tail of X so that x = X + Y.
-//
-// Algorithm
-//  1. Since ieee_cos(-x) = ieee_cos(x), we need only to consider positive x.
-//  2. ieee_cos(x) is approximated by a polynomial of degree 14 on
-//     [0,pi/4]
-//                                   4            14
-//          cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
-//     where the remez error is
-//
-//  |                   2     4     6     8     10    12     14 |     -58
-//  |ieee_cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x  +C6*x  )| <= 2
-//  |                                                           |
-//
-//                 4     6     8     10    12     14
-//  3. let r = C1*x +C2*x +C3*x +C4*x +C5*x  +C6*x  , then
-//         ieee_cos(x) = 1 - x*x/2 + r
-//     since ieee_cos(X+Y) ~ ieee_cos(X) - ieee_sin(X)*Y
-//                    ~ ieee_cos(X) - X*Y,
-//     a correction term is necessary in ieee_cos(x) and hence
-//         cos(X+Y) = 1 - (X*X/2 - (r - X*Y))
-//     For better accuracy when x > 0.3, let qx = |x|/4 with
-//     the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125.
-//     Then
-//         cos(X+Y) = (1-qx) - ((X*X/2-qx) - (r-X*Y)).
-//     Note that 1-qx and (X*X/2-qx) is EXACT here, and the
-//     magnitude of the latter is at least a quarter of X*X/2,
-//     thus, reducing the rounding error in the subtraction.
-//
-define C1 = 4.16666666666666019037e-02;
-define C2 = -1.38888888888741095749e-03;
-define C3 = 2.48015872894767294178e-05;
-define C4 = -2.75573143513906633035e-07;
-define C5 = 2.08757232129817482790e-09;
-define C6 = -1.13596475577881948265e-11;
-
-macro RETURN_KERNELCOS(X, Y, SIGN)
-  var ix = %_DoubleHi(X) & 0x7fffffff;
-  var z = X * X;
-  var r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6)))));
-  if (ix < 0x3fd33333) {  // |x| ~< 0.3
-    return (1 - (0.5 * z - (z * r - X * Y))) SIGN;
-  } else {
-    var qx;
-    if (ix > 0x3fe90000) {  // |x| > 0.78125
-      qx = 0.28125;
-    } else {
-      qx = %_ConstructDouble(%_DoubleHi(0.25 * X), 0);
-    }
-    var hz = 0.5 * z - qx;
-    return (1 - qx - (hz - (z * r - X * Y))) SIGN;
-  }
-endmacro
-
-
-// kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854
-// Input x is assumed to be bounded by ~pi/4 in magnitude.
-// Input y is the tail of x.
-// Input k indicates whether ieee_tan (if k = 1) or -1/tan (if k = -1)
-// is returned.
-//
-// Algorithm
-//  1. Since ieee_tan(-x) = -ieee_tan(x), we need only to consider positive x.
-//  2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0.
-//  3. ieee_tan(x) is approximated by a odd polynomial of degree 27 on
-//     [0,0.67434]
-//                           3             27
-//          tan(x) ~ x + T1*x + ... + T13*x
-//     where
-//
-//     |ieee_tan(x)    2     4            26   |     -59.2
-//     |----- - (1+T1*x +T2*x +.... +T13*x    )| <= 2
-//     |  x                                    |
-//
-//     Note: ieee_tan(x+y) = ieee_tan(x) + tan'(x)*y
-//                    ~ ieee_tan(x) + (1+x*x)*y
-//     Therefore, for better accuracy in computing ieee_tan(x+y), let
-//               3      2      2       2       2
-//          r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
-//     then
-//                              3    2
-//          tan(x+y) = x + (T1*x + (x *(r+y)+y))
-//
-//  4. For x in [0.67434,pi/4],  let y = pi/4 - x, then
-//          tan(x) = ieee_tan(pi/4-y) = (1-ieee_tan(y))/(1+ieee_tan(y))
-//                 = 1 - 2*(ieee_tan(y) - (ieee_tan(y)^2)/(1+ieee_tan(y)))
-//
-// Set returnTan to 1 for tan; -1 for cot.  Anything else is illegal
-// and will cause incorrect results.
-//
-define T00 = 3.33333333333334091986e-01;
-define T01 = 1.33333333333201242699e-01;
-define T02 = 5.39682539762260521377e-02;
-define T03 = 2.18694882948595424599e-02;
-define T04 = 8.86323982359930005737e-03;
-define T05 = 3.59207910759131235356e-03;
-define T06 = 1.45620945432529025516e-03;
-define T07 = 5.88041240820264096874e-04;
-define T08 = 2.46463134818469906812e-04;
-define T09 = 7.81794442939557092300e-05;
-define T10 = 7.14072491382608190305e-05;
-define T11 = -1.85586374855275456654e-05;
-define T12 = 2.59073051863633712884e-05;
-
-function KernelTan(x, y, returnTan) {
-  var z;
-  var w;
-  var hx = %_DoubleHi(x);
-  var ix = hx & 0x7fffffff;
-
-  if (ix < 0x3e300000) {  // |x| < 2^-28
-    if (((ix | %_DoubleLo(x)) | (returnTan + 1)) == 0) {
-      // x == 0 && returnTan = -1
-      return 1 / MathAbs(x);
-    } else {
-      if (returnTan == 1) {
-        return x;
-      } else {
-        // Compute -1/(x + y) carefully
-        var w = x + y;
-        var z = %_ConstructDouble(%_DoubleHi(w), 0);
-        var v = y - (z - x);
-        var a = -1 / w;
-        var t = %_ConstructDouble(%_DoubleHi(a), 0);
-        var s = 1 + t * z;
-        return t + a * (s + t * v);
-      }
-    }
-  }
-  if (ix >= 0x3fe59428) {  // |x| > .6744
-    if (x < 0) {
-      x = -x;
-      y = -y;
-    }
-    z = PIO4 - x;
-    w = PIO4LO - y;
-    x = z + w;
-    y = 0;
-  }
-  z = x * x;
-  w = z * z;
-
-  // Break x^5 * (T1 + x^2*T2 + ...) into
-  // x^5 * (T1 + x^4*T3 + ... + x^20*T11) +
-  // x^5 * (x^2 * (T2 + x^4*T4 + ... + x^22*T12))
-  var r = T01 + w * (T03 + w * (T05 +
-                w * (T07 + w * (T09 + w * T11))));
-  var v = z * (T02 + w * (T04 + w * (T06 +
-                     w * (T08 + w * (T10 + w * T12)))));
-  var s = z * x;
-  r = y + z * (s * (r + v) + y);
-  r = r + T00 * s;
-  w = x + r;
-  if (ix >= 0x3fe59428) {
-    return (1 - ((hx >> 30) & 2)) *
-      (returnTan - 2.0 * (x - (w * w / (w + returnTan) - r)));
-  }
-  if (returnTan == 1) {
-    return w;
-  } else {
-    z = %_ConstructDouble(%_DoubleHi(w), 0);
-    v = r - (z - x);
-    var a = -1 / w;
-    var t = %_ConstructDouble(%_DoubleHi(a), 0);
-    s = 1 + t * z;
-    return t + a * (s + t * v);
-  }
-}
-
-function MathSinSlow(x) {
-  REMPIO2(x);
-  var sign = 1 - (n & 2);
-  if (n & 1) {
-    RETURN_KERNELCOS(y0, y1, * sign);
-  } else {
-    RETURN_KERNELSIN(y0, y1, * sign);
-  }
-}
-
-function MathCosSlow(x) {
-  REMPIO2(x);
-  if (n & 1) {
-    var sign = (n & 2) - 1;
-    RETURN_KERNELSIN(y0, y1, * sign);
-  } else {
-    var sign = 1 - (n & 2);
-    RETURN_KERNELCOS(y0, y1, * sign);
-  }
-}
-
-// ECMA 262 - 15.8.2.16
-function MathSin(x) {
-  x = +x;  // Convert to number.
-  if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) {
-    // |x| < pi/4, approximately.  No reduction needed.
-    RETURN_KERNELSIN(x, 0, /* empty */);
-  }
-  return +MathSinSlow(x);
-}
-
-// ECMA 262 - 15.8.2.7
-function MathCos(x) {
-  x = +x;  // Convert to number.
-  if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) {
-    // |x| < pi/4, approximately.  No reduction needed.
-    RETURN_KERNELCOS(x, 0, /* empty */);
-  }
-  return +MathCosSlow(x);
-}
-
-// ECMA 262 - 15.8.2.18
-function MathTan(x) {
-  x = x * 1;  // Convert to number.
-  if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) {
-    // |x| < pi/4, approximately.  No reduction needed.
-    return KernelTan(x, 0, 1);
-  }
-  REMPIO2(x);
-  return KernelTan(y0, y1, (n & 1) ? -1 : 1);
-}
-
-// ES6 draft 09-27-13, section 20.2.2.20.
-// Math.log1p
-//
-// Method :                  
-//   1. Argument Reduction: find k and f such that 
-//                      1+x = 2^k * (1+f), 
-//         where  sqrt(2)/2 < 1+f < sqrt(2) .
-//
-//      Note. If k=0, then f=x is exact. However, if k!=0, then f
-//      may not be representable exactly. In that case, a correction
-//      term is need. Let u=1+x rounded. Let c = (1+x)-u, then
-//      log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u),
-//      and add back the correction term c/u.
-//      (Note: when x > 2**53, one can simply return log(x))
-//
-//   2. Approximation of log1p(f).
-//      Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
-//            = 2s + 2/3 s**3 + 2/5 s**5 + .....,
-//            = 2s + s*R
-//      We use a special Reme algorithm on [0,0.1716] to generate 
-//      a polynomial of degree 14 to approximate R The maximum error 
-//      of this polynomial approximation is bounded by 2**-58.45. In
-//      other words,
-//                      2      4      6      8      10      12      14
-//          R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s  +Lp6*s  +Lp7*s
-//      (the values of Lp1 to Lp7 are listed in the program)
-//      and
-//          |      2          14          |     -58.45
-//          | Lp1*s +...+Lp7*s    -  R(z) | <= 2 
-//          |                             |
-//      Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
-//      In order to guarantee error in log below 1ulp, we compute log
-//      by
-//              log1p(f) = f - (hfsq - s*(hfsq+R)).
-//
-//      3. Finally, log1p(x) = k*ln2 + log1p(f).  
-//                           = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
-//         Here ln2 is split into two floating point number: 
-//                      ln2_hi + ln2_lo,
-//         where n*ln2_hi is always exact for |n| < 2000.
-//
-// Special cases:
-//      log1p(x) is NaN with signal if x < -1 (including -INF) ; 
-//      log1p(+INF) is +INF; log1p(-1) is -INF with signal;
-//      log1p(NaN) is that NaN with no signal.
-//
-// Accuracy:
-//      according to an error analysis, the error is always less than
-//      1 ulp (unit in the last place).
-//
-// Constants:
-//      Constants are found in fdlibm.cc. We assume the C++ compiler to convert
-//      from decimal to binary accurately enough to produce the intended values.
-//
-// Note: Assuming log() return accurate answer, the following
-//       algorithm can be used to compute log1p(x) to within a few ULP:
-//
-//              u = 1+x;
-//              if (u==1.0) return x ; else
-//                          return log(u)*(x/(u-1.0));
-//
-//       See HP-15C Advanced Functions Handbook, p.193.
-//
-define LN2_HI    = 6.93147180369123816490e-01;
-define LN2_LO    = 1.90821492927058770002e-10;
-define TWO_THIRD = 6.666666666666666666e-01;
-define LP1 = 6.666666666666735130e-01;
-define LP2 = 3.999999999940941908e-01;
-define LP3 = 2.857142874366239149e-01;
-define LP4 = 2.222219843214978396e-01;
-define LP5 = 1.818357216161805012e-01;
-define LP6 = 1.531383769920937332e-01;
-define LP7 = 1.479819860511658591e-01;
-
-// 2^54
-define TWO54 = 18014398509481984;
-
-function MathLog1p(x) {
-  x = x * 1;  // Convert to number.
-  var hx = %_DoubleHi(x);
-  var ax = hx & 0x7fffffff;
-  var k = 1;
-  var f = x;
-  var hu = 1;
-  var c = 0;
-  var u = x;
-
-  if (hx < 0x3fda827a) {
-    // x < 0.41422
-    if (ax >= 0x3ff00000) {  // |x| >= 1
-      if (x === -1) {
-        return -INFINITY;  // log1p(-1) = -inf
-      } else {
-        return NaN;  // log1p(x<-1) = NaN
-      }
-    } else if (ax < 0x3c900000)  {
-      // For |x| < 2^-54 we can return x.
-      return x;
-    } else if (ax < 0x3e200000) {
-      // For |x| < 2^-29 we can use a simple two-term Taylor series.
-      return x - x * x * 0.5;
-    }
-
-    if ((hx > 0) || (hx <= -0x402D413D)) {  // (int) 0xbfd2bec3 = -0x402d413d
-      // -.2929 < x < 0.41422
-      k = 0;
-    }
-  }
-
-  // Handle Infinity and NaN
-  if (hx >= 0x7ff00000) return x;
-
-  if (k !== 0) {
-    if (hx < 0x43400000) {
-      // x < 2^53
-      u = 1 + x;
-      hu = %_DoubleHi(u);
-      k = (hu >> 20) - 1023;
-      c = (k > 0) ? 1 - (u - x) : x - (u - 1);
-      c = c / u;
-    } else {
-      hu = %_DoubleHi(u);
-      k = (hu >> 20) - 1023;
-    }
-    hu = hu & 0xfffff;
-    if (hu < 0x6a09e) {
-      u = %_ConstructDouble(hu | 0x3ff00000, %_DoubleLo(u));  // Normalize u.
-    } else {
-      ++k;
-      u = %_ConstructDouble(hu | 0x3fe00000, %_DoubleLo(u));  // Normalize u/2.
-      hu = (0x00100000 - hu) >> 2;
-    }
-    f = u - 1;
-  }
-
-  var hfsq = 0.5 * f * f;
-  if (hu === 0) {
-    // |f| < 2^-20;
-    if (f === 0) {
-      if (k === 0) {
-        return 0.0;
-      } else {
-        return k * LN2_HI + (c + k * LN2_LO);
-      }
-    }
-    var R = hfsq * (1 - TWO_THIRD * f);
-    if (k === 0) {
-      return f - R;
-    } else {
-      return k * LN2_HI - ((R - (k * LN2_LO + c)) - f);
-    }
-  }
-
-  var s = f / (2 + f); 
-  var z = s * s;
-  var R = z * (LP1 + z * (LP2 + z * (LP3 + z * (LP4 +
-          z * (LP5 + z * (LP6 + z * LP7))))));
-  if (k === 0) {
-    return f - (hfsq - s * (hfsq + R));
-  } else {
-    return k * LN2_HI - ((hfsq - (s * (hfsq + R) + (k * LN2_LO + c))) - f);
-  }
-}
-
-// ES6 draft 09-27-13, section 20.2.2.14.
-// Math.expm1
-// Returns exp(x)-1, the exponential of x minus 1.
-//
-// Method
-//   1. Argument reduction:
-//      Given x, find r and integer k such that
-//
-//               x = k*ln2 + r,  |r| <= 0.5*ln2 ~ 0.34658  
-//
-//      Here a correction term c will be computed to compensate 
-//      the error in r when rounded to a floating-point number.
-//
-//   2. Approximating expm1(r) by a special rational function on
-//      the interval [0,0.34658]:
-//      Since
-//          r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ...
-//      we define R1(r*r) by
-//          r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r)
-//      That is,
-//          R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r)
-//                   = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r))
-//                   = 1 - r^2/60 + r^4/2520 - r^6/100800 + ...
-//      We use a special Remes algorithm on [0,0.347] to generate 
-//      a polynomial of degree 5 in r*r to approximate R1. The 
-//      maximum error of this polynomial approximation is bounded 
-//      by 2**-61. In other words,
-//          R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5
-//      where   Q1  =  -1.6666666666666567384E-2,
-//              Q2  =   3.9682539681370365873E-4,
-//              Q3  =  -9.9206344733435987357E-6,
-//              Q4  =   2.5051361420808517002E-7,
-//              Q5  =  -6.2843505682382617102E-9;
-//      (where z=r*r, and the values of Q1 to Q5 are listed below)
-//      with error bounded by
-//          |                  5           |     -61
-//          | 1.0+Q1*z+...+Q5*z   -  R1(z) | <= 2 
-//          |                              |
-//
-//      expm1(r) = exp(r)-1 is then computed by the following 
-//      specific way which minimize the accumulation rounding error: 
-//                             2     3
-//                            r     r    [ 3 - (R1 + R1*r/2)  ]
-//            expm1(r) = r + --- + --- * [--------------------]
-//                            2     2    [ 6 - r*(3 - R1*r/2) ]
-//
-//      To compensate the error in the argument reduction, we use
-//              expm1(r+c) = expm1(r) + c + expm1(r)*c 
-//                         ~ expm1(r) + c + r*c 
-//      Thus c+r*c will be added in as the correction terms for
-//      expm1(r+c). Now rearrange the term to avoid optimization 
-//      screw up:
-//                      (      2                                    2 )
-//                      ({  ( r    [ R1 -  (3 - R1*r/2) ]  )  }    r  )
-//       expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- )
-//                      ({  ( 2    [ 6 - r*(3 - R1*r/2) ]  )  }    2  )
-//                      (                                             )
-//
-//                 = r - E
-//   3. Scale back to obtain expm1(x):
-//      From step 1, we have
-//         expm1(x) = either 2^k*[expm1(r)+1] - 1
-//                  = or     2^k*[expm1(r) + (1-2^-k)]
-//   4. Implementation notes:
-//      (A). To save one multiplication, we scale the coefficient Qi
-//           to Qi*2^i, and replace z by (x^2)/2.
-//      (B). To achieve maximum accuracy, we compute expm1(x) by
-//        (i)   if x < -56*ln2, return -1.0, (raise inexact if x!=inf)
-//        (ii)  if k=0, return r-E
-//        (iii) if k=-1, return 0.5*(r-E)-0.5
-//        (iv)  if k=1 if r < -0.25, return 2*((r+0.5)- E)
-//                     else          return  1.0+2.0*(r-E);
-//        (v)   if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1)
-//        (vi)  if k <= 20, return 2^k((1-2^-k)-(E-r)), else
-//        (vii) return 2^k(1-((E+2^-k)-r)) 
-//
-// Special cases:
-//      expm1(INF) is INF, expm1(NaN) is NaN;
-//      expm1(-INF) is -1, and
-//      for finite argument, only expm1(0)=0 is exact.
-//
-// Accuracy:
-//      according to an error analysis, the error is always less than
-//      1 ulp (unit in the last place).
-//
-// Misc. info.
-//      For IEEE double 
-//          if x > 7.09782712893383973096e+02 then expm1(x) overflow
-//
-define KEXPM1_OVERFLOW = 7.09782712893383973096e+02;
-define INVLN2          = 1.44269504088896338700;
-define EXPM1_1 = -3.33333333333331316428e-02;
-define EXPM1_2 = 1.58730158725481460165e-03;
-define EXPM1_3 = -7.93650757867487942473e-05;
-define EXPM1_4 = 4.00821782732936239552e-06;
-define EXPM1_5 = -2.01099218183624371326e-07;
-
-function MathExpm1(x) {
-  x = x * 1;  // Convert to number.
-  var y;
-  var hi;
-  var lo;
-  var k;
-  var t;
-  var c;
-    
-  var hx = %_DoubleHi(x);
-  var xsb = hx & 0x80000000;     // Sign bit of x
-  var y = (xsb === 0) ? x : -x;  // y = |x|
-  hx &= 0x7fffffff;              // High word of |x|
-
-  // Filter out huge and non-finite argument
-  if (hx >= 0x4043687a) {     // if |x| ~=> 56 * ln2
-    if (hx >= 0x40862e42) {   // if |x| >= 709.78
-      if (hx >= 0x7ff00000) {
-        // expm1(inf) = inf; expm1(-inf) = -1; expm1(nan) = nan;
-        return (x === -INFINITY) ? -1 : x;
-      }
-      if (x > KEXPM1_OVERFLOW) return INFINITY;  // Overflow
-    }
-    if (xsb != 0) return -1;  // x < -56 * ln2, return -1.
-  }
-
-  // Argument reduction
-  if (hx > 0x3fd62e42) {    // if |x| > 0.5 * ln2
-    if (hx < 0x3ff0a2b2) {  // and |x| < 1.5 * ln2
-      if (xsb === 0) {
-        hi = x - LN2_HI;
-        lo = LN2_LO;
-        k = 1;
-      } else {
-        hi = x + LN2_HI;
-        lo = -LN2_LO;
-        k = -1;
-      }
-    } else {
-      k = (INVLN2 * x + ((xsb === 0) ? 0.5 : -0.5)) | 0;
-      t = k;
-      // t * ln2_hi is exact here.
-      hi = x - t * LN2_HI;
-      lo = t * LN2_LO;
-    }
-    x = hi - lo;
-    c = (hi - x) - lo;
-  } else if (hx < 0x3c900000)	{
-    // When |x| < 2^-54, we can return x.
-    return x;
-  } else {
-    // Fall through.
-    k = 0;
-  }
-
-  // x is now in primary range
-  var hfx = 0.5 * x;
-  var hxs = x * hfx;
-  var r1 = 1 + hxs * (EXPM1_1 + hxs * (EXPM1_2 + hxs *
-                     (EXPM1_3 + hxs * (EXPM1_4 + hxs * EXPM1_5))));
-  t = 3 - r1 * hfx;
-  var e = hxs * ((r1 - t) / (6 - x * t));
-  if (k === 0) {  // c is 0
-    return x - (x*e - hxs);
-  } else {
-    e = (x * (e - c) - c);
-    e -= hxs;
-    if (k === -1) return 0.5 * (x - e) - 0.5;
-    if (k === 1) {
-      if (x < -0.25) return -2 * (e - (x + 0.5));
-      return 1 + 2 * (x - e);
-    }
-
-    if (k <= -2 || k > 56) {
-      // suffice to return exp(x) + 1
-      y = 1 - (e - x);
-      // Add k to y's exponent
-      y = %_ConstructDouble(%_DoubleHi(y) + (k << 20), %_DoubleLo(y));
-      return y - 1;
-    }
-    if (k < 20) {
-      // t = 1 - 2^k
-      t = %_ConstructDouble(0x3ff00000 - (0x200000 >> k), 0);
-      y = t - (e - x);
-      // Add k to y's exponent
-      y = %_ConstructDouble(%_DoubleHi(y) + (k << 20), %_DoubleLo(y));
-    } else {
-      // t = 2^-k
-      t = %_ConstructDouble((0x3ff - k) << 20, 0);
-      y = x - (e + t);
-      y += 1;
-      // Add k to y's exponent
-      y = %_ConstructDouble(%_DoubleHi(y) + (k << 20), %_DoubleLo(y));
-    }
-  }
-  return y;
-}
-
-
 // ES6 draft 09-27-13, section 20.2.2.30.
 // Math.sinh
 // Method :
@@ -792,11 +69,11 @@
     return h * (t + t / (t + 1));
   }
   // |x| in [22, log(maxdouble)], return 0.5 * exp(|x|)
-  if (ax < LOG_MAXD) return h * MathExp(ax);
+  if (ax < LOG_MAXD) return h * %math_exp(ax);
   // |x| in [log(maxdouble), overflowthreshold]
   // overflowthreshold = 710.4758600739426
   if (ax <= KSINH_OVERFLOW) {
-    var w = MathExp(0.5 * ax);
+    var w = %math_exp(0.5 * ax);
     var t = h * w;
     return t * w;
   }
@@ -842,14 +119,14 @@
   }
   // |x| in [0.5*log2, 22], return (exp(|x|)+1/exp(|x|)/2
   if (ix < 0x40360000) {
-    var t = MathExp(MathAbs(x));
+    var t = %math_exp(MathAbs(x));
     return 0.5 * t + 0.5 / t;
   }
   // |x| in [22, log(maxdouble)], return half*exp(|x|)
-  if (ix < 0x40862e42) return 0.5 * MathExp(MathAbs(x));
+  if (ix < 0x40862e42) return 0.5 * %math_exp(MathAbs(x));
   // |x| in [log(maxdouble), overflowthreshold]
   if (MathAbs(x) <= KCOSH_OVERFLOW) {
-    var w = MathExp(0.5 * MathAbs(x));
+    var w = %math_exp(0.5 * MathAbs(x));
     var t = 0.5 * w;
     return t * w;
   }
@@ -915,203 +192,12 @@
   return (x >= 0) ? z : -z;
 }
 
-// ES6 draft 09-27-13, section 20.2.2.21.
-// Return the base 10 logarithm of x
-//
-// Method :
-//      Let log10_2hi = leading 40 bits of log10(2) and
-//          log10_2lo = log10(2) - log10_2hi,
-//          ivln10   = 1/log(10) rounded.
-//      Then
-//              n = ilogb(x),
-//              if(n<0)  n = n+1;
-//              x = scalbn(x,-n);
-//              log10(x) := n*log10_2hi + (n*log10_2lo + ivln10*log(x))
-//
-// Note 1:
-//      To guarantee log10(10**n)=n, where 10**n is normal, the rounding
-//      mode must set to Round-to-Nearest.
-// Note 2:
-//      [1/log(10)] rounded to 53 bits has error .198 ulps;
-//      log10 is monotonic at all binary break points.
-//
-// Special cases:
-//      log10(x) is NaN if x < 0;
-//      log10(+INF) is +INF; log10(0) is -INF;
-//      log10(NaN) is that NaN;
-//      log10(10**N) = N  for N=0,1,...,22.
-//
-
-define IVLN10 = 4.34294481903251816668e-01;
-define LOG10_2HI = 3.01029995663611771306e-01;
-define LOG10_2LO = 3.69423907715893078616e-13;
-
-function MathLog10(x) {
-  x = x * 1;  // Convert to number.
-  var hx = %_DoubleHi(x);
-  var lx = %_DoubleLo(x);
-  var k = 0;
-
-  if (hx < 0x00100000) {
-    // x < 2^-1022
-    // log10(+/- 0) = -Infinity.
-    if (((hx & 0x7fffffff) | lx) === 0) return -INFINITY;
-    // log10 of negative number is NaN.
-    if (hx < 0) return NaN;
-    // Subnormal number. Scale up x.
-    k -= 54;
-    x *= TWO54;
-    hx = %_DoubleHi(x);
-    lx = %_DoubleLo(x);
-  }
-
-  // Infinity or NaN.
-  if (hx >= 0x7ff00000) return x;
-
-  k += (hx >> 20) - 1023;
-  var i = (k & 0x80000000) >>> 31;
-  hx = (hx & 0x000fffff) | ((0x3ff - i) << 20);
-  var y = k + i;
-  x = %_ConstructDouble(hx, lx);
-
-  var z = y * LOG10_2LO + IVLN10 * %_MathLogRT(x);
-  return z + y * LOG10_2HI;
-}
-
-
-// ES6 draft 09-27-13, section 20.2.2.22.
-// Return the base 2 logarithm of x
-//
-// fdlibm does not have an explicit log2 function, but fdlibm's pow
-// function does implement an accurate log2 function as part of the
-// pow implementation.  This extracts the core parts of that as a
-// separate log2 function.
-
-// Method:
-// Compute log2(x) in two pieces:
-// log2(x) = w1 + w2
-// where w1 has 53-24 = 29 bits of trailing zeroes.
-
-define DP_H = 5.84962487220764160156e-01;
-define DP_L = 1.35003920212974897128e-08;
-
-// Polynomial coefficients for (3/2)*(log2(x) - 2*s - 2/3*s^3)
-define LOG2_1 = 5.99999999999994648725e-01;
-define LOG2_2 = 4.28571428578550184252e-01;
-define LOG2_3 = 3.33333329818377432918e-01;
-define LOG2_4 = 2.72728123808534006489e-01;
-define LOG2_5 = 2.30660745775561754067e-01;
-define LOG2_6 = 2.06975017800338417784e-01;
-
-// cp = 2/(3*ln(2)). Note that cp_h + cp_l is cp, but with more accuracy.
-define CP = 9.61796693925975554329e-01;
-define CP_H = 9.61796700954437255859e-01;
-define CP_L = -7.02846165095275826516e-09;
-// 2^53
-define TWO53 = 9007199254740992; 
-
-function MathLog2(x) {
-  x = x * 1;  // Convert to number.
-  var ax = MathAbs(x);
-  var hx = %_DoubleHi(x);
-  var lx = %_DoubleLo(x);
-  var ix = hx & 0x7fffffff;
-
-  // Handle special cases.
-  // log2(+/- 0) = -Infinity
-  if ((ix | lx) == 0) return -INFINITY;
-
-  // log(x) = NaN, if x < 0
-  if (hx < 0) return NaN;
-
-  // log2(Infinity) = Infinity, log2(NaN) = NaN
-  if (ix >= 0x7ff00000) return x;
-
-  var n = 0;
-
-  // Take care of subnormal number.
-  if (ix < 0x00100000) {
-    ax *= TWO53;
-    n -= 53;
-    ix = %_DoubleHi(ax);
-  }
-
-  n += (ix >> 20) - 0x3ff;
-  var j = ix & 0x000fffff;
-
-  // Determine interval.
-  ix = j | 0x3ff00000;  // normalize ix.
-
-  var bp = 1;
-  var dp_h = 0;
-  var dp_l = 0;
-  if (j > 0x3988e) {  // |x| > sqrt(3/2)
-    if (j < 0xbb67a) {  // |x| < sqrt(3)
-      bp = 1.5;
-      dp_h = DP_H;
-      dp_l = DP_L;
-    } else {
-      n += 1;
-      ix -= 0x00100000;
-    }
-  }
- 
-  ax = %_ConstructDouble(ix, %_DoubleLo(ax));
-
-  // Compute ss = s_h + s_l = (x - 1)/(x+1) or (x - 1.5)/(x + 1.5)
-  var u = ax - bp;
-  var v = 1 / (ax + bp);
-  var ss = u * v;
-  var s_h = %_ConstructDouble(%_DoubleHi(ss), 0);
-
-  // t_h = ax + bp[k] High
-  var t_h = %_ConstructDouble(%_DoubleHi(ax + bp), 0)
-  var t_l = ax - (t_h - bp);
-  var s_l = v * ((u - s_h * t_h) - s_h * t_l);
-
-  // Compute log2(ax)
-  var s2 = ss * ss;
-  var r = s2 * s2 * (LOG2_1 + s2 * (LOG2_2 + s2 * (LOG2_3 + s2 * (
-                     LOG2_4 + s2 * (LOG2_5 + s2 * LOG2_6)))));
-  r += s_l * (s_h + ss);
-  s2  = s_h * s_h;
-  t_h = %_ConstructDouble(%_DoubleHi(3.0 + s2 + r), 0);
-  t_l = r - ((t_h - 3.0) - s2);
-  // u + v = ss * (1 + ...)
-  u = s_h * t_h;
-  v = s_l * t_h + t_l * ss;
-
-  // 2 / (3 * log(2)) * (ss + ...)
-  var p_h = %_ConstructDouble(%_DoubleHi(u + v), 0);
-  var p_l = v - (p_h - u);
-  var z_h = CP_H * p_h;
-  var z_l = CP_L * p_h + p_l * CP + dp_l;
-
-  // log2(ax) = (ss + ...) * 2 / (3 * log(2)) = n + dp_h + z_h + z_l
-  var t = n;
-  var t1 = %_ConstructDouble(%_DoubleHi(((z_h + z_l) + dp_h) + t), 0);
-  var t2 = z_l - (((t1 - t) - dp_h) - z_h);
-
-  // t1 + t2 = log2(ax), sum up because we do not care about extra precision.
-  return t1 + t2;
-}
-
 //-------------------------------------------------------------------
 
 utils.InstallFunctions(GlobalMath, DONT_ENUM, [
-  "cos", MathCos,
-  "sin", MathSin,
-  "tan", MathTan,
   "sinh", MathSinh,
   "cosh", MathCosh,
-  "tanh", MathTanh,
-  "log10", MathLog10,
-  "log2", MathLog2,
-  "log1p", MathLog1p,
-  "expm1", MathExpm1
+  "tanh", MathTanh
 ]);
 
-%SetForceInlineFlag(MathSin);
-%SetForceInlineFlag(MathCos);
-
 })
diff --git a/src/third_party/vtune/v8vtune.gyp b/src/third_party/vtune/v8vtune.gyp
index 6adf365..aaf521f 100644
--- a/src/third_party/vtune/v8vtune.gyp
+++ b/src/third_party/vtune/v8vtune.gyp
@@ -29,13 +29,13 @@
   'variables': {
     'v8_code': 1,
   },
-  'includes': ['../../../build/toolchain.gypi', '../../../build/features.gypi'],
+  'includes': ['../../../gypfiles/toolchain.gypi', '../../../gypfiles/features.gypi'],
   'targets': [
     {
       'target_name': 'v8_vtune',
       'type': 'static_library',
       'dependencies': [
-        '../../../tools/gyp/v8.gyp:v8',
+        '../../v8.gyp:v8',
       ],
       'sources': [
         'ittnotify_config.h',
diff --git a/src/third_party/vtune/vtune-jit.cc b/src/third_party/vtune/vtune-jit.cc
index 30f6196..0bd1954 100644
--- a/src/third_party/vtune/vtune-jit.cc
+++ b/src/third_party/vtune/vtune-jit.cc
@@ -55,26 +55,12 @@
   (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 <stdlib.h>
 #include <string.h>
 
-#ifdef WIN32
-#include <hash_map>
-using namespace std;
-#else
-// To avoid GCC 4.4 compilation warning about hash_map being deprecated.
-#define OLD_DEPRECATED __DEPRECATED
-#undef __DEPRECATED
-#if defined (ANDROID)
-#include <hash_map>
-using namespace std;
-#else
-#include <ext/hash_map>
-using namespace __gnu_cxx;
-#endif
-#define __DEPRECATED OLD_DEPRECATED
-#endif
-
 #include <list>
+#include <unordered_map>
 
 #include "v8-vtune.h"
 #include "vtune-jit.h"
@@ -126,11 +112,8 @@
   }
 };
 
-#ifdef WIN32
-typedef hash_map<void*, void*> JitInfoMap;
-#else
-typedef hash_map<void*, void*, HashForCodeObject, SameCodeObjects> JitInfoMap;
-#endif
+typedef std::unordered_map<void*, void*, HashForCodeObject, SameCodeObjects>
+    JitInfoMap;
 
 static JitInfoMap* GetEntries() {
   static JitInfoMap* entries;
diff --git a/src/transitions-inl.h b/src/transitions-inl.h
index ea02d61..828a673 100644
--- a/src/transitions-inl.h
+++ b/src/transitions-inl.h
@@ -113,8 +113,7 @@
   return name == heap->nonextensible_symbol() ||
          name == heap->sealed_symbol() || name == heap->frozen_symbol() ||
          name == heap->elements_transition_symbol() ||
-         name == heap->strict_function_transition_symbol() ||
-         name == heap->observed_symbol();
+         name == heap->strict_function_transition_symbol();
 }
 #endif
 
diff --git a/src/type-cache.h b/src/type-cache.h
index 2a95df9..2c13b39 100644
--- a/src/type-cache.h
+++ b/src/type-cache.h
@@ -48,19 +48,30 @@
   Type* const kZeroish =
       Type::Union(kSingletonZero, Type::MinusZeroOrNaN(), zone());
   Type* const kInteger = CreateRange(-V8_INFINITY, V8_INFINITY);
-  Type* const kPositiveInteger = CreateRange(0.0, V8_INFINITY);
   Type* const kIntegerOrMinusZero =
       Type::Union(kInteger, Type::MinusZero(), zone());
   Type* const kIntegerOrMinusZeroOrNaN =
       Type::Union(kIntegerOrMinusZero, Type::NaN(), zone());
+  Type* const kPositiveInteger = CreateRange(0.0, V8_INFINITY);
+  Type* const kPositiveIntegerOrMinusZero =
+      Type::Union(kPositiveInteger, Type::MinusZero(), zone());
+  Type* const kPositiveIntegerOrMinusZeroOrNaN =
+      Type::Union(kPositiveIntegerOrMinusZero, Type::NaN(), zone());
 
   Type* const kAdditiveSafeInteger =
       CreateRange(-4503599627370496.0, 4503599627370496.0);
   Type* const kSafeInteger = CreateRange(-kMaxSafeInteger, kMaxSafeInteger);
+  Type* const kAdditiveSafeIntegerOrMinusZero =
+      Type::Union(kAdditiveSafeInteger, Type::MinusZero(), zone());
+  Type* const kSafeIntegerOrMinusZero =
+      Type::Union(kSafeInteger, Type::MinusZero(), zone());
   Type* const kPositiveSafeInteger = CreateRange(0.0, kMaxSafeInteger);
+  Type* const kSafeSigned32 = CreateRange(-kMaxInt, kMaxInt);
 
   Type* const kUntaggedUndefined =
       Type::Intersect(Type::Undefined(), Type::Untagged(), zone());
+  Type* const kSigned32OrMinusZero =
+      Type::Union(Type::Signed32(), Type::MinusZero(), zone());
 
   // Asm.js related types.
   Type* const kAsmSigned = kInt32;
diff --git a/src/type-feedback-vector-inl.h b/src/type-feedback-vector-inl.h
index 015104e..771021f 100644
--- a/src/type-feedback-vector-inl.h
+++ b/src/type-feedback-vector-inl.h
@@ -14,13 +14,11 @@
 template <typename Derived>
 FeedbackVectorSlot FeedbackVectorSpecBase<Derived>::AddSlot(
     FeedbackVectorSlotKind kind) {
-  Derived* derived = static_cast<Derived*>(this);
-
-  int slot = derived->slots();
+  int slot = This()->slots();
   int entries_per_slot = TypeFeedbackMetadata::GetSlotSize(kind);
-  derived->append(kind);
+  This()->append(kind);
   for (int i = 1; i < entries_per_slot; i++) {
-    derived->append(FeedbackVectorSlotKind::INVALID);
+    This()->append(FeedbackVectorSlotKind::INVALID);
   }
   return FeedbackVectorSlot(slot);
 }
@@ -32,6 +30,10 @@
   return reinterpret_cast<TypeFeedbackMetadata*>(obj);
 }
 
+bool TypeFeedbackMetadata::is_empty() const {
+  if (length() == 0) return true;
+  return false;
+}
 
 int TypeFeedbackMetadata::slot_count() const {
   if (length() == 0) return 0;
@@ -53,6 +55,26 @@
   return kind == FeedbackVectorSlotKind::GENERAL ? 1 : 2;
 }
 
+bool TypeFeedbackMetadata::SlotRequiresName(FeedbackVectorSlotKind kind) {
+  switch (kind) {
+    case FeedbackVectorSlotKind::LOAD_GLOBAL_IC:
+      return true;
+
+    case FeedbackVectorSlotKind::CALL_IC:
+    case FeedbackVectorSlotKind::LOAD_IC:
+    case FeedbackVectorSlotKind::KEYED_LOAD_IC:
+    case FeedbackVectorSlotKind::STORE_IC:
+    case FeedbackVectorSlotKind::KEYED_STORE_IC:
+    case FeedbackVectorSlotKind::GENERAL:
+    case FeedbackVectorSlotKind::INVALID:
+      return false;
+
+    case FeedbackVectorSlotKind::KINDS_NUMBER:
+      break;
+  }
+  UNREACHABLE();
+  return false;
+}
 
 bool TypeFeedbackVector::is_empty() const {
   if (length() == 0) return true;
@@ -73,24 +95,10 @@
                     : TypeFeedbackMetadata::cast(get(kMetadataIndex));
 }
 
-
-FeedbackVectorSlotKind TypeFeedbackVector::GetKind(
-    FeedbackVectorSlot slot) const {
-  DCHECK(!is_empty());
-  return metadata()->GetKind(slot);
-}
-
-
-int TypeFeedbackVector::GetIndex(FeedbackVectorSlot slot) const {
-  DCHECK(slot.ToInt() < slot_count());
-  return kReservedIndexCount + slot.ToInt();
-}
-
-
-// Conversion from an integer index to either a slot or an ic slot. The caller
-// should know what kind she expects.
-FeedbackVectorSlot TypeFeedbackVector::ToSlot(int index) const {
-  DCHECK(index >= kReservedIndexCount && index < length());
+// Conversion from an integer index to either a slot or an ic slot.
+// static
+FeedbackVectorSlot TypeFeedbackVector::ToSlot(int index) {
+  DCHECK(index >= kReservedIndexCount);
   return FeedbackVectorSlot(index - kReservedIndexCount);
 }
 
@@ -149,6 +157,21 @@
   return isolate->heap()->uninitialized_symbol();
 }
 
+bool TypeFeedbackMetadataIterator::HasNext() const {
+  return next_slot_.ToInt() < metadata()->slot_count();
+}
+
+FeedbackVectorSlot TypeFeedbackMetadataIterator::Next() {
+  DCHECK(HasNext());
+  cur_slot_ = next_slot_;
+  slot_kind_ = metadata()->GetKind(cur_slot_);
+  next_slot_ = FeedbackVectorSlot(next_slot_.ToInt() + entry_size());
+  return cur_slot_;
+}
+
+int TypeFeedbackMetadataIterator::entry_size() const {
+  return TypeFeedbackMetadata::GetSlotSize(kind());
+}
 
 Object* FeedbackNexus::GetFeedback() const { return vector()->Get(slot()); }
 
diff --git a/src/type-feedback-vector.cc b/src/type-feedback-vector.cc
index 4519bd6..bc2f1c2 100644
--- a/src/type-feedback-vector.cc
+++ b/src/type-feedback-vector.cc
@@ -37,6 +37,23 @@
   return VectorICComputer::decode(data, slot.ToInt());
 }
 
+String* TypeFeedbackMetadata::GetName(FeedbackVectorSlot slot) const {
+  DCHECK(SlotRequiresName(GetKind(slot)));
+  FixedArray* names = FixedArray::cast(get(kNamesTableIndex));
+  // TODO(ishell): consider using binary search here or even Dictionary when we
+  // have more ICs with names.
+  Smi* key = Smi::FromInt(slot.ToInt());
+  for (int entry = 0; entry < names->length(); entry += kNameTableEntrySize) {
+    Object* current_key = names->get(entry + kNameTableSlotIndex);
+    if (current_key == key) {
+      Object* name = names->get(entry + kNameTableNameIndex);
+      DCHECK(name->IsString());
+      return String::cast(name);
+    }
+  }
+  UNREACHABLE();
+  return nullptr;
+}
 
 void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot,
                                    FeedbackVectorSlotKind kind) {
@@ -57,12 +74,13 @@
 template <typename Spec>
 Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate,
                                                        const Spec* spec) {
+  Factory* factory = isolate->factory();
+
   const int slot_count = spec->slots();
   const int slot_kinds_length = VectorICComputer::word_count(slot_count);
   const int length = slot_kinds_length + kReservedIndexCount;
   if (length == kReservedIndexCount) {
-    return Handle<TypeFeedbackMetadata>::cast(
-        isolate->factory()->empty_fixed_array());
+    return Handle<TypeFeedbackMetadata>::cast(factory->empty_fixed_array());
   }
 #ifdef DEBUG
   for (int i = 0; i < slot_count;) {
@@ -76,7 +94,7 @@
   }
 #endif
 
-  Handle<FixedArray> array = isolate->factory()->NewFixedArray(length, TENURED);
+  Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
   array->set(kSlotsCountIndex, Smi::FromInt(slot_count));
   // Fill the bit-vector part with zeros.
   for (int i = 0; i < slot_kinds_length; i++) {
@@ -85,9 +103,37 @@
 
   Handle<TypeFeedbackMetadata> metadata =
       Handle<TypeFeedbackMetadata>::cast(array);
+
+  // Add names to NamesTable.
+  const int name_count = spec->name_count();
+
+  Handle<FixedArray> names =
+      name_count == 0
+          ? factory->empty_fixed_array()
+          : factory->NewFixedArray(name_count * kNameTableEntrySize);
+  int name_index = 0;
   for (int i = 0; i < slot_count; i++) {
-    metadata->SetKind(FeedbackVectorSlot(i), spec->GetKind(i));
+    FeedbackVectorSlotKind kind = spec->GetKind(i);
+    metadata->SetKind(FeedbackVectorSlot(i), kind);
+    if (SlotRequiresName(kind)) {
+      Handle<String> name = spec->GetName(name_index);
+      DCHECK(!name.is_null());
+      int entry = name_index * kNameTableEntrySize;
+      names->set(entry + kNameTableSlotIndex, Smi::FromInt(i));
+      names->set(entry + kNameTableNameIndex, *name);
+      name_index++;
+    }
   }
+  DCHECK_EQ(name_count, name_index);
+  metadata->set(kNamesTableIndex, *names);
+
+  // It's important that the TypeFeedbackMetadata have a COW map, since it's
+  // pointed to by both a SharedFunctionInfo and indirectly by closures through
+  // the TypeFeedbackVector. The serializer uses the COW map type to decide
+  // this object belongs in the startup snapshot and not the partial
+  // snapshot(s).
+  metadata->set_map(isolate->heap()->fixed_cow_array_map());
+
   return metadata;
 }
 
@@ -99,14 +145,51 @@
   }
 
   int slots = slot_count();
-  for (int i = 0; i < slots; i++) {
-    if (GetKind(FeedbackVectorSlot(i)) != other_spec->GetKind(i)) {
+  int name_index = 0;
+  for (int i = 0; i < slots;) {
+    FeedbackVectorSlot slot(i);
+    FeedbackVectorSlotKind kind = GetKind(slot);
+    int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
+
+    if (kind != other_spec->GetKind(i)) {
       return true;
     }
+    if (SlotRequiresName(kind)) {
+      String* name = GetName(slot);
+      DCHECK(name != GetHeap()->empty_string());
+      String* other_name = *other_spec->GetName(name_index++);
+      if (name != other_name) {
+        return true;
+      }
+    }
+    i += entry_size;
   }
   return false;
 }
 
+bool TypeFeedbackMetadata::DiffersFrom(
+    const TypeFeedbackMetadata* other_metadata) const {
+  if (other_metadata->slot_count() != slot_count()) {
+    return true;
+  }
+
+  int slots = slot_count();
+  for (int i = 0; i < slots;) {
+    FeedbackVectorSlot slot(i);
+    FeedbackVectorSlotKind kind = GetKind(slot);
+    int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
+    if (GetKind(slot) != other_metadata->GetKind(slot)) {
+      return true;
+    }
+    if (SlotRequiresName(kind)) {
+      if (GetName(slot) != other_metadata->GetName(slot)) {
+        return true;
+      }
+    }
+    i += entry_size;
+  }
+  return false;
+}
 
 const char* TypeFeedbackMetadata::Kind2String(FeedbackVectorSlotKind kind) {
   switch (kind) {
@@ -116,6 +199,8 @@
       return "CALL_IC";
     case FeedbackVectorSlotKind::LOAD_IC:
       return "LOAD_IC";
+    case FeedbackVectorSlotKind::LOAD_GLOBAL_IC:
+      return "LOAD_GLOBAL_IC";
     case FeedbackVectorSlotKind::KEYED_LOAD_IC:
       return "KEYED_LOAD_IC";
     case FeedbackVectorSlotKind::STORE_IC:
@@ -131,6 +216,16 @@
   return "?";
 }
 
+FeedbackVectorSlotKind TypeFeedbackVector::GetKind(
+    FeedbackVectorSlot slot) const {
+  DCHECK(!is_empty());
+  return metadata()->GetKind(slot);
+}
+
+String* TypeFeedbackVector::GetName(FeedbackVectorSlot slot) const {
+  DCHECK(!is_empty());
+  return metadata()->GetName(slot);
+}
 
 // static
 Handle<TypeFeedbackVector> TypeFeedbackVector::New(
@@ -146,13 +241,29 @@
   Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
   array->set(kMetadataIndex, *metadata);
 
+  DisallowHeapAllocation no_gc;
+
   // Ensure we can skip the write barrier
   Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate);
   DCHECK_EQ(*factory->uninitialized_symbol(), *uninitialized_sentinel);
-  for (int i = kReservedIndexCount; i < length; i++) {
-    array->set(i, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
-  }
+  for (int i = 0; i < slot_count;) {
+    FeedbackVectorSlot slot(i);
+    FeedbackVectorSlotKind kind = metadata->GetKind(slot);
+    int index = TypeFeedbackVector::GetIndex(slot);
+    int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
 
+    Object* value;
+    if (kind == FeedbackVectorSlotKind::LOAD_GLOBAL_IC) {
+      value = *factory->empty_weak_cell();
+    } else {
+      value = *uninitialized_sentinel;
+    }
+    array->set(index, value, SKIP_WRITE_BARRIER);
+    for (int j = 1; j < entry_size; j++) {
+      array->set(index + j, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
+    }
+    i += entry_size;
+  }
   return Handle<TypeFeedbackVector>::cast(array);
 }
 
@@ -208,6 +319,11 @@
           nexus.Clear(shared->code());
           break;
         }
+        case FeedbackVectorSlotKind::LOAD_GLOBAL_IC: {
+          LoadGlobalICNexus nexus(this, slot);
+          nexus.Clear(shared->code());
+          break;
+        }
         case FeedbackVectorSlotKind::KEYED_LOAD_IC: {
           KeyedLoadICNexus nexus(this, slot);
           nexus.Clear(shared->code());
@@ -251,8 +367,28 @@
   SharedFunctionInfo::Iterator iterator(isolate);
   SharedFunctionInfo* shared;
   while ((shared = iterator.Next())) {
-    TypeFeedbackVector* vector = shared->feedback_vector();
-    vector->ClearKeyedStoreICs(shared);
+    if (!shared->OptimizedCodeMapIsCleared()) {
+      FixedArray* optimized_code_map = shared->optimized_code_map();
+      int length = optimized_code_map->length();
+      for (int i = SharedFunctionInfo::kEntriesStart; i < length;
+           i += SharedFunctionInfo::kEntryLength) {
+        Object* lits =
+            optimized_code_map->get(i + SharedFunctionInfo::kLiteralsOffset);
+        TypeFeedbackVector* vector = nullptr;
+        if (lits->IsWeakCell()) {
+          WeakCell* cell = WeakCell::cast(lits);
+          if (cell->value()->IsLiteralsArray()) {
+            vector = LiteralsArray::cast(cell->value())->feedback_vector();
+          }
+        } else {
+          DCHECK(lits->IsLiteralsArray());
+          vector = LiteralsArray::cast(lits)->feedback_vector();
+        }
+        if (vector != nullptr) {
+          vector->ClearKeyedStoreICs(shared);
+        }
+      }
+    }
   }
 }
 
@@ -389,6 +525,17 @@
   return UNINITIALIZED;
 }
 
+InlineCacheState LoadGlobalICNexus::StateFromFeedback() const {
+  Isolate* isolate = GetIsolate();
+  Object* feedback = GetFeedback();
+
+  Object* extra = GetFeedbackExtra();
+  if (!WeakCell::cast(feedback)->cleared() ||
+      extra != *TypeFeedbackVector::UninitializedSentinel(isolate)) {
+    return MONOMORPHIC;
+  }
+  return UNINITIALIZED;
+}
 
 InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
   Isolate* isolate = GetIsolate();
@@ -488,7 +635,7 @@
 int CallICNexus::ExtractCallCount() {
   Object* call_count = GetFeedbackExtra();
   if (call_count->IsSmi()) {
-    int value = Smi::cast(call_count)->value() / 2;
+    int value = Smi::cast(call_count)->value();
     return value;
   }
   return -1;
@@ -505,14 +652,14 @@
         GetIsolate()->factory()->NewAllocationSite();
     SetFeedback(*new_site);
   }
-  SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER);
+  SetFeedbackExtra(Smi::FromInt(1), SKIP_WRITE_BARRIER);
 }
 
 
 void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) {
   Handle<WeakCell> new_cell = GetIsolate()->factory()->NewWeakCell(function);
   SetFeedback(*new_cell);
-  SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER);
+  SetFeedbackExtra(Smi::FromInt(1), SKIP_WRITE_BARRIER);
 }
 
 
@@ -524,8 +671,7 @@
 void CallICNexus::ConfigureMegamorphic(int call_count) {
   SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()),
               SKIP_WRITE_BARRIER);
-  SetFeedbackExtra(Smi::FromInt(call_count * kCallCountIncrement),
-                   SKIP_WRITE_BARRIER);
+  SetFeedbackExtra(Smi::FromInt(call_count), SKIP_WRITE_BARRIER);
 }
 
 
@@ -536,6 +682,24 @@
   SetFeedbackExtra(*handler);
 }
 
+void LoadGlobalICNexus::ConfigureUninitialized() {
+  Isolate* isolate = GetIsolate();
+  SetFeedback(isolate->heap()->empty_weak_cell(), SKIP_WRITE_BARRIER);
+  SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
+                   SKIP_WRITE_BARRIER);
+}
+
+void LoadGlobalICNexus::ConfigurePropertyCellMode(Handle<PropertyCell> cell) {
+  Isolate* isolate = GetIsolate();
+  SetFeedback(*isolate->factory()->NewWeakCell(cell));
+  SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
+                   SKIP_WRITE_BARRIER);
+}
+
+void LoadGlobalICNexus::ConfigureHandlerMode(Handle<Code> handler) {
+  SetFeedback(GetIsolate()->heap()->empty_weak_cell());
+  SetFeedbackExtra(*handler);
+}
 
 void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name,
                                             Handle<Map> receiver_map,
@@ -587,7 +751,6 @@
                    SKIP_WRITE_BARRIER);
 }
 
-
 void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name,
                                             MapHandleList* maps,
                                             CodeHandleList* handlers) {
@@ -781,6 +944,9 @@
 
 void LoadICNexus::Clear(Code* host) { LoadIC::Clear(GetIsolate(), host, this); }
 
+void LoadGlobalICNexus::Clear(Code* host) {
+  LoadGlobalIC::Clear(GetIsolate(), host, this);
+}
 
 void KeyedLoadICNexus::Clear(Code* host) {
   KeyedLoadIC::Clear(GetIsolate(), host, this);
diff --git a/src/type-feedback-vector.h b/src/type-feedback-vector.h
index 770b5e5..38d5695 100644
--- a/src/type-feedback-vector.h
+++ b/src/type-feedback-vector.h
@@ -15,7 +15,6 @@
 namespace v8 {
 namespace internal {
 
-
 enum class FeedbackVectorSlotKind {
   // This kind means that the slot points to the middle of other slot
   // which occupies more than one feedback vector element.
@@ -24,6 +23,7 @@
 
   CALL_IC,
   LOAD_IC,
+  LOAD_GLOBAL_IC,
   KEYED_LOAD_IC,
   STORE_IC,
   KEYED_STORE_IC,
@@ -34,7 +34,6 @@
   KINDS_NUMBER  // Last value indicating number of kinds.
 };
 
-
 std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind);
 
 
@@ -51,6 +50,11 @@
     return AddSlot(FeedbackVectorSlotKind::LOAD_IC);
   }
 
+  FeedbackVectorSlot AddLoadGlobalICSlot(Handle<String> name) {
+    This()->append_name(name);
+    return AddSlot(FeedbackVectorSlotKind::LOAD_GLOBAL_IC);
+  }
+
   FeedbackVectorSlot AddKeyedLoadICSlot() {
     return AddSlot(FeedbackVectorSlotKind::KEYED_LOAD_IC);
   }
@@ -66,40 +70,65 @@
   FeedbackVectorSlot AddGeneralSlot() {
     return AddSlot(FeedbackVectorSlotKind::GENERAL);
   }
+
+#ifdef OBJECT_PRINT
+  // For gdb debugging.
+  void Print();
+#endif  // OBJECT_PRINT
+
+  DECLARE_PRINTER(FeedbackVectorSpec)
+
+ private:
+  Derived* This() { return static_cast<Derived*>(this); }
 };
 
 
 class StaticFeedbackVectorSpec
     : public FeedbackVectorSpecBase<StaticFeedbackVectorSpec> {
  public:
-  StaticFeedbackVectorSpec() : slots_(0) {}
+  StaticFeedbackVectorSpec() : slot_count_(0), name_count_(0) {}
 
-  int slots() const { return slots_; }
+  int slots() const { return slot_count_; }
 
   FeedbackVectorSlotKind GetKind(int slot) const {
-    DCHECK(slot >= 0 && slot < slots_);
+    DCHECK(slot >= 0 && slot < slot_count_);
     return kinds_[slot];
   }
 
+  int name_count() const { return name_count_; }
+
+  Handle<String> GetName(int index) const {
+    DCHECK(index >= 0 && index < name_count_);
+    return names_[index];
+  }
+
  private:
   friend class FeedbackVectorSpecBase<StaticFeedbackVectorSpec>;
 
   void append(FeedbackVectorSlotKind kind) {
-    DCHECK(slots_ < kMaxLength);
-    kinds_[slots_++] = kind;
+    DCHECK(slot_count_ < kMaxLength);
+    kinds_[slot_count_++] = kind;
+  }
+
+  void append_name(Handle<String> name) {
+    DCHECK(name_count_ < kMaxLength);
+    names_[name_count_++] = name;
   }
 
   static const int kMaxLength = 12;
 
-  int slots_;
+  int slot_count_;
   FeedbackVectorSlotKind kinds_[kMaxLength];
+  int name_count_;
+  Handle<String> names_[kMaxLength];
 };
 
 
 class FeedbackVectorSpec : public FeedbackVectorSpecBase<FeedbackVectorSpec> {
  public:
-  explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone) {
+  explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone), names_(zone) {
     slot_kinds_.reserve(16);
+    names_.reserve(8);
   }
 
   int slots() const { return static_cast<int>(slot_kinds_.size()); }
@@ -108,6 +137,10 @@
     return static_cast<FeedbackVectorSlotKind>(slot_kinds_.at(slot));
   }
 
+  int name_count() const { return static_cast<int>(names_.size()); }
+
+  Handle<String> GetName(int index) const { return names_.at(index); }
+
  private:
   friend class FeedbackVectorSpecBase<FeedbackVectorSpec>;
 
@@ -115,13 +148,17 @@
     slot_kinds_.push_back(static_cast<unsigned char>(kind));
   }
 
+  void append_name(Handle<String> name) { names_.push_back(name); }
+
   ZoneVector<unsigned char> slot_kinds_;
+  ZoneVector<Handle<String>> names_;
 };
 
 
 // The shape of the TypeFeedbackMetadata is an array with:
 // 0: slot_count
-// 1..N: slot kinds packed into a bit vector
+// 1: names table
+// 2..N: slot kinds packed into a bit vector
 //
 class TypeFeedbackMetadata : public FixedArray {
  public:
@@ -129,19 +166,34 @@
   static inline TypeFeedbackMetadata* cast(Object* obj);
 
   static const int kSlotsCountIndex = 0;
-  static const int kReservedIndexCount = 1;
+  static const int kNamesTableIndex = 1;
+  static const int kReservedIndexCount = 2;
+
+  static const int kNameTableEntrySize = 2;
+  static const int kNameTableSlotIndex = 0;
+  static const int kNameTableNameIndex = 1;
 
   // Returns number of feedback vector elements used by given slot kind.
   static inline int GetSlotSize(FeedbackVectorSlotKind kind);
 
+  // Defines if slots of given kind require "name".
+  static inline bool SlotRequiresName(FeedbackVectorSlotKind kind);
+
   bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const;
 
+  bool DiffersFrom(const TypeFeedbackMetadata* other_metadata) const;
+
+  inline bool is_empty() const;
+
   // Returns number of slots in the vector.
   inline int slot_count() const;
 
   // Returns slot kind for given slot.
   FeedbackVectorSlotKind GetKind(FeedbackVectorSlot slot) const;
 
+  // Returns name for given slot.
+  String* GetName(FeedbackVectorSlot slot) const;
+
   template <typename Spec>
   static Handle<TypeFeedbackMetadata> New(Isolate* isolate, const Spec* spec);
 
@@ -155,7 +207,7 @@
   static const char* Kind2String(FeedbackVectorSlotKind kind);
 
  private:
-  static const int kFeedbackVectorSlotKindBits = 3;
+  static const int kFeedbackVectorSlotKindBits = 4;
   STATIC_ASSERT(static_cast<int>(FeedbackVectorSlotKind::KINDS_NUMBER) <
                 (1 << kFeedbackVectorSlotKindBits));
 
@@ -172,9 +224,9 @@
 // 0: feedback metadata
 // 1: ics_with_types
 // 2: ics_with_generic_info
-// 3: feedback slot #0 (N >= 3)
+// 3: feedback slot #0
 // ...
-// N + slot_count - 1: feedback slot #(slot_count-1)
+// 3 + slot_count - 1: feedback slot #(slot_count-1)
 //
 class TypeFeedbackVector : public FixedArray {
  public:
@@ -194,18 +246,22 @@
   inline TypeFeedbackMetadata* metadata() const;
 
   // Conversion from a slot to an integer index to the underlying array.
-  inline int GetIndex(FeedbackVectorSlot slot) const;
+  static int GetIndex(FeedbackVectorSlot slot) {
+    return kReservedIndexCount + slot.ToInt();
+  }
   static int GetIndexFromSpec(const FeedbackVectorSpec* spec,
                               FeedbackVectorSlot slot);
 
   // Conversion from an integer index to the underlying array to a slot.
-  inline FeedbackVectorSlot ToSlot(int index) const;
+  static inline FeedbackVectorSlot ToSlot(int index);
   inline Object* Get(FeedbackVectorSlot slot) const;
   inline void Set(FeedbackVectorSlot slot, Object* value,
                   WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
 
   // Returns slot kind for given slot.
-  inline FeedbackVectorSlotKind GetKind(FeedbackVectorSlot slot) const;
+  FeedbackVectorSlotKind GetKind(FeedbackVectorSlot slot) const;
+  // Returns name corresponding to given slot or an empty string.
+  String* GetName(FeedbackVectorSlot slot) const;
 
   static Handle<TypeFeedbackVector> New(Isolate* isolate,
                                         Handle<TypeFeedbackMetadata> metadata);
@@ -280,23 +336,17 @@
  public:
   explicit TypeFeedbackMetadataIterator(Handle<TypeFeedbackMetadata> metadata)
       : metadata_handle_(metadata),
-        slot_(FeedbackVectorSlot(0)),
+        next_slot_(FeedbackVectorSlot(0)),
         slot_kind_(FeedbackVectorSlotKind::INVALID) {}
 
   explicit TypeFeedbackMetadataIterator(TypeFeedbackMetadata* metadata)
       : metadata_(metadata),
-        slot_(FeedbackVectorSlot(0)),
+        next_slot_(FeedbackVectorSlot(0)),
         slot_kind_(FeedbackVectorSlotKind::INVALID) {}
 
-  bool HasNext() const { return slot_.ToInt() < metadata()->slot_count(); }
+  inline bool HasNext() const;
 
-  FeedbackVectorSlot Next() {
-    DCHECK(HasNext());
-    FeedbackVectorSlot slot = slot_;
-    slot_kind_ = metadata()->GetKind(slot);
-    slot_ = FeedbackVectorSlot(slot_.ToInt() + entry_size());
-    return slot;
-  }
+  inline FeedbackVectorSlot Next();
 
   // Returns slot kind of the last slot returned by Next().
   FeedbackVectorSlotKind kind() const {
@@ -306,7 +356,12 @@
   }
 
   // Returns entry size of the last slot returned by Next().
-  int entry_size() const { return TypeFeedbackMetadata::GetSlotSize(kind()); }
+  inline int entry_size() const;
+
+  String* name() const {
+    DCHECK(TypeFeedbackMetadata::SlotRequiresName(kind()));
+    return metadata()->GetName(cur_slot_);
+  }
 
  private:
   TypeFeedbackMetadata* metadata() const {
@@ -318,7 +373,8 @@
   // pointer use cases.
   Handle<TypeFeedbackMetadata> metadata_handle_;
   TypeFeedbackMetadata* metadata_;
-  FeedbackVectorSlot slot_;
+  FeedbackVectorSlot cur_slot_;
+  FeedbackVectorSlot next_slot_;
   FeedbackVectorSlotKind slot_kind_;
 };
 
@@ -393,10 +449,6 @@
 
 class CallICNexus final : public FeedbackNexus {
  public:
-  // Monomorphic call ics store call counts. Platform code needs to increment
-  // the count appropriately (ie, by 2).
-  static const int kCallCountIncrement = 2;
-
   CallICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
       : FeedbackNexus(vector, slot) {
     DCHECK_EQ(FeedbackVectorSlotKind::CALL_IC, vector->GetKind(slot));
@@ -454,6 +506,37 @@
   InlineCacheState StateFromFeedback() const override;
 };
 
+class LoadGlobalICNexus : public FeedbackNexus {
+ public:
+  LoadGlobalICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
+      : FeedbackNexus(vector, slot) {
+    DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC, vector->GetKind(slot));
+  }
+  LoadGlobalICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
+      : FeedbackNexus(vector, slot) {
+    DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC, vector->GetKind(slot));
+  }
+
+  int ExtractMaps(MapHandleList* maps) const final {
+    // LoadGlobalICs don't record map feedback.
+    return 0;
+  }
+  MaybeHandle<Code> FindHandlerForMap(Handle<Map> map) const final {
+    return MaybeHandle<Code>();
+  }
+  bool FindHandlers(CodeHandleList* code_list, int length = -1) const final {
+    return length == 0;
+  }
+
+  void ConfigureMegamorphic() override { UNREACHABLE(); }
+  void Clear(Code* host);
+
+  void ConfigureUninitialized() override;
+  void ConfigurePropertyCellMode(Handle<PropertyCell> cell);
+  void ConfigureHandlerMode(Handle<Code> handler);
+
+  InlineCacheState StateFromFeedback() const override;
+};
 
 class KeyedLoadICNexus : public FeedbackNexus {
  public:
diff --git a/src/type-info.cc b/src/type-info.cc
index 9087576..5f5c1e8 100644
--- a/src/type-info.cc
+++ b/src/type-info.cc
@@ -108,7 +108,7 @@
 
 bool TypeFeedbackOracle::CallIsUninitialized(FeedbackVectorSlot slot) {
   Handle<Object> value = GetInfo(slot);
-  return value->IsUndefined() ||
+  return value->IsUndefined(isolate()) ||
          value.is_identical_to(
              TypeFeedbackVector::UninitializedSentinel(isolate()));
 }
@@ -295,7 +295,7 @@
     *key_type = ELEMENT;
   } else {
     KeyedLoadICNexus nexus(feedback_vector_, slot);
-    CollectReceiverTypes<FeedbackNexus>(&nexus, receiver_types);
+    CollectReceiverTypes(&nexus, receiver_types);
     *is_string = HasOnlyStringMaps(receiver_types);
     *key_type = nexus.GetKeyType();
   }
@@ -332,21 +332,20 @@
                                               Code::Flags flags,
                                               SmallMapList* types) {
   StoreICNexus nexus(feedback_vector_, slot);
-  CollectReceiverTypes<FeedbackNexus>(&nexus, name, flags, types);
+  CollectReceiverTypes(&nexus, name, flags, types);
 }
 
-
-template <class T>
-void TypeFeedbackOracle::CollectReceiverTypes(T* obj, Handle<Name> name,
+void TypeFeedbackOracle::CollectReceiverTypes(FeedbackNexus* nexus,
+                                              Handle<Name> name,
                                               Code::Flags flags,
                                               SmallMapList* types) {
   if (FLAG_collect_megamorphic_maps_from_stub_cache &&
-      obj->ic_state() == MEGAMORPHIC) {
+      nexus->ic_state() == MEGAMORPHIC) {
     types->Reserve(4, zone());
     isolate()->stub_cache()->CollectMatchingMaps(
         types, name, flags, native_context_, zone());
   } else {
-    CollectReceiverTypes<T>(obj, types);
+    CollectReceiverTypes(nexus, types);
   }
 }
 
@@ -356,23 +355,22 @@
   FeedbackVectorSlotKind kind = feedback_vector_->GetKind(slot);
   if (kind == FeedbackVectorSlotKind::STORE_IC) {
     StoreICNexus nexus(feedback_vector_, slot);
-    CollectReceiverTypes<FeedbackNexus>(&nexus, types);
+    CollectReceiverTypes(&nexus, types);
   } else {
     DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, kind);
     KeyedStoreICNexus nexus(feedback_vector_, slot);
-    CollectReceiverTypes<FeedbackNexus>(&nexus, types);
+    CollectReceiverTypes(&nexus, types);
   }
 }
 
-
-template <class T>
-void TypeFeedbackOracle::CollectReceiverTypes(T* obj, SmallMapList* types) {
+void TypeFeedbackOracle::CollectReceiverTypes(FeedbackNexus* nexus,
+                                              SmallMapList* types) {
   MapHandleList maps;
-  if (obj->ic_state() == MONOMORPHIC) {
-    Map* map = obj->FindFirstMap();
+  if (nexus->ic_state() == MONOMORPHIC) {
+    Map* map = nexus->FindFirstMap();
     if (map != NULL) maps.Add(handle(map));
-  } else if (obj->ic_state() == POLYMORPHIC) {
-    obj->FindAllMaps(&maps);
+  } else if (nexus->ic_state() == POLYMORPHIC) {
+    nexus->FindAllMaps(&maps);
   } else {
     return;
   }
diff --git a/src/type-info.h b/src/type-info.h
index c4b0928..3c734be 100644
--- a/src/type-info.h
+++ b/src/type-info.h
@@ -17,7 +17,7 @@
 
 // Forward declarations.
 class SmallMapList;
-
+class FeedbackNexus;
 
 class TypeFeedbackOracle: public ZoneObject {
  public:
@@ -56,8 +56,7 @@
                           SmallMapList* receiver_types);
 
   void CollectReceiverTypes(FeedbackVectorSlot slot, SmallMapList* types);
-  template <class T>
-  void CollectReceiverTypes(T* obj, SmallMapList* types);
+  void CollectReceiverTypes(FeedbackNexus* nexus, SmallMapList* types);
 
   static bool IsRelevantFeedback(Map* map, Context* native_context) {
     Object* constructor = map->GetConstructor();
@@ -98,9 +97,8 @@
  private:
   void CollectReceiverTypes(FeedbackVectorSlot slot, Handle<Name> name,
                             Code::Flags flags, SmallMapList* types);
-  template <class T>
-  void CollectReceiverTypes(T* obj, Handle<Name> name, Code::Flags flags,
-                            SmallMapList* types);
+  void CollectReceiverTypes(FeedbackNexus* nexus, Handle<Name> name,
+                            Code::Flags flags, SmallMapList* types);
 
   // Returns true if there is at least one string map and if
   // all maps are string maps.
diff --git a/src/types.cc b/src/types.cc
index 49c9418..a48736b 100644
--- a/src/types.cc
+++ b/src/types.cc
@@ -192,7 +192,8 @@
              map == heap->no_interceptor_result_sentinel_map() ||
              map == heap->termination_exception_map() ||
              map == heap->arguments_marker_map() ||
-             map == heap->optimized_out_map());
+             map == heap->optimized_out_map() ||
+             map == heap->stale_register_map());
       return kInternal & kTaggedPointer;
     }
     case HEAP_NUMBER_TYPE:
@@ -200,8 +201,11 @@
     case SIMD128_VALUE_TYPE:
       return kSimd;
     case JS_OBJECT_TYPE:
+    case JS_ARGUMENTS_TYPE:
+    case JS_ERROR_TYPE:
     case JS_GLOBAL_OBJECT_TYPE:
     case JS_GLOBAL_PROXY_TYPE:
+    case JS_API_OBJECT_TYPE:
     case JS_SPECIAL_API_OBJECT_TYPE:
       if (map->is_undetectable()) return kOtherUndetectable;
       return kOtherObject;
@@ -266,8 +270,6 @@
     case SIGNATURE_INFO_TYPE:
     case TYPE_SWITCH_INFO_TYPE:
     case ALLOCATION_MEMENTO_TYPE:
-    case CODE_CACHE_TYPE:
-    case POLYMORPHIC_CODE_CACHE_TYPE:
     case TYPE_FEEDBACK_INFO_TYPE:
     case ALIASED_ARGUMENTS_ENTRY_TYPE:
     case BOX_TYPE:
diff --git a/src/types.h b/src/types.h
index 8061410..2541838 100644
--- a/src/types.h
+++ b/src/types.h
@@ -219,6 +219,8 @@
   V(BooleanOrNullOrUndefined, kBoolean | kNull | kUndefined) \
   V(NullOrUndefined,          kNull | kUndefined) \
   V(Undetectable,             kNullOrUndefined | kOtherUndetectable) \
+  V(NumberOrOddball,          kNumber | kNullOrUndefined | kBoolean) \
+  V(NumberOrSimdOrString,     kNumber | kSimd | kString) \
   V(NumberOrString,           kNumber | kString) \
   V(NumberOrUndefined,        kNumber | kUndefined) \
   V(PlainPrimitive,           kNumberOrString | kBoolean | kNullOrUndefined) \
@@ -229,6 +231,7 @@
   V(StringOrReceiver,         kString | kReceiver) \
   V(Unique,                   kBoolean | kUniqueName | kNull | kUndefined | \
                               kReceiver) \
+  V(NonInternal,              kPrimitive | kReceiver) \
   V(NonNumber,                kUnique | kString | kInternal) \
   V(Any,                      0xfffffffeu)
 
@@ -740,8 +743,8 @@
   SIMD128_TYPES(CONSTRUCT_SIMD_TYPE)
 #undef CONSTRUCT_SIMD_TYPE
 
-  static Type* Union(Type* type1, Type* type2, Zone* reg);
-  static Type* Intersect(Type* type1, Type* type2, Zone* reg);
+  static Type* Union(Type* type1, Type* type2, Zone* zone);
+  static Type* Intersect(Type* type1, Type* type2, Zone* zone);
 
   static Type* Of(double value, Zone* zone) {
     return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(value)));
diff --git a/src/typing-asm.cc b/src/typing-asm.cc
index 7482c4f..2390e7e 100644
--- a/src/typing-asm.cc
+++ b/src/typing-asm.cc
@@ -44,7 +44,7 @@
       root_(root),
       valid_(true),
       allow_simd_(false),
-      property_info_(NULL),
+      property_info_(nullptr),
       intish_(0),
       stdlib_types_(zone),
       stdlib_heap_types_(zone),
@@ -53,16 +53,17 @@
   stdlib_simd_##name##_types_(zone),
       SIMD128_TYPES(V)
 #undef V
-          global_variable_type_(HashMap::PointersMatch,
+          global_variable_type_(base::HashMap::PointersMatch,
                                 ZoneHashMap::kDefaultHashMapCapacity,
                                 ZoneAllocationPolicy(zone)),
-      local_variable_type_(HashMap::PointersMatch,
+      local_variable_type_(base::HashMap::PointersMatch,
                            ZoneHashMap::kDefaultHashMapCapacity,
                            ZoneAllocationPolicy(zone)),
       in_function_(false),
       building_function_tables_(false),
       visiting_exports_(false),
-      cache_(TypeCache::Get()) {
+      cache_(TypeCache::Get()),
+      bounds_(zone) {
   InitializeAstVisitor(isolate);
   InitializeStdlib();
 }
@@ -79,16 +80,16 @@
   if (!scope->is_function_scope()) FAIL(fun, "not at function scope");
 
   ExpressionStatement* use_asm = fun->body()->first()->AsExpressionStatement();
-  if (use_asm == NULL) FAIL(fun, "missing \"use asm\"");
+  if (use_asm == nullptr) FAIL(fun, "missing \"use asm\"");
   Literal* use_asm_literal = use_asm->expression()->AsLiteral();
-  if (use_asm_literal == NULL) FAIL(fun, "missing \"use asm\"");
+  if (use_asm_literal == nullptr) FAIL(fun, "missing \"use asm\"");
   if (!use_asm_literal->raw_value()->AsString()->IsOneByteEqualTo("use asm"))
     FAIL(fun, "missing \"use asm\"");
 
   // Module parameters.
   for (int i = 0; i < scope->num_parameters(); ++i) {
     Variable* param = scope->parameter(i);
-    DCHECK(GetType(param) == NULL);
+    DCHECK(GetType(param) == nullptr);
     SetType(param, Type::None());
   }
 
@@ -96,7 +97,7 @@
 
   // Set all globals to type Any.
   VariableDeclaration* decl = scope->function();
-  if (decl != NULL) SetType(decl->proxy()->var(), Type::None());
+  if (decl != nullptr) SetType(decl->proxy()->var(), Type::None());
   RECURSE(VisitDeclarations(scope->declarations()));
 
   // Validate global variables.
@@ -105,15 +106,15 @@
   // Validate function annotations.
   for (int i = 0; i < decls->length(); ++i) {
     FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration();
-    if (decl != NULL) {
+    if (decl != nullptr) {
       RECURSE(VisitFunctionAnnotation(decl->fun()));
       Variable* var = decl->proxy()->var();
-      if (property_info_ != NULL) {
+      if (property_info_ != nullptr) {
         SetVariableInfo(var, property_info_);
-        property_info_ = NULL;
+        property_info_ = nullptr;
       }
       SetType(var, computed_type_);
-      DCHECK(GetType(var) != NULL);
+      DCHECK(GetType(var) != nullptr);
     }
   }
 
@@ -125,7 +126,7 @@
   // Validate function bodies.
   for (int i = 0; i < decls->length(); ++i) {
     FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration();
-    if (decl != NULL) {
+    if (decl != nullptr) {
       RECURSE(VisitWithExpectation(decl->fun(), Type::Any(), "UNREACHABLE"));
       if (!computed_type_->IsFunction()) {
         FAIL(decl->fun(), "function literal expected to be a function");
@@ -147,13 +148,13 @@
 void AsmTyper::VisitVariableDeclaration(VariableDeclaration* decl) {
   Variable* var = decl->proxy()->var();
   if (var->location() != VariableLocation::PARAMETER) {
-    if (GetType(var) == NULL) {
+    if (GetType(var) == nullptr) {
       SetType(var, Type::Any());
     } else {
       DCHECK(!GetType(var)->IsFunction());
     }
   }
-  DCHECK(GetType(var) != NULL);
+  DCHECK(GetType(var) != nullptr);
   intish_ = 0;
 }
 
@@ -165,6 +166,10 @@
   // Set function type so global references to functions have some type
   // (so they can give a more useful error).
   Variable* var = decl->proxy()->var();
+  if (GetVariableInfo(var)) {
+    // Detect previously-seen functions.
+    FAIL(decl->fun(), "function repeated in module");
+  }
   SetType(var, Type::Function());
 }
 
@@ -175,14 +180,14 @@
   Type* result_type = Type::Undefined();
   if (body->length() > 0) {
     ReturnStatement* stmt = body->last()->AsReturnStatement();
-    if (stmt != NULL) {
+    if (stmt != nullptr) {
       Literal* literal = stmt->expression()->AsLiteral();
       Type* old_expected = expected_type_;
       expected_type_ = Type::Any();
       if (literal) {
         RECURSE(VisitLiteral(literal, true));
       } else {
-        RECURSE(VisitExpressionAnnotation(stmt->expression(), NULL, true));
+        RECURSE(VisitExpressionAnnotation(stmt->expression(), nullptr, true));
       }
       expected_type_ = old_expected;
       result_type = computed_type_;
@@ -197,18 +202,18 @@
     good = false;
     if (i >= body->length()) break;
     ExpressionStatement* stmt = body->at(i)->AsExpressionStatement();
-    if (stmt == NULL) break;
+    if (stmt == nullptr) break;
     Assignment* expr = stmt->expression()->AsAssignment();
-    if (expr == NULL || expr->is_compound()) break;
+    if (expr == nullptr || expr->is_compound()) break;
     VariableProxy* proxy = expr->target()->AsVariableProxy();
-    if (proxy == NULL) break;
+    if (proxy == nullptr) break;
     Variable* var = proxy->var();
     if (var->location() != VariableLocation::PARAMETER || var->index() != i)
       break;
     RECURSE(VisitExpressionAnnotation(expr->value(), var, false));
-    if (property_info_ != NULL) {
+    if (property_info_ != nullptr) {
       SetVariableInfo(var, property_info_);
-      property_info_ = NULL;
+      property_info_ = nullptr;
     }
     SetType(var, computed_type_);
     type->AsFunction()->InitParameter(i, computed_type_);
@@ -224,10 +229,10 @@
                                          bool is_return) {
   // Normal +x or x|0 annotations.
   BinaryOperation* bin = expr->AsBinaryOperation();
-  if (bin != NULL) {
-    if (var != NULL) {
+  if (bin != nullptr) {
+    if (var != nullptr) {
       VariableProxy* proxy = bin->left()->AsVariableProxy();
-      if (proxy == NULL) {
+      if (proxy == nullptr) {
         FAIL(bin->left(), "expected variable for type annotation");
       }
       if (proxy->var() != var) {
@@ -235,7 +240,7 @@
       }
     }
     Literal* right = bin->right()->AsLiteral();
-    if (right != NULL) {
+    if (right != nullptr) {
       switch (bin->op()) {
         case Token::MUL:  // We encode +x as x*1.0
           if (right->raw_value()->ContainsDot() &&
@@ -269,10 +274,10 @@
   }
 
   Call* call = expr->AsCall();
-  if (call != NULL) {
+  if (call != nullptr) {
     VariableProxy* proxy = call->expression()->AsVariableProxy();
-    if (proxy != NULL) {
-      VariableInfo* info = GetVariableInfo(proxy->var(), false);
+    if (proxy != nullptr) {
+      VariableInfo* info = GetVariableInfo(proxy->var());
       if (!info ||
           (!info->is_check_function && !info->is_constructor_function)) {
         if (allow_simd_) {
@@ -448,14 +453,14 @@
   if (!in_function_) {
     FAIL(stmt, "for statement inside module body");
   }
-  if (stmt->init() != NULL) {
+  if (stmt->init() != nullptr) {
     RECURSE(Visit(stmt->init()));
   }
-  if (stmt->cond() != NULL) {
+  if (stmt->cond() != nullptr) {
     RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned,
                                  "for condition expected to be integer"));
   }
-  if (stmt->next() != NULL) {
+  if (stmt->next() != nullptr) {
     RECURSE(Visit(stmt->next()));
   }
   RECURSE(Visit(stmt->body()));
@@ -494,11 +499,11 @@
   Scope* scope = expr->scope();
   DCHECK(scope->is_function_scope());
 
-  if (!expr->bounds().upper->IsFunction()) {
+  if (!bounds_.get(expr).upper->IsFunction()) {
     FAIL(expr, "invalid function literal");
   }
 
-  Type* type = expr->bounds().upper;
+  Type* type = bounds_.get(expr).upper;
   Type* save_return_type = return_type_;
   return_type_ = type->AsFunction()->Result();
   in_function_ = true;
@@ -507,7 +512,7 @@
   RECURSE(VisitStatements(expr->body()));
   in_function_ = false;
   return_type_ = save_return_type;
-  IntersectResult(expr, type);
+  RECURSE(IntersectResult(expr, type));
 }
 
 
@@ -551,45 +556,36 @@
     FAIL(expr, "then and else expressions in ? must have the same type");
   }
 
-  IntersectResult(expr, then_type);
+  RECURSE(IntersectResult(expr, then_type));
 }
 
 
 void AsmTyper::VisitVariableProxy(VariableProxy* expr) {
-  VisitVariableProxy(expr, false);
-}
-
-void AsmTyper::VisitVariableProxy(VariableProxy* expr, bool assignment) {
   Variable* var = expr->var();
-  VariableInfo* info = GetVariableInfo(var, false);
-  if (!assignment && !in_function_ && !building_function_tables_ &&
-      !visiting_exports_) {
+  VariableInfo* info = GetVariableInfo(var);
+  if (!in_function_ && !building_function_tables_ && !visiting_exports_) {
     if (var->location() != VariableLocation::PARAMETER || var->index() >= 3) {
       FAIL(expr, "illegal variable reference in module body");
     }
   }
-  if (info == NULL || info->type == NULL) {
+  if (info == nullptr || info->type == nullptr) {
     if (var->mode() == TEMPORARY) {
       SetType(var, Type::Any());
-      info = GetVariableInfo(var, false);
+      info = GetVariableInfo(var);
     } else {
       FAIL(expr, "unbound variable");
     }
   }
-  if (property_info_ != NULL) {
+  if (property_info_ != nullptr) {
     SetVariableInfo(var, property_info_);
-    property_info_ = NULL;
+    property_info_ = nullptr;
   }
   Type* type = Type::Intersect(info->type, expected_type_, zone());
-  if (type->Is(cache_.kAsmInt)) {
-    type = cache_.kAsmInt;
-  }
-  info->type = type;
+  if (type->Is(cache_.kAsmInt)) type = cache_.kAsmInt;
   intish_ = 0;
-  IntersectResult(expr, type);
+  RECURSE(IntersectResult(expr, type));
 }
 
-
 void AsmTyper::VisitLiteral(Literal* expr, bool is_return) {
   intish_ = 0;
   Handle<Object> value = expr->value();
@@ -597,22 +593,22 @@
     int32_t i;
     uint32_t u;
     if (expr->raw_value()->ContainsDot()) {
-      IntersectResult(expr, cache_.kAsmDouble);
+      RECURSE(IntersectResult(expr, cache_.kAsmDouble));
     } else if (!is_return && value->ToUint32(&u)) {
       if (u <= 0x7fffffff) {
-        IntersectResult(expr, cache_.kAsmFixnum);
+        RECURSE(IntersectResult(expr, cache_.kAsmFixnum));
       } else {
-        IntersectResult(expr, cache_.kAsmUnsigned);
+        RECURSE(IntersectResult(expr, cache_.kAsmUnsigned));
       }
     } else if (value->ToInt32(&i)) {
-      IntersectResult(expr, cache_.kAsmSigned);
+      RECURSE(IntersectResult(expr, cache_.kAsmSigned));
     } else {
       FAIL(expr, "illegal number");
     }
   } else if (!is_return && value->IsString()) {
-    IntersectResult(expr, Type::String());
-  } else if (value->IsUndefined()) {
-    IntersectResult(expr, Type::Undefined());
+    RECURSE(IntersectResult(expr, Type::String()));
+  } else if (value->IsUndefined(isolate_)) {
+    RECURSE(IntersectResult(expr, Type::Undefined()));
   } else {
     FAIL(expr, "illegal literal");
   }
@@ -641,7 +637,7 @@
       FAIL(prop->value(), "non-function in function table");
     }
   }
-  IntersectResult(expr, Type::Object());
+  RECURSE(IntersectResult(expr, Type::Object()));
 }
 
 
@@ -661,7 +657,7 @@
     elem_type = Type::Union(elem_type, computed_type_, zone());
   }
   array_size_ = values->length();
-  IntersectResult(expr, Type::Array(elem_type, zone()));
+  RECURSE(IntersectResult(expr, Type::Array(elem_type, zone())));
 }
 
 
@@ -683,13 +679,38 @@
   RECURSE(VisitWithExpectation(
       expr->value(), type, "assignment value expected to match surrounding"));
   Type* target_type = StorageType(computed_type_);
+
   if (expr->target()->IsVariableProxy()) {
+    // Assignment to a local or context variable.
+    VariableProxy* proxy = expr->target()->AsVariableProxy();
     if (intish_ != 0) {
       FAIL(expr, "intish or floatish assignment");
     }
+    if (in_function_ && target_type->IsArray()) {
+      FAIL(expr, "assignment to array variable");
+    }
     expected_type_ = target_type;
-    VisitVariableProxy(expr->target()->AsVariableProxy(), true);
+    Variable* var = proxy->var();
+    VariableInfo* info = GetVariableInfo(var);
+    if (info == nullptr || info->type == nullptr) {
+      if (var->mode() == TEMPORARY) {
+        SetType(var, Type::Any());
+        info = GetVariableInfo(var);
+      } else {
+        FAIL(proxy, "unbound variable");
+      }
+    }
+    if (property_info_ != nullptr) {
+      SetVariableInfo(var, property_info_);
+      property_info_ = nullptr;
+    }
+    Type* type = Type::Intersect(info->type, expected_type_, zone());
+    if (type->Is(cache_.kAsmInt)) type = cache_.kAsmInt;
+    info->type = type;
+    intish_ = 0;
+    RECURSE(IntersectResult(proxy, type));
   } else if (expr->target()->IsProperty()) {
+    // Assignment to a property: should be a heap assignment {H[x] = y}.
     int32_t value_intish = intish_;
     Property* property = expr->target()->AsProperty();
     RECURSE(VisitWithExpectation(property->obj(), Type::Any(),
@@ -702,7 +723,7 @@
     }
     VisitHeapAccess(property, true, target_type);
   }
-  IntersectResult(expr, target_type);
+  RECURSE(IntersectResult(expr, target_type));
 }
 
 
@@ -745,13 +766,13 @@
     }
     // TODO(bradnelson): Fix the parser and then un-comment this part
     // BinaryOperation* bin = expr->key()->AsBinaryOperation();
-    // if (bin == NULL || bin->op() != Token::BIT_AND) {
+    // if (bin == nullptr || bin->op() != Token::BIT_AND) {
     //   FAIL(expr->key(), "expected & in call");
     // }
     // RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned,
     //                              "array index expected to be integer"));
     // Literal* right = bin->right()->AsLiteral();
-    // if (right == NULL || right->raw_value()->ContainsDot()) {
+    // if (right == nullptr || right->raw_value()->ContainsDot()) {
     //   FAIL(right, "call mask must be integer");
     // }
     // RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned,
@@ -762,7 +783,7 @@
     // bin->set_bounds(Bounds(cache_.kAsmSigned));
     RECURSE(VisitWithExpectation(expr->key(), cache_.kAsmSigned,
                                  "must be integer"));
-    IntersectResult(expr, type);
+    RECURSE(IntersectResult(expr, type));
   } else {
     Literal* literal = expr->key()->AsLiteral();
     if (literal) {
@@ -774,13 +795,13 @@
         RECURSE(Visit(expr->key()));
       } else {
         BinaryOperation* bin = expr->key()->AsBinaryOperation();
-        if (bin == NULL || bin->op() != Token::SAR) {
+        if (bin == nullptr || bin->op() != Token::SAR) {
           FAIL(expr->key(), "expected >> in heap access");
         }
         RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned,
                                      "array index expected to be integer"));
         Literal* right = bin->right()->AsLiteral();
-        if (right == NULL || right->raw_value()->ContainsDot()) {
+        if (right == nullptr || right->raw_value()->ContainsDot()) {
           FAIL(bin->right(), "heap access shift must be integer");
         }
         RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned,
@@ -790,7 +811,7 @@
           FAIL(right, "heap access shift must match element size");
         }
       }
-      expr->key()->set_bounds(Bounds(cache_.kAsmSigned));
+      bounds_.set(expr->key(), Bounds(cache_.kAsmSigned));
     }
     Type* result_type;
     if (type->Is(cache_.kAsmIntArrayElement)) {
@@ -821,8 +842,8 @@
         FAIL(expr, "illegal type in assignment");
       }
     } else {
-      IntersectResult(expr, expected_type_);
-      IntersectResult(expr, result_type);
+      RECURSE(IntersectResult(expr, expected_type_));
+      RECURSE(IntersectResult(expr, result_type));
     }
   }
 }
@@ -830,18 +851,18 @@
 
 bool AsmTyper::IsStdlibObject(Expression* expr) {
   VariableProxy* proxy = expr->AsVariableProxy();
-  if (proxy == NULL) {
+  if (proxy == nullptr) {
     return false;
   }
   Variable* var = proxy->var();
-  VariableInfo* info = GetVariableInfo(var, false);
+  VariableInfo* info = GetVariableInfo(var);
   if (info) {
     if (info->standard_member == kStdlib) return true;
   }
   if (var->location() != VariableLocation::PARAMETER || var->index() != 0) {
     return false;
   }
-  info = GetVariableInfo(var, true);
+  info = MakeVariableInfo(var);
   info->type = Type::Object();
   info->standard_member = kStdlib;
   return true;
@@ -851,13 +872,13 @@
 Expression* AsmTyper::GetReceiverOfPropertyAccess(Expression* expr,
                                                   const char* name) {
   Property* property = expr->AsProperty();
-  if (property == NULL) {
-    return NULL;
+  if (property == nullptr) {
+    return nullptr;
   }
   Literal* key = property->key()->AsLiteral();
-  if (key == NULL || !key->IsPropertyName() ||
+  if (key == nullptr || !key->IsPropertyName() ||
       !key->AsPropertyName()->IsUtf8EqualTo(CStrVector(name))) {
-    return NULL;
+    return nullptr;
   }
   return property->obj();
 }
@@ -904,7 +925,7 @@
     return;
   }
 
-  property_info_ = NULL;
+  property_info_ = nullptr;
 
   // Only recurse at this point so that we avoid needing
   // stdlib.Math to have a real type.
@@ -913,12 +934,12 @@
 
   // For heap view or function table access.
   if (computed_type_->IsArray()) {
-    VisitHeapAccess(expr, false, NULL);
+    VisitHeapAccess(expr, false, nullptr);
     return;
   }
 
   VariableProxy* proxy = expr->obj()->AsVariableProxy();
-  if (proxy != NULL) {
+  if (proxy != nullptr) {
     Variable* var = proxy->var();
     if (var->location() == VariableLocation::PARAMETER && var->index() == 1) {
       // foreign.x - Function represent as () -> Any
@@ -941,7 +962,7 @@
   }
   // Handle polymorphic stdlib functions specially.
   Expression* arg0 = args->at(0);
-  Type* arg0_type = arg0->bounds().upper;
+  Type* arg0_type = bounds_.get(arg0).upper;
   switch (standard_member) {
     case kMathFround: {
       if (!arg0_type->Is(cache_.kAsmFloat) &&
@@ -970,8 +991,8 @@
         FAIL(arg0, "illegal function argument type");
       }
       if (args->length() > 1) {
-        Type* other = Type::Intersect(args->at(0)->bounds().upper,
-                                      args->at(1)->bounds().upper, zone());
+        Type* other = Type::Intersect(bounds_.get(args->at(0)).upper,
+                                      bounds_.get(args->at(1)).upper, zone());
         if (!other->Is(cache_.kAsmFloat) && !other->Is(cache_.kAsmDouble) &&
             !other->Is(cache_.kAsmSigned)) {
           FAIL(arg0, "function arguments types don't match");
@@ -992,10 +1013,10 @@
   if (proxy) {
     standard_member = VariableAsStandardMember(proxy->var());
   }
-  if (!in_function_ && (proxy == NULL || standard_member != kMathFround)) {
+  if (!in_function_ && (proxy == nullptr || standard_member != kMathFround)) {
     FAIL(expr, "calls forbidden outside function bodies");
   }
-  if (proxy == NULL && !expr->expression()->IsProperty()) {
+  if (proxy == nullptr && !expr->expression()->IsProperty()) {
     FAIL(expr, "calls must be to bound variables or function tables");
   }
   if (computed_type_->IsFunction()) {
@@ -1018,9 +1039,9 @@
         }
       }
       intish_ = 0;
-      expr->expression()->set_bounds(
-          Bounds(Type::Function(Type::Any(), zone())));
-      IntersectResult(expr, expected_type);
+      bounds_.set(expr->expression(),
+                  Bounds(Type::Function(Type::Any(), zone())));
+      RECURSE(IntersectResult(expr, expected_type));
     } else {
       if (fun_type->Arity() != args->length()) {
         FAIL(expr, "call with wrong arity");
@@ -1037,7 +1058,7 @@
       }
       RECURSE(CheckPolymorphicStdlibArguments(standard_member, args));
       intish_ = 0;
-      IntersectResult(expr, result_type);
+      RECURSE(IntersectResult(expr, result_type));
     }
   } else {
     FAIL(expr, "invalid callee");
@@ -1062,7 +1083,7 @@
           arg, fun_type->Parameter(i),
           "constructor argument expected to match callee parameter"));
     }
-    IntersectResult(expr, fun_type->Result());
+    RECURSE(IntersectResult(expr, fun_type->Result()));
     return;
   }
 
@@ -1071,7 +1092,7 @@
 
 
 void AsmTyper::VisitCallRuntime(CallRuntime* expr) {
-  // Allow runtime calls for now.
+  FAIL(expr, "runtime call not allowed");
 }
 
 
@@ -1083,7 +1104,7 @@
     case Token::NOT:  // Used to encode != and !==
       RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt,
                                    "operand expected to be integer"));
-      IntersectResult(expr, cache_.kAsmSigned);
+      RECURSE(IntersectResult(expr, cache_.kAsmSigned));
       return;
     case Token::DELETE:
       FAIL(expr, "delete operator encountered");
@@ -1142,7 +1163,7 @@
       FAIL(expr, "ill-typed bitwise operation");
     }
   }
-  IntersectResult(expr, result_type);
+  RECURSE(IntersectResult(expr, result_type));
 }
 
 
@@ -1174,7 +1195,7 @@
                                    "left comma operand expected to be any"));
       RECURSE(VisitWithExpectation(expr->right(), Type::Any(),
                                    "right comma operand expected to be any"));
-      IntersectResult(expr, computed_type_);
+      RECURSE(IntersectResult(expr, computed_type_));
       return;
     }
     case Token::OR:
@@ -1185,11 +1206,12 @@
       RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ,
                                           cache_.kAsmSigned, true));
       if (expr->left()->IsCall() && expr->op() == Token::BIT_OR &&
-          Type::Number()->Is(expr->left()->bounds().upper)) {
+          Type::Number()->Is(bounds_.get(expr->left()).upper)) {
         // Force the return types of foreign functions.
-        expr->left()->set_bounds(Bounds(cache_.kAsmSigned));
+        bounds_.set(expr->left(), Bounds(cache_.kAsmSigned));
       }
-      if (in_function_ && !expr->left()->bounds().upper->Is(cache_.kAsmIntQ)) {
+      if (in_function_ &&
+          !bounds_.get(expr->left()).upper->Is(cache_.kAsmIntQ)) {
         FAIL(expr->left(), "intish required");
       }
       return;
@@ -1199,10 +1221,10 @@
       Literal* left = expr->left()->AsLiteral();
       if (left && left->value()->IsBoolean()) {
         if (left->ToBooleanIsTrue()) {
-          left->set_bounds(Bounds(cache_.kSingletonOne));
+          bounds_.set(left, Bounds(cache_.kSingletonOne));
           RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmIntQ,
                                        "not operator expects an integer"));
-          IntersectResult(expr, cache_.kAsmSigned);
+          RECURSE(IntersectResult(expr, cache_.kAsmSigned));
           return;
         } else {
           FAIL(left, "unexpected false");
@@ -1264,7 +1286,7 @@
             FAIL(expr, "multiply must be by value in -2^20 < n < 2^20");
           }
           intish_ = i;
-          IntersectResult(expr, cache_.kAsmInt);
+          RECURSE(IntersectResult(expr, cache_.kAsmInt));
           return;
         } else {
           intish_ = left_intish + right_intish + 1;
@@ -1277,7 +1299,7 @@
               FAIL(expr, "too many consecutive multiplicative ops");
             }
           }
-          IntersectResult(expr, cache_.kAsmInt);
+          RECURSE(IntersectResult(expr, cache_.kAsmInt));
           return;
         }
       } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() &&
@@ -1286,13 +1308,13 @@
                  expr->right()->AsLiteral()->raw_value()->AsNumber() == 1.0) {
         // For unary +, expressed as x * 1.0
         if (expr->left()->IsCall() &&
-            Type::Number()->Is(expr->left()->bounds().upper)) {
+            Type::Number()->Is(bounds_.get(expr->left()).upper)) {
           // Force the return types of foreign functions.
-          expr->left()->set_bounds(Bounds(cache_.kAsmDouble));
-          left_type = expr->left()->bounds().upper;
+          bounds_.set(expr->left(), Bounds(cache_.kAsmDouble));
+          left_type = bounds_.get(expr->left()).upper;
         }
         if (!(expr->left()->IsProperty() &&
-              Type::Number()->Is(expr->left()->bounds().upper))) {
+              Type::Number()->Is(bounds_.get(expr->left()).upper))) {
           if (!left_type->Is(cache_.kAsmSigned) &&
               !left_type->Is(cache_.kAsmUnsigned) &&
               !left_type->Is(cache_.kAsmFixnum) &&
@@ -1303,25 +1325,25 @@
                 "unary + only allowed on signed, unsigned, float?, or double?");
           }
         }
-        IntersectResult(expr, cache_.kAsmDouble);
+        RECURSE(IntersectResult(expr, cache_.kAsmDouble));
         return;
       } else if (expr->op() == Token::MUL && left_type->Is(cache_.kAsmDouble) &&
                  expr->right()->IsLiteral() &&
                  !expr->right()->AsLiteral()->raw_value()->ContainsDot() &&
                  expr->right()->AsLiteral()->raw_value()->AsNumber() == -1.0) {
         // For unary -, expressed as x * -1
-        expr->right()->set_bounds(Bounds(cache_.kAsmDouble));
-        IntersectResult(expr, cache_.kAsmDouble);
+        bounds_.set(expr->right(), Bounds(cache_.kAsmDouble));
+        RECURSE(IntersectResult(expr, cache_.kAsmDouble));
         return;
       } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) {
         if (left_intish != 0 || right_intish != 0) {
           FAIL(expr, "float operation before required fround");
         }
-        IntersectResult(expr, cache_.kAsmFloat);
+        RECURSE(IntersectResult(expr, cache_.kAsmFloat));
         intish_ = 1;
         return;
       } else if (type->Is(cache_.kAsmDouble)) {
-        IntersectResult(expr, cache_.kAsmDouble);
+        RECURSE(IntersectResult(expr, cache_.kAsmDouble));
         return;
       } else {
         FAIL(expr, "ill-typed arithmetic operation");
@@ -1363,7 +1385,7 @@
     FAIL(expr, "left and right side of comparison must match");
   }
 
-  IntersectResult(expr, cache_.kAsmSigned);
+  RECURSE(IntersectResult(expr, cache_.kAsmSigned));
 }
 
 
@@ -1502,11 +1524,12 @@
 
 void AsmTyper::VisitLibraryAccess(ObjectTypeMap* map, Property* expr) {
   Literal* key = expr->key()->AsLiteral();
-  if (key == NULL || !key->IsPropertyName())
+  if (key == nullptr || !key->IsPropertyName())
     FAIL(expr, "invalid key used on stdlib member");
   Handle<String> name = key->AsPropertyName();
   VariableInfo* info = LibType(map, name);
-  if (info == NULL || info->type == NULL) FAIL(expr, "unknown stdlib function");
+  if (info == nullptr || info->type == nullptr)
+    FAIL(expr, "unknown stdlib function");
   SetResult(expr, info->type);
   property_info_ = info;
 }
@@ -1517,55 +1540,47 @@
   base::SmartArrayPointer<char> aname = name->ToCString();
   ObjectTypeMap::iterator i = map->find(std::string(aname.get()));
   if (i == map->end()) {
-    return NULL;
+    return nullptr;
   }
   return i->second;
 }
 
 
 void AsmTyper::SetType(Variable* variable, Type* type) {
-  VariableInfo* info = GetVariableInfo(variable, true);
+  VariableInfo* info = MakeVariableInfo(variable);
   info->type = type;
 }
 
 
 Type* AsmTyper::GetType(Variable* variable) {
-  VariableInfo* info = GetVariableInfo(variable, false);
-  if (!info) return NULL;
+  VariableInfo* info = GetVariableInfo(variable);
+  if (!info) return nullptr;
   return info->type;
 }
 
+AsmTyper::VariableInfo* AsmTyper::GetVariableInfo(Variable* variable) {
+  ZoneHashMap* map =
+      in_function_ ? &local_variable_type_ : &global_variable_type_;
+  ZoneHashMap::Entry* entry =
+      map->Lookup(variable, ComputePointerHash(variable));
+  if (!entry && in_function_) {
+    entry =
+        global_variable_type_.Lookup(variable, ComputePointerHash(variable));
+  }
+  return entry ? reinterpret_cast<VariableInfo*>(entry->value) : nullptr;
+}
 
-AsmTyper::VariableInfo* AsmTyper::GetVariableInfo(Variable* variable,
-                                                  bool setting) {
-  ZoneHashMap::Entry* entry;
-  ZoneHashMap* map;
-  if (in_function_) {
-    map = &local_variable_type_;
-  } else {
-    map = &global_variable_type_;
-  }
-  if (setting) {
-    entry = map->LookupOrInsert(variable, ComputePointerHash(variable),
-                                ZoneAllocationPolicy(zone()));
-  } else {
-    entry = map->Lookup(variable, ComputePointerHash(variable));
-    if (!entry && in_function_) {
-      entry =
-          global_variable_type_.Lookup(variable, ComputePointerHash(variable));
-    }
-  }
-  if (!entry) return NULL;
-  if (!entry->value) {
-    if (!setting) return NULL;
-    entry->value = new (zone()) VariableInfo;
-  }
+AsmTyper::VariableInfo* AsmTyper::MakeVariableInfo(Variable* variable) {
+  ZoneHashMap* map =
+      in_function_ ? &local_variable_type_ : &global_variable_type_;
+  ZoneHashMap::Entry* entry = map->LookupOrInsert(
+      variable, ComputePointerHash(variable), ZoneAllocationPolicy(zone()));
+  if (!entry->value) entry->value = new (zone()) VariableInfo;
   return reinterpret_cast<VariableInfo*>(entry->value);
 }
 
-
 void AsmTyper::SetVariableInfo(Variable* variable, const VariableInfo* info) {
-  VariableInfo* dest = GetVariableInfo(variable, true);
+  VariableInfo* dest = MakeVariableInfo(variable);
   dest->type = info->type;
   dest->is_check_function = info->is_check_function;
   dest->is_constructor_function = info->is_constructor_function;
@@ -1575,7 +1590,7 @@
 
 AsmTyper::StandardMember AsmTyper::VariableAsStandardMember(
     Variable* variable) {
-  VariableInfo* info = GetVariableInfo(variable, false);
+  VariableInfo* info = GetVariableInfo(variable);
   if (!info) return kNone;
   return info->standard_member;
 }
@@ -1583,14 +1598,23 @@
 
 void AsmTyper::SetResult(Expression* expr, Type* type) {
   computed_type_ = type;
-  expr->set_bounds(Bounds(computed_type_));
+  bounds_.set(expr, Bounds(computed_type_));
 }
 
 
 void AsmTyper::IntersectResult(Expression* expr, Type* type) {
   computed_type_ = type;
   Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone());
-  expr->set_bounds(Bounds(bounded_type));
+  if (Type::Representation(bounded_type, zone())->Is(Type::None())) {
+#ifdef DEBUG
+    PrintF("Computed type: ");
+    computed_type_->Print();
+    PrintF("Expected type: ");
+    expected_type_->Print();
+#endif
+    FAIL(expr, "type mismatch");
+  }
+  bounds_.set(expr, Bounds(bounded_type));
 }
 
 
@@ -1600,7 +1624,7 @@
   expected_type_ = expected_type;
   RECURSE(Visit(expr));
   Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone());
-  if (bounded_type->Is(Type::None())) {
+  if (Type::Representation(bounded_type, zone())->Is(Type::None())) {
 #ifdef DEBUG
     PrintF("Computed type: ");
     computed_type_->Print();
diff --git a/src/typing-asm.h b/src/typing-asm.h
index c7984b2..09eacaa 100644
--- a/src/typing-asm.h
+++ b/src/typing-asm.h
@@ -6,6 +6,7 @@
 #define V8_TYPING_ASM_H_
 
 #include "src/allocation.h"
+#include "src/ast/ast-type-bounds.h"
 #include "src/ast/ast.h"
 #include "src/effects.h"
 #include "src/type-info.h"
@@ -24,6 +25,7 @@
   bool Validate();
   void set_allow_simd(bool simd) { allow_simd_ = simd; }
   const char* error_message() { return error_message_; }
+  const AstTypeBounds* bounds() { return &bounds_; }
 
   enum StandardMember {
     kNone = 0,
@@ -117,6 +119,8 @@
 
   TypeCache const& cache_;
 
+  AstTypeBounds bounds_;
+
   static const int kErrorMessageLimit = 100;
   char error_message_[kErrorMessageLimit];
 
@@ -151,7 +155,8 @@
 
   void SetType(Variable* variable, Type* type);
   Type* GetType(Variable* variable);
-  VariableInfo* GetVariableInfo(Variable* variable, bool setting);
+  VariableInfo* GetVariableInfo(Variable* variable);
+  VariableInfo* MakeVariableInfo(Variable* variable);
   void SetVariableInfo(Variable* variable, const VariableInfo* info);
 
   VariableInfo* LibType(ObjectTypeMap* map, Handle<String> name);
@@ -165,8 +170,6 @@
 
   void VisitLiteral(Literal* expr, bool is_return);
 
-  void VisitVariableProxy(VariableProxy* expr, bool assignment);
-
   void VisitIntegerBitwiseOperator(BinaryOperation* expr, Type* left_expected,
                                    Type* right_expected, Type* result_type,
                                    bool conversion);
diff --git a/src/typing-reset.cc b/src/typing-reset.cc
deleted file mode 100644
index c22f7a9..0000000
--- a/src/typing-reset.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/v8.h"
-
-#include "src/typing-reset.h"
-
-#include "src/ast/ast.h"
-#include "src/ast/scopes.h"
-#include "src/codegen.h"
-
-namespace v8 {
-namespace internal {
-
-
-TypingReseter::TypingReseter(Isolate* isolate, FunctionLiteral* root)
-    : AstExpressionVisitor(isolate, root) {}
-
-
-void TypingReseter::VisitExpression(Expression* expression) {
-  expression->set_bounds(Bounds::Unbounded());
-}
-}  // namespace internal
-}  // namespace v8
diff --git a/src/typing-reset.h b/src/typing-reset.h
deleted file mode 100644
index 3e1969d..0000000
--- a/src/typing-reset.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_TYPING_RESET_H_
-#define V8_TYPING_RESET_H_
-
-#include "src/ast/ast-expression-visitor.h"
-
-namespace v8 {
-namespace internal {
-
-// A Visitor over a CompilationInfo's AST that resets
-// typing bounds back to their default.
-
-class TypingReseter : public AstExpressionVisitor {
- public:
-  TypingReseter(Isolate* isolate, FunctionLiteral* root);
-
- protected:
-  void VisitExpression(Expression* expression) override;
-};
-}  // namespace internal
-}  // namespace v8
-
-#endif  // V8_TYPING_RESET_H_
diff --git a/src/unicode-inl.h b/src/unicode-inl.h
index b22e482..ebebfaa 100644
--- a/src/unicode-inl.h
+++ b/src/unicode-inl.h
@@ -137,6 +137,12 @@
   }
 }
 
+bool Utf8::IsValidCharacter(uchar c) {
+  return c < 0xD800u || (c >= 0xE000u && c < 0xFDD0u) ||
+         (c > 0xFDEFu && c <= 0x10FFFFu && (c & 0xFFFEu) != 0xFFFEu &&
+          c != kBadChar);
+}
+
 }  // namespace unibrow
 
 #endif  // V8_UNICODE_INL_H_
diff --git a/src/unicode.cc b/src/unicode.cc
index de5e360..db98be8 100644
--- a/src/unicode.cc
+++ b/src/unicode.cc
@@ -305,6 +305,20 @@
          0x03C82080;
 }
 
+bool Utf8::Validate(const byte* bytes, size_t length) {
+  size_t cursor = 0;
+
+  // Performance optimization: Skip over single-byte values first.
+  while (cursor < length && bytes[cursor] <= kMaxOneByteChar) {
+    ++cursor;
+  }
+
+  while (cursor < length) {
+    uchar c = ValueOf(bytes + cursor, length - cursor, &cursor);
+    if (!IsValidCharacter(c)) return false;
+  }
+  return true;
+}
 
 // Uppercase:            point.category == 'Lu'
 
diff --git a/src/unicode.h b/src/unicode.h
index 7471a63..35717bc 100644
--- a/src/unicode.h
+++ b/src/unicode.h
@@ -155,6 +155,11 @@
   // UTF-8.
   static const unsigned kMax16BitCodeUnitSize  = 3;
   static inline uchar ValueOf(const byte* str, size_t length, size_t* cursor);
+
+  // Excludes non-characters from the set of valid code points.
+  static inline bool IsValidCharacter(uchar c);
+
+  static bool Validate(const byte* str, size_t length);
 };
 
 struct Uppercase {
diff --git a/src/uri.cc b/src/uri.cc
new file mode 100644
index 0000000..0107721
--- /dev/null
+++ b/src/uri.cc
@@ -0,0 +1,505 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/uri.h"
+
+#include "src/char-predicates-inl.h"
+#include "src/handles.h"
+#include "src/isolate-inl.h"
+#include "src/list.h"
+#include "src/string-search.h"
+
+namespace v8 {
+namespace internal {
+
+namespace {  // anonymous namespace for DecodeURI helper functions
+bool IsReservedPredicate(uc16 c) {
+  switch (c) {
+    case '#':
+    case '$':
+    case '&':
+    case '+':
+    case ',':
+    case '/':
+    case ':':
+    case ';':
+    case '=':
+    case '?':
+    case '@':
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool IsReplacementCharacter(const uint8_t* octets, int length) {
+  // The replacement character is at codepoint U+FFFD in the Unicode Specials
+  // table. Its UTF-8 encoding is 0xEF 0xBF 0xBD.
+  if (length != 3 || octets[0] != 0xef || octets[1] != 0xbf ||
+      octets[2] != 0xbd) {
+    return false;
+  }
+  return true;
+}
+
+bool DecodeOctets(const uint8_t* octets, int length, List<uc16>* buffer) {
+  size_t cursor = 0;
+  uc32 value = unibrow::Utf8::ValueOf(octets, length, &cursor);
+  if (value == unibrow::Utf8::kBadChar &&
+      !IsReplacementCharacter(octets, length)) {
+    return false;
+  }
+
+  if (value <= unibrow::Utf16::kMaxNonSurrogateCharCode) {
+    buffer->Add(value);
+  } else {
+    buffer->Add(unibrow::Utf16::LeadSurrogate(value));
+    buffer->Add(unibrow::Utf16::TrailSurrogate(value));
+  }
+  return true;
+}
+
+int TwoDigitHex(uc16 character1, uc16 character2) {
+  if (character1 > 'f') return -1;
+  int high = HexValue(character1);
+  if (high == -1) return -1;
+  if (character2 > 'f') return -1;
+  int low = HexValue(character2);
+  if (low == -1) return -1;
+  return (high << 4) + low;
+}
+
+template <typename T>
+void AddToBuffer(uc16 decoded, String::FlatContent* uri_content, int index,
+                 bool is_uri, List<T>* buffer) {
+  if (is_uri && IsReservedPredicate(decoded)) {
+    buffer->Add('%');
+    uc16 first = uri_content->Get(index + 1);
+    uc16 second = uri_content->Get(index + 2);
+    DCHECK_GT(std::numeric_limits<T>::max(), first);
+    DCHECK_GT(std::numeric_limits<T>::max(), second);
+
+    buffer->Add(first);
+    buffer->Add(second);
+  } else {
+    buffer->Add(decoded);
+  }
+}
+
+bool IntoTwoByte(int index, bool is_uri, int uri_length,
+                 String::FlatContent* uri_content, List<uc16>* buffer) {
+  for (int k = index; k < uri_length; k++) {
+    uc16 code = uri_content->Get(k);
+    if (code == '%') {
+      uc16 decoded;
+      if (k + 2 >= uri_length ||
+          (decoded = TwoDigitHex(uri_content->Get(k + 1),
+                                 uri_content->Get(k + 2))) < 0) {
+        return false;
+      }
+      k += 2;
+      if (decoded > unibrow::Utf8::kMaxOneByteChar) {
+        uint8_t octets[unibrow::Utf8::kMaxEncodedSize];
+        octets[0] = decoded;
+
+        int number_of_continuation_bytes = 0;
+        while ((decoded << ++number_of_continuation_bytes) & 0x80) {
+          if (number_of_continuation_bytes > 3 || k + 3 >= uri_length) {
+            return false;
+          }
+
+          uc16 continuation_byte;
+
+          if (uri_content->Get(++k) != '%' ||
+              (continuation_byte = TwoDigitHex(uri_content->Get(k + 1),
+                                               uri_content->Get(k + 2))) < 0) {
+            return false;
+          }
+          k += 2;
+          octets[number_of_continuation_bytes] = continuation_byte;
+        }
+
+        if (!DecodeOctets(octets, number_of_continuation_bytes, buffer)) {
+          return false;
+        }
+      } else {
+        AddToBuffer(decoded, uri_content, k - 2, is_uri, buffer);
+      }
+    } else {
+      buffer->Add(code);
+    }
+  }
+  return true;
+}
+
+bool IntoOneAndTwoByte(Handle<String> uri, bool is_uri,
+                       List<uint8_t>* one_byte_buffer,
+                       List<uc16>* two_byte_buffer) {
+  DisallowHeapAllocation no_gc;
+  String::FlatContent uri_content = uri->GetFlatContent();
+
+  int uri_length = uri->length();
+  for (int k = 0; k < uri_length; k++) {
+    uc16 code = uri_content.Get(k);
+    if (code == '%') {
+      uc16 decoded;
+      if (k + 2 >= uri_length ||
+          (decoded = TwoDigitHex(uri_content.Get(k + 1),
+                                 uri_content.Get(k + 2))) < 0) {
+        return false;
+      }
+
+      if (decoded > unibrow::Utf8::kMaxOneByteChar) {
+        return IntoTwoByte(k, is_uri, uri_length, &uri_content,
+                           two_byte_buffer);
+      }
+
+      AddToBuffer(decoded, &uri_content, k, is_uri, one_byte_buffer);
+      k += 2;
+    } else {
+      if (code > unibrow::Utf8::kMaxOneByteChar) {
+        return IntoTwoByte(k, is_uri, uri_length, &uri_content,
+                           two_byte_buffer);
+      }
+      one_byte_buffer->Add(code);
+    }
+  }
+  return true;
+}
+
+}  // anonymous namespace
+
+MaybeHandle<String> Uri::Decode(Isolate* isolate, Handle<String> uri,
+                                bool is_uri) {
+  uri = String::Flatten(uri);
+  List<uint8_t> one_byte_buffer;
+  List<uc16> two_byte_buffer;
+
+  if (!IntoOneAndTwoByte(uri, is_uri, &one_byte_buffer, &two_byte_buffer)) {
+    THROW_NEW_ERROR(isolate, NewURIError(), String);
+  }
+
+  if (two_byte_buffer.is_empty()) {
+    return isolate->factory()->NewStringFromOneByte(
+        one_byte_buffer.ToConstVector());
+  }
+
+  Handle<SeqTwoByteString> result;
+  ASSIGN_RETURN_ON_EXCEPTION(
+      isolate, result, isolate->factory()->NewRawTwoByteString(
+                           one_byte_buffer.length() + two_byte_buffer.length()),
+      String);
+
+  CopyChars(result->GetChars(), one_byte_buffer.ToConstVector().start(),
+            one_byte_buffer.length());
+  CopyChars(result->GetChars() + one_byte_buffer.length(),
+            two_byte_buffer.ToConstVector().start(), two_byte_buffer.length());
+
+  return result;
+}
+
+namespace {  // anonymous namespace for EncodeURI helper functions
+bool IsUnescapePredicateInUriComponent(uc16 c) {
+  if (IsAlphaNumeric(c)) {
+    return true;
+  }
+
+  switch (c) {
+    case '!':
+    case '\'':
+    case '(':
+    case ')':
+    case '*':
+    case '-':
+    case '.':
+    case '_':
+    case '~':
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool IsUriSeparator(uc16 c) {
+  switch (c) {
+    case '#':
+    case ':':
+    case ';':
+    case '/':
+    case '?':
+    case '$':
+    case '&':
+    case '+':
+    case ',':
+    case '@':
+    case '=':
+      return true;
+    default:
+      return false;
+  }
+}
+
+void AddEncodedOctetToBuffer(uint8_t octet, List<uint8_t>* buffer) {
+  buffer->Add('%');
+  buffer->Add(HexCharOfValue(octet >> 4));
+  buffer->Add(HexCharOfValue(octet & 0x0F));
+}
+
+void EncodeSingle(uc16 c, List<uint8_t>* buffer) {
+  char s[4] = {};
+  int number_of_bytes;
+  number_of_bytes =
+      unibrow::Utf8::Encode(s, c, unibrow::Utf16::kNoPreviousCharacter, false);
+  for (int k = 0; k < number_of_bytes; k++) {
+    AddEncodedOctetToBuffer(s[k], buffer);
+  }
+}
+
+void EncodePair(uc16 cc1, uc16 cc2, List<uint8_t>* buffer) {
+  char s[4] = {};
+  int number_of_bytes =
+      unibrow::Utf8::Encode(s, unibrow::Utf16::CombineSurrogatePair(cc1, cc2),
+                            unibrow::Utf16::kNoPreviousCharacter, false);
+  for (int k = 0; k < number_of_bytes; k++) {
+    AddEncodedOctetToBuffer(s[k], buffer);
+  }
+}
+
+}  // anonymous namespace
+
+MaybeHandle<String> Uri::Encode(Isolate* isolate, Handle<String> uri,
+                                bool is_uri) {
+  uri = String::Flatten(uri);
+  int uri_length = uri->length();
+  List<uint8_t> buffer(uri_length);
+
+  {
+    DisallowHeapAllocation no_gc;
+    String::FlatContent uri_content = uri->GetFlatContent();
+
+    for (int k = 0; k < uri_length; k++) {
+      uc16 cc1 = uri_content.Get(k);
+      if (unibrow::Utf16::IsLeadSurrogate(cc1)) {
+        k++;
+        if (k < uri_length) {
+          uc16 cc2 = uri->Get(k);
+          if (unibrow::Utf16::IsTrailSurrogate(cc2)) {
+            EncodePair(cc1, cc2, &buffer);
+            continue;
+          }
+        }
+      } else if (!unibrow::Utf16::IsTrailSurrogate(cc1)) {
+        if (IsUnescapePredicateInUriComponent(cc1) ||
+            (is_uri && IsUriSeparator(cc1))) {
+          buffer.Add(cc1);
+        } else {
+          EncodeSingle(cc1, &buffer);
+        }
+        continue;
+      }
+
+      AllowHeapAllocation allocate_error_and_return;
+      THROW_NEW_ERROR(isolate, NewURIError(), String);
+    }
+  }
+
+  return isolate->factory()->NewStringFromOneByte(buffer.ToConstVector());
+}
+
+namespace {  // Anonymous namespace for Escape and Unescape
+
+template <typename Char>
+int UnescapeChar(Vector<const Char> vector, int i, int length, int* step) {
+  uint16_t character = vector[i];
+  int32_t hi = 0;
+  int32_t lo = 0;
+  if (character == '%' && i <= length - 6 && vector[i + 1] == 'u' &&
+      (hi = TwoDigitHex(vector[i + 2], vector[i + 3])) > -1 &&
+      (lo = TwoDigitHex(vector[i + 4], vector[i + 5])) > -1) {
+    *step = 6;
+    return (hi << 8) + lo;
+  } else if (character == '%' && i <= length - 3 &&
+             (lo = TwoDigitHex(vector[i + 1], vector[i + 2])) > -1) {
+    *step = 3;
+    return lo;
+  } else {
+    *step = 1;
+    return character;
+  }
+}
+
+template <typename Char>
+MaybeHandle<String> UnescapeSlow(Isolate* isolate, Handle<String> string,
+                                 int start_index) {
+  bool one_byte = true;
+  int length = string->length();
+
+  int unescaped_length = 0;
+  {
+    DisallowHeapAllocation no_allocation;
+    Vector<const Char> vector = string->GetCharVector<Char>();
+    for (int i = start_index; i < length; unescaped_length++) {
+      int step;
+      if (UnescapeChar(vector, i, length, &step) >
+          String::kMaxOneByteCharCode) {
+        one_byte = false;
+      }
+      i += step;
+    }
+  }
+
+  DCHECK(start_index < length);
+  Handle<String> first_part =
+      isolate->factory()->NewProperSubString(string, 0, start_index);
+
+  int dest_position = 0;
+  Handle<String> second_part;
+  DCHECK(unescaped_length <= String::kMaxLength);
+  if (one_byte) {
+    Handle<SeqOneByteString> dest = isolate->factory()
+                                        ->NewRawOneByteString(unescaped_length)
+                                        .ToHandleChecked();
+    DisallowHeapAllocation no_allocation;
+    Vector<const Char> vector = string->GetCharVector<Char>();
+    for (int i = start_index; i < length; dest_position++) {
+      int step;
+      dest->SeqOneByteStringSet(dest_position,
+                                UnescapeChar(vector, i, length, &step));
+      i += step;
+    }
+    second_part = dest;
+  } else {
+    Handle<SeqTwoByteString> dest = isolate->factory()
+                                        ->NewRawTwoByteString(unescaped_length)
+                                        .ToHandleChecked();
+    DisallowHeapAllocation no_allocation;
+    Vector<const Char> vector = string->GetCharVector<Char>();
+    for (int i = start_index; i < length; dest_position++) {
+      int step;
+      dest->SeqTwoByteStringSet(dest_position,
+                                UnescapeChar(vector, i, length, &step));
+      i += step;
+    }
+    second_part = dest;
+  }
+  return isolate->factory()->NewConsString(first_part, second_part);
+}
+
+bool IsNotEscaped(uint16_t c) {
+  if (IsAlphaNumeric(c)) {
+    return true;
+  }
+  //  @*_+-./
+  switch (c) {
+    case '@':
+    case '*':
+    case '_':
+    case '+':
+    case '-':
+    case '.':
+    case '/':
+      return true;
+    default:
+      return false;
+  }
+}
+
+template <typename Char>
+static MaybeHandle<String> UnescapePrivate(Isolate* isolate,
+                                           Handle<String> source) {
+  int index;
+  {
+    DisallowHeapAllocation no_allocation;
+    StringSearch<uint8_t, Char> search(isolate, STATIC_CHAR_VECTOR("%"));
+    index = search.Search(source->GetCharVector<Char>(), 0);
+    if (index < 0) return source;
+  }
+  return UnescapeSlow<Char>(isolate, source, index);
+}
+
+template <typename Char>
+static MaybeHandle<String> EscapePrivate(Isolate* isolate,
+                                         Handle<String> string) {
+  DCHECK(string->IsFlat());
+  int escaped_length = 0;
+  int length = string->length();
+
+  {
+    DisallowHeapAllocation no_allocation;
+    Vector<const Char> vector = string->GetCharVector<Char>();
+    for (int i = 0; i < length; i++) {
+      uint16_t c = vector[i];
+      if (c >= 256) {
+        escaped_length += 6;
+      } else if (IsNotEscaped(c)) {
+        escaped_length++;
+      } else {
+        escaped_length += 3;
+      }
+
+      // We don't allow strings that are longer than a maximal length.
+      DCHECK(String::kMaxLength < 0x7fffffff - 6);     // Cannot overflow.
+      if (escaped_length > String::kMaxLength) break;  // Provoke exception.
+    }
+  }
+
+  // No length change implies no change.  Return original string if no change.
+  if (escaped_length == length) return string;
+
+  Handle<SeqOneByteString> dest;
+  ASSIGN_RETURN_ON_EXCEPTION(
+      isolate, dest, isolate->factory()->NewRawOneByteString(escaped_length),
+      String);
+  int dest_position = 0;
+
+  {
+    DisallowHeapAllocation no_allocation;
+    Vector<const Char> vector = string->GetCharVector<Char>();
+    for (int i = 0; i < length; i++) {
+      uint16_t c = vector[i];
+      if (c >= 256) {
+        dest->SeqOneByteStringSet(dest_position, '%');
+        dest->SeqOneByteStringSet(dest_position + 1, 'u');
+        dest->SeqOneByteStringSet(dest_position + 2, HexCharOfValue(c >> 12));
+        dest->SeqOneByteStringSet(dest_position + 3,
+                                  HexCharOfValue((c >> 8) & 0xf));
+        dest->SeqOneByteStringSet(dest_position + 4,
+                                  HexCharOfValue((c >> 4) & 0xf));
+        dest->SeqOneByteStringSet(dest_position + 5, HexCharOfValue(c & 0xf));
+        dest_position += 6;
+      } else if (IsNotEscaped(c)) {
+        dest->SeqOneByteStringSet(dest_position, c);
+        dest_position++;
+      } else {
+        dest->SeqOneByteStringSet(dest_position, '%');
+        dest->SeqOneByteStringSet(dest_position + 1, HexCharOfValue(c >> 4));
+        dest->SeqOneByteStringSet(dest_position + 2, HexCharOfValue(c & 0xf));
+        dest_position += 3;
+      }
+    }
+  }
+
+  return dest;
+}
+
+}  // Anonymous namespace
+
+MaybeHandle<String> Uri::Escape(Isolate* isolate, Handle<String> string) {
+  Handle<String> result;
+  string = String::Flatten(string);
+  return string->IsOneByteRepresentationUnderneath()
+             ? EscapePrivate<uint8_t>(isolate, string)
+             : EscapePrivate<uc16>(isolate, string);
+}
+
+MaybeHandle<String> Uri::Unescape(Isolate* isolate, Handle<String> string) {
+  Handle<String> result;
+  string = String::Flatten(string);
+  return string->IsOneByteRepresentationUnderneath()
+             ? UnescapePrivate<uint8_t>(isolate, string)
+             : UnescapePrivate<uc16>(isolate, string);
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/src/uri.h b/src/uri.h
new file mode 100644
index 0000000..dfa057f
--- /dev/null
+++ b/src/uri.h
@@ -0,0 +1,54 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_URI_H_
+#define V8_URI_H_
+
+#include "src/allocation.h"
+#include "src/objects.h"
+
+namespace v8 {
+namespace internal {
+
+class Uri : public AllStatic {
+ public:
+  // ES6 section 18.2.6.2 decodeURI (encodedURI)
+  static MaybeHandle<String> DecodeUri(Isolate* isolate, Handle<String> uri) {
+    return Decode(isolate, uri, true);
+  }
+
+  // ES6 section 18.2.6.3 decodeURIComponent (encodedURIComponent)
+  static MaybeHandle<String> DecodeUriComponent(Isolate* isolate,
+                                                Handle<String> component) {
+    return Decode(isolate, component, false);
+  }
+
+  // ES6 section 18.2.6.4 encodeURI (uri)
+  static MaybeHandle<String> EncodeUri(Isolate* isolate, Handle<String> uri) {
+    return Encode(isolate, uri, true);
+  }
+
+  // ES6 section 18.2.6.5 encodeURIComponenet (uriComponent)
+  static MaybeHandle<String> EncodeUriComponent(Isolate* isolate,
+                                                Handle<String> component) {
+    return Encode(isolate, component, false);
+  }
+
+  // ES6 section B.2.1.1 escape (string)
+  static MaybeHandle<String> Escape(Isolate* isolate, Handle<String> string);
+
+  // ES6 section B.2.1.2 unescape (string)
+  static MaybeHandle<String> Unescape(Isolate* isolate, Handle<String> string);
+
+ private:
+  static MaybeHandle<String> Decode(Isolate* isolate, Handle<String> uri,
+                                    bool is_uri);
+  static MaybeHandle<String> Encode(Isolate* isolate, Handle<String> uri,
+                                    bool is_uri);
+};
+
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_URI_H_
diff --git a/src/utils.cc b/src/utils.cc
index c46028f..16b5b7c 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -430,11 +430,8 @@
 
 bool DoubleToBoolean(double d) {
   // NaN, +0, and -0 should return the false object
-#if V8_TARGET_LITTLE_ENDIAN
-  union IeeeDoubleLittleEndianArchType u;
-#else
-  union IeeeDoubleBigEndianArchType u;
-#endif
+  IeeeDoubleArchType u;
+
   u.d = d;
   if (u.bits.exp == 2047) {
     // Detect NaN for IEEE double precision floating point.
diff --git a/src/utils.h b/src/utils.h
index 44865ed..9b94a2f 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -13,6 +13,7 @@
 #include "include/v8.h"
 #include "src/allocation.h"
 #include "src/base/bits.h"
+#include "src/base/compiler-specific.h"
 #include "src/base/logging.h"
 #include "src/base/macros.h"
 #include "src/base/platform/platform.h"
@@ -36,6 +37,11 @@
   return -1;
 }
 
+inline char HexCharOfValue(int value) {
+  DCHECK(0 <= value && value <= 16);
+  if (value < 10) return value + '0';
+  return value - 10 + 'A';
+}
 
 inline int BoolToInt(bool b) { return b ? 1 : 0; }
 
@@ -932,42 +938,21 @@
 // ----------------------------------------------------------------------------
 // I/O support.
 
-#if __GNUC__ >= 4
-// On gcc we can ask the compiler to check the types of %d-style format
-// specifiers and their associated arguments.  TODO(erikcorry) fix this
-// so it works on MacOSX.
-#if defined(__MACH__) && defined(__APPLE__)
-#define PRINTF_CHECKING
-#define FPRINTF_CHECKING
-#define PRINTF_METHOD_CHECKING
-#define FPRINTF_METHOD_CHECKING
-#else  // MacOsX.
-#define PRINTF_CHECKING __attribute__ ((format (printf, 1, 2)))
-#define FPRINTF_CHECKING __attribute__ ((format (printf, 2, 3)))
-#define PRINTF_METHOD_CHECKING __attribute__ ((format (printf, 2, 3)))
-#define FPRINTF_METHOD_CHECKING __attribute__ ((format (printf, 3, 4)))
-#endif
-#else
-#define PRINTF_CHECKING
-#define FPRINTF_CHECKING
-#define PRINTF_METHOD_CHECKING
-#define FPRINTF_METHOD_CHECKING
-#endif
-
 // Our version of printf().
-void PRINTF_CHECKING PrintF(const char* format, ...);
-void FPRINTF_CHECKING PrintF(FILE* out, const char* format, ...);
+void PRINTF_FORMAT(1, 2) PrintF(const char* format, ...);
+void PRINTF_FORMAT(2, 3) PrintF(FILE* out, const char* format, ...);
 
 // Prepends the current process ID to the output.
-void PRINTF_CHECKING PrintPID(const char* format, ...);
+void PRINTF_FORMAT(1, 2) PrintPID(const char* format, ...);
 
 // Prepends the current process ID and given isolate pointer to the output.
-void PrintIsolate(void* isolate, const char* format, ...);
+void PRINTF_FORMAT(2, 3) PrintIsolate(void* isolate, const char* format, ...);
 
 // Safe formatting print. Ensures that str is always null-terminated.
 // Returns the number of chars written, or -1 if output was truncated.
-int FPRINTF_CHECKING SNPrintF(Vector<char> str, const char* format, ...);
-int VSNPrintF(Vector<char> str, const char* format, va_list args);
+int PRINTF_FORMAT(2, 3) SNPrintF(Vector<char> str, const char* format, ...);
+int PRINTF_FORMAT(2, 0)
+    VSNPrintF(Vector<char> str, const char* format, va_list args);
 
 void StrNCpy(Vector<char> dest, const char* src, size_t n);
 
@@ -1470,10 +1455,11 @@
   StringBuilder(char* buffer, int size) : SimpleStringBuilder(buffer, size) { }
 
   // Add formatted contents to the builder just like printf().
-  void AddFormatted(const char* format, ...);
+  void PRINTF_FORMAT(2, 3) AddFormatted(const char* format, ...);
 
   // Add formatted contents like printf based on a va_list.
-  void AddFormattedList(const char* format, va_list list);
+  void PRINTF_FORMAT(2, 0) AddFormattedList(const char* format, va_list list);
+
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
 };
@@ -1538,6 +1524,10 @@
 #endif  // V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
 }
 
+static inline double ReadFloatValue(const void* p) {
+  return ReadUnalignedValue<float>(p);
+}
+
 static inline double ReadDoubleValue(const void* p) {
   return ReadUnalignedValue<double>(p);
 }
diff --git a/src/v8.cc b/src/v8.cc
index 154cf62..d660b58 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -14,9 +14,9 @@
 #include "src/elements.h"
 #include "src/frames.h"
 #include "src/isolate.h"
+#include "src/libsampler/v8-sampler.h"
 #include "src/objects.h"
 #include "src/profiler/heap-profiler.h"
-#include "src/profiler/sampler.h"
 #include "src/runtime-profiler.h"
 #include "src/snapshot/natives.h"
 #include "src/snapshot/snapshot.h"
@@ -45,10 +45,9 @@
   Bootstrapper::TearDownExtensions();
   ElementsAccessor::TearDown();
   LOperand::TearDownCaches();
-  ExternalReference::TearDownMathExpData();
   RegisteredExtension::UnregisterAll();
   Isolate::GlobalTearDown();
-  Sampler::TearDown();
+  sampler::Sampler::TearDown();
   FlagList::ResetAllFlags();  // Frees memory held by string arguments.
 }
 
@@ -76,7 +75,7 @@
 
   Isolate::InitializeOncePerProcess();
 
-  Sampler::SetUp();
+  sampler::Sampler::SetUp();
   CpuFeatures::Probe(false);
   ElementsAccessor::InitializeOncePerProcess();
   LOperand::SetUpCaches();
diff --git a/src/v8.gyp b/src/v8.gyp
new file mode 100644
index 0000000..84c361e
--- /dev/null
+++ b/src/v8.gyp
@@ -0,0 +1,2297 @@
+# Copyright 2012 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * 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.
+
+{
+  'variables': {
+    'v8_code': 1,
+    'v8_random_seed%': 314159265,
+    'v8_vector_stores%': 0,
+    'embed_script%': "",
+    'warmup_script%': "",
+    'v8_extra_library_files%': [],
+    'v8_experimental_extra_library_files%': [],
+    'mksnapshot_exec': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)mksnapshot<(EXECUTABLE_SUFFIX)',
+  },
+  'includes': ['../gypfiles/toolchain.gypi', '../gypfiles/features.gypi'],
+  'targets': [
+    {
+      'target_name': 'v8',
+      'dependencies_traverse': 1,
+      'dependencies': ['v8_maybe_snapshot'],
+      'conditions': [
+        ['want_separate_host_toolset==1', {
+          'toolsets': ['host', 'target'],
+        }, {
+          'toolsets': ['target'],
+        }],
+        ['component=="shared_library"', {
+          'type': '<(component)',
+          'sources': [
+            # Note: on non-Windows we still build this file so that gyp
+            # has some sources to link into the component.
+            'v8dll-main.cc',
+          ],
+          'include_dirs': [
+            '..',
+          ],
+          'defines': [
+            'V8_SHARED',
+            'BUILDING_V8_SHARED',
+          ],
+          'direct_dependent_settings': {
+            'defines': [
+              'V8_SHARED',
+              'USING_V8_SHARED',
+            ],
+          },
+          'target_conditions': [
+            ['OS=="android" and _toolset=="target"', {
+              'libraries': [
+                '-llog',
+              ],
+              'include_dirs': [
+                'src/common/android/include',
+              ],
+            }],
+          ],
+          'conditions': [
+            ['OS=="mac"', {
+              'xcode_settings': {
+                'OTHER_LDFLAGS': ['-dynamiclib', '-all_load']
+              },
+            }],
+            ['soname_version!=""', {
+              'product_extension': 'so.<(soname_version)',
+            }],
+          ],
+        },
+        {
+          'type': 'none',
+        }],
+      ],
+      'direct_dependent_settings': {
+        'include_dirs': [
+          '../include',
+        ],
+      },
+    },
+    {
+      # This rule delegates to either v8_snapshot, v8_nosnapshot, or
+      # v8_external_snapshot, depending on the current variables.
+      # The intention is to make the 'calling' rules a bit simpler.
+      'target_name': 'v8_maybe_snapshot',
+      'type': 'none',
+      'conditions': [
+        ['v8_use_snapshot!="true"', {
+          # The dependency on v8_base should come from a transitive
+          # dependency however the Android toolchain requires libv8_base.a
+          # to appear before libv8_snapshot.a so it's listed explicitly.
+          'dependencies': ['v8_base', 'v8_nosnapshot'],
+        }],
+        ['v8_use_snapshot=="true" and v8_use_external_startup_data==0', {
+          # The dependency on v8_base should come from a transitive
+          # dependency however the Android toolchain requires libv8_base.a
+          # to appear before libv8_snapshot.a so it's listed explicitly.
+          'dependencies': ['v8_base', 'v8_snapshot'],
+        }],
+        ['v8_use_snapshot=="true" and v8_use_external_startup_data==1 and want_separate_host_toolset==0', {
+          'dependencies': ['v8_base', 'v8_external_snapshot'],
+          'inputs': [ '<(PRODUCT_DIR)/snapshot_blob.bin', ],
+        }],
+        ['v8_use_snapshot=="true" and v8_use_external_startup_data==1 and want_separate_host_toolset==1', {
+          'dependencies': ['v8_base', 'v8_external_snapshot'],
+          'target_conditions': [
+            ['_toolset=="host"', {
+              'inputs': [
+                '<(PRODUCT_DIR)/snapshot_blob_host.bin',
+              ],
+            }, {
+              'inputs': [
+                '<(PRODUCT_DIR)/snapshot_blob.bin',
+              ],
+            }],
+          ],
+        }],
+        ['want_separate_host_toolset==1', {
+          'toolsets': ['host', 'target'],
+        }, {
+          'toolsets': ['target'],
+        }],
+      ]
+    },
+    {
+      'target_name': 'v8_snapshot',
+      'type': 'static_library',
+      'conditions': [
+        ['want_separate_host_toolset==1', {
+          'toolsets': ['host', 'target'],
+          'dependencies': [
+            'mksnapshot#host',
+            'js2c#host',
+          ],
+        }, {
+          'toolsets': ['target'],
+          'dependencies': [
+            'mksnapshot',
+            'js2c',
+          ],
+        }],
+        ['component=="shared_library"', {
+          'defines': [
+            'V8_SHARED',
+            'BUILDING_V8_SHARED',
+          ],
+          'direct_dependent_settings': {
+            'defines': [
+              'V8_SHARED',
+              'USING_V8_SHARED',
+            ],
+          },
+        }],
+      ],
+      'dependencies': [
+        'v8_base',
+      ],
+      'include_dirs+': [
+        '..',
+      ],
+      'sources': [
+        '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
+        '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc',
+        '<(SHARED_INTERMEDIATE_DIR)/extras-libraries.cc',
+        '<(SHARED_INTERMEDIATE_DIR)/experimental-extras-libraries.cc',
+        '<(INTERMEDIATE_DIR)/snapshot.cc',
+      ],
+      'actions': [
+        {
+          'action_name': 'run_mksnapshot',
+          'inputs': [
+            '<(mksnapshot_exec)',
+          ],
+          'conditions': [
+            ['embed_script!=""', {
+              'inputs': [
+                '<(embed_script)',
+              ],
+            }],
+            ['warmup_script!=""', {
+              'inputs': [
+                '<(warmup_script)',
+              ],
+            }],
+          ],
+          'outputs': [
+            '<(INTERMEDIATE_DIR)/snapshot.cc',
+          ],
+          'variables': {
+            'mksnapshot_flags': [],
+            'conditions': [
+              ['v8_random_seed!=0', {
+                'mksnapshot_flags': ['--random-seed', '<(v8_random_seed)'],
+              }],
+              ['v8_vector_stores!=0', {
+                'mksnapshot_flags': ['--vector-stores'],
+              }],
+            ],
+          },
+          'action': [
+            '<(mksnapshot_exec)',
+            '<@(mksnapshot_flags)',
+            '--startup_src', '<@(INTERMEDIATE_DIR)/snapshot.cc',
+            '<(embed_script)',
+            '<(warmup_script)',
+          ],
+        },
+      ],
+    },
+    {
+      'target_name': 'v8_nosnapshot',
+      'type': 'static_library',
+      'dependencies': [
+        'v8_base',
+      ],
+      'include_dirs+': [
+        '..',
+      ],
+      'sources': [
+        '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
+        '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc',
+        '<(SHARED_INTERMEDIATE_DIR)/extras-libraries.cc',
+        '<(SHARED_INTERMEDIATE_DIR)/experimental-extras-libraries.cc',
+        'snapshot/snapshot-empty.cc',
+      ],
+      'conditions': [
+        ['want_separate_host_toolset==1', {
+          'toolsets': ['host', 'target'],
+          'dependencies': ['js2c#host'],
+        }, {
+          'toolsets': ['target'],
+          'dependencies': ['js2c'],
+        }],
+        ['component=="shared_library"', {
+          'defines': [
+            'BUILDING_V8_SHARED',
+            'V8_SHARED',
+          ],
+        }],
+      ]
+    },
+    {
+      'target_name': 'v8_external_snapshot',
+      'type': 'static_library',
+      'conditions': [
+        [ 'v8_use_external_startup_data==1', {
+          'conditions': [
+            ['want_separate_host_toolset==1', {
+              'toolsets': ['host', 'target'],
+              'dependencies': [
+                'mksnapshot#host',
+                'js2c#host',
+                'natives_blob',
+            ]}, {
+              'toolsets': ['target'],
+              'dependencies': [
+                'mksnapshot',
+                'js2c',
+                'natives_blob',
+              ],
+            }],
+            ['component=="shared_library"', {
+              'defines': [
+                'V8_SHARED',
+                'BUILDING_V8_SHARED',
+              ],
+              'direct_dependent_settings': {
+                'defines': [
+                  'V8_SHARED',
+                  'USING_V8_SHARED',
+                ],
+              },
+            }],
+          ],
+          'dependencies': [
+            'v8_base',
+          ],
+          'include_dirs+': [
+            '..',
+          ],
+          'sources': [
+            'snapshot/natives-external.cc',
+            'snapshot/snapshot-external.cc',
+          ],
+          'actions': [
+            {
+              'action_name': 'run_mksnapshot (external)',
+              'inputs': [
+                '<(mksnapshot_exec)',
+              ],
+              'variables': {
+                'mksnapshot_flags': [],
+                'conditions': [
+                  ['v8_random_seed!=0', {
+                    'mksnapshot_flags': ['--random-seed', '<(v8_random_seed)'],
+                  }],
+                  ['v8_vector_stores!=0', {
+                    'mksnapshot_flags': ['--vector-stores'],
+                  }],
+                ],
+              },
+              'conditions': [
+                ['embed_script!=""', {
+                  'inputs': [
+                    '<(embed_script)',
+                  ],
+                }],
+                ['warmup_script!=""', {
+                  'inputs': [
+                    '<(warmup_script)',
+                  ],
+                }],
+                ['want_separate_host_toolset==1', {
+                  'target_conditions': [
+                    ['_toolset=="host"', {
+                      'outputs': [
+                        '<(PRODUCT_DIR)/snapshot_blob_host.bin',
+                      ],
+                      'action': [
+                        '<(mksnapshot_exec)',
+                        '<@(mksnapshot_flags)',
+                        '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob_host.bin',
+                        '<(embed_script)',
+                        '<(warmup_script)',
+                      ],
+                    }, {
+                      'outputs': [
+                        '<(PRODUCT_DIR)/snapshot_blob.bin',
+                      ],
+                      'action': [
+                        '<(mksnapshot_exec)',
+                        '<@(mksnapshot_flags)',
+                        '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob.bin',
+                        '<(embed_script)',
+                        '<(warmup_script)',
+                      ],
+                    }],
+                  ],
+                }, {
+                  'outputs': [
+                    '<(PRODUCT_DIR)/snapshot_blob.bin',
+                  ],
+                  'action': [
+                    '<(mksnapshot_exec)',
+                    '<@(mksnapshot_flags)',
+                    '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob.bin',
+                    '<(embed_script)',
+                    '<(warmup_script)',
+                  ],
+                }],
+              ],
+            },
+          ],
+        }],
+      ],
+    },
+    {
+      'target_name': 'v8_base',
+      'type': 'static_library',
+      'dependencies': [
+        'v8_libbase',
+        'v8_libsampler',
+      ],
+      'variables': {
+        'optimize': 'max',
+      },
+      'include_dirs+': [
+        '..',
+        '<(DEPTH)',
+      ],
+      'sources': [  ### gcmole(all) ###
+        '../include/v8-debug.h',
+        '../include/v8-experimental.h',
+        '../include/v8-platform.h',
+        '../include/v8-profiler.h',
+        '../include/v8-testing.h',
+        '../include/v8-util.h',
+        '../include/v8-version.h',
+        '../include/v8.h',
+        '../include/v8config.h',
+        'accessors.cc',
+        'accessors.h',
+        'address-map.cc',
+        'address-map.h',
+        'allocation.cc',
+        'allocation.h',
+        'allocation-site-scopes.cc',
+        'allocation-site-scopes.h',
+        'api-experimental.cc',
+        'api-experimental.h',
+        'api.cc',
+        'api.h',
+        'api-arguments-inl.h',
+        'api-arguments.cc',
+        'api-arguments.h',
+        'api-natives.cc',
+        'api-natives.h',
+        'arguments.cc',
+        'arguments.h',
+        'assembler.cc',
+        'assembler.h',
+        'assert-scope.h',
+        'assert-scope.cc',
+        'ast/ast-expression-rewriter.cc',
+        'ast/ast-expression-rewriter.h',
+        'ast/ast-expression-visitor.cc',
+        'ast/ast-expression-visitor.h',
+        'ast/ast-literal-reindexer.cc',
+        'ast/ast-literal-reindexer.h',
+        'ast/ast-numbering.cc',
+        'ast/ast-numbering.h',
+        'ast/ast-type-bounds.h',
+        'ast/ast-value-factory.cc',
+        'ast/ast-value-factory.h',
+        'ast/ast.cc',
+        'ast/ast.h',
+        'ast/modules.cc',
+        'ast/modules.h',
+        'ast/prettyprinter.cc',
+        'ast/prettyprinter.h',
+        'ast/scopeinfo.cc',
+        'ast/scopeinfo.h',
+        'ast/scopes.cc',
+        'ast/scopes.h',
+        'ast/variables.cc',
+        'ast/variables.h',
+        'background-parsing-task.cc',
+        'background-parsing-task.h',
+        'bailout-reason.cc',
+        'bailout-reason.h',
+        'basic-block-profiler.cc',
+        'basic-block-profiler.h',
+        'bignum-dtoa.cc',
+        'bignum-dtoa.h',
+        'bignum.cc',
+        'bignum.h',
+        'bit-vector.cc',
+        'bit-vector.h',
+        'bootstrapper.cc',
+        'bootstrapper.h',
+        'builtins.cc',
+        'builtins.h',
+        'cached-powers.cc',
+        'cached-powers.h',
+        'cancelable-task.cc',
+        'cancelable-task.h',
+        'char-predicates.cc',
+        'char-predicates-inl.h',
+        'char-predicates.h',
+        'checks.h',
+        'code-events.h',
+        'code-factory.cc',
+        'code-factory.h',
+        'code-stub-assembler.cc',
+        'code-stub-assembler.h',
+        'code-stubs.cc',
+        'code-stubs.h',
+        'code-stubs-hydrogen.cc',
+        'codegen.cc',
+        'codegen.h',
+        'collector.h',
+        'compilation-cache.cc',
+        'compilation-cache.h',
+        'compilation-dependencies.cc',
+        'compilation-dependencies.h',
+        'compilation-statistics.cc',
+        'compilation-statistics.h',
+        'compiler/access-builder.cc',
+        'compiler/access-builder.h',
+        'compiler/access-info.cc',
+        'compiler/access-info.h',
+        'compiler/all-nodes.cc',
+        'compiler/all-nodes.h',
+        'compiler/ast-graph-builder.cc',
+        'compiler/ast-graph-builder.h',
+        'compiler/ast-loop-assignment-analyzer.cc',
+        'compiler/ast-loop-assignment-analyzer.h',
+        'compiler/basic-block-instrumentor.cc',
+        'compiler/basic-block-instrumentor.h',
+        'compiler/branch-elimination.cc',
+        'compiler/branch-elimination.h',
+        'compiler/bytecode-branch-analysis.cc',
+        'compiler/bytecode-branch-analysis.h',
+        'compiler/bytecode-graph-builder.cc',
+        'compiler/bytecode-graph-builder.h',
+        'compiler/c-linkage.cc',
+        'compiler/checkpoint-elimination.cc',
+        'compiler/checkpoint-elimination.h',
+        'compiler/code-generator-impl.h',
+        'compiler/code-generator.cc',
+        'compiler/code-generator.h',
+        'compiler/code-assembler.cc',
+        'compiler/code-assembler.h',
+        'compiler/common-node-cache.cc',
+        'compiler/common-node-cache.h',
+        'compiler/common-operator-reducer.cc',
+        'compiler/common-operator-reducer.h',
+        'compiler/common-operator.cc',
+        'compiler/common-operator.h',
+        'compiler/control-builders.cc',
+        'compiler/control-builders.h',
+        'compiler/control-equivalence.cc',
+        'compiler/control-equivalence.h',
+        'compiler/control-flow-optimizer.cc',
+        'compiler/control-flow-optimizer.h',
+        'compiler/dead-code-elimination.cc',
+        'compiler/dead-code-elimination.h',
+        'compiler/diamond.h',
+        'compiler/effect-control-linearizer.cc',
+        'compiler/effect-control-linearizer.h',
+        'compiler/escape-analysis.cc',
+        'compiler/escape-analysis.h',
+        "compiler/escape-analysis-reducer.cc",
+        "compiler/escape-analysis-reducer.h",
+        'compiler/frame.cc',
+        'compiler/frame.h',
+        'compiler/frame-elider.cc',
+        'compiler/frame-elider.h',
+        "compiler/frame-states.cc",
+        "compiler/frame-states.h",
+        'compiler/gap-resolver.cc',
+        'compiler/gap-resolver.h',
+        'compiler/graph-reducer.cc',
+        'compiler/graph-reducer.h',
+        'compiler/graph-replay.cc',
+        'compiler/graph-replay.h',
+        'compiler/graph-trimmer.cc',
+        'compiler/graph-trimmer.h',
+        'compiler/graph-visualizer.cc',
+        'compiler/graph-visualizer.h',
+        'compiler/graph.cc',
+        'compiler/graph.h',
+        'compiler/instruction-codes.h',
+        'compiler/instruction-selector-impl.h',
+        'compiler/instruction-selector.cc',
+        'compiler/instruction-selector.h',
+        'compiler/instruction-scheduler.cc',
+        'compiler/instruction-scheduler.h',
+        'compiler/instruction.cc',
+        'compiler/instruction.h',
+        'compiler/int64-lowering.cc',
+        'compiler/int64-lowering.h',
+        'compiler/js-builtin-reducer.cc',
+        'compiler/js-builtin-reducer.h',
+        'compiler/js-call-reducer.cc',
+        'compiler/js-call-reducer.h',
+        'compiler/js-context-specialization.cc',
+        'compiler/js-context-specialization.h',
+        'compiler/js-create-lowering.cc',
+        'compiler/js-create-lowering.h',
+        'compiler/js-frame-specialization.cc',
+        'compiler/js-frame-specialization.h',
+        'compiler/js-generic-lowering.cc',
+        'compiler/js-generic-lowering.h',
+        'compiler/js-global-object-specialization.cc',
+        'compiler/js-global-object-specialization.h',
+        'compiler/js-graph.cc',
+        'compiler/js-graph.h',
+        'compiler/js-inlining.cc',
+        'compiler/js-inlining.h',
+        'compiler/js-inlining-heuristic.cc',
+        'compiler/js-inlining-heuristic.h',
+        'compiler/js-intrinsic-lowering.cc',
+        'compiler/js-intrinsic-lowering.h',
+        'compiler/js-native-context-specialization.cc',
+        'compiler/js-native-context-specialization.h',
+        'compiler/js-operator.cc',
+        'compiler/js-operator.h',
+        'compiler/js-typed-lowering.cc',
+        'compiler/js-typed-lowering.h',
+        'compiler/jump-threading.cc',
+        'compiler/jump-threading.h',
+        'compiler/linkage.cc',
+        'compiler/linkage.h',
+        'compiler/liveness-analyzer.cc',
+        'compiler/liveness-analyzer.h',
+        'compiler/live-range-separator.cc',
+        'compiler/live-range-separator.h',
+        'compiler/load-elimination.cc',
+        'compiler/load-elimination.h',
+        'compiler/loop-analysis.cc',
+        'compiler/loop-analysis.h',
+        'compiler/loop-peeling.cc',
+        'compiler/loop-peeling.h',
+        'compiler/machine-operator-reducer.cc',
+        'compiler/machine-operator-reducer.h',
+        'compiler/machine-operator.cc',
+        'compiler/machine-operator.h',
+        'compiler/memory-optimizer.cc',
+        'compiler/memory-optimizer.h',
+        'compiler/move-optimizer.cc',
+        'compiler/move-optimizer.h',
+        'compiler/node-aux-data.h',
+        'compiler/node-cache.cc',
+        'compiler/node-cache.h',
+        'compiler/node-marker.cc',
+        'compiler/node-marker.h',
+        'compiler/node-matchers.cc',
+        'compiler/node-matchers.h',
+        'compiler/node-properties.cc',
+        'compiler/node-properties.h',
+        'compiler/node.cc',
+        'compiler/node.h',
+        'compiler/opcodes.cc',
+        'compiler/opcodes.h',
+        'compiler/operation-typer.cc',
+        'compiler/operation-typer.h',
+        'compiler/operator-properties.cc',
+        'compiler/operator-properties.h',
+        'compiler/operator.cc',
+        'compiler/operator.h',
+        'compiler/osr.cc',
+        'compiler/osr.h',
+        'compiler/pipeline.cc',
+        'compiler/pipeline.h',
+        'compiler/pipeline-statistics.cc',
+        'compiler/pipeline-statistics.h',
+        'compiler/raw-machine-assembler.cc',
+        'compiler/raw-machine-assembler.h',
+        'compiler/redundancy-elimination.cc',
+        'compiler/redundancy-elimination.h',
+        'compiler/register-allocator.cc',
+        'compiler/register-allocator.h',
+        'compiler/register-allocator-verifier.cc',
+        'compiler/register-allocator-verifier.h',
+        'compiler/representation-change.cc',
+        'compiler/representation-change.h',
+        'compiler/schedule.cc',
+        'compiler/schedule.h',
+        'compiler/scheduler.cc',
+        'compiler/scheduler.h',
+        'compiler/select-lowering.cc',
+        'compiler/select-lowering.h',
+        'compiler/simplified-lowering.cc',
+        'compiler/simplified-lowering.h',
+        'compiler/simplified-operator-reducer.cc',
+        'compiler/simplified-operator-reducer.h',
+        'compiler/simplified-operator.cc',
+        'compiler/simplified-operator.h',
+        'compiler/source-position.cc',
+        'compiler/source-position.h',
+        'compiler/state-values-utils.cc',
+        'compiler/state-values-utils.h',
+        'compiler/store-store-elimination.cc',
+        'compiler/store-store-elimination.h',
+        'compiler/tail-call-optimization.cc',
+        'compiler/tail-call-optimization.h',
+        'compiler/type-hint-analyzer.cc',
+        'compiler/type-hint-analyzer.h',
+        'compiler/type-hints.cc',
+        'compiler/type-hints.h',
+        'compiler/typer.cc',
+        'compiler/typer.h',
+        'compiler/value-numbering-reducer.cc',
+        'compiler/value-numbering-reducer.h',
+        'compiler/verifier.cc',
+        'compiler/verifier.h',
+        'compiler/wasm-compiler.cc',
+        'compiler/wasm-compiler.h',
+        'compiler/wasm-linkage.cc',
+        'compiler/zone-pool.cc',
+        'compiler/zone-pool.h',
+        'compiler.cc',
+        'compiler.h',
+        'context-measure.cc',
+        'context-measure.h',
+        'contexts-inl.h',
+        'contexts.cc',
+        'contexts.h',
+        'conversions-inl.h',
+        'conversions.cc',
+        'conversions.h',
+        'counters-inl.h',
+        'counters.cc',
+        'counters.h',
+        'crankshaft/compilation-phase.cc',
+        'crankshaft/compilation-phase.h',
+        'crankshaft/hydrogen-alias-analysis.h',
+        'crankshaft/hydrogen-bce.cc',
+        'crankshaft/hydrogen-bce.h',
+        'crankshaft/hydrogen-canonicalize.cc',
+        'crankshaft/hydrogen-canonicalize.h',
+        'crankshaft/hydrogen-check-elimination.cc',
+        'crankshaft/hydrogen-check-elimination.h',
+        'crankshaft/hydrogen-dce.cc',
+        'crankshaft/hydrogen-dce.h',
+        'crankshaft/hydrogen-dehoist.cc',
+        'crankshaft/hydrogen-dehoist.h',
+        'crankshaft/hydrogen-environment-liveness.cc',
+        'crankshaft/hydrogen-environment-liveness.h',
+        'crankshaft/hydrogen-escape-analysis.cc',
+        'crankshaft/hydrogen-escape-analysis.h',
+        'crankshaft/hydrogen-flow-engine.h',
+        'crankshaft/hydrogen-gvn.cc',
+        'crankshaft/hydrogen-gvn.h',
+        'crankshaft/hydrogen-infer-representation.cc',
+        'crankshaft/hydrogen-infer-representation.h',
+        'crankshaft/hydrogen-infer-types.cc',
+        'crankshaft/hydrogen-infer-types.h',
+        'crankshaft/hydrogen-instructions.cc',
+        'crankshaft/hydrogen-instructions.h',
+        'crankshaft/hydrogen-load-elimination.cc',
+        'crankshaft/hydrogen-load-elimination.h',
+        'crankshaft/hydrogen-mark-deoptimize.cc',
+        'crankshaft/hydrogen-mark-deoptimize.h',
+        'crankshaft/hydrogen-mark-unreachable.cc',
+        'crankshaft/hydrogen-mark-unreachable.h',
+        'crankshaft/hydrogen-osr.cc',
+        'crankshaft/hydrogen-osr.h',
+        'crankshaft/hydrogen-range-analysis.cc',
+        'crankshaft/hydrogen-range-analysis.h',
+        'crankshaft/hydrogen-redundant-phi.cc',
+        'crankshaft/hydrogen-redundant-phi.h',
+        'crankshaft/hydrogen-removable-simulates.cc',
+        'crankshaft/hydrogen-removable-simulates.h',
+        'crankshaft/hydrogen-representation-changes.cc',
+        'crankshaft/hydrogen-representation-changes.h',
+        'crankshaft/hydrogen-sce.cc',
+        'crankshaft/hydrogen-sce.h',
+        'crankshaft/hydrogen-store-elimination.cc',
+        'crankshaft/hydrogen-store-elimination.h',
+        'crankshaft/hydrogen-types.cc',
+        'crankshaft/hydrogen-types.h',
+        'crankshaft/hydrogen-uint32-analysis.cc',
+        'crankshaft/hydrogen-uint32-analysis.h',
+        'crankshaft/hydrogen.cc',
+        'crankshaft/hydrogen.h',
+        'crankshaft/lithium-allocator-inl.h',
+        'crankshaft/lithium-allocator.cc',
+        'crankshaft/lithium-allocator.h',
+        'crankshaft/lithium-codegen.cc',
+        'crankshaft/lithium-codegen.h',
+        'crankshaft/lithium.cc',
+        'crankshaft/lithium.h',
+        'crankshaft/lithium-inl.h',
+        'crankshaft/typing.cc',
+        'crankshaft/typing.h',
+        'crankshaft/unique.h',
+        'date.cc',
+        'date.h',
+        'dateparser-inl.h',
+        'dateparser.cc',
+        'dateparser.h',
+        'debug/debug-evaluate.cc',
+        'debug/debug-evaluate.h',
+        'debug/debug-frames.cc',
+        'debug/debug-frames.h',
+        'debug/debug-scopes.cc',
+        'debug/debug-scopes.h',
+        'debug/debug.cc',
+        'debug/debug.h',
+        'debug/liveedit.cc',
+        'debug/liveedit.h',
+        'deoptimizer.cc',
+        'deoptimizer.h',
+        'disasm.h',
+        'disassembler.cc',
+        'disassembler.h',
+        'diy-fp.cc',
+        'diy-fp.h',
+        'double.h',
+        'dtoa.cc',
+        'dtoa.h',
+        'effects.h',
+        'eh-frame.cc',
+        'eh-frame.h',
+        'elements-kind.cc',
+        'elements-kind.h',
+        'elements.cc',
+        'elements.h',
+        'execution.cc',
+        'execution.h',
+        'extensions/externalize-string-extension.cc',
+        'extensions/externalize-string-extension.h',
+        'extensions/free-buffer-extension.cc',
+        'extensions/free-buffer-extension.h',
+        'extensions/gc-extension.cc',
+        'extensions/gc-extension.h',
+        'extensions/ignition-statistics-extension.cc',
+        'extensions/ignition-statistics-extension.h',
+        'extensions/statistics-extension.cc',
+        'extensions/statistics-extension.h',
+        'extensions/trigger-failure-extension.cc',
+        'extensions/trigger-failure-extension.h',
+        'external-reference-table.cc',
+        'external-reference-table.h',
+        'factory.cc',
+        'factory.h',
+        'fast-accessor-assembler.cc',
+        'fast-accessor-assembler.h',
+        'fast-dtoa.cc',
+        'fast-dtoa.h',
+        'field-index.h',
+        'field-index-inl.h',
+        'field-type.cc',
+        'field-type.h',
+        'fixed-dtoa.cc',
+        'fixed-dtoa.h',
+        'flag-definitions.h',
+        'flags.cc',
+        'flags.h',
+        'frames-inl.h',
+        'frames.cc',
+        'frames.h',
+        'full-codegen/full-codegen.cc',
+        'full-codegen/full-codegen.h',
+        'futex-emulation.cc',
+        'futex-emulation.h',
+        'gdb-jit.cc',
+        'gdb-jit.h',
+        'global-handles.cc',
+        'global-handles.h',
+        'globals.h',
+        'handles-inl.h',
+        'handles.cc',
+        'handles.h',
+        'heap-symbols.h',
+        'heap/array-buffer-tracker-inl.h',
+        'heap/array-buffer-tracker.cc',
+        'heap/array-buffer-tracker.h',
+        'heap/memory-reducer.cc',
+        'heap/memory-reducer.h',
+        'heap/gc-idle-time-handler.cc',
+        'heap/gc-idle-time-handler.h',
+        'heap/gc-tracer.cc',
+        'heap/gc-tracer.h',
+        'heap/heap-inl.h',
+        'heap/heap.cc',
+        'heap/heap.h',
+        'heap/incremental-marking-inl.h',
+        'heap/incremental-marking-job.cc',
+        'heap/incremental-marking-job.h',
+        'heap/incremental-marking.cc',
+        'heap/incremental-marking.h',
+        'heap/mark-compact-inl.h',
+        'heap/mark-compact.cc',
+        'heap/mark-compact.h',
+        'heap/object-stats.cc',
+        'heap/object-stats.h',
+        'heap/objects-visiting-inl.h',
+        'heap/objects-visiting.cc',
+        'heap/objects-visiting.h',
+        'heap/page-parallel-job.h',
+        'heap/remembered-set.cc',
+        'heap/remembered-set.h',
+        'heap/scavenge-job.h',
+        'heap/scavenge-job.cc',
+        'heap/scavenger-inl.h',
+        'heap/scavenger.cc',
+        'heap/scavenger.h',
+        'heap/slot-set.h',
+        'heap/spaces-inl.h',
+        'heap/spaces.cc',
+        'heap/spaces.h',
+        'heap/store-buffer.cc',
+        'heap/store-buffer.h',
+        'i18n.cc',
+        'i18n.h',
+        'icu_util.cc',
+        'icu_util.h',
+        'ic/access-compiler.cc',
+        'ic/access-compiler.h',
+        'ic/call-optimization.cc',
+        'ic/call-optimization.h',
+        'ic/handler-compiler.cc',
+        'ic/handler-compiler.h',
+        'ic/ic-inl.h',
+        'ic/ic-state.cc',
+        'ic/ic-state.h',
+        'ic/ic.cc',
+        'ic/ic.h',
+        'ic/ic-compiler.cc',
+        'ic/ic-compiler.h',
+        'identity-map.cc',
+        'identity-map.h',
+        'interface-descriptors.cc',
+        'interface-descriptors.h',
+        'interpreter/bytecodes.cc',
+        'interpreter/bytecodes.h',
+        'interpreter/bytecode-array-builder.cc',
+        'interpreter/bytecode-array-builder.h',
+        'interpreter/bytecode-array-iterator.cc',
+        'interpreter/bytecode-array-iterator.h',
+        'interpreter/bytecode-array-writer.cc',
+        'interpreter/bytecode-array-writer.h',
+        'interpreter/bytecode-dead-code-optimizer.cc',
+        'interpreter/bytecode-dead-code-optimizer.h',
+        'interpreter/bytecode-label.h',
+        'interpreter/bytecode-generator.cc',
+        'interpreter/bytecode-generator.h',
+        'interpreter/bytecode-peephole-optimizer.cc',
+        'interpreter/bytecode-peephole-optimizer.h',
+        'interpreter/bytecode-pipeline.cc',
+        'interpreter/bytecode-pipeline.h',
+        'interpreter/bytecode-register-allocator.cc',
+        'interpreter/bytecode-register-allocator.h',
+        'interpreter/bytecode-register-optimizer.cc',
+        'interpreter/bytecode-register-optimizer.h',
+        'interpreter/bytecode-traits.h',
+        'interpreter/constant-array-builder.cc',
+        'interpreter/constant-array-builder.h',
+        'interpreter/control-flow-builders.cc',
+        'interpreter/control-flow-builders.h',
+        'interpreter/handler-table-builder.cc',
+        'interpreter/handler-table-builder.h',
+        'interpreter/interpreter.cc',
+        'interpreter/interpreter.h',
+        'interpreter/interpreter-assembler.cc',
+        'interpreter/interpreter-assembler.h',
+        'interpreter/interpreter-intrinsics.cc',
+        'interpreter/interpreter-intrinsics.h',
+        'interpreter/source-position-table.cc',
+        'interpreter/source-position-table.h',
+        'isolate-inl.h',
+        'isolate.cc',
+        'isolate.h',
+        'json-parser.cc',
+        'json-parser.h',
+        'json-stringifier.cc',
+        'json-stringifier.h',
+        'keys.h',
+        'keys.cc',
+        'layout-descriptor-inl.h',
+        'layout-descriptor.cc',
+        'layout-descriptor.h',
+        'list-inl.h',
+        'list.h',
+        'locked-queue-inl.h',
+        'locked-queue.h',
+        'log-inl.h',
+        'log-utils.cc',
+        'log-utils.h',
+        'log.cc',
+        'log.h',
+        'lookup.cc',
+        'lookup.h',
+        'macro-assembler.h',
+        'machine-type.cc',
+        'machine-type.h',
+        'messages.cc',
+        'messages.h',
+        'msan.h',
+        'objects-body-descriptors-inl.h',
+        'objects-body-descriptors.h',
+        'objects-debug.cc',
+        'objects-inl.h',
+        'objects-printer.cc',
+        'objects.cc',
+        'objects.h',
+        'optimizing-compile-dispatcher.cc',
+        'optimizing-compile-dispatcher.h',
+        'ostreams.cc',
+        'ostreams.h',
+        'parsing/expression-classifier.h',
+        'parsing/func-name-inferrer.cc',
+        'parsing/func-name-inferrer.h',
+        'parsing/parameter-initializer-rewriter.cc',
+        'parsing/parameter-initializer-rewriter.h',
+        'parsing/parser-base.h',
+        'parsing/parser.cc',
+        'parsing/parser.h',
+        'parsing/pattern-rewriter.cc',
+        'parsing/preparse-data-format.h',
+        'parsing/preparse-data.cc',
+        'parsing/preparse-data.h',
+        'parsing/preparser.cc',
+        'parsing/preparser.h',
+        'parsing/rewriter.cc',
+        'parsing/rewriter.h',
+        'parsing/scanner-character-streams.cc',
+        'parsing/scanner-character-streams.h',
+        'parsing/scanner.cc',
+        'parsing/scanner.h',
+        'parsing/token.cc',
+        'parsing/token.h',
+        'pending-compilation-error-handler.cc',
+        'pending-compilation-error-handler.h',
+        'perf-jit.cc',
+        'perf-jit.h',
+        'profiler/allocation-tracker.cc',
+        'profiler/allocation-tracker.h',
+        'profiler/circular-queue-inl.h',
+        'profiler/circular-queue.h',
+        'profiler/cpu-profiler-inl.h',
+        'profiler/cpu-profiler.cc',
+        'profiler/cpu-profiler.h',
+        'profiler/heap-profiler.cc',
+        'profiler/heap-profiler.h',
+        'profiler/heap-snapshot-generator-inl.h',
+        'profiler/heap-snapshot-generator.cc',
+        'profiler/heap-snapshot-generator.h',
+        'profiler/profiler-listener.cc',
+        'profiler/profiler-listener.h',
+        'profiler/profile-generator-inl.h',
+        'profiler/profile-generator.cc',
+        'profiler/profile-generator.h',
+        'profiler/sampling-heap-profiler.cc',
+        'profiler/sampling-heap-profiler.h',
+        'profiler/strings-storage.cc',
+        'profiler/strings-storage.h',
+        'profiler/tick-sample.cc',
+        'profiler/tick-sample.h',
+        'profiler/unbound-queue-inl.h',
+        'profiler/unbound-queue.h',
+        'property-descriptor.cc',
+        'property-descriptor.h',
+        'property-details.h',
+        'property.cc',
+        'property.h',
+        'prototype.h',
+        'regexp/bytecodes-irregexp.h',
+        'regexp/interpreter-irregexp.cc',
+        'regexp/interpreter-irregexp.h',
+        'regexp/jsregexp-inl.h',
+        'regexp/jsregexp.cc',
+        'regexp/jsregexp.h',
+        'regexp/regexp-ast.cc',
+        'regexp/regexp-ast.h',
+        'regexp/regexp-macro-assembler-irregexp-inl.h',
+        'regexp/regexp-macro-assembler-irregexp.cc',
+        'regexp/regexp-macro-assembler-irregexp.h',
+        'regexp/regexp-macro-assembler-tracer.cc',
+        'regexp/regexp-macro-assembler-tracer.h',
+        'regexp/regexp-macro-assembler.cc',
+        'regexp/regexp-macro-assembler.h',
+        'regexp/regexp-parser.cc',
+        'regexp/regexp-parser.h',
+        'regexp/regexp-stack.cc',
+        'regexp/regexp-stack.h',
+        'register-configuration.cc',
+        'register-configuration.h',
+        'runtime-profiler.cc',
+        'runtime-profiler.h',
+        'runtime/runtime-array.cc',
+        'runtime/runtime-atomics.cc',
+        'runtime/runtime-classes.cc',
+        'runtime/runtime-collections.cc',
+        'runtime/runtime-compiler.cc',
+        'runtime/runtime-date.cc',
+        'runtime/runtime-debug.cc',
+        'runtime/runtime-forin.cc',
+        'runtime/runtime-function.cc',
+        'runtime/runtime-futex.cc',
+        'runtime/runtime-generator.cc',
+        'runtime/runtime-i18n.cc',
+        'runtime/runtime-internal.cc',
+        'runtime/runtime-interpreter.cc',
+        'runtime/runtime-literals.cc',
+        'runtime/runtime-liveedit.cc',
+        'runtime/runtime-maths.cc',
+        'runtime/runtime-numbers.cc',
+        'runtime/runtime-object.cc',
+        'runtime/runtime-operators.cc',
+        'runtime/runtime-proxy.cc',
+        'runtime/runtime-regexp.cc',
+        'runtime/runtime-scopes.cc',
+        'runtime/runtime-simd.cc',
+        'runtime/runtime-strings.cc',
+        'runtime/runtime-symbol.cc',
+        'runtime/runtime-test.cc',
+        'runtime/runtime-typedarray.cc',
+        'runtime/runtime-utils.h',
+        'runtime/runtime.cc',
+        'runtime/runtime.h',
+        'safepoint-table.cc',
+        'safepoint-table.h',
+        'signature.h',
+        'simulator.h',
+        'small-pointer-list.h',
+        'snapshot/code-serializer.cc',
+        'snapshot/code-serializer.h',
+        'snapshot/deserializer.cc',
+        'snapshot/deserializer.h',
+        'snapshot/natives.h',
+        'snapshot/natives-common.cc',
+        'snapshot/partial-serializer.cc',
+        'snapshot/partial-serializer.h',
+        'snapshot/serializer.cc',
+        'snapshot/serializer.h',
+        'snapshot/serializer-common.cc',
+        'snapshot/serializer-common.h',
+        'snapshot/snapshot.h',
+        'snapshot/snapshot-common.cc',
+        'snapshot/snapshot-source-sink.cc',
+        'snapshot/snapshot-source-sink.h',
+        'snapshot/startup-serializer.cc',
+        'snapshot/startup-serializer.h',
+        'source-position.h',
+        'splay-tree.h',
+        'splay-tree-inl.h',
+        'startup-data-util.cc',
+        'startup-data-util.h',
+        'string-builder.cc',
+        'string-builder.h',
+        'string-search.h',
+        'string-stream.cc',
+        'string-stream.h',
+        'strtod.cc',
+        'strtod.h',
+        'ic/stub-cache.cc',
+        'ic/stub-cache.h',
+        'tracing/trace-event.cc',
+        'tracing/trace-event.h',
+        'transitions-inl.h',
+        'transitions.cc',
+        'transitions.h',
+        'type-cache.cc',
+        'type-cache.h',
+        'type-feedback-vector-inl.h',
+        'type-feedback-vector.cc',
+        'type-feedback-vector.h',
+        'type-info.cc',
+        'type-info.h',
+        'types.cc',
+        'types.h',
+        'typing-asm.cc',
+        'typing-asm.h',
+        'unicode-inl.h',
+        'unicode.cc',
+        'unicode.h',
+        'unicode-cache-inl.h',
+        'unicode-cache.h',
+        'unicode-decoder.cc',
+        'unicode-decoder.h',
+        'uri.cc',
+        'uri.h',
+        'utils-inl.h',
+        'utils.cc',
+        'utils.h',
+        'v8.cc',
+        'v8.h',
+        'v8memory.h',
+        'v8threads.cc',
+        'v8threads.h',
+        'vector.h',
+        'version.cc',
+        'version.h',
+        'vm-state-inl.h',
+        'vm-state.h',
+        'wasm/asm-types.cc',
+        'wasm/asm-types.h',
+        'wasm/asm-wasm-builder.cc',
+        'wasm/asm-wasm-builder.h',
+        'wasm/ast-decoder.cc',
+        'wasm/ast-decoder.h',
+        'wasm/decoder.h',
+        'wasm/encoder.cc',
+        'wasm/encoder.h',
+        'wasm/leb-helper.h',
+        'wasm/module-decoder.cc',
+        'wasm/module-decoder.h',
+        'wasm/switch-logic.h',
+        'wasm/switch-logic.cc',
+        'wasm/wasm-debug.cc',
+        'wasm/wasm-debug.h',
+        'wasm/wasm-external-refs.cc',
+        'wasm/wasm-external-refs.h',
+        'wasm/wasm-function-name-table.cc',
+        'wasm/wasm-function-name-table.h',
+        'wasm/wasm-js.cc',
+        'wasm/wasm-js.h',
+        'wasm/wasm-macro-gen.h',
+        'wasm/wasm-module.cc',
+        'wasm/wasm-module.h',
+        'wasm/wasm-interpreter.cc',
+        'wasm/wasm-interpreter.h',
+        'wasm/wasm-opcodes.cc',
+        'wasm/wasm-opcodes.h',
+        'wasm/wasm-result.cc',
+        'wasm/wasm-result.h',
+        'zone.cc',
+        'zone.h',
+        'zone-allocator.h',
+        'zone-containers.h',
+      ],
+      'conditions': [
+        ['want_separate_host_toolset==1', {
+          'toolsets': ['host', 'target'],
+        }, {
+          'toolsets': ['target'],
+        }],
+        ['v8_target_arch=="arm"', {
+          'sources': [  ### gcmole(arch:arm) ###
+            'arm/assembler-arm-inl.h',
+            'arm/assembler-arm.cc',
+            'arm/assembler-arm.h',
+            'arm/builtins-arm.cc',
+            'arm/code-stubs-arm.cc',
+            'arm/code-stubs-arm.h',
+            'arm/codegen-arm.cc',
+            'arm/codegen-arm.h',
+            'arm/constants-arm.h',
+            'arm/constants-arm.cc',
+            'arm/cpu-arm.cc',
+            'arm/deoptimizer-arm.cc',
+            'arm/disasm-arm.cc',
+            'arm/frames-arm.cc',
+            'arm/frames-arm.h',
+            'arm/interface-descriptors-arm.cc',
+            'arm/interface-descriptors-arm.h',
+            'arm/macro-assembler-arm.cc',
+            'arm/macro-assembler-arm.h',
+            'arm/simulator-arm.cc',
+            'arm/simulator-arm.h',
+            'compiler/arm/code-generator-arm.cc',
+            'compiler/arm/instruction-codes-arm.h',
+            'compiler/arm/instruction-scheduler-arm.cc',
+            'compiler/arm/instruction-selector-arm.cc',
+            'crankshaft/arm/lithium-arm.cc',
+            'crankshaft/arm/lithium-arm.h',
+            'crankshaft/arm/lithium-codegen-arm.cc',
+            'crankshaft/arm/lithium-codegen-arm.h',
+            'crankshaft/arm/lithium-gap-resolver-arm.cc',
+            'crankshaft/arm/lithium-gap-resolver-arm.h',
+            'debug/arm/debug-arm.cc',
+            'full-codegen/arm/full-codegen-arm.cc',
+            'ic/arm/access-compiler-arm.cc',
+            'ic/arm/handler-compiler-arm.cc',
+            'ic/arm/ic-arm.cc',
+            'ic/arm/ic-compiler-arm.cc',
+            'ic/arm/stub-cache-arm.cc',
+            'regexp/arm/regexp-macro-assembler-arm.cc',
+            'regexp/arm/regexp-macro-assembler-arm.h',
+          ],
+        }],
+        ['v8_target_arch=="arm64"', {
+          'sources': [  ### gcmole(arch:arm64) ###
+            'arm64/assembler-arm64.cc',
+            'arm64/assembler-arm64.h',
+            'arm64/assembler-arm64-inl.h',
+            'arm64/builtins-arm64.cc',
+            'arm64/codegen-arm64.cc',
+            'arm64/codegen-arm64.h',
+            'arm64/code-stubs-arm64.cc',
+            'arm64/code-stubs-arm64.h',
+            'arm64/constants-arm64.h',
+            'arm64/cpu-arm64.cc',
+            'arm64/decoder-arm64.cc',
+            'arm64/decoder-arm64.h',
+            'arm64/decoder-arm64-inl.h',
+            'arm64/deoptimizer-arm64.cc',
+            'arm64/disasm-arm64.cc',
+            'arm64/disasm-arm64.h',
+            'arm64/frames-arm64.cc',
+            'arm64/frames-arm64.h',
+            'arm64/instructions-arm64.cc',
+            'arm64/instructions-arm64.h',
+            'arm64/instrument-arm64.cc',
+            'arm64/instrument-arm64.h',
+            'arm64/interface-descriptors-arm64.cc',
+            'arm64/interface-descriptors-arm64.h',
+            'arm64/macro-assembler-arm64.cc',
+            'arm64/macro-assembler-arm64.h',
+            'arm64/macro-assembler-arm64-inl.h',
+            'arm64/simulator-arm64.cc',
+            'arm64/simulator-arm64.h',
+            'arm64/utils-arm64.cc',
+            'arm64/utils-arm64.h',
+            'compiler/arm64/code-generator-arm64.cc',
+            'compiler/arm64/instruction-codes-arm64.h',
+            'compiler/arm64/instruction-scheduler-arm64.cc',
+            'compiler/arm64/instruction-selector-arm64.cc',
+            'crankshaft/arm64/delayed-masm-arm64.cc',
+            'crankshaft/arm64/delayed-masm-arm64.h',
+            'crankshaft/arm64/delayed-masm-arm64-inl.h',
+            'crankshaft/arm64/lithium-arm64.cc',
+            'crankshaft/arm64/lithium-arm64.h',
+            'crankshaft/arm64/lithium-codegen-arm64.cc',
+            'crankshaft/arm64/lithium-codegen-arm64.h',
+            'crankshaft/arm64/lithium-gap-resolver-arm64.cc',
+            'crankshaft/arm64/lithium-gap-resolver-arm64.h',
+            'debug/arm64/debug-arm64.cc',
+            'full-codegen/arm64/full-codegen-arm64.cc',
+            'ic/arm64/access-compiler-arm64.cc',
+            'ic/arm64/handler-compiler-arm64.cc',
+            'ic/arm64/ic-arm64.cc',
+            'ic/arm64/ic-compiler-arm64.cc',
+            'ic/arm64/stub-cache-arm64.cc',
+            'regexp/arm64/regexp-macro-assembler-arm64.cc',
+            'regexp/arm64/regexp-macro-assembler-arm64.h',
+          ],
+        }],
+        ['v8_target_arch=="ia32"', {
+          'sources': [  ### gcmole(arch:ia32) ###
+            'ia32/assembler-ia32-inl.h',
+            'ia32/assembler-ia32.cc',
+            'ia32/assembler-ia32.h',
+            'ia32/builtins-ia32.cc',
+            'ia32/code-stubs-ia32.cc',
+            'ia32/code-stubs-ia32.h',
+            'ia32/codegen-ia32.cc',
+            'ia32/codegen-ia32.h',
+            'ia32/cpu-ia32.cc',
+            'ia32/deoptimizer-ia32.cc',
+            'ia32/disasm-ia32.cc',
+            'ia32/frames-ia32.cc',
+            'ia32/frames-ia32.h',
+            'ia32/interface-descriptors-ia32.cc',
+            'ia32/macro-assembler-ia32.cc',
+            'ia32/macro-assembler-ia32.h',
+            'compiler/ia32/code-generator-ia32.cc',
+            'compiler/ia32/instruction-codes-ia32.h',
+            'compiler/ia32/instruction-scheduler-ia32.cc',
+            'compiler/ia32/instruction-selector-ia32.cc',
+            'crankshaft/ia32/lithium-codegen-ia32.cc',
+            'crankshaft/ia32/lithium-codegen-ia32.h',
+            'crankshaft/ia32/lithium-gap-resolver-ia32.cc',
+            'crankshaft/ia32/lithium-gap-resolver-ia32.h',
+            'crankshaft/ia32/lithium-ia32.cc',
+            'crankshaft/ia32/lithium-ia32.h',
+            'debug/ia32/debug-ia32.cc',
+            'full-codegen/ia32/full-codegen-ia32.cc',
+            'ic/ia32/access-compiler-ia32.cc',
+            'ic/ia32/handler-compiler-ia32.cc',
+            'ic/ia32/ic-ia32.cc',
+            'ic/ia32/ic-compiler-ia32.cc',
+            'ic/ia32/stub-cache-ia32.cc',
+            'regexp/ia32/regexp-macro-assembler-ia32.cc',
+            'regexp/ia32/regexp-macro-assembler-ia32.h',
+          ],
+        }],
+        ['v8_target_arch=="x87"', {
+          'sources': [  ### gcmole(arch:x87) ###
+            'x87/assembler-x87-inl.h',
+            'x87/assembler-x87.cc',
+            'x87/assembler-x87.h',
+            'x87/builtins-x87.cc',
+            'x87/code-stubs-x87.cc',
+            'x87/code-stubs-x87.h',
+            'x87/codegen-x87.cc',
+            'x87/codegen-x87.h',
+            'x87/cpu-x87.cc',
+            'x87/deoptimizer-x87.cc',
+            'x87/disasm-x87.cc',
+            'x87/frames-x87.cc',
+            'x87/frames-x87.h',
+            'x87/interface-descriptors-x87.cc',
+            'x87/macro-assembler-x87.cc',
+            'x87/macro-assembler-x87.h',
+            'compiler/x87/code-generator-x87.cc',
+            'compiler/x87/instruction-codes-x87.h',
+            'compiler/x87/instruction-scheduler-x87.cc',
+            'compiler/x87/instruction-selector-x87.cc',
+            'crankshaft/x87/lithium-codegen-x87.cc',
+            'crankshaft/x87/lithium-codegen-x87.h',
+            'crankshaft/x87/lithium-gap-resolver-x87.cc',
+            'crankshaft/x87/lithium-gap-resolver-x87.h',
+            'crankshaft/x87/lithium-x87.cc',
+            'crankshaft/x87/lithium-x87.h',
+            'debug/x87/debug-x87.cc',
+            'full-codegen/x87/full-codegen-x87.cc',
+            'ic/x87/access-compiler-x87.cc',
+            'ic/x87/handler-compiler-x87.cc',
+            'ic/x87/ic-x87.cc',
+            'ic/x87/ic-compiler-x87.cc',
+            'ic/x87/stub-cache-x87.cc',
+            'regexp/x87/regexp-macro-assembler-x87.cc',
+            'regexp/x87/regexp-macro-assembler-x87.h',
+          ],
+        }],
+        ['v8_target_arch=="mips" or v8_target_arch=="mipsel"', {
+          'sources': [  ### gcmole(arch:mipsel) ###
+            'mips/assembler-mips.cc',
+            'mips/assembler-mips.h',
+            'mips/assembler-mips-inl.h',
+            'mips/builtins-mips.cc',
+            'mips/codegen-mips.cc',
+            'mips/codegen-mips.h',
+            'mips/code-stubs-mips.cc',
+            'mips/code-stubs-mips.h',
+            'mips/constants-mips.cc',
+            'mips/constants-mips.h',
+            'mips/cpu-mips.cc',
+            'mips/deoptimizer-mips.cc',
+            'mips/disasm-mips.cc',
+            'mips/frames-mips.cc',
+            'mips/frames-mips.h',
+            'mips/interface-descriptors-mips.cc',
+            'mips/macro-assembler-mips.cc',
+            'mips/macro-assembler-mips.h',
+            'mips/simulator-mips.cc',
+            'mips/simulator-mips.h',
+            'compiler/mips/code-generator-mips.cc',
+            'compiler/mips/instruction-codes-mips.h',
+            'compiler/mips/instruction-scheduler-mips.cc',
+            'compiler/mips/instruction-selector-mips.cc',
+            'crankshaft/mips/lithium-codegen-mips.cc',
+            'crankshaft/mips/lithium-codegen-mips.h',
+            'crankshaft/mips/lithium-gap-resolver-mips.cc',
+            'crankshaft/mips/lithium-gap-resolver-mips.h',
+            'crankshaft/mips/lithium-mips.cc',
+            'crankshaft/mips/lithium-mips.h',
+            'full-codegen/mips/full-codegen-mips.cc',
+            'debug/mips/debug-mips.cc',
+            'ic/mips/access-compiler-mips.cc',
+            'ic/mips/handler-compiler-mips.cc',
+            'ic/mips/ic-mips.cc',
+            'ic/mips/ic-compiler-mips.cc',
+            'ic/mips/stub-cache-mips.cc',
+            'regexp/mips/regexp-macro-assembler-mips.cc',
+            'regexp/mips/regexp-macro-assembler-mips.h',
+          ],
+        }],
+        ['v8_target_arch=="mips64" or v8_target_arch=="mips64el"', {
+          'sources': [  ### gcmole(arch:mips64el) ###
+            'mips64/assembler-mips64.cc',
+            'mips64/assembler-mips64.h',
+            'mips64/assembler-mips64-inl.h',
+            'mips64/builtins-mips64.cc',
+            'mips64/codegen-mips64.cc',
+            'mips64/codegen-mips64.h',
+            'mips64/code-stubs-mips64.cc',
+            'mips64/code-stubs-mips64.h',
+            'mips64/constants-mips64.cc',
+            'mips64/constants-mips64.h',
+            'mips64/cpu-mips64.cc',
+            'mips64/deoptimizer-mips64.cc',
+            'mips64/disasm-mips64.cc',
+            'mips64/frames-mips64.cc',
+            'mips64/frames-mips64.h',
+            'mips64/interface-descriptors-mips64.cc',
+            'mips64/macro-assembler-mips64.cc',
+            'mips64/macro-assembler-mips64.h',
+            'mips64/simulator-mips64.cc',
+            'mips64/simulator-mips64.h',
+            'compiler/mips64/code-generator-mips64.cc',
+            'compiler/mips64/instruction-codes-mips64.h',
+            'compiler/mips64/instruction-scheduler-mips64.cc',
+            'compiler/mips64/instruction-selector-mips64.cc',
+            'crankshaft/mips64/lithium-codegen-mips64.cc',
+            'crankshaft/mips64/lithium-codegen-mips64.h',
+            'crankshaft/mips64/lithium-gap-resolver-mips64.cc',
+            'crankshaft/mips64/lithium-gap-resolver-mips64.h',
+            'crankshaft/mips64/lithium-mips64.cc',
+            'crankshaft/mips64/lithium-mips64.h',
+            'debug/mips64/debug-mips64.cc',
+            'full-codegen/mips64/full-codegen-mips64.cc',
+            'ic/mips64/access-compiler-mips64.cc',
+            'ic/mips64/handler-compiler-mips64.cc',
+            'ic/mips64/ic-mips64.cc',
+            'ic/mips64/ic-compiler-mips64.cc',
+            'ic/mips64/stub-cache-mips64.cc',
+            'regexp/mips64/regexp-macro-assembler-mips64.cc',
+            'regexp/mips64/regexp-macro-assembler-mips64.h',
+          ],
+        }],
+        ['v8_target_arch=="x64" or v8_target_arch=="x32"', {
+          'sources': [  ### gcmole(arch:x64) ###
+            'crankshaft/x64/lithium-codegen-x64.cc',
+            'crankshaft/x64/lithium-codegen-x64.h',
+            'crankshaft/x64/lithium-gap-resolver-x64.cc',
+            'crankshaft/x64/lithium-gap-resolver-x64.h',
+            'crankshaft/x64/lithium-x64.cc',
+            'crankshaft/x64/lithium-x64.h',
+            'x64/assembler-x64-inl.h',
+            'x64/assembler-x64.cc',
+            'x64/assembler-x64.h',
+            'x64/builtins-x64.cc',
+            'x64/code-stubs-x64.cc',
+            'x64/code-stubs-x64.h',
+            'x64/codegen-x64.cc',
+            'x64/codegen-x64.h',
+            'x64/cpu-x64.cc',
+            'x64/deoptimizer-x64.cc',
+            'x64/disasm-x64.cc',
+            'x64/frames-x64.cc',
+            'x64/frames-x64.h',
+            'x64/interface-descriptors-x64.cc',
+            'x64/macro-assembler-x64.cc',
+            'x64/macro-assembler-x64.h',
+            'debug/x64/debug-x64.cc',
+            'full-codegen/x64/full-codegen-x64.cc',
+            'ic/x64/access-compiler-x64.cc',
+            'ic/x64/handler-compiler-x64.cc',
+            'ic/x64/ic-x64.cc',
+            'ic/x64/ic-compiler-x64.cc',
+            'ic/x64/stub-cache-x64.cc',
+            'regexp/x64/regexp-macro-assembler-x64.cc',
+            'regexp/x64/regexp-macro-assembler-x64.h',
+          ],
+        }],
+        ['v8_target_arch=="x64"', {
+          'sources': [
+            'compiler/x64/code-generator-x64.cc',
+            'compiler/x64/instruction-codes-x64.h',
+            'compiler/x64/instruction-scheduler-x64.cc',
+            'compiler/x64/instruction-selector-x64.cc',
+          ],
+        }],
+        ['v8_target_arch=="ppc" or v8_target_arch=="ppc64"', {
+          'sources': [  ### gcmole(arch:ppc) ###
+            'compiler/ppc/code-generator-ppc.cc',
+            'compiler/ppc/instruction-codes-ppc.h',
+            'compiler/ppc/instruction-scheduler-ppc.cc',
+            'compiler/ppc/instruction-selector-ppc.cc',
+            'crankshaft/ppc/lithium-ppc.cc',
+            'crankshaft/ppc/lithium-ppc.h',
+            'crankshaft/ppc/lithium-codegen-ppc.cc',
+            'crankshaft/ppc/lithium-codegen-ppc.h',
+            'crankshaft/ppc/lithium-gap-resolver-ppc.cc',
+            'crankshaft/ppc/lithium-gap-resolver-ppc.h',
+            'debug/ppc/debug-ppc.cc',
+            'full-codegen/ppc/full-codegen-ppc.cc',
+            'ic/ppc/access-compiler-ppc.cc',
+            'ic/ppc/handler-compiler-ppc.cc',
+            'ic/ppc/ic-ppc.cc',
+            'ic/ppc/ic-compiler-ppc.cc',
+            'ic/ppc/stub-cache-ppc.cc',
+            'ppc/assembler-ppc-inl.h',
+            'ppc/assembler-ppc.cc',
+            'ppc/assembler-ppc.h',
+            'ppc/builtins-ppc.cc',
+            'ppc/code-stubs-ppc.cc',
+            'ppc/code-stubs-ppc.h',
+            'ppc/codegen-ppc.cc',
+            'ppc/codegen-ppc.h',
+            'ppc/constants-ppc.h',
+            'ppc/constants-ppc.cc',
+            'ppc/cpu-ppc.cc',
+            'ppc/deoptimizer-ppc.cc',
+            'ppc/disasm-ppc.cc',
+            'ppc/frames-ppc.cc',
+            'ppc/frames-ppc.h',
+            'ppc/interface-descriptors-ppc.cc',
+            'ppc/macro-assembler-ppc.cc',
+            'ppc/macro-assembler-ppc.h',
+            'ppc/simulator-ppc.cc',
+            'ppc/simulator-ppc.h',
+            'regexp/ppc/regexp-macro-assembler-ppc.cc',
+            'regexp/ppc/regexp-macro-assembler-ppc.h',
+          ],
+        }],
+        ['v8_target_arch=="s390" or v8_target_arch=="s390x"', {
+          'sources': [  ### gcmole(arch:s390) ###
+            'compiler/s390/code-generator-s390.cc',
+            'compiler/s390/instruction-codes-s390.h',
+            'compiler/s390/instruction-scheduler-s390.cc',
+            'compiler/s390/instruction-selector-s390.cc',
+            'crankshaft/s390/lithium-codegen-s390.cc',
+            'crankshaft/s390/lithium-codegen-s390.h',
+            'crankshaft/s390/lithium-gap-resolver-s390.cc',
+            'crankshaft/s390/lithium-gap-resolver-s390.h',
+            'crankshaft/s390/lithium-s390.cc',
+            'crankshaft/s390/lithium-s390.h',
+            'debug/s390/debug-s390.cc',
+            'full-codegen/s390/full-codegen-s390.cc',
+            'ic/s390/access-compiler-s390.cc',
+            'ic/s390/handler-compiler-s390.cc',
+            'ic/s390/ic-compiler-s390.cc',
+            'ic/s390/ic-s390.cc',
+            'ic/s390/stub-cache-s390.cc',
+            'regexp/s390/regexp-macro-assembler-s390.cc',
+            'regexp/s390/regexp-macro-assembler-s390.h',
+            's390/assembler-s390.cc',
+            's390/assembler-s390.h',
+            's390/assembler-s390-inl.h',
+            's390/builtins-s390.cc',
+            's390/codegen-s390.cc',
+            's390/codegen-s390.h',
+            's390/code-stubs-s390.cc',
+            's390/code-stubs-s390.h',
+            's390/constants-s390.cc',
+            's390/constants-s390.h',
+            's390/cpu-s390.cc',
+            's390/deoptimizer-s390.cc',
+            's390/disasm-s390.cc',
+            's390/frames-s390.cc',
+            's390/frames-s390.h',
+            's390/interface-descriptors-s390.cc',
+            's390/macro-assembler-s390.cc',
+            's390/macro-assembler-s390.h',
+            's390/simulator-s390.cc',
+            's390/simulator-s390.h',
+          ],
+        }],
+        ['OS=="win"', {
+          'variables': {
+            'gyp_generators': '<!(echo $GYP_GENERATORS)',
+          },
+          'msvs_disabled_warnings': [4351, 4355, 4800],
+          # When building Official, the .lib is too large and exceeds the 2G
+          # limit. This breaks it into multiple pieces to avoid the limit.
+          # See http://crbug.com/485155.
+          'msvs_shard': 4,
+        }],
+        ['component=="shared_library"', {
+          'defines': [
+            'BUILDING_V8_SHARED',
+            'V8_SHARED',
+          ],
+        }],
+        ['v8_postmortem_support=="true"', {
+          'sources': [
+            '<(SHARED_INTERMEDIATE_DIR)/debug-support.cc',
+          ]
+        }],
+        ['v8_enable_i18n_support==1', {
+          'dependencies': [
+            '<(icu_gyp_path):icui18n',
+            '<(icu_gyp_path):icuuc',
+          ],
+          'conditions': [
+            ['icu_use_data_file_flag==1', {
+              'defines': ['ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE'],
+            }, { # else icu_use_data_file_flag !=1
+              'conditions': [
+                ['OS=="win"', {
+                  'defines': ['ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_SHARED'],
+                }, {
+                  'defines': ['ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC'],
+                }],
+              ],
+            }],
+          ],
+        }, {  # v8_enable_i18n_support==0
+          'sources!': [
+            'i18n.cc',
+            'i18n.h',
+          ],
+        }],
+        ['OS=="win" and v8_enable_i18n_support==1', {
+          'dependencies': [
+            '<(icu_gyp_path):icudata',
+          ],
+        }],
+      ],
+    },
+    {
+      'target_name': 'v8_libbase',
+      'type': 'static_library',
+      'variables': {
+        'optimize': 'max',
+      },
+      'include_dirs+': [
+        '..',
+      ],
+      'sources': [
+        'base/accounting-allocator.cc',
+        'base/accounting-allocator.h',
+        'base/adapters.h',
+        'base/atomic-utils.h',
+        'base/atomicops.h',
+        'base/atomicops_internals_arm64_gcc.h',
+        'base/atomicops_internals_arm_gcc.h',
+        'base/atomicops_internals_atomicword_compat.h',
+        'base/atomicops_internals_mac.h',
+        'base/atomicops_internals_mips_gcc.h',
+        'base/atomicops_internals_mips64_gcc.h',
+        'base/atomicops_internals_portable.h',
+        'base/atomicops_internals_ppc_gcc.h',
+        'base/atomicops_internals_s390_gcc.h',
+        'base/atomicops_internals_tsan.h',
+        'base/atomicops_internals_x86_gcc.cc',
+        'base/atomicops_internals_x86_gcc.h',
+        'base/atomicops_internals_x86_msvc.h',
+        'base/bits.cc',
+        'base/bits.h',
+        'base/build_config.h',
+        'base/compiler-specific.h',
+        'base/cpu.cc',
+        'base/cpu.h',
+        'base/division-by-constant.cc',
+        'base/division-by-constant.h',
+        'base/file-utils.cc',
+        'base/file-utils.h',
+        'base/flags.h',
+        'base/format-macros.h',
+        'base/functional.cc',
+        'base/functional.h',
+        'base/hashmap.h',
+        'base/ieee754.cc',
+        'base/ieee754.h',
+        'base/iterator.h',
+        'base/lazy-instance.h',
+        'base/logging.cc',
+        'base/logging.h',
+        'base/macros.h',
+        'base/once.cc',
+        'base/once.h',
+        'base/platform/elapsed-timer.h',
+        'base/platform/time.cc',
+        'base/platform/time.h',
+        'base/platform/condition-variable.cc',
+        'base/platform/condition-variable.h',
+        'base/platform/mutex.cc',
+        'base/platform/mutex.h',
+        'base/platform/platform.h',
+        'base/platform/semaphore.cc',
+        'base/platform/semaphore.h',
+        'base/safe_conversions.h',
+        'base/safe_conversions_impl.h',
+        'base/safe_math.h',
+        'base/safe_math_impl.h',
+        'base/smart-pointers.h',
+        'base/sys-info.cc',
+        'base/sys-info.h',
+        'base/utils/random-number-generator.cc',
+        'base/utils/random-number-generator.h',
+      ],
+      'conditions': [
+        ['want_separate_host_toolset==1', {
+          'toolsets': ['host', 'target'],
+        }, {
+          'toolsets': ['target'],
+        }],
+        ['OS=="linux"', {
+            'conditions': [
+              ['nacl_target_arch=="none"', {
+                'link_settings': {
+                  'libraries': [
+                    '-ldl',
+                    '-lrt'
+                  ],
+                },
+              }, {
+                'defines': [
+                  'V8_LIBRT_NOT_AVAILABLE=1',
+                ],
+              }],
+            ],
+            'sources': [
+              'base/platform/platform-linux.cc',
+              'base/platform/platform-posix.cc'
+            ],
+          }
+        ],
+        ['OS=="android"', {
+            'sources': [
+              'base/platform/platform-posix.cc'
+            ],
+            'link_settings': {
+              'target_conditions': [
+                ['_toolset=="host" and host_os!="mac"', {
+                  # Only include libdl and librt on host builds because they
+                  # are included by default on Android target builds, and we
+                  # don't want to re-include them here since this will change
+                  # library order and break (see crbug.com/469973).
+                  # These libraries do not exist on Mac hosted builds.
+                  'libraries': [
+                    '-ldl',
+                    '-lrt'
+                  ]
+                }]
+              ]
+            },
+            'conditions': [
+              ['host_os=="mac"', {
+                'target_conditions': [
+                  ['_toolset=="host"', {
+                    'sources': [
+                      'base/platform/platform-macos.cc'
+                    ]
+                  }, {
+                    'sources': [
+                      'base/platform/platform-linux.cc'
+                    ]
+                  }],
+                ],
+              }, {
+                'sources': [
+                  'base/platform/platform-linux.cc'
+                ]
+              }],
+            ],
+          },
+        ],
+        ['OS=="qnx"', {
+            'link_settings': {
+              'target_conditions': [
+                ['_toolset=="host" and host_os=="linux"', {
+                  'libraries': [
+                    '-lrt'
+                  ],
+                }],
+                ['_toolset=="target"', {
+                  'libraries': [
+                    '-lbacktrace'
+                  ],
+                }],
+              ],
+            },
+            'sources': [
+              'base/platform/platform-posix.cc',
+              'base/qnx-math.h',
+            ],
+            'target_conditions': [
+              ['_toolset=="host" and host_os=="linux"', {
+                'sources': [
+                  'base/platform/platform-linux.cc'
+                ],
+              }],
+              ['_toolset=="host" and host_os=="mac"', {
+                'sources': [
+                  'base/platform/platform-macos.cc'
+                ],
+              }],
+              ['_toolset=="target"', {
+                'sources': [
+                  'base/platform/platform-qnx.cc'
+                ],
+              }],
+            ],
+          },
+        ],
+        ['OS=="freebsd"', {
+            'link_settings': {
+              'libraries': [
+                '-L/usr/local/lib -lexecinfo',
+            ]},
+            'sources': [
+              'base/platform/platform-freebsd.cc',
+              'base/platform/platform-posix.cc'
+            ],
+          }
+        ],
+        ['OS=="openbsd"', {
+            'link_settings': {
+              'libraries': [
+                '-L/usr/local/lib -lexecinfo',
+            ]},
+            'sources': [
+              'base/platform/platform-openbsd.cc',
+              'base/platform/platform-posix.cc'
+            ],
+          }
+        ],
+        ['OS=="netbsd"', {
+            'link_settings': {
+              'libraries': [
+                '-L/usr/pkg/lib -Wl,-R/usr/pkg/lib -lexecinfo',
+            ]},
+            'sources': [
+              'base/platform/platform-openbsd.cc',
+              'base/platform/platform-posix.cc'
+            ],
+          }
+        ],
+        ['OS=="aix"', {
+          'sources': [
+            'base/platform/platform-aix.cc',
+            'base/platform/platform-posix.cc'
+          ]},
+        ],
+        ['OS=="solaris"', {
+            'link_settings': {
+              'libraries': [
+                '-lnsl -lrt',
+            ]},
+            'sources': [
+              'base/platform/platform-solaris.cc',
+              'base/platform/platform-posix.cc'
+            ],
+          }
+        ],
+        ['OS=="mac"', {
+          'sources': [
+            'base/platform/platform-macos.cc',
+            'base/platform/platform-posix.cc'
+          ]},
+        ],
+        ['OS=="win"', {
+          'defines': [
+            '_CRT_RAND_S'  # for rand_s()
+          ],
+          'variables': {
+            'gyp_generators': '<!(echo $GYP_GENERATORS)',
+          },
+          'conditions': [
+            ['gyp_generators=="make"', {
+              'variables': {
+                'build_env': '<!(uname -o)',
+              },
+              'conditions': [
+                ['build_env=="Cygwin"', {
+                  'sources': [
+                    'base/platform/platform-cygwin.cc',
+                    'base/platform/platform-posix.cc'
+                  ],
+                }, {
+                  'sources': [
+                    'base/platform/platform-win32.cc',
+                    'base/win32-headers.h',
+                  ],
+                }],
+              ],
+              'link_settings':  {
+                'libraries': [ '-lwinmm', '-lws2_32' ],
+              },
+            }, {
+              'sources': [
+                'base/platform/platform-win32.cc',
+                'base/win32-headers.h',
+              ],
+              'msvs_disabled_warnings': [4351, 4355, 4800],
+              'link_settings':  {
+                'libraries': [ '-lwinmm.lib', '-lws2_32.lib' ],
+              },
+            }],
+          ],
+        }],
+      ],
+    },
+    {
+      'target_name': 'v8_libplatform',
+      'type': 'static_library',
+      'variables': {
+        'optimize': 'max',
+      },
+      'dependencies': [
+        'v8_libbase',
+      ],
+      'include_dirs+': [
+        '..',
+        '../include',
+      ],
+      'sources': [
+        '../include/libplatform/libplatform.h',
+        'libplatform/default-platform.cc',
+        'libplatform/default-platform.h',
+        'libplatform/task-queue.cc',
+        'libplatform/task-queue.h',
+        'libplatform/worker-thread.cc',
+        'libplatform/worker-thread.h',
+      ],
+      'conditions': [
+        ['want_separate_host_toolset==1', {
+          'toolsets': ['host', 'target'],
+        }, {
+          'toolsets': ['target'],
+        }],
+      ],
+      'direct_dependent_settings': {
+        'include_dirs': [
+          '../include',
+        ],
+      },
+    },
+    {
+      'target_name': 'v8_libsampler',
+      'type': 'static_library',
+      'variables': {
+        'optimize': 'max',
+      },
+      'dependencies': [
+        'v8_libbase',
+      ],
+      'include_dirs+': [
+        '..',
+        '../include',
+      ],
+      'sources': [
+        'libsampler/v8-sampler.cc',
+        'libsampler/v8-sampler.h'
+      ],
+      'conditions': [
+        ['want_separate_host_toolset==1', {
+          'toolsets': ['host', 'target'],
+        }, {
+          'toolsets': ['target'],
+        }],
+      ],
+      'direct_dependent_settings': {
+        'include_dirs': [
+          '../include',
+        ],
+      },
+    },
+    {
+      'target_name': 'natives_blob',
+      'type': 'none',
+      'conditions': [
+        [ 'v8_use_external_startup_data==1', {
+          'conditions': [
+            ['want_separate_host_toolset==1', {
+              'dependencies': ['js2c#host'],
+            }, {
+              'dependencies': ['js2c'],
+            }],
+          ],
+          'actions': [{
+            'action_name': 'concatenate_natives_blob',
+            'inputs': [
+              '../tools/concatenate-files.py',
+              '<(SHARED_INTERMEDIATE_DIR)/libraries.bin',
+              '<(SHARED_INTERMEDIATE_DIR)/libraries-experimental.bin',
+              '<(SHARED_INTERMEDIATE_DIR)/libraries-extras.bin',
+              '<(SHARED_INTERMEDIATE_DIR)/libraries-experimental-extras.bin',
+            ],
+            'conditions': [
+              ['want_separate_host_toolset==1', {
+                'target_conditions': [
+                  ['_toolset=="host"', {
+                    'outputs': [
+                      '<(PRODUCT_DIR)/natives_blob_host.bin',
+                    ],
+                    'action': [
+                      'python', '<@(_inputs)', '<(PRODUCT_DIR)/natives_blob_host.bin'
+                    ],
+                  }, {
+                    'outputs': [
+                      '<(PRODUCT_DIR)/natives_blob.bin',
+                    ],
+                    'action': [
+                      'python', '<@(_inputs)', '<(PRODUCT_DIR)/natives_blob.bin'
+                    ],
+                  }],
+                ],
+              }, {
+                'outputs': [
+                  '<(PRODUCT_DIR)/natives_blob.bin',
+                ],
+                'action': [
+                  'python', '<@(_inputs)', '<(PRODUCT_DIR)/natives_blob.bin'
+                ],
+              }],
+            ],
+          }],
+        }],
+        ['want_separate_host_toolset==1', {
+          'toolsets': ['host', 'target'],
+        }, {
+          'toolsets': ['target'],
+        }],
+      ]
+    },
+    {
+      'target_name': 'js2c',
+      'type': 'none',
+      'conditions': [
+        ['want_separate_host_toolset==1', {
+          'toolsets': ['host'],
+        }, {
+          'toolsets': ['target'],
+        }],
+      ],
+      'variables': {
+        'library_files': [
+          'js/macros.py',
+          'messages.h',
+          'js/prologue.js',
+          'js/runtime.js',
+          'js/v8natives.js',
+          'js/symbol.js',
+          'js/array.js',
+          'js/string.js',
+          'js/math.js',
+          'third_party/fdlibm/fdlibm.js',
+          'js/regexp.js',
+          'js/arraybuffer.js',
+          'js/typedarray.js',
+          'js/iterator-prototype.js',
+          'js/collection.js',
+          'js/weak-collection.js',
+          'js/collection-iterator.js',
+          'js/promise.js',
+          'js/messages.js',
+          'js/array-iterator.js',
+          'js/string-iterator.js',
+          'js/templates.js',
+          'js/spread.js',
+          'js/proxy.js',
+          'debug/mirrors.js',
+          'debug/debug.js',
+          'debug/liveedit.js',
+        ],
+        'experimental_library_files': [
+          'js/macros.py',
+          'messages.h',
+          'js/harmony-atomics.js',
+          'js/harmony-sharedarraybuffer.js',
+          'js/harmony-simd.js',
+          'js/harmony-string-padding.js',
+          'js/promise-extra.js',
+          'js/harmony-async-await.js'
+        ],
+        'libraries_bin_file': '<(SHARED_INTERMEDIATE_DIR)/libraries.bin',
+        'libraries_experimental_bin_file': '<(SHARED_INTERMEDIATE_DIR)/libraries-experimental.bin',
+        'libraries_extras_bin_file': '<(SHARED_INTERMEDIATE_DIR)/libraries-extras.bin',
+        'libraries_experimental_extras_bin_file': '<(SHARED_INTERMEDIATE_DIR)/libraries-experimental-extras.bin',
+        'conditions': [
+          ['v8_enable_i18n_support==1', {
+            'library_files': ['js/i18n.js'],
+            'experimental_library_files': [
+              'js/icu-case-mapping.js',
+              'js/intl-extra.js',
+             ],
+          }],
+        ],
+      },
+      'actions': [
+        {
+          'action_name': 'js2c',
+          'inputs': [
+            '../tools/js2c.py',
+            '<@(library_files)',
+          ],
+          'outputs': ['<(SHARED_INTERMEDIATE_DIR)/libraries.cc'],
+          'action': [
+            'python',
+            '../tools/js2c.py',
+            '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
+            'CORE',
+            '<@(library_files)',
+          ],
+        },
+        {
+          'action_name': 'js2c_bin',
+          'inputs': [
+            '../tools/js2c.py',
+            '<@(library_files)',
+          ],
+          'outputs': ['<@(libraries_bin_file)'],
+          'action': [
+            'python',
+            '../tools/js2c.py',
+            '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
+            'CORE',
+            '<@(library_files)',
+            '--startup_blob', '<@(libraries_bin_file)',
+            '--nojs',
+          ],
+        },
+        {
+          'action_name': 'js2c_experimental',
+          'inputs': [
+            '../tools/js2c.py',
+            '<@(experimental_library_files)',
+          ],
+          'outputs': ['<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc'],
+          'action': [
+            'python',
+            '../tools/js2c.py',
+            '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc',
+            'EXPERIMENTAL',
+            '<@(experimental_library_files)',
+          ],
+        },
+        {
+          'action_name': 'js2c_experimental_bin',
+          'inputs': [
+            '../tools/js2c.py',
+            '<@(experimental_library_files)',
+          ],
+          'outputs': ['<@(libraries_experimental_bin_file)'],
+          'action': [
+            'python',
+            '../tools/js2c.py',
+            '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc',
+            'EXPERIMENTAL',
+            '<@(experimental_library_files)',
+            '--startup_blob', '<@(libraries_experimental_bin_file)',
+            '--nojs',
+          ],
+        },
+        {
+          'action_name': 'js2c_extras',
+          'inputs': [
+            '../tools/js2c.py',
+            '<@(v8_extra_library_files)',
+          ],
+          'outputs': ['<(SHARED_INTERMEDIATE_DIR)/extras-libraries.cc'],
+          'action': [
+            'python',
+            '../tools/js2c.py',
+            '<(SHARED_INTERMEDIATE_DIR)/extras-libraries.cc',
+            'EXTRAS',
+            '<@(v8_extra_library_files)',
+          ],
+        },
+        {
+          'action_name': 'js2c_extras_bin',
+          'inputs': [
+            '../tools/js2c.py',
+            '<@(v8_extra_library_files)',
+          ],
+          'outputs': ['<@(libraries_extras_bin_file)'],
+          'action': [
+            'python',
+            '../tools/js2c.py',
+            '<(SHARED_INTERMEDIATE_DIR)/extras-libraries.cc',
+            'EXTRAS',
+            '<@(v8_extra_library_files)',
+            '--startup_blob', '<@(libraries_extras_bin_file)',
+            '--nojs',
+          ],
+        },
+        {
+          'action_name': 'js2c_experimental_extras',
+          'inputs': [
+            '../tools/js2c.py',
+            '<@(v8_experimental_extra_library_files)',
+          ],
+          'outputs': [
+            '<(SHARED_INTERMEDIATE_DIR)/experimental-extras-libraries.cc',
+          ],
+          'action': [
+            'python',
+            '../tools/js2c.py',
+            '<(SHARED_INTERMEDIATE_DIR)/experimental-extras-libraries.cc',
+            'EXPERIMENTAL_EXTRAS',
+            '<@(v8_experimental_extra_library_files)',
+          ],
+        },
+        {
+          'action_name': 'js2c_experimental_extras_bin',
+          'inputs': [
+            '../tools/js2c.py',
+            '<@(v8_experimental_extra_library_files)',
+          ],
+          'outputs': ['<@(libraries_experimental_extras_bin_file)'],
+          'action': [
+            'python',
+            '../tools/js2c.py',
+            '<(SHARED_INTERMEDIATE_DIR)/experimental-extras-libraries.cc',
+            'EXPERIMENTAL_EXTRAS',
+            '<@(v8_experimental_extra_library_files)',
+            '--startup_blob', '<@(libraries_experimental_extras_bin_file)',
+            '--nojs',
+          ],
+        },
+      ],
+    },
+    {
+      'target_name': 'postmortem-metadata',
+      'type': 'none',
+      'variables': {
+        'heapobject_files': [
+            'objects.h',
+            'objects-inl.h',
+        ],
+      },
+      'actions': [
+          {
+            'action_name': 'gen-postmortem-metadata',
+            'inputs': [
+              '../tools/gen-postmortem-metadata.py',
+              '<@(heapobject_files)',
+            ],
+            'outputs': [
+              '<(SHARED_INTERMEDIATE_DIR)/debug-support.cc',
+            ],
+            'action': [
+              'python',
+              '../tools/gen-postmortem-metadata.py',
+              '<@(_outputs)',
+              '<@(heapobject_files)'
+            ]
+          }
+        ]
+    },
+    {
+      'target_name': 'mksnapshot',
+      'type': 'executable',
+      'dependencies': ['v8_base', 'v8_nosnapshot', 'v8_libplatform'],
+      'include_dirs+': [
+        '..',
+      ],
+      'sources': [
+        'snapshot/mksnapshot.cc',
+      ],
+      'conditions': [
+        ['v8_enable_i18n_support==1', {
+          'dependencies': [
+            '<(icu_gyp_path):icui18n',
+            '<(icu_gyp_path):icuuc',
+          ]
+        }],
+        ['want_separate_host_toolset==1', {
+          'toolsets': ['host'],
+        }, {
+          'toolsets': ['target'],
+        }],
+      ],
+    },
+  ],
+}
diff --git a/src/v8.h b/src/v8.h
index 6016ef1..a1b18b2 100644
--- a/src/v8.h
+++ b/src/v8.h
@@ -21,7 +21,7 @@
   // Report process out of memory. Implementation found in api.cc.
   // This function will not return, but will terminate the execution.
   static void FatalProcessOutOfMemory(const char* location,
-                                      bool take_snapshot = false);
+                                      bool is_heap_oom = false);
 
   static void InitializePlatform(v8::Platform* platform);
   static void ShutdownPlatform();
diff --git a/src/v8memory.h b/src/v8memory.h
index b1ae939..d34bce7 100644
--- a/src/v8memory.h
+++ b/src/v8memory.h
@@ -64,6 +64,13 @@
   static Handle<Object>& Object_Handle_at(Address addr)  {
     return *reinterpret_cast<Handle<Object>*>(addr);
   }
+
+  static bool IsAddressInRange(Address base, Address address, uint32_t size) {
+    uintptr_t numeric_base = reinterpret_cast<uintptr_t>(base);
+    uintptr_t numeric_address = reinterpret_cast<uintptr_t>(address);
+    return numeric_base <= numeric_address &&
+           numeric_address < numeric_base + size;
+  }
 };
 
 }  // namespace internal
diff --git a/src/vector.h b/src/vector.h
index e4637c9..d120dfc 100644
--- a/src/vector.h
+++ b/src/vector.h
@@ -24,6 +24,9 @@
     DCHECK(length == 0 || (length > 0 && data != NULL));
   }
 
+  template <int N>
+  explicit Vector(T (&arr)[N]) : start_(arr), length_(N) {}
+
   static Vector<T> New(int length) {
     return Vector<T>(NewArray<T>(length), length);
   }
@@ -201,6 +204,10 @@
   return Vector<char>(data, (length < max) ? length : max);
 }
 
+template <typename T, int N>
+inline Vector<T> ArrayVector(T (&arr)[N]) {
+  return Vector<T>(arr);
+}
 
 }  // namespace internal
 }  // namespace v8
diff --git a/src/vm-state-inl.h b/src/vm-state-inl.h
index c8bd4e8..35b69a1 100644
--- a/src/vm-state-inl.h
+++ b/src/vm-state-inl.h
@@ -63,19 +63,11 @@
   scope_address_ = Simulator::current(isolate)->get_sp();
 #endif
   isolate_->set_external_callback_scope(this);
-  if (FLAG_runtime_call_stats) {
-    RuntimeCallStats* stats = isolate->counters()->runtime_call_stats();
-    timer_.Initialize(&stats->ExternalCallback, stats->current_timer());
-    stats->Enter(&timer_);
-  }
   TRACE_EVENT_BEGIN0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"),
                      "V8.ExternalCallback");
 }
 
 ExternalCallbackScope::~ExternalCallbackScope() {
-  if (FLAG_runtime_call_stats) {
-    isolate_->counters()->runtime_call_stats()->Leave(&timer_);
-  }
   isolate_->set_external_callback_scope(previous_scope_);
   TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"),
                    "V8.ExternalCallback");
diff --git a/src/vm-state.h b/src/vm-state.h
index 3f8d381..29cbf39 100644
--- a/src/vm-state.h
+++ b/src/vm-state.h
@@ -49,7 +49,6 @@
   Isolate* isolate_;
   Address callback_;
   ExternalCallbackScope* previous_scope_;
-  RuntimeCallTimer timer_;
 #ifdef USE_SIMULATOR
   Address scope_address_;
 #endif
diff --git a/src/wasm/asm-types.cc b/src/wasm/asm-types.cc
new file mode 100644
index 0000000..e5588ae
--- /dev/null
+++ b/src/wasm/asm-types.cc
@@ -0,0 +1,319 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "src/wasm/asm-types.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+AsmCallableType* AsmType::AsCallableType() {
+  if (AsValueType() != nullptr) {
+    return nullptr;
+  }
+
+  DCHECK(this->AsFunctionType() != nullptr ||
+         this->AsOverloadedFunctionType() != nullptr ||
+         this->AsFFIType() != nullptr ||
+         this->AsFunctionTableType() != nullptr);
+  return reinterpret_cast<AsmCallableType*>(this);
+}
+
+std::string AsmType::Name() {
+  AsmValueType* avt = this->AsValueType();
+  if (avt != nullptr) {
+    switch (avt->Bitset()) {
+#define RETURN_TYPE_NAME(CamelName, string_name, number, parent_types) \
+  case AsmValueType::kAsm##CamelName:                                  \
+    return string_name;
+      FOR_EACH_ASM_VALUE_TYPE_LIST(RETURN_TYPE_NAME)
+#undef RETURN_TYPE_NAME
+      default:
+        UNREACHABLE();
+    }
+  }
+
+  return this->AsCallableType()->Name();
+}
+
+bool AsmType::IsExactly(AsmType* that) {
+  // TODO(jpp): maybe this can become this == that.
+  AsmValueType* avt = this->AsValueType();
+  if (avt != nullptr) {
+    AsmValueType* tavt = that->AsValueType();
+    if (tavt == nullptr) {
+      return false;
+    }
+    return avt->Bitset() == tavt->Bitset();
+  }
+
+  // TODO(jpp): is it useful to allow non-value types to be tested with
+  // IsExactly?
+  return that == this;
+}
+
+bool AsmType::IsA(AsmType* that) {
+  // IsA is used for querying inheritance relationships. Therefore it is only
+  // meaningful for basic types.
+  AsmValueType* tavt = that->AsValueType();
+  if (tavt != nullptr) {
+    AsmValueType* avt = this->AsValueType();
+    if (avt == nullptr) {
+      return false;
+    }
+    return (avt->Bitset() & tavt->Bitset()) == tavt->Bitset();
+  }
+
+  // TODO(jpp): is it useful to allow non-value types to be tested with IsA?
+  return that == this;
+}
+
+int32_t AsmType::ElementSizeInBytes() {
+  auto* value = AsValueType();
+  if (value == nullptr) {
+    return AsmType::kNotHeapType;
+  }
+  switch (value->Bitset()) {
+    case AsmValueType::kAsmInt8Array:
+    case AsmValueType::kAsmUint8Array:
+      return 1;
+    case AsmValueType::kAsmInt16Array:
+    case AsmValueType::kAsmUint16Array:
+      return 2;
+    case AsmValueType::kAsmInt32Array:
+    case AsmValueType::kAsmUint32Array:
+    case AsmValueType::kAsmFloat32Array:
+      return 4;
+    case AsmValueType::kAsmFloat64Array:
+      return 8;
+    default:
+      return AsmType::kNotHeapType;
+  }
+}
+
+AsmType* AsmType::LoadType() {
+  auto* value = AsValueType();
+  if (value == nullptr) {
+    return AsmType::None();
+  }
+  switch (value->Bitset()) {
+    case AsmValueType::kAsmInt8Array:
+    case AsmValueType::kAsmUint8Array:
+    case AsmValueType::kAsmInt16Array:
+    case AsmValueType::kAsmUint16Array:
+    case AsmValueType::kAsmInt32Array:
+    case AsmValueType::kAsmUint32Array:
+      return AsmType::Intish();
+    case AsmValueType::kAsmFloat32Array:
+      return AsmType::FloatQ();
+    case AsmValueType::kAsmFloat64Array:
+      return AsmType::DoubleQ();
+    default:
+      return AsmType::None();
+  }
+}
+
+AsmType* AsmType::StoreType() {
+  auto* value = AsValueType();
+  if (value == nullptr) {
+    return AsmType::None();
+  }
+  switch (value->Bitset()) {
+    case AsmValueType::kAsmInt8Array:
+    case AsmValueType::kAsmUint8Array:
+    case AsmValueType::kAsmInt16Array:
+    case AsmValueType::kAsmUint16Array:
+    case AsmValueType::kAsmInt32Array:
+    case AsmValueType::kAsmUint32Array:
+      return AsmType::Intish();
+    case AsmValueType::kAsmFloat32Array:
+      return AsmType::FloatishDoubleQ();
+    case AsmValueType::kAsmFloat64Array:
+      return AsmType::FloatQDoubleQ();
+    default:
+      return AsmType::None();
+  }
+}
+
+std::string AsmFunctionType::Name() {
+  if (IsFroundType()) {
+    return "fround";
+  }
+
+  std::string ret;
+  ret += "(";
+  for (size_t ii = 0; ii < args_.size(); ++ii) {
+    ret += args_[ii]->Name();
+    if (ii != args_.size() - 1) {
+      ret += ", ";
+    }
+  }
+  if (IsMinMaxType()) {
+    DCHECK_EQ(args_.size(), 2);
+    ret += "...";
+  }
+  ret += ") -> ";
+  ret += return_type_->Name();
+  return ret;
+}
+
+namespace {
+class AsmFroundType final : public AsmFunctionType {
+ public:
+  bool IsFroundType() const override { return true; }
+
+ private:
+  friend AsmType;
+
+  explicit AsmFroundType(Zone* zone)
+      : AsmFunctionType(zone, AsmType::Float()) {}
+
+  AsmType* ValidateCall(AsmType* return_type,
+                        const ZoneVector<AsmType*>& args) override;
+};
+}  // namespace
+
+AsmType* AsmType::FroundType(Zone* zone) {
+  auto* Fround = new (zone) AsmFroundType(zone);
+  return reinterpret_cast<AsmType*>(Fround);
+}
+
+AsmType* AsmFroundType::ValidateCall(AsmType* return_type,
+                                     const ZoneVector<AsmType*>& args) {
+  if (args.size() != 1) {
+    return AsmType::None();
+  }
+
+  auto* arg = args[0];
+  if (!arg->IsA(AsmType::Floatish()) && !arg->IsA(AsmType::DoubleQ()) &&
+      !arg->IsA(AsmType::Signed()) && !arg->IsA(AsmType::Unsigned())) {
+    return AsmType::None();
+  }
+
+  return AsmType::Float();
+}
+
+namespace {
+class AsmMinMaxType final : public AsmFunctionType {
+ public:
+  bool IsMinMaxType() const override { return true; }
+
+ private:
+  friend AsmType;
+
+  AsmMinMaxType(Zone* zone, AsmType* dest, AsmType* src)
+      : AsmFunctionType(zone, dest) {
+    AddArgument(src);
+    AddArgument(src);
+  }
+
+  AsmType* ValidateCall(AsmType* return_type,
+                        const ZoneVector<AsmType*>& args) override {
+    if (!ReturnType()->IsExactly(return_type)) {
+      return AsmType::None();
+    }
+
+    if (args.size() < 2) {
+      return AsmType::None();
+    }
+
+    for (size_t ii = 0; ii < Arguments().size(); ++ii) {
+      if (!Arguments()[0]->IsExactly(args[ii])) {
+        return AsmType::None();
+      }
+    }
+
+    return ReturnType();
+  }
+};
+}  // namespace
+
+AsmType* AsmType::MinMaxType(Zone* zone, AsmType* dest, AsmType* src) {
+  DCHECK(dest->AsValueType() != nullptr);
+  DCHECK(src->AsValueType() != nullptr);
+  auto* MinMax = new (zone) AsmMinMaxType(zone, dest, src);
+  return reinterpret_cast<AsmType*>(MinMax);
+}
+
+AsmType* AsmFFIType::ValidateCall(AsmType* return_type,
+                                  const ZoneVector<AsmType*>& args) {
+  for (size_t ii = 0; ii < args.size(); ++ii) {
+    if (!args[ii]->IsA(AsmType::Extern())) {
+      return AsmType::None();
+    }
+  }
+
+  return return_type;
+}
+
+AsmType* AsmFunctionType::ValidateCall(AsmType* return_type,
+                                       const ZoneVector<AsmType*>& args) {
+  if (!return_type_->IsExactly(return_type)) {
+    return AsmType::None();
+  }
+
+  if (args_.size() != args.size()) {
+    return AsmType::None();
+  }
+
+  for (size_t ii = 0; ii < args_.size(); ++ii) {
+    if (!args_[ii]->IsExactly(args[ii])) {
+      return AsmType::None();
+    }
+  }
+
+  return return_type_;
+}
+
+std::string AsmOverloadedFunctionType::Name() {
+  std::string ret;
+
+  for (size_t ii = 0; ii < overloads_.size(); ++ii) {
+    if (ii != 0) {
+      ret += " /\\ ";
+    }
+    ret += overloads_[ii]->Name();
+  }
+
+  return ret;
+}
+
+AsmType* AsmOverloadedFunctionType::ValidateCall(
+    AsmType* return_type, const ZoneVector<AsmType*>& args) {
+  for (size_t ii = 0; ii < overloads_.size(); ++ii) {
+    auto* validated_type =
+        overloads_[ii]->AsCallableType()->ValidateCall(return_type, args);
+    if (validated_type != AsmType::None()) {
+      return validated_type;
+    }
+  }
+
+  return AsmType::None();
+}
+
+void AsmOverloadedFunctionType::AddOverload(AsmType* overload) {
+  DCHECK(overload->AsFunctionType() != nullptr);
+  overloads_.push_back(overload);
+}
+
+AsmFunctionTableType::AsmFunctionTableType(size_t length, AsmType* signature)
+    : length_(length), signature_(signature) {
+  DCHECK(signature_ != nullptr);
+  DCHECK(signature_->AsFunctionType() != nullptr);
+}
+
+std::string AsmFunctionTableType::Name() {
+  return signature_->Name() + "[" + std::to_string(length_) + "]";
+}
+
+AsmType* AsmFunctionTableType::ValidateCall(AsmType* return_type,
+                                            const ZoneVector<AsmType*>& args) {
+  return signature_->AsCallableType()->ValidateCall(return_type, args);
+}
+
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
diff --git a/src/wasm/asm-types.h b/src/wasm/asm-types.h
new file mode 100644
index 0000000..a102fc8
--- /dev/null
+++ b/src/wasm/asm-types.h
@@ -0,0 +1,344 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SRC_WASM_ASM_TYPES_H_
+#define SRC_WASM_ASM_TYPES_H_
+
+#include <string>
+
+#include "src/base/macros.h"
+#include "src/zone-containers.h"
+#include "src/zone.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+class AsmType;
+class AsmFFIType;
+class AsmFunctionType;
+class AsmOverloadedFunctionType;
+class AsmFunctionTableType;
+
+// List of V(CamelName, string_name, number, parent_types)
+#define FOR_EACH_ASM_VALUE_TYPE_LIST(V)                                       \
+  /* These tags are not types that are expressable in the asm source. They */ \
+  /* are used to express semantic information about the types they tag.    */ \
+  V(Heap, "[]", 1, 0)                                                         \
+  /*The following are actual types that appear in the asm source. */          \
+  V(Void, "void", 2, 0)                                                       \
+  V(Extern, "extern", 3, 0)                                                   \
+  V(DoubleQ, "double?", 4, 0)                                                 \
+  V(Double, "double", 5, kAsmDoubleQ | kAsmExtern)                            \
+  V(Intish, "intish", 6, 0)                                                   \
+  V(Int, "int", 7, kAsmIntish)                                                \
+  V(Signed, "signed", 8, kAsmInt | kAsmExtern)                                \
+  V(Unsigned, "unsigned", 9, kAsmInt)                                         \
+  V(FixNum, "fixnum", 10, kAsmSigned | kAsmUnsigned)                          \
+  V(Floatish, "floatish", 11, 0)                                              \
+  V(FloatQ, "float?", 12, kAsmFloatish)                                       \
+  V(Float, "float", 13, kAsmFloatQ)                                           \
+  /* Types used for expressing the Heap accesses. */                          \
+  V(Uint8Array, "Uint8Array", 14, kAsmHeap)                                   \
+  V(Int8Array, "Int8Array", 15, kAsmHeap)                                     \
+  V(Uint16Array, "Uint16Array", 16, kAsmHeap)                                 \
+  V(Int16Array, "Int16Array", 17, kAsmHeap)                                   \
+  V(Uint32Array, "Uint32Array", 18, kAsmHeap)                                 \
+  V(Int32Array, "Int32Array", 19, kAsmHeap)                                   \
+  V(Float32Array, "Float32Array", 20, kAsmHeap)                               \
+  V(Float64Array, "Float64Array", 21, kAsmHeap)                               \
+  /* Pseudo-types used in representing heap access for fp types.*/            \
+  V(FloatishDoubleQ, "floatish|double?", 22, kAsmFloatish | kAsmDoubleQ)      \
+  V(FloatQDoubleQ, "float?|double?", 23, kAsmFloatQ | kAsmDoubleQ)            \
+  /* None is used to represent errors in the type checker. */                 \
+  V(None, "<none>", 31, 0)
+
+// List of V(CamelName)
+#define FOR_EACH_ASM_CALLABLE_TYPE_LIST(V) \
+  V(FunctionType)                          \
+  V(FFIType)                               \
+  V(OverloadedFunctionType)                \
+  V(FunctionTableType)
+
+class AsmValueType {
+ public:
+  typedef uint32_t bitset_t;
+
+  enum : uint32_t {
+#define DEFINE_TAG(CamelName, string_name, number, parent_types) \
+  kAsm##CamelName = ((1u << (number)) | (parent_types)),
+    FOR_EACH_ASM_VALUE_TYPE_LIST(DEFINE_TAG)
+#undef DEFINE_TAG
+        kAsmUnknown = 0,
+    kAsmValueTypeTag = 1u
+  };
+
+ private:
+  friend class AsmType;
+
+  static AsmValueType* AsValueType(AsmType* type) {
+    if ((reinterpret_cast<uintptr_t>(type) & kAsmValueTypeTag) ==
+        kAsmValueTypeTag) {
+      return reinterpret_cast<AsmValueType*>(type);
+    }
+    return nullptr;
+  }
+
+  bitset_t Bitset() const {
+    DCHECK((reinterpret_cast<uintptr_t>(this) & kAsmValueTypeTag) ==
+           kAsmValueTypeTag);
+    return static_cast<bitset_t>(reinterpret_cast<uintptr_t>(this) &
+                                 ~kAsmValueTypeTag);
+  }
+
+  static AsmType* New(bitset_t bits) {
+    DCHECK_EQ((bits & kAsmValueTypeTag), 0);
+    return reinterpret_cast<AsmType*>(
+        static_cast<uintptr_t>(bits | kAsmValueTypeTag));
+  }
+
+  // AsmValueTypes can't be created except through AsmValueType::New.
+  DISALLOW_IMPLICIT_CONSTRUCTORS(AsmValueType);
+};
+
+class AsmCallableType : public ZoneObject {
+ public:
+  virtual std::string Name() = 0;
+  virtual AsmType* ValidateCall(AsmType* return_type,
+                                const ZoneVector<AsmType*>& args) = 0;
+
+#define DECLARE_CAST(CamelName) \
+  virtual Asm##CamelName* As##CamelName() { return nullptr; }
+  FOR_EACH_ASM_CALLABLE_TYPE_LIST(DECLARE_CAST)
+#undef DECLARE_CAST
+
+ protected:
+  AsmCallableType() = default;
+  virtual ~AsmCallableType() = default;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AsmCallableType);
+};
+
+class AsmFunctionType : public AsmCallableType {
+ public:
+  AsmFunctionType* AsFunctionType() final { return this; }
+
+  void AddArgument(AsmType* type) { args_.push_back(type); }
+  const ZoneVector<AsmType*> Arguments() const { return args_; }
+  AsmType* ReturnType() const { return return_type_; }
+
+  virtual bool IsMinMaxType() const { return false; }
+  virtual bool IsFroundType() const { return false; }
+
+ protected:
+  AsmFunctionType(Zone* zone, AsmType* return_type)
+      : return_type_(return_type), args_(zone) {}
+
+ private:
+  friend AsmType;
+
+  std::string Name() override;
+  AsmType* ValidateCall(AsmType* return_type,
+                        const ZoneVector<AsmType*>& args) override;
+
+  AsmType* return_type_;
+  ZoneVector<AsmType*> args_;
+
+  DISALLOW_COPY_AND_ASSIGN(AsmFunctionType);
+};
+
+class AsmOverloadedFunctionType final : public AsmCallableType {
+ public:
+  AsmOverloadedFunctionType* AsOverloadedFunctionType() override {
+    return this;
+  }
+
+  void AddOverload(AsmType* overload);
+
+ private:
+  friend AsmType;
+
+  explicit AsmOverloadedFunctionType(Zone* zone) : overloads_(zone) {}
+
+  std::string Name() override;
+  AsmType* ValidateCall(AsmType* return_type,
+                        const ZoneVector<AsmType*>& args) override;
+
+  ZoneVector<AsmType*> overloads_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(AsmOverloadedFunctionType);
+};
+
+class AsmFFIType final : public AsmCallableType {
+ public:
+  AsmFFIType* AsFFIType() override { return this; }
+
+  std::string Name() override { return "Function"; }
+  AsmType* ValidateCall(AsmType* return_type,
+                        const ZoneVector<AsmType*>& args) override;
+
+ private:
+  friend AsmType;
+
+  AsmFFIType() = default;
+
+  DISALLOW_COPY_AND_ASSIGN(AsmFFIType);
+};
+
+class AsmFunctionTableType : public AsmCallableType {
+ public:
+  AsmFunctionTableType* AsFunctionTableType() override { return this; }
+
+  std::string Name() override;
+
+  AsmType* ValidateCall(AsmType* return_type,
+                        const ZoneVector<AsmType*>& args) override;
+
+  size_t length() const { return length_; }
+
+ private:
+  friend class AsmType;
+
+  AsmFunctionTableType(size_t length, AsmType* signature);
+
+  size_t length_;
+  AsmType* signature_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(AsmFunctionTableType);
+};
+
+class AsmType {
+ public:
+#define DEFINE_CONSTRUCTOR(CamelName, string_name, number, parent_types) \
+  static AsmType* CamelName() {                                          \
+    return AsmValueType::New(AsmValueType::kAsm##CamelName);             \
+  }
+  FOR_EACH_ASM_VALUE_TYPE_LIST(DEFINE_CONSTRUCTOR)
+#undef DEFINE_CONSTRUCTOR
+
+#define DEFINE_CAST(CamelCase)                                        \
+  Asm##CamelCase* As##CamelCase() {                                   \
+    if (AsValueType() != nullptr) {                                   \
+      return nullptr;                                                 \
+    }                                                                 \
+    return reinterpret_cast<AsmCallableType*>(this)->As##CamelCase(); \
+  }
+  FOR_EACH_ASM_CALLABLE_TYPE_LIST(DEFINE_CAST)
+#undef DEFINE_CAST
+  AsmValueType* AsValueType() { return AsmValueType::AsValueType(this); }
+  AsmCallableType* AsCallableType();
+
+  // A function returning ret. Callers still need to invoke AddArgument with the
+  // returned type to fully create this type.
+  static AsmType* Function(Zone* zone, AsmType* ret) {
+    AsmFunctionType* f = new (zone) AsmFunctionType(zone, ret);
+    return reinterpret_cast<AsmType*>(f);
+  }
+
+  // Overloaded function types. Not creatable by asm source, but useful to
+  // represent the overloaded stdlib functions.
+  static AsmType* OverloadedFunction(Zone* zone) {
+    auto* f = new (zone) AsmOverloadedFunctionType(zone);
+    return reinterpret_cast<AsmType*>(f);
+  }
+
+  // The type for fround(src).
+  static AsmType* FroundType(Zone* zone);
+
+  // The (variadic) type for min and max.
+  static AsmType* MinMaxType(Zone* zone, AsmType* dest, AsmType* src);
+
+  // The type for foreign functions.
+  static AsmType* FFIType(Zone* zone) {
+    auto* f = new (zone) AsmFFIType();
+    return reinterpret_cast<AsmType*>(f);
+  }
+
+  // The type for function tables.
+  static AsmType* FunctionTableType(Zone* zone, size_t length,
+                                    AsmType* signature) {
+    auto* f = new (zone) AsmFunctionTableType(length, signature);
+    return reinterpret_cast<AsmType*>(f);
+  }
+
+  std::string Name();
+  // IsExactly returns true if this is the exact same type as that. For
+  // non-value types (e.g., callables), this returns this == that.
+  bool IsExactly(AsmType* that);
+  // IsA is used to query whether this is an instance of that (i.e., if this is
+  // a type derived from that.) For non-value types (e.g., callables), this
+  // returns this == that.
+  bool IsA(AsmType* that);
+
+  // Types allowed in return statements. void is the type for returns without
+  // an expression.
+  bool IsReturnType() {
+    return this == AsmType::Void() || this == AsmType::Double() ||
+           this == AsmType::Signed() || this == AsmType::Float();
+  }
+
+  // Converts this to the corresponding valid argument type.
+  AsmType* ToReturnType() {
+    if (this->IsA(AsmType::Signed())) {
+      return AsmType::Signed();
+    }
+    if (this->IsA(AsmType::Double())) {
+      return AsmType::Double();
+    }
+    if (this->IsA(AsmType::Float())) {
+      return AsmType::Float();
+    }
+    if (this->IsA(AsmType::Void())) {
+      return AsmType::Void();
+    }
+    return AsmType::None();
+  }
+
+  // Types allowed to be parameters in asm functions.
+  bool IsParameterType() {
+    return this == AsmType::Double() || this == AsmType::Int() ||
+           this == AsmType::Float();
+  }
+
+  // Converts this to the corresponding valid argument type.
+  AsmType* ToParameterType() {
+    if (this->IsA(AsmType::Int())) {
+      return AsmType::Int();
+    }
+    if (this->IsA(AsmType::Double())) {
+      return AsmType::Double();
+    }
+    if (this->IsA(AsmType::Float())) {
+      return AsmType::Float();
+    }
+    return AsmType::None();
+  }
+
+  // Types allowed to be compared using the comparison operators.
+  bool IsComparableType() {
+    return this == AsmType::Double() || this == AsmType::Signed() ||
+           this == AsmType::Unsigned() || this == AsmType::Float();
+  }
+
+  // The following methods are meant to be used for inspecting the traits of
+  // element types for the heap view types.
+  enum : int32_t { kNotHeapType = -1 };
+
+  // Returns the element size if this is a heap type. Otherwise returns
+  // kNotHeapType.
+  int32_t ElementSizeInBytes();
+  // Returns the load type if this is a heap type. AsmType::None is returned if
+  // this is not a heap type.
+  AsmType* LoadType();
+  // Returns the store type if this is a heap type. AsmType::None is returned if
+  // this is not a heap type.
+  AsmType* StoreType();
+};
+
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
+
+#endif  // SRC_WASM_ASM_TYPES_H_
diff --git a/src/wasm/asm-wasm-builder.cc b/src/wasm/asm-wasm-builder.cc
index d16d3a8..958fd0c 100644
--- a/src/wasm/asm-wasm-builder.cc
+++ b/src/wasm/asm-wasm-builder.cc
@@ -11,6 +11,7 @@
 #include <math.h>
 
 #include "src/wasm/asm-wasm-builder.h"
+#include "src/wasm/switch-logic.h"
 #include "src/wasm/wasm-macro-gen.h"
 #include "src/wasm/wasm-opcodes.h"
 
@@ -30,81 +31,127 @@
     if (HasStackOverflow()) return; \
   } while (false)
 
+enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope };
+
+struct ForeignVariable {
+  Handle<Name> name;
+  Variable* var;
+  LocalType type;
+};
 
 class AsmWasmBuilderImpl : public AstVisitor {
  public:
   AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal,
-                     Handle<Object> foreign, AsmTyper* typer)
-      : local_variables_(HashMap::PointersMatch,
+                     AsmTyper* typer)
+      : local_variables_(base::HashMap::PointersMatch,
                          ZoneHashMap::kDefaultHashMapCapacity,
                          ZoneAllocationPolicy(zone)),
-        functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity,
+        functions_(base::HashMap::PointersMatch,
+                   ZoneHashMap::kDefaultHashMapCapacity,
                    ZoneAllocationPolicy(zone)),
-        global_variables_(HashMap::PointersMatch,
+        global_variables_(base::HashMap::PointersMatch,
                           ZoneHashMap::kDefaultHashMapCapacity,
                           ZoneAllocationPolicy(zone)),
-        in_function_(false),
-        is_set_op_(false),
-        marking_exported(false),
+        scope_(kModuleScope),
         builder_(new (zone) WasmModuleBuilder(zone)),
         current_function_builder_(nullptr),
         literal_(literal),
         isolate_(isolate),
         zone_(zone),
-        foreign_(foreign),
         typer_(typer),
         cache_(TypeCache::Get()),
         breakable_blocks_(zone),
-        block_size_(0),
+        foreign_variables_(zone),
         init_function_index_(0),
+        foreign_init_function_index_(0),
         next_table_index_(0),
-        function_tables_(HashMap::PointersMatch,
+        function_tables_(base::HashMap::PointersMatch,
                          ZoneHashMap::kDefaultHashMapCapacity,
                          ZoneAllocationPolicy(zone)),
-        imported_function_table_(this) {
+        imported_function_table_(this),
+        bounds_(typer->bounds()) {
     InitializeAstVisitor(isolate);
   }
 
   void InitializeInitFunction() {
     init_function_index_ = builder_->AddFunction();
+    FunctionSig::Builder b(zone(), 0, 0);
     current_function_builder_ = builder_->FunctionAt(init_function_index_);
-    current_function_builder_->ReturnType(kAstStmt);
+    current_function_builder_->SetSignature(b.Build());
     builder_->MarkStartFunction(init_function_index_);
     current_function_builder_ = nullptr;
   }
 
-  void Compile() {
-    InitializeInitFunction();
-    RECURSE(VisitFunctionLiteral(literal_));
+  void BuildForeignInitFunction() {
+    foreign_init_function_index_ = builder_->AddFunction();
+    FunctionSig::Builder b(zone(), 0, foreign_variables_.size());
+    for (auto i = foreign_variables_.begin(); i != foreign_variables_.end();
+         ++i) {
+      b.AddParam(i->type);
+    }
+    current_function_builder_ =
+        builder_->FunctionAt(foreign_init_function_index_);
+    current_function_builder_->SetExported();
+    std::string raw_name = "__foreign_init__";
+    current_function_builder_->SetName(raw_name.data(),
+                                       static_cast<int>(raw_name.size()));
+    current_function_builder_->SetSignature(b.Build());
+    for (size_t pos = 0; pos < foreign_variables_.size(); ++pos) {
+      current_function_builder_->EmitGetLocal(static_cast<uint32_t>(pos));
+      ForeignVariable* fv = &foreign_variables_[pos];
+      uint32_t index = LookupOrInsertGlobal(fv->var, fv->type);
+      current_function_builder_->EmitWithVarInt(kExprStoreGlobal, index);
+    }
+    current_function_builder_ = nullptr;
   }
 
-  void VisitVariableDeclaration(VariableDeclaration* decl) {}
+  i::Handle<i::FixedArray> GetForeignArgs() {
+    i::Handle<FixedArray> ret = isolate_->factory()->NewFixedArray(
+        static_cast<int>(foreign_variables_.size()));
+    for (size_t i = 0; i < foreign_variables_.size(); ++i) {
+      ForeignVariable* fv = &foreign_variables_[i];
+      ret->set(static_cast<int>(i), *fv->name);
+    }
+    return ret;
+  }
 
-  void VisitFunctionDeclaration(FunctionDeclaration* decl) {
-    DCHECK(!in_function_);
+  void Build() {
+    InitializeInitFunction();
+    RECURSE(VisitFunctionLiteral(literal_));
+    BuildForeignInitFunction();
+  }
+
+  void VisitVariableDeclaration(VariableDeclaration* decl) override {}
+
+  void VisitFunctionDeclaration(FunctionDeclaration* decl) override {
+    DCHECK_EQ(kModuleScope, scope_);
     DCHECK_NULL(current_function_builder_);
-    uint16_t index = LookupOrInsertFunction(decl->proxy()->var());
+    uint32_t index = LookupOrInsertFunction(decl->proxy()->var());
     current_function_builder_ = builder_->FunctionAt(index);
-    in_function_ = true;
+    scope_ = kFuncScope;
     RECURSE(Visit(decl->fun()));
-    in_function_ = false;
+    scope_ = kModuleScope;
     current_function_builder_ = nullptr;
     local_variables_.Clear();
   }
 
-  void VisitImportDeclaration(ImportDeclaration* decl) {}
+  void VisitImportDeclaration(ImportDeclaration* decl) override {}
 
-  void VisitExportDeclaration(ExportDeclaration* decl) {}
+  void VisitExportDeclaration(ExportDeclaration* decl) override {}
 
-  void VisitStatements(ZoneList<Statement*>* stmts) {
+  void VisitStatements(ZoneList<Statement*>* stmts) override {
     for (int i = 0; i < stmts->length(); ++i) {
       Statement* stmt = stmts->at(i);
+      ExpressionStatement* e = stmt->AsExpressionStatement();
+      if (e != nullptr && e->expression()->IsUndefinedLiteral()) {
+        continue;
+      }
       RECURSE(Visit(stmt));
       if (stmt->IsJump()) break;
     }
   }
 
-  void VisitBlock(Block* stmt) {
+  void VisitBlock(Block* stmt) override {
     if (stmt->statements()->length() == 1) {
       ExpressionStatement* expr =
           stmt->statements()->at(0)->AsExpressionStatement();
@@ -115,12 +162,10 @@
         }
       }
     }
-    if (in_function_) {
+    if (scope_ == kFuncScope) {
       BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock,
-                           false,
-                           static_cast<byte>(stmt->statements()->length()));
+                           false);
       RECURSE(VisitStatements(stmt->statements()));
-      DCHECK(block_size_ >= 0);
     } else {
       RECURSE(VisitStatements(stmt->statements()));
     }
@@ -128,57 +173,50 @@
 
   class BlockVisitor {
    private:
-    int prev_block_size_;
-    uint32_t index_;
     AsmWasmBuilderImpl* builder_;
 
    public:
     BlockVisitor(AsmWasmBuilderImpl* builder, BreakableStatement* stmt,
-                 WasmOpcode opcode, bool is_loop, int initial_block_size)
+                 WasmOpcode opcode, bool is_loop)
         : builder_(builder) {
       builder_->breakable_blocks_.push_back(std::make_pair(stmt, is_loop));
       builder_->current_function_builder_->Emit(opcode);
-      index_ =
-          builder_->current_function_builder_->EmitEditableVarIntImmediate();
-      prev_block_size_ = builder_->block_size_;
-      builder_->block_size_ = initial_block_size;
     }
     ~BlockVisitor() {
-      builder_->current_function_builder_->EditVarIntImmediate(
-          index_, builder_->block_size_);
-      builder_->block_size_ = prev_block_size_;
+      builder_->current_function_builder_->Emit(kExprEnd);
       builder_->breakable_blocks_.pop_back();
     }
   };
 
-  void VisitExpressionStatement(ExpressionStatement* stmt) {
+  void VisitExpressionStatement(ExpressionStatement* stmt) override {
     RECURSE(Visit(stmt->expression()));
   }
 
-  void VisitEmptyStatement(EmptyStatement* stmt) {}
+  void VisitEmptyStatement(EmptyStatement* stmt) override {}
 
-  void VisitEmptyParentheses(EmptyParentheses* paren) { UNREACHABLE(); }
-
-  void VisitIfStatement(IfStatement* stmt) {
-    DCHECK(in_function_);
-    if (stmt->HasElseStatement()) {
-      current_function_builder_->Emit(kExprIfElse);
-    } else {
-      current_function_builder_->Emit(kExprIf);
-    }
-    RECURSE(Visit(stmt->condition()));
-    if (stmt->HasThenStatement()) {
-      RECURSE(Visit(stmt->then_statement()));
-    } else {
-      current_function_builder_->Emit(kExprNop);
-    }
-    if (stmt->HasElseStatement()) {
-      RECURSE(Visit(stmt->else_statement()));
-    }
+  void VisitEmptyParentheses(EmptyParentheses* paren) override {
+    UNREACHABLE();
   }
 
-  void VisitContinueStatement(ContinueStatement* stmt) {
-    DCHECK(in_function_);
+  void VisitIfStatement(IfStatement* stmt) override {
+    DCHECK_EQ(kFuncScope, scope_);
+    RECURSE(Visit(stmt->condition()));
+    current_function_builder_->Emit(kExprIf);
+    // WASM ifs come with implement blocks for both arms.
+    breakable_blocks_.push_back(std::make_pair(nullptr, false));
+    if (stmt->HasThenStatement()) {
+      RECURSE(Visit(stmt->then_statement()));
+    }
+    if (stmt->HasElseStatement()) {
+      current_function_builder_->Emit(kExprElse);
+      RECURSE(Visit(stmt->else_statement()));
+    }
+    current_function_builder_->Emit(kExprEnd);
+    breakable_blocks_.pop_back();
+  }
+
+  void VisitContinueStatement(ContinueStatement* stmt) override {
+    DCHECK_EQ(kFuncScope, scope_);
     DCHECK_NOT_NULL(stmt->target());
     int i = static_cast<int>(breakable_blocks_.size()) - 1;
     int block_distance = 0;
@@ -194,12 +232,12 @@
       }
     }
     DCHECK(i >= 0);
-    current_function_builder_->EmitWithVarInt(kExprBr, block_distance);
-    current_function_builder_->Emit(kExprNop);
+    current_function_builder_->EmitWithU8(kExprBr, ARITY_0);
+    current_function_builder_->EmitVarInt(block_distance);
   }
 
-  void VisitBreakStatement(BreakStatement* stmt) {
-    DCHECK(in_function_);
+  void VisitBreakStatement(BreakStatement* stmt) override {
+    DCHECK_EQ(kFuncScope, scope_);
     DCHECK_NOT_NULL(stmt->target());
     int i = static_cast<int>(breakable_blocks_.size()) - 1;
     int block_distance = 0;
@@ -217,147 +255,226 @@
       }
     }
     DCHECK(i >= 0);
-    current_function_builder_->EmitWithVarInt(kExprBr, block_distance);
-    current_function_builder_->Emit(kExprNop);
+    current_function_builder_->EmitWithU8(kExprBr, ARITY_0);
+    current_function_builder_->EmitVarInt(block_distance);
   }
 
-  void VisitReturnStatement(ReturnStatement* stmt) {
-    if (in_function_) {
-      current_function_builder_->Emit(kExprReturn);
+  void VisitReturnStatement(ReturnStatement* stmt) override {
+    if (scope_ == kModuleScope) {
+      scope_ = kExportScope;
+      RECURSE(Visit(stmt->expression()));
+      scope_ = kModuleScope;
+    } else if (scope_ == kFuncScope) {
+      RECURSE(Visit(stmt->expression()));
+      uint8_t arity =
+          TypeOf(stmt->expression()) == kAstStmt ? ARITY_0 : ARITY_1;
+      current_function_builder_->EmitWithU8(kExprReturn, arity);
     } else {
-      marking_exported = true;
-    }
-    RECURSE(Visit(stmt->expression()));
-    if (!in_function_) {
-      marking_exported = false;
+      UNREACHABLE();
     }
   }
 
-  void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); }
+  void VisitWithStatement(WithStatement* stmt) override { UNREACHABLE(); }
 
-  void SetLocalTo(uint16_t index, int value) {
-    current_function_builder_->Emit(kExprSetLocal);
-    AddLeb128(index, true);
-    // TODO(bradnelson): variable size
-    byte code[] = {WASM_I32V(value)};
-    current_function_builder_->EmitCode(code, sizeof(code));
-    block_size_++;
+  void HandleCase(CaseNode* node,
+                  const ZoneMap<int, unsigned int>& case_to_block,
+                  VariableProxy* tag, int default_block, int if_depth) {
+    int prev_if_depth = if_depth;
+    if (node->left != nullptr) {
+      VisitVariableProxy(tag);
+      current_function_builder_->EmitI32Const(node->begin);
+      current_function_builder_->Emit(kExprI32LtS);
+      current_function_builder_->Emit(kExprIf);
+      if_depth++;
+      breakable_blocks_.push_back(std::make_pair(nullptr, false));
+      HandleCase(node->left, case_to_block, tag, default_block, if_depth);
+      current_function_builder_->Emit(kExprElse);
+    }
+    if (node->right != nullptr) {
+      VisitVariableProxy(tag);
+      current_function_builder_->EmitI32Const(node->end);
+      current_function_builder_->Emit(kExprI32GtS);
+      current_function_builder_->Emit(kExprIf);
+      if_depth++;
+      breakable_blocks_.push_back(std::make_pair(nullptr, false));
+      HandleCase(node->right, case_to_block, tag, default_block, if_depth);
+      current_function_builder_->Emit(kExprElse);
+    }
+    if (node->begin == node->end) {
+      VisitVariableProxy(tag);
+      current_function_builder_->EmitI32Const(node->begin);
+      current_function_builder_->Emit(kExprI32Eq);
+      current_function_builder_->Emit(kExprIf);
+      DCHECK(case_to_block.find(node->begin) != case_to_block.end());
+      current_function_builder_->EmitWithU8(kExprBr, ARITY_0);
+      current_function_builder_->EmitVarInt(1 + if_depth +
+                                            case_to_block.at(node->begin));
+      current_function_builder_->Emit(kExprEnd);
+    } else {
+      if (node->begin != 0) {
+        VisitVariableProxy(tag);
+        current_function_builder_->EmitI32Const(node->begin);
+        current_function_builder_->Emit(kExprI32Sub);
+      } else {
+        VisitVariableProxy(tag);
+      }
+      current_function_builder_->EmitWithU8(kExprBrTable, ARITY_0);
+      current_function_builder_->EmitVarInt(node->end - node->begin + 1);
+      for (int v = node->begin; v <= node->end; v++) {
+        if (case_to_block.find(v) != case_to_block.end()) {
+          byte break_code[] = {BR_TARGET(if_depth + case_to_block.at(v))};
+          current_function_builder_->EmitCode(break_code, sizeof(break_code));
+        } else {
+          byte break_code[] = {BR_TARGET(if_depth + default_block)};
+          current_function_builder_->EmitCode(break_code, sizeof(break_code));
+        }
+        if (v == kMaxInt) {
+          break;
+        }
+      }
+      byte break_code[] = {BR_TARGET(if_depth + default_block)};
+      current_function_builder_->EmitCode(break_code, sizeof(break_code));
+    }
+
+    while (if_depth-- != prev_if_depth) {
+      breakable_blocks_.pop_back();
+      current_function_builder_->Emit(kExprEnd);
+    }
   }
 
-  void CompileCase(CaseClause* clause, uint16_t fall_through,
-                   VariableProxy* tag) {
-    Literal* label = clause->label()->AsLiteral();
-    DCHECK_NOT_NULL(label);
-    block_size_++;
-    current_function_builder_->Emit(kExprIf);
-    current_function_builder_->Emit(kExprI32Ior);
-    current_function_builder_->Emit(kExprI32Eq);
-    VisitVariableProxy(tag);
-    VisitLiteral(label);
-    current_function_builder_->Emit(kExprGetLocal);
-    AddLeb128(fall_through, true);
-    BlockVisitor visitor(this, nullptr, kExprBlock, false, 0);
-    SetLocalTo(fall_through, 1);
-    ZoneList<Statement*>* stmts = clause->statements();
-    block_size_ += stmts->length();
-    RECURSE(VisitStatements(stmts));
-  }
-
-  void VisitSwitchStatement(SwitchStatement* stmt) {
+  void VisitSwitchStatement(SwitchStatement* stmt) override {
     VariableProxy* tag = stmt->tag()->AsVariableProxy();
     DCHECK_NOT_NULL(tag);
-    BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false,
-                         0);
-    uint16_t fall_through = current_function_builder_->AddLocal(kAstI32);
-    SetLocalTo(fall_through, 0);
-
     ZoneList<CaseClause*>* clauses = stmt->cases();
-    for (int i = 0; i < clauses->length(); ++i) {
+    int case_count = clauses->length();
+    if (case_count == 0) {
+      return;
+    }
+    BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false);
+    ZoneVector<BlockVisitor*> blocks(zone_);
+    ZoneVector<int32_t> cases(zone_);
+    ZoneMap<int, unsigned int> case_to_block(zone_);
+    bool has_default = false;
+    for (int i = case_count - 1; i >= 0; i--) {
       CaseClause* clause = clauses->at(i);
+      blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock, false));
       if (!clause->is_default()) {
-        CompileCase(clause, fall_through, tag);
+        Literal* label = clause->label()->AsLiteral();
+        Handle<Object> value = label->value();
+        DCHECK(value->IsNumber() &&
+               bounds_->get(label).upper->Is(cache_.kAsmSigned));
+        int32_t label_value;
+        if (!value->ToInt32(&label_value)) {
+          UNREACHABLE();
+        }
+        case_to_block[label_value] = i;
+        cases.push_back(label_value);
       } else {
-        ZoneList<Statement*>* stmts = clause->statements();
-        block_size_ += stmts->length();
-        RECURSE(VisitStatements(stmts));
+        DCHECK_EQ(i, case_count - 1);
+        has_default = true;
       }
     }
+    if (!has_default || case_count > 1) {
+      int default_block = has_default ? case_count - 1 : case_count;
+      BlockVisitor switch_logic_block(this, nullptr, kExprBlock, false);
+      CaseNode* root = OrderCases(&cases, zone_);
+      HandleCase(root, case_to_block, tag, default_block, 0);
+      if (root->left != nullptr || root->right != nullptr ||
+          root->begin == root->end) {
+        current_function_builder_->EmitWithU8(kExprBr, ARITY_0);
+        current_function_builder_->EmitVarInt(default_block);
+      }
+    }
+    for (int i = 0; i < case_count; ++i) {
+      CaseClause* clause = clauses->at(i);
+      RECURSE(VisitStatements(clause->statements()));
+      BlockVisitor* v = blocks.at(case_count - i - 1);
+      blocks.pop_back();
+      delete v;
+    }
   }
 
-  void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); }
+  void VisitCaseClause(CaseClause* clause) override { UNREACHABLE(); }
 
-  void VisitDoWhileStatement(DoWhileStatement* stmt) {
-    DCHECK(in_function_);
-    BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true,
-                         2);
+  void VisitDoWhileStatement(DoWhileStatement* stmt) override {
+    DCHECK_EQ(kFuncScope, scope_);
+    BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true);
     RECURSE(Visit(stmt->body()));
-    current_function_builder_->Emit(kExprIf);
     RECURSE(Visit(stmt->cond()));
-    current_function_builder_->EmitWithVarInt(kExprBr, 0);
-    current_function_builder_->Emit(kExprNop);
+    current_function_builder_->Emit(kExprIf);
+    current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 1);
+    current_function_builder_->Emit(kExprEnd);
   }
 
-  void VisitWhileStatement(WhileStatement* stmt) {
-    DCHECK(in_function_);
-    BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true,
-                         1);
-    current_function_builder_->Emit(kExprIf);
+  void VisitWhileStatement(WhileStatement* stmt) override {
+    DCHECK_EQ(kFuncScope, scope_);
+    BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true);
     RECURSE(Visit(stmt->cond()));
-    current_function_builder_->EmitWithVarInt(kExprBr, 0);
+    breakable_blocks_.push_back(std::make_pair(nullptr, false));
+    current_function_builder_->Emit(kExprIf);
     RECURSE(Visit(stmt->body()));
+    current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 1);
+    current_function_builder_->Emit(kExprEnd);
+    breakable_blocks_.pop_back();
   }
 
-  void VisitForStatement(ForStatement* stmt) {
-    DCHECK(in_function_);
+  void VisitForStatement(ForStatement* stmt) override {
+    DCHECK_EQ(kFuncScope, scope_);
     if (stmt->init() != nullptr) {
-      block_size_++;
       RECURSE(Visit(stmt->init()));
     }
-    BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true,
-                         0);
+    BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true);
     if (stmt->cond() != nullptr) {
-      block_size_++;
-      current_function_builder_->Emit(kExprIf);
-      current_function_builder_->Emit(kExprI32Eqz);
       RECURSE(Visit(stmt->cond()));
-      current_function_builder_->EmitWithVarInt(kExprBr, 1);
+      current_function_builder_->Emit(kExprI32Eqz);
+      current_function_builder_->Emit(kExprIf);
       current_function_builder_->Emit(kExprNop);
+      current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 2);
+      current_function_builder_->Emit(kExprEnd);
     }
     if (stmt->body() != nullptr) {
-      block_size_++;
       RECURSE(Visit(stmt->body()));
     }
     if (stmt->next() != nullptr) {
-      block_size_++;
       RECURSE(Visit(stmt->next()));
     }
-    block_size_++;
-    current_function_builder_->EmitWithVarInt(kExprBr, 0);
     current_function_builder_->Emit(kExprNop);
+    current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 0);
   }
 
-  void VisitForInStatement(ForInStatement* stmt) { UNREACHABLE(); }
+  void VisitForInStatement(ForInStatement* stmt) override { UNREACHABLE(); }
 
-  void VisitForOfStatement(ForOfStatement* stmt) { UNREACHABLE(); }
+  void VisitForOfStatement(ForOfStatement* stmt) override { UNREACHABLE(); }
 
-  void VisitTryCatchStatement(TryCatchStatement* stmt) { UNREACHABLE(); }
+  void VisitTryCatchStatement(TryCatchStatement* stmt) override {
+    UNREACHABLE();
+  }
 
-  void VisitTryFinallyStatement(TryFinallyStatement* stmt) { UNREACHABLE(); }
+  void VisitTryFinallyStatement(TryFinallyStatement* stmt) override {
+    UNREACHABLE();
+  }
 
-  void VisitDebuggerStatement(DebuggerStatement* stmt) { UNREACHABLE(); }
+  void VisitDebuggerStatement(DebuggerStatement* stmt) override {
+    UNREACHABLE();
+  }
 
-  void VisitFunctionLiteral(FunctionLiteral* expr) {
+  void VisitFunctionLiteral(FunctionLiteral* expr) override {
     Scope* scope = expr->scope();
-    if (in_function_) {
-      if (expr->bounds().lower->IsFunction()) {
-        FunctionType* func_type = expr->bounds().lower->AsFunction();
+    if (scope_ == kFuncScope) {
+      if (bounds_->get(expr).lower->IsFunction()) {
+        // Build the signature for the function.
+        FunctionType* func_type = bounds_->get(expr).lower->AsFunction();
         LocalType return_type = TypeFrom(func_type->Result());
-        current_function_builder_->ReturnType(return_type);
-        for (int i = 0; i < expr->parameter_count(); i++) {
+        FunctionSig::Builder b(zone(), return_type == kAstStmt ? 0 : 1,
+                               func_type->Arity());
+        if (return_type != kAstStmt) b.AddReturn(return_type);
+        for (int i = 0; i < expr->parameter_count(); ++i) {
           LocalType type = TypeFrom(func_type->Parameter(i));
           DCHECK_NE(kAstStmt, type);
-          LookupOrInsertLocal(scope->parameter(i), type);
+          b.AddParam(type);
+          InsertParameter(scope->parameter(i), type, i);
         }
+        current_function_builder_->SetSignature(b.Build());
       } else {
         UNREACHABLE();
       }
@@ -366,16 +483,21 @@
     RECURSE(VisitDeclarations(scope->declarations()));
   }
 
-  void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
+  void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) override {
     UNREACHABLE();
   }
 
-  void VisitConditional(Conditional* expr) {
-    DCHECK(in_function_);
-    current_function_builder_->Emit(kExprIfElse);
+  void VisitConditional(Conditional* expr) override {
+    DCHECK_EQ(kFuncScope, scope_);
     RECURSE(Visit(expr->condition()));
+    // WASM ifs come with implicit blocks for both arms.
+    breakable_blocks_.push_back(std::make_pair(nullptr, false));
+    current_function_builder_->Emit(kExprIf);
     RECURSE(Visit(expr->then_expression()));
+    current_function_builder_->Emit(kExprElse);
     RECURSE(Visit(expr->else_expression()));
+    current_function_builder_->Emit(kExprEnd);
+    breakable_blocks_.pop_back();
   }
 
   bool VisitStdlibConstant(Variable* var) {
@@ -430,42 +552,30 @@
     return true;
   }
 
-  void VisitVariableProxy(VariableProxy* expr) {
-    if (in_function_) {
+  void VisitVariableProxy(VariableProxy* expr) override {
+    if (scope_ == kFuncScope || scope_ == kInitScope) {
       Variable* var = expr->var();
-      if (is_set_op_) {
-        if (var->IsContextSlot()) {
-          current_function_builder_->Emit(kExprStoreGlobal);
-        } else {
-          current_function_builder_->Emit(kExprSetLocal);
-        }
-        is_set_op_ = false;
-      } else {
-        if (VisitStdlibConstant(var)) {
-          return;
-        }
-        if (var->IsContextSlot()) {
-          current_function_builder_->Emit(kExprLoadGlobal);
-        } else {
-          current_function_builder_->Emit(kExprGetLocal);
-        }
+      if (VisitStdlibConstant(var)) {
+        return;
       }
       LocalType var_type = TypeOf(expr);
       DCHECK_NE(kAstStmt, var_type);
       if (var->IsContextSlot()) {
-        AddLeb128(LookupOrInsertGlobal(var, var_type), false);
+        current_function_builder_->EmitWithVarInt(
+            kExprLoadGlobal, LookupOrInsertGlobal(var, var_type));
       } else {
-        AddLeb128(LookupOrInsertLocal(var, var_type), true);
+        current_function_builder_->EmitGetLocal(
+            LookupOrInsertLocal(var, var_type));
       }
     }
   }
 
-  void VisitLiteral(Literal* expr) {
+  void VisitLiteral(Literal* expr) override {
     Handle<Object> value = expr->value();
-    if (!in_function_ || !value->IsNumber()) {
+    if (!value->IsNumber() || (scope_ != kFuncScope && scope_ != kInitScope)) {
       return;
     }
-    Type* type = expr->bounds().upper;
+    Type* type = bounds_->get(expr).upper;
     if (type->Is(cache_.kAsmSigned)) {
       int32_t i = 0;
       if (!value->ToInt32(&i)) {
@@ -490,13 +600,13 @@
     }
   }
 
-  void VisitRegExpLiteral(RegExpLiteral* expr) { UNREACHABLE(); }
+  void VisitRegExpLiteral(RegExpLiteral* expr) override { UNREACHABLE(); }
 
-  void VisitObjectLiteral(ObjectLiteral* expr) {
+  void VisitObjectLiteral(ObjectLiteral* expr) override {
     ZoneList<ObjectLiteralProperty*>* props = expr->properties();
     for (int i = 0; i < props->length(); ++i) {
       ObjectLiteralProperty* prop = props->at(i);
-      DCHECK(marking_exported);
+      DCHECK_EQ(kExportScope, scope_);
       VariableProxy* expr = prop->value()->AsVariableProxy();
       DCHECK_NOT_NULL(expr);
       Variable* var = expr->var();
@@ -505,42 +615,43 @@
       DCHECK(name->IsPropertyName());
       const AstRawString* raw_name = name->AsRawPropertyName();
       if (var->is_function()) {
-        uint16_t index = LookupOrInsertFunction(var);
-        builder_->FunctionAt(index)->Exported(1);
-        builder_->FunctionAt(index)
-            ->SetName(raw_name->raw_data(), raw_name->length());
+        uint32_t index = LookupOrInsertFunction(var);
+        builder_->FunctionAt(index)->SetExported();
+        builder_->FunctionAt(index)->SetName(
+            reinterpret_cast<const char*>(raw_name->raw_data()),
+            raw_name->length());
       }
     }
   }
 
-  void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); }
+  void VisitArrayLiteral(ArrayLiteral* expr) override { UNREACHABLE(); }
 
   void LoadInitFunction() {
     current_function_builder_ = builder_->FunctionAt(init_function_index_);
-    in_function_ = true;
+    scope_ = kInitScope;
   }
 
   void UnLoadInitFunction() {
-    in_function_ = false;
+    scope_ = kModuleScope;
     current_function_builder_ = nullptr;
   }
 
   void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) {
     FunctionType* func_type =
-        funcs->bounds().lower->AsArray()->Element()->AsFunction();
+        bounds_->get(funcs).lower->AsArray()->Element()->AsFunction();
     LocalType return_type = TypeFrom(func_type->Result());
     FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1,
                              func_type->Arity());
     if (return_type != kAstStmt) {
       sig.AddReturn(static_cast<LocalType>(return_type));
     }
-    for (int i = 0; i < func_type->Arity(); i++) {
+    for (int i = 0; i < func_type->Arity(); ++i) {
       sig.AddParam(TypeFrom(func_type->Parameter(i)));
     }
-    uint16_t signature_index = builder_->AddSignature(sig.Build());
+    uint32_t signature_index = builder_->AddSignature(sig.Build());
     InsertFunctionTable(table->var(), next_table_index_, signature_index);
     next_table_index_ += funcs->values()->length();
-    for (int i = 0; i < funcs->values()->length(); i++) {
+    for (int i = 0; i < funcs->values()->length(); ++i) {
       VariableProxy* func = funcs->values()->at(i)->AsVariableProxy();
       DCHECK_NOT_NULL(func);
       builder_->AddIndirectFunction(LookupOrInsertFunction(func->var()));
@@ -549,11 +660,11 @@
 
   struct FunctionTableIndices : public ZoneObject {
     uint32_t start_index;
-    uint16_t signature_index;
+    uint32_t signature_index;
   };
 
   void InsertFunctionTable(Variable* v, uint32_t start_index,
-                           uint16_t signature_index) {
+                           uint32_t signature_index) {
     FunctionTableIndices* container = new (zone()) FunctionTableIndices();
     container->start_index = start_index;
     container->signature_index = signature_index;
@@ -573,12 +684,11 @@
    private:
     class ImportedFunctionIndices : public ZoneObject {
      public:
-      const unsigned char* name_;
+      const char* name_;
       int name_length_;
       WasmModuleBuilder::SignatureMap signature_to_index_;
 
-      ImportedFunctionIndices(const unsigned char* name, int name_length,
-                              Zone* zone)
+      ImportedFunctionIndices(const char* name, int name_length, Zone* zone)
           : name_(name), name_length_(name_length), signature_to_index_(zone) {}
     };
     ZoneHashMap table_;
@@ -586,11 +696,12 @@
 
    public:
     explicit ImportedFunctionTable(AsmWasmBuilderImpl* builder)
-        : table_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity,
+        : table_(base::HashMap::PointersMatch,
+                 ZoneHashMap::kDefaultHashMapCapacity,
                  ZoneAllocationPolicy(builder->zone())),
           builder_(builder) {}
 
-    void AddImport(Variable* v, const unsigned char* name, int name_length) {
+    void AddImport(Variable* v, const char* name, int name_length) {
       ImportedFunctionIndices* indices = new (builder_->zone())
           ImportedFunctionIndices(name, name_length, builder_->zone());
       ZoneHashMap::Entry* entry = table_.LookupOrInsert(
@@ -598,7 +709,7 @@
       entry->value = indices;
     }
 
-    uint16_t GetFunctionIndex(Variable* v, FunctionSig* sig) {
+    uint32_t GetFunctionIndex(Variable* v, FunctionSig* sig) {
       ZoneHashMap::Entry* entry = table_.Lookup(v, ComputePointerHash(v));
       DCHECK_NOT_NULL(entry);
       ImportedFunctionIndices* indices =
@@ -608,60 +719,141 @@
       if (pos != indices->signature_to_index_.end()) {
         return pos->second;
       } else {
-        uint16_t index = builder_->builder_->AddFunction();
+        uint32_t index = builder_->builder_->AddImport(
+            indices->name_, indices->name_length_, sig);
         indices->signature_to_index_[sig] = index;
-        WasmFunctionBuilder* function = builder_->builder_->FunctionAt(index);
-        function->External(1);
-        function->SetName(indices->name_, indices->name_length_);
-        if (sig->return_count() > 0) {
-          function->ReturnType(sig->GetReturn());
-        }
-        for (size_t i = 0; i < sig->parameter_count(); i++) {
-          function->AddParam(sig->GetParam(i));
-        }
         return index;
       }
     }
   };
 
-  void VisitAssignment(Assignment* expr) {
-    bool in_init = false;
-    if (!in_function_) {
-      BinaryOperation* binop = expr->value()->AsBinaryOperation();
-      if (binop != nullptr) {
+  void EmitAssignmentLhs(Expression* target, MachineType* mtype) {
+    // Match the left hand side of the assignment.
+    VariableProxy* target_var = target->AsVariableProxy();
+    if (target_var != nullptr) {
+      // Left hand side is a local or a global variable, no code on LHS.
+      return;
+    }
+
+    Property* target_prop = target->AsProperty();
+    if (target_prop != nullptr) {
+      // Left hand side is a property access, i.e. the asm.js heap.
+      VisitPropertyAndEmitIndex(target_prop, mtype);
+      return;
+    }
+
+    if (target_var == nullptr && target_prop == nullptr) {
+      UNREACHABLE();  // invalid assignment.
+    }
+  }
+
+  void EmitAssignmentRhs(Expression* target, Expression* value, bool* is_nop) {
+    BinaryOperation* binop = value->AsBinaryOperation();
+    if (binop != nullptr) {
+      if (scope_ == kInitScope) {
+        // Handle foreign variables in the initialization scope.
         Property* prop = binop->left()->AsProperty();
-        DCHECK_NOT_NULL(prop);
-        LoadInitFunction();
-        is_set_op_ = true;
-        RECURSE(Visit(expr->target()));
-        DCHECK(!is_set_op_);
         if (binop->op() == Token::MUL) {
           DCHECK(binop->right()->IsLiteral());
           DCHECK_EQ(1.0, binop->right()->AsLiteral()->raw_value()->AsNumber());
           DCHECK(binop->right()->AsLiteral()->raw_value()->ContainsDot());
-          VisitForeignVariable(true, prop);
+          DCHECK(target->IsVariableProxy());
+          VisitForeignVariable(true, target->AsVariableProxy()->var(), prop);
+          *is_nop = true;
+          return;
         } else if (binop->op() == Token::BIT_OR) {
           DCHECK(binop->right()->IsLiteral());
           DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber());
           DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot());
-          VisitForeignVariable(false, prop);
+          DCHECK(target->IsVariableProxy());
+          VisitForeignVariable(false, target->AsVariableProxy()->var(), prop);
+          *is_nop = true;
+          return;
         } else {
           UNREACHABLE();
         }
-        UnLoadInitFunction();
-        return;
       }
+      if (MatchBinaryOperation(binop) == kAsIs) {
+        VariableProxy* target_var = target->AsVariableProxy();
+        VariableProxy* effective_value_var = GetLeft(binop)->AsVariableProxy();
+        if (target_var != nullptr && effective_value_var != nullptr &&
+            target_var->var() == effective_value_var->var()) {
+          *is_nop = true;
+          return;
+        }
+      }
+    }
+    RECURSE(Visit(value));
+  }
+
+  void EmitAssignment(Assignment* expr, MachineType type) {
+    // Match the left hand side of the assignment.
+    VariableProxy* target_var = expr->target()->AsVariableProxy();
+    if (target_var != nullptr) {
+      // Left hand side is a local or a global variable.
+      Variable* var = target_var->var();
+      LocalType var_type = TypeOf(expr);
+      DCHECK_NE(kAstStmt, var_type);
+      if (var->IsContextSlot()) {
+        current_function_builder_->EmitWithVarInt(
+            kExprStoreGlobal, LookupOrInsertGlobal(var, var_type));
+      } else {
+        current_function_builder_->EmitSetLocal(
+            LookupOrInsertLocal(var, var_type));
+      }
+    }
+
+    Property* target_prop = expr->target()->AsProperty();
+    if (target_prop != nullptr) {
+      // Left hand side is a property access, i.e. the asm.js heap.
+      if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() &&
+          bounds_->get(expr->target()->AsProperty()->obj())
+              .lower->Is(cache_.kFloat32Array)) {
+        current_function_builder_->Emit(kExprF32ConvertF64);
+      }
+      WasmOpcode opcode;
+      if (type == MachineType::Int8()) {
+        opcode = kExprI32AsmjsStoreMem8;
+      } else if (type == MachineType::Uint8()) {
+        opcode = kExprI32AsmjsStoreMem8;
+      } else if (type == MachineType::Int16()) {
+        opcode = kExprI32AsmjsStoreMem16;
+      } else if (type == MachineType::Uint16()) {
+        opcode = kExprI32AsmjsStoreMem16;
+      } else if (type == MachineType::Int32()) {
+        opcode = kExprI32AsmjsStoreMem;
+      } else if (type == MachineType::Uint32()) {
+        opcode = kExprI32AsmjsStoreMem;
+      } else if (type == MachineType::Float32()) {
+        opcode = kExprF32AsmjsStoreMem;
+      } else if (type == MachineType::Float64()) {
+        opcode = kExprF64AsmjsStoreMem;
+      } else {
+        UNREACHABLE();
+      }
+      current_function_builder_->Emit(opcode);
+    }
+
+    if (target_var == nullptr && target_prop == nullptr) {
+      UNREACHABLE();  // invalid assignment.
+    }
+  }
+
+  void VisitAssignment(Assignment* expr) override {
+    bool as_init = false;
+    if (scope_ == kModuleScope) {
       Property* prop = expr->value()->AsProperty();
       if (prop != nullptr) {
         VariableProxy* vp = prop->obj()->AsVariableProxy();
         if (vp != nullptr && vp->var()->IsParameter() &&
             vp->var()->index() == 1) {
           VariableProxy* target = expr->target()->AsVariableProxy();
-          if (target->bounds().lower->Is(Type::Function())) {
+          if (bounds_->get(target).lower->Is(Type::Function())) {
             const AstRawString* name =
                 prop->key()->AsLiteral()->AsRawPropertyName();
-            imported_function_table_.AddImport(target->var(), name->raw_data(),
-                                               name->length());
+            imported_function_table_.AddImport(
+                target->var(), reinterpret_cast<const char*>(name->raw_data()),
+                name->length());
           }
         }
         // Property values in module scope don't emit code, so return.
@@ -669,7 +861,7 @@
       }
       ArrayLiteral* funcs = expr->value()->AsArrayLiteral();
       if (funcs != nullptr &&
-          funcs->bounds().lower->AsArray()->Element()->IsFunction()) {
+          bounds_->get(funcs).lower->AsArray()->Element()->IsFunction()) {
         VariableProxy* target = expr->target()->AsVariableProxy();
         DCHECK_NOT_NULL(target);
         AddFunctionTable(target, funcs);
@@ -680,128 +872,74 @@
         // No init code to emit for CallNew nodes.
         return;
       }
-      in_init = true;
-      LoadInitFunction();
+      as_init = true;
     }
-    BinaryOperation* value_op = expr->value()->AsBinaryOperation();
-    if (value_op != nullptr && MatchBinaryOperation(value_op) == kAsIs) {
-      VariableProxy* target_var = expr->target()->AsVariableProxy();
-      VariableProxy* effective_value_var = GetLeft(value_op)->AsVariableProxy();
-      if (target_var != nullptr && effective_value_var != nullptr &&
-          target_var->var() == effective_value_var->var()) {
-        block_size_--;
-        return;
-      }
+
+    if (as_init) LoadInitFunction();
+    MachineType mtype;
+    bool is_nop = false;
+    EmitAssignmentLhs(expr->target(), &mtype);
+    EmitAssignmentRhs(expr->target(), expr->value(), &is_nop);
+    if (!is_nop) {
+      EmitAssignment(expr, mtype);
     }
-    is_set_op_ = true;
-    RECURSE(Visit(expr->target()));
-    DCHECK(!is_set_op_);
-    // Assignment to heapf32 from float64 converts.
-    if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() &&
-        expr->target()->AsProperty()->obj()->bounds().lower->Is(
-            cache_.kFloat32Array)) {
-      current_function_builder_->Emit(kExprF32ConvertF64);
-    }
-    RECURSE(Visit(expr->value()));
-    if (in_init) {
-      UnLoadInitFunction();
-    }
+    if (as_init) UnLoadInitFunction();
   }
 
-  void VisitYield(Yield* expr) { UNREACHABLE(); }
+  void VisitYield(Yield* expr) override { UNREACHABLE(); }
 
-  void VisitThrow(Throw* expr) { UNREACHABLE(); }
+  void VisitThrow(Throw* expr) override { UNREACHABLE(); }
 
-  void VisitForeignVariable(bool is_float, Property* expr) {
+  void VisitForeignVariable(bool is_float, Variable* var, Property* expr) {
     DCHECK(expr->obj()->AsVariableProxy());
     DCHECK(VariableLocation::PARAMETER ==
            expr->obj()->AsVariableProxy()->var()->location());
     DCHECK_EQ(1, expr->obj()->AsVariableProxy()->var()->index());
     Literal* key_literal = expr->key()->AsLiteral();
     DCHECK_NOT_NULL(key_literal);
-    if (!key_literal->value().is_null() && !foreign_.is_null() &&
-        foreign_->IsObject()) {
+    if (!key_literal->value().is_null()) {
       Handle<Name> name =
           i::Object::ToName(isolate_, key_literal->value()).ToHandleChecked();
-      MaybeHandle<Object> maybe_value = i::Object::GetProperty(foreign_, name);
-      if (!maybe_value.is_null()) {
-        Handle<Object> value = maybe_value.ToHandleChecked();
-        if (is_float) {
-          MaybeHandle<Object> maybe_nvalue = i::Object::ToNumber(value);
-          if (!maybe_nvalue.is_null()) {
-            Handle<Object> nvalue = maybe_nvalue.ToHandleChecked();
-            if (nvalue->IsNumber()) {
-              double val = nvalue->Number();
-              byte code[] = {WASM_F64(val)};
-              current_function_builder_->EmitCode(code, sizeof(code));
-              return;
-            }
-          }
-        } else {
-          MaybeHandle<Object> maybe_nvalue =
-              i::Object::ToInt32(isolate_, value);
-          if (!maybe_nvalue.is_null()) {
-            Handle<Object> nvalue = maybe_nvalue.ToHandleChecked();
-            if (nvalue->IsNumber()) {
-              int32_t val = static_cast<int32_t>(nvalue->Number());
-              // TODO(bradnelson): variable size
-              byte code[] = {WASM_I32V(val)};
-              current_function_builder_->EmitCode(code, sizeof(code));
-              return;
-            }
-          }
-        }
-      }
-    }
-    if (is_float) {
-      byte code[] = {WASM_F64(std::numeric_limits<double>::quiet_NaN())};
-      current_function_builder_->EmitCode(code, sizeof(code));
-    } else {
-      byte code[] = {WASM_I32V_1(0)};
-      current_function_builder_->EmitCode(code, sizeof(code));
+      LocalType type = is_float ? kAstF64 : kAstI32;
+      foreign_variables_.push_back({name, var, type});
     }
   }
 
-  void VisitProperty(Property* expr) {
+  void VisitPropertyAndEmitIndex(Property* expr, MachineType* mtype) {
     Expression* obj = expr->obj();
-    DCHECK_EQ(obj->bounds().lower, obj->bounds().upper);
-    Type* type = obj->bounds().lower;
-    MachineType mtype;
+    DCHECK_EQ(bounds_->get(obj).lower, bounds_->get(obj).upper);
+    Type* type = bounds_->get(obj).lower;
     int size;
     if (type->Is(cache_.kUint8Array)) {
-      mtype = MachineType::Uint8();
+      *mtype = MachineType::Uint8();
       size = 1;
     } else if (type->Is(cache_.kInt8Array)) {
-      mtype = MachineType::Int8();
+      *mtype = MachineType::Int8();
       size = 1;
     } else if (type->Is(cache_.kUint16Array)) {
-      mtype = MachineType::Uint16();
+      *mtype = MachineType::Uint16();
       size = 2;
     } else if (type->Is(cache_.kInt16Array)) {
-      mtype = MachineType::Int16();
+      *mtype = MachineType::Int16();
       size = 2;
     } else if (type->Is(cache_.kUint32Array)) {
-      mtype = MachineType::Uint32();
+      *mtype = MachineType::Uint32();
       size = 4;
     } else if (type->Is(cache_.kInt32Array)) {
-      mtype = MachineType::Int32();
+      *mtype = MachineType::Int32();
       size = 4;
     } else if (type->Is(cache_.kUint32Array)) {
-      mtype = MachineType::Uint32();
+      *mtype = MachineType::Uint32();
       size = 4;
     } else if (type->Is(cache_.kFloat32Array)) {
-      mtype = MachineType::Float32();
+      *mtype = MachineType::Float32();
       size = 4;
     } else if (type->Is(cache_.kFloat64Array)) {
-      mtype = MachineType::Float64();
+      *mtype = MachineType::Float64();
       size = 8;
     } else {
       UNREACHABLE();
     }
-    // TODO(titzer): use special asm-compatibility opcodes?
-    current_function_builder_->EmitWithU8U8(
-        WasmOpcodes::LoadStoreOpcodeOf(mtype, is_set_op_), 0, 0);
-    is_set_op_ = false;
     if (size == 1) {
       // Allow more general expression in byte arrays than the spec
       // strictly permits.
@@ -809,87 +947,123 @@
       // places that strictly should be HEAP8[HEAP32[..]>>0].
       RECURSE(Visit(expr->key()));
       return;
-    } else {
-      Literal* value = expr->key()->AsLiteral();
-      if (value) {
-        DCHECK(value->raw_value()->IsNumber());
-        DCHECK_EQ(kAstI32, TypeOf(value));
-        int val = static_cast<int>(value->raw_value()->AsNumber());
-        // TODO(bradnelson): variable size
-        byte code[] = {WASM_I32V(val * size)};
-        current_function_builder_->EmitCode(code, sizeof(code));
-        return;
-      }
-      BinaryOperation* binop = expr->key()->AsBinaryOperation();
-      if (binop) {
-        DCHECK_EQ(Token::SAR, binop->op());
-        DCHECK(binop->right()->AsLiteral()->raw_value()->IsNumber());
-        DCHECK(kAstI32 == TypeOf(binop->right()->AsLiteral()));
-        DCHECK_EQ(size,
-                  1 << static_cast<int>(
-                      binop->right()->AsLiteral()->raw_value()->AsNumber()));
-        // Mask bottom bits to match asm.js behavior.
-        current_function_builder_->Emit(kExprI32And);
-        byte code[] = {WASM_I8(~(size - 1))};
-        current_function_builder_->EmitCode(code, sizeof(code));
-        RECURSE(Visit(binop->left()));
-        return;
-      }
+    }
+
+    Literal* value = expr->key()->AsLiteral();
+    if (value) {
+      DCHECK(value->raw_value()->IsNumber());
+      DCHECK_EQ(kAstI32, TypeOf(value));
+      int32_t val = static_cast<int32_t>(value->raw_value()->AsNumber());
+      // TODO(titzer): handle overflow here.
+      current_function_builder_->EmitI32Const(val * size);
+      return;
+    }
+    BinaryOperation* binop = expr->key()->AsBinaryOperation();
+    if (binop) {
+      DCHECK_EQ(Token::SAR, binop->op());
+      DCHECK(binop->right()->AsLiteral()->raw_value()->IsNumber());
+      DCHECK(kAstI32 == TypeOf(binop->right()->AsLiteral()));
+      DCHECK_EQ(size,
+                1 << static_cast<int>(
+                    binop->right()->AsLiteral()->raw_value()->AsNumber()));
+      // Mask bottom bits to match asm.js behavior.
+      byte mask = static_cast<byte>(~(size - 1));
+      RECURSE(Visit(binop->left()));
+      current_function_builder_->EmitWithU8(kExprI8Const, mask);
+      current_function_builder_->Emit(kExprI32And);
+      return;
     }
     UNREACHABLE();
   }
 
+  void VisitProperty(Property* expr) override {
+    MachineType type;
+    VisitPropertyAndEmitIndex(expr, &type);
+    WasmOpcode opcode;
+    if (type == MachineType::Int8()) {
+      opcode = kExprI32AsmjsLoadMem8S;
+    } else if (type == MachineType::Uint8()) {
+      opcode = kExprI32AsmjsLoadMem8U;
+    } else if (type == MachineType::Int16()) {
+      opcode = kExprI32AsmjsLoadMem16S;
+    } else if (type == MachineType::Uint16()) {
+      opcode = kExprI32AsmjsLoadMem16U;
+    } else if (type == MachineType::Int32()) {
+      opcode = kExprI32AsmjsLoadMem;
+    } else if (type == MachineType::Uint32()) {
+      opcode = kExprI32AsmjsLoadMem;
+    } else if (type == MachineType::Float32()) {
+      opcode = kExprF32AsmjsLoadMem;
+    } else if (type == MachineType::Float64()) {
+      opcode = kExprF64AsmjsLoadMem;
+    } else {
+      UNREACHABLE();
+    }
+
+    current_function_builder_->Emit(opcode);
+  }
+
   bool VisitStdlibFunction(Call* call, VariableProxy* expr) {
     Variable* var = expr->var();
     AsmTyper::StandardMember standard_object =
         typer_->VariableAsStandardMember(var);
     ZoneList<Expression*>* args = call->arguments();
     LocalType call_type = TypeOf(call);
+
     switch (standard_object) {
       case AsmTyper::kNone: {
         return false;
       }
       case AsmTyper::kMathAcos: {
+        VisitCallArgs(call);
         DCHECK_EQ(kAstF64, call_type);
         current_function_builder_->Emit(kExprF64Acos);
         break;
       }
       case AsmTyper::kMathAsin: {
+        VisitCallArgs(call);
         DCHECK_EQ(kAstF64, call_type);
         current_function_builder_->Emit(kExprF64Asin);
         break;
       }
       case AsmTyper::kMathAtan: {
+        VisitCallArgs(call);
         DCHECK_EQ(kAstF64, call_type);
         current_function_builder_->Emit(kExprF64Atan);
         break;
       }
       case AsmTyper::kMathCos: {
+        VisitCallArgs(call);
         DCHECK_EQ(kAstF64, call_type);
         current_function_builder_->Emit(kExprF64Cos);
         break;
       }
       case AsmTyper::kMathSin: {
+        VisitCallArgs(call);
         DCHECK_EQ(kAstF64, call_type);
         current_function_builder_->Emit(kExprF64Sin);
         break;
       }
       case AsmTyper::kMathTan: {
+        VisitCallArgs(call);
         DCHECK_EQ(kAstF64, call_type);
         current_function_builder_->Emit(kExprF64Tan);
         break;
       }
       case AsmTyper::kMathExp: {
+        VisitCallArgs(call);
         DCHECK_EQ(kAstF64, call_type);
         current_function_builder_->Emit(kExprF64Exp);
         break;
       }
       case AsmTyper::kMathLog: {
+        VisitCallArgs(call);
         DCHECK_EQ(kAstF64, call_type);
         current_function_builder_->Emit(kExprF64Log);
         break;
       }
       case AsmTyper::kMathCeil: {
+        VisitCallArgs(call);
         if (call_type == kAstF32) {
           current_function_builder_->Emit(kExprF32Ceil);
         } else if (call_type == kAstF64) {
@@ -900,6 +1074,7 @@
         break;
       }
       case AsmTyper::kMathFloor: {
+        VisitCallArgs(call);
         if (call_type == kAstF32) {
           current_function_builder_->Emit(kExprF32Floor);
         } else if (call_type == kAstF64) {
@@ -910,6 +1085,7 @@
         break;
       }
       case AsmTyper::kMathSqrt: {
+        VisitCallArgs(call);
         if (call_type == kAstF32) {
           current_function_builder_->Emit(kExprF32Sqrt);
         } else if (call_type == kAstF64) {
@@ -920,19 +1096,33 @@
         break;
       }
       case AsmTyper::kMathAbs: {
-        // TODO(bradnelson): Should this be cast to float?
         if (call_type == kAstI32) {
-          current_function_builder_->Emit(kExprIfElse);
-          current_function_builder_->Emit(kExprI32LtS);
-          Visit(args->at(0));
+          uint32_t tmp = current_function_builder_->AddLocal(kAstI32);
+
+          // if set_local(tmp, x) < 0
+          Visit(call->arguments()->at(0));
+          current_function_builder_->EmitSetLocal(tmp);
           byte code[] = {WASM_I8(0)};
           current_function_builder_->EmitCode(code, sizeof(code));
-          current_function_builder_->Emit(kExprI32Sub);
+          current_function_builder_->Emit(kExprI32LtS);
+          current_function_builder_->Emit(kExprIf);
+
+          // then (0 - tmp)
           current_function_builder_->EmitCode(code, sizeof(code));
-          Visit(args->at(0));
+          current_function_builder_->EmitGetLocal(tmp);
+          current_function_builder_->Emit(kExprI32Sub);
+
+          // else tmp
+          current_function_builder_->Emit(kExprElse);
+          current_function_builder_->EmitGetLocal(tmp);
+          // end
+          current_function_builder_->Emit(kExprEnd);
+
         } else if (call_type == kAstF32) {
+          VisitCallArgs(call);
           current_function_builder_->Emit(kExprF32Abs);
         } else if (call_type == kAstF64) {
+          VisitCallArgs(call);
           current_function_builder_->Emit(kExprF64Abs);
         } else {
           UNREACHABLE();
@@ -942,13 +1132,32 @@
       case AsmTyper::kMathMin: {
         // TODO(bradnelson): Change wasm to match Math.min in asm.js mode.
         if (call_type == kAstI32) {
-          current_function_builder_->Emit(kExprIfElse);
+          uint32_t tmp_x = current_function_builder_->AddLocal(kAstI32);
+          uint32_t tmp_y = current_function_builder_->AddLocal(kAstI32);
+
+          // if set_local(tmp_x, x) < set_local(tmp_y, y)
+          Visit(call->arguments()->at(0));
+          current_function_builder_->EmitSetLocal(tmp_x);
+
+          Visit(call->arguments()->at(1));
+          current_function_builder_->EmitSetLocal(tmp_y);
+
           current_function_builder_->Emit(kExprI32LeS);
-          Visit(args->at(0));
-          Visit(args->at(1));
+          current_function_builder_->Emit(kExprIf);
+
+          // then tmp_x
+          current_function_builder_->EmitGetLocal(tmp_x);
+
+          // else tmp_y
+          current_function_builder_->Emit(kExprElse);
+          current_function_builder_->EmitGetLocal(tmp_y);
+          current_function_builder_->Emit(kExprEnd);
+
         } else if (call_type == kAstF32) {
+          VisitCallArgs(call);
           current_function_builder_->Emit(kExprF32Min);
         } else if (call_type == kAstF64) {
+          VisitCallArgs(call);
           current_function_builder_->Emit(kExprF64Min);
         } else {
           UNREACHABLE();
@@ -958,13 +1167,33 @@
       case AsmTyper::kMathMax: {
         // TODO(bradnelson): Change wasm to match Math.max in asm.js mode.
         if (call_type == kAstI32) {
-          current_function_builder_->Emit(kExprIfElse);
-          current_function_builder_->Emit(kExprI32GtS);
-          Visit(args->at(0));
-          Visit(args->at(1));
+          uint32_t tmp_x = current_function_builder_->AddLocal(kAstI32);
+          uint32_t tmp_y = current_function_builder_->AddLocal(kAstI32);
+
+          // if set_local(tmp_x, x) < set_local(tmp_y, y)
+          Visit(call->arguments()->at(0));
+
+          current_function_builder_->EmitSetLocal(tmp_x);
+
+          Visit(call->arguments()->at(1));
+          current_function_builder_->EmitSetLocal(tmp_y);
+
+          current_function_builder_->Emit(kExprI32LeS);
+          current_function_builder_->Emit(kExprIf);
+
+          // then tmp_y
+          current_function_builder_->EmitGetLocal(tmp_y);
+
+          // else tmp_x
+          current_function_builder_->Emit(kExprElse);
+          current_function_builder_->EmitGetLocal(tmp_x);
+          current_function_builder_->Emit(kExprEnd);
+
         } else if (call_type == kAstF32) {
+          VisitCallArgs(call);
           current_function_builder_->Emit(kExprF32Max);
         } else if (call_type == kAstF64) {
+          VisitCallArgs(call);
           current_function_builder_->Emit(kExprF64Max);
         } else {
           UNREACHABLE();
@@ -972,16 +1201,19 @@
         break;
       }
       case AsmTyper::kMathAtan2: {
+        VisitCallArgs(call);
         DCHECK_EQ(kAstF64, call_type);
         current_function_builder_->Emit(kExprF64Atan2);
         break;
       }
       case AsmTyper::kMathPow: {
+        VisitCallArgs(call);
         DCHECK_EQ(kAstF64, call_type);
         current_function_builder_->Emit(kExprF64Pow);
         break;
       }
       case AsmTyper::kMathImul: {
+        VisitCallArgs(call);
         current_function_builder_->Emit(kExprI32Mul);
         break;
       }
@@ -989,6 +1221,7 @@
         DCHECK(args->length() == 1);
         Literal* literal = args->at(0)->AsLiteral();
         if (literal != nullptr) {
+          // constant fold Math.fround(#const);
           if (literal->raw_value()->IsNumber()) {
             float val = static_cast<float>(literal->raw_value()->AsNumber());
             byte code[] = {WASM_F32(val)};
@@ -996,6 +1229,7 @@
             return true;
           }
         }
+        VisitCallArgs(call);
         switch (TypeIndexOf(args->at(0))) {
           case kInt32:
           case kFixnum:
@@ -1019,7 +1253,6 @@
         break;
       }
     }
-    VisitCallArgs(call);
     return true;
   }
 
@@ -1031,21 +1264,21 @@
     }
   }
 
-  void VisitCall(Call* expr) {
+  void VisitCall(Call* expr) override {
     Call::CallType call_type = expr->GetCallType(isolate_);
     switch (call_type) {
       case Call::OTHER_CALL: {
-        DCHECK(in_function_);
+        DCHECK_EQ(kFuncScope, scope_);
         VariableProxy* proxy = expr->expression()->AsVariableProxy();
         if (proxy != nullptr) {
           if (VisitStdlibFunction(expr, proxy)) {
             return;
           }
         }
-        uint16_t index;
+        uint32_t index;
         VariableProxy* vp = expr->expression()->AsVariableProxy();
         if (vp != nullptr &&
-            Type::Any()->Is(vp->bounds().lower->AsFunction()->Result())) {
+            Type::Any()->Is(bounds_->get(vp).lower->AsFunction()->Result())) {
           LocalType return_type = TypeOf(expr);
           ZoneList<Expression*>* args = expr->arguments();
           FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1,
@@ -1053,47 +1286,51 @@
           if (return_type != kAstStmt) {
             sig.AddReturn(return_type);
           }
-          for (int i = 0; i < args->length(); i++) {
+          for (int i = 0; i < args->length(); ++i) {
             sig.AddParam(TypeOf(args->at(i)));
           }
           index =
               imported_function_table_.GetFunctionIndex(vp->var(), sig.Build());
+          VisitCallArgs(expr);
+          current_function_builder_->Emit(kExprCallImport);
+          current_function_builder_->EmitVarInt(expr->arguments()->length());
+          current_function_builder_->EmitVarInt(index);
         } else {
           index = LookupOrInsertFunction(vp->var());
+          VisitCallArgs(expr);
+          current_function_builder_->Emit(kExprCallFunction);
+          current_function_builder_->EmitVarInt(expr->arguments()->length());
+          current_function_builder_->EmitVarInt(index);
         }
-        current_function_builder_->Emit(kExprCallFunction);
-        std::vector<uint8_t> index_arr = UnsignedLEB128From(index);
-        current_function_builder_->EmitCode(
-            &index_arr[0], static_cast<uint32_t>(index_arr.size()));
         break;
       }
       case Call::KEYED_PROPERTY_CALL: {
-        DCHECK(in_function_);
+        DCHECK_EQ(kFuncScope, scope_);
         Property* p = expr->expression()->AsProperty();
         DCHECK_NOT_NULL(p);
         VariableProxy* var = p->obj()->AsVariableProxy();
         DCHECK_NOT_NULL(var);
         FunctionTableIndices* indices = LookupFunctionTable(var->var());
-        current_function_builder_->EmitWithVarInt(kExprCallIndirect,
-                                                  indices->signature_index);
-        current_function_builder_->Emit(kExprI32Add);
-        // TODO(bradnelson): variable size
-        byte code[] = {WASM_I32V(indices->start_index)};
-        current_function_builder_->EmitCode(code, sizeof(code));
         RECURSE(Visit(p->key()));
+        current_function_builder_->EmitI32Const(indices->start_index);
+        current_function_builder_->Emit(kExprI32Add);
+        VisitCallArgs(expr);
+        current_function_builder_->Emit(kExprCallIndirect);
+        current_function_builder_->EmitVarInt(expr->arguments()->length());
+        current_function_builder_->EmitVarInt(indices->signature_index);
         break;
       }
       default:
         UNREACHABLE();
     }
-    VisitCallArgs(expr);
   }
 
-  void VisitCallNew(CallNew* expr) { UNREACHABLE(); }
+  void VisitCallNew(CallNew* expr) override { UNREACHABLE(); }
 
-  void VisitCallRuntime(CallRuntime* expr) { UNREACHABLE(); }
+  void VisitCallRuntime(CallRuntime* expr) override { UNREACHABLE(); }
 
-  void VisitUnaryOperation(UnaryOperation* expr) {
+  void VisitUnaryOperation(UnaryOperation* expr) override {
+    RECURSE(Visit(expr->expression()));
     switch (expr->op()) {
       case Token::NOT: {
         DCHECK_EQ(kAstI32, TypeOf(expr->expression()));
@@ -1103,10 +1340,9 @@
       default:
         UNREACHABLE();
     }
-    RECURSE(Visit(expr->expression()));
   }
 
-  void VisitCountOperation(CountOperation* expr) { UNREACHABLE(); }
+  void VisitCountOperation(CountOperation* expr) override { UNREACHABLE(); }
 
   bool MatchIntBinaryOperation(BinaryOperation* expr, Token::Value op,
                                int32_t val) {
@@ -1207,9 +1443,6 @@
 #ifdef Mul
 #undef Mul
 #endif
-#ifdef Div
-#undef Div
-#endif
 
 #define NON_SIGNED_BINOP(op)      \
   static WasmOpcode opcodes[] = { \
@@ -1246,9 +1479,10 @@
     }
   }
 
-  void VisitBinaryOperation(BinaryOperation* expr) {
+  void VisitBinaryOperation(BinaryOperation* expr) override {
     ConvertOperation convertOperation = MatchBinaryOperation(expr);
     if (convertOperation == kToDouble) {
+      RECURSE(Visit(expr->left()));
       TypeIndex type = TypeIndexOf(expr->left());
       if (type == kInt32 || type == kFixnum) {
         current_function_builder_->Emit(kExprF64SConvertI32);
@@ -1259,37 +1493,53 @@
       } else {
         UNREACHABLE();
       }
-      RECURSE(Visit(expr->left()));
     } else if (convertOperation == kToInt) {
+      RECURSE(Visit(GetLeft(expr)));
       TypeIndex type = TypeIndexOf(GetLeft(expr));
       if (type == kFloat32) {
-        current_function_builder_->Emit(kExprI32SConvertF32);
+        current_function_builder_->Emit(kExprI32AsmjsSConvertF32);
       } else if (type == kFloat64) {
-        current_function_builder_->Emit(kExprI32SConvertF64);
+        current_function_builder_->Emit(kExprI32AsmjsSConvertF64);
       } else {
         UNREACHABLE();
       }
-      RECURSE(Visit(GetLeft(expr)));
     } else if (convertOperation == kAsIs) {
       RECURSE(Visit(GetLeft(expr)));
     } else {
+      if (expr->op() == Token::COMMA) {
+        current_function_builder_->Emit(kExprBlock);
+      }
+
+      RECURSE(Visit(expr->left()));
+      RECURSE(Visit(expr->right()));
+
+      if (expr->op() == Token::COMMA) {
+        current_function_builder_->Emit(kExprEnd);
+      }
+
       switch (expr->op()) {
         BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true);
         BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true);
         BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true);
-        BINOP_CASE(Token::DIV, Div, SIGNED_BINOP, false);
         BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true);
         BINOP_CASE(Token::BIT_AND, And, NON_SIGNED_INT_BINOP, true);
         BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true);
         BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true);
         BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true);
         BINOP_CASE(Token::SHR, ShrU, NON_SIGNED_INT_BINOP, true);
+        case Token::DIV: {
+          static WasmOpcode opcodes[] = {kExprI32AsmjsDivS, kExprI32AsmjsDivU,
+                                         kExprF32Div, kExprF64Div};
+          int type = TypeIndexOf(expr->left(), expr->right(), false);
+          current_function_builder_->Emit(opcodes[type]);
+          break;
+        }
         case Token::MOD: {
           TypeIndex type = TypeIndexOf(expr->left(), expr->right(), false);
           if (type == kInt32) {
-            current_function_builder_->Emit(kExprI32RemS);
+            current_function_builder_->Emit(kExprI32AsmjsRemS);
           } else if (type == kUint32) {
-            current_function_builder_->Emit(kExprI32RemU);
+            current_function_builder_->Emit(kExprI32AsmjsRemU);
           } else if (type == kFloat64) {
             current_function_builder_->Emit(kExprF64Mod);
             return;
@@ -1299,31 +1549,17 @@
           break;
         }
         case Token::COMMA: {
-          current_function_builder_->EmitWithVarInt(kExprBlock, 2);
           break;
         }
         default:
           UNREACHABLE();
       }
-      RECURSE(Visit(expr->left()));
-      RECURSE(Visit(expr->right()));
     }
   }
 
-  void AddLeb128(uint32_t index, bool is_local) {
-    std::vector<uint8_t> index_vec = UnsignedLEB128From(index);
-    if (is_local) {
-      uint32_t pos_of_index[1] = {0};
-      current_function_builder_->EmitCode(
-          &index_vec[0], static_cast<uint32_t>(index_vec.size()), pos_of_index,
-          1);
-    } else {
-      current_function_builder_->EmitCode(
-          &index_vec[0], static_cast<uint32_t>(index_vec.size()));
-    }
-  }
-
-  void VisitCompareOperation(CompareOperation* expr) {
+  void VisitCompareOperation(CompareOperation* expr) override {
+    RECURSE(Visit(expr->left()));
+    RECURSE(Visit(expr->right()));
     switch (expr->op()) {
       BINOP_CASE(Token::EQ, Eq, NON_SIGNED_BINOP, false);
       BINOP_CASE(Token::LT, Lt, SIGNED_BINOP, false);
@@ -1333,8 +1569,6 @@
       default:
         UNREACHABLE();
     }
-    RECURSE(Visit(expr->left()));
-    RECURSE(Visit(expr->right()));
   }
 
 #undef BINOP_CASE
@@ -1369,8 +1603,8 @@
   }
 
   TypeIndex TypeIndexOf(Expression* expr) {
-    DCHECK_EQ(expr->bounds().lower, expr->bounds().upper);
-    Type* type = expr->bounds().lower;
+    DCHECK_EQ(bounds_->get(expr).lower, bounds_->get(expr).upper);
+    Type* type = bounds_->get(expr).lower;
     if (type->Is(cache_.kAsmFixnum)) {
       return kFixnum;
     } else if (type->Is(cache_.kAsmSigned)) {
@@ -1394,48 +1628,50 @@
 #undef SIGNED
 #undef NON_SIGNED
 
-  void VisitThisFunction(ThisFunction* expr) { UNREACHABLE(); }
+  void VisitThisFunction(ThisFunction* expr) override { UNREACHABLE(); }
 
-  void VisitDeclarations(ZoneList<Declaration*>* decls) {
+  void VisitDeclarations(ZoneList<Declaration*>* decls) override {
     for (int i = 0; i < decls->length(); ++i) {
       Declaration* decl = decls->at(i);
       RECURSE(Visit(decl));
     }
   }
 
-  void VisitClassLiteral(ClassLiteral* expr) { UNREACHABLE(); }
+  void VisitClassLiteral(ClassLiteral* expr) override { UNREACHABLE(); }
 
-  void VisitSpread(Spread* expr) { UNREACHABLE(); }
+  void VisitSpread(Spread* expr) override { UNREACHABLE(); }
 
-  void VisitSuperPropertyReference(SuperPropertyReference* expr) {
+  void VisitSuperPropertyReference(SuperPropertyReference* expr) override {
     UNREACHABLE();
   }
 
-  void VisitSuperCallReference(SuperCallReference* expr) { UNREACHABLE(); }
-
-  void VisitSloppyBlockFunctionStatement(SloppyBlockFunctionStatement* expr) {
+  void VisitSuperCallReference(SuperCallReference* expr) override {
     UNREACHABLE();
   }
 
-  void VisitDoExpression(DoExpression* expr) { UNREACHABLE(); }
+  void VisitSloppyBlockFunctionStatement(
+      SloppyBlockFunctionStatement* expr) override {
+    UNREACHABLE();
+  }
 
-  void VisitRewritableExpression(RewritableExpression* expr) { UNREACHABLE(); }
+  void VisitDoExpression(DoExpression* expr) override { UNREACHABLE(); }
+
+  void VisitRewritableExpression(RewritableExpression* expr) override {
+    UNREACHABLE();
+  }
 
   struct IndexContainer : public ZoneObject {
-    uint16_t index;
+    uint32_t index;
   };
 
-  uint16_t LookupOrInsertLocal(Variable* v, LocalType type) {
+  uint32_t LookupOrInsertLocal(Variable* v, LocalType type) {
     DCHECK_NOT_NULL(current_function_builder_);
     ZoneHashMap::Entry* entry =
         local_variables_.Lookup(v, ComputePointerHash(v));
     if (entry == nullptr) {
-      uint16_t index;
-      if (v->IsParameter()) {
-        index = current_function_builder_->AddParam(type);
-      } else {
-        index = current_function_builder_->AddLocal(type);
-      }
+      uint32_t index;
+      DCHECK(!v->IsParameter());
+      index = current_function_builder_->AddLocal(type);
       IndexContainer* container = new (zone()) IndexContainer();
       container->index = index;
       entry = local_variables_.LookupOrInsert(v, ComputePointerHash(v),
@@ -1445,11 +1681,24 @@
     return (reinterpret_cast<IndexContainer*>(entry->value))->index;
   }
 
-  uint16_t LookupOrInsertGlobal(Variable* v, LocalType type) {
+  void InsertParameter(Variable* v, LocalType type, uint32_t index) {
+    DCHECK(v->IsParameter());
+    DCHECK_NOT_NULL(current_function_builder_);
+    ZoneHashMap::Entry* entry =
+        local_variables_.Lookup(v, ComputePointerHash(v));
+    DCHECK_NULL(entry);
+    IndexContainer* container = new (zone()) IndexContainer();
+    container->index = index;
+    entry = local_variables_.LookupOrInsert(v, ComputePointerHash(v),
+                                            ZoneAllocationPolicy(zone()));
+    entry->value = container;
+  }
+
+  uint32_t LookupOrInsertGlobal(Variable* v, LocalType type) {
     ZoneHashMap::Entry* entry =
         global_variables_.Lookup(v, ComputePointerHash(v));
     if (entry == nullptr) {
-      uint16_t index =
+      uint32_t index =
           builder_->AddGlobal(WasmOpcodes::MachineTypeFor(type), 0);
       IndexContainer* container = new (zone()) IndexContainer();
       container->index = index;
@@ -1460,11 +1709,11 @@
     return (reinterpret_cast<IndexContainer*>(entry->value))->index;
   }
 
-  uint16_t LookupOrInsertFunction(Variable* v) {
+  uint32_t LookupOrInsertFunction(Variable* v) {
     DCHECK_NOT_NULL(builder_);
     ZoneHashMap::Entry* entry = functions_.Lookup(v, ComputePointerHash(v));
     if (entry == nullptr) {
-      uint16_t index = builder_->AddFunction();
+      uint32_t index = builder_->AddFunction();
       IndexContainer* container = new (zone()) IndexContainer();
       container->index = index;
       entry = functions_.LookupOrInsert(v, ComputePointerHash(v),
@@ -1475,8 +1724,8 @@
   }
 
   LocalType TypeOf(Expression* expr) {
-    DCHECK_EQ(expr->bounds().lower, expr->bounds().upper);
-    return TypeFrom(expr->bounds().lower);
+    DCHECK_EQ(bounds_->get(expr).lower, bounds_->get(expr).upper);
+    return TypeFrom(bounds_->get(expr).lower);
   }
 
   LocalType TypeFrom(Type* type) {
@@ -1496,23 +1745,22 @@
   ZoneHashMap local_variables_;
   ZoneHashMap functions_;
   ZoneHashMap global_variables_;
-  bool in_function_;
-  bool is_set_op_;
-  bool marking_exported;
+  AsmScope scope_;
   WasmModuleBuilder* builder_;
   WasmFunctionBuilder* current_function_builder_;
   FunctionLiteral* literal_;
   Isolate* isolate_;
   Zone* zone_;
-  Handle<Object> foreign_;
   AsmTyper* typer_;
   TypeCache const& cache_;
   ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_;
-  int block_size_;
-  uint16_t init_function_index_;
+  ZoneVector<ForeignVariable> foreign_variables_;
+  uint32_t init_function_index_;
+  uint32_t foreign_init_function_index_;
   uint32_t next_table_index_;
   ZoneHashMap function_tables_;
   ImportedFunctionTable imported_function_table_;
+  const AstTypeBounds* bounds_;
 
   DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
 
@@ -1521,21 +1769,18 @@
 };
 
 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone,
-                               FunctionLiteral* literal, Handle<Object> foreign,
-                               AsmTyper* typer)
-    : isolate_(isolate),
-      zone_(zone),
-      literal_(literal),
-      foreign_(foreign),
-      typer_(typer) {}
+                               FunctionLiteral* literal, AsmTyper* typer)
+    : isolate_(isolate), zone_(zone), literal_(literal), typer_(typer) {}
 
 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so
 // that zone in constructor may be thrown away once wasm module is written.
-WasmModuleIndex* AsmWasmBuilder::Run() {
-  AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_);
-  impl.Compile();
-  WasmModuleWriter* writer = impl.builder_->Build(zone_);
-  return writer->WriteTo(zone_);
+ZoneBuffer* AsmWasmBuilder::Run(i::Handle<i::FixedArray>* foreign_args) {
+  AsmWasmBuilderImpl impl(isolate_, zone_, literal_, typer_);
+  impl.Build();
+  *foreign_args = impl.GetForeignArgs();
+  ZoneBuffer* buffer = new (zone_) ZoneBuffer(zone_);
+  impl.builder_->WriteTo(*buffer);
+  return buffer;
 }
 }  // namespace wasm
 }  // namespace internal
diff --git a/src/wasm/asm-wasm-builder.h b/src/wasm/asm-wasm-builder.h
index 09645ee..b99c3ef 100644
--- a/src/wasm/asm-wasm-builder.h
+++ b/src/wasm/asm-wasm-builder.h
@@ -21,14 +21,13 @@
 class AsmWasmBuilder {
  public:
   explicit AsmWasmBuilder(Isolate* isolate, Zone* zone, FunctionLiteral* root,
-                          Handle<Object> foreign, AsmTyper* typer);
-  WasmModuleIndex* Run();
+                          AsmTyper* typer);
+  ZoneBuffer* Run(Handle<FixedArray>* foreign_args);
 
  private:
   Isolate* isolate_;
   Zone* zone_;
   FunctionLiteral* literal_;
-  Handle<Object> foreign_;
   AsmTyper* typer_;
 };
 }  // namespace wasm
diff --git a/src/wasm/ast-decoder.cc b/src/wasm/ast-decoder.cc
index e2f6a04..ef83c67 100644
--- a/src/wasm/ast-decoder.cc
+++ b/src/wasm/ast-decoder.cc
@@ -42,17 +42,6 @@
   WasmOpcode opcode() const { return static_cast<WasmOpcode>(*pc); }
 };
 
-// A production represents an incomplete decoded tree in the LR decoder.
-struct Production {
-  Tree* tree;  // the root of the syntax tree.
-  int index;   // the current index into the children of the tree.
-
-  WasmOpcode opcode() const { return static_cast<WasmOpcode>(*pc()); }
-  const byte* pc() const { return tree->pc; }
-  bool done() const { return index >= static_cast<int>(tree->count); }
-  Tree* last() const { return index > 0 ? tree->children[index - 1] : nullptr; }
-};
-
 // An SsaEnv environment carries the current local variable renaming
 // as well as the current effect and control dependency in the TF graph.
 // It maintains a control state that tracks whether the environment
@@ -72,19 +61,30 @@
     control = nullptr;
     effect = nullptr;
   }
+  void SetNotMerged() {
+    if (state == kMerged) state = kReached;
+  }
 };
 
-// An entry in the stack of blocks during decoding.
-struct Block {
-  SsaEnv* ssa_env;  // SSA renaming environment.
-  int stack_depth;  // production stack depth.
+// An entry on the value stack.
+struct Value {
+  const byte* pc;
+  TFNode* node;
+  LocalType type;
 };
 
-// An entry in the stack of ifs during decoding.
-struct IfEnv {
-  SsaEnv* false_env;
-  SsaEnv* merge_env;
-  SsaEnv** case_envs;
+// An entry on the control stack (i.e. if, block, loop).
+struct Control {
+  const byte* pc;
+  int stack_depth;    // stack height at the beginning of the construct.
+  SsaEnv* end_env;    // end environment for the construct.
+  SsaEnv* false_env;  // false environment (only for if).
+  TFNode* node;       // result node for the construct.
+  LocalType type;     // result type for the construct.
+  bool is_loop;       // true if this is the inner label of a loop.
+
+  bool is_if() { return *pc == kExprIf; }
+  bool is_block() { return *pc == kExprBlock; }
 };
 
 // Macros that build nodes only if there is a graph and the current SSA
@@ -157,40 +157,85 @@
     return false;
   }
 
-  inline bool Validate(const byte* pc, FunctionIndexOperand& operand) {
+  inline bool Complete(const byte* pc, CallFunctionOperand& operand) {
     ModuleEnv* m = module_;
     if (m && m->module && operand.index < m->module->functions.size()) {
       operand.sig = m->module->functions[operand.index].sig;
       return true;
     }
+    return false;
+  }
+
+  inline bool Validate(const byte* pc, CallFunctionOperand& operand) {
+    if (Complete(pc, operand)) {
+      uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count());
+      if (operand.arity != expected) {
+        error(pc, pc + 1,
+              "arity mismatch in direct function call (expected %u, got %u)",
+              expected, operand.arity);
+        return false;
+      }
+      return true;
+    }
     error(pc, pc + 1, "invalid function index");
     return false;
   }
 
-  inline bool Validate(const byte* pc, SignatureIndexOperand& operand) {
+  inline bool Complete(const byte* pc, CallIndirectOperand& operand) {
     ModuleEnv* m = module_;
     if (m && m->module && operand.index < m->module->signatures.size()) {
       operand.sig = m->module->signatures[operand.index];
       return true;
     }
+    return false;
+  }
+
+  inline bool Validate(const byte* pc, CallIndirectOperand& operand) {
+    if (Complete(pc, operand)) {
+      uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count());
+      if (operand.arity != expected) {
+        error(pc, pc + 1,
+              "arity mismatch in indirect function call (expected %u, got %u)",
+              expected, operand.arity);
+        return false;
+      }
+      return true;
+    }
     error(pc, pc + 1, "invalid signature index");
     return false;
   }
 
-  inline bool Validate(const byte* pc, ImportIndexOperand& operand) {
+  inline bool Complete(const byte* pc, CallImportOperand& operand) {
     ModuleEnv* m = module_;
     if (m && m->module && operand.index < m->module->import_table.size()) {
       operand.sig = m->module->import_table[operand.index].sig;
       return true;
     }
+    return false;
+  }
+
+  inline bool Validate(const byte* pc, CallImportOperand& operand) {
+    if (Complete(pc, operand)) {
+      uint32_t expected = static_cast<uint32_t>(operand.sig->parameter_count());
+      if (operand.arity != expected) {
+        error(pc, pc + 1, "arity mismatch in import call (expected %u, got %u)",
+              expected, operand.arity);
+        return false;
+      }
+      return true;
+    }
     error(pc, pc + 1, "invalid signature index");
     return false;
   }
 
   inline bool Validate(const byte* pc, BreakDepthOperand& operand,
-                       ZoneVector<Block>& blocks) {
-    if (operand.depth < blocks.size()) {
-      operand.target = &blocks[blocks.size() - operand.depth - 1];
+                       ZoneVector<Control>& control) {
+    if (operand.arity > 1) {
+      error(pc, pc + 1, "invalid arity for br or br_if");
+      return false;
+    }
+    if (operand.depth < control.size()) {
+      operand.target = &control[control.size() - operand.depth - 1];
       return true;
     }
     error(pc, pc + 1, "invalid break depth");
@@ -199,8 +244,12 @@
 
   bool Validate(const byte* pc, BranchTableOperand& operand,
                 size_t block_depth) {
+    if (operand.arity > 1) {
+      error(pc, pc + 1, "invalid arity for break");
+      return false;
+    }
     // Verify table.
-    for (uint32_t i = 0; i < operand.table_count + 1; i++) {
+    for (uint32_t i = 0; i < operand.table_count + 1; ++i) {
       uint32_t target = operand.read_entry(this, i);
       if (target >= block_depth) {
         error(operand.table + i * 2, "improper branch in br_table");
@@ -210,7 +259,7 @@
     return true;
   }
 
-  int OpcodeArity(const byte* pc) {
+  unsigned OpcodeArity(const byte* pc) {
 #define DECLARE_ARITY(name, ...)                          \
   static const LocalType kTypes_##name[] = {__VA_ARGS__}; \
   static const int kArity_##name =                        \
@@ -229,46 +278,49 @@
       case kExprLoadGlobal:
       case kExprNop:
       case kExprUnreachable:
+      case kExprEnd:
+      case kExprBlock:
+      case kExprLoop:
         return 0;
 
-      case kExprBr:
       case kExprStoreGlobal:
       case kExprSetLocal:
+      case kExprElse:
         return 1;
 
+      case kExprBr: {
+        BreakDepthOperand operand(this, pc);
+        return operand.arity;
+      }
+      case kExprBrIf: {
+        BreakDepthOperand operand(this, pc);
+        return 1 + operand.arity;
+      }
+      case kExprBrTable: {
+        BranchTableOperand operand(this, pc);
+        return 1 + operand.arity;
+      }
+
       case kExprIf:
-      case kExprBrIf:
-        return 2;
-      case kExprIfElse:
+        return 1;
       case kExprSelect:
         return 3;
 
-      case kExprBlock:
-      case kExprLoop: {
-        BlockCountOperand operand(this, pc);
-        return operand.count;
-      }
-
       case kExprCallFunction: {
-        FunctionIndexOperand operand(this, pc);
-        return static_cast<int>(
-            module_->GetFunctionSignature(operand.index)->parameter_count());
+        CallFunctionOperand operand(this, pc);
+        return operand.arity;
       }
       case kExprCallIndirect: {
-        SignatureIndexOperand operand(this, pc);
-        return 1 + static_cast<int>(
-                       module_->GetSignature(operand.index)->parameter_count());
+        CallIndirectOperand operand(this, pc);
+        return 1 + operand.arity;
       }
       case kExprCallImport: {
-        ImportIndexOperand operand(this, pc);
-        return static_cast<int>(
-            module_->GetImportSignature(operand.index)->parameter_count());
+        CallImportOperand operand(this, pc);
+        return operand.arity;
       }
       case kExprReturn: {
-        return static_cast<int>(sig_->return_count());
-      }
-      case kExprBrTable: {
-        return 1;
+        ReturnArityOperand operand(this, pc);
+        return operand.arity;
       }
 
 #define DECLARE_OPCODE_CASE(name, opcode, sig) \
@@ -280,15 +332,15 @@
         FOREACH_MISC_MEM_OPCODE(DECLARE_OPCODE_CASE)
         FOREACH_SIMPLE_OPCODE(DECLARE_OPCODE_CASE)
         FOREACH_ASMJS_COMPAT_OPCODE(DECLARE_OPCODE_CASE)
+        FOREACH_SIMD_OPCODE(DECLARE_OPCODE_CASE)
 #undef DECLARE_OPCODE_CASE
-      case kExprDeclLocals:
       default:
         UNREACHABLE();
         return 0;
     }
   }
 
-  int OpcodeLength(const byte* pc) {
+  unsigned OpcodeLength(const byte* pc) {
     switch (static_cast<WasmOpcode>(*pc)) {
 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
@@ -298,11 +350,6 @@
         MemoryAccessOperand operand(this, pc);
         return 1 + operand.length;
       }
-      case kExprBlock:
-      case kExprLoop: {
-        BlockCountOperand operand(this, pc);
-        return 1 + operand.length;
-      }
       case kExprBr:
       case kExprBrIf: {
         BreakDepthOperand operand(this, pc);
@@ -315,15 +362,15 @@
       }
 
       case kExprCallFunction: {
-        FunctionIndexOperand operand(this, pc);
+        CallFunctionOperand operand(this, pc);
         return 1 + operand.length;
       }
       case kExprCallIndirect: {
-        SignatureIndexOperand operand(this, pc);
+        CallIndirectOperand operand(this, pc);
         return 1 + operand.length;
       }
       case kExprCallImport: {
-        ImportIndexOperand operand(this, pc);
+        CallImportOperand operand(this, pc);
         return 1 + operand.length;
       }
 
@@ -350,6 +397,10 @@
         return 5;
       case kExprF64Const:
         return 9;
+      case kExprReturn: {
+        ReturnArityOperand operand(this, pc);
+        return 1 + operand.length;
+      }
 
       default:
         return 1;
@@ -357,66 +408,72 @@
   }
 };
 
-
 // A shift-reduce-parser strategy for decoding Wasm code that uses an explicit
 // shift-reduce strategy with multiple internal stacks.
 class SR_WasmDecoder : public WasmDecoder {
  public:
-  SR_WasmDecoder(Zone* zone, TFBuilder* builder, FunctionBody& body)
+  SR_WasmDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body)
       : WasmDecoder(body.module, body.sig, body.start, body.end),
         zone_(zone),
         builder_(builder),
         base_(body.base),
         local_type_vec_(zone),
-        trees_(zone),
         stack_(zone),
-        blocks_(zone),
-        ifs_(zone) {
+        control_(zone) {
     local_types_ = &local_type_vec_;
   }
 
-  TreeResult Decode() {
+  bool Decode() {
+    base::ElapsedTimer decode_timer;
+    if (FLAG_trace_wasm_decode_time) {
+      decode_timer.Start();
+    }
+    stack_.clear();
+    control_.clear();
+
     if (end_ < pc_) {
       error(pc_, "function body end < start");
-      return result_;
+      return false;
     }
 
     DecodeLocalDecls();
     InitSsaEnv();
     DecodeFunctionBody();
 
-    Tree* tree = nullptr;
-    if (ok()) {
-      if (ssa_env_->go()) {
-        if (stack_.size() > 0) {
-          error(stack_.back().pc(), end_, "fell off end of code");
-        }
-        AddImplicitReturnAtEnd();
-      }
-      if (trees_.size() == 0) {
-        if (sig_->return_count() > 0) {
-          error(start_, "no trees created");
-        }
-      } else {
-        tree = trees_[0];
-      }
+    if (failed()) return TraceFailed();
+
+    if (!control_.empty()) {
+      error(pc_, control_.back().pc, "unterminated control structure");
+      return TraceFailed();
     }
 
-    if (ok()) {
-      TRACE("wasm-decode ok\n");
+    if (ssa_env_->go()) {
+      TRACE("  @%-6d #xx:%-20s|", startrel(pc_), "ImplicitReturn");
+      DoReturn();
+      if (failed()) return TraceFailed();
+      TRACE("\n");
+    }
+
+    if (FLAG_trace_wasm_decode_time) {
+      double ms = decode_timer.Elapsed().InMillisecondsF();
+      PrintF("wasm-decode ok (%0.3f ms)\n\n", ms);
     } else {
-      TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_),
-            startrel(error_pc_), error_msg_.get());
+      TRACE("wasm-decode ok\n\n");
     }
 
-    return toResult(tree);
+    return true;
+  }
+
+  bool TraceFailed() {
+    TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_),
+          startrel(error_pc_), error_msg_.get());
+    return false;
   }
 
   bool DecodeLocalDecls(AstLocalDecls& decls) {
     DecodeLocalDecls();
     if (failed()) return false;
     decls.decls_encoded_size = pc_offset();
-    decls.total_local_count = 0;
     decls.local_types.reserve(local_type_vec_.size());
     for (size_t pos = 0; pos < local_type_vec_.size();) {
       uint32_t count = 0;
@@ -425,9 +482,9 @@
         pos++;
         count++;
       }
-      decls.total_local_count += count;
       decls.local_types.push_back(std::pair<LocalType, uint32_t>(type, count));
     }
+    decls.total_local_count = static_cast<uint32_t>(local_type_vec_.size());
     return true;
   }
 
@@ -448,15 +505,12 @@
   Zone* zone_;
   TFBuilder* builder_;
   const byte* base_;
-  TreeResult result_;
 
   SsaEnv* ssa_env_;
 
-  ZoneVector<LocalType> local_type_vec_;
-  ZoneVector<Tree*> trees_;
-  ZoneVector<Production> stack_;
-  ZoneVector<Block> blocks_;
-  ZoneVector<IfEnv> ifs_;
+  ZoneVector<LocalType> local_type_vec_;  // types of local variables.
+  ZoneVector<Value> stack_;               // stack of values.
+  ZoneVector<Control> control_;           // stack of blocks, loops, and ifs.
 
   inline bool build() { return builder_ && ssa_env_->go(); }
 
@@ -508,57 +562,10 @@
     }
   }
 
-  void Leaf(LocalType type, TFNode* node = nullptr) {
-    size_t size = sizeof(Tree);
-    Tree* tree = reinterpret_cast<Tree*>(zone_->New(size));
-    tree->type = type;
-    tree->count = 0;
-    tree->pc = pc_;
-    tree->node = node;
-    tree->children[0] = nullptr;
-    Reduce(tree);
-  }
-
-  void Shift(LocalType type, uint32_t count) {
-    size_t size =
-        sizeof(Tree) + (count == 0 ? 0 : ((count - 1) * sizeof(Tree*)));
-    Tree* tree = reinterpret_cast<Tree*>(zone_->New(size));
-    tree->type = type;
-    tree->count = count;
-    tree->pc = pc_;
-    tree->node = nullptr;
-    for (uint32_t i = 0; i < count; i++) tree->children[i] = nullptr;
-    if (count == 0) {
-      Production p = {tree, 0};
-      Reduce(&p);
-      Reduce(tree);
-    } else {
-      stack_.push_back({tree, 0});
-    }
-  }
-
-  void Reduce(Tree* tree) {
-    while (true) {
-      if (stack_.size() == 0) {
-        trees_.push_back(tree);
-        break;
-      }
-      Production* p = &stack_.back();
-      p->tree->children[p->index++] = tree;
-      Reduce(p);
-      if (p->done()) {
-        tree = p->tree;
-        stack_.pop_back();
-      } else {
-        break;
-      }
-    }
-  }
-
   char* indentation() {
     static const int kMaxIndent = 64;
     static char bytes[kMaxIndent + 1];
-    for (int i = 0; i < kMaxIndent; i++) bytes[i] = ' ';
+    for (int i = 0; i < kMaxIndent; ++i) bytes[i] = ' ';
     bytes[kMaxIndent] = 0;
     if (stack_.size() < kMaxIndent / 2) {
       bytes[stack_.size() * 2] = 0;
@@ -572,15 +579,14 @@
     // Initialize {local_type_vec} from signature.
     if (sig_) {
       local_type_vec_.reserve(sig_->parameter_count());
-      for (size_t i = 0; i < sig_->parameter_count(); i++) {
+      for (size_t i = 0; i < sig_->parameter_count(); ++i) {
         local_type_vec_.push_back(sig_->GetParam(i));
       }
     }
     // Decode local declarations, if any.
-    int length;
-    uint32_t entries = consume_u32v(&length, "local decls count");
+    uint32_t entries = consume_u32v("local decls count");
     while (entries-- > 0 && pc_ < limit_) {
-      uint32_t count = consume_u32v(&length, "local count");
+      uint32_t count = consume_u32v("local count");
       byte code = consume_u8("local type");
       LocalType type;
       switch (code) {
@@ -605,61 +611,57 @@
     total_locals_ = local_type_vec_.size();
   }
 
-  // Decodes the body of a function, producing reduced trees into {result}.
+  // Decodes the body of a function.
   void DecodeFunctionBody() {
-    TRACE("wasm-decode %p...%p (%d bytes) %s\n",
+    TRACE("wasm-decode %p...%p (module+%d, %d bytes) %s\n",
           reinterpret_cast<const void*>(start_),
-          reinterpret_cast<const void*>(limit_),
+          reinterpret_cast<const void*>(limit_), baserel(pc_),
           static_cast<int>(limit_ - start_), builder_ ? "graph building" : "");
 
     if (pc_ >= limit_) return;  // Nothing to do.
 
     while (true) {  // decoding loop.
-      int len = 1;
+      unsigned len = 1;
       WasmOpcode opcode = static_cast<WasmOpcode>(*pc_);
-      TRACE("wasm-decode module+%-6d %s func+%d: 0x%02x %s\n", baserel(pc_),
-            indentation(), startrel(pc_), opcode,
-            WasmOpcodes::OpcodeName(opcode));
+      TRACE("  @%-6d #%02x:%-20s|", startrel(pc_), opcode,
+            WasmOpcodes::ShortOpcodeName(opcode));
 
       FunctionSig* sig = WasmOpcodes::Signature(opcode);
       if (sig) {
-        // A simple expression with a fixed signature.
-        Shift(sig->GetReturn(), static_cast<uint32_t>(sig->parameter_count()));
-        pc_ += len;
-        if (pc_ >= limit_) {
-          // End of code reached or exceeded.
-          if (pc_ > limit_ && ok()) {
-            error("Beyond end of code");
+        // Fast case of a simple operator.
+        TFNode* node;
+        switch (sig->parameter_count()) {
+          case 1: {
+            Value val = Pop(0, sig->GetParam(0));
+            node = BUILD(Unop, opcode, val.node, position());
+            break;
           }
-          return;
+          case 2: {
+            Value rval = Pop(1, sig->GetParam(1));
+            Value lval = Pop(0, sig->GetParam(0));
+            node = BUILD(Binop, opcode, lval.node, rval.node, position());
+            break;
+          }
+          default:
+            UNREACHABLE();
+            node = nullptr;
+            break;
         }
-        continue;  // back to decoding loop.
-      }
-
-      switch (opcode) {
-        case kExprNop:
-          Leaf(kAstStmt);
-          break;
-        case kExprBlock: {
-          BlockCountOperand operand(this, pc_);
-          if (operand.count < 1) {
-            Leaf(kAstStmt);
-          } else {
-            Shift(kAstEnd, operand.count);
+        Push(GetReturnType(sig), node);
+      } else {
+        // Complex bytecode.
+        switch (opcode) {
+          case kExprNop:
+            Push(kAstStmt, nullptr);
+            break;
+          case kExprBlock: {
             // The break environment is the outer environment.
             SsaEnv* break_env = ssa_env_;
             PushBlock(break_env);
             SetEnv("block:start", Steal(break_env));
+            break;
           }
-          len = 1 + operand.length;
-          break;
-        }
-        case kExprLoop: {
-          BlockCountOperand operand(this, pc_);
-          if (operand.count < 1) {
-            Leaf(kAstStmt);
-          } else {
-            Shift(kAstEnd, operand.count);
+          case kExprLoop: {
             // The break environment is the outer environment.
             SsaEnv* break_env = ssa_env_;
             PushBlock(break_env);
@@ -667,268 +669,536 @@
             // The continue environment is the inner environment.
             PrepareForLoop(pc_, cont_env);
             SetEnv("loop:start", Split(cont_env));
-            if (ssa_env_->go()) ssa_env_->state = SsaEnv::kReached;
-            PushBlock(cont_env);
-            blocks_.back().stack_depth = -1;  // no production for inner block.
+            ssa_env_->SetNotMerged();
+            PushLoop(cont_env);
+            break;
           }
-          len = 1 + operand.length;
-          break;
-        }
-        case kExprIf:
-          Shift(kAstStmt, 2);
-          break;
-        case kExprIfElse:
-          Shift(kAstEnd, 3);  // Result type is typeof(x) in {c ? x : y}.
-          break;
-        case kExprSelect:
-          Shift(kAstStmt, 3);  // Result type is typeof(x) in {c ? x : y}.
-          break;
-        case kExprBr: {
-          BreakDepthOperand operand(this, pc_);
-          if (Validate(pc_, operand, blocks_)) {
-            Shift(kAstEnd, 1);
+          case kExprIf: {
+            // Condition on top of stack. Split environments for branches.
+            Value cond = Pop(0, kAstI32);
+            TFNode* if_true = nullptr;
+            TFNode* if_false = nullptr;
+            BUILD(Branch, cond.node, &if_true, &if_false);
+            SsaEnv* end_env = ssa_env_;
+            SsaEnv* false_env = Split(ssa_env_);
+            false_env->control = if_false;
+            SsaEnv* true_env = Steal(ssa_env_);
+            true_env->control = if_true;
+            PushIf(end_env, false_env);
+            SetEnv("if:true", true_env);
+            break;
           }
-          len = 1 + operand.length;
-          break;
-        }
-        case kExprBrIf: {
-          BreakDepthOperand operand(this, pc_);
-          if (Validate(pc_, operand, blocks_)) {
-            Shift(kAstStmt, 2);
+          case kExprElse: {
+            if (control_.empty()) {
+              error(pc_, "else does not match any if");
+              break;
+            }
+            Control* c = &control_.back();
+            if (!c->is_if()) {
+              error(pc_, c->pc, "else does not match an if");
+              break;
+            }
+            if (c->false_env == nullptr) {
+              error(pc_, c->pc, "else already present for if");
+              break;
+            }
+            Value val = PopUpTo(c->stack_depth);
+            MergeInto(c->end_env, &c->node, &c->type, val);
+            // Switch to environment for false branch.
+            SetEnv("if_else:false", c->false_env);
+            c->false_env = nullptr;  // record that an else is already seen
+            break;
           }
-          len = 1 + operand.length;
-          break;
-        }
-        case kExprBrTable: {
-          BranchTableOperand operand(this, pc_);
-          if (Validate(pc_, operand, blocks_.size())) {
-            Shift(kAstEnd, 1);
+          case kExprEnd: {
+            if (control_.empty()) {
+              error(pc_, "end does not match any if or block");
+              break;
+            }
+            const char* name = "block:end";
+            Control* c = &control_.back();
+            if (c->is_loop) {
+              // Loops always push control in pairs.
+              control_.pop_back();
+              c = &control_.back();
+              name = "loop:end";
+            }
+            Value val = PopUpTo(c->stack_depth);
+            if (c->is_if()) {
+              if (c->false_env != nullptr) {
+                // End the true branch of a one-armed if.
+                Goto(c->false_env, c->end_env);
+                val = {val.pc, nullptr, kAstStmt};
+                name = "if:merge";
+              } else {
+                // End the false branch of a two-armed if.
+                name = "if_else:merge";
+              }
+            }
+            if (ssa_env_->go()) {
+              MergeInto(c->end_env, &c->node, &c->type, val);
+            }
+            SetEnv(name, c->end_env);
+            stack_.resize(c->stack_depth);
+            Push(c->type, c->node);
+            control_.pop_back();
+            break;
           }
-          len = 1 + operand.length;
-          break;
-        }
-        case kExprReturn: {
-          int count = static_cast<int>(sig_->return_count());
-          if (count == 0) {
-            BUILD(Return, 0, builder_->Buffer(0));
-            ssa_env_->Kill();
-            Leaf(kAstEnd);
-          } else {
-            Shift(kAstEnd, count);
+          case kExprSelect: {
+            Value cond = Pop(2, kAstI32);
+            Value fval = Pop();
+            Value tval = Pop();
+            if (tval.type == kAstStmt || tval.type != fval.type) {
+              if (tval.type != kAstEnd && fval.type != kAstEnd) {
+                error(pc_, "type mismatch in select");
+                break;
+              }
+            }
+            if (build()) {
+              DCHECK(tval.type != kAstEnd);
+              DCHECK(fval.type != kAstEnd);
+              DCHECK(cond.type != kAstEnd);
+              TFNode* controls[2];
+              builder_->Branch(cond.node, &controls[0], &controls[1]);
+              TFNode* merge = builder_->Merge(2, controls);
+              TFNode* vals[2] = {tval.node, fval.node};
+              TFNode* phi = builder_->Phi(tval.type, 2, vals, merge);
+              Push(tval.type, phi);
+              ssa_env_->control = merge;
+            } else {
+              Push(tval.type, nullptr);
+            }
+            break;
           }
-          break;
-        }
-        case kExprUnreachable: {
-          BUILD0(Unreachable);
-          ssa_env_->Kill(SsaEnv::kControlEnd);
-          Leaf(kAstEnd, nullptr);
-          break;
-        }
-        case kExprI8Const: {
-          ImmI8Operand operand(this, pc_);
-          Leaf(kAstI32, BUILD(Int32Constant, operand.value));
-          len = 1 + operand.length;
-          break;
-        }
-        case kExprI32Const: {
-          ImmI32Operand operand(this, pc_);
-          Leaf(kAstI32, BUILD(Int32Constant, operand.value));
-          len = 1 + operand.length;
-          break;
-        }
-        case kExprI64Const: {
-          ImmI64Operand operand(this, pc_);
-          Leaf(kAstI64, BUILD(Int64Constant, operand.value));
-          len = 1 + operand.length;
-          break;
-        }
-        case kExprF32Const: {
-          ImmF32Operand operand(this, pc_);
-          Leaf(kAstF32, BUILD(Float32Constant, operand.value));
-          len = 1 + operand.length;
-          break;
-        }
-        case kExprF64Const: {
-          ImmF64Operand operand(this, pc_);
-          Leaf(kAstF64, BUILD(Float64Constant, operand.value));
-          len = 1 + operand.length;
-          break;
-        }
-        case kExprGetLocal: {
-          LocalIndexOperand operand(this, pc_);
-          if (Validate(pc_, operand)) {
-            TFNode* val = build() ? ssa_env_->locals[operand.index] : nullptr;
-            Leaf(operand.type, val);
+          case kExprBr: {
+            BreakDepthOperand operand(this, pc_);
+            Value val = {pc_, nullptr, kAstStmt};
+            if (operand.arity) val = Pop();
+            if (Validate(pc_, operand, control_)) {
+              BreakTo(operand.target, val);
+            }
+            len = 1 + operand.length;
+            Push(kAstEnd, nullptr);
+            break;
           }
-          len = 1 + operand.length;
-          break;
-        }
-        case kExprSetLocal: {
-          LocalIndexOperand operand(this, pc_);
-          if (Validate(pc_, operand)) {
-            Shift(operand.type, 1);
+          case kExprBrIf: {
+            BreakDepthOperand operand(this, pc_);
+            Value cond = Pop(operand.arity, kAstI32);
+            Value val = {pc_, nullptr, kAstStmt};
+            if (operand.arity == 1) val = Pop();
+            if (Validate(pc_, operand, control_)) {
+              SsaEnv* fenv = ssa_env_;
+              SsaEnv* tenv = Split(fenv);
+              fenv->SetNotMerged();
+              BUILD(Branch, cond.node, &tenv->control, &fenv->control);
+              ssa_env_ = tenv;
+              BreakTo(operand.target, val);
+              ssa_env_ = fenv;
+            }
+            len = 1 + operand.length;
+            Push(kAstStmt, nullptr);
+            break;
           }
-          len = 1 + operand.length;
-          break;
-        }
-        case kExprLoadGlobal: {
-          GlobalIndexOperand operand(this, pc_);
-          if (Validate(pc_, operand)) {
-            Leaf(operand.type, BUILD(LoadGlobal, operand.index));
+          case kExprBrTable: {
+            BranchTableOperand operand(this, pc_);
+            if (Validate(pc_, operand, control_.size())) {
+              Value key = Pop(operand.arity, kAstI32);
+              Value val = {pc_, nullptr, kAstStmt};
+              if (operand.arity == 1) val = Pop();
+              if (failed()) break;
+
+              SsaEnv* break_env = ssa_env_;
+              if (operand.table_count > 0) {
+                // Build branches to the various blocks based on the table.
+                TFNode* sw = BUILD(Switch, operand.table_count + 1, key.node);
+
+                SsaEnv* copy = Steal(break_env);
+                ssa_env_ = copy;
+                for (uint32_t i = 0; i < operand.table_count + 1; ++i) {
+                  uint16_t target = operand.read_entry(this, i);
+                  ssa_env_ = Split(copy);
+                  ssa_env_->control = (i == operand.table_count)
+                                          ? BUILD(IfDefault, sw)
+                                          : BUILD(IfValue, i, sw);
+                  int depth = target;
+                  Control* c = &control_[control_.size() - depth - 1];
+                  MergeInto(c->end_env, &c->node, &c->type, val);
+                }
+              } else {
+                // Only a default target. Do the equivalent of br.
+                uint16_t target = operand.read_entry(this, 0);
+                int depth = target;
+                Control* c = &control_[control_.size() - depth - 1];
+                MergeInto(c->end_env, &c->node, &c->type, val);
+              }
+              // br_table ends the control flow like br.
+              ssa_env_ = break_env;
+              Push(kAstStmt, nullptr);
+            }
+            len = 1 + operand.length;
+            break;
           }
-          len = 1 + operand.length;
-          break;
-        }
-        case kExprStoreGlobal: {
-          GlobalIndexOperand operand(this, pc_);
-          if (Validate(pc_, operand)) {
-            Shift(operand.type, 1);
+          case kExprReturn: {
+            ReturnArityOperand operand(this, pc_);
+            if (operand.arity != sig_->return_count()) {
+              error(pc_, pc_ + 1, "arity mismatch in return");
+            }
+            DoReturn();
+            len = 1 + operand.length;
+            break;
           }
-          len = 1 + operand.length;
-          break;
-        }
-        case kExprI32LoadMem8S:
-        case kExprI32LoadMem8U:
-        case kExprI32LoadMem16S:
-        case kExprI32LoadMem16U:
-        case kExprI32LoadMem:
-          len = DecodeLoadMem(pc_, kAstI32);
-          break;
-        case kExprI64LoadMem8S:
-        case kExprI64LoadMem8U:
-        case kExprI64LoadMem16S:
-        case kExprI64LoadMem16U:
-        case kExprI64LoadMem32S:
-        case kExprI64LoadMem32U:
-        case kExprI64LoadMem:
-          len = DecodeLoadMem(pc_, kAstI64);
-          break;
-        case kExprF32LoadMem:
-          len = DecodeLoadMem(pc_, kAstF32);
-          break;
-        case kExprF64LoadMem:
-          len = DecodeLoadMem(pc_, kAstF64);
-          break;
-        case kExprI32StoreMem8:
-        case kExprI32StoreMem16:
-        case kExprI32StoreMem:
-          len = DecodeStoreMem(pc_, kAstI32);
-          break;
-        case kExprI64StoreMem8:
-        case kExprI64StoreMem16:
-        case kExprI64StoreMem32:
-        case kExprI64StoreMem:
-          len = DecodeStoreMem(pc_, kAstI64);
-          break;
-        case kExprF32StoreMem:
-          len = DecodeStoreMem(pc_, kAstF32);
-          break;
-        case kExprF64StoreMem:
-          len = DecodeStoreMem(pc_, kAstF64);
-          break;
-        case kExprMemorySize:
-          Leaf(kAstI32, BUILD(MemSize, 0));
-          break;
-        case kExprGrowMemory:
-          Shift(kAstI32, 1);
-          break;
-        case kExprCallFunction: {
-          FunctionIndexOperand operand(this, pc_);
-          if (Validate(pc_, operand)) {
-            LocalType type = operand.sig->return_count() == 0
-                                 ? kAstStmt
-                                 : operand.sig->GetReturn();
-            Shift(type, static_cast<int>(operand.sig->parameter_count()));
+          case kExprUnreachable: {
+            Push(kAstEnd, BUILD(Unreachable, position()));
+            ssa_env_->Kill(SsaEnv::kControlEnd);
+            break;
           }
-          len = 1 + operand.length;
-          break;
-        }
-        case kExprCallIndirect: {
-          SignatureIndexOperand operand(this, pc_);
-          if (Validate(pc_, operand)) {
-            LocalType type = operand.sig->return_count() == 0
-                                 ? kAstStmt
-                                 : operand.sig->GetReturn();
-            Shift(type, static_cast<int>(1 + operand.sig->parameter_count()));
+          case kExprI8Const: {
+            ImmI8Operand operand(this, pc_);
+            Push(kAstI32, BUILD(Int32Constant, operand.value));
+            len = 1 + operand.length;
+            break;
           }
-          len = 1 + operand.length;
-          break;
-        }
-        case kExprCallImport: {
-          ImportIndexOperand operand(this, pc_);
-          if (Validate(pc_, operand)) {
-            LocalType type = operand.sig->return_count() == 0
-                                 ? kAstStmt
-                                 : operand.sig->GetReturn();
-            Shift(type, static_cast<int>(operand.sig->parameter_count()));
+          case kExprI32Const: {
+            ImmI32Operand operand(this, pc_);
+            Push(kAstI32, BUILD(Int32Constant, operand.value));
+            len = 1 + operand.length;
+            break;
           }
-          len = 1 + operand.length;
-          break;
+          case kExprI64Const: {
+            ImmI64Operand operand(this, pc_);
+            Push(kAstI64, BUILD(Int64Constant, operand.value));
+            len = 1 + operand.length;
+            break;
+          }
+          case kExprF32Const: {
+            ImmF32Operand operand(this, pc_);
+            Push(kAstF32, BUILD(Float32Constant, operand.value));
+            len = 1 + operand.length;
+            break;
+          }
+          case kExprF64Const: {
+            ImmF64Operand operand(this, pc_);
+            Push(kAstF64, BUILD(Float64Constant, operand.value));
+            len = 1 + operand.length;
+            break;
+          }
+          case kExprGetLocal: {
+            LocalIndexOperand operand(this, pc_);
+            if (Validate(pc_, operand)) {
+              if (build()) {
+                Push(operand.type, ssa_env_->locals[operand.index]);
+              } else {
+                Push(operand.type, nullptr);
+              }
+            }
+            len = 1 + operand.length;
+            break;
+          }
+          case kExprSetLocal: {
+            LocalIndexOperand operand(this, pc_);
+            if (Validate(pc_, operand)) {
+              Value val = Pop(0, local_type_vec_[operand.index]);
+              if (ssa_env_->locals) ssa_env_->locals[operand.index] = val.node;
+              Push(val.type, val.node);
+            }
+            len = 1 + operand.length;
+            break;
+          }
+          case kExprLoadGlobal: {
+            GlobalIndexOperand operand(this, pc_);
+            if (Validate(pc_, operand)) {
+              Push(operand.type, BUILD(LoadGlobal, operand.index));
+            }
+            len = 1 + operand.length;
+            break;
+          }
+          case kExprStoreGlobal: {
+            GlobalIndexOperand operand(this, pc_);
+            if (Validate(pc_, operand)) {
+              Value val = Pop(0, operand.type);
+              BUILD(StoreGlobal, operand.index, val.node);
+              Push(val.type, val.node);
+            }
+            len = 1 + operand.length;
+            break;
+          }
+          case kExprI32LoadMem8S:
+            len = DecodeLoadMem(kAstI32, MachineType::Int8());
+            break;
+          case kExprI32LoadMem8U:
+            len = DecodeLoadMem(kAstI32, MachineType::Uint8());
+            break;
+          case kExprI32LoadMem16S:
+            len = DecodeLoadMem(kAstI32, MachineType::Int16());
+            break;
+          case kExprI32LoadMem16U:
+            len = DecodeLoadMem(kAstI32, MachineType::Uint16());
+            break;
+          case kExprI32LoadMem:
+            len = DecodeLoadMem(kAstI32, MachineType::Int32());
+            break;
+
+          case kExprI64LoadMem8S:
+            len = DecodeLoadMem(kAstI64, MachineType::Int8());
+            break;
+          case kExprI64LoadMem8U:
+            len = DecodeLoadMem(kAstI64, MachineType::Uint8());
+            break;
+          case kExprI64LoadMem16S:
+            len = DecodeLoadMem(kAstI64, MachineType::Int16());
+            break;
+          case kExprI64LoadMem16U:
+            len = DecodeLoadMem(kAstI64, MachineType::Uint16());
+            break;
+          case kExprI64LoadMem32S:
+            len = DecodeLoadMem(kAstI64, MachineType::Int32());
+            break;
+          case kExprI64LoadMem32U:
+            len = DecodeLoadMem(kAstI64, MachineType::Uint32());
+            break;
+          case kExprI64LoadMem:
+            len = DecodeLoadMem(kAstI64, MachineType::Int64());
+            break;
+          case kExprF32LoadMem:
+            len = DecodeLoadMem(kAstF32, MachineType::Float32());
+            break;
+          case kExprF64LoadMem:
+            len = DecodeLoadMem(kAstF64, MachineType::Float64());
+            break;
+          case kExprI32StoreMem8:
+            len = DecodeStoreMem(kAstI32, MachineType::Int8());
+            break;
+          case kExprI32StoreMem16:
+            len = DecodeStoreMem(kAstI32, MachineType::Int16());
+            break;
+          case kExprI32StoreMem:
+            len = DecodeStoreMem(kAstI32, MachineType::Int32());
+            break;
+          case kExprI64StoreMem8:
+            len = DecodeStoreMem(kAstI64, MachineType::Int8());
+            break;
+          case kExprI64StoreMem16:
+            len = DecodeStoreMem(kAstI64, MachineType::Int16());
+            break;
+          case kExprI64StoreMem32:
+            len = DecodeStoreMem(kAstI64, MachineType::Int32());
+            break;
+          case kExprI64StoreMem:
+            len = DecodeStoreMem(kAstI64, MachineType::Int64());
+            break;
+          case kExprF32StoreMem:
+            len = DecodeStoreMem(kAstF32, MachineType::Float32());
+            break;
+          case kExprF64StoreMem:
+            len = DecodeStoreMem(kAstF64, MachineType::Float64());
+            break;
+
+          case kExprMemorySize:
+            Push(kAstI32, BUILD(MemSize, 0));
+            break;
+          case kExprGrowMemory: {
+            Value val = Pop(0, kAstI32);
+            USE(val);  // TODO(titzer): build node for grow memory
+            Push(kAstI32, BUILD(Int32Constant, 0));
+            break;
+          }
+          case kExprCallFunction: {
+            CallFunctionOperand operand(this, pc_);
+            if (Validate(pc_, operand)) {
+              TFNode** buffer = PopArgs(operand.sig);
+              TFNode* call =
+                  BUILD(CallDirect, operand.index, buffer, position());
+              Push(GetReturnType(operand.sig), call);
+            }
+            len = 1 + operand.length;
+            break;
+          }
+          case kExprCallIndirect: {
+            CallIndirectOperand operand(this, pc_);
+            if (Validate(pc_, operand)) {
+              TFNode** buffer = PopArgs(operand.sig);
+              Value index = Pop(0, kAstI32);
+              if (buffer) buffer[0] = index.node;
+              TFNode* call =
+                  BUILD(CallIndirect, operand.index, buffer, position());
+              Push(GetReturnType(operand.sig), call);
+            }
+            len = 1 + operand.length;
+            break;
+          }
+          case kExprCallImport: {
+            CallImportOperand operand(this, pc_);
+            if (Validate(pc_, operand)) {
+              TFNode** buffer = PopArgs(operand.sig);
+              TFNode* call =
+                  BUILD(CallImport, operand.index, buffer, position());
+              Push(GetReturnType(operand.sig), call);
+            }
+            len = 1 + operand.length;
+            break;
+          }
+          default:
+            error("Invalid opcode");
+            return;
         }
-        case kExprDeclLocals:
-        default:
-          error("Invalid opcode");
-          return;
+      }  // end complex bytecode
+
+#if DEBUG
+      if (FLAG_trace_wasm_decoder) {
+        for (size_t i = 0; i < stack_.size(); ++i) {
+          Value& val = stack_[i];
+          WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
+          PrintF(" %c@%d:%s", WasmOpcodes::ShortNameOf(val.type),
+                 static_cast<int>(val.pc - start_),
+                 WasmOpcodes::ShortOpcodeName(opcode));
+          switch (opcode) {
+            case kExprI32Const: {
+              ImmI32Operand operand(this, val.pc);
+              PrintF("[%d]", operand.value);
+              break;
+            }
+            case kExprGetLocal: {
+              LocalIndexOperand operand(this, val.pc);
+              PrintF("[%u]", operand.index);
+              break;
+            }
+            case kExprSetLocal: {
+              LocalIndexOperand operand(this, val.pc);
+              PrintF("[%u]", operand.index);
+              break;
+            }
+            default:
+              break;
+          }
+        }
+        PrintF("\n");
       }
+#endif
       pc_ += len;
       if (pc_ >= limit_) {
         // End of code reached or exceeded.
-        if (pc_ > limit_ && ok()) {
-          error("Beyond end of code");
-        }
+        if (pc_ > limit_ && ok()) error("Beyond end of code");
         return;
       }
+    }  // end decode loop
+  }    // end DecodeFunctionBody()
+
+  TFNode** PopArgs(FunctionSig* sig) {
+    if (build()) {
+      int count = static_cast<int>(sig->parameter_count());
+      TFNode** buffer = builder_->Buffer(count + 1);
+      buffer[0] = nullptr;  // reserved for code object or function index.
+      for (int i = count - 1; i >= 0; i--) {
+        buffer[i + 1] = Pop(i, sig->GetParam(i)).node;
+      }
+      return buffer;
+    } else {
+      int count = static_cast<int>(sig->parameter_count());
+      for (int i = count - 1; i >= 0; i--) {
+        Pop(i, sig->GetParam(i));
+      }
+      return nullptr;
     }
   }
 
-  void PushBlock(SsaEnv* ssa_env) {
-    blocks_.push_back({ssa_env, static_cast<int>(stack_.size() - 1)});
+  LocalType GetReturnType(FunctionSig* sig) {
+    return sig->return_count() == 0 ? kAstStmt : sig->GetReturn();
   }
 
-  int DecodeLoadMem(const byte* pc, LocalType type) {
-    MemoryAccessOperand operand(this, pc);
-    Shift(type, 1);
+  void PushBlock(SsaEnv* end_env) {
+    int stack_depth = static_cast<int>(stack_.size());
+    control_.push_back(
+        {pc_, stack_depth, end_env, nullptr, nullptr, kAstEnd, false});
+  }
+
+  void PushLoop(SsaEnv* end_env) {
+    int stack_depth = static_cast<int>(stack_.size());
+    control_.push_back(
+        {pc_, stack_depth, end_env, nullptr, nullptr, kAstEnd, true});
+  }
+
+  void PushIf(SsaEnv* end_env, SsaEnv* false_env) {
+    int stack_depth = static_cast<int>(stack_.size());
+    control_.push_back(
+        {pc_, stack_depth, end_env, false_env, nullptr, kAstStmt, false});
+  }
+
+  int DecodeLoadMem(LocalType type, MachineType mem_type) {
+    MemoryAccessOperand operand(this, pc_);
+    Value index = Pop(0, kAstI32);
+    TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset,
+                         operand.alignment, position());
+    Push(type, node);
     return 1 + operand.length;
   }
 
-  int DecodeStoreMem(const byte* pc, LocalType type) {
-    MemoryAccessOperand operand(this, pc);
-    Shift(type, 2);
+  int DecodeStoreMem(LocalType type, MachineType mem_type) {
+    MemoryAccessOperand operand(this, pc_);
+    Value val = Pop(1, type);
+    Value index = Pop(0, kAstI32);
+    BUILD(StoreMem, mem_type, index.node, operand.offset, operand.alignment,
+          val.node, position());
+    Push(type, val.node);
     return 1 + operand.length;
   }
 
-  void AddImplicitReturnAtEnd() {
-    int retcount = static_cast<int>(sig_->return_count());
-    if (retcount == 0) {
-      BUILD0(ReturnVoid);
-      return;
+  void DoReturn() {
+    int count = static_cast<int>(sig_->return_count());
+    TFNode** buffer = nullptr;
+    if (build()) buffer = builder_->Buffer(count);
+
+    // Pop return values off the stack in reverse order.
+    for (int i = count - 1; i >= 0; i--) {
+      Value val = Pop(i, sig_->GetReturn(i));
+      if (buffer) buffer[i] = val.node;
     }
 
-    if (static_cast<int>(trees_.size()) < retcount) {
-      error(limit_, nullptr,
-            "ImplicitReturn expects %d arguments, only %d remain", retcount,
-            static_cast<int>(trees_.size()));
-      return;
-    }
+    Push(kAstEnd, BUILD(Return, count, buffer));
+    ssa_env_->Kill(SsaEnv::kControlEnd);
+  }
 
-    TRACE("wasm-decode implicit return of %d args\n", retcount);
+  void Push(LocalType type, TFNode* node) {
+    stack_.push_back({pc_, node, type});
+  }
 
-    TFNode** buffer = BUILD(Buffer, retcount);
-    for (int index = 0; index < retcount; index++) {
-      Tree* tree = trees_[trees_.size() - 1 - index];
-      if (buffer) buffer[index] = tree->node;
-      LocalType expected = sig_->GetReturn(index);
-      if (tree->type != expected) {
-        error(limit_, tree->pc,
-              "ImplicitReturn[%d] expected type %s, found %s of type %s", index,
-              WasmOpcodes::TypeName(expected),
-              WasmOpcodes::OpcodeName(tree->opcode()),
-              WasmOpcodes::TypeName(tree->type));
-        return;
+  const char* SafeOpcodeNameAt(const byte* pc) {
+    if (pc >= end_) return "<end>";
+    return WasmOpcodes::ShortOpcodeName(static_cast<WasmOpcode>(*pc));
+  }
+
+  Value Pop(int index, LocalType expected) {
+    Value val = Pop();
+    if (val.type != expected) {
+      if (val.type != kAstEnd) {
+        error(pc_, val.pc, "%s[%d] expected type %s, found %s of type %s",
+              SafeOpcodeNameAt(pc_), index, WasmOpcodes::TypeName(expected),
+              SafeOpcodeNameAt(val.pc), WasmOpcodes::TypeName(val.type));
       }
     }
+    return val;
+  }
 
-    BUILD(Return, retcount, buffer);
+  Value Pop() {
+    size_t limit = control_.empty() ? 0 : control_.back().stack_depth;
+    if (stack_.size() <= limit) {
+      Value val = {pc_, nullptr, kAstStmt};
+      error(pc_, pc_, "%s found empty stack", SafeOpcodeNameAt(pc_));
+      return val;
+    }
+    Value val = stack_.back();
+    stack_.pop_back();
+    return val;
+  }
+
+  Value PopUpTo(int stack_depth) {
+    if (stack_depth == stack_.size()) {
+      Value val = {pc_, nullptr, kAstStmt};
+      return val;
+    } else {
+      DCHECK_LE(stack_depth, static_cast<int>(stack_.size()));
+      Value val = Pop();
+      stack_.resize(stack_depth);
+      return val;
+    }
   }
 
   int baserel(const byte* ptr) {
@@ -937,437 +1207,65 @@
 
   int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); }
 
-  void Reduce(Production* p) {
-    WasmOpcode opcode = p->opcode();
-    TRACE("-----reduce module+%-6d %s func+%d: 0x%02x %s\n", baserel(p->pc()),
-          indentation(), startrel(p->pc()), opcode,
-          WasmOpcodes::OpcodeName(opcode));
-    FunctionSig* sig = WasmOpcodes::Signature(opcode);
-    if (sig) {
-      // A simple expression with a fixed signature.
-      TypeCheckLast(p, sig->GetParam(p->index - 1));
-      if (p->done() && build()) {
-        if (sig->parameter_count() == 2) {
-          p->tree->node = builder_->Binop(opcode, p->tree->children[0]->node,
-                                          p->tree->children[1]->node);
-        } else if (sig->parameter_count() == 1) {
-          p->tree->node = builder_->Unop(opcode, p->tree->children[0]->node);
-        } else {
-          UNREACHABLE();
-        }
-      }
-      return;
-    }
-
-    switch (opcode) {
-      case kExprBlock: {
-        if (p->done()) {
-          Block* last = &blocks_.back();
-          DCHECK_EQ(stack_.size() - 1, last->stack_depth);
-          // fallthrough with the last expression.
-          ReduceBreakToExprBlock(p, last);
-          SetEnv("block:end", last->ssa_env);
-          blocks_.pop_back();
-        }
-        break;
-      }
-      case kExprLoop: {
-        if (p->done()) {
-          // Pop the continue environment.
-          blocks_.pop_back();
-          // Get the break environment.
-          Block* last = &blocks_.back();
-          DCHECK_EQ(stack_.size() - 1, last->stack_depth);
-          // fallthrough with the last expression.
-          ReduceBreakToExprBlock(p, last);
-          SetEnv("loop:end", last->ssa_env);
-          blocks_.pop_back();
-        }
-        break;
-      }
-      case kExprIf: {
-        if (p->index == 1) {
-          // Condition done. Split environment for true branch.
-          TypeCheckLast(p, kAstI32);
-          SsaEnv* false_env = ssa_env_;
-          SsaEnv* true_env = Split(ssa_env_);
-          ifs_.push_back({nullptr, false_env, nullptr});
-          BUILD(Branch, p->last()->node, &true_env->control,
-                &false_env->control);
-          SetEnv("if:true", true_env);
-        } else if (p->index == 2) {
-          // True block done. Merge true and false environments.
-          IfEnv* env = &ifs_.back();
-          SsaEnv* merge = env->merge_env;
-          if (merge->go()) {
-            merge->state = SsaEnv::kReached;
-            Goto(ssa_env_, merge);
-          }
-          SetEnv("if:merge", merge);
-          ifs_.pop_back();
-        }
-        break;
-      }
-      case kExprIfElse: {
-        if (p->index == 1) {
-          // Condition done. Split environment for true and false branches.
-          TypeCheckLast(p, kAstI32);
-          SsaEnv* merge_env = ssa_env_;
-          TFNode* if_true = nullptr;
-          TFNode* if_false = nullptr;
-          BUILD(Branch, p->last()->node, &if_true, &if_false);
-          SsaEnv* false_env = Split(ssa_env_);
-          SsaEnv* true_env = Steal(ssa_env_);
-          false_env->control = if_false;
-          true_env->control = if_true;
-          ifs_.push_back({false_env, merge_env, nullptr});
-          SetEnv("if_else:true", true_env);
-        } else if (p->index == 2) {
-          // True expr done.
-          IfEnv* env = &ifs_.back();
-          MergeIntoProduction(p, env->merge_env, p->last());
-          // Switch to environment for false branch.
-          SsaEnv* false_env = ifs_.back().false_env;
-          SetEnv("if_else:false", false_env);
-        } else if (p->index == 3) {
-          // False expr done.
-          IfEnv* env = &ifs_.back();
-          MergeIntoProduction(p, env->merge_env, p->last());
-          SetEnv("if_else:merge", env->merge_env);
-          ifs_.pop_back();
-        }
-        break;
-      }
-      case kExprSelect: {
-        if (p->index == 1) {
-          // True expression done.
-          p->tree->type = p->last()->type;
-          if (p->tree->type == kAstStmt) {
-            error(p->pc(), p->tree->children[1]->pc,
-                  "select operand should be expression");
-          }
-        } else if (p->index == 2) {
-          // False expression done.
-          TypeCheckLast(p, p->tree->type);
-        } else {
-          // Condition done.
-          DCHECK(p->done());
-          TypeCheckLast(p, kAstI32);
-          if (build()) {
-            TFNode* controls[2];
-            builder_->Branch(p->tree->children[2]->node, &controls[0],
-                             &controls[1]);
-            TFNode* merge = builder_->Merge(2, controls);
-            TFNode* vals[2] = {p->tree->children[0]->node,
-                               p->tree->children[1]->node};
-            TFNode* phi = builder_->Phi(p->tree->type, 2, vals, merge);
-            p->tree->node = phi;
-            ssa_env_->control = merge;
-          }
-        }
-        break;
-      }
-      case kExprBr: {
-        BreakDepthOperand operand(this, p->pc());
-        CHECK(Validate(p->pc(), operand, blocks_));
-        ReduceBreakToExprBlock(p, operand.target);
-        break;
-      }
-      case kExprBrIf: {
-        if (p->done()) {
-          TypeCheckLast(p, kAstI32);
-          BreakDepthOperand operand(this, p->pc());
-          CHECK(Validate(p->pc(), operand, blocks_));
-          SsaEnv* fenv = ssa_env_;
-          SsaEnv* tenv = Split(fenv);
-          BUILD(Branch, p->tree->children[1]->node, &tenv->control,
-                &fenv->control);
-          ssa_env_ = tenv;
-          ReduceBreakToExprBlock(p, operand.target, p->tree->children[0]);
-          ssa_env_ = fenv;
-        }
-        break;
-      }
-      case kExprBrTable: {
-        if (p->index == 1) {
-          // Switch key finished.
-          TypeCheckLast(p, kAstI32);
-          if (failed()) break;
-
-          BranchTableOperand operand(this, p->pc());
-          DCHECK(Validate(p->pc(), operand, blocks_.size()));
-
-          // Build a switch only if it has more than just a default target.
-          bool build_switch = operand.table_count > 0;
-          TFNode* sw = nullptr;
-          if (build_switch) {
-            sw = BUILD(Switch, operand.table_count + 1, p->last()->node);
-          }
-
-          // Process the targets of the break table.
-          SsaEnv* prev = ssa_env_;
-          SsaEnv* copy = Steal(prev);
-          for (uint32_t i = 0; i < operand.table_count + 1; i++) {
-            uint32_t target = operand.read_entry(this, i);
-            SsaEnv* env = copy;
-            if (build_switch) {
-              ssa_env_ = env = Split(env);
-              env->control = i == operand.table_count ? BUILD(IfDefault, sw)
-                                                      : BUILD(IfValue, i, sw);
-            }
-            SsaEnv* tenv = blocks_[blocks_.size() - target - 1].ssa_env;
-            Goto(env, tenv);
-          }
-          ssa_env_ = prev;
-        }
-        break;
-      }
-      case kExprReturn: {
-        TypeCheckLast(p, sig_->GetReturn(p->index - 1));
-        if (p->done()) {
-          if (build()) {
-            int count = p->tree->count;
-            TFNode** buffer = builder_->Buffer(count);
-            for (int i = 0; i < count; i++) {
-              buffer[i] = p->tree->children[i]->node;
-            }
-            BUILD(Return, count, buffer);
-          }
-          ssa_env_->Kill(SsaEnv::kControlEnd);
-        }
-        break;
-      }
-      case kExprSetLocal: {
-        LocalIndexOperand operand(this, p->pc());
-        CHECK(Validate(p->pc(), operand));
-        Tree* val = p->last();
-        if (operand.type == val->type) {
-          if (build()) ssa_env_->locals[operand.index] = val->node;
-          p->tree->node = val->node;
-        } else {
-          error(p->pc(), val->pc, "Typecheck failed in SetLocal");
-        }
-        break;
-      }
-      case kExprStoreGlobal: {
-        GlobalIndexOperand operand(this, p->pc());
-        CHECK(Validate(p->pc(), operand));
-        Tree* val = p->last();
-        if (operand.type == val->type) {
-          BUILD(StoreGlobal, operand.index, val->node);
-          p->tree->node = val->node;
-        } else {
-          error(p->pc(), val->pc, "Typecheck failed in StoreGlobal");
-        }
-        break;
-      }
-
-      case kExprI32LoadMem8S:
-        return ReduceLoadMem(p, kAstI32, MachineType::Int8());
-      case kExprI32LoadMem8U:
-        return ReduceLoadMem(p, kAstI32, MachineType::Uint8());
-      case kExprI32LoadMem16S:
-        return ReduceLoadMem(p, kAstI32, MachineType::Int16());
-      case kExprI32LoadMem16U:
-        return ReduceLoadMem(p, kAstI32, MachineType::Uint16());
-      case kExprI32LoadMem:
-        return ReduceLoadMem(p, kAstI32, MachineType::Int32());
-
-      case kExprI64LoadMem8S:
-        return ReduceLoadMem(p, kAstI64, MachineType::Int8());
-      case kExprI64LoadMem8U:
-        return ReduceLoadMem(p, kAstI64, MachineType::Uint8());
-      case kExprI64LoadMem16S:
-        return ReduceLoadMem(p, kAstI64, MachineType::Int16());
-      case kExprI64LoadMem16U:
-        return ReduceLoadMem(p, kAstI64, MachineType::Uint16());
-      case kExprI64LoadMem32S:
-        return ReduceLoadMem(p, kAstI64, MachineType::Int32());
-      case kExprI64LoadMem32U:
-        return ReduceLoadMem(p, kAstI64, MachineType::Uint32());
-      case kExprI64LoadMem:
-        return ReduceLoadMem(p, kAstI64, MachineType::Int64());
-
-      case kExprF32LoadMem:
-        return ReduceLoadMem(p, kAstF32, MachineType::Float32());
-
-      case kExprF64LoadMem:
-        return ReduceLoadMem(p, kAstF64, MachineType::Float64());
-
-      case kExprI32StoreMem8:
-        return ReduceStoreMem(p, kAstI32, MachineType::Int8());
-      case kExprI32StoreMem16:
-        return ReduceStoreMem(p, kAstI32, MachineType::Int16());
-      case kExprI32StoreMem:
-        return ReduceStoreMem(p, kAstI32, MachineType::Int32());
-
-      case kExprI64StoreMem8:
-        return ReduceStoreMem(p, kAstI64, MachineType::Int8());
-      case kExprI64StoreMem16:
-        return ReduceStoreMem(p, kAstI64, MachineType::Int16());
-      case kExprI64StoreMem32:
-        return ReduceStoreMem(p, kAstI64, MachineType::Int32());
-      case kExprI64StoreMem:
-        return ReduceStoreMem(p, kAstI64, MachineType::Int64());
-
-      case kExprF32StoreMem:
-        return ReduceStoreMem(p, kAstF32, MachineType::Float32());
-
-      case kExprF64StoreMem:
-        return ReduceStoreMem(p, kAstF64, MachineType::Float64());
-
-      case kExprGrowMemory:
-        TypeCheckLast(p, kAstI32);
-        // TODO(titzer): build node for GrowMemory
-        p->tree->node = BUILD(Int32Constant, 0);
-        return;
-
-      case kExprCallFunction: {
-        FunctionIndexOperand operand(this, p->pc());
-        CHECK(Validate(p->pc(), operand));
-        if (p->index > 0) {
-          TypeCheckLast(p, operand.sig->GetParam(p->index - 1));
-        }
-        if (p->done() && build()) {
-          uint32_t count = p->tree->count + 1;
-          TFNode** buffer = builder_->Buffer(count);
-          buffer[0] = nullptr;  // reserved for code object.
-          for (uint32_t i = 1; i < count; i++) {
-            buffer[i] = p->tree->children[i - 1]->node;
-          }
-          p->tree->node = builder_->CallDirect(operand.index, buffer);
-        }
-        break;
-      }
-      case kExprCallIndirect: {
-        SignatureIndexOperand operand(this, p->pc());
-        CHECK(Validate(p->pc(), operand));
-        if (p->index == 1) {
-          TypeCheckLast(p, kAstI32);
-        } else {
-          TypeCheckLast(p, operand.sig->GetParam(p->index - 2));
-        }
-        if (p->done() && build()) {
-          uint32_t count = p->tree->count;
-          TFNode** buffer = builder_->Buffer(count);
-          for (uint32_t i = 0; i < count; i++) {
-            buffer[i] = p->tree->children[i]->node;
-          }
-          p->tree->node = builder_->CallIndirect(operand.index, buffer);
-        }
-        break;
-      }
-      case kExprCallImport: {
-        ImportIndexOperand operand(this, p->pc());
-        CHECK(Validate(p->pc(), operand));
-        if (p->index > 0) {
-          TypeCheckLast(p, operand.sig->GetParam(p->index - 1));
-        }
-        if (p->done() && build()) {
-          uint32_t count = p->tree->count + 1;
-          TFNode** buffer = builder_->Buffer(count);
-          buffer[0] = nullptr;  // reserved for code object.
-          for (uint32_t i = 1; i < count; i++) {
-            buffer[i] = p->tree->children[i - 1]->node;
-          }
-          p->tree->node = builder_->CallImport(operand.index, buffer);
-        }
-        break;
-      }
-      default:
-        break;
-    }
-  }
-
-  void ReduceBreakToExprBlock(Production* p, Block* block) {
-    ReduceBreakToExprBlock(p, block, p->tree->count > 0 ? p->last() : nullptr);
-  }
-
-  void ReduceBreakToExprBlock(Production* p, Block* block, Tree* val) {
-    if (block->stack_depth < 0) {
+  void BreakTo(Control* block, Value& val) {
+    if (block->is_loop) {
       // This is the inner loop block, which does not have a value.
-      Goto(ssa_env_, block->ssa_env);
+      Goto(ssa_env_, block->end_env);
     } else {
       // Merge the value into the production for the block.
-      Production* bp = &stack_[block->stack_depth];
-      MergeIntoProduction(bp, block->ssa_env, val);
+      MergeInto(block->end_env, &block->node, &block->type, val);
     }
   }
 
-  void MergeIntoProduction(Production* p, SsaEnv* target, Tree* expr) {
+  void MergeInto(SsaEnv* target, TFNode** node, LocalType* type, Value& val) {
     if (!ssa_env_->go()) return;
+    DCHECK_NE(kAstEnd, val.type);
 
     bool first = target->state == SsaEnv::kUnreachable;
     Goto(ssa_env_, target);
-    if (expr == nullptr || expr->type == kAstEnd) return;
 
     if (first) {
       // first merge to this environment; set the type and the node.
-      p->tree->type = expr->type;
-      p->tree->node = expr->node;
-    } else {
+      *type = val.type;
+      *node = val.node;
+    } else if (val.type == *type && val.type != kAstStmt) {
       // merge with the existing value for this block.
-      LocalType type = p->tree->type;
-      if (expr->type != type) {
-        type = kAstStmt;
-        p->tree->type = kAstStmt;
-        p->tree->node = nullptr;
-      } else if (type != kAstStmt) {
-        p->tree->node = CreateOrMergeIntoPhi(type, target->control,
-                                             p->tree->node, expr->node);
-      }
-    }
-  }
-
-  void ReduceLoadMem(Production* p, LocalType type, MachineType mem_type) {
-    DCHECK_EQ(1, p->index);
-    TypeCheckLast(p, kAstI32);  // index
-    if (build()) {
-      MemoryAccessOperand operand(this, p->pc());
-      p->tree->node =
-          builder_->LoadMem(type, mem_type, p->last()->node, operand.offset);
-    }
-  }
-
-  void ReduceStoreMem(Production* p, LocalType type, MachineType mem_type) {
-    if (p->index == 1) {
-      TypeCheckLast(p, kAstI32);  // index
+      *node = CreateOrMergeIntoPhi(*type, target->control, *node, val.node);
     } else {
-      DCHECK_EQ(2, p->index);
-      TypeCheckLast(p, type);
-      if (build()) {
-        MemoryAccessOperand operand(this, p->pc());
-        TFNode* val = p->tree->children[1]->node;
-        builder_->StoreMem(mem_type, p->tree->children[0]->node, operand.offset,
-                           val);
-        p->tree->node = val;
-      }
-    }
-  }
-
-  void TypeCheckLast(Production* p, LocalType expected) {
-    LocalType result = p->last()->type;
-    if (result == expected) return;
-    if (result == kAstEnd) return;
-    if (expected != kAstStmt) {
-      error(p->pc(), p->last()->pc,
-            "%s[%d] expected type %s, found %s of type %s",
-            WasmOpcodes::OpcodeName(p->opcode()), p->index - 1,
-            WasmOpcodes::TypeName(expected),
-            WasmOpcodes::OpcodeName(p->last()->opcode()),
-            WasmOpcodes::TypeName(p->last()->type));
+      // types don't match, or block is already a stmt.
+      *type = kAstStmt;
+      *node = nullptr;
     }
   }
 
   void SetEnv(const char* reason, SsaEnv* env) {
 #if DEBUG
-    TRACE("  env = %p, block depth = %d, reason = %s", static_cast<void*>(env),
-          static_cast<int>(blocks_.size()), reason);
-    if (FLAG_trace_wasm_decoder && env && env->control) {
-      TRACE(", control = ");
-      compiler::WasmGraphBuilder::PrintDebugName(env->control);
+    if (FLAG_trace_wasm_decoder) {
+      char state = 'X';
+      if (env) {
+        switch (env->state) {
+          case SsaEnv::kReached:
+            state = 'R';
+            break;
+          case SsaEnv::kUnreachable:
+            state = 'U';
+            break;
+          case SsaEnv::kMerged:
+            state = 'M';
+            break;
+          case SsaEnv::kControlEnd:
+            state = 'E';
+            break;
+        }
+      }
+      PrintF("  env = %p, state = %c, reason = %s", static_cast<void*>(env),
+             state, reason);
+      if (env && env->control) {
+        PrintF(", control = ");
+        compiler::WasmGraphBuilder::PrintDebugName(env->control);
+      }
+      PrintF("\n");
     }
-    TRACE("\n");
 #endif
     ssa_env_ = env;
     if (builder_) {
@@ -1417,7 +1315,7 @@
         builder_->AppendToMerge(merge, from->control);
         // Merge effects.
         if (builder_->IsPhiWithMerge(to->effect, merge)) {
-          builder_->AppendToPhi(merge, to->effect, from->effect);
+          builder_->AppendToPhi(to->effect, from->effect);
         } else if (to->effect != from->effect) {
           uint32_t count = builder_->InputCount(merge);
           TFNode** effects = builder_->Buffer(count);
@@ -1432,7 +1330,7 @@
           TFNode* tnode = to->locals[i];
           TFNode* fnode = from->locals[i];
           if (builder_->IsPhiWithMerge(tnode, merge)) {
-            builder_->AppendToPhi(merge, tnode, fnode);
+            builder_->AppendToPhi(tnode, fnode);
           } else if (tnode != fnode) {
             uint32_t count = builder_->InputCount(merge);
             TFNode** vals = builder_->Buffer(count);
@@ -1455,7 +1353,7 @@
   TFNode* CreateOrMergeIntoPhi(LocalType type, TFNode* merge, TFNode* tnode,
                                TFNode* fnode) {
     if (builder_->IsPhiWithMerge(tnode, merge)) {
-      builder_->AppendToPhi(merge, tnode, fnode);
+      builder_->AppendToPhi(tnode, fnode);
     } else if (tnode != fnode) {
       uint32_t count = builder_->InputCount(merge);
       TFNode** vals = builder_->Buffer(count);
@@ -1501,8 +1399,6 @@
     size_t size = sizeof(TFNode*) * EnvironmentCount();
     result->control = from->control;
     result->effect = from->effect;
-    result->state = from->state == SsaEnv::kUnreachable ? SsaEnv::kUnreachable
-                                                        : SsaEnv::kReached;
 
     if (from->go()) {
       result->state = SsaEnv::kReached;
@@ -1549,88 +1445,53 @@
   virtual void onFirstError() {
     limit_ = start_;     // Terminate decoding loop.
     builder_ = nullptr;  // Don't build any more nodes.
-#if DEBUG
-    PrintStackForDebugging();
-#endif
+    TRACE(" !%s\n", error_msg_.get());
   }
-
-#if DEBUG
-  void PrintStackForDebugging() { PrintProduction(0); }
-
-  void PrintProduction(size_t depth) {
-    if (depth >= stack_.size()) return;
-    Production* p = &stack_[depth];
-    for (size_t d = 0; d < depth; d++) PrintF("  ");
-
-    PrintF("@%d %s [%d]\n", static_cast<int>(p->tree->pc - start_),
-           WasmOpcodes::OpcodeName(p->opcode()), p->tree->count);
-    for (int i = 0; i < p->index; i++) {
-      Tree* child = p->tree->children[i];
-      for (size_t d = 0; d <= depth; d++) PrintF("  ");
-      PrintF("@%d %s [%d]", static_cast<int>(child->pc - start_),
-             WasmOpcodes::OpcodeName(child->opcode()), child->count);
-      if (child->node) {
-        PrintF(" => TF");
-        compiler::WasmGraphBuilder::PrintDebugName(child->node);
-      }
-      PrintF("\n");
-    }
-    PrintProduction(depth + 1);
-  }
-#endif
-
   BitVector* AnalyzeLoopAssignment(const byte* pc) {
     if (pc >= limit_) return nullptr;
     if (*pc != kExprLoop) return nullptr;
 
     BitVector* assigned =
-        new (zone_) BitVector(static_cast<int>(total_locals_), zone_);
-    // Keep a stack to model the nesting of expressions.
-    std::vector<int> arity_stack;
-    arity_stack.push_back(OpcodeArity(pc));
-    pc += OpcodeLength(pc);
-
+        new (zone_) BitVector(static_cast<int>(local_type_vec_.size()), zone_);
+    int depth = 0;
     // Iteratively process all AST nodes nested inside the loop.
-    while (pc < limit_) {
+    while (pc < limit_ && ok()) {
       WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
-      int arity = 0;
-      int length = 1;
-      int assigned_index = -1;
-      if (opcode == kExprSetLocal) {
-        LocalIndexOperand operand(this, pc);
-        if (assigned->length() > 0 &&
-            static_cast<int>(operand.index) < assigned->length()) {
-          // Unverified code might have an out-of-bounds index.
-          // Ignore out-of-bounds indices, as the main verification will fail.
-          assigned->Add(operand.index);
-          assigned_index = operand.index;
+      unsigned length = 1;
+      switch (opcode) {
+        case kExprLoop:
+        case kExprIf:
+        case kExprBlock:
+          depth++;
+          DCHECK_EQ(1, OpcodeLength(pc));
+          break;
+        case kExprSetLocal: {
+          LocalIndexOperand operand(this, pc);
+          if (assigned->length() > 0 &&
+              static_cast<int>(operand.index) < assigned->length()) {
+            // Unverified code might have an out-of-bounds index.
+            assigned->Add(operand.index);
+          }
+          length = 1 + operand.length;
+          break;
         }
-        arity = 1;
-        length = 1 + operand.length;
-      } else {
-        arity = OpcodeArity(pc);
-        length = OpcodeLength(pc);
+        case kExprEnd:
+          depth--;
+          break;
+        default:
+          length = OpcodeLength(pc);
+          break;
       }
-
-      TRACE("loop-assign module+%-6d %s func+%d: 0x%02x %s", baserel(pc),
-            indentation(), startrel(pc), opcode,
-            WasmOpcodes::OpcodeName(opcode));
-
-      if (assigned_index >= 0) {
-        TRACE(" (assigned local #%d)\n", assigned_index);
-      } else {
-        TRACE("\n");
-      }
-
+      if (depth <= 0) break;
       pc += length;
-      arity_stack.push_back(arity);
-      while (arity_stack.back() == 0) {
-        arity_stack.pop_back();
-        if (arity_stack.empty()) return assigned;  // reached end of loop
-        arity_stack.back()--;
-      }
     }
-    return assigned;
+    return ok() ? assigned : nullptr;
+  }
+
+  inline wasm::WasmCodePosition position() {
+    int offset = static_cast<int>(pc_ - start_);
+    DCHECK_EQ(pc_ - start_, offset);  // overflows cannot happen
+    return offset;
   }
 };
 
@@ -1647,19 +1508,18 @@
                           FunctionBody& body) {
   Zone zone(allocator);
   SR_WasmDecoder decoder(&zone, nullptr, body);
-  TreeResult result = decoder.Decode();
-  return result;
+  decoder.Decode();
+  return decoder.toResult<Tree*>(nullptr);
 }
 
 TreeResult BuildTFGraph(base::AccountingAllocator* allocator,
                         TFBuilder* builder, FunctionBody& body) {
   Zone zone(allocator);
   SR_WasmDecoder decoder(&zone, builder, body);
-  TreeResult result = decoder.Decode();
-  return result;
+  decoder.Decode();
+  return decoder.toResult<Tree*>(nullptr);
 }
 
-
 std::ostream& operator<<(std::ostream& os, const Tree& tree) {
   if (tree.pc == nullptr) {
     os << "null";
@@ -1667,7 +1527,7 @@
   }
   PrintF("%s", WasmOpcodes::OpcodeName(tree.opcode()));
   if (tree.count > 0) os << "(";
-  for (uint32_t i = 0; i < tree.count; i++) {
+  for (uint32_t i = 0; i < tree.count; ++i) {
     if (i > 0) os << ", ";
     os << *tree.children[i];
   }
@@ -1675,37 +1535,33 @@
   return os;
 }
 
-
-ReadUnsignedLEB128ErrorCode ReadUnsignedLEB128Operand(const byte* pc,
-                                                      const byte* limit,
-                                                      int* length,
-                                                      uint32_t* result) {
-  Decoder decoder(pc, limit);
-  *result = decoder.checked_read_u32v(pc, 0, length);
-  if (decoder.ok()) return kNoError;
-  return (limit - pc) > 1 ? kInvalidLEB128 : kMissingLEB128;
-}
-
-int OpcodeLength(const byte* pc, const byte* end) {
+unsigned OpcodeLength(const byte* pc, const byte* end) {
   WasmDecoder decoder(nullptr, nullptr, pc, end);
   return decoder.OpcodeLength(pc);
 }
 
-int OpcodeArity(ModuleEnv* module, FunctionSig* sig, const byte* pc,
-                const byte* end) {
-  WasmDecoder decoder(module, sig, pc, end);
+unsigned OpcodeArity(const byte* pc, const byte* end) {
+  WasmDecoder decoder(nullptr, nullptr, pc, end);
   return decoder.OpcodeArity(pc);
 }
 
-void PrintAst(base::AccountingAllocator* allocator, FunctionBody& body) {
+void PrintAstForDebugging(const byte* start, const byte* end) {
+  base::AccountingAllocator allocator;
+  OFStream os(stdout);
+  PrintAst(&allocator, FunctionBodyForTesting(start, end), os, nullptr);
+}
+
+bool PrintAst(base::AccountingAllocator* allocator, const FunctionBody& body,
+              std::ostream& os,
+              std::vector<std::tuple<uint32_t, int, int>>* offset_table) {
   Zone zone(allocator);
   SR_WasmDecoder decoder(&zone, nullptr, body);
-
-  OFStream os(stdout);
+  int line_nr = 0;
 
   // Print the function signature.
   if (body.sig) {
     os << "// signature: " << *body.sig << std::endl;
+    ++line_nr;
   }
 
   // Print the local declarations.
@@ -1713,7 +1569,7 @@
   decoder.DecodeLocalDecls(decls);
   const byte* pc = decoder.pc();
   if (body.start != decoder.pc()) {
-    printf("// locals:");
+    os << "// locals: ";
     for (auto p : decls.local_types) {
       LocalType type = p.first;
       uint32_t count = p.second;
@@ -1722,67 +1578,107 @@
     os << std::endl;
 
     for (const byte* locals = body.start; locals < pc; locals++) {
-      printf(" 0x%02x,", *locals);
+      os << (locals == body.start ? "0x" : " 0x") << AsHex(*locals, 2) << ",";
     }
-    printf("\n");
+    os << std::endl;
+    ++line_nr;
   }
 
-  printf("// body: \n");
-  std::vector<int> arity_stack;
+  os << "// body: " << std::endl;
+  ++line_nr;
+  unsigned control_depth = 0;
   while (pc < body.end) {
-    int arity = decoder.OpcodeArity(pc);
-    size_t length = decoder.OpcodeLength(pc);
-
-    for (auto arity : arity_stack) {
-      printf("  ");
-      USE(arity);
-    }
+    unsigned length = decoder.OpcodeLength(pc);
 
     WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
-    printf("k%s,", WasmOpcodes::OpcodeName(opcode));
+    if (opcode == kExprElse) control_depth--;
 
-    for (size_t i = 1; i < length; i++) {
-      printf(" 0x%02x,", pc[i]);
+    int num_whitespaces = control_depth < 32 ? 2 * control_depth : 64;
+    if (offset_table) {
+      offset_table->push_back(
+          std::make_tuple(pc - body.start, line_nr, num_whitespaces));
     }
 
-    if (body.module) {
-      switch (opcode) {
-        case kExprCallIndirect: {
-          SignatureIndexOperand operand(&decoder, pc);
-          if (decoder.Validate(pc, operand)) {
-            os << " // sig #" << operand.index << ": " << *operand.sig;
-          }
-          break;
-        }
-        case kExprCallImport: {
-          ImportIndexOperand operand(&decoder, pc);
-          if (decoder.Validate(pc, operand)) {
-            os << " // import #" << operand.index << ": " << *operand.sig;
-          }
-          break;
-        }
-        case kExprCallFunction: {
-          FunctionIndexOperand operand(&decoder, pc);
-          if (decoder.Validate(pc, operand)) {
-            os << " // function #" << operand.index << ": " << *operand.sig;
-          }
-          break;
-        }
-        default:
-          break;
+    // 64 whitespaces
+    const char* padding =
+        "                                                                ";
+    os.write(padding, num_whitespaces);
+    os << "k" << WasmOpcodes::OpcodeName(opcode) << ",";
+
+    for (size_t i = 1; i < length; ++i) {
+      os << " " << AsHex(pc[i], 2) << ",";
+    }
+
+    switch (opcode) {
+      case kExprIf:
+      case kExprElse:
+      case kExprLoop:
+      case kExprBlock:
+        os << "   // @" << static_cast<int>(pc - body.start);
+        control_depth++;
+        break;
+      case kExprEnd:
+        os << "   // @" << static_cast<int>(pc - body.start);
+        control_depth--;
+        break;
+      case kExprBr: {
+        BreakDepthOperand operand(&decoder, pc);
+        os << "   // arity=" << operand.arity << " depth=" << operand.depth;
+        break;
       }
-    }
+      case kExprBrIf: {
+        BreakDepthOperand operand(&decoder, pc);
+        os << "   // arity=" << operand.arity << " depth" << operand.depth;
+        break;
+      }
+      case kExprBrTable: {
+        BranchTableOperand operand(&decoder, pc);
+        os << "   // arity=" << operand.arity
+           << " entries=" << operand.table_count;
+        break;
+      }
+      case kExprCallIndirect: {
+        CallIndirectOperand operand(&decoder, pc);
+        if (decoder.Complete(pc, operand)) {
+          os << "   // sig #" << operand.index << ": " << *operand.sig;
+        } else {
+          os << " // arity=" << operand.arity << " sig #" << operand.index;
+        }
+        break;
+      }
+      case kExprCallImport: {
+        CallImportOperand operand(&decoder, pc);
+        if (decoder.Complete(pc, operand)) {
+          os << "   // import #" << operand.index << ": " << *operand.sig;
+        } else {
+          os << " // arity=" << operand.arity << " import #" << operand.index;
+        }
+        break;
+      }
+      case kExprCallFunction: {
+        CallFunctionOperand operand(&decoder, pc);
+        if (decoder.Complete(pc, operand)) {
+          os << "   // function #" << operand.index << ": " << *operand.sig;
+        } else {
+          os << " // arity=" << operand.arity << " function #" << operand.index;
+        }
+        break;
+      }
+      case kExprReturn: {
+        ReturnArityOperand operand(&decoder, pc);
+        os << "   // arity=" << operand.arity;
+        break;
+      }
+      default:
+        break;
+      }
 
     pc += length;
-    printf("\n");
-
-    arity_stack.push_back(arity);
-    while (arity_stack.back() == 0) {
-      arity_stack.pop_back();
-      if (arity_stack.empty()) break;
-      arity_stack.back()--;
-    }
+    os << std::endl;
+    ++line_nr;
   }
+
+  return decoder.ok();
 }
 
 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
diff --git a/src/wasm/ast-decoder.h b/src/wasm/ast-decoder.h
index 5376e7b..27170dd 100644
--- a/src/wasm/ast-decoder.h
+++ b/src/wasm/ast-decoder.h
@@ -25,7 +25,7 @@
 struct LocalIndexOperand {
   uint32_t index;
   LocalType type;
-  int length;
+  unsigned length;
 
   inline LocalIndexOperand(Decoder* decoder, const byte* pc) {
     index = decoder->checked_read_u32v(pc, 1, &length, "local index");
@@ -35,7 +35,7 @@
 
 struct ImmI8Operand {
   int8_t value;
-  int length;
+  unsigned length;
   inline ImmI8Operand(Decoder* decoder, const byte* pc) {
     value = bit_cast<int8_t>(decoder->checked_read_u8(pc, 1, "immi8"));
     length = 1;
@@ -44,7 +44,7 @@
 
 struct ImmI32Operand {
   int32_t value;
-  int length;
+  unsigned length;
   inline ImmI32Operand(Decoder* decoder, const byte* pc) {
     value = decoder->checked_read_i32v(pc, 1, &length, "immi32");
   }
@@ -52,7 +52,7 @@
 
 struct ImmI64Operand {
   int64_t value;
-  int length;
+  unsigned length;
   inline ImmI64Operand(Decoder* decoder, const byte* pc) {
     value = decoder->checked_read_i64v(pc, 1, &length, "immi64");
   }
@@ -60,7 +60,7 @@
 
 struct ImmF32Operand {
   float value;
-  int length;
+  unsigned length;
   inline ImmF32Operand(Decoder* decoder, const byte* pc) {
     value = bit_cast<float>(decoder->checked_read_u32(pc, 1, "immf32"));
     length = 4;
@@ -69,7 +69,7 @@
 
 struct ImmF64Operand {
   double value;
-  int length;
+  unsigned length;
   inline ImmF64Operand(Decoder* decoder, const byte* pc) {
     value = bit_cast<double>(decoder->checked_read_u64(pc, 1, "immf64"));
     length = 8;
@@ -80,7 +80,7 @@
   uint32_t index;
   LocalType type;
   MachineType machine_type;
-  int length;
+  unsigned length;
 
   inline GlobalIndexOperand(Decoder* decoder, const byte* pc) {
     index = decoder->checked_read_u32v(pc, 1, &length, "global index");
@@ -89,66 +89,85 @@
   }
 };
 
-struct Block;
+struct Control;
 struct BreakDepthOperand {
+  uint32_t arity;
   uint32_t depth;
-  Block* target;
-  int length;
+  Control* target;
+  unsigned length;
   inline BreakDepthOperand(Decoder* decoder, const byte* pc) {
-    depth = decoder->checked_read_u32v(pc, 1, &length, "break depth");
+    unsigned len1 = 0;
+    unsigned len2 = 0;
+    arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
+    depth = decoder->checked_read_u32v(pc, 1 + len1, &len2, "break depth");
+    length = len1 + len2;
     target = nullptr;
   }
 };
 
-struct BlockCountOperand {
-  uint32_t count;
-  int length;
-  inline BlockCountOperand(Decoder* decoder, const byte* pc) {
-    count = decoder->checked_read_u32v(pc, 1, &length, "block count");
-  }
-};
-
-struct SignatureIndexOperand {
+struct CallIndirectOperand {
+  uint32_t arity;
   uint32_t index;
   FunctionSig* sig;
-  int length;
-  inline SignatureIndexOperand(Decoder* decoder, const byte* pc) {
-    index = decoder->checked_read_u32v(pc, 1, &length, "signature index");
+  unsigned length;
+  inline CallIndirectOperand(Decoder* decoder, const byte* pc) {
+    unsigned len1 = 0;
+    unsigned len2 = 0;
+    arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
+    index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "signature index");
+    length = len1 + len2;
     sig = nullptr;
   }
 };
 
-struct FunctionIndexOperand {
+struct CallFunctionOperand {
+  uint32_t arity;
   uint32_t index;
   FunctionSig* sig;
-  int length;
-  inline FunctionIndexOperand(Decoder* decoder, const byte* pc) {
-    index = decoder->checked_read_u32v(pc, 1, &length, "function index");
+  unsigned length;
+  inline CallFunctionOperand(Decoder* decoder, const byte* pc) {
+    unsigned len1 = 0;
+    unsigned len2 = 0;
+    arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
+    index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "function index");
+    length = len1 + len2;
     sig = nullptr;
   }
 };
 
-struct ImportIndexOperand {
+struct CallImportOperand {
+  uint32_t arity;
   uint32_t index;
   FunctionSig* sig;
-  int length;
-  inline ImportIndexOperand(Decoder* decoder, const byte* pc) {
-    index = decoder->checked_read_u32v(pc, 1, &length, "import index");
+  unsigned length;
+  inline CallImportOperand(Decoder* decoder, const byte* pc) {
+    unsigned len1 = 0;
+    unsigned len2 = 0;
+    arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
+    index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "import index");
+    length = len1 + len2;
     sig = nullptr;
   }
 };
 
 struct BranchTableOperand {
+  uint32_t arity;
   uint32_t table_count;
   const byte* table;
-  int length;
+  unsigned length;
   inline BranchTableOperand(Decoder* decoder, const byte* pc) {
-    int varint_length;
+    unsigned len1 = 0;
+    unsigned len2 = 0;
+    arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
     table_count =
-        decoder->checked_read_u32v(pc, 1, &varint_length, "expected #entries");
-    length = varint_length + (table_count + 1) * sizeof(uint32_t);
+        decoder->checked_read_u32v(pc, 1 + len1, &len2, "table count");
+    if (table_count > (UINT_MAX / sizeof(uint32_t)) - 1 ||
+        len1 + len2 > UINT_MAX - (table_count + 1) * sizeof(uint32_t)) {
+      decoder->error(pc, "branch table size overflow");
+    }
+    length = len1 + len2 + (table_count + 1) * sizeof(uint32_t);
 
-    uint32_t table_start = 1 + varint_length;
+    uint32_t table_start = 1 + len1 + len2;
     if (decoder->check(pc, table_start, (table_count + 1) * sizeof(uint32_t),
                        "expected <table entries>")) {
       table = pc + table_start;
@@ -156,8 +175,8 @@
       table = nullptr;
     }
   }
-  inline uint32_t read_entry(Decoder* decoder, int i) {
-    DCHECK(i >= 0 && static_cast<uint32_t>(i) <= table_count);
+  inline uint32_t read_entry(Decoder* decoder, unsigned i) {
+    DCHECK(i <= table_count);
     return table ? decoder->read_u32(table + i * sizeof(uint32_t)) : 0;
   }
 };
@@ -165,18 +184,27 @@
 struct MemoryAccessOperand {
   uint32_t alignment;
   uint32_t offset;
-  int length;
+  unsigned length;
   inline MemoryAccessOperand(Decoder* decoder, const byte* pc) {
-    int alignment_length;
+    unsigned alignment_length;
     alignment =
         decoder->checked_read_u32v(pc, 1, &alignment_length, "alignment");
-    int offset_length;
+    unsigned offset_length;
     offset = decoder->checked_read_u32v(pc, 1 + alignment_length,
                                         &offset_length, "offset");
     length = alignment_length + offset_length;
   }
 };
 
+struct ReturnArityOperand {
+  uint32_t arity;
+  unsigned length;
+
+  inline ReturnArityOperand(Decoder* decoder, const byte* pc) {
+    arity = decoder->checked_read_u32v(pc, 1, &length, "return count");
+  }
+};
+
 typedef compiler::WasmGraphBuilder TFBuilder;
 struct ModuleEnv;  // forward declaration of module interface.
 
@@ -189,6 +217,11 @@
   const byte* end;    // end of the function body
 };
 
+static inline FunctionBody FunctionBodyForTesting(const byte* start,
+                                                  const byte* end) {
+  return {nullptr, nullptr, start, start, end};
+}
+
 struct Tree;
 typedef Result<Tree*> TreeResult;
 
@@ -198,7 +231,12 @@
                           FunctionBody& body);
 TreeResult BuildTFGraph(base::AccountingAllocator* allocator,
                         TFBuilder* builder, FunctionBody& body);
-void PrintAst(base::AccountingAllocator* allocator, FunctionBody& body);
+bool PrintAst(base::AccountingAllocator* allocator, const FunctionBody& body,
+              std::ostream& os,
+              std::vector<std::tuple<uint32_t, int, int>>* offset_table);
+
+// A simplified form of AST printing, e.g. from a debugger.
+void PrintAstForDebugging(const byte* start, const byte* end);
 
 inline TreeResult VerifyWasmCode(base::AccountingAllocator* allocator,
                                  ModuleEnv* module, FunctionSig* sig,
@@ -215,11 +253,6 @@
   return BuildTFGraph(allocator, builder, body);
 }
 
-enum ReadUnsignedLEB128ErrorCode { kNoError, kInvalidLEB128, kMissingLEB128 };
-
-ReadUnsignedLEB128ErrorCode ReadUnsignedLEB128Operand(const byte*, const byte*,
-                                                      int*, uint32_t*);
-
 struct AstLocalDecls {
   // The size of the encoded declarations.
   uint32_t decls_encoded_size;  // size of encoded declarations
@@ -240,11 +273,11 @@
                                            const byte* start, const byte* end);
 
 // Computes the length of the opcode at the given address.
-int OpcodeLength(const byte* pc, const byte* end);
+unsigned OpcodeLength(const byte* pc, const byte* end);
 
 // Computes the arity (number of sub-nodes) of the opcode at the given address.
-int OpcodeArity(ModuleEnv* module, FunctionSig* sig, const byte* pc,
-                const byte* end);
+unsigned OpcodeArity(const byte* pc, const byte* end);
+
 }  // namespace wasm
 }  // namespace internal
 }  // namespace v8
diff --git a/src/wasm/decoder.h b/src/wasm/decoder.h
index f9de2e1..c1090a8 100644
--- a/src/wasm/decoder.h
+++ b/src/wasm/decoder.h
@@ -5,9 +5,11 @@
 #ifndef V8_WASM_DECODER_H_
 #define V8_WASM_DECODER_H_
 
+#include "src/base/compiler-specific.h"
 #include "src/base/smart-pointers.h"
 #include "src/flags.h"
 #include "src/signature.h"
+#include "src/utils.h"
 #include "src/wasm/wasm-result.h"
 #include "src/zone-containers.h"
 
@@ -44,47 +46,49 @@
 
   virtual ~Decoder() {}
 
-  inline bool check(const byte* base, int offset, int length, const char* msg) {
+  inline bool check(const byte* base, unsigned offset, unsigned length,
+                    const char* msg) {
     DCHECK_GE(base, start_);
     if ((base + offset + length) > limit_) {
-      error(base, base + offset, msg);
+      error(base, base + offset, "%s", msg);
       return false;
     }
     return true;
   }
 
   // Reads a single 8-bit byte, reporting an error if out of bounds.
-  inline uint8_t checked_read_u8(const byte* base, int offset,
+  inline uint8_t checked_read_u8(const byte* base, unsigned offset,
                                  const char* msg = "expected 1 byte") {
     return check(base, offset, 1, msg) ? base[offset] : 0;
   }
 
   // Reads 16-bit word, reporting an error if out of bounds.
-  inline uint16_t checked_read_u16(const byte* base, int offset,
+  inline uint16_t checked_read_u16(const byte* base, unsigned offset,
                                    const char* msg = "expected 2 bytes") {
     return check(base, offset, 2, msg) ? read_u16(base + offset) : 0;
   }
 
   // Reads 32-bit word, reporting an error if out of bounds.
-  inline uint32_t checked_read_u32(const byte* base, int offset,
+  inline uint32_t checked_read_u32(const byte* base, unsigned offset,
                                    const char* msg = "expected 4 bytes") {
     return check(base, offset, 4, msg) ? read_u32(base + offset) : 0;
   }
 
   // Reads 64-bit word, reporting an error if out of bounds.
-  inline uint64_t checked_read_u64(const byte* base, int offset,
+  inline uint64_t checked_read_u64(const byte* base, unsigned offset,
                                    const char* msg = "expected 8 bytes") {
     return check(base, offset, 8, msg) ? read_u64(base + offset) : 0;
   }
 
   // Reads a variable-length unsigned integer (little endian).
-  uint32_t checked_read_u32v(const byte* base, int offset, int* length,
+  uint32_t checked_read_u32v(const byte* base, unsigned offset,
+                             unsigned* length,
                              const char* msg = "expected LEB32") {
     return checked_read_leb<uint32_t, false>(base, offset, length, msg);
   }
 
   // Reads a variable-length signed integer (little endian).
-  int32_t checked_read_i32v(const byte* base, int offset, int* length,
+  int32_t checked_read_i32v(const byte* base, unsigned offset, unsigned* length,
                             const char* msg = "expected SLEB32") {
     uint32_t result =
         checked_read_leb<uint32_t, true>(base, offset, length, msg);
@@ -98,13 +102,14 @@
   }
 
   // Reads a variable-length unsigned integer (little endian).
-  uint64_t checked_read_u64v(const byte* base, int offset, int* length,
+  uint64_t checked_read_u64v(const byte* base, unsigned offset,
+                             unsigned* length,
                              const char* msg = "expected LEB64") {
     return checked_read_leb<uint64_t, false>(base, offset, length, msg);
   }
 
   // Reads a variable-length signed integer (little endian).
-  int64_t checked_read_i64v(const byte* base, int offset, int* length,
+  int64_t checked_read_i64v(const byte* base, unsigned offset, unsigned* length,
                             const char* msg = "expected SLEB64") {
     uint64_t result =
         checked_read_leb<uint64_t, true>(base, offset, length, msg);
@@ -202,10 +207,9 @@
   }
 
   // Reads a LEB128 variable-length 32-bit integer and advances {pc_}.
-  uint32_t consume_u32v(int* length, const char* name = nullptr) {
+  uint32_t consume_u32v(const char* name = nullptr) {
     TRACE("  +%d  %-20s: ", static_cast<int>(pc_ - start_),
           name ? name : "varint");
-
     if (checkAvailable(1)) {
       const byte* pos = pc_;
       const byte* end = pc_ + 5;
@@ -222,10 +226,10 @@
         shift += 7;
       }
 
-      *length = static_cast<int>(pc_ - pos);
+      int length = static_cast<int>(pc_ - pos);
       if (pc_ == end && (b & 0x80)) {
         error(pc_ - 1, "varint too large");
-      } else if (*length == 0) {
+      } else if (length == 0) {
         error(pc_, "varint of length 0");
       } else {
         TRACE("= %u\n", result);
@@ -258,12 +262,13 @@
     }
   }
 
-  void error(const char* msg) { error(pc_, nullptr, msg); }
+  void error(const char* msg) { error(pc_, nullptr, "%s", msg); }
 
-  void error(const byte* pc, const char* msg) { error(pc, nullptr, msg); }
+  void error(const byte* pc, const char* msg) { error(pc, nullptr, "%s", msg); }
 
   // Sets internal error state.
-  void error(const byte* pc, const byte* pt, const char* format, ...) {
+  void PRINTF_FORMAT(4, 5)
+      error(const byte* pc, const byte* pt, const char* format, ...) {
     if (ok()) {
 #if DEBUG
       if (FLAG_wasm_break_on_decoder_error) {
@@ -313,7 +318,7 @@
     } else {
       result.error_code = kSuccess;
     }
-    result.val = val;
+    result.val = std::move(val);
     return result;
   }
 
@@ -347,7 +352,7 @@
 
  private:
   template <typename IntType, bool is_signed>
-  IntType checked_read_leb(const byte* base, int offset, int* length,
+  IntType checked_read_leb(const byte* base, unsigned offset, unsigned* length,
                            const char* msg) {
     if (!check(base, offset, 1, msg)) {
       *length = 0;
@@ -368,7 +373,7 @@
       shift += 7;
     }
     DCHECK_LE(ptr - (base + offset), kMaxLength);
-    *length = static_cast<int>(ptr - (base + offset));
+    *length = static_cast<unsigned>(ptr - (base + offset));
     if (ptr == end) {
       // Check there are no bits set beyond the bitwidth of {IntType}.
       const int kExtraBits = (1 + kMaxLength * 7) - (sizeof(IntType) * 8);
@@ -392,7 +397,7 @@
         return 0;
       }
       if ((b & 0x80) != 0) {
-        error(base, ptr, msg);
+        error(base, ptr, "%s", msg);
         return 0;
       }
     }
diff --git a/src/wasm/encoder.cc b/src/wasm/encoder.cc
index 92e6b11..ffd0294 100644
--- a/src/wasm/encoder.cc
+++ b/src/wasm/encoder.cc
@@ -10,6 +10,7 @@
 
 #include "src/wasm/ast-decoder.h"
 #include "src/wasm/encoder.h"
+#include "src/wasm/leb-helper.h"
 #include "src/wasm/wasm-macro-gen.h"
 #include "src/wasm/wasm-module.h"
 #include "src/wasm/wasm-opcodes.h"
@@ -29,146 +30,72 @@
 namespace internal {
 namespace wasm {
 
-/*TODO: add error cases for adding too many locals, too many functions and bad
-  indices in body */
-
-namespace {
-void EmitUint8(byte** b, uint8_t x) {
-  Memory::uint8_at(*b) = x;
-  *b += 1;
-}
-
-
-void EmitUint16(byte** b, uint16_t x) {
-  WriteUnalignedUInt16(*b, x);
-  *b += 2;
-}
-
-
-void EmitUint32(byte** b, uint32_t x) {
-  WriteUnalignedUInt32(*b, x);
-  *b += 4;
-}
-
-// Sections all start with a size, but it's unknown at the start.
-// We generate a large varint which we then fixup later when the size is known.
-//
-// TODO(jfb) Not strictly necessary since sizes are calculated ahead of time.
-const size_t padded_varint = 5;
-
-void EmitVarInt(byte** b, size_t val) {
-  while (true) {
-    size_t next = val >> 7;
-    byte out = static_cast<byte>(val & 0x7f);
-    if (next) {
-      *((*b)++) = 0x80 | out;
-      val = next;
-    } else {
-      *((*b)++) = out;
-      break;
-    }
-  }
-}
-
-size_t SizeOfVarInt(size_t value) {
-  size_t size = 0;
-  do {
-    size++;
-    value = value >> 7;
-  } while (value > 0);
-  return size;
-}
-
-void FixupSection(byte* start, byte* end) {
-  // Same as EmitVarInt, but fixed-width with zeroes in the MSBs.
-  size_t val = end - start - padded_varint;
-  TRACE("  fixup %u\n", (unsigned)val);
-  for (size_t pos = 0; pos != padded_varint; ++pos) {
-    size_t next = val >> 7;
-    byte out = static_cast<byte>(val & 0x7f);
-    if (pos != padded_varint - 1) {
-      *(start++) = 0x80 | out;
-      val = next;
-    } else {
-      *(start++) = out;
-      // TODO(jfb) check that the pre-allocated fixup size isn't overflowed.
-    }
-  }
-}
-
-// Returns the start of the section, where the section VarInt size is.
-byte* EmitSection(WasmSection::Code code, byte** b) {
-  byte* start = *b;
+// Emit a section name and the size as a padded varint that can be patched
+// later.
+size_t EmitSection(WasmSection::Code code, ZoneBuffer& buffer) {
+  // Emit the section name.
   const char* name = WasmSection::getName(code);
-  size_t length = WasmSection::getNameLength(code);
   TRACE("emit section: %s\n", name);
-  for (size_t padding = 0; padding != padded_varint; ++padding) {
-    EmitUint8(b, 0xff);  // Will get fixed up later.
-  }
-  EmitVarInt(b, length);  // Section name string size.
-  for (size_t i = 0; i != length; ++i) EmitUint8(b, name[i]);
-  return start;
+  size_t length = WasmSection::getNameLength(code);
+  buffer.write_size(length);  // Section name string size.
+  buffer.write(reinterpret_cast<const byte*>(name), length);
+
+  // Emit a placeholder for the length.
+  return buffer.reserve_u32v();
 }
-}  // namespace
 
-struct WasmFunctionBuilder::Type {
-  bool param_;
-  LocalType type_;
-};
+// Patch the size of a section after it's finished.
+void FixupSection(ZoneBuffer& buffer, size_t start) {
+  buffer.patch_u32v(start, static_cast<uint32_t>(buffer.offset() - start -
+                                                 kPaddedVarInt32Size));
+}
 
-
-WasmFunctionBuilder::WasmFunctionBuilder(Zone* zone)
-    : return_type_(kAstI32),
-      locals_(zone),
+WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder)
+    : builder_(builder),
+      locals_(builder->zone()),
+      signature_index_(0),
       exported_(0),
-      external_(0),
-      body_(zone),
-      local_indices_(zone),
-      name_(zone) {}
+      body_(builder->zone()),
+      name_(builder->zone()) {}
 
-
-uint16_t WasmFunctionBuilder::AddParam(LocalType type) {
-  return AddVar(type, true);
+void WasmFunctionBuilder::EmitVarInt(uint32_t val) {
+  byte buffer[8];
+  byte* ptr = buffer;
+  LEBHelper::write_u32v(&ptr, val);
+  for (byte* p = buffer; p < ptr; p++) {
+    body_.push_back(*p);
+  }
 }
 
-
-uint16_t WasmFunctionBuilder::AddLocal(LocalType type) {
-  return AddVar(type, false);
+void WasmFunctionBuilder::SetSignature(FunctionSig* sig) {
+  DCHECK(!locals_.has_sig());
+  locals_.set_sig(sig);
+  signature_index_ = builder_->AddSignature(sig);
 }
 
-
-uint16_t WasmFunctionBuilder::AddVar(LocalType type, bool param) {
-  locals_.push_back({param, type});
-  return static_cast<uint16_t>(locals_.size() - 1);
+uint32_t WasmFunctionBuilder::AddLocal(LocalType type) {
+  DCHECK(locals_.has_sig());
+  return locals_.AddLocals(1, type);
 }
 
+void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) {
+  EmitWithVarInt(kExprGetLocal, local_index);
+}
 
-void WasmFunctionBuilder::ReturnType(LocalType type) { return_type_ = type; }
-
+void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) {
+  EmitWithVarInt(kExprSetLocal, local_index);
+}
 
 void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
-  EmitCode(code, code_size, nullptr, 0);
-}
-
-
-void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size,
-                                   const uint32_t* local_indices,
-                                   uint32_t indices_size) {
-  size_t size = body_.size();
-  for (size_t i = 0; i < code_size; i++) {
+  for (size_t i = 0; i < code_size; ++i) {
     body_.push_back(code[i]);
   }
-  for (size_t i = 0; i < indices_size; i++) {
-    local_indices_.push_back(local_indices[i] + static_cast<uint32_t>(size));
-  }
 }
 
-
 void WasmFunctionBuilder::Emit(WasmOpcode opcode) {
   body_.push_back(static_cast<byte>(opcode));
 }
 
-
 void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) {
   body_.push_back(static_cast<byte>(opcode));
   body_.push_back(immediate);
@@ -184,251 +111,75 @@
 void WasmFunctionBuilder::EmitWithVarInt(WasmOpcode opcode,
                                          uint32_t immediate) {
   body_.push_back(static_cast<byte>(opcode));
-  size_t immediate_size = SizeOfVarInt(immediate);
-  body_.insert(body_.end(), immediate_size, 0);
-  byte* p = &body_[body_.size() - immediate_size];
-  EmitVarInt(&p, immediate);
+  EmitVarInt(immediate);
 }
 
-uint32_t WasmFunctionBuilder::EmitEditableVarIntImmediate() {
-  // Guess that the immediate will be 1 byte. If it is more, we'll have to
-  // shift everything down.
-  body_.push_back(0);
-  return static_cast<uint32_t>(body_.size()) - 1;
-}
-
-void WasmFunctionBuilder::EditVarIntImmediate(uint32_t offset,
-                                              const uint32_t immediate) {
-  uint32_t immediate_size = static_cast<uint32_t>(SizeOfVarInt(immediate));
-  // In EmitEditableVarIntImmediate, we guessed that we'd only need one byte.
-  // If we need more, shift everything down to make room for the larger
-  // immediate.
-  if (immediate_size > 1) {
-    uint32_t diff = immediate_size - 1;
-    body_.insert(body_.begin() + offset, diff, 0);
-
-    for (size_t i = 0; i < local_indices_.size(); ++i) {
-      if (local_indices_[i] >= offset) {
-        local_indices_[i] += diff;
-      }
-    }
+void WasmFunctionBuilder::EmitI32Const(int32_t value) {
+  // TODO(titzer): variable-length signed and unsigned i32 constants.
+  if (-128 <= value && value <= 127) {
+    EmitWithU8(kExprI8Const, static_cast<byte>(value));
+  } else {
+    byte code[] = {WASM_I32V_5(value)};
+    EmitCode(code, sizeof(code));
   }
-  DCHECK(offset + immediate_size <= body_.size());
-  byte* p = &body_[offset];
-  EmitVarInt(&p, immediate);
 }
 
+void WasmFunctionBuilder::SetExported() { exported_ = true; }
 
-void WasmFunctionBuilder::Exported(uint8_t flag) { exported_ = flag; }
-
-
-void WasmFunctionBuilder::External(uint8_t flag) { external_ = flag; }
-
-void WasmFunctionBuilder::SetName(const unsigned char* name, int name_length) {
+void WasmFunctionBuilder::SetName(const char* name, int name_length) {
   name_.clear();
   if (name_length > 0) {
-    for (int i = 0; i < name_length; i++) {
+    for (int i = 0; i < name_length; ++i) {
       name_.push_back(*(name + i));
     }
   }
 }
 
+void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const {
+  buffer.write_u32v(signature_index_);
+}
 
-WasmFunctionEncoder* WasmFunctionBuilder::Build(Zone* zone,
-                                                WasmModuleBuilder* mb) const {
-  WasmFunctionEncoder* e =
-      new (zone) WasmFunctionEncoder(zone, return_type_, exported_, external_);
-  uint16_t* var_index = zone->NewArray<uint16_t>(locals_.size());
-  IndexVars(e, var_index);
+void WasmFunctionBuilder::WriteExport(ZoneBuffer& buffer,
+                                      uint32_t func_index) const {
+  if (exported_) {
+    buffer.write_u32v(func_index);
+    buffer.write_size(name_.size());
+    if (name_.size() > 0) {
+      buffer.write(reinterpret_cast<const byte*>(&name_[0]), name_.size());
+    }
+  }
+}
+
+void WasmFunctionBuilder::WriteBody(ZoneBuffer& buffer) const {
+  size_t locals_size = locals_.Size();
+  buffer.write_size(locals_size + body_.size());
+  buffer.EnsureSpace(locals_size);
+  byte** ptr = buffer.pos_ptr();
+  locals_.Emit(*ptr);
+  (*ptr) += locals_size;  // UGLY: manual bump of position pointer
   if (body_.size() > 0) {
-    // TODO(titzer): iterate over local indexes, not the bytes.
-    const byte* start = &body_[0];
-    const byte* end = start + body_.size();
-    size_t local_index = 0;
-    for (size_t i = 0; i < body_.size();) {
-      if (local_index < local_indices_.size() &&
-          i == local_indices_[local_index]) {
-        int length = 0;
-        uint32_t index;
-        ReadUnsignedLEB128Operand(start + i, end, &length, &index);
-        uint16_t new_index = var_index[index];
-        const std::vector<uint8_t>& index_vec = UnsignedLEB128From(new_index);
-        for (size_t j = 0; j < index_vec.size(); j++) {
-          e->body_.push_back(index_vec.at(j));
-        }
-        i += length;
-        local_index++;
-      } else {
-        e->body_.push_back(*(start + i));
-        i++;
-      }
-    }
-  }
-  FunctionSig::Builder sig(zone, return_type_ == kAstStmt ? 0 : 1,
-                           e->params_.size());
-  if (return_type_ != kAstStmt) {
-    sig.AddReturn(static_cast<LocalType>(return_type_));
-  }
-  for (size_t i = 0; i < e->params_.size(); i++) {
-    sig.AddParam(static_cast<LocalType>(e->params_[i]));
-  }
-  e->signature_index_ = mb->AddSignature(sig.Build());
-  e->name_.insert(e->name_.begin(), name_.begin(), name_.end());
-  return e;
-}
-
-
-void WasmFunctionBuilder::IndexVars(WasmFunctionEncoder* e,
-                                    uint16_t* var_index) const {
-  uint16_t param = 0;
-  uint16_t i32 = 0;
-  uint16_t i64 = 0;
-  uint16_t f32 = 0;
-  uint16_t f64 = 0;
-  for (size_t i = 0; i < locals_.size(); i++) {
-    if (locals_.at(i).param_) {
-      param++;
-    } else if (locals_.at(i).type_ == kAstI32) {
-      i32++;
-    } else if (locals_.at(i).type_ == kAstI64) {
-      i64++;
-    } else if (locals_.at(i).type_ == kAstF32) {
-      f32++;
-    } else if (locals_.at(i).type_ == kAstF64) {
-      f64++;
-    }
-  }
-  e->local_i32_count_ = i32;
-  e->local_i64_count_ = i64;
-  e->local_f32_count_ = f32;
-  e->local_f64_count_ = f64;
-  f64 = param + i32 + i64 + f32;
-  f32 = param + i32 + i64;
-  i64 = param + i32;
-  i32 = param;
-  param = 0;
-  for (size_t i = 0; i < locals_.size(); i++) {
-    if (locals_.at(i).param_) {
-      e->params_.push_back(locals_.at(i).type_);
-      var_index[i] = param++;
-    } else if (locals_.at(i).type_ == kAstI32) {
-      var_index[i] = i32++;
-    } else if (locals_.at(i).type_ == kAstI64) {
-      var_index[i] = i64++;
-    } else if (locals_.at(i).type_ == kAstF32) {
-      var_index[i] = f32++;
-    } else if (locals_.at(i).type_ == kAstF64) {
-      var_index[i] = f64++;
-    }
+    buffer.write(&body_[0], body_.size());
   }
 }
 
-
-WasmFunctionEncoder::WasmFunctionEncoder(Zone* zone, LocalType return_type,
-                                         bool exported, bool external)
-    : params_(zone),
-      exported_(exported),
-      external_(external),
-      body_(zone),
-      name_(zone) {}
-
-
-uint32_t WasmFunctionEncoder::HeaderSize() const {
-  uint32_t size = 3;
-  if (!external_) size += 2;
-  if (HasName()) {
-    uint32_t name_size = NameSize();
-    size += static_cast<uint32_t>(SizeOfVarInt(name_size)) + name_size;
-  }
-  return size;
-}
-
-
-uint32_t WasmFunctionEncoder::BodySize(void) const {
-  // TODO(titzer): embed a LocalDeclEncoder in the WasmFunctionEncoder
-  LocalDeclEncoder local_decl;
-  local_decl.AddLocals(local_i32_count_, kAstI32);
-  local_decl.AddLocals(local_i64_count_, kAstI64);
-  local_decl.AddLocals(local_f32_count_, kAstF32);
-  local_decl.AddLocals(local_f64_count_, kAstF64);
-
-  return external_ ? 0
-                   : static_cast<uint32_t>(body_.size() + local_decl.Size());
-}
-
-
-uint32_t WasmFunctionEncoder::NameSize() const {
-  return HasName() ? static_cast<uint32_t>(name_.size()) : 0;
-}
-
-
-void WasmFunctionEncoder::Serialize(byte* buffer, byte** header,
-                                    byte** body) const {
-  uint8_t decl_bits = (exported_ ? kDeclFunctionExport : 0) |
-                      (external_ ? kDeclFunctionImport : 0) |
-                      (HasName() ? kDeclFunctionName : 0);
-
-  EmitUint8(header, decl_bits);
-  EmitUint16(header, signature_index_);
-
-  if (HasName()) {
-    EmitVarInt(header, NameSize());
-    for (size_t i = 0; i < name_.size(); ++i) {
-      EmitUint8(header, name_[i]);
-    }
-  }
-
-
-  if (!external_) {
-    // TODO(titzer): embed a LocalDeclEncoder in the WasmFunctionEncoder
-    LocalDeclEncoder local_decl;
-    local_decl.AddLocals(local_i32_count_, kAstI32);
-    local_decl.AddLocals(local_i64_count_, kAstI64);
-    local_decl.AddLocals(local_f32_count_, kAstF32);
-    local_decl.AddLocals(local_f64_count_, kAstF64);
-
-    EmitUint16(header, static_cast<uint16_t>(body_.size() + local_decl.Size()));
-    (*header) += local_decl.Emit(*header);
-    if (body_.size() > 0) {
-      std::memcpy(*header, &body_[0], body_.size());
-      (*header) += body_.size();
-    }
-  }
-}
-
-
 WasmDataSegmentEncoder::WasmDataSegmentEncoder(Zone* zone, const byte* data,
                                                uint32_t size, uint32_t dest)
     : data_(zone), dest_(dest) {
-  for (size_t i = 0; i < size; i++) {
+  for (size_t i = 0; i < size; ++i) {
     data_.push_back(data[i]);
   }
 }
 
-
-uint32_t WasmDataSegmentEncoder::HeaderSize() const {
-  static const int kDataSegmentSize = 13;
-  return kDataSegmentSize;
-}
-
-
-uint32_t WasmDataSegmentEncoder::BodySize() const {
-  return static_cast<uint32_t>(data_.size());
-}
-
-
-void WasmDataSegmentEncoder::Serialize(byte* buffer, byte** header,
-                                       byte** body) const {
-  EmitVarInt(header, dest_);
-  EmitVarInt(header, static_cast<uint32_t>(data_.size()));
-
-  std::memcpy(*header, &data_[0], data_.size());
-  (*header) += data_.size();
+void WasmDataSegmentEncoder::Write(ZoneBuffer& buffer) const {
+  buffer.write_u32v(dest_);
+  buffer.write_u32v(static_cast<uint32_t>(data_.size()));
+  buffer.write(&data_[0], data_.size());
 }
 
 WasmModuleBuilder::WasmModuleBuilder(Zone* zone)
     : zone_(zone),
       signatures_(zone),
+      imports_(zone),
       functions_(zone),
       data_segments_(zone),
       indirect_functions_(zone),
@@ -436,12 +187,11 @@
       signature_map_(zone),
       start_function_index_(-1) {}
 
-uint16_t WasmModuleBuilder::AddFunction() {
-  functions_.push_back(new (zone_) WasmFunctionBuilder(zone_));
-  return static_cast<uint16_t>(functions_.size() - 1);
+uint32_t WasmModuleBuilder::AddFunction() {
+  functions_.push_back(new (zone_) WasmFunctionBuilder(this));
+  return static_cast<uint32_t>(functions_.size() - 1);
 }
 
-
 WasmFunctionBuilder* WasmModuleBuilder::FunctionAt(size_t index) {
   if (functions_.size() > index) {
     return functions_.at(index);
@@ -450,12 +200,10 @@
   }
 }
 
-
 void WasmModuleBuilder::AddDataSegment(WasmDataSegmentEncoder* data) {
   data_segments_.push_back(data);
 }
 
-
 bool WasmModuleBuilder::CompareFunctionSigs::operator()(FunctionSig* a,
                                                         FunctionSig* b) const {
   if (a->return_count() < b->return_count()) return true;
@@ -473,266 +221,161 @@
   return false;
 }
 
-
-uint16_t WasmModuleBuilder::AddSignature(FunctionSig* sig) {
+uint32_t WasmModuleBuilder::AddSignature(FunctionSig* sig) {
   SignatureMap::iterator pos = signature_map_.find(sig);
   if (pos != signature_map_.end()) {
     return pos->second;
   } else {
-    uint16_t index = static_cast<uint16_t>(signatures_.size());
+    uint32_t index = static_cast<uint32_t>(signatures_.size());
     signature_map_[sig] = index;
     signatures_.push_back(sig);
     return index;
   }
 }
 
-
-void WasmModuleBuilder::AddIndirectFunction(uint16_t index) {
+void WasmModuleBuilder::AddIndirectFunction(uint32_t index) {
   indirect_functions_.push_back(index);
 }
 
-void WasmModuleBuilder::MarkStartFunction(uint16_t index) {
+uint32_t WasmModuleBuilder::AddImport(const char* name, int name_length,
+                                      FunctionSig* sig) {
+  imports_.push_back({AddSignature(sig), name, name_length});
+  return static_cast<uint32_t>(imports_.size() - 1);
+}
+
+void WasmModuleBuilder::MarkStartFunction(uint32_t index) {
   start_function_index_ = index;
 }
 
-WasmModuleWriter* WasmModuleBuilder::Build(Zone* zone) {
-  WasmModuleWriter* writer = new (zone) WasmModuleWriter(zone);
-  for (auto function : functions_) {
-    writer->functions_.push_back(function->Build(zone, this));
-  }
-  for (auto segment : data_segments_) {
-    writer->data_segments_.push_back(segment);
-  }
-  for (auto sig : signatures_) {
-    writer->signatures_.push_back(sig);
-  }
-  for (auto index : indirect_functions_) {
-    writer->indirect_functions_.push_back(index);
-  }
-  for (auto global : globals_) {
-    writer->globals_.push_back(global);
-  }
-  writer->start_function_index_ = start_function_index_;
-  return writer;
-}
-
-
 uint32_t WasmModuleBuilder::AddGlobal(MachineType type, bool exported) {
   globals_.push_back(std::make_pair(type, exported));
   return static_cast<uint32_t>(globals_.size() - 1);
 }
 
+void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
+  uint32_t exports = 0;
 
-WasmModuleWriter::WasmModuleWriter(Zone* zone)
-    : functions_(zone),
-      data_segments_(zone),
-      signatures_(zone),
-      indirect_functions_(zone),
-      globals_(zone) {}
-
-struct Sizes {
-  size_t header_size;
-  size_t body_size;
-
-  size_t total() { return header_size + body_size; }
-
-  void Add(size_t header, size_t body) {
-    header_size += header;
-    body_size += body;
-  }
-
-  void AddSection(WasmSection::Code code, size_t other_size) {
-    Add(padded_varint + SizeOfVarInt(WasmSection::getNameLength(code)) +
-            WasmSection::getNameLength(code),
-        0);
-    if (other_size) Add(SizeOfVarInt(other_size), 0);
-  }
-};
-
-WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const {
-  Sizes sizes = {0, 0};
-
-  sizes.Add(2 * sizeof(uint32_t), 0);  // header
-
-  sizes.AddSection(WasmSection::Code::Memory, 0);
-  sizes.Add(kDeclMemorySize, 0);
-  TRACE("Size after memory: %u, %u\n", (unsigned)sizes.header_size,
-        (unsigned)sizes.body_size);
-
-  if (globals_.size() > 0) {
-    sizes.AddSection(WasmSection::Code::Globals, globals_.size());
-    /* These globals never have names, so are always 3 bytes. */
-    sizes.Add(3 * globals_.size(), 0);
-    TRACE("Size after globals: %u, %u\n", (unsigned)sizes.header_size,
-          (unsigned)sizes.body_size);
-  }
-
-  if (signatures_.size() > 0) {
-    sizes.AddSection(WasmSection::Code::Signatures, signatures_.size());
-    for (auto sig : signatures_) {
-      sizes.Add(
-          1 + SizeOfVarInt(sig->parameter_count()) + sig->parameter_count(), 0);
-    }
-    TRACE("Size after signatures: %u, %u\n", (unsigned)sizes.header_size,
-          (unsigned)sizes.body_size);
-  }
-
-  if (functions_.size() > 0) {
-    sizes.AddSection(WasmSection::Code::Functions, functions_.size());
-    for (auto function : functions_) {
-      sizes.Add(function->HeaderSize() + function->BodySize(),
-                function->NameSize());
-    }
-    TRACE("Size after functions: %u, %u\n", (unsigned)sizes.header_size,
-          (unsigned)sizes.body_size);
-  }
-
-  if (start_function_index_ >= 0) {
-    sizes.AddSection(WasmSection::Code::StartFunction, 0);
-    sizes.Add(SizeOfVarInt(start_function_index_), 0);
-    TRACE("Size after start: %u, %u\n", (unsigned)sizes.header_size,
-          (unsigned)sizes.body_size);
-  }
-
-  if (data_segments_.size() > 0) {
-    sizes.AddSection(WasmSection::Code::DataSegments, data_segments_.size());
-    for (auto segment : data_segments_) {
-      sizes.Add(segment->HeaderSize(), segment->BodySize());
-    }
-    TRACE("Size after data segments: %u, %u\n", (unsigned)sizes.header_size,
-          (unsigned)sizes.body_size);
-  }
-
-  if (indirect_functions_.size() > 0) {
-    sizes.AddSection(WasmSection::Code::FunctionTable,
-                     indirect_functions_.size());
-    for (auto function_index : indirect_functions_) {
-      sizes.Add(SizeOfVarInt(function_index), 0);
-    }
-    TRACE("Size after indirect functions: %u, %u\n",
-          (unsigned)sizes.header_size, (unsigned)sizes.body_size);
-  }
-
-  if (sizes.body_size > 0) {
-    sizes.AddSection(WasmSection::Code::End, 0);
-    TRACE("Size after end: %u, %u\n", (unsigned)sizes.header_size,
-          (unsigned)sizes.body_size);
-  }
-
-  ZoneVector<uint8_t> buffer_vector(sizes.total(), zone);
-  byte* buffer = &buffer_vector[0];
-  byte* header = buffer;
-  byte* body = buffer + sizes.header_size;
-
-  // -- emit magic -------------------------------------------------------------
+  // == Emit magic =============================================================
   TRACE("emit magic\n");
-  EmitUint32(&header, kWasmMagic);
-  EmitUint32(&header, kWasmVersion);
+  buffer.write_u32(kWasmMagic);
+  buffer.write_u32(kWasmVersion);
 
-  // -- emit memory declaration ------------------------------------------------
-  {
-    byte* section = EmitSection(WasmSection::Code::Memory, &header);
-    EmitVarInt(&header, 16);  // min memory size
-    EmitVarInt(&header, 16);  // max memory size
-    EmitUint8(&header, 0);    // memory export
-    static_assert(kDeclMemorySize == 3, "memory size must match emit above");
-    FixupSection(section, header);
-  }
-
-  // -- emit globals -----------------------------------------------------------
-  if (globals_.size() > 0) {
-    byte* section = EmitSection(WasmSection::Code::Globals, &header);
-    EmitVarInt(&header, globals_.size());
-
-    for (auto global : globals_) {
-      EmitVarInt(&header, 0);  // Length of the global name.
-      EmitUint8(&header, WasmOpcodes::MemTypeCodeFor(global.first));
-      EmitUint8(&header, global.second);
-    }
-    FixupSection(section, header);
-  }
-
-  // -- emit signatures --------------------------------------------------------
+  // == Emit signatures ========================================================
   if (signatures_.size() > 0) {
-    byte* section = EmitSection(WasmSection::Code::Signatures, &header);
-    EmitVarInt(&header, signatures_.size());
+    size_t start = EmitSection(WasmSection::Code::Signatures, buffer);
+    buffer.write_size(signatures_.size());
 
     for (FunctionSig* sig : signatures_) {
-      EmitVarInt(&header, sig->parameter_count());
-      if (sig->return_count() > 0) {
-        EmitUint8(&header, WasmOpcodes::LocalTypeCodeFor(sig->GetReturn()));
-      } else {
-        EmitUint8(&header, kLocalVoid);
-      }
+      buffer.write_u8(kWasmFunctionTypeForm);
+      buffer.write_size(sig->parameter_count());
       for (size_t j = 0; j < sig->parameter_count(); j++) {
-        EmitUint8(&header, WasmOpcodes::LocalTypeCodeFor(sig->GetParam(j)));
+        buffer.write_u8(WasmOpcodes::LocalTypeCodeFor(sig->GetParam(j)));
+      }
+      buffer.write_size(sig->return_count());
+      for (size_t j = 0; j < sig->return_count(); j++) {
+        buffer.write_u8(WasmOpcodes::LocalTypeCodeFor(sig->GetReturn(j)));
       }
     }
-    FixupSection(section, header);
+    FixupSection(buffer, start);
   }
 
-  // -- emit functions ---------------------------------------------------------
+  // == Emit globals ===========================================================
+  if (globals_.size() > 0) {
+    size_t start = EmitSection(WasmSection::Code::Globals, buffer);
+    buffer.write_size(globals_.size());
+
+    for (auto global : globals_) {
+      buffer.write_u32v(0);  // Length of the global name.
+      buffer.write_u8(WasmOpcodes::MemTypeCodeFor(global.first));
+      buffer.write_u8(global.second);
+    }
+    FixupSection(buffer, start);
+  }
+
+  // == Emit imports ===========================================================
+  if (imports_.size() > 0) {
+    size_t start = EmitSection(WasmSection::Code::ImportTable, buffer);
+    buffer.write_size(imports_.size());
+    for (auto import : imports_) {
+      buffer.write_u32v(import.sig_index);
+      buffer.write_u32v(import.name_length);
+      buffer.write(reinterpret_cast<const byte*>(import.name),
+                   import.name_length);
+      buffer.write_u32v(0);
+    }
+    FixupSection(buffer, start);
+  }
+
+  // == Emit function signatures ===============================================
   if (functions_.size() > 0) {
-    byte* section = EmitSection(WasmSection::Code::Functions, &header);
-    EmitVarInt(&header, functions_.size());
-
-    for (auto func : functions_) {
-      func->Serialize(buffer, &header, &body);
+    size_t start = EmitSection(WasmSection::Code::FunctionSignatures, buffer);
+    buffer.write_size(functions_.size());
+    for (auto function : functions_) {
+      function->WriteSignature(buffer);
+      if (function->exported()) exports++;
     }
-    FixupSection(section, header);
+    FixupSection(buffer, start);
   }
 
-  // -- emit start function index ----------------------------------------------
-  if (start_function_index_ >= 0) {
-    byte* section = EmitSection(WasmSection::Code::StartFunction, &header);
-    EmitVarInt(&header, start_function_index_);
-    FixupSection(section, header);
-  }
-
-  // -- emit data segments -----------------------------------------------------
-  if (data_segments_.size() > 0) {
-    byte* section = EmitSection(WasmSection::Code::DataSegments, &header);
-    EmitVarInt(&header, data_segments_.size());
-
-    for (auto segment : data_segments_) {
-      segment->Serialize(buffer, &header, &body);
-    }
-    FixupSection(section, header);
-  }
-
-  // -- emit function table ----------------------------------------------------
+  // == emit function table ====================================================
   if (indirect_functions_.size() > 0) {
-    byte* section = EmitSection(WasmSection::Code::FunctionTable, &header);
-    EmitVarInt(&header, indirect_functions_.size());
+    size_t start = EmitSection(WasmSection::Code::FunctionTable, buffer);
+    buffer.write_size(indirect_functions_.size());
 
     for (auto index : indirect_functions_) {
-      EmitVarInt(&header, index);
+      buffer.write_u32v(index);
     }
-    FixupSection(section, header);
+    FixupSection(buffer, start);
   }
 
-  if (sizes.body_size > 0) {
-    byte* section = EmitSection(WasmSection::Code::End, &header);
-    FixupSection(section, header);
+  // == emit memory declaration ================================================
+  {
+    size_t start = EmitSection(WasmSection::Code::Memory, buffer);
+    buffer.write_u32v(16);  // min memory size
+    buffer.write_u32v(16);  // max memory size
+    buffer.write_u8(0);     // memory export
+    static_assert(kDeclMemorySize == 3, "memory size must match emit above");
+    FixupSection(buffer, start);
   }
 
-  return new (zone) WasmModuleIndex(buffer, buffer + sizes.total());
-}
-
-
-std::vector<uint8_t> UnsignedLEB128From(uint32_t result) {
-  std::vector<uint8_t> output;
-  uint8_t next = 0;
-  int shift = 0;
-  do {
-    next = static_cast<uint8_t>(result >> shift);
-    if (((result >> shift) & 0xFFFFFF80) != 0) {
-      next = next | 0x80;
+  // == emit exports ===========================================================
+  if (exports > 0) {
+    size_t start = EmitSection(WasmSection::Code::ExportTable, buffer);
+    buffer.write_u32v(exports);
+    uint32_t index = 0;
+    for (auto function : functions_) {
+      function->WriteExport(buffer, index++);
     }
-    output.push_back(next);
-    shift += 7;
-  } while ((next & 0x80) != 0);
-  return output;
+    FixupSection(buffer, start);
+  }
+
+  // == emit start function index ==============================================
+  if (start_function_index_ >= 0) {
+    size_t start = EmitSection(WasmSection::Code::StartFunction, buffer);
+    buffer.write_u32v(start_function_index_);
+    FixupSection(buffer, start);
+  }
+
+  // == emit code ==============================================================
+  if (functions_.size() > 0) {
+    size_t start = EmitSection(WasmSection::Code::FunctionBodies, buffer);
+    buffer.write_size(functions_.size());
+    for (auto function : functions_) {
+      function->WriteBody(buffer);
+    }
+    FixupSection(buffer, start);
+  }
+
+  // == emit data segments =====================================================
+  if (data_segments_.size() > 0) {
+    size_t start = EmitSection(WasmSection::Code::DataSegments, buffer);
+    buffer.write_size(data_segments_.size());
+
+    for (auto segment : data_segments_) {
+      segment->Write(buffer);
+    }
+    FixupSection(buffer, start);
+  }
 }
 }  // namespace wasm
 }  // namespace internal
diff --git a/src/wasm/encoder.h b/src/wasm/encoder.h
index 49a7bf7..19fc397 100644
--- a/src/wasm/encoder.h
+++ b/src/wasm/encoder.h
@@ -10,6 +10,8 @@
 
 #include "src/base/smart-pointers.h"
 
+#include "src/wasm/leb-helper.h"
+#include "src/wasm/wasm-macro-gen.h"
 #include "src/wasm/wasm-module.h"
 #include "src/wasm/wasm-opcodes.h"
 #include "src/wasm/wasm-result.h"
@@ -18,137 +20,198 @@
 namespace internal {
 namespace wasm {
 
-class WasmModuleBuilder;
-
-class WasmFunctionEncoder : public ZoneObject {
+class ZoneBuffer : public ZoneObject {
  public:
-  uint32_t HeaderSize() const;
-  uint32_t BodySize() const;
-  uint32_t NameSize() const;
-  void Serialize(byte* buffer, byte** header, byte** body) const;
+  static const uint32_t kInitialSize = 4096;
+  explicit ZoneBuffer(Zone* zone, size_t initial = kInitialSize)
+      : zone_(zone), buffer_(reinterpret_cast<byte*>(zone->New(initial))) {
+    pos_ = buffer_;
+    end_ = buffer_ + initial;
+  }
+
+  void write_u8(uint8_t x) {
+    EnsureSpace(1);
+    *(pos_++) = x;
+  }
+
+  void write_u16(uint16_t x) {
+    EnsureSpace(2);
+#if V8_TARGET_LITTLE_ENDIAN
+    WriteUnalignedUInt16(pos_, x);
+#else
+    pos_[0] = x & 0xff;
+    pos_[1] = (x >> 8) & 0xff;
+#endif
+    pos_ += 2;
+  }
+
+  void write_u32(uint32_t x) {
+    EnsureSpace(4);
+#if V8_TARGET_LITTLE_ENDIAN
+    WriteUnalignedUInt32(pos_, x);
+#else
+    pos_[0] = x & 0xff;
+    pos_[1] = (x >> 8) & 0xff;
+    pos_[2] = (x >> 16) & 0xff;
+    pos_[3] = (x >> 24) & 0xff;
+#endif
+    pos_ += 4;
+  }
+
+  void write_u32v(uint32_t val) {
+    EnsureSpace(kMaxVarInt32Size);
+    LEBHelper::write_u32v(&pos_, val);
+  }
+
+  void write_size(size_t val) {
+    EnsureSpace(kMaxVarInt32Size);
+    DCHECK_EQ(val, static_cast<uint32_t>(val));
+    LEBHelper::write_u32v(&pos_, static_cast<uint32_t>(val));
+  }
+
+  void write(const byte* data, size_t size) {
+    EnsureSpace(size);
+    memcpy(pos_, data, size);
+    pos_ += size;
+  }
+
+  size_t reserve_u32v() {
+    size_t off = offset();
+    EnsureSpace(kMaxVarInt32Size);
+    pos_ += kMaxVarInt32Size;
+    return off;
+  }
+
+  // Patch a (padded) u32v at the given offset to be the given value.
+  void patch_u32v(size_t offset, uint32_t val) {
+    byte* ptr = buffer_ + offset;
+    for (size_t pos = 0; pos != kPaddedVarInt32Size; ++pos) {
+      uint32_t next = val >> 7;
+      byte out = static_cast<byte>(val & 0x7f);
+      if (pos != kPaddedVarInt32Size - 1) {
+        *(ptr++) = 0x80 | out;
+        val = next;
+      } else {
+        *(ptr++) = out;
+      }
+    }
+  }
+
+  size_t offset() { return static_cast<size_t>(pos_ - buffer_); }
+  size_t size() { return static_cast<size_t>(pos_ - buffer_); }
+  const byte* begin() { return buffer_; }
+  const byte* end() { return pos_; }
+
+  void EnsureSpace(size_t size) {
+    if ((pos_ + size) > end_) {
+      size_t new_size = 4096 + (end_ - buffer_) * 3;
+      byte* new_buffer = reinterpret_cast<byte*>(zone_->New(new_size));
+      memcpy(new_buffer, buffer_, (pos_ - buffer_));
+      pos_ = new_buffer + (pos_ - buffer_);
+      buffer_ = new_buffer;
+      end_ = new_buffer + new_size;
+    }
+  }
+
+  byte** pos_ptr() { return &pos_; }
 
  private:
-  WasmFunctionEncoder(Zone* zone, LocalType return_type, bool exported,
-                      bool external);
-  friend class WasmFunctionBuilder;
-  uint16_t signature_index_;
-  ZoneVector<LocalType> params_;
-  uint16_t local_i32_count_;
-  uint16_t local_i64_count_;
-  uint16_t local_f32_count_;
-  uint16_t local_f64_count_;
-  bool exported_;
-  bool external_;
-  ZoneVector<uint8_t> body_;
-  ZoneVector<char> name_;
-
-  bool HasName() const { return (exported_ || external_) && name_.size() > 0; }
+  Zone* zone_;
+  byte* buffer_;
+  byte* pos_;
+  byte* end_;
 };
 
+class WasmModuleBuilder;
+
 class WasmFunctionBuilder : public ZoneObject {
  public:
-  uint16_t AddParam(LocalType type);
-  uint16_t AddLocal(LocalType type);
-  void ReturnType(LocalType type);
+  // Building methods.
+  void SetSignature(FunctionSig* sig);
+  uint32_t AddLocal(LocalType type);
+  void EmitVarInt(uint32_t val);
   void EmitCode(const byte* code, uint32_t code_size);
-  void EmitCode(const byte* code, uint32_t code_size,
-                const uint32_t* local_indices, uint32_t indices_size);
   void Emit(WasmOpcode opcode);
+  void EmitGetLocal(uint32_t index);
+  void EmitSetLocal(uint32_t index);
+  void EmitI32Const(int32_t val);
   void EmitWithU8(WasmOpcode opcode, const byte immediate);
   void EmitWithU8U8(WasmOpcode opcode, const byte imm1, const byte imm2);
   void EmitWithVarInt(WasmOpcode opcode, uint32_t immediate);
-  uint32_t EmitEditableVarIntImmediate();
-  void EditVarIntImmediate(uint32_t offset, const uint32_t immediate);
-  void Exported(uint8_t flag);
-  void External(uint8_t flag);
-  void SetName(const unsigned char* name, int name_length);
-  WasmFunctionEncoder* Build(Zone* zone, WasmModuleBuilder* mb) const;
+  void SetExported();
+  void SetName(const char* name, int name_length);
+  bool exported() { return exported_; }
+
+  // Writing methods.
+  void WriteSignature(ZoneBuffer& buffer) const;
+  void WriteExport(ZoneBuffer& buffer, uint32_t func_index) const;
+  void WriteBody(ZoneBuffer& buffer) const;
 
  private:
-  explicit WasmFunctionBuilder(Zone* zone);
+  explicit WasmFunctionBuilder(WasmModuleBuilder* builder);
   friend class WasmModuleBuilder;
-  LocalType return_type_;
-  struct Type;
-  ZoneVector<Type> locals_;
-  uint8_t exported_;
-  uint8_t external_;
+  WasmModuleBuilder* builder_;
+  LocalDeclEncoder locals_;
+  uint32_t signature_index_;
+  bool exported_;
   ZoneVector<uint8_t> body_;
-  ZoneVector<uint32_t> local_indices_;
   ZoneVector<char> name_;
-  uint16_t AddVar(LocalType type, bool param);
-  void IndexVars(WasmFunctionEncoder* e, uint16_t* var_index) const;
 };
 
+// TODO(titzer): kill!
 class WasmDataSegmentEncoder : public ZoneObject {
  public:
   WasmDataSegmentEncoder(Zone* zone, const byte* data, uint32_t size,
                          uint32_t dest);
-  uint32_t HeaderSize() const;
-  uint32_t BodySize() const;
-  void Serialize(byte* buffer, byte** header, byte** body) const;
+  void Write(ZoneBuffer& buffer) const;
 
  private:
   ZoneVector<byte> data_;
   uint32_t dest_;
 };
 
-class WasmModuleIndex : public ZoneObject {
- public:
-  const byte* Begin() const { return begin_; }
-  const byte* End() const { return end_; }
-
- private:
-  friend class WasmModuleWriter;
-  WasmModuleIndex(const byte* begin, const byte* end)
-      : begin_(begin), end_(end) {}
-  const byte* begin_;
-  const byte* end_;
-};
-
-class WasmModuleWriter : public ZoneObject {
- public:
-  WasmModuleIndex* WriteTo(Zone* zone) const;
-
- private:
-  friend class WasmModuleBuilder;
-  explicit WasmModuleWriter(Zone* zone);
-  ZoneVector<WasmFunctionEncoder*> functions_;
-  ZoneVector<WasmDataSegmentEncoder*> data_segments_;
-  ZoneVector<FunctionSig*> signatures_;
-  ZoneVector<uint16_t> indirect_functions_;
-  ZoneVector<std::pair<MachineType, bool>> globals_;
-  int start_function_index_;
+struct WasmFunctionImport {
+  uint32_t sig_index;
+  const char* name;
+  int name_length;
 };
 
 class WasmModuleBuilder : public ZoneObject {
  public:
   explicit WasmModuleBuilder(Zone* zone);
-  uint16_t AddFunction();
+
+  // Building methods.
+  uint32_t AddFunction();
   uint32_t AddGlobal(MachineType type, bool exported);
   WasmFunctionBuilder* FunctionAt(size_t index);
   void AddDataSegment(WasmDataSegmentEncoder* data);
-  uint16_t AddSignature(FunctionSig* sig);
-  void AddIndirectFunction(uint16_t index);
-  void MarkStartFunction(uint16_t index);
-  WasmModuleWriter* Build(Zone* zone);
+  uint32_t AddSignature(FunctionSig* sig);
+  void AddIndirectFunction(uint32_t index);
+  void MarkStartFunction(uint32_t index);
+  uint32_t AddImport(const char* name, int name_length, FunctionSig* sig);
+
+  // Writing methods.
+  void WriteTo(ZoneBuffer& buffer) const;
 
   struct CompareFunctionSigs {
     bool operator()(FunctionSig* a, FunctionSig* b) const;
   };
-  typedef ZoneMap<FunctionSig*, uint16_t, CompareFunctionSigs> SignatureMap;
+  typedef ZoneMap<FunctionSig*, uint32_t, CompareFunctionSigs> SignatureMap;
+
+  Zone* zone() { return zone_; }
 
  private:
   Zone* zone_;
   ZoneVector<FunctionSig*> signatures_;
+  ZoneVector<WasmFunctionImport> imports_;
   ZoneVector<WasmFunctionBuilder*> functions_;
   ZoneVector<WasmDataSegmentEncoder*> data_segments_;
-  ZoneVector<uint16_t> indirect_functions_;
+  ZoneVector<uint32_t> indirect_functions_;
   ZoneVector<std::pair<MachineType, bool>> globals_;
   SignatureMap signature_map_;
   int start_function_index_;
 };
 
-std::vector<uint8_t> UnsignedLEB128From(uint32_t result);
 }  // namespace wasm
 }  // namespace internal
 }  // namespace v8
diff --git a/src/wasm/leb-helper.h b/src/wasm/leb-helper.h
new file mode 100644
index 0000000..0e4ba34
--- /dev/null
+++ b/src/wasm/leb-helper.h
@@ -0,0 +1,134 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_WASM_LEB_HELPER_H_
+#define V8_WASM_LEB_HELPER_H_
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+static const size_t kPaddedVarInt32Size = 5;
+static const size_t kMaxVarInt32Size = 5;
+
+class LEBHelper {
+ public:
+  // Write a 32-bit unsigned LEB to {dest}, updating {dest} to point after
+  // the last uint8_t written. No safety checks.
+  static void write_u32v(uint8_t** dest, uint32_t val) {
+    while (val >= 0x80) {
+      *((*dest)++) = static_cast<uint8_t>(0x80 | (val & 0x7F));
+      val >>= 7;
+    }
+    *((*dest)++) = static_cast<uint8_t>(val & 0x7F);
+  }
+
+  // Write a 32-bit signed LEB to {dest}, updating {dest} to point after
+  // the last uint8_t written. No safety checks.
+  static void write_i32v(uint8_t** dest, int32_t val) {
+    if (val >= 0) {
+      while (val >= 0x40) {  // prevent sign extension.
+        *((*dest)++) = static_cast<uint8_t>(0x80 | (val & 0x7F));
+        val >>= 7;
+      }
+      *((*dest)++) = static_cast<uint8_t>(val & 0xFF);
+    } else {
+      while ((val >> 6) != -1) {
+        *((*dest)++) = static_cast<uint8_t>(0x80 | (val & 0x7F));
+        val >>= 7;
+      }
+      *((*dest)++) = static_cast<uint8_t>(val & 0x7F);
+    }
+  }
+
+  // Write a 64-bit unsigned LEB to {dest}, updating {dest} to point after
+  // the last uint8_t written. No safety checks.
+  static void write_u64v(uint8_t** dest, uint64_t val) {
+    while (val >= 0x80) {
+      *((*dest)++) = static_cast<uint8_t>(0x80 | (val & 0x7F));
+      val >>= 7;
+    }
+    *((*dest)++) = static_cast<uint8_t>(val & 0x7F);
+  }
+
+  // Write a 64-bit signed LEB to {dest}, updating {dest} to point after
+  // the last uint8_t written. No safety checks.
+  static void write_i64v(uint8_t** dest, int64_t val) {
+    if (val >= 0) {
+      while (val >= 0x40) {  // prevent sign extension.
+        *((*dest)++) = static_cast<uint8_t>(0x80 | (val & 0x7F));
+        val >>= 7;
+      }
+      *((*dest)++) = static_cast<uint8_t>(val & 0xFF);
+    } else {
+      while ((val >> 6) != -1) {
+        *((*dest)++) = static_cast<uint8_t>(0x80 | (val & 0x7F));
+        val >>= 7;
+      }
+      *((*dest)++) = static_cast<uint8_t>(val & 0x7F);
+    }
+  }
+
+  // TODO(titzer): move core logic for decoding LEBs from decoder.h to here.
+
+  // Compute the size of {val} if emitted as an LEB32.
+  static inline size_t sizeof_u32v(size_t val) {
+    size_t size = 0;
+    do {
+      size++;
+      val = val >> 7;
+    } while (val > 0);
+    return size;
+  }
+
+  // Compute the size of {val} if emitted as an LEB32.
+  static inline size_t sizeof_i32v(int32_t val) {
+    size_t size = 1;
+    if (val >= 0) {
+      while (val >= 0x40) {  // prevent sign extension.
+        size++;
+        val >>= 7;
+      }
+    } else {
+      while ((val >> 6) != -1) {
+        size++;
+        val >>= 7;
+      }
+    }
+    return size;
+  }
+
+  // Compute the size of {val} if emitted as an unsigned LEB64.
+  static inline size_t sizeof_u64v(uint64_t val) {
+    size_t size = 0;
+    do {
+      size++;
+      val = val >> 7;
+    } while (val > 0);
+    return size;
+  }
+
+  // Compute the size of {val} if emitted as a signed LEB64.
+  static inline size_t sizeof_i64v(int64_t val) {
+    size_t size = 1;
+    if (val >= 0) {
+      while (val >= 0x40) {  // prevent sign extension.
+        size++;
+        val >>= 7;
+      }
+    } else {
+      while ((val >> 6) != -1) {
+        size++;
+        val >>= 7;
+      }
+    }
+    return size;
+  }
+};
+
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_WASM_LEB_HELPER_H_
diff --git a/src/wasm/module-decoder.cc b/src/wasm/module-decoder.cc
index 3e85a1b..c356eb8 100644
--- a/src/wasm/module-decoder.cc
+++ b/src/wasm/module-decoder.cc
@@ -25,6 +25,7 @@
 #define TRACE(...)
 #endif
 
+namespace {
 
 // The main logic for decoding the bytes of a module.
 class ModuleDecoder : public Decoder {
@@ -79,9 +80,8 @@
     module->mem_external = false;
     module->origin = origin_;
 
-    bool sections[(size_t)WasmSection::Code::Max] = {false};
-
     const byte* pos = pc_;
+    int current_order = 0;
     uint32_t magic_word = consume_u32("wasm magic");
 #define BYTES(x) (x & 0xff), (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff
     if (magic_word != kWasmMagic) {
@@ -109,91 +109,85 @@
       TRACE("DecodeSection\n");
       pos = pc_;
 
-      int length;
-      uint32_t section_length = consume_u32v(&length, "section size");
-
-      int section_string_leb_length = 0;
-      uint32_t section_string_length = 0;
-      WasmSection::Code section = consume_section_name(
-          &section_string_leb_length, &section_string_length);
-      uint32_t string_and_leb_length =
-          section_string_leb_length + section_string_length;
-      if (string_and_leb_length > section_length) {
-        error(pos, pos,
-              "section string of size %u longer than total section bytes %u",
-              string_and_leb_length, section_length);
+      // Read the section name.
+      uint32_t string_length = consume_u32v("section name length");
+      const byte* section_name_start = pc_;
+      consume_bytes(string_length);
+      if (failed()) {
+        TRACE("Section name of length %u couldn't be read\n", string_length);
         break;
       }
 
-      if (section == WasmSection::Code::Max) {
-        // Skip unknown section.
-        uint32_t skip = section_length - string_and_leb_length;
-        TRACE("skipping %u bytes from unknown section\n", skip);
-        consume_bytes(skip);
-        continue;
-      }
+      TRACE("  +%d  section name        : \"%.*s\"\n",
+            static_cast<int>(section_name_start - start_),
+            string_length < 20 ? string_length : 20, section_name_start);
 
-      // Each section should appear at most once.
-      CheckForPreviousSection(sections, section, false);
-      sections[(size_t)section] = true;
+      WasmSection::Code section =
+          WasmSection::lookup(section_name_start, string_length);
+
+      // Read and check the section size.
+      uint32_t section_length = consume_u32v("section length");
+      if (!checkAvailable(section_length)) {
+        // The section would extend beyond the end of the module.
+        break;
+      }
+      const byte* section_start = pc_;
+      const byte* expected_section_end = pc_ + section_length;
+
+      current_order = CheckSectionOrder(current_order, section);
 
       switch (section) {
         case WasmSection::Code::End:
           // Terminate section decoding.
           limit_ = pc_;
           break;
-        case WasmSection::Code::Memory:
-          int length;
-          module->min_mem_pages = consume_u32v(&length, "min memory");
-          module->max_mem_pages = consume_u32v(&length, "max memory");
+        case WasmSection::Code::Memory: {
+          module->min_mem_pages = consume_u32v("min memory");
+          module->max_mem_pages = consume_u32v("max memory");
           module->mem_export = consume_u8("export memory") != 0;
           break;
+        }
         case WasmSection::Code::Signatures: {
-          int length;
-          uint32_t signatures_count = consume_u32v(&length, "signatures count");
+          uint32_t signatures_count = consume_u32v("signatures count");
           module->signatures.reserve(SafeReserve(signatures_count));
           // Decode signatures.
-          for (uint32_t i = 0; i < signatures_count; i++) {
+          for (uint32_t i = 0; i < signatures_count; ++i) {
             if (failed()) break;
             TRACE("DecodeSignature[%d] module+%d\n", i,
                   static_cast<int>(pc_ - start_));
-            FunctionSig* s = consume_sig();  // read function sig.
+            FunctionSig* s = consume_sig();
             module->signatures.push_back(s);
           }
           break;
         }
         case WasmSection::Code::FunctionSignatures: {
-          // Functions require a signature table first.
-          CheckForPreviousSection(sections, WasmSection::Code::Signatures,
-                                  true);
-          int length;
-          uint32_t functions_count = consume_u32v(&length, "functions count");
+          uint32_t functions_count = consume_u32v("functions count");
           module->functions.reserve(SafeReserve(functions_count));
-          for (uint32_t i = 0; i < functions_count; i++) {
-            module->functions.push_back(
-                {nullptr, i, 0, 0, 0, 0, 0, 0, false, false});
+          for (uint32_t i = 0; i < functions_count; ++i) {
+            module->functions.push_back({nullptr,  // sig
+                                         i,        // func_index
+                                         0,        // sig_index
+                                         0,        // name_offset
+                                         0,        // name_length
+                                         0,        // code_start_offset
+                                         0});      // code_end_offset
             WasmFunction* function = &module->functions.back();
             function->sig_index = consume_sig_index(module, &function->sig);
           }
           break;
         }
         case WasmSection::Code::FunctionBodies: {
-          // Function bodies should follow signatures.
-          CheckForPreviousSection(sections,
-                                  WasmSection::Code::FunctionSignatures, true);
-          int length;
           const byte* pos = pc_;
-          uint32_t functions_count = consume_u32v(&length, "functions count");
+          uint32_t functions_count = consume_u32v("functions count");
           if (functions_count != module->functions.size()) {
             error(pos, pos, "function body count %u mismatch (%u expected)",
                   functions_count,
                   static_cast<uint32_t>(module->functions.size()));
             break;
           }
-          for (uint32_t i = 0; i < functions_count; i++) {
+          for (uint32_t i = 0; i < functions_count; ++i) {
             WasmFunction* function = &module->functions[i];
-            int length;
-            uint32_t size = consume_u32v(&length, "body size");
+            uint32_t size = consume_u32v("body size");
             function->code_start_offset = pc_offset();
             function->code_end_offset = pc_offset() + size;
 
@@ -206,49 +200,9 @@
           }
           break;
         }
-        case WasmSection::Code::Functions: {
-          // Functions require a signature table first.
-          CheckForPreviousSection(sections, WasmSection::Code::Signatures,
-                                  true);
-          int length;
-          uint32_t functions_count = consume_u32v(&length, "functions count");
-          module->functions.reserve(SafeReserve(functions_count));
-          // Set up module environment for verification.
-          ModuleEnv menv;
-          menv.module = module;
-          menv.instance = nullptr;
-          menv.origin = origin_;
-          // Decode functions.
-          for (uint32_t i = 0; i < functions_count; i++) {
-            if (failed()) break;
-            TRACE("DecodeFunction[%d] module+%d\n", i,
-                  static_cast<int>(pc_ - start_));
-
-            module->functions.push_back(
-                {nullptr, i, 0, 0, 0, 0, 0, 0, false, false});
-            WasmFunction* function = &module->functions.back();
-            DecodeFunctionInModule(module, function, false);
-          }
-          if (ok() && verify_functions) {
-            for (uint32_t i = 0; i < functions_count; i++) {
-              if (failed()) break;
-              WasmFunction* function = &module->functions[i];
-              if (!function->external) {
-                VerifyFunctionBody(i, &menv, function);
-                if (result_.failed())
-                  error(result_.error_pc, result_.error_msg.get());
-              }
-            }
-          }
-          break;
-        }
         case WasmSection::Code::Names: {
-          // Names correspond to functions.
-          CheckForPreviousSection(sections,
-                                  WasmSection::Code::FunctionSignatures, true);
-          int length;
           const byte* pos = pc_;
-          uint32_t functions_count = consume_u32v(&length, "functions count");
+          uint32_t functions_count = consume_u32v("functions count");
           if (functions_count != module->functions.size()) {
             error(pos, pos, "function name count %u mismatch (%u expected)",
                   functions_count,
@@ -256,16 +210,15 @@
             break;
           }
 
-          for (uint32_t i = 0; i < functions_count; i++) {
+          for (uint32_t i = 0; i < functions_count; ++i) {
             WasmFunction* function = &module->functions[i];
             function->name_offset =
-                consume_string(&function->name_length, "function name");
+                consume_string(&function->name_length, false);
 
-            uint32_t local_names_count =
-                consume_u32v(&length, "local names count");
+            uint32_t local_names_count = consume_u32v("local names count");
             for (uint32_t j = 0; j < local_names_count; j++) {
               uint32_t unused = 0;
-              uint32_t offset = consume_string(&unused, "local name");
+              uint32_t offset = consume_string(&unused, false);
               USE(unused);
               USE(offset);
             }
@@ -273,11 +226,10 @@
           break;
         }
         case WasmSection::Code::Globals: {
-          int length;
-          uint32_t globals_count = consume_u32v(&length, "globals count");
+          uint32_t globals_count = consume_u32v("globals count");
           module->globals.reserve(SafeReserve(globals_count));
           // Decode globals.
-          for (uint32_t i = 0; i < globals_count; i++) {
+          for (uint32_t i = 0; i < globals_count; ++i) {
             if (failed()) break;
             TRACE("DecodeGlobal[%d] module+%d\n", i,
                   static_cast<int>(pc_ - start_));
@@ -288,40 +240,55 @@
           break;
         }
         case WasmSection::Code::DataSegments: {
-          int length;
-          uint32_t data_segments_count =
-              consume_u32v(&length, "data segments count");
+          uint32_t data_segments_count = consume_u32v("data segments count");
           module->data_segments.reserve(SafeReserve(data_segments_count));
           // Decode data segments.
-          for (uint32_t i = 0; i < data_segments_count; i++) {
+          for (uint32_t i = 0; i < data_segments_count; ++i) {
             if (failed()) break;
             TRACE("DecodeDataSegment[%d] module+%d\n", i,
                   static_cast<int>(pc_ - start_));
-            module->data_segments.push_back({0, 0, 0});
+            module->data_segments.push_back({0,        // dest_addr
+                                             0,        // source_offset
+                                             0,        // source_size
+                                             false});  // init
             WasmDataSegment* segment = &module->data_segments.back();
             DecodeDataSegmentInModule(module, segment);
           }
           break;
         }
+        case WasmSection::Code::FunctionTablePad: {
+          if (!FLAG_wasm_jit_prototype) {
+            error("FunctionTablePad section without jiting enabled");
+          }
+          // An indirect function table requires functions first.
+          module->indirect_table_size = consume_u32v("indirect entry count");
+          if (module->indirect_table_size > 0 &&
+              module->indirect_table_size < module->function_table.size()) {
+            error("more predefined indirect entries than table can hold");
+          }
+          break;
+        }
         case WasmSection::Code::FunctionTable: {
           // An indirect function table requires functions first.
           CheckForFunctions(module, section);
-          int length;
-          uint32_t function_table_count =
-              consume_u32v(&length, "function table count");
+          uint32_t function_table_count = consume_u32v("function table count");
           module->function_table.reserve(SafeReserve(function_table_count));
           // Decode function table.
-          for (uint32_t i = 0; i < function_table_count; i++) {
+          for (uint32_t i = 0; i < function_table_count; ++i) {
             if (failed()) break;
             TRACE("DecodeFunctionTable[%d] module+%d\n", i,
                   static_cast<int>(pc_ - start_));
-            uint16_t index = consume_u32v(&length);
+            uint16_t index = consume_u32v();
             if (index >= module->functions.size()) {
               error(pc_ - 2, "invalid function index");
               break;
             }
             module->function_table.push_back(index);
           }
+          if (module->indirect_table_size > 0 &&
+              module->indirect_table_size < module->function_table.size()) {
+            error("more predefined indirect entries than table can hold");
+          }
           break;
         }
         case WasmSection::Code::StartFunction: {
@@ -341,63 +308,109 @@
           break;
         }
         case WasmSection::Code::ImportTable: {
-          // Declares an import table.
-          CheckForPreviousSection(sections, WasmSection::Code::Signatures,
-                                  true);
-          int length;
-          uint32_t import_table_count =
-              consume_u32v(&length, "import table count");
+          uint32_t import_table_count = consume_u32v("import table count");
           module->import_table.reserve(SafeReserve(import_table_count));
           // Decode import table.
-          for (uint32_t i = 0; i < import_table_count; i++) {
+          for (uint32_t i = 0; i < import_table_count; ++i) {
             if (failed()) break;
             TRACE("DecodeImportTable[%d] module+%d\n", i,
                   static_cast<int>(pc_ - start_));
 
-            module->import_table.push_back({nullptr, 0, 0});
+            module->import_table.push_back({nullptr,  // sig
+                                            0,        // sig_index
+                                            0,        // module_name_offset
+                                            0,        // module_name_length
+                                            0,        // function_name_offset
+                                            0});      // function_name_length
             WasmImport* import = &module->import_table.back();
 
             import->sig_index = consume_sig_index(module, &import->sig);
             const byte* pos = pc_;
-            import->module_name_offset = consume_string(
-                &import->module_name_length, "import module name");
+            import->module_name_offset =
+                consume_string(&import->module_name_length, true);
             if (import->module_name_length == 0) {
               error(pos, "import module name cannot be NULL");
             }
-            import->function_name_offset = consume_string(
-                &import->function_name_length, "import function name");
+            import->function_name_offset =
+                consume_string(&import->function_name_length, true);
           }
           break;
         }
         case WasmSection::Code::ExportTable: {
           // Declares an export table.
           CheckForFunctions(module, section);
-          int length;
-          uint32_t export_table_count =
-              consume_u32v(&length, "export table count");
+          uint32_t export_table_count = consume_u32v("export table count");
           module->export_table.reserve(SafeReserve(export_table_count));
           // Decode export table.
-          for (uint32_t i = 0; i < export_table_count; i++) {
+          for (uint32_t i = 0; i < export_table_count; ++i) {
             if (failed()) break;
             TRACE("DecodeExportTable[%d] module+%d\n", i,
                   static_cast<int>(pc_ - start_));
 
-            module->export_table.push_back({0, 0});
+            module->export_table.push_back({0,    // func_index
+                                            0,    // name_offset
+                                            0});  // name_length
             WasmExport* exp = &module->export_table.back();
 
             WasmFunction* func;
             exp->func_index = consume_func_index(module, &func);
-            exp->name_offset = consume_string(&exp->name_length, "export name");
+            exp->name_offset = consume_string(&exp->name_length, true);
+          }
+          // Check for duplicate exports.
+          if (ok() && module->export_table.size() > 1) {
+            std::vector<WasmExport> sorted_exports(module->export_table);
+            const byte* base = start_;
+            auto cmp_less = [base](const WasmExport& a, const WasmExport& b) {
+              // Return true if a < b.
+              uint32_t len = a.name_length;
+              if (len != b.name_length) return len < b.name_length;
+              return memcmp(base + a.name_offset, base + b.name_offset, len) <
+                     0;
+            };
+            std::stable_sort(sorted_exports.begin(), sorted_exports.end(),
+                             cmp_less);
+            auto it = sorted_exports.begin();
+            WasmExport* last = &*it++;
+            for (auto end = sorted_exports.end(); it != end; last = &*it++) {
+              DCHECK(!cmp_less(*it, *last));  // Vector must be sorted.
+              if (!cmp_less(*last, *it)) {
+                const byte* pc = start_ + it->name_offset;
+                error(pc, pc,
+                      "Duplicate export name '%.*s' for functions %d and %d",
+                      it->name_length, pc, last->func_index, it->func_index);
+                break;
+              }
+            }
           }
           break;
         }
         case WasmSection::Code::Max:
-          UNREACHABLE();  // Already skipped unknown sections.
+          // Skip unknown sections.
+          TRACE("Unknown section: '");
+          for (uint32_t i = 0; i != string_length; ++i) {
+            TRACE("%c", *(section_name_start + i));
+          }
+          TRACE("'\n");
+          consume_bytes(section_length);
+          break;
+      }
+
+      if (pc_ != expected_section_end) {
+        const char* diff = pc_ < expected_section_end ? "shorter" : "longer";
+        size_t expected_length = static_cast<size_t>(section_length);
+        size_t actual_length = static_cast<size_t>(pc_ - section_start);
+        error(pc_, pc_,
+              "section \"%s\" %s (%zu bytes) than specified (%zu bytes)",
+              WasmSection::getName(section), diff, actual_length,
+              expected_length);
+        break;
       }
     }
 
   done:
-    ModuleResult result = toResult(module);
+    if (ok()) CalculateGlobalsOffsets(module);
+    const WasmModule* finished_module = module;
+    ModuleResult result = toResult(finished_module);
     if (FLAG_dump_wasm_module) {
       DumpModule(module, result);
     }
@@ -417,17 +430,18 @@
     }
   }
 
-  void CheckForPreviousSection(bool* sections, WasmSection::Code section,
-                               bool present) {
-    if (section >= WasmSection::Code::Max) return;
-    if (sections[(size_t)section] == present) return;
-    if (present) {
-      error(pc_ - 1, nullptr, "required %s section missing",
-            WasmSection::getName(section));
-    } else {
-      error(pc_ - 1, nullptr, "%s section already present",
+  int CheckSectionOrder(int current_order, WasmSection::Code section) {
+    int next_order = WasmSection::getOrder(section);
+    if (next_order == 0) return current_order;
+    if (next_order == current_order) {
+      error(pc_, pc_, "section \"%s\" already defined",
             WasmSection::getName(section));
     }
+    if (next_order < current_order) {
+      error(pc_, pc_, "section \"%s\" out of order",
+            WasmSection::getName(section));
+    }
+    return next_order;
   }
 
   // Decodes a single anonymous function starting at {start_}.
@@ -439,8 +453,6 @@
     function->name_length = 0;                // ---- name length
     function->code_start_offset = off(pc_);   // ---- code start
     function->code_end_offset = off(limit_);  // ---- code end
-    function->exported = false;               // ---- exported
-    function->external = false;               // ---- external
 
     if (ok()) VerifyFunctionBody(0, module_env, function);
 
@@ -466,69 +478,16 @@
 
   // Decodes a single global entry inside a module starting at {pc_}.
   void DecodeGlobalInModule(WasmGlobal* global) {
-    global->name_offset = consume_string(&global->name_length, "global name");
+    global->name_offset = consume_string(&global->name_length, false);
+    if (!unibrow::Utf8::Validate(start_ + global->name_offset,
+                                 global->name_length)) {
+      error("global name is not valid utf8");
+    }
     global->type = mem_type();
     global->offset = 0;
     global->exported = consume_u8("exported") != 0;
   }
 
-  // Decodes a single function entry inside a module starting at {pc_}.
-  // TODO(titzer): legacy function body; remove
-  void DecodeFunctionInModule(WasmModule* module, WasmFunction* function,
-                              bool verify_body = true) {
-    byte decl_bits = consume_u8("function decl");
-
-    const byte* sigpos = pc_;
-    function->sig_index = consume_u16("signature index");
-
-    if (function->sig_index >= module->signatures.size()) {
-      return error(sigpos, "invalid signature index");
-    } else {
-      function->sig = module->signatures[function->sig_index];
-    }
-
-    TRACE("  +%d  <function attributes:%s%s%s%s%s>\n",
-          static_cast<int>(pc_ - start_),
-          decl_bits & kDeclFunctionName ? " name" : "",
-          decl_bits & kDeclFunctionImport ? " imported" : "",
-          decl_bits & kDeclFunctionLocals ? " locals" : "",
-          decl_bits & kDeclFunctionExport ? " exported" : "",
-          (decl_bits & kDeclFunctionImport) == 0 ? " body" : "");
-
-    if (decl_bits & kDeclFunctionName) {
-      function->name_offset =
-          consume_string(&function->name_length, "function name");
-    }
-
-    function->exported = decl_bits & kDeclFunctionExport;
-
-    // Imported functions have no locals or body.
-    if (decl_bits & kDeclFunctionImport) {
-      function->external = true;
-      return;
-    }
-
-    if (decl_bits & kDeclFunctionLocals) {
-      function->local_i32_count = consume_u16("i32 count");
-      function->local_i64_count = consume_u16("i64 count");
-      function->local_f32_count = consume_u16("f32 count");
-      function->local_f64_count = consume_u16("f64 count");
-    }
-
-    uint16_t size = consume_u16("body size");
-    if (ok()) {
-      if ((pc_ + size) > limit_) {
-        return error(pc_, limit_,
-                     "expected %d bytes for function body, fell off end", size);
-      }
-      function->code_start_offset = static_cast<uint32_t>(pc_ - start_);
-      function->code_end_offset = function->code_start_offset + size;
-      TRACE("  +%d  %-20s: (%d bytes)\n", static_cast<int>(pc_ - start_),
-            "function body", size);
-      pc_ += size;
-    }
-  }
-
   bool IsWithinLimit(uint32_t limit, uint32_t offset, uint32_t size) {
     if (offset > limit) return false;
     if ((offset + size) < offset) return false;  // overflow
@@ -538,9 +497,8 @@
   // Decodes a single data segment entry inside a module starting at {pc_}.
   void DecodeDataSegmentInModule(WasmModule* module, WasmDataSegment* segment) {
     const byte* start = pc_;
-    int length;
-    segment->dest_addr = consume_u32v(&length, "destination");
-    segment->source_size = consume_u32v(&length, "source size");
+    segment->dest_addr = consume_u32v("destination");
+    segment->source_size = consume_u32v("source size");
     segment->source_offset = static_cast<uint32_t>(pc_ - start_);
     segment->init = true;
 
@@ -563,14 +521,29 @@
     consume_bytes(segment->source_size);
   }
 
+  // Calculate individual global offsets and total size of globals table.
+  void CalculateGlobalsOffsets(WasmModule* module) {
+    uint32_t offset = 0;
+    if (module->globals.size() == 0) {
+      module->globals_size = 0;
+      return;
+    }
+    for (WasmGlobal& global : module->globals) {
+      byte size = WasmOpcodes::MemSize(global.type);
+      offset = (offset + size - 1) & ~(size - 1);  // align
+      global.offset = offset;
+      offset += size;
+    }
+    module->globals_size = offset;
+  }
+
   // Verifies the body (code) of a given function.
   void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv,
                           WasmFunction* function) {
-    if (FLAG_trace_wasm_decode_time) {
+    if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) {
       OFStream os(stdout);
       os << "Verifying WASM function " << WasmFunctionName(function, menv)
          << std::endl;
-      os << std::endl;
     }
     FunctionBody body = {menv, function->sig, start_,
                          start_ + function->code_start_offset,
@@ -606,19 +579,20 @@
 
   // Reads a length-prefixed string, checking that it is within bounds. Returns
   // the offset of the string, and the length as an out parameter.
-  uint32_t consume_string(uint32_t* length, const char* name = nullptr) {
-    int varint_length;
-    *length = consume_u32v(&varint_length, "string length");
+  uint32_t consume_string(uint32_t* length, bool validate_utf8) {
+    *length = consume_u32v("string length");
     uint32_t offset = pc_offset();
     TRACE("  +%u  %-20s: (%u bytes)\n", offset, "string", *length);
+    if (validate_utf8 && !unibrow::Utf8::Validate(pc_, *length)) {
+      error(pc_, "no valid UTF-8 string");
+    }
     consume_bytes(*length);
     return offset;
   }
 
   uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
     const byte* pos = pc_;
-    int length;
-    uint32_t sig_index = consume_u32v(&length, "signature index");
+    uint32_t sig_index = consume_u32v("signature index");
     if (sig_index >= module->signatures.size()) {
       error(pos, pos, "signature index %u out of bounds (%d signatures)",
             sig_index, static_cast<int>(module->signatures.size()));
@@ -631,8 +605,7 @@
 
   uint32_t consume_func_index(WasmModule* module, WasmFunction** func) {
     const byte* pos = pc_;
-    int length;
-    uint32_t func_index = consume_u32v(&length, "function index");
+    uint32_t func_index = consume_u32v("function index");
     if (func_index >= module->functions.size()) {
       error(pos, pos, "function index %u out of bounds (%d functions)",
             func_index, static_cast<int>(module->functions.size()));
@@ -643,30 +616,6 @@
     return func_index;
   }
 
-  // Reads a section name.
-  WasmSection::Code consume_section_name(int* string_leb_length,
-                                         uint32_t* string_length) {
-    *string_length = consume_u32v(string_leb_length, "name length");
-    const byte* start = pc_;
-    consume_bytes(*string_length);
-    if (failed()) {
-      TRACE("Section name of length %u couldn't be read\n", *string_length);
-      return WasmSection::Code::Max;
-    }
-    // TODO(jfb) Linear search, it may be better to do a common-prefix search.
-    for (WasmSection::Code i = WasmSection::begin(); i != WasmSection::end();
-         i = WasmSection::next(i)) {
-      if (WasmSection::getNameLength(i) == *string_length &&
-          0 == memcmp(WasmSection::getName(i), start, *string_length)) {
-        return i;
-      }
-    }
-    TRACE("Unknown section: '");
-    for (uint32_t i = 0; i != *string_length; ++i) TRACE("%c", *(start + i));
-    TRACE("'\n");
-    return WasmSection::Code::Max;
-  }
-
   // Reads a single 8-bit integer, interpreting it as a local type.
   LocalType consume_local_type() {
     byte val = consume_u8("local type");
@@ -713,30 +662,58 @@
         return MachineType::Float32();
       case kMemF64:
         return MachineType::Float64();
+      case kMemS128:
+        return MachineType::Simd128();
       default:
         error(pc_ - 1, "invalid memory type");
         return MachineType::None();
     }
   }
 
-  // Parses an inline function signature.
+  // Parses a type entry, which is currently limited to functions only.
   FunctionSig* consume_sig() {
-    int length;
-    byte count = consume_u32v(&length, "param count");
-    LocalType ret = consume_local_type();
-    FunctionSig::Builder builder(module_zone, ret == kAstStmt ? 0 : 1, count);
-    if (ret != kAstStmt) builder.AddReturn(ret);
-
-    for (int i = 0; i < count; i++) {
+    const byte* pos = pc_;
+    byte form = consume_u8("type form");
+    if (form != kWasmFunctionTypeForm) {
+      error(pos, pos, "expected function type form (0x%02x), got: 0x%02x",
+            kWasmFunctionTypeForm, form);
+      return nullptr;
+    }
+    // parse parameter types
+    uint32_t param_count = consume_u32v("param count");
+    std::vector<LocalType> params;
+    for (uint32_t i = 0; i < param_count; ++i) {
       LocalType param = consume_local_type();
       if (param == kAstStmt) error(pc_ - 1, "invalid void parameter type");
-      builder.AddParam(param);
+      params.push_back(param);
     }
-    return builder.Build();
+
+    // parse return types
+    const byte* pt = pc_;
+    uint32_t return_count = consume_u32v("return count");
+    if (return_count > kMaxReturnCount) {
+      error(pt, pt, "return count of %u exceeds maximum of %u", return_count,
+            kMaxReturnCount);
+      return nullptr;
+    }
+    std::vector<LocalType> returns;
+    for (uint32_t i = 0; i < return_count; ++i) {
+      LocalType ret = consume_local_type();
+      if (ret == kAstStmt) error(pc_ - 1, "invalid void return type");
+      returns.push_back(ret);
+    }
+
+    // FunctionSig stores the return types first.
+    LocalType* buffer =
+        module_zone->NewArray<LocalType>(param_count + return_count);
+    uint32_t b = 0;
+    for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i];
+    for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i];
+
+    return new (module_zone) FunctionSig(return_count, param_count, buffer);
   }
 };
 
-
 // Helpers for nice error messages.
 class ModuleError : public ModuleResult {
  public:
@@ -750,7 +727,6 @@
   }
 };
 
-
 // Helpers for nice error messages.
 class FunctionError : public FunctionResult {
  public:
@@ -764,37 +740,111 @@
   }
 };
 
+Vector<const byte> FindSection(const byte* module_start, const byte* module_end,
+                               WasmSection::Code code) {
+  Decoder decoder(module_start, module_end);
+
+  uint32_t magic_word = decoder.consume_u32("wasm magic");
+  if (magic_word != kWasmMagic) decoder.error("wrong magic word");
+
+  uint32_t magic_version = decoder.consume_u32("wasm version");
+  if (magic_version != kWasmVersion) decoder.error("wrong wasm version");
+
+  while (decoder.more() && decoder.ok()) {
+    // Read the section name.
+    uint32_t string_length = decoder.consume_u32v("section name length");
+    const byte* section_name_start = decoder.pc();
+    decoder.consume_bytes(string_length);
+    if (decoder.failed()) break;
+
+    WasmSection::Code section =
+        WasmSection::lookup(section_name_start, string_length);
+
+    // Read and check the section size.
+    uint32_t section_length = decoder.consume_u32v("section length");
+
+    const byte* section_start = decoder.pc();
+    decoder.consume_bytes(section_length);
+    if (section == code && decoder.ok()) {
+      return Vector<const uint8_t>(section_start, section_length);
+    }
+  }
+
+  return Vector<const uint8_t>();
+}
+
+}  // namespace
+
 ModuleResult DecodeWasmModule(Isolate* isolate, Zone* zone,
                               const byte* module_start, const byte* module_end,
                               bool verify_functions, ModuleOrigin origin) {
+  size_t decode_memory_start = zone->allocation_size();
+  HistogramTimerScope wasm_decode_module_time_scope(
+      isolate->counters()->wasm_decode_module_time());
   size_t size = module_end - module_start;
   if (module_start > module_end) return ModuleError("start > end");
   if (size >= kMaxModuleSize) return ModuleError("size > maximum module size");
+  // TODO(bradnelson): Improve histogram handling of size_t.
+  isolate->counters()->wasm_module_size_bytes()->AddSample(
+      static_cast<int>(size));
   WasmModule* module = new WasmModule();
   ModuleDecoder decoder(zone, module_start, module_end, origin);
-  return decoder.DecodeModule(module, verify_functions);
+  ModuleResult result = decoder.DecodeModule(module, verify_functions);
+  // TODO(bradnelson): Improve histogram handling of size_t.
+  isolate->counters()->wasm_decode_module_peak_memory_bytes()->AddSample(
+      static_cast<int>(zone->allocation_size() - decode_memory_start));
+  return result;
 }
 
-
 FunctionSig* DecodeWasmSignatureForTesting(Zone* zone, const byte* start,
                                            const byte* end) {
   ModuleDecoder decoder(zone, start, end, kWasmOrigin);
   return decoder.DecodeFunctionSignature(start);
 }
 
-
 FunctionResult DecodeWasmFunction(Isolate* isolate, Zone* zone,
                                   ModuleEnv* module_env,
                                   const byte* function_start,
                                   const byte* function_end) {
+  HistogramTimerScope wasm_decode_function_time_scope(
+      isolate->counters()->wasm_decode_function_time());
   size_t size = function_end - function_start;
   if (function_start > function_end) return FunctionError("start > end");
   if (size > kMaxFunctionSize)
     return FunctionError("size > maximum function size");
+  isolate->counters()->wasm_function_size_bytes()->AddSample(
+      static_cast<int>(size));
   WasmFunction* function = new WasmFunction();
   ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin);
   return decoder.DecodeSingleFunction(module_env, function);
 }
+
+FunctionOffsetsResult DecodeWasmFunctionOffsets(const byte* module_start,
+                                                const byte* module_end) {
+  Vector<const byte> code_section =
+      FindSection(module_start, module_end, WasmSection::Code::FunctionBodies);
+  Decoder decoder(code_section.start(), code_section.end());
+  if (!code_section.start()) decoder.error("no code section");
+
+  uint32_t functions_count = decoder.consume_u32v("functions count");
+  FunctionOffsets table;
+  // Take care of invalid input here.
+  if (functions_count < static_cast<unsigned>(code_section.length()) / 2)
+    table.reserve(functions_count);
+  int section_offset = static_cast<int>(code_section.start() - module_start);
+  DCHECK_LE(0, section_offset);
+  for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
+    uint32_t size = decoder.consume_u32v("body size");
+    int offset = static_cast<int>(section_offset + decoder.pc_offset());
+    table.push_back(std::make_pair(offset, static_cast<int>(size)));
+    DCHECK(table.back().first >= 0 && table.back().second >= 0);
+    decoder.consume_bytes(size);
+  }
+  if (decoder.more()) decoder.error("unexpected additional bytes");
+
+  return decoder.toResult(std::move(table));
+}
+
 }  // namespace wasm
 }  // namespace internal
 }  // namespace v8
diff --git a/src/wasm/module-decoder.h b/src/wasm/module-decoder.h
index 00a9b87..dd6bd3b 100644
--- a/src/wasm/module-decoder.h
+++ b/src/wasm/module-decoder.h
@@ -26,6 +26,13 @@
 FunctionResult DecodeWasmFunction(Isolate* isolate, Zone* zone, ModuleEnv* env,
                                   const byte* function_start,
                                   const byte* function_end);
+
+// Extracts the function offset table from the wasm module bytes.
+// Returns a vector with <offset, length> entries, or failure if the wasm bytes
+// are detected as invalid. Note that this validation is not complete.
+FunctionOffsetsResult DecodeWasmFunctionOffsets(const byte* module_start,
+                                                const byte* module_end);
+
 }  // namespace wasm
 }  // namespace internal
 }  // namespace v8
diff --git a/src/wasm/switch-logic.cc b/src/wasm/switch-logic.cc
new file mode 100644
index 0000000..9ebc0b3
--- /dev/null
+++ b/src/wasm/switch-logic.cc
@@ -0,0 +1,63 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/wasm/switch-logic.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+namespace {
+CaseNode* CreateBst(ZoneVector<CaseNode*>* nodes, size_t begin, size_t end) {
+  if (end < begin) {
+    return nullptr;
+  } else if (end == begin) {
+    return nodes->at(begin);
+  } else {
+    size_t root_index = (begin + end) / 2;
+    CaseNode* root = nodes->at(root_index);
+    if (root_index != 0) {
+      root->left = CreateBst(nodes, begin, root_index - 1);
+    }
+    root->right = CreateBst(nodes, root_index + 1, end);
+    return root;
+  }
+}
+}  // namespace
+
+CaseNode* OrderCases(ZoneVector<int>* cases, Zone* zone) {
+  const int max_distance = 2;
+  const int min_size = 4;
+  if (cases->empty()) {
+    return nullptr;
+  }
+  std::sort(cases->begin(), cases->end());
+  ZoneVector<size_t> table_breaks(zone);
+  for (size_t i = 1; i < cases->size(); ++i) {
+    if (cases->at(i) - cases->at(i - 1) > max_distance) {
+      table_breaks.push_back(i);
+    }
+  }
+  table_breaks.push_back(cases->size());
+  ZoneVector<CaseNode*> nodes(zone);
+  size_t curr_pos = 0;
+  for (size_t i = 0; i < table_breaks.size(); ++i) {
+    size_t break_pos = table_breaks[i];
+    if (break_pos - curr_pos >= min_size) {
+      int begin = cases->at(curr_pos);
+      int end = cases->at(break_pos - 1);
+      nodes.push_back(new (zone) CaseNode(begin, end));
+      curr_pos = break_pos;
+    } else {
+      for (; curr_pos < break_pos; curr_pos++) {
+        nodes.push_back(new (zone)
+                            CaseNode(cases->at(curr_pos), cases->at(curr_pos)));
+      }
+    }
+  }
+  return CreateBst(&nodes, 0, nodes.size() - 1);
+}
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
diff --git a/src/wasm/switch-logic.h b/src/wasm/switch-logic.h
new file mode 100644
index 0000000..8cef08b
--- /dev/null
+++ b/src/wasm/switch-logic.h
@@ -0,0 +1,31 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_WASM_SWITCH_LOGIC_H
+#define V8_WASM_SWITCH_LOGIC_H
+
+#include "src/zone-containers.h"
+#include "src/zone.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+struct CaseNode : public ZoneObject {
+  const int begin;
+  const int end;
+  CaseNode* left;
+  CaseNode* right;
+  CaseNode(int begin, int end) : begin(begin), end(end) {
+    left = nullptr;
+    right = nullptr;
+  }
+};
+
+CaseNode* OrderCases(ZoneVector<int>* cases, Zone* zone);
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
+
+#endif
diff --git a/src/wasm/wasm-debug.cc b/src/wasm/wasm-debug.cc
new file mode 100644
index 0000000..5b9c2cb
--- /dev/null
+++ b/src/wasm/wasm-debug.cc
@@ -0,0 +1,185 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/wasm/wasm-debug.h"
+
+#include "src/assert-scope.h"
+#include "src/debug/debug.h"
+#include "src/factory.h"
+#include "src/isolate.h"
+#include "src/wasm/module-decoder.h"
+#include "src/wasm/wasm-module.h"
+
+using namespace v8::internal;
+using namespace v8::internal::wasm;
+
+namespace {
+
+enum {
+  kWasmDebugInfoWasmObj,
+  kWasmDebugInfoWasmBytesHash,
+  kWasmDebugInfoFunctionByteOffsets,
+  kWasmDebugInfoNumEntries
+};
+
+ByteArray *GetOrCreateFunctionOffsetTable(Handle<WasmDebugInfo> debug_info) {
+  Object *offset_table = debug_info->get(kWasmDebugInfoFunctionByteOffsets);
+  Isolate *isolate = debug_info->GetIsolate();
+  if (!offset_table->IsUndefined(isolate)) return ByteArray::cast(offset_table);
+
+  FunctionOffsetsResult function_offsets;
+  {
+    DisallowHeapAllocation no_gc;
+    SeqOneByteString *wasm_bytes =
+        wasm::GetWasmBytes(debug_info->wasm_object());
+    const byte *bytes_start = wasm_bytes->GetChars();
+    const byte *bytes_end = bytes_start + wasm_bytes->length();
+    function_offsets = wasm::DecodeWasmFunctionOffsets(bytes_start, bytes_end);
+  }
+  DCHECK(function_offsets.ok());
+  size_t array_size = 2 * kIntSize * function_offsets.val.size();
+  CHECK_LE(array_size, static_cast<size_t>(kMaxInt));
+  ByteArray *arr =
+      *isolate->factory()->NewByteArray(static_cast<int>(array_size));
+  int idx = 0;
+  for (std::pair<int, int> p : function_offsets.val) {
+    arr->set_int(idx++, p.first);
+    arr->set_int(idx++, p.second);
+  }
+  DCHECK_EQ(arr->length(), idx * kIntSize);
+  debug_info->set(kWasmDebugInfoFunctionByteOffsets, arr);
+
+  return arr;
+}
+
+std::pair<int, int> GetFunctionOffsetAndLength(Handle<WasmDebugInfo> debug_info,
+                                               int func_index) {
+  ByteArray *arr = GetOrCreateFunctionOffsetTable(debug_info);
+  DCHECK(func_index >= 0 && func_index < arr->length() / kIntSize / 2);
+
+  int offset = arr->get_int(2 * func_index);
+  int length = arr->get_int(2 * func_index + 1);
+  // Assert that it's distinguishable from the "illegal function index" return.
+  DCHECK(offset > 0 && length > 0);
+  return {offset, length};
+}
+
+Vector<const uint8_t> GetFunctionBytes(Handle<WasmDebugInfo> debug_info,
+                                       int func_index) {
+  SeqOneByteString *module_bytes =
+      wasm::GetWasmBytes(debug_info->wasm_object());
+  std::pair<int, int> offset_and_length =
+      GetFunctionOffsetAndLength(debug_info, func_index);
+  return Vector<const uint8_t>(
+      module_bytes->GetChars() + offset_and_length.first,
+      offset_and_length.second);
+}
+
+}  // namespace
+
+Handle<WasmDebugInfo> WasmDebugInfo::New(Handle<JSObject> wasm) {
+  Isolate *isolate = wasm->GetIsolate();
+  Factory *factory = isolate->factory();
+  Handle<FixedArray> arr =
+      factory->NewFixedArray(kWasmDebugInfoNumEntries, TENURED);
+  arr->set(kWasmDebugInfoWasmObj, *wasm);
+  int hash = 0;
+  Handle<SeqOneByteString> wasm_bytes(GetWasmBytes(*wasm), isolate);
+  {
+    DisallowHeapAllocation no_gc;
+    hash = StringHasher::HashSequentialString(
+        wasm_bytes->GetChars(), wasm_bytes->length(), kZeroHashSeed);
+  }
+  Handle<Object> hash_obj = factory->NewNumberFromInt(hash, TENURED);
+  arr->set(kWasmDebugInfoWasmBytesHash, *hash_obj);
+
+  return Handle<WasmDebugInfo>::cast(arr);
+}
+
+bool WasmDebugInfo::IsDebugInfo(Object *object) {
+  if (!object->IsFixedArray()) return false;
+  FixedArray *arr = FixedArray::cast(object);
+  Isolate *isolate = arr->GetIsolate();
+  return arr->length() == kWasmDebugInfoNumEntries &&
+         IsWasmObject(arr->get(kWasmDebugInfoWasmObj)) &&
+         arr->get(kWasmDebugInfoWasmBytesHash)->IsNumber() &&
+         (arr->get(kWasmDebugInfoFunctionByteOffsets)->IsUndefined(isolate) ||
+          arr->get(kWasmDebugInfoFunctionByteOffsets)->IsByteArray());
+}
+
+WasmDebugInfo *WasmDebugInfo::cast(Object *object) {
+  DCHECK(IsDebugInfo(object));
+  return reinterpret_cast<WasmDebugInfo *>(object);
+}
+
+JSObject *WasmDebugInfo::wasm_object() {
+  return JSObject::cast(get(kWasmDebugInfoWasmObj));
+}
+
+bool WasmDebugInfo::SetBreakPoint(int byte_offset) {
+  // TODO(clemensh): Implement this.
+  return false;
+}
+
+Handle<String> WasmDebugInfo::DisassembleFunction(
+    Handle<WasmDebugInfo> debug_info, int func_index) {
+  std::ostringstream disassembly_os;
+
+  {
+    Vector<const uint8_t> bytes_vec = GetFunctionBytes(debug_info, func_index);
+    DisallowHeapAllocation no_gc;
+
+    base::AccountingAllocator allocator;
+    bool ok = PrintAst(
+        &allocator, FunctionBodyForTesting(bytes_vec.start(), bytes_vec.end()),
+        disassembly_os, nullptr);
+    DCHECK(ok);
+    USE(ok);
+  }
+
+  // Unfortunately, we have to copy the string here.
+  std::string code_str = disassembly_os.str();
+  CHECK_LE(code_str.length(), static_cast<size_t>(kMaxInt));
+  Factory *factory = debug_info->GetIsolate()->factory();
+  Vector<const char> code_vec(code_str.data(),
+                              static_cast<int>(code_str.length()));
+  return factory->NewStringFromAscii(code_vec).ToHandleChecked();
+}
+
+Handle<FixedArray> WasmDebugInfo::GetFunctionOffsetTable(
+    Handle<WasmDebugInfo> debug_info, int func_index) {
+  class NullBuf : public std::streambuf {};
+  NullBuf null_buf;
+  std::ostream null_stream(&null_buf);
+
+  std::vector<std::tuple<uint32_t, int, int>> offset_table_vec;
+
+  {
+    Vector<const uint8_t> bytes_vec = GetFunctionBytes(debug_info, func_index);
+    DisallowHeapAllocation no_gc;
+
+    v8::base::AccountingAllocator allocator;
+    bool ok = PrintAst(
+        &allocator, FunctionBodyForTesting(bytes_vec.start(), bytes_vec.end()),
+        null_stream, &offset_table_vec);
+    DCHECK(ok);
+    USE(ok);
+  }
+
+  size_t arr_size = 3 * offset_table_vec.size();
+  CHECK_LE(arr_size, static_cast<size_t>(kMaxInt));
+  Factory *factory = debug_info->GetIsolate()->factory();
+  Handle<FixedArray> offset_table =
+      factory->NewFixedArray(static_cast<int>(arr_size), TENURED);
+
+  int idx = 0;
+  for (std::tuple<uint32_t, int, int> elem : offset_table_vec) {
+    offset_table->set(idx++, Smi::FromInt(std::get<0>(elem)));
+    offset_table->set(idx++, Smi::FromInt(std::get<1>(elem)));
+    offset_table->set(idx++, Smi::FromInt(std::get<2>(elem)));
+  }
+  DCHECK_EQ(idx, offset_table->length());
+
+  return offset_table;
+}
diff --git a/src/wasm/wasm-debug.h b/src/wasm/wasm-debug.h
new file mode 100644
index 0000000..48dc4be
--- /dev/null
+++ b/src/wasm/wasm-debug.h
@@ -0,0 +1,41 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_WASM_DEBUG_H_
+#define V8_WASM_DEBUG_H_
+
+#include "src/handles.h"
+#include "src/objects.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+class WasmDebugInfo : public FixedArray {
+ public:
+  static Handle<WasmDebugInfo> New(Handle<JSObject> wasm);
+
+  static bool IsDebugInfo(Object* object);
+  static WasmDebugInfo* cast(Object* object);
+
+  JSObject* wasm_object();
+
+  bool SetBreakPoint(int byte_offset);
+
+  // Disassemble the specified function from this module.
+  static Handle<String> DisassembleFunction(Handle<WasmDebugInfo> debug_info,
+                                            int func_index);
+
+  // Get the offset table for the specified function.
+  // Returns an array with three entries per instruction: byte offset, line and
+  // column.
+  static Handle<FixedArray> GetFunctionOffsetTable(
+      Handle<WasmDebugInfo> debug_info, int func_index);
+};
+
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_WASM_DEBUG_H_
diff --git a/src/wasm/wasm-external-refs.cc b/src/wasm/wasm-external-refs.cc
new file mode 100644
index 0000000..e155f3c
--- /dev/null
+++ b/src/wasm/wasm-external-refs.cc
@@ -0,0 +1,199 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <math.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <limits>
+
+#include "include/v8config.h"
+
+#include "src/base/bits.h"
+#include "src/wasm/wasm-external-refs.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+void f32_trunc_wrapper(float* param) { *param = truncf(*param); }
+
+void f32_floor_wrapper(float* param) { *param = floorf(*param); }
+
+void f32_ceil_wrapper(float* param) { *param = ceilf(*param); }
+
+void f32_nearest_int_wrapper(float* param) { *param = nearbyintf(*param); }
+
+void f64_trunc_wrapper(double* param) { *param = trunc(*param); }
+
+void f64_floor_wrapper(double* param) { *param = floor(*param); }
+
+void f64_ceil_wrapper(double* param) { *param = ceil(*param); }
+
+void f64_nearest_int_wrapper(double* param) { *param = nearbyint(*param); }
+
+void int64_to_float32_wrapper(int64_t* input, float* output) {
+  *output = static_cast<float>(*input);
+}
+
+void uint64_to_float32_wrapper(uint64_t* input, float* output) {
+#if V8_CC_MSVC
+  // With MSVC we use static_cast<float>(uint32_t) instead of
+  // static_cast<float>(uint64_t) to achieve round-to-nearest-ties-even
+  // semantics. The idea is to calculate
+  // static_cast<float>(high_word) * 2^32 + static_cast<float>(low_word). To
+  // achieve proper rounding in all cases we have to adjust the high_word
+  // with a "rounding bit" sometimes. The rounding bit is stored in the LSB of
+  // the high_word if the low_word may affect the rounding of the high_word.
+  uint32_t low_word = static_cast<uint32_t>(*input & 0xffffffff);
+  uint32_t high_word = static_cast<uint32_t>(*input >> 32);
+
+  float shift = static_cast<float>(1ull << 32);
+  // If the MSB of the high_word is set, then we make space for a rounding bit.
+  if (high_word < 0x80000000) {
+    high_word <<= 1;
+    shift = static_cast<float>(1ull << 31);
+  }
+
+  if ((high_word & 0xfe000000) && low_word) {
+    // Set the rounding bit.
+    high_word |= 1;
+  }
+
+  float result = static_cast<float>(high_word);
+  result *= shift;
+  result += static_cast<float>(low_word);
+  *output = result;
+
+#else
+  *output = static_cast<float>(*input);
+#endif
+}
+
+void int64_to_float64_wrapper(int64_t* input, double* output) {
+  *output = static_cast<double>(*input);
+}
+
+void uint64_to_float64_wrapper(uint64_t* input, double* output) {
+#if V8_CC_MSVC
+  // With MSVC we use static_cast<double>(uint32_t) instead of
+  // static_cast<double>(uint64_t) to achieve round-to-nearest-ties-even
+  // semantics. The idea is to calculate
+  // static_cast<double>(high_word) * 2^32 + static_cast<double>(low_word).
+  uint32_t low_word = static_cast<uint32_t>(*input & 0xffffffff);
+  uint32_t high_word = static_cast<uint32_t>(*input >> 32);
+
+  double shift = static_cast<double>(1ull << 32);
+
+  double result = static_cast<double>(high_word);
+  result *= shift;
+  result += static_cast<double>(low_word);
+  *output = result;
+
+#else
+  *output = static_cast<double>(*input);
+#endif
+}
+
+int32_t float32_to_int64_wrapper(float* input, int64_t* output) {
+  // We use "<" here to check the upper bound because of rounding problems: With
+  // "<=" some inputs would be considered within int64 range which are actually
+  // not within int64 range.
+  if (*input >= static_cast<float>(std::numeric_limits<int64_t>::min()) &&
+      *input < static_cast<float>(std::numeric_limits<int64_t>::max())) {
+    *output = static_cast<int64_t>(*input);
+    return 1;
+  }
+  return 0;
+}
+
+int32_t float32_to_uint64_wrapper(float* input, uint64_t* output) {
+  // We use "<" here to check the upper bound because of rounding problems: With
+  // "<=" some inputs would be considered within uint64 range which are actually
+  // not within uint64 range.
+  if (*input > -1.0 &&
+      *input < static_cast<float>(std::numeric_limits<uint64_t>::max())) {
+    *output = static_cast<uint64_t>(*input);
+    return 1;
+  }
+  return 0;
+}
+
+int32_t float64_to_int64_wrapper(double* input, int64_t* output) {
+  // We use "<" here to check the upper bound because of rounding problems: With
+  // "<=" some inputs would be considered within int64 range which are actually
+  // not within int64 range.
+  if (*input >= static_cast<double>(std::numeric_limits<int64_t>::min()) &&
+      *input < static_cast<double>(std::numeric_limits<int64_t>::max())) {
+    *output = static_cast<int64_t>(*input);
+    return 1;
+  }
+  return 0;
+}
+
+int32_t float64_to_uint64_wrapper(double* input, uint64_t* output) {
+  // We use "<" here to check the upper bound because of rounding problems: With
+  // "<=" some inputs would be considered within uint64 range which are actually
+  // not within uint64 range.
+  if (*input > -1.0 &&
+      *input < static_cast<double>(std::numeric_limits<uint64_t>::max())) {
+    *output = static_cast<uint64_t>(*input);
+    return 1;
+  }
+  return 0;
+}
+
+int32_t int64_div_wrapper(int64_t* dst, int64_t* src) {
+  if (*src == 0) {
+    return 0;
+  }
+  if (*src == -1 && *dst == std::numeric_limits<int64_t>::min()) {
+    return -1;
+  }
+  *dst /= *src;
+  return 1;
+}
+
+int32_t int64_mod_wrapper(int64_t* dst, int64_t* src) {
+  if (*src == 0) {
+    return 0;
+  }
+  *dst %= *src;
+  return 1;
+}
+
+int32_t uint64_div_wrapper(uint64_t* dst, uint64_t* src) {
+  if (*src == 0) {
+    return 0;
+  }
+  *dst /= *src;
+  return 1;
+}
+
+int32_t uint64_mod_wrapper(uint64_t* dst, uint64_t* src) {
+  if (*src == 0) {
+    return 0;
+  }
+  *dst %= *src;
+  return 1;
+}
+
+uint32_t word32_ctz_wrapper(uint32_t* input) {
+  return static_cast<uint32_t>(base::bits::CountTrailingZeros32(*input));
+}
+
+uint32_t word64_ctz_wrapper(uint64_t* input) {
+  return static_cast<uint32_t>(base::bits::CountTrailingZeros64(*input));
+}
+
+uint32_t word32_popcnt_wrapper(uint32_t* input) {
+  return static_cast<uint32_t>(base::bits::CountPopulation(*input));
+}
+
+uint32_t word64_popcnt_wrapper(uint64_t* input) {
+  return static_cast<uint32_t>(base::bits::CountPopulation(*input));
+}
+
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
diff --git a/src/wasm/wasm-external-refs.h b/src/wasm/wasm-external-refs.h
index 4aa452b..ac938d6 100644
--- a/src/wasm/wasm-external-refs.h
+++ b/src/wasm/wasm-external-refs.h
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <stdint.h>
+
 #ifndef WASM_EXTERNAL_REFS_H
 #define WASM_EXTERNAL_REFS_H
 
@@ -9,173 +11,54 @@
 namespace internal {
 namespace wasm {
 
-static void f32_trunc_wrapper(float* param) { *param = truncf(*param); }
+void f32_trunc_wrapper(float* param);
 
-static void f32_floor_wrapper(float* param) { *param = floorf(*param); }
+void f32_floor_wrapper(float* param);
 
-static void f32_ceil_wrapper(float* param) { *param = ceilf(*param); }
+void f32_ceil_wrapper(float* param);
 
-static void f32_nearest_int_wrapper(float* param) {
-  *param = nearbyintf(*param);
-}
+void f32_nearest_int_wrapper(float* param);
 
-static void f64_trunc_wrapper(double* param) { *param = trunc(*param); }
+void f64_trunc_wrapper(double* param);
 
-static void f64_floor_wrapper(double* param) { *param = floor(*param); }
+void f64_floor_wrapper(double* param);
 
-static void f64_ceil_wrapper(double* param) { *param = ceil(*param); }
+void f64_ceil_wrapper(double* param);
 
-static void f64_nearest_int_wrapper(double* param) {
-  *param = nearbyint(*param);
-}
+void f64_nearest_int_wrapper(double* param);
 
-static void int64_to_float32_wrapper(int64_t* input, float* output) {
-  *output = static_cast<float>(*input);
-}
+void int64_to_float32_wrapper(int64_t* input, float* output);
 
-static void uint64_to_float32_wrapper(uint64_t* input, float* output) {
-#if V8_CC_MSVC
-  // With MSVC we use static_cast<float>(uint32_t) instead of
-  // static_cast<float>(uint64_t) to achieve round-to-nearest-ties-even
-  // semantics. The idea is to calculate
-  // static_cast<float>(high_word) * 2^32 + static_cast<float>(low_word). To
-  // achieve proper rounding in all cases we have to adjust the high_word
-  // with a "rounding bit" sometimes. The rounding bit is stored in the LSB of
-  // the high_word if the low_word may affect the rounding of the high_word.
-  uint32_t low_word = static_cast<uint32_t>(*input & 0xffffffff);
-  uint32_t high_word = static_cast<uint32_t>(*input >> 32);
+void uint64_to_float32_wrapper(uint64_t* input, float* output);
 
-  float shift = static_cast<float>(1ull << 32);
-  // If the MSB of the high_word is set, then we make space for a rounding bit.
-  if (high_word < 0x80000000) {
-    high_word <<= 1;
-    shift = static_cast<float>(1ull << 31);
-  }
+void int64_to_float64_wrapper(int64_t* input, double* output);
 
-  if ((high_word & 0xfe000000) && low_word) {
-    // Set the rounding bit.
-    high_word |= 1;
-  }
+void uint64_to_float64_wrapper(uint64_t* input, double* output);
 
-  float result = static_cast<float>(high_word);
-  result *= shift;
-  result += static_cast<float>(low_word);
-  *output = result;
+int32_t float32_to_int64_wrapper(float* input, int64_t* output);
 
-#else
-  *output = static_cast<float>(*input);
-#endif
-}
+int32_t float32_to_uint64_wrapper(float* input, uint64_t* output);
 
-static void int64_to_float64_wrapper(int64_t* input, double* output) {
-  *output = static_cast<double>(*input);
-}
+int32_t float64_to_int64_wrapper(double* input, int64_t* output);
 
-static void uint64_to_float64_wrapper(uint64_t* input, double* output) {
-#if V8_CC_MSVC
-  // With MSVC we use static_cast<double>(uint32_t) instead of
-  // static_cast<double>(uint64_t) to achieve round-to-nearest-ties-even
-  // semantics. The idea is to calculate
-  // static_cast<double>(high_word) * 2^32 + static_cast<double>(low_word).
-  uint32_t low_word = static_cast<uint32_t>(*input & 0xffffffff);
-  uint32_t high_word = static_cast<uint32_t>(*input >> 32);
+int32_t float64_to_uint64_wrapper(double* input, uint64_t* output);
 
-  double shift = static_cast<double>(1ull << 32);
+int32_t int64_div_wrapper(int64_t* dst, int64_t* src);
 
-  double result = static_cast<double>(high_word);
-  result *= shift;
-  result += static_cast<double>(low_word);
-  *output = result;
+int32_t int64_mod_wrapper(int64_t* dst, int64_t* src);
 
-#else
-  *output = static_cast<double>(*input);
-#endif
-}
+int32_t uint64_div_wrapper(uint64_t* dst, uint64_t* src);
 
-static int32_t float32_to_int64_wrapper(float* input, int64_t* output) {
-  // We use "<" here to check the upper bound because of rounding problems: With
-  // "<=" some inputs would be considered within int64 range which are actually
-  // not within int64 range.
-  if (*input >= static_cast<float>(std::numeric_limits<int64_t>::min()) &&
-      *input < static_cast<float>(std::numeric_limits<int64_t>::max())) {
-    *output = static_cast<int64_t>(*input);
-    return 1;
-  }
-  return 0;
-}
+int32_t uint64_mod_wrapper(uint64_t* dst, uint64_t* src);
 
-static int32_t float32_to_uint64_wrapper(float* input, uint64_t* output) {
-  // We use "<" here to check the upper bound because of rounding problems: With
-  // "<=" some inputs would be considered within uint64 range which are actually
-  // not within uint64 range.
-  if (*input > -1.0 &&
-      *input < static_cast<float>(std::numeric_limits<uint64_t>::max())) {
-    *output = static_cast<uint64_t>(*input);
-    return 1;
-  }
-  return 0;
-}
+uint32_t word32_ctz_wrapper(uint32_t* input);
 
-static int32_t float64_to_int64_wrapper(double* input, int64_t* output) {
-  // We use "<" here to check the upper bound because of rounding problems: With
-  // "<=" some inputs would be considered within int64 range which are actually
-  // not within int64 range.
-  if (*input >= static_cast<double>(std::numeric_limits<int64_t>::min()) &&
-      *input < static_cast<double>(std::numeric_limits<int64_t>::max())) {
-    *output = static_cast<int64_t>(*input);
-    return 1;
-  }
-  return 0;
-}
+uint32_t word64_ctz_wrapper(uint64_t* input);
 
-static int32_t float64_to_uint64_wrapper(double* input, uint64_t* output) {
-  // We use "<" here to check the upper bound because of rounding problems: With
-  // "<=" some inputs would be considered within uint64 range which are actually
-  // not within uint64 range.
-  if (*input > -1.0 &&
-      *input < static_cast<double>(std::numeric_limits<uint64_t>::max())) {
-    *output = static_cast<uint64_t>(*input);
-    return 1;
-  }
-  return 0;
-}
+uint32_t word32_popcnt_wrapper(uint32_t* input);
 
-static int32_t int64_div_wrapper(int64_t* dst, int64_t* src) {
-  if (*src == 0) {
-    return 0;
-  }
-  if (*src == -1 && *dst == std::numeric_limits<int64_t>::min()) {
-    return -1;
-  }
-  *dst /= *src;
-  return 1;
-}
-
-static int32_t int64_mod_wrapper(int64_t* dst, int64_t* src) {
-  if (*src == 0) {
-    return 0;
-  }
-  *dst %= *src;
-  return 1;
-}
-
-static int32_t uint64_div_wrapper(uint64_t* dst, uint64_t* src) {
-  if (*src == 0) {
-    return 0;
-  }
-  *dst /= *src;
-  return 1;
-}
-
-static int32_t uint64_mod_wrapper(uint64_t* dst, uint64_t* src) {
-  if (*src == 0) {
-    return 0;
-  }
-  *dst %= *src;
-  return 1;
-}
+uint32_t word64_popcnt_wrapper(uint64_t* input);
 }  // namespace wasm
 }  // namespace internal
 }  // namespace v8
-
 #endif
diff --git a/src/wasm/wasm-function-name-table.cc b/src/wasm/wasm-function-name-table.cc
new file mode 100644
index 0000000..32c302d
--- /dev/null
+++ b/src/wasm/wasm-function-name-table.cc
@@ -0,0 +1,71 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/wasm/wasm-function-name-table.h"
+
+#include "src/wasm/wasm-module.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+// Build an array with all function names. If there are N functions in the
+// module, then the first (kIntSize * (N+1)) bytes are integer entries.
+// The first integer entry encodes the number of functions in the module.
+// The entries 1 to N contain offsets into the second part of this array.
+// If a function is unnamed (not to be confused with an empty name), then the
+// integer entry is the negative offset of the next function name.
+// After these N+1 integer entries, the second part begins, which holds a
+// concatenation of all function names.
+Handle<ByteArray> BuildFunctionNamesTable(Isolate* isolate,
+                                          const WasmModule* module) {
+  uint64_t func_names_length = 0;
+  for (auto& func : module->functions) func_names_length += func.name_length;
+  int num_funcs_int = static_cast<int>(module->functions.size());
+  int current_offset = (num_funcs_int + 1) * kIntSize;
+  uint64_t total_array_length = current_offset + func_names_length;
+  int total_array_length_int = static_cast<int>(total_array_length);
+  // Check for overflow.
+  CHECK(total_array_length_int == total_array_length && num_funcs_int >= 0 &&
+        num_funcs_int == module->functions.size());
+  Handle<ByteArray> func_names_array =
+      isolate->factory()->NewByteArray(total_array_length_int, TENURED);
+  func_names_array->set_int(0, num_funcs_int);
+  int func_index = 0;
+  for (const WasmFunction& fun : module->functions) {
+    WasmName name = module->GetNameOrNull(&fun);
+    if (name.start() == nullptr) {
+      func_names_array->set_int(func_index + 1, -current_offset);
+    } else {
+      func_names_array->copy_in(current_offset,
+                                reinterpret_cast<const byte*>(name.start()),
+                                name.length());
+      func_names_array->set_int(func_index + 1, current_offset);
+      current_offset += name.length();
+    }
+    ++func_index;
+  }
+  return func_names_array;
+}
+
+MaybeHandle<String> GetWasmFunctionNameFromTable(
+    Handle<ByteArray> func_names_array, uint32_t func_index) {
+  uint32_t num_funcs = static_cast<uint32_t>(func_names_array->get_int(0));
+  DCHECK(static_cast<int>(num_funcs) >= 0);
+  Factory* factory = func_names_array->GetIsolate()->factory();
+  if (func_index >= num_funcs) return {};
+  int offset = func_names_array->get_int(func_index + 1);
+  if (offset < 0) return {};
+  int next_offset = func_index == num_funcs - 1
+                        ? func_names_array->length()
+                        : abs(func_names_array->get_int(func_index + 2));
+  ScopedVector<byte> buffer(next_offset - offset);
+  func_names_array->copy_out(offset, buffer.start(), next_offset - offset);
+  if (!unibrow::Utf8::Validate(buffer.start(), buffer.length())) return {};
+  return factory->NewStringFromUtf8(Vector<const char>::cast(buffer));
+}
+
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
diff --git a/src/wasm/wasm-function-name-table.h b/src/wasm/wasm-function-name-table.h
new file mode 100644
index 0000000..ffee782
--- /dev/null
+++ b/src/wasm/wasm-function-name-table.h
@@ -0,0 +1,33 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_WASM_FUNCTION_NAME_TABLE_H_
+#define V8_WASM_FUNCTION_NAME_TABLE_H_
+
+#include "src/handles.h"
+#include "src/objects.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+// Forward declarations for some WASM data structures.
+struct WasmModule;
+
+// Encode all function names of the WasmModule into one ByteArray.
+Handle<ByteArray> BuildFunctionNamesTable(Isolate* isolate,
+                                          const WasmModule* module);
+
+// Extract the function name for the given func_index from the function name
+// table.
+// Returns a null handle if the respective function is unnamed (not to be
+// confused with empty names) or the function name is not a valid UTF-8 string.
+MaybeHandle<String> GetWasmFunctionNameFromTable(
+    Handle<ByteArray> wasm_names_table, uint32_t func_index);
+
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_WASM_FUNCTION_NAME_TABLE_H_
diff --git a/src/wasm/wasm-interpreter.cc b/src/wasm/wasm-interpreter.cc
new file mode 100644
index 0000000..a88fa93
--- /dev/null
+++ b/src/wasm/wasm-interpreter.cc
@@ -0,0 +1,1830 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/wasm/wasm-interpreter.h"
+#include "src/wasm/ast-decoder.h"
+#include "src/wasm/decoder.h"
+#include "src/wasm/wasm-external-refs.h"
+#include "src/wasm/wasm-module.h"
+
+#include "src/base/accounting-allocator.h"
+#include "src/zone-containers.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+#if DEBUG
+#define TRACE(...)                                        \
+  do {                                                    \
+    if (FLAG_trace_wasm_interpreter) PrintF(__VA_ARGS__); \
+  } while (false)
+#else
+#define TRACE(...)
+#endif
+
+#define FOREACH_INTERNAL_OPCODE(V) V(Breakpoint, 0xFF)
+
+#define FOREACH_SIMPLE_BINOP(V) \
+  V(I32Add, uint32_t, +)        \
+  V(I32Sub, uint32_t, -)        \
+  V(I32Mul, uint32_t, *)        \
+  V(I32And, uint32_t, &)        \
+  V(I32Ior, uint32_t, |)        \
+  V(I32Xor, uint32_t, ^)        \
+  V(I32Eq, uint32_t, ==)        \
+  V(I32Ne, uint32_t, !=)        \
+  V(I32LtU, uint32_t, <)        \
+  V(I32LeU, uint32_t, <=)       \
+  V(I32GtU, uint32_t, >)        \
+  V(I32GeU, uint32_t, >=)       \
+  V(I32LtS, int32_t, <)         \
+  V(I32LeS, int32_t, <=)        \
+  V(I32GtS, int32_t, >)         \
+  V(I32GeS, int32_t, >=)        \
+  V(I64Add, uint64_t, +)        \
+  V(I64Sub, uint64_t, -)        \
+  V(I64Mul, uint64_t, *)        \
+  V(I64And, uint64_t, &)        \
+  V(I64Ior, uint64_t, |)        \
+  V(I64Xor, uint64_t, ^)        \
+  V(I64Eq, uint64_t, ==)        \
+  V(I64Ne, uint64_t, !=)        \
+  V(I64LtU, uint64_t, <)        \
+  V(I64LeU, uint64_t, <=)       \
+  V(I64GtU, uint64_t, >)        \
+  V(I64GeU, uint64_t, >=)       \
+  V(I64LtS, int64_t, <)         \
+  V(I64LeS, int64_t, <=)        \
+  V(I64GtS, int64_t, >)         \
+  V(I64GeS, int64_t, >=)        \
+  V(F32Add, float, +)           \
+  V(F32Mul, float, *)           \
+  V(F32Div, float, /)           \
+  V(F32Eq, float, ==)           \
+  V(F32Ne, float, !=)           \
+  V(F32Lt, float, <)            \
+  V(F32Le, float, <=)           \
+  V(F32Gt, float, >)            \
+  V(F32Ge, float, >=)           \
+  V(F64Add, double, +)          \
+  V(F64Mul, double, *)          \
+  V(F64Div, double, /)          \
+  V(F64Eq, double, ==)          \
+  V(F64Ne, double, !=)          \
+  V(F64Lt, double, <)           \
+  V(F64Le, double, <=)          \
+  V(F64Gt, double, >)           \
+  V(F64Ge, double, >=)
+
+#define FOREACH_OTHER_BINOP(V) \
+  V(I32DivS, int32_t)          \
+  V(I32DivU, uint32_t)         \
+  V(I32RemS, int32_t)          \
+  V(I32RemU, uint32_t)         \
+  V(I32Shl, uint32_t)          \
+  V(I32ShrU, uint32_t)         \
+  V(I32ShrS, int32_t)          \
+  V(I64DivS, int64_t)          \
+  V(I64DivU, uint64_t)         \
+  V(I64RemS, int64_t)          \
+  V(I64RemU, uint64_t)         \
+  V(I64Shl, uint64_t)          \
+  V(I64ShrU, uint64_t)         \
+  V(I64ShrS, int64_t)          \
+  V(I32Ror, int32_t)           \
+  V(I32Rol, int32_t)           \
+  V(I64Ror, int64_t)           \
+  V(I64Rol, int64_t)           \
+  V(F32Sub, float)             \
+  V(F32Min, float)             \
+  V(F32Max, float)             \
+  V(F32CopySign, float)        \
+  V(F64Min, double)            \
+  V(F64Max, double)            \
+  V(F64Sub, double)            \
+  V(F64CopySign, double)       \
+  V(I32AsmjsDivS, int32_t)     \
+  V(I32AsmjsDivU, uint32_t)    \
+  V(I32AsmjsRemS, int32_t)     \
+  V(I32AsmjsRemU, uint32_t)
+
+#define FOREACH_OTHER_UNOP(V)    \
+  V(I32Clz, uint32_t)            \
+  V(I32Ctz, uint32_t)            \
+  V(I32Popcnt, uint32_t)         \
+  V(I32Eqz, uint32_t)            \
+  V(I64Clz, uint64_t)            \
+  V(I64Ctz, uint64_t)            \
+  V(I64Popcnt, uint64_t)         \
+  V(I64Eqz, uint64_t)            \
+  V(F32Abs, float)               \
+  V(F32Neg, float)               \
+  V(F32Ceil, float)              \
+  V(F32Floor, float)             \
+  V(F32Trunc, float)             \
+  V(F32NearestInt, float)        \
+  V(F32Sqrt, float)              \
+  V(F64Abs, double)              \
+  V(F64Neg, double)              \
+  V(F64Ceil, double)             \
+  V(F64Floor, double)            \
+  V(F64Trunc, double)            \
+  V(F64NearestInt, double)       \
+  V(F64Sqrt, double)             \
+  V(I32SConvertF32, float)       \
+  V(I32SConvertF64, double)      \
+  V(I32UConvertF32, float)       \
+  V(I32UConvertF64, double)      \
+  V(I32ConvertI64, int64_t)      \
+  V(I64SConvertF32, float)       \
+  V(I64SConvertF64, double)      \
+  V(I64UConvertF32, float)       \
+  V(I64UConvertF64, double)      \
+  V(I64SConvertI32, int32_t)     \
+  V(I64UConvertI32, uint32_t)    \
+  V(F32SConvertI32, int32_t)     \
+  V(F32UConvertI32, uint32_t)    \
+  V(F32SConvertI64, int64_t)     \
+  V(F32UConvertI64, uint64_t)    \
+  V(F32ConvertF64, double)       \
+  V(F32ReinterpretI32, int32_t)  \
+  V(F64SConvertI32, int32_t)     \
+  V(F64UConvertI32, uint32_t)    \
+  V(F64SConvertI64, int64_t)     \
+  V(F64UConvertI64, uint64_t)    \
+  V(F64ConvertF32, float)        \
+  V(F64ReinterpretI64, int64_t)  \
+  V(I32ReinterpretF32, float)    \
+  V(I64ReinterpretF64, double)   \
+  V(I32AsmjsSConvertF32, float)  \
+  V(I32AsmjsUConvertF32, float)  \
+  V(I32AsmjsSConvertF64, double) \
+  V(I32AsmjsUConvertF64, double)
+
+static inline int32_t ExecuteI32DivS(int32_t a, int32_t b, TrapReason* trap) {
+  if (b == 0) {
+    *trap = kTrapDivByZero;
+    return 0;
+  }
+  if (b == -1 && a == std::numeric_limits<int32_t>::min()) {
+    *trap = kTrapDivUnrepresentable;
+    return 0;
+  }
+  return a / b;
+}
+
+static inline uint32_t ExecuteI32DivU(uint32_t a, uint32_t b,
+                                      TrapReason* trap) {
+  if (b == 0) {
+    *trap = kTrapDivByZero;
+    return 0;
+  }
+  return a / b;
+}
+
+static inline int32_t ExecuteI32RemS(int32_t a, int32_t b, TrapReason* trap) {
+  if (b == 0) {
+    *trap = kTrapRemByZero;
+    return 0;
+  }
+  if (b == -1) return 0;
+  return a % b;
+}
+
+static inline uint32_t ExecuteI32RemU(uint32_t a, uint32_t b,
+                                      TrapReason* trap) {
+  if (b == 0) {
+    *trap = kTrapRemByZero;
+    return 0;
+  }
+  return a % b;
+}
+
+static inline uint32_t ExecuteI32Shl(uint32_t a, uint32_t b, TrapReason* trap) {
+  return a << (b & 0x1f);
+}
+
+static inline uint32_t ExecuteI32ShrU(uint32_t a, uint32_t b,
+                                      TrapReason* trap) {
+  return a >> (b & 0x1f);
+}
+
+static inline int32_t ExecuteI32ShrS(int32_t a, int32_t b, TrapReason* trap) {
+  return a >> (b & 0x1f);
+}
+
+static inline int64_t ExecuteI64DivS(int64_t a, int64_t b, TrapReason* trap) {
+  if (b == 0) {
+    *trap = kTrapDivByZero;
+    return 0;
+  }
+  if (b == -1 && a == std::numeric_limits<int64_t>::min()) {
+    *trap = kTrapDivUnrepresentable;
+    return 0;
+  }
+  return a / b;
+}
+
+static inline uint64_t ExecuteI64DivU(uint64_t a, uint64_t b,
+                                      TrapReason* trap) {
+  if (b == 0) {
+    *trap = kTrapDivByZero;
+    return 0;
+  }
+  return a / b;
+}
+
+static inline int64_t ExecuteI64RemS(int64_t a, int64_t b, TrapReason* trap) {
+  if (b == 0) {
+    *trap = kTrapRemByZero;
+    return 0;
+  }
+  if (b == -1) return 0;
+  return a % b;
+}
+
+static inline uint64_t ExecuteI64RemU(uint64_t a, uint64_t b,
+                                      TrapReason* trap) {
+  if (b == 0) {
+    *trap = kTrapRemByZero;
+    return 0;
+  }
+  return a % b;
+}
+
+static inline uint64_t ExecuteI64Shl(uint64_t a, uint64_t b, TrapReason* trap) {
+  return a << (b & 0x3f);
+}
+
+static inline uint64_t ExecuteI64ShrU(uint64_t a, uint64_t b,
+                                      TrapReason* trap) {
+  return a >> (b & 0x3f);
+}
+
+static inline int64_t ExecuteI64ShrS(int64_t a, int64_t b, TrapReason* trap) {
+  return a >> (b & 0x3f);
+}
+
+static inline uint32_t ExecuteI32Ror(uint32_t a, uint32_t b, TrapReason* trap) {
+  uint32_t shift = (b & 0x1f);
+  return (a >> shift) | (a << (32 - shift));
+}
+
+static inline uint32_t ExecuteI32Rol(uint32_t a, uint32_t b, TrapReason* trap) {
+  uint32_t shift = (b & 0x1f);
+  return (a << shift) | (a >> (32 - shift));
+}
+
+static inline uint64_t ExecuteI64Ror(uint64_t a, uint64_t b, TrapReason* trap) {
+  uint32_t shift = (b & 0x3f);
+  return (a >> shift) | (a << (64 - shift));
+}
+
+static inline uint64_t ExecuteI64Rol(uint64_t a, uint64_t b, TrapReason* trap) {
+  uint32_t shift = (b & 0x3f);
+  return (a << shift) | (a >> (64 - shift));
+}
+
+static float quiet(float a) {
+  static const uint32_t kSignalingBit = 1 << 22;
+  uint32_t q = bit_cast<uint32_t>(std::numeric_limits<float>::quiet_NaN());
+  if ((q & kSignalingBit) != 0) {
+    // On some machines, the signaling bit set indicates it's a quiet NaN.
+    return bit_cast<float>(bit_cast<uint32_t>(a) | kSignalingBit);
+  } else {
+    // On others, the signaling bit set indicates it's a signaling NaN.
+    return bit_cast<float>(bit_cast<uint32_t>(a) & ~kSignalingBit);
+  }
+}
+
+static double quiet(double a) {
+  static const uint64_t kSignalingBit = 1ULL << 51;
+  uint64_t q = bit_cast<uint64_t>(std::numeric_limits<double>::quiet_NaN());
+  if ((q & kSignalingBit) != 0) {
+    // On some machines, the signaling bit set indicates it's a quiet NaN.
+    return bit_cast<double>(bit_cast<uint64_t>(a) | kSignalingBit);
+  } else {
+    // On others, the signaling bit set indicates it's a signaling NaN.
+    return bit_cast<double>(bit_cast<uint64_t>(a) & ~kSignalingBit);
+  }
+}
+
+static inline float ExecuteF32Sub(float a, float b, TrapReason* trap) {
+  float result = a - b;
+  // Some architectures (e.g. MIPS) need extra checking to preserve the payload
+  // of a NaN operand.
+  if (result - result != 0) {
+    if (std::isnan(a)) return quiet(a);
+    if (std::isnan(b)) return quiet(b);
+  }
+  return result;
+}
+
+static inline float ExecuteF32Min(float a, float b, TrapReason* trap) {
+  if (std::isnan(a)) return quiet(a);
+  if (std::isnan(b)) return quiet(b);
+  return std::min(a, b);
+}
+
+static inline float ExecuteF32Max(float a, float b, TrapReason* trap) {
+  if (std::isnan(a)) return quiet(a);
+  if (std::isnan(b)) return quiet(b);
+  return std::max(a, b);
+}
+
+static inline float ExecuteF32CopySign(float a, float b, TrapReason* trap) {
+  return copysignf(a, b);
+}
+
+static inline double ExecuteF64Sub(double a, double b, TrapReason* trap) {
+  double result = a - b;
+  // Some architectures (e.g. MIPS) need extra checking to preserve the payload
+  // of a NaN operand.
+  if (result - result != 0) {
+    if (std::isnan(a)) return quiet(a);
+    if (std::isnan(b)) return quiet(b);
+  }
+  return result;
+}
+
+static inline double ExecuteF64Min(double a, double b, TrapReason* trap) {
+  if (std::isnan(a)) return quiet(a);
+  if (std::isnan(b)) return quiet(b);
+  return std::min(a, b);
+}
+
+static inline double ExecuteF64Max(double a, double b, TrapReason* trap) {
+  if (std::isnan(a)) return quiet(a);
+  if (std::isnan(b)) return quiet(b);
+  return std::max(a, b);
+}
+
+static inline double ExecuteF64CopySign(double a, double b, TrapReason* trap) {
+  return copysign(a, b);
+}
+
+static inline int32_t ExecuteI32AsmjsDivS(int32_t a, int32_t b,
+                                          TrapReason* trap) {
+  if (b == 0) return 0;
+  if (b == -1 && a == std::numeric_limits<int32_t>::min()) {
+    return std::numeric_limits<int32_t>::min();
+  }
+  return a / b;
+}
+
+static inline uint32_t ExecuteI32AsmjsDivU(uint32_t a, uint32_t b,
+                                           TrapReason* trap) {
+  if (b == 0) return 0;
+  return a / b;
+}
+
+static inline int32_t ExecuteI32AsmjsRemS(int32_t a, int32_t b,
+                                          TrapReason* trap) {
+  if (b == 0) return 0;
+  if (b == -1) return 0;
+  return a % b;
+}
+
+static inline uint32_t ExecuteI32AsmjsRemU(uint32_t a, uint32_t b,
+                                           TrapReason* trap) {
+  if (b == 0) return 0;
+  return a % b;
+}
+
+static inline int32_t ExecuteI32AsmjsSConvertF32(float a, TrapReason* trap) {
+  return DoubleToInt32(a);
+}
+
+static inline uint32_t ExecuteI32AsmjsUConvertF32(float a, TrapReason* trap) {
+  return DoubleToUint32(a);
+}
+
+static inline int32_t ExecuteI32AsmjsSConvertF64(double a, TrapReason* trap) {
+  return DoubleToInt32(a);
+}
+
+static inline uint32_t ExecuteI32AsmjsUConvertF64(double a, TrapReason* trap) {
+  return DoubleToUint32(a);
+}
+
+static int32_t ExecuteI32Clz(uint32_t val, TrapReason* trap) {
+  return base::bits::CountLeadingZeros32(val);
+}
+
+static uint32_t ExecuteI32Ctz(uint32_t val, TrapReason* trap) {
+  return base::bits::CountTrailingZeros32(val);
+}
+
+static uint32_t ExecuteI32Popcnt(uint32_t val, TrapReason* trap) {
+  return word32_popcnt_wrapper(&val);
+}
+
+static inline uint32_t ExecuteI32Eqz(uint32_t val, TrapReason* trap) {
+  return val == 0 ? 1 : 0;
+}
+
+static int64_t ExecuteI64Clz(uint64_t val, TrapReason* trap) {
+  return base::bits::CountLeadingZeros64(val);
+}
+
+static inline uint64_t ExecuteI64Ctz(uint64_t val, TrapReason* trap) {
+  return base::bits::CountTrailingZeros64(val);
+}
+
+static inline int64_t ExecuteI64Popcnt(uint64_t val, TrapReason* trap) {
+  return word64_popcnt_wrapper(&val);
+}
+
+static inline int32_t ExecuteI64Eqz(uint64_t val, TrapReason* trap) {
+  return val == 0 ? 1 : 0;
+}
+
+static inline float ExecuteF32Abs(float a, TrapReason* trap) {
+  return bit_cast<float>(bit_cast<uint32_t>(a) & 0x7fffffff);
+}
+
+static inline float ExecuteF32Neg(float a, TrapReason* trap) {
+  return bit_cast<float>(bit_cast<uint32_t>(a) ^ 0x80000000);
+}
+
+static inline float ExecuteF32Ceil(float a, TrapReason* trap) {
+  return ceilf(a);
+}
+
+static inline float ExecuteF32Floor(float a, TrapReason* trap) {
+  return floorf(a);
+}
+
+static inline float ExecuteF32Trunc(float a, TrapReason* trap) {
+  return truncf(a);
+}
+
+static inline float ExecuteF32NearestInt(float a, TrapReason* trap) {
+  return nearbyintf(a);
+}
+
+static inline float ExecuteF32Sqrt(float a, TrapReason* trap) {
+  return sqrtf(a);
+}
+
+static inline double ExecuteF64Abs(double a, TrapReason* trap) {
+  return bit_cast<double>(bit_cast<uint64_t>(a) & 0x7fffffffffffffff);
+}
+
+static inline double ExecuteF64Neg(double a, TrapReason* trap) {
+  return bit_cast<double>(bit_cast<uint64_t>(a) ^ 0x8000000000000000);
+}
+
+static inline double ExecuteF64Ceil(double a, TrapReason* trap) {
+  return ceil(a);
+}
+
+static inline double ExecuteF64Floor(double a, TrapReason* trap) {
+  return floor(a);
+}
+
+static inline double ExecuteF64Trunc(double a, TrapReason* trap) {
+  return trunc(a);
+}
+
+static inline double ExecuteF64NearestInt(double a, TrapReason* trap) {
+  return nearbyint(a);
+}
+
+static inline double ExecuteF64Sqrt(double a, TrapReason* trap) {
+  return sqrt(a);
+}
+
+static int32_t ExecuteI32SConvertF32(float a, TrapReason* trap) {
+  if (a < static_cast<float>(INT32_MAX) && a >= static_cast<float>(INT32_MIN)) {
+    return static_cast<int32_t>(a);
+  }
+  *trap = kTrapFloatUnrepresentable;
+  return 0;
+}
+
+static int32_t ExecuteI32SConvertF64(double a, TrapReason* trap) {
+  if (a < (static_cast<double>(INT32_MAX) + 1.0) &&
+      a > (static_cast<double>(INT32_MIN) - 1.0)) {
+    return static_cast<int32_t>(a);
+  }
+  *trap = kTrapFloatUnrepresentable;
+  return 0;
+}
+
+static uint32_t ExecuteI32UConvertF32(float a, TrapReason* trap) {
+  if (a < (static_cast<float>(UINT32_MAX) + 1.0) && a > -1) {
+    return static_cast<uint32_t>(a);
+  }
+  *trap = kTrapFloatUnrepresentable;
+  return 0;
+}
+
+static uint32_t ExecuteI32UConvertF64(double a, TrapReason* trap) {
+  if (a < (static_cast<float>(UINT32_MAX) + 1.0) && a > -1) {
+    return static_cast<uint32_t>(a);
+  }
+  *trap = kTrapFloatUnrepresentable;
+  return 0;
+}
+
+static inline uint32_t ExecuteI32ConvertI64(int64_t a, TrapReason* trap) {
+  return static_cast<uint32_t>(a & 0xFFFFFFFF);
+}
+
+static int64_t ExecuteI64SConvertF32(float a, TrapReason* trap) {
+  int64_t output;
+  if (!float32_to_int64_wrapper(&a, &output)) {
+    *trap = kTrapFloatUnrepresentable;
+  }
+  return output;
+}
+
+static int64_t ExecuteI64SConvertF64(double a, TrapReason* trap) {
+  int64_t output;
+  if (!float64_to_int64_wrapper(&a, &output)) {
+    *trap = kTrapFloatUnrepresentable;
+  }
+  return output;
+}
+
+static uint64_t ExecuteI64UConvertF32(float a, TrapReason* trap) {
+  uint64_t output;
+  if (!float32_to_uint64_wrapper(&a, &output)) {
+    *trap = kTrapFloatUnrepresentable;
+  }
+  return output;
+}
+
+static uint64_t ExecuteI64UConvertF64(double a, TrapReason* trap) {
+  uint64_t output;
+  if (!float64_to_uint64_wrapper(&a, &output)) {
+    *trap = kTrapFloatUnrepresentable;
+  }
+  return output;
+}
+
+static inline int64_t ExecuteI64SConvertI32(int32_t a, TrapReason* trap) {
+  return static_cast<int64_t>(a);
+}
+
+static inline int64_t ExecuteI64UConvertI32(uint32_t a, TrapReason* trap) {
+  return static_cast<uint64_t>(a);
+}
+
+static inline float ExecuteF32SConvertI32(int32_t a, TrapReason* trap) {
+  return static_cast<float>(a);
+}
+
+static inline float ExecuteF32UConvertI32(uint32_t a, TrapReason* trap) {
+  return static_cast<float>(a);
+}
+
+static inline float ExecuteF32SConvertI64(int64_t a, TrapReason* trap) {
+  float output;
+  int64_to_float32_wrapper(&a, &output);
+  return output;
+}
+
+static inline float ExecuteF32UConvertI64(uint64_t a, TrapReason* trap) {
+  float output;
+  uint64_to_float32_wrapper(&a, &output);
+  return output;
+}
+
+static inline float ExecuteF32ConvertF64(double a, TrapReason* trap) {
+  return static_cast<float>(a);
+}
+
+static inline float ExecuteF32ReinterpretI32(int32_t a, TrapReason* trap) {
+  return bit_cast<float>(a);
+}
+
+static inline double ExecuteF64SConvertI32(int32_t a, TrapReason* trap) {
+  return static_cast<double>(a);
+}
+
+static inline double ExecuteF64UConvertI32(uint32_t a, TrapReason* trap) {
+  return static_cast<double>(a);
+}
+
+static inline double ExecuteF64SConvertI64(int64_t a, TrapReason* trap) {
+  double output;
+  int64_to_float64_wrapper(&a, &output);
+  return output;
+}
+
+static inline double ExecuteF64UConvertI64(uint64_t a, TrapReason* trap) {
+  double output;
+  uint64_to_float64_wrapper(&a, &output);
+  return output;
+}
+
+static inline double ExecuteF64ConvertF32(float a, TrapReason* trap) {
+  return static_cast<double>(a);
+}
+
+static inline double ExecuteF64ReinterpretI64(int64_t a, TrapReason* trap) {
+  return bit_cast<double>(a);
+}
+
+static inline int32_t ExecuteI32ReinterpretF32(float a, TrapReason* trap) {
+  return bit_cast<int32_t>(a);
+}
+
+static inline int64_t ExecuteI64ReinterpretF64(double a, TrapReason* trap) {
+  return bit_cast<int64_t>(a);
+}
+
+enum InternalOpcode {
+#define DECL_INTERNAL_ENUM(name, value) kInternal##name = value,
+  FOREACH_INTERNAL_OPCODE(DECL_INTERNAL_ENUM)
+#undef DECL_INTERNAL_ENUM
+};
+
+static const char* OpcodeName(uint32_t val) {
+  switch (val) {
+#define DECL_INTERNAL_CASE(name, value) \
+  case kInternal##name:                 \
+    return "Internal" #name;
+    FOREACH_INTERNAL_OPCODE(DECL_INTERNAL_CASE)
+#undef DECL_INTERNAL_CASE
+  }
+  return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(val));
+}
+
+static const int kRunSteps = 1000;
+
+// A helper class to compute the control transfers for each bytecode offset.
+// Control transfers allow Br, BrIf, BrTable, If, Else, and End bytecodes to
+// be directly executed without the need to dynamically track blocks.
+class ControlTransfers : public ZoneObject {
+ public:
+  ControlTransferMap map_;
+
+  ControlTransfers(Zone* zone, size_t locals_encoded_size, const byte* start,
+                   const byte* end)
+      : map_(zone) {
+    // A control reference including from PC, from value depth, and whether
+    // a value is explicitly passed (e.g. br/br_if/br_table with value).
+    struct CRef {
+      const byte* pc;
+      sp_t value_depth;
+      bool explicit_value;
+    };
+
+    // Represents a control flow label.
+    struct CLabel : public ZoneObject {
+      const byte* target;
+      size_t value_depth;
+      ZoneVector<CRef> refs;
+
+      CLabel(Zone* zone, size_t v)
+          : target(nullptr), value_depth(v), refs(zone) {}
+
+      // Bind this label to the given PC.
+      void Bind(ControlTransferMap* map, const byte* start, const byte* pc,
+                bool expect_value) {
+        DCHECK_NULL(target);
+        target = pc;
+        for (auto from : refs) {
+          auto pcdiff = static_cast<pcdiff_t>(target - from.pc);
+          auto spdiff = static_cast<spdiff_t>(from.value_depth - value_depth);
+          ControlTransfer::StackAction action = ControlTransfer::kNoAction;
+          if (expect_value && !from.explicit_value) {
+            action = spdiff == 0 ? ControlTransfer::kPushVoid
+                                 : ControlTransfer::kPopAndRepush;
+          }
+          pc_t offset = static_cast<size_t>(from.pc - start);
+          (*map)[offset] = {pcdiff, spdiff, action};
+        }
+      }
+
+      // Reference this label from the given location.
+      void Ref(ControlTransferMap* map, const byte* start, CRef from) {
+        DCHECK_GE(from.value_depth, value_depth);
+        if (target) {
+          auto pcdiff = static_cast<pcdiff_t>(target - from.pc);
+          auto spdiff = static_cast<spdiff_t>(from.value_depth - value_depth);
+          pc_t offset = static_cast<size_t>(from.pc - start);
+          (*map)[offset] = {pcdiff, spdiff, ControlTransfer::kNoAction};
+        } else {
+          refs.push_back(from);
+        }
+      }
+    };
+
+    // An entry in the control stack.
+    struct Control {
+      const byte* pc;
+      CLabel* end_label;
+      CLabel* else_label;
+
+      void Ref(ControlTransferMap* map, const byte* start, const byte* from_pc,
+               size_t from_value_depth, bool explicit_value) {
+        end_label->Ref(map, start, {from_pc, from_value_depth, explicit_value});
+      }
+    };
+
+    // Compute the ControlTransfer map.
+    // This works by maintaining a stack of control constructs similar to the
+    // AST decoder. The {control_stack} allows matching {br,br_if,br_table}
+    // bytecodes with their target, as well as determining whether the current
+    // bytecodes are within the true or false block of an else.
+    // The value stack depth is tracked as {value_depth} and is needed to
+    // determine how many values to pop off the stack for explicit and
+    // implicit control flow.
+
+    std::vector<Control> control_stack;
+    size_t value_depth = 0;
+    Decoder decoder(start, end);  // for reading operands.
+    const byte* pc = start + locals_encoded_size;
+
+    while (pc < end) {
+      WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
+      TRACE("@%td: control %s (depth = %zu)\n", (pc - start),
+            WasmOpcodes::OpcodeName(opcode), value_depth);
+      switch (opcode) {
+        case kExprBlock: {
+          TRACE("control @%td $%zu: Block\n", (pc - start), value_depth);
+          CLabel* label = new (zone) CLabel(zone, value_depth);
+          control_stack.push_back({pc, label, nullptr});
+          break;
+        }
+        case kExprLoop: {
+          TRACE("control @%td $%zu: Loop\n", (pc - start), value_depth);
+          CLabel* label1 = new (zone) CLabel(zone, value_depth);
+          CLabel* label2 = new (zone) CLabel(zone, value_depth);
+          control_stack.push_back({pc, label1, nullptr});
+          control_stack.push_back({pc, label2, nullptr});
+          label2->Bind(&map_, start, pc, false);
+          break;
+        }
+        case kExprIf: {
+          TRACE("control @%td $%zu: If\n", (pc - start), value_depth);
+          value_depth--;
+          CLabel* end_label = new (zone) CLabel(zone, value_depth);
+          CLabel* else_label = new (zone) CLabel(zone, value_depth);
+          control_stack.push_back({pc, end_label, else_label});
+          else_label->Ref(&map_, start, {pc, value_depth, false});
+          break;
+        }
+        case kExprElse: {
+          Control* c = &control_stack.back();
+          TRACE("control @%td $%zu: Else\n", (pc - start), value_depth);
+          c->end_label->Ref(&map_, start, {pc, value_depth, false});
+          value_depth = c->end_label->value_depth;
+          DCHECK_NOT_NULL(c->else_label);
+          c->else_label->Bind(&map_, start, pc + 1, false);
+          c->else_label = nullptr;
+          break;
+        }
+        case kExprEnd: {
+          Control* c = &control_stack.back();
+          TRACE("control @%td $%zu: End\n", (pc - start), value_depth);
+          if (c->end_label->target) {
+            // only loops have bound labels.
+            DCHECK_EQ(kExprLoop, *c->pc);
+            control_stack.pop_back();
+            c = &control_stack.back();
+          }
+          if (c->else_label) c->else_label->Bind(&map_, start, pc + 1, true);
+          c->end_label->Ref(&map_, start, {pc, value_depth, false});
+          c->end_label->Bind(&map_, start, pc + 1, true);
+          value_depth = c->end_label->value_depth + 1;
+          control_stack.pop_back();
+          break;
+        }
+        case kExprBr: {
+          BreakDepthOperand operand(&decoder, pc);
+          TRACE("control @%td $%zu: Br[arity=%u, depth=%u]\n", (pc - start),
+                value_depth, operand.arity, operand.depth);
+          value_depth -= operand.arity;
+          control_stack[control_stack.size() - operand.depth - 1].Ref(
+              &map_, start, pc, value_depth, operand.arity > 0);
+          value_depth++;
+          break;
+        }
+        case kExprBrIf: {
+          BreakDepthOperand operand(&decoder, pc);
+          TRACE("control @%td $%zu: BrIf[arity=%u, depth=%u]\n", (pc - start),
+                value_depth, operand.arity, operand.depth);
+          value_depth -= (operand.arity + 1);
+          control_stack[control_stack.size() - operand.depth - 1].Ref(
+              &map_, start, pc, value_depth, operand.arity > 0);
+          value_depth++;
+          break;
+        }
+        case kExprBrTable: {
+          BranchTableOperand operand(&decoder, pc);
+          TRACE("control @%td $%zu: BrTable[arity=%u count=%u]\n", (pc - start),
+                value_depth, operand.arity, operand.table_count);
+          value_depth -= (operand.arity + 1);
+          for (uint32_t i = 0; i < operand.table_count + 1; ++i) {
+            uint32_t target = operand.read_entry(&decoder, i);
+            control_stack[control_stack.size() - target - 1].Ref(
+                &map_, start, pc + i, value_depth, operand.arity > 0);
+          }
+          value_depth++;
+          break;
+        }
+        default: {
+          value_depth = value_depth - OpcodeArity(pc, end) + 1;
+          break;
+        }
+      }
+
+      pc += OpcodeLength(pc, end);
+    }
+  }
+
+  ControlTransfer Lookup(pc_t from) {
+    auto result = map_.find(from);
+    if (result == map_.end()) {
+      V8_Fatal(__FILE__, __LINE__, "no control target for pc %zu", from);
+    }
+    return result->second;
+  }
+};
+
+// Code and metadata needed to execute a function.
+struct InterpreterCode {
+  const WasmFunction* function;  // wasm function
+  AstLocalDecls locals;          // local declarations
+  const byte* orig_start;        // start of original code
+  const byte* orig_end;          // end of original code
+  byte* start;                   // start of (maybe altered) code
+  byte* end;                     // end of (maybe altered) code
+  ControlTransfers* targets;     // helper for control flow.
+
+  const byte* at(pc_t pc) { return start + pc; }
+};
+
+// The main storage for interpreter code. It maps {WasmFunction} to the
+// metadata needed to execute each function.
+class CodeMap {
+ public:
+  Zone* zone_;
+  const WasmModule* module_;
+  ZoneVector<InterpreterCode> interpreter_code_;
+
+  CodeMap(const WasmModule* module, Zone* zone)
+      : zone_(zone), module_(module), interpreter_code_(zone) {
+    if (module == nullptr) return;
+    for (size_t i = 0; i < module->functions.size(); ++i) {
+      const WasmFunction* function = &module->functions[i];
+      const byte* code_start =
+          module->module_start + function->code_start_offset;
+      const byte* code_end = module->module_start + function->code_end_offset;
+      AddFunction(function, code_start, code_end);
+    }
+  }
+
+  InterpreterCode* FindCode(const WasmFunction* function) {
+    if (function->func_index < interpreter_code_.size()) {
+      InterpreterCode* code = &interpreter_code_[function->func_index];
+      DCHECK_EQ(function, code->function);
+      return code;
+    }
+    return nullptr;
+  }
+
+  InterpreterCode* GetCode(uint32_t function_index) {
+    CHECK_LT(function_index, interpreter_code_.size());
+    return Preprocess(&interpreter_code_[function_index]);
+  }
+
+  InterpreterCode* GetIndirectCode(uint32_t indirect_index) {
+    if (indirect_index >= module_->function_table.size()) return nullptr;
+    uint32_t index = module_->function_table[indirect_index];
+    if (index >= interpreter_code_.size()) return nullptr;
+    return GetCode(index);
+  }
+
+  InterpreterCode* Preprocess(InterpreterCode* code) {
+    if (code->targets == nullptr && code->start) {
+      // Compute the control targets map and the local declarations.
+      CHECK(DecodeLocalDecls(code->locals, code->start, code->end));
+      code->targets =
+          new (zone_) ControlTransfers(zone_, code->locals.decls_encoded_size,
+                                       code->orig_start, code->orig_end);
+    }
+    return code;
+  }
+
+  int AddFunction(const WasmFunction* function, const byte* code_start,
+                  const byte* code_end) {
+    InterpreterCode code = {
+        function, AstLocalDecls(zone_),          code_start,
+        code_end, const_cast<byte*>(code_start), const_cast<byte*>(code_end),
+        nullptr};
+
+    DCHECK_EQ(interpreter_code_.size(), function->func_index);
+    interpreter_code_.push_back(code);
+    return static_cast<int>(interpreter_code_.size()) - 1;
+  }
+
+  bool SetFunctionCode(const WasmFunction* function, const byte* start,
+                       const byte* end) {
+    InterpreterCode* code = FindCode(function);
+    if (code == nullptr) return false;
+    code->targets = nullptr;
+    code->orig_start = start;
+    code->orig_end = end;
+    code->start = const_cast<byte*>(start);
+    code->end = const_cast<byte*>(end);
+    Preprocess(code);
+    return true;
+  }
+};
+
+// Responsible for executing code directly.
+class ThreadImpl : public WasmInterpreter::Thread {
+ public:
+  ThreadImpl(Zone* zone, CodeMap* codemap, WasmModuleInstance* instance)
+      : codemap_(codemap),
+        instance_(instance),
+        stack_(zone),
+        frames_(zone),
+        state_(WasmInterpreter::STOPPED),
+        break_pc_(kInvalidPc),
+        trap_reason_(kTrapCount) {}
+
+  virtual ~ThreadImpl() {}
+
+  //==========================================================================
+  // Implementation of public interface for WasmInterpreter::Thread.
+  //==========================================================================
+
+  virtual WasmInterpreter::State state() { return state_; }
+
+  virtual void PushFrame(const WasmFunction* function, WasmVal* args) {
+    InterpreterCode* code = codemap()->FindCode(function);
+    CHECK_NOT_NULL(code);
+    frames_.push_back({code, 0, 0, stack_.size()});
+    for (size_t i = 0; i < function->sig->parameter_count(); ++i) {
+      stack_.push_back(args[i]);
+    }
+    frames_.back().ret_pc = InitLocals(code);
+    TRACE("  => PushFrame(#%u @%zu)\n", code->function->func_index,
+          frames_.back().ret_pc);
+  }
+
+  virtual WasmInterpreter::State Run() {
+    do {
+      TRACE("  => Run()\n");
+      if (state_ == WasmInterpreter::STOPPED ||
+          state_ == WasmInterpreter::PAUSED) {
+        state_ = WasmInterpreter::RUNNING;
+        Execute(frames_.back().code, frames_.back().ret_pc, kRunSteps);
+      }
+    } while (state_ == WasmInterpreter::STOPPED);
+    return state_;
+  }
+
+  virtual WasmInterpreter::State Step() {
+    TRACE("  => Step()\n");
+    if (state_ == WasmInterpreter::STOPPED ||
+        state_ == WasmInterpreter::PAUSED) {
+      state_ = WasmInterpreter::RUNNING;
+      Execute(frames_.back().code, frames_.back().ret_pc, 1);
+    }
+    return state_;
+  }
+
+  virtual void Pause() { UNIMPLEMENTED(); }
+
+  virtual void Reset() {
+    TRACE("----- RESET -----\n");
+    stack_.clear();
+    frames_.clear();
+    state_ = WasmInterpreter::STOPPED;
+    trap_reason_ = kTrapCount;
+  }
+
+  virtual int GetFrameCount() { return static_cast<int>(frames_.size()); }
+
+  virtual const WasmFrame* GetFrame(int index) {
+    UNIMPLEMENTED();
+    return nullptr;
+  }
+
+  virtual WasmFrame* GetMutableFrame(int index) {
+    UNIMPLEMENTED();
+    return nullptr;
+  }
+
+  virtual WasmVal GetReturnValue() {
+    if (state_ == WasmInterpreter::TRAPPED) return WasmVal(0xdeadbeef);
+    CHECK_EQ(WasmInterpreter::FINISHED, state_);
+    CHECK_EQ(1, stack_.size());
+    return stack_[0];
+  }
+
+  virtual pc_t GetBreakpointPc() { return break_pc_; }
+
+  bool Terminated() {
+    return state_ == WasmInterpreter::TRAPPED ||
+           state_ == WasmInterpreter::FINISHED;
+  }
+
+ private:
+  // Entries on the stack of functions being evaluated.
+  struct Frame {
+    InterpreterCode* code;
+    pc_t call_pc;
+    pc_t ret_pc;
+    sp_t sp;
+
+    // Limit of parameters.
+    sp_t plimit() { return sp + code->function->sig->parameter_count(); }
+    // Limit of locals.
+    sp_t llimit() { return plimit() + code->locals.total_local_count; }
+  };
+
+  CodeMap* codemap_;
+  WasmModuleInstance* instance_;
+  ZoneVector<WasmVal> stack_;
+  ZoneVector<Frame> frames_;
+  WasmInterpreter::State state_;
+  pc_t break_pc_;
+  TrapReason trap_reason_;
+
+  CodeMap* codemap() { return codemap_; }
+  WasmModuleInstance* instance() { return instance_; }
+  const WasmModule* module() { return instance_->module; }
+
+  void DoTrap(TrapReason trap, pc_t pc) {
+    state_ = WasmInterpreter::TRAPPED;
+    trap_reason_ = trap;
+    CommitPc(pc);
+  }
+
+  // Push a frame with arguments already on the stack.
+  void PushFrame(InterpreterCode* code, pc_t call_pc, pc_t ret_pc) {
+    CHECK_NOT_NULL(code);
+    DCHECK(!frames_.empty());
+    frames_.back().call_pc = call_pc;
+    frames_.back().ret_pc = ret_pc;
+    size_t arity = code->function->sig->parameter_count();
+    DCHECK_GE(stack_.size(), arity);
+    // The parameters will overlap the arguments already on the stack.
+    frames_.push_back({code, 0, 0, stack_.size() - arity});
+    frames_.back().ret_pc = InitLocals(code);
+    TRACE("  => push func#%u @%zu\n", code->function->func_index,
+          frames_.back().ret_pc);
+  }
+
+  pc_t InitLocals(InterpreterCode* code) {
+    for (auto p : code->locals.local_types) {
+      WasmVal val;
+      switch (p.first) {
+        case kAstI32:
+          val = WasmVal(static_cast<int32_t>(0));
+          break;
+        case kAstI64:
+          val = WasmVal(static_cast<int64_t>(0));
+          break;
+        case kAstF32:
+          val = WasmVal(static_cast<float>(0));
+          break;
+        case kAstF64:
+          val = WasmVal(static_cast<double>(0));
+          break;
+        default:
+          UNREACHABLE();
+          break;
+      }
+      stack_.insert(stack_.end(), p.second, val);
+    }
+    return code->locals.decls_encoded_size;
+  }
+
+  void CommitPc(pc_t pc) {
+    if (!frames_.empty()) {
+      frames_.back().ret_pc = pc;
+    }
+  }
+
+  bool SkipBreakpoint(InterpreterCode* code, pc_t pc) {
+    if (pc == break_pc_) {
+      break_pc_ = kInvalidPc;
+      return true;
+    }
+    return false;
+  }
+
+  bool DoReturn(InterpreterCode** code, pc_t* pc, pc_t* limit, WasmVal val) {
+    DCHECK_GT(frames_.size(), 0u);
+    stack_.resize(frames_.back().sp);
+    frames_.pop_back();
+    if (frames_.size() == 0) {
+      // A return from the top frame terminates the execution.
+      state_ = WasmInterpreter::FINISHED;
+      stack_.clear();
+      stack_.push_back(val);
+      TRACE("  => finish\n");
+      return false;
+    } else {
+      // Return to caller frame.
+      Frame* top = &frames_.back();
+      *code = top->code;
+      *pc = top->ret_pc;
+      *limit = top->code->end - top->code->start;
+      if (top->code->start[top->call_pc] == kExprCallIndirect ||
+          (top->code->orig_start &&
+           top->code->orig_start[top->call_pc] == kExprCallIndirect)) {
+        // UGLY: An indirect call has the additional function index on the
+        // stack.
+        stack_.pop_back();
+      }
+      TRACE("  => pop func#%u @%zu\n", (*code)->function->func_index, *pc);
+
+      stack_.push_back(val);
+      return true;
+    }
+  }
+
+  void DoCall(InterpreterCode* target, pc_t* pc, pc_t ret_pc, pc_t* limit) {
+    PushFrame(target, *pc, ret_pc);
+    *pc = frames_.back().ret_pc;
+    *limit = target->end - target->start;
+  }
+
+  // Adjust the program counter {pc} and the stack contents according to the
+  // code's precomputed control transfer map. Returns the different between
+  // the new pc and the old pc.
+  int DoControlTransfer(InterpreterCode* code, pc_t pc) {
+    auto target = code->targets->Lookup(pc);
+    switch (target.action) {
+      case ControlTransfer::kNoAction:
+        TRACE("  action [sp-%u]\n", target.spdiff);
+        PopN(target.spdiff);
+        break;
+      case ControlTransfer::kPopAndRepush: {
+        WasmVal val = Pop();
+        TRACE("  action [pop x, sp-%u, push x]\n", target.spdiff - 1);
+        DCHECK_GE(target.spdiff, 1u);
+        PopN(target.spdiff - 1);
+        Push(pc, val);
+        break;
+      }
+      case ControlTransfer::kPushVoid:
+        TRACE("  action [sp-%u, push void]\n", target.spdiff);
+        PopN(target.spdiff);
+        Push(pc, WasmVal());
+        break;
+    }
+    return target.pcdiff;
+  }
+
+  void Execute(InterpreterCode* code, pc_t pc, int max) {
+    Decoder decoder(code->start, code->end);
+    pc_t limit = code->end - code->start;
+    while (true) {
+      if (max-- <= 0) {
+        // Maximum number of instructions reached.
+        state_ = WasmInterpreter::PAUSED;
+        return CommitPc(pc);
+      }
+
+      if (pc >= limit) {
+        // Fell off end of code; do an implicit return.
+        TRACE("@%-3zu: ImplicitReturn\n", pc);
+        WasmVal val = PopArity(code->function->sig->return_count());
+        if (!DoReturn(&code, &pc, &limit, val)) return;
+        decoder.Reset(code->start, code->end);
+        continue;
+      }
+
+      const char* skip = "        ";
+      int len = 1;
+      byte opcode = code->start[pc];
+      byte orig = opcode;
+      if (opcode == kInternalBreakpoint) {
+        orig = code->orig_start[pc];
+        if (SkipBreakpoint(code, pc)) {
+          // skip breakpoint by switching on original code.
+          skip = "[skip]  ";
+        } else {
+          state_ = WasmInterpreter::PAUSED;
+          TRACE("@%-3zu: [break] %-24s:", pc,
+                WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(orig)));
+          TraceValueStack();
+          TRACE("\n");
+          break_pc_ = pc;
+          return CommitPc(pc);
+        }
+      }
+
+      USE(skip);
+      TRACE("@%-3zu: %s%-24s:", pc, skip,
+            WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(orig)));
+      TraceValueStack();
+      TRACE("\n");
+
+      switch (orig) {
+        case kExprNop:
+          Push(pc, WasmVal());
+          break;
+        case kExprBlock:
+        case kExprLoop: {
+          // Do nothing.
+          break;
+        }
+        case kExprIf: {
+          WasmVal cond = Pop();
+          bool is_true = cond.to<uint32_t>() != 0;
+          if (is_true) {
+            // fall through to the true block.
+            TRACE("  true => fallthrough\n");
+          } else {
+            len = DoControlTransfer(code, pc);
+            TRACE("  false => @%zu\n", pc + len);
+          }
+          break;
+        }
+        case kExprElse: {
+          len = DoControlTransfer(code, pc);
+          TRACE("  end => @%zu\n", pc + len);
+          break;
+        }
+        case kExprSelect: {
+          WasmVal cond = Pop();
+          WasmVal fval = Pop();
+          WasmVal tval = Pop();
+          Push(pc, cond.to<int32_t>() != 0 ? tval : fval);
+          break;
+        }
+        case kExprBr: {
+          BreakDepthOperand operand(&decoder, code->at(pc));
+          WasmVal val = PopArity(operand.arity);
+          len = DoControlTransfer(code, pc);
+          TRACE("  br => @%zu\n", pc + len);
+          if (operand.arity > 0) Push(pc, val);
+          break;
+        }
+        case kExprBrIf: {
+          BreakDepthOperand operand(&decoder, code->at(pc));
+          WasmVal cond = Pop();
+          WasmVal val = PopArity(operand.arity);
+          bool is_true = cond.to<uint32_t>() != 0;
+          if (is_true) {
+            len = DoControlTransfer(code, pc);
+            TRACE("  br_if => @%zu\n", pc + len);
+            if (operand.arity > 0) Push(pc, val);
+          } else {
+            TRACE("  false => fallthrough\n");
+            len = 1 + operand.length;
+            Push(pc, WasmVal());
+          }
+          break;
+        }
+        case kExprBrTable: {
+          BranchTableOperand operand(&decoder, code->at(pc));
+          uint32_t key = Pop().to<uint32_t>();
+          WasmVal val = PopArity(operand.arity);
+          if (key >= operand.table_count) key = operand.table_count;
+          len = DoControlTransfer(code, pc + key) + key;
+          TRACE("  br[%u] => @%zu\n", key, pc + len);
+          if (operand.arity > 0) Push(pc, val);
+          break;
+        }
+        case kExprReturn: {
+          ReturnArityOperand operand(&decoder, code->at(pc));
+          WasmVal val = PopArity(operand.arity);
+          if (!DoReturn(&code, &pc, &limit, val)) return;
+          decoder.Reset(code->start, code->end);
+          continue;
+        }
+        case kExprUnreachable: {
+          DoTrap(kTrapUnreachable, pc);
+          return CommitPc(pc);
+        }
+        case kExprEnd: {
+          len = DoControlTransfer(code, pc);
+          DCHECK_EQ(1, len);
+          break;
+        }
+        case kExprI8Const: {
+          ImmI8Operand operand(&decoder, code->at(pc));
+          Push(pc, WasmVal(operand.value));
+          len = 1 + operand.length;
+          break;
+        }
+        case kExprI32Const: {
+          ImmI32Operand operand(&decoder, code->at(pc));
+          Push(pc, WasmVal(operand.value));
+          len = 1 + operand.length;
+          break;
+        }
+        case kExprI64Const: {
+          ImmI64Operand operand(&decoder, code->at(pc));
+          Push(pc, WasmVal(operand.value));
+          len = 1 + operand.length;
+          break;
+        }
+        case kExprF32Const: {
+          ImmF32Operand operand(&decoder, code->at(pc));
+          Push(pc, WasmVal(operand.value));
+          len = 1 + operand.length;
+          break;
+        }
+        case kExprF64Const: {
+          ImmF64Operand operand(&decoder, code->at(pc));
+          Push(pc, WasmVal(operand.value));
+          len = 1 + operand.length;
+          break;
+        }
+        case kExprGetLocal: {
+          LocalIndexOperand operand(&decoder, code->at(pc));
+          Push(pc, stack_[frames_.back().sp + operand.index]);
+          len = 1 + operand.length;
+          break;
+        }
+        case kExprSetLocal: {
+          LocalIndexOperand operand(&decoder, code->at(pc));
+          WasmVal val = Pop();
+          stack_[frames_.back().sp + operand.index] = val;
+          Push(pc, val);
+          len = 1 + operand.length;
+          break;
+        }
+        case kExprCallFunction: {
+          CallFunctionOperand operand(&decoder, code->at(pc));
+          InterpreterCode* target = codemap()->GetCode(operand.index);
+          DoCall(target, &pc, pc + 1 + operand.length, &limit);
+          code = target;
+          decoder.Reset(code->start, code->end);
+          continue;
+        }
+        case kExprCallIndirect: {
+          CallIndirectOperand operand(&decoder, code->at(pc));
+          size_t index = stack_.size() - operand.arity - 1;
+          DCHECK_LT(index, stack_.size());
+          uint32_t table_index = stack_[index].to<uint32_t>();
+          if (table_index >= module()->function_table.size()) {
+            return DoTrap(kTrapFuncInvalid, pc);
+          }
+          uint16_t function_index = module()->function_table[table_index];
+          InterpreterCode* target = codemap()->GetCode(function_index);
+          DCHECK(target);
+          if (target->function->sig_index != operand.index) {
+            return DoTrap(kTrapFuncSigMismatch, pc);
+          }
+
+          DoCall(target, &pc, pc + 1 + operand.length, &limit);
+          code = target;
+          decoder.Reset(code->start, code->end);
+          continue;
+        }
+        case kExprCallImport: {
+          UNIMPLEMENTED();
+          break;
+        }
+        case kExprLoadGlobal: {
+          GlobalIndexOperand operand(&decoder, code->at(pc));
+          const WasmGlobal* global = &module()->globals[operand.index];
+          byte* ptr = instance()->globals_start + global->offset;
+          MachineType type = global->type;
+          WasmVal val;
+          if (type == MachineType::Int8()) {
+            val =
+                WasmVal(static_cast<int32_t>(*reinterpret_cast<int8_t*>(ptr)));
+          } else if (type == MachineType::Uint8()) {
+            val =
+                WasmVal(static_cast<int32_t>(*reinterpret_cast<uint8_t*>(ptr)));
+          } else if (type == MachineType::Int16()) {
+            val =
+                WasmVal(static_cast<int32_t>(*reinterpret_cast<int16_t*>(ptr)));
+          } else if (type == MachineType::Uint16()) {
+            val = WasmVal(
+                static_cast<int32_t>(*reinterpret_cast<uint16_t*>(ptr)));
+          } else if (type == MachineType::Int32()) {
+            val = WasmVal(*reinterpret_cast<int32_t*>(ptr));
+          } else if (type == MachineType::Uint32()) {
+            val = WasmVal(*reinterpret_cast<uint32_t*>(ptr));
+          } else if (type == MachineType::Int64()) {
+            val = WasmVal(*reinterpret_cast<int64_t*>(ptr));
+          } else if (type == MachineType::Uint64()) {
+            val = WasmVal(*reinterpret_cast<uint64_t*>(ptr));
+          } else if (type == MachineType::Float32()) {
+            val = WasmVal(*reinterpret_cast<float*>(ptr));
+          } else if (type == MachineType::Float64()) {
+            val = WasmVal(*reinterpret_cast<double*>(ptr));
+          } else {
+            UNREACHABLE();
+          }
+          Push(pc, val);
+          len = 1 + operand.length;
+          break;
+        }
+        case kExprStoreGlobal: {
+          GlobalIndexOperand operand(&decoder, code->at(pc));
+          const WasmGlobal* global = &module()->globals[operand.index];
+          byte* ptr = instance()->globals_start + global->offset;
+          MachineType type = global->type;
+          WasmVal val = Pop();
+          if (type == MachineType::Int8()) {
+            *reinterpret_cast<int8_t*>(ptr) =
+                static_cast<int8_t>(val.to<int32_t>());
+          } else if (type == MachineType::Uint8()) {
+            *reinterpret_cast<uint8_t*>(ptr) =
+                static_cast<uint8_t>(val.to<uint32_t>());
+          } else if (type == MachineType::Int16()) {
+            *reinterpret_cast<int16_t*>(ptr) =
+                static_cast<int16_t>(val.to<int32_t>());
+          } else if (type == MachineType::Uint16()) {
+            *reinterpret_cast<uint16_t*>(ptr) =
+                static_cast<uint16_t>(val.to<uint32_t>());
+          } else if (type == MachineType::Int32()) {
+            *reinterpret_cast<int32_t*>(ptr) = val.to<int32_t>();
+          } else if (type == MachineType::Uint32()) {
+            *reinterpret_cast<uint32_t*>(ptr) = val.to<uint32_t>();
+          } else if (type == MachineType::Int64()) {
+            *reinterpret_cast<int64_t*>(ptr) = val.to<int64_t>();
+          } else if (type == MachineType::Uint64()) {
+            *reinterpret_cast<uint64_t*>(ptr) = val.to<uint64_t>();
+          } else if (type == MachineType::Float32()) {
+            *reinterpret_cast<float*>(ptr) = val.to<float>();
+          } else if (type == MachineType::Float64()) {
+            *reinterpret_cast<double*>(ptr) = val.to<double>();
+          } else {
+            UNREACHABLE();
+          }
+          Push(pc, val);
+          len = 1 + operand.length;
+          break;
+        }
+
+#define LOAD_CASE(name, ctype, mtype)                                    \
+  case kExpr##name: {                                                    \
+    MemoryAccessOperand operand(&decoder, code->at(pc));                 \
+    uint32_t index = Pop().to<uint32_t>();                               \
+    size_t effective_mem_size = instance()->mem_size - sizeof(mtype);    \
+    if (operand.offset > effective_mem_size ||                           \
+        index > (effective_mem_size - operand.offset)) {                 \
+      return DoTrap(kTrapMemOutOfBounds, pc);                            \
+    }                                                                    \
+    byte* addr = instance()->mem_start + operand.offset + index;         \
+    WasmVal result(static_cast<ctype>(ReadUnalignedValue<mtype>(addr))); \
+    Push(pc, result);                                                    \
+    len = 1 + operand.length;                                            \
+    break;                                                               \
+  }
+
+          LOAD_CASE(I32LoadMem8S, int32_t, int8_t);
+          LOAD_CASE(I32LoadMem8U, int32_t, uint8_t);
+          LOAD_CASE(I32LoadMem16S, int32_t, int16_t);
+          LOAD_CASE(I32LoadMem16U, int32_t, uint16_t);
+          LOAD_CASE(I64LoadMem8S, int64_t, int8_t);
+          LOAD_CASE(I64LoadMem8U, int64_t, uint8_t);
+          LOAD_CASE(I64LoadMem16S, int64_t, int16_t);
+          LOAD_CASE(I64LoadMem16U, int64_t, uint16_t);
+          LOAD_CASE(I64LoadMem32S, int64_t, int32_t);
+          LOAD_CASE(I64LoadMem32U, int64_t, uint32_t);
+          LOAD_CASE(I32LoadMem, int32_t, int32_t);
+          LOAD_CASE(I64LoadMem, int64_t, int64_t);
+          LOAD_CASE(F32LoadMem, float, float);
+          LOAD_CASE(F64LoadMem, double, double);
+#undef LOAD_CASE
+
+#define STORE_CASE(name, ctype, mtype)                                     \
+  case kExpr##name: {                                                      \
+    MemoryAccessOperand operand(&decoder, code->at(pc));                   \
+    WasmVal val = Pop();                                                   \
+    uint32_t index = Pop().to<uint32_t>();                                 \
+    size_t effective_mem_size = instance()->mem_size - sizeof(mtype);      \
+    if (operand.offset > effective_mem_size ||                             \
+        index > (effective_mem_size - operand.offset)) {                   \
+      return DoTrap(kTrapMemOutOfBounds, pc);                              \
+    }                                                                      \
+    byte* addr = instance()->mem_start + operand.offset + index;           \
+    WriteUnalignedValue<mtype>(addr, static_cast<mtype>(val.to<ctype>())); \
+    Push(pc, val);                                                         \
+    len = 1 + operand.length;                                              \
+    break;                                                                 \
+  }
+
+          STORE_CASE(I32StoreMem8, int32_t, int8_t);
+          STORE_CASE(I32StoreMem16, int32_t, int16_t);
+          STORE_CASE(I64StoreMem8, int64_t, int8_t);
+          STORE_CASE(I64StoreMem16, int64_t, int16_t);
+          STORE_CASE(I64StoreMem32, int64_t, int32_t);
+          STORE_CASE(I32StoreMem, int32_t, int32_t);
+          STORE_CASE(I64StoreMem, int64_t, int64_t);
+          STORE_CASE(F32StoreMem, float, float);
+          STORE_CASE(F64StoreMem, double, double);
+#undef STORE_CASE
+
+#define ASMJS_LOAD_CASE(name, ctype, mtype, defval)                 \
+  case kExpr##name: {                                               \
+    uint32_t index = Pop().to<uint32_t>();                          \
+    ctype result;                                                   \
+    if (index >= (instance()->mem_size - sizeof(mtype))) {          \
+      result = defval;                                              \
+    } else {                                                        \
+      byte* addr = instance()->mem_start + index;                   \
+      /* TODO(titzer): alignment for asmjs load mem? */             \
+      result = static_cast<ctype>(*reinterpret_cast<mtype*>(addr)); \
+    }                                                               \
+    Push(pc, WasmVal(result));                                      \
+    break;                                                          \
+  }
+          ASMJS_LOAD_CASE(I32AsmjsLoadMem8S, int32_t, int8_t, 0);
+          ASMJS_LOAD_CASE(I32AsmjsLoadMem8U, int32_t, uint8_t, 0);
+          ASMJS_LOAD_CASE(I32AsmjsLoadMem16S, int32_t, int16_t, 0);
+          ASMJS_LOAD_CASE(I32AsmjsLoadMem16U, int32_t, uint16_t, 0);
+          ASMJS_LOAD_CASE(I32AsmjsLoadMem, int32_t, int32_t, 0);
+          ASMJS_LOAD_CASE(F32AsmjsLoadMem, float, float,
+                          std::numeric_limits<float>::quiet_NaN());
+          ASMJS_LOAD_CASE(F64AsmjsLoadMem, double, double,
+                          std::numeric_limits<double>::quiet_NaN());
+#undef ASMJS_LOAD_CASE
+
+#define ASMJS_STORE_CASE(name, ctype, mtype)                                   \
+  case kExpr##name: {                                                          \
+    WasmVal val = Pop();                                                       \
+    uint32_t index = Pop().to<uint32_t>();                                     \
+    if (index < (instance()->mem_size - sizeof(mtype))) {                      \
+      byte* addr = instance()->mem_start + index;                              \
+      /* TODO(titzer): alignment for asmjs store mem? */                       \
+      *(reinterpret_cast<mtype*>(addr)) = static_cast<mtype>(val.to<ctype>()); \
+    }                                                                          \
+    Push(pc, val);                                                             \
+    break;                                                                     \
+  }
+
+          ASMJS_STORE_CASE(I32AsmjsStoreMem8, int32_t, int8_t);
+          ASMJS_STORE_CASE(I32AsmjsStoreMem16, int32_t, int16_t);
+          ASMJS_STORE_CASE(I32AsmjsStoreMem, int32_t, int32_t);
+          ASMJS_STORE_CASE(F32AsmjsStoreMem, float, float);
+          ASMJS_STORE_CASE(F64AsmjsStoreMem, double, double);
+#undef ASMJS_STORE_CASE
+
+        case kExprMemorySize: {
+          Push(pc, WasmVal(static_cast<uint32_t>(instance()->mem_size)));
+          break;
+        }
+#define EXECUTE_SIMPLE_BINOP(name, ctype, op)             \
+  case kExpr##name: {                                     \
+    WasmVal rval = Pop();                                 \
+    WasmVal lval = Pop();                                 \
+    WasmVal result(lval.to<ctype>() op rval.to<ctype>()); \
+    Push(pc, result);                                     \
+    break;                                                \
+  }
+          FOREACH_SIMPLE_BINOP(EXECUTE_SIMPLE_BINOP)
+#undef EXECUTE_SIMPLE_BINOP
+
+#define EXECUTE_OTHER_BINOP(name, ctype)              \
+  case kExpr##name: {                                 \
+    TrapReason trap = kTrapCount;                     \
+    volatile ctype rval = Pop().to<ctype>();          \
+    volatile ctype lval = Pop().to<ctype>();          \
+    WasmVal result(Execute##name(lval, rval, &trap)); \
+    if (trap != kTrapCount) return DoTrap(trap, pc);  \
+    Push(pc, result);                                 \
+    break;                                            \
+  }
+          FOREACH_OTHER_BINOP(EXECUTE_OTHER_BINOP)
+#undef EXECUTE_OTHER_BINOP
+
+#define EXECUTE_OTHER_UNOP(name, ctype)              \
+  case kExpr##name: {                                \
+    TrapReason trap = kTrapCount;                    \
+    volatile ctype val = Pop().to<ctype>();          \
+    WasmVal result(Execute##name(val, &trap));       \
+    if (trap != kTrapCount) return DoTrap(trap, pc); \
+    Push(pc, result);                                \
+    break;                                           \
+  }
+          FOREACH_OTHER_UNOP(EXECUTE_OTHER_UNOP)
+#undef EXECUTE_OTHER_UNOP
+
+        default:
+          V8_Fatal(__FILE__, __LINE__, "Unknown or unimplemented opcode #%d:%s",
+                   code->start[pc], OpcodeName(code->start[pc]));
+          UNREACHABLE();
+      }
+
+      pc += len;
+    }
+    UNREACHABLE();  // above decoding loop should run forever.
+  }
+
+  WasmVal Pop() {
+    DCHECK_GT(stack_.size(), 0u);
+    DCHECK_GT(frames_.size(), 0u);
+    DCHECK_GT(stack_.size(), frames_.back().llimit());  // can't pop into locals
+    WasmVal val = stack_.back();
+    stack_.pop_back();
+    return val;
+  }
+
+  void PopN(int n) {
+    DCHECK_GE(stack_.size(), static_cast<size_t>(n));
+    DCHECK_GT(frames_.size(), 0u);
+    size_t nsize = stack_.size() - n;
+    DCHECK_GE(nsize, frames_.back().llimit());  // can't pop into locals
+    stack_.resize(nsize);
+  }
+
+  WasmVal PopArity(size_t arity) {
+    if (arity == 0) return WasmVal();
+    CHECK_EQ(1, arity);
+    return Pop();
+  }
+
+  void Push(pc_t pc, WasmVal val) {
+    // TODO(titzer): store PC as well?
+    stack_.push_back(val);
+  }
+
+  void TraceStack(const char* phase, pc_t pc) {
+    if (FLAG_trace_wasm_interpreter) {
+      PrintF("%s @%zu", phase, pc);
+      UNIMPLEMENTED();
+      PrintF("\n");
+    }
+  }
+
+  void TraceValueStack() {
+    Frame* top = frames_.size() > 0 ? &frames_.back() : nullptr;
+    sp_t sp = top ? top->sp : 0;
+    sp_t plimit = top ? top->plimit() : 0;
+    sp_t llimit = top ? top->llimit() : 0;
+    if (FLAG_trace_wasm_interpreter) {
+      for (size_t i = sp; i < stack_.size(); ++i) {
+        if (i < plimit)
+          PrintF(" p%zu:", i);
+        else if (i < llimit)
+          PrintF(" l%zu:", i);
+        else
+          PrintF(" s%zu:", i);
+        WasmVal val = stack_[i];
+        switch (val.type) {
+          case kAstI32:
+            PrintF("i32:%d", val.to<int32_t>());
+            break;
+          case kAstI64:
+            PrintF("i64:%" PRId64 "", val.to<int64_t>());
+            break;
+          case kAstF32:
+            PrintF("f32:%f", val.to<float>());
+            break;
+          case kAstF64:
+            PrintF("f64:%lf", val.to<double>());
+            break;
+          case kAstStmt:
+            PrintF("void");
+            break;
+          default:
+            UNREACHABLE();
+            break;
+        }
+      }
+    }
+  }
+};
+
+//============================================================================
+// The implementation details of the interpreter.
+//============================================================================
+class WasmInterpreterInternals : public ZoneObject {
+ public:
+  WasmModuleInstance* instance_;
+  CodeMap codemap_;
+  ZoneVector<ThreadImpl*> threads_;
+
+  WasmInterpreterInternals(Zone* zone, WasmModuleInstance* instance)
+      : instance_(instance),
+        codemap_(instance_ ? instance_->module : nullptr, zone),
+        threads_(zone) {
+    threads_.push_back(new ThreadImpl(zone, &codemap_, instance));
+  }
+
+  void Delete() {
+    // TODO(titzer): CFI doesn't like threads in the ZoneVector.
+    for (auto t : threads_) delete t;
+    threads_.resize(0);
+  }
+};
+
+//============================================================================
+// Implementation of the public interface of the interpreter.
+//============================================================================
+WasmInterpreter::WasmInterpreter(WasmModuleInstance* instance,
+                                 base::AccountingAllocator* allocator)
+    : zone_(allocator),
+      internals_(new (&zone_) WasmInterpreterInternals(&zone_, instance)) {}
+
+WasmInterpreter::~WasmInterpreter() { internals_->Delete(); }
+
+void WasmInterpreter::Run() { internals_->threads_[0]->Run(); }
+
+void WasmInterpreter::Pause() { internals_->threads_[0]->Pause(); }
+
+bool WasmInterpreter::SetBreakpoint(const WasmFunction* function, pc_t pc,
+                                    bool enabled) {
+  InterpreterCode* code = internals_->codemap_.FindCode(function);
+  if (!code) return false;
+  size_t size = static_cast<size_t>(code->end - code->start);
+  // Check bounds for {pc}.
+  if (pc < code->locals.decls_encoded_size || pc >= size) return false;
+  // Make a copy of the code before enabling a breakpoint.
+  if (enabled && code->orig_start == code->start) {
+    code->start = reinterpret_cast<byte*>(zone_.New(size));
+    memcpy(code->start, code->orig_start, size);
+    code->end = code->start + size;
+  }
+  bool prev = code->start[pc] == kInternalBreakpoint;
+  if (enabled) {
+    code->start[pc] = kInternalBreakpoint;
+  } else {
+    code->start[pc] = code->orig_start[pc];
+  }
+  return prev;
+}
+
+bool WasmInterpreter::GetBreakpoint(const WasmFunction* function, pc_t pc) {
+  InterpreterCode* code = internals_->codemap_.FindCode(function);
+  if (!code) return false;
+  size_t size = static_cast<size_t>(code->end - code->start);
+  // Check bounds for {pc}.
+  if (pc < code->locals.decls_encoded_size || pc >= size) return false;
+  // Check if a breakpoint is present at that place in the code.
+  return code->start[pc] == kInternalBreakpoint;
+}
+
+bool WasmInterpreter::SetTracing(const WasmFunction* function, bool enabled) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+int WasmInterpreter::GetThreadCount() {
+  return 1;  // only one thread for now.
+}
+
+WasmInterpreter::Thread* WasmInterpreter::GetThread(int id) {
+  CHECK_EQ(0, id);  // only one thread for now.
+  return internals_->threads_[id];
+}
+
+WasmVal WasmInterpreter::GetLocalVal(const WasmFrame* frame, int index) {
+  CHECK_GE(index, 0);
+  UNIMPLEMENTED();
+  WasmVal none;
+  none.type = kAstStmt;
+  return none;
+}
+
+WasmVal WasmInterpreter::GetExprVal(const WasmFrame* frame, int pc) {
+  UNIMPLEMENTED();
+  WasmVal none;
+  none.type = kAstStmt;
+  return none;
+}
+
+void WasmInterpreter::SetLocalVal(WasmFrame* frame, int index, WasmVal val) {
+  UNIMPLEMENTED();
+}
+
+void WasmInterpreter::SetExprVal(WasmFrame* frame, int pc, WasmVal val) {
+  UNIMPLEMENTED();
+}
+
+size_t WasmInterpreter::GetMemorySize() {
+  return internals_->instance_->mem_size;
+}
+
+WasmVal WasmInterpreter::ReadMemory(size_t offset) {
+  UNIMPLEMENTED();
+  return WasmVal();
+}
+
+void WasmInterpreter::WriteMemory(size_t offset, WasmVal val) {
+  UNIMPLEMENTED();
+}
+
+int WasmInterpreter::AddFunctionForTesting(const WasmFunction* function) {
+  return internals_->codemap_.AddFunction(function, nullptr, nullptr);
+}
+
+bool WasmInterpreter::SetFunctionCodeForTesting(const WasmFunction* function,
+                                                const byte* start,
+                                                const byte* end) {
+  return internals_->codemap_.SetFunctionCode(function, start, end);
+}
+
+ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting(
+    Zone* zone, const byte* start, const byte* end) {
+  ControlTransfers targets(zone, 0, start, end);
+  return targets.map_;
+}
+
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
diff --git a/src/wasm/wasm-interpreter.h b/src/wasm/wasm-interpreter.h
new file mode 100644
index 0000000..b106a20
--- /dev/null
+++ b/src/wasm/wasm-interpreter.h
@@ -0,0 +1,209 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_WASM_INTERPRETER_H_
+#define V8_WASM_INTERPRETER_H_
+
+#include "src/wasm/wasm-opcodes.h"
+#include "src/zone-containers.h"
+
+namespace v8 {
+namespace base {
+class AccountingAllocator;
+}
+
+namespace internal {
+namespace wasm {
+
+// forward declarations.
+struct WasmFunction;
+struct WasmModuleInstance;
+class WasmInterpreterInternals;
+
+typedef size_t pc_t;
+typedef size_t sp_t;
+typedef int32_t pcdiff_t;
+typedef uint32_t spdiff_t;
+
+const pc_t kInvalidPc = 0x80000000;
+
+// Visible for testing. A {ControlTransfer} helps the interpreter figure out
+// the target program counter and stack manipulations for a branch.
+struct ControlTransfer {
+  enum StackAction { kNoAction, kPopAndRepush, kPushVoid };
+  pcdiff_t pcdiff;  // adjustment to the program counter (positive or negative).
+  spdiff_t spdiff;  // number of elements to pop off the stack.
+  StackAction action;  // action to perform on the stack.
+};
+typedef ZoneMap<pc_t, ControlTransfer> ControlTransferMap;
+
+// Macro for defining union members.
+#define FOREACH_UNION_MEMBER(V) \
+  V(i32, kAstI32, int32_t)      \
+  V(u32, kAstI32, uint32_t)     \
+  V(i64, kAstI64, int64_t)      \
+  V(u64, kAstI64, uint64_t)     \
+  V(f32, kAstF32, float)        \
+  V(f64, kAstF64, double)
+
+// Representation of values within the interpreter.
+struct WasmVal {
+  LocalType type;
+  union {
+#define DECLARE_FIELD(field, localtype, ctype) ctype field;
+    FOREACH_UNION_MEMBER(DECLARE_FIELD)
+#undef DECLARE_FIELD
+  } val;
+
+  WasmVal() : type(kAstStmt) {}
+
+#define DECLARE_CONSTRUCTOR(field, localtype, ctype) \
+  explicit WasmVal(ctype v) : type(localtype) { val.field = v; }
+  FOREACH_UNION_MEMBER(DECLARE_CONSTRUCTOR)
+#undef DECLARE_CONSTRUCTOR
+
+  template <typename T>
+  T to() {
+    UNREACHABLE();
+  }
+};
+
+#define DECLARE_CAST(field, localtype, ctype) \
+  template <>                                 \
+  inline ctype WasmVal::to() {                \
+    CHECK_EQ(localtype, type);                \
+    return val.field;                         \
+  }
+FOREACH_UNION_MEMBER(DECLARE_CAST)
+#undef DECLARE_CAST
+
+template <>
+inline void WasmVal::to() {
+  CHECK_EQ(kAstStmt, type);
+}
+
+// Representation of frames within the interpreter.
+class WasmFrame {
+ public:
+  const WasmFunction* function() const { return function_; }
+  int pc() const { return pc_; }
+
+ private:
+  friend class WasmInterpreter;
+
+  WasmFrame(const WasmFunction* function, int pc, int fp, int sp)
+      : function_(function), pc_(pc), fp_(fp), sp_(sp) {}
+
+  const WasmFunction* function_;
+  int pc_;
+  int fp_;
+  int sp_;
+};
+
+// An interpreter capable of executing WASM.
+class WasmInterpreter {
+ public:
+  // State machine for a Thread:
+  //                       +---------------Run()-----------+
+  //                       V                               |
+  // STOPPED ---Run()-->  RUNNING  ------Pause()-----+-> PAUSED  <------+
+  //                       | | |                    /      |            |
+  //                       | | +---- Breakpoint ---+       +-- Step() --+
+  //                       | |
+  //                       | +------------ Trap --------------> TRAPPED
+  //                       +------------- Finish -------------> FINISHED
+  enum State { STOPPED, RUNNING, PAUSED, FINISHED, TRAPPED };
+
+  // Representation of a thread in the interpreter.
+  class Thread {
+   public:
+    // Execution control.
+    virtual State state() = 0;
+    virtual void PushFrame(const WasmFunction* function, WasmVal* args) = 0;
+    virtual State Run() = 0;
+    virtual State Step() = 0;
+    virtual void Pause() = 0;
+    virtual void Reset() = 0;
+    virtual ~Thread() {}
+
+    // Stack inspection and modification.
+    virtual pc_t GetBreakpointPc() = 0;
+    virtual int GetFrameCount() = 0;
+    virtual const WasmFrame* GetFrame(int index) = 0;
+    virtual WasmFrame* GetMutableFrame(int index) = 0;
+    virtual WasmVal GetReturnValue() = 0;
+
+    // Thread-specific breakpoints.
+    bool SetBreakpoint(const WasmFunction* function, int pc, bool enabled);
+    bool GetBreakpoint(const WasmFunction* function, int pc);
+  };
+
+  WasmInterpreter(WasmModuleInstance* instance,
+                  base::AccountingAllocator* allocator);
+  ~WasmInterpreter();
+
+  //==========================================================================
+  // Execution controls.
+  //==========================================================================
+  void Run();
+  void Pause();
+
+  // Set a breakpoint at {pc} in {function} to be {enabled}. Returns the
+  // previous state of the breakpoint at {pc}.
+  bool SetBreakpoint(const WasmFunction* function, pc_t pc, bool enabled);
+
+  // Gets the current state of the breakpoint at {function}.
+  bool GetBreakpoint(const WasmFunction* function, pc_t pc);
+
+  // Enable or disable tracing for {function}. Return the previous state.
+  bool SetTracing(const WasmFunction* function, bool enabled);
+
+  //==========================================================================
+  // Thread iteration and inspection.
+  //==========================================================================
+  int GetThreadCount();
+  Thread* GetThread(int id);
+
+  //==========================================================================
+  // Stack frame inspection.
+  //==========================================================================
+  WasmVal GetLocalVal(const WasmFrame* frame, int index);
+  WasmVal GetExprVal(const WasmFrame* frame, int pc);
+  void SetLocalVal(WasmFrame* frame, int index, WasmVal val);
+  void SetExprVal(WasmFrame* frame, int pc, WasmVal val);
+
+  //==========================================================================
+  // Memory access.
+  //==========================================================================
+  size_t GetMemorySize();
+  WasmVal ReadMemory(size_t offset);
+  void WriteMemory(size_t offset, WasmVal val);
+
+  //==========================================================================
+  // Testing functionality.
+  //==========================================================================
+  // Manually adds a function to this interpreter, returning the index of the
+  // function.
+  int AddFunctionForTesting(const WasmFunction* function);
+  // Manually adds code to the interpreter for the given function.
+  bool SetFunctionCodeForTesting(const WasmFunction* function,
+                                 const byte* start, const byte* end);
+
+  // Computes the control targets for the given bytecode as {pc offset, sp
+  // offset}
+  // pairs. Used internally in the interpreter, but exposed for testing.
+  static ControlTransferMap ComputeControlTransfersForTesting(Zone* zone,
+                                                              const byte* start,
+                                                              const byte* end);
+
+ private:
+  Zone zone_;
+  WasmInterpreterInternals* internals_;
+};
+
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_WASM_INTERPRETER_H_
diff --git a/src/wasm/wasm-js.cc b/src/wasm/wasm-js.cc
index 83009d7..6dc1495 100644
--- a/src/wasm/wasm-js.cc
+++ b/src/wasm/wasm-js.cc
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "src/api.h"
 #include "src/api-natives.h"
+#include "src/api.h"
 #include "src/assert-scope.h"
 #include "src/ast/ast.h"
 #include "src/ast/scopes.h"
+#include "src/execution.h"
 #include "src/factory.h"
 #include "src/handles.h"
 #include "src/isolate.h"
@@ -34,31 +35,25 @@
   size_t size() { return static_cast<size_t>(end - start); }
 };
 
-
-RawBuffer GetRawBufferArgument(
-    ErrorThrower& thrower, const v8::FunctionCallbackInfo<v8::Value>& args) {
-  if (args.Length() < 1) {
-    thrower.Error("Argument 0 must be an array buffer");
-    return {nullptr, nullptr};
-  }
-
+RawBuffer GetRawBufferSource(
+    v8::Local<v8::Value> source, ErrorThrower* thrower) {
   const byte* start = nullptr;
   const byte* end = nullptr;
 
-  if (args[0]->IsArrayBuffer()) {
+  if (source->IsArrayBuffer()) {
     // A raw array buffer was passed.
-    Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[0]);
+    Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source);
     ArrayBuffer::Contents contents = buffer->GetContents();
 
     start = reinterpret_cast<const byte*>(contents.Data());
     end = start + contents.ByteLength();
 
     if (start == nullptr || end == start) {
-      thrower.Error("ArrayBuffer argument is empty");
+      thrower->Error("ArrayBuffer argument is empty");
     }
-  } else if (args[0]->IsTypedArray()) {
+  } else if (source->IsTypedArray()) {
     // A TypedArray was passed.
-    Local<TypedArray> array = Local<TypedArray>::Cast(args[0]);
+    Local<TypedArray> array = Local<TypedArray>::Cast(source);
     Local<ArrayBuffer> buffer = array->Buffer();
 
     ArrayBuffer::Contents contents = buffer->GetContents();
@@ -68,22 +63,25 @@
     end = start + array->ByteLength();
 
     if (start == nullptr || end == start) {
-      thrower.Error("ArrayBuffer argument is empty");
+      thrower->Error("ArrayBuffer argument is empty");
     }
   } else {
-    thrower.Error("Argument 0 must be an ArrayBuffer or Uint8Array");
+    thrower->Error("Argument 0 must be an ArrayBuffer or Uint8Array");
   }
 
   return {start, end};
 }
 
-
 void VerifyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
   HandleScope scope(args.GetIsolate());
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
-  ErrorThrower thrower(isolate, "WASM.verifyModule()");
+  ErrorThrower thrower(isolate, "Wasm.verifyModule()");
 
-  RawBuffer buffer = GetRawBufferArgument(thrower, args);
+  if (args.Length() < 1) {
+    thrower.Error("Argument 0 must be a buffer source");
+    return;
+  }
+  RawBuffer buffer = GetRawBufferSource(args[0], &thrower);
   if (thrower.error()) return;
 
   i::Zone zone(isolate->allocator());
@@ -98,13 +96,16 @@
   if (result.val) delete result.val;
 }
 
-
 void VerifyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) {
   HandleScope scope(args.GetIsolate());
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
-  ErrorThrower thrower(isolate, "WASM.verifyFunction()");
+  ErrorThrower thrower(isolate, "Wasm.verifyFunction()");
 
-  RawBuffer buffer = GetRawBufferArgument(thrower, args);
+  if (args.Length() < 1) {
+    thrower.Error("Argument 0 must be a buffer source");
+    return;
+  }
+  RawBuffer buffer = GetRawBufferSource(args[0], &thrower);
   if (thrower.error()) return;
 
   internal::wasm::FunctionResult result;
@@ -123,8 +124,9 @@
   if (result.val) delete result.val;
 }
 
-v8::internal::wasm::WasmModuleIndex* TranslateAsmModule(
-    i::ParseInfo* info, i::Handle<i::Object> foreign, ErrorThrower* thrower) {
+v8::internal::wasm::ZoneBuffer* TranslateAsmModule(
+    i::ParseInfo* info, ErrorThrower* thrower,
+    i::Handle<i::FixedArray>* foreign_args) {
   info->set_global();
   info->set_lazy(false);
   info->set_allow_lazy_parsing(false);
@@ -134,6 +136,11 @@
     return nullptr;
   }
 
+  if (info->scope()->declarations()->length() == 0) {
+    thrower->Error("Asm.js validation failed: no declarations in scope");
+    return nullptr;
+  }
+
   info->set_literal(
       info->scope()->declarations()->at(0)->AsFunctionDeclaration()->fun());
 
@@ -147,61 +154,58 @@
     return nullptr;
   }
 
-  auto module =
-      v8::internal::wasm::AsmWasmBuilder(info->isolate(), info->zone(),
-                                         info->literal(), foreign, &typer)
-          .Run();
+  v8::internal::wasm::AsmWasmBuilder builder(info->isolate(), info->zone(),
+                                             info->literal(), &typer);
 
-  return module;
+  return builder.Run(foreign_args);
 }
 
-void InstantiateModuleCommon(const v8::FunctionCallbackInfo<v8::Value>& args,
-                             const byte* start, const byte* end,
-                             ErrorThrower* thrower,
-                             internal::wasm::ModuleOrigin origin) {
+i::MaybeHandle<i::JSObject> InstantiateModuleCommon(
+    const v8::FunctionCallbackInfo<v8::Value>& args, const byte* start,
+    const byte* end, ErrorThrower* thrower,
+    internal::wasm::ModuleOrigin origin = i::wasm::kWasmOrigin) {
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
 
-  i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null();
-  if (args.Length() > 2 && args[2]->IsArrayBuffer()) {
-    Local<Object> obj = Local<Object>::Cast(args[2]);
-    i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj);
-    memory = i::Handle<i::JSArrayBuffer>(i::JSArrayBuffer::cast(*mem_obj));
-  }
-
   // Decode but avoid a redundant pass over function bodies for verification.
   // Verification will happen during compilation.
   i::Zone zone(isolate->allocator());
   internal::wasm::ModuleResult result = internal::wasm::DecodeWasmModule(
       isolate, &zone, start, end, false, origin);
 
+  i::MaybeHandle<i::JSObject> object;
   if (result.failed() && origin == internal::wasm::kAsmJsOrigin) {
     thrower->Error("Asm.js converted module failed to decode");
   } else if (result.failed()) {
     thrower->Failed("", result);
   } else {
     // Success. Instantiate the module and return the object.
-    i::Handle<i::JSObject> ffi = i::Handle<i::JSObject>::null();
+    i::Handle<i::JSReceiver> ffi = i::Handle<i::JSObject>::null();
     if (args.Length() > 1 && args[1]->IsObject()) {
       Local<Object> obj = Local<Object>::Cast(args[1]);
-      ffi = i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*obj));
+      ffi = i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj));
     }
 
-    i::MaybeHandle<i::JSObject> object =
-        result.val->Instantiate(isolate, ffi, memory);
+    i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null();
+    if (args.Length() > 2 && args[2]->IsArrayBuffer()) {
+      Local<Object> obj = Local<Object>::Cast(args[2]);
+      i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj);
+      memory = i::Handle<i::JSArrayBuffer>(i::JSArrayBuffer::cast(*mem_obj));
+    }
 
+    object = result.val->Instantiate(isolate, ffi, memory);
     if (!object.is_null()) {
       args.GetReturnValue().Set(v8::Utils::ToLocal(object.ToHandleChecked()));
     }
   }
 
   if (result.val) delete result.val;
+  return object;
 }
 
-
 void InstantiateModuleFromAsm(const v8::FunctionCallbackInfo<v8::Value>& args) {
   HandleScope scope(args.GetIsolate());
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
-  ErrorThrower thrower(isolate, "WASM.instantiateModuleFromAsm()");
+  ErrorThrower thrower(isolate, "Wasm.instantiateModuleFromAsm()");
 
   if (!args[0]->IsString()) {
     thrower.Error("Asm module text should be a string");
@@ -220,30 +224,160 @@
     foreign = v8::Utils::OpenHandle(*local_foreign);
   }
 
-  auto module = TranslateAsmModule(&info, foreign, &thrower);
+  i::Handle<i::FixedArray> foreign_args;
+  auto module = TranslateAsmModule(&info, &thrower, &foreign_args);
   if (module == nullptr) {
     return;
   }
 
-  InstantiateModuleCommon(args, module->Begin(), module->End(), &thrower,
-                          internal::wasm::kAsmJsOrigin);
-}
+  i::MaybeHandle<i::Object> maybe_module_object =
+      InstantiateModuleCommon(args, module->begin(), module->end(), &thrower,
+                              internal::wasm::kAsmJsOrigin);
+  if (maybe_module_object.is_null()) {
+    return;
+  }
 
+  i::Handle<i::Name> name =
+      factory->NewStringFromStaticChars("__foreign_init__");
+
+  i::Handle<i::Object> module_object = maybe_module_object.ToHandleChecked();
+  i::MaybeHandle<i::Object> maybe_init =
+      i::Object::GetProperty(module_object, name);
+  DCHECK(!maybe_init.is_null());
+
+  i::Handle<i::Object> init = maybe_init.ToHandleChecked();
+  i::Handle<i::Object> undefined = isolate->factory()->undefined_value();
+  i::Handle<i::Object>* foreign_args_array =
+      new i::Handle<i::Object>[foreign_args->length()];
+  for (int j = 0; j < foreign_args->length(); j++) {
+    if (!foreign.is_null()) {
+      i::MaybeHandle<i::Name> name = i::Object::ToName(
+          isolate, i::Handle<i::Object>(foreign_args->get(j), isolate));
+      if (!name.is_null()) {
+        i::MaybeHandle<i::Object> val =
+            i::Object::GetProperty(foreign, name.ToHandleChecked());
+        if (!val.is_null()) {
+          foreign_args_array[j] = val.ToHandleChecked();
+          continue;
+        }
+      }
+    }
+    foreign_args_array[j] = undefined;
+  }
+  i::MaybeHandle<i::Object> retval = i::Execution::Call(
+      isolate, init, undefined, foreign_args->length(), foreign_args_array);
+  delete[] foreign_args_array;
+
+  if (retval.is_null()) {
+    thrower.Error(
+        "WASM.instantiateModuleFromAsm(): foreign init function failed");
+  }
+}
 
 void InstantiateModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
   HandleScope scope(args.GetIsolate());
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
-  ErrorThrower thrower(isolate, "WASM.instantiateModule()");
+  ErrorThrower thrower(isolate, "Wasm.instantiateModule()");
 
-  RawBuffer buffer = GetRawBufferArgument(thrower, args);
+  if (args.Length() < 1) {
+    thrower.Error("Argument 0 must be a buffer source");
+    return;
+  }
+  RawBuffer buffer = GetRawBufferSource(args[0], &thrower);
   if (buffer.start == nullptr) return;
 
-  InstantiateModuleCommon(args, buffer.start, buffer.end, &thrower,
-                          internal::wasm::kWasmOrigin);
+  InstantiateModuleCommon(args, buffer.start, buffer.end, &thrower);
+}
+
+
+static i::MaybeHandle<i::JSObject> CreateModuleObject(
+    v8::Isolate* isolate, const v8::Local<v8::Value> source,
+    ErrorThrower* thrower) {
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+
+  RawBuffer buffer = GetRawBufferSource(source, thrower);
+  if (buffer.start == nullptr) return i::MaybeHandle<i::JSObject>();
+
+  // TODO(rossberg): Once we can, do compilation here.
+  DCHECK(source->IsArrayBuffer() || source->IsTypedArray());
+  Local<Context> context = isolate->GetCurrentContext();
+  i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
+  i::Handle<i::JSFunction> module_cons(i_context->wasm_module_constructor());
+  i::Handle<i::JSObject> module_obj =
+      i_isolate->factory()->NewJSObject(module_cons);
+  i::Handle<i::Object> module_ref = Utils::OpenHandle(*source);
+  i::Handle<i::Symbol> module_sym(i_context->wasm_module_sym());
+  i::Object::SetProperty(module_obj, module_sym, module_ref, i::STRICT).Check();
+
+  return module_obj;
+}
+
+void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  v8::Isolate* isolate = args.GetIsolate();
+  HandleScope scope(isolate);
+  ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate),
+                       "WebAssembly.compile()");
+
+  if (args.Length() < 1) {
+    thrower.Error("Argument 0 must be a buffer source");
+    return;
+  }
+  i::MaybeHandle<i::JSObject> module_obj =
+      CreateModuleObject(isolate, args[0], &thrower);
+  if (module_obj.is_null()) return;
+
+  Local<Context> context = isolate->GetCurrentContext();
+  v8::Local<v8::Promise::Resolver> resolver;
+  if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return;
+  resolver->Resolve(context, Utils::ToLocal(module_obj.ToHandleChecked()));
+
+  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
+  return_value.Set(resolver->GetPromise());
+}
+
+void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  v8::Isolate* isolate = args.GetIsolate();
+  HandleScope scope(isolate);
+  ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate),
+                       "WebAssembly.Module()");
+
+  if (args.Length() < 1) {
+    thrower.Error("Argument 0 must be a buffer source");
+    return;
+  }
+  i::MaybeHandle<i::JSObject> module_obj =
+      CreateModuleObject(isolate, args[0], &thrower);
+  if (module_obj.is_null()) return;
+
+  v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
+  return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked()));
+}
+
+void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  HandleScope scope(args.GetIsolate());
+  v8::Isolate* isolate = args.GetIsolate();
+  ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate),
+                       "WebAssembly.Instance()");
+
+  if (args.Length() < 1) {
+    thrower.Error("Argument 0 must be a WebAssembly.Module");
+    return;
+  }
+  Local<Context> context = isolate->GetCurrentContext();
+  i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
+  i::Handle<i::Symbol> module_sym(i_context->wasm_module_sym());
+  i::MaybeHandle<i::Object> source =
+      i::Object::GetProperty(Utils::OpenHandle(*args[0]), module_sym);
+  if (source.is_null()) return;
+
+  RawBuffer buffer =
+      GetRawBufferSource(Utils::ToLocal(source.ToHandleChecked()), &thrower);
+  if (buffer.start == nullptr) return;
+
+  InstantiateModuleCommon(args, buffer.start, buffer.end, &thrower);
 }
 }  // namespace
 
-
 // TODO(titzer): we use the API to create the function template because the
 // internal guts are too ugly to replicate here.
 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate,
@@ -253,15 +387,13 @@
   return v8::Utils::OpenHandle(*local);
 }
 
-
 namespace internal {
 static Handle<String> v8_str(Isolate* isolate, const char* str) {
   return isolate->factory()->NewStringFromAsciiChecked(str);
 }
 
-
-static void InstallFunc(Isolate* isolate, Handle<JSObject> object,
-                        const char* str, FunctionCallback func) {
+static Handle<JSFunction> InstallFunc(Isolate* isolate, Handle<JSObject> object,
+                                      const char* str, FunctionCallback func) {
   Handle<String> name = v8_str(isolate, str);
   Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func);
   Handle<JSFunction> function =
@@ -269,17 +401,54 @@
   PropertyAttributes attributes =
       static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
   JSObject::AddProperty(object, name, function, attributes);
+  return function;
 }
 
-
 void WasmJs::Install(Isolate* isolate, Handle<JSGlobalObject> global) {
+  Factory* factory = isolate->factory();
+
   // Setup wasm function map.
   Handle<Context> context(global->native_context(), isolate);
   InstallWasmFunctionMap(isolate, context);
 
-  // Bind the WASM object.
-  Factory* factory = isolate->factory();
-  Handle<String> name = v8_str(isolate, "Wasm");
+  // Bind the experimental WASM object.
+  // TODO(rossberg, titzer): remove once it's no longer needed.
+  {
+    Handle<String> name = v8_str(isolate, "Wasm");
+    Handle<JSFunction> cons = factory->NewFunction(name);
+    JSFunction::SetInstancePrototype(
+        cons, Handle<Object>(context->initial_object_prototype(), isolate));
+    cons->shared()->set_instance_class_name(*name);
+    Handle<JSObject> wasm_object = factory->NewJSObject(cons, TENURED);
+    PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM);
+    JSObject::AddProperty(global, name, wasm_object, attributes);
+
+    // Install functions on the WASM object.
+    InstallFunc(isolate, wasm_object, "verifyModule", VerifyModule);
+    InstallFunc(isolate, wasm_object, "verifyFunction", VerifyFunction);
+    InstallFunc(isolate, wasm_object, "instantiateModule", InstantiateModule);
+    InstallFunc(isolate, wasm_object, "instantiateModuleFromAsm",
+                InstantiateModuleFromAsm);
+
+    {
+      // Add the Wasm.experimentalVersion property.
+      Handle<String> name = v8_str(isolate, "experimentalVersion");
+      PropertyAttributes attributes =
+          static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
+      Handle<Smi> value =
+          Handle<Smi>(Smi::FromInt(wasm::kWasmVersion), isolate);
+      JSObject::AddProperty(wasm_object, name, value, attributes);
+    }
+  }
+
+  // Create private symbols.
+  Handle<Symbol> module_sym = isolate->factory()->NewPrivateSymbol();
+  Handle<Symbol> instance_sym = isolate->factory()->NewPrivateSymbol();
+  context->set_wasm_module_sym(*module_sym);
+  context->set_wasm_instance_sym(*instance_sym);
+
+  // Bind the WebAssembly object.
+  Handle<String> name = v8_str(isolate, "WebAssembly");
   Handle<JSFunction> cons = factory->NewFunction(name);
   JSFunction::SetInstancePrototype(
       cons, Handle<Object>(context->initial_object_prototype(), isolate));
@@ -288,15 +457,16 @@
   PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM);
   JSObject::AddProperty(global, name, wasm_object, attributes);
 
-  // Install functions on the WASM object.
-  InstallFunc(isolate, wasm_object, "verifyModule", VerifyModule);
-  InstallFunc(isolate, wasm_object, "verifyFunction", VerifyFunction);
-  InstallFunc(isolate, wasm_object, "instantiateModule", InstantiateModule);
-  InstallFunc(isolate, wasm_object, "instantiateModuleFromAsm",
-              InstantiateModuleFromAsm);
+  // Install static methods on WebAssembly object.
+  InstallFunc(isolate, wasm_object, "compile", WebAssemblyCompile);
+  Handle<JSFunction> module_constructor =
+      InstallFunc(isolate, wasm_object, "Module", WebAssemblyModule);
+  Handle<JSFunction> instance_constructor =
+      InstallFunc(isolate, wasm_object, "Instance", WebAssemblyInstance);
+  context->set_wasm_module_constructor(*module_constructor);
+  context->set_wasm_instance_constructor(*instance_constructor);
 }
 
-
 void WasmJs::InstallWasmFunctionMap(Isolate* isolate, Handle<Context> context) {
   if (!context->get(Context::WASM_FUNCTION_MAP_INDEX)->IsMap()) {
     // TODO(titzer): Move this to bootstrapper.cc??
diff --git a/src/wasm/wasm-js.h b/src/wasm/wasm-js.h
index e7305aa..ded9a1a 100644
--- a/src/wasm/wasm-js.h
+++ b/src/wasm/wasm-js.h
@@ -7,7 +7,7 @@
 
 #ifndef V8_SHARED
 #include "src/allocation.h"
-#include "src/hashmap.h"
+#include "src/base/hashmap.h"
 #else
 #include "include/v8.h"
 #include "src/base/compiler-specific.h"
diff --git a/src/wasm/wasm-macro-gen.h b/src/wasm/wasm-macro-gen.h
index d9199e8..d08d709 100644
--- a/src/wasm/wasm-macro-gen.h
+++ b/src/wasm/wasm-macro-gen.h
@@ -7,6 +7,8 @@
 
 #include "src/wasm/wasm-opcodes.h"
 
+#include "src/zone-containers.h"
+
 #define U32_LE(v)                                    \
   static_cast<byte>(v), static_cast<byte>((v) >> 8), \
       static_cast<byte>((v) >> 16), static_cast<byte>((v) >> 24)
@@ -58,27 +60,38 @@
 //------------------------------------------------------------------------------
 #define WASM_NOP kExprNop
 
-#define WASM_BLOCK(count, ...) kExprBlock, static_cast<byte>(count), __VA_ARGS__
-#define WASM_INFINITE_LOOP kExprLoop, 1, kExprBr, 0, kExprNop
-#define WASM_LOOP(count, ...) kExprLoop, static_cast<byte>(count), __VA_ARGS__
-#define WASM_IF(cond, tstmt) kExprIf, cond, tstmt
-#define WASM_IF_ELSE(cond, tstmt, fstmt) kExprIfElse, cond, tstmt, fstmt
-#define WASM_SELECT(cond, tval, fval) kExprSelect, cond, tval, fval
-#define WASM_BR(depth) kExprBr, static_cast<byte>(depth), kExprNop
+#define ARITY_0 0
+#define ARITY_1 1
+#define DEPTH_0 0
+#define DEPTH_1 1
+
+#define WASM_BLOCK(count, ...) kExprBlock, __VA_ARGS__, kExprEnd
+#define WASM_INFINITE_LOOP kExprLoop, kExprBr, ARITY_0, DEPTH_0, kExprEnd
+#define WASM_LOOP(count, ...) kExprLoop, __VA_ARGS__, kExprEnd
+#define WASM_IF(cond, tstmt) cond, kExprIf, tstmt, kExprEnd
+#define WASM_IF_ELSE(cond, tstmt, fstmt) \
+  cond, kExprIf, tstmt, kExprElse, fstmt, kExprEnd
+#define WASM_SELECT(tval, fval, cond) tval, fval, cond, kExprSelect
+#define WASM_BR(depth) kExprBr, ARITY_0, static_cast<byte>(depth)
 #define WASM_BR_IF(depth, cond) \
-  kExprBrIf, static_cast<byte>(depth), kExprNop, cond
-#define WASM_BRV(depth, val) kExprBr, static_cast<byte>(depth), val
+  cond, kExprBrIf, ARITY_0, static_cast<byte>(depth)
+#define WASM_BRV(depth, val) val, kExprBr, ARITY_1, static_cast<byte>(depth)
 #define WASM_BRV_IF(depth, val, cond) \
-  kExprBrIf, static_cast<byte>(depth), val, cond
-#define WASM_BREAK(depth) kExprBr, static_cast<byte>(depth + 1), kExprNop
-#define WASM_CONTINUE(depth) kExprBr, static_cast<byte>(depth), kExprNop
-#define WASM_BREAKV(depth, val) kExprBr, static_cast<byte>(depth + 1), val
-#define WASM_RETURN0 kExprReturn
-#define WASM_RETURN(...) kExprReturn, __VA_ARGS__
+  val, cond, kExprBrIf, ARITY_1, static_cast<byte>(depth)
+#define WASM_BREAK(depth) kExprBr, ARITY_0, static_cast<byte>(depth + 1)
+#define WASM_CONTINUE(depth) kExprBr, ARITY_0, static_cast<byte>(depth)
+#define WASM_BREAKV(depth, val) \
+  val, kExprBr, ARITY_1, static_cast<byte>(depth + 1)
+#define WASM_RETURN0 kExprReturn, ARITY_0
+#define WASM_RETURN1(val) val, kExprReturn, ARITY_1
+#define WASM_RETURNN(count, ...) __VA_ARGS__, kExprReturn, count
 #define WASM_UNREACHABLE kExprUnreachable
 
 #define WASM_BR_TABLE(key, count, ...) \
-  kExprBrTable, U32V_1(count), __VA_ARGS__, key
+  key, kExprBrTable, ARITY_0, U32V_1(count), __VA_ARGS__
+
+#define WASM_BR_TABLEV(val, key, count, ...) \
+  val, key, kExprBrTable, ARITY_1, U32V_1(count), __VA_ARGS__
 
 #define WASM_CASE(x) static_cast<byte>(x), static_cast<byte>(x >> 8)
 #define WASM_CASE_BR(x) static_cast<byte>(x), static_cast<byte>(0x80 | (x) >> 8)
@@ -119,13 +132,17 @@
 
 // A helper for encoding local declarations prepended to the body of a
 // function.
+// TODO(titzer): move this to an appropriate header.
 class LocalDeclEncoder {
  public:
+  explicit LocalDeclEncoder(Zone* zone, FunctionSig* s = nullptr)
+      : sig(s), local_decls(zone), total(0) {}
+
   // Prepend local declarations by creating a new buffer and copying data
   // over. The new buffer must be delete[]'d by the caller.
-  void Prepend(const byte** start, const byte** end) const {
+  void Prepend(Zone* zone, const byte** start, const byte** end) const {
     size_t size = (*end - *start);
-    byte* buffer = new byte[Size() + size];
+    byte* buffer = reinterpret_cast<byte*>(zone->New(Size() + size));
     size_t pos = Emit(buffer);
     memcpy(buffer + pos, *start, size);
     pos += size;
@@ -136,7 +153,7 @@
   size_t Emit(byte* buffer) const {
     size_t pos = 0;
     pos = WriteUint32v(buffer, pos, static_cast<uint32_t>(local_decls.size()));
-    for (size_t i = 0; i < local_decls.size(); i++) {
+    for (size_t i = 0; i < local_decls.size(); ++i) {
       pos = WriteUint32v(buffer, pos, local_decls[i].first);
       buffer[pos++] = WasmOpcodes::LocalTypeCodeFor(local_decls[i].second);
     }
@@ -146,19 +163,16 @@
 
   // Add locals declarations to this helper. Return the index of the newly added
   // local(s), with an optional adjustment for the parameters.
-  uint32_t AddLocals(uint32_t count, LocalType type,
-                     FunctionSig* sig = nullptr) {
-    if (count == 0) {
-      return static_cast<uint32_t>((sig ? sig->parameter_count() : 0) +
-                                   local_decls.size());
-    }
-    size_t pos = local_decls.size();
+  uint32_t AddLocals(uint32_t count, LocalType type) {
+    uint32_t result =
+        static_cast<uint32_t>(total + (sig ? sig->parameter_count() : 0));
+    total += count;
     if (local_decls.size() > 0 && local_decls.back().second == type) {
       count += local_decls.back().first;
       local_decls.pop_back();
     }
     local_decls.push_back(std::pair<uint32_t, LocalType>(count, type));
-    return static_cast<uint32_t>(pos + (sig ? sig->parameter_count() : 0));
+    return result;
   }
 
   size_t Size() const {
@@ -167,8 +181,14 @@
     return size;
   }
 
+  bool has_sig() const { return sig != nullptr; }
+  FunctionSig* get_sig() const { return sig; }
+  void set_sig(FunctionSig* s) { sig = s; }
+
  private:
-  std::vector<std::pair<uint32_t, LocalType>> local_decls;
+  FunctionSig* sig;
+  ZoneVector<std::pair<uint32_t, LocalType>> local_decls;
+  size_t total;
 
   size_t SizeofUint32v(uint32_t val) const {
     size_t size = 1;
@@ -322,193 +342,260 @@
       static_cast<byte>(bit_cast<uint64_t>(val) >> 48),      \
       static_cast<byte>(bit_cast<uint64_t>(val) >> 56)
 #define WASM_GET_LOCAL(index) kExprGetLocal, static_cast<byte>(index)
-#define WASM_SET_LOCAL(index, val) kExprSetLocal, static_cast<byte>(index), val
+#define WASM_SET_LOCAL(index, val) val, kExprSetLocal, static_cast<byte>(index)
 #define WASM_LOAD_GLOBAL(index) kExprLoadGlobal, static_cast<byte>(index)
 #define WASM_STORE_GLOBAL(index, val) \
-  kExprStoreGlobal, static_cast<byte>(index), val
-#define WASM_LOAD_MEM(type, index)                                      \
-  static_cast<byte>(                                                    \
-      v8::internal::wasm::WasmOpcodes::LoadStoreOpcodeOf(type, false)), \
-      ZERO_ALIGNMENT, ZERO_OFFSET, index
-#define WASM_STORE_MEM(type, index, val)                               \
-  static_cast<byte>(                                                   \
-      v8::internal::wasm::WasmOpcodes::LoadStoreOpcodeOf(type, true)), \
-      ZERO_ALIGNMENT, ZERO_OFFSET, index, val
-#define WASM_LOAD_MEM_OFFSET(type, offset, index)                       \
-  static_cast<byte>(                                                    \
-      v8::internal::wasm::WasmOpcodes::LoadStoreOpcodeOf(type, false)), \
-      ZERO_ALIGNMENT, U32V_1(offset), index
-#define WASM_STORE_MEM_OFFSET(type, offset, index, val)                \
-  static_cast<byte>(                                                   \
-      v8::internal::wasm::WasmOpcodes::LoadStoreOpcodeOf(type, true)), \
-      ZERO_ALIGNMENT, U32V_1(offset), index, val
-#define WASM_CALL_FUNCTION(index, ...) \
-  kExprCallFunction, static_cast<byte>(index), __VA_ARGS__
-#define WASM_CALL_IMPORT(index, ...) \
-  kExprCallImport, static_cast<byte>(index), __VA_ARGS__
-#define WASM_CALL_INDIRECT(index, func, ...) \
-  kExprCallIndirect, static_cast<byte>(index), func, __VA_ARGS__
-#define WASM_CALL_FUNCTION0(index) kExprCallFunction, static_cast<byte>(index)
-#define WASM_CALL_IMPORT0(index) kExprCallImport, static_cast<byte>(index)
+  val, kExprStoreGlobal, static_cast<byte>(index)
+#define WASM_LOAD_MEM(type, index)                                             \
+  index, static_cast<byte>(                                                    \
+             v8::internal::wasm::WasmOpcodes::LoadStoreOpcodeOf(type, false)), \
+      ZERO_ALIGNMENT, ZERO_OFFSET
+#define WASM_STORE_MEM(type, index, val)                                   \
+  index, val,                                                              \
+      static_cast<byte>(                                                   \
+          v8::internal::wasm::WasmOpcodes::LoadStoreOpcodeOf(type, true)), \
+      ZERO_ALIGNMENT, ZERO_OFFSET
+#define WASM_LOAD_MEM_OFFSET(type, offset, index)                              \
+  index, static_cast<byte>(                                                    \
+             v8::internal::wasm::WasmOpcodes::LoadStoreOpcodeOf(type, false)), \
+      ZERO_ALIGNMENT, static_cast<byte>(offset)
+#define WASM_STORE_MEM_OFFSET(type, offset, index, val)                    \
+  index, val,                                                              \
+      static_cast<byte>(                                                   \
+          v8::internal::wasm::WasmOpcodes::LoadStoreOpcodeOf(type, true)), \
+      ZERO_ALIGNMENT, static_cast<byte>(offset)
+#define WASM_LOAD_MEM_ALIGNMENT(type, index, alignment)                        \
+  index, static_cast<byte>(                                                    \
+             v8::internal::wasm::WasmOpcodes::LoadStoreOpcodeOf(type, false)), \
+      alignment, ZERO_OFFSET
+#define WASM_STORE_MEM_ALIGNMENT(type, index, alignment, val)              \
+  index, val,                                                              \
+      static_cast<byte>(                                                   \
+          v8::internal::wasm::WasmOpcodes::LoadStoreOpcodeOf(type, true)), \
+      alignment, ZERO_OFFSET
+
+#define WASM_CALL_FUNCTION0(index) \
+  kExprCallFunction, 0, static_cast<byte>(index)
+#define WASM_CALL_FUNCTION1(index, a) \
+  a, kExprCallFunction, 1, static_cast<byte>(index)
+#define WASM_CALL_FUNCTION2(index, a, b) \
+  a, b, kExprCallFunction, 2, static_cast<byte>(index)
+#define WASM_CALL_FUNCTION3(index, a, b, c) \
+  a, b, c, kExprCallFunction, 3, static_cast<byte>(index)
+#define WASM_CALL_FUNCTION4(index, a, b, c, d) \
+  a, b, c, d, kExprCallFunction, 4, static_cast<byte>(index)
+#define WASM_CALL_FUNCTION5(index, a, b, c, d, e) \
+  kExprCallFunction, 5, static_cast<byte>(index)
+#define WASM_CALL_FUNCTIONN(arity, index, ...) \
+  __VA_ARGS__, kExprCallFunction, arity, static_cast<byte>(index)
+
+#define WASM_CALL_IMPORT0(index) kExprCallImport, 0, static_cast<byte>(index)
+#define WASM_CALL_IMPORT1(index, a) \
+  a, kExprCallImport, 1, static_cast<byte>(index)
+#define WASM_CALL_IMPORT2(index, a, b) \
+  a, b, kExprCallImport, 2, static_cast<byte>(index)
+#define WASM_CALL_IMPORT3(index, a, b, c) \
+  a, b, c, kExprCallImport, 3, static_cast<byte>(index)
+#define WASM_CALL_IMPORT4(index, a, b, c, d) \
+  a, b, c, d, kExprCallImport, 4, static_cast<byte>(index)
+#define WASM_CALL_IMPORT5(index, a, b, c, d, e) \
+  a, b, c, d, e, kExprCallImport, 5, static_cast<byte>(index)
+#define WASM_CALL_IMPORTN(arity, index, ...) \
+  __VA_ARGS__, kExprCallImport, U32V_1(arity), static_cast<byte>(index),
+
 #define WASM_CALL_INDIRECT0(index, func) \
-  kExprCallIndirect, static_cast<byte>(index), func
-#define WASM_NOT(x) kExprI32Eqz, x
+  func, kExprCallIndirect, 0, static_cast<byte>(index)
+#define WASM_CALL_INDIRECT1(index, func, a) \
+  func, a, kExprCallIndirect, 1, static_cast<byte>(index)
+#define WASM_CALL_INDIRECT2(index, func, a, b) \
+  func, a, b, kExprCallIndirect, 2, static_cast<byte>(index)
+#define WASM_CALL_INDIRECT3(index, func, a, b, c) \
+  func, a, b, c, kExprCallIndirect, 3, static_cast<byte>(index)
+#define WASM_CALL_INDIRECT4(index, func, a, b, c, d) \
+  func, a, b, c, d, kExprCallIndirect, 4, static_cast<byte>(index)
+#define WASM_CALL_INDIRECT5(index, func, a, b, c, d, e) \
+  func, a, b, c, d, e, kExprCallIndirect, 5, static_cast<byte>(index)
+#define WASM_CALL_INDIRECTN(arity, index, func, ...) \
+  func, __VA_ARGS__, kExprCallIndirect, U32V_1(arity), static_cast<byte>(index)
+
+#define WASM_NOT(x) x, kExprI32Eqz
+#define WASM_SEQ(...) __VA_ARGS__
 
 //------------------------------------------------------------------------------
 // Constructs that are composed of multiple bytecodes.
 //------------------------------------------------------------------------------
-#define WASM_WHILE(x, y) kExprLoop, 1, kExprIf, x, kExprBr, 0, y
-#define WASM_INC_LOCAL(index)                                          \
-  kExprSetLocal, static_cast<byte>(index), kExprI32Add, kExprGetLocal, \
-      static_cast<byte>(index), kExprI8Const, 1
-#define WASM_INC_LOCAL_BY(index, count)                                \
-  kExprSetLocal, static_cast<byte>(index), kExprI32Add, kExprGetLocal, \
-      static_cast<byte>(index), kExprI8Const, static_cast<int8_t>(count)
-
-#define WASM_UNOP(opcode, x) static_cast<byte>(opcode), x
-#define WASM_BINOP(opcode, x, y) static_cast<byte>(opcode), x, y
+#define WASM_WHILE(x, y) \
+  kExprLoop, x, kExprIf, y, kExprBr, ARITY_1, DEPTH_1, kExprEnd, kExprEnd
+#define WASM_INC_LOCAL(index)                                            \
+  kExprGetLocal, static_cast<byte>(index), kExprI8Const, 1, kExprI32Add, \
+      kExprSetLocal, static_cast<byte>(index)
+#define WASM_INC_LOCAL_BY(index, count)                     \
+  kExprGetLocal, static_cast<byte>(index), kExprI8Const,    \
+      static_cast<byte>(count), kExprI32Add, kExprSetLocal, \
+      static_cast<byte>(index)
+#define WASM_UNOP(opcode, x) x, static_cast<byte>(opcode)
+#define WASM_BINOP(opcode, x, y) x, y, static_cast<byte>(opcode)
 
 //------------------------------------------------------------------------------
 // Int32 operations
 //------------------------------------------------------------------------------
-#define WASM_I32_ADD(x, y) kExprI32Add, x, y
-#define WASM_I32_SUB(x, y) kExprI32Sub, x, y
-#define WASM_I32_MUL(x, y) kExprI32Mul, x, y
-#define WASM_I32_DIVS(x, y) kExprI32DivS, x, y
-#define WASM_I32_DIVU(x, y) kExprI32DivU, x, y
-#define WASM_I32_REMS(x, y) kExprI32RemS, x, y
-#define WASM_I32_REMU(x, y) kExprI32RemU, x, y
-#define WASM_I32_AND(x, y) kExprI32And, x, y
-#define WASM_I32_IOR(x, y) kExprI32Ior, x, y
-#define WASM_I32_XOR(x, y) kExprI32Xor, x, y
-#define WASM_I32_SHL(x, y) kExprI32Shl, x, y
-#define WASM_I32_SHR(x, y) kExprI32ShrU, x, y
-#define WASM_I32_SAR(x, y) kExprI32ShrS, x, y
-#define WASM_I32_ROR(x, y) kExprI32Ror, x, y
-#define WASM_I32_ROL(x, y) kExprI32Rol, x, y
-#define WASM_I32_EQ(x, y) kExprI32Eq, x, y
-#define WASM_I32_NE(x, y) kExprI32Ne, x, y
-#define WASM_I32_LTS(x, y) kExprI32LtS, x, y
-#define WASM_I32_LES(x, y) kExprI32LeS, x, y
-#define WASM_I32_LTU(x, y) kExprI32LtU, x, y
-#define WASM_I32_LEU(x, y) kExprI32LeU, x, y
-#define WASM_I32_GTS(x, y) kExprI32GtS, x, y
-#define WASM_I32_GES(x, y) kExprI32GeS, x, y
-#define WASM_I32_GTU(x, y) kExprI32GtU, x, y
-#define WASM_I32_GEU(x, y) kExprI32GeU, x, y
-#define WASM_I32_CLZ(x) kExprI32Clz, x
-#define WASM_I32_CTZ(x) kExprI32Ctz, x
-#define WASM_I32_POPCNT(x) kExprI32Popcnt, x
-#define WASM_I32_EQZ(x) kExprI32Eqz, x
+#define WASM_I32_ADD(x, y) x, y, kExprI32Add
+#define WASM_I32_SUB(x, y) x, y, kExprI32Sub
+#define WASM_I32_MUL(x, y) x, y, kExprI32Mul
+#define WASM_I32_DIVS(x, y) x, y, kExprI32DivS
+#define WASM_I32_DIVU(x, y) x, y, kExprI32DivU
+#define WASM_I32_REMS(x, y) x, y, kExprI32RemS
+#define WASM_I32_REMU(x, y) x, y, kExprI32RemU
+#define WASM_I32_AND(x, y) x, y, kExprI32And
+#define WASM_I32_IOR(x, y) x, y, kExprI32Ior
+#define WASM_I32_XOR(x, y) x, y, kExprI32Xor
+#define WASM_I32_SHL(x, y) x, y, kExprI32Shl
+#define WASM_I32_SHR(x, y) x, y, kExprI32ShrU
+#define WASM_I32_SAR(x, y) x, y, kExprI32ShrS
+#define WASM_I32_ROR(x, y) x, y, kExprI32Ror
+#define WASM_I32_ROL(x, y) x, y, kExprI32Rol
+#define WASM_I32_EQ(x, y) x, y, kExprI32Eq
+#define WASM_I32_NE(x, y) x, y, kExprI32Ne
+#define WASM_I32_LTS(x, y) x, y, kExprI32LtS
+#define WASM_I32_LES(x, y) x, y, kExprI32LeS
+#define WASM_I32_LTU(x, y) x, y, kExprI32LtU
+#define WASM_I32_LEU(x, y) x, y, kExprI32LeU
+#define WASM_I32_GTS(x, y) x, y, kExprI32GtS
+#define WASM_I32_GES(x, y) x, y, kExprI32GeS
+#define WASM_I32_GTU(x, y) x, y, kExprI32GtU
+#define WASM_I32_GEU(x, y) x, y, kExprI32GeU
+#define WASM_I32_CLZ(x) x, kExprI32Clz
+#define WASM_I32_CTZ(x) x, kExprI32Ctz
+#define WASM_I32_POPCNT(x) x, kExprI32Popcnt
+#define WASM_I32_EQZ(x) x, kExprI32Eqz
 
 //------------------------------------------------------------------------------
 // Int64 operations
 //------------------------------------------------------------------------------
-#define WASM_I64_ADD(x, y) kExprI64Add, x, y
-#define WASM_I64_SUB(x, y) kExprI64Sub, x, y
-#define WASM_I64_MUL(x, y) kExprI64Mul, x, y
-#define WASM_I64_DIVS(x, y) kExprI64DivS, x, y
-#define WASM_I64_DIVU(x, y) kExprI64DivU, x, y
-#define WASM_I64_REMS(x, y) kExprI64RemS, x, y
-#define WASM_I64_REMU(x, y) kExprI64RemU, x, y
-#define WASM_I64_AND(x, y) kExprI64And, x, y
-#define WASM_I64_IOR(x, y) kExprI64Ior, x, y
-#define WASM_I64_XOR(x, y) kExprI64Xor, x, y
-#define WASM_I64_SHL(x, y) kExprI64Shl, x, y
-#define WASM_I64_SHR(x, y) kExprI64ShrU, x, y
-#define WASM_I64_SAR(x, y) kExprI64ShrS, x, y
-#define WASM_I64_ROR(x, y) kExprI64Ror, x, y
-#define WASM_I64_ROL(x, y) kExprI64Rol, x, y
-#define WASM_I64_EQ(x, y) kExprI64Eq, x, y
-#define WASM_I64_NE(x, y) kExprI64Ne, x, y
-#define WASM_I64_LTS(x, y) kExprI64LtS, x, y
-#define WASM_I64_LES(x, y) kExprI64LeS, x, y
-#define WASM_I64_LTU(x, y) kExprI64LtU, x, y
-#define WASM_I64_LEU(x, y) kExprI64LeU, x, y
-#define WASM_I64_GTS(x, y) kExprI64GtS, x, y
-#define WASM_I64_GES(x, y) kExprI64GeS, x, y
-#define WASM_I64_GTU(x, y) kExprI64GtU, x, y
-#define WASM_I64_GEU(x, y) kExprI64GeU, x, y
-#define WASM_I64_CLZ(x) kExprI64Clz, x
-#define WASM_I64_CTZ(x) kExprI64Ctz, x
-#define WASM_I64_POPCNT(x) kExprI64Popcnt, x
-#define WASM_I64_EQZ(x) kExprI64Eqz, x
+#define WASM_I64_ADD(x, y) x, y, kExprI64Add
+#define WASM_I64_SUB(x, y) x, y, kExprI64Sub
+#define WASM_I64_MUL(x, y) x, y, kExprI64Mul
+#define WASM_I64_DIVS(x, y) x, y, kExprI64DivS
+#define WASM_I64_DIVU(x, y) x, y, kExprI64DivU
+#define WASM_I64_REMS(x, y) x, y, kExprI64RemS
+#define WASM_I64_REMU(x, y) x, y, kExprI64RemU
+#define WASM_I64_AND(x, y) x, y, kExprI64And
+#define WASM_I64_IOR(x, y) x, y, kExprI64Ior
+#define WASM_I64_XOR(x, y) x, y, kExprI64Xor
+#define WASM_I64_SHL(x, y) x, y, kExprI64Shl
+#define WASM_I64_SHR(x, y) x, y, kExprI64ShrU
+#define WASM_I64_SAR(x, y) x, y, kExprI64ShrS
+#define WASM_I64_ROR(x, y) x, y, kExprI64Ror
+#define WASM_I64_ROL(x, y) x, y, kExprI64Rol
+#define WASM_I64_EQ(x, y) x, y, kExprI64Eq
+#define WASM_I64_NE(x, y) x, y, kExprI64Ne
+#define WASM_I64_LTS(x, y) x, y, kExprI64LtS
+#define WASM_I64_LES(x, y) x, y, kExprI64LeS
+#define WASM_I64_LTU(x, y) x, y, kExprI64LtU
+#define WASM_I64_LEU(x, y) x, y, kExprI64LeU
+#define WASM_I64_GTS(x, y) x, y, kExprI64GtS
+#define WASM_I64_GES(x, y) x, y, kExprI64GeS
+#define WASM_I64_GTU(x, y) x, y, kExprI64GtU
+#define WASM_I64_GEU(x, y) x, y, kExprI64GeU
+#define WASM_I64_CLZ(x) x, kExprI64Clz
+#define WASM_I64_CTZ(x) x, kExprI64Ctz
+#define WASM_I64_POPCNT(x) x, kExprI64Popcnt
+#define WASM_I64_EQZ(x) x, kExprI64Eqz
 
 //------------------------------------------------------------------------------
 // Float32 operations
 //------------------------------------------------------------------------------
-#define WASM_F32_ADD(x, y) kExprF32Add, x, y
-#define WASM_F32_SUB(x, y) kExprF32Sub, x, y
-#define WASM_F32_MUL(x, y) kExprF32Mul, x, y
-#define WASM_F32_DIV(x, y) kExprF32Div, x, y
-#define WASM_F32_MIN(x, y) kExprF32Min, x, y
-#define WASM_F32_MAX(x, y) kExprF32Max, x, y
-#define WASM_F32_ABS(x) kExprF32Abs, x
-#define WASM_F32_NEG(x) kExprF32Neg, x
-#define WASM_F32_COPYSIGN(x, y) kExprF32CopySign, x, y
-#define WASM_F32_CEIL(x) kExprF32Ceil, x
-#define WASM_F32_FLOOR(x) kExprF32Floor, x
-#define WASM_F32_TRUNC(x) kExprF32Trunc, x
-#define WASM_F32_NEARESTINT(x) kExprF32NearestInt, x
-#define WASM_F32_SQRT(x) kExprF32Sqrt, x
-#define WASM_F32_EQ(x, y) kExprF32Eq, x, y
-#define WASM_F32_NE(x, y) kExprF32Ne, x, y
-#define WASM_F32_LT(x, y) kExprF32Lt, x, y
-#define WASM_F32_LE(x, y) kExprF32Le, x, y
-#define WASM_F32_GT(x, y) kExprF32Gt, x, y
-#define WASM_F32_GE(x, y) kExprF32Ge, x, y
+#define WASM_F32_ADD(x, y) x, y, kExprF32Add
+#define WASM_F32_SUB(x, y) x, y, kExprF32Sub
+#define WASM_F32_MUL(x, y) x, y, kExprF32Mul
+#define WASM_F32_DIV(x, y) x, y, kExprF32Div
+#define WASM_F32_MIN(x, y) x, y, kExprF32Min
+#define WASM_F32_MAX(x, y) x, y, kExprF32Max
+#define WASM_F32_ABS(x) x, kExprF32Abs
+#define WASM_F32_NEG(x) x, kExprF32Neg
+#define WASM_F32_COPYSIGN(x, y) x, y, kExprF32CopySign
+#define WASM_F32_CEIL(x) x, kExprF32Ceil
+#define WASM_F32_FLOOR(x) x, kExprF32Floor
+#define WASM_F32_TRUNC(x) x, kExprF32Trunc
+#define WASM_F32_NEARESTINT(x) x, kExprF32NearestInt
+#define WASM_F32_SQRT(x) x, kExprF32Sqrt
+#define WASM_F32_EQ(x, y) x, y, kExprF32Eq
+#define WASM_F32_NE(x, y) x, y, kExprF32Ne
+#define WASM_F32_LT(x, y) x, y, kExprF32Lt
+#define WASM_F32_LE(x, y) x, y, kExprF32Le
+#define WASM_F32_GT(x, y) x, y, kExprF32Gt
+#define WASM_F32_GE(x, y) x, y, kExprF32Ge
 
 //------------------------------------------------------------------------------
 // Float64 operations
 //------------------------------------------------------------------------------
-#define WASM_F64_ADD(x, y) kExprF64Add, x, y
-#define WASM_F64_SUB(x, y) kExprF64Sub, x, y
-#define WASM_F64_MUL(x, y) kExprF64Mul, x, y
-#define WASM_F64_DIV(x, y) kExprF64Div, x, y
-#define WASM_F64_MIN(x, y) kExprF64Min, x, y
-#define WASM_F64_MAX(x, y) kExprF64Max, x, y
-#define WASM_F64_ABS(x) kExprF64Abs, x
-#define WASM_F64_NEG(x) kExprF64Neg, x
-#define WASM_F64_COPYSIGN(x, y) kExprF64CopySign, x, y
-#define WASM_F64_CEIL(x) kExprF64Ceil, x
-#define WASM_F64_FLOOR(x) kExprF64Floor, x
-#define WASM_F64_TRUNC(x) kExprF64Trunc, x
-#define WASM_F64_NEARESTINT(x) kExprF64NearestInt, x
-#define WASM_F64_SQRT(x) kExprF64Sqrt, x
-#define WASM_F64_EQ(x, y) kExprF64Eq, x, y
-#define WASM_F64_NE(x, y) kExprF64Ne, x, y
-#define WASM_F64_LT(x, y) kExprF64Lt, x, y
-#define WASM_F64_LE(x, y) kExprF64Le, x, y
-#define WASM_F64_GT(x, y) kExprF64Gt, x, y
-#define WASM_F64_GE(x, y) kExprF64Ge, x, y
+#define WASM_F64_ADD(x, y) x, y, kExprF64Add
+#define WASM_F64_SUB(x, y) x, y, kExprF64Sub
+#define WASM_F64_MUL(x, y) x, y, kExprF64Mul
+#define WASM_F64_DIV(x, y) x, y, kExprF64Div
+#define WASM_F64_MIN(x, y) x, y, kExprF64Min
+#define WASM_F64_MAX(x, y) x, y, kExprF64Max
+#define WASM_F64_ABS(x) x, kExprF64Abs
+#define WASM_F64_NEG(x) x, kExprF64Neg
+#define WASM_F64_COPYSIGN(x, y) x, y, kExprF64CopySign
+#define WASM_F64_CEIL(x) x, kExprF64Ceil
+#define WASM_F64_FLOOR(x) x, kExprF64Floor
+#define WASM_F64_TRUNC(x) x, kExprF64Trunc
+#define WASM_F64_NEARESTINT(x) x, kExprF64NearestInt
+#define WASM_F64_SQRT(x) x, kExprF64Sqrt
+#define WASM_F64_EQ(x, y) x, y, kExprF64Eq
+#define WASM_F64_NE(x, y) x, y, kExprF64Ne
+#define WASM_F64_LT(x, y) x, y, kExprF64Lt
+#define WASM_F64_LE(x, y) x, y, kExprF64Le
+#define WASM_F64_GT(x, y) x, y, kExprF64Gt
+#define WASM_F64_GE(x, y) x, y, kExprF64Ge
 
 //------------------------------------------------------------------------------
 // Type conversions.
 //------------------------------------------------------------------------------
-#define WASM_I32_SCONVERT_F32(x) kExprI32SConvertF32, x
-#define WASM_I32_SCONVERT_F64(x) kExprI32SConvertF64, x
-#define WASM_I32_UCONVERT_F32(x) kExprI32UConvertF32, x
-#define WASM_I32_UCONVERT_F64(x) kExprI32UConvertF64, x
-#define WASM_I32_CONVERT_I64(x) kExprI32ConvertI64, x
-#define WASM_I64_SCONVERT_F32(x) kExprI64SConvertF32, x
-#define WASM_I64_SCONVERT_F64(x) kExprI64SConvertF64, x
-#define WASM_I64_UCONVERT_F32(x) kExprI64UConvertF32, x
-#define WASM_I64_UCONVERT_F64(x) kExprI64UConvertF64, x
-#define WASM_I64_SCONVERT_I32(x) kExprI64SConvertI32, x
-#define WASM_I64_UCONVERT_I32(x) kExprI64UConvertI32, x
-#define WASM_F32_SCONVERT_I32(x) kExprF32SConvertI32, x
-#define WASM_F32_UCONVERT_I32(x) kExprF32UConvertI32, x
-#define WASM_F32_SCONVERT_I64(x) kExprF32SConvertI64, x
-#define WASM_F32_UCONVERT_I64(x) kExprF32UConvertI64, x
-#define WASM_F32_CONVERT_F64(x) kExprF32ConvertF64, x
-#define WASM_F32_REINTERPRET_I32(x) kExprF32ReinterpretI32, x
-#define WASM_F64_SCONVERT_I32(x) kExprF64SConvertI32, x
-#define WASM_F64_UCONVERT_I32(x) kExprF64UConvertI32, x
-#define WASM_F64_SCONVERT_I64(x) kExprF64SConvertI64, x
-#define WASM_F64_UCONVERT_I64(x) kExprF64UConvertI64, x
-#define WASM_F64_CONVERT_F32(x) kExprF64ConvertF32, x
-#define WASM_F64_REINTERPRET_I64(x) kExprF64ReinterpretI64, x
-#define WASM_I32_REINTERPRET_F32(x) kExprI32ReinterpretF32, x
-#define WASM_I64_REINTERPRET_F64(x) kExprI64ReinterpretF64, x
+#define WASM_I32_SCONVERT_F32(x) x, kExprI32SConvertF32
+#define WASM_I32_SCONVERT_F64(x) x, kExprI32SConvertF64
+#define WASM_I32_UCONVERT_F32(x) x, kExprI32UConvertF32
+#define WASM_I32_UCONVERT_F64(x) x, kExprI32UConvertF64
+#define WASM_I32_CONVERT_I64(x) x, kExprI32ConvertI64
+#define WASM_I64_SCONVERT_F32(x) x, kExprI64SConvertF32
+#define WASM_I64_SCONVERT_F64(x) x, kExprI64SConvertF64
+#define WASM_I64_UCONVERT_F32(x) x, kExprI64UConvertF32
+#define WASM_I64_UCONVERT_F64(x) x, kExprI64UConvertF64
+#define WASM_I64_SCONVERT_I32(x) x, kExprI64SConvertI32
+#define WASM_I64_UCONVERT_I32(x) x, kExprI64UConvertI32
+#define WASM_F32_SCONVERT_I32(x) x, kExprF32SConvertI32
+#define WASM_F32_UCONVERT_I32(x) x, kExprF32UConvertI32
+#define WASM_F32_SCONVERT_I64(x) x, kExprF32SConvertI64
+#define WASM_F32_UCONVERT_I64(x) x, kExprF32UConvertI64
+#define WASM_F32_CONVERT_F64(x) x, kExprF32ConvertF64
+#define WASM_F32_REINTERPRET_I32(x) x, kExprF32ReinterpretI32
+#define WASM_F64_SCONVERT_I32(x) x, kExprF64SConvertI32
+#define WASM_F64_UCONVERT_I32(x) x, kExprF64UConvertI32
+#define WASM_F64_SCONVERT_I64(x) x, kExprF64SConvertI64
+#define WASM_F64_UCONVERT_I64(x) x, kExprF64UConvertI64
+#define WASM_F64_CONVERT_F32(x) x, kExprF64ConvertF32
+#define WASM_F64_REINTERPRET_I64(x) x, kExprF64ReinterpretI64
+#define WASM_I32_REINTERPRET_F32(x) x, kExprI32ReinterpretF32
+#define WASM_I64_REINTERPRET_F64(x) x, kExprI64ReinterpretF64
+
+#define SIG_ENTRY_v_v kWasmFunctionTypeForm, 0, 0
+#define SIZEOF_SIG_ENTRY_v_v 3
+
+#define SIG_ENTRY_v_x(a) kWasmFunctionTypeForm, 1, a, 0
+#define SIG_ENTRY_v_xx(a, b) kWasmFunctionTypeForm, 2, a, b, 0
+#define SIG_ENTRY_v_xxx(a, b, c) kWasmFunctionTypeForm, 3, a, b, c, 0
+#define SIZEOF_SIG_ENTRY_v_x 4
+#define SIZEOF_SIG_ENTRY_v_xx 5
+#define SIZEOF_SIG_ENTRY_v_xxx 6
+
+#define SIG_ENTRY_x(r) kWasmFunctionTypeForm, 0, 1, r
+#define SIG_ENTRY_x_x(r, a) kWasmFunctionTypeForm, 1, a, 1, r
+#define SIG_ENTRY_x_xx(r, a, b) kWasmFunctionTypeForm, 2, a, b, 1, r
+#define SIG_ENTRY_x_xxx(r, a, b, c) kWasmFunctionTypeForm, 3, a, b, c, 1, r
+#define SIZEOF_SIG_ENTRY_x 4
+#define SIZEOF_SIG_ENTRY_x_x 5
+#define SIZEOF_SIG_ENTRY_x_xx 6
+#define SIZEOF_SIG_ENTRY_x_xxx 7
 
 #endif  // V8_WASM_MACRO_GEN_H_
diff --git a/src/wasm/wasm-module.cc b/src/wasm/wasm-module.cc
index a1c2a7a..ca0a9b9 100644
--- a/src/wasm/wasm-module.cc
+++ b/src/wasm/wasm-module.cc
@@ -2,14 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "src/base/atomic-utils.h"
 #include "src/macro-assembler.h"
 #include "src/objects.h"
+#include "src/property-descriptor.h"
 #include "src/v8.h"
 
 #include "src/simulator.h"
 
 #include "src/wasm/ast-decoder.h"
 #include "src/wasm/module-decoder.h"
+#include "src/wasm/wasm-debug.h"
+#include "src/wasm/wasm-function-name-table.h"
 #include "src/wasm/wasm-module.h"
 #include "src/wasm/wasm-result.h"
 
@@ -19,20 +23,31 @@
 namespace internal {
 namespace wasm {
 
+static const int kPlaceholderMarker = 1000000000;
+
 static const char* wasmSections[] = {
-#define F(enumerator, string) string,
+#define F(enumerator, order, string) string,
     FOR_EACH_WASM_SECTION_TYPE(F)
 #undef F
+        "<unknown>"  // entry for "Max"
 };
 
 static uint8_t wasmSectionsLengths[]{
-#define F(enumerator, string) sizeof(string) - 1,
+#define F(enumerator, order, string) sizeof(string) - 1,
     FOR_EACH_WASM_SECTION_TYPE(F)
 #undef F
+        9  // entry for "Max"
+};
+
+static uint8_t wasmSectionsOrders[]{
+#define F(enumerator, order, string) order,
+    FOR_EACH_WASM_SECTION_TYPE(F)
+#undef F
+        0  // entry for "Max"
 };
 
 static_assert(sizeof(wasmSections) / sizeof(wasmSections[0]) ==
-                  (size_t)WasmSection::Code::Max,
+                  (size_t)WasmSection::Code::Max + 1,
               "expected enum WasmSection::Code to be monotonic from 0");
 
 WasmSection::Code WasmSection::begin() { return (WasmSection::Code)0; }
@@ -49,6 +64,20 @@
   return wasmSectionsLengths[(size_t)code];
 }
 
+int WasmSection::getOrder(WasmSection::Code code) {
+  return wasmSectionsOrders[(size_t)code];
+}
+
+WasmSection::Code WasmSection::lookup(const byte* string, uint32_t length) {
+  // TODO(jfb) Linear search, it may be better to do a common-prefix search.
+  for (Code i = begin(); i != end(); i = next(i)) {
+    if (getNameLength(i) == length && 0 == memcmp(getName(i), string, length)) {
+      return i;
+    }
+  }
+  return Code::Max;
+}
+
 std::ostream& operator<<(std::ostream& os, const WasmModule& module) {
   os << "WASM module with ";
   os << (module.min_mem_pages * module.kPageSize) << " min mem";
@@ -59,16 +88,9 @@
   return os;
 }
 
-
 std::ostream& operator<<(std::ostream& os, const WasmFunction& function) {
   os << "WASM function with signature " << *function.sig;
 
-  os << " locals: ";
-  if (function.local_i32_count) os << function.local_i32_count << " i32s ";
-  if (function.local_i64_count) os << function.local_i64_count << " i64s ";
-  if (function.local_f32_count) os << function.local_f32_count << " f32s ";
-  if (function.local_f64_count) os << function.local_f64_count << " f64s ";
-
   os << " code bytes: "
      << (function.code_end_offset - function.code_start_offset);
   return os;
@@ -80,7 +102,7 @@
     if (pair.module_) {
       WasmName name = pair.module_->GetName(pair.function_->name_offset,
                                             pair.function_->name_length);
-      os.write(name.name, name.length);
+      os.write(name.start(), name.length());
     } else {
       os << "+" << pair.function_->func_index;
     }
@@ -90,113 +112,24 @@
   return os;
 }
 
-// A helper class for compiling multiple wasm functions that offers
-// placeholder code objects for calling functions that are not yet compiled.
-class WasmLinker {
- public:
-  WasmLinker(Isolate* isolate, size_t size)
-      : isolate_(isolate), placeholder_code_(size), function_code_(size) {}
-
-  // Get the code object for a function, allocating a placeholder if it has
-  // not yet been compiled.
-  Handle<Code> GetFunctionCode(uint32_t index) {
-    DCHECK(index < function_code_.size());
-    if (function_code_[index].is_null()) {
-      // Create a placeholder code object and encode the corresponding index in
-      // the {constant_pool_offset} field of the code object.
-      // TODO(titzer): placeholder code objects are somewhat dangerous.
-      Handle<Code> self(nullptr, isolate_);
-      byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0};  // fake instructions.
-      CodeDesc desc = {buffer, 8, 8, 0, 0, nullptr};
-      Handle<Code> code = isolate_->factory()->NewCode(
-          desc, Code::KindField::encode(Code::WASM_FUNCTION), self);
-      code->set_constant_pool_offset(index + kPlaceholderMarker);
-      placeholder_code_[index] = code;
-      function_code_[index] = code;
-    }
-    return function_code_[index];
-  }
-
-  void Finish(uint32_t index, Handle<Code> code) {
-    DCHECK(index < function_code_.size());
-    function_code_[index] = code;
-  }
-
-  void Link(Handle<FixedArray> function_table,
-            std::vector<uint16_t>& functions) {
-    for (size_t i = 0; i < function_code_.size(); i++) {
-      LinkFunction(function_code_[i]);
-    }
-    if (!function_table.is_null()) {
-      int table_size = static_cast<int>(functions.size());
-      DCHECK_EQ(function_table->length(), table_size * 2);
-      for (int i = 0; i < table_size; i++) {
-        function_table->set(i + table_size, *function_code_[functions[i]]);
-      }
-    }
-  }
-
- private:
-  static const int kPlaceholderMarker = 1000000000;
-
-  Isolate* isolate_;
-  std::vector<Handle<Code>> placeholder_code_;
-  std::vector<Handle<Code>> function_code_;
-
-  void LinkFunction(Handle<Code> code) {
-    bool modified = false;
-    int mode_mask = RelocInfo::kCodeTargetMask;
-    AllowDeferredHandleDereference embedding_raw_address;
-    for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
-      RelocInfo::Mode mode = it.rinfo()->rmode();
-      if (RelocInfo::IsCodeTarget(mode)) {
-        Code* target =
-            Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
-        if (target->kind() == Code::WASM_FUNCTION &&
-            target->constant_pool_offset() >= kPlaceholderMarker) {
-          // Patch direct calls to placeholder code objects.
-          uint32_t index = target->constant_pool_offset() - kPlaceholderMarker;
-          CHECK(index < function_code_.size());
-          Handle<Code> new_target = function_code_[index];
-          if (target != *new_target) {
-            CHECK_EQ(*placeholder_code_[index], target);
-            it.rinfo()->set_target_address(new_target->instruction_start(),
-                                           SKIP_WRITE_BARRIER,
-                                           SKIP_ICACHE_FLUSH);
-            modified = true;
-          }
-        }
-      }
-    }
-    if (modified) {
-      Assembler::FlushICache(isolate_, code->instruction_start(),
-                             code->instruction_size());
-    }
-  }
-};
-
 namespace {
 // Internal constants for the layout of the module object.
-const int kWasmModuleInternalFieldCount = 4;
 const int kWasmModuleFunctionTable = 0;
 const int kWasmModuleCodeTable = 1;
 const int kWasmMemArrayBuffer = 2;
 const int kWasmGlobalsArrayBuffer = 3;
+// TODO(clemensh): Remove function name array, extract names from module bytes.
+const int kWasmFunctionNamesArray = 4;
+const int kWasmModuleBytesString = 5;
+const int kWasmDebugInfo = 6;
+const int kWasmModuleInternalFieldCount = 7;
 
-size_t AllocateGlobalsOffsets(std::vector<WasmGlobal>& globals) {
-  uint32_t offset = 0;
-  if (globals.size() == 0) return 0;
-  for (WasmGlobal& global : globals) {
-    byte size = WasmOpcodes::MemSize(global.type);
-    offset = (offset + size - 1) & ~(size - 1);  // align
-    global.offset = offset;
-    offset += size;
-  }
-  return offset;
+uint32_t GetMinModuleMemSize(const WasmModule* module) {
+  return WasmModule::kPageSize * module->min_mem_pages;
 }
 
-
-void LoadDataSegments(WasmModule* module, byte* mem_addr, size_t mem_size) {
+void LoadDataSegments(const WasmModule* module, byte* mem_addr,
+                      size_t mem_size) {
   for (const WasmDataSegment& segment : module->data_segments) {
     if (!segment.init) continue;
     if (!segment.source_size) continue;
@@ -209,15 +142,20 @@
   }
 }
 
-
-Handle<FixedArray> BuildFunctionTable(Isolate* isolate, WasmModule* module) {
-  if (module->function_table.size() == 0) {
+Handle<FixedArray> BuildFunctionTable(Isolate* isolate,
+                                      const WasmModule* module) {
+  // Compute the size of the indirect function table
+  uint32_t table_size = module->FunctionTableSize();
+  if (table_size == 0) {
     return Handle<FixedArray>::null();
   }
-  int table_size = static_cast<int>(module->function_table.size());
+
   Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size);
-  for (int i = 0; i < table_size; i++) {
-    WasmFunction* function = &module->functions[module->function_table[i]];
+  for (uint32_t i = 0;
+       i < static_cast<uint32_t>(module->function_table.size());
+       ++i) {
+    const WasmFunction* function =
+        &module->functions[module->function_table[i]];
     fixed->set(i, Smi::FromInt(function->sig_index));
   }
   return fixed;
@@ -225,15 +163,13 @@
 
 Handle<JSArrayBuffer> NewArrayBuffer(Isolate* isolate, size_t size,
                                      byte** backing_store) {
+  *backing_store = nullptr;
   if (size > (WasmModule::kMaxMemPages * WasmModule::kPageSize)) {
     // TODO(titzer): lift restriction on maximum memory allocated here.
-    *backing_store = nullptr;
     return Handle<JSArrayBuffer>::null();
   }
-  void* memory =
-      isolate->array_buffer_allocator()->Allocate(static_cast<int>(size));
-  if (!memory) {
-    *backing_store = nullptr;
+  void* memory = isolate->array_buffer_allocator()->Allocate(size);
+  if (memory == nullptr) {
     return Handle<JSArrayBuffer>::null();
   }
 
@@ -242,7 +178,7 @@
 #if DEBUG
   // Double check the API allocator actually zero-initialized the memory.
   byte* bytes = reinterpret_cast<byte*>(*backing_store);
-  for (size_t i = 0; i < size; i++) {
+  for (size_t i = 0; i < size; ++i) {
     DCHECK_EQ(0, bytes[i]);
   }
 #endif
@@ -253,12 +189,27 @@
   return buffer;
 }
 
+void RelocateInstanceCode(WasmModuleInstance* instance) {
+  for (uint32_t i = 0; i < instance->function_code.size(); ++i) {
+    Handle<Code> function = instance->function_code[i];
+    AllowDeferredHandleDereference embedding_raw_address;
+    int mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE) |
+               (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
+    for (RelocIterator it(*function, mask); !it.done(); it.next()) {
+      it.rinfo()->update_wasm_memory_reference(
+          nullptr, instance->mem_start, GetMinModuleMemSize(instance->module),
+          static_cast<uint32_t>(instance->mem_size));
+    }
+  }
+}
+
 // Set the memory for a module instance to be the {memory} array buffer.
 void SetMemory(WasmModuleInstance* instance, Handle<JSArrayBuffer> memory) {
   memory->set_is_neuterable(false);
   instance->mem_start = reinterpret_cast<byte*>(memory->backing_store());
   instance->mem_size = memory->byte_length()->Number();
   instance->mem_buffer = memory;
+  RelocateInstanceCode(instance);
 }
 
 // Allocate memory for a module instance as a new JSArrayBuffer.
@@ -271,63 +222,153 @@
     thrower->Error("Out of memory: wasm memory too large");
     return false;
   }
-  instance->mem_size = WasmModule::kPageSize * instance->module->min_mem_pages;
+  instance->mem_size = GetMinModuleMemSize(instance->module);
   instance->mem_buffer =
       NewArrayBuffer(isolate, instance->mem_size, &instance->mem_start);
-  if (!instance->mem_start) {
+  if (instance->mem_start == nullptr) {
     thrower->Error("Out of memory: wasm memory");
     instance->mem_size = 0;
     return false;
   }
+  RelocateInstanceCode(instance);
   return true;
 }
 
 bool AllocateGlobals(ErrorThrower* thrower, Isolate* isolate,
                      WasmModuleInstance* instance) {
-  instance->globals_size = AllocateGlobalsOffsets(instance->module->globals);
-
-  if (instance->globals_size > 0) {
-    instance->globals_buffer = NewArrayBuffer(isolate, instance->globals_size,
-                                              &instance->globals_start);
+  uint32_t globals_size = instance->module->globals_size;
+  if (globals_size > 0) {
+    instance->globals_buffer =
+        NewArrayBuffer(isolate, globals_size, &instance->globals_start);
     if (!instance->globals_start) {
       // Not enough space for backing store of globals.
       thrower->Error("Out of memory: wasm globals");
       return false;
     }
+
+    for (uint32_t i = 0; i < instance->function_code.size(); ++i) {
+      Handle<Code> function = instance->function_code[i];
+      AllowDeferredHandleDereference embedding_raw_address;
+      int mask = 1 << RelocInfo::WASM_GLOBAL_REFERENCE;
+      for (RelocIterator it(*function, mask); !it.done(); it.next()) {
+        it.rinfo()->update_wasm_global_reference(nullptr,
+                                                 instance->globals_start);
+      }
+    }
   }
   return true;
 }
+
+Handle<Code> CreatePlaceholder(Factory* factory, uint32_t index,
+                               Code::Kind kind) {
+  // Create a placeholder code object and encode the corresponding index in
+  // the {constant_pool_offset} field of the code object.
+  // TODO(titzer): placeholder code objects are somewhat dangerous.
+  static byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0};  // fake instructions.
+  static CodeDesc desc = {buffer, 8, 8, 0, 0, nullptr, 0, nullptr};
+  Handle<Code> code = factory->NewCode(desc, Code::KindField::encode(kind),
+                                       Handle<Object>::null());
+  code->set_constant_pool_offset(static_cast<int>(index) + kPlaceholderMarker);
+  return code;
+}
+
+// TODO(mtrofin): remove when we stop relying on placeholders.
+void InitializePlaceholders(Factory* factory,
+                            std::vector<Handle<Code>>* placeholders,
+                            size_t size) {
+  DCHECK(placeholders->empty());
+  placeholders->reserve(size);
+
+  for (uint32_t i = 0; i < size; ++i) {
+    placeholders->push_back(CreatePlaceholder(factory, i, Code::WASM_FUNCTION));
+  }
+}
+
+bool LinkFunction(Handle<Code> unlinked,
+                  const std::vector<Handle<Code>>& code_targets,
+                  Code::Kind kind) {
+  bool modified = false;
+  int mode_mask = RelocInfo::kCodeTargetMask;
+  AllowDeferredHandleDereference embedding_raw_address;
+  for (RelocIterator it(*unlinked, mode_mask); !it.done(); it.next()) {
+    RelocInfo::Mode mode = it.rinfo()->rmode();
+    if (RelocInfo::IsCodeTarget(mode)) {
+      Code* target =
+          Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
+      if (target->kind() == kind &&
+          target->constant_pool_offset() >= kPlaceholderMarker) {
+        // Patch direct calls to placeholder code objects.
+        uint32_t index = target->constant_pool_offset() - kPlaceholderMarker;
+        CHECK(index < code_targets.size());
+        Handle<Code> new_target = code_targets[index];
+        if (target != *new_target) {
+          it.rinfo()->set_target_address(new_target->instruction_start(),
+                                         SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
+          modified = true;
+        }
+      }
+    }
+  }
+  return modified;
+}
+
+void LinkModuleFunctions(Isolate* isolate,
+                         std::vector<Handle<Code>>& functions) {
+  for (size_t i = 0; i < functions.size(); ++i) {
+    Handle<Code> code = functions[i];
+    bool modified = LinkFunction(code, functions, Code::WASM_FUNCTION);
+    if (modified) {
+      Assembler::FlushICache(isolate, code->instruction_start(),
+                             code->instruction_size());
+    }
+  }
+}
+
+void LinkImports(Isolate* isolate, std::vector<Handle<Code>>& functions,
+                 const std::vector<Handle<Code>>& imports) {
+  for (uint32_t i = 0; i < functions.size(); ++i) {
+    Handle<Code> code = functions[i];
+    bool modified = LinkFunction(code, imports, Code::WASM_TO_JS_FUNCTION);
+    if (modified) {
+      Assembler::FlushICache(isolate, code->instruction_start(),
+                             code->instruction_size());
+    }
+  }
+}
+
 }  // namespace
 
 WasmModule::WasmModule()
-    : shared_isolate(nullptr),
-      module_start(nullptr),
+    : module_start(nullptr),
       module_end(nullptr),
       min_mem_pages(0),
       max_mem_pages(0),
       mem_export(false),
       mem_external(false),
       start_function_index(-1),
-      origin(kWasmOrigin) {}
+      origin(kWasmOrigin),
+      globals_size(0),
+      indirect_table_size(0),
+      pending_tasks(new base::Semaphore(0)) {}
 
 static MaybeHandle<JSFunction> ReportFFIError(ErrorThrower& thrower,
                                               const char* error, uint32_t index,
                                               wasm::WasmName module_name,
                                               wasm::WasmName function_name) {
-  if (function_name.name) {
+  if (!function_name.is_empty()) {
     thrower.Error("Import #%d module=\"%.*s\" function=\"%.*s\" error: %s",
-                  index, module_name.length, module_name.name,
-                  function_name.length, function_name.name, error);
+                  index, module_name.length(), module_name.start(),
+                  function_name.length(), function_name.start(), error);
   } else {
     thrower.Error("Import #%d module=\"%.*s\" error: %s", index,
-                  module_name.length, module_name.name, error);
+                  module_name.length(), module_name.start(), error);
   }
   thrower.Error("Import ");
   return MaybeHandle<JSFunction>();
 }
 
 static MaybeHandle<JSFunction> LookupFunction(
-    ErrorThrower& thrower, Factory* factory, Handle<JSObject> ffi,
+    ErrorThrower& thrower, Factory* factory, Handle<JSReceiver> ffi,
     uint32_t index, wasm::WasmName module_name, wasm::WasmName function_name) {
   if (ffi.is_null()) {
     return ReportFFIError(thrower, "FFI is not an object", index, module_name,
@@ -335,8 +376,7 @@
   }
 
   // Look up the module first.
-  Handle<String> name = factory->InternalizeUtf8String(
-      Vector<const char>(module_name.name, module_name.length));
+  Handle<String> name = factory->InternalizeUtf8String(module_name);
   MaybeHandle<Object> result = Object::GetProperty(ffi, name);
   if (result.is_null()) {
     return ReportFFIError(thrower, "module not found", index, module_name,
@@ -351,10 +391,9 @@
   }
 
   Handle<Object> function;
-  if (function_name.name) {
+  if (!function_name.is_empty()) {
     // Look up the function in the module.
-    Handle<String> name = factory->InternalizeUtf8String(
-        Vector<const char>(function_name.name, function_name.length));
+    Handle<String> name = factory->InternalizeUtf8String(function_name);
     MaybeHandle<Object> result = Object::GetProperty(module, name);
     if (result.is_null()) {
       return ReportFFIError(thrower, "function not found", index, module_name,
@@ -374,15 +413,360 @@
   return Handle<JSFunction>::cast(function);
 }
 
+namespace {
+// Fetches the compilation unit of a wasm function and executes its parallel
+// phase.
+bool FetchAndExecuteCompilationUnit(
+    Isolate* isolate,
+    std::vector<compiler::WasmCompilationUnit*>* compilation_units,
+    std::queue<compiler::WasmCompilationUnit*>* executed_units,
+    base::Mutex* result_mutex, base::AtomicNumber<size_t>* next_unit) {
+  DisallowHeapAllocation no_allocation;
+  DisallowHandleAllocation no_handles;
+  DisallowHandleDereference no_deref;
+  DisallowCodeDependencyChange no_dependency_change;
+
+  // - 1 because AtomicIntrement returns the value after the atomic increment.
+  size_t index = next_unit->Increment(1) - 1;
+  if (index >= compilation_units->size()) {
+    return false;
+  }
+
+  compiler::WasmCompilationUnit* unit = compilation_units->at(index);
+  if (unit != nullptr) {
+    unit->ExecuteCompilation();
+    {
+      base::LockGuard<base::Mutex> guard(result_mutex);
+      executed_units->push(unit);
+    }
+  }
+  return true;
+}
+
+class WasmCompilationTask : public CancelableTask {
+ public:
+  WasmCompilationTask(
+      Isolate* isolate,
+      std::vector<compiler::WasmCompilationUnit*>* compilation_units,
+      std::queue<compiler::WasmCompilationUnit*>* executed_units,
+      base::Semaphore* on_finished, base::Mutex* result_mutex,
+      base::AtomicNumber<size_t>* next_unit)
+      : CancelableTask(isolate),
+        isolate_(isolate),
+        compilation_units_(compilation_units),
+        executed_units_(executed_units),
+        on_finished_(on_finished),
+        result_mutex_(result_mutex),
+        next_unit_(next_unit) {}
+
+  void RunInternal() override {
+    while (FetchAndExecuteCompilationUnit(isolate_, compilation_units_,
+                                          executed_units_, result_mutex_,
+                                          next_unit_)) {
+    }
+    on_finished_->Signal();
+  }
+
+  Isolate* isolate_;
+  std::vector<compiler::WasmCompilationUnit*>* compilation_units_;
+  std::queue<compiler::WasmCompilationUnit*>* executed_units_;
+  base::Semaphore* on_finished_;
+  base::Mutex* result_mutex_;
+  base::AtomicNumber<size_t>* next_unit_;
+};
+
+// Records statistics on the code generated by compiling WASM functions.
+struct CodeStats {
+  size_t code_size;
+  size_t reloc_size;
+
+  inline CodeStats() : code_size(0), reloc_size(0) {}
+
+  inline void Record(Code* code) {
+    code_size += code->body_size();
+    reloc_size += code->relocation_info()->length();
+  }
+
+  inline void Report() {
+    PrintF("Total generated wasm code: %zu bytes\n", code_size);
+    PrintF("Total generated wasm reloc: %zu bytes\n", reloc_size);
+  }
+};
+
+bool CompileWrappersToImportedFunctions(
+    Isolate* isolate, const WasmModule* module, const Handle<JSReceiver> ffi,
+    WasmModuleInstance* instance, ErrorThrower* thrower, Factory* factory) {
+  if (module->import_table.size() > 0) {
+    instance->import_code.reserve(module->import_table.size());
+    for (uint32_t index = 0; index < module->import_table.size(); ++index) {
+      const WasmImport& import = module->import_table[index];
+      WasmName module_name = module->GetNameOrNull(import.module_name_offset,
+                                                   import.module_name_length);
+      WasmName function_name = module->GetNameOrNull(
+          import.function_name_offset, import.function_name_length);
+      MaybeHandle<JSFunction> function = LookupFunction(
+          *thrower, factory, ffi, index, module_name, function_name);
+      if (function.is_null()) return false;
+
+      Handle<Code> code = compiler::CompileWasmToJSWrapper(
+          isolate, function.ToHandleChecked(), import.sig, module_name,
+          function_name);
+      instance->import_code[index] = code;
+    }
+  }
+  return true;
+}
+
+void InitializeParallelCompilation(
+    Isolate* isolate, const std::vector<WasmFunction>& functions,
+    std::vector<compiler::WasmCompilationUnit*>& compilation_units,
+    ModuleEnv& module_env, ErrorThrower& thrower) {
+  for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) {
+    compilation_units[i] = new compiler::WasmCompilationUnit(
+        &thrower, isolate, &module_env, &functions[i], i);
+  }
+}
+
+uint32_t* StartCompilationTasks(
+    Isolate* isolate,
+    std::vector<compiler::WasmCompilationUnit*>& compilation_units,
+    std::queue<compiler::WasmCompilationUnit*>& executed_units,
+    base::Semaphore* pending_tasks, base::Mutex& result_mutex,
+    base::AtomicNumber<size_t>& next_unit) {
+  const size_t num_tasks =
+      Min(static_cast<size_t>(FLAG_wasm_num_compilation_tasks),
+          V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads());
+  uint32_t* task_ids = new uint32_t[num_tasks];
+  for (size_t i = 0; i < num_tasks; ++i) {
+    WasmCompilationTask* task =
+        new WasmCompilationTask(isolate, &compilation_units, &executed_units,
+                                pending_tasks, &result_mutex, &next_unit);
+    task_ids[i] = task->id();
+    V8::GetCurrentPlatform()->CallOnBackgroundThread(
+        task, v8::Platform::kShortRunningTask);
+  }
+  return task_ids;
+}
+
+void WaitForCompilationTasks(Isolate* isolate, uint32_t* task_ids,
+                             base::Semaphore* pending_tasks) {
+  const size_t num_tasks =
+      Min(static_cast<size_t>(FLAG_wasm_num_compilation_tasks),
+          V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads());
+  for (size_t i = 0; i < num_tasks; ++i) {
+    // If the task has not started yet, then we abort it. Otherwise we wait for
+    // it to finish.
+    if (!isolate->cancelable_task_manager()->TryAbort(task_ids[i])) {
+      pending_tasks->Wait();
+    }
+  }
+}
+
+void FinishCompilationUnits(
+    std::queue<compiler::WasmCompilationUnit*>& executed_units,
+    std::vector<Handle<Code>>& results, base::Mutex& result_mutex) {
+  while (true) {
+    compiler::WasmCompilationUnit* unit = nullptr;
+    {
+      base::LockGuard<base::Mutex> guard(&result_mutex);
+      if (executed_units.empty()) {
+        break;
+      }
+      unit = executed_units.front();
+      executed_units.pop();
+    }
+    int j = unit->index();
+    results[j] = unit->FinishCompilation();
+    delete unit;
+  }
+}
+
+void CompileInParallel(Isolate* isolate, const WasmModule* module,
+                       std::vector<Handle<Code>>& functions,
+                       ErrorThrower* thrower, ModuleEnv* module_env) {
+  // Data structures for the parallel compilation.
+  std::vector<compiler::WasmCompilationUnit*> compilation_units(
+      module->functions.size());
+  std::queue<compiler::WasmCompilationUnit*> executed_units;
+
+  //-----------------------------------------------------------------------
+  // For parallel compilation:
+  // 1) The main thread allocates a compilation unit for each wasm function
+  //    and stores them in the vector {compilation_units}.
+  // 2) The main thread spawns {WasmCompilationTask} instances which run on
+  //    the background threads.
+  // 3.a) The background threads and the main thread pick one compilation
+  //      unit at a time and execute the parallel phase of the compilation
+  //      unit. After finishing the execution of the parallel phase, the
+  //      result is enqueued in {executed_units}.
+  // 3.b) If {executed_units} contains a compilation unit, the main thread
+  //      dequeues it and finishes the compilation.
+  // 4) After the parallel phase of all compilation units has started, the
+  //    main thread waits for all {WasmCompilationTask} instances to finish.
+  // 5) The main thread finishes the compilation.
+
+  // Turn on the {CanonicalHandleScope} so that the background threads can
+  // use the node cache.
+  CanonicalHandleScope canonical(isolate);
+
+  // 1) The main thread allocates a compilation unit for each wasm function
+  //    and stores them in the vector {compilation_units}.
+  InitializeParallelCompilation(isolate, module->functions, compilation_units,
+                                *module_env, *thrower);
+
+  // Objects for the synchronization with the background threads.
+  base::Mutex result_mutex;
+  base::AtomicNumber<size_t> next_unit(
+      static_cast<size_t>(FLAG_skip_compiling_wasm_funcs));
+
+  // 2) The main thread spawns {WasmCompilationTask} instances which run on
+  //    the background threads.
+  base::SmartArrayPointer<uint32_t> task_ids(StartCompilationTasks(
+      isolate, compilation_units, executed_units, module->pending_tasks.get(),
+      result_mutex, next_unit));
+
+  // 3.a) The background threads and the main thread pick one compilation
+  //      unit at a time and execute the parallel phase of the compilation
+  //      unit. After finishing the execution of the parallel phase, the
+  //      result is enqueued in {executed_units}.
+  while (FetchAndExecuteCompilationUnit(isolate, &compilation_units,
+                                        &executed_units, &result_mutex,
+                                        &next_unit)) {
+    // 3.b) If {executed_units} contains a compilation unit, the main thread
+    //      dequeues it and finishes the compilation unit. Compilation units
+    //      are finished concurrently to the background threads to save
+    //      memory.
+    FinishCompilationUnits(executed_units, functions, result_mutex);
+  }
+  // 4) After the parallel phase of all compilation units has started, the
+  //    main thread waits for all {WasmCompilationTask} instances to finish.
+  WaitForCompilationTasks(isolate, task_ids.get(), module->pending_tasks.get());
+  // Finish the compilation of the remaining compilation units.
+  FinishCompilationUnits(executed_units, functions, result_mutex);
+}
+
+void CompileSequentially(Isolate* isolate, const WasmModule* module,
+                         std::vector<Handle<Code>>& functions,
+                         ErrorThrower* thrower, ModuleEnv* module_env) {
+  DCHECK(!thrower->error());
+
+  for (uint32_t i = FLAG_skip_compiling_wasm_funcs;
+       i < module->functions.size(); ++i) {
+    const WasmFunction& func = module->functions[i];
+
+    DCHECK_EQ(i, func.func_index);
+    WasmName str = module->GetName(func.name_offset, func.name_length);
+    Handle<Code> code = Handle<Code>::null();
+    // Compile the function.
+    code = compiler::WasmCompilationUnit::CompileWasmFunction(
+        thrower, isolate, module_env, &func);
+    if (code.is_null()) {
+      thrower->Error("Compilation of #%d:%.*s failed.", i, str.length(),
+                     str.start());
+      break;
+    }
+      // Install the code into the linker table.
+    functions[i] = code;
+  }
+}
+
+void PopulateFunctionTable(WasmModuleInstance* instance) {
+  if (!instance->function_table.is_null()) {
+    uint32_t table_size = instance->module->FunctionTableSize();
+    DCHECK_EQ(table_size * 2, instance->function_table->length());
+    uint32_t populated_table_size =
+        static_cast<uint32_t>(instance->module->function_table.size());
+    for (uint32_t i = 0; i < populated_table_size; ++i) {
+    instance->function_table->set(
+        i + table_size,
+        *instance->function_code[instance->module->function_table[i]]);
+    }
+  }
+}
+}  // namespace
+
+void SetDeoptimizationData(Factory* factory, Handle<JSObject> js_object,
+                           std::vector<Handle<Code>>& functions) {
+  for (size_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) {
+    Handle<Code> code = functions[i];
+    DCHECK(code->deoptimization_data() == nullptr ||
+           code->deoptimization_data()->length() == 0);
+    Handle<FixedArray> deopt_data = factory->NewFixedArray(2, TENURED);
+    if (!js_object.is_null()) {
+      deopt_data->set(0, *js_object);
+    }
+    deopt_data->set(1, Smi::FromInt(static_cast<int>(i)));
+    deopt_data->set_length(2);
+    code->set_deoptimization_data(*deopt_data);
+  }
+}
+
+Handle<FixedArray> WasmModule::CompileFunctions(Isolate* isolate) const {
+  Factory* factory = isolate->factory();
+  ErrorThrower thrower(isolate, "WasmModule::CompileFunctions()");
+
+  WasmModuleInstance temp_instance_for_compilation(this);
+  temp_instance_for_compilation.function_table =
+      BuildFunctionTable(isolate, this);
+  temp_instance_for_compilation.context = isolate->native_context();
+  temp_instance_for_compilation.mem_size = GetMinModuleMemSize(this);
+  temp_instance_for_compilation.mem_start = nullptr;
+  temp_instance_for_compilation.globals_start = nullptr;
+
+  ModuleEnv module_env;
+  module_env.module = this;
+  module_env.instance = &temp_instance_for_compilation;
+  module_env.origin = origin;
+  InitializePlaceholders(factory, &module_env.placeholders, functions.size());
+
+  Handle<FixedArray> ret =
+      factory->NewFixedArray(static_cast<int>(functions.size()), TENURED);
+
+  temp_instance_for_compilation.import_code.resize(import_table.size());
+  for (uint32_t i = 0; i < import_table.size(); ++i) {
+    temp_instance_for_compilation.import_code[i] =
+        CreatePlaceholder(factory, i, Code::WASM_TO_JS_FUNCTION);
+  }
+  isolate->counters()->wasm_functions_per_module()->AddSample(
+      static_cast<int>(functions.size()));
+  if (FLAG_wasm_num_compilation_tasks != 0) {
+    CompileInParallel(isolate, this,
+                      temp_instance_for_compilation.function_code, &thrower,
+                      &module_env);
+  } else {
+    CompileSequentially(isolate, this,
+                        temp_instance_for_compilation.function_code, &thrower,
+                        &module_env);
+  }
+  if (thrower.error()) {
+    return Handle<FixedArray>::null();
+  }
+
+  LinkModuleFunctions(isolate, temp_instance_for_compilation.function_code);
+
+  // At this point, compilation has completed. Update the code table
+  // and record sizes.
+  for (size_t i = FLAG_skip_compiling_wasm_funcs;
+       i < temp_instance_for_compilation.function_code.size(); ++i) {
+    Code* code = *temp_instance_for_compilation.function_code[i];
+    ret->set(static_cast<int>(i), code);
+  }
+
+  PopulateFunctionTable(&temp_instance_for_compilation);
+
+  return ret;
+}
+
 // Instantiates a wasm module as a JSObject.
 //  * allocates a backing store of {mem_size} bytes.
 //  * installs a named property "memory" for that buffer if exported
 //  * installs named properties on the object for exported functions
 //  * compiles wasm code to machine code
-MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate,
-                                              Handle<JSObject> ffi,
-                                              Handle<JSArrayBuffer> memory) {
-  this->shared_isolate = isolate;  // TODO(titzer): have a real shared isolate.
+MaybeHandle<JSObject> WasmModule::Instantiate(
+    Isolate* isolate, Handle<JSReceiver> ffi,
+    Handle<JSArrayBuffer> memory) const {
+  HistogramTimerScope wasm_instantiate_module_time_scope(
+      isolate->counters()->wasm_instantiate_module_time());
   ErrorThrower thrower(isolate, "WasmModule::Instantiate()");
   Factory* factory = isolate->factory();
 
@@ -395,13 +779,34 @@
   WasmModuleInstance instance(this);
   instance.context = isolate->native_context();
   instance.js_object = factory->NewJSObjectFromMap(map, TENURED);
-  Handle<FixedArray> code_table =
-      factory->NewFixedArray(static_cast<int>(functions.size()), TENURED);
+
+  Handle<FixedArray> code_table = CompileFunctions(isolate);
+  if (code_table.is_null()) return Handle<JSObject>::null();
+
   instance.js_object->SetInternalField(kWasmModuleCodeTable, *code_table);
+  size_t module_bytes_len =
+      instance.module->module_end - instance.module->module_start;
+  DCHECK_LE(module_bytes_len, static_cast<size_t>(kMaxInt));
+  Vector<const uint8_t> module_bytes_vec(instance.module->module_start,
+                                         static_cast<int>(module_bytes_len));
+  Handle<String> module_bytes_string =
+      factory->NewStringFromOneByte(module_bytes_vec, TENURED)
+          .ToHandleChecked();
+  instance.js_object->SetInternalField(kWasmModuleBytesString,
+                                       *module_bytes_string);
+
+  for (uint32_t i = 0; i < functions.size(); ++i) {
+    Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i)));
+    instance.function_code[i] = code;
+  }
 
   //-------------------------------------------------------------------------
   // Allocate and initialize the linear memory.
   //-------------------------------------------------------------------------
+  isolate->counters()->wasm_min_mem_pages_count()->AddSample(
+      instance.module->min_mem_pages);
+  isolate->counters()->wasm_max_mem_pages_count()->AddSample(
+      instance.module->max_mem_pages);
   if (memory.is_null()) {
     if (!AllocateMemory(&thrower, isolate, &instance)) {
       return MaybeHandle<JSObject>();
@@ -424,136 +829,111 @@
                                          *instance.globals_buffer);
   }
 
-  //-------------------------------------------------------------------------
-  // Compile wrappers to imported functions.
-  //-------------------------------------------------------------------------
-  uint32_t index = 0;
-  instance.function_table = BuildFunctionTable(isolate, this);
-  WasmLinker linker(isolate, functions.size());
+  HistogramTimerScope wasm_compile_module_time_scope(
+      isolate->counters()->wasm_compile_module_time());
+
   ModuleEnv module_env;
   module_env.module = this;
   module_env.instance = &instance;
-  module_env.linker = &linker;
   module_env.origin = origin;
 
-  if (import_table.size() > 0) {
-    instance.import_code.reserve(import_table.size());
-    for (const WasmImport& import : import_table) {
-      WasmName module_name =
-          GetNameOrNull(import.module_name_offset, import.module_name_length);
-      WasmName function_name = GetNameOrNull(import.function_name_offset,
-                                             import.function_name_length);
-      MaybeHandle<JSFunction> function = LookupFunction(
-          thrower, factory, ffi, index, module_name, function_name);
-      if (function.is_null()) return MaybeHandle<JSObject>();
-      Handle<Code> code = compiler::CompileWasmToJSWrapper(
-          isolate, &module_env, function.ToHandleChecked(), import.sig,
-          module_name, function_name);
-      instance.import_code.push_back(code);
-      index++;
-    }
+  //-------------------------------------------------------------------------
+  // Compile wrappers to imported functions.
+  //-------------------------------------------------------------------------
+  if (!CompileWrappersToImportedFunctions(isolate, this, ffi, &instance,
+                                          &thrower, factory)) {
+    return MaybeHandle<JSObject>();
   }
 
-  //-------------------------------------------------------------------------
-  // Compile all functions in the module.
-  //-------------------------------------------------------------------------
+  // If FLAG_print_wasm_code_size is set, this aggregates the sum of all code
+  // objects created for this module.
+  // TODO(titzer): switch this to TRACE_EVENT
+  CodeStats code_stats;
+  if (FLAG_print_wasm_code_size) {
+    for (Handle<Code> c : instance.function_code) code_stats.Record(*c);
+    for (Handle<Code> c : instance.import_code) code_stats.Record(*c);
+  }
 
-  // First pass: compile each function and initialize the code table.
-  index = FLAG_skip_compiling_wasm_funcs;
-  while (index < functions.size()) {
-    const WasmFunction& func = functions[index];
-    if (thrower.error()) break;
-    DCHECK_EQ(index, func.func_index);
+  {
+    instance.js_object->SetInternalField(kWasmModuleFunctionTable,
+                                         Smi::FromInt(0));
+    LinkImports(isolate, instance.function_code, instance.import_code);
 
-    WasmName str = GetName(func.name_offset, func.name_length);
-    WasmName str_null = {nullptr, 0};
-    Handle<String> name = factory->InternalizeUtf8String(
-        Vector<const char>(str.name, str.length));
-    Handle<Code> code = Handle<Code>::null();
-    Handle<JSFunction> function = Handle<JSFunction>::null();
-    if (func.external) {
-      // Lookup external function in FFI object.
-      MaybeHandle<JSFunction> function =
-          LookupFunction(thrower, factory, ffi, index, str, str_null);
-      if (function.is_null()) return MaybeHandle<JSObject>();
-      code = compiler::CompileWasmToJSWrapper(isolate, &module_env,
-                                              function.ToHandleChecked(),
-                                              func.sig, str, str_null);
-    } else {
-      // Compile the function.
-      code = compiler::CompileWasmFunction(thrower, isolate, &module_env, func);
-      if (code.is_null()) {
-        thrower.Error("Compilation of #%d:%.*s failed.", index, str.length,
-                      str.name);
-        return MaybeHandle<JSObject>();
+    SetDeoptimizationData(factory, instance.js_object, instance.function_code);
+
+    //-------------------------------------------------------------------------
+    // Create and populate the exports object.
+    //-------------------------------------------------------------------------
+    if (export_table.size() > 0 || mem_export) {
+      Handle<JSObject> exports_object;
+      if (origin == kWasmOrigin) {
+        // Create the "exports" object.
+        Handle<JSFunction> object_function = Handle<JSFunction>(
+            isolate->native_context()->object_function(), isolate);
+        exports_object = factory->NewJSObject(object_function, TENURED);
+        Handle<String> exports_name = factory->InternalizeUtf8String("exports");
+        JSObject::AddProperty(instance.js_object, exports_name, exports_object,
+                              READ_ONLY);
+      } else {
+        // Just export the functions directly on the object returned.
+        exports_object = instance.js_object;
       }
-      if (func.exported) {
-        function = compiler::CompileJSToWasmWrapper(
-            isolate, &module_env, name, code, instance.js_object, index);
+
+      PropertyDescriptor desc;
+      desc.set_writable(false);
+
+      // Compile wrappers and add them to the exports object.
+      for (const WasmExport& exp : export_table) {
+        if (thrower.error()) break;
+        WasmName str = GetName(exp.name_offset, exp.name_length);
+        Handle<String> name = factory->InternalizeUtf8String(str);
+        Handle<Code> code = instance.function_code[exp.func_index];
+        Handle<JSFunction> function = compiler::CompileJSToWasmWrapper(
+            isolate, &module_env, name, code, instance.js_object,
+            exp.func_index);
+        if (FLAG_print_wasm_code_size) {
+          code_stats.Record(function->code());
+        }
+        desc.set_value(function);
+        Maybe<bool> status = JSReceiver::DefineOwnProperty(
+            isolate, exports_object, name, &desc, Object::THROW_ON_ERROR);
+        if (!status.IsJust()) {
+          thrower.Error("export of %.*s failed.", str.length(), str.start());
+          break;
+        }
+      }
+
+      if (mem_export) {
+        // Export the memory as a named property.
+        Handle<String> name = factory->InternalizeUtf8String("memory");
+        JSObject::AddProperty(exports_object, name, instance.mem_buffer,
+                              READ_ONLY);
       }
     }
-    if (!code.is_null()) {
-      // Install the code into the linker table.
-      linker.Finish(index, code);
-      code_table->set(index, *code);
-    }
-    if (func.exported) {
-      // Exported functions are installed as read-only properties on the module.
-      JSObject::AddProperty(instance.js_object, name, function, READ_ONLY);
-    }
-    index++;
   }
 
-  // Second pass: patch all direct call sites.
-  linker.Link(instance.function_table, this->function_table);
-  instance.js_object->SetInternalField(kWasmModuleFunctionTable,
-                                       Smi::FromInt(0));
-
-  //-------------------------------------------------------------------------
-  // Create and populate the exports object.
-  //-------------------------------------------------------------------------
-  if (export_table.size() > 0 || mem_export) {
-    index = 0;
-    // Create the "exports" object.
-    Handle<JSFunction> object_function = Handle<JSFunction>(
-        isolate->native_context()->object_function(), isolate);
-    Handle<JSObject> exports_object =
-        factory->NewJSObject(object_function, TENURED);
-    Handle<String> exports_name = factory->InternalizeUtf8String("exports");
-    JSObject::AddProperty(instance.js_object, exports_name, exports_object,
-                          READ_ONLY);
-
-    // Compile wrappers and add them to the exports object.
-    for (const WasmExport& exp : export_table) {
-      if (thrower.error()) break;
-      WasmName str = GetName(exp.name_offset, exp.name_length);
-      Handle<String> name = factory->InternalizeUtf8String(
-          Vector<const char>(str.name, str.length));
-      Handle<Code> code = linker.GetFunctionCode(exp.func_index);
-      Handle<JSFunction> function = compiler::CompileJSToWasmWrapper(
-          isolate, &module_env, name, code, instance.js_object, exp.func_index);
-      JSObject::AddProperty(exports_object, name, function, READ_ONLY);
-    }
-
-    if (mem_export) {
-      // Export the memory as a named property.
-      Handle<String> name = factory->InternalizeUtf8String("memory");
-      JSObject::AddProperty(exports_object, name, instance.mem_buffer,
-                            READ_ONLY);
-    }
+  if (FLAG_print_wasm_code_size) {
+    code_stats.Report();
   }
+  //-------------------------------------------------------------------------
+  // Attach the function name table.
+  //-------------------------------------------------------------------------
+  Handle<ByteArray> function_name_table =
+      BuildFunctionNamesTable(isolate, module_env.module);
+  instance.js_object->SetInternalField(kWasmFunctionNamesArray,
+                                       *function_name_table);
 
   // Run the start function if one was specified.
   if (this->start_function_index >= 0) {
     HandleScope scope(isolate);
     uint32_t index = static_cast<uint32_t>(this->start_function_index);
     Handle<String> name = isolate->factory()->NewStringFromStaticChars("start");
-    Handle<Code> code = linker.GetFunctionCode(index);
+    Handle<Code> code = instance.function_code[index];
     Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper(
         isolate, &module_env, name, code, instance.js_object, index);
 
     // Call the JS function.
-    Handle<Object> undefined(isolate->heap()->undefined_value(), isolate);
+    Handle<Object> undefined = isolate->factory()->undefined_value();
     MaybeHandle<Object> retval =
         Execution::Call(isolate, jsfunc, undefined, 0, nullptr);
 
@@ -564,11 +944,12 @@
   return instance.js_object;
 }
 
-
-Handle<Code> ModuleEnv::GetFunctionCode(uint32_t index) {
+// TODO(mtrofin): remove this once we move to WASM_DIRECT_CALL
+Handle<Code> ModuleEnv::GetCodeOrPlaceholder(uint32_t index) const {
   DCHECK(IsValidFunction(index));
-  if (linker) return linker->GetFunctionCode(index);
-  return instance ? instance->function_code[index] : Handle<Code>::null();
+  if (!placeholders.empty()) return placeholders[index];
+  DCHECK_NOT_NULL(instance);
+  return instance->function_code[index];
 }
 
 Handle<Code> ModuleEnv::GetImportCode(uint32_t index) {
@@ -581,102 +962,122 @@
   DCHECK(IsValidFunction(index));
   // Always make a direct call to whatever is in the table at that location.
   // A wrapper will be generated for FFI calls.
-  WasmFunction* function = &module->functions[index];
+  const WasmFunction* function = &module->functions[index];
   return GetWasmCallDescriptor(zone, function->sig);
 }
 
+Handle<Object> GetWasmFunctionNameOrNull(Isolate* isolate, Handle<Object> wasm,
+                                         uint32_t func_index) {
+  if (!wasm->IsUndefined(isolate)) {
+    Handle<ByteArray> func_names_arr_obj(
+        ByteArray::cast(Handle<JSObject>::cast(wasm)->GetInternalField(
+            kWasmFunctionNamesArray)),
+        isolate);
+    // TODO(clemens): Extract this from the module bytes; skip whole function
+    // name table.
+    Handle<Object> name;
+    if (GetWasmFunctionNameFromTable(func_names_arr_obj, func_index)
+            .ToHandle(&name)) {
+      return name;
+    }
+  }
+  return isolate->factory()->null_value();
+}
+
+Handle<String> GetWasmFunctionName(Isolate* isolate, Handle<Object> wasm,
+                                   uint32_t func_index) {
+  Handle<Object> name_or_null =
+      GetWasmFunctionNameOrNull(isolate, wasm, func_index);
+  if (!name_or_null->IsNull(isolate)) {
+    return Handle<String>::cast(name_or_null);
+  }
+  return isolate->factory()->NewStringFromStaticChars("<WASM UNNAMED>");
+}
+
+bool IsWasmObject(Object* object) {
+  if (!object->IsJSObject()) return false;
+  JSObject* obj = JSObject::cast(object);
+  if (obj->GetInternalFieldCount() != kWasmModuleInternalFieldCount ||
+      !obj->GetInternalField(kWasmModuleCodeTable)->IsFixedArray() ||
+      !obj->GetInternalField(kWasmMemArrayBuffer)->IsJSArrayBuffer() ||
+      !obj->GetInternalField(kWasmFunctionNamesArray)->IsByteArray() ||
+      !obj->GetInternalField(kWasmModuleBytesString)->IsSeqOneByteString()) {
+    return false;
+  }
+  DisallowHeapAllocation no_gc;
+  SeqOneByteString* bytes =
+      SeqOneByteString::cast(obj->GetInternalField(kWasmModuleBytesString));
+  if (bytes->length() < 4) return false;
+  if (memcmp(bytes->GetChars(), "\0asm", 4)) return false;
+
+  // All checks passed.
+  return true;
+}
+
+SeqOneByteString* GetWasmBytes(JSObject* wasm) {
+  return SeqOneByteString::cast(wasm->GetInternalField(kWasmModuleBytesString));
+}
+
+WasmDebugInfo* GetDebugInfo(JSObject* wasm) {
+  Object* info = wasm->GetInternalField(kWasmDebugInfo);
+  if (!info->IsUndefined(wasm->GetIsolate())) return WasmDebugInfo::cast(info);
+  Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(handle(wasm));
+  wasm->SetInternalField(kWasmDebugInfo, *new_info);
+  return *new_info;
+}
+
+namespace testing {
 
 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
                                 const byte* module_end, bool asm_js) {
   HandleScope scope(isolate);
   Zone zone(isolate->allocator());
+  ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
+
   // Decode the module, but don't verify function bodies, since we'll
   // be compiling them anyway.
-  ModuleResult result = DecodeWasmModule(isolate, &zone, module_start,
-                                         module_end, false, kWasmOrigin);
-  if (result.failed()) {
-    if (result.val) {
-      delete result.val;
-    }
+  ModuleResult decoding_result =
+      DecodeWasmModule(isolate, &zone, module_start, module_end, false,
+                       asm_js ? kAsmJsOrigin : kWasmOrigin);
+
+  std::unique_ptr<const WasmModule> module(decoding_result.val);
+  if (decoding_result.failed()) {
     // Module verification failed. throw.
-    std::ostringstream str;
-    str << "WASM.compileRun() failed: " << result;
-    isolate->Throw(
-        *isolate->factory()->NewStringFromAsciiChecked(str.str().c_str()));
+    thrower.Error("WASM.compileRun() failed: %s",
+                  decoding_result.error_msg.get());
     return -1;
   }
 
-  int32_t retval = CompileAndRunWasmModule(isolate, result.val);
-  delete result.val;
-  return retval;
-}
-
-
-int32_t CompileAndRunWasmModule(Isolate* isolate, WasmModule* module) {
-  ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
-  WasmModuleInstance instance(module);
-
-  // Allocate and initialize the linear memory.
-  if (!AllocateMemory(&thrower, isolate, &instance)) {
-    return -1;
+  if (module->import_table.size() > 0) {
+    thrower.Error("Not supported: module has imports.");
   }
-  LoadDataSegments(module, instance.mem_start, instance.mem_size);
-
-  // Allocate the globals area if necessary.
-  if (!AllocateGlobals(&thrower, isolate, &instance)) {
-    return -1;
+  if (module->export_table.size() == 0) {
+    thrower.Error("Not supported: module has no exports.");
   }
 
-  // Build the function table.
-  instance.function_table = BuildFunctionTable(isolate, module);
+  if (thrower.error()) return -1;
 
-  // Create module environment.
-  WasmLinker linker(isolate, module->functions.size());
-  ModuleEnv module_env;
-  module_env.module = module;
-  module_env.instance = &instance;
-  module_env.linker = &linker;
-  module_env.origin = module->origin;
+  Handle<JSObject> instance =
+      module
+          ->Instantiate(isolate, Handle<JSReceiver>::null(),
+                        Handle<JSArrayBuffer>::null())
+          .ToHandleChecked();
 
-  // Compile all functions.
-  Handle<Code> main_code = Handle<Code>::null();  // record last code.
-  uint32_t index = 0;
-  int main_index = 0;
-  for (const WasmFunction& func : module->functions) {
-    DCHECK_EQ(index, func.func_index);
-    if (!func.external) {
-      // Compile the function and install it in the code table.
-      Handle<Code> code =
-          compiler::CompileWasmFunction(thrower, isolate, &module_env, func);
-      if (!code.is_null()) {
-        if (func.exported) {
-          main_code = code;
-          main_index = index;
-        }
-        linker.Finish(index, code);
-      }
-      if (thrower.error()) return -1;
-    }
-    index++;
-  }
+  Handle<Name> exports = isolate->factory()->InternalizeUtf8String("exports");
+  Handle<JSObject> exports_object = Handle<JSObject>::cast(
+      JSObject::GetProperty(instance, exports).ToHandleChecked());
+  Handle<Name> main_name = isolate->factory()->NewStringFromStaticChars("main");
+  PropertyDescriptor desc;
+  Maybe<bool> property_found = JSReceiver::GetOwnPropertyDescriptor(
+      isolate, exports_object, main_name, &desc);
+  if (!property_found.FromMaybe(false)) return -1;
 
-  if (main_code.is_null()) {
-    thrower.Error("WASM.compileRun() failed: no main code found");
-    return -1;
-  }
-
-  linker.Link(instance.function_table, instance.module->function_table);
-
-  // Wrap the main code so it can be called as a JS function.
-  Handle<String> name = isolate->factory()->NewStringFromStaticChars("main");
-  Handle<JSObject> module_object = Handle<JSObject>(0, isolate);
-  Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper(
-      isolate, &module_env, name, main_code, module_object, main_index);
+  Handle<JSFunction> main_export = Handle<JSFunction>::cast(desc.value());
 
   // Call the JS function.
-  Handle<Object> undefined(isolate->heap()->undefined_value(), isolate);
+  Handle<Object> undefined = isolate->factory()->undefined_value();
   MaybeHandle<Object> retval =
-      Execution::Call(isolate, jsfunc, undefined, 0, nullptr);
+      Execution::Call(isolate, main_export, undefined, 0, nullptr);
 
   // The result should be a number.
   if (retval.is_null()) {
@@ -693,6 +1094,8 @@
   thrower.Error("WASM.compileRun() failed: Return value should be number");
   return -1;
 }
+
+}  // namespace testing
 }  // namespace wasm
 }  // namespace internal
 }  // namespace v8
diff --git a/src/wasm/wasm-module.h b/src/wasm/wasm-module.h
index 4e5aa78..019dc56 100644
--- a/src/wasm/wasm-module.h
+++ b/src/wasm/wasm-module.h
@@ -5,17 +5,17 @@
 #ifndef V8_WASM_MODULE_H_
 #define V8_WASM_MODULE_H_
 
-#include "src/wasm/wasm-opcodes.h"
-#include "src/wasm/wasm-result.h"
-
 #include "src/api.h"
 #include "src/handles.h"
+#include "src/wasm/wasm-opcodes.h"
+#include "src/wasm/wasm-result.h"
 
 namespace v8 {
 namespace internal {
 
 namespace compiler {
 class CallDescriptor;
+class WasmCompilationUnit;
 }
 
 namespace wasm {
@@ -23,69 +23,65 @@
 const size_t kMaxFunctionSize = 128 * 1024;
 const size_t kMaxStringSize = 256;
 const uint32_t kWasmMagic = 0x6d736100;
-const uint32_t kWasmVersion = 0x0a;
+const uint32_t kWasmVersion = 0x0b;
+const uint8_t kWasmFunctionTypeForm = 0x40;
 
 // WebAssembly sections are named as strings in the binary format, but
 // internally V8 uses an enum to handle them.
 //
 // Entries have the form F(enumerator, string).
-#define FOR_EACH_WASM_SECTION_TYPE(F)          \
-  F(Memory, "memory")                          \
-  F(Signatures, "signatures")                  \
-  F(Functions, "functions")                    \
-  F(Globals, "globals")                        \
-  F(DataSegments, "data_segments")             \
-  F(FunctionTable, "function_table")           \
-  F(End, "end")                                \
-  F(StartFunction, "start_function")           \
-  F(ImportTable, "import_table")               \
-  F(ExportTable, "export_table")               \
-  F(FunctionSignatures, "function_signatures") \
-  F(FunctionBodies, "function_bodies")         \
-  F(Names, "names")
+#define FOR_EACH_WASM_SECTION_TYPE(F)  \
+  F(Signatures, 1, "type")             \
+  F(ImportTable, 2, "import")          \
+  F(FunctionSignatures, 3, "function") \
+  F(FunctionTable, 4, "table")         \
+  F(Memory, 5, "memory")               \
+  F(ExportTable, 6, "export")          \
+  F(StartFunction, 7, "start")         \
+  F(FunctionBodies, 8, "code")         \
+  F(DataSegments, 9, "data")           \
+  F(Names, 10, "name")                 \
+  F(FunctionTablePad, 11, "table_pad") \
+  F(Globals, 0, "global")              \
+  F(End, 0, "end")
 
 // Contants for the above section types: {LEB128 length, characters...}.
 #define WASM_SECTION_MEMORY 6, 'm', 'e', 'm', 'o', 'r', 'y'
-#define WASM_SECTION_SIGNATURES \
-  10, 's', 'i', 'g', 'n', 'a', 't', 'u', 'r', 'e', 's'
-#define WASM_SECTION_FUNCTIONS 9, 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', 's'
-#define WASM_SECTION_GLOBALS 7, 'g', 'l', 'o', 'b', 'a', 'l', 's'
-#define WASM_SECTION_DATA_SEGMENTS \
-  13, 'd', 'a', 't', 'a', '_', 's', 'e', 'g', 'm', 'e', 'n', 't', 's'
-#define WASM_SECTION_FUNCTION_TABLE \
-  14, 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '_', 't', 'a', 'b', 'l', 'e'
+#define WASM_SECTION_SIGNATURES 4, 't', 'y', 'p', 'e'
+#define WASM_SECTION_GLOBALS 6, 'g', 'l', 'o', 'b', 'a', 'l'
+#define WASM_SECTION_DATA_SEGMENTS 4, 'd', 'a', 't', 'a'
+#define WASM_SECTION_FUNCTION_TABLE 5, 't', 'a', 'b', 'l', 'e'
 #define WASM_SECTION_END 3, 'e', 'n', 'd'
-#define WASM_SECTION_START_FUNCTION \
-  14, 's', 't', 'a', 'r', 't', '_', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n'
-#define WASM_SECTION_IMPORT_TABLE \
-  12, 'i', 'm', 'p', 'o', 'r', 't', '_', 't', 'a', 'b', 'l', 'e'
-#define WASM_SECTION_EXPORT_TABLE \
-  12, 'e', 'x', 'p', 'o', 'r', 't', '_', 't', 'a', 'b', 'l', 'e'
-#define WASM_SECTION_FUNCTION_SIGNATURES                                    \
-  19, 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '_', 's', 'i', 'g', 'n', 'a', \
-      't', 'u', 'r', 'e', 's'
-#define WASM_SECTION_FUNCTION_BODIES \
-  15, 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '_', 'b', 'o', 'd', 'i', 'e', 's'
-#define WASM_SECTION_NAMES 5, 'n', 'a', 'm', 'e', 's'
+#define WASM_SECTION_START_FUNCTION 5, 's', 't', 'a', 'r', 't'
+#define WASM_SECTION_IMPORT_TABLE 6, 'i', 'm', 'p', 'o', 'r', 't'
+#define WASM_SECTION_EXPORT_TABLE 6, 'e', 'x', 'p', 'o', 'r', 't'
+#define WASM_SECTION_FUNCTION_SIGNATURES \
+  8, 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n'
+#define WASM_SECTION_FUNCTION_BODIES 4, 'c', 'o', 'd', 'e'
+#define WASM_SECTION_NAMES 4, 'n', 'a', 'm', 'e'
+#define WASM_SECTION_FUNCTION_TABLE_PAD \
+  9, 't', 'a', 'b', 'l', 'e', '_', 'p', 'a', 'd'
 
 // Constants for the above section headers' size (LEB128 + characters).
 #define WASM_SECTION_MEMORY_SIZE ((size_t)7)
-#define WASM_SECTION_SIGNATURES_SIZE ((size_t)11)
-#define WASM_SECTION_FUNCTIONS_SIZE ((size_t)10)
-#define WASM_SECTION_GLOBALS_SIZE ((size_t)8)
-#define WASM_SECTION_DATA_SEGMENTS_SIZE ((size_t)14)
-#define WASM_SECTION_FUNCTION_TABLE_SIZE ((size_t)15)
+#define WASM_SECTION_SIGNATURES_SIZE ((size_t)5)
+#define WASM_SECTION_GLOBALS_SIZE ((size_t)7)
+#define WASM_SECTION_DATA_SEGMENTS_SIZE ((size_t)5)
+#define WASM_SECTION_FUNCTION_TABLE_SIZE ((size_t)6)
 #define WASM_SECTION_END_SIZE ((size_t)4)
-#define WASM_SECTION_START_FUNCTION_SIZE ((size_t)15)
-#define WASM_SECTION_IMPORT_TABLE_SIZE ((size_t)13)
-#define WASM_SECTION_EXPORT_TABLE_SIZE ((size_t)13)
-#define WASM_SECTION_FUNCTION_SIGNATURES_SIZE ((size_t)20)
-#define WASM_SECTION_FUNCTION_BODIES_SIZE ((size_t)16)
-#define WASM_SECTION_NAMES_SIZE ((size_t)6)
+#define WASM_SECTION_START_FUNCTION_SIZE ((size_t)6)
+#define WASM_SECTION_IMPORT_TABLE_SIZE ((size_t)7)
+#define WASM_SECTION_EXPORT_TABLE_SIZE ((size_t)7)
+#define WASM_SECTION_FUNCTION_SIGNATURES_SIZE ((size_t)9)
+#define WASM_SECTION_FUNCTION_BODIES_SIZE ((size_t)5)
+#define WASM_SECTION_NAMES_SIZE ((size_t)5)
+#define WASM_SECTION_FUNCTION_TABLE_PAD_SIZE ((size_t)10)
+
+class WasmDebugInfo;
 
 struct WasmSection {
   enum class Code : uint32_t {
-#define F(enumerator, string) enumerator,
+#define F(enumerator, order, string) enumerator,
     FOR_EACH_WASM_SECTION_TYPE(F)
 #undef F
         Max
@@ -94,13 +90,13 @@
   static WasmSection::Code end();
   static WasmSection::Code next(WasmSection::Code code);
   static const char* getName(Code code);
+  static int getOrder(Code code);
   static size_t getNameLength(Code code);
+  static WasmSection::Code lookup(const byte* string, uint32_t length);
 };
 
 enum WasmFunctionDeclBit {
   kDeclFunctionName = 0x01,
-  kDeclFunctionImport = 0x02,
-  kDeclFunctionLocals = 0x04,
   kDeclFunctionExport = 0x08
 };
 
@@ -108,6 +104,8 @@
 static const size_t kDeclMemorySize = 3;
 static const size_t kDeclDataSegmentSize = 13;
 
+static const uint32_t kMaxReturnCount = 1;
+
 // Static representation of a WASM function.
 struct WasmFunction {
   FunctionSig* sig;      // signature of the function.
@@ -117,12 +115,6 @@
   uint32_t name_length;  // length in bytes of the name.
   uint32_t code_start_offset;    // offset in the module bytes of code start.
   uint32_t code_end_offset;      // offset in the module bytes of code end.
-  uint16_t local_i32_count;      // number of i32 local variables.
-  uint16_t local_i64_count;      // number of i64 local variables.
-  uint16_t local_f32_count;      // number of f32 local variables.
-  uint16_t local_f64_count;      // number of f64 local variables.
-  bool exported;                 // true if this function is exported.
-  bool external;  // true if this function is externally supplied.
 };
 
 // Static representation of an imported WASM function.
@@ -167,7 +159,6 @@
   static const uint32_t kMinMemPages = 1;       // Minimum memory size = 64kb
   static const uint32_t kMaxMemPages = 16384;   // Maximum memory size =  1gb
 
-  Isolate* shared_isolate;    // isolate for storing shared code.
   const byte* module_start;   // starting address for the module bytes.
   const byte* module_end;     // end address for the module bytes.
   uint32_t min_mem_pages;     // minimum size of the memory in 64k pages.
@@ -178,12 +169,23 @@
   ModuleOrigin origin;        // origin of the module
 
   std::vector<WasmGlobal> globals;             // globals in this module.
+  uint32_t globals_size;                       // size of globals table.
+  uint32_t indirect_table_size;                // size of indirect function
+                                               //     table (includes padding).
   std::vector<FunctionSig*> signatures;        // signatures in this module.
   std::vector<WasmFunction> functions;         // functions in this module.
   std::vector<WasmDataSegment> data_segments;  // data segments in this module.
   std::vector<uint16_t> function_table;        // function table.
   std::vector<WasmImport> import_table;        // import table.
   std::vector<WasmExport> export_table;        // export table.
+  // We store the semaphore here to extend its lifetime. In <libc-2.21, which we
+  // use on the try bots, semaphore::Wait() can return while some compilation
+  // tasks are still executing semaphore::Signal(). If the semaphore is cleaned
+  // up right after semaphore::Wait() returns, then this can cause an
+  // invalid-semaphore error in the compilation tasks.
+  // TODO(wasm): Move this semaphore back to CompileInParallel when the try bots
+  // switch to libc-2.21 or higher.
+  base::SmartPointer<base::Semaphore> pending_tasks;
 
   WasmModule();
 
@@ -191,30 +193,54 @@
   WasmName GetName(uint32_t offset, uint32_t length) const {
     if (length == 0) return {"<?>", 3};  // no name.
     CHECK(BoundsCheck(offset, offset + length));
-    return {reinterpret_cast<const char*>(module_start + offset), length};
+    DCHECK_GE(static_cast<int>(length), 0);
+    return {reinterpret_cast<const char*>(module_start + offset),
+            static_cast<int>(length)};
+  }
+
+  // Get a string stored in the module bytes representing a function name.
+  WasmName GetName(WasmFunction* function) const {
+    return GetName(function->name_offset, function->name_length);
   }
 
   // Get a string stored in the module bytes representing a name.
   WasmName GetNameOrNull(uint32_t offset, uint32_t length) const {
-    if (length == 0) return {NULL, 0};  // no name.
+    if (offset == 0 && length == 0) return {NULL, 0};  // no name.
     CHECK(BoundsCheck(offset, offset + length));
-    return {reinterpret_cast<const char*>(module_start + offset), length};
+    DCHECK_GE(static_cast<int>(length), 0);
+    return {reinterpret_cast<const char*>(module_start + offset),
+            static_cast<int>(length)};
+  }
+
+  // Get a string stored in the module bytes representing a function name.
+  WasmName GetNameOrNull(const WasmFunction* function) const {
+    return GetNameOrNull(function->name_offset, function->name_length);
   }
 
   // Checks the given offset range is contained within the module bytes.
   bool BoundsCheck(uint32_t start, uint32_t end) const {
     size_t size = module_end - module_start;
-    return start < size && end < size;
+    return start <= size && end <= size;
   }
 
   // Creates a new instantiation of the module in the given isolate.
-  MaybeHandle<JSObject> Instantiate(Isolate* isolate, Handle<JSObject> ffi,
-                                    Handle<JSArrayBuffer> memory);
+  MaybeHandle<JSObject> Instantiate(Isolate* isolate, Handle<JSReceiver> ffi,
+                                    Handle<JSArrayBuffer> memory) const;
+
+  Handle<FixedArray> CompileFunctions(Isolate* isolate) const;
+
+  uint32_t FunctionTableSize() const {
+    if (indirect_table_size > 0) {
+      return indirect_table_size;
+    }
+    DCHECK_LE(function_table.size(), UINT32_MAX);
+    return static_cast<uint32_t>(function_table.size());
+  }
 };
 
 // An instantiated WASM module, including memory, function table, etc.
 struct WasmModuleInstance {
-  WasmModule* module;  // static representation of the module.
+  const WasmModule* module;  // static representation of the module.
   // -- Heap allocated --------------------------------------------------------
   Handle<JSObject> js_object;            // JavaScript module object.
   Handle<Context> context;               // JavaScript native context.
@@ -225,34 +251,33 @@
   std::vector<Handle<Code>> import_code;    // code objects for each import.
   // -- raw memory ------------------------------------------------------------
   byte* mem_start;  // start of linear memory.
-  size_t mem_size;  // size of the linear memory.
+  uint32_t mem_size;  // size of the linear memory.
   // -- raw globals -----------------------------------------------------------
   byte* globals_start;  // start of the globals area.
-  size_t globals_size;  // size of the globals area.
 
-  explicit WasmModuleInstance(WasmModule* m)
+  explicit WasmModuleInstance(const WasmModule* m)
       : module(m),
+        function_code(m->functions.size()),
+        import_code(m->import_table.size()),
         mem_start(nullptr),
         mem_size(0),
-        globals_start(nullptr),
-        globals_size(0) {}
+        globals_start(nullptr) {}
 };
 
-// forward declaration.
-class WasmLinker;
-
 // Interface provided to the decoder/graph builder which contains only
 // minimal information about the globals, functions, and function tables.
 struct ModuleEnv {
-  WasmModule* module;
+  const WasmModule* module;
   WasmModuleInstance* instance;
-  WasmLinker* linker;
   ModuleOrigin origin;
+  // TODO(mtrofin): remove this once we introduce WASM_DIRECT_CALL
+  // reloc infos.
+  std::vector<Handle<Code>> placeholders;
 
   bool IsValidGlobal(uint32_t index) {
     return module && index < module->globals.size();
   }
-  bool IsValidFunction(uint32_t index) {
+  bool IsValidFunction(uint32_t index) const {
     return module && index < module->functions.size();
   }
   bool IsValidSignature(uint32_t index) {
@@ -277,15 +302,14 @@
     DCHECK(IsValidSignature(index));
     return module->signatures[index];
   }
-  size_t FunctionTableSize() {
-    return module ? module->function_table.size() : 0;
+  uint32_t FunctionTableSize() const {
+    return module->FunctionTableSize();
   }
 
   bool asm_js() { return origin == kAsmJsOrigin; }
 
-  Handle<Code> GetFunctionCode(uint32_t index);
+  Handle<Code> GetCodeOrPlaceholder(uint32_t index) const;
   Handle<Code> GetImportCode(uint32_t index);
-  Handle<FixedArray> GetFunctionTable();
 
   static compiler::CallDescriptor* GetWasmCallDescriptor(Zone* zone,
                                                          FunctionSig* sig);
@@ -306,17 +330,45 @@
 std::ostream& operator<<(std::ostream& os, const WasmFunction& function);
 std::ostream& operator<<(std::ostream& os, const WasmFunctionName& name);
 
-typedef Result<WasmModule*> ModuleResult;
+typedef Result<const WasmModule*> ModuleResult;
 typedef Result<WasmFunction*> FunctionResult;
+typedef std::vector<std::pair<int, int>> FunctionOffsets;
+typedef Result<FunctionOffsets> FunctionOffsetsResult;
 
-// For testing. Decode, verify, and run the last exported function in the
-// given encoded module.
+// Extract a function name from the given wasm object.
+// Returns "<WASM UNNAMED>" if the function is unnamed or the name is not a
+// valid UTF-8 string.
+Handle<String> GetWasmFunctionName(Isolate* isolate, Handle<Object> wasm,
+                                   uint32_t func_index);
+
+// Extract a function name from the given wasm object.
+// Returns a null handle if the function is unnamed or the name is not a valid
+// UTF-8 string.
+Handle<Object> GetWasmFunctionNameOrNull(Isolate* isolate, Handle<Object> wasm,
+                                         uint32_t func_index);
+
+// Return the binary source bytes of a wasm module.
+SeqOneByteString* GetWasmBytes(JSObject* wasm);
+
+// Get the debug info associated with the given wasm object.
+// If no debug info exists yet, it is created automatically.
+WasmDebugInfo* GetDebugInfo(JSObject* wasm);
+
+// Check whether the given object is a wasm object.
+// This checks the number and type of internal fields, so it's not 100 percent
+// secure. If it turns out that we need more complete checks, we could add a
+// special marker as internal field, which will definitely never occur anywhere
+// else.
+bool IsWasmObject(Object* object);
+
+namespace testing {
+
+// Decode, verify, and run the function labeled "main" in the
+// given encoded module. The module should have no imports.
 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
                                 const byte* module_end, bool asm_js = false);
 
-// For testing. Decode, verify, and run the last exported function in the
-// given decoded module.
-int32_t CompileAndRunWasmModule(Isolate* isolate, WasmModule* module);
+}  // namespace testing
 
 }  // namespace wasm
 }  // namespace internal
diff --git a/src/wasm/wasm-opcodes.cc b/src/wasm/wasm-opcodes.cc
index 736c4d9..da6c161 100644
--- a/src/wasm/wasm-opcodes.cc
+++ b/src/wasm/wasm-opcodes.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "src/wasm/wasm-opcodes.h"
+#include "src/messages.h"
 #include "src/signature.h"
 
 namespace v8 {
@@ -24,27 +25,36 @@
   return "Unknown";
 }
 
+const char* WasmOpcodes::ShortOpcodeName(WasmOpcode opcode) {
+  switch (opcode) {
+#define DECLARE_NAME_CASE(name, opcode, sig) \
+  case kExpr##name:                          \
+    return #name;
+    FOREACH_OPCODE(DECLARE_NAME_CASE)
+#undef DECLARE_NAME_CASE
+    default:
+      break;
+  }
+  return "Unknown";
+}
 
 std::ostream& operator<<(std::ostream& os, const FunctionSig& sig) {
   if (sig.return_count() == 0) os << "v";
-  for (size_t i = 0; i < sig.return_count(); i++) {
+  for (size_t i = 0; i < sig.return_count(); ++i) {
     os << WasmOpcodes::ShortNameOf(sig.GetReturn(i));
   }
   os << "_";
   if (sig.parameter_count() == 0) os << "v";
-  for (size_t i = 0; i < sig.parameter_count(); i++) {
+  for (size_t i = 0; i < sig.parameter_count(); ++i) {
     os << WasmOpcodes::ShortNameOf(sig.GetParam(i));
   }
   return os;
 }
 
-
 #define DECLARE_SIG_ENUM(name, ...) kSigEnum_##name,
 
-
 enum WasmOpcodeSig { FOREACH_SIGNATURE(DECLARE_SIG_ENUM) };
 
-
 // TODO(titzer): not static-initializer safe. Wrap in LazyInstance.
 #define DECLARE_SIG(name, ...)                      \
   static LocalType kTypes_##name[] = {__VA_ARGS__}; \
@@ -60,7 +70,6 @@
 
 static byte kSimpleExprSigTable[256];
 
-
 // Initialize the signature table.
 static void InitSigTable() {
 #define SET_SIG_TABLE(name, opcode, sig) \
@@ -70,15 +79,24 @@
 #undef SET_SIG_TABLE
 }
 
+class SigTable {
+ public:
+  SigTable() {
+    // TODO(ahaas): Move {InitSigTable} into the class.
+    InitSigTable();
+  }
+  FunctionSig* Signature(WasmOpcode opcode) const {
+    return const_cast<FunctionSig*>(
+        kSimpleExprSigs[kSimpleExprSigTable[static_cast<byte>(opcode)]]);
+  }
+};
+
+static base::LazyInstance<SigTable>::type sig_table = LAZY_INSTANCE_INITIALIZER;
 
 FunctionSig* WasmOpcodes::Signature(WasmOpcode opcode) {
-  // TODO(titzer): use LazyInstance to make this thread safe.
-  if (kSimpleExprSigTable[kExprI32Add] == 0) InitSigTable();
-  return const_cast<FunctionSig*>(
-      kSimpleExprSigs[kSimpleExprSigTable[static_cast<byte>(opcode)]]);
+  return sig_table.Get().Signature(opcode);
 }
 
-
 // TODO(titzer): pull WASM_64 up to a common header.
 #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64
 #define WASM_64 1
@@ -86,64 +104,20 @@
 #define WASM_64 0
 #endif
 
-
-bool WasmOpcodes::IsSupported(WasmOpcode opcode) {
-#if !WASM_64
-  switch (opcode) {
-    // Opcodes not supported on 32-bit platforms.
-    case kExprI64Add:
-    case kExprI64Sub:
-    case kExprI64Mul:
-    case kExprI64DivS:
-    case kExprI64DivU:
-    case kExprI64RemS:
-    case kExprI64RemU:
-    case kExprI64And:
-    case kExprI64Ior:
-    case kExprI64Xor:
-    case kExprI64Shl:
-    case kExprI64ShrU:
-    case kExprI64ShrS:
-    case kExprI64Ror:
-    case kExprI64Rol:
-    case kExprI64Eq:
-    case kExprI64Ne:
-    case kExprI64LtS:
-    case kExprI64LeS:
-    case kExprI64LtU:
-    case kExprI64LeU:
-    case kExprI64GtS:
-    case kExprI64GeS:
-    case kExprI64GtU:
-    case kExprI64GeU:
-
-    case kExprI32ConvertI64:
-    case kExprI64SConvertI32:
-    case kExprI64UConvertI32:
-
-    case kExprF64ReinterpretI64:
-    case kExprI64ReinterpretF64:
-
-    case kExprI64Clz:
-    case kExprI64Ctz:
-    case kExprI64Popcnt:
-
-    case kExprF32SConvertI64:
-    case kExprF32UConvertI64:
-    case kExprF64SConvertI64:
-    case kExprF64UConvertI64:
-    case kExprI64SConvertF32:
-    case kExprI64SConvertF64:
-    case kExprI64UConvertF32:
-    case kExprI64UConvertF64:
-
-      return false;
+int WasmOpcodes::TrapReasonToMessageId(TrapReason reason) {
+  switch (reason) {
+#define TRAPREASON_TO_MESSAGE(name) \
+  case k##name:                     \
+    return MessageTemplate::kWasm##name;
+    FOREACH_WASM_TRAPREASON(TRAPREASON_TO_MESSAGE)
+#undef TRAPREASON_TO_MESSAGE
     default:
-      return true;
+      return MessageTemplate::kNone;
   }
-#else
-  return true;
-#endif
+}
+
+const char* WasmOpcodes::TrapReasonMessage(TrapReason reason) {
+  return MessageTemplate::TemplateString(TrapReasonToMessageId(reason));
 }
 }  // namespace wasm
 }  // namespace internal
diff --git a/src/wasm/wasm-opcodes.h b/src/wasm/wasm-opcodes.h
index 52f85aa..b29e4a0 100644
--- a/src/wasm/wasm-opcodes.h
+++ b/src/wasm/wasm-opcodes.h
@@ -18,7 +18,8 @@
   kLocalI32 = 1,
   kLocalI64 = 2,
   kLocalF32 = 3,
-  kLocalF64 = 4
+  kLocalF64 = 4,
+  kLocalS128 = 5
 };
 
 // Binary encoding of memory types.
@@ -32,7 +33,8 @@
   kMemI64 = 6,
   kMemU64 = 7,
   kMemF32 = 8,
-  kMemF64 = 9
+  kMemF64 = 9,
+  kMemS128 = 10
 };
 
 // We reuse the internal machine type to represent WebAssembly AST types.
@@ -43,18 +45,17 @@
 const LocalType kAstI64 = MachineRepresentation::kWord64;
 const LocalType kAstF32 = MachineRepresentation::kFloat32;
 const LocalType kAstF64 = MachineRepresentation::kFloat64;
+const LocalType kAstS128 = MachineRepresentation::kSimd128;
 // We use kTagged here because kNone is already used by kAstStmt.
 const LocalType kAstEnd = MachineRepresentation::kTagged;
 
 typedef Signature<LocalType> FunctionSig;
 std::ostream& operator<<(std::ostream& os, const FunctionSig& function);
 
-struct WasmName {
-  const char* name;
-  uint32_t length;
-};
+typedef Vector<const char> WasmName;
 
-// TODO(titzer): Renumber all the opcodes to fill in holes.
+typedef int WasmCodePosition;
+const WasmCodePosition kNoCodePosition = -1;
 
 // Control expressions and blocks.
 #define FOREACH_CONTROL_OPCODE(V) \
@@ -62,29 +63,29 @@
   V(Block, 0x01, _)               \
   V(Loop, 0x02, _)                \
   V(If, 0x03, _)                  \
-  V(IfElse, 0x04, _)              \
+  V(Else, 0x04, _)                \
   V(Select, 0x05, _)              \
   V(Br, 0x06, _)                  \
   V(BrIf, 0x07, _)                \
   V(BrTable, 0x08, _)             \
-  V(Return, 0x14, _)              \
-  V(Unreachable, 0x15, _)
+  V(Return, 0x09, _)              \
+  V(Unreachable, 0x0a, _)         \
+  V(End, 0x0F, _)
 
 // Constants, locals, globals, and calls.
 #define FOREACH_MISC_OPCODE(V) \
-  V(I8Const, 0x09, _)          \
-  V(I32Const, 0x0a, _)         \
-  V(I64Const, 0x0b, _)         \
-  V(F64Const, 0x0c, _)         \
-  V(F32Const, 0x0d, _)         \
-  V(GetLocal, 0x0e, _)         \
-  V(SetLocal, 0x0f, _)         \
-  V(LoadGlobal, 0x10, _)       \
-  V(StoreGlobal, 0x11, _)      \
-  V(CallFunction, 0x12, _)     \
-  V(CallIndirect, 0x13, _)     \
-  V(CallImport, 0x1F, _)       \
-  V(DeclLocals, 0x1E, _)
+  V(I32Const, 0x10, _)         \
+  V(I64Const, 0x11, _)         \
+  V(F64Const, 0x12, _)         \
+  V(F32Const, 0x13, _)         \
+  V(GetLocal, 0x14, _)         \
+  V(SetLocal, 0x15, _)         \
+  V(CallFunction, 0x16, _)     \
+  V(CallIndirect, 0x17, _)     \
+  V(CallImport, 0x18, _)       \
+  V(I8Const, 0xcb, _)          \
+  V(LoadGlobal, 0xcc, _)       \
+  V(StoreGlobal, 0xcd, _)
 
 // Load memory expressions.
 #define FOREACH_LOAD_MEM_OPCODE(V) \
@@ -117,8 +118,8 @@
 
 // Load memory expressions.
 #define FOREACH_MISC_MEM_OPCODE(V) \
-  V(MemorySize, 0x3b, i_v)         \
-  V(GrowMemory, 0x39, i_i)
+  V(GrowMemory, 0x39, i_i)         \
+  V(MemorySize, 0x3b, i_v)
 
 // Expressions with signatures.
 #define FOREACH_SIMPLE_OPCODE(V)  \
@@ -258,42 +259,166 @@
   V(F64Log, 0xc7, d_d)                 \
   V(F64Atan2, 0xc8, d_dd)              \
   V(F64Pow, 0xc9, d_dd)                \
-  V(F64Mod, 0xca, d_dd)
+  V(F64Mod, 0xca, d_dd)                \
+  V(I32AsmjsDivS, 0xd0, i_ii)          \
+  V(I32AsmjsDivU, 0xd1, i_ii)          \
+  V(I32AsmjsRemS, 0xd2, i_ii)          \
+  V(I32AsmjsRemU, 0xd3, i_ii)          \
+  V(I32AsmjsLoadMem8S, 0xd4, i_i)      \
+  V(I32AsmjsLoadMem8U, 0xd5, i_i)      \
+  V(I32AsmjsLoadMem16S, 0xd6, i_i)     \
+  V(I32AsmjsLoadMem16U, 0xd7, i_i)     \
+  V(I32AsmjsLoadMem, 0xd8, i_i)        \
+  V(F32AsmjsLoadMem, 0xd9, f_i)        \
+  V(F64AsmjsLoadMem, 0xda, d_i)        \
+  V(I32AsmjsStoreMem8, 0xdb, i_ii)     \
+  V(I32AsmjsStoreMem16, 0xdc, i_ii)    \
+  V(I32AsmjsStoreMem, 0xdd, i_ii)      \
+  V(F32AsmjsStoreMem, 0xde, f_if)      \
+  V(F64AsmjsStoreMem, 0xdf, d_id)      \
+  V(I32AsmjsSConvertF32, 0xe0, i_f)    \
+  V(I32AsmjsUConvertF32, 0xe1, i_f)    \
+  V(I32AsmjsSConvertF64, 0xe2, i_d)    \
+  V(I32AsmjsUConvertF64, 0xe3, i_d)
 
-// TODO(titzer): sketch of asm-js compatibility bytecodes
-/* V(I32AsmjsDivS, 0xd0, i_ii)          \ */
-/* V(I32AsmjsDivU, 0xd1, i_ii)          \ */
-/* V(I32AsmjsRemS, 0xd2, i_ii)          \ */
-/* V(I32AsmjsRemU, 0xd3, i_ii)          \ */
-/* V(I32AsmjsLoad8S, 0xd4, i_i)         \ */
-/* V(I32AsmjsLoad8U, 0xd5, i_i)         \ */
-/* V(I32AsmjsLoad16S, 0xd6, i_i)        \ */
-/* V(I32AsmjsLoad16U, 0xd7, i_i)        \ */
-/* V(I32AsmjsLoad, 0xd8, i_i)           \ */
-/* V(F32AsmjsLoad, 0xd9, f_i)           \ */
-/* V(F64AsmjsLoad, 0xda, d_i)           \ */
-/* V(I32AsmjsStore8, 0xdb, i_i)         \ */
-/* V(I32AsmjsStore16, 0xdc, i_i)        \ */
-/* V(I32AsmjsStore, 0xdd, i_ii)         \ */
-/* V(F32AsmjsStore, 0xde, i_if)         \ */
-/* V(F64AsmjsStore, 0xdf, i_id)         \ */
-/* V(I32SAsmjsConvertF32, 0xe0, i_f)    \ */
-/* V(I32UAsmjsConvertF32, 0xe1, i_f)    \ */
-/* V(I32SAsmjsConvertF64, 0xe2, i_d)    \ */
-/* V(I32SAsmjsConvertF64, 0xe3, i_d) */
+#define FOREACH_SIMD_OPCODE(V)         \
+  V(F32x4Splat, 0xe500, s_f)           \
+  V(F32x4ExtractLane, 0xe501, f_si)    \
+  V(F32x4ReplaceLane, 0xe502, s_sif)   \
+  V(F32x4Abs, 0xe503, s_s)             \
+  V(F32x4Neg, 0xe504, s_s)             \
+  V(F32x4Sqrt, 0xe505, s_s)            \
+  V(F32x4RecipApprox, 0xe506, s_s)     \
+  V(F32x4SqrtApprox, 0xe507, s_s)      \
+  V(F32x4Add, 0xe508, s_ss)            \
+  V(F32x4Sub, 0xe509, s_ss)            \
+  V(F32x4Mul, 0xe50a, s_ss)            \
+  V(F32x4Div, 0xe50b, s_ss)            \
+  V(F32x4Min, 0xe50c, s_ss)            \
+  V(F32x4Max, 0xe50d, s_ss)            \
+  V(F32x4MinNum, 0xe50e, s_ss)         \
+  V(F32x4MaxNum, 0xe50f, s_ss)         \
+  V(F32x4Eq, 0xe510, s_ss)             \
+  V(F32x4Ne, 0xe511, s_ss)             \
+  V(F32x4Lt, 0xe512, s_ss)             \
+  V(F32x4Le, 0xe513, s_ss)             \
+  V(F32x4Gt, 0xe514, s_ss)             \
+  V(F32x4Ge, 0xe515, s_ss)             \
+  V(F32x4Select, 0xe516, s_sss)        \
+  V(F32x4Swizzle, 0xe517, s_s)         \
+  V(F32x4Shuffle, 0xe518, s_ss)        \
+  V(F32x4FromInt32x4, 0xe519, s_s)     \
+  V(F32x4FromUint32x4, 0xe51a, s_s)    \
+  V(I32x4Splat, 0xe51b, s_i)           \
+  V(I32x4ExtractLane, 0xe51c, i_si)    \
+  V(I32x4ReplaceLane, 0xe51d, s_sii)   \
+  V(I32x4Neg, 0xe51e, s_s)             \
+  V(I32x4Add, 0xe51f, s_ss)            \
+  V(I32x4Sub, 0xe520, s_ss)            \
+  V(I32x4Mul, 0xe521, s_ss)            \
+  V(I32x4Min_s, 0xe522, s_ss)          \
+  V(I32x4Max_s, 0xe523, s_ss)          \
+  V(I32x4Shl, 0xe524, s_si)            \
+  V(I32x4Shr_s, 0xe525, s_si)          \
+  V(I32x4Eq, 0xe526, s_ss)             \
+  V(I32x4Ne, 0xe527, s_ss)             \
+  V(I32x4Lt_s, 0xe528, s_ss)           \
+  V(I32x4Le_s, 0xe529, s_ss)           \
+  V(I32x4Gt_s, 0xe52a, s_ss)           \
+  V(I32x4Ge_s, 0xe52b, s_ss)           \
+  V(I32x4Select, 0xe52c, s_sss)        \
+  V(I32x4Swizzle, 0xe52d, s_s)         \
+  V(I32x4Shuffle, 0xe52e, s_ss)        \
+  V(I32x4FromFloat32x4, 0xe52f, s_s)   \
+  V(I32x4Min_u, 0xe530, s_ss)          \
+  V(I32x4Max_u, 0xe531, s_ss)          \
+  V(I32x4Shr_u, 0xe532, s_ss)          \
+  V(I32x4Lt_u, 0xe533, s_ss)           \
+  V(I32x4Le_u, 0xe534, s_ss)           \
+  V(I32x4Gt_u, 0xe535, s_ss)           \
+  V(I32x4Ge_u, 0xe536, s_ss)           \
+  V(Ui32x4FromFloat32x4, 0xe537, s_s)  \
+  V(I16x8Splat, 0xe538, s_i)           \
+  V(I16x8ExtractLane, 0xe539, i_si)    \
+  V(I16x8ReplaceLane, 0xe53a, s_sii)   \
+  V(I16x8Neg, 0xe53b, s_s)             \
+  V(I16x8Add, 0xe53c, s_ss)            \
+  V(I16x8AddSaturate_s, 0xe53d, s_ss)  \
+  V(I16x8Sub, 0xe53e, s_ss)            \
+  V(I16x8SubSaturate_s, 0xe53f, s_ss)  \
+  V(I16x8Mul, 0xe540, s_ss)            \
+  V(I16x8Min_s, 0xe541, s_ss)          \
+  V(I16x8Max_s, 0xe542, s_ss)          \
+  V(I16x8Shl, 0xe543, s_si)            \
+  V(I16x8Shr_s, 0xe544, s_si)          \
+  V(I16x8Eq, 0xe545, s_ss)             \
+  V(I16x8Ne, 0xe546, s_ss)             \
+  V(I16x8Lt_s, 0xe547, s_ss)           \
+  V(I16x8Le_s, 0xe548, s_ss)           \
+  V(I16x8Gt_s, 0xe549, s_ss)           \
+  V(I16x8Ge_s, 0xe54a, s_ss)           \
+  V(I16x8Select, 0xe54b, s_sss)        \
+  V(I16x8Swizzle, 0xe54c, s_s)         \
+  V(I16x8Shuffle, 0xe54d, s_ss)        \
+  V(I16x8AddSaturate_u, 0xe54e, s_ss)  \
+  V(I16x8SubSaturate_u, 0xe54f, s_ss)  \
+  V(I16x8Min_u, 0xe550, s_ss)          \
+  V(I16x8Max_u, 0xe551, s_ss)          \
+  V(I16x8Shr_u, 0xe552, s_si)          \
+  V(I16x8Lt_u, 0xe553, s_ss)           \
+  V(I16x8Le_u, 0xe554, s_ss)           \
+  V(I16x8Gt_u, 0xe555, s_ss)           \
+  V(I16x8Ge_u, 0xe556, s_ss)           \
+  V(I8x16Splat, 0xe557, s_i)           \
+  V(I8x16ExtractLane, 0xe558, i_si)    \
+  V(I8x16ReplaceLane, 0xe559, s_sii)   \
+  V(I8x16Neg, 0xe55a, s_s)             \
+  V(I8x16Add, 0xe55b, s_ss)            \
+  V(I8x16AddSaturate_s, 0xe55c, s_ss)  \
+  V(I8x16Sub, 0xe55d, s_ss)            \
+  V(I8x16SubSaturate_s, 0xe55e, s_ss)  \
+  V(I8x16Mul, 0xe55f, s_ss)            \
+  V(I8x16Min_s, 0xe560, s_ss)          \
+  V(I8x16Max_s, 0xe561, s_ss)          \
+  V(I8x16Shl, 0xe562, s_si)            \
+  V(I8x16Shr_s, 0xe563, s_si)          \
+  V(I8x16Eq, 0xe564, s_ss)             \
+  V(I8x16Neq, 0xe565, s_ss)            \
+  V(I8x16Lt_s, 0xe566, s_ss)           \
+  V(I8x16Le_s, 0xe567, s_ss)           \
+  V(I8x16Gt_s, 0xe568, s_ss)           \
+  V(I8x16Ge_s, 0xe569, s_ss)           \
+  V(I8x16Select, 0xe56a, s_sss)        \
+  V(I8x16Swizzle, 0xe56b, s_s)         \
+  V(I8x16Shuffle, 0xe56c, s_ss)        \
+  V(I8x16AddSaturate_u, 0xe56d, s_ss)  \
+  V(I8x16Sub_saturate_u, 0xe56e, s_ss) \
+  V(I8x16Min_u, 0xe56f, s_ss)          \
+  V(I8x16Max_u, 0xe570, s_ss)          \
+  V(I8x16Shr_u, 0xe571, s_ss)          \
+  V(I8x16Lt_u, 0xe572, s_ss)           \
+  V(I8x16Le_u, 0xe573, s_ss)           \
+  V(I8x16Gt_u, 0xe574, s_ss)           \
+  V(I8x16Ge_u, 0xe575, s_ss)           \
+  V(S128And, 0xe576, s_ss)             \
+  V(S128Ior, 0xe577, s_ss)             \
+  V(S128Xor, 0xe578, s_ss)             \
+  V(S128Not, 0xe579, s_s)
 
 // All opcodes.
-#define FOREACH_OPCODE(V)     \
-  FOREACH_CONTROL_OPCODE(V)   \
-  FOREACH_MISC_OPCODE(V)      \
-  FOREACH_SIMPLE_OPCODE(V)    \
-  FOREACH_STORE_MEM_OPCODE(V) \
-  FOREACH_LOAD_MEM_OPCODE(V)  \
-  FOREACH_MISC_MEM_OPCODE(V)  \
-  FOREACH_ASMJS_COMPAT_OPCODE(V)
+#define FOREACH_OPCODE(V)        \
+  FOREACH_CONTROL_OPCODE(V)      \
+  FOREACH_MISC_OPCODE(V)         \
+  FOREACH_SIMPLE_OPCODE(V)       \
+  FOREACH_STORE_MEM_OPCODE(V)    \
+  FOREACH_LOAD_MEM_OPCODE(V)     \
+  FOREACH_MISC_MEM_OPCODE(V)     \
+  FOREACH_ASMJS_COMPAT_OPCODE(V) \
+  FOREACH_SIMD_OPCODE(V)
 
 // All signatures.
 #define FOREACH_SIGNATURE(V)         \
+  FOREACH_SIMD_SIGNATURE(V)          \
   V(i_ii, kAstI32, kAstI32, kAstI32) \
   V(i_i, kAstI32, kAstI32)           \
   V(i_v, kAstI32)                    \
@@ -322,6 +447,18 @@
   V(f_if, kAstF32, kAstI32, kAstF32) \
   V(l_il, kAstI64, kAstI32, kAstI64)
 
+#define FOREACH_SIMD_SIGNATURE(V)                  \
+  V(s_s, kAstS128, kAstS128)                       \
+  V(s_f, kAstS128, kAstF32)                        \
+  V(f_si, kAstF32, kAstS128, kAstI32)              \
+  V(s_sif, kAstS128, kAstS128, kAstI32, kAstF32)   \
+  V(s_ss, kAstS128, kAstS128, kAstS128)            \
+  V(s_sss, kAstS128, kAstS128, kAstS128, kAstS128) \
+  V(s_i, kAstS128, kAstI32)                        \
+  V(i_si, kAstI32, kAstS128, kAstI32)              \
+  V(s_sii, kAstS128, kAstS128, kAstI32, kAstI32)   \
+  V(s_si, kAstS128, kAstS128, kAstI32)
+
 enum WasmOpcode {
 // Declare expression opcodes.
 #define DECLARE_NAMED_ENUM(name, opcode, sig) kExpr##name = opcode,
@@ -330,25 +467,33 @@
 };
 
 // The reason for a trap.
+#define FOREACH_WASM_TRAPREASON(V) \
+  V(TrapUnreachable)          \
+  V(TrapMemOutOfBounds)       \
+  V(TrapDivByZero)            \
+  V(TrapDivUnrepresentable)   \
+  V(TrapRemByZero)            \
+  V(TrapFloatUnrepresentable) \
+  V(TrapFuncInvalid)          \
+  V(TrapFuncSigMismatch)
+
 enum TrapReason {
-  kTrapUnreachable,
-  kTrapMemOutOfBounds,
-  kTrapDivByZero,
-  kTrapDivUnrepresentable,
-  kTrapRemByZero,
-  kTrapFloatUnrepresentable,
-  kTrapFuncInvalid,
-  kTrapFuncSigMismatch,
+#define DECLARE_ENUM(name) k##name,
+  FOREACH_WASM_TRAPREASON(DECLARE_ENUM)
   kTrapCount
+#undef DECLARE_ENUM
 };
 
 // A collection of opcode-related static methods.
 class WasmOpcodes {
  public:
-  static bool IsSupported(WasmOpcode opcode);
   static const char* OpcodeName(WasmOpcode opcode);
+  static const char* ShortOpcodeName(WasmOpcode opcode);
   static FunctionSig* Signature(WasmOpcode opcode);
 
+  static int TrapReasonToMessageId(TrapReason reason);
+  static const char* TrapReasonMessage(TrapReason reason);
+
   static byte MemSize(MachineType type) {
     return 1 << ElementSizeLog2Of(type.representation());
   }
@@ -365,6 +510,8 @@
         return kLocalF64;
       case kAstStmt:
         return kLocalVoid;
+      case kAstS128:
+        return kLocalS128;
       default:
         UNREACHABLE();
         return kLocalVoid;
@@ -392,6 +539,8 @@
       return kMemF32;
     } else if (type == MachineType::Float64()) {
       return kMemF64;
+    } else if (type == MachineType::Simd128()) {
+      return kMemS128;
     } else {
       UNREACHABLE();
       return kMemI32;
@@ -408,6 +557,8 @@
         return MachineType::Float32();
       case kAstF64:
         return MachineType::Float64();
+      case kAstS128:
+        return MachineType::Simd128();
       case kAstStmt:
         return MachineType::None();
       default:
@@ -437,6 +588,8 @@
       return kAstF32;
     } else if (type == MachineType::Float64()) {
       return kAstF64;
+    } else if (type == MachineType::Simd128()) {
+      return kAstS128;
     } else {
       UNREACHABLE();
       return kAstI32;
@@ -480,6 +633,8 @@
         return 'f';
       case kAstF64:
         return 'd';
+      case kAstS128:
+        return 's';
       case kAstStmt:
         return 'v';
       case kAstEnd:
@@ -500,6 +655,8 @@
         return "f32";
       case kAstF64:
         return "f64";
+      case kAstS128:
+        return "s128";
       case kAstStmt:
         return "<stmt>";
       case kAstEnd:
@@ -508,29 +665,6 @@
         return "<unknown>";
     }
   }
-
-  static const char* TrapReasonName(TrapReason reason) {
-    switch (reason) {
-      case kTrapUnreachable:
-        return "unreachable";
-      case kTrapMemOutOfBounds:
-        return "memory access out of bounds";
-      case kTrapDivByZero:
-        return "divide by zero";
-      case kTrapDivUnrepresentable:
-        return "divide result unrepresentable";
-      case kTrapRemByZero:
-        return "remainder by zero";
-      case kTrapFloatUnrepresentable:
-        return "integer result unrepresentable";
-      case kTrapFuncInvalid:
-        return "invalid function";
-      case kTrapFuncSigMismatch:
-        return "function signature mismatch";
-      default:
-        return "<?>";
-    }
-  }
 };
 }  // namespace wasm
 }  // namespace internal
diff --git a/src/wasm/wasm-result.cc b/src/wasm/wasm-result.cc
index 4fd17ee..30268ac 100644
--- a/src/wasm/wasm-result.cc
+++ b/src/wasm/wasm-result.cc
@@ -6,8 +6,7 @@
 
 #include "src/factory.h"
 #include "src/heap/heap.h"
-#include "src/isolate.h"
-#include "src/objects-inl.h"  // TODO(mstarzinger): Temporary cycle breaker!
+#include "src/isolate-inl.h"
 #include "src/objects.h"
 
 #include "src/base/platform/platform.h"
@@ -28,12 +27,11 @@
   return os;
 }
 
-
 void ErrorThrower::Error(const char* format, ...) {
-  if (error_) return;  // only report the first error.
-  error_ = true;
-  char buffer[256];
+  // Only report the first error.
+  if (error()) return;
 
+  char buffer[256];
   va_list arguments;
   va_start(arguments, format);
   base::OS::VSNPrintF(buffer, 255, format, arguments);
@@ -45,8 +43,13 @@
   }
   str << buffer;
 
-  isolate_->ScheduleThrow(
-      *isolate_->factory()->NewStringFromAsciiChecked(str.str().c_str()));
+  message_ = isolate_->factory()->NewStringFromAsciiChecked(str.str().c_str());
+}
+
+ErrorThrower::~ErrorThrower() {
+  if (error() && !isolate_->has_pending_exception()) {
+    isolate_->ScheduleThrow(*message_);
+  }
 }
 }  // namespace wasm
 }  // namespace internal
diff --git a/src/wasm/wasm-result.h b/src/wasm/wasm-result.h
index 59ab29e..e741de8 100644
--- a/src/wasm/wasm-result.h
+++ b/src/wasm/wasm-result.h
@@ -5,8 +5,10 @@
 #ifndef V8_WASM_RESULT_H_
 #define V8_WASM_RESULT_H_
 
+#include "src/base/compiler-specific.h"
 #include "src/base/smart-pointers.h"
 
+#include "src/handles.h"
 #include "src/globals.h"
 
 namespace v8 {
@@ -37,8 +39,7 @@
 // The overall result of decoding a function or a module.
 template <typename T>
 struct Result {
-  Result()
-      : val(nullptr), error_code(kSuccess), start(nullptr), error_pc(nullptr) {
+  Result() : val(), error_code(kSuccess), start(nullptr), error_pc(nullptr) {
     error_msg.Reset(nullptr);
   }
 
@@ -91,23 +92,30 @@
 class ErrorThrower {
  public:
   ErrorThrower(Isolate* isolate, const char* context)
-      : isolate_(isolate), context_(context), error_(false) {}
+      : isolate_(isolate), context_(context) {}
+  ~ErrorThrower();
 
-  void Error(const char* fmt, ...);
+  PRINTF_FORMAT(2, 3) void Error(const char* fmt, ...);
 
   template <typename T>
   void Failed(const char* error, Result<T>& result) {
     std::ostringstream str;
     str << error << result;
-    return Error(str.str().c_str());
+    return Error("%s", str.str().c_str());
   }
 
-  bool error() const { return error_; }
+  i::Handle<i::String> Reify() {
+    auto result = message_;
+    message_ = i::Handle<i::String>();
+    return result;
+  }
+
+  bool error() const { return !message_.is_null(); }
 
  private:
   Isolate* isolate_;
   const char* context_;
-  bool error_;
+  i::Handle<i::String> message_;
 };
 }  // namespace wasm
 }  // namespace internal
diff --git a/src/x64/assembler-x64-inl.h b/src/x64/assembler-x64-inl.h
index f32f407..60acacd 100644
--- a/src/x64/assembler-x64-inl.h
+++ b/src/x64/assembler-x64-inl.h
@@ -78,7 +78,8 @@
 void Assembler::emit_runtime_entry(Address entry, RelocInfo::Mode rmode) {
   DCHECK(RelocInfo::IsRuntimeEntry(rmode));
   RecordRelocInfo(rmode);
-  emitl(static_cast<uint32_t>(entry - isolate()->code_range()->start()));
+  emitl(static_cast<uint32_t>(
+      entry - isolate()->heap()->memory_allocator()->code_range()->start()));
 }
 
 
@@ -178,12 +179,10 @@
   if (rm_reg.high_bit()) emit(0x41);
 }
 
-
 void Assembler::emit_optional_rex_32(XMMRegister rm_reg) {
   if (rm_reg.high_bit()) emit(0x41);
 }
 
-
 void Assembler::emit_optional_rex_32(const Operand& op) {
   if (op.rex_ != 0) emit(0x40 | op.rex_);
 }
@@ -299,7 +298,8 @@
 
 
 Address Assembler::runtime_entry_at(Address pc) {
-  return Memory::int32_at(pc) + isolate()->code_range()->start();
+  return Memory::int32_at(pc) +
+         isolate()->heap()->memory_allocator()->code_range()->start();
 }
 
 // -----------------------------------------------------------------------------
@@ -326,11 +326,6 @@
   return Assembler::target_address_at(pc_, host_);
 }
 
-Address RelocInfo::wasm_memory_reference() {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  return Memory::Address_at(pc_);
-}
-
 Address RelocInfo::target_address_address() {
   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
                               || rmode_ == EMBEDDED_OBJECT
@@ -368,21 +363,6 @@
   }
 }
 
-void RelocInfo::update_wasm_memory_reference(
-    Address old_base, Address new_base, size_t old_size, size_t new_size,
-    ICacheFlushMode icache_flush_mode) {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  DCHECK(old_base <= wasm_memory_reference() &&
-         wasm_memory_reference() < old_base + old_size);
-  Address updated_reference = new_base + (wasm_memory_reference() - old_base);
-  DCHECK(new_base <= updated_reference &&
-         updated_reference < new_base + new_size);
-  Memory::Address_at(pc_) = updated_reference;
-  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
-    Assembler::FlushICache(isolate_, pc_, sizeof(int64_t));
-  }
-}
-
 Object* RelocInfo::target_object() {
   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
   return Memory::Object_at(pc_);
@@ -538,7 +518,7 @@
   }
 }
 
-
+template <typename ObjectVisitor>
 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index 214b786..3345e30 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -114,6 +114,33 @@
       CpuFeatures::IsSupported(POPCNT), CpuFeatures::IsSupported(ATOM));
 }
 
+// -----------------------------------------------------------------------------
+// Implementation of RelocInfo
+
+Address RelocInfo::wasm_memory_reference() {
+  DCHECK(IsWasmMemoryReference(rmode_));
+  return Memory::Address_at(pc_);
+}
+
+Address RelocInfo::wasm_global_reference() {
+  DCHECK(IsWasmGlobalReference(rmode_));
+  return Memory::Address_at(pc_);
+}
+
+uint32_t RelocInfo::wasm_memory_size_reference() {
+  DCHECK(IsWasmMemorySizeReference(rmode_));
+  return Memory::uint32_at(pc_);
+}
+
+void RelocInfo::unchecked_update_wasm_memory_reference(
+    Address address, ICacheFlushMode flush_mode) {
+  Memory::Address_at(pc_) = address;
+}
+
+void RelocInfo::unchecked_update_wasm_memory_size(uint32_t size,
+                                                  ICacheFlushMode flush_mode) {
+  Memory::uint32_at(pc_) = size;
+}
 
 // -----------------------------------------------------------------------------
 // Implementation of Operand
@@ -293,6 +320,8 @@
       static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer.pos());
   desc->origin = this;
   desc->constant_pool_size = 0;
+  desc->unwinding_info_size = 0;
+  desc->unwinding_info = nullptr;
 }
 
 
@@ -560,17 +589,17 @@
                                         int size) {
   EnsureSpace ensure_space(this);
   emit_rex(dst, size);
-  if (is_int8(src.value_)) {
+  if (is_int8(src.value_) && RelocInfo::IsNone(src.rmode_)) {
     emit(0x83);
     emit_modrm(subcode, dst);
     emit(src.value_);
   } else if (dst.is(rax)) {
     emit(0x05 | (subcode << 3));
-    emitl(src.value_);
+    emit(src);
   } else {
     emit(0x81);
     emit_modrm(subcode, dst);
-    emitl(src.value_);
+    emit(src);
   }
 }
 
@@ -583,11 +612,14 @@
   if (is_int8(src.value_)) {
     emit(0x83);
     emit_operand(subcode, dst);
+    if (!RelocInfo::IsNone(src.rmode_)) {
+      RecordRelocInfo(src.rmode_);
+    }
     emit(src.value_);
   } else {
     emit(0x81);
     emit_operand(subcode, dst);
-    emitl(src.value_);
+    emit(src);
   }
 }
 
@@ -803,7 +835,6 @@
 
 
 void Assembler::call(Label* L) {
-  positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
   // 1110 1000 #32-bit disp.
   emit(0xE8);
@@ -825,7 +856,6 @@
 
 void Assembler::call(Address entry, RelocInfo::Mode rmode) {
   DCHECK(RelocInfo::IsRuntimeEntry(rmode));
-  positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
   // 1110 1000 #32-bit disp.
   emit(0xE8);
@@ -836,7 +866,6 @@
 void Assembler::call(Handle<Code> target,
                      RelocInfo::Mode rmode,
                      TypeFeedbackId ast_id) {
-  positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
   // 1110 1000 #32-bit disp.
   emit(0xE8);
@@ -845,7 +874,6 @@
 
 
 void Assembler::call(Register adr) {
-  positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
   // Opcode: FF /2 r64.
   emit_optional_rex_32(adr);
@@ -855,7 +883,6 @@
 
 
 void Assembler::call(const Operand& op) {
-  positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
   // Opcode: FF /2 m64.
   emit_optional_rex_32(op);
@@ -869,7 +896,6 @@
 // same Code object. Should not be used when generating new code (use labels),
 // but only when patching existing code.
 void Assembler::call(Address target) {
-  positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
   // 1110 1000 #32-bit disp.
   emit(0xE8);
@@ -971,6 +997,40 @@
   emit(imm8.value_);
 }
 
+void Assembler::lock() {
+  EnsureSpace ensure_space(this);
+  emit(0xf0);
+}
+
+void Assembler::cmpxchgb(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  if (!src.is_byte_register()) {
+    // Register is not one of al, bl, cl, dl.  Its encoding needs REX.
+    emit_rex_32(src, dst);
+  } else {
+    emit_optional_rex_32(src, dst);
+  }
+  emit(0x0f);
+  emit(0xb0);
+  emit_operand(src, dst);
+}
+
+void Assembler::cmpxchgw(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(src, dst);
+  emit(0x0f);
+  emit(0xb1);
+  emit_operand(src, dst);
+}
+
+void Assembler::emit_cmpxchg(const Operand& dst, Register src, int size) {
+  EnsureSpace ensure_space(this);
+  emit_rex(src, dst, size);
+  emit(0x0f);
+  emit(0xb1);
+  emit_operand(src, dst);
+}
 
 void Assembler::cpuid() {
   EnsureSpace ensure_space(this);
@@ -1484,7 +1544,6 @@
   movq(dst, static_cast<int64_t>(value), rmode);
 }
 
-
 // Loads the ip-relative location of the src label into the target location
 // (as a 32-bit offset sign extended to 64-bit).
 void Assembler::movl(const Operand& dst, Label* src) {
@@ -1909,6 +1968,25 @@
   emit_modrm(src, dst);
 }
 
+void Assembler::xchgb(Register reg, const Operand& op) {
+  EnsureSpace ensure_space(this);
+  if (!reg.is_byte_register()) {
+    // Register is not one of al, bl, cl, dl.  Its encoding needs REX.
+    emit_rex_32(reg, op);
+  } else {
+    emit_optional_rex_32(reg, op);
+  }
+  emit(0x86);
+  emit_operand(reg, op);
+}
+
+void Assembler::xchgw(Register reg, const Operand& op) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(reg, op);
+  emit(0x87);
+  emit_operand(reg, op);
+}
 
 void Assembler::emit_xchg(Register dst, Register src, int size) {
   EnsureSpace ensure_space(this);
@@ -2032,14 +2110,14 @@
   emit(0x66);
   if (reg.is(rax)) {
     emit(0xA9);
-    emit(mask.value_);
+    emitw(mask.value_);
   } else {
     if (reg.low_bits() == 4) {
       emit_rex_32(reg);
     }
     emit(0xF7);
     emit_modrm(0x0, reg);
-    emit(mask.value_);
+    emitw(mask.value_);
   }
 }
 
@@ -2050,7 +2128,7 @@
   emit_optional_rex_32(rax, op);
   emit(0xF7);
   emit_operand(rax, op);
-  emit(mask.value_);
+  emitw(mask.value_);
 }
 
 void Assembler::testw(const Operand& op, Register reg) {
@@ -2793,6 +2871,18 @@
   emit(imm8);
 }
 
+void Assembler::insertps(XMMRegister dst, XMMRegister src, byte imm8) {
+  DCHECK(CpuFeatures::IsSupported(SSE4_1));
+  DCHECK(is_uint8(imm8));
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x3A);
+  emit(0x21);
+  emit_sse_operand(dst, src);
+  emit(imm8);
+}
 
 void Assembler::movsd(const Operand& dst, XMMRegister src) {
   DCHECK(!IsEnabled(AVX));
@@ -3114,6 +3204,38 @@
   emit(imm8);
 }
 
+void Assembler::cmpps(XMMRegister dst, XMMRegister src, int8_t cmp) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0xC2);
+  emit_sse_operand(dst, src);
+  emit(cmp);
+}
+
+void Assembler::cmpeqps(XMMRegister dst, XMMRegister src) {
+  cmpps(dst, src, 0x0);
+}
+
+void Assembler::cmpltps(XMMRegister dst, XMMRegister src) {
+  cmpps(dst, src, 0x1);
+}
+
+void Assembler::cmpleps(XMMRegister dst, XMMRegister src) {
+  cmpps(dst, src, 0x2);
+}
+
+void Assembler::cmpneqps(XMMRegister dst, XMMRegister src) {
+  cmpps(dst, src, 0x4);
+}
+
+void Assembler::cmpnltps(XMMRegister dst, XMMRegister src) {
+  cmpps(dst, src, 0x5);
+}
+
+void Assembler::cmpnleps(XMMRegister dst, XMMRegister src) {
+  cmpps(dst, src, 0x6);
+}
 
 void Assembler::cvttss2si(Register dst, const Operand& src) {
   DCHECK(!IsEnabled(AVX));
@@ -3631,6 +3753,14 @@
   emit_sse_operand(dst, src);
 }
 
+void Assembler::punpckldq(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x62);
+  emit_sse_operand(dst, src);
+}
 
 void Assembler::punpckhdq(XMMRegister dst, XMMRegister src) {
   EnsureSpace ensure_space(this);
@@ -4095,6 +4225,246 @@
   emit(imm8);
 }
 
+void Assembler::minps(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x5D);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::minps(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x5D);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::maxps(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x5F);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::maxps(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x5F);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::rcpps(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x53);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::rcpps(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x53);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::rsqrtps(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x52);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::rsqrtps(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x52);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::sqrtps(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x51);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::sqrtps(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x51);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::cvtdq2ps(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x5B);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::cvtdq2ps(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x5B);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::movups(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  if (src.low_bits() == 4) {
+    // Try to avoid an unnecessary SIB byte.
+    emit_optional_rex_32(src, dst);
+    emit(0x0F);
+    emit(0x11);
+    emit_sse_operand(src, dst);
+  } else {
+    emit_optional_rex_32(dst, src);
+    emit(0x0F);
+    emit(0x10);
+    emit_sse_operand(dst, src);
+  }
+}
+
+void Assembler::movups(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x10);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::movups(const Operand& dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  emit_optional_rex_32(src, dst);
+  emit(0x0F);
+  emit(0x11);
+  emit_sse_operand(src, dst);
+}
+
+void Assembler::paddd(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0xFE);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::paddd(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0xFE);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::psubd(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0xFA);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::psubd(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0xFA);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::pmulld(XMMRegister dst, XMMRegister src) {
+  DCHECK(IsEnabled(SSE4_1));
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x38);
+  emit(0x40);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::pmulld(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x38);
+  emit(0x40);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::pmuludq(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0xF4);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::pmuludq(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0xF4);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::psrldq(XMMRegister dst, uint8_t shift) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(dst);
+  emit(0x0F);
+  emit(0x73);
+  emit_sse_operand(dst);
+  emit(shift);
+}
+
+void Assembler::cvtps2dq(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x5B);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::cvtps2dq(XMMRegister dst, const Operand& src) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x5B);
+  emit_sse_operand(dst, src);
+}
+
+void Assembler::pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x70);
+  emit_sse_operand(dst, src);
+  emit(shuffle);
+}
 
 void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
   Register ireg = { reg.code() };
@@ -4122,6 +4492,10 @@
   emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
 }
 
+void Assembler::emit_sse_operand(XMMRegister dst) {
+  emit(0xD8 | dst.low_bits());
+}
+
 
 void Assembler::db(uint8_t data) {
   EnsureSpace ensure_space(this);
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index e48f358..a7759c3 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -117,8 +117,6 @@
     Register r = {code};
     return r;
   }
-  const char* ToString();
-  bool IsAllocatable() const;
   bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
   bool is(Register reg) const { return reg_code == reg.reg_code; }
   int code() const {
@@ -183,7 +181,10 @@
   V(xmm14)                  \
   V(xmm15)
 
+#define FLOAT_REGISTERS DOUBLE_REGISTERS
+
 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \
+  V(xmm0)                               \
   V(xmm1)                               \
   V(xmm2)                               \
   V(xmm3)                               \
@@ -197,11 +198,11 @@
   V(xmm11)                              \
   V(xmm12)                              \
   V(xmm13)                              \
-  V(xmm14)                              \
-  V(xmm15)
+  V(xmm14)
 
+static const bool kSimpleFPAliasing = true;
 
-struct DoubleRegister {
+struct XMMRegister {
   enum Code {
 #define REGISTER_CODE(R) kCode_##R,
     DOUBLE_REGISTERS(REGISTER_CODE)
@@ -212,15 +213,13 @@
 
   static const int kMaxNumRegisters = Code::kAfterLast;
 
-  static DoubleRegister from_code(int code) {
-    DoubleRegister result = {code};
+  static XMMRegister from_code(int code) {
+    XMMRegister result = {code};
     return result;
   }
 
-  const char* ToString();
-  bool IsAllocatable() const;
   bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
-  bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
+  bool is(XMMRegister reg) const { return reg_code == reg.reg_code; }
   int code() const {
     DCHECK(is_valid());
     return reg_code;
@@ -238,6 +237,11 @@
   int reg_code;
 };
 
+typedef XMMRegister FloatRegister;
+
+typedef XMMRegister DoubleRegister;
+
+typedef XMMRegister Simd128Register;
 
 #define DECLARE_REGISTER(R) \
   const DoubleRegister R = {DoubleRegister::kCode_##R};
@@ -245,11 +249,6 @@
 #undef DECLARE_REGISTER
 const DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg};
 
-
-typedef DoubleRegister XMMRegister;
-
-typedef DoubleRegister Simd128Register;
-
 enum Condition {
   // any value < 0 is considered no_condition
   no_condition  = -1,
@@ -334,6 +333,8 @@
 class Immediate BASE_EMBEDDED {
  public:
   explicit Immediate(int32_t value) : value_(value) {}
+  explicit Immediate(int32_t value, RelocInfo::Mode rmode)
+      : value_(value), rmode_(rmode) {}
   explicit Immediate(Smi* value) {
     DCHECK(SmiValuesAre31Bits());  // Only available for 31-bit SMI.
     value_ = static_cast<int32_t>(reinterpret_cast<intptr_t>(value));
@@ -341,6 +342,7 @@
 
  private:
   int32_t value_;
+  RelocInfo::Mode rmode_ = RelocInfo::NONE32;
 
   friend class Assembler;
 };
@@ -417,11 +419,11 @@
   friend class Assembler;
 };
 
-
 #define ASSEMBLER_INSTRUCTION_LIST(V) \
   V(add)                              \
   V(and)                              \
   V(cmp)                              \
+  V(cmpxchg)                          \
   V(dec)                              \
   V(idiv)                             \
   V(div)                              \
@@ -441,7 +443,6 @@
   V(xchg)                             \
   V(xor)
 
-
 // Shift instructions on operands/registers with kPointerSize, kInt32Size and
 // kInt64Size.
 #define SHIFT_INSTRUCTION_LIST(V)       \
@@ -784,6 +785,15 @@
   void decb(Register dst);
   void decb(const Operand& dst);
 
+  // Lock prefix.
+  void lock();
+
+  void xchgb(Register reg, const Operand& op);
+  void xchgw(Register reg, const Operand& op);
+
+  void cmpxchgb(const Operand& dst, Register src);
+  void cmpxchgw(const Operand& dst, Register src);
+
   // Sign-extends rax into rdx:rax.
   void cqo();
   // Sign-extends eax into edx:eax.
@@ -1142,19 +1152,55 @@
   void movmskpd(Register dst, XMMRegister src);
 
   void punpckldq(XMMRegister dst, XMMRegister src);
+  void punpckldq(XMMRegister dst, const Operand& src);
   void punpckhdq(XMMRegister dst, XMMRegister src);
 
   // SSE 4.1 instruction
+  void insertps(XMMRegister dst, XMMRegister src, byte imm8);
   void extractps(Register dst, XMMRegister src, byte imm8);
-
   void pextrd(Register dst, XMMRegister src, int8_t imm8);
-
   void pinsrd(XMMRegister dst, Register src, int8_t imm8);
   void pinsrd(XMMRegister dst, const Operand& src, int8_t imm8);
 
   void roundss(XMMRegister dst, XMMRegister src, RoundingMode mode);
   void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);
 
+  void cmpps(XMMRegister dst, XMMRegister src, int8_t cmp);
+  void cmpeqps(XMMRegister dst, XMMRegister src);
+  void cmpltps(XMMRegister dst, XMMRegister src);
+  void cmpleps(XMMRegister dst, XMMRegister src);
+  void cmpneqps(XMMRegister dst, XMMRegister src);
+  void cmpnltps(XMMRegister dst, XMMRegister src);
+  void cmpnleps(XMMRegister dst, XMMRegister src);
+
+  void minps(XMMRegister dst, XMMRegister src);
+  void minps(XMMRegister dst, const Operand& src);
+  void maxps(XMMRegister dst, XMMRegister src);
+  void maxps(XMMRegister dst, const Operand& src);
+  void rcpps(XMMRegister dst, XMMRegister src);
+  void rcpps(XMMRegister dst, const Operand& src);
+  void rsqrtps(XMMRegister dst, XMMRegister src);
+  void rsqrtps(XMMRegister dst, const Operand& src);
+  void sqrtps(XMMRegister dst, XMMRegister src);
+  void sqrtps(XMMRegister dst, const Operand& src);
+  void movups(XMMRegister dst, XMMRegister src);
+  void movups(XMMRegister dst, const Operand& src);
+  void movups(const Operand& dst, XMMRegister src);
+  void paddd(XMMRegister dst, XMMRegister src);
+  void paddd(XMMRegister dst, const Operand& src);
+  void psubd(XMMRegister dst, XMMRegister src);
+  void psubd(XMMRegister dst, const Operand& src);
+  void pmulld(XMMRegister dst, XMMRegister src);
+  void pmulld(XMMRegister dst, const Operand& src);
+  void pmuludq(XMMRegister dst, XMMRegister src);
+  void pmuludq(XMMRegister dst, const Operand& src);
+  void psrldq(XMMRegister dst, uint8_t shift);
+  void pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle);
+  void cvtps2dq(XMMRegister dst, XMMRegister src);
+  void cvtps2dq(XMMRegister dst, const Operand& src);
+  void cvtdq2ps(XMMRegister dst, XMMRegister src);
+  void cvtdq2ps(XMMRegister dst, const Operand& src);
+
   // AVX instruction
   void vfmadd132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
     vfmasd(0x99, dst, src1, src2);
@@ -1689,7 +1735,7 @@
 
   // Record a deoptimization reason that can be used by a log or cpu profiler.
   // Use --trace-deopt to enable.
-  void RecordDeoptReason(const int reason, int raw_position);
+  void RecordDeoptReason(const int reason, int raw_position, int id);
 
   void PatchConstantPoolAccessInstruction(int pc_offset, int offset,
                                           ConstantPoolEntry::Access access,
@@ -1755,7 +1801,12 @@
                                RelocInfo::Mode rmode,
                                TypeFeedbackId ast_id = TypeFeedbackId::None());
   inline void emit_runtime_entry(Address entry, RelocInfo::Mode rmode);
-  void emit(Immediate x) { emitl(x.value_); }
+  void emit(Immediate x) {
+    if (!RelocInfo::IsNone(x.rmode_)) {
+      RecordRelocInfo(x.rmode_);
+    }
+    emitl(x.value_);
+  }
 
   // Emits a REX prefix that encodes a 64-bit operand size and
   // the top bit of both register codes.
@@ -1926,6 +1977,7 @@
   void emit_sse_operand(Register reg, const Operand& adr);
   void emit_sse_operand(XMMRegister dst, Register src);
   void emit_sse_operand(Register dst, XMMRegister src);
+  void emit_sse_operand(XMMRegister dst);
 
   // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
   // AND, OR, XOR, or CMP.  The encodings of these operations are all
@@ -2042,6 +2094,11 @@
     immediate_arithmetic_op(0x7, dst, src, size);
   }
 
+  // Compare {al,ax,eax,rax} with src.  If equal, set ZF and write dst into
+  // src. Otherwise clear ZF and write src into {al,ax,eax,rax}.  This
+  // operation is only atomic if prefixed by the lock instruction.
+  void emit_cmpxchg(const Operand& dst, Register src, int size);
+
   void emit_dec(Register dst, int size);
   void emit_dec(const Operand& dst, int size);
 
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
index 3163783..fb43324 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -15,10 +15,7 @@
 
 #define __ ACCESS_MASM(masm)
 
-
-void Builtins::Generate_Adaptor(MacroAssembler* masm,
-                                CFunctionId id,
-                                BuiltinExtraArguments extra_args) {
+void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
   // ----------- S t a t e -------------
   //  -- rax                 : number of arguments excluding receiver
   //  -- rdi                 : target
@@ -37,20 +34,13 @@
   // ordinary functions).
   __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
 
-  // Insert extra arguments.
-  int num_extra_args = 0;
-  if (extra_args != BuiltinExtraArguments::kNone) {
-    __ PopReturnAddressTo(kScratchRegister);
-    if (extra_args & BuiltinExtraArguments::kTarget) {
-      ++num_extra_args;
-      __ Push(rdi);
-    }
-    if (extra_args & BuiltinExtraArguments::kNewTarget) {
-      ++num_extra_args;
-      __ Push(rdx);
-    }
-    __ PushReturnAddressFrom(kScratchRegister);
-  }
+  // Unconditionally insert the target and new target as extra arguments. They
+  // will be used by stack frame iterators when constructing the stack trace.
+  const int num_extra_args = 2;
+  __ PopReturnAddressTo(kScratchRegister);
+  __ Push(rdi);
+  __ Push(rdx);
+  __ PushReturnAddressFrom(kScratchRegister);
 
   // JumpToExternalReference expects rax to contain the number of arguments
   // including the receiver and the extra arguments.
@@ -185,16 +175,9 @@
     __ j(greater_equal, &loop);
 
     // Call the function.
-    if (is_api_function) {
-      __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
-      Handle<Code> code =
-          masm->isolate()->builtins()->HandleApiCallConstruct();
-      __ Call(code, RelocInfo::CODE_TARGET);
-    } else {
-      ParameterCount actual(rax);
-      __ InvokeFunction(rdi, rdx, actual, CALL_FUNCTION,
-                        CheckDebugStepCallWrapper());
-    }
+    ParameterCount actual(rax);
+    __ InvokeFunction(rdi, rdx, actual, CALL_FUNCTION,
+                      CheckDebugStepCallWrapper());
 
     // Store offset of return address for deoptimizer.
     if (create_implicit_receiver && !is_api_function) {
@@ -464,6 +447,191 @@
   Generate_JSEntryTrampolineHelper(masm, true);
 }
 
+// static
+void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- rax    : the value to pass to the generator
+  //  -- rbx    : the JSGeneratorObject to resume
+  //  -- rdx    : the resume mode (tagged)
+  //  -- rsp[0] : return address
+  // -----------------------------------
+  __ AssertGeneratorObject(rbx);
+
+  // Store input value into generator object.
+  __ movp(FieldOperand(rbx, JSGeneratorObject::kInputOrDebugPosOffset), rax);
+  __ RecordWriteField(rbx, JSGeneratorObject::kInputOrDebugPosOffset, rax, rcx,
+                      kDontSaveFPRegs);
+
+  // Store resume mode into generator object.
+  __ movp(FieldOperand(rbx, JSGeneratorObject::kResumeModeOffset), rdx);
+
+  // Load suspended function and context.
+  __ movp(rsi, FieldOperand(rbx, JSGeneratorObject::kContextOffset));
+  __ movp(rdi, FieldOperand(rbx, JSGeneratorObject::kFunctionOffset));
+
+  // Flood function if we are stepping.
+  Label prepare_step_in_if_stepping, prepare_step_in_suspended_generator;
+  Label stepping_prepared;
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(masm->isolate());
+  Operand last_step_action_operand = masm->ExternalOperand(last_step_action);
+  STATIC_ASSERT(StepFrame > StepIn);
+  __ cmpb(last_step_action_operand, Immediate(StepIn));
+  __ j(greater_equal, &prepare_step_in_if_stepping);
+
+  // Flood function if we need to continue stepping in the suspended generator.
+  ExternalReference debug_suspended_generator =
+      ExternalReference::debug_suspended_generator_address(masm->isolate());
+  Operand debug_suspended_generator_operand =
+      masm->ExternalOperand(debug_suspended_generator);
+  __ cmpp(rbx, debug_suspended_generator_operand);
+  __ j(equal, &prepare_step_in_suspended_generator);
+  __ bind(&stepping_prepared);
+
+  // Pop return address.
+  __ PopReturnAddressTo(rax);
+
+  // Push receiver.
+  __ Push(FieldOperand(rbx, JSGeneratorObject::kReceiverOffset));
+
+  // ----------- S t a t e -------------
+  //  -- rax    : return address
+  //  -- rbx    : the JSGeneratorObject to resume
+  //  -- rdx    : the resume mode (tagged)
+  //  -- rdi    : generator function
+  //  -- rsi    : generator context
+  //  -- rsp[0] : generator receiver
+  // -----------------------------------
+
+  // Push holes for arguments to generator function. Since the parser forced
+  // context allocation for any variables in generators, the actual argument
+  // values have already been copied into the context and these dummy values
+  // will never be used.
+  __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
+  __ LoadSharedFunctionInfoSpecialField(
+      rcx, rcx, SharedFunctionInfo::kFormalParameterCountOffset);
+  {
+    Label done_loop, loop;
+    __ bind(&loop);
+    __ subl(rcx, Immediate(1));
+    __ j(carry, &done_loop, Label::kNear);
+    __ PushRoot(Heap::kTheHoleValueRootIndex);
+    __ jmp(&loop);
+    __ bind(&done_loop);
+  }
+
+  // Dispatch on the kind of generator object.
+  Label old_generator;
+  __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
+  __ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kFunctionDataOffset));
+  __ CmpObjectType(rcx, BYTECODE_ARRAY_TYPE, rcx);
+  __ j(not_equal, &old_generator);
+
+  // New-style (ignition/turbofan) generator object.
+  {
+    __ PushReturnAddressFrom(rax);
+    __ movp(rax, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
+    __ LoadSharedFunctionInfoSpecialField(
+        rax, rax, SharedFunctionInfo::kFormalParameterCountOffset);
+    // We abuse new.target both to indicate that this is a resume call and to
+    // pass in the generator object.  In ordinary calls, new.target is always
+    // undefined because generator functions are non-constructable.
+    __ movp(rdx, rbx);
+    __ jmp(FieldOperand(rdi, JSFunction::kCodeEntryOffset));
+  }
+
+  // Old-style (full-codegen) generator object.
+  __ bind(&old_generator);
+  {
+    // Enter a new JavaScript frame, and initialize its slots as they were when
+    // the generator was suspended.
+    FrameScope scope(masm, StackFrame::MANUAL);
+    __ PushReturnAddressFrom(rax);  // Return address.
+    __ Push(rbp);                   // Caller's frame pointer.
+    __ Move(rbp, rsp);
+    __ Push(rsi);  // Callee's context.
+    __ Push(rdi);  // Callee's JS Function.
+
+    // Restore the operand stack.
+    __ movp(rsi, FieldOperand(rbx, JSGeneratorObject::kOperandStackOffset));
+    __ SmiToInteger32(rax, FieldOperand(rsi, FixedArray::kLengthOffset));
+    {
+      Label done_loop, loop;
+      __ Set(rcx, 0);
+      __ bind(&loop);
+      __ cmpl(rcx, rax);
+      __ j(equal, &done_loop, Label::kNear);
+      __ Push(
+          FieldOperand(rsi, rcx, times_pointer_size, FixedArray::kHeaderSize));
+      __ addl(rcx, Immediate(1));
+      __ jmp(&loop);
+      __ bind(&done_loop);
+    }
+
+    // Reset operand stack so we don't leak.
+    __ LoadRoot(FieldOperand(rbx, JSGeneratorObject::kOperandStackOffset),
+                Heap::kEmptyFixedArrayRootIndex);
+
+    // Restore context.
+    __ movp(rsi, FieldOperand(rbx, JSGeneratorObject::kContextOffset));
+
+    // Resume the generator function at the continuation.
+    __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
+    __ movp(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset));
+    __ SmiToInteger64(
+        rcx, FieldOperand(rbx, JSGeneratorObject::kContinuationOffset));
+    __ leap(rdx, FieldOperand(rdx, rcx, times_1, Code::kHeaderSize));
+    __ Move(FieldOperand(rbx, JSGeneratorObject::kContinuationOffset),
+            Smi::FromInt(JSGeneratorObject::kGeneratorExecuting));
+    __ movp(rax, rbx);  // Continuation expects generator object in rax.
+    __ jmp(rdx);
+  }
+
+  __ bind(&prepare_step_in_if_stepping);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ Push(rbx);
+    __ Push(rdx);
+    __ Push(rdi);
+    __ CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
+    __ Pop(rdx);
+    __ Pop(rbx);
+    __ movp(rdi, FieldOperand(rbx, JSGeneratorObject::kFunctionOffset));
+  }
+  __ jmp(&stepping_prepared);
+
+  __ bind(&prepare_step_in_suspended_generator);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ Push(rbx);
+    __ Push(rdx);
+    __ CallRuntime(Runtime::kDebugPrepareStepInSuspendedGenerator);
+    __ Pop(rdx);
+    __ Pop(rbx);
+    __ movp(rdi, FieldOperand(rbx, JSGeneratorObject::kFunctionOffset));
+  }
+  __ jmp(&stepping_prepared);
+}
+
+static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch1,
+                                  Register scratch2) {
+  Register args_count = scratch1;
+  Register return_pc = scratch2;
+
+  // Get the arguments + receiver count.
+  __ movp(args_count,
+          Operand(rbp, InterpreterFrameConstants::kBytecodeArrayFromFp));
+  __ movl(args_count,
+          FieldOperand(args_count, BytecodeArray::kParameterSizeOffset));
+
+  // Leave the frame (also dropping the register file).
+  __ leave();
+
+  // Drop receiver + arguments.
+  __ PopReturnAddressTo(return_pc);
+  __ addp(rsp, args_count);
+  __ PushReturnAddressFrom(return_pc);
+}
 
 // Generate code for entering a JS function with the interpreter.
 // On entry to the function the receiver and arguments have been pushed on the
@@ -480,6 +648,8 @@
 // The function builds an interpreter frame.  See InterpreterFrameConstants in
 // frames.h for its layout.
 void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
+  ProfileEntryHookStub::MaybeCallEntryHook(masm);
+
   // Open a frame scope to indicate that there is a frame on the stack.  The
   // MANUAL indicates that the scope shouldn't actually generate code to set up
   // the frame (that is done below).
@@ -490,10 +660,9 @@
   __ Push(rdi);  // Callee's JS function.
   __ Push(rdx);  // Callee's new target.
 
-  // Get the bytecode array from the function object and load the pointer to the
-  // first entry into edi (InterpreterBytecodeRegister).
+  // Get the bytecode array from the function object (or from the DebugInfo if
+  // it is present) and load it into kInterpreterBytecodeArrayRegister.
   __ movp(rax, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
-
   Label load_debug_bytecode_array, bytecode_array_loaded;
   DCHECK_EQ(Smi::FromInt(0), DebugInfo::uninitialized());
   __ cmpp(FieldOperand(rax, SharedFunctionInfo::kDebugInfoOffset),
@@ -503,18 +672,26 @@
           FieldOperand(rax, SharedFunctionInfo::kFunctionDataOffset));
   __ bind(&bytecode_array_loaded);
 
+  // Check function data field is actually a BytecodeArray object.
+  Label bytecode_array_not_present;
+  __ CompareRoot(kInterpreterBytecodeArrayRegister,
+                 Heap::kUndefinedValueRootIndex);
+  __ j(equal, &bytecode_array_not_present);
   if (FLAG_debug_code) {
-    // Check function data field is actually a BytecodeArray object.
     __ AssertNotSmi(kInterpreterBytecodeArrayRegister);
     __ CmpObjectType(kInterpreterBytecodeArrayRegister, BYTECODE_ARRAY_TYPE,
                      rax);
     __ Assert(equal, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry);
   }
 
-  // Push bytecode array.
+  // Load initial bytecode offset.
+  __ movp(kInterpreterBytecodeOffsetRegister,
+          Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
+
+  // Push bytecode array and Smi tagged bytecode offset.
   __ Push(kInterpreterBytecodeArrayRegister);
-  // Push zero for bytecode array offset.
-  __ Push(Immediate(0));
+  __ Integer32ToSmi(rcx, kInterpreterBytecodeOffsetRegister);
+  __ Push(rcx);
 
   // Allocate the local and temporary register file on the stack.
   {
@@ -545,19 +722,8 @@
     __ j(greater_equal, &loop_header, Label::kNear);
   }
 
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's prologue:
-  //  - Call ProfileEntryHookStub when isolate has a function_entry_hook.
-  //  - Code aging of the BytecodeArray object.
-
-  // Load accumulator, register file, bytecode offset, dispatch table into
-  // registers.
+  // Load accumulator and dispatch table into registers.
   __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
-  __ movp(kInterpreterRegisterFileRegister, rbp);
-  __ addp(kInterpreterRegisterFileRegister,
-          Immediate(InterpreterFrameConstants::kRegisterFilePointerFromFp));
-  __ movp(kInterpreterBytecodeOffsetRegister,
-          Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
   __ Move(
       kInterpreterDispatchTableRegister,
       ExternalReference::interpreter_dispatch_table_address(masm->isolate()));
@@ -567,13 +733,12 @@
                           kInterpreterBytecodeOffsetRegister, times_1, 0));
   __ movp(rbx, Operand(kInterpreterDispatchTableRegister, rbx,
                        times_pointer_size, 0));
-  // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
-  // and header removal.
-  __ addp(rbx, Immediate(Code::kHeaderSize - kHeapObjectTag));
   __ call(rbx);
+  masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
 
-  // Even though the first bytecode handler was called, we will never return.
-  __ Abort(kUnexpectedReturnFromBytecodeHandler);
+  // The return value is in rax.
+  LeaveInterpreterFrame(masm, rbx, rcx);
+  __ ret(0);
 
   // Load debug copy of the bytecode array.
   __ bind(&load_debug_bytecode_array);
@@ -582,31 +747,45 @@
   __ movp(kInterpreterBytecodeArrayRegister,
           FieldOperand(debug_info, DebugInfo::kAbstractCodeIndex));
   __ jmp(&bytecode_array_loaded);
+
+  // If the bytecode array is no longer present, then the underlying function
+  // has been switched to a different kind of code and we heal the closure by
+  // switching the code entry field over to the new code object as well.
+  __ bind(&bytecode_array_not_present);
+  __ leave();  // Leave the frame so we can tail call.
+  __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
+  __ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kCodeOffset));
+  __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize));
+  __ movp(FieldOperand(rdi, JSFunction::kCodeEntryOffset), rcx);
+  __ RecordWriteCodeEntryField(rdi, rcx, r15);
+  __ jmp(rcx);
 }
 
+void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) {
+  // Save the function and context for call to CompileBaseline.
+  __ movp(rdi, Operand(rbp, StandardFrameConstants::kFunctionOffset));
+  __ movp(kContextRegister,
+          Operand(rbp, StandardFrameConstants::kContextOffset));
 
-void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's EmitReturnSequence.
-  //  - Supporting FLAG_trace for Runtime::TraceExit.
-  //  - Support profiler (specifically decrementing profiling_counter
-  //    appropriately and calling out to HandleInterrupts if necessary).
+  // Leave the frame before recompiling for baseline so that we don't count as
+  // an activation on the stack.
+  LeaveInterpreterFrame(masm, rbx, rcx);
 
-  // The return value is in accumulator, which is already in rax.
+  {
+    FrameScope frame_scope(masm, StackFrame::INTERNAL);
+    // Push return value.
+    __ Push(rax);
 
-  // Leave the frame (also dropping the register file).
-  __ leave();
+    // Push function as argument and compile for baseline.
+    __ Push(rdi);
+    __ CallRuntime(Runtime::kCompileBaseline);
 
-  // Drop receiver + arguments and return.
-  __ movl(rbx, FieldOperand(kInterpreterBytecodeArrayRegister,
-                            BytecodeArray::kParameterSizeOffset));
-  __ PopReturnAddressTo(rcx);
-  __ addp(rsp, rbx);
-  __ PushReturnAddressFrom(rcx);
+    // Restore return value.
+    __ Pop(rax);
+  }
   __ ret(0);
 }
 
-
 static void Generate_InterpreterPushArgs(MacroAssembler* masm,
                                          bool push_receiver) {
   // ----------- S t a t e -------------
@@ -637,7 +816,6 @@
   __ j(greater, &loop_header, Label::kNear);
 }
 
-
 // static
 void Builtins::Generate_InterpreterPushArgsAndCallImpl(
     MacroAssembler* masm, TailCallMode tail_call_mode) {
@@ -661,7 +839,6 @@
           RelocInfo::CODE_TARGET);
 }
 
-
 // static
 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
   // ----------- S t a t e -------------
@@ -689,26 +866,25 @@
   __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
 }
 
+void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
+  // Set the return address to the correct point in the interpreter entry
+  // trampoline.
+  Smi* interpreter_entry_return_pc_offset(
+      masm->isolate()->heap()->interpreter_entry_return_pc_offset());
+  DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
+  __ Move(rbx, masm->isolate()->builtins()->InterpreterEntryTrampoline());
+  __ addp(rbx, Immediate(interpreter_entry_return_pc_offset->value() +
+                         Code::kHeaderSize - kHeapObjectTag));
+  __ Push(rbx);
 
-static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
-  // Initialize register file register and dispatch table register.
-  __ movp(kInterpreterRegisterFileRegister, rbp);
-  __ addp(kInterpreterRegisterFileRegister,
-          Immediate(InterpreterFrameConstants::kRegisterFilePointerFromFp));
+  // Initialize dispatch table register.
   __ Move(
       kInterpreterDispatchTableRegister,
       ExternalReference::interpreter_dispatch_table_address(masm->isolate()));
 
-  // Get the context from the frame.
-  __ movp(kContextRegister,
-          Operand(kInterpreterRegisterFileRegister,
-                  InterpreterFrameConstants::kContextFromRegisterPointer));
-
   // Get the bytecode array pointer from the frame.
-  __ movp(
-      kInterpreterBytecodeArrayRegister,
-      Operand(kInterpreterRegisterFileRegister,
-              InterpreterFrameConstants::kBytecodeArrayFromRegisterPointer));
+  __ movp(kInterpreterBytecodeArrayRegister,
+          Operand(rbp, InterpreterFrameConstants::kBytecodeArrayFromFp));
 
   if (FLAG_debug_code) {
     // Check function data field is actually a BytecodeArray object.
@@ -719,10 +895,8 @@
   }
 
   // Get the target bytecode offset from the frame.
-  __ movp(
-      kInterpreterBytecodeOffsetRegister,
-      Operand(kInterpreterRegisterFileRegister,
-              InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
+  __ movp(kInterpreterBytecodeOffsetRegister,
+          Operand(rbp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
   __ SmiToInteger32(kInterpreterBytecodeOffsetRegister,
                     kInterpreterBytecodeOffsetRegister);
 
@@ -731,66 +905,161 @@
                           kInterpreterBytecodeOffsetRegister, times_1, 0));
   __ movp(rbx, Operand(kInterpreterDispatchTableRegister, rbx,
                        times_pointer_size, 0));
-  __ addp(rbx, Immediate(Code::kHeaderSize - kHeapObjectTag));
   __ jmp(rbx);
 }
 
-
-static void Generate_InterpreterNotifyDeoptimizedHelper(
-    MacroAssembler* masm, Deoptimizer::BailoutType type) {
-  // Enter an internal frame.
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Pass the deoptimization type to the runtime system.
-    __ Push(Smi::FromInt(static_cast<int>(type)));
-    __ CallRuntime(Runtime::kNotifyDeoptimized);
-    // Tear down internal frame.
-  }
-
-  // Drop state (we don't use these for interpreter deopts) and and pop the
-  // accumulator value into the accumulator register and push PC at top
-  // of stack (to simulate initial call to bytecode handler in interpreter entry
-  // trampoline).
-  __ Pop(rbx);
-  __ Drop(1);
-  __ Pop(kInterpreterAccumulatorRegister);
-  __ Push(rbx);
-
-  // Enter the bytecode dispatch.
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-
-void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
-}
-
-
-void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
-}
-
-
-void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
-}
-
-void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
-  // Set the address of the interpreter entry trampoline as a return address.
-  // This simulates the initial call to bytecode handlers in interpreter entry
-  // trampoline. The return will never actually be taken, but our stack walker
-  // uses this address to determine whether a frame is interpreted.
-  __ Push(masm->isolate()->builtins()->InterpreterEntryTrampoline());
-
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-
 void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- rax : argument count (preserved for callee)
+  //  -- rdx : new target (preserved for callee)
+  //  -- rdi : target function (preserved for callee)
+  // -----------------------------------
+  // First lookup code, maybe we don't need to compile!
+  Label gotta_call_runtime;
+  Label maybe_call_runtime;
+  Label try_shared;
+  Label loop_top, loop_bottom;
+
+  Register closure = rdi;
+  Register map = r8;
+  Register index = r9;
+  __ movp(map, FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ movp(map, FieldOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset));
+  __ SmiToInteger32(index, FieldOperand(map, FixedArray::kLengthOffset));
+  __ cmpl(index, Immediate(2));
+  __ j(less, &gotta_call_runtime);
+
+  // Find literals.
+  // r14 : native context
+  // r9  : length / index
+  // r8  : optimized code map
+  // rdx : new target
+  // rdi : closure
+  Register native_context = r14;
+  __ movp(native_context, NativeContextOperand());
+
+  __ bind(&loop_top);
+  // Native context match?
+  Register temp = r11;
+  __ movp(temp, FieldOperand(map, index, times_pointer_size,
+                             SharedFunctionInfo::kOffsetToPreviousContext));
+  __ movp(temp, FieldOperand(temp, WeakCell::kValueOffset));
+  __ cmpp(temp, native_context);
+  __ j(not_equal, &loop_bottom);
+  // OSR id set to none?
+  __ movp(temp, FieldOperand(map, index, times_pointer_size,
+                             SharedFunctionInfo::kOffsetToPreviousOsrAstId));
+  __ SmiToInteger32(temp, temp);
+  const int bailout_id = BailoutId::None().ToInt();
+  __ cmpl(temp, Immediate(bailout_id));
+  __ j(not_equal, &loop_bottom);
+
+  // Literals available?
+  Label got_literals, maybe_cleared_weakcell;
+  __ movp(temp, FieldOperand(map, index, times_pointer_size,
+                             SharedFunctionInfo::kOffsetToPreviousLiterals));
+  // temp contains either a WeakCell pointing to the literals array or the
+  // literals array directly.
+  STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
+  __ movp(r15, FieldOperand(temp, WeakCell::kValueOffset));
+  __ JumpIfSmi(r15, &maybe_cleared_weakcell);
+  // r15 is a pointer, therefore temp is a WeakCell pointing to a literals
+  // array.
+  __ movp(temp, FieldOperand(temp, WeakCell::kValueOffset));
+  __ jmp(&got_literals);
+
+  // r15 is a smi. If it's 0, then we are looking at a cleared WeakCell
+  // around the literals array, and we should visit the runtime. If it's > 0,
+  // then temp already contains the literals array.
+  __ bind(&maybe_cleared_weakcell);
+  __ cmpp(r15, Immediate(0));
+  __ j(equal, &gotta_call_runtime);
+
+  // Save the literals in the closure.
+  __ bind(&got_literals);
+  __ movp(FieldOperand(closure, JSFunction::kLiteralsOffset), temp);
+  __ movp(r15, index);
+  __ RecordWriteField(closure, JSFunction::kLiteralsOffset, temp, r15,
+                      kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+
+  // Code available?
+  Register entry = rcx;
+  __ movp(entry, FieldOperand(map, index, times_pointer_size,
+                              SharedFunctionInfo::kOffsetToPreviousCachedCode));
+  __ movp(entry, FieldOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &maybe_call_runtime);
+
+  // Found literals and code. Get them into the closure and return.
+  __ leap(entry, FieldOperand(entry, Code::kHeaderSize));
+
+  Label install_optimized_code_and_tailcall;
+  __ bind(&install_optimized_code_and_tailcall);
+  __ movp(FieldOperand(closure, JSFunction::kCodeEntryOffset), entry);
+  __ RecordWriteCodeEntryField(closure, entry, r15);
+
+  // Link the closure into the optimized function list.
+  // rcx : code entry (entry)
+  // r14 : native context
+  // rdx : new target
+  // rdi : closure
+  __ movp(rbx,
+          ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
+  __ movp(FieldOperand(closure, JSFunction::kNextFunctionLinkOffset), rbx);
+  __ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, rbx, r15,
+                      kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+  const int function_list_offset =
+      Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
+  __ movp(ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST),
+          closure);
+  // Save closure before the write barrier.
+  __ movp(rbx, closure);
+  __ RecordWriteContextSlot(native_context, function_list_offset, closure, r15,
+                            kDontSaveFPRegs);
+  __ movp(closure, rbx);
+  __ jmp(entry);
+
+  __ bind(&loop_bottom);
+  __ subl(index, Immediate(SharedFunctionInfo::kEntryLength));
+  __ cmpl(index, Immediate(1));
+  __ j(greater, &loop_top);
+
+  // We found neither literals nor code.
+  __ jmp(&gotta_call_runtime);
+
+  __ bind(&maybe_call_runtime);
+
+  // Last possibility. Check the context free optimized code map entry.
+  __ movp(entry, FieldOperand(map, FixedArray::kHeaderSize +
+                                       SharedFunctionInfo::kSharedCodeIndex));
+  __ movp(entry, FieldOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &try_shared);
+
+  // Store code entry in the closure.
+  __ leap(entry, FieldOperand(entry, Code::kHeaderSize));
+  __ jmp(&install_optimized_code_and_tailcall);
+
+  __ bind(&try_shared);
+  // Is the full code valid?
+  __ movp(entry, FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ movp(entry, FieldOperand(entry, SharedFunctionInfo::kCodeOffset));
+  __ movl(rbx, FieldOperand(entry, Code::kFlagsOffset));
+  __ andl(rbx, Immediate(Code::KindField::kMask));
+  __ shrl(rbx, Immediate(Code::KindField::kShift));
+  __ cmpl(rbx, Immediate(Code::BUILTIN));
+  __ j(equal, &gotta_call_runtime);
+  // Yes, install the full code.
+  __ leap(entry, FieldOperand(entry, Code::kHeaderSize));
+  __ movp(FieldOperand(closure, JSFunction::kCodeEntryOffset), entry);
+  __ RecordWriteCodeEntryField(closure, entry, r15);
+  __ jmp(entry);
+
+  __ bind(&gotta_call_runtime);
   GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
 }
 
+void Builtins::Generate_CompileBaseline(MacroAssembler* masm) {
+  GenerateTailCallToReturnedCode(masm, Runtime::kCompileBaseline);
+}
 
 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
   GenerateTailCallToReturnedCode(masm,
@@ -929,13 +1198,16 @@
 
   // Switch on the state.
   Label not_no_registers, not_tos_rax;
-  __ cmpp(kScratchRegister, Immediate(FullCodeGenerator::NO_REGISTERS));
+  __ cmpp(kScratchRegister,
+          Immediate(static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS)));
   __ j(not_equal, &not_no_registers, Label::kNear);
   __ ret(1 * kPointerSize);  // Remove state.
 
   __ bind(&not_no_registers);
+  DCHECK_EQ(kInterpreterAccumulatorRegister.code(), rax.code());
   __ movp(rax, Operand(rsp, kPCOnStackSize + kPointerSize));
-  __ cmpp(kScratchRegister, Immediate(FullCodeGenerator::TOS_REG));
+  __ cmpp(kScratchRegister,
+          Immediate(static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER)));
   __ j(not_equal, &not_tos_rax, Label::kNear);
   __ ret(2 * kPointerSize);  // Remove state, rax.
 
@@ -963,6 +1235,9 @@
 void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
                                                int field_index) {
   // ----------- S t a t e -------------
+  //  -- rax    : number of arguments
+  //  -- rdi    : function
+  //  -- rsi    : context
   //  -- rsp[0] : return address
   //  -- rsp[8] : receiver
   // -----------------------------------
@@ -1004,35 +1279,16 @@
   __ bind(&receiver_not_date);
   {
     FrameScope scope(masm, StackFrame::MANUAL);
-    __ EnterFrame(StackFrame::INTERNAL);
+    __ Push(rbp);
+    __ Move(rbp, rsp);
+    __ Push(rsi);
+    __ Push(rdi);
+    __ Push(Immediate(0));
     __ CallRuntime(Runtime::kThrowNotDateError);
   }
 }
 
 // static
-void Builtins::Generate_FunctionHasInstance(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- rax     : argc
-  //  -- rsp[0]  : return address
-  //  -- rsp[8]  : first argument (left-hand side)
-  //  -- rsp[16] : receiver (right-hand side)
-  // -----------------------------------
-
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-    __ movp(InstanceOfDescriptor::LeftRegister(),
-            Operand(rbp, 2 * kPointerSize));  // Load left-hand side.
-    __ movp(InstanceOfDescriptor::RightRegister(),
-            Operand(rbp, 3 * kPointerSize));  // Load right-hand side.
-    InstanceOfStub stub(masm->isolate(), true);
-    __ CallStub(&stub);
-  }
-
-  // Pop the argument and the receiver.
-  __ ret(2 * kPointerSize);
-}
-
-// static
 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
   // ----------- S t a t e -------------
   //  -- rax     : argc
@@ -1378,6 +1634,8 @@
 void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
   // ----------- S t a t e -------------
   //  -- rax                 : number of arguments
+  //  -- rdi                 : function
+  //  -- rsi                 : context
   //  -- rsp[0]              : return address
   //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
   //  -- rsp[(argc + 1) * 8] : receiver
@@ -1405,27 +1663,32 @@
     __ movp(rbx, Operand(rsp, rcx, times_pointer_size, 0));
 
     // Load the double value of the parameter into xmm1, maybe converting the
-    // parameter to a number first using the ToNumberStub if necessary.
+    // parameter to a number first using the ToNumber builtin if necessary.
     Label convert, convert_smi, convert_number, done_convert;
     __ bind(&convert);
     __ JumpIfSmi(rbx, &convert_smi);
     __ JumpIfRoot(FieldOperand(rbx, HeapObject::kMapOffset),
                   Heap::kHeapNumberMapRootIndex, &convert_number);
     {
-      // Parameter is not a Number, use the ToNumberStub to convert it.
-      FrameScope scope(masm, StackFrame::INTERNAL);
+      // Parameter is not a Number, use the ToNumber builtin to convert it.
+      FrameScope scope(masm, StackFrame::MANUAL);
+      __ Push(rbp);
+      __ Move(rbp, rsp);
+      __ Push(rsi);
+      __ Push(rdi);
       __ Integer32ToSmi(rax, rax);
       __ Integer32ToSmi(rcx, rcx);
       __ Push(rax);
       __ Push(rcx);
       __ Push(rdx);
       __ movp(rax, rbx);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
       __ movp(rbx, rax);
       __ Pop(rdx);
       __ Pop(rcx);
       __ Pop(rax);
+      __ Pop(rdi);
+      __ Pop(rsi);
       {
         // Restore the double accumulator value (xmm0).
         Label restore_smi, done_restore;
@@ -1438,6 +1701,7 @@
       }
       __ SmiToInteger32(rcx, rcx);
       __ SmiToInteger32(rax, rax);
+      __ leave();
     }
     __ jmp(&convert);
     __ bind(&convert_number);
@@ -1511,8 +1775,7 @@
   }
 
   // 2a. Convert the first argument to a number.
-  ToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
+  __ Jump(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
 
   // 2b. No arguments, return +0 (already in rax).
   __ bind(&no_arguments);
@@ -1563,8 +1826,7 @@
       __ Push(rdx);
       __ Push(rdi);
       __ Move(rax, rbx);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
       __ Move(rbx, rax);
       __ Pop(rdi);
       __ Pop(rdx);
@@ -1789,6 +2051,109 @@
   __ PushReturnAddressFrom(rcx);
 }
 
+// static
+void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- rdx    : requested object size (untagged)
+  //  -- rsp[0] : return address
+  // -----------------------------------
+  __ Integer32ToSmi(rdx, rdx);
+  __ PopReturnAddressTo(rcx);
+  __ Push(rdx);
+  __ PushReturnAddressFrom(rcx);
+  __ Move(rsi, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInNewSpace);
+}
+
+// static
+void Builtins::Generate_AllocateInOldSpace(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- rdx    : requested object size (untagged)
+  //  -- rsp[0] : return address
+  // -----------------------------------
+  __ Integer32ToSmi(rdx, rdx);
+  __ PopReturnAddressTo(rcx);
+  __ Push(rdx);
+  __ Push(Smi::FromInt(AllocateTargetSpace::encode(OLD_SPACE)));
+  __ PushReturnAddressFrom(rcx);
+  __ Move(rsi, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInTargetSpace);
+}
+
+void Builtins::Generate_StringToNumber(MacroAssembler* masm) {
+  // The StringToNumber stub takes one argument in rax.
+  __ AssertString(rax);
+
+  // Check if string has a cached array index.
+  Label runtime;
+  __ testl(FieldOperand(rax, String::kHashFieldOffset),
+           Immediate(String::kContainsCachedArrayIndexMask));
+  __ j(not_zero, &runtime, Label::kNear);
+  __ movl(rax, FieldOperand(rax, String::kHashFieldOffset));
+  __ IndexFromHash(rax, rax);
+  __ Ret();
+
+  __ bind(&runtime);
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ Push(rax);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kStringToNumber);
+  }
+  __ Ret();
+}
+
+// static
+void Builtins::Generate_ToNumber(MacroAssembler* masm) {
+  // The ToNumber stub takes one argument in rax.
+  Label not_smi;
+  __ JumpIfNotSmi(rax, &not_smi, Label::kNear);
+  __ Ret();
+  __ bind(&not_smi);
+
+  Label not_heap_number;
+  __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
+                 Heap::kHeapNumberMapRootIndex);
+  __ j(not_equal, &not_heap_number, Label::kNear);
+  __ Ret();
+  __ bind(&not_heap_number);
+
+  __ Jump(masm->isolate()->builtins()->NonNumberToNumber(),
+          RelocInfo::CODE_TARGET);
+}
+
+// static
+void Builtins::Generate_NonNumberToNumber(MacroAssembler* masm) {
+  // The NonNumberToNumber stub takes one argument in rax.
+  __ AssertNotNumber(rax);
+
+  Label not_string;
+  __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdi);
+  // rax: object
+  // rdi: object map
+  __ j(above_equal, &not_string, Label::kNear);
+  __ Jump(masm->isolate()->builtins()->StringToNumber(),
+          RelocInfo::CODE_TARGET);
+  __ bind(&not_string);
+
+  Label not_oddball;
+  __ CmpInstanceType(rdi, ODDBALL_TYPE);
+  __ j(not_equal, &not_oddball, Label::kNear);
+  __ movp(rax, FieldOperand(rax, Oddball::kToNumberOffset));
+  __ Ret();
+  __ bind(&not_oddball);
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ Push(rax);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kToNumber);
+  }
+  __ Ret();
+}
 
 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
   // ----------- S t a t e -------------
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index e737801..b89438f 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -20,60 +20,16 @@
 namespace v8 {
 namespace internal {
 
+#define __ ACCESS_MASM(masm)
 
-static void InitializeArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  Address deopt_handler = Runtime::FunctionForId(
-      Runtime::kArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(rax, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-
-static void InitializeInternalArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  Address deopt_handler = Runtime::FunctionForId(
-      Runtime::kInternalArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(rax, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-
-void ArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 0);
-}
-
-
-void ArraySingleArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 1);
-}
-
-
-void ArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-void InternalArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0);
+void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
+  __ popq(rcx);
+  __ movq(MemOperand(rsp, rax, times_8, 0), rdi);
+  __ pushq(rdi);
+  __ pushq(rbx);
+  __ pushq(rcx);
+  __ addq(rax, Immediate(3));
+  __ TailCallRuntime(Runtime::kNewArray);
 }
 
 void FastArrayPushStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
@@ -81,21 +37,12 @@
   descriptor->Initialize(rax, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-void InternalArraySingleArgumentConstructorStub::InitializeDescriptor(
+void FastFunctionBindStub::InitializeDescriptor(
     CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1);
+  Address deopt_handler = Runtime::FunctionForId(Runtime::kFunctionBind)->entry;
+  descriptor->Initialize(rax, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-
-void InternalArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-#define __ ACCESS_MASM(masm)
-
-
 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm,
                                                ExternalReference miss) {
   // Update the static counter each time a new code stub is generated.
@@ -185,7 +132,7 @@
 
     bool stash_exponent_copy = !input_reg.is(rsp);
     __ movl(scratch1, mantissa_operand);
-    __ Movsd(xmm0, mantissa_operand);
+    __ Movsd(kScratchDoubleReg, mantissa_operand);
     __ movl(rcx, exponent_operand);
     if (stash_exponent_copy) __ pushq(rcx);
 
@@ -205,7 +152,7 @@
     __ jmp(&check_negative);
 
     __ bind(&process_64_bits);
-    __ Cvttsd2siq(result_reg, xmm0);
+    __ Cvttsd2siq(result_reg, kScratchDoubleReg);
     __ jmp(&done, Label::kNear);
 
     // If the double was negative, negate the integer result.
@@ -558,7 +505,6 @@
                                           &miss,  // When not a string.
                                           &miss,  // When not a number.
                                           &miss,  // When index out of range.
-                                          STRING_INDEX_IS_ARRAY_INDEX,
                                           RECEIVER_IS_STRING);
   char_at_generator.GenerateFast(masm);
   __ ret(0);
@@ -1354,8 +1300,8 @@
   // rdx : slot in feedback vector (Smi)
   // rdi : the function to call
   Isolate* isolate = masm->isolate();
-  Label initialize, done, miss, megamorphic, not_array_function,
-      done_no_smi_convert;
+  Label initialize, done, miss, megamorphic, not_array_function;
+  Label done_initialize_count, done_increment_count;
 
   // Load the cache state into r11.
   __ SmiToInteger32(rdx, rdx);
@@ -1369,7 +1315,7 @@
   // type-feedback-vector.h).
   Label check_allocation_site;
   __ cmpp(rdi, FieldOperand(r11, WeakCell::kValueOffset));
-  __ j(equal, &done, Label::kFar);
+  __ j(equal, &done_increment_count, Label::kFar);
   __ CompareRoot(r11, Heap::kmegamorphic_symbolRootIndex);
   __ j(equal, &done, Label::kFar);
   __ CompareRoot(FieldOperand(r11, HeapObject::kMapOffset),
@@ -1393,7 +1339,7 @@
   __ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r11);
   __ cmpp(rdi, r11);
   __ j(not_equal, &megamorphic);
-  __ jmp(&done);
+  __ jmp(&done_increment_count);
 
   __ bind(&miss);
 
@@ -1419,17 +1365,29 @@
 
   CreateAllocationSiteStub create_stub(isolate);
   CallStubInRecordCallTarget(masm, &create_stub);
-  __ jmp(&done_no_smi_convert);
+  __ jmp(&done_initialize_count);
 
   __ bind(&not_array_function);
   CreateWeakCellStub weak_cell_stub(isolate);
   CallStubInRecordCallTarget(masm, &weak_cell_stub);
-  __ jmp(&done_no_smi_convert);
+
+  __ bind(&done_initialize_count);
+  // Initialize the call counter.
+  __ SmiToInteger32(rdx, rdx);
+  __ Move(FieldOperand(rbx, rdx, times_pointer_size,
+                       FixedArray::kHeaderSize + kPointerSize),
+          Smi::FromInt(1));
+  __ jmp(&done);
+
+  __ bind(&done_increment_count);
+
+  // Increment the call count for monomorphic function calls.
+  __ SmiAddConstant(FieldOperand(rbx, rdx, times_pointer_size,
+                                 FixedArray::kHeaderSize + kPointerSize),
+                    Smi::FromInt(1));
 
   __ bind(&done);
   __ Integer32ToSmi(rdx, rdx);
-
-  __ bind(&done_no_smi_convert);
 }
 
 
@@ -1490,7 +1448,7 @@
   // Increment the call count for monomorphic function calls.
   __ SmiAddConstant(FieldOperand(rbx, rdx, times_pointer_size,
                                  FixedArray::kHeaderSize + kPointerSize),
-                    Smi::FromInt(CallICNexus::kCallCountIncrement));
+                    Smi::FromInt(1));
 
   __ movp(rbx, rcx);
   __ movp(rdx, rdi);
@@ -1540,7 +1498,7 @@
   // Increment the call count for monomorphic function calls.
   __ SmiAddConstant(FieldOperand(rbx, rdx, times_pointer_size,
                                  FixedArray::kHeaderSize + kPointerSize),
-                    Smi::FromInt(CallICNexus::kCallCountIncrement));
+                    Smi::FromInt(1));
 
   __ bind(&call_function);
   __ Set(rax, argc);
@@ -1610,7 +1568,7 @@
   // Initialize the call counter.
   __ Move(FieldOperand(rbx, rdx, times_pointer_size,
                        FixedArray::kHeaderSize + kPointerSize),
-          Smi::FromInt(CallICNexus::kCallCountIncrement));
+          Smi::FromInt(1));
 
   // Store the function. Use a stub since we need a frame for allocation.
   // rbx - vector
@@ -1667,7 +1625,7 @@
   StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
   StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
   // It is important that the store buffer overflow stubs are generated first.
-  ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
+  CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate);
   CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
   CreateWeakCellStub::GenerateAheadOfTime(isolate);
   BinaryOpICStub::GenerateAheadOfTime(isolate);
@@ -2013,125 +1971,6 @@
 }
 
 
-void InstanceOfStub::Generate(MacroAssembler* masm) {
-  Register const object = rdx;              // Object (lhs).
-  Register const function = rax;            // Function (rhs).
-  Register const object_map = rcx;          // Map of {object}.
-  Register const function_map = r8;         // Map of {function}.
-  Register const function_prototype = rdi;  // Prototype of {function}.
-
-  DCHECK(object.is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(function.is(InstanceOfDescriptor::RightRegister()));
-
-  // Check if {object} is a smi.
-  Label object_is_smi;
-  __ JumpIfSmi(object, &object_is_smi, Label::kNear);
-
-  // Lookup the {function} and the {object} map in the global instanceof cache.
-  // Note: This is safe because we clear the global instanceof cache whenever
-  // we change the prototype of any object.
-  Label fast_case, slow_case;
-  __ movp(object_map, FieldOperand(object, HeapObject::kMapOffset));
-  __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
-  __ j(not_equal, &fast_case, Label::kNear);
-  __ CompareRoot(object_map, Heap::kInstanceofCacheMapRootIndex);
-  __ j(not_equal, &fast_case, Label::kNear);
-  __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
-  __ ret(0);
-
-  // If {object} is a smi we can safely return false if {function} is a JS
-  // function, otherwise we have to miss to the runtime and throw an exception.
-  __ bind(&object_is_smi);
-  __ JumpIfSmi(function, &slow_case);
-  __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map);
-  __ j(not_equal, &slow_case);
-  __ LoadRoot(rax, Heap::kFalseValueRootIndex);
-  __ ret(0);
-
-  // Fast-case: The {function} must be a valid JSFunction.
-  __ bind(&fast_case);
-  __ JumpIfSmi(function, &slow_case);
-  __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map);
-  __ j(not_equal, &slow_case);
-
-  // Go to the runtime if the function is not a constructor.
-  __ testb(FieldOperand(function_map, Map::kBitFieldOffset),
-           Immediate(1 << Map::kIsConstructor));
-  __ j(zero, &slow_case);
-
-  // Ensure that {function} has an instance prototype.
-  __ testb(FieldOperand(function_map, Map::kBitFieldOffset),
-           Immediate(1 << Map::kHasNonInstancePrototype));
-  __ j(not_zero, &slow_case);
-
-  // Get the "prototype" (or initial map) of the {function}.
-  __ movp(function_prototype,
-          FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
-  __ AssertNotSmi(function_prototype);
-
-  // Resolve the prototype if the {function} has an initial map.  Afterwards the
-  // {function_prototype} will be either the JSReceiver prototype object or the
-  // hole value, which means that no instances of the {function} were created so
-  // far and hence we should return false.
-  Label function_prototype_valid;
-  Register const function_prototype_map = kScratchRegister;
-  __ CmpObjectType(function_prototype, MAP_TYPE, function_prototype_map);
-  __ j(not_equal, &function_prototype_valid, Label::kNear);
-  __ movp(function_prototype,
-          FieldOperand(function_prototype, Map::kPrototypeOffset));
-  __ bind(&function_prototype_valid);
-  __ AssertNotSmi(function_prototype);
-
-  // Update the global instanceof cache with the current {object} map and
-  // {function}.  The cached answer will be set when it is known below.
-  __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
-  __ StoreRoot(object_map, Heap::kInstanceofCacheMapRootIndex);
-
-  // Loop through the prototype chain looking for the {function} prototype.
-  // Assume true, and change to false if not found.
-  Label done, loop, fast_runtime_fallback;
-  __ LoadRoot(rax, Heap::kTrueValueRootIndex);
-  __ bind(&loop);
-
-  __ testb(FieldOperand(object_map, Map::kBitFieldOffset),
-           Immediate(1 << Map::kIsAccessCheckNeeded));
-  __ j(not_zero, &fast_runtime_fallback, Label::kNear);
-  __ CmpInstanceType(object_map, JS_PROXY_TYPE);
-  __ j(equal, &fast_runtime_fallback, Label::kNear);
-
-  __ movp(object, FieldOperand(object_map, Map::kPrototypeOffset));
-  __ cmpp(object, function_prototype);
-  __ j(equal, &done, Label::kNear);
-  __ CompareRoot(object, Heap::kNullValueRootIndex);
-  __ movp(object_map, FieldOperand(object, HeapObject::kMapOffset));
-  __ j(not_equal, &loop);
-  __ LoadRoot(rax, Heap::kFalseValueRootIndex);
-  __ bind(&done);
-  __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
-  __ ret(0);
-
-  // Found Proxy or access check needed: Call the runtime.
-  __ bind(&fast_runtime_fallback);
-  __ PopReturnAddressTo(kScratchRegister);
-  __ Push(object);
-  __ Push(function_prototype);
-  __ PushReturnAddressFrom(kScratchRegister);
-  // Invalidate the instanceof cache.
-  __ Move(rax, Smi::FromInt(0));
-  __ StoreRoot(rax, Heap::kInstanceofCacheFunctionRootIndex);
-  __ TailCallRuntime(Runtime::kHasInPrototypeChain);
-
-  // Slow-case: Call the %InstanceOf runtime function.
-  __ bind(&slow_case);
-  __ PopReturnAddressTo(kScratchRegister);
-  __ Push(object);
-  __ Push(function);
-  __ PushReturnAddressFrom(kScratchRegister);
-  __ TailCallRuntime(is_es6_instanceof() ? Runtime::kOrdinaryHasInstance
-                                         : Runtime::kInstanceOf);
-}
-
-
 // -------------------------------------------------------------------------
 // StringCharCodeAtGenerator
 
@@ -2186,13 +2025,7 @@
   }
   __ Push(object_);
   __ Push(index_);  // Consumed by runtime conversion function.
-  if (index_flags_ == STRING_INDEX_IS_NUMBER) {
-    __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero);
-  } else {
-    DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
-    // NumberToSmi discards numbers that are not exact integers.
-    __ CallRuntime(Runtime::kNumberToSmi);
-  }
+  __ CallRuntime(Runtime::kNumberToSmi);
   if (!index_.is(rax)) {
     // Save the conversion result before the pop instructions below
     // have a chance to overwrite it.
@@ -2513,78 +2346,12 @@
   // rcx: sub string length (smi)
   // rdx: from index (smi)
   StringCharAtGenerator generator(rax, rdx, rcx, rax, &runtime, &runtime,
-                                  &runtime, STRING_INDEX_IS_NUMBER,
-                                  RECEIVER_IS_STRING);
+                                  &runtime, RECEIVER_IS_STRING);
   generator.GenerateFast(masm);
   __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize);
   generator.SkipSlow(masm, &runtime);
 }
 
-
-void ToNumberStub::Generate(MacroAssembler* masm) {
-  // The ToNumber stub takes one argument in rax.
-  Label not_smi;
-  __ JumpIfNotSmi(rax, &not_smi, Label::kNear);
-  __ Ret();
-  __ bind(&not_smi);
-
-  Label not_heap_number;
-  __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
-                 Heap::kHeapNumberMapRootIndex);
-  __ j(not_equal, &not_heap_number, Label::kNear);
-  __ Ret();
-  __ bind(&not_heap_number);
-
-  NonNumberToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
-}
-
-void NonNumberToNumberStub::Generate(MacroAssembler* masm) {
-  // The NonNumberToNumber stub takes one argument in rax.
-  __ AssertNotNumber(rax);
-
-  Label not_string;
-  __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdi);
-  // rax: object
-  // rdi: object map
-  __ j(above_equal, &not_string, Label::kNear);
-  StringToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
-  __ bind(&not_string);
-
-  Label not_oddball;
-  __ CmpInstanceType(rdi, ODDBALL_TYPE);
-  __ j(not_equal, &not_oddball, Label::kNear);
-  __ movp(rax, FieldOperand(rax, Oddball::kToNumberOffset));
-  __ Ret();
-  __ bind(&not_oddball);
-
-  __ PopReturnAddressTo(rcx);     // Pop return address.
-  __ Push(rax);                   // Push argument.
-  __ PushReturnAddressFrom(rcx);  // Push return address.
-  __ TailCallRuntime(Runtime::kToNumber);
-}
-
-void StringToNumberStub::Generate(MacroAssembler* masm) {
-  // The StringToNumber stub takes one argument in rax.
-  __ AssertString(rax);
-
-  // Check if string has a cached array index.
-  Label runtime;
-  __ testl(FieldOperand(rax, String::kHashFieldOffset),
-           Immediate(String::kContainsCachedArrayIndexMask));
-  __ j(not_zero, &runtime, Label::kNear);
-  __ movl(rax, FieldOperand(rax, String::kHashFieldOffset));
-  __ IndexFromHash(rax, rax);
-  __ Ret();
-
-  __ bind(&runtime);
-  __ PopReturnAddressTo(rcx);     // Pop return address.
-  __ Push(rax);                   // Push argument.
-  __ PushReturnAddressFrom(rcx);  // Push return address.
-  __ TailCallRuntime(Runtime::kStringToNumber);
-}
-
 void ToStringStub::Generate(MacroAssembler* masm) {
   // The ToString stub takes one argument in rax.
   Label is_number;
@@ -2619,7 +2386,6 @@
   __ TailCallRuntime(Runtime::kToString);
 }
 
-
 void ToNameStub::Generate(MacroAssembler* masm) {
   // The ToName stub takes one argument in rax.
   Label is_number;
@@ -2802,7 +2568,7 @@
   // Load rcx with the allocation site.  We stick an undefined dummy value here
   // and replace it with the real allocation site later when we instantiate this
   // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate().
-  __ Move(rcx, handle(isolate()->heap()->undefined_value()));
+  __ Move(rcx, isolate()->factory()->undefined_value());
 
   // Make sure that we actually patched the allocation site.
   if (FLAG_debug_code) {
@@ -3612,14 +3378,14 @@
 
 void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  LoadICStub stub(isolate(), state());
+  LoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate(), state());
+  KeyedLoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -3735,8 +3501,8 @@
   __ bind(&not_array);
   __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
   __ j(not_equal, &miss);
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
   masm->isolate()->stub_cache()->GenerateProbe(
       masm, Code::LOAD_IC, code_flags, receiver, name, feedback, no_reg);
 
@@ -3877,8 +3643,8 @@
   __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
   __ j(not_equal, &miss);
 
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, code_flags,
                                                receiver, key, feedback, no_reg);
 
@@ -4100,9 +3866,6 @@
   // rdi - constructor?
   // rsp[0] - return address
   // rsp[8] - last argument
-  Handle<Object> undefined_sentinel(
-      masm->isolate()->heap()->undefined_value(),
-      masm->isolate());
 
   Label normal_sequence;
   if (mode == DONT_OVERRIDE) {
@@ -4193,19 +3956,14 @@
   }
 }
 
-
-void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
+void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
   ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
       isolate);
   ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
       isolate);
-  ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
-      isolate);
-}
+  ArrayNArgumentsConstructorStub stub(isolate);
+  stub.GetCode();
 
-
-void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
-    Isolate* isolate) {
   ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS };
   for (int i = 0; i < 2; i++) {
     // For internal arrays we only need a few things
@@ -4213,8 +3971,6 @@
     stubh1.GetCode();
     InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]);
     stubh2.GetCode();
-    InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]);
-    stubh3.GetCode();
   }
 }
 
@@ -4234,13 +3990,15 @@
     CreateArrayDispatchOneArgument(masm, mode);
 
     __ bind(&not_one_case);
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else if (argument_count() == NONE) {
     CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
   } else if (argument_count() == ONE) {
     CreateArrayDispatchOneArgument(masm, mode);
   } else if (argument_count() == MORE_THAN_ONE) {
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else {
     UNREACHABLE();
   }
@@ -4359,7 +4117,7 @@
   __ TailCallStub(&stub1);
 
   __ bind(&not_one_case);
-  InternalArrayNArgumentsConstructorStub stubN(isolate(), kind);
+  ArrayNArgumentsConstructorStub stubN(isolate());
   __ TailCallStub(&stubN);
 }
 
@@ -4449,15 +4207,15 @@
   __ bind(&done_allocate);
 
   // Initialize the JSObject fields.
-  __ movp(Operand(rax, JSObject::kMapOffset), rcx);
+  __ movp(FieldOperand(rax, JSObject::kMapOffset), rcx);
   __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex);
-  __ movp(Operand(rax, JSObject::kPropertiesOffset), rbx);
-  __ movp(Operand(rax, JSObject::kElementsOffset), rbx);
+  __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx);
+  __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx);
   STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize);
-  __ leap(rbx, Operand(rax, JSObject::kHeaderSize));
+  __ leap(rbx, FieldOperand(rax, JSObject::kHeaderSize));
 
   // ----------- S t a t e -------------
-  //  -- rax    : result (untagged)
+  //  -- rax    : result (tagged)
   //  -- rbx    : result fields (untagged)
   //  -- rdi    : result end (untagged)
   //  -- rcx    : initial map
@@ -4475,10 +4233,6 @@
   {
     // Initialize all in-object fields with undefined.
     __ InitializeFieldsWithFiller(rbx, rdi, r11);
-
-    // Add the object tag to make the JSObject real.
-    STATIC_ASSERT(kHeapObjectTag == 1);
-    __ incp(rax);
     __ Ret();
   }
   __ bind(&slack_tracking);
@@ -4498,10 +4252,6 @@
     __ LoadRoot(r11, Heap::kOnePointerFillerMapRootIndex);
     __ InitializeFieldsWithFiller(rdx, rdi, r11);
 
-    // Add the object tag to make the JSObject real.
-    STATIC_ASSERT(kHeapObjectTag == 1);
-    __ incp(rax);
-
     // Check if we can finalize the instance size.
     Label finalize;
     STATIC_ASSERT(Map::kSlackTrackingCounterEnd == 1);
@@ -4532,10 +4282,10 @@
     __ CallRuntime(Runtime::kAllocateInNewSpace);
     __ Pop(rcx);
   }
-  STATIC_ASSERT(kHeapObjectTag == 1);
-  __ decp(rax);
   __ movzxbl(rbx, FieldOperand(rcx, Map::kInstanceSizeOffset));
   __ leap(rdi, Operand(rax, rbx, times_pointer_size, 0));
+  STATIC_ASSERT(kHeapObjectTag == 1);
+  __ decp(rdi);  // Remove the tag from the end address.
   __ jmp(&done_allocate);
 
   // Fall back to %NewObject.
@@ -4557,19 +4307,19 @@
   // -----------------------------------
   __ AssertFunction(rdi);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make rdx point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ movp(rdx, rbp);
-    __ jmp(&loop_entry, Label::kNear);
-    __ bind(&loop);
+  // Make rdx point to the JavaScript frame.
+  __ movp(rdx, rbp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ movp(rdx, Operand(rdx, StandardFrameConstants::kCallerFPOffset));
-    __ bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ cmpp(rdi, Operand(rdx, StandardFrameConstants::kFunctionOffset));
-    __ j(not_equal, &loop);
+    __ j(equal, &ok);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
   }
 
   // Check if we have rest parameters (only possible if we have an
@@ -4601,7 +4351,7 @@
 
     // Allocate an empty rest parameter array.
     Label allocate, done_allocate;
-    __ Allocate(JSArray::kSize, rax, rdx, rcx, &allocate, TAG_OBJECT);
+    __ Allocate(JSArray::kSize, rax, rdx, rcx, &allocate, NO_ALLOCATION_FLAGS);
     __ bind(&done_allocate);
 
     // Setup the rest parameter array in rax.
@@ -4632,6 +4382,7 @@
                              1 * kPointerSize));
 
     // ----------- S t a t e -------------
+    //  -- rdi    : function
     //  -- rsi    : context
     //  -- rax    : number of rest parameters
     //  -- rbx    : pointer to first rest parameters
@@ -4642,7 +4393,7 @@
     Label allocate, done_allocate;
     __ leal(rcx, Operand(rax, times_pointer_size,
                          JSArray::kSize + FixedArray::kHeaderSize));
-    __ Allocate(rcx, rdx, rdi, no_reg, &allocate, TAG_OBJECT);
+    __ Allocate(rcx, rdx, r8, no_reg, &allocate, NO_ALLOCATION_FLAGS);
     __ bind(&done_allocate);
 
     // Compute the arguments.length in rdi.
@@ -4680,8 +4431,11 @@
     STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
     __ Ret();
 
-    // Fall back to %AllocateInNewSpace.
+    // Fall back to %AllocateInNewSpace (if not too big).
+    Label too_big_for_new_space;
     __ bind(&allocate);
+    __ cmpl(rcx, Immediate(Page::kMaxRegularHeapObjectSize));
+    __ j(greater, &too_big_for_new_space);
     {
       FrameScope scope(masm, StackFrame::INTERNAL);
       __ Integer32ToSmi(rax, rax);
@@ -4696,6 +4450,13 @@
       __ SmiToInteger32(rax, rax);
     }
     __ jmp(&done_allocate);
+
+    // Fall back to %NewRestParameter.
+    __ bind(&too_big_for_new_space);
+    __ PopReturnAddressTo(kScratchRegister);
+    __ Push(rdi);
+    __ PushReturnAddressFrom(kScratchRegister);
+    __ TailCallRuntime(Runtime::kNewRestParameter);
   }
 }
 
@@ -4709,11 +4470,26 @@
   // -----------------------------------
   __ AssertFunction(rdi);
 
+  // Make r9 point to the JavaScript frame.
+  __ movp(r9, rbp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
+    __ movp(r9, Operand(r9, StandardFrameConstants::kCallerFPOffset));
+  }
+  if (FLAG_debug_code) {
+    Label ok;
+    __ cmpp(rdi, Operand(r9, StandardFrameConstants::kFunctionOffset));
+    __ j(equal, &ok);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
+  }
+
   // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub.
   __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
   __ LoadSharedFunctionInfoSpecialField(
       rcx, rcx, SharedFunctionInfo::kFormalParameterCountOffset);
-  __ leap(rdx, Operand(rbp, rcx, times_pointer_size,
+  __ leap(rdx, Operand(r9, rcx, times_pointer_size,
                        StandardFrameConstants::kCallerSPOffset));
   __ Integer32ToSmi(rcx, rcx);
 
@@ -4721,6 +4497,7 @@
   // rdx : parameters pointer
   // rdi : function
   // rsp[0] : return address
+  // r9  : JavaScript frame pointer.
   // Registers used over the whole function:
   //  rbx: the mapped parameter count (untagged)
   //  rax: the allocated object (tagged).
@@ -4731,7 +4508,7 @@
 
   // Check if the calling frame is an arguments adaptor frame.
   Label adaptor_frame, try_allocate, runtime;
-  __ movp(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
+  __ movp(rax, Operand(r9, StandardFrameConstants::kCallerFPOffset));
   __ movp(r8, Operand(rax, CommonFrameConstants::kContextOrFrameTypeOffset));
   __ Cmp(r8, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
   __ j(equal, &adaptor_frame);
@@ -4774,7 +4551,7 @@
   __ addp(r8, Immediate(JSSloppyArgumentsObject::kSize));
 
   // Do the allocation of all three objects in one go.
-  __ Allocate(r8, rax, r9, no_reg, &runtime, TAG_OBJECT);
+  __ Allocate(r8, rax, r9, no_reg, &runtime, NO_ALLOCATION_FLAGS);
 
   // rax = address of new object(s) (tagged)
   // r11 = argument count (untagged)
@@ -4927,19 +4704,19 @@
   // -----------------------------------
   __ AssertFunction(rdi);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make rdx point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ movp(rdx, rbp);
-    __ jmp(&loop_entry, Label::kNear);
-    __ bind(&loop);
+  // Make rdx point to the JavaScript frame.
+  __ movp(rdx, rbp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ movp(rdx, Operand(rdx, StandardFrameConstants::kCallerFPOffset));
-    __ bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ cmpp(rdi, Operand(rdx, StandardFrameConstants::kFunctionOffset));
-    __ j(not_equal, &loop);
+    __ j(equal, &ok);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
   }
 
   // Check if we have an arguments adaptor frame below the function frame.
@@ -4970,6 +4747,7 @@
   // ----------- S t a t e -------------
   //  -- rax    : number of arguments
   //  -- rbx    : pointer to the first argument
+  //  -- rdi    : function
   //  -- rsi    : context
   //  -- rsp[0] : return address
   // -----------------------------------
@@ -4978,7 +4756,7 @@
   Label allocate, done_allocate;
   __ leal(rcx, Operand(rax, times_pointer_size, JSStrictArgumentsObject::kSize +
                                                     FixedArray::kHeaderSize));
-  __ Allocate(rcx, rdx, rdi, no_reg, &allocate, TAG_OBJECT);
+  __ Allocate(rcx, rdx, r8, no_reg, &allocate, NO_ALLOCATION_FLAGS);
   __ bind(&done_allocate);
 
   // Compute the arguments.length in rdi.
@@ -5016,8 +4794,11 @@
   STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
   __ Ret();
 
-  // Fall back to %AllocateInNewSpace.
+  // Fall back to %AllocateInNewSpace (if not too big).
+  Label too_big_for_new_space;
   __ bind(&allocate);
+  __ cmpl(rcx, Immediate(Page::kMaxRegularHeapObjectSize));
+  __ j(greater, &too_big_for_new_space);
   {
     FrameScope scope(masm, StackFrame::INTERNAL);
     __ Integer32ToSmi(rax, rax);
@@ -5032,37 +4813,13 @@
     __ SmiToInteger32(rax, rax);
   }
   __ jmp(&done_allocate);
-}
 
-
-void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
-  Register context_reg = rsi;
-  Register slot_reg = rbx;
-  Register result_reg = rax;
-  Label slow_case;
-
-  // Go up context chain to the script context.
-  for (int i = 0; i < depth(); ++i) {
-    __ movp(rdi, ContextOperand(context_reg, Context::PREVIOUS_INDEX));
-    context_reg = rdi;
-  }
-
-  // Load the PropertyCell value at the specified slot.
-  __ movp(result_reg, ContextOperand(context_reg, slot_reg));
-  __ movp(result_reg, FieldOperand(result_reg, PropertyCell::kValueOffset));
-
-  // Check that value is not the_hole.
-  __ CompareRoot(result_reg, Heap::kTheHoleValueRootIndex);
-  __ j(equal, &slow_case, Label::kNear);
-  __ Ret();
-
-  // Fallback to the runtime.
-  __ bind(&slow_case);
-  __ Integer32ToSmi(slot_reg, slot_reg);
+  // Fall back to %NewStrictArguments.
+  __ bind(&too_big_for_new_space);
   __ PopReturnAddressTo(kScratchRegister);
-  __ Push(slot_reg);
-  __ Push(kScratchRegister);
-  __ TailCallRuntime(Runtime::kLoadGlobalViaContext);
+  __ Push(rdi);
+  __ PushReturnAddressFrom(kScratchRegister);
+  __ TailCallRuntime(Runtime::kNewStrictArguments);
 }
 
 
@@ -5404,10 +5161,14 @@
   STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
   STATIC_ASSERT(FCA::kIsolateIndex == 1);
   STATIC_ASSERT(FCA::kHolderIndex == 0);
-  STATIC_ASSERT(FCA::kArgsLength == 7);
+  STATIC_ASSERT(FCA::kNewTargetIndex == 7);
+  STATIC_ASSERT(FCA::kArgsLength == 8);
 
   __ PopReturnAddressTo(return_address);
 
+  // new target
+  __ PushRoot(Heap::kUndefinedValueRootIndex);
+
   // context save
   __ Push(context);
 
@@ -5441,7 +5202,7 @@
 
   // Allocate the v8::Arguments structure in the arguments' space since
   // it's not controlled by GC.
-  const int kApiStackSpace = 4;
+  const int kApiStackSpace = 3;
 
   PrepareCallApiFunction(masm, kApiStackSpace);
 
@@ -5453,8 +5214,6 @@
   __ movp(StackSpaceOperand(1), scratch);
   // FunctionCallbackInfo::length_.
   __ Set(StackSpaceOperand(2), argc);
-  // FunctionCallbackInfo::is_construct_call_.
-  __ Set(StackSpaceOperand(3), 0);
 
 #if defined(__MINGW64__) || defined(_WIN64)
   Register arguments_arg = rcx;
@@ -5479,11 +5238,11 @@
                                        ARGUMENTS_DONT_CONTAIN_RECEIVER);
   Operand context_restore_operand = args_from_rbp.GetArgumentOperand(
       FCA::kArgsLength - FCA::kContextSaveIndex);
-  Operand is_construct_call_operand = StackSpaceOperand(3);
+  Operand length_operand = StackSpaceOperand(2);
   Operand return_value_operand = args_from_rbp.GetArgumentOperand(
       this->is_store() ? 0 : FCA::kArgsLength - FCA::kReturnValueOffset);
   int stack_space = 0;
-  Operand* stack_space_operand = &is_construct_call_operand;
+  Operand* stack_space_operand = &length_operand;
   stack_space = argc + FCA::kArgsLength + 1;
   stack_space_operand = nullptr;
   CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, callback_arg,
@@ -5493,14 +5252,6 @@
 
 
 void CallApiGetterStub::Generate(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- rsp[0]                          : return address
-  //  -- rsp[8]                          : name
-  //  -- rsp[16 .. (16 + kArgsLength*8)] : v8::PropertyCallbackInfo::args_
-  //  -- ...
-  //  -- r8                              : api_function_address
-  // -----------------------------------
-
 #if defined(__MINGW64__) || defined(_WIN64)
   Register getter_arg = r8;
   Register accessor_info_arg = rdx;
@@ -5510,9 +5261,36 @@
   Register accessor_info_arg = rsi;
   Register name_arg = rdi;
 #endif
-  Register api_function_address = ApiGetterDescriptor::function_address();
-  DCHECK(api_function_address.is(r8));
+  Register api_function_address = r8;
+  Register receiver = ApiGetterDescriptor::ReceiverRegister();
+  Register holder = ApiGetterDescriptor::HolderRegister();
+  Register callback = ApiGetterDescriptor::CallbackRegister();
   Register scratch = rax;
+  DCHECK(!AreAliased(receiver, holder, callback, scratch));
+
+  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
+  // name below the exit frame to make GC aware of them.
+  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
+  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
+  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
+  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
+  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
+  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
+
+  // Insert additional parameters into the stack frame above return address.
+  __ PopReturnAddressTo(scratch);
+  __ Push(receiver);
+  __ Push(FieldOperand(callback, AccessorInfo::kDataOffset));
+  __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
+  __ Push(kScratchRegister);  // return value
+  __ Push(kScratchRegister);  // return value default
+  __ PushAddress(ExternalReference::isolate_address(isolate()));
+  __ Push(holder);
+  __ Push(Smi::FromInt(0));  // should_throw_on_error -> false
+  __ Push(FieldOperand(callback, AccessorInfo::kNameOffset));
+  __ PushReturnAddressFrom(scratch);
 
   // v8::PropertyCallbackInfo::args_ array and name handle.
   const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
@@ -5539,8 +5317,11 @@
 
   // It's okay if api_function_address == getter_arg
   // but not accessor_info_arg or name_arg
-  DCHECK(!api_function_address.is(accessor_info_arg) &&
-         !api_function_address.is(name_arg));
+  DCHECK(!api_function_address.is(accessor_info_arg));
+  DCHECK(!api_function_address.is(name_arg));
+  __ movp(scratch, FieldOperand(callback, AccessorInfo::kJsGetterOffset));
+  __ movp(api_function_address,
+          FieldOperand(scratch, Foreign::kForeignAddressOffset));
 
   // +3 is to skip prolog, return address and name handle.
   Operand return_value_operand(
@@ -5550,7 +5331,6 @@
                            NULL);
 }
 
-
 #undef __
 
 }  // namespace internal
diff --git a/src/x64/code-stubs-x64.h b/src/x64/code-stubs-x64.h
index d4f8b29..a181377 100644
--- a/src/x64/code-stubs-x64.h
+++ b/src/x64/code-stubs-x64.h
@@ -295,8 +295,8 @@
                                   Register r2,
                                   Register r3) {
       for (int i = 0; i < Register::kNumRegisters; i++) {
-        Register candidate = Register::from_code(i);
-        if (candidate.IsAllocatable()) {
+        if (RegisterConfiguration::Crankshaft()->IsAllocatableGeneralCode(i)) {
+          Register candidate = Register::from_code(i);
           if (candidate.is(rcx)) continue;
           if (candidate.is(r1)) continue;
           if (candidate.is(r2)) continue;
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index 33e987e..911f3cb 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -32,38 +32,6 @@
 #define __ masm.
 
 
-UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) {
-  size_t actual_size;
-  byte* buffer =
-      static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
-  if (buffer == nullptr) return nullptr;
-  ExternalReference::InitializeMathExpData();
-
-  MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
-                      CodeObjectRequired::kNo);
-  // xmm0: raw double input.
-  XMMRegister input = xmm0;
-  XMMRegister result = xmm1;
-  __ pushq(rax);
-  __ pushq(rbx);
-
-  MathExpGenerator::EmitMathExp(&masm, input, result, xmm2, rax, rbx);
-
-  __ popq(rbx);
-  __ popq(rax);
-  __ Movsd(xmm0, result);
-  __ Ret();
-
-  CodeDesc desc;
-  masm.GetCode(&desc);
-  DCHECK(!RelocInfo::RequiresRelocation(desc));
-
-  Assembler::FlushICache(isolate, buffer, actual_size);
-  base::OS::ProtectCode(buffer, actual_size);
-  return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
-}
-
-
 UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
   size_t actual_size;
   // Allocate buffer in executable space.
@@ -204,7 +172,7 @@
   // Allocate new backing store.
   __ bind(&new_backing_store);
   __ leap(rdi, Operand(r9, times_8, FixedArray::kHeaderSize));
-  __ Allocate(rdi, r14, r11, r15, fail, TAG_OBJECT);
+  __ Allocate(rdi, r14, r11, r15, fail, NO_ALLOCATION_FLAGS);
   // Set backing store's map
   __ LoadRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex);
   __ movp(FieldOperand(r14, HeapObject::kMapOffset), rdi);
@@ -243,8 +211,9 @@
   // rbx: current element (smi-tagged)
   __ JumpIfNotSmi(rbx, &convert_hole);
   __ SmiToInteger32(rbx, rbx);
-  __ Cvtlsi2sd(xmm0, rbx);
-  __ Movsd(FieldOperand(r14, r9, times_8, FixedDoubleArray::kHeaderSize), xmm0);
+  __ Cvtlsi2sd(kScratchDoubleReg, rbx);
+  __ Movsd(FieldOperand(r14, r9, times_8, FixedDoubleArray::kHeaderSize),
+           kScratchDoubleReg);
   __ jmp(&entry);
   __ bind(&convert_hole);
 
@@ -296,7 +265,7 @@
   // r8 : source FixedDoubleArray
   // r9 : number of elements
   __ leap(rdi, Operand(r9, times_pointer_size, FixedArray::kHeaderSize));
-  __ Allocate(rdi, r11, r14, r15, &gc_required, TAG_OBJECT);
+  __ Allocate(rdi, r11, r14, r15, &gc_required, NO_ALLOCATION_FLAGS);
   // r11: destination FixedArray
   __ LoadRoot(rdi, Heap::kFixedArrayMapRootIndex);
   __ movp(FieldOperand(r11, HeapObject::kMapOffset), rdi);
@@ -498,59 +467,6 @@
   __ bind(&done);
 }
 
-
-void MathExpGenerator::EmitMathExp(MacroAssembler* masm,
-                                   XMMRegister input,
-                                   XMMRegister result,
-                                   XMMRegister double_scratch,
-                                   Register temp1,
-                                   Register temp2) {
-  DCHECK(!input.is(result));
-  DCHECK(!input.is(double_scratch));
-  DCHECK(!result.is(double_scratch));
-  DCHECK(!temp1.is(temp2));
-  DCHECK(ExternalReference::math_exp_constants(0).address() != NULL);
-  DCHECK(!masm->serializer_enabled());  // External references not serializable.
-
-  Label done;
-
-  __ Move(kScratchRegister, ExternalReference::math_exp_constants(0));
-  __ Movsd(double_scratch, Operand(kScratchRegister, 0 * kDoubleSize));
-  __ Xorpd(result, result);
-  __ Ucomisd(double_scratch, input);
-  __ j(above_equal, &done);
-  __ Ucomisd(input, Operand(kScratchRegister, 1 * kDoubleSize));
-  __ Movsd(result, Operand(kScratchRegister, 2 * kDoubleSize));
-  __ j(above_equal, &done);
-  __ Movsd(double_scratch, Operand(kScratchRegister, 3 * kDoubleSize));
-  __ Movsd(result, Operand(kScratchRegister, 4 * kDoubleSize));
-  __ Mulsd(double_scratch, input);
-  __ Addsd(double_scratch, result);
-  __ Movq(temp2, double_scratch);
-  __ Subsd(double_scratch, result);
-  __ Movsd(result, Operand(kScratchRegister, 6 * kDoubleSize));
-  __ leaq(temp1, Operand(temp2, 0x1ff800));
-  __ andq(temp2, Immediate(0x7ff));
-  __ shrq(temp1, Immediate(11));
-  __ Mulsd(double_scratch, Operand(kScratchRegister, 5 * kDoubleSize));
-  __ Move(kScratchRegister, ExternalReference::math_exp_log_table());
-  __ shlq(temp1, Immediate(52));
-  __ orq(temp1, Operand(kScratchRegister, temp2, times_8, 0));
-  __ Move(kScratchRegister, ExternalReference::math_exp_constants(0));
-  __ Subsd(double_scratch, input);
-  __ Movsd(input, double_scratch);
-  __ Subsd(result, double_scratch);
-  __ Mulsd(input, double_scratch);
-  __ Mulsd(result, input);
-  __ Movq(input, temp1);
-  __ Mulsd(result, Operand(kScratchRegister, 7 * kDoubleSize));
-  __ Subsd(result, double_scratch);
-  __ Addsd(result, Operand(kScratchRegister, 8 * kDoubleSize));
-  __ Mulsd(result, input);
-
-  __ bind(&done);
-}
-
 #undef __
 
 
diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h
index 1403781..62945f7 100644
--- a/src/x64/codegen-x64.h
+++ b/src/x64/codegen-x64.h
@@ -28,20 +28,6 @@
 };
 
 
-class MathExpGenerator : public AllStatic {
- public:
-  static void EmitMathExp(MacroAssembler* masm,
-                          XMMRegister input,
-                          XMMRegister result,
-                          XMMRegister double_scratch,
-                          Register temp1,
-                          Register temp2);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MathExpGenerator);
-};
-
-
 enum StackArgumentsAccessorReceiverMode {
   ARGUMENTS_CONTAIN_RECEIVER,
   ARGUMENTS_DONT_CONTAIN_RECEIVER
diff --git a/src/x64/deoptimizer-x64.cc b/src/x64/deoptimizer-x64.cc
index 9d70c32..35da7a2 100644
--- a/src/x64/deoptimizer-x64.cc
+++ b/src/x64/deoptimizer-x64.cc
@@ -116,8 +116,7 @@
   const int kDoubleRegsSize = kDoubleSize * XMMRegister::kMaxNumRegisters;
   __ subp(rsp, Immediate(kDoubleRegsSize));
 
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
     int code = config->GetAllocatableDoubleCode(i);
     XMMRegister xmm_reg = XMMRegister::from_code(code);
diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc
index a9532dc..d679898 100644
--- a/src/x64/disasm-x64.cc
+++ b/src/x64/disasm-x64.cc
@@ -8,6 +8,7 @@
 
 #if V8_TARGET_ARCH_X64
 
+#include "src/base/compiler-specific.h"
 #include "src/base/lazy-instance.h"
 #include "src/disasm.h"
 
@@ -141,19 +142,18 @@
   SHORT_IMMEDIATE_INSTR
 };
 
-
 enum Prefixes {
   ESCAPE_PREFIX = 0x0F,
   OPERAND_SIZE_OVERRIDE_PREFIX = 0x66,
   ADDRESS_SIZE_OVERRIDE_PREFIX = 0x67,
   VEX3_PREFIX = 0xC4,
   VEX2_PREFIX = 0xC5,
+  LOCK_PREFIX = 0xF0,
   REPNE_PREFIX = 0xF2,
   REP_PREFIX = 0xF3,
   REPEQ_PREFIX = REP_PREFIX
 };
 
-
 struct InstructionDesc {
   const char* mnem;
   InstructionType type;
@@ -359,7 +359,7 @@
   bool vex_128() {
     DCHECK(vex_byte0_ == VEX3_PREFIX || vex_byte0_ == VEX2_PREFIX);
     byte checked = vex_byte0_ == VEX3_PREFIX ? vex_byte2_ : vex_byte1_;
-    return (checked & 4) != 1;
+    return (checked & 4) == 0;
   }
 
   bool vex_none() {
@@ -479,7 +479,7 @@
   int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
   int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
   int AVXInstruction(byte* data);
-  void AppendToBuffer(const char* format, ...);
+  PRINTF_FORMAT(2, 3) void AppendToBuffer(const char* format, ...);
 
   void UnimplementedInstruction() {
     if (abort_on_unimplemented_) {
@@ -618,7 +618,7 @@
       value = 0;  // Initialize variables on all paths to satisfy the compiler.
       count = 0;
   }
-  AppendToBuffer("%" V8_PTR_PREFIX "x", value);
+  AppendToBuffer("%" PRIx64, value);
   return count;
 }
 
@@ -1513,7 +1513,16 @@
   if (operand_size_ == 0x66) {
     // 0x66 0x0F prefix.
     int mod, regop, rm;
-    if (opcode == 0x3A) {
+    if (opcode == 0x38) {
+      byte third_byte = *current;
+      current = data + 3;
+      if (third_byte == 0x40) {
+        // pmulld xmm, xmm/m128
+        get_modrm(*current, &mod, &regop, &rm);
+        AppendToBuffer("pmulld %s,", NameOfXMMRegister(regop));
+        current += PrintRightXMMOperand(current);
+      }
+    } else if (opcode == 0x3A) {
       byte third_byte = *current;
       current = data + 3;
       if (third_byte == 0x17) {
@@ -1536,11 +1545,18 @@
         AppendToBuffer(",0x%x", (*current) & 3);
         current += 1;
       } else if (third_byte == 0x16) {
-        get_modrm(*current, &mod, &rm, &regop);
+        get_modrm(*current, &mod, &regop, &rm);
         AppendToBuffer("pextrd ");  // reg/m32, xmm, imm8
         current += PrintRightOperand(current);
         AppendToBuffer(",%s,%d", NameOfXMMRegister(regop), (*current) & 3);
         current += 1;
+      } else if (third_byte == 0x21) {
+        get_modrm(*current, &mod, &regop, &rm);
+        // insertps xmm, xmm/m32, imm8
+        AppendToBuffer("insertps %s,", NameOfXMMRegister(regop));
+        current += PrintRightXMMOperand(current);
+        AppendToBuffer(",0x%x", (*current) & 3);
+        current += 1;
       } else if (third_byte == 0x22) {
         get_modrm(*current, &mod, &regop, &rm);
         AppendToBuffer("pinsrd ");  // xmm, reg/m32, imm8
@@ -1596,6 +1612,11 @@
       } else if (opcode == 0x50) {
         AppendToBuffer("movmskpd %s,", NameOfCPURegister(regop));
         current += PrintRightXMMOperand(current);
+      } else if (opcode == 0x70) {
+        AppendToBuffer("pshufd %s,", NameOfXMMRegister(regop));
+        current += PrintRightXMMOperand(current);
+        AppendToBuffer(",0x%x", *current);
+        current += 1;
       } else if (opcode == 0x72) {
         current += 1;
         AppendToBuffer("%s %s,%d", (regop == 6) ? "pslld" : "psrld",
@@ -1606,6 +1627,8 @@
         AppendToBuffer("%s %s,%d", (regop == 6) ? "psllq" : "psrlq",
                        NameOfXMMRegister(rm), *current & 0x7f);
         current += 1;
+      } else if (opcode == 0xB1) {
+        current += PrintOperands("cmpxchg", OPER_REG_OP_ORDER, current);
       } else {
         const char* mnemonic = "?";
         if (opcode == 0x54) {
@@ -1614,6 +1637,8 @@
           mnemonic = "orpd";
         } else  if (opcode == 0x57) {
           mnemonic = "xorpd";
+        } else if (opcode == 0x5B) {
+          mnemonic = "cvtps2dq";
         } else if (opcode == 0x2E) {
           mnemonic = "ucomisd";
         } else if (opcode == 0x2F) {
@@ -1624,6 +1649,12 @@
           mnemonic = "punpckldq";
         } else if (opcode == 0x6A) {
           mnemonic = "punpckhdq";
+        } else if (opcode == 0xF4) {
+          mnemonic = "pmuludq";
+        } else if (opcode == 0xFA) {
+          mnemonic = "psubd";
+        } else if (opcode == 0xFE) {
+          mnemonic = "paddd";
         } else {
           UnimplementedInstruction();
         }
@@ -1765,6 +1796,19 @@
     } else {
       UnimplementedInstruction();
     }
+  } else if (opcode == 0x10 || opcode == 0x11) {
+    // movups xmm, xmm/m128
+    // movups xmm/m128, xmm
+    int mod, regop, rm;
+    get_modrm(*current, &mod, &regop, &rm);
+    AppendToBuffer("movups ");
+    if (opcode == 0x11) {
+      current += PrintRightXMMOperand(current);
+      AppendToBuffer(",%s", NameOfXMMRegister(regop));
+    } else {
+      AppendToBuffer("%s,", NameOfXMMRegister(regop));
+      current += PrintRightXMMOperand(current);
+    }
   } else if (opcode == 0x1F) {
     // NOP
     int mod, regop, rm;
@@ -1811,29 +1855,28 @@
     byte_size_operand_ = idesc.byte_size_operation;
     current += PrintOperands(idesc.mnem, idesc.op_order_, current);
 
-  } else if (opcode >= 0x53 && opcode <= 0x5F) {
+  } else if (opcode >= 0x51 && opcode <= 0x5F) {
     const char* const pseudo_op[] = {
-      "rcpps",
-      "andps",
-      "andnps",
-      "orps",
-      "xorps",
-      "addps",
-      "mulps",
-      "cvtps2pd",
-      "cvtdq2ps",
-      "subps",
-      "minps",
-      "divps",
-      "maxps",
+        "sqrtps",   "rsqrtps", "rcpps", "andps", "andnps",
+        "orps",     "xorps",   "addps", "mulps", "cvtps2pd",
+        "cvtdq2ps", "subps",   "minps", "divps", "maxps",
     };
     int mod, regop, rm;
     get_modrm(*current, &mod, &regop, &rm);
-    AppendToBuffer("%s %s,",
-                   pseudo_op[opcode - 0x53],
+    AppendToBuffer("%s %s,", pseudo_op[opcode - 0x51],
                    NameOfXMMRegister(regop));
     current += PrintRightXMMOperand(current);
 
+  } else if (opcode == 0xC2) {
+    // cmpps xmm, xmm/m128, imm8
+    int mod, regop, rm;
+    get_modrm(*current, &mod, &regop, &rm);
+    const char* const pseudo_op[] = {"cmpeqps",    "cmpltps",  "cmpleps",
+                                     "cmpunordps", "cmpneqps", "cmpnltps",
+                                     "cmpnleps",   "cmpordps"};
+    AppendToBuffer("%s %s,%s", pseudo_op[current[1]], NameOfXMMRegister(regop),
+                   NameOfXMMRegister(rm));
+    current += 2;
   } else if (opcode == 0xC6) {
     // shufps xmm, xmm/m128, imm8
     int mod, regop, rm;
@@ -1842,7 +1885,6 @@
     current += PrintRightXMMOperand(current);
     AppendToBuffer(", %d", (*current) & 3);
     current += 1;
-
   } else if (opcode == 0x50) {
     // movmskps reg, xmm
     int mod, regop, rm;
@@ -1883,6 +1925,12 @@
     current += PrintRightOperand(current);
   } else if (opcode == 0x0B) {
     AppendToBuffer("ud2");
+  } else if (opcode == 0xB0 || opcode == 0xB1) {
+    // CMPXCHG.
+    if (opcode == 0xB0) {
+      byte_size_operand_ = true;
+    }
+    current += PrintOperands(mnemonic, OPER_REG_OP_ORDER, current);
   } else {
     UnimplementedInstruction();
   }
@@ -1925,6 +1973,9 @@
       return "shrd";
     case 0xAF:
       return "imul";
+    case 0xB0:
+    case 0xB1:
+      return "cmpxchg";
     case 0xB6:
       return "movzxb";
     case 0xB7:
@@ -1962,6 +2013,8 @@
       if (rex_w()) AppendToBuffer("REX.W ");
     } else if ((current & 0xFE) == 0xF2) {  // Group 1 prefix (0xF2 or 0xF3).
       group_1_prefix_ = current;
+    } else if (current == LOCK_PREFIX) {
+      AppendToBuffer("lock ");
     } else if (current == VEX3_PREFIX) {
       vex_byte0_ = current;
       vex_byte1_ = *(data + 1);
@@ -1999,7 +2052,7 @@
           if (rex_w()) AppendToBuffer("REX.W ");
           AppendToBuffer("%s%c", idesc.mnem, operand_size_code());
         } else {
-          AppendToBuffer("%s", idesc.mnem, operand_size_code());
+          AppendToBuffer("%s%c", idesc.mnem, operand_size_code());
         }
         data++;
         break;
@@ -2141,9 +2194,11 @@
           default:
             mnem = "???";
         }
-        AppendToBuffer(((regop <= 1) ? "%s%c " : "%s "),
-                       mnem,
-                       operand_size_code());
+        if (regop <= 1) {
+          AppendToBuffer("%s%c ", mnem, operand_size_code());
+        } else {
+          AppendToBuffer("%s ", mnem);
+        }
         data += PrintRightOperand(data);
       }
         break;
@@ -2334,9 +2389,7 @@
           default:
             UNREACHABLE();
         }
-        AppendToBuffer("test%c rax,0x%" V8_PTR_PREFIX "x",
-                       operand_size_code(),
-                       value);
+        AppendToBuffer("test%c rax,0x%" PRIx64, operand_size_code(), value);
         break;
       }
       case 0xD1:  // fall through
@@ -2426,7 +2479,7 @@
 
 
 const char* NameConverter::NameOfAddress(byte* addr) const {
-  v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
+  v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
   return tmp_buffer_.start();
 }
 
@@ -2493,7 +2546,7 @@
     buffer[0] = '\0';
     byte* prev_pc = pc;
     pc += d.InstructionDecode(buffer, pc);
-    fprintf(f, "%p", prev_pc);
+    fprintf(f, "%p", static_cast<void*>(prev_pc));
     fprintf(f, "    ");
 
     for (byte* bp = prev_pc; bp < pc; bp++) {
diff --git a/src/x64/interface-descriptors-x64.cc b/src/x64/interface-descriptors-x64.cc
index b10b522..a7cf120 100644
--- a/src/x64/interface-descriptors-x64.cc
+++ b/src/x64/interface-descriptors-x64.cc
@@ -11,6 +11,14 @@
 
 const Register CallInterfaceDescriptor::ContextRegister() { return rsi; }
 
+void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
+    CallInterfaceDescriptorData* data, int register_parameter_count) {
+  const Register default_stub_registers[] = {rax, rbx, rcx, rdx, rdi};
+  CHECK_LE(static_cast<size_t>(register_parameter_count),
+           arraysize(default_stub_registers));
+  data->InitializePlatformSpecific(register_parameter_count,
+                                   default_stub_registers);
+}
 
 const Register LoadDescriptor::ReceiverRegister() { return rdx; }
 const Register LoadDescriptor::NameRegister() { return rcx; }
@@ -39,23 +47,15 @@
 const Register StoreTransitionDescriptor::MapRegister() { return rbx; }
 
 
-const Register LoadGlobalViaContextDescriptor::SlotRegister() { return rbx; }
-
-
 const Register StoreGlobalViaContextDescriptor::SlotRegister() { return rbx; }
 const Register StoreGlobalViaContextDescriptor::ValueRegister() { return rax; }
 
 
-const Register InstanceOfDescriptor::LeftRegister() { return rdx; }
-const Register InstanceOfDescriptor::RightRegister() { return rax; }
-
-
 const Register StringCompareDescriptor::LeftRegister() { return rdx; }
 const Register StringCompareDescriptor::RightRegister() { return rax; }
 
-
-const Register ApiGetterDescriptor::function_address() { return r8; }
-
+const Register ApiGetterDescriptor::HolderRegister() { return rcx; }
+const Register ApiGetterDescriptor::CallbackRegister() { return rbx; }
 
 const Register MathPowTaggedDescriptor::exponent() { return rdx; }
 
@@ -243,50 +243,37 @@
 SIMD128_TYPES(SIMD128_ALLOC_DESC)
 #undef SIMD128_ALLOC_DESC
 
-void AllocateInNewSpaceDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  Register registers[] = {rax};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-void ArrayConstructorConstantArgCountDescriptor::InitializePlatformSpecific(
+void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // register state
   // rax -- number of arguments
   // rdi -- function
   // rbx -- allocation site with elements kind
-  Register registers[] = {rdi, rbx};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-void ArrayConstructorDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  // stack param count needs (constructor pointer, and single argument)
   Register registers[] = {rdi, rbx, rax};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
+  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
-
-void InternalArrayConstructorConstantArgCountDescriptor::
-    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
+void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
   // register state
   // rax -- number of arguments
-  // rdi -- constructor function
-  Register registers[] = {rdi};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
+  // rdi -- function
+  // rbx -- allocation site with elements kind
+  Register registers[] = {rdi, rbx, rax};
+  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
-
-void InternalArrayConstructorDescriptor::InitializePlatformSpecific(
+void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
-  // stack param count needs (constructor pointer, and single argument)
-  Register registers[] = {rdi, rax};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
+  // register state
+  // rax -- number of arguments
+  // rdi -- function
+  // rbx -- allocation site with elements kind
+  Register registers[] = {rdi, rbx, rax};
+  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
-void FastArrayPushDescriptor::InitializePlatformSpecific(
+void VarArgFunctionDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // stack param count needs (arg count)
   Register registers[] = {rax};
@@ -313,6 +300,11 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
+void CountOpDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {rax};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
 
 void StringAddDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
@@ -373,9 +365,8 @@
 void InterpreterDispatchDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {
-      kInterpreterAccumulatorRegister, kInterpreterRegisterFileRegister,
-      kInterpreterBytecodeOffsetRegister, kInterpreterBytecodeArrayRegister,
-      kInterpreterDispatchTableRegister};
+      kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
+      kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
@@ -410,6 +401,16 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
+void ResumeGeneratorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {
+      rax,  // the value to pass to the generator
+      rbx,  // the JSGeneratorObject to resume
+      rdx   // the resume mode (tagged)
+  };
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 566091d..cd6b90c 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -489,7 +489,7 @@
   // easier.
   DCHECK(js_function.is(rdi));
   DCHECK(code_entry.is(rcx));
-  DCHECK(scratch.is(rax));
+  DCHECK(scratch.is(r15));
 
   // Since a code entry (value) is always in old space, we don't need to update
   // remembered set. If incremental marking is off, there is nothing for us to
@@ -537,13 +537,13 @@
     DCHECK(arg_reg_2.is(rdx) && arg_reg_3.is(r8));
 
     movp(arg_reg_1, js_function);  // rcx gets rdi.
-    movp(arg_reg_2, dst);          // rdx gets rax.
+    movp(arg_reg_2, dst);          // rdx gets r15.
   } else {
     // AMD64 calling convention.
     DCHECK(arg_reg_1.is(rdi) && arg_reg_2.is(rsi) && arg_reg_3.is(rdx));
 
     // rdi is already loaded with js_function.
-    movp(arg_reg_2, dst);  // rsi gets rax.
+    movp(arg_reg_2, dst);  // rsi gets r15.
   }
   Move(arg_reg_3, ExternalReference::isolate_address(isolate()));
 
@@ -1116,15 +1116,6 @@
   }
 }
 
-void MacroAssembler::Set(Register dst, int64_t x, RelocInfo::Mode rmode) {
-  if (rmode == RelocInfo::WASM_MEMORY_REFERENCE) {
-    DCHECK(x != 0);
-    movq(dst, x, rmode);
-  } else {
-    DCHECK(RelocInfo::IsNone(rmode));
-  }
-}
-
 void MacroAssembler::Set(const Operand& dst, intptr_t x) {
   if (kPointerSize == kInt64Size) {
     if (is_int32(x)) {
@@ -3268,12 +3259,12 @@
     pinsrd(dst, src, imm8);
     return;
   }
-  Movd(xmm0, src);
+  Movd(kScratchDoubleReg, src);
   if (imm8 == 1) {
-    punpckldq(dst, xmm0);
+    punpckldq(dst, kScratchDoubleReg);
   } else {
     DCHECK_EQ(0, imm8);
-    Movss(dst, xmm0);
+    Movss(dst, kScratchDoubleReg);
   }
 }
 
@@ -3285,12 +3276,12 @@
     pinsrd(dst, src, imm8);
     return;
   }
-  Movd(xmm0, src);
+  Movd(kScratchDoubleReg, src);
   if (imm8 == 1) {
-    punpckldq(dst, xmm0);
+    punpckldq(dst, kScratchDoubleReg);
   } else {
     DCHECK_EQ(0, imm8);
-    Movss(dst, xmm0);
+    Movss(dst, kScratchDoubleReg);
   }
 }
 
@@ -3752,15 +3743,15 @@
 void MacroAssembler::TruncateHeapNumberToI(Register result_reg,
                                            Register input_reg) {
   Label done;
-  Movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
-  Cvttsd2siq(result_reg, xmm0);
+  Movsd(kScratchDoubleReg, FieldOperand(input_reg, HeapNumber::kValueOffset));
+  Cvttsd2siq(result_reg, kScratchDoubleReg);
   cmpq(result_reg, Immediate(1));
   j(no_overflow, &done, Label::kNear);
 
   // Slow case.
   if (input_reg.is(result_reg)) {
     subp(rsp, Immediate(kDoubleSize));
-    Movsd(MemOperand(rsp, 0), xmm0);
+    Movsd(MemOperand(rsp, 0), kScratchDoubleReg);
     SlowTruncateToI(result_reg, rsp, 0);
     addp(rsp, Immediate(kDoubleSize));
   } else {
@@ -3797,8 +3788,8 @@
                                Label* lost_precision, Label* is_nan,
                                Label* minus_zero, Label::Distance dst) {
   Cvttsd2si(result_reg, input_reg);
-  Cvtlsi2sd(xmm0, result_reg);
-  Ucomisd(xmm0, input_reg);
+  Cvtlsi2sd(kScratchDoubleReg, result_reg);
+  Ucomisd(kScratchDoubleReg, input_reg);
   j(not_equal, lost_precision, dst);
   j(parity_even, is_nan, dst);  // NaN.
   if (minus_zero_mode == FAIL_ON_MINUS_ZERO) {
@@ -3970,6 +3961,16 @@
   }
 }
 
+void MacroAssembler::AssertGeneratorObject(Register object) {
+  if (emit_debug_code()) {
+    testb(object, Immediate(kSmiTagMask));
+    Check(not_equal, kOperandIsASmiAndNotAGeneratorObject);
+    Push(object);
+    CmpObjectType(object, JS_GENERATOR_OBJECT_TYPE, object);
+    Pop(object);
+    Check(equal, kOperandIsNotAGeneratorObject);
+  }
+}
 
 void MacroAssembler::AssertReceiver(Register object) {
   if (emit_debug_code()) {
@@ -4337,11 +4338,12 @@
                                              const ParameterCount& expected,
                                              const ParameterCount& actual) {
   Label skip_flooding;
-  ExternalReference step_in_enabled =
-      ExternalReference::debug_step_in_enabled_address(isolate());
-  Operand step_in_enabled_operand = ExternalOperand(step_in_enabled);
-  cmpb(step_in_enabled_operand, Immediate(0));
-  j(equal, &skip_flooding);
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(isolate());
+  Operand last_step_action_operand = ExternalOperand(last_step_action);
+  STATIC_ASSERT(StepFrame > StepIn);
+  cmpb(last_step_action_operand, Immediate(StepIn));
+  j(less, &skip_flooding);
   {
     FrameScope frame(this,
                      has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
@@ -4400,8 +4402,8 @@
 
 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
   movp(vector, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
-  movp(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset));
-  movp(vector, FieldOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset));
+  movp(vector, FieldOperand(vector, JSFunction::kLiteralsOffset));
+  movp(vector, FieldOperand(vector, LiteralsArray::kFeedbackVectorOffset));
 }
 
 
@@ -4482,8 +4484,7 @@
                 arg_stack_space * kRegisterSize;
     subp(rsp, Immediate(space));
     int offset = -ExitFrameConstants::kFixedFrameSizeFromFp;
-    const RegisterConfiguration* config =
-        RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+    const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
     for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
       DoubleRegister reg =
           DoubleRegister::from_code(config->GetAllocatableDoubleCode(i));
@@ -4529,8 +4530,7 @@
   // r15 : argv
   if (save_doubles) {
     int offset = -ExitFrameConstants::kFixedFrameSizeFromFp;
-    const RegisterConfiguration* config =
-        RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+    const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
     for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
       DoubleRegister reg =
           DoubleRegister::from_code(config->GetAllocatableDoubleCode(i));
@@ -4829,7 +4829,7 @@
     Label aligned;
     testl(result, Immediate(kDoubleAlignmentMask));
     j(zero, &aligned, Label::kNear);
-    if ((flags & PRETENURE) != 0) {
+    if (((flags & ALLOCATION_FOLDED) == 0) && ((flags & PRETENURE) != 0)) {
       ExternalReference allocation_limit =
           AllocationUtils::GetAllocationLimitReference(isolate(), flags);
       cmpp(result, ExternalOperand(allocation_limit));
@@ -4872,6 +4872,7 @@
                               AllocationFlags flags) {
   DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
   DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -4905,23 +4906,19 @@
     movp(top_reg, result);
   }
   addp(top_reg, Immediate(object_size));
-  j(carry, gc_required);
   Operand limit_operand = ExternalOperand(allocation_limit);
   cmpp(top_reg, limit_operand);
   j(above, gc_required);
 
-  // Update allocation top.
-  UpdateAllocationTopHelper(top_reg, scratch, flags);
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    UpdateAllocationTopHelper(top_reg, scratch, flags);
+  }
 
-  bool tag_result = (flags & TAG_OBJECT) != 0;
   if (top_reg.is(result)) {
-    if (tag_result) {
-      subp(result, Immediate(object_size - kHeapObjectTag));
-    } else {
-      subp(result, Immediate(object_size));
-    }
-  } else if (tag_result) {
-    // Tag the result if requested.
+    subp(result, Immediate(object_size - kHeapObjectTag));
+  } else {
+    // Tag the result.
     DCHECK(kHeapObjectTag == 1);
     incp(result);
   }
@@ -4937,6 +4934,8 @@
                               Label* gc_required,
                               AllocationFlags flags) {
   DCHECK((flags & SIZE_IN_WORDS) == 0);
+  DCHECK((flags & ALLOCATION_FOLDING_DOMINATOR) == 0);
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   leap(result_end, Operand(element_count, element_size, header_size));
   Allocate(result_end, result, result_end, scratch, gc_required, flags);
 }
@@ -4949,6 +4948,7 @@
                               Label* gc_required,
                               AllocationFlags flags) {
   DCHECK((flags & SIZE_IN_WORDS) == 0);
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -4971,34 +4971,66 @@
     MakeSureDoubleAlignedHelper(result, scratch, gc_required, flags);
   }
 
-  // Calculate new top and bail out if new space is exhausted.
   ExternalReference allocation_limit =
       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
   if (!object_size.is(result_end)) {
     movp(result_end, object_size);
   }
   addp(result_end, result);
-  j(carry, gc_required);
   Operand limit_operand = ExternalOperand(allocation_limit);
   cmpp(result_end, limit_operand);
   j(above, gc_required);
 
-  // Update allocation top.
-  UpdateAllocationTopHelper(result_end, scratch, flags);
-
-  // Tag the result if requested.
-  if ((flags & TAG_OBJECT) != 0) {
-    addp(result, Immediate(kHeapObjectTag));
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    UpdateAllocationTopHelper(result_end, scratch, flags);
   }
+
+  // Tag the result.
+  addp(result, Immediate(kHeapObjectTag));
 }
 
+void MacroAssembler::FastAllocate(int object_size, Register result,
+                                  Register result_end, AllocationFlags flags) {
+  DCHECK(!result.is(result_end));
+  // Load address of new object into result.
+  LoadAllocationTopHelper(result, no_reg, flags);
+
+  if ((flags & DOUBLE_ALIGNMENT) != 0) {
+    MakeSureDoubleAlignedHelper(result, no_reg, NULL, flags);
+  }
+
+  leap(result_end, Operand(result, object_size));
+
+  UpdateAllocationTopHelper(result_end, no_reg, flags);
+
+  addp(result, Immediate(kHeapObjectTag));
+}
+
+void MacroAssembler::FastAllocate(Register object_size, Register result,
+                                  Register result_end, AllocationFlags flags) {
+  DCHECK(!result.is(result_end));
+  // Load address of new object into result.
+  LoadAllocationTopHelper(result, no_reg, flags);
+
+  if ((flags & DOUBLE_ALIGNMENT) != 0) {
+    MakeSureDoubleAlignedHelper(result, no_reg, NULL, flags);
+  }
+
+  leap(result_end, Operand(result, object_size, times_1, 0));
+
+  UpdateAllocationTopHelper(result_end, no_reg, flags);
+
+  addp(result, Immediate(kHeapObjectTag));
+}
 
 void MacroAssembler::AllocateHeapNumber(Register result,
                                         Register scratch,
                                         Label* gc_required,
                                         MutableMode mode) {
   // Allocate heap number in new space.
-  Allocate(HeapNumber::kSize, result, scratch, no_reg, gc_required, TAG_OBJECT);
+  Allocate(HeapNumber::kSize, result, scratch, no_reg, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   Heap::RootListIndex map_index = mode == MUTABLE
       ? Heap::kMutableHeapNumberMapRootIndex
@@ -5030,14 +5062,8 @@
   }
 
   // Allocate two byte string in new space.
-  Allocate(SeqTwoByteString::kHeaderSize,
-           times_1,
-           scratch1,
-           result,
-           scratch2,
-           scratch3,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(SeqTwoByteString::kHeaderSize, times_1, scratch1, result, scratch2,
+           scratch3, gc_required, NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   LoadRoot(kScratchRegister, Heap::kStringMapRootIndex);
@@ -5066,14 +5092,8 @@
   }
 
   // Allocate one-byte string in new space.
-  Allocate(SeqOneByteString::kHeaderSize,
-           times_1,
-           scratch1,
-           result,
-           scratch2,
-           scratch3,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(SeqOneByteString::kHeaderSize, times_1, scratch1, result, scratch2,
+           scratch3, gc_required, NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   LoadRoot(kScratchRegister, Heap::kOneByteStringMapRootIndex);
@@ -5091,7 +5111,7 @@
                                         Label* gc_required) {
   // Allocate heap number in new space.
   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   // Set the map. The other fields are left uninitialized.
   LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex);
@@ -5103,12 +5123,8 @@
                                                Register scratch1,
                                                Register scratch2,
                                                Label* gc_required) {
-  Allocate(ConsString::kSize,
-           result,
-           scratch1,
-           scratch2,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map. The other fields are left uninitialized.
   LoadRoot(kScratchRegister, Heap::kConsOneByteStringMapRootIndex);
@@ -5122,7 +5138,7 @@
                                           Label* gc_required) {
   // Allocate heap number in new space.
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   // Set the map. The other fields are left uninitialized.
   LoadRoot(kScratchRegister, Heap::kSlicedStringMapRootIndex);
@@ -5136,7 +5152,7 @@
                                                  Label* gc_required) {
   // Allocate heap number in new space.
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   // Set the map. The other fields are left uninitialized.
   LoadRoot(kScratchRegister, Heap::kSlicedOneByteStringMapRootIndex);
@@ -5152,7 +5168,8 @@
   DCHECK(!result.is(value));
 
   // Allocate JSValue in new space.
-  Allocate(JSValue::kSize, result, scratch, no_reg, gc_required, TAG_OBJECT);
+  Allocate(JSValue::kSize, result, scratch, no_reg, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Initialize the JSValue.
   LoadGlobalFunctionInitialMap(constructor, scratch);
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index af3dd03..b088c7d 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -21,8 +21,8 @@
 const Register kReturnRegister2 = {Register::kCode_r8};
 const Register kJSFunctionRegister = {Register::kCode_rdi};
 const Register kContextRegister = {Register::kCode_rsi};
+const Register kAllocateSizeRegister = {Register::kCode_rdx};
 const Register kInterpreterAccumulatorRegister = {Register::kCode_rax};
-const Register kInterpreterRegisterFileRegister = {Register::kCode_r11};
 const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_r12};
 const Register kInterpreterBytecodeArrayRegister = {Register::kCode_r14};
 const Register kInterpreterDispatchTableRegister = {Register::kCode_r15};
@@ -34,8 +34,9 @@
 // Default scratch register used by MacroAssembler (and other code that needs
 // a spare register). The register isn't callee save, and not used by the
 // function calling convention.
-const Register kScratchRegister = { 10 };      // r10.
-const Register kRootRegister = { 13 };         // r13 (callee save).
+const Register kScratchRegister = {10};      // r10.
+const XMMRegister kScratchDoubleReg = {15};  // xmm15.
+const Register kRootRegister = {13};         // r13 (callee save).
 // Actual value of root register is offset from the root array's start
 // to take advantage of negitive 8-bit displacement values.
 const int kRootRegisterBias = 128;
@@ -818,7 +819,6 @@
 
   // Load a register with a long value as efficiently as possible.
   void Set(Register dst, int64_t x);
-  void Set(Register dst, int64_t x, RelocInfo::Mode rmode);
   void Set(const Operand& dst, intptr_t x);
 
   void Cvtss2sd(XMMRegister dst, XMMRegister src);
@@ -1224,6 +1224,10 @@
   // enabled via --debug-code.
   void AssertBoundFunction(Register object);
 
+  // Abort execution if argument is not a JSGeneratorObject,
+  // enabled via --debug-code.
+  void AssertGeneratorObject(Register object);
+
   // Abort execution if argument is not a JSReceiver, enabled via --debug-code.
   void AssertReceiver(Register object);
 
@@ -1304,6 +1308,15 @@
                 Label* gc_required,
                 AllocationFlags flags);
 
+  // FastAllocate is right now only used for folded allocations. It just
+  // increments the top pointer without checking against limit. This can only
+  // be done if it was proved earlier that the allocation will succeed.
+  void FastAllocate(int object_size, Register result, Register result_end,
+                    AllocationFlags flags);
+
+  void FastAllocate(Register object_size, Register result, Register result_end,
+                    AllocationFlags flags);
+
   // Allocate a heap number in new space with undefined value. Returns
   // tagged pointer in result register, or jumps to gc_required if new
   // space is full.
diff --git a/src/x87/assembler-x87-inl.h b/src/x87/assembler-x87-inl.h
index 802c80f..ba2a864 100644
--- a/src/x87/assembler-x87-inl.h
+++ b/src/x87/assembler-x87-inl.h
@@ -81,11 +81,6 @@
   return Assembler::target_address_at(pc_, host_);
 }
 
-Address RelocInfo::wasm_memory_reference() {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  return Memory::Address_at(pc_);
-}
-
 Address RelocInfo::target_address_address() {
   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
                               || rmode_ == EMBEDDED_OBJECT
@@ -120,21 +115,6 @@
   }
 }
 
-void RelocInfo::update_wasm_memory_reference(
-    Address old_base, Address new_base, size_t old_size, size_t new_size,
-    ICacheFlushMode icache_flush_mode) {
-  DCHECK(IsWasmMemoryReference(rmode_));
-  DCHECK(old_base <= wasm_memory_reference() &&
-         wasm_memory_reference() < old_base + old_size);
-  Address updated_reference = new_base + (wasm_memory_reference() - old_base);
-  DCHECK(new_base <= updated_reference &&
-         updated_reference < new_base + new_size);
-  Memory::Address_at(pc_) = updated_reference;
-  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
-    Assembler::FlushICache(isolate_, pc_, sizeof(int32_t));
-  }
-}
-
 Object* RelocInfo::target_object() {
   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
   return Memory::Object_at(pc_);
@@ -284,7 +264,7 @@
   }
 }
 
-
+template <typename ObjectVisitor>
 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
   RelocInfo::Mode mode = rmode();
   if (mode == RelocInfo::EMBEDDED_OBJECT) {
diff --git a/src/x87/assembler-x87.cc b/src/x87/assembler-x87.cc
index e74d770..e7e4abe 100644
--- a/src/x87/assembler-x87.cc
+++ b/src/x87/assembler-x87.cc
@@ -101,6 +101,30 @@
   return false;
 }
 
+Address RelocInfo::wasm_memory_reference() {
+  DCHECK(IsWasmMemoryReference(rmode_));
+  return Memory::Address_at(pc_);
+}
+
+Address RelocInfo::wasm_global_reference() {
+  DCHECK(IsWasmGlobalReference(rmode_));
+  return Memory::Address_at(pc_);
+}
+
+uint32_t RelocInfo::wasm_memory_size_reference() {
+  DCHECK(IsWasmMemorySizeReference(rmode_));
+  return Memory::uint32_at(pc_);
+}
+
+void RelocInfo::unchecked_update_wasm_memory_reference(
+    Address address, ICacheFlushMode flush_mode) {
+  Memory::Address_at(pc_) = address;
+}
+
+void RelocInfo::unchecked_update_wasm_memory_size(uint32_t size,
+                                                  ICacheFlushMode flush_mode) {
+  Memory::uint32_at(pc_) = size;
+}
 
 // -----------------------------------------------------------------------------
 // Implementation of Operand
@@ -223,6 +247,8 @@
   desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
   desc->origin = this;
   desc->constant_pool_size = 0;
+  desc->unwinding_info_size = 0;
+  desc->unwinding_info = nullptr;
 }
 
 
@@ -552,6 +578,45 @@
   emit_operand(dst, src);
 }
 
+void Assembler::xchg_b(Register reg, const Operand& op) {
+  EnsureSpace ensure_space(this);
+  EMIT(0x86);
+  emit_operand(reg, op);
+}
+
+void Assembler::xchg_w(Register reg, const Operand& op) {
+  EnsureSpace ensure_space(this);
+  EMIT(0x66);
+  EMIT(0x87);
+  emit_operand(reg, op);
+}
+
+void Assembler::lock() {
+  EnsureSpace ensure_space(this);
+  EMIT(0xF0);
+}
+
+void Assembler::cmpxchg(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  EMIT(0x0F);
+  EMIT(0xB1);
+  emit_operand(src, dst);
+}
+
+void Assembler::cmpxchg_b(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  EMIT(0x0F);
+  EMIT(0xB0);
+  emit_operand(src, dst);
+}
+
+void Assembler::cmpxchg_w(const Operand& dst, Register src) {
+  EnsureSpace ensure_space(this);
+  EMIT(0x66);
+  EMIT(0x0F);
+  EMIT(0xB1);
+  emit_operand(src, dst);
+}
 
 void Assembler::adc(Register dst, int32_t imm32) {
   EnsureSpace ensure_space(this);
@@ -1339,7 +1404,6 @@
 
 
 void Assembler::call(Label* L) {
-  positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
   if (L->is_bound()) {
     const int long_size = 5;
@@ -1357,7 +1421,6 @@
 
 
 void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
-  positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
   DCHECK(!RelocInfo::IsCodeTarget(rmode));
   EMIT(0xE8);
@@ -1376,7 +1439,6 @@
 
 
 void Assembler::call(const Operand& adr) {
-  positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
   EMIT(0xFF);
   emit_operand(edx, adr);
@@ -1391,7 +1453,6 @@
 void Assembler::call(Handle<Code> code,
                      RelocInfo::Mode rmode,
                      TypeFeedbackId ast_id) {
-  positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
   DCHECK(RelocInfo::IsCodeTarget(rmode)
       || rmode == RelocInfo::CODE_AGE_SEQUENCE);
diff --git a/src/x87/assembler-x87.h b/src/x87/assembler-x87.h
index 96eced9..d4cde52 100644
--- a/src/x87/assembler-x87.h
+++ b/src/x87/assembler-x87.h
@@ -74,6 +74,8 @@
   V(stX_6)                  \
   V(stX_7)
 
+#define FLOAT_REGISTERS DOUBLE_REGISTERS
+
 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \
   V(stX_0)                              \
   V(stX_1)                              \
@@ -120,8 +122,6 @@
     Register r = {code};
     return r;
   }
-  const char* ToString();
-  bool IsAllocatable() const;
   bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
   bool is(Register reg) const { return reg_code == reg.reg_code; }
   int code() const {
@@ -145,8 +145,9 @@
 #undef DECLARE_REGISTER
 const Register no_reg = {Register::kCode_no_reg};
 
+static const bool kSimpleFPAliasing = true;
 
-struct DoubleRegister {
+struct X87Register {
   enum Code {
 #define REGISTER_CODE(R) kCode_##R,
     DOUBLE_REGISTERS(REGISTER_CODE)
@@ -158,12 +159,11 @@
   static const int kMaxNumRegisters = Code::kAfterLast;
   static const int kMaxNumAllocatableRegisters = 6;
 
-  static DoubleRegister from_code(int code) {
-    DoubleRegister result = {code};
+  static X87Register from_code(int code) {
+    X87Register result = {code};
     return result;
   }
 
-  bool IsAllocatable() const;
   bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
 
   int code() const {
@@ -171,24 +171,24 @@
     return reg_code;
   }
 
-  bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
-
-  const char* ToString();
+  bool is(X87Register reg) const { return reg_code == reg.reg_code; }
 
   int reg_code;
 };
 
+typedef X87Register FloatRegister;
+
+typedef X87Register DoubleRegister;
+
+// TODO(x87) Define SIMD registers.
+typedef X87Register Simd128Register;
+
 #define DECLARE_REGISTER(R) \
   const DoubleRegister R = {DoubleRegister::kCode_##R};
 DOUBLE_REGISTERS(DECLARE_REGISTER)
 #undef DECLARE_REGISTER
 const DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg};
 
-typedef DoubleRegister X87Register;
-
-// TODO(x87) Define SIMD registers.
-typedef DoubleRegister Simd128Register;
-
 enum Condition {
   // any value < 0 is considered no_condition
   no_condition  = -1,
@@ -648,6 +648,16 @@
   // Exchange
   void xchg(Register dst, Register src);
   void xchg(Register dst, const Operand& src);
+  void xchg_b(Register reg, const Operand& op);
+  void xchg_w(Register reg, const Operand& op);
+
+  // Lock prefix
+  void lock();
+
+  // CompareExchange
+  void cmpxchg(const Operand& dst, Register src);
+  void cmpxchg_b(const Operand& dst, Register src);
+  void cmpxchg_w(const Operand& dst, Register src);
 
   // Arithmetics
   void adc(Register dst, int32_t imm32);
@@ -958,7 +968,7 @@
 
   // Record a deoptimization reason that can be used by a log or cpu profiler.
   // Use --trace-deopt to enable.
-  void RecordDeoptReason(const int reason, int raw_position);
+  void RecordDeoptReason(const int reason, int raw_position, int id);
 
   // Writes a single byte or word of data in the code stream.  Used for
   // inline tables, e.g., jump-tables.
diff --git a/src/x87/builtins-x87.cc b/src/x87/builtins-x87.cc
index 9e13172..0600f0d 100644
--- a/src/x87/builtins-x87.cc
+++ b/src/x87/builtins-x87.cc
@@ -16,10 +16,7 @@
 
 #define __ ACCESS_MASM(masm)
 
-
-void Builtins::Generate_Adaptor(MacroAssembler* masm,
-                                CFunctionId id,
-                                BuiltinExtraArguments extra_args) {
+void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
   // ----------- S t a t e -------------
   //  -- eax                : number of arguments excluding receiver
   //  -- edi                : target
@@ -39,19 +36,11 @@
   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
 
   // Insert extra arguments.
-  int num_extra_args = 0;
-  if (extra_args != BuiltinExtraArguments::kNone) {
-    __ PopReturnAddressTo(ecx);
-    if (extra_args & BuiltinExtraArguments::kTarget) {
-      ++num_extra_args;
-      __ Push(edi);
-    }
-    if (extra_args & BuiltinExtraArguments::kNewTarget) {
-      ++num_extra_args;
-      __ Push(edx);
-    }
-    __ PushReturnAddressFrom(ecx);
-  }
+  const int num_extra_args = 2;
+  __ PopReturnAddressTo(ecx);
+  __ Push(edi);
+  __ Push(edx);
+  __ PushReturnAddressFrom(ecx);
 
   // JumpToExternalReference expects eax to contain the number of arguments
   // including the receiver and the extra arguments.
@@ -186,16 +175,9 @@
     __ j(greater_equal, &loop);
 
     // Call the function.
-    if (is_api_function) {
-      __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
-      Handle<Code> code =
-          masm->isolate()->builtins()->HandleApiCallConstruct();
-      __ call(code, RelocInfo::CODE_TARGET);
-    } else {
-      ParameterCount actual(eax);
-      __ InvokeFunction(edi, edx, actual, CALL_FUNCTION,
-                        CheckDebugStepCallWrapper());
-    }
+    ParameterCount actual(eax);
+    __ InvokeFunction(edi, edx, actual, CALL_FUNCTION,
+                      CheckDebugStepCallWrapper());
 
     // Store offset of return address for deoptimizer.
     if (create_implicit_receiver && !is_api_function) {
@@ -392,6 +374,184 @@
   Generate_JSEntryTrampolineHelper(masm, true);
 }
 
+// static
+void Builtins::Generate_ResumeGeneratorTrampoline(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- eax    : the value to pass to the generator
+  //  -- ebx    : the JSGeneratorObject to resume
+  //  -- edx    : the resume mode (tagged)
+  //  -- esp[0] : return address
+  // -----------------------------------
+  __ AssertGeneratorObject(ebx);
+
+  // Store input value into generator object.
+  __ mov(FieldOperand(ebx, JSGeneratorObject::kInputOrDebugPosOffset), eax);
+  __ RecordWriteField(ebx, JSGeneratorObject::kInputOrDebugPosOffset, eax, ecx,
+                      kDontSaveFPRegs);
+
+  // Store resume mode into generator object.
+  __ mov(FieldOperand(ebx, JSGeneratorObject::kResumeModeOffset), edx);
+
+  // Load suspended function and context.
+  __ mov(esi, FieldOperand(ebx, JSGeneratorObject::kContextOffset));
+  __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset));
+
+  // Flood function if we are stepping.
+  Label prepare_step_in_if_stepping, prepare_step_in_suspended_generator;
+  Label stepping_prepared;
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(masm->isolate());
+  STATIC_ASSERT(StepFrame > StepIn);
+  __ cmpb(Operand::StaticVariable(last_step_action), Immediate(StepIn));
+  __ j(greater_equal, &prepare_step_in_if_stepping);
+
+  // Flood function if we need to continue stepping in the suspended generator.
+  ExternalReference debug_suspended_generator =
+      ExternalReference::debug_suspended_generator_address(masm->isolate());
+  __ cmp(ebx, Operand::StaticVariable(debug_suspended_generator));
+  __ j(equal, &prepare_step_in_suspended_generator);
+  __ bind(&stepping_prepared);
+
+  // Pop return address.
+  __ PopReturnAddressTo(eax);
+
+  // Push receiver.
+  __ Push(FieldOperand(ebx, JSGeneratorObject::kReceiverOffset));
+
+  // ----------- S t a t e -------------
+  //  -- eax    : return address
+  //  -- ebx    : the JSGeneratorObject to resume
+  //  -- edx    : the resume mode (tagged)
+  //  -- edi    : generator function
+  //  -- esi    : generator context
+  //  -- esp[0] : generator receiver
+  // -----------------------------------
+
+  // Push holes for arguments to generator function. Since the parser forced
+  // context allocation for any variables in generators, the actual argument
+  // values have already been copied into the context and these dummy values
+  // will never be used.
+  __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+  __ mov(ecx,
+         FieldOperand(ecx, SharedFunctionInfo::kFormalParameterCountOffset));
+  {
+    Label done_loop, loop;
+    __ bind(&loop);
+    __ sub(ecx, Immediate(Smi::FromInt(1)));
+    __ j(carry, &done_loop, Label::kNear);
+    __ PushRoot(Heap::kTheHoleValueRootIndex);
+    __ jmp(&loop);
+    __ bind(&done_loop);
+  }
+
+  // Dispatch on the kind of generator object.
+  Label old_generator;
+  __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+  __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kFunctionDataOffset));
+  __ CmpObjectType(ecx, BYTECODE_ARRAY_TYPE, ecx);
+  __ j(not_equal, &old_generator);
+
+  // New-style (ignition/turbofan) generator object
+  {
+    __ PushReturnAddressFrom(eax);
+    __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+    __ mov(eax,
+           FieldOperand(ecx, SharedFunctionInfo::kFormalParameterCountOffset));
+    // We abuse new.target both to indicate that this is a resume call and to
+    // pass in the generator object.  In ordinary calls, new.target is always
+    // undefined because generator functions are non-constructable.
+    __ mov(edx, ebx);
+    __ jmp(FieldOperand(edi, JSFunction::kCodeEntryOffset));
+  }
+
+  // Old-style (full-codegen) generator object
+  __ bind(&old_generator);
+  {
+    // Enter a new JavaScript frame, and initialize its slots as they were when
+    // the generator was suspended.
+    FrameScope scope(masm, StackFrame::MANUAL);
+    __ PushReturnAddressFrom(eax);  // Return address.
+    __ Push(ebp);                   // Caller's frame pointer.
+    __ Move(ebp, esp);
+    __ Push(esi);  // Callee's context.
+    __ Push(edi);  // Callee's JS Function.
+
+    // Restore the operand stack.
+    __ mov(eax, FieldOperand(ebx, JSGeneratorObject::kOperandStackOffset));
+    {
+      Label done_loop, loop;
+      __ Move(ecx, Smi::FromInt(0));
+      __ bind(&loop);
+      __ cmp(ecx, FieldOperand(eax, FixedArray::kLengthOffset));
+      __ j(equal, &done_loop, Label::kNear);
+      __ Push(FieldOperand(eax, ecx, times_half_pointer_size,
+                           FixedArray::kHeaderSize));
+      __ add(ecx, Immediate(Smi::FromInt(1)));
+      __ jmp(&loop);
+      __ bind(&done_loop);
+    }
+
+    // Reset operand stack so we don't leak.
+    __ mov(FieldOperand(ebx, JSGeneratorObject::kOperandStackOffset),
+           Immediate(masm->isolate()->factory()->empty_fixed_array()));
+
+    // Resume the generator function at the continuation.
+    __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+    __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));
+    __ mov(ecx, FieldOperand(ebx, JSGeneratorObject::kContinuationOffset));
+    __ SmiUntag(ecx);
+    __ lea(edx, FieldOperand(edx, ecx, times_1, Code::kHeaderSize));
+    __ mov(FieldOperand(ebx, JSGeneratorObject::kContinuationOffset),
+           Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
+    __ mov(eax, ebx);  // Continuation expects generator object in eax.
+    __ jmp(edx);
+  }
+
+  __ bind(&prepare_step_in_if_stepping);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ Push(ebx);
+    __ Push(edx);
+    __ Push(edi);
+    __ CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
+    __ Pop(edx);
+    __ Pop(ebx);
+    __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset));
+  }
+  __ jmp(&stepping_prepared);
+
+  __ bind(&prepare_step_in_suspended_generator);
+  {
+    FrameScope scope(masm, StackFrame::INTERNAL);
+    __ Push(ebx);
+    __ Push(edx);
+    __ CallRuntime(Runtime::kDebugPrepareStepInSuspendedGenerator);
+    __ Pop(edx);
+    __ Pop(ebx);
+    __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset));
+  }
+  __ jmp(&stepping_prepared);
+}
+
+static void LeaveInterpreterFrame(MacroAssembler* masm, Register scratch1,
+                                  Register scratch2) {
+  Register args_count = scratch1;
+  Register return_pc = scratch2;
+
+  // Get the arguments + reciever count.
+  __ mov(args_count,
+         Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp));
+  __ mov(args_count,
+         FieldOperand(args_count, BytecodeArray::kParameterSizeOffset));
+
+  // Leave the frame (also dropping the register file).
+  __ leave();
+
+  // Drop receiver + arguments.
+  __ pop(return_pc);
+  __ add(esp, args_count);
+  __ push(return_pc);
+}
 
 // Generate code for entering a JS function with the interpreter.
 // On entry to the function the receiver and arguments have been pushed on the
@@ -408,6 +568,8 @@
 // The function builds an interpreter frame.  See InterpreterFrameConstants in
 // frames.h for its layout.
 void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
+  ProfileEntryHookStub::MaybeCallEntryHook(masm);
+
   // Open a frame scope to indicate that there is a frame on the stack.  The
   // MANUAL indicates that the scope shouldn't actually generate code to set up
   // the frame (that is done below).
@@ -418,10 +580,9 @@
   __ push(edi);  // Callee's JS function.
   __ push(edx);  // Callee's new target.
 
-  // Get the bytecode array from the function object and load the pointer to the
-  // first entry into edi (InterpreterBytecodeRegister).
+  // Get the bytecode array from the function object (or from the DebugInfo if
+  // it is present) and load it into kInterpreterBytecodeArrayRegister.
   __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
-
   Label load_debug_bytecode_array, bytecode_array_loaded;
   __ cmp(FieldOperand(eax, SharedFunctionInfo::kDebugInfoOffset),
          Immediate(DebugInfo::uninitialized()));
@@ -430,8 +591,12 @@
          FieldOperand(eax, SharedFunctionInfo::kFunctionDataOffset));
   __ bind(&bytecode_array_loaded);
 
+  // Check function data field is actually a BytecodeArray object.
+  Label bytecode_array_not_present;
+  __ CompareRoot(kInterpreterBytecodeArrayRegister,
+                 Heap::kUndefinedValueRootIndex);
+  __ j(equal, &bytecode_array_not_present);
   if (FLAG_debug_code) {
-    // Check function data field is actually a BytecodeArray object.
     __ AssertNotSmi(kInterpreterBytecodeArrayRegister);
     __ CmpObjectType(kInterpreterBytecodeArrayRegister, BYTECODE_ARRAY_TYPE,
                      eax);
@@ -440,8 +605,8 @@
 
   // Push bytecode array.
   __ push(kInterpreterBytecodeArrayRegister);
-  // Push zero for bytecode array offset.
-  __ push(Immediate(0));
+  // Push Smi tagged initial bytecode array offset.
+  __ push(Immediate(Smi::FromInt(BytecodeArray::kHeaderSize - kHeapObjectTag)));
 
   // Allocate the local and temporary register file on the stack.
   {
@@ -474,41 +639,25 @@
     __ j(greater_equal, &loop_header);
   }
 
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's prologue:
-  //  - Call ProfileEntryHookStub when isolate has a function_entry_hook.
-  //  - Code aging of the BytecodeArray object.
-
-  // Load accumulator, register file, bytecode offset, dispatch table into
-  // registers.
+  // Load accumulator, bytecode offset and dispatch table into registers.
   __ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
-  __ mov(kInterpreterRegisterFileRegister, ebp);
-  __ add(kInterpreterRegisterFileRegister,
-         Immediate(InterpreterFrameConstants::kRegisterFilePointerFromFp));
   __ mov(kInterpreterBytecodeOffsetRegister,
          Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
-  __ mov(ebx, Immediate(ExternalReference::interpreter_dispatch_table_address(
-                  masm->isolate())));
-
-  // Push dispatch table as a stack located parameter to the bytecode handler.
-  DCHECK_EQ(-1, kInterpreterDispatchTableSpillSlot);
-  __ push(ebx);
+  __ mov(kInterpreterDispatchTableRegister,
+         Immediate(ExternalReference::interpreter_dispatch_table_address(
+             masm->isolate())));
 
   // Dispatch to the first bytecode handler for the function.
-  __ movzx_b(eax, Operand(kInterpreterBytecodeArrayRegister,
+  __ movzx_b(ebx, Operand(kInterpreterBytecodeArrayRegister,
                           kInterpreterBytecodeOffsetRegister, times_1, 0));
-  __ mov(ebx, Operand(ebx, eax, times_pointer_size, 0));
-  // Restore undefined_value in accumulator (eax)
-  // TODO(rmcilroy): Remove this once we move the dispatch table back into a
-  // register.
-  __ mov(eax, Immediate(masm->isolate()->factory()->undefined_value()));
-  // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
-  // and header removal.
-  __ add(ebx, Immediate(Code::kHeaderSize - kHeapObjectTag));
+  __ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx,
+                      times_pointer_size, 0));
   __ call(ebx);
+  masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
 
-  // Even though the first bytecode handler was called, we will never return.
-  __ Abort(kUnexpectedReturnFromBytecodeHandler);
+  // The return value is in eax.
+  LeaveInterpreterFrame(masm, ebx, ecx);
+  __ ret(0);
 
   // Load debug copy of the bytecode array.
   __ bind(&load_debug_bytecode_array);
@@ -517,31 +666,48 @@
   __ mov(kInterpreterBytecodeArrayRegister,
          FieldOperand(debug_info, DebugInfo::kAbstractCodeIndex));
   __ jmp(&bytecode_array_loaded);
+
+  // If the bytecode array is no longer present, then the underlying function
+  // has been switched to a different kind of code and we heal the closure by
+  // switching the code entry field over to the new code object as well.
+  __ bind(&bytecode_array_not_present);
+  __ pop(edx);  // Callee's new target.
+  __ pop(edi);  // Callee's JS function.
+  __ pop(esi);  // Callee's context.
+  __ leave();   // Leave the frame so we can tail call.
+  __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+  __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kCodeOffset));
+  __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize));
+  __ mov(FieldOperand(edi, JSFunction::kCodeEntryOffset), ecx);
+  __ RecordWriteCodeEntryField(edi, ecx, ebx);
+  __ jmp(ecx);
 }
 
+void Builtins::Generate_InterpreterMarkBaselineOnReturn(MacroAssembler* masm) {
+  // Save the function and context for call to CompileBaseline.
+  __ mov(edi, Operand(ebp, StandardFrameConstants::kFunctionOffset));
+  __ mov(kContextRegister,
+         Operand(ebp, StandardFrameConstants::kContextOffset));
 
-void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
-  // TODO(rmcilroy): List of things not currently dealt with here but done in
-  // fullcodegen's EmitReturnSequence.
-  //  - Supporting FLAG_trace for Runtime::TraceExit.
-  //  - Support profiler (specifically decrementing profiling_counter
-  //    appropriately and calling out to HandleInterrupts if necessary).
+  // Leave the frame before recompiling for baseline so that we don't count as
+  // an activation on the stack.
+  LeaveInterpreterFrame(masm, ebx, ecx);
 
-  // The return value is in accumulator, which is already in rax.
+  {
+    FrameScope frame_scope(masm, StackFrame::INTERNAL);
+    // Push return value.
+    __ push(eax);
 
-  // Leave the frame (also dropping the register file).
-  __ leave();
+    // Push function as argument and compile for baseline.
+    __ push(edi);
+    __ CallRuntime(Runtime::kCompileBaseline);
 
-  // Drop receiver + arguments and return.
-  __ mov(ebx, FieldOperand(kInterpreterBytecodeArrayRegister,
-                           BytecodeArray::kParameterSizeOffset));
-  __ pop(ecx);
-  __ add(esp, ebx);
-  __ push(ecx);
+    // Restore return value.
+    __ pop(eax);
+  }
   __ ret(0);
 }
 
-
 static void Generate_InterpreterPushArgs(MacroAssembler* masm,
                                          Register array_limit) {
   // ----------- S t a t e -------------
@@ -559,7 +725,6 @@
   __ j(greater, &loop_header, Label::kNear);
 }
 
-
 // static
 void Builtins::Generate_InterpreterPushArgsAndCallImpl(
     MacroAssembler* masm, TailCallMode tail_call_mode) {
@@ -628,17 +793,26 @@
   __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
 }
 
+void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
+  // Set the return address to the correct point in the interpreter entry
+  // trampoline.
+  Smi* interpreter_entry_return_pc_offset(
+      masm->isolate()->heap()->interpreter_entry_return_pc_offset());
+  DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
+  __ LoadHeapObject(ebx,
+                    masm->isolate()->builtins()->InterpreterEntryTrampoline());
+  __ add(ebx, Immediate(interpreter_entry_return_pc_offset->value() +
+                        Code::kHeaderSize - kHeapObjectTag));
+  __ push(ebx);
 
-static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
-  // Initialize register file register.
-  __ mov(kInterpreterRegisterFileRegister, ebp);
-  __ add(kInterpreterRegisterFileRegister,
-         Immediate(InterpreterFrameConstants::kRegisterFilePointerFromFp));
+  // Initialize the dispatch table register.
+  __ mov(kInterpreterDispatchTableRegister,
+         Immediate(ExternalReference::interpreter_dispatch_table_address(
+             masm->isolate())));
 
   // Get the bytecode array pointer from the frame.
   __ mov(kInterpreterBytecodeArrayRegister,
-         Operand(kInterpreterRegisterFileRegister,
-                 InterpreterFrameConstants::kBytecodeArrayFromRegisterPointer));
+         Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp));
 
   if (FLAG_debug_code) {
     // Check function data field is actually a BytecodeArray object.
@@ -649,92 +823,190 @@
   }
 
   // Get the target bytecode offset from the frame.
-  __ mov(
-      kInterpreterBytecodeOffsetRegister,
-      Operand(kInterpreterRegisterFileRegister,
-              InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
+  __ mov(kInterpreterBytecodeOffsetRegister,
+         Operand(ebp, InterpreterFrameConstants::kBytecodeOffsetFromFp));
   __ SmiUntag(kInterpreterBytecodeOffsetRegister);
 
-  // Push dispatch table as a stack located parameter to the bytecode handler.
-  __ mov(ebx, Immediate(ExternalReference::interpreter_dispatch_table_address(
-                  masm->isolate())));
-  DCHECK_EQ(-1, kInterpreterDispatchTableSpillSlot);
-  __ Pop(esi);
-  __ Push(ebx);
-  __ Push(esi);
-
   // Dispatch to the target bytecode.
-  __ movzx_b(esi, Operand(kInterpreterBytecodeArrayRegister,
+  __ movzx_b(ebx, Operand(kInterpreterBytecodeArrayRegister,
                           kInterpreterBytecodeOffsetRegister, times_1, 0));
-  __ mov(ebx, Operand(ebx, esi, times_pointer_size, 0));
-
-  // Get the context from the frame.
-  __ mov(kContextRegister,
-         Operand(kInterpreterRegisterFileRegister,
-                 InterpreterFrameConstants::kContextFromRegisterPointer));
-
-  // TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
-  // and header removal.
-  __ add(ebx, Immediate(Code::kHeaderSize - kHeapObjectTag));
+  __ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx,
+                      times_pointer_size, 0));
   __ jmp(ebx);
 }
 
-
-static void Generate_InterpreterNotifyDeoptimizedHelper(
-    MacroAssembler* masm, Deoptimizer::BailoutType type) {
-  // Enter an internal frame.
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Pass the deoptimization type to the runtime system.
-    __ Push(Smi::FromInt(static_cast<int>(type)));
-    __ CallRuntime(Runtime::kNotifyDeoptimized);
-    // Tear down internal frame.
-  }
-
-  // Drop state (we don't use these for interpreter deopts) and and pop the
-  // accumulator value into the accumulator register and push PC at top
-  // of stack (to simulate initial call to bytecode handler in interpreter entry
-  // trampoline).
-  __ Pop(ebx);
-  __ Drop(1);
-  __ Pop(kInterpreterAccumulatorRegister);
-  __ Push(ebx);
-
-  // Enter the bytecode dispatch.
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-
-void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
-}
-
-
-void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
-}
-
-
-void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
-  Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
-}
-
-void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
-  // Set the address of the interpreter entry trampoline as a return address.
-  // This simulates the initial call to bytecode handlers in interpreter entry
-  // trampoline. The return will never actually be taken, but our stack walker
-  // uses this address to determine whether a frame is interpreted.
-  __ Push(masm->isolate()->builtins()->InterpreterEntryTrampoline());
-
-  Generate_EnterBytecodeDispatch(masm);
-}
-
-
 void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- eax : argument count (preserved for callee)
+  //  -- edx : new target (preserved for callee)
+  //  -- edi : target function (preserved for callee)
+  // -----------------------------------
+  // First lookup code, maybe we don't need to compile!
+  Label gotta_call_runtime, gotta_call_runtime_no_stack;
+  Label maybe_call_runtime;
+  Label try_shared;
+  Label loop_top, loop_bottom;
+
+  Register closure = edi;
+  Register new_target = edx;
+  Register argument_count = eax;
+
+  __ push(argument_count);
+  __ push(new_target);
+  __ push(closure);
+
+  Register map = argument_count;
+  Register index = ebx;
+  __ mov(map, FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ mov(map, FieldOperand(map, SharedFunctionInfo::kOptimizedCodeMapOffset));
+  __ mov(index, FieldOperand(map, FixedArray::kLengthOffset));
+  __ cmp(index, Immediate(Smi::FromInt(2)));
+  __ j(less, &gotta_call_runtime);
+
+  // Find literals.
+  // edx : native context
+  // ebx : length / index
+  // eax : optimized code map
+  // stack[0] : new target
+  // stack[4] : closure
+  Register native_context = edx;
+  __ mov(native_context, NativeContextOperand());
+
+  __ bind(&loop_top);
+  Register temp = edi;
+
+  // Does the native context match?
+  __ mov(temp, FieldOperand(map, index, times_half_pointer_size,
+                            SharedFunctionInfo::kOffsetToPreviousContext));
+  __ mov(temp, FieldOperand(temp, WeakCell::kValueOffset));
+  __ cmp(temp, native_context);
+  __ j(not_equal, &loop_bottom);
+  // OSR id set to none?
+  __ mov(temp, FieldOperand(map, index, times_half_pointer_size,
+                            SharedFunctionInfo::kOffsetToPreviousOsrAstId));
+  const int bailout_id = BailoutId::None().ToInt();
+  __ cmp(temp, Immediate(Smi::FromInt(bailout_id)));
+  __ j(not_equal, &loop_bottom);
+
+  // Literals available?
+  Label got_literals, maybe_cleared_weakcell;
+  __ mov(temp, FieldOperand(map, index, times_half_pointer_size,
+                            SharedFunctionInfo::kOffsetToPreviousLiterals));
+
+  // temp contains either a WeakCell pointing to the literals array or the
+  // literals array directly.
+  STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
+  __ JumpIfSmi(FieldOperand(temp, WeakCell::kValueOffset),
+               &maybe_cleared_weakcell);
+  // The WeakCell value is a pointer, therefore it's a valid literals array.
+  __ mov(temp, FieldOperand(temp, WeakCell::kValueOffset));
+  __ jmp(&got_literals);
+
+  // We have a smi. If it's 0, then we are looking at a cleared WeakCell
+  // around the literals array, and we should visit the runtime. If it's > 0,
+  // then temp already contains the literals array.
+  __ bind(&maybe_cleared_weakcell);
+  __ cmp(FieldOperand(temp, WeakCell::kValueOffset), Immediate(0));
+  __ j(equal, &gotta_call_runtime);
+
+  // Save the literals in the closure.
+  __ bind(&got_literals);
+  __ mov(ecx, Operand(esp, 0));
+  __ mov(FieldOperand(ecx, JSFunction::kLiteralsOffset), temp);
+  __ push(index);
+  __ RecordWriteField(ecx, JSFunction::kLiteralsOffset, temp, index,
+                      kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+  __ pop(index);
+
+  // Code available?
+  Register entry = ecx;
+  __ mov(entry, FieldOperand(map, index, times_half_pointer_size,
+                             SharedFunctionInfo::kOffsetToPreviousCachedCode));
+  __ mov(entry, FieldOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &maybe_call_runtime);
+
+  // Found literals and code. Get them into the closure and return.
+  __ pop(closure);
+  // Store code entry in the closure.
+  __ lea(entry, FieldOperand(entry, Code::kHeaderSize));
+
+  Label install_optimized_code_and_tailcall;
+  __ bind(&install_optimized_code_and_tailcall);
+  __ mov(FieldOperand(closure, JSFunction::kCodeEntryOffset), entry);
+  __ RecordWriteCodeEntryField(closure, entry, eax);
+
+  // Link the closure into the optimized function list.
+  // ecx : code entry
+  // edx : native context
+  // edi : closure
+  __ mov(ebx,
+         ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST));
+  __ mov(FieldOperand(closure, JSFunction::kNextFunctionLinkOffset), ebx);
+  __ RecordWriteField(closure, JSFunction::kNextFunctionLinkOffset, ebx, eax,
+                      kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+  const int function_list_offset =
+      Context::SlotOffset(Context::OPTIMIZED_FUNCTIONS_LIST);
+  __ mov(ContextOperand(native_context, Context::OPTIMIZED_FUNCTIONS_LIST),
+         closure);
+  // Save closure before the write barrier.
+  __ mov(ebx, closure);
+  __ RecordWriteContextSlot(native_context, function_list_offset, closure, eax,
+                            kDontSaveFPRegs);
+  __ mov(closure, ebx);
+  __ pop(new_target);
+  __ pop(argument_count);
+  __ jmp(entry);
+
+  __ bind(&loop_bottom);
+  __ sub(index, Immediate(Smi::FromInt(SharedFunctionInfo::kEntryLength)));
+  __ cmp(index, Immediate(Smi::FromInt(1)));
+  __ j(greater, &loop_top);
+
+  // We found neither literals nor code.
+  __ jmp(&gotta_call_runtime);
+
+  __ bind(&maybe_call_runtime);
+  __ pop(closure);
+
+  // Last possibility. Check the context free optimized code map entry.
+  __ mov(entry, FieldOperand(map, FixedArray::kHeaderSize +
+                                      SharedFunctionInfo::kSharedCodeIndex));
+  __ mov(entry, FieldOperand(entry, WeakCell::kValueOffset));
+  __ JumpIfSmi(entry, &try_shared);
+
+  // Store code entry in the closure.
+  __ lea(entry, FieldOperand(entry, Code::kHeaderSize));
+  __ jmp(&install_optimized_code_and_tailcall);
+
+  __ bind(&try_shared);
+  __ pop(new_target);
+  __ pop(argument_count);
+  // Is the full code valid?
+  __ mov(entry, FieldOperand(closure, JSFunction::kSharedFunctionInfoOffset));
+  __ mov(entry, FieldOperand(entry, SharedFunctionInfo::kCodeOffset));
+  __ mov(ebx, FieldOperand(entry, Code::kFlagsOffset));
+  __ and_(ebx, Code::KindField::kMask);
+  __ shr(ebx, Code::KindField::kShift);
+  __ cmp(ebx, Immediate(Code::BUILTIN));
+  __ j(equal, &gotta_call_runtime_no_stack);
+  // Yes, install the full code.
+  __ lea(entry, FieldOperand(entry, Code::kHeaderSize));
+  __ mov(FieldOperand(closure, JSFunction::kCodeEntryOffset), entry);
+  __ RecordWriteCodeEntryField(closure, entry, ebx);
+  __ jmp(entry);
+
+  __ bind(&gotta_call_runtime);
+  __ pop(closure);
+  __ pop(new_target);
+  __ pop(argument_count);
+  __ bind(&gotta_call_runtime_no_stack);
+
   GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy);
 }
 
+void Builtins::Generate_CompileBaseline(MacroAssembler* masm) {
+  GenerateTailCallToReturnedCode(masm, Runtime::kCompileBaseline);
+}
 
 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) {
   GenerateTailCallToReturnedCode(masm,
@@ -876,13 +1148,14 @@
 
   // Switch on the state.
   Label not_no_registers, not_tos_eax;
-  __ cmp(ecx, FullCodeGenerator::NO_REGISTERS);
+  __ cmp(ecx, static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS));
   __ j(not_equal, &not_no_registers, Label::kNear);
   __ ret(1 * kPointerSize);  // Remove state.
 
   __ bind(&not_no_registers);
+  DCHECK_EQ(kInterpreterAccumulatorRegister.code(), eax.code());
   __ mov(eax, Operand(esp, 2 * kPointerSize));
-  __ cmp(ecx, FullCodeGenerator::TOS_REG);
+  __ cmp(ecx, static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER));
   __ j(not_equal, &not_tos_eax, Label::kNear);
   __ ret(2 * kPointerSize);  // Remove state, eax.
 
@@ -910,6 +1183,9 @@
 void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
                                                int field_index) {
   // ----------- S t a t e -------------
+  //  -- eax    : number of arguments
+  //  -- edi    : function
+  //  -- esi    : context
   //  -- esp[0] : return address
   //  -- esp[4] : receiver
   // -----------------------------------
@@ -952,35 +1228,16 @@
   __ bind(&receiver_not_date);
   {
     FrameScope scope(masm, StackFrame::MANUAL);
-    __ EnterFrame(StackFrame::INTERNAL);
+    __ Push(ebp);
+    __ Move(ebp, esp);
+    __ Push(esi);
+    __ Push(edi);
+    __ Push(Immediate(0));
     __ CallRuntime(Runtime::kThrowNotDateError);
   }
 }
 
 // static
-void Builtins::Generate_FunctionHasInstance(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- eax    : argc
-  //  -- esp[0] : return address
-  //  -- esp[4] : first argument (left-hand side)
-  //  -- esp[8] : receiver (right-hand side)
-  // -----------------------------------
-
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-    __ mov(InstanceOfDescriptor::LeftRegister(),
-           Operand(ebp, 2 * kPointerSize));  // Load left-hand side.
-    __ mov(InstanceOfDescriptor::RightRegister(),
-           Operand(ebp, 3 * kPointerSize));  // Load right-hand side.
-    InstanceOfStub stub(masm->isolate(), true);
-    __ CallStub(&stub);
-  }
-
-  // Pop the argument and the receiver.
-  __ ret(2 * kPointerSize);
-}
-
-// static
 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
   // ----------- S t a t e -------------
   //  -- eax     : argc
@@ -1309,6 +1566,8 @@
 void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) {
   // ----------- S t a t e -------------
   //  -- eax                 : number of arguments
+  //  -- edi                 : function
+  //  -- esi                 : context
   //  -- esp[0]              : return address
   //  -- esp[(argc - n) * 8] : arg[n] (zero-based)
   //  -- esp[(argc + 1) * 8] : receiver
@@ -1336,27 +1595,32 @@
     __ mov(ebx, Operand(esp, ecx, times_pointer_size, 0));
 
     // Load the double value of the parameter into stx_1, maybe converting the
-    // parameter to a number first using the ToNumberStub if necessary.
+    // parameter to a number first using the ToNumber builtin if necessary.
     Label convert, convert_smi, convert_number, done_convert;
     __ bind(&convert);
     __ JumpIfSmi(ebx, &convert_smi);
     __ JumpIfRoot(FieldOperand(ebx, HeapObject::kMapOffset),
                   Heap::kHeapNumberMapRootIndex, &convert_number);
     {
-      // Parameter is not a Number, use the ToNumberStub to convert it.
-      FrameScope scope(masm, StackFrame::INTERNAL);
+      // Parameter is not a Number, use the ToNumber builtin to convert it.
+      FrameScope scope(masm, StackFrame::MANUAL);
+      __ Push(ebp);
+      __ Move(ebp, esp);
+      __ Push(esi);
+      __ Push(edi);
       __ SmiTag(eax);
       __ SmiTag(ecx);
       __ Push(eax);
       __ Push(ecx);
       __ Push(edx);
       __ mov(eax, ebx);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
       __ mov(ebx, eax);
       __ Pop(edx);
       __ Pop(ecx);
       __ Pop(eax);
+      __ Pop(edi);
+      __ Pop(esi);
       {
         // Restore the double accumulator value (stX_0).
         Label restore_smi, done_restore;
@@ -1373,6 +1637,7 @@
       }
       __ SmiUntag(ecx);
       __ SmiUntag(eax);
+      __ leave();
     }
     __ jmp(&convert);
     __ bind(&convert_number);
@@ -1463,8 +1728,7 @@
   }
 
   // 2a. Convert the first argument to a number.
-  ToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
+  __ Jump(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
 
   // 2b. No arguments, return +0 (already in eax).
   __ bind(&no_arguments);
@@ -1514,8 +1778,7 @@
       __ Push(edi);
       __ Push(edx);
       __ Move(eax, ebx);
-      ToNumberStub stub(masm->isolate());
-      __ CallStub(&stub);
+      __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
       __ Move(ebx, eax);
       __ Pop(edx);
       __ Pop(edi);
@@ -2385,6 +2648,109 @@
           RelocInfo::CODE_TARGET);
 }
 
+// static
+void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- edx    : requested object size (untagged)
+  //  -- esp[0] : return address
+  // -----------------------------------
+  __ SmiTag(edx);
+  __ PopReturnAddressTo(ecx);
+  __ Push(edx);
+  __ PushReturnAddressFrom(ecx);
+  __ Move(esi, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInNewSpace);
+}
+
+// static
+void Builtins::Generate_AllocateInOldSpace(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- edx    : requested object size (untagged)
+  //  -- esp[0] : return address
+  // -----------------------------------
+  __ SmiTag(edx);
+  __ PopReturnAddressTo(ecx);
+  __ Push(edx);
+  __ Push(Smi::FromInt(AllocateTargetSpace::encode(OLD_SPACE)));
+  __ PushReturnAddressFrom(ecx);
+  __ Move(esi, Smi::FromInt(0));
+  __ TailCallRuntime(Runtime::kAllocateInTargetSpace);
+}
+
+// static
+void Builtins::Generate_StringToNumber(MacroAssembler* masm) {
+  // The StringToNumber stub takes one argument in eax.
+  __ AssertString(eax);
+
+  // Check if string has a cached array index.
+  Label runtime;
+  __ test(FieldOperand(eax, String::kHashFieldOffset),
+          Immediate(String::kContainsCachedArrayIndexMask));
+  __ j(not_zero, &runtime, Label::kNear);
+  __ mov(eax, FieldOperand(eax, String::kHashFieldOffset));
+  __ IndexFromHash(eax, eax);
+  __ Ret();
+
+  __ bind(&runtime);
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ push(eax);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kStringToNumber);
+  }
+  __ Ret();
+}
+
+// static
+void Builtins::Generate_ToNumber(MacroAssembler* masm) {
+  // The ToNumber stub takes one argument in eax.
+  Label not_smi;
+  __ JumpIfNotSmi(eax, &not_smi, Label::kNear);
+  __ Ret();
+  __ bind(&not_smi);
+
+  Label not_heap_number;
+  __ CompareMap(eax, masm->isolate()->factory()->heap_number_map());
+  __ j(not_equal, &not_heap_number, Label::kNear);
+  __ Ret();
+  __ bind(&not_heap_number);
+
+  __ Jump(masm->isolate()->builtins()->NonNumberToNumber(),
+          RelocInfo::CODE_TARGET);
+}
+
+// static
+void Builtins::Generate_NonNumberToNumber(MacroAssembler* masm) {
+  // The NonNumberToNumber stub takes one argument in eax.
+  __ AssertNotNumber(eax);
+
+  Label not_string;
+  __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edi);
+  // eax: object
+  // edi: object map
+  __ j(above_equal, &not_string, Label::kNear);
+  __ Jump(masm->isolate()->builtins()->StringToNumber(),
+          RelocInfo::CODE_TARGET);
+  __ bind(&not_string);
+
+  Label not_oddball;
+  __ CmpInstanceType(edi, ODDBALL_TYPE);
+  __ j(not_equal, &not_oddball, Label::kNear);
+  __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset));
+  __ Ret();
+  __ bind(&not_oddball);
+  {
+    FrameScope frame(masm, StackFrame::INTERNAL);
+    // Push argument.
+    __ push(eax);
+    // We cannot use a tail call here because this builtin can also be called
+    // from wasm.
+    __ CallRuntime(Runtime::kToNumber);
+  }
+  __ Ret();
+}
 
 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
   // ----------- S t a t e -------------
diff --git a/src/x87/code-stubs-x87.cc b/src/x87/code-stubs-x87.cc
index 71adfd3..7b069ac 100644
--- a/src/x87/code-stubs-x87.cc
+++ b/src/x87/code-stubs-x87.cc
@@ -22,67 +22,16 @@
 namespace v8 {
 namespace internal {
 
+#define __ ACCESS_MASM(masm)
 
-static void InitializeArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  // register state
-  // eax -- number of arguments
-  // edi -- function
-  // ebx -- allocation site with elements kind
-  Address deopt_handler = Runtime::FunctionForId(
-      Runtime::kArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(eax, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-
-static void InitializeInternalArrayConstructorDescriptor(
-    Isolate* isolate, CodeStubDescriptor* descriptor,
-    int constant_stack_parameter_count) {
-  // register state
-  // eax -- number of arguments
-  // edi -- constructor function
-  Address deopt_handler = Runtime::FunctionForId(
-      Runtime::kInternalArrayConstructor)->entry;
-
-  if (constant_stack_parameter_count == 0) {
-    descriptor->Initialize(deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  } else {
-    descriptor->Initialize(eax, deopt_handler, constant_stack_parameter_count,
-                           JS_FUNCTION_STUB_MODE);
-  }
-}
-
-
-void ArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 0);
-}
-
-
-void ArraySingleArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, 1);
-}
-
-
-void ArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-void InternalArrayNoArgumentConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0);
+void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
+  __ pop(ecx);
+  __ mov(MemOperand(esp, eax, times_4, 0), edi);
+  __ push(edi);
+  __ push(ebx);
+  __ push(ecx);
+  __ add(eax, Immediate(3));
+  __ TailCallRuntime(Runtime::kNewArray);
 }
 
 void FastArrayPushStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
@@ -90,21 +39,12 @@
   descriptor->Initialize(eax, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-void InternalArraySingleArgumentConstructorStub::InitializeDescriptor(
+void FastFunctionBindStub::InitializeDescriptor(
     CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 1);
+  Address deopt_handler = Runtime::FunctionForId(Runtime::kFunctionBind)->entry;
+  descriptor->Initialize(eax, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
 }
 
-
-void InternalArrayNArgumentsConstructorStub::InitializeDescriptor(
-    CodeStubDescriptor* descriptor) {
-  InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, -1);
-}
-
-
-#define __ ACCESS_MASM(masm)
-
-
 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm,
                                                ExternalReference miss) {
   // Update the static counter each time a new code stub is generated.
@@ -392,7 +332,6 @@
                                           &miss,  // When not a string.
                                           &miss,  // When not a number.
                                           &miss,  // When index out of range.
-                                          STRING_INDEX_IS_ARRAY_INDEX,
                                           RECEIVER_IS_STRING);
   char_at_generator.GenerateFast(masm);
   __ ret(0);
@@ -1189,6 +1128,7 @@
   // edi : the function to call
   Isolate* isolate = masm->isolate();
   Label initialize, done, miss, megamorphic, not_array_function;
+  Label done_increment_count, done_initialize_count;
 
   // Load the cache state into ecx.
   __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
@@ -1201,7 +1141,7 @@
   // type-feedback-vector.h).
   Label check_allocation_site;
   __ cmp(edi, FieldOperand(ecx, WeakCell::kValueOffset));
-  __ j(equal, &done, Label::kFar);
+  __ j(equal, &done_increment_count, Label::kFar);
   __ CompareRoot(ecx, Heap::kmegamorphic_symbolRootIndex);
   __ j(equal, &done, Label::kFar);
   __ CompareRoot(FieldOperand(ecx, HeapObject::kMapOffset),
@@ -1224,7 +1164,7 @@
   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx);
   __ cmp(edi, ecx);
   __ j(not_equal, &megamorphic);
-  __ jmp(&done, Label::kFar);
+  __ jmp(&done_increment_count, Label::kFar);
 
   __ bind(&miss);
 
@@ -1253,11 +1193,25 @@
   // slot.
   CreateAllocationSiteStub create_stub(isolate);
   CallStubInRecordCallTarget(masm, &create_stub);
-  __ jmp(&done);
+  __ jmp(&done_initialize_count);
 
   __ bind(&not_array_function);
   CreateWeakCellStub weak_cell_stub(isolate);
   CallStubInRecordCallTarget(masm, &weak_cell_stub);
+  __ bind(&done_initialize_count);
+
+  // Initialize the call counter.
+  __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
+                      FixedArray::kHeaderSize + kPointerSize),
+         Immediate(Smi::FromInt(1)));
+  __ jmp(&done);
+
+  __ bind(&done_increment_count);
+  // Increment the call count for monomorphic function calls.
+  __ add(FieldOperand(ebx, edx, times_half_pointer_size,
+                      FixedArray::kHeaderSize + kPointerSize),
+         Immediate(Smi::FromInt(1)));
+
   __ bind(&done);
 }
 
@@ -1321,7 +1275,7 @@
   // Increment the call count for monomorphic function calls.
   __ add(FieldOperand(ebx, edx, times_half_pointer_size,
                       FixedArray::kHeaderSize + kPointerSize),
-         Immediate(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+         Immediate(Smi::FromInt(1)));
 
   __ mov(ebx, ecx);
   __ mov(edx, edi);
@@ -1369,7 +1323,7 @@
   // Increment the call count for monomorphic function calls.
   __ add(FieldOperand(ebx, edx, times_half_pointer_size,
                       FixedArray::kHeaderSize + kPointerSize),
-         Immediate(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+         Immediate(Smi::FromInt(1)));
 
   __ bind(&call_function);
   __ Set(eax, argc);
@@ -1440,7 +1394,7 @@
   // Initialize the call counter.
   __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
                       FixedArray::kHeaderSize + kPointerSize),
-         Immediate(Smi::FromInt(CallICNexus::kCallCountIncrement)));
+         Immediate(Smi::FromInt(1)));
 
   // Store the function. Use a stub since we need a frame for allocation.
   // ebx - vector
@@ -1494,7 +1448,7 @@
   StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
   StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
   // It is important that the store buffer overflow stubs are generated first.
-  ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
+  CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate);
   CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
   CreateWeakCellStub::GenerateAheadOfTime(isolate);
   BinaryOpICStub::GenerateAheadOfTime(isolate);
@@ -1781,129 +1735,6 @@
 }
 
 
-void InstanceOfStub::Generate(MacroAssembler* masm) {
-  Register const object = edx;                       // Object (lhs).
-  Register const function = eax;                     // Function (rhs).
-  Register const object_map = ecx;                   // Map of {object}.
-  Register const function_map = ebx;                 // Map of {function}.
-  Register const function_prototype = function_map;  // Prototype of {function}.
-  Register const scratch = edi;
-
-  DCHECK(object.is(InstanceOfDescriptor::LeftRegister()));
-  DCHECK(function.is(InstanceOfDescriptor::RightRegister()));
-
-  // Check if {object} is a smi.
-  Label object_is_smi;
-  __ JumpIfSmi(object, &object_is_smi, Label::kNear);
-
-  // Lookup the {function} and the {object} map in the global instanceof cache.
-  // Note: This is safe because we clear the global instanceof cache whenever
-  // we change the prototype of any object.
-  Label fast_case, slow_case;
-  __ mov(object_map, FieldOperand(object, HeapObject::kMapOffset));
-  __ CompareRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex);
-  __ j(not_equal, &fast_case, Label::kNear);
-  __ CompareRoot(object_map, scratch, Heap::kInstanceofCacheMapRootIndex);
-  __ j(not_equal, &fast_case, Label::kNear);
-  __ LoadRoot(eax, Heap::kInstanceofCacheAnswerRootIndex);
-  __ ret(0);
-
-  // If {object} is a smi we can safely return false if {function} is a JS
-  // function, otherwise we have to miss to the runtime and throw an exception.
-  __ bind(&object_is_smi);
-  __ JumpIfSmi(function, &slow_case);
-  __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map);
-  __ j(not_equal, &slow_case);
-  __ LoadRoot(eax, Heap::kFalseValueRootIndex);
-  __ ret(0);
-
-  // Fast-case: The {function} must be a valid JSFunction.
-  __ bind(&fast_case);
-  __ JumpIfSmi(function, &slow_case);
-  __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map);
-  __ j(not_equal, &slow_case);
-
-  // Go to the runtime if the function is not a constructor.
-  __ test_b(FieldOperand(function_map, Map::kBitFieldOffset),
-            Immediate(1 << Map::kIsConstructor));
-  __ j(zero, &slow_case);
-
-  // Ensure that {function} has an instance prototype.
-  __ test_b(FieldOperand(function_map, Map::kBitFieldOffset),
-            Immediate(1 << Map::kHasNonInstancePrototype));
-  __ j(not_zero, &slow_case);
-
-  // Get the "prototype" (or initial map) of the {function}.
-  __ mov(function_prototype,
-         FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
-  __ AssertNotSmi(function_prototype);
-
-  // Resolve the prototype if the {function} has an initial map.  Afterwards the
-  // {function_prototype} will be either the JSReceiver prototype object or the
-  // hole value, which means that no instances of the {function} were created so
-  // far and hence we should return false.
-  Label function_prototype_valid;
-  Register const function_prototype_map = scratch;
-  __ CmpObjectType(function_prototype, MAP_TYPE, function_prototype_map);
-  __ j(not_equal, &function_prototype_valid, Label::kNear);
-  __ mov(function_prototype,
-         FieldOperand(function_prototype, Map::kPrototypeOffset));
-  __ bind(&function_prototype_valid);
-  __ AssertNotSmi(function_prototype);
-
-  // Update the global instanceof cache with the current {object} map and
-  // {function}.  The cached answer will be set when it is known below.
-  __ StoreRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex);
-  __ StoreRoot(object_map, scratch, Heap::kInstanceofCacheMapRootIndex);
-
-  // Loop through the prototype chain looking for the {function} prototype.
-  // Assume true, and change to false if not found.
-  Label done, loop, fast_runtime_fallback;
-  __ mov(eax, isolate()->factory()->true_value());
-  __ bind(&loop);
-
-  // Check if the object needs to be access checked.
-  __ test_b(FieldOperand(object_map, Map::kBitFieldOffset),
-            Immediate(1 << Map::kIsAccessCheckNeeded));
-  __ j(not_zero, &fast_runtime_fallback, Label::kNear);
-  // Check if the current object is a Proxy.
-  __ CmpInstanceType(object_map, JS_PROXY_TYPE);
-  __ j(equal, &fast_runtime_fallback, Label::kNear);
-
-  __ mov(object, FieldOperand(object_map, Map::kPrototypeOffset));
-  __ cmp(object, function_prototype);
-  __ j(equal, &done, Label::kNear);
-  __ mov(object_map, FieldOperand(object, HeapObject::kMapOffset));
-  __ cmp(object, isolate()->factory()->null_value());
-  __ j(not_equal, &loop);
-  __ mov(eax, isolate()->factory()->false_value());
-
-  __ bind(&done);
-  __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex);
-  __ ret(0);
-
-  // Found Proxy or access check needed: Call the runtime.
-  __ bind(&fast_runtime_fallback);
-  __ PopReturnAddressTo(scratch);
-  __ Push(object);
-  __ Push(function_prototype);
-  __ PushReturnAddressFrom(scratch);
-  // Invalidate the instanceof cache.
-  __ Move(eax, Immediate(Smi::FromInt(0)));
-  __ StoreRoot(eax, scratch, Heap::kInstanceofCacheFunctionRootIndex);
-  __ TailCallRuntime(Runtime::kHasInPrototypeChain);
-
-  // Slow-case: Call the %InstanceOf runtime function.
-  __ bind(&slow_case);
-  __ PopReturnAddressTo(scratch);
-  __ Push(object);
-  __ Push(function);
-  __ PushReturnAddressFrom(scratch);
-  __ TailCallRuntime(is_es6_instanceof() ? Runtime::kOrdinaryHasInstance
-                                         : Runtime::kInstanceOf);
-}
-
-
 // -------------------------------------------------------------------------
 // StringCharCodeAtGenerator
 
@@ -1958,13 +1789,7 @@
   }
   __ push(object_);
   __ push(index_);  // Consumed by runtime conversion function.
-  if (index_flags_ == STRING_INDEX_IS_NUMBER) {
-    __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero);
-  } else {
-    DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
-    // NumberToSmi discards numbers that are not exact integers.
-    __ CallRuntime(Runtime::kNumberToSmi);
-  }
+  __ CallRuntime(Runtime::kNumberToSmi);
   if (!index_.is(eax)) {
     // Save the conversion result before the pop instructions below
     // have a chance to overwrite it.
@@ -2297,77 +2122,12 @@
   // ecx: sub string length (smi)
   // edx: from index (smi)
   StringCharAtGenerator generator(eax, edx, ecx, eax, &runtime, &runtime,
-                                  &runtime, STRING_INDEX_IS_NUMBER,
-                                  RECEIVER_IS_STRING);
+                                  &runtime, RECEIVER_IS_STRING);
   generator.GenerateFast(masm);
   __ ret(3 * kPointerSize);
   generator.SkipSlow(masm, &runtime);
 }
 
-
-void ToNumberStub::Generate(MacroAssembler* masm) {
-  // The ToNumber stub takes one argument in eax.
-  Label not_smi;
-  __ JumpIfNotSmi(eax, &not_smi, Label::kNear);
-  __ Ret();
-  __ bind(&not_smi);
-
-  Label not_heap_number;
-  __ CompareMap(eax, masm->isolate()->factory()->heap_number_map());
-  __ j(not_equal, &not_heap_number, Label::kNear);
-  __ Ret();
-  __ bind(&not_heap_number);
-
-  NonNumberToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
-}
-
-void NonNumberToNumberStub::Generate(MacroAssembler* masm) {
-  // The NonNumberToNumber stub takes one argument in eax.
-  __ AssertNotNumber(eax);
-
-  Label not_string;
-  __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edi);
-  // eax: object
-  // edi: object map
-  __ j(above_equal, &not_string, Label::kNear);
-  StringToNumberStub stub(masm->isolate());
-  __ TailCallStub(&stub);
-  __ bind(&not_string);
-
-  Label not_oddball;
-  __ CmpInstanceType(edi, ODDBALL_TYPE);
-  __ j(not_equal, &not_oddball, Label::kNear);
-  __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset));
-  __ Ret();
-  __ bind(&not_oddball);
-
-  __ pop(ecx);   // Pop return address.
-  __ push(eax);  // Push argument.
-  __ push(ecx);  // Push return address.
-  __ TailCallRuntime(Runtime::kToNumber);
-}
-
-void StringToNumberStub::Generate(MacroAssembler* masm) {
-  // The StringToNumber stub takes one argument in eax.
-  __ AssertString(eax);
-
-  // Check if string has a cached array index.
-  Label runtime;
-  __ test(FieldOperand(eax, String::kHashFieldOffset),
-          Immediate(String::kContainsCachedArrayIndexMask));
-  __ j(not_zero, &runtime, Label::kNear);
-  __ mov(eax, FieldOperand(eax, String::kHashFieldOffset));
-  __ IndexFromHash(eax, eax);
-  __ Ret();
-
-  __ bind(&runtime);
-  __ PopReturnAddressTo(ecx);     // Pop return address.
-  __ Push(eax);                   // Push argument.
-  __ PushReturnAddressFrom(ecx);  // Push return address.
-  __ TailCallRuntime(Runtime::kStringToNumber);
-}
-
 void ToStringStub::Generate(MacroAssembler* masm) {
   // The ToString stub takes one argument in eax.
   Label is_number;
@@ -2574,7 +2334,7 @@
   // Load ecx with the allocation site.  We stick an undefined dummy value here
   // and replace it with the real allocation site later when we instantiate this
   // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate().
-  __ mov(ecx, handle(isolate()->heap()->undefined_value()));
+  __ mov(ecx, isolate()->factory()->undefined_value());
 
   // Make sure that we actually patched the allocation site.
   if (FLAG_debug_code) {
@@ -3375,14 +3135,14 @@
 
 void LoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  LoadICStub stub(isolate(), state());
+  LoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
 
 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
   __ EmitLoadTypeFeedbackVector(LoadWithVectorDescriptor::VectorRegister());
-  KeyedLoadICStub stub(isolate(), state());
+  KeyedLoadICStub stub(isolate());
   stub.GenerateForTrampoline(masm);
 }
 
@@ -3534,8 +3294,8 @@
   __ j(not_equal, &miss);
   __ push(slot);
   __ push(vector);
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::LOAD_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::LOAD_IC, code_flags,
                                                receiver, name, vector, scratch);
   __ pop(vector);
@@ -3795,8 +3555,8 @@
   __ pop(value);
   __ push(slot);
   __ push(vector);
-  Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
-      Code::ComputeHandlerFlags(Code::STORE_IC));
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
   masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, code_flags,
                                                receiver, key, slot, no_reg);
   __ pop(vector);
@@ -4147,17 +3907,14 @@
   }
 }
 
-void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
+void CommonArrayConstructorStub::GenerateStubsAheadOfTime(Isolate* isolate) {
   ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
       isolate);
   ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
       isolate);
-  ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
-      isolate);
-}
+  ArrayNArgumentsConstructorStub stub(isolate);
+  stub.GetCode();
 
-void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime(
-    Isolate* isolate) {
   ElementsKind kinds[2] = {FAST_ELEMENTS, FAST_HOLEY_ELEMENTS};
   for (int i = 0; i < 2; i++) {
     // For internal arrays we only need a few things
@@ -4165,8 +3922,6 @@
     stubh1.GetCode();
     InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]);
     stubh2.GetCode();
-    InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]);
-    stubh3.GetCode();
   }
 }
 
@@ -4184,13 +3939,15 @@
     CreateArrayDispatchOneArgument(masm, mode);
 
     __ bind(&not_one_case);
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else if (argument_count() == NONE) {
     CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode);
   } else if (argument_count() == ONE) {
     CreateArrayDispatchOneArgument(masm, mode);
   } else if (argument_count() == MORE_THAN_ONE) {
-    CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode);
+    ArrayNArgumentsConstructorStub stub(masm->isolate());
+    __ TailCallStub(&stub);
   } else {
     UNREACHABLE();
   }
@@ -4300,7 +4057,7 @@
   __ TailCallStub(&stub1);
 
   __ bind(&not_one_case);
-  InternalArrayNArgumentsConstructorStub stubN(isolate(), kind);
+  ArrayNArgumentsConstructorStub stubN(isolate());
   __ TailCallStub(&stubN);
 }
 
@@ -4386,16 +4143,16 @@
   __ bind(&done_allocate);
 
   // Initialize the JSObject fields.
-  __ mov(Operand(eax, JSObject::kMapOffset), ecx);
-  __ mov(Operand(eax, JSObject::kPropertiesOffset),
+  __ mov(FieldOperand(eax, JSObject::kMapOffset), ecx);
+  __ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
          masm->isolate()->factory()->empty_fixed_array());
-  __ mov(Operand(eax, JSObject::kElementsOffset),
+  __ mov(FieldOperand(eax, JSObject::kElementsOffset),
          masm->isolate()->factory()->empty_fixed_array());
   STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize);
-  __ lea(ebx, Operand(eax, JSObject::kHeaderSize));
+  __ lea(ebx, FieldOperand(eax, JSObject::kHeaderSize));
 
   // ----------- S t a t e -------------
-  //  -- eax    : result (untagged)
+  //  -- eax    : result (tagged)
   //  -- ebx    : result fields (untagged)
   //  -- edi    : result end (untagged)
   //  -- ecx    : initial map
@@ -4413,10 +4170,6 @@
     // Initialize all in-object fields with undefined.
     __ LoadRoot(edx, Heap::kUndefinedValueRootIndex);
     __ InitializeFieldsWithFiller(ebx, edi, edx);
-
-    // Add the object tag to make the JSObject real.
-    STATIC_ASSERT(kHeapObjectTag == 1);
-    __ inc(eax);
     __ Ret();
   }
   __ bind(&slack_tracking);
@@ -4439,10 +4192,6 @@
     __ LoadRoot(edi, Heap::kOnePointerFillerMapRootIndex);
     __ InitializeFieldsWithFiller(ebx, edx, edi);
 
-    // Add the object tag to make the JSObject real.
-    STATIC_ASSERT(kHeapObjectTag == 1);
-    __ inc(eax);
-
     // Check if we can finalize the instance size.
     Label finalize;
     STATIC_ASSERT(Map::kSlackTrackingCounterEnd == 1);
@@ -4473,10 +4222,10 @@
     __ CallRuntime(Runtime::kAllocateInNewSpace);
     __ Pop(ecx);
   }
-  STATIC_ASSERT(kHeapObjectTag == 1);
-  __ dec(eax);
   __ movzx_b(ebx, FieldOperand(ecx, Map::kInstanceSizeOffset));
   __ lea(edi, Operand(eax, ebx, times_pointer_size, 0));
+  STATIC_ASSERT(kHeapObjectTag == 1);
+  __ dec(edi);
   __ jmp(&done_allocate);
 
   // Fall back to %NewObject.
@@ -4497,19 +4246,19 @@
   // -----------------------------------
   __ AssertFunction(edi);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make edx point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ mov(edx, ebp);
-    __ jmp(&loop_entry, Label::kNear);
-    __ bind(&loop);
+  // Make edx point to the JavaScript frame.
+  __ mov(edx, ebp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ mov(edx, Operand(edx, StandardFrameConstants::kCallerFPOffset));
-    __ bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ cmp(edi, Operand(edx, StandardFrameConstants::kFunctionOffset));
-    __ j(not_equal, &loop);
+    __ j(equal, &ok);
+    __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+    __ bind(&ok);
   }
 
   // Check if we have rest parameters (only possible if we have an
@@ -4539,7 +4288,7 @@
 
     // Allocate an empty rest parameter array.
     Label allocate, done_allocate;
-    __ Allocate(JSArray::kSize, eax, edx, ecx, &allocate, TAG_OBJECT);
+    __ Allocate(JSArray::kSize, eax, edx, ecx, &allocate, NO_ALLOCATION_FLAGS);
     __ bind(&done_allocate);
 
     // Setup the rest parameter array in rax.
@@ -4581,7 +4330,7 @@
     Label allocate, done_allocate;
     __ lea(ecx, Operand(eax, times_half_pointer_size,
                         JSArray::kSize + FixedArray::kHeaderSize));
-    __ Allocate(ecx, edx, edi, no_reg, &allocate, TAG_OBJECT);
+    __ Allocate(ecx, edx, edi, no_reg, &allocate, NO_ALLOCATION_FLAGS);
     __ bind(&done_allocate);
 
     // Setup the elements array in edx.
@@ -4617,8 +4366,11 @@
     __ mov(eax, edi);
     __ Ret();
 
-    // Fall back to %AllocateInNewSpace.
+    // Fall back to %AllocateInNewSpace (if not too big).
+    Label too_big_for_new_space;
     __ bind(&allocate);
+    __ cmp(ecx, Immediate(Page::kMaxRegularHeapObjectSize));
+    __ j(greater, &too_big_for_new_space);
     {
       FrameScope scope(masm, StackFrame::INTERNAL);
       __ SmiTag(ecx);
@@ -4631,6 +4383,22 @@
       __ Pop(eax);
     }
     __ jmp(&done_allocate);
+
+    // Fall back to %NewRestParameter.
+    __ bind(&too_big_for_new_space);
+    __ PopReturnAddressTo(ecx);
+    // We reload the function from the caller frame due to register pressure
+    // within this stub. This is the slow path, hence reloading is preferable.
+    if (skip_stub_frame()) {
+      // For Ignition we need to skip the handler/stub frame to reach the
+      // JavaScript frame for the function.
+      __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
+      __ Push(Operand(edx, StandardFrameConstants::kFunctionOffset));
+    } else {
+      __ Push(Operand(ebp, StandardFrameConstants::kFunctionOffset));
+    }
+    __ PushReturnAddressFrom(ecx);
+    __ TailCallRuntime(Runtime::kNewRestParameter);
   }
 }
 
@@ -4643,35 +4411,50 @@
   // -----------------------------------
   __ AssertFunction(edi);
 
+  // Make ecx point to the JavaScript frame.
+  __ mov(ecx, ebp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
+    __ mov(ecx, Operand(ecx, StandardFrameConstants::kCallerFPOffset));
+  }
+  if (FLAG_debug_code) {
+    Label ok;
+    __ cmp(edi, Operand(ecx, StandardFrameConstants::kFunctionOffset));
+    __ j(equal, &ok);
+    __ Abort(kInvalidFrameForFastNewSloppyArgumentsStub);
+    __ bind(&ok);
+  }
+
   // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub.
-  __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
-  __ mov(ecx,
-         FieldOperand(ecx, SharedFunctionInfo::kFormalParameterCountOffset));
-  __ lea(edx, Operand(ebp, ecx, times_half_pointer_size,
+  __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+  __ mov(ebx,
+         FieldOperand(ebx, SharedFunctionInfo::kFormalParameterCountOffset));
+  __ lea(edx, Operand(ecx, ebx, times_half_pointer_size,
                       StandardFrameConstants::kCallerSPOffset));
 
-  // ecx : number of parameters (tagged)
+  // ebx : number of parameters (tagged)
   // edx : parameters pointer
   // edi : function
+  // ecx : JavaScript frame pointer.
   // esp[0] : return address
 
   // Check if the calling frame is an arguments adaptor frame.
   Label adaptor_frame, try_allocate, runtime;
-  __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
-  __ mov(eax, Operand(ebx, CommonFrameConstants::kContextOrFrameTypeOffset));
+  __ mov(eax, Operand(ecx, StandardFrameConstants::kCallerFPOffset));
+  __ mov(eax, Operand(eax, CommonFrameConstants::kContextOrFrameTypeOffset));
   __ cmp(eax, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
   __ j(equal, &adaptor_frame, Label::kNear);
 
   // No adaptor, parameter count = argument count.
-  __ mov(ebx, ecx);
-  __ push(ecx);
+  __ mov(ecx, ebx);
+  __ push(ebx);
   __ jmp(&try_allocate, Label::kNear);
 
   // We have an adaptor frame. Patch the parameters pointer.
   __ bind(&adaptor_frame);
-  __ mov(ebx, ecx);
-  __ push(ecx);
-  __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
+  __ push(ebx);
+  __ mov(edx, Operand(ecx, StandardFrameConstants::kCallerFPOffset));
   __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
   __ lea(edx,
          Operand(edx, ecx, times_2, StandardFrameConstants::kCallerSPOffset));
@@ -4705,7 +4488,7 @@
   __ add(ebx, Immediate(JSSloppyArgumentsObject::kSize));
 
   // Do the allocation of all three objects in one go.
-  __ Allocate(ebx, eax, edi, no_reg, &runtime, TAG_OBJECT);
+  __ Allocate(ebx, eax, edi, no_reg, &runtime, NO_ALLOCATION_FLAGS);
 
   // eax = address of new object(s) (tagged)
   // ecx = argument count (smi-tagged)
@@ -4883,19 +4666,19 @@
   // -----------------------------------
   __ AssertFunction(edi);
 
-  // For Ignition we need to skip all possible handler/stub frames until
-  // we reach the JavaScript frame for the function (similar to what the
-  // runtime fallback implementation does). So make edx point to that
-  // JavaScript frame.
-  {
-    Label loop, loop_entry;
-    __ mov(edx, ebp);
-    __ jmp(&loop_entry, Label::kNear);
-    __ bind(&loop);
+  // Make edx point to the JavaScript frame.
+  __ mov(edx, ebp);
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
     __ mov(edx, Operand(edx, StandardFrameConstants::kCallerFPOffset));
-    __ bind(&loop_entry);
+  }
+  if (FLAG_debug_code) {
+    Label ok;
     __ cmp(edi, Operand(edx, StandardFrameConstants::kFunctionOffset));
-    __ j(not_equal, &loop);
+    __ j(equal, &ok);
+    __ Abort(kInvalidFrameForFastNewStrictArgumentsStub);
+    __ bind(&ok);
   }
 
   // Check if we have an arguments adaptor frame below the function frame.
@@ -4934,7 +4717,7 @@
   __ lea(ecx,
          Operand(eax, times_half_pointer_size,
                  JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
-  __ Allocate(ecx, edx, edi, no_reg, &allocate, TAG_OBJECT);
+  __ Allocate(ecx, edx, edi, no_reg, &allocate, NO_ALLOCATION_FLAGS);
   __ bind(&done_allocate);
 
   // Setup the elements array in edx.
@@ -4970,8 +4753,11 @@
   __ mov(eax, edi);
   __ Ret();
 
-  // Fall back to %AllocateInNewSpace.
+  // Fall back to %AllocateInNewSpace (if not too big).
+  Label too_big_for_new_space;
   __ bind(&allocate);
+  __ cmp(ecx, Immediate(Page::kMaxRegularHeapObjectSize));
+  __ j(greater, &too_big_for_new_space);
   {
     FrameScope scope(masm, StackFrame::INTERNAL);
     __ SmiTag(ecx);
@@ -4984,39 +4770,24 @@
     __ Pop(eax);
   }
   __ jmp(&done_allocate);
-}
 
-void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) {
-  Register context_reg = esi;
-  Register slot_reg = ebx;
-  Register result_reg = eax;
-  Label slow_case;
-
-  // Go up context chain to the script context.
-  for (int i = 0; i < depth(); ++i) {
-    __ mov(result_reg, ContextOperand(context_reg, Context::PREVIOUS_INDEX));
-    context_reg = result_reg;
+  // Fall back to %NewStrictArguments.
+  __ bind(&too_big_for_new_space);
+  __ PopReturnAddressTo(ecx);
+  // We reload the function from the caller frame due to register pressure
+  // within this stub. This is the slow path, hence reloading is preferable.
+  if (skip_stub_frame()) {
+    // For Ignition we need to skip the handler/stub frame to reach the
+    // JavaScript frame for the function.
+    __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
+    __ Push(Operand(edx, StandardFrameConstants::kFunctionOffset));
+  } else {
+    __ Push(Operand(ebp, StandardFrameConstants::kFunctionOffset));
   }
-
-  // Load the PropertyCell value at the specified slot.
-  __ mov(result_reg, ContextOperand(context_reg, slot_reg));
-  __ mov(result_reg, FieldOperand(result_reg, PropertyCell::kValueOffset));
-
-  // Check that value is not the_hole.
-  __ CompareRoot(result_reg, Heap::kTheHoleValueRootIndex);
-  __ j(equal, &slow_case, Label::kNear);
-  __ Ret();
-
-  // Fallback to the runtime.
-  __ bind(&slow_case);
-  __ SmiTag(slot_reg);
-  __ Pop(result_reg);  // Pop return address.
-  __ Push(slot_reg);
-  __ Push(result_reg);  // Push return address.
-  __ TailCallRuntime(Runtime::kLoadGlobalViaContext);
+  __ PushReturnAddressFrom(ecx);
+  __ TailCallRuntime(Runtime::kNewStrictArguments);
 }
 
-
 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) {
   Register context_reg = esi;
   Register slot_reg = ebx;
@@ -5354,9 +5125,14 @@
   STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
   STATIC_ASSERT(FCA::kIsolateIndex == 1);
   STATIC_ASSERT(FCA::kHolderIndex == 0);
-  STATIC_ASSERT(FCA::kArgsLength == 7);
+  STATIC_ASSERT(FCA::kNewTargetIndex == 7);
+  STATIC_ASSERT(FCA::kArgsLength == 8);
 
   __ pop(return_address);
+
+  // new target
+  __ PushRoot(Heap::kUndefinedValueRootIndex);
+
   // context save.
   __ push(context);
 
@@ -5401,7 +5177,7 @@
 
   // Allocate the v8::Arguments structure in the arguments' space since
   // it's not controlled by GC.
-  const int kApiStackSpace = 4;
+  const int kApiStackSpace = 3;
 
   PrepareCallApiFunction(masm, kApiArgc + kApiStackSpace);
 
@@ -5412,8 +5188,6 @@
   __ mov(ApiParameterOperand(3), scratch);
   // FunctionCallbackInfo::length_.
   __ Move(ApiParameterOperand(4), Immediate(argc()));
-  // FunctionCallbackInfo::is_construct_call_.
-  __ Move(ApiParameterOperand(5), Immediate(0));
 
   // v8::InvocationCallback's argument.
   __ lea(scratch, ApiParameterOperand(2));
@@ -5433,8 +5207,8 @@
   }
   Operand return_value_operand(ebp, return_value_offset * kPointerSize);
   int stack_space = 0;
-  Operand is_construct_call_operand = ApiParameterOperand(5);
-  Operand* stack_space_operand = &is_construct_call_operand;
+  Operand length_operand = ApiParameterOperand(4);
+  Operand* stack_space_operand = &length_operand;
   stack_space = argc() + FCA::kArgsLength + 1;
   stack_space_operand = nullptr;
   CallApiFunctionAndReturn(masm, api_function_address, thunk_ref,
@@ -5445,14 +5219,34 @@
 
 
 void CallApiGetterStub::Generate(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- esp[0]                        : return address
-  //  -- esp[4]                        : name
-  //  -- esp[8 .. (8 + kArgsLength*4)] : v8::PropertyCallbackInfo::args_
-  //  -- ...
-  //  -- edx                           : api_function_address
-  // -----------------------------------
-  DCHECK(edx.is(ApiGetterDescriptor::function_address()));
+  // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
+  // name below the exit frame to make GC aware of them.
+  STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
+  STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
+  STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
+  STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
+  STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
+  STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
+  STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
+
+  Register receiver = ApiGetterDescriptor::ReceiverRegister();
+  Register holder = ApiGetterDescriptor::HolderRegister();
+  Register callback = ApiGetterDescriptor::CallbackRegister();
+  Register scratch = ebx;
+  DCHECK(!AreAliased(receiver, holder, callback, scratch));
+
+  __ pop(scratch);  // Pop return address to extend the frame.
+  __ push(receiver);
+  __ push(FieldOperand(callback, AccessorInfo::kDataOffset));
+  __ PushRoot(Heap::kUndefinedValueRootIndex);  // ReturnValue
+  // ReturnValue default value
+  __ PushRoot(Heap::kUndefinedValueRootIndex);
+  __ push(Immediate(ExternalReference::isolate_address(isolate())));
+  __ push(holder);
+  __ push(Immediate(Smi::FromInt(0)));  // should_throw_on_error -> false
+  __ push(FieldOperand(callback, AccessorInfo::kNameOffset));
+  __ push(scratch);  // Restore return address.
 
   // v8::PropertyCallbackInfo::args_ array and name handle.
   const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
@@ -5462,9 +5256,6 @@
   // active) in non-GCed stack space.
   const int kApiArgc = 3 + 1;
 
-  Register api_function_address = edx;
-  Register scratch = ebx;
-
   // Load address of v8::PropertyAccessorInfo::args_ array.
   __ lea(scratch, Operand(esp, 2 * kPointerSize));
 
@@ -5474,25 +5265,30 @@
   Operand info_object = ApiParameterOperand(3);
   __ mov(info_object, scratch);
 
+  // Name as handle.
   __ sub(scratch, Immediate(kPointerSize));
-  __ mov(ApiParameterOperand(0), scratch);  // name.
+  __ mov(ApiParameterOperand(0), scratch);
+  // Arguments pointer.
   __ lea(scratch, info_object);
-  __ mov(ApiParameterOperand(1), scratch);  // arguments pointer.
+  __ mov(ApiParameterOperand(1), scratch);
   // Reserve space for optional callback address parameter.
   Operand thunk_last_arg = ApiParameterOperand(2);
 
   ExternalReference thunk_ref =
       ExternalReference::invoke_accessor_getter_callback(isolate());
 
+  __ mov(scratch, FieldOperand(callback, AccessorInfo::kJsGetterOffset));
+  Register function_address = edx;
+  __ mov(function_address,
+         FieldOperand(scratch, Foreign::kForeignAddressOffset));
   // +3 is to skip prolog, return address and name handle.
   Operand return_value_operand(
       ebp, (PropertyCallbackArguments::kReturnValueOffset + 3) * kPointerSize);
-  CallApiFunctionAndReturn(masm, api_function_address, thunk_ref,
-                           thunk_last_arg, kStackUnwindSpace, nullptr,
-                           return_value_operand, NULL);
+  CallApiFunctionAndReturn(masm, function_address, thunk_ref, thunk_last_arg,
+                           kStackUnwindSpace, nullptr, return_value_operand,
+                           NULL);
 }
 
-
 #undef __
 
 }  // namespace internal
diff --git a/src/x87/code-stubs-x87.h b/src/x87/code-stubs-x87.h
index 39a4603..6290cfe 100644
--- a/src/x87/code-stubs-x87.h
+++ b/src/x87/code-stubs-x87.h
@@ -298,8 +298,8 @@
                                   Register r2,
                                   Register r3) {
       for (int i = 0; i < Register::kNumRegisters; i++) {
-        Register candidate = Register::from_code(i);
-        if (candidate.IsAllocatable()) {
+        if (RegisterConfiguration::Crankshaft()->IsAllocatableGeneralCode(i)) {
+          Register candidate = Register::from_code(i);
           if (candidate.is(ecx)) continue;
           if (candidate.is(r1)) continue;
           if (candidate.is(r2)) continue;
diff --git a/src/x87/codegen-x87.cc b/src/x87/codegen-x87.cc
index 776edeb..5cda23d 100644
--- a/src/x87/codegen-x87.cc
+++ b/src/x87/codegen-x87.cc
@@ -33,10 +33,6 @@
 
 #define __ masm.
 
-UnaryMathFunctionWithIsolate CreateExpFunction(Isolate* isolate) {
-  return nullptr;
-}
-
 
 UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
   size_t actual_size;
@@ -269,14 +265,14 @@
 
   __ push(eax);
   __ push(ebx);
+  __ push(esi);
 
   __ mov(edi, FieldOperand(edi, FixedArray::kLengthOffset));
 
   // Allocate new FixedDoubleArray.
   // edx: receiver
   // edi: length of source FixedArray (smi-tagged)
-  AllocationFlags flags =
-      static_cast<AllocationFlags>(TAG_OBJECT | DOUBLE_ALIGNMENT);
+  AllocationFlags flags = static_cast<AllocationFlags>(DOUBLE_ALIGNMENT);
   __ Allocate(FixedDoubleArray::kHeaderSize, times_8, edi,
               REGISTER_VALUE_IS_SMI, eax, ebx, no_reg, &gc_required, flags);
 
@@ -302,8 +298,9 @@
 
   // Call into runtime if GC is required.
   __ bind(&gc_required);
+
   // Restore registers before jumping into runtime.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  __ pop(esi);
   __ pop(ebx);
   __ pop(eax);
   __ jmp(fail);
@@ -339,12 +336,11 @@
   __ sub(edi, Immediate(Smi::FromInt(1)));
   __ j(not_sign, &loop);
 
+  // Restore registers.
+  __ pop(esi);
   __ pop(ebx);
   __ pop(eax);
 
-  // Restore esi.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-
   __ bind(&only_change_map);
   // eax: value
   // ebx: target map
@@ -391,7 +387,7 @@
   // Allocate new FixedArray.
   // ebx: length of source FixedDoubleArray (smi-tagged)
   __ lea(edi, Operand(ebx, times_2, FixedArray::kHeaderSize));
-  __ Allocate(edi, eax, esi, no_reg, &gc_required, TAG_OBJECT);
+  __ Allocate(edi, eax, esi, no_reg, &gc_required, NO_ALLOCATION_FLAGS);
 
   // eax: destination FixedArray
   // ebx: number of elements
diff --git a/src/x87/deoptimizer-x87.cc b/src/x87/deoptimizer-x87.cc
index 9d4645e..15dabb9 100644
--- a/src/x87/deoptimizer-x87.cc
+++ b/src/x87/deoptimizer-x87.cc
@@ -277,8 +277,7 @@
   }
 
   int double_regs_offset = FrameDescription::double_registers_offset();
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   // Fill in the double input registers.
   for (int i = 0; i < X87Register::kMaxNumAllocatableRegisters; ++i) {
     int code = config->GetAllocatableDoubleCode(i);
diff --git a/src/x87/disasm-x87.cc b/src/x87/disasm-x87.cc
index 91ce227..be9167b 100644
--- a/src/x87/disasm-x87.cc
+++ b/src/x87/disasm-x87.cc
@@ -8,6 +8,7 @@
 
 #if V8_TARGET_ARCH_X87
 
+#include "src/base/compiler-specific.h"
 #include "src/disasm.h"
 
 namespace disasm {
@@ -29,18 +30,19 @@
 };
 
 static const ByteMnemonic two_operands_instr[] = {
-    {0x01, "add", OPER_REG_OP_ORDER},   {0x03, "add", REG_OPER_OP_ORDER},
-    {0x09, "or", OPER_REG_OP_ORDER},    {0x0B, "or", REG_OPER_OP_ORDER},
-    {0x13, "adc", REG_OPER_OP_ORDER},   {0x1B, "sbb", REG_OPER_OP_ORDER},
-    {0x21, "and", OPER_REG_OP_ORDER},   {0x23, "and", REG_OPER_OP_ORDER},
-    {0x29, "sub", OPER_REG_OP_ORDER},   {0x2A, "subb", REG_OPER_OP_ORDER},
-    {0x2B, "sub", REG_OPER_OP_ORDER},   {0x31, "xor", OPER_REG_OP_ORDER},
-    {0x33, "xor", REG_OPER_OP_ORDER},   {0x38, "cmpb", OPER_REG_OP_ORDER},
-    {0x39, "cmp", OPER_REG_OP_ORDER},   {0x3A, "cmpb", REG_OPER_OP_ORDER},
-    {0x3B, "cmp", REG_OPER_OP_ORDER},   {0x84, "test_b", REG_OPER_OP_ORDER},
-    {0x85, "test", REG_OPER_OP_ORDER},  {0x87, "xchg", REG_OPER_OP_ORDER},
-    {0x8A, "mov_b", REG_OPER_OP_ORDER}, {0x8B, "mov", REG_OPER_OP_ORDER},
-    {0x8D, "lea", REG_OPER_OP_ORDER},   {-1, "", UNSET_OP_ORDER}};
+    {0x01, "add", OPER_REG_OP_ORDER},  {0x03, "add", REG_OPER_OP_ORDER},
+    {0x09, "or", OPER_REG_OP_ORDER},   {0x0B, "or", REG_OPER_OP_ORDER},
+    {0x13, "adc", REG_OPER_OP_ORDER},  {0x1B, "sbb", REG_OPER_OP_ORDER},
+    {0x21, "and", OPER_REG_OP_ORDER},  {0x23, "and", REG_OPER_OP_ORDER},
+    {0x29, "sub", OPER_REG_OP_ORDER},  {0x2A, "subb", REG_OPER_OP_ORDER},
+    {0x2B, "sub", REG_OPER_OP_ORDER},  {0x31, "xor", OPER_REG_OP_ORDER},
+    {0x33, "xor", REG_OPER_OP_ORDER},  {0x38, "cmpb", OPER_REG_OP_ORDER},
+    {0x39, "cmp", OPER_REG_OP_ORDER},  {0x3A, "cmpb", REG_OPER_OP_ORDER},
+    {0x3B, "cmp", REG_OPER_OP_ORDER},  {0x84, "test_b", REG_OPER_OP_ORDER},
+    {0x85, "test", REG_OPER_OP_ORDER}, {0x86, "xchg_b", REG_OPER_OP_ORDER},
+    {0x87, "xchg", REG_OPER_OP_ORDER}, {0x8A, "mov_b", REG_OPER_OP_ORDER},
+    {0x8B, "mov", REG_OPER_OP_ORDER},  {0x8D, "lea", REG_OPER_OP_ORDER},
+    {-1, "", UNSET_OP_ORDER}};
 
 static const ByteMnemonic zero_operands_instr[] = {
   {0xC3, "ret", UNSET_OP_ORDER},
@@ -325,8 +327,7 @@
   int FPUInstruction(byte* data);
   int MemoryFPUInstruction(int escape_opcode, int regop, byte* modrm_start);
   int RegisterFPUInstruction(int escape_opcode, byte modrm_byte);
-  void AppendToBuffer(const char* format, ...);
-
+  PRINTF_FORMAT(2, 3) void AppendToBuffer(const char* format, ...);
 
   void UnimplementedInstruction() {
     if (abort_on_unimplemented_) {
@@ -919,6 +920,10 @@
       return "shrd";  // 3-operand version.
     case 0xAB:
       return "bts";
+    case 0xB0:
+      return "cmpxchg_b";
+    case 0xB1:
+      return "cmpxchg";
     case 0xBC:
       return "bsf";
     case 0xBD:
@@ -942,13 +947,17 @@
   } else if (*data == 0x2E /*cs*/) {
     branch_hint = "predicted not taken";
     data++;
+  } else if (*data == 0xF0 /*lock*/) {
+    AppendToBuffer("lock ");
+    data++;
   }
+
   bool processed = true;  // Will be set to false if the current instruction
                           // is not in 'instructions' table.
   const InstructionDesc& idesc = instruction_table_->Get(*data);
   switch (idesc.type) {
     case ZERO_OPERANDS_INSTR:
-      AppendToBuffer(idesc.mnem);
+      AppendToBuffer("%s", idesc.mnem);
       data++;
       break;
 
@@ -1161,6 +1170,24 @@
             } else {
               AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
             }
+          } else if (f0byte == 0xB0) {
+            // cmpxchg_b
+            data += 2;
+            AppendToBuffer("%s ", f0mnem);
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            data += PrintRightOperand(data);
+            AppendToBuffer(",%s", NameOfByteCPURegister(regop));
+          } else if (f0byte == 0xB1) {
+            // cmpxchg
+            data += 2;
+            data += PrintOperands(f0mnem, OPER_REG_OP_ORDER, data);
+          } else if (f0byte == 0xBC) {
+            data += 2;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            AppendToBuffer("%s %s,", f0mnem, NameOfCPURegister(regop));
+            data += PrintRightOperand(data);
           } else if (f0byte == 0xBD) {
             data += 2;
             int mod, regop, rm;
@@ -1267,6 +1294,12 @@
         } else if (*data == 0x8B) {
           data++;
           data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data);
+        } else if (*data == 0x87) {
+          data++;
+          int mod, regop, rm;
+          get_modrm(*data, &mod, &regop, &rm);
+          AppendToBuffer("xchg_w %s,", NameOfCPURegister(regop));
+          data += PrintRightOperand(data);
         } else if (*data == 0x89) {
           data++;
           int mod, regop, rm;
@@ -1505,6 +1538,9 @@
                            NameOfXMMRegister(regop),
                            NameOfXMMRegister(rm));
             data++;
+          } else if (*data == 0xB1) {
+            data++;
+            data += PrintOperands("cmpxchg_w", OPER_REG_OP_ORDER, data);
           } else {
             UnimplementedInstruction();
           }
@@ -1744,7 +1780,7 @@
 
 
 const char* NameConverter::NameOfAddress(byte* addr) const {
-  v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
+  v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
   return tmp_buffer_.start();
 }
 
@@ -1807,7 +1843,7 @@
     buffer[0] = '\0';
     byte* prev_pc = pc;
     pc += d.InstructionDecode(buffer, pc);
-    fprintf(f, "%p", prev_pc);
+    fprintf(f, "%p", static_cast<void*>(prev_pc));
     fprintf(f, "    ");
 
     for (byte* bp = prev_pc; bp < pc; bp++) {
diff --git a/src/x87/interface-descriptors-x87.cc b/src/x87/interface-descriptors-x87.cc
index e41d42c..99664dc 100644
--- a/src/x87/interface-descriptors-x87.cc
+++ b/src/x87/interface-descriptors-x87.cc
@@ -11,6 +11,14 @@
 
 const Register CallInterfaceDescriptor::ContextRegister() { return esi; }
 
+void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
+    CallInterfaceDescriptorData* data, int register_parameter_count) {
+  const Register default_stub_registers[] = {eax, ebx, ecx, edx, edi};
+  CHECK_LE(static_cast<size_t>(register_parameter_count),
+           arraysize(default_stub_registers));
+  data->InitializePlatformSpecific(register_parameter_count,
+                                   default_stub_registers);
+}
 
 const Register LoadDescriptor::ReceiverRegister() { return edx; }
 const Register LoadDescriptor::NameRegister() { return ecx; }
@@ -44,23 +52,15 @@
 const Register StoreTransitionDescriptor::MapRegister() { return ebx; }
 
 
-const Register LoadGlobalViaContextDescriptor::SlotRegister() { return ebx; }
-
-
 const Register StoreGlobalViaContextDescriptor::SlotRegister() { return ebx; }
 const Register StoreGlobalViaContextDescriptor::ValueRegister() { return eax; }
 
 
-const Register InstanceOfDescriptor::LeftRegister() { return edx; }
-const Register InstanceOfDescriptor::RightRegister() { return eax; }
-
-
 const Register StringCompareDescriptor::LeftRegister() { return edx; }
 const Register StringCompareDescriptor::RightRegister() { return eax; }
 
-
-const Register ApiGetterDescriptor::function_address() { return edx; }
-
+const Register ApiGetterDescriptor::HolderRegister() { return ecx; }
+const Register ApiGetterDescriptor::CallbackRegister() { return eax; }
 
 const Register MathPowTaggedDescriptor::exponent() { return eax; }
 
@@ -250,50 +250,37 @@
 SIMD128_TYPES(SIMD128_ALLOC_DESC)
 #undef SIMD128_ALLOC_DESC
 
-void AllocateInNewSpaceDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  Register registers[] = {eax};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-void ArrayConstructorConstantArgCountDescriptor::InitializePlatformSpecific(
+void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // register state
   // eax -- number of arguments
   // edi -- function
   // ebx -- allocation site with elements kind
-  Register registers[] = {edi, ebx};
+  Register registers[] = {edi, ebx, eax};
   data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
-
-void ArrayConstructorDescriptor::InitializePlatformSpecific(
+void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
-  // stack param count needs (constructor pointer, and single argument)
-  Register registers[] = {edi, ebx, eax};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-void InternalArrayConstructorConstantArgCountDescriptor::
-    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
   // register state
   // eax -- number of arguments
   // edi -- function
-  Register registers[] = {edi};
+  // ebx -- allocation site with elements kind
+  Register registers[] = {edi, ebx, eax};
   data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
-
-void InternalArrayConstructorDescriptor::InitializePlatformSpecific(
+void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
-  // stack param count needs (constructor pointer, and single argument)
-  Register registers[] = {edi, eax};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
+  // register state
+  // eax -- number of arguments
+  // edi -- function
+  // ebx -- allocation site with elements kind
+  Register registers[] = {edi, ebx, eax};
+  data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
-void FastArrayPushDescriptor::InitializePlatformSpecific(
+void VarArgFunctionDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // stack param count needs (arg count)
   Register registers[] = {eax};
@@ -320,6 +307,11 @@
   data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
 }
 
+void CountOpDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {eax};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
 
 void StringAddDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
@@ -380,8 +372,8 @@
 void InterpreterDispatchDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {
-      kInterpreterAccumulatorRegister, kInterpreterRegisterFileRegister,
-      kInterpreterBytecodeOffsetRegister, kInterpreterBytecodeArrayRegister};
+      kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
+      kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
@@ -416,6 +408,16 @@
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
 
+void ResumeGeneratorDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {
+      eax,  // the value to pass to the generator
+      ebx,  // the JSGeneratorObject to resume
+      edx   // the resume mode (tagged)
+  };
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
 }  // namespace internal
 }  // namespace v8
 
diff --git a/src/x87/macro-assembler-x87.cc b/src/x87/macro-assembler-x87.cc
index b46167d..ef96912 100644
--- a/src/x87/macro-assembler-x87.cc
+++ b/src/x87/macro-assembler-x87.cc
@@ -973,6 +973,17 @@
   }
 }
 
+void MacroAssembler::AssertGeneratorObject(Register object) {
+  if (emit_debug_code()) {
+    test(object, Immediate(kSmiTagMask));
+    Check(not_equal, kOperandIsASmiAndNotAGeneratorObject);
+    Push(object);
+    CmpObjectType(object, JS_GENERATOR_OBJECT_TYPE, object);
+    Pop(object);
+    Check(equal, kOperandIsNotAGeneratorObject);
+  }
+}
+
 void MacroAssembler::AssertReceiver(Register object) {
   if (emit_debug_code()) {
     test(object, Immediate(kSmiTagMask));
@@ -1032,8 +1043,8 @@
 
 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
   mov(vector, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
-  mov(vector, FieldOperand(vector, JSFunction::kSharedFunctionInfoOffset));
-  mov(vector, FieldOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset));
+  mov(vector, FieldOperand(vector, JSFunction::kLiteralsOffset));
+  mov(vector, FieldOperand(vector, LiteralsArray::kFeedbackVectorOffset));
 }
 
 
@@ -1458,6 +1469,7 @@
                               AllocationFlags flags) {
   DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
   DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -1499,26 +1511,23 @@
 
   // Calculate new top and bail out if space is exhausted.
   Register top_reg = result_end.is_valid() ? result_end : result;
+
   if (!top_reg.is(result)) {
     mov(top_reg, result);
   }
   add(top_reg, Immediate(object_size));
-  j(carry, gc_required);
   cmp(top_reg, Operand::StaticVariable(allocation_limit));
   j(above, gc_required);
 
-  // Update allocation top.
-  UpdateAllocationTopHelper(top_reg, scratch, flags);
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    UpdateAllocationTopHelper(top_reg, scratch, flags);
+  }
 
-  // Tag result if requested.
-  bool tag_result = (flags & TAG_OBJECT) != 0;
   if (top_reg.is(result)) {
-    if (tag_result) {
-      sub(result, Immediate(object_size - kHeapObjectTag));
-    } else {
-      sub(result, Immediate(object_size));
-    }
-  } else if (tag_result) {
+    sub(result, Immediate(object_size - kHeapObjectTag));
+  } else {
+    // Tag the result.
     DCHECK(kHeapObjectTag == 1);
     inc(result);
   }
@@ -1535,6 +1544,8 @@
                               Label* gc_required,
                               AllocationFlags flags) {
   DCHECK((flags & SIZE_IN_WORDS) == 0);
+  DCHECK((flags & ALLOCATION_FOLDING_DOMINATOR) == 0);
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -1592,16 +1603,14 @@
   cmp(result_end, Operand::StaticVariable(allocation_limit));
   j(above, gc_required);
 
-  if ((flags & TAG_OBJECT) != 0) {
-    DCHECK(kHeapObjectTag == 1);
-    inc(result);
-  }
+  // Tag result.
+  DCHECK(kHeapObjectTag == 1);
+  inc(result);
 
   // Update allocation top.
   UpdateAllocationTopHelper(result_end, scratch, flags);
 }
 
-
 void MacroAssembler::Allocate(Register object_size,
                               Register result,
                               Register result_end,
@@ -1609,6 +1618,7 @@
                               Label* gc_required,
                               AllocationFlags flags) {
   DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
+  DCHECK((flags & ALLOCATION_FOLDED) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -1652,20 +1662,66 @@
     mov(result_end, object_size);
   }
   add(result_end, result);
-  j(carry, gc_required);
   cmp(result_end, Operand::StaticVariable(allocation_limit));
   j(above, gc_required);
 
-  // Tag result if requested.
-  if ((flags & TAG_OBJECT) != 0) {
-    DCHECK(kHeapObjectTag == 1);
-    inc(result);
-  }
+  // Tag result.
+  DCHECK(kHeapObjectTag == 1);
+  inc(result);
 
-  // Update allocation top.
-  UpdateAllocationTopHelper(result_end, scratch, flags);
+  if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
+    // The top pointer is not updated for allocation folding dominators.
+    UpdateAllocationTopHelper(result_end, scratch, flags);
+  }
 }
 
+void MacroAssembler::FastAllocate(int object_size, Register result,
+                                  Register result_end, AllocationFlags flags) {
+  DCHECK(!result.is(result_end));
+  // Load address of new object into result.
+  LoadAllocationTopHelper(result, no_reg, flags);
+
+  if ((flags & DOUBLE_ALIGNMENT) != 0) {
+    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
+    Label aligned;
+    test(result, Immediate(kDoubleAlignmentMask));
+    j(zero, &aligned, Label::kNear);
+    mov(Operand(result, 0),
+        Immediate(isolate()->factory()->one_pointer_filler_map()));
+    add(result, Immediate(kDoubleSize / 2));
+    bind(&aligned);
+  }
+
+  lea(result_end, Operand(result, object_size));
+  UpdateAllocationTopHelper(result_end, no_reg, flags);
+
+  DCHECK(kHeapObjectTag == 1);
+  inc(result);
+}
+
+void MacroAssembler::FastAllocate(Register object_size, Register result,
+                                  Register result_end, AllocationFlags flags) {
+  DCHECK(!result.is(result_end));
+  // Load address of new object into result.
+  LoadAllocationTopHelper(result, no_reg, flags);
+
+  if ((flags & DOUBLE_ALIGNMENT) != 0) {
+    DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
+    Label aligned;
+    test(result, Immediate(kDoubleAlignmentMask));
+    j(zero, &aligned, Label::kNear);
+    mov(Operand(result, 0),
+        Immediate(isolate()->factory()->one_pointer_filler_map()));
+    add(result, Immediate(kDoubleSize / 2));
+    bind(&aligned);
+  }
+
+  lea(result_end, Operand(result, object_size, times_1, 0));
+  UpdateAllocationTopHelper(result_end, no_reg, flags);
+
+  DCHECK(kHeapObjectTag == 1);
+  inc(result);
+}
 
 void MacroAssembler::AllocateHeapNumber(Register result,
                                         Register scratch1,
@@ -1674,7 +1730,7 @@
                                         MutableMode mode) {
   // Allocate heap number in new space.
   Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   Handle<Map> map = mode == MUTABLE
       ? isolate()->factory()->mutable_heap_number_map()
@@ -1700,15 +1756,9 @@
   and_(scratch1, Immediate(~kObjectAlignmentMask));
 
   // Allocate two byte string in new space.
-  Allocate(SeqTwoByteString::kHeaderSize,
-           times_1,
-           scratch1,
-           REGISTER_VALUE_IS_INT32,
-           result,
-           scratch2,
-           scratch3,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(SeqTwoByteString::kHeaderSize, times_1, scratch1,
+           REGISTER_VALUE_IS_INT32, result, scratch2, scratch3, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1734,15 +1784,9 @@
   and_(scratch1, Immediate(~kObjectAlignmentMask));
 
   // Allocate one-byte string in new space.
-  Allocate(SeqOneByteString::kHeaderSize,
-           times_1,
-           scratch1,
-           REGISTER_VALUE_IS_INT32,
-           result,
-           scratch2,
-           scratch3,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(SeqOneByteString::kHeaderSize, times_1, scratch1,
+           REGISTER_VALUE_IS_INT32, result, scratch2, scratch3, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1762,7 +1806,7 @@
 
   // Allocate one-byte string in new space.
   Allocate(SeqOneByteString::SizeFor(length), result, scratch1, scratch2,
-           gc_required, TAG_OBJECT);
+           gc_required, NO_ALLOCATION_FLAGS);
 
   // Set the map, length and hash field.
   mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1780,7 +1824,7 @@
                                         Label* gc_required) {
   // Allocate heap number in new space.
   Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   // Set the map. The other fields are left uninitialized.
   mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1792,12 +1836,8 @@
                                                Register scratch1,
                                                Register scratch2,
                                                Label* gc_required) {
-  Allocate(ConsString::kSize,
-           result,
-           scratch1,
-           scratch2,
-           gc_required,
-           TAG_OBJECT);
+  Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Set the map. The other fields are left uninitialized.
   mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1811,7 +1851,7 @@
                                           Label* gc_required) {
   // Allocate heap number in new space.
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   // Set the map. The other fields are left uninitialized.
   mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1825,7 +1865,7 @@
                                                  Label* gc_required) {
   // Allocate heap number in new space.
   Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
-           TAG_OBJECT);
+           NO_ALLOCATION_FLAGS);
 
   // Set the map. The other fields are left uninitialized.
   mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1841,7 +1881,8 @@
   DCHECK(!result.is(value));
 
   // Allocate JSValue in new space.
-  Allocate(JSValue::kSize, result, scratch, no_reg, gc_required, TAG_OBJECT);
+  Allocate(JSValue::kSize, result, scratch, no_reg, gc_required,
+           NO_ALLOCATION_FLAGS);
 
   // Initialize the JSValue.
   LoadGlobalFunctionInitialMap(constructor, scratch);
@@ -2261,10 +2302,11 @@
                                              const ParameterCount& expected,
                                              const ParameterCount& actual) {
   Label skip_flooding;
-  ExternalReference step_in_enabled =
-      ExternalReference::debug_step_in_enabled_address(isolate());
-  cmpb(Operand::StaticVariable(step_in_enabled), Immediate(0));
-  j(equal, &skip_flooding);
+  ExternalReference last_step_action =
+      ExternalReference::debug_last_step_action_address(isolate());
+  STATIC_ASSERT(StepFrame > StepIn);
+  cmpb(Operand::StaticVariable(last_step_action), Immediate(StepIn));
+  j(less, &skip_flooding);
   {
     FrameScope frame(this,
                      has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
@@ -2600,7 +2642,7 @@
 
 
 void MacroAssembler::Move(Register dst, const Immediate& x) {
-  if (x.is_zero()) {
+  if (x.is_zero() && RelocInfo::IsNone(x.rmode_)) {
     xor_(dst, dst);  // Shorter than mov of 32-bit immediate 0.
   } else {
     mov(dst, x);
diff --git a/src/x87/macro-assembler-x87.h b/src/x87/macro-assembler-x87.h
index 5571413..42b7eb1 100644
--- a/src/x87/macro-assembler-x87.h
+++ b/src/x87/macro-assembler-x87.h
@@ -19,10 +19,11 @@
 const Register kReturnRegister2 = {Register::kCode_edi};
 const Register kJSFunctionRegister = {Register::kCode_edi};
 const Register kContextRegister = {Register::kCode_esi};
+const Register kAllocateSizeRegister = {Register::kCode_edx};
 const Register kInterpreterAccumulatorRegister = {Register::kCode_eax};
-const Register kInterpreterRegisterFileRegister = {Register::kCode_edx};
 const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_ecx};
 const Register kInterpreterBytecodeArrayRegister = {Register::kCode_edi};
+const Register kInterpreterDispatchTableRegister = {Register::kCode_esi};
 const Register kJavaScriptCallArgCountRegister = {Register::kCode_eax};
 const Register kJavaScriptCallNewTargetRegister = {Register::kCode_edx};
 const Register kRuntimeCallFunctionRegister = {Register::kCode_ebx};
@@ -499,6 +500,23 @@
     j(not_zero, not_smi_label, distance);
   }
 
+  // Jump if the value cannot be represented by a smi.
+  inline void JumpIfNotValidSmiValue(Register value, Register scratch,
+                                     Label* on_invalid,
+                                     Label::Distance distance = Label::kFar) {
+    mov(scratch, value);
+    add(scratch, Immediate(0x40000000U));
+    j(sign, on_invalid, distance);
+  }
+
+  // Jump if the unsigned integer value cannot be represented by a smi.
+  inline void JumpIfUIntNotValidSmiValue(
+      Register value, Label* on_invalid,
+      Label::Distance distance = Label::kFar) {
+    cmp(value, Immediate(0x40000000U));
+    j(above_equal, on_invalid, distance);
+  }
+
   void LoadInstanceDescriptors(Register map, Register descriptors);
   void EnumLength(Register dst, Register map);
   void NumberOfOwnDescriptors(Register dst, Register map);
@@ -552,6 +570,10 @@
   // enabled via --debug-code.
   void AssertBoundFunction(Register object);
 
+  // Abort execution if argument is not a JSGeneratorObject,
+  // enabled via --debug-code.
+  void AssertGeneratorObject(Register object);
+
   // Abort execution if argument is not a JSReceiver, enabled via --debug-code.
   void AssertReceiver(Register object);
 
@@ -607,6 +629,14 @@
   void Allocate(Register object_size, Register result, Register result_end,
                 Register scratch, Label* gc_required, AllocationFlags flags);
 
+  // FastAllocate is right now only used for folded allocations. It just
+  // increments the top pointer without checking against limit. This can only
+  // be done if it was proved earlier that the allocation will succeed.
+  void FastAllocate(int object_size, Register result, Register result_end,
+                    AllocationFlags flags);
+  void FastAllocate(Register object_size, Register result, Register result_end,
+                    AllocationFlags flags);
+
   // Allocate a heap number in new space with undefined value. The
   // register scratch2 can be passed as no_reg; the others must be
   // valid registers. Returns tagged pointer in result register, or
diff --git a/src/zone.h b/src/zone.h
index fa21155..29055cb 100644
--- a/src/zone.h
+++ b/src/zone.h
@@ -8,9 +8,9 @@
 #include <limits>
 
 #include "src/base/accounting-allocator.h"
+#include "src/base/hashmap.h"
 #include "src/base/logging.h"
 #include "src/globals.h"
-#include "src/hashmap.h"
 #include "src/list.h"
 #include "src/splay-tree.h"
 
@@ -244,8 +244,7 @@
   void operator delete(void* pointer, Zone* zone) { UNREACHABLE(); }
 };
 
-
-typedef TemplateHashMapImpl<ZoneAllocationPolicy> ZoneHashMap;
+typedef base::TemplateHashMapImpl<ZoneAllocationPolicy> ZoneHashMap;
 
 }  // namespace internal
 }  // namespace v8
diff --git a/test/BUILD.gn b/test/BUILD.gn
new file mode 100644
index 0000000..271df0d
--- /dev/null
+++ b/test/BUILD.gn
@@ -0,0 +1,203 @@
+# Copyright 2016 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("../gni/isolate.gni")
+
+group("gn_all") {
+  testonly = true
+
+  deps = [
+    ":default_tests",
+  ]
+
+  if (host_os != "mac" || !is_android) {
+    # These items don't compile for Android on Mac.
+    deps += [
+      "cctest:cctest",
+      "cctest:generate-bytecode-expectations",
+      "unittests:unittests",
+    ]
+  }
+
+  if (v8_test_isolation_mode != "noop") {
+    deps += [
+      ":bot_default_run",
+      ":benchmarks_run",
+      ":default_run",
+      ":mozilla_run",
+      ":simdjs_run",
+      "test262:test262_run",
+    ]
+  }
+}
+
+###############################################################################
+# Test groups
+#
+
+group("default_tests") {
+  testonly = true
+
+  if (v8_test_isolation_mode != "noop") {
+    deps = [
+      ":cctest_run",
+      ":fuzzer_run",
+      ":intl_run",
+      ":message_run",
+      ":mjsunit_run",
+      ":preparser_run",
+      ":unittests_run",
+    ]
+  }
+}
+
+v8_isolate_run("bot_default") {
+  deps = [
+    ":default_tests", 
+    ":webkit_run",
+  ]
+
+  isolate = "bot_default.isolate"
+}
+
+v8_isolate_run("default") {
+  deps = [
+    ":default_tests",
+  ]
+
+  isolate = "default.isolate"
+}
+
+v8_isolate_run("ignition") {
+  deps = [
+    ":cctest_run",
+    ":mjsunit_run",
+  ]
+
+  isolate = "ignition.isolate"
+}
+
+v8_isolate_run("optimize_for_size") {
+  deps = [
+    ":cctest_run",
+    ":intl_run",
+    ":mjsunit_run",
+    ":webkit_run",
+  ]
+
+  isolate = "optimize_for_size.isolate"
+}
+
+v8_isolate_run("perf") {
+  deps = [
+    ":cctest_exe_run",
+    "..:d8_run",
+  ]
+
+  isolate = "perf.isolate"
+}
+
+###############################################################################
+# Subtests
+#
+
+v8_isolate_run("benchmarks") {
+  deps = [
+    "..:d8_run",
+  ]
+
+  isolate = "benchmarks/benchmarks.isolate"
+}
+
+v8_isolate_run("cctest") {
+  deps = [
+    ":cctest_exe_run",
+  ]
+
+  isolate = "cctest/cctest.isolate"
+}
+
+v8_isolate_run("cctest_exe") {
+  deps = [
+    "cctest:cctest",
+  ]
+
+  isolate = "cctest/cctest_exe.isolate"
+}
+
+v8_isolate_run("fuzzer") {
+  deps = [
+    "..:v8_simple_json_fuzzer",
+    "..:v8_simple_parser_fuzzer",
+    "..:v8_simple_regexp_fuzzer",
+    "..:v8_simple_wasm_fuzzer",
+    "..:v8_simple_wasm_asmjs_fuzzer",
+  ]
+
+  isolate = "fuzzer/fuzzer.isolate"
+}
+
+v8_isolate_run("intl") {
+  deps = [
+    "..:d8_run",
+  ]
+
+  isolate = "intl/intl.isolate"
+}
+
+v8_isolate_run("message") {
+  deps = [
+    "..:d8_run",
+  ]
+
+  isolate = "message/message.isolate"
+}
+
+v8_isolate_run("mjsunit") {
+  deps = [
+    "..:d8_run",
+  ]
+
+  isolate = "mjsunit/mjsunit.isolate"
+}
+
+v8_isolate_run("mozilla") {
+  deps = [
+    "..:d8_run",
+  ]
+
+  isolate = "mozilla/mozilla.isolate"
+}
+
+v8_isolate_run("preparser") {
+  deps = [
+    "..:d8_run",
+  ]
+
+  isolate = "preparser/preparser.isolate"
+}
+
+v8_isolate_run("simdjs") {
+  deps = [
+    "..:d8_run",
+  ]
+
+  isolate = "simdjs/simdjs.isolate"
+}
+
+v8_isolate_run("unittests") {
+  deps = [
+    "unittests:unittests",
+  ]
+
+  isolate = "unittests/unittests.isolate"
+}
+
+v8_isolate_run("webkit") {
+  deps = [
+    "..:d8_run",
+  ]
+
+  isolate = "webkit/webkit.isolate"
+}
diff --git a/test/benchmarks/benchmarks.gyp b/test/benchmarks/benchmarks.gyp
index 3884b09..0822ee4 100644
--- a/test/benchmarks/benchmarks.gyp
+++ b/test/benchmarks/benchmarks.gyp
@@ -13,8 +13,8 @@
             '../../src/d8.gyp:d8_run',
           ],
           'includes': [
-            '../../build/features.gypi',
-            '../../build/isolate.gypi',
+            '../../gypfiles/features.gypi',
+            '../../gypfiles/isolate.gypi',
           ],
           'sources': [
             'benchmarks.isolate',
diff --git a/test/bot_default.gyp b/test/bot_default.gyp
index 9b39f58..0467918 100644
--- a/test/bot_default.gyp
+++ b/test/bot_default.gyp
@@ -20,8 +20,8 @@
             'webkit/webkit.gyp:webkit_run',
           ],
           'includes': [
-            '../build/features.gypi',
-            '../build/isolate.gypi',
+            '../gypfiles/features.gypi',
+            '../gypfiles/isolate.gypi',
           ],
           'sources': [
             'bot_default.isolate',
diff --git a/test/cctest/BUILD.gn b/test/cctest/BUILD.gn
new file mode 100644
index 0000000..38738b7
--- /dev/null
+++ b/test/cctest/BUILD.gn
@@ -0,0 +1,402 @@
+# Copyright 2016 The V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Please keep this file in sync with cctest.gyp.
+
+import("../../gni/v8.gni")
+
+v8_executable("cctest") {
+  testonly = true
+
+  sources = [
+    "$target_gen_dir/resources.cc",
+    "cctest.cc",
+    "compiler/c-signature.h",
+    "compiler/code-assembler-tester.h",
+    "compiler/codegen-tester.cc",
+    "compiler/codegen-tester.h",
+    "compiler/function-tester.h",
+    "compiler/graph-builder-tester.h",
+    "compiler/test-basic-block-profiler.cc",
+    "compiler/test-branch-combine.cc",
+    "compiler/test-code-assembler.cc",
+    "compiler/test-gap-resolver.cc",
+    "compiler/test-graph-visualizer.cc",
+    "compiler/test-instruction.cc",
+    "compiler/test-js-constant-cache.cc",
+    "compiler/test-js-context-specialization.cc",
+    "compiler/test-js-typed-lowering.cc",
+    "compiler/test-jump-threading.cc",
+    "compiler/test-linkage.cc",
+    "compiler/test-loop-analysis.cc",
+    "compiler/test-loop-assignment-analysis.cc",
+    "compiler/test-machine-operator-reducer.cc",
+    "compiler/test-multiple-return.cc",
+    "compiler/test-node.cc",
+    "compiler/test-operator.cc",
+    "compiler/test-osr.cc",
+    "compiler/test-representation-change.cc",
+    "compiler/test-run-bytecode-graph-builder.cc",
+    "compiler/test-run-calls-to-external-references.cc",
+    "compiler/test-run-deopt.cc",
+    "compiler/test-run-inlining.cc",
+    "compiler/test-run-intrinsics.cc",
+    "compiler/test-run-jsbranches.cc",
+    "compiler/test-run-jscalls.cc",
+    "compiler/test-run-jsexceptions.cc",
+    "compiler/test-run-jsobjects.cc",
+    "compiler/test-run-jsops.cc",
+    "compiler/test-run-load-store.cc",
+    "compiler/test-run-machops.cc",
+    "compiler/test-run-native-calls.cc",
+    "compiler/test-run-stackcheck.cc",
+    "compiler/test-run-stubs.cc",
+    "compiler/test-run-variables.cc",
+    "compiler/test-run-wasm-machops.cc",
+    "compiler/test-simplified-lowering.cc",
+    "expression-type-collector.cc",
+    "expression-type-collector.h",
+    "gay-fixed.cc",
+    "gay-precision.cc",
+    "gay-shortest.cc",
+    "heap/heap-tester.h",
+    "heap/heap-utils.cc",
+    "heap/heap-utils.h",
+    "heap/test-alloc.cc",
+    "heap/test-array-buffer-tracker.cc",
+    "heap/test-compaction.cc",
+    "heap/test-heap.cc",
+    "heap/test-incremental-marking.cc",
+    "heap/test-lab.cc",
+    "heap/test-mark-compact.cc",
+    "heap/test-page-promotion.cc",
+    "heap/test-spaces.cc",
+    "interpreter/bytecode-expectations-printer.cc",
+    "interpreter/bytecode-expectations-printer.h",
+    "interpreter/interpreter-tester.cc",
+    "interpreter/source-position-matcher.cc",
+    "interpreter/source-position-matcher.h",
+    "interpreter/test-bytecode-generator.cc",
+    "interpreter/test-interpreter-intrinsics.cc",
+    "interpreter/test-interpreter.cc",
+    "interpreter/test-source-positions.cc",
+    "libsampler/test-sampler.cc",
+    "print-extension.cc",
+    "profiler-extension.cc",
+    "test-access-checks.cc",
+    "test-accessors.cc",
+    "test-api-accessors.cc",
+    "test-api-fast-accessor-builder.cc",
+    "test-api-interceptors.cc",
+    "test-api.cc",
+    "test-api.h",
+    "test-array-list.cc",
+    "test-asm-validator.cc",
+    "test-ast-expression-visitor.cc",
+    "test-ast.cc",
+    "test-atomicops.cc",
+    "test-bignum-dtoa.cc",
+    "test-bignum.cc",
+    "test-bit-vector.cc",
+    "test-circular-queue.cc",
+    "test-code-cache.cc",
+    "test-code-layout.cc",
+    "test-code-stub-assembler.cc",
+    "test-compiler.cc",
+    "test-constantpool.cc",
+    "test-conversions.cc",
+    "test-cpu-profiler.cc",
+    "test-date.cc",
+    "test-debug.cc",
+    "test-decls.cc",
+    "test-deoptimization.cc",
+    "test-dictionary.cc",
+    "test-diy-fp.cc",
+    "test-double.cc",
+    "test-dtoa.cc",
+    "test-eh-frame-hdr.cc",
+    "test-elements-kind.cc",
+    "test-fast-dtoa.cc",
+    "test-feedback-vector.cc",
+    "test-field-type-tracking.cc",
+    "test-fixed-dtoa.cc",
+    "test-flags.cc",
+    "test-func-name-inference.cc",
+    "test-global-handles.cc",
+    "test-global-object.cc",
+    "test-hashing.cc",
+    "test-hashmap.cc",
+    "test-heap-profiler.cc",
+    "test-hydrogen-types.cc",
+    "test-identity-map.cc",
+    "test-inobject-slack-tracking.cc",
+    "test-list.cc",
+    "test-liveedit.cc",
+    "test-lockers.cc",
+    "test-log.cc",
+    "test-mementos.cc",
+    "test-parsing.cc",
+    "test-platform.cc",
+    "test-profile-generator.cc",
+    "test-random-number-generator.cc",
+    "test-receiver-check-hidden-prototype.cc",
+    "test-regexp.cc",
+    "test-reloc-info.cc",
+    "test-representation.cc",
+    "test-sampler-api.cc",
+    "test-serialize.cc",
+    "test-simd.cc",
+    "test-strings.cc",
+    "test-strtod.cc",
+    "test-symbols.cc",
+    "test-thread-termination.cc",
+    "test-threads.cc",
+    "test-trace-event.cc",
+    "test-transitions.cc",
+    "test-typedarrays.cc",
+    "test-types.cc",
+    "test-unbound-queue.cc",
+    "test-unboxed-doubles.cc",
+    "test-unique.cc",
+    "test-unscopables-hidden-prototype.cc",
+    "test-usecounters.cc",
+    "test-utils.cc",
+    "test-version.cc",
+    "test-weakmaps.cc",
+    "test-weaksets.cc",
+    "trace-extension.cc",
+    "wasm/test-run-wasm-64.cc",
+    "wasm/test-run-wasm-asmjs.cc",
+    "wasm/test-run-wasm-interpreter.cc",
+    "wasm/test-run-wasm-js.cc",
+    "wasm/test-run-wasm-module.cc",
+    "wasm/test-run-wasm-relocation.cc",
+    "wasm/test-run-wasm.cc",
+    "wasm/test-signatures.h",
+    "wasm/test-wasm-function-name-table.cc",
+    "wasm/test-wasm-stack.cc",
+    "wasm/test-wasm-trap-position.cc",
+    "wasm/wasm-run-utils.h",
+  ]
+
+  if (v8_target_cpu == "arm") {
+    sources += [
+      "test-assembler-arm.cc",
+      "test-code-stubs-arm.cc",
+      "test-code-stubs.cc",
+      "test-disasm-arm.cc",
+      "test-macro-assembler-arm.cc",
+      "test-run-wasm-relocation-arm.cc",
+    ]
+  } else if (v8_target_cpu == "arm64") {
+    sources += [
+      "test-assembler-arm64.cc",
+      "test-code-stubs-arm64.cc",
+      "test-code-stubs.cc",
+      "test-disasm-arm64.cc",
+      "test-fuzz-arm64.cc",
+      "test-javascript-arm64.cc",
+      "test-js-arm64-variables.cc",
+      "test-run-wasm-relocation-arm64.cc",
+      "test-utils-arm64.cc",
+    ]
+  } else if (v8_target_cpu == "x86") {
+    sources += [
+      "test-assembler-ia32.cc",
+      "test-code-stubs-ia32.cc",
+      "test-code-stubs.cc",
+      "test-disasm-ia32.cc",
+      "test-log-stack-tracer.cc",
+      "test-macro-assembler-ia32.cc",
+      "test-run-wasm-relocation-ia32.cc",
+    ]
+  } else if (v8_target_cpu == "mips") {
+    sources += [
+      "test-assembler-mips.cc",
+      "test-code-stubs-mips.cc",
+      "test-code-stubs.cc",
+      "test-disasm-mips.cc",
+      "test-macro-assembler-mips.cc",
+    ]
+  } else if (v8_target_cpu == "mipsel") {
+    sources += [
+      "test-assembler-mips.cc",
+      "test-code-stubs-mips.cc",
+      "test-code-stubs.cc",
+      "test-disasm-mips.cc",
+      "test-macro-assembler-mips.cc",
+    ]
+  } else if (v8_target_cpu == "mips64") {
+    sources += [
+      "test-assembler-mips64.cc",
+      "test-code-stubs-mips64.cc",
+      "test-code-stubs.cc",
+      "test-disasm-mips64.cc",
+      "test-macro-assembler-mips64.cc",
+    ]
+  } else if (v8_target_cpu == "mips64el") {
+    sources += [
+      "test-assembler-mips64.cc",
+      "test-code-stubs-mips64.cc",
+      "test-code-stubs.cc",
+      "test-disasm-mips64.cc",
+      "test-macro-assembler-mips64.cc",
+    ]
+  } else if (v8_target_cpu == "x64") {
+    sources += [
+      "test-assembler-x64.cc",
+      "test-code-stubs-x64.cc",
+      "test-code-stubs.cc",
+      "test-disasm-x64.cc",
+      "test-log-stack-tracer.cc",
+      "test-macro-assembler-x64.cc",
+      "test-run-wasm-relocation-x64.cc",
+    ]
+  } else if (v8_target_cpu == "x87") {
+    sources += [
+      "test-assembler-x87.cc",
+      "test-code-stubs-x87.cc",
+      "test-code-stubs.cc",
+      "test-disasm-x87.cc",
+      "test-log-stack-tracer.cc",
+      "test-macro-assembler-x87.cc",
+      "test-run-wasm-relocation-x87.cc",
+    ]
+  } else if (v8_target_cpu == "ppc" || v8_target_cpu == "ppc64") {
+    sources += [
+      "test-assembler-ppc.cc",
+      "test-code-stubs.cc",
+      "test-disasm-ppc.cc",
+    ]
+  } else if (v8_target_cpu == "s390" || v8_target_cpu == "s390x") {
+    sources += [
+      "test-assembler-s390.cc",
+      "test-code-stubs.cc",
+      "test-disasm-s390.cc",
+    ]
+  }
+
+  if (is_linux) {
+    # TODO(machenbach): Translate 'or OS=="qnx"' from gyp.
+    sources += [ "test-platform-linux.cc" ]
+  } else if (is_win) {
+    sources += [ "test-platform-win32.cc" ]
+    # TODO(machenbach): Translate from gyp.
+    # "msvs_settings": {
+    #   "VCCLCompilerTool": {
+    #     # MSVS wants this for gay-{precision,shortest}.cc.
+    #     "AdditionalOptions": ["/bigobj"],
+    #   },
+    # },
+  }
+
+  configs = [
+    "../..:external_config",
+    "../..:internal_config_base",
+  ]
+
+  # TODO(machenbach): Translate from gyp.
+  #['v8_target_cpu=="ppc" or v8_target_cpu=="ppc64" \
+  #  or v8_target_cpu=="arm" or v8_target_cpu=="arm64" \
+  #  or v8_target_cpu=="s390" or v8_target_cpu=="s390x"', {
+  #  # disable fmadd/fmsub so that expected results match generated code in
+  #  # RunFloat64MulAndFloat64Add1 and friends.
+  #  'cflags': ['-ffp-contract=off'],
+  #}],
+
+  # TODO(machenbach): Translate from gyp.
+  #["OS=="aix"", {
+  #  "ldflags": [ "-Wl,-bbigtoc" ],
+  #}],
+
+  deps = [
+    ":resources",
+    "../..:v8_libplatform",
+    "//build/config/sanitizers:deps",
+    "//build/win:default_exe_manifest",
+  ]
+
+  if (is_component_build) {
+    # cctest can't be built against a shared library, so we
+    # need to depend on the underlying static target in that case.
+    deps += [ "../..:v8_maybe_snapshot" ]
+  } else {
+    deps += [ "../..:v8" ]
+  }
+
+  if (is_win) {
+    # This warning is benignly triggered by the U16 and U32 macros in
+    # bytecode-utils.h.
+    # C4309: 'static_cast': truncation of constant value
+    cflags = [ "/wd4309" ]
+
+    # Suppress warnings about importing locally defined symbols.
+    if (is_component_build) {
+      ldflags = [
+        "/ignore:4049",
+        "/ignore:4217",
+      ]
+    }
+  }
+}
+
+action("resources") {
+  visibility = [ ":*" ]  # Only targets in this file can depend on this.
+
+  script = "../../tools/js2c.py"
+
+  # The script depends on this other script, this rule causes a rebuild if it
+  # changes.
+  inputs = [
+    "../../tools/jsmin.py",
+  ]
+
+  # NOSORT
+  sources = [
+    "../../tools/splaytree.js",
+    "../../tools/codemap.js",
+    "../../tools/csvparser.js",
+    "../../tools/consarray.js",
+    "../../tools/profile.js",
+    "../../tools/profile_view.js",
+    "../../tools/logreader.js",
+    "log-eq-of-logging-and-traversal.js",
+  ]
+
+  outputs = [
+    "$target_gen_dir/resources.cc",
+  ]
+
+  args = [
+    rebase_path("$target_gen_dir/resources.cc", root_build_dir),
+    "TEST",
+  ]
+  args += rebase_path(sources, root_build_dir)
+}
+
+v8_executable("generate-bytecode-expectations") {
+  sources = [
+    "interpreter/bytecode-expectations-printer.cc",
+    "interpreter/bytecode-expectations-printer.h",
+    "interpreter/generate-bytecode-expectations.cc",
+  ]
+
+  configs = [
+    "../..:external_config",
+    "../..:internal_config_base",
+  ]
+
+  deps = [
+    "../..:v8_libplatform",
+    "//build/config/sanitizers:deps",
+    "//build/win:default_exe_manifest",
+  ]
+
+  if (is_component_build) {
+    # Same as cctest, we need to depend on the underlying static target.
+    deps += [ "../..:v8_maybe_snapshot" ]
+  } else {
+    deps += [ "../..:v8" ]
+  }
+}
diff --git a/test/cctest/cctest.cc b/test/cctest/cctest.cc
index 5681f70..312001a 100644
--- a/test/cctest/cctest.cc
+++ b/test/cctest/cctest.cc
@@ -186,7 +186,7 @@
     }
   }
 
-  v8::V8::InitializeICU();
+  v8::V8::InitializeICUDefaultLocation(argv[0]);
   v8::Platform* platform = v8::platform::CreateDefaultPlatform();
   v8::V8::InitializePlatform(platform);
   v8::internal::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index 2e00e88..c71bc9f 100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -25,19 +25,21 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+# Please keep this file in sync with BUILD.gn.
+
 {
   'variables': {
     'v8_code': 1,
     'generated_file': '<(SHARED_INTERMEDIATE_DIR)/resources.cc',
   },
-  'includes': ['../../build/toolchain.gypi', '../../build/features.gypi'],
+  'includes': ['../../gypfiles/toolchain.gypi', '../../gypfiles/features.gypi'],
   'targets': [
     {
       'target_name': 'cctest',
       'type': 'executable',
       'dependencies': [
         'resources',
-        '../../tools/gyp/v8.gyp:v8_libplatform',
+        '../../src/v8.gyp:v8_libplatform',
       ],
       'include_dirs': [
         '../..',
@@ -47,14 +49,14 @@
         'compiler/c-signature.h',
         'compiler/codegen-tester.cc',
         'compiler/codegen-tester.h',
+        'compiler/code-assembler-tester.h',
         'compiler/function-tester.h',
         'compiler/graph-builder-tester.h',
         'compiler/test-basic-block-profiler.cc',
         'compiler/test-branch-combine.cc',
-        'compiler/test-changes-lowering.cc',
-        'compiler/test-code-stub-assembler.cc',
         'compiler/test-gap-resolver.cc',
         'compiler/test-graph-visualizer.cc',
+        'compiler/test-code-assembler.cc',
         'compiler/test-instruction.cc',
         'compiler/test-js-context-specialization.cc',
         'compiler/test-js-constant-cache.cc',
@@ -68,7 +70,6 @@
         'compiler/test-node.cc',
         'compiler/test-operator.cc',
         'compiler/test-osr.cc',
-        'compiler/test-pipeline.cc',
         'compiler/test-representation-change.cc',
         'compiler/test-run-bytecode-graph-builder.cc',
         'compiler/test-run-calls-to-external-references.cc',
@@ -80,35 +81,45 @@
         'compiler/test-run-jsexceptions.cc',
         'compiler/test-run-jsobjects.cc',
         'compiler/test-run-jsops.cc',
+        'compiler/test-run-load-store.cc',
         'compiler/test-run-machops.cc',
         'compiler/test-run-native-calls.cc',
         'compiler/test-run-stackcheck.cc',
         'compiler/test-run-stubs.cc',
         'compiler/test-run-variables.cc',
+        'compiler/test-run-wasm-machops.cc',
         'compiler/test-simplified-lowering.cc',
         'cctest.cc',
         'expression-type-collector.cc',
         'expression-type-collector.h',
         'interpreter/interpreter-tester.cc',
+        'interpreter/source-position-matcher.cc',
+        'interpreter/source-position-matcher.h',
         'interpreter/test-bytecode-generator.cc',
         'interpreter/test-interpreter.cc',
         'interpreter/test-interpreter-intrinsics.cc',
+        'interpreter/test-source-positions.cc',
         'interpreter/bytecode-expectations-printer.cc',
         'interpreter/bytecode-expectations-printer.h',
         'gay-fixed.cc',
         'gay-precision.cc',
         'gay-shortest.cc',
         'heap/heap-tester.h',
+        'heap/heap-utils.cc',
+        'heap/heap-utils.h',
         'heap/test-alloc.cc',
+        'heap/test-array-buffer-tracker.cc',
         'heap/test-compaction.cc',
         'heap/test-heap.cc',
         'heap/test-incremental-marking.cc',
         'heap/test-lab.cc',
         'heap/test-mark-compact.cc',
+        'heap/test-page-promotion.cc',
         'heap/test-spaces.cc',
-        'heap/utils-inl.h',
+        'libsampler/test-sampler.cc',
         'print-extension.cc',
         'profiler-extension.cc',
+        'test-access-checks.cc',
         'test-accessors.cc',
         'test-api.cc',
         'test-api.h',
@@ -124,6 +135,9 @@
         'test-bignum-dtoa.cc',
         'test-bit-vector.cc',
         'test-circular-queue.cc',
+        'test-code-cache.cc',
+        'test-code-layout.cc',
+        'test-code-stub-assembler.cc',
         'test-compiler.cc',
         'test-constantpool.cc',
         'test-conversions.cc',
@@ -137,6 +151,7 @@
         'test-double.cc',
         'test-dtoa.cc',
         'test-elements-kind.cc',
+        'test-eh-frame-hdr.cc',
         'test-fast-dtoa.cc',
         'test-feedback-vector.cc',
         'test-field-type-tracking.cc',
@@ -155,9 +170,7 @@
         'test-liveedit.cc',
         'test-lockers.cc',
         'test-log.cc',
-        'test-microtask-delivery.cc',
         'test-mementos.cc',
-        'test-object-observe.cc',
         'test-parsing.cc',
         'test-platform.cc',
         'test-profile-generator.cc',
@@ -178,11 +191,11 @@
         'test-transitions.cc',
         'test-typedarrays.cc',
         'test-types.cc',
-        'test-typing-reset.cc',
         'test-unbound-queue.cc',
         'test-unboxed-doubles.cc',
         'test-unique.cc',
         'test-unscopables-hidden-prototype.cc',
+        'test-usecounters.cc',
         'test-utils.cc',
         'test-version.cc',
         'test-weakmaps.cc',
@@ -190,9 +203,15 @@
         'trace-extension.cc',
         'wasm/test-run-wasm.cc',
         'wasm/test-run-wasm-64.cc',
+        'wasm/test-run-wasm-asmjs.cc',
+        'wasm/test-run-wasm-interpreter.cc',
         'wasm/test-run-wasm-js.cc',
         'wasm/test-run-wasm-module.cc',
         'wasm/test-signatures.h',
+        'wasm/test-wasm-function-name-table.cc',
+        'wasm/test-run-wasm-relocation.cc',
+        'wasm/test-wasm-stack.cc',
+        'wasm/test-wasm-trap-position.cc',
         'wasm/wasm-run-utils.h',
       ],
       'conditions': [
@@ -269,6 +288,15 @@
             'test-disasm-ppc.cc'
           ],
         }],
+        ['v8_target_arch=="mips"', {
+          'sources': [  ### gcmole(arch:mips) ###
+            'test-assembler-mips.cc',
+            'test-code-stubs.cc',
+            'test-code-stubs-mips.cc',
+            'test-disasm-mips.cc',
+            'test-macro-assembler-mips.cc'
+          ],
+        }],
         ['v8_target_arch=="mipsel"', {
           'sources': [  ### gcmole(arch:mipsel) ###
             'test-assembler-mips.cc',
@@ -278,8 +306,17 @@
             'test-macro-assembler-mips.cc'
           ],
         }],
+        ['v8_target_arch=="mips64"', {
+          'sources': [  ### gcmole(arch:mips64) ###
+            'test-assembler-mips64.cc',
+            'test-code-stubs.cc',
+            'test-code-stubs-mips64.cc',
+            'test-disasm-mips64.cc',
+            'test-macro-assembler-mips64.cc'
+          ],
+        }],
         ['v8_target_arch=="mips64el"', {
-          'sources': [
+          'sources': [  ### gcmole(arch:mips64el) ###
             'test-assembler-mips64.cc',
             'test-code-stubs.cc',
             'test-code-stubs-mips64.cc',
@@ -327,9 +364,9 @@
         ['component=="shared_library"', {
           # cctest can't be built against a shared library, so we need to
           # depend on the underlying static target in that case.
-          'dependencies': ['../../tools/gyp/v8.gyp:v8_maybe_snapshot'],
+          'dependencies': ['../../src/v8.gyp:v8_maybe_snapshot'],
         }, {
-          'dependencies': ['../../tools/gyp/v8.gyp:v8'],
+          'dependencies': ['../../src/v8.gyp:v8'],
         }],
       ],
     },
@@ -372,14 +409,14 @@
       'target_name': 'generate-bytecode-expectations',
       'type': 'executable',
       'dependencies': [
-        '../../tools/gyp/v8.gyp:v8_libplatform',
+        '../../src/v8.gyp:v8_libplatform',
       ],
       'conditions': [
         ['component=="shared_library"', {
           # Same as cctest, we need to depend on the underlying static target.
-          'dependencies': ['../../tools/gyp/v8.gyp:v8_maybe_snapshot'],
+          'dependencies': ['../../src/v8.gyp:v8_maybe_snapshot'],
         }, {
-          'dependencies': ['../../tools/gyp/v8.gyp:v8'],
+          'dependencies': ['../../src/v8.gyp:v8'],
         }],
       ],
       'include_dirs+': [
@@ -402,7 +439,7 @@
             'cctest',
           ],
           'includes': [
-            '../../build/isolate.gypi',
+            '../../gypfiles/isolate.gypi',
           ],
           'sources': [
             'cctest_exe.isolate',
@@ -415,7 +452,7 @@
             'cctest_exe_run',
           ],
           'includes': [
-            '../../build/isolate.gypi',
+            '../../gypfiles/isolate.gypi',
           ],
           'sources': [
             'cctest.isolate',
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index c992ab6..a669a83 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -132,6 +132,53 @@
   'test-debug/CallFunctionInDebugger': [PASS, ['mode == debug', SLOW]],
   'test-strings/StringOOM*': [PASS, ['mode == debug', SKIP]],
   'test-serialize/CustomSnapshotDataBlobImmortalImmovableRoots': [PASS, ['mode == debug', SKIP]],
+
+  ############################################################################
+  # Ignition
+
+  # TODO(rmcilroy,4680): Related to lack of code flushing. Check failed: !function->shared()->is_compiled() || function->IsOptimized().
+  'test-heap/TestCodeFlushingPreAged': [PASS, NO_IGNITION],
+  'test-heap/TestCodeFlushingIncrementalScavenge': [PASS, NO_IGNITION],
+  'test-heap/TestCodeFlushing': [PASS, NO_IGNITION],
+  'test-heap/TestCodeFlushingIncremental': [PASS, NO_IGNITION],
+  'test-heap/TestCodeFlushingIncrementalAbort': [PASS, ['mode == debug or dcheck_always_on == True', NO_IGNITION]],
+
+  # TODO(rmcilroy,4680): Fails to find the correct function name for the
+  # anonymous function. Fails without ignition but with --no-lazy also, so seems
+  # to be an issue when eagerly parsing.
+  'test-func-name-inference/ReturnAnonymousFunction': [PASS, NO_IGNITION],
+
+  # TODO(mythria,4780): Related to type feedback support for calls.
+  'test-feedback-vector/VectorCallICStates': [PASS, NO_IGNITION],
+  'test-feedback-vector/VectorCallCounts': [PASS, NO_IGNITION],
+  'test-compiler/FeedbackVectorPreservedAcrossRecompiles': [PASS, NO_IGNITION],
+  'test-heap/WeakFunctionInConstructor': [PASS, NO_IGNITION],
+  'test-heap/IncrementalMarkingClearsMonomorphicConstructor': [PASS, NO_IGNITION],
+  'test-heap/IncrementalMarkingPreservesMonomorphicConstructor': [PASS, NO_IGNITION],
+  'test-heap/IncrementalMarkingPreservesMonomorphicCallIC': [PASS, NO_IGNITION],
+  'test-heap/CellsInOptimizedCodeAreWeak': [PASS, NO_IGNITION],
+
+  # TODO(mythria,4680): Lack of code-ageing in interpreter.
+  'test-heap/Regress169209': [PASS, NO_IGNITION],
+
+  # TODO(mythria,4680): Lack of code-ageing and/or lack of compilation cache
+  # in interpreter.
+  'test-heap/CompilationCacheCachingBehavior': [PASS, NO_IGNITION],
+
+  # TODO(mstarzinger,4680): Fails due to the turbo-asm pipeline only being taken
+  # in compiler.cc GetLazyCode for uncompiled code, and no similar path for eager
+  # code.
+  'test-api/TurboAsmDisablesNeuter': [PASS, NO_IGNITION],
+
+  # TODO(mvstanton,4900): CHECK(!g_function->is_compiled());
+  'test-heap/TestUseOfIncrementalBarrierOnCompileLazy': [PASS, NO_IGNITION],
+
+  # BUG(rmcilroy,4680): Function is optimized without type feedback and so immediately deopts again, causing check failure in the test.
+  'test-heap/ResetSharedFunctionInfoCountersDuringIncrementalMarking': [PASS, NO_IGNITION],
+  'test-heap/ResetSharedFunctionInfoCountersDuringMarkSweep': [PASS, NO_IGNITION],
+
+  # BUG(4751). Flaky with ignition.
+  'test-cpu-profiler/JsNativeJsSample': [PASS, NO_IGNITION],
 }],  # ALWAYS
 
 ##############################################################################
@@ -256,15 +303,18 @@
   'test-run-wasm-module/Run_WasmModule_Return114': [SKIP],
   'test-run-wasm-module/Run_WasmModule_CheckMemoryIsZero': [SKIP],
   'test-run-wasm-module/Run_WasmModule_Global': [SKIP],
-  'test-run-wasm/Run_Wasm_Int32LoadInt16_signext': [SKIP],
-  'test-run-wasm/Run_Wasm_Int32LoadInt16_zeroext': [SKIP],
-  'test-run-wasm/Run_WasmMixedGlobals': [SKIP],
-  'test-run-wasm-64/Run_WasmI64*': [SKIP],
-  'test-run-wasm-64/Run_Wasm_I64*': [SKIP],
-  'test-run-wasm-64/Run_Wasm_LoadStoreI64_sx': [SKIP],
+  'test-run-wasm/RunWasmCompiled_Int32LoadInt16_signext': [SKIP],
+  'test-run-wasm/RunWasmInterpreted_Int32LoadInt16_signext': [SKIP],
+  'test-run-wasm/RunWasmCompiled_Int32LoadInt16_zeroext': [SKIP],
+  'test-run-wasm/RunWasmInterpreted_Int32LoadInt16_zeroext': [SKIP],
+  'test-run-wasm/RunWasmCompiled_MixedGlobals': [SKIP],
+  'test-run-wasm/RunWasmInterpreted_MixedGlobals': [SKIP],
+  'test-run-wasm-64/RunWasmCompiled_I64*': [SKIP],
+  'test-run-wasm-64/RunWasmCompiled_LoadStoreI64_sx': [SKIP],
+  'test-run-wasm-64/RunWasmInterpreted_LoadStoreI64_sx': [SKIP],
   'test-run-wasm-64/Run_TestI64WasmRunner': [SKIP],
-  'test-run-wasm-64/Run_WasmCall_Int64Sub': [SKIP],
-  'test-run-wasm-64/Run_Wasm_MemI64_Sum': [SKIP],
+  'test-run-wasm-64/RunWasmCompiled_Call_Int64Sub': [SKIP],
+  'test-run-wasm-64/RunWasmCompiled_MemI64_Sum': [SKIP],
 }],  # 'byteorder == big'
 
 ##############################################################################
@@ -341,7 +391,12 @@
   'test-run-machops/RunFloat64MulAndFloat64Add2': [SKIP],
   'test-run-machops/RunFloat64MulAndFloat64Sub1': [SKIP],
   'test-run-machops/RunFloat64MulAndFloat64Sub2': [SKIP],
+  'test-run-machops/RunFloat64Sin': [SKIP],
+  'test-run-machops/RunFloat64Cos': [SKIP],
+  'test-run-machops/RunFloat64Expm1': [SKIP],
+  'test-run-machops/RunFloat64Tan': [SKIP],
   'test-cpu-profiler/Inlining': [SKIP],
+  'test-gap-resolver/FuzzResolver': [SKIP],
 }],  # 'arch == x87'
 
 ##############################################################################
@@ -488,22 +543,14 @@
 }],  # 'arch == ppc64 and simulator_run == True'
 
 ##############################################################################
-['ignition == True', {
-
-  # TODO(rmcilroy,4680): The function_data field should be a BytecodeArray on interpreter entry
-  'test-api/SetFunctionEntryHook': [FAIL],
-
-  # TODO(rmcilroy,4680): Check failed: !function->shared()->is_compiled() || function->IsOptimized().
+['ignition or ignition_turbofan', {
+  # TODO(rmcilroy,4680): Related to lack of code flushing. Check failed: !function->shared()->is_compiled() || function->IsOptimized().
   'test-heap/TestCodeFlushingPreAged': [FAIL],
   'test-heap/TestCodeFlushingIncrementalScavenge': [FAIL],
   'test-heap/TestCodeFlushing': [FAIL],
   'test-heap/TestCodeFlushingIncremental': [FAIL],
   'test-heap/TestCodeFlushingIncrementalAbort': [PASS, ['mode == debug or dcheck_always_on == True', FAIL]],
 
-  # TODO(rmcilroy,4766): Requires BytecodeGraphBuilder to track source position
-  # on nodes (behind --turbo_source_positions flag).
-  'test-cpu-profiler/TickLinesOptimized': [FAIL],
-
   # TODO(rmcilroy,4680): Fails to find the correct function name for the
   # anonymous function. Fails without ignition but with --no-lazy also, so seems
   # to be an issue when eagerly parsing.
@@ -511,6 +558,7 @@
 
   # TODO(mythria,4780): Related to type feedback support for calls.
   'test-feedback-vector/VectorCallICStates': [FAIL],
+  'test-feedback-vector/VectorCallCounts': [FAIL],
   'test-compiler/FeedbackVectorPreservedAcrossRecompiles': [FAIL],
   'test-heap/WeakFunctionInConstructor': [FAIL],
   'test-heap/IncrementalMarkingClearsMonomorphicConstructor': [FAIL],
@@ -530,31 +578,11 @@
   # code.
   'test-api/TurboAsmDisablesNeuter': [FAIL],
 
-  # TODO(rmcilroy,4837): We don't set a LoadContextSlot for a function as
-  # immutable in the BytecodeGraphBuilder, therefore no inlining happens.
-  'test-run-inlining/InlineLoopGuardedTwice': [FAIL],
-  'test-run-inlining/InlineSurplusArgumentsDeopt': [FAIL],
-  'test-run-inlining/InlineTwice': [FAIL],
-  'test-run-inlining/InlineSurplusArgumentsObject': [FAIL],
-  'test-run-inlining/InlineTwiceDependentDiamond': [FAIL],
-  'test-run-inlining/InlineWithArguments': [FAIL],
-  'test-run-inlining/InlineLoopUnguardedTwice': [FAIL],
-  'test-run-inlining/InlineOmitArgumentsObject': [FAIL],
-  'test-run-inlining/InlineLoopUnguardedOnce': [FAIL],
-  'test-run-inlining/InlineOmitArgumentsDeopt': [FAIL],
-  'test-run-inlining/InlineTwiceDependentDiamondDifferent': [FAIL],
-  'test-run-inlining/SimpleInliningContext': [FAIL],
-  'test-run-inlining/InlineMutuallyRecursive': [FAIL],
-  'test-run-inlining/InlineLoopGuardedEmpty': [FAIL],
-  'test-run-inlining/InlineLoopGuardedOnce': [FAIL],
-  'test-run-inlining/InlineOmitArguments': [FAIL],
-  'test-run-inlining/SimpleInlining': [FAIL],
-  'test-run-inlining/InlineLoopUnguardedEmpty': [FAIL],
-  'test-run-inlining/InlineNestedBuiltin': [FAIL],
-  'test-run-inlining/InlineSurplusArguments': [FAIL],
-  'test-run-inlining/InlineBuiltin': [FAIL],
-  'test-run-inlining/InlineTwiceDependent': [FAIL],
-  'test-run-inlining/SimpleInliningContextDeopt': [FAIL],
-}],  # ignition == True
+  # TODO(mvstanton,4900): CHECK(!g_function->is_compiled());
+  'test-heap/TestUseOfIncrementalBarrierOnCompileLazy': [FAIL],
+
+  # BUG(4751). Flaky with Ignition.
+  'test-cpu-profiler/JsNativeJsSample': [SKIP],
+}],  # ignition or ignition_turbofan
 
 ]
diff --git a/test/cctest/compiler/call-tester.h b/test/cctest/compiler/call-tester.h
index c75bde1..77d2ce1 100644
--- a/test/cctest/compiler/call-tester.h
+++ b/test/cctest/compiler/call-tester.h
@@ -106,12 +106,14 @@
   static int64_t Cast(int32_t r) { return static_cast<int64_t>(r); }
 };
 
+#if !V8_TARGET_ARCH_PPC64
 template <>
 struct ParameterTraits<uint32_t> {
   static int64_t Cast(uint32_t r) {
     return static_cast<int64_t>(static_cast<int32_t>(r));
   }
 };
+#endif
 
 #endif  // !V8_TARGET_ARCH_64_BIT
 
diff --git a/test/cctest/compiler/code-assembler-tester.h b/test/cctest/compiler/code-assembler-tester.h
new file mode 100644
index 0000000..609a137
--- /dev/null
+++ b/test/cctest/compiler/code-assembler-tester.h
@@ -0,0 +1,67 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/handles.h"
+#include "src/interface-descriptors.h"
+#include "src/isolate.h"
+#include "test/cctest/compiler/function-tester.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class ZoneHolder {
+ public:
+  explicit ZoneHolder(Isolate* isolate) : zone_(isolate->allocator()) {}
+  Zone* zone() { return &zone_; }
+
+ private:
+  Zone zone_;
+};
+
+// Inherit from ZoneHolder in order to create a zone that can be passed to
+// CodeAssembler base class constructor.
+template <typename CodeAssemblerT>
+class CodeAssemblerTesterImpl : private ZoneHolder, public CodeAssemblerT {
+ public:
+  // Test generating code for a stub.
+  CodeAssemblerTesterImpl(Isolate* isolate,
+                          const CallInterfaceDescriptor& descriptor)
+      : ZoneHolder(isolate),
+        CodeAssemblerT(isolate, ZoneHolder::zone(), descriptor,
+                       Code::ComputeFlags(Code::STUB), "test"),
+        scope_(isolate) {}
+
+  // Test generating code for a JS function (e.g. builtins).
+  CodeAssemblerTesterImpl(Isolate* isolate, int parameter_count)
+      : ZoneHolder(isolate),
+        CodeAssemblerT(isolate, ZoneHolder::zone(), parameter_count,
+                       Code::ComputeFlags(Code::FUNCTION), "test"),
+        scope_(isolate) {}
+
+  // This constructor is intended to be used for creating code objects with
+  // specific flags.
+  CodeAssemblerTesterImpl(Isolate* isolate, Code::Flags flags)
+      : ZoneHolder(isolate),
+        CodeAssemblerT(isolate, ZoneHolder::zone(), 0, flags, "test"),
+        scope_(isolate) {}
+
+  Handle<Code> GenerateCodeCloseAndEscape() {
+    return scope_.CloseAndEscape(CodeAssemblerT::GenerateCode());
+  }
+
+  // Expose some internal methods.
+
+  Node* SmiShiftBitsConstant() {
+    return CodeAssemblerT::SmiShiftBitsConstant();
+  }
+
+ private:
+  HandleScope scope_;
+  LocalContext context_;
+};
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/test/cctest/compiler/codegen-tester.h b/test/cctest/compiler/codegen-tester.h
index 5d670bf..3450c3a 100644
--- a/test/cctest/compiler/codegen-tester.h
+++ b/test/cctest/compiler/codegen-tester.h
@@ -65,7 +65,7 @@
       Schedule* schedule = this->Export();
       CallDescriptor* call_descriptor = this->call_descriptor();
       Graph* graph = this->graph();
-      CompilationInfo info("testing", main_isolate(), main_zone());
+      CompilationInfo info(ArrayVector("testing"), main_isolate(), main_zone());
       code_ = Pipeline::GenerateCodeForTesting(&info, call_descriptor, graph,
                                                schedule);
     }
@@ -256,7 +256,7 @@
   // parameters from memory. Thereby it is possible to pass 64 bit parameters
   // to the IR graph.
   Node* Parameter(size_t index) {
-    CHECK(index >= 0 && index < 4);
+    CHECK(index < 4);
     return parameter_nodes_[index];
   }
 
diff --git a/test/cctest/compiler/function-tester.h b/test/cctest/compiler/function-tester.h
index 631bdde..c7304f1 100644
--- a/test/cctest/compiler/function-tester.h
+++ b/test/cctest/compiler/function-tester.h
@@ -31,7 +31,7 @@
     Compile(function);
     const uint32_t supported_flags =
         CompilationInfo::kFunctionContextSpecializing |
-        CompilationInfo::kInliningEnabled | CompilationInfo::kTypingEnabled;
+        CompilationInfo::kInliningEnabled;
     CHECK_EQ(0u, flags_ & ~supported_flags);
   }
 
@@ -42,16 +42,18 @@
     CompileGraph(graph);
   }
 
-  FunctionTester(const CallInterfaceDescriptor& descriptor, Handle<Code> code)
+  FunctionTester(Handle<Code> code, int param_count)
       : isolate(main_isolate()),
-        function(
-            (FLAG_allow_natives_syntax = true,
-             NewFunction(BuildFunctionFromDescriptor(descriptor).c_str()))),
+        function((FLAG_allow_natives_syntax = true,
+                  NewFunction(BuildFunction(param_count).c_str()))),
         flags_(0) {
     Compile(function);
     function->ReplaceCode(*code);
   }
 
+  FunctionTester(const CallInterfaceDescriptor& descriptor, Handle<Code> code)
+      : FunctionTester(code, descriptor.GetParameterCount()) {}
+
   Isolate* isolate;
   Handle<JSFunction> function;
 
@@ -59,11 +61,22 @@
     return Execution::Call(isolate, function, undefined(), 0, nullptr);
   }
 
+  MaybeHandle<Object> Call(Handle<Object> a) {
+    Handle<Object> args[] = {a};
+    return Execution::Call(isolate, function, undefined(), 1, args);
+  }
+
   MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b) {
     Handle<Object> args[] = {a, b};
     return Execution::Call(isolate, function, undefined(), 2, args);
   }
 
+  MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b,
+                           Handle<Object> c) {
+    Handle<Object> args[] = {a, b, c};
+    return Execution::Call(isolate, function, undefined(), 3, args);
+  }
+
   MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b, Handle<Object> c,
                            Handle<Object> d) {
     Handle<Object> args[] = {a, b, c, d};
@@ -91,41 +104,56 @@
     return try_catch.Message();
   }
 
-  void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b) {
-    Handle<Object> result = Call(a, b).ToHandleChecked();
+  void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b,
+                 Handle<Object> c, Handle<Object> d) {
+    Handle<Object> result = Call(a, b, c, d).ToHandleChecked();
     CHECK(expected->SameValue(*result));
   }
 
+  void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b,
+                 Handle<Object> c) {
+    return CheckCall(expected, a, b, c, undefined());
+  }
+
+  void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b) {
+    return CheckCall(expected, a, b, undefined());
+  }
+
   void CheckCall(Handle<Object> expected, Handle<Object> a) {
     CheckCall(expected, a, undefined());
   }
 
-  void CheckCall(Handle<Object> expected) {
-    CheckCall(expected, undefined(), undefined());
-  }
+  void CheckCall(Handle<Object> expected) { CheckCall(expected, undefined()); }
 
   void CheckCall(double expected, double a, double b) {
     CheckCall(Val(expected), Val(a), Val(b));
   }
 
+  void CheckTrue(Handle<Object> a) { CheckCall(true_value(), a); }
+
   void CheckTrue(Handle<Object> a, Handle<Object> b) {
     CheckCall(true_value(), a, b);
   }
 
-  void CheckTrue(Handle<Object> a) { CheckCall(true_value(), a, undefined()); }
+  void CheckTrue(Handle<Object> a, Handle<Object> b, Handle<Object> c) {
+    CheckCall(true_value(), a, b, c);
+  }
+
+  void CheckTrue(Handle<Object> a, Handle<Object> b, Handle<Object> c,
+                 Handle<Object> d) {
+    CheckCall(true_value(), a, b, c, d);
+  }
 
   void CheckTrue(double a, double b) {
     CheckCall(true_value(), Val(a), Val(b));
   }
 
+  void CheckFalse(Handle<Object> a) { CheckCall(false_value(), a); }
+
   void CheckFalse(Handle<Object> a, Handle<Object> b) {
     CheckCall(false_value(), a, b);
   }
 
-  void CheckFalse(Handle<Object> a) {
-    CheckCall(false_value(), a, undefined());
-  }
-
   void CheckFalse(double a, double b) {
     CheckCall(false_value(), Val(a), Val(b));
   }
@@ -177,7 +205,7 @@
   Handle<JSFunction> Compile(Handle<JSFunction> function) {
     Zone zone(function->GetIsolate()->allocator());
     ParseInfo parse_info(&zone, function);
-    CompilationInfo info(&parse_info);
+    CompilationInfo info(&parse_info, function);
     info.MarkAsDeoptimizationEnabled();
 
     CHECK(Parser::ParseStatic(info.parse_info()));
@@ -188,14 +216,15 @@
     if (flags_ & CompilationInfo::kInliningEnabled) {
       info.MarkAsInliningEnabled();
     }
-    if (flags_ & CompilationInfo::kTypingEnabled) {
-      info.MarkAsTypingEnabled();
+    if (FLAG_turbo_from_bytecode && function->shared()->HasBytecodeArray()) {
+      info.MarkAsOptimizeFromBytecode();
+    } else {
+      CHECK(Compiler::Analyze(info.parse_info()));
+      CHECK(Compiler::EnsureDeoptimizationSupport(&info));
     }
-    CHECK(Compiler::Analyze(info.parse_info()));
-    CHECK(Compiler::EnsureDeoptimizationSupport(&info));
+    JSFunction::EnsureLiterals(function);
 
-    Pipeline pipeline(&info);
-    Handle<Code> code = pipeline.GenerateCode();
+    Handle<Code> code = Pipeline::GenerateCodeForTesting(&info);
     CHECK(!code.is_null());
     info.dependencies()->Commit(code);
     info.context()->native_context()->AddOptimizedCode(*code);
@@ -216,22 +245,15 @@
     return function_string;
   }
 
-  std::string BuildFunctionFromDescriptor(
-      const CallInterfaceDescriptor& descriptor) {
-    return BuildFunction(descriptor.GetParameterCount());
-  }
-
   // Compile the given machine graph instead of the source of the function
   // and replace the JSFunction's code with the result.
   Handle<JSFunction> CompileGraph(Graph* graph) {
     Zone zone(function->GetIsolate()->allocator());
     ParseInfo parse_info(&zone, function);
-    CompilationInfo info(&parse_info);
+    CompilationInfo info(&parse_info, function);
 
     CHECK(Parser::ParseStatic(info.parse_info()));
     info.SetOptimizing();
-    CHECK(Compiler::Analyze(info.parse_info()));
-    CHECK(Compiler::EnsureDeoptimizationSupport(&info));
 
     Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, graph);
     CHECK(!code.is_null());
diff --git a/test/cctest/compiler/graph-builder-tester.h b/test/cctest/compiler/graph-builder-tester.h
index de2713a..e4cccda 100644
--- a/test/cctest/compiler/graph-builder-tester.h
+++ b/test/cctest/compiler/graph-builder-tester.h
@@ -168,11 +168,11 @@
   Node* ChangeFloat64ToTagged(Node* a) {
     return NewNode(simplified()->ChangeFloat64ToTagged(), a);
   }
-  Node* ChangeBoolToBit(Node* a) {
-    return NewNode(simplified()->ChangeBoolToBit(), a);
+  Node* ChangeTaggedToBit(Node* a) {
+    return NewNode(simplified()->ChangeTaggedToBit(), a);
   }
-  Node* ChangeBitToBool(Node* a) {
-    return NewNode(simplified()->ChangeBitToBool(), a);
+  Node* ChangeBitToTagged(Node* a) {
+    return NewNode(simplified()->ChangeBitToTagged(), a);
   }
 
   Node* LoadField(const FieldAccess& access, Node* object) {
@@ -277,7 +277,7 @@
       Zone* zone = graph()->zone();
       CallDescriptor* desc =
           Linkage::GetSimplifiedCDescriptor(zone, this->csig_);
-      CompilationInfo info("testing", main_isolate(), main_zone());
+      CompilationInfo info(ArrayVector("testing"), main_isolate(), main_zone());
       code_ = Pipeline::GenerateCodeForTesting(&info, desc, graph());
 #ifdef ENABLE_DISASSEMBLER
       if (!code_.is_null() && FLAG_print_opt_code) {
diff --git a/test/cctest/compiler/test-branch-combine.cc b/test/cctest/compiler/test-branch-combine.cc
index c3b4308..c5c4166 100644
--- a/test/cctest/compiler/test-branch-combine.cc
+++ b/test/cctest/compiler/test-branch-combine.cc
@@ -457,6 +457,27 @@
   }
 }
 
+TEST(BranchCombineEffectLevel) {
+  // Test that the load doesn't get folded into the branch, as there's a store
+  // between them. See http://crbug.com/611976.
+  int32_t input = 0;
+
+  RawMachineAssemblerTester<int32_t> m;
+  Node* a = m.LoadFromPointer(&input, MachineType::Int32());
+  Node* compare = m.Word32And(a, m.Int32Constant(1));
+  Node* equal = m.Word32Equal(compare, m.Int32Constant(0));
+  m.StoreToPointer(&input, MachineRepresentation::kWord32, m.Int32Constant(1));
+
+  RawMachineLabel blocka, blockb;
+  m.Branch(equal, &blocka, &blockb);
+  m.Bind(&blocka);
+  m.Return(m.Int32Constant(42));
+  m.Bind(&blockb);
+  m.Return(m.Int32Constant(0));
+
+  CHECK_EQ(42, m.Call());
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/test/cctest/compiler/test-changes-lowering.cc b/test/cctest/compiler/test-changes-lowering.cc
deleted file mode 100644
index ddeabe4..0000000
--- a/test/cctest/compiler/test-changes-lowering.cc
+++ /dev/null
@@ -1,290 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <limits>
-
-#include "src/ast/scopes.h"
-#include "src/compiler/change-lowering.h"
-#include "src/compiler/control-builders.h"
-#include "src/compiler/js-graph.h"
-#include "src/compiler/node-properties.h"
-#include "src/compiler/pipeline.h"
-#include "src/compiler/select-lowering.h"
-#include "src/compiler/simplified-lowering.h"
-#include "src/compiler/typer.h"
-#include "src/compiler/verifier.h"
-#include "src/execution.h"
-#include "src/globals.h"
-#include "src/parsing/parser.h"
-#include "src/parsing/rewriter.h"
-#include "test/cctest/cctest.h"
-#include "test/cctest/compiler/codegen-tester.h"
-#include "test/cctest/compiler/function-tester.h"
-#include "test/cctest/compiler/graph-builder-tester.h"
-#include "test/cctest/compiler/value-helper.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-template <typename ReturnType>
-class ChangesLoweringTester : public GraphBuilderTester<ReturnType> {
- public:
-  explicit ChangesLoweringTester(MachineType p0 = MachineType::None())
-      : GraphBuilderTester<ReturnType>(p0),
-        javascript(this->zone()),
-        jsgraph(this->isolate(), this->graph(), this->common(), &javascript,
-                nullptr, this->machine()),
-        function(Handle<JSFunction>::null()) {}
-
-  JSOperatorBuilder javascript;
-  JSGraph jsgraph;
-  Handle<JSFunction> function;
-
-  Node* start() { return this->graph()->start(); }
-
-  template <typename T>
-  T* CallWithPotentialGC() {
-    // TODO(titzer): we wrap the code in a JSFunction here to reuse the
-    // JSEntryStub; that could be done with a special prologue or other stub.
-    if (function.is_null()) {
-      function = FunctionTester::ForMachineGraph(this->graph());
-    }
-    Handle<Object>* args = NULL;
-    MaybeHandle<Object> result =
-        Execution::Call(this->isolate(), function, factory()->undefined_value(),
-                        0, args, false);
-    return T::cast(*result.ToHandleChecked());
-  }
-
-  void StoreFloat64(Node* node, double* ptr) {
-    Node* ptr_node = this->PointerConstant(ptr);
-    this->Store(MachineType::Float64(), ptr_node, node);
-  }
-
-  Node* LoadInt32(int32_t* ptr) {
-    Node* ptr_node = this->PointerConstant(ptr);
-    return this->Load(MachineType::Int32(), ptr_node);
-  }
-
-  Node* LoadUint32(uint32_t* ptr) {
-    Node* ptr_node = this->PointerConstant(ptr);
-    return this->Load(MachineType::Uint32(), ptr_node);
-  }
-
-  Node* LoadFloat64(double* ptr) {
-    Node* ptr_node = this->PointerConstant(ptr);
-    return this->Load(MachineType::Float64(), ptr_node);
-  }
-
-  void CheckNumber(double expected, Object* number) {
-    CHECK(this->isolate()->factory()->NewNumber(expected)->SameValue(number));
-  }
-
-  void BuildAndLower(const Operator* op) {
-    // We build a graph by hand here, because the raw machine assembler
-    // does not add the correct control and effect nodes.
-    Node* p0 = this->Parameter(0);
-    Node* change = this->graph()->NewNode(op, p0);
-    Node* ret = this->graph()->NewNode(this->common()->Return(), change,
-                                       this->start(), this->start());
-    Node* end = this->graph()->NewNode(this->common()->End(1), ret);
-    this->graph()->SetEnd(end);
-    LowerChange(change);
-  }
-
-  void BuildStoreAndLower(const Operator* op, const Operator* store_op,
-                          void* location) {
-    // We build a graph by hand here, because the raw machine assembler
-    // does not add the correct control and effect nodes.
-    Node* p0 = this->Parameter(0);
-    Node* change = this->graph()->NewNode(op, p0);
-    Node* store = this->graph()->NewNode(
-        store_op, this->PointerConstant(location), this->Int32Constant(0),
-        change, this->start(), this->start());
-    Node* ret = this->graph()->NewNode(
-        this->common()->Return(), this->Int32Constant(0), store, this->start());
-    Node* end = this->graph()->NewNode(this->common()->End(1), ret);
-    this->graph()->SetEnd(end);
-    LowerChange(change);
-  }
-
-  void BuildLoadAndLower(const Operator* op, const Operator* load_op,
-                         void* location) {
-    // We build a graph by hand here, because the raw machine assembler
-    // does not add the correct control and effect nodes.
-    Node* load = this->graph()->NewNode(
-        load_op, this->PointerConstant(location), this->Int32Constant(0),
-        this->start(), this->start());
-    Node* change = this->graph()->NewNode(op, load);
-    Node* ret = this->graph()->NewNode(this->common()->Return(), change,
-                                       this->start(), this->start());
-    Node* end = this->graph()->NewNode(this->common()->End(1), ret);
-    this->graph()->SetEnd(end);
-    LowerChange(change);
-  }
-
-  void LowerChange(Node* change) {
-    // Run the graph reducer with changes lowering on a single node.
-    Typer typer(this->isolate(), this->graph());
-    typer.Run();
-    ChangeLowering change_lowering(&jsgraph);
-    SelectLowering select_lowering(this->graph(), this->common());
-    GraphReducer reducer(this->zone(), this->graph());
-    reducer.AddReducer(&change_lowering);
-    reducer.AddReducer(&select_lowering);
-    reducer.ReduceNode(change);
-    Verifier::Run(this->graph(), Verifier::UNTYPED);
-  }
-
-  Factory* factory() { return this->isolate()->factory(); }
-  Heap* heap() { return this->isolate()->heap(); }
-};
-
-
-TEST(RunChangeTaggedToInt32) {
-  // Build and lower a graph by hand.
-  ChangesLoweringTester<int32_t> t(MachineType::AnyTagged());
-  t.BuildAndLower(t.simplified()->ChangeTaggedToInt32());
-
-    FOR_INT32_INPUTS(i) {
-      int32_t input = *i;
-
-      if (Smi::IsValid(input)) {
-        int32_t result = t.Call(Smi::FromInt(input));
-        CHECK_EQ(input, result);
-      }
-
-      {
-        Handle<Object> number = t.factory()->NewNumber(input);
-        int32_t result = t.Call(*number);
-        CHECK_EQ(input, result);
-      }
-
-      {
-        Handle<HeapNumber> number = t.factory()->NewHeapNumber(input);
-        int32_t result = t.Call(*number);
-        CHECK_EQ(input, result);
-      }
-  }
-}
-
-
-TEST(RunChangeTaggedToUint32) {
-  // Build and lower a graph by hand.
-  ChangesLoweringTester<uint32_t> t(MachineType::AnyTagged());
-  t.BuildAndLower(t.simplified()->ChangeTaggedToUint32());
-
-    FOR_UINT32_INPUTS(i) {
-      uint32_t input = *i;
-
-      if (Smi::IsValid(input)) {
-        uint32_t result = t.Call(Smi::FromInt(input));
-        CHECK_EQ(static_cast<int32_t>(input), static_cast<int32_t>(result));
-      }
-
-      {
-        Handle<Object> number = t.factory()->NewNumber(input);
-        uint32_t result = t.Call(*number);
-        CHECK_EQ(static_cast<int32_t>(input), static_cast<int32_t>(result));
-      }
-
-      {
-        Handle<HeapNumber> number = t.factory()->NewHeapNumber(input);
-        uint32_t result = t.Call(*number);
-        CHECK_EQ(static_cast<int32_t>(input), static_cast<int32_t>(result));
-      }
-    }
-}
-
-
-TEST(RunChangeTaggedToFloat64) {
-  ChangesLoweringTester<int32_t> t(MachineType::AnyTagged());
-  double result;
-
-  t.BuildStoreAndLower(t.simplified()->ChangeTaggedToFloat64(),
-                       t.machine()->Store(StoreRepresentation(
-                           MachineRepresentation::kFloat64, kNoWriteBarrier)),
-                       &result);
-
-  {
-    FOR_INT32_INPUTS(i) {
-      int32_t input = *i;
-
-      if (Smi::IsValid(input)) {
-        t.Call(Smi::FromInt(input));
-        CHECK_EQ(input, static_cast<int32_t>(result));
-      }
-
-      {
-        Handle<Object> number = t.factory()->NewNumber(input);
-        t.Call(*number);
-        CHECK_EQ(input, static_cast<int32_t>(result));
-      }
-
-      {
-        Handle<HeapNumber> number = t.factory()->NewHeapNumber(input);
-        t.Call(*number);
-        CHECK_EQ(input, static_cast<int32_t>(result));
-      }
-    }
-  }
-
-  {
-    FOR_FLOAT64_INPUTS(i) {
-      double input = *i;
-      {
-        Handle<Object> number = t.factory()->NewNumber(input);
-        t.Call(*number);
-        CHECK_DOUBLE_EQ(input, result);
-      }
-
-      {
-        Handle<HeapNumber> number = t.factory()->NewHeapNumber(input);
-        t.Call(*number);
-        CHECK_DOUBLE_EQ(input, result);
-      }
-    }
-  }
-}
-
-
-TEST(RunChangeBoolToBit) {
-  ChangesLoweringTester<int32_t> t(MachineType::AnyTagged());
-  t.BuildAndLower(t.simplified()->ChangeBoolToBit());
-
-  {
-    Object* true_obj = t.heap()->true_value();
-    int32_t result = t.Call(true_obj);
-    CHECK_EQ(1, result);
-  }
-
-  {
-    Object* false_obj = t.heap()->false_value();
-    int32_t result = t.Call(false_obj);
-    CHECK_EQ(0, result);
-  }
-}
-
-
-TEST(RunChangeBitToBool) {
-  ChangesLoweringTester<Object*> t(MachineType::Int32());
-  t.BuildAndLower(t.simplified()->ChangeBitToBool());
-
-  {
-    Object* result = t.Call(1);
-    Object* true_obj = t.heap()->true_value();
-    CHECK_EQ(true_obj, result);
-  }
-
-  {
-    Object* result = t.Call(0);
-    Object* false_obj = t.heap()->false_value();
-    CHECK_EQ(false_obj, result);
-  }
-}
-
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
diff --git a/test/cctest/compiler/test-code-assembler.cc b/test/cctest/compiler/test-code-assembler.cc
new file mode 100644
index 0000000..7f27a6f
--- /dev/null
+++ b/test/cctest/compiler/test-code-assembler.cc
@@ -0,0 +1,438 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/code-assembler.h"
+#include "src/isolate.h"
+#include "test/cctest/compiler/code-assembler-tester.h"
+#include "test/cctest/compiler/function-tester.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+typedef CodeAssemblerTesterImpl<CodeAssembler> CodeAssemblerTester;
+
+namespace {
+
+Node* SmiTag(CodeAssemblerTester& m, Node* value) {
+  int32_t constant_value;
+  if (m.ToInt32Constant(value, constant_value) &&
+      Smi::IsValid(constant_value)) {
+    return m.SmiConstant(Smi::FromInt(constant_value));
+  }
+  return m.WordShl(value, m.SmiShiftBitsConstant());
+}
+
+Node* UndefinedConstant(CodeAssemblerTester& m) {
+  return m.LoadRoot(Heap::kUndefinedValueRootIndex);
+}
+
+Node* LoadObjectField(CodeAssemblerTester& m, Node* object, int offset,
+                      MachineType rep = MachineType::AnyTagged()) {
+  return m.Load(rep, object, m.IntPtrConstant(offset - kHeapObjectTag));
+}
+
+}  // namespace
+
+TEST(SimpleSmiReturn) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  m.Return(SmiTag(m, m.Int32Constant(37)));
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(descriptor, code);
+  MaybeHandle<Object> result = ft.Call();
+  CHECK_EQ(37, Handle<Smi>::cast(result.ToHandleChecked())->value());
+}
+
+TEST(SimpleIntPtrReturn) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  int test;
+  m.Return(m.IntPtrConstant(reinterpret_cast<intptr_t>(&test)));
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(descriptor, code);
+  MaybeHandle<Object> result = ft.Call();
+  CHECK_EQ(reinterpret_cast<intptr_t>(&test),
+           reinterpret_cast<intptr_t>(*result.ToHandleChecked()));
+}
+
+TEST(SimpleDoubleReturn) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  m.Return(m.NumberConstant(0.5));
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(descriptor, code);
+  MaybeHandle<Object> result = ft.Call();
+  CHECK_EQ(0.5, Handle<HeapNumber>::cast(result.ToHandleChecked())->value());
+}
+
+TEST(SimpleCallRuntime1Arg) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
+  Node* b = SmiTag(m, m.Int32Constant(0));
+  m.Return(m.CallRuntime(Runtime::kNumberToSmi, context, b));
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(descriptor, code);
+  MaybeHandle<Object> result = ft.Call();
+  CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value());
+}
+
+TEST(SimpleTailCallRuntime1Arg) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
+  Node* b = SmiTag(m, m.Int32Constant(0));
+  m.TailCallRuntime(Runtime::kNumberToSmi, context, b);
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(descriptor, code);
+  MaybeHandle<Object> result = ft.Call();
+  CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value());
+}
+
+TEST(SimpleCallRuntime2Arg) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
+  Node* a = SmiTag(m, m.Int32Constant(2));
+  Node* b = SmiTag(m, m.Int32Constant(4));
+  m.Return(m.CallRuntime(Runtime::kMathPow, context, a, b));
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(descriptor, code);
+  MaybeHandle<Object> result = ft.Call();
+  CHECK_EQ(16, Handle<Smi>::cast(result.ToHandleChecked())->value());
+}
+
+TEST(SimpleTailCallRuntime2Arg) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
+  Node* a = SmiTag(m, m.Int32Constant(2));
+  Node* b = SmiTag(m, m.Int32Constant(4));
+  m.TailCallRuntime(Runtime::kMathPow, context, a, b);
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(descriptor, code);
+  MaybeHandle<Object> result = ft.Call();
+  CHECK_EQ(16, Handle<Smi>::cast(result.ToHandleChecked())->value());
+}
+
+namespace {
+
+Handle<JSFunction> CreateSumAllArgumentsFunction(FunctionTester& ft) {
+  const char* source =
+      "(function() {\n"
+      "  var sum = 0 + this;\n"
+      "  for (var i = 0; i < arguments.length; i++) {\n"
+      "    sum += arguments[i];\n"
+      "  }\n"
+      "  return sum;\n"
+      "})";
+  return ft.NewFunction(source);
+}
+
+}  // namespace
+
+TEST(SimpleCallJSFunction0Arg) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  const int kNumParams = 1;
+  CodeAssemblerTester m(isolate, kNumParams);
+  {
+    Node* function = m.Parameter(0);
+    Node* context = m.Parameter(kNumParams + 2);
+
+    Node* receiver = SmiTag(m, m.Int32Constant(42));
+
+    Callable callable = CodeFactory::Call(isolate);
+    Node* result = m.CallJS(callable, context, function, receiver);
+    m.Return(result);
+  }
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(code, kNumParams);
+
+  Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
+  MaybeHandle<Object> result = ft.Call(sum);
+  CHECK_EQ(Smi::FromInt(42), *result.ToHandleChecked());
+}
+
+TEST(SimpleCallJSFunction1Arg) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  const int kNumParams = 2;
+  CodeAssemblerTester m(isolate, kNumParams);
+  {
+    Node* function = m.Parameter(0);
+    Node* context = m.Parameter(1);
+
+    Node* receiver = SmiTag(m, m.Int32Constant(42));
+    Node* a = SmiTag(m, m.Int32Constant(13));
+
+    Callable callable = CodeFactory::Call(isolate);
+    Node* result = m.CallJS(callable, context, function, receiver, a);
+    m.Return(result);
+  }
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(code, kNumParams);
+
+  Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
+  MaybeHandle<Object> result = ft.Call(sum);
+  CHECK_EQ(Smi::FromInt(55), *result.ToHandleChecked());
+}
+
+TEST(SimpleCallJSFunction2Arg) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  const int kNumParams = 2;
+  CodeAssemblerTester m(isolate, kNumParams);
+  {
+    Node* function = m.Parameter(0);
+    Node* context = m.Parameter(1);
+
+    Node* receiver = SmiTag(m, m.Int32Constant(42));
+    Node* a = SmiTag(m, m.Int32Constant(13));
+    Node* b = SmiTag(m, m.Int32Constant(153));
+
+    Callable callable = CodeFactory::Call(isolate);
+    Node* result = m.CallJS(callable, context, function, receiver, a, b);
+    m.Return(result);
+  }
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(code, kNumParams);
+
+  Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
+  MaybeHandle<Object> result = ft.Call(sum);
+  CHECK_EQ(Smi::FromInt(208), *result.ToHandleChecked());
+}
+
+TEST(VariableMerge1) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
+  CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
+  Node* temp = m.Int32Constant(0);
+  var1.Bind(temp);
+  m.Branch(m.Int32Constant(1), &l1, &l2);
+  m.Bind(&l1);
+  CHECK_EQ(var1.value(), temp);
+  m.Goto(&merge);
+  m.Bind(&l2);
+  CHECK_EQ(var1.value(), temp);
+  m.Goto(&merge);
+  m.Bind(&merge);
+  CHECK_EQ(var1.value(), temp);
+}
+
+TEST(VariableMerge2) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
+  CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
+  Node* temp = m.Int32Constant(0);
+  var1.Bind(temp);
+  m.Branch(m.Int32Constant(1), &l1, &l2);
+  m.Bind(&l1);
+  CHECK_EQ(var1.value(), temp);
+  m.Goto(&merge);
+  m.Bind(&l2);
+  Node* temp2 = m.Int32Constant(2);
+  var1.Bind(temp2);
+  CHECK_EQ(var1.value(), temp2);
+  m.Goto(&merge);
+  m.Bind(&merge);
+  CHECK_NE(var1.value(), temp);
+}
+
+TEST(VariableMerge3) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
+  CodeStubAssembler::Variable var2(&m, MachineRepresentation::kTagged);
+  CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
+  Node* temp = m.Int32Constant(0);
+  var1.Bind(temp);
+  var2.Bind(temp);
+  m.Branch(m.Int32Constant(1), &l1, &l2);
+  m.Bind(&l1);
+  CHECK_EQ(var1.value(), temp);
+  m.Goto(&merge);
+  m.Bind(&l2);
+  Node* temp2 = m.Int32Constant(2);
+  var1.Bind(temp2);
+  CHECK_EQ(var1.value(), temp2);
+  m.Goto(&merge);
+  m.Bind(&merge);
+  CHECK_NE(var1.value(), temp);
+  CHECK_NE(var1.value(), temp2);
+  CHECK_EQ(var2.value(), temp);
+}
+
+TEST(VariableMergeBindFirst) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
+  CodeStubAssembler::Label l1(&m), l2(&m), merge(&m, &var1), end(&m);
+  Node* temp = m.Int32Constant(0);
+  var1.Bind(temp);
+  m.Branch(m.Int32Constant(1), &l1, &l2);
+  m.Bind(&l1);
+  CHECK_EQ(var1.value(), temp);
+  m.Goto(&merge);
+  m.Bind(&merge);
+  CHECK(var1.value() != temp);
+  CHECK(var1.value() != nullptr);
+  m.Goto(&end);
+  m.Bind(&l2);
+  Node* temp2 = m.Int32Constant(2);
+  var1.Bind(temp2);
+  CHECK_EQ(var1.value(), temp2);
+  m.Goto(&merge);
+  m.Bind(&end);
+  CHECK(var1.value() != temp);
+  CHECK(var1.value() != nullptr);
+}
+
+TEST(VariableMergeSwitch) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
+  CodeStubAssembler::Label l1(&m), l2(&m), default_label(&m);
+  CodeStubAssembler::Label* labels[] = {&l1, &l2};
+  int32_t values[] = {1, 2};
+  Node* temp = m.Int32Constant(0);
+  var1.Bind(temp);
+  m.Switch(m.Int32Constant(2), &default_label, values, labels, 2);
+  m.Bind(&l1);
+  DCHECK_EQ(temp, var1.value());
+  m.Return(temp);
+  m.Bind(&l2);
+  DCHECK_EQ(temp, var1.value());
+  m.Return(temp);
+  m.Bind(&default_label);
+  DCHECK_EQ(temp, var1.value());
+  m.Return(temp);
+}
+
+TEST(SplitEdgeBranchMerge) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  CodeStubAssembler::Label l1(&m), merge(&m);
+  m.Branch(m.Int32Constant(1), &l1, &merge);
+  m.Bind(&l1);
+  m.Goto(&merge);
+  m.Bind(&merge);
+  USE(m.GenerateCode());
+}
+
+TEST(SplitEdgeSwitchMerge) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  CodeStubAssembler::Label l1(&m), l2(&m), l3(&m), default_label(&m);
+  CodeStubAssembler::Label* labels[] = {&l1, &l2};
+  int32_t values[] = {1, 2};
+  m.Branch(m.Int32Constant(1), &l3, &l1);
+  m.Bind(&l3);
+  m.Switch(m.Int32Constant(2), &default_label, values, labels, 2);
+  m.Bind(&l1);
+  m.Goto(&l2);
+  m.Bind(&l2);
+  m.Goto(&default_label);
+  m.Bind(&default_label);
+  USE(m.GenerateCode());
+}
+
+TEST(TestToConstant) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  int32_t value32;
+  int64_t value64;
+  Node* a = m.Int32Constant(5);
+  CHECK(m.ToInt32Constant(a, value32));
+  CHECK(m.ToInt64Constant(a, value64));
+
+  a = m.Int64Constant(static_cast<int64_t>(1) << 32);
+  CHECK(!m.ToInt32Constant(a, value32));
+  CHECK(m.ToInt64Constant(a, value64));
+
+  a = m.Int64Constant(13);
+  CHECK(m.ToInt32Constant(a, value32));
+  CHECK(m.ToInt64Constant(a, value64));
+
+  a = UndefinedConstant(m);
+  CHECK(!m.ToInt32Constant(a, value32));
+  CHECK(!m.ToInt64Constant(a, value64));
+
+  a = UndefinedConstant(m);
+  CHECK(!m.ToInt32Constant(a, value32));
+  CHECK(!m.ToInt64Constant(a, value64));
+}
+
+TEST(DeferredCodePhiHints) {
+  typedef compiler::Node Node;
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  Label block1(&m, Label::kDeferred);
+  m.Goto(&block1);
+  m.Bind(&block1);
+  {
+    Variable var_object(&m, MachineRepresentation::kTagged);
+    Label loop(&m, &var_object);
+    var_object.Bind(m.IntPtrConstant(0));
+    m.Goto(&loop);
+    m.Bind(&loop);
+    {
+      Node* map = LoadObjectField(m, var_object.value(), JSObject::kMapOffset);
+      var_object.Bind(map);
+      m.Goto(&loop);
+    }
+  }
+  CHECK(!m.GenerateCode().is_null());
+}
+
+TEST(TestOutOfScopeVariable) {
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeAssemblerTester m(isolate, descriptor);
+  Label block1(&m);
+  Label block2(&m);
+  Label block3(&m);
+  Label block4(&m);
+  m.Branch(m.WordEqual(m.Parameter(0), m.IntPtrConstant(0)), &block1, &block4);
+  m.Bind(&block4);
+  {
+    Variable var_object(&m, MachineRepresentation::kTagged);
+    m.Branch(m.WordEqual(m.Parameter(0), m.IntPtrConstant(0)), &block2,
+             &block3);
+
+    m.Bind(&block2);
+    var_object.Bind(m.IntPtrConstant(55));
+    m.Goto(&block1);
+
+    m.Bind(&block3);
+    var_object.Bind(m.IntPtrConstant(66));
+    m.Goto(&block1);
+  }
+  m.Bind(&block1);
+  CHECK(!m.GenerateCode().is_null());
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/test/cctest/compiler/test-code-stub-assembler.cc b/test/cctest/compiler/test-code-stub-assembler.cc
deleted file mode 100644
index ff02cc9..0000000
--- a/test/cctest/compiler/test-code-stub-assembler.cc
+++ /dev/null
@@ -1,366 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/interface-descriptors.h"
-#include "src/isolate.h"
-#include "test/cctest/compiler/function-tester.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-
-class CodeStubAssemblerTester : public CodeStubAssembler {
- public:
-  // Test generating code for a stub.
-  CodeStubAssemblerTester(Isolate* isolate,
-                          const CallInterfaceDescriptor& descriptor)
-      : CodeStubAssembler(isolate, isolate->runtime_zone(), descriptor,
-                          Code::ComputeFlags(Code::STUB), "test"),
-        scope_(isolate) {}
-
-  // Test generating code for a JS function (e.g. builtins).
-  CodeStubAssemblerTester(Isolate* isolate, int parameter_count)
-      : CodeStubAssembler(isolate, isolate->runtime_zone(), parameter_count,
-                          Code::ComputeFlags(Code::FUNCTION), "test"),
-        scope_(isolate) {}
-
- private:
-  HandleScope scope_;
-  LocalContext context_;
-};
-
-
-TEST(SimpleSmiReturn) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  m.Return(m.SmiTag(m.Int32Constant(37)));
-  Handle<Code> code = m.GenerateCode();
-  FunctionTester ft(descriptor, code);
-  MaybeHandle<Object> result = ft.Call();
-  CHECK_EQ(37, Handle<Smi>::cast(result.ToHandleChecked())->value());
-}
-
-
-TEST(SimpleIntPtrReturn) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  int test;
-  m.Return(m.IntPtrConstant(reinterpret_cast<intptr_t>(&test)));
-  Handle<Code> code = m.GenerateCode();
-  FunctionTester ft(descriptor, code);
-  MaybeHandle<Object> result = ft.Call();
-  CHECK_EQ(reinterpret_cast<intptr_t>(&test),
-           reinterpret_cast<intptr_t>(*result.ToHandleChecked()));
-}
-
-
-TEST(SimpleDoubleReturn) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  m.Return(m.NumberConstant(0.5));
-  Handle<Code> code = m.GenerateCode();
-  FunctionTester ft(descriptor, code);
-  MaybeHandle<Object> result = ft.Call();
-  CHECK_EQ(0.5, Handle<HeapNumber>::cast(result.ToHandleChecked())->value());
-}
-
-
-TEST(SimpleCallRuntime1Arg) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
-  Node* b = m.SmiTag(m.Int32Constant(0));
-  m.Return(m.CallRuntime(Runtime::kNumberToSmi, context, b));
-  Handle<Code> code = m.GenerateCode();
-  FunctionTester ft(descriptor, code);
-  MaybeHandle<Object> result = ft.Call();
-  CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value());
-}
-
-
-TEST(SimpleTailCallRuntime1Arg) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
-  Node* b = m.SmiTag(m.Int32Constant(0));
-  m.TailCallRuntime(Runtime::kNumberToSmi, context, b);
-  Handle<Code> code = m.GenerateCode();
-  FunctionTester ft(descriptor, code);
-  MaybeHandle<Object> result = ft.Call();
-  CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value());
-}
-
-
-TEST(SimpleCallRuntime2Arg) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
-  Node* a = m.SmiTag(m.Int32Constant(2));
-  Node* b = m.SmiTag(m.Int32Constant(4));
-  m.Return(m.CallRuntime(Runtime::kMathPow, context, a, b));
-  Handle<Code> code = m.GenerateCode();
-  FunctionTester ft(descriptor, code);
-  MaybeHandle<Object> result = ft.Call();
-  CHECK_EQ(16, Handle<Smi>::cast(result.ToHandleChecked())->value());
-}
-
-
-TEST(SimpleTailCallRuntime2Arg) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
-  Node* a = m.SmiTag(m.Int32Constant(2));
-  Node* b = m.SmiTag(m.Int32Constant(4));
-  m.TailCallRuntime(Runtime::kMathPow, context, a, b);
-  Handle<Code> code = m.GenerateCode();
-  FunctionTester ft(descriptor, code);
-  MaybeHandle<Object> result = ft.Call();
-  CHECK_EQ(16, Handle<Smi>::cast(result.ToHandleChecked())->value());
-}
-
-TEST(VariableMerge1) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
-  CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
-  Node* temp = m.Int32Constant(0);
-  var1.Bind(temp);
-  m.Branch(m.Int32Constant(1), &l1, &l2);
-  m.Bind(&l1);
-  CHECK_EQ(var1.value(), temp);
-  m.Goto(&merge);
-  m.Bind(&l2);
-  CHECK_EQ(var1.value(), temp);
-  m.Goto(&merge);
-  m.Bind(&merge);
-  CHECK_EQ(var1.value(), temp);
-}
-
-TEST(VariableMerge2) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
-  CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
-  Node* temp = m.Int32Constant(0);
-  var1.Bind(temp);
-  m.Branch(m.Int32Constant(1), &l1, &l2);
-  m.Bind(&l1);
-  CHECK_EQ(var1.value(), temp);
-  m.Goto(&merge);
-  m.Bind(&l2);
-  Node* temp2 = m.Int32Constant(2);
-  var1.Bind(temp2);
-  CHECK_EQ(var1.value(), temp2);
-  m.Goto(&merge);
-  m.Bind(&merge);
-  CHECK_NE(var1.value(), temp);
-}
-
-TEST(VariableMerge3) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
-  CodeStubAssembler::Variable var2(&m, MachineRepresentation::kTagged);
-  CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
-  Node* temp = m.Int32Constant(0);
-  var1.Bind(temp);
-  var2.Bind(temp);
-  m.Branch(m.Int32Constant(1), &l1, &l2);
-  m.Bind(&l1);
-  CHECK_EQ(var1.value(), temp);
-  m.Goto(&merge);
-  m.Bind(&l2);
-  Node* temp2 = m.Int32Constant(2);
-  var1.Bind(temp2);
-  CHECK_EQ(var1.value(), temp2);
-  m.Goto(&merge);
-  m.Bind(&merge);
-  CHECK_NE(var1.value(), temp);
-  CHECK_NE(var1.value(), temp2);
-  CHECK_EQ(var2.value(), temp);
-}
-
-TEST(VariableMergeBindFirst) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
-  CodeStubAssembler::Label l1(&m), l2(&m), merge(&m, &var1), end(&m);
-  Node* temp = m.Int32Constant(0);
-  var1.Bind(temp);
-  m.Branch(m.Int32Constant(1), &l1, &l2);
-  m.Bind(&l1);
-  CHECK_EQ(var1.value(), temp);
-  m.Goto(&merge);
-  m.Bind(&merge);
-  CHECK(var1.value() != temp);
-  CHECK(var1.value() != nullptr);
-  m.Goto(&end);
-  m.Bind(&l2);
-  Node* temp2 = m.Int32Constant(2);
-  var1.Bind(temp2);
-  CHECK_EQ(var1.value(), temp2);
-  m.Goto(&merge);
-  m.Bind(&end);
-  CHECK(var1.value() != temp);
-  CHECK(var1.value() != nullptr);
-}
-
-TEST(VariableMergeSwitch) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
-  CodeStubAssembler::Label l1(&m), l2(&m), default_label(&m);
-  CodeStubAssembler::Label* labels[] = {&l1, &l2};
-  int32_t values[] = {1, 2};
-  Node* temp = m.Int32Constant(0);
-  var1.Bind(temp);
-  m.Switch(m.Int32Constant(2), &default_label, values, labels, 2);
-  m.Bind(&l1);
-  DCHECK_EQ(temp, var1.value());
-  m.Return(temp);
-  m.Bind(&l2);
-  DCHECK_EQ(temp, var1.value());
-  m.Return(temp);
-  m.Bind(&default_label);
-  DCHECK_EQ(temp, var1.value());
-  m.Return(temp);
-}
-
-TEST(FixedArrayAccessSmiIndex) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  Handle<FixedArray> array = isolate->factory()->NewFixedArray(5);
-  array->set(4, Smi::FromInt(733));
-  m.Return(m.LoadFixedArrayElementSmiIndex(m.HeapConstant(array),
-                                           m.SmiTag(m.Int32Constant(4))));
-  Handle<Code> code = m.GenerateCode();
-  FunctionTester ft(descriptor, code);
-  MaybeHandle<Object> result = ft.Call();
-  CHECK_EQ(733, Handle<Smi>::cast(result.ToHandleChecked())->value());
-}
-
-TEST(LoadHeapNumberValue) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(1234);
-  m.Return(m.SmiTag(
-      m.ChangeFloat64ToUint32(m.LoadHeapNumberValue(m.HeapConstant(number)))));
-  Handle<Code> code = m.GenerateCode();
-  FunctionTester ft(descriptor, code);
-  MaybeHandle<Object> result = ft.Call();
-  CHECK_EQ(1234, Handle<Smi>::cast(result.ToHandleChecked())->value());
-}
-
-TEST(LoadInstanceType) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  Handle<HeapObject> undefined = isolate->factory()->undefined_value();
-  m.Return(m.SmiTag(m.LoadInstanceType(m.HeapConstant(undefined))));
-  Handle<Code> code = m.GenerateCode();
-  FunctionTester ft(descriptor, code);
-  MaybeHandle<Object> result = ft.Call();
-  CHECK_EQ(InstanceType::ODDBALL_TYPE,
-           Handle<Smi>::cast(result.ToHandleChecked())->value());
-}
-
-namespace {
-
-class TestBitField : public BitField<unsigned, 3, 3> {};
-
-}  // namespace
-
-TEST(BitFieldDecode) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  m.Return(m.SmiTag(m.BitFieldDecode<TestBitField>(m.Int32Constant(0x2f))));
-  Handle<Code> code = m.GenerateCode();
-  FunctionTester ft(descriptor, code);
-  MaybeHandle<Object> result = ft.Call();
-  // value  = 00101111
-  // mask   = 00111000
-  // result = 101
-  CHECK_EQ(5, Handle<Smi>::cast(result.ToHandleChecked())->value());
-}
-
-namespace {
-
-Handle<JSFunction> CreateFunctionFromCode(int parameter_count_with_receiver,
-                                          Handle<Code> code) {
-  Isolate* isolate = code->GetIsolate();
-  Handle<String> name = isolate->factory()->InternalizeUtf8String("test");
-  Handle<JSFunction> function =
-      isolate->factory()->NewFunctionWithoutPrototype(name, code);
-  function->shared()->set_internal_formal_parameter_count(
-      parameter_count_with_receiver - 1);  // Implicit undefined receiver.
-  return function;
-}
-
-}  // namespace
-
-TEST(JSFunction) {
-  const int kNumParams = 3;  // Receiver, left, right.
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  CodeStubAssemblerTester m(isolate, kNumParams);
-  m.Return(m.SmiTag(m.Int32Add(m.SmiToWord32(m.Parameter(1)),
-                               m.SmiToWord32(m.Parameter(2)))));
-  Handle<Code> code = m.GenerateCode();
-  Handle<JSFunction> function = CreateFunctionFromCode(kNumParams, code);
-  Handle<Object> args[] = {Handle<Smi>(Smi::FromInt(23), isolate),
-                           Handle<Smi>(Smi::FromInt(34), isolate)};
-  MaybeHandle<Object> result =
-      Execution::Call(isolate, function, isolate->factory()->undefined_value(),
-                      arraysize(args), args);
-  CHECK_EQ(57, Handle<Smi>::cast(result.ToHandleChecked())->value());
-}
-
-TEST(SplitEdgeBranchMerge) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  CodeStubAssembler::Label l1(&m), merge(&m);
-  m.Branch(m.Int32Constant(1), &l1, &merge);
-  m.Bind(&l1);
-  m.Goto(&merge);
-  m.Bind(&merge);
-  USE(m.GenerateCode());
-}
-
-TEST(SplitEdgeSwitchMerge) {
-  Isolate* isolate(CcTest::InitIsolateOnce());
-  VoidDescriptor descriptor(isolate);
-  CodeStubAssemblerTester m(isolate, descriptor);
-  CodeStubAssembler::Label l1(&m), l2(&m), l3(&m), default_label(&m);
-  CodeStubAssembler::Label* labels[] = {&l1, &l2};
-  int32_t values[] = {1, 2};
-  m.Branch(m.Int32Constant(1), &l3, &l1);
-  m.Bind(&l3);
-  m.Switch(m.Int32Constant(2), &default_label, values, labels, 2);
-  m.Bind(&l1);
-  m.Goto(&l2);
-  m.Bind(&l2);
-  m.Goto(&default_label);
-  m.Bind(&default_label);
-  USE(m.GenerateCode());
-}
-
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
diff --git a/test/cctest/compiler/test-gap-resolver.cc b/test/cctest/compiler/test-gap-resolver.cc
index 7f85088..8d0ca8b 100644
--- a/test/cctest/compiler/test-gap-resolver.cc
+++ b/test/cctest/compiler/test-gap-resolver.cc
@@ -81,7 +81,7 @@
     if (!is_constant) {
       if (op.IsRegister()) {
         index = LocationOperand::cast(op).GetRegister().code();
-      } else if (op.IsDoubleRegister()) {
+      } else if (op.IsFPRegister()) {
         index = LocationOperand::cast(op).GetDoubleRegister().code();
       } else {
         index = LocationOperand::cast(op).index();
@@ -116,9 +116,7 @@
       InstructionOperand source = FromKey(it->first);
       InstructionOperand destination = FromKey(it->second);
       MoveOperands mo(source, destination);
-      PrintableMoveOperands pmo = {
-          RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN),
-          &mo};
+      PrintableMoveOperands pmo = {RegisterConfiguration::Turbofan(), &mo};
       os << pmo;
     }
     return os;
@@ -167,8 +165,10 @@
   ParallelMove* Create(int size) {
     ParallelMove* parallel_move = new (main_zone()) ParallelMove(main_zone());
     std::set<InstructionOperand, CompareOperandModuloType> seen;
+    MachineRepresentation rep = RandomRepresentation();
     for (int i = 0; i < size; ++i) {
-      MoveOperands mo(CreateRandomOperand(true), CreateRandomOperand(false));
+      MoveOperands mo(CreateRandomOperand(true, rep),
+                      CreateRandomOperand(false, rep));
       if (!mo.IsRedundant() && seen.find(mo.destination()) == seen.end()) {
         parallel_move->AddMove(mo.source(), mo.destination());
         seen.insert(mo.destination());
@@ -179,52 +179,54 @@
 
  private:
   MachineRepresentation RandomRepresentation() {
-    int index = rng_->NextInt(3);
+    int index = rng_->NextInt(5);
     switch (index) {
       case 0:
         return MachineRepresentation::kWord32;
       case 1:
         return MachineRepresentation::kWord64;
       case 2:
+        return MachineRepresentation::kFloat32;
+      case 3:
+        return MachineRepresentation::kFloat64;
+      case 4:
         return MachineRepresentation::kTagged;
     }
     UNREACHABLE();
     return MachineRepresentation::kNone;
   }
 
-  MachineRepresentation RandomDoubleRepresentation() {
-    int index = rng_->NextInt(2);
-    if (index == 0) return MachineRepresentation::kFloat64;
-    return MachineRepresentation::kFloat32;
-  }
+  InstructionOperand CreateRandomOperand(bool is_source,
+                                         MachineRepresentation rep) {
+    auto conf = RegisterConfiguration::Turbofan();
+    auto GetRegisterCode = [&conf](MachineRepresentation rep, int index) {
+      switch (rep) {
+        case MachineRepresentation::kFloat32:
+        case MachineRepresentation::kFloat64:
+          return conf->RegisterConfiguration::GetAllocatableDoubleCode(index);
+          break;
 
-  InstructionOperand CreateRandomOperand(bool is_source) {
+        default:
+          return conf->RegisterConfiguration::GetAllocatableGeneralCode(index);
+          break;
+      }
+      UNREACHABLE();
+      return static_cast<int>(Register::kCode_no_reg);
+    };
     int index = rng_->NextInt(7);
     // destination can't be Constant.
-    switch (rng_->NextInt(is_source ? 7 : 6)) {
+    switch (rng_->NextInt(is_source ? 5 : 4)) {
       case 0:
-        return AllocatedOperand(LocationOperand::STACK_SLOT,
-                                RandomRepresentation(), index);
+        return AllocatedOperand(LocationOperand::STACK_SLOT, rep, index);
       case 1:
-        return AllocatedOperand(LocationOperand::STACK_SLOT,
-                                RandomDoubleRepresentation(), index);
+        return AllocatedOperand(LocationOperand::REGISTER, rep, index);
       case 2:
-        return AllocatedOperand(LocationOperand::REGISTER,
-                                RandomRepresentation(), index);
+        return ExplicitOperand(LocationOperand::REGISTER, rep,
+                               GetRegisterCode(rep, 1));
       case 3:
-        return AllocatedOperand(LocationOperand::REGISTER,
-                                RandomDoubleRepresentation(), index);
+        return ExplicitOperand(LocationOperand::STACK_SLOT, rep,
+                               GetRegisterCode(rep, index));
       case 4:
-        return ExplicitOperand(
-            LocationOperand::REGISTER, RandomRepresentation(),
-            RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-                ->GetAllocatableGeneralCode(1));
-      case 5:
-        return ExplicitOperand(
-            LocationOperand::STACK_SLOT, RandomRepresentation(),
-            RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-                ->GetAllocatableGeneralCode(index));
-      case 6:
         return ConstantOperand(index);
     }
     UNREACHABLE();
diff --git a/test/cctest/compiler/test-js-context-specialization.cc b/test/cctest/compiler/test-js-context-specialization.cc
index c7cd47a..e9bf064 100644
--- a/test/cctest/compiler/test-js-context-specialization.cc
+++ b/test/cctest/compiler/test-js-context-specialization.cc
@@ -186,81 +186,6 @@
 }
 
 
-// TODO(titzer): factor out common code with effects checking in typed lowering.
-static void CheckEffectInput(Node* effect, Node* use) {
-  CHECK_EQ(effect, NodeProperties::GetEffectInput(use));
-}
-
-
-TEST(SpecializeToContext) {
-  ContextSpecializationTester t;
-
-  Node* start = t.graph()->NewNode(t.common()->Start(0));
-  t.graph()->SetStart(start);
-
-  // Make a context and initialize it a bit for this test.
-  Handle<Context> native = t.factory()->NewNativeContext();
-  Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!");
-  const int slot = Context::NATIVE_CONTEXT_INDEX;
-  native->set(slot, *expected);
-
-  Node* const_context = t.jsgraph()->Constant(native);
-  Node* param_context = t.graph()->NewNode(t.common()->Parameter(0), start);
-
-  {
-    // Check that specialization replaces values and forwards effects
-    // correctly, and folds values from constant and non-constant contexts
-    Node* effect_in = start;
-    Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, slot, true),
-                                    const_context, const_context, effect_in);
-
-
-    Node* value_use =
-        t.graph()->NewNode(t.simplified()->ChangeTaggedToInt32(), load);
-    Node* other_load =
-        t.graph()->NewNode(t.javascript()->LoadContext(0, slot, true),
-                           param_context, param_context, load);
-    Node* effect_use = other_load;
-    Node* other_use =
-        t.graph()->NewNode(t.simplified()->ChangeTaggedToInt32(), other_load);
-
-    Node* add = t.graph()->NewNode(
-        t.javascript()->Add(BinaryOperationHints::Any()), value_use, other_use,
-        param_context, t.jsgraph()->EmptyFrameState(),
-        t.jsgraph()->EmptyFrameState(), other_load, start);
-
-    Node* ret =
-        t.graph()->NewNode(t.common()->Return(), add, effect_use, start);
-    Node* end = t.graph()->NewNode(t.common()->End(1), ret);
-    USE(end);
-    t.graph()->SetEnd(end);
-
-    // Double check the above graph is what we expect, or the test is broken.
-    CheckEffectInput(effect_in, load);
-    CheckEffectInput(load, effect_use);
-
-    // Perform the reduction on the entire graph.
-    GraphReducer graph_reducer(t.main_zone(), t.graph());
-    JSContextSpecialization spec(&graph_reducer, t.jsgraph(),
-                                 MaybeHandle<Context>());
-    graph_reducer.AddReducer(&spec);
-    graph_reducer.ReduceGraph();
-
-    // Effects should have been forwarded (not replaced with a value).
-    CheckEffectInput(effect_in, effect_use);
-
-    // Use of {other_load} should not have been replaced.
-    CHECK_EQ(other_load, other_use->InputAt(0));
-
-    Node* replacement = value_use->InputAt(0);
-    HeapObjectMatcher match(replacement);
-    CHECK(match.HasValue());
-    CHECK_EQ(*expected, *match.Value());
-  }
-  // TODO(titzer): clean up above test and test more complicated effects.
-}
-
-
 TEST(SpecializeJSFunction_ToConstant1) {
   FunctionTester T(
       "(function() { var x = 1; function inc(a)"
@@ -300,10 +225,14 @@
     FunctionTester T(
         "(function() { if (false) { var x = 1; } function inc(a)"
         " { return x; } return inc; })()");  // x is undefined!
-
-    CHECK(T.Call(T.Val(0.0), T.Val(0.0)).ToHandleChecked()->IsUndefined());
-    CHECK(T.Call(T.Val(2.0), T.Val(0.0)).ToHandleChecked()->IsUndefined());
-    CHECK(T.Call(T.Val(-2.1), T.Val(0.0)).ToHandleChecked()->IsUndefined());
+    i::Isolate* isolate = CcTest::i_isolate();
+    CHECK(
+        T.Call(T.Val(0.0), T.Val(0.0)).ToHandleChecked()->IsUndefined(isolate));
+    CHECK(
+        T.Call(T.Val(2.0), T.Val(0.0)).ToHandleChecked()->IsUndefined(isolate));
+    CHECK(T.Call(T.Val(-2.1), T.Val(0.0))
+              .ToHandleChecked()
+              ->IsUndefined(isolate));
   }
 
   {
diff --git a/test/cctest/compiler/test-js-typed-lowering.cc b/test/cctest/compiler/test-js-typed-lowering.cc
index 0075de5..0dac0da 100644
--- a/test/cctest/compiler/test-js-typed-lowering.cc
+++ b/test/cctest/compiler/test-js-typed-lowering.cc
@@ -47,7 +47,8 @@
   Graph graph;
   Typer typer;
   Node* context_node;
-  BinaryOperationHints const hints = BinaryOperationHints::Any();
+  BinaryOperationHints const binop_hints = BinaryOperationHints::Any();
+  CompareOperationHints const compare_hints = CompareOperationHints::Any();
 
   Node* Parameter(Type* t, int32_t index = 0) {
     Node* n = graph.NewNode(common.Parameter(index), graph.start());
@@ -255,11 +256,11 @@
 TEST(NumberBinops) {
   JSTypedLoweringTester R;
   const Operator* ops[] = {
-      R.javascript.Add(R.hints),      R.simplified.NumberAdd(),
-      R.javascript.Subtract(R.hints), R.simplified.NumberSubtract(),
-      R.javascript.Multiply(R.hints), R.simplified.NumberMultiply(),
-      R.javascript.Divide(R.hints),   R.simplified.NumberDivide(),
-      R.javascript.Modulus(R.hints),  R.simplified.NumberModulus(),
+      R.javascript.Add(R.binop_hints),      R.simplified.NumberAdd(),
+      R.javascript.Subtract(R.binop_hints), R.simplified.NumberSubtract(),
+      R.javascript.Multiply(R.binop_hints), R.simplified.NumberMultiply(),
+      R.javascript.Divide(R.binop_hints),   R.simplified.NumberDivide(),
+      R.javascript.Modulus(R.binop_hints),  R.simplified.NumberModulus(),
   };
 
   for (size_t i = 0; i < arraysize(kNumberTypes); ++i) {
@@ -301,11 +302,11 @@
  public:
   JSBitwiseShiftTypedLoweringTester() : JSTypedLoweringTester() {
     int i = 0;
-    set(i++, javascript.ShiftLeft(hints), true);
+    set(i++, javascript.ShiftLeft(binop_hints), true);
     set(i++, simplified.NumberShiftLeft(), false);
-    set(i++, javascript.ShiftRight(hints), true);
+    set(i++, javascript.ShiftRight(binop_hints), true);
     set(i++, simplified.NumberShiftRight(), false);
-    set(i++, javascript.ShiftRightLogical(hints), false);
+    set(i++, javascript.ShiftRightLogical(binop_hints), false);
     set(i++, simplified.NumberShiftRightLogical(), false);
   }
   static const int kNumberOps = 6;
@@ -357,11 +358,11 @@
  public:
   JSBitwiseTypedLoweringTester() : JSTypedLoweringTester() {
     int i = 0;
-    set(i++, javascript.BitwiseOr(hints), true);
+    set(i++, javascript.BitwiseOr(binop_hints), true);
     set(i++, simplified.NumberBitwiseOr(), true);
-    set(i++, javascript.BitwiseXor(hints), true);
+    set(i++, javascript.BitwiseXor(binop_hints), true);
     set(i++, simplified.NumberBitwiseXor(), true);
-    set(i++, javascript.BitwiseAnd(hints), true);
+    set(i++, javascript.BitwiseAnd(binop_hints), true);
     set(i++, simplified.NumberBitwiseAnd(), true);
   }
   static const int kNumberOps = 6;
@@ -492,7 +493,7 @@
   for (size_t i = 0; i < arraysize(others); i++) {
     Type* t = Type::Union(Type::Number(), others[i], R.main_zone());
     Node* r = R.ReduceUnop(R.javascript.ToNumber(), t);
-    CHECK_EQ(IrOpcode::kJSToNumber, r->opcode());
+    CHECK_EQ(IrOpcode::kPlainPrimitiveToNumber, r->opcode());
   }
 }
 
@@ -571,10 +572,14 @@
   JSTypedLoweringTester R;
 
   const Operator* ops[] = {
-      R.javascript.LessThan(),           R.simplified.StringLessThan(),
-      R.javascript.LessThanOrEqual(),    R.simplified.StringLessThanOrEqual(),
-      R.javascript.GreaterThan(),        R.simplified.StringLessThan(),
-      R.javascript.GreaterThanOrEqual(), R.simplified.StringLessThanOrEqual()};
+      R.javascript.LessThan(CompareOperationHints::Any()),
+      R.simplified.StringLessThan(),
+      R.javascript.LessThanOrEqual(CompareOperationHints::Any()),
+      R.simplified.StringLessThanOrEqual(),
+      R.javascript.GreaterThan(CompareOperationHints::Any()),
+      R.simplified.StringLessThan(),
+      R.javascript.GreaterThanOrEqual(CompareOperationHints::Any()),
+      R.simplified.StringLessThanOrEqual()};
 
   for (size_t i = 0; i < arraysize(kStringTypes); i++) {
     Node* p0 = R.Parameter(kStringTypes[i], 0);
@@ -618,10 +623,14 @@
   JSTypedLoweringTester R;
 
   const Operator* ops[] = {
-      R.javascript.LessThan(),           R.simplified.NumberLessThan(),
-      R.javascript.LessThanOrEqual(),    R.simplified.NumberLessThanOrEqual(),
-      R.javascript.GreaterThan(),        R.simplified.NumberLessThan(),
-      R.javascript.GreaterThanOrEqual(), R.simplified.NumberLessThanOrEqual()};
+      R.javascript.LessThan(CompareOperationHints::Any()),
+      R.simplified.NumberLessThan(),
+      R.javascript.LessThanOrEqual(CompareOperationHints::Any()),
+      R.simplified.NumberLessThanOrEqual(),
+      R.javascript.GreaterThan(CompareOperationHints::Any()),
+      R.simplified.NumberLessThan(),
+      R.javascript.GreaterThanOrEqual(CompareOperationHints::Any()),
+      R.simplified.NumberLessThanOrEqual()};
 
   Node* const p0 = R.Parameter(Type::Number(), 0);
   Node* const p1 = R.Parameter(Type::Number(), 1);
@@ -655,7 +664,8 @@
     for (size_t j = 0; j < arraysize(types); j++) {
       Node* p1 = R.Parameter(types[j], 1);
       {
-        const Operator* less_than = R.javascript.LessThan();
+        const Operator* less_than =
+            R.javascript.LessThan(CompareOperationHints::Any());
         Node* cmp = R.Binop(less_than, p0, p1);
         Node* r = R.reduce(cmp);
         if (types[i]->Is(Type::String()) && types[j]->Is(Type::String())) {
@@ -700,14 +710,14 @@
       case 2:
         effect_use = R.graph.NewNode(R.common.EffectPhi(1), ton, R.start());
       case 3:
-        effect_use =
-            R.graph.NewNode(R.javascript.Add(R.hints), ton, ton, R.context(),
-                            frame_state, frame_state, ton, R.start());
+        effect_use = R.graph.NewNode(R.javascript.Add(R.binop_hints), ton, ton,
+                                     R.context(), frame_state, frame_state, ton,
+                                     R.start());
         break;
       case 4:
-        effect_use =
-            R.graph.NewNode(R.javascript.Add(R.hints), p0, p0, R.context(),
-                            frame_state, frame_state, ton, R.start());
+        effect_use = R.graph.NewNode(R.javascript.Add(R.binop_hints), p0, p0,
+                                     R.context(), frame_state, frame_state, ton,
+                                     R.start());
         break;
       case 5:
         effect_use = R.graph.NewNode(R.common.Return(), p0, ton, R.start());
@@ -801,7 +811,8 @@
 
     {
       const Operator* op =
-          strict ? R->javascript.StrictEqual() : R->javascript.Equal();
+          strict ? R->javascript.StrictEqual(CompareOperationHints::Any())
+                 : R->javascript.Equal(CompareOperationHints::Any());
       Node* eq = R->Binop(op, p0, p1);
       Node* r = R->reduce(eq);
       R->CheckBinop(expected, r);
@@ -809,7 +820,8 @@
 
     {
       const Operator* op =
-          strict ? R->javascript.StrictNotEqual() : R->javascript.NotEqual();
+          strict ? R->javascript.StrictNotEqual(CompareOperationHints::Any())
+                 : R->javascript.NotEqual(CompareOperationHints::Any());
       Node* ne = R->Binop(op, p0, p1);
       Node* n = R->reduce(ne);
       CHECK_EQ(IrOpcode::kBooleanNot, n->opcode());
@@ -876,14 +888,22 @@
   JSTypedLoweringTester R;
 
   const Operator* ops[] = {
-      R.javascript.Equal(),           R.simplified.NumberEqual(),
-      R.javascript.Add(R.hints),      R.simplified.NumberAdd(),
-      R.javascript.Subtract(R.hints), R.simplified.NumberSubtract(),
-      R.javascript.Multiply(R.hints), R.simplified.NumberMultiply(),
-      R.javascript.Divide(R.hints),   R.simplified.NumberDivide(),
-      R.javascript.Modulus(R.hints),  R.simplified.NumberModulus(),
-      R.javascript.LessThan(),        R.simplified.NumberLessThan(),
-      R.javascript.LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
+      R.javascript.Equal(R.compare_hints),
+      R.simplified.NumberEqual(),
+      R.javascript.Add(R.binop_hints),
+      R.simplified.NumberAdd(),
+      R.javascript.Subtract(R.binop_hints),
+      R.simplified.NumberSubtract(),
+      R.javascript.Multiply(R.binop_hints),
+      R.simplified.NumberMultiply(),
+      R.javascript.Divide(R.binop_hints),
+      R.simplified.NumberDivide(),
+      R.javascript.Modulus(R.binop_hints),
+      R.simplified.NumberModulus(),
+      R.javascript.LessThan(R.compare_hints),
+      R.simplified.NumberLessThan(),
+      R.javascript.LessThanOrEqual(R.compare_hints),
+      R.simplified.NumberLessThanOrEqual(),
   };
 
   for (size_t j = 0; j < arraysize(ops); j += 2) {
@@ -904,9 +924,9 @@
   JSTypedLoweringTester R;
 
   const Operator* ops[] = {
-      R.javascript.Subtract(R.hints), R.simplified.NumberSubtract(),
-      R.javascript.Multiply(R.hints), R.simplified.NumberMultiply(),
-      R.javascript.Divide(R.hints),   R.simplified.NumberDivide(),
+      R.javascript.Subtract(R.binop_hints), R.simplified.NumberSubtract(),
+      R.javascript.Multiply(R.binop_hints), R.simplified.NumberMultiply(),
+      R.javascript.Divide(R.binop_hints),   R.simplified.NumberDivide(),
   };
 
   for (size_t j = 0; j < arraysize(ops); j += 2) {
@@ -929,10 +949,10 @@
   JSTypedLoweringTester R;
 
   const Operator* ops[] = {
-      R.javascript.Add(R.hints),      R.simplified.NumberAdd(),
-      R.javascript.Subtract(R.hints), R.simplified.NumberSubtract(),
-      R.javascript.Multiply(R.hints), R.simplified.NumberMultiply(),
-      R.javascript.Divide(R.hints),   R.simplified.NumberDivide(),
+      R.javascript.Add(R.binop_hints),      R.simplified.NumberAdd(),
+      R.javascript.Subtract(R.binop_hints), R.simplified.NumberSubtract(),
+      R.javascript.Multiply(R.binop_hints), R.simplified.NumberMultiply(),
+      R.javascript.Divide(R.binop_hints),   R.simplified.NumberDivide(),
   };
 
   for (size_t j = 0; j < arraysize(ops); j += 2) {
@@ -967,8 +987,9 @@
   JSTypedLoweringTester R;
 
   const Operator* ops[] = {
-      R.javascript.GreaterThan(), R.simplified.NumberLessThan(),
-      R.javascript.GreaterThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
+      R.javascript.GreaterThan(R.compare_hints), R.simplified.NumberLessThan(),
+      R.javascript.GreaterThanOrEqual(R.compare_hints),
+      R.simplified.NumberLessThanOrEqual(),
   };
 
   for (size_t j = 0; j < arraysize(ops); j += 2) {
@@ -1178,16 +1199,16 @@
   };
 
   Entry ops[] = {
-      {R.javascript.LessThan(), R.machine.Uint32LessThan(),
+      {R.javascript.LessThan(R.compare_hints), R.machine.Uint32LessThan(),
        R.machine.Int32LessThan(), R.simplified.NumberLessThan(), false},
-      {R.javascript.LessThanOrEqual(), R.machine.Uint32LessThanOrEqual(),
-       R.machine.Int32LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
-       false},
-      {R.javascript.GreaterThan(), R.machine.Uint32LessThan(),
+      {R.javascript.LessThanOrEqual(R.compare_hints),
+       R.machine.Uint32LessThanOrEqual(), R.machine.Int32LessThanOrEqual(),
+       R.simplified.NumberLessThanOrEqual(), false},
+      {R.javascript.GreaterThan(R.compare_hints), R.machine.Uint32LessThan(),
        R.machine.Int32LessThan(), R.simplified.NumberLessThan(), true},
-      {R.javascript.GreaterThanOrEqual(), R.machine.Uint32LessThanOrEqual(),
-       R.machine.Int32LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
-       true}};
+      {R.javascript.GreaterThanOrEqual(R.compare_hints),
+       R.machine.Uint32LessThanOrEqual(), R.machine.Int32LessThanOrEqual(),
+       R.simplified.NumberLessThanOrEqual(), true}};
 
   for (size_t o = 0; o < arraysize(ops); o++) {
     for (size_t i = 0; i < arraysize(kNumberTypes); i++) {
diff --git a/test/cctest/compiler/test-linkage.cc b/test/cctest/compiler/test-linkage.cc
index 0cbdb4c..436b0f3 100644
--- a/test/cctest/compiler/test-linkage.cc
+++ b/test/cctest/compiler/test-linkage.cc
@@ -7,6 +7,7 @@
 #include "src/parsing/parser.h"
 #include "src/zone.h"
 
+#include "src/code-factory.h"
 #include "src/compiler/common-operator.h"
 #include "src/compiler/graph.h"
 #include "src/compiler/linkage.h"
@@ -43,7 +44,7 @@
   HandleAndZoneScope handles;
   Handle<JSFunction> function = Compile("a + b");
   ParseInfo parse_info(handles.main_zone(), function);
-  CompilationInfo info(&parse_info);
+  CompilationInfo info(&parse_info, function);
   CallDescriptor* descriptor = Linkage::ComputeIncoming(info.zone(), &info);
   CHECK(descriptor);
 }
@@ -59,7 +60,7 @@
         Handle<JSFunction>::cast(v8::Utils::OpenHandle(
             *v8::Local<v8::Function>::Cast(CompileRun(sources[i]))));
     ParseInfo parse_info(handles.main_zone(), function);
-    CompilationInfo info(&parse_info);
+    CompilationInfo info(&parse_info, function);
     CallDescriptor* descriptor = Linkage::ComputeIncoming(info.zone(), &info);
     CHECK(descriptor);
 
@@ -75,7 +76,7 @@
   HandleAndZoneScope handles;
   Handle<JSFunction> function = Compile("a + c");
   ParseInfo parse_info(handles.main_zone(), function);
-  CompilationInfo info(&parse_info);
+  CompilationInfo info(&parse_info, function);
 
   for (int i = 0; i < 32; i++) {
     CallDescriptor* descriptor = Linkage::GetJSCallDescriptor(
@@ -97,13 +98,12 @@
 TEST(TestLinkageStubCall) {
   Isolate* isolate = CcTest::InitIsolateOnce();
   Zone zone(isolate->allocator());
-  ToNumberStub stub(isolate);
-  CompilationInfo info("test", isolate, &zone, Code::ComputeFlags(Code::STUB));
-  CallInterfaceDescriptor interface_descriptor =
-      stub.GetCallInterfaceDescriptor();
+  Callable callable = CodeFactory::ToNumber(isolate);
+  CompilationInfo info(ArrayVector("test"), isolate, &zone,
+                       Code::ComputeFlags(Code::STUB));
   CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
-      isolate, &zone, interface_descriptor, stub.GetStackParameterCount(),
-      CallDescriptor::kNoFlags, Operator::kNoProperties);
+      isolate, &zone, callable.descriptor(), 0, CallDescriptor::kNoFlags,
+      Operator::kNoProperties);
   CHECK(descriptor);
   CHECK_EQ(0, static_cast<int>(descriptor->StackParameterCount()));
   CHECK_EQ(1, static_cast<int>(descriptor->ReturnCount()));
diff --git a/test/cctest/compiler/test-loop-assignment-analysis.cc b/test/cctest/compiler/test-loop-assignment-analysis.cc
index 69f5e15..eafd0ec 100644
--- a/test/cctest/compiler/test-loop-assignment-analysis.cc
+++ b/test/cctest/compiler/test-loop-assignment-analysis.cc
@@ -31,7 +31,7 @@
   void CheckLoopAssignedCount(int expected, const char* var_name) {
     // TODO(titzer): don't scope analyze every single time.
     ParseInfo parse_info(main_zone(), function);
-    CompilationInfo info(&parse_info);
+    CompilationInfo info(&parse_info, function);
 
     CHECK(Parser::ParseStatic(&parse_info));
     CHECK(Rewriter::Rewrite(&parse_info));
diff --git a/test/cctest/compiler/test-machine-operator-reducer.cc b/test/cctest/compiler/test-machine-operator-reducer.cc
index 86888e9..799a804 100644
--- a/test/cctest/compiler/test-machine-operator-reducer.cc
+++ b/test/cctest/compiler/test-machine-operator-reducer.cc
@@ -616,13 +616,8 @@
   R.CheckDontPutConstantOnRight(-440197);
 
   Node* x = R.Parameter(0);
-  Node* y = R.Parameter(1);
-  Node* zero = R.Constant<int32_t>(0);
-  Node* sub = R.graph.NewNode(R.machine.Int32Sub(), x, y);
 
   R.CheckFoldBinop<int32_t>(0, x, x);  // x < x  => 0
-  R.CheckFoldBinop(x, y, sub, zero);   // x - y < 0 => x < y
-  R.CheckFoldBinop(y, x, zero, sub);   // 0 < x - y => y < x
 }
 
 
@@ -640,13 +635,8 @@
   FOR_INT32_INPUTS(i) { R.CheckDontPutConstantOnRight<int32_t>(*i); }
 
   Node* x = R.Parameter(0);
-  Node* y = R.Parameter(1);
-  Node* zero = R.Constant<int32_t>(0);
-  Node* sub = R.graph.NewNode(R.machine.Int32Sub(), x, y);
 
   R.CheckFoldBinop<int32_t>(1, x, x);  // x <= x => 1
-  R.CheckFoldBinop(x, y, sub, zero);   // x - y <= 0 => x <= y
-  R.CheckFoldBinop(y, x, zero, sub);   // 0 <= x - y => y <= x
 }
 
 
diff --git a/test/cctest/compiler/test-multiple-return.cc b/test/cctest/compiler/test-multiple-return.cc
index 2108ab1..aa7ec02 100644
--- a/test/cctest/compiler/test-multiple-return.cc
+++ b/test/cctest/compiler/test-multiple-return.cc
@@ -27,8 +27,7 @@
                                   int param_count) {
   MachineSignature::Builder msig(zone, return_count, param_count);
   LocationSignature::Builder locations(zone, return_count, param_count);
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
+  const RegisterConfiguration* config = RegisterConfiguration::Turbofan();
 
   // Add return location(s).
   CHECK(return_count <= config->num_allocatable_general_registers());
@@ -85,7 +84,8 @@
   Node* mul = m.Int32Mul(p0, p1);
   m.Return(add, sub, mul);
 
-  CompilationInfo info("testing", handles.main_isolate(), handles.main_zone());
+  CompilationInfo info(ArrayVector("testing"), handles.main_isolate(),
+                       handles.main_zone());
   Handle<Code> code =
       Pipeline::GenerateCodeForTesting(&info, desc, m.graph(), m.Export());
 #ifdef ENABLE_DISASSEMBLER
diff --git a/test/cctest/compiler/test-pipeline.cc b/test/cctest/compiler/test-pipeline.cc
deleted file mode 100644
index 35e3427..0000000
--- a/test/cctest/compiler/test-pipeline.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/compiler.h"
-#include "src/compiler/pipeline.h"
-#include "src/handles.h"
-#include "src/parsing/parser.h"
-#include "test/cctest/cctest.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-static void RunPipeline(Zone* zone, const char* source) {
-  Handle<JSFunction> function = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
-      *v8::Local<v8::Function>::Cast(CompileRun(source))));
-  ParseInfo parse_info(zone, function);
-  CHECK(Compiler::ParseAndAnalyze(&parse_info));
-  CompilationInfo info(&parse_info);
-  info.SetOptimizing();
-
-  Pipeline pipeline(&info);
-  Handle<Code> code = pipeline.GenerateCode();
-  CHECK(!code.is_null());
-}
-
-
-TEST(PipelineTyped) {
-  HandleAndZoneScope handles;
-  FLAG_turbo_types = true;
-  RunPipeline(handles.main_zone(), "(function(a,b) { return a + b; })");
-}
-
-
-TEST(PipelineGeneric) {
-  HandleAndZoneScope handles;
-  FLAG_turbo_types = false;
-  RunPipeline(handles.main_zone(), "(function(a,b) { return a + b; })");
-}
-
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
diff --git a/test/cctest/compiler/test-representation-change.cc b/test/cctest/compiler/test-representation-change.cc
index 7e75bf8..0d6b5b2 100644
--- a/test/cctest/compiler/test-representation-change.cc
+++ b/test/cctest/compiler/test-representation-change.cc
@@ -83,12 +83,20 @@
     return n;
   }
 
+  Node* Return(Node* input) {
+    Node* n = graph()->NewNode(common()->Return(), input, graph()->start(),
+                               graph()->start());
+    return n;
+  }
+
   void CheckTypeError(MachineRepresentation from, Type* from_type,
                       MachineRepresentation to) {
     changer()->testing_type_errors_ = true;
     changer()->type_error_ = false;
     Node* n = Parameter(0);
-    Node* c = changer()->GetRepresentationFor(n, from, from_type, to);
+    Node* use = Return(n);
+    Node* c = changer()->GetRepresentationFor(n, from, from_type, use,
+                                              UseInfo(to, Truncation::None()));
     CHECK(changer()->type_error_);
     CHECK_EQ(n, c);
   }
@@ -96,7 +104,9 @@
   void CheckNop(MachineRepresentation from, Type* from_type,
                 MachineRepresentation to) {
     Node* n = Parameter(0);
-    Node* c = changer()->GetRepresentationFor(n, from, from_type, to);
+    Node* use = Return(n);
+    Node* c = changer()->GetRepresentationFor(n, from, from_type, use,
+                                              UseInfo(to, Truncation::None()));
     CHECK_EQ(n, c);
   }
 };
@@ -113,15 +123,17 @@
   RepresentationChangerTester r;
 
   Node* true_node = r.jsgraph()->TrueConstant();
+  Node* true_use = r.Return(true_node);
   Node* true_bit = r.changer()->GetRepresentationFor(
-      true_node, MachineRepresentation::kTagged, Type::None(),
-      MachineRepresentation::kBit);
+      true_node, MachineRepresentation::kTagged, Type::None(), true_use,
+      UseInfo(MachineRepresentation::kBit, Truncation::None()));
   r.CheckInt32Constant(true_bit, 1);
 
   Node* false_node = r.jsgraph()->FalseConstant();
+  Node* false_use = r.Return(false_node);
   Node* false_bit = r.changer()->GetRepresentationFor(
-      false_node, MachineRepresentation::kTagged, Type::None(),
-      MachineRepresentation::kBit);
+      false_node, MachineRepresentation::kTagged, Type::None(), false_use,
+      UseInfo(MachineRepresentation::kBit, Truncation::None()));
   r.CheckInt32Constant(false_bit, 0);
 }
 
@@ -131,9 +143,10 @@
 
   for (int i = -5; i < 5; i++) {
     Node* node = r.jsgraph()->Int32Constant(i);
+    Node* use = r.Return(node);
     Node* val = r.changer()->GetRepresentationFor(
-        node, MachineRepresentation::kBit, Type::Boolean(),
-        MachineRepresentation::kTagged);
+        node, MachineRepresentation::kBit, Type::Boolean(), use,
+        UseInfo(MachineRepresentation::kTagged, Truncation::None()));
     r.CheckHeapConstant(val, i == 0 ? r.isolate()->heap()->false_value()
                                     : r.isolate()->heap()->true_value());
   }
@@ -146,49 +159,54 @@
   {
     FOR_FLOAT64_INPUTS(i) {
       Node* n = r.jsgraph()->Float64Constant(*i);
-      Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kFloat64, Type::None(),
-          MachineRepresentation::kTagged);
-      r.CheckNumberConstant(c, *i);
+  Node* use = r.Return(n);
+  Node* c = r.changer()->GetRepresentationFor(
+      n, MachineRepresentation::kFloat64, Type::None(), use,
+      UseInfo(MachineRepresentation::kTagged, Truncation::None()));
+  r.CheckNumberConstant(c, *i);
     }
   }
 
   {
     FOR_FLOAT64_INPUTS(i) {
       Node* n = r.jsgraph()->Constant(*i);
-      Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kFloat64, Type::None(),
-          MachineRepresentation::kTagged);
-      r.CheckNumberConstant(c, *i);
+  Node* use = r.Return(n);
+  Node* c = r.changer()->GetRepresentationFor(
+      n, MachineRepresentation::kFloat64, Type::None(), use,
+      UseInfo(MachineRepresentation::kTagged, Truncation::None()));
+  r.CheckNumberConstant(c, *i);
     }
   }
 
   {
     FOR_FLOAT32_INPUTS(i) {
       Node* n = r.jsgraph()->Float32Constant(*i);
-      Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kFloat32, Type::None(),
-          MachineRepresentation::kTagged);
-      r.CheckNumberConstant(c, *i);
+  Node* use = r.Return(n);
+  Node* c = r.changer()->GetRepresentationFor(
+      n, MachineRepresentation::kFloat32, Type::None(), use,
+      UseInfo(MachineRepresentation::kTagged, Truncation::None()));
+  r.CheckNumberConstant(c, *i);
     }
   }
 
   {
     FOR_INT32_INPUTS(i) {
       Node* n = r.jsgraph()->Int32Constant(*i);
-      Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kWord32, Type::Signed32(),
-          MachineRepresentation::kTagged);
-      r.CheckNumberConstant(c, *i);
+  Node* use = r.Return(n);
+  Node* c = r.changer()->GetRepresentationFor(
+      n, MachineRepresentation::kWord32, Type::Signed32(), use,
+      UseInfo(MachineRepresentation::kTagged, Truncation::None()));
+  r.CheckNumberConstant(c, *i);
     }
   }
 
   {
     FOR_UINT32_INPUTS(i) {
       Node* n = r.jsgraph()->Int32Constant(*i);
+      Node* use = r.Return(n);
       Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kWord32, Type::Unsigned32(),
-          MachineRepresentation::kTagged);
+          n, MachineRepresentation::kWord32, Type::Unsigned32(), use,
+          UseInfo(MachineRepresentation::kTagged, Truncation::None()));
       r.CheckNumberConstant(c, *i);
     }
   }
@@ -201,49 +219,54 @@
   {
     FOR_FLOAT64_INPUTS(i) {
       Node* n = r.jsgraph()->Float64Constant(*i);
-      Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kFloat64, Type::None(),
-          MachineRepresentation::kFloat64);
-      CHECK_EQ(n, c);
+  Node* use = r.Return(n);
+  Node* c = r.changer()->GetRepresentationFor(
+      n, MachineRepresentation::kFloat64, Type::None(), use,
+      UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
+  CHECK_EQ(n, c);
     }
   }
 
   {
     FOR_FLOAT64_INPUTS(i) {
       Node* n = r.jsgraph()->Constant(*i);
-      Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kTagged, Type::None(),
-          MachineRepresentation::kFloat64);
-      r.CheckFloat64Constant(c, *i);
+  Node* use = r.Return(n);
+  Node* c = r.changer()->GetRepresentationFor(
+      n, MachineRepresentation::kTagged, Type::None(), use,
+      UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
+  r.CheckFloat64Constant(c, *i);
     }
   }
 
   {
     FOR_FLOAT32_INPUTS(i) {
       Node* n = r.jsgraph()->Float32Constant(*i);
-      Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kFloat32, Type::None(),
-          MachineRepresentation::kFloat64);
-      r.CheckFloat64Constant(c, *i);
+  Node* use = r.Return(n);
+  Node* c = r.changer()->GetRepresentationFor(
+      n, MachineRepresentation::kFloat32, Type::None(), use,
+      UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
+  r.CheckFloat64Constant(c, *i);
     }
   }
 
   {
     FOR_INT32_INPUTS(i) {
       Node* n = r.jsgraph()->Int32Constant(*i);
-      Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kWord32, Type::Signed32(),
-          MachineRepresentation::kFloat64);
-      r.CheckFloat64Constant(c, *i);
+  Node* use = r.Return(n);
+  Node* c = r.changer()->GetRepresentationFor(
+      n, MachineRepresentation::kWord32, Type::Signed32(), use,
+      UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
+  r.CheckFloat64Constant(c, *i);
     }
   }
 
   {
     FOR_UINT32_INPUTS(i) {
       Node* n = r.jsgraph()->Int32Constant(*i);
+      Node* use = r.Return(n);
       Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kWord32, Type::Unsigned32(),
-          MachineRepresentation::kFloat64);
+          n, MachineRepresentation::kWord32, Type::Unsigned32(), use,
+          UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
       r.CheckFloat64Constant(c, *i);
     }
   }
@@ -264,30 +287,33 @@
   {
     FOR_FLOAT32_INPUTS(i) {
       Node* n = r.jsgraph()->Float32Constant(*i);
-      Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kFloat32, Type::None(),
-          MachineRepresentation::kFloat32);
-      CHECK_EQ(n, c);
+  Node* use = r.Return(n);
+  Node* c = r.changer()->GetRepresentationFor(
+      n, MachineRepresentation::kFloat32, Type::None(), use,
+      UseInfo(MachineRepresentation::kFloat32, Truncation::None()));
+  CHECK_EQ(n, c);
     }
   }
 
   {
     FOR_FLOAT32_INPUTS(i) {
       Node* n = r.jsgraph()->Constant(*i);
-      Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kTagged, Type::None(),
-          MachineRepresentation::kFloat32);
-      r.CheckFloat32Constant(c, *i);
+  Node* use = r.Return(n);
+  Node* c = r.changer()->GetRepresentationFor(
+      n, MachineRepresentation::kTagged, Type::None(), use,
+      UseInfo(MachineRepresentation::kFloat32, Truncation::None()));
+  r.CheckFloat32Constant(c, *i);
     }
   }
 
   {
     FOR_FLOAT32_INPUTS(i) {
       Node* n = r.jsgraph()->Float64Constant(*i);
-      Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kFloat64, Type::None(),
-          MachineRepresentation::kFloat32);
-      r.CheckFloat32Constant(c, *i);
+  Node* use = r.Return(n);
+  Node* c = r.changer()->GetRepresentationFor(
+      n, MachineRepresentation::kFloat64, Type::None(), use,
+      UseInfo(MachineRepresentation::kFloat32, Truncation::None()));
+  r.CheckFloat32Constant(c, *i);
     }
   }
 
@@ -295,9 +321,10 @@
     FOR_INT32_INPUTS(i) {
       if (!IsFloat32Int32(*i)) continue;
       Node* n = r.jsgraph()->Int32Constant(*i);
+      Node* use = r.Return(n);
       Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kWord32, Type::Signed32(),
-          MachineRepresentation::kFloat32);
+          n, MachineRepresentation::kWord32, Type::Signed32(), use,
+          UseInfo(MachineRepresentation::kFloat32, Truncation::None()));
       r.CheckFloat32Constant(c, static_cast<float>(*i));
     }
   }
@@ -306,9 +333,10 @@
     FOR_UINT32_INPUTS(i) {
       if (!IsFloat32Uint32(*i)) continue;
       Node* n = r.jsgraph()->Int32Constant(*i);
+      Node* use = r.Return(n);
       Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kWord32, Type::Unsigned32(),
-          MachineRepresentation::kFloat32);
+          n, MachineRepresentation::kWord32, Type::Unsigned32(), use,
+          UseInfo(MachineRepresentation::kFloat32, Truncation::None()));
       r.CheckFloat32Constant(c, static_cast<float>(*i));
     }
   }
@@ -321,10 +349,11 @@
   {
     FOR_INT32_INPUTS(i) {
       Node* n = r.jsgraph()->Int32Constant(*i);
-      Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kWord32, Type::Signed32(),
-          MachineRepresentation::kWord32);
-      r.CheckInt32Constant(c, *i);
+  Node* use = r.Return(n);
+  Node* c = r.changer()->GetRepresentationFor(
+      n, MachineRepresentation::kWord32, Type::Signed32(), use,
+      UseInfo(MachineRepresentation::kWord32, Truncation::None()));
+  r.CheckInt32Constant(c, *i);
     }
   }
 
@@ -332,9 +361,10 @@
     FOR_INT32_INPUTS(i) {
       if (!IsFloat32Int32(*i)) continue;
       Node* n = r.jsgraph()->Float32Constant(static_cast<float>(*i));
+      Node* use = r.Return(n);
       Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kFloat32, Type::Signed32(),
-          MachineRepresentation::kWord32);
+          n, MachineRepresentation::kFloat32, Type::Signed32(), use,
+          UseInfo(MachineRepresentation::kWord32, Truncation::None()));
       r.CheckInt32Constant(c, *i);
     }
   }
@@ -342,19 +372,21 @@
   {
     FOR_INT32_INPUTS(i) {
       Node* n = r.jsgraph()->Float64Constant(*i);
-      Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kFloat64, Type::Signed32(),
-          MachineRepresentation::kWord32);
-      r.CheckInt32Constant(c, *i);
+  Node* use = r.Return(n);
+  Node* c = r.changer()->GetRepresentationFor(
+      n, MachineRepresentation::kFloat64, Type::Signed32(), use,
+      UseInfo(MachineRepresentation::kWord32, Truncation::None()));
+  r.CheckInt32Constant(c, *i);
     }
   }
 
   {
     FOR_INT32_INPUTS(i) {
       Node* n = r.jsgraph()->Constant(*i);
+      Node* use = r.Return(n);
       Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kTagged, Type::Signed32(),
-          MachineRepresentation::kWord32);
+          n, MachineRepresentation::kTagged, Type::Signed32(), use,
+          UseInfo(MachineRepresentation::kWord32, Truncation::None()));
       r.CheckInt32Constant(c, *i);
     }
   }
@@ -367,10 +399,11 @@
   {
     FOR_UINT32_INPUTS(i) {
       Node* n = r.jsgraph()->Int32Constant(*i);
-      Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kWord32, Type::Unsigned32(),
-          MachineRepresentation::kWord32);
-      r.CheckUint32Constant(c, *i);
+  Node* use = r.Return(n);
+  Node* c = r.changer()->GetRepresentationFor(
+      n, MachineRepresentation::kWord32, Type::Unsigned32(), use,
+      UseInfo(MachineRepresentation::kWord32, Truncation::None()));
+  r.CheckUint32Constant(c, *i);
     }
   }
 
@@ -378,9 +411,10 @@
     FOR_UINT32_INPUTS(i) {
       if (!IsFloat32Uint32(*i)) continue;
       Node* n = r.jsgraph()->Float32Constant(static_cast<float>(*i));
+      Node* use = r.Return(n);
       Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kFloat32, Type::Unsigned32(),
-          MachineRepresentation::kWord32);
+          n, MachineRepresentation::kFloat32, Type::Unsigned32(), use,
+          UseInfo(MachineRepresentation::kWord32, Truncation::None()));
       r.CheckUint32Constant(c, *i);
     }
   }
@@ -388,19 +422,21 @@
   {
     FOR_UINT32_INPUTS(i) {
       Node* n = r.jsgraph()->Float64Constant(*i);
-      Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kFloat64, Type::Unsigned32(),
-          MachineRepresentation::kWord32);
-      r.CheckUint32Constant(c, *i);
+  Node* use = r.Return(n);
+  Node* c = r.changer()->GetRepresentationFor(
+      n, MachineRepresentation::kFloat64, Type::Unsigned32(), use,
+      UseInfo(MachineRepresentation::kWord32, Truncation::None()));
+  r.CheckUint32Constant(c, *i);
     }
   }
 
   {
     FOR_UINT32_INPUTS(i) {
       Node* n = r.jsgraph()->Constant(static_cast<double>(*i));
+      Node* use = r.Return(n);
       Node* c = r.changer()->GetRepresentationFor(
-          n, MachineRepresentation::kTagged, Type::Unsigned32(),
-          MachineRepresentation::kWord32);
+          n, MachineRepresentation::kTagged, Type::Unsigned32(), use,
+          UseInfo(MachineRepresentation::kWord32, Truncation::None()));
       r.CheckUint32Constant(c, *i);
     }
   }
@@ -412,7 +448,9 @@
   RepresentationChangerTester r;
 
   Node* n = r.Parameter();
-  Node* c = r.changer()->GetRepresentationFor(n, from, from_type, to);
+  Node* use = r.Return(n);
+  Node* c = r.changer()->GetRepresentationFor(n, from, from_type, use,
+                                              UseInfo(to, Truncation::None()));
 
   CHECK_NE(c, n);
   CHECK_EQ(expected, c->opcode());
@@ -427,7 +465,9 @@
   RepresentationChangerTester r;
 
   Node* n = r.Parameter();
-  Node* c1 = r.changer()->GetRepresentationFor(n, from, from_type, to);
+  Node* use = r.Return(n);
+  Node* c1 = r.changer()->GetRepresentationFor(n, from, from_type, use,
+                                               UseInfo(to, Truncation::None()));
 
   CHECK_NE(c1, n);
   CHECK_EQ(expected1, c1->opcode());
@@ -439,24 +479,48 @@
 
 
 TEST(SingleChanges) {
-  CheckChange(IrOpcode::kChangeBoolToBit, MachineRepresentation::kTagged,
+  CheckChange(IrOpcode::kChangeTaggedToBit, MachineRepresentation::kTagged,
               Type::None(), MachineRepresentation::kBit);
-  CheckChange(IrOpcode::kChangeBitToBool, MachineRepresentation::kBit,
+  CheckChange(IrOpcode::kChangeBitToTagged, MachineRepresentation::kBit,
               Type::None(), MachineRepresentation::kTagged);
 
+  CheckChange(IrOpcode::kChangeInt31ToTaggedSigned,
+              MachineRepresentation::kWord32, Type::Signed31(),
+              MachineRepresentation::kTagged);
   CheckChange(IrOpcode::kChangeInt32ToTagged, MachineRepresentation::kWord32,
               Type::Signed32(), MachineRepresentation::kTagged);
   CheckChange(IrOpcode::kChangeUint32ToTagged, MachineRepresentation::kWord32,
               Type::Unsigned32(), MachineRepresentation::kTagged);
   CheckChange(IrOpcode::kChangeFloat64ToTagged, MachineRepresentation::kFloat64,
-              Type::None(), MachineRepresentation::kTagged);
+              Type::Number(), MachineRepresentation::kTagged);
+  CheckTwoChanges(IrOpcode::kChangeFloat64ToInt32,
+                  IrOpcode::kChangeInt31ToTaggedSigned,
+                  MachineRepresentation::kFloat64, Type::Signed31(),
+                  MachineRepresentation::kTagged);
+  CheckTwoChanges(IrOpcode::kChangeFloat64ToInt32,
+                  IrOpcode::kChangeInt32ToTagged,
+                  MachineRepresentation::kFloat64, Type::Signed32(),
+                  MachineRepresentation::kTagged);
+  CheckTwoChanges(IrOpcode::kChangeFloat64ToUint32,
+                  IrOpcode::kChangeUint32ToTagged,
+                  MachineRepresentation::kFloat64, Type::Unsigned32(),
+                  MachineRepresentation::kTagged);
 
   CheckChange(IrOpcode::kChangeTaggedToInt32, MachineRepresentation::kTagged,
               Type::Signed32(), MachineRepresentation::kWord32);
   CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged,
               Type::Unsigned32(), MachineRepresentation::kWord32);
   CheckChange(IrOpcode::kChangeTaggedToFloat64, MachineRepresentation::kTagged,
-              Type::None(), MachineRepresentation::kFloat64);
+              Type::Number(), MachineRepresentation::kFloat64);
+  CheckChange(IrOpcode::kChangeTaggedToFloat64, MachineRepresentation::kTagged,
+              Type::Number(), MachineRepresentation::kFloat64);
+  CheckChange(IrOpcode::kTruncateTaggedToFloat64,
+              MachineRepresentation::kTagged, Type::NumberOrUndefined(),
+              MachineRepresentation::kFloat64);
+  CheckTwoChanges(IrOpcode::kChangeTaggedSignedToInt32,
+                  IrOpcode::kChangeInt32ToFloat64,
+                  MachineRepresentation::kTagged, Type::TaggedSigned(),
+                  MachineRepresentation::kFloat64);
 
   // Int32,Uint32 <-> Float64 are actually machine conversions.
   CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32,
@@ -513,7 +577,7 @@
               Type::None(), MachineRepresentation::kFloat64);
   CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64,
               Type::Signed32(), MachineRepresentation::kWord32);
-  CheckChange(IrOpcode::kTruncateFloat64ToInt32,
+  CheckChange(IrOpcode::kTruncateFloat64ToWord32,
               MachineRepresentation::kFloat64, Type::Number(),
               MachineRepresentation::kWord32);
 
@@ -522,7 +586,7 @@
                   MachineRepresentation::kWord32, Type::None(),
                   MachineRepresentation::kFloat32);
   CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
-                  IrOpcode::kTruncateFloat64ToInt32,
+                  IrOpcode::kTruncateFloat64ToWord32,
                   MachineRepresentation::kFloat32, Type::Number(),
                   MachineRepresentation::kWord32);
 }
diff --git a/test/cctest/compiler/test-run-bytecode-graph-builder.cc b/test/cctest/compiler/test-run-bytecode-graph-builder.cc
index c32f923..024747f 100644
--- a/test/cctest/compiler/test-run-bytecode-graph-builder.cc
+++ b/test/cctest/compiler/test-run-bytecode-graph-builder.cc
@@ -125,11 +125,11 @@
     // having to instantiate a ParseInfo first. Fix this!
     ParseInfo parse_info(zone_, function);
 
-    CompilationInfo compilation_info(&parse_info);
+    CompilationInfo compilation_info(&parse_info, function);
     compilation_info.SetOptimizing();
     compilation_info.MarkAsDeoptimizationEnabled();
-    compiler::Pipeline pipeline(&compilation_info);
-    Handle<Code> code = pipeline.GenerateCode();
+    compilation_info.MarkAsOptimizeFromBytecode();
+    Handle<Code> code = Pipeline::GenerateCodeForTesting(&compilation_info);
     function->ReplaceCode(*code);
 
     return function;
diff --git a/test/cctest/compiler/test-run-calls-to-external-references.cc b/test/cctest/compiler/test-run-calls-to-external-references.cc
index 3b79cd8..430e238 100644
--- a/test/cctest/compiler/test-run-calls-to-external-references.cc
+++ b/test/cctest/compiler/test-run-calls-to-external-references.cc
@@ -2,6 +2,7 @@
 // source code is governed by a BSD-style license that can be found in the
 // LICENSE file.
 
+#include "src/wasm/wasm-external-refs.h"
 #include "test/cctest/cctest.h"
 #include "test/cctest/compiler/codegen-tester.h"
 #include "test/cctest/compiler/value-helper.h"
@@ -10,521 +11,234 @@
 namespace internal {
 namespace compiler {
 
-template <typename T>
-void TestExternalReferenceRoundingFunction(
-    BufferedRawMachineAssemblerTester<int32_t>* m, ExternalReference ref,
-    T (*comparison)(T)) {
-  T parameter;
+template <typename P>
+void TestExternalReference(BufferedRawMachineAssemblerTester<int32_t>* m,
+                           ExternalReference ref, void (*comparison)(P*),
+                           P param) {
+  P comparison_param = param;
 
   Node* function = m->ExternalConstant(ref);
   m->CallCFunction1(MachineType::Pointer(), MachineType::Pointer(), function,
-                    m->PointerConstant(&parameter));
+                    m->PointerConstant(&param));
   m->Return(m->Int32Constant(4356));
-  FOR_FLOAT64_INPUTS(i) {
-    parameter = *i;
-    m->Call();
-    CHECK_DOUBLE_EQ(comparison(*i), parameter);
-  }
+
+  m->Call();
+  comparison(&comparison_param);
+
+  CHECK_EQ(comparison_param, param);
+}
+
+template <typename P1, typename P2>
+void TestExternalReference(BufferedRawMachineAssemblerTester<int32_t>* m,
+                           ExternalReference ref, void (*comparison)(P1*, P2*),
+                           P1 param1, P2 param2) {
+  P1 comparison_param1 = param1;
+  P2 comparison_param2 = param2;
+
+  Node* function = m->ExternalConstant(ref);
+  m->CallCFunction2(MachineType::Pointer(), MachineType::Pointer(),
+                    MachineType::Pointer(), function,
+                    m->PointerConstant(&param1), m->PointerConstant(&param2));
+  m->Return(m->Int32Constant(4356));
+
+  m->Call();
+  comparison(&comparison_param1, &comparison_param2);
+
+  CHECK_EQ(comparison_param1, param1);
+  CHECK_EQ(comparison_param2, param2);
+}
+
+template <typename R, typename P>
+void TestExternalReference(BufferedRawMachineAssemblerTester<R>* m,
+                           ExternalReference ref, R (*comparison)(P*),
+                           P param) {
+  P comparison_param = param;
+
+  Node* function = m->ExternalConstant(ref);
+  m->Return(m->CallCFunction1(MachineType::Pointer(), MachineType::Pointer(),
+                              function, m->PointerConstant(&param)));
+
+  CHECK_EQ(comparison(&comparison_param), m->Call());
+
+  CHECK_EQ(comparison_param, param);
+}
+
+template <typename R, typename P1, typename P2>
+void TestExternalReference(BufferedRawMachineAssemblerTester<R>* m,
+                           ExternalReference ref, R (*comparison)(P1*, P2*),
+                           P1 param1, P2 param2) {
+  P1 comparison_param1 = param1;
+  P2 comparison_param2 = param2;
+
+  Node* function = m->ExternalConstant(ref);
+  m->Return(m->CallCFunction2(
+      MachineType::Pointer(), MachineType::Pointer(), MachineType::Pointer(),
+      function, m->PointerConstant(&param1), m->PointerConstant(&param2)));
+
+  CHECK_EQ(comparison(&comparison_param1, &comparison_param2), m->Call());
+
+  CHECK_EQ(comparison_param1, param1);
+  CHECK_EQ(comparison_param2, param2);
 }
 
 TEST(RunCallF32Trunc) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref = ExternalReference::wasm_f32_trunc(m.isolate());
-  TestExternalReferenceRoundingFunction<float>(&m, ref, truncf);
+  TestExternalReference(&m, ref, wasm::f32_trunc_wrapper, 1.25f);
 }
 
 TEST(RunCallF32Floor) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref = ExternalReference::wasm_f32_floor(m.isolate());
-  TestExternalReferenceRoundingFunction<float>(&m, ref, floorf);
+  TestExternalReference(&m, ref, wasm::f32_floor_wrapper, 1.25f);
 }
 
 TEST(RunCallF32Ceil) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref = ExternalReference::wasm_f32_ceil(m.isolate());
-  TestExternalReferenceRoundingFunction<float>(&m, ref, ceilf);
+  TestExternalReference(&m, ref, wasm::f32_ceil_wrapper, 1.25f);
 }
 
 TEST(RunCallF32RoundTiesEven) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref = ExternalReference::wasm_f32_nearest_int(m.isolate());
-  TestExternalReferenceRoundingFunction<float>(&m, ref, nearbyintf);
+  TestExternalReference(&m, ref, wasm::f32_nearest_int_wrapper, 1.25f);
 }
 
 TEST(RunCallF64Trunc) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref = ExternalReference::wasm_f64_trunc(m.isolate());
-  TestExternalReferenceRoundingFunction<double>(&m, ref, trunc);
+  TestExternalReference(&m, ref, wasm::f64_trunc_wrapper, 1.25);
 }
 
 TEST(RunCallF64Floor) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref = ExternalReference::wasm_f64_floor(m.isolate());
-  TestExternalReferenceRoundingFunction<double>(&m, ref, floor);
+  TestExternalReference(&m, ref, wasm::f64_floor_wrapper, 1.25);
 }
 
 TEST(RunCallF64Ceil) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref = ExternalReference::wasm_f64_ceil(m.isolate());
-  TestExternalReferenceRoundingFunction<double>(&m, ref, ceil);
+  TestExternalReference(&m, ref, wasm::f64_ceil_wrapper, 1.25);
 }
 
 TEST(RunCallF64RoundTiesEven) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref = ExternalReference::wasm_f64_nearest_int(m.isolate());
-  TestExternalReferenceRoundingFunction<double>(&m, ref, nearbyint);
+  TestExternalReference(&m, ref, wasm::f64_nearest_int_wrapper, 1.25);
 }
 
 TEST(RunCallInt64ToFloat32) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref = ExternalReference::wasm_int64_to_float32(m.isolate());
-
-  int64_t input;
-  float output;
-
-  Node* function = m.ExternalConstant(ref);
-  m.CallCFunction2(MachineType::Pointer(), MachineType::Pointer(),
-                   MachineType::Pointer(), function, m.PointerConstant(&input),
-                   m.PointerConstant(&output));
-  m.Return(m.Int32Constant(4356));
-  FOR_INT64_INPUTS(i) {
-    input = *i;
-    m.Call();
-    CHECK_FLOAT_EQ(static_cast<float>(*i), output);
-  }
+  TestExternalReference(&m, ref, wasm::int64_to_float32_wrapper, int64_t(-2124),
+                        1.25f);
 }
 
 TEST(RunCallUint64ToFloat32) {
-  struct {
-    uint64_t input;
-    uint32_t expected;
-  } values[] = {{0x0, 0x0},
-                {0x1, 0x3f800000},
-                {0xffffffff, 0x4f800000},
-                {0x1b09788b, 0x4dd84bc4},
-                {0x4c5fce8, 0x4c98bf9d},
-                {0xcc0de5bf, 0x4f4c0de6},
-                {0x2, 0x40000000},
-                {0x3, 0x40400000},
-                {0x4, 0x40800000},
-                {0x5, 0x40a00000},
-                {0x8, 0x41000000},
-                {0x9, 0x41100000},
-                {0xffffffffffffffff, 0x5f800000},
-                {0xfffffffffffffffe, 0x5f800000},
-                {0xfffffffffffffffd, 0x5f800000},
-                {0x0, 0x0},
-                {0x100000000, 0x4f800000},
-                {0xffffffff00000000, 0x5f800000},
-                {0x1b09788b00000000, 0x5dd84bc4},
-                {0x4c5fce800000000, 0x5c98bf9d},
-                {0xcc0de5bf00000000, 0x5f4c0de6},
-                {0x200000000, 0x50000000},
-                {0x300000000, 0x50400000},
-                {0x400000000, 0x50800000},
-                {0x500000000, 0x50a00000},
-                {0x800000000, 0x51000000},
-                {0x900000000, 0x51100000},
-                {0x273a798e187937a3, 0x5e1ce9e6},
-                {0xece3af835495a16b, 0x5f6ce3b0},
-                {0xb668ecc11223344, 0x5d3668ed},
-                {0x9e, 0x431e0000},
-                {0x43, 0x42860000},
-                {0xaf73, 0x472f7300},
-                {0x116b, 0x458b5800},
-                {0x658ecc, 0x4acb1d98},
-                {0x2b3b4c, 0x4a2ced30},
-                {0x88776655, 0x4f087766},
-                {0x70000000, 0x4ee00000},
-                {0x7200000, 0x4ce40000},
-                {0x7fffffff, 0x4f000000},
-                {0x56123761, 0x4eac246f},
-                {0x7fffff00, 0x4efffffe},
-                {0x761c4761eeeeeeee, 0x5eec388f},
-                {0x80000000eeeeeeee, 0x5f000000},
-                {0x88888888dddddddd, 0x5f088889},
-                {0xa0000000dddddddd, 0x5f200000},
-                {0xddddddddaaaaaaaa, 0x5f5dddde},
-                {0xe0000000aaaaaaaa, 0x5f600000},
-                {0xeeeeeeeeeeeeeeee, 0x5f6eeeef},
-                {0xfffffffdeeeeeeee, 0x5f800000},
-                {0xf0000000dddddddd, 0x5f700000},
-                {0x7fffffdddddddd, 0x5b000000},
-                {0x3fffffaaaaaaaa, 0x5a7fffff},
-                {0x1fffffaaaaaaaa, 0x59fffffd},
-                {0xfffff, 0x497ffff0},
-                {0x7ffff, 0x48ffffe0},
-                {0x3ffff, 0x487fffc0},
-                {0x1ffff, 0x47ffff80},
-                {0xffff, 0x477fff00},
-                {0x7fff, 0x46fffe00},
-                {0x3fff, 0x467ffc00},
-                {0x1fff, 0x45fff800},
-                {0xfff, 0x457ff000},
-                {0x7ff, 0x44ffe000},
-                {0x3ff, 0x447fc000},
-                {0x1ff, 0x43ff8000},
-                {0x3fffffffffff, 0x56800000},
-                {0x1fffffffffff, 0x56000000},
-                {0xfffffffffff, 0x55800000},
-                {0x7ffffffffff, 0x55000000},
-                {0x3ffffffffff, 0x54800000},
-                {0x1ffffffffff, 0x54000000},
-                {0x8000008000000000, 0x5f000000},
-                {0x8000008000000001, 0x5f000001},
-                {0x8000008000000002, 0x5f000001},
-                {0x8000008000000004, 0x5f000001},
-                {0x8000008000000008, 0x5f000001},
-                {0x8000008000000010, 0x5f000001},
-                {0x8000008000000020, 0x5f000001},
-                {0x8000009000000000, 0x5f000001},
-                {0x800000a000000000, 0x5f000001},
-                {0x8000008000100000, 0x5f000001},
-                {0x8000000000000400, 0x5f000000},
-                {0x8000000000000401, 0x5f000000}};
-
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref =
       ExternalReference::wasm_uint64_to_float32(m.isolate());
-
-  uint64_t input;
-  float output;
-
-  Node* function = m.ExternalConstant(ref);
-  m.CallCFunction2(MachineType::Pointer(), MachineType::Pointer(),
-                   MachineType::Pointer(), function, m.PointerConstant(&input),
-                   m.PointerConstant(&output));
-  m.Return(m.Int32Constant(4356));
-
-  for (size_t i = 0; i < arraysize(values); i++) {
-    input = values[i].input;
-    m.Call();
-    CHECK_EQ(values[i].expected, bit_cast<uint32_t>(output));
-  }
+  TestExternalReference(&m, ref, wasm::uint64_to_float32_wrapper,
+                        uint64_t(2124), 1.25f);
 }
 
 TEST(RunCallInt64ToFloat64) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref = ExternalReference::wasm_int64_to_float64(m.isolate());
-
-  int64_t input;
-  double output;
-
-  Node* function = m.ExternalConstant(ref);
-  m.CallCFunction2(MachineType::Pointer(), MachineType::Pointer(),
-                   MachineType::Pointer(), function, m.PointerConstant(&input),
-                   m.PointerConstant(&output));
-  m.Return(m.Int32Constant(4356));
-  FOR_INT64_INPUTS(i) {
-    input = *i;
-    m.Call();
-    CHECK_DOUBLE_EQ(static_cast<double>(*i), output);
-  }
+  TestExternalReference(&m, ref, wasm::int64_to_float64_wrapper, int64_t(2124),
+                        1.25);
 }
 
 TEST(RunCallUint64ToFloat64) {
-  struct {
-    uint64_t input;
-    uint64_t expected;
-  } values[] = {{0x0, 0x0},
-                {0x1, 0x3ff0000000000000},
-                {0xffffffff, 0x41efffffffe00000},
-                {0x1b09788b, 0x41bb09788b000000},
-                {0x4c5fce8, 0x419317f3a0000000},
-                {0xcc0de5bf, 0x41e981bcb7e00000},
-                {0x2, 0x4000000000000000},
-                {0x3, 0x4008000000000000},
-                {0x4, 0x4010000000000000},
-                {0x5, 0x4014000000000000},
-                {0x8, 0x4020000000000000},
-                {0x9, 0x4022000000000000},
-                {0xffffffffffffffff, 0x43f0000000000000},
-                {0xfffffffffffffffe, 0x43f0000000000000},
-                {0xfffffffffffffffd, 0x43f0000000000000},
-                {0x100000000, 0x41f0000000000000},
-                {0xffffffff00000000, 0x43efffffffe00000},
-                {0x1b09788b00000000, 0x43bb09788b000000},
-                {0x4c5fce800000000, 0x439317f3a0000000},
-                {0xcc0de5bf00000000, 0x43e981bcb7e00000},
-                {0x200000000, 0x4200000000000000},
-                {0x300000000, 0x4208000000000000},
-                {0x400000000, 0x4210000000000000},
-                {0x500000000, 0x4214000000000000},
-                {0x800000000, 0x4220000000000000},
-                {0x900000000, 0x4222000000000000},
-                {0x273a798e187937a3, 0x43c39d3cc70c3c9c},
-                {0xece3af835495a16b, 0x43ed9c75f06a92b4},
-                {0xb668ecc11223344, 0x43a6cd1d98224467},
-                {0x9e, 0x4063c00000000000},
-                {0x43, 0x4050c00000000000},
-                {0xaf73, 0x40e5ee6000000000},
-                {0x116b, 0x40b16b0000000000},
-                {0x658ecc, 0x415963b300000000},
-                {0x2b3b4c, 0x41459da600000000},
-                {0x88776655, 0x41e10eeccaa00000},
-                {0x70000000, 0x41dc000000000000},
-                {0x7200000, 0x419c800000000000},
-                {0x7fffffff, 0x41dfffffffc00000},
-                {0x56123761, 0x41d5848dd8400000},
-                {0x7fffff00, 0x41dfffffc0000000},
-                {0x761c4761eeeeeeee, 0x43dd8711d87bbbbc},
-                {0x80000000eeeeeeee, 0x43e00000001dddde},
-                {0x88888888dddddddd, 0x43e11111111bbbbc},
-                {0xa0000000dddddddd, 0x43e40000001bbbbc},
-                {0xddddddddaaaaaaaa, 0x43ebbbbbbbb55555},
-                {0xe0000000aaaaaaaa, 0x43ec000000155555},
-                {0xeeeeeeeeeeeeeeee, 0x43edddddddddddde},
-                {0xfffffffdeeeeeeee, 0x43efffffffbdddde},
-                {0xf0000000dddddddd, 0x43ee0000001bbbbc},
-                {0x7fffffdddddddd, 0x435ffffff7777777},
-                {0x3fffffaaaaaaaa, 0x434fffffd5555555},
-                {0x1fffffaaaaaaaa, 0x433fffffaaaaaaaa},
-                {0xfffff, 0x412ffffe00000000},
-                {0x7ffff, 0x411ffffc00000000},
-                {0x3ffff, 0x410ffff800000000},
-                {0x1ffff, 0x40fffff000000000},
-                {0xffff, 0x40efffe000000000},
-                {0x7fff, 0x40dfffc000000000},
-                {0x3fff, 0x40cfff8000000000},
-                {0x1fff, 0x40bfff0000000000},
-                {0xfff, 0x40affe0000000000},
-                {0x7ff, 0x409ffc0000000000},
-                {0x3ff, 0x408ff80000000000},
-                {0x1ff, 0x407ff00000000000},
-                {0x3fffffffffff, 0x42cfffffffffff80},
-                {0x1fffffffffff, 0x42bfffffffffff00},
-                {0xfffffffffff, 0x42affffffffffe00},
-                {0x7ffffffffff, 0x429ffffffffffc00},
-                {0x3ffffffffff, 0x428ffffffffff800},
-                {0x1ffffffffff, 0x427ffffffffff000},
-                {0x8000008000000000, 0x43e0000010000000},
-                {0x8000008000000001, 0x43e0000010000000},
-                {0x8000000000000400, 0x43e0000000000000},
-                {0x8000000000000401, 0x43e0000000000001},
-                {0x8000000000000402, 0x43e0000000000001},
-                {0x8000000000000404, 0x43e0000000000001},
-                {0x8000000000000408, 0x43e0000000000001},
-                {0x8000000000000410, 0x43e0000000000001},
-                {0x8000000000000420, 0x43e0000000000001},
-                {0x8000000000000440, 0x43e0000000000001},
-                {0x8000000000000480, 0x43e0000000000001},
-                {0x8000000000000500, 0x43e0000000000001},
-                {0x8000000000000600, 0x43e0000000000001}};
-
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref =
       ExternalReference::wasm_uint64_to_float64(m.isolate());
-
-  uint64_t input;
-  double output;
-
-  Node* function = m.ExternalConstant(ref);
-  m.CallCFunction2(MachineType::Pointer(), MachineType::Pointer(),
-                   MachineType::Pointer(), function, m.PointerConstant(&input),
-                   m.PointerConstant(&output));
-  m.Return(m.Int32Constant(4356));
-
-  for (size_t i = 0; i < arraysize(values); i++) {
-    input = values[i].input;
-    m.Call();
-    CHECK_EQ(values[i].expected, bit_cast<uint64_t>(output));
-  }
+  TestExternalReference(&m, ref, wasm::uint64_to_float64_wrapper,
+                        uint64_t(2124), 1.25);
 }
 
 TEST(RunCallFloat32ToInt64) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref = ExternalReference::wasm_float32_to_int64(m.isolate());
-
-  float input;
-  int64_t output;
-
-  Node* function = m.ExternalConstant(ref);
-  m.Return(m.CallCFunction2(
-      MachineType::Int32(), MachineType::Pointer(), MachineType::Pointer(),
-      function, m.PointerConstant(&input), m.PointerConstant(&output)));
-  FOR_FLOAT32_INPUTS(i) {
-    input = *i;
-    if (*i >= static_cast<float>(std::numeric_limits<int64_t>::min()) &&
-        *i < static_cast<float>(std::numeric_limits<int64_t>::max())) {
-      CHECK_EQ(1, m.Call());
-      CHECK_EQ(static_cast<int64_t>(*i), output);
-    } else {
-      CHECK_EQ(0, m.Call());
-    }
-  }
+  TestExternalReference(&m, ref, wasm::float32_to_int64_wrapper, 1.25f,
+                        int64_t(2124));
 }
 
 TEST(RunCallFloat32ToUint64) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref =
       ExternalReference::wasm_float32_to_uint64(m.isolate());
-
-  float input;
-  uint64_t output;
-
-  Node* function = m.ExternalConstant(ref);
-  m.Return(m.CallCFunction2(
-      MachineType::Int32(), MachineType::Pointer(), MachineType::Pointer(),
-      function, m.PointerConstant(&input), m.PointerConstant(&output)));
-  FOR_FLOAT32_INPUTS(i) {
-    input = *i;
-    if (*i > -1.0 &&
-        *i < static_cast<float>(std::numeric_limits<uint64_t>::max())) {
-      CHECK_EQ(1, m.Call());
-      CHECK_EQ(static_cast<uint64_t>(*i), output);
-    } else {
-      CHECK_EQ(0, m.Call());
-    }
-  }
+  TestExternalReference(&m, ref, wasm::float32_to_uint64_wrapper, 1.25f,
+                        uint64_t(2124));
 }
 
 TEST(RunCallFloat64ToInt64) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref = ExternalReference::wasm_float64_to_int64(m.isolate());
-
-  double input;
-  int64_t output;
-
-  Node* function = m.ExternalConstant(ref);
-  m.Return(m.CallCFunction2(
-      MachineType::Int32(), MachineType::Pointer(), MachineType::Pointer(),
-      function, m.PointerConstant(&input), m.PointerConstant(&output)));
-  FOR_FLOAT64_INPUTS(i) {
-    input = *i;
-    if (*i >= static_cast<double>(std::numeric_limits<int64_t>::min()) &&
-        *i < static_cast<double>(std::numeric_limits<int64_t>::max())) {
-      CHECK_EQ(1, m.Call());
-      CHECK_EQ(static_cast<int64_t>(*i), output);
-    } else {
-      CHECK_EQ(0, m.Call());
-    }
-  }
+  TestExternalReference(&m, ref, wasm::float64_to_int64_wrapper, 1.25,
+                        int64_t(2124));
 }
 
 TEST(RunCallFloat64ToUint64) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref =
       ExternalReference::wasm_float64_to_uint64(m.isolate());
-
-  double input;
-  uint64_t output;
-
-  Node* function = m.ExternalConstant(ref);
-  m.Return(m.CallCFunction2(
-      MachineType::Int32(), MachineType::Pointer(), MachineType::Pointer(),
-      function, m.PointerConstant(&input), m.PointerConstant(&output)));
-  FOR_FLOAT64_INPUTS(i) {
-    input = *i;
-    if (*i > -1.0 &&
-        *i < static_cast<double>(std::numeric_limits<uint64_t>::max())) {
-      CHECK_EQ(1, m.Call());
-      CHECK_EQ(static_cast<uint64_t>(*i), output);
-    } else {
-      CHECK_EQ(0, m.Call());
-    }
-  }
+  TestExternalReference(&m, ref, wasm::float64_to_uint64_wrapper, 1.25,
+                        uint64_t(2124));
 }
 
 TEST(RunCallInt64Div) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref = ExternalReference::wasm_int64_div(m.isolate());
-
-  int64_t dst;
-  int64_t src;
-
-  Node* function = m.ExternalConstant(ref);
-  m.Return(m.CallCFunction2(MachineType::Int32(), MachineType::Pointer(),
-                            MachineType::Pointer(), function,
-                            m.PointerConstant(&dst), m.PointerConstant(&src)));
-  FOR_INT64_INPUTS(i) {
-    FOR_INT64_INPUTS(j) {
-      dst = *i;
-      src = *j;
-      if (src == 0) {
-        CHECK_EQ(0, m.Call());
-      } else if (src == -1 && dst == std::numeric_limits<int64_t>::min()) {
-        CHECK_EQ(-1, m.Call());
-      } else {
-        CHECK_EQ(1, m.Call());
-        CHECK_EQ(*i / *j, dst);
-      }
-    }
-  }
+  TestExternalReference(&m, ref, wasm::int64_div_wrapper, int64_t(1774),
+                        int64_t(21));
 }
 
 TEST(RunCallInt64Mod) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref = ExternalReference::wasm_int64_mod(m.isolate());
-
-  int64_t dst;
-  int64_t src;
-
-  Node* function = m.ExternalConstant(ref);
-  m.Return(m.CallCFunction2(MachineType::Int32(), MachineType::Pointer(),
-                            MachineType::Pointer(), function,
-                            m.PointerConstant(&dst), m.PointerConstant(&src)));
-  FOR_INT64_INPUTS(i) {
-    FOR_INT64_INPUTS(j) {
-      dst = *i;
-      src = *j;
-      if (src == 0) {
-        CHECK_EQ(0, m.Call());
-      } else {
-        CHECK_EQ(1, m.Call());
-        CHECK_EQ(*i % *j, dst);
-      }
-    }
-  }
+  TestExternalReference(&m, ref, wasm::int64_mod_wrapper, int64_t(1774),
+                        int64_t(21));
 }
 
 TEST(RunCallUint64Div) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref = ExternalReference::wasm_uint64_div(m.isolate());
-
-  uint64_t dst;
-  uint64_t src;
-
-  Node* function = m.ExternalConstant(ref);
-  m.Return(m.CallCFunction2(MachineType::Int32(), MachineType::Pointer(),
-                            MachineType::Pointer(), function,
-                            m.PointerConstant(&dst), m.PointerConstant(&src)));
-  FOR_UINT64_INPUTS(i) {
-    FOR_UINT64_INPUTS(j) {
-      dst = *i;
-      src = *j;
-      if (src == 0) {
-        CHECK_EQ(0, m.Call());
-      } else {
-        CHECK_EQ(1, m.Call());
-        CHECK_EQ(*i / *j, dst);
-      }
-    }
-  }
+  TestExternalReference(&m, ref, wasm::uint64_div_wrapper, uint64_t(1774),
+                        uint64_t(21));
 }
 
 TEST(RunCallUint64Mod) {
   BufferedRawMachineAssemblerTester<int32_t> m;
   ExternalReference ref = ExternalReference::wasm_uint64_mod(m.isolate());
+  TestExternalReference(&m, ref, wasm::uint64_mod_wrapper, uint64_t(1774),
+                        uint64_t(21));
+}
 
-  uint64_t dst;
-  uint64_t src;
+TEST(RunCallWord32Ctz) {
+  BufferedRawMachineAssemblerTester<uint32_t> m;
+  ExternalReference ref = ExternalReference::wasm_word32_ctz(m.isolate());
+  TestExternalReference(&m, ref, wasm::word32_ctz_wrapper, uint32_t(1774));
+}
 
-  Node* function = m.ExternalConstant(ref);
-  m.Return(m.CallCFunction2(MachineType::Int32(), MachineType::Pointer(),
-                            MachineType::Pointer(), function,
-                            m.PointerConstant(&dst), m.PointerConstant(&src)));
-  FOR_UINT64_INPUTS(i) {
-    FOR_UINT64_INPUTS(j) {
-      dst = *i;
-      src = *j;
-      if (src == 0) {
-        CHECK_EQ(0, m.Call());
-      } else {
-        CHECK_EQ(1, m.Call());
-        CHECK_EQ(*i % *j, dst);
-      }
-    }
-  }
+TEST(RunCallWord64Ctz) {
+  BufferedRawMachineAssemblerTester<uint32_t> m;
+  ExternalReference ref = ExternalReference::wasm_word64_ctz(m.isolate());
+  TestExternalReference(&m, ref, wasm::word64_ctz_wrapper, uint64_t(1774));
+}
+
+TEST(RunCallWord32Popcnt) {
+  BufferedRawMachineAssemblerTester<uint32_t> m;
+  ExternalReference ref = ExternalReference::wasm_word32_popcnt(m.isolate());
+  TestExternalReference(&m, ref, wasm::word32_popcnt_wrapper, uint32_t(1774));
+}
+
+TEST(RunCallWord64Popcnt) {
+  BufferedRawMachineAssemblerTester<uint32_t> m;
+  ExternalReference ref = ExternalReference::wasm_word64_popcnt(m.isolate());
+  TestExternalReference(&m, ref, wasm::word64_popcnt_wrapper, uint64_t(1774));
 }
 }  // namespace compiler
 }  // namespace internal
diff --git a/test/cctest/compiler/test-run-inlining.cc b/test/cctest/compiler/test-run-inlining.cc
index 234060c..e689bf7 100644
--- a/test/cctest/compiler/test-run-inlining.cc
+++ b/test/cctest/compiler/test-run-inlining.cc
@@ -16,9 +16,9 @@
 void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
   StackTraceFrameIterator it(CcTest::i_isolate());
   int frames_seen = 0;
-  JavaScriptFrame* topmost = it.frame();
+  JavaScriptFrame* topmost = it.javascript_frame();
   while (!it.done()) {
-    JavaScriptFrame* frame = it.frame();
+    JavaScriptFrame* frame = it.javascript_frame();
     List<JSFunction*> functions(2);
     frame->GetFunctions(&functions);
     PrintF("%d %s, inline count: %d\n", frames_seen,
@@ -47,14 +47,11 @@
             .FromJust());
 }
 
-
 const uint32_t kRestrictedInliningFlags =
-    CompilationInfo::kFunctionContextSpecializing |
-    CompilationInfo::kTypingEnabled;
+    CompilationInfo::kFunctionContextSpecializing;
 
 const uint32_t kInlineFlags = CompilationInfo::kInliningEnabled |
-                              CompilationInfo::kFunctionContextSpecializing |
-                              CompilationInfo::kTypingEnabled;
+                              CompilationInfo::kFunctionContextSpecializing;
 
 }  // namespace
 
diff --git a/test/cctest/compiler/test-run-intrinsics.cc b/test/cctest/compiler/test-run-intrinsics.cc
index 6aa5f39..0ea611b 100644
--- a/test/cctest/compiler/test-run-intrinsics.cc
+++ b/test/cctest/compiler/test-run-intrinsics.cc
@@ -111,37 +111,6 @@
 }
 
 
-TEST(OneByteSeqStringGetChar) {
-  FunctionTester T("(function(a,b) { return %_OneByteSeqStringGetChar(a,b); })",
-                   flags);
-
-  Handle<SeqOneByteString> string =
-      T.main_isolate()->factory()->NewRawOneByteString(3).ToHandleChecked();
-  string->SeqOneByteStringSet(0, 'b');
-  string->SeqOneByteStringSet(1, 'a');
-  string->SeqOneByteStringSet(2, 'r');
-  T.CheckCall(T.Val('b'), string, T.Val(0.0));
-  T.CheckCall(T.Val('a'), string, T.Val(1));
-  T.CheckCall(T.Val('r'), string, T.Val(2));
-}
-
-
-TEST(OneByteSeqStringSetChar) {
-  FunctionTester T("(function(a,b) { %_OneByteSeqStringSetChar(a,88,b); })",
-                   flags);
-
-  Handle<SeqOneByteString> string =
-      T.main_isolate()->factory()->NewRawOneByteString(3).ToHandleChecked();
-  string->SeqOneByteStringSet(0, 'b');
-  string->SeqOneByteStringSet(1, 'a');
-  string->SeqOneByteStringSet(2, 'r');
-  T.Call(T.Val(1), string);
-  CHECK_EQ('b', string->SeqOneByteStringGet(0));
-  CHECK_EQ('X', string->SeqOneByteStringGet(1));
-  CHECK_EQ('r', string->SeqOneByteStringGet(2));
-}
-
-
 TEST(StringAdd) {
   FunctionTester T("(function(a,b) { return %_StringAdd(a,b); })", flags);
 
@@ -151,15 +120,6 @@
 }
 
 
-TEST(StringCharAt) {
-  FunctionTester T("(function(a,b) { return %_StringCharAt(a,b); })", flags);
-
-  T.CheckCall(T.Val("e"), T.Val("huge fan!"), T.Val(3));
-  T.CheckCall(T.Val("f"), T.Val("\xE2\x9D\x8A fan!"), T.Val(2));
-  T.CheckCall(T.Val(""), T.Val("not a fan!"), T.Val(23));
-}
-
-
 TEST(StringCharCodeAt) {
   FunctionTester T("(function(a,b) { return %_StringCharCodeAt(a,b); })",
                    flags);
@@ -197,37 +157,6 @@
 }
 
 
-TEST(TwoByteSeqStringGetChar) {
-  FunctionTester T("(function(a,b) { return %_TwoByteSeqStringGetChar(a,b); })",
-                   flags);
-
-  Handle<SeqTwoByteString> string =
-      T.main_isolate()->factory()->NewRawTwoByteString(3).ToHandleChecked();
-  string->SeqTwoByteStringSet(0, 'b');
-  string->SeqTwoByteStringSet(1, 'a');
-  string->SeqTwoByteStringSet(2, 'r');
-  T.CheckCall(T.Val('b'), string, T.Val(0.0));
-  T.CheckCall(T.Val('a'), string, T.Val(1));
-  T.CheckCall(T.Val('r'), string, T.Val(2));
-}
-
-
-TEST(TwoByteSeqStringSetChar) {
-  FunctionTester T("(function(a,b) { %_TwoByteSeqStringSetChar(a,88,b); })",
-                   flags);
-
-  Handle<SeqTwoByteString> string =
-      T.main_isolate()->factory()->NewRawTwoByteString(3).ToHandleChecked();
-  string->SeqTwoByteStringSet(0, 'b');
-  string->SeqTwoByteStringSet(1, 'a');
-  string->SeqTwoByteStringSet(2, 'r');
-  T.Call(T.Val(1), string);
-  CHECK_EQ('b', string->SeqTwoByteStringGet(0));
-  CHECK_EQ('X', string->SeqTwoByteStringGet(1));
-  CHECK_EQ('r', string->SeqTwoByteStringGet(2));
-}
-
-
 TEST(ValueOf) {
   FunctionTester T("(function(a) { return %_ValueOf(a); })", flags);
 
diff --git a/test/cctest/compiler/test-run-jscalls.cc b/test/cctest/compiler/test-run-jscalls.cc
index 12566c2..06cfcd2 100644
--- a/test/cctest/compiler/test-run-jscalls.cc
+++ b/test/cctest/compiler/test-run-jscalls.cc
@@ -218,6 +218,7 @@
   i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun);
   jsfun->set_code(T.function->code());
   jsfun->set_shared(T.function->shared());
+  jsfun->set_literals(T.function->literals());
   CHECK(context->Global()
             ->Set(context, v8_str("foo"), v8::Utils::CallableToLocal(jsfun))
             .FromJust());
@@ -242,6 +243,7 @@
   i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun);
   jsfun->set_code(T.function->code());
   jsfun->set_shared(T.function->shared());
+  jsfun->set_literals(T.function->literals());
   CHECK(context->Global()
             ->Set(context, v8_str("foo"), v8::Utils::CallableToLocal(jsfun))
             .FromJust());
diff --git a/test/cctest/compiler/test-run-jsops.cc b/test/cctest/compiler/test-run-jsops.cc
index b68fc1c..78e1257 100644
--- a/test/cctest/compiler/test-run-jsops.cc
+++ b/test/cctest/compiler/test-run-jsops.cc
@@ -512,7 +512,6 @@
 
 
 TEST(ClassLiteral) {
-  FLAG_harmony_sloppy = true;
   const char* src =
       "(function(a,b) {"
       "  class C {"
diff --git a/test/cctest/compiler/test-run-load-store.cc b/test/cctest/compiler/test-run-load-store.cc
new file mode 100644
index 0000000..6484d30
--- /dev/null
+++ b/test/cctest/compiler/test-run-load-store.cc
@@ -0,0 +1,919 @@
+// Copyright 2016 the V8 project authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in the
+// LICENSE file.
+
+#include <cmath>
+#include <functional>
+#include <limits>
+
+#include "src/base/bits.h"
+#include "src/base/utils/random-number-generator.h"
+#include "src/codegen.h"
+#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/codegen-tester.h"
+#include "test/cctest/compiler/graph-builder-tester.h"
+#include "test/cctest/compiler/value-helper.h"
+
+using namespace v8::base;
+
+namespace {
+template <typename Type>
+void CheckOobValue(Type val) {
+  UNREACHABLE();
+}
+
+template <>
+void CheckOobValue(int32_t val) {
+  CHECK_EQ(0, val);
+}
+
+template <>
+void CheckOobValue(int64_t val) {
+  CHECK_EQ(0, val);
+}
+
+template <>
+void CheckOobValue(float val) {
+  CHECK(std::isnan(val));
+}
+
+template <>
+void CheckOobValue(double val) {
+  CHECK(std::isnan(val));
+}
+}  // namespace
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+// This is a America!
+#define A_BILLION 1000000000ULL
+#define A_GIG (1024ULL * 1024ULL * 1024ULL)
+
+TEST(RunLoadInt32) {
+  RawMachineAssemblerTester<int32_t> m;
+
+  int32_t p1 = 0;  // loads directly from this location.
+  m.Return(m.LoadFromPointer(&p1, MachineType::Int32()));
+
+  FOR_INT32_INPUTS(i) {
+    p1 = *i;
+    CHECK_EQ(p1, m.Call());
+  }
+}
+
+TEST(RunLoadInt32Offset) {
+  int32_t p1 = 0;  // loads directly from this location.
+
+  int32_t offsets[] = {-2000000, -100, -101, 1,          3,
+                       7,        120,  2000, 2000000000, 0xff};
+
+  for (size_t i = 0; i < arraysize(offsets); i++) {
+    RawMachineAssemblerTester<int32_t> m;
+    int32_t offset = offsets[i];
+    byte* pointer = reinterpret_cast<byte*>(&p1) - offset;
+    // generate load [#base + #index]
+    m.Return(m.LoadFromPointer(pointer, MachineType::Int32(), offset));
+
+    FOR_INT32_INPUTS(j) {
+      p1 = *j;
+      CHECK_EQ(p1, m.Call());
+    }
+  }
+}
+
+TEST(RunLoadStoreFloat32Offset) {
+  float p1 = 0.0f;  // loads directly from this location.
+  float p2 = 0.0f;  // and stores directly into this location.
+
+  FOR_INT32_INPUTS(i) {
+    int32_t magic = 0x2342aabb + *i * 3;
+    RawMachineAssemblerTester<int32_t> m;
+    int32_t offset = *i;
+    byte* from = reinterpret_cast<byte*>(&p1) - offset;
+    byte* to = reinterpret_cast<byte*>(&p2) - offset;
+    // generate load [#base + #index]
+    Node* load = m.Load(MachineType::Float32(), m.PointerConstant(from),
+                        m.IntPtrConstant(offset));
+    m.Store(MachineRepresentation::kFloat32, m.PointerConstant(to),
+            m.IntPtrConstant(offset), load, kNoWriteBarrier);
+    m.Return(m.Int32Constant(magic));
+
+    FOR_FLOAT32_INPUTS(j) {
+      p1 = *j;
+      p2 = *j - 5;
+      CHECK_EQ(magic, m.Call());
+      CheckDoubleEq(p1, p2);
+    }
+  }
+}
+
+TEST(RunLoadStoreFloat64Offset) {
+  double p1 = 0;  // loads directly from this location.
+  double p2 = 0;  // and stores directly into this location.
+
+  FOR_INT32_INPUTS(i) {
+    int32_t magic = 0x2342aabb + *i * 3;
+    RawMachineAssemblerTester<int32_t> m;
+    int32_t offset = *i;
+    byte* from = reinterpret_cast<byte*>(&p1) - offset;
+    byte* to = reinterpret_cast<byte*>(&p2) - offset;
+    // generate load [#base + #index]
+    Node* load = m.Load(MachineType::Float64(), m.PointerConstant(from),
+                        m.IntPtrConstant(offset));
+    m.Store(MachineRepresentation::kFloat64, m.PointerConstant(to),
+            m.IntPtrConstant(offset), load, kNoWriteBarrier);
+    m.Return(m.Int32Constant(magic));
+
+    FOR_FLOAT64_INPUTS(j) {
+      p1 = *j;
+      p2 = *j - 5;
+      CHECK_EQ(magic, m.Call());
+      CheckDoubleEq(p1, p2);
+    }
+  }
+}
+
+namespace {
+template <typename Type>
+void RunLoadImmIndex(MachineType rep) {
+  const int kNumElems = 3;
+  Type buffer[kNumElems];
+
+  // initialize the buffer with some raw data.
+  byte* raw = reinterpret_cast<byte*>(buffer);
+  for (size_t i = 0; i < sizeof(buffer); i++) {
+    raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA);
+  }
+
+  // Test with various large and small offsets.
+  for (int offset = -1; offset <= 200000; offset *= -5) {
+    for (int i = 0; i < kNumElems; i++) {
+      BufferedRawMachineAssemblerTester<Type> m;
+      Node* base = m.PointerConstant(buffer - offset);
+      Node* index = m.Int32Constant((offset + i) * sizeof(buffer[0]));
+      m.Return(m.Load(rep, base, index));
+
+      volatile Type expected = buffer[i];
+      volatile Type actual = m.Call();
+      CHECK_EQ(expected, actual);
+    }
+  }
+}
+
+template <typename CType>
+void RunLoadStore(MachineType rep) {
+  const int kNumElems = 4;
+  CType buffer[kNumElems];
+
+  for (int32_t x = 0; x < kNumElems; x++) {
+    int32_t y = kNumElems - x - 1;
+    // initialize the buffer with raw data.
+    byte* raw = reinterpret_cast<byte*>(buffer);
+    for (size_t i = 0; i < sizeof(buffer); i++) {
+      raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA);
+    }
+
+    RawMachineAssemblerTester<int32_t> m;
+    int32_t OK = 0x29000 + x;
+    Node* base = m.PointerConstant(buffer);
+    Node* index0 = m.IntPtrConstant(x * sizeof(buffer[0]));
+    Node* load = m.Load(rep, base, index0);
+    Node* index1 = m.IntPtrConstant(y * sizeof(buffer[0]));
+    m.Store(rep.representation(), base, index1, load, kNoWriteBarrier);
+    m.Return(m.Int32Constant(OK));
+
+    CHECK(buffer[x] != buffer[y]);
+    CHECK_EQ(OK, m.Call());
+    CHECK(buffer[x] == buffer[y]);
+  }
+}
+}  // namespace
+
+TEST(RunLoadImmIndex) {
+  RunLoadImmIndex<int8_t>(MachineType::Int8());
+  RunLoadImmIndex<uint8_t>(MachineType::Uint8());
+  RunLoadImmIndex<int16_t>(MachineType::Int16());
+  RunLoadImmIndex<uint16_t>(MachineType::Uint16());
+  RunLoadImmIndex<int32_t>(MachineType::Int32());
+  RunLoadImmIndex<uint32_t>(MachineType::Uint32());
+  RunLoadImmIndex<int32_t*>(MachineType::AnyTagged());
+  RunLoadImmIndex<float>(MachineType::Float32());
+  RunLoadImmIndex<double>(MachineType::Float64());
+#if V8_TARGET_ARCH_64_BIT
+  RunLoadImmIndex<int64_t>(MachineType::Int64());
+#endif
+  // TODO(titzer): test various indexing modes.
+}
+
+TEST(RunLoadStore) {
+  RunLoadStore<int8_t>(MachineType::Int8());
+  RunLoadStore<uint8_t>(MachineType::Uint8());
+  RunLoadStore<int16_t>(MachineType::Int16());
+  RunLoadStore<uint16_t>(MachineType::Uint16());
+  RunLoadStore<int32_t>(MachineType::Int32());
+  RunLoadStore<uint32_t>(MachineType::Uint32());
+  RunLoadStore<void*>(MachineType::AnyTagged());
+  RunLoadStore<float>(MachineType::Float32());
+  RunLoadStore<double>(MachineType::Float64());
+#if V8_TARGET_ARCH_64_BIT
+  RunLoadStore<int64_t>(MachineType::Int64());
+#endif
+}
+
+#if V8_TARGET_LITTLE_ENDIAN
+#define LSB(addr, bytes) addr
+#elif V8_TARGET_BIG_ENDIAN
+#define LSB(addr, bytes) reinterpret_cast<byte*>(addr + 1) - bytes
+#else
+#error "Unknown Architecture"
+#endif
+
+TEST(RunLoadStoreSignExtend32) {
+  int32_t buffer[4];
+  RawMachineAssemblerTester<int32_t> m;
+  Node* load8 = m.LoadFromPointer(LSB(&buffer[0], 1), MachineType::Int8());
+  Node* load16 = m.LoadFromPointer(LSB(&buffer[0], 2), MachineType::Int16());
+  Node* load32 = m.LoadFromPointer(&buffer[0], MachineType::Int32());
+  m.StoreToPointer(&buffer[1], MachineRepresentation::kWord32, load8);
+  m.StoreToPointer(&buffer[2], MachineRepresentation::kWord32, load16);
+  m.StoreToPointer(&buffer[3], MachineRepresentation::kWord32, load32);
+  m.Return(load8);
+
+  FOR_INT32_INPUTS(i) {
+    buffer[0] = *i;
+
+    CHECK_EQ(static_cast<int8_t>(*i & 0xff), m.Call());
+    CHECK_EQ(static_cast<int8_t>(*i & 0xff), buffer[1]);
+    CHECK_EQ(static_cast<int16_t>(*i & 0xffff), buffer[2]);
+    CHECK_EQ(*i, buffer[3]);
+  }
+}
+
+TEST(RunLoadStoreZeroExtend32) {
+  uint32_t buffer[4];
+  RawMachineAssemblerTester<uint32_t> m;
+  Node* load8 = m.LoadFromPointer(LSB(&buffer[0], 1), MachineType::Uint8());
+  Node* load16 = m.LoadFromPointer(LSB(&buffer[0], 2), MachineType::Uint16());
+  Node* load32 = m.LoadFromPointer(&buffer[0], MachineType::Uint32());
+  m.StoreToPointer(&buffer[1], MachineRepresentation::kWord32, load8);
+  m.StoreToPointer(&buffer[2], MachineRepresentation::kWord32, load16);
+  m.StoreToPointer(&buffer[3], MachineRepresentation::kWord32, load32);
+  m.Return(load8);
+
+  FOR_UINT32_INPUTS(i) {
+    buffer[0] = *i;
+
+    CHECK_EQ((*i & 0xff), m.Call());
+    CHECK_EQ((*i & 0xff), buffer[1]);
+    CHECK_EQ((*i & 0xffff), buffer[2]);
+    CHECK_EQ(*i, buffer[3]);
+  }
+}
+
+#if V8_TARGET_ARCH_64_BIT
+TEST(RunCheckedLoadInt64) {
+  int64_t buffer[] = {0x66bbccddeeff0011LL, 0x1122334455667788LL};
+  RawMachineAssemblerTester<int64_t> m(MachineType::Int32());
+  Node* base = m.PointerConstant(buffer);
+  Node* index = m.Parameter(0);
+  Node* length = m.Int32Constant(16);
+  Node* load = m.AddNode(m.machine()->CheckedLoad(MachineType::Int64()), base,
+                         index, length);
+  m.Return(load);
+
+  CHECK_EQ(buffer[0], m.Call(0));
+  CHECK_EQ(buffer[1], m.Call(8));
+  CheckOobValue(m.Call(16));
+}
+
+TEST(RunLoadStoreSignExtend64) {
+  if (true) return;  // TODO(titzer): sign extension of loads to 64-bit.
+  int64_t buffer[5];
+  RawMachineAssemblerTester<int64_t> m;
+  Node* load8 = m.LoadFromPointer(LSB(&buffer[0], 1), MachineType::Int8());
+  Node* load16 = m.LoadFromPointer(LSB(&buffer[0], 2), MachineType::Int16());
+  Node* load32 = m.LoadFromPointer(LSB(&buffer[0], 4), MachineType::Int32());
+  Node* load64 = m.LoadFromPointer(&buffer[0], MachineType::Int64());
+  m.StoreToPointer(&buffer[1], MachineRepresentation::kWord64, load8);
+  m.StoreToPointer(&buffer[2], MachineRepresentation::kWord64, load16);
+  m.StoreToPointer(&buffer[3], MachineRepresentation::kWord64, load32);
+  m.StoreToPointer(&buffer[4], MachineRepresentation::kWord64, load64);
+  m.Return(load8);
+
+  FOR_INT64_INPUTS(i) {
+    buffer[0] = *i;
+
+    CHECK_EQ(static_cast<int8_t>(*i & 0xff), m.Call());
+    CHECK_EQ(static_cast<int8_t>(*i & 0xff), buffer[1]);
+    CHECK_EQ(static_cast<int16_t>(*i & 0xffff), buffer[2]);
+    CHECK_EQ(static_cast<int32_t>(*i & 0xffffffff), buffer[3]);
+    CHECK_EQ(*i, buffer[4]);
+  }
+}
+
+TEST(RunLoadStoreZeroExtend64) {
+  if (kPointerSize < 8) return;
+  uint64_t buffer[5];
+  RawMachineAssemblerTester<int64_t> m;
+  Node* load8 = m.LoadFromPointer(LSB(&buffer[0], 1), MachineType::Uint8());
+  Node* load16 = m.LoadFromPointer(LSB(&buffer[0], 2), MachineType::Uint16());
+  Node* load32 = m.LoadFromPointer(LSB(&buffer[0], 4), MachineType::Uint32());
+  Node* load64 = m.LoadFromPointer(&buffer[0], MachineType::Uint64());
+  m.StoreToPointer(&buffer[1], MachineRepresentation::kWord64, load8);
+  m.StoreToPointer(&buffer[2], MachineRepresentation::kWord64, load16);
+  m.StoreToPointer(&buffer[3], MachineRepresentation::kWord64, load32);
+  m.StoreToPointer(&buffer[4], MachineRepresentation::kWord64, load64);
+  m.Return(load8);
+
+  FOR_UINT64_INPUTS(i) {
+    buffer[0] = *i;
+
+    CHECK_EQ((*i & 0xff), m.Call());
+    CHECK_EQ((*i & 0xff), buffer[1]);
+    CHECK_EQ((*i & 0xffff), buffer[2]);
+    CHECK_EQ((*i & 0xffffffff), buffer[3]);
+    CHECK_EQ(*i, buffer[4]);
+  }
+}
+
+TEST(RunCheckedStoreInt64) {
+  const int64_t write = 0x5566778899aabbLL;
+  const int64_t before = 0x33bbccddeeff0011LL;
+  int64_t buffer[] = {before, before};
+  RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
+  Node* base = m.PointerConstant(buffer);
+  Node* index = m.Parameter(0);
+  Node* length = m.Int32Constant(16);
+  Node* value = m.Int64Constant(write);
+  Node* store =
+      m.AddNode(m.machine()->CheckedStore(MachineRepresentation::kWord64), base,
+                index, length, value);
+  USE(store);
+  m.Return(m.Int32Constant(11));
+
+  CHECK_EQ(11, m.Call(16));
+  CHECK_EQ(before, buffer[0]);
+  CHECK_EQ(before, buffer[1]);
+
+  CHECK_EQ(11, m.Call(0));
+  CHECK_EQ(write, buffer[0]);
+  CHECK_EQ(before, buffer[1]);
+
+  CHECK_EQ(11, m.Call(8));
+  CHECK_EQ(write, buffer[0]);
+  CHECK_EQ(write, buffer[1]);
+}
+#endif
+
+namespace {
+template <typename IntType>
+void LoadStoreTruncation(MachineType kRepresentation) {
+  IntType input;
+
+  RawMachineAssemblerTester<int32_t> m;
+  Node* a = m.LoadFromPointer(&input, kRepresentation);
+  Node* ap1 = m.Int32Add(a, m.Int32Constant(1));
+  m.StoreToPointer(&input, kRepresentation.representation(), ap1);
+  m.Return(ap1);
+
+  const IntType max = std::numeric_limits<IntType>::max();
+  const IntType min = std::numeric_limits<IntType>::min();
+
+  // Test upper bound.
+  input = max;
+  CHECK_EQ(max + 1, m.Call());
+  CHECK_EQ(min, input);
+
+  // Test lower bound.
+  input = min;
+  CHECK_EQ(static_cast<IntType>(max + 2), m.Call());
+  CHECK_EQ(min + 1, input);
+
+  // Test all one byte values that are not one byte bounds.
+  for (int i = -127; i < 127; i++) {
+    input = i;
+    int expected = i >= 0 ? i + 1 : max + (i - min) + 2;
+    CHECK_EQ(static_cast<IntType>(expected), m.Call());
+    CHECK_EQ(static_cast<IntType>(i + 1), input);
+  }
+}
+}  // namespace
+
+TEST(RunLoadStoreTruncation) {
+  LoadStoreTruncation<int8_t>(MachineType::Int8());
+  LoadStoreTruncation<int16_t>(MachineType::Int16());
+}
+
+void TestRunOobCheckedLoad(bool length_is_immediate) {
+  USE(CheckOobValue<int32_t>);
+  USE(CheckOobValue<int64_t>);
+  USE(CheckOobValue<float>);
+  USE(CheckOobValue<double>);
+
+  RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
+                                       MachineType::Int32());
+  MachineOperatorBuilder machine(m.zone());
+  const int32_t kNumElems = 27;
+  const int32_t kLength = kNumElems * 4;
+
+  int32_t buffer[kNumElems];
+  Node* base = m.PointerConstant(buffer);
+  Node* offset = m.Parameter(0);
+  Node* len = length_is_immediate ? m.Int32Constant(kLength) : m.Parameter(1);
+  Node* node =
+      m.AddNode(machine.CheckedLoad(MachineType::Int32()), base, offset, len);
+  m.Return(node);
+
+  {
+    // randomize memory.
+    v8::base::RandomNumberGenerator rng;
+    rng.SetSeed(100);
+    rng.NextBytes(&buffer[0], sizeof(buffer));
+  }
+
+  // in-bounds accesses.
+  for (int32_t i = 0; i < kNumElems; i++) {
+    int32_t offset = static_cast<int32_t>(i * sizeof(int32_t));
+    int32_t expected = buffer[i];
+    CHECK_EQ(expected, m.Call(offset, kLength));
+  }
+
+  // slightly out-of-bounds accesses.
+  for (int32_t i = kLength; i < kNumElems + 30; i++) {
+    int32_t offset = static_cast<int32_t>(i * sizeof(int32_t));
+    CheckOobValue(m.Call(offset, kLength));
+  }
+
+  // way out-of-bounds accesses.
+  for (int32_t offset = -2000000000; offset <= 2000000000;
+       offset += 100000000) {
+    if (offset == 0) continue;
+    CheckOobValue(m.Call(offset, kLength));
+  }
+}
+
+TEST(RunOobCheckedLoad) { TestRunOobCheckedLoad(false); }
+
+TEST(RunOobCheckedLoadImm) { TestRunOobCheckedLoad(true); }
+
+void TestRunOobCheckedStore(bool length_is_immediate) {
+  RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
+                                       MachineType::Int32());
+  MachineOperatorBuilder machine(m.zone());
+  const int32_t kNumElems = 29;
+  const int32_t kValue = -78227234;
+  const int32_t kLength = kNumElems * 4;
+
+  int32_t buffer[kNumElems + kNumElems];
+  Node* base = m.PointerConstant(buffer);
+  Node* offset = m.Parameter(0);
+  Node* len = length_is_immediate ? m.Int32Constant(kLength) : m.Parameter(1);
+  Node* val = m.Int32Constant(kValue);
+  m.AddNode(machine.CheckedStore(MachineRepresentation::kWord32), base, offset,
+            len, val);
+  m.Return(val);
+
+  // in-bounds accesses.
+  for (int32_t i = 0; i < kNumElems; i++) {
+    memset(buffer, 0, sizeof(buffer));
+    int32_t offset = static_cast<int32_t>(i * sizeof(int32_t));
+    CHECK_EQ(kValue, m.Call(offset, kLength));
+    for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
+      if (i == j) {
+        CHECK_EQ(kValue, buffer[j]);
+      } else {
+        CHECK_EQ(0, buffer[j]);
+      }
+    }
+  }
+
+  memset(buffer, 0, sizeof(buffer));
+
+  // slightly out-of-bounds accesses.
+  for (int32_t i = kLength; i < kNumElems + 30; i++) {
+    int32_t offset = static_cast<int32_t>(i * sizeof(int32_t));
+    CHECK_EQ(kValue, m.Call(offset, kLength));
+    for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
+      CHECK_EQ(0, buffer[j]);
+    }
+  }
+
+  // way out-of-bounds accesses.
+  for (int32_t offset = -2000000000; offset <= 2000000000;
+       offset += 100000000) {
+    if (offset == 0) continue;
+    CHECK_EQ(kValue, m.Call(offset, kLength));
+    for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
+      CHECK_EQ(0, buffer[j]);
+    }
+  }
+}
+
+TEST(RunOobCheckedStore) { TestRunOobCheckedStore(false); }
+
+TEST(RunOobCheckedStoreImm) { TestRunOobCheckedStore(true); }
+
+// TODO(titzer): CheckedLoad/CheckedStore don't support 64-bit offsets.
+#define ALLOW_64_BIT_OFFSETS 0
+
+#if V8_TARGET_ARCH_64_BIT && ALLOW_64_BIT_OFFSETS
+
+void TestRunOobCheckedLoad64(uint32_t pseudo_base, bool length_is_immediate) {
+  RawMachineAssemblerTester<int32_t> m(MachineType::Uint64(),
+                                       MachineType::Uint64());
+  MachineOperatorBuilder machine(m.zone());
+  const uint32_t kNumElems = 25;
+  const uint32_t kLength = kNumElems * 4;
+  int32_t real_buffer[kNumElems];
+
+  // Simulate the end of a large buffer.
+  int32_t* buffer = real_buffer - (pseudo_base / 4);
+  uint64_t length = kLength + pseudo_base;
+
+  Node* base = m.PointerConstant(buffer);
+  Node* offset = m.Parameter(0);
+  Node* len = length_is_immediate ? m.Int64Constant(length) : m.Parameter(1);
+  Node* node =
+      m.AddNode(machine.CheckedLoad(MachineType::Int32()), base, offset, len);
+  m.Return(node);
+
+  {
+    // randomize memory.
+    v8::base::RandomNumberGenerator rng;
+    rng.SetSeed(100);
+    rng.NextBytes(&real_buffer[0], sizeof(real_buffer));
+  }
+
+  // in-bounds accesses.
+  for (uint32_t i = 0; i < kNumElems; i++) {
+    uint64_t offset = pseudo_base + i * 4;
+    int32_t expected = real_buffer[i];
+    CHECK_EQ(expected, m.Call(offset, length));
+  }
+
+  // in-bounds accesses w.r.t lower 32-bits, but upper bits set.
+  for (uint64_t i = 0x100000000ULL; i != 0; i <<= 1) {
+    uint64_t offset = pseudo_base + i;
+    CheckOobValue(m.Call(offset, length));
+  }
+
+  // slightly out-of-bounds accesses.
+  for (uint32_t i = kLength; i < kNumElems + 30; i++) {
+    uint64_t offset = pseudo_base + i * 4;
+    CheckOobValue(0, m.Call(offset, length));
+  }
+
+  // way out-of-bounds accesses.
+  for (uint64_t offset = length; offset < 100 * A_BILLION; offset += A_GIG) {
+    if (offset < length) continue;
+    CheckOobValue(0, m.Call(offset, length));
+  }
+}
+
+TEST(RunOobCheckedLoad64_0) {
+  TestRunOobCheckedLoad64(0, false);
+  TestRunOobCheckedLoad64(0, true);
+}
+
+TEST(RunOobCheckedLoad64_1) {
+  TestRunOobCheckedLoad64(1 * A_BILLION, false);
+  TestRunOobCheckedLoad64(1 * A_BILLION, true);
+}
+
+TEST(RunOobCheckedLoad64_2) {
+  TestRunOobCheckedLoad64(2 * A_BILLION, false);
+  TestRunOobCheckedLoad64(2 * A_BILLION, true);
+}
+
+TEST(RunOobCheckedLoad64_3) {
+  TestRunOobCheckedLoad64(3 * A_BILLION, false);
+  TestRunOobCheckedLoad64(3 * A_BILLION, true);
+}
+
+TEST(RunOobCheckedLoad64_4) {
+  TestRunOobCheckedLoad64(4 * A_BILLION, false);
+  TestRunOobCheckedLoad64(4 * A_BILLION, true);
+}
+
+void TestRunOobCheckedStore64(uint32_t pseudo_base, bool length_is_immediate) {
+  RawMachineAssemblerTester<int32_t> m(MachineType::Uint64(),
+                                       MachineType::Uint64());
+  MachineOperatorBuilder machine(m.zone());
+  const uint32_t kNumElems = 21;
+  const uint32_t kLength = kNumElems * 4;
+  const uint32_t kValue = 897234987;
+  int32_t real_buffer[kNumElems + kNumElems];
+
+  // Simulate the end of a large buffer.
+  int32_t* buffer = real_buffer - (pseudo_base / 4);
+  uint64_t length = kLength + pseudo_base;
+
+  Node* base = m.PointerConstant(buffer);
+  Node* offset = m.Parameter(0);
+  Node* len = length_is_immediate ? m.Int64Constant(length) : m.Parameter(1);
+  Node* val = m.Int32Constant(kValue);
+  m.AddNode(machine.CheckedStore(MachineRepresentation::kWord32), base, offset,
+            len, val);
+  m.Return(val);
+
+  // in-bounds accesses.
+  for (uint32_t i = 0; i < kNumElems; i++) {
+    memset(real_buffer, 0, sizeof(real_buffer));
+    uint64_t offset = pseudo_base + i * 4;
+    CHECK_EQ(kValue, m.Call(offset, length));
+    for (uint32_t j = 0; j < kNumElems + kNumElems; j++) {
+      if (i == j) {
+        CHECK_EQ(kValue, real_buffer[j]);
+      } else {
+        CHECK_EQ(0, real_buffer[j]);
+      }
+    }
+  }
+
+  memset(real_buffer, 0, sizeof(real_buffer));
+
+  // in-bounds accesses w.r.t lower 32-bits, but upper bits set.
+  for (uint64_t i = 0x100000000ULL; i != 0; i <<= 1) {
+    uint64_t offset = pseudo_base + i;
+    CHECK_EQ(kValue, m.Call(offset, length));
+    for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
+      CHECK_EQ(0, real_buffer[j]);
+    }
+  }
+
+  // slightly out-of-bounds accesses.
+  for (uint32_t i = kLength; i < kNumElems + 30; i++) {
+    uint64_t offset = pseudo_base + i * 4;
+    CHECK_EQ(kValue, m.Call(offset, length));
+    for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
+      CHECK_EQ(0, real_buffer[j]);
+    }
+  }
+
+  // way out-of-bounds accesses.
+  for (uint64_t offset = length; offset < 100 * A_BILLION; offset += A_GIG) {
+    if (offset < length) continue;
+    CHECK_EQ(kValue, m.Call(offset, length));
+    for (int32_t j = 0; j < kNumElems + kNumElems; j++) {
+      CHECK_EQ(0, real_buffer[j]);
+    }
+  }
+}
+
+TEST(RunOobCheckedStore64_0) {
+  TestRunOobCheckedStore64(0, false);
+  TestRunOobCheckedStore64(0, true);
+}
+
+TEST(RunOobCheckedStore64_1) {
+  TestRunOobCheckedStore64(1 * A_BILLION, false);
+  TestRunOobCheckedStore64(1 * A_BILLION, true);
+}
+
+TEST(RunOobCheckedStore64_2) {
+  TestRunOobCheckedStore64(2 * A_BILLION, false);
+  TestRunOobCheckedStore64(2 * A_BILLION, true);
+}
+
+TEST(RunOobCheckedStore64_3) {
+  TestRunOobCheckedStore64(3 * A_BILLION, false);
+  TestRunOobCheckedStore64(3 * A_BILLION, true);
+}
+
+TEST(RunOobCheckedStore64_4) {
+  TestRunOobCheckedStore64(4 * A_BILLION, false);
+  TestRunOobCheckedStore64(4 * A_BILLION, true);
+}
+
+#endif
+
+void TestRunOobCheckedLoad_pseudo(uint64_t x, bool length_is_immediate) {
+  RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
+                                       MachineType::Uint32());
+
+  uint32_t pseudo_base = static_cast<uint32_t>(x);
+  MachineOperatorBuilder machine(m.zone());
+  const uint32_t kNumElems = 29;
+  const uint32_t kLength = pseudo_base + kNumElems * 4;
+
+  int32_t buffer[kNumElems];
+  Node* base = m.PointerConstant(reinterpret_cast<byte*>(buffer) - pseudo_base);
+  Node* offset = m.Parameter(0);
+  Node* len = length_is_immediate ? m.Int32Constant(kLength) : m.Parameter(1);
+  Node* node =
+      m.AddNode(machine.CheckedLoad(MachineType::Int32()), base, offset, len);
+  m.Return(node);
+
+  {
+    // randomize memory.
+    v8::base::RandomNumberGenerator rng;
+    rng.SetSeed(100);
+    rng.NextBytes(&buffer[0], sizeof(buffer));
+  }
+
+  // in-bounds accesses.
+  for (uint32_t i = 0; i < kNumElems; i++) {
+    uint32_t offset = static_cast<uint32_t>(i * sizeof(int32_t));
+    uint32_t expected = buffer[i];
+    CHECK_EQ(expected, m.Call(offset + pseudo_base, kLength));
+  }
+
+  // slightly out-of-bounds accesses.
+  for (int32_t i = kNumElems; i < kNumElems + 30; i++) {
+    uint32_t offset = static_cast<uint32_t>(i * sizeof(int32_t));
+    CheckOobValue(m.Call(offset + pseudo_base, kLength));
+  }
+
+  // way out-of-bounds accesses.
+  for (uint64_t i = pseudo_base + sizeof(buffer); i < 0xFFFFFFFF;
+       i += A_BILLION) {
+    uint32_t offset = static_cast<uint32_t>(i);
+    CheckOobValue(m.Call(offset, kLength));
+  }
+}
+
+TEST(RunOobCheckedLoad_pseudo0) {
+  TestRunOobCheckedLoad_pseudo(0, false);
+  TestRunOobCheckedLoad_pseudo(0, true);
+}
+
+TEST(RunOobCheckedLoad_pseudo1) {
+  TestRunOobCheckedLoad_pseudo(100000, false);
+  TestRunOobCheckedLoad_pseudo(100000, true);
+}
+
+TEST(RunOobCheckedLoad_pseudo2) {
+  TestRunOobCheckedLoad_pseudo(A_BILLION, false);
+  TestRunOobCheckedLoad_pseudo(A_BILLION, true);
+}
+
+TEST(RunOobCheckedLoad_pseudo3) {
+  TestRunOobCheckedLoad_pseudo(A_GIG, false);
+  TestRunOobCheckedLoad_pseudo(A_GIG, true);
+}
+
+TEST(RunOobCheckedLoad_pseudo4) {
+  TestRunOobCheckedLoad_pseudo(2 * A_BILLION, false);
+  TestRunOobCheckedLoad_pseudo(2 * A_BILLION, true);
+}
+
+TEST(RunOobCheckedLoad_pseudo5) {
+  TestRunOobCheckedLoad_pseudo(2 * A_GIG, false);
+  TestRunOobCheckedLoad_pseudo(2 * A_GIG, true);
+}
+
+TEST(RunOobCheckedLoad_pseudo6) {
+  TestRunOobCheckedLoad_pseudo(3 * A_BILLION, false);
+  TestRunOobCheckedLoad_pseudo(3 * A_BILLION, true);
+}
+
+TEST(RunOobCheckedLoad_pseudo7) {
+  TestRunOobCheckedLoad_pseudo(3 * A_GIG, false);
+  TestRunOobCheckedLoad_pseudo(3 * A_GIG, true);
+}
+
+TEST(RunOobCheckedLoad_pseudo8) {
+  TestRunOobCheckedLoad_pseudo(4 * A_BILLION, false);
+  TestRunOobCheckedLoad_pseudo(4 * A_BILLION, true);
+}
+
+template <typename MemType>
+void TestRunOobCheckedLoadT_pseudo(uint64_t x, bool length_is_immediate) {
+  const int32_t kReturn = 11999;
+  const uint32_t kNumElems = 29;
+  MemType buffer[kNumElems];
+  uint32_t pseudo_base = static_cast<uint32_t>(x);
+  const uint32_t kLength = static_cast<uint32_t>(pseudo_base + sizeof(buffer));
+
+  MemType result;
+
+  RawMachineAssemblerTester<int32_t> m(MachineType::Uint32(),
+                                       MachineType::Uint32());
+  MachineOperatorBuilder machine(m.zone());
+  Node* base = m.PointerConstant(reinterpret_cast<byte*>(buffer) - pseudo_base);
+  Node* offset = m.Parameter(0);
+  Node* len = length_is_immediate ? m.Int32Constant(kLength) : m.Parameter(1);
+  Node* node = m.AddNode(machine.CheckedLoad(MachineTypeForC<MemType>()), base,
+                         offset, len);
+  Node* store = m.StoreToPointer(
+      &result, MachineTypeForC<MemType>().representation(), node);
+  USE(store);
+  m.Return(m.Int32Constant(kReturn));
+
+  {
+    // randomize memory.
+    v8::base::RandomNumberGenerator rng;
+    rng.SetSeed(103);
+    rng.NextBytes(&buffer[0], sizeof(buffer));
+  }
+
+  // in-bounds accesses.
+  for (uint32_t i = 0; i < kNumElems; i++) {
+    uint32_t offset = static_cast<uint32_t>(i * sizeof(MemType));
+    MemType expected = buffer[i];
+    CHECK_EQ(kReturn, m.Call(offset + pseudo_base, kLength));
+    CHECK_EQ(expected, result);
+  }
+
+  // slightly out-of-bounds accesses.
+  for (int32_t i = kNumElems; i < kNumElems + 30; i++) {
+    uint32_t offset = static_cast<uint32_t>(i * sizeof(MemType));
+    CHECK_EQ(kReturn, m.Call(offset + pseudo_base, kLength));
+    CheckOobValue(result);
+  }
+
+  // way out-of-bounds accesses.
+  for (uint64_t i = pseudo_base + sizeof(buffer); i < 0xFFFFFFFF;
+       i += A_BILLION) {
+    uint32_t offset = static_cast<uint32_t>(i);
+    CHECK_EQ(kReturn, m.Call(offset, kLength));
+    CheckOobValue(result);
+  }
+}
+
+TEST(RunOobCheckedLoadT_pseudo0) {
+  TestRunOobCheckedLoadT_pseudo<int32_t>(0, false);
+  TestRunOobCheckedLoadT_pseudo<int32_t>(0, true);
+  TestRunOobCheckedLoadT_pseudo<float>(0, false);
+  TestRunOobCheckedLoadT_pseudo<float>(0, true);
+  TestRunOobCheckedLoadT_pseudo<double>(0, false);
+  TestRunOobCheckedLoadT_pseudo<double>(0, true);
+}
+
+TEST(RunOobCheckedLoadT_pseudo1) {
+  TestRunOobCheckedLoadT_pseudo<int32_t>(100000, false);
+  TestRunOobCheckedLoadT_pseudo<int32_t>(100000, true);
+  TestRunOobCheckedLoadT_pseudo<float>(100000, false);
+  TestRunOobCheckedLoadT_pseudo<float>(100000, true);
+  TestRunOobCheckedLoadT_pseudo<double>(100000, false);
+  TestRunOobCheckedLoadT_pseudo<double>(100000, true);
+}
+
+TEST(RunOobCheckedLoadT_pseudo2) {
+  TestRunOobCheckedLoadT_pseudo<int32_t>(A_BILLION, false);
+  TestRunOobCheckedLoadT_pseudo<int32_t>(A_BILLION, true);
+  TestRunOobCheckedLoadT_pseudo<float>(A_BILLION, false);
+  TestRunOobCheckedLoadT_pseudo<float>(A_BILLION, true);
+  TestRunOobCheckedLoadT_pseudo<double>(A_BILLION, false);
+  TestRunOobCheckedLoadT_pseudo<double>(A_BILLION, true);
+}
+
+TEST(RunOobCheckedLoadT_pseudo3) {
+  TestRunOobCheckedLoadT_pseudo<int32_t>(A_GIG, false);
+  TestRunOobCheckedLoadT_pseudo<int32_t>(A_GIG, true);
+  TestRunOobCheckedLoadT_pseudo<float>(A_GIG, false);
+  TestRunOobCheckedLoadT_pseudo<float>(A_GIG, true);
+  TestRunOobCheckedLoadT_pseudo<double>(A_GIG, false);
+  TestRunOobCheckedLoadT_pseudo<double>(A_GIG, true);
+}
+
+TEST(RunOobCheckedLoadT_pseudo4) {
+  TestRunOobCheckedLoadT_pseudo<int32_t>(2 * A_BILLION, false);
+  TestRunOobCheckedLoadT_pseudo<int32_t>(2 * A_BILLION, true);
+  TestRunOobCheckedLoadT_pseudo<float>(2 * A_BILLION, false);
+  TestRunOobCheckedLoadT_pseudo<float>(2 * A_BILLION, true);
+  TestRunOobCheckedLoadT_pseudo<double>(2 * A_BILLION, false);
+  TestRunOobCheckedLoadT_pseudo<double>(2 * A_BILLION, true);
+}
+
+TEST(RunOobCheckedLoadT_pseudo5) {
+  TestRunOobCheckedLoadT_pseudo<int32_t>(2 * A_GIG, false);
+  TestRunOobCheckedLoadT_pseudo<int32_t>(2 * A_GIG, true);
+  TestRunOobCheckedLoadT_pseudo<float>(2 * A_GIG, false);
+  TestRunOobCheckedLoadT_pseudo<float>(2 * A_GIG, true);
+  TestRunOobCheckedLoadT_pseudo<double>(2 * A_GIG, false);
+  TestRunOobCheckedLoadT_pseudo<double>(2 * A_GIG, true);
+}
+
+TEST(RunOobCheckedLoadT_pseudo6) {
+  TestRunOobCheckedLoadT_pseudo<int32_t>(3 * A_BILLION, false);
+  TestRunOobCheckedLoadT_pseudo<int32_t>(3 * A_BILLION, true);
+  TestRunOobCheckedLoadT_pseudo<float>(3 * A_BILLION, false);
+  TestRunOobCheckedLoadT_pseudo<float>(3 * A_BILLION, true);
+  TestRunOobCheckedLoadT_pseudo<double>(3 * A_BILLION, false);
+  TestRunOobCheckedLoadT_pseudo<double>(3 * A_BILLION, true);
+}
+
+TEST(RunOobCheckedLoadT_pseudo7) {
+  TestRunOobCheckedLoadT_pseudo<int32_t>(3 * A_GIG, false);
+  TestRunOobCheckedLoadT_pseudo<int32_t>(3 * A_GIG, true);
+  TestRunOobCheckedLoadT_pseudo<float>(3 * A_GIG, false);
+  TestRunOobCheckedLoadT_pseudo<float>(3 * A_GIG, true);
+  TestRunOobCheckedLoadT_pseudo<double>(3 * A_GIG, false);
+  TestRunOobCheckedLoadT_pseudo<double>(3 * A_GIG, true);
+}
+
+TEST(RunOobCheckedLoadT_pseudo8) {
+  TestRunOobCheckedLoadT_pseudo<int32_t>(4 * A_BILLION, false);
+  TestRunOobCheckedLoadT_pseudo<int32_t>(4 * A_BILLION, true);
+  TestRunOobCheckedLoadT_pseudo<float>(4 * A_BILLION, false);
+  TestRunOobCheckedLoadT_pseudo<float>(4 * A_BILLION, true);
+  TestRunOobCheckedLoadT_pseudo<double>(4 * A_BILLION, false);
+  TestRunOobCheckedLoadT_pseudo<double>(4 * A_BILLION, true);
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/test/cctest/compiler/test-run-machops.cc b/test/cctest/compiler/test-run-machops.cc
index 2bfe124..685918a 100644
--- a/test/cctest/compiler/test-run-machops.cc
+++ b/test/cctest/compiler/test-run-machops.cc
@@ -7,6 +7,7 @@
 #include <limits>
 
 #include "src/base/bits.h"
+#include "src/base/ieee754.h"
 #include "src/base/utils/random-number-generator.h"
 #include "src/codegen.h"
 #include "test/cctest/cctest.h"
@@ -28,6 +29,39 @@
   CHECK_EQ(1, m.Call());
 }
 
+static int RunInt32AddShift(bool is_left, int32_t add_left, int32_t add_right,
+                            int32_t shift_left, int32_t shit_right) {
+  RawMachineAssemblerTester<int32_t> m;
+  Node* shift =
+      m.Word32Shl(m.Int32Constant(shift_left), m.Int32Constant(shit_right));
+  Node* add = m.Int32Add(m.Int32Constant(add_left), m.Int32Constant(add_right));
+  Node* lsa = is_left ? m.Int32Add(shift, add) : m.Int32Add(add, shift);
+  m.Return(lsa);
+  return m.Call();
+}
+
+TEST(RunInt32AddShift) {
+  struct Test_case {
+    int32_t add_left, add_right, shift_left, shit_right, expected;
+  };
+
+  Test_case tc[] = {
+      {20, 22, 4, 2, 58},
+      {20, 22, 4, 1, 50},
+      {20, 22, 1, 6, 106},
+      {INT_MAX - 2, 1, 1, 1, INT_MIN},  // INT_MAX - 2 + 1 + (1 << 1), overflow.
+  };
+  const size_t tc_size = sizeof(tc) / sizeof(Test_case);
+
+  for (size_t i = 0; i < tc_size; ++i) {
+    CHECK_EQ(tc[i].expected,
+             RunInt32AddShift(false, tc[i].add_left, tc[i].add_right,
+                              tc[i].shift_left, tc[i].shit_right));
+    CHECK_EQ(tc[i].expected,
+             RunInt32AddShift(true, tc[i].add_left, tc[i].add_right,
+                              tc[i].shift_left, tc[i].shit_right));
+  }
+}
 
 TEST(RunWord32ReverseBits) {
   BufferedRawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
@@ -636,6 +670,38 @@
   }
 }
 
+static int64_t RunInt64AddShift(bool is_left, int64_t add_left,
+                                int64_t add_right, int64_t shift_left,
+                                int64_t shit_right) {
+  RawMachineAssemblerTester<int64_t> m;
+  Node* shift = m.Word64Shl(m.Int64Constant(4), m.Int64Constant(2));
+  Node* add = m.Int64Add(m.Int64Constant(20), m.Int64Constant(22));
+  Node* dlsa = is_left ? m.Int64Add(shift, add) : m.Int64Add(add, shift);
+  m.Return(dlsa);
+  return m.Call();
+}
+
+TEST(RunInt64AddShift) {
+  struct Test_case {
+    int64_t add_left, add_right, shift_left, shit_right, expected;
+  };
+
+  Test_case tc[] = {
+      {20, 22, 4, 2, 58},
+      {20, 22, 4, 1, 50},
+      {20, 22, 1, 6, 106},
+      {INT64_MAX - 2, 1, 1, 1,
+       INT64_MIN},  // INT64_MAX - 2 + 1 + (1 << 1), overflow.
+  };
+  const size_t tc_size = sizeof(tc) / sizeof(Test_case);
+
+  for (size_t i = 0; i < tc_size; ++i) {
+    CHECK_EQ(58, RunInt64AddShift(false, tc[i].add_left, tc[i].add_right,
+                                  tc[i].shift_left, tc[i].shit_right));
+    CHECK_EQ(58, RunInt64AddShift(true, tc[i].add_left, tc[i].add_right,
+                                  tc[i].shift_left, tc[i].shit_right));
+  }
+}
 
 // TODO(titzer): add tests that run 64-bit integer operations.
 #endif  // V8_TARGET_ARCH_64_BIT
@@ -1142,94 +1208,6 @@
 }
 
 
-TEST(RunLoadInt32) {
-  RawMachineAssemblerTester<int32_t> m;
-
-  int32_t p1 = 0;  // loads directly from this location.
-  m.Return(m.LoadFromPointer(&p1, MachineType::Int32()));
-
-  FOR_INT32_INPUTS(i) {
-    p1 = *i;
-    CHECK_EQ(p1, m.Call());
-  }
-}
-
-
-TEST(RunLoadInt32Offset) {
-  int32_t p1 = 0;  // loads directly from this location.
-
-  int32_t offsets[] = {-2000000, -100, -101, 1,          3,
-                       7,        120,  2000, 2000000000, 0xff};
-
-  for (size_t i = 0; i < arraysize(offsets); i++) {
-    RawMachineAssemblerTester<int32_t> m;
-    int32_t offset = offsets[i];
-    byte* pointer = reinterpret_cast<byte*>(&p1) - offset;
-    // generate load [#base + #index]
-    m.Return(m.LoadFromPointer(pointer, MachineType::Int32(), offset));
-
-    FOR_INT32_INPUTS(j) {
-      p1 = *j;
-      CHECK_EQ(p1, m.Call());
-    }
-  }
-}
-
-
-TEST(RunLoadStoreFloat32Offset) {
-  float p1 = 0.0f;  // loads directly from this location.
-  float p2 = 0.0f;  // and stores directly into this location.
-
-  FOR_INT32_INPUTS(i) {
-    int32_t magic = 0x2342aabb + *i * 3;
-    RawMachineAssemblerTester<int32_t> m;
-    int32_t offset = *i;
-    byte* from = reinterpret_cast<byte*>(&p1) - offset;
-    byte* to = reinterpret_cast<byte*>(&p2) - offset;
-    // generate load [#base + #index]
-    Node* load = m.Load(MachineType::Float32(), m.PointerConstant(from),
-                        m.IntPtrConstant(offset));
-    m.Store(MachineRepresentation::kFloat32, m.PointerConstant(to),
-            m.IntPtrConstant(offset), load, kNoWriteBarrier);
-    m.Return(m.Int32Constant(magic));
-
-    FOR_FLOAT32_INPUTS(j) {
-      p1 = *j;
-      p2 = *j - 5;
-      CHECK_EQ(magic, m.Call());
-      CHECK_DOUBLE_EQ(p1, p2);
-    }
-  }
-}
-
-
-TEST(RunLoadStoreFloat64Offset) {
-  double p1 = 0;  // loads directly from this location.
-  double p2 = 0;  // and stores directly into this location.
-
-  FOR_INT32_INPUTS(i) {
-    int32_t magic = 0x2342aabb + *i * 3;
-    RawMachineAssemblerTester<int32_t> m;
-    int32_t offset = *i;
-    byte* from = reinterpret_cast<byte*>(&p1) - offset;
-    byte* to = reinterpret_cast<byte*>(&p2) - offset;
-    // generate load [#base + #index]
-    Node* load = m.Load(MachineType::Float64(), m.PointerConstant(from),
-                        m.IntPtrConstant(offset));
-    m.Store(MachineRepresentation::kFloat64, m.PointerConstant(to),
-            m.IntPtrConstant(offset), load, kNoWriteBarrier);
-    m.Return(m.Int32Constant(magic));
-
-    FOR_FLOAT64_INPUTS(j) {
-      p1 = *j;
-      p2 = *j - 5;
-      CHECK_EQ(magic, m.Call());
-      CHECK_DOUBLE_EQ(p1, p2);
-    }
-  }
-}
-
-
 TEST(RunInt32AddP) {
   RawMachineAssemblerTester<int32_t> m;
   Int32BinopTester bt(&m);
@@ -1709,7 +1687,6 @@
   }
 }
 
-
 TEST(RunInt32SubImm) {
   {
     FOR_UINT32_INPUTS(i) {
@@ -1733,6 +1710,11 @@
   }
 }
 
+TEST(RunInt32SubImm2) {
+  BufferedRawMachineAssemblerTester<int32_t> r;
+  r.Return(r.Int32Sub(r.Int32Constant(-1), r.Int32Constant(0)));
+  CHECK_EQ(-1, r.Call());
+}
 
 TEST(RunInt32SubAndWord32SarP) {
   {
@@ -3566,92 +3548,6 @@
 }
 
 
-template <typename Type>
-static void RunLoadImmIndex(MachineType rep) {
-  const int kNumElems = 3;
-  Type buffer[kNumElems];
-
-  // initialize the buffer with some raw data.
-  byte* raw = reinterpret_cast<byte*>(buffer);
-  for (size_t i = 0; i < sizeof(buffer); i++) {
-    raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA);
-  }
-
-  // Test with various large and small offsets.
-  for (int offset = -1; offset <= 200000; offset *= -5) {
-    for (int i = 0; i < kNumElems; i++) {
-      BufferedRawMachineAssemblerTester<Type> m;
-      Node* base = m.PointerConstant(buffer - offset);
-      Node* index = m.Int32Constant((offset + i) * sizeof(buffer[0]));
-      m.Return(m.Load(rep, base, index));
-
-      volatile Type expected = buffer[i];
-      volatile Type actual = m.Call();
-      CHECK_EQ(expected, actual);
-    }
-  }
-}
-
-
-TEST(RunLoadImmIndex) {
-  RunLoadImmIndex<int8_t>(MachineType::Int8());
-  RunLoadImmIndex<uint8_t>(MachineType::Uint8());
-  RunLoadImmIndex<int16_t>(MachineType::Int16());
-  RunLoadImmIndex<uint16_t>(MachineType::Uint16());
-  RunLoadImmIndex<int32_t>(MachineType::Int32());
-  RunLoadImmIndex<uint32_t>(MachineType::Uint32());
-  RunLoadImmIndex<int32_t*>(MachineType::AnyTagged());
-  RunLoadImmIndex<float>(MachineType::Float32());
-  RunLoadImmIndex<double>(MachineType::Float64());
-  if (kPointerSize == 8) {
-    RunLoadImmIndex<int64_t>(MachineType::Int64());
-  }
-  // TODO(titzer): test various indexing modes.
-}
-
-
-template <typename CType>
-static void RunLoadStore(MachineType rep) {
-  const int kNumElems = 4;
-  CType buffer[kNumElems];
-
-  for (int32_t x = 0; x < kNumElems; x++) {
-    int32_t y = kNumElems - x - 1;
-    // initialize the buffer with raw data.
-    byte* raw = reinterpret_cast<byte*>(buffer);
-    for (size_t i = 0; i < sizeof(buffer); i++) {
-      raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA);
-    }
-
-    RawMachineAssemblerTester<int32_t> m;
-    int32_t OK = 0x29000 + x;
-    Node* base = m.PointerConstant(buffer);
-    Node* index0 = m.IntPtrConstant(x * sizeof(buffer[0]));
-    Node* load = m.Load(rep, base, index0);
-    Node* index1 = m.IntPtrConstant(y * sizeof(buffer[0]));
-    m.Store(rep.representation(), base, index1, load, kNoWriteBarrier);
-    m.Return(m.Int32Constant(OK));
-
-    CHECK(buffer[x] != buffer[y]);
-    CHECK_EQ(OK, m.Call());
-    CHECK(buffer[x] == buffer[y]);
-  }
-}
-
-
-TEST(RunLoadStore) {
-  RunLoadStore<int8_t>(MachineType::Int8());
-  RunLoadStore<uint8_t>(MachineType::Uint8());
-  RunLoadStore<int16_t>(MachineType::Int16());
-  RunLoadStore<uint16_t>(MachineType::Uint16());
-  RunLoadStore<int32_t>(MachineType::Int32());
-  RunLoadStore<uint32_t>(MachineType::Uint32());
-  RunLoadStore<void*>(MachineType::AnyTagged());
-  RunLoadStore<float>(MachineType::Float32());
-  RunLoadStore<double>(MachineType::Float64());
-}
-
-
 TEST(RunFloat32Add) {
   BufferedRawMachineAssemblerTester<float> m(MachineType::Float32(),
                                              MachineType::Float32());
@@ -3673,6 +3569,12 @@
   }
 }
 
+TEST(RunFloat32Neg) {
+  BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
+  if (!m.machine()->Float32Neg().IsSupported()) return;
+  m.Return(m.AddNode(m.machine()->Float32Neg().op(), m.Parameter(0)));
+  FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(-0.0f - *i, m.Call(*i)); }
+}
 
 TEST(RunFloat32Mul) {
   BufferedRawMachineAssemblerTester<float> m(MachineType::Float32(),
@@ -3717,6 +3619,12 @@
   }
 }
 
+TEST(RunFloat64Neg) {
+  BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+  if (!m.machine()->Float64Neg().IsSupported()) return;
+  m.Return(m.AddNode(m.machine()->Float64Neg().op(), m.Parameter(0)));
+  FOR_FLOAT64_INPUTS(i) { CHECK_FLOAT_EQ(-0.0 - *i, m.Call(*i)); }
+}
 
 TEST(RunFloat64Mul) {
   BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
@@ -4124,7 +4032,7 @@
   m.Return(m.TruncateFloat32ToUint32(m.Parameter(0)));
   {
     FOR_UINT32_INPUTS(i) {
-      float input = static_cast<float>(*i);
+      volatile float input = static_cast<float>(*i);
       // This condition on 'input' is required because
       // static_cast<float>(std::numeric_limits<uint32_t>::max()) results in a
       // value outside uint32 range.
@@ -4201,7 +4109,7 @@
   return (static_cast<uint64_t>(high) << 32) | static_cast<uint64_t>(low);
 }
 
-#if V8_TARGET_ARCH_32_BIT && !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_X87
+#if V8_TARGET_ARCH_32_BIT && !V8_TARGET_ARCH_X87
 TEST(RunInt32PairAdd) {
   BufferedRawMachineAssemblerTester<int32_t> m(
       MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32(),
@@ -4449,6 +4357,56 @@
   TestWord32PairShlWithSharedInput(1, 1);
 }
 
+TEST(RunWord32PairShr) {
+  BufferedRawMachineAssemblerTester<int32_t> m(
+      MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
+
+  uint32_t high;
+  uint32_t low;
+
+  Node* PairAdd =
+      m.Word32PairShr(m.Parameter(0), m.Parameter(1), m.Parameter(2));
+
+  m.StoreToPointer(&low, MachineRepresentation::kWord32,
+                   m.Projection(0, PairAdd));
+  m.StoreToPointer(&high, MachineRepresentation::kWord32,
+                   m.Projection(1, PairAdd));
+  m.Return(m.Int32Constant(74));
+
+  FOR_UINT64_INPUTS(i) {
+    for (uint32_t j = 0; j < 64; j++) {
+      m.Call(static_cast<uint32_t>(*i & 0xffffffff),
+             static_cast<uint32_t>(*i >> 32), j);
+      CHECK_EQ(*i >> j, ToInt64(low, high));
+    }
+  }
+}
+
+TEST(RunWord32PairSar) {
+  BufferedRawMachineAssemblerTester<int32_t> m(
+      MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
+
+  uint32_t high;
+  uint32_t low;
+
+  Node* PairAdd =
+      m.Word32PairSar(m.Parameter(0), m.Parameter(1), m.Parameter(2));
+
+  m.StoreToPointer(&low, MachineRepresentation::kWord32,
+                   m.Projection(0, PairAdd));
+  m.StoreToPointer(&high, MachineRepresentation::kWord32,
+                   m.Projection(1, PairAdd));
+  m.Return(m.Int32Constant(74));
+
+  FOR_INT64_INPUTS(i) {
+    for (uint32_t j = 0; j < 64; j++) {
+      m.Call(static_cast<uint32_t>(*i & 0xffffffff),
+             static_cast<uint32_t>(*i >> 32), j);
+      CHECK_EQ(*i >> j, ToInt64(low, high));
+    }
+  }
+}
+
 #endif
 
 TEST(RunDeadChangeFloat64ToInt32) {
@@ -4968,45 +4926,6 @@
 }
 
 
-template <typename IntType>
-static void LoadStoreTruncation(MachineType kRepresentation) {
-  IntType input;
-
-  RawMachineAssemblerTester<int32_t> m;
-  Node* a = m.LoadFromPointer(&input, kRepresentation);
-  Node* ap1 = m.Int32Add(a, m.Int32Constant(1));
-  m.StoreToPointer(&input, kRepresentation.representation(), ap1);
-  m.Return(ap1);
-
-  const IntType max = std::numeric_limits<IntType>::max();
-  const IntType min = std::numeric_limits<IntType>::min();
-
-  // Test upper bound.
-  input = max;
-  CHECK_EQ(max + 1, m.Call());
-  CHECK_EQ(min, input);
-
-  // Test lower bound.
-  input = min;
-  CHECK_EQ(static_cast<IntType>(max + 2), m.Call());
-  CHECK_EQ(min + 1, input);
-
-  // Test all one byte values that are not one byte bounds.
-  for (int i = -127; i < 127; i++) {
-    input = i;
-    int expected = i >= 0 ? i + 1 : max + (i - min) + 2;
-    CHECK_EQ(static_cast<IntType>(expected), m.Call());
-    CHECK_EQ(static_cast<IntType>(i + 1), input);
-  }
-}
-
-
-TEST(RunLoadStoreTruncation) {
-  LoadStoreTruncation<int8_t>(MachineType::Int8());
-  LoadStoreTruncation<int16_t>(MachineType::Int16());
-}
-
-
 static void IntPtrCompare(intptr_t left, intptr_t right) {
   for (int test = 0; test < 7; test++) {
     RawMachineAssemblerTester<bool> m(MachineType::Pointer(),
@@ -5417,8 +5336,7 @@
   }
 }
 
-
-TEST(RunTruncateFloat64ToInt32P) {
+TEST(RunTruncateFloat64ToWord32P) {
   struct {
     double from;
     double raw;
@@ -5479,8 +5397,7 @@
                  {-1.7976931348623157e+308, 0}};
   double input = -1.0;
   RawMachineAssemblerTester<int32_t> m;
-  m.Return(m.TruncateFloat64ToInt32(
-      TruncationMode::kJavaScript,
+  m.Return(m.TruncateFloat64ToWord32(
       m.LoadFromPointer(&input, MachineType::Float64())));
   for (size_t i = 0; i < arraysize(kValues); ++i) {
     input = kValues[i].from;
@@ -5489,6 +5406,12 @@
   }
 }
 
+TEST(RunTruncateFloat64ToWord32SignExtension) {
+  BufferedRawMachineAssemblerTester<int32_t> r;
+  r.Return(r.Int32Sub(r.TruncateFloat64ToWord32(r.Float64Constant(-1.0)),
+                      r.Int32Constant(0)));
+  CHECK_EQ(-1, r.Call());
+}
 
 TEST(RunChangeFloat32ToFloat64) {
   BufferedRawMachineAssemblerTester<double> m(MachineType::Float32());
@@ -5573,6 +5496,156 @@
   FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(std::abs(*i), m.Call(*i)); }
 }
 
+TEST(RunFloat64Atan) {
+  BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+  m.Return(m.Float64Atan(m.Parameter(0)));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
+  CHECK_DOUBLE_EQ(-0.0, m.Call(-0.0));
+  CHECK_DOUBLE_EQ(0.0, m.Call(0.0));
+  FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::atan(*i), m.Call(*i)); }
+}
+
+TEST(RunFloat64Atan2) {
+  BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
+                                              MachineType::Float64());
+  m.Return(m.Float64Atan2(m.Parameter(0), m.Parameter(1)));
+  FOR_FLOAT64_INPUTS(i) {
+    FOR_FLOAT64_INPUTS(j) {
+      CHECK_DOUBLE_EQ(ieee754::atan2(*i, *j), m.Call(*i, *j));
+    }
+  }
+}
+
+TEST(RunFloat64Atanh) {
+  BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+  m.Return(m.Float64Atanh(m.Parameter(0)));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
+  CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(), m.Call(1.0));
+  CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(), m.Call(-1.0));
+  CHECK_DOUBLE_EQ(-0.0, m.Call(-0.0));
+  CHECK_DOUBLE_EQ(0.0, m.Call(0.0));
+  FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::atanh(*i), m.Call(*i)); }
+}
+
+TEST(RunFloat64Cos) {
+  BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+  m.Return(m.Float64Cos(m.Parameter(0)));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
+  FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::cos(*i), m.Call(*i)); }
+}
+
+TEST(RunFloat64Exp) {
+  BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+  m.Return(m.Float64Exp(m.Parameter(0)));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
+  CHECK_EQ(0.0, m.Call(-std::numeric_limits<double>::infinity()));
+  CHECK_DOUBLE_EQ(1.0, m.Call(-0.0));
+  CHECK_DOUBLE_EQ(1.0, m.Call(0.0));
+  CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(),
+                  m.Call(std::numeric_limits<double>::infinity()));
+  FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::exp(*i), m.Call(*i)); }
+}
+
+TEST(RunFloat64Expm1) {
+  BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+  m.Return(m.Float64Expm1(m.Parameter(0)));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
+  CHECK_EQ(-1.0, m.Call(-std::numeric_limits<double>::infinity()));
+  CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(),
+                  m.Call(std::numeric_limits<double>::infinity()));
+  FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::expm1(*i), m.Call(*i)); }
+}
+
+TEST(RunFloat64Log) {
+  BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+  m.Return(m.Float64Log(m.Parameter(0)));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
+  CHECK(std::isnan(m.Call(-std::numeric_limits<double>::infinity())));
+  CHECK(std::isnan(m.Call(-1.0)));
+  CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(), m.Call(-0.0));
+  CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(), m.Call(0.0));
+  CHECK_DOUBLE_EQ(0.0, m.Call(1.0));
+  CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(),
+                  m.Call(std::numeric_limits<double>::infinity()));
+  FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::log(*i), m.Call(*i)); }
+}
+
+TEST(RunFloat64Log1p) {
+  BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+  m.Return(m.Float64Log1p(m.Parameter(0)));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
+  CHECK(std::isnan(m.Call(-std::numeric_limits<double>::infinity())));
+  CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(), m.Call(-1.0));
+  CHECK_DOUBLE_EQ(0.0, m.Call(0.0));
+  CHECK_DOUBLE_EQ(-0.0, m.Call(-0.0));
+  CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(),
+                  m.Call(std::numeric_limits<double>::infinity()));
+  FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::log1p(*i), m.Call(*i)); }
+}
+
+TEST(RunFloat64Log2) {
+  BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+  m.Return(m.Float64Log2(m.Parameter(0)));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
+  CHECK(std::isnan(m.Call(-std::numeric_limits<double>::infinity())));
+  CHECK(std::isnan(m.Call(-1.0)));
+  CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(), m.Call(-0.0));
+  CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(), m.Call(0.0));
+  CHECK_DOUBLE_EQ(0.0, m.Call(1.0));
+  CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(),
+                  m.Call(std::numeric_limits<double>::infinity()));
+  FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::log2(*i), m.Call(*i)); }
+}
+
+TEST(RunFloat64Log10) {
+  BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+  m.Return(m.Float64Log10(m.Parameter(0)));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
+  CHECK(std::isnan(m.Call(-std::numeric_limits<double>::infinity())));
+  CHECK(std::isnan(m.Call(-1.0)));
+  CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(), m.Call(-0.0));
+  CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(), m.Call(0.0));
+  CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(),
+                  m.Call(std::numeric_limits<double>::infinity()));
+  FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::log10(*i), m.Call(*i)); }
+}
+
+TEST(RunFloat64Cbrt) {
+  BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+  m.Return(m.Float64Cbrt(m.Parameter(0)));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
+  CHECK_DOUBLE_EQ(std::numeric_limits<double>::infinity(),
+                  m.Call(std::numeric_limits<double>::infinity()));
+  CHECK_DOUBLE_EQ(-std::numeric_limits<double>::infinity(),
+                  m.Call(-std::numeric_limits<double>::infinity()));
+  FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::cbrt(*i), m.Call(*i)); }
+}
+
+TEST(RunFloat64Sin) {
+  BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+  m.Return(m.Float64Sin(m.Parameter(0)));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
+  FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::sin(*i), m.Call(*i)); }
+}
+
+TEST(RunFloat64Tan) {
+  BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+  m.Return(m.Float64Tan(m.Parameter(0)));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::quiet_NaN())));
+  CHECK(std::isnan(m.Call(std::numeric_limits<double>::signaling_NaN())));
+  FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ieee754::tan(*i), m.Call(*i)); }
+}
 
 static double two_30 = 1 << 30;             // 2^30 is a smi boundary.
 static double two_52 = two_30 * (1 << 22);  // 2^52 is a precision boundary.
@@ -5854,50 +5927,6 @@
 
 #if V8_TARGET_ARCH_64_BIT
 // TODO(titzer): run int64 tests on all platforms when supported.
-TEST(RunCheckedLoadInt64) {
-  int64_t buffer[] = {0x66bbccddeeff0011LL, 0x1122334455667788LL};
-  RawMachineAssemblerTester<int64_t> m(MachineType::Int32());
-  Node* base = m.PointerConstant(buffer);
-  Node* index = m.Parameter(0);
-  Node* length = m.Int32Constant(16);
-  Node* load = m.AddNode(m.machine()->CheckedLoad(MachineType::Int64()), base,
-                         index, length);
-  m.Return(load);
-
-  CHECK_EQ(buffer[0], m.Call(0));
-  CHECK_EQ(buffer[1], m.Call(8));
-  CHECK_EQ(0, m.Call(16));
-}
-
-
-TEST(RunCheckedStoreInt64) {
-  const int64_t write = 0x5566778899aabbLL;
-  const int64_t before = 0x33bbccddeeff0011LL;
-  int64_t buffer[] = {before, before};
-  RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
-  Node* base = m.PointerConstant(buffer);
-  Node* index = m.Parameter(0);
-  Node* length = m.Int32Constant(16);
-  Node* value = m.Int64Constant(write);
-  Node* store =
-      m.AddNode(m.machine()->CheckedStore(MachineRepresentation::kWord64), base,
-                index, length, value);
-  USE(store);
-  m.Return(m.Int32Constant(11));
-
-  CHECK_EQ(11, m.Call(16));
-  CHECK_EQ(before, buffer[0]);
-  CHECK_EQ(before, buffer[1]);
-
-  CHECK_EQ(11, m.Call(0));
-  CHECK_EQ(write, buffer[0]);
-  CHECK_EQ(before, buffer[1]);
-
-  CHECK_EQ(11, m.Call(8));
-  CHECK_EQ(write, buffer[0]);
-  CHECK_EQ(write, buffer[1]);
-}
-
 
 TEST(RunBitcastInt64ToFloat64) {
   int64_t input = 1;
diff --git a/test/cctest/compiler/test-run-native-calls.cc b/test/cctest/compiler/test-run-native-calls.cc
index bfdcc0e..9c67fd5 100644
--- a/test/cctest/compiler/test-run-native-calls.cc
+++ b/test/cctest/compiler/test-run-native-calls.cc
@@ -18,6 +18,8 @@
 namespace internal {
 namespace compiler {
 
+const auto GetRegConfig = RegisterConfiguration::Turbofan;
+
 namespace {
 typedef float float32;
 typedef double float64;
@@ -76,12 +78,8 @@
 class RegisterPairs : public Pairs {
  public:
   RegisterPairs()
-      : Pairs(
-            100,
-            RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-                ->num_allocatable_general_registers(),
-            RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-                ->allocatable_general_codes()) {}
+      : Pairs(100, GetRegConfig()->num_allocatable_general_registers(),
+              GetRegConfig()->allocatable_general_codes()) {}
 };
 
 
@@ -91,10 +89,14 @@
   Float32RegisterPairs()
       : Pairs(
             100,
-            RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-                ->num_allocatable_aliased_double_registers(),
-            RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-                ->allocatable_double_codes()) {}
+#if V8_TARGET_ARCH_ARM
+            // TODO(bbudge) Modify wasm linkage to allow use of all float regs.
+            GetRegConfig()->num_allocatable_double_registers() / 2 - 2,
+#else
+            GetRegConfig()->num_allocatable_double_registers(),
+#endif
+            GetRegConfig()->allocatable_double_codes()) {
+  }
 };
 
 
@@ -102,12 +104,8 @@
 class Float64RegisterPairs : public Pairs {
  public:
   Float64RegisterPairs()
-      : Pairs(
-            100,
-            RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-                ->num_allocatable_aliased_double_registers(),
-            RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-                ->allocatable_double_codes()) {}
+      : Pairs(100, GetRegConfig()->num_allocatable_double_registers(),
+              GetRegConfig()->allocatable_double_codes()) {}
 };
 
 
@@ -136,7 +134,12 @@
     if (IsFloatingPoint(type.representation())) {
       // Allocate a floating point register/stack location.
       if (fp_offset < fp_count) {
-        return LinkageLocation::ForRegister(fp_regs[fp_offset++]);
+        int code = fp_regs[fp_offset++];
+#if V8_TARGET_ARCH_ARM
+        // TODO(bbudge) Modify wasm linkage to allow use of all float regs.
+        if (type.representation() == MachineRepresentation::kFloat32) code *= 2;
+#endif
+        return LinkageLocation::ForRegister(code);
       } else {
         int offset = -1 - stack_offset;
         stack_offset += StackWords(type);
@@ -154,10 +157,7 @@
     }
   }
   int StackWords(MachineType type) {
-    // TODO(titzer): hack. float32 occupies 8 bytes on stack.
-    int size = IsFloatingPoint(type.representation())
-                   ? kDoubleSize
-                   : (1 << ElementSizeLog2Of(type.representation()));
+    int size = 1 << ElementSizeLog2Of(type.representation());
     return size <= kPointerSize ? 1 : size / kPointerSize;
   }
   void Reset() {
@@ -255,7 +255,7 @@
 Handle<Code> CompileGraph(const char* name, CallDescriptor* desc, Graph* graph,
                           Schedule* schedule = nullptr) {
   Isolate* isolate = CcTest::InitIsolateOnce();
-  CompilationInfo info("testing", isolate, graph->zone());
+  CompilationInfo info(ArrayVector("testing"), isolate, graph->zone());
   Handle<Code> code =
       Pipeline::GenerateCodeForTesting(&info, desc, graph, schedule);
   CHECK(!code.is_null());
@@ -636,15 +636,14 @@
 
 
 // Separate tests for parallelization.
-#define TEST_INT32_SUB_WITH_RET(x)                \
-  TEST(Run_Int32Sub_all_allocatable_pairs_##x) {  \
-    if (x < Register::kNumRegisters &&            \
-        Register::from_code(x).IsAllocatable()) { \
-      Test_RunInt32SubWithRet(x);                 \
-    }                                             \
+#define TEST_INT32_SUB_WITH_RET(x)                     \
+  TEST(Run_Int32Sub_all_allocatable_pairs_##x) {       \
+    if (x < Register::kNumRegisters &&                 \
+        GetRegConfig()->IsAllocatableGeneralCode(x)) { \
+      Test_RunInt32SubWithRet(x);                      \
+    }                                                  \
   }
 
-
 TEST_INT32_SUB_WITH_RET(0)
 TEST_INT32_SUB_WITH_RET(1)
 TEST_INT32_SUB_WITH_RET(2)
@@ -692,9 +691,7 @@
     base::AccountingAllocator allocator;
     Zone zone(&allocator);
     int parray[2];
-    int rarray[] = {
-        RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-            ->GetAllocatableGeneralCode(0)};
+    int rarray[] = {GetRegConfig()->GetAllocatableGeneralCode(0)};
     pairs.Next(&parray[0], &parray[1], false);
     Allocator params(parray, 2, nullptr, 0);
     Allocator rets(rarray, 1, nullptr, 0);
@@ -741,14 +738,12 @@
 static void Test_Int32_WeightedSum_of_size(int count) {
   Int32Signature sig(count);
   for (int p0 = 0; p0 < Register::kNumRegisters; p0++) {
-    if (Register::from_code(p0).IsAllocatable()) {
+    if (GetRegConfig()->IsAllocatableGeneralCode(p0)) {
       base::AccountingAllocator allocator;
       Zone zone(&allocator);
 
       int parray[] = {p0};
-      int rarray[] = {
-          RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-              ->GetAllocatableGeneralCode(0)};
+      int rarray[] = {GetRegConfig()->GetAllocatableGeneralCode(0)};
       Allocator params(parray, 1, nullptr, 0);
       Allocator rets(rarray, 1, nullptr, 0);
       RegisterConfig config(params, rets);
@@ -801,12 +796,8 @@
 
 template <int which>
 void Test_Int32_Select() {
-  int parray[] = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableGeneralCode(0)};
-  int rarray[] = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableGeneralCode(0)};
+  int parray[] = {GetRegConfig()->GetAllocatableGeneralCode(0)};
+  int rarray[] = {GetRegConfig()->GetAllocatableGeneralCode(0)};
   Allocator params(parray, 1, nullptr, 0);
   Allocator rets(rarray, 1, nullptr, 0);
   RegisterConfig config(params, rets);
@@ -843,14 +834,10 @@
 
 
 TEST(Int64Select_registers) {
-  if (RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->num_allocatable_general_registers() < 2)
-    return;
+  if (GetRegConfig()->num_allocatable_general_registers() < 2) return;
   if (kPointerSize < 8) return;  // TODO(titzer): int64 on 32-bit platforms
 
-  int rarray[] = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableGeneralCode(0)};
+  int rarray[] = {GetRegConfig()->GetAllocatableGeneralCode(0)};
   ArgsBuffer<int64_t>::Sig sig(2);
 
   RegisterPairs pairs;
@@ -871,14 +858,11 @@
 
 
 TEST(Float32Select_registers) {
-  if (RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->num_allocatable_double_registers() < 2) {
+  if (GetRegConfig()->num_allocatable_double_registers() < 2) {
     return;
   }
 
-  int rarray[] = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableDoubleCode(0)};
+  int rarray[] = {GetRegConfig()->GetAllocatableDoubleCode(0)};
   ArgsBuffer<float32>::Sig sig(2);
 
   Float32RegisterPairs pairs;
@@ -899,15 +883,9 @@
 
 
 TEST(Float64Select_registers) {
-  if (RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->num_allocatable_double_registers() < 2)
-    return;
-  if (RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->num_allocatable_general_registers() < 2)
-    return;
-  int rarray[] = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableDoubleCode(0)};
+  if (GetRegConfig()->num_allocatable_double_registers() < 2) return;
+  if (GetRegConfig()->num_allocatable_general_registers() < 2) return;
+  int rarray[] = {GetRegConfig()->GetAllocatableDoubleCode(0)};
   ArgsBuffer<float64>::Sig sig(2);
 
   Float64RegisterPairs pairs;
@@ -928,9 +906,7 @@
 
 
 TEST(Float32Select_stack_params_return_reg) {
-  int rarray[] = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableDoubleCode(0)};
+  int rarray[] = {GetRegConfig()->GetAllocatableDoubleCode(0)};
   Allocator params(nullptr, 0, nullptr, 0);
   Allocator rets(nullptr, 0, rarray, 1);
   RegisterConfig config(params, rets);
@@ -951,9 +927,7 @@
 
 
 TEST(Float64Select_stack_params_return_reg) {
-  int rarray[] = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableDoubleCode(0)};
+  int rarray[] = {GetRegConfig()->GetAllocatableDoubleCode(0)};
   Allocator params(nullptr, 0, nullptr, 0);
   Allocator rets(nullptr, 0, rarray, 1);
   RegisterConfig config(params, rets);
@@ -1006,9 +980,7 @@
 
 
 TEST(Float64StackParamsToStackParams) {
-  int rarray[] = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableDoubleCode(0)};
+  int rarray[] = {GetRegConfig()->GetAllocatableDoubleCode(0)};
   Allocator params(nullptr, 0, nullptr, 0);
   Allocator rets(nullptr, 0, rarray, 1);
 
@@ -1027,9 +999,7 @@
 
 
 void MixedParamTest(int start) {
-  if (RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->num_double_registers() < 2)
-    return;
+  if (GetRegConfig()->num_double_registers() < 2) return;
 
 // TODO(titzer): mix in 64-bit types on all platforms when supported.
 #if V8_TARGET_ARCH_32_BIT
@@ -1058,22 +1028,12 @@
   const int num_params = static_cast<int>(arraysize(types) - start);
 
   // Build call descriptor
-  int parray_gp[] = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableGeneralCode(0),
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableGeneralCode(1)};
-  int rarray_gp[] = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableGeneralCode(0)};
-  int parray_fp[] = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableDoubleCode(0),
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableDoubleCode(1)};
-  int rarray_fp[] = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableDoubleCode(0)};
+  int parray_gp[] = {GetRegConfig()->GetAllocatableGeneralCode(0),
+                     GetRegConfig()->GetAllocatableGeneralCode(1)};
+  int rarray_gp[] = {GetRegConfig()->GetAllocatableGeneralCode(0)};
+  int parray_fp[] = {GetRegConfig()->GetAllocatableDoubleCode(0),
+                     GetRegConfig()->GetAllocatableDoubleCode(1)};
+  int rarray_fp[] = {GetRegConfig()->GetAllocatableDoubleCode(0)};
   Allocator palloc(parray_gp, 2, parray_fp, 2);
   Allocator ralloc(rarray_gp, 1, rarray_fp, 1);
   RegisterConfig config(palloc, ralloc);
@@ -1174,29 +1134,17 @@
   // Test: Generate with a function f which reserves a stack slot, call an inner
   // function g from f which writes into the stack slot of f.
 
-  if (RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->num_allocatable_double_registers() < 2)
-    return;
+  if (GetRegConfig()->num_allocatable_double_registers() < 2) return;
 
   Isolate* isolate = CcTest::InitIsolateOnce();
 
   // Lots of code to generate the build descriptor for the inner function.
-  int parray_gp[] = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableGeneralCode(0),
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableGeneralCode(1)};
-  int rarray_gp[] = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableGeneralCode(0)};
-  int parray_fp[] = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableDoubleCode(0),
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableDoubleCode(1)};
-  int rarray_fp[] = {
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableDoubleCode(0)};
+  int parray_gp[] = {GetRegConfig()->GetAllocatableGeneralCode(0),
+                     GetRegConfig()->GetAllocatableGeneralCode(1)};
+  int rarray_gp[] = {GetRegConfig()->GetAllocatableGeneralCode(0)};
+  int parray_fp[] = {GetRegConfig()->GetAllocatableDoubleCode(0),
+                     GetRegConfig()->GetAllocatableDoubleCode(1)};
+  int rarray_fp[] = {GetRegConfig()->GetAllocatableDoubleCode(0)};
   Allocator palloc(parray_gp, 2, parray_fp, 2);
   Allocator ralloc(rarray_gp, 1, rarray_fp, 1);
   RegisterConfig config(palloc, ralloc);
diff --git a/test/cctest/compiler/test-run-stubs.cc b/test/cctest/compiler/test-run-stubs.cc
index c745219..feb25c9 100644
--- a/test/cctest/compiler/test-run-stubs.cc
+++ b/test/cctest/compiler/test-run-stubs.cc
@@ -27,7 +27,7 @@
   // Create code and an accompanying descriptor.
   StringLengthStub stub(isolate);
   Handle<Code> code = stub.GenerateCode();
-  CompilationInfo info("test", isolate, zone,
+  CompilationInfo info(ArrayVector("test"), isolate, zone,
                        Code::ComputeFlags(Code::HANDLER));
   CallInterfaceDescriptor interface_descriptor =
       stub.GetCallInterfaceDescriptor();
diff --git a/test/cctest/compiler/test-run-wasm-machops.cc b/test/cctest/compiler/test-run-wasm-machops.cc
new file mode 100644
index 0000000..0b23669
--- /dev/null
+++ b/test/cctest/compiler/test-run-wasm-machops.cc
@@ -0,0 +1,170 @@
+// Copyright 2016 the V8 project authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in the
+// LICENSE file.
+
+#include <cmath>
+#include <functional>
+#include <limits>
+
+#include "src/base/bits.h"
+#include "src/base/utils/random-number-generator.h"
+#include "src/codegen.h"
+#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/codegen-tester.h"
+#include "test/cctest/compiler/graph-builder-tester.h"
+#include "test/cctest/compiler/value-helper.h"
+
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+
+static void UpdateMemoryReferences(Handle<Code> code, Address old_base,
+                                   Address new_base, uint32_t old_size,
+                                   uint32_t new_size) {
+  Isolate* isolate = CcTest::i_isolate();
+  bool modified = false;
+  int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) |
+                  RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
+  for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
+    RelocInfo::Mode mode = it.rinfo()->rmode();
+    if (RelocInfo::IsWasmMemoryReference(mode) ||
+        RelocInfo::IsWasmMemorySizeReference(mode)) {
+      // Patch addresses with change in memory start address
+      it.rinfo()->update_wasm_memory_reference(old_base, new_base, old_size,
+                                               new_size);
+      modified = true;
+    }
+  }
+  if (modified) {
+    Assembler::FlushICache(isolate, code->instruction_start(),
+                           code->instruction_size());
+  }
+}
+
+template <typename CType>
+static void RunLoadStoreRelocation(MachineType rep) {
+  const int kNumElems = 2;
+  CType buffer[kNumElems];
+  CType new_buffer[kNumElems];
+  byte* raw = reinterpret_cast<byte*>(buffer);
+  byte* new_raw = reinterpret_cast<byte*>(new_buffer);
+  for (size_t i = 0; i < sizeof(buffer); i++) {
+    raw[i] = static_cast<byte>((i + sizeof(CType)) ^ 0xAA);
+    new_raw[i] = static_cast<byte>((i + sizeof(CType)) ^ 0xAA);
+  }
+  int32_t OK = 0x29000;
+  RawMachineAssemblerTester<uint32_t> m;
+  Node* base = m.RelocatableIntPtrConstant(reinterpret_cast<intptr_t>(raw),
+                                           RelocInfo::WASM_MEMORY_REFERENCE);
+  Node* base1 = m.RelocatableIntPtrConstant(
+      reinterpret_cast<intptr_t>(raw + sizeof(CType)),
+      RelocInfo::WASM_MEMORY_REFERENCE);
+  Node* index = m.Int32Constant(0);
+  Node* load = m.Load(rep, base, index);
+  m.Store(rep.representation(), base1, index, load, kNoWriteBarrier);
+  m.Return(m.Int32Constant(OK));
+  CHECK(buffer[0] != buffer[1]);
+  CHECK_EQ(OK, m.Call());
+  CHECK(buffer[0] == buffer[1]);
+  m.GenerateCode();
+  Handle<Code> code = m.GetCode();
+  UpdateMemoryReferences(code, raw, new_raw, sizeof(buffer),
+                         sizeof(new_buffer));
+  CHECK(new_buffer[0] != new_buffer[1]);
+  CHECK_EQ(OK, m.Call());
+  CHECK(new_buffer[0] == new_buffer[1]);
+}
+
+TEST(RunLoadStoreRelocation) {
+  RunLoadStoreRelocation<int8_t>(MachineType::Int8());
+  RunLoadStoreRelocation<uint8_t>(MachineType::Uint8());
+  RunLoadStoreRelocation<int16_t>(MachineType::Int16());
+  RunLoadStoreRelocation<uint16_t>(MachineType::Uint16());
+  RunLoadStoreRelocation<int32_t>(MachineType::Int32());
+  RunLoadStoreRelocation<uint32_t>(MachineType::Uint32());
+  RunLoadStoreRelocation<void*>(MachineType::AnyTagged());
+  RunLoadStoreRelocation<float>(MachineType::Float32());
+  RunLoadStoreRelocation<double>(MachineType::Float64());
+}
+
+template <typename CType>
+static void RunLoadStoreRelocationOffset(MachineType rep) {
+  RawMachineAssemblerTester<int32_t> r(MachineType::Int32());
+  const int kNumElems = 4;
+  CType buffer[kNumElems];
+  CType new_buffer[kNumElems + 1];
+
+  for (int32_t x = 0; x < kNumElems; x++) {
+    int32_t y = kNumElems - x - 1;
+    // initialize the buffer with raw data.
+    byte* raw = reinterpret_cast<byte*>(buffer);
+    for (size_t i = 0; i < sizeof(buffer); i++) {
+      raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA);
+    }
+
+    RawMachineAssemblerTester<int32_t> m;
+    int32_t OK = 0x29000 + x;
+    Node* base = m.RelocatableIntPtrConstant(reinterpret_cast<intptr_t>(buffer),
+                                             RelocInfo::WASM_MEMORY_REFERENCE);
+    Node* index0 = m.IntPtrConstant(x * sizeof(buffer[0]));
+    Node* load = m.Load(rep, base, index0);
+    Node* index1 = m.IntPtrConstant(y * sizeof(buffer[0]));
+    m.Store(rep.representation(), base, index1, load, kNoWriteBarrier);
+    m.Return(m.Int32Constant(OK));
+
+    CHECK(buffer[x] != buffer[y]);
+    CHECK_EQ(OK, m.Call());
+    CHECK(buffer[x] == buffer[y]);
+    m.GenerateCode();
+
+    // Initialize new buffer and set old_buffer to 0
+    byte* new_raw = reinterpret_cast<byte*>(new_buffer);
+    for (size_t i = 0; i < sizeof(buffer); i++) {
+      raw[i] = 0;
+      new_raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA);
+    }
+
+    // Perform relocation on generated code
+    Handle<Code> code = m.GetCode();
+    UpdateMemoryReferences(code, raw, new_raw, sizeof(buffer),
+                           sizeof(new_buffer));
+
+    CHECK(new_buffer[x] != new_buffer[y]);
+    CHECK_EQ(OK, m.Call());
+    CHECK(new_buffer[x] == new_buffer[y]);
+  }
+}
+
+TEST(RunLoadStoreRelocationOffset) {
+  RunLoadStoreRelocationOffset<int8_t>(MachineType::Int8());
+  RunLoadStoreRelocationOffset<uint8_t>(MachineType::Uint8());
+  RunLoadStoreRelocationOffset<int16_t>(MachineType::Int16());
+  RunLoadStoreRelocationOffset<uint16_t>(MachineType::Uint16());
+  RunLoadStoreRelocationOffset<int32_t>(MachineType::Int32());
+  RunLoadStoreRelocationOffset<uint32_t>(MachineType::Uint32());
+  RunLoadStoreRelocationOffset<void*>(MachineType::AnyTagged());
+  RunLoadStoreRelocationOffset<float>(MachineType::Float32());
+  RunLoadStoreRelocationOffset<double>(MachineType::Float64());
+}
+
+TEST(Uint32LessThanRelocation) {
+  RawMachineAssemblerTester<uint32_t> m;
+  RawMachineLabel within_bounds, out_of_bounds;
+  Node* index = m.Int32Constant(0x200);
+  Node* limit =
+      m.RelocatableInt32Constant(0x200, RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
+  Node* cond = m.AddNode(m.machine()->Uint32LessThan(), index, limit);
+  m.Branch(cond, &within_bounds, &out_of_bounds);
+  m.Bind(&within_bounds);
+  m.Return(m.Int32Constant(0xaced));
+  m.Bind(&out_of_bounds);
+  m.Return(m.Int32Constant(0xdeadbeef));
+  // Check that index is out of bounds with current size
+  CHECK_EQ(0xdeadbeef, m.Call());
+  m.GenerateCode();
+
+  Handle<Code> code = m.GetCode();
+  UpdateMemoryReferences(code, reinterpret_cast<Address>(1234),
+                         reinterpret_cast<Address>(1234), 0x200, 0x400);
+  // Check that after limit is increased, index is within bounds.
+  CHECK_EQ(0xaced, m.Call());
+}
diff --git a/test/cctest/compiler/test-simplified-lowering.cc b/test/cctest/compiler/test-simplified-lowering.cc
index b5e9929..b56721e 100644
--- a/test/cctest/compiler/test-simplified-lowering.cc
+++ b/test/cctest/compiler/test-simplified-lowering.cc
@@ -6,13 +6,14 @@
 
 #include "src/ast/scopes.h"
 #include "src/compiler/access-builder.h"
-#include "src/compiler/change-lowering.h"
 #include "src/compiler/control-builders.h"
-#include "src/compiler/graph-reducer.h"
+#include "src/compiler/effect-control-linearizer.h"
 #include "src/compiler/graph-visualizer.h"
+#include "src/compiler/memory-optimizer.h"
 #include "src/compiler/node-properties.h"
 #include "src/compiler/pipeline.h"
 #include "src/compiler/representation-change.h"
+#include "src/compiler/scheduler.h"
 #include "src/compiler/simplified-lowering.h"
 #include "src/compiler/source-position.h"
 #include "src/compiler/typer.h"
@@ -60,11 +61,13 @@
     typer.Run();
     lowering.LowerAllNodes();
 
-    ChangeLowering lowering(&jsgraph);
-    GraphReducer reducer(this->zone(), this->graph());
-    reducer.AddReducer(&lowering);
-    reducer.ReduceGraph();
-    Verifier::Run(this->graph());
+    Schedule* schedule = Scheduler::ComputeSchedule(this->zone(), this->graph(),
+                                                    Scheduler::kNoFlags);
+    EffectControlLinearizer linearizer(&jsgraph, schedule, this->zone());
+    linearizer.Run();
+
+    MemoryOptimizer memory_optimizer(&jsgraph, this->zone());
+    memory_optimizer.Optimize();
   }
 
   void CheckNumberCall(double expected, double input) {
@@ -99,13 +102,15 @@
   double input;
   int32_t result;
   SimplifiedLoweringTester<Object*> t;
-  FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(),
-                      MachineType::Float64()};
+  FieldAccess load = {kUntaggedBase,          0,
+                      Handle<Name>(),         Type::Number(),
+                      MachineType::Float64(), kNoWriteBarrier};
   Node* loaded = t.LoadField(load, t.PointerConstant(&input));
   NodeProperties::SetType(loaded, Type::Number());
   Node* convert = t.NumberToInt32(loaded);
-  FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Signed32(),
-                       MachineType::Int32()};
+  FieldAccess store = {kUntaggedBase,        0,
+                       Handle<Name>(),       Type::Signed32(),
+                       MachineType::Int32(), kNoWriteBarrier};
   t.StoreField(store, t.PointerConstant(&result), convert);
   t.Return(t.jsgraph.TrueConstant());
   t.LowerAllNodesAndLowerChanges();
@@ -126,13 +131,15 @@
   double input;
   uint32_t result;
   SimplifiedLoweringTester<Object*> t;
-  FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(),
-                      MachineType::Float64()};
+  FieldAccess load = {kUntaggedBase,          0,
+                      Handle<Name>(),         Type::Number(),
+                      MachineType::Float64(), kNoWriteBarrier};
   Node* loaded = t.LoadField(load, t.PointerConstant(&input));
   NodeProperties::SetType(loaded, Type::Number());
   Node* convert = t.NumberToUint32(loaded);
-  FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Unsigned32(),
-                       MachineType::Uint32()};
+  FieldAccess store = {kUntaggedBase,         0,
+                       Handle<Name>(),        Type::Unsigned32(),
+                       MachineType::Uint32(), kNoWriteBarrier};
   t.StoreField(store, t.PointerConstant(&result), convert);
   t.Return(t.jsgraph.TrueConstant());
   t.LowerAllNodesAndLowerChanges();
@@ -291,8 +298,12 @@
 
   for (size_t i = 0; i < arraysize(smis); i++) {
     int offset = static_cast<int>(i * sizeof(Smi*));
-    FieldAccess access = {kUntaggedBase, offset, Handle<Name>(),
-                          Type::Integral32(), MachineType::AnyTagged()};
+    FieldAccess access = {kUntaggedBase,
+                          offset,
+                          Handle<Name>(),
+                          Type::Integral32(),
+                          MachineType::AnyTagged(),
+                          kNoWriteBarrier};
 
     SimplifiedLoweringTester<Object*> t;
     Node* load = t.LoadField(access, t.PointerConstant(smis));
@@ -313,8 +324,12 @@
 
   for (size_t i = 0; i < arraysize(smis); i++) {
     int offset = static_cast<int>(i * sizeof(Smi*));
-    FieldAccess access = {kUntaggedBase, offset, Handle<Name>(),
-                          Type::Integral32(), MachineType::AnyTagged()};
+    FieldAccess access = {kUntaggedBase,
+                          offset,
+                          Handle<Name>(),
+                          Type::Integral32(),
+                          MachineType::AnyTagged(),
+                          kNoWriteBarrier};
 
     SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
     Node* p0 = t.Parameter(0);
@@ -340,7 +355,7 @@
     for (size_t j = 0; (i + j) < arraysize(smis); j++) {  // for element index
       int offset = static_cast<int>(i * sizeof(Smi*));
       ElementAccess access = {kUntaggedBase, offset, Type::Integral32(),
-                              MachineType::AnyTagged()};
+                              MachineType::AnyTagged(), kNoWriteBarrier};
 
       SimplifiedLoweringTester<Object*> t;
       Node* load = t.LoadElement(access, t.PointerConstant(smis),
@@ -366,7 +381,7 @@
     for (size_t j = 0; (i + j) < arraysize(smis); j++) {  // for element index
       int offset = static_cast<int>(i * sizeof(Smi*));
       ElementAccess access = {kUntaggedBase, offset, Type::Integral32(),
-                              MachineType::AnyTagged()};
+                              MachineType::AnyTagged(), kNoWriteBarrier};
 
       SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
       Node* p0 = t.Parameter(0);
@@ -518,7 +533,7 @@
   ElementAccess GetElementAccess() {
     ElementAccess access = {tagged ? kTaggedBase : kUntaggedBase,
                             tagged ? FixedArrayBase::kHeaderSize : 0,
-                            Type::Any(), rep};
+                            Type::Any(), rep, kFullWriteBarrier};
     return access;
   }
 
@@ -526,7 +541,10 @@
     int offset = field * sizeof(E);
     FieldAccess access = {tagged ? kTaggedBase : kUntaggedBase,
                           offset + (tagged ? FixedArrayBase::kHeaderSize : 0),
-                          Handle<Name>(), Type::Any(), rep};
+                          Handle<Name>(),
+                          Type::Any(),
+                          rep,
+                          kFullWriteBarrier};
     return access;
   }
 
@@ -726,11 +744,13 @@
     SourcePositionTable table(jsgraph.graph());
     SimplifiedLowering(&jsgraph, jsgraph.zone(), &table).LowerAllNodes();
 
-    ChangeLowering lowering(&jsgraph);
-    GraphReducer reducer(this->zone(), this->graph());
-    reducer.AddReducer(&lowering);
-    reducer.ReduceGraph();
-    Verifier::Run(this->graph());
+    Schedule* schedule = Scheduler::ComputeSchedule(this->zone(), this->graph(),
+                                                    Scheduler::kNoFlags);
+    EffectControlLinearizer linearizer(&jsgraph, schedule, this->zone());
+    linearizer.Run();
+
+    MemoryOptimizer memory_optimizer(&jsgraph, this->zone());
+    memory_optimizer.Optimize();
   }
 
   // Inserts the node as the return value of the graph.
@@ -831,7 +851,7 @@
   Node* use = t.Use(inv, MachineType::AnyTagged());
   t.Return(use);
   t.Lower();
-  CHECK_EQ(IrOpcode::kChangeBitToBool, use->InputAt(0)->opcode());
+  CHECK_EQ(IrOpcode::kChangeBitToTagged, use->InputAt(0)->opcode());
   Node* cmp = use->InputAt(0)->InputAt(0);
   CHECK_EQ(t.machine()->Word32Equal()->opcode(), cmp->opcode());
   CHECK(b == cmp->InputAt(0) || b == cmp->InputAt(1));
@@ -863,7 +883,7 @@
   Node* use = t.Use(inv, MachineType::AnyTagged());
   t.Return(use);
   t.Lower();
-  CHECK_EQ(IrOpcode::kChangeBitToBool, use->InputAt(0)->opcode());
+  CHECK_EQ(IrOpcode::kChangeBitToTagged, use->InputAt(0)->opcode());
   Node* cmp = use->InputAt(0)->InputAt(0);
   CHECK_EQ(t.machine()->WordEqual()->opcode(), cmp->opcode());
   CHECK(b == cmp->InputAt(0) || b == cmp->InputAt(1));
@@ -908,7 +928,7 @@
   t.Return(use);
   t.Lower();
   CHECK_EQ(b, use->InputAt(0)->InputAt(0));
-  CHECK_EQ(IrOpcode::kChangeUint32ToTagged, use->InputAt(0)->opcode());
+  CHECK_EQ(IrOpcode::kChangeInt31ToTaggedSigned, use->InputAt(0)->opcode());
 }
 
 
@@ -921,7 +941,7 @@
   t.Return(use);
   t.Lower();
   CHECK_EQ(cnv, use->InputAt(0)->InputAt(0));
-  CHECK_EQ(IrOpcode::kChangeUint32ToTagged, use->InputAt(0)->opcode());
+  CHECK_EQ(IrOpcode::kChangeInt31ToTaggedSigned, use->InputAt(0)->opcode());
   CHECK_EQ(t.machine()->WordEqual()->opcode(), cnv->opcode());
   CHECK(b == cnv->InputAt(0) || b == cnv->InputAt(1));
   Node* c = t.jsgraph.TrueConstant();
@@ -1046,8 +1066,7 @@
   CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p0, use->InputAt(0));
 }
 
-
-TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32) {
+TEST(LowerNumberToInt32_to_TruncateFloat64ToWord32) {
   // NumberToInt32(x: kRepFloat64) used as MachineType::Int32()
   TestingGraph t(Type::Number());
   Node* p0 = t.ExampleWithOutput(MachineType::Float64());
@@ -1055,22 +1074,17 @@
   Node* use = t.Use(trunc, MachineType::Int32());
   t.Return(use);
   t.Lower();
-  CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0));
+  CheckChangeOf(IrOpcode::kTruncateFloat64ToWord32, p0, use->InputAt(0));
 }
 
-
-TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32_with_change) {
+TEST(LowerNumberToInt32_to_TruncateTaggedToWord32) {
   // NumberToInt32(x: kTypeNumber | kRepTagged) used as MachineType::Int32()
   TestingGraph t(Type::Number());
   Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), t.p0);
   Node* use = t.Use(trunc, MachineType::Int32());
   t.Return(use);
   t.Lower();
-  Node* node = use->InputAt(0);
-  CHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, node->opcode());
-  Node* of = node->InputAt(0);
-  CHECK_EQ(IrOpcode::kChangeTaggedToFloat64, of->opcode());
-  CHECK_EQ(t.p0, of->InputAt(0));
+  CheckChangeOf(IrOpcode::kTruncateTaggedToWord32, t.p0, use->InputAt(0));
 }
 
 
@@ -1084,8 +1098,7 @@
   CheckChangeOf(IrOpcode::kChangeTaggedToUint32, t.p0, use->InputAt(0));
 }
 
-
-TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32) {
+TEST(LowerNumberToUint32_to_TruncateFloat64ToWord32) {
   // NumberToUint32(x: kRepFloat64) used as MachineType::Uint32()
   TestingGraph t(Type::Number());
   Node* p0 = t.ExampleWithOutput(MachineType::Float64());
@@ -1095,26 +1108,20 @@
   Node* use = t.Use(trunc, MachineType::Uint32());
   t.Return(use);
   t.Lower();
-  CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0));
+  CheckChangeOf(IrOpcode::kTruncateFloat64ToWord32, p0, use->InputAt(0));
 }
 
-
-TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_with_change) {
+TEST(LowerNumberToUint32_to_TruncateTaggedToWord32) {
   // NumberToInt32(x: kTypeNumber | kRepTagged) used as MachineType::Uint32()
   TestingGraph t(Type::Number());
   Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), t.p0);
   Node* use = t.Use(trunc, MachineType::Uint32());
   t.Return(use);
   t.Lower();
-  Node* node = use->InputAt(0);
-  CHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, node->opcode());
-  Node* of = node->InputAt(0);
-  CHECK_EQ(IrOpcode::kChangeTaggedToFloat64, of->opcode());
-  CHECK_EQ(t.p0, of->InputAt(0));
+  CheckChangeOf(IrOpcode::kTruncateTaggedToWord32, t.p0, use->InputAt(0));
 }
 
-
-TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_uint32) {
+TEST(LowerNumberToUint32_to_TruncateFloat64ToWord32_uint32) {
   // NumberToUint32(x: kRepFloat64) used as kRepWord32
   TestingGraph t(Type::Unsigned32());
   Node* input = t.ExampleWithOutput(MachineType::Float64());
@@ -1122,7 +1129,7 @@
   Node* use = t.Use(trunc, MachineType::RepWord32());
   t.Return(use);
   t.Lower();
-  CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, input, use->InputAt(0));
+  CheckChangeOf(IrOpcode::kTruncateFloat64ToWord32, input, use->InputAt(0));
 }
 
 
@@ -1150,7 +1157,7 @@
                        MachineType::Int32(), Type::Signed32());
   CheckChangeInsertion(IrOpcode::kChangeFloat64ToUint32, MachineType::Float64(),
                        MachineType::Uint32(), Type::Unsigned32());
-  CheckChangeInsertion(IrOpcode::kTruncateFloat64ToInt32,
+  CheckChangeInsertion(IrOpcode::kTruncateFloat64ToWord32,
                        MachineType::Float64(), MachineType::Uint32(),
                        Type::Integral32());
   CheckChangeInsertion(IrOpcode::kChangeTaggedToInt32, MachineType::AnyTagged(),
@@ -1160,7 +1167,7 @@
                        Type::Unsigned32());
 
   CheckChangeInsertion(IrOpcode::kChangeFloat64ToTagged, MachineType::Float64(),
-                       MachineType::AnyTagged());
+                       MachineType::AnyTagged(), Type::Number());
   CheckChangeInsertion(IrOpcode::kChangeTaggedToFloat64,
                        MachineType::AnyTagged(), MachineType::Float64(),
                        Type::Number());
@@ -1222,7 +1229,7 @@
 
   for (size_t i = 0; i < arraysize(ops); i++) {
     CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToInt32,
-                            IrOpcode::kChangeBitToBool);
+                            IrOpcode::kChangeBitToTagged);
   }
 }
 
@@ -1235,7 +1242,7 @@
 
   for (size_t i = 0; i < arraysize(ops); i++) {
     CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToUint32,
-                            IrOpcode::kChangeBitToBool);
+                            IrOpcode::kChangeBitToTagged);
   }
 }
 
@@ -1251,7 +1258,7 @@
 
   for (size_t i = 0; i < arraysize(ops); i++) {
     CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToFloat64,
-                            IrOpcode::kChangeFloat64ToTagged);
+                            IrOpcode::kChangeFloat64ToTagged, Type::Number());
   }
 }
 
@@ -1265,7 +1272,7 @@
 
   for (size_t i = 0; i < arraysize(ops); i++) {
     CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToFloat64,
-                            IrOpcode::kChangeBitToBool);
+                            IrOpcode::kChangeBitToTagged);
   }
 }
 
@@ -1311,11 +1318,11 @@
 
 
 TEST(LowerLoadField_to_load) {
-  TestingGraph t(Type::Any(), Type::Signed32());
-
   for (size_t i = 0; i < arraysize(kMachineReps); i++) {
-    FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
-                          Handle<Name>::null(), Type::Any(), kMachineReps[i]};
+    TestingGraph t(Type::Any(), Type::Signed32());
+    FieldAccess access = {kTaggedBase,          FixedArrayBase::kHeaderSize,
+                          Handle<Name>::null(), Type::Any(),
+                          kMachineReps[i],      kNoWriteBarrier};
 
     Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0,
                                     t.start, t.start);
@@ -1337,9 +1344,9 @@
     TestingGraph t(Type::Any(), Type::Signed32());
 
     for (size_t i = 0; i < arraysize(kMachineReps); i++) {
-      FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
-                            Handle<Name>::null(), Type::Any(), kMachineReps[i]};
-
+      FieldAccess access = {kTaggedBase,          FixedArrayBase::kHeaderSize,
+                            Handle<Name>::null(), Type::Any(),
+                            kMachineReps[i],      kNoWriteBarrier};
 
       Node* val = t.ExampleWithOutput(kMachineReps[i]);
       Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
@@ -1352,7 +1359,7 @@
 
       StoreRepresentation rep = StoreRepresentationOf(store->op());
       if (kMachineReps[i].representation() == MachineRepresentation::kTagged) {
-        CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind());
+        CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind());
       }
       CHECK_EQ(kMachineReps[i].representation(), rep.representation());
     }
@@ -1362,9 +1369,9 @@
     Zone* z = scope.main_zone();
     TestingGraph t(Type::Any(), Type::Intersect(Type::SignedSmall(),
                                                 Type::TaggedSigned(), z));
-    FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
-                          Handle<Name>::null(), Type::Any(),
-                          MachineType::AnyTagged()};
+    FieldAccess access = {
+        kTaggedBase, FixedArrayBase::kHeaderSize, Handle<Name>::null(),
+        Type::Any(), MachineType::AnyTagged(),    kNoWriteBarrier};
     Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
                                      t.p1, t.start, t.start);
     t.Effect(store);
@@ -1378,11 +1385,10 @@
 
 
 TEST(LowerLoadElement_to_load) {
-  TestingGraph t(Type::Any(), Type::Signed32());
-
   for (size_t i = 0; i < arraysize(kMachineReps); i++) {
+    TestingGraph t(Type::Any(), Type::Signed32());
     ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
-                            Type::Any(), kMachineReps[i]};
+                            Type::Any(), kMachineReps[i], kNoWriteBarrier};
 
     Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0,
                                     t.p1, t.start, t.start);
@@ -1401,11 +1407,11 @@
 
 TEST(LowerStoreElement_to_store) {
   {
-    TestingGraph t(Type::Any(), Type::Signed32());
-
     for (size_t i = 0; i < arraysize(kMachineReps); i++) {
+      TestingGraph t(Type::Any(), Type::Signed32());
+
       ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
-                              Type::Any(), kMachineReps[i]};
+                              Type::Any(), kMachineReps[i], kNoWriteBarrier};
 
       Node* val = t.ExampleWithOutput(kMachineReps[i]);
       Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access),
@@ -1418,7 +1424,7 @@
 
       StoreRepresentation rep = StoreRepresentationOf(store->op());
       if (kMachineReps[i].representation() == MachineRepresentation::kTagged) {
-        CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind());
+        CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind());
       }
       CHECK_EQ(kMachineReps[i].representation(), rep.representation());
     }
@@ -1430,7 +1436,8 @@
         Type::Any(), Type::Signed32(),
         Type::Intersect(Type::SignedSmall(), Type::TaggedSigned(), z));
     ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
-                            Type::Any(), MachineType::AnyTagged()};
+                            Type::Any(), MachineType::AnyTagged(),
+                            kNoWriteBarrier};
     Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0,
                                      t.p1, t.p2, t.start, t.start);
     t.Effect(store);
@@ -1448,7 +1455,7 @@
   //   Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k))
   TestingGraph t(Type::Any(), Type::Signed32());
   ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
-                          MachineType::AnyTagged()};
+                          MachineType::AnyTagged(), kNoWriteBarrier};
 
   Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0,
                                   t.p1, t.start, t.start);
@@ -1465,7 +1472,7 @@
   //   Store(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k), val)
   TestingGraph t(Type::Any(), Type::Signed32());
   ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
-                          MachineType::AnyTagged()};
+                          MachineType::AnyTagged(), kFullWriteBarrier};
 
   Node* store =
       t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, t.p1,
@@ -1481,8 +1488,9 @@
 TEST(InsertChangeForLoadElement) {
   // TODO(titzer): test all load/store representation change insertions.
   TestingGraph t(Type::Any(), Type::Signed32(), Type::Any());
-  ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
-                          MachineType::Float64()};
+  ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
+                          Type::Number(), MachineType::Float64(),
+                          kNoWriteBarrier};
 
   Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0,
                                   t.p1, t.start, t.start);
@@ -1497,9 +1505,9 @@
 TEST(InsertChangeForLoadField) {
   // TODO(titzer): test all load/store representation change insertions.
   TestingGraph t(Type::Any(), Type::Signed32());
-  FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
-                        Handle<Name>::null(), Type::Any(),
-                        MachineType::Float64()};
+  FieldAccess access = {
+      kTaggedBase,    FixedArrayBase::kHeaderSize, Handle<Name>::null(),
+      Type::Number(), MachineType::Float64(),      kNoWriteBarrier};
 
   Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0,
                                   t.start, t.start);
@@ -1515,7 +1523,7 @@
   // TODO(titzer): test all load/store representation change insertions.
   TestingGraph t(Type::Any(), Type::Signed32());
   ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
-                          MachineType::Float64()};
+                          MachineType::Float64(), kFullWriteBarrier};
 
   Node* store =
       t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0,
@@ -1532,9 +1540,9 @@
 TEST(InsertChangeForStoreField) {
   // TODO(titzer): test all load/store representation change insertions.
   TestingGraph t(Type::Any(), Type::Signed32());
-  FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
-                        Handle<Name>::null(), Type::Any(),
-                        MachineType::Float64()};
+  FieldAccess access = {
+      kTaggedBase, FixedArrayBase::kHeaderSize, Handle<Name>::null(),
+      Type::Any(), MachineType::Float64(),      kNoWriteBarrier};
 
   Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
                                    t.p1, t.start, t.start);
@@ -1554,8 +1562,9 @@
   Type* kTypes[] = {Type::Signed32(), Type::Unsigned32(), Type::Number()};
 
   for (size_t i = 0; i < arraysize(kMachineTypes); i++) {
-    FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
-                          Handle<Name>::null(), kTypes[i], kMachineTypes[i]};
+    FieldAccess access = {kTaggedBase,          FixedArrayBase::kHeaderSize,
+                          Handle<Name>::null(), kTypes[i],
+                          kMachineTypes[i],     kFullWriteBarrier};
 
     Node* load0 = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0,
                                      t.start, t.start);
diff --git a/test/cctest/compiler/value-helper.h b/test/cctest/compiler/value-helper.h
index 7d26dba..75d22b4 100644
--- a/test/cctest/compiler/value-helper.h
+++ b/test/cctest/compiler/value-helper.h
@@ -110,7 +110,9 @@
         -3.63759e-10f,
         -4.30175e-14f,
         -5.27385e-15f,
+        -1.5707963267948966f,
         -1.48084e-15f,
+        -2.220446049250313e-16f,
         -1.05755e-19f,
         -3.2995e-21f,
         -1.67354e-23f,
@@ -129,6 +131,7 @@
         6.25073e-22f,
         4.1723e-13f,
         1.44343e-09f,
+        1.5707963267948966f,
         5.27004e-08f,
         9.48298e-08f,
         5.57888e-07f,
@@ -177,6 +180,7 @@
   static std::vector<double> float64_vector() {
     static const double nan = std::numeric_limits<double>::quiet_NaN();
     static const double values[] = {-2e66,
+                                    -2.220446049250313e-16,
                                     -9223373136366403584.0,
                                     -9223372036854775808.0,  // INT64_MIN
                                     -2147483649.5,
@@ -188,6 +192,7 @@
                                     -999.75,
                                     -2e66,
                                     -1.75,
+                                    -1.5707963267948966,
                                     -1.0,
                                     -0.5,
                                     -0.0,
@@ -198,7 +203,11 @@
                                     0.375,
                                     0.5,
                                     1.0,
+                                    1.17549e-38,
+                                    1.56657e-37,
+                                    1.0000001,
                                     1.25,
+                                    1.5707963267948966,
                                     2,
                                     3.1e7,
                                     5.125,
diff --git a/test/cctest/expression-type-collector.cc b/test/cctest/expression-type-collector.cc
index c5218b3..f1289a7 100644
--- a/test/cctest/expression-type-collector.cc
+++ b/test/cctest/expression-type-collector.cc
@@ -6,6 +6,7 @@
 
 #include "test/cctest/expression-type-collector.h"
 
+#include "src/ast/ast-type-bounds.h"
 #include "src/ast/ast.h"
 #include "src/ast/scopes.h"
 #include "src/codegen.h"
@@ -27,12 +28,10 @@
 
 }  // namespace
 
-
 ExpressionTypeCollector::ExpressionTypeCollector(
-    Isolate* isolate, FunctionLiteral* root,
+    Isolate* isolate, FunctionLiteral* root, const AstTypeBounds* bounds,
     ZoneVector<ExpressionTypeEntry>* dst)
-    : AstExpressionVisitor(isolate, root), result_(dst) {}
-
+    : AstExpressionVisitor(isolate, root), bounds_(bounds), result_(dst) {}
 
 void ExpressionTypeCollector::Run() {
   result_->clear();
@@ -47,7 +46,7 @@
   if (proxy) {
     e.name = proxy->raw_name();
   }
-  e.bounds = expression->bounds();
+  e.bounds = bounds_->get(expression);
   AstNode::NodeType type = expression->node_type();
   e.kind = "unknown";
   for (size_t i = 0; i < arraysize(NodeTypeNameList); ++i) {
diff --git a/test/cctest/expression-type-collector.h b/test/cctest/expression-type-collector.h
index 37bb9a3..a52cfda 100644
--- a/test/cctest/expression-type-collector.h
+++ b/test/cctest/expression-type-collector.h
@@ -10,6 +10,8 @@
 namespace v8 {
 namespace internal {
 
+class AstTypeBounds;
+
 // A Visitor over an AST that collects a human readable string summarizing
 // structure and types. Used for testing of the typing information attached
 // to the expression nodes of an AST.
@@ -24,6 +26,7 @@
 class ExpressionTypeCollector : public AstExpressionVisitor {
  public:
   ExpressionTypeCollector(Isolate* isolate, FunctionLiteral* root,
+                          const AstTypeBounds* bounds,
                           ZoneVector<ExpressionTypeEntry>* dst);
   void Run();
 
@@ -31,6 +34,7 @@
   void VisitExpression(Expression* expression);
 
  private:
+  const AstTypeBounds* bounds_;
   ZoneVector<ExpressionTypeEntry>* result_;
 };
 }  // namespace internal
diff --git a/test/cctest/heap/heap-utils.cc b/test/cctest/heap/heap-utils.cc
new file mode 100644
index 0000000..7d4d4bf
--- /dev/null
+++ b/test/cctest/heap/heap-utils.cc
@@ -0,0 +1,158 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "test/cctest/heap/heap-utils.h"
+
+#include "src/factory.h"
+#include "src/heap/heap-inl.h"
+#include "src/heap/incremental-marking.h"
+#include "src/heap/mark-compact.h"
+#include "src/isolate.h"
+
+namespace v8 {
+namespace internal {
+namespace heap {
+
+void SealCurrentObjects(Heap* heap) {
+  heap->CollectAllGarbage();
+  heap->CollectAllGarbage();
+  heap->mark_compact_collector()->EnsureSweepingCompleted();
+  heap->old_space()->EmptyAllocationInfo();
+  for (Page* page : *heap->old_space()) {
+    page->MarkNeverAllocateForTesting();
+  }
+}
+
+int FixedArrayLenFromSize(int size) {
+  return (size - FixedArray::kHeaderSize) / kPointerSize;
+}
+
+std::vector<Handle<FixedArray>> CreatePadding(Heap* heap, int padding_size,
+                                              PretenureFlag tenure,
+                                              int object_size) {
+  std::vector<Handle<FixedArray>> handles;
+  Isolate* isolate = heap->isolate();
+  int allocate_memory;
+  int length;
+  int free_memory = padding_size;
+  if (tenure == i::TENURED) {
+    heap->old_space()->EmptyAllocationInfo();
+    int overall_free_memory = static_cast<int>(heap->old_space()->Available());
+    CHECK(padding_size <= overall_free_memory || overall_free_memory == 0);
+  } else {
+    heap->new_space()->DisableInlineAllocationSteps();
+    int overall_free_memory =
+        static_cast<int>(*heap->new_space()->allocation_limit_address() -
+                         *heap->new_space()->allocation_top_address());
+    CHECK(padding_size <= overall_free_memory || overall_free_memory == 0);
+  }
+  while (free_memory > 0) {
+    if (free_memory > object_size) {
+      allocate_memory = object_size;
+      length = FixedArrayLenFromSize(allocate_memory);
+    } else {
+      allocate_memory = free_memory;
+      length = FixedArrayLenFromSize(allocate_memory);
+      if (length <= 0) {
+        // Not enough room to create another fixed array. Let's create a filler.
+        if (free_memory > (2 * kPointerSize)) {
+          heap->CreateFillerObjectAt(
+              *heap->old_space()->allocation_top_address(), free_memory,
+              ClearRecordedSlots::kNo);
+        }
+        break;
+      }
+    }
+    handles.push_back(isolate->factory()->NewFixedArray(length, tenure));
+    CHECK((tenure == NOT_TENURED && heap->InNewSpace(*handles.back())) ||
+          (tenure == TENURED && heap->InOldSpace(*handles.back())));
+    free_memory -= allocate_memory;
+  }
+  return handles;
+}
+
+void AllocateAllButNBytes(v8::internal::NewSpace* space, int extra_bytes,
+                          std::vector<Handle<FixedArray>>* out_handles) {
+  space->DisableInlineAllocationSteps();
+  int space_remaining = static_cast<int>(*space->allocation_limit_address() -
+                                         *space->allocation_top_address());
+  CHECK(space_remaining >= extra_bytes);
+  int new_linear_size = space_remaining - extra_bytes;
+  if (new_linear_size == 0) return;
+  std::vector<Handle<FixedArray>> handles =
+      heap::CreatePadding(space->heap(), new_linear_size, i::NOT_TENURED);
+  if (out_handles != nullptr)
+    out_handles->insert(out_handles->end(), handles.begin(), handles.end());
+}
+
+void FillCurrentPage(v8::internal::NewSpace* space,
+                     std::vector<Handle<FixedArray>>* out_handles) {
+  heap::AllocateAllButNBytes(space, 0, out_handles);
+}
+
+bool FillUpOnePage(v8::internal::NewSpace* space,
+                   std::vector<Handle<FixedArray>>* out_handles) {
+  space->DisableInlineAllocationSteps();
+  int space_remaining = static_cast<int>(*space->allocation_limit_address() -
+                                         *space->allocation_top_address());
+  if (space_remaining == 0) return false;
+  std::vector<Handle<FixedArray>> handles =
+      heap::CreatePadding(space->heap(), space_remaining, i::NOT_TENURED);
+  if (out_handles != nullptr)
+    out_handles->insert(out_handles->end(), handles.begin(), handles.end());
+  return true;
+}
+
+void SimulateFullSpace(v8::internal::NewSpace* space,
+                       std::vector<Handle<FixedArray>>* out_handles) {
+  heap::FillCurrentPage(space, out_handles);
+  while (heap::FillUpOnePage(space, out_handles) || space->AddFreshPage()) {
+  }
+}
+
+void SimulateIncrementalMarking(i::Heap* heap, bool force_completion) {
+  i::MarkCompactCollector* collector = heap->mark_compact_collector();
+  i::IncrementalMarking* marking = heap->incremental_marking();
+  if (collector->sweeping_in_progress()) {
+    collector->EnsureSweepingCompleted();
+  }
+  CHECK(marking->IsMarking() || marking->IsStopped());
+  if (marking->IsStopped()) {
+    heap->StartIncrementalMarking();
+  }
+  CHECK(marking->IsMarking());
+  if (!force_completion) return;
+
+  while (!marking->IsComplete()) {
+    marking->Step(i::MB, i::IncrementalMarking::NO_GC_VIA_STACK_GUARD);
+    if (marking->IsReadyToOverApproximateWeakClosure()) {
+      marking->FinalizeIncrementally();
+    }
+  }
+  CHECK(marking->IsComplete());
+}
+
+void SimulateFullSpace(v8::internal::PagedSpace* space) {
+  space->EmptyAllocationInfo();
+  space->ResetFreeList();
+  space->ClearStats();
+}
+
+void AbandonCurrentlyFreeMemory(PagedSpace* space) {
+  space->EmptyAllocationInfo();
+  for (Page* page : *space) {
+    page->MarkNeverAllocateForTesting();
+  }
+}
+
+void GcAndSweep(Heap* heap, AllocationSpace space) {
+  heap->CollectGarbage(space);
+  if (heap->mark_compact_collector()->sweeping_in_progress()) {
+    heap->mark_compact_collector()->EnsureSweepingCompleted();
+  }
+}
+
+}  // namespace heap
+}  // namespace internal
+}  // namespace v8
diff --git a/test/cctest/heap/heap-utils.h b/test/cctest/heap/heap-utils.h
new file mode 100644
index 0000000..e03e6fa
--- /dev/null
+++ b/test/cctest/heap/heap-utils.h
@@ -0,0 +1,51 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef HEAP_HEAP_UTILS_H_
+#define HEAP_HEAP_UTILS_H_
+
+#include "src/heap/heap.h"
+
+namespace v8 {
+namespace internal {
+namespace heap {
+
+void SealCurrentObjects(Heap* heap);
+
+int FixedArrayLenFromSize(int size);
+
+std::vector<Handle<FixedArray>> CreatePadding(
+    Heap* heap, int padding_size, PretenureFlag tenure,
+    int object_size = Page::kMaxRegularHeapObjectSize);
+
+void AllocateAllButNBytes(
+    v8::internal::NewSpace* space, int extra_bytes,
+    std::vector<Handle<FixedArray>>* out_handles = nullptr);
+
+void FillCurrentPage(v8::internal::NewSpace* space,
+                     std::vector<Handle<FixedArray>>* out_handles = nullptr);
+
+// Helper function that simulates a full new-space in the heap.
+bool FillUpOnePage(v8::internal::NewSpace* space,
+                   std::vector<Handle<FixedArray>>* out_handles = nullptr);
+
+void SimulateFullSpace(v8::internal::NewSpace* space,
+                       std::vector<Handle<FixedArray>>* out_handles = nullptr);
+
+// Helper function that simulates many incremental marking steps until
+// marking is completed.
+void SimulateIncrementalMarking(i::Heap* heap, bool force_completion = true);
+
+// Helper function that simulates a full old-space in the heap.
+void SimulateFullSpace(v8::internal::PagedSpace* space);
+
+void AbandonCurrentlyFreeMemory(PagedSpace* space);
+
+void GcAndSweep(Heap* heap, AllocationSpace space);
+
+}  // namespace heap
+}  // namespace internal
+}  // namespace v8
+
+#endif  // HEAP_HEAP_UTILS_H_
diff --git a/test/cctest/heap/test-alloc.cc b/test/cctest/heap/test-alloc.cc
index 1b969b2..348ba19 100644
--- a/test/cctest/heap/test-alloc.cc
+++ b/test/cctest/heap/test-alloc.cc
@@ -31,7 +31,7 @@
 #include "src/accessors.h"
 #include "src/api.h"
 #include "test/cctest/heap/heap-tester.h"
-#include "test/cctest/heap/utils-inl.h"
+#include "test/cctest/heap/heap-utils.h"
 
 using namespace v8::internal;
 
@@ -52,11 +52,11 @@
   heap->CopyJSObject(JSObject::cast(object)).ToObjectChecked();
 
   // Old data space.
-  SimulateFullSpace(heap->old_space());
+  heap::SimulateFullSpace(heap->old_space());
   heap->AllocateByteArray(100, TENURED).ToObjectChecked();
 
   // Old pointer space.
-  SimulateFullSpace(heap->old_space());
+  heap::SimulateFullSpace(heap->old_space());
   heap->AllocateFixedArray(10000, TENURED).ToObjectChecked();
 
   // Large object space.
@@ -72,12 +72,12 @@
       kLargeObjectSpaceFillerLength, TENURED).ToObjectChecked();
 
   // Map space.
-  SimulateFullSpace(heap->map_space());
+  heap::SimulateFullSpace(heap->map_space());
   int instance_size = JSObject::kHeaderSize;
   heap->AllocateMap(JS_OBJECT_TYPE, instance_size).ToObjectChecked();
 
   // Test that we can allocate in old pointer space and code space.
-  SimulateFullSpace(heap->code_space());
+  heap::SimulateFullSpace(heap->code_space());
   heap->AllocateFixedArray(100, TENURED).ToObjectChecked();
   heap->CopyCode(CcTest::i_isolate()->builtins()->builtin(
       Builtins::kIllegal)).ToObjectChecked();
@@ -102,7 +102,7 @@
   v8::Local<v8::Context> env = v8::Context::New(CcTest::isolate());
   env->Enter();
   Handle<Object> o = TestAllocateAfterFailures();
-  CHECK(o->IsTrue());
+  CHECK(o->IsTrue(CcTest::i_isolate()));
   env->Exit();
 }
 
@@ -211,8 +211,7 @@
   const size_t code_range_size = 32*MB;
   CcTest::InitializeVM();
   CodeRange code_range(reinterpret_cast<Isolate*>(CcTest::isolate()));
-  code_range.SetUp(code_range_size +
-                   kReservedCodeRangePages * v8::base::OS::CommitPageSize());
+  code_range.SetUp(code_range_size);
   size_t current_allocated = 0;
   size_t total_allocated = 0;
   List< ::Block> blocks(1000);
diff --git a/test/cctest/heap/test-array-buffer-tracker.cc b/test/cctest/heap/test-array-buffer-tracker.cc
new file mode 100644
index 0000000..b331f6b
--- /dev/null
+++ b/test/cctest/heap/test-array-buffer-tracker.cc
@@ -0,0 +1,318 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/heap/array-buffer-tracker.h"
+#include "test/cctest/cctest.h"
+#include "test/cctest/heap/heap-utils.h"
+
+namespace {
+
+typedef i::LocalArrayBufferTracker LocalTracker;
+
+bool IsTracked(i::JSArrayBuffer* buf) {
+  return i::ArrayBufferTracker::IsTracked(buf);
+}
+
+}  // namespace
+
+namespace v8 {
+namespace internal {
+
+// The following tests make sure that JSArrayBuffer tracking works expected when
+// moving the objects through various spaces during GC phases.
+
+TEST(ArrayBuffer_OnlyMC) {
+  CcTest::InitializeVM();
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
+
+  JSArrayBuffer* raw_ab = nullptr;
+  {
+    v8::HandleScope handle_scope(isolate);
+    Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 100);
+    Handle<JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
+    CHECK(IsTracked(*buf));
+    heap::GcAndSweep(heap, OLD_SPACE);
+    CHECK(IsTracked(*buf));
+    heap::GcAndSweep(heap, OLD_SPACE);
+    CHECK(IsTracked(*buf));
+    raw_ab = *buf;
+    // Prohibit page from being released.
+    Page::FromAddress(buf->address())->MarkNeverEvacuate();
+  }
+  // 2 GCs are needed because we promote to old space as live, meaning that
+  // we will survive one GC.
+  heap::GcAndSweep(heap, OLD_SPACE);
+  heap::GcAndSweep(heap, OLD_SPACE);
+  CHECK(!IsTracked(raw_ab));
+}
+
+TEST(ArrayBuffer_OnlyScavenge) {
+  CcTest::InitializeVM();
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
+
+  JSArrayBuffer* raw_ab = nullptr;
+  {
+    v8::HandleScope handle_scope(isolate);
+    Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 100);
+    Handle<JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
+    CHECK(IsTracked(*buf));
+    heap::GcAndSweep(heap, NEW_SPACE);
+    CHECK(IsTracked(*buf));
+    heap::GcAndSweep(heap, NEW_SPACE);
+    CHECK(IsTracked(*buf));
+    heap::GcAndSweep(heap, NEW_SPACE);
+    CHECK(IsTracked(*buf));
+    raw_ab = *buf;
+    // Prohibit page from being released.
+    Page::FromAddress(buf->address())->MarkNeverEvacuate();
+  }
+  // 2 GCs are needed because we promote to old space as live, meaning that
+  // we will survive one GC.
+  heap::GcAndSweep(heap, OLD_SPACE);
+  heap::GcAndSweep(heap, OLD_SPACE);
+  CHECK(!IsTracked(raw_ab));
+}
+
+TEST(ArrayBuffer_ScavengeAndMC) {
+  CcTest::InitializeVM();
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
+
+  JSArrayBuffer* raw_ab = nullptr;
+  {
+    v8::HandleScope handle_scope(isolate);
+    Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 100);
+    Handle<JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
+    CHECK(IsTracked(*buf));
+    heap::GcAndSweep(heap, NEW_SPACE);
+    CHECK(IsTracked(*buf));
+    heap::GcAndSweep(heap, NEW_SPACE);
+    CHECK(IsTracked(*buf));
+    heap::GcAndSweep(heap, OLD_SPACE);
+    CHECK(IsTracked(*buf));
+    heap::GcAndSweep(heap, NEW_SPACE);
+    CHECK(IsTracked(*buf));
+    raw_ab = *buf;
+    // Prohibit page from being released.
+    Page::FromAddress(buf->address())->MarkNeverEvacuate();
+  }
+  // 2 GCs are needed because we promote to old space as live, meaning that
+  // we will survive one GC.
+  heap::GcAndSweep(heap, OLD_SPACE);
+  heap::GcAndSweep(heap, OLD_SPACE);
+  CHECK(!IsTracked(raw_ab));
+}
+
+TEST(ArrayBuffer_Compaction) {
+  FLAG_manual_evacuation_candidates_selection = true;
+  CcTest::InitializeVM();
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
+  heap::AbandonCurrentlyFreeMemory(heap->old_space());
+
+  v8::HandleScope handle_scope(isolate);
+  Local<v8::ArrayBuffer> ab1 = v8::ArrayBuffer::New(isolate, 100);
+  Handle<JSArrayBuffer> buf1 = v8::Utils::OpenHandle(*ab1);
+  CHECK(IsTracked(*buf1));
+  heap::GcAndSweep(heap, NEW_SPACE);
+  heap::GcAndSweep(heap, NEW_SPACE);
+
+  Page* page_before_gc = Page::FromAddress(buf1->address());
+  page_before_gc->SetFlag(MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING);
+  CHECK(IsTracked(*buf1));
+
+  heap->CollectAllGarbage();
+
+  Page* page_after_gc = Page::FromAddress(buf1->address());
+  CHECK(IsTracked(*buf1));
+
+  CHECK_NE(page_before_gc, page_after_gc);
+}
+
+TEST(ArrayBuffer_UnregisterDuringSweep) {
+// Regular pages in old space (without compaction) are processed concurrently
+// in the sweeper. If we happen to unregister a buffer (either explicitly, or
+// implicitly through e.g. |Externalize|) we need to sync with the sweeper
+// task.
+//
+// Note: This test will will only fail on TSAN configurations.
+
+// Disable verify-heap since it forces sweeping to be completed in the
+// epilogue of the GC.
+#ifdef VERIFY_HEAP
+  i::FLAG_verify_heap = false;
+#endif  // VERIFY_HEAP
+
+  CcTest::InitializeVM();
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
+  {
+    v8::HandleScope handle_scope(isolate);
+    Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 100);
+    Handle<JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
+
+    {
+      v8::HandleScope handle_scope(isolate);
+      // Allocate another buffer on the same page to force processing a
+      // non-empty set of buffers in the last GC.
+      Local<v8::ArrayBuffer> ab2 = v8::ArrayBuffer::New(isolate, 100);
+      Handle<JSArrayBuffer> buf2 = v8::Utils::OpenHandle(*ab2);
+      CHECK(IsTracked(*buf));
+      CHECK(IsTracked(*buf));
+      heap::GcAndSweep(heap, NEW_SPACE);
+      CHECK(IsTracked(*buf));
+      CHECK(IsTracked(*buf));
+      heap::GcAndSweep(heap, NEW_SPACE);
+      CHECK(IsTracked(*buf));
+      CHECK(IsTracked(*buf2));
+    }
+
+    heap->CollectGarbage(OLD_SPACE);
+    // |Externalize| will cause the buffer to be |Unregister|ed. Without
+    // barriers and proper synchronization this will trigger a data race on
+    // TSAN.
+    v8::ArrayBuffer::Contents contents = ab->Externalize();
+    heap->isolate()->array_buffer_allocator()->Free(contents.Data(),
+                                                    contents.ByteLength());
+  }
+}
+
+TEST(ArrayBuffer_NonLivePromotion) {
+  // The test verifies that the marking state is preserved when promoting
+  // a buffer to old space.
+  CcTest::InitializeVM();
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
+
+  JSArrayBuffer* raw_ab = nullptr;
+  {
+    v8::HandleScope handle_scope(isolate);
+    Handle<FixedArray> root =
+        heap->isolate()->factory()->NewFixedArray(1, TENURED);
+    {
+      v8::HandleScope handle_scope(isolate);
+      Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 100);
+      Handle<JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
+      root->set(0, *buf);  // Buffer that should not be promoted as live.
+    }
+    heap::SimulateIncrementalMarking(heap, false);
+    CHECK(IsTracked(JSArrayBuffer::cast(root->get(0))));
+    heap::GcAndSweep(heap, NEW_SPACE);
+    CHECK(IsTracked(JSArrayBuffer::cast(root->get(0))));
+    heap::GcAndSweep(heap, NEW_SPACE);
+    CHECK(IsTracked(JSArrayBuffer::cast(root->get(0))));
+    raw_ab = JSArrayBuffer::cast(root->get(0));
+    root->set(0, heap->undefined_value());
+    heap::SimulateIncrementalMarking(heap, true);
+    // Prohibit page from being released.
+    Page::FromAddress(raw_ab->address())->MarkNeverEvacuate();
+    heap::GcAndSweep(heap, OLD_SPACE);
+    CHECK(!IsTracked(raw_ab));
+  }
+}
+
+TEST(ArrayBuffer_LivePromotion) {
+  // The test verifies that the marking state is preserved when promoting
+  // a buffer to old space.
+  CcTest::InitializeVM();
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
+
+  JSArrayBuffer* raw_ab = nullptr;
+  {
+    v8::HandleScope handle_scope(isolate);
+    Handle<FixedArray> root =
+        heap->isolate()->factory()->NewFixedArray(1, TENURED);
+    {
+      v8::HandleScope handle_scope(isolate);
+      Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 100);
+      Handle<JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
+      root->set(0, *buf);  // Buffer that should be promoted as live.
+    }
+    heap::SimulateIncrementalMarking(heap, true);
+    CHECK(IsTracked(JSArrayBuffer::cast(root->get(0))));
+    heap::GcAndSweep(heap, NEW_SPACE);
+    CHECK(IsTracked(JSArrayBuffer::cast(root->get(0))));
+    heap::GcAndSweep(heap, NEW_SPACE);
+    CHECK(IsTracked(JSArrayBuffer::cast(root->get(0))));
+    raw_ab = JSArrayBuffer::cast(root->get(0));
+    root->set(0, heap->undefined_value());
+    // Prohibit page from being released.
+    Page::FromAddress(raw_ab->address())->MarkNeverEvacuate();
+    heap::GcAndSweep(heap, OLD_SPACE);
+    CHECK(IsTracked(raw_ab));
+  }
+}
+
+TEST(ArrayBuffer_SemiSpaceCopyThenPagePromotion) {
+  // The test verifies that the marking state is preserved across semispace
+  // copy.
+  CcTest::InitializeVM();
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
+
+  heap::SealCurrentObjects(heap);
+  {
+    v8::HandleScope handle_scope(isolate);
+    Handle<FixedArray> root =
+        heap->isolate()->factory()->NewFixedArray(1, TENURED);
+    {
+      v8::HandleScope handle_scope(isolate);
+      Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 100);
+      Handle<JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
+      root->set(0, *buf);  // Buffer that should be promoted as live.
+      Page::FromAddress(buf->address())->MarkNeverEvacuate();
+    }
+    std::vector<Handle<FixedArray>> handles;
+    // Make the whole page transition from new->old, getting the buffers
+    // processed in the sweeper (relying on marking information) instead of
+    // processing during newspace evacuation.
+    heap::FillCurrentPage(heap->new_space(), &handles);
+    CHECK(IsTracked(JSArrayBuffer::cast(root->get(0))));
+    heap::GcAndSweep(heap, NEW_SPACE);
+    heap::SimulateIncrementalMarking(heap, true);
+    heap::GcAndSweep(heap, OLD_SPACE);
+    CHECK(IsTracked(JSArrayBuffer::cast(root->get(0))));
+  }
+}
+
+UNINITIALIZED_TEST(ArrayBuffer_SemiSpaceCopyMultipleTasks) {
+  if (FLAG_optimize_for_size) return;
+  // Test allocates JSArrayBuffer on different pages before triggering a
+  // full GC that performs the semispace copy. If parallelized, this test
+  // ensures proper synchronization in TSAN configurations.
+  FLAG_min_semi_space_size = 2 * Page::kPageSize / MB;
+  v8::Isolate::CreateParams create_params;
+  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+  v8::Isolate* isolate = v8::Isolate::New(create_params);
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  {
+    v8::Isolate::Scope isolate_scope(isolate);
+    v8::HandleScope handle_scope(isolate);
+    v8::Context::New(isolate)->Enter();
+    Heap* heap = i_isolate->heap();
+
+    Local<v8::ArrayBuffer> ab1 = v8::ArrayBuffer::New(isolate, 100);
+    Handle<JSArrayBuffer> buf1 = v8::Utils::OpenHandle(*ab1);
+    heap::FillCurrentPage(heap->new_space());
+    Local<v8::ArrayBuffer> ab2 = v8::ArrayBuffer::New(isolate, 100);
+    Handle<JSArrayBuffer> buf2 = v8::Utils::OpenHandle(*ab2);
+    CHECK_NE(Page::FromAddress(buf1->address()),
+             Page::FromAddress(buf2->address()));
+    heap::GcAndSweep(heap, OLD_SPACE);
+  }
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/test/cctest/heap/test-compaction.cc b/test/cctest/heap/test-compaction.cc
index 0feee5f..f61f7e1 100644
--- a/test/cctest/heap/test-compaction.cc
+++ b/test/cctest/heap/test-compaction.cc
@@ -4,12 +4,14 @@
 
 #include "test/cctest/cctest.h"
 #include "test/cctest/heap/heap-tester.h"
-#include "test/cctest/heap/utils-inl.h"
+#include "test/cctest/heap/heap-utils.h"
 
 namespace v8 {
 namespace internal {
 
-static void CheckInvariantsOfAbortedPage(Page* page) {
+namespace {
+
+void CheckInvariantsOfAbortedPage(Page* page) {
   // Check invariants:
   // 1) Markbits are cleared
   // 2) The page is not marked as evacuation candidate anymore
@@ -19,6 +21,14 @@
   CHECK(!page->IsFlagSet(Page::COMPACTION_WAS_ABORTED));
 }
 
+void CheckAllObjectsOnPage(std::vector<Handle<FixedArray>>& handles,
+                           Page* page) {
+  for (auto& fixed_array : handles) {
+    CHECK(Page::FromAddress(fixed_array->address()) == page);
+  }
+}
+
+}  // namespace
 
 HEAP_TEST(CompactionFullAbortedPage) {
   // Test the scenario where we reach OOM during compaction and the whole page
@@ -33,23 +43,23 @@
   Heap* heap = isolate->heap();
   {
     HandleScope scope1(isolate);
-    PageIterator it(heap->old_space());
-    while (it.has_next()) {
-      it.next()->MarkNeverAllocateForTesting();
-    }
+
+    heap::SealCurrentObjects(heap);
 
     {
       HandleScope scope2(isolate);
       CHECK(heap->old_space()->Expand());
       auto compaction_page_handles =
-          CreatePadding(heap, Page::kAllocatableMemory, TENURED);
+          heap::CreatePadding(heap, Page::kAllocatableMemory, TENURED);
       Page* to_be_aborted_page =
           Page::FromAddress(compaction_page_handles.front()->address());
       to_be_aborted_page->SetFlag(
           MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING);
+      CheckAllObjectsOnPage(compaction_page_handles, to_be_aborted_page);
 
       heap->set_force_oom(true);
       heap->CollectAllGarbage();
+      heap->mark_compact_collector()->EnsureSweepingCompleted();
 
       // Check that all handles still point to the same page, i.e., compaction
       // has been aborted on the page.
@@ -71,29 +81,29 @@
   FLAG_concurrent_sweeping = false;
   FLAG_manual_evacuation_candidates_selection = true;
 
-  const int object_size = 128 * KB;
+  const int objects_per_page = 10;
+  const int object_size = Page::kAllocatableMemory / objects_per_page;
 
   CcTest::InitializeVM();
   Isolate* isolate = CcTest::i_isolate();
   Heap* heap = isolate->heap();
   {
     HandleScope scope1(isolate);
-    PageIterator it(heap->old_space());
-    while (it.has_next()) {
-      it.next()->MarkNeverAllocateForTesting();
-    }
+
+    heap::SealCurrentObjects(heap);
 
     {
       HandleScope scope2(isolate);
       // Fill another page with objects of size {object_size} (last one is
       // properly adjusted).
       CHECK(heap->old_space()->Expand());
-      auto compaction_page_handles =
-          CreatePadding(heap, Page::kAllocatableMemory, TENURED, object_size);
+      auto compaction_page_handles = heap::CreatePadding(
+          heap, Page::kAllocatableMemory, TENURED, object_size);
       Page* to_be_aborted_page =
           Page::FromAddress(compaction_page_handles.front()->address());
       to_be_aborted_page->SetFlag(
           MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING);
+      CheckAllObjectsOnPage(compaction_page_handles, to_be_aborted_page);
 
       {
         // Add another page that is filled with {num_objects} objects of size
@@ -101,13 +111,15 @@
         HandleScope scope3(isolate);
         CHECK(heap->old_space()->Expand());
         const int num_objects = 3;
-        std::vector<Handle<FixedArray>> page_to_fill_handles = CreatePadding(
-            heap, object_size * num_objects, TENURED, object_size);
+        std::vector<Handle<FixedArray>> page_to_fill_handles =
+            heap::CreatePadding(heap, object_size * num_objects, TENURED,
+                                object_size);
         Page* page_to_fill =
             Page::FromAddress(page_to_fill_handles.front()->address());
 
         heap->set_force_oom(true);
         heap->CollectAllGarbage();
+        heap->mark_compact_collector()->EnsureSweepingCompleted();
 
         bool migration_aborted = false;
         for (Handle<FixedArray> object : compaction_page_handles) {
@@ -143,7 +155,8 @@
   FLAG_concurrent_sweeping = false;
   FLAG_manual_evacuation_candidates_selection = true;
 
-  const int object_size = 128 * KB;
+  const int objects_per_page = 10;
+  const int object_size = Page::kAllocatableMemory / objects_per_page;
 
   CcTest::InitializeVM();
   Isolate* isolate = CcTest::i_isolate();
@@ -153,10 +166,7 @@
     Handle<FixedArray> root_array =
         isolate->factory()->NewFixedArray(10, TENURED);
 
-    PageIterator it(heap->old_space());
-    while (it.has_next()) {
-      it.next()->MarkNeverAllocateForTesting();
-    }
+    heap::SealCurrentObjects(heap);
 
     Page* to_be_aborted_page = nullptr;
     {
@@ -165,7 +175,8 @@
       // properly adjusted).
       CHECK(heap->old_space()->Expand());
       std::vector<Handle<FixedArray>> compaction_page_handles =
-          CreatePadding(heap, Page::kAllocatableMemory, TENURED, object_size);
+          heap::CreatePadding(heap, Page::kAllocatableMemory, TENURED,
+                              object_size);
       to_be_aborted_page =
           Page::FromAddress(compaction_page_handles.front()->address());
       to_be_aborted_page->SetFlag(
@@ -174,8 +185,8 @@
         compaction_page_handles[i]->set(0, *compaction_page_handles[i - 1]);
       }
       root_array->set(0, *compaction_page_handles.back());
+      CheckAllObjectsOnPage(compaction_page_handles, to_be_aborted_page);
     }
-
     {
       // Add another page that is filled with {num_objects} objects of size
       // {object_size}.
@@ -184,12 +195,13 @@
       const int num_objects = 2;
       int used_memory = object_size * num_objects;
       std::vector<Handle<FixedArray>> page_to_fill_handles =
-          CreatePadding(heap, used_memory, TENURED, object_size);
+          heap::CreatePadding(heap, used_memory, TENURED, object_size);
       Page* page_to_fill =
           Page::FromAddress(page_to_fill_handles.front()->address());
 
       heap->set_force_oom(true);
       heap->CollectAllGarbage();
+      heap->mark_compact_collector()->EnsureSweepingCompleted();
 
       // The following check makes sure that we compacted "some" objects, while
       // leaving others in place.
@@ -230,7 +242,8 @@
   FLAG_concurrent_sweeping = false;
   FLAG_manual_evacuation_candidates_selection = true;
 
-  const int object_size = 128 * KB;
+  const int objects_per_page = 10;
+  const int object_size = Page::kAllocatableMemory / objects_per_page;
 
   CcTest::InitializeVM();
   Isolate* isolate = CcTest::i_isolate();
@@ -239,10 +252,7 @@
     HandleScope scope1(isolate);
     Handle<FixedArray> root_array =
         isolate->factory()->NewFixedArray(10, TENURED);
-    PageIterator it(heap->old_space());
-    while (it.has_next()) {
-      it.next()->MarkNeverAllocateForTesting();
-    }
+    heap::SealCurrentObjects(heap);
 
     Page* to_be_aborted_page = nullptr;
     {
@@ -250,8 +260,8 @@
       // Fill another page with objects of size {object_size} (last one is
       // properly adjusted).
       CHECK(heap->old_space()->Expand());
-      auto compaction_page_handles =
-          CreatePadding(heap, Page::kAllocatableMemory, TENURED, object_size);
+      auto compaction_page_handles = heap::CreatePadding(
+          heap, Page::kAllocatableMemory, TENURED, object_size);
       // Sanity check that we have enough space for linking up arrays.
       CHECK_GE(compaction_page_handles.front()->length(), 2);
       to_be_aborted_page =
@@ -267,6 +277,7 @@
           isolate->factory()->NewFixedArray(1, NOT_TENURED);
       CHECK(heap->InNewSpace(*new_space_array));
       compaction_page_handles.front()->set(1, *new_space_array);
+      CheckAllObjectsOnPage(compaction_page_handles, to_be_aborted_page);
     }
 
     {
@@ -277,12 +288,13 @@
       const int num_objects = 2;
       int used_memory = object_size * num_objects;
       std::vector<Handle<FixedArray>> page_to_fill_handles =
-          CreatePadding(heap, used_memory, TENURED, object_size);
+          heap::CreatePadding(heap, used_memory, TENURED, object_size);
       Page* page_to_fill =
           Page::FromAddress(page_to_fill_handles.front()->address());
 
       heap->set_force_oom(true);
       heap->CollectAllGarbage();
+      heap->mark_compact_collector()->EnsureSweepingCompleted();
 
       // The following check makes sure that we compacted "some" objects, while
       // leaving others in place.
diff --git a/test/cctest/heap/test-heap.cc b/test/cctest/heap/test-heap.cc
index 424e987..524a553 100644
--- a/test/cctest/heap/test-heap.cc
+++ b/test/cctest/heap/test-heap.cc
@@ -31,6 +31,7 @@
 #include "src/compilation-cache.h"
 #include "src/context-measure.h"
 #include "src/deoptimizer.h"
+#include "src/elements.h"
 #include "src/execution.h"
 #include "src/factory.h"
 #include "src/field-type.h"
@@ -43,7 +44,7 @@
 #include "src/snapshot/snapshot.h"
 #include "test/cctest/cctest.h"
 #include "test/cctest/heap/heap-tester.h"
-#include "test/cctest/heap/utils-inl.h"
+#include "test/cctest/heap/heap-utils.h"
 #include "test/cctest/test-feedback-vector.h"
 
 
@@ -577,7 +578,7 @@
 static bool WeakPointerCleared = false;
 
 static void TestWeakGlobalHandleCallback(
-    const v8::WeakCallbackData<v8::Value, void>& data) {
+    const v8::WeakCallbackInfo<void>& data) {
   std::pair<v8::Persistent<v8::Value>*, int>* p =
       reinterpret_cast<std::pair<v8::Persistent<v8::Value>*, int>*>(
           data.GetParameter());
@@ -610,9 +611,9 @@
   }
 
   std::pair<Handle<Object>*, int> handle_and_id(&h2, 1234);
-  GlobalHandles::MakeWeak(h2.location(),
-                          reinterpret_cast<void*>(&handle_and_id),
-                          &TestWeakGlobalHandleCallback);
+  GlobalHandles::MakeWeak(
+      h2.location(), reinterpret_cast<void*>(&handle_and_id),
+      &TestWeakGlobalHandleCallback, v8::WeakCallbackType::kParameter);
 
   // Scavenge treats weak pointers as normal roots.
   heap->CollectGarbage(NEW_SPACE);
@@ -657,9 +658,9 @@
   CHECK(!heap->InNewSpace(*h1) && !heap->InNewSpace(*h2));
 
   std::pair<Handle<Object>*, int> handle_and_id(&h2, 1234);
-  GlobalHandles::MakeWeak(h2.location(),
-                          reinterpret_cast<void*>(&handle_and_id),
-                          &TestWeakGlobalHandleCallback);
+  GlobalHandles::MakeWeak(
+      h2.location(), reinterpret_cast<void*>(&handle_and_id),
+      &TestWeakGlobalHandleCallback, v8::WeakCallbackType::kParameter);
   CHECK(!GlobalHandles::IsNearDeath(h1.location()));
   CHECK(!GlobalHandles::IsNearDeath(h2.location()));
 
@@ -695,9 +696,9 @@
   }
 
   std::pair<Handle<Object>*, int> handle_and_id(&h, 1234);
-  GlobalHandles::MakeWeak(h.location(),
-                          reinterpret_cast<void*>(&handle_and_id),
-                          &TestWeakGlobalHandleCallback);
+  GlobalHandles::MakeWeak(h.location(), reinterpret_cast<void*>(&handle_and_id),
+                          &TestWeakGlobalHandleCallback,
+                          v8::WeakCallbackType::kParameter);
 
   // Scanvenge does not recognize weak reference.
   heap->CollectGarbage(NEW_SPACE);
@@ -710,6 +711,44 @@
   CHECK(WeakPointerCleared);
 }
 
+TEST(DoNotPromoteWhiteObjectsOnScavenge) {
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  Heap* heap = isolate->heap();
+  Factory* factory = isolate->factory();
+
+  HandleScope scope(isolate);
+  Handle<Object> white = factory->NewStringFromStaticChars("white");
+
+  CHECK(Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(*white))));
+
+  heap->CollectGarbage(NEW_SPACE);
+
+  CHECK(heap->InNewSpace(*white));
+}
+
+TEST(PromoteGreyOrBlackObjectsOnScavenge) {
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  Heap* heap = isolate->heap();
+  Factory* factory = isolate->factory();
+
+  HandleScope scope(isolate);
+  Handle<Object> marked = factory->NewStringFromStaticChars("marked");
+
+  IncrementalMarking* marking = heap->incremental_marking();
+  marking->Stop();
+  heap->StartIncrementalMarking();
+  while (Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(*marked)))) {
+    marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD,
+                  IncrementalMarking::FORCE_MARKING,
+                  IncrementalMarking::DO_NOT_FORCE_COMPLETION);
+  }
+
+  heap->CollectGarbage(NEW_SPACE);
+
+  CHECK(!heap->InNewSpace(*marked));
+}
 
 TEST(BytecodeArray) {
   static const uint8_t kRawBytes[] = {0xc3, 0x7e, 0xa5, 0x5a};
@@ -724,7 +763,7 @@
   Factory* factory = isolate->factory();
   HandleScope scope(isolate);
 
-  SimulateFullSpace(heap->old_space());
+  heap::SimulateFullSpace(heap->old_space());
   Handle<FixedArray> constant_pool = factory->NewFixedArray(5, TENURED);
   for (int i = 0; i < 5; i++) {
     Handle<Object> number = factory->NewHeapNumber(i);
@@ -1349,7 +1388,7 @@
   // Simulate several GCs that use incremental marking.
   const int kAgingThreshold = 6;
   for (int i = 0; i < kAgingThreshold; i++) {
-    SimulateIncrementalMarking(CcTest::heap());
+    heap::SimulateIncrementalMarking(CcTest::heap());
     CcTest::heap()->CollectAllGarbage();
   }
   CHECK(!function->shared()->is_compiled() || function->IsOptimized());
@@ -1363,8 +1402,9 @@
   // Simulate several GCs that use incremental marking but make sure
   // the loop breaks once the function is enqueued as a candidate.
   for (int i = 0; i < kAgingThreshold; i++) {
-    SimulateIncrementalMarking(CcTest::heap());
-    if (!function->next_function_link()->IsUndefined()) break;
+    heap::SimulateIncrementalMarking(CcTest::heap());
+    if (!function->next_function_link()->IsUndefined(CcTest::i_isolate()))
+      break;
     CcTest::heap()->CollectAllGarbage();
   }
 
@@ -1439,7 +1479,7 @@
   // Simulate incremental marking so that the functions are enqueued as
   // code flushing candidates. Then kill one of the functions. Finally
   // perform a scavenge while incremental marking is still running.
-  SimulateIncrementalMarking(CcTest::heap());
+  heap::SimulateIncrementalMarking(CcTest::heap());
   *function2.location() = NULL;
   CcTest::heap()->CollectGarbage(NEW_SPACE, "test scavenge while marking");
 
@@ -1493,7 +1533,7 @@
 
   // Simulate incremental marking so that the function is enqueued as
   // code flushing candidate.
-  SimulateIncrementalMarking(heap);
+  heap::SimulateIncrementalMarking(heap);
 
   // Enable the debugger and add a breakpoint while incremental marking
   // is running so that incremental marking aborts and code flushing is
@@ -1546,12 +1586,9 @@
   Handle<Object> g_value =
       Object::GetProperty(isolate->global_object(), g_name).ToHandleChecked();
   Handle<JSFunction> g_function = Handle<JSFunction>::cast(g_value);
-  // TODO(mvstanton): change to check that g is *not* compiled when optimized
-  // cache
-  // map lookup moves to the compile lazy builtin.
-  CHECK(g_function->is_compiled());
+  CHECK(!g_function->is_compiled());
 
-  SimulateIncrementalMarking(heap);
+  heap::SimulateIncrementalMarking(heap);
   CompileRun("%OptimizeFunctionOnNextCall(f); f();");
 
   // g should now have available an optimized function, unmarked by gc. The
@@ -1590,25 +1627,11 @@
     CompileRun(raw_source);
   }
 
-  // On first compilation, only a hash is inserted in the code cache. We can't
-  // find that value.
+  // The script should be in the cache now.
   MaybeHandle<SharedFunctionInfo> info = compilation_cache->LookupScript(
       source, Handle<Object>(), 0, 0,
       v8::ScriptOriginOptions(false, true, false), native_context,
       language_mode);
-  CHECK(info.is_null());
-
-  {
-    v8::HandleScope scope(CcTest::isolate());
-    CompileRun(raw_source);
-  }
-
-  // On second compilation, the hash is replaced by a real cache entry mapping
-  // the source to the shared function info containing the code.
-  info = compilation_cache->LookupScript(
-      source, Handle<Object>(), 0, 0,
-      v8::ScriptOriginOptions(false, true, false), native_context,
-      language_mode);
   CHECK(!info.is_null());
 
   // Check that the code cache entry survives at least on GC.
@@ -1640,36 +1663,6 @@
       v8::ScriptOriginOptions(false, true, false), native_context,
       language_mode);
   CHECK(info.is_null());
-
-  {
-    v8::HandleScope scope(CcTest::isolate());
-    CompileRun(raw_source);
-  }
-
-  // On first compilation, only a hash is inserted in the code cache. We can't
-  // find that value.
-  info = compilation_cache->LookupScript(
-      source, Handle<Object>(), 0, 0,
-      v8::ScriptOriginOptions(false, true, false), native_context,
-      language_mode);
-  CHECK(info.is_null());
-
-  for (int i = 0; i < CompilationCacheTable::kHashGenerations; i++) {
-    compilation_cache->MarkCompactPrologue();
-  }
-
-  {
-    v8::HandleScope scope(CcTest::isolate());
-    CompileRun(raw_source);
-  }
-
-  // If we aged the cache before caching the script, ensure that we didn't cache
-  // on next compilation.
-  info = compilation_cache->LookupScript(
-      source, Handle<Object>(), 0, 0,
-      v8::ScriptOriginOptions(false, true, false), native_context,
-      language_mode);
-  CHECK(info.is_null());
 }
 
 
@@ -1690,9 +1683,9 @@
 int CountNativeContexts() {
   int count = 0;
   Object* object = CcTest::heap()->native_contexts_list();
-  while (!object->IsUndefined()) {
+  while (!object->IsUndefined(CcTest::i_isolate())) {
     count++;
-    object = Context::cast(object)->get(Context::NEXT_CONTEXT_LINK);
+    object = Context::cast(object)->next_context_link();
   }
   return count;
 }
@@ -1826,12 +1819,11 @@
   Heap* heap = isolate->heap();
   int count = 0;
   Handle<Object> object(heap->native_contexts_list(), isolate);
-  while (!object->IsUndefined()) {
+  while (!object->IsUndefined(isolate)) {
     count++;
     if (count == n) heap->CollectAllGarbage();
     object =
-        Handle<Object>(Context::cast(*object)->get(Context::NEXT_CONTEXT_LINK),
-                       isolate);
+        Handle<Object>(Context::cast(*object)->next_context_link(), isolate);
   }
   return count;
 }
@@ -2296,16 +2288,20 @@
   // on the heap.
   if (size_of_objects_1 > size_of_objects_2) {
     intptr_t delta = size_of_objects_1 - size_of_objects_2;
-    PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, "
-           "Iterator: %" V8_PTR_PREFIX "d, "
-           "delta: %" V8_PTR_PREFIX "d\n",
+    PrintF("Heap::SizeOfObjects: %" V8PRIdPTR
+           ", "
+           "Iterator: %" V8PRIdPTR
+           ", "
+           "delta: %" V8PRIdPTR "\n",
            size_of_objects_1, size_of_objects_2, delta);
     CHECK_GT(size_of_objects_1 / 20, delta);
   } else {
     intptr_t delta = size_of_objects_2 - size_of_objects_1;
-    PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, "
-           "Iterator: %" V8_PTR_PREFIX "d, "
-           "delta: %" V8_PTR_PREFIX "d\n",
+    PrintF("Heap::SizeOfObjects: %" V8PRIdPTR
+           ", "
+           "Iterator: %" V8PRIdPTR
+           ", "
+           "delta: %" V8PRIdPTR "\n",
            size_of_objects_1, size_of_objects_2, delta);
     CHECK_GT(size_of_objects_2 / 20, delta);
   }
@@ -2657,6 +2653,14 @@
   CcTest::heap()->CollectGarbage(OLD_SPACE);
 }
 
+namespace {
+
+int GetProfilerTicks(SharedFunctionInfo* shared) {
+  return FLAG_ignition ? shared->profiler_ticks()
+                       : shared->code()->profiler_ticks();
+}
+
+}  // namespace
 
 TEST(ResetSharedFunctionInfoCountersDuringIncrementalMarking) {
   i::FLAG_stress_compaction = false;
@@ -2687,16 +2691,18 @@
           CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
   CHECK(f->IsOptimized());
 
-  IncrementalMarking* marking = CcTest::heap()->incremental_marking();
-  marking->Stop();
+  // Make sure incremental marking it not running.
+  CcTest::heap()->incremental_marking()->Stop();
+
   CcTest::heap()->StartIncrementalMarking();
   // The following calls will increment CcTest::heap()->global_ic_age().
   CcTest::isolate()->ContextDisposedNotification();
-  SimulateIncrementalMarking(CcTest::heap());
+  heap::SimulateIncrementalMarking(CcTest::heap());
   CcTest::heap()->CollectAllGarbage();
+
   CHECK_EQ(CcTest::heap()->global_ic_age(), f->shared()->ic_age());
   CHECK_EQ(0, f->shared()->opt_count());
-  CHECK_EQ(0, f->shared()->code()->profiler_ticks());
+  CHECK_EQ(0, GetProfilerTicks(f->shared()));
 }
 
 
@@ -2727,9 +2733,9 @@
   i::Handle<JSFunction> f = i::Handle<JSFunction>::cast(
       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
           CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
-
   CHECK(f->IsOptimized());
 
+  // Make sure incremental marking it not running.
   CcTest::heap()->incremental_marking()->Stop();
 
   // The following two calls will increment CcTest::heap()->global_ic_age().
@@ -2738,7 +2744,7 @@
 
   CHECK_EQ(CcTest::heap()->global_ic_age(), f->shared()->ic_age());
   CHECK_EQ(0, f->shared()->opt_count());
-  CHECK_EQ(0, f->shared()->code()->profiler_ticks());
+  CHECK_EQ(0, GetProfilerTicks(f->shared()));
 }
 
 
@@ -2776,12 +2782,13 @@
 TEST(IdleNotificationFinishMarking) {
   i::FLAG_allow_natives_syntax = true;
   CcTest::InitializeVM();
-  SimulateFullSpace(CcTest::heap()->old_space());
+  const int initial_gc_count = CcTest::heap()->gc_count();
+  heap::SimulateFullSpace(CcTest::heap()->old_space());
   IncrementalMarking* marking = CcTest::heap()->incremental_marking();
   marking->Stop();
   CcTest::heap()->StartIncrementalMarking();
 
-  CHECK_EQ(CcTest::heap()->gc_count(), 0);
+  CHECK_EQ(CcTest::heap()->gc_count(), initial_gc_count);
 
   // TODO(hpayer): We cannot write proper unit test right now for heap.
   // The ideal test would call kMaxIdleMarkingDelayCounter to test the
@@ -2816,7 +2823,7 @@
       (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
        static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
       kLongIdleTime);
-  CHECK_EQ(CcTest::heap()->gc_count(), 1);
+  CHECK_EQ(CcTest::heap()->gc_count(), initial_gc_count + 1);
 }
 
 
@@ -2828,7 +2835,7 @@
   if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
   v8::HandleScope scope(CcTest::isolate());
   v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
-  SimulateFullSpace(CcTest::heap()->new_space());
+  heap::SimulateFullSpace(CcTest::heap()->new_space());
   AlwaysAllocateScope always_allocate(CcTest::i_isolate());
   v8::Local<v8::Value> res = CompileRun(
       "function c(x) {"
@@ -3303,7 +3310,7 @@
   CompileRun("%DebugPrint(root);");
   CHECK_EQ(transitions_count, transitions_before);
 
-  SimulateIncrementalMarking(CcTest::heap());
+  heap::SimulateIncrementalMarking(CcTest::heap());
   CcTest::heap()->CollectAllGarbage();
 
   // Count number of live transitions after marking.  Note that one transition
@@ -3473,7 +3480,7 @@
              "root.foo = 0;"
              "root = new Object;");
 
-  SimulateIncrementalMarking(CcTest::heap());
+  heap::SimulateIncrementalMarking(CcTest::heap());
 
   // Compile a StoreIC that performs the prepared map transition. This
   // will restart incremental marking and should make sure the root is
@@ -3513,7 +3520,7 @@
              "root.foo = 0;"
              "root = new Object;");
 
-  SimulateIncrementalMarking(CcTest::heap());
+  heap::SimulateIncrementalMarking(CcTest::heap());
 
   // Compile an optimized LStoreNamedField that performs the prepared
   // map transition. This will restart incremental marking and should
@@ -3557,6 +3564,8 @@
   // Concurrent sweeping adds non determinism, depending on when memory is
   // available for further reuse.
   i::FLAG_concurrent_sweeping = false;
+  // Fast evacuation of pages may result in a different page count in old space.
+  i::FLAG_page_promotion = false;
   CcTest::InitializeVM();
   Isolate* isolate = CcTest::i_isolate();
   Factory* factory = isolate->factory();
@@ -3566,28 +3575,29 @@
 
   // Prepare many pages with low live-bytes count.
   PagedSpace* old_space = heap->old_space();
-  CHECK_EQ(1, old_space->CountTotalPages());
+  const int initial_page_count = old_space->CountTotalPages();
+  const int overall_page_count = number_of_test_pages + initial_page_count;
   for (int i = 0; i < number_of_test_pages; i++) {
     AlwaysAllocateScope always_allocate(isolate);
-    SimulateFullSpace(old_space);
+    heap::SimulateFullSpace(old_space);
     factory->NewFixedArray(1, TENURED);
   }
-  CHECK_EQ(number_of_test_pages + 1, old_space->CountTotalPages());
+  CHECK_EQ(overall_page_count, old_space->CountTotalPages());
 
   // Triggering one GC will cause a lot of garbage to be discovered but
   // even spread across all allocated pages.
   heap->CollectAllGarbage(Heap::kFinalizeIncrementalMarkingMask,
                           "triggered for preparation");
-  CHECK_GE(number_of_test_pages + 1, old_space->CountTotalPages());
+  CHECK_GE(overall_page_count, old_space->CountTotalPages());
 
   // Triggering subsequent GCs should cause at least half of the pages
   // to be released to the OS after at most two cycles.
   heap->CollectAllGarbage(Heap::kFinalizeIncrementalMarkingMask,
                           "triggered by test 1");
-  CHECK_GE(number_of_test_pages + 1, old_space->CountTotalPages());
+  CHECK_GE(overall_page_count, old_space->CountTotalPages());
   heap->CollectAllGarbage(Heap::kFinalizeIncrementalMarkingMask,
                           "triggered by test 2");
-  CHECK_GE(number_of_test_pages + 1, old_space->CountTotalPages() * 2);
+  CHECK_GE(overall_page_count, old_space->CountTotalPages() * 2);
 
   // Triggering a last-resort GC should cause all pages to be released to the
   // OS so that other processes can seize the memory.  If we get a failure here
@@ -3597,7 +3607,7 @@
   // boots, but if the 20 small arrays don't fit on the first page then that's
   // an indication that it is too small.
   heap->CollectAllAvailableGarbage("triggered really hard");
-  CHECK_EQ(1, old_space->CountTotalPages());
+  CHECK_EQ(initial_page_count, old_space->CountTotalPages());
 }
 
 static int forced_gc_counter = 0;
@@ -3670,7 +3680,7 @@
       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
           CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
 
-  Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector());
+  Handle<TypeFeedbackVector> feedback_vector(f->feedback_vector());
   FeedbackVectorHelper feedback_helper(feedback_vector);
 
   int expected_slots = 2;
@@ -3680,7 +3690,7 @@
   CHECK(feedback_vector->Get(feedback_helper.slot(slot1))->IsWeakCell());
   CHECK(feedback_vector->Get(feedback_helper.slot(slot2))->IsWeakCell());
 
-  SimulateIncrementalMarking(CcTest::heap());
+  heap::SimulateIncrementalMarking(CcTest::heap());
   CcTest::heap()->CollectAllGarbage();
 
   CHECK(!WeakCell::cast(feedback_vector->Get(feedback_helper.slot(slot1)))
@@ -3707,7 +3717,7 @@
 static void CheckVectorIC(Handle<JSFunction> f, int slot_index,
                           InlineCacheState desired_state) {
   Handle<TypeFeedbackVector> vector =
-      Handle<TypeFeedbackVector>(f->shared()->feedback_vector());
+      Handle<TypeFeedbackVector>(f->feedback_vector());
   FeedbackVectorHelper helper(vector);
   FeedbackVectorSlot slot = helper.slot(slot_index);
   if (vector->GetKind(slot) == FeedbackVectorSlotKind::LOAD_IC) {
@@ -3720,16 +3730,6 @@
   }
 }
 
-
-static void CheckVectorICCleared(Handle<JSFunction> f, int slot_index) {
-  Handle<TypeFeedbackVector> vector =
-      Handle<TypeFeedbackVector>(f->shared()->feedback_vector());
-  FeedbackVectorSlot slot(slot_index);
-  LoadICNexus nexus(vector, slot);
-  CHECK(IC::IsCleared(&nexus));
-}
-
-
 TEST(IncrementalMarkingPreservesMonomorphicConstructor) {
   if (i::FLAG_always_opt) return;
   CcTest::InitializeVM();
@@ -3744,54 +3744,15 @@
       v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
           CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
 
-  Handle<TypeFeedbackVector> vector(f->shared()->feedback_vector());
+  Handle<TypeFeedbackVector> vector(f->feedback_vector());
   CHECK(vector->Get(FeedbackVectorSlot(0))->IsWeakCell());
 
-  SimulateIncrementalMarking(CcTest::heap());
+  heap::SimulateIncrementalMarking(CcTest::heap());
   CcTest::heap()->CollectAllGarbage();
 
   CHECK(vector->Get(FeedbackVectorSlot(0))->IsWeakCell());
 }
 
-
-TEST(IncrementalMarkingClearsMonomorphicConstructor) {
-  if (i::FLAG_always_opt) return;
-  CcTest::InitializeVM();
-  Isolate* isolate = CcTest::i_isolate();
-  v8::HandleScope scope(CcTest::isolate());
-  v8::Local<v8::Value> fun1;
-  v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
-
-  {
-    LocalContext env;
-    CompileRun("function fun() { this.x = 1; };");
-    fun1 = env->Global()->Get(env.local(), v8_str("fun")).ToLocalChecked();
-  }
-
-  // Prepare function f that contains a monomorphic constructor for object
-  // originating from a different native context.
-  CHECK(CcTest::global()->Set(ctx, v8_str("fun1"), fun1).FromJust());
-  CompileRun(
-      "function fun() { this.x = 1; };"
-      "function f(o) { return new o(); } f(fun1); f(fun1);");
-  Handle<JSFunction> f = Handle<JSFunction>::cast(
-      v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
-          CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
-
-
-  Handle<TypeFeedbackVector> vector(f->shared()->feedback_vector());
-  CHECK(vector->Get(FeedbackVectorSlot(0))->IsWeakCell());
-
-  // Fire context dispose notification.
-  CcTest::isolate()->ContextDisposedNotification();
-  SimulateIncrementalMarking(CcTest::heap());
-  CcTest::heap()->CollectAllGarbage();
-
-  CHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(isolate),
-           vector->Get(FeedbackVectorSlot(0)));
-}
-
-
 TEST(IncrementalMarkingPreservesMonomorphicIC) {
   if (i::FLAG_always_opt) return;
   CcTest::InitializeVM();
@@ -3807,45 +3768,12 @@
 
   CheckVectorIC(f, 0, MONOMORPHIC);
 
-  SimulateIncrementalMarking(CcTest::heap());
+  heap::SimulateIncrementalMarking(CcTest::heap());
   CcTest::heap()->CollectAllGarbage();
 
   CheckVectorIC(f, 0, MONOMORPHIC);
 }
 
-
-TEST(IncrementalMarkingClearsMonomorphicIC) {
-  if (i::FLAG_always_opt) return;
-  CcTest::InitializeVM();
-  v8::HandleScope scope(CcTest::isolate());
-  v8::Local<v8::Value> obj1;
-  v8::Local<v8::Context> ctx = CcTest::isolate()->GetCurrentContext();
-
-  {
-    LocalContext env;
-    CompileRun("function fun() { this.x = 1; }; var obj = new fun();");
-    obj1 = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
-  }
-
-  // Prepare function f that contains a monomorphic IC for object
-  // originating from a different native context.
-  CHECK(CcTest::global()->Set(ctx, v8_str("obj1"), obj1).FromJust());
-  CompileRun("function f(o) { return o.x; } f(obj1); f(obj1);");
-  Handle<JSFunction> f = Handle<JSFunction>::cast(
-      v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
-          CcTest::global()->Get(ctx, v8_str("f")).ToLocalChecked())));
-
-  CheckVectorIC(f, 0, MONOMORPHIC);
-
-  // Fire context dispose notification.
-  CcTest::isolate()->ContextDisposedNotification();
-  SimulateIncrementalMarking(CcTest::heap());
-  CcTest::heap()->CollectAllGarbage();
-
-  CheckVectorICCleared(f, 0);
-}
-
-
 TEST(IncrementalMarkingPreservesPolymorphicIC) {
   if (i::FLAG_always_opt) return;
   CcTest::InitializeVM();
@@ -3877,14 +3805,13 @@
   CheckVectorIC(f, 0, POLYMORPHIC);
 
   // Fire context dispose notification.
-  SimulateIncrementalMarking(CcTest::heap());
+  heap::SimulateIncrementalMarking(CcTest::heap());
   CcTest::heap()->CollectAllGarbage();
 
   CheckVectorIC(f, 0, POLYMORPHIC);
 }
 
-
-TEST(IncrementalMarkingClearsPolymorphicIC) {
+TEST(ContextDisposeDoesntClearPolymorphicIC) {
   if (i::FLAG_always_opt) return;
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
@@ -3916,10 +3843,10 @@
 
   // Fire context dispose notification.
   CcTest::isolate()->ContextDisposedNotification();
-  SimulateIncrementalMarking(CcTest::heap());
+  heap::SimulateIncrementalMarking(CcTest::heap());
   CcTest::heap()->CollectAllGarbage();
 
-  CheckVectorICCleared(f, 0);
+  CheckVectorIC(f, 0, POLYMORPHIC);
 }
 
 
@@ -4088,7 +4015,7 @@
   // Simulate incremental marking so that the functions are enqueued as
   // code flushing candidates. Then optimize one function. Finally
   // finish the GC to complete code flushing.
-  SimulateIncrementalMarking(heap);
+  heap::SimulateIncrementalMarking(heap);
   CompileRun("%OptimizeFunctionOnNextCall(g); g(3);");
   heap->CollectAllGarbage();
 
@@ -4134,7 +4061,7 @@
 
   // Simulate incremental marking so that unoptimized code is flushed
   // even though it still is cached in the optimized code map.
-  SimulateIncrementalMarking(heap);
+  heap::SimulateIncrementalMarking(heap);
   heap->CollectAllGarbage();
 
   // Make a new closure that will get code installed from the code map.
@@ -4202,7 +4129,7 @@
   }
 
   // Simulate incremental marking and collect code flushing candidates.
-  SimulateIncrementalMarking(heap);
+  heap::SimulateIncrementalMarking(heap);
   CHECK(shared1->code()->gc_metadata() != NULL);
 
   // Optimize function and make sure the unoptimized code is replaced.
@@ -4258,9 +4185,9 @@
   array_data->set(0, Smi::FromInt(1));
   array_data->set(1, Smi::FromInt(2));
 
-  AllocateAllButNBytes(CcTest::heap()->new_space(),
-                       JSArray::kSize + AllocationMemento::kSize +
-                       kPointerSize);
+  heap::AllocateAllButNBytes(
+      CcTest::heap()->new_space(),
+      JSArray::kSize + AllocationMemento::kSize + kPointerSize);
 
   Handle<JSArray> array =
       factory->NewJSArrayWithElements(array_data, FAST_SMI_ELEMENTS);
@@ -4333,7 +4260,8 @@
     if (!code->is_optimized_code()) return;
   }
 
-  Handle<TypeFeedbackVector> vector = handle(shared->feedback_vector());
+  Handle<TypeFeedbackVector> vector =
+      TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata()));
   Handle<LiteralsArray> lit =
       LiteralsArray::New(isolate, vector, shared->num_literals(), TENURED);
   Handle<Context> context(isolate->context());
@@ -4390,7 +4318,8 @@
     if (!code->is_optimized_code()) return;
   }
 
-  Handle<TypeFeedbackVector> vector = handle(shared->feedback_vector());
+  Handle<TypeFeedbackVector> vector =
+      TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata()));
   Handle<LiteralsArray> lit =
       LiteralsArray::New(isolate, vector, shared->num_literals(), TENURED);
   Handle<Context> context(isolate->context());
@@ -4409,7 +4338,7 @@
     HandleScope inner_scope(isolate);
     AlwaysAllocateScope always_allocate(isolate);
     // Make sure literal is placed on an old-space evacuation candidate.
-    SimulateFullSpace(heap->old_space());
+    heap::SimulateFullSpace(heap->old_space());
 
     // Make sure there the number of literals is > 0.
     Handle<LiteralsArray> lit =
@@ -4424,7 +4353,7 @@
   // simulate incremental marking to enqueue optimized code map.
   FLAG_manual_evacuation_candidates_selection = true;
   evac_page->SetFlag(MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING);
-  SimulateIncrementalMarking(heap);
+  heap::SimulateIncrementalMarking(heap);
 
   // No matter whether reachable or not, {boomer} is doomed.
   Handle<Object> boomer(shared->optimized_code_map(), isolate);
@@ -4621,7 +4550,7 @@
   HandleScope scope(isolate);
 
   // Create an object on an evacuation candidate.
-  SimulateFullSpace(heap->old_space());
+  heap::SimulateFullSpace(heap->old_space());
   Handle<FixedArray> lit = isolate->factory()->NewFixedArray(4, TENURED);
   Page* evac_page = Page::FromAddress(lit->address());
   evac_page->SetFlag(MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING);
@@ -4634,7 +4563,7 @@
   CHECK(heap->lo_space()->Contains(*lo));
 
   // Start incremental marking to active write barrier.
-  SimulateIncrementalMarking(heap, false);
+  heap::SimulateIncrementalMarking(heap, false);
   heap->incremental_marking()->AdvanceIncrementalMarking(
       10000000, IncrementalMarking::IdleStepActions());
 
@@ -4735,7 +4664,7 @@
 static int AllocationSitesCount(Heap* heap) {
   int count = 0;
   for (Object* site = heap->allocation_sites_list();
-       !(site->IsUndefined());
+       !(site->IsUndefined(heap->isolate()));
        site = AllocationSite::cast(site)->weak_next()) {
     count++;
   }
@@ -4911,7 +4840,7 @@
   if (!isolate->use_crankshaft()) return;
   HandleScope outer_scope(heap->isolate());
   for (int i = 0; i < 3; i++) {
-    SimulateIncrementalMarking(heap);
+    heap::SimulateIncrementalMarking(heap);
     {
       LocalContext context;
       HandleScope scope(heap->isolate());
@@ -5095,7 +5024,7 @@
   // cleared. Now, verify that one additional call with a new function
   // allows monomorphicity.
   Handle<TypeFeedbackVector> feedback_vector = Handle<TypeFeedbackVector>(
-      createObj->shared()->feedback_vector(), CcTest::i_isolate());
+      createObj->feedback_vector(), CcTest::i_isolate());
   for (int i = 0; i < 20; i++) {
     Object* slot_value = feedback_vector->Get(FeedbackVectorSlot(0));
     CHECK(slot_value->IsWeakCell());
@@ -5296,12 +5225,11 @@
   return Handle<JSFunction>::cast(obj);
 }
 
-
-void CheckIC(Code* code, Code::Kind kind, SharedFunctionInfo* shared,
-             int slot_index, InlineCacheState state) {
+void CheckIC(Handle<JSFunction> function, Code::Kind kind, int slot_index,
+             InlineCacheState state) {
   if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC ||
       kind == Code::CALL_IC) {
-    TypeFeedbackVector* vector = shared->feedback_vector();
+    TypeFeedbackVector* vector = function->feedback_vector();
     FeedbackVectorSlot slot(slot_index);
     if (kind == Code::LOAD_IC) {
       LoadICNexus nexus(vector, slot);
@@ -5314,9 +5242,10 @@
       CHECK_EQ(nexus.StateFromFeedback(), state);
     }
   } else {
-    Code* ic = FindFirstIC(code, kind);
+    Code* ic = FindFirstIC(function->code(), kind);
     CHECK(ic->is_inline_cache_stub());
-    CHECK(ic->ic_state() == state);
+    CHECK(!IC::ICUseVector(kind));
+    CHECK_EQ(state, IC::StateFromCode(ic));
   }
 }
 
@@ -5345,12 +5274,12 @@
     CompileRun("(testIC())");
   }
   heap->CollectAllGarbage();
-  CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, MONOMORPHIC);
+  CheckIC(loadIC, Code::LOAD_IC, 0, MONOMORPHIC);
   {
     v8::HandleScope scope(CcTest::isolate());
     CompileRun("(testIC())");
   }
-  CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, MONOMORPHIC);
+  CheckIC(loadIC, Code::LOAD_IC, 0, MONOMORPHIC);
 }
 
 
@@ -5381,12 +5310,12 @@
     CompileRun("(testIC())");
   }
   heap->CollectAllGarbage();
-  CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, POLYMORPHIC);
+  CheckIC(loadIC, Code::LOAD_IC, 0, POLYMORPHIC);
   {
     v8::HandleScope scope(CcTest::isolate());
     CompileRun("(testIC())");
   }
-  CheckIC(loadIC->code(), Code::LOAD_IC, loadIC->shared(), 0, POLYMORPHIC);
+  CheckIC(loadIC, Code::LOAD_IC, 0, POLYMORPHIC);
 }
 
 
@@ -5547,19 +5476,21 @@
   isolate->Enter();
   {
     i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+    Heap* heap = i_isolate->heap();
     HandleScope handle_scope(i_isolate);
-    PagedSpace* old_space = i_isolate->heap()->old_space();
+    PagedSpace* old_space = heap->old_space();
     const int kMaxObjects = 10000;
     const int kFixedArrayLen = 512;
     Handle<FixedArray> objects[kMaxObjects];
-    for (int i = 0; (i < kMaxObjects) && old_space->CanExpand(Page::kPageSize);
+    for (int i = 0; (i < kMaxObjects) &&
+                    heap->CanExpandOldGeneration(old_space->AreaSize());
          i++) {
       objects[i] = i_isolate->factory()->NewFixedArray(kFixedArrayLen, TENURED);
       Page::FromAddress(objects[i]->address())
           ->SetFlag(MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING);
     }
-    SimulateFullSpace(old_space);
-    i_isolate->heap()->CollectGarbage(OLD_SPACE);
+    heap::SimulateFullSpace(old_space);
+    heap->CollectGarbage(OLD_SPACE);
     // If we get this far, we've successfully aborted compaction. Any further
     // allocations might trigger OOM.
   }
@@ -5618,7 +5549,7 @@
 
 UNINITIALIZED_TEST(PromotionQueue) {
   i::FLAG_expose_gc = true;
-  i::FLAG_max_semi_space_size = 2 * (Page::kPageSize / MB);
+  i::FLAG_max_semi_space_size = 2 * Page::kPageSize / MB;
   i::FLAG_min_semi_space_size = i::FLAG_max_semi_space_size;
   v8::Isolate::CreateParams create_params;
   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
@@ -5671,7 +5602,7 @@
     CHECK(i::FLAG_min_semi_space_size * MB == new_space->TotalCapacity());
 
     // Fill-up the first semi-space page.
-    FillUpOnePage(new_space);
+    heap::FillUpOnePage(new_space);
 
     // Create a small object to initialize the bump pointer on the second
     // semi-space page.
@@ -5680,7 +5611,7 @@
     CHECK(heap->InNewSpace(*small));
 
     // Fill-up the second semi-space page.
-    FillUpOnePage(new_space);
+    heap::FillUpOnePage(new_space);
 
     // This scavenge will corrupt memory if the promotion queue is not
     // evacuated.
@@ -5710,9 +5641,9 @@
 
   // Allocate padding objects in old pointer space so, that object allocated
   // afterwards would end at the end of the page.
-  SimulateFullSpace(heap->old_space());
+  heap::SimulateFullSpace(heap->old_space());
   int padding_size = desired_offset - Page::kObjectStartOffset;
-  CreatePadding(heap, padding_size, TENURED);
+  heap::CreatePadding(heap, padding_size, TENURED);
 
   Handle<JSObject> o = factory->NewJSObjectFromMap(map1, TENURED);
   o->set_properties(*factory->empty_fixed_array());
@@ -5859,11 +5790,11 @@
   Handle<WeakCell> weak_cell = AddRetainedMap(isolate, heap);
   CHECK(!weak_cell->cleared());
   for (int i = 0; i < n; i++) {
-    SimulateIncrementalMarking(heap);
+    heap::SimulateIncrementalMarking(heap);
     heap->CollectGarbage(OLD_SPACE);
   }
   CHECK(!weak_cell->cleared());
-  SimulateIncrementalMarking(heap);
+  heap::SimulateIncrementalMarking(heap);
   heap->CollectGarbage(OLD_SPACE);
   CHECK(weak_cell->cleared());
 }
@@ -5892,7 +5823,7 @@
   heap->CollectGarbage(OLD_SPACE);
   // Force GC in old space on next addition of retained map.
   Map::WeakCellForMap(map);
-  SimulateFullSpace(CcTest::heap()->new_space());
+  heap::SimulateFullSpace(CcTest::heap()->new_space());
   for (int i = 0; i < 10; i++) {
     heap->AddRetainedMap(map);
   }
@@ -6175,6 +6106,7 @@
   Isolate* isolate = CcTest::i_isolate();
   Heap* heap = isolate->heap();
   GCTracer* tracer = heap->tracer();
+  tracer->ResetForTesting();
   int time1 = 100;
   size_t counter1 = 1000;
   tracer->SampleAllocation(time1, counter1, 0);
@@ -6198,6 +6130,7 @@
   Isolate* isolate = CcTest::i_isolate();
   Heap* heap = isolate->heap();
   GCTracer* tracer = heap->tracer();
+  tracer->ResetForTesting();
   int time1 = 100;
   size_t counter1 = 1000;
   tracer->SampleAllocation(time1, counter1, 0);
@@ -6219,7 +6152,7 @@
   Isolate* isolate = CcTest::i_isolate();
   Object* message =
       *reinterpret_cast<Object**>(isolate->pending_message_obj_address());
-  CHECK(message->IsTheHole());
+  CHECK(message->IsTheHole(isolate));
 }
 
 
@@ -6304,6 +6237,28 @@
       "check(g1, g2);");
 }
 
+TEST(RemoveCodeFromSharedFunctionInfoButNotFromClosure) {
+  CcTest::InitializeVM();
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
+  global->Set(isolate, "check", v8::FunctionTemplate::New(
+                                    isolate, CheckEqualSharedFunctionInfos));
+  global->Set(isolate, "remove",
+              v8::FunctionTemplate::New(isolate, RemoveCodeAndGC));
+  v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
+  v8::Context::Scope cscope(context);
+  CompileRun(
+      "function f() { return function g() {}; }"
+      "var g1 = f();"
+      "var g2 = f();"
+      "check(g1, g2);"
+      "g1();"
+      "g2();"
+      "remove(g1);"
+      "g2();"
+      "check(g1, g2);");
+}
 
 TEST(OldGenerationAllocationThroughput) {
   CcTest::InitializeVM();
@@ -6311,6 +6266,7 @@
   Isolate* isolate = CcTest::i_isolate();
   Heap* heap = isolate->heap();
   GCTracer* tracer = heap->tracer();
+  tracer->ResetForTesting();
   int time1 = 100;
   size_t counter1 = 1000;
   tracer->SampleAllocation(time1, 0, counter1);
@@ -6335,6 +6291,7 @@
   Isolate* isolate = CcTest::i_isolate();
   Heap* heap = isolate->heap();
   GCTracer* tracer = heap->tracer();
+  tracer->ResetForTesting();
   int time1 = 100;
   size_t counter1 = 1000;
   tracer->SampleAllocation(time1, counter1, counter1);
@@ -6452,7 +6409,7 @@
   parent.Reset(isolate, v8::Object::New(isolate));
   child.Reset(isolate, v8::Object::New(isolate));
 
-  SimulateFullSpace(heap->old_space());
+  heap::SimulateFullSpace(heap->old_space());
   heap->CollectGarbage(OLD_SPACE);
   {
     UniqueId id = MakeUniqueId(parent);
@@ -6511,7 +6468,7 @@
     array->set(i, *number);
   }
   heap->CollectGarbage(OLD_SPACE);
-  SimulateFullSpace(heap->old_space());
+  heap::SimulateFullSpace(heap->old_space());
   heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(*array, N - 1);
   heap->mark_compact_collector()->EnsureSweepingCompleted();
   ByteArray* byte_array;
@@ -6594,7 +6551,7 @@
         }
       }
     }
-    SimulateIncrementalMarking(heap);
+    heap::SimulateIncrementalMarking(heap);
     for (size_t j = 0; j < arrays.size(); j++) {
       heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(arrays[j], N - 1);
     }
@@ -6604,6 +6561,106 @@
   heap->CollectGarbage(OLD_SPACE);
 }
 
+TEST(Regress598319) {
+  // This test ensures that no white objects can cross the progress bar of large
+  // objects during incremental marking. It checks this by using Shift() during
+  // incremental marking.
+  CcTest::InitializeVM();
+  v8::HandleScope scope(CcTest::isolate());
+  Heap* heap = CcTest::heap();
+  Isolate* isolate = heap->isolate();
+
+  const int kNumberOfObjects = Page::kMaxRegularHeapObjectSize / kPointerSize;
+
+  struct Arr {
+    Arr(Isolate* isolate, int number_of_objects) {
+      root = isolate->factory()->NewFixedArray(1, TENURED);
+      {
+        // Temporary scope to avoid getting any other objects into the root set.
+        v8::HandleScope scope(CcTest::isolate());
+        Handle<FixedArray> tmp =
+            isolate->factory()->NewFixedArray(number_of_objects);
+        root->set(0, *tmp);
+        for (int i = 0; i < get()->length(); i++) {
+          tmp = isolate->factory()->NewFixedArray(100, TENURED);
+          get()->set(i, *tmp);
+        }
+      }
+    }
+
+    FixedArray* get() { return FixedArray::cast(root->get(0)); }
+
+    Handle<FixedArray> root;
+  } arr(isolate, kNumberOfObjects);
+
+  CHECK_EQ(arr.get()->length(), kNumberOfObjects);
+  CHECK(heap->lo_space()->Contains(arr.get()));
+  LargePage* page = heap->lo_space()->FindPage(arr.get()->address());
+  CHECK_NOT_NULL(page);
+
+  // GC to cleanup state
+  heap->CollectGarbage(OLD_SPACE);
+  MarkCompactCollector* collector = heap->mark_compact_collector();
+  if (collector->sweeping_in_progress()) {
+    collector->EnsureSweepingCompleted();
+  }
+
+  CHECK(heap->lo_space()->Contains(arr.get()));
+  CHECK(Marking::IsWhite(Marking::MarkBitFrom(arr.get())));
+  for (int i = 0; i < arr.get()->length(); i++) {
+    CHECK(Marking::IsWhite(
+        Marking::MarkBitFrom(HeapObject::cast(arr.get()->get(i)))));
+  }
+
+  // Start incremental marking.
+  IncrementalMarking* marking = heap->incremental_marking();
+  CHECK(marking->IsMarking() || marking->IsStopped());
+  if (marking->IsStopped()) {
+    heap->StartIncrementalMarking();
+  }
+  CHECK(marking->IsMarking());
+
+  // Check that we have not marked the interesting array during root scanning.
+  for (int i = 0; i < arr.get()->length(); i++) {
+    CHECK(Marking::IsWhite(
+        Marking::MarkBitFrom(HeapObject::cast(arr.get()->get(i)))));
+  }
+
+  // Now we search for a state where we are in incremental marking and have
+  // only partially marked the large object.
+  while (!marking->IsComplete()) {
+    marking->Step(i::KB, i::IncrementalMarking::NO_GC_VIA_STACK_GUARD);
+    if (page->IsFlagSet(Page::HAS_PROGRESS_BAR) && page->progress_bar() > 0) {
+      CHECK_NE(page->progress_bar(), arr.get()->Size());
+      {
+        // Shift by 1, effectively moving one white object across the progress
+        // bar, meaning that we will miss marking it.
+        v8::HandleScope scope(CcTest::isolate());
+        Handle<JSArray> js_array = isolate->factory()->NewJSArrayWithElements(
+            Handle<FixedArray>(arr.get()));
+        js_array->GetElementsAccessor()->Shift(js_array);
+      }
+      break;
+    }
+  }
+
+  // Finish marking with bigger steps to speed up test.
+  while (!marking->IsComplete()) {
+    marking->Step(10 * i::MB, i::IncrementalMarking::NO_GC_VIA_STACK_GUARD);
+    if (marking->IsReadyToOverApproximateWeakClosure()) {
+      marking->FinalizeIncrementally();
+    }
+  }
+  CHECK(marking->IsComplete());
+
+  // All objects need to be black after marking. If a white object crossed the
+  // progress bar, we would fail here.
+  for (int i = 0; i < arr.get()->length(); i++) {
+    CHECK(Marking::IsBlack(
+        Marking::MarkBitFrom(HeapObject::cast(arr.get()->get(i)))));
+  }
+}
+
 TEST(Regress609761) {
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
@@ -6617,5 +6674,61 @@
   CHECK_EQ(size_after, size_before + array->Size());
 }
 
+TEST(Regress615489) {
+  FLAG_black_allocation = true;
+  CcTest::InitializeVM();
+  v8::HandleScope scope(CcTest::isolate());
+  Heap* heap = CcTest::heap();
+  Isolate* isolate = heap->isolate();
+  heap->CollectAllGarbage();
+
+  i::MarkCompactCollector* collector = heap->mark_compact_collector();
+  i::IncrementalMarking* marking = heap->incremental_marking();
+  if (collector->sweeping_in_progress()) {
+    collector->EnsureSweepingCompleted();
+  }
+  CHECK(marking->IsMarking() || marking->IsStopped());
+  if (marking->IsStopped()) {
+    heap->StartIncrementalMarking();
+  }
+  CHECK(marking->IsMarking());
+  marking->StartBlackAllocationForTesting();
+  {
+    AlwaysAllocateScope always_allocate(CcTest::i_isolate());
+    v8::HandleScope inner(CcTest::isolate());
+    isolate->factory()->NewFixedArray(500, TENURED)->Size();
+  }
+  while (!marking->IsComplete()) {
+    marking->Step(i::MB, i::IncrementalMarking::NO_GC_VIA_STACK_GUARD);
+    if (marking->IsReadyToOverApproximateWeakClosure()) {
+      marking->FinalizeIncrementally();
+    }
+  }
+  CHECK(marking->IsComplete());
+  intptr_t size_before = heap->SizeOfObjects();
+  CcTest::heap()->CollectAllGarbage();
+  intptr_t size_after = heap->SizeOfObjects();
+  // Live size does not increase after garbage collection.
+  CHECK_LE(size_after, size_before);
+}
+
+TEST(Regress618958) {
+  CcTest::InitializeVM();
+  v8::HandleScope scope(CcTest::isolate());
+  Heap* heap = CcTest::heap();
+  bool isolate_is_locked = true;
+  heap->update_external_memory(100 * MB);
+  int mark_sweep_count_before = heap->ms_count();
+  heap->MemoryPressureNotification(MemoryPressureLevel::kCritical,
+                                   isolate_is_locked);
+  int mark_sweep_count_after = heap->ms_count();
+  int mark_sweeps_performed = mark_sweep_count_after - mark_sweep_count_before;
+  // The memory pressuer handler either performed two GCs or performed one and
+  // started incremental marking.
+  CHECK(mark_sweeps_performed == 2 ||
+        (mark_sweeps_performed == 1 &&
+         !heap->incremental_marking()->IsStopped()));
+}
+
 }  // namespace internal
 }  // namespace v8
diff --git a/test/cctest/heap/test-incremental-marking.cc b/test/cctest/heap/test-incremental-marking.cc
index 74cbf2c..59697a9 100644
--- a/test/cctest/heap/test-incremental-marking.cc
+++ b/test/cctest/heap/test-incremental-marking.cc
@@ -19,8 +19,7 @@
 #include "src/full-codegen/full-codegen.h"
 #include "src/global-handles.h"
 #include "test/cctest/cctest.h"
-#include "test/cctest/heap/utils-inl.h"
-
+#include "test/cctest/heap/heap-utils.h"
 
 using v8::IdleTask;
 using v8::Task;
@@ -120,7 +119,7 @@
   v8::Platform* old_platform = i::V8::GetCurrentPlatform();
   MockPlatform platform(old_platform);
   i::V8::SetPlatformForTesting(&platform);
-  SimulateFullSpace(CcTest::heap()->old_space());
+  i::heap::SimulateFullSpace(CcTest::heap()->old_space());
   i::IncrementalMarking* marking = CcTest::heap()->incremental_marking();
   marking->Stop();
   marking->Start();
@@ -145,7 +144,7 @@
   v8::Platform* old_platform = i::V8::GetCurrentPlatform();
   MockPlatform platform(old_platform);
   i::V8::SetPlatformForTesting(&platform);
-  SimulateFullSpace(CcTest::heap()->old_space());
+  i::heap::SimulateFullSpace(CcTest::heap()->old_space());
   CcTest::heap()->CollectAllGarbage();
   i::IncrementalMarking* marking = CcTest::heap()->incremental_marking();
   marking->Stop();
@@ -171,7 +170,7 @@
   v8::Platform* old_platform = i::V8::GetCurrentPlatform();
   MockPlatform platform(old_platform);
   i::V8::SetPlatformForTesting(&platform);
-  SimulateFullSpace(CcTest::heap()->old_space());
+  i::heap::SimulateFullSpace(CcTest::heap()->old_space());
   i::IncrementalMarking* marking = CcTest::heap()->incremental_marking();
   marking->Stop();
   marking->Start();
diff --git a/test/cctest/heap/test-mark-compact.cc b/test/cctest/heap/test-mark-compact.cc
index cfcf149..1e5d30d 100644
--- a/test/cctest/heap/test-mark-compact.cc
+++ b/test/cctest/heap/test-mark-compact.cc
@@ -43,8 +43,7 @@
 #include "src/global-handles.h"
 #include "test/cctest/cctest.h"
 #include "test/cctest/heap/heap-tester.h"
-#include "test/cctest/heap/utils-inl.h"
-
+#include "test/cctest/heap/heap-utils.h"
 
 using namespace v8::internal;
 using v8::Just;
@@ -76,58 +75,49 @@
   DeleteArray(mem);
 }
 
-
-HEAP_TEST(Promotion) {
+TEST(Promotion) {
   CcTest::InitializeVM();
-  Heap* heap = CcTest::heap();
-  heap->ConfigureHeap(1, 1, 1, 0);
+  Isolate* isolate = CcTest::i_isolate();
+  {
+    v8::HandleScope sc(CcTest::isolate());
+    Heap* heap = isolate->heap();
 
-  v8::HandleScope sc(CcTest::isolate());
+    heap::SealCurrentObjects(heap);
 
-  // Allocate a fixed array in the new space.
-  int array_length =
-      (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) /
-      (4 * kPointerSize);
-  Object* obj = heap->AllocateFixedArray(array_length).ToObjectChecked();
-  Handle<FixedArray> array(FixedArray::cast(obj));
+    int array_length =
+        heap::FixedArrayLenFromSize(Page::kMaxRegularHeapObjectSize);
+    Handle<FixedArray> array = isolate->factory()->NewFixedArray(array_length);
 
-  // Array should be in the new space.
-  CHECK(heap->InSpace(*array, NEW_SPACE));
-
-  // Call mark compact GC, so array becomes an old object.
-  heap->CollectAllGarbage();
-  heap->CollectAllGarbage();
-
-  // Array now sits in the old space
-  CHECK(heap->InSpace(*array, OLD_SPACE));
+    // Array should be in the new space.
+    CHECK(heap->InSpace(*array, NEW_SPACE));
+    heap->CollectAllGarbage();
+    heap->CollectAllGarbage();
+    CHECK(heap->InSpace(*array, OLD_SPACE));
+  }
 }
 
-
 HEAP_TEST(NoPromotion) {
   CcTest::InitializeVM();
-  Heap* heap = CcTest::heap();
-  heap->ConfigureHeap(1, 1, 1, 0);
+  Isolate* isolate = CcTest::i_isolate();
+  {
+    v8::HandleScope sc(CcTest::isolate());
+    Heap* heap = isolate->heap();
 
-  v8::HandleScope sc(CcTest::isolate());
+    heap::SealCurrentObjects(heap);
 
-  // Allocate a big fixed array in the new space.
-  int array_length =
-      (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) /
-      (2 * kPointerSize);
-  Object* obj = heap->AllocateFixedArray(array_length).ToObjectChecked();
-  Handle<FixedArray> array(FixedArray::cast(obj));
+    int array_length =
+        heap::FixedArrayLenFromSize(Page::kMaxRegularHeapObjectSize);
+    Handle<FixedArray> array = isolate->factory()->NewFixedArray(array_length);
 
-  // Array should be in the new space.
-  CHECK(heap->InSpace(*array, NEW_SPACE));
-
-  // Simulate a full old space to make promotion fail.
-  SimulateFullSpace(heap->old_space());
-
-  // Call mark compact GC, and it should pass.
-  heap->CollectGarbage(OLD_SPACE);
+    heap->set_force_oom(true);
+    // Array should be in the new space.
+    CHECK(heap->InSpace(*array, NEW_SPACE));
+    heap->CollectAllGarbage();
+    heap->CollectAllGarbage();
+    CHECK(heap->InSpace(*array, NEW_SPACE));
+  }
 }
 
-
 HEAP_TEST(MarkCompactCollector) {
   FLAG_incremental_marking = false;
   FLAG_retain_maps_for_n_gc = 0;
@@ -236,8 +226,7 @@
 
 
 static int NumberOfWeakCalls = 0;
-static void WeakPointerCallback(
-    const v8::WeakCallbackData<v8::Value, void>& data) {
+static void WeakPointerCallback(const v8::WeakCallbackInfo<void>& data) {
   std::pair<v8::Persistent<v8::Value>*, int>* p =
       reinterpret_cast<std::pair<v8::Persistent<v8::Value>*, int>*>(
           data.GetParameter());
@@ -262,17 +251,17 @@
   Handle<Object> g1c1 =
       global_handles->Create(heap->AllocateFixedArray(1).ToObjectChecked());
   std::pair<Handle<Object>*, int> g1s1_and_id(&g1s1, 1234);
-  GlobalHandles::MakeWeak(g1s1.location(),
-                          reinterpret_cast<void*>(&g1s1_and_id),
-                          &WeakPointerCallback);
+  GlobalHandles::MakeWeak(
+      g1s1.location(), reinterpret_cast<void*>(&g1s1_and_id),
+      &WeakPointerCallback, v8::WeakCallbackType::kParameter);
   std::pair<Handle<Object>*, int> g1s2_and_id(&g1s2, 1234);
-  GlobalHandles::MakeWeak(g1s2.location(),
-                          reinterpret_cast<void*>(&g1s2_and_id),
-                          &WeakPointerCallback);
+  GlobalHandles::MakeWeak(
+      g1s2.location(), reinterpret_cast<void*>(&g1s2_and_id),
+      &WeakPointerCallback, v8::WeakCallbackType::kParameter);
   std::pair<Handle<Object>*, int> g1c1_and_id(&g1c1, 1234);
-  GlobalHandles::MakeWeak(g1c1.location(),
-                          reinterpret_cast<void*>(&g1c1_and_id),
-                          &WeakPointerCallback);
+  GlobalHandles::MakeWeak(
+      g1c1.location(), reinterpret_cast<void*>(&g1c1_and_id),
+      &WeakPointerCallback, v8::WeakCallbackType::kParameter);
 
   Handle<Object> g2s1 =
       global_handles->Create(heap->AllocateFixedArray(1).ToObjectChecked());
@@ -281,17 +270,17 @@
   Handle<Object> g2c1 =
     global_handles->Create(heap->AllocateFixedArray(1).ToObjectChecked());
   std::pair<Handle<Object>*, int> g2s1_and_id(&g2s1, 1234);
-  GlobalHandles::MakeWeak(g2s1.location(),
-                          reinterpret_cast<void*>(&g2s1_and_id),
-                          &WeakPointerCallback);
+  GlobalHandles::MakeWeak(
+      g2s1.location(), reinterpret_cast<void*>(&g2s1_and_id),
+      &WeakPointerCallback, v8::WeakCallbackType::kParameter);
   std::pair<Handle<Object>*, int> g2s2_and_id(&g2s2, 1234);
-  GlobalHandles::MakeWeak(g2s2.location(),
-                          reinterpret_cast<void*>(&g2s2_and_id),
-                          &WeakPointerCallback);
+  GlobalHandles::MakeWeak(
+      g2s2.location(), reinterpret_cast<void*>(&g2s2_and_id),
+      &WeakPointerCallback, v8::WeakCallbackType::kParameter);
   std::pair<Handle<Object>*, int> g2c1_and_id(&g2c1, 1234);
-  GlobalHandles::MakeWeak(g2c1.location(),
-                          reinterpret_cast<void*>(&g2c1_and_id),
-                          &WeakPointerCallback);
+  GlobalHandles::MakeWeak(
+      g2c1.location(), reinterpret_cast<void*>(&g2c1_and_id),
+      &WeakPointerCallback, v8::WeakCallbackType::kParameter);
 
   Handle<Object> root = global_handles->Create(*g1s1);  // make a root.
 
@@ -317,9 +306,9 @@
 
   // Weaken the root.
   std::pair<Handle<Object>*, int> root_and_id(&root, 1234);
-  GlobalHandles::MakeWeak(root.location(),
-                          reinterpret_cast<void*>(&root_and_id),
-                          &WeakPointerCallback);
+  GlobalHandles::MakeWeak(
+      root.location(), reinterpret_cast<void*>(&root_and_id),
+      &WeakPointerCallback, v8::WeakCallbackType::kParameter);
   // But make children strong roots---all the objects (except for children)
   // should be collectable now.
   global_handles->ClearWeakness(g1c1.location());
@@ -343,12 +332,12 @@
   CHECK_EQ(5, NumberOfWeakCalls);
 
   // And now make children weak again and collect them.
-  GlobalHandles::MakeWeak(g1c1.location(),
-                          reinterpret_cast<void*>(&g1c1_and_id),
-                          &WeakPointerCallback);
-  GlobalHandles::MakeWeak(g2c1.location(),
-                          reinterpret_cast<void*>(&g2c1_and_id),
-                          &WeakPointerCallback);
+  GlobalHandles::MakeWeak(
+      g1c1.location(), reinterpret_cast<void*>(&g1c1_and_id),
+      &WeakPointerCallback, v8::WeakCallbackType::kParameter);
+  GlobalHandles::MakeWeak(
+      g2c1.location(), reinterpret_cast<void*>(&g2c1_and_id),
+      &WeakPointerCallback, v8::WeakCallbackType::kParameter);
 
   heap->CollectGarbage(OLD_SPACE);
   CHECK_EQ(7, NumberOfWeakCalls);
diff --git a/test/cctest/heap/test-page-promotion.cc b/test/cctest/heap/test-page-promotion.cc
new file mode 100644
index 0000000..4ec2e2a
--- /dev/null
+++ b/test/cctest/heap/test-page-promotion.cc
@@ -0,0 +1,129 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/heap/array-buffer-tracker.h"
+#include "test/cctest/cctest.h"
+#include "test/cctest/heap/heap-utils.h"
+
+namespace {
+
+v8::Isolate* NewIsolateForPagePromotion() {
+  i::FLAG_page_promotion = true;
+  i::FLAG_page_promotion_threshold = 0;  // %
+  i::FLAG_min_semi_space_size = 8 * (i::Page::kPageSize / i::MB);
+  // We cannot optimize for size as we require a new space with more than one
+  // page.
+  i::FLAG_optimize_for_size = false;
+  // Set max_semi_space_size because it could've been initialized by an
+  // implication of optimize_for_size.
+  i::FLAG_max_semi_space_size = i::FLAG_min_semi_space_size;
+  v8::Isolate::CreateParams create_params;
+  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+  v8::Isolate* isolate = v8::Isolate::New(create_params);
+  return isolate;
+}
+
+}  // namespace
+
+namespace v8 {
+namespace internal {
+
+UNINITIALIZED_TEST(PagePromotion_NewToOld) {
+  v8::Isolate* isolate = NewIsolateForPagePromotion();
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  {
+    v8::Isolate::Scope isolate_scope(isolate);
+    v8::HandleScope handle_scope(isolate);
+    v8::Context::New(isolate)->Enter();
+    Heap* heap = i_isolate->heap();
+
+    std::vector<Handle<FixedArray>> handles;
+    heap::SimulateFullSpace(heap->new_space(), &handles);
+    heap->CollectGarbage(NEW_SPACE);
+    CHECK_GT(handles.size(), 0u);
+    // First object in handle should be on the first page.
+    Handle<FixedArray> first_object = handles.front();
+    Page* first_page = Page::FromAddress(first_object->address());
+    // To perform a sanity check on live bytes we need to mark the heap.
+    heap::SimulateIncrementalMarking(heap, true);
+    // Sanity check that the page meets the requirements for promotion.
+    const int threshold_bytes =
+        FLAG_page_promotion_threshold * Page::kAllocatableMemory / 100;
+    CHECK_GE(first_page->LiveBytes(), threshold_bytes);
+
+    // Actual checks: The page is in new space first, but is moved to old space
+    // during a full GC.
+    CHECK(heap->new_space()->ContainsSlow(first_page->address()));
+    CHECK(!heap->old_space()->ContainsSlow(first_page->address()));
+    heap::GcAndSweep(heap, OLD_SPACE);
+    CHECK(!heap->new_space()->ContainsSlow(first_page->address()));
+    CHECK(heap->old_space()->ContainsSlow(first_page->address()));
+  }
+}
+
+UNINITIALIZED_TEST(PagePromotion_NewToNew) {
+  v8::Isolate* isolate = NewIsolateForPagePromotion();
+  Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate);
+  {
+    v8::Isolate::Scope isolate_scope(isolate);
+    v8::HandleScope handle_scope(isolate);
+    v8::Context::New(isolate)->Enter();
+    Heap* heap = i_isolate->heap();
+
+    std::vector<Handle<FixedArray>> handles;
+    heap::SimulateFullSpace(heap->new_space(), &handles);
+    CHECK_GT(handles.size(), 0u);
+    // Last object in handles should definitely be on the last page which does
+    // not contain the age mark.
+    Handle<FixedArray> last_object = handles.back();
+    Page* to_be_promoted_page = Page::FromAddress(last_object->address());
+    CHECK(to_be_promoted_page->Contains(last_object->address()));
+    CHECK(heap->new_space()->ToSpaceContainsSlow(last_object->address()));
+    heap::GcAndSweep(heap, OLD_SPACE);
+    CHECK(heap->new_space()->ToSpaceContainsSlow(last_object->address()));
+    CHECK(to_be_promoted_page->Contains(last_object->address()));
+  }
+}
+
+UNINITIALIZED_TEST(PagePromotion_NewToNewJSArrayBuffer) {
+  // Test makes sure JSArrayBuffer backing stores are still tracked after
+  // new-to-new promotion.
+  v8::Isolate* isolate = NewIsolateForPagePromotion();
+  Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate);
+  {
+    v8::Isolate::Scope isolate_scope(isolate);
+    v8::HandleScope handle_scope(isolate);
+    v8::Context::New(isolate)->Enter();
+    Heap* heap = i_isolate->heap();
+
+    // Fill the current page which potentially contains the age mark.
+    heap::FillCurrentPage(heap->new_space());
+
+    // Allocate a buffer we would like to check against.
+    Handle<JSArrayBuffer> buffer =
+        i_isolate->factory()->NewJSArrayBuffer(SharedFlag::kNotShared);
+    JSArrayBuffer::SetupAllocatingData(buffer, i_isolate, 100);
+    std::vector<Handle<FixedArray>> handles;
+    // Simulate a full space, filling the interesting page with live objects.
+    heap::SimulateFullSpace(heap->new_space(), &handles);
+    CHECK_GT(handles.size(), 0u);
+    // Last object in handles should definitely be on the last page which does
+    // not contain the age mark.
+    Handle<FixedArray> first_object = handles.front();
+    Page* to_be_promoted_page = Page::FromAddress(first_object->address());
+    CHECK(to_be_promoted_page->Contains(first_object->address()));
+    CHECK(to_be_promoted_page->Contains(buffer->address()));
+    CHECK(heap->new_space()->ToSpaceContainsSlow(first_object->address()));
+    CHECK(heap->new_space()->ToSpaceContainsSlow(buffer->address()));
+    heap::GcAndSweep(heap, OLD_SPACE);
+    CHECK(heap->new_space()->ToSpaceContainsSlow(first_object->address()));
+    CHECK(heap->new_space()->ToSpaceContainsSlow(buffer->address()));
+    CHECK(to_be_promoted_page->Contains(first_object->address()));
+    CHECK(to_be_promoted_page->Contains(buffer->address()));
+    CHECK(ArrayBufferTracker::IsTracked(*buffer));
+  }
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/test/cctest/heap/test-spaces.cc b/test/cctest/heap/test-spaces.cc
index a7cf161..2328518 100644
--- a/test/cctest/heap/test-spaces.cc
+++ b/test/cctest/heap/test-spaces.cc
@@ -32,7 +32,6 @@
 #include "src/v8.h"
 #include "test/cctest/cctest.h"
 #include "test/cctest/heap/heap-tester.h"
-#include "test/cctest/heap/utils-inl.h"
 
 namespace v8 {
 namespace internal {
@@ -107,13 +106,12 @@
 class TestMemoryAllocatorScope {
  public:
   TestMemoryAllocatorScope(Isolate* isolate, MemoryAllocator* allocator)
-      : isolate_(isolate),
-        old_allocator_(isolate->memory_allocator_) {
-    isolate->memory_allocator_ = allocator;
+      : isolate_(isolate), old_allocator_(isolate->heap()->memory_allocator()) {
+    isolate->heap()->memory_allocator_ = allocator;
   }
 
   ~TestMemoryAllocatorScope() {
-    isolate_->memory_allocator_ = old_allocator_;
+    isolate_->heap()->memory_allocator_ = old_allocator_;
   }
 
  private:
@@ -129,12 +127,12 @@
  public:
   TestCodeRangeScope(Isolate* isolate, CodeRange* code_range)
       : isolate_(isolate),
-        old_code_range_(isolate->code_range_) {
-    isolate->code_range_ = code_range;
+        old_code_range_(isolate->heap()->memory_allocator()->code_range()) {
+    isolate->heap()->memory_allocator()->code_range_ = code_range;
   }
 
   ~TestCodeRangeScope() {
-    isolate_->code_range_ = old_code_range_;
+    isolate_->heap()->memory_allocator()->code_range_ = old_code_range_;
   }
 
  private:
@@ -153,50 +151,49 @@
                               size_t second_commit_area_size,
                               Executability executable) {
   MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
-  CHECK(memory_allocator->SetUp(heap->MaxReserved(),
-                                heap->MaxExecutableSize()));
-  TestMemoryAllocatorScope test_allocator_scope(isolate, memory_allocator);
-  TestCodeRangeScope test_code_range_scope(isolate, code_range);
+  CHECK(memory_allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize(),
+                                0));
+  {
+    TestMemoryAllocatorScope test_allocator_scope(isolate, memory_allocator);
+    TestCodeRangeScope test_code_range_scope(isolate, code_range);
 
-  size_t header_size = (executable == EXECUTABLE)
-                       ? MemoryAllocator::CodePageGuardStartOffset()
-                       : MemoryChunk::kObjectStartOffset;
-  size_t guard_size = (executable == EXECUTABLE)
-                       ? MemoryAllocator::CodePageGuardSize()
-                       : 0;
+    size_t header_size = (executable == EXECUTABLE)
+                             ? MemoryAllocator::CodePageGuardStartOffset()
+                             : MemoryChunk::kObjectStartOffset;
+    size_t guard_size =
+        (executable == EXECUTABLE) ? MemoryAllocator::CodePageGuardSize() : 0;
 
-  MemoryChunk* memory_chunk = memory_allocator->AllocateChunk(reserve_area_size,
-                                                              commit_area_size,
-                                                              executable,
-                                                              NULL);
-  size_t alignment = code_range != NULL && code_range->valid()
-                         ? MemoryChunk::kAlignment
-                         : base::OS::CommitPageSize();
-  size_t reserved_size =
-      ((executable == EXECUTABLE))
-          ? RoundUp(header_size + guard_size + reserve_area_size + guard_size,
-                    alignment)
-          : RoundUp(header_size + reserve_area_size,
-                    base::OS::CommitPageSize());
-  CHECK(memory_chunk->size() == reserved_size);
-  CHECK(memory_chunk->area_start() < memory_chunk->address() +
-                                     memory_chunk->size());
-  CHECK(memory_chunk->area_end() <= memory_chunk->address() +
-                                    memory_chunk->size());
-  CHECK(static_cast<size_t>(memory_chunk->area_size()) == commit_area_size);
+    MemoryChunk* memory_chunk = memory_allocator->AllocateChunk(
+        reserve_area_size, commit_area_size, executable, NULL);
+    size_t alignment = code_range != NULL && code_range->valid()
+                           ? MemoryChunk::kAlignment
+                           : base::OS::CommitPageSize();
+    size_t reserved_size =
+        ((executable == EXECUTABLE))
+            ? RoundUp(header_size + guard_size + reserve_area_size + guard_size,
+                      alignment)
+            : RoundUp(header_size + reserve_area_size,
+                      base::OS::CommitPageSize());
+    CHECK(memory_chunk->size() == reserved_size);
+    CHECK(memory_chunk->area_start() <
+          memory_chunk->address() + memory_chunk->size());
+    CHECK(memory_chunk->area_end() <=
+          memory_chunk->address() + memory_chunk->size());
+    CHECK(static_cast<size_t>(memory_chunk->area_size()) == commit_area_size);
 
-  Address area_start = memory_chunk->area_start();
+    Address area_start = memory_chunk->area_start();
 
-  memory_chunk->CommitArea(second_commit_area_size);
-  CHECK(area_start == memory_chunk->area_start());
-  CHECK(memory_chunk->area_start() < memory_chunk->address() +
-                                     memory_chunk->size());
-  CHECK(memory_chunk->area_end() <= memory_chunk->address() +
-                                    memory_chunk->size());
-  CHECK(static_cast<size_t>(memory_chunk->area_size()) ==
-      second_commit_area_size);
+    memory_chunk->CommitArea(second_commit_area_size);
+    CHECK(area_start == memory_chunk->area_start());
+    CHECK(memory_chunk->area_start() <
+          memory_chunk->address() + memory_chunk->size());
+    CHECK(memory_chunk->area_end() <=
+          memory_chunk->address() + memory_chunk->size());
+    CHECK(static_cast<size_t>(memory_chunk->area_size()) ==
+          second_commit_area_size);
 
-  memory_allocator->Free(memory_chunk);
+    memory_allocator->Free<MemoryAllocator::kFull>(memory_chunk);
+  }
   memory_allocator->TearDown();
   delete memory_allocator;
 }
@@ -205,36 +202,32 @@
 TEST(Regress3540) {
   Isolate* isolate = CcTest::i_isolate();
   Heap* heap = isolate->heap();
-  const int pageSize = Page::kPageSize;
   MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
-  CHECK(
-      memory_allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize()));
+  CHECK(memory_allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize(),
+                                0));
   TestMemoryAllocatorScope test_allocator_scope(isolate, memory_allocator);
   CodeRange* code_range = new CodeRange(isolate);
-  const size_t code_range_size = 4 * pageSize;
-  if (!code_range->SetUp(
-          code_range_size +
-          RoundUp(v8::base::OS::CommitPageSize() * kReservedCodeRangePages,
-                  MemoryChunk::kAlignment) +
-          v8::internal::MemoryAllocator::CodePageAreaSize())) {
+  size_t code_range_size =
+      kMinimumCodeRangeSize > 0 ? kMinimumCodeRangeSize : 3 * Page::kPageSize;
+  if (!code_range->SetUp(code_range_size)) {
     return;
   }
 
   Address address;
   size_t size;
-  size_t request_size = code_range_size - 2 * pageSize;
+  size_t request_size = code_range_size - Page::kPageSize;
   address = code_range->AllocateRawMemory(
       request_size, request_size - (2 * MemoryAllocator::CodePageGuardSize()),
       &size);
-  CHECK(address != NULL);
+  CHECK_NOT_NULL(address);
 
   Address null_address;
   size_t null_size;
-  request_size = code_range_size - pageSize;
+  request_size = code_range_size - Page::kPageSize;
   null_address = code_range->AllocateRawMemory(
       request_size, request_size - (2 * MemoryAllocator::CodePageGuardSize()),
       &null_size);
-  CHECK(null_address == NULL);
+  CHECK_NULL(null_address);
 
   code_range->FreeRawMemory(address, size);
   delete code_range;
@@ -283,8 +276,8 @@
                       NOT_EXECUTABLE);
     delete code_range;
 
-    // Without CodeRange.
-    code_range = NULL;
+    // Without a valid CodeRange, i.e., omitting SetUp.
+    code_range = new CodeRange(isolate);
     VerifyMemoryChunk(isolate,
                       heap,
                       code_range,
@@ -300,6 +293,7 @@
                       initial_commit_area_size,
                       second_commit_area_size,
                       NOT_EXECUTABLE);
+    delete code_range;
   }
 }
 
@@ -310,19 +304,19 @@
 
   MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
   CHECK(memory_allocator != nullptr);
-  CHECK(memory_allocator->SetUp(heap->MaxReserved(),
-                                heap->MaxExecutableSize()));
+  CHECK(memory_allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize(),
+                                0));
   TestMemoryAllocatorScope test_scope(isolate, memory_allocator);
 
   {
     int total_pages = 0;
     OldSpace faked_space(heap, OLD_SPACE, NOT_EXECUTABLE);
-    Page* first_page = memory_allocator->AllocatePage<Page>(
+    Page* first_page = memory_allocator->AllocatePage(
         faked_space.AreaSize(), static_cast<PagedSpace*>(&faked_space),
         NOT_EXECUTABLE);
 
     first_page->InsertAfter(faked_space.anchor()->prev_page());
-    CHECK(first_page->is_valid());
+    CHECK(Page::IsValid(first_page));
     CHECK(first_page->next_page() == faked_space.anchor());
     total_pages++;
 
@@ -331,10 +325,10 @@
     }
 
     // Again, we should get n or n - 1 pages.
-    Page* other = memory_allocator->AllocatePage<Page>(
+    Page* other = memory_allocator->AllocatePage(
         faked_space.AreaSize(), static_cast<PagedSpace*>(&faked_space),
         NOT_EXECUTABLE);
-    CHECK(other->is_valid());
+    CHECK(Page::IsValid(other));
     total_pages++;
     other->InsertAfter(first_page);
     int page_count = 0;
@@ -345,7 +339,7 @@
     CHECK(total_pages == page_count);
 
     Page* second_page = first_page->next_page();
-    CHECK(second_page->is_valid());
+    CHECK(Page::IsValid(second_page));
 
     // OldSpace's destructor will tear down the space and free up all pages.
   }
@@ -358,8 +352,8 @@
   Isolate* isolate = CcTest::i_isolate();
   Heap* heap = isolate->heap();
   MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
-  CHECK(memory_allocator->SetUp(heap->MaxReserved(),
-                                heap->MaxExecutableSize()));
+  CHECK(memory_allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize(),
+                                0));
   TestMemoryAllocatorScope test_scope(isolate, memory_allocator);
 
   NewSpace new_space(heap);
@@ -385,8 +379,8 @@
   Isolate* isolate = CcTest::i_isolate();
   Heap* heap = isolate->heap();
   MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
-  CHECK(memory_allocator->SetUp(heap->MaxReserved(),
-                                heap->MaxExecutableSize()));
+  CHECK(memory_allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize(),
+                                0));
   TestMemoryAllocatorScope test_scope(isolate, memory_allocator);
 
   OldSpace* s = new OldSpace(heap, OLD_SPACE, NOT_EXECUTABLE);
@@ -409,8 +403,8 @@
   Heap* heap = isolate->heap();
   MemoryAllocator* memory_allocator = new MemoryAllocator(isolate);
   CHECK(memory_allocator != nullptr);
-  CHECK(
-      memory_allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize()));
+  CHECK(memory_allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize(),
+                                0));
   TestMemoryAllocatorScope test_scope(isolate, memory_allocator);
 
   CompactionSpace* compaction_space =
@@ -491,7 +485,15 @@
   CcTest::InitializeVM();
   Isolate* isolate = CcTest::i_isolate();
   if (!isolate->snapshot_available()) return;
-  if (Snapshot::EmbedsScript(isolate)) return;
+  HandleScope scope(isolate);
+  v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
+  // Skip this test on the custom snapshot builder.
+  if (!CcTest::global()
+           ->Get(context, v8_str("assertEquals"))
+           .ToLocalChecked()
+           ->IsUndefined()) {
+    return;
+  }
 
   // If this test fails due to enabling experimental natives that are not part
   // of the snapshot, we may need to adjust CalculateFirstPageSizes.
@@ -504,7 +506,6 @@
   }
 
   // Executing the empty script gets by with one page per space.
-  HandleScope scope(isolate);
   CompileRun("/*empty*/");
   for (int i = FIRST_PAGED_SPACE; i <= LAST_PAGED_SPACE; i++) {
     // Debug code can be very large, so skip CODE_SPACE if we are generating it.
diff --git a/test/cctest/heap/utils-inl.h b/test/cctest/heap/utils-inl.h
deleted file mode 100644
index 56033c1..0000000
--- a/test/cctest/heap/utils-inl.h
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef HEAP_UTILS_H_
-#define HEAP_UTILS_H_
-
-#include "src/factory.h"
-#include "src/heap/heap-inl.h"
-#include "src/heap/incremental-marking.h"
-#include "src/heap/mark-compact.h"
-#include "src/isolate.h"
-
-
-namespace v8 {
-namespace internal {
-
-static int LenFromSize(int size) {
-  return (size - FixedArray::kHeaderSize) / kPointerSize;
-}
-
-
-static inline std::vector<Handle<FixedArray>> CreatePadding(
-    Heap* heap, int padding_size, PretenureFlag tenure,
-    int object_size = Page::kMaxRegularHeapObjectSize) {
-  std::vector<Handle<FixedArray>> handles;
-  Isolate* isolate = heap->isolate();
-  int allocate_memory;
-  int length;
-  int free_memory = padding_size;
-  if (tenure == i::TENURED) {
-    heap->old_space()->EmptyAllocationInfo();
-    int overall_free_memory = static_cast<int>(heap->old_space()->Available());
-    CHECK(padding_size <= overall_free_memory || overall_free_memory == 0);
-  } else {
-    heap->new_space()->DisableInlineAllocationSteps();
-    int overall_free_memory =
-        static_cast<int>(*heap->new_space()->allocation_limit_address() -
-                         *heap->new_space()->allocation_top_address());
-    CHECK(padding_size <= overall_free_memory || overall_free_memory == 0);
-  }
-  while (free_memory > 0) {
-    if (free_memory > object_size) {
-      allocate_memory = object_size;
-      length = LenFromSize(allocate_memory);
-    } else {
-      allocate_memory = free_memory;
-      length = LenFromSize(allocate_memory);
-      if (length <= 0) {
-        // Not enough room to create another fixed array. Let's create a filler.
-        heap->CreateFillerObjectAt(*heap->old_space()->allocation_top_address(),
-                                   free_memory, ClearRecordedSlots::kNo);
-        break;
-      }
-    }
-    handles.push_back(isolate->factory()->NewFixedArray(length, tenure));
-    CHECK((tenure == NOT_TENURED && heap->InNewSpace(*handles.back())) ||
-          (tenure == TENURED && heap->InOldSpace(*handles.back())));
-    free_memory -= allocate_memory;
-  }
-  return handles;
-}
-
-
-// Helper function that simulates a full new-space in the heap.
-static inline bool FillUpOnePage(v8::internal::NewSpace* space) {
-  space->DisableInlineAllocationSteps();
-  int space_remaining = static_cast<int>(*space->allocation_limit_address() -
-                                         *space->allocation_top_address());
-  if (space_remaining == 0) return false;
-  CreatePadding(space->heap(), space_remaining, i::NOT_TENURED);
-  return true;
-}
-
-
-// Helper function that simulates a fill new-space in the heap.
-static inline void AllocateAllButNBytes(v8::internal::NewSpace* space,
-                                        int extra_bytes) {
-  space->DisableInlineAllocationSteps();
-  int space_remaining = static_cast<int>(*space->allocation_limit_address() -
-                                         *space->allocation_top_address());
-  CHECK(space_remaining >= extra_bytes);
-  int new_linear_size = space_remaining - extra_bytes;
-  if (new_linear_size == 0) return;
-  CreatePadding(space->heap(), new_linear_size, i::NOT_TENURED);
-}
-
-
-static inline void FillCurrentPage(v8::internal::NewSpace* space) {
-  AllocateAllButNBytes(space, 0);
-}
-
-
-static inline void SimulateFullSpace(v8::internal::NewSpace* space) {
-  FillCurrentPage(space);
-  while (FillUpOnePage(space)) {
-  }
-}
-
-
-// Helper function that simulates a full old-space in the heap.
-static inline void SimulateFullSpace(v8::internal::PagedSpace* space) {
-  space->EmptyAllocationInfo();
-  space->ResetFreeList();
-  space->ClearStats();
-}
-
-
-// Helper function that simulates many incremental marking steps until
-// marking is completed.
-static inline void SimulateIncrementalMarking(i::Heap* heap,
-                                              bool force_completion = true) {
-  i::MarkCompactCollector* collector = heap->mark_compact_collector();
-  i::IncrementalMarking* marking = heap->incremental_marking();
-  if (collector->sweeping_in_progress()) {
-    collector->EnsureSweepingCompleted();
-  }
-  CHECK(marking->IsMarking() || marking->IsStopped());
-  if (marking->IsStopped()) {
-    heap->StartIncrementalMarking();
-  }
-  CHECK(marking->IsMarking());
-  if (!force_completion) return;
-
-  while (!marking->IsComplete()) {
-    marking->Step(i::MB, i::IncrementalMarking::NO_GC_VIA_STACK_GUARD);
-    if (marking->IsReadyToOverApproximateWeakClosure()) {
-      marking->FinalizeIncrementally();
-    }
-  }
-  CHECK(marking->IsComplete());
-}
-
-}  // namespace internal
-}  // namespace v8
-
-#endif  // HEAP_UTILS_H_
diff --git a/test/cctest/interpreter/bytecode-expectations-printer.cc b/test/cctest/interpreter/bytecode-expectations-printer.cc
index bf43b95..83f11c6 100644
--- a/test/cctest/interpreter/bytecode-expectations-printer.cc
+++ b/test/cctest/interpreter/bytecode-expectations-printer.cc
@@ -4,6 +4,7 @@
 
 #include "test/cctest/interpreter/bytecode-expectations-printer.h"
 
+#include <iomanip>
 #include <iostream>
 #include <vector>
 
@@ -18,7 +19,9 @@
 #include "src/interpreter/bytecode-array-iterator.h"
 #include "src/interpreter/bytecode-generator.h"
 #include "src/interpreter/bytecodes.h"
+#include "src/interpreter/interpreter-intrinsics.h"
 #include "src/interpreter/interpreter.h"
+#include "src/interpreter/source-position-table.h"
 
 namespace v8 {
 namespace internal {
@@ -27,6 +30,7 @@
 // static
 const char* const BytecodeExpectationsPrinter::kDefaultTopFunctionName =
     "__genbckexp_wrapper__";
+const char* const BytecodeExpectationsPrinter::kIndent = "  ";
 
 v8::Local<v8::String> BytecodeExpectationsPrinter::V8StringFromUTF8(
     const char* data) const {
@@ -95,18 +99,12 @@
   }
 }
 
-namespace {
-i::Runtime::FunctionId IndexToFunctionId(uint32_t index) {
-  return static_cast<i::Runtime::FunctionId>(index);
-}
-}  // namespace
-
 void BytecodeExpectationsPrinter::PrintBytecodeOperand(
-    std::ostream& stream, const BytecodeArrayIterator& bytecode_iter,
+    std::ostream& stream, const BytecodeArrayIterator& bytecode_iterator,
     const Bytecode& bytecode, int op_index, int parameter_count) const {
   OperandType op_type = Bytecodes::GetOperandType(bytecode, op_index);
   OperandSize op_size = Bytecodes::GetOperandSize(
-      bytecode, op_index, bytecode_iter.current_operand_scale());
+      bytecode, op_index, bytecode_iterator.current_operand_scale());
 
   const char* size_tag;
   switch (op_size) {
@@ -125,7 +123,7 @@
   }
 
   if (Bytecodes::IsRegisterOperandType(op_type)) {
-    Register register_value = bytecode_iter.GetRegisterOperand(op_index);
+    Register register_value = bytecode_iterator.GetRegisterOperand(op_index);
     stream << 'R';
     if (op_size != OperandSize::kByte) stream << size_tag;
     if (register_value.is_new_target()) {
@@ -149,21 +147,27 @@
 
     switch (op_type) {
       case OperandType::kFlag8:
-        stream << bytecode_iter.GetFlagOperand(op_index);
+        stream << bytecode_iterator.GetFlagOperand(op_index);
         break;
       case OperandType::kIdx:
-        stream << bytecode_iter.GetIndexOperand(op_index);
+        stream << bytecode_iterator.GetIndexOperand(op_index);
         break;
       case OperandType::kImm:
-        stream << bytecode_iter.GetImmediateOperand(op_index);
+        stream << bytecode_iterator.GetImmediateOperand(op_index);
         break;
       case OperandType::kRegCount:
-        stream << bytecode_iter.GetRegisterCountOperand(op_index);
+        stream << bytecode_iterator.GetRegisterCountOperand(op_index);
         break;
       case OperandType::kRuntimeId: {
-        uint32_t operand = bytecode_iter.GetRuntimeIdOperand(op_index);
-        stream << "Runtime::k"
-               << i::Runtime::FunctionForId(IndexToFunctionId(operand))->name;
+        Runtime::FunctionId id =
+            bytecode_iterator.GetRuntimeIdOperand(op_index);
+        stream << "Runtime::k" << i::Runtime::FunctionForId(id)->name;
+        break;
+      }
+      case OperandType::kIntrinsicId: {
+        Runtime::FunctionId id =
+            bytecode_iterator.GetIntrinsicIdOperand(op_index);
+        stream << "Runtime::k" << i::Runtime::FunctionForId(id)->name;
         break;
       }
       default:
@@ -175,10 +179,10 @@
 }
 
 void BytecodeExpectationsPrinter::PrintBytecode(
-    std::ostream& stream, const BytecodeArrayIterator& bytecode_iter,
+    std::ostream& stream, const BytecodeArrayIterator& bytecode_iterator,
     int parameter_count) const {
-  Bytecode bytecode = bytecode_iter.current_bytecode();
-  OperandScale operand_scale = bytecode_iter.current_operand_scale();
+  Bytecode bytecode = bytecode_iterator.current_bytecode();
+  OperandScale operand_scale = bytecode_iterator.current_operand_scale();
   if (Bytecodes::OperandScaleRequiresPrefixBytecode(operand_scale)) {
     Bytecode prefix = Bytecodes::OperandScaleToPrefixBytecode(operand_scale);
     stream << "B(" << Bytecodes::ToString(prefix) << "), ";
@@ -187,11 +191,30 @@
   int operands_count = Bytecodes::NumberOfOperands(bytecode);
   for (int op_index = 0; op_index < operands_count; ++op_index) {
     stream << ", ";
-    PrintBytecodeOperand(stream, bytecode_iter, bytecode, op_index,
+    PrintBytecodeOperand(stream, bytecode_iterator, bytecode, op_index,
                          parameter_count);
   }
 }
 
+void BytecodeExpectationsPrinter::PrintSourcePosition(
+    std::ostream& stream, SourcePositionTableIterator& source_iterator,
+    int bytecode_offset) const {
+  static const size_t kPositionWidth = 4;
+  if (!source_iterator.done() &&
+      source_iterator.bytecode_offset() == bytecode_offset) {
+    stream << "/* " << std::setw(kPositionWidth)
+           << source_iterator.source_position();
+    if (source_iterator.is_statement()) {
+      stream << " S> */ ";
+    } else {
+      stream << " E> */ ";
+    }
+    source_iterator.Advance();
+  } else {
+    stream << "   " << std::setw(kPositionWidth) << ' ' << "       ";
+  }
+}
+
 void BytecodeExpectationsPrinter::PrintV8String(std::ostream& stream,
                                                 i::String* string) const {
   stream << '"';
@@ -246,10 +269,15 @@
     std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const {
   stream << "bytecode array length: " << bytecode_array->length()
          << "\nbytecodes: [\n";
-  BytecodeArrayIterator bytecode_iter(bytecode_array);
-  for (; !bytecode_iter.done(); bytecode_iter.Advance()) {
-    stream << "  ";
-    PrintBytecode(stream, bytecode_iter, bytecode_array->parameter_count());
+
+  SourcePositionTableIterator source_iterator(
+      bytecode_array->source_position_table());
+  BytecodeArrayIterator bytecode_iterator(bytecode_array);
+  for (; !bytecode_iterator.done(); bytecode_iterator.Advance()) {
+    stream << kIndent;
+    PrintSourcePosition(stream, source_iterator,
+                        bytecode_iterator.current_offset());
+    PrintBytecode(stream, bytecode_iterator, bytecode_array->parameter_count());
     stream << ",\n";
   }
   stream << "]\n";
@@ -261,7 +289,7 @@
   int num_constants = constant_pool->length();
   if (num_constants > 0) {
     for (int i = 0; i < num_constants; ++i) {
-      stream << "  ";
+      stream << kIndent;
       PrintConstant(stream, i::FixedArray::get(constant_pool, i, i_isolate()));
       stream << ",\n";
     }
@@ -275,7 +303,7 @@
   std::stringstream body_stream(body);
   std::string body_line;
   while (std::getline(body_stream, body_line)) {
-    stream << "  ";
+    stream << kIndent;
     PrintEscapedString(stream, body_line);
     stream << '\n';
   }
diff --git a/test/cctest/interpreter/bytecode-expectations-printer.h b/test/cctest/interpreter/bytecode-expectations-printer.h
index 0fcead5..32b8ff4 100644
--- a/test/cctest/interpreter/bytecode-expectations-printer.h
+++ b/test/cctest/interpreter/bytecode-expectations-printer.h
@@ -20,6 +20,7 @@
 namespace interpreter {
 
 class BytecodeArrayIterator;
+class SourcePositionTableIterator;
 
 class BytecodeExpectationsPrinter final {
  public:
@@ -65,12 +66,15 @@
   void PrintEscapedString(std::ostream& stream,  // NOLINT
                           const std::string& string) const;
   void PrintBytecodeOperand(std::ostream& stream,  // NOLINT
-                            const BytecodeArrayIterator& bytecode_iter,
+                            const BytecodeArrayIterator& bytecode_iterator,
                             const Bytecode& bytecode, int op_index,
                             int parameter_count) const;
   void PrintBytecode(std::ostream& stream,  // NOLINT
-                     const BytecodeArrayIterator& bytecode_iter,
+                     const BytecodeArrayIterator& bytecode_iterator,
                      int parameter_count) const;
+  void PrintSourcePosition(std::ostream& stream,  // NOLINT
+                           SourcePositionTableIterator& source_iterator,
+                           int bytecode_offset) const;
   void PrintV8String(std::ostream& stream,  // NOLINT
                      i::String* string) const;
   void PrintConstant(std::ostream& stream,  // NOLINT
@@ -111,6 +115,7 @@
   std::string test_function_name_;
 
   static const char* const kDefaultTopFunctionName;
+  static const char* const kIndent;
 };
 
 }  // namespace interpreter
diff --git a/test/cctest/interpreter/bytecode_expectations/ArrayLiterals.golden b/test/cctest/interpreter/bytecode_expectations/ArrayLiterals.golden
index 4c9753f..6bde246 100644
--- a/test/cctest/interpreter/bytecode_expectations/ArrayLiterals.golden
+++ b/test/cctest/interpreter/bytecode_expectations/ArrayLiterals.golden
@@ -15,9 +15,9 @@
 parameter count: 1
 bytecode array length: 6
 bytecodes: [
-  B(StackCheck),
-  B(CreateArrayLiteral), U8(0), U8(0), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(3),
+  /*   51 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -29,28 +29,26 @@
 snippet: "
   var a = 1; return [ a, a + 1 ];
 "
-frame size: 4
+frame size: 3
 parameter count: 1
-bytecode array length: 39
+bytecode array length: 35
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(CreateArrayLiteral), U8(0), U8(0), U8(3),
-  B(Star), R(2),
-  B(LdaZero),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(KeyedStoreICSloppy), R(2), R(1), U8(1),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Star), R(3),
-  B(LdaSmi), U8(1),
-  B(Add), R(3),
-  B(KeyedStoreICSloppy), R(2), R(1), U8(1),
-  B(Ldar), R(2),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(3),
+                B(Star), R(2),
+                B(LdaZero),
+                B(Star), R(1),
+                B(Ldar), R(0),
+  /*   54 E> */ B(StaKeyedPropertySloppy), R(2), R(1), U8(1),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(1),
+  /*   57 E> */ B(Add), R(0),
+                B(StaKeyedPropertySloppy), R(2), R(1), U8(1),
+                B(Ldar), R(2),
+  /*   66 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -66,9 +64,9 @@
 parameter count: 1
 bytecode array length: 6
 bytecodes: [
-  B(StackCheck),
-  B(CreateArrayLiteral), U8(0), U8(2), U8(2),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(CreateArrayLiteral), U8(0), U8(2), U8(2),
+  /*   62 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -80,40 +78,38 @@
 snippet: "
   var a = 1; return [ [ a, 2 ], [ a + 2 ] ];
 "
-frame size: 6
+frame size: 5
 parameter count: 1
-bytecode array length: 69
+bytecode array length: 65
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(CreateArrayLiteral), U8(0), U8(2), U8(2),
-  B(Star), R(2),
-  B(LdaZero),
-  B(Star), R(1),
-  B(CreateArrayLiteral), U8(1), U8(0), U8(3),
-  B(Star), R(4),
-  B(LdaZero),
-  B(Star), R(3),
-  B(Ldar), R(0),
-  B(KeyedStoreICSloppy), R(4), R(3), U8(1),
-  B(Ldar), R(4),
-  B(KeyedStoreICSloppy), R(2), R(1), U8(5),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(CreateArrayLiteral), U8(2), U8(1), U8(3),
-  B(Star), R(4),
-  B(LdaZero),
-  B(Star), R(3),
-  B(Ldar), R(0),
-  B(Star), R(5),
-  B(LdaSmi), U8(2),
-  B(Add), R(5),
-  B(KeyedStoreICSloppy), R(4), R(3), U8(3),
-  B(Ldar), R(4),
-  B(KeyedStoreICSloppy), R(2), R(1), U8(5),
-  B(Ldar), R(2),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(CreateArrayLiteral), U8(0), U8(2), U8(2),
+                B(Star), R(2),
+                B(LdaZero),
+                B(Star), R(1),
+                B(CreateArrayLiteral), U8(1), U8(0), U8(3),
+                B(Star), R(4),
+                B(LdaZero),
+                B(Star), R(3),
+                B(Ldar), R(0),
+  /*   56 E> */ B(StaKeyedPropertySloppy), R(4), R(3), U8(1),
+                B(Ldar), R(4),
+                B(StaKeyedPropertySloppy), R(2), R(1), U8(5),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(CreateArrayLiteral), U8(2), U8(1), U8(3),
+                B(Star), R(4),
+                B(LdaZero),
+                B(Star), R(3),
+                B(LdaSmi), U8(2),
+  /*   66 E> */ B(Add), R(0),
+                B(StaKeyedPropertySloppy), R(4), R(3), U8(3),
+                B(Ldar), R(4),
+                B(StaKeyedPropertySloppy), R(2), R(1), U8(5),
+                B(Ldar), R(2),
+  /*   77 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/ArrayLiteralsWide.golden b/test/cctest/interpreter/bytecode_expectations/ArrayLiteralsWide.golden
index 2077b79..9f9a251 100644
--- a/test/cctest/interpreter/bytecode_expectations/ArrayLiteralsWide.golden
+++ b/test/cctest/interpreter/bytecode_expectations/ArrayLiteralsWide.golden
@@ -272,521 +272,521 @@
 parameter count: 1
 bytecode array length: 1033
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(LdaConstant), U8(1),
-  B(Star), R(0),
-  B(LdaConstant), U8(2),
-  B(Star), R(0),
-  B(LdaConstant), U8(3),
-  B(Star), R(0),
-  B(LdaConstant), U8(4),
-  B(Star), R(0),
-  B(LdaConstant), U8(5),
-  B(Star), R(0),
-  B(LdaConstant), U8(6),
-  B(Star), R(0),
-  B(LdaConstant), U8(7),
-  B(Star), R(0),
-  B(LdaConstant), U8(8),
-  B(Star), R(0),
-  B(LdaConstant), U8(9),
-  B(Star), R(0),
-  B(LdaConstant), U8(10),
-  B(Star), R(0),
-  B(LdaConstant), U8(11),
-  B(Star), R(0),
-  B(LdaConstant), U8(12),
-  B(Star), R(0),
-  B(LdaConstant), U8(13),
-  B(Star), R(0),
-  B(LdaConstant), U8(14),
-  B(Star), R(0),
-  B(LdaConstant), U8(15),
-  B(Star), R(0),
-  B(LdaConstant), U8(16),
-  B(Star), R(0),
-  B(LdaConstant), U8(17),
-  B(Star), R(0),
-  B(LdaConstant), U8(18),
-  B(Star), R(0),
-  B(LdaConstant), U8(19),
-  B(Star), R(0),
-  B(LdaConstant), U8(20),
-  B(Star), R(0),
-  B(LdaConstant), U8(21),
-  B(Star), R(0),
-  B(LdaConstant), U8(22),
-  B(Star), R(0),
-  B(LdaConstant), U8(23),
-  B(Star), R(0),
-  B(LdaConstant), U8(24),
-  B(Star), R(0),
-  B(LdaConstant), U8(25),
-  B(Star), R(0),
-  B(LdaConstant), U8(26),
-  B(Star), R(0),
-  B(LdaConstant), U8(27),
-  B(Star), R(0),
-  B(LdaConstant), U8(28),
-  B(Star), R(0),
-  B(LdaConstant), U8(29),
-  B(Star), R(0),
-  B(LdaConstant), U8(30),
-  B(Star), R(0),
-  B(LdaConstant), U8(31),
-  B(Star), R(0),
-  B(LdaConstant), U8(32),
-  B(Star), R(0),
-  B(LdaConstant), U8(33),
-  B(Star), R(0),
-  B(LdaConstant), U8(34),
-  B(Star), R(0),
-  B(LdaConstant), U8(35),
-  B(Star), R(0),
-  B(LdaConstant), U8(36),
-  B(Star), R(0),
-  B(LdaConstant), U8(37),
-  B(Star), R(0),
-  B(LdaConstant), U8(38),
-  B(Star), R(0),
-  B(LdaConstant), U8(39),
-  B(Star), R(0),
-  B(LdaConstant), U8(40),
-  B(Star), R(0),
-  B(LdaConstant), U8(41),
-  B(Star), R(0),
-  B(LdaConstant), U8(42),
-  B(Star), R(0),
-  B(LdaConstant), U8(43),
-  B(Star), R(0),
-  B(LdaConstant), U8(44),
-  B(Star), R(0),
-  B(LdaConstant), U8(45),
-  B(Star), R(0),
-  B(LdaConstant), U8(46),
-  B(Star), R(0),
-  B(LdaConstant), U8(47),
-  B(Star), R(0),
-  B(LdaConstant), U8(48),
-  B(Star), R(0),
-  B(LdaConstant), U8(49),
-  B(Star), R(0),
-  B(LdaConstant), U8(50),
-  B(Star), R(0),
-  B(LdaConstant), U8(51),
-  B(Star), R(0),
-  B(LdaConstant), U8(52),
-  B(Star), R(0),
-  B(LdaConstant), U8(53),
-  B(Star), R(0),
-  B(LdaConstant), U8(54),
-  B(Star), R(0),
-  B(LdaConstant), U8(55),
-  B(Star), R(0),
-  B(LdaConstant), U8(56),
-  B(Star), R(0),
-  B(LdaConstant), U8(57),
-  B(Star), R(0),
-  B(LdaConstant), U8(58),
-  B(Star), R(0),
-  B(LdaConstant), U8(59),
-  B(Star), R(0),
-  B(LdaConstant), U8(60),
-  B(Star), R(0),
-  B(LdaConstant), U8(61),
-  B(Star), R(0),
-  B(LdaConstant), U8(62),
-  B(Star), R(0),
-  B(LdaConstant), U8(63),
-  B(Star), R(0),
-  B(LdaConstant), U8(64),
-  B(Star), R(0),
-  B(LdaConstant), U8(65),
-  B(Star), R(0),
-  B(LdaConstant), U8(66),
-  B(Star), R(0),
-  B(LdaConstant), U8(67),
-  B(Star), R(0),
-  B(LdaConstant), U8(68),
-  B(Star), R(0),
-  B(LdaConstant), U8(69),
-  B(Star), R(0),
-  B(LdaConstant), U8(70),
-  B(Star), R(0),
-  B(LdaConstant), U8(71),
-  B(Star), R(0),
-  B(LdaConstant), U8(72),
-  B(Star), R(0),
-  B(LdaConstant), U8(73),
-  B(Star), R(0),
-  B(LdaConstant), U8(74),
-  B(Star), R(0),
-  B(LdaConstant), U8(75),
-  B(Star), R(0),
-  B(LdaConstant), U8(76),
-  B(Star), R(0),
-  B(LdaConstant), U8(77),
-  B(Star), R(0),
-  B(LdaConstant), U8(78),
-  B(Star), R(0),
-  B(LdaConstant), U8(79),
-  B(Star), R(0),
-  B(LdaConstant), U8(80),
-  B(Star), R(0),
-  B(LdaConstant), U8(81),
-  B(Star), R(0),
-  B(LdaConstant), U8(82),
-  B(Star), R(0),
-  B(LdaConstant), U8(83),
-  B(Star), R(0),
-  B(LdaConstant), U8(84),
-  B(Star), R(0),
-  B(LdaConstant), U8(85),
-  B(Star), R(0),
-  B(LdaConstant), U8(86),
-  B(Star), R(0),
-  B(LdaConstant), U8(87),
-  B(Star), R(0),
-  B(LdaConstant), U8(88),
-  B(Star), R(0),
-  B(LdaConstant), U8(89),
-  B(Star), R(0),
-  B(LdaConstant), U8(90),
-  B(Star), R(0),
-  B(LdaConstant), U8(91),
-  B(Star), R(0),
-  B(LdaConstant), U8(92),
-  B(Star), R(0),
-  B(LdaConstant), U8(93),
-  B(Star), R(0),
-  B(LdaConstant), U8(94),
-  B(Star), R(0),
-  B(LdaConstant), U8(95),
-  B(Star), R(0),
-  B(LdaConstant), U8(96),
-  B(Star), R(0),
-  B(LdaConstant), U8(97),
-  B(Star), R(0),
-  B(LdaConstant), U8(98),
-  B(Star), R(0),
-  B(LdaConstant), U8(99),
-  B(Star), R(0),
-  B(LdaConstant), U8(100),
-  B(Star), R(0),
-  B(LdaConstant), U8(101),
-  B(Star), R(0),
-  B(LdaConstant), U8(102),
-  B(Star), R(0),
-  B(LdaConstant), U8(103),
-  B(Star), R(0),
-  B(LdaConstant), U8(104),
-  B(Star), R(0),
-  B(LdaConstant), U8(105),
-  B(Star), R(0),
-  B(LdaConstant), U8(106),
-  B(Star), R(0),
-  B(LdaConstant), U8(107),
-  B(Star), R(0),
-  B(LdaConstant), U8(108),
-  B(Star), R(0),
-  B(LdaConstant), U8(109),
-  B(Star), R(0),
-  B(LdaConstant), U8(110),
-  B(Star), R(0),
-  B(LdaConstant), U8(111),
-  B(Star), R(0),
-  B(LdaConstant), U8(112),
-  B(Star), R(0),
-  B(LdaConstant), U8(113),
-  B(Star), R(0),
-  B(LdaConstant), U8(114),
-  B(Star), R(0),
-  B(LdaConstant), U8(115),
-  B(Star), R(0),
-  B(LdaConstant), U8(116),
-  B(Star), R(0),
-  B(LdaConstant), U8(117),
-  B(Star), R(0),
-  B(LdaConstant), U8(118),
-  B(Star), R(0),
-  B(LdaConstant), U8(119),
-  B(Star), R(0),
-  B(LdaConstant), U8(120),
-  B(Star), R(0),
-  B(LdaConstant), U8(121),
-  B(Star), R(0),
-  B(LdaConstant), U8(122),
-  B(Star), R(0),
-  B(LdaConstant), U8(123),
-  B(Star), R(0),
-  B(LdaConstant), U8(124),
-  B(Star), R(0),
-  B(LdaConstant), U8(125),
-  B(Star), R(0),
-  B(LdaConstant), U8(126),
-  B(Star), R(0),
-  B(LdaConstant), U8(127),
-  B(Star), R(0),
-  B(LdaConstant), U8(128),
-  B(Star), R(0),
-  B(LdaConstant), U8(129),
-  B(Star), R(0),
-  B(LdaConstant), U8(130),
-  B(Star), R(0),
-  B(LdaConstant), U8(131),
-  B(Star), R(0),
-  B(LdaConstant), U8(132),
-  B(Star), R(0),
-  B(LdaConstant), U8(133),
-  B(Star), R(0),
-  B(LdaConstant), U8(134),
-  B(Star), R(0),
-  B(LdaConstant), U8(135),
-  B(Star), R(0),
-  B(LdaConstant), U8(136),
-  B(Star), R(0),
-  B(LdaConstant), U8(137),
-  B(Star), R(0),
-  B(LdaConstant), U8(138),
-  B(Star), R(0),
-  B(LdaConstant), U8(139),
-  B(Star), R(0),
-  B(LdaConstant), U8(140),
-  B(Star), R(0),
-  B(LdaConstant), U8(141),
-  B(Star), R(0),
-  B(LdaConstant), U8(142),
-  B(Star), R(0),
-  B(LdaConstant), U8(143),
-  B(Star), R(0),
-  B(LdaConstant), U8(144),
-  B(Star), R(0),
-  B(LdaConstant), U8(145),
-  B(Star), R(0),
-  B(LdaConstant), U8(146),
-  B(Star), R(0),
-  B(LdaConstant), U8(147),
-  B(Star), R(0),
-  B(LdaConstant), U8(148),
-  B(Star), R(0),
-  B(LdaConstant), U8(149),
-  B(Star), R(0),
-  B(LdaConstant), U8(150),
-  B(Star), R(0),
-  B(LdaConstant), U8(151),
-  B(Star), R(0),
-  B(LdaConstant), U8(152),
-  B(Star), R(0),
-  B(LdaConstant), U8(153),
-  B(Star), R(0),
-  B(LdaConstant), U8(154),
-  B(Star), R(0),
-  B(LdaConstant), U8(155),
-  B(Star), R(0),
-  B(LdaConstant), U8(156),
-  B(Star), R(0),
-  B(LdaConstant), U8(157),
-  B(Star), R(0),
-  B(LdaConstant), U8(158),
-  B(Star), R(0),
-  B(LdaConstant), U8(159),
-  B(Star), R(0),
-  B(LdaConstant), U8(160),
-  B(Star), R(0),
-  B(LdaConstant), U8(161),
-  B(Star), R(0),
-  B(LdaConstant), U8(162),
-  B(Star), R(0),
-  B(LdaConstant), U8(163),
-  B(Star), R(0),
-  B(LdaConstant), U8(164),
-  B(Star), R(0),
-  B(LdaConstant), U8(165),
-  B(Star), R(0),
-  B(LdaConstant), U8(166),
-  B(Star), R(0),
-  B(LdaConstant), U8(167),
-  B(Star), R(0),
-  B(LdaConstant), U8(168),
-  B(Star), R(0),
-  B(LdaConstant), U8(169),
-  B(Star), R(0),
-  B(LdaConstant), U8(170),
-  B(Star), R(0),
-  B(LdaConstant), U8(171),
-  B(Star), R(0),
-  B(LdaConstant), U8(172),
-  B(Star), R(0),
-  B(LdaConstant), U8(173),
-  B(Star), R(0),
-  B(LdaConstant), U8(174),
-  B(Star), R(0),
-  B(LdaConstant), U8(175),
-  B(Star), R(0),
-  B(LdaConstant), U8(176),
-  B(Star), R(0),
-  B(LdaConstant), U8(177),
-  B(Star), R(0),
-  B(LdaConstant), U8(178),
-  B(Star), R(0),
-  B(LdaConstant), U8(179),
-  B(Star), R(0),
-  B(LdaConstant), U8(180),
-  B(Star), R(0),
-  B(LdaConstant), U8(181),
-  B(Star), R(0),
-  B(LdaConstant), U8(182),
-  B(Star), R(0),
-  B(LdaConstant), U8(183),
-  B(Star), R(0),
-  B(LdaConstant), U8(184),
-  B(Star), R(0),
-  B(LdaConstant), U8(185),
-  B(Star), R(0),
-  B(LdaConstant), U8(186),
-  B(Star), R(0),
-  B(LdaConstant), U8(187),
-  B(Star), R(0),
-  B(LdaConstant), U8(188),
-  B(Star), R(0),
-  B(LdaConstant), U8(189),
-  B(Star), R(0),
-  B(LdaConstant), U8(190),
-  B(Star), R(0),
-  B(LdaConstant), U8(191),
-  B(Star), R(0),
-  B(LdaConstant), U8(192),
-  B(Star), R(0),
-  B(LdaConstant), U8(193),
-  B(Star), R(0),
-  B(LdaConstant), U8(194),
-  B(Star), R(0),
-  B(LdaConstant), U8(195),
-  B(Star), R(0),
-  B(LdaConstant), U8(196),
-  B(Star), R(0),
-  B(LdaConstant), U8(197),
-  B(Star), R(0),
-  B(LdaConstant), U8(198),
-  B(Star), R(0),
-  B(LdaConstant), U8(199),
-  B(Star), R(0),
-  B(LdaConstant), U8(200),
-  B(Star), R(0),
-  B(LdaConstant), U8(201),
-  B(Star), R(0),
-  B(LdaConstant), U8(202),
-  B(Star), R(0),
-  B(LdaConstant), U8(203),
-  B(Star), R(0),
-  B(LdaConstant), U8(204),
-  B(Star), R(0),
-  B(LdaConstant), U8(205),
-  B(Star), R(0),
-  B(LdaConstant), U8(206),
-  B(Star), R(0),
-  B(LdaConstant), U8(207),
-  B(Star), R(0),
-  B(LdaConstant), U8(208),
-  B(Star), R(0),
-  B(LdaConstant), U8(209),
-  B(Star), R(0),
-  B(LdaConstant), U8(210),
-  B(Star), R(0),
-  B(LdaConstant), U8(211),
-  B(Star), R(0),
-  B(LdaConstant), U8(212),
-  B(Star), R(0),
-  B(LdaConstant), U8(213),
-  B(Star), R(0),
-  B(LdaConstant), U8(214),
-  B(Star), R(0),
-  B(LdaConstant), U8(215),
-  B(Star), R(0),
-  B(LdaConstant), U8(216),
-  B(Star), R(0),
-  B(LdaConstant), U8(217),
-  B(Star), R(0),
-  B(LdaConstant), U8(218),
-  B(Star), R(0),
-  B(LdaConstant), U8(219),
-  B(Star), R(0),
-  B(LdaConstant), U8(220),
-  B(Star), R(0),
-  B(LdaConstant), U8(221),
-  B(Star), R(0),
-  B(LdaConstant), U8(222),
-  B(Star), R(0),
-  B(LdaConstant), U8(223),
-  B(Star), R(0),
-  B(LdaConstant), U8(224),
-  B(Star), R(0),
-  B(LdaConstant), U8(225),
-  B(Star), R(0),
-  B(LdaConstant), U8(226),
-  B(Star), R(0),
-  B(LdaConstant), U8(227),
-  B(Star), R(0),
-  B(LdaConstant), U8(228),
-  B(Star), R(0),
-  B(LdaConstant), U8(229),
-  B(Star), R(0),
-  B(LdaConstant), U8(230),
-  B(Star), R(0),
-  B(LdaConstant), U8(231),
-  B(Star), R(0),
-  B(LdaConstant), U8(232),
-  B(Star), R(0),
-  B(LdaConstant), U8(233),
-  B(Star), R(0),
-  B(LdaConstant), U8(234),
-  B(Star), R(0),
-  B(LdaConstant), U8(235),
-  B(Star), R(0),
-  B(LdaConstant), U8(236),
-  B(Star), R(0),
-  B(LdaConstant), U8(237),
-  B(Star), R(0),
-  B(LdaConstant), U8(238),
-  B(Star), R(0),
-  B(LdaConstant), U8(239),
-  B(Star), R(0),
-  B(LdaConstant), U8(240),
-  B(Star), R(0),
-  B(LdaConstant), U8(241),
-  B(Star), R(0),
-  B(LdaConstant), U8(242),
-  B(Star), R(0),
-  B(LdaConstant), U8(243),
-  B(Star), R(0),
-  B(LdaConstant), U8(244),
-  B(Star), R(0),
-  B(LdaConstant), U8(245),
-  B(Star), R(0),
-  B(LdaConstant), U8(246),
-  B(Star), R(0),
-  B(LdaConstant), U8(247),
-  B(Star), R(0),
-  B(LdaConstant), U8(248),
-  B(Star), R(0),
-  B(LdaConstant), U8(249),
-  B(Star), R(0),
-  B(LdaConstant), U8(250),
-  B(Star), R(0),
-  B(LdaConstant), U8(251),
-  B(Star), R(0),
-  B(LdaConstant), U8(252),
-  B(Star), R(0),
-  B(LdaConstant), U8(253),
-  B(Star), R(0),
-  B(LdaConstant), U8(254),
-  B(Star), R(0),
-  B(LdaConstant), U8(255),
-  B(Star), R(0),
-  B(Wide), B(CreateArrayLiteral), U16(256), U16(0), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   41 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   51 S> */ B(LdaConstant), U8(1),
+                B(Star), R(0),
+  /*   61 S> */ B(LdaConstant), U8(2),
+                B(Star), R(0),
+  /*   71 S> */ B(LdaConstant), U8(3),
+                B(Star), R(0),
+  /*   81 S> */ B(LdaConstant), U8(4),
+                B(Star), R(0),
+  /*   91 S> */ B(LdaConstant), U8(5),
+                B(Star), R(0),
+  /*  101 S> */ B(LdaConstant), U8(6),
+                B(Star), R(0),
+  /*  111 S> */ B(LdaConstant), U8(7),
+                B(Star), R(0),
+  /*  121 S> */ B(LdaConstant), U8(8),
+                B(Star), R(0),
+  /*  131 S> */ B(LdaConstant), U8(9),
+                B(Star), R(0),
+  /*  141 S> */ B(LdaConstant), U8(10),
+                B(Star), R(0),
+  /*  151 S> */ B(LdaConstant), U8(11),
+                B(Star), R(0),
+  /*  161 S> */ B(LdaConstant), U8(12),
+                B(Star), R(0),
+  /*  171 S> */ B(LdaConstant), U8(13),
+                B(Star), R(0),
+  /*  181 S> */ B(LdaConstant), U8(14),
+                B(Star), R(0),
+  /*  191 S> */ B(LdaConstant), U8(15),
+                B(Star), R(0),
+  /*  201 S> */ B(LdaConstant), U8(16),
+                B(Star), R(0),
+  /*  211 S> */ B(LdaConstant), U8(17),
+                B(Star), R(0),
+  /*  221 S> */ B(LdaConstant), U8(18),
+                B(Star), R(0),
+  /*  231 S> */ B(LdaConstant), U8(19),
+                B(Star), R(0),
+  /*  241 S> */ B(LdaConstant), U8(20),
+                B(Star), R(0),
+  /*  251 S> */ B(LdaConstant), U8(21),
+                B(Star), R(0),
+  /*  261 S> */ B(LdaConstant), U8(22),
+                B(Star), R(0),
+  /*  271 S> */ B(LdaConstant), U8(23),
+                B(Star), R(0),
+  /*  281 S> */ B(LdaConstant), U8(24),
+                B(Star), R(0),
+  /*  291 S> */ B(LdaConstant), U8(25),
+                B(Star), R(0),
+  /*  301 S> */ B(LdaConstant), U8(26),
+                B(Star), R(0),
+  /*  311 S> */ B(LdaConstant), U8(27),
+                B(Star), R(0),
+  /*  321 S> */ B(LdaConstant), U8(28),
+                B(Star), R(0),
+  /*  331 S> */ B(LdaConstant), U8(29),
+                B(Star), R(0),
+  /*  341 S> */ B(LdaConstant), U8(30),
+                B(Star), R(0),
+  /*  351 S> */ B(LdaConstant), U8(31),
+                B(Star), R(0),
+  /*  361 S> */ B(LdaConstant), U8(32),
+                B(Star), R(0),
+  /*  371 S> */ B(LdaConstant), U8(33),
+                B(Star), R(0),
+  /*  381 S> */ B(LdaConstant), U8(34),
+                B(Star), R(0),
+  /*  391 S> */ B(LdaConstant), U8(35),
+                B(Star), R(0),
+  /*  401 S> */ B(LdaConstant), U8(36),
+                B(Star), R(0),
+  /*  411 S> */ B(LdaConstant), U8(37),
+                B(Star), R(0),
+  /*  421 S> */ B(LdaConstant), U8(38),
+                B(Star), R(0),
+  /*  431 S> */ B(LdaConstant), U8(39),
+                B(Star), R(0),
+  /*  441 S> */ B(LdaConstant), U8(40),
+                B(Star), R(0),
+  /*  451 S> */ B(LdaConstant), U8(41),
+                B(Star), R(0),
+  /*  461 S> */ B(LdaConstant), U8(42),
+                B(Star), R(0),
+  /*  471 S> */ B(LdaConstant), U8(43),
+                B(Star), R(0),
+  /*  481 S> */ B(LdaConstant), U8(44),
+                B(Star), R(0),
+  /*  491 S> */ B(LdaConstant), U8(45),
+                B(Star), R(0),
+  /*  501 S> */ B(LdaConstant), U8(46),
+                B(Star), R(0),
+  /*  511 S> */ B(LdaConstant), U8(47),
+                B(Star), R(0),
+  /*  521 S> */ B(LdaConstant), U8(48),
+                B(Star), R(0),
+  /*  531 S> */ B(LdaConstant), U8(49),
+                B(Star), R(0),
+  /*  541 S> */ B(LdaConstant), U8(50),
+                B(Star), R(0),
+  /*  551 S> */ B(LdaConstant), U8(51),
+                B(Star), R(0),
+  /*  561 S> */ B(LdaConstant), U8(52),
+                B(Star), R(0),
+  /*  571 S> */ B(LdaConstant), U8(53),
+                B(Star), R(0),
+  /*  581 S> */ B(LdaConstant), U8(54),
+                B(Star), R(0),
+  /*  591 S> */ B(LdaConstant), U8(55),
+                B(Star), R(0),
+  /*  601 S> */ B(LdaConstant), U8(56),
+                B(Star), R(0),
+  /*  611 S> */ B(LdaConstant), U8(57),
+                B(Star), R(0),
+  /*  621 S> */ B(LdaConstant), U8(58),
+                B(Star), R(0),
+  /*  631 S> */ B(LdaConstant), U8(59),
+                B(Star), R(0),
+  /*  641 S> */ B(LdaConstant), U8(60),
+                B(Star), R(0),
+  /*  651 S> */ B(LdaConstant), U8(61),
+                B(Star), R(0),
+  /*  661 S> */ B(LdaConstant), U8(62),
+                B(Star), R(0),
+  /*  671 S> */ B(LdaConstant), U8(63),
+                B(Star), R(0),
+  /*  681 S> */ B(LdaConstant), U8(64),
+                B(Star), R(0),
+  /*  691 S> */ B(LdaConstant), U8(65),
+                B(Star), R(0),
+  /*  701 S> */ B(LdaConstant), U8(66),
+                B(Star), R(0),
+  /*  711 S> */ B(LdaConstant), U8(67),
+                B(Star), R(0),
+  /*  721 S> */ B(LdaConstant), U8(68),
+                B(Star), R(0),
+  /*  731 S> */ B(LdaConstant), U8(69),
+                B(Star), R(0),
+  /*  741 S> */ B(LdaConstant), U8(70),
+                B(Star), R(0),
+  /*  751 S> */ B(LdaConstant), U8(71),
+                B(Star), R(0),
+  /*  761 S> */ B(LdaConstant), U8(72),
+                B(Star), R(0),
+  /*  771 S> */ B(LdaConstant), U8(73),
+                B(Star), R(0),
+  /*  781 S> */ B(LdaConstant), U8(74),
+                B(Star), R(0),
+  /*  791 S> */ B(LdaConstant), U8(75),
+                B(Star), R(0),
+  /*  801 S> */ B(LdaConstant), U8(76),
+                B(Star), R(0),
+  /*  811 S> */ B(LdaConstant), U8(77),
+                B(Star), R(0),
+  /*  821 S> */ B(LdaConstant), U8(78),
+                B(Star), R(0),
+  /*  831 S> */ B(LdaConstant), U8(79),
+                B(Star), R(0),
+  /*  841 S> */ B(LdaConstant), U8(80),
+                B(Star), R(0),
+  /*  851 S> */ B(LdaConstant), U8(81),
+                B(Star), R(0),
+  /*  861 S> */ B(LdaConstant), U8(82),
+                B(Star), R(0),
+  /*  871 S> */ B(LdaConstant), U8(83),
+                B(Star), R(0),
+  /*  881 S> */ B(LdaConstant), U8(84),
+                B(Star), R(0),
+  /*  891 S> */ B(LdaConstant), U8(85),
+                B(Star), R(0),
+  /*  901 S> */ B(LdaConstant), U8(86),
+                B(Star), R(0),
+  /*  911 S> */ B(LdaConstant), U8(87),
+                B(Star), R(0),
+  /*  921 S> */ B(LdaConstant), U8(88),
+                B(Star), R(0),
+  /*  931 S> */ B(LdaConstant), U8(89),
+                B(Star), R(0),
+  /*  941 S> */ B(LdaConstant), U8(90),
+                B(Star), R(0),
+  /*  951 S> */ B(LdaConstant), U8(91),
+                B(Star), R(0),
+  /*  961 S> */ B(LdaConstant), U8(92),
+                B(Star), R(0),
+  /*  971 S> */ B(LdaConstant), U8(93),
+                B(Star), R(0),
+  /*  981 S> */ B(LdaConstant), U8(94),
+                B(Star), R(0),
+  /*  991 S> */ B(LdaConstant), U8(95),
+                B(Star), R(0),
+  /* 1001 S> */ B(LdaConstant), U8(96),
+                B(Star), R(0),
+  /* 1011 S> */ B(LdaConstant), U8(97),
+                B(Star), R(0),
+  /* 1021 S> */ B(LdaConstant), U8(98),
+                B(Star), R(0),
+  /* 1031 S> */ B(LdaConstant), U8(99),
+                B(Star), R(0),
+  /* 1041 S> */ B(LdaConstant), U8(100),
+                B(Star), R(0),
+  /* 1051 S> */ B(LdaConstant), U8(101),
+                B(Star), R(0),
+  /* 1061 S> */ B(LdaConstant), U8(102),
+                B(Star), R(0),
+  /* 1071 S> */ B(LdaConstant), U8(103),
+                B(Star), R(0),
+  /* 1081 S> */ B(LdaConstant), U8(104),
+                B(Star), R(0),
+  /* 1091 S> */ B(LdaConstant), U8(105),
+                B(Star), R(0),
+  /* 1101 S> */ B(LdaConstant), U8(106),
+                B(Star), R(0),
+  /* 1111 S> */ B(LdaConstant), U8(107),
+                B(Star), R(0),
+  /* 1121 S> */ B(LdaConstant), U8(108),
+                B(Star), R(0),
+  /* 1131 S> */ B(LdaConstant), U8(109),
+                B(Star), R(0),
+  /* 1141 S> */ B(LdaConstant), U8(110),
+                B(Star), R(0),
+  /* 1151 S> */ B(LdaConstant), U8(111),
+                B(Star), R(0),
+  /* 1161 S> */ B(LdaConstant), U8(112),
+                B(Star), R(0),
+  /* 1171 S> */ B(LdaConstant), U8(113),
+                B(Star), R(0),
+  /* 1181 S> */ B(LdaConstant), U8(114),
+                B(Star), R(0),
+  /* 1191 S> */ B(LdaConstant), U8(115),
+                B(Star), R(0),
+  /* 1201 S> */ B(LdaConstant), U8(116),
+                B(Star), R(0),
+  /* 1211 S> */ B(LdaConstant), U8(117),
+                B(Star), R(0),
+  /* 1221 S> */ B(LdaConstant), U8(118),
+                B(Star), R(0),
+  /* 1231 S> */ B(LdaConstant), U8(119),
+                B(Star), R(0),
+  /* 1241 S> */ B(LdaConstant), U8(120),
+                B(Star), R(0),
+  /* 1251 S> */ B(LdaConstant), U8(121),
+                B(Star), R(0),
+  /* 1261 S> */ B(LdaConstant), U8(122),
+                B(Star), R(0),
+  /* 1271 S> */ B(LdaConstant), U8(123),
+                B(Star), R(0),
+  /* 1281 S> */ B(LdaConstant), U8(124),
+                B(Star), R(0),
+  /* 1291 S> */ B(LdaConstant), U8(125),
+                B(Star), R(0),
+  /* 1301 S> */ B(LdaConstant), U8(126),
+                B(Star), R(0),
+  /* 1311 S> */ B(LdaConstant), U8(127),
+                B(Star), R(0),
+  /* 1321 S> */ B(LdaConstant), U8(128),
+                B(Star), R(0),
+  /* 1331 S> */ B(LdaConstant), U8(129),
+                B(Star), R(0),
+  /* 1341 S> */ B(LdaConstant), U8(130),
+                B(Star), R(0),
+  /* 1351 S> */ B(LdaConstant), U8(131),
+                B(Star), R(0),
+  /* 1361 S> */ B(LdaConstant), U8(132),
+                B(Star), R(0),
+  /* 1371 S> */ B(LdaConstant), U8(133),
+                B(Star), R(0),
+  /* 1381 S> */ B(LdaConstant), U8(134),
+                B(Star), R(0),
+  /* 1391 S> */ B(LdaConstant), U8(135),
+                B(Star), R(0),
+  /* 1401 S> */ B(LdaConstant), U8(136),
+                B(Star), R(0),
+  /* 1411 S> */ B(LdaConstant), U8(137),
+                B(Star), R(0),
+  /* 1421 S> */ B(LdaConstant), U8(138),
+                B(Star), R(0),
+  /* 1431 S> */ B(LdaConstant), U8(139),
+                B(Star), R(0),
+  /* 1441 S> */ B(LdaConstant), U8(140),
+                B(Star), R(0),
+  /* 1451 S> */ B(LdaConstant), U8(141),
+                B(Star), R(0),
+  /* 1461 S> */ B(LdaConstant), U8(142),
+                B(Star), R(0),
+  /* 1471 S> */ B(LdaConstant), U8(143),
+                B(Star), R(0),
+  /* 1481 S> */ B(LdaConstant), U8(144),
+                B(Star), R(0),
+  /* 1491 S> */ B(LdaConstant), U8(145),
+                B(Star), R(0),
+  /* 1501 S> */ B(LdaConstant), U8(146),
+                B(Star), R(0),
+  /* 1511 S> */ B(LdaConstant), U8(147),
+                B(Star), R(0),
+  /* 1521 S> */ B(LdaConstant), U8(148),
+                B(Star), R(0),
+  /* 1531 S> */ B(LdaConstant), U8(149),
+                B(Star), R(0),
+  /* 1541 S> */ B(LdaConstant), U8(150),
+                B(Star), R(0),
+  /* 1551 S> */ B(LdaConstant), U8(151),
+                B(Star), R(0),
+  /* 1561 S> */ B(LdaConstant), U8(152),
+                B(Star), R(0),
+  /* 1571 S> */ B(LdaConstant), U8(153),
+                B(Star), R(0),
+  /* 1581 S> */ B(LdaConstant), U8(154),
+                B(Star), R(0),
+  /* 1591 S> */ B(LdaConstant), U8(155),
+                B(Star), R(0),
+  /* 1601 S> */ B(LdaConstant), U8(156),
+                B(Star), R(0),
+  /* 1611 S> */ B(LdaConstant), U8(157),
+                B(Star), R(0),
+  /* 1621 S> */ B(LdaConstant), U8(158),
+                B(Star), R(0),
+  /* 1631 S> */ B(LdaConstant), U8(159),
+                B(Star), R(0),
+  /* 1641 S> */ B(LdaConstant), U8(160),
+                B(Star), R(0),
+  /* 1651 S> */ B(LdaConstant), U8(161),
+                B(Star), R(0),
+  /* 1661 S> */ B(LdaConstant), U8(162),
+                B(Star), R(0),
+  /* 1671 S> */ B(LdaConstant), U8(163),
+                B(Star), R(0),
+  /* 1681 S> */ B(LdaConstant), U8(164),
+                B(Star), R(0),
+  /* 1691 S> */ B(LdaConstant), U8(165),
+                B(Star), R(0),
+  /* 1701 S> */ B(LdaConstant), U8(166),
+                B(Star), R(0),
+  /* 1711 S> */ B(LdaConstant), U8(167),
+                B(Star), R(0),
+  /* 1721 S> */ B(LdaConstant), U8(168),
+                B(Star), R(0),
+  /* 1731 S> */ B(LdaConstant), U8(169),
+                B(Star), R(0),
+  /* 1741 S> */ B(LdaConstant), U8(170),
+                B(Star), R(0),
+  /* 1751 S> */ B(LdaConstant), U8(171),
+                B(Star), R(0),
+  /* 1761 S> */ B(LdaConstant), U8(172),
+                B(Star), R(0),
+  /* 1771 S> */ B(LdaConstant), U8(173),
+                B(Star), R(0),
+  /* 1781 S> */ B(LdaConstant), U8(174),
+                B(Star), R(0),
+  /* 1791 S> */ B(LdaConstant), U8(175),
+                B(Star), R(0),
+  /* 1801 S> */ B(LdaConstant), U8(176),
+                B(Star), R(0),
+  /* 1811 S> */ B(LdaConstant), U8(177),
+                B(Star), R(0),
+  /* 1821 S> */ B(LdaConstant), U8(178),
+                B(Star), R(0),
+  /* 1831 S> */ B(LdaConstant), U8(179),
+                B(Star), R(0),
+  /* 1841 S> */ B(LdaConstant), U8(180),
+                B(Star), R(0),
+  /* 1851 S> */ B(LdaConstant), U8(181),
+                B(Star), R(0),
+  /* 1861 S> */ B(LdaConstant), U8(182),
+                B(Star), R(0),
+  /* 1871 S> */ B(LdaConstant), U8(183),
+                B(Star), R(0),
+  /* 1881 S> */ B(LdaConstant), U8(184),
+                B(Star), R(0),
+  /* 1891 S> */ B(LdaConstant), U8(185),
+                B(Star), R(0),
+  /* 1901 S> */ B(LdaConstant), U8(186),
+                B(Star), R(0),
+  /* 1911 S> */ B(LdaConstant), U8(187),
+                B(Star), R(0),
+  /* 1921 S> */ B(LdaConstant), U8(188),
+                B(Star), R(0),
+  /* 1931 S> */ B(LdaConstant), U8(189),
+                B(Star), R(0),
+  /* 1941 S> */ B(LdaConstant), U8(190),
+                B(Star), R(0),
+  /* 1951 S> */ B(LdaConstant), U8(191),
+                B(Star), R(0),
+  /* 1961 S> */ B(LdaConstant), U8(192),
+                B(Star), R(0),
+  /* 1971 S> */ B(LdaConstant), U8(193),
+                B(Star), R(0),
+  /* 1981 S> */ B(LdaConstant), U8(194),
+                B(Star), R(0),
+  /* 1991 S> */ B(LdaConstant), U8(195),
+                B(Star), R(0),
+  /* 2001 S> */ B(LdaConstant), U8(196),
+                B(Star), R(0),
+  /* 2011 S> */ B(LdaConstant), U8(197),
+                B(Star), R(0),
+  /* 2021 S> */ B(LdaConstant), U8(198),
+                B(Star), R(0),
+  /* 2031 S> */ B(LdaConstant), U8(199),
+                B(Star), R(0),
+  /* 2041 S> */ B(LdaConstant), U8(200),
+                B(Star), R(0),
+  /* 2051 S> */ B(LdaConstant), U8(201),
+                B(Star), R(0),
+  /* 2061 S> */ B(LdaConstant), U8(202),
+                B(Star), R(0),
+  /* 2071 S> */ B(LdaConstant), U8(203),
+                B(Star), R(0),
+  /* 2081 S> */ B(LdaConstant), U8(204),
+                B(Star), R(0),
+  /* 2091 S> */ B(LdaConstant), U8(205),
+                B(Star), R(0),
+  /* 2101 S> */ B(LdaConstant), U8(206),
+                B(Star), R(0),
+  /* 2111 S> */ B(LdaConstant), U8(207),
+                B(Star), R(0),
+  /* 2121 S> */ B(LdaConstant), U8(208),
+                B(Star), R(0),
+  /* 2131 S> */ B(LdaConstant), U8(209),
+                B(Star), R(0),
+  /* 2141 S> */ B(LdaConstant), U8(210),
+                B(Star), R(0),
+  /* 2151 S> */ B(LdaConstant), U8(211),
+                B(Star), R(0),
+  /* 2161 S> */ B(LdaConstant), U8(212),
+                B(Star), R(0),
+  /* 2171 S> */ B(LdaConstant), U8(213),
+                B(Star), R(0),
+  /* 2181 S> */ B(LdaConstant), U8(214),
+                B(Star), R(0),
+  /* 2191 S> */ B(LdaConstant), U8(215),
+                B(Star), R(0),
+  /* 2201 S> */ B(LdaConstant), U8(216),
+                B(Star), R(0),
+  /* 2211 S> */ B(LdaConstant), U8(217),
+                B(Star), R(0),
+  /* 2221 S> */ B(LdaConstant), U8(218),
+                B(Star), R(0),
+  /* 2231 S> */ B(LdaConstant), U8(219),
+                B(Star), R(0),
+  /* 2241 S> */ B(LdaConstant), U8(220),
+                B(Star), R(0),
+  /* 2251 S> */ B(LdaConstant), U8(221),
+                B(Star), R(0),
+  /* 2261 S> */ B(LdaConstant), U8(222),
+                B(Star), R(0),
+  /* 2271 S> */ B(LdaConstant), U8(223),
+                B(Star), R(0),
+  /* 2281 S> */ B(LdaConstant), U8(224),
+                B(Star), R(0),
+  /* 2291 S> */ B(LdaConstant), U8(225),
+                B(Star), R(0),
+  /* 2301 S> */ B(LdaConstant), U8(226),
+                B(Star), R(0),
+  /* 2311 S> */ B(LdaConstant), U8(227),
+                B(Star), R(0),
+  /* 2321 S> */ B(LdaConstant), U8(228),
+                B(Star), R(0),
+  /* 2331 S> */ B(LdaConstant), U8(229),
+                B(Star), R(0),
+  /* 2341 S> */ B(LdaConstant), U8(230),
+                B(Star), R(0),
+  /* 2351 S> */ B(LdaConstant), U8(231),
+                B(Star), R(0),
+  /* 2361 S> */ B(LdaConstant), U8(232),
+                B(Star), R(0),
+  /* 2371 S> */ B(LdaConstant), U8(233),
+                B(Star), R(0),
+  /* 2381 S> */ B(LdaConstant), U8(234),
+                B(Star), R(0),
+  /* 2391 S> */ B(LdaConstant), U8(235),
+                B(Star), R(0),
+  /* 2401 S> */ B(LdaConstant), U8(236),
+                B(Star), R(0),
+  /* 2411 S> */ B(LdaConstant), U8(237),
+                B(Star), R(0),
+  /* 2421 S> */ B(LdaConstant), U8(238),
+                B(Star), R(0),
+  /* 2431 S> */ B(LdaConstant), U8(239),
+                B(Star), R(0),
+  /* 2441 S> */ B(LdaConstant), U8(240),
+                B(Star), R(0),
+  /* 2451 S> */ B(LdaConstant), U8(241),
+                B(Star), R(0),
+  /* 2461 S> */ B(LdaConstant), U8(242),
+                B(Star), R(0),
+  /* 2471 S> */ B(LdaConstant), U8(243),
+                B(Star), R(0),
+  /* 2481 S> */ B(LdaConstant), U8(244),
+                B(Star), R(0),
+  /* 2491 S> */ B(LdaConstant), U8(245),
+                B(Star), R(0),
+  /* 2501 S> */ B(LdaConstant), U8(246),
+                B(Star), R(0),
+  /* 2511 S> */ B(LdaConstant), U8(247),
+                B(Star), R(0),
+  /* 2521 S> */ B(LdaConstant), U8(248),
+                B(Star), R(0),
+  /* 2531 S> */ B(LdaConstant), U8(249),
+                B(Star), R(0),
+  /* 2541 S> */ B(LdaConstant), U8(250),
+                B(Star), R(0),
+  /* 2551 S> */ B(LdaConstant), U8(251),
+                B(Star), R(0),
+  /* 2561 S> */ B(LdaConstant), U8(252),
+                B(Star), R(0),
+  /* 2571 S> */ B(LdaConstant), U8(253),
+                B(Star), R(0),
+  /* 2581 S> */ B(LdaConstant), U8(254),
+                B(Star), R(0),
+  /* 2591 S> */ B(LdaConstant), U8(255),
+                B(Star), R(0),
+  /* 2601 S> */ B(Wide), B(CreateArrayLiteral), U16(256), U16(0), U8(3),
+  /* 2619 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::HEAP_NUMBER_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/AssignmentsInBinaryExpression.golden b/test/cctest/interpreter/bytecode_expectations/AssignmentsInBinaryExpression.golden
index f569bab..cdda7f2 100644
--- a/test/cctest/interpreter/bytecode_expectations/AssignmentsInBinaryExpression.golden
+++ b/test/cctest/interpreter/bytecode_expectations/AssignmentsInBinaryExpression.golden
@@ -16,20 +16,20 @@
 parameter count: 1
 bytecode array length: 25
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(0),
-  B(LdaSmi), U8(3),
-  B(Star), R(1),
-  B(LdaSmi), U8(4),
-  B(Star), R(0),
-  B(LdaSmi), U8(5),
-  B(Star), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   49 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+  /*   52 S> */ B(LdaSmi), U8(2),
+                B(Star), R(0),
+                B(LdaSmi), U8(3),
+                B(Star), R(1),
+                B(LdaSmi), U8(4),
+                B(Star), R(0),
+                B(LdaSmi), U8(5),
+                B(Star), R(1),
+  /*   89 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -44,15 +44,16 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 12
+bytecode array length: 13
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(55),
-  B(Star), R(0),
-  B(LdaSmi), U8(100),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(55),
+                B(Star), R(0),
+  /*   57 S> */ B(LdaSmi), U8(100),
+                B(Star), R(0),
+                B(Star), R(1),
+  /*   65 S> */ B(Nop),
+  /*   75 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -67,21 +68,22 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 24
+bytecode array length: 26
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(55),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(100),
-  B(Star), R(0),
-  B(Add), R(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(101),
-  B(Star), R(0),
-  B(Add), R(2),
-  B(Star), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(55),
+                B(Star), R(0),
+  /*   46 S> */ B(LdaSmi), U8(100),
+                B(Mov), R(0), R(1),
+                B(Star), R(0),
+  /*   57 E> */ B(Add), R(1),
+                B(Star), R(2),
+                B(LdaSmi), U8(101),
+                B(Star), R(0),
+  /*   69 E> */ B(Add), R(2),
+                B(Star), R(0),
+  /*   77 S> */ B(Nop),
+  /*   87 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -97,26 +99,25 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 32
+bytecode array length: 29
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(55),
-  B(Star), R(0),
-  B(LdaSmi), U8(56),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Sub), R(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(57),
-  B(Star), R(0),
-  B(Add), R(2),
-  B(Star), R(0),
-  B(ToNumber),
-  B(Star), R(1),
-  B(Inc),
-  B(Star), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(55),
+                B(Star), R(0),
+  /*   46 S> */ B(LdaSmi), U8(56),
+                B(Star), R(0),
+  /*   61 E> */ B(Sub), R(0),
+                B(Star), R(2),
+                B(LdaSmi), U8(57),
+                B(Star), R(0),
+  /*   68 E> */ B(Add), R(2),
+                B(Star), R(0),
+  /*   75 S> */ B(ToNumber),
+                B(Star), R(1),
+                B(Inc),
+                B(Star), R(0),
+  /*   80 S> */ B(Nop),
+  /*   90 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -131,25 +132,26 @@
 "
 frame size: 4
 parameter count: 1
-bytecode array length: 32
+bytecode array length: 34
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(55),
-  B(Star), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(Add), R(2),
-  B(Star), R(3),
-  B(LdaSmi), U8(2),
-  B(Star), R(0),
-  B(Add), R(3),
-  B(Star), R(2),
-  B(LdaSmi), U8(3),
-  B(Star), R(0),
-  B(Add), R(2),
-  B(Star), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(55),
+                B(Star), R(0),
+  /*   76 S> */ B(LdaSmi), U8(1),
+                B(Mov), R(0), R(2),
+                B(Star), R(0),
+  /*   61 E> */ B(Add), R(2),
+                B(Star), R(3),
+                B(LdaSmi), U8(2),
+                B(Star), R(0),
+  /*   71 E> */ B(Add), R(3),
+                B(Star), R(2),
+                B(LdaSmi), U8(3),
+                B(Star), R(0),
+  /*   81 E> */ B(Add), R(2),
+                B(Star), R(1),
+  /*   87 S> */ B(Nop),
+  /*   97 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -164,25 +166,26 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 32
+bytecode array length: 34
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(55),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(Add), R(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(2),
-  B(Star), R(0),
-  B(Add), R(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(Star), R(0),
-  B(Add), R(1),
-  B(Star), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(55),
+                B(Star), R(0),
+  /*   76 S> */ B(LdaSmi), U8(1),
+                B(Mov), R(0), R(1),
+                B(Star), R(0),
+  /*   61 E> */ B(Add), R(1),
+                B(Star), R(2),
+                B(LdaSmi), U8(2),
+                B(Star), R(0),
+  /*   71 E> */ B(Add), R(2),
+                B(Star), R(1),
+                B(LdaSmi), U8(3),
+                B(Star), R(0),
+  /*   81 E> */ B(Add), R(1),
+                B(Star), R(0),
+  /*   87 S> */ B(Nop),
+  /*   97 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -196,44 +199,41 @@
 "
 frame size: 5
 parameter count: 1
-bytecode array length: 70
+bytecode array length: 65
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(Star), R(0),
-  B(LdaSmi), U8(20),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(Add), R(2),
-  B(Star), R(3),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Add), R(2),
-  B(Star), R(4),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(Mul), R(4),
-  B(Add), R(3),
-  B(Star), R(2),
-  B(LdaSmi), U8(3),
-  B(Star), R(1),
-  B(Add), R(2),
-  B(Star), R(3),
-  B(LdaSmi), U8(4),
-  B(Star), R(0),
-  B(Add), R(3),
-  B(Star), R(2),
-  B(LdaSmi), U8(5),
-  B(Star), R(1),
-  B(Add), R(2),
-  B(Star), R(3),
-  B(Ldar), R(1),
-  B(Add), R(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(10),
+                B(Star), R(0),
+  /*   50 S> */ B(LdaSmi), U8(20),
+                B(Star), R(1),
+  /*   54 S> */ B(LdaSmi), U8(1),
+                B(Mov), R(0), R(2),
+                B(Star), R(0),
+  /*   68 E> */ B(Add), R(2),
+                B(Star), R(3),
+                B(LdaSmi), U8(1),
+  /*   76 E> */ B(Add), R(0),
+                B(Star), R(4),
+                B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*   88 E> */ B(Mul), R(4),
+                B(Add), R(3),
+                B(Star), R(2),
+                B(LdaSmi), U8(3),
+                B(Star), R(1),
+  /*   98 E> */ B(Add), R(2),
+                B(Star), R(3),
+                B(LdaSmi), U8(4),
+                B(Star), R(0),
+  /*  108 E> */ B(Add), R(3),
+                B(Star), R(2),
+                B(LdaSmi), U8(5),
+                B(Star), R(1),
+  /*  118 E> */ B(Add), R(2),
+                B(Star), R(3),
+                B(Ldar), R(1),
+  /*  125 E> */ B(Add), R(3),
+  /*  128 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -247,30 +247,29 @@
 "
 frame size: 4
 parameter count: 1
-bytecode array length: 38
+bytecode array length: 37
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(17),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Add), R(1),
-  B(Star), R(2),
-  B(Ldar), R(0),
-  B(ToNumber),
-  B(Star), R(1),
-  B(Inc),
-  B(Star), R(0),
-  B(Ldar), R(1),
-  B(Add), R(2),
-  B(Star), R(3),
-  B(Ldar), R(0),
-  B(ToNumber),
-  B(Inc),
-  B(Star), R(0),
-  B(Add), R(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(17),
+                B(Star), R(0),
+  /*   46 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(Ldar), R(0),
+  /*   57 E> */ B(Add), R(1),
+                B(Star), R(2),
+                B(Ldar), R(0),
+                B(ToNumber),
+                B(Star), R(1),
+                B(Inc),
+                B(Star), R(0),
+                B(Ldar), R(1),
+  /*   63 E> */ B(Add), R(2),
+                B(Star), R(3),
+                B(Ldar), R(0),
+                B(Inc),
+                B(Star), R(0),
+  /*   72 E> */ B(Add), R(3),
+  /*   76 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/BasicBlockToBoolean.golden b/test/cctest/interpreter/bytecode_expectations/BasicBlockToBoolean.golden
index ee98e5a..ed81b46 100644
--- a/test/cctest/interpreter/bytecode_expectations/BasicBlockToBoolean.golden
+++ b/test/cctest/interpreter/bytecode_expectations/BasicBlockToBoolean.golden
@@ -11,23 +11,21 @@
 snippet: "
   var a = 1; if (a || a < 0) { return 1; }
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 21
+bytecode array length: 17
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(JumpIfToBooleanTrue), U8(9),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaZero),
-  B(TestLessThan), R(1),
-  B(JumpIfToBooleanFalse), U8(5),
-  B(LdaSmi), U8(1),
-  B(Return),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(JumpIfToBooleanTrue), U8(5),
+                B(LdaZero),
+  /*   56 E> */ B(TestLessThan), R(0),
+                B(JumpIfToBooleanFalse), U8(5),
+  /*   63 S> */ B(LdaSmi), U8(1),
+  /*   75 S> */ B(Return),
+                B(LdaUndefined),
+  /*   75 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -38,23 +36,21 @@
 snippet: "
   var a = 1; if (a && a < 0) { return 1; }
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 21
+bytecode array length: 17
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(JumpIfToBooleanFalse), U8(9),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaZero),
-  B(TestLessThan), R(1),
-  B(JumpIfToBooleanFalse), U8(5),
-  B(LdaSmi), U8(1),
-  B(Return),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(JumpIfToBooleanFalse), U8(5),
+                B(LdaZero),
+  /*   56 E> */ B(TestLessThan), R(0),
+                B(JumpIfToBooleanFalse), U8(5),
+  /*   63 S> */ B(LdaSmi), U8(1),
+  /*   75 S> */ B(Return),
+                B(LdaUndefined),
+  /*   75 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -65,25 +61,23 @@
 snippet: "
   var a = 1; a = (a || a < 0) ? 2 : 3;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 26
+bytecode array length: 22
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(JumpIfToBooleanTrue), U8(9),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaZero),
-  B(TestLessThan), R(1),
-  B(JumpIfToBooleanFalse), U8(6),
-  B(LdaSmi), U8(2),
-  B(Jump), U8(4),
-  B(LdaSmi), U8(3),
-  B(Star), R(0),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(JumpIfToBooleanTrue), U8(5),
+                B(LdaZero),
+  /*   57 E> */ B(TestLessThan), R(0),
+                B(JumpIfToBooleanFalse), U8(6),
+                B(LdaSmi), U8(2),
+                B(Jump), U8(4),
+                B(LdaSmi), U8(3),
+                B(Star), R(0),
+                B(LdaUndefined),
+  /*   71 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/BasicLoops.golden b/test/cctest/interpreter/bytecode_expectations/BasicLoops.golden
index 05ee657..8be4e9d 100644
--- a/test/cctest/interpreter/bytecode_expectations/BasicLoops.golden
+++ b/test/cctest/interpreter/bytecode_expectations/BasicLoops.golden
@@ -15,12 +15,13 @@
 "
 frame size: 1
 parameter count: 1
-bytecode array length: 5
+bytecode array length: 6
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   88 S> */ B(Nop),
+  /*   98 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -37,12 +38,13 @@
 "
 frame size: 1
 parameter count: 1
-bytecode array length: 5
+bytecode array length: 6
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   77 S> */ B(Nop),
+  /*   87 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -61,45 +63,36 @@
   }
   return y;
 "
-frame size: 3
+frame size: 2
 parameter count: 1
-bytecode array length: 66
+bytecode array length: 48
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(10),
-  B(TestLessThan), R(2),
-  B(JumpIfFalse), U8(47),
-  B(StackCheck),
-  B(Ldar), R(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(12),
-  B(Mul), R(2),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Add), R(2),
-  B(Star), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(3),
-  B(TestEqual), R(2),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(-39),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(4),
-  B(TestEqual), R(2),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(4),
-  B(Jump), U8(-53),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   53 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+  /*   65 S> */ B(LdaSmi), U8(10),
+  /*   65 E> */ B(TestLessThan), R(0),
+                B(JumpIfFalse), U8(33),
+  /*   56 E> */ B(StackCheck),
+  /*   75 S> */ B(LdaSmi), U8(12),
+                B(Mul), R(1),
+                B(Star), R(1),
+  /*   89 S> */ B(LdaSmi), U8(1),
+                B(Add), R(0),
+                B(Star), R(0),
+  /*  102 S> */ B(LdaSmi), U8(3),
+  /*  108 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*  114 S> */ B(Jump), U8(10),
+  /*  126 S> */ B(LdaSmi), U8(4),
+  /*  132 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*  138 S> */ B(Jump), U8(4),
+                B(Jump), U8(-35),
+  /*  147 S> */ B(Ldar), R(1),
+  /*  157 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -119,52 +112,40 @@
   }
   return i;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 79
+bytecode array length: 55
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaZero),
-  B(TestLessThan), R(1),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(-10),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(TestEqual), R(1),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(50),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(4),
-  B(TestEqual), R(1),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(38),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(10),
-  B(TestEqual), R(1),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(-46),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(5),
-  B(TestEqual), R(1),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(14),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(Add), R(1),
-  B(Star), R(0),
-  B(Jump), U8(-70),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   45 E> */ B(StackCheck),
+  /*   62 S> */ B(LdaZero),
+  /*   68 E> */ B(TestLessThan), R(0),
+                B(JumpIfFalse), U8(4),
+  /*   73 S> */ B(Jump), U8(40),
+  /*   85 S> */ B(LdaSmi), U8(3),
+  /*   91 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*   97 S> */ B(Jump), U8(34),
+  /*  106 S> */ B(LdaSmi), U8(4),
+  /*  112 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*  118 S> */ B(Jump), U8(26),
+  /*  127 S> */ B(LdaSmi), U8(10),
+  /*  133 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*  140 S> */ B(Jump), U8(16),
+  /*  152 S> */ B(LdaSmi), U8(5),
+  /*  158 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*  164 S> */ B(Jump), U8(10),
+  /*  173 S> */ B(LdaSmi), U8(1),
+                B(Add), R(0),
+                B(Star), R(0),
+                B(Jump), U8(-46),
+  /*  186 S> */ B(Ldar), R(0),
+  /*  196 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -184,41 +165,33 @@
   }
   return i;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 57
+bytecode array length: 41
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(TestLessThan), R(1),
-  B(JumpIfFalse), U8(27),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(TestEqual), R(1),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(14),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(Add), R(1),
-  B(Star), R(0),
-  B(Jump), U8(-33),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(Add), R(1),
-  B(Star), R(0),
-  B(Jump), U8(4),
-  B(Jump), U8(-48),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   45 E> */ B(StackCheck),
+  /*   71 S> */ B(LdaSmi), U8(3),
+  /*   71 E> */ B(TestLessThan), R(0),
+                B(JumpIfFalse), U8(19),
+  /*   62 E> */ B(StackCheck),
+  /*   82 S> */ B(LdaSmi), U8(2),
+  /*   88 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*   94 S> */ B(Jump), U8(10),
+  /*  105 S> */ B(LdaSmi), U8(1),
+                B(Add), R(0),
+                B(Star), R(0),
+                B(Jump), U8(-21),
+  /*  122 S> */ B(LdaSmi), U8(1),
+                B(Add), R(0),
+                B(Star), R(0),
+  /*  135 S> */ B(Jump), U8(4),
+                B(Jump), U8(-32),
+  /*  144 S> */ B(Ldar), R(0),
+  /*  154 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -235,31 +208,27 @@
   }
   return y;
 "
-frame size: 3
+frame size: 2
 parameter count: 1
-bytecode array length: 39
+bytecode array length: 31
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(JumpIfToBooleanFalse), U8(25),
-  B(StackCheck),
-  B(Ldar), R(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(12),
-  B(Mul), R(2),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Sub), R(2),
-  B(Star), R(0),
-  B(Jump), U8(-25),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(10),
+                B(Star), R(0),
+  /*   54 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+  /*   64 S> */ B(Ldar), R(0),
+                B(JumpIfToBooleanFalse), U8(17),
+  /*   57 E> */ B(StackCheck),
+  /*   71 S> */ B(LdaSmi), U8(12),
+                B(Mul), R(1),
+                B(Star), R(1),
+  /*   85 S> */ B(LdaSmi), U8(1),
+                B(Sub), R(0),
+                B(Star), R(0),
+                B(Jump), U8(-17),
+  /*   98 S> */ B(Ldar), R(1),
+  /*  108 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -277,45 +246,35 @@
   } while (x < 10);
   return y;
 "
-frame size: 3
+frame size: 2
 parameter count: 1
-bytecode array length: 66
+bytecode array length: 46
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(StackCheck),
-  B(Ldar), R(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(10),
-  B(Mul), R(2),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(5),
-  B(TestEqual), R(2),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(34),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(6),
-  B(TestEqual), R(2),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(12),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Add), R(2),
-  B(Star), R(0),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(10),
-  B(TestLessThan), R(2),
-  B(JumpIfTrue), U8(-53),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   53 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+  /*   56 E> */ B(StackCheck),
+  /*   63 S> */ B(LdaSmi), U8(10),
+                B(Mul), R(1),
+                B(Star), R(1),
+  /*   77 S> */ B(LdaSmi), U8(5),
+  /*   83 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*   89 S> */ B(Jump), U8(22),
+  /*   98 S> */ B(LdaSmi), U8(6),
+  /*  104 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*  110 S> */ B(Jump), U8(8),
+  /*  122 S> */ B(LdaSmi), U8(1),
+                B(Add), R(0),
+                B(Star), R(0),
+  /*  144 S> */ B(LdaSmi), U8(10),
+  /*  144 E> */ B(TestLessThan), R(0),
+                B(JumpIfTrue), U8(-33),
+  /*  151 S> */ B(Ldar), R(1),
+  /*  161 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -332,30 +291,26 @@
   } while (x);
   return y;
 "
-frame size: 3
+frame size: 2
 parameter count: 1
-bytecode array length: 37
+bytecode array length: 29
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(StackCheck),
-  B(Ldar), R(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(12),
-  B(Mul), R(2),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Sub), R(2),
-  B(Star), R(0),
-  B(Ldar), R(0),
-  B(JumpIfToBooleanTrue), U8(-23),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(10),
+                B(Star), R(0),
+  /*   54 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+  /*   57 E> */ B(StackCheck),
+  /*   64 S> */ B(LdaSmi), U8(12),
+                B(Mul), R(1),
+                B(Star), R(1),
+  /*   78 S> */ B(LdaSmi), U8(1),
+                B(Sub), R(0),
+                B(Star), R(0),
+  /*   98 S> */ B(Ldar), R(0),
+                B(JumpIfToBooleanTrue), U8(-15),
+  /*  102 S> */ B(Ldar), R(1),
+  /*  112 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -373,39 +328,32 @@
   } while (false);
   return y;
 "
-frame size: 3
+frame size: 2
 parameter count: 1
-bytecode array length: 54
+bytecode array length: 40
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(StackCheck),
-  B(Ldar), R(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(10),
-  B(Mul), R(2),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(5),
-  B(TestEqual), R(2),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(22),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Add), R(2),
-  B(Star), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(6),
-  B(TestEqual), R(2),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(2),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   53 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+  /*   56 E> */ B(StackCheck),
+  /*   63 S> */ B(LdaSmi), U8(10),
+                B(Mul), R(1),
+                B(Star), R(1),
+  /*   77 S> */ B(LdaSmi), U8(5),
+  /*   83 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*   89 S> */ B(Jump), U8(16),
+  /*   98 S> */ B(LdaSmi), U8(1),
+                B(Add), R(0),
+                B(Star), R(0),
+  /*  111 S> */ B(LdaSmi), U8(6),
+  /*  117 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*  123 S> */ B(Jump), U8(2),
+  /*  150 S> */ B(Ldar), R(1),
+  /*  160 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -423,40 +371,33 @@
   } while (true);
   return y;
 "
-frame size: 3
+frame size: 2
 parameter count: 1
-bytecode array length: 56
+bytecode array length: 42
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(StackCheck),
-  B(Ldar), R(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(10),
-  B(Mul), R(2),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(5),
-  B(TestEqual), R(2),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(24),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Add), R(2),
-  B(Star), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(6),
-  B(TestEqual), R(2),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(-41),
-  B(Jump), U8(-43),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   53 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+  /*   56 E> */ B(StackCheck),
+  /*   63 S> */ B(LdaSmi), U8(10),
+                B(Mul), R(1),
+                B(Star), R(1),
+  /*   77 S> */ B(LdaSmi), U8(5),
+  /*   83 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*   89 S> */ B(Jump), U8(18),
+  /*   98 S> */ B(LdaSmi), U8(1),
+                B(Add), R(0),
+                B(Star), R(0),
+  /*  111 S> */ B(LdaSmi), U8(6),
+  /*  117 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*  123 S> */ B(Jump), U8(2),
+                B(Jump), U8(-29),
+  /*  149 S> */ B(Ldar), R(1),
+  /*  159 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -472,34 +413,28 @@
     x = x + 1;
   }
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 43
+bytecode array length: 31
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(TestEqual), R(1),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(26),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(TestEqual), R(1),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(-23),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(Add), R(1),
-  B(Star), R(0),
-  B(Jump), U8(-35),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   45 E> */ B(StackCheck),
+  /*   58 S> */ B(LdaSmi), U8(1),
+  /*   64 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*   70 S> */ B(Jump), U8(18),
+  /*   79 S> */ B(LdaSmi), U8(2),
+  /*   85 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*   91 S> */ B(Jump), U8(8),
+  /*  103 S> */ B(LdaSmi), U8(1),
+                B(Add), R(0),
+                B(Star), R(0),
+                B(Jump), U8(-23),
+                B(LdaUndefined),
+  /*  116 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -514,34 +449,28 @@
     x = x + 1;
   }
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 43
+bytecode array length: 31
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(TestEqual), R(1),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(26),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(TestEqual), R(1),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(-23),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(Add), R(1),
-  B(Star), R(0),
-  B(Jump), U8(-35),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   47 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   34 E> */ B(StackCheck),
+  /*   56 S> */ B(LdaSmi), U8(1),
+  /*   62 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*   68 S> */ B(Jump), U8(18),
+  /*   77 S> */ B(LdaSmi), U8(2),
+  /*   83 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*   89 S> */ B(Jump), U8(8),
+  /*  101 S> */ B(LdaSmi), U8(1),
+                B(Add), R(0),
+                B(Star), R(0),
+                B(Jump), U8(-23),
+                B(LdaUndefined),
+  /*  114 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -556,34 +485,28 @@
     if (x == 2) continue;
   }
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 43
+bytecode array length: 31
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(TestEqual), R(1),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(26),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(TestEqual), R(1),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(2),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(Add), R(1),
-  B(Star), R(0),
-  B(Jump), U8(-35),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   45 E> */ B(StackCheck),
+  /*   68 S> */ B(LdaSmi), U8(1),
+  /*   74 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*   80 S> */ B(Jump), U8(18),
+  /*   89 S> */ B(LdaSmi), U8(2),
+  /*   95 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*  101 S> */ B(Jump), U8(2),
+  /*   55 S> */ B(LdaSmi), U8(1),
+                B(Add), R(0),
+                B(Star), R(0),
+                B(Jump), U8(-23),
+                B(LdaUndefined),
+  /*  113 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -597,34 +520,28 @@
     if (x == 2) continue;
   }
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 43
+bytecode array length: 31
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(TestEqual), R(1),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(26),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(TestEqual), R(1),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(2),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(Add), R(1),
-  B(Star), R(0),
-  B(Jump), U8(-35),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   47 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   34 E> */ B(StackCheck),
+  /*   66 S> */ B(LdaSmi), U8(1),
+  /*   72 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*   78 S> */ B(Jump), U8(18),
+  /*   87 S> */ B(LdaSmi), U8(2),
+  /*   93 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*   99 S> */ B(Jump), U8(2),
+  /*   53 S> */ B(LdaSmi), U8(1),
+                B(Add), R(0),
+                B(Star), R(0),
+                B(Jump), U8(-23),
+                B(LdaUndefined),
+  /*  111 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -639,35 +556,29 @@
     continue;
   }
 "
-frame size: 3
+frame size: 2
 parameter count: 1
-bytecode array length: 44
+bytecode array length: 32
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(LdaZero),
-  B(Star), R(1),
-  B(Ldar), R(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(100),
-  B(TestLessThan), R(2),
-  B(JumpIfFalse), U8(27),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Add), R(2),
-  B(Star), R(0),
-  B(Jump), U8(2),
-  B(Ldar), R(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Add), R(2),
-  B(Star), R(1),
-  B(Jump), U8(-33),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   58 S> */ B(LdaZero),
+                B(Star), R(1),
+  /*   63 S> */ B(LdaSmi), U8(100),
+  /*   63 E> */ B(TestLessThan), R(1),
+                B(JumpIfFalse), U8(19),
+  /*   45 E> */ B(StackCheck),
+  /*   85 S> */ B(LdaSmi), U8(1),
+                B(Add), R(0),
+                B(Star), R(0),
+  /*   98 S> */ B(Jump), U8(2),
+  /*   72 S> */ B(LdaSmi), U8(1),
+                B(Add), R(1),
+                B(Star), R(1),
+                B(Jump), U8(-21),
+                B(LdaUndefined),
+  /*  110 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -682,30 +593,27 @@
   }
   return y;
 "
-frame size: 3
+frame size: 2
 parameter count: 1
-bytecode array length: 35
+bytecode array length: 30
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(LdaSmi), U8(10),
-  B(Star), R(1),
-  B(Ldar), R(1),
-  B(JumpIfToBooleanFalse), U8(21),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(12),
-  B(Mul), R(2),
-  B(Star), R(0),
-  B(Ldar), R(1),
-  B(ToNumber),
-  B(Dec),
-  B(Star), R(1),
-  B(Jump), U8(-21),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   58 S> */ B(LdaSmi), U8(10),
+                B(Star), R(1),
+  /*   62 S> */ B(Ldar), R(1),
+                B(JumpIfToBooleanFalse), U8(16),
+  /*   45 E> */ B(StackCheck),
+  /*   74 S> */ B(LdaSmi), U8(12),
+                B(Mul), R(0),
+                B(Star), R(0),
+  /*   67 S> */ B(Ldar), R(1),
+                B(Dec),
+                B(Star), R(1),
+                B(Jump), U8(-16),
+  /*   88 S> */ B(Ldar), R(0),
+  /*   98 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -724,13 +632,13 @@
 parameter count: 1
 bytecode array length: 10
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(LdaZero),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   58 S> */ B(LdaZero),
+                B(Star), R(1),
+  /*   91 S> */ B(Ldar), R(0),
+  /*  101 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -746,33 +654,29 @@
   };
   return x;
 "
-frame size: 3
+frame size: 2
 parameter count: 1
-bytecode array length: 39
+bytecode array length: 32
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(LdaZero),
-  B(Star), R(1),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Add), R(2),
-  B(Star), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(20),
-  B(TestEqual), R(2),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(10),
-  B(Ldar), R(1),
-  B(ToNumber),
-  B(Inc),
-  B(Star), R(1),
-  B(Jump), U8(-27),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   58 S> */ B(LdaZero),
+                B(Star), R(1),
+  /*   45 E> */ B(StackCheck),
+  /*   76 S> */ B(LdaSmi), U8(1),
+                B(Add), R(0),
+                B(Star), R(0),
+  /*   89 S> */ B(LdaSmi), U8(20),
+  /*   95 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+  /*  102 S> */ B(Jump), U8(9),
+  /*   69 S> */ B(Ldar), R(1),
+                B(Inc),
+                B(Star), R(1),
+                B(Jump), U8(-20),
+  /*  112 S> */ B(Ldar), R(0),
+  /*  122 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -793,61 +697,60 @@
 "
 frame size: 7
 parameter count: 1
-bytecode array length: 120
+bytecode array length: 119
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(1),
-  B(Ldar), R(1),
-  B(JumpIfToBooleanFalse), U8(112),
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(4),
-  B(Ldar), R(closure),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kPushBlockContext), R(4), U8(2),
-  B(PushContext), R(3),
-  B(LdaTheHole),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(1), U8(0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StaContextSlot), R(context), U8(4),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(2),
-  B(Star), R(4),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
-  B(Star), R(2),
-  B(LdaContextSlot), R(context), U8(4),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(3),
-  B(Star), R(4),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
-  B(JumpIfToBooleanFalse), U8(8),
-  B(PopContext), R(3),
-  B(PopContext), R(3),
-  B(Jump), U8(-69),
-  B(LdaContextSlot), R(context), U8(4),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(3),
-  B(Star), R(4),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
-  B(ToNumber),
-  B(Star), R(4),
-  B(Inc),
-  B(Star), R(5),
-  B(LdaContextSlot), R(context), U8(4),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(3),
-  B(Star), R(6),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(6), U8(1),
-  B(Ldar), R(5),
-  B(StaContextSlot), R(context), U8(4),
-  B(PopContext), R(3),
-  B(Jump), U8(-112),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(1),
+  /*   52 S> */ B(Ldar), R(1),
+                B(JumpIfToBooleanFalse), U8(111),
+  /*   45 E> */ B(StackCheck),
+                B(LdaConstant), U8(0),
+                B(Star), R(4),
+                B(Mov), R(closure), R(5),
+                B(CallRuntime), U16(Runtime::kPushBlockContext), R(4), U8(2),
+                B(PushContext), R(3),
+                B(LdaTheHole),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateClosure), U8(1), U8(0),
+                B(Star), R(0),
+  /*   73 S> */ B(LdaSmi), U8(1),
+  /*   73 E> */ B(StaContextSlot), R(context), U8(4),
+                B(Ldar), R(0),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(2),
+                B(Star), R(4),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
+                B(Star), R(2),
+  /*  106 S> */ B(LdaContextSlot), R(context), U8(4),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(3),
+                B(Star), R(4),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
+                B(JumpIfToBooleanFalse), U8(8),
+  /*  113 S> */ B(PopContext), R(3),
+                B(PopContext), R(3),
+                B(Jump), U8(43),
+  /*  126 S> */ B(LdaContextSlot), R(context), U8(4),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(3),
+                B(Star), R(4),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
+                B(ToNumber),
+                B(Star), R(4),
+                B(Inc),
+                B(Star), R(5),
+  /*  127 E> */ B(LdaContextSlot), R(context), U8(4),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(3),
+                B(Star), R(6),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(6), U8(1),
+                B(Ldar), R(5),
+                B(StaContextSlot), R(context), U8(4),
+                B(PopContext), R(3),
+                B(Jump), U8(-111),
+                B(LdaUndefined),
+  /*  137 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/BreakableBlocks.golden b/test/cctest/interpreter/bytecode_expectations/BreakableBlocks.golden
index 162297d..fab6901 100644
--- a/test/cctest/interpreter/bytecode_expectations/BreakableBlocks.golden
+++ b/test/cctest/interpreter/bytecode_expectations/BreakableBlocks.golden
@@ -17,20 +17,19 @@
   }
   return x;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 17
+bytecode array length: 15
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(Add), R(1),
-  B(Star), R(0),
-  B(Jump), U8(2),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   56 S> */ B(LdaSmi), U8(1),
+                B(Add), R(0),
+                B(Star), R(0),
+  /*   69 S> */ B(Jump), U8(2),
+  /*   97 S> */ B(Ldar), R(0),
+  /*  107 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -52,52 +51,43 @@
 "
 frame size: 5
 parameter count: 1
-bytecode array length: 75
+bytecode array length: 60
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(LdaZero),
-  B(Star), R(1),
-  B(Ldar), R(1),
-  B(Star), R(3),
-  B(LdaSmi), U8(10),
-  B(TestLessThan), R(3),
-  B(JumpIfFalse), U8(57),
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(2),
-  B(Ldar), R(2),
-  B(Star), R(3),
-  B(LdaSmi), U8(3),
-  B(TestLessThan), R(3),
-  B(JumpIfFalse), U8(35),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(ToNumber),
-  B(Inc),
-  B(Star), R(0),
-  B(Ldar), R(1),
-  B(Star), R(3),
-  B(Ldar), R(2),
-  B(Add), R(3),
-  B(Star), R(4),
-  B(LdaSmi), U8(12),
-  B(TestEqual), R(4),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(18),
-  B(Ldar), R(2),
-  B(ToNumber),
-  B(Inc),
-  B(Star), R(2),
-  B(Jump), U8(-41),
-  B(Ldar), R(1),
-  B(ToNumber),
-  B(Inc),
-  B(Star), R(1),
-  B(Jump), U8(-63),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   44 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   71 S> */ B(LdaZero),
+                B(Star), R(1),
+  /*   76 S> */ B(LdaSmi), U8(10),
+  /*   76 E> */ B(TestLessThan), R(1),
+                B(JumpIfFalse), U8(46),
+  /*   58 E> */ B(StackCheck),
+  /*  106 S> */ B(LdaZero),
+                B(Star), R(2),
+  /*  111 S> */ B(LdaSmi), U8(3),
+  /*  111 E> */ B(TestLessThan), R(2),
+                B(JumpIfFalse), U8(29),
+  /*   93 E> */ B(StackCheck),
+  /*  129 S> */ B(Ldar), R(0),
+                B(Inc),
+                B(Star), R(0),
+  /*  142 S> */ B(Ldar), R(2),
+  /*  150 E> */ B(Add), R(1),
+                B(Star), R(4),
+                B(LdaSmi), U8(12),
+  /*  152 E> */ B(TestEqual), R(4),
+                B(JumpIfFalse), U8(4),
+  /*  161 S> */ B(Jump), U8(16),
+  /*  118 S> */ B(Ldar), R(2),
+                B(Inc),
+                B(Star), R(2),
+                B(Jump), U8(-31),
+  /*   84 S> */ B(Ldar), R(1),
+                B(Inc),
+                B(Star), R(1),
+                B(Jump), U8(-48),
+  /*  188 S> */ B(Ldar), R(0),
+  /*  200 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -114,31 +104,30 @@
 "
 frame size: 5
 parameter count: 1
-bytecode array length: 51
+bytecode array length: 50
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(3),
-  B(Ldar), R(closure),
-  B(Star), R(4),
-  B(CallRuntime), U16(Runtime::kPushBlockContext), R(3), U8(2),
-  B(PushContext), R(2),
-  B(LdaTheHole),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(1), U8(0),
-  B(Star), R(0),
-  B(LdaSmi), U8(10),
-  B(StaContextSlot), R(context), U8(4),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(2),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
-  B(Star), R(1),
-  B(Jump), U8(2),
-  B(PopContext), R(2),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+                B(LdaConstant), U8(0),
+                B(Star), R(3),
+                B(Mov), R(closure), R(4),
+                B(CallRuntime), U16(Runtime::kPushBlockContext), R(3), U8(2),
+                B(PushContext), R(2),
+                B(LdaTheHole),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateClosure), U8(1), U8(0),
+                B(Star), R(0),
+  /*   53 S> */ B(LdaSmi), U8(10),
+  /*   53 E> */ B(StaContextSlot), R(context), U8(4),
+                B(Ldar), R(0),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(2),
+                B(Star), R(3),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
+                B(Star), R(1),
+  /*   88 S> */ B(Jump), U8(2),
+                B(PopContext), R(2),
+                B(LdaUndefined),
+  /*  103 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -163,62 +152,61 @@
 "
 frame size: 6
 parameter count: 1
-bytecode array length: 131
+bytecode array length: 130
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(2),
-  B(LdaTheHole),
-  B(StaContextSlot), R(context), U8(4),
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaConstant), U8(0),
-  B(Star), R(4),
-  B(Ldar), R(closure),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kPushBlockContext), R(4), U8(2),
-  B(PushContext), R(3),
-  B(LdaTheHole),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(1), U8(0),
-  B(Star), R(0),
-  B(LdaSmi), U8(2),
-  B(StaContextSlot), R(context), U8(4),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(2),
-  B(Star), R(4),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
-  B(Star), R(1),
-  B(LdaContextSlot), R(context), U8(4),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(3),
-  B(Star), R(4),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
-  B(JumpIfToBooleanFalse), U8(6),
-  B(PopContext), R(3),
-  B(Jump), U8(27),
-  B(LdaSmi), U8(3),
-  B(Star), R(4),
-  B(LdaContextSlot), R(context), U8(4),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(3),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1),
-  B(Ldar), R(4),
-  B(StaContextSlot), R(context), U8(4),
-  B(PopContext), R(3),
-  B(LdaSmi), U8(4),
-  B(Star), R(4),
-  B(LdaContextSlot), R(context), U8(4),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(4),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1),
-  B(Ldar), R(4),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaUndefined),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(2),
+                B(LdaTheHole),
+                B(StaContextSlot), R(context), U8(4),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+  /*   42 E> */ B(StaContextSlot), R(context), U8(4),
+                B(LdaConstant), U8(0),
+                B(Star), R(4),
+                B(Mov), R(closure), R(5),
+                B(CallRuntime), U16(Runtime::kPushBlockContext), R(4), U8(2),
+                B(PushContext), R(3),
+                B(LdaTheHole),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateClosure), U8(1), U8(0),
+                B(Star), R(0),
+  /*   76 S> */ B(LdaSmi), U8(2),
+  /*   76 E> */ B(StaContextSlot), R(context), U8(4),
+                B(Ldar), R(0),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(2),
+                B(Star), R(4),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
+                B(Star), R(1),
+  /*  118 S> */ B(LdaContextSlot), R(context), U8(4),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(3),
+                B(Star), R(4),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
+                B(JumpIfToBooleanFalse), U8(6),
+  /*  125 S> */ B(PopContext), R(3),
+                B(Jump), U8(27),
+  /*  142 S> */ B(LdaSmi), U8(3),
+                B(Star), R(4),
+  /*  144 E> */ B(LdaContextSlot), R(context), U8(4),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(3),
+                B(Star), R(5),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1),
+                B(Ldar), R(4),
+                B(StaContextSlot), R(context), U8(4),
+                B(PopContext), R(3),
+  /*  155 S> */ B(LdaSmi), U8(4),
+                B(Star), R(4),
+  /*  157 E> */ B(LdaContextSlot), R(context), U8(4),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(4),
+                B(Star), R(5),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1),
+                B(Ldar), R(4),
+                B(StaContextSlot), R(context), U8(4),
+                B(LdaUndefined),
+  /*  162 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/CallGlobal.golden b/test/cctest/interpreter/bytecode_expectations/CallGlobal.golden
index 04bc3a9..45fb07a 100644
--- a/test/cctest/interpreter/bytecode_expectations/CallGlobal.golden
+++ b/test/cctest/interpreter/bytecode_expectations/CallGlobal.golden
@@ -16,18 +16,15 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 15
+bytecode array length: 12
 bytecodes: [
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Star), R(1),
-  B(LdaGlobal), U8(0), U8(3),
-  B(Star), R(0),
-  B(Call), R(0), R(1), U8(1), U8(1),
-  B(Return),
+  /*   27 E> */ B(StackCheck),
+  /*   32 S> */ B(LdrUndefined), R(1),
+                B(LdrGlobal), U8(3), R(0),
+  /*   39 E> */ B(Call), R(0), R(1), U8(1), U8(1),
+  /*   44 S> */ B(Return),
 ]
 constant pool: [
-  "t",
 ]
 handlers: [
 ]
@@ -40,24 +37,21 @@
 "
 frame size: 5
 parameter count: 1
-bytecode array length: 27
+bytecode array length: 24
 bytecodes: [
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Star), R(1),
-  B(LdaGlobal), U8(0), U8(3),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(2),
-  B(Star), R(3),
-  B(LdaSmi), U8(3),
-  B(Star), R(4),
-  B(Call), R(0), R(1), U8(4), U8(1),
-  B(Return),
+  /*   34 E> */ B(StackCheck),
+  /*   39 S> */ B(LdrUndefined), R(1),
+                B(LdrGlobal), U8(3), R(0),
+                B(LdaSmi), U8(1),
+                B(Star), R(2),
+                B(LdaSmi), U8(2),
+                B(Star), R(3),
+                B(LdaSmi), U8(3),
+                B(Star), R(4),
+  /*   46 E> */ B(Call), R(0), R(1), U8(4), U8(1),
+  /*   58 S> */ B(Return),
 ]
 constant pool: [
-  "t",
 ]
 handlers: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/CallLookupSlot.golden b/test/cctest/interpreter/bytecode_expectations/CallLookupSlot.golden
index 30b69d3..792faf3 100644
--- a/test/cctest/interpreter/bytecode_expectations/CallLookupSlot.golden
+++ b/test/cctest/interpreter/bytecode_expectations/CallLookupSlot.golden
@@ -11,41 +11,43 @@
 snippet: "
   g = function(){}; eval(''); return g();
 "
-frame size: 9
+frame size: 10
 parameter count: 1
-bytecode array length: 85
+bytecode array length: 89
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(0),
-  B(Ldar), R(this),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateMappedArguments),
-  B(StaContextSlot), R(context), U8(5),
-  B(Ldar), R(new_target),
-  B(StaContextSlot), R(context), U8(6),
-  B(StackCheck),
-  B(CreateClosure), U8(0), U8(0),
-  B(StaLookupSlotSloppy), U8(1),
-  B(LdaConstant), U8(2),
-  B(Star), R(3),
-  B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(3), U8(1), R(1),
-  B(LdaConstant), U8(3),
-  B(Star), R(3),
-  B(Mov), R(1), R(4),
-  B(Mov), R(3), R(5),
-  B(Mov), R(closure), R(6),
-  B(LdaZero),
-  B(Star), R(7),
-  B(LdaSmi), U8(30),
-  B(Star), R(8),
-  B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(5),
-  B(Star), R(1),
-  B(Call), R(1), R(2), U8(2), U8(0),
-  B(LdaConstant), U8(1),
-  B(Star), R(3),
-  B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(3), U8(1), R(1),
-  B(Call), R(1), R(2), U8(1), U8(3),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+                B(Ldar), R(this),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateMappedArguments),
+                B(StaContextSlot), R(context), U8(5),
+                B(Ldar), R(new_target),
+                B(StaContextSlot), R(context), U8(6),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(CreateClosure), U8(0), U8(0),
+  /*   36 E> */ B(StaLookupSlotSloppy), U8(1),
+  /*   52 S> */ B(LdaConstant), U8(2),
+                B(Star), R(3),
+                B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(3), U8(1), R(1),
+                B(LdaConstant), U8(3),
+                B(Star), R(3),
+                B(LdaZero),
+                B(Star), R(7),
+                B(LdaSmi), U8(30),
+                B(Star), R(8),
+                B(LdaSmi), U8(52),
+                B(Star), R(9),
+                B(Mov), R(1), R(4),
+                B(Mov), R(3), R(5),
+                B(Mov), R(closure), R(6),
+                B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6),
+                B(Star), R(1),
+  /*   52 E> */ B(Call), R(1), R(2), U8(2), U8(0),
+  /*   62 S> */ B(LdaConstant), U8(1),
+                B(Star), R(3),
+                B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(3), U8(1), R(1),
+  /*   69 E> */ B(Call), R(1), R(2), U8(1), U8(3),
+  /*   74 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/CallNew.golden b/test/cctest/interpreter/bytecode_expectations/CallNew.golden
index 4952c73..2ee9613 100644
--- a/test/cctest/interpreter/bytecode_expectations/CallNew.golden
+++ b/test/cctest/interpreter/bytecode_expectations/CallNew.golden
@@ -18,14 +18,13 @@
 parameter count: 1
 bytecode array length: 11
 bytecodes: [
-  B(StackCheck),
-  B(LdaGlobal), U8(0), U8(2),
-  B(Star), R(0),
-  B(New), R(0), R(0), U8(0),
-  B(Return),
+  /*   45 E> */ B(StackCheck),
+  /*   50 S> */ B(LdrGlobal), U8(3), R(0),
+                B(Ldar), R(0),
+  /*   57 E> */ B(New), R(0), R(0), U8(0),
+  /*   68 S> */ B(Return),
 ]
 constant pool: [
-  InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
 ]
 handlers: [
 ]
@@ -38,19 +37,17 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 17
+bytecode array length: 15
 bytecodes: [
-  B(StackCheck),
-  B(LdaGlobal), U8(0), U8(2),
-  B(Star), R(0),
-  B(LdaSmi), U8(3),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(New), R(0), R(1), U8(1),
-  B(Return),
+  /*   58 E> */ B(StackCheck),
+  /*   63 S> */ B(LdrGlobal), U8(3), R(0),
+                B(LdaSmi), U8(3),
+                B(Star), R(1),
+                B(Ldar), R(0),
+  /*   70 E> */ B(New), R(0), R(1), U8(1),
+  /*   82 S> */ B(Return),
 ]
 constant pool: [
-  InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
 ]
 handlers: [
 ]
@@ -68,23 +65,21 @@
 "
 frame size: 4
 parameter count: 1
-bytecode array length: 25
+bytecode array length: 23
 bytecodes: [
-  B(StackCheck),
-  B(LdaGlobal), U8(0), U8(2),
-  B(Star), R(0),
-  B(LdaSmi), U8(3),
-  B(Star), R(1),
-  B(LdaSmi), U8(4),
-  B(Star), R(2),
-  B(LdaSmi), U8(5),
-  B(Star), R(3),
-  B(Ldar), R(0),
-  B(New), R(0), R(1), U8(3),
-  B(Return),
+  /*  100 E> */ B(StackCheck),
+  /*  105 S> */ B(LdrGlobal), U8(3), R(0),
+                B(LdaSmi), U8(3),
+                B(Star), R(1),
+                B(LdaSmi), U8(4),
+                B(Star), R(2),
+                B(LdaSmi), U8(5),
+                B(Star), R(3),
+                B(Ldar), R(0),
+  /*  112 E> */ B(New), R(0), R(1), U8(3),
+  /*  130 S> */ B(Return),
 ]
 constant pool: [
-  InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
 ]
 handlers: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/CallRuntime.golden b/test/cctest/interpreter/bytecode_expectations/CallRuntime.golden
index ec10e67..0a88098 100644
--- a/test/cctest/interpreter/bytecode_expectations/CallRuntime.golden
+++ b/test/cctest/interpreter/bytecode_expectations/CallRuntime.golden
@@ -17,10 +17,10 @@
 parameter count: 1
 bytecode array length: 8
 bytecodes: [
-  B(StackCheck),
-  B(CallRuntime), U16(Runtime::kTheHole), R(0), U8(0),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   15 S> */ B(CallRuntime), U16(Runtime::kTheHole), R(0), U8(0),
+                B(LdaUndefined),
+  /*   26 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -32,15 +32,13 @@
   function f(a) { return %IsArray(a) }
   f(undefined);
 "
-frame size: 1
+frame size: 0
 parameter count: 2
-bytecode array length: 11
+bytecode array length: 7
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(CallRuntime), U16(Runtime::kIsArray), R(0), U8(1),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   16 S> */ B(CallRuntime), U16(Runtime::kIsArray), R(arg0), U8(1),
+  /*   35 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -56,13 +54,13 @@
 parameter count: 1
 bytecode array length: 15
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(CallRuntime), U16(Runtime::kAdd), R(0), U8(2),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   15 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+                B(LdaSmi), U8(2),
+                B(Star), R(1),
+                B(CallRuntime), U16(Runtime::kAdd), R(0), U8(2),
+  /*   33 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -76,15 +74,14 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 15
+bytecode array length: 14
 bytecodes: [
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Star), R(0),
-  B(CreateArrayLiteral), U8(0), U8(0), U8(3),
-  B(Star), R(1),
-  B(CallJSRuntime), U8(115), R(0), U8(2),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   15 S> */ B(LdrUndefined), R(0),
+                B(CreateArrayLiteral), U8(0), U8(0), U8(3),
+                B(Star), R(1),
+                B(CallJSRuntime), U8(129), R(0), U8(2),
+  /*   44 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden b/test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden
index 6869c5b..dc1e110 100644
--- a/test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden
+++ b/test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden
@@ -24,32 +24,29 @@
 "
 frame size: 7
 parameter count: 1
-bytecode array length: 57
+bytecode array length: 54
 bytecodes: [
-  B(Ldar), R(closure),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(this),
-  B(Star), R(3),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(0),
-  B(Star), R(6),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(6), U8(1),
-  B(Star), R(6),
-  B(LdaConstant), U8(1),
-  B(KeyedLoadIC), R(6), U8(3),
-  B(Star), R(4),
-  B(LdaConstant), U8(2),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kLoadFromSuper), R(3), U8(3),
-  B(Mov), R(3), R(2),
-  B(Star), R(1),
-  B(Call), R(1), R(2), U8(1), U8(1),
-  B(Star), R(3),
-  B(LdaSmi), U8(1),
-  B(Add), R(3),
-  B(Return),
+                B(Mov), R(closure), R(0),
+  /*   99 E> */ B(StackCheck),
+  /*  104 S> */ B(Mov), R(this), R(3),
+                B(Ldar), R(closure),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(0),
+                B(Star), R(6),
+  /*  111 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(6), U8(1),
+                B(Star), R(6),
+                B(LdaConstant), U8(1),
+  /*  111 E> */ B(LdrKeyedProperty), R(6), U8(3), R(4),
+                B(LdaConstant), U8(2),
+                B(Star), R(5),
+                B(CallRuntime), U16(Runtime::kLoadFromSuper), R(3), U8(3),
+                B(Mov), R(3), R(2),
+                B(Star), R(1),
+  /*  117 E> */ B(Call), R(1), R(2), U8(1), U8(1),
+                B(Star), R(3),
+                B(LdaSmi), U8(1),
+                B(Add), R(3),
+  /*  131 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
@@ -76,42 +73,37 @@
 "
 frame size: 6
 parameter count: 1
-bytecode array length: 80
+bytecode array length: 75
 bytecodes: [
-  B(Ldar), R(closure),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(this),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(0),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1),
-  B(Star), R(5),
-  B(LdaConstant), U8(1),
-  B(KeyedLoadIC), R(5), U8(1),
-  B(Star), R(2),
-  B(LdaConstant), U8(2),
-  B(Star), R(3),
-  B(LdaSmi), U8(2),
-  B(Star), R(4),
-  B(CallRuntime), U16(Runtime::kStoreToSuper_Strict), R(1), U8(4),
-  B(Ldar), R(this),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(0),
-  B(Star), R(4),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
-  B(Star), R(4),
-  B(LdaConstant), U8(1),
-  B(KeyedLoadIC), R(4), U8(3),
-  B(Star), R(2),
-  B(LdaConstant), U8(2),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kLoadFromSuper), R(1), U8(3),
-  B(Return),
+                B(Mov), R(closure), R(0),
+  /*  125 E> */ B(StackCheck),
+  /*  130 S> */ B(Mov), R(this), R(1),
+                B(Ldar), R(closure),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(0),
+                B(Star), R(5),
+  /*  130 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1),
+                B(Star), R(5),
+                B(LdaConstant), U8(1),
+  /*  130 E> */ B(LdrKeyedProperty), R(5), U8(1), R(2),
+                B(LdaConstant), U8(2),
+                B(Star), R(3),
+                B(LdaSmi), U8(2),
+                B(Star), R(4),
+  /*  138 E> */ B(CallRuntime), U16(Runtime::kStoreToSuper_Strict), R(1), U8(4),
+  /*  143 S> */ B(Mov), R(this), R(1),
+                B(Ldar), R(0),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(0),
+                B(Star), R(4),
+  /*  150 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
+                B(Star), R(4),
+                B(LdaConstant), U8(1),
+  /*  150 E> */ B(LdrKeyedProperty), R(4), U8(3), R(2),
+                B(LdaConstant), U8(2),
+                B(Star), R(3),
+                B(CallRuntime), U16(Runtime::kLoadFromSuper), R(1), U8(3),
+  /*  159 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
@@ -136,51 +128,49 @@
 "
 frame size: 5
 parameter count: 1
-bytecode array length: 106
+bytecode array length: 105
 bytecodes: [
-  B(Ldar), R(closure),
-  B(Star), R(1),
-  B(Ldar), R(new_target),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(1),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(0),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::k_GetSuperConstructor), R(2), U8(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(3),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(1),
-  B(Star), R(4),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
-  B(New), R(2), R(3), U8(1),
-  B(Star), R(2),
-  B(Ldar), R(this),
-  B(JumpIfNotHole), U8(4),
-  B(Jump), U8(11),
-  B(LdaConstant), U8(2),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
-  B(Ldar), R(2),
-  B(Star), R(this),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(2),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(2),
-  B(StoreICStrict), R(2), U8(3), U8(4),
-  B(Ldar), R(this),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(2),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
-  B(Return),
+                B(Mov), R(closure), R(1),
+                B(Mov), R(new_target), R(0),
+  /*  113 E> */ B(StackCheck),
+  /*  118 S> */ B(Ldar), R(closure),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(0),
+                B(Star), R(3),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::k_GetSuperConstructor), R(2), U8(1),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(3),
+                B(Ldar), R(0),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(1),
+                B(Star), R(4),
+  /*  118 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
+  /*  118 E> */ B(New), R(2), R(3), U8(1),
+                B(Star), R(2),
+                B(Ldar), R(this),
+                B(JumpIfNotHole), U8(4),
+                B(Jump), U8(11),
+                B(LdaConstant), U8(2),
+                B(Star), R(3),
+  /*  118 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
+                B(Mov), R(2), R(this),
+  /*  128 S> */ B(Ldar), R(this),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(2),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
+                B(Star), R(2),
+                B(LdaSmi), U8(2),
+  /*  136 E> */ B(StaNamedPropertyStrict), R(2), U8(3), U8(4),
+                B(Ldar), R(this),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(2),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
+  /*  141 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
@@ -206,49 +196,47 @@
 "
 frame size: 4
 parameter count: 1
-bytecode array length: 102
+bytecode array length: 101
 bytecodes: [
-  B(Ldar), R(closure),
-  B(Star), R(1),
-  B(Ldar), R(new_target),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(1),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(0),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::k_GetSuperConstructor), R(2), U8(1),
-  B(Star), R(2),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(1),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
-  B(New), R(2), R(0), U8(0),
-  B(Star), R(2),
-  B(Ldar), R(this),
-  B(JumpIfNotHole), U8(4),
-  B(Jump), U8(11),
-  B(LdaConstant), U8(2),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
-  B(Ldar), R(2),
-  B(Star), R(this),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(2),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(2),
-  B(StoreICStrict), R(2), U8(3), U8(4),
-  B(Ldar), R(this),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(2),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
-  B(Return),
+                B(Mov), R(closure), R(1),
+                B(Mov), R(new_target), R(0),
+  /*  112 E> */ B(StackCheck),
+  /*  117 S> */ B(Ldar), R(closure),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(0),
+                B(Star), R(3),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::k_GetSuperConstructor), R(2), U8(1),
+                B(Star), R(2),
+                B(Ldar), R(0),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(1),
+                B(Star), R(3),
+  /*  117 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
+  /*  117 E> */ B(New), R(2), R(0), U8(0),
+                B(Star), R(2),
+                B(Ldar), R(this),
+                B(JumpIfNotHole), U8(4),
+                B(Jump), U8(11),
+                B(LdaConstant), U8(2),
+                B(Star), R(3),
+  /*  117 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
+                B(Mov), R(2), R(this),
+  /*  126 S> */ B(Ldar), R(this),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(2),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
+                B(Star), R(2),
+                B(LdaSmi), U8(2),
+  /*  134 E> */ B(StaNamedPropertyStrict), R(2), U8(3), U8(4),
+                B(Ldar), R(this),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(2),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
+  /*  139 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/ClassDeclarations.golden b/test/cctest/interpreter/bytecode_expectations/ClassDeclarations.golden
index db42c50..c28e474 100644
--- a/test/cctest/interpreter/bytecode_expectations/ClassDeclarations.golden
+++ b/test/cctest/interpreter/bytecode_expectations/ClassDeclarations.golden
@@ -16,40 +16,39 @@
 "
 frame size: 9
 parameter count: 1
-bytecode array length: 73
+bytecode array length: 72
 bytecodes: [
-  B(LdaTheHole),
-  B(Star), R(1),
-  B(StackCheck),
-  B(LdaTheHole),
-  B(Star), R(0),
-  B(LdaTheHole),
-  B(Star), R(2),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(3),
-  B(LdaSmi), U8(34),
-  B(Star), R(4),
-  B(Wide), B(LdaSmi), U16(148),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4),
-  B(Star), R(2),
-  B(LoadIC), R(2), U8(1), U8(1),
-  B(Star), R(3),
-  B(Mov), R(3), R(4),
-  B(LdaConstant), U8(2),
-  B(Star), R(5),
-  B(CreateClosure), U8(3), U8(0),
-  B(Star), R(6),
-  B(LdaSmi), U8(2),
-  B(Star), R(7),
-  B(LdaZero),
-  B(Star), R(8),
-  B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(4), U8(5),
-  B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(2), U8(2),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaUndefined),
-  B(Return),
+                B(LdaTheHole),
+                B(Star), R(1),
+  /*   30 E> */ B(StackCheck),
+                B(LdaTheHole),
+                B(Star), R(0),
+                B(LdaTheHole),
+                B(Star), R(2),
+                B(CreateClosure), U8(0), U8(0),
+                B(Star), R(3),
+                B(LdaSmi), U8(34),
+                B(Star), R(4),
+                B(Wide), B(LdaSmi), U16(148),
+                B(Star), R(5),
+                B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4),
+                B(Star), R(2),
+                B(LdrNamedProperty), R(2), U8(1), U8(1), R(3),
+                B(LdaConstant), U8(2),
+                B(Star), R(5),
+                B(CreateClosure), U8(3), U8(0),
+                B(Star), R(6),
+                B(LdaSmi), U8(2),
+                B(Star), R(7),
+                B(LdaZero),
+                B(Star), R(8),
+                B(Mov), R(3), R(4),
+                B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(4), U8(5),
+                B(CallRuntime), U16(Runtime::kToFastProperties), R(2), U8(1),
+                B(Star), R(0),
+                B(Star), R(1),
+                B(LdaUndefined),
+  /*  149 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -69,40 +68,39 @@
 "
 frame size: 9
 parameter count: 1
-bytecode array length: 73
+bytecode array length: 72
 bytecodes: [
-  B(LdaTheHole),
-  B(Star), R(1),
-  B(StackCheck),
-  B(LdaTheHole),
-  B(Star), R(0),
-  B(LdaTheHole),
-  B(Star), R(2),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(3),
-  B(LdaSmi), U8(34),
-  B(Star), R(4),
-  B(Wide), B(LdaSmi), U16(148),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4),
-  B(Star), R(2),
-  B(LoadIC), R(2), U8(1), U8(1),
-  B(Star), R(3),
-  B(Mov), R(3), R(4),
-  B(LdaConstant), U8(2),
-  B(Star), R(5),
-  B(CreateClosure), U8(3), U8(0),
-  B(Star), R(6),
-  B(LdaSmi), U8(2),
-  B(Star), R(7),
-  B(LdaZero),
-  B(Star), R(8),
-  B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(4), U8(5),
-  B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(2), U8(2),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaUndefined),
-  B(Return),
+                B(LdaTheHole),
+                B(Star), R(1),
+  /*   30 E> */ B(StackCheck),
+                B(LdaTheHole),
+                B(Star), R(0),
+                B(LdaTheHole),
+                B(Star), R(2),
+                B(CreateClosure), U8(0), U8(0),
+                B(Star), R(3),
+                B(LdaSmi), U8(34),
+                B(Star), R(4),
+                B(Wide), B(LdaSmi), U16(148),
+                B(Star), R(5),
+                B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4),
+                B(Star), R(2),
+                B(LdrNamedProperty), R(2), U8(1), U8(1), R(3),
+                B(LdaConstant), U8(2),
+                B(Star), R(5),
+                B(CreateClosure), U8(3), U8(0),
+                B(Star), R(6),
+                B(LdaSmi), U8(2),
+                B(Star), R(7),
+                B(LdaZero),
+                B(Star), R(8),
+                B(Mov), R(3), R(4),
+                B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(4), U8(5),
+                B(CallRuntime), U16(Runtime::kToFastProperties), R(2), U8(1),
+                B(Star), R(0),
+                B(Star), R(1),
+                B(LdaUndefined),
+  /*  149 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -124,60 +122,59 @@
 "
 frame size: 10
 parameter count: 1
-bytecode array length: 127
+bytecode array length: 126
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(2),
-  B(LdaTheHole),
-  B(Star), R(1),
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaConstant), U8(1),
-  B(StaContextSlot), R(context), U8(5),
-  B(LdaTheHole),
-  B(Star), R(0),
-  B(LdaTheHole),
-  B(Star), R(3),
-  B(CreateClosure), U8(2), U8(0),
-  B(Star), R(4),
-  B(LdaSmi), U8(62),
-  B(Star), R(5),
-  B(Wide), B(LdaSmi), U16(128),
-  B(Star), R(6),
-  B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
-  B(Star), R(3),
-  B(LoadIC), R(3), U8(3), U8(1),
-  B(Star), R(4),
-  B(Mov), R(4), R(5),
-  B(LdaContextSlot), R(context), U8(4),
-  B(ToName),
-  B(Star), R(6),
-  B(CreateClosure), U8(4), U8(0),
-  B(Star), R(7),
-  B(LdaSmi), U8(2),
-  B(Star), R(8),
-  B(LdaSmi), U8(1),
-  B(Star), R(9),
-  B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5),
-  B(Mov), R(3), R(5),
-  B(LdaContextSlot), R(context), U8(5),
-  B(ToName),
-  B(Star), R(6),
-  B(LdaConstant), U8(3),
-  B(TestEqualStrict), R(6),
-  B(JumpIfFalse), U8(7),
-  B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), R(0), U8(0),
-  B(CreateClosure), U8(5), U8(0),
-  B(Star), R(7),
-  B(LdaSmi), U8(1),
-  B(Star), R(9),
-  B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5),
-  B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(3), U8(2),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaUndefined),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(2),
+                B(LdaTheHole),
+                B(Star), R(1),
+  /*   30 E> */ B(StackCheck),
+  /*   43 S> */ B(LdaConstant), U8(0),
+  /*   43 E> */ B(StaContextSlot), R(context), U8(4),
+  /*   57 S> */ B(LdaConstant), U8(1),
+  /*   57 E> */ B(StaContextSlot), R(context), U8(5),
+                B(LdaTheHole),
+                B(Star), R(0),
+                B(LdaTheHole),
+                B(Star), R(3),
+                B(CreateClosure), U8(2), U8(0),
+                B(Star), R(4),
+                B(LdaSmi), U8(62),
+                B(Star), R(5),
+                B(Wide), B(LdaSmi), U16(128),
+                B(Star), R(6),
+                B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
+                B(Star), R(3),
+                B(LdrNamedProperty), R(3), U8(3), U8(1), R(4),
+  /*   75 E> */ B(LdaContextSlot), R(context), U8(4),
+                B(ToName),
+                B(Star), R(6),
+                B(CreateClosure), U8(4), U8(0),
+                B(Star), R(7),
+                B(LdaSmi), U8(2),
+                B(Star), R(8),
+                B(LdaSmi), U8(1),
+                B(Star), R(9),
+                B(Mov), R(4), R(5),
+                B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5),
+  /*  106 E> */ B(LdaContextSlot), R(context), U8(5),
+                B(ToName),
+                B(Star), R(6),
+                B(LdaConstant), U8(3),
+                B(TestEqualStrict), R(6),
+                B(Mov), R(3), R(5),
+                B(JumpIfToBooleanFalse), U8(7),
+                B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), R(0), U8(0),
+                B(CreateClosure), U8(5), U8(0),
+                B(Star), R(7),
+                B(LdaSmi), U8(1),
+                B(Star), R(9),
+                B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5),
+                B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
+                B(Star), R(0),
+                B(Star), R(1),
+                B(LdaUndefined),
+  /*  129 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
@@ -196,41 +193,40 @@
   class C { constructor() { count++; }}
   return new C();
 "
-frame size: 10
+frame size: 7
 parameter count: 1
-bytecode array length: 74
+bytecode array length: 73
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(2),
-  B(LdaTheHole),
-  B(Star), R(1),
-  B(StackCheck),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaTheHole),
-  B(Star), R(0),
-  B(LdaTheHole),
-  B(Star), R(3),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(4),
-  B(LdaSmi), U8(49),
-  B(Star), R(5),
-  B(LdaSmi), U8(86),
-  B(Star), R(6),
-  B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
-  B(Star), R(3),
-  B(LoadIC), R(3), U8(1), U8(1),
-  B(Star), R(4),
-  B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(3), U8(2),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(2),
-  B(Star), R(4),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
-  B(Star), R(3),
-  B(New), R(3), R(0), U8(0),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(2),
+                B(LdaTheHole),
+                B(Star), R(1),
+  /*   30 E> */ B(StackCheck),
+  /*   46 S> */ B(LdaZero),
+  /*   46 E> */ B(StaContextSlot), R(context), U8(4),
+                B(LdaTheHole),
+                B(Star), R(0),
+                B(LdaTheHole),
+                B(Star), R(3),
+                B(CreateClosure), U8(0), U8(0),
+                B(Star), R(4),
+                B(LdaSmi), U8(49),
+                B(Star), R(5),
+                B(LdaSmi), U8(86),
+                B(Star), R(6),
+                B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
+                B(Star), R(3),
+                B(LdrNamedProperty), R(3), U8(1), U8(1), R(4),
+                B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
+                B(Star), R(0),
+                B(Star), R(1),
+  /*   87 S> */ B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(2),
+                B(Star), R(4),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
+                B(Star), R(3),
+  /*   94 E> */ B(New), R(3), R(0), U8(0),
+  /*  103 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/CompoundExpressions.golden b/test/cctest/interpreter/bytecode_expectations/CompoundExpressions.golden
index ccabedc..24c6a5e 100644
--- a/test/cctest/interpreter/bytecode_expectations/CompoundExpressions.golden
+++ b/test/cctest/interpreter/bytecode_expectations/CompoundExpressions.golden
@@ -13,17 +13,17 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 15
+bytecode array length: 16
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Add), R(1),
-  B(Star), R(0),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(2),
+                B(Add), R(0),
+                B(Mov), R(0), R(1),
+                B(Star), R(0),
+                B(LdaUndefined),
+  /*   53 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -36,17 +36,17 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 15
+bytecode array length: 16
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Div), R(1),
-  B(Star), R(0),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(2),
+                B(Div), R(0),
+                B(Mov), R(0), R(1),
+                B(Star), R(0),
+                B(LdaUndefined),
+  /*   53 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -59,20 +59,18 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 27
+bytecode array length: 24
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(1), U8(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(2),
-  B(Mul), R(2),
-  B(StoreICSloppy), R(1), U8(1), U8(3),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(1),
+                B(Star), R(0),
+  /*   54 S> */ B(LdrNamedProperty), R(0), U8(1), U8(1), R(2),
+                B(LdaSmi), U8(2),
+                B(Mul), R(2),
+  /*   61 E> */ B(StaNamedPropertySloppy), R(0), U8(1), U8(3),
+                B(LdaUndefined),
+  /*   67 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -87,22 +85,20 @@
 "
 frame size: 4
 parameter count: 1
-bytecode array length: 30
+bytecode array length: 27
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(Star), R(2),
-  B(KeyedLoadIC), R(1), U8(1),
-  B(Star), R(3),
-  B(LdaSmi), U8(2),
-  B(BitwiseXor), R(3),
-  B(KeyedStoreICSloppy), R(1), R(2), U8(3),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(1),
+                B(Star), R(0),
+  /*   52 S> */ B(LdaSmi), U8(1),
+                B(Star), R(2),
+                B(LdrKeyedProperty), R(0), U8(1), R(3),
+                B(LdaSmi), U8(2),
+                B(BitwiseXor), R(3),
+  /*   57 E> */ B(StaKeyedPropertySloppy), R(0), R(2), U8(3),
+                B(LdaUndefined),
+  /*   63 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -116,21 +112,20 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 30
+bytecode array length: 29
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(0), U8(0),
-  B(LdaContextSlot), R(context), U8(4),
-  B(Star), R(1),
-  B(LdaSmi), U8(24),
-  B(BitwiseOr), R(1),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaUndefined),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+  /*   42 E> */ B(StaContextSlot), R(context), U8(4),
+  /*   45 S> */ B(CreateClosure), U8(0), U8(0),
+  /*   75 S> */ B(LdrContextSlot), R(context), U8(4), R(1),
+                B(LdaSmi), U8(24),
+                B(BitwiseOr), R(1),
+  /*   77 E> */ B(StaContextSlot), R(context), U8(4),
+                B(LdaUndefined),
+  /*   84 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/Conditional.golden b/test/cctest/interpreter/bytecode_expectations/Conditional.golden
index 17327a5..e051d45 100644
--- a/test/cctest/interpreter/bytecode_expectations/Conditional.golden
+++ b/test/cctest/interpreter/bytecode_expectations/Conditional.golden
@@ -15,13 +15,13 @@
 parameter count: 1
 bytecode array length: 12
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(JumpIfToBooleanFalse), U8(6),
-  B(LdaSmi), U8(2),
-  B(Jump), U8(4),
-  B(LdaSmi), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaSmi), U8(1),
+                B(JumpIfToBooleanFalse), U8(6),
+                B(LdaSmi), U8(2),
+                B(Jump), U8(4),
+                B(LdaSmi), U8(3),
+  /*   52 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -36,17 +36,17 @@
 parameter count: 1
 bytecode array length: 20
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(JumpIfToBooleanFalse), U8(14),
-  B(LdaSmi), U8(2),
-  B(JumpIfToBooleanFalse), U8(6),
-  B(LdaSmi), U8(3),
-  B(Jump), U8(4),
-  B(LdaSmi), U8(4),
-  B(Jump), U8(4),
-  B(LdaSmi), U8(5),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaSmi), U8(1),
+                B(JumpIfToBooleanFalse), U8(14),
+                B(LdaSmi), U8(2),
+                B(JumpIfToBooleanFalse), U8(6),
+                B(LdaSmi), U8(3),
+                B(Jump), U8(4),
+                B(LdaSmi), U8(4),
+                B(Jump), U8(4),
+                B(LdaSmi), U8(5),
+  /*   60 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/ConstVariable.golden b/test/cctest/interpreter/bytecode_expectations/ConstVariable.golden
index d3fb484..4c511b5 100644
--- a/test/cctest/interpreter/bytecode_expectations/ConstVariable.golden
+++ b/test/cctest/interpreter/bytecode_expectations/ConstVariable.golden
@@ -15,13 +15,13 @@
 parameter count: 1
 bytecode array length: 10
 bytecodes: [
-  B(LdaTheHole),
-  B(Star), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(Star), R(0),
-  B(LdaUndefined),
-  B(Return),
+                B(LdaTheHole),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   44 S> */ B(LdaSmi), U8(10),
+                B(Star), R(0),
+                B(LdaUndefined),
+  /*   48 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -36,16 +36,16 @@
 parameter count: 1
 bytecode array length: 20
 bytecodes: [
-  B(LdaTheHole),
-  B(Star), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(Star), R(0),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(0),
-  B(Star), R(1),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(1), U8(1),
-  B(Return),
+                B(LdaTheHole),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   44 S> */ B(LdaSmi), U8(10),
+                B(Star), R(0),
+  /*   48 S> */ B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(0),
+                B(Star), R(1),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(1), U8(1),
+  /*   58 S> */ B(Return),
 ]
 constant pool: [
   "x",
@@ -59,23 +59,23 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 32
+bytecode array length: 33
 bytecodes: [
-  B(LdaTheHole),
-  B(Star), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(20),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(0),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
-  B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), U8(0),
-  B(Ldar), R(1),
-  B(Star), R(0),
-  B(LdaUndefined),
-  B(Return),
+                B(LdaTheHole),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   48 S> */ B(LdaSmi), U8(20),
+                B(Star), R(1),
+                B(Ldar), R(0),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(0),
+                B(Star), R(2),
+  /*   48 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
+                B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), U8(0),
+                B(Mov), R(1), R(0),
+                B(Ldar), R(0),
+                B(LdaUndefined),
+  /*   55 S> */ B(Return),
 ]
 constant pool: [
   "x",
@@ -89,25 +89,24 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 36
+bytecode array length: 35
 bytecodes: [
-  B(LdaTheHole),
-  B(Star), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(Star), R(0),
-  B(LdaSmi), U8(20),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(0),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
-  B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), U8(0),
-  B(Ldar), R(1),
-  B(Star), R(0),
-  B(LdaUndefined),
-  B(Return),
+                B(LdaTheHole),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   44 S> */ B(LdaSmi), U8(10),
+                B(Star), R(0),
+  /*   48 S> */ B(LdaSmi), U8(20),
+                B(Star), R(1),
+                B(Ldar), R(0),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(0),
+                B(Star), R(2),
+  /*   50 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
+                B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), U8(0),
+                B(Mov), R(1), R(0),
+                B(LdaUndefined),
+  /*   56 S> */ B(Return),
 ]
 constant pool: [
   "x",
diff --git a/test/cctest/interpreter/bytecode_expectations/ConstVariableContextSlot.golden b/test/cctest/interpreter/bytecode_expectations/ConstVariableContextSlot.golden
index 3b445c1..1cfdea8 100644
--- a/test/cctest/interpreter/bytecode_expectations/ConstVariableContextSlot.golden
+++ b/test/cctest/interpreter/bytecode_expectations/ConstVariableContextSlot.golden
@@ -15,17 +15,17 @@
 parameter count: 1
 bytecode array length: 24
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(1),
-  B(LdaTheHole),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaUndefined),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(1),
+                B(LdaTheHole),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateClosure), U8(0), U8(0),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   44 S> */ B(LdaSmi), U8(10),
+  /*   44 E> */ B(StaContextSlot), R(context), U8(4),
+                B(LdaUndefined),
+  /*   74 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -41,21 +41,21 @@
 parameter count: 1
 bytecode array length: 37
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(1),
-  B(LdaTheHole),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaContextSlot), R(context), U8(4),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(1),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(1),
+                B(LdaTheHole),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateClosure), U8(0), U8(0),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   44 S> */ B(LdaSmi), U8(10),
+  /*   44 E> */ B(StaContextSlot), R(context), U8(4),
+  /*   74 S> */ B(LdaContextSlot), R(context), U8(4),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(1),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
+  /*   84 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -72,26 +72,26 @@
 parameter count: 1
 bytecode array length: 50
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(1),
-  B(LdaTheHole),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(20),
-  B(Star), R(2),
-  B(LdaContextSlot), R(context), U8(4),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(1),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
-  B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), U8(0),
-  B(Ldar), R(2),
-  B(StaContextSlot), R(context), U8(4),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaUndefined),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(1),
+                B(LdaTheHole),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateClosure), U8(0), U8(0),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   47 S> */ B(LdaSmi), U8(20),
+                B(Star), R(2),
+  /*   47 E> */ B(LdaContextSlot), R(context), U8(4),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(1),
+                B(Star), R(3),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
+                B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), U8(0),
+                B(Ldar), R(2),
+                B(StaContextSlot), R(context), U8(4),
+  /*   47 E> */ B(StaContextSlot), R(context), U8(4),
+                B(LdaUndefined),
+  /*   80 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -108,27 +108,27 @@
 parameter count: 1
 bytecode array length: 52
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(1),
-  B(LdaTheHole),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaSmi), U8(20),
-  B(Star), R(2),
-  B(LdaContextSlot), R(context), U8(4),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(1),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
-  B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), U8(0),
-  B(Ldar), R(2),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaUndefined),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(1),
+                B(LdaTheHole),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateClosure), U8(0), U8(0),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   44 S> */ B(LdaSmi), U8(10),
+  /*   44 E> */ B(StaContextSlot), R(context), U8(4),
+  /*   48 S> */ B(LdaSmi), U8(20),
+                B(Star), R(2),
+  /*   50 E> */ B(LdaContextSlot), R(context), U8(4),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(1),
+                B(Star), R(3),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
+                B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), U8(0),
+                B(Ldar), R(2),
+                B(StaContextSlot), R(context), U8(4),
+                B(LdaUndefined),
+  /*   82 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/ContextParameters.golden b/test/cctest/interpreter/bytecode_expectations/ContextParameters.golden
index fb74600..09a0f5a 100644
--- a/test/cctest/interpreter/bytecode_expectations/ContextParameters.golden
+++ b/test/cctest/interpreter/bytecode_expectations/ContextParameters.golden
@@ -17,13 +17,13 @@
 parameter count: 2
 bytecode array length: 17
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(0),
-  B(Ldar), R(arg0),
-  B(StaContextSlot), R(context), U8(4),
-  B(StackCheck),
-  B(CreateClosure), U8(0), U8(0),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+                B(Ldar), R(arg0),
+                B(StaContextSlot), R(context), U8(4),
+  /*   10 E> */ B(StackCheck),
+  /*   19 S> */ B(CreateClosure), U8(0), U8(0),
+  /*   52 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -40,15 +40,15 @@
 parameter count: 2
 bytecode array length: 22
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(1),
-  B(Ldar), R(arg0),
-  B(StaContextSlot), R(context), U8(4),
-  B(StackCheck),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(0),
-  B(LdaContextSlot), R(context), U8(4),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(1),
+                B(Ldar), R(arg0),
+                B(StaContextSlot), R(context), U8(4),
+  /*   10 E> */ B(StackCheck),
+  /*   27 S> */ B(CreateClosure), U8(0), U8(0),
+                B(Star), R(0),
+  /*   53 S> */ B(LdaContextSlot), R(context), U8(4),
+  /*   66 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -65,15 +65,15 @@
 parameter count: 5
 bytecode array length: 22
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(0),
-  B(Ldar), R(arg0),
-  B(StaContextSlot), R(context), U8(5),
-  B(Ldar), R(arg2),
-  B(StaContextSlot), R(context), U8(4),
-  B(StackCheck),
-  B(CreateClosure), U8(0), U8(0),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+                B(Ldar), R(arg0),
+                B(StaContextSlot), R(context), U8(5),
+                B(Ldar), R(arg2),
+                B(StaContextSlot), R(context), U8(4),
+  /*   10 E> */ B(StackCheck),
+  /*   29 S> */ B(CreateClosure), U8(0), U8(0),
+  /*   61 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -90,13 +90,13 @@
 parameter count: 1
 bytecode array length: 17
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(0),
-  B(StackCheck),
-  B(Ldar), R(this),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(0), U8(0),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+  /*   10 E> */ B(StackCheck),
+  /*   26 S> */ B(Ldar), R(this),
+  /*   26 E> */ B(StaContextSlot), R(context), U8(4),
+  /*   32 S> */ B(CreateClosure), U8(0), U8(0),
+  /*   65 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/ContextVariables.golden b/test/cctest/interpreter/bytecode_expectations/ContextVariables.golden
index b86e22b..7b69f9e 100644
--- a/test/cctest/interpreter/bytecode_expectations/ContextVariables.golden
+++ b/test/cctest/interpreter/bytecode_expectations/ContextVariables.golden
@@ -15,11 +15,11 @@
 parameter count: 1
 bytecode array length: 12
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(0),
-  B(StackCheck),
-  B(CreateClosure), U8(0), U8(0),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   41 S> */ B(CreateClosure), U8(0), U8(0),
+  /*   71 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -35,13 +35,13 @@
 parameter count: 1
 bytecode array length: 17
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(0), U8(0),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+  /*   42 E> */ B(StaContextSlot), R(context), U8(4),
+  /*   45 S> */ B(CreateClosure), U8(0), U8(0),
+  /*   75 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -57,15 +57,15 @@
 parameter count: 1
 bytecode array length: 22
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaSmi), U8(2),
-  B(StaContextSlot), R(context), U8(5),
-  B(CreateClosure), U8(0), U8(0),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+  /*   42 E> */ B(StaContextSlot), R(context), U8(4),
+  /*   53 S> */ B(LdaSmi), U8(2),
+  /*   53 E> */ B(StaContextSlot), R(context), U8(5),
+  /*   56 S> */ B(CreateClosure), U8(0), U8(0),
+  /*   92 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -79,18 +79,17 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 25
+bytecode array length: 24
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(0),
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Star), R(2),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(1),
-  B(Call), R(1), R(2), U8(1), U8(1),
-  B(LdaContextSlot), R(context), U8(4),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   41 S> */ B(LdrUndefined), R(2),
+                B(CreateClosure), U8(0), U8(0),
+                B(Star), R(1),
+  /*   64 E> */ B(Call), R(1), R(2), U8(1), U8(1),
+  /*   68 S> */ B(LdaContextSlot), R(context), U8(4),
+  /*   78 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -106,28 +105,27 @@
 "
 frame size: 4
 parameter count: 1
-bytecode array length: 47
+bytecode array length: 46
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(0),
-  B(LdaTheHole),
-  B(StaContextSlot), R(context), U8(4),
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaConstant), U8(0),
-  B(Star), R(2),
-  B(Ldar), R(closure),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kPushBlockContext), R(2), U8(2),
-  B(PushContext), R(1),
-  B(LdaTheHole),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaSmi), U8(2),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(1), U8(0),
-  B(PopContext), R(0),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+                B(LdaTheHole),
+                B(StaContextSlot), R(context), U8(4),
+  /*   30 E> */ B(StackCheck),
+  /*   56 S> */ B(LdaSmi), U8(1),
+  /*   56 E> */ B(StaContextSlot), R(context), U8(4),
+                B(LdaConstant), U8(0),
+                B(Star), R(2),
+                B(Mov), R(closure), R(3),
+                B(CallRuntime), U16(Runtime::kPushBlockContext), R(2), U8(2),
+                B(PushContext), R(1),
+                B(LdaTheHole),
+                B(StaContextSlot), R(context), U8(4),
+  /*   69 S> */ B(LdaSmi), U8(2),
+  /*   69 E> */ B(StaContextSlot), R(context), U8(4),
+  /*   72 S> */ B(CreateClosure), U8(1), U8(0),
+                B(PopContext), R(0),
+  /*  104 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -394,527 +392,524 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 1046
+bytecode array length: 1043
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(0),
-  B(Ldar), R(this),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateUnmappedArguments),
-  B(StaContextSlot), R(context), U8(5),
-  B(Ldar), R(new_target),
-  B(StaContextSlot), R(context), U8(6),
-  B(StackCheck),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(7),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(8),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(9),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(10),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(11),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(12),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(13),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(14),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(15),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(16),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(17),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(18),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(19),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(20),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(21),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(22),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(23),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(24),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(25),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(26),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(27),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(28),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(29),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(30),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(31),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(32),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(33),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(34),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(35),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(36),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(37),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(38),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(39),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(40),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(41),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(42),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(43),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(44),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(45),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(46),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(47),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(48),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(49),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(50),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(51),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(52),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(53),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(54),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(55),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(56),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(57),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(58),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(59),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(60),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(61),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(62),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(63),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(64),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(65),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(66),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(67),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(68),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(69),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(70),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(71),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(72),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(73),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(74),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(75),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(76),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(77),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(78),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(79),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(80),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(81),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(82),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(83),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(84),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(85),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(86),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(87),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(88),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(89),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(90),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(91),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(92),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(93),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(94),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(95),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(96),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(97),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(98),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(99),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(100),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(101),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(102),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(103),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(104),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(105),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(106),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(107),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(108),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(109),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(110),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(111),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(112),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(113),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(114),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(115),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(116),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(117),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(118),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(119),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(120),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(121),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(122),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(123),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(124),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(125),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(126),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(127),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(128),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(129),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(130),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(131),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(132),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(133),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(134),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(135),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(136),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(137),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(138),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(139),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(140),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(141),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(142),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(143),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(144),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(145),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(146),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(147),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(148),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(149),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(150),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(151),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(152),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(153),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(154),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(155),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(156),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(157),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(158),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(159),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(160),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(161),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(162),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(163),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(164),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(165),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(166),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(167),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(168),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(169),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(170),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(171),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(172),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(173),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(174),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(175),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(176),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(177),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(178),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(179),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(180),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(181),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(182),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(183),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(184),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(185),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(186),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(187),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(188),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(189),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(190),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(191),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(192),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(193),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(194),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(195),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(196),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(197),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(198),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(199),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(200),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(201),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(202),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(203),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(204),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(205),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(206),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(207),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(208),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(209),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(210),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(211),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(212),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(213),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(214),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(215),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(216),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(217),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(218),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(219),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(220),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(221),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(222),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(223),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(224),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(225),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(226),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(227),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(228),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(229),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(230),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(231),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(232),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(233),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(234),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(235),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(236),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(237),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(238),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(239),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(240),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(241),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(242),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(243),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(244),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(245),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(246),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(247),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(248),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(249),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(250),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(251),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(252),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(253),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(254),
-  B(LdaZero),
-  B(StaContextSlot), R(context), U8(255),
-  B(LdaUndefined),
-  B(Star), R(2),
-  B(LdaGlobal), U8(0), U8(1),
-  B(Star), R(1),
-  B(Call), R(1), R(2), U8(1), U8(0),
-  B(LdaSmi), U8(100),
-  B(Wide), B(StaContextSlot), R16(context), U16(256),
-  B(Wide), B(LdaContextSlot), R16(context), U16(256),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+                B(Ldar), R(this),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateUnmappedArguments),
+                B(StaContextSlot), R(context), U8(5),
+                B(Ldar), R(new_target),
+                B(StaContextSlot), R(context), U8(6),
+  /*   30 E> */ B(StackCheck),
+  /*   57 S> */ B(LdaZero),
+  /*   57 E> */ B(StaContextSlot), R(context), U8(7),
+  /*   69 S> */ B(LdaZero),
+  /*   69 E> */ B(StaContextSlot), R(context), U8(8),
+  /*   81 S> */ B(LdaZero),
+  /*   81 E> */ B(StaContextSlot), R(context), U8(9),
+  /*   93 S> */ B(LdaZero),
+  /*   93 E> */ B(StaContextSlot), R(context), U8(10),
+  /*  105 S> */ B(LdaZero),
+  /*  105 E> */ B(StaContextSlot), R(context), U8(11),
+  /*  117 S> */ B(LdaZero),
+  /*  117 E> */ B(StaContextSlot), R(context), U8(12),
+  /*  129 S> */ B(LdaZero),
+  /*  129 E> */ B(StaContextSlot), R(context), U8(13),
+  /*  141 S> */ B(LdaZero),
+  /*  141 E> */ B(StaContextSlot), R(context), U8(14),
+  /*  153 S> */ B(LdaZero),
+  /*  153 E> */ B(StaContextSlot), R(context), U8(15),
+  /*  165 S> */ B(LdaZero),
+  /*  165 E> */ B(StaContextSlot), R(context), U8(16),
+  /*  178 S> */ B(LdaZero),
+  /*  178 E> */ B(StaContextSlot), R(context), U8(17),
+  /*  191 S> */ B(LdaZero),
+  /*  191 E> */ B(StaContextSlot), R(context), U8(18),
+  /*  204 S> */ B(LdaZero),
+  /*  204 E> */ B(StaContextSlot), R(context), U8(19),
+  /*  217 S> */ B(LdaZero),
+  /*  217 E> */ B(StaContextSlot), R(context), U8(20),
+  /*  230 S> */ B(LdaZero),
+  /*  230 E> */ B(StaContextSlot), R(context), U8(21),
+  /*  243 S> */ B(LdaZero),
+  /*  243 E> */ B(StaContextSlot), R(context), U8(22),
+  /*  256 S> */ B(LdaZero),
+  /*  256 E> */ B(StaContextSlot), R(context), U8(23),
+  /*  269 S> */ B(LdaZero),
+  /*  269 E> */ B(StaContextSlot), R(context), U8(24),
+  /*  282 S> */ B(LdaZero),
+  /*  282 E> */ B(StaContextSlot), R(context), U8(25),
+  /*  295 S> */ B(LdaZero),
+  /*  295 E> */ B(StaContextSlot), R(context), U8(26),
+  /*  308 S> */ B(LdaZero),
+  /*  308 E> */ B(StaContextSlot), R(context), U8(27),
+  /*  321 S> */ B(LdaZero),
+  /*  321 E> */ B(StaContextSlot), R(context), U8(28),
+  /*  334 S> */ B(LdaZero),
+  /*  334 E> */ B(StaContextSlot), R(context), U8(29),
+  /*  347 S> */ B(LdaZero),
+  /*  347 E> */ B(StaContextSlot), R(context), U8(30),
+  /*  360 S> */ B(LdaZero),
+  /*  360 E> */ B(StaContextSlot), R(context), U8(31),
+  /*  373 S> */ B(LdaZero),
+  /*  373 E> */ B(StaContextSlot), R(context), U8(32),
+  /*  386 S> */ B(LdaZero),
+  /*  386 E> */ B(StaContextSlot), R(context), U8(33),
+  /*  399 S> */ B(LdaZero),
+  /*  399 E> */ B(StaContextSlot), R(context), U8(34),
+  /*  412 S> */ B(LdaZero),
+  /*  412 E> */ B(StaContextSlot), R(context), U8(35),
+  /*  425 S> */ B(LdaZero),
+  /*  425 E> */ B(StaContextSlot), R(context), U8(36),
+  /*  438 S> */ B(LdaZero),
+  /*  438 E> */ B(StaContextSlot), R(context), U8(37),
+  /*  451 S> */ B(LdaZero),
+  /*  451 E> */ B(StaContextSlot), R(context), U8(38),
+  /*  464 S> */ B(LdaZero),
+  /*  464 E> */ B(StaContextSlot), R(context), U8(39),
+  /*  477 S> */ B(LdaZero),
+  /*  477 E> */ B(StaContextSlot), R(context), U8(40),
+  /*  490 S> */ B(LdaZero),
+  /*  490 E> */ B(StaContextSlot), R(context), U8(41),
+  /*  503 S> */ B(LdaZero),
+  /*  503 E> */ B(StaContextSlot), R(context), U8(42),
+  /*  516 S> */ B(LdaZero),
+  /*  516 E> */ B(StaContextSlot), R(context), U8(43),
+  /*  529 S> */ B(LdaZero),
+  /*  529 E> */ B(StaContextSlot), R(context), U8(44),
+  /*  542 S> */ B(LdaZero),
+  /*  542 E> */ B(StaContextSlot), R(context), U8(45),
+  /*  555 S> */ B(LdaZero),
+  /*  555 E> */ B(StaContextSlot), R(context), U8(46),
+  /*  568 S> */ B(LdaZero),
+  /*  568 E> */ B(StaContextSlot), R(context), U8(47),
+  /*  581 S> */ B(LdaZero),
+  /*  581 E> */ B(StaContextSlot), R(context), U8(48),
+  /*  594 S> */ B(LdaZero),
+  /*  594 E> */ B(StaContextSlot), R(context), U8(49),
+  /*  607 S> */ B(LdaZero),
+  /*  607 E> */ B(StaContextSlot), R(context), U8(50),
+  /*  620 S> */ B(LdaZero),
+  /*  620 E> */ B(StaContextSlot), R(context), U8(51),
+  /*  633 S> */ B(LdaZero),
+  /*  633 E> */ B(StaContextSlot), R(context), U8(52),
+  /*  646 S> */ B(LdaZero),
+  /*  646 E> */ B(StaContextSlot), R(context), U8(53),
+  /*  659 S> */ B(LdaZero),
+  /*  659 E> */ B(StaContextSlot), R(context), U8(54),
+  /*  672 S> */ B(LdaZero),
+  /*  672 E> */ B(StaContextSlot), R(context), U8(55),
+  /*  685 S> */ B(LdaZero),
+  /*  685 E> */ B(StaContextSlot), R(context), U8(56),
+  /*  698 S> */ B(LdaZero),
+  /*  698 E> */ B(StaContextSlot), R(context), U8(57),
+  /*  711 S> */ B(LdaZero),
+  /*  711 E> */ B(StaContextSlot), R(context), U8(58),
+  /*  724 S> */ B(LdaZero),
+  /*  724 E> */ B(StaContextSlot), R(context), U8(59),
+  /*  737 S> */ B(LdaZero),
+  /*  737 E> */ B(StaContextSlot), R(context), U8(60),
+  /*  750 S> */ B(LdaZero),
+  /*  750 E> */ B(StaContextSlot), R(context), U8(61),
+  /*  763 S> */ B(LdaZero),
+  /*  763 E> */ B(StaContextSlot), R(context), U8(62),
+  /*  776 S> */ B(LdaZero),
+  /*  776 E> */ B(StaContextSlot), R(context), U8(63),
+  /*  789 S> */ B(LdaZero),
+  /*  789 E> */ B(StaContextSlot), R(context), U8(64),
+  /*  802 S> */ B(LdaZero),
+  /*  802 E> */ B(StaContextSlot), R(context), U8(65),
+  /*  815 S> */ B(LdaZero),
+  /*  815 E> */ B(StaContextSlot), R(context), U8(66),
+  /*  828 S> */ B(LdaZero),
+  /*  828 E> */ B(StaContextSlot), R(context), U8(67),
+  /*  841 S> */ B(LdaZero),
+  /*  841 E> */ B(StaContextSlot), R(context), U8(68),
+  /*  854 S> */ B(LdaZero),
+  /*  854 E> */ B(StaContextSlot), R(context), U8(69),
+  /*  867 S> */ B(LdaZero),
+  /*  867 E> */ B(StaContextSlot), R(context), U8(70),
+  /*  880 S> */ B(LdaZero),
+  /*  880 E> */ B(StaContextSlot), R(context), U8(71),
+  /*  893 S> */ B(LdaZero),
+  /*  893 E> */ B(StaContextSlot), R(context), U8(72),
+  /*  906 S> */ B(LdaZero),
+  /*  906 E> */ B(StaContextSlot), R(context), U8(73),
+  /*  919 S> */ B(LdaZero),
+  /*  919 E> */ B(StaContextSlot), R(context), U8(74),
+  /*  932 S> */ B(LdaZero),
+  /*  932 E> */ B(StaContextSlot), R(context), U8(75),
+  /*  945 S> */ B(LdaZero),
+  /*  945 E> */ B(StaContextSlot), R(context), U8(76),
+  /*  958 S> */ B(LdaZero),
+  /*  958 E> */ B(StaContextSlot), R(context), U8(77),
+  /*  971 S> */ B(LdaZero),
+  /*  971 E> */ B(StaContextSlot), R(context), U8(78),
+  /*  984 S> */ B(LdaZero),
+  /*  984 E> */ B(StaContextSlot), R(context), U8(79),
+  /*  997 S> */ B(LdaZero),
+  /*  997 E> */ B(StaContextSlot), R(context), U8(80),
+  /* 1010 S> */ B(LdaZero),
+  /* 1010 E> */ B(StaContextSlot), R(context), U8(81),
+  /* 1023 S> */ B(LdaZero),
+  /* 1023 E> */ B(StaContextSlot), R(context), U8(82),
+  /* 1036 S> */ B(LdaZero),
+  /* 1036 E> */ B(StaContextSlot), R(context), U8(83),
+  /* 1049 S> */ B(LdaZero),
+  /* 1049 E> */ B(StaContextSlot), R(context), U8(84),
+  /* 1062 S> */ B(LdaZero),
+  /* 1062 E> */ B(StaContextSlot), R(context), U8(85),
+  /* 1075 S> */ B(LdaZero),
+  /* 1075 E> */ B(StaContextSlot), R(context), U8(86),
+  /* 1088 S> */ B(LdaZero),
+  /* 1088 E> */ B(StaContextSlot), R(context), U8(87),
+  /* 1101 S> */ B(LdaZero),
+  /* 1101 E> */ B(StaContextSlot), R(context), U8(88),
+  /* 1114 S> */ B(LdaZero),
+  /* 1114 E> */ B(StaContextSlot), R(context), U8(89),
+  /* 1127 S> */ B(LdaZero),
+  /* 1127 E> */ B(StaContextSlot), R(context), U8(90),
+  /* 1140 S> */ B(LdaZero),
+  /* 1140 E> */ B(StaContextSlot), R(context), U8(91),
+  /* 1153 S> */ B(LdaZero),
+  /* 1153 E> */ B(StaContextSlot), R(context), U8(92),
+  /* 1166 S> */ B(LdaZero),
+  /* 1166 E> */ B(StaContextSlot), R(context), U8(93),
+  /* 1179 S> */ B(LdaZero),
+  /* 1179 E> */ B(StaContextSlot), R(context), U8(94),
+  /* 1192 S> */ B(LdaZero),
+  /* 1192 E> */ B(StaContextSlot), R(context), U8(95),
+  /* 1205 S> */ B(LdaZero),
+  /* 1205 E> */ B(StaContextSlot), R(context), U8(96),
+  /* 1218 S> */ B(LdaZero),
+  /* 1218 E> */ B(StaContextSlot), R(context), U8(97),
+  /* 1231 S> */ B(LdaZero),
+  /* 1231 E> */ B(StaContextSlot), R(context), U8(98),
+  /* 1244 S> */ B(LdaZero),
+  /* 1244 E> */ B(StaContextSlot), R(context), U8(99),
+  /* 1257 S> */ B(LdaZero),
+  /* 1257 E> */ B(StaContextSlot), R(context), U8(100),
+  /* 1270 S> */ B(LdaZero),
+  /* 1270 E> */ B(StaContextSlot), R(context), U8(101),
+  /* 1283 S> */ B(LdaZero),
+  /* 1283 E> */ B(StaContextSlot), R(context), U8(102),
+  /* 1296 S> */ B(LdaZero),
+  /* 1296 E> */ B(StaContextSlot), R(context), U8(103),
+  /* 1309 S> */ B(LdaZero),
+  /* 1309 E> */ B(StaContextSlot), R(context), U8(104),
+  /* 1322 S> */ B(LdaZero),
+  /* 1322 E> */ B(StaContextSlot), R(context), U8(105),
+  /* 1335 S> */ B(LdaZero),
+  /* 1335 E> */ B(StaContextSlot), R(context), U8(106),
+  /* 1349 S> */ B(LdaZero),
+  /* 1349 E> */ B(StaContextSlot), R(context), U8(107),
+  /* 1363 S> */ B(LdaZero),
+  /* 1363 E> */ B(StaContextSlot), R(context), U8(108),
+  /* 1377 S> */ B(LdaZero),
+  /* 1377 E> */ B(StaContextSlot), R(context), U8(109),
+  /* 1391 S> */ B(LdaZero),
+  /* 1391 E> */ B(StaContextSlot), R(context), U8(110),
+  /* 1405 S> */ B(LdaZero),
+  /* 1405 E> */ B(StaContextSlot), R(context), U8(111),
+  /* 1419 S> */ B(LdaZero),
+  /* 1419 E> */ B(StaContextSlot), R(context), U8(112),
+  /* 1433 S> */ B(LdaZero),
+  /* 1433 E> */ B(StaContextSlot), R(context), U8(113),
+  /* 1447 S> */ B(LdaZero),
+  /* 1447 E> */ B(StaContextSlot), R(context), U8(114),
+  /* 1461 S> */ B(LdaZero),
+  /* 1461 E> */ B(StaContextSlot), R(context), U8(115),
+  /* 1475 S> */ B(LdaZero),
+  /* 1475 E> */ B(StaContextSlot), R(context), U8(116),
+  /* 1489 S> */ B(LdaZero),
+  /* 1489 E> */ B(StaContextSlot), R(context), U8(117),
+  /* 1503 S> */ B(LdaZero),
+  /* 1503 E> */ B(StaContextSlot), R(context), U8(118),
+  /* 1517 S> */ B(LdaZero),
+  /* 1517 E> */ B(StaContextSlot), R(context), U8(119),
+  /* 1531 S> */ B(LdaZero),
+  /* 1531 E> */ B(StaContextSlot), R(context), U8(120),
+  /* 1545 S> */ B(LdaZero),
+  /* 1545 E> */ B(StaContextSlot), R(context), U8(121),
+  /* 1559 S> */ B(LdaZero),
+  /* 1559 E> */ B(StaContextSlot), R(context), U8(122),
+  /* 1573 S> */ B(LdaZero),
+  /* 1573 E> */ B(StaContextSlot), R(context), U8(123),
+  /* 1587 S> */ B(LdaZero),
+  /* 1587 E> */ B(StaContextSlot), R(context), U8(124),
+  /* 1601 S> */ B(LdaZero),
+  /* 1601 E> */ B(StaContextSlot), R(context), U8(125),
+  /* 1615 S> */ B(LdaZero),
+  /* 1615 E> */ B(StaContextSlot), R(context), U8(126),
+  /* 1629 S> */ B(LdaZero),
+  /* 1629 E> */ B(StaContextSlot), R(context), U8(127),
+  /* 1643 S> */ B(LdaZero),
+  /* 1643 E> */ B(StaContextSlot), R(context), U8(128),
+  /* 1657 S> */ B(LdaZero),
+  /* 1657 E> */ B(StaContextSlot), R(context), U8(129),
+  /* 1671 S> */ B(LdaZero),
+  /* 1671 E> */ B(StaContextSlot), R(context), U8(130),
+  /* 1685 S> */ B(LdaZero),
+  /* 1685 E> */ B(StaContextSlot), R(context), U8(131),
+  /* 1699 S> */ B(LdaZero),
+  /* 1699 E> */ B(StaContextSlot), R(context), U8(132),
+  /* 1713 S> */ B(LdaZero),
+  /* 1713 E> */ B(StaContextSlot), R(context), U8(133),
+  /* 1727 S> */ B(LdaZero),
+  /* 1727 E> */ B(StaContextSlot), R(context), U8(134),
+  /* 1741 S> */ B(LdaZero),
+  /* 1741 E> */ B(StaContextSlot), R(context), U8(135),
+  /* 1755 S> */ B(LdaZero),
+  /* 1755 E> */ B(StaContextSlot), R(context), U8(136),
+  /* 1769 S> */ B(LdaZero),
+  /* 1769 E> */ B(StaContextSlot), R(context), U8(137),
+  /* 1783 S> */ B(LdaZero),
+  /* 1783 E> */ B(StaContextSlot), R(context), U8(138),
+  /* 1797 S> */ B(LdaZero),
+  /* 1797 E> */ B(StaContextSlot), R(context), U8(139),
+  /* 1811 S> */ B(LdaZero),
+  /* 1811 E> */ B(StaContextSlot), R(context), U8(140),
+  /* 1825 S> */ B(LdaZero),
+  /* 1825 E> */ B(StaContextSlot), R(context), U8(141),
+  /* 1839 S> */ B(LdaZero),
+  /* 1839 E> */ B(StaContextSlot), R(context), U8(142),
+  /* 1853 S> */ B(LdaZero),
+  /* 1853 E> */ B(StaContextSlot), R(context), U8(143),
+  /* 1867 S> */ B(LdaZero),
+  /* 1867 E> */ B(StaContextSlot), R(context), U8(144),
+  /* 1881 S> */ B(LdaZero),
+  /* 1881 E> */ B(StaContextSlot), R(context), U8(145),
+  /* 1895 S> */ B(LdaZero),
+  /* 1895 E> */ B(StaContextSlot), R(context), U8(146),
+  /* 1909 S> */ B(LdaZero),
+  /* 1909 E> */ B(StaContextSlot), R(context), U8(147),
+  /* 1923 S> */ B(LdaZero),
+  /* 1923 E> */ B(StaContextSlot), R(context), U8(148),
+  /* 1937 S> */ B(LdaZero),
+  /* 1937 E> */ B(StaContextSlot), R(context), U8(149),
+  /* 1951 S> */ B(LdaZero),
+  /* 1951 E> */ B(StaContextSlot), R(context), U8(150),
+  /* 1965 S> */ B(LdaZero),
+  /* 1965 E> */ B(StaContextSlot), R(context), U8(151),
+  /* 1979 S> */ B(LdaZero),
+  /* 1979 E> */ B(StaContextSlot), R(context), U8(152),
+  /* 1993 S> */ B(LdaZero),
+  /* 1993 E> */ B(StaContextSlot), R(context), U8(153),
+  /* 2007 S> */ B(LdaZero),
+  /* 2007 E> */ B(StaContextSlot), R(context), U8(154),
+  /* 2021 S> */ B(LdaZero),
+  /* 2021 E> */ B(StaContextSlot), R(context), U8(155),
+  /* 2035 S> */ B(LdaZero),
+  /* 2035 E> */ B(StaContextSlot), R(context), U8(156),
+  /* 2049 S> */ B(LdaZero),
+  /* 2049 E> */ B(StaContextSlot), R(context), U8(157),
+  /* 2063 S> */ B(LdaZero),
+  /* 2063 E> */ B(StaContextSlot), R(context), U8(158),
+  /* 2077 S> */ B(LdaZero),
+  /* 2077 E> */ B(StaContextSlot), R(context), U8(159),
+  /* 2091 S> */ B(LdaZero),
+  /* 2091 E> */ B(StaContextSlot), R(context), U8(160),
+  /* 2105 S> */ B(LdaZero),
+  /* 2105 E> */ B(StaContextSlot), R(context), U8(161),
+  /* 2119 S> */ B(LdaZero),
+  /* 2119 E> */ B(StaContextSlot), R(context), U8(162),
+  /* 2133 S> */ B(LdaZero),
+  /* 2133 E> */ B(StaContextSlot), R(context), U8(163),
+  /* 2147 S> */ B(LdaZero),
+  /* 2147 E> */ B(StaContextSlot), R(context), U8(164),
+  /* 2161 S> */ B(LdaZero),
+  /* 2161 E> */ B(StaContextSlot), R(context), U8(165),
+  /* 2175 S> */ B(LdaZero),
+  /* 2175 E> */ B(StaContextSlot), R(context), U8(166),
+  /* 2189 S> */ B(LdaZero),
+  /* 2189 E> */ B(StaContextSlot), R(context), U8(167),
+  /* 2203 S> */ B(LdaZero),
+  /* 2203 E> */ B(StaContextSlot), R(context), U8(168),
+  /* 2217 S> */ B(LdaZero),
+  /* 2217 E> */ B(StaContextSlot), R(context), U8(169),
+  /* 2231 S> */ B(LdaZero),
+  /* 2231 E> */ B(StaContextSlot), R(context), U8(170),
+  /* 2245 S> */ B(LdaZero),
+  /* 2245 E> */ B(StaContextSlot), R(context), U8(171),
+  /* 2259 S> */ B(LdaZero),
+  /* 2259 E> */ B(StaContextSlot), R(context), U8(172),
+  /* 2273 S> */ B(LdaZero),
+  /* 2273 E> */ B(StaContextSlot), R(context), U8(173),
+  /* 2287 S> */ B(LdaZero),
+  /* 2287 E> */ B(StaContextSlot), R(context), U8(174),
+  /* 2301 S> */ B(LdaZero),
+  /* 2301 E> */ B(StaContextSlot), R(context), U8(175),
+  /* 2315 S> */ B(LdaZero),
+  /* 2315 E> */ B(StaContextSlot), R(context), U8(176),
+  /* 2329 S> */ B(LdaZero),
+  /* 2329 E> */ B(StaContextSlot), R(context), U8(177),
+  /* 2343 S> */ B(LdaZero),
+  /* 2343 E> */ B(StaContextSlot), R(context), U8(178),
+  /* 2357 S> */ B(LdaZero),
+  /* 2357 E> */ B(StaContextSlot), R(context), U8(179),
+  /* 2371 S> */ B(LdaZero),
+  /* 2371 E> */ B(StaContextSlot), R(context), U8(180),
+  /* 2385 S> */ B(LdaZero),
+  /* 2385 E> */ B(StaContextSlot), R(context), U8(181),
+  /* 2399 S> */ B(LdaZero),
+  /* 2399 E> */ B(StaContextSlot), R(context), U8(182),
+  /* 2413 S> */ B(LdaZero),
+  /* 2413 E> */ B(StaContextSlot), R(context), U8(183),
+  /* 2427 S> */ B(LdaZero),
+  /* 2427 E> */ B(StaContextSlot), R(context), U8(184),
+  /* 2441 S> */ B(LdaZero),
+  /* 2441 E> */ B(StaContextSlot), R(context), U8(185),
+  /* 2455 S> */ B(LdaZero),
+  /* 2455 E> */ B(StaContextSlot), R(context), U8(186),
+  /* 2469 S> */ B(LdaZero),
+  /* 2469 E> */ B(StaContextSlot), R(context), U8(187),
+  /* 2483 S> */ B(LdaZero),
+  /* 2483 E> */ B(StaContextSlot), R(context), U8(188),
+  /* 2497 S> */ B(LdaZero),
+  /* 2497 E> */ B(StaContextSlot), R(context), U8(189),
+  /* 2511 S> */ B(LdaZero),
+  /* 2511 E> */ B(StaContextSlot), R(context), U8(190),
+  /* 2525 S> */ B(LdaZero),
+  /* 2525 E> */ B(StaContextSlot), R(context), U8(191),
+  /* 2539 S> */ B(LdaZero),
+  /* 2539 E> */ B(StaContextSlot), R(context), U8(192),
+  /* 2553 S> */ B(LdaZero),
+  /* 2553 E> */ B(StaContextSlot), R(context), U8(193),
+  /* 2567 S> */ B(LdaZero),
+  /* 2567 E> */ B(StaContextSlot), R(context), U8(194),
+  /* 2581 S> */ B(LdaZero),
+  /* 2581 E> */ B(StaContextSlot), R(context), U8(195),
+  /* 2595 S> */ B(LdaZero),
+  /* 2595 E> */ B(StaContextSlot), R(context), U8(196),
+  /* 2609 S> */ B(LdaZero),
+  /* 2609 E> */ B(StaContextSlot), R(context), U8(197),
+  /* 2623 S> */ B(LdaZero),
+  /* 2623 E> */ B(StaContextSlot), R(context), U8(198),
+  /* 2637 S> */ B(LdaZero),
+  /* 2637 E> */ B(StaContextSlot), R(context), U8(199),
+  /* 2651 S> */ B(LdaZero),
+  /* 2651 E> */ B(StaContextSlot), R(context), U8(200),
+  /* 2665 S> */ B(LdaZero),
+  /* 2665 E> */ B(StaContextSlot), R(context), U8(201),
+  /* 2679 S> */ B(LdaZero),
+  /* 2679 E> */ B(StaContextSlot), R(context), U8(202),
+  /* 2693 S> */ B(LdaZero),
+  /* 2693 E> */ B(StaContextSlot), R(context), U8(203),
+  /* 2707 S> */ B(LdaZero),
+  /* 2707 E> */ B(StaContextSlot), R(context), U8(204),
+  /* 2721 S> */ B(LdaZero),
+  /* 2721 E> */ B(StaContextSlot), R(context), U8(205),
+  /* 2735 S> */ B(LdaZero),
+  /* 2735 E> */ B(StaContextSlot), R(context), U8(206),
+  /* 2749 S> */ B(LdaZero),
+  /* 2749 E> */ B(StaContextSlot), R(context), U8(207),
+  /* 2763 S> */ B(LdaZero),
+  /* 2763 E> */ B(StaContextSlot), R(context), U8(208),
+  /* 2777 S> */ B(LdaZero),
+  /* 2777 E> */ B(StaContextSlot), R(context), U8(209),
+  /* 2791 S> */ B(LdaZero),
+  /* 2791 E> */ B(StaContextSlot), R(context), U8(210),
+  /* 2805 S> */ B(LdaZero),
+  /* 2805 E> */ B(StaContextSlot), R(context), U8(211),
+  /* 2819 S> */ B(LdaZero),
+  /* 2819 E> */ B(StaContextSlot), R(context), U8(212),
+  /* 2833 S> */ B(LdaZero),
+  /* 2833 E> */ B(StaContextSlot), R(context), U8(213),
+  /* 2847 S> */ B(LdaZero),
+  /* 2847 E> */ B(StaContextSlot), R(context), U8(214),
+  /* 2861 S> */ B(LdaZero),
+  /* 2861 E> */ B(StaContextSlot), R(context), U8(215),
+  /* 2875 S> */ B(LdaZero),
+  /* 2875 E> */ B(StaContextSlot), R(context), U8(216),
+  /* 2889 S> */ B(LdaZero),
+  /* 2889 E> */ B(StaContextSlot), R(context), U8(217),
+  /* 2903 S> */ B(LdaZero),
+  /* 2903 E> */ B(StaContextSlot), R(context), U8(218),
+  /* 2917 S> */ B(LdaZero),
+  /* 2917 E> */ B(StaContextSlot), R(context), U8(219),
+  /* 2931 S> */ B(LdaZero),
+  /* 2931 E> */ B(StaContextSlot), R(context), U8(220),
+  /* 2945 S> */ B(LdaZero),
+  /* 2945 E> */ B(StaContextSlot), R(context), U8(221),
+  /* 2959 S> */ B(LdaZero),
+  /* 2959 E> */ B(StaContextSlot), R(context), U8(222),
+  /* 2973 S> */ B(LdaZero),
+  /* 2973 E> */ B(StaContextSlot), R(context), U8(223),
+  /* 2987 S> */ B(LdaZero),
+  /* 2987 E> */ B(StaContextSlot), R(context), U8(224),
+  /* 3001 S> */ B(LdaZero),
+  /* 3001 E> */ B(StaContextSlot), R(context), U8(225),
+  /* 3015 S> */ B(LdaZero),
+  /* 3015 E> */ B(StaContextSlot), R(context), U8(226),
+  /* 3029 S> */ B(LdaZero),
+  /* 3029 E> */ B(StaContextSlot), R(context), U8(227),
+  /* 3043 S> */ B(LdaZero),
+  /* 3043 E> */ B(StaContextSlot), R(context), U8(228),
+  /* 3057 S> */ B(LdaZero),
+  /* 3057 E> */ B(StaContextSlot), R(context), U8(229),
+  /* 3071 S> */ B(LdaZero),
+  /* 3071 E> */ B(StaContextSlot), R(context), U8(230),
+  /* 3085 S> */ B(LdaZero),
+  /* 3085 E> */ B(StaContextSlot), R(context), U8(231),
+  /* 3099 S> */ B(LdaZero),
+  /* 3099 E> */ B(StaContextSlot), R(context), U8(232),
+  /* 3113 S> */ B(LdaZero),
+  /* 3113 E> */ B(StaContextSlot), R(context), U8(233),
+  /* 3127 S> */ B(LdaZero),
+  /* 3127 E> */ B(StaContextSlot), R(context), U8(234),
+  /* 3141 S> */ B(LdaZero),
+  /* 3141 E> */ B(StaContextSlot), R(context), U8(235),
+  /* 3155 S> */ B(LdaZero),
+  /* 3155 E> */ B(StaContextSlot), R(context), U8(236),
+  /* 3169 S> */ B(LdaZero),
+  /* 3169 E> */ B(StaContextSlot), R(context), U8(237),
+  /* 3183 S> */ B(LdaZero),
+  /* 3183 E> */ B(StaContextSlot), R(context), U8(238),
+  /* 3197 S> */ B(LdaZero),
+  /* 3197 E> */ B(StaContextSlot), R(context), U8(239),
+  /* 3211 S> */ B(LdaZero),
+  /* 3211 E> */ B(StaContextSlot), R(context), U8(240),
+  /* 3225 S> */ B(LdaZero),
+  /* 3225 E> */ B(StaContextSlot), R(context), U8(241),
+  /* 3239 S> */ B(LdaZero),
+  /* 3239 E> */ B(StaContextSlot), R(context), U8(242),
+  /* 3253 S> */ B(LdaZero),
+  /* 3253 E> */ B(StaContextSlot), R(context), U8(243),
+  /* 3267 S> */ B(LdaZero),
+  /* 3267 E> */ B(StaContextSlot), R(context), U8(244),
+  /* 3281 S> */ B(LdaZero),
+  /* 3281 E> */ B(StaContextSlot), R(context), U8(245),
+  /* 3295 S> */ B(LdaZero),
+  /* 3295 E> */ B(StaContextSlot), R(context), U8(246),
+  /* 3309 S> */ B(LdaZero),
+  /* 3309 E> */ B(StaContextSlot), R(context), U8(247),
+  /* 3323 S> */ B(LdaZero),
+  /* 3323 E> */ B(StaContextSlot), R(context), U8(248),
+  /* 3337 S> */ B(LdaZero),
+  /* 3337 E> */ B(StaContextSlot), R(context), U8(249),
+  /* 3351 S> */ B(LdaZero),
+  /* 3351 E> */ B(StaContextSlot), R(context), U8(250),
+  /* 3365 S> */ B(LdaZero),
+  /* 3365 E> */ B(StaContextSlot), R(context), U8(251),
+  /* 3379 S> */ B(LdaZero),
+  /* 3379 E> */ B(StaContextSlot), R(context), U8(252),
+  /* 3393 S> */ B(LdaZero),
+  /* 3393 E> */ B(StaContextSlot), R(context), U8(253),
+  /* 3407 S> */ B(LdaZero),
+  /* 3407 E> */ B(StaContextSlot), R(context), U8(254),
+  /* 3421 S> */ B(LdaZero),
+  /* 3421 E> */ B(StaContextSlot), R(context), U8(255),
+  /* 3424 S> */ B(LdrUndefined), R(2),
+  /* 3424 E> */ B(LdrGlobal), U8(1), R(1),
+  /* 3424 E> */ B(Call), R(1), R(2), U8(1), U8(0),
+  /* 3440 S> */ B(LdaSmi), U8(100),
+  /* 3440 E> */ B(Wide), B(StaContextSlot), R16(context), U16(256),
+  /* 3445 S> */ B(Wide), B(LdaContextSlot), R16(context), U16(256),
+  /* 3454 S> */ B(Return),
 ]
 constant pool: [
-  InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
 ]
 handlers: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/CountOperators.golden b/test/cctest/interpreter/bytecode_expectations/CountOperators.golden
index 8857789..3f6696c 100644
--- a/test/cctest/interpreter/bytecode_expectations/CountOperators.golden
+++ b/test/cctest/interpreter/bytecode_expectations/CountOperators.golden
@@ -13,15 +13,14 @@
 "
 frame size: 1
 parameter count: 1
-bytecode array length: 10
+bytecode array length: 9
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(ToNumber),
-  B(Inc),
-  B(Star), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(Inc),
+                B(Star), R(0),
+  /*   57 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -36,15 +35,15 @@
 parameter count: 1
 bytecode array length: 14
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(ToNumber),
-  B(Star), R(1),
-  B(Inc),
-  B(Star), R(0),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(ToNumber),
+                B(Star), R(1),
+                B(Inc),
+                B(Star), R(0),
+                B(Ldar), R(1),
+  /*   57 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -57,15 +56,14 @@
 "
 frame size: 1
 parameter count: 1
-bytecode array length: 10
+bytecode array length: 9
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(ToNumber),
-  B(Dec),
-  B(Star), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(Dec),
+                B(Star), R(0),
+  /*   57 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -80,15 +78,15 @@
 parameter count: 1
 bytecode array length: 14
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(ToNumber),
-  B(Star), R(1),
-  B(Dec),
-  B(Star), R(0),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(ToNumber),
+                B(Star), R(1),
+                B(Dec),
+                B(Star), R(0),
+                B(Ldar), R(1),
+  /*   57 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -101,20 +99,19 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 26
+bytecode array length: 24
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(1), U8(1),
-  B(ToNumber),
-  B(Star), R(2),
-  B(Inc),
-  B(StoreICSloppy), R(1), U8(1), U8(3),
-  B(Ldar), R(2),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(1),
+                B(Star), R(0),
+  /*   54 S> */ B(LdaNamedProperty), R(0), U8(1), U8(1),
+                B(ToNumber),
+                B(Star), R(2),
+                B(Inc),
+  /*   66 E> */ B(StaNamedPropertySloppy), R(0), U8(1), U8(3),
+                B(Ldar), R(2),
+  /*   70 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -129,18 +126,16 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 22
+bytecode array length: 19
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(1), U8(1),
-  B(ToNumber),
-  B(Dec),
-  B(StoreICSloppy), R(1), U8(1), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(1),
+                B(Star), R(0),
+  /*   54 S> */ B(LdaNamedProperty), R(0), U8(1), U8(1),
+                B(Dec),
+  /*   65 E> */ B(StaNamedPropertySloppy), R(0), U8(1), U8(3),
+  /*   70 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -155,24 +150,22 @@
 "
 frame size: 5
 parameter count: 1
-bytecode array length: 33
+bytecode array length: 29
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(CreateObjectLiteral), U8(1), U8(0), U8(5),
-  B(Star), R(2),
-  B(Star), R(1),
-  B(Star), R(2),
-  B(Ldar), R(0),
-  B(Star), R(3),
-  B(KeyedLoadIC), R(2), U8(1),
-  B(ToNumber),
-  B(Star), R(4),
-  B(Dec),
-  B(KeyedStoreICSloppy), R(2), R(3), U8(3),
-  B(Ldar), R(4),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   45 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   60 S> */ B(CreateObjectLiteral), U8(1), U8(0), U8(1),
+                B(Star), R(2),
+                B(Star), R(1),
+  /*   72 S> */ B(Ldar), R(0),
+  /*   81 E> */ B(LdaKeyedProperty), R(1), U8(1),
+                B(ToNumber),
+                B(Star), R(4),
+                B(Dec),
+  /*   86 E> */ B(StaKeyedPropertySloppy), R(1), R(0), U8(3),
+                B(Ldar), R(4),
+  /*   90 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
@@ -185,24 +178,21 @@
 snippet: "
   var name = 'var'; var a = { val: 1 }; return ++a[name];
 "
-frame size: 4
+frame size: 3
 parameter count: 1
-bytecode array length: 29
+bytecode array length: 24
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(CreateObjectLiteral), U8(1), U8(0), U8(5),
-  B(Star), R(2),
-  B(Star), R(1),
-  B(Star), R(2),
-  B(Ldar), R(0),
-  B(Star), R(3),
-  B(KeyedLoadIC), R(2), U8(1),
-  B(ToNumber),
-  B(Inc),
-  B(KeyedStoreICSloppy), R(2), R(3), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   45 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   60 S> */ B(CreateObjectLiteral), U8(1), U8(0), U8(1),
+                B(Star), R(2),
+                B(Star), R(1),
+  /*   72 S> */ B(Ldar), R(0),
+  /*   83 E> */ B(LdaKeyedProperty), R(1), U8(1),
+                B(Inc),
+  /*   87 E> */ B(StaKeyedPropertySloppy), R(1), R(0), U8(3),
+  /*   90 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
@@ -217,20 +207,19 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 27
+bytecode array length: 26
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(1),
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(0),
-  B(LdaContextSlot), R(context), U8(4),
-  B(ToNumber),
-  B(Inc),
-  B(StaContextSlot), R(context), U8(4),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(1),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+  /*   42 E> */ B(StaContextSlot), R(context), U8(4),
+  /*   53 S> */ B(CreateClosure), U8(0), U8(0),
+                B(Star), R(0),
+  /*   78 S> */ B(LdaContextSlot), R(context), U8(4),
+                B(Inc),
+  /*   87 E> */ B(StaContextSlot), R(context), U8(4),
+  /*   90 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -246,20 +235,20 @@
 parameter count: 1
 bytecode array length: 31
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(1),
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(0),
-  B(LdaContextSlot), R(context), U8(4),
-  B(ToNumber),
-  B(Star), R(2),
-  B(Dec),
-  B(StaContextSlot), R(context), U8(4),
-  B(Ldar), R(2),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(1),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+  /*   42 E> */ B(StaContextSlot), R(context), U8(4),
+  /*   53 S> */ B(CreateClosure), U8(0), U8(0),
+                B(Star), R(0),
+  /*   78 S> */ B(LdaContextSlot), R(context), U8(4),
+                B(ToNumber),
+                B(Star), R(2),
+                B(Dec),
+  /*   86 E> */ B(StaContextSlot), R(context), U8(4),
+                B(Ldar), R(2),
+  /*   90 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -273,22 +262,21 @@
 "
 frame size: 4
 parameter count: 1
-bytecode array length: 28
+bytecode array length: 26
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(CreateArrayLiteral), U8(0), U8(0), U8(3),
-  B(Star), R(1),
-  B(Star), R(2),
-  B(Ldar), R(0),
-  B(ToNumber),
-  B(Star), R(3),
-  B(Inc),
-  B(Star), R(0),
-  B(LdaSmi), U8(2),
-  B(KeyedStoreICSloppy), R(2), R(3), U8(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   44 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   55 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(3),
+                B(Star), R(1),
+  /*   63 S> */ B(Ldar), R(0),
+                B(ToNumber),
+                B(Star), R(3),
+                B(Inc),
+                B(Star), R(0),
+                B(LdaSmi), U8(2),
+  /*   79 E> */ B(StaKeyedPropertySloppy), R(1), R(3), U8(1),
+  /*   84 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/CreateArguments.golden b/test/cctest/interpreter/bytecode_expectations/CreateArguments.golden
index ab60ba4..edd6f05 100644
--- a/test/cctest/interpreter/bytecode_expectations/CreateArguments.golden
+++ b/test/cctest/interpreter/bytecode_expectations/CreateArguments.golden
@@ -15,13 +15,13 @@
 "
 frame size: 1
 parameter count: 1
-bytecode array length: 7
+bytecode array length: 6
 bytecodes: [
-  B(CreateMappedArguments),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Return),
+                B(CreateMappedArguments),
+                B(Star), R(0),
+  /*   10 E> */ B(StackCheck),
+  /*   15 S> */ B(Nop),
+  /*   33 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -33,18 +33,16 @@
   function f() { return arguments[0]; }
   f();
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 13
+bytecode array length: 9
 bytecodes: [
-  B(CreateMappedArguments),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaZero),
-  B(KeyedLoadIC), R(1), U8(1),
-  B(Return),
+                B(CreateMappedArguments),
+                B(Star), R(0),
+  /*   10 E> */ B(StackCheck),
+  /*   15 S> */ B(LdaZero),
+  /*   31 E> */ B(LdaKeyedProperty), R(0), U8(1),
+  /*   36 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -58,13 +56,13 @@
 "
 frame size: 1
 parameter count: 1
-bytecode array length: 7
+bytecode array length: 6
 bytecodes: [
-  B(CreateUnmappedArguments),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Return),
+                B(CreateUnmappedArguments),
+                B(Star), R(0),
+  /*   10 E> */ B(StackCheck),
+  /*   29 S> */ B(Nop),
+  /*   47 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -76,22 +74,20 @@
   function f(a) { return arguments[0]; }
   f();
 "
-frame size: 3
+frame size: 2
 parameter count: 2
-bytecode array length: 25
+bytecode array length: 21
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(1),
-  B(Ldar), R(arg0),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateMappedArguments),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaZero),
-  B(KeyedLoadIC), R(2), U8(1),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(1),
+                B(Ldar), R(arg0),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateMappedArguments),
+                B(Star), R(0),
+  /*   10 E> */ B(StackCheck),
+  /*   16 S> */ B(LdaZero),
+  /*   32 E> */ B(LdaKeyedProperty), R(0), U8(1),
+  /*   37 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -105,21 +101,21 @@
 "
 frame size: 2
 parameter count: 4
-bytecode array length: 29
+bytecode array length: 28
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(1),
-  B(Ldar), R(arg0),
-  B(StaContextSlot), R(context), U8(6),
-  B(Ldar), R(arg1),
-  B(StaContextSlot), R(context), U8(5),
-  B(Ldar), R(arg2),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateMappedArguments),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(1),
+                B(Ldar), R(arg0),
+                B(StaContextSlot), R(context), U8(6),
+                B(Ldar), R(arg1),
+                B(StaContextSlot), R(context), U8(5),
+                B(Ldar), R(arg2),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateMappedArguments),
+                B(Star), R(0),
+  /*   10 E> */ B(StackCheck),
+  /*   22 S> */ B(Nop),
+  /*   40 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -133,13 +129,13 @@
 "
 frame size: 1
 parameter count: 4
-bytecode array length: 7
+bytecode array length: 6
 bytecodes: [
-  B(CreateUnmappedArguments),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Return),
+                B(CreateUnmappedArguments),
+                B(Star), R(0),
+  /*   10 E> */ B(StackCheck),
+  /*   36 S> */ B(Nop),
+  /*   54 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/CreateRestParameter.golden b/test/cctest/interpreter/bytecode_expectations/CreateRestParameter.golden
index e43a8cd..feb9088 100644
--- a/test/cctest/interpreter/bytecode_expectations/CreateRestParameter.golden
+++ b/test/cctest/interpreter/bytecode_expectations/CreateRestParameter.golden
@@ -15,13 +15,13 @@
 "
 frame size: 1
 parameter count: 1
-bytecode array length: 7
+bytecode array length: 6
 bytecodes: [
-  B(CreateRestParameter),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Return),
+                B(CreateRestParameter),
+                B(Star), R(0),
+  /*   10 E> */ B(StackCheck),
+  /*   26 S> */ B(Nop),
+  /*   43 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -35,17 +35,16 @@
 "
 frame size: 2
 parameter count: 2
-bytecode array length: 14
+bytecode array length: 13
 bytecodes: [
-  B(CreateRestParameter),
-  B(Star), R(0),
-  B(LdaTheHole),
-  B(Star), R(1),
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Return),
+                B(CreateRestParameter),
+                B(Star), R(0),
+                B(LdaTheHole),
+                B(Star), R(1),
+  /*   10 E> */ B(StackCheck),
+                B(Mov), R(arg0), R(1),
+  /*   29 S> */ B(Ldar), R(0),
+  /*   46 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -57,22 +56,19 @@
   function f(a, ...restArgs) { return restArgs[0]; }
   f();
 "
-frame size: 3
+frame size: 2
 parameter count: 2
-bytecode array length: 20
+bytecode array length: 15
 bytecodes: [
-  B(CreateRestParameter),
-  B(Star), R(0),
-  B(LdaTheHole),
-  B(Star), R(1),
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaZero),
-  B(KeyedLoadIC), R(2), U8(1),
-  B(Return),
+                B(CreateRestParameter),
+                B(Star), R(0),
+                B(LdaTheHole),
+                B(Star), R(1),
+  /*   10 E> */ B(StackCheck),
+                B(Mov), R(arg0), R(1),
+  /*   29 S> */ B(LdaZero),
+  /*   44 E> */ B(LdaKeyedProperty), R(0), U8(1),
+  /*   49 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -86,28 +82,22 @@
 "
 frame size: 5
 parameter count: 2
-bytecode array length: 35
+bytecode array length: 25
 bytecodes: [
-  B(CreateUnmappedArguments),
-  B(Star), R(0),
-  B(CreateRestParameter),
-  B(Star), R(1),
-  B(LdaTheHole),
-  B(Star), R(2),
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(2),
-  B(Ldar), R(1),
-  B(Star), R(3),
-  B(LdaZero),
-  B(KeyedLoadIC), R(3), U8(1),
-  B(Star), R(4),
-  B(Ldar), R(0),
-  B(Star), R(3),
-  B(LdaZero),
-  B(KeyedLoadIC), R(3), U8(3),
-  B(Add), R(4),
-  B(Return),
+                B(CreateUnmappedArguments),
+                B(Star), R(0),
+                B(CreateRestParameter),
+                B(Star), R(1),
+                B(LdaTheHole),
+                B(Star), R(2),
+  /*   10 E> */ B(StackCheck),
+                B(Mov), R(arg0), R(2),
+  /*   29 S> */ B(LdaZero),
+  /*   44 E> */ B(LdrKeyedProperty), R(1), U8(1), R(4),
+                B(LdaZero),
+  /*   59 E> */ B(LdaKeyedProperty), R(0), U8(3),
+                B(Add), R(4),
+  /*   64 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/DeadCodeRemoval.golden b/test/cctest/interpreter/bytecode_expectations/DeadCodeRemoval.golden
index 0c7c176..2530404 100644
--- a/test/cctest/interpreter/bytecode_expectations/DeadCodeRemoval.golden
+++ b/test/cctest/interpreter/bytecode_expectations/DeadCodeRemoval.golden
@@ -15,9 +15,9 @@
 parameter count: 1
 bytecode array length: 3
 bytecodes: [
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaUndefined),
+  /*   58 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -32,11 +32,11 @@
 parameter count: 1
 bytecode array length: 7
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   66 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+                B(LdaUndefined),
+  /*   69 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -51,9 +51,9 @@
 parameter count: 1
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   46 S> */ B(LdaSmi), U8(1),
+  /*   78 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -68,14 +68,14 @@
 parameter count: 1
 bytecode array length: 13
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(JumpIfToBooleanFalse), U8(5),
-  B(LdaSmi), U8(1),
-  B(Return),
-  B(LdaSmi), U8(2),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(JumpIfToBooleanFalse), U8(5),
+  /*   54 S> */ B(LdaSmi), U8(1),
+  /*   77 S> */ B(Return),
+  /*   67 S> */ B(LdaSmi), U8(2),
+  /*   77 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/DeclareGlobals.golden b/test/cctest/interpreter/bytecode_expectations/DeclareGlobals.golden
index bedbe31..97e403e 100644
--- a/test/cctest/interpreter/bytecode_expectations/DeclareGlobals.golden
+++ b/test/cctest/interpreter/bytecode_expectations/DeclareGlobals.golden
@@ -16,21 +16,21 @@
 parameter count: 1
 bytecode array length: 31
 bytecodes: [
-  B(LdaConstant), U8(0),
-  B(Star), R(1),
-  B(LdaZero),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2),
-  B(StackCheck),
-  B(LdaConstant), U8(1),
-  B(Star), R(1),
-  B(LdaZero),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3),
-  B(LdaUndefined),
-  B(Return),
+                B(LdaConstant), U8(0),
+                B(Star), R(1),
+                B(LdaZero),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2),
+  /*    0 E> */ B(StackCheck),
+  /*    8 S> */ B(LdaConstant), U8(1),
+                B(Star), R(1),
+                B(LdaZero),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(3),
+                B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3),
+                B(LdaUndefined),
+  /*   10 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -47,14 +47,14 @@
 parameter count: 1
 bytecode array length: 15
 bytecodes: [
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(LdaZero),
-  B(Star), R(1),
-  B(CallRuntime), U16(Runtime::kDeclareGlobals), R(0), U8(2),
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Return),
+                B(LdaConstant), U8(0),
+                B(Star), R(0),
+                B(LdaZero),
+                B(Star), R(1),
+                B(CallRuntime), U16(Runtime::kDeclareGlobals), R(0), U8(2),
+  /*    0 E> */ B(StackCheck),
+                B(LdaUndefined),
+  /*   15 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -71,23 +71,23 @@
 parameter count: 1
 bytecode array length: 37
 bytecodes: [
-  B(LdaConstant), U8(0),
-  B(Star), R(1),
-  B(LdaZero),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2),
-  B(StackCheck),
-  B(LdaConstant), U8(1),
-  B(Star), R(1),
-  B(LdaZero),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3),
-  B(LdaSmi), U8(2),
-  B(StaGlobalSloppy), U8(1), U8(3),
-  B(Star), R(0),
-  B(Return),
+                B(LdaConstant), U8(0),
+                B(Star), R(1),
+                B(LdaZero),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2),
+  /*    0 E> */ B(StackCheck),
+  /*    8 S> */ B(LdaConstant), U8(1),
+                B(Star), R(1),
+                B(LdaZero),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(3),
+                B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3),
+  /*   11 S> */ B(LdaSmi), U8(2),
+  /*   12 E> */ B(StaGlobalSloppy), U8(1), U8(3),
+                B(Star), R(0),
+  /*   15 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -103,25 +103,22 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 29
+bytecode array length: 26
 bytecodes: [
-  B(LdaConstant), U8(0),
-  B(Star), R(1),
-  B(LdaZero),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2),
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Star), R(2),
-  B(LdaGlobal), U8(1), U8(1),
-  B(Star), R(1),
-  B(Call), R(1), R(2), U8(1), U8(3),
-  B(Star), R(0),
-  B(Return),
+                B(LdaConstant), U8(0),
+                B(Star), R(1),
+                B(LdaZero),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2),
+  /*    0 E> */ B(StackCheck),
+  /*   16 S> */ B(LdrUndefined), R(2),
+                B(LdrGlobal), U8(1), R(1),
+  /*   16 E> */ B(Call), R(1), R(2), U8(1), U8(3),
+                B(Star), R(0),
+  /*   20 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
-  InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
 ]
 handlers: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/Delete.golden b/test/cctest/interpreter/bytecode_expectations/Delete.golden
index 369c158..b4ed9f6 100644
--- a/test/cctest/interpreter/bytecode_expectations/Delete.golden
+++ b/test/cctest/interpreter/bytecode_expectations/Delete.golden
@@ -13,16 +13,15 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 16
+bytecode array length: 14
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaConstant), U8(1),
-  B(DeletePropertySloppy), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(1),
+                B(Star), R(0),
+  /*   56 S> */ B(LdaConstant), U8(1),
+                B(DeletePropertySloppy), R(0),
+  /*   75 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -37,16 +36,15 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 16
+bytecode array length: 14
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaConstant), U8(1),
-  B(DeletePropertyStrict), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   56 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(1),
+                B(Star), R(0),
+  /*   70 S> */ B(LdaConstant), U8(1),
+                B(DeletePropertyStrict), R(0),
+  /*   89 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -61,16 +59,15 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 16
+bytecode array length: 14
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(DeletePropertySloppy), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(1),
+                B(Star), R(0),
+  /*   56 S> */ B(LdaSmi), U8(2),
+                B(DeletePropertySloppy), R(0),
+  /*   76 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -86,11 +83,11 @@
 parameter count: 1
 bytecode array length: 7
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(Star), R(0),
-  B(LdaFalse),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(10),
+                B(Star), R(0),
+  /*   46 S> */ B(LdaFalse),
+  /*   63 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -106,20 +103,19 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 30
+bytecode array length: 29
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(0),
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(1),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(1), U8(0),
-  B(LdaContextSlot), R(context), U8(4),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(DeletePropertyStrict), R(1),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   56 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(1),
+  /*   56 E> */ B(StaContextSlot), R(context), U8(4),
+  /*   64 S> */ B(CreateClosure), U8(1), U8(0),
+  /*   93 S> */ B(LdrContextSlot), R(context), U8(4), R(1),
+                B(LdaSmi), U8(1),
+                B(DeletePropertyStrict), R(1),
+  /*  113 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -136,9 +132,9 @@
 parameter count: 1
 bytecode array length: 3
 bytecodes: [
-  B(StackCheck),
-  B(LdaTrue),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaTrue),
+  /*   56 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/DeleteLookupSlotInEval.golden b/test/cctest/interpreter/bytecode_expectations/DeleteLookupSlotInEval.golden
index b36f421..dcc7213 100644
--- a/test/cctest/interpreter/bytecode_expectations/DeleteLookupSlotInEval.golden
+++ b/test/cctest/interpreter/bytecode_expectations/DeleteLookupSlotInEval.golden
@@ -23,12 +23,12 @@
 parameter count: 1
 bytecode array length: 12
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(CallRuntime), U16(Runtime::kDeleteLookupSlot), R(0), U8(1),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   15 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+                B(CallRuntime), U16(Runtime::kDeleteLookupSlot), R(0), U8(1),
+                B(LdaUndefined),
+  /*   25 S> */ B(Return),
 ]
 constant pool: [
   "x",
@@ -51,9 +51,9 @@
 parameter count: 1
 bytecode array length: 3
 bytecodes: [
-  B(StackCheck),
-  B(LdaFalse),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   15 S> */ B(LdaFalse),
+  /*   32 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -75,11 +75,11 @@
 parameter count: 1
 bytecode array length: 11
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(CallRuntime), U16(Runtime::kDeleteLookupSlot), R(0), U8(1),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   15 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+                B(CallRuntime), U16(Runtime::kDeleteLookupSlot), R(0), U8(1),
+  /*   32 S> */ B(Return),
 ]
 constant pool: [
   "z",
diff --git a/test/cctest/interpreter/bytecode_expectations/DoDebugger.golden b/test/cctest/interpreter/bytecode_expectations/DoDebugger.golden
index ca26065..ac0b2ee 100644
--- a/test/cctest/interpreter/bytecode_expectations/DoDebugger.golden
+++ b/test/cctest/interpreter/bytecode_expectations/DoDebugger.golden
@@ -15,10 +15,10 @@
 parameter count: 1
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(Debugger),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(Debugger),
+                B(LdaUndefined),
+  /*   44 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/DoExpression.golden b/test/cctest/interpreter/bytecode_expectations/DoExpression.golden
index b46fa57..0fae9e6 100644
--- a/test/cctest/interpreter/bytecode_expectations/DoExpression.golden
+++ b/test/cctest/interpreter/bytecode_expectations/DoExpression.golden
@@ -14,12 +14,12 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 6
+bytecode array length: 7
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(Mov), R(0), R(1),
+  /*   50 S> */ B(Ldar), R(1),
+  /*   60 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -32,15 +32,16 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 11
+bytecode array length: 13
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(100),
-  B(Star), R(1),
-  B(LdaUndefined),
-  B(Star), R(0),
-  B(Star), R(2),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   55 S> */ B(LdaSmi), U8(100),
+                B(Star), R(1),
+  /*   42 S> */ B(LdrUndefined), R(0),
+                B(Ldar), R(0),
+                B(Star), R(2),
+  /*   63 S> */ B(Nop),
+  /*   73 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -53,24 +54,19 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 26
+bytecode array length: 17
 bytecodes: [
-  B(StackCheck),
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(Star), R(1),
-  B(ToNumber),
-  B(Inc),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Jump), U8(12),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(20),
-  B(Star), R(1),
-  B(Jump), U8(-21),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 E> */ B(StackCheck),
+  /*   56 S> */ B(LdaSmi), U8(10),
+                B(Star), R(1),
+  /*   69 S> */ B(Inc),
+                B(Star), R(1),
+                B(Star), R(0),
+  /*   74 S> */ B(Jump), U8(4),
+                B(Jump), U8(-12),
+                B(LdaUndefined),
+  /*   94 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/Eval.golden b/test/cctest/interpreter/bytecode_expectations/Eval.golden
index e3e48bc..6dfdf95 100644
--- a/test/cctest/interpreter/bytecode_expectations/Eval.golden
+++ b/test/cctest/interpreter/bytecode_expectations/Eval.golden
@@ -11,35 +11,37 @@
 snippet: "
   return eval('1;');
 "
-frame size: 9
+frame size: 10
 parameter count: 1
-bytecode array length: 65
+bytecode array length: 69
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(0),
-  B(Ldar), R(this),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateMappedArguments),
-  B(StaContextSlot), R(context), U8(5),
-  B(Ldar), R(new_target),
-  B(StaContextSlot), R(context), U8(6),
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(3),
-  B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(3), U8(1), R(1),
-  B(LdaConstant), U8(1),
-  B(Star), R(3),
-  B(Mov), R(1), R(4),
-  B(Mov), R(3), R(5),
-  B(Mov), R(closure), R(6),
-  B(LdaZero),
-  B(Star), R(7),
-  B(LdaSmi), U8(30),
-  B(Star), R(8),
-  B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(5),
-  B(Star), R(1),
-  B(Call), R(1), R(2), U8(2), U8(0),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+                B(Ldar), R(this),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateMappedArguments),
+                B(StaContextSlot), R(context), U8(5),
+                B(Ldar), R(new_target),
+                B(StaContextSlot), R(context), U8(6),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaConstant), U8(0),
+                B(Star), R(3),
+                B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(3), U8(1), R(1),
+                B(LdaConstant), U8(1),
+                B(Star), R(3),
+                B(LdaZero),
+                B(Star), R(7),
+                B(LdaSmi), U8(30),
+                B(Star), R(8),
+                B(LdaSmi), U8(41),
+                B(Star), R(9),
+                B(Mov), R(1), R(4),
+                B(Mov), R(3), R(5),
+                B(Mov), R(closure), R(6),
+                B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6),
+                B(Star), R(1),
+  /*   41 E> */ B(Call), R(1), R(2), U8(2), U8(0),
+  /*   53 S> */ B(Return),
 ]
 constant pool: [
   "eval",
diff --git a/test/cctest/interpreter/bytecode_expectations/ForIn.golden b/test/cctest/interpreter/bytecode_expectations/ForIn.golden
index 9f0c64a..8bc9d2a 100644
--- a/test/cctest/interpreter/bytecode_expectations/ForIn.golden
+++ b/test/cctest/interpreter/bytecode_expectations/ForIn.golden
@@ -15,9 +15,9 @@
 parameter count: 1
 bytecode array length: 3
 bytecodes: [
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+                B(LdaUndefined),
+  /*   57 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -32,9 +32,9 @@
 parameter count: 1
 bytecode array length: 3
 bytecodes: [
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+                B(LdaUndefined),
+  /*   62 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -49,9 +49,9 @@
 parameter count: 1
 bytecode array length: 3
 bytecodes: [
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+                B(LdaUndefined),
+  /*   62 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -65,32 +65,32 @@
 "
 frame size: 8
 parameter count: 1
-bytecode array length: 45
+bytecode array length: 44
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(1),
-  B(JumpIfUndefined), U8(38),
-  B(JumpIfNull), U8(36),
-  B(ToObject),
-  B(Star), R(3),
-  B(ForInPrepare), R(4),
-  B(LdaZero),
-  B(Star), R(7),
-  B(ForInDone), R(7), R(6),
-  B(JumpIfTrue), U8(23),
-  B(ForInNext), R(3), R(7), R(4), U8(1),
-  B(JumpIfUndefined), U8(10),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(Return),
-  B(ForInStep), R(7),
-  B(Star), R(7),
-  B(Jump), U8(-24),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaConstant), U8(0),
+                B(Star), R(1),
+  /*   68 S> */ B(JumpIfUndefined), U8(37),
+                B(JumpIfNull), U8(35),
+                B(ToObject),
+                B(ForInPrepare), R(4),
+                B(Star), R(3),
+                B(LdaZero),
+                B(Star), R(7),
+  /*   63 S> */ B(ForInDone), R(7), R(6),
+                B(JumpIfTrue), U8(22),
+                B(ForInNext), R(3), R(7), R(4), U8(1),
+                B(JumpIfUndefined), U8(9),
+                B(Star), R(0),
+  /*   54 E> */ B(StackCheck),
+                B(Star), R(2),
+  /*   73 S> */ B(Nop),
+  /*   85 S> */ B(Return),
+                B(ForInStep), R(7),
+                B(Star), R(7),
+                B(Jump), U8(-23),
+                B(LdaUndefined),
+  /*   85 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
@@ -105,37 +105,35 @@
 "
 frame size: 9
 parameter count: 1
-bytecode array length: 57
+bytecode array length: 54
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(1),
-  B(CreateArrayLiteral), U8(0), U8(0), U8(3),
-  B(JumpIfUndefined), U8(47),
-  B(JumpIfNull), U8(45),
-  B(ToObject),
-  B(Star), R(3),
-  B(ForInPrepare), R(4),
-  B(LdaZero),
-  B(Star), R(7),
-  B(ForInDone), R(7), R(6),
-  B(JumpIfTrue), U8(32),
-  B(ForInNext), R(3), R(7), R(4), U8(1),
-  B(JumpIfUndefined), U8(19),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(Ldar), R(1),
-  B(Star), R(8),
-  B(Ldar), R(2),
-  B(Add), R(8),
-  B(Star), R(1),
-  B(ForInStep), R(7),
-  B(Star), R(7),
-  B(Jump), U8(-33),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(1),
+  /*   59 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(3),
+                B(JumpIfUndefined), U8(44),
+                B(JumpIfNull), U8(42),
+                B(ToObject),
+                B(ForInPrepare), R(4),
+                B(Star), R(3),
+                B(LdaZero),
+                B(Star), R(7),
+  /*   54 S> */ B(ForInDone), R(7), R(6),
+                B(JumpIfTrue), U8(29),
+                B(ForInNext), R(3), R(7), R(4), U8(1),
+                B(JumpIfUndefined), U8(16),
+                B(Star), R(0),
+  /*   45 E> */ B(StackCheck),
+                B(Star), R(2),
+  /*   70 S> */ B(Ldar), R(0),
+  /*   75 E> */ B(Add), R(1),
+                B(Mov), R(1), R(8),
+                B(Star), R(1),
+  /*   72 E> */ B(ForInStep), R(7),
+                B(Star), R(7),
+                B(Jump), U8(-30),
+                B(LdaUndefined),
+  /*   80 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -153,51 +151,44 @@
 "
 frame size: 8
 parameter count: 1
-bytecode array length: 94
+bytecode array length: 80
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(CreateArrayLiteral), U8(1), U8(1), U8(3),
-  B(JumpIfUndefined), U8(79),
-  B(JumpIfNull), U8(77),
-  B(ToObject),
-  B(Star), R(1),
-  B(ForInPrepare), R(2),
-  B(LdaZero),
-  B(Star), R(5),
-  B(ForInDone), R(5), R(4),
-  B(JumpIfTrue), U8(64),
-  B(ForInNext), R(1), R(5), R(2), U8(9),
-  B(JumpIfUndefined), U8(51),
-  B(Star), R(6),
-  B(Ldar), R(0),
-  B(Star), R(7),
-  B(Ldar), R(6),
-  B(StoreICSloppy), R(7), U8(2), U8(7),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(6),
-  B(LoadIC), R(6), U8(2), U8(3),
-  B(Star), R(7),
-  B(LdaSmi), U8(10),
-  B(TestEqual), R(7),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(20),
-  B(Ldar), R(0),
-  B(Star), R(6),
-  B(LoadIC), R(6), U8(2), U8(5),
-  B(Star), R(7),
-  B(LdaSmi), U8(20),
-  B(TestEqual), R(7),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(8),
-  B(ForInStep), R(5),
-  B(Star), R(5),
-  B(Jump), U8(-65),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(1),
+                B(Star), R(0),
+  /*   77 S> */ B(CreateArrayLiteral), U8(1), U8(1), U8(3),
+                B(JumpIfUndefined), U8(65),
+                B(JumpIfNull), U8(63),
+                B(ToObject),
+                B(ForInPrepare), R(2),
+                B(Star), R(1),
+                B(LdaZero),
+                B(Star), R(5),
+  /*   68 S> */ B(ForInDone), R(5), R(4),
+                B(JumpIfTrue), U8(50),
+                B(ForInNext), R(1), R(5), R(2), U8(9),
+                B(JumpIfUndefined), U8(37),
+                B(Star), R(6),
+  /*   67 E> */ B(StaNamedPropertySloppy), R(0), U8(2), U8(7),
+  /*   62 E> */ B(StackCheck),
+  /*   95 S> */ B(Nop),
+  /*  100 E> */ B(LdrNamedProperty), R(0), U8(2), U8(3), R(7),
+                B(LdaSmi), U8(10),
+  /*  106 E> */ B(TestEqual), R(7),
+                B(JumpIfFalse), U8(4),
+  /*  113 S> */ B(Jump), U8(16),
+  /*  125 S> */ B(Nop),
+  /*  130 E> */ B(LdrNamedProperty), R(0), U8(2), U8(5), R(7),
+                B(LdaSmi), U8(20),
+  /*  136 E> */ B(TestEqual), R(7),
+                B(JumpIfFalse), U8(4),
+  /*  143 S> */ B(Jump), U8(8),
+                B(ForInStep), R(5),
+                B(Star), R(5),
+                B(Jump), U8(-51),
+                B(LdaUndefined),
+  /*  152 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -214,41 +205,37 @@
 "
 frame size: 9
 parameter count: 1
-bytecode array length: 69
+bytecode array length: 61
 bytecodes: [
-  B(StackCheck),
-  B(CreateArrayLiteral), U8(0), U8(0), U8(3),
-  B(Star), R(0),
-  B(CreateArrayLiteral), U8(1), U8(1), U8(3),
-  B(JumpIfUndefined), U8(56),
-  B(JumpIfNull), U8(54),
-  B(ToObject),
-  B(Star), R(1),
-  B(ForInPrepare), R(2),
-  B(LdaZero),
-  B(Star), R(5),
-  B(ForInDone), R(5), R(4),
-  B(JumpIfTrue), U8(41),
-  B(ForInNext), R(1), R(5), R(2), U8(7),
-  B(JumpIfUndefined), U8(28),
-  B(Star), R(6),
-  B(Ldar), R(0),
-  B(Star), R(7),
-  B(LdaZero),
-  B(Star), R(8),
-  B(Ldar), R(6),
-  B(KeyedStoreICSloppy), R(7), R(8), U8(5),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(6),
-  B(LdaSmi), U8(3),
-  B(KeyedLoadIC), R(6), U8(3),
-  B(Return),
-  B(ForInStep), R(5),
-  B(Star), R(5),
-  B(Jump), U8(-42),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(3),
+                B(Star), R(0),
+  /*   72 S> */ B(CreateArrayLiteral), U8(1), U8(1), U8(3),
+                B(JumpIfUndefined), U8(48),
+                B(JumpIfNull), U8(46),
+                B(ToObject),
+                B(ForInPrepare), R(2),
+                B(Star), R(1),
+                B(LdaZero),
+                B(Star), R(5),
+  /*   65 S> */ B(ForInDone), R(5), R(4),
+                B(JumpIfTrue), U8(33),
+                B(ForInNext), R(1), R(5), R(2), U8(7),
+                B(JumpIfUndefined), U8(20),
+                B(Star), R(6),
+                B(LdaZero),
+                B(Star), R(8),
+                B(Ldar), R(6),
+  /*   64 E> */ B(StaKeyedPropertySloppy), R(0), R(8), U8(5),
+  /*   59 E> */ B(StackCheck),
+  /*   83 S> */ B(LdaSmi), U8(3),
+  /*   91 E> */ B(LdaKeyedProperty), R(0), U8(3),
+  /*   98 S> */ B(Return),
+                B(ForInStep), R(5),
+                B(Star), R(5),
+                B(Jump), U8(-34),
+                B(LdaUndefined),
+  /*   98 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/ForOf.golden b/test/cctest/interpreter/bytecode_expectations/ForOf.golden
index 9b10f41..06cdb3d 100644
--- a/test/cctest/interpreter/bytecode_expectations/ForOf.golden
+++ b/test/cctest/interpreter/bytecode_expectations/ForOf.golden
@@ -13,159 +13,123 @@
 "
 frame size: 16
 parameter count: 1
-bytecode array length: 347
+bytecode array length: 284
 bytecodes: [
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Star), R(4),
-  B(LdaZero),
-  B(Star), R(3),
-  B(Mov), R(context), R(11),
-  B(Mov), R(context), R(12),
-  B(CreateArrayLiteral), U8(0), U8(0), U8(3),
-  B(Star), R(14),
-  B(LdaConstant), U8(1),
-  B(KeyedLoadIC), R(14), U8(3),
-  B(Star), R(13),
-  B(Call), R(13), R(14), U8(1), U8(1),
-  B(Star), R(1),
-  B(Ldar), R(1),
-  B(Star), R(15),
-  B(LoadIC), R(15), U8(2), U8(7),
-  B(Star), R(14),
-  B(Call), R(14), R(15), U8(1), U8(5),
-  B(Star), R(2),
-  B(Star), R(13),
-  B(InvokeIntrinsic), U16(Runtime::k_IsJSReceiver), R(13), U8(1),
-  B(LogicalNot),
-  B(JumpIfFalse), U8(11),
-  B(Ldar), R(2),
-  B(Star), R(13),
-  B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(13), U8(1),
-  B(Ldar), R(2),
-  B(Star), R(13),
-  B(LoadIC), R(13), U8(3), U8(9),
-  B(JumpIfToBooleanTrue), U8(28),
-  B(LdaSmi), U8(2),
-  B(Star), R(3),
-  B(Ldar), R(2),
-  B(Star), R(13),
-  B(LoadIC), R(13), U8(4), U8(11),
-  B(Star), R(0),
-  B(Ldar), R(4),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(7),
-  B(LdaZero),
-  B(Star), R(3),
-  B(Jump), U8(-70),
-  B(Jump), U8(47),
-  B(Star), R(14),
-  B(LdaConstant), U8(5),
-  B(Star), R(13),
-  B(Ldar), R(closure),
-  B(Star), R(15),
-  B(CallRuntime), U16(Runtime::kPushCatchContext), R(13), U8(3),
-  B(Star), R(12),
-  B(PushContext), R(8),
-  B(Ldar), R(3),
-  B(Star), R(13),
-  B(LdaSmi), U8(2),
-  B(TestEqualStrict), R(13),
-  B(JumpIfFalse), U8(6),
-  B(LdaSmi), U8(1),
-  B(Star), R(3),
-  B(LdaContextSlot), R(context), U8(4),
-  B(Star), R(13),
-  B(CallRuntime), U16(Runtime::kReThrow), R(13), U8(1),
-  B(PopContext), R(8),
-  B(LdaSmi), U8(-1),
-  B(Star), R(9),
-  B(Jump), U8(7),
-  B(Star), R(10),
-  B(LdaZero),
-  B(Star), R(9),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Star), R(11),
-  B(Ldar), R(3),
-  B(Star), R(12),
-  B(LdaZero),
-  B(TestEqualStrict), R(12),
-  B(JumpIfTrue), U8(9),
-  B(Ldar), R(1),
-  B(Star), R(12),
-  B(LdaUndefined),
-  B(TestEqualStrict), R(12),
-  B(LogicalNot),
-  B(JumpIfFalseConstant), U8(9),
-  B(Ldar), R(1),
-  B(Star), R(12),
-  B(LoadIC), R(12), U8(6), U8(13),
-  B(Star), R(5),
-  B(Star), R(12),
-  B(LdaNull),
-  B(TestEqual), R(12),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(124),
-  B(Ldar), R(3),
-  B(Star), R(12),
-  B(LdaSmi), U8(1),
-  B(TestEqualStrict), R(12),
-  B(JumpIfFalse), U8(79),
-  B(Ldar), R(5),
-  B(TypeOf),
-  B(Star), R(12),
-  B(LdaConstant), U8(7),
-  B(TestEqualStrict), R(12),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(18),
-  B(Wide), B(LdaSmi), U16(139),
-  B(Star), R(12),
-  B(LdaConstant), U8(8),
-  B(Star), R(13),
-  B(CallRuntime), U16(Runtime::kNewTypeError), R(12), U8(2),
-  B(Throw),
-  B(Mov), R(context), R(12),
-  B(Ldar), R(5),
-  B(Star), R(13),
-  B(Ldar), R(1),
-  B(Star), R(14),
-  B(CallRuntime), U16(Runtime::k_Call), R(13), U8(2),
-  B(Jump), U8(30),
-  B(Star), R(14),
-  B(LdaConstant), U8(5),
-  B(Star), R(13),
-  B(Ldar), R(closure),
-  B(Star), R(15),
-  B(CallRuntime), U16(Runtime::kPushCatchContext), R(13), U8(3),
-  B(Star), R(12),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Ldar), R(12),
-  B(PushContext), R(8),
-  B(PopContext), R(8),
-  B(Jump), U8(37),
-  B(Ldar), R(5),
-  B(Star), R(12),
-  B(Ldar), R(1),
-  B(Star), R(13),
-  B(CallRuntime), U16(Runtime::k_Call), R(12), U8(2),
-  B(Star), R(6),
-  B(Star), R(12),
-  B(InvokeIntrinsic), U16(Runtime::k_IsJSReceiver), R(12), U8(1),
-  B(JumpIfToBooleanFalse), U8(4),
-  B(Jump), U8(11),
-  B(Ldar), R(6),
-  B(Star), R(12),
-  B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(12), U8(1),
-  B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(11), U8(1),
-  B(LdaZero),
-  B(TestEqualStrict), R(9),
-  B(JumpIfTrue), U8(4),
-  B(Jump), U8(5),
-  B(Ldar), R(10),
-  B(ReThrow),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+                B(LdrUndefined), R(4),
+                B(LdaZero),
+                B(Star), R(3),
+                B(Mov), R(context), R(11),
+                B(Mov), R(context), R(12),
+  /*   48 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(3),
+                B(Star), R(14),
+                B(LdaConstant), U8(1),
+  /*   48 E> */ B(LdrKeyedProperty), R(14), U8(3), R(13),
+  /*   48 E> */ B(Call), R(13), R(14), U8(1), U8(1),
+                B(Star), R(1),
+  /*   45 S> */ B(LdrNamedProperty), R(1), U8(2), U8(7), R(14),
+  /*   45 E> */ B(Call), R(14), R(1), U8(1), U8(5),
+                B(Star), R(2),
+  /*   45 E> */ B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(2), U8(1),
+                B(ToBooleanLogicalNot),
+                B(JumpIfFalse), U8(7),
+                B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(2), U8(1),
+                B(LdaNamedProperty), R(2), U8(3), U8(9),
+                B(JumpIfToBooleanTrue), U8(22),
+                B(LdaSmi), U8(2),
+                B(Star), R(3),
+                B(LdrNamedProperty), R(2), U8(4), U8(11), R(0),
+                B(Ldar), R(0),
+  /*   34 E> */ B(StackCheck),
+                B(Mov), R(0), R(7),
+                B(LdaZero),
+                B(Star), R(3),
+                B(Jump), U8(-48),
+                B(Jump), U8(41),
+                B(Star), R(14),
+                B(LdaConstant), U8(5),
+                B(Star), R(13),
+                B(Mov), R(closure), R(15),
+                B(CallRuntime), U16(Runtime::kPushCatchContext), R(13), U8(3),
+                B(Star), R(12),
+                B(PushContext), R(8),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(3),
+                B(JumpIfFalse), U8(6),
+                B(LdaSmi), U8(1),
+                B(Star), R(3),
+                B(LdrContextSlot), R(context), U8(4), R(13),
+                B(CallRuntime), U16(Runtime::kReThrow), R(13), U8(1),
+                B(PopContext), R(8),
+                B(LdaSmi), U8(-1),
+                B(Star), R(9),
+                B(Jump), U8(7),
+                B(Star), R(10),
+                B(LdaZero),
+                B(Star), R(9),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Star), R(11),
+                B(LdaZero),
+                B(TestEqualStrict), R(3),
+                B(JumpIfTrue), U8(5),
+                B(LdaUndefined),
+                B(TestEqualStrict), R(1),
+                B(ToBooleanLogicalNot),
+                B(JumpIfFalse), U8(118),
+                B(LdrNamedProperty), R(1), U8(6), U8(13), R(5),
+                B(LdaNull),
+                B(TestEqual), R(5),
+                B(JumpIfFalse), U8(4),
+                B(Jump), U8(106),
+                B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(3),
+                B(JumpIfFalse), U8(75),
+                B(Ldar), R(5),
+                B(TypeOf),
+                B(Star), R(12),
+                B(LdaConstant), U8(7),
+                B(TestEqualStrict), R(12),
+                B(JumpIfFalse), U8(4),
+                B(Jump), U8(18),
+                B(Wide), B(LdaSmi), U16(128),
+                B(Star), R(12),
+                B(LdaConstant), U8(8),
+                B(Star), R(13),
+                B(CallRuntime), U16(Runtime::kNewTypeError), R(12), U8(2),
+                B(Throw),
+                B(Mov), R(context), R(12),
+                B(Mov), R(5), R(13),
+                B(Mov), R(1), R(14),
+                B(InvokeIntrinsic), U8(Runtime::k_Call), R(13), U8(2),
+                B(Jump), U8(29),
+                B(Star), R(14),
+                B(LdaConstant), U8(5),
+                B(Star), R(13),
+                B(Mov), R(closure), R(15),
+                B(CallRuntime), U16(Runtime::kPushCatchContext), R(13), U8(3),
+                B(Star), R(12),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Ldar), R(12),
+                B(PushContext), R(8),
+                B(PopContext), R(8),
+                B(Jump), U8(27),
+                B(Mov), R(5), R(12),
+                B(Mov), R(1), R(13),
+                B(InvokeIntrinsic), U8(Runtime::k_Call), R(12), U8(2),
+                B(Star), R(6),
+                B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(6), U8(1),
+                B(JumpIfToBooleanFalse), U8(4),
+                B(Jump), U8(7),
+                B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(6), U8(1),
+                B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(11), U8(1),
+                B(LdaZero),
+                B(TestEqualStrict), R(9),
+                B(JumpIfTrue), U8(4),
+                B(Jump), U8(5),
+                B(Ldar), R(10),
+                B(ReThrow),
+                B(LdaUndefined),
+  /*   62 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -177,12 +141,11 @@
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
-  kInstanceTypeDontCare,
 ]
 handlers: [
-  [10, 152, 158],
-  [13, 105, 107],
-  [250, 263, 265],
+  [9, 122, 128],
+  [12, 81, 83],
+  [201, 211, 213],
 ]
 
 ---
@@ -192,168 +155,130 @@
 "
 frame size: 17
 parameter count: 1
-bytecode array length: 363
+bytecode array length: 297
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(7),
-  B(LdaUndefined),
-  B(Star), R(4),
-  B(LdaZero),
-  B(Star), R(3),
-  B(Mov), R(context), R(12),
-  B(Mov), R(context), R(13),
-  B(Ldar), R(7),
-  B(Star), R(15),
-  B(LdaConstant), U8(1),
-  B(KeyedLoadIC), R(15), U8(3),
-  B(Star), R(14),
-  B(Call), R(14), R(15), U8(1), U8(1),
-  B(Star), R(1),
-  B(Ldar), R(1),
-  B(Star), R(16),
-  B(LoadIC), R(16), U8(2), U8(7),
-  B(Star), R(15),
-  B(Call), R(15), R(16), U8(1), U8(5),
-  B(Star), R(2),
-  B(Star), R(14),
-  B(InvokeIntrinsic), U16(Runtime::k_IsJSReceiver), R(14), U8(1),
-  B(LogicalNot),
-  B(JumpIfFalse), U8(11),
-  B(Ldar), R(2),
-  B(Star), R(14),
-  B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(14), U8(1),
-  B(Ldar), R(2),
-  B(Star), R(14),
-  B(LoadIC), R(14), U8(3), U8(9),
-  B(JumpIfToBooleanTrue), U8(32),
-  B(LdaSmi), U8(2),
-  B(Star), R(3),
-  B(Ldar), R(2),
-  B(Star), R(14),
-  B(LoadIC), R(14), U8(4), U8(11),
-  B(Star), R(0),
-  B(Ldar), R(4),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(8),
-  B(Star), R(11),
-  B(LdaZero),
-  B(Star), R(10),
-  B(Jump), U8(63),
-  B(Jump), U8(-74),
-  B(Jump), U8(47),
-  B(Star), R(15),
-  B(LdaConstant), U8(5),
-  B(Star), R(14),
-  B(Ldar), R(closure),
-  B(Star), R(16),
-  B(CallRuntime), U16(Runtime::kPushCatchContext), R(14), U8(3),
-  B(Star), R(13),
-  B(PushContext), R(9),
-  B(Ldar), R(3),
-  B(Star), R(14),
-  B(LdaSmi), U8(2),
-  B(TestEqualStrict), R(14),
-  B(JumpIfFalse), U8(6),
-  B(LdaSmi), U8(1),
-  B(Star), R(3),
-  B(LdaContextSlot), R(context), U8(4),
-  B(Star), R(14),
-  B(CallRuntime), U16(Runtime::kReThrow), R(14), U8(1),
-  B(PopContext), R(9),
-  B(LdaSmi), U8(-1),
-  B(Star), R(10),
-  B(Jump), U8(8),
-  B(Star), R(11),
-  B(LdaSmi), U8(1),
-  B(Star), R(10),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Star), R(12),
-  B(Ldar), R(3),
-  B(Star), R(13),
-  B(LdaZero),
-  B(TestEqualStrict), R(13),
-  B(JumpIfTrue), U8(9),
-  B(Ldar), R(1),
-  B(Star), R(13),
-  B(LdaUndefined),
-  B(TestEqualStrict), R(13),
-  B(LogicalNot),
-  B(JumpIfFalseConstant), U8(9),
-  B(Ldar), R(1),
-  B(Star), R(13),
-  B(LoadIC), R(13), U8(6), U8(13),
-  B(Star), R(5),
-  B(Star), R(13),
-  B(LdaNull),
-  B(TestEqual), R(13),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(124),
-  B(Ldar), R(3),
-  B(Star), R(13),
-  B(LdaSmi), U8(1),
-  B(TestEqualStrict), R(13),
-  B(JumpIfFalse), U8(79),
-  B(Ldar), R(5),
-  B(TypeOf),
-  B(Star), R(13),
-  B(LdaConstant), U8(7),
-  B(TestEqualStrict), R(13),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(18),
-  B(Wide), B(LdaSmi), U16(139),
-  B(Star), R(13),
-  B(LdaConstant), U8(8),
-  B(Star), R(14),
-  B(CallRuntime), U16(Runtime::kNewTypeError), R(13), U8(2),
-  B(Throw),
-  B(Mov), R(context), R(13),
-  B(Ldar), R(5),
-  B(Star), R(14),
-  B(Ldar), R(1),
-  B(Star), R(15),
-  B(CallRuntime), U16(Runtime::k_Call), R(14), U8(2),
-  B(Jump), U8(30),
-  B(Star), R(15),
-  B(LdaConstant), U8(5),
-  B(Star), R(14),
-  B(Ldar), R(closure),
-  B(Star), R(16),
-  B(CallRuntime), U16(Runtime::kPushCatchContext), R(14), U8(3),
-  B(Star), R(13),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Ldar), R(13),
-  B(PushContext), R(9),
-  B(PopContext), R(9),
-  B(Jump), U8(37),
-  B(Ldar), R(5),
-  B(Star), R(13),
-  B(Ldar), R(1),
-  B(Star), R(14),
-  B(CallRuntime), U16(Runtime::k_Call), R(13), U8(2),
-  B(Star), R(6),
-  B(Star), R(13),
-  B(InvokeIntrinsic), U16(Runtime::k_IsJSReceiver), R(13), U8(1),
-  B(JumpIfToBooleanFalse), U8(4),
-  B(Jump), U8(11),
-  B(Ldar), R(6),
-  B(Star), R(13),
-  B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(13), U8(1),
-  B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(12), U8(1),
-  B(LdaZero),
-  B(TestEqualStrict), R(10),
-  B(JumpIfTrue), U8(10),
-  B(LdaSmi), U8(1),
-  B(TestEqualStrict), R(10),
-  B(JumpIfTrue), U8(7),
-  B(Jump), U8(8),
-  B(Ldar), R(11),
-  B(Return),
-  B(Ldar), R(11),
-  B(ReThrow),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaConstant), U8(0),
+                B(Star), R(7),
+                B(LdrUndefined), R(4),
+                B(LdaZero),
+                B(Star), R(3),
+                B(Mov), R(context), R(12),
+                B(Mov), R(context), R(13),
+  /*   68 S> */ B(LdaConstant), U8(1),
+  /*   68 E> */ B(LdrKeyedProperty), R(7), U8(3), R(14),
+  /*   68 E> */ B(Call), R(14), R(7), U8(1), U8(1),
+                B(Star), R(1),
+  /*   65 S> */ B(LdrNamedProperty), R(1), U8(2), U8(7), R(15),
+  /*   65 E> */ B(Call), R(15), R(1), U8(1), U8(5),
+                B(Star), R(2),
+  /*   65 E> */ B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(2), U8(1),
+                B(ToBooleanLogicalNot),
+                B(JumpIfFalse), U8(7),
+                B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(2), U8(1),
+                B(LdaNamedProperty), R(2), U8(3), U8(9),
+                B(JumpIfToBooleanTrue), U8(27),
+                B(LdaSmi), U8(2),
+                B(Star), R(3),
+                B(LdrNamedProperty), R(2), U8(4), U8(11), R(0),
+                B(Ldar), R(0),
+  /*   54 E> */ B(StackCheck),
+                B(Mov), R(0), R(8),
+  /*   73 S> */ B(LdaZero),
+                B(Star), R(10),
+                B(Mov), R(0), R(11),
+                B(Jump), U8(57),
+                B(Jump), U8(-53),
+                B(Jump), U8(41),
+                B(Star), R(15),
+                B(LdaConstant), U8(5),
+                B(Star), R(14),
+                B(Mov), R(closure), R(16),
+                B(CallRuntime), U16(Runtime::kPushCatchContext), R(14), U8(3),
+                B(Star), R(13),
+                B(PushContext), R(9),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(3),
+                B(JumpIfFalse), U8(6),
+                B(LdaSmi), U8(1),
+                B(Star), R(3),
+                B(LdrContextSlot), R(context), U8(4), R(14),
+                B(CallRuntime), U16(Runtime::kReThrow), R(14), U8(1),
+                B(PopContext), R(9),
+                B(LdaSmi), U8(-1),
+                B(Star), R(10),
+                B(Jump), U8(8),
+                B(Star), R(11),
+                B(LdaSmi), U8(1),
+                B(Star), R(10),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Star), R(12),
+                B(LdaZero),
+                B(TestEqualStrict), R(3),
+                B(JumpIfTrue), U8(5),
+                B(LdaUndefined),
+                B(TestEqualStrict), R(1),
+                B(ToBooleanLogicalNot),
+                B(JumpIfFalse), U8(118),
+                B(LdrNamedProperty), R(1), U8(6), U8(13), R(5),
+                B(LdaNull),
+                B(TestEqual), R(5),
+                B(JumpIfFalse), U8(4),
+                B(Jump), U8(106),
+                B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(3),
+                B(JumpIfFalse), U8(75),
+                B(Ldar), R(5),
+                B(TypeOf),
+                B(Star), R(13),
+                B(LdaConstant), U8(7),
+                B(TestEqualStrict), R(13),
+                B(JumpIfFalse), U8(4),
+                B(Jump), U8(18),
+                B(Wide), B(LdaSmi), U16(128),
+                B(Star), R(13),
+                B(LdaConstant), U8(8),
+                B(Star), R(14),
+                B(CallRuntime), U16(Runtime::kNewTypeError), R(13), U8(2),
+                B(Throw),
+                B(Mov), R(context), R(13),
+                B(Mov), R(5), R(14),
+                B(Mov), R(1), R(15),
+                B(InvokeIntrinsic), U8(Runtime::k_Call), R(14), U8(2),
+                B(Jump), U8(29),
+                B(Star), R(15),
+                B(LdaConstant), U8(5),
+                B(Star), R(14),
+                B(Mov), R(closure), R(16),
+                B(CallRuntime), U16(Runtime::kPushCatchContext), R(14), U8(3),
+                B(Star), R(13),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Ldar), R(13),
+                B(PushContext), R(9),
+                B(PopContext), R(9),
+                B(Jump), U8(27),
+                B(Mov), R(5), R(13),
+                B(Mov), R(1), R(14),
+                B(InvokeIntrinsic), U8(Runtime::k_Call), R(13), U8(2),
+                B(Star), R(6),
+                B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(6), U8(1),
+                B(JumpIfToBooleanFalse), U8(4),
+                B(Jump), U8(7),
+                B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(6), U8(1),
+                B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(12), U8(1),
+                B(LdaZero),
+                B(TestEqualStrict), R(10),
+                B(JumpIfTrue), U8(10),
+                B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(10),
+                B(JumpIfTrue), U8(7),
+                B(Jump), U8(8),
+                B(Ldar), R(11),
+  /*   85 S> */ B(Return),
+                B(Ldar), R(11),
+                B(ReThrow),
+                B(LdaUndefined),
+  /*   85 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
@@ -365,12 +290,11 @@
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
-  kInstanceTypeDontCare,
 ]
 handlers: [
-  [14, 158, 164],
-  [17, 111, 113],
-  [257, 270, 272],
+  [13, 125, 131],
+  [16, 84, 86],
+  [205, 215, 217],
 ]
 
 ---
@@ -382,170 +306,131 @@
 "
 frame size: 16
 parameter count: 1
-bytecode array length: 369
+bytecode array length: 300
 bytecodes: [
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Star), R(4),
-  B(LdaZero),
-  B(Star), R(3),
-  B(Mov), R(context), R(11),
-  B(Mov), R(context), R(12),
-  B(CreateArrayLiteral), U8(0), U8(0), U8(3),
-  B(Star), R(14),
-  B(LdaConstant), U8(1),
-  B(KeyedLoadIC), R(14), U8(3),
-  B(Star), R(13),
-  B(Call), R(13), R(14), U8(1), U8(1),
-  B(Star), R(1),
-  B(Ldar), R(1),
-  B(Star), R(15),
-  B(LoadIC), R(15), U8(2), U8(7),
-  B(Star), R(14),
-  B(Call), R(14), R(15), U8(1), U8(5),
-  B(Star), R(2),
-  B(Star), R(13),
-  B(InvokeIntrinsic), U16(Runtime::k_IsJSReceiver), R(13), U8(1),
-  B(LogicalNot),
-  B(JumpIfFalse), U8(11),
-  B(Ldar), R(2),
-  B(Star), R(13),
-  B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(13), U8(1),
-  B(Ldar), R(2),
-  B(Star), R(13),
-  B(LoadIC), R(13), U8(3), U8(9),
-  B(JumpIfToBooleanTrue), U8(50),
-  B(LdaSmi), U8(2),
-  B(Star), R(3),
-  B(Ldar), R(2),
-  B(Star), R(13),
-  B(LoadIC), R(13), U8(4), U8(11),
-  B(Star), R(0),
-  B(Ldar), R(4),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(7),
-  B(Star), R(13),
-  B(LdaSmi), U8(10),
-  B(TestEqual), R(13),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(-75),
-  B(Ldar), R(7),
-  B(Star), R(13),
-  B(LdaSmi), U8(20),
-  B(TestEqual), R(13),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(7),
-  B(LdaZero),
-  B(Star), R(3),
-  B(Jump), U8(-92),
-  B(Jump), U8(47),
-  B(Star), R(14),
-  B(LdaConstant), U8(5),
-  B(Star), R(13),
-  B(Ldar), R(closure),
-  B(Star), R(15),
-  B(CallRuntime), U16(Runtime::kPushCatchContext), R(13), U8(3),
-  B(Star), R(12),
-  B(PushContext), R(8),
-  B(Ldar), R(3),
-  B(Star), R(13),
-  B(LdaSmi), U8(2),
-  B(TestEqualStrict), R(13),
-  B(JumpIfFalse), U8(6),
-  B(LdaSmi), U8(1),
-  B(Star), R(3),
-  B(LdaContextSlot), R(context), U8(4),
-  B(Star), R(13),
-  B(CallRuntime), U16(Runtime::kReThrow), R(13), U8(1),
-  B(PopContext), R(8),
-  B(LdaSmi), U8(-1),
-  B(Star), R(9),
-  B(Jump), U8(7),
-  B(Star), R(10),
-  B(LdaZero),
-  B(Star), R(9),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Star), R(11),
-  B(Ldar), R(3),
-  B(Star), R(12),
-  B(LdaZero),
-  B(TestEqualStrict), R(12),
-  B(JumpIfTrue), U8(9),
-  B(Ldar), R(1),
-  B(Star), R(12),
-  B(LdaUndefined),
-  B(TestEqualStrict), R(12),
-  B(LogicalNot),
-  B(JumpIfFalseConstant), U8(9),
-  B(Ldar), R(1),
-  B(Star), R(12),
-  B(LoadIC), R(12), U8(6), U8(13),
-  B(Star), R(5),
-  B(Star), R(12),
-  B(LdaNull),
-  B(TestEqual), R(12),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(124),
-  B(Ldar), R(3),
-  B(Star), R(12),
-  B(LdaSmi), U8(1),
-  B(TestEqualStrict), R(12),
-  B(JumpIfFalse), U8(79),
-  B(Ldar), R(5),
-  B(TypeOf),
-  B(Star), R(12),
-  B(LdaConstant), U8(7),
-  B(TestEqualStrict), R(12),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(18),
-  B(Wide), B(LdaSmi), U16(139),
-  B(Star), R(12),
-  B(LdaConstant), U8(8),
-  B(Star), R(13),
-  B(CallRuntime), U16(Runtime::kNewTypeError), R(12), U8(2),
-  B(Throw),
-  B(Mov), R(context), R(12),
-  B(Ldar), R(5),
-  B(Star), R(13),
-  B(Ldar), R(1),
-  B(Star), R(14),
-  B(CallRuntime), U16(Runtime::k_Call), R(13), U8(2),
-  B(Jump), U8(30),
-  B(Star), R(14),
-  B(LdaConstant), U8(5),
-  B(Star), R(13),
-  B(Ldar), R(closure),
-  B(Star), R(15),
-  B(CallRuntime), U16(Runtime::kPushCatchContext), R(13), U8(3),
-  B(Star), R(12),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Ldar), R(12),
-  B(PushContext), R(8),
-  B(PopContext), R(8),
-  B(Jump), U8(37),
-  B(Ldar), R(5),
-  B(Star), R(12),
-  B(Ldar), R(1),
-  B(Star), R(13),
-  B(CallRuntime), U16(Runtime::k_Call), R(12), U8(2),
-  B(Star), R(6),
-  B(Star), R(12),
-  B(InvokeIntrinsic), U16(Runtime::k_IsJSReceiver), R(12), U8(1),
-  B(JumpIfToBooleanFalse), U8(4),
-  B(Jump), U8(11),
-  B(Ldar), R(6),
-  B(Star), R(12),
-  B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(12), U8(1),
-  B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(11), U8(1),
-  B(LdaZero),
-  B(TestEqualStrict), R(9),
-  B(JumpIfTrue), U8(4),
-  B(Jump), U8(5),
-  B(Ldar), R(10),
-  B(ReThrow),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+                B(LdrUndefined), R(4),
+                B(LdaZero),
+                B(Star), R(3),
+                B(Mov), R(context), R(11),
+                B(Mov), R(context), R(12),
+  /*   48 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(3),
+                B(Star), R(14),
+                B(LdaConstant), U8(1),
+  /*   48 E> */ B(LdrKeyedProperty), R(14), U8(3), R(13),
+  /*   48 E> */ B(Call), R(13), R(14), U8(1), U8(1),
+                B(Star), R(1),
+  /*   45 S> */ B(LdrNamedProperty), R(1), U8(2), U8(7), R(14),
+  /*   45 E> */ B(Call), R(14), R(1), U8(1), U8(5),
+                B(Star), R(2),
+  /*   45 E> */ B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(2), U8(1),
+                B(ToBooleanLogicalNot),
+                B(JumpIfFalse), U8(7),
+                B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(2), U8(1),
+                B(LdaNamedProperty), R(2), U8(3), U8(9),
+                B(JumpIfToBooleanTrue), U8(38),
+                B(LdaSmi), U8(2),
+                B(Star), R(3),
+                B(LdrNamedProperty), R(2), U8(4), U8(11), R(0),
+                B(Ldar), R(0),
+  /*   34 E> */ B(StackCheck),
+                B(Mov), R(0), R(7),
+  /*   66 S> */ B(LdaSmi), U8(10),
+  /*   72 E> */ B(TestEqual), R(7),
+                B(JumpIfFalse), U8(4),
+  /*   79 S> */ B(Jump), U8(13),
+  /*   91 S> */ B(LdaSmi), U8(20),
+  /*   97 E> */ B(TestEqual), R(7),
+                B(JumpIfFalse), U8(4),
+  /*  104 S> */ B(Jump), U8(7),
+                B(LdaZero),
+                B(Star), R(3),
+                B(Jump), U8(-64),
+                B(Jump), U8(41),
+                B(Star), R(14),
+                B(LdaConstant), U8(5),
+                B(Star), R(13),
+                B(Mov), R(closure), R(15),
+                B(CallRuntime), U16(Runtime::kPushCatchContext), R(13), U8(3),
+                B(Star), R(12),
+                B(PushContext), R(8),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(3),
+                B(JumpIfFalse), U8(6),
+                B(LdaSmi), U8(1),
+                B(Star), R(3),
+                B(LdrContextSlot), R(context), U8(4), R(13),
+                B(CallRuntime), U16(Runtime::kReThrow), R(13), U8(1),
+                B(PopContext), R(8),
+                B(LdaSmi), U8(-1),
+                B(Star), R(9),
+                B(Jump), U8(7),
+                B(Star), R(10),
+                B(LdaZero),
+                B(Star), R(9),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Star), R(11),
+                B(LdaZero),
+                B(TestEqualStrict), R(3),
+                B(JumpIfTrue), U8(5),
+                B(LdaUndefined),
+                B(TestEqualStrict), R(1),
+                B(ToBooleanLogicalNot),
+                B(JumpIfFalse), U8(118),
+                B(LdrNamedProperty), R(1), U8(6), U8(13), R(5),
+                B(LdaNull),
+                B(TestEqual), R(5),
+                B(JumpIfFalse), U8(4),
+                B(Jump), U8(106),
+                B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(3),
+                B(JumpIfFalse), U8(75),
+                B(Ldar), R(5),
+                B(TypeOf),
+                B(Star), R(12),
+                B(LdaConstant), U8(7),
+                B(TestEqualStrict), R(12),
+                B(JumpIfFalse), U8(4),
+                B(Jump), U8(18),
+                B(Wide), B(LdaSmi), U16(128),
+                B(Star), R(12),
+                B(LdaConstant), U8(8),
+                B(Star), R(13),
+                B(CallRuntime), U16(Runtime::kNewTypeError), R(12), U8(2),
+                B(Throw),
+                B(Mov), R(context), R(12),
+                B(Mov), R(5), R(13),
+                B(Mov), R(1), R(14),
+                B(InvokeIntrinsic), U8(Runtime::k_Call), R(13), U8(2),
+                B(Jump), U8(29),
+                B(Star), R(14),
+                B(LdaConstant), U8(5),
+                B(Star), R(13),
+                B(Mov), R(closure), R(15),
+                B(CallRuntime), U16(Runtime::kPushCatchContext), R(13), U8(3),
+                B(Star), R(12),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Ldar), R(12),
+                B(PushContext), R(8),
+                B(PopContext), R(8),
+                B(Jump), U8(27),
+                B(Mov), R(5), R(12),
+                B(Mov), R(1), R(13),
+                B(InvokeIntrinsic), U8(Runtime::k_Call), R(12), U8(2),
+                B(Star), R(6),
+                B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(6), U8(1),
+                B(JumpIfToBooleanFalse), U8(4),
+                B(Jump), U8(7),
+                B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(6), U8(1),
+                B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(11), U8(1),
+                B(LdaZero),
+                B(TestEqualStrict), R(9),
+                B(JumpIfTrue), U8(4),
+                B(Jump), U8(5),
+                B(Ldar), R(10),
+                B(ReThrow),
+                B(LdaUndefined),
+  /*  113 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -557,12 +442,11 @@
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
-  kInstanceTypeDontCare,
 ]
 handlers: [
-  [10, 174, 180],
-  [13, 127, 129],
-  [272, 285, 287],
+  [9, 138, 144],
+  [12, 97, 99],
+  [217, 227, 229],
 ]
 
 ---
@@ -572,172 +456,133 @@
 "
 frame size: 15
 parameter count: 1
-bytecode array length: 379
+bytecode array length: 308
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(8),
-  B(Star), R(6),
-  B(LdaUndefined),
-  B(Star), R(3),
-  B(LdaZero),
-  B(Star), R(2),
-  B(Mov), R(context), R(10),
-  B(Mov), R(context), R(11),
-  B(CreateArrayLiteral), U8(1), U8(1), U8(3),
-  B(Star), R(13),
-  B(LdaConstant), U8(2),
-  B(KeyedLoadIC), R(13), U8(3),
-  B(Star), R(12),
-  B(Call), R(12), R(13), U8(1), U8(1),
-  B(Star), R(0),
-  B(Ldar), R(0),
-  B(Star), R(14),
-  B(LoadIC), R(14), U8(3), U8(7),
-  B(Star), R(13),
-  B(Call), R(13), R(14), U8(1), U8(5),
-  B(Star), R(1),
-  B(Star), R(12),
-  B(InvokeIntrinsic), U16(Runtime::k_IsJSReceiver), R(12), U8(1),
-  B(LogicalNot),
-  B(JumpIfFalse), U8(11),
-  B(Ldar), R(1),
-  B(Star), R(12),
-  B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(12), U8(1),
-  B(Ldar), R(1),
-  B(Star), R(12),
-  B(LoadIC), R(12), U8(4), U8(9),
-  B(JumpIfToBooleanTrue), U8(42),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(Ldar), R(6),
-  B(Star), R(12),
-  B(Ldar), R(1),
-  B(Star), R(13),
-  B(LoadIC), R(13), U8(5), U8(11),
-  B(StoreICSloppy), R(12), U8(6), U8(13),
-  B(Ldar), R(3),
-  B(StackCheck),
-  B(Ldar), R(6),
-  B(Star), R(12),
-  B(LoadIC), R(12), U8(6), U8(15),
-  B(Star), R(9),
-  B(LdaZero),
-  B(Star), R(8),
-  B(Jump), U8(63),
-  B(Jump), U8(-84),
-  B(Jump), U8(47),
-  B(Star), R(13),
-  B(LdaConstant), U8(7),
-  B(Star), R(12),
-  B(Ldar), R(closure),
-  B(Star), R(14),
-  B(CallRuntime), U16(Runtime::kPushCatchContext), R(12), U8(3),
-  B(Star), R(11),
-  B(PushContext), R(7),
-  B(Ldar), R(2),
-  B(Star), R(12),
-  B(LdaSmi), U8(2),
-  B(TestEqualStrict), R(12),
-  B(JumpIfFalse), U8(6),
-  B(LdaSmi), U8(1),
-  B(Star), R(2),
-  B(LdaContextSlot), R(context), U8(4),
-  B(Star), R(12),
-  B(CallRuntime), U16(Runtime::kReThrow), R(12), U8(1),
-  B(PopContext), R(7),
-  B(LdaSmi), U8(-1),
-  B(Star), R(8),
-  B(Jump), U8(8),
-  B(Star), R(9),
-  B(LdaSmi), U8(1),
-  B(Star), R(8),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Star), R(10),
-  B(Ldar), R(2),
-  B(Star), R(11),
-  B(LdaZero),
-  B(TestEqualStrict), R(11),
-  B(JumpIfTrue), U8(9),
-  B(Ldar), R(0),
-  B(Star), R(11),
-  B(LdaUndefined),
-  B(TestEqualStrict), R(11),
-  B(LogicalNot),
-  B(JumpIfFalseConstant), U8(11),
-  B(Ldar), R(0),
-  B(Star), R(11),
-  B(LoadIC), R(11), U8(8), U8(17),
-  B(Star), R(4),
-  B(Star), R(11),
-  B(LdaNull),
-  B(TestEqual), R(11),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(124),
-  B(Ldar), R(2),
-  B(Star), R(11),
-  B(LdaSmi), U8(1),
-  B(TestEqualStrict), R(11),
-  B(JumpIfFalse), U8(79),
-  B(Ldar), R(4),
-  B(TypeOf),
-  B(Star), R(11),
-  B(LdaConstant), U8(9),
-  B(TestEqualStrict), R(11),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(18),
-  B(Wide), B(LdaSmi), U16(139),
-  B(Star), R(11),
-  B(LdaConstant), U8(10),
-  B(Star), R(12),
-  B(CallRuntime), U16(Runtime::kNewTypeError), R(11), U8(2),
-  B(Throw),
-  B(Mov), R(context), R(11),
-  B(Ldar), R(4),
-  B(Star), R(12),
-  B(Ldar), R(0),
-  B(Star), R(13),
-  B(CallRuntime), U16(Runtime::k_Call), R(12), U8(2),
-  B(Jump), U8(30),
-  B(Star), R(13),
-  B(LdaConstant), U8(7),
-  B(Star), R(12),
-  B(Ldar), R(closure),
-  B(Star), R(14),
-  B(CallRuntime), U16(Runtime::kPushCatchContext), R(12), U8(3),
-  B(Star), R(11),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Ldar), R(11),
-  B(PushContext), R(7),
-  B(PopContext), R(7),
-  B(Jump), U8(37),
-  B(Ldar), R(4),
-  B(Star), R(11),
-  B(Ldar), R(0),
-  B(Star), R(12),
-  B(CallRuntime), U16(Runtime::k_Call), R(11), U8(2),
-  B(Star), R(5),
-  B(Star), R(11),
-  B(InvokeIntrinsic), U16(Runtime::k_IsJSReceiver), R(11), U8(1),
-  B(JumpIfToBooleanFalse), U8(4),
-  B(Jump), U8(11),
-  B(Ldar), R(5),
-  B(Star), R(11),
-  B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(11), U8(1),
-  B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(10), U8(1),
-  B(LdaZero),
-  B(TestEqualStrict), R(8),
-  B(JumpIfTrue), U8(10),
-  B(LdaSmi), U8(1),
-  B(TestEqualStrict), R(8),
-  B(JumpIfTrue), U8(7),
-  B(Jump), U8(8),
-  B(Ldar), R(9),
-  B(Return),
-  B(Ldar), R(9),
-  B(ReThrow),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(8),
+                B(Star), R(6),
+                B(LdrUndefined), R(3),
+                B(LdaZero),
+                B(Star), R(2),
+                B(Mov), R(context), R(10),
+                B(Mov), R(context), R(11),
+  /*   77 S> */ B(CreateArrayLiteral), U8(1), U8(1), U8(3),
+                B(Star), R(13),
+                B(LdaConstant), U8(2),
+  /*   77 E> */ B(LdrKeyedProperty), R(13), U8(3), R(12),
+  /*   77 E> */ B(Call), R(12), R(13), U8(1), U8(1),
+                B(Star), R(0),
+  /*   74 S> */ B(LdrNamedProperty), R(0), U8(3), U8(7), R(13),
+  /*   74 E> */ B(Call), R(13), R(0), U8(1), U8(5),
+                B(Star), R(1),
+  /*   74 E> */ B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(1), U8(1),
+                B(ToBooleanLogicalNot),
+                B(JumpIfFalse), U8(7),
+                B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(1), U8(1),
+                B(LdaNamedProperty), R(1), U8(4), U8(9),
+                B(JumpIfToBooleanTrue), U8(28),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+  /*   67 E> */ B(LdaNamedProperty), R(1), U8(5), U8(11),
+                B(StaNamedPropertySloppy), R(6), U8(6), U8(13),
+  /*   62 E> */ B(StackCheck),
+  /*   88 S> */ B(Nop),
+  /*   96 E> */ B(LdrNamedProperty), R(6), U8(6), U8(15), R(9),
+                B(LdaZero),
+                B(Star), R(8),
+                B(Jump), U8(57),
+                B(Jump), U8(-54),
+                B(Jump), U8(41),
+                B(Star), R(13),
+                B(LdaConstant), U8(7),
+                B(Star), R(12),
+                B(Mov), R(closure), R(14),
+                B(CallRuntime), U16(Runtime::kPushCatchContext), R(12), U8(3),
+                B(Star), R(11),
+                B(PushContext), R(7),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(2),
+                B(JumpIfFalse), U8(6),
+                B(LdaSmi), U8(1),
+                B(Star), R(2),
+                B(LdrContextSlot), R(context), U8(4), R(12),
+                B(CallRuntime), U16(Runtime::kReThrow), R(12), U8(1),
+                B(PopContext), R(7),
+                B(LdaSmi), U8(-1),
+                B(Star), R(8),
+                B(Jump), U8(8),
+                B(Star), R(9),
+                B(LdaSmi), U8(1),
+                B(Star), R(8),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Star), R(10),
+                B(LdaZero),
+                B(TestEqualStrict), R(2),
+                B(JumpIfTrue), U8(5),
+                B(LdaUndefined),
+                B(TestEqualStrict), R(0),
+                B(ToBooleanLogicalNot),
+                B(JumpIfFalse), U8(118),
+                B(LdrNamedProperty), R(0), U8(8), U8(17), R(4),
+                B(LdaNull),
+                B(TestEqual), R(4),
+                B(JumpIfFalse), U8(4),
+                B(Jump), U8(106),
+                B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(2),
+                B(JumpIfFalse), U8(75),
+                B(Ldar), R(4),
+                B(TypeOf),
+                B(Star), R(11),
+                B(LdaConstant), U8(9),
+                B(TestEqualStrict), R(11),
+                B(JumpIfFalse), U8(4),
+                B(Jump), U8(18),
+                B(Wide), B(LdaSmi), U16(128),
+                B(Star), R(11),
+                B(LdaConstant), U8(10),
+                B(Star), R(12),
+                B(CallRuntime), U16(Runtime::kNewTypeError), R(11), U8(2),
+                B(Throw),
+                B(Mov), R(context), R(11),
+                B(Mov), R(4), R(12),
+                B(Mov), R(0), R(13),
+                B(InvokeIntrinsic), U8(Runtime::k_Call), R(12), U8(2),
+                B(Jump), U8(29),
+                B(Star), R(13),
+                B(LdaConstant), U8(7),
+                B(Star), R(12),
+                B(Mov), R(closure), R(14),
+                B(CallRuntime), U16(Runtime::kPushCatchContext), R(12), U8(3),
+                B(Star), R(11),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Ldar), R(11),
+                B(PushContext), R(7),
+                B(PopContext), R(7),
+                B(Jump), U8(27),
+                B(Mov), R(4), R(11),
+                B(Mov), R(0), R(12),
+                B(InvokeIntrinsic), U8(Runtime::k_Call), R(11), U8(2),
+                B(Star), R(5),
+                B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(5), U8(1),
+                B(JumpIfToBooleanFalse), U8(4),
+                B(Jump), U8(7),
+                B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(5), U8(1),
+                B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(10), U8(1),
+                B(LdaZero),
+                B(TestEqualStrict), R(8),
+                B(JumpIfTrue), U8(10),
+                B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(8),
+                B(JumpIfTrue), U8(7),
+                B(Jump), U8(8),
+                B(Ldar), R(9),
+  /*  105 S> */ B(Return),
+                B(Ldar), R(9),
+                B(ReThrow),
+                B(LdaUndefined),
+  /*  105 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -751,11 +596,10 @@
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
-  kInstanceTypeDontCare,
 ]
 handlers: [
-  [18, 174, 180],
-  [21, 127, 129],
-  [273, 286, 288],
+  [17, 136, 142],
+  [20, 95, 97],
+  [216, 226, 228],
 ]
 
diff --git a/test/cctest/interpreter/bytecode_expectations/FunctionLiterals.golden b/test/cctest/interpreter/bytecode_expectations/FunctionLiterals.golden
index fe7176c..b89bbd6 100644
--- a/test/cctest/interpreter/bytecode_expectations/FunctionLiterals.golden
+++ b/test/cctest/interpreter/bytecode_expectations/FunctionLiterals.golden
@@ -15,9 +15,9 @@
 parameter count: 1
 bytecode array length: 5
 bytecodes: [
-  B(StackCheck),
-  B(CreateClosure), U8(0), U8(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(CreateClosure), U8(0), U8(0),
+  /*   55 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -31,15 +31,14 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 15
+bytecode array length: 14
 bytecodes: [
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Star), R(1),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(0),
-  B(Call), R(0), R(1), U8(1), U8(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdrUndefined), R(1),
+                B(CreateClosure), U8(0), U8(0),
+                B(Star), R(0),
+  /*   56 E> */ B(Call), R(0), R(1), U8(1), U8(1),
+  /*   59 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -53,17 +52,16 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 19
+bytecode array length: 18
 bytecodes: [
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Star), R(1),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(Star), R(2),
-  B(Call), R(0), R(1), U8(2), U8(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdrUndefined), R(1),
+                B(CreateClosure), U8(0), U8(0),
+                B(Star), R(0),
+                B(LdaSmi), U8(1),
+                B(Star), R(2),
+  /*   67 E> */ B(Call), R(0), R(1), U8(2), U8(1),
+  /*   71 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/Generators.golden b/test/cctest/interpreter/bytecode_expectations/Generators.golden
new file mode 100644
index 0000000..f75b47e
--- /dev/null
+++ b/test/cctest/interpreter/bytecode_expectations/Generators.golden
@@ -0,0 +1,615 @@
+#
+# Autogenerated by generate-bytecode-expectations.
+#
+
+---
+pool type: mixed
+execute: yes
+wrap: no
+test function name: f
+ignition generators: yes
+
+---
+snippet: "
+  function* f() { }
+  f();
+"
+frame size: 11
+parameter count: 1
+bytecode array length: 204
+bytecodes: [
+                B(Ldar), R(new_target),
+                B(JumpIfUndefined), U8(20),
+                B(ResumeGenerator), R(new_target),
+                B(Star), R(1),
+                B(LdaZero),
+                B(TestEqualStrict), R(1),
+                B(JumpIfTrue), U8(60),
+                B(LdaSmi), U8(76),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::kAbort), R(2), U8(1),
+                B(LdaSmi), U8(-2),
+                B(Star), R(1),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+                B(Ldar), R(this),
+                B(StaContextSlot), R(context), U8(4),
+  /*   11 E> */ B(StackCheck),
+                B(Mov), R(context), R(4),
+  /*   11 E> */ B(LdrContextSlot), R(context), U8(4), R(6),
+                B(Ldar), R(6),
+                B(Mov), R(closure), R(5),
+                B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(5), U8(2),
+                B(StaContextSlot), R(context), U8(5),
+                B(Star), R(5),
+                B(LdrContextSlot), R(context), U8(5), R(6),
+                B(LdaZero),
+                B(SuspendGenerator), R(6),
+                B(Ldar), R(5),
+  /*   16 S> */ B(Return),
+                B(LdaSmi), U8(-2),
+                B(Star), R(1),
+                B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(6), U8(1),
+                B(Star), R(7),
+                B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(6), U8(1),
+                B(Star), R(8),
+                B(LdaZero),
+                B(TestEqualStrict), R(8),
+                B(JumpIfTrue), U8(31),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(8),
+                B(JumpIfTrue), U8(22),
+                B(Jump), U8(2),
+                B(LdaTrue),
+                B(Star), R(10),
+                B(Mov), R(7), R(9),
+                B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(9), U8(2),
+                B(Star), R(3),
+                B(LdaZero),
+                B(Star), R(2),
+                B(Jump), U8(35),
+                B(Ldar), R(7),
+  /*   11 E> */ B(Throw),
+                B(LdrUndefined), R(5),
+                B(LdaTrue),
+                B(Star), R(6),
+                B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(5), U8(2),
+                B(Star), R(3),
+                B(LdaSmi), U8(1),
+                B(Star), R(2),
+                B(Jump), U8(14),
+                B(LdaSmi), U8(-1),
+                B(Star), R(2),
+                B(Jump), U8(8),
+                B(Star), R(3),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Star), R(4),
+                B(LdrContextSlot), R(context), U8(5), R(5),
+                B(CallRuntime), U16(Runtime::k_GeneratorClose), R(5), U8(1),
+                B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(4), U8(1),
+                B(LdaZero),
+                B(TestEqualStrict), R(2),
+                B(JumpIfTrue), U8(16),
+                B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(2),
+                B(JumpIfTrue), U8(13),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(2),
+                B(JumpIfTrue), U8(10),
+                B(Jump), U8(11),
+                B(Ldar), R(3),
+  /*   16 S> */ B(Return),
+                B(Ldar), R(3),
+  /*   16 S> */ B(Return),
+                B(Ldar), R(3),
+                B(ReThrow),
+                B(LdaUndefined),
+  /*   16 S> */ B(Return),
+]
+constant pool: [
+]
+handlers: [
+  [42, 141, 147],
+]
+
+---
+snippet: "
+  function* f() { yield 42 }
+  f();
+"
+frame size: 11
+parameter count: 1
+bytecode array length: 297
+bytecodes: [
+                B(Ldar), R(new_target),
+                B(JumpIfUndefined), U8(26),
+                B(ResumeGenerator), R(new_target),
+                B(Star), R(1),
+                B(LdaZero),
+                B(TestEqualStrict), R(1),
+                B(JumpIfTrue), U8(66),
+                B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(1),
+                B(JumpIfTrueConstant), U8(0),
+                B(LdaSmi), U8(76),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::kAbort), R(2), U8(1),
+                B(LdaSmi), U8(-2),
+                B(Star), R(1),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+                B(Ldar), R(this),
+                B(StaContextSlot), R(context), U8(4),
+  /*   11 E> */ B(StackCheck),
+                B(Mov), R(context), R(4),
+  /*   11 E> */ B(LdrContextSlot), R(context), U8(4), R(6),
+                B(Ldar), R(6),
+                B(Mov), R(closure), R(5),
+                B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(5), U8(2),
+                B(StaContextSlot), R(context), U8(5),
+                B(Star), R(5),
+                B(LdrContextSlot), R(context), U8(5), R(6),
+                B(LdaZero),
+                B(SuspendGenerator), R(6),
+                B(Ldar), R(5),
+  /*   25 S> */ B(Return),
+                B(LdaSmi), U8(-2),
+                B(Star), R(1),
+                B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(6), U8(1),
+                B(Star), R(7),
+                B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(6), U8(1),
+                B(Star), R(8),
+                B(LdaZero),
+                B(TestEqualStrict), R(8),
+                B(JumpIfTrue), U8(31),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(8),
+                B(JumpIfTrue), U8(22),
+                B(Jump), U8(2),
+                B(LdaTrue),
+                B(Star), R(10),
+                B(Mov), R(7), R(9),
+                B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(9), U8(2),
+                B(Star), R(3),
+                B(LdaZero),
+                B(Star), R(2),
+                B(Jump), U8(113),
+                B(Ldar), R(7),
+  /*   11 E> */ B(Throw),
+  /*   16 S> */ B(LdaSmi), U8(42),
+                B(Star), R(5),
+                B(LdaFalse),
+                B(Star), R(6),
+                B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(5), U8(2),
+                B(Star), R(7),
+                B(LdrContextSlot), R(context), U8(5), R(5),
+                B(LdaSmi), U8(1),
+                B(SuspendGenerator), R(5),
+                B(Ldar), R(7),
+  /*   25 S> */ B(Return),
+                B(LdaSmi), U8(-2),
+                B(Star), R(1),
+                B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(5), U8(1),
+                B(Star), R(6),
+                B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(5), U8(1),
+                B(Star), R(8),
+                B(LdaZero),
+                B(TestEqualStrict), R(8),
+                B(JumpIfTrue), U8(32),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(8),
+                B(JumpIfTrue), U8(23),
+                B(Jump), U8(2),
+                B(LdaTrue),
+                B(Star), R(10),
+                B(Mov), R(6), R(9),
+                B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(9), U8(2),
+                B(Star), R(3),
+                B(LdaSmi), U8(1),
+                B(Star), R(2),
+                B(Jump), U8(35),
+                B(Ldar), R(6),
+  /*   16 E> */ B(Throw),
+                B(LdrUndefined), R(5),
+                B(LdaTrue),
+                B(Star), R(6),
+                B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(5), U8(2),
+                B(Star), R(3),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(Jump), U8(14),
+                B(LdaSmi), U8(-1),
+                B(Star), R(2),
+                B(Jump), U8(8),
+                B(Star), R(3),
+                B(LdaSmi), U8(3),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Star), R(4),
+                B(LdrContextSlot), R(context), U8(5), R(5),
+                B(CallRuntime), U16(Runtime::k_GeneratorClose), R(5), U8(1),
+                B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(4), U8(1),
+                B(LdaZero),
+                B(TestEqualStrict), R(2),
+                B(JumpIfTrue), U8(22),
+                B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(2),
+                B(JumpIfTrue), U8(19),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(2),
+                B(JumpIfTrue), U8(16),
+                B(LdaSmi), U8(3),
+                B(TestEqualStrict), R(2),
+                B(JumpIfTrue), U8(13),
+                B(Jump), U8(14),
+                B(Ldar), R(3),
+  /*   25 S> */ B(Return),
+                B(Ldar), R(3),
+  /*   25 S> */ B(Return),
+                B(Ldar), R(3),
+  /*   25 S> */ B(Return),
+                B(Ldar), R(3),
+                B(ReThrow),
+                B(LdaUndefined),
+  /*   25 S> */ B(Return),
+]
+constant pool: [
+  kInstanceTypeDontCare,
+]
+handlers: [
+  [48, 225, 231],
+]
+
+---
+snippet: "
+  function* f() { for (let x of [42]) yield x }
+  f();
+"
+frame size: 17
+parameter count: 1
+bytecode array length: 779
+bytecodes: [
+                B(Ldar), R(new_target),
+                B(JumpIfUndefined), U8(26),
+                B(ResumeGenerator), R(new_target),
+                B(Star), R(3),
+                B(LdaZero),
+                B(TestEqualStrict), R(3),
+                B(JumpIfTrue), U8(66),
+                B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(3),
+                B(JumpIfTrueConstant), U8(3),
+                B(LdaSmi), U8(76),
+                B(Star), R(4),
+                B(CallRuntime), U16(Runtime::kAbort), R(4), U8(1),
+                B(LdaSmi), U8(-2),
+                B(Star), R(3),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+                B(Ldar), R(this),
+                B(StaContextSlot), R(context), U8(4),
+  /*   11 E> */ B(StackCheck),
+                B(Mov), R(context), R(6),
+  /*   11 E> */ B(LdrContextSlot), R(context), U8(4), R(8),
+                B(Ldar), R(8),
+                B(Mov), R(closure), R(7),
+                B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(7), U8(2),
+                B(StaContextSlot), R(context), U8(5),
+                B(Star), R(7),
+                B(LdrContextSlot), R(context), U8(5), R(8),
+                B(LdaZero),
+                B(SuspendGenerator), R(8),
+                B(Ldar), R(7),
+  /*   44 S> */ B(Return),
+                B(LdaSmi), U8(-2),
+                B(Star), R(3),
+                B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(8), U8(1),
+                B(Star), R(9),
+                B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(8), U8(1),
+                B(Star), R(10),
+                B(LdaZero),
+                B(TestEqualStrict), R(10),
+                B(JumpIfTrue), U8(31),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(10),
+                B(JumpIfTrue), U8(22),
+                B(Jump), U8(2),
+                B(LdaTrue),
+                B(Star), R(12),
+                B(Mov), R(9), R(11),
+                B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(11), U8(2),
+                B(Star), R(5),
+                B(LdaZero),
+                B(Star), R(4),
+                B(JumpConstant), U8(16),
+                B(Ldar), R(9),
+  /*   11 E> */ B(Throw),
+                B(LdaConstant), U8(0),
+                B(Star), R(7),
+                B(Mov), R(closure), R(8),
+                B(CallRuntime), U16(Runtime::kPushBlockContext), R(7), U8(2),
+                B(PushContext), R(1),
+                B(LdaTheHole),
+                B(StaContextSlot), R(context), U8(4),
+                B(LdaUndefined),
+                B(StaContextSlot), R(1), U8(10),
+                B(LdaZero),
+                B(StaContextSlot), R(1), U8(9),
+                B(Mov), R(context), R(9),
+                B(Mov), R(context), R(10),
+  /*   30 S> */ B(CreateArrayLiteral), U8(1), U8(0), U8(3),
+                B(Star), R(12),
+                B(LdaConstant), U8(2),
+  /*   30 E> */ B(LdrKeyedProperty), R(12), U8(3), R(11),
+  /*   30 E> */ B(Call), R(11), R(12), U8(1), U8(1),
+  /*   30 E> */ B(StaContextSlot), R(1), U8(7),
+                B(LdaSmi), U8(-2),
+                B(TestEqual), R(3),
+                B(JumpIfTrue), U8(17),
+                B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(3),
+                B(JumpIfTrueConstant), U8(9),
+                B(LdaSmi), U8(76),
+                B(Star), R(11),
+                B(CallRuntime), U16(Runtime::kAbort), R(11), U8(1),
+  /*   27 S> */ B(LdrContextSlot), R(1), U8(7), R(13),
+                B(LdrNamedProperty), R(13), U8(4), U8(7), R(12),
+  /*   27 E> */ B(Call), R(12), R(13), U8(1), U8(5),
+  /*   27 E> */ B(StaContextSlot), R(1), U8(8),
+                B(Star), R(11),
+                B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(11), U8(1),
+                B(ToBooleanLogicalNot),
+                B(JumpIfFalse), U8(11),
+                B(LdrContextSlot), R(1), U8(8), R(11),
+                B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(11), U8(1),
+                B(LdrContextSlot), R(1), U8(8), R(11),
+                B(LdaNamedProperty), R(11), U8(5), U8(9),
+                B(JumpIfToBooleanTrueConstant), U8(10),
+                B(LdaSmi), U8(2),
+                B(StaContextSlot), R(1), U8(9),
+                B(LdrContextSlot), R(1), U8(8), R(11),
+                B(LdaNamedProperty), R(11), U8(6), U8(11),
+                B(StaContextSlot), R(1), U8(6),
+                B(LdaContextSlot), R(1), U8(10),
+  /*   16 E> */ B(StackCheck),
+                B(LdaConstant), U8(7),
+                B(Star), R(11),
+                B(Mov), R(closure), R(12),
+                B(CallRuntime), U16(Runtime::kPushBlockContext), R(11), U8(2),
+                B(PushContext), R(2),
+                B(LdaTheHole),
+                B(StaContextSlot), R(context), U8(4),
+                B(LdaContextSlot), R(1), U8(6),
+                B(StaContextSlot), R(context), U8(4),
+  /*   36 S> */ B(LdaContextSlot), R(context), U8(4),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(8),
+                B(Star), R(12),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(12), U8(1),
+                B(Star), R(11),
+                B(LdaFalse),
+                B(Star), R(12),
+                B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(11), U8(2),
+                B(Star), R(13),
+                B(LdrContextSlot), R(1), U8(5), R(11),
+                B(LdaSmi), U8(1),
+                B(SuspendGenerator), R(11),
+                B(Ldar), R(13),
+  /*   44 S> */ B(Return),
+                B(LdaSmi), U8(-2),
+                B(Star), R(3),
+                B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(11), U8(1),
+                B(Star), R(12),
+                B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(11), U8(1),
+                B(Star), R(14),
+                B(LdaZero),
+                B(TestEqualStrict), R(14),
+                B(JumpIfTrue), U8(45),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(14),
+                B(JumpIfTrue), U8(36),
+                B(Jump), U8(2),
+                B(LdaTrue),
+                B(Star), R(16),
+                B(Mov), R(12), R(15),
+                B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(15), U8(2),
+                B(PopContext), R(2),
+                B(PopContext), R(2),
+                B(PopContext), R(2),
+                B(PopContext), R(2),
+                B(PopContext), R(2),
+                B(PopContext), R(2),
+                B(PopContext), R(2),
+                B(Star), R(8),
+                B(LdaZero),
+                B(Star), R(7),
+                B(Jump), U8(75),
+                B(Ldar), R(12),
+  /*   36 E> */ B(Throw),
+                B(Ldar), R(12),
+                B(PopContext), R(2),
+                B(LdaZero),
+                B(StaContextSlot), R(1), U8(9),
+                B(Wide), B(Jump), U16(-222),
+                B(Jump), U8(46),
+                B(Star), R(12),
+                B(LdaConstant), U8(11),
+                B(Star), R(11),
+                B(Mov), R(closure), R(13),
+                B(CallRuntime), U16(Runtime::kPushCatchContext), R(11), U8(3),
+                B(Star), R(10),
+                B(PushContext), R(2),
+                B(LdrContextSlot), R(1), U8(9), R(11),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(11),
+                B(JumpIfFalse), U8(7),
+                B(LdaSmi), U8(1),
+                B(StaContextSlot), R(1), U8(9),
+                B(LdrContextSlot), R(context), U8(4), R(11),
+                B(CallRuntime), U16(Runtime::kReThrow), R(11), U8(1),
+                B(PopContext), R(2),
+                B(LdaSmi), U8(-1),
+                B(Star), R(7),
+                B(Jump), U8(8),
+                B(Star), R(8),
+                B(LdaSmi), U8(1),
+                B(Star), R(7),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Star), R(9),
+                B(LdrContextSlot), R(1), U8(9), R(10),
+                B(LdaZero),
+                B(TestEqualStrict), R(10),
+                B(JumpIfTrue), U8(9),
+                B(LdrContextSlot), R(1), U8(7), R(10),
+                B(LdaUndefined),
+                B(TestEqualStrict), R(10),
+                B(ToBooleanLogicalNot),
+                B(JumpIfFalseConstant), U8(15),
+                B(LdrContextSlot), R(1), U8(7), R(10),
+                B(LdaNamedProperty), R(10), U8(12), U8(13),
+                B(StaContextSlot), R(1), U8(11),
+                B(LdrContextSlot), R(1), U8(11), R(10),
+                B(LdaNull),
+                B(TestEqual), R(10),
+                B(JumpIfFalse), U8(4),
+                B(Jump), U8(124),
+                B(LdrContextSlot), R(1), U8(9), R(10),
+                B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(10),
+                B(JumpIfFalse), U8(78),
+                B(LdaContextSlot), R(1), U8(11),
+                B(TypeOf),
+                B(Star), R(10),
+                B(LdaConstant), U8(13),
+                B(TestEqualStrict), R(10),
+                B(JumpIfFalse), U8(4),
+                B(Jump), U8(18),
+                B(Wide), B(LdaSmi), U16(128),
+                B(Star), R(10),
+                B(LdaConstant), U8(14),
+                B(Star), R(11),
+                B(CallRuntime), U16(Runtime::kNewTypeError), R(10), U8(2),
+                B(Throw),
+                B(Mov), R(context), R(10),
+                B(LdrContextSlot), R(1), U8(11), R(11),
+                B(LdrContextSlot), R(1), U8(7), R(12),
+                B(InvokeIntrinsic), U8(Runtime::k_Call), R(11), U8(2),
+                B(Jump), U8(29),
+                B(Star), R(12),
+                B(LdaConstant), U8(11),
+                B(Star), R(11),
+                B(Mov), R(closure), R(13),
+                B(CallRuntime), U16(Runtime::kPushCatchContext), R(11), U8(3),
+                B(Star), R(10),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Ldar), R(10),
+                B(PushContext), R(2),
+                B(PopContext), R(2),
+                B(Jump), U8(38),
+                B(LdrContextSlot), R(1), U8(11), R(10),
+                B(LdrContextSlot), R(1), U8(7), R(11),
+                B(InvokeIntrinsic), U8(Runtime::k_Call), R(10), U8(2),
+                B(StaContextSlot), R(1), U8(12),
+                B(LdrContextSlot), R(1), U8(12), R(10),
+                B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(10), U8(1),
+                B(JumpIfToBooleanFalse), U8(4),
+                B(Jump), U8(11),
+                B(LdrContextSlot), R(1), U8(12), R(10),
+                B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(10), U8(1),
+                B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(9), U8(1),
+                B(LdaZero),
+                B(TestEqualStrict), R(7),
+                B(JumpIfTrue), U8(10),
+                B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(7),
+                B(JumpIfTrue), U8(17),
+                B(Jump), U8(28),
+                B(PopContext), R(1),
+                B(PopContext), R(1),
+                B(LdaSmi), U8(1),
+                B(Star), R(4),
+                B(Mov), R(8), R(5),
+                B(Jump), U8(47),
+                B(PopContext), R(1),
+                B(PopContext), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(4),
+                B(Mov), R(8), R(5),
+                B(Jump), U8(34),
+                B(PopContext), R(1),
+                B(LdrUndefined), R(7),
+                B(LdaTrue),
+                B(Star), R(8),
+                B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(7), U8(2),
+                B(Star), R(5),
+                B(LdaSmi), U8(3),
+                B(Star), R(4),
+                B(Jump), U8(14),
+                B(LdaSmi), U8(-1),
+                B(Star), R(4),
+                B(Jump), U8(8),
+                B(Star), R(5),
+                B(LdaSmi), U8(4),
+                B(Star), R(4),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Star), R(6),
+                B(LdrContextSlot), R(context), U8(5), R(7),
+                B(CallRuntime), U16(Runtime::k_GeneratorClose), R(7), U8(1),
+                B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(6), U8(1),
+                B(LdaZero),
+                B(TestEqualStrict), R(4),
+                B(JumpIfTrue), U8(28),
+                B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(4),
+                B(JumpIfTrue), U8(25),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(4),
+                B(JumpIfTrue), U8(22),
+                B(LdaSmi), U8(3),
+                B(TestEqualStrict), R(4),
+                B(JumpIfTrue), U8(19),
+                B(LdaSmi), U8(4),
+                B(TestEqualStrict), R(4),
+                B(JumpIfTrue), U8(16),
+                B(Jump), U8(17),
+                B(Ldar), R(5),
+  /*   44 S> */ B(Return),
+                B(Ldar), R(5),
+  /*   44 S> */ B(Return),
+                B(Ldar), R(5),
+                B(ReThrow),
+                B(Ldar), R(5),
+  /*   44 S> */ B(Return),
+                B(Ldar), R(5),
+                B(ReThrow),
+                B(LdaUndefined),
+  /*   44 S> */ B(Return),
+]
+constant pool: [
+  InstanceType::FIXED_ARRAY_TYPE,
+  InstanceType::FIXED_ARRAY_TYPE,
+  InstanceType::SYMBOL_TYPE,
+  kInstanceTypeDontCare,
+  InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+  InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+  InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+  InstanceType::FIXED_ARRAY_TYPE,
+  InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+  kInstanceTypeDontCare,
+  kInstanceTypeDontCare,
+  InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+  InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+  InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+  InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+  kInstanceTypeDontCare,
+  kInstanceTypeDontCare,
+]
+handlers: [
+  [48, 698, 704],
+  [158, 452, 458],
+  [161, 406, 408],
+  [555, 567, 569],
+]
+
diff --git a/test/cctest/interpreter/bytecode_expectations/GlobalCompoundExpressions.golden b/test/cctest/interpreter/bytecode_expectations/GlobalCompoundExpressions.golden
index 42a2c5b..5c9524d 100644
--- a/test/cctest/interpreter/bytecode_expectations/GlobalCompoundExpressions.golden
+++ b/test/cctest/interpreter/bytecode_expectations/GlobalCompoundExpressions.golden
@@ -16,15 +16,14 @@
 "
 frame size: 1
 parameter count: 1
-bytecode array length: 14
+bytecode array length: 12
 bytecodes: [
-  B(StackCheck),
-  B(LdaGlobal), U8(0), U8(1),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(BitwiseAnd), R(0),
-  B(StaGlobalSloppy), U8(0), U8(3),
-  B(Return),
+  /*   26 E> */ B(StackCheck),
+  /*   31 S> */ B(LdrGlobal), U8(1), R(0),
+                B(LdaSmi), U8(1),
+                B(BitwiseAnd), R(0),
+  /*   45 E> */ B(StaGlobalSloppy), U8(0), U8(3),
+  /*   51 S> */ B(Return),
 ]
 constant pool: [
   "global",
@@ -40,15 +39,14 @@
 "
 frame size: 1
 parameter count: 1
-bytecode array length: 14
+bytecode array length: 12
 bytecodes: [
-  B(StackCheck),
-  B(LdaGlobal), U8(0), U8(1),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(Add), R(0),
-  B(StaGlobalSloppy), U8(0), U8(3),
-  B(Return),
+  /*   27 E> */ B(StackCheck),
+  /*   32 S> */ B(LdrGlobal), U8(1), R(0),
+                B(LdaSmi), U8(1),
+                B(Add), R(0),
+  /*   51 E> */ B(StaGlobalSloppy), U8(0), U8(3),
+  /*   57 S> */ B(Return),
 ]
 constant pool: [
   "unallocated",
diff --git a/test/cctest/interpreter/bytecode_expectations/GlobalCompoundExpressions.golden1 b/test/cctest/interpreter/bytecode_expectations/GlobalCompoundExpressions.golden1
new file mode 100644
index 0000000..b44d37b
--- /dev/null
+++ b/test/cctest/interpreter/bytecode_expectations/GlobalCompoundExpressions.golden1
@@ -0,0 +1,64 @@
+#
+# Autogenerated by generate-bytecode-expectations.
+#
+
+---
+pool type: mixed
+execute: yes
+wrap: yes
+
+---
+snippet: "
+  var global = 1;
+  function f() { return global &= 1; }
+  f();
+"
+frame size: 4
+parameter count: 1
+bytecode array length: 27
+bytecodes: [
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(1),
+                B(CreateClosure), U8(0), U8(0),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   47 S> */ B(LdaSmi), U8(1),
+  /*   47 E> */ B(StaContextSlot), R(context), U8(4),
+  /*   87 S> */ B(LdrUndefined), R(3),
+  /*   87 E> */ B(Call), R(0), R(3), U8(1), U8(1),
+                B(LdaUndefined),
+  /*   92 S> */ B(Return),
+]
+constant pool: [
+  InstanceType::SHARED_FUNCTION_INFO_TYPE,
+]
+handlers: [
+]
+
+---
+snippet: "
+  unallocated = 1;
+  function f() { return unallocated += 1; }
+  f();
+"
+frame size: 3
+parameter count: 1
+bytecode array length: 20
+bytecodes: [
+                B(CreateClosure), U8(0), U8(0),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaSmi), U8(1),
+  /*   46 E> */ B(StaGlobalSloppy), U8(1), U8(1),
+  /*   93 S> */ B(LdrUndefined), R(2),
+  /*   93 E> */ B(Call), R(0), R(2), U8(1), U8(3),
+                B(LdaUndefined),
+  /*   98 S> */ B(Return),
+]
+constant pool: [
+  InstanceType::SHARED_FUNCTION_INFO_TYPE,
+  InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+]
+handlers: [
+]
+
diff --git a/test/cctest/interpreter/bytecode_expectations/GlobalCountOperators.golden b/test/cctest/interpreter/bytecode_expectations/GlobalCountOperators.golden
index 7d64503..ea50000 100644
--- a/test/cctest/interpreter/bytecode_expectations/GlobalCountOperators.golden
+++ b/test/cctest/interpreter/bytecode_expectations/GlobalCountOperators.golden
@@ -16,14 +16,13 @@
 "
 frame size: 0
 parameter count: 1
-bytecode array length: 10
+bytecode array length: 8
 bytecodes: [
-  B(StackCheck),
-  B(LdaGlobal), U8(0), U8(1),
-  B(ToNumber),
-  B(Inc),
-  B(StaGlobalSloppy), U8(0), U8(3),
-  B(Return),
+  /*   26 E> */ B(StackCheck),
+  /*   31 S> */ B(LdaGlobal), U8(1),
+                B(Inc),
+  /*   40 E> */ B(StaGlobalSloppy), U8(0), U8(3),
+  /*   48 S> */ B(Return),
 ]
 constant pool: [
   "global",
@@ -39,16 +38,16 @@
 "
 frame size: 1
 parameter count: 1
-bytecode array length: 14
+bytecode array length: 13
 bytecodes: [
-  B(StackCheck),
-  B(LdaGlobal), U8(0), U8(1),
-  B(ToNumber),
-  B(Star), R(0),
-  B(Dec),
-  B(StaGlobalSloppy), U8(0), U8(3),
-  B(Ldar), R(0),
-  B(Return),
+  /*   26 E> */ B(StackCheck),
+  /*   31 S> */ B(LdaGlobal), U8(1),
+                B(ToNumber),
+                B(Star), R(0),
+                B(Dec),
+  /*   44 E> */ B(StaGlobalSloppy), U8(0), U8(3),
+                B(Ldar), R(0),
+  /*   48 S> */ B(Return),
 ]
 constant pool: [
   "global",
@@ -64,14 +63,13 @@
 "
 frame size: 0
 parameter count: 1
-bytecode array length: 10
+bytecode array length: 8
 bytecodes: [
-  B(StackCheck),
-  B(LdaGlobal), U8(0), U8(1),
-  B(ToNumber),
-  B(Dec),
-  B(StaGlobalStrict), U8(0), U8(3),
-  B(Return),
+  /*   27 E> */ B(StackCheck),
+  /*   46 S> */ B(LdaGlobal), U8(1),
+                B(Dec),
+  /*   55 E> */ B(StaGlobalStrict), U8(0), U8(3),
+  /*   68 S> */ B(Return),
 ]
 constant pool: [
   "unallocated",
@@ -87,16 +85,16 @@
 "
 frame size: 1
 parameter count: 1
-bytecode array length: 14
+bytecode array length: 13
 bytecodes: [
-  B(StackCheck),
-  B(LdaGlobal), U8(0), U8(1),
-  B(ToNumber),
-  B(Star), R(0),
-  B(Inc),
-  B(StaGlobalSloppy), U8(0), U8(3),
-  B(Ldar), R(0),
-  B(Return),
+  /*   27 E> */ B(StackCheck),
+  /*   32 S> */ B(LdaGlobal), U8(1),
+                B(ToNumber),
+                B(Star), R(0),
+                B(Inc),
+  /*   50 E> */ B(StaGlobalSloppy), U8(0), U8(3),
+                B(Ldar), R(0),
+  /*   54 S> */ B(Return),
 ]
 constant pool: [
   "unallocated",
diff --git a/test/cctest/interpreter/bytecode_expectations/GlobalDelete.golden b/test/cctest/interpreter/bytecode_expectations/GlobalDelete.golden
index ffed12e..adead06 100644
--- a/test/cctest/interpreter/bytecode_expectations/GlobalDelete.golden
+++ b/test/cctest/interpreter/bytecode_expectations/GlobalDelete.golden
@@ -18,18 +18,16 @@
 "
 frame size: 1
 parameter count: 1
-bytecode array length: 11
+bytecode array length: 9
 bytecodes: [
-  B(StackCheck),
-  B(LdaGlobal), U8(0), U8(1),
-  B(Star), R(0),
-  B(LdaConstant), U8(1),
-  B(DeletePropertySloppy), R(0),
-  B(Return),
+  /*   32 E> */ B(StackCheck),
+  /*   39 S> */ B(LdrGlobal), U8(1), R(0),
+                B(LdaConstant), U8(0),
+                B(DeletePropertySloppy), R(0),
+  /*   58 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
-  InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
 ]
 handlers: [
 ]
@@ -45,17 +43,15 @@
 "
 frame size: 1
 parameter count: 1
-bytecode array length: 11
+bytecode array length: 9
 bytecodes: [
-  B(StackCheck),
-  B(LdaGlobal), U8(0), U8(1),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(DeletePropertyStrict), R(0),
-  B(Return),
+  /*   28 E> */ B(StackCheck),
+  /*   51 S> */ B(LdrGlobal), U8(1), R(0),
+                B(LdaSmi), U8(1),
+                B(DeletePropertyStrict), R(0),
+  /*   71 S> */ B(Return),
 ]
 constant pool: [
-  InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
 ]
 handlers: [
 ]
@@ -70,16 +66,14 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 16
+bytecode array length: 14
 bytecodes: [
-  B(StackCheck),
-  B(LdaContextSlot), R(context), U8(3),
-  B(Star), R(0),
-  B(LdaContextSlot), R(0), U8(2),
-  B(Star), R(1),
-  B(LdaConstant), U8(0),
-  B(DeletePropertySloppy), R(1),
-  B(Return),
+  /*   32 E> */ B(StackCheck),
+  /*   39 S> */ B(LdrContextSlot), R(context), U8(3), R(0),
+                B(LdrContextSlot), R(0), U8(2), R(1),
+                B(LdaConstant), U8(0),
+                B(DeletePropertySloppy), R(1),
+  /*   56 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
@@ -97,16 +91,14 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 16
+bytecode array length: 14
 bytecodes: [
-  B(StackCheck),
-  B(LdaContextSlot), R(context), U8(3),
-  B(Star), R(0),
-  B(LdaContextSlot), R(0), U8(2),
-  B(Star), R(1),
-  B(LdaConstant), U8(0),
-  B(DeletePropertySloppy), R(1),
-  B(Return),
+  /*   18 E> */ B(StackCheck),
+  /*   25 S> */ B(LdrContextSlot), R(context), U8(3), R(0),
+                B(LdrContextSlot), R(0), U8(2), R(1),
+                B(LdaConstant), U8(0),
+                B(DeletePropertySloppy), R(1),
+  /*   42 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/HeapNumberConstants.golden b/test/cctest/interpreter/bytecode_expectations/HeapNumberConstants.golden
index 2ff2485..f70321a 100644
--- a/test/cctest/interpreter/bytecode_expectations/HeapNumberConstants.golden
+++ b/test/cctest/interpreter/bytecode_expectations/HeapNumberConstants.golden
@@ -15,9 +15,9 @@
 parameter count: 1
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaConstant), U8(0),
+  /*   46 S> */ B(Return),
 ]
 constant pool: [
   1.2,
@@ -33,11 +33,11 @@
 parameter count: 1
 bytecode array length: 8
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(LdaConstant), U8(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   47 S> */ B(LdaConstant), U8(1),
+  /*   59 S> */ B(Return),
 ]
 constant pool: [
   1.2,
@@ -54,11 +54,11 @@
 parameter count: 1
 bytecode array length: 8
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(LdaConstant), U8(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   48 S> */ B(LdaConstant), U8(1),
+  /*   61 S> */ B(Return),
 ]
 constant pool: [
   3.14,
@@ -331,523 +331,523 @@
 parameter count: 1
 bytecode array length: 1033
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(LdaConstant), U8(1),
-  B(Star), R(0),
-  B(LdaConstant), U8(2),
-  B(Star), R(0),
-  B(LdaConstant), U8(3),
-  B(Star), R(0),
-  B(LdaConstant), U8(4),
-  B(Star), R(0),
-  B(LdaConstant), U8(5),
-  B(Star), R(0),
-  B(LdaConstant), U8(6),
-  B(Star), R(0),
-  B(LdaConstant), U8(7),
-  B(Star), R(0),
-  B(LdaConstant), U8(8),
-  B(Star), R(0),
-  B(LdaConstant), U8(9),
-  B(Star), R(0),
-  B(LdaConstant), U8(10),
-  B(Star), R(0),
-  B(LdaConstant), U8(11),
-  B(Star), R(0),
-  B(LdaConstant), U8(12),
-  B(Star), R(0),
-  B(LdaConstant), U8(13),
-  B(Star), R(0),
-  B(LdaConstant), U8(14),
-  B(Star), R(0),
-  B(LdaConstant), U8(15),
-  B(Star), R(0),
-  B(LdaConstant), U8(16),
-  B(Star), R(0),
-  B(LdaConstant), U8(17),
-  B(Star), R(0),
-  B(LdaConstant), U8(18),
-  B(Star), R(0),
-  B(LdaConstant), U8(19),
-  B(Star), R(0),
-  B(LdaConstant), U8(20),
-  B(Star), R(0),
-  B(LdaConstant), U8(21),
-  B(Star), R(0),
-  B(LdaConstant), U8(22),
-  B(Star), R(0),
-  B(LdaConstant), U8(23),
-  B(Star), R(0),
-  B(LdaConstant), U8(24),
-  B(Star), R(0),
-  B(LdaConstant), U8(25),
-  B(Star), R(0),
-  B(LdaConstant), U8(26),
-  B(Star), R(0),
-  B(LdaConstant), U8(27),
-  B(Star), R(0),
-  B(LdaConstant), U8(28),
-  B(Star), R(0),
-  B(LdaConstant), U8(29),
-  B(Star), R(0),
-  B(LdaConstant), U8(30),
-  B(Star), R(0),
-  B(LdaConstant), U8(31),
-  B(Star), R(0),
-  B(LdaConstant), U8(32),
-  B(Star), R(0),
-  B(LdaConstant), U8(33),
-  B(Star), R(0),
-  B(LdaConstant), U8(34),
-  B(Star), R(0),
-  B(LdaConstant), U8(35),
-  B(Star), R(0),
-  B(LdaConstant), U8(36),
-  B(Star), R(0),
-  B(LdaConstant), U8(37),
-  B(Star), R(0),
-  B(LdaConstant), U8(38),
-  B(Star), R(0),
-  B(LdaConstant), U8(39),
-  B(Star), R(0),
-  B(LdaConstant), U8(40),
-  B(Star), R(0),
-  B(LdaConstant), U8(41),
-  B(Star), R(0),
-  B(LdaConstant), U8(42),
-  B(Star), R(0),
-  B(LdaConstant), U8(43),
-  B(Star), R(0),
-  B(LdaConstant), U8(44),
-  B(Star), R(0),
-  B(LdaConstant), U8(45),
-  B(Star), R(0),
-  B(LdaConstant), U8(46),
-  B(Star), R(0),
-  B(LdaConstant), U8(47),
-  B(Star), R(0),
-  B(LdaConstant), U8(48),
-  B(Star), R(0),
-  B(LdaConstant), U8(49),
-  B(Star), R(0),
-  B(LdaConstant), U8(50),
-  B(Star), R(0),
-  B(LdaConstant), U8(51),
-  B(Star), R(0),
-  B(LdaConstant), U8(52),
-  B(Star), R(0),
-  B(LdaConstant), U8(53),
-  B(Star), R(0),
-  B(LdaConstant), U8(54),
-  B(Star), R(0),
-  B(LdaConstant), U8(55),
-  B(Star), R(0),
-  B(LdaConstant), U8(56),
-  B(Star), R(0),
-  B(LdaConstant), U8(57),
-  B(Star), R(0),
-  B(LdaConstant), U8(58),
-  B(Star), R(0),
-  B(LdaConstant), U8(59),
-  B(Star), R(0),
-  B(LdaConstant), U8(60),
-  B(Star), R(0),
-  B(LdaConstant), U8(61),
-  B(Star), R(0),
-  B(LdaConstant), U8(62),
-  B(Star), R(0),
-  B(LdaConstant), U8(63),
-  B(Star), R(0),
-  B(LdaConstant), U8(64),
-  B(Star), R(0),
-  B(LdaConstant), U8(65),
-  B(Star), R(0),
-  B(LdaConstant), U8(66),
-  B(Star), R(0),
-  B(LdaConstant), U8(67),
-  B(Star), R(0),
-  B(LdaConstant), U8(68),
-  B(Star), R(0),
-  B(LdaConstant), U8(69),
-  B(Star), R(0),
-  B(LdaConstant), U8(70),
-  B(Star), R(0),
-  B(LdaConstant), U8(71),
-  B(Star), R(0),
-  B(LdaConstant), U8(72),
-  B(Star), R(0),
-  B(LdaConstant), U8(73),
-  B(Star), R(0),
-  B(LdaConstant), U8(74),
-  B(Star), R(0),
-  B(LdaConstant), U8(75),
-  B(Star), R(0),
-  B(LdaConstant), U8(76),
-  B(Star), R(0),
-  B(LdaConstant), U8(77),
-  B(Star), R(0),
-  B(LdaConstant), U8(78),
-  B(Star), R(0),
-  B(LdaConstant), U8(79),
-  B(Star), R(0),
-  B(LdaConstant), U8(80),
-  B(Star), R(0),
-  B(LdaConstant), U8(81),
-  B(Star), R(0),
-  B(LdaConstant), U8(82),
-  B(Star), R(0),
-  B(LdaConstant), U8(83),
-  B(Star), R(0),
-  B(LdaConstant), U8(84),
-  B(Star), R(0),
-  B(LdaConstant), U8(85),
-  B(Star), R(0),
-  B(LdaConstant), U8(86),
-  B(Star), R(0),
-  B(LdaConstant), U8(87),
-  B(Star), R(0),
-  B(LdaConstant), U8(88),
-  B(Star), R(0),
-  B(LdaConstant), U8(89),
-  B(Star), R(0),
-  B(LdaConstant), U8(90),
-  B(Star), R(0),
-  B(LdaConstant), U8(91),
-  B(Star), R(0),
-  B(LdaConstant), U8(92),
-  B(Star), R(0),
-  B(LdaConstant), U8(93),
-  B(Star), R(0),
-  B(LdaConstant), U8(94),
-  B(Star), R(0),
-  B(LdaConstant), U8(95),
-  B(Star), R(0),
-  B(LdaConstant), U8(96),
-  B(Star), R(0),
-  B(LdaConstant), U8(97),
-  B(Star), R(0),
-  B(LdaConstant), U8(98),
-  B(Star), R(0),
-  B(LdaConstant), U8(99),
-  B(Star), R(0),
-  B(LdaConstant), U8(100),
-  B(Star), R(0),
-  B(LdaConstant), U8(101),
-  B(Star), R(0),
-  B(LdaConstant), U8(102),
-  B(Star), R(0),
-  B(LdaConstant), U8(103),
-  B(Star), R(0),
-  B(LdaConstant), U8(104),
-  B(Star), R(0),
-  B(LdaConstant), U8(105),
-  B(Star), R(0),
-  B(LdaConstant), U8(106),
-  B(Star), R(0),
-  B(LdaConstant), U8(107),
-  B(Star), R(0),
-  B(LdaConstant), U8(108),
-  B(Star), R(0),
-  B(LdaConstant), U8(109),
-  B(Star), R(0),
-  B(LdaConstant), U8(110),
-  B(Star), R(0),
-  B(LdaConstant), U8(111),
-  B(Star), R(0),
-  B(LdaConstant), U8(112),
-  B(Star), R(0),
-  B(LdaConstant), U8(113),
-  B(Star), R(0),
-  B(LdaConstant), U8(114),
-  B(Star), R(0),
-  B(LdaConstant), U8(115),
-  B(Star), R(0),
-  B(LdaConstant), U8(116),
-  B(Star), R(0),
-  B(LdaConstant), U8(117),
-  B(Star), R(0),
-  B(LdaConstant), U8(118),
-  B(Star), R(0),
-  B(LdaConstant), U8(119),
-  B(Star), R(0),
-  B(LdaConstant), U8(120),
-  B(Star), R(0),
-  B(LdaConstant), U8(121),
-  B(Star), R(0),
-  B(LdaConstant), U8(122),
-  B(Star), R(0),
-  B(LdaConstant), U8(123),
-  B(Star), R(0),
-  B(LdaConstant), U8(124),
-  B(Star), R(0),
-  B(LdaConstant), U8(125),
-  B(Star), R(0),
-  B(LdaConstant), U8(126),
-  B(Star), R(0),
-  B(LdaConstant), U8(127),
-  B(Star), R(0),
-  B(LdaConstant), U8(128),
-  B(Star), R(0),
-  B(LdaConstant), U8(129),
-  B(Star), R(0),
-  B(LdaConstant), U8(130),
-  B(Star), R(0),
-  B(LdaConstant), U8(131),
-  B(Star), R(0),
-  B(LdaConstant), U8(132),
-  B(Star), R(0),
-  B(LdaConstant), U8(133),
-  B(Star), R(0),
-  B(LdaConstant), U8(134),
-  B(Star), R(0),
-  B(LdaConstant), U8(135),
-  B(Star), R(0),
-  B(LdaConstant), U8(136),
-  B(Star), R(0),
-  B(LdaConstant), U8(137),
-  B(Star), R(0),
-  B(LdaConstant), U8(138),
-  B(Star), R(0),
-  B(LdaConstant), U8(139),
-  B(Star), R(0),
-  B(LdaConstant), U8(140),
-  B(Star), R(0),
-  B(LdaConstant), U8(141),
-  B(Star), R(0),
-  B(LdaConstant), U8(142),
-  B(Star), R(0),
-  B(LdaConstant), U8(143),
-  B(Star), R(0),
-  B(LdaConstant), U8(144),
-  B(Star), R(0),
-  B(LdaConstant), U8(145),
-  B(Star), R(0),
-  B(LdaConstant), U8(146),
-  B(Star), R(0),
-  B(LdaConstant), U8(147),
-  B(Star), R(0),
-  B(LdaConstant), U8(148),
-  B(Star), R(0),
-  B(LdaConstant), U8(149),
-  B(Star), R(0),
-  B(LdaConstant), U8(150),
-  B(Star), R(0),
-  B(LdaConstant), U8(151),
-  B(Star), R(0),
-  B(LdaConstant), U8(152),
-  B(Star), R(0),
-  B(LdaConstant), U8(153),
-  B(Star), R(0),
-  B(LdaConstant), U8(154),
-  B(Star), R(0),
-  B(LdaConstant), U8(155),
-  B(Star), R(0),
-  B(LdaConstant), U8(156),
-  B(Star), R(0),
-  B(LdaConstant), U8(157),
-  B(Star), R(0),
-  B(LdaConstant), U8(158),
-  B(Star), R(0),
-  B(LdaConstant), U8(159),
-  B(Star), R(0),
-  B(LdaConstant), U8(160),
-  B(Star), R(0),
-  B(LdaConstant), U8(161),
-  B(Star), R(0),
-  B(LdaConstant), U8(162),
-  B(Star), R(0),
-  B(LdaConstant), U8(163),
-  B(Star), R(0),
-  B(LdaConstant), U8(164),
-  B(Star), R(0),
-  B(LdaConstant), U8(165),
-  B(Star), R(0),
-  B(LdaConstant), U8(166),
-  B(Star), R(0),
-  B(LdaConstant), U8(167),
-  B(Star), R(0),
-  B(LdaConstant), U8(168),
-  B(Star), R(0),
-  B(LdaConstant), U8(169),
-  B(Star), R(0),
-  B(LdaConstant), U8(170),
-  B(Star), R(0),
-  B(LdaConstant), U8(171),
-  B(Star), R(0),
-  B(LdaConstant), U8(172),
-  B(Star), R(0),
-  B(LdaConstant), U8(173),
-  B(Star), R(0),
-  B(LdaConstant), U8(174),
-  B(Star), R(0),
-  B(LdaConstant), U8(175),
-  B(Star), R(0),
-  B(LdaConstant), U8(176),
-  B(Star), R(0),
-  B(LdaConstant), U8(177),
-  B(Star), R(0),
-  B(LdaConstant), U8(178),
-  B(Star), R(0),
-  B(LdaConstant), U8(179),
-  B(Star), R(0),
-  B(LdaConstant), U8(180),
-  B(Star), R(0),
-  B(LdaConstant), U8(181),
-  B(Star), R(0),
-  B(LdaConstant), U8(182),
-  B(Star), R(0),
-  B(LdaConstant), U8(183),
-  B(Star), R(0),
-  B(LdaConstant), U8(184),
-  B(Star), R(0),
-  B(LdaConstant), U8(185),
-  B(Star), R(0),
-  B(LdaConstant), U8(186),
-  B(Star), R(0),
-  B(LdaConstant), U8(187),
-  B(Star), R(0),
-  B(LdaConstant), U8(188),
-  B(Star), R(0),
-  B(LdaConstant), U8(189),
-  B(Star), R(0),
-  B(LdaConstant), U8(190),
-  B(Star), R(0),
-  B(LdaConstant), U8(191),
-  B(Star), R(0),
-  B(LdaConstant), U8(192),
-  B(Star), R(0),
-  B(LdaConstant), U8(193),
-  B(Star), R(0),
-  B(LdaConstant), U8(194),
-  B(Star), R(0),
-  B(LdaConstant), U8(195),
-  B(Star), R(0),
-  B(LdaConstant), U8(196),
-  B(Star), R(0),
-  B(LdaConstant), U8(197),
-  B(Star), R(0),
-  B(LdaConstant), U8(198),
-  B(Star), R(0),
-  B(LdaConstant), U8(199),
-  B(Star), R(0),
-  B(LdaConstant), U8(200),
-  B(Star), R(0),
-  B(LdaConstant), U8(201),
-  B(Star), R(0),
-  B(LdaConstant), U8(202),
-  B(Star), R(0),
-  B(LdaConstant), U8(203),
-  B(Star), R(0),
-  B(LdaConstant), U8(204),
-  B(Star), R(0),
-  B(LdaConstant), U8(205),
-  B(Star), R(0),
-  B(LdaConstant), U8(206),
-  B(Star), R(0),
-  B(LdaConstant), U8(207),
-  B(Star), R(0),
-  B(LdaConstant), U8(208),
-  B(Star), R(0),
-  B(LdaConstant), U8(209),
-  B(Star), R(0),
-  B(LdaConstant), U8(210),
-  B(Star), R(0),
-  B(LdaConstant), U8(211),
-  B(Star), R(0),
-  B(LdaConstant), U8(212),
-  B(Star), R(0),
-  B(LdaConstant), U8(213),
-  B(Star), R(0),
-  B(LdaConstant), U8(214),
-  B(Star), R(0),
-  B(LdaConstant), U8(215),
-  B(Star), R(0),
-  B(LdaConstant), U8(216),
-  B(Star), R(0),
-  B(LdaConstant), U8(217),
-  B(Star), R(0),
-  B(LdaConstant), U8(218),
-  B(Star), R(0),
-  B(LdaConstant), U8(219),
-  B(Star), R(0),
-  B(LdaConstant), U8(220),
-  B(Star), R(0),
-  B(LdaConstant), U8(221),
-  B(Star), R(0),
-  B(LdaConstant), U8(222),
-  B(Star), R(0),
-  B(LdaConstant), U8(223),
-  B(Star), R(0),
-  B(LdaConstant), U8(224),
-  B(Star), R(0),
-  B(LdaConstant), U8(225),
-  B(Star), R(0),
-  B(LdaConstant), U8(226),
-  B(Star), R(0),
-  B(LdaConstant), U8(227),
-  B(Star), R(0),
-  B(LdaConstant), U8(228),
-  B(Star), R(0),
-  B(LdaConstant), U8(229),
-  B(Star), R(0),
-  B(LdaConstant), U8(230),
-  B(Star), R(0),
-  B(LdaConstant), U8(231),
-  B(Star), R(0),
-  B(LdaConstant), U8(232),
-  B(Star), R(0),
-  B(LdaConstant), U8(233),
-  B(Star), R(0),
-  B(LdaConstant), U8(234),
-  B(Star), R(0),
-  B(LdaConstant), U8(235),
-  B(Star), R(0),
-  B(LdaConstant), U8(236),
-  B(Star), R(0),
-  B(LdaConstant), U8(237),
-  B(Star), R(0),
-  B(LdaConstant), U8(238),
-  B(Star), R(0),
-  B(LdaConstant), U8(239),
-  B(Star), R(0),
-  B(LdaConstant), U8(240),
-  B(Star), R(0),
-  B(LdaConstant), U8(241),
-  B(Star), R(0),
-  B(LdaConstant), U8(242),
-  B(Star), R(0),
-  B(LdaConstant), U8(243),
-  B(Star), R(0),
-  B(LdaConstant), U8(244),
-  B(Star), R(0),
-  B(LdaConstant), U8(245),
-  B(Star), R(0),
-  B(LdaConstant), U8(246),
-  B(Star), R(0),
-  B(LdaConstant), U8(247),
-  B(Star), R(0),
-  B(LdaConstant), U8(248),
-  B(Star), R(0),
-  B(LdaConstant), U8(249),
-  B(Star), R(0),
-  B(LdaConstant), U8(250),
-  B(Star), R(0),
-  B(LdaConstant), U8(251),
-  B(Star), R(0),
-  B(LdaConstant), U8(252),
-  B(Star), R(0),
-  B(LdaConstant), U8(253),
-  B(Star), R(0),
-  B(LdaConstant), U8(254),
-  B(Star), R(0),
-  B(LdaConstant), U8(255),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(256),
-  B(Star), R(0),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   41 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   52 S> */ B(LdaConstant), U8(1),
+                B(Star), R(0),
+  /*   63 S> */ B(LdaConstant), U8(2),
+                B(Star), R(0),
+  /*   74 S> */ B(LdaConstant), U8(3),
+                B(Star), R(0),
+  /*   85 S> */ B(LdaConstant), U8(4),
+                B(Star), R(0),
+  /*   96 S> */ B(LdaConstant), U8(5),
+                B(Star), R(0),
+  /*  107 S> */ B(LdaConstant), U8(6),
+                B(Star), R(0),
+  /*  118 S> */ B(LdaConstant), U8(7),
+                B(Star), R(0),
+  /*  129 S> */ B(LdaConstant), U8(8),
+                B(Star), R(0),
+  /*  140 S> */ B(LdaConstant), U8(9),
+                B(Star), R(0),
+  /*  151 S> */ B(LdaConstant), U8(10),
+                B(Star), R(0),
+  /*  162 S> */ B(LdaConstant), U8(11),
+                B(Star), R(0),
+  /*  173 S> */ B(LdaConstant), U8(12),
+                B(Star), R(0),
+  /*  184 S> */ B(LdaConstant), U8(13),
+                B(Star), R(0),
+  /*  195 S> */ B(LdaConstant), U8(14),
+                B(Star), R(0),
+  /*  206 S> */ B(LdaConstant), U8(15),
+                B(Star), R(0),
+  /*  217 S> */ B(LdaConstant), U8(16),
+                B(Star), R(0),
+  /*  228 S> */ B(LdaConstant), U8(17),
+                B(Star), R(0),
+  /*  239 S> */ B(LdaConstant), U8(18),
+                B(Star), R(0),
+  /*  250 S> */ B(LdaConstant), U8(19),
+                B(Star), R(0),
+  /*  261 S> */ B(LdaConstant), U8(20),
+                B(Star), R(0),
+  /*  272 S> */ B(LdaConstant), U8(21),
+                B(Star), R(0),
+  /*  283 S> */ B(LdaConstant), U8(22),
+                B(Star), R(0),
+  /*  294 S> */ B(LdaConstant), U8(23),
+                B(Star), R(0),
+  /*  305 S> */ B(LdaConstant), U8(24),
+                B(Star), R(0),
+  /*  316 S> */ B(LdaConstant), U8(25),
+                B(Star), R(0),
+  /*  327 S> */ B(LdaConstant), U8(26),
+                B(Star), R(0),
+  /*  338 S> */ B(LdaConstant), U8(27),
+                B(Star), R(0),
+  /*  349 S> */ B(LdaConstant), U8(28),
+                B(Star), R(0),
+  /*  360 S> */ B(LdaConstant), U8(29),
+                B(Star), R(0),
+  /*  371 S> */ B(LdaConstant), U8(30),
+                B(Star), R(0),
+  /*  382 S> */ B(LdaConstant), U8(31),
+                B(Star), R(0),
+  /*  393 S> */ B(LdaConstant), U8(32),
+                B(Star), R(0),
+  /*  404 S> */ B(LdaConstant), U8(33),
+                B(Star), R(0),
+  /*  415 S> */ B(LdaConstant), U8(34),
+                B(Star), R(0),
+  /*  426 S> */ B(LdaConstant), U8(35),
+                B(Star), R(0),
+  /*  437 S> */ B(LdaConstant), U8(36),
+                B(Star), R(0),
+  /*  448 S> */ B(LdaConstant), U8(37),
+                B(Star), R(0),
+  /*  459 S> */ B(LdaConstant), U8(38),
+                B(Star), R(0),
+  /*  470 S> */ B(LdaConstant), U8(39),
+                B(Star), R(0),
+  /*  481 S> */ B(LdaConstant), U8(40),
+                B(Star), R(0),
+  /*  492 S> */ B(LdaConstant), U8(41),
+                B(Star), R(0),
+  /*  503 S> */ B(LdaConstant), U8(42),
+                B(Star), R(0),
+  /*  514 S> */ B(LdaConstant), U8(43),
+                B(Star), R(0),
+  /*  525 S> */ B(LdaConstant), U8(44),
+                B(Star), R(0),
+  /*  536 S> */ B(LdaConstant), U8(45),
+                B(Star), R(0),
+  /*  547 S> */ B(LdaConstant), U8(46),
+                B(Star), R(0),
+  /*  558 S> */ B(LdaConstant), U8(47),
+                B(Star), R(0),
+  /*  569 S> */ B(LdaConstant), U8(48),
+                B(Star), R(0),
+  /*  580 S> */ B(LdaConstant), U8(49),
+                B(Star), R(0),
+  /*  591 S> */ B(LdaConstant), U8(50),
+                B(Star), R(0),
+  /*  602 S> */ B(LdaConstant), U8(51),
+                B(Star), R(0),
+  /*  613 S> */ B(LdaConstant), U8(52),
+                B(Star), R(0),
+  /*  624 S> */ B(LdaConstant), U8(53),
+                B(Star), R(0),
+  /*  635 S> */ B(LdaConstant), U8(54),
+                B(Star), R(0),
+  /*  646 S> */ B(LdaConstant), U8(55),
+                B(Star), R(0),
+  /*  657 S> */ B(LdaConstant), U8(56),
+                B(Star), R(0),
+  /*  668 S> */ B(LdaConstant), U8(57),
+                B(Star), R(0),
+  /*  679 S> */ B(LdaConstant), U8(58),
+                B(Star), R(0),
+  /*  690 S> */ B(LdaConstant), U8(59),
+                B(Star), R(0),
+  /*  701 S> */ B(LdaConstant), U8(60),
+                B(Star), R(0),
+  /*  712 S> */ B(LdaConstant), U8(61),
+                B(Star), R(0),
+  /*  723 S> */ B(LdaConstant), U8(62),
+                B(Star), R(0),
+  /*  734 S> */ B(LdaConstant), U8(63),
+                B(Star), R(0),
+  /*  745 S> */ B(LdaConstant), U8(64),
+                B(Star), R(0),
+  /*  756 S> */ B(LdaConstant), U8(65),
+                B(Star), R(0),
+  /*  767 S> */ B(LdaConstant), U8(66),
+                B(Star), R(0),
+  /*  778 S> */ B(LdaConstant), U8(67),
+                B(Star), R(0),
+  /*  789 S> */ B(LdaConstant), U8(68),
+                B(Star), R(0),
+  /*  800 S> */ B(LdaConstant), U8(69),
+                B(Star), R(0),
+  /*  811 S> */ B(LdaConstant), U8(70),
+                B(Star), R(0),
+  /*  822 S> */ B(LdaConstant), U8(71),
+                B(Star), R(0),
+  /*  833 S> */ B(LdaConstant), U8(72),
+                B(Star), R(0),
+  /*  844 S> */ B(LdaConstant), U8(73),
+                B(Star), R(0),
+  /*  855 S> */ B(LdaConstant), U8(74),
+                B(Star), R(0),
+  /*  866 S> */ B(LdaConstant), U8(75),
+                B(Star), R(0),
+  /*  877 S> */ B(LdaConstant), U8(76),
+                B(Star), R(0),
+  /*  888 S> */ B(LdaConstant), U8(77),
+                B(Star), R(0),
+  /*  899 S> */ B(LdaConstant), U8(78),
+                B(Star), R(0),
+  /*  910 S> */ B(LdaConstant), U8(79),
+                B(Star), R(0),
+  /*  921 S> */ B(LdaConstant), U8(80),
+                B(Star), R(0),
+  /*  932 S> */ B(LdaConstant), U8(81),
+                B(Star), R(0),
+  /*  943 S> */ B(LdaConstant), U8(82),
+                B(Star), R(0),
+  /*  954 S> */ B(LdaConstant), U8(83),
+                B(Star), R(0),
+  /*  965 S> */ B(LdaConstant), U8(84),
+                B(Star), R(0),
+  /*  976 S> */ B(LdaConstant), U8(85),
+                B(Star), R(0),
+  /*  987 S> */ B(LdaConstant), U8(86),
+                B(Star), R(0),
+  /*  998 S> */ B(LdaConstant), U8(87),
+                B(Star), R(0),
+  /* 1009 S> */ B(LdaConstant), U8(88),
+                B(Star), R(0),
+  /* 1020 S> */ B(LdaConstant), U8(89),
+                B(Star), R(0),
+  /* 1031 S> */ B(LdaConstant), U8(90),
+                B(Star), R(0),
+  /* 1042 S> */ B(LdaConstant), U8(91),
+                B(Star), R(0),
+  /* 1053 S> */ B(LdaConstant), U8(92),
+                B(Star), R(0),
+  /* 1064 S> */ B(LdaConstant), U8(93),
+                B(Star), R(0),
+  /* 1075 S> */ B(LdaConstant), U8(94),
+                B(Star), R(0),
+  /* 1086 S> */ B(LdaConstant), U8(95),
+                B(Star), R(0),
+  /* 1097 S> */ B(LdaConstant), U8(96),
+                B(Star), R(0),
+  /* 1108 S> */ B(LdaConstant), U8(97),
+                B(Star), R(0),
+  /* 1119 S> */ B(LdaConstant), U8(98),
+                B(Star), R(0),
+  /* 1130 S> */ B(LdaConstant), U8(99),
+                B(Star), R(0),
+  /* 1141 S> */ B(LdaConstant), U8(100),
+                B(Star), R(0),
+  /* 1152 S> */ B(LdaConstant), U8(101),
+                B(Star), R(0),
+  /* 1163 S> */ B(LdaConstant), U8(102),
+                B(Star), R(0),
+  /* 1174 S> */ B(LdaConstant), U8(103),
+                B(Star), R(0),
+  /* 1185 S> */ B(LdaConstant), U8(104),
+                B(Star), R(0),
+  /* 1196 S> */ B(LdaConstant), U8(105),
+                B(Star), R(0),
+  /* 1207 S> */ B(LdaConstant), U8(106),
+                B(Star), R(0),
+  /* 1218 S> */ B(LdaConstant), U8(107),
+                B(Star), R(0),
+  /* 1229 S> */ B(LdaConstant), U8(108),
+                B(Star), R(0),
+  /* 1240 S> */ B(LdaConstant), U8(109),
+                B(Star), R(0),
+  /* 1251 S> */ B(LdaConstant), U8(110),
+                B(Star), R(0),
+  /* 1262 S> */ B(LdaConstant), U8(111),
+                B(Star), R(0),
+  /* 1273 S> */ B(LdaConstant), U8(112),
+                B(Star), R(0),
+  /* 1284 S> */ B(LdaConstant), U8(113),
+                B(Star), R(0),
+  /* 1295 S> */ B(LdaConstant), U8(114),
+                B(Star), R(0),
+  /* 1306 S> */ B(LdaConstant), U8(115),
+                B(Star), R(0),
+  /* 1317 S> */ B(LdaConstant), U8(116),
+                B(Star), R(0),
+  /* 1328 S> */ B(LdaConstant), U8(117),
+                B(Star), R(0),
+  /* 1339 S> */ B(LdaConstant), U8(118),
+                B(Star), R(0),
+  /* 1350 S> */ B(LdaConstant), U8(119),
+                B(Star), R(0),
+  /* 1361 S> */ B(LdaConstant), U8(120),
+                B(Star), R(0),
+  /* 1372 S> */ B(LdaConstant), U8(121),
+                B(Star), R(0),
+  /* 1383 S> */ B(LdaConstant), U8(122),
+                B(Star), R(0),
+  /* 1394 S> */ B(LdaConstant), U8(123),
+                B(Star), R(0),
+  /* 1405 S> */ B(LdaConstant), U8(124),
+                B(Star), R(0),
+  /* 1416 S> */ B(LdaConstant), U8(125),
+                B(Star), R(0),
+  /* 1427 S> */ B(LdaConstant), U8(126),
+                B(Star), R(0),
+  /* 1438 S> */ B(LdaConstant), U8(127),
+                B(Star), R(0),
+  /* 1449 S> */ B(LdaConstant), U8(128),
+                B(Star), R(0),
+  /* 1460 S> */ B(LdaConstant), U8(129),
+                B(Star), R(0),
+  /* 1471 S> */ B(LdaConstant), U8(130),
+                B(Star), R(0),
+  /* 1482 S> */ B(LdaConstant), U8(131),
+                B(Star), R(0),
+  /* 1493 S> */ B(LdaConstant), U8(132),
+                B(Star), R(0),
+  /* 1504 S> */ B(LdaConstant), U8(133),
+                B(Star), R(0),
+  /* 1515 S> */ B(LdaConstant), U8(134),
+                B(Star), R(0),
+  /* 1526 S> */ B(LdaConstant), U8(135),
+                B(Star), R(0),
+  /* 1537 S> */ B(LdaConstant), U8(136),
+                B(Star), R(0),
+  /* 1548 S> */ B(LdaConstant), U8(137),
+                B(Star), R(0),
+  /* 1559 S> */ B(LdaConstant), U8(138),
+                B(Star), R(0),
+  /* 1570 S> */ B(LdaConstant), U8(139),
+                B(Star), R(0),
+  /* 1581 S> */ B(LdaConstant), U8(140),
+                B(Star), R(0),
+  /* 1592 S> */ B(LdaConstant), U8(141),
+                B(Star), R(0),
+  /* 1603 S> */ B(LdaConstant), U8(142),
+                B(Star), R(0),
+  /* 1614 S> */ B(LdaConstant), U8(143),
+                B(Star), R(0),
+  /* 1625 S> */ B(LdaConstant), U8(144),
+                B(Star), R(0),
+  /* 1636 S> */ B(LdaConstant), U8(145),
+                B(Star), R(0),
+  /* 1647 S> */ B(LdaConstant), U8(146),
+                B(Star), R(0),
+  /* 1658 S> */ B(LdaConstant), U8(147),
+                B(Star), R(0),
+  /* 1669 S> */ B(LdaConstant), U8(148),
+                B(Star), R(0),
+  /* 1680 S> */ B(LdaConstant), U8(149),
+                B(Star), R(0),
+  /* 1691 S> */ B(LdaConstant), U8(150),
+                B(Star), R(0),
+  /* 1702 S> */ B(LdaConstant), U8(151),
+                B(Star), R(0),
+  /* 1713 S> */ B(LdaConstant), U8(152),
+                B(Star), R(0),
+  /* 1724 S> */ B(LdaConstant), U8(153),
+                B(Star), R(0),
+  /* 1735 S> */ B(LdaConstant), U8(154),
+                B(Star), R(0),
+  /* 1746 S> */ B(LdaConstant), U8(155),
+                B(Star), R(0),
+  /* 1757 S> */ B(LdaConstant), U8(156),
+                B(Star), R(0),
+  /* 1768 S> */ B(LdaConstant), U8(157),
+                B(Star), R(0),
+  /* 1779 S> */ B(LdaConstant), U8(158),
+                B(Star), R(0),
+  /* 1790 S> */ B(LdaConstant), U8(159),
+                B(Star), R(0),
+  /* 1801 S> */ B(LdaConstant), U8(160),
+                B(Star), R(0),
+  /* 1812 S> */ B(LdaConstant), U8(161),
+                B(Star), R(0),
+  /* 1823 S> */ B(LdaConstant), U8(162),
+                B(Star), R(0),
+  /* 1834 S> */ B(LdaConstant), U8(163),
+                B(Star), R(0),
+  /* 1845 S> */ B(LdaConstant), U8(164),
+                B(Star), R(0),
+  /* 1856 S> */ B(LdaConstant), U8(165),
+                B(Star), R(0),
+  /* 1867 S> */ B(LdaConstant), U8(166),
+                B(Star), R(0),
+  /* 1878 S> */ B(LdaConstant), U8(167),
+                B(Star), R(0),
+  /* 1889 S> */ B(LdaConstant), U8(168),
+                B(Star), R(0),
+  /* 1900 S> */ B(LdaConstant), U8(169),
+                B(Star), R(0),
+  /* 1911 S> */ B(LdaConstant), U8(170),
+                B(Star), R(0),
+  /* 1922 S> */ B(LdaConstant), U8(171),
+                B(Star), R(0),
+  /* 1933 S> */ B(LdaConstant), U8(172),
+                B(Star), R(0),
+  /* 1944 S> */ B(LdaConstant), U8(173),
+                B(Star), R(0),
+  /* 1955 S> */ B(LdaConstant), U8(174),
+                B(Star), R(0),
+  /* 1966 S> */ B(LdaConstant), U8(175),
+                B(Star), R(0),
+  /* 1977 S> */ B(LdaConstant), U8(176),
+                B(Star), R(0),
+  /* 1988 S> */ B(LdaConstant), U8(177),
+                B(Star), R(0),
+  /* 1999 S> */ B(LdaConstant), U8(178),
+                B(Star), R(0),
+  /* 2010 S> */ B(LdaConstant), U8(179),
+                B(Star), R(0),
+  /* 2021 S> */ B(LdaConstant), U8(180),
+                B(Star), R(0),
+  /* 2032 S> */ B(LdaConstant), U8(181),
+                B(Star), R(0),
+  /* 2043 S> */ B(LdaConstant), U8(182),
+                B(Star), R(0),
+  /* 2054 S> */ B(LdaConstant), U8(183),
+                B(Star), R(0),
+  /* 2065 S> */ B(LdaConstant), U8(184),
+                B(Star), R(0),
+  /* 2076 S> */ B(LdaConstant), U8(185),
+                B(Star), R(0),
+  /* 2087 S> */ B(LdaConstant), U8(186),
+                B(Star), R(0),
+  /* 2098 S> */ B(LdaConstant), U8(187),
+                B(Star), R(0),
+  /* 2109 S> */ B(LdaConstant), U8(188),
+                B(Star), R(0),
+  /* 2120 S> */ B(LdaConstant), U8(189),
+                B(Star), R(0),
+  /* 2131 S> */ B(LdaConstant), U8(190),
+                B(Star), R(0),
+  /* 2142 S> */ B(LdaConstant), U8(191),
+                B(Star), R(0),
+  /* 2153 S> */ B(LdaConstant), U8(192),
+                B(Star), R(0),
+  /* 2164 S> */ B(LdaConstant), U8(193),
+                B(Star), R(0),
+  /* 2175 S> */ B(LdaConstant), U8(194),
+                B(Star), R(0),
+  /* 2186 S> */ B(LdaConstant), U8(195),
+                B(Star), R(0),
+  /* 2197 S> */ B(LdaConstant), U8(196),
+                B(Star), R(0),
+  /* 2208 S> */ B(LdaConstant), U8(197),
+                B(Star), R(0),
+  /* 2219 S> */ B(LdaConstant), U8(198),
+                B(Star), R(0),
+  /* 2230 S> */ B(LdaConstant), U8(199),
+                B(Star), R(0),
+  /* 2241 S> */ B(LdaConstant), U8(200),
+                B(Star), R(0),
+  /* 2252 S> */ B(LdaConstant), U8(201),
+                B(Star), R(0),
+  /* 2263 S> */ B(LdaConstant), U8(202),
+                B(Star), R(0),
+  /* 2274 S> */ B(LdaConstant), U8(203),
+                B(Star), R(0),
+  /* 2285 S> */ B(LdaConstant), U8(204),
+                B(Star), R(0),
+  /* 2296 S> */ B(LdaConstant), U8(205),
+                B(Star), R(0),
+  /* 2307 S> */ B(LdaConstant), U8(206),
+                B(Star), R(0),
+  /* 2318 S> */ B(LdaConstant), U8(207),
+                B(Star), R(0),
+  /* 2329 S> */ B(LdaConstant), U8(208),
+                B(Star), R(0),
+  /* 2340 S> */ B(LdaConstant), U8(209),
+                B(Star), R(0),
+  /* 2351 S> */ B(LdaConstant), U8(210),
+                B(Star), R(0),
+  /* 2362 S> */ B(LdaConstant), U8(211),
+                B(Star), R(0),
+  /* 2373 S> */ B(LdaConstant), U8(212),
+                B(Star), R(0),
+  /* 2384 S> */ B(LdaConstant), U8(213),
+                B(Star), R(0),
+  /* 2395 S> */ B(LdaConstant), U8(214),
+                B(Star), R(0),
+  /* 2406 S> */ B(LdaConstant), U8(215),
+                B(Star), R(0),
+  /* 2417 S> */ B(LdaConstant), U8(216),
+                B(Star), R(0),
+  /* 2428 S> */ B(LdaConstant), U8(217),
+                B(Star), R(0),
+  /* 2439 S> */ B(LdaConstant), U8(218),
+                B(Star), R(0),
+  /* 2450 S> */ B(LdaConstant), U8(219),
+                B(Star), R(0),
+  /* 2461 S> */ B(LdaConstant), U8(220),
+                B(Star), R(0),
+  /* 2472 S> */ B(LdaConstant), U8(221),
+                B(Star), R(0),
+  /* 2483 S> */ B(LdaConstant), U8(222),
+                B(Star), R(0),
+  /* 2494 S> */ B(LdaConstant), U8(223),
+                B(Star), R(0),
+  /* 2505 S> */ B(LdaConstant), U8(224),
+                B(Star), R(0),
+  /* 2516 S> */ B(LdaConstant), U8(225),
+                B(Star), R(0),
+  /* 2527 S> */ B(LdaConstant), U8(226),
+                B(Star), R(0),
+  /* 2538 S> */ B(LdaConstant), U8(227),
+                B(Star), R(0),
+  /* 2549 S> */ B(LdaConstant), U8(228),
+                B(Star), R(0),
+  /* 2560 S> */ B(LdaConstant), U8(229),
+                B(Star), R(0),
+  /* 2571 S> */ B(LdaConstant), U8(230),
+                B(Star), R(0),
+  /* 2582 S> */ B(LdaConstant), U8(231),
+                B(Star), R(0),
+  /* 2593 S> */ B(LdaConstant), U8(232),
+                B(Star), R(0),
+  /* 2604 S> */ B(LdaConstant), U8(233),
+                B(Star), R(0),
+  /* 2615 S> */ B(LdaConstant), U8(234),
+                B(Star), R(0),
+  /* 2626 S> */ B(LdaConstant), U8(235),
+                B(Star), R(0),
+  /* 2637 S> */ B(LdaConstant), U8(236),
+                B(Star), R(0),
+  /* 2648 S> */ B(LdaConstant), U8(237),
+                B(Star), R(0),
+  /* 2659 S> */ B(LdaConstant), U8(238),
+                B(Star), R(0),
+  /* 2670 S> */ B(LdaConstant), U8(239),
+                B(Star), R(0),
+  /* 2681 S> */ B(LdaConstant), U8(240),
+                B(Star), R(0),
+  /* 2692 S> */ B(LdaConstant), U8(241),
+                B(Star), R(0),
+  /* 2703 S> */ B(LdaConstant), U8(242),
+                B(Star), R(0),
+  /* 2714 S> */ B(LdaConstant), U8(243),
+                B(Star), R(0),
+  /* 2725 S> */ B(LdaConstant), U8(244),
+                B(Star), R(0),
+  /* 2736 S> */ B(LdaConstant), U8(245),
+                B(Star), R(0),
+  /* 2747 S> */ B(LdaConstant), U8(246),
+                B(Star), R(0),
+  /* 2758 S> */ B(LdaConstant), U8(247),
+                B(Star), R(0),
+  /* 2769 S> */ B(LdaConstant), U8(248),
+                B(Star), R(0),
+  /* 2780 S> */ B(LdaConstant), U8(249),
+                B(Star), R(0),
+  /* 2791 S> */ B(LdaConstant), U8(250),
+                B(Star), R(0),
+  /* 2802 S> */ B(LdaConstant), U8(251),
+                B(Star), R(0),
+  /* 2813 S> */ B(LdaConstant), U8(252),
+                B(Star), R(0),
+  /* 2824 S> */ B(LdaConstant), U8(253),
+                B(Star), R(0),
+  /* 2835 S> */ B(LdaConstant), U8(254),
+                B(Star), R(0),
+  /* 2846 S> */ B(LdaConstant), U8(255),
+                B(Star), R(0),
+  /* 2857 S> */ B(Wide), B(LdaConstant), U16(256),
+                B(Star), R(0),
+                B(LdaUndefined),
+  /* 2867 S> */ B(Return),
 ]
 constant pool: [
   1.414,
diff --git a/test/cctest/interpreter/bytecode_expectations/IfConditions.golden b/test/cctest/interpreter/bytecode_expectations/IfConditions.golden
index f450f3f..98c8229 100644
--- a/test/cctest/interpreter/bytecode_expectations/IfConditions.golden
+++ b/test/cctest/interpreter/bytecode_expectations/IfConditions.golden
@@ -3,7 +3,7 @@
 #
 
 ---
-pool type: number
+pool type: mixed
 execute: yes
 wrap: no
 test function name: f
@@ -23,9 +23,9 @@
 parameter count: 1
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(-1),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   55 S> */ B(LdaSmi), U8(-1),
+  /*   70 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -47,9 +47,9 @@
 parameter count: 1
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   36 S> */ B(LdaSmi), U8(1),
+  /*   76 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -71,9 +71,9 @@
 parameter count: 1
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(-1),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   59 S> */ B(LdaSmi), U8(-1),
+  /*   74 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -93,9 +93,9 @@
 parameter count: 1
 bytecode array length: 3
 bytecodes: [
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   17 S> */ B(LdaUndefined),
+  /*   48 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -116,22 +116,21 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 24
+bytecode array length: 23
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(JumpIfToBooleanFalse), U8(14),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(Add), R(1),
-  B(Star), R(0),
-  B(Jump), U8(5),
-  B(LdaSmi), U8(2),
-  B(Return),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   25 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   30 S> */ B(JumpIfToBooleanFalse), U8(13),
+  /*   43 S> */ B(LdaSmi), U8(1),
+                B(Add), R(0),
+                B(Mov), R(0), R(1),
+                B(Star), R(0),
+                B(Jump), U8(5),
+  /*   66 S> */ B(LdaSmi), U8(2),
+  /*   80 S> */ B(Return),
+                B(LdaUndefined),
+  /*   80 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -149,22 +148,20 @@
   };
   f(99);
 "
-frame size: 1
+frame size: 0
 parameter count: 2
-bytecode array length: 22
+bytecode array length: 18
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaZero),
-  B(TestLessThanOrEqual), R(0),
-  B(JumpIfFalse), U8(7),
-  B(Wide), B(LdaSmi), U16(200),
-  B(Return),
-  B(Wide), B(LdaSmi), U16(-200),
-  B(Return),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   18 S> */ B(LdaZero),
+  /*   24 E> */ B(TestLessThanOrEqual), R(arg0),
+                B(JumpIfFalse), U8(7),
+  /*   36 S> */ B(Wide), B(LdaSmi), U16(200),
+  /*   80 S> */ B(Return),
+  /*   63 S> */ B(Wide), B(LdaSmi), U16(-200),
+  /*   80 S> */ B(Return),
+                B(LdaUndefined),
+  /*   80 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -175,20 +172,18 @@
 snippet: "
   function f(a, b) { if (a in b) { return 200; } }f('prop', { prop: 'yes'});
 "
-frame size: 1
+frame size: 0
 parameter count: 3
-bytecode array length: 18
+bytecode array length: 14
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(TestIn), R(0),
-  B(JumpIfFalse), U8(7),
-  B(Wide), B(LdaSmi), U16(200),
-  B(Return),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   19 S> */ B(Ldar), R(arg1),
+  /*   25 E> */ B(TestIn), R(arg0),
+                B(JumpIfFalse), U8(7),
+  /*   33 S> */ B(Wide), B(LdaSmi), U16(200),
+  /*   47 S> */ B(Return),
+                B(LdaUndefined),
+  /*   47 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -264,159 +259,156 @@
     b = a; a = b;
    return 200; } else { return -200; } } f(0.001);
 "
-frame size: 3
+frame size: 2
 parameter count: 2
-bytecode array length: 287
+bytecode array length: 409
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(LdaZero),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaConstant), U8(0),
-  B(TestEqualStrict), R(2),
-  B(JumpIfFalseConstant), U8(1),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Wide), B(LdaSmi), U16(200),
-  B(Return),
-  B(Wide), B(LdaSmi), U16(-200),
-  B(Return),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   24 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   35 S> */ B(LdaZero),
+                B(Star), R(1),
+  /*   38 S> */ B(LdaConstant), U8(0),
+  /*   44 E> */ B(TestEqualStrict), R(0),
+                B(JumpIfFalseConstant), U8(1),
+  /*   58 S> */ B(Mov), R(0), R(1),
+  /*   65 S> */ B(Mov), R(1), R(0),
+  /*   74 S> */ B(Mov), R(0), R(1),
+  /*   81 S> */ B(Mov), R(1), R(0),
+  /*   90 S> */ B(Mov), R(0), R(1),
+  /*   97 S> */ B(Mov), R(1), R(0),
+  /*  106 S> */ B(Mov), R(0), R(1),
+  /*  113 S> */ B(Mov), R(1), R(0),
+  /*  122 S> */ B(Mov), R(0), R(1),
+  /*  129 S> */ B(Mov), R(1), R(0),
+  /*  138 S> */ B(Mov), R(0), R(1),
+  /*  145 S> */ B(Mov), R(1), R(0),
+  /*  154 S> */ B(Mov), R(0), R(1),
+  /*  161 S> */ B(Mov), R(1), R(0),
+  /*  170 S> */ B(Mov), R(0), R(1),
+  /*  177 S> */ B(Mov), R(1), R(0),
+  /*  186 S> */ B(Mov), R(0), R(1),
+  /*  193 S> */ B(Mov), R(1), R(0),
+  /*  202 S> */ B(Mov), R(0), R(1),
+  /*  209 S> */ B(Mov), R(1), R(0),
+  /*  218 S> */ B(Mov), R(0), R(1),
+  /*  225 S> */ B(Mov), R(1), R(0),
+  /*  234 S> */ B(Mov), R(0), R(1),
+  /*  241 S> */ B(Mov), R(1), R(0),
+  /*  250 S> */ B(Mov), R(0), R(1),
+  /*  257 S> */ B(Mov), R(1), R(0),
+  /*  266 S> */ B(Mov), R(0), R(1),
+  /*  273 S> */ B(Mov), R(1), R(0),
+  /*  282 S> */ B(Mov), R(0), R(1),
+  /*  289 S> */ B(Mov), R(1), R(0),
+  /*  298 S> */ B(Mov), R(0), R(1),
+  /*  305 S> */ B(Mov), R(1), R(0),
+  /*  314 S> */ B(Mov), R(0), R(1),
+  /*  321 S> */ B(Mov), R(1), R(0),
+  /*  330 S> */ B(Mov), R(0), R(1),
+  /*  337 S> */ B(Mov), R(1), R(0),
+  /*  346 S> */ B(Mov), R(0), R(1),
+  /*  353 S> */ B(Mov), R(1), R(0),
+  /*  362 S> */ B(Mov), R(0), R(1),
+  /*  369 S> */ B(Mov), R(1), R(0),
+  /*  378 S> */ B(Mov), R(0), R(1),
+  /*  385 S> */ B(Mov), R(1), R(0),
+  /*  394 S> */ B(Mov), R(0), R(1),
+  /*  401 S> */ B(Mov), R(1), R(0),
+  /*  410 S> */ B(Mov), R(0), R(1),
+  /*  417 S> */ B(Mov), R(1), R(0),
+  /*  426 S> */ B(Mov), R(0), R(1),
+  /*  433 S> */ B(Mov), R(1), R(0),
+  /*  442 S> */ B(Mov), R(0), R(1),
+  /*  449 S> */ B(Mov), R(1), R(0),
+  /*  458 S> */ B(Mov), R(0), R(1),
+  /*  465 S> */ B(Mov), R(1), R(0),
+  /*  474 S> */ B(Mov), R(0), R(1),
+  /*  481 S> */ B(Mov), R(1), R(0),
+  /*  490 S> */ B(Mov), R(0), R(1),
+  /*  497 S> */ B(Mov), R(1), R(0),
+  /*  506 S> */ B(Mov), R(0), R(1),
+  /*  513 S> */ B(Mov), R(1), R(0),
+  /*  522 S> */ B(Mov), R(0), R(1),
+  /*  529 S> */ B(Mov), R(1), R(0),
+  /*  538 S> */ B(Mov), R(0), R(1),
+  /*  545 S> */ B(Mov), R(1), R(0),
+  /*  554 S> */ B(Mov), R(0), R(1),
+  /*  561 S> */ B(Mov), R(1), R(0),
+  /*  570 S> */ B(Mov), R(0), R(1),
+  /*  577 S> */ B(Mov), R(1), R(0),
+  /*  586 S> */ B(Mov), R(0), R(1),
+  /*  593 S> */ B(Mov), R(1), R(0),
+  /*  602 S> */ B(Mov), R(0), R(1),
+  /*  609 S> */ B(Mov), R(1), R(0),
+  /*  618 S> */ B(Mov), R(0), R(1),
+  /*  625 S> */ B(Mov), R(1), R(0),
+  /*  634 S> */ B(Mov), R(0), R(1),
+  /*  641 S> */ B(Mov), R(1), R(0),
+  /*  650 S> */ B(Mov), R(0), R(1),
+  /*  657 S> */ B(Mov), R(1), R(0),
+  /*  666 S> */ B(Mov), R(0), R(1),
+  /*  673 S> */ B(Mov), R(1), R(0),
+  /*  682 S> */ B(Mov), R(0), R(1),
+  /*  689 S> */ B(Mov), R(1), R(0),
+  /*  698 S> */ B(Mov), R(0), R(1),
+  /*  705 S> */ B(Mov), R(1), R(0),
+  /*  714 S> */ B(Mov), R(0), R(1),
+  /*  721 S> */ B(Mov), R(1), R(0),
+  /*  730 S> */ B(Mov), R(0), R(1),
+  /*  737 S> */ B(Mov), R(1), R(0),
+  /*  746 S> */ B(Mov), R(0), R(1),
+  /*  753 S> */ B(Mov), R(1), R(0),
+  /*  762 S> */ B(Mov), R(0), R(1),
+  /*  769 S> */ B(Mov), R(1), R(0),
+  /*  778 S> */ B(Mov), R(0), R(1),
+  /*  785 S> */ B(Mov), R(1), R(0),
+  /*  794 S> */ B(Mov), R(0), R(1),
+  /*  801 S> */ B(Mov), R(1), R(0),
+  /*  810 S> */ B(Mov), R(0), R(1),
+  /*  817 S> */ B(Mov), R(1), R(0),
+  /*  826 S> */ B(Mov), R(0), R(1),
+  /*  833 S> */ B(Mov), R(1), R(0),
+  /*  842 S> */ B(Mov), R(0), R(1),
+  /*  849 S> */ B(Mov), R(1), R(0),
+  /*  858 S> */ B(Mov), R(0), R(1),
+  /*  865 S> */ B(Mov), R(1), R(0),
+  /*  874 S> */ B(Mov), R(0), R(1),
+  /*  881 S> */ B(Mov), R(1), R(0),
+  /*  890 S> */ B(Mov), R(0), R(1),
+  /*  897 S> */ B(Mov), R(1), R(0),
+  /*  906 S> */ B(Mov), R(0), R(1),
+  /*  913 S> */ B(Mov), R(1), R(0),
+  /*  922 S> */ B(Mov), R(0), R(1),
+  /*  929 S> */ B(Mov), R(1), R(0),
+  /*  938 S> */ B(Mov), R(0), R(1),
+  /*  945 S> */ B(Mov), R(1), R(0),
+  /*  954 S> */ B(Mov), R(0), R(1),
+  /*  961 S> */ B(Mov), R(1), R(0),
+  /*  970 S> */ B(Mov), R(0), R(1),
+  /*  977 S> */ B(Mov), R(1), R(0),
+  /*  986 S> */ B(Mov), R(0), R(1),
+  /*  993 S> */ B(Mov), R(1), R(0),
+  /* 1002 S> */ B(Mov), R(0), R(1),
+  /* 1009 S> */ B(Mov), R(1), R(0),
+  /* 1018 S> */ B(Mov), R(0), R(1),
+  /* 1025 S> */ B(Mov), R(1), R(0),
+  /* 1034 S> */ B(Mov), R(0), R(1),
+  /* 1041 S> */ B(Mov), R(1), R(0),
+  /* 1050 S> */ B(Mov), R(0), R(1),
+  /* 1057 S> */ B(Mov), R(1), R(0),
+  /* 1066 S> */ B(Mov), R(0), R(1),
+  /* 1073 S> */ B(Mov), R(1), R(0),
+  /* 1081 S> */ B(Wide), B(LdaSmi), U16(200),
+  /* 1117 S> */ B(Return),
+  /* 1102 S> */ B(Wide), B(LdaSmi), U16(-200),
+  /* 1117 S> */ B(Return),
+                B(LdaUndefined),
+  /* 1117 S> */ B(Return),
 ]
 constant pool: [
-  0.01,
-  265,
+  InstanceType::HEAP_NUMBER_TYPE,
+  kInstanceTypeDontCare,
 ]
 handlers: [
 ]
@@ -496,153 +488,152 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 281
+bytecode array length: 407
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(LdaZero),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(JumpIfToBooleanFalseConstant), U8(0),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Wide), B(LdaSmi), U16(200),
-  B(Return),
-  B(Wide), B(LdaSmi), U16(-200),
-  B(Return),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   25 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   36 S> */ B(LdaZero),
+                B(Star), R(1),
+  /*   41 S> */ B(Ldar), R(0),
+                B(JumpIfToBooleanFalseConstant), U8(0),
+  /*   52 S> */ B(Mov), R(0), R(1),
+  /*   59 S> */ B(Mov), R(1), R(0),
+  /*   68 S> */ B(Mov), R(0), R(1),
+  /*   75 S> */ B(Mov), R(1), R(0),
+  /*   84 S> */ B(Mov), R(0), R(1),
+  /*   91 S> */ B(Mov), R(1), R(0),
+  /*  100 S> */ B(Mov), R(0), R(1),
+  /*  107 S> */ B(Mov), R(1), R(0),
+  /*  116 S> */ B(Mov), R(0), R(1),
+  /*  123 S> */ B(Mov), R(1), R(0),
+  /*  132 S> */ B(Mov), R(0), R(1),
+  /*  139 S> */ B(Mov), R(1), R(0),
+  /*  148 S> */ B(Mov), R(0), R(1),
+  /*  155 S> */ B(Mov), R(1), R(0),
+  /*  164 S> */ B(Mov), R(0), R(1),
+  /*  171 S> */ B(Mov), R(1), R(0),
+  /*  180 S> */ B(Mov), R(0), R(1),
+  /*  187 S> */ B(Mov), R(1), R(0),
+  /*  196 S> */ B(Mov), R(0), R(1),
+  /*  203 S> */ B(Mov), R(1), R(0),
+  /*  212 S> */ B(Mov), R(0), R(1),
+  /*  219 S> */ B(Mov), R(1), R(0),
+  /*  228 S> */ B(Mov), R(0), R(1),
+  /*  235 S> */ B(Mov), R(1), R(0),
+  /*  244 S> */ B(Mov), R(0), R(1),
+  /*  251 S> */ B(Mov), R(1), R(0),
+  /*  260 S> */ B(Mov), R(0), R(1),
+  /*  267 S> */ B(Mov), R(1), R(0),
+  /*  276 S> */ B(Mov), R(0), R(1),
+  /*  283 S> */ B(Mov), R(1), R(0),
+  /*  292 S> */ B(Mov), R(0), R(1),
+  /*  299 S> */ B(Mov), R(1), R(0),
+  /*  308 S> */ B(Mov), R(0), R(1),
+  /*  315 S> */ B(Mov), R(1), R(0),
+  /*  324 S> */ B(Mov), R(0), R(1),
+  /*  331 S> */ B(Mov), R(1), R(0),
+  /*  340 S> */ B(Mov), R(0), R(1),
+  /*  347 S> */ B(Mov), R(1), R(0),
+  /*  356 S> */ B(Mov), R(0), R(1),
+  /*  363 S> */ B(Mov), R(1), R(0),
+  /*  372 S> */ B(Mov), R(0), R(1),
+  /*  379 S> */ B(Mov), R(1), R(0),
+  /*  388 S> */ B(Mov), R(0), R(1),
+  /*  395 S> */ B(Mov), R(1), R(0),
+  /*  404 S> */ B(Mov), R(0), R(1),
+  /*  411 S> */ B(Mov), R(1), R(0),
+  /*  420 S> */ B(Mov), R(0), R(1),
+  /*  427 S> */ B(Mov), R(1), R(0),
+  /*  436 S> */ B(Mov), R(0), R(1),
+  /*  443 S> */ B(Mov), R(1), R(0),
+  /*  452 S> */ B(Mov), R(0), R(1),
+  /*  459 S> */ B(Mov), R(1), R(0),
+  /*  468 S> */ B(Mov), R(0), R(1),
+  /*  475 S> */ B(Mov), R(1), R(0),
+  /*  484 S> */ B(Mov), R(0), R(1),
+  /*  491 S> */ B(Mov), R(1), R(0),
+  /*  500 S> */ B(Mov), R(0), R(1),
+  /*  507 S> */ B(Mov), R(1), R(0),
+  /*  516 S> */ B(Mov), R(0), R(1),
+  /*  523 S> */ B(Mov), R(1), R(0),
+  /*  532 S> */ B(Mov), R(0), R(1),
+  /*  539 S> */ B(Mov), R(1), R(0),
+  /*  548 S> */ B(Mov), R(0), R(1),
+  /*  555 S> */ B(Mov), R(1), R(0),
+  /*  564 S> */ B(Mov), R(0), R(1),
+  /*  571 S> */ B(Mov), R(1), R(0),
+  /*  580 S> */ B(Mov), R(0), R(1),
+  /*  587 S> */ B(Mov), R(1), R(0),
+  /*  596 S> */ B(Mov), R(0), R(1),
+  /*  603 S> */ B(Mov), R(1), R(0),
+  /*  612 S> */ B(Mov), R(0), R(1),
+  /*  619 S> */ B(Mov), R(1), R(0),
+  /*  628 S> */ B(Mov), R(0), R(1),
+  /*  635 S> */ B(Mov), R(1), R(0),
+  /*  644 S> */ B(Mov), R(0), R(1),
+  /*  651 S> */ B(Mov), R(1), R(0),
+  /*  660 S> */ B(Mov), R(0), R(1),
+  /*  667 S> */ B(Mov), R(1), R(0),
+  /*  676 S> */ B(Mov), R(0), R(1),
+  /*  683 S> */ B(Mov), R(1), R(0),
+  /*  692 S> */ B(Mov), R(0), R(1),
+  /*  699 S> */ B(Mov), R(1), R(0),
+  /*  708 S> */ B(Mov), R(0), R(1),
+  /*  715 S> */ B(Mov), R(1), R(0),
+  /*  724 S> */ B(Mov), R(0), R(1),
+  /*  731 S> */ B(Mov), R(1), R(0),
+  /*  740 S> */ B(Mov), R(0), R(1),
+  /*  747 S> */ B(Mov), R(1), R(0),
+  /*  756 S> */ B(Mov), R(0), R(1),
+  /*  763 S> */ B(Mov), R(1), R(0),
+  /*  772 S> */ B(Mov), R(0), R(1),
+  /*  779 S> */ B(Mov), R(1), R(0),
+  /*  788 S> */ B(Mov), R(0), R(1),
+  /*  795 S> */ B(Mov), R(1), R(0),
+  /*  804 S> */ B(Mov), R(0), R(1),
+  /*  811 S> */ B(Mov), R(1), R(0),
+  /*  820 S> */ B(Mov), R(0), R(1),
+  /*  827 S> */ B(Mov), R(1), R(0),
+  /*  836 S> */ B(Mov), R(0), R(1),
+  /*  843 S> */ B(Mov), R(1), R(0),
+  /*  852 S> */ B(Mov), R(0), R(1),
+  /*  859 S> */ B(Mov), R(1), R(0),
+  /*  868 S> */ B(Mov), R(0), R(1),
+  /*  875 S> */ B(Mov), R(1), R(0),
+  /*  884 S> */ B(Mov), R(0), R(1),
+  /*  891 S> */ B(Mov), R(1), R(0),
+  /*  900 S> */ B(Mov), R(0), R(1),
+  /*  907 S> */ B(Mov), R(1), R(0),
+  /*  916 S> */ B(Mov), R(0), R(1),
+  /*  923 S> */ B(Mov), R(1), R(0),
+  /*  932 S> */ B(Mov), R(0), R(1),
+  /*  939 S> */ B(Mov), R(1), R(0),
+  /*  948 S> */ B(Mov), R(0), R(1),
+  /*  955 S> */ B(Mov), R(1), R(0),
+  /*  964 S> */ B(Mov), R(0), R(1),
+  /*  971 S> */ B(Mov), R(1), R(0),
+  /*  980 S> */ B(Mov), R(0), R(1),
+  /*  987 S> */ B(Mov), R(1), R(0),
+  /*  996 S> */ B(Mov), R(0), R(1),
+  /* 1003 S> */ B(Mov), R(1), R(0),
+  /* 1012 S> */ B(Mov), R(0), R(1),
+  /* 1019 S> */ B(Mov), R(1), R(0),
+  /* 1028 S> */ B(Mov), R(0), R(1),
+  /* 1035 S> */ B(Mov), R(1), R(0),
+  /* 1044 S> */ B(Mov), R(0), R(1),
+  /* 1051 S> */ B(Mov), R(1), R(0),
+  /* 1060 S> */ B(Mov), R(0), R(1),
+  /* 1067 S> */ B(Mov), R(1), R(0),
+  /* 1076 S> */ B(Wide), B(LdaSmi), U16(200),
+  /* 1112 S> */ B(Return),
+  /* 1097 S> */ B(Wide), B(LdaSmi), U16(-200),
+  /* 1112 S> */ B(Return),
+                B(LdaUndefined),
+  /* 1112 S> */ B(Return),
 ]
 constant pool: [
-  265,
+  kInstanceTypeDontCare,
 ]
 handlers: [
 ]
@@ -662,69 +653,53 @@
   }
   f(1, 1);
 "
-frame size: 1
+frame size: 0
 parameter count: 3
-bytecode array length: 107
+bytecode array length: 75
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(TestEqual), R(0),
-  B(JumpIfFalse), U8(5),
-  B(LdaSmi), U8(1),
-  B(Return),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(TestEqualStrict), R(0),
-  B(JumpIfFalse), U8(5),
-  B(LdaSmi), U8(1),
-  B(Return),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(TestLessThan), R(0),
-  B(JumpIfFalse), U8(5),
-  B(LdaSmi), U8(1),
-  B(Return),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(TestGreaterThan), R(0),
-  B(JumpIfFalse), U8(5),
-  B(LdaSmi), U8(1),
-  B(Return),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(TestLessThanOrEqual), R(0),
-  B(JumpIfFalse), U8(5),
-  B(LdaSmi), U8(1),
-  B(Return),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(TestGreaterThanOrEqual), R(0),
-  B(JumpIfFalse), U8(5),
-  B(LdaSmi), U8(1),
-  B(Return),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(TestIn), R(0),
-  B(JumpIfFalse), U8(5),
-  B(LdaSmi), U8(1),
-  B(Return),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(TestInstanceOf), R(0),
-  B(JumpIfFalse), U8(5),
-  B(LdaSmi), U8(1),
-  B(Return),
-  B(LdaZero),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   21 S> */ B(Ldar), R(arg1),
+  /*   27 E> */ B(TestEqual), R(arg0),
+                B(JumpIfFalse), U8(5),
+  /*   35 S> */ B(LdaSmi), U8(1),
+  /*  262 S> */ B(Return),
+  /*   49 S> */ B(Ldar), R(arg1),
+  /*   55 E> */ B(TestEqualStrict), R(arg0),
+                B(JumpIfFalse), U8(5),
+  /*   64 S> */ B(LdaSmi), U8(1),
+  /*  262 S> */ B(Return),
+  /*   78 S> */ B(Ldar), R(arg1),
+  /*   84 E> */ B(TestLessThan), R(arg0),
+                B(JumpIfFalse), U8(5),
+  /*   91 S> */ B(LdaSmi), U8(1),
+  /*  262 S> */ B(Return),
+  /*  105 S> */ B(Ldar), R(arg1),
+  /*  111 E> */ B(TestGreaterThan), R(arg0),
+                B(JumpIfFalse), U8(5),
+  /*  118 S> */ B(LdaSmi), U8(1),
+  /*  262 S> */ B(Return),
+  /*  132 S> */ B(Ldar), R(arg1),
+  /*  138 E> */ B(TestLessThanOrEqual), R(arg0),
+                B(JumpIfFalse), U8(5),
+  /*  146 S> */ B(LdaSmi), U8(1),
+  /*  262 S> */ B(Return),
+  /*  160 S> */ B(Ldar), R(arg1),
+  /*  166 E> */ B(TestGreaterThanOrEqual), R(arg0),
+                B(JumpIfFalse), U8(5),
+  /*  174 S> */ B(LdaSmi), U8(1),
+  /*  262 S> */ B(Return),
+  /*  188 S> */ B(Ldar), R(arg1),
+  /*  194 E> */ B(TestIn), R(arg0),
+                B(JumpIfFalse), U8(5),
+  /*  202 S> */ B(LdaSmi), U8(1),
+  /*  262 S> */ B(Return),
+  /*  216 S> */ B(Ldar), R(arg1),
+  /*  222 E> */ B(TestInstanceOf), R(arg0),
+                B(JumpIfFalse), U8(5),
+  /*  238 S> */ B(LdaSmi), U8(1),
+  /*  262 S> */ B(Return),
+  /*  252 S> */ B(LdaZero),
+  /*  262 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -747,16 +722,16 @@
 parameter count: 1
 bytecode array length: 14
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(JumpIfToBooleanFalse), U8(5),
-  B(LdaSmi), U8(20),
-  B(Return),
-  B(LdaSmi), U8(-20),
-  B(Return),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   25 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   30 S> */ B(JumpIfToBooleanFalse), U8(5),
+  /*   43 S> */ B(LdaSmi), U8(20),
+  /*   85 S> */ B(Return),
+  /*   69 S> */ B(LdaSmi), U8(-20),
+  /*   85 S> */ B(Return),
+                B(LdaUndefined),
+  /*   85 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/IntegerConstants.golden b/test/cctest/interpreter/bytecode_expectations/IntegerConstants.golden
index 1c37c12..6ac81a6 100644
--- a/test/cctest/interpreter/bytecode_expectations/IntegerConstants.golden
+++ b/test/cctest/interpreter/bytecode_expectations/IntegerConstants.golden
@@ -15,9 +15,9 @@
 parameter count: 1
 bytecode array length: 8
 bytecodes: [
-  B(StackCheck),
-  B(ExtraWide), B(LdaSmi), U32(12345678),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(ExtraWide), B(LdaSmi), U32(12345678),
+  /*   51 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -32,11 +32,11 @@
 parameter count: 1
 bytecode array length: 12
 bytecodes: [
-  B(StackCheck),
-  B(Wide), B(LdaSmi), U16(1234),
-  B(Star), R(0),
-  B(Wide), B(LdaSmi), U16(5678),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(Wide), B(LdaSmi), U16(1234),
+                B(Star), R(0),
+  /*   48 S> */ B(Wide), B(LdaSmi), U16(5678),
+  /*   61 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -51,11 +51,11 @@
 parameter count: 1
 bytecode array length: 12
 bytecodes: [
-  B(StackCheck),
-  B(Wide), B(LdaSmi), U16(1234),
-  B(Star), R(0),
-  B(Wide), B(LdaSmi), U16(1234),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(Wide), B(LdaSmi), U16(1234),
+                B(Star), R(0),
+  /*   48 S> */ B(Wide), B(LdaSmi), U16(1234),
+  /*   61 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/JumpsRequiringConstantWideOperands.golden b/test/cctest/interpreter/bytecode_expectations/JumpsRequiringConstantWideOperands.golden
index 3f0b49d..3bf0a4f 100644
--- a/test/cctest/interpreter/bytecode_expectations/JumpsRequiringConstantWideOperands.golden
+++ b/test/cctest/interpreter/bytecode_expectations/JumpsRequiringConstantWideOperands.golden
@@ -329,661 +329,655 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 1422
+bytecode array length: 1410
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(LdaConstant), U8(1),
-  B(Star), R(0),
-  B(LdaConstant), U8(2),
-  B(Star), R(0),
-  B(LdaConstant), U8(3),
-  B(Star), R(0),
-  B(LdaConstant), U8(4),
-  B(Star), R(0),
-  B(LdaConstant), U8(5),
-  B(Star), R(0),
-  B(LdaConstant), U8(6),
-  B(Star), R(0),
-  B(LdaConstant), U8(7),
-  B(Star), R(0),
-  B(LdaConstant), U8(8),
-  B(Star), R(0),
-  B(LdaConstant), U8(9),
-  B(Star), R(0),
-  B(LdaConstant), U8(10),
-  B(Star), R(0),
-  B(LdaConstant), U8(11),
-  B(Star), R(0),
-  B(LdaConstant), U8(12),
-  B(Star), R(0),
-  B(LdaConstant), U8(13),
-  B(Star), R(0),
-  B(LdaConstant), U8(14),
-  B(Star), R(0),
-  B(LdaConstant), U8(15),
-  B(Star), R(0),
-  B(LdaConstant), U8(16),
-  B(Star), R(0),
-  B(LdaConstant), U8(17),
-  B(Star), R(0),
-  B(LdaConstant), U8(18),
-  B(Star), R(0),
-  B(LdaConstant), U8(19),
-  B(Star), R(0),
-  B(LdaConstant), U8(20),
-  B(Star), R(0),
-  B(LdaConstant), U8(21),
-  B(Star), R(0),
-  B(LdaConstant), U8(22),
-  B(Star), R(0),
-  B(LdaConstant), U8(23),
-  B(Star), R(0),
-  B(LdaConstant), U8(24),
-  B(Star), R(0),
-  B(LdaConstant), U8(25),
-  B(Star), R(0),
-  B(LdaConstant), U8(26),
-  B(Star), R(0),
-  B(LdaConstant), U8(27),
-  B(Star), R(0),
-  B(LdaConstant), U8(28),
-  B(Star), R(0),
-  B(LdaConstant), U8(29),
-  B(Star), R(0),
-  B(LdaConstant), U8(30),
-  B(Star), R(0),
-  B(LdaConstant), U8(31),
-  B(Star), R(0),
-  B(LdaConstant), U8(32),
-  B(Star), R(0),
-  B(LdaConstant), U8(33),
-  B(Star), R(0),
-  B(LdaConstant), U8(34),
-  B(Star), R(0),
-  B(LdaConstant), U8(35),
-  B(Star), R(0),
-  B(LdaConstant), U8(36),
-  B(Star), R(0),
-  B(LdaConstant), U8(37),
-  B(Star), R(0),
-  B(LdaConstant), U8(38),
-  B(Star), R(0),
-  B(LdaConstant), U8(39),
-  B(Star), R(0),
-  B(LdaConstant), U8(40),
-  B(Star), R(0),
-  B(LdaConstant), U8(41),
-  B(Star), R(0),
-  B(LdaConstant), U8(42),
-  B(Star), R(0),
-  B(LdaConstant), U8(43),
-  B(Star), R(0),
-  B(LdaConstant), U8(44),
-  B(Star), R(0),
-  B(LdaConstant), U8(45),
-  B(Star), R(0),
-  B(LdaConstant), U8(46),
-  B(Star), R(0),
-  B(LdaConstant), U8(47),
-  B(Star), R(0),
-  B(LdaConstant), U8(48),
-  B(Star), R(0),
-  B(LdaConstant), U8(49),
-  B(Star), R(0),
-  B(LdaConstant), U8(50),
-  B(Star), R(0),
-  B(LdaConstant), U8(51),
-  B(Star), R(0),
-  B(LdaConstant), U8(52),
-  B(Star), R(0),
-  B(LdaConstant), U8(53),
-  B(Star), R(0),
-  B(LdaConstant), U8(54),
-  B(Star), R(0),
-  B(LdaConstant), U8(55),
-  B(Star), R(0),
-  B(LdaConstant), U8(56),
-  B(Star), R(0),
-  B(LdaConstant), U8(57),
-  B(Star), R(0),
-  B(LdaConstant), U8(58),
-  B(Star), R(0),
-  B(LdaConstant), U8(59),
-  B(Star), R(0),
-  B(LdaConstant), U8(60),
-  B(Star), R(0),
-  B(LdaConstant), U8(61),
-  B(Star), R(0),
-  B(LdaConstant), U8(62),
-  B(Star), R(0),
-  B(LdaConstant), U8(63),
-  B(Star), R(0),
-  B(LdaConstant), U8(64),
-  B(Star), R(0),
-  B(LdaConstant), U8(65),
-  B(Star), R(0),
-  B(LdaConstant), U8(66),
-  B(Star), R(0),
-  B(LdaConstant), U8(67),
-  B(Star), R(0),
-  B(LdaConstant), U8(68),
-  B(Star), R(0),
-  B(LdaConstant), U8(69),
-  B(Star), R(0),
-  B(LdaConstant), U8(70),
-  B(Star), R(0),
-  B(LdaConstant), U8(71),
-  B(Star), R(0),
-  B(LdaConstant), U8(72),
-  B(Star), R(0),
-  B(LdaConstant), U8(73),
-  B(Star), R(0),
-  B(LdaConstant), U8(74),
-  B(Star), R(0),
-  B(LdaConstant), U8(75),
-  B(Star), R(0),
-  B(LdaConstant), U8(76),
-  B(Star), R(0),
-  B(LdaConstant), U8(77),
-  B(Star), R(0),
-  B(LdaConstant), U8(78),
-  B(Star), R(0),
-  B(LdaConstant), U8(79),
-  B(Star), R(0),
-  B(LdaConstant), U8(80),
-  B(Star), R(0),
-  B(LdaConstant), U8(81),
-  B(Star), R(0),
-  B(LdaConstant), U8(82),
-  B(Star), R(0),
-  B(LdaConstant), U8(83),
-  B(Star), R(0),
-  B(LdaConstant), U8(84),
-  B(Star), R(0),
-  B(LdaConstant), U8(85),
-  B(Star), R(0),
-  B(LdaConstant), U8(86),
-  B(Star), R(0),
-  B(LdaConstant), U8(87),
-  B(Star), R(0),
-  B(LdaConstant), U8(88),
-  B(Star), R(0),
-  B(LdaConstant), U8(89),
-  B(Star), R(0),
-  B(LdaConstant), U8(90),
-  B(Star), R(0),
-  B(LdaConstant), U8(91),
-  B(Star), R(0),
-  B(LdaConstant), U8(92),
-  B(Star), R(0),
-  B(LdaConstant), U8(93),
-  B(Star), R(0),
-  B(LdaConstant), U8(94),
-  B(Star), R(0),
-  B(LdaConstant), U8(95),
-  B(Star), R(0),
-  B(LdaConstant), U8(96),
-  B(Star), R(0),
-  B(LdaConstant), U8(97),
-  B(Star), R(0),
-  B(LdaConstant), U8(98),
-  B(Star), R(0),
-  B(LdaConstant), U8(99),
-  B(Star), R(0),
-  B(LdaConstant), U8(100),
-  B(Star), R(0),
-  B(LdaConstant), U8(101),
-  B(Star), R(0),
-  B(LdaConstant), U8(102),
-  B(Star), R(0),
-  B(LdaConstant), U8(103),
-  B(Star), R(0),
-  B(LdaConstant), U8(104),
-  B(Star), R(0),
-  B(LdaConstant), U8(105),
-  B(Star), R(0),
-  B(LdaConstant), U8(106),
-  B(Star), R(0),
-  B(LdaConstant), U8(107),
-  B(Star), R(0),
-  B(LdaConstant), U8(108),
-  B(Star), R(0),
-  B(LdaConstant), U8(109),
-  B(Star), R(0),
-  B(LdaConstant), U8(110),
-  B(Star), R(0),
-  B(LdaConstant), U8(111),
-  B(Star), R(0),
-  B(LdaConstant), U8(112),
-  B(Star), R(0),
-  B(LdaConstant), U8(113),
-  B(Star), R(0),
-  B(LdaConstant), U8(114),
-  B(Star), R(0),
-  B(LdaConstant), U8(115),
-  B(Star), R(0),
-  B(LdaConstant), U8(116),
-  B(Star), R(0),
-  B(LdaConstant), U8(117),
-  B(Star), R(0),
-  B(LdaConstant), U8(118),
-  B(Star), R(0),
-  B(LdaConstant), U8(119),
-  B(Star), R(0),
-  B(LdaConstant), U8(120),
-  B(Star), R(0),
-  B(LdaConstant), U8(121),
-  B(Star), R(0),
-  B(LdaConstant), U8(122),
-  B(Star), R(0),
-  B(LdaConstant), U8(123),
-  B(Star), R(0),
-  B(LdaConstant), U8(124),
-  B(Star), R(0),
-  B(LdaConstant), U8(125),
-  B(Star), R(0),
-  B(LdaConstant), U8(126),
-  B(Star), R(0),
-  B(LdaConstant), U8(127),
-  B(Star), R(0),
-  B(LdaConstant), U8(128),
-  B(Star), R(0),
-  B(LdaConstant), U8(129),
-  B(Star), R(0),
-  B(LdaConstant), U8(130),
-  B(Star), R(0),
-  B(LdaConstant), U8(131),
-  B(Star), R(0),
-  B(LdaConstant), U8(132),
-  B(Star), R(0),
-  B(LdaConstant), U8(133),
-  B(Star), R(0),
-  B(LdaConstant), U8(134),
-  B(Star), R(0),
-  B(LdaConstant), U8(135),
-  B(Star), R(0),
-  B(LdaConstant), U8(136),
-  B(Star), R(0),
-  B(LdaConstant), U8(137),
-  B(Star), R(0),
-  B(LdaConstant), U8(138),
-  B(Star), R(0),
-  B(LdaConstant), U8(139),
-  B(Star), R(0),
-  B(LdaConstant), U8(140),
-  B(Star), R(0),
-  B(LdaConstant), U8(141),
-  B(Star), R(0),
-  B(LdaConstant), U8(142),
-  B(Star), R(0),
-  B(LdaConstant), U8(143),
-  B(Star), R(0),
-  B(LdaConstant), U8(144),
-  B(Star), R(0),
-  B(LdaConstant), U8(145),
-  B(Star), R(0),
-  B(LdaConstant), U8(146),
-  B(Star), R(0),
-  B(LdaConstant), U8(147),
-  B(Star), R(0),
-  B(LdaConstant), U8(148),
-  B(Star), R(0),
-  B(LdaConstant), U8(149),
-  B(Star), R(0),
-  B(LdaConstant), U8(150),
-  B(Star), R(0),
-  B(LdaConstant), U8(151),
-  B(Star), R(0),
-  B(LdaConstant), U8(152),
-  B(Star), R(0),
-  B(LdaConstant), U8(153),
-  B(Star), R(0),
-  B(LdaConstant), U8(154),
-  B(Star), R(0),
-  B(LdaConstant), U8(155),
-  B(Star), R(0),
-  B(LdaConstant), U8(156),
-  B(Star), R(0),
-  B(LdaConstant), U8(157),
-  B(Star), R(0),
-  B(LdaConstant), U8(158),
-  B(Star), R(0),
-  B(LdaConstant), U8(159),
-  B(Star), R(0),
-  B(LdaConstant), U8(160),
-  B(Star), R(0),
-  B(LdaConstant), U8(161),
-  B(Star), R(0),
-  B(LdaConstant), U8(162),
-  B(Star), R(0),
-  B(LdaConstant), U8(163),
-  B(Star), R(0),
-  B(LdaConstant), U8(164),
-  B(Star), R(0),
-  B(LdaConstant), U8(165),
-  B(Star), R(0),
-  B(LdaConstant), U8(166),
-  B(Star), R(0),
-  B(LdaConstant), U8(167),
-  B(Star), R(0),
-  B(LdaConstant), U8(168),
-  B(Star), R(0),
-  B(LdaConstant), U8(169),
-  B(Star), R(0),
-  B(LdaConstant), U8(170),
-  B(Star), R(0),
-  B(LdaConstant), U8(171),
-  B(Star), R(0),
-  B(LdaConstant), U8(172),
-  B(Star), R(0),
-  B(LdaConstant), U8(173),
-  B(Star), R(0),
-  B(LdaConstant), U8(174),
-  B(Star), R(0),
-  B(LdaConstant), U8(175),
-  B(Star), R(0),
-  B(LdaConstant), U8(176),
-  B(Star), R(0),
-  B(LdaConstant), U8(177),
-  B(Star), R(0),
-  B(LdaConstant), U8(178),
-  B(Star), R(0),
-  B(LdaConstant), U8(179),
-  B(Star), R(0),
-  B(LdaConstant), U8(180),
-  B(Star), R(0),
-  B(LdaConstant), U8(181),
-  B(Star), R(0),
-  B(LdaConstant), U8(182),
-  B(Star), R(0),
-  B(LdaConstant), U8(183),
-  B(Star), R(0),
-  B(LdaConstant), U8(184),
-  B(Star), R(0),
-  B(LdaConstant), U8(185),
-  B(Star), R(0),
-  B(LdaConstant), U8(186),
-  B(Star), R(0),
-  B(LdaConstant), U8(187),
-  B(Star), R(0),
-  B(LdaConstant), U8(188),
-  B(Star), R(0),
-  B(LdaConstant), U8(189),
-  B(Star), R(0),
-  B(LdaConstant), U8(190),
-  B(Star), R(0),
-  B(LdaConstant), U8(191),
-  B(Star), R(0),
-  B(LdaConstant), U8(192),
-  B(Star), R(0),
-  B(LdaConstant), U8(193),
-  B(Star), R(0),
-  B(LdaConstant), U8(194),
-  B(Star), R(0),
-  B(LdaConstant), U8(195),
-  B(Star), R(0),
-  B(LdaConstant), U8(196),
-  B(Star), R(0),
-  B(LdaConstant), U8(197),
-  B(Star), R(0),
-  B(LdaConstant), U8(198),
-  B(Star), R(0),
-  B(LdaConstant), U8(199),
-  B(Star), R(0),
-  B(LdaConstant), U8(200),
-  B(Star), R(0),
-  B(LdaConstant), U8(201),
-  B(Star), R(0),
-  B(LdaConstant), U8(202),
-  B(Star), R(0),
-  B(LdaConstant), U8(203),
-  B(Star), R(0),
-  B(LdaConstant), U8(204),
-  B(Star), R(0),
-  B(LdaConstant), U8(205),
-  B(Star), R(0),
-  B(LdaConstant), U8(206),
-  B(Star), R(0),
-  B(LdaConstant), U8(207),
-  B(Star), R(0),
-  B(LdaConstant), U8(208),
-  B(Star), R(0),
-  B(LdaConstant), U8(209),
-  B(Star), R(0),
-  B(LdaConstant), U8(210),
-  B(Star), R(0),
-  B(LdaConstant), U8(211),
-  B(Star), R(0),
-  B(LdaConstant), U8(212),
-  B(Star), R(0),
-  B(LdaConstant), U8(213),
-  B(Star), R(0),
-  B(LdaConstant), U8(214),
-  B(Star), R(0),
-  B(LdaConstant), U8(215),
-  B(Star), R(0),
-  B(LdaConstant), U8(216),
-  B(Star), R(0),
-  B(LdaConstant), U8(217),
-  B(Star), R(0),
-  B(LdaConstant), U8(218),
-  B(Star), R(0),
-  B(LdaConstant), U8(219),
-  B(Star), R(0),
-  B(LdaConstant), U8(220),
-  B(Star), R(0),
-  B(LdaConstant), U8(221),
-  B(Star), R(0),
-  B(LdaConstant), U8(222),
-  B(Star), R(0),
-  B(LdaConstant), U8(223),
-  B(Star), R(0),
-  B(LdaConstant), U8(224),
-  B(Star), R(0),
-  B(LdaConstant), U8(225),
-  B(Star), R(0),
-  B(LdaConstant), U8(226),
-  B(Star), R(0),
-  B(LdaConstant), U8(227),
-  B(Star), R(0),
-  B(LdaConstant), U8(228),
-  B(Star), R(0),
-  B(LdaConstant), U8(229),
-  B(Star), R(0),
-  B(LdaConstant), U8(230),
-  B(Star), R(0),
-  B(LdaConstant), U8(231),
-  B(Star), R(0),
-  B(LdaConstant), U8(232),
-  B(Star), R(0),
-  B(LdaConstant), U8(233),
-  B(Star), R(0),
-  B(LdaConstant), U8(234),
-  B(Star), R(0),
-  B(LdaConstant), U8(235),
-  B(Star), R(0),
-  B(LdaConstant), U8(236),
-  B(Star), R(0),
-  B(LdaConstant), U8(237),
-  B(Star), R(0),
-  B(LdaConstant), U8(238),
-  B(Star), R(0),
-  B(LdaConstant), U8(239),
-  B(Star), R(0),
-  B(LdaConstant), U8(240),
-  B(Star), R(0),
-  B(LdaConstant), U8(241),
-  B(Star), R(0),
-  B(LdaConstant), U8(242),
-  B(Star), R(0),
-  B(LdaConstant), U8(243),
-  B(Star), R(0),
-  B(LdaConstant), U8(244),
-  B(Star), R(0),
-  B(LdaConstant), U8(245),
-  B(Star), R(0),
-  B(LdaConstant), U8(246),
-  B(Star), R(0),
-  B(LdaConstant), U8(247),
-  B(Star), R(0),
-  B(LdaConstant), U8(248),
-  B(Star), R(0),
-  B(LdaConstant), U8(249),
-  B(Star), R(0),
-  B(LdaConstant), U8(250),
-  B(Star), R(0),
-  B(LdaConstant), U8(251),
-  B(Star), R(0),
-  B(LdaConstant), U8(252),
-  B(Star), R(0),
-  B(LdaConstant), U8(253),
-  B(Star), R(0),
-  B(LdaConstant), U8(254),
-  B(Star), R(0),
-  B(LdaConstant), U8(255),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(256),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(257),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(258),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(259),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(260),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(261),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(262),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(263),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(264),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(265),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(266),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(267),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(268),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(269),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(270),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(271),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(272),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(273),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(274),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(275),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(276),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(277),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(278),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(279),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(280),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(281),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(282),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(283),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(284),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(285),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(286),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(287),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(288),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(289),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(290),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(291),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(292),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(293),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(294),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(295),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(296),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(297),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(298),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(299),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(300),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(301),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(302),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(303),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(304),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(305),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(306),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(307),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(308),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(309),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(310),
-  B(Star), R(0),
-  B(Wide), B(LdaConstant), U16(311),
-  B(Star), R(0),
-  B(LdaZero),
-  B(Star), R(1),
-  B(Ldar), R(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(3),
-  B(TestLessThan), R(2),
-  B(Wide), B(JumpIfFalse), U16(46),
-  B(StackCheck),
-  B(Ldar), R(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(TestEqual), R(2),
-  B(Wide), B(JumpIfFalse), U16(7),
-  B(Wide), B(Jump), U16(19),
-  B(Ldar), R(1),
-  B(Star), R(2),
-  B(LdaSmi), U8(2),
-  B(TestEqual), R(2),
-  B(Wide), B(JumpIfFalse), U16(7),
-  B(Wide), B(Jump), U16(13),
-  B(Ldar), R(1),
-  B(ToNumber),
-  B(Star), R(2),
-  B(Inc),
-  B(Star), R(1),
-  B(Jump), U8(-53),
-  B(LdaSmi), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   55 S> */ B(LdaConstant), U8(1),
+                B(Star), R(0),
+  /*   68 S> */ B(LdaConstant), U8(2),
+                B(Star), R(0),
+  /*   81 S> */ B(LdaConstant), U8(3),
+                B(Star), R(0),
+  /*   94 S> */ B(LdaConstant), U8(4),
+                B(Star), R(0),
+  /*  107 S> */ B(LdaConstant), U8(5),
+                B(Star), R(0),
+  /*  120 S> */ B(LdaConstant), U8(6),
+                B(Star), R(0),
+  /*  133 S> */ B(LdaConstant), U8(7),
+                B(Star), R(0),
+  /*  146 S> */ B(LdaConstant), U8(8),
+                B(Star), R(0),
+  /*  159 S> */ B(LdaConstant), U8(9),
+                B(Star), R(0),
+  /*  172 S> */ B(LdaConstant), U8(10),
+                B(Star), R(0),
+  /*  185 S> */ B(LdaConstant), U8(11),
+                B(Star), R(0),
+  /*  198 S> */ B(LdaConstant), U8(12),
+                B(Star), R(0),
+  /*  211 S> */ B(LdaConstant), U8(13),
+                B(Star), R(0),
+  /*  224 S> */ B(LdaConstant), U8(14),
+                B(Star), R(0),
+  /*  237 S> */ B(LdaConstant), U8(15),
+                B(Star), R(0),
+  /*  250 S> */ B(LdaConstant), U8(16),
+                B(Star), R(0),
+  /*  263 S> */ B(LdaConstant), U8(17),
+                B(Star), R(0),
+  /*  276 S> */ B(LdaConstant), U8(18),
+                B(Star), R(0),
+  /*  289 S> */ B(LdaConstant), U8(19),
+                B(Star), R(0),
+  /*  302 S> */ B(LdaConstant), U8(20),
+                B(Star), R(0),
+  /*  315 S> */ B(LdaConstant), U8(21),
+                B(Star), R(0),
+  /*  328 S> */ B(LdaConstant), U8(22),
+                B(Star), R(0),
+  /*  341 S> */ B(LdaConstant), U8(23),
+                B(Star), R(0),
+  /*  354 S> */ B(LdaConstant), U8(24),
+                B(Star), R(0),
+  /*  367 S> */ B(LdaConstant), U8(25),
+                B(Star), R(0),
+  /*  380 S> */ B(LdaConstant), U8(26),
+                B(Star), R(0),
+  /*  393 S> */ B(LdaConstant), U8(27),
+                B(Star), R(0),
+  /*  406 S> */ B(LdaConstant), U8(28),
+                B(Star), R(0),
+  /*  419 S> */ B(LdaConstant), U8(29),
+                B(Star), R(0),
+  /*  432 S> */ B(LdaConstant), U8(30),
+                B(Star), R(0),
+  /*  445 S> */ B(LdaConstant), U8(31),
+                B(Star), R(0),
+  /*  458 S> */ B(LdaConstant), U8(32),
+                B(Star), R(0),
+  /*  471 S> */ B(LdaConstant), U8(33),
+                B(Star), R(0),
+  /*  484 S> */ B(LdaConstant), U8(34),
+                B(Star), R(0),
+  /*  497 S> */ B(LdaConstant), U8(35),
+                B(Star), R(0),
+  /*  510 S> */ B(LdaConstant), U8(36),
+                B(Star), R(0),
+  /*  523 S> */ B(LdaConstant), U8(37),
+                B(Star), R(0),
+  /*  536 S> */ B(LdaConstant), U8(38),
+                B(Star), R(0),
+  /*  549 S> */ B(LdaConstant), U8(39),
+                B(Star), R(0),
+  /*  562 S> */ B(LdaConstant), U8(40),
+                B(Star), R(0),
+  /*  575 S> */ B(LdaConstant), U8(41),
+                B(Star), R(0),
+  /*  588 S> */ B(LdaConstant), U8(42),
+                B(Star), R(0),
+  /*  601 S> */ B(LdaConstant), U8(43),
+                B(Star), R(0),
+  /*  614 S> */ B(LdaConstant), U8(44),
+                B(Star), R(0),
+  /*  627 S> */ B(LdaConstant), U8(45),
+                B(Star), R(0),
+  /*  640 S> */ B(LdaConstant), U8(46),
+                B(Star), R(0),
+  /*  653 S> */ B(LdaConstant), U8(47),
+                B(Star), R(0),
+  /*  666 S> */ B(LdaConstant), U8(48),
+                B(Star), R(0),
+  /*  679 S> */ B(LdaConstant), U8(49),
+                B(Star), R(0),
+  /*  692 S> */ B(LdaConstant), U8(50),
+                B(Star), R(0),
+  /*  705 S> */ B(LdaConstant), U8(51),
+                B(Star), R(0),
+  /*  718 S> */ B(LdaConstant), U8(52),
+                B(Star), R(0),
+  /*  731 S> */ B(LdaConstant), U8(53),
+                B(Star), R(0),
+  /*  744 S> */ B(LdaConstant), U8(54),
+                B(Star), R(0),
+  /*  757 S> */ B(LdaConstant), U8(55),
+                B(Star), R(0),
+  /*  770 S> */ B(LdaConstant), U8(56),
+                B(Star), R(0),
+  /*  783 S> */ B(LdaConstant), U8(57),
+                B(Star), R(0),
+  /*  796 S> */ B(LdaConstant), U8(58),
+                B(Star), R(0),
+  /*  809 S> */ B(LdaConstant), U8(59),
+                B(Star), R(0),
+  /*  822 S> */ B(LdaConstant), U8(60),
+                B(Star), R(0),
+  /*  835 S> */ B(LdaConstant), U8(61),
+                B(Star), R(0),
+  /*  848 S> */ B(LdaConstant), U8(62),
+                B(Star), R(0),
+  /*  861 S> */ B(LdaConstant), U8(63),
+                B(Star), R(0),
+  /*  874 S> */ B(LdaConstant), U8(64),
+                B(Star), R(0),
+  /*  887 S> */ B(LdaConstant), U8(65),
+                B(Star), R(0),
+  /*  900 S> */ B(LdaConstant), U8(66),
+                B(Star), R(0),
+  /*  913 S> */ B(LdaConstant), U8(67),
+                B(Star), R(0),
+  /*  926 S> */ B(LdaConstant), U8(68),
+                B(Star), R(0),
+  /*  939 S> */ B(LdaConstant), U8(69),
+                B(Star), R(0),
+  /*  952 S> */ B(LdaConstant), U8(70),
+                B(Star), R(0),
+  /*  965 S> */ B(LdaConstant), U8(71),
+                B(Star), R(0),
+  /*  978 S> */ B(LdaConstant), U8(72),
+                B(Star), R(0),
+  /*  991 S> */ B(LdaConstant), U8(73),
+                B(Star), R(0),
+  /* 1004 S> */ B(LdaConstant), U8(74),
+                B(Star), R(0),
+  /* 1017 S> */ B(LdaConstant), U8(75),
+                B(Star), R(0),
+  /* 1030 S> */ B(LdaConstant), U8(76),
+                B(Star), R(0),
+  /* 1043 S> */ B(LdaConstant), U8(77),
+                B(Star), R(0),
+  /* 1056 S> */ B(LdaConstant), U8(78),
+                B(Star), R(0),
+  /* 1069 S> */ B(LdaConstant), U8(79),
+                B(Star), R(0),
+  /* 1082 S> */ B(LdaConstant), U8(80),
+                B(Star), R(0),
+  /* 1095 S> */ B(LdaConstant), U8(81),
+                B(Star), R(0),
+  /* 1108 S> */ B(LdaConstant), U8(82),
+                B(Star), R(0),
+  /* 1121 S> */ B(LdaConstant), U8(83),
+                B(Star), R(0),
+  /* 1134 S> */ B(LdaConstant), U8(84),
+                B(Star), R(0),
+  /* 1147 S> */ B(LdaConstant), U8(85),
+                B(Star), R(0),
+  /* 1160 S> */ B(LdaConstant), U8(86),
+                B(Star), R(0),
+  /* 1173 S> */ B(LdaConstant), U8(87),
+                B(Star), R(0),
+  /* 1186 S> */ B(LdaConstant), U8(88),
+                B(Star), R(0),
+  /* 1199 S> */ B(LdaConstant), U8(89),
+                B(Star), R(0),
+  /* 1212 S> */ B(LdaConstant), U8(90),
+                B(Star), R(0),
+  /* 1225 S> */ B(LdaConstant), U8(91),
+                B(Star), R(0),
+  /* 1238 S> */ B(LdaConstant), U8(92),
+                B(Star), R(0),
+  /* 1251 S> */ B(LdaConstant), U8(93),
+                B(Star), R(0),
+  /* 1264 S> */ B(LdaConstant), U8(94),
+                B(Star), R(0),
+  /* 1277 S> */ B(LdaConstant), U8(95),
+                B(Star), R(0),
+  /* 1290 S> */ B(LdaConstant), U8(96),
+                B(Star), R(0),
+  /* 1303 S> */ B(LdaConstant), U8(97),
+                B(Star), R(0),
+  /* 1316 S> */ B(LdaConstant), U8(98),
+                B(Star), R(0),
+  /* 1329 S> */ B(LdaConstant), U8(99),
+                B(Star), R(0),
+  /* 1342 S> */ B(LdaConstant), U8(100),
+                B(Star), R(0),
+  /* 1355 S> */ B(LdaConstant), U8(101),
+                B(Star), R(0),
+  /* 1368 S> */ B(LdaConstant), U8(102),
+                B(Star), R(0),
+  /* 1381 S> */ B(LdaConstant), U8(103),
+                B(Star), R(0),
+  /* 1394 S> */ B(LdaConstant), U8(104),
+                B(Star), R(0),
+  /* 1407 S> */ B(LdaConstant), U8(105),
+                B(Star), R(0),
+  /* 1420 S> */ B(LdaConstant), U8(106),
+                B(Star), R(0),
+  /* 1433 S> */ B(LdaConstant), U8(107),
+                B(Star), R(0),
+  /* 1446 S> */ B(LdaConstant), U8(108),
+                B(Star), R(0),
+  /* 1459 S> */ B(LdaConstant), U8(109),
+                B(Star), R(0),
+  /* 1472 S> */ B(LdaConstant), U8(110),
+                B(Star), R(0),
+  /* 1485 S> */ B(LdaConstant), U8(111),
+                B(Star), R(0),
+  /* 1498 S> */ B(LdaConstant), U8(112),
+                B(Star), R(0),
+  /* 1511 S> */ B(LdaConstant), U8(113),
+                B(Star), R(0),
+  /* 1524 S> */ B(LdaConstant), U8(114),
+                B(Star), R(0),
+  /* 1537 S> */ B(LdaConstant), U8(115),
+                B(Star), R(0),
+  /* 1550 S> */ B(LdaConstant), U8(116),
+                B(Star), R(0),
+  /* 1563 S> */ B(LdaConstant), U8(117),
+                B(Star), R(0),
+  /* 1576 S> */ B(LdaConstant), U8(118),
+                B(Star), R(0),
+  /* 1589 S> */ B(LdaConstant), U8(119),
+                B(Star), R(0),
+  /* 1602 S> */ B(LdaConstant), U8(120),
+                B(Star), R(0),
+  /* 1615 S> */ B(LdaConstant), U8(121),
+                B(Star), R(0),
+  /* 1628 S> */ B(LdaConstant), U8(122),
+                B(Star), R(0),
+  /* 1641 S> */ B(LdaConstant), U8(123),
+                B(Star), R(0),
+  /* 1654 S> */ B(LdaConstant), U8(124),
+                B(Star), R(0),
+  /* 1667 S> */ B(LdaConstant), U8(125),
+                B(Star), R(0),
+  /* 1680 S> */ B(LdaConstant), U8(126),
+                B(Star), R(0),
+  /* 1693 S> */ B(LdaConstant), U8(127),
+                B(Star), R(0),
+  /* 1706 S> */ B(LdaConstant), U8(128),
+                B(Star), R(0),
+  /* 1719 S> */ B(LdaConstant), U8(129),
+                B(Star), R(0),
+  /* 1732 S> */ B(LdaConstant), U8(130),
+                B(Star), R(0),
+  /* 1745 S> */ B(LdaConstant), U8(131),
+                B(Star), R(0),
+  /* 1758 S> */ B(LdaConstant), U8(132),
+                B(Star), R(0),
+  /* 1771 S> */ B(LdaConstant), U8(133),
+                B(Star), R(0),
+  /* 1784 S> */ B(LdaConstant), U8(134),
+                B(Star), R(0),
+  /* 1797 S> */ B(LdaConstant), U8(135),
+                B(Star), R(0),
+  /* 1810 S> */ B(LdaConstant), U8(136),
+                B(Star), R(0),
+  /* 1823 S> */ B(LdaConstant), U8(137),
+                B(Star), R(0),
+  /* 1836 S> */ B(LdaConstant), U8(138),
+                B(Star), R(0),
+  /* 1849 S> */ B(LdaConstant), U8(139),
+                B(Star), R(0),
+  /* 1862 S> */ B(LdaConstant), U8(140),
+                B(Star), R(0),
+  /* 1875 S> */ B(LdaConstant), U8(141),
+                B(Star), R(0),
+  /* 1888 S> */ B(LdaConstant), U8(142),
+                B(Star), R(0),
+  /* 1901 S> */ B(LdaConstant), U8(143),
+                B(Star), R(0),
+  /* 1914 S> */ B(LdaConstant), U8(144),
+                B(Star), R(0),
+  /* 1927 S> */ B(LdaConstant), U8(145),
+                B(Star), R(0),
+  /* 1940 S> */ B(LdaConstant), U8(146),
+                B(Star), R(0),
+  /* 1953 S> */ B(LdaConstant), U8(147),
+                B(Star), R(0),
+  /* 1966 S> */ B(LdaConstant), U8(148),
+                B(Star), R(0),
+  /* 1979 S> */ B(LdaConstant), U8(149),
+                B(Star), R(0),
+  /* 1992 S> */ B(LdaConstant), U8(150),
+                B(Star), R(0),
+  /* 2005 S> */ B(LdaConstant), U8(151),
+                B(Star), R(0),
+  /* 2018 S> */ B(LdaConstant), U8(152),
+                B(Star), R(0),
+  /* 2031 S> */ B(LdaConstant), U8(153),
+                B(Star), R(0),
+  /* 2044 S> */ B(LdaConstant), U8(154),
+                B(Star), R(0),
+  /* 2057 S> */ B(LdaConstant), U8(155),
+                B(Star), R(0),
+  /* 2070 S> */ B(LdaConstant), U8(156),
+                B(Star), R(0),
+  /* 2083 S> */ B(LdaConstant), U8(157),
+                B(Star), R(0),
+  /* 2096 S> */ B(LdaConstant), U8(158),
+                B(Star), R(0),
+  /* 2109 S> */ B(LdaConstant), U8(159),
+                B(Star), R(0),
+  /* 2122 S> */ B(LdaConstant), U8(160),
+                B(Star), R(0),
+  /* 2135 S> */ B(LdaConstant), U8(161),
+                B(Star), R(0),
+  /* 2148 S> */ B(LdaConstant), U8(162),
+                B(Star), R(0),
+  /* 2161 S> */ B(LdaConstant), U8(163),
+                B(Star), R(0),
+  /* 2174 S> */ B(LdaConstant), U8(164),
+                B(Star), R(0),
+  /* 2187 S> */ B(LdaConstant), U8(165),
+                B(Star), R(0),
+  /* 2200 S> */ B(LdaConstant), U8(166),
+                B(Star), R(0),
+  /* 2213 S> */ B(LdaConstant), U8(167),
+                B(Star), R(0),
+  /* 2226 S> */ B(LdaConstant), U8(168),
+                B(Star), R(0),
+  /* 2239 S> */ B(LdaConstant), U8(169),
+                B(Star), R(0),
+  /* 2252 S> */ B(LdaConstant), U8(170),
+                B(Star), R(0),
+  /* 2265 S> */ B(LdaConstant), U8(171),
+                B(Star), R(0),
+  /* 2278 S> */ B(LdaConstant), U8(172),
+                B(Star), R(0),
+  /* 2291 S> */ B(LdaConstant), U8(173),
+                B(Star), R(0),
+  /* 2304 S> */ B(LdaConstant), U8(174),
+                B(Star), R(0),
+  /* 2317 S> */ B(LdaConstant), U8(175),
+                B(Star), R(0),
+  /* 2330 S> */ B(LdaConstant), U8(176),
+                B(Star), R(0),
+  /* 2343 S> */ B(LdaConstant), U8(177),
+                B(Star), R(0),
+  /* 2356 S> */ B(LdaConstant), U8(178),
+                B(Star), R(0),
+  /* 2369 S> */ B(LdaConstant), U8(179),
+                B(Star), R(0),
+  /* 2382 S> */ B(LdaConstant), U8(180),
+                B(Star), R(0),
+  /* 2395 S> */ B(LdaConstant), U8(181),
+                B(Star), R(0),
+  /* 2408 S> */ B(LdaConstant), U8(182),
+                B(Star), R(0),
+  /* 2421 S> */ B(LdaConstant), U8(183),
+                B(Star), R(0),
+  /* 2434 S> */ B(LdaConstant), U8(184),
+                B(Star), R(0),
+  /* 2447 S> */ B(LdaConstant), U8(185),
+                B(Star), R(0),
+  /* 2460 S> */ B(LdaConstant), U8(186),
+                B(Star), R(0),
+  /* 2473 S> */ B(LdaConstant), U8(187),
+                B(Star), R(0),
+  /* 2486 S> */ B(LdaConstant), U8(188),
+                B(Star), R(0),
+  /* 2499 S> */ B(LdaConstant), U8(189),
+                B(Star), R(0),
+  /* 2512 S> */ B(LdaConstant), U8(190),
+                B(Star), R(0),
+  /* 2525 S> */ B(LdaConstant), U8(191),
+                B(Star), R(0),
+  /* 2538 S> */ B(LdaConstant), U8(192),
+                B(Star), R(0),
+  /* 2551 S> */ B(LdaConstant), U8(193),
+                B(Star), R(0),
+  /* 2564 S> */ B(LdaConstant), U8(194),
+                B(Star), R(0),
+  /* 2577 S> */ B(LdaConstant), U8(195),
+                B(Star), R(0),
+  /* 2590 S> */ B(LdaConstant), U8(196),
+                B(Star), R(0),
+  /* 2603 S> */ B(LdaConstant), U8(197),
+                B(Star), R(0),
+  /* 2616 S> */ B(LdaConstant), U8(198),
+                B(Star), R(0),
+  /* 2629 S> */ B(LdaConstant), U8(199),
+                B(Star), R(0),
+  /* 2642 S> */ B(LdaConstant), U8(200),
+                B(Star), R(0),
+  /* 2655 S> */ B(LdaConstant), U8(201),
+                B(Star), R(0),
+  /* 2668 S> */ B(LdaConstant), U8(202),
+                B(Star), R(0),
+  /* 2681 S> */ B(LdaConstant), U8(203),
+                B(Star), R(0),
+  /* 2694 S> */ B(LdaConstant), U8(204),
+                B(Star), R(0),
+  /* 2707 S> */ B(LdaConstant), U8(205),
+                B(Star), R(0),
+  /* 2720 S> */ B(LdaConstant), U8(206),
+                B(Star), R(0),
+  /* 2733 S> */ B(LdaConstant), U8(207),
+                B(Star), R(0),
+  /* 2746 S> */ B(LdaConstant), U8(208),
+                B(Star), R(0),
+  /* 2759 S> */ B(LdaConstant), U8(209),
+                B(Star), R(0),
+  /* 2772 S> */ B(LdaConstant), U8(210),
+                B(Star), R(0),
+  /* 2785 S> */ B(LdaConstant), U8(211),
+                B(Star), R(0),
+  /* 2798 S> */ B(LdaConstant), U8(212),
+                B(Star), R(0),
+  /* 2811 S> */ B(LdaConstant), U8(213),
+                B(Star), R(0),
+  /* 2824 S> */ B(LdaConstant), U8(214),
+                B(Star), R(0),
+  /* 2837 S> */ B(LdaConstant), U8(215),
+                B(Star), R(0),
+  /* 2850 S> */ B(LdaConstant), U8(216),
+                B(Star), R(0),
+  /* 2863 S> */ B(LdaConstant), U8(217),
+                B(Star), R(0),
+  /* 2876 S> */ B(LdaConstant), U8(218),
+                B(Star), R(0),
+  /* 2889 S> */ B(LdaConstant), U8(219),
+                B(Star), R(0),
+  /* 2902 S> */ B(LdaConstant), U8(220),
+                B(Star), R(0),
+  /* 2915 S> */ B(LdaConstant), U8(221),
+                B(Star), R(0),
+  /* 2928 S> */ B(LdaConstant), U8(222),
+                B(Star), R(0),
+  /* 2941 S> */ B(LdaConstant), U8(223),
+                B(Star), R(0),
+  /* 2954 S> */ B(LdaConstant), U8(224),
+                B(Star), R(0),
+  /* 2967 S> */ B(LdaConstant), U8(225),
+                B(Star), R(0),
+  /* 2980 S> */ B(LdaConstant), U8(226),
+                B(Star), R(0),
+  /* 2993 S> */ B(LdaConstant), U8(227),
+                B(Star), R(0),
+  /* 3006 S> */ B(LdaConstant), U8(228),
+                B(Star), R(0),
+  /* 3019 S> */ B(LdaConstant), U8(229),
+                B(Star), R(0),
+  /* 3032 S> */ B(LdaConstant), U8(230),
+                B(Star), R(0),
+  /* 3045 S> */ B(LdaConstant), U8(231),
+                B(Star), R(0),
+  /* 3058 S> */ B(LdaConstant), U8(232),
+                B(Star), R(0),
+  /* 3071 S> */ B(LdaConstant), U8(233),
+                B(Star), R(0),
+  /* 3084 S> */ B(LdaConstant), U8(234),
+                B(Star), R(0),
+  /* 3097 S> */ B(LdaConstant), U8(235),
+                B(Star), R(0),
+  /* 3110 S> */ B(LdaConstant), U8(236),
+                B(Star), R(0),
+  /* 3123 S> */ B(LdaConstant), U8(237),
+                B(Star), R(0),
+  /* 3136 S> */ B(LdaConstant), U8(238),
+                B(Star), R(0),
+  /* 3149 S> */ B(LdaConstant), U8(239),
+                B(Star), R(0),
+  /* 3162 S> */ B(LdaConstant), U8(240),
+                B(Star), R(0),
+  /* 3175 S> */ B(LdaConstant), U8(241),
+                B(Star), R(0),
+  /* 3188 S> */ B(LdaConstant), U8(242),
+                B(Star), R(0),
+  /* 3201 S> */ B(LdaConstant), U8(243),
+                B(Star), R(0),
+  /* 3214 S> */ B(LdaConstant), U8(244),
+                B(Star), R(0),
+  /* 3227 S> */ B(LdaConstant), U8(245),
+                B(Star), R(0),
+  /* 3240 S> */ B(LdaConstant), U8(246),
+                B(Star), R(0),
+  /* 3253 S> */ B(LdaConstant), U8(247),
+                B(Star), R(0),
+  /* 3266 S> */ B(LdaConstant), U8(248),
+                B(Star), R(0),
+  /* 3279 S> */ B(LdaConstant), U8(249),
+                B(Star), R(0),
+  /* 3292 S> */ B(LdaConstant), U8(250),
+                B(Star), R(0),
+  /* 3305 S> */ B(LdaConstant), U8(251),
+                B(Star), R(0),
+  /* 3318 S> */ B(LdaConstant), U8(252),
+                B(Star), R(0),
+  /* 3331 S> */ B(LdaConstant), U8(253),
+                B(Star), R(0),
+  /* 3344 S> */ B(LdaConstant), U8(254),
+                B(Star), R(0),
+  /* 3357 S> */ B(LdaConstant), U8(255),
+                B(Star), R(0),
+  /* 3370 S> */ B(Wide), B(LdaConstant), U16(256),
+                B(Star), R(0),
+  /* 3383 S> */ B(Wide), B(LdaConstant), U16(257),
+                B(Star), R(0),
+  /* 3396 S> */ B(Wide), B(LdaConstant), U16(258),
+                B(Star), R(0),
+  /* 3409 S> */ B(Wide), B(LdaConstant), U16(259),
+                B(Star), R(0),
+  /* 3422 S> */ B(Wide), B(LdaConstant), U16(260),
+                B(Star), R(0),
+  /* 3435 S> */ B(Wide), B(LdaConstant), U16(261),
+                B(Star), R(0),
+  /* 3448 S> */ B(Wide), B(LdaConstant), U16(262),
+                B(Star), R(0),
+  /* 3461 S> */ B(Wide), B(LdaConstant), U16(263),
+                B(Star), R(0),
+  /* 3474 S> */ B(Wide), B(LdaConstant), U16(264),
+                B(Star), R(0),
+  /* 3487 S> */ B(Wide), B(LdaConstant), U16(265),
+                B(Star), R(0),
+  /* 3500 S> */ B(Wide), B(LdaConstant), U16(266),
+                B(Star), R(0),
+  /* 3513 S> */ B(Wide), B(LdaConstant), U16(267),
+                B(Star), R(0),
+  /* 3526 S> */ B(Wide), B(LdaConstant), U16(268),
+                B(Star), R(0),
+  /* 3539 S> */ B(Wide), B(LdaConstant), U16(269),
+                B(Star), R(0),
+  /* 3552 S> */ B(Wide), B(LdaConstant), U16(270),
+                B(Star), R(0),
+  /* 3565 S> */ B(Wide), B(LdaConstant), U16(271),
+                B(Star), R(0),
+  /* 3578 S> */ B(Wide), B(LdaConstant), U16(272),
+                B(Star), R(0),
+  /* 3591 S> */ B(Wide), B(LdaConstant), U16(273),
+                B(Star), R(0),
+  /* 3604 S> */ B(Wide), B(LdaConstant), U16(274),
+                B(Star), R(0),
+  /* 3617 S> */ B(Wide), B(LdaConstant), U16(275),
+                B(Star), R(0),
+  /* 3630 S> */ B(Wide), B(LdaConstant), U16(276),
+                B(Star), R(0),
+  /* 3643 S> */ B(Wide), B(LdaConstant), U16(277),
+                B(Star), R(0),
+  /* 3656 S> */ B(Wide), B(LdaConstant), U16(278),
+                B(Star), R(0),
+  /* 3669 S> */ B(Wide), B(LdaConstant), U16(279),
+                B(Star), R(0),
+  /* 3682 S> */ B(Wide), B(LdaConstant), U16(280),
+                B(Star), R(0),
+  /* 3695 S> */ B(Wide), B(LdaConstant), U16(281),
+                B(Star), R(0),
+  /* 3708 S> */ B(Wide), B(LdaConstant), U16(282),
+                B(Star), R(0),
+  /* 3721 S> */ B(Wide), B(LdaConstant), U16(283),
+                B(Star), R(0),
+  /* 3734 S> */ B(Wide), B(LdaConstant), U16(284),
+                B(Star), R(0),
+  /* 3747 S> */ B(Wide), B(LdaConstant), U16(285),
+                B(Star), R(0),
+  /* 3760 S> */ B(Wide), B(LdaConstant), U16(286),
+                B(Star), R(0),
+  /* 3773 S> */ B(Wide), B(LdaConstant), U16(287),
+                B(Star), R(0),
+  /* 3786 S> */ B(Wide), B(LdaConstant), U16(288),
+                B(Star), R(0),
+  /* 3799 S> */ B(Wide), B(LdaConstant), U16(289),
+                B(Star), R(0),
+  /* 3812 S> */ B(Wide), B(LdaConstant), U16(290),
+                B(Star), R(0),
+  /* 3825 S> */ B(Wide), B(LdaConstant), U16(291),
+                B(Star), R(0),
+  /* 3838 S> */ B(Wide), B(LdaConstant), U16(292),
+                B(Star), R(0),
+  /* 3851 S> */ B(Wide), B(LdaConstant), U16(293),
+                B(Star), R(0),
+  /* 3864 S> */ B(Wide), B(LdaConstant), U16(294),
+                B(Star), R(0),
+  /* 3877 S> */ B(Wide), B(LdaConstant), U16(295),
+                B(Star), R(0),
+  /* 3890 S> */ B(Wide), B(LdaConstant), U16(296),
+                B(Star), R(0),
+  /* 3903 S> */ B(Wide), B(LdaConstant), U16(297),
+                B(Star), R(0),
+  /* 3916 S> */ B(Wide), B(LdaConstant), U16(298),
+                B(Star), R(0),
+  /* 3929 S> */ B(Wide), B(LdaConstant), U16(299),
+                B(Star), R(0),
+  /* 3942 S> */ B(Wide), B(LdaConstant), U16(300),
+                B(Star), R(0),
+  /* 3955 S> */ B(Wide), B(LdaConstant), U16(301),
+                B(Star), R(0),
+  /* 3968 S> */ B(Wide), B(LdaConstant), U16(302),
+                B(Star), R(0),
+  /* 3981 S> */ B(Wide), B(LdaConstant), U16(303),
+                B(Star), R(0),
+  /* 3994 S> */ B(Wide), B(LdaConstant), U16(304),
+                B(Star), R(0),
+  /* 4007 S> */ B(Wide), B(LdaConstant), U16(305),
+                B(Star), R(0),
+  /* 4020 S> */ B(Wide), B(LdaConstant), U16(306),
+                B(Star), R(0),
+  /* 4033 S> */ B(Wide), B(LdaConstant), U16(307),
+                B(Star), R(0),
+  /* 4046 S> */ B(Wide), B(LdaConstant), U16(308),
+                B(Star), R(0),
+  /* 4059 S> */ B(Wide), B(LdaConstant), U16(309),
+                B(Star), R(0),
+  /* 4072 S> */ B(Wide), B(LdaConstant), U16(310),
+                B(Star), R(0),
+  /* 4085 S> */ B(Wide), B(LdaConstant), U16(311),
+                B(Star), R(0),
+  /* 4103 S> */ B(LdaZero),
+                B(Star), R(1),
+  /* 4108 S> */ B(LdaSmi), U8(3),
+  /* 4108 E> */ B(TestLessThan), R(1),
+                B(Wide), B(JumpIfFalse), U16(38),
+  /* 4090 E> */ B(StackCheck),
+  /* 4122 S> */ B(LdaSmi), U8(1),
+  /* 4128 E> */ B(TestEqual), R(1),
+                B(Wide), B(JumpIfFalse), U16(7),
+  /* 4134 S> */ B(Wide), B(Jump), U16(15),
+  /* 4146 S> */ B(LdaSmi), U8(2),
+  /* 4152 E> */ B(TestEqual), R(1),
+                B(Wide), B(JumpIfFalse), U16(7),
+  /* 4158 S> */ B(Wide), B(Jump), U16(13),
+  /* 4114 S> */ B(Ldar), R(1),
+                B(ToNumber),
+                B(Star), R(2),
+                B(Inc),
+                B(Star), R(1),
+                B(Jump), U8(-41),
+  /* 4167 S> */ B(LdaSmi), U8(3),
+  /* 4177 S> */ B(Return),
 ]
 constant pool: [
   0.1,
diff --git a/test/cctest/interpreter/bytecode_expectations/LetVariable.golden b/test/cctest/interpreter/bytecode_expectations/LetVariable.golden
index 5ceda85..e54769c 100644
--- a/test/cctest/interpreter/bytecode_expectations/LetVariable.golden
+++ b/test/cctest/interpreter/bytecode_expectations/LetVariable.golden
@@ -15,13 +15,13 @@
 parameter count: 1
 bytecode array length: 10
 bytecodes: [
-  B(LdaTheHole),
-  B(Star), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(Star), R(0),
-  B(LdaUndefined),
-  B(Return),
+                B(LdaTheHole),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(10),
+                B(Star), R(0),
+                B(LdaUndefined),
+  /*   46 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -36,16 +36,16 @@
 parameter count: 1
 bytecode array length: 20
 bytecodes: [
-  B(LdaTheHole),
-  B(Star), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(Star), R(0),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(0),
-  B(Star), R(1),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(1), U8(1),
-  B(Return),
+                B(LdaTheHole),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(10),
+                B(Star), R(0),
+  /*   46 S> */ B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(0),
+                B(Star), R(1),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(1), U8(1),
+  /*   56 S> */ B(Return),
 ]
 constant pool: [
   "x",
@@ -59,22 +59,22 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 27
+bytecode array length: 28
 bytecodes: [
-  B(LdaTheHole),
-  B(Star), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(20),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(0),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
-  B(Ldar), R(1),
-  B(Star), R(0),
-  B(LdaUndefined),
-  B(Return),
+                B(LdaTheHole),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   45 S> */ B(LdaSmi), U8(20),
+                B(Star), R(1),
+                B(Ldar), R(0),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(0),
+                B(Star), R(2),
+  /*   45 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
+                B(Mov), R(1), R(0),
+                B(Ldar), R(0),
+                B(LdaUndefined),
+  /*   52 S> */ B(Return),
 ]
 constant pool: [
   "x",
@@ -88,24 +88,23 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 31
+bytecode array length: 30
 bytecodes: [
-  B(LdaTheHole),
-  B(Star), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(Star), R(0),
-  B(LdaSmi), U8(20),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(0),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
-  B(Ldar), R(1),
-  B(Star), R(0),
-  B(LdaUndefined),
-  B(Return),
+                B(LdaTheHole),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(10),
+                B(Star), R(0),
+  /*   46 S> */ B(LdaSmi), U8(20),
+                B(Star), R(1),
+                B(Ldar), R(0),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(0),
+                B(Star), R(2),
+  /*   48 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
+                B(Mov), R(1), R(0),
+                B(LdaUndefined),
+  /*   54 S> */ B(Return),
 ]
 constant pool: [
   "x",
diff --git a/test/cctest/interpreter/bytecode_expectations/LetVariableContextSlot.golden b/test/cctest/interpreter/bytecode_expectations/LetVariableContextSlot.golden
index 4fc5c4f..4725033 100644
--- a/test/cctest/interpreter/bytecode_expectations/LetVariableContextSlot.golden
+++ b/test/cctest/interpreter/bytecode_expectations/LetVariableContextSlot.golden
@@ -15,17 +15,17 @@
 parameter count: 1
 bytecode array length: 24
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(1),
-  B(LdaTheHole),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaUndefined),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(1),
+                B(LdaTheHole),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateClosure), U8(0), U8(0),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(10),
+  /*   42 E> */ B(StaContextSlot), R(context), U8(4),
+                B(LdaUndefined),
+  /*   72 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -41,21 +41,21 @@
 parameter count: 1
 bytecode array length: 37
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(1),
-  B(LdaTheHole),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaContextSlot), R(context), U8(4),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(1),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(1),
+                B(LdaTheHole),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateClosure), U8(0), U8(0),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(10),
+  /*   42 E> */ B(StaContextSlot), R(context), U8(4),
+  /*   72 S> */ B(LdaContextSlot), R(context), U8(4),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(1),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1),
+  /*   82 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -72,25 +72,25 @@
 parameter count: 1
 bytecode array length: 45
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(1),
-  B(LdaTheHole),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(20),
-  B(Star), R(2),
-  B(LdaContextSlot), R(context), U8(4),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(1),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
-  B(Ldar), R(2),
-  B(StaContextSlot), R(context), U8(4),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaUndefined),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(1),
+                B(LdaTheHole),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateClosure), U8(0), U8(0),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   45 S> */ B(LdaSmi), U8(20),
+                B(Star), R(2),
+  /*   45 E> */ B(LdaContextSlot), R(context), U8(4),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(1),
+                B(Star), R(3),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
+                B(Ldar), R(2),
+                B(StaContextSlot), R(context), U8(4),
+  /*   45 E> */ B(StaContextSlot), R(context), U8(4),
+                B(LdaUndefined),
+  /*   78 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
@@ -107,26 +107,26 @@
 parameter count: 1
 bytecode array length: 47
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(1),
-  B(LdaTheHole),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateClosure), U8(0), U8(0),
-  B(Star), R(0),
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaSmi), U8(20),
-  B(Star), R(2),
-  B(LdaContextSlot), R(context), U8(4),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(1),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
-  B(Ldar), R(2),
-  B(StaContextSlot), R(context), U8(4),
-  B(LdaUndefined),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(1),
+                B(LdaTheHole),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateClosure), U8(0), U8(0),
+                B(Star), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(10),
+  /*   42 E> */ B(StaContextSlot), R(context), U8(4),
+  /*   46 S> */ B(LdaSmi), U8(20),
+                B(Star), R(2),
+  /*   48 E> */ B(LdaContextSlot), R(context), U8(4),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(1),
+                B(Star), R(3),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
+                B(Ldar), R(2),
+                B(StaContextSlot), R(context), U8(4),
+                B(LdaUndefined),
+  /*   80 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::SHARED_FUNCTION_INFO_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/LoadGlobal.golden b/test/cctest/interpreter/bytecode_expectations/LoadGlobal.golden
index 0a96cae..dd9f714 100644
--- a/test/cctest/interpreter/bytecode_expectations/LoadGlobal.golden
+++ b/test/cctest/interpreter/bytecode_expectations/LoadGlobal.golden
@@ -16,14 +16,13 @@
 "
 frame size: 0
 parameter count: 1
-bytecode array length: 5
+bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaGlobal), U8(0), U8(1),
-  B(Return),
+  /*   21 E> */ B(StackCheck),
+  /*   26 S> */ B(LdaGlobal), U8(1),
+  /*   36 S> */ B(Return),
 ]
 constant pool: [
-  "a",
 ]
 handlers: [
 ]
@@ -36,14 +35,13 @@
 "
 frame size: 0
 parameter count: 1
-bytecode array length: 5
+bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaGlobal), U8(0), U8(1),
-  B(Return),
+  /*   27 E> */ B(StackCheck),
+  /*   32 S> */ B(LdaGlobal), U8(1),
+  /*   42 S> */ B(Return),
 ]
 constant pool: [
-  "t",
 ]
 handlers: [
 ]
@@ -56,14 +54,13 @@
 "
 frame size: 0
 parameter count: 1
-bytecode array length: 5
+bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaGlobal), U8(0), U8(1),
-  B(Return),
+  /*   17 E> */ B(StackCheck),
+  /*   22 S> */ B(LdaGlobal), U8(1),
+  /*   32 S> */ B(Return),
 ]
 constant pool: [
-  "a",
 ]
 handlers: [
 ]
@@ -204,401 +201,272 @@
   }
   f({name: 1});
 "
-frame size: 1
+frame size: 0
 parameter count: 2
-bytecode array length: 1032
+bytecode array length: 646
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(1),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(3),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(5),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(7),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(9),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(11),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(13),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(15),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(17),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(19),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(21),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(23),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(25),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(27),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(29),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(31),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(33),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(35),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(37),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(39),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(41),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(43),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(45),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(47),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(49),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(51),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(53),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(55),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(57),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(59),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(61),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(63),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(65),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(67),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(69),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(71),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(73),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(75),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(77),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(79),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(81),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(83),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(85),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(87),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(89),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(91),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(93),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(95),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(97),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(99),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(101),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(103),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(105),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(107),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(109),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(111),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(113),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(115),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(117),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(119),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(121),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(123),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(125),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(127),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(129),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(131),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(133),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(135),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(137),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(139),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(141),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(143),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(145),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(147),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(149),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(151),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(153),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(155),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(157),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(159),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(161),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(163),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(165),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(167),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(169),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(171),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(173),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(175),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(177),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(179),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(181),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(183),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(185),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(187),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(189),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(191),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(193),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(195),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(197),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(199),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(201),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(203),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(205),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(207),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(209),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(211),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(213),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(215),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(217),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(219),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(221),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(223),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(225),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(227),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(229),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(231),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(233),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(235),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(237),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(239),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(241),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(243),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(245),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(247),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(249),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(251),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(253),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(255),
-  B(Wide), B(LdaGlobal), U16(1), U16(257),
-  B(Return),
+  /*   17 E> */ B(StackCheck),
+  /*   25 S> */ B(Nop),
+  /*   26 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(1),
+  /*   35 S> */ B(Nop),
+  /*   36 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(3),
+  /*   45 S> */ B(Nop),
+  /*   46 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(5),
+  /*   55 S> */ B(Nop),
+  /*   56 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(7),
+  /*   65 S> */ B(Nop),
+  /*   66 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(9),
+  /*   75 S> */ B(Nop),
+  /*   76 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(11),
+  /*   85 S> */ B(Nop),
+  /*   86 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(13),
+  /*   95 S> */ B(Nop),
+  /*   96 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(15),
+  /*  105 S> */ B(Nop),
+  /*  106 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(17),
+  /*  115 S> */ B(Nop),
+  /*  116 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(19),
+  /*  125 S> */ B(Nop),
+  /*  126 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(21),
+  /*  135 S> */ B(Nop),
+  /*  136 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(23),
+  /*  145 S> */ B(Nop),
+  /*  146 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(25),
+  /*  155 S> */ B(Nop),
+  /*  156 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(27),
+  /*  165 S> */ B(Nop),
+  /*  166 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(29),
+  /*  175 S> */ B(Nop),
+  /*  176 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(31),
+  /*  185 S> */ B(Nop),
+  /*  186 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(33),
+  /*  195 S> */ B(Nop),
+  /*  196 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(35),
+  /*  205 S> */ B(Nop),
+  /*  206 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(37),
+  /*  215 S> */ B(Nop),
+  /*  216 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(39),
+  /*  225 S> */ B(Nop),
+  /*  226 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(41),
+  /*  235 S> */ B(Nop),
+  /*  236 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(43),
+  /*  245 S> */ B(Nop),
+  /*  246 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(45),
+  /*  255 S> */ B(Nop),
+  /*  256 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(47),
+  /*  265 S> */ B(Nop),
+  /*  266 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(49),
+  /*  275 S> */ B(Nop),
+  /*  276 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(51),
+  /*  285 S> */ B(Nop),
+  /*  286 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(53),
+  /*  295 S> */ B(Nop),
+  /*  296 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(55),
+  /*  305 S> */ B(Nop),
+  /*  306 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(57),
+  /*  315 S> */ B(Nop),
+  /*  316 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(59),
+  /*  325 S> */ B(Nop),
+  /*  326 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(61),
+  /*  335 S> */ B(Nop),
+  /*  336 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(63),
+  /*  345 S> */ B(Nop),
+  /*  346 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(65),
+  /*  355 S> */ B(Nop),
+  /*  356 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(67),
+  /*  365 S> */ B(Nop),
+  /*  366 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(69),
+  /*  375 S> */ B(Nop),
+  /*  376 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(71),
+  /*  385 S> */ B(Nop),
+  /*  386 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(73),
+  /*  395 S> */ B(Nop),
+  /*  396 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(75),
+  /*  405 S> */ B(Nop),
+  /*  406 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(77),
+  /*  415 S> */ B(Nop),
+  /*  416 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(79),
+  /*  425 S> */ B(Nop),
+  /*  426 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(81),
+  /*  435 S> */ B(Nop),
+  /*  436 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(83),
+  /*  445 S> */ B(Nop),
+  /*  446 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(85),
+  /*  455 S> */ B(Nop),
+  /*  456 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(87),
+  /*  465 S> */ B(Nop),
+  /*  466 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(89),
+  /*  475 S> */ B(Nop),
+  /*  476 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(91),
+  /*  485 S> */ B(Nop),
+  /*  486 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(93),
+  /*  495 S> */ B(Nop),
+  /*  496 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(95),
+  /*  505 S> */ B(Nop),
+  /*  506 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(97),
+  /*  515 S> */ B(Nop),
+  /*  516 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(99),
+  /*  525 S> */ B(Nop),
+  /*  526 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(101),
+  /*  535 S> */ B(Nop),
+  /*  536 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(103),
+  /*  545 S> */ B(Nop),
+  /*  546 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(105),
+  /*  555 S> */ B(Nop),
+  /*  556 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(107),
+  /*  565 S> */ B(Nop),
+  /*  566 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(109),
+  /*  575 S> */ B(Nop),
+  /*  576 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(111),
+  /*  585 S> */ B(Nop),
+  /*  586 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(113),
+  /*  595 S> */ B(Nop),
+  /*  596 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(115),
+  /*  605 S> */ B(Nop),
+  /*  606 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(117),
+  /*  615 S> */ B(Nop),
+  /*  616 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(119),
+  /*  625 S> */ B(Nop),
+  /*  626 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(121),
+  /*  635 S> */ B(Nop),
+  /*  636 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(123),
+  /*  645 S> */ B(Nop),
+  /*  646 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(125),
+  /*  655 S> */ B(Nop),
+  /*  656 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(127),
+  /*  665 S> */ B(Nop),
+  /*  666 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(129),
+  /*  675 S> */ B(Nop),
+  /*  676 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(131),
+  /*  685 S> */ B(Nop),
+  /*  686 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(133),
+  /*  695 S> */ B(Nop),
+  /*  696 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(135),
+  /*  705 S> */ B(Nop),
+  /*  706 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(137),
+  /*  715 S> */ B(Nop),
+  /*  716 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(139),
+  /*  725 S> */ B(Nop),
+  /*  726 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(141),
+  /*  735 S> */ B(Nop),
+  /*  736 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(143),
+  /*  745 S> */ B(Nop),
+  /*  746 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(145),
+  /*  755 S> */ B(Nop),
+  /*  756 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(147),
+  /*  765 S> */ B(Nop),
+  /*  766 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(149),
+  /*  775 S> */ B(Nop),
+  /*  776 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(151),
+  /*  785 S> */ B(Nop),
+  /*  786 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(153),
+  /*  795 S> */ B(Nop),
+  /*  796 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(155),
+  /*  805 S> */ B(Nop),
+  /*  806 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(157),
+  /*  815 S> */ B(Nop),
+  /*  816 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(159),
+  /*  825 S> */ B(Nop),
+  /*  826 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(161),
+  /*  835 S> */ B(Nop),
+  /*  836 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(163),
+  /*  845 S> */ B(Nop),
+  /*  846 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(165),
+  /*  855 S> */ B(Nop),
+  /*  856 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(167),
+  /*  865 S> */ B(Nop),
+  /*  866 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(169),
+  /*  875 S> */ B(Nop),
+  /*  876 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(171),
+  /*  885 S> */ B(Nop),
+  /*  886 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(173),
+  /*  895 S> */ B(Nop),
+  /*  896 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(175),
+  /*  905 S> */ B(Nop),
+  /*  906 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(177),
+  /*  915 S> */ B(Nop),
+  /*  916 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(179),
+  /*  925 S> */ B(Nop),
+  /*  926 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(181),
+  /*  935 S> */ B(Nop),
+  /*  936 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(183),
+  /*  945 S> */ B(Nop),
+  /*  946 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(185),
+  /*  955 S> */ B(Nop),
+  /*  956 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(187),
+  /*  965 S> */ B(Nop),
+  /*  966 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(189),
+  /*  975 S> */ B(Nop),
+  /*  976 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(191),
+  /*  985 S> */ B(Nop),
+  /*  986 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(193),
+  /*  995 S> */ B(Nop),
+  /*  996 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(195),
+  /* 1005 S> */ B(Nop),
+  /* 1006 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(197),
+  /* 1015 S> */ B(Nop),
+  /* 1016 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(199),
+  /* 1025 S> */ B(Nop),
+  /* 1026 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(201),
+  /* 1035 S> */ B(Nop),
+  /* 1036 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(203),
+  /* 1045 S> */ B(Nop),
+  /* 1046 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(205),
+  /* 1055 S> */ B(Nop),
+  /* 1056 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(207),
+  /* 1065 S> */ B(Nop),
+  /* 1066 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(209),
+  /* 1075 S> */ B(Nop),
+  /* 1076 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(211),
+  /* 1085 S> */ B(Nop),
+  /* 1086 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(213),
+  /* 1095 S> */ B(Nop),
+  /* 1096 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(215),
+  /* 1105 S> */ B(Nop),
+  /* 1106 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(217),
+  /* 1115 S> */ B(Nop),
+  /* 1116 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(219),
+  /* 1125 S> */ B(Nop),
+  /* 1126 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(221),
+  /* 1135 S> */ B(Nop),
+  /* 1136 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(223),
+  /* 1145 S> */ B(Nop),
+  /* 1146 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(225),
+  /* 1155 S> */ B(Nop),
+  /* 1156 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(227),
+  /* 1165 S> */ B(Nop),
+  /* 1166 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(229),
+  /* 1175 S> */ B(Nop),
+  /* 1176 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(231),
+  /* 1185 S> */ B(Nop),
+  /* 1186 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(233),
+  /* 1195 S> */ B(Nop),
+  /* 1196 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(235),
+  /* 1205 S> */ B(Nop),
+  /* 1206 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(237),
+  /* 1215 S> */ B(Nop),
+  /* 1216 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(239),
+  /* 1225 S> */ B(Nop),
+  /* 1226 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(241),
+  /* 1235 S> */ B(Nop),
+  /* 1236 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(243),
+  /* 1245 S> */ B(Nop),
+  /* 1246 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(245),
+  /* 1255 S> */ B(Nop),
+  /* 1256 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(247),
+  /* 1265 S> */ B(Nop),
+  /* 1266 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(249),
+  /* 1275 S> */ B(Nop),
+  /* 1276 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(251),
+  /* 1285 S> */ B(Nop),
+  /* 1286 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(253),
+  /* 1295 S> */ B(Nop),
+  /* 1296 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(255),
+  /* 1305 S> */ B(Wide), B(LdaGlobal), U16(257),
+  /* 1315 S> */ B(Return),
 ]
 constant pool: [
   "name",
-  "a",
 ]
 handlers: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/LogicalExpressions.golden b/test/cctest/interpreter/bytecode_expectations/LogicalExpressions.golden
index cddb9a1..b8c8c5f 100644
--- a/test/cctest/interpreter/bytecode_expectations/LogicalExpressions.golden
+++ b/test/cctest/interpreter/bytecode_expectations/LogicalExpressions.golden
@@ -15,12 +15,12 @@
 parameter count: 1
 bytecode array length: 9
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(JumpIfToBooleanTrue), U8(4),
-  B(LdaSmi), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   45 S> */ B(JumpIfToBooleanTrue), U8(4),
+                B(LdaSmi), U8(3),
+  /*   60 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -31,19 +31,18 @@
 snippet: "
   var x = 0; return (x == 1) || 3;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 15
+bytecode array length: 13
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(TestEqual), R(1),
-  B(JumpIfTrue), U8(4),
-  B(LdaSmi), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(1),
+  /*   55 E> */ B(TestEqual), R(0),
+                B(JumpIfTrue), U8(4),
+                B(LdaSmi), U8(3),
+  /*   67 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -58,12 +57,12 @@
 parameter count: 1
 bytecode array length: 9
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(JumpIfToBooleanFalse), U8(4),
-  B(LdaSmi), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   45 S> */ B(JumpIfToBooleanFalse), U8(4),
+                B(LdaSmi), U8(3),
+  /*   60 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -74,19 +73,18 @@
 snippet: "
   var x = 0; return (x == 0) && 3;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 14
+bytecode array length: 12
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaZero),
-  B(TestEqual), R(1),
-  B(JumpIfFalse), U8(4),
-  B(LdaSmi), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaZero),
+  /*   55 E> */ B(TestEqual), R(0),
+                B(JumpIfFalse), U8(4),
+                B(LdaSmi), U8(3),
+  /*   67 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -101,12 +99,12 @@
 parameter count: 1
 bytecode array length: 9
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(JumpIfToBooleanTrue), U8(4),
-  B(LdaSmi), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   45 S> */ B(JumpIfToBooleanTrue), U8(4),
+                B(LdaSmi), U8(3),
+  /*   68 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -119,25 +117,21 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 32
+bytecode array length: 24
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(2),
-  B(Star), R(0),
-  B(LdaSmi), U8(3),
-  B(Star), R(1),
-  B(LdaSmi), U8(4),
-  B(Star), R(2),
-  B(Ldar), R(0),
-  B(JumpIfToBooleanTrue), U8(16),
-  B(Ldar), R(0),
-  B(Ldar), R(1),
-  B(Ldar), R(0),
-  B(Ldar), R(1),
-  B(LdaSmi), U8(5),
-  B(Star), R(2),
-  B(LdaSmi), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(2),
+                B(Star), R(0),
+  /*   49 S> */ B(LdaSmi), U8(3),
+                B(Star), R(1),
+  /*   56 S> */ B(LdaSmi), U8(4),
+                B(Star), R(2),
+  /*   59 S> */ B(Ldar), R(0),
+                B(JumpIfToBooleanTrue), U8(8),
+                B(LdaSmi), U8(5),
+                B(Star), R(2),
+                B(LdaSmi), U8(3),
+  /*   95 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -184,145 +178,145 @@
 parameter count: 1
 bytecode array length: 276
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(Star), R(2),
-  B(Ldar), R(0),
-  B(JumpIfToBooleanTrueConstant), U8(0),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   53 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*   60 S> */ B(LdaSmi), U8(3),
+                B(Star), R(2),
+  /*   63 S> */ B(Ldar), R(0),
+                B(JumpIfToBooleanTrueConstant), U8(0),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(3),
+  /*  624 S> */ B(Return),
 ]
 constant pool: [
   260,
@@ -370,145 +364,145 @@
 parameter count: 1
 bytecode array length: 275
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(Star), R(2),
-  B(Ldar), R(0),
-  B(JumpIfToBooleanFalseConstant), U8(0),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   53 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*   60 S> */ B(LdaSmi), U8(3),
+                B(Star), R(2),
+  /*   63 S> */ B(Ldar), R(0),
+                B(JumpIfToBooleanFalseConstant), U8(0),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(3),
+  /*  624 S> */ B(Return),
 ]
 constant pool: [
   260,
@@ -552,152 +546,150 @@
     a = 1, b = 2, 
     a = 1, b = 2, 3);
 "
-frame size: 4
+frame size: 3
 parameter count: 1
-bytecode array length: 282
+bytecode array length: 278
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(Star), R(2),
-  B(Ldar), R(0),
-  B(Star), R(3),
-  B(LdaSmi), U8(3),
-  B(TestGreaterThan), R(3),
-  B(JumpIfTrueConstant), U8(0),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   53 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*   60 S> */ B(LdaSmi), U8(3),
+                B(Star), R(2),
+  /*   63 S> */ B(LdaSmi), U8(3),
+  /*   73 E> */ B(TestGreaterThan), R(0),
+                B(JumpIfTrueConstant), U8(0),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(3),
+  /*  630 S> */ B(Return),
 ]
 constant pool: [
   260,
@@ -741,152 +733,150 @@
     a = 1, b = 2, 
     a = 1, b = 2, 3);
 "
-frame size: 4
+frame size: 3
 parameter count: 1
-bytecode array length: 281
+bytecode array length: 277
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(Star), R(2),
-  B(Ldar), R(0),
-  B(Star), R(3),
-  B(LdaSmi), U8(5),
-  B(TestLessThan), R(3),
-  B(JumpIfFalseConstant), U8(0),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(LdaSmi), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   53 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*   60 S> */ B(LdaSmi), U8(3),
+                B(Star), R(2),
+  /*   63 S> */ B(LdaSmi), U8(5),
+  /*   73 E> */ B(TestLessThan), R(0),
+                B(JumpIfFalseConstant), U8(0),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(2),
+                B(Star), R(2),
+                B(LdaSmi), U8(3),
+  /*  630 S> */ B(Return),
 ]
 constant pool: [
   260,
@@ -902,9 +892,9 @@
 parameter count: 1
 bytecode array length: 3
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaZero),
+  /*   49 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -919,9 +909,9 @@
 parameter count: 1
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaSmi), U8(1),
+  /*   49 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -936,15 +926,15 @@
 parameter count: 1
 bytecode array length: 15
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(JumpIfToBooleanFalse), U8(4),
-  B(LdaSmi), U8(3),
-  B(JumpIfToBooleanTrue), U8(3),
-  B(LdaZero),
-  B(LdaSmi), U8(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(JumpIfToBooleanFalse), U8(4),
+                B(LdaSmi), U8(3),
+                B(JumpIfToBooleanTrue), U8(3),
+                B(LdaZero),
+                B(LdaSmi), U8(1),
+  /*   68 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/LookupSlot.golden b/test/cctest/interpreter/bytecode_expectations/LookupSlot.golden
index acec42f..0ce9f01 100644
--- a/test/cctest/interpreter/bytecode_expectations/LookupSlot.golden
+++ b/test/cctest/interpreter/bytecode_expectations/LookupSlot.golden
@@ -11,36 +11,38 @@
 snippet: "
   eval('var x = 10;'); return x;
 "
-frame size: 9
+frame size: 10
 parameter count: 1
-bytecode array length: 67
+bytecode array length: 71
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(0),
-  B(Ldar), R(this),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateMappedArguments),
-  B(StaContextSlot), R(context), U8(5),
-  B(Ldar), R(new_target),
-  B(StaContextSlot), R(context), U8(6),
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(3),
-  B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(3), U8(1), R(1),
-  B(LdaConstant), U8(1),
-  B(Star), R(3),
-  B(Mov), R(1), R(4),
-  B(Mov), R(3), R(5),
-  B(Mov), R(closure), R(6),
-  B(LdaZero),
-  B(Star), R(7),
-  B(LdaSmi), U8(30),
-  B(Star), R(8),
-  B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(5),
-  B(Star), R(1),
-  B(Call), R(1), R(2), U8(2), U8(0),
-  B(LdaLookupSlot), U8(2),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+                B(Ldar), R(this),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateMappedArguments),
+                B(StaContextSlot), R(context), U8(5),
+                B(Ldar), R(new_target),
+                B(StaContextSlot), R(context), U8(6),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaConstant), U8(0),
+                B(Star), R(3),
+                B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(3), U8(1), R(1),
+                B(LdaConstant), U8(1),
+                B(Star), R(3),
+                B(LdaZero),
+                B(Star), R(7),
+                B(LdaSmi), U8(30),
+                B(Star), R(8),
+                B(LdaSmi), U8(34),
+                B(Star), R(9),
+                B(Mov), R(1), R(4),
+                B(Mov), R(3), R(5),
+                B(Mov), R(closure), R(6),
+                B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6),
+                B(Star), R(1),
+  /*   34 E> */ B(Call), R(1), R(2), U8(2), U8(0),
+  /*   55 S> */ B(LdaLookupSlot), U8(2),
+  /*   65 S> */ B(Return),
 ]
 constant pool: [
   "eval",
@@ -54,37 +56,39 @@
 snippet: "
   eval('var x = 10;'); return typeof x;
 "
-frame size: 9
+frame size: 10
 parameter count: 1
-bytecode array length: 68
+bytecode array length: 72
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(0),
-  B(Ldar), R(this),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateMappedArguments),
-  B(StaContextSlot), R(context), U8(5),
-  B(Ldar), R(new_target),
-  B(StaContextSlot), R(context), U8(6),
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(3),
-  B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(3), U8(1), R(1),
-  B(LdaConstant), U8(1),
-  B(Star), R(3),
-  B(Mov), R(1), R(4),
-  B(Mov), R(3), R(5),
-  B(Mov), R(closure), R(6),
-  B(LdaZero),
-  B(Star), R(7),
-  B(LdaSmi), U8(30),
-  B(Star), R(8),
-  B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(5),
-  B(Star), R(1),
-  B(Call), R(1), R(2), U8(2), U8(0),
-  B(LdaLookupSlotInsideTypeof), U8(2),
-  B(TypeOf),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+                B(Ldar), R(this),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateMappedArguments),
+                B(StaContextSlot), R(context), U8(5),
+                B(Ldar), R(new_target),
+                B(StaContextSlot), R(context), U8(6),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaConstant), U8(0),
+                B(Star), R(3),
+                B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(3), U8(1), R(1),
+                B(LdaConstant), U8(1),
+                B(Star), R(3),
+                B(LdaZero),
+                B(Star), R(7),
+                B(LdaSmi), U8(30),
+                B(Star), R(8),
+                B(LdaSmi), U8(34),
+                B(Star), R(9),
+                B(Mov), R(1), R(4),
+                B(Mov), R(3), R(5),
+                B(Mov), R(closure), R(6),
+                B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6),
+                B(Star), R(1),
+  /*   34 E> */ B(Call), R(1), R(2), U8(2), U8(0),
+  /*   55 S> */ B(LdaLookupSlotInsideTypeof), U8(2),
+                B(TypeOf),
+  /*   72 S> */ B(Return),
 ]
 constant pool: [
   "eval",
@@ -98,37 +102,39 @@
 snippet: "
   x = 20; return eval('');
 "
-frame size: 9
+frame size: 10
 parameter count: 1
-bytecode array length: 69
+bytecode array length: 73
 bytecodes: [
-  B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
-  B(PushContext), R(0),
-  B(Ldar), R(this),
-  B(StaContextSlot), R(context), U8(4),
-  B(CreateMappedArguments),
-  B(StaContextSlot), R(context), U8(5),
-  B(Ldar), R(new_target),
-  B(StaContextSlot), R(context), U8(6),
-  B(StackCheck),
-  B(LdaSmi), U8(20),
-  B(StaLookupSlotSloppy), U8(0),
-  B(LdaConstant), U8(1),
-  B(Star), R(3),
-  B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(3), U8(1), R(1),
-  B(LdaConstant), U8(2),
-  B(Star), R(3),
-  B(Mov), R(1), R(4),
-  B(Mov), R(3), R(5),
-  B(Mov), R(closure), R(6),
-  B(LdaZero),
-  B(Star), R(7),
-  B(LdaSmi), U8(30),
-  B(Star), R(8),
-  B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(5),
-  B(Star), R(1),
-  B(Call), R(1), R(2), U8(2), U8(0),
-  B(Return),
+                B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
+                B(PushContext), R(0),
+                B(Ldar), R(this),
+                B(StaContextSlot), R(context), U8(4),
+                B(CreateMappedArguments),
+                B(StaContextSlot), R(context), U8(5),
+                B(Ldar), R(new_target),
+                B(StaContextSlot), R(context), U8(6),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaSmi), U8(20),
+  /*   36 E> */ B(StaLookupSlotSloppy), U8(0),
+  /*   42 S> */ B(LdaConstant), U8(1),
+                B(Star), R(3),
+                B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), R(3), U8(1), R(1),
+                B(LdaConstant), U8(2),
+                B(Star), R(3),
+                B(LdaZero),
+                B(Star), R(7),
+                B(LdaSmi), U8(30),
+                B(Star), R(8),
+                B(LdaSmi), U8(49),
+                B(Star), R(9),
+                B(Mov), R(1), R(4),
+                B(Mov), R(3), R(5),
+                B(Mov), R(closure), R(6),
+                B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6),
+                B(Star), R(1),
+  /*   49 E> */ B(Call), R(1), R(2), U8(2), U8(0),
+  /*   59 S> */ B(Return),
 ]
 constant pool: [
   "x",
diff --git a/test/cctest/interpreter/bytecode_expectations/LookupSlotInEval.golden b/test/cctest/interpreter/bytecode_expectations/LookupSlotInEval.golden
index 26e11e3..4147631 100644
--- a/test/cctest/interpreter/bytecode_expectations/LookupSlotInEval.golden
+++ b/test/cctest/interpreter/bytecode_expectations/LookupSlotInEval.golden
@@ -21,9 +21,9 @@
 parameter count: 1
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaLookupSlot), U8(0),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   15 S> */ B(LdaLookupSlot), U8(0),
+  /*   25 S> */ B(Return),
 ]
 constant pool: [
   "x",
@@ -44,11 +44,11 @@
 parameter count: 1
 bytecode array length: 7
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(StaLookupSlotSloppy), U8(0),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   15 S> */ B(LdaSmi), U8(10),
+  /*   17 E> */ B(StaLookupSlotSloppy), U8(0),
+                B(LdaUndefined),
+  /*   23 S> */ B(Return),
 ]
 constant pool: [
   "x",
@@ -69,11 +69,11 @@
 parameter count: 1
 bytecode array length: 7
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(StaLookupSlotStrict), U8(0),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   29 S> */ B(LdaSmi), U8(10),
+  /*   31 E> */ B(StaLookupSlotStrict), U8(0),
+                B(LdaUndefined),
+  /*   37 S> */ B(Return),
 ]
 constant pool: [
   "x",
@@ -94,10 +94,10 @@
 parameter count: 1
 bytecode array length: 5
 bytecodes: [
-  B(StackCheck),
-  B(LdaLookupSlotInsideTypeof), U8(0),
-  B(TypeOf),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   15 S> */ B(LdaLookupSlotInsideTypeof), U8(0),
+                B(TypeOf),
+  /*   32 S> */ B(Return),
 ]
 constant pool: [
   "x",
diff --git a/test/cctest/interpreter/bytecode_expectations/LookupSlotWideInEval.golden b/test/cctest/interpreter/bytecode_expectations/LookupSlotWideInEval.golden
index 2fdc3e9..a668d62 100644
--- a/test/cctest/interpreter/bytecode_expectations/LookupSlotWideInEval.golden
+++ b/test/cctest/interpreter/bytecode_expectations/LookupSlotWideInEval.golden
@@ -281,521 +281,521 @@
 parameter count: 1
 bytecode array length: 1030
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(LdaConstant), U8(1),
-  B(Star), R(0),
-  B(LdaConstant), U8(2),
-  B(Star), R(0),
-  B(LdaConstant), U8(3),
-  B(Star), R(0),
-  B(LdaConstant), U8(4),
-  B(Star), R(0),
-  B(LdaConstant), U8(5),
-  B(Star), R(0),
-  B(LdaConstant), U8(6),
-  B(Star), R(0),
-  B(LdaConstant), U8(7),
-  B(Star), R(0),
-  B(LdaConstant), U8(8),
-  B(Star), R(0),
-  B(LdaConstant), U8(9),
-  B(Star), R(0),
-  B(LdaConstant), U8(10),
-  B(Star), R(0),
-  B(LdaConstant), U8(11),
-  B(Star), R(0),
-  B(LdaConstant), U8(12),
-  B(Star), R(0),
-  B(LdaConstant), U8(13),
-  B(Star), R(0),
-  B(LdaConstant), U8(14),
-  B(Star), R(0),
-  B(LdaConstant), U8(15),
-  B(Star), R(0),
-  B(LdaConstant), U8(16),
-  B(Star), R(0),
-  B(LdaConstant), U8(17),
-  B(Star), R(0),
-  B(LdaConstant), U8(18),
-  B(Star), R(0),
-  B(LdaConstant), U8(19),
-  B(Star), R(0),
-  B(LdaConstant), U8(20),
-  B(Star), R(0),
-  B(LdaConstant), U8(21),
-  B(Star), R(0),
-  B(LdaConstant), U8(22),
-  B(Star), R(0),
-  B(LdaConstant), U8(23),
-  B(Star), R(0),
-  B(LdaConstant), U8(24),
-  B(Star), R(0),
-  B(LdaConstant), U8(25),
-  B(Star), R(0),
-  B(LdaConstant), U8(26),
-  B(Star), R(0),
-  B(LdaConstant), U8(27),
-  B(Star), R(0),
-  B(LdaConstant), U8(28),
-  B(Star), R(0),
-  B(LdaConstant), U8(29),
-  B(Star), R(0),
-  B(LdaConstant), U8(30),
-  B(Star), R(0),
-  B(LdaConstant), U8(31),
-  B(Star), R(0),
-  B(LdaConstant), U8(32),
-  B(Star), R(0),
-  B(LdaConstant), U8(33),
-  B(Star), R(0),
-  B(LdaConstant), U8(34),
-  B(Star), R(0),
-  B(LdaConstant), U8(35),
-  B(Star), R(0),
-  B(LdaConstant), U8(36),
-  B(Star), R(0),
-  B(LdaConstant), U8(37),
-  B(Star), R(0),
-  B(LdaConstant), U8(38),
-  B(Star), R(0),
-  B(LdaConstant), U8(39),
-  B(Star), R(0),
-  B(LdaConstant), U8(40),
-  B(Star), R(0),
-  B(LdaConstant), U8(41),
-  B(Star), R(0),
-  B(LdaConstant), U8(42),
-  B(Star), R(0),
-  B(LdaConstant), U8(43),
-  B(Star), R(0),
-  B(LdaConstant), U8(44),
-  B(Star), R(0),
-  B(LdaConstant), U8(45),
-  B(Star), R(0),
-  B(LdaConstant), U8(46),
-  B(Star), R(0),
-  B(LdaConstant), U8(47),
-  B(Star), R(0),
-  B(LdaConstant), U8(48),
-  B(Star), R(0),
-  B(LdaConstant), U8(49),
-  B(Star), R(0),
-  B(LdaConstant), U8(50),
-  B(Star), R(0),
-  B(LdaConstant), U8(51),
-  B(Star), R(0),
-  B(LdaConstant), U8(52),
-  B(Star), R(0),
-  B(LdaConstant), U8(53),
-  B(Star), R(0),
-  B(LdaConstant), U8(54),
-  B(Star), R(0),
-  B(LdaConstant), U8(55),
-  B(Star), R(0),
-  B(LdaConstant), U8(56),
-  B(Star), R(0),
-  B(LdaConstant), U8(57),
-  B(Star), R(0),
-  B(LdaConstant), U8(58),
-  B(Star), R(0),
-  B(LdaConstant), U8(59),
-  B(Star), R(0),
-  B(LdaConstant), U8(60),
-  B(Star), R(0),
-  B(LdaConstant), U8(61),
-  B(Star), R(0),
-  B(LdaConstant), U8(62),
-  B(Star), R(0),
-  B(LdaConstant), U8(63),
-  B(Star), R(0),
-  B(LdaConstant), U8(64),
-  B(Star), R(0),
-  B(LdaConstant), U8(65),
-  B(Star), R(0),
-  B(LdaConstant), U8(66),
-  B(Star), R(0),
-  B(LdaConstant), U8(67),
-  B(Star), R(0),
-  B(LdaConstant), U8(68),
-  B(Star), R(0),
-  B(LdaConstant), U8(69),
-  B(Star), R(0),
-  B(LdaConstant), U8(70),
-  B(Star), R(0),
-  B(LdaConstant), U8(71),
-  B(Star), R(0),
-  B(LdaConstant), U8(72),
-  B(Star), R(0),
-  B(LdaConstant), U8(73),
-  B(Star), R(0),
-  B(LdaConstant), U8(74),
-  B(Star), R(0),
-  B(LdaConstant), U8(75),
-  B(Star), R(0),
-  B(LdaConstant), U8(76),
-  B(Star), R(0),
-  B(LdaConstant), U8(77),
-  B(Star), R(0),
-  B(LdaConstant), U8(78),
-  B(Star), R(0),
-  B(LdaConstant), U8(79),
-  B(Star), R(0),
-  B(LdaConstant), U8(80),
-  B(Star), R(0),
-  B(LdaConstant), U8(81),
-  B(Star), R(0),
-  B(LdaConstant), U8(82),
-  B(Star), R(0),
-  B(LdaConstant), U8(83),
-  B(Star), R(0),
-  B(LdaConstant), U8(84),
-  B(Star), R(0),
-  B(LdaConstant), U8(85),
-  B(Star), R(0),
-  B(LdaConstant), U8(86),
-  B(Star), R(0),
-  B(LdaConstant), U8(87),
-  B(Star), R(0),
-  B(LdaConstant), U8(88),
-  B(Star), R(0),
-  B(LdaConstant), U8(89),
-  B(Star), R(0),
-  B(LdaConstant), U8(90),
-  B(Star), R(0),
-  B(LdaConstant), U8(91),
-  B(Star), R(0),
-  B(LdaConstant), U8(92),
-  B(Star), R(0),
-  B(LdaConstant), U8(93),
-  B(Star), R(0),
-  B(LdaConstant), U8(94),
-  B(Star), R(0),
-  B(LdaConstant), U8(95),
-  B(Star), R(0),
-  B(LdaConstant), U8(96),
-  B(Star), R(0),
-  B(LdaConstant), U8(97),
-  B(Star), R(0),
-  B(LdaConstant), U8(98),
-  B(Star), R(0),
-  B(LdaConstant), U8(99),
-  B(Star), R(0),
-  B(LdaConstant), U8(100),
-  B(Star), R(0),
-  B(LdaConstant), U8(101),
-  B(Star), R(0),
-  B(LdaConstant), U8(102),
-  B(Star), R(0),
-  B(LdaConstant), U8(103),
-  B(Star), R(0),
-  B(LdaConstant), U8(104),
-  B(Star), R(0),
-  B(LdaConstant), U8(105),
-  B(Star), R(0),
-  B(LdaConstant), U8(106),
-  B(Star), R(0),
-  B(LdaConstant), U8(107),
-  B(Star), R(0),
-  B(LdaConstant), U8(108),
-  B(Star), R(0),
-  B(LdaConstant), U8(109),
-  B(Star), R(0),
-  B(LdaConstant), U8(110),
-  B(Star), R(0),
-  B(LdaConstant), U8(111),
-  B(Star), R(0),
-  B(LdaConstant), U8(112),
-  B(Star), R(0),
-  B(LdaConstant), U8(113),
-  B(Star), R(0),
-  B(LdaConstant), U8(114),
-  B(Star), R(0),
-  B(LdaConstant), U8(115),
-  B(Star), R(0),
-  B(LdaConstant), U8(116),
-  B(Star), R(0),
-  B(LdaConstant), U8(117),
-  B(Star), R(0),
-  B(LdaConstant), U8(118),
-  B(Star), R(0),
-  B(LdaConstant), U8(119),
-  B(Star), R(0),
-  B(LdaConstant), U8(120),
-  B(Star), R(0),
-  B(LdaConstant), U8(121),
-  B(Star), R(0),
-  B(LdaConstant), U8(122),
-  B(Star), R(0),
-  B(LdaConstant), U8(123),
-  B(Star), R(0),
-  B(LdaConstant), U8(124),
-  B(Star), R(0),
-  B(LdaConstant), U8(125),
-  B(Star), R(0),
-  B(LdaConstant), U8(126),
-  B(Star), R(0),
-  B(LdaConstant), U8(127),
-  B(Star), R(0),
-  B(LdaConstant), U8(128),
-  B(Star), R(0),
-  B(LdaConstant), U8(129),
-  B(Star), R(0),
-  B(LdaConstant), U8(130),
-  B(Star), R(0),
-  B(LdaConstant), U8(131),
-  B(Star), R(0),
-  B(LdaConstant), U8(132),
-  B(Star), R(0),
-  B(LdaConstant), U8(133),
-  B(Star), R(0),
-  B(LdaConstant), U8(134),
-  B(Star), R(0),
-  B(LdaConstant), U8(135),
-  B(Star), R(0),
-  B(LdaConstant), U8(136),
-  B(Star), R(0),
-  B(LdaConstant), U8(137),
-  B(Star), R(0),
-  B(LdaConstant), U8(138),
-  B(Star), R(0),
-  B(LdaConstant), U8(139),
-  B(Star), R(0),
-  B(LdaConstant), U8(140),
-  B(Star), R(0),
-  B(LdaConstant), U8(141),
-  B(Star), R(0),
-  B(LdaConstant), U8(142),
-  B(Star), R(0),
-  B(LdaConstant), U8(143),
-  B(Star), R(0),
-  B(LdaConstant), U8(144),
-  B(Star), R(0),
-  B(LdaConstant), U8(145),
-  B(Star), R(0),
-  B(LdaConstant), U8(146),
-  B(Star), R(0),
-  B(LdaConstant), U8(147),
-  B(Star), R(0),
-  B(LdaConstant), U8(148),
-  B(Star), R(0),
-  B(LdaConstant), U8(149),
-  B(Star), R(0),
-  B(LdaConstant), U8(150),
-  B(Star), R(0),
-  B(LdaConstant), U8(151),
-  B(Star), R(0),
-  B(LdaConstant), U8(152),
-  B(Star), R(0),
-  B(LdaConstant), U8(153),
-  B(Star), R(0),
-  B(LdaConstant), U8(154),
-  B(Star), R(0),
-  B(LdaConstant), U8(155),
-  B(Star), R(0),
-  B(LdaConstant), U8(156),
-  B(Star), R(0),
-  B(LdaConstant), U8(157),
-  B(Star), R(0),
-  B(LdaConstant), U8(158),
-  B(Star), R(0),
-  B(LdaConstant), U8(159),
-  B(Star), R(0),
-  B(LdaConstant), U8(160),
-  B(Star), R(0),
-  B(LdaConstant), U8(161),
-  B(Star), R(0),
-  B(LdaConstant), U8(162),
-  B(Star), R(0),
-  B(LdaConstant), U8(163),
-  B(Star), R(0),
-  B(LdaConstant), U8(164),
-  B(Star), R(0),
-  B(LdaConstant), U8(165),
-  B(Star), R(0),
-  B(LdaConstant), U8(166),
-  B(Star), R(0),
-  B(LdaConstant), U8(167),
-  B(Star), R(0),
-  B(LdaConstant), U8(168),
-  B(Star), R(0),
-  B(LdaConstant), U8(169),
-  B(Star), R(0),
-  B(LdaConstant), U8(170),
-  B(Star), R(0),
-  B(LdaConstant), U8(171),
-  B(Star), R(0),
-  B(LdaConstant), U8(172),
-  B(Star), R(0),
-  B(LdaConstant), U8(173),
-  B(Star), R(0),
-  B(LdaConstant), U8(174),
-  B(Star), R(0),
-  B(LdaConstant), U8(175),
-  B(Star), R(0),
-  B(LdaConstant), U8(176),
-  B(Star), R(0),
-  B(LdaConstant), U8(177),
-  B(Star), R(0),
-  B(LdaConstant), U8(178),
-  B(Star), R(0),
-  B(LdaConstant), U8(179),
-  B(Star), R(0),
-  B(LdaConstant), U8(180),
-  B(Star), R(0),
-  B(LdaConstant), U8(181),
-  B(Star), R(0),
-  B(LdaConstant), U8(182),
-  B(Star), R(0),
-  B(LdaConstant), U8(183),
-  B(Star), R(0),
-  B(LdaConstant), U8(184),
-  B(Star), R(0),
-  B(LdaConstant), U8(185),
-  B(Star), R(0),
-  B(LdaConstant), U8(186),
-  B(Star), R(0),
-  B(LdaConstant), U8(187),
-  B(Star), R(0),
-  B(LdaConstant), U8(188),
-  B(Star), R(0),
-  B(LdaConstant), U8(189),
-  B(Star), R(0),
-  B(LdaConstant), U8(190),
-  B(Star), R(0),
-  B(LdaConstant), U8(191),
-  B(Star), R(0),
-  B(LdaConstant), U8(192),
-  B(Star), R(0),
-  B(LdaConstant), U8(193),
-  B(Star), R(0),
-  B(LdaConstant), U8(194),
-  B(Star), R(0),
-  B(LdaConstant), U8(195),
-  B(Star), R(0),
-  B(LdaConstant), U8(196),
-  B(Star), R(0),
-  B(LdaConstant), U8(197),
-  B(Star), R(0),
-  B(LdaConstant), U8(198),
-  B(Star), R(0),
-  B(LdaConstant), U8(199),
-  B(Star), R(0),
-  B(LdaConstant), U8(200),
-  B(Star), R(0),
-  B(LdaConstant), U8(201),
-  B(Star), R(0),
-  B(LdaConstant), U8(202),
-  B(Star), R(0),
-  B(LdaConstant), U8(203),
-  B(Star), R(0),
-  B(LdaConstant), U8(204),
-  B(Star), R(0),
-  B(LdaConstant), U8(205),
-  B(Star), R(0),
-  B(LdaConstant), U8(206),
-  B(Star), R(0),
-  B(LdaConstant), U8(207),
-  B(Star), R(0),
-  B(LdaConstant), U8(208),
-  B(Star), R(0),
-  B(LdaConstant), U8(209),
-  B(Star), R(0),
-  B(LdaConstant), U8(210),
-  B(Star), R(0),
-  B(LdaConstant), U8(211),
-  B(Star), R(0),
-  B(LdaConstant), U8(212),
-  B(Star), R(0),
-  B(LdaConstant), U8(213),
-  B(Star), R(0),
-  B(LdaConstant), U8(214),
-  B(Star), R(0),
-  B(LdaConstant), U8(215),
-  B(Star), R(0),
-  B(LdaConstant), U8(216),
-  B(Star), R(0),
-  B(LdaConstant), U8(217),
-  B(Star), R(0),
-  B(LdaConstant), U8(218),
-  B(Star), R(0),
-  B(LdaConstant), U8(219),
-  B(Star), R(0),
-  B(LdaConstant), U8(220),
-  B(Star), R(0),
-  B(LdaConstant), U8(221),
-  B(Star), R(0),
-  B(LdaConstant), U8(222),
-  B(Star), R(0),
-  B(LdaConstant), U8(223),
-  B(Star), R(0),
-  B(LdaConstant), U8(224),
-  B(Star), R(0),
-  B(LdaConstant), U8(225),
-  B(Star), R(0),
-  B(LdaConstant), U8(226),
-  B(Star), R(0),
-  B(LdaConstant), U8(227),
-  B(Star), R(0),
-  B(LdaConstant), U8(228),
-  B(Star), R(0),
-  B(LdaConstant), U8(229),
-  B(Star), R(0),
-  B(LdaConstant), U8(230),
-  B(Star), R(0),
-  B(LdaConstant), U8(231),
-  B(Star), R(0),
-  B(LdaConstant), U8(232),
-  B(Star), R(0),
-  B(LdaConstant), U8(233),
-  B(Star), R(0),
-  B(LdaConstant), U8(234),
-  B(Star), R(0),
-  B(LdaConstant), U8(235),
-  B(Star), R(0),
-  B(LdaConstant), U8(236),
-  B(Star), R(0),
-  B(LdaConstant), U8(237),
-  B(Star), R(0),
-  B(LdaConstant), U8(238),
-  B(Star), R(0),
-  B(LdaConstant), U8(239),
-  B(Star), R(0),
-  B(LdaConstant), U8(240),
-  B(Star), R(0),
-  B(LdaConstant), U8(241),
-  B(Star), R(0),
-  B(LdaConstant), U8(242),
-  B(Star), R(0),
-  B(LdaConstant), U8(243),
-  B(Star), R(0),
-  B(LdaConstant), U8(244),
-  B(Star), R(0),
-  B(LdaConstant), U8(245),
-  B(Star), R(0),
-  B(LdaConstant), U8(246),
-  B(Star), R(0),
-  B(LdaConstant), U8(247),
-  B(Star), R(0),
-  B(LdaConstant), U8(248),
-  B(Star), R(0),
-  B(LdaConstant), U8(249),
-  B(Star), R(0),
-  B(LdaConstant), U8(250),
-  B(Star), R(0),
-  B(LdaConstant), U8(251),
-  B(Star), R(0),
-  B(LdaConstant), U8(252),
-  B(Star), R(0),
-  B(LdaConstant), U8(253),
-  B(Star), R(0),
-  B(LdaConstant), U8(254),
-  B(Star), R(0),
-  B(LdaConstant), U8(255),
-  B(Star), R(0),
-  B(Wide), B(LdaLookupSlot), U16(256),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   22 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   34 S> */ B(LdaConstant), U8(1),
+                B(Star), R(0),
+  /*   46 S> */ B(LdaConstant), U8(2),
+                B(Star), R(0),
+  /*   58 S> */ B(LdaConstant), U8(3),
+                B(Star), R(0),
+  /*   70 S> */ B(LdaConstant), U8(4),
+                B(Star), R(0),
+  /*   82 S> */ B(LdaConstant), U8(5),
+                B(Star), R(0),
+  /*   94 S> */ B(LdaConstant), U8(6),
+                B(Star), R(0),
+  /*  106 S> */ B(LdaConstant), U8(7),
+                B(Star), R(0),
+  /*  118 S> */ B(LdaConstant), U8(8),
+                B(Star), R(0),
+  /*  130 S> */ B(LdaConstant), U8(9),
+                B(Star), R(0),
+  /*  142 S> */ B(LdaConstant), U8(10),
+                B(Star), R(0),
+  /*  154 S> */ B(LdaConstant), U8(11),
+                B(Star), R(0),
+  /*  166 S> */ B(LdaConstant), U8(12),
+                B(Star), R(0),
+  /*  178 S> */ B(LdaConstant), U8(13),
+                B(Star), R(0),
+  /*  190 S> */ B(LdaConstant), U8(14),
+                B(Star), R(0),
+  /*  202 S> */ B(LdaConstant), U8(15),
+                B(Star), R(0),
+  /*  214 S> */ B(LdaConstant), U8(16),
+                B(Star), R(0),
+  /*  226 S> */ B(LdaConstant), U8(17),
+                B(Star), R(0),
+  /*  238 S> */ B(LdaConstant), U8(18),
+                B(Star), R(0),
+  /*  250 S> */ B(LdaConstant), U8(19),
+                B(Star), R(0),
+  /*  262 S> */ B(LdaConstant), U8(20),
+                B(Star), R(0),
+  /*  274 S> */ B(LdaConstant), U8(21),
+                B(Star), R(0),
+  /*  286 S> */ B(LdaConstant), U8(22),
+                B(Star), R(0),
+  /*  298 S> */ B(LdaConstant), U8(23),
+                B(Star), R(0),
+  /*  310 S> */ B(LdaConstant), U8(24),
+                B(Star), R(0),
+  /*  322 S> */ B(LdaConstant), U8(25),
+                B(Star), R(0),
+  /*  334 S> */ B(LdaConstant), U8(26),
+                B(Star), R(0),
+  /*  346 S> */ B(LdaConstant), U8(27),
+                B(Star), R(0),
+  /*  358 S> */ B(LdaConstant), U8(28),
+                B(Star), R(0),
+  /*  370 S> */ B(LdaConstant), U8(29),
+                B(Star), R(0),
+  /*  382 S> */ B(LdaConstant), U8(30),
+                B(Star), R(0),
+  /*  394 S> */ B(LdaConstant), U8(31),
+                B(Star), R(0),
+  /*  406 S> */ B(LdaConstant), U8(32),
+                B(Star), R(0),
+  /*  418 S> */ B(LdaConstant), U8(33),
+                B(Star), R(0),
+  /*  430 S> */ B(LdaConstant), U8(34),
+                B(Star), R(0),
+  /*  442 S> */ B(LdaConstant), U8(35),
+                B(Star), R(0),
+  /*  454 S> */ B(LdaConstant), U8(36),
+                B(Star), R(0),
+  /*  466 S> */ B(LdaConstant), U8(37),
+                B(Star), R(0),
+  /*  478 S> */ B(LdaConstant), U8(38),
+                B(Star), R(0),
+  /*  490 S> */ B(LdaConstant), U8(39),
+                B(Star), R(0),
+  /*  502 S> */ B(LdaConstant), U8(40),
+                B(Star), R(0),
+  /*  514 S> */ B(LdaConstant), U8(41),
+                B(Star), R(0),
+  /*  526 S> */ B(LdaConstant), U8(42),
+                B(Star), R(0),
+  /*  538 S> */ B(LdaConstant), U8(43),
+                B(Star), R(0),
+  /*  550 S> */ B(LdaConstant), U8(44),
+                B(Star), R(0),
+  /*  562 S> */ B(LdaConstant), U8(45),
+                B(Star), R(0),
+  /*  574 S> */ B(LdaConstant), U8(46),
+                B(Star), R(0),
+  /*  586 S> */ B(LdaConstant), U8(47),
+                B(Star), R(0),
+  /*  598 S> */ B(LdaConstant), U8(48),
+                B(Star), R(0),
+  /*  610 S> */ B(LdaConstant), U8(49),
+                B(Star), R(0),
+  /*  622 S> */ B(LdaConstant), U8(50),
+                B(Star), R(0),
+  /*  634 S> */ B(LdaConstant), U8(51),
+                B(Star), R(0),
+  /*  646 S> */ B(LdaConstant), U8(52),
+                B(Star), R(0),
+  /*  658 S> */ B(LdaConstant), U8(53),
+                B(Star), R(0),
+  /*  670 S> */ B(LdaConstant), U8(54),
+                B(Star), R(0),
+  /*  682 S> */ B(LdaConstant), U8(55),
+                B(Star), R(0),
+  /*  694 S> */ B(LdaConstant), U8(56),
+                B(Star), R(0),
+  /*  706 S> */ B(LdaConstant), U8(57),
+                B(Star), R(0),
+  /*  718 S> */ B(LdaConstant), U8(58),
+                B(Star), R(0),
+  /*  730 S> */ B(LdaConstant), U8(59),
+                B(Star), R(0),
+  /*  742 S> */ B(LdaConstant), U8(60),
+                B(Star), R(0),
+  /*  754 S> */ B(LdaConstant), U8(61),
+                B(Star), R(0),
+  /*  766 S> */ B(LdaConstant), U8(62),
+                B(Star), R(0),
+  /*  778 S> */ B(LdaConstant), U8(63),
+                B(Star), R(0),
+  /*  790 S> */ B(LdaConstant), U8(64),
+                B(Star), R(0),
+  /*  802 S> */ B(LdaConstant), U8(65),
+                B(Star), R(0),
+  /*  814 S> */ B(LdaConstant), U8(66),
+                B(Star), R(0),
+  /*  826 S> */ B(LdaConstant), U8(67),
+                B(Star), R(0),
+  /*  838 S> */ B(LdaConstant), U8(68),
+                B(Star), R(0),
+  /*  850 S> */ B(LdaConstant), U8(69),
+                B(Star), R(0),
+  /*  862 S> */ B(LdaConstant), U8(70),
+                B(Star), R(0),
+  /*  874 S> */ B(LdaConstant), U8(71),
+                B(Star), R(0),
+  /*  886 S> */ B(LdaConstant), U8(72),
+                B(Star), R(0),
+  /*  898 S> */ B(LdaConstant), U8(73),
+                B(Star), R(0),
+  /*  910 S> */ B(LdaConstant), U8(74),
+                B(Star), R(0),
+  /*  922 S> */ B(LdaConstant), U8(75),
+                B(Star), R(0),
+  /*  934 S> */ B(LdaConstant), U8(76),
+                B(Star), R(0),
+  /*  946 S> */ B(LdaConstant), U8(77),
+                B(Star), R(0),
+  /*  958 S> */ B(LdaConstant), U8(78),
+                B(Star), R(0),
+  /*  970 S> */ B(LdaConstant), U8(79),
+                B(Star), R(0),
+  /*  982 S> */ B(LdaConstant), U8(80),
+                B(Star), R(0),
+  /*  994 S> */ B(LdaConstant), U8(81),
+                B(Star), R(0),
+  /* 1006 S> */ B(LdaConstant), U8(82),
+                B(Star), R(0),
+  /* 1018 S> */ B(LdaConstant), U8(83),
+                B(Star), R(0),
+  /* 1030 S> */ B(LdaConstant), U8(84),
+                B(Star), R(0),
+  /* 1042 S> */ B(LdaConstant), U8(85),
+                B(Star), R(0),
+  /* 1054 S> */ B(LdaConstant), U8(86),
+                B(Star), R(0),
+  /* 1066 S> */ B(LdaConstant), U8(87),
+                B(Star), R(0),
+  /* 1078 S> */ B(LdaConstant), U8(88),
+                B(Star), R(0),
+  /* 1090 S> */ B(LdaConstant), U8(89),
+                B(Star), R(0),
+  /* 1102 S> */ B(LdaConstant), U8(90),
+                B(Star), R(0),
+  /* 1114 S> */ B(LdaConstant), U8(91),
+                B(Star), R(0),
+  /* 1126 S> */ B(LdaConstant), U8(92),
+                B(Star), R(0),
+  /* 1138 S> */ B(LdaConstant), U8(93),
+                B(Star), R(0),
+  /* 1150 S> */ B(LdaConstant), U8(94),
+                B(Star), R(0),
+  /* 1162 S> */ B(LdaConstant), U8(95),
+                B(Star), R(0),
+  /* 1174 S> */ B(LdaConstant), U8(96),
+                B(Star), R(0),
+  /* 1186 S> */ B(LdaConstant), U8(97),
+                B(Star), R(0),
+  /* 1198 S> */ B(LdaConstant), U8(98),
+                B(Star), R(0),
+  /* 1210 S> */ B(LdaConstant), U8(99),
+                B(Star), R(0),
+  /* 1222 S> */ B(LdaConstant), U8(100),
+                B(Star), R(0),
+  /* 1234 S> */ B(LdaConstant), U8(101),
+                B(Star), R(0),
+  /* 1246 S> */ B(LdaConstant), U8(102),
+                B(Star), R(0),
+  /* 1258 S> */ B(LdaConstant), U8(103),
+                B(Star), R(0),
+  /* 1270 S> */ B(LdaConstant), U8(104),
+                B(Star), R(0),
+  /* 1282 S> */ B(LdaConstant), U8(105),
+                B(Star), R(0),
+  /* 1294 S> */ B(LdaConstant), U8(106),
+                B(Star), R(0),
+  /* 1306 S> */ B(LdaConstant), U8(107),
+                B(Star), R(0),
+  /* 1318 S> */ B(LdaConstant), U8(108),
+                B(Star), R(0),
+  /* 1330 S> */ B(LdaConstant), U8(109),
+                B(Star), R(0),
+  /* 1342 S> */ B(LdaConstant), U8(110),
+                B(Star), R(0),
+  /* 1354 S> */ B(LdaConstant), U8(111),
+                B(Star), R(0),
+  /* 1366 S> */ B(LdaConstant), U8(112),
+                B(Star), R(0),
+  /* 1378 S> */ B(LdaConstant), U8(113),
+                B(Star), R(0),
+  /* 1390 S> */ B(LdaConstant), U8(114),
+                B(Star), R(0),
+  /* 1402 S> */ B(LdaConstant), U8(115),
+                B(Star), R(0),
+  /* 1414 S> */ B(LdaConstant), U8(116),
+                B(Star), R(0),
+  /* 1426 S> */ B(LdaConstant), U8(117),
+                B(Star), R(0),
+  /* 1438 S> */ B(LdaConstant), U8(118),
+                B(Star), R(0),
+  /* 1450 S> */ B(LdaConstant), U8(119),
+                B(Star), R(0),
+  /* 1462 S> */ B(LdaConstant), U8(120),
+                B(Star), R(0),
+  /* 1474 S> */ B(LdaConstant), U8(121),
+                B(Star), R(0),
+  /* 1486 S> */ B(LdaConstant), U8(122),
+                B(Star), R(0),
+  /* 1498 S> */ B(LdaConstant), U8(123),
+                B(Star), R(0),
+  /* 1510 S> */ B(LdaConstant), U8(124),
+                B(Star), R(0),
+  /* 1522 S> */ B(LdaConstant), U8(125),
+                B(Star), R(0),
+  /* 1534 S> */ B(LdaConstant), U8(126),
+                B(Star), R(0),
+  /* 1546 S> */ B(LdaConstant), U8(127),
+                B(Star), R(0),
+  /* 1558 S> */ B(LdaConstant), U8(128),
+                B(Star), R(0),
+  /* 1570 S> */ B(LdaConstant), U8(129),
+                B(Star), R(0),
+  /* 1582 S> */ B(LdaConstant), U8(130),
+                B(Star), R(0),
+  /* 1594 S> */ B(LdaConstant), U8(131),
+                B(Star), R(0),
+  /* 1606 S> */ B(LdaConstant), U8(132),
+                B(Star), R(0),
+  /* 1618 S> */ B(LdaConstant), U8(133),
+                B(Star), R(0),
+  /* 1630 S> */ B(LdaConstant), U8(134),
+                B(Star), R(0),
+  /* 1642 S> */ B(LdaConstant), U8(135),
+                B(Star), R(0),
+  /* 1654 S> */ B(LdaConstant), U8(136),
+                B(Star), R(0),
+  /* 1666 S> */ B(LdaConstant), U8(137),
+                B(Star), R(0),
+  /* 1678 S> */ B(LdaConstant), U8(138),
+                B(Star), R(0),
+  /* 1690 S> */ B(LdaConstant), U8(139),
+                B(Star), R(0),
+  /* 1702 S> */ B(LdaConstant), U8(140),
+                B(Star), R(0),
+  /* 1714 S> */ B(LdaConstant), U8(141),
+                B(Star), R(0),
+  /* 1726 S> */ B(LdaConstant), U8(142),
+                B(Star), R(0),
+  /* 1738 S> */ B(LdaConstant), U8(143),
+                B(Star), R(0),
+  /* 1750 S> */ B(LdaConstant), U8(144),
+                B(Star), R(0),
+  /* 1762 S> */ B(LdaConstant), U8(145),
+                B(Star), R(0),
+  /* 1774 S> */ B(LdaConstant), U8(146),
+                B(Star), R(0),
+  /* 1786 S> */ B(LdaConstant), U8(147),
+                B(Star), R(0),
+  /* 1798 S> */ B(LdaConstant), U8(148),
+                B(Star), R(0),
+  /* 1810 S> */ B(LdaConstant), U8(149),
+                B(Star), R(0),
+  /* 1822 S> */ B(LdaConstant), U8(150),
+                B(Star), R(0),
+  /* 1834 S> */ B(LdaConstant), U8(151),
+                B(Star), R(0),
+  /* 1846 S> */ B(LdaConstant), U8(152),
+                B(Star), R(0),
+  /* 1858 S> */ B(LdaConstant), U8(153),
+                B(Star), R(0),
+  /* 1870 S> */ B(LdaConstant), U8(154),
+                B(Star), R(0),
+  /* 1882 S> */ B(LdaConstant), U8(155),
+                B(Star), R(0),
+  /* 1894 S> */ B(LdaConstant), U8(156),
+                B(Star), R(0),
+  /* 1906 S> */ B(LdaConstant), U8(157),
+                B(Star), R(0),
+  /* 1918 S> */ B(LdaConstant), U8(158),
+                B(Star), R(0),
+  /* 1930 S> */ B(LdaConstant), U8(159),
+                B(Star), R(0),
+  /* 1942 S> */ B(LdaConstant), U8(160),
+                B(Star), R(0),
+  /* 1954 S> */ B(LdaConstant), U8(161),
+                B(Star), R(0),
+  /* 1966 S> */ B(LdaConstant), U8(162),
+                B(Star), R(0),
+  /* 1978 S> */ B(LdaConstant), U8(163),
+                B(Star), R(0),
+  /* 1990 S> */ B(LdaConstant), U8(164),
+                B(Star), R(0),
+  /* 2002 S> */ B(LdaConstant), U8(165),
+                B(Star), R(0),
+  /* 2014 S> */ B(LdaConstant), U8(166),
+                B(Star), R(0),
+  /* 2026 S> */ B(LdaConstant), U8(167),
+                B(Star), R(0),
+  /* 2038 S> */ B(LdaConstant), U8(168),
+                B(Star), R(0),
+  /* 2050 S> */ B(LdaConstant), U8(169),
+                B(Star), R(0),
+  /* 2062 S> */ B(LdaConstant), U8(170),
+                B(Star), R(0),
+  /* 2074 S> */ B(LdaConstant), U8(171),
+                B(Star), R(0),
+  /* 2086 S> */ B(LdaConstant), U8(172),
+                B(Star), R(0),
+  /* 2098 S> */ B(LdaConstant), U8(173),
+                B(Star), R(0),
+  /* 2110 S> */ B(LdaConstant), U8(174),
+                B(Star), R(0),
+  /* 2122 S> */ B(LdaConstant), U8(175),
+                B(Star), R(0),
+  /* 2134 S> */ B(LdaConstant), U8(176),
+                B(Star), R(0),
+  /* 2146 S> */ B(LdaConstant), U8(177),
+                B(Star), R(0),
+  /* 2158 S> */ B(LdaConstant), U8(178),
+                B(Star), R(0),
+  /* 2170 S> */ B(LdaConstant), U8(179),
+                B(Star), R(0),
+  /* 2182 S> */ B(LdaConstant), U8(180),
+                B(Star), R(0),
+  /* 2194 S> */ B(LdaConstant), U8(181),
+                B(Star), R(0),
+  /* 2206 S> */ B(LdaConstant), U8(182),
+                B(Star), R(0),
+  /* 2218 S> */ B(LdaConstant), U8(183),
+                B(Star), R(0),
+  /* 2230 S> */ B(LdaConstant), U8(184),
+                B(Star), R(0),
+  /* 2242 S> */ B(LdaConstant), U8(185),
+                B(Star), R(0),
+  /* 2254 S> */ B(LdaConstant), U8(186),
+                B(Star), R(0),
+  /* 2266 S> */ B(LdaConstant), U8(187),
+                B(Star), R(0),
+  /* 2278 S> */ B(LdaConstant), U8(188),
+                B(Star), R(0),
+  /* 2290 S> */ B(LdaConstant), U8(189),
+                B(Star), R(0),
+  /* 2302 S> */ B(LdaConstant), U8(190),
+                B(Star), R(0),
+  /* 2314 S> */ B(LdaConstant), U8(191),
+                B(Star), R(0),
+  /* 2326 S> */ B(LdaConstant), U8(192),
+                B(Star), R(0),
+  /* 2338 S> */ B(LdaConstant), U8(193),
+                B(Star), R(0),
+  /* 2350 S> */ B(LdaConstant), U8(194),
+                B(Star), R(0),
+  /* 2362 S> */ B(LdaConstant), U8(195),
+                B(Star), R(0),
+  /* 2374 S> */ B(LdaConstant), U8(196),
+                B(Star), R(0),
+  /* 2386 S> */ B(LdaConstant), U8(197),
+                B(Star), R(0),
+  /* 2398 S> */ B(LdaConstant), U8(198),
+                B(Star), R(0),
+  /* 2410 S> */ B(LdaConstant), U8(199),
+                B(Star), R(0),
+  /* 2422 S> */ B(LdaConstant), U8(200),
+                B(Star), R(0),
+  /* 2434 S> */ B(LdaConstant), U8(201),
+                B(Star), R(0),
+  /* 2446 S> */ B(LdaConstant), U8(202),
+                B(Star), R(0),
+  /* 2458 S> */ B(LdaConstant), U8(203),
+                B(Star), R(0),
+  /* 2470 S> */ B(LdaConstant), U8(204),
+                B(Star), R(0),
+  /* 2482 S> */ B(LdaConstant), U8(205),
+                B(Star), R(0),
+  /* 2494 S> */ B(LdaConstant), U8(206),
+                B(Star), R(0),
+  /* 2506 S> */ B(LdaConstant), U8(207),
+                B(Star), R(0),
+  /* 2518 S> */ B(LdaConstant), U8(208),
+                B(Star), R(0),
+  /* 2530 S> */ B(LdaConstant), U8(209),
+                B(Star), R(0),
+  /* 2542 S> */ B(LdaConstant), U8(210),
+                B(Star), R(0),
+  /* 2554 S> */ B(LdaConstant), U8(211),
+                B(Star), R(0),
+  /* 2566 S> */ B(LdaConstant), U8(212),
+                B(Star), R(0),
+  /* 2578 S> */ B(LdaConstant), U8(213),
+                B(Star), R(0),
+  /* 2590 S> */ B(LdaConstant), U8(214),
+                B(Star), R(0),
+  /* 2602 S> */ B(LdaConstant), U8(215),
+                B(Star), R(0),
+  /* 2614 S> */ B(LdaConstant), U8(216),
+                B(Star), R(0),
+  /* 2626 S> */ B(LdaConstant), U8(217),
+                B(Star), R(0),
+  /* 2638 S> */ B(LdaConstant), U8(218),
+                B(Star), R(0),
+  /* 2650 S> */ B(LdaConstant), U8(219),
+                B(Star), R(0),
+  /* 2662 S> */ B(LdaConstant), U8(220),
+                B(Star), R(0),
+  /* 2674 S> */ B(LdaConstant), U8(221),
+                B(Star), R(0),
+  /* 2686 S> */ B(LdaConstant), U8(222),
+                B(Star), R(0),
+  /* 2698 S> */ B(LdaConstant), U8(223),
+                B(Star), R(0),
+  /* 2710 S> */ B(LdaConstant), U8(224),
+                B(Star), R(0),
+  /* 2722 S> */ B(LdaConstant), U8(225),
+                B(Star), R(0),
+  /* 2734 S> */ B(LdaConstant), U8(226),
+                B(Star), R(0),
+  /* 2746 S> */ B(LdaConstant), U8(227),
+                B(Star), R(0),
+  /* 2758 S> */ B(LdaConstant), U8(228),
+                B(Star), R(0),
+  /* 2770 S> */ B(LdaConstant), U8(229),
+                B(Star), R(0),
+  /* 2782 S> */ B(LdaConstant), U8(230),
+                B(Star), R(0),
+  /* 2794 S> */ B(LdaConstant), U8(231),
+                B(Star), R(0),
+  /* 2806 S> */ B(LdaConstant), U8(232),
+                B(Star), R(0),
+  /* 2818 S> */ B(LdaConstant), U8(233),
+                B(Star), R(0),
+  /* 2830 S> */ B(LdaConstant), U8(234),
+                B(Star), R(0),
+  /* 2842 S> */ B(LdaConstant), U8(235),
+                B(Star), R(0),
+  /* 2854 S> */ B(LdaConstant), U8(236),
+                B(Star), R(0),
+  /* 2866 S> */ B(LdaConstant), U8(237),
+                B(Star), R(0),
+  /* 2878 S> */ B(LdaConstant), U8(238),
+                B(Star), R(0),
+  /* 2890 S> */ B(LdaConstant), U8(239),
+                B(Star), R(0),
+  /* 2902 S> */ B(LdaConstant), U8(240),
+                B(Star), R(0),
+  /* 2914 S> */ B(LdaConstant), U8(241),
+                B(Star), R(0),
+  /* 2926 S> */ B(LdaConstant), U8(242),
+                B(Star), R(0),
+  /* 2938 S> */ B(LdaConstant), U8(243),
+                B(Star), R(0),
+  /* 2950 S> */ B(LdaConstant), U8(244),
+                B(Star), R(0),
+  /* 2962 S> */ B(LdaConstant), U8(245),
+                B(Star), R(0),
+  /* 2974 S> */ B(LdaConstant), U8(246),
+                B(Star), R(0),
+  /* 2986 S> */ B(LdaConstant), U8(247),
+                B(Star), R(0),
+  /* 2998 S> */ B(LdaConstant), U8(248),
+                B(Star), R(0),
+  /* 3010 S> */ B(LdaConstant), U8(249),
+                B(Star), R(0),
+  /* 3022 S> */ B(LdaConstant), U8(250),
+                B(Star), R(0),
+  /* 3034 S> */ B(LdaConstant), U8(251),
+                B(Star), R(0),
+  /* 3046 S> */ B(LdaConstant), U8(252),
+                B(Star), R(0),
+  /* 3058 S> */ B(LdaConstant), U8(253),
+                B(Star), R(0),
+  /* 3070 S> */ B(LdaConstant), U8(254),
+                B(Star), R(0),
+  /* 3082 S> */ B(LdaConstant), U8(255),
+                B(Star), R(0),
+  /* 3086 S> */ B(Wide), B(LdaLookupSlot), U16(256),
+  /* 3095 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::HEAP_NUMBER_TYPE,
@@ -1332,522 +1332,522 @@
 parameter count: 1
 bytecode array length: 1031
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(LdaConstant), U8(1),
-  B(Star), R(0),
-  B(LdaConstant), U8(2),
-  B(Star), R(0),
-  B(LdaConstant), U8(3),
-  B(Star), R(0),
-  B(LdaConstant), U8(4),
-  B(Star), R(0),
-  B(LdaConstant), U8(5),
-  B(Star), R(0),
-  B(LdaConstant), U8(6),
-  B(Star), R(0),
-  B(LdaConstant), U8(7),
-  B(Star), R(0),
-  B(LdaConstant), U8(8),
-  B(Star), R(0),
-  B(LdaConstant), U8(9),
-  B(Star), R(0),
-  B(LdaConstant), U8(10),
-  B(Star), R(0),
-  B(LdaConstant), U8(11),
-  B(Star), R(0),
-  B(LdaConstant), U8(12),
-  B(Star), R(0),
-  B(LdaConstant), U8(13),
-  B(Star), R(0),
-  B(LdaConstant), U8(14),
-  B(Star), R(0),
-  B(LdaConstant), U8(15),
-  B(Star), R(0),
-  B(LdaConstant), U8(16),
-  B(Star), R(0),
-  B(LdaConstant), U8(17),
-  B(Star), R(0),
-  B(LdaConstant), U8(18),
-  B(Star), R(0),
-  B(LdaConstant), U8(19),
-  B(Star), R(0),
-  B(LdaConstant), U8(20),
-  B(Star), R(0),
-  B(LdaConstant), U8(21),
-  B(Star), R(0),
-  B(LdaConstant), U8(22),
-  B(Star), R(0),
-  B(LdaConstant), U8(23),
-  B(Star), R(0),
-  B(LdaConstant), U8(24),
-  B(Star), R(0),
-  B(LdaConstant), U8(25),
-  B(Star), R(0),
-  B(LdaConstant), U8(26),
-  B(Star), R(0),
-  B(LdaConstant), U8(27),
-  B(Star), R(0),
-  B(LdaConstant), U8(28),
-  B(Star), R(0),
-  B(LdaConstant), U8(29),
-  B(Star), R(0),
-  B(LdaConstant), U8(30),
-  B(Star), R(0),
-  B(LdaConstant), U8(31),
-  B(Star), R(0),
-  B(LdaConstant), U8(32),
-  B(Star), R(0),
-  B(LdaConstant), U8(33),
-  B(Star), R(0),
-  B(LdaConstant), U8(34),
-  B(Star), R(0),
-  B(LdaConstant), U8(35),
-  B(Star), R(0),
-  B(LdaConstant), U8(36),
-  B(Star), R(0),
-  B(LdaConstant), U8(37),
-  B(Star), R(0),
-  B(LdaConstant), U8(38),
-  B(Star), R(0),
-  B(LdaConstant), U8(39),
-  B(Star), R(0),
-  B(LdaConstant), U8(40),
-  B(Star), R(0),
-  B(LdaConstant), U8(41),
-  B(Star), R(0),
-  B(LdaConstant), U8(42),
-  B(Star), R(0),
-  B(LdaConstant), U8(43),
-  B(Star), R(0),
-  B(LdaConstant), U8(44),
-  B(Star), R(0),
-  B(LdaConstant), U8(45),
-  B(Star), R(0),
-  B(LdaConstant), U8(46),
-  B(Star), R(0),
-  B(LdaConstant), U8(47),
-  B(Star), R(0),
-  B(LdaConstant), U8(48),
-  B(Star), R(0),
-  B(LdaConstant), U8(49),
-  B(Star), R(0),
-  B(LdaConstant), U8(50),
-  B(Star), R(0),
-  B(LdaConstant), U8(51),
-  B(Star), R(0),
-  B(LdaConstant), U8(52),
-  B(Star), R(0),
-  B(LdaConstant), U8(53),
-  B(Star), R(0),
-  B(LdaConstant), U8(54),
-  B(Star), R(0),
-  B(LdaConstant), U8(55),
-  B(Star), R(0),
-  B(LdaConstant), U8(56),
-  B(Star), R(0),
-  B(LdaConstant), U8(57),
-  B(Star), R(0),
-  B(LdaConstant), U8(58),
-  B(Star), R(0),
-  B(LdaConstant), U8(59),
-  B(Star), R(0),
-  B(LdaConstant), U8(60),
-  B(Star), R(0),
-  B(LdaConstant), U8(61),
-  B(Star), R(0),
-  B(LdaConstant), U8(62),
-  B(Star), R(0),
-  B(LdaConstant), U8(63),
-  B(Star), R(0),
-  B(LdaConstant), U8(64),
-  B(Star), R(0),
-  B(LdaConstant), U8(65),
-  B(Star), R(0),
-  B(LdaConstant), U8(66),
-  B(Star), R(0),
-  B(LdaConstant), U8(67),
-  B(Star), R(0),
-  B(LdaConstant), U8(68),
-  B(Star), R(0),
-  B(LdaConstant), U8(69),
-  B(Star), R(0),
-  B(LdaConstant), U8(70),
-  B(Star), R(0),
-  B(LdaConstant), U8(71),
-  B(Star), R(0),
-  B(LdaConstant), U8(72),
-  B(Star), R(0),
-  B(LdaConstant), U8(73),
-  B(Star), R(0),
-  B(LdaConstant), U8(74),
-  B(Star), R(0),
-  B(LdaConstant), U8(75),
-  B(Star), R(0),
-  B(LdaConstant), U8(76),
-  B(Star), R(0),
-  B(LdaConstant), U8(77),
-  B(Star), R(0),
-  B(LdaConstant), U8(78),
-  B(Star), R(0),
-  B(LdaConstant), U8(79),
-  B(Star), R(0),
-  B(LdaConstant), U8(80),
-  B(Star), R(0),
-  B(LdaConstant), U8(81),
-  B(Star), R(0),
-  B(LdaConstant), U8(82),
-  B(Star), R(0),
-  B(LdaConstant), U8(83),
-  B(Star), R(0),
-  B(LdaConstant), U8(84),
-  B(Star), R(0),
-  B(LdaConstant), U8(85),
-  B(Star), R(0),
-  B(LdaConstant), U8(86),
-  B(Star), R(0),
-  B(LdaConstant), U8(87),
-  B(Star), R(0),
-  B(LdaConstant), U8(88),
-  B(Star), R(0),
-  B(LdaConstant), U8(89),
-  B(Star), R(0),
-  B(LdaConstant), U8(90),
-  B(Star), R(0),
-  B(LdaConstant), U8(91),
-  B(Star), R(0),
-  B(LdaConstant), U8(92),
-  B(Star), R(0),
-  B(LdaConstant), U8(93),
-  B(Star), R(0),
-  B(LdaConstant), U8(94),
-  B(Star), R(0),
-  B(LdaConstant), U8(95),
-  B(Star), R(0),
-  B(LdaConstant), U8(96),
-  B(Star), R(0),
-  B(LdaConstant), U8(97),
-  B(Star), R(0),
-  B(LdaConstant), U8(98),
-  B(Star), R(0),
-  B(LdaConstant), U8(99),
-  B(Star), R(0),
-  B(LdaConstant), U8(100),
-  B(Star), R(0),
-  B(LdaConstant), U8(101),
-  B(Star), R(0),
-  B(LdaConstant), U8(102),
-  B(Star), R(0),
-  B(LdaConstant), U8(103),
-  B(Star), R(0),
-  B(LdaConstant), U8(104),
-  B(Star), R(0),
-  B(LdaConstant), U8(105),
-  B(Star), R(0),
-  B(LdaConstant), U8(106),
-  B(Star), R(0),
-  B(LdaConstant), U8(107),
-  B(Star), R(0),
-  B(LdaConstant), U8(108),
-  B(Star), R(0),
-  B(LdaConstant), U8(109),
-  B(Star), R(0),
-  B(LdaConstant), U8(110),
-  B(Star), R(0),
-  B(LdaConstant), U8(111),
-  B(Star), R(0),
-  B(LdaConstant), U8(112),
-  B(Star), R(0),
-  B(LdaConstant), U8(113),
-  B(Star), R(0),
-  B(LdaConstant), U8(114),
-  B(Star), R(0),
-  B(LdaConstant), U8(115),
-  B(Star), R(0),
-  B(LdaConstant), U8(116),
-  B(Star), R(0),
-  B(LdaConstant), U8(117),
-  B(Star), R(0),
-  B(LdaConstant), U8(118),
-  B(Star), R(0),
-  B(LdaConstant), U8(119),
-  B(Star), R(0),
-  B(LdaConstant), U8(120),
-  B(Star), R(0),
-  B(LdaConstant), U8(121),
-  B(Star), R(0),
-  B(LdaConstant), U8(122),
-  B(Star), R(0),
-  B(LdaConstant), U8(123),
-  B(Star), R(0),
-  B(LdaConstant), U8(124),
-  B(Star), R(0),
-  B(LdaConstant), U8(125),
-  B(Star), R(0),
-  B(LdaConstant), U8(126),
-  B(Star), R(0),
-  B(LdaConstant), U8(127),
-  B(Star), R(0),
-  B(LdaConstant), U8(128),
-  B(Star), R(0),
-  B(LdaConstant), U8(129),
-  B(Star), R(0),
-  B(LdaConstant), U8(130),
-  B(Star), R(0),
-  B(LdaConstant), U8(131),
-  B(Star), R(0),
-  B(LdaConstant), U8(132),
-  B(Star), R(0),
-  B(LdaConstant), U8(133),
-  B(Star), R(0),
-  B(LdaConstant), U8(134),
-  B(Star), R(0),
-  B(LdaConstant), U8(135),
-  B(Star), R(0),
-  B(LdaConstant), U8(136),
-  B(Star), R(0),
-  B(LdaConstant), U8(137),
-  B(Star), R(0),
-  B(LdaConstant), U8(138),
-  B(Star), R(0),
-  B(LdaConstant), U8(139),
-  B(Star), R(0),
-  B(LdaConstant), U8(140),
-  B(Star), R(0),
-  B(LdaConstant), U8(141),
-  B(Star), R(0),
-  B(LdaConstant), U8(142),
-  B(Star), R(0),
-  B(LdaConstant), U8(143),
-  B(Star), R(0),
-  B(LdaConstant), U8(144),
-  B(Star), R(0),
-  B(LdaConstant), U8(145),
-  B(Star), R(0),
-  B(LdaConstant), U8(146),
-  B(Star), R(0),
-  B(LdaConstant), U8(147),
-  B(Star), R(0),
-  B(LdaConstant), U8(148),
-  B(Star), R(0),
-  B(LdaConstant), U8(149),
-  B(Star), R(0),
-  B(LdaConstant), U8(150),
-  B(Star), R(0),
-  B(LdaConstant), U8(151),
-  B(Star), R(0),
-  B(LdaConstant), U8(152),
-  B(Star), R(0),
-  B(LdaConstant), U8(153),
-  B(Star), R(0),
-  B(LdaConstant), U8(154),
-  B(Star), R(0),
-  B(LdaConstant), U8(155),
-  B(Star), R(0),
-  B(LdaConstant), U8(156),
-  B(Star), R(0),
-  B(LdaConstant), U8(157),
-  B(Star), R(0),
-  B(LdaConstant), U8(158),
-  B(Star), R(0),
-  B(LdaConstant), U8(159),
-  B(Star), R(0),
-  B(LdaConstant), U8(160),
-  B(Star), R(0),
-  B(LdaConstant), U8(161),
-  B(Star), R(0),
-  B(LdaConstant), U8(162),
-  B(Star), R(0),
-  B(LdaConstant), U8(163),
-  B(Star), R(0),
-  B(LdaConstant), U8(164),
-  B(Star), R(0),
-  B(LdaConstant), U8(165),
-  B(Star), R(0),
-  B(LdaConstant), U8(166),
-  B(Star), R(0),
-  B(LdaConstant), U8(167),
-  B(Star), R(0),
-  B(LdaConstant), U8(168),
-  B(Star), R(0),
-  B(LdaConstant), U8(169),
-  B(Star), R(0),
-  B(LdaConstant), U8(170),
-  B(Star), R(0),
-  B(LdaConstant), U8(171),
-  B(Star), R(0),
-  B(LdaConstant), U8(172),
-  B(Star), R(0),
-  B(LdaConstant), U8(173),
-  B(Star), R(0),
-  B(LdaConstant), U8(174),
-  B(Star), R(0),
-  B(LdaConstant), U8(175),
-  B(Star), R(0),
-  B(LdaConstant), U8(176),
-  B(Star), R(0),
-  B(LdaConstant), U8(177),
-  B(Star), R(0),
-  B(LdaConstant), U8(178),
-  B(Star), R(0),
-  B(LdaConstant), U8(179),
-  B(Star), R(0),
-  B(LdaConstant), U8(180),
-  B(Star), R(0),
-  B(LdaConstant), U8(181),
-  B(Star), R(0),
-  B(LdaConstant), U8(182),
-  B(Star), R(0),
-  B(LdaConstant), U8(183),
-  B(Star), R(0),
-  B(LdaConstant), U8(184),
-  B(Star), R(0),
-  B(LdaConstant), U8(185),
-  B(Star), R(0),
-  B(LdaConstant), U8(186),
-  B(Star), R(0),
-  B(LdaConstant), U8(187),
-  B(Star), R(0),
-  B(LdaConstant), U8(188),
-  B(Star), R(0),
-  B(LdaConstant), U8(189),
-  B(Star), R(0),
-  B(LdaConstant), U8(190),
-  B(Star), R(0),
-  B(LdaConstant), U8(191),
-  B(Star), R(0),
-  B(LdaConstant), U8(192),
-  B(Star), R(0),
-  B(LdaConstant), U8(193),
-  B(Star), R(0),
-  B(LdaConstant), U8(194),
-  B(Star), R(0),
-  B(LdaConstant), U8(195),
-  B(Star), R(0),
-  B(LdaConstant), U8(196),
-  B(Star), R(0),
-  B(LdaConstant), U8(197),
-  B(Star), R(0),
-  B(LdaConstant), U8(198),
-  B(Star), R(0),
-  B(LdaConstant), U8(199),
-  B(Star), R(0),
-  B(LdaConstant), U8(200),
-  B(Star), R(0),
-  B(LdaConstant), U8(201),
-  B(Star), R(0),
-  B(LdaConstant), U8(202),
-  B(Star), R(0),
-  B(LdaConstant), U8(203),
-  B(Star), R(0),
-  B(LdaConstant), U8(204),
-  B(Star), R(0),
-  B(LdaConstant), U8(205),
-  B(Star), R(0),
-  B(LdaConstant), U8(206),
-  B(Star), R(0),
-  B(LdaConstant), U8(207),
-  B(Star), R(0),
-  B(LdaConstant), U8(208),
-  B(Star), R(0),
-  B(LdaConstant), U8(209),
-  B(Star), R(0),
-  B(LdaConstant), U8(210),
-  B(Star), R(0),
-  B(LdaConstant), U8(211),
-  B(Star), R(0),
-  B(LdaConstant), U8(212),
-  B(Star), R(0),
-  B(LdaConstant), U8(213),
-  B(Star), R(0),
-  B(LdaConstant), U8(214),
-  B(Star), R(0),
-  B(LdaConstant), U8(215),
-  B(Star), R(0),
-  B(LdaConstant), U8(216),
-  B(Star), R(0),
-  B(LdaConstant), U8(217),
-  B(Star), R(0),
-  B(LdaConstant), U8(218),
-  B(Star), R(0),
-  B(LdaConstant), U8(219),
-  B(Star), R(0),
-  B(LdaConstant), U8(220),
-  B(Star), R(0),
-  B(LdaConstant), U8(221),
-  B(Star), R(0),
-  B(LdaConstant), U8(222),
-  B(Star), R(0),
-  B(LdaConstant), U8(223),
-  B(Star), R(0),
-  B(LdaConstant), U8(224),
-  B(Star), R(0),
-  B(LdaConstant), U8(225),
-  B(Star), R(0),
-  B(LdaConstant), U8(226),
-  B(Star), R(0),
-  B(LdaConstant), U8(227),
-  B(Star), R(0),
-  B(LdaConstant), U8(228),
-  B(Star), R(0),
-  B(LdaConstant), U8(229),
-  B(Star), R(0),
-  B(LdaConstant), U8(230),
-  B(Star), R(0),
-  B(LdaConstant), U8(231),
-  B(Star), R(0),
-  B(LdaConstant), U8(232),
-  B(Star), R(0),
-  B(LdaConstant), U8(233),
-  B(Star), R(0),
-  B(LdaConstant), U8(234),
-  B(Star), R(0),
-  B(LdaConstant), U8(235),
-  B(Star), R(0),
-  B(LdaConstant), U8(236),
-  B(Star), R(0),
-  B(LdaConstant), U8(237),
-  B(Star), R(0),
-  B(LdaConstant), U8(238),
-  B(Star), R(0),
-  B(LdaConstant), U8(239),
-  B(Star), R(0),
-  B(LdaConstant), U8(240),
-  B(Star), R(0),
-  B(LdaConstant), U8(241),
-  B(Star), R(0),
-  B(LdaConstant), U8(242),
-  B(Star), R(0),
-  B(LdaConstant), U8(243),
-  B(Star), R(0),
-  B(LdaConstant), U8(244),
-  B(Star), R(0),
-  B(LdaConstant), U8(245),
-  B(Star), R(0),
-  B(LdaConstant), U8(246),
-  B(Star), R(0),
-  B(LdaConstant), U8(247),
-  B(Star), R(0),
-  B(LdaConstant), U8(248),
-  B(Star), R(0),
-  B(LdaConstant), U8(249),
-  B(Star), R(0),
-  B(LdaConstant), U8(250),
-  B(Star), R(0),
-  B(LdaConstant), U8(251),
-  B(Star), R(0),
-  B(LdaConstant), U8(252),
-  B(Star), R(0),
-  B(LdaConstant), U8(253),
-  B(Star), R(0),
-  B(LdaConstant), U8(254),
-  B(Star), R(0),
-  B(LdaConstant), U8(255),
-  B(Star), R(0),
-  B(Wide), B(LdaLookupSlotInsideTypeof), U16(256),
-  B(TypeOf),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   22 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   34 S> */ B(LdaConstant), U8(1),
+                B(Star), R(0),
+  /*   46 S> */ B(LdaConstant), U8(2),
+                B(Star), R(0),
+  /*   58 S> */ B(LdaConstant), U8(3),
+                B(Star), R(0),
+  /*   70 S> */ B(LdaConstant), U8(4),
+                B(Star), R(0),
+  /*   82 S> */ B(LdaConstant), U8(5),
+                B(Star), R(0),
+  /*   94 S> */ B(LdaConstant), U8(6),
+                B(Star), R(0),
+  /*  106 S> */ B(LdaConstant), U8(7),
+                B(Star), R(0),
+  /*  118 S> */ B(LdaConstant), U8(8),
+                B(Star), R(0),
+  /*  130 S> */ B(LdaConstant), U8(9),
+                B(Star), R(0),
+  /*  142 S> */ B(LdaConstant), U8(10),
+                B(Star), R(0),
+  /*  154 S> */ B(LdaConstant), U8(11),
+                B(Star), R(0),
+  /*  166 S> */ B(LdaConstant), U8(12),
+                B(Star), R(0),
+  /*  178 S> */ B(LdaConstant), U8(13),
+                B(Star), R(0),
+  /*  190 S> */ B(LdaConstant), U8(14),
+                B(Star), R(0),
+  /*  202 S> */ B(LdaConstant), U8(15),
+                B(Star), R(0),
+  /*  214 S> */ B(LdaConstant), U8(16),
+                B(Star), R(0),
+  /*  226 S> */ B(LdaConstant), U8(17),
+                B(Star), R(0),
+  /*  238 S> */ B(LdaConstant), U8(18),
+                B(Star), R(0),
+  /*  250 S> */ B(LdaConstant), U8(19),
+                B(Star), R(0),
+  /*  262 S> */ B(LdaConstant), U8(20),
+                B(Star), R(0),
+  /*  274 S> */ B(LdaConstant), U8(21),
+                B(Star), R(0),
+  /*  286 S> */ B(LdaConstant), U8(22),
+                B(Star), R(0),
+  /*  298 S> */ B(LdaConstant), U8(23),
+                B(Star), R(0),
+  /*  310 S> */ B(LdaConstant), U8(24),
+                B(Star), R(0),
+  /*  322 S> */ B(LdaConstant), U8(25),
+                B(Star), R(0),
+  /*  334 S> */ B(LdaConstant), U8(26),
+                B(Star), R(0),
+  /*  346 S> */ B(LdaConstant), U8(27),
+                B(Star), R(0),
+  /*  358 S> */ B(LdaConstant), U8(28),
+                B(Star), R(0),
+  /*  370 S> */ B(LdaConstant), U8(29),
+                B(Star), R(0),
+  /*  382 S> */ B(LdaConstant), U8(30),
+                B(Star), R(0),
+  /*  394 S> */ B(LdaConstant), U8(31),
+                B(Star), R(0),
+  /*  406 S> */ B(LdaConstant), U8(32),
+                B(Star), R(0),
+  /*  418 S> */ B(LdaConstant), U8(33),
+                B(Star), R(0),
+  /*  430 S> */ B(LdaConstant), U8(34),
+                B(Star), R(0),
+  /*  442 S> */ B(LdaConstant), U8(35),
+                B(Star), R(0),
+  /*  454 S> */ B(LdaConstant), U8(36),
+                B(Star), R(0),
+  /*  466 S> */ B(LdaConstant), U8(37),
+                B(Star), R(0),
+  /*  478 S> */ B(LdaConstant), U8(38),
+                B(Star), R(0),
+  /*  490 S> */ B(LdaConstant), U8(39),
+                B(Star), R(0),
+  /*  502 S> */ B(LdaConstant), U8(40),
+                B(Star), R(0),
+  /*  514 S> */ B(LdaConstant), U8(41),
+                B(Star), R(0),
+  /*  526 S> */ B(LdaConstant), U8(42),
+                B(Star), R(0),
+  /*  538 S> */ B(LdaConstant), U8(43),
+                B(Star), R(0),
+  /*  550 S> */ B(LdaConstant), U8(44),
+                B(Star), R(0),
+  /*  562 S> */ B(LdaConstant), U8(45),
+                B(Star), R(0),
+  /*  574 S> */ B(LdaConstant), U8(46),
+                B(Star), R(0),
+  /*  586 S> */ B(LdaConstant), U8(47),
+                B(Star), R(0),
+  /*  598 S> */ B(LdaConstant), U8(48),
+                B(Star), R(0),
+  /*  610 S> */ B(LdaConstant), U8(49),
+                B(Star), R(0),
+  /*  622 S> */ B(LdaConstant), U8(50),
+                B(Star), R(0),
+  /*  634 S> */ B(LdaConstant), U8(51),
+                B(Star), R(0),
+  /*  646 S> */ B(LdaConstant), U8(52),
+                B(Star), R(0),
+  /*  658 S> */ B(LdaConstant), U8(53),
+                B(Star), R(0),
+  /*  670 S> */ B(LdaConstant), U8(54),
+                B(Star), R(0),
+  /*  682 S> */ B(LdaConstant), U8(55),
+                B(Star), R(0),
+  /*  694 S> */ B(LdaConstant), U8(56),
+                B(Star), R(0),
+  /*  706 S> */ B(LdaConstant), U8(57),
+                B(Star), R(0),
+  /*  718 S> */ B(LdaConstant), U8(58),
+                B(Star), R(0),
+  /*  730 S> */ B(LdaConstant), U8(59),
+                B(Star), R(0),
+  /*  742 S> */ B(LdaConstant), U8(60),
+                B(Star), R(0),
+  /*  754 S> */ B(LdaConstant), U8(61),
+                B(Star), R(0),
+  /*  766 S> */ B(LdaConstant), U8(62),
+                B(Star), R(0),
+  /*  778 S> */ B(LdaConstant), U8(63),
+                B(Star), R(0),
+  /*  790 S> */ B(LdaConstant), U8(64),
+                B(Star), R(0),
+  /*  802 S> */ B(LdaConstant), U8(65),
+                B(Star), R(0),
+  /*  814 S> */ B(LdaConstant), U8(66),
+                B(Star), R(0),
+  /*  826 S> */ B(LdaConstant), U8(67),
+                B(Star), R(0),
+  /*  838 S> */ B(LdaConstant), U8(68),
+                B(Star), R(0),
+  /*  850 S> */ B(LdaConstant), U8(69),
+                B(Star), R(0),
+  /*  862 S> */ B(LdaConstant), U8(70),
+                B(Star), R(0),
+  /*  874 S> */ B(LdaConstant), U8(71),
+                B(Star), R(0),
+  /*  886 S> */ B(LdaConstant), U8(72),
+                B(Star), R(0),
+  /*  898 S> */ B(LdaConstant), U8(73),
+                B(Star), R(0),
+  /*  910 S> */ B(LdaConstant), U8(74),
+                B(Star), R(0),
+  /*  922 S> */ B(LdaConstant), U8(75),
+                B(Star), R(0),
+  /*  934 S> */ B(LdaConstant), U8(76),
+                B(Star), R(0),
+  /*  946 S> */ B(LdaConstant), U8(77),
+                B(Star), R(0),
+  /*  958 S> */ B(LdaConstant), U8(78),
+                B(Star), R(0),
+  /*  970 S> */ B(LdaConstant), U8(79),
+                B(Star), R(0),
+  /*  982 S> */ B(LdaConstant), U8(80),
+                B(Star), R(0),
+  /*  994 S> */ B(LdaConstant), U8(81),
+                B(Star), R(0),
+  /* 1006 S> */ B(LdaConstant), U8(82),
+                B(Star), R(0),
+  /* 1018 S> */ B(LdaConstant), U8(83),
+                B(Star), R(0),
+  /* 1030 S> */ B(LdaConstant), U8(84),
+                B(Star), R(0),
+  /* 1042 S> */ B(LdaConstant), U8(85),
+                B(Star), R(0),
+  /* 1054 S> */ B(LdaConstant), U8(86),
+                B(Star), R(0),
+  /* 1066 S> */ B(LdaConstant), U8(87),
+                B(Star), R(0),
+  /* 1078 S> */ B(LdaConstant), U8(88),
+                B(Star), R(0),
+  /* 1090 S> */ B(LdaConstant), U8(89),
+                B(Star), R(0),
+  /* 1102 S> */ B(LdaConstant), U8(90),
+                B(Star), R(0),
+  /* 1114 S> */ B(LdaConstant), U8(91),
+                B(Star), R(0),
+  /* 1126 S> */ B(LdaConstant), U8(92),
+                B(Star), R(0),
+  /* 1138 S> */ B(LdaConstant), U8(93),
+                B(Star), R(0),
+  /* 1150 S> */ B(LdaConstant), U8(94),
+                B(Star), R(0),
+  /* 1162 S> */ B(LdaConstant), U8(95),
+                B(Star), R(0),
+  /* 1174 S> */ B(LdaConstant), U8(96),
+                B(Star), R(0),
+  /* 1186 S> */ B(LdaConstant), U8(97),
+                B(Star), R(0),
+  /* 1198 S> */ B(LdaConstant), U8(98),
+                B(Star), R(0),
+  /* 1210 S> */ B(LdaConstant), U8(99),
+                B(Star), R(0),
+  /* 1222 S> */ B(LdaConstant), U8(100),
+                B(Star), R(0),
+  /* 1234 S> */ B(LdaConstant), U8(101),
+                B(Star), R(0),
+  /* 1246 S> */ B(LdaConstant), U8(102),
+                B(Star), R(0),
+  /* 1258 S> */ B(LdaConstant), U8(103),
+                B(Star), R(0),
+  /* 1270 S> */ B(LdaConstant), U8(104),
+                B(Star), R(0),
+  /* 1282 S> */ B(LdaConstant), U8(105),
+                B(Star), R(0),
+  /* 1294 S> */ B(LdaConstant), U8(106),
+                B(Star), R(0),
+  /* 1306 S> */ B(LdaConstant), U8(107),
+                B(Star), R(0),
+  /* 1318 S> */ B(LdaConstant), U8(108),
+                B(Star), R(0),
+  /* 1330 S> */ B(LdaConstant), U8(109),
+                B(Star), R(0),
+  /* 1342 S> */ B(LdaConstant), U8(110),
+                B(Star), R(0),
+  /* 1354 S> */ B(LdaConstant), U8(111),
+                B(Star), R(0),
+  /* 1366 S> */ B(LdaConstant), U8(112),
+                B(Star), R(0),
+  /* 1378 S> */ B(LdaConstant), U8(113),
+                B(Star), R(0),
+  /* 1390 S> */ B(LdaConstant), U8(114),
+                B(Star), R(0),
+  /* 1402 S> */ B(LdaConstant), U8(115),
+                B(Star), R(0),
+  /* 1414 S> */ B(LdaConstant), U8(116),
+                B(Star), R(0),
+  /* 1426 S> */ B(LdaConstant), U8(117),
+                B(Star), R(0),
+  /* 1438 S> */ B(LdaConstant), U8(118),
+                B(Star), R(0),
+  /* 1450 S> */ B(LdaConstant), U8(119),
+                B(Star), R(0),
+  /* 1462 S> */ B(LdaConstant), U8(120),
+                B(Star), R(0),
+  /* 1474 S> */ B(LdaConstant), U8(121),
+                B(Star), R(0),
+  /* 1486 S> */ B(LdaConstant), U8(122),
+                B(Star), R(0),
+  /* 1498 S> */ B(LdaConstant), U8(123),
+                B(Star), R(0),
+  /* 1510 S> */ B(LdaConstant), U8(124),
+                B(Star), R(0),
+  /* 1522 S> */ B(LdaConstant), U8(125),
+                B(Star), R(0),
+  /* 1534 S> */ B(LdaConstant), U8(126),
+                B(Star), R(0),
+  /* 1546 S> */ B(LdaConstant), U8(127),
+                B(Star), R(0),
+  /* 1558 S> */ B(LdaConstant), U8(128),
+                B(Star), R(0),
+  /* 1570 S> */ B(LdaConstant), U8(129),
+                B(Star), R(0),
+  /* 1582 S> */ B(LdaConstant), U8(130),
+                B(Star), R(0),
+  /* 1594 S> */ B(LdaConstant), U8(131),
+                B(Star), R(0),
+  /* 1606 S> */ B(LdaConstant), U8(132),
+                B(Star), R(0),
+  /* 1618 S> */ B(LdaConstant), U8(133),
+                B(Star), R(0),
+  /* 1630 S> */ B(LdaConstant), U8(134),
+                B(Star), R(0),
+  /* 1642 S> */ B(LdaConstant), U8(135),
+                B(Star), R(0),
+  /* 1654 S> */ B(LdaConstant), U8(136),
+                B(Star), R(0),
+  /* 1666 S> */ B(LdaConstant), U8(137),
+                B(Star), R(0),
+  /* 1678 S> */ B(LdaConstant), U8(138),
+                B(Star), R(0),
+  /* 1690 S> */ B(LdaConstant), U8(139),
+                B(Star), R(0),
+  /* 1702 S> */ B(LdaConstant), U8(140),
+                B(Star), R(0),
+  /* 1714 S> */ B(LdaConstant), U8(141),
+                B(Star), R(0),
+  /* 1726 S> */ B(LdaConstant), U8(142),
+                B(Star), R(0),
+  /* 1738 S> */ B(LdaConstant), U8(143),
+                B(Star), R(0),
+  /* 1750 S> */ B(LdaConstant), U8(144),
+                B(Star), R(0),
+  /* 1762 S> */ B(LdaConstant), U8(145),
+                B(Star), R(0),
+  /* 1774 S> */ B(LdaConstant), U8(146),
+                B(Star), R(0),
+  /* 1786 S> */ B(LdaConstant), U8(147),
+                B(Star), R(0),
+  /* 1798 S> */ B(LdaConstant), U8(148),
+                B(Star), R(0),
+  /* 1810 S> */ B(LdaConstant), U8(149),
+                B(Star), R(0),
+  /* 1822 S> */ B(LdaConstant), U8(150),
+                B(Star), R(0),
+  /* 1834 S> */ B(LdaConstant), U8(151),
+                B(Star), R(0),
+  /* 1846 S> */ B(LdaConstant), U8(152),
+                B(Star), R(0),
+  /* 1858 S> */ B(LdaConstant), U8(153),
+                B(Star), R(0),
+  /* 1870 S> */ B(LdaConstant), U8(154),
+                B(Star), R(0),
+  /* 1882 S> */ B(LdaConstant), U8(155),
+                B(Star), R(0),
+  /* 1894 S> */ B(LdaConstant), U8(156),
+                B(Star), R(0),
+  /* 1906 S> */ B(LdaConstant), U8(157),
+                B(Star), R(0),
+  /* 1918 S> */ B(LdaConstant), U8(158),
+                B(Star), R(0),
+  /* 1930 S> */ B(LdaConstant), U8(159),
+                B(Star), R(0),
+  /* 1942 S> */ B(LdaConstant), U8(160),
+                B(Star), R(0),
+  /* 1954 S> */ B(LdaConstant), U8(161),
+                B(Star), R(0),
+  /* 1966 S> */ B(LdaConstant), U8(162),
+                B(Star), R(0),
+  /* 1978 S> */ B(LdaConstant), U8(163),
+                B(Star), R(0),
+  /* 1990 S> */ B(LdaConstant), U8(164),
+                B(Star), R(0),
+  /* 2002 S> */ B(LdaConstant), U8(165),
+                B(Star), R(0),
+  /* 2014 S> */ B(LdaConstant), U8(166),
+                B(Star), R(0),
+  /* 2026 S> */ B(LdaConstant), U8(167),
+                B(Star), R(0),
+  /* 2038 S> */ B(LdaConstant), U8(168),
+                B(Star), R(0),
+  /* 2050 S> */ B(LdaConstant), U8(169),
+                B(Star), R(0),
+  /* 2062 S> */ B(LdaConstant), U8(170),
+                B(Star), R(0),
+  /* 2074 S> */ B(LdaConstant), U8(171),
+                B(Star), R(0),
+  /* 2086 S> */ B(LdaConstant), U8(172),
+                B(Star), R(0),
+  /* 2098 S> */ B(LdaConstant), U8(173),
+                B(Star), R(0),
+  /* 2110 S> */ B(LdaConstant), U8(174),
+                B(Star), R(0),
+  /* 2122 S> */ B(LdaConstant), U8(175),
+                B(Star), R(0),
+  /* 2134 S> */ B(LdaConstant), U8(176),
+                B(Star), R(0),
+  /* 2146 S> */ B(LdaConstant), U8(177),
+                B(Star), R(0),
+  /* 2158 S> */ B(LdaConstant), U8(178),
+                B(Star), R(0),
+  /* 2170 S> */ B(LdaConstant), U8(179),
+                B(Star), R(0),
+  /* 2182 S> */ B(LdaConstant), U8(180),
+                B(Star), R(0),
+  /* 2194 S> */ B(LdaConstant), U8(181),
+                B(Star), R(0),
+  /* 2206 S> */ B(LdaConstant), U8(182),
+                B(Star), R(0),
+  /* 2218 S> */ B(LdaConstant), U8(183),
+                B(Star), R(0),
+  /* 2230 S> */ B(LdaConstant), U8(184),
+                B(Star), R(0),
+  /* 2242 S> */ B(LdaConstant), U8(185),
+                B(Star), R(0),
+  /* 2254 S> */ B(LdaConstant), U8(186),
+                B(Star), R(0),
+  /* 2266 S> */ B(LdaConstant), U8(187),
+                B(Star), R(0),
+  /* 2278 S> */ B(LdaConstant), U8(188),
+                B(Star), R(0),
+  /* 2290 S> */ B(LdaConstant), U8(189),
+                B(Star), R(0),
+  /* 2302 S> */ B(LdaConstant), U8(190),
+                B(Star), R(0),
+  /* 2314 S> */ B(LdaConstant), U8(191),
+                B(Star), R(0),
+  /* 2326 S> */ B(LdaConstant), U8(192),
+                B(Star), R(0),
+  /* 2338 S> */ B(LdaConstant), U8(193),
+                B(Star), R(0),
+  /* 2350 S> */ B(LdaConstant), U8(194),
+                B(Star), R(0),
+  /* 2362 S> */ B(LdaConstant), U8(195),
+                B(Star), R(0),
+  /* 2374 S> */ B(LdaConstant), U8(196),
+                B(Star), R(0),
+  /* 2386 S> */ B(LdaConstant), U8(197),
+                B(Star), R(0),
+  /* 2398 S> */ B(LdaConstant), U8(198),
+                B(Star), R(0),
+  /* 2410 S> */ B(LdaConstant), U8(199),
+                B(Star), R(0),
+  /* 2422 S> */ B(LdaConstant), U8(200),
+                B(Star), R(0),
+  /* 2434 S> */ B(LdaConstant), U8(201),
+                B(Star), R(0),
+  /* 2446 S> */ B(LdaConstant), U8(202),
+                B(Star), R(0),
+  /* 2458 S> */ B(LdaConstant), U8(203),
+                B(Star), R(0),
+  /* 2470 S> */ B(LdaConstant), U8(204),
+                B(Star), R(0),
+  /* 2482 S> */ B(LdaConstant), U8(205),
+                B(Star), R(0),
+  /* 2494 S> */ B(LdaConstant), U8(206),
+                B(Star), R(0),
+  /* 2506 S> */ B(LdaConstant), U8(207),
+                B(Star), R(0),
+  /* 2518 S> */ B(LdaConstant), U8(208),
+                B(Star), R(0),
+  /* 2530 S> */ B(LdaConstant), U8(209),
+                B(Star), R(0),
+  /* 2542 S> */ B(LdaConstant), U8(210),
+                B(Star), R(0),
+  /* 2554 S> */ B(LdaConstant), U8(211),
+                B(Star), R(0),
+  /* 2566 S> */ B(LdaConstant), U8(212),
+                B(Star), R(0),
+  /* 2578 S> */ B(LdaConstant), U8(213),
+                B(Star), R(0),
+  /* 2590 S> */ B(LdaConstant), U8(214),
+                B(Star), R(0),
+  /* 2602 S> */ B(LdaConstant), U8(215),
+                B(Star), R(0),
+  /* 2614 S> */ B(LdaConstant), U8(216),
+                B(Star), R(0),
+  /* 2626 S> */ B(LdaConstant), U8(217),
+                B(Star), R(0),
+  /* 2638 S> */ B(LdaConstant), U8(218),
+                B(Star), R(0),
+  /* 2650 S> */ B(LdaConstant), U8(219),
+                B(Star), R(0),
+  /* 2662 S> */ B(LdaConstant), U8(220),
+                B(Star), R(0),
+  /* 2674 S> */ B(LdaConstant), U8(221),
+                B(Star), R(0),
+  /* 2686 S> */ B(LdaConstant), U8(222),
+                B(Star), R(0),
+  /* 2698 S> */ B(LdaConstant), U8(223),
+                B(Star), R(0),
+  /* 2710 S> */ B(LdaConstant), U8(224),
+                B(Star), R(0),
+  /* 2722 S> */ B(LdaConstant), U8(225),
+                B(Star), R(0),
+  /* 2734 S> */ B(LdaConstant), U8(226),
+                B(Star), R(0),
+  /* 2746 S> */ B(LdaConstant), U8(227),
+                B(Star), R(0),
+  /* 2758 S> */ B(LdaConstant), U8(228),
+                B(Star), R(0),
+  /* 2770 S> */ B(LdaConstant), U8(229),
+                B(Star), R(0),
+  /* 2782 S> */ B(LdaConstant), U8(230),
+                B(Star), R(0),
+  /* 2794 S> */ B(LdaConstant), U8(231),
+                B(Star), R(0),
+  /* 2806 S> */ B(LdaConstant), U8(232),
+                B(Star), R(0),
+  /* 2818 S> */ B(LdaConstant), U8(233),
+                B(Star), R(0),
+  /* 2830 S> */ B(LdaConstant), U8(234),
+                B(Star), R(0),
+  /* 2842 S> */ B(LdaConstant), U8(235),
+                B(Star), R(0),
+  /* 2854 S> */ B(LdaConstant), U8(236),
+                B(Star), R(0),
+  /* 2866 S> */ B(LdaConstant), U8(237),
+                B(Star), R(0),
+  /* 2878 S> */ B(LdaConstant), U8(238),
+                B(Star), R(0),
+  /* 2890 S> */ B(LdaConstant), U8(239),
+                B(Star), R(0),
+  /* 2902 S> */ B(LdaConstant), U8(240),
+                B(Star), R(0),
+  /* 2914 S> */ B(LdaConstant), U8(241),
+                B(Star), R(0),
+  /* 2926 S> */ B(LdaConstant), U8(242),
+                B(Star), R(0),
+  /* 2938 S> */ B(LdaConstant), U8(243),
+                B(Star), R(0),
+  /* 2950 S> */ B(LdaConstant), U8(244),
+                B(Star), R(0),
+  /* 2962 S> */ B(LdaConstant), U8(245),
+                B(Star), R(0),
+  /* 2974 S> */ B(LdaConstant), U8(246),
+                B(Star), R(0),
+  /* 2986 S> */ B(LdaConstant), U8(247),
+                B(Star), R(0),
+  /* 2998 S> */ B(LdaConstant), U8(248),
+                B(Star), R(0),
+  /* 3010 S> */ B(LdaConstant), U8(249),
+                B(Star), R(0),
+  /* 3022 S> */ B(LdaConstant), U8(250),
+                B(Star), R(0),
+  /* 3034 S> */ B(LdaConstant), U8(251),
+                B(Star), R(0),
+  /* 3046 S> */ B(LdaConstant), U8(252),
+                B(Star), R(0),
+  /* 3058 S> */ B(LdaConstant), U8(253),
+                B(Star), R(0),
+  /* 3070 S> */ B(LdaConstant), U8(254),
+                B(Star), R(0),
+  /* 3082 S> */ B(LdaConstant), U8(255),
+                B(Star), R(0),
+  /* 3086 S> */ B(Wide), B(LdaLookupSlotInsideTypeof), U16(256),
+                B(TypeOf),
+  /* 3102 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::HEAP_NUMBER_TYPE,
@@ -2384,523 +2384,523 @@
 parameter count: 1
 bytecode array length: 1033
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(LdaConstant), U8(1),
-  B(Star), R(0),
-  B(LdaConstant), U8(2),
-  B(Star), R(0),
-  B(LdaConstant), U8(3),
-  B(Star), R(0),
-  B(LdaConstant), U8(4),
-  B(Star), R(0),
-  B(LdaConstant), U8(5),
-  B(Star), R(0),
-  B(LdaConstant), U8(6),
-  B(Star), R(0),
-  B(LdaConstant), U8(7),
-  B(Star), R(0),
-  B(LdaConstant), U8(8),
-  B(Star), R(0),
-  B(LdaConstant), U8(9),
-  B(Star), R(0),
-  B(LdaConstant), U8(10),
-  B(Star), R(0),
-  B(LdaConstant), U8(11),
-  B(Star), R(0),
-  B(LdaConstant), U8(12),
-  B(Star), R(0),
-  B(LdaConstant), U8(13),
-  B(Star), R(0),
-  B(LdaConstant), U8(14),
-  B(Star), R(0),
-  B(LdaConstant), U8(15),
-  B(Star), R(0),
-  B(LdaConstant), U8(16),
-  B(Star), R(0),
-  B(LdaConstant), U8(17),
-  B(Star), R(0),
-  B(LdaConstant), U8(18),
-  B(Star), R(0),
-  B(LdaConstant), U8(19),
-  B(Star), R(0),
-  B(LdaConstant), U8(20),
-  B(Star), R(0),
-  B(LdaConstant), U8(21),
-  B(Star), R(0),
-  B(LdaConstant), U8(22),
-  B(Star), R(0),
-  B(LdaConstant), U8(23),
-  B(Star), R(0),
-  B(LdaConstant), U8(24),
-  B(Star), R(0),
-  B(LdaConstant), U8(25),
-  B(Star), R(0),
-  B(LdaConstant), U8(26),
-  B(Star), R(0),
-  B(LdaConstant), U8(27),
-  B(Star), R(0),
-  B(LdaConstant), U8(28),
-  B(Star), R(0),
-  B(LdaConstant), U8(29),
-  B(Star), R(0),
-  B(LdaConstant), U8(30),
-  B(Star), R(0),
-  B(LdaConstant), U8(31),
-  B(Star), R(0),
-  B(LdaConstant), U8(32),
-  B(Star), R(0),
-  B(LdaConstant), U8(33),
-  B(Star), R(0),
-  B(LdaConstant), U8(34),
-  B(Star), R(0),
-  B(LdaConstant), U8(35),
-  B(Star), R(0),
-  B(LdaConstant), U8(36),
-  B(Star), R(0),
-  B(LdaConstant), U8(37),
-  B(Star), R(0),
-  B(LdaConstant), U8(38),
-  B(Star), R(0),
-  B(LdaConstant), U8(39),
-  B(Star), R(0),
-  B(LdaConstant), U8(40),
-  B(Star), R(0),
-  B(LdaConstant), U8(41),
-  B(Star), R(0),
-  B(LdaConstant), U8(42),
-  B(Star), R(0),
-  B(LdaConstant), U8(43),
-  B(Star), R(0),
-  B(LdaConstant), U8(44),
-  B(Star), R(0),
-  B(LdaConstant), U8(45),
-  B(Star), R(0),
-  B(LdaConstant), U8(46),
-  B(Star), R(0),
-  B(LdaConstant), U8(47),
-  B(Star), R(0),
-  B(LdaConstant), U8(48),
-  B(Star), R(0),
-  B(LdaConstant), U8(49),
-  B(Star), R(0),
-  B(LdaConstant), U8(50),
-  B(Star), R(0),
-  B(LdaConstant), U8(51),
-  B(Star), R(0),
-  B(LdaConstant), U8(52),
-  B(Star), R(0),
-  B(LdaConstant), U8(53),
-  B(Star), R(0),
-  B(LdaConstant), U8(54),
-  B(Star), R(0),
-  B(LdaConstant), U8(55),
-  B(Star), R(0),
-  B(LdaConstant), U8(56),
-  B(Star), R(0),
-  B(LdaConstant), U8(57),
-  B(Star), R(0),
-  B(LdaConstant), U8(58),
-  B(Star), R(0),
-  B(LdaConstant), U8(59),
-  B(Star), R(0),
-  B(LdaConstant), U8(60),
-  B(Star), R(0),
-  B(LdaConstant), U8(61),
-  B(Star), R(0),
-  B(LdaConstant), U8(62),
-  B(Star), R(0),
-  B(LdaConstant), U8(63),
-  B(Star), R(0),
-  B(LdaConstant), U8(64),
-  B(Star), R(0),
-  B(LdaConstant), U8(65),
-  B(Star), R(0),
-  B(LdaConstant), U8(66),
-  B(Star), R(0),
-  B(LdaConstant), U8(67),
-  B(Star), R(0),
-  B(LdaConstant), U8(68),
-  B(Star), R(0),
-  B(LdaConstant), U8(69),
-  B(Star), R(0),
-  B(LdaConstant), U8(70),
-  B(Star), R(0),
-  B(LdaConstant), U8(71),
-  B(Star), R(0),
-  B(LdaConstant), U8(72),
-  B(Star), R(0),
-  B(LdaConstant), U8(73),
-  B(Star), R(0),
-  B(LdaConstant), U8(74),
-  B(Star), R(0),
-  B(LdaConstant), U8(75),
-  B(Star), R(0),
-  B(LdaConstant), U8(76),
-  B(Star), R(0),
-  B(LdaConstant), U8(77),
-  B(Star), R(0),
-  B(LdaConstant), U8(78),
-  B(Star), R(0),
-  B(LdaConstant), U8(79),
-  B(Star), R(0),
-  B(LdaConstant), U8(80),
-  B(Star), R(0),
-  B(LdaConstant), U8(81),
-  B(Star), R(0),
-  B(LdaConstant), U8(82),
-  B(Star), R(0),
-  B(LdaConstant), U8(83),
-  B(Star), R(0),
-  B(LdaConstant), U8(84),
-  B(Star), R(0),
-  B(LdaConstant), U8(85),
-  B(Star), R(0),
-  B(LdaConstant), U8(86),
-  B(Star), R(0),
-  B(LdaConstant), U8(87),
-  B(Star), R(0),
-  B(LdaConstant), U8(88),
-  B(Star), R(0),
-  B(LdaConstant), U8(89),
-  B(Star), R(0),
-  B(LdaConstant), U8(90),
-  B(Star), R(0),
-  B(LdaConstant), U8(91),
-  B(Star), R(0),
-  B(LdaConstant), U8(92),
-  B(Star), R(0),
-  B(LdaConstant), U8(93),
-  B(Star), R(0),
-  B(LdaConstant), U8(94),
-  B(Star), R(0),
-  B(LdaConstant), U8(95),
-  B(Star), R(0),
-  B(LdaConstant), U8(96),
-  B(Star), R(0),
-  B(LdaConstant), U8(97),
-  B(Star), R(0),
-  B(LdaConstant), U8(98),
-  B(Star), R(0),
-  B(LdaConstant), U8(99),
-  B(Star), R(0),
-  B(LdaConstant), U8(100),
-  B(Star), R(0),
-  B(LdaConstant), U8(101),
-  B(Star), R(0),
-  B(LdaConstant), U8(102),
-  B(Star), R(0),
-  B(LdaConstant), U8(103),
-  B(Star), R(0),
-  B(LdaConstant), U8(104),
-  B(Star), R(0),
-  B(LdaConstant), U8(105),
-  B(Star), R(0),
-  B(LdaConstant), U8(106),
-  B(Star), R(0),
-  B(LdaConstant), U8(107),
-  B(Star), R(0),
-  B(LdaConstant), U8(108),
-  B(Star), R(0),
-  B(LdaConstant), U8(109),
-  B(Star), R(0),
-  B(LdaConstant), U8(110),
-  B(Star), R(0),
-  B(LdaConstant), U8(111),
-  B(Star), R(0),
-  B(LdaConstant), U8(112),
-  B(Star), R(0),
-  B(LdaConstant), U8(113),
-  B(Star), R(0),
-  B(LdaConstant), U8(114),
-  B(Star), R(0),
-  B(LdaConstant), U8(115),
-  B(Star), R(0),
-  B(LdaConstant), U8(116),
-  B(Star), R(0),
-  B(LdaConstant), U8(117),
-  B(Star), R(0),
-  B(LdaConstant), U8(118),
-  B(Star), R(0),
-  B(LdaConstant), U8(119),
-  B(Star), R(0),
-  B(LdaConstant), U8(120),
-  B(Star), R(0),
-  B(LdaConstant), U8(121),
-  B(Star), R(0),
-  B(LdaConstant), U8(122),
-  B(Star), R(0),
-  B(LdaConstant), U8(123),
-  B(Star), R(0),
-  B(LdaConstant), U8(124),
-  B(Star), R(0),
-  B(LdaConstant), U8(125),
-  B(Star), R(0),
-  B(LdaConstant), U8(126),
-  B(Star), R(0),
-  B(LdaConstant), U8(127),
-  B(Star), R(0),
-  B(LdaConstant), U8(128),
-  B(Star), R(0),
-  B(LdaConstant), U8(129),
-  B(Star), R(0),
-  B(LdaConstant), U8(130),
-  B(Star), R(0),
-  B(LdaConstant), U8(131),
-  B(Star), R(0),
-  B(LdaConstant), U8(132),
-  B(Star), R(0),
-  B(LdaConstant), U8(133),
-  B(Star), R(0),
-  B(LdaConstant), U8(134),
-  B(Star), R(0),
-  B(LdaConstant), U8(135),
-  B(Star), R(0),
-  B(LdaConstant), U8(136),
-  B(Star), R(0),
-  B(LdaConstant), U8(137),
-  B(Star), R(0),
-  B(LdaConstant), U8(138),
-  B(Star), R(0),
-  B(LdaConstant), U8(139),
-  B(Star), R(0),
-  B(LdaConstant), U8(140),
-  B(Star), R(0),
-  B(LdaConstant), U8(141),
-  B(Star), R(0),
-  B(LdaConstant), U8(142),
-  B(Star), R(0),
-  B(LdaConstant), U8(143),
-  B(Star), R(0),
-  B(LdaConstant), U8(144),
-  B(Star), R(0),
-  B(LdaConstant), U8(145),
-  B(Star), R(0),
-  B(LdaConstant), U8(146),
-  B(Star), R(0),
-  B(LdaConstant), U8(147),
-  B(Star), R(0),
-  B(LdaConstant), U8(148),
-  B(Star), R(0),
-  B(LdaConstant), U8(149),
-  B(Star), R(0),
-  B(LdaConstant), U8(150),
-  B(Star), R(0),
-  B(LdaConstant), U8(151),
-  B(Star), R(0),
-  B(LdaConstant), U8(152),
-  B(Star), R(0),
-  B(LdaConstant), U8(153),
-  B(Star), R(0),
-  B(LdaConstant), U8(154),
-  B(Star), R(0),
-  B(LdaConstant), U8(155),
-  B(Star), R(0),
-  B(LdaConstant), U8(156),
-  B(Star), R(0),
-  B(LdaConstant), U8(157),
-  B(Star), R(0),
-  B(LdaConstant), U8(158),
-  B(Star), R(0),
-  B(LdaConstant), U8(159),
-  B(Star), R(0),
-  B(LdaConstant), U8(160),
-  B(Star), R(0),
-  B(LdaConstant), U8(161),
-  B(Star), R(0),
-  B(LdaConstant), U8(162),
-  B(Star), R(0),
-  B(LdaConstant), U8(163),
-  B(Star), R(0),
-  B(LdaConstant), U8(164),
-  B(Star), R(0),
-  B(LdaConstant), U8(165),
-  B(Star), R(0),
-  B(LdaConstant), U8(166),
-  B(Star), R(0),
-  B(LdaConstant), U8(167),
-  B(Star), R(0),
-  B(LdaConstant), U8(168),
-  B(Star), R(0),
-  B(LdaConstant), U8(169),
-  B(Star), R(0),
-  B(LdaConstant), U8(170),
-  B(Star), R(0),
-  B(LdaConstant), U8(171),
-  B(Star), R(0),
-  B(LdaConstant), U8(172),
-  B(Star), R(0),
-  B(LdaConstant), U8(173),
-  B(Star), R(0),
-  B(LdaConstant), U8(174),
-  B(Star), R(0),
-  B(LdaConstant), U8(175),
-  B(Star), R(0),
-  B(LdaConstant), U8(176),
-  B(Star), R(0),
-  B(LdaConstant), U8(177),
-  B(Star), R(0),
-  B(LdaConstant), U8(178),
-  B(Star), R(0),
-  B(LdaConstant), U8(179),
-  B(Star), R(0),
-  B(LdaConstant), U8(180),
-  B(Star), R(0),
-  B(LdaConstant), U8(181),
-  B(Star), R(0),
-  B(LdaConstant), U8(182),
-  B(Star), R(0),
-  B(LdaConstant), U8(183),
-  B(Star), R(0),
-  B(LdaConstant), U8(184),
-  B(Star), R(0),
-  B(LdaConstant), U8(185),
-  B(Star), R(0),
-  B(LdaConstant), U8(186),
-  B(Star), R(0),
-  B(LdaConstant), U8(187),
-  B(Star), R(0),
-  B(LdaConstant), U8(188),
-  B(Star), R(0),
-  B(LdaConstant), U8(189),
-  B(Star), R(0),
-  B(LdaConstant), U8(190),
-  B(Star), R(0),
-  B(LdaConstant), U8(191),
-  B(Star), R(0),
-  B(LdaConstant), U8(192),
-  B(Star), R(0),
-  B(LdaConstant), U8(193),
-  B(Star), R(0),
-  B(LdaConstant), U8(194),
-  B(Star), R(0),
-  B(LdaConstant), U8(195),
-  B(Star), R(0),
-  B(LdaConstant), U8(196),
-  B(Star), R(0),
-  B(LdaConstant), U8(197),
-  B(Star), R(0),
-  B(LdaConstant), U8(198),
-  B(Star), R(0),
-  B(LdaConstant), U8(199),
-  B(Star), R(0),
-  B(LdaConstant), U8(200),
-  B(Star), R(0),
-  B(LdaConstant), U8(201),
-  B(Star), R(0),
-  B(LdaConstant), U8(202),
-  B(Star), R(0),
-  B(LdaConstant), U8(203),
-  B(Star), R(0),
-  B(LdaConstant), U8(204),
-  B(Star), R(0),
-  B(LdaConstant), U8(205),
-  B(Star), R(0),
-  B(LdaConstant), U8(206),
-  B(Star), R(0),
-  B(LdaConstant), U8(207),
-  B(Star), R(0),
-  B(LdaConstant), U8(208),
-  B(Star), R(0),
-  B(LdaConstant), U8(209),
-  B(Star), R(0),
-  B(LdaConstant), U8(210),
-  B(Star), R(0),
-  B(LdaConstant), U8(211),
-  B(Star), R(0),
-  B(LdaConstant), U8(212),
-  B(Star), R(0),
-  B(LdaConstant), U8(213),
-  B(Star), R(0),
-  B(LdaConstant), U8(214),
-  B(Star), R(0),
-  B(LdaConstant), U8(215),
-  B(Star), R(0),
-  B(LdaConstant), U8(216),
-  B(Star), R(0),
-  B(LdaConstant), U8(217),
-  B(Star), R(0),
-  B(LdaConstant), U8(218),
-  B(Star), R(0),
-  B(LdaConstant), U8(219),
-  B(Star), R(0),
-  B(LdaConstant), U8(220),
-  B(Star), R(0),
-  B(LdaConstant), U8(221),
-  B(Star), R(0),
-  B(LdaConstant), U8(222),
-  B(Star), R(0),
-  B(LdaConstant), U8(223),
-  B(Star), R(0),
-  B(LdaConstant), U8(224),
-  B(Star), R(0),
-  B(LdaConstant), U8(225),
-  B(Star), R(0),
-  B(LdaConstant), U8(226),
-  B(Star), R(0),
-  B(LdaConstant), U8(227),
-  B(Star), R(0),
-  B(LdaConstant), U8(228),
-  B(Star), R(0),
-  B(LdaConstant), U8(229),
-  B(Star), R(0),
-  B(LdaConstant), U8(230),
-  B(Star), R(0),
-  B(LdaConstant), U8(231),
-  B(Star), R(0),
-  B(LdaConstant), U8(232),
-  B(Star), R(0),
-  B(LdaConstant), U8(233),
-  B(Star), R(0),
-  B(LdaConstant), U8(234),
-  B(Star), R(0),
-  B(LdaConstant), U8(235),
-  B(Star), R(0),
-  B(LdaConstant), U8(236),
-  B(Star), R(0),
-  B(LdaConstant), U8(237),
-  B(Star), R(0),
-  B(LdaConstant), U8(238),
-  B(Star), R(0),
-  B(LdaConstant), U8(239),
-  B(Star), R(0),
-  B(LdaConstant), U8(240),
-  B(Star), R(0),
-  B(LdaConstant), U8(241),
-  B(Star), R(0),
-  B(LdaConstant), U8(242),
-  B(Star), R(0),
-  B(LdaConstant), U8(243),
-  B(Star), R(0),
-  B(LdaConstant), U8(244),
-  B(Star), R(0),
-  B(LdaConstant), U8(245),
-  B(Star), R(0),
-  B(LdaConstant), U8(246),
-  B(Star), R(0),
-  B(LdaConstant), U8(247),
-  B(Star), R(0),
-  B(LdaConstant), U8(248),
-  B(Star), R(0),
-  B(LdaConstant), U8(249),
-  B(Star), R(0),
-  B(LdaConstant), U8(250),
-  B(Star), R(0),
-  B(LdaConstant), U8(251),
-  B(Star), R(0),
-  B(LdaConstant), U8(252),
-  B(Star), R(0),
-  B(LdaConstant), U8(253),
-  B(Star), R(0),
-  B(LdaConstant), U8(254),
-  B(Star), R(0),
-  B(LdaConstant), U8(255),
-  B(Star), R(0),
-  B(LdaSmi), U8(10),
-  B(Wide), B(StaLookupSlotSloppy), U16(256),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   22 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   34 S> */ B(LdaConstant), U8(1),
+                B(Star), R(0),
+  /*   46 S> */ B(LdaConstant), U8(2),
+                B(Star), R(0),
+  /*   58 S> */ B(LdaConstant), U8(3),
+                B(Star), R(0),
+  /*   70 S> */ B(LdaConstant), U8(4),
+                B(Star), R(0),
+  /*   82 S> */ B(LdaConstant), U8(5),
+                B(Star), R(0),
+  /*   94 S> */ B(LdaConstant), U8(6),
+                B(Star), R(0),
+  /*  106 S> */ B(LdaConstant), U8(7),
+                B(Star), R(0),
+  /*  118 S> */ B(LdaConstant), U8(8),
+                B(Star), R(0),
+  /*  130 S> */ B(LdaConstant), U8(9),
+                B(Star), R(0),
+  /*  142 S> */ B(LdaConstant), U8(10),
+                B(Star), R(0),
+  /*  154 S> */ B(LdaConstant), U8(11),
+                B(Star), R(0),
+  /*  166 S> */ B(LdaConstant), U8(12),
+                B(Star), R(0),
+  /*  178 S> */ B(LdaConstant), U8(13),
+                B(Star), R(0),
+  /*  190 S> */ B(LdaConstant), U8(14),
+                B(Star), R(0),
+  /*  202 S> */ B(LdaConstant), U8(15),
+                B(Star), R(0),
+  /*  214 S> */ B(LdaConstant), U8(16),
+                B(Star), R(0),
+  /*  226 S> */ B(LdaConstant), U8(17),
+                B(Star), R(0),
+  /*  238 S> */ B(LdaConstant), U8(18),
+                B(Star), R(0),
+  /*  250 S> */ B(LdaConstant), U8(19),
+                B(Star), R(0),
+  /*  262 S> */ B(LdaConstant), U8(20),
+                B(Star), R(0),
+  /*  274 S> */ B(LdaConstant), U8(21),
+                B(Star), R(0),
+  /*  286 S> */ B(LdaConstant), U8(22),
+                B(Star), R(0),
+  /*  298 S> */ B(LdaConstant), U8(23),
+                B(Star), R(0),
+  /*  310 S> */ B(LdaConstant), U8(24),
+                B(Star), R(0),
+  /*  322 S> */ B(LdaConstant), U8(25),
+                B(Star), R(0),
+  /*  334 S> */ B(LdaConstant), U8(26),
+                B(Star), R(0),
+  /*  346 S> */ B(LdaConstant), U8(27),
+                B(Star), R(0),
+  /*  358 S> */ B(LdaConstant), U8(28),
+                B(Star), R(0),
+  /*  370 S> */ B(LdaConstant), U8(29),
+                B(Star), R(0),
+  /*  382 S> */ B(LdaConstant), U8(30),
+                B(Star), R(0),
+  /*  394 S> */ B(LdaConstant), U8(31),
+                B(Star), R(0),
+  /*  406 S> */ B(LdaConstant), U8(32),
+                B(Star), R(0),
+  /*  418 S> */ B(LdaConstant), U8(33),
+                B(Star), R(0),
+  /*  430 S> */ B(LdaConstant), U8(34),
+                B(Star), R(0),
+  /*  442 S> */ B(LdaConstant), U8(35),
+                B(Star), R(0),
+  /*  454 S> */ B(LdaConstant), U8(36),
+                B(Star), R(0),
+  /*  466 S> */ B(LdaConstant), U8(37),
+                B(Star), R(0),
+  /*  478 S> */ B(LdaConstant), U8(38),
+                B(Star), R(0),
+  /*  490 S> */ B(LdaConstant), U8(39),
+                B(Star), R(0),
+  /*  502 S> */ B(LdaConstant), U8(40),
+                B(Star), R(0),
+  /*  514 S> */ B(LdaConstant), U8(41),
+                B(Star), R(0),
+  /*  526 S> */ B(LdaConstant), U8(42),
+                B(Star), R(0),
+  /*  538 S> */ B(LdaConstant), U8(43),
+                B(Star), R(0),
+  /*  550 S> */ B(LdaConstant), U8(44),
+                B(Star), R(0),
+  /*  562 S> */ B(LdaConstant), U8(45),
+                B(Star), R(0),
+  /*  574 S> */ B(LdaConstant), U8(46),
+                B(Star), R(0),
+  /*  586 S> */ B(LdaConstant), U8(47),
+                B(Star), R(0),
+  /*  598 S> */ B(LdaConstant), U8(48),
+                B(Star), R(0),
+  /*  610 S> */ B(LdaConstant), U8(49),
+                B(Star), R(0),
+  /*  622 S> */ B(LdaConstant), U8(50),
+                B(Star), R(0),
+  /*  634 S> */ B(LdaConstant), U8(51),
+                B(Star), R(0),
+  /*  646 S> */ B(LdaConstant), U8(52),
+                B(Star), R(0),
+  /*  658 S> */ B(LdaConstant), U8(53),
+                B(Star), R(0),
+  /*  670 S> */ B(LdaConstant), U8(54),
+                B(Star), R(0),
+  /*  682 S> */ B(LdaConstant), U8(55),
+                B(Star), R(0),
+  /*  694 S> */ B(LdaConstant), U8(56),
+                B(Star), R(0),
+  /*  706 S> */ B(LdaConstant), U8(57),
+                B(Star), R(0),
+  /*  718 S> */ B(LdaConstant), U8(58),
+                B(Star), R(0),
+  /*  730 S> */ B(LdaConstant), U8(59),
+                B(Star), R(0),
+  /*  742 S> */ B(LdaConstant), U8(60),
+                B(Star), R(0),
+  /*  754 S> */ B(LdaConstant), U8(61),
+                B(Star), R(0),
+  /*  766 S> */ B(LdaConstant), U8(62),
+                B(Star), R(0),
+  /*  778 S> */ B(LdaConstant), U8(63),
+                B(Star), R(0),
+  /*  790 S> */ B(LdaConstant), U8(64),
+                B(Star), R(0),
+  /*  802 S> */ B(LdaConstant), U8(65),
+                B(Star), R(0),
+  /*  814 S> */ B(LdaConstant), U8(66),
+                B(Star), R(0),
+  /*  826 S> */ B(LdaConstant), U8(67),
+                B(Star), R(0),
+  /*  838 S> */ B(LdaConstant), U8(68),
+                B(Star), R(0),
+  /*  850 S> */ B(LdaConstant), U8(69),
+                B(Star), R(0),
+  /*  862 S> */ B(LdaConstant), U8(70),
+                B(Star), R(0),
+  /*  874 S> */ B(LdaConstant), U8(71),
+                B(Star), R(0),
+  /*  886 S> */ B(LdaConstant), U8(72),
+                B(Star), R(0),
+  /*  898 S> */ B(LdaConstant), U8(73),
+                B(Star), R(0),
+  /*  910 S> */ B(LdaConstant), U8(74),
+                B(Star), R(0),
+  /*  922 S> */ B(LdaConstant), U8(75),
+                B(Star), R(0),
+  /*  934 S> */ B(LdaConstant), U8(76),
+                B(Star), R(0),
+  /*  946 S> */ B(LdaConstant), U8(77),
+                B(Star), R(0),
+  /*  958 S> */ B(LdaConstant), U8(78),
+                B(Star), R(0),
+  /*  970 S> */ B(LdaConstant), U8(79),
+                B(Star), R(0),
+  /*  982 S> */ B(LdaConstant), U8(80),
+                B(Star), R(0),
+  /*  994 S> */ B(LdaConstant), U8(81),
+                B(Star), R(0),
+  /* 1006 S> */ B(LdaConstant), U8(82),
+                B(Star), R(0),
+  /* 1018 S> */ B(LdaConstant), U8(83),
+                B(Star), R(0),
+  /* 1030 S> */ B(LdaConstant), U8(84),
+                B(Star), R(0),
+  /* 1042 S> */ B(LdaConstant), U8(85),
+                B(Star), R(0),
+  /* 1054 S> */ B(LdaConstant), U8(86),
+                B(Star), R(0),
+  /* 1066 S> */ B(LdaConstant), U8(87),
+                B(Star), R(0),
+  /* 1078 S> */ B(LdaConstant), U8(88),
+                B(Star), R(0),
+  /* 1090 S> */ B(LdaConstant), U8(89),
+                B(Star), R(0),
+  /* 1102 S> */ B(LdaConstant), U8(90),
+                B(Star), R(0),
+  /* 1114 S> */ B(LdaConstant), U8(91),
+                B(Star), R(0),
+  /* 1126 S> */ B(LdaConstant), U8(92),
+                B(Star), R(0),
+  /* 1138 S> */ B(LdaConstant), U8(93),
+                B(Star), R(0),
+  /* 1150 S> */ B(LdaConstant), U8(94),
+                B(Star), R(0),
+  /* 1162 S> */ B(LdaConstant), U8(95),
+                B(Star), R(0),
+  /* 1174 S> */ B(LdaConstant), U8(96),
+                B(Star), R(0),
+  /* 1186 S> */ B(LdaConstant), U8(97),
+                B(Star), R(0),
+  /* 1198 S> */ B(LdaConstant), U8(98),
+                B(Star), R(0),
+  /* 1210 S> */ B(LdaConstant), U8(99),
+                B(Star), R(0),
+  /* 1222 S> */ B(LdaConstant), U8(100),
+                B(Star), R(0),
+  /* 1234 S> */ B(LdaConstant), U8(101),
+                B(Star), R(0),
+  /* 1246 S> */ B(LdaConstant), U8(102),
+                B(Star), R(0),
+  /* 1258 S> */ B(LdaConstant), U8(103),
+                B(Star), R(0),
+  /* 1270 S> */ B(LdaConstant), U8(104),
+                B(Star), R(0),
+  /* 1282 S> */ B(LdaConstant), U8(105),
+                B(Star), R(0),
+  /* 1294 S> */ B(LdaConstant), U8(106),
+                B(Star), R(0),
+  /* 1306 S> */ B(LdaConstant), U8(107),
+                B(Star), R(0),
+  /* 1318 S> */ B(LdaConstant), U8(108),
+                B(Star), R(0),
+  /* 1330 S> */ B(LdaConstant), U8(109),
+                B(Star), R(0),
+  /* 1342 S> */ B(LdaConstant), U8(110),
+                B(Star), R(0),
+  /* 1354 S> */ B(LdaConstant), U8(111),
+                B(Star), R(0),
+  /* 1366 S> */ B(LdaConstant), U8(112),
+                B(Star), R(0),
+  /* 1378 S> */ B(LdaConstant), U8(113),
+                B(Star), R(0),
+  /* 1390 S> */ B(LdaConstant), U8(114),
+                B(Star), R(0),
+  /* 1402 S> */ B(LdaConstant), U8(115),
+                B(Star), R(0),
+  /* 1414 S> */ B(LdaConstant), U8(116),
+                B(Star), R(0),
+  /* 1426 S> */ B(LdaConstant), U8(117),
+                B(Star), R(0),
+  /* 1438 S> */ B(LdaConstant), U8(118),
+                B(Star), R(0),
+  /* 1450 S> */ B(LdaConstant), U8(119),
+                B(Star), R(0),
+  /* 1462 S> */ B(LdaConstant), U8(120),
+                B(Star), R(0),
+  /* 1474 S> */ B(LdaConstant), U8(121),
+                B(Star), R(0),
+  /* 1486 S> */ B(LdaConstant), U8(122),
+                B(Star), R(0),
+  /* 1498 S> */ B(LdaConstant), U8(123),
+                B(Star), R(0),
+  /* 1510 S> */ B(LdaConstant), U8(124),
+                B(Star), R(0),
+  /* 1522 S> */ B(LdaConstant), U8(125),
+                B(Star), R(0),
+  /* 1534 S> */ B(LdaConstant), U8(126),
+                B(Star), R(0),
+  /* 1546 S> */ B(LdaConstant), U8(127),
+                B(Star), R(0),
+  /* 1558 S> */ B(LdaConstant), U8(128),
+                B(Star), R(0),
+  /* 1570 S> */ B(LdaConstant), U8(129),
+                B(Star), R(0),
+  /* 1582 S> */ B(LdaConstant), U8(130),
+                B(Star), R(0),
+  /* 1594 S> */ B(LdaConstant), U8(131),
+                B(Star), R(0),
+  /* 1606 S> */ B(LdaConstant), U8(132),
+                B(Star), R(0),
+  /* 1618 S> */ B(LdaConstant), U8(133),
+                B(Star), R(0),
+  /* 1630 S> */ B(LdaConstant), U8(134),
+                B(Star), R(0),
+  /* 1642 S> */ B(LdaConstant), U8(135),
+                B(Star), R(0),
+  /* 1654 S> */ B(LdaConstant), U8(136),
+                B(Star), R(0),
+  /* 1666 S> */ B(LdaConstant), U8(137),
+                B(Star), R(0),
+  /* 1678 S> */ B(LdaConstant), U8(138),
+                B(Star), R(0),
+  /* 1690 S> */ B(LdaConstant), U8(139),
+                B(Star), R(0),
+  /* 1702 S> */ B(LdaConstant), U8(140),
+                B(Star), R(0),
+  /* 1714 S> */ B(LdaConstant), U8(141),
+                B(Star), R(0),
+  /* 1726 S> */ B(LdaConstant), U8(142),
+                B(Star), R(0),
+  /* 1738 S> */ B(LdaConstant), U8(143),
+                B(Star), R(0),
+  /* 1750 S> */ B(LdaConstant), U8(144),
+                B(Star), R(0),
+  /* 1762 S> */ B(LdaConstant), U8(145),
+                B(Star), R(0),
+  /* 1774 S> */ B(LdaConstant), U8(146),
+                B(Star), R(0),
+  /* 1786 S> */ B(LdaConstant), U8(147),
+                B(Star), R(0),
+  /* 1798 S> */ B(LdaConstant), U8(148),
+                B(Star), R(0),
+  /* 1810 S> */ B(LdaConstant), U8(149),
+                B(Star), R(0),
+  /* 1822 S> */ B(LdaConstant), U8(150),
+                B(Star), R(0),
+  /* 1834 S> */ B(LdaConstant), U8(151),
+                B(Star), R(0),
+  /* 1846 S> */ B(LdaConstant), U8(152),
+                B(Star), R(0),
+  /* 1858 S> */ B(LdaConstant), U8(153),
+                B(Star), R(0),
+  /* 1870 S> */ B(LdaConstant), U8(154),
+                B(Star), R(0),
+  /* 1882 S> */ B(LdaConstant), U8(155),
+                B(Star), R(0),
+  /* 1894 S> */ B(LdaConstant), U8(156),
+                B(Star), R(0),
+  /* 1906 S> */ B(LdaConstant), U8(157),
+                B(Star), R(0),
+  /* 1918 S> */ B(LdaConstant), U8(158),
+                B(Star), R(0),
+  /* 1930 S> */ B(LdaConstant), U8(159),
+                B(Star), R(0),
+  /* 1942 S> */ B(LdaConstant), U8(160),
+                B(Star), R(0),
+  /* 1954 S> */ B(LdaConstant), U8(161),
+                B(Star), R(0),
+  /* 1966 S> */ B(LdaConstant), U8(162),
+                B(Star), R(0),
+  /* 1978 S> */ B(LdaConstant), U8(163),
+                B(Star), R(0),
+  /* 1990 S> */ B(LdaConstant), U8(164),
+                B(Star), R(0),
+  /* 2002 S> */ B(LdaConstant), U8(165),
+                B(Star), R(0),
+  /* 2014 S> */ B(LdaConstant), U8(166),
+                B(Star), R(0),
+  /* 2026 S> */ B(LdaConstant), U8(167),
+                B(Star), R(0),
+  /* 2038 S> */ B(LdaConstant), U8(168),
+                B(Star), R(0),
+  /* 2050 S> */ B(LdaConstant), U8(169),
+                B(Star), R(0),
+  /* 2062 S> */ B(LdaConstant), U8(170),
+                B(Star), R(0),
+  /* 2074 S> */ B(LdaConstant), U8(171),
+                B(Star), R(0),
+  /* 2086 S> */ B(LdaConstant), U8(172),
+                B(Star), R(0),
+  /* 2098 S> */ B(LdaConstant), U8(173),
+                B(Star), R(0),
+  /* 2110 S> */ B(LdaConstant), U8(174),
+                B(Star), R(0),
+  /* 2122 S> */ B(LdaConstant), U8(175),
+                B(Star), R(0),
+  /* 2134 S> */ B(LdaConstant), U8(176),
+                B(Star), R(0),
+  /* 2146 S> */ B(LdaConstant), U8(177),
+                B(Star), R(0),
+  /* 2158 S> */ B(LdaConstant), U8(178),
+                B(Star), R(0),
+  /* 2170 S> */ B(LdaConstant), U8(179),
+                B(Star), R(0),
+  /* 2182 S> */ B(LdaConstant), U8(180),
+                B(Star), R(0),
+  /* 2194 S> */ B(LdaConstant), U8(181),
+                B(Star), R(0),
+  /* 2206 S> */ B(LdaConstant), U8(182),
+                B(Star), R(0),
+  /* 2218 S> */ B(LdaConstant), U8(183),
+                B(Star), R(0),
+  /* 2230 S> */ B(LdaConstant), U8(184),
+                B(Star), R(0),
+  /* 2242 S> */ B(LdaConstant), U8(185),
+                B(Star), R(0),
+  /* 2254 S> */ B(LdaConstant), U8(186),
+                B(Star), R(0),
+  /* 2266 S> */ B(LdaConstant), U8(187),
+                B(Star), R(0),
+  /* 2278 S> */ B(LdaConstant), U8(188),
+                B(Star), R(0),
+  /* 2290 S> */ B(LdaConstant), U8(189),
+                B(Star), R(0),
+  /* 2302 S> */ B(LdaConstant), U8(190),
+                B(Star), R(0),
+  /* 2314 S> */ B(LdaConstant), U8(191),
+                B(Star), R(0),
+  /* 2326 S> */ B(LdaConstant), U8(192),
+                B(Star), R(0),
+  /* 2338 S> */ B(LdaConstant), U8(193),
+                B(Star), R(0),
+  /* 2350 S> */ B(LdaConstant), U8(194),
+                B(Star), R(0),
+  /* 2362 S> */ B(LdaConstant), U8(195),
+                B(Star), R(0),
+  /* 2374 S> */ B(LdaConstant), U8(196),
+                B(Star), R(0),
+  /* 2386 S> */ B(LdaConstant), U8(197),
+                B(Star), R(0),
+  /* 2398 S> */ B(LdaConstant), U8(198),
+                B(Star), R(0),
+  /* 2410 S> */ B(LdaConstant), U8(199),
+                B(Star), R(0),
+  /* 2422 S> */ B(LdaConstant), U8(200),
+                B(Star), R(0),
+  /* 2434 S> */ B(LdaConstant), U8(201),
+                B(Star), R(0),
+  /* 2446 S> */ B(LdaConstant), U8(202),
+                B(Star), R(0),
+  /* 2458 S> */ B(LdaConstant), U8(203),
+                B(Star), R(0),
+  /* 2470 S> */ B(LdaConstant), U8(204),
+                B(Star), R(0),
+  /* 2482 S> */ B(LdaConstant), U8(205),
+                B(Star), R(0),
+  /* 2494 S> */ B(LdaConstant), U8(206),
+                B(Star), R(0),
+  /* 2506 S> */ B(LdaConstant), U8(207),
+                B(Star), R(0),
+  /* 2518 S> */ B(LdaConstant), U8(208),
+                B(Star), R(0),
+  /* 2530 S> */ B(LdaConstant), U8(209),
+                B(Star), R(0),
+  /* 2542 S> */ B(LdaConstant), U8(210),
+                B(Star), R(0),
+  /* 2554 S> */ B(LdaConstant), U8(211),
+                B(Star), R(0),
+  /* 2566 S> */ B(LdaConstant), U8(212),
+                B(Star), R(0),
+  /* 2578 S> */ B(LdaConstant), U8(213),
+                B(Star), R(0),
+  /* 2590 S> */ B(LdaConstant), U8(214),
+                B(Star), R(0),
+  /* 2602 S> */ B(LdaConstant), U8(215),
+                B(Star), R(0),
+  /* 2614 S> */ B(LdaConstant), U8(216),
+                B(Star), R(0),
+  /* 2626 S> */ B(LdaConstant), U8(217),
+                B(Star), R(0),
+  /* 2638 S> */ B(LdaConstant), U8(218),
+                B(Star), R(0),
+  /* 2650 S> */ B(LdaConstant), U8(219),
+                B(Star), R(0),
+  /* 2662 S> */ B(LdaConstant), U8(220),
+                B(Star), R(0),
+  /* 2674 S> */ B(LdaConstant), U8(221),
+                B(Star), R(0),
+  /* 2686 S> */ B(LdaConstant), U8(222),
+                B(Star), R(0),
+  /* 2698 S> */ B(LdaConstant), U8(223),
+                B(Star), R(0),
+  /* 2710 S> */ B(LdaConstant), U8(224),
+                B(Star), R(0),
+  /* 2722 S> */ B(LdaConstant), U8(225),
+                B(Star), R(0),
+  /* 2734 S> */ B(LdaConstant), U8(226),
+                B(Star), R(0),
+  /* 2746 S> */ B(LdaConstant), U8(227),
+                B(Star), R(0),
+  /* 2758 S> */ B(LdaConstant), U8(228),
+                B(Star), R(0),
+  /* 2770 S> */ B(LdaConstant), U8(229),
+                B(Star), R(0),
+  /* 2782 S> */ B(LdaConstant), U8(230),
+                B(Star), R(0),
+  /* 2794 S> */ B(LdaConstant), U8(231),
+                B(Star), R(0),
+  /* 2806 S> */ B(LdaConstant), U8(232),
+                B(Star), R(0),
+  /* 2818 S> */ B(LdaConstant), U8(233),
+                B(Star), R(0),
+  /* 2830 S> */ B(LdaConstant), U8(234),
+                B(Star), R(0),
+  /* 2842 S> */ B(LdaConstant), U8(235),
+                B(Star), R(0),
+  /* 2854 S> */ B(LdaConstant), U8(236),
+                B(Star), R(0),
+  /* 2866 S> */ B(LdaConstant), U8(237),
+                B(Star), R(0),
+  /* 2878 S> */ B(LdaConstant), U8(238),
+                B(Star), R(0),
+  /* 2890 S> */ B(LdaConstant), U8(239),
+                B(Star), R(0),
+  /* 2902 S> */ B(LdaConstant), U8(240),
+                B(Star), R(0),
+  /* 2914 S> */ B(LdaConstant), U8(241),
+                B(Star), R(0),
+  /* 2926 S> */ B(LdaConstant), U8(242),
+                B(Star), R(0),
+  /* 2938 S> */ B(LdaConstant), U8(243),
+                B(Star), R(0),
+  /* 2950 S> */ B(LdaConstant), U8(244),
+                B(Star), R(0),
+  /* 2962 S> */ B(LdaConstant), U8(245),
+                B(Star), R(0),
+  /* 2974 S> */ B(LdaConstant), U8(246),
+                B(Star), R(0),
+  /* 2986 S> */ B(LdaConstant), U8(247),
+                B(Star), R(0),
+  /* 2998 S> */ B(LdaConstant), U8(248),
+                B(Star), R(0),
+  /* 3010 S> */ B(LdaConstant), U8(249),
+                B(Star), R(0),
+  /* 3022 S> */ B(LdaConstant), U8(250),
+                B(Star), R(0),
+  /* 3034 S> */ B(LdaConstant), U8(251),
+                B(Star), R(0),
+  /* 3046 S> */ B(LdaConstant), U8(252),
+                B(Star), R(0),
+  /* 3058 S> */ B(LdaConstant), U8(253),
+                B(Star), R(0),
+  /* 3070 S> */ B(LdaConstant), U8(254),
+                B(Star), R(0),
+  /* 3082 S> */ B(LdaConstant), U8(255),
+                B(Star), R(0),
+  /* 3086 S> */ B(LdaSmi), U8(10),
+  /* 3088 E> */ B(Wide), B(StaLookupSlotSloppy), U16(256),
+                B(LdaUndefined),
+  /* 3093 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::HEAP_NUMBER_TYPE,
@@ -3438,523 +3438,523 @@
 parameter count: 1
 bytecode array length: 1033
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(LdaConstant), U8(1),
-  B(Star), R(0),
-  B(LdaConstant), U8(2),
-  B(Star), R(0),
-  B(LdaConstant), U8(3),
-  B(Star), R(0),
-  B(LdaConstant), U8(4),
-  B(Star), R(0),
-  B(LdaConstant), U8(5),
-  B(Star), R(0),
-  B(LdaConstant), U8(6),
-  B(Star), R(0),
-  B(LdaConstant), U8(7),
-  B(Star), R(0),
-  B(LdaConstant), U8(8),
-  B(Star), R(0),
-  B(LdaConstant), U8(9),
-  B(Star), R(0),
-  B(LdaConstant), U8(10),
-  B(Star), R(0),
-  B(LdaConstant), U8(11),
-  B(Star), R(0),
-  B(LdaConstant), U8(12),
-  B(Star), R(0),
-  B(LdaConstant), U8(13),
-  B(Star), R(0),
-  B(LdaConstant), U8(14),
-  B(Star), R(0),
-  B(LdaConstant), U8(15),
-  B(Star), R(0),
-  B(LdaConstant), U8(16),
-  B(Star), R(0),
-  B(LdaConstant), U8(17),
-  B(Star), R(0),
-  B(LdaConstant), U8(18),
-  B(Star), R(0),
-  B(LdaConstant), U8(19),
-  B(Star), R(0),
-  B(LdaConstant), U8(20),
-  B(Star), R(0),
-  B(LdaConstant), U8(21),
-  B(Star), R(0),
-  B(LdaConstant), U8(22),
-  B(Star), R(0),
-  B(LdaConstant), U8(23),
-  B(Star), R(0),
-  B(LdaConstant), U8(24),
-  B(Star), R(0),
-  B(LdaConstant), U8(25),
-  B(Star), R(0),
-  B(LdaConstant), U8(26),
-  B(Star), R(0),
-  B(LdaConstant), U8(27),
-  B(Star), R(0),
-  B(LdaConstant), U8(28),
-  B(Star), R(0),
-  B(LdaConstant), U8(29),
-  B(Star), R(0),
-  B(LdaConstant), U8(30),
-  B(Star), R(0),
-  B(LdaConstant), U8(31),
-  B(Star), R(0),
-  B(LdaConstant), U8(32),
-  B(Star), R(0),
-  B(LdaConstant), U8(33),
-  B(Star), R(0),
-  B(LdaConstant), U8(34),
-  B(Star), R(0),
-  B(LdaConstant), U8(35),
-  B(Star), R(0),
-  B(LdaConstant), U8(36),
-  B(Star), R(0),
-  B(LdaConstant), U8(37),
-  B(Star), R(0),
-  B(LdaConstant), U8(38),
-  B(Star), R(0),
-  B(LdaConstant), U8(39),
-  B(Star), R(0),
-  B(LdaConstant), U8(40),
-  B(Star), R(0),
-  B(LdaConstant), U8(41),
-  B(Star), R(0),
-  B(LdaConstant), U8(42),
-  B(Star), R(0),
-  B(LdaConstant), U8(43),
-  B(Star), R(0),
-  B(LdaConstant), U8(44),
-  B(Star), R(0),
-  B(LdaConstant), U8(45),
-  B(Star), R(0),
-  B(LdaConstant), U8(46),
-  B(Star), R(0),
-  B(LdaConstant), U8(47),
-  B(Star), R(0),
-  B(LdaConstant), U8(48),
-  B(Star), R(0),
-  B(LdaConstant), U8(49),
-  B(Star), R(0),
-  B(LdaConstant), U8(50),
-  B(Star), R(0),
-  B(LdaConstant), U8(51),
-  B(Star), R(0),
-  B(LdaConstant), U8(52),
-  B(Star), R(0),
-  B(LdaConstant), U8(53),
-  B(Star), R(0),
-  B(LdaConstant), U8(54),
-  B(Star), R(0),
-  B(LdaConstant), U8(55),
-  B(Star), R(0),
-  B(LdaConstant), U8(56),
-  B(Star), R(0),
-  B(LdaConstant), U8(57),
-  B(Star), R(0),
-  B(LdaConstant), U8(58),
-  B(Star), R(0),
-  B(LdaConstant), U8(59),
-  B(Star), R(0),
-  B(LdaConstant), U8(60),
-  B(Star), R(0),
-  B(LdaConstant), U8(61),
-  B(Star), R(0),
-  B(LdaConstant), U8(62),
-  B(Star), R(0),
-  B(LdaConstant), U8(63),
-  B(Star), R(0),
-  B(LdaConstant), U8(64),
-  B(Star), R(0),
-  B(LdaConstant), U8(65),
-  B(Star), R(0),
-  B(LdaConstant), U8(66),
-  B(Star), R(0),
-  B(LdaConstant), U8(67),
-  B(Star), R(0),
-  B(LdaConstant), U8(68),
-  B(Star), R(0),
-  B(LdaConstant), U8(69),
-  B(Star), R(0),
-  B(LdaConstant), U8(70),
-  B(Star), R(0),
-  B(LdaConstant), U8(71),
-  B(Star), R(0),
-  B(LdaConstant), U8(72),
-  B(Star), R(0),
-  B(LdaConstant), U8(73),
-  B(Star), R(0),
-  B(LdaConstant), U8(74),
-  B(Star), R(0),
-  B(LdaConstant), U8(75),
-  B(Star), R(0),
-  B(LdaConstant), U8(76),
-  B(Star), R(0),
-  B(LdaConstant), U8(77),
-  B(Star), R(0),
-  B(LdaConstant), U8(78),
-  B(Star), R(0),
-  B(LdaConstant), U8(79),
-  B(Star), R(0),
-  B(LdaConstant), U8(80),
-  B(Star), R(0),
-  B(LdaConstant), U8(81),
-  B(Star), R(0),
-  B(LdaConstant), U8(82),
-  B(Star), R(0),
-  B(LdaConstant), U8(83),
-  B(Star), R(0),
-  B(LdaConstant), U8(84),
-  B(Star), R(0),
-  B(LdaConstant), U8(85),
-  B(Star), R(0),
-  B(LdaConstant), U8(86),
-  B(Star), R(0),
-  B(LdaConstant), U8(87),
-  B(Star), R(0),
-  B(LdaConstant), U8(88),
-  B(Star), R(0),
-  B(LdaConstant), U8(89),
-  B(Star), R(0),
-  B(LdaConstant), U8(90),
-  B(Star), R(0),
-  B(LdaConstant), U8(91),
-  B(Star), R(0),
-  B(LdaConstant), U8(92),
-  B(Star), R(0),
-  B(LdaConstant), U8(93),
-  B(Star), R(0),
-  B(LdaConstant), U8(94),
-  B(Star), R(0),
-  B(LdaConstant), U8(95),
-  B(Star), R(0),
-  B(LdaConstant), U8(96),
-  B(Star), R(0),
-  B(LdaConstant), U8(97),
-  B(Star), R(0),
-  B(LdaConstant), U8(98),
-  B(Star), R(0),
-  B(LdaConstant), U8(99),
-  B(Star), R(0),
-  B(LdaConstant), U8(100),
-  B(Star), R(0),
-  B(LdaConstant), U8(101),
-  B(Star), R(0),
-  B(LdaConstant), U8(102),
-  B(Star), R(0),
-  B(LdaConstant), U8(103),
-  B(Star), R(0),
-  B(LdaConstant), U8(104),
-  B(Star), R(0),
-  B(LdaConstant), U8(105),
-  B(Star), R(0),
-  B(LdaConstant), U8(106),
-  B(Star), R(0),
-  B(LdaConstant), U8(107),
-  B(Star), R(0),
-  B(LdaConstant), U8(108),
-  B(Star), R(0),
-  B(LdaConstant), U8(109),
-  B(Star), R(0),
-  B(LdaConstant), U8(110),
-  B(Star), R(0),
-  B(LdaConstant), U8(111),
-  B(Star), R(0),
-  B(LdaConstant), U8(112),
-  B(Star), R(0),
-  B(LdaConstant), U8(113),
-  B(Star), R(0),
-  B(LdaConstant), U8(114),
-  B(Star), R(0),
-  B(LdaConstant), U8(115),
-  B(Star), R(0),
-  B(LdaConstant), U8(116),
-  B(Star), R(0),
-  B(LdaConstant), U8(117),
-  B(Star), R(0),
-  B(LdaConstant), U8(118),
-  B(Star), R(0),
-  B(LdaConstant), U8(119),
-  B(Star), R(0),
-  B(LdaConstant), U8(120),
-  B(Star), R(0),
-  B(LdaConstant), U8(121),
-  B(Star), R(0),
-  B(LdaConstant), U8(122),
-  B(Star), R(0),
-  B(LdaConstant), U8(123),
-  B(Star), R(0),
-  B(LdaConstant), U8(124),
-  B(Star), R(0),
-  B(LdaConstant), U8(125),
-  B(Star), R(0),
-  B(LdaConstant), U8(126),
-  B(Star), R(0),
-  B(LdaConstant), U8(127),
-  B(Star), R(0),
-  B(LdaConstant), U8(128),
-  B(Star), R(0),
-  B(LdaConstant), U8(129),
-  B(Star), R(0),
-  B(LdaConstant), U8(130),
-  B(Star), R(0),
-  B(LdaConstant), U8(131),
-  B(Star), R(0),
-  B(LdaConstant), U8(132),
-  B(Star), R(0),
-  B(LdaConstant), U8(133),
-  B(Star), R(0),
-  B(LdaConstant), U8(134),
-  B(Star), R(0),
-  B(LdaConstant), U8(135),
-  B(Star), R(0),
-  B(LdaConstant), U8(136),
-  B(Star), R(0),
-  B(LdaConstant), U8(137),
-  B(Star), R(0),
-  B(LdaConstant), U8(138),
-  B(Star), R(0),
-  B(LdaConstant), U8(139),
-  B(Star), R(0),
-  B(LdaConstant), U8(140),
-  B(Star), R(0),
-  B(LdaConstant), U8(141),
-  B(Star), R(0),
-  B(LdaConstant), U8(142),
-  B(Star), R(0),
-  B(LdaConstant), U8(143),
-  B(Star), R(0),
-  B(LdaConstant), U8(144),
-  B(Star), R(0),
-  B(LdaConstant), U8(145),
-  B(Star), R(0),
-  B(LdaConstant), U8(146),
-  B(Star), R(0),
-  B(LdaConstant), U8(147),
-  B(Star), R(0),
-  B(LdaConstant), U8(148),
-  B(Star), R(0),
-  B(LdaConstant), U8(149),
-  B(Star), R(0),
-  B(LdaConstant), U8(150),
-  B(Star), R(0),
-  B(LdaConstant), U8(151),
-  B(Star), R(0),
-  B(LdaConstant), U8(152),
-  B(Star), R(0),
-  B(LdaConstant), U8(153),
-  B(Star), R(0),
-  B(LdaConstant), U8(154),
-  B(Star), R(0),
-  B(LdaConstant), U8(155),
-  B(Star), R(0),
-  B(LdaConstant), U8(156),
-  B(Star), R(0),
-  B(LdaConstant), U8(157),
-  B(Star), R(0),
-  B(LdaConstant), U8(158),
-  B(Star), R(0),
-  B(LdaConstant), U8(159),
-  B(Star), R(0),
-  B(LdaConstant), U8(160),
-  B(Star), R(0),
-  B(LdaConstant), U8(161),
-  B(Star), R(0),
-  B(LdaConstant), U8(162),
-  B(Star), R(0),
-  B(LdaConstant), U8(163),
-  B(Star), R(0),
-  B(LdaConstant), U8(164),
-  B(Star), R(0),
-  B(LdaConstant), U8(165),
-  B(Star), R(0),
-  B(LdaConstant), U8(166),
-  B(Star), R(0),
-  B(LdaConstant), U8(167),
-  B(Star), R(0),
-  B(LdaConstant), U8(168),
-  B(Star), R(0),
-  B(LdaConstant), U8(169),
-  B(Star), R(0),
-  B(LdaConstant), U8(170),
-  B(Star), R(0),
-  B(LdaConstant), U8(171),
-  B(Star), R(0),
-  B(LdaConstant), U8(172),
-  B(Star), R(0),
-  B(LdaConstant), U8(173),
-  B(Star), R(0),
-  B(LdaConstant), U8(174),
-  B(Star), R(0),
-  B(LdaConstant), U8(175),
-  B(Star), R(0),
-  B(LdaConstant), U8(176),
-  B(Star), R(0),
-  B(LdaConstant), U8(177),
-  B(Star), R(0),
-  B(LdaConstant), U8(178),
-  B(Star), R(0),
-  B(LdaConstant), U8(179),
-  B(Star), R(0),
-  B(LdaConstant), U8(180),
-  B(Star), R(0),
-  B(LdaConstant), U8(181),
-  B(Star), R(0),
-  B(LdaConstant), U8(182),
-  B(Star), R(0),
-  B(LdaConstant), U8(183),
-  B(Star), R(0),
-  B(LdaConstant), U8(184),
-  B(Star), R(0),
-  B(LdaConstant), U8(185),
-  B(Star), R(0),
-  B(LdaConstant), U8(186),
-  B(Star), R(0),
-  B(LdaConstant), U8(187),
-  B(Star), R(0),
-  B(LdaConstant), U8(188),
-  B(Star), R(0),
-  B(LdaConstant), U8(189),
-  B(Star), R(0),
-  B(LdaConstant), U8(190),
-  B(Star), R(0),
-  B(LdaConstant), U8(191),
-  B(Star), R(0),
-  B(LdaConstant), U8(192),
-  B(Star), R(0),
-  B(LdaConstant), U8(193),
-  B(Star), R(0),
-  B(LdaConstant), U8(194),
-  B(Star), R(0),
-  B(LdaConstant), U8(195),
-  B(Star), R(0),
-  B(LdaConstant), U8(196),
-  B(Star), R(0),
-  B(LdaConstant), U8(197),
-  B(Star), R(0),
-  B(LdaConstant), U8(198),
-  B(Star), R(0),
-  B(LdaConstant), U8(199),
-  B(Star), R(0),
-  B(LdaConstant), U8(200),
-  B(Star), R(0),
-  B(LdaConstant), U8(201),
-  B(Star), R(0),
-  B(LdaConstant), U8(202),
-  B(Star), R(0),
-  B(LdaConstant), U8(203),
-  B(Star), R(0),
-  B(LdaConstant), U8(204),
-  B(Star), R(0),
-  B(LdaConstant), U8(205),
-  B(Star), R(0),
-  B(LdaConstant), U8(206),
-  B(Star), R(0),
-  B(LdaConstant), U8(207),
-  B(Star), R(0),
-  B(LdaConstant), U8(208),
-  B(Star), R(0),
-  B(LdaConstant), U8(209),
-  B(Star), R(0),
-  B(LdaConstant), U8(210),
-  B(Star), R(0),
-  B(LdaConstant), U8(211),
-  B(Star), R(0),
-  B(LdaConstant), U8(212),
-  B(Star), R(0),
-  B(LdaConstant), U8(213),
-  B(Star), R(0),
-  B(LdaConstant), U8(214),
-  B(Star), R(0),
-  B(LdaConstant), U8(215),
-  B(Star), R(0),
-  B(LdaConstant), U8(216),
-  B(Star), R(0),
-  B(LdaConstant), U8(217),
-  B(Star), R(0),
-  B(LdaConstant), U8(218),
-  B(Star), R(0),
-  B(LdaConstant), U8(219),
-  B(Star), R(0),
-  B(LdaConstant), U8(220),
-  B(Star), R(0),
-  B(LdaConstant), U8(221),
-  B(Star), R(0),
-  B(LdaConstant), U8(222),
-  B(Star), R(0),
-  B(LdaConstant), U8(223),
-  B(Star), R(0),
-  B(LdaConstant), U8(224),
-  B(Star), R(0),
-  B(LdaConstant), U8(225),
-  B(Star), R(0),
-  B(LdaConstant), U8(226),
-  B(Star), R(0),
-  B(LdaConstant), U8(227),
-  B(Star), R(0),
-  B(LdaConstant), U8(228),
-  B(Star), R(0),
-  B(LdaConstant), U8(229),
-  B(Star), R(0),
-  B(LdaConstant), U8(230),
-  B(Star), R(0),
-  B(LdaConstant), U8(231),
-  B(Star), R(0),
-  B(LdaConstant), U8(232),
-  B(Star), R(0),
-  B(LdaConstant), U8(233),
-  B(Star), R(0),
-  B(LdaConstant), U8(234),
-  B(Star), R(0),
-  B(LdaConstant), U8(235),
-  B(Star), R(0),
-  B(LdaConstant), U8(236),
-  B(Star), R(0),
-  B(LdaConstant), U8(237),
-  B(Star), R(0),
-  B(LdaConstant), U8(238),
-  B(Star), R(0),
-  B(LdaConstant), U8(239),
-  B(Star), R(0),
-  B(LdaConstant), U8(240),
-  B(Star), R(0),
-  B(LdaConstant), U8(241),
-  B(Star), R(0),
-  B(LdaConstant), U8(242),
-  B(Star), R(0),
-  B(LdaConstant), U8(243),
-  B(Star), R(0),
-  B(LdaConstant), U8(244),
-  B(Star), R(0),
-  B(LdaConstant), U8(245),
-  B(Star), R(0),
-  B(LdaConstant), U8(246),
-  B(Star), R(0),
-  B(LdaConstant), U8(247),
-  B(Star), R(0),
-  B(LdaConstant), U8(248),
-  B(Star), R(0),
-  B(LdaConstant), U8(249),
-  B(Star), R(0),
-  B(LdaConstant), U8(250),
-  B(Star), R(0),
-  B(LdaConstant), U8(251),
-  B(Star), R(0),
-  B(LdaConstant), U8(252),
-  B(Star), R(0),
-  B(LdaConstant), U8(253),
-  B(Star), R(0),
-  B(LdaConstant), U8(254),
-  B(Star), R(0),
-  B(LdaConstant), U8(255),
-  B(Star), R(0),
-  B(LdaSmi), U8(10),
-  B(Wide), B(StaLookupSlotStrict), U16(256),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   35 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   47 S> */ B(LdaConstant), U8(1),
+                B(Star), R(0),
+  /*   59 S> */ B(LdaConstant), U8(2),
+                B(Star), R(0),
+  /*   71 S> */ B(LdaConstant), U8(3),
+                B(Star), R(0),
+  /*   83 S> */ B(LdaConstant), U8(4),
+                B(Star), R(0),
+  /*   95 S> */ B(LdaConstant), U8(5),
+                B(Star), R(0),
+  /*  107 S> */ B(LdaConstant), U8(6),
+                B(Star), R(0),
+  /*  119 S> */ B(LdaConstant), U8(7),
+                B(Star), R(0),
+  /*  131 S> */ B(LdaConstant), U8(8),
+                B(Star), R(0),
+  /*  143 S> */ B(LdaConstant), U8(9),
+                B(Star), R(0),
+  /*  155 S> */ B(LdaConstant), U8(10),
+                B(Star), R(0),
+  /*  167 S> */ B(LdaConstant), U8(11),
+                B(Star), R(0),
+  /*  179 S> */ B(LdaConstant), U8(12),
+                B(Star), R(0),
+  /*  191 S> */ B(LdaConstant), U8(13),
+                B(Star), R(0),
+  /*  203 S> */ B(LdaConstant), U8(14),
+                B(Star), R(0),
+  /*  215 S> */ B(LdaConstant), U8(15),
+                B(Star), R(0),
+  /*  227 S> */ B(LdaConstant), U8(16),
+                B(Star), R(0),
+  /*  239 S> */ B(LdaConstant), U8(17),
+                B(Star), R(0),
+  /*  251 S> */ B(LdaConstant), U8(18),
+                B(Star), R(0),
+  /*  263 S> */ B(LdaConstant), U8(19),
+                B(Star), R(0),
+  /*  275 S> */ B(LdaConstant), U8(20),
+                B(Star), R(0),
+  /*  287 S> */ B(LdaConstant), U8(21),
+                B(Star), R(0),
+  /*  299 S> */ B(LdaConstant), U8(22),
+                B(Star), R(0),
+  /*  311 S> */ B(LdaConstant), U8(23),
+                B(Star), R(0),
+  /*  323 S> */ B(LdaConstant), U8(24),
+                B(Star), R(0),
+  /*  335 S> */ B(LdaConstant), U8(25),
+                B(Star), R(0),
+  /*  347 S> */ B(LdaConstant), U8(26),
+                B(Star), R(0),
+  /*  359 S> */ B(LdaConstant), U8(27),
+                B(Star), R(0),
+  /*  371 S> */ B(LdaConstant), U8(28),
+                B(Star), R(0),
+  /*  383 S> */ B(LdaConstant), U8(29),
+                B(Star), R(0),
+  /*  395 S> */ B(LdaConstant), U8(30),
+                B(Star), R(0),
+  /*  407 S> */ B(LdaConstant), U8(31),
+                B(Star), R(0),
+  /*  419 S> */ B(LdaConstant), U8(32),
+                B(Star), R(0),
+  /*  431 S> */ B(LdaConstant), U8(33),
+                B(Star), R(0),
+  /*  443 S> */ B(LdaConstant), U8(34),
+                B(Star), R(0),
+  /*  455 S> */ B(LdaConstant), U8(35),
+                B(Star), R(0),
+  /*  467 S> */ B(LdaConstant), U8(36),
+                B(Star), R(0),
+  /*  479 S> */ B(LdaConstant), U8(37),
+                B(Star), R(0),
+  /*  491 S> */ B(LdaConstant), U8(38),
+                B(Star), R(0),
+  /*  503 S> */ B(LdaConstant), U8(39),
+                B(Star), R(0),
+  /*  515 S> */ B(LdaConstant), U8(40),
+                B(Star), R(0),
+  /*  527 S> */ B(LdaConstant), U8(41),
+                B(Star), R(0),
+  /*  539 S> */ B(LdaConstant), U8(42),
+                B(Star), R(0),
+  /*  551 S> */ B(LdaConstant), U8(43),
+                B(Star), R(0),
+  /*  563 S> */ B(LdaConstant), U8(44),
+                B(Star), R(0),
+  /*  575 S> */ B(LdaConstant), U8(45),
+                B(Star), R(0),
+  /*  587 S> */ B(LdaConstant), U8(46),
+                B(Star), R(0),
+  /*  599 S> */ B(LdaConstant), U8(47),
+                B(Star), R(0),
+  /*  611 S> */ B(LdaConstant), U8(48),
+                B(Star), R(0),
+  /*  623 S> */ B(LdaConstant), U8(49),
+                B(Star), R(0),
+  /*  635 S> */ B(LdaConstant), U8(50),
+                B(Star), R(0),
+  /*  647 S> */ B(LdaConstant), U8(51),
+                B(Star), R(0),
+  /*  659 S> */ B(LdaConstant), U8(52),
+                B(Star), R(0),
+  /*  671 S> */ B(LdaConstant), U8(53),
+                B(Star), R(0),
+  /*  683 S> */ B(LdaConstant), U8(54),
+                B(Star), R(0),
+  /*  695 S> */ B(LdaConstant), U8(55),
+                B(Star), R(0),
+  /*  707 S> */ B(LdaConstant), U8(56),
+                B(Star), R(0),
+  /*  719 S> */ B(LdaConstant), U8(57),
+                B(Star), R(0),
+  /*  731 S> */ B(LdaConstant), U8(58),
+                B(Star), R(0),
+  /*  743 S> */ B(LdaConstant), U8(59),
+                B(Star), R(0),
+  /*  755 S> */ B(LdaConstant), U8(60),
+                B(Star), R(0),
+  /*  767 S> */ B(LdaConstant), U8(61),
+                B(Star), R(0),
+  /*  779 S> */ B(LdaConstant), U8(62),
+                B(Star), R(0),
+  /*  791 S> */ B(LdaConstant), U8(63),
+                B(Star), R(0),
+  /*  803 S> */ B(LdaConstant), U8(64),
+                B(Star), R(0),
+  /*  815 S> */ B(LdaConstant), U8(65),
+                B(Star), R(0),
+  /*  827 S> */ B(LdaConstant), U8(66),
+                B(Star), R(0),
+  /*  839 S> */ B(LdaConstant), U8(67),
+                B(Star), R(0),
+  /*  851 S> */ B(LdaConstant), U8(68),
+                B(Star), R(0),
+  /*  863 S> */ B(LdaConstant), U8(69),
+                B(Star), R(0),
+  /*  875 S> */ B(LdaConstant), U8(70),
+                B(Star), R(0),
+  /*  887 S> */ B(LdaConstant), U8(71),
+                B(Star), R(0),
+  /*  899 S> */ B(LdaConstant), U8(72),
+                B(Star), R(0),
+  /*  911 S> */ B(LdaConstant), U8(73),
+                B(Star), R(0),
+  /*  923 S> */ B(LdaConstant), U8(74),
+                B(Star), R(0),
+  /*  935 S> */ B(LdaConstant), U8(75),
+                B(Star), R(0),
+  /*  947 S> */ B(LdaConstant), U8(76),
+                B(Star), R(0),
+  /*  959 S> */ B(LdaConstant), U8(77),
+                B(Star), R(0),
+  /*  971 S> */ B(LdaConstant), U8(78),
+                B(Star), R(0),
+  /*  983 S> */ B(LdaConstant), U8(79),
+                B(Star), R(0),
+  /*  995 S> */ B(LdaConstant), U8(80),
+                B(Star), R(0),
+  /* 1007 S> */ B(LdaConstant), U8(81),
+                B(Star), R(0),
+  /* 1019 S> */ B(LdaConstant), U8(82),
+                B(Star), R(0),
+  /* 1031 S> */ B(LdaConstant), U8(83),
+                B(Star), R(0),
+  /* 1043 S> */ B(LdaConstant), U8(84),
+                B(Star), R(0),
+  /* 1055 S> */ B(LdaConstant), U8(85),
+                B(Star), R(0),
+  /* 1067 S> */ B(LdaConstant), U8(86),
+                B(Star), R(0),
+  /* 1079 S> */ B(LdaConstant), U8(87),
+                B(Star), R(0),
+  /* 1091 S> */ B(LdaConstant), U8(88),
+                B(Star), R(0),
+  /* 1103 S> */ B(LdaConstant), U8(89),
+                B(Star), R(0),
+  /* 1115 S> */ B(LdaConstant), U8(90),
+                B(Star), R(0),
+  /* 1127 S> */ B(LdaConstant), U8(91),
+                B(Star), R(0),
+  /* 1139 S> */ B(LdaConstant), U8(92),
+                B(Star), R(0),
+  /* 1151 S> */ B(LdaConstant), U8(93),
+                B(Star), R(0),
+  /* 1163 S> */ B(LdaConstant), U8(94),
+                B(Star), R(0),
+  /* 1175 S> */ B(LdaConstant), U8(95),
+                B(Star), R(0),
+  /* 1187 S> */ B(LdaConstant), U8(96),
+                B(Star), R(0),
+  /* 1199 S> */ B(LdaConstant), U8(97),
+                B(Star), R(0),
+  /* 1211 S> */ B(LdaConstant), U8(98),
+                B(Star), R(0),
+  /* 1223 S> */ B(LdaConstant), U8(99),
+                B(Star), R(0),
+  /* 1235 S> */ B(LdaConstant), U8(100),
+                B(Star), R(0),
+  /* 1247 S> */ B(LdaConstant), U8(101),
+                B(Star), R(0),
+  /* 1259 S> */ B(LdaConstant), U8(102),
+                B(Star), R(0),
+  /* 1271 S> */ B(LdaConstant), U8(103),
+                B(Star), R(0),
+  /* 1283 S> */ B(LdaConstant), U8(104),
+                B(Star), R(0),
+  /* 1295 S> */ B(LdaConstant), U8(105),
+                B(Star), R(0),
+  /* 1307 S> */ B(LdaConstant), U8(106),
+                B(Star), R(0),
+  /* 1319 S> */ B(LdaConstant), U8(107),
+                B(Star), R(0),
+  /* 1331 S> */ B(LdaConstant), U8(108),
+                B(Star), R(0),
+  /* 1343 S> */ B(LdaConstant), U8(109),
+                B(Star), R(0),
+  /* 1355 S> */ B(LdaConstant), U8(110),
+                B(Star), R(0),
+  /* 1367 S> */ B(LdaConstant), U8(111),
+                B(Star), R(0),
+  /* 1379 S> */ B(LdaConstant), U8(112),
+                B(Star), R(0),
+  /* 1391 S> */ B(LdaConstant), U8(113),
+                B(Star), R(0),
+  /* 1403 S> */ B(LdaConstant), U8(114),
+                B(Star), R(0),
+  /* 1415 S> */ B(LdaConstant), U8(115),
+                B(Star), R(0),
+  /* 1427 S> */ B(LdaConstant), U8(116),
+                B(Star), R(0),
+  /* 1439 S> */ B(LdaConstant), U8(117),
+                B(Star), R(0),
+  /* 1451 S> */ B(LdaConstant), U8(118),
+                B(Star), R(0),
+  /* 1463 S> */ B(LdaConstant), U8(119),
+                B(Star), R(0),
+  /* 1475 S> */ B(LdaConstant), U8(120),
+                B(Star), R(0),
+  /* 1487 S> */ B(LdaConstant), U8(121),
+                B(Star), R(0),
+  /* 1499 S> */ B(LdaConstant), U8(122),
+                B(Star), R(0),
+  /* 1511 S> */ B(LdaConstant), U8(123),
+                B(Star), R(0),
+  /* 1523 S> */ B(LdaConstant), U8(124),
+                B(Star), R(0),
+  /* 1535 S> */ B(LdaConstant), U8(125),
+                B(Star), R(0),
+  /* 1547 S> */ B(LdaConstant), U8(126),
+                B(Star), R(0),
+  /* 1559 S> */ B(LdaConstant), U8(127),
+                B(Star), R(0),
+  /* 1571 S> */ B(LdaConstant), U8(128),
+                B(Star), R(0),
+  /* 1583 S> */ B(LdaConstant), U8(129),
+                B(Star), R(0),
+  /* 1595 S> */ B(LdaConstant), U8(130),
+                B(Star), R(0),
+  /* 1607 S> */ B(LdaConstant), U8(131),
+                B(Star), R(0),
+  /* 1619 S> */ B(LdaConstant), U8(132),
+                B(Star), R(0),
+  /* 1631 S> */ B(LdaConstant), U8(133),
+                B(Star), R(0),
+  /* 1643 S> */ B(LdaConstant), U8(134),
+                B(Star), R(0),
+  /* 1655 S> */ B(LdaConstant), U8(135),
+                B(Star), R(0),
+  /* 1667 S> */ B(LdaConstant), U8(136),
+                B(Star), R(0),
+  /* 1679 S> */ B(LdaConstant), U8(137),
+                B(Star), R(0),
+  /* 1691 S> */ B(LdaConstant), U8(138),
+                B(Star), R(0),
+  /* 1703 S> */ B(LdaConstant), U8(139),
+                B(Star), R(0),
+  /* 1715 S> */ B(LdaConstant), U8(140),
+                B(Star), R(0),
+  /* 1727 S> */ B(LdaConstant), U8(141),
+                B(Star), R(0),
+  /* 1739 S> */ B(LdaConstant), U8(142),
+                B(Star), R(0),
+  /* 1751 S> */ B(LdaConstant), U8(143),
+                B(Star), R(0),
+  /* 1763 S> */ B(LdaConstant), U8(144),
+                B(Star), R(0),
+  /* 1775 S> */ B(LdaConstant), U8(145),
+                B(Star), R(0),
+  /* 1787 S> */ B(LdaConstant), U8(146),
+                B(Star), R(0),
+  /* 1799 S> */ B(LdaConstant), U8(147),
+                B(Star), R(0),
+  /* 1811 S> */ B(LdaConstant), U8(148),
+                B(Star), R(0),
+  /* 1823 S> */ B(LdaConstant), U8(149),
+                B(Star), R(0),
+  /* 1835 S> */ B(LdaConstant), U8(150),
+                B(Star), R(0),
+  /* 1847 S> */ B(LdaConstant), U8(151),
+                B(Star), R(0),
+  /* 1859 S> */ B(LdaConstant), U8(152),
+                B(Star), R(0),
+  /* 1871 S> */ B(LdaConstant), U8(153),
+                B(Star), R(0),
+  /* 1883 S> */ B(LdaConstant), U8(154),
+                B(Star), R(0),
+  /* 1895 S> */ B(LdaConstant), U8(155),
+                B(Star), R(0),
+  /* 1907 S> */ B(LdaConstant), U8(156),
+                B(Star), R(0),
+  /* 1919 S> */ B(LdaConstant), U8(157),
+                B(Star), R(0),
+  /* 1931 S> */ B(LdaConstant), U8(158),
+                B(Star), R(0),
+  /* 1943 S> */ B(LdaConstant), U8(159),
+                B(Star), R(0),
+  /* 1955 S> */ B(LdaConstant), U8(160),
+                B(Star), R(0),
+  /* 1967 S> */ B(LdaConstant), U8(161),
+                B(Star), R(0),
+  /* 1979 S> */ B(LdaConstant), U8(162),
+                B(Star), R(0),
+  /* 1991 S> */ B(LdaConstant), U8(163),
+                B(Star), R(0),
+  /* 2003 S> */ B(LdaConstant), U8(164),
+                B(Star), R(0),
+  /* 2015 S> */ B(LdaConstant), U8(165),
+                B(Star), R(0),
+  /* 2027 S> */ B(LdaConstant), U8(166),
+                B(Star), R(0),
+  /* 2039 S> */ B(LdaConstant), U8(167),
+                B(Star), R(0),
+  /* 2051 S> */ B(LdaConstant), U8(168),
+                B(Star), R(0),
+  /* 2063 S> */ B(LdaConstant), U8(169),
+                B(Star), R(0),
+  /* 2075 S> */ B(LdaConstant), U8(170),
+                B(Star), R(0),
+  /* 2087 S> */ B(LdaConstant), U8(171),
+                B(Star), R(0),
+  /* 2099 S> */ B(LdaConstant), U8(172),
+                B(Star), R(0),
+  /* 2111 S> */ B(LdaConstant), U8(173),
+                B(Star), R(0),
+  /* 2123 S> */ B(LdaConstant), U8(174),
+                B(Star), R(0),
+  /* 2135 S> */ B(LdaConstant), U8(175),
+                B(Star), R(0),
+  /* 2147 S> */ B(LdaConstant), U8(176),
+                B(Star), R(0),
+  /* 2159 S> */ B(LdaConstant), U8(177),
+                B(Star), R(0),
+  /* 2171 S> */ B(LdaConstant), U8(178),
+                B(Star), R(0),
+  /* 2183 S> */ B(LdaConstant), U8(179),
+                B(Star), R(0),
+  /* 2195 S> */ B(LdaConstant), U8(180),
+                B(Star), R(0),
+  /* 2207 S> */ B(LdaConstant), U8(181),
+                B(Star), R(0),
+  /* 2219 S> */ B(LdaConstant), U8(182),
+                B(Star), R(0),
+  /* 2231 S> */ B(LdaConstant), U8(183),
+                B(Star), R(0),
+  /* 2243 S> */ B(LdaConstant), U8(184),
+                B(Star), R(0),
+  /* 2255 S> */ B(LdaConstant), U8(185),
+                B(Star), R(0),
+  /* 2267 S> */ B(LdaConstant), U8(186),
+                B(Star), R(0),
+  /* 2279 S> */ B(LdaConstant), U8(187),
+                B(Star), R(0),
+  /* 2291 S> */ B(LdaConstant), U8(188),
+                B(Star), R(0),
+  /* 2303 S> */ B(LdaConstant), U8(189),
+                B(Star), R(0),
+  /* 2315 S> */ B(LdaConstant), U8(190),
+                B(Star), R(0),
+  /* 2327 S> */ B(LdaConstant), U8(191),
+                B(Star), R(0),
+  /* 2339 S> */ B(LdaConstant), U8(192),
+                B(Star), R(0),
+  /* 2351 S> */ B(LdaConstant), U8(193),
+                B(Star), R(0),
+  /* 2363 S> */ B(LdaConstant), U8(194),
+                B(Star), R(0),
+  /* 2375 S> */ B(LdaConstant), U8(195),
+                B(Star), R(0),
+  /* 2387 S> */ B(LdaConstant), U8(196),
+                B(Star), R(0),
+  /* 2399 S> */ B(LdaConstant), U8(197),
+                B(Star), R(0),
+  /* 2411 S> */ B(LdaConstant), U8(198),
+                B(Star), R(0),
+  /* 2423 S> */ B(LdaConstant), U8(199),
+                B(Star), R(0),
+  /* 2435 S> */ B(LdaConstant), U8(200),
+                B(Star), R(0),
+  /* 2447 S> */ B(LdaConstant), U8(201),
+                B(Star), R(0),
+  /* 2459 S> */ B(LdaConstant), U8(202),
+                B(Star), R(0),
+  /* 2471 S> */ B(LdaConstant), U8(203),
+                B(Star), R(0),
+  /* 2483 S> */ B(LdaConstant), U8(204),
+                B(Star), R(0),
+  /* 2495 S> */ B(LdaConstant), U8(205),
+                B(Star), R(0),
+  /* 2507 S> */ B(LdaConstant), U8(206),
+                B(Star), R(0),
+  /* 2519 S> */ B(LdaConstant), U8(207),
+                B(Star), R(0),
+  /* 2531 S> */ B(LdaConstant), U8(208),
+                B(Star), R(0),
+  /* 2543 S> */ B(LdaConstant), U8(209),
+                B(Star), R(0),
+  /* 2555 S> */ B(LdaConstant), U8(210),
+                B(Star), R(0),
+  /* 2567 S> */ B(LdaConstant), U8(211),
+                B(Star), R(0),
+  /* 2579 S> */ B(LdaConstant), U8(212),
+                B(Star), R(0),
+  /* 2591 S> */ B(LdaConstant), U8(213),
+                B(Star), R(0),
+  /* 2603 S> */ B(LdaConstant), U8(214),
+                B(Star), R(0),
+  /* 2615 S> */ B(LdaConstant), U8(215),
+                B(Star), R(0),
+  /* 2627 S> */ B(LdaConstant), U8(216),
+                B(Star), R(0),
+  /* 2639 S> */ B(LdaConstant), U8(217),
+                B(Star), R(0),
+  /* 2651 S> */ B(LdaConstant), U8(218),
+                B(Star), R(0),
+  /* 2663 S> */ B(LdaConstant), U8(219),
+                B(Star), R(0),
+  /* 2675 S> */ B(LdaConstant), U8(220),
+                B(Star), R(0),
+  /* 2687 S> */ B(LdaConstant), U8(221),
+                B(Star), R(0),
+  /* 2699 S> */ B(LdaConstant), U8(222),
+                B(Star), R(0),
+  /* 2711 S> */ B(LdaConstant), U8(223),
+                B(Star), R(0),
+  /* 2723 S> */ B(LdaConstant), U8(224),
+                B(Star), R(0),
+  /* 2735 S> */ B(LdaConstant), U8(225),
+                B(Star), R(0),
+  /* 2747 S> */ B(LdaConstant), U8(226),
+                B(Star), R(0),
+  /* 2759 S> */ B(LdaConstant), U8(227),
+                B(Star), R(0),
+  /* 2771 S> */ B(LdaConstant), U8(228),
+                B(Star), R(0),
+  /* 2783 S> */ B(LdaConstant), U8(229),
+                B(Star), R(0),
+  /* 2795 S> */ B(LdaConstant), U8(230),
+                B(Star), R(0),
+  /* 2807 S> */ B(LdaConstant), U8(231),
+                B(Star), R(0),
+  /* 2819 S> */ B(LdaConstant), U8(232),
+                B(Star), R(0),
+  /* 2831 S> */ B(LdaConstant), U8(233),
+                B(Star), R(0),
+  /* 2843 S> */ B(LdaConstant), U8(234),
+                B(Star), R(0),
+  /* 2855 S> */ B(LdaConstant), U8(235),
+                B(Star), R(0),
+  /* 2867 S> */ B(LdaConstant), U8(236),
+                B(Star), R(0),
+  /* 2879 S> */ B(LdaConstant), U8(237),
+                B(Star), R(0),
+  /* 2891 S> */ B(LdaConstant), U8(238),
+                B(Star), R(0),
+  /* 2903 S> */ B(LdaConstant), U8(239),
+                B(Star), R(0),
+  /* 2915 S> */ B(LdaConstant), U8(240),
+                B(Star), R(0),
+  /* 2927 S> */ B(LdaConstant), U8(241),
+                B(Star), R(0),
+  /* 2939 S> */ B(LdaConstant), U8(242),
+                B(Star), R(0),
+  /* 2951 S> */ B(LdaConstant), U8(243),
+                B(Star), R(0),
+  /* 2963 S> */ B(LdaConstant), U8(244),
+                B(Star), R(0),
+  /* 2975 S> */ B(LdaConstant), U8(245),
+                B(Star), R(0),
+  /* 2987 S> */ B(LdaConstant), U8(246),
+                B(Star), R(0),
+  /* 2999 S> */ B(LdaConstant), U8(247),
+                B(Star), R(0),
+  /* 3011 S> */ B(LdaConstant), U8(248),
+                B(Star), R(0),
+  /* 3023 S> */ B(LdaConstant), U8(249),
+                B(Star), R(0),
+  /* 3035 S> */ B(LdaConstant), U8(250),
+                B(Star), R(0),
+  /* 3047 S> */ B(LdaConstant), U8(251),
+                B(Star), R(0),
+  /* 3059 S> */ B(LdaConstant), U8(252),
+                B(Star), R(0),
+  /* 3071 S> */ B(LdaConstant), U8(253),
+                B(Star), R(0),
+  /* 3083 S> */ B(LdaConstant), U8(254),
+                B(Star), R(0),
+  /* 3095 S> */ B(LdaConstant), U8(255),
+                B(Star), R(0),
+  /* 3099 S> */ B(LdaSmi), U8(10),
+  /* 3101 E> */ B(Wide), B(StaLookupSlotStrict), U16(256),
+                B(LdaUndefined),
+  /* 3106 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::HEAP_NUMBER_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/NewTarget.golden b/test/cctest/interpreter/bytecode_expectations/NewTarget.golden
index da2d35e..398b857 100644
--- a/test/cctest/interpreter/bytecode_expectations/NewTarget.golden
+++ b/test/cctest/interpreter/bytecode_expectations/NewTarget.golden
@@ -13,17 +13,16 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 19
+bytecode array length: 18
 bytecodes: [
-  B(Ldar), R(new_target),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(0),
-  B(Star), R(1),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(1), U8(1),
-  B(Return),
+                B(Mov), R(new_target), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(Ldar), R(new_target),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(0),
+                B(Star), R(1),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(1), U8(1),
+  /*   53 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
@@ -37,18 +36,17 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 20
+bytecode array length: 19
 bytecodes: [
-  B(Ldar), R(new_target),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(11),
-  B(LdaConstant), U8(0),
-  B(Star), R(1),
-  B(CallRuntime), U16(Runtime::kThrowReferenceError), R(1), U8(1),
-  B(LdaUndefined),
-  B(Return),
+                B(Mov), R(new_target), R(0),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(Ldar), R(new_target),
+                B(JumpIfNotHole), U8(11),
+                B(LdaConstant), U8(0),
+                B(Star), R(1),
+                B(CallRuntime), U16(Runtime::kThrowReferenceError), R(1), U8(1),
+                B(LdaUndefined),
+  /*   46 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/ObjectLiterals.golden b/test/cctest/interpreter/bytecode_expectations/ObjectLiterals.golden
index 063ebbf..2f4bd05 100644
--- a/test/cctest/interpreter/bytecode_expectations/ObjectLiterals.golden
+++ b/test/cctest/interpreter/bytecode_expectations/ObjectLiterals.golden
@@ -15,10 +15,10 @@
 parameter count: 1
 bytecode array length: 8
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(7),
-  B(Star), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(35),
+                B(Star), R(0),
+  /*   46 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -34,10 +34,10 @@
 parameter count: 1
 bytecode array length: 8
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(0),
+  /*   71 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -53,15 +53,15 @@
 parameter count: 1
 bytecode array length: 20
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(StoreICSloppy), R(1), U8(1), U8(1),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(1),
+                B(Ldar), R(0),
+  /*   75 E> */ B(StaNamedPropertySloppy), R(1), U8(1), U8(1),
+                B(Ldar), R(1),
+  /*   80 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -74,22 +74,20 @@
 snippet: "
   var a = 1; return { val: a, val: a + 1 };
 "
-frame size: 3
+frame size: 2
 parameter count: 1
-bytecode array length: 26
+bytecode array length: 22
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(Add), R(2),
-  B(StoreICSloppy), R(1), U8(1), U8(1),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(1),
+  /*   67 E> */ B(Add), R(0),
+                B(StaNamedPropertySloppy), R(1), U8(1), U8(1),
+                B(Ldar), R(1),
+  /*   76 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -106,13 +104,13 @@
 parameter count: 1
 bytecode array length: 17
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(0),
-  B(CreateClosure), U8(1), U8(0),
-  B(StoreICSloppy), R(0), U8(2), U8(1),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(0),
+                B(CreateClosure), U8(1), U8(0),
+                B(StaNamedPropertySloppy), R(0), U8(2), U8(1),
+                B(Ldar), R(0),
+  /*   67 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -130,13 +128,13 @@
 parameter count: 1
 bytecode array length: 17
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(0),
-  B(CreateClosure), U8(1), U8(0),
-  B(StoreICSloppy), R(0), U8(2), U8(1),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(0),
+                B(CreateClosure), U8(1), U8(0),
+                B(StaNamedPropertySloppy), R(0), U8(2), U8(1),
+                B(Ldar), R(0),
+  /*   68 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -154,21 +152,21 @@
 parameter count: 1
 bytecode array length: 33
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(0),
-  B(Mov), R(0), R(1),
-  B(LdaConstant), U8(1),
-  B(Star), R(2),
-  B(CreateClosure), U8(2), U8(0),
-  B(Star), R(3),
-  B(LdaNull),
-  B(Star), R(4),
-  B(LdaZero),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), R(1), U8(5),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(0),
+                B(LdaConstant), U8(1),
+                B(Star), R(2),
+                B(CreateClosure), U8(2), U8(0),
+                B(Star), R(3),
+                B(LdaNull),
+                B(Star), R(4),
+                B(LdaZero),
+                B(Star), R(5),
+                B(Mov), R(0), R(1),
+                B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), R(1), U8(5),
+                B(Ldar), R(0),
+  /*   68 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -186,21 +184,21 @@
 parameter count: 1
 bytecode array length: 35
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(0),
-  B(Mov), R(0), R(1),
-  B(LdaConstant), U8(1),
-  B(Star), R(2),
-  B(CreateClosure), U8(2), U8(0),
-  B(Star), R(3),
-  B(CreateClosure), U8(3), U8(0),
-  B(Star), R(4),
-  B(LdaZero),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), R(1), U8(5),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(0),
+                B(LdaConstant), U8(1),
+                B(Star), R(2),
+                B(CreateClosure), U8(2), U8(0),
+                B(Star), R(3),
+                B(CreateClosure), U8(3), U8(0),
+                B(Star), R(4),
+                B(LdaZero),
+                B(Star), R(5),
+                B(Mov), R(0), R(1),
+                B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), R(1), U8(5),
+                B(Ldar), R(0),
+  /*  102 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -219,21 +217,21 @@
 parameter count: 1
 bytecode array length: 33
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(0),
-  B(Mov), R(0), R(1),
-  B(LdaConstant), U8(1),
-  B(Star), R(2),
-  B(LdaNull),
-  B(Star), R(3),
-  B(CreateClosure), U8(2), U8(0),
-  B(Star), R(4),
-  B(LdaZero),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), R(1), U8(5),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(0),
+                B(LdaConstant), U8(1),
+                B(Star), R(2),
+                B(LdaNull),
+                B(Star), R(3),
+                B(CreateClosure), U8(2), U8(0),
+                B(Star), R(4),
+                B(LdaZero),
+                B(Star), R(5),
+                B(Mov), R(0), R(1),
+                B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), R(1), U8(5),
+                B(Ldar), R(0),
+  /*   74 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -249,23 +247,22 @@
 "
 frame size: 6
 parameter count: 1
-bytecode array length: 33
+bytecode array length: 32
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(1),
-  B(Mov), R(1), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(3),
-  B(Ldar), R(0),
-  B(Star), R(4),
-  B(LdaZero),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kSetProperty), R(2), U8(4),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(1),
+                B(LdaSmi), U8(1),
+                B(Star), R(3),
+                B(LdaZero),
+                B(Star), R(5),
+                B(Mov), R(1), R(2),
+                B(Mov), R(0), R(4),
+  /*   57 E> */ B(CallRuntime), U16(Runtime::kSetProperty), R(2), U8(4),
+                B(Ldar), R(1),
+  /*   62 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -281,15 +278,15 @@
 parameter count: 1
 bytecode array length: 21
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(7),
-  B(Star), R(0),
-  B(Mov), R(0), R(1),
-  B(LdaNull),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(1), U8(2),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(35),
+                B(Star), R(0),
+                B(LdaNull),
+                B(Star), R(2),
+                B(Mov), R(0), R(1),
+                B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(1), U8(2),
+                B(Ldar), R(0),
+  /*   62 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
@@ -305,24 +302,24 @@
 parameter count: 1
 bytecode array length: 37
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(CreateObjectLiteral), U8(1), U8(0), U8(7),
-  B(Star), R(1),
-  B(Mov), R(1), R(2),
-  B(Ldar), R(0),
-  B(ToName),
-  B(Star), R(3),
-  B(LdaSmi), U8(1),
-  B(Star), R(4),
-  B(LdaZero),
-  B(Star), R(5),
-  B(LdaZero),
-  B(Star), R(6),
-  B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), U8(5),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   50 S> */ B(CreateObjectLiteral), U8(1), U8(0), U8(35),
+                B(Star), R(1),
+                B(Ldar), R(0),
+  /*   60 E> */ B(ToName),
+                B(Star), R(3),
+                B(LdaSmi), U8(1),
+                B(Star), R(4),
+                B(LdaZero),
+                B(Star), R(5),
+                B(LdaZero),
+                B(Star), R(6),
+                B(Mov), R(1), R(2),
+                B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), U8(5),
+                B(Ldar), R(1),
+  /*   69 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
@@ -337,28 +334,27 @@
 "
 frame size: 7
 parameter count: 1
-bytecode array length: 43
+bytecode array length: 41
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(CreateObjectLiteral), U8(1), U8(0), U8(5),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(StoreICSloppy), R(1), U8(2), U8(1),
-  B(Mov), R(1), R(2),
-  B(Ldar), R(0),
-  B(ToName),
-  B(Star), R(3),
-  B(LdaSmi), U8(1),
-  B(Star), R(4),
-  B(LdaZero),
-  B(Star), R(5),
-  B(LdaZero),
-  B(Star), R(6),
-  B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), U8(5),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   50 S> */ B(CreateObjectLiteral), U8(1), U8(0), U8(1),
+                B(Star), R(1),
+                B(Ldar), R(0),
+  /*   64 E> */ B(StaNamedPropertySloppy), R(1), U8(2), U8(1),
+  /*   68 E> */ B(ToName),
+                B(Star), R(3),
+                B(LdaSmi), U8(1),
+                B(Star), R(4),
+                B(LdaZero),
+                B(Star), R(5),
+                B(LdaZero),
+                B(Star), R(6),
+                B(Mov), R(1), R(2),
+                B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), U8(5),
+                B(Ldar), R(1),
+  /*   77 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
@@ -374,31 +370,31 @@
 "
 frame size: 7
 parameter count: 1
-bytecode array length: 53
+bytecode array length: 54
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(CreateObjectLiteral), U8(1), U8(1), U8(7),
-  B(Star), R(1),
-  B(Mov), R(1), R(2),
-  B(Ldar), R(0),
-  B(ToName),
-  B(Star), R(3),
-  B(LdaSmi), U8(1),
-  B(Star), R(4),
-  B(LdaZero),
-  B(Star), R(5),
-  B(LdaZero),
-  B(Star), R(6),
-  B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), U8(5),
-  B(Mov), R(1), R(2),
-  B(CreateObjectLiteral), U8(1), U8(0), U8(7),
-  B(Star), R(4),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(2), U8(2),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   50 S> */ B(CreateObjectLiteral), U8(1), U8(1), U8(35),
+                B(Star), R(1),
+                B(Ldar), R(0),
+  /*   60 E> */ B(ToName),
+                B(Star), R(3),
+                B(LdaSmi), U8(1),
+                B(Star), R(4),
+                B(LdaZero),
+                B(Star), R(5),
+                B(LdaZero),
+                B(Star), R(6),
+                B(Mov), R(1), R(2),
+                B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), U8(5),
+                B(CreateObjectLiteral), U8(1), U8(0), U8(35),
+                B(Star), R(4),
+                B(Mov), R(1), R(2),
+                B(Mov), R(4), R(3),
+                B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(2), U8(2),
+                B(Ldar), R(1),
+  /*   84 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
@@ -415,40 +411,40 @@
 parameter count: 1
 bytecode array length: 77
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(CreateObjectLiteral), U8(1), U8(0), U8(7),
-  B(Star), R(1),
-  B(Mov), R(1), R(2),
-  B(Ldar), R(0),
-  B(ToName),
-  B(Star), R(3),
-  B(LdaConstant), U8(2),
-  B(Star), R(4),
-  B(LdaZero),
-  B(Star), R(5),
-  B(LdaZero),
-  B(Star), R(6),
-  B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), U8(5),
-  B(Mov), R(1), R(2),
-  B(LdaConstant), U8(3),
-  B(Star), R(3),
-  B(CreateClosure), U8(4), U8(0),
-  B(Star), R(4),
-  B(LdaZero),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kDefineGetterPropertyUnchecked), R(2), U8(4),
-  B(Mov), R(1), R(2),
-  B(LdaConstant), U8(3),
-  B(Star), R(3),
-  B(CreateClosure), U8(5), U8(0),
-  B(Star), R(4),
-  B(LdaZero),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kDefineSetterPropertyUnchecked), R(2), U8(4),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   50 S> */ B(CreateObjectLiteral), U8(1), U8(0), U8(35),
+                B(Star), R(1),
+                B(Ldar), R(0),
+  /*   60 E> */ B(ToName),
+                B(Star), R(3),
+                B(LdaConstant), U8(2),
+                B(Star), R(4),
+                B(LdaZero),
+                B(Star), R(5),
+                B(LdaZero),
+                B(Star), R(6),
+                B(Mov), R(1), R(2),
+                B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), U8(5),
+                B(LdaConstant), U8(3),
+                B(Star), R(3),
+                B(CreateClosure), U8(4), U8(0),
+                B(Star), R(4),
+                B(LdaZero),
+                B(Star), R(5),
+                B(Mov), R(1), R(2),
+                B(CallRuntime), U16(Runtime::kDefineGetterPropertyUnchecked), R(2), U8(4),
+                B(LdaConstant), U8(3),
+                B(Star), R(3),
+                B(CreateClosure), U8(5), U8(0),
+                B(Star), R(4),
+                B(LdaZero),
+                B(Star), R(5),
+                B(Mov), R(1), R(2),
+                B(CallRuntime), U16(Runtime::kDefineSetterPropertyUnchecked), R(2), U8(4),
+                B(Ldar), R(1),
+  /*   99 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/ObjectLiteralsWide.golden b/test/cctest/interpreter/bytecode_expectations/ObjectLiteralsWide.golden
index 83c6fe9..144a3c5 100644
--- a/test/cctest/interpreter/bytecode_expectations/ObjectLiteralsWide.golden
+++ b/test/cctest/interpreter/bytecode_expectations/ObjectLiteralsWide.golden
@@ -272,522 +272,522 @@
 parameter count: 1
 bytecode array length: 1035
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(LdaConstant), U8(1),
-  B(Star), R(0),
-  B(LdaConstant), U8(2),
-  B(Star), R(0),
-  B(LdaConstant), U8(3),
-  B(Star), R(0),
-  B(LdaConstant), U8(4),
-  B(Star), R(0),
-  B(LdaConstant), U8(5),
-  B(Star), R(0),
-  B(LdaConstant), U8(6),
-  B(Star), R(0),
-  B(LdaConstant), U8(7),
-  B(Star), R(0),
-  B(LdaConstant), U8(8),
-  B(Star), R(0),
-  B(LdaConstant), U8(9),
-  B(Star), R(0),
-  B(LdaConstant), U8(10),
-  B(Star), R(0),
-  B(LdaConstant), U8(11),
-  B(Star), R(0),
-  B(LdaConstant), U8(12),
-  B(Star), R(0),
-  B(LdaConstant), U8(13),
-  B(Star), R(0),
-  B(LdaConstant), U8(14),
-  B(Star), R(0),
-  B(LdaConstant), U8(15),
-  B(Star), R(0),
-  B(LdaConstant), U8(16),
-  B(Star), R(0),
-  B(LdaConstant), U8(17),
-  B(Star), R(0),
-  B(LdaConstant), U8(18),
-  B(Star), R(0),
-  B(LdaConstant), U8(19),
-  B(Star), R(0),
-  B(LdaConstant), U8(20),
-  B(Star), R(0),
-  B(LdaConstant), U8(21),
-  B(Star), R(0),
-  B(LdaConstant), U8(22),
-  B(Star), R(0),
-  B(LdaConstant), U8(23),
-  B(Star), R(0),
-  B(LdaConstant), U8(24),
-  B(Star), R(0),
-  B(LdaConstant), U8(25),
-  B(Star), R(0),
-  B(LdaConstant), U8(26),
-  B(Star), R(0),
-  B(LdaConstant), U8(27),
-  B(Star), R(0),
-  B(LdaConstant), U8(28),
-  B(Star), R(0),
-  B(LdaConstant), U8(29),
-  B(Star), R(0),
-  B(LdaConstant), U8(30),
-  B(Star), R(0),
-  B(LdaConstant), U8(31),
-  B(Star), R(0),
-  B(LdaConstant), U8(32),
-  B(Star), R(0),
-  B(LdaConstant), U8(33),
-  B(Star), R(0),
-  B(LdaConstant), U8(34),
-  B(Star), R(0),
-  B(LdaConstant), U8(35),
-  B(Star), R(0),
-  B(LdaConstant), U8(36),
-  B(Star), R(0),
-  B(LdaConstant), U8(37),
-  B(Star), R(0),
-  B(LdaConstant), U8(38),
-  B(Star), R(0),
-  B(LdaConstant), U8(39),
-  B(Star), R(0),
-  B(LdaConstant), U8(40),
-  B(Star), R(0),
-  B(LdaConstant), U8(41),
-  B(Star), R(0),
-  B(LdaConstant), U8(42),
-  B(Star), R(0),
-  B(LdaConstant), U8(43),
-  B(Star), R(0),
-  B(LdaConstant), U8(44),
-  B(Star), R(0),
-  B(LdaConstant), U8(45),
-  B(Star), R(0),
-  B(LdaConstant), U8(46),
-  B(Star), R(0),
-  B(LdaConstant), U8(47),
-  B(Star), R(0),
-  B(LdaConstant), U8(48),
-  B(Star), R(0),
-  B(LdaConstant), U8(49),
-  B(Star), R(0),
-  B(LdaConstant), U8(50),
-  B(Star), R(0),
-  B(LdaConstant), U8(51),
-  B(Star), R(0),
-  B(LdaConstant), U8(52),
-  B(Star), R(0),
-  B(LdaConstant), U8(53),
-  B(Star), R(0),
-  B(LdaConstant), U8(54),
-  B(Star), R(0),
-  B(LdaConstant), U8(55),
-  B(Star), R(0),
-  B(LdaConstant), U8(56),
-  B(Star), R(0),
-  B(LdaConstant), U8(57),
-  B(Star), R(0),
-  B(LdaConstant), U8(58),
-  B(Star), R(0),
-  B(LdaConstant), U8(59),
-  B(Star), R(0),
-  B(LdaConstant), U8(60),
-  B(Star), R(0),
-  B(LdaConstant), U8(61),
-  B(Star), R(0),
-  B(LdaConstant), U8(62),
-  B(Star), R(0),
-  B(LdaConstant), U8(63),
-  B(Star), R(0),
-  B(LdaConstant), U8(64),
-  B(Star), R(0),
-  B(LdaConstant), U8(65),
-  B(Star), R(0),
-  B(LdaConstant), U8(66),
-  B(Star), R(0),
-  B(LdaConstant), U8(67),
-  B(Star), R(0),
-  B(LdaConstant), U8(68),
-  B(Star), R(0),
-  B(LdaConstant), U8(69),
-  B(Star), R(0),
-  B(LdaConstant), U8(70),
-  B(Star), R(0),
-  B(LdaConstant), U8(71),
-  B(Star), R(0),
-  B(LdaConstant), U8(72),
-  B(Star), R(0),
-  B(LdaConstant), U8(73),
-  B(Star), R(0),
-  B(LdaConstant), U8(74),
-  B(Star), R(0),
-  B(LdaConstant), U8(75),
-  B(Star), R(0),
-  B(LdaConstant), U8(76),
-  B(Star), R(0),
-  B(LdaConstant), U8(77),
-  B(Star), R(0),
-  B(LdaConstant), U8(78),
-  B(Star), R(0),
-  B(LdaConstant), U8(79),
-  B(Star), R(0),
-  B(LdaConstant), U8(80),
-  B(Star), R(0),
-  B(LdaConstant), U8(81),
-  B(Star), R(0),
-  B(LdaConstant), U8(82),
-  B(Star), R(0),
-  B(LdaConstant), U8(83),
-  B(Star), R(0),
-  B(LdaConstant), U8(84),
-  B(Star), R(0),
-  B(LdaConstant), U8(85),
-  B(Star), R(0),
-  B(LdaConstant), U8(86),
-  B(Star), R(0),
-  B(LdaConstant), U8(87),
-  B(Star), R(0),
-  B(LdaConstant), U8(88),
-  B(Star), R(0),
-  B(LdaConstant), U8(89),
-  B(Star), R(0),
-  B(LdaConstant), U8(90),
-  B(Star), R(0),
-  B(LdaConstant), U8(91),
-  B(Star), R(0),
-  B(LdaConstant), U8(92),
-  B(Star), R(0),
-  B(LdaConstant), U8(93),
-  B(Star), R(0),
-  B(LdaConstant), U8(94),
-  B(Star), R(0),
-  B(LdaConstant), U8(95),
-  B(Star), R(0),
-  B(LdaConstant), U8(96),
-  B(Star), R(0),
-  B(LdaConstant), U8(97),
-  B(Star), R(0),
-  B(LdaConstant), U8(98),
-  B(Star), R(0),
-  B(LdaConstant), U8(99),
-  B(Star), R(0),
-  B(LdaConstant), U8(100),
-  B(Star), R(0),
-  B(LdaConstant), U8(101),
-  B(Star), R(0),
-  B(LdaConstant), U8(102),
-  B(Star), R(0),
-  B(LdaConstant), U8(103),
-  B(Star), R(0),
-  B(LdaConstant), U8(104),
-  B(Star), R(0),
-  B(LdaConstant), U8(105),
-  B(Star), R(0),
-  B(LdaConstant), U8(106),
-  B(Star), R(0),
-  B(LdaConstant), U8(107),
-  B(Star), R(0),
-  B(LdaConstant), U8(108),
-  B(Star), R(0),
-  B(LdaConstant), U8(109),
-  B(Star), R(0),
-  B(LdaConstant), U8(110),
-  B(Star), R(0),
-  B(LdaConstant), U8(111),
-  B(Star), R(0),
-  B(LdaConstant), U8(112),
-  B(Star), R(0),
-  B(LdaConstant), U8(113),
-  B(Star), R(0),
-  B(LdaConstant), U8(114),
-  B(Star), R(0),
-  B(LdaConstant), U8(115),
-  B(Star), R(0),
-  B(LdaConstant), U8(116),
-  B(Star), R(0),
-  B(LdaConstant), U8(117),
-  B(Star), R(0),
-  B(LdaConstant), U8(118),
-  B(Star), R(0),
-  B(LdaConstant), U8(119),
-  B(Star), R(0),
-  B(LdaConstant), U8(120),
-  B(Star), R(0),
-  B(LdaConstant), U8(121),
-  B(Star), R(0),
-  B(LdaConstant), U8(122),
-  B(Star), R(0),
-  B(LdaConstant), U8(123),
-  B(Star), R(0),
-  B(LdaConstant), U8(124),
-  B(Star), R(0),
-  B(LdaConstant), U8(125),
-  B(Star), R(0),
-  B(LdaConstant), U8(126),
-  B(Star), R(0),
-  B(LdaConstant), U8(127),
-  B(Star), R(0),
-  B(LdaConstant), U8(128),
-  B(Star), R(0),
-  B(LdaConstant), U8(129),
-  B(Star), R(0),
-  B(LdaConstant), U8(130),
-  B(Star), R(0),
-  B(LdaConstant), U8(131),
-  B(Star), R(0),
-  B(LdaConstant), U8(132),
-  B(Star), R(0),
-  B(LdaConstant), U8(133),
-  B(Star), R(0),
-  B(LdaConstant), U8(134),
-  B(Star), R(0),
-  B(LdaConstant), U8(135),
-  B(Star), R(0),
-  B(LdaConstant), U8(136),
-  B(Star), R(0),
-  B(LdaConstant), U8(137),
-  B(Star), R(0),
-  B(LdaConstant), U8(138),
-  B(Star), R(0),
-  B(LdaConstant), U8(139),
-  B(Star), R(0),
-  B(LdaConstant), U8(140),
-  B(Star), R(0),
-  B(LdaConstant), U8(141),
-  B(Star), R(0),
-  B(LdaConstant), U8(142),
-  B(Star), R(0),
-  B(LdaConstant), U8(143),
-  B(Star), R(0),
-  B(LdaConstant), U8(144),
-  B(Star), R(0),
-  B(LdaConstant), U8(145),
-  B(Star), R(0),
-  B(LdaConstant), U8(146),
-  B(Star), R(0),
-  B(LdaConstant), U8(147),
-  B(Star), R(0),
-  B(LdaConstant), U8(148),
-  B(Star), R(0),
-  B(LdaConstant), U8(149),
-  B(Star), R(0),
-  B(LdaConstant), U8(150),
-  B(Star), R(0),
-  B(LdaConstant), U8(151),
-  B(Star), R(0),
-  B(LdaConstant), U8(152),
-  B(Star), R(0),
-  B(LdaConstant), U8(153),
-  B(Star), R(0),
-  B(LdaConstant), U8(154),
-  B(Star), R(0),
-  B(LdaConstant), U8(155),
-  B(Star), R(0),
-  B(LdaConstant), U8(156),
-  B(Star), R(0),
-  B(LdaConstant), U8(157),
-  B(Star), R(0),
-  B(LdaConstant), U8(158),
-  B(Star), R(0),
-  B(LdaConstant), U8(159),
-  B(Star), R(0),
-  B(LdaConstant), U8(160),
-  B(Star), R(0),
-  B(LdaConstant), U8(161),
-  B(Star), R(0),
-  B(LdaConstant), U8(162),
-  B(Star), R(0),
-  B(LdaConstant), U8(163),
-  B(Star), R(0),
-  B(LdaConstant), U8(164),
-  B(Star), R(0),
-  B(LdaConstant), U8(165),
-  B(Star), R(0),
-  B(LdaConstant), U8(166),
-  B(Star), R(0),
-  B(LdaConstant), U8(167),
-  B(Star), R(0),
-  B(LdaConstant), U8(168),
-  B(Star), R(0),
-  B(LdaConstant), U8(169),
-  B(Star), R(0),
-  B(LdaConstant), U8(170),
-  B(Star), R(0),
-  B(LdaConstant), U8(171),
-  B(Star), R(0),
-  B(LdaConstant), U8(172),
-  B(Star), R(0),
-  B(LdaConstant), U8(173),
-  B(Star), R(0),
-  B(LdaConstant), U8(174),
-  B(Star), R(0),
-  B(LdaConstant), U8(175),
-  B(Star), R(0),
-  B(LdaConstant), U8(176),
-  B(Star), R(0),
-  B(LdaConstant), U8(177),
-  B(Star), R(0),
-  B(LdaConstant), U8(178),
-  B(Star), R(0),
-  B(LdaConstant), U8(179),
-  B(Star), R(0),
-  B(LdaConstant), U8(180),
-  B(Star), R(0),
-  B(LdaConstant), U8(181),
-  B(Star), R(0),
-  B(LdaConstant), U8(182),
-  B(Star), R(0),
-  B(LdaConstant), U8(183),
-  B(Star), R(0),
-  B(LdaConstant), U8(184),
-  B(Star), R(0),
-  B(LdaConstant), U8(185),
-  B(Star), R(0),
-  B(LdaConstant), U8(186),
-  B(Star), R(0),
-  B(LdaConstant), U8(187),
-  B(Star), R(0),
-  B(LdaConstant), U8(188),
-  B(Star), R(0),
-  B(LdaConstant), U8(189),
-  B(Star), R(0),
-  B(LdaConstant), U8(190),
-  B(Star), R(0),
-  B(LdaConstant), U8(191),
-  B(Star), R(0),
-  B(LdaConstant), U8(192),
-  B(Star), R(0),
-  B(LdaConstant), U8(193),
-  B(Star), R(0),
-  B(LdaConstant), U8(194),
-  B(Star), R(0),
-  B(LdaConstant), U8(195),
-  B(Star), R(0),
-  B(LdaConstant), U8(196),
-  B(Star), R(0),
-  B(LdaConstant), U8(197),
-  B(Star), R(0),
-  B(LdaConstant), U8(198),
-  B(Star), R(0),
-  B(LdaConstant), U8(199),
-  B(Star), R(0),
-  B(LdaConstant), U8(200),
-  B(Star), R(0),
-  B(LdaConstant), U8(201),
-  B(Star), R(0),
-  B(LdaConstant), U8(202),
-  B(Star), R(0),
-  B(LdaConstant), U8(203),
-  B(Star), R(0),
-  B(LdaConstant), U8(204),
-  B(Star), R(0),
-  B(LdaConstant), U8(205),
-  B(Star), R(0),
-  B(LdaConstant), U8(206),
-  B(Star), R(0),
-  B(LdaConstant), U8(207),
-  B(Star), R(0),
-  B(LdaConstant), U8(208),
-  B(Star), R(0),
-  B(LdaConstant), U8(209),
-  B(Star), R(0),
-  B(LdaConstant), U8(210),
-  B(Star), R(0),
-  B(LdaConstant), U8(211),
-  B(Star), R(0),
-  B(LdaConstant), U8(212),
-  B(Star), R(0),
-  B(LdaConstant), U8(213),
-  B(Star), R(0),
-  B(LdaConstant), U8(214),
-  B(Star), R(0),
-  B(LdaConstant), U8(215),
-  B(Star), R(0),
-  B(LdaConstant), U8(216),
-  B(Star), R(0),
-  B(LdaConstant), U8(217),
-  B(Star), R(0),
-  B(LdaConstant), U8(218),
-  B(Star), R(0),
-  B(LdaConstant), U8(219),
-  B(Star), R(0),
-  B(LdaConstant), U8(220),
-  B(Star), R(0),
-  B(LdaConstant), U8(221),
-  B(Star), R(0),
-  B(LdaConstant), U8(222),
-  B(Star), R(0),
-  B(LdaConstant), U8(223),
-  B(Star), R(0),
-  B(LdaConstant), U8(224),
-  B(Star), R(0),
-  B(LdaConstant), U8(225),
-  B(Star), R(0),
-  B(LdaConstant), U8(226),
-  B(Star), R(0),
-  B(LdaConstant), U8(227),
-  B(Star), R(0),
-  B(LdaConstant), U8(228),
-  B(Star), R(0),
-  B(LdaConstant), U8(229),
-  B(Star), R(0),
-  B(LdaConstant), U8(230),
-  B(Star), R(0),
-  B(LdaConstant), U8(231),
-  B(Star), R(0),
-  B(LdaConstant), U8(232),
-  B(Star), R(0),
-  B(LdaConstant), U8(233),
-  B(Star), R(0),
-  B(LdaConstant), U8(234),
-  B(Star), R(0),
-  B(LdaConstant), U8(235),
-  B(Star), R(0),
-  B(LdaConstant), U8(236),
-  B(Star), R(0),
-  B(LdaConstant), U8(237),
-  B(Star), R(0),
-  B(LdaConstant), U8(238),
-  B(Star), R(0),
-  B(LdaConstant), U8(239),
-  B(Star), R(0),
-  B(LdaConstant), U8(240),
-  B(Star), R(0),
-  B(LdaConstant), U8(241),
-  B(Star), R(0),
-  B(LdaConstant), U8(242),
-  B(Star), R(0),
-  B(LdaConstant), U8(243),
-  B(Star), R(0),
-  B(LdaConstant), U8(244),
-  B(Star), R(0),
-  B(LdaConstant), U8(245),
-  B(Star), R(0),
-  B(LdaConstant), U8(246),
-  B(Star), R(0),
-  B(LdaConstant), U8(247),
-  B(Star), R(0),
-  B(LdaConstant), U8(248),
-  B(Star), R(0),
-  B(LdaConstant), U8(249),
-  B(Star), R(0),
-  B(LdaConstant), U8(250),
-  B(Star), R(0),
-  B(LdaConstant), U8(251),
-  B(Star), R(0),
-  B(LdaConstant), U8(252),
-  B(Star), R(0),
-  B(LdaConstant), U8(253),
-  B(Star), R(0),
-  B(LdaConstant), U8(254),
-  B(Star), R(0),
-  B(LdaConstant), U8(255),
-  B(Star), R(0),
-  B(Wide), B(CreateObjectLiteral), U16(256), U16(0), U8(5),
-  B(Star), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   41 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   51 S> */ B(LdaConstant), U8(1),
+                B(Star), R(0),
+  /*   61 S> */ B(LdaConstant), U8(2),
+                B(Star), R(0),
+  /*   71 S> */ B(LdaConstant), U8(3),
+                B(Star), R(0),
+  /*   81 S> */ B(LdaConstant), U8(4),
+                B(Star), R(0),
+  /*   91 S> */ B(LdaConstant), U8(5),
+                B(Star), R(0),
+  /*  101 S> */ B(LdaConstant), U8(6),
+                B(Star), R(0),
+  /*  111 S> */ B(LdaConstant), U8(7),
+                B(Star), R(0),
+  /*  121 S> */ B(LdaConstant), U8(8),
+                B(Star), R(0),
+  /*  131 S> */ B(LdaConstant), U8(9),
+                B(Star), R(0),
+  /*  141 S> */ B(LdaConstant), U8(10),
+                B(Star), R(0),
+  /*  151 S> */ B(LdaConstant), U8(11),
+                B(Star), R(0),
+  /*  161 S> */ B(LdaConstant), U8(12),
+                B(Star), R(0),
+  /*  171 S> */ B(LdaConstant), U8(13),
+                B(Star), R(0),
+  /*  181 S> */ B(LdaConstant), U8(14),
+                B(Star), R(0),
+  /*  191 S> */ B(LdaConstant), U8(15),
+                B(Star), R(0),
+  /*  201 S> */ B(LdaConstant), U8(16),
+                B(Star), R(0),
+  /*  211 S> */ B(LdaConstant), U8(17),
+                B(Star), R(0),
+  /*  221 S> */ B(LdaConstant), U8(18),
+                B(Star), R(0),
+  /*  231 S> */ B(LdaConstant), U8(19),
+                B(Star), R(0),
+  /*  241 S> */ B(LdaConstant), U8(20),
+                B(Star), R(0),
+  /*  251 S> */ B(LdaConstant), U8(21),
+                B(Star), R(0),
+  /*  261 S> */ B(LdaConstant), U8(22),
+                B(Star), R(0),
+  /*  271 S> */ B(LdaConstant), U8(23),
+                B(Star), R(0),
+  /*  281 S> */ B(LdaConstant), U8(24),
+                B(Star), R(0),
+  /*  291 S> */ B(LdaConstant), U8(25),
+                B(Star), R(0),
+  /*  301 S> */ B(LdaConstant), U8(26),
+                B(Star), R(0),
+  /*  311 S> */ B(LdaConstant), U8(27),
+                B(Star), R(0),
+  /*  321 S> */ B(LdaConstant), U8(28),
+                B(Star), R(0),
+  /*  331 S> */ B(LdaConstant), U8(29),
+                B(Star), R(0),
+  /*  341 S> */ B(LdaConstant), U8(30),
+                B(Star), R(0),
+  /*  351 S> */ B(LdaConstant), U8(31),
+                B(Star), R(0),
+  /*  361 S> */ B(LdaConstant), U8(32),
+                B(Star), R(0),
+  /*  371 S> */ B(LdaConstant), U8(33),
+                B(Star), R(0),
+  /*  381 S> */ B(LdaConstant), U8(34),
+                B(Star), R(0),
+  /*  391 S> */ B(LdaConstant), U8(35),
+                B(Star), R(0),
+  /*  401 S> */ B(LdaConstant), U8(36),
+                B(Star), R(0),
+  /*  411 S> */ B(LdaConstant), U8(37),
+                B(Star), R(0),
+  /*  421 S> */ B(LdaConstant), U8(38),
+                B(Star), R(0),
+  /*  431 S> */ B(LdaConstant), U8(39),
+                B(Star), R(0),
+  /*  441 S> */ B(LdaConstant), U8(40),
+                B(Star), R(0),
+  /*  451 S> */ B(LdaConstant), U8(41),
+                B(Star), R(0),
+  /*  461 S> */ B(LdaConstant), U8(42),
+                B(Star), R(0),
+  /*  471 S> */ B(LdaConstant), U8(43),
+                B(Star), R(0),
+  /*  481 S> */ B(LdaConstant), U8(44),
+                B(Star), R(0),
+  /*  491 S> */ B(LdaConstant), U8(45),
+                B(Star), R(0),
+  /*  501 S> */ B(LdaConstant), U8(46),
+                B(Star), R(0),
+  /*  511 S> */ B(LdaConstant), U8(47),
+                B(Star), R(0),
+  /*  521 S> */ B(LdaConstant), U8(48),
+                B(Star), R(0),
+  /*  531 S> */ B(LdaConstant), U8(49),
+                B(Star), R(0),
+  /*  541 S> */ B(LdaConstant), U8(50),
+                B(Star), R(0),
+  /*  551 S> */ B(LdaConstant), U8(51),
+                B(Star), R(0),
+  /*  561 S> */ B(LdaConstant), U8(52),
+                B(Star), R(0),
+  /*  571 S> */ B(LdaConstant), U8(53),
+                B(Star), R(0),
+  /*  581 S> */ B(LdaConstant), U8(54),
+                B(Star), R(0),
+  /*  591 S> */ B(LdaConstant), U8(55),
+                B(Star), R(0),
+  /*  601 S> */ B(LdaConstant), U8(56),
+                B(Star), R(0),
+  /*  611 S> */ B(LdaConstant), U8(57),
+                B(Star), R(0),
+  /*  621 S> */ B(LdaConstant), U8(58),
+                B(Star), R(0),
+  /*  631 S> */ B(LdaConstant), U8(59),
+                B(Star), R(0),
+  /*  641 S> */ B(LdaConstant), U8(60),
+                B(Star), R(0),
+  /*  651 S> */ B(LdaConstant), U8(61),
+                B(Star), R(0),
+  /*  661 S> */ B(LdaConstant), U8(62),
+                B(Star), R(0),
+  /*  671 S> */ B(LdaConstant), U8(63),
+                B(Star), R(0),
+  /*  681 S> */ B(LdaConstant), U8(64),
+                B(Star), R(0),
+  /*  691 S> */ B(LdaConstant), U8(65),
+                B(Star), R(0),
+  /*  701 S> */ B(LdaConstant), U8(66),
+                B(Star), R(0),
+  /*  711 S> */ B(LdaConstant), U8(67),
+                B(Star), R(0),
+  /*  721 S> */ B(LdaConstant), U8(68),
+                B(Star), R(0),
+  /*  731 S> */ B(LdaConstant), U8(69),
+                B(Star), R(0),
+  /*  741 S> */ B(LdaConstant), U8(70),
+                B(Star), R(0),
+  /*  751 S> */ B(LdaConstant), U8(71),
+                B(Star), R(0),
+  /*  761 S> */ B(LdaConstant), U8(72),
+                B(Star), R(0),
+  /*  771 S> */ B(LdaConstant), U8(73),
+                B(Star), R(0),
+  /*  781 S> */ B(LdaConstant), U8(74),
+                B(Star), R(0),
+  /*  791 S> */ B(LdaConstant), U8(75),
+                B(Star), R(0),
+  /*  801 S> */ B(LdaConstant), U8(76),
+                B(Star), R(0),
+  /*  811 S> */ B(LdaConstant), U8(77),
+                B(Star), R(0),
+  /*  821 S> */ B(LdaConstant), U8(78),
+                B(Star), R(0),
+  /*  831 S> */ B(LdaConstant), U8(79),
+                B(Star), R(0),
+  /*  841 S> */ B(LdaConstant), U8(80),
+                B(Star), R(0),
+  /*  851 S> */ B(LdaConstant), U8(81),
+                B(Star), R(0),
+  /*  861 S> */ B(LdaConstant), U8(82),
+                B(Star), R(0),
+  /*  871 S> */ B(LdaConstant), U8(83),
+                B(Star), R(0),
+  /*  881 S> */ B(LdaConstant), U8(84),
+                B(Star), R(0),
+  /*  891 S> */ B(LdaConstant), U8(85),
+                B(Star), R(0),
+  /*  901 S> */ B(LdaConstant), U8(86),
+                B(Star), R(0),
+  /*  911 S> */ B(LdaConstant), U8(87),
+                B(Star), R(0),
+  /*  921 S> */ B(LdaConstant), U8(88),
+                B(Star), R(0),
+  /*  931 S> */ B(LdaConstant), U8(89),
+                B(Star), R(0),
+  /*  941 S> */ B(LdaConstant), U8(90),
+                B(Star), R(0),
+  /*  951 S> */ B(LdaConstant), U8(91),
+                B(Star), R(0),
+  /*  961 S> */ B(LdaConstant), U8(92),
+                B(Star), R(0),
+  /*  971 S> */ B(LdaConstant), U8(93),
+                B(Star), R(0),
+  /*  981 S> */ B(LdaConstant), U8(94),
+                B(Star), R(0),
+  /*  991 S> */ B(LdaConstant), U8(95),
+                B(Star), R(0),
+  /* 1001 S> */ B(LdaConstant), U8(96),
+                B(Star), R(0),
+  /* 1011 S> */ B(LdaConstant), U8(97),
+                B(Star), R(0),
+  /* 1021 S> */ B(LdaConstant), U8(98),
+                B(Star), R(0),
+  /* 1031 S> */ B(LdaConstant), U8(99),
+                B(Star), R(0),
+  /* 1041 S> */ B(LdaConstant), U8(100),
+                B(Star), R(0),
+  /* 1051 S> */ B(LdaConstant), U8(101),
+                B(Star), R(0),
+  /* 1061 S> */ B(LdaConstant), U8(102),
+                B(Star), R(0),
+  /* 1071 S> */ B(LdaConstant), U8(103),
+                B(Star), R(0),
+  /* 1081 S> */ B(LdaConstant), U8(104),
+                B(Star), R(0),
+  /* 1091 S> */ B(LdaConstant), U8(105),
+                B(Star), R(0),
+  /* 1101 S> */ B(LdaConstant), U8(106),
+                B(Star), R(0),
+  /* 1111 S> */ B(LdaConstant), U8(107),
+                B(Star), R(0),
+  /* 1121 S> */ B(LdaConstant), U8(108),
+                B(Star), R(0),
+  /* 1131 S> */ B(LdaConstant), U8(109),
+                B(Star), R(0),
+  /* 1141 S> */ B(LdaConstant), U8(110),
+                B(Star), R(0),
+  /* 1151 S> */ B(LdaConstant), U8(111),
+                B(Star), R(0),
+  /* 1161 S> */ B(LdaConstant), U8(112),
+                B(Star), R(0),
+  /* 1171 S> */ B(LdaConstant), U8(113),
+                B(Star), R(0),
+  /* 1181 S> */ B(LdaConstant), U8(114),
+                B(Star), R(0),
+  /* 1191 S> */ B(LdaConstant), U8(115),
+                B(Star), R(0),
+  /* 1201 S> */ B(LdaConstant), U8(116),
+                B(Star), R(0),
+  /* 1211 S> */ B(LdaConstant), U8(117),
+                B(Star), R(0),
+  /* 1221 S> */ B(LdaConstant), U8(118),
+                B(Star), R(0),
+  /* 1231 S> */ B(LdaConstant), U8(119),
+                B(Star), R(0),
+  /* 1241 S> */ B(LdaConstant), U8(120),
+                B(Star), R(0),
+  /* 1251 S> */ B(LdaConstant), U8(121),
+                B(Star), R(0),
+  /* 1261 S> */ B(LdaConstant), U8(122),
+                B(Star), R(0),
+  /* 1271 S> */ B(LdaConstant), U8(123),
+                B(Star), R(0),
+  /* 1281 S> */ B(LdaConstant), U8(124),
+                B(Star), R(0),
+  /* 1291 S> */ B(LdaConstant), U8(125),
+                B(Star), R(0),
+  /* 1301 S> */ B(LdaConstant), U8(126),
+                B(Star), R(0),
+  /* 1311 S> */ B(LdaConstant), U8(127),
+                B(Star), R(0),
+  /* 1321 S> */ B(LdaConstant), U8(128),
+                B(Star), R(0),
+  /* 1331 S> */ B(LdaConstant), U8(129),
+                B(Star), R(0),
+  /* 1341 S> */ B(LdaConstant), U8(130),
+                B(Star), R(0),
+  /* 1351 S> */ B(LdaConstant), U8(131),
+                B(Star), R(0),
+  /* 1361 S> */ B(LdaConstant), U8(132),
+                B(Star), R(0),
+  /* 1371 S> */ B(LdaConstant), U8(133),
+                B(Star), R(0),
+  /* 1381 S> */ B(LdaConstant), U8(134),
+                B(Star), R(0),
+  /* 1391 S> */ B(LdaConstant), U8(135),
+                B(Star), R(0),
+  /* 1401 S> */ B(LdaConstant), U8(136),
+                B(Star), R(0),
+  /* 1411 S> */ B(LdaConstant), U8(137),
+                B(Star), R(0),
+  /* 1421 S> */ B(LdaConstant), U8(138),
+                B(Star), R(0),
+  /* 1431 S> */ B(LdaConstant), U8(139),
+                B(Star), R(0),
+  /* 1441 S> */ B(LdaConstant), U8(140),
+                B(Star), R(0),
+  /* 1451 S> */ B(LdaConstant), U8(141),
+                B(Star), R(0),
+  /* 1461 S> */ B(LdaConstant), U8(142),
+                B(Star), R(0),
+  /* 1471 S> */ B(LdaConstant), U8(143),
+                B(Star), R(0),
+  /* 1481 S> */ B(LdaConstant), U8(144),
+                B(Star), R(0),
+  /* 1491 S> */ B(LdaConstant), U8(145),
+                B(Star), R(0),
+  /* 1501 S> */ B(LdaConstant), U8(146),
+                B(Star), R(0),
+  /* 1511 S> */ B(LdaConstant), U8(147),
+                B(Star), R(0),
+  /* 1521 S> */ B(LdaConstant), U8(148),
+                B(Star), R(0),
+  /* 1531 S> */ B(LdaConstant), U8(149),
+                B(Star), R(0),
+  /* 1541 S> */ B(LdaConstant), U8(150),
+                B(Star), R(0),
+  /* 1551 S> */ B(LdaConstant), U8(151),
+                B(Star), R(0),
+  /* 1561 S> */ B(LdaConstant), U8(152),
+                B(Star), R(0),
+  /* 1571 S> */ B(LdaConstant), U8(153),
+                B(Star), R(0),
+  /* 1581 S> */ B(LdaConstant), U8(154),
+                B(Star), R(0),
+  /* 1591 S> */ B(LdaConstant), U8(155),
+                B(Star), R(0),
+  /* 1601 S> */ B(LdaConstant), U8(156),
+                B(Star), R(0),
+  /* 1611 S> */ B(LdaConstant), U8(157),
+                B(Star), R(0),
+  /* 1621 S> */ B(LdaConstant), U8(158),
+                B(Star), R(0),
+  /* 1631 S> */ B(LdaConstant), U8(159),
+                B(Star), R(0),
+  /* 1641 S> */ B(LdaConstant), U8(160),
+                B(Star), R(0),
+  /* 1651 S> */ B(LdaConstant), U8(161),
+                B(Star), R(0),
+  /* 1661 S> */ B(LdaConstant), U8(162),
+                B(Star), R(0),
+  /* 1671 S> */ B(LdaConstant), U8(163),
+                B(Star), R(0),
+  /* 1681 S> */ B(LdaConstant), U8(164),
+                B(Star), R(0),
+  /* 1691 S> */ B(LdaConstant), U8(165),
+                B(Star), R(0),
+  /* 1701 S> */ B(LdaConstant), U8(166),
+                B(Star), R(0),
+  /* 1711 S> */ B(LdaConstant), U8(167),
+                B(Star), R(0),
+  /* 1721 S> */ B(LdaConstant), U8(168),
+                B(Star), R(0),
+  /* 1731 S> */ B(LdaConstant), U8(169),
+                B(Star), R(0),
+  /* 1741 S> */ B(LdaConstant), U8(170),
+                B(Star), R(0),
+  /* 1751 S> */ B(LdaConstant), U8(171),
+                B(Star), R(0),
+  /* 1761 S> */ B(LdaConstant), U8(172),
+                B(Star), R(0),
+  /* 1771 S> */ B(LdaConstant), U8(173),
+                B(Star), R(0),
+  /* 1781 S> */ B(LdaConstant), U8(174),
+                B(Star), R(0),
+  /* 1791 S> */ B(LdaConstant), U8(175),
+                B(Star), R(0),
+  /* 1801 S> */ B(LdaConstant), U8(176),
+                B(Star), R(0),
+  /* 1811 S> */ B(LdaConstant), U8(177),
+                B(Star), R(0),
+  /* 1821 S> */ B(LdaConstant), U8(178),
+                B(Star), R(0),
+  /* 1831 S> */ B(LdaConstant), U8(179),
+                B(Star), R(0),
+  /* 1841 S> */ B(LdaConstant), U8(180),
+                B(Star), R(0),
+  /* 1851 S> */ B(LdaConstant), U8(181),
+                B(Star), R(0),
+  /* 1861 S> */ B(LdaConstant), U8(182),
+                B(Star), R(0),
+  /* 1871 S> */ B(LdaConstant), U8(183),
+                B(Star), R(0),
+  /* 1881 S> */ B(LdaConstant), U8(184),
+                B(Star), R(0),
+  /* 1891 S> */ B(LdaConstant), U8(185),
+                B(Star), R(0),
+  /* 1901 S> */ B(LdaConstant), U8(186),
+                B(Star), R(0),
+  /* 1911 S> */ B(LdaConstant), U8(187),
+                B(Star), R(0),
+  /* 1921 S> */ B(LdaConstant), U8(188),
+                B(Star), R(0),
+  /* 1931 S> */ B(LdaConstant), U8(189),
+                B(Star), R(0),
+  /* 1941 S> */ B(LdaConstant), U8(190),
+                B(Star), R(0),
+  /* 1951 S> */ B(LdaConstant), U8(191),
+                B(Star), R(0),
+  /* 1961 S> */ B(LdaConstant), U8(192),
+                B(Star), R(0),
+  /* 1971 S> */ B(LdaConstant), U8(193),
+                B(Star), R(0),
+  /* 1981 S> */ B(LdaConstant), U8(194),
+                B(Star), R(0),
+  /* 1991 S> */ B(LdaConstant), U8(195),
+                B(Star), R(0),
+  /* 2001 S> */ B(LdaConstant), U8(196),
+                B(Star), R(0),
+  /* 2011 S> */ B(LdaConstant), U8(197),
+                B(Star), R(0),
+  /* 2021 S> */ B(LdaConstant), U8(198),
+                B(Star), R(0),
+  /* 2031 S> */ B(LdaConstant), U8(199),
+                B(Star), R(0),
+  /* 2041 S> */ B(LdaConstant), U8(200),
+                B(Star), R(0),
+  /* 2051 S> */ B(LdaConstant), U8(201),
+                B(Star), R(0),
+  /* 2061 S> */ B(LdaConstant), U8(202),
+                B(Star), R(0),
+  /* 2071 S> */ B(LdaConstant), U8(203),
+                B(Star), R(0),
+  /* 2081 S> */ B(LdaConstant), U8(204),
+                B(Star), R(0),
+  /* 2091 S> */ B(LdaConstant), U8(205),
+                B(Star), R(0),
+  /* 2101 S> */ B(LdaConstant), U8(206),
+                B(Star), R(0),
+  /* 2111 S> */ B(LdaConstant), U8(207),
+                B(Star), R(0),
+  /* 2121 S> */ B(LdaConstant), U8(208),
+                B(Star), R(0),
+  /* 2131 S> */ B(LdaConstant), U8(209),
+                B(Star), R(0),
+  /* 2141 S> */ B(LdaConstant), U8(210),
+                B(Star), R(0),
+  /* 2151 S> */ B(LdaConstant), U8(211),
+                B(Star), R(0),
+  /* 2161 S> */ B(LdaConstant), U8(212),
+                B(Star), R(0),
+  /* 2171 S> */ B(LdaConstant), U8(213),
+                B(Star), R(0),
+  /* 2181 S> */ B(LdaConstant), U8(214),
+                B(Star), R(0),
+  /* 2191 S> */ B(LdaConstant), U8(215),
+                B(Star), R(0),
+  /* 2201 S> */ B(LdaConstant), U8(216),
+                B(Star), R(0),
+  /* 2211 S> */ B(LdaConstant), U8(217),
+                B(Star), R(0),
+  /* 2221 S> */ B(LdaConstant), U8(218),
+                B(Star), R(0),
+  /* 2231 S> */ B(LdaConstant), U8(219),
+                B(Star), R(0),
+  /* 2241 S> */ B(LdaConstant), U8(220),
+                B(Star), R(0),
+  /* 2251 S> */ B(LdaConstant), U8(221),
+                B(Star), R(0),
+  /* 2261 S> */ B(LdaConstant), U8(222),
+                B(Star), R(0),
+  /* 2271 S> */ B(LdaConstant), U8(223),
+                B(Star), R(0),
+  /* 2281 S> */ B(LdaConstant), U8(224),
+                B(Star), R(0),
+  /* 2291 S> */ B(LdaConstant), U8(225),
+                B(Star), R(0),
+  /* 2301 S> */ B(LdaConstant), U8(226),
+                B(Star), R(0),
+  /* 2311 S> */ B(LdaConstant), U8(227),
+                B(Star), R(0),
+  /* 2321 S> */ B(LdaConstant), U8(228),
+                B(Star), R(0),
+  /* 2331 S> */ B(LdaConstant), U8(229),
+                B(Star), R(0),
+  /* 2341 S> */ B(LdaConstant), U8(230),
+                B(Star), R(0),
+  /* 2351 S> */ B(LdaConstant), U8(231),
+                B(Star), R(0),
+  /* 2361 S> */ B(LdaConstant), U8(232),
+                B(Star), R(0),
+  /* 2371 S> */ B(LdaConstant), U8(233),
+                B(Star), R(0),
+  /* 2381 S> */ B(LdaConstant), U8(234),
+                B(Star), R(0),
+  /* 2391 S> */ B(LdaConstant), U8(235),
+                B(Star), R(0),
+  /* 2401 S> */ B(LdaConstant), U8(236),
+                B(Star), R(0),
+  /* 2411 S> */ B(LdaConstant), U8(237),
+                B(Star), R(0),
+  /* 2421 S> */ B(LdaConstant), U8(238),
+                B(Star), R(0),
+  /* 2431 S> */ B(LdaConstant), U8(239),
+                B(Star), R(0),
+  /* 2441 S> */ B(LdaConstant), U8(240),
+                B(Star), R(0),
+  /* 2451 S> */ B(LdaConstant), U8(241),
+                B(Star), R(0),
+  /* 2461 S> */ B(LdaConstant), U8(242),
+                B(Star), R(0),
+  /* 2471 S> */ B(LdaConstant), U8(243),
+                B(Star), R(0),
+  /* 2481 S> */ B(LdaConstant), U8(244),
+                B(Star), R(0),
+  /* 2491 S> */ B(LdaConstant), U8(245),
+                B(Star), R(0),
+  /* 2501 S> */ B(LdaConstant), U8(246),
+                B(Star), R(0),
+  /* 2511 S> */ B(LdaConstant), U8(247),
+                B(Star), R(0),
+  /* 2521 S> */ B(LdaConstant), U8(248),
+                B(Star), R(0),
+  /* 2531 S> */ B(LdaConstant), U8(249),
+                B(Star), R(0),
+  /* 2541 S> */ B(LdaConstant), U8(250),
+                B(Star), R(0),
+  /* 2551 S> */ B(LdaConstant), U8(251),
+                B(Star), R(0),
+  /* 2561 S> */ B(LdaConstant), U8(252),
+                B(Star), R(0),
+  /* 2571 S> */ B(LdaConstant), U8(253),
+                B(Star), R(0),
+  /* 2581 S> */ B(LdaConstant), U8(254),
+                B(Star), R(0),
+  /* 2591 S> */ B(LdaConstant), U8(255),
+                B(Star), R(0),
+  /* 2601 S> */ B(Wide), B(CreateObjectLiteral), U16(256), U16(0), U8(1),
+                B(Star), R(1),
+  /* 2638 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::HEAP_NUMBER_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/OuterContextVariables.golden b/test/cctest/interpreter/bytecode_expectations/OuterContextVariables.golden
index 378a5b7..4478c4d 100644
--- a/test/cctest/interpreter/bytecode_expectations/OuterContextVariables.golden
+++ b/test/cctest/interpreter/bytecode_expectations/OuterContextVariables.golden
@@ -22,18 +22,14 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 21
+bytecode array length: 15
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(context),
-  B(Star), R(0),
-  B(LdaContextSlot), R(0), U8(1),
-  B(Star), R(0),
-  B(LdaContextSlot), R(0), U8(4),
-  B(Star), R(1),
-  B(LdaContextSlot), R(context), U8(4),
-  B(Mul), R(1),
-  B(Return),
+  /*   97 E> */ B(StackCheck),
+  /*  102 S> */ B(LdrContextSlot), R(context), U8(1), R(0),
+                B(LdrContextSlot), R(0), U8(4), R(1),
+  /*  120 E> */ B(LdaContextSlot), R(context), U8(4),
+                B(Mul), R(1),
+  /*  130 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -54,19 +50,15 @@
 "
 frame size: 2
 parameter count: 1
-bytecode array length: 22
+bytecode array length: 16
 bytecodes: [
-  B(StackCheck),
-  B(LdaContextSlot), R(context), U8(4),
-  B(Star), R(0),
-  B(Ldar), R(context),
-  B(Star), R(1),
-  B(LdaContextSlot), R(1), U8(1),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(StaContextSlot), R(1), U8(4),
-  B(LdaUndefined),
-  B(Return),
+  /*   97 E> */ B(StackCheck),
+  /*  102 S> */ B(LdrContextSlot), R(context), U8(4), R(0),
+  /*  111 E> */ B(LdrContextSlot), R(context), U8(1), R(1),
+                B(Ldar), R(0),
+                B(StaContextSlot), R(1), U8(4),
+                B(LdaUndefined),
+  /*  123 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/Parameters.golden b/test/cctest/interpreter/bytecode_expectations/Parameters.golden
index e124788..71b6df7 100644
--- a/test/cctest/interpreter/bytecode_expectations/Parameters.golden
+++ b/test/cctest/interpreter/bytecode_expectations/Parameters.golden
@@ -17,9 +17,9 @@
 parameter count: 1
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(this),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   15 S> */ B(Ldar), R(this),
+  /*   28 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -35,9 +35,9 @@
 parameter count: 2
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   19 S> */ B(Ldar), R(arg0),
+  /*   32 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -53,9 +53,9 @@
 parameter count: 2
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(this),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   19 S> */ B(Ldar), R(this),
+  /*   32 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -71,9 +71,9 @@
 parameter count: 8
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg3),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   55 S> */ B(Ldar), R(arg3),
+  /*   68 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -89,9 +89,9 @@
 parameter count: 8
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(this),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   55 S> */ B(Ldar), R(this),
+  /*   68 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -107,11 +107,11 @@
 parameter count: 2
 bytecode array length: 7
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(arg0),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   19 S> */ B(LdaSmi), U8(1),
+                B(Star), R(arg0),
+                B(LdaUndefined),
+  /*   29 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -127,11 +127,11 @@
 parameter count: 5
 bytecode array length: 7
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(arg1),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   37 S> */ B(LdaSmi), U8(1),
+                B(Star), R(arg1),
+                B(LdaUndefined),
+  /*   47 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/PrimitiveExpressions.golden b/test/cctest/interpreter/bytecode_expectations/PrimitiveExpressions.golden
index 08b20dd..8ff00a0 100644
--- a/test/cctest/interpreter/bytecode_expectations/PrimitiveExpressions.golden
+++ b/test/cctest/interpreter/bytecode_expectations/PrimitiveExpressions.golden
@@ -13,12 +13,13 @@
 "
 frame size: 1
 parameter count: 1
-bytecode array length: 5
+bytecode array length: 6
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   45 S> */ B(Nop),
+  /*   55 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -29,17 +30,16 @@
 snippet: "
   var x = 0; return x + 3;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 11
+bytecode array length: 9
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(Add), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(3),
+                B(Add), R(0),
+  /*   59 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -50,17 +50,16 @@
 snippet: "
   var x = 0; return x - 3;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 11
+bytecode array length: 9
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(Sub), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(3),
+                B(Sub), R(0),
+  /*   59 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -71,17 +70,16 @@
 snippet: "
   var x = 4; return x * 3;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 12
+bytecode array length: 10
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(4),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(Mul), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(4),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(3),
+                B(Mul), R(0),
+  /*   59 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -92,17 +90,16 @@
 snippet: "
   var x = 4; return x / 3;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 12
+bytecode array length: 10
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(4),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(Div), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(4),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(3),
+                B(Div), R(0),
+  /*   59 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -113,17 +110,16 @@
 snippet: "
   var x = 4; return x % 3;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 12
+bytecode array length: 10
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(4),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(Mod), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(4),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(3),
+                B(Mod), R(0),
+  /*   59 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -134,17 +130,16 @@
 snippet: "
   var x = 1; return x | 2;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 12
+bytecode array length: 10
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(BitwiseOr), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(2),
+                B(BitwiseOr), R(0),
+  /*   59 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -155,17 +150,16 @@
 snippet: "
   var x = 1; return x ^ 2;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 12
+bytecode array length: 10
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(BitwiseXor), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(2),
+                B(BitwiseXor), R(0),
+  /*   59 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -176,17 +170,16 @@
 snippet: "
   var x = 1; return x & 2;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 12
+bytecode array length: 10
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(BitwiseAnd), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(2),
+                B(BitwiseAnd), R(0),
+  /*   59 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -197,17 +190,16 @@
 snippet: "
   var x = 10; return x << 3;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 12
+bytecode array length: 10
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(ShiftLeft), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(10),
+                B(Star), R(0),
+  /*   46 S> */ B(LdaSmi), U8(3),
+                B(ShiftLeft), R(0),
+  /*   61 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -218,17 +210,16 @@
 snippet: "
   var x = 10; return x >> 3;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 12
+bytecode array length: 10
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(ShiftRight), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(10),
+                B(Star), R(0),
+  /*   46 S> */ B(LdaSmi), U8(3),
+                B(ShiftRight), R(0),
+  /*   61 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -239,17 +230,16 @@
 snippet: "
   var x = 10; return x >>> 3;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 12
+bytecode array length: 10
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(10),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(ShiftRightLogical), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(10),
+                B(Star), R(0),
+  /*   46 S> */ B(LdaSmi), U8(3),
+                B(ShiftRightLogical), R(0),
+  /*   62 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -264,11 +254,11 @@
 parameter count: 1
 bytecode array length: 7
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(LdaSmi), U8(3),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(3),
+  /*   60 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/PrimitiveReturnStatements.golden b/test/cctest/interpreter/bytecode_expectations/PrimitiveReturnStatements.golden
index 0a23f2b..a707451 100644
--- a/test/cctest/interpreter/bytecode_expectations/PrimitiveReturnStatements.golden
+++ b/test/cctest/interpreter/bytecode_expectations/PrimitiveReturnStatements.golden
@@ -14,9 +14,9 @@
 parameter count: 1
 bytecode array length: 3
 bytecodes: [
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+                B(LdaUndefined),
+  /*   34 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -31,9 +31,9 @@
 parameter count: 1
 bytecode array length: 3
 bytecodes: [
-  B(StackCheck),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaUndefined),
+  /*   42 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -48,9 +48,9 @@
 parameter count: 1
 bytecode array length: 3
 bytecodes: [
-  B(StackCheck),
-  B(LdaNull),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaNull),
+  /*   47 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -65,9 +65,9 @@
 parameter count: 1
 bytecode array length: 3
 bytecodes: [
-  B(StackCheck),
-  B(LdaTrue),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaTrue),
+  /*   47 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -82,9 +82,9 @@
 parameter count: 1
 bytecode array length: 3
 bytecodes: [
-  B(StackCheck),
-  B(LdaFalse),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaFalse),
+  /*   48 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -99,9 +99,9 @@
 parameter count: 1
 bytecode array length: 3
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaZero),
+  /*   44 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -116,9 +116,9 @@
 parameter count: 1
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaSmi), U8(1),
+  /*   45 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -133,9 +133,9 @@
 parameter count: 1
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(-1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaSmi), U8(-1),
+  /*   45 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -150,9 +150,9 @@
 parameter count: 1
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(127),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaSmi), U8(127),
+  /*   47 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -167,9 +167,9 @@
 parameter count: 1
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(-128),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaSmi), U8(-128),
+  /*   47 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/PropertyCall.golden b/test/cctest/interpreter/bytecode_expectations/PropertyCall.golden
index d6108f1..583a073 100644
--- a/test/cctest/interpreter/bytecode_expectations/PropertyCall.golden
+++ b/test/cctest/interpreter/bytecode_expectations/PropertyCall.golden
@@ -13,17 +13,15 @@
   function f(a) { return a.func(); }
   f(new (function Obj() { this.func = function() { return; }})())
 "
-frame size: 2
+frame size: 1
 parameter count: 2
-bytecode array length: 17
+bytecode array length: 13
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(3),
-  B(Star), R(0),
-  B(Call), R(0), R(1), U8(1), U8(1),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   16 S> */ B(Nop),
+  /*   24 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(3), R(0),
+  /*   25 E> */ B(Call), R(0), R(arg0), U8(1), U8(1),
+  /*   33 S> */ B(Return),
 ]
 constant pool: [
   "func",
@@ -38,19 +36,17 @@
 "
 frame size: 4
 parameter count: 4
-bytecode array length: 25
+bytecode array length: 24
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(3),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(2),
-  B(Ldar), R(arg2),
-  B(Star), R(3),
-  B(Call), R(0), R(1), U8(3), U8(1),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   22 S> */ B(Nop),
+  /*   30 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(3), R(0),
+                B(Ldar), R(0),
+                B(Mov), R(arg0), R(1),
+                B(Mov), R(arg1), R(2),
+                B(Mov), R(arg2), R(3),
+  /*   31 E> */ B(Call), R(0), R(1), U8(3), U8(1),
+  /*   43 S> */ B(Return),
 ]
 constant pool: [
   "func",
@@ -65,22 +61,18 @@
 "
 frame size: 4
 parameter count: 3
-bytecode array length: 31
+bytecode array length: 25
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(3),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(3),
-  B(Ldar), R(arg1),
-  B(Add), R(3),
-  B(Star), R(2),
-  B(Ldar), R(arg1),
-  B(Star), R(3),
-  B(Call), R(0), R(1), U8(3), U8(1),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   19 S> */ B(Nop),
+  /*   27 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(3), R(0),
+                B(Ldar), R(arg1),
+  /*   37 E> */ B(Add), R(arg1),
+                B(Star), R(2),
+                B(Mov), R(arg0), R(1),
+                B(Mov), R(arg1), R(3),
+  /*   28 E> */ B(Call), R(0), R(1), U8(3), U8(1),
+  /*   44 S> */ B(Return),
 ]
 constant pool: [
   "func",
@@ -222,401 +214,271 @@
    return a.func(); }
   f(new (function Obj() { this.func = function() { return; }})())
 "
-frame size: 2
+frame size: 1
 parameter count: 2
-bytecode array length: 1050
+bytecode array length: 663
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(1),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(3),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(5),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(7),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(9),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(11),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(13),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(15),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(17),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(19),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(21),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(23),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(25),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(27),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(29),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(31),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(33),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(35),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(37),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(39),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(41),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(43),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(45),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(47),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(49),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(51),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(53),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(55),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(57),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(59),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(61),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(63),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(65),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(67),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(69),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(71),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(73),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(75),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(77),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(79),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(81),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(83),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(85),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(87),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(89),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(91),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(93),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(95),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(97),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(99),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(101),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(103),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(105),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(107),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(109),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(111),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(113),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(115),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(117),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(119),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(121),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(123),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(125),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(127),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(129),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(131),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(133),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(135),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(137),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(139),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(141),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(143),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(145),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(147),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(149),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(151),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(153),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(155),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(157),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(159),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(161),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(163),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(165),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(167),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(169),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(171),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(173),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(175),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(177),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(179),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(181),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(183),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(185),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(187),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(189),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(191),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(193),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(195),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(197),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(199),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(201),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(203),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(205),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(207),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(209),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(211),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(213),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(215),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(217),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(219),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(221),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(223),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(225),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(227),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(229),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(231),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(233),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(235),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(237),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(239),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(241),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(243),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(245),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(247),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(249),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(251),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(253),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(255),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Wide), B(LoadIC), R16(1), U16(0), U16(259),
-  B(Star), R(0),
-  B(Wide), B(Call), R16(0), R16(1), U16(1), U16(257),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   17 S> */ B(Nop),
+  /*   18 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(1),
+  /*   26 S> */ B(Nop),
+  /*   27 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(3),
+  /*   35 S> */ B(Nop),
+  /*   36 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(5),
+  /*   44 S> */ B(Nop),
+  /*   45 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(7),
+  /*   53 S> */ B(Nop),
+  /*   54 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(9),
+  /*   62 S> */ B(Nop),
+  /*   63 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(11),
+  /*   71 S> */ B(Nop),
+  /*   72 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(13),
+  /*   80 S> */ B(Nop),
+  /*   81 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(15),
+  /*   89 S> */ B(Nop),
+  /*   90 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(17),
+  /*   98 S> */ B(Nop),
+  /*   99 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(19),
+  /*  107 S> */ B(Nop),
+  /*  108 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(21),
+  /*  116 S> */ B(Nop),
+  /*  117 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(23),
+  /*  125 S> */ B(Nop),
+  /*  126 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(25),
+  /*  134 S> */ B(Nop),
+  /*  135 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(27),
+  /*  143 S> */ B(Nop),
+  /*  144 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(29),
+  /*  152 S> */ B(Nop),
+  /*  153 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(31),
+  /*  161 S> */ B(Nop),
+  /*  162 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(33),
+  /*  170 S> */ B(Nop),
+  /*  171 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(35),
+  /*  179 S> */ B(Nop),
+  /*  180 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(37),
+  /*  188 S> */ B(Nop),
+  /*  189 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(39),
+  /*  197 S> */ B(Nop),
+  /*  198 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(41),
+  /*  206 S> */ B(Nop),
+  /*  207 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(43),
+  /*  215 S> */ B(Nop),
+  /*  216 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(45),
+  /*  224 S> */ B(Nop),
+  /*  225 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(47),
+  /*  233 S> */ B(Nop),
+  /*  234 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(49),
+  /*  242 S> */ B(Nop),
+  /*  243 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(51),
+  /*  251 S> */ B(Nop),
+  /*  252 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(53),
+  /*  260 S> */ B(Nop),
+  /*  261 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(55),
+  /*  269 S> */ B(Nop),
+  /*  270 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(57),
+  /*  278 S> */ B(Nop),
+  /*  279 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(59),
+  /*  287 S> */ B(Nop),
+  /*  288 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(61),
+  /*  296 S> */ B(Nop),
+  /*  297 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(63),
+  /*  305 S> */ B(Nop),
+  /*  306 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(65),
+  /*  314 S> */ B(Nop),
+  /*  315 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(67),
+  /*  323 S> */ B(Nop),
+  /*  324 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(69),
+  /*  332 S> */ B(Nop),
+  /*  333 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(71),
+  /*  341 S> */ B(Nop),
+  /*  342 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(73),
+  /*  350 S> */ B(Nop),
+  /*  351 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(75),
+  /*  359 S> */ B(Nop),
+  /*  360 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(77),
+  /*  368 S> */ B(Nop),
+  /*  369 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(79),
+  /*  377 S> */ B(Nop),
+  /*  378 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(81),
+  /*  386 S> */ B(Nop),
+  /*  387 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(83),
+  /*  395 S> */ B(Nop),
+  /*  396 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(85),
+  /*  404 S> */ B(Nop),
+  /*  405 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(87),
+  /*  413 S> */ B(Nop),
+  /*  414 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(89),
+  /*  422 S> */ B(Nop),
+  /*  423 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(91),
+  /*  431 S> */ B(Nop),
+  /*  432 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(93),
+  /*  440 S> */ B(Nop),
+  /*  441 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(95),
+  /*  449 S> */ B(Nop),
+  /*  450 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(97),
+  /*  458 S> */ B(Nop),
+  /*  459 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(99),
+  /*  467 S> */ B(Nop),
+  /*  468 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(101),
+  /*  476 S> */ B(Nop),
+  /*  477 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(103),
+  /*  485 S> */ B(Nop),
+  /*  486 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(105),
+  /*  494 S> */ B(Nop),
+  /*  495 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(107),
+  /*  503 S> */ B(Nop),
+  /*  504 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(109),
+  /*  512 S> */ B(Nop),
+  /*  513 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(111),
+  /*  521 S> */ B(Nop),
+  /*  522 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(113),
+  /*  530 S> */ B(Nop),
+  /*  531 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(115),
+  /*  539 S> */ B(Nop),
+  /*  540 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(117),
+  /*  548 S> */ B(Nop),
+  /*  549 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(119),
+  /*  557 S> */ B(Nop),
+  /*  558 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(121),
+  /*  566 S> */ B(Nop),
+  /*  567 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(123),
+  /*  575 S> */ B(Nop),
+  /*  576 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(125),
+  /*  584 S> */ B(Nop),
+  /*  585 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(127),
+  /*  593 S> */ B(Nop),
+  /*  594 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(129),
+  /*  602 S> */ B(Nop),
+  /*  603 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(131),
+  /*  611 S> */ B(Nop),
+  /*  612 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(133),
+  /*  620 S> */ B(Nop),
+  /*  621 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(135),
+  /*  629 S> */ B(Nop),
+  /*  630 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(137),
+  /*  638 S> */ B(Nop),
+  /*  639 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(139),
+  /*  647 S> */ B(Nop),
+  /*  648 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(141),
+  /*  656 S> */ B(Nop),
+  /*  657 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(143),
+  /*  665 S> */ B(Nop),
+  /*  666 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(145),
+  /*  674 S> */ B(Nop),
+  /*  675 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(147),
+  /*  683 S> */ B(Nop),
+  /*  684 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(149),
+  /*  692 S> */ B(Nop),
+  /*  693 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(151),
+  /*  701 S> */ B(Nop),
+  /*  702 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(153),
+  /*  710 S> */ B(Nop),
+  /*  711 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(155),
+  /*  719 S> */ B(Nop),
+  /*  720 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(157),
+  /*  728 S> */ B(Nop),
+  /*  729 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(159),
+  /*  737 S> */ B(Nop),
+  /*  738 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(161),
+  /*  746 S> */ B(Nop),
+  /*  747 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(163),
+  /*  755 S> */ B(Nop),
+  /*  756 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(165),
+  /*  764 S> */ B(Nop),
+  /*  765 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(167),
+  /*  773 S> */ B(Nop),
+  /*  774 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(169),
+  /*  782 S> */ B(Nop),
+  /*  783 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(171),
+  /*  791 S> */ B(Nop),
+  /*  792 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(173),
+  /*  800 S> */ B(Nop),
+  /*  801 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(175),
+  /*  809 S> */ B(Nop),
+  /*  810 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(177),
+  /*  818 S> */ B(Nop),
+  /*  819 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(179),
+  /*  827 S> */ B(Nop),
+  /*  828 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(181),
+  /*  836 S> */ B(Nop),
+  /*  837 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(183),
+  /*  845 S> */ B(Nop),
+  /*  846 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(185),
+  /*  854 S> */ B(Nop),
+  /*  855 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(187),
+  /*  863 S> */ B(Nop),
+  /*  864 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(189),
+  /*  872 S> */ B(Nop),
+  /*  873 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(191),
+  /*  881 S> */ B(Nop),
+  /*  882 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(193),
+  /*  890 S> */ B(Nop),
+  /*  891 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(195),
+  /*  899 S> */ B(Nop),
+  /*  900 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(197),
+  /*  908 S> */ B(Nop),
+  /*  909 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(199),
+  /*  917 S> */ B(Nop),
+  /*  918 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(201),
+  /*  926 S> */ B(Nop),
+  /*  927 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(203),
+  /*  935 S> */ B(Nop),
+  /*  936 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(205),
+  /*  944 S> */ B(Nop),
+  /*  945 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(207),
+  /*  953 S> */ B(Nop),
+  /*  954 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(209),
+  /*  962 S> */ B(Nop),
+  /*  963 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(211),
+  /*  971 S> */ B(Nop),
+  /*  972 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(213),
+  /*  980 S> */ B(Nop),
+  /*  981 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(215),
+  /*  989 S> */ B(Nop),
+  /*  990 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(217),
+  /*  998 S> */ B(Nop),
+  /*  999 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(219),
+  /* 1007 S> */ B(Nop),
+  /* 1008 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(221),
+  /* 1016 S> */ B(Nop),
+  /* 1017 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(223),
+  /* 1025 S> */ B(Nop),
+  /* 1026 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(225),
+  /* 1034 S> */ B(Nop),
+  /* 1035 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(227),
+  /* 1043 S> */ B(Nop),
+  /* 1044 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(229),
+  /* 1052 S> */ B(Nop),
+  /* 1053 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(231),
+  /* 1061 S> */ B(Nop),
+  /* 1062 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(233),
+  /* 1070 S> */ B(Nop),
+  /* 1071 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(235),
+  /* 1079 S> */ B(Nop),
+  /* 1080 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(237),
+  /* 1088 S> */ B(Nop),
+  /* 1089 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(239),
+  /* 1097 S> */ B(Nop),
+  /* 1098 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(241),
+  /* 1106 S> */ B(Nop),
+  /* 1107 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(243),
+  /* 1115 S> */ B(Nop),
+  /* 1116 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(245),
+  /* 1124 S> */ B(Nop),
+  /* 1125 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(247),
+  /* 1133 S> */ B(Nop),
+  /* 1134 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(249),
+  /* 1142 S> */ B(Nop),
+  /* 1143 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(251),
+  /* 1151 S> */ B(Nop),
+  /* 1152 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(253),
+  /* 1160 S> */ B(Nop),
+  /* 1161 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(255),
+  /* 1169 S> */ B(Nop),
+  /* 1177 E> */ B(Wide), B(LdrNamedProperty), R16(arg0), U16(0), U16(259), R16(0),
+  /* 1178 E> */ B(Wide), B(Call), R16(0), R16(arg0), U16(1), U16(257),
+  /* 1186 S> */ B(Return),
 ]
 constant pool: [
   "func",
diff --git a/test/cctest/interpreter/bytecode_expectations/PropertyLoads.golden b/test/cctest/interpreter/bytecode_expectations/PropertyLoads.golden
index 7d5a58e..cee0357 100644
--- a/test/cctest/interpreter/bytecode_expectations/PropertyLoads.golden
+++ b/test/cctest/interpreter/bytecode_expectations/PropertyLoads.golden
@@ -13,15 +13,14 @@
   function f(a) { return a.name; }
   f({name : \"test\"});
 "
-frame size: 1
+frame size: 0
 parameter count: 2
-bytecode array length: 10
+bytecode array length: 7
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(1),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   16 S> */ B(Nop),
+  /*   24 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(1),
+  /*   31 S> */ B(Return),
 ]
 constant pool: [
   "name",
@@ -34,15 +33,14 @@
   function f(a) { return a[\"key\"]; }
   f({key : \"test\"});
 "
-frame size: 1
+frame size: 0
 parameter count: 2
-bytecode array length: 10
+bytecode array length: 7
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(1),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   16 S> */ B(Nop),
+  /*   24 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(1),
+  /*   33 S> */ B(Return),
 ]
 constant pool: [
   "key",
@@ -55,16 +53,14 @@
   function f(a) { return a[100]; }
   f({100 : \"test\"});
 "
-frame size: 1
+frame size: 0
 parameter count: 2
-bytecode array length: 11
+bytecode array length: 7
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(100),
-  B(KeyedLoadIC), R(0), U8(1),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   16 S> */ B(LdaSmi), U8(100),
+  /*   24 E> */ B(LdaKeyedProperty), R(arg0), U8(1),
+  /*   31 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -76,16 +72,14 @@
   function f(a, b) { return a[b]; }
   f({arg : \"test\"}, \"arg\");
 "
-frame size: 1
+frame size: 0
 parameter count: 3
-bytecode array length: 11
+bytecode array length: 7
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(0), U8(1),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   19 S> */ B(Ldar), R(arg1),
+  /*   28 E> */ B(LdaKeyedProperty), R(arg0), U8(1),
+  /*   32 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -97,20 +91,17 @@
   function f(a) { var b = a.name; return a[-124]; }
   f({\"-124\" : \"test\", name : 123 })
 "
-frame size: 2
+frame size: 1
 parameter count: 2
-bytecode array length: 21
+bytecode array length: 15
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(1),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LdaSmi), U8(-124),
-  B(KeyedLoadIC), R(1), U8(3),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   25 S> */ B(Nop),
+  /*   25 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(1), R(0),
+                B(Ldar), R(0),
+  /*   32 S> */ B(LdaSmi), U8(-124),
+  /*   40 E> */ B(LdaKeyedProperty), R(arg0), U8(3),
+  /*   48 S> */ B(Return),
 ]
 constant pool: [
   "name",
@@ -254,527 +245,398 @@
   }
   f({name : \"test\"})
 "
-frame size: 2
+frame size: 1
 parameter count: 2
-bytecode array length: 1294
+bytecode array length: 1035
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(1),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(3),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(5),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(7),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(9),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(11),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(13),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(15),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(17),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(19),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(21),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(23),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(25),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(27),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(29),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(31),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(33),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(35),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(37),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(39),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(41),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(43),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(45),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(47),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(49),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(51),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(53),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(55),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(57),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(59),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(61),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(63),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(65),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(67),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(69),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(71),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(73),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(75),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(77),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(79),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(81),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(83),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(85),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(87),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(89),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(91),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(93),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(95),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(97),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(99),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(101),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(103),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(105),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(107),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(109),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(111),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(113),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(115),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(117),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(119),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(121),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(123),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(125),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(127),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(129),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(131),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(133),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(135),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(137),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(139),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(141),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(143),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(145),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(147),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(149),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(151),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(153),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(155),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(157),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(159),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(161),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(163),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(165),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(167),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(169),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(171),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(173),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(175),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(177),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(179),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(181),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(183),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(185),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(187),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(189),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(191),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(193),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(195),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(197),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(199),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(201),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(203),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(205),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(207),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(209),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(211),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(213),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(215),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(217),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(219),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(221),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(223),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(225),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(227),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(229),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(231),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(233),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(235),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(237),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(239),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(241),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(243),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(245),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(247),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(249),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(251),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(253),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(0), U8(255),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Wide), B(LoadIC), R16(1), U16(0), U16(257),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   27 S> */ B(Nop),
+  /*   32 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(1), R(0),
+                B(Ldar), R(0),
+  /*   41 S> */ B(Nop),
+  /*   46 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(3), R(0),
+                B(Ldar), R(0),
+  /*   55 S> */ B(Nop),
+  /*   60 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(5), R(0),
+                B(Ldar), R(0),
+  /*   69 S> */ B(Nop),
+  /*   74 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(7), R(0),
+                B(Ldar), R(0),
+  /*   83 S> */ B(Nop),
+  /*   88 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(9), R(0),
+                B(Ldar), R(0),
+  /*   97 S> */ B(Nop),
+  /*  102 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(11), R(0),
+                B(Ldar), R(0),
+  /*  111 S> */ B(Nop),
+  /*  116 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(13), R(0),
+                B(Ldar), R(0),
+  /*  125 S> */ B(Nop),
+  /*  130 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(15), R(0),
+                B(Ldar), R(0),
+  /*  139 S> */ B(Nop),
+  /*  144 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(17), R(0),
+                B(Ldar), R(0),
+  /*  153 S> */ B(Nop),
+  /*  158 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(19), R(0),
+                B(Ldar), R(0),
+  /*  167 S> */ B(Nop),
+  /*  172 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(21), R(0),
+                B(Ldar), R(0),
+  /*  181 S> */ B(Nop),
+  /*  186 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(23), R(0),
+                B(Ldar), R(0),
+  /*  195 S> */ B(Nop),
+  /*  200 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(25), R(0),
+                B(Ldar), R(0),
+  /*  209 S> */ B(Nop),
+  /*  214 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(27), R(0),
+                B(Ldar), R(0),
+  /*  223 S> */ B(Nop),
+  /*  228 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(29), R(0),
+                B(Ldar), R(0),
+  /*  237 S> */ B(Nop),
+  /*  242 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(31), R(0),
+                B(Ldar), R(0),
+  /*  251 S> */ B(Nop),
+  /*  256 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(33), R(0),
+                B(Ldar), R(0),
+  /*  265 S> */ B(Nop),
+  /*  270 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(35), R(0),
+                B(Ldar), R(0),
+  /*  279 S> */ B(Nop),
+  /*  284 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(37), R(0),
+                B(Ldar), R(0),
+  /*  293 S> */ B(Nop),
+  /*  298 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(39), R(0),
+                B(Ldar), R(0),
+  /*  307 S> */ B(Nop),
+  /*  312 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(41), R(0),
+                B(Ldar), R(0),
+  /*  321 S> */ B(Nop),
+  /*  326 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(43), R(0),
+                B(Ldar), R(0),
+  /*  335 S> */ B(Nop),
+  /*  340 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(45), R(0),
+                B(Ldar), R(0),
+  /*  349 S> */ B(Nop),
+  /*  354 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(47), R(0),
+                B(Ldar), R(0),
+  /*  363 S> */ B(Nop),
+  /*  368 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(49), R(0),
+                B(Ldar), R(0),
+  /*  377 S> */ B(Nop),
+  /*  382 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(51), R(0),
+                B(Ldar), R(0),
+  /*  391 S> */ B(Nop),
+  /*  396 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(53), R(0),
+                B(Ldar), R(0),
+  /*  405 S> */ B(Nop),
+  /*  410 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(55), R(0),
+                B(Ldar), R(0),
+  /*  419 S> */ B(Nop),
+  /*  424 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(57), R(0),
+                B(Ldar), R(0),
+  /*  433 S> */ B(Nop),
+  /*  438 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(59), R(0),
+                B(Ldar), R(0),
+  /*  447 S> */ B(Nop),
+  /*  452 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(61), R(0),
+                B(Ldar), R(0),
+  /*  461 S> */ B(Nop),
+  /*  466 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(63), R(0),
+                B(Ldar), R(0),
+  /*  475 S> */ B(Nop),
+  /*  480 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(65), R(0),
+                B(Ldar), R(0),
+  /*  489 S> */ B(Nop),
+  /*  494 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(67), R(0),
+                B(Ldar), R(0),
+  /*  503 S> */ B(Nop),
+  /*  508 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(69), R(0),
+                B(Ldar), R(0),
+  /*  517 S> */ B(Nop),
+  /*  522 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(71), R(0),
+                B(Ldar), R(0),
+  /*  531 S> */ B(Nop),
+  /*  536 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(73), R(0),
+                B(Ldar), R(0),
+  /*  545 S> */ B(Nop),
+  /*  550 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(75), R(0),
+                B(Ldar), R(0),
+  /*  559 S> */ B(Nop),
+  /*  564 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(77), R(0),
+                B(Ldar), R(0),
+  /*  573 S> */ B(Nop),
+  /*  578 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(79), R(0),
+                B(Ldar), R(0),
+  /*  587 S> */ B(Nop),
+  /*  592 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(81), R(0),
+                B(Ldar), R(0),
+  /*  601 S> */ B(Nop),
+  /*  606 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(83), R(0),
+                B(Ldar), R(0),
+  /*  615 S> */ B(Nop),
+  /*  620 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(85), R(0),
+                B(Ldar), R(0),
+  /*  629 S> */ B(Nop),
+  /*  634 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(87), R(0),
+                B(Ldar), R(0),
+  /*  643 S> */ B(Nop),
+  /*  648 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(89), R(0),
+                B(Ldar), R(0),
+  /*  657 S> */ B(Nop),
+  /*  662 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(91), R(0),
+                B(Ldar), R(0),
+  /*  671 S> */ B(Nop),
+  /*  676 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(93), R(0),
+                B(Ldar), R(0),
+  /*  685 S> */ B(Nop),
+  /*  690 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(95), R(0),
+                B(Ldar), R(0),
+  /*  699 S> */ B(Nop),
+  /*  704 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(97), R(0),
+                B(Ldar), R(0),
+  /*  713 S> */ B(Nop),
+  /*  718 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(99), R(0),
+                B(Ldar), R(0),
+  /*  727 S> */ B(Nop),
+  /*  732 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(101), R(0),
+                B(Ldar), R(0),
+  /*  741 S> */ B(Nop),
+  /*  746 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(103), R(0),
+                B(Ldar), R(0),
+  /*  755 S> */ B(Nop),
+  /*  760 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(105), R(0),
+                B(Ldar), R(0),
+  /*  769 S> */ B(Nop),
+  /*  774 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(107), R(0),
+                B(Ldar), R(0),
+  /*  783 S> */ B(Nop),
+  /*  788 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(109), R(0),
+                B(Ldar), R(0),
+  /*  797 S> */ B(Nop),
+  /*  802 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(111), R(0),
+                B(Ldar), R(0),
+  /*  811 S> */ B(Nop),
+  /*  816 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(113), R(0),
+                B(Ldar), R(0),
+  /*  825 S> */ B(Nop),
+  /*  830 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(115), R(0),
+                B(Ldar), R(0),
+  /*  839 S> */ B(Nop),
+  /*  844 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(117), R(0),
+                B(Ldar), R(0),
+  /*  853 S> */ B(Nop),
+  /*  858 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(119), R(0),
+                B(Ldar), R(0),
+  /*  867 S> */ B(Nop),
+  /*  872 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(121), R(0),
+                B(Ldar), R(0),
+  /*  881 S> */ B(Nop),
+  /*  886 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(123), R(0),
+                B(Ldar), R(0),
+  /*  895 S> */ B(Nop),
+  /*  900 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(125), R(0),
+                B(Ldar), R(0),
+  /*  909 S> */ B(Nop),
+  /*  914 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(127), R(0),
+                B(Ldar), R(0),
+  /*  923 S> */ B(Nop),
+  /*  928 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(129), R(0),
+                B(Ldar), R(0),
+  /*  937 S> */ B(Nop),
+  /*  942 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(131), R(0),
+                B(Ldar), R(0),
+  /*  951 S> */ B(Nop),
+  /*  956 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(133), R(0),
+                B(Ldar), R(0),
+  /*  965 S> */ B(Nop),
+  /*  970 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(135), R(0),
+                B(Ldar), R(0),
+  /*  979 S> */ B(Nop),
+  /*  984 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(137), R(0),
+                B(Ldar), R(0),
+  /*  993 S> */ B(Nop),
+  /*  998 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(139), R(0),
+                B(Ldar), R(0),
+  /* 1007 S> */ B(Nop),
+  /* 1012 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(141), R(0),
+                B(Ldar), R(0),
+  /* 1021 S> */ B(Nop),
+  /* 1026 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(143), R(0),
+                B(Ldar), R(0),
+  /* 1035 S> */ B(Nop),
+  /* 1040 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(145), R(0),
+                B(Ldar), R(0),
+  /* 1049 S> */ B(Nop),
+  /* 1054 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(147), R(0),
+                B(Ldar), R(0),
+  /* 1063 S> */ B(Nop),
+  /* 1068 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(149), R(0),
+                B(Ldar), R(0),
+  /* 1077 S> */ B(Nop),
+  /* 1082 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(151), R(0),
+                B(Ldar), R(0),
+  /* 1091 S> */ B(Nop),
+  /* 1096 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(153), R(0),
+                B(Ldar), R(0),
+  /* 1105 S> */ B(Nop),
+  /* 1110 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(155), R(0),
+                B(Ldar), R(0),
+  /* 1119 S> */ B(Nop),
+  /* 1124 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(157), R(0),
+                B(Ldar), R(0),
+  /* 1133 S> */ B(Nop),
+  /* 1138 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(159), R(0),
+                B(Ldar), R(0),
+  /* 1147 S> */ B(Nop),
+  /* 1152 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(161), R(0),
+                B(Ldar), R(0),
+  /* 1161 S> */ B(Nop),
+  /* 1166 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(163), R(0),
+                B(Ldar), R(0),
+  /* 1175 S> */ B(Nop),
+  /* 1180 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(165), R(0),
+                B(Ldar), R(0),
+  /* 1189 S> */ B(Nop),
+  /* 1194 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(167), R(0),
+                B(Ldar), R(0),
+  /* 1203 S> */ B(Nop),
+  /* 1208 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(169), R(0),
+                B(Ldar), R(0),
+  /* 1217 S> */ B(Nop),
+  /* 1222 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(171), R(0),
+                B(Ldar), R(0),
+  /* 1231 S> */ B(Nop),
+  /* 1236 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(173), R(0),
+                B(Ldar), R(0),
+  /* 1245 S> */ B(Nop),
+  /* 1250 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(175), R(0),
+                B(Ldar), R(0),
+  /* 1259 S> */ B(Nop),
+  /* 1264 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(177), R(0),
+                B(Ldar), R(0),
+  /* 1273 S> */ B(Nop),
+  /* 1278 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(179), R(0),
+                B(Ldar), R(0),
+  /* 1287 S> */ B(Nop),
+  /* 1292 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(181), R(0),
+                B(Ldar), R(0),
+  /* 1301 S> */ B(Nop),
+  /* 1306 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(183), R(0),
+                B(Ldar), R(0),
+  /* 1315 S> */ B(Nop),
+  /* 1320 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(185), R(0),
+                B(Ldar), R(0),
+  /* 1329 S> */ B(Nop),
+  /* 1334 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(187), R(0),
+                B(Ldar), R(0),
+  /* 1343 S> */ B(Nop),
+  /* 1348 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(189), R(0),
+                B(Ldar), R(0),
+  /* 1357 S> */ B(Nop),
+  /* 1362 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(191), R(0),
+                B(Ldar), R(0),
+  /* 1371 S> */ B(Nop),
+  /* 1376 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(193), R(0),
+                B(Ldar), R(0),
+  /* 1385 S> */ B(Nop),
+  /* 1390 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(195), R(0),
+                B(Ldar), R(0),
+  /* 1399 S> */ B(Nop),
+  /* 1404 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(197), R(0),
+                B(Ldar), R(0),
+  /* 1413 S> */ B(Nop),
+  /* 1418 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(199), R(0),
+                B(Ldar), R(0),
+  /* 1427 S> */ B(Nop),
+  /* 1432 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(201), R(0),
+                B(Ldar), R(0),
+  /* 1441 S> */ B(Nop),
+  /* 1446 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(203), R(0),
+                B(Ldar), R(0),
+  /* 1455 S> */ B(Nop),
+  /* 1460 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(205), R(0),
+                B(Ldar), R(0),
+  /* 1469 S> */ B(Nop),
+  /* 1474 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(207), R(0),
+                B(Ldar), R(0),
+  /* 1483 S> */ B(Nop),
+  /* 1488 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(209), R(0),
+                B(Ldar), R(0),
+  /* 1497 S> */ B(Nop),
+  /* 1502 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(211), R(0),
+                B(Ldar), R(0),
+  /* 1511 S> */ B(Nop),
+  /* 1516 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(213), R(0),
+                B(Ldar), R(0),
+  /* 1525 S> */ B(Nop),
+  /* 1530 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(215), R(0),
+                B(Ldar), R(0),
+  /* 1539 S> */ B(Nop),
+  /* 1544 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(217), R(0),
+                B(Ldar), R(0),
+  /* 1553 S> */ B(Nop),
+  /* 1558 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(219), R(0),
+                B(Ldar), R(0),
+  /* 1567 S> */ B(Nop),
+  /* 1572 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(221), R(0),
+                B(Ldar), R(0),
+  /* 1581 S> */ B(Nop),
+  /* 1586 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(223), R(0),
+                B(Ldar), R(0),
+  /* 1595 S> */ B(Nop),
+  /* 1600 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(225), R(0),
+                B(Ldar), R(0),
+  /* 1609 S> */ B(Nop),
+  /* 1614 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(227), R(0),
+                B(Ldar), R(0),
+  /* 1623 S> */ B(Nop),
+  /* 1628 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(229), R(0),
+                B(Ldar), R(0),
+  /* 1637 S> */ B(Nop),
+  /* 1642 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(231), R(0),
+                B(Ldar), R(0),
+  /* 1651 S> */ B(Nop),
+  /* 1656 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(233), R(0),
+                B(Ldar), R(0),
+  /* 1665 S> */ B(Nop),
+  /* 1670 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(235), R(0),
+                B(Ldar), R(0),
+  /* 1679 S> */ B(Nop),
+  /* 1684 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(237), R(0),
+                B(Ldar), R(0),
+  /* 1693 S> */ B(Nop),
+  /* 1698 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(239), R(0),
+                B(Ldar), R(0),
+  /* 1707 S> */ B(Nop),
+  /* 1712 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(241), R(0),
+                B(Ldar), R(0),
+  /* 1721 S> */ B(Nop),
+  /* 1726 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(243), R(0),
+                B(Ldar), R(0),
+  /* 1735 S> */ B(Nop),
+  /* 1740 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(245), R(0),
+                B(Ldar), R(0),
+  /* 1749 S> */ B(Nop),
+  /* 1754 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(247), R(0),
+                B(Ldar), R(0),
+  /* 1763 S> */ B(Nop),
+  /* 1768 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(249), R(0),
+                B(Ldar), R(0),
+  /* 1777 S> */ B(Nop),
+  /* 1782 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(251), R(0),
+                B(Ldar), R(0),
+  /* 1791 S> */ B(Nop),
+  /* 1796 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(253), R(0),
+                B(Ldar), R(0),
+  /* 1805 S> */ B(Nop),
+  /* 1810 E> */ B(LdrNamedProperty), R(arg0), U8(0), U8(255), R(0),
+                B(Ldar), R(0),
+  /* 1819 S> */ B(Nop),
+  /* 1827 E> */ B(Wide), B(LdaNamedProperty), R16(arg0), U16(0), U16(257),
+  /* 1834 S> */ B(Return),
 ]
 constant pool: [
   "name",
@@ -918,656 +780,398 @@
   }
   f({name : \"test\"}, \"name\")
 "
-frame size: 2
+frame size: 1
 parameter count: 3
-bytecode array length: 1422
+bytecode array length: 1034
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(1),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(3),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(5),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(7),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(9),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(11),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(13),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(15),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(17),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(19),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(21),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(23),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(25),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(27),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(29),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(31),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(33),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(35),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(37),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(39),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(41),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(43),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(45),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(47),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(49),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(51),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(53),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(55),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(57),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(59),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(61),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(63),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(65),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(67),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(69),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(71),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(73),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(75),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(77),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(79),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(81),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(83),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(85),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(87),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(89),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(91),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(93),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(95),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(97),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(99),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(101),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(103),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(105),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(107),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(109),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(111),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(113),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(115),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(117),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(119),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(121),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(123),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(125),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(127),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(129),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(131),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(133),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(135),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(137),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(139),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(141),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(143),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(145),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(147),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(149),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(151),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(153),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(155),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(157),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(159),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(161),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(163),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(165),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(167),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(169),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(171),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(173),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(175),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(177),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(179),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(181),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(183),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(185),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(187),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(189),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(191),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(193),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(195),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(197),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(199),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(201),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(203),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(205),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(207),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(209),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(211),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(213),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(215),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(217),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(219),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(221),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(223),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(225),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(227),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(229),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(231),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(233),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(235),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(237),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(239),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(241),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(243),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(245),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(247),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(249),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(251),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(253),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(KeyedLoadIC), R(1), U8(255),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(Ldar), R(arg1),
-  B(Wide), B(KeyedLoadIC), R16(1), U16(257),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   30 S> */ B(Ldar), R(arg1),
+  /*   36 E> */ B(LdrKeyedProperty), R(arg0), U8(1), R(0),
+                B(Ldar), R(0),
+  /*   42 S> */ B(Ldar), R(arg1),
+  /*   48 E> */ B(LdrKeyedProperty), R(arg0), U8(3), R(0),
+                B(Ldar), R(0),
+  /*   54 S> */ B(Ldar), R(arg1),
+  /*   60 E> */ B(LdrKeyedProperty), R(arg0), U8(5), R(0),
+                B(Ldar), R(0),
+  /*   66 S> */ B(Ldar), R(arg1),
+  /*   72 E> */ B(LdrKeyedProperty), R(arg0), U8(7), R(0),
+                B(Ldar), R(0),
+  /*   78 S> */ B(Ldar), R(arg1),
+  /*   84 E> */ B(LdrKeyedProperty), R(arg0), U8(9), R(0),
+                B(Ldar), R(0),
+  /*   90 S> */ B(Ldar), R(arg1),
+  /*   96 E> */ B(LdrKeyedProperty), R(arg0), U8(11), R(0),
+                B(Ldar), R(0),
+  /*  102 S> */ B(Ldar), R(arg1),
+  /*  108 E> */ B(LdrKeyedProperty), R(arg0), U8(13), R(0),
+                B(Ldar), R(0),
+  /*  114 S> */ B(Ldar), R(arg1),
+  /*  120 E> */ B(LdrKeyedProperty), R(arg0), U8(15), R(0),
+                B(Ldar), R(0),
+  /*  126 S> */ B(Ldar), R(arg1),
+  /*  132 E> */ B(LdrKeyedProperty), R(arg0), U8(17), R(0),
+                B(Ldar), R(0),
+  /*  138 S> */ B(Ldar), R(arg1),
+  /*  144 E> */ B(LdrKeyedProperty), R(arg0), U8(19), R(0),
+                B(Ldar), R(0),
+  /*  150 S> */ B(Ldar), R(arg1),
+  /*  156 E> */ B(LdrKeyedProperty), R(arg0), U8(21), R(0),
+                B(Ldar), R(0),
+  /*  162 S> */ B(Ldar), R(arg1),
+  /*  168 E> */ B(LdrKeyedProperty), R(arg0), U8(23), R(0),
+                B(Ldar), R(0),
+  /*  174 S> */ B(Ldar), R(arg1),
+  /*  180 E> */ B(LdrKeyedProperty), R(arg0), U8(25), R(0),
+                B(Ldar), R(0),
+  /*  186 S> */ B(Ldar), R(arg1),
+  /*  192 E> */ B(LdrKeyedProperty), R(arg0), U8(27), R(0),
+                B(Ldar), R(0),
+  /*  198 S> */ B(Ldar), R(arg1),
+  /*  204 E> */ B(LdrKeyedProperty), R(arg0), U8(29), R(0),
+                B(Ldar), R(0),
+  /*  210 S> */ B(Ldar), R(arg1),
+  /*  216 E> */ B(LdrKeyedProperty), R(arg0), U8(31), R(0),
+                B(Ldar), R(0),
+  /*  222 S> */ B(Ldar), R(arg1),
+  /*  228 E> */ B(LdrKeyedProperty), R(arg0), U8(33), R(0),
+                B(Ldar), R(0),
+  /*  234 S> */ B(Ldar), R(arg1),
+  /*  240 E> */ B(LdrKeyedProperty), R(arg0), U8(35), R(0),
+                B(Ldar), R(0),
+  /*  246 S> */ B(Ldar), R(arg1),
+  /*  252 E> */ B(LdrKeyedProperty), R(arg0), U8(37), R(0),
+                B(Ldar), R(0),
+  /*  258 S> */ B(Ldar), R(arg1),
+  /*  264 E> */ B(LdrKeyedProperty), R(arg0), U8(39), R(0),
+                B(Ldar), R(0),
+  /*  270 S> */ B(Ldar), R(arg1),
+  /*  276 E> */ B(LdrKeyedProperty), R(arg0), U8(41), R(0),
+                B(Ldar), R(0),
+  /*  282 S> */ B(Ldar), R(arg1),
+  /*  288 E> */ B(LdrKeyedProperty), R(arg0), U8(43), R(0),
+                B(Ldar), R(0),
+  /*  294 S> */ B(Ldar), R(arg1),
+  /*  300 E> */ B(LdrKeyedProperty), R(arg0), U8(45), R(0),
+                B(Ldar), R(0),
+  /*  306 S> */ B(Ldar), R(arg1),
+  /*  312 E> */ B(LdrKeyedProperty), R(arg0), U8(47), R(0),
+                B(Ldar), R(0),
+  /*  318 S> */ B(Ldar), R(arg1),
+  /*  324 E> */ B(LdrKeyedProperty), R(arg0), U8(49), R(0),
+                B(Ldar), R(0),
+  /*  330 S> */ B(Ldar), R(arg1),
+  /*  336 E> */ B(LdrKeyedProperty), R(arg0), U8(51), R(0),
+                B(Ldar), R(0),
+  /*  342 S> */ B(Ldar), R(arg1),
+  /*  348 E> */ B(LdrKeyedProperty), R(arg0), U8(53), R(0),
+                B(Ldar), R(0),
+  /*  354 S> */ B(Ldar), R(arg1),
+  /*  360 E> */ B(LdrKeyedProperty), R(arg0), U8(55), R(0),
+                B(Ldar), R(0),
+  /*  366 S> */ B(Ldar), R(arg1),
+  /*  372 E> */ B(LdrKeyedProperty), R(arg0), U8(57), R(0),
+                B(Ldar), R(0),
+  /*  378 S> */ B(Ldar), R(arg1),
+  /*  384 E> */ B(LdrKeyedProperty), R(arg0), U8(59), R(0),
+                B(Ldar), R(0),
+  /*  390 S> */ B(Ldar), R(arg1),
+  /*  396 E> */ B(LdrKeyedProperty), R(arg0), U8(61), R(0),
+                B(Ldar), R(0),
+  /*  402 S> */ B(Ldar), R(arg1),
+  /*  408 E> */ B(LdrKeyedProperty), R(arg0), U8(63), R(0),
+                B(Ldar), R(0),
+  /*  414 S> */ B(Ldar), R(arg1),
+  /*  420 E> */ B(LdrKeyedProperty), R(arg0), U8(65), R(0),
+                B(Ldar), R(0),
+  /*  426 S> */ B(Ldar), R(arg1),
+  /*  432 E> */ B(LdrKeyedProperty), R(arg0), U8(67), R(0),
+                B(Ldar), R(0),
+  /*  438 S> */ B(Ldar), R(arg1),
+  /*  444 E> */ B(LdrKeyedProperty), R(arg0), U8(69), R(0),
+                B(Ldar), R(0),
+  /*  450 S> */ B(Ldar), R(arg1),
+  /*  456 E> */ B(LdrKeyedProperty), R(arg0), U8(71), R(0),
+                B(Ldar), R(0),
+  /*  462 S> */ B(Ldar), R(arg1),
+  /*  468 E> */ B(LdrKeyedProperty), R(arg0), U8(73), R(0),
+                B(Ldar), R(0),
+  /*  474 S> */ B(Ldar), R(arg1),
+  /*  480 E> */ B(LdrKeyedProperty), R(arg0), U8(75), R(0),
+                B(Ldar), R(0),
+  /*  486 S> */ B(Ldar), R(arg1),
+  /*  492 E> */ B(LdrKeyedProperty), R(arg0), U8(77), R(0),
+                B(Ldar), R(0),
+  /*  498 S> */ B(Ldar), R(arg1),
+  /*  504 E> */ B(LdrKeyedProperty), R(arg0), U8(79), R(0),
+                B(Ldar), R(0),
+  /*  510 S> */ B(Ldar), R(arg1),
+  /*  516 E> */ B(LdrKeyedProperty), R(arg0), U8(81), R(0),
+                B(Ldar), R(0),
+  /*  522 S> */ B(Ldar), R(arg1),
+  /*  528 E> */ B(LdrKeyedProperty), R(arg0), U8(83), R(0),
+                B(Ldar), R(0),
+  /*  534 S> */ B(Ldar), R(arg1),
+  /*  540 E> */ B(LdrKeyedProperty), R(arg0), U8(85), R(0),
+                B(Ldar), R(0),
+  /*  546 S> */ B(Ldar), R(arg1),
+  /*  552 E> */ B(LdrKeyedProperty), R(arg0), U8(87), R(0),
+                B(Ldar), R(0),
+  /*  558 S> */ B(Ldar), R(arg1),
+  /*  564 E> */ B(LdrKeyedProperty), R(arg0), U8(89), R(0),
+                B(Ldar), R(0),
+  /*  570 S> */ B(Ldar), R(arg1),
+  /*  576 E> */ B(LdrKeyedProperty), R(arg0), U8(91), R(0),
+                B(Ldar), R(0),
+  /*  582 S> */ B(Ldar), R(arg1),
+  /*  588 E> */ B(LdrKeyedProperty), R(arg0), U8(93), R(0),
+                B(Ldar), R(0),
+  /*  594 S> */ B(Ldar), R(arg1),
+  /*  600 E> */ B(LdrKeyedProperty), R(arg0), U8(95), R(0),
+                B(Ldar), R(0),
+  /*  606 S> */ B(Ldar), R(arg1),
+  /*  612 E> */ B(LdrKeyedProperty), R(arg0), U8(97), R(0),
+                B(Ldar), R(0),
+  /*  618 S> */ B(Ldar), R(arg1),
+  /*  624 E> */ B(LdrKeyedProperty), R(arg0), U8(99), R(0),
+                B(Ldar), R(0),
+  /*  630 S> */ B(Ldar), R(arg1),
+  /*  636 E> */ B(LdrKeyedProperty), R(arg0), U8(101), R(0),
+                B(Ldar), R(0),
+  /*  642 S> */ B(Ldar), R(arg1),
+  /*  648 E> */ B(LdrKeyedProperty), R(arg0), U8(103), R(0),
+                B(Ldar), R(0),
+  /*  654 S> */ B(Ldar), R(arg1),
+  /*  660 E> */ B(LdrKeyedProperty), R(arg0), U8(105), R(0),
+                B(Ldar), R(0),
+  /*  666 S> */ B(Ldar), R(arg1),
+  /*  672 E> */ B(LdrKeyedProperty), R(arg0), U8(107), R(0),
+                B(Ldar), R(0),
+  /*  678 S> */ B(Ldar), R(arg1),
+  /*  684 E> */ B(LdrKeyedProperty), R(arg0), U8(109), R(0),
+                B(Ldar), R(0),
+  /*  690 S> */ B(Ldar), R(arg1),
+  /*  696 E> */ B(LdrKeyedProperty), R(arg0), U8(111), R(0),
+                B(Ldar), R(0),
+  /*  702 S> */ B(Ldar), R(arg1),
+  /*  708 E> */ B(LdrKeyedProperty), R(arg0), U8(113), R(0),
+                B(Ldar), R(0),
+  /*  714 S> */ B(Ldar), R(arg1),
+  /*  720 E> */ B(LdrKeyedProperty), R(arg0), U8(115), R(0),
+                B(Ldar), R(0),
+  /*  726 S> */ B(Ldar), R(arg1),
+  /*  732 E> */ B(LdrKeyedProperty), R(arg0), U8(117), R(0),
+                B(Ldar), R(0),
+  /*  738 S> */ B(Ldar), R(arg1),
+  /*  744 E> */ B(LdrKeyedProperty), R(arg0), U8(119), R(0),
+                B(Ldar), R(0),
+  /*  750 S> */ B(Ldar), R(arg1),
+  /*  756 E> */ B(LdrKeyedProperty), R(arg0), U8(121), R(0),
+                B(Ldar), R(0),
+  /*  762 S> */ B(Ldar), R(arg1),
+  /*  768 E> */ B(LdrKeyedProperty), R(arg0), U8(123), R(0),
+                B(Ldar), R(0),
+  /*  774 S> */ B(Ldar), R(arg1),
+  /*  780 E> */ B(LdrKeyedProperty), R(arg0), U8(125), R(0),
+                B(Ldar), R(0),
+  /*  786 S> */ B(Ldar), R(arg1),
+  /*  792 E> */ B(LdrKeyedProperty), R(arg0), U8(127), R(0),
+                B(Ldar), R(0),
+  /*  798 S> */ B(Ldar), R(arg1),
+  /*  804 E> */ B(LdrKeyedProperty), R(arg0), U8(129), R(0),
+                B(Ldar), R(0),
+  /*  810 S> */ B(Ldar), R(arg1),
+  /*  816 E> */ B(LdrKeyedProperty), R(arg0), U8(131), R(0),
+                B(Ldar), R(0),
+  /*  822 S> */ B(Ldar), R(arg1),
+  /*  828 E> */ B(LdrKeyedProperty), R(arg0), U8(133), R(0),
+                B(Ldar), R(0),
+  /*  834 S> */ B(Ldar), R(arg1),
+  /*  840 E> */ B(LdrKeyedProperty), R(arg0), U8(135), R(0),
+                B(Ldar), R(0),
+  /*  846 S> */ B(Ldar), R(arg1),
+  /*  852 E> */ B(LdrKeyedProperty), R(arg0), U8(137), R(0),
+                B(Ldar), R(0),
+  /*  858 S> */ B(Ldar), R(arg1),
+  /*  864 E> */ B(LdrKeyedProperty), R(arg0), U8(139), R(0),
+                B(Ldar), R(0),
+  /*  870 S> */ B(Ldar), R(arg1),
+  /*  876 E> */ B(LdrKeyedProperty), R(arg0), U8(141), R(0),
+                B(Ldar), R(0),
+  /*  882 S> */ B(Ldar), R(arg1),
+  /*  888 E> */ B(LdrKeyedProperty), R(arg0), U8(143), R(0),
+                B(Ldar), R(0),
+  /*  894 S> */ B(Ldar), R(arg1),
+  /*  900 E> */ B(LdrKeyedProperty), R(arg0), U8(145), R(0),
+                B(Ldar), R(0),
+  /*  906 S> */ B(Ldar), R(arg1),
+  /*  912 E> */ B(LdrKeyedProperty), R(arg0), U8(147), R(0),
+                B(Ldar), R(0),
+  /*  918 S> */ B(Ldar), R(arg1),
+  /*  924 E> */ B(LdrKeyedProperty), R(arg0), U8(149), R(0),
+                B(Ldar), R(0),
+  /*  930 S> */ B(Ldar), R(arg1),
+  /*  936 E> */ B(LdrKeyedProperty), R(arg0), U8(151), R(0),
+                B(Ldar), R(0),
+  /*  942 S> */ B(Ldar), R(arg1),
+  /*  948 E> */ B(LdrKeyedProperty), R(arg0), U8(153), R(0),
+                B(Ldar), R(0),
+  /*  954 S> */ B(Ldar), R(arg1),
+  /*  960 E> */ B(LdrKeyedProperty), R(arg0), U8(155), R(0),
+                B(Ldar), R(0),
+  /*  966 S> */ B(Ldar), R(arg1),
+  /*  972 E> */ B(LdrKeyedProperty), R(arg0), U8(157), R(0),
+                B(Ldar), R(0),
+  /*  978 S> */ B(Ldar), R(arg1),
+  /*  984 E> */ B(LdrKeyedProperty), R(arg0), U8(159), R(0),
+                B(Ldar), R(0),
+  /*  990 S> */ B(Ldar), R(arg1),
+  /*  996 E> */ B(LdrKeyedProperty), R(arg0), U8(161), R(0),
+                B(Ldar), R(0),
+  /* 1002 S> */ B(Ldar), R(arg1),
+  /* 1008 E> */ B(LdrKeyedProperty), R(arg0), U8(163), R(0),
+                B(Ldar), R(0),
+  /* 1014 S> */ B(Ldar), R(arg1),
+  /* 1020 E> */ B(LdrKeyedProperty), R(arg0), U8(165), R(0),
+                B(Ldar), R(0),
+  /* 1026 S> */ B(Ldar), R(arg1),
+  /* 1032 E> */ B(LdrKeyedProperty), R(arg0), U8(167), R(0),
+                B(Ldar), R(0),
+  /* 1038 S> */ B(Ldar), R(arg1),
+  /* 1044 E> */ B(LdrKeyedProperty), R(arg0), U8(169), R(0),
+                B(Ldar), R(0),
+  /* 1050 S> */ B(Ldar), R(arg1),
+  /* 1056 E> */ B(LdrKeyedProperty), R(arg0), U8(171), R(0),
+                B(Ldar), R(0),
+  /* 1062 S> */ B(Ldar), R(arg1),
+  /* 1068 E> */ B(LdrKeyedProperty), R(arg0), U8(173), R(0),
+                B(Ldar), R(0),
+  /* 1074 S> */ B(Ldar), R(arg1),
+  /* 1080 E> */ B(LdrKeyedProperty), R(arg0), U8(175), R(0),
+                B(Ldar), R(0),
+  /* 1086 S> */ B(Ldar), R(arg1),
+  /* 1092 E> */ B(LdrKeyedProperty), R(arg0), U8(177), R(0),
+                B(Ldar), R(0),
+  /* 1098 S> */ B(Ldar), R(arg1),
+  /* 1104 E> */ B(LdrKeyedProperty), R(arg0), U8(179), R(0),
+                B(Ldar), R(0),
+  /* 1110 S> */ B(Ldar), R(arg1),
+  /* 1116 E> */ B(LdrKeyedProperty), R(arg0), U8(181), R(0),
+                B(Ldar), R(0),
+  /* 1122 S> */ B(Ldar), R(arg1),
+  /* 1128 E> */ B(LdrKeyedProperty), R(arg0), U8(183), R(0),
+                B(Ldar), R(0),
+  /* 1134 S> */ B(Ldar), R(arg1),
+  /* 1140 E> */ B(LdrKeyedProperty), R(arg0), U8(185), R(0),
+                B(Ldar), R(0),
+  /* 1146 S> */ B(Ldar), R(arg1),
+  /* 1152 E> */ B(LdrKeyedProperty), R(arg0), U8(187), R(0),
+                B(Ldar), R(0),
+  /* 1158 S> */ B(Ldar), R(arg1),
+  /* 1164 E> */ B(LdrKeyedProperty), R(arg0), U8(189), R(0),
+                B(Ldar), R(0),
+  /* 1170 S> */ B(Ldar), R(arg1),
+  /* 1176 E> */ B(LdrKeyedProperty), R(arg0), U8(191), R(0),
+                B(Ldar), R(0),
+  /* 1182 S> */ B(Ldar), R(arg1),
+  /* 1188 E> */ B(LdrKeyedProperty), R(arg0), U8(193), R(0),
+                B(Ldar), R(0),
+  /* 1194 S> */ B(Ldar), R(arg1),
+  /* 1200 E> */ B(LdrKeyedProperty), R(arg0), U8(195), R(0),
+                B(Ldar), R(0),
+  /* 1206 S> */ B(Ldar), R(arg1),
+  /* 1212 E> */ B(LdrKeyedProperty), R(arg0), U8(197), R(0),
+                B(Ldar), R(0),
+  /* 1218 S> */ B(Ldar), R(arg1),
+  /* 1224 E> */ B(LdrKeyedProperty), R(arg0), U8(199), R(0),
+                B(Ldar), R(0),
+  /* 1230 S> */ B(Ldar), R(arg1),
+  /* 1236 E> */ B(LdrKeyedProperty), R(arg0), U8(201), R(0),
+                B(Ldar), R(0),
+  /* 1242 S> */ B(Ldar), R(arg1),
+  /* 1248 E> */ B(LdrKeyedProperty), R(arg0), U8(203), R(0),
+                B(Ldar), R(0),
+  /* 1254 S> */ B(Ldar), R(arg1),
+  /* 1260 E> */ B(LdrKeyedProperty), R(arg0), U8(205), R(0),
+                B(Ldar), R(0),
+  /* 1266 S> */ B(Ldar), R(arg1),
+  /* 1272 E> */ B(LdrKeyedProperty), R(arg0), U8(207), R(0),
+                B(Ldar), R(0),
+  /* 1278 S> */ B(Ldar), R(arg1),
+  /* 1284 E> */ B(LdrKeyedProperty), R(arg0), U8(209), R(0),
+                B(Ldar), R(0),
+  /* 1290 S> */ B(Ldar), R(arg1),
+  /* 1296 E> */ B(LdrKeyedProperty), R(arg0), U8(211), R(0),
+                B(Ldar), R(0),
+  /* 1302 S> */ B(Ldar), R(arg1),
+  /* 1308 E> */ B(LdrKeyedProperty), R(arg0), U8(213), R(0),
+                B(Ldar), R(0),
+  /* 1314 S> */ B(Ldar), R(arg1),
+  /* 1320 E> */ B(LdrKeyedProperty), R(arg0), U8(215), R(0),
+                B(Ldar), R(0),
+  /* 1326 S> */ B(Ldar), R(arg1),
+  /* 1332 E> */ B(LdrKeyedProperty), R(arg0), U8(217), R(0),
+                B(Ldar), R(0),
+  /* 1338 S> */ B(Ldar), R(arg1),
+  /* 1344 E> */ B(LdrKeyedProperty), R(arg0), U8(219), R(0),
+                B(Ldar), R(0),
+  /* 1350 S> */ B(Ldar), R(arg1),
+  /* 1356 E> */ B(LdrKeyedProperty), R(arg0), U8(221), R(0),
+                B(Ldar), R(0),
+  /* 1362 S> */ B(Ldar), R(arg1),
+  /* 1368 E> */ B(LdrKeyedProperty), R(arg0), U8(223), R(0),
+                B(Ldar), R(0),
+  /* 1374 S> */ B(Ldar), R(arg1),
+  /* 1380 E> */ B(LdrKeyedProperty), R(arg0), U8(225), R(0),
+                B(Ldar), R(0),
+  /* 1386 S> */ B(Ldar), R(arg1),
+  /* 1392 E> */ B(LdrKeyedProperty), R(arg0), U8(227), R(0),
+                B(Ldar), R(0),
+  /* 1398 S> */ B(Ldar), R(arg1),
+  /* 1404 E> */ B(LdrKeyedProperty), R(arg0), U8(229), R(0),
+                B(Ldar), R(0),
+  /* 1410 S> */ B(Ldar), R(arg1),
+  /* 1416 E> */ B(LdrKeyedProperty), R(arg0), U8(231), R(0),
+                B(Ldar), R(0),
+  /* 1422 S> */ B(Ldar), R(arg1),
+  /* 1428 E> */ B(LdrKeyedProperty), R(arg0), U8(233), R(0),
+                B(Ldar), R(0),
+  /* 1434 S> */ B(Ldar), R(arg1),
+  /* 1440 E> */ B(LdrKeyedProperty), R(arg0), U8(235), R(0),
+                B(Ldar), R(0),
+  /* 1446 S> */ B(Ldar), R(arg1),
+  /* 1452 E> */ B(LdrKeyedProperty), R(arg0), U8(237), R(0),
+                B(Ldar), R(0),
+  /* 1458 S> */ B(Ldar), R(arg1),
+  /* 1464 E> */ B(LdrKeyedProperty), R(arg0), U8(239), R(0),
+                B(Ldar), R(0),
+  /* 1470 S> */ B(Ldar), R(arg1),
+  /* 1476 E> */ B(LdrKeyedProperty), R(arg0), U8(241), R(0),
+                B(Ldar), R(0),
+  /* 1482 S> */ B(Ldar), R(arg1),
+  /* 1488 E> */ B(LdrKeyedProperty), R(arg0), U8(243), R(0),
+                B(Ldar), R(0),
+  /* 1494 S> */ B(Ldar), R(arg1),
+  /* 1500 E> */ B(LdrKeyedProperty), R(arg0), U8(245), R(0),
+                B(Ldar), R(0),
+  /* 1506 S> */ B(Ldar), R(arg1),
+  /* 1512 E> */ B(LdrKeyedProperty), R(arg0), U8(247), R(0),
+                B(Ldar), R(0),
+  /* 1518 S> */ B(Ldar), R(arg1),
+  /* 1524 E> */ B(LdrKeyedProperty), R(arg0), U8(249), R(0),
+                B(Ldar), R(0),
+  /* 1530 S> */ B(Ldar), R(arg1),
+  /* 1536 E> */ B(LdrKeyedProperty), R(arg0), U8(251), R(0),
+                B(Ldar), R(0),
+  /* 1542 S> */ B(Ldar), R(arg1),
+  /* 1548 E> */ B(LdrKeyedProperty), R(arg0), U8(253), R(0),
+                B(Ldar), R(0),
+  /* 1554 S> */ B(Ldar), R(arg1),
+  /* 1560 E> */ B(LdrKeyedProperty), R(arg0), U8(255), R(0),
+                B(Ldar), R(0),
+  /* 1566 S> */ B(Ldar), R(arg1),
+  /* 1575 E> */ B(Wide), B(LdaKeyedProperty), R16(arg0), U16(257),
+  /* 1579 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/PropertyStores.golden b/test/cctest/interpreter/bytecode_expectations/PropertyStores.golden
index 9e67a90..7f456cf 100644
--- a/test/cctest/interpreter/bytecode_expectations/PropertyStores.golden
+++ b/test/cctest/interpreter/bytecode_expectations/PropertyStores.golden
@@ -13,17 +13,15 @@
   function f(a) { a.name = \"val\"; }
   f({name : \"test\"})
 "
-frame size: 1
+frame size: 0
 parameter count: 2
-bytecode array length: 13
+bytecode array length: 9
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaConstant), U8(0),
-  B(StoreICSloppy), R(0), U8(1), U8(1),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   16 S> */ B(LdaConstant), U8(0),
+  /*   23 E> */ B(StaNamedPropertySloppy), R(arg0), U8(1), U8(1),
+                B(LdaUndefined),
+  /*   32 S> */ B(Return),
 ]
 constant pool: [
   "val",
@@ -37,17 +35,15 @@
   function f(a) { a[\"key\"] = \"val\"; }
   f({key : \"test\"})
 "
-frame size: 1
+frame size: 0
 parameter count: 2
-bytecode array length: 13
+bytecode array length: 9
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaConstant), U8(0),
-  B(StoreICSloppy), R(0), U8(1), U8(1),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   16 S> */ B(LdaConstant), U8(0),
+  /*   25 E> */ B(StaNamedPropertySloppy), R(arg0), U8(1), U8(1),
+                B(LdaUndefined),
+  /*   34 S> */ B(Return),
 ]
 constant pool: [
   "val",
@@ -63,17 +59,15 @@
 "
 frame size: 2
 parameter count: 2
-bytecode array length: 17
+bytecode array length: 13
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(100),
-  B(Star), R(1),
-  B(LdaConstant), U8(0),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(1),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   16 S> */ B(LdaSmi), U8(100),
+                B(Star), R(1),
+                B(LdaConstant), U8(0),
+  /*   23 E> */ B(StaKeyedPropertySloppy), R(arg0), R(1), U8(1),
+                B(LdaUndefined),
+  /*   32 S> */ B(Return),
 ]
 constant pool: [
   "val",
@@ -86,19 +80,15 @@
   function f(a, b) { a[b] = \"val\"; }
   f({arg : \"test\"}, \"arg\")
 "
-frame size: 2
+frame size: 0
 parameter count: 3
-bytecode array length: 17
+bytecode array length: 9
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaConstant), U8(0),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(1),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   19 S> */ B(LdaConstant), U8(0),
+  /*   24 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(1),
+                B(LdaUndefined),
+  /*   33 S> */ B(Return),
 ]
 constant pool: [
   "val",
@@ -111,20 +101,16 @@
   function f(a) { a.name = a[-124]; }
   f({\"-124\" : \"test\", name : 123 })
 "
-frame size: 2
+frame size: 0
 parameter count: 2
-bytecode array length: 20
+bytecode array length: 12
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg0),
-  B(Star), R(1),
-  B(LdaSmi), U8(-124),
-  B(KeyedLoadIC), R(1), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(3),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   16 S> */ B(LdaSmi), U8(-124),
+  /*   26 E> */ B(LdaKeyedProperty), R(arg0), U8(1),
+  /*   23 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(3),
+                B(LdaUndefined),
+  /*   34 S> */ B(Return),
 ]
 constant pool: [
   "name",
@@ -137,17 +123,15 @@
   function f(a) { \"use strict\"; a.name = \"val\"; }
   f({name : \"test\"})
 "
-frame size: 1
+frame size: 0
 parameter count: 2
-bytecode array length: 13
+bytecode array length: 9
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaConstant), U8(0),
-  B(StoreICStrict), R(0), U8(1), U8(1),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   30 S> */ B(LdaConstant), U8(0),
+  /*   37 E> */ B(StaNamedPropertyStrict), R(arg0), U8(1), U8(1),
+                B(LdaUndefined),
+  /*   46 S> */ B(Return),
 ]
 constant pool: [
   "val",
@@ -161,19 +145,15 @@
   function f(a, b) { \"use strict\"; a[b] = \"val\"; }
   f({arg : \"test\"}, \"arg\")
 "
-frame size: 2
+frame size: 0
 parameter count: 3
-bytecode array length: 17
+bytecode array length: 9
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaConstant), U8(0),
-  B(KeyedStoreICStrict), R(0), R(1), U8(1),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   33 S> */ B(LdaConstant), U8(0),
+  /*   38 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(1),
+                B(LdaUndefined),
+  /*   47 S> */ B(Return),
 ]
 constant pool: [
   "val",
@@ -316,529 +296,271 @@
   }
   f({name : \"test\"})
 "
-frame size: 1
+frame size: 0
 parameter count: 2
-bytecode array length: 1297
+bytecode array length: 781
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(1),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(3),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(5),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(7),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(9),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(11),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(13),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(15),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(17),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(19),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(21),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(23),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(25),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(27),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(29),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(31),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(33),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(35),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(37),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(39),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(41),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(43),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(45),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(47),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(49),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(51),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(53),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(55),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(57),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(59),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(61),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(63),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(65),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(67),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(69),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(71),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(73),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(75),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(77),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(79),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(81),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(83),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(85),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(87),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(89),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(91),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(93),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(95),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(97),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(99),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(101),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(103),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(105),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(107),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(109),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(111),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(113),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(115),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(117),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(119),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(121),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(123),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(125),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(127),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(129),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(131),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(133),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(135),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(137),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(139),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(141),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(143),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(145),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(147),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(149),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(151),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(153),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(155),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(157),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(159),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(161),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(163),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(165),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(167),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(169),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(171),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(173),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(175),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(177),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(179),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(181),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(183),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(185),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(187),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(189),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(191),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(193),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(195),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(197),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(199),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(201),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(203),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(205),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(207),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(209),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(211),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(213),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(215),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(217),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(219),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(221),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(223),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(225),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(227),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(229),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(231),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(233),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(235),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(237),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(239),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(241),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(243),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(245),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(247),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(249),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(251),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(253),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICSloppy), R(0), U8(0), U8(255),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(2),
-  B(Wide), B(StoreICSloppy), R16(0), U16(0), U16(257),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   18 S> */ B(LdaSmi), U8(1),
+  /*   25 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(1),
+  /*   32 S> */ B(LdaSmi), U8(1),
+  /*   39 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(3),
+  /*   46 S> */ B(LdaSmi), U8(1),
+  /*   53 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(5),
+  /*   60 S> */ B(LdaSmi), U8(1),
+  /*   67 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(7),
+  /*   74 S> */ B(LdaSmi), U8(1),
+  /*   81 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(9),
+  /*   88 S> */ B(LdaSmi), U8(1),
+  /*   95 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(11),
+  /*  102 S> */ B(LdaSmi), U8(1),
+  /*  109 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(13),
+  /*  116 S> */ B(LdaSmi), U8(1),
+  /*  123 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(15),
+  /*  130 S> */ B(LdaSmi), U8(1),
+  /*  137 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(17),
+  /*  144 S> */ B(LdaSmi), U8(1),
+  /*  151 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(19),
+  /*  158 S> */ B(LdaSmi), U8(1),
+  /*  165 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(21),
+  /*  172 S> */ B(LdaSmi), U8(1),
+  /*  179 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(23),
+  /*  186 S> */ B(LdaSmi), U8(1),
+  /*  193 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(25),
+  /*  200 S> */ B(LdaSmi), U8(1),
+  /*  207 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(27),
+  /*  214 S> */ B(LdaSmi), U8(1),
+  /*  221 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(29),
+  /*  228 S> */ B(LdaSmi), U8(1),
+  /*  235 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(31),
+  /*  242 S> */ B(LdaSmi), U8(1),
+  /*  249 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(33),
+  /*  256 S> */ B(LdaSmi), U8(1),
+  /*  263 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(35),
+  /*  270 S> */ B(LdaSmi), U8(1),
+  /*  277 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(37),
+  /*  284 S> */ B(LdaSmi), U8(1),
+  /*  291 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(39),
+  /*  298 S> */ B(LdaSmi), U8(1),
+  /*  305 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(41),
+  /*  312 S> */ B(LdaSmi), U8(1),
+  /*  319 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(43),
+  /*  326 S> */ B(LdaSmi), U8(1),
+  /*  333 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(45),
+  /*  340 S> */ B(LdaSmi), U8(1),
+  /*  347 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(47),
+  /*  354 S> */ B(LdaSmi), U8(1),
+  /*  361 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(49),
+  /*  368 S> */ B(LdaSmi), U8(1),
+  /*  375 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(51),
+  /*  382 S> */ B(LdaSmi), U8(1),
+  /*  389 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(53),
+  /*  396 S> */ B(LdaSmi), U8(1),
+  /*  403 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(55),
+  /*  410 S> */ B(LdaSmi), U8(1),
+  /*  417 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(57),
+  /*  424 S> */ B(LdaSmi), U8(1),
+  /*  431 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(59),
+  /*  438 S> */ B(LdaSmi), U8(1),
+  /*  445 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(61),
+  /*  452 S> */ B(LdaSmi), U8(1),
+  /*  459 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(63),
+  /*  466 S> */ B(LdaSmi), U8(1),
+  /*  473 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(65),
+  /*  480 S> */ B(LdaSmi), U8(1),
+  /*  487 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(67),
+  /*  494 S> */ B(LdaSmi), U8(1),
+  /*  501 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(69),
+  /*  508 S> */ B(LdaSmi), U8(1),
+  /*  515 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(71),
+  /*  522 S> */ B(LdaSmi), U8(1),
+  /*  529 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(73),
+  /*  536 S> */ B(LdaSmi), U8(1),
+  /*  543 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(75),
+  /*  550 S> */ B(LdaSmi), U8(1),
+  /*  557 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(77),
+  /*  564 S> */ B(LdaSmi), U8(1),
+  /*  571 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(79),
+  /*  578 S> */ B(LdaSmi), U8(1),
+  /*  585 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(81),
+  /*  592 S> */ B(LdaSmi), U8(1),
+  /*  599 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(83),
+  /*  606 S> */ B(LdaSmi), U8(1),
+  /*  613 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(85),
+  /*  620 S> */ B(LdaSmi), U8(1),
+  /*  627 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(87),
+  /*  634 S> */ B(LdaSmi), U8(1),
+  /*  641 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(89),
+  /*  648 S> */ B(LdaSmi), U8(1),
+  /*  655 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(91),
+  /*  662 S> */ B(LdaSmi), U8(1),
+  /*  669 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(93),
+  /*  676 S> */ B(LdaSmi), U8(1),
+  /*  683 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(95),
+  /*  690 S> */ B(LdaSmi), U8(1),
+  /*  697 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(97),
+  /*  704 S> */ B(LdaSmi), U8(1),
+  /*  711 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(99),
+  /*  718 S> */ B(LdaSmi), U8(1),
+  /*  725 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(101),
+  /*  732 S> */ B(LdaSmi), U8(1),
+  /*  739 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(103),
+  /*  746 S> */ B(LdaSmi), U8(1),
+  /*  753 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(105),
+  /*  760 S> */ B(LdaSmi), U8(1),
+  /*  767 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(107),
+  /*  774 S> */ B(LdaSmi), U8(1),
+  /*  781 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(109),
+  /*  788 S> */ B(LdaSmi), U8(1),
+  /*  795 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(111),
+  /*  802 S> */ B(LdaSmi), U8(1),
+  /*  809 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(113),
+  /*  816 S> */ B(LdaSmi), U8(1),
+  /*  823 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(115),
+  /*  830 S> */ B(LdaSmi), U8(1),
+  /*  837 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(117),
+  /*  844 S> */ B(LdaSmi), U8(1),
+  /*  851 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(119),
+  /*  858 S> */ B(LdaSmi), U8(1),
+  /*  865 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(121),
+  /*  872 S> */ B(LdaSmi), U8(1),
+  /*  879 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(123),
+  /*  886 S> */ B(LdaSmi), U8(1),
+  /*  893 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(125),
+  /*  900 S> */ B(LdaSmi), U8(1),
+  /*  907 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(127),
+  /*  914 S> */ B(LdaSmi), U8(1),
+  /*  921 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(129),
+  /*  928 S> */ B(LdaSmi), U8(1),
+  /*  935 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(131),
+  /*  942 S> */ B(LdaSmi), U8(1),
+  /*  949 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(133),
+  /*  956 S> */ B(LdaSmi), U8(1),
+  /*  963 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(135),
+  /*  970 S> */ B(LdaSmi), U8(1),
+  /*  977 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(137),
+  /*  984 S> */ B(LdaSmi), U8(1),
+  /*  991 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(139),
+  /*  998 S> */ B(LdaSmi), U8(1),
+  /* 1005 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(141),
+  /* 1012 S> */ B(LdaSmi), U8(1),
+  /* 1019 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(143),
+  /* 1026 S> */ B(LdaSmi), U8(1),
+  /* 1033 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(145),
+  /* 1040 S> */ B(LdaSmi), U8(1),
+  /* 1047 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(147),
+  /* 1054 S> */ B(LdaSmi), U8(1),
+  /* 1061 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(149),
+  /* 1068 S> */ B(LdaSmi), U8(1),
+  /* 1075 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(151),
+  /* 1082 S> */ B(LdaSmi), U8(1),
+  /* 1089 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(153),
+  /* 1096 S> */ B(LdaSmi), U8(1),
+  /* 1103 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(155),
+  /* 1110 S> */ B(LdaSmi), U8(1),
+  /* 1117 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(157),
+  /* 1124 S> */ B(LdaSmi), U8(1),
+  /* 1131 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(159),
+  /* 1138 S> */ B(LdaSmi), U8(1),
+  /* 1145 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(161),
+  /* 1152 S> */ B(LdaSmi), U8(1),
+  /* 1159 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(163),
+  /* 1166 S> */ B(LdaSmi), U8(1),
+  /* 1173 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(165),
+  /* 1180 S> */ B(LdaSmi), U8(1),
+  /* 1187 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(167),
+  /* 1194 S> */ B(LdaSmi), U8(1),
+  /* 1201 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(169),
+  /* 1208 S> */ B(LdaSmi), U8(1),
+  /* 1215 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(171),
+  /* 1222 S> */ B(LdaSmi), U8(1),
+  /* 1229 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(173),
+  /* 1236 S> */ B(LdaSmi), U8(1),
+  /* 1243 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(175),
+  /* 1250 S> */ B(LdaSmi), U8(1),
+  /* 1257 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(177),
+  /* 1264 S> */ B(LdaSmi), U8(1),
+  /* 1271 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(179),
+  /* 1278 S> */ B(LdaSmi), U8(1),
+  /* 1285 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(181),
+  /* 1292 S> */ B(LdaSmi), U8(1),
+  /* 1299 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(183),
+  /* 1306 S> */ B(LdaSmi), U8(1),
+  /* 1313 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(185),
+  /* 1320 S> */ B(LdaSmi), U8(1),
+  /* 1327 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(187),
+  /* 1334 S> */ B(LdaSmi), U8(1),
+  /* 1341 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(189),
+  /* 1348 S> */ B(LdaSmi), U8(1),
+  /* 1355 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(191),
+  /* 1362 S> */ B(LdaSmi), U8(1),
+  /* 1369 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(193),
+  /* 1376 S> */ B(LdaSmi), U8(1),
+  /* 1383 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(195),
+  /* 1390 S> */ B(LdaSmi), U8(1),
+  /* 1397 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(197),
+  /* 1404 S> */ B(LdaSmi), U8(1),
+  /* 1411 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(199),
+  /* 1418 S> */ B(LdaSmi), U8(1),
+  /* 1425 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(201),
+  /* 1432 S> */ B(LdaSmi), U8(1),
+  /* 1439 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(203),
+  /* 1446 S> */ B(LdaSmi), U8(1),
+  /* 1453 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(205),
+  /* 1460 S> */ B(LdaSmi), U8(1),
+  /* 1467 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(207),
+  /* 1474 S> */ B(LdaSmi), U8(1),
+  /* 1481 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(209),
+  /* 1488 S> */ B(LdaSmi), U8(1),
+  /* 1495 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(211),
+  /* 1502 S> */ B(LdaSmi), U8(1),
+  /* 1509 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(213),
+  /* 1516 S> */ B(LdaSmi), U8(1),
+  /* 1523 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(215),
+  /* 1530 S> */ B(LdaSmi), U8(1),
+  /* 1537 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(217),
+  /* 1544 S> */ B(LdaSmi), U8(1),
+  /* 1551 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(219),
+  /* 1558 S> */ B(LdaSmi), U8(1),
+  /* 1565 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(221),
+  /* 1572 S> */ B(LdaSmi), U8(1),
+  /* 1579 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(223),
+  /* 1586 S> */ B(LdaSmi), U8(1),
+  /* 1593 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(225),
+  /* 1600 S> */ B(LdaSmi), U8(1),
+  /* 1607 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(227),
+  /* 1614 S> */ B(LdaSmi), U8(1),
+  /* 1621 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(229),
+  /* 1628 S> */ B(LdaSmi), U8(1),
+  /* 1635 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(231),
+  /* 1642 S> */ B(LdaSmi), U8(1),
+  /* 1649 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(233),
+  /* 1656 S> */ B(LdaSmi), U8(1),
+  /* 1663 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(235),
+  /* 1670 S> */ B(LdaSmi), U8(1),
+  /* 1677 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(237),
+  /* 1684 S> */ B(LdaSmi), U8(1),
+  /* 1691 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(239),
+  /* 1698 S> */ B(LdaSmi), U8(1),
+  /* 1705 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(241),
+  /* 1712 S> */ B(LdaSmi), U8(1),
+  /* 1719 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(243),
+  /* 1726 S> */ B(LdaSmi), U8(1),
+  /* 1733 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(245),
+  /* 1740 S> */ B(LdaSmi), U8(1),
+  /* 1747 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(247),
+  /* 1754 S> */ B(LdaSmi), U8(1),
+  /* 1761 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(249),
+  /* 1768 S> */ B(LdaSmi), U8(1),
+  /* 1775 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(251),
+  /* 1782 S> */ B(LdaSmi), U8(1),
+  /* 1789 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(253),
+  /* 1796 S> */ B(LdaSmi), U8(1),
+  /* 1803 E> */ B(StaNamedPropertySloppy), R(arg0), U8(0), U8(255),
+  /* 1810 S> */ B(LdaSmi), U8(2),
+  /* 1817 E> */ B(Wide), B(StaNamedPropertySloppy), R16(arg0), U16(0), U16(257),
+                B(LdaUndefined),
+  /* 1822 S> */ B(Return),
 ]
 constant pool: [
   "name",
@@ -982,529 +704,271 @@
   }
   f({name : \"test\"})
 "
-frame size: 1
+frame size: 0
 parameter count: 2
-bytecode array length: 1297
+bytecode array length: 781
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(1),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(3),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(5),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(7),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(9),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(11),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(13),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(15),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(17),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(19),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(21),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(23),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(25),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(27),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(29),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(31),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(33),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(35),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(37),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(39),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(41),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(43),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(45),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(47),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(49),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(51),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(53),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(55),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(57),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(59),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(61),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(63),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(65),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(67),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(69),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(71),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(73),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(75),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(77),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(79),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(81),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(83),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(85),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(87),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(89),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(91),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(93),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(95),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(97),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(99),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(101),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(103),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(105),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(107),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(109),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(111),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(113),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(115),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(117),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(119),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(121),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(123),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(125),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(127),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(129),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(131),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(133),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(135),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(137),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(139),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(141),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(143),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(145),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(147),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(149),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(151),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(153),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(155),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(157),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(159),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(161),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(163),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(165),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(167),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(169),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(171),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(173),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(175),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(177),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(179),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(181),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(183),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(185),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(187),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(189),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(191),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(193),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(195),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(197),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(199),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(201),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(203),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(205),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(207),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(209),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(211),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(213),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(215),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(217),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(219),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(221),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(223),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(225),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(227),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(229),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(231),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(233),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(235),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(237),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(239),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(241),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(243),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(245),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(247),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(249),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(251),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(253),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(1),
-  B(StoreICStrict), R(0), U8(0), U8(255),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LdaSmi), U8(2),
-  B(Wide), B(StoreICStrict), R16(0), U16(0), U16(257),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   33 S> */ B(LdaSmi), U8(1),
+  /*   40 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(1),
+  /*   47 S> */ B(LdaSmi), U8(1),
+  /*   54 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(3),
+  /*   61 S> */ B(LdaSmi), U8(1),
+  /*   68 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(5),
+  /*   75 S> */ B(LdaSmi), U8(1),
+  /*   82 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(7),
+  /*   89 S> */ B(LdaSmi), U8(1),
+  /*   96 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(9),
+  /*  103 S> */ B(LdaSmi), U8(1),
+  /*  110 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(11),
+  /*  117 S> */ B(LdaSmi), U8(1),
+  /*  124 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(13),
+  /*  131 S> */ B(LdaSmi), U8(1),
+  /*  138 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(15),
+  /*  145 S> */ B(LdaSmi), U8(1),
+  /*  152 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(17),
+  /*  159 S> */ B(LdaSmi), U8(1),
+  /*  166 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(19),
+  /*  173 S> */ B(LdaSmi), U8(1),
+  /*  180 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(21),
+  /*  187 S> */ B(LdaSmi), U8(1),
+  /*  194 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(23),
+  /*  201 S> */ B(LdaSmi), U8(1),
+  /*  208 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(25),
+  /*  215 S> */ B(LdaSmi), U8(1),
+  /*  222 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(27),
+  /*  229 S> */ B(LdaSmi), U8(1),
+  /*  236 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(29),
+  /*  243 S> */ B(LdaSmi), U8(1),
+  /*  250 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(31),
+  /*  257 S> */ B(LdaSmi), U8(1),
+  /*  264 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(33),
+  /*  271 S> */ B(LdaSmi), U8(1),
+  /*  278 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(35),
+  /*  285 S> */ B(LdaSmi), U8(1),
+  /*  292 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(37),
+  /*  299 S> */ B(LdaSmi), U8(1),
+  /*  306 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(39),
+  /*  313 S> */ B(LdaSmi), U8(1),
+  /*  320 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(41),
+  /*  327 S> */ B(LdaSmi), U8(1),
+  /*  334 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(43),
+  /*  341 S> */ B(LdaSmi), U8(1),
+  /*  348 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(45),
+  /*  355 S> */ B(LdaSmi), U8(1),
+  /*  362 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(47),
+  /*  369 S> */ B(LdaSmi), U8(1),
+  /*  376 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(49),
+  /*  383 S> */ B(LdaSmi), U8(1),
+  /*  390 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(51),
+  /*  397 S> */ B(LdaSmi), U8(1),
+  /*  404 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(53),
+  /*  411 S> */ B(LdaSmi), U8(1),
+  /*  418 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(55),
+  /*  425 S> */ B(LdaSmi), U8(1),
+  /*  432 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(57),
+  /*  439 S> */ B(LdaSmi), U8(1),
+  /*  446 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(59),
+  /*  453 S> */ B(LdaSmi), U8(1),
+  /*  460 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(61),
+  /*  467 S> */ B(LdaSmi), U8(1),
+  /*  474 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(63),
+  /*  481 S> */ B(LdaSmi), U8(1),
+  /*  488 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(65),
+  /*  495 S> */ B(LdaSmi), U8(1),
+  /*  502 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(67),
+  /*  509 S> */ B(LdaSmi), U8(1),
+  /*  516 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(69),
+  /*  523 S> */ B(LdaSmi), U8(1),
+  /*  530 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(71),
+  /*  537 S> */ B(LdaSmi), U8(1),
+  /*  544 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(73),
+  /*  551 S> */ B(LdaSmi), U8(1),
+  /*  558 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(75),
+  /*  565 S> */ B(LdaSmi), U8(1),
+  /*  572 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(77),
+  /*  579 S> */ B(LdaSmi), U8(1),
+  /*  586 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(79),
+  /*  593 S> */ B(LdaSmi), U8(1),
+  /*  600 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(81),
+  /*  607 S> */ B(LdaSmi), U8(1),
+  /*  614 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(83),
+  /*  621 S> */ B(LdaSmi), U8(1),
+  /*  628 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(85),
+  /*  635 S> */ B(LdaSmi), U8(1),
+  /*  642 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(87),
+  /*  649 S> */ B(LdaSmi), U8(1),
+  /*  656 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(89),
+  /*  663 S> */ B(LdaSmi), U8(1),
+  /*  670 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(91),
+  /*  677 S> */ B(LdaSmi), U8(1),
+  /*  684 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(93),
+  /*  691 S> */ B(LdaSmi), U8(1),
+  /*  698 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(95),
+  /*  705 S> */ B(LdaSmi), U8(1),
+  /*  712 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(97),
+  /*  719 S> */ B(LdaSmi), U8(1),
+  /*  726 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(99),
+  /*  733 S> */ B(LdaSmi), U8(1),
+  /*  740 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(101),
+  /*  747 S> */ B(LdaSmi), U8(1),
+  /*  754 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(103),
+  /*  761 S> */ B(LdaSmi), U8(1),
+  /*  768 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(105),
+  /*  775 S> */ B(LdaSmi), U8(1),
+  /*  782 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(107),
+  /*  789 S> */ B(LdaSmi), U8(1),
+  /*  796 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(109),
+  /*  803 S> */ B(LdaSmi), U8(1),
+  /*  810 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(111),
+  /*  817 S> */ B(LdaSmi), U8(1),
+  /*  824 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(113),
+  /*  831 S> */ B(LdaSmi), U8(1),
+  /*  838 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(115),
+  /*  845 S> */ B(LdaSmi), U8(1),
+  /*  852 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(117),
+  /*  859 S> */ B(LdaSmi), U8(1),
+  /*  866 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(119),
+  /*  873 S> */ B(LdaSmi), U8(1),
+  /*  880 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(121),
+  /*  887 S> */ B(LdaSmi), U8(1),
+  /*  894 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(123),
+  /*  901 S> */ B(LdaSmi), U8(1),
+  /*  908 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(125),
+  /*  915 S> */ B(LdaSmi), U8(1),
+  /*  922 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(127),
+  /*  929 S> */ B(LdaSmi), U8(1),
+  /*  936 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(129),
+  /*  943 S> */ B(LdaSmi), U8(1),
+  /*  950 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(131),
+  /*  957 S> */ B(LdaSmi), U8(1),
+  /*  964 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(133),
+  /*  971 S> */ B(LdaSmi), U8(1),
+  /*  978 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(135),
+  /*  985 S> */ B(LdaSmi), U8(1),
+  /*  992 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(137),
+  /*  999 S> */ B(LdaSmi), U8(1),
+  /* 1006 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(139),
+  /* 1013 S> */ B(LdaSmi), U8(1),
+  /* 1020 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(141),
+  /* 1027 S> */ B(LdaSmi), U8(1),
+  /* 1034 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(143),
+  /* 1041 S> */ B(LdaSmi), U8(1),
+  /* 1048 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(145),
+  /* 1055 S> */ B(LdaSmi), U8(1),
+  /* 1062 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(147),
+  /* 1069 S> */ B(LdaSmi), U8(1),
+  /* 1076 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(149),
+  /* 1083 S> */ B(LdaSmi), U8(1),
+  /* 1090 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(151),
+  /* 1097 S> */ B(LdaSmi), U8(1),
+  /* 1104 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(153),
+  /* 1111 S> */ B(LdaSmi), U8(1),
+  /* 1118 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(155),
+  /* 1125 S> */ B(LdaSmi), U8(1),
+  /* 1132 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(157),
+  /* 1139 S> */ B(LdaSmi), U8(1),
+  /* 1146 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(159),
+  /* 1153 S> */ B(LdaSmi), U8(1),
+  /* 1160 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(161),
+  /* 1167 S> */ B(LdaSmi), U8(1),
+  /* 1174 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(163),
+  /* 1181 S> */ B(LdaSmi), U8(1),
+  /* 1188 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(165),
+  /* 1195 S> */ B(LdaSmi), U8(1),
+  /* 1202 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(167),
+  /* 1209 S> */ B(LdaSmi), U8(1),
+  /* 1216 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(169),
+  /* 1223 S> */ B(LdaSmi), U8(1),
+  /* 1230 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(171),
+  /* 1237 S> */ B(LdaSmi), U8(1),
+  /* 1244 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(173),
+  /* 1251 S> */ B(LdaSmi), U8(1),
+  /* 1258 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(175),
+  /* 1265 S> */ B(LdaSmi), U8(1),
+  /* 1272 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(177),
+  /* 1279 S> */ B(LdaSmi), U8(1),
+  /* 1286 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(179),
+  /* 1293 S> */ B(LdaSmi), U8(1),
+  /* 1300 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(181),
+  /* 1307 S> */ B(LdaSmi), U8(1),
+  /* 1314 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(183),
+  /* 1321 S> */ B(LdaSmi), U8(1),
+  /* 1328 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(185),
+  /* 1335 S> */ B(LdaSmi), U8(1),
+  /* 1342 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(187),
+  /* 1349 S> */ B(LdaSmi), U8(1),
+  /* 1356 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(189),
+  /* 1363 S> */ B(LdaSmi), U8(1),
+  /* 1370 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(191),
+  /* 1377 S> */ B(LdaSmi), U8(1),
+  /* 1384 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(193),
+  /* 1391 S> */ B(LdaSmi), U8(1),
+  /* 1398 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(195),
+  /* 1405 S> */ B(LdaSmi), U8(1),
+  /* 1412 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(197),
+  /* 1419 S> */ B(LdaSmi), U8(1),
+  /* 1426 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(199),
+  /* 1433 S> */ B(LdaSmi), U8(1),
+  /* 1440 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(201),
+  /* 1447 S> */ B(LdaSmi), U8(1),
+  /* 1454 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(203),
+  /* 1461 S> */ B(LdaSmi), U8(1),
+  /* 1468 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(205),
+  /* 1475 S> */ B(LdaSmi), U8(1),
+  /* 1482 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(207),
+  /* 1489 S> */ B(LdaSmi), U8(1),
+  /* 1496 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(209),
+  /* 1503 S> */ B(LdaSmi), U8(1),
+  /* 1510 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(211),
+  /* 1517 S> */ B(LdaSmi), U8(1),
+  /* 1524 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(213),
+  /* 1531 S> */ B(LdaSmi), U8(1),
+  /* 1538 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(215),
+  /* 1545 S> */ B(LdaSmi), U8(1),
+  /* 1552 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(217),
+  /* 1559 S> */ B(LdaSmi), U8(1),
+  /* 1566 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(219),
+  /* 1573 S> */ B(LdaSmi), U8(1),
+  /* 1580 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(221),
+  /* 1587 S> */ B(LdaSmi), U8(1),
+  /* 1594 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(223),
+  /* 1601 S> */ B(LdaSmi), U8(1),
+  /* 1608 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(225),
+  /* 1615 S> */ B(LdaSmi), U8(1),
+  /* 1622 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(227),
+  /* 1629 S> */ B(LdaSmi), U8(1),
+  /* 1636 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(229),
+  /* 1643 S> */ B(LdaSmi), U8(1),
+  /* 1650 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(231),
+  /* 1657 S> */ B(LdaSmi), U8(1),
+  /* 1664 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(233),
+  /* 1671 S> */ B(LdaSmi), U8(1),
+  /* 1678 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(235),
+  /* 1685 S> */ B(LdaSmi), U8(1),
+  /* 1692 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(237),
+  /* 1699 S> */ B(LdaSmi), U8(1),
+  /* 1706 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(239),
+  /* 1713 S> */ B(LdaSmi), U8(1),
+  /* 1720 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(241),
+  /* 1727 S> */ B(LdaSmi), U8(1),
+  /* 1734 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(243),
+  /* 1741 S> */ B(LdaSmi), U8(1),
+  /* 1748 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(245),
+  /* 1755 S> */ B(LdaSmi), U8(1),
+  /* 1762 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(247),
+  /* 1769 S> */ B(LdaSmi), U8(1),
+  /* 1776 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(249),
+  /* 1783 S> */ B(LdaSmi), U8(1),
+  /* 1790 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(251),
+  /* 1797 S> */ B(LdaSmi), U8(1),
+  /* 1804 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(253),
+  /* 1811 S> */ B(LdaSmi), U8(1),
+  /* 1818 E> */ B(StaNamedPropertyStrict), R(arg0), U8(0), U8(255),
+  /* 1825 S> */ B(LdaSmi), U8(2),
+  /* 1832 E> */ B(Wide), B(StaNamedPropertyStrict), R16(arg0), U16(0), U16(257),
+                B(LdaUndefined),
+  /* 1837 S> */ B(Return),
 ]
 constant pool: [
   "name",
@@ -1647,787 +1111,271 @@
   }
   f({name : \"test\"})
 "
-frame size: 2
+frame size: 0
 parameter count: 3
-bytecode array length: 1813
+bytecode array length: 781
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(1),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(3),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(5),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(7),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(9),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(11),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(13),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(15),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(17),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(19),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(21),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(23),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(25),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(27),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(29),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(31),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(33),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(35),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(37),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(39),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(41),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(43),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(45),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(47),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(49),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(51),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(53),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(55),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(57),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(59),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(61),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(63),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(65),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(67),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(69),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(71),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(73),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(75),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(77),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(79),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(81),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(83),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(85),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(87),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(89),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(91),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(93),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(95),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(97),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(99),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(101),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(103),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(105),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(107),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(109),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(111),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(113),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(115),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(117),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(119),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(121),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(123),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(125),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(127),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(129),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(131),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(133),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(135),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(137),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(139),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(141),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(143),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(145),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(147),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(149),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(151),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(153),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(155),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(157),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(159),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(161),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(163),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(165),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(167),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(169),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(171),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(173),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(175),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(177),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(179),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(181),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(183),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(185),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(187),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(189),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(191),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(193),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(195),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(197),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(199),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(201),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(203),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(205),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(207),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(209),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(211),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(213),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(215),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(217),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(219),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(221),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(223),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(225),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(227),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(229),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(231),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(233),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(235),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(237),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(239),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(241),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(243),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(245),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(247),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(249),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(251),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(253),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICSloppy), R(0), R(1), U8(255),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Wide), B(KeyedStoreICSloppy), R16(0), R16(1), U16(257),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   21 S> */ B(LdaSmi), U8(1),
+  /*   26 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(1),
+  /*   33 S> */ B(LdaSmi), U8(1),
+  /*   38 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(3),
+  /*   45 S> */ B(LdaSmi), U8(1),
+  /*   50 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(5),
+  /*   57 S> */ B(LdaSmi), U8(1),
+  /*   62 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(7),
+  /*   69 S> */ B(LdaSmi), U8(1),
+  /*   74 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(9),
+  /*   81 S> */ B(LdaSmi), U8(1),
+  /*   86 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(11),
+  /*   93 S> */ B(LdaSmi), U8(1),
+  /*   98 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(13),
+  /*  105 S> */ B(LdaSmi), U8(1),
+  /*  110 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(15),
+  /*  117 S> */ B(LdaSmi), U8(1),
+  /*  122 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(17),
+  /*  129 S> */ B(LdaSmi), U8(1),
+  /*  134 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(19),
+  /*  141 S> */ B(LdaSmi), U8(1),
+  /*  146 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(21),
+  /*  153 S> */ B(LdaSmi), U8(1),
+  /*  158 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(23),
+  /*  165 S> */ B(LdaSmi), U8(1),
+  /*  170 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(25),
+  /*  177 S> */ B(LdaSmi), U8(1),
+  /*  182 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(27),
+  /*  189 S> */ B(LdaSmi), U8(1),
+  /*  194 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(29),
+  /*  201 S> */ B(LdaSmi), U8(1),
+  /*  206 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(31),
+  /*  213 S> */ B(LdaSmi), U8(1),
+  /*  218 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(33),
+  /*  225 S> */ B(LdaSmi), U8(1),
+  /*  230 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(35),
+  /*  237 S> */ B(LdaSmi), U8(1),
+  /*  242 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(37),
+  /*  249 S> */ B(LdaSmi), U8(1),
+  /*  254 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(39),
+  /*  261 S> */ B(LdaSmi), U8(1),
+  /*  266 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(41),
+  /*  273 S> */ B(LdaSmi), U8(1),
+  /*  278 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(43),
+  /*  285 S> */ B(LdaSmi), U8(1),
+  /*  290 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(45),
+  /*  297 S> */ B(LdaSmi), U8(1),
+  /*  302 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(47),
+  /*  309 S> */ B(LdaSmi), U8(1),
+  /*  314 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(49),
+  /*  321 S> */ B(LdaSmi), U8(1),
+  /*  326 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(51),
+  /*  333 S> */ B(LdaSmi), U8(1),
+  /*  338 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(53),
+  /*  345 S> */ B(LdaSmi), U8(1),
+  /*  350 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(55),
+  /*  357 S> */ B(LdaSmi), U8(1),
+  /*  362 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(57),
+  /*  369 S> */ B(LdaSmi), U8(1),
+  /*  374 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(59),
+  /*  381 S> */ B(LdaSmi), U8(1),
+  /*  386 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(61),
+  /*  393 S> */ B(LdaSmi), U8(1),
+  /*  398 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(63),
+  /*  405 S> */ B(LdaSmi), U8(1),
+  /*  410 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(65),
+  /*  417 S> */ B(LdaSmi), U8(1),
+  /*  422 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(67),
+  /*  429 S> */ B(LdaSmi), U8(1),
+  /*  434 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(69),
+  /*  441 S> */ B(LdaSmi), U8(1),
+  /*  446 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(71),
+  /*  453 S> */ B(LdaSmi), U8(1),
+  /*  458 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(73),
+  /*  465 S> */ B(LdaSmi), U8(1),
+  /*  470 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(75),
+  /*  477 S> */ B(LdaSmi), U8(1),
+  /*  482 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(77),
+  /*  489 S> */ B(LdaSmi), U8(1),
+  /*  494 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(79),
+  /*  501 S> */ B(LdaSmi), U8(1),
+  /*  506 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(81),
+  /*  513 S> */ B(LdaSmi), U8(1),
+  /*  518 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(83),
+  /*  525 S> */ B(LdaSmi), U8(1),
+  /*  530 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(85),
+  /*  537 S> */ B(LdaSmi), U8(1),
+  /*  542 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(87),
+  /*  549 S> */ B(LdaSmi), U8(1),
+  /*  554 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(89),
+  /*  561 S> */ B(LdaSmi), U8(1),
+  /*  566 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(91),
+  /*  573 S> */ B(LdaSmi), U8(1),
+  /*  578 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(93),
+  /*  585 S> */ B(LdaSmi), U8(1),
+  /*  590 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(95),
+  /*  597 S> */ B(LdaSmi), U8(1),
+  /*  602 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(97),
+  /*  609 S> */ B(LdaSmi), U8(1),
+  /*  614 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(99),
+  /*  621 S> */ B(LdaSmi), U8(1),
+  /*  626 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(101),
+  /*  633 S> */ B(LdaSmi), U8(1),
+  /*  638 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(103),
+  /*  645 S> */ B(LdaSmi), U8(1),
+  /*  650 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(105),
+  /*  657 S> */ B(LdaSmi), U8(1),
+  /*  662 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(107),
+  /*  669 S> */ B(LdaSmi), U8(1),
+  /*  674 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(109),
+  /*  681 S> */ B(LdaSmi), U8(1),
+  /*  686 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(111),
+  /*  693 S> */ B(LdaSmi), U8(1),
+  /*  698 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(113),
+  /*  705 S> */ B(LdaSmi), U8(1),
+  /*  710 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(115),
+  /*  717 S> */ B(LdaSmi), U8(1),
+  /*  722 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(117),
+  /*  729 S> */ B(LdaSmi), U8(1),
+  /*  734 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(119),
+  /*  741 S> */ B(LdaSmi), U8(1),
+  /*  746 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(121),
+  /*  753 S> */ B(LdaSmi), U8(1),
+  /*  758 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(123),
+  /*  765 S> */ B(LdaSmi), U8(1),
+  /*  770 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(125),
+  /*  777 S> */ B(LdaSmi), U8(1),
+  /*  782 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(127),
+  /*  789 S> */ B(LdaSmi), U8(1),
+  /*  794 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(129),
+  /*  801 S> */ B(LdaSmi), U8(1),
+  /*  806 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(131),
+  /*  813 S> */ B(LdaSmi), U8(1),
+  /*  818 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(133),
+  /*  825 S> */ B(LdaSmi), U8(1),
+  /*  830 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(135),
+  /*  837 S> */ B(LdaSmi), U8(1),
+  /*  842 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(137),
+  /*  849 S> */ B(LdaSmi), U8(1),
+  /*  854 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(139),
+  /*  861 S> */ B(LdaSmi), U8(1),
+  /*  866 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(141),
+  /*  873 S> */ B(LdaSmi), U8(1),
+  /*  878 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(143),
+  /*  885 S> */ B(LdaSmi), U8(1),
+  /*  890 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(145),
+  /*  897 S> */ B(LdaSmi), U8(1),
+  /*  902 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(147),
+  /*  909 S> */ B(LdaSmi), U8(1),
+  /*  914 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(149),
+  /*  921 S> */ B(LdaSmi), U8(1),
+  /*  926 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(151),
+  /*  933 S> */ B(LdaSmi), U8(1),
+  /*  938 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(153),
+  /*  945 S> */ B(LdaSmi), U8(1),
+  /*  950 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(155),
+  /*  957 S> */ B(LdaSmi), U8(1),
+  /*  962 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(157),
+  /*  969 S> */ B(LdaSmi), U8(1),
+  /*  974 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(159),
+  /*  981 S> */ B(LdaSmi), U8(1),
+  /*  986 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(161),
+  /*  993 S> */ B(LdaSmi), U8(1),
+  /*  998 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(163),
+  /* 1005 S> */ B(LdaSmi), U8(1),
+  /* 1010 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(165),
+  /* 1017 S> */ B(LdaSmi), U8(1),
+  /* 1022 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(167),
+  /* 1029 S> */ B(LdaSmi), U8(1),
+  /* 1034 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(169),
+  /* 1041 S> */ B(LdaSmi), U8(1),
+  /* 1046 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(171),
+  /* 1053 S> */ B(LdaSmi), U8(1),
+  /* 1058 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(173),
+  /* 1065 S> */ B(LdaSmi), U8(1),
+  /* 1070 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(175),
+  /* 1077 S> */ B(LdaSmi), U8(1),
+  /* 1082 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(177),
+  /* 1089 S> */ B(LdaSmi), U8(1),
+  /* 1094 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(179),
+  /* 1101 S> */ B(LdaSmi), U8(1),
+  /* 1106 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(181),
+  /* 1113 S> */ B(LdaSmi), U8(1),
+  /* 1118 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(183),
+  /* 1125 S> */ B(LdaSmi), U8(1),
+  /* 1130 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(185),
+  /* 1137 S> */ B(LdaSmi), U8(1),
+  /* 1142 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(187),
+  /* 1149 S> */ B(LdaSmi), U8(1),
+  /* 1154 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(189),
+  /* 1161 S> */ B(LdaSmi), U8(1),
+  /* 1166 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(191),
+  /* 1173 S> */ B(LdaSmi), U8(1),
+  /* 1178 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(193),
+  /* 1185 S> */ B(LdaSmi), U8(1),
+  /* 1190 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(195),
+  /* 1197 S> */ B(LdaSmi), U8(1),
+  /* 1202 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(197),
+  /* 1209 S> */ B(LdaSmi), U8(1),
+  /* 1214 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(199),
+  /* 1221 S> */ B(LdaSmi), U8(1),
+  /* 1226 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(201),
+  /* 1233 S> */ B(LdaSmi), U8(1),
+  /* 1238 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(203),
+  /* 1245 S> */ B(LdaSmi), U8(1),
+  /* 1250 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(205),
+  /* 1257 S> */ B(LdaSmi), U8(1),
+  /* 1262 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(207),
+  /* 1269 S> */ B(LdaSmi), U8(1),
+  /* 1274 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(209),
+  /* 1281 S> */ B(LdaSmi), U8(1),
+  /* 1286 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(211),
+  /* 1293 S> */ B(LdaSmi), U8(1),
+  /* 1298 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(213),
+  /* 1305 S> */ B(LdaSmi), U8(1),
+  /* 1310 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(215),
+  /* 1317 S> */ B(LdaSmi), U8(1),
+  /* 1322 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(217),
+  /* 1329 S> */ B(LdaSmi), U8(1),
+  /* 1334 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(219),
+  /* 1341 S> */ B(LdaSmi), U8(1),
+  /* 1346 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(221),
+  /* 1353 S> */ B(LdaSmi), U8(1),
+  /* 1358 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(223),
+  /* 1365 S> */ B(LdaSmi), U8(1),
+  /* 1370 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(225),
+  /* 1377 S> */ B(LdaSmi), U8(1),
+  /* 1382 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(227),
+  /* 1389 S> */ B(LdaSmi), U8(1),
+  /* 1394 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(229),
+  /* 1401 S> */ B(LdaSmi), U8(1),
+  /* 1406 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(231),
+  /* 1413 S> */ B(LdaSmi), U8(1),
+  /* 1418 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(233),
+  /* 1425 S> */ B(LdaSmi), U8(1),
+  /* 1430 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(235),
+  /* 1437 S> */ B(LdaSmi), U8(1),
+  /* 1442 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(237),
+  /* 1449 S> */ B(LdaSmi), U8(1),
+  /* 1454 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(239),
+  /* 1461 S> */ B(LdaSmi), U8(1),
+  /* 1466 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(241),
+  /* 1473 S> */ B(LdaSmi), U8(1),
+  /* 1478 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(243),
+  /* 1485 S> */ B(LdaSmi), U8(1),
+  /* 1490 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(245),
+  /* 1497 S> */ B(LdaSmi), U8(1),
+  /* 1502 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(247),
+  /* 1509 S> */ B(LdaSmi), U8(1),
+  /* 1514 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(249),
+  /* 1521 S> */ B(LdaSmi), U8(1),
+  /* 1526 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(251),
+  /* 1533 S> */ B(LdaSmi), U8(1),
+  /* 1538 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(253),
+  /* 1545 S> */ B(LdaSmi), U8(1),
+  /* 1550 E> */ B(StaKeyedPropertySloppy), R(arg0), R(arg1), U8(255),
+  /* 1557 S> */ B(LdaSmi), U8(2),
+  /* 1562 E> */ B(Wide), B(StaKeyedPropertySloppy), R16(arg0), R16(arg1), U16(257),
+                B(LdaUndefined),
+  /* 1567 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -2570,787 +1518,271 @@
   }
   f({name : \"test\"})
 "
-frame size: 2
+frame size: 0
 parameter count: 3
-bytecode array length: 1813
+bytecode array length: 781
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(1),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(3),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(5),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(7),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(9),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(11),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(13),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(15),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(17),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(19),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(21),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(23),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(25),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(27),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(29),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(31),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(33),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(35),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(37),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(39),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(41),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(43),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(45),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(47),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(49),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(51),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(53),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(55),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(57),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(59),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(61),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(63),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(65),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(67),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(69),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(71),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(73),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(75),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(77),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(79),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(81),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(83),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(85),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(87),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(89),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(91),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(93),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(95),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(97),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(99),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(101),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(103),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(105),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(107),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(109),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(111),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(113),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(115),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(117),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(119),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(121),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(123),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(125),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(127),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(129),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(131),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(133),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(135),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(137),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(139),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(141),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(143),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(145),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(147),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(149),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(151),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(153),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(155),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(157),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(159),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(161),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(163),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(165),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(167),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(169),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(171),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(173),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(175),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(177),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(179),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(181),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(183),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(185),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(187),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(189),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(191),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(193),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(195),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(197),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(199),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(201),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(203),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(205),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(207),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(209),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(211),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(213),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(215),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(217),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(219),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(221),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(223),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(225),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(227),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(229),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(231),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(233),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(235),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(237),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(239),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(241),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(243),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(245),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(247),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(249),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(251),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(253),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(KeyedStoreICStrict), R(0), R(1), U8(255),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(Ldar), R(arg1),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Wide), B(KeyedStoreICStrict), R16(0), R16(1), U16(257),
-  B(LdaUndefined),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   37 S> */ B(LdaSmi), U8(1),
+  /*   42 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(1),
+  /*   49 S> */ B(LdaSmi), U8(1),
+  /*   54 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(3),
+  /*   61 S> */ B(LdaSmi), U8(1),
+  /*   66 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(5),
+  /*   73 S> */ B(LdaSmi), U8(1),
+  /*   78 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(7),
+  /*   85 S> */ B(LdaSmi), U8(1),
+  /*   90 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(9),
+  /*   97 S> */ B(LdaSmi), U8(1),
+  /*  102 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(11),
+  /*  109 S> */ B(LdaSmi), U8(1),
+  /*  114 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(13),
+  /*  121 S> */ B(LdaSmi), U8(1),
+  /*  126 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(15),
+  /*  133 S> */ B(LdaSmi), U8(1),
+  /*  138 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(17),
+  /*  145 S> */ B(LdaSmi), U8(1),
+  /*  150 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(19),
+  /*  157 S> */ B(LdaSmi), U8(1),
+  /*  162 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(21),
+  /*  169 S> */ B(LdaSmi), U8(1),
+  /*  174 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(23),
+  /*  181 S> */ B(LdaSmi), U8(1),
+  /*  186 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(25),
+  /*  193 S> */ B(LdaSmi), U8(1),
+  /*  198 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(27),
+  /*  205 S> */ B(LdaSmi), U8(1),
+  /*  210 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(29),
+  /*  217 S> */ B(LdaSmi), U8(1),
+  /*  222 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(31),
+  /*  229 S> */ B(LdaSmi), U8(1),
+  /*  234 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(33),
+  /*  241 S> */ B(LdaSmi), U8(1),
+  /*  246 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(35),
+  /*  253 S> */ B(LdaSmi), U8(1),
+  /*  258 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(37),
+  /*  265 S> */ B(LdaSmi), U8(1),
+  /*  270 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(39),
+  /*  277 S> */ B(LdaSmi), U8(1),
+  /*  282 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(41),
+  /*  289 S> */ B(LdaSmi), U8(1),
+  /*  294 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(43),
+  /*  301 S> */ B(LdaSmi), U8(1),
+  /*  306 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(45),
+  /*  313 S> */ B(LdaSmi), U8(1),
+  /*  318 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(47),
+  /*  325 S> */ B(LdaSmi), U8(1),
+  /*  330 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(49),
+  /*  337 S> */ B(LdaSmi), U8(1),
+  /*  342 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(51),
+  /*  349 S> */ B(LdaSmi), U8(1),
+  /*  354 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(53),
+  /*  361 S> */ B(LdaSmi), U8(1),
+  /*  366 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(55),
+  /*  373 S> */ B(LdaSmi), U8(1),
+  /*  378 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(57),
+  /*  385 S> */ B(LdaSmi), U8(1),
+  /*  390 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(59),
+  /*  397 S> */ B(LdaSmi), U8(1),
+  /*  402 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(61),
+  /*  409 S> */ B(LdaSmi), U8(1),
+  /*  414 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(63),
+  /*  421 S> */ B(LdaSmi), U8(1),
+  /*  426 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(65),
+  /*  433 S> */ B(LdaSmi), U8(1),
+  /*  438 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(67),
+  /*  445 S> */ B(LdaSmi), U8(1),
+  /*  450 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(69),
+  /*  457 S> */ B(LdaSmi), U8(1),
+  /*  462 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(71),
+  /*  469 S> */ B(LdaSmi), U8(1),
+  /*  474 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(73),
+  /*  481 S> */ B(LdaSmi), U8(1),
+  /*  486 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(75),
+  /*  493 S> */ B(LdaSmi), U8(1),
+  /*  498 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(77),
+  /*  505 S> */ B(LdaSmi), U8(1),
+  /*  510 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(79),
+  /*  517 S> */ B(LdaSmi), U8(1),
+  /*  522 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(81),
+  /*  529 S> */ B(LdaSmi), U8(1),
+  /*  534 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(83),
+  /*  541 S> */ B(LdaSmi), U8(1),
+  /*  546 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(85),
+  /*  553 S> */ B(LdaSmi), U8(1),
+  /*  558 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(87),
+  /*  565 S> */ B(LdaSmi), U8(1),
+  /*  570 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(89),
+  /*  577 S> */ B(LdaSmi), U8(1),
+  /*  582 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(91),
+  /*  589 S> */ B(LdaSmi), U8(1),
+  /*  594 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(93),
+  /*  601 S> */ B(LdaSmi), U8(1),
+  /*  606 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(95),
+  /*  613 S> */ B(LdaSmi), U8(1),
+  /*  618 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(97),
+  /*  625 S> */ B(LdaSmi), U8(1),
+  /*  630 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(99),
+  /*  637 S> */ B(LdaSmi), U8(1),
+  /*  642 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(101),
+  /*  649 S> */ B(LdaSmi), U8(1),
+  /*  654 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(103),
+  /*  661 S> */ B(LdaSmi), U8(1),
+  /*  666 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(105),
+  /*  673 S> */ B(LdaSmi), U8(1),
+  /*  678 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(107),
+  /*  685 S> */ B(LdaSmi), U8(1),
+  /*  690 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(109),
+  /*  697 S> */ B(LdaSmi), U8(1),
+  /*  702 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(111),
+  /*  709 S> */ B(LdaSmi), U8(1),
+  /*  714 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(113),
+  /*  721 S> */ B(LdaSmi), U8(1),
+  /*  726 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(115),
+  /*  733 S> */ B(LdaSmi), U8(1),
+  /*  738 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(117),
+  /*  745 S> */ B(LdaSmi), U8(1),
+  /*  750 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(119),
+  /*  757 S> */ B(LdaSmi), U8(1),
+  /*  762 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(121),
+  /*  769 S> */ B(LdaSmi), U8(1),
+  /*  774 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(123),
+  /*  781 S> */ B(LdaSmi), U8(1),
+  /*  786 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(125),
+  /*  793 S> */ B(LdaSmi), U8(1),
+  /*  798 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(127),
+  /*  805 S> */ B(LdaSmi), U8(1),
+  /*  810 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(129),
+  /*  817 S> */ B(LdaSmi), U8(1),
+  /*  822 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(131),
+  /*  829 S> */ B(LdaSmi), U8(1),
+  /*  834 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(133),
+  /*  841 S> */ B(LdaSmi), U8(1),
+  /*  846 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(135),
+  /*  853 S> */ B(LdaSmi), U8(1),
+  /*  858 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(137),
+  /*  865 S> */ B(LdaSmi), U8(1),
+  /*  870 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(139),
+  /*  877 S> */ B(LdaSmi), U8(1),
+  /*  882 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(141),
+  /*  889 S> */ B(LdaSmi), U8(1),
+  /*  894 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(143),
+  /*  901 S> */ B(LdaSmi), U8(1),
+  /*  906 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(145),
+  /*  913 S> */ B(LdaSmi), U8(1),
+  /*  918 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(147),
+  /*  925 S> */ B(LdaSmi), U8(1),
+  /*  930 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(149),
+  /*  937 S> */ B(LdaSmi), U8(1),
+  /*  942 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(151),
+  /*  949 S> */ B(LdaSmi), U8(1),
+  /*  954 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(153),
+  /*  961 S> */ B(LdaSmi), U8(1),
+  /*  966 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(155),
+  /*  973 S> */ B(LdaSmi), U8(1),
+  /*  978 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(157),
+  /*  985 S> */ B(LdaSmi), U8(1),
+  /*  990 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(159),
+  /*  997 S> */ B(LdaSmi), U8(1),
+  /* 1002 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(161),
+  /* 1009 S> */ B(LdaSmi), U8(1),
+  /* 1014 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(163),
+  /* 1021 S> */ B(LdaSmi), U8(1),
+  /* 1026 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(165),
+  /* 1033 S> */ B(LdaSmi), U8(1),
+  /* 1038 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(167),
+  /* 1045 S> */ B(LdaSmi), U8(1),
+  /* 1050 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(169),
+  /* 1057 S> */ B(LdaSmi), U8(1),
+  /* 1062 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(171),
+  /* 1069 S> */ B(LdaSmi), U8(1),
+  /* 1074 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(173),
+  /* 1081 S> */ B(LdaSmi), U8(1),
+  /* 1086 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(175),
+  /* 1093 S> */ B(LdaSmi), U8(1),
+  /* 1098 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(177),
+  /* 1105 S> */ B(LdaSmi), U8(1),
+  /* 1110 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(179),
+  /* 1117 S> */ B(LdaSmi), U8(1),
+  /* 1122 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(181),
+  /* 1129 S> */ B(LdaSmi), U8(1),
+  /* 1134 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(183),
+  /* 1141 S> */ B(LdaSmi), U8(1),
+  /* 1146 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(185),
+  /* 1153 S> */ B(LdaSmi), U8(1),
+  /* 1158 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(187),
+  /* 1165 S> */ B(LdaSmi), U8(1),
+  /* 1170 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(189),
+  /* 1177 S> */ B(LdaSmi), U8(1),
+  /* 1182 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(191),
+  /* 1189 S> */ B(LdaSmi), U8(1),
+  /* 1194 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(193),
+  /* 1201 S> */ B(LdaSmi), U8(1),
+  /* 1206 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(195),
+  /* 1213 S> */ B(LdaSmi), U8(1),
+  /* 1218 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(197),
+  /* 1225 S> */ B(LdaSmi), U8(1),
+  /* 1230 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(199),
+  /* 1237 S> */ B(LdaSmi), U8(1),
+  /* 1242 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(201),
+  /* 1249 S> */ B(LdaSmi), U8(1),
+  /* 1254 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(203),
+  /* 1261 S> */ B(LdaSmi), U8(1),
+  /* 1266 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(205),
+  /* 1273 S> */ B(LdaSmi), U8(1),
+  /* 1278 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(207),
+  /* 1285 S> */ B(LdaSmi), U8(1),
+  /* 1290 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(209),
+  /* 1297 S> */ B(LdaSmi), U8(1),
+  /* 1302 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(211),
+  /* 1309 S> */ B(LdaSmi), U8(1),
+  /* 1314 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(213),
+  /* 1321 S> */ B(LdaSmi), U8(1),
+  /* 1326 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(215),
+  /* 1333 S> */ B(LdaSmi), U8(1),
+  /* 1338 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(217),
+  /* 1345 S> */ B(LdaSmi), U8(1),
+  /* 1350 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(219),
+  /* 1357 S> */ B(LdaSmi), U8(1),
+  /* 1362 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(221),
+  /* 1369 S> */ B(LdaSmi), U8(1),
+  /* 1374 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(223),
+  /* 1381 S> */ B(LdaSmi), U8(1),
+  /* 1386 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(225),
+  /* 1393 S> */ B(LdaSmi), U8(1),
+  /* 1398 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(227),
+  /* 1405 S> */ B(LdaSmi), U8(1),
+  /* 1410 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(229),
+  /* 1417 S> */ B(LdaSmi), U8(1),
+  /* 1422 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(231),
+  /* 1429 S> */ B(LdaSmi), U8(1),
+  /* 1434 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(233),
+  /* 1441 S> */ B(LdaSmi), U8(1),
+  /* 1446 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(235),
+  /* 1453 S> */ B(LdaSmi), U8(1),
+  /* 1458 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(237),
+  /* 1465 S> */ B(LdaSmi), U8(1),
+  /* 1470 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(239),
+  /* 1477 S> */ B(LdaSmi), U8(1),
+  /* 1482 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(241),
+  /* 1489 S> */ B(LdaSmi), U8(1),
+  /* 1494 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(243),
+  /* 1501 S> */ B(LdaSmi), U8(1),
+  /* 1506 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(245),
+  /* 1513 S> */ B(LdaSmi), U8(1),
+  /* 1518 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(247),
+  /* 1525 S> */ B(LdaSmi), U8(1),
+  /* 1530 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(249),
+  /* 1537 S> */ B(LdaSmi), U8(1),
+  /* 1542 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(251),
+  /* 1549 S> */ B(LdaSmi), U8(1),
+  /* 1554 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(253),
+  /* 1561 S> */ B(LdaSmi), U8(1),
+  /* 1566 E> */ B(StaKeyedPropertyStrict), R(arg0), R(arg1), U8(255),
+  /* 1573 S> */ B(LdaSmi), U8(2),
+  /* 1578 E> */ B(Wide), B(StaKeyedPropertyStrict), R16(arg0), R16(arg1), U16(257),
+                B(LdaUndefined),
+  /* 1583 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/RegExpLiterals.golden b/test/cctest/interpreter/bytecode_expectations/RegExpLiterals.golden
index adffb75..210a350 100644
--- a/test/cctest/interpreter/bytecode_expectations/RegExpLiterals.golden
+++ b/test/cctest/interpreter/bytecode_expectations/RegExpLiterals.golden
@@ -15,9 +15,9 @@
 parameter count: 1
 bytecode array length: 6
 bytecodes: [
-  B(StackCheck),
-  B(CreateRegExpLiteral), U8(0), U8(0), U8(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(CreateRegExpLiteral), U8(0), U8(0), U8(0),
+  /*   49 S> */ B(Return),
 ]
 constant pool: [
   "ab+d",
@@ -33,9 +33,9 @@
 parameter count: 1
 bytecode array length: 6
 bytecodes: [
-  B(StackCheck),
-  B(CreateRegExpLiteral), U8(0), U8(0), U8(2),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(CreateRegExpLiteral), U8(0), U8(0), U8(2),
+  /*   58 S> */ B(Return),
 ]
 constant pool: [
   "(\x5cw+)\x5cs(\x5cw+)",
@@ -49,17 +49,16 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 23
+bytecode array length: 22
 bytecodes: [
-  B(StackCheck),
-  B(CreateRegExpLiteral), U8(0), U8(0), U8(0),
-  B(Star), R(1),
-  B(LoadIC), R(1), U8(1), U8(3),
-  B(Star), R(0),
-  B(LdaConstant), U8(2),
-  B(Star), R(2),
-  B(Call), R(0), R(1), U8(2), U8(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(CreateRegExpLiteral), U8(0), U8(0), U8(0),
+                B(Star), R(1),
+  /*   47 E> */ B(LdrNamedProperty), R(1), U8(1), U8(3), R(0),
+                B(LdaConstant), U8(2),
+                B(Star), R(2),
+  /*   48 E> */ B(Call), R(0), R(1), U8(2), U8(1),
+  /*   62 S> */ B(Return),
 ]
 constant pool: [
   "ab+d",
diff --git a/test/cctest/interpreter/bytecode_expectations/RegExpLiteralsWide.golden b/test/cctest/interpreter/bytecode_expectations/RegExpLiteralsWide.golden
index d6fb160..3c5499b 100644
--- a/test/cctest/interpreter/bytecode_expectations/RegExpLiteralsWide.golden
+++ b/test/cctest/interpreter/bytecode_expectations/RegExpLiteralsWide.golden
@@ -272,521 +272,521 @@
 parameter count: 1
 bytecode array length: 1033
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(LdaConstant), U8(1),
-  B(Star), R(0),
-  B(LdaConstant), U8(2),
-  B(Star), R(0),
-  B(LdaConstant), U8(3),
-  B(Star), R(0),
-  B(LdaConstant), U8(4),
-  B(Star), R(0),
-  B(LdaConstant), U8(5),
-  B(Star), R(0),
-  B(LdaConstant), U8(6),
-  B(Star), R(0),
-  B(LdaConstant), U8(7),
-  B(Star), R(0),
-  B(LdaConstant), U8(8),
-  B(Star), R(0),
-  B(LdaConstant), U8(9),
-  B(Star), R(0),
-  B(LdaConstant), U8(10),
-  B(Star), R(0),
-  B(LdaConstant), U8(11),
-  B(Star), R(0),
-  B(LdaConstant), U8(12),
-  B(Star), R(0),
-  B(LdaConstant), U8(13),
-  B(Star), R(0),
-  B(LdaConstant), U8(14),
-  B(Star), R(0),
-  B(LdaConstant), U8(15),
-  B(Star), R(0),
-  B(LdaConstant), U8(16),
-  B(Star), R(0),
-  B(LdaConstant), U8(17),
-  B(Star), R(0),
-  B(LdaConstant), U8(18),
-  B(Star), R(0),
-  B(LdaConstant), U8(19),
-  B(Star), R(0),
-  B(LdaConstant), U8(20),
-  B(Star), R(0),
-  B(LdaConstant), U8(21),
-  B(Star), R(0),
-  B(LdaConstant), U8(22),
-  B(Star), R(0),
-  B(LdaConstant), U8(23),
-  B(Star), R(0),
-  B(LdaConstant), U8(24),
-  B(Star), R(0),
-  B(LdaConstant), U8(25),
-  B(Star), R(0),
-  B(LdaConstant), U8(26),
-  B(Star), R(0),
-  B(LdaConstant), U8(27),
-  B(Star), R(0),
-  B(LdaConstant), U8(28),
-  B(Star), R(0),
-  B(LdaConstant), U8(29),
-  B(Star), R(0),
-  B(LdaConstant), U8(30),
-  B(Star), R(0),
-  B(LdaConstant), U8(31),
-  B(Star), R(0),
-  B(LdaConstant), U8(32),
-  B(Star), R(0),
-  B(LdaConstant), U8(33),
-  B(Star), R(0),
-  B(LdaConstant), U8(34),
-  B(Star), R(0),
-  B(LdaConstant), U8(35),
-  B(Star), R(0),
-  B(LdaConstant), U8(36),
-  B(Star), R(0),
-  B(LdaConstant), U8(37),
-  B(Star), R(0),
-  B(LdaConstant), U8(38),
-  B(Star), R(0),
-  B(LdaConstant), U8(39),
-  B(Star), R(0),
-  B(LdaConstant), U8(40),
-  B(Star), R(0),
-  B(LdaConstant), U8(41),
-  B(Star), R(0),
-  B(LdaConstant), U8(42),
-  B(Star), R(0),
-  B(LdaConstant), U8(43),
-  B(Star), R(0),
-  B(LdaConstant), U8(44),
-  B(Star), R(0),
-  B(LdaConstant), U8(45),
-  B(Star), R(0),
-  B(LdaConstant), U8(46),
-  B(Star), R(0),
-  B(LdaConstant), U8(47),
-  B(Star), R(0),
-  B(LdaConstant), U8(48),
-  B(Star), R(0),
-  B(LdaConstant), U8(49),
-  B(Star), R(0),
-  B(LdaConstant), U8(50),
-  B(Star), R(0),
-  B(LdaConstant), U8(51),
-  B(Star), R(0),
-  B(LdaConstant), U8(52),
-  B(Star), R(0),
-  B(LdaConstant), U8(53),
-  B(Star), R(0),
-  B(LdaConstant), U8(54),
-  B(Star), R(0),
-  B(LdaConstant), U8(55),
-  B(Star), R(0),
-  B(LdaConstant), U8(56),
-  B(Star), R(0),
-  B(LdaConstant), U8(57),
-  B(Star), R(0),
-  B(LdaConstant), U8(58),
-  B(Star), R(0),
-  B(LdaConstant), U8(59),
-  B(Star), R(0),
-  B(LdaConstant), U8(60),
-  B(Star), R(0),
-  B(LdaConstant), U8(61),
-  B(Star), R(0),
-  B(LdaConstant), U8(62),
-  B(Star), R(0),
-  B(LdaConstant), U8(63),
-  B(Star), R(0),
-  B(LdaConstant), U8(64),
-  B(Star), R(0),
-  B(LdaConstant), U8(65),
-  B(Star), R(0),
-  B(LdaConstant), U8(66),
-  B(Star), R(0),
-  B(LdaConstant), U8(67),
-  B(Star), R(0),
-  B(LdaConstant), U8(68),
-  B(Star), R(0),
-  B(LdaConstant), U8(69),
-  B(Star), R(0),
-  B(LdaConstant), U8(70),
-  B(Star), R(0),
-  B(LdaConstant), U8(71),
-  B(Star), R(0),
-  B(LdaConstant), U8(72),
-  B(Star), R(0),
-  B(LdaConstant), U8(73),
-  B(Star), R(0),
-  B(LdaConstant), U8(74),
-  B(Star), R(0),
-  B(LdaConstant), U8(75),
-  B(Star), R(0),
-  B(LdaConstant), U8(76),
-  B(Star), R(0),
-  B(LdaConstant), U8(77),
-  B(Star), R(0),
-  B(LdaConstant), U8(78),
-  B(Star), R(0),
-  B(LdaConstant), U8(79),
-  B(Star), R(0),
-  B(LdaConstant), U8(80),
-  B(Star), R(0),
-  B(LdaConstant), U8(81),
-  B(Star), R(0),
-  B(LdaConstant), U8(82),
-  B(Star), R(0),
-  B(LdaConstant), U8(83),
-  B(Star), R(0),
-  B(LdaConstant), U8(84),
-  B(Star), R(0),
-  B(LdaConstant), U8(85),
-  B(Star), R(0),
-  B(LdaConstant), U8(86),
-  B(Star), R(0),
-  B(LdaConstant), U8(87),
-  B(Star), R(0),
-  B(LdaConstant), U8(88),
-  B(Star), R(0),
-  B(LdaConstant), U8(89),
-  B(Star), R(0),
-  B(LdaConstant), U8(90),
-  B(Star), R(0),
-  B(LdaConstant), U8(91),
-  B(Star), R(0),
-  B(LdaConstant), U8(92),
-  B(Star), R(0),
-  B(LdaConstant), U8(93),
-  B(Star), R(0),
-  B(LdaConstant), U8(94),
-  B(Star), R(0),
-  B(LdaConstant), U8(95),
-  B(Star), R(0),
-  B(LdaConstant), U8(96),
-  B(Star), R(0),
-  B(LdaConstant), U8(97),
-  B(Star), R(0),
-  B(LdaConstant), U8(98),
-  B(Star), R(0),
-  B(LdaConstant), U8(99),
-  B(Star), R(0),
-  B(LdaConstant), U8(100),
-  B(Star), R(0),
-  B(LdaConstant), U8(101),
-  B(Star), R(0),
-  B(LdaConstant), U8(102),
-  B(Star), R(0),
-  B(LdaConstant), U8(103),
-  B(Star), R(0),
-  B(LdaConstant), U8(104),
-  B(Star), R(0),
-  B(LdaConstant), U8(105),
-  B(Star), R(0),
-  B(LdaConstant), U8(106),
-  B(Star), R(0),
-  B(LdaConstant), U8(107),
-  B(Star), R(0),
-  B(LdaConstant), U8(108),
-  B(Star), R(0),
-  B(LdaConstant), U8(109),
-  B(Star), R(0),
-  B(LdaConstant), U8(110),
-  B(Star), R(0),
-  B(LdaConstant), U8(111),
-  B(Star), R(0),
-  B(LdaConstant), U8(112),
-  B(Star), R(0),
-  B(LdaConstant), U8(113),
-  B(Star), R(0),
-  B(LdaConstant), U8(114),
-  B(Star), R(0),
-  B(LdaConstant), U8(115),
-  B(Star), R(0),
-  B(LdaConstant), U8(116),
-  B(Star), R(0),
-  B(LdaConstant), U8(117),
-  B(Star), R(0),
-  B(LdaConstant), U8(118),
-  B(Star), R(0),
-  B(LdaConstant), U8(119),
-  B(Star), R(0),
-  B(LdaConstant), U8(120),
-  B(Star), R(0),
-  B(LdaConstant), U8(121),
-  B(Star), R(0),
-  B(LdaConstant), U8(122),
-  B(Star), R(0),
-  B(LdaConstant), U8(123),
-  B(Star), R(0),
-  B(LdaConstant), U8(124),
-  B(Star), R(0),
-  B(LdaConstant), U8(125),
-  B(Star), R(0),
-  B(LdaConstant), U8(126),
-  B(Star), R(0),
-  B(LdaConstant), U8(127),
-  B(Star), R(0),
-  B(LdaConstant), U8(128),
-  B(Star), R(0),
-  B(LdaConstant), U8(129),
-  B(Star), R(0),
-  B(LdaConstant), U8(130),
-  B(Star), R(0),
-  B(LdaConstant), U8(131),
-  B(Star), R(0),
-  B(LdaConstant), U8(132),
-  B(Star), R(0),
-  B(LdaConstant), U8(133),
-  B(Star), R(0),
-  B(LdaConstant), U8(134),
-  B(Star), R(0),
-  B(LdaConstant), U8(135),
-  B(Star), R(0),
-  B(LdaConstant), U8(136),
-  B(Star), R(0),
-  B(LdaConstant), U8(137),
-  B(Star), R(0),
-  B(LdaConstant), U8(138),
-  B(Star), R(0),
-  B(LdaConstant), U8(139),
-  B(Star), R(0),
-  B(LdaConstant), U8(140),
-  B(Star), R(0),
-  B(LdaConstant), U8(141),
-  B(Star), R(0),
-  B(LdaConstant), U8(142),
-  B(Star), R(0),
-  B(LdaConstant), U8(143),
-  B(Star), R(0),
-  B(LdaConstant), U8(144),
-  B(Star), R(0),
-  B(LdaConstant), U8(145),
-  B(Star), R(0),
-  B(LdaConstant), U8(146),
-  B(Star), R(0),
-  B(LdaConstant), U8(147),
-  B(Star), R(0),
-  B(LdaConstant), U8(148),
-  B(Star), R(0),
-  B(LdaConstant), U8(149),
-  B(Star), R(0),
-  B(LdaConstant), U8(150),
-  B(Star), R(0),
-  B(LdaConstant), U8(151),
-  B(Star), R(0),
-  B(LdaConstant), U8(152),
-  B(Star), R(0),
-  B(LdaConstant), U8(153),
-  B(Star), R(0),
-  B(LdaConstant), U8(154),
-  B(Star), R(0),
-  B(LdaConstant), U8(155),
-  B(Star), R(0),
-  B(LdaConstant), U8(156),
-  B(Star), R(0),
-  B(LdaConstant), U8(157),
-  B(Star), R(0),
-  B(LdaConstant), U8(158),
-  B(Star), R(0),
-  B(LdaConstant), U8(159),
-  B(Star), R(0),
-  B(LdaConstant), U8(160),
-  B(Star), R(0),
-  B(LdaConstant), U8(161),
-  B(Star), R(0),
-  B(LdaConstant), U8(162),
-  B(Star), R(0),
-  B(LdaConstant), U8(163),
-  B(Star), R(0),
-  B(LdaConstant), U8(164),
-  B(Star), R(0),
-  B(LdaConstant), U8(165),
-  B(Star), R(0),
-  B(LdaConstant), U8(166),
-  B(Star), R(0),
-  B(LdaConstant), U8(167),
-  B(Star), R(0),
-  B(LdaConstant), U8(168),
-  B(Star), R(0),
-  B(LdaConstant), U8(169),
-  B(Star), R(0),
-  B(LdaConstant), U8(170),
-  B(Star), R(0),
-  B(LdaConstant), U8(171),
-  B(Star), R(0),
-  B(LdaConstant), U8(172),
-  B(Star), R(0),
-  B(LdaConstant), U8(173),
-  B(Star), R(0),
-  B(LdaConstant), U8(174),
-  B(Star), R(0),
-  B(LdaConstant), U8(175),
-  B(Star), R(0),
-  B(LdaConstant), U8(176),
-  B(Star), R(0),
-  B(LdaConstant), U8(177),
-  B(Star), R(0),
-  B(LdaConstant), U8(178),
-  B(Star), R(0),
-  B(LdaConstant), U8(179),
-  B(Star), R(0),
-  B(LdaConstant), U8(180),
-  B(Star), R(0),
-  B(LdaConstant), U8(181),
-  B(Star), R(0),
-  B(LdaConstant), U8(182),
-  B(Star), R(0),
-  B(LdaConstant), U8(183),
-  B(Star), R(0),
-  B(LdaConstant), U8(184),
-  B(Star), R(0),
-  B(LdaConstant), U8(185),
-  B(Star), R(0),
-  B(LdaConstant), U8(186),
-  B(Star), R(0),
-  B(LdaConstant), U8(187),
-  B(Star), R(0),
-  B(LdaConstant), U8(188),
-  B(Star), R(0),
-  B(LdaConstant), U8(189),
-  B(Star), R(0),
-  B(LdaConstant), U8(190),
-  B(Star), R(0),
-  B(LdaConstant), U8(191),
-  B(Star), R(0),
-  B(LdaConstant), U8(192),
-  B(Star), R(0),
-  B(LdaConstant), U8(193),
-  B(Star), R(0),
-  B(LdaConstant), U8(194),
-  B(Star), R(0),
-  B(LdaConstant), U8(195),
-  B(Star), R(0),
-  B(LdaConstant), U8(196),
-  B(Star), R(0),
-  B(LdaConstant), U8(197),
-  B(Star), R(0),
-  B(LdaConstant), U8(198),
-  B(Star), R(0),
-  B(LdaConstant), U8(199),
-  B(Star), R(0),
-  B(LdaConstant), U8(200),
-  B(Star), R(0),
-  B(LdaConstant), U8(201),
-  B(Star), R(0),
-  B(LdaConstant), U8(202),
-  B(Star), R(0),
-  B(LdaConstant), U8(203),
-  B(Star), R(0),
-  B(LdaConstant), U8(204),
-  B(Star), R(0),
-  B(LdaConstant), U8(205),
-  B(Star), R(0),
-  B(LdaConstant), U8(206),
-  B(Star), R(0),
-  B(LdaConstant), U8(207),
-  B(Star), R(0),
-  B(LdaConstant), U8(208),
-  B(Star), R(0),
-  B(LdaConstant), U8(209),
-  B(Star), R(0),
-  B(LdaConstant), U8(210),
-  B(Star), R(0),
-  B(LdaConstant), U8(211),
-  B(Star), R(0),
-  B(LdaConstant), U8(212),
-  B(Star), R(0),
-  B(LdaConstant), U8(213),
-  B(Star), R(0),
-  B(LdaConstant), U8(214),
-  B(Star), R(0),
-  B(LdaConstant), U8(215),
-  B(Star), R(0),
-  B(LdaConstant), U8(216),
-  B(Star), R(0),
-  B(LdaConstant), U8(217),
-  B(Star), R(0),
-  B(LdaConstant), U8(218),
-  B(Star), R(0),
-  B(LdaConstant), U8(219),
-  B(Star), R(0),
-  B(LdaConstant), U8(220),
-  B(Star), R(0),
-  B(LdaConstant), U8(221),
-  B(Star), R(0),
-  B(LdaConstant), U8(222),
-  B(Star), R(0),
-  B(LdaConstant), U8(223),
-  B(Star), R(0),
-  B(LdaConstant), U8(224),
-  B(Star), R(0),
-  B(LdaConstant), U8(225),
-  B(Star), R(0),
-  B(LdaConstant), U8(226),
-  B(Star), R(0),
-  B(LdaConstant), U8(227),
-  B(Star), R(0),
-  B(LdaConstant), U8(228),
-  B(Star), R(0),
-  B(LdaConstant), U8(229),
-  B(Star), R(0),
-  B(LdaConstant), U8(230),
-  B(Star), R(0),
-  B(LdaConstant), U8(231),
-  B(Star), R(0),
-  B(LdaConstant), U8(232),
-  B(Star), R(0),
-  B(LdaConstant), U8(233),
-  B(Star), R(0),
-  B(LdaConstant), U8(234),
-  B(Star), R(0),
-  B(LdaConstant), U8(235),
-  B(Star), R(0),
-  B(LdaConstant), U8(236),
-  B(Star), R(0),
-  B(LdaConstant), U8(237),
-  B(Star), R(0),
-  B(LdaConstant), U8(238),
-  B(Star), R(0),
-  B(LdaConstant), U8(239),
-  B(Star), R(0),
-  B(LdaConstant), U8(240),
-  B(Star), R(0),
-  B(LdaConstant), U8(241),
-  B(Star), R(0),
-  B(LdaConstant), U8(242),
-  B(Star), R(0),
-  B(LdaConstant), U8(243),
-  B(Star), R(0),
-  B(LdaConstant), U8(244),
-  B(Star), R(0),
-  B(LdaConstant), U8(245),
-  B(Star), R(0),
-  B(LdaConstant), U8(246),
-  B(Star), R(0),
-  B(LdaConstant), U8(247),
-  B(Star), R(0),
-  B(LdaConstant), U8(248),
-  B(Star), R(0),
-  B(LdaConstant), U8(249),
-  B(Star), R(0),
-  B(LdaConstant), U8(250),
-  B(Star), R(0),
-  B(LdaConstant), U8(251),
-  B(Star), R(0),
-  B(LdaConstant), U8(252),
-  B(Star), R(0),
-  B(LdaConstant), U8(253),
-  B(Star), R(0),
-  B(LdaConstant), U8(254),
-  B(Star), R(0),
-  B(LdaConstant), U8(255),
-  B(Star), R(0),
-  B(Wide), B(CreateRegExpLiteral), U16(256), U16(0), U8(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   41 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   51 S> */ B(LdaConstant), U8(1),
+                B(Star), R(0),
+  /*   61 S> */ B(LdaConstant), U8(2),
+                B(Star), R(0),
+  /*   71 S> */ B(LdaConstant), U8(3),
+                B(Star), R(0),
+  /*   81 S> */ B(LdaConstant), U8(4),
+                B(Star), R(0),
+  /*   91 S> */ B(LdaConstant), U8(5),
+                B(Star), R(0),
+  /*  101 S> */ B(LdaConstant), U8(6),
+                B(Star), R(0),
+  /*  111 S> */ B(LdaConstant), U8(7),
+                B(Star), R(0),
+  /*  121 S> */ B(LdaConstant), U8(8),
+                B(Star), R(0),
+  /*  131 S> */ B(LdaConstant), U8(9),
+                B(Star), R(0),
+  /*  141 S> */ B(LdaConstant), U8(10),
+                B(Star), R(0),
+  /*  151 S> */ B(LdaConstant), U8(11),
+                B(Star), R(0),
+  /*  161 S> */ B(LdaConstant), U8(12),
+                B(Star), R(0),
+  /*  171 S> */ B(LdaConstant), U8(13),
+                B(Star), R(0),
+  /*  181 S> */ B(LdaConstant), U8(14),
+                B(Star), R(0),
+  /*  191 S> */ B(LdaConstant), U8(15),
+                B(Star), R(0),
+  /*  201 S> */ B(LdaConstant), U8(16),
+                B(Star), R(0),
+  /*  211 S> */ B(LdaConstant), U8(17),
+                B(Star), R(0),
+  /*  221 S> */ B(LdaConstant), U8(18),
+                B(Star), R(0),
+  /*  231 S> */ B(LdaConstant), U8(19),
+                B(Star), R(0),
+  /*  241 S> */ B(LdaConstant), U8(20),
+                B(Star), R(0),
+  /*  251 S> */ B(LdaConstant), U8(21),
+                B(Star), R(0),
+  /*  261 S> */ B(LdaConstant), U8(22),
+                B(Star), R(0),
+  /*  271 S> */ B(LdaConstant), U8(23),
+                B(Star), R(0),
+  /*  281 S> */ B(LdaConstant), U8(24),
+                B(Star), R(0),
+  /*  291 S> */ B(LdaConstant), U8(25),
+                B(Star), R(0),
+  /*  301 S> */ B(LdaConstant), U8(26),
+                B(Star), R(0),
+  /*  311 S> */ B(LdaConstant), U8(27),
+                B(Star), R(0),
+  /*  321 S> */ B(LdaConstant), U8(28),
+                B(Star), R(0),
+  /*  331 S> */ B(LdaConstant), U8(29),
+                B(Star), R(0),
+  /*  341 S> */ B(LdaConstant), U8(30),
+                B(Star), R(0),
+  /*  351 S> */ B(LdaConstant), U8(31),
+                B(Star), R(0),
+  /*  361 S> */ B(LdaConstant), U8(32),
+                B(Star), R(0),
+  /*  371 S> */ B(LdaConstant), U8(33),
+                B(Star), R(0),
+  /*  381 S> */ B(LdaConstant), U8(34),
+                B(Star), R(0),
+  /*  391 S> */ B(LdaConstant), U8(35),
+                B(Star), R(0),
+  /*  401 S> */ B(LdaConstant), U8(36),
+                B(Star), R(0),
+  /*  411 S> */ B(LdaConstant), U8(37),
+                B(Star), R(0),
+  /*  421 S> */ B(LdaConstant), U8(38),
+                B(Star), R(0),
+  /*  431 S> */ B(LdaConstant), U8(39),
+                B(Star), R(0),
+  /*  441 S> */ B(LdaConstant), U8(40),
+                B(Star), R(0),
+  /*  451 S> */ B(LdaConstant), U8(41),
+                B(Star), R(0),
+  /*  461 S> */ B(LdaConstant), U8(42),
+                B(Star), R(0),
+  /*  471 S> */ B(LdaConstant), U8(43),
+                B(Star), R(0),
+  /*  481 S> */ B(LdaConstant), U8(44),
+                B(Star), R(0),
+  /*  491 S> */ B(LdaConstant), U8(45),
+                B(Star), R(0),
+  /*  501 S> */ B(LdaConstant), U8(46),
+                B(Star), R(0),
+  /*  511 S> */ B(LdaConstant), U8(47),
+                B(Star), R(0),
+  /*  521 S> */ B(LdaConstant), U8(48),
+                B(Star), R(0),
+  /*  531 S> */ B(LdaConstant), U8(49),
+                B(Star), R(0),
+  /*  541 S> */ B(LdaConstant), U8(50),
+                B(Star), R(0),
+  /*  551 S> */ B(LdaConstant), U8(51),
+                B(Star), R(0),
+  /*  561 S> */ B(LdaConstant), U8(52),
+                B(Star), R(0),
+  /*  571 S> */ B(LdaConstant), U8(53),
+                B(Star), R(0),
+  /*  581 S> */ B(LdaConstant), U8(54),
+                B(Star), R(0),
+  /*  591 S> */ B(LdaConstant), U8(55),
+                B(Star), R(0),
+  /*  601 S> */ B(LdaConstant), U8(56),
+                B(Star), R(0),
+  /*  611 S> */ B(LdaConstant), U8(57),
+                B(Star), R(0),
+  /*  621 S> */ B(LdaConstant), U8(58),
+                B(Star), R(0),
+  /*  631 S> */ B(LdaConstant), U8(59),
+                B(Star), R(0),
+  /*  641 S> */ B(LdaConstant), U8(60),
+                B(Star), R(0),
+  /*  651 S> */ B(LdaConstant), U8(61),
+                B(Star), R(0),
+  /*  661 S> */ B(LdaConstant), U8(62),
+                B(Star), R(0),
+  /*  671 S> */ B(LdaConstant), U8(63),
+                B(Star), R(0),
+  /*  681 S> */ B(LdaConstant), U8(64),
+                B(Star), R(0),
+  /*  691 S> */ B(LdaConstant), U8(65),
+                B(Star), R(0),
+  /*  701 S> */ B(LdaConstant), U8(66),
+                B(Star), R(0),
+  /*  711 S> */ B(LdaConstant), U8(67),
+                B(Star), R(0),
+  /*  721 S> */ B(LdaConstant), U8(68),
+                B(Star), R(0),
+  /*  731 S> */ B(LdaConstant), U8(69),
+                B(Star), R(0),
+  /*  741 S> */ B(LdaConstant), U8(70),
+                B(Star), R(0),
+  /*  751 S> */ B(LdaConstant), U8(71),
+                B(Star), R(0),
+  /*  761 S> */ B(LdaConstant), U8(72),
+                B(Star), R(0),
+  /*  771 S> */ B(LdaConstant), U8(73),
+                B(Star), R(0),
+  /*  781 S> */ B(LdaConstant), U8(74),
+                B(Star), R(0),
+  /*  791 S> */ B(LdaConstant), U8(75),
+                B(Star), R(0),
+  /*  801 S> */ B(LdaConstant), U8(76),
+                B(Star), R(0),
+  /*  811 S> */ B(LdaConstant), U8(77),
+                B(Star), R(0),
+  /*  821 S> */ B(LdaConstant), U8(78),
+                B(Star), R(0),
+  /*  831 S> */ B(LdaConstant), U8(79),
+                B(Star), R(0),
+  /*  841 S> */ B(LdaConstant), U8(80),
+                B(Star), R(0),
+  /*  851 S> */ B(LdaConstant), U8(81),
+                B(Star), R(0),
+  /*  861 S> */ B(LdaConstant), U8(82),
+                B(Star), R(0),
+  /*  871 S> */ B(LdaConstant), U8(83),
+                B(Star), R(0),
+  /*  881 S> */ B(LdaConstant), U8(84),
+                B(Star), R(0),
+  /*  891 S> */ B(LdaConstant), U8(85),
+                B(Star), R(0),
+  /*  901 S> */ B(LdaConstant), U8(86),
+                B(Star), R(0),
+  /*  911 S> */ B(LdaConstant), U8(87),
+                B(Star), R(0),
+  /*  921 S> */ B(LdaConstant), U8(88),
+                B(Star), R(0),
+  /*  931 S> */ B(LdaConstant), U8(89),
+                B(Star), R(0),
+  /*  941 S> */ B(LdaConstant), U8(90),
+                B(Star), R(0),
+  /*  951 S> */ B(LdaConstant), U8(91),
+                B(Star), R(0),
+  /*  961 S> */ B(LdaConstant), U8(92),
+                B(Star), R(0),
+  /*  971 S> */ B(LdaConstant), U8(93),
+                B(Star), R(0),
+  /*  981 S> */ B(LdaConstant), U8(94),
+                B(Star), R(0),
+  /*  991 S> */ B(LdaConstant), U8(95),
+                B(Star), R(0),
+  /* 1001 S> */ B(LdaConstant), U8(96),
+                B(Star), R(0),
+  /* 1011 S> */ B(LdaConstant), U8(97),
+                B(Star), R(0),
+  /* 1021 S> */ B(LdaConstant), U8(98),
+                B(Star), R(0),
+  /* 1031 S> */ B(LdaConstant), U8(99),
+                B(Star), R(0),
+  /* 1041 S> */ B(LdaConstant), U8(100),
+                B(Star), R(0),
+  /* 1051 S> */ B(LdaConstant), U8(101),
+                B(Star), R(0),
+  /* 1061 S> */ B(LdaConstant), U8(102),
+                B(Star), R(0),
+  /* 1071 S> */ B(LdaConstant), U8(103),
+                B(Star), R(0),
+  /* 1081 S> */ B(LdaConstant), U8(104),
+                B(Star), R(0),
+  /* 1091 S> */ B(LdaConstant), U8(105),
+                B(Star), R(0),
+  /* 1101 S> */ B(LdaConstant), U8(106),
+                B(Star), R(0),
+  /* 1111 S> */ B(LdaConstant), U8(107),
+                B(Star), R(0),
+  /* 1121 S> */ B(LdaConstant), U8(108),
+                B(Star), R(0),
+  /* 1131 S> */ B(LdaConstant), U8(109),
+                B(Star), R(0),
+  /* 1141 S> */ B(LdaConstant), U8(110),
+                B(Star), R(0),
+  /* 1151 S> */ B(LdaConstant), U8(111),
+                B(Star), R(0),
+  /* 1161 S> */ B(LdaConstant), U8(112),
+                B(Star), R(0),
+  /* 1171 S> */ B(LdaConstant), U8(113),
+                B(Star), R(0),
+  /* 1181 S> */ B(LdaConstant), U8(114),
+                B(Star), R(0),
+  /* 1191 S> */ B(LdaConstant), U8(115),
+                B(Star), R(0),
+  /* 1201 S> */ B(LdaConstant), U8(116),
+                B(Star), R(0),
+  /* 1211 S> */ B(LdaConstant), U8(117),
+                B(Star), R(0),
+  /* 1221 S> */ B(LdaConstant), U8(118),
+                B(Star), R(0),
+  /* 1231 S> */ B(LdaConstant), U8(119),
+                B(Star), R(0),
+  /* 1241 S> */ B(LdaConstant), U8(120),
+                B(Star), R(0),
+  /* 1251 S> */ B(LdaConstant), U8(121),
+                B(Star), R(0),
+  /* 1261 S> */ B(LdaConstant), U8(122),
+                B(Star), R(0),
+  /* 1271 S> */ B(LdaConstant), U8(123),
+                B(Star), R(0),
+  /* 1281 S> */ B(LdaConstant), U8(124),
+                B(Star), R(0),
+  /* 1291 S> */ B(LdaConstant), U8(125),
+                B(Star), R(0),
+  /* 1301 S> */ B(LdaConstant), U8(126),
+                B(Star), R(0),
+  /* 1311 S> */ B(LdaConstant), U8(127),
+                B(Star), R(0),
+  /* 1321 S> */ B(LdaConstant), U8(128),
+                B(Star), R(0),
+  /* 1331 S> */ B(LdaConstant), U8(129),
+                B(Star), R(0),
+  /* 1341 S> */ B(LdaConstant), U8(130),
+                B(Star), R(0),
+  /* 1351 S> */ B(LdaConstant), U8(131),
+                B(Star), R(0),
+  /* 1361 S> */ B(LdaConstant), U8(132),
+                B(Star), R(0),
+  /* 1371 S> */ B(LdaConstant), U8(133),
+                B(Star), R(0),
+  /* 1381 S> */ B(LdaConstant), U8(134),
+                B(Star), R(0),
+  /* 1391 S> */ B(LdaConstant), U8(135),
+                B(Star), R(0),
+  /* 1401 S> */ B(LdaConstant), U8(136),
+                B(Star), R(0),
+  /* 1411 S> */ B(LdaConstant), U8(137),
+                B(Star), R(0),
+  /* 1421 S> */ B(LdaConstant), U8(138),
+                B(Star), R(0),
+  /* 1431 S> */ B(LdaConstant), U8(139),
+                B(Star), R(0),
+  /* 1441 S> */ B(LdaConstant), U8(140),
+                B(Star), R(0),
+  /* 1451 S> */ B(LdaConstant), U8(141),
+                B(Star), R(0),
+  /* 1461 S> */ B(LdaConstant), U8(142),
+                B(Star), R(0),
+  /* 1471 S> */ B(LdaConstant), U8(143),
+                B(Star), R(0),
+  /* 1481 S> */ B(LdaConstant), U8(144),
+                B(Star), R(0),
+  /* 1491 S> */ B(LdaConstant), U8(145),
+                B(Star), R(0),
+  /* 1501 S> */ B(LdaConstant), U8(146),
+                B(Star), R(0),
+  /* 1511 S> */ B(LdaConstant), U8(147),
+                B(Star), R(0),
+  /* 1521 S> */ B(LdaConstant), U8(148),
+                B(Star), R(0),
+  /* 1531 S> */ B(LdaConstant), U8(149),
+                B(Star), R(0),
+  /* 1541 S> */ B(LdaConstant), U8(150),
+                B(Star), R(0),
+  /* 1551 S> */ B(LdaConstant), U8(151),
+                B(Star), R(0),
+  /* 1561 S> */ B(LdaConstant), U8(152),
+                B(Star), R(0),
+  /* 1571 S> */ B(LdaConstant), U8(153),
+                B(Star), R(0),
+  /* 1581 S> */ B(LdaConstant), U8(154),
+                B(Star), R(0),
+  /* 1591 S> */ B(LdaConstant), U8(155),
+                B(Star), R(0),
+  /* 1601 S> */ B(LdaConstant), U8(156),
+                B(Star), R(0),
+  /* 1611 S> */ B(LdaConstant), U8(157),
+                B(Star), R(0),
+  /* 1621 S> */ B(LdaConstant), U8(158),
+                B(Star), R(0),
+  /* 1631 S> */ B(LdaConstant), U8(159),
+                B(Star), R(0),
+  /* 1641 S> */ B(LdaConstant), U8(160),
+                B(Star), R(0),
+  /* 1651 S> */ B(LdaConstant), U8(161),
+                B(Star), R(0),
+  /* 1661 S> */ B(LdaConstant), U8(162),
+                B(Star), R(0),
+  /* 1671 S> */ B(LdaConstant), U8(163),
+                B(Star), R(0),
+  /* 1681 S> */ B(LdaConstant), U8(164),
+                B(Star), R(0),
+  /* 1691 S> */ B(LdaConstant), U8(165),
+                B(Star), R(0),
+  /* 1701 S> */ B(LdaConstant), U8(166),
+                B(Star), R(0),
+  /* 1711 S> */ B(LdaConstant), U8(167),
+                B(Star), R(0),
+  /* 1721 S> */ B(LdaConstant), U8(168),
+                B(Star), R(0),
+  /* 1731 S> */ B(LdaConstant), U8(169),
+                B(Star), R(0),
+  /* 1741 S> */ B(LdaConstant), U8(170),
+                B(Star), R(0),
+  /* 1751 S> */ B(LdaConstant), U8(171),
+                B(Star), R(0),
+  /* 1761 S> */ B(LdaConstant), U8(172),
+                B(Star), R(0),
+  /* 1771 S> */ B(LdaConstant), U8(173),
+                B(Star), R(0),
+  /* 1781 S> */ B(LdaConstant), U8(174),
+                B(Star), R(0),
+  /* 1791 S> */ B(LdaConstant), U8(175),
+                B(Star), R(0),
+  /* 1801 S> */ B(LdaConstant), U8(176),
+                B(Star), R(0),
+  /* 1811 S> */ B(LdaConstant), U8(177),
+                B(Star), R(0),
+  /* 1821 S> */ B(LdaConstant), U8(178),
+                B(Star), R(0),
+  /* 1831 S> */ B(LdaConstant), U8(179),
+                B(Star), R(0),
+  /* 1841 S> */ B(LdaConstant), U8(180),
+                B(Star), R(0),
+  /* 1851 S> */ B(LdaConstant), U8(181),
+                B(Star), R(0),
+  /* 1861 S> */ B(LdaConstant), U8(182),
+                B(Star), R(0),
+  /* 1871 S> */ B(LdaConstant), U8(183),
+                B(Star), R(0),
+  /* 1881 S> */ B(LdaConstant), U8(184),
+                B(Star), R(0),
+  /* 1891 S> */ B(LdaConstant), U8(185),
+                B(Star), R(0),
+  /* 1901 S> */ B(LdaConstant), U8(186),
+                B(Star), R(0),
+  /* 1911 S> */ B(LdaConstant), U8(187),
+                B(Star), R(0),
+  /* 1921 S> */ B(LdaConstant), U8(188),
+                B(Star), R(0),
+  /* 1931 S> */ B(LdaConstant), U8(189),
+                B(Star), R(0),
+  /* 1941 S> */ B(LdaConstant), U8(190),
+                B(Star), R(0),
+  /* 1951 S> */ B(LdaConstant), U8(191),
+                B(Star), R(0),
+  /* 1961 S> */ B(LdaConstant), U8(192),
+                B(Star), R(0),
+  /* 1971 S> */ B(LdaConstant), U8(193),
+                B(Star), R(0),
+  /* 1981 S> */ B(LdaConstant), U8(194),
+                B(Star), R(0),
+  /* 1991 S> */ B(LdaConstant), U8(195),
+                B(Star), R(0),
+  /* 2001 S> */ B(LdaConstant), U8(196),
+                B(Star), R(0),
+  /* 2011 S> */ B(LdaConstant), U8(197),
+                B(Star), R(0),
+  /* 2021 S> */ B(LdaConstant), U8(198),
+                B(Star), R(0),
+  /* 2031 S> */ B(LdaConstant), U8(199),
+                B(Star), R(0),
+  /* 2041 S> */ B(LdaConstant), U8(200),
+                B(Star), R(0),
+  /* 2051 S> */ B(LdaConstant), U8(201),
+                B(Star), R(0),
+  /* 2061 S> */ B(LdaConstant), U8(202),
+                B(Star), R(0),
+  /* 2071 S> */ B(LdaConstant), U8(203),
+                B(Star), R(0),
+  /* 2081 S> */ B(LdaConstant), U8(204),
+                B(Star), R(0),
+  /* 2091 S> */ B(LdaConstant), U8(205),
+                B(Star), R(0),
+  /* 2101 S> */ B(LdaConstant), U8(206),
+                B(Star), R(0),
+  /* 2111 S> */ B(LdaConstant), U8(207),
+                B(Star), R(0),
+  /* 2121 S> */ B(LdaConstant), U8(208),
+                B(Star), R(0),
+  /* 2131 S> */ B(LdaConstant), U8(209),
+                B(Star), R(0),
+  /* 2141 S> */ B(LdaConstant), U8(210),
+                B(Star), R(0),
+  /* 2151 S> */ B(LdaConstant), U8(211),
+                B(Star), R(0),
+  /* 2161 S> */ B(LdaConstant), U8(212),
+                B(Star), R(0),
+  /* 2171 S> */ B(LdaConstant), U8(213),
+                B(Star), R(0),
+  /* 2181 S> */ B(LdaConstant), U8(214),
+                B(Star), R(0),
+  /* 2191 S> */ B(LdaConstant), U8(215),
+                B(Star), R(0),
+  /* 2201 S> */ B(LdaConstant), U8(216),
+                B(Star), R(0),
+  /* 2211 S> */ B(LdaConstant), U8(217),
+                B(Star), R(0),
+  /* 2221 S> */ B(LdaConstant), U8(218),
+                B(Star), R(0),
+  /* 2231 S> */ B(LdaConstant), U8(219),
+                B(Star), R(0),
+  /* 2241 S> */ B(LdaConstant), U8(220),
+                B(Star), R(0),
+  /* 2251 S> */ B(LdaConstant), U8(221),
+                B(Star), R(0),
+  /* 2261 S> */ B(LdaConstant), U8(222),
+                B(Star), R(0),
+  /* 2271 S> */ B(LdaConstant), U8(223),
+                B(Star), R(0),
+  /* 2281 S> */ B(LdaConstant), U8(224),
+                B(Star), R(0),
+  /* 2291 S> */ B(LdaConstant), U8(225),
+                B(Star), R(0),
+  /* 2301 S> */ B(LdaConstant), U8(226),
+                B(Star), R(0),
+  /* 2311 S> */ B(LdaConstant), U8(227),
+                B(Star), R(0),
+  /* 2321 S> */ B(LdaConstant), U8(228),
+                B(Star), R(0),
+  /* 2331 S> */ B(LdaConstant), U8(229),
+                B(Star), R(0),
+  /* 2341 S> */ B(LdaConstant), U8(230),
+                B(Star), R(0),
+  /* 2351 S> */ B(LdaConstant), U8(231),
+                B(Star), R(0),
+  /* 2361 S> */ B(LdaConstant), U8(232),
+                B(Star), R(0),
+  /* 2371 S> */ B(LdaConstant), U8(233),
+                B(Star), R(0),
+  /* 2381 S> */ B(LdaConstant), U8(234),
+                B(Star), R(0),
+  /* 2391 S> */ B(LdaConstant), U8(235),
+                B(Star), R(0),
+  /* 2401 S> */ B(LdaConstant), U8(236),
+                B(Star), R(0),
+  /* 2411 S> */ B(LdaConstant), U8(237),
+                B(Star), R(0),
+  /* 2421 S> */ B(LdaConstant), U8(238),
+                B(Star), R(0),
+  /* 2431 S> */ B(LdaConstant), U8(239),
+                B(Star), R(0),
+  /* 2441 S> */ B(LdaConstant), U8(240),
+                B(Star), R(0),
+  /* 2451 S> */ B(LdaConstant), U8(241),
+                B(Star), R(0),
+  /* 2461 S> */ B(LdaConstant), U8(242),
+                B(Star), R(0),
+  /* 2471 S> */ B(LdaConstant), U8(243),
+                B(Star), R(0),
+  /* 2481 S> */ B(LdaConstant), U8(244),
+                B(Star), R(0),
+  /* 2491 S> */ B(LdaConstant), U8(245),
+                B(Star), R(0),
+  /* 2501 S> */ B(LdaConstant), U8(246),
+                B(Star), R(0),
+  /* 2511 S> */ B(LdaConstant), U8(247),
+                B(Star), R(0),
+  /* 2521 S> */ B(LdaConstant), U8(248),
+                B(Star), R(0),
+  /* 2531 S> */ B(LdaConstant), U8(249),
+                B(Star), R(0),
+  /* 2541 S> */ B(LdaConstant), U8(250),
+                B(Star), R(0),
+  /* 2551 S> */ B(LdaConstant), U8(251),
+                B(Star), R(0),
+  /* 2561 S> */ B(LdaConstant), U8(252),
+                B(Star), R(0),
+  /* 2571 S> */ B(LdaConstant), U8(253),
+                B(Star), R(0),
+  /* 2581 S> */ B(LdaConstant), U8(254),
+                B(Star), R(0),
+  /* 2591 S> */ B(LdaConstant), U8(255),
+                B(Star), R(0),
+  /* 2601 S> */ B(Wide), B(CreateRegExpLiteral), U16(256), U16(0), U8(0),
+  /* 2616 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::HEAP_NUMBER_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/RemoveRedundantLdar.golden b/test/cctest/interpreter/bytecode_expectations/RemoveRedundantLdar.golden
index e9283cd..d96a3bc 100644
--- a/test/cctest/interpreter/bytecode_expectations/RemoveRedundantLdar.golden
+++ b/test/cctest/interpreter/bytecode_expectations/RemoveRedundantLdar.golden
@@ -16,27 +16,24 @@
   }
   return ld_a;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 31
+bytecode array length: 25
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Add), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(10),
-  B(TestGreaterThan), R(1),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(4),
-  B(Jump), U8(-21),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   45 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   48 E> */ B(StackCheck),
+  /*   64 S> */ B(Ldar), R(0),
+  /*   78 E> */ B(Add), R(0),
+                B(Star), R(0),
+  /*   86 S> */ B(LdaSmi), U8(10),
+  /*   95 E> */ B(TestGreaterThan), R(0),
+                B(JumpIfFalse), U8(4),
+  /*  101 S> */ B(Jump), U8(4),
+                B(Jump), U8(-15),
+  /*  110 S> */ B(Ldar), R(0),
+  /*  123 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -52,26 +49,23 @@
   } while(false);
   return ld_a;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 29
+bytecode array length: 23
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Add), R(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(10),
-  B(TestGreaterThan), R(1),
-  B(JumpIfFalse), U8(4),
-  B(Jump), U8(2),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   45 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   48 E> */ B(StackCheck),
+  /*   55 S> */ B(Ldar), R(0),
+  /*   69 E> */ B(Add), R(0),
+                B(Star), R(0),
+  /*   77 S> */ B(LdaSmi), U8(10),
+  /*   86 E> */ B(TestGreaterThan), R(0),
+                B(JumpIfFalse), U8(4),
+  /*   92 S> */ B(Jump), U8(2),
+  /*  118 S> */ B(Ldar), R(0),
+  /*  131 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -84,18 +78,18 @@
     ld_a = ld_a + ld_a;
     return ld_a;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 14
+bytecode array length: 12
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(Add), R(1),
-  B(Star), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   45 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   50 S> */ B(Nop),
+  /*   64 E> */ B(Add), R(0),
+                B(Star), R(0),
+  /*   72 S> */ B(Nop),
+  /*   85 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/StoreGlobal.golden b/test/cctest/interpreter/bytecode_expectations/StoreGlobal.golden
index 151c334..5cc49b2 100644
--- a/test/cctest/interpreter/bytecode_expectations/StoreGlobal.golden
+++ b/test/cctest/interpreter/bytecode_expectations/StoreGlobal.golden
@@ -18,11 +18,11 @@
 parameter count: 1
 bytecode array length: 8
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(2),
-  B(StaGlobalSloppy), U8(0), U8(1),
-  B(LdaUndefined),
-  B(Return),
+  /*   21 E> */ B(StackCheck),
+  /*   26 S> */ B(LdaSmi), U8(2),
+  /*   28 E> */ B(StaGlobalSloppy), U8(0), U8(1),
+                B(LdaUndefined),
+  /*   33 S> */ B(Return),
 ]
 constant pool: [
   "a",
@@ -39,11 +39,11 @@
 parameter count: 2
 bytecode array length: 8
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(StaGlobalSloppy), U8(0), U8(1),
-  B(LdaUndefined),
-  B(Return),
+  /*   26 E> */ B(StackCheck),
+  /*   32 S> */ B(Ldar), R(arg0),
+  /*   34 E> */ B(StaGlobalSloppy), U8(0), U8(1),
+                B(LdaUndefined),
+  /*   39 S> */ B(Return),
 ]
 constant pool: [
   "a",
@@ -61,11 +61,11 @@
 parameter count: 1
 bytecode array length: 8
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(2),
-  B(StaGlobalStrict), U8(0), U8(1),
-  B(LdaUndefined),
-  B(Return),
+  /*   35 E> */ B(StackCheck),
+  /*   40 S> */ B(LdaSmi), U8(2),
+  /*   42 E> */ B(StaGlobalStrict), U8(0), U8(1),
+                B(LdaUndefined),
+  /*   47 S> */ B(Return),
 ]
 constant pool: [
   "a",
@@ -83,11 +83,11 @@
 parameter count: 1
 bytecode array length: 8
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(2),
-  B(StaGlobalSloppy), U8(0), U8(1),
-  B(LdaUndefined),
-  B(Return),
+  /*   17 E> */ B(StackCheck),
+  /*   22 S> */ B(LdaSmi), U8(2),
+  /*   24 E> */ B(StaGlobalSloppy), U8(0), U8(1),
+                B(LdaUndefined),
+  /*   29 S> */ B(Return),
 ]
 constant pool: [
   "a",
@@ -231,399 +231,271 @@
   }
   f({name: 1});
 "
-frame size: 1
+frame size: 0
 parameter count: 2
-bytecode array length: 1035
+bytecode array length: 651
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(1),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(3),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(5),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(7),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(9),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(11),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(13),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(15),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(17),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(19),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(21),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(23),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(25),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(27),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(29),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(31),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(33),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(35),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(37),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(39),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(41),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(43),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(45),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(47),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(49),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(51),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(53),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(55),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(57),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(59),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(61),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(63),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(65),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(67),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(69),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(71),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(73),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(75),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(77),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(79),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(81),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(83),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(85),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(87),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(89),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(91),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(93),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(95),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(97),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(99),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(101),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(103),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(105),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(107),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(109),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(111),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(113),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(115),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(117),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(119),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(121),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(123),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(125),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(127),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(129),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(131),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(133),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(135),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(137),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(139),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(141),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(143),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(145),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(147),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(149),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(151),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(153),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(155),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(157),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(159),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(161),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(163),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(165),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(167),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(169),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(171),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(173),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(175),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(177),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(179),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(181),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(183),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(185),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(187),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(189),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(191),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(193),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(195),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(197),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(199),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(201),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(203),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(205),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(207),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(209),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(211),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(213),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(215),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(217),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(219),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(221),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(223),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(225),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(227),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(229),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(231),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(233),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(235),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(237),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(239),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(241),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(243),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(245),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(247),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(249),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(251),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(253),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(255),
-  B(LdaSmi), U8(2),
-  B(Wide), B(StaGlobalSloppy), U16(1), U16(257),
-  B(LdaUndefined),
-  B(Return),
+  /*   17 E> */ B(StackCheck),
+  /*   25 S> */ B(Nop),
+  /*   26 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(1),
+  /*   35 S> */ B(Nop),
+  /*   36 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(3),
+  /*   45 S> */ B(Nop),
+  /*   46 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(5),
+  /*   55 S> */ B(Nop),
+  /*   56 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(7),
+  /*   65 S> */ B(Nop),
+  /*   66 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(9),
+  /*   75 S> */ B(Nop),
+  /*   76 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(11),
+  /*   85 S> */ B(Nop),
+  /*   86 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(13),
+  /*   95 S> */ B(Nop),
+  /*   96 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(15),
+  /*  105 S> */ B(Nop),
+  /*  106 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(17),
+  /*  115 S> */ B(Nop),
+  /*  116 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(19),
+  /*  125 S> */ B(Nop),
+  /*  126 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(21),
+  /*  135 S> */ B(Nop),
+  /*  136 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(23),
+  /*  145 S> */ B(Nop),
+  /*  146 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(25),
+  /*  155 S> */ B(Nop),
+  /*  156 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(27),
+  /*  165 S> */ B(Nop),
+  /*  166 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(29),
+  /*  175 S> */ B(Nop),
+  /*  176 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(31),
+  /*  185 S> */ B(Nop),
+  /*  186 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(33),
+  /*  195 S> */ B(Nop),
+  /*  196 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(35),
+  /*  205 S> */ B(Nop),
+  /*  206 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(37),
+  /*  215 S> */ B(Nop),
+  /*  216 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(39),
+  /*  225 S> */ B(Nop),
+  /*  226 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(41),
+  /*  235 S> */ B(Nop),
+  /*  236 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(43),
+  /*  245 S> */ B(Nop),
+  /*  246 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(45),
+  /*  255 S> */ B(Nop),
+  /*  256 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(47),
+  /*  265 S> */ B(Nop),
+  /*  266 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(49),
+  /*  275 S> */ B(Nop),
+  /*  276 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(51),
+  /*  285 S> */ B(Nop),
+  /*  286 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(53),
+  /*  295 S> */ B(Nop),
+  /*  296 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(55),
+  /*  305 S> */ B(Nop),
+  /*  306 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(57),
+  /*  315 S> */ B(Nop),
+  /*  316 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(59),
+  /*  325 S> */ B(Nop),
+  /*  326 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(61),
+  /*  335 S> */ B(Nop),
+  /*  336 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(63),
+  /*  345 S> */ B(Nop),
+  /*  346 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(65),
+  /*  355 S> */ B(Nop),
+  /*  356 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(67),
+  /*  365 S> */ B(Nop),
+  /*  366 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(69),
+  /*  375 S> */ B(Nop),
+  /*  376 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(71),
+  /*  385 S> */ B(Nop),
+  /*  386 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(73),
+  /*  395 S> */ B(Nop),
+  /*  396 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(75),
+  /*  405 S> */ B(Nop),
+  /*  406 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(77),
+  /*  415 S> */ B(Nop),
+  /*  416 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(79),
+  /*  425 S> */ B(Nop),
+  /*  426 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(81),
+  /*  435 S> */ B(Nop),
+  /*  436 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(83),
+  /*  445 S> */ B(Nop),
+  /*  446 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(85),
+  /*  455 S> */ B(Nop),
+  /*  456 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(87),
+  /*  465 S> */ B(Nop),
+  /*  466 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(89),
+  /*  475 S> */ B(Nop),
+  /*  476 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(91),
+  /*  485 S> */ B(Nop),
+  /*  486 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(93),
+  /*  495 S> */ B(Nop),
+  /*  496 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(95),
+  /*  505 S> */ B(Nop),
+  /*  506 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(97),
+  /*  515 S> */ B(Nop),
+  /*  516 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(99),
+  /*  525 S> */ B(Nop),
+  /*  526 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(101),
+  /*  535 S> */ B(Nop),
+  /*  536 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(103),
+  /*  545 S> */ B(Nop),
+  /*  546 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(105),
+  /*  555 S> */ B(Nop),
+  /*  556 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(107),
+  /*  565 S> */ B(Nop),
+  /*  566 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(109),
+  /*  575 S> */ B(Nop),
+  /*  576 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(111),
+  /*  585 S> */ B(Nop),
+  /*  586 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(113),
+  /*  595 S> */ B(Nop),
+  /*  596 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(115),
+  /*  605 S> */ B(Nop),
+  /*  606 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(117),
+  /*  615 S> */ B(Nop),
+  /*  616 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(119),
+  /*  625 S> */ B(Nop),
+  /*  626 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(121),
+  /*  635 S> */ B(Nop),
+  /*  636 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(123),
+  /*  645 S> */ B(Nop),
+  /*  646 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(125),
+  /*  655 S> */ B(Nop),
+  /*  656 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(127),
+  /*  665 S> */ B(Nop),
+  /*  666 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(129),
+  /*  675 S> */ B(Nop),
+  /*  676 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(131),
+  /*  685 S> */ B(Nop),
+  /*  686 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(133),
+  /*  695 S> */ B(Nop),
+  /*  696 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(135),
+  /*  705 S> */ B(Nop),
+  /*  706 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(137),
+  /*  715 S> */ B(Nop),
+  /*  716 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(139),
+  /*  725 S> */ B(Nop),
+  /*  726 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(141),
+  /*  735 S> */ B(Nop),
+  /*  736 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(143),
+  /*  745 S> */ B(Nop),
+  /*  746 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(145),
+  /*  755 S> */ B(Nop),
+  /*  756 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(147),
+  /*  765 S> */ B(Nop),
+  /*  766 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(149),
+  /*  775 S> */ B(Nop),
+  /*  776 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(151),
+  /*  785 S> */ B(Nop),
+  /*  786 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(153),
+  /*  795 S> */ B(Nop),
+  /*  796 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(155),
+  /*  805 S> */ B(Nop),
+  /*  806 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(157),
+  /*  815 S> */ B(Nop),
+  /*  816 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(159),
+  /*  825 S> */ B(Nop),
+  /*  826 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(161),
+  /*  835 S> */ B(Nop),
+  /*  836 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(163),
+  /*  845 S> */ B(Nop),
+  /*  846 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(165),
+  /*  855 S> */ B(Nop),
+  /*  856 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(167),
+  /*  865 S> */ B(Nop),
+  /*  866 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(169),
+  /*  875 S> */ B(Nop),
+  /*  876 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(171),
+  /*  885 S> */ B(Nop),
+  /*  886 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(173),
+  /*  895 S> */ B(Nop),
+  /*  896 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(175),
+  /*  905 S> */ B(Nop),
+  /*  906 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(177),
+  /*  915 S> */ B(Nop),
+  /*  916 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(179),
+  /*  925 S> */ B(Nop),
+  /*  926 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(181),
+  /*  935 S> */ B(Nop),
+  /*  936 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(183),
+  /*  945 S> */ B(Nop),
+  /*  946 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(185),
+  /*  955 S> */ B(Nop),
+  /*  956 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(187),
+  /*  965 S> */ B(Nop),
+  /*  966 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(189),
+  /*  975 S> */ B(Nop),
+  /*  976 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(191),
+  /*  985 S> */ B(Nop),
+  /*  986 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(193),
+  /*  995 S> */ B(Nop),
+  /*  996 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(195),
+  /* 1005 S> */ B(Nop),
+  /* 1006 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(197),
+  /* 1015 S> */ B(Nop),
+  /* 1016 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(199),
+  /* 1025 S> */ B(Nop),
+  /* 1026 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(201),
+  /* 1035 S> */ B(Nop),
+  /* 1036 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(203),
+  /* 1045 S> */ B(Nop),
+  /* 1046 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(205),
+  /* 1055 S> */ B(Nop),
+  /* 1056 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(207),
+  /* 1065 S> */ B(Nop),
+  /* 1066 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(209),
+  /* 1075 S> */ B(Nop),
+  /* 1076 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(211),
+  /* 1085 S> */ B(Nop),
+  /* 1086 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(213),
+  /* 1095 S> */ B(Nop),
+  /* 1096 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(215),
+  /* 1105 S> */ B(Nop),
+  /* 1106 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(217),
+  /* 1115 S> */ B(Nop),
+  /* 1116 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(219),
+  /* 1125 S> */ B(Nop),
+  /* 1126 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(221),
+  /* 1135 S> */ B(Nop),
+  /* 1136 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(223),
+  /* 1145 S> */ B(Nop),
+  /* 1146 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(225),
+  /* 1155 S> */ B(Nop),
+  /* 1156 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(227),
+  /* 1165 S> */ B(Nop),
+  /* 1166 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(229),
+  /* 1175 S> */ B(Nop),
+  /* 1176 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(231),
+  /* 1185 S> */ B(Nop),
+  /* 1186 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(233),
+  /* 1195 S> */ B(Nop),
+  /* 1196 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(235),
+  /* 1205 S> */ B(Nop),
+  /* 1206 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(237),
+  /* 1215 S> */ B(Nop),
+  /* 1216 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(239),
+  /* 1225 S> */ B(Nop),
+  /* 1226 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(241),
+  /* 1235 S> */ B(Nop),
+  /* 1236 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(243),
+  /* 1245 S> */ B(Nop),
+  /* 1246 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(245),
+  /* 1255 S> */ B(Nop),
+  /* 1256 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(247),
+  /* 1265 S> */ B(Nop),
+  /* 1266 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(249),
+  /* 1275 S> */ B(Nop),
+  /* 1276 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(251),
+  /* 1285 S> */ B(Nop),
+  /* 1286 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(253),
+  /* 1295 S> */ B(Nop),
+  /* 1296 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(255),
+  /* 1305 S> */ B(LdaSmi), U8(2),
+  /* 1307 E> */ B(Wide), B(StaGlobalSloppy), U16(1), U16(257),
+                B(LdaUndefined),
+  /* 1312 S> */ B(Return),
 ]
 constant pool: [
   "name",
@@ -769,399 +641,271 @@
   }
   f({name: 1});
 "
-frame size: 1
+frame size: 0
 parameter count: 2
-bytecode array length: 1035
+bytecode array length: 651
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(1),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(3),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(5),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(7),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(9),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(11),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(13),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(15),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(17),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(19),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(21),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(23),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(25),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(27),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(29),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(31),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(33),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(35),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(37),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(39),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(41),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(43),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(45),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(47),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(49),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(51),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(53),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(55),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(57),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(59),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(61),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(63),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(65),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(67),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(69),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(71),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(73),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(75),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(77),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(79),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(81),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(83),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(85),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(87),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(89),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(91),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(93),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(95),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(97),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(99),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(101),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(103),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(105),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(107),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(109),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(111),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(113),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(115),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(117),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(119),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(121),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(123),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(125),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(127),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(129),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(131),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(133),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(135),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(137),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(139),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(141),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(143),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(145),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(147),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(149),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(151),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(153),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(155),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(157),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(159),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(161),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(163),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(165),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(167),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(169),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(171),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(173),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(175),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(177),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(179),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(181),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(183),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(185),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(187),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(189),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(191),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(193),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(195),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(197),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(199),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(201),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(203),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(205),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(207),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(209),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(211),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(213),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(215),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(217),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(219),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(221),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(223),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(225),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(227),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(229),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(231),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(233),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(235),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(237),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(239),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(241),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(243),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(245),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(247),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(249),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(251),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(253),
-  B(Ldar), R(arg0),
-  B(Star), R(0),
-  B(LoadIC), R(0), U8(0), U8(255),
-  B(LdaSmi), U8(2),
-  B(Wide), B(StaGlobalStrict), U16(1), U16(257),
-  B(LdaUndefined),
-  B(Return),
+  /*   17 E> */ B(StackCheck),
+  /*   41 S> */ B(Nop),
+  /*   42 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(1),
+  /*   51 S> */ B(Nop),
+  /*   52 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(3),
+  /*   61 S> */ B(Nop),
+  /*   62 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(5),
+  /*   71 S> */ B(Nop),
+  /*   72 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(7),
+  /*   81 S> */ B(Nop),
+  /*   82 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(9),
+  /*   91 S> */ B(Nop),
+  /*   92 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(11),
+  /*  101 S> */ B(Nop),
+  /*  102 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(13),
+  /*  111 S> */ B(Nop),
+  /*  112 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(15),
+  /*  121 S> */ B(Nop),
+  /*  122 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(17),
+  /*  131 S> */ B(Nop),
+  /*  132 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(19),
+  /*  141 S> */ B(Nop),
+  /*  142 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(21),
+  /*  151 S> */ B(Nop),
+  /*  152 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(23),
+  /*  161 S> */ B(Nop),
+  /*  162 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(25),
+  /*  171 S> */ B(Nop),
+  /*  172 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(27),
+  /*  181 S> */ B(Nop),
+  /*  182 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(29),
+  /*  191 S> */ B(Nop),
+  /*  192 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(31),
+  /*  201 S> */ B(Nop),
+  /*  202 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(33),
+  /*  211 S> */ B(Nop),
+  /*  212 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(35),
+  /*  221 S> */ B(Nop),
+  /*  222 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(37),
+  /*  231 S> */ B(Nop),
+  /*  232 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(39),
+  /*  241 S> */ B(Nop),
+  /*  242 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(41),
+  /*  251 S> */ B(Nop),
+  /*  252 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(43),
+  /*  261 S> */ B(Nop),
+  /*  262 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(45),
+  /*  271 S> */ B(Nop),
+  /*  272 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(47),
+  /*  281 S> */ B(Nop),
+  /*  282 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(49),
+  /*  291 S> */ B(Nop),
+  /*  292 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(51),
+  /*  301 S> */ B(Nop),
+  /*  302 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(53),
+  /*  311 S> */ B(Nop),
+  /*  312 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(55),
+  /*  321 S> */ B(Nop),
+  /*  322 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(57),
+  /*  331 S> */ B(Nop),
+  /*  332 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(59),
+  /*  341 S> */ B(Nop),
+  /*  342 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(61),
+  /*  351 S> */ B(Nop),
+  /*  352 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(63),
+  /*  361 S> */ B(Nop),
+  /*  362 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(65),
+  /*  371 S> */ B(Nop),
+  /*  372 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(67),
+  /*  381 S> */ B(Nop),
+  /*  382 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(69),
+  /*  391 S> */ B(Nop),
+  /*  392 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(71),
+  /*  401 S> */ B(Nop),
+  /*  402 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(73),
+  /*  411 S> */ B(Nop),
+  /*  412 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(75),
+  /*  421 S> */ B(Nop),
+  /*  422 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(77),
+  /*  431 S> */ B(Nop),
+  /*  432 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(79),
+  /*  441 S> */ B(Nop),
+  /*  442 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(81),
+  /*  451 S> */ B(Nop),
+  /*  452 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(83),
+  /*  461 S> */ B(Nop),
+  /*  462 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(85),
+  /*  471 S> */ B(Nop),
+  /*  472 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(87),
+  /*  481 S> */ B(Nop),
+  /*  482 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(89),
+  /*  491 S> */ B(Nop),
+  /*  492 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(91),
+  /*  501 S> */ B(Nop),
+  /*  502 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(93),
+  /*  511 S> */ B(Nop),
+  /*  512 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(95),
+  /*  521 S> */ B(Nop),
+  /*  522 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(97),
+  /*  531 S> */ B(Nop),
+  /*  532 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(99),
+  /*  541 S> */ B(Nop),
+  /*  542 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(101),
+  /*  551 S> */ B(Nop),
+  /*  552 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(103),
+  /*  561 S> */ B(Nop),
+  /*  562 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(105),
+  /*  571 S> */ B(Nop),
+  /*  572 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(107),
+  /*  581 S> */ B(Nop),
+  /*  582 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(109),
+  /*  591 S> */ B(Nop),
+  /*  592 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(111),
+  /*  601 S> */ B(Nop),
+  /*  602 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(113),
+  /*  611 S> */ B(Nop),
+  /*  612 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(115),
+  /*  621 S> */ B(Nop),
+  /*  622 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(117),
+  /*  631 S> */ B(Nop),
+  /*  632 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(119),
+  /*  641 S> */ B(Nop),
+  /*  642 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(121),
+  /*  651 S> */ B(Nop),
+  /*  652 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(123),
+  /*  661 S> */ B(Nop),
+  /*  662 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(125),
+  /*  671 S> */ B(Nop),
+  /*  672 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(127),
+  /*  681 S> */ B(Nop),
+  /*  682 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(129),
+  /*  691 S> */ B(Nop),
+  /*  692 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(131),
+  /*  701 S> */ B(Nop),
+  /*  702 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(133),
+  /*  711 S> */ B(Nop),
+  /*  712 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(135),
+  /*  721 S> */ B(Nop),
+  /*  722 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(137),
+  /*  731 S> */ B(Nop),
+  /*  732 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(139),
+  /*  741 S> */ B(Nop),
+  /*  742 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(141),
+  /*  751 S> */ B(Nop),
+  /*  752 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(143),
+  /*  761 S> */ B(Nop),
+  /*  762 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(145),
+  /*  771 S> */ B(Nop),
+  /*  772 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(147),
+  /*  781 S> */ B(Nop),
+  /*  782 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(149),
+  /*  791 S> */ B(Nop),
+  /*  792 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(151),
+  /*  801 S> */ B(Nop),
+  /*  802 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(153),
+  /*  811 S> */ B(Nop),
+  /*  812 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(155),
+  /*  821 S> */ B(Nop),
+  /*  822 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(157),
+  /*  831 S> */ B(Nop),
+  /*  832 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(159),
+  /*  841 S> */ B(Nop),
+  /*  842 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(161),
+  /*  851 S> */ B(Nop),
+  /*  852 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(163),
+  /*  861 S> */ B(Nop),
+  /*  862 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(165),
+  /*  871 S> */ B(Nop),
+  /*  872 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(167),
+  /*  881 S> */ B(Nop),
+  /*  882 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(169),
+  /*  891 S> */ B(Nop),
+  /*  892 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(171),
+  /*  901 S> */ B(Nop),
+  /*  902 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(173),
+  /*  911 S> */ B(Nop),
+  /*  912 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(175),
+  /*  921 S> */ B(Nop),
+  /*  922 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(177),
+  /*  931 S> */ B(Nop),
+  /*  932 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(179),
+  /*  941 S> */ B(Nop),
+  /*  942 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(181),
+  /*  951 S> */ B(Nop),
+  /*  952 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(183),
+  /*  961 S> */ B(Nop),
+  /*  962 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(185),
+  /*  971 S> */ B(Nop),
+  /*  972 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(187),
+  /*  981 S> */ B(Nop),
+  /*  982 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(189),
+  /*  991 S> */ B(Nop),
+  /*  992 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(191),
+  /* 1001 S> */ B(Nop),
+  /* 1002 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(193),
+  /* 1011 S> */ B(Nop),
+  /* 1012 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(195),
+  /* 1021 S> */ B(Nop),
+  /* 1022 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(197),
+  /* 1031 S> */ B(Nop),
+  /* 1032 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(199),
+  /* 1041 S> */ B(Nop),
+  /* 1042 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(201),
+  /* 1051 S> */ B(Nop),
+  /* 1052 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(203),
+  /* 1061 S> */ B(Nop),
+  /* 1062 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(205),
+  /* 1071 S> */ B(Nop),
+  /* 1072 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(207),
+  /* 1081 S> */ B(Nop),
+  /* 1082 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(209),
+  /* 1091 S> */ B(Nop),
+  /* 1092 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(211),
+  /* 1101 S> */ B(Nop),
+  /* 1102 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(213),
+  /* 1111 S> */ B(Nop),
+  /* 1112 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(215),
+  /* 1121 S> */ B(Nop),
+  /* 1122 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(217),
+  /* 1131 S> */ B(Nop),
+  /* 1132 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(219),
+  /* 1141 S> */ B(Nop),
+  /* 1142 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(221),
+  /* 1151 S> */ B(Nop),
+  /* 1152 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(223),
+  /* 1161 S> */ B(Nop),
+  /* 1162 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(225),
+  /* 1171 S> */ B(Nop),
+  /* 1172 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(227),
+  /* 1181 S> */ B(Nop),
+  /* 1182 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(229),
+  /* 1191 S> */ B(Nop),
+  /* 1192 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(231),
+  /* 1201 S> */ B(Nop),
+  /* 1202 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(233),
+  /* 1211 S> */ B(Nop),
+  /* 1212 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(235),
+  /* 1221 S> */ B(Nop),
+  /* 1222 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(237),
+  /* 1231 S> */ B(Nop),
+  /* 1232 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(239),
+  /* 1241 S> */ B(Nop),
+  /* 1242 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(241),
+  /* 1251 S> */ B(Nop),
+  /* 1252 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(243),
+  /* 1261 S> */ B(Nop),
+  /* 1262 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(245),
+  /* 1271 S> */ B(Nop),
+  /* 1272 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(247),
+  /* 1281 S> */ B(Nop),
+  /* 1282 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(249),
+  /* 1291 S> */ B(Nop),
+  /* 1292 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(251),
+  /* 1301 S> */ B(Nop),
+  /* 1302 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(253),
+  /* 1311 S> */ B(Nop),
+  /* 1312 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(255),
+  /* 1321 S> */ B(LdaSmi), U8(2),
+  /* 1323 E> */ B(Wide), B(StaGlobalStrict), U16(1), U16(257),
+                B(LdaUndefined),
+  /* 1328 S> */ B(Return),
 ]
 constant pool: [
   "name",
diff --git a/test/cctest/interpreter/bytecode_expectations/StringConstants.golden b/test/cctest/interpreter/bytecode_expectations/StringConstants.golden
index 9cf212c..c28ac2a 100644
--- a/test/cctest/interpreter/bytecode_expectations/StringConstants.golden
+++ b/test/cctest/interpreter/bytecode_expectations/StringConstants.golden
@@ -15,9 +15,9 @@
 parameter count: 1
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaConstant), U8(0),
+  /*   61 S> */ B(Return),
 ]
 constant pool: [
   "This is a string",
@@ -33,11 +33,11 @@
 parameter count: 1
 bytecode array length: 8
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(LdaConstant), U8(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   58 S> */ B(LdaConstant), U8(1),
+  /*   82 S> */ B(Return),
 ]
 constant pool: [
   "First string",
@@ -54,11 +54,11 @@
 parameter count: 1
 bytecode array length: 8
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Star), R(0),
-  B(LdaConstant), U8(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaConstant), U8(0),
+                B(Star), R(0),
+  /*   57 S> */ B(LdaConstant), U8(0),
+  /*   79 S> */ B(Return),
 ]
 constant pool: [
   "Same string",
diff --git a/test/cctest/interpreter/bytecode_expectations/Switch.golden b/test/cctest/interpreter/bytecode_expectations/Switch.golden
index c908959..ddb8a7a 100644
--- a/test/cctest/interpreter/bytecode_expectations/Switch.golden
+++ b/test/cctest/interpreter/bytecode_expectations/Switch.golden
@@ -17,26 +17,26 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 31
+bytecode array length: 32
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(TestEqualStrict), R(2),
-  B(JumpIfTrue), U8(10),
-  B(LdaSmi), U8(2),
-  B(TestEqualStrict), R(2),
-  B(JumpIfTrue), U8(7),
-  B(Jump), U8(8),
-  B(LdaSmi), U8(2),
-  B(Return),
-  B(LdaSmi), U8(3),
-  B(Return),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(0),
+                B(Mov), R(0), R(2),
+                B(JumpIfToBooleanTrue), U8(10),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(2),
+                B(JumpIfTrue), U8(7),
+                B(Jump), U8(8),
+  /*   66 S> */ B(LdaSmi), U8(2),
+  /*   97 S> */ B(Return),
+  /*   85 S> */ B(LdaSmi), U8(3),
+  /*   97 S> */ B(Return),
+                B(LdaUndefined),
+  /*   97 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -53,28 +53,28 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 37
+bytecode array length: 38
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(TestEqualStrict), R(2),
-  B(JumpIfTrue), U8(10),
-  B(LdaSmi), U8(2),
-  B(TestEqualStrict), R(2),
-  B(JumpIfTrue), U8(10),
-  B(Jump), U8(14),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(Jump), U8(8),
-  B(LdaSmi), U8(3),
-  B(Star), R(1),
-  B(Jump), U8(2),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(0),
+                B(Mov), R(0), R(2),
+                B(JumpIfToBooleanTrue), U8(10),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(2),
+                B(JumpIfTrue), U8(10),
+                B(Jump), U8(14),
+  /*   66 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*   73 S> */ B(Jump), U8(8),
+  /*   89 S> */ B(LdaSmi), U8(3),
+                B(Star), R(1),
+  /*   96 S> */ B(Jump), U8(2),
+                B(LdaUndefined),
+  /*  105 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -91,27 +91,27 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 35
+bytecode array length: 36
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(TestEqualStrict), R(2),
-  B(JumpIfTrue), U8(10),
-  B(LdaSmi), U8(2),
-  B(TestEqualStrict), R(2),
-  B(JumpIfTrue), U8(8),
-  B(Jump), U8(12),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(Star), R(1),
-  B(Jump), U8(2),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(0),
+                B(Mov), R(0), R(2),
+                B(JumpIfToBooleanTrue), U8(10),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(2),
+                B(JumpIfTrue), U8(8),
+                B(Jump), U8(12),
+  /*   66 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*   98 S> */ B(LdaSmi), U8(3),
+                B(Star), R(1),
+  /*  105 S> */ B(Jump), U8(2),
+                B(LdaUndefined),
+  /*  114 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -129,27 +129,27 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 35
+bytecode array length: 36
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(2),
-  B(TestEqualStrict), R(2),
-  B(JumpIfTrue), U8(10),
-  B(LdaSmi), U8(3),
-  B(TestEqualStrict), R(2),
-  B(JumpIfTrue), U8(6),
-  B(Jump), U8(6),
-  B(Jump), U8(10),
-  B(Jump), U8(8),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(Jump), U8(2),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(0),
+                B(Mov), R(0), R(2),
+                B(JumpIfToBooleanTrue), U8(10),
+                B(LdaSmi), U8(3),
+                B(TestEqualStrict), R(2),
+                B(JumpIfTrue), U8(6),
+                B(Jump), U8(6),
+  /*   66 S> */ B(Jump), U8(10),
+  /*   82 S> */ B(Jump), U8(8),
+  /*   99 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+  /*  106 S> */ B(Jump), U8(2),
+                B(LdaUndefined),
+  /*  115 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -167,32 +167,32 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 44
+bytecode array length: 45
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(TypeOf),
-  B(Star), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(2),
-  B(TestEqualStrict), R(2),
-  B(JumpIfTrue), U8(10),
-  B(LdaSmi), U8(3),
-  B(TestEqualStrict), R(2),
-  B(JumpIfTrue), U8(10),
-  B(Jump), U8(14),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(Jump), U8(14),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(Jump), U8(8),
-  B(LdaSmi), U8(3),
-  B(Star), R(1),
-  B(Jump), U8(2),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+  /*   42 E> */ B(TypeOf),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(0),
+                B(Mov), R(0), R(2),
+                B(JumpIfToBooleanTrue), U8(10),
+                B(LdaSmi), U8(3),
+                B(TestEqualStrict), R(2),
+                B(JumpIfTrue), U8(10),
+                B(Jump), U8(14),
+  /*   74 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+  /*   81 S> */ B(Jump), U8(14),
+  /*   97 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  104 S> */ B(Jump), U8(8),
+  /*  121 S> */ B(LdaSmi), U8(3),
+                B(Star), R(1),
+  /*  128 S> */ B(Jump), U8(2),
+                B(LdaUndefined),
+  /*  137 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -209,26 +209,25 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 32
+bytecode array length: 31
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(2),
-  B(Ldar), R(1),
-  B(TypeOf),
-  B(TestEqualStrict), R(2),
-  B(JumpIfTrue), U8(4),
-  B(Jump), U8(8),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(Jump), U8(8),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(Jump), U8(2),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(Star), R(0),
+  /*   45 S> */ B(TypeOf),
+                B(TestEqualStrict), R(0),
+                B(Mov), R(0), R(2),
+                B(JumpIfToBooleanTrue), U8(4),
+                B(Jump), U8(8),
+  /*   74 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+  /*   81 S> */ B(Jump), U8(8),
+  /*   98 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  105 S> */ B(Jump), U8(2),
+                B(LdaUndefined),
+  /*  114 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -312,154 +311,154 @@
 "
 frame size: 3
 parameter count: 1
-bytecode array length: 289
+bytecode array length: 290
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(1),
-  B(Star), R(0),
-  B(Star), R(2),
-  B(LdaSmi), U8(1),
-  B(TestEqualStrict), R(2),
-  B(JumpIfTrue), U8(10),
-  B(LdaSmi), U8(2),
-  B(TestEqualStrict), R(2),
-  B(JumpIfTrueConstant), U8(0),
-  B(JumpConstant), U8(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(1),
-  B(Jump), U8(8),
-  B(LdaSmi), U8(3),
-  B(Star), R(1),
-  B(Jump), U8(2),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(1),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(0),
+                B(Mov), R(0), R(2),
+                B(JumpIfToBooleanTrue), U8(10),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(2),
+                B(JumpIfTrueConstant), U8(0),
+                B(JumpConstant), U8(1),
+  /*   68 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*   77 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*   86 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*   95 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  104 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  113 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  122 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  131 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  140 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  149 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  158 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  167 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  176 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  185 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  194 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  203 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  212 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  221 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  230 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  239 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  248 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  257 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  266 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  275 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  284 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  293 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  302 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  311 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  320 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  329 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  338 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  347 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  356 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  365 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  374 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  383 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  392 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  401 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  410 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  419 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  428 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  437 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  446 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  455 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  464 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  473 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  482 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  491 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  500 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  509 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  518 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  527 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  536 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  545 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  554 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  563 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  572 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  581 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  590 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  599 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  608 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  617 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  626 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  635 S> */ B(LdaSmi), U8(2),
+                B(Star), R(1),
+  /*  644 S> */ B(Jump), U8(8),
+  /*  662 S> */ B(LdaSmi), U8(3),
+                B(Star), R(1),
+  /*  671 S> */ B(Jump), U8(2),
+                B(LdaUndefined),
+  /*  680 S> */ B(Return),
 ]
 constant pool: [
   262,
@@ -482,40 +481,38 @@
 "
 frame size: 5
 parameter count: 1
-bytecode array length: 61
+bytecode array length: 59
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(2),
-  B(Star), R(0),
-  B(Star), R(3),
-  B(LdaSmi), U8(1),
-  B(TestEqualStrict), R(3),
-  B(JumpIfTrue), U8(10),
-  B(LdaSmi), U8(2),
-  B(TestEqualStrict), R(3),
-  B(JumpIfTrue), U8(36),
-  B(Jump), U8(38),
-  B(Ldar), R(2),
-  B(Star), R(4),
-  B(LdaSmi), U8(1),
-  B(Add), R(4),
-  B(Star), R(1),
-  B(Star), R(4),
-  B(LdaSmi), U8(2),
-  B(TestEqualStrict), R(4),
-  B(JumpIfTrue), U8(4),
-  B(Jump), U8(8),
-  B(LdaSmi), U8(1),
-  B(Star), R(2),
-  B(Jump), U8(8),
-  B(LdaSmi), U8(2),
-  B(Star), R(2),
-  B(Jump), U8(2),
-  B(LdaSmi), U8(3),
-  B(Star), R(2),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(2),
+                B(Star), R(0),
+  /*   45 S> */ B(LdaSmi), U8(1),
+                B(TestEqualStrict), R(0),
+                B(Mov), R(0), R(3),
+                B(JumpIfToBooleanTrue), U8(10),
+                B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(3),
+                B(JumpIfTrue), U8(33),
+                B(Jump), U8(35),
+                B(LdaSmi), U8(1),
+  /*   77 E> */ B(Add), R(2),
+                B(Star), R(1),
+  /*   70 S> */ B(LdaSmi), U8(2),
+                B(TestEqualStrict), R(1),
+                B(Mov), R(1), R(4),
+                B(JumpIfToBooleanTrue), U8(4),
+                B(Jump), U8(8),
+  /*  101 S> */ B(LdaSmi), U8(1),
+                B(Star), R(2),
+  /*  108 S> */ B(Jump), U8(8),
+  /*  131 S> */ B(LdaSmi), U8(2),
+                B(Star), R(2),
+  /*  138 S> */ B(Jump), U8(2),
+  /*  176 S> */ B(LdaSmi), U8(3),
+                B(Star), R(2),
+                B(LdaUndefined),
+  /*  185 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/ThisFunction.golden b/test/cctest/interpreter/bytecode_expectations/ThisFunction.golden
index da84a49..582c087 100644
--- a/test/cctest/interpreter/bytecode_expectations/ThisFunction.golden
+++ b/test/cctest/interpreter/bytecode_expectations/ThisFunction.golden
@@ -14,21 +14,14 @@
   f = function f() {};
   f();
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 19
+bytecode array length: 6
 bytecodes: [
-  B(LdaTheHole),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(closure),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(5),
-  B(Mov), R(1), R(0),
-  B(Ldar), R(1),
-  B(LdaUndefined),
-  B(Return),
+  /*   21 E> */ B(StackCheck),
+                B(Mov), R(closure), R(0),
+                B(LdaUndefined),
+  /*   25 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -41,23 +34,14 @@
   f = function f() { return f; };
   f();
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 23
+bytecode array length: 7
 bytecodes: [
-  B(LdaTheHole),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(closure),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(5),
-  B(Mov), R(1), R(0),
-  B(Ldar), R(1),
-  B(Ldar), R(0),
-  B(JumpIfNotHole), U8(3),
-  B(LdaUndefined),
-  B(Return),
+  /*   21 E> */ B(StackCheck),
+                B(Mov), R(closure), R(0),
+  /*   26 S> */ B(Ldar), R(0),
+  /*   36 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/Throw.golden b/test/cctest/interpreter/bytecode_expectations/Throw.golden
index 99e17fc..4e7a0bc 100644
--- a/test/cctest/interpreter/bytecode_expectations/Throw.golden
+++ b/test/cctest/interpreter/bytecode_expectations/Throw.golden
@@ -15,9 +15,9 @@
 parameter count: 1
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Throw),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaSmi), U8(1),
+  /*   34 E> */ B(Throw),
 ]
 constant pool: [
 ]
@@ -32,9 +32,9 @@
 parameter count: 1
 bytecode array length: 4
 bytecodes: [
-  B(StackCheck),
-  B(LdaConstant), U8(0),
-  B(Throw),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(LdaConstant), U8(0),
+  /*   34 E> */ B(Throw),
 ]
 constant pool: [
   "Error",
@@ -50,14 +50,14 @@
 parameter count: 1
 bytecode array length: 12
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(JumpIfToBooleanFalse), U8(5),
-  B(LdaConstant), U8(0),
-  B(Throw),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+  /*   45 S> */ B(JumpIfToBooleanFalse), U8(5),
+  /*   54 S> */ B(LdaConstant), U8(0),
+  /*   54 E> */ B(Throw),
+                B(LdaUndefined),
+  /*   72 S> */ B(Return),
 ]
 constant pool: [
   "Error",
diff --git a/test/cctest/interpreter/bytecode_expectations/TopLevelObjectLiterals.golden b/test/cctest/interpreter/bytecode_expectations/TopLevelObjectLiterals.golden
index 23d3609..00df0af 100644
--- a/test/cctest/interpreter/bytecode_expectations/TopLevelObjectLiterals.golden
+++ b/test/cctest/interpreter/bytecode_expectations/TopLevelObjectLiterals.golden
@@ -14,27 +14,26 @@
 "
 frame size: 5
 parameter count: 1
-bytecode array length: 44
+bytecode array length: 43
 bytecodes: [
-  B(LdaConstant), U8(0),
-  B(Star), R(1),
-  B(LdaZero),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2),
-  B(StackCheck),
-  B(LdaConstant), U8(1),
-  B(Star), R(1),
-  B(LdaZero),
-  B(Star), R(2),
-  B(CreateObjectLiteral), U8(2), U8(0), U8(5),
-  B(Star), R(4),
-  B(CreateClosure), U8(3), U8(0),
-  B(StoreICSloppy), R(4), U8(4), U8(3),
-  B(Ldar), R(4),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3),
-  B(LdaUndefined),
-  B(Return),
+                B(LdaConstant), U8(0),
+                B(Star), R(1),
+                B(LdaZero),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2),
+  /*    0 E> */ B(StackCheck),
+  /*    8 S> */ B(LdaConstant), U8(1),
+                B(Star), R(1),
+                B(LdaZero),
+                B(Star), R(2),
+                B(CreateObjectLiteral), U8(2), U8(0), U8(1),
+                B(Star), R(4),
+                B(CreateClosure), U8(3), U8(0),
+                B(StaNamedPropertySloppy), R(4), U8(4), U8(3),
+                B(Mov), R(4), R(3),
+                B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3),
+                B(LdaUndefined),
+  /*   33 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
diff --git a/test/cctest/interpreter/bytecode_expectations/TryCatch.golden b/test/cctest/interpreter/bytecode_expectations/TryCatch.golden
index 20abd3e..f061b70 100644
--- a/test/cctest/interpreter/bytecode_expectations/TryCatch.golden
+++ b/test/cctest/interpreter/bytecode_expectations/TryCatch.golden
@@ -13,33 +13,33 @@
 "
 frame size: 5
 parameter count: 1
-bytecode array length: 40
+bytecode array length: 41
 bytecodes: [
-  B(StackCheck),
-  B(Mov), R(context), R(1),
-  B(LdaSmi), U8(1),
-  B(Return),
-  B(Star), R(3),
-  B(LdaConstant), U8(0),
-  B(Star), R(2),
-  B(Ldar), R(closure),
-  B(Star), R(4),
-  B(CallRuntime), U16(Runtime::kPushCatchContext), R(2), U8(3),
-  B(Star), R(1),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Ldar), R(1),
-  B(PushContext), R(0),
-  B(LdaSmi), U8(2),
-  B(PopContext), R(0),
-  B(Return),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+                B(Mov), R(context), R(1),
+  /*   40 S> */ B(LdaSmi), U8(1),
+  /*   75 S> */ B(Return),
+                B(Jump), U8(32),
+                B(Star), R(3),
+                B(LdaConstant), U8(0),
+                B(Star), R(2),
+                B(Mov), R(closure), R(4),
+                B(CallRuntime), U16(Runtime::kPushCatchContext), R(2), U8(3),
+                B(Star), R(1),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Ldar), R(1),
+                B(PushContext), R(0),
+  /*   63 S> */ B(LdaSmi), U8(2),
+                B(PopContext), R(0),
+  /*   75 S> */ B(Return),
+                B(LdaUndefined),
+  /*   75 S> */ B(Return),
 ]
 constant pool: [
   "e",
 ]
 handlers: [
-  [4, 7, 7],
+  [4, 7, 9],
 ]
 
 ---
@@ -50,43 +50,41 @@
 "
 frame size: 6
 parameter count: 1
-bytecode array length: 81
+bytecode array length: 79
 bytecodes: [
-  B(StackCheck),
-  B(Mov), R(context), R(2),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(Jump), U8(30),
-  B(Star), R(4),
-  B(LdaConstant), U8(0),
-  B(Star), R(3),
-  B(Ldar), R(closure),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kPushCatchContext), R(3), U8(3),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Ldar), R(2),
-  B(PushContext), R(1),
-  B(PopContext), R(1),
-  B(Mov), R(context), R(2),
-  B(LdaSmi), U8(2),
-  B(Star), R(0),
-  B(Jump), U8(34),
-  B(Star), R(4),
-  B(LdaConstant), U8(1),
-  B(Star), R(3),
-  B(Ldar), R(closure),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kPushCatchContext), R(3), U8(3),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Ldar), R(2),
-  B(PushContext), R(1),
-  B(LdaSmi), U8(3),
-  B(Star), R(0),
-  B(PopContext), R(1),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+                B(Mov), R(context), R(2),
+  /*   47 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+                B(Jump), U8(29),
+                B(Star), R(4),
+                B(LdaConstant), U8(0),
+                B(Star), R(3),
+                B(Mov), R(closure), R(5),
+  /*   49 E> */ B(CallRuntime), U16(Runtime::kPushCatchContext), R(3), U8(3),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Ldar), R(2),
+                B(PushContext), R(1),
+                B(PopContext), R(1),
+                B(Mov), R(context), R(2),
+  /*   75 S> */ B(LdaSmi), U8(2),
+                B(Star), R(0),
+                B(Jump), U8(33),
+                B(Star), R(4),
+                B(LdaConstant), U8(1),
+                B(Star), R(3),
+                B(Mov), R(closure), R(5),
+  /*   77 E> */ B(CallRuntime), U16(Runtime::kPushCatchContext), R(3), U8(3),
+                B(Star), R(2),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Ldar), R(2),
+                B(PushContext), R(1),
+  /*   95 S> */ B(LdaSmi), U8(3),
+                B(Star), R(0),
+                B(PopContext), R(1),
+                B(LdaUndefined),
+  /*  103 S> */ B(Return),
 ]
 constant pool: [
   "e1",
@@ -94,6 +92,6 @@
 ]
 handlers: [
   [4, 8, 10],
-  [41, 45, 47],
+  [40, 44, 46],
 ]
 
diff --git a/test/cctest/interpreter/bytecode_expectations/TryFinally.golden b/test/cctest/interpreter/bytecode_expectations/TryFinally.golden
index e14a709..de3bbf0 100644
--- a/test/cctest/interpreter/bytecode_expectations/TryFinally.golden
+++ b/test/cctest/interpreter/bytecode_expectations/TryFinally.golden
@@ -16,31 +16,31 @@
 parameter count: 1
 bytecode array length: 51
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(Mov), R(context), R(3),
-  B(LdaSmi), U8(2),
-  B(Star), R(0),
-  B(LdaSmi), U8(-1),
-  B(Star), R(1),
-  B(Jump), U8(7),
-  B(Star), R(2),
-  B(LdaZero),
-  B(Star), R(1),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Star), R(3),
-  B(LdaSmi), U8(3),
-  B(Star), R(0),
-  B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(3), U8(1),
-  B(LdaZero),
-  B(TestEqualStrict), R(1),
-  B(JumpIfTrue), U8(4),
-  B(Jump), U8(5),
-  B(Ldar), R(2),
-  B(ReThrow),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+                B(Mov), R(context), R(3),
+  /*   51 S> */ B(LdaSmi), U8(2),
+                B(Star), R(0),
+                B(LdaSmi), U8(-1),
+                B(Star), R(1),
+                B(Jump), U8(7),
+                B(Star), R(2),
+                B(LdaZero),
+                B(Star), R(1),
+  /*   53 E> */ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Star), R(3),
+  /*   70 S> */ B(LdaSmi), U8(3),
+                B(Star), R(0),
+  /*   72 E> */ B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(3), U8(1),
+                B(LdaZero),
+                B(TestEqualStrict), R(1),
+                B(JumpIfTrue), U8(4),
+                B(Jump), U8(5),
+                B(Ldar), R(2),
+                B(ReThrow),
+                B(LdaUndefined),
+  /*   79 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -55,54 +55,53 @@
 "
 frame size: 9
 parameter count: 1
-bytecode array length: 88
+bytecode array length: 87
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(Mov), R(context), R(4),
-  B(Mov), R(context), R(5),
-  B(LdaSmi), U8(2),
-  B(Star), R(0),
-  B(Jump), U8(34),
-  B(Star), R(7),
-  B(LdaConstant), U8(0),
-  B(Star), R(6),
-  B(Ldar), R(closure),
-  B(Star), R(8),
-  B(CallRuntime), U16(Runtime::kPushCatchContext), R(6), U8(3),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Ldar), R(5),
-  B(PushContext), R(1),
-  B(LdaSmi), U8(20),
-  B(Star), R(0),
-  B(PopContext), R(1),
-  B(LdaSmi), U8(-1),
-  B(Star), R(2),
-  B(Jump), U8(7),
-  B(Star), R(3),
-  B(LdaZero),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Star), R(4),
-  B(LdaSmi), U8(3),
-  B(Star), R(0),
-  B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(4), U8(1),
-  B(LdaZero),
-  B(TestEqualStrict), R(2),
-  B(JumpIfTrue), U8(4),
-  B(Jump), U8(5),
-  B(Ldar), R(3),
-  B(ReThrow),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+                B(Mov), R(context), R(4),
+                B(Mov), R(context), R(5),
+  /*   51 S> */ B(LdaSmi), U8(2),
+                B(Star), R(0),
+                B(Jump), U8(33),
+                B(Star), R(7),
+                B(LdaConstant), U8(0),
+                B(Star), R(6),
+                B(Mov), R(closure), R(8),
+  /*   53 E> */ B(CallRuntime), U16(Runtime::kPushCatchContext), R(6), U8(3),
+                B(Star), R(5),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Ldar), R(5),
+                B(PushContext), R(1),
+  /*   71 S> */ B(LdaSmi), U8(20),
+                B(Star), R(0),
+                B(PopContext), R(1),
+                B(LdaSmi), U8(-1),
+                B(Star), R(2),
+                B(Jump), U8(7),
+                B(Star), R(3),
+                B(LdaZero),
+                B(Star), R(2),
+  /*   73 E> */ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Star), R(4),
+  /*   90 S> */ B(LdaSmi), U8(3),
+                B(Star), R(0),
+  /*   92 E> */ B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(4), U8(1),
+                B(LdaZero),
+                B(TestEqualStrict), R(2),
+                B(JumpIfTrue), U8(4),
+                B(Jump), U8(5),
+                B(Ldar), R(3),
+                B(ReThrow),
+                B(LdaUndefined),
+  /*   99 S> */ B(Return),
 ]
 constant pool: [
   "e",
 ]
 handlers: [
-  [8, 49, 55],
+  [8, 48, 54],
   [11, 15, 17],
 ]
 
@@ -114,68 +113,66 @@
 "
 frame size: 10
 parameter count: 1
-bytecode array length: 121
+bytecode array length: 119
 bytecodes: [
-  B(StackCheck),
-  B(Mov), R(context), R(4),
-  B(Mov), R(context), R(5),
-  B(Mov), R(context), R(6),
-  B(LdaSmi), U8(1),
-  B(Star), R(0),
-  B(Jump), U8(34),
-  B(Star), R(8),
-  B(LdaConstant), U8(0),
-  B(Star), R(7),
-  B(Ldar), R(closure),
-  B(Star), R(9),
-  B(CallRuntime), U16(Runtime::kPushCatchContext), R(7), U8(3),
-  B(Star), R(6),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Ldar), R(6),
-  B(PushContext), R(1),
-  B(LdaSmi), U8(2),
-  B(Star), R(0),
-  B(PopContext), R(1),
-  B(Jump), U8(34),
-  B(Star), R(7),
-  B(LdaConstant), U8(0),
-  B(Star), R(6),
-  B(Ldar), R(closure),
-  B(Star), R(8),
-  B(CallRuntime), U16(Runtime::kPushCatchContext), R(6), U8(3),
-  B(Star), R(5),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Ldar), R(5),
-  B(PushContext), R(1),
-  B(LdaSmi), U8(20),
-  B(Star), R(0),
-  B(PopContext), R(1),
-  B(LdaSmi), U8(-1),
-  B(Star), R(2),
-  B(Jump), U8(7),
-  B(Star), R(3),
-  B(LdaZero),
-  B(Star), R(2),
-  B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
-  B(Star), R(4),
-  B(LdaSmi), U8(3),
-  B(Star), R(0),
-  B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(4), U8(1),
-  B(LdaZero),
-  B(TestEqualStrict), R(2),
-  B(JumpIfTrue), U8(4),
-  B(Jump), U8(5),
-  B(Ldar), R(3),
-  B(ReThrow),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+                B(Mov), R(context), R(4),
+                B(Mov), R(context), R(5),
+                B(Mov), R(context), R(6),
+  /*   55 S> */ B(LdaSmi), U8(1),
+                B(Star), R(0),
+                B(Jump), U8(33),
+                B(Star), R(8),
+                B(LdaConstant), U8(0),
+                B(Star), R(7),
+                B(Mov), R(closure), R(9),
+  /*   57 E> */ B(CallRuntime), U16(Runtime::kPushCatchContext), R(7), U8(3),
+                B(Star), R(6),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Ldar), R(6),
+                B(PushContext), R(1),
+  /*   74 S> */ B(LdaSmi), U8(2),
+                B(Star), R(0),
+                B(PopContext), R(1),
+                B(Jump), U8(33),
+                B(Star), R(7),
+                B(LdaConstant), U8(0),
+                B(Star), R(6),
+                B(Mov), R(closure), R(8),
+  /*   76 E> */ B(CallRuntime), U16(Runtime::kPushCatchContext), R(6), U8(3),
+                B(Star), R(5),
+                B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Ldar), R(5),
+                B(PushContext), R(1),
+  /*   95 S> */ B(LdaSmi), U8(20),
+                B(Star), R(0),
+                B(PopContext), R(1),
+                B(LdaSmi), U8(-1),
+                B(Star), R(2),
+                B(Jump), U8(7),
+                B(Star), R(3),
+                B(LdaZero),
+                B(Star), R(2),
+  /*   97 E> */ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0),
+                B(Star), R(4),
+  /*  114 S> */ B(LdaSmi), U8(3),
+                B(Star), R(0),
+  /*  116 E> */ B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(4), U8(1),
+                B(LdaZero),
+                B(TestEqualStrict), R(2),
+                B(JumpIfTrue), U8(4),
+                B(Jump), U8(5),
+                B(Ldar), R(3),
+                B(ReThrow),
+                B(LdaUndefined),
+  /*  123 S> */ B(Return),
 ]
 constant pool: [
   "e",
 ]
 handlers: [
-  [4, 82, 88],
-  [7, 48, 50],
+  [4, 80, 86],
+  [7, 47, 49],
   [10, 14, 16],
 ]
 
diff --git a/test/cctest/interpreter/bytecode_expectations/Typeof.golden b/test/cctest/interpreter/bytecode_expectations/Typeof.golden
index e5db7a7..1fe9354 100644
--- a/test/cctest/interpreter/bytecode_expectations/Typeof.golden
+++ b/test/cctest/interpreter/bytecode_expectations/Typeof.golden
@@ -20,11 +20,11 @@
 parameter count: 1
 bytecode array length: 7
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(13),
-  B(Star), R(0),
-  B(TypeOf),
-  B(Return),
+  /*   10 E> */ B(StackCheck),
+  /*   24 S> */ B(LdaSmi), U8(13),
+                B(Star), R(0),
+  /*   29 S> */ B(TypeOf),
+  /*   47 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -41,15 +41,14 @@
 "
 frame size: 0
 parameter count: 1
-bytecode array length: 6
+bytecode array length: 5
 bytecodes: [
-  B(StackCheck),
-  B(LdaGlobalInsideTypeof), U8(0), U8(1),
-  B(TypeOf),
-  B(Return),
+  /*   22 E> */ B(StackCheck),
+  /*   28 S> */ B(LdaGlobalInsideTypeof), U8(1),
+                B(TypeOf),
+  /*   46 S> */ B(Return),
 ]
 constant pool: [
-  "x",
 ]
 handlers: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/UnaryOperators.golden b/test/cctest/interpreter/bytecode_expectations/UnaryOperators.golden
index 0a3ca76..dc2a930 100644
--- a/test/cctest/interpreter/bytecode_expectations/UnaryOperators.golden
+++ b/test/cctest/interpreter/bytecode_expectations/UnaryOperators.golden
@@ -15,28 +15,24 @@
   }
   return x;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 31
+bytecode array length: 23
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(10),
-  B(TestEqual), R(1),
-  B(LogicalNot),
-  B(JumpIfFalse), U8(15),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(10),
-  B(Add), R(1),
-  B(Star), R(0),
-  B(Jump), U8(-22),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaZero),
+                B(Star), R(0),
+  /*   54 S> */ B(LdaSmi), U8(10),
+  /*   54 E> */ B(TestEqual), R(0),
+                B(LogicalNot),
+                B(JumpIfFalse), U8(11),
+  /*   45 E> */ B(StackCheck),
+  /*   65 S> */ B(LdaSmi), U8(10),
+                B(Add), R(0),
+                B(Star), R(0),
+                B(Jump), U8(-14),
+  /*   79 S> */ B(Ldar), R(0),
+  /*   89 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -51,24 +47,22 @@
   } while(x == false);
   return x;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 22
+bytecode array length: 18
 bytecodes: [
-  B(StackCheck),
-  B(LdaFalse),
-  B(Star), R(0),
-  B(StackCheck),
-  B(Ldar), R(0),
-  B(LogicalNot),
-  B(Star), R(0),
-  B(Ldar), R(0),
-  B(Star), R(1),
-  B(LdaFalse),
-  B(TestEqual), R(1),
-  B(JumpIfTrue), U8(-13),
-  B(Ldar), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaFalse),
+                B(Star), R(0),
+  /*   49 E> */ B(StackCheck),
+  /*   56 S> */ B(Ldar), R(0),
+                B(ToBooleanLogicalNot),
+                B(Star), R(0),
+  /*   74 S> */ B(LdaFalse),
+  /*   74 E> */ B(TestEqual), R(0),
+                B(JumpIfTrue), U8(-9),
+  /*   85 S> */ B(Ldar), R(0),
+  /*   95 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -80,18 +74,17 @@
   var x = 101;
   return void(x * 3);
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 13
+bytecode array length: 11
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(101),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(3),
-  B(Mul), R(1),
-  B(LdaUndefined),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(101),
+                B(Star), R(0),
+  /*   47 S> */ B(LdaSmi), U8(3),
+                B(Mul), R(0),
+                B(LdaUndefined),
+  /*   67 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -106,20 +99,20 @@
 "
 frame size: 4
 parameter count: 1
-bytecode array length: 23
+bytecode array length: 22
 bytecodes: [
-  B(StackCheck),
-  B(Wide), B(LdaSmi), U16(1234),
-  B(Star), R(0),
-  B(Star), R(2),
-  B(Ldar), R(0),
-  B(Mul), R(2),
-  B(Star), R(3),
-  B(LdaSmi), U8(1),
-  B(Sub), R(3),
-  B(LdaUndefined),
-  B(Star), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(Wide), B(LdaSmi), U16(1234),
+                B(Star), R(0),
+  /*   56 S> */ B(Nop),
+  /*   66 E> */ B(Mul), R(0),
+                B(Star), R(3),
+                B(LdaSmi), U8(1),
+                B(Sub), R(3),
+                B(LdrUndefined), R(1),
+                B(Ldar), R(1),
+  /*   74 S> */ B(Nop),
+  /*   84 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -131,17 +124,16 @@
   var x = 13;
   return ~x;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 12
+bytecode array length: 10
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(13),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(-1),
-  B(BitwiseXor), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(13),
+                B(Star), R(0),
+  /*   46 S> */ B(LdaSmi), U8(-1),
+                B(BitwiseXor), R(0),
+  /*   57 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -153,17 +145,16 @@
   var x = 13;
   return +x;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 12
+bytecode array length: 10
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(13),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(1),
-  B(Mul), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(13),
+                B(Star), R(0),
+  /*   46 S> */ B(LdaSmi), U8(1),
+                B(Mul), R(0),
+  /*   57 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -175,17 +166,16 @@
   var x = 13;
   return -x;
 "
-frame size: 2
+frame size: 1
 parameter count: 1
-bytecode array length: 12
+bytecode array length: 10
 bytecodes: [
-  B(StackCheck),
-  B(LdaSmi), U8(13),
-  B(Star), R(0),
-  B(Star), R(1),
-  B(LdaSmi), U8(-1),
-  B(Mul), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   42 S> */ B(LdaSmi), U8(13),
+                B(Star), R(0),
+  /*   46 S> */ B(LdaSmi), U8(-1),
+                B(Mul), R(0),
+  /*   57 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/WideRegisters.golden b/test/cctest/interpreter/bytecode_expectations/WideRegisters.golden
index 9300775..717f323 100644
--- a/test/cctest/interpreter/bytecode_expectations/WideRegisters.golden
+++ b/test/cctest/interpreter/bytecode_expectations/WideRegisters.golden
@@ -171,12 +171,12 @@
 "
 frame size: 157
 parameter count: 1
-bytecode array length: 6
+bytecode array length: 10
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(127),
-  B(Star), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /* 1494 S> */ B(Wide), B(Mov), R16(127), R16(0),
+  /* 1505 S> */ B(Ldar), R(0),
+  /* 1516 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -347,12 +347,12 @@
 "
 frame size: 157
 parameter count: 1
-bytecode array length: 6
+bytecode array length: 12
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(126),
-  B(Star), R(127),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /* 1494 S> */ B(Wide), B(Mov), R16(126), R16(127),
+  /* 1507 S> */ B(Wide), B(Ldar), R16(127),
+  /* 1520 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -521,20 +521,18 @@
   if (x2 > 3) { return x129; }
   return x128;
 "
-frame size: 158
+frame size: 157
 parameter count: 1
-bytecode array length: 23
+bytecode array length: 17
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(2),
-  B(Wide), B(Star), R16(157),
-  B(LdaSmi), U8(3),
-  B(Wide), B(TestGreaterThan), R16(157),
-  B(JumpIfFalse), U8(7),
-  B(Wide), B(Ldar), R16(129),
-  B(Return),
-  B(Ldar), R(128),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /* 1494 S> */ B(LdaSmi), U8(3),
+  /* 1501 E> */ B(TestGreaterThan), R(2),
+                B(JumpIfFalse), U8(7),
+  /* 1508 S> */ B(Wide), B(Ldar), R16(129),
+  /* 1536 S> */ B(Return),
+  /* 1523 S> */ B(Wide), B(Ldar), R16(128),
+  /* 1536 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -705,29 +703,25 @@
   if (x2 > 3) { return x0; }
   return x129;
 "
-frame size: 158
+frame size: 157
 parameter count: 1
-bytecode array length: 48
+bytecode array length: 34
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(Wide), B(Ldar), R16(129),
-  B(Wide), B(Star), R16(157),
-  B(LdaSmi), U8(3),
-  B(Wide), B(TestEqual), R16(157),
-  B(JumpIfFalse), U8(8),
-  B(Ldar), R(0),
-  B(Wide), B(Star), R16(129),
-  B(Ldar), R(2),
-  B(Wide), B(Star), R16(157),
-  B(LdaSmi), U8(3),
-  B(Wide), B(TestGreaterThan), R16(157),
-  B(JumpIfFalse), U8(5),
-  B(Ldar), R(0),
-  B(Return),
-  B(Wide), B(Ldar), R16(129),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /* 1503 S> */ B(LdaZero),
+                B(Star), R(0),
+  /* 1506 S> */ B(LdaSmi), U8(3),
+  /* 1515 E> */ B(Wide), B(TestEqual), R16(129),
+                B(JumpIfFalse), U8(10),
+  /* 1534 S> */ B(Wide), B(Mov), R16(0), R16(129),
+                B(Ldar), R(0),
+  /* 1540 S> */ B(LdaSmi), U8(3),
+  /* 1547 E> */ B(TestGreaterThan), R(2),
+                B(JumpIfFalse), U8(5),
+  /* 1554 S> */ B(Ldar), R(0),
+  /* 1580 S> */ B(Return),
+  /* 1567 S> */ B(Wide), B(Ldar), R16(129),
+  /* 1580 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -899,34 +893,31 @@
 "
 frame size: 158
 parameter count: 1
-bytecode array length: 54
+bytecode array length: 56
 bytecodes: [
-  B(StackCheck),
-  B(LdaZero),
-  B(Star), R(0),
-  B(LdaZero),
-  B(Star), R(1),
-  B(LdaZero),
-  B(Star), R(128),
-  B(Ldar), R(128),
-  B(Wide), B(Star), R16(157),
-  B(LdaSmi), U8(64),
-  B(Wide), B(TestLessThan), R16(157),
-  B(JumpIfFalse), U8(29),
-  B(StackCheck),
-  B(Ldar), R(1),
-  B(Wide), B(Star), R16(157),
-  B(Ldar), R(128),
-  B(Wide), B(Add), R16(157),
-  B(Star), R(1),
-  B(Ldar), R(128),
-  B(ToNumber),
-  B(Wide), B(Star), R16(157),
-  B(Inc),
-  B(Star), R(128),
-  B(Jump), U8(-39),
-  B(Ldar), R(128),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /* 1503 S> */ B(LdaZero),
+                B(Star), R(0),
+  /* 1515 S> */ B(LdaZero),
+                B(Star), R(1),
+  /* 1523 S> */ B(LdaZero),
+                B(Wide), B(Star), R16(128),
+  /* 1538 S> */ B(LdaSmi), U8(64),
+  /* 1538 E> */ B(Wide), B(TestLessThan), R16(128),
+                B(JumpIfFalse), U8(33),
+  /* 1518 E> */ B(StackCheck),
+  /* 1555 S> */ B(Wide), B(Ldar), R16(128),
+  /* 1561 E> */ B(Add), R(1),
+                B(Wide), B(Mov), R16(1), R16(157),
+                B(Star), R(1),
+  /* 1548 S> */ B(Wide), B(Ldar), R16(128),
+                B(ToNumber),
+                B(Wide), B(Star), R16(157),
+                B(Inc),
+                B(Wide), B(Star), R16(128),
+                B(Jump), U8(-37),
+  /* 1567 S> */ B(Wide), B(Ldar), R16(128),
+  /* 1580 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -1098,37 +1089,36 @@
 "
 frame size: 163
 parameter count: 1
-bytecode array length: 80
+bytecode array length: 82
 bytecodes: [
-  B(StackCheck),
-  B(Wide), B(LdaSmi), U16(1234),
-  B(Star), R(0),
-  B(LdaZero),
-  B(Star), R(1),
-  B(Ldar), R(0),
-  B(JumpIfUndefined), U8(65),
-  B(JumpIfNull), U8(63),
-  B(ToObject),
-  B(Wide), B(Star), R16(157),
-  B(Wide), B(ForInPrepare), R16(158),
-  B(LdaZero),
-  B(Wide), B(Star), R16(161),
-  B(Wide), B(ForInDone), R16(161), R16(160),
-  B(JumpIfTrue), U8(41),
-  B(Wide), B(ForInNext), R16(157), R16(161), R16(158), U16(1),
-  B(JumpIfUndefined), U8(19),
-  B(Star), R(128),
-  B(StackCheck),
-  B(Ldar), R(1),
-  B(Wide), B(Star), R16(162),
-  B(Ldar), R(128),
-  B(Wide), B(Add), R16(162),
-  B(Star), R(1),
-  B(Wide), B(ForInStep), R16(161),
-  B(Wide), B(Star), R16(161),
-  B(Jump), U8(-45),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /* 1503 S> */ B(Wide), B(LdaSmi), U16(1234),
+                B(Star), R(0),
+  /* 1518 S> */ B(LdaZero),
+                B(Star), R(1),
+  /* 1534 S> */ B(Ldar), R(0),
+                B(JumpIfUndefined), U8(67),
+                B(JumpIfNull), U8(65),
+                B(ToObject),
+                B(Wide), B(ForInPrepare), R16(158),
+                B(Wide), B(Star), R16(157),
+                B(LdaZero),
+                B(Wide), B(Star), R16(161),
+  /* 1526 S> */ B(Wide), B(ForInDone), R16(161), R16(160),
+                B(JumpIfTrue), U8(43),
+                B(Wide), B(ForInNext), R16(157), R16(161), R16(158), U16(1),
+                B(JumpIfUndefined), U8(21),
+                B(Wide), B(Star), R16(128),
+  /* 1521 E> */ B(StackCheck),
+  /* 1541 S> */ B(Wide), B(Ldar), R16(128),
+  /* 1547 E> */ B(Add), R(1),
+                B(Wide), B(Mov), R16(1), R16(162),
+                B(Star), R(1),
+  /* 1544 E> */ B(Wide), B(ForInStep), R16(161),
+                B(Wide), B(Star), R16(161),
+                B(Jump), U8(-47),
+  /* 1553 S> */ B(Ldar), R(1),
+  /* 1564 S> */ B(Return),
 ]
 constant pool: [
 ]
@@ -1301,24 +1291,20 @@
 "
 frame size: 159
 parameter count: 1
-bytecode array length: 55
+bytecode array length: 53
 bytecodes: [
-  B(StackCheck),
-  B(Ldar), R(64),
-  B(Wide), B(Star), R16(157),
-  B(Ldar), R(63),
-  B(Wide), B(Star), R16(158),
-  B(Wide), B(CallRuntime), U16(Runtime::kAdd), R16(157), U16(2),
-  B(Star), R(0),
-  B(Ldar), R(27),
-  B(Wide), B(Star), R16(157),
-  B(Wide), B(Ldar), R16(143),
-  B(Wide), B(Star), R16(158),
-  B(Wide), B(CallRuntime), U16(Runtime::kAdd), R16(157), U16(2),
-  B(Star), R(1),
-  B(CallRuntime), U16(Runtime::kTheHole), R(0), U8(0),
-  B(Ldar), R(1),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /* 1494 S> */ B(Wide), B(Mov), R16(64), R16(157),
+                B(Wide), B(Mov), R16(63), R16(158),
+  /* 1509 E> */ B(Wide), B(CallRuntime), U16(Runtime::kAdd), R16(157), U16(2),
+                B(Star), R(0),
+  /* 1515 S> */ B(Wide), B(Mov), R16(27), R16(157),
+                B(Wide), B(Mov), R16(143), R16(158),
+  /* 1530 E> */ B(Wide), B(CallRuntime), U16(Runtime::kAdd), R16(157), U16(2),
+                B(Star), R(1),
+  /* 1537 S> */ B(CallRuntime), U16(Runtime::kTheHole), R(0), U8(0),
+  /* 1549 S> */ B(Ldar), R(1),
+  /* 1560 S> */ B(Return),
 ]
 constant pool: [
 ]
diff --git a/test/cctest/interpreter/bytecode_expectations/WithStatement.golden b/test/cctest/interpreter/bytecode_expectations/WithStatement.golden
index 350a0a5..71183de 100644
--- a/test/cctest/interpreter/bytecode_expectations/WithStatement.golden
+++ b/test/cctest/interpreter/bytecode_expectations/WithStatement.golden
@@ -13,20 +13,19 @@
 "
 frame size: 4
 parameter count: 1
-bytecode array length: 26
+bytecode array length: 25
 bytecodes: [
-  B(StackCheck),
-  B(CreateObjectLiteral), U8(0), U8(0), U8(5),
-  B(Star), R(1),
-  B(ToObject),
-  B(Star), R(2),
-  B(Ldar), R(closure),
-  B(Star), R(3),
-  B(CallRuntime), U16(Runtime::kPushWithContext), R(2), U8(2),
-  B(PushContext), R(0),
-  B(LdaLookupSlot), U8(1),
-  B(PopContext), R(0),
-  B(Return),
+  /*   30 E> */ B(StackCheck),
+  /*   34 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
+                B(Star), R(1),
+                B(ToObject),
+                B(Star), R(2),
+                B(Mov), R(closure), R(3),
+                B(CallRuntime), U16(Runtime::kPushWithContext), R(2), U8(2),
+                B(PushContext), R(0),
+  /*   50 S> */ B(LdaLookupSlot), U8(1),
+                B(PopContext), R(0),
+  /*   62 S> */ B(Return),
 ]
 constant pool: [
   InstanceType::FIXED_ARRAY_TYPE,
diff --git a/test/cctest/interpreter/generate-bytecode-expectations.cc b/test/cctest/interpreter/generate-bytecode-expectations.cc
index 92ba9ba..53f2e3f 100644
--- a/test/cctest/interpreter/generate-bytecode-expectations.cc
+++ b/test/cctest/interpreter/generate-bytecode-expectations.cc
@@ -44,6 +44,7 @@
         execute_(true),
         top_level_(false),
         do_expressions_(false),
+        ignition_generators_(false),
         verbose_(false),
         const_pool_type_(
             BytecodeExpectationsPrinter::ConstantPoolType::kMixed) {}
@@ -64,6 +65,7 @@
   bool execute() const { return execute_; }
   bool top_level() const { return top_level_; }
   bool do_expressions() const { return do_expressions_; }
+  bool ignition_generators() const { return ignition_generators_; }
   bool verbose() const { return verbose_; }
   bool suppress_runtime_errors() const { return rebaseline_ && !verbose_; }
   BytecodeExpectationsPrinter::ConstantPoolType const_pool_type() const {
@@ -83,6 +85,7 @@
   bool execute_;
   bool top_level_;
   bool do_expressions_;
+  bool ignition_generators_;
   bool verbose_;
   BytecodeExpectationsPrinter::ConstantPoolType const_pool_type_;
   std::vector<std::string> input_filenames_;
@@ -212,6 +215,8 @@
       options.top_level_ = true;
     } else if (strcmp(argv[i], "--do-expressions") == 0) {
       options.do_expressions_ = true;
+    } else if (strcmp(argv[i], "--ignition-generators") == 0) {
+      options.ignition_generators_ = true;
     } else if (strcmp(argv[i], "--verbose") == 0) {
       options.verbose_ = true;
     } else if (strncmp(argv[i], "--output=", 9) == 0) {
@@ -316,6 +321,8 @@
       top_level_ = ParseBoolean(line.c_str() + 11);
     } else if (line.compare(0, 16, "do expressions: ") == 0) {
       do_expressions_ = ParseBoolean(line.c_str() + 16);
+    } else if (line.compare(0, 21, "ignition generators: ") == 0) {
+      ignition_generators_ = ParseBoolean(line.c_str() + 21);
     } else if (line == "---") {
       break;
     } else if (line.empty()) {
@@ -340,6 +347,7 @@
 
   if (top_level_) stream << "\ntop level: yes";
   if (do_expressions_) stream << "\ndo expressions: yes";
+  if (ignition_generators_) stream << "\nignition generators: yes";
 
   stream << "\n\n";
 }
@@ -350,7 +358,7 @@
   i::FLAG_always_opt = false;
   i::FLAG_allow_natives_syntax = true;
 
-  v8::V8::InitializeICU();
+  v8::V8::InitializeICUDefaultLocation(exec_path);
   v8::V8::InitializeExternalStartupData(exec_path);
   v8::V8::InitializePlatform(platform_.get());
   v8::V8::Initialize();
@@ -445,6 +453,7 @@
   }
 
   if (options.do_expressions()) i::FLAG_harmony_do_expressions = true;
+  if (options.ignition_generators()) i::FLAG_ignition_generators = true;
 
   stream << "#\n# Autogenerated by generate-bytecode-expectations.\n#\n\n";
   options.PrintHeader(stream);
@@ -497,6 +506,7 @@
          "Specify the name of the test function.\n"
          "  --top-level   Process top level code, not the top-level function.\n"
          "  --do-expressions  Enable harmony_do_expressions flag.\n"
+         "  --ignition-generators  Enable ignition_generators flag.\n"
          "  --output=file.name\n"
          "      Specify the output file. If not specified, output goes to "
          "stdout.\n"
diff --git a/test/cctest/interpreter/interpreter-tester.h b/test/cctest/interpreter/interpreter-tester.h
index f8a0a8a..4e202ea 100644
--- a/test/cctest/interpreter/interpreter-tester.h
+++ b/test/cctest/interpreter/interpreter-tester.h
@@ -114,7 +114,7 @@
       function->shared()->set_function_data(*bytecode_.ToHandleChecked());
     }
     if (!feedback_vector_.is_null()) {
-      function->shared()->set_feedback_vector(
+      function->literals()->set_feedback_vector(
           *feedback_vector_.ToHandleChecked());
     }
     return function;
diff --git a/test/cctest/interpreter/source-position-matcher.cc b/test/cctest/interpreter/source-position-matcher.cc
new file mode 100644
index 0000000..122f2c8
--- /dev/null
+++ b/test/cctest/interpreter/source-position-matcher.cc
@@ -0,0 +1,225 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "test/cctest/interpreter/source-position-matcher.h"
+
+#include "src/objects-inl.h"
+#include "src/objects.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+// Comparer for PositionTableEntry instances.
+struct PositionTableEntryComparer {
+  bool operator()(const PositionTableEntry& lhs,
+                  const PositionTableEntry& rhs) const {
+    int lhs_type_score = type_score(lhs);
+    int rhs_type_score = type_score(rhs);
+    if (lhs_type_score == rhs_type_score) {
+      return lhs.source_position < rhs.source_position;
+    } else {
+      return lhs_type_score < rhs_type_score;
+    }
+  }
+
+  int type_score(const PositionTableEntry& entry) const {
+    return entry.is_statement ? 1 : 0;
+  }
+};
+
+//
+// The principles for comparing source positions in bytecode arrays
+// are:
+//
+// 1. The number of statement positions must be the same in both.
+//
+// 2. Statement positions may be moved provide they do not affect the
+//    debuggers causal view of the v8 heap and local state. This means
+//    statement positions may be moved when their initial position is
+//    on bytecodes that manipulate the accumulator and temporary
+//    registers.
+//
+// 3. When duplicate expression positions are present, either may
+//    be dropped.
+//
+// 4. Expression positions may be applied to later bytecodes in the
+//    bytecode array if the current bytecode does not throw.
+//
+// 5. Expression positions may be dropped when they are applied to
+//    bytecodes that manipulate local frame state and immediately
+//    proceeded by another source position.
+//
+// 6. The relative ordering of source positions must be preserved.
+//
+bool SourcePositionMatcher::Match(Handle<BytecodeArray> original_bytecode,
+                                  Handle<BytecodeArray> optimized_bytecode) {
+  SourcePositionTableIterator original(
+      original_bytecode->source_position_table());
+  SourcePositionTableIterator optimized(
+      optimized_bytecode->source_position_table());
+
+  int last_original_bytecode_offset = 0;
+  int last_optimized_bytecode_offset = 0;
+
+  // Ordered lists of expression positions immediately before the
+  // latest statements in each bytecode array.
+  std::vector<PositionTableEntry> original_expression_entries;
+  std::vector<PositionTableEntry> optimized_expression_entries;
+
+  while (true) {
+    MoveToNextStatement(&original, &original_expression_entries);
+    MoveToNextStatement(&optimized, &optimized_expression_entries);
+
+    if (original.done() && optimized.done()) {
+      return true;
+    } else if (original.done()) {
+      return false;
+    } else if (optimized.done()) {
+      return false;
+    }
+
+    if (HasNewExpressionPositionsInOptimized(&original_expression_entries,
+                                             &optimized_expression_entries)) {
+      return false;
+    }
+
+    StripUnneededExpressionPositions(original_bytecode,
+                                     &original_expression_entries,
+                                     original.bytecode_offset());
+    StripUnneededExpressionPositions(optimized_bytecode,
+                                     &optimized_expression_entries,
+                                     optimized.bytecode_offset());
+
+    if (!CompareExpressionPositions(&original_expression_entries,
+                                    &optimized_expression_entries)) {
+      // Message logged in CompareExpressionPositions().
+      return false;
+    }
+
+    // Check original and optimized have matching source positions.
+    if (original.source_position() != optimized.source_position()) {
+      return false;
+    }
+
+    if (original.bytecode_offset() < last_original_bytecode_offset) {
+      return false;
+    }
+    last_original_bytecode_offset = original.bytecode_offset();
+
+    if (optimized.bytecode_offset() < last_optimized_bytecode_offset) {
+      return false;
+    }
+    last_optimized_bytecode_offset = optimized.bytecode_offset();
+
+    // TODO(oth): Can we compare statement positions are semantically
+    // equivalent? e.g. before a bytecode that has debugger observable
+    // effects. This is likely non-trivial.
+  }
+
+  return true;
+}
+
+bool SourcePositionMatcher::HasNewExpressionPositionsInOptimized(
+    const std::vector<PositionTableEntry>* const original_positions,
+    const std::vector<PositionTableEntry>* const optimized_positions) {
+  std::set<PositionTableEntry, PositionTableEntryComparer> original_set(
+      original_positions->begin(), original_positions->end());
+
+  bool retval = false;
+  for (auto optimized_position : *optimized_positions) {
+    if (original_set.find(optimized_position) == original_set.end()) {
+      retval = true;
+    }
+  }
+  return retval;
+}
+
+bool SourcePositionMatcher::CompareExpressionPositions(
+    const std::vector<PositionTableEntry>* const original_positions,
+    const std::vector<PositionTableEntry>* const optimized_positions) {
+  if (original_positions->size() != optimized_positions->size()) {
+    return false;
+  }
+
+  if (original_positions->size() == 0) {
+    return true;
+  }
+
+  for (size_t i = 0; i < original_positions->size(); ++i) {
+    PositionTableEntry original = original_positions->at(i);
+    PositionTableEntry optimized = original_positions->at(i);
+    CHECK(original.source_position > 0);
+    if ((original.is_statement || optimized.is_statement) ||
+        (original.source_position != optimized.source_position) ||
+        (original.source_position < 0)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+void SourcePositionMatcher::StripUnneededExpressionPositions(
+    Handle<BytecodeArray> bytecode_array,
+    std::vector<PositionTableEntry>* expression_positions,
+    int next_statement_bytecode_offset) {
+  size_t j = 0;
+  for (size_t i = 0; i < expression_positions->size(); ++i) {
+    CHECK(expression_positions->at(i).source_position > 0 &&
+          !expression_positions->at(i).is_statement);
+    int bytecode_end = (i == expression_positions->size() - 1)
+                           ? next_statement_bytecode_offset
+                           : expression_positions->at(i + 1).bytecode_offset;
+    if (ExpressionPositionIsNeeded(bytecode_array,
+                                   expression_positions->at(i).bytecode_offset,
+                                   bytecode_end)) {
+      expression_positions->at(j++) = expression_positions->at(i);
+    }
+  }
+  expression_positions->resize(j);
+}
+
+void SourcePositionMatcher::AdvanceBytecodeIterator(
+    BytecodeArrayIterator* iterator, int bytecode_offset) {
+  while (iterator->current_offset() != bytecode_offset) {
+    iterator->Advance();
+  }
+}
+
+bool SourcePositionMatcher::ExpressionPositionIsNeeded(
+    Handle<BytecodeArray> bytecode_array, int start_offset, int end_offset) {
+  CHECK_GT(end_offset, start_offset);
+  BytecodeArrayIterator iterator(bytecode_array);
+  AdvanceBytecodeIterator(&iterator, start_offset);
+
+  while (iterator.current_offset() != end_offset) {
+    if (Bytecodes::IsWithoutExternalSideEffects(iterator.current_bytecode())) {
+      iterator.Advance();
+    } else {
+      // Bytecode could throw so need an expression position.
+      return true;
+    }
+  }
+  return false;
+}
+
+void SourcePositionMatcher::MoveToNextStatement(
+    SourcePositionTableIterator* iterator,
+    std::vector<PositionTableEntry>* positions) {
+  iterator->Advance();
+  positions->clear();
+  while (!iterator->done()) {
+    if (iterator->is_statement()) {
+      break;
+    }
+    positions->push_back({iterator->bytecode_offset(),
+                          iterator->source_position(),
+                          iterator->is_statement()});
+    iterator->Advance();
+  }
+}
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
diff --git a/test/cctest/interpreter/source-position-matcher.h b/test/cctest/interpreter/source-position-matcher.h
new file mode 100644
index 0000000..0bb5bed
--- /dev/null
+++ b/test/cctest/interpreter/source-position-matcher.h
@@ -0,0 +1,50 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TEST_CCTEST_INTERPRETER_SOURCE_POSITION_COMPARER_H_
+#define TEST_CCTEST_INTERPRETER_SOURCE_POSITION_COMPARER_H_
+
+#include "src/interpreter/bytecode-array-iterator.h"
+#include "src/interpreter/source-position-table.h"
+#include "src/objects.h"
+#include "src/v8.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+class SourcePositionMatcher final {
+ public:
+  bool Match(Handle<BytecodeArray> original, Handle<BytecodeArray> optimized);
+
+ private:
+  bool HasNewExpressionPositionsInOptimized(
+      const std::vector<PositionTableEntry>* const original_positions,
+      const std::vector<PositionTableEntry>* const optimized_positions);
+
+  bool CompareExpressionPositions(
+      const std::vector<PositionTableEntry>* const original_positions,
+      const std::vector<PositionTableEntry>* const optimized_positions);
+
+  void StripUnneededExpressionPositions(
+      Handle<BytecodeArray> bytecode_array,
+      std::vector<PositionTableEntry>* positions,
+      int next_statement_bytecode_offset);
+
+  bool ExpressionPositionIsNeeded(Handle<BytecodeArray> bytecode_array,
+                                  int start_offset, int end_offset);
+
+  void MoveToNextStatement(
+      SourcePositionTableIterator* iterator,
+      std::vector<PositionTableEntry>* expression_positions);
+
+  void AdvanceBytecodeIterator(BytecodeArrayIterator* iterator,
+                               int bytecode_offset);
+};
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
+
+#endif  // TEST_CCTEST_INTERPRETER_SOURCE_POSITION_COMPARER_H_
diff --git a/test/cctest/interpreter/test-bytecode-generator.cc b/test/cctest/interpreter/test-bytecode-generator.cc
index 2519f25..401ea14 100644
--- a/test/cctest/interpreter/test-bytecode-generator.cc
+++ b/test/cctest/interpreter/test-bytecode-generator.cc
@@ -113,6 +113,44 @@
   return actual_stream.str();
 }
 
+bool CompareTexts(const std::string& generated, const std::string& expected) {
+  std::istringstream generated_stream(generated);
+  std::istringstream expected_stream(expected);
+  std::string generated_line;
+  std::string expected_line;
+  // Line number does not include golden file header.
+  int line_number = 0;
+
+  do {
+    std::getline(generated_stream, generated_line);
+    std::getline(expected_stream, expected_line);
+
+    if (!generated_stream.good() && !expected_stream.good()) {
+      return true;
+    }
+
+    if (!generated_stream.good()) {
+      std::cerr << "Expected has extra lines after line " << line_number
+                << "\n";
+      std::cerr << "  Expected: '" << expected_line << "'\n";
+      return false;
+    } else if (!expected_stream.good()) {
+      std::cerr << "Generated has extra lines after line " << line_number
+                << "\n";
+      std::cerr << "  Generated: '" << generated_line << "'\n";
+      return false;
+    }
+
+    if (generated_line != expected_line) {
+      std::cerr << "Inputs differ at line " << line_number << "\n";
+      std::cerr << "  Generated: '" << generated_line << "'\n";
+      std::cerr << "  Expected:  '" << expected_line << "'\n";
+      return false;
+    }
+    line_number++;
+  } while (true);
+}
+
 using ConstantPoolType = BytecodeExpectationsPrinter::ConstantPoolType;
 
 TEST(PrimitiveReturnStatements) {
@@ -122,27 +160,27 @@
   const char* snippets[] = {
       "",
 
-      "return;",
+      "return;\n",
 
-      "return null;",
+      "return null;\n",
 
-      "return true;",
+      "return true;\n",
 
-      "return false;",
+      "return false;\n",
 
-      "return 0;",
+      "return 0;\n",
 
-      "return +1;",
+      "return +1;\n",
 
-      "return -1;",
+      "return -1;\n",
 
-      "return +127;",
+      "return +127;\n",
 
-      "return -128;",
+      "return -128;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("PrimitiveReturnStatements.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("PrimitiveReturnStatements.golden")));
 }
 
 TEST(PrimitiveExpressions) {
@@ -150,35 +188,35 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kNumber);
   const char* snippets[] = {
-      "var x = 0; return x;",
+      "var x = 0; return x;\n",
 
-      "var x = 0; return x + 3;",
+      "var x = 0; return x + 3;\n",
 
-      "var x = 0; return x - 3;",
+      "var x = 0; return x - 3;\n",
 
-      "var x = 4; return x * 3;",
+      "var x = 4; return x * 3;\n",
 
-      "var x = 4; return x / 3;",
+      "var x = 4; return x / 3;\n",
 
-      "var x = 4; return x % 3;",
+      "var x = 4; return x % 3;\n",
 
-      "var x = 1; return x | 2;",
+      "var x = 1; return x | 2;\n",
 
-      "var x = 1; return x ^ 2;",
+      "var x = 1; return x ^ 2;\n",
 
-      "var x = 1; return x & 2;",
+      "var x = 1; return x & 2;\n",
 
-      "var x = 10; return x << 3;",
+      "var x = 10; return x << 3;\n",
 
-      "var x = 10; return x >> 3;",
+      "var x = 10; return x >> 3;\n",
 
-      "var x = 10; return x >>> 3;",
+      "var x = 10; return x >>> 3;\n",
 
-      "var x = 0; return (x, 3);",
+      "var x = 0; return (x, 3);\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("PrimitiveExpressions.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("PrimitiveExpressions.golden")));
 }
 
 TEST(LogicalExpressions) {
@@ -186,43 +224,43 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kNumber);
   const char* snippets[] = {
-      "var x = 0; return x || 3;",
+      "var x = 0; return x || 3;\n",
 
-      "var x = 0; return (x == 1) || 3;",
+      "var x = 0; return (x == 1) || 3;\n",
 
-      "var x = 0; return x && 3;",
+      "var x = 0; return x && 3;\n",
 
-      "var x = 0; return (x == 0) && 3;",
+      "var x = 0; return (x == 0) && 3;\n",
 
-      "var x = 0; return x || (1, 2, 3);",
+      "var x = 0; return x || (1, 2, 3);\n",
 
-      "var a = 2, b = 3, c = 4; return a || (a, b, a, b, c = 5, 3);",
+      "var a = 2, b = 3, c = 4; return a || (a, b, a, b, c = 5, 3);\n",
 
       "var x = 1; var a = 2, b = 3; return x || ("  //
       REPEAT_32("\n  a = 1, b = 2, ")               //
-      "3);",
+      "3);\n",
 
       "var x = 0; var a = 2, b = 3; return x && ("  //
       REPEAT_32("\n  a = 1, b = 2, ")               //
-      "3);",
+      "3);\n",
 
       "var x = 1; var a = 2, b = 3; return (x > 3) || ("  //
       REPEAT_32("\n  a = 1, b = 2, ")                     //
-      "3);",
+      "3);\n",
 
       "var x = 0; var a = 2, b = 3; return (x < 5) && ("  //
       REPEAT_32("\n  a = 1, b = 2, ")                     //
-      "3);",
+      "3);\n",
 
-      "return 0 && 3;",
+      "return 0 && 3;\n",
 
-      "return 1 || 3;",
+      "return 1 || 3;\n",
 
-      "var x = 1; return x && 3 || 0, 1;",
+      "var x = 1; return x && 3 || 0, 1;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("LogicalExpressions.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("LogicalExpressions.golden")));
 }
 
 TEST(Parameters) {
@@ -248,8 +286,8 @@
       "function f(arg1, arg2, arg3, arg4) { arg2 = 1; }",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets, "", "\nf();"),
-           LoadGolden("Parameters.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
+                     LoadGolden("Parameters.golden")));
 }
 
 TEST(IntegerConstants) {
@@ -257,15 +295,15 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kNumber);
   const char* snippets[] = {
-      "return 12345678;",
+      "return 12345678;\n",
 
-      "var a = 1234; return 5678;",
+      "var a = 1234; return 5678;\n",
 
-      "var a = 1234; return 1234;",
+      "var a = 1234; return 1234;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("IntegerConstants.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("IntegerConstants.golden")));
 }
 
 TEST(HeapNumberConstants) {
@@ -273,19 +311,19 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kNumber);
   const char* snippets[] = {
-      "return 1.2;",
+      "return 1.2;\n",
 
-      "var a = 1.2; return 2.6;",
+      "var a = 1.2; return 2.6;\n",
 
-      "var a = 3.14; return 3.14;",
+      "var a = 3.14; return 3.14;\n",
 
       "var a;"                    //
       REPEAT_256("\na = 1.414;")  //
-      " a = 3.14;",
+      " a = 3.14;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("HeapNumberConstants.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("HeapNumberConstants.golden")));
 }
 
 TEST(StringConstants) {
@@ -293,15 +331,15 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kString);
   const char* snippets[] = {
-      "return \"This is a string\";",
+      "return \"This is a string\";\n",
 
-      "var a = \"First string\"; return \"Second string\";",
+      "var a = \"First string\"; return \"Second string\";\n",
 
-      "var a = \"Same string\"; return \"Same string\";",
+      "var a = \"Same string\"; return \"Same string\";\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("StringConstants.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("StringConstants.golden")));
 }
 
 TEST(PropertyLoads) {
@@ -313,16 +351,16 @@
 
   const char* snippets[] = {
     "function f(a) { return a.name; }\n"
-    "f({name : \"test\"});",
+    "f({name : \"test\"});\n",
 
     "function f(a) { return a[\"key\"]; }\n"
-    "f({key : \"test\"});",
+    "f({key : \"test\"});\n",
 
     "function f(a) { return a[100]; }\n"
-    "f({100 : \"test\"});",
+    "f({100 : \"test\"});\n",
 
     "function f(a, b) { return a[b]; }\n"
-    "f({arg : \"test\"}, \"arg\");",
+    "f({arg : \"test\"}, \"arg\");\n",
 
     "function f(a) { var b = a.name; return a[-124]; }\n"
     "f({\"-124\" : \"test\", name : 123 })",
@@ -344,7 +382,8 @@
     "f({name : \"test\"}, \"name\")\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("PropertyLoads.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("PropertyLoads.golden")));
 }
 
 TEST(PropertyStores) {
@@ -407,7 +446,8 @@
     "f({name : \"test\"})\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("PropertyStores.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("PropertyStores.golden")));
 }
 
 #define FUNC_ARG "new (function Obj() { this.func = function() { return; }})()"
@@ -436,7 +476,8 @@
       "f(" FUNC_ARG ")",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("PropertyCall.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("PropertyCall.golden")));
 }
 
 TEST(LoadGlobal) {
@@ -465,10 +506,11 @@
     REPEAT_127("  b.name;\n")
     "  return a;\n"
     "}\n"
-    "f({name: 1});",
+    "f({name: 1});\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("LoadGlobal.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("LoadGlobal.golden")));
 }
 
 TEST(StoreGlobal) {
@@ -481,18 +523,18 @@
   const char* snippets[] = {
     "var a = 1;\n"
     "function f() { a = 2; }\n"
-    "f();",
+    "f();\n",
 
     "var a = \"test\"; function f(b) { a = b; }\n"
-    "f(\"global\");",
+    "f(\"global\");\n",
 
     "'use strict'; var a = 1;\n"
     "function f() { a = 2; }\n"
-    "f();",
+    "f();\n",
 
     "a = 1;\n"
     "function f() { a = 2; }\n"
-    "f();",
+    "f();\n",
 
     "a = 1;\n"
     "function f(b) {\n"
@@ -500,7 +542,7 @@
     REPEAT_127("  b.name;\n")
     "  a = 2;\n"
     "}\n"
-    "f({name: 1});",
+    "f({name: 1});\n",
 
     "a = 1;\n"
     "function f(b) {\n"
@@ -509,10 +551,11 @@
     REPEAT_127("  b.name;\n")
     "  a = 2;\n"
     "}\n"
-    "f({name: 1});",
+    "f({name: 1});\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("StoreGlobal.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("StoreGlobal.golden")));
 }
 
 TEST(CallGlobal) {
@@ -525,14 +568,15 @@
   const char* snippets[] = {
       "function t() { }\n"
       "function f() { return t(); }\n"
-      "f();",
+      "f();\n",
 
       "function t(a, b, c) { }\n"
       "function f() { return t(1, 2, 3); }\n"
-      "f();",
+      "f();\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("CallGlobal.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("CallGlobal.golden")));
 }
 
 TEST(CallRuntime) {
@@ -544,30 +588,26 @@
 
   const char* snippets[] = {
       "function f() { %TheHole() }\n"
-      "f();",
+      "f();\n",
 
       "function f(a) { return %IsArray(a) }\n"
-      "f(undefined);",
+      "f(undefined);\n",
 
       "function f() { return %Add(1, 2) }\n"
-      "f();",
+      "f();\n",
 
       "function f() { return %spread_iterable([1]) }\n"
-      "f();",
+      "f();\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("CallRuntime.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("CallRuntime.golden")));
 }
 
 TEST(IfConditions) {
-  if (FLAG_harmony_instanceof) {
-    // TODO(mvstanton): when ES6 instanceof ships, regenerate the bytecode
-    // expectations and remove this flag check.
-    return;
-  }
   InitializedIgnitionHandleScope scope;
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
-                                      ConstantPoolType::kNumber);
+                                      ConstantPoolType::kMixed);
   printer.set_wrap(false);
   printer.set_test_function_name("f");
 
@@ -579,7 +619,7 @@
     "    return -1;\n"
     "  }\n"
     "};\n"
-    "f();",
+    "f();\n",
 
     "function f() {\n"
     "  if ('lucky') {\n"
@@ -588,7 +628,7 @@
     "    return -1;\n"
     "  }\n"
     "};\n"
-    "f();",
+    "f();\n",
 
     "function f() {\n"
     "  if (false) {\n"
@@ -597,14 +637,14 @@
     "    return -1;\n"
     "  }\n"
     "};\n"
-    "f();",
+    "f();\n",
 
     "function f() {\n"
     "  if (false) {\n"
     "    return 1;\n"
     "  }\n"
     "};\n"
-    "f();",
+    "f();\n",
 
     "function f() {\n"
     "  var a = 1;\n"
@@ -614,7 +654,7 @@
     "    return 2;\n"
     "  }\n"
     "};\n"
-    "f();",
+    "f();\n",
 
     "function f(a) {\n"
     "  if (a <= 0) {\n"
@@ -623,14 +663,14 @@
     "    return -200;\n"
     "  }\n"
     "};\n"
-    "f(99);",
+    "f(99);\n",
 
     "function f(a, b) { if (a in b) { return 200; } }"
-    "f('prop', { prop: 'yes'});",
+    "f('prop', { prop: 'yes'});\n",
 
     "function f(z) { var a = 0; var b = 0; if (a === 0.01) {\n"
     REPEAT_64("  b = a; a = b;\n")
-    " return 200; } else { return -200; } } f(0.001);",
+    " return 200; } else { return -200; } } f(0.001);\n",
 
     "function f() {\n"
     "  var a = 0; var b = 0;\n"
@@ -638,7 +678,7 @@
     REPEAT_64("  b = a; a = b;\n")
     "  return 200; } else { return -200; }\n"
     "};\n"
-    "f();",
+    "f();\n",
 
     "function f(a, b) {\n"
     "  if (a == b) { return 1; }\n"
@@ -651,7 +691,7 @@
     "  if (a instanceof b) { return 1; }\n"
     "  return 0;\n"
     "}\n"
-    "f(1, 1);",
+    "f(1, 1);\n",
 
     "function f() {\n"
     "  var a = 0;\n"
@@ -661,10 +701,11 @@
     "    return -20;\n"
     "  }\n"
     "};\n"
-    "f();",
+    "f();\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("IfConditions.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("IfConditions.golden")));
 }
 
 TEST(DeclareGlobals) {
@@ -677,18 +718,19 @@
   printer.set_top_level(true);
 
   const char* snippets[] = {
-      "var a = 1;",
+      "var a = 1;\n",
 
-      "function f() {}",
+      "function f() {}\n",
 
       "var a = 1;\n"
-      "a=2;",
+      "a=2;\n",
 
       "function f() {}\n"
-      "f();",
+      "f();\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("DeclareGlobals.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("DeclareGlobals.golden")));
 }
 
 TEST(BreakableBlocks) {
@@ -703,7 +745,7 @@
       "  break label;\n"
       "  x = x + 1;\n"
       "}\n"
-      "return x;",
+      "return x;\n",
 
       "var sum = 0;\n"
       "outer: {\n"
@@ -714,7 +756,7 @@
       "    }\n"
       "  }\n"
       "}\n"
-      "return sum;",
+      "return sum;\n",
 
       "outer: {\n"
       "  let y = 10;\n"
@@ -731,11 +773,11 @@
       "    y = 3;\n"
       "  }\n"
       "}\n"
-      "x = 4;",
+      "x = 4;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("BreakableBlocks.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("BreakableBlocks.golden")));
 }
 
 TEST(BasicLoops) {
@@ -745,13 +787,13 @@
   const char* snippets[] = {
       "var x = 0;\n"
       "while (false) { x = 99; break; continue; }\n"
-      "return x;",
+      "return x;\n",
 
       "var x = 0;\n"
       "while (false) {\n"
       "  x = x + 1;\n"
       "};\n"
-      "return x;",
+      "return x;\n",
 
       "var x = 0;\n"
       "var y = 1;\n"
@@ -761,7 +803,7 @@
       "  if (x == 3) continue;\n"
       "  if (x == 4) break;\n"
       "}\n"
-      "return y;",
+      "return y;\n",
 
       "var i = 0;\n"
       "while (true) {\n"
@@ -772,7 +814,7 @@
       "  if (i == 5) break;\n"
       "  i = i + 1;\n"
       "}\n"
-      "return i;",
+      "return i;\n",
 
       "var i = 0;\n"
       "while (true) {\n"
@@ -783,7 +825,7 @@
       "  i = i + 1;\n"
       "  break;\n"
       "}\n"
-      "return i;",
+      "return i;\n",
 
       "var x = 10;\n"
       "var y = 1;\n"
@@ -791,7 +833,7 @@
       "  y = y * 12;\n"
       "  x = x - 1;\n"
       "}\n"
-      "return y;",
+      "return y;\n",
 
       "var x = 0; var y = 1;\n"
       "do {\n"
@@ -800,7 +842,7 @@
       "  if (x == 6) continue;\n"
       "  x = x + 1;\n"
       "} while (x < 10);\n"
-      "return y;",
+      "return y;\n",
 
       "var x = 10;\n"
       "var y = 1;\n"
@@ -808,7 +850,7 @@
       "  y = y * 12;\n"
       "  x = x - 1;\n"
       "} while (x);\n"
-      "return y;",
+      "return y;\n",
 
       "var x = 0; var y = 1;\n"
       "do {\n"
@@ -817,7 +859,7 @@
       "  x = x + 1;\n"
       "  if (x == 6) continue;\n"
       "} while (false);\n"
-      "return y;",
+      "return y;\n",
 
       "var x = 0; var y = 1;\n"
       "do {\n"
@@ -826,56 +868,56 @@
       "  x = x + 1;\n"
       "  if (x == 6) continue;\n"
       "} while (true);\n"
-      "return y;",
+      "return y;\n",
 
       "var x = 0;\n"
       "for (;;) {\n"
       "  if (x == 1) break;\n"
       "  if (x == 2) continue;\n"
       "  x = x + 1;\n"
-      "}",
+      "}\n",
 
       "for (var x = 0;;) {\n"
       "  if (x == 1) break;\n"
       "  if (x == 2) continue;\n"
       "  x = x + 1;\n"
-      "}",
+      "}\n",
 
       "var x = 0;\n"
       "for (;; x = x + 1) {\n"
       "  if (x == 1) break;\n"
       "  if (x == 2) continue;\n"
-      "}",
+      "}\n",
 
       "for (var x = 0;; x = x + 1) {\n"
       "  if (x == 1) break;\n"
       "  if (x == 2) continue;\n"
-      "}",
+      "}\n",
 
       "var u = 0;\n"
       "for (var i = 0; i < 100; i = i + 1) {\n"
       "  u = u + 1;\n"
       "  continue;\n"
-      "}",
+      "}\n",
 
       "var y = 1;\n"
       "for (var x = 10; x; --x) {\n"
       "  y = y * 12;\n"
       "}\n"
-      "return y;",
+      "return y;\n",
 
       "var x = 0;\n"
       "for (var i = 0; false; i++) {\n"
       "  x = x + 1;\n"
       "};\n"
-      "return x;",
+      "return x;\n",
 
       "var x = 0;\n"
       "for (var i = 0; true; ++i) {\n"
       "  x = x + 1;\n"
       "  if (x == 20) break;\n"
       "};\n"
-      "return x;",
+      "return x;\n",
 
       "var a = 0;\n"
       "while (a) {\n"
@@ -885,10 +927,11 @@
       "   if (z) continue;\n"
       "   z++;\n"
       "  }\n"
-      "}",
+      "}\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("BasicLoops.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("BasicLoops.golden")));
 }
 
 TEST(JumpsRequiringConstantWideOperands) {
@@ -904,11 +947,11 @@
     "  if (i == 1) continue;\n"
     "  if (i == 2) break;\n"
     "}\n"
-    "return 3;",
+    "return 3;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("JumpsRequiringConstantWideOperands.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("JumpsRequiringConstantWideOperands.golden")));
 }
 
 TEST(UnaryOperators) {
@@ -920,32 +963,33 @@
       "while (x != 10) {\n"
       "  x = x + 10;\n"
       "}\n"
-      "return x;",
+      "return x;\n",
 
       "var x = false;\n"
       "do {\n"
       "  x = !x;\n"
       "} while(x == false);\n"
-      "return x;",
+      "return x;\n",
 
       "var x = 101;\n"
-      "return void(x * 3);",
+      "return void(x * 3);\n",
 
       "var x = 1234;\n"
       "var y = void (x * x - 1);\n"
-      "return y;",
+      "return y;\n",
 
       "var x = 13;\n"
-      "return ~x;",
+      "return ~x;\n",
 
       "var x = 13;\n"
-      "return +x;",
+      "return +x;\n",
 
       "var x = 13;\n"
-      "return -x;",
+      "return -x;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("UnaryOperators.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("UnaryOperators.golden")));
 }
 
 TEST(Typeof) {
@@ -967,8 +1011,8 @@
       "};",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets, "", "\nf();"),
-           LoadGolden("Typeof.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
+                     LoadGolden("Typeof.golden")));
 }
 
 TEST(Delete) {
@@ -977,23 +1021,24 @@
                                       ConstantPoolType::kMixed);
 
   const char* snippets[] = {
-      "var a = {x:13, y:14}; return delete a.x;",
+      "var a = {x:13, y:14}; return delete a.x;\n",
 
-      "'use strict'; var a = {x:13, y:14}; return delete a.x;",
+      "'use strict'; var a = {x:13, y:14}; return delete a.x;\n",
 
-      "var a = {1:13, 2:14}; return delete a[2];",
+      "var a = {1:13, 2:14}; return delete a[2];\n",
 
-      "var a = 10; return delete a;",
+      "var a = 10; return delete a;\n",
 
       "'use strict';\n"
       "var a = {1:10};\n"
       "(function f1() {return a;});\n"
-      "return delete a[1];",
+      "return delete a[1];\n",
 
-      "return delete 'test';",
+      "return delete 'test';\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("Delete.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("Delete.golden")));
 }
 
 TEST(GlobalDelete) {
@@ -1008,29 +1053,30 @@
       "function f() {\n"
       "  return delete a.x;\n"
       "};\n"
-      "f();",
+      "f();\n",
 
       "a = {1:13, 2:14};\n"
       "function f() {\n"
       "  'use strict';\n"
       "  return delete a[1];\n"
       "};\n"
-      "f();",
+      "f();\n",
 
       "var a = {x:13, y:14};\n"
       "function f() {\n"
       "  return delete a;\n"
       "};\n"
-      "f();",
+      "f();\n",
 
       "b = 30;\n"
       "function f() {\n"
       "  return delete b;\n"
       "};\n"
-      "f();",
+      "f();\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("GlobalDelete.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("GlobalDelete.golden")));
 }
 
 TEST(FunctionLiterals) {
@@ -1039,15 +1085,15 @@
                                       ConstantPoolType::kMixed);
 
   const char* snippets[] = {
-      "return function(){ }",
+      "return function(){ }\n",
 
-      "return (function(){ })()",
+      "return (function(){ })()\n",
 
-      "return (function(x){ return x; })(1)",
+      "return (function(x){ return x; })(1)\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("FunctionLiterals.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("FunctionLiterals.golden")));
 }
 
 TEST(RegExpLiterals) {
@@ -1056,14 +1102,15 @@
                                       ConstantPoolType::kString);
 
   const char* snippets[] = {
-      "return /ab+d/;",
+      "return /ab+d/;\n",
 
-      "return /(\\w+)\\s(\\w+)/i;",
+      "return /(\\w+)\\s(\\w+)/i;\n",
 
-      "return /ab+d/.exec('abdd');",
+      "return /ab+d/.exec('abdd');\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("RegExpLiterals.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("RegExpLiterals.golden")));
 }
 
 TEST(RegExpLiteralsWide) {
@@ -1074,11 +1121,11 @@
   const char* snippets[] = {
       "var a;"                   //
       REPEAT_256("\na = 1.23;")  //
-      "\nreturn /ab+d/;",
+      "\nreturn /ab+d/;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("RegExpLiteralsWide.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("RegExpLiteralsWide.golden")));
 }
 
 TEST(ArrayLiterals) {
@@ -1087,16 +1134,17 @@
                                       ConstantPoolType::kMixed);
 
   const char* snippets[] = {
-      "return [ 1, 2 ];",
+      "return [ 1, 2 ];\n",
 
-      "var a = 1; return [ a, a + 1 ];",
+      "var a = 1; return [ a, a + 1 ];\n",
 
-      "return [ [ 1, 2 ], [ 3 ] ];",
+      "return [ [ 1, 2 ], [ 3 ] ];\n",
 
-      "var a = 1; return [ [ a, 2 ], [ a + 2 ] ];",
+      "var a = 1; return [ [ a, 2 ], [ a + 2 ] ];\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("ArrayLiterals.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("ArrayLiterals.golden")));
 }
 
 TEST(ArrayLiteralsWide) {
@@ -1107,11 +1155,11 @@
   const char* snippets[] = {
       "var a;"                   //
       REPEAT_256("\na = 1.23;")  //
-      "\nreturn [ 1 , 2 ];",
+      "\nreturn [ 1 , 2 ];\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("ArrayLiteralsWide.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("ArrayLiteralsWide.golden")));
 }
 
 TEST(ObjectLiterals) {
@@ -1120,38 +1168,39 @@
                                       ConstantPoolType::kMixed);
 
   const char* snippets[] = {
-      "return { };",
+      "return { };\n",
 
-      "return { name: 'string', val: 9.2 };",
+      "return { name: 'string', val: 9.2 };\n",
 
-      "var a = 1; return { name: 'string', val: a };",
+      "var a = 1; return { name: 'string', val: a };\n",
 
-      "var a = 1; return { val: a, val: a + 1 };",
+      "var a = 1; return { val: a, val: a + 1 };\n",
 
-      "return { func: function() { } };",
+      "return { func: function() { } };\n",
 
-      "return { func(a) { return a; } };",
+      "return { func(a) { return a; } };\n",
 
-      "return { get a() { return 2; } };",
+      "return { get a() { return 2; } };\n",
 
-      "return { get a() { return this.x; }, set a(val) { this.x = val } };",
+      "return { get a() { return this.x; }, set a(val) { this.x = val } };\n",
 
-      "return { set b(val) { this.y = val } };",
+      "return { set b(val) { this.y = val } };\n",
 
-      "var a = 1; return { 1: a };",
+      "var a = 1; return { 1: a };\n",
 
-      "return { __proto__: null };",
+      "return { __proto__: null };\n",
 
-      "var a = 'test'; return { [a]: 1 };",
+      "var a = 'test'; return { [a]: 1 };\n",
 
-      "var a = 'test'; return { val: a, [a]: 1 };",
+      "var a = 'test'; return { val: a, [a]: 1 };\n",
 
-      "var a = 'test'; return { [a]: 1, __proto__: {} };",
+      "var a = 'test'; return { [a]: 1, __proto__: {} };\n",
 
-      "var n = 'name'; return { [n]: 'val', get a() { }, set a(b) {} };",
+      "var n = 'name'; return { [n]: 'val', get a() { }, set a(b) {} };\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("ObjectLiterals.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("ObjectLiterals.golden")));
 }
 
 TEST(ObjectLiteralsWide) {
@@ -1161,11 +1210,11 @@
   const char* snippets[] = {
       "var a;"                   //
       REPEAT_256("\na = 1.23;")  //
-      "\nreturn { name: 'string', val: 9.2 };",
+      "\nreturn { name: 'string', val: 9.2 };\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("ObjectLiteralsWide.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("ObjectLiteralsWide.golden")));
 }
 
 TEST(TopLevelObjectLiterals) {
@@ -1178,11 +1227,11 @@
   printer.set_top_level(true);
 
   const char* snippets[] = {
-      "var a = { func: function() { } };",
+      "var a = { func: function() { } };\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("TopLevelObjectLiterals.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("TopLevelObjectLiterals.golden")));
 }
 
 TEST(TryCatch) {
@@ -1191,14 +1240,15 @@
                                       ConstantPoolType::kString);
 
   const char* snippets[] = {
-      "try { return 1; } catch(e) { return 2; }",
+      "try { return 1; } catch(e) { return 2; }\n",
 
       "var a;\n"
       "try { a = 1 } catch(e1) {};\n"
-      "try { a = 2 } catch(e2) { a = 3 }",
+      "try { a = 2 } catch(e2) { a = 3 }\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("TryCatch.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("TryCatch.golden")));
 }
 
 TEST(TryFinally) {
@@ -1207,17 +1257,18 @@
                                       ConstantPoolType::kString);
   const char* snippets[] = {
       "var a = 1;\n"
-      "try { a = 2; } finally { a = 3; }",
+      "try { a = 2; } finally { a = 3; }\n",
 
       "var a = 1;\n"
-      "try { a = 2; } catch(e) { a = 20 } finally { a = 3; }",
+      "try { a = 2; } catch(e) { a = 20 } finally { a = 3; }\n",
 
       "var a; try {\n"
       "  try { a = 1 } catch(e) { a = 2 }\n"
-      "} catch(e) { a = 20 } finally { a = 3; }",
+      "} catch(e) { a = 20 } finally { a = 3; }\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("TryFinally.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("TryFinally.golden")));
 }
 
 TEST(Throw) {
@@ -1225,14 +1276,15 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kString);
   const char* snippets[] = {
-      "throw 1;",
+      "throw 1;\n",
 
-      "throw 'Error';",
+      "throw 'Error';\n",
 
-      "var a = 1; if (a) { throw 'Error'; };",
+      "var a = 1; if (a) { throw 'Error'; };\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("Throw.golden"));
+  CHECK(
+      CompareTexts(BuildActual(printer, snippets), LoadGolden("Throw.golden")));
 }
 
 TEST(CallNew) {
@@ -1245,11 +1297,11 @@
   const char* snippets[] = {
       "function bar() { this.value = 0; }\n"
       "function f() { return new bar(); }\n"
-      "f();",
+      "f();\n",
 
       "function bar(x) { this.value = 18; this.x = x;}\n"
       "function f() { return new bar(3); }\n"
-      "f();",
+      "f();\n",
 
       "function bar(w, x, y, z) {\n"
       "  this.value = 18;\n"
@@ -1258,10 +1310,11 @@
       "  this.z = z;\n"
       "}\n"
       "function f() { return new bar(3, 4, 5); }\n"
-      "f();",
+      "f();\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("CallNew.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("CallNew.golden")));
 }
 
 TEST(ContextVariables) {
@@ -1274,27 +1327,27 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kMixed);
   const char* snippets[] = {
-    "var a; return function() { a = 1; };",
+    "var a; return function() { a = 1; };\n",
 
-    "var a = 1; return function() { a = 2; };",
+    "var a = 1; return function() { a = 2; };\n",
 
-    "var a = 1; var b = 2; return function() { a = 2; b = 3 };",
+    "var a = 1; var b = 2; return function() { a = 2; b = 3 };\n",
 
-    "var a; (function() { a = 2; })(); return a;",
+    "var a; (function() { a = 2; })(); return a;\n",
 
     "'use strict';\n"
     "let a = 1;\n"
-    "{ let b = 2; return function() { a + b; }; }",
+    "{ let b = 2; return function() { a + b; }; }\n",
 
     "'use strict';\n"
     REPEAT_249_UNIQUE_VARS()
     "eval();\n"
     "var b = 100;\n"
-    "return b",
+    "return b\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("ContextVariables.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("ContextVariables.golden")));
 }
 
 TEST(ContextParameters) {
@@ -1314,8 +1367,8 @@
       "function f() { var self = this; return function() { self = 2; }; }",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets, "", "\nf();"),
-           LoadGolden("ContextParameters.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
+                     LoadGolden("ContextParameters.golden")));
 }
 
 TEST(OuterContextVariables) {
@@ -1345,8 +1398,8 @@
       "var f = new Outer().getInnerFunc();",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets, "", "\nf();"),
-           LoadGolden("OuterContextVariables.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
+                     LoadGolden("OuterContextVariables.golden")));
 }
 
 TEST(CountOperators) {
@@ -1354,30 +1407,31 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kMixed);
   const char* snippets[] = {
-      "var a = 1; return ++a;",
+      "var a = 1; return ++a;\n",
 
-      "var a = 1; return a++;",
+      "var a = 1; return a++;\n",
 
-      "var a = 1; return --a;",
+      "var a = 1; return --a;\n",
 
-      "var a = 1; return a--;",
+      "var a = 1; return a--;\n",
 
-      "var a = { val: 1 }; return a.val++;",
+      "var a = { val: 1 }; return a.val++;\n",
 
-      "var a = { val: 1 }; return --a.val;",
+      "var a = { val: 1 }; return --a.val;\n",
 
-      "var name = 'var'; var a = { val: 1 }; return a[name]--;",
+      "var name = 'var'; var a = { val: 1 }; return a[name]--;\n",
 
-      "var name = 'var'; var a = { val: 1 }; return ++a[name];",
+      "var name = 'var'; var a = { val: 1 }; return ++a[name];\n",
 
-      "var a = 1; var b = function() { return a }; return ++a;",
+      "var a = 1; var b = function() { return a }; return ++a;\n",
 
-      "var a = 1; var b = function() { return a }; return a--;",
+      "var a = 1; var b = function() { return a }; return a--;\n",
 
-      "var idx = 1; var a = [1, 2]; return a[idx++] = 2;",
+      "var idx = 1; var a = [1, 2]; return a[idx++] = 2;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("CountOperators.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("CountOperators.golden")));
 }
 
 TEST(GlobalCountOperators) {
@@ -1390,23 +1444,23 @@
   const char* snippets[] = {
       "var global = 1;\n"
       "function f() { return ++global; }\n"
-      "f();",
+      "f();\n",
 
       "var global = 1;\n"
       "function f() { return global--; }\n"
-      "f();",
+      "f();\n",
 
       "unallocated = 1;\n"
       "function f() { 'use strict'; return --unallocated; }\n"
-      "f();",
+      "f();\n",
 
       "unallocated = 1;\n"
       "function f() { return unallocated++; }\n"
-      "f();",
+      "f();\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("GlobalCountOperators.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("GlobalCountOperators.golden")));
 }
 
 TEST(CompoundExpressions) {
@@ -1414,19 +1468,19 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kMixed);
   const char* snippets[] = {
-      "var a = 1; a += 2;",
+      "var a = 1; a += 2;\n",
 
-      "var a = 1; a /= 2;",
+      "var a = 1; a /= 2;\n",
 
-      "var a = { val: 2 }; a.name *= 2;",
+      "var a = { val: 2 }; a.name *= 2;\n",
 
-      "var a = { 1: 2 }; a[1] ^= 2;",
+      "var a = { 1: 2 }; a[1] ^= 2;\n",
 
-      "var a = 1; (function f() { return a; }); a |= 24;",
+      "var a = 1; (function f() { return a; }); a |= 24;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("CompoundExpressions.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("CompoundExpressions.golden")));
 }
 
 TEST(GlobalCompoundExpressions) {
@@ -1439,15 +1493,15 @@
   const char* snippets[] = {
       "var global = 1;\n"
       "function f() { return global &= 1; }\n"
-      "f();",
+      "f();\n",
 
       "unallocated = 1;\n"
       "function f() { return unallocated += 1; }\n"
-      "f();",
+      "f();\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("GlobalCompoundExpressions.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("GlobalCompoundExpressions.golden")));
 }
 
 TEST(CreateArguments) {
@@ -1471,8 +1525,8 @@
       "function f(a, b, c) { 'use strict'; return arguments; }",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets, "", "\nf();"),
-           LoadGolden("CreateArguments.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
+                     LoadGolden("CreateArguments.golden")));
 }
 
 TEST(CreateRestParameter) {
@@ -1492,8 +1546,8 @@
       "function f(a, ...restArgs) { return restArgs[0] + arguments[0]; }",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets, "", "\nf();"),
-           LoadGolden("CreateRestParameter.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
+                     LoadGolden("CreateRestParameter.golden")));
 }
 
 TEST(ForIn) {
@@ -1501,29 +1555,30 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kMixed);
   const char* snippets[] = {
-      "for (var p in null) {}",
+      "for (var p in null) {}\n",
 
-      "for (var p in undefined) {}",
+      "for (var p in undefined) {}\n",
 
-      "for (var p in undefined) {}",
+      "for (var p in undefined) {}\n",
 
       "var x = 'potatoes';\n"
-      "for (var p in x) { return p; }",
+      "for (var p in x) { return p; }\n",
 
       "var x = 0;\n"
-      "for (var p in [1,2,3]) { x += p; }",
+      "for (var p in [1,2,3]) { x += p; }\n",
 
       "var x = { 'a': 1, 'b': 2 };\n"
       "for (x['a'] in [10, 20, 30]) {\n"
       "  if (x['a'] == 10) continue;\n"
       "  if (x['a'] == 20) break;\n"
-      "}",
+      "}\n",
 
       "var x = [ 10, 11, 12 ] ;\n"
-      "for (x[0] in [1,2,3]) { return x[3]; }",
+      "for (x[0] in [1,2,3]) { return x[3]; }\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("ForIn.golden"));
+  CHECK(
+      CompareTexts(BuildActual(printer, snippets), LoadGolden("ForIn.golden")));
 }
 
 TEST(ForOf) {
@@ -1531,21 +1586,22 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kMixed);
   const char* snippets[] = {
-      "for (var p of [0, 1, 2]) {}",
+      "for (var p of [0, 1, 2]) {}\n",
 
       "var x = 'potatoes';\n"
-      "for (var p of x) { return p; }",
+      "for (var p of x) { return p; }\n",
 
       "for (var x of [10, 20, 30]) {\n"
       "  if (x == 10) continue;\n"
       "  if (x == 20) break;\n"
-      "}",
+      "}\n",
 
       "var x = { 'a': 1, 'b': 2 };\n"
-      "for (x['a'] of [1,2,3]) { return x['a']; }",
+      "for (x['a'] of [1,2,3]) { return x['a']; }\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("ForOf.golden"));
+  CHECK(
+      CompareTexts(BuildActual(printer, snippets), LoadGolden("ForOf.golden")));
 }
 
 TEST(Conditional) {
@@ -1553,12 +1609,13 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kNumber);
   const char* snippets[] = {
-      "return 1 ? 2 : 3;",
+      "return 1 ? 2 : 3;\n",
 
-      "return 1 ? 2 ? 3 : 4 : 5;",
+      "return 1 ? 2 ? 3 : 4 : 5;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("Conditional.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("Conditional.golden")));
 }
 
 TEST(Switch) {
@@ -1570,39 +1627,39 @@
     "switch(a) {\n"
     " case 1: return 2;\n"
     " case 2: return 3;\n"
-    "}",
+    "}\n",
 
     "var a = 1;\n"
     "switch(a) {\n"
     " case 1: a = 2; break;\n"
     " case 2: a = 3; break;\n"
-    "}",
+    "}\n",
 
     "var a = 1;\n"
     "switch(a) {\n"
     " case 1: a = 2; // fall-through\n"
     " case 2: a = 3; break;\n"
-    "}",
+    "}\n",
 
     "var a = 1;\n"
     "switch(a) {\n"
     " case 2: break;\n"
     " case 3: break;\n"
     " default: a = 1; break;\n"
-    "}",
+    "}\n",
 
     "var a = 1;\n"
     "switch(typeof(a)) {\n"
     " case 2: a = 1; break;\n"
     " case 3: a = 2; break;\n"
     " default: a = 3; break;\n"
-    "}",
+    "}\n",
 
     "var a = 1;\n"
     "switch(a) {\n"
     " case typeof(a): a = 1; break;\n"
     " default: a = 2; break;\n"
-    "}",
+    "}\n",
 
     "var a = 1;\n"
     "switch(a) {\n"
@@ -1612,7 +1669,7 @@
     " case 2:\n"
     "  a = 3;\n"
     "  break;\n"
-    "}",
+    "}\n",
 
     "var a = 1;\n"
     "switch(a) {\n"
@@ -1622,10 +1679,11 @@
     "      default : a = 2; break;\n"
     "   }  // fall-through\n"
     " case 2: a = 3;\n"
-    "}",
+    "}\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("Switch.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("Switch.golden")));
 }
 
 TEST(BasicBlockToBoolean) {
@@ -1633,15 +1691,15 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kNumber);
   const char* snippets[] = {
-      "var a = 1; if (a || a < 0) { return 1; }",
+      "var a = 1; if (a || a < 0) { return 1; }\n",
 
-      "var a = 1; if (a && a < 0) { return 1; }",
+      "var a = 1; if (a && a < 0) { return 1; }\n",
 
-      "var a = 1; a = (a || a < 0) ? 2 : 3;",
+      "var a = 1; a = (a || a < 0) ? 2 : 3;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("BasicBlockToBoolean.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("BasicBlockToBoolean.golden")));
 }
 
 TEST(DeadCodeRemoval) {
@@ -1649,17 +1707,17 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kNumber);
   const char* snippets[] = {
-      "return; var a = 1; a();",
+      "return; var a = 1; a();\n",
 
-      "if (false) { return; }; var a = 1;",
+      "if (false) { return; }; var a = 1;\n",
 
-      "if (true) { return 1; } else { return 2; };",
+      "if (true) { return 1; } else { return 2; };\n",
 
-      "var a = 1; if (a) { return 1; }; return 2;",
+      "var a = 1; if (a) { return 1; }; return 2;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("DeadCodeRemoval.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("DeadCodeRemoval.golden")));
 }
 
 TEST(ThisFunction) {
@@ -1677,8 +1735,8 @@
       "f = function f() { return f; };",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets, "", "\nf();"),
-           LoadGolden("ThisFunction.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
+                     LoadGolden("ThisFunction.golden")));
 }
 
 TEST(NewTarget) {
@@ -1687,12 +1745,13 @@
                                       ConstantPoolType::kMixed);
 
   const char* snippets[] = {
-      "return new.target;",
+      "return new.target;\n",
 
-      "new.target;",
+      "new.target;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("NewTarget.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("NewTarget.golden")));
 }
 
 TEST(RemoveRedundantLdar) {
@@ -1705,22 +1764,22 @@
       "  ld_a = ld_a + ld_a;\n"  // in a different basicblock.
       "  if (ld_a > 10) break;\n"
       "}\n"
-      "return ld_a;",
+      "return ld_a;\n",
 
       "var ld_a = 1;\n"
       "do {\n"
       "  ld_a = ld_a + ld_a;\n"
       "  if (ld_a > 10) continue;\n"
       "} while(false);\n"
-      "return ld_a;",
+      "return ld_a;\n",
 
       "var ld_a = 1;\n"
       "  ld_a = ld_a + ld_a;\n"
-      "  return ld_a;",
+      "  return ld_a;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("RemoveRedundantLdar.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("RemoveRedundantLdar.golden")));
 }
 
 TEST(AssignmentsInBinaryExpression) {
@@ -1729,28 +1788,28 @@
                                       ConstantPoolType::kString);
   const char* snippets[] = {
       "var x = 0, y = 1;\n"
-      "return (x = 2, y = 3, x = 4, y = 5);",
+      "return (x = 2, y = 3, x = 4, y = 5);\n",
 
       "var x = 55;\n"
       "var y = (x = 100);\n"
-      "return y;",
+      "return y;\n",
 
       "var x = 55;\n"
       "x = x + (x = 100) + (x = 101);\n"
-      "return x;",
+      "return x;\n",
 
       "var x = 55;\n"
       "x = (x = 56) - x + (x = 57);\n"
       "x++;\n"
-      "return x;",
+      "return x;\n",
 
       "var x = 55;\n"
       "var y = x + (x = 1) + (x = 2) + (x = 3);\n"
-      "return y;",
+      "return y;\n",
 
       "var x = 55;\n"
       "var x = x + (x = 1) + (x = 2) + (x = 3);\n"
-      "return x;",
+      "return x;\n",
 
       "var x = 10, y = 20;\n"
       "return x + (x = 1) + (x + 1) * (y = 2) + (y = 3) + (x = 4) + (y = 5) + "
@@ -1760,8 +1819,8 @@
       "return 1 + x + (x++) + (++x);\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("AssignmentsInBinaryExpression.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("AssignmentsInBinaryExpression.golden")));
 }
 
 TEST(Eval) {
@@ -1769,10 +1828,11 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kString);
   const char* snippets[] = {
-      "return eval('1;');",
+      "return eval('1;');\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("Eval.golden"));
+  CHECK(
+      CompareTexts(BuildActual(printer, snippets), LoadGolden("Eval.golden")));
 }
 
 TEST(LookupSlot) {
@@ -1781,14 +1841,15 @@
                                       ConstantPoolType::kString);
 
   const char* snippets[] = {
-      "eval('var x = 10;'); return x;",
+      "eval('var x = 10;'); return x;\n",
 
-      "eval('var x = 10;'); return typeof x;",
+      "eval('var x = 10;'); return typeof x;\n",
 
-      "x = 20; return eval('');",
+      "x = 20; return eval('');\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("LookupSlot.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("LookupSlot.golden")));
 }
 
 TEST(CallLookupSlot) {
@@ -1796,10 +1857,11 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kMixed);
   const char* snippets[] = {
-      "g = function(){}; eval(''); return g();",
+      "g = function(){}; eval(''); return g();\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("CallLookupSlot.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("CallLookupSlot.golden")));
 }
 
 // TODO(mythria): tests for variable/function declaration in lookup slots.
@@ -1831,7 +1893,7 @@
                                    "}\n"
                                    "f1();");
 
-  CHECK_EQ(actual, LoadGolden("LookupSlotInEval.golden"));
+  CHECK(CompareTexts(actual, LoadGolden("LookupSlotInEval.golden")));
 }
 
 TEST(LookupSlotWideInEval) {
@@ -1867,7 +1929,7 @@
                                    "}\n"
                                    "f1();");
 
-  CHECK_EQ(actual, LoadGolden("LookupSlotWideInEval.golden"));
+  CHECK(CompareTexts(actual, LoadGolden("LookupSlotWideInEval.golden")));
 }
 
 TEST(DeleteLookupSlotInEval) {
@@ -1897,7 +1959,7 @@
                                    "}\n"
                                    "f1();");
 
-  CHECK_EQ(actual, LoadGolden("DeleteLookupSlotInEval.golden"));
+  CHECK(CompareTexts(actual, LoadGolden("DeleteLookupSlotInEval.golden")));
 }
 
 TEST(WideRegisters) {
@@ -1913,41 +1975,41 @@
                                       ConstantPoolType::kNumber);
   const char* snippets[] = {
       "x0 = x127;\n"
-      "return x0;",
+      "return x0;\n",
 
       "x127 = x126;\n"
-      "return x127;",
+      "return x127;\n",
 
       "if (x2 > 3) { return x129; }\n"
-      "return x128;",
+      "return x128;\n",
 
       "var x0 = 0;\n"
       "if (x129 == 3) { var x129 = x0; }\n"
       "if (x2 > 3) { return x0; }\n"
-      "return x129;",
+      "return x129;\n",
 
       "var x0 = 0;\n"
       "var x1 = 0;\n"
       "for (x128 = 0; x128 < 64; x128++) {"
       "  x1 += x128;"
       "}"
-      "return x128;",
+      "return x128;\n",
 
       "var x0 = 1234;\n"
       "var x1 = 0;\n"
       "for (x128 in x0) {"
       "  x1 += x128;"
       "}"
-      "return x1;",
+      "return x1;\n",
 
       "x0 = %Add(x64, x63);\n"
       "x1 = %Add(x27, x143);\n"
       "%TheHole();\n"
-      "return x1;",
+      "return x1;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets, prologue.c_str()),
-           LoadGolden("WideRegisters.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets, prologue.c_str()),
+                     LoadGolden("WideRegisters.golden")));
 }
 
 TEST(ConstVariable) {
@@ -1955,16 +2017,17 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kString);
   const char* snippets[] = {
-      "const x = 10;",
+      "const x = 10;\n",
 
-      "const x = 10; return x;",
+      "const x = 10; return x;\n",
 
-      "const x = ( x = 20);",
+      "const x = ( x = 20);\n",
 
-      "const x = 10; x = 20;",
+      "const x = 10; x = 20;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("ConstVariable.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("ConstVariable.golden")));
 }
 
 TEST(LetVariable) {
@@ -1972,16 +2035,17 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kString);
   const char* snippets[] = {
-      "let x = 10;",
+      "let x = 10;\n",
 
-      "let x = 10; return x;",
+      "let x = 10; return x;\n",
 
-      "let x = (x = 20);",
+      "let x = (x = 20);\n",
 
-      "let x = 10; x = 20;",
+      "let x = 10; x = 20;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("LetVariable.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("LetVariable.golden")));
 }
 
 TEST(ConstVariableContextSlot) {
@@ -1991,17 +2055,17 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kMixed);
   const char* snippets[] = {
-      "const x = 10; function f1() {return x;}",
+      "const x = 10; function f1() {return x;}\n",
 
-      "const x = 10; function f1() {return x;} return x;",
+      "const x = 10; function f1() {return x;} return x;\n",
 
-      "const x = (x = 20); function f1() {return x;}",
+      "const x = (x = 20); function f1() {return x;}\n",
 
-      "const x = 10; x = 20; function f1() {return x;}",
+      "const x = 10; x = 20; function f1() {return x;}\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("ConstVariableContextSlot.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("ConstVariableContextSlot.golden")));
 }
 
 TEST(LetVariableContextSlot) {
@@ -2009,17 +2073,17 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kMixed);
   const char* snippets[] = {
-      "let x = 10; function f1() {return x;}",
+      "let x = 10; function f1() {return x;}\n",
 
-      "let x = 10; function f1() {return x;} return x;",
+      "let x = 10; function f1() {return x;} return x;\n",
 
-      "let x = (x = 20); function f1() {return x;}",
+      "let x = (x = 20); function f1() {return x;}\n",
 
-      "let x = 10; x = 20; function f1() {return x;}",
+      "let x = 10; x = 20; function f1() {return x;}\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("LetVariableContextSlot.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("LetVariableContextSlot.golden")));
 }
 
 TEST(DoExpression) {
@@ -2030,14 +2094,15 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kString);
   const char* snippets[] = {
-      "var a = do { }; return a;",
+      "var a = do { }; return a;\n",
 
-      "var a = do { var x = 100; }; return a;",
+      "var a = do { var x = 100; }; return a;\n",
 
-      "while(true) { var a = 10; a = do { ++a; break; }; a = 20; }",
+      "while(true) { var a = 10; a = do { ++a; break; }; a = 20; }\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("DoExpression.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("DoExpression.golden")));
 
   FLAG_harmony_do_expressions = old_flag;
 }
@@ -2047,10 +2112,11 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kMixed);
   const char* snippets[] = {
-      "with ({x:42}) { return x; }",
+      "with ({x:42}) { return x; }\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("WithStatement.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("WithStatement.golden")));
 }
 
 TEST(DoDebugger) {
@@ -2058,10 +2124,11 @@
   BytecodeExpectationsPrinter printer(CcTest::isolate(),
                                       ConstantPoolType::kString);
   const char* snippets[] = {
-      "debugger;",
+      "debugger;\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets), LoadGolden("DoDebugger.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("DoDebugger.golden")));
 }
 
 TEST(ClassDeclarations) {
@@ -2072,27 +2139,27 @@
       "class Person {\n"
       "  constructor(name) { this.name = name; }\n"
       "  speak() { console.log(this.name + ' is speaking.'); }\n"
-      "}",
+      "}\n",
 
       "class person {\n"
       "  constructor(name) { this.name = name; }\n"
       "  speak() { console.log(this.name + ' is speaking.'); }\n"
-      "}",
+      "}\n",
 
       "var n0 = 'a';\n"
       "var n1 = 'b';\n"
       "class N {\n"
       "  [n0]() { return n0; }\n"
       "  static [n1]() { return n1; }\n"
-      "}",
+      "}\n",
 
       "var count = 0;\n"
       "class C { constructor() { count++; }}\n"
       "return new C();\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("ClassDeclarations.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("ClassDeclarations.golden")));
 }
 
 TEST(ClassAndSuperClass) {
@@ -2150,8 +2217,35 @@
       "})();\n",
   };
 
-  CHECK_EQ(BuildActual(printer, snippets),
-           LoadGolden("ClassAndSuperClass.golden"));
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("ClassAndSuperClass.golden")));
+}
+
+TEST(Generators) {
+  bool old_flag = FLAG_ignition_generators;
+  FLAG_ignition_generators = true;
+
+  InitializedIgnitionHandleScope scope;
+  BytecodeExpectationsPrinter printer(CcTest::isolate(),
+                                      ConstantPoolType::kMixed);
+  printer.set_wrap(false);
+  printer.set_test_function_name("f");
+
+  const char* snippets[] = {
+      "function* f() { }\n"
+      "f();\n",
+
+      "function* f() { yield 42 }\n"
+      "f();\n",
+
+      "function* f() { for (let x of [42]) yield x }\n"
+      "f();\n",
+  };
+
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("Generators.golden")));
+
+  FLAG_ignition_generators = old_flag;
 }
 
 }  // namespace interpreter
diff --git a/test/cctest/interpreter/test-interpreter-intrinsics.cc b/test/cctest/interpreter/test-interpreter-intrinsics.cc
index e4cf809..b8fce7a 100644
--- a/test/cctest/interpreter/test-interpreter-intrinsics.cc
+++ b/test/cctest/interpreter/test-interpreter-intrinsics.cc
@@ -29,7 +29,7 @@
     builder.CallRuntime(function_id_, builder.Parameter(0), sizeof...(args))
         .Return();
     InterpreterTester tester(isolate_, builder.ToBytecodeArray());
-    auto callable = tester.GetCallable<Handle<Object>>();
+    auto callable = tester.GetCallable<A...>();
     return callable(args...).ToHandleChecked();
   }
 
@@ -91,6 +91,189 @@
   CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42")));
 }
 
+TEST(IsJSProxy) {
+  HandleAndZoneScope handles;
+
+  InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(),
+                               Runtime::kInlineIsJSProxy);
+  Factory* factory = handles.main_isolate()->factory();
+
+  CHECK_EQ(*factory->false_value(),
+           *helper.Invoke(helper.NewObject("new Date()")));
+  CHECK_EQ(*factory->false_value(),
+           *helper.Invoke(helper.NewObject("(function() {})")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("([1])")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("({})")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("(/x/)")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Undefined()));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Null()));
+  CHECK_EQ(*factory->false_value(),
+           *helper.Invoke(helper.NewObject("'string'")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42")));
+  CHECK_EQ(*factory->true_value(),
+           *helper.Invoke(helper.NewObject("new Proxy({},{})")));
+}
+
+TEST(IsRegExp) {
+  HandleAndZoneScope handles;
+
+  InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(),
+                               Runtime::kInlineIsRegExp);
+  Factory* factory = handles.main_isolate()->factory();
+
+  CHECK_EQ(*factory->false_value(),
+           *helper.Invoke(helper.NewObject("new Date()")));
+  CHECK_EQ(*factory->false_value(),
+           *helper.Invoke(helper.NewObject("(function() {})")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("([1])")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("({})")));
+  CHECK_EQ(*factory->true_value(), *helper.Invoke(helper.NewObject("(/x/)")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Undefined()));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Null()));
+  CHECK_EQ(*factory->false_value(),
+           *helper.Invoke(helper.NewObject("'string'")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42")));
+}
+
+TEST(IsTypedArray) {
+  HandleAndZoneScope handles;
+
+  InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(),
+                               Runtime::kInlineIsTypedArray);
+  Factory* factory = handles.main_isolate()->factory();
+
+  CHECK_EQ(*factory->false_value(),
+           *helper.Invoke(helper.NewObject("new Date()")));
+  CHECK_EQ(*factory->false_value(),
+           *helper.Invoke(helper.NewObject("(function() {})")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("([1])")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("({})")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("(/x/)")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Undefined()));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Null()));
+  CHECK_EQ(*factory->false_value(),
+           *helper.Invoke(helper.NewObject("'string'")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42")));
+
+  CHECK_EQ(
+      *factory->true_value(),
+      *helper.Invoke(helper.NewObject("new Uint8Array(new ArrayBuffer(1));")));
+  CHECK_EQ(
+      *factory->true_value(),
+      *helper.Invoke(helper.NewObject("new Uint16Array(new ArrayBuffer(2));")));
+  CHECK_EQ(
+      *factory->true_value(),
+      *helper.Invoke(helper.NewObject("new Int32Array(new ArrayBuffer(4));")));
+}
+
+TEST(IsSmi) {
+  HandleAndZoneScope handles;
+
+  InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(),
+                               Runtime::kInlineIsSmi);
+  Factory* factory = handles.main_isolate()->factory();
+
+  CHECK_EQ(*factory->false_value(),
+           *helper.Invoke(helper.NewObject("new Date()")));
+  CHECK_EQ(*factory->false_value(),
+           *helper.Invoke(helper.NewObject("(function() {})")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("([1])")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("({})")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("(/x/)")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Undefined()));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Null()));
+  CHECK_EQ(*factory->false_value(),
+           *helper.Invoke(helper.NewObject("'string'")));
+  CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42.2")));
+  CHECK_EQ(*factory->false_value(),
+           *helper.Invoke(helper.NewObject("4294967297")));
+  CHECK_EQ(*factory->true_value(), *helper.Invoke(helper.NewObject("42")));
+}
+
+TEST(Call) {
+  HandleAndZoneScope handles;
+  Isolate* isolate = handles.main_isolate();
+  Factory* factory = isolate->factory();
+  InvokeIntrinsicHelper helper(isolate, handles.main_zone(),
+                               Runtime::kInlineCall);
+
+  CHECK_EQ(Smi::FromInt(20),
+           *helper.Invoke(helper.NewObject("(function() { return this.x; })"),
+                          helper.NewObject("({ x: 20 })")));
+  CHECK_EQ(Smi::FromInt(50),
+           *helper.Invoke(helper.NewObject("(function(arg1) { return arg1; })"),
+                          factory->undefined_value(),
+                          handle(Smi::FromInt(50), isolate)));
+  CHECK_EQ(
+      Smi::FromInt(20),
+      *helper.Invoke(
+          helper.NewObject("(function(a, b, c) { return a + b + c; })"),
+          factory->undefined_value(), handle(Smi::FromInt(10), isolate),
+          handle(Smi::FromInt(7), isolate), handle(Smi::FromInt(3), isolate)));
+}
+
+TEST(IntrinsicAsStubCall) {
+  HandleAndZoneScope handles;
+  Isolate* isolate = handles.main_isolate();
+  Factory* factory = isolate->factory();
+  InvokeIntrinsicHelper to_number_helper(isolate, handles.main_zone(),
+                                         Runtime::kInlineToNumber);
+  CHECK_EQ(Smi::FromInt(46),
+           *to_number_helper.Invoke(to_number_helper.NewObject("'46'")));
+
+  InvokeIntrinsicHelper to_integer_helper(isolate, handles.main_zone(),
+                                          Runtime::kInlineToInteger);
+  CHECK_EQ(Smi::FromInt(502),
+           *to_integer_helper.Invoke(to_integer_helper.NewObject("502.67")));
+
+  InvokeIntrinsicHelper math_pow_helper(isolate, handles.main_zone(),
+                                        Runtime::kInlineMathPow);
+  CHECK(math_pow_helper
+            .Invoke(math_pow_helper.NewObject("3"),
+                    math_pow_helper.NewObject("7"))
+            ->SameValue(Smi::FromInt(2187)));
+
+  InvokeIntrinsicHelper has_property_helper(isolate, handles.main_zone(),
+                                            Runtime::kInlineHasProperty);
+  CHECK_EQ(*factory->true_value(),
+           *has_property_helper.Invoke(
+               has_property_helper.NewObject("'x'"),
+               has_property_helper.NewObject("({ x: 20 })")));
+  CHECK_EQ(*factory->false_value(),
+           *has_property_helper.Invoke(
+               has_property_helper.NewObject("'y'"),
+               has_property_helper.NewObject("({ x: 20 })")));
+
+  InvokeIntrinsicHelper sub_string_helper(isolate, handles.main_zone(),
+                                          Runtime::kInlineSubString);
+  CHECK(sub_string_helper
+            .Invoke(sub_string_helper.NewObject("'foobar'"),
+                    sub_string_helper.NewObject("3"),
+                    sub_string_helper.NewObject("6"))
+            ->SameValue(*sub_string_helper.NewObject("'bar'")));
+}
+
+TEST(ValueOf) {
+  HandleAndZoneScope handles;
+  Isolate* isolate = handles.main_isolate();
+  Factory* factory = isolate->factory();
+  InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(),
+                               Runtime::kInlineValueOf);
+
+  CHECK_EQ(Smi::FromInt(1234), *helper.Invoke(helper.NewObject("1234")));
+  CHECK_EQ(Smi::FromInt(5678),
+           *helper.Invoke(helper.NewObject("new Object(5678)")));
+
+  CHECK_EQ(*factory->true_value(), *helper.Invoke(helper.NewObject("true")));
+  CHECK_EQ(*factory->false_value(),
+           *helper.Invoke(helper.NewObject("new Object(false)")));
+
+  CHECK(helper.Invoke(helper.NewObject("'foobar'"))
+            ->SameValue(*helper.NewObject("'foobar'")));
+  CHECK(helper.Invoke(helper.NewObject("new Object('foobar')"))
+            ->SameValue(*helper.NewObject("'foobar'")));
+}
+
 }  // namespace interpreter
 }  // namespace internal
 }  // namespace v8
diff --git a/test/cctest/interpreter/test-interpreter.cc b/test/cctest/interpreter/test-interpreter.cc
index c8dc776..07a22b7 100644
--- a/test/cctest/interpreter/test-interpreter.cc
+++ b/test/cctest/interpreter/test-interpreter.cc
@@ -8,6 +8,7 @@
 #include "src/handles.h"
 #include "src/interpreter/bytecode-array-builder.h"
 #include "src/interpreter/bytecode-array-iterator.h"
+#include "src/interpreter/bytecode-label.h"
 #include "src/interpreter/interpreter.h"
 #include "test/cctest/cctest.h"
 #include "test/cctest/interpreter/interpreter-tester.h"
@@ -138,6 +139,7 @@
   {
     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                  0, 0);
+
     builder.LoadLiteral(Smi::FromInt(0x12345678)).Return();
     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -151,6 +153,7 @@
   {
     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                  0, 0);
+
     builder.LoadLiteral(factory->NewHeapNumber(-2.1e19)).Return();
     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -164,6 +167,7 @@
   {
     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                  0, 0);
+
     Handle<i::String> string = factory->NewStringFromAsciiChecked("String");
     builder.LoadLiteral(string).Return();
     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -182,6 +186,7 @@
   for (int i = 0; i <= kMaxInt8; i++) {
     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                  0, i + 1);
+
     Register reg(i);
     builder.LoadTrue()
         .StoreAccumulatorInRegister(reg)
@@ -297,6 +302,7 @@
         i::Factory* factory = handles.main_isolate()->factory();
         BytecodeArrayBuilder builder(handles.main_isolate(),
                                      handles.main_zone(), 1, 0, 1);
+
         Register reg(0);
         int lhs = lhs_inputs[l];
         int rhs = rhs_inputs[r];
@@ -387,6 +393,7 @@
   for (size_t i = 0; i < arraysize(test_cases); i++) {
     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                  0, 1);
+
     Register reg(0);
     builder.LoadLiteral(test_cases[i].lhs)
         .StoreAccumulatorInRegister(reg)
@@ -407,6 +414,7 @@
   HandleAndZoneScope handles;
   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                0, 0);
+
   builder.LoadAccumulatorWithRegister(builder.Parameter(0)).Return();
   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
@@ -429,6 +437,7 @@
   HandleAndZoneScope handles;
   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 8,
                                0, 0);
+
   builder.LoadAccumulatorWithRegister(builder.Parameter(0))
       .BinaryOperation(Token::Value::ADD, builder.Parameter(1))
       .BinaryOperation(Token::Value::ADD, builder.Parameter(2))
@@ -464,6 +473,7 @@
   HandleAndZoneScope handles;
   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                0, 0);
+
   builder.LoadLiteral(Smi::FromInt(5))
       .StoreAccumulatorInRegister(builder.Parameter(0))
       .LoadAccumulatorWithRegister(builder.Parameter(0))
@@ -592,6 +602,7 @@
 
   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                0, 0);
+
   builder.LoadNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot))
       .Return();
   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -645,6 +656,7 @@
 
   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                0, 1);
+
   builder.LoadLiteral(key)
       .LoadKeyedProperty(builder.Parameter(0), vector->GetIndex(slot))
       .Return();
@@ -687,6 +699,7 @@
 
   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                0, 0);
+
   builder.LoadLiteral(Smi::FromInt(999))
       .StoreNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot),
                           i::STRICT)
@@ -746,6 +759,7 @@
 
   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                0, 1);
+
   builder.LoadLiteral(name)
       .StoreAccumulatorInRegister(Register(0))
       .LoadLiteral(Smi::FromInt(999))
@@ -796,6 +810,7 @@
   {
     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                  0, 1);
+
     builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
         .StoreAccumulatorInRegister(Register(0))
         .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode)
@@ -815,6 +830,7 @@
   {
     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                  0, 1);
+
     builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
         .StoreAccumulatorInRegister(Register(0))
         .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode)
@@ -837,6 +853,7 @@
   {
     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                  0, 4);
+
     builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
         .StoreAccumulatorInRegister(Register(0))
         .LoadAccumulatorWithRegister(builder.Parameter(0))
@@ -864,6 +881,7 @@
   {
     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                  0, 12);
+
     builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
         .StoreAccumulatorInRegister(Register(0))
         .LoadAccumulatorWithRegister(builder.Parameter(0))
@@ -938,6 +956,7 @@
   HandleAndZoneScope handles;
   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
                                0, 2);
+
   Register reg(0), scratch(1);
   BytecodeLabel label[3];
 
@@ -965,6 +984,7 @@
   HandleAndZoneScope handles;
   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
                                0, 2);
+
   Register reg(0), scratch(1);
   BytecodeLabel label[2];
   BytecodeLabel done, done1;
@@ -998,6 +1018,7 @@
   HandleAndZoneScope handles;
   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
                                0, 2);
+
   Register reg(0), scratch(1);
   BytecodeLabel label[2];
   BytecodeLabel done, done1;
@@ -1030,8 +1051,9 @@
   HandleAndZoneScope handles;
   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                0, 257);
+
   Register reg(0), scratch(256);
-  BytecodeLabel done;
+  BytecodeLabel done, fake;
 
   builder.LoadLiteral(Smi::FromInt(0));
   builder.StoreAccumulatorInRegister(reg);
@@ -1044,6 +1066,7 @@
   builder.Jump(&done);
 
   // Emit more than 16-bit immediate operands worth of code to jump over.
+  builder.Bind(&fake);
   for (int i = 0; i < 6600; i++) {
     builder.LoadLiteral(Smi::FromInt(0));                 // 1-byte
     builder.BinaryOperation(Token::Value::ADD, scratch);  // 4-bytes
@@ -1167,6 +1190,7 @@
         HandleAndZoneScope handles;
         BytecodeArrayBuilder builder(handles.main_isolate(),
                                      handles.main_zone(), 0, 0, 1);
+
         Register r0(0);
         builder.LoadLiteral(Smi::FromInt(inputs[i]))
             .StoreAccumulatorInRegister(r0)
@@ -1203,6 +1227,7 @@
         i::Factory* factory = handles.main_isolate()->factory();
         BytecodeArrayBuilder builder(handles.main_isolate(),
                                      handles.main_zone(), 0, 0, 1);
+
         Register r0(0);
         builder.LoadLiteral(factory->NewHeapNumber(inputs[i]))
             .StoreAccumulatorInRegister(r0)
@@ -1236,6 +1261,7 @@
         i::Factory* factory = handles.main_isolate()->factory();
         BytecodeArrayBuilder builder(handles.main_isolate(),
                                      handles.main_zone(), 0, 0, 1);
+
         Register r0(0);
         builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs))
             .StoreAccumulatorInRegister(r0)
@@ -1280,6 +1306,7 @@
           i::Factory* factory = handles.main_isolate()->factory();
           BytecodeArrayBuilder builder(handles.main_isolate(),
                                        handles.main_zone(), 0, 0, 1);
+
           Register r0(0);
           if (pass == 0) {
             // Comparison with HeapNumber on the lhs and String on the rhs
@@ -1383,11 +1410,6 @@
 
 TEST(InterpreterInstanceOf) {
   HandleAndZoneScope handles;
-  // TODO(4447): The new ES6 'instanceof' operator is fully desugared in the
-  // parser and the Token::INSTANCEOF is not needed anymore. This test only
-  // makes sense with --no-harmony-instanceof and can be removed once we
-  // deprecate the ability to switch to old skool ES5 'instanceof' for good.
-  FLAG_harmony_instanceof = false;
   i::Factory* factory = handles.main_isolate()->factory();
   Handle<i::String> name = factory->NewStringFromAsciiChecked("cons");
   Handle<i::JSFunction> func = factory->NewFunction(name);
@@ -1398,6 +1420,7 @@
     bool expected_value = (i == 0);
     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
                                  0, 1);
+
     Register r0(0);
     builder.LoadLiteral(cases[i]);
     builder.StoreAccumulatorInRegister(r0)
@@ -1427,6 +1450,7 @@
     bool expected_value = (i == 0);
     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
                                  0, 1);
+
     Register r0(0);
     builder.LoadLiteral(factory->NewStringFromAsciiChecked(properties[i]))
         .StoreAccumulatorInRegister(r0)
@@ -1450,6 +1474,7 @@
     bool expected_value = ((i & 1) == 1);
     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
                                  0, 0);
+
     Register r0(0);
     builder.LoadFalse();
     for (size_t j = 0; j < i; j++) {
@@ -1511,6 +1536,7 @@
   for (size_t i = 0; i < arraysize(object_type_tuples); i++) {
     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
                                  0, 0);
+
     Register r0(0);
     LoadAny(&builder, factory, object_type_tuples[i].first);
     builder.LogicalNot();
@@ -1557,6 +1583,7 @@
 
   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                0, 2);
+
   builder.LoadLiteral(Smi::FromInt(15))
       .StoreAccumulatorInRegister(Register(0))
       .LoadLiteral(Smi::FromInt(40))
@@ -1577,6 +1604,7 @@
 
   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
                                0, 2);
+
   builder.LoadLiteral(Smi::FromInt(15))
       .StoreAccumulatorInRegister(Register(0))
       .CallRuntime(Runtime::kInlineIsArray, Register(0), 1)
@@ -2259,6 +2287,8 @@
       std::make_pair("function f(a, b, c, d) {"
                      "  'use strict'; c = b; return arguments[2]; }",
                      2),
+      // Check arguments for duplicate parameters in sloppy mode.
+      std::make_pair("function f(a, a, b) { return arguments[1]; }", 1),
       // check rest parameters
       std::make_pair("function f(...restArray) { return restArray[0]; }", 0),
       std::make_pair("function f(a, ...restArray) { return restArray[0]; }", 1),
@@ -4139,6 +4169,35 @@
   }
 }
 
+TEST(InterpreterGenerators) {
+  bool old_flag = FLAG_ignition_generators;
+  FLAG_ignition_generators = true;
+
+  HandleAndZoneScope handles;
+  i::Isolate* isolate = handles.main_isolate();
+  i::Factory* factory = isolate->factory();
+
+  std::pair<const char*, Handle<Object>> tests[] = {
+      {"function* f() { }; return f().next().value",
+       factory->undefined_value()},
+      {"function* f() { yield 42 }; return f().next().value",
+       factory->NewNumberFromInt(42)},
+      {"function* f() { for (let x of [42]) yield x}; return f().next().value",
+       factory->NewNumberFromInt(42)},
+  };
+
+  for (size_t i = 0; i < arraysize(tests); i++) {
+    std::string source(InterpreterTester::SourceForBody(tests[i].first));
+    InterpreterTester tester(handles.main_isolate(), source.c_str());
+    auto callable = tester.GetCallable<>();
+
+    Handle<i::Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*tests[i].second));
+  }
+
+  FLAG_ignition_generators = old_flag;
+}
+
 }  // namespace interpreter
 }  // namespace internal
 }  // namespace v8
diff --git a/test/cctest/interpreter/test-source-positions.cc b/test/cctest/interpreter/test-source-positions.cc
new file mode 100644
index 0000000..19be47f
--- /dev/null
+++ b/test/cctest/interpreter/test-source-positions.cc
@@ -0,0 +1,252 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "src/compiler/pipeline.h"
+#include "src/handles.h"
+#include "src/interpreter/bytecode-generator.h"
+#include "src/interpreter/interpreter.h"
+#include "src/isolate.h"
+#include "src/parsing/parser.h"
+#include "test/cctest/cctest.h"
+#include "test/cctest/interpreter/source-position-matcher.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+// Flags enabling optimizations that change generated bytecode array.
+// Format is <command-line flag> <flag name> <bit index>
+#define OPTIMIZATION_FLAGS(V)                                                 \
+  V(FLAG_ignition_reo, kUseReo, 0)                                            \
+  V(FLAG_ignition_peephole, kUsePeephole, 1)                                  \
+  V(FLAG_ignition_filter_expression_positions, kUseFilterExpressionPositions, \
+    2)                                                                        \
+  V(FLAG_ignition_deadcode, kUseDeadCode, 3)
+
+#define DECLARE_BIT(_, Name, BitIndex) static const int Name = 1 << BitIndex;
+OPTIMIZATION_FLAGS(DECLARE_BIT)
+#undef DECLARE_BIT
+
+// Test cases source positions are checked for. Please ensure all
+// combinations of flags are present here. This is done manually
+// because it provides easier to comprehend failure case for humans.
+#define TEST_CASES(V)                                              \
+  V(UsingReo, kUseReo)                                             \
+  V(UsingPeephole, kUsePeephole)                                   \
+  V(UsingDeadCode, kUseDeadCode)                                   \
+  V(UsingFilterExpressionPositions, kUseFilterExpressionPositions) \
+  V(UsingReoAndPeephole, kUseReo | kUsePeephole)                   \
+  V(UsingReoAndFilterExpressionPositions,                          \
+    kUseReo | kUseFilterExpressionPositions)                       \
+  V(UsingReoAndDeadCode, kUseReo | kUseDeadCode)                   \
+  V(UsingPeepholeAndFilterExpressionPositions,                     \
+    kUsePeephole | kUseFilterExpressionPositions)                  \
+  V(UsingPeepholeAndDeadCode, kUsePeephole | kUseDeadCode)         \
+  V(UsingFilterExpressionPositionsAndDeadCode,                     \
+    kUseFilterExpressionPositions | kUseDeadCode)                  \
+  V(UsingAllOptimizations,                                         \
+    kUseReo | kUsePeephole | kUseFilterExpressionPositions | kUseDeadCode)
+
+struct TestCaseData {
+  TestCaseData(const char* const script,
+               const char* const declaration_parameters = "",
+               const char* const arguments = "")
+      : script_(script),
+        declaration_parameters_(declaration_parameters),
+        arguments_(arguments) {}
+
+  const char* const script() const { return script_; }
+  const char* const declaration_parameters() const {
+    return declaration_parameters_;
+  }
+  const char* const arguments() const { return arguments_; }
+
+ private:
+  TestCaseData();
+
+  const char* const script_;
+  const char* const declaration_parameters_;
+  const char* const arguments_;
+};
+
+static const TestCaseData kTestCaseData[] = {
+    {"var x = (y = 3) + (x = y); return x + y;"},
+    {"var x = 55;\n"
+     "var y = x + (x = 1) + (x = 2) + (x = 3);\n"
+     "return y;"},
+    {"var x = 10; return x >>> 3;\n"},
+    {"var x = 0; return x || (1, 2, 3);\n"},
+    {"return a || (a, b, a, b, c = 5, 3);\n"},
+    {"var a = 3; var b = 4; a = b; b = a; a = b; return a;\n"},
+    {"var a = 1; return [[a, 2], [a + 2]];\n"},
+    {"var a = 1; if (a || a < 0) { return 1; }\n"},
+    {"var b;"
+     "b = a.name;"
+     "b = a.name;"
+     "a.name = a;"
+     "b = a.name;"
+     "a.name = a;"
+     "return b;"},
+    {"var sum = 0;\n"
+     "outer: {\n"
+     "  for (var x = 0; x < 10; ++x) {\n"
+     "    for (var y = 0; y < 3; ++y) {\n"
+     "      ++sum;\n"
+     "      if (x + y == 12) { break outer; }\n"
+     "    }\n"
+     "  }\n"
+     "}\n"
+     "return sum;\n"},
+    {"var a = 1;"
+     "switch (a) {"
+     "  case 1: return a * a + 1;"
+     "  case 1: break;"
+     "  case 2: return (a = 3) * a + (a = 4);"
+     "  case 3:"
+     "}"
+     "return a;"},
+    {"for (var p of [0, 1, 2]) {}"},
+    {"var x = { 'a': 1, 'b': 2 };"
+     "for (x['a'] of [1,2,3]) { return x['a']; }"},
+    {"while (x == 4) {\n"
+     "  var y = x + 1;\n"
+     "  if (y == 2) break;\n"
+     "  for (z['a'] of [0]) {\n"
+     "    x += (x *= 3) + y;"
+     "  }\n"
+     "}\n"},
+    {"function g(a, b) { return a.func(b + b, b); }\n"
+     "g(new (function Obj() { this.func = function() { return; }})(), 1)\n"},
+    {"return some_global[name];", "name", "'a'"}};
+
+class OptimizedBytecodeSourcePositionTester final {
+ public:
+  explicit OptimizedBytecodeSourcePositionTester(Isolate* isolate)
+      : isolate_(isolate) {
+    SaveOptimizationFlags();
+    saved_flag_ignition_ = FLAG_ignition;
+    FLAG_ignition = true;
+    saved_flag_always_opt_ = FLAG_always_opt;
+    FLAG_always_opt = false;
+  }
+
+  ~OptimizedBytecodeSourcePositionTester() {
+    RestoreOptimizationFlags();
+    FLAG_ignition = saved_flag_ignition_;
+    FLAG_always_opt = saved_flag_always_opt_;
+  }
+
+  bool SourcePositionsMatch(int optimization_bitmap, const char* function_body,
+                            const char* function_decl_params,
+                            const char* function_args);
+
+ private:
+  Handle<BytecodeArray> MakeBytecode(int optimization_bitmap,
+                                     const char* function_body,
+                                     const char* function_decl_params,
+                                     const char* function_args);
+  static std::string MakeScript(const char* function_body,
+                                const char* function_decl_params,
+                                const char* function_args);
+
+  void SetOptimizationFlags(int optimization_bitmap);
+  void SaveOptimizationFlags();
+  void RestoreOptimizationFlags();
+
+  Isolate* isolate() const { return isolate_; }
+
+  Isolate* isolate_;
+  int saved_optimization_bitmap_;
+  bool saved_flag_ignition_;
+  bool saved_flag_always_opt_;
+};
+
+// static
+std::string OptimizedBytecodeSourcePositionTester::MakeScript(
+    const char* function_body, const char* function_decl_params,
+    const char* function_args) {
+  std::ostringstream os;
+  os << "function test_function"
+     << "(" << function_decl_params << ") {";
+  os << function_body;
+  os << "}";
+  os << "test_function(" << function_args << ");";
+  return os.str();
+}
+
+Handle<BytecodeArray> OptimizedBytecodeSourcePositionTester::MakeBytecode(
+    int optimization_bitmap, const char* function_body,
+    const char* function_decl_params, const char* function_args) {
+  std::string script =
+      MakeScript(function_body, function_decl_params, function_args);
+  SetOptimizationFlags(optimization_bitmap);
+  CompileRun(script.c_str());
+
+  Local<Function> api_function = Local<Function>::Cast(
+      CcTest::global()
+          ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("test_function"))
+          .ToLocalChecked());
+  Handle<JSFunction> function =
+      Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function));
+  return handle(function->shared()->bytecode_array());
+}
+
+void OptimizedBytecodeSourcePositionTester::SetOptimizationFlags(
+    int optimization_bitmap) {
+#define SET_FLAG(V8Flag, BitName, _) \
+  V8Flag = (optimization_bitmap & BitName) ? true : false;
+  OPTIMIZATION_FLAGS(SET_FLAG)
+#undef SET_FLAG
+}
+
+void OptimizedBytecodeSourcePositionTester::SaveOptimizationFlags() {
+  saved_optimization_bitmap_ = 0;
+#define SAVE_FLAG(V8Flag, BitName, _) \
+  if (V8Flag) saved_optimization_bitmap_ |= BitName;
+#undef SET_FLAG
+}
+
+void OptimizedBytecodeSourcePositionTester::RestoreOptimizationFlags() {
+  SetOptimizationFlags(saved_optimization_bitmap_);
+}
+
+bool OptimizedBytecodeSourcePositionTester::SourcePositionsMatch(
+    int optimization_bitmap, const char* function_body,
+    const char* function_decl_params, const char* function_args) {
+  Handle<BytecodeArray> unoptimized_bytecode =
+      MakeBytecode(0, function_body, function_decl_params, function_args);
+  Handle<BytecodeArray> optimized_bytecode = MakeBytecode(
+      optimization_bitmap, function_body, function_decl_params, function_args);
+  SourcePositionMatcher matcher;
+  if (!matcher.Match(unoptimized_bytecode, optimized_bytecode)) {
+    return false;
+  }
+  return true;
+}
+
+void TestSourcePositionsEquivalent(int optimization_bitmap) {
+  HandleAndZoneScope handles;
+  // Ensure handler table is generated.
+  handles.main_isolate()->interpreter()->Initialize();
+
+  OptimizedBytecodeSourcePositionTester tester(handles.main_isolate());
+  for (auto test_case_data : kTestCaseData) {
+    CHECK(tester.SourcePositionsMatch(
+        optimization_bitmap, test_case_data.script(),
+        test_case_data.declaration_parameters(), test_case_data.arguments()));
+  }
+}
+
+#define MAKE_TEST(Name, Bitmap)               \
+  TEST(TestSourcePositionsEquivalent##Name) { \
+    TestSourcePositionsEquivalent(Bitmap);    \
+  }
+TEST_CASES(MAKE_TEST)
+#undef MAKE_TEST
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
diff --git a/test/cctest/libsampler/test-sampler.cc b/test/cctest/libsampler/test-sampler.cc
new file mode 100644
index 0000000..745b139
--- /dev/null
+++ b/test/cctest/libsampler/test-sampler.cc
@@ -0,0 +1,141 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+// Tests of sampler functionalities.
+
+#include "src/libsampler/v8-sampler.h"
+
+#include "src/base/platform/platform.h"
+#include "test/cctest/cctest.h"
+
+
+namespace v8 {
+namespace sampler {
+
+namespace {
+
+class TestSamplingThread : public base::Thread {
+ public:
+  static const int kSamplerThreadStackSize = 64 * 1024;
+
+  explicit TestSamplingThread(Sampler* sampler)
+      : Thread(base::Thread::Options("TestSamplingThread",
+                                     kSamplerThreadStackSize)),
+        sampler_(sampler) {}
+
+  // Implement Thread::Run().
+  void Run() override {
+    while (sampler_->IsProfiling()) {
+      sampler_->DoSample();
+      base::OS::Sleep(base::TimeDelta::FromMilliseconds(1));
+    }
+  }
+
+ private:
+  Sampler* sampler_;
+};
+
+
+class TestSampler : public Sampler {
+ public:
+  explicit TestSampler(Isolate* isolate) : Sampler(isolate) {}
+
+  void SampleStack(const v8::RegisterState& regs) override {
+    void* frames[Sampler::kMaxFramesCount];
+    SampleInfo sample_info;
+    isolate()->GetStackSample(regs, reinterpret_cast<void**>(frames),
+                              Sampler::kMaxFramesCount, &sample_info);
+    if (is_counting_samples_) {
+      if (sample_info.vm_state == JS) ++js_sample_count_;
+      if (sample_info.vm_state == EXTERNAL) ++external_sample_count_;
+    }
+  }
+};
+
+
+class TestApiCallbacks {
+ public:
+  TestApiCallbacks() {}
+
+  static void Getter(v8::Local<v8::String> name,
+                     const v8::PropertyCallbackInfo<v8::Value>& info) {
+  }
+
+  static void Setter(v8::Local<v8::String> name,
+                     v8::Local<v8::Value> value,
+                     const v8::PropertyCallbackInfo<void>& info) {
+  }
+};
+
+
+static void RunSampler(v8::Local<v8::Context> env,
+                       v8::Local<v8::Function> function,
+                       v8::Local<v8::Value> argv[], int argc,
+                       unsigned min_js_samples = 0,
+                       unsigned min_external_samples = 0) {
+  Sampler::SetUp();
+  TestSampler* sampler = new TestSampler(env->GetIsolate());
+  TestSamplingThread* thread = new TestSamplingThread(sampler);
+  sampler->IncreaseProfilingDepth();
+  sampler->Start();
+  sampler->StartCountingSamples();
+  thread->StartSynchronously();
+  do {
+    function->Call(env, env->Global(), argc, argv).ToLocalChecked();
+  } while (sampler->js_sample_count() < min_js_samples ||
+           sampler->external_sample_count() < min_external_samples);
+  sampler->Stop();
+  sampler->DecreaseProfilingDepth();
+  thread->Join();
+  delete thread;
+  delete sampler;
+  Sampler::TearDown();
+}
+
+}  // namespace
+
+static const char* sampler_test_source = "function start(count) {\n"
+"  for (var i = 0; i < count; i++) {\n"
+"    var o = instance.foo;\n"
+"    instance.foo = o + 1;\n"
+"  }\n"
+"}\n";
+
+static v8::Local<v8::Function> GetFunction(v8::Local<v8::Context> env,
+                                           const char* name) {
+  return v8::Local<v8::Function>::Cast(
+      env->Global()->Get(env, v8_str(name)).ToLocalChecked());
+}
+
+
+TEST(LibSamplerCollectSample) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+
+  v8::Local<v8::FunctionTemplate> func_template =
+      v8::FunctionTemplate::New(isolate);
+  v8::Local<v8::ObjectTemplate> instance_template =
+      func_template->InstanceTemplate();
+
+  TestApiCallbacks accessors;
+  v8::Local<v8::External> data =
+      v8::External::New(isolate, &accessors);
+  instance_template->SetAccessor(v8_str("foo"), &TestApiCallbacks::Getter,
+                                 &TestApiCallbacks::Setter, data);
+  v8::Local<v8::Function> func =
+      func_template->GetFunction(env.local()).ToLocalChecked();
+  v8::Local<v8::Object> instance =
+      func->NewInstance(env.local()).ToLocalChecked();
+  env->Global()->Set(env.local(), v8_str("instance"), instance).FromJust();
+
+  CompileRun(sampler_test_source);
+  v8::Local<v8::Function> function = GetFunction(env.local(), "start");
+
+  int32_t repeat_count = 100;
+  v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)};
+  RunSampler(env.local(), function, args, arraysize(args), 100, 100);
+}
+
+}  // namespace sampler
+}  // namespace v8
diff --git a/test/cctest/test-access-checks.cc b/test/cctest/test-access-checks.cc
new file mode 100644
index 0000000..34b64c4
--- /dev/null
+++ b/test/cctest/test-access-checks.cc
@@ -0,0 +1,182 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdlib.h>
+
+#include "test/cctest/cctest.h"
+
+namespace {
+
+int32_t g_cross_context_int = 0;
+
+void NamedGetter(v8::Local<v8::Name> property,
+                 const v8::PropertyCallbackInfo<v8::Value>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  if (property->Equals(context, v8_str("cross_context_int")).FromJust())
+    info.GetReturnValue().Set(g_cross_context_int);
+}
+
+void NamedSetter(v8::Local<v8::Name> property, v8::Local<v8::Value> value,
+                 const v8::PropertyCallbackInfo<v8::Value>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  if (!property->Equals(context, v8_str("cross_context_int")).FromJust())
+    return;
+  if (value->IsInt32()) {
+    g_cross_context_int = value->ToInt32(context).ToLocalChecked()->Value();
+  }
+  info.GetReturnValue().Set(value);
+}
+
+void NamedQuery(v8::Local<v8::Name> property,
+                const v8::PropertyCallbackInfo<v8::Integer>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  if (!property->Equals(context, v8_str("cross_context_int")).FromJust())
+    return;
+  info.GetReturnValue().Set(v8::DontDelete);
+}
+
+void NamedDeleter(v8::Local<v8::Name> property,
+                  const v8::PropertyCallbackInfo<v8::Boolean>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  if (!property->Equals(context, v8_str("cross_context_int")).FromJust())
+    return;
+  info.GetReturnValue().Set(false);
+}
+
+void NamedEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  v8::Local<v8::Array> names = v8::Array::New(isolate, 1);
+  names->Set(context, 0, v8_str("cross_context_int")).FromJust();
+  info.GetReturnValue().Set(names);
+}
+
+void IndexedGetter(uint32_t index,
+                   const v8::PropertyCallbackInfo<v8::Value>& info) {
+  if (index == 7) info.GetReturnValue().Set(g_cross_context_int);
+}
+
+void IndexedSetter(uint32_t index, v8::Local<v8::Value> value,
+                   const v8::PropertyCallbackInfo<v8::Value>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  if (index != 7) return;
+  if (value->IsInt32()) {
+    g_cross_context_int = value->ToInt32(context).ToLocalChecked()->Value();
+  }
+  info.GetReturnValue().Set(value);
+}
+
+void IndexedQuery(uint32_t index,
+                  const v8::PropertyCallbackInfo<v8::Integer>& info) {
+  if (index == 7) info.GetReturnValue().Set(v8::DontDelete);
+}
+
+void IndexedDeleter(uint32_t index,
+                    const v8::PropertyCallbackInfo<v8::Boolean>& info) {
+  if (index == 7) info.GetReturnValue().Set(false);
+}
+
+void IndexedEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  v8::Local<v8::Array> names = v8::Array::New(isolate, 1);
+  names->Set(context, 0, v8_str("7")).FromJust();
+  info.GetReturnValue().Set(names);
+}
+
+bool AccessCheck(v8::Local<v8::Context> accessing_context,
+                 v8::Local<v8::Object> accessed_object,
+                 v8::Local<v8::Value> data) {
+  return false;
+}
+
+void GetCrossContextInt(v8::Local<v8::String> property,
+                        const v8::PropertyCallbackInfo<v8::Value>& info) {
+  info.GetReturnValue().Set(g_cross_context_int);
+}
+
+void SetCrossContextInt(v8::Local<v8::String> property,
+                        v8::Local<v8::Value> value,
+                        const v8::PropertyCallbackInfo<void>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  if (value->IsInt32()) {
+    g_cross_context_int = value->ToInt32(context).ToLocalChecked()->Value();
+  }
+}
+
+void Return42(v8::Local<v8::String> property,
+              const v8::PropertyCallbackInfo<v8::Value>& info) {
+  info.GetReturnValue().Set(42);
+}
+
+}  // namespace
+
+TEST(AccessCheckWithInterceptor) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  v8::Local<v8::ObjectTemplate> global_template =
+      v8::ObjectTemplate::New(isolate);
+  global_template->SetAccessCheckCallbackAndHandler(
+      AccessCheck,
+      v8::NamedPropertyHandlerConfiguration(
+          NamedGetter, NamedSetter, NamedQuery, NamedDeleter, NamedEnumerator),
+      v8::IndexedPropertyHandlerConfiguration(IndexedGetter, IndexedSetter,
+                                              IndexedQuery, IndexedDeleter,
+                                              IndexedEnumerator));
+  global_template->SetNativeDataProperty(
+      v8_str("cross_context_int"), GetCrossContextInt, SetCrossContextInt);
+  global_template->SetNativeDataProperty(
+      v8_str("all_can_read"), Return42, nullptr, v8::Local<v8::Value>(),
+      v8::None, v8::Local<v8::AccessorSignature>(), v8::ALL_CAN_READ);
+
+  v8::Local<v8::Context> context0 =
+      v8::Context::New(isolate, nullptr, global_template);
+  context0->Enter();
+
+  // Running script in this context should work.
+  CompileRunChecked(isolate, "this.foo = 42; this[23] = true;");
+  ExpectInt32("this.all_can_read", 42);
+  CompileRunChecked(isolate, "this.cross_context_int = 23");
+  CHECK_EQ(g_cross_context_int, 23);
+  ExpectInt32("this.cross_context_int", 23);
+
+  // Create another context.
+  {
+    v8::HandleScope other_scope(isolate);
+    v8::Local<v8::Context> context1 =
+        v8::Context::New(isolate, nullptr, global_template);
+    context1->Global()
+        ->Set(context1, v8_str("other"), context0->Global())
+        .FromJust();
+    v8::Context::Scope context_scope(context1);
+
+    {
+      v8::TryCatch try_catch(isolate);
+      CHECK(CompileRun(context1, "this.other.foo").IsEmpty());
+    }
+    {
+      v8::TryCatch try_catch(isolate);
+      CHECK(CompileRun(context1, "this.other[23]").IsEmpty());
+    }
+
+    // AllCanRead properties are also inaccessible.
+    {
+      v8::TryCatch try_catch(isolate);
+      CHECK(CompileRun(context1, "this.other.all_can_read").IsEmpty());
+    }
+
+    // Intercepted properties are accessible, however.
+    ExpectInt32("this.other.cross_context_int", 23);
+    CompileRunChecked(isolate, "this.other.cross_context_int = 42");
+    ExpectInt32("this.other[7]", 42);
+    ExpectString("JSON.stringify(Object.getOwnPropertyNames(this.other))",
+                 "[\"7\",\"cross_context_int\"]");
+  }
+}
diff --git a/test/cctest/test-accessors.cc b/test/cctest/test-accessors.cc
index 67803ee..9667afb 100644
--- a/test/cctest/test-accessors.cc
+++ b/test/cctest/test-accessors.cc
@@ -775,19 +775,18 @@
   }
 }
 
-static void check_receiver(Local<String> name,
-                           const v8::PropertyCallbackInfo<v8::Value>& info) {
+static void CheckReceiver(Local<String> name,
+                          const v8::PropertyCallbackInfo<v8::Value>& info) {
   CHECK(info.This()->IsObject());
 }
 
 TEST(Regress609134) {
-  v8::internal::FLAG_allow_natives_syntax = true;
   LocalContext env;
   v8::Isolate* isolate = env->GetIsolate();
   v8::HandleScope scope(isolate);
   auto fun_templ = v8::FunctionTemplate::New(isolate);
   fun_templ->InstanceTemplate()->SetNativeDataProperty(v8_str("foo"),
-                                                       check_receiver);
+                                                       CheckReceiver);
 
   CHECK(env->Global()
             ->Set(env.local(), v8_str("Fun"),
@@ -797,5 +796,6 @@
   CompileRun(
       "var f = new Fun();"
       "Number.prototype.__proto__ = f;"
-      "[42][0].foo");
+      "var a = 42;"
+      "for (var i = 0; i<3; i++) { a.foo; }");
 }
diff --git a/test/cctest/test-api-interceptors.cc b/test/cctest/test-api-interceptors.cc
index a1894fa..1636e4b 100644
--- a/test/cctest/test-api-interceptors.cc
+++ b/test/cctest/test-api-interceptors.cc
@@ -854,6 +854,66 @@
   CHECK_EQ(42 * 10, value->Int32Value(context.local()).FromJust());
 }
 
+// Test load of a non-existing global when a global object has an interceptor.
+THREADED_TEST(InterceptorLoadGlobalICGlobalWithInterceptor) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  v8::Local<v8::ObjectTemplate> templ_global = v8::ObjectTemplate::New(isolate);
+  templ_global->SetHandler(v8::NamedPropertyHandlerConfiguration(
+      EmptyInterceptorGetter, EmptyInterceptorSetter));
+
+  LocalContext context(nullptr, templ_global);
+  i::Handle<i::JSReceiver> global_proxy =
+      v8::Utils::OpenHandle<Object, i::JSReceiver>(context->Global());
+  CHECK(global_proxy->IsJSGlobalProxy());
+  i::Handle<i::JSGlobalObject> global(
+      i::JSGlobalObject::cast(global_proxy->map()->prototype()));
+  CHECK(global->map()->has_named_interceptor());
+
+  v8::Local<Value> value = CompileRun(
+      "var f = function() { "
+      "  try {"
+      "    x1;"
+      "  } catch(e) {"
+      "  }"
+      "  return typeof x1 === 'undefined';"
+      "};"
+      "for (var i = 0; i < 10; i++) {"
+      "  f();"
+      "};"
+      "f();");
+  CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
+
+  value = CompileRun(
+      "var f = function() { "
+      "  try {"
+      "    x2;"
+      "    return false;"
+      "  } catch(e) {"
+      "    return true;"
+      "  }"
+      "};"
+      "for (var i = 0; i < 10; i++) {"
+      "  f();"
+      "};"
+      "f();");
+  CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
+
+  value = CompileRun(
+      "var f = function() { "
+      "  try {"
+      "    typeof(x3);"
+      "    return true;"
+      "  } catch(e) {"
+      "    return false;"
+      "  }"
+      "};"
+      "for (var i = 0; i < 10; i++) {"
+      "  f();"
+      "};"
+      "f();");
+  CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
+}
 
 static void InterceptorLoadICGetter0(
     Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
@@ -2270,33 +2330,34 @@
   // This order is not mandated by the spec, so this test is just
   // documenting our behavior.
   CHECK_EQ(17u, result->Length());
-  // Indexed properties + indexed interceptor properties in numerical order.
-  CHECK(v8_str("0")
+  // Indexed properties.
+  CHECK(v8_str("5")
             ->Equals(context.local(),
                      result->Get(context.local(), v8::Integer::New(isolate, 0))
                          .ToLocalChecked())
             .FromJust());
-  CHECK(v8_str("1")
+  CHECK(v8_str("10")
             ->Equals(context.local(),
                      result->Get(context.local(), v8::Integer::New(isolate, 1))
                          .ToLocalChecked())
             .FromJust());
-  CHECK(v8_str("5")
+  CHECK(v8_str("140000")
             ->Equals(context.local(),
                      result->Get(context.local(), v8::Integer::New(isolate, 2))
                          .ToLocalChecked())
             .FromJust());
-  CHECK(v8_str("10")
+  CHECK(v8_str("4294967294")
             ->Equals(context.local(),
                      result->Get(context.local(), v8::Integer::New(isolate, 3))
                          .ToLocalChecked())
             .FromJust());
-  CHECK(v8_str("140000")
+  // Indexed Interceptor properties
+  CHECK(v8_str("0")
             ->Equals(context.local(),
                      result->Get(context.local(), v8::Integer::New(isolate, 4))
                          .ToLocalChecked())
             .FromJust());
-  CHECK(v8_str("4294967294")
+  CHECK(v8_str("1")
             ->Equals(context.local(),
                      result->Get(context.local(), v8::Integer::New(isolate, 5))
                          .ToLocalChecked())
@@ -3245,6 +3306,25 @@
   CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
 }
 
+THREADED_TEST(Regress625155) {
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
+  AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
+  context->Global()
+      ->Set(context.local(), v8_str("Bug"),
+            templ->GetFunction(context.local()).ToLocalChecked())
+      .FromJust();
+  CompileRun(
+      "Number.prototype.__proto__ = new Bug;"
+      "var x;"
+      "x = 0xdead;"
+      "x.boom = 0;"
+      "x = 's';"
+      "x.boom = 0;"
+      "x = 1.5;"
+      "x.boom = 0;");
+}
 
 THREADED_TEST(Regress125988) {
   v8::HandleScope scope(CcTest::isolate());
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 220b0cd..5624e3f 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -47,11 +47,12 @@
 #include "src/futex-emulation.h"
 #include "src/objects.h"
 #include "src/parsing/parser.h"
+#include "src/profiler/cpu-profiler.h"
 #include "src/unicode-inl.h"
 #include "src/utils.h"
 #include "src/vm-state.h"
 #include "test/cctest/heap/heap-tester.h"
-#include "test/cctest/heap/utils-inl.h"
+#include "test/cctest/heap/heap-utils.h"
 
 static const bool kLogThreading = false;
 
@@ -555,40 +556,19 @@
   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
 
   uint16_t* two_byte_string = AsciiToTwoByteString("s1");
-  Local<String> small_string =
+  Local<String> local_string =
       String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
                              v8::NewStringType::kNormal)
           .ToLocalChecked();
   i::DeleteArray(two_byte_string);
 
-  // We should refuse to externalize small strings.
-  CHECK(!small_string->CanMakeExternal());
+  // We should refuse to externalize new space strings.
+  CHECK(!local_string->CanMakeExternal());
   // Trigger GCs so that the newly allocated string moves to old gen.
   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
   // Old space strings should be accepted.
-  CHECK(small_string->CanMakeExternal());
-
-  two_byte_string = AsciiToTwoByteString("small string 2");
-  small_string = String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
-                                        v8::NewStringType::kNormal)
-                     .ToLocalChecked();
-  i::DeleteArray(two_byte_string);
-
-  const int buf_size = 10 * 1024;
-  char* buf = i::NewArray<char>(buf_size);
-  memset(buf, 'a', buf_size);
-  buf[buf_size - 1] = '\0';
-
-  two_byte_string = AsciiToTwoByteString(buf);
-  Local<String> large_string =
-      String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
-                             v8::NewStringType::kNormal)
-          .ToLocalChecked();
-  i::DeleteArray(buf);
-  i::DeleteArray(two_byte_string);
-  // Large strings should be immediately accepted.
-  CHECK(large_string->CanMakeExternal());
+  CHECK(local_string->CanMakeExternal());
 }
 
 
@@ -600,23 +580,14 @@
   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
 
-  Local<String> small_string = v8_str("s1");
-  // We should refuse to externalize small strings.
-  CHECK(!small_string->CanMakeExternal());
+  Local<String> local_string = v8_str("s1");
+  // We should refuse to externalize new space strings.
+  CHECK(!local_string->CanMakeExternal());
   // Trigger GCs so that the newly allocated string moves to old gen.
   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
   // Old space strings should be accepted.
-  CHECK(small_string->CanMakeExternal());
-
-  const int buf_size = 10 * 1024;
-  char* buf = i::NewArray<char>(buf_size);
-  memset(buf, 'a', buf_size);
-  buf[buf_size - 1] = '\0';
-  Local<String> large_string = v8_str(buf);
-  i::DeleteArray(buf);
-  // Large strings should be immediately accepted.
-  CHECK(large_string->CanMakeExternal());
+  CHECK(local_string->CanMakeExternal());
 }
 
 
@@ -634,7 +605,7 @@
       "slice('abcdefghijklmnopqrstuvwxyz');"));
 
   // Trigger GCs so that the newly allocated string moves to old gen.
-  SimulateFullSpace(CcTest::heap()->old_space());
+  i::heap::SimulateFullSpace(CcTest::heap()->old_space());
   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in survivor space now
   CcTest::heap()->CollectGarbage(i::NEW_SPACE);  // in old gen now
 
@@ -2142,6 +2113,95 @@
       Constructor_GetFunction_New);
 }
 
+THREADED_TEST(TestObjectTemplateClassInheritance) {
+  LocalContext env;
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+
+  Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
+  fun_A->SetClassName(v8_str("A"));
+
+  Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
+  templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
+  templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
+
+  Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
+  v8::Local<v8::String> class_name = v8_str("B");
+  fun_B->SetClassName(class_name);
+  fun_B->Inherit(fun_A);
+
+  v8::Local<v8::String> subclass_name = v8_str("C");
+  v8::Local<v8::Object> b_proto;
+  v8::Local<v8::Object> c_proto;
+  // Perform several iterations to make sure the cache doesn't break
+  // subclassing.
+  for (int i = 0; i < 3; i++) {
+    Local<v8::Function> function_B =
+        fun_B->GetFunction(env.local()).ToLocalChecked();
+    if (i == 0) {
+      CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust());
+      CompileRun("class C extends B {}");
+      b_proto =
+          CompileRun("B.prototype")->ToObject(env.local()).ToLocalChecked();
+      c_proto =
+          CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked();
+      CHECK(b_proto->Equals(env.local(), c_proto->GetPrototype()).FromJust());
+    }
+    Local<v8::Object> instance =
+        CompileRun("new C()")->ToObject(env.local()).ToLocalChecked();
+    CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust());
+
+    CHECK(subclass_name->StrictEquals(instance->GetConstructorName()));
+    CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
+
+    CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
+    CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
+  }
+}
+
+static void NamedPropertyGetterWhichReturns42(
+    Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
+  info.GetReturnValue().Set(v8_num(42));
+}
+
+THREADED_TEST(TestObjectTemplateReflectConstruct) {
+  LocalContext env;
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+
+  Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
+  fun_B->InstanceTemplate()->SetHandler(
+      v8::NamedPropertyHandlerConfiguration(NamedPropertyGetterWhichReturns42));
+  v8::Local<v8::String> class_name = v8_str("B");
+  fun_B->SetClassName(class_name);
+
+  v8::Local<v8::String> subclass_name = v8_str("C");
+  v8::Local<v8::Object> b_proto;
+  v8::Local<v8::Object> c_proto;
+  // Perform several iterations to make sure the cache doesn't break
+  // subclassing.
+  for (int i = 0; i < 3; i++) {
+    Local<v8::Function> function_B =
+        fun_B->GetFunction(env.local()).ToLocalChecked();
+    if (i == 0) {
+      CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust());
+      CompileRun("function C() {}");
+      c_proto =
+          CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked();
+    }
+    Local<v8::Object> instance = CompileRun("Reflect.construct(B, [], C)")
+                                     ->ToObject(env.local())
+                                     .ToLocalChecked();
+    CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust());
+
+    CHECK(subclass_name->StrictEquals(instance->GetConstructorName()));
+    CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
+
+    CHECK_EQ(42, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
+    CHECK_EQ(42, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
+  }
+}
+
 static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
   ApiTestFuzzer::Fuzz();
   args.GetReturnValue().Set(v8_num(17.2));
@@ -2738,16 +2798,15 @@
   CHECK(env->Global()
             ->Set(env.local(), v8_str("global"), global_proxy)
             .FromJust());
-  i::Handle<i::Object> original_hash;
+  int32_t hash1;
   if (set_in_js) {
     CompileRun("var m = new Set(); m.add(global);");
-    original_hash = i::Handle<i::Object>(i_global_proxy->GetHash(), i_isolate);
+    i::Object* original_hash = i_global_proxy->GetHash();
+    CHECK(original_hash->IsSmi());
+    hash1 = i::Smi::cast(original_hash)->value();
   } else {
-    original_hash = i::Handle<i::Object>(
-        i::Object::GetOrCreateHash(i_isolate, i_global_proxy));
+    hash1 = i::Object::GetOrCreateHash(i_isolate, i_global_proxy)->value();
   }
-  CHECK(original_hash->IsSmi());
-  int32_t hash1 = i::Handle<i::Smi>::cast(original_hash)->value();
   // Hash should be retained after being detached.
   env->DetachGlobal();
   int hash2 = global_proxy->GetIdentityHash();
@@ -4687,126 +4746,6 @@
 }
 
 
-// TODO(mstarzinger): This should be a THREADED_TEST but causes failures
-// on the buildbots, so was made non-threaded for the time being.
-TEST(ApiObjectGroupsCycleForScavenger) {
-  i::FLAG_stress_compaction = false;
-  i::FLAG_gc_global = false;
-  LocalContext env;
-  v8::Isolate* iso = env->GetIsolate();
-  HandleScope scope(iso);
-
-  WeakCallCounter counter(1234);
-
-  WeakCallCounterAndPersistent<Value> g1s1(&counter);
-  WeakCallCounterAndPersistent<Value> g1s2(&counter);
-  WeakCallCounterAndPersistent<Value> g2s1(&counter);
-  WeakCallCounterAndPersistent<Value> g2s2(&counter);
-  WeakCallCounterAndPersistent<Value> g3s1(&counter);
-  WeakCallCounterAndPersistent<Value> g3s2(&counter);
-
-  {
-    HandleScope scope(iso);
-    g1s1.handle.Reset(iso, Object::New(iso));
-    g1s2.handle.Reset(iso, Object::New(iso));
-    g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
-                        v8::WeakCallbackType::kParameter);
-    g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
-                        v8::WeakCallbackType::kParameter);
-
-    g2s1.handle.Reset(iso, Object::New(iso));
-    g2s2.handle.Reset(iso, Object::New(iso));
-    g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
-                        v8::WeakCallbackType::kParameter);
-    g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
-                        v8::WeakCallbackType::kParameter);
-
-    g3s1.handle.Reset(iso, Object::New(iso));
-    g3s2.handle.Reset(iso, Object::New(iso));
-    g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
-                        v8::WeakCallbackType::kParameter);
-    g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
-                        v8::WeakCallbackType::kParameter);
-  }
-
-  // Make a root.
-  WeakCallCounterAndPersistent<Value> root(&counter);
-  root.handle.Reset(iso, g1s1.handle);
-  root.handle.MarkPartiallyDependent();
-
-  // Connect groups.  We're building the following cycle:
-  // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
-  // groups.
-  {
-    HandleScope handle_scope(iso);
-    g1s1.handle.MarkPartiallyDependent();
-    g1s2.handle.MarkPartiallyDependent();
-    g2s1.handle.MarkPartiallyDependent();
-    g2s2.handle.MarkPartiallyDependent();
-    g3s1.handle.MarkPartiallyDependent();
-    g3s2.handle.MarkPartiallyDependent();
-    iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
-    iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
-    Local<Object>::New(iso, g1s1.handle.As<Object>())
-        ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g2s1.handle))
-        .FromJust();
-    iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
-    iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
-    Local<Object>::New(iso, g2s1.handle.As<Object>())
-        ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g3s1.handle))
-        .FromJust();
-    iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
-    iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
-    Local<Object>::New(iso, g3s1.handle.As<Object>())
-        ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g1s1.handle))
-        .FromJust();
-  }
-
-  v8::internal::Heap* heap =
-      reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
-  heap->CollectAllGarbage();
-
-  // All objects should be alive.
-  CHECK_EQ(0, counter.NumberOfWeakCalls());
-
-  // Weaken the root.
-  root.handle.SetWeak(&root, &WeakPointerCallback,
-                      v8::WeakCallbackType::kParameter);
-  root.handle.MarkPartiallyDependent();
-
-  // Groups are deleted, rebuild groups.
-  {
-    HandleScope handle_scope(iso);
-    g1s1.handle.MarkPartiallyDependent();
-    g1s2.handle.MarkPartiallyDependent();
-    g2s1.handle.MarkPartiallyDependent();
-    g2s2.handle.MarkPartiallyDependent();
-    g3s1.handle.MarkPartiallyDependent();
-    g3s2.handle.MarkPartiallyDependent();
-    iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
-    iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
-    Local<Object>::New(iso, g1s1.handle.As<Object>())
-        ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g2s1.handle))
-        .FromJust();
-    iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
-    iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
-    Local<Object>::New(iso, g2s1.handle.As<Object>())
-        ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g3s1.handle))
-        .FromJust();
-    iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
-    iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
-    Local<Object>::New(iso, g3s1.handle.As<Object>())
-        ->Set(env.local(), v8_str("x"), Local<Value>::New(iso, g1s1.handle))
-        .FromJust();
-  }
-
-  heap->CollectAllGarbage();
-
-  // All objects should be gone. 7 global handles in total.
-  CHECK_EQ(7, counter.NumberOfWeakCalls());
-}
-
-
 THREADED_TEST(ScriptException) {
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
@@ -6511,6 +6450,46 @@
   CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
 }
 
+THREADED_TEST(TypeOf) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(context->GetIsolate());
+
+  Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
+  Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
+
+  CHECK(v8::Undefined(isolate)
+            ->TypeOf(isolate)
+            ->Equals(context.local(), v8_str("undefined"))
+            .FromJust());
+  CHECK(v8::Null(isolate)
+            ->TypeOf(isolate)
+            ->Equals(context.local(), v8_str("object"))
+            .FromJust());
+  CHECK(v8_str("str")
+            ->TypeOf(isolate)
+            ->Equals(context.local(), v8_str("string"))
+            .FromJust());
+  CHECK(v8_num(0.0)
+            ->TypeOf(isolate)
+            ->Equals(context.local(), v8_str("number"))
+            .FromJust());
+  CHECK(v8_num(1)
+            ->TypeOf(isolate)
+            ->Equals(context.local(), v8_str("number"))
+            .FromJust());
+  CHECK(v8::Object::New(isolate)
+            ->TypeOf(isolate)
+            ->Equals(context.local(), v8_str("object"))
+            .FromJust());
+  CHECK(v8::Boolean::New(isolate, true)
+            ->TypeOf(isolate)
+            ->Equals(context.local(), v8_str("boolean"))
+            .FromJust());
+  CHECK(fun->TypeOf(isolate)
+            ->Equals(context.local(), v8_str("function"))
+            .FromJust());
+}
 
 THREADED_TEST(MultiRun) {
   LocalContext context;
@@ -9046,33 +9025,6 @@
 }
 
 
-TEST(ApiUncaughtExceptionInObjectObserve) {
-  v8::internal::FLAG_harmony_object_observe = true;
-  v8::internal::FLAG_stack_size = 150;
-  report_count = 0;
-  LocalContext env;
-  v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope scope(isolate);
-  isolate->AddMessageListener(ApiUncaughtExceptionTestListener);
-  CompileRun(
-      "var obj = {};"
-      "var observe_count = 0;"
-      "function observer1() { ++observe_count; };"
-      "function observer2() { ++observe_count; };"
-      "function observer_throws() { throw new Error(); };"
-      "function stack_overflow() { return (function f(x) { f(x+1); })(0); };"
-      "Object.observe(obj, observer_throws.bind());"
-      "Object.observe(obj, observer1);"
-      "Object.observe(obj, stack_overflow);"
-      "Object.observe(obj, observer2);"
-      "Object.observe(obj, observer_throws.bind());"
-      "obj.foo = 'bar';");
-  CHECK_EQ(3, report_count);
-  ExpectInt32("observe_count", 2);
-  isolate->RemoveMessageListeners(ApiUncaughtExceptionTestListener);
-}
-
-
 static const char* script_resource_name = "ExceptionInNativeScript.js";
 static void ExceptionInNativeScriptTestListener(v8::Local<v8::Message> message,
                                                 v8::Local<Value>) {
@@ -10541,6 +10493,69 @@
   }
 }
 
+THREADED_TEST(ObjectGetOwnPropertyNames) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope handle_scope(isolate);
+
+  v8::Local<v8::Object> value =
+      v8::Local<v8::Object>::Cast(v8::StringObject::New(v8_str("test")));
+  v8::Local<v8::Array> properties;
+
+  CHECK(value
+            ->GetOwnPropertyNames(context.local(),
+                                  static_cast<v8::PropertyFilter>(
+                                      v8::PropertyFilter::ALL_PROPERTIES |
+                                      v8::PropertyFilter::SKIP_SYMBOLS))
+            .ToLocal(&properties));
+  CHECK_EQ(5, properties->Length());
+  v8::Local<v8::Value> property;
+  CHECK(properties->Get(context.local(), 4).ToLocal(&property) &&
+        property->IsString());
+  CHECK(property.As<v8::String>()
+            ->Equals(context.local(), v8_str("length"))
+            .FromMaybe(false));
+  for (int i = 0; i < 4; ++i) {
+    v8::Local<v8::Value> property;
+    CHECK(properties->Get(context.local(), i).ToLocal(&property) &&
+          property->IsInt32());
+    CHECK_EQ(property.As<v8::Int32>()->Value(), i);
+  }
+
+  CHECK(value->GetOwnPropertyNames(context.local(), v8::ONLY_ENUMERABLE)
+            .ToLocal(&properties));
+  CHECK_EQ(4, properties->Length());
+  for (int i = 0; i < 4; ++i) {
+    v8::Local<v8::Value> property;
+    CHECK(properties->Get(context.local(), i).ToLocal(&property) &&
+          property->IsInt32());
+    CHECK_EQ(property.As<v8::Int32>()->Value(), i);
+  }
+
+  value = value->GetPrototype().As<v8::Object>();
+  CHECK(value
+            ->GetOwnPropertyNames(context.local(),
+                                  static_cast<v8::PropertyFilter>(
+                                      v8::PropertyFilter::ALL_PROPERTIES |
+                                      v8::PropertyFilter::SKIP_SYMBOLS))
+            .ToLocal(&properties));
+  bool concat_found = false;
+  bool starts_with_found = false;
+  for (uint32_t i = 0; i < properties->Length(); ++i) {
+    v8::Local<v8::Value> property;
+    CHECK(properties->Get(context.local(), i).ToLocal(&property));
+    if (!property->IsString()) continue;
+    if (!concat_found)
+      concat_found = property.As<v8::String>()
+                         ->Equals(context.local(), v8_str("concat"))
+                         .FromMaybe(false);
+    if (!starts_with_found)
+      starts_with_found = property.As<v8::String>()
+                              ->Equals(context.local(), v8_str("startsWith"))
+                              .FromMaybe(false);
+  }
+  CHECK(concat_found && starts_with_found);
+}
 
 THREADED_TEST(CallKnownGlobalReceiver) {
   v8::Isolate* isolate = CcTest::isolate();
@@ -11185,6 +11200,7 @@
   Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
   t1->RemovePrototype();
   Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
+  CHECK(!fun->IsConstructor());
   CHECK(context->Global()->Set(context.local(), v8_str("fun"), fun).FromJust());
   CHECK(!CompileRun("'prototype' in fun")
              ->BooleanValue(context.local())
@@ -13261,6 +13277,43 @@
   CHECK(value->BooleanValue(context.local()).FromJust());
 }
 
+static void NewTargetHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  ApiTestFuzzer::Fuzz();
+  args.GetReturnValue().Set(args.NewTarget());
+}
+
+THREADED_TEST(NewTargetHandler) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+
+  // Function template with call handler.
+  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
+  templ->SetCallHandler(NewTargetHandler);
+
+  LocalContext context;
+
+  Local<Function> function =
+      templ->GetFunction(context.local()).ToLocalChecked();
+  CHECK(context->Global()
+            ->Set(context.local(), v8_str("f"), function)
+            .FromJust());
+  Local<Value> value = CompileRun("f()");
+  CHECK(value->IsUndefined());
+  value = CompileRun("new f()");
+  CHECK(value->IsFunction());
+  CHECK(value == function);
+  Local<Value> subclass = CompileRun("var g = class extends f { }; g");
+  CHECK(subclass->IsFunction());
+  value = CompileRun("new g()");
+  CHECK(value->IsFunction());
+  CHECK(value == subclass);
+  value = CompileRun("Reflect.construct(f, [], Array)");
+  CHECK(value->IsFunction());
+  CHECK(value ==
+        context->Global()
+            ->Get(context.local(), v8_str("Array"))
+            .ToLocalChecked());
+}
 
 THREADED_TEST(ObjectProtoToString) {
   v8::Isolate* isolate = CcTest::isolate();
@@ -13298,7 +13351,7 @@
   value =
       context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
   CHECK(value->IsString() &&
-        value->Equals(context.local(), v8_str("[object global]")).FromJust());
+        value->Equals(context.local(), v8_str("[object Object]")).FromJust());
 
   // Check ordinary object
   Local<Value> object =
@@ -13344,7 +13397,7 @@
   value =
       context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
   CHECK(value->IsString() &&
-        value->Equals(context.local(), v8_str("[object global]")).FromJust());
+        value->Equals(context.local(), v8_str("[object Object]")).FromJust());
 
   // Check ordinary object
   Local<Value> object = CompileRun("new Object()");
@@ -14416,7 +14469,6 @@
   return invocations;
 }
 
-
 void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
   v8::HandleScope outer(isolate);
   v8::Local<Context> env = Context::New(isolate);
@@ -14474,10 +14526,19 @@
 
     RunLoopInNewEnv(isolate);
 
-    // Check the exepected invocation counts.
-    CHECK_EQ(2, CountInvocations(NULL, "bar"));
-    CHECK_EQ(200, CountInvocations("bar", "foo"));
-    CHECK_EQ(200, CountInvocations(NULL, "foo"));
+    // Check the expected invocation counts.
+    if (!i::FLAG_ignition) {
+      CHECK_EQ(2, CountInvocations(NULL, "bar"));
+      CHECK_EQ(200, CountInvocations("bar", "foo"));
+      CHECK_EQ(200, CountInvocations(NULL, "foo"));
+    } else {
+      // For ignition we don't see the actual functions being called, instead
+      // we see the IterpreterEntryTrampoline at least 102 times
+      // (100 unoptimized calls to foo, and 2 calls to bar).
+      CHECK_LE(102, CountInvocations(NULL, "InterpreterEntryTrampoline"));
+      // We should also see the calls to the optimized function foo.
+      CHECK_EQ(100, CountInvocations(NULL, "foo"));
+    }
 
     // Verify that we have an entry hook on some specific stubs.
     CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
@@ -14519,9 +14580,8 @@
   test.RunTest();
 }
 
-
-static i::HashMap* code_map = NULL;
-static i::HashMap* jitcode_line_info = NULL;
+static v8::base::HashMap* code_map = NULL;
+static v8::base::HashMap* jitcode_line_info = NULL;
 static int saw_bar = 0;
 static int move_events = 0;
 
@@ -14581,7 +14641,7 @@
         CHECK(event->code_start != NULL);
         CHECK_NE(0, static_cast<int>(event->code_len));
         CHECK(event->name.str != NULL);
-        i::HashMap::Entry* entry = code_map->LookupOrInsert(
+        v8::base::HashMap::Entry* entry = code_map->LookupOrInsert(
             event->code_start, i::ComputePointerHash(event->code_start));
         entry->value = reinterpret_cast<void*>(event->code_len);
 
@@ -14600,7 +14660,8 @@
         // Compiler::RecordFunctionCompilation) and the line endings
         // calculations can cause a GC, which can move the newly created code
         // before its existence can be logged.
-        i::HashMap::Entry* entry = code_map->Lookup(event->code_start, hash);
+        v8::base::HashMap::Entry* entry =
+            code_map->Lookup(event->code_start, hash);
         if (entry != NULL) {
           ++move_events;
 
@@ -14627,7 +14688,7 @@
         DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
         v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
         temp_event->user_data = line_info;
-        i::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
+        v8::base::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
             line_info, i::ComputePointerHash(line_info));
         entry->value = reinterpret_cast<void*>(line_info);
       }
@@ -14638,7 +14699,7 @@
     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
         CHECK(event->user_data != NULL);
         uint32_t hash = i::ComputePointerHash(event->user_data);
-        i::HashMap::Entry* entry =
+        v8::base::HashMap::Entry* entry =
             jitcode_line_info->Lookup(event->user_data, hash);
         CHECK(entry != NULL);
         delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
@@ -14648,7 +14709,7 @@
     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
         CHECK(event->user_data != NULL);
         uint32_t hash = i::ComputePointerHash(event->user_data);
-        i::HashMap::Entry* entry =
+        v8::base::HashMap::Entry* entry =
             jitcode_line_info->Lookup(event->user_data, hash);
         CHECK(entry != NULL);
       }
@@ -14690,10 +14751,10 @@
 
   {
     v8::HandleScope scope(isolate);
-    i::HashMap code(MatchPointers);
+    v8::base::HashMap code(MatchPointers);
     code_map = &code;
 
-    i::HashMap lineinfo(MatchPointers);
+    v8::base::HashMap lineinfo(MatchPointers);
     jitcode_line_info = &lineinfo;
 
     saw_bar = 0;
@@ -14707,8 +14768,8 @@
     for (int i = 0; i < kIterations; ++i) {
       LocalContext env(isolate);
       i::AlwaysAllocateScope always_allocate(i_isolate);
-      SimulateFullSpace(i::FLAG_ignition ? heap->old_space()
-                                         : heap->code_space());
+      i::heap::SimulateFullSpace(i::FLAG_ignition ? heap->old_space()
+                                                  : heap->code_space());
       CompileRun(script);
 
       // Keep a strong reference to the code object in the handle scope.
@@ -14756,10 +14817,10 @@
     CompileRun(script);
 
     // Now get code through initial iteration.
-    i::HashMap code(MatchPointers);
+    v8::base::HashMap code(MatchPointers);
     code_map = &code;
 
-    i::HashMap lineinfo(MatchPointers);
+    v8::base::HashMap lineinfo(MatchPointers);
     jitcode_line_info = &lineinfo;
 
     isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
@@ -14792,8 +14853,7 @@
            isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
   CHECK_EQ(baseline,
            isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
-  const int64_t kTriggerGCSize =
-      v8::internal::Internals::kExternalAllocationLimit + 1;
+  const int64_t kTriggerGCSize = i::kExternalAllocationLimit + 1;
   CHECK_EQ(baseline + kTriggerGCSize,
            isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
   CHECK_EQ(baseline,
@@ -14805,8 +14865,7 @@
   i::FLAG_incremental_marking = false;
   CcTest::InitializeVM();
 
-  const int64_t kTriggerGCSize =
-      v8::internal::Internals::kExternalAllocationLimit + 1;
+  const int64_t kTriggerGCSize = i::kExternalAllocationLimit + 1;
   v8::Isolate* isolate = CcTest::isolate();
   isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize);
 }
@@ -14981,18 +15040,39 @@
   CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
 }
 
+void CheckIsSymbolAt(v8::Isolate* isolate, v8::Local<v8::Array> properties,
+                     unsigned index, const char* name) {
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  v8::Local<v8::Value> value =
+      properties->Get(context, v8::Integer::New(isolate, index))
+          .ToLocalChecked();
+  CHECK(value->IsSymbol());
+  v8::String::Utf8Value symbol_name(Local<Symbol>::Cast(value)->Name());
+  CHECK_EQ(0, strcmp(name, *symbol_name));
+}
+
+void CheckStringArray(v8::Isolate* isolate, v8::Local<v8::Array> properties,
+                      unsigned length, const char* names[]) {
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  CHECK_EQ(length, properties->Length());
+  for (unsigned i = 0; i < length; i++) {
+    v8::Local<v8::Value> value =
+        properties->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked();
+    if (names[i] == nullptr) {
+      DCHECK(value->IsSymbol());
+    } else {
+      v8::String::Utf8Value elm(value);
+      CHECK_EQ(0, strcmp(names[i], *elm));
+    }
+  }
+}
 
 void CheckProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
-                     unsigned elmc, const char* elmv[]) {
+                     unsigned length, const char* names[]) {
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   v8::Local<v8::Object> obj = val.As<v8::Object>();
   v8::Local<v8::Array> props = obj->GetPropertyNames(context).ToLocalChecked();
-  CHECK_EQ(elmc, props->Length());
-  for (unsigned i = 0; i < elmc; i++) {
-    v8::String::Utf8Value elm(
-        props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
-    CHECK_EQ(0, strcmp(elmv[i], *elm));
-  }
+  CheckStringArray(isolate, props, length, names);
 }
 
 
@@ -15103,6 +15183,97 @@
   }
 }
 
+THREADED_TEST(PropertyNames) {
+  LocalContext context;
+  v8::Isolate* isolate = context->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::Local<v8::Value> result = CompileRun(
+      "var result = {0: 0, 1: 1, a: 2, b: 3};"
+      "result[Symbol('symbol')] = true;"
+      "result.__proto__ = {2: 4, 3: 5, c: 6, d: 7};"
+      "result;");
+  v8::Local<v8::Object> object = result.As<v8::Object>();
+  v8::PropertyFilter default_filter =
+      static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOLS);
+  v8::PropertyFilter include_symbols_filter = v8::ONLY_ENUMERABLE;
+
+  v8::Local<v8::Array> properties =
+      object->GetPropertyNames(context.local()).ToLocalChecked();
+  const char* expected_properties1[] = {"0", "1", "a", "b", "2", "3", "c", "d"};
+  CheckStringArray(isolate, properties, 8, expected_properties1);
+
+  properties =
+      object
+          ->GetPropertyNames(context.local(),
+                             v8::KeyCollectionMode::kIncludePrototypes,
+                             default_filter, v8::IndexFilter::kIncludeIndices)
+          .ToLocalChecked();
+  CheckStringArray(isolate, properties, 8, expected_properties1);
+
+  properties = object
+                   ->GetPropertyNames(context.local(),
+                                      v8::KeyCollectionMode::kIncludePrototypes,
+                                      include_symbols_filter,
+                                      v8::IndexFilter::kIncludeIndices)
+                   .ToLocalChecked();
+  const char* expected_properties1_1[] = {"0", "1", "a", "b", nullptr,
+                                          "2", "3", "c", "d"};
+  CheckStringArray(isolate, properties, 9, expected_properties1_1);
+  CheckIsSymbolAt(isolate, properties, 4, "symbol");
+
+  properties =
+      object
+          ->GetPropertyNames(context.local(),
+                             v8::KeyCollectionMode::kIncludePrototypes,
+                             default_filter, v8::IndexFilter::kSkipIndices)
+          .ToLocalChecked();
+  const char* expected_properties2[] = {"a", "b", "c", "d"};
+  CheckStringArray(isolate, properties, 4, expected_properties2);
+
+  properties = object
+                   ->GetPropertyNames(context.local(),
+                                      v8::KeyCollectionMode::kIncludePrototypes,
+                                      include_symbols_filter,
+                                      v8::IndexFilter::kSkipIndices)
+                   .ToLocalChecked();
+  const char* expected_properties2_1[] = {"a", "b", nullptr, "c", "d"};
+  CheckStringArray(isolate, properties, 5, expected_properties2_1);
+  CheckIsSymbolAt(isolate, properties, 2, "symbol");
+
+  properties =
+      object
+          ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
+                             default_filter, v8::IndexFilter::kIncludeIndices)
+          .ToLocalChecked();
+  const char* expected_properties3[] = {"0", "1", "a", "b"};
+  CheckStringArray(isolate, properties, 4, expected_properties3);
+
+  properties = object
+                   ->GetPropertyNames(
+                       context.local(), v8::KeyCollectionMode::kOwnOnly,
+                       include_symbols_filter, v8::IndexFilter::kIncludeIndices)
+                   .ToLocalChecked();
+  const char* expected_properties3_1[] = {"0", "1", "a", "b", nullptr};
+  CheckStringArray(isolate, properties, 5, expected_properties3_1);
+  CheckIsSymbolAt(isolate, properties, 4, "symbol");
+
+  properties =
+      object
+          ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
+                             default_filter, v8::IndexFilter::kSkipIndices)
+          .ToLocalChecked();
+  const char* expected_properties4[] = {"a", "b"};
+  CheckStringArray(isolate, properties, 2, expected_properties4);
+
+  properties = object
+                   ->GetPropertyNames(
+                       context.local(), v8::KeyCollectionMode::kOwnOnly,
+                       include_symbols_filter, v8::IndexFilter::kSkipIndices)
+                   .ToLocalChecked();
+  const char* expected_properties4_1[] = {"a", "b", nullptr};
+  CheckStringArray(isolate, properties, 3, expected_properties4_1);
+  CheckIsSymbolAt(isolate, properties, 2, "symbol");
+}
 
 THREADED_TEST(AccessChecksReenabledCorrectly) {
   LocalContext context;
@@ -18371,7 +18542,6 @@
 
 
 THREADED_TEST(FunctionGetDebugName) {
-  i::FLAG_harmony_function_name = true;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
   const char* code =
@@ -18728,12 +18898,6 @@
 }
 
 
-static void NamedPropertyGetterWhichReturns42(
-    Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
-  info.GetReturnValue().Set(v8_num(42));
-}
-
-
 static void NamedPropertySetterWhichSetsYOnThisTo23(
     Local<Name> name, Local<Value> value,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
@@ -18916,7 +19080,7 @@
   ++prologue_call_count_alloc;
 
   // Simulate full heap to see if we will reenter this callback
-  SimulateFullSpace(CcTest::heap()->new_space());
+  i::heap::SimulateFullSpace(CcTest::heap()->new_space());
 
   Local<Object> obj = Object::New(isolate);
   CHECK(!obj.IsEmpty());
@@ -18936,7 +19100,7 @@
   ++epilogue_call_count_alloc;
 
   // Simulate full heap to see if we will reenter this callback
-  SimulateFullSpace(CcTest::heap()->new_space());
+  i::heap::SimulateFullSpace(CcTest::heap()->new_space());
 
   Local<Object> obj = Object::New(isolate);
   CHECK(!obj.IsEmpty());
@@ -19912,7 +20076,6 @@
 
 
 TEST(RegExp) {
-  i::FLAG_harmony_unicode_regexps = true;
   LocalContext context;
   v8::HandleScope scope(context->GetIsolate());
 
@@ -20313,6 +20476,7 @@
         HasOwnPropertyNamedPropertyGetter));
     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
     CHECK(!instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
+    CHECK(!instance->HasOwnProperty(env.local(), 42).FromJust());
     CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
     CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
   }
@@ -20322,7 +20486,9 @@
         HasOwnPropertyIndexedPropertyGetter));
     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
     CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
+    CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
     CHECK(!instance->HasOwnProperty(env.local(), v8_str("43")).FromJust());
+    CHECK(!instance->HasOwnProperty(env.local(), 43).FromJust());
     CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
   }
   { // Check named query interceptors.
@@ -20339,7 +20505,9 @@
         0, 0, HasOwnPropertyIndexedPropertyQuery));
     Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
     CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
+    CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
     CHECK(!instance->HasOwnProperty(env.local(), v8_str("41")).FromJust());
+    CHECK(!instance->HasOwnProperty(env.local(), 41).FromJust());
   }
   { // Check callbacks.
     Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
@@ -20917,6 +21085,7 @@
 
 
 static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
+  CHECK(v8::MicrotasksScope::IsRunningMicrotasks(info.GetIsolate()));
   v8::HandleScope scope(info.GetIsolate());
   v8::MicrotasksScope microtasks(info.GetIsolate(),
                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
@@ -20925,6 +21094,7 @@
 
 
 static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
+  CHECK(v8::MicrotasksScope::IsRunningMicrotasks(info.GetIsolate()));
   v8::HandleScope scope(info.GetIsolate());
   v8::MicrotasksScope microtasks(info.GetIsolate(),
                                  v8::MicrotasksScope::kDoNotRunMicrotasks);
@@ -20943,6 +21113,7 @@
 TEST(EnqueueMicrotask) {
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
+  CHECK(!v8::MicrotasksScope::IsRunningMicrotasks(env->GetIsolate()));
   CompileRun(
       "var ext1Calls = 0;"
       "var ext2Calls = 0;");
@@ -21282,48 +21453,17 @@
   env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
 }
 
-
-static void DebugEventInObserver(const v8::Debug::EventDetails& event_details) {
-  v8::DebugEvent event = event_details.GetEvent();
-  if (event != v8::Break) return;
-  Local<Object> exec_state = event_details.GetExecutionState();
-  Local<Context> context = CcTest::isolate()->GetCurrentContext();
-  Local<Value> break_id =
-      exec_state->Get(context, v8_str("break_id")).ToLocalChecked();
-  CompileRun("function f(id) { new FrameDetails(id, 0); }");
-  Local<Function> fun = Local<Function>::Cast(
-      CcTest::global()->Get(context, v8_str("f")).ToLocalChecked());
-  fun->Call(context, CcTest::global(), 1, &break_id).ToLocalChecked();
-}
-
-
-TEST(Regress385349) {
-  i::FLAG_harmony_object_observe = true;
-  i::FLAG_allow_natives_syntax = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  HandleScope handle_scope(isolate);
-  isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
-  Local<Context> context = Context::New(isolate);
-  v8::Debug::SetDebugEventListener(isolate, DebugEventInObserver);
-  {
-    Context::Scope context_scope(context);
-    CompileRun("var obj = {};"
-               "Object.observe(obj, function(changes) { debugger; });"
-               "obj.a = 0;");
-  }
-  isolate->RunMicrotasks();
-  isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
-  v8::Debug::SetDebugEventListener(isolate, nullptr);
-}
-
-
 #ifdef ENABLE_DISASSEMBLER
-static int probes_counter = 0;
-static int misses_counter = 0;
-static int updates_counter = 0;
+// FLAG_test_primary_stub_cache and FLAG_test_secondary_stub_cache are read
+// only when ENABLE_DISASSEMBLER is not defined.
 
+namespace {
 
-static int* LookupCounter(const char* name) {
+int probes_counter = 0;
+int misses_counter = 0;
+int updates_counter = 0;
+
+int* LookupCounter(const char* name) {
   if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
     return &probes_counter;
   } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
@@ -21334,24 +21474,28 @@
   return NULL;
 }
 
+const char* kMegamorphicTestProgram =
+    "function CreateClass(name) {\n"
+    "  var src = \n"
+    "    `  function ${name}() {};` +\n"
+    "    `  ${name}.prototype.foo = function() {};` +\n"
+    "    `  ${name};\\n`;\n"
+    "  return (0, eval)(src);\n"
+    "}\n"
+    "function fooify(obj) { obj.foo(); };\n"
+    "var objs = [];\n"
+    "for (var i = 0; i < 6; i++) {\n"
+    "  var Class = CreateClass('Class' + i);\n"
+    "  var obj = new Class();\n"
+    "  objs.push(obj);\n"
+    "}\n"
+    "for (var i = 0; i < 10000; i++) {\n"
+    "  for (var obj of objs) {\n"
+    "    fooify(obj);\n"
+    "  }\n"
+    "}\n";
 
-static const char* kMegamorphicTestProgram =
-    "function ClassA() { };"
-    "function ClassB() { };"
-    "ClassA.prototype.foo = function() { };"
-    "ClassB.prototype.foo = function() { };"
-    "function fooify(obj) { obj.foo(); };"
-    "var a = new ClassA();"
-    "var b = new ClassB();"
-    "for (var i = 0; i < 10000; i++) {"
-    "  fooify(a);"
-    "  fooify(b);"
-    "}";
-#endif
-
-
-static void StubCacheHelper(bool primary) {
-#ifdef ENABLE_DISASSEMBLER
+void StubCacheHelper(bool primary) {
   i::FLAG_native_code_counters = true;
   if (primary) {
     i::FLAG_test_primary_stub_cache = true;
@@ -21359,36 +21503,47 @@
     i::FLAG_test_secondary_stub_cache = true;
   }
   i::FLAG_crankshaft = false;
-  LocalContext env;
-  env->GetIsolate()->SetCounterFunction(LookupCounter);
-  v8::HandleScope scope(env->GetIsolate());
-  int initial_probes = probes_counter;
-  int initial_misses = misses_counter;
-  int initial_updates = updates_counter;
-  CompileRun(kMegamorphicTestProgram);
-  int probes = probes_counter - initial_probes;
-  int misses = misses_counter - initial_misses;
-  int updates = updates_counter - initial_updates;
-  CHECK_LT(updates, 10);
-  CHECK_LT(misses, 10);
-  // TODO(verwaest): Update this test to overflow the degree of polymorphism
-  // before megamorphism. The number of probes will only work once we teach the
-  // serializer to embed references to counters in the stubs, given that the
-  // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
-  CHECK_GE(probes, 0);
-#endif
+  i::FLAG_turbo = false;
+  v8::Isolate::CreateParams create_params;
+  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
+  create_params.counter_lookup_callback = LookupCounter;
+  v8::Isolate* isolate = v8::Isolate::New(create_params);
+  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+
+  if (!i_isolate->snapshot_available()) {
+    // The test is valid only for no-snapshot mode.
+    v8::Isolate::Scope isolate_scope(isolate);
+    LocalContext env(isolate);
+    v8::HandleScope scope(isolate);
+
+    int initial_probes = probes_counter;
+    int initial_misses = misses_counter;
+    int initial_updates = updates_counter;
+    CompileRun(kMegamorphicTestProgram);
+    int probes = probes_counter - initial_probes;
+    int misses = misses_counter - initial_misses;
+    int updates = updates_counter - initial_updates;
+    const int kClassesCount = 6;
+    // Check that updates and misses counts are bounded.
+    CHECK_LE(kClassesCount, updates);
+    CHECK_LT(updates, kClassesCount * 3);
+    CHECK_LE(1, misses);
+    CHECK_LT(misses, kClassesCount * 2);
+    // 2 is for PREMONOMORPHIC and MONOMORPHIC states,
+    // 4 is for POLYMORPHIC states,
+    // and all the others probes are for MEGAMORPHIC state.
+    CHECK_EQ(10000 * kClassesCount - 2 - 4, probes);
+  }
+  isolate->Dispose();
 }
 
+}  // namespace
 
-TEST(SecondaryStubCache) {
-  StubCacheHelper(true);
-}
+UNINITIALIZED_TEST(PrimaryStubCache) { StubCacheHelper(true); }
 
+UNINITIALIZED_TEST(SecondaryStubCache) { StubCacheHelper(false); }
 
-TEST(PrimaryStubCache) {
-  StubCacheHelper(false);
-}
-
+#endif  // ENABLE_DISASSEMBLER
 
 #ifdef DEBUG
 static int cow_arrays_created_runtime = 0;
@@ -21960,29 +22115,53 @@
   CHECK(function->IsFunction());
 }
 
-
 THREADED_TEST(JSONParseObject) {
   LocalContext context;
   HandleScope scope(context->GetIsolate());
   Local<Value> obj =
-      v8::JSON::Parse(context->GetIsolate(), v8_str("{\"x\":42}"))
-          .ToLocalChecked();
+      v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
   Local<Object> global = context->Global();
   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   ExpectString("JSON.stringify(obj)", "{\"x\":42}");
 }
 
-
 THREADED_TEST(JSONParseNumber) {
   LocalContext context;
   HandleScope scope(context->GetIsolate());
   Local<Value> obj =
-      v8::JSON::Parse(context->GetIsolate(), v8_str("42")).ToLocalChecked();
+      v8::JSON::Parse(context.local(), v8_str("42")).ToLocalChecked();
   Local<Object> global = context->Global();
   global->Set(context.local(), v8_str("obj"), obj).FromJust();
   ExpectString("JSON.stringify(obj)", "42");
 }
 
+THREADED_TEST(JSONStringifyObject) {
+  LocalContext context;
+  HandleScope scope(context->GetIsolate());
+  Local<Value> value =
+      v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
+  Local<Object> obj = value->ToObject(context.local()).ToLocalChecked();
+  Local<Object> global = context->Global();
+  global->Set(context.local(), v8_str("obj"), obj).FromJust();
+  Local<String> json =
+      v8::JSON::Stringify(context.local(), obj).ToLocalChecked();
+  v8::String::Utf8Value utf8(json);
+  ExpectString("JSON.stringify(obj)", *utf8);
+}
+
+THREADED_TEST(JSONStringifyObjectWithGap) {
+  LocalContext context;
+  HandleScope scope(context->GetIsolate());
+  Local<Value> value =
+      v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
+  Local<Object> obj = value->ToObject(context.local()).ToLocalChecked();
+  Local<Object> global = context->Global();
+  global->Set(context.local(), v8_str("obj"), obj).FromJust();
+  Local<String> json =
+      v8::JSON::Stringify(context.local(), obj, v8_str("*")).ToLocalChecked();
+  v8::String::Utf8Value utf8(json);
+  ExpectString("JSON.stringify(obj, null,  '*')", *utf8);
+}
 
 #if V8_OS_POSIX && !V8_OS_NACL
 class ThreadInterruptTest {
@@ -23344,6 +23523,88 @@
   CHECK_EQ(13, line_number);
 }
 
+TEST(ScriptPositionInfo) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  const char* url = "http://www.foo.com/foo.js";
+  v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
+  v8::ScriptCompiler::Source script_source(v8_str("var foo;\n"
+                                                  "var bar;\n"
+                                                  "var fisk = foo + bar;\n"),
+                                           origin);
+  Local<Script> script =
+      v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
+
+  i::Handle<i::SharedFunctionInfo> obj = i::Handle<i::SharedFunctionInfo>::cast(
+      v8::Utils::OpenHandle(*script->GetUnboundScript()));
+  CHECK(obj->script()->IsScript());
+
+  i::Handle<i::Script> script1(i::Script::cast(obj->script()));
+
+  v8::internal::Script::PositionInfo info;
+
+  // With offset.
+
+  // Behave as if 0 was passed if position is negative.
+  CHECK(script1->GetPositionInfo(-1, &info, script1->WITH_OFFSET));
+  CHECK_EQ(13, info.line);
+  CHECK_EQ(0, info.column);
+  CHECK_EQ(0, info.line_start);
+  CHECK_EQ(8, info.line_end);
+
+  CHECK(script1->GetPositionInfo(0, &info, script1->WITH_OFFSET));
+  CHECK_EQ(13, info.line);
+  CHECK_EQ(0, info.column);
+  CHECK_EQ(0, info.line_start);
+  CHECK_EQ(8, info.line_end);
+
+  CHECK(script1->GetPositionInfo(8, &info, script1->WITH_OFFSET));
+  CHECK_EQ(13, info.line);
+  CHECK_EQ(8, info.column);
+  CHECK_EQ(0, info.line_start);
+  CHECK_EQ(8, info.line_end);
+
+  CHECK(script1->GetPositionInfo(9, &info, script1->WITH_OFFSET));
+  CHECK_EQ(14, info.line);
+  CHECK_EQ(0, info.column);
+  CHECK_EQ(9, info.line_start);
+  CHECK_EQ(17, info.line_end);
+
+  // Fail when position is larger than script size.
+  CHECK(!script1->GetPositionInfo(220384, &info, script1->WITH_OFFSET));
+
+  // Without offset.
+
+  // Behave as if 0 was passed if position is negative.
+  CHECK(script1->GetPositionInfo(-1, &info, script1->NO_OFFSET));
+  CHECK_EQ(0, info.line);
+  CHECK_EQ(0, info.column);
+  CHECK_EQ(0, info.line_start);
+  CHECK_EQ(8, info.line_end);
+
+  CHECK(script1->GetPositionInfo(0, &info, script1->NO_OFFSET));
+  CHECK_EQ(0, info.line);
+  CHECK_EQ(0, info.column);
+  CHECK_EQ(0, info.line_start);
+  CHECK_EQ(8, info.line_end);
+
+  CHECK(script1->GetPositionInfo(8, &info, script1->NO_OFFSET));
+  CHECK_EQ(0, info.line);
+  CHECK_EQ(8, info.column);
+  CHECK_EQ(0, info.line_start);
+  CHECK_EQ(8, info.line_end);
+
+  CHECK(script1->GetPositionInfo(9, &info, script1->NO_OFFSET));
+  CHECK_EQ(1, info.line);
+  CHECK_EQ(0, info.column);
+  CHECK_EQ(9, info.line_start);
+  CHECK_EQ(17, info.line_end);
+
+  // Fail when position is larger than script size.
+  CHECK(!script1->GetPositionInfo(220384, &info, script1->NO_OFFSET));
+}
+
 void CheckMagicComments(Local<Script> script, const char* expected_source_url,
                         const char* expected_source_mapping_url) {
   if (expected_source_url != NULL) {
@@ -24077,8 +24338,7 @@
       script->Run(context).ToLocalChecked()->Int32Value(context).FromJust());
 }
 
-
-TEST(InvalidCacheData) {
+TEST(InvalidParserCacheData) {
   v8::V8::Initialize();
   v8::HandleScope scope(CcTest::isolate());
   LocalContext context;
@@ -24086,6 +24346,12 @@
     // Cached parser data is not consumed while parsing eagerly.
     TestInvalidCacheData(v8::ScriptCompiler::kConsumeParserCache);
   }
+}
+
+TEST(InvalidCodeCacheData) {
+  v8::V8::Initialize();
+  v8::HandleScope scope(CcTest::isolate());
+  LocalContext context;
   TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
 }
 
@@ -24168,6 +24434,7 @@
 
 
 TEST(TurboAsmDisablesNeuter) {
+  i::FLAG_allow_natives_syntax = true;
   v8::V8::Initialize();
   v8::HandleScope scope(CcTest::isolate());
   LocalContext context;
@@ -24180,10 +24447,11 @@
       "  return { load: load };"
       "}"
       "var buffer = new ArrayBuffer(4);"
-      "Module(this, {}, buffer).load();"
+      "var module = Module(this, {}, buffer);"
+      "%OptimizeFunctionOnNextCall(module.load);"
+      "module.load();"
       "buffer";
 
-  i::FLAG_turbo_osr = false;  // TODO(titzer): test requires eager TF.
   v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
   CHECK_EQ(should_be_neuterable, result->IsNeuterable());
 
@@ -24195,10 +24463,11 @@
       "  return { store: store };"
       "}"
       "var buffer = new ArrayBuffer(4);"
-      "Module(this, {}, buffer).store();"
+      "var module = Module(this, {}, buffer);"
+      "%OptimizeFunctionOnNextCall(module.store);"
+      "module.store();"
       "buffer";
 
-  i::FLAG_turbo_osr = false;  // TODO(titzer): test requires eager TF.
   result = CompileRun(store).As<v8::ArrayBuffer>();
   CHECK_EQ(should_be_neuterable, result->IsNeuterable());
 }
@@ -24629,6 +24898,60 @@
   CHECK_EQ(0U, set->Size());
 }
 
+TEST(SetDeleteThenAsArray) {
+  // https://bugs.chromium.org/p/v8/issues/detail?id=4946
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  LocalContext env;
+
+  // make a Set
+  v8::Local<v8::Value> val = CompileRun("new Set([1, 2, 3])");
+  v8::Local<v8::Set> set = v8::Local<v8::Set>::Cast(val);
+  CHECK_EQ(3U, set->Size());
+
+  // delete the "middle" element (using AsArray to
+  // determine which element is the "middle" element)
+  v8::Local<v8::Array> array1 = set->AsArray();
+  CHECK_EQ(3U, array1->Length());
+  CHECK(set->Delete(env.local(), array1->Get(env.local(), 1).ToLocalChecked())
+            .FromJust());
+
+  // make sure there are no undefined values when we convert to an array again.
+  v8::Local<v8::Array> array2 = set->AsArray();
+  uint32_t length = array2->Length();
+  CHECK_EQ(2U, length);
+  for (uint32_t i = 0; i < length; i++) {
+    CHECK(!array2->Get(env.local(), i).ToLocalChecked()->IsUndefined());
+  }
+}
+
+TEST(MapDeleteThenAsArray) {
+  // https://bugs.chromium.org/p/v8/issues/detail?id=4946
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope handle_scope(isolate);
+  LocalContext env;
+
+  // make a Map
+  v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4], [5, 6]])");
+  v8::Local<v8::Map> map = v8::Local<v8::Map>::Cast(val);
+  CHECK_EQ(3U, map->Size());
+
+  // delete the "middle" element (using AsArray to
+  // determine which element is the "middle" element)
+  v8::Local<v8::Array> array1 = map->AsArray();
+  CHECK_EQ(6U, array1->Length());
+  // Map::AsArray returns a flat array, so the second key is at index 2.
+  v8::Local<v8::Value> key = array1->Get(env.local(), 2).ToLocalChecked();
+  CHECK(map->Delete(env.local(), key).FromJust());
+
+  // make sure there are no undefined values when we convert to an array again.
+  v8::Local<v8::Array> array2 = map->AsArray();
+  uint32_t length = array2->Length();
+  CHECK_EQ(4U, length);
+  for (uint32_t i = 0; i < length; i++) {
+    CHECK(!array2->Get(env.local(), i).ToLocalChecked()->IsUndefined());
+  }
+}
 
 TEST(CompatibleReceiverCheckOnCachedICHandler) {
   v8::Isolate* isolate = CcTest::isolate();
diff --git a/test/cctest/test-api.h b/test/cctest/test-api.h
index 8887a8a..f9a335a 100644
--- a/test/cctest/test-api.h
+++ b/test/cctest/test-api.h
@@ -5,7 +5,6 @@
 #include "src/v8.h"
 
 #include "src/isolate.h"
-#include "src/profiler/cpu-profiler.h"
 #include "src/vm-state.h"
 #include "test/cctest/cctest.h"
 
@@ -14,10 +13,11 @@
   v8::ReturnValue<v8::Value> rv = t.GetReturnValue();
   i::Object** o = *reinterpret_cast<i::Object***>(&rv);
   CHECK_EQ(CcTest::isolate(), t.GetIsolate());
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(t.GetIsolate());
   CHECK_EQ(t.GetIsolate(), rv.GetIsolate());
-  CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
+  CHECK((*o)->IsTheHole(isolate) || (*o)->IsUndefined(isolate));
   // Verify reset
-  bool is_runtime = (*o)->IsTheHole();
+  bool is_runtime = (*o)->IsTheHole(isolate);
   if (is_runtime) {
     CHECK(rv.Get()->IsUndefined());
   } else {
@@ -25,14 +25,13 @@
     CHECK_EQ(*v, *o);
   }
   rv.Set(true);
-  CHECK(!(*o)->IsTheHole() && !(*o)->IsUndefined());
+  CHECK(!(*o)->IsTheHole(isolate) && !(*o)->IsUndefined(isolate));
   rv.Set(v8::Local<v8::Object>());
-  CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
-  CHECK_EQ(is_runtime, (*o)->IsTheHole());
-  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(t.GetIsolate());
+  CHECK((*o)->IsTheHole(isolate) || (*o)->IsUndefined(isolate));
+  CHECK_EQ(is_runtime, (*o)->IsTheHole(isolate));
   // If CPU profiler is active check that when API callback is invoked
   // VMState is set to EXTERNAL.
-  if (isolate->cpu_profiler()->is_profiling()) {
+  if (isolate->is_profiling()) {
     CHECK_EQ(v8::EXTERNAL, isolate->current_vm_state());
     CHECK(isolate->external_callback_scope());
     CHECK_EQ(callback, isolate->external_callback_scope()->callback());
diff --git a/test/cctest/test-asm-validator.cc b/test/cctest/test-asm-validator.cc
index d5b5179..39d490e 100644
--- a/test/cctest/test-asm-validator.cc
+++ b/test/cctest/test-asm-validator.cc
@@ -61,7 +61,6 @@
 
   i::ParseInfo info(zone, script);
   i::Parser parser(&info);
-  parser.set_allow_harmony_sloppy(true);
   info.set_global();
   info.set_lazy(false);
   info.set_allow_lazy_parsing(false);
@@ -73,7 +72,7 @@
       info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun();
   AsmTyper typer(isolate, zone, *script, root);
   if (typer.Validate()) {
-    ExpressionTypeCollector(isolate, root, types).Run();
+    ExpressionTypeCollector(isolate, root, typer.bounds(), types).Run();
     return "";
   } else {
     return typer.error_message();
@@ -1362,6 +1361,12 @@
       "asm: line 1: left and right side of comparison must match\n");
 }
 
+TEST(FunctionRepeated) {
+  CHECK_FUNC_ERROR(
+      "function foo() { return 0; }\n"
+      "function foo() { return 0; }",
+      "asm: line 2: function repeated in module\n");
+}
 
 TEST(Float64ToInt32) {
   CHECK_FUNC_TYPES_BEGIN(
@@ -1801,14 +1806,10 @@
 
 
 TEST(InstanceOf) {
-  const char* errorMsg = FLAG_harmony_instanceof
-                             ? "asm: line 0: do-expression encountered\n"
-                             : "asm: line 1: illegal comparison operator\n";
-
   CHECK_FUNC_ERROR(
       "function bar() { return (0 instanceof 0)|0; }\n"
       "function foo() { bar(); }",
-      errorMsg);
+      "asm: line 1: illegal comparison operator\n");
 }
 
 
diff --git a/test/cctest/test-assembler-arm.cc b/test/cctest/test-assembler-arm.cc
index 3763f06..cf404b0 100644
--- a/test/cctest/test-assembler-arm.cc
+++ b/test/cctest/test-assembler-arm.cc
@@ -412,29 +412,26 @@
 
   Assembler assm(isolate, NULL, 0);
 
-  if (CpuFeatures::IsSupported(ARMv7)) {
-    CpuFeatureScope scope(&assm, ARMv7);
-    __ usat(r1, 8, Operand(r0));           // Sat 0xFFFF to 0-255 = 0xFF.
-    __ usat(r2, 12, Operand(r0, ASR, 9));  // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
-    __ usat(r3, 1, Operand(r0, LSL, 16));  // Sat (0xFFFF<<16) to 0-1 = 0x0.
-    __ add(r0, r1, Operand(r2));
-    __ add(r0, r0, Operand(r3));
-    __ mov(pc, Operand(lr));
+  __ usat(r1, 8, Operand(r0));           // Sat 0xFFFF to 0-255 = 0xFF.
+  __ usat(r2, 12, Operand(r0, ASR, 9));  // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
+  __ usat(r3, 1, Operand(r0, LSL, 16));  // Sat (0xFFFF<<16) to 0-1 = 0x0.
+  __ add(r0, r1, Operand(r2));
+  __ add(r0, r0, Operand(r3));
+  __ mov(pc, Operand(lr));
 
-    CodeDesc desc;
-    assm.GetCode(&desc);
-    Handle<Code> code = isolate->factory()->NewCode(
-        desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Handle<Code> code = isolate->factory()->NewCode(
+      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
 #ifdef DEBUG
-    OFStream os(stdout);
-    code->Print(os);
+  OFStream os(stdout);
+  code->Print(os);
 #endif
-    F1 f = FUNCTION_CAST<F1>(code->entry());
-    int res = reinterpret_cast<int>(
-        CALL_GENERATED_CODE(isolate, f, 0xFFFF, 0, 0, 0, 0));
-    ::printf("f() = %d\n", res);
-    CHECK_EQ(382, res);
-  }
+  F1 f = FUNCTION_CAST<F1>(code->entry());
+  int res = reinterpret_cast<int>(
+      CALL_GENERATED_CODE(isolate, f, 0xFFFF, 0, 0, 0, 0));
+  ::printf("f() = %d\n", res);
+  CHECK_EQ(382, res);
 }
 
 
@@ -2231,6 +2228,158 @@
   }
 }
 
+TEST(ARMv8_vsel) {
+  // Test the vsel floating point instructions.
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  HandleScope scope(isolate);
+
+  Assembler assm(isolate, NULL, 0);
+
+  // Used to indicate whether a condition passed or failed.
+  static constexpr float kResultPass = 1.0f;
+  static constexpr float kResultFail = -kResultPass;
+
+  struct ResultsF32 {
+    float vseleq_;
+    float vselge_;
+    float vselgt_;
+    float vselvs_;
+
+    // The following conditions aren't architecturally supported, but the
+    // assembler implements them by swapping the inputs.
+    float vselne_;
+    float vsellt_;
+    float vselle_;
+    float vselvc_;
+  };
+
+  struct ResultsF64 {
+    double vseleq_;
+    double vselge_;
+    double vselgt_;
+    double vselvs_;
+
+    // The following conditions aren't architecturally supported, but the
+    // assembler implements them by swapping the inputs.
+    double vselne_;
+    double vsellt_;
+    double vselle_;
+    double vselvc_;
+  };
+
+  if (CpuFeatures::IsSupported(ARMv8)) {
+    CpuFeatureScope scope(&assm, ARMv8);
+
+    // Create a helper function:
+    //  void TestVsel(uint32_t nzcv,
+    //                ResultsF32* results_f32,
+    //                ResultsF64* results_f64);
+    __ msr(CPSR_f, Operand(r0));
+
+    __ vmov(s1, kResultPass);
+    __ vmov(s2, kResultFail);
+
+    __ vsel(eq, s0, s1, s2);
+    __ vstr(s0, r1, offsetof(ResultsF32, vseleq_));
+    __ vsel(ge, s0, s1, s2);
+    __ vstr(s0, r1, offsetof(ResultsF32, vselge_));
+    __ vsel(gt, s0, s1, s2);
+    __ vstr(s0, r1, offsetof(ResultsF32, vselgt_));
+    __ vsel(vs, s0, s1, s2);
+    __ vstr(s0, r1, offsetof(ResultsF32, vselvs_));
+
+    __ vsel(ne, s0, s1, s2);
+    __ vstr(s0, r1, offsetof(ResultsF32, vselne_));
+    __ vsel(lt, s0, s1, s2);
+    __ vstr(s0, r1, offsetof(ResultsF32, vsellt_));
+    __ vsel(le, s0, s1, s2);
+    __ vstr(s0, r1, offsetof(ResultsF32, vselle_));
+    __ vsel(vc, s0, s1, s2);
+    __ vstr(s0, r1, offsetof(ResultsF32, vselvc_));
+
+    __ vmov(d1, kResultPass);
+    __ vmov(d2, kResultFail);
+
+    __ vsel(eq, d0, d1, d2);
+    __ vstr(d0, r2, offsetof(ResultsF64, vseleq_));
+    __ vsel(ge, d0, d1, d2);
+    __ vstr(d0, r2, offsetof(ResultsF64, vselge_));
+    __ vsel(gt, d0, d1, d2);
+    __ vstr(d0, r2, offsetof(ResultsF64, vselgt_));
+    __ vsel(vs, d0, d1, d2);
+    __ vstr(d0, r2, offsetof(ResultsF64, vselvs_));
+
+    __ vsel(ne, d0, d1, d2);
+    __ vstr(d0, r2, offsetof(ResultsF64, vselne_));
+    __ vsel(lt, d0, d1, d2);
+    __ vstr(d0, r2, offsetof(ResultsF64, vsellt_));
+    __ vsel(le, d0, d1, d2);
+    __ vstr(d0, r2, offsetof(ResultsF64, vselle_));
+    __ vsel(vc, d0, d1, d2);
+    __ vstr(d0, r2, offsetof(ResultsF64, vselvc_));
+
+    __ bx(lr);
+
+    CodeDesc desc;
+    assm.GetCode(&desc);
+    Handle<Code> code = isolate->factory()->NewCode(
+        desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+#ifdef DEBUG
+    OFStream os(stdout);
+    code->Print(os);
+#endif
+    F5 f = FUNCTION_CAST<F5>(code->entry());
+    Object* dummy = nullptr;
+    USE(dummy);
+
+    STATIC_ASSERT(kResultPass == -kResultFail);
+#define CHECK_VSEL(n, z, c, v, vseleq, vselge, vselgt, vselvs)                \
+  do {                                                                        \
+    ResultsF32 results_f32;                                                   \
+    ResultsF64 results_f64;                                                   \
+    uint32_t nzcv = (n << 31) | (z << 30) | (c << 29) | (v << 28);            \
+    dummy = CALL_GENERATED_CODE(isolate, f, nzcv, &results_f32, &results_f64, \
+                                0, 0);                                        \
+    CHECK_EQ(vseleq, results_f32.vseleq_);                                    \
+    CHECK_EQ(vselge, results_f32.vselge_);                                    \
+    CHECK_EQ(vselgt, results_f32.vselgt_);                                    \
+    CHECK_EQ(vselvs, results_f32.vselvs_);                                    \
+    CHECK_EQ(-vseleq, results_f32.vselne_);                                   \
+    CHECK_EQ(-vselge, results_f32.vsellt_);                                   \
+    CHECK_EQ(-vselgt, results_f32.vselle_);                                   \
+    CHECK_EQ(-vselvs, results_f32.vselvc_);                                   \
+    CHECK_EQ(vseleq, results_f64.vseleq_);                                    \
+    CHECK_EQ(vselge, results_f64.vselge_);                                    \
+    CHECK_EQ(vselgt, results_f64.vselgt_);                                    \
+    CHECK_EQ(vselvs, results_f64.vselvs_);                                    \
+    CHECK_EQ(-vseleq, results_f64.vselne_);                                   \
+    CHECK_EQ(-vselge, results_f64.vsellt_);                                   \
+    CHECK_EQ(-vselgt, results_f64.vselle_);                                   \
+    CHECK_EQ(-vselvs, results_f64.vselvc_);                                   \
+  } while (0);
+
+    //         N  Z  C  V  vseleq       vselge       vselgt       vselvs
+    CHECK_VSEL(0, 0, 0, 0, kResultFail, kResultPass, kResultPass, kResultFail);
+    CHECK_VSEL(0, 0, 0, 1, kResultFail, kResultFail, kResultFail, kResultPass);
+    CHECK_VSEL(0, 0, 1, 0, kResultFail, kResultPass, kResultPass, kResultFail);
+    CHECK_VSEL(0, 0, 1, 1, kResultFail, kResultFail, kResultFail, kResultPass);
+    CHECK_VSEL(0, 1, 0, 0, kResultPass, kResultPass, kResultFail, kResultFail);
+    CHECK_VSEL(0, 1, 0, 1, kResultPass, kResultFail, kResultFail, kResultPass);
+    CHECK_VSEL(0, 1, 1, 0, kResultPass, kResultPass, kResultFail, kResultFail);
+    CHECK_VSEL(0, 1, 1, 1, kResultPass, kResultFail, kResultFail, kResultPass);
+    CHECK_VSEL(1, 0, 0, 0, kResultFail, kResultFail, kResultFail, kResultFail);
+    CHECK_VSEL(1, 0, 0, 1, kResultFail, kResultPass, kResultPass, kResultPass);
+    CHECK_VSEL(1, 0, 1, 0, kResultFail, kResultFail, kResultFail, kResultFail);
+    CHECK_VSEL(1, 0, 1, 1, kResultFail, kResultPass, kResultPass, kResultPass);
+    CHECK_VSEL(1, 1, 0, 0, kResultPass, kResultFail, kResultFail, kResultFail);
+    CHECK_VSEL(1, 1, 0, 1, kResultPass, kResultPass, kResultFail, kResultPass);
+    CHECK_VSEL(1, 1, 1, 0, kResultPass, kResultFail, kResultFail, kResultFail);
+    CHECK_VSEL(1, 1, 1, 1, kResultPass, kResultPass, kResultFail, kResultPass);
+
+#undef CHECK_VSEL
+  }
+}
 
 TEST(regress4292_b) {
   CcTest::InitializeVM();
diff --git a/test/cctest/test-assembler-ia32.cc b/test/cctest/test-assembler-ia32.cc
index 12733c2..e4cac56 100644
--- a/test/cctest/test-assembler-ia32.cc
+++ b/test/cctest/test-assembler-ia32.cc
@@ -1497,4 +1497,45 @@
   }
 }
 
+TEST(Regress621926) {
+  // Bug description:
+  // The opcodes for cmpw r/m16, r16 and cmpw r16, r/m16 were swapped.
+  // This was causing non-commutative comparisons to produce the wrong result.
+  CcTest::InitializeVM();
+  Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
+  HandleScope scope(isolate);
+  Assembler assm(isolate, nullptr, 0);
+
+  uint16_t a = 42;
+
+  Label fail;
+  __ push(ebx);
+  __ mov(ebx, Immediate(reinterpret_cast<intptr_t>(&a)));
+  __ mov(eax, Immediate(41));
+  __ cmpw(eax, Operand(ebx, 0));
+  __ j(above_equal, &fail);
+  __ cmpw(Operand(ebx, 0), eax);
+  __ j(below_equal, &fail);
+  __ mov(eax, 1);
+  __ pop(ebx);
+  __ ret(0);
+  __ bind(&fail);
+  __ mov(eax, 0);
+  __ pop(ebx);
+  __ ret(0);
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Handle<Code> code = isolate->factory()->NewCode(
+      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+
+#ifdef OBJECT_PRINT
+  OFStream os(stdout);
+  code->Print(os);
+#endif
+
+  F0 f = FUNCTION_CAST<F0>(code->entry());
+  CHECK_EQ(f(), 1);
+}
+
 #undef __
diff --git a/test/cctest/test-assembler-mips.cc b/test/cctest/test-assembler-mips.cc
index b8a0426..e73b40e 100644
--- a/test/cctest/test-assembler-mips.cc
+++ b/test/cctest/test-assembler-mips.cc
@@ -2048,7 +2048,7 @@
                         v8::internal::CodeObjectRequired::kYes);
 
     typedef struct test_float {
-      int64_t rt;
+      int32_t rt;
       double a;
       double b;
       double bold;
@@ -3191,6 +3191,8 @@
   __ jr(ra);
   __ nop();
 
+  CHECK_EQ(assm.UnboundLabelsCount(), 0);
+
   CodeDesc desc;
   assm.GetCode(&desc);
   Handle<Code> code = isolate->factory()->NewCode(
diff --git a/test/cctest/test-assembler-mips64.cc b/test/cctest/test-assembler-mips64.cc
index dd6ed6b..9529dab 100644
--- a/test/cctest/test-assembler-mips64.cc
+++ b/test/cctest/test-assembler-mips64.cc
@@ -1385,16 +1385,22 @@
   Isolate* isolate = CcTest::i_isolate();
   HandleScope scope(isolate);
 
-  typedef struct {
+  struct T {
     int64_t r1;
     int64_t r2;
     int64_t r3;
     int64_t r4;
     int64_t r5;
     int64_t r6;
+    int64_t r7;
+    int64_t r8;
+    int64_t r9;
+    int64_t r10;
+    int64_t r11;
+    int64_t r12;
     uint32_t ui;
     int32_t si;
-  } T;
+  };
   T t;
 
   Assembler assm(isolate, NULL, 0);
@@ -1423,26 +1429,25 @@
 
   // lh with positive data.
   __ lh(a5, MemOperand(a0, offsetof(T, ui)));
-  __ sw(a5, MemOperand(a0, offsetof(T, r2)));
+  __ sw(a5, MemOperand(a0, offsetof(T, r7)));
 
   // lh with negative data.
   __ lh(a6, MemOperand(a0, offsetof(T, si)));
-  __ sw(a6, MemOperand(a0, offsetof(T, r3)));
+  __ sw(a6, MemOperand(a0, offsetof(T, r8)));
 
   // lhu with negative data.
   __ lhu(a7, MemOperand(a0, offsetof(T, si)));
-  __ sw(a7, MemOperand(a0, offsetof(T, r4)));
+  __ sw(a7, MemOperand(a0, offsetof(T, r9)));
 
   // lb with negative data.
   __ lb(t0, MemOperand(a0, offsetof(T, si)));
-  __ sw(t0, MemOperand(a0, offsetof(T, r5)));
+  __ sw(t0, MemOperand(a0, offsetof(T, r10)));
 
-  // // sh writes only 1/2 of word.
-  __ lui(t1, 0x3333);
-  __ ori(t1, t1, 0x3333);
-  __ sw(t1, MemOperand(a0, offsetof(T, r6)));
-  __ lhu(t1, MemOperand(a0, offsetof(T, si)));
-  __ sh(t1, MemOperand(a0, offsetof(T, r6)));
+  // sh writes only 1/2 of word.
+  __ lw(a4, MemOperand(a0, offsetof(T, ui)));
+  __ sh(a4, MemOperand(a0, offsetof(T, r11)));
+  __ lw(a4, MemOperand(a0, offsetof(T, si)));
+  __ sh(a4, MemOperand(a0, offsetof(T, r12)));
 
   __ jr(ra);
   __ nop();
@@ -1454,26 +1459,75 @@
   F3 f = FUNCTION_CAST<F3>(code->entry());
   t.ui = 0x44332211;
   t.si = 0x99aabbcc;
-  t.r1 = 0x1111111111111111;
-  t.r2 = 0x2222222222222222;
-  t.r3 = 0x3333333333333333;
-  t.r4 = 0x4444444444444444;
+  t.r1 = 0x5555555555555555;
+  t.r2 = 0x5555555555555555;
+  t.r3 = 0x5555555555555555;
+  t.r4 = 0x5555555555555555;
   t.r5 = 0x5555555555555555;
-  t.r6 = 0x6666666666666666;
+  t.r6 = 0x5555555555555555;
+  t.r7 = 0x5555555555555555;
+  t.r8 = 0x5555555555555555;
+  t.r9 = 0x5555555555555555;
+  t.r10 = 0x5555555555555555;
+  t.r11 = 0x5555555555555555;
+  t.r12 = 0x5555555555555555;
+
   Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
   USE(dummy);
 
-  // Unsigned data, 32 & 64.
-  CHECK_EQ(static_cast<int64_t>(0x1111111144332211L), t.r1);
-  CHECK_EQ(static_cast<int64_t>(0x0000000000002211L), t.r2);
+  if (kArchEndian == kLittle) {
+    // Unsigned data, 32 & 64
+    CHECK_EQ(static_cast<int64_t>(0x5555555544332211L), t.r1);  // lw, sw.
+    CHECK_EQ(static_cast<int64_t>(0x0000000044332211L), t.r2);  // sd.
 
-  // Signed data, 32 & 64.
-  CHECK_EQ(static_cast<int64_t>(0x33333333ffffbbccL), t.r3);
-  CHECK_EQ(static_cast<int64_t>(0xffffffff0000bbccL), t.r4);
+    // Signed data, 32 & 64.
+    CHECK_EQ(static_cast<int64_t>(0x5555555599aabbccL), t.r3);  // lw, sw.
+    CHECK_EQ(static_cast<int64_t>(0xffffffff99aabbccL), t.r4);  // sd.
 
-  // Signed data, 32 & 64.
-  CHECK_EQ(static_cast<int64_t>(0x55555555ffffffccL), t.r5);
-  CHECK_EQ(static_cast<int64_t>(0x000000003333bbccL), t.r6);
+    // Signed data, 32 & 64.
+    CHECK_EQ(static_cast<int64_t>(0x5555555599aabbccL), t.r5);  // lwu, sw.
+    CHECK_EQ(static_cast<int64_t>(0x0000000099aabbccL), t.r6);  // sd.
+
+    // lh with unsigned and signed data.
+    CHECK_EQ(static_cast<int64_t>(0x5555555500002211L), t.r7);  // lh, sw.
+    CHECK_EQ(static_cast<int64_t>(0x55555555ffffbbccL), t.r8);  // lh, sw.
+
+    // lhu with signed data.
+    CHECK_EQ(static_cast<int64_t>(0x555555550000bbccL), t.r9);  // lhu, sw.
+
+    // lb with signed data.
+    CHECK_EQ(static_cast<int64_t>(0x55555555ffffffccL), t.r10);  // lb, sw.
+
+    // sh with unsigned and signed data.
+    CHECK_EQ(static_cast<int64_t>(0x5555555555552211L), t.r11);  // lw, sh.
+    CHECK_EQ(static_cast<int64_t>(0x555555555555bbccL), t.r12);  // lw, sh.
+  } else {
+    // Unsigned data, 32 & 64
+    CHECK_EQ(static_cast<int64_t>(0x4433221155555555L), t.r1);  // lw, sw.
+    CHECK_EQ(static_cast<int64_t>(0x0000000044332211L), t.r2);  // sd.
+
+    // Signed data, 32 & 64.
+    CHECK_EQ(static_cast<int64_t>(0x99aabbcc55555555L), t.r3);  // lw, sw.
+    CHECK_EQ(static_cast<int64_t>(0xffffffff99aabbccL), t.r4);  // sd.
+
+    // Signed data, 32 & 64.
+    CHECK_EQ(static_cast<int64_t>(0x99aabbcc55555555L), t.r5);  // lwu, sw.
+    CHECK_EQ(static_cast<int64_t>(0x0000000099aabbccL), t.r6);  // sd.
+
+    // lh with unsigned and signed data.
+    CHECK_EQ(static_cast<int64_t>(0x0000443355555555L), t.r7);  // lh, sw.
+    CHECK_EQ(static_cast<int64_t>(0xffff99aa55555555L), t.r8);  // lh, sw.
+
+    // lhu with signed data.
+    CHECK_EQ(static_cast<int64_t>(0x000099aa55555555L), t.r9);  // lhu, sw.
+
+    // lb with signed data.
+    CHECK_EQ(static_cast<int64_t>(0xffffff9955555555L), t.r10);  // lb, sw.
+
+    // sh with unsigned and signed data.
+    CHECK_EQ(static_cast<int64_t>(0x2211555555555555L), t.r11);  // lw, sh.
+    CHECK_EQ(static_cast<int64_t>(0xbbcc555555555555L), t.r12);  // lw, sh.
+  }
 }
 
 
@@ -2162,7 +2216,7 @@
 
     __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
     __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, c)) );
-    __ lw(t0, MemOperand(a0, offsetof(TestFloat, rt)) );
+    __ ld(t0, MemOperand(a0, offsetof(TestFloat, rt)));
     __ Move(f12, 0.0);
     __ Move(f10, 0.0);
     __ Move(f16, 0.0);
@@ -3261,6 +3315,8 @@
   __ jr(ra);
   __ nop();
 
+  CHECK_EQ(assm.UnboundLabelsCount(), 0);
+
   CodeDesc desc;
   assm.GetCode(&desc);
   Handle<Code> code = isolate->factory()->NewCode(
@@ -5559,15 +5615,22 @@
       uint64_t  expected_res;
     };
 
-    struct TestCaseLdpc tc[] = {
-      // offset,         expected_res
-      { -131072,         0x250ffffe250fffff },
-      {      -4,         0x250c0006250c0007 },
-      {      -1,         0x250c0000250c0001 },
-      {       0,         0x03001025ef180000 },
-      {       1,         0x2508000125080000 },
-      {       4,         0x2508000725080006 },
-      {  131071,         0x250bfffd250bfffc },
+    auto doubleword = [](uint32_t word2, uint32_t word1) {
+      if (kArchEndian == kLittle)
+        return (static_cast<uint64_t>(word2) << 32) + word1;
+      else
+        return (static_cast<uint64_t>(word1) << 32) + word2;
+    };
+
+    TestCaseLdpc tc[] = {
+        // offset,  expected_res
+        {-131072, doubleword(0x250ffffe, 0x250fffff)},
+        {-4, doubleword(0x250c0006, 0x250c0007)},
+        {-1, doubleword(0x250c0000, 0x250c0001)},
+        {0, doubleword(0x03001025, 0xef180000)},
+        {1, doubleword(0x25080001, 0x25080000)},
+        {4, doubleword(0x25080007, 0x25080006)},
+        {131071, doubleword(0x250bfffd, 0x250bfffc)},
     };
 
     size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLdpc);
diff --git a/test/cctest/test-assembler-s390.cc b/test/cctest/test-assembler-s390.cc
index dee8e07..ab6796b 100644
--- a/test/cctest/test-assembler-s390.cc
+++ b/test/cctest/test-assembler-s390.cc
@@ -202,7 +202,7 @@
   __ sll(r13, Operand(10));
 
   v8::internal::byte* bufPos = assm.buffer_pos();
-  ::printf("buffer position = %p", bufPos);
+  ::printf("buffer position = %p", static_cast<void*>(bufPos));
   ::fflush(stdout);
   // OS::DebugBreak();
 
diff --git a/test/cctest/test-assembler-x64.cc b/test/cctest/test-assembler-x64.cc
index 66199fb..00d3609 100644
--- a/test/cctest/test-assembler-x64.cc
+++ b/test/cctest/test-assembler-x64.cc
@@ -328,6 +328,32 @@
   CHECK_EQ(1u, result);
 }
 
+TEST(AssemblerX64TestwOperations) {
+  typedef uint16_t (*F)(uint16_t * x);
+  CcTest::InitializeVM();
+  // Allocate an executable page of memory.
+  size_t actual_size;
+  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
+      Assembler::kMinimalBufferSize, &actual_size, true));
+  CHECK(buffer);
+  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
+
+  // Set rax with the ZF flag of the testl instruction.
+  Label done;
+  __ movq(rax, Immediate(1));
+  __ testw(Operand(arg1, 0), Immediate(0xf0f0));
+  __ j(not_zero, &done, Label::kNear);
+  __ movq(rax, Immediate(0));
+  __ bind(&done);
+  __ ret(0);
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  // Call the function from C++.
+  uint16_t operand = 0x8000;
+  uint16_t result = FUNCTION_CAST<F>(buffer)(&operand);
+  CHECK_EQ(1u, result);
+}
 
 TEST(AssemblerX64XorlOperations) {
   CcTest::InitializeVM();
@@ -2270,4 +2296,24 @@
   }
 }
 
+TEST(AssemblerX64PslldWithXmm15) {
+  CcTest::InitializeVM();
+  // Allocate an executable page of memory.
+  size_t actual_size;
+  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
+      Assembler::kMinimalBufferSize, &actual_size, true));
+  CHECK(buffer);
+  Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size));
+
+  __ movq(xmm15, arg1);
+  __ pslld(xmm15, 1);
+  __ movq(rax, xmm15);
+  __ ret(0);
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  uint64_t result = FUNCTION_CAST<F5>(buffer)(V8_UINT64_C(0x1122334455667788));
+  CHECK_EQ(V8_UINT64_C(0x22446688aaccef10), result);
+}
+
 #undef __
diff --git a/test/cctest/test-ast-expression-visitor.cc b/test/cctest/test-ast-expression-visitor.cc
index bda1fba..5df8253 100644
--- a/test/cctest/test-ast-expression-visitor.cc
+++ b/test/cctest/test-ast-expression-visitor.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include <stdlib.h>
+#include <map>
 
 #include "src/v8.h"
 
@@ -19,39 +20,25 @@
 
 namespace {
 
-static void CollectTypes(HandleAndZoneScope* handles, const char* source,
-                         ZoneVector<ExpressionTypeEntry>* dst) {
-  i::Isolate* isolate = CcTest::i_isolate();
-  i::Factory* factory = isolate->factory();
+class NodeTypeCounter : public AstExpressionVisitor {
+ public:
+  typedef std::map<AstNode::NodeType, int> Counters;
 
-  i::Handle<i::String> source_code =
-      factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked();
+  NodeTypeCounter(Isolate* isolate, Expression* expr, Counters* counts)
+      : AstExpressionVisitor(isolate, expr), counts_(counts) {}
 
-  i::Handle<i::Script> script = factory->NewScript(source_code);
+ protected:
+  void VisitExpression(Expression* expr) override {
+    (*counts_)[expr->node_type()]++;
+  }
 
-  i::ParseInfo info(handles->main_zone(), script);
-  i::Parser parser(&info);
-  parser.set_allow_harmony_sloppy(true);
-  info.set_global();
-  info.set_lazy(false);
-  info.set_allow_lazy_parsing(false);
-  info.set_toplevel(true);
-
-  CHECK(i::Compiler::ParseAndAnalyze(&info));
-
-  ExpressionTypeCollector(
-      isolate,
-      info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun(), dst)
-      .Run();
-}
+ private:
+  Counters* counts_;
+};
 
 }  // namespace
 
-
-TEST(VisitExpressions) {
-  v8::V8::Initialize();
-  HandleAndZoneScope handles;
-  ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
+TEST(VisitExpression) {
   const char test_function[] =
       "function GeometricMean(stdlib, foreign, buffer) {\n"
       "  \"use asm\";\n"
@@ -85,339 +72,31 @@
       "  return { geometricMean: geometricMean };\n"
       "}\n";
 
-  CollectTypes(&handles, test_function, &types);
-  CHECK_TYPES_BEGIN {
-    // function logSum
-    CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
-      CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
-        CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-          CHECK_VAR(start, Bounds::Unbounded());
-          CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-            CHECK_VAR(start, Bounds::Unbounded());
-            CHECK_EXPR(Literal, Bounds::Unbounded());
-          }
-        }
-        CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-          CHECK_VAR(end, Bounds::Unbounded());
-          CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-            CHECK_VAR(end, Bounds::Unbounded());
-            CHECK_EXPR(Literal, Bounds::Unbounded());
-          }
-        }
-        CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-          CHECK_VAR(sum, Bounds::Unbounded());
-          CHECK_EXPR(Literal, Bounds::Unbounded());
-        }
-        CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-          CHECK_VAR(p, Bounds::Unbounded());
-          CHECK_EXPR(Literal, Bounds::Unbounded());
-        }
-        CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-          CHECK_VAR(q, Bounds::Unbounded());
-          CHECK_EXPR(Literal, Bounds::Unbounded());
-        }
-        // for (p = start << 3, q = end << 3;
-        CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-          CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-            CHECK_VAR(p, Bounds::Unbounded());
-            CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-              CHECK_VAR(start, Bounds::Unbounded());
-              CHECK_EXPR(Literal, Bounds::Unbounded());
-            }
-          }
-          CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-            CHECK_VAR(q, Bounds::Unbounded());
-            CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-              CHECK_VAR(end, Bounds::Unbounded());
-              CHECK_EXPR(Literal, Bounds::Unbounded());
-            }
-          }
-        }
-        // (p|0) < (q|0);
-        CHECK_EXPR(CompareOperation, Bounds::Unbounded()) {
-          CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-            CHECK_VAR(p, Bounds::Unbounded());
-            CHECK_EXPR(Literal, Bounds::Unbounded());
-          }
-          CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-            CHECK_VAR(q, Bounds::Unbounded());
-            CHECK_EXPR(Literal, Bounds::Unbounded());
-          }
-        }
-        // p = (p + 8)|0) {\n"
-        CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-          CHECK_VAR(p, Bounds::Unbounded());
-          CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-            CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-              CHECK_VAR(p, Bounds::Unbounded());
-              CHECK_EXPR(Literal, Bounds::Unbounded());
-            }
-            CHECK_EXPR(Literal, Bounds::Unbounded());
-          }
-        }
-        // sum = sum + +log(values[p>>3]);
-        CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-          CHECK_VAR(sum, Bounds::Unbounded());
-          CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-            CHECK_VAR(sum, Bounds::Unbounded());
-            CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-              CHECK_EXPR(Call, Bounds::Unbounded()) {
-                CHECK_VAR(log, Bounds::Unbounded());
-                CHECK_EXPR(Property, Bounds::Unbounded()) {
-                  CHECK_VAR(values, Bounds::Unbounded());
-                  CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-                    CHECK_VAR(p, Bounds::Unbounded());
-                    CHECK_EXPR(Literal, Bounds::Unbounded());
-                  }
-                }
-              }
-              CHECK_EXPR(Literal, Bounds::Unbounded());
-            }
-          }
-        }
-        // return +sum;
-        CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-          CHECK_VAR(sum, Bounds::Unbounded());
-          CHECK_EXPR(Literal, Bounds::Unbounded());
-        }
-      }
-      // function geometricMean
-      CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
-        CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-          CHECK_VAR(start, Bounds::Unbounded());
-          CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-            CHECK_VAR(start, Bounds::Unbounded());
-            CHECK_EXPR(Literal, Bounds::Unbounded());
-          }
-        }
-        CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-          CHECK_VAR(end, Bounds::Unbounded());
-          CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-            CHECK_VAR(end, Bounds::Unbounded());
-            CHECK_EXPR(Literal, Bounds::Unbounded());
-          }
-        }
-        // return +exp(+logSum(start, end) / +((end - start)|0));
-        CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-          CHECK_EXPR(Call, Bounds::Unbounded()) {
-            CHECK_VAR(exp, Bounds::Unbounded());
-            CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-              CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-                CHECK_EXPR(Call, Bounds::Unbounded()) {
-                  CHECK_VAR(logSum, Bounds::Unbounded());
-                  CHECK_VAR(start, Bounds::Unbounded());
-                  CHECK_VAR(end, Bounds::Unbounded());
-                }
-                CHECK_EXPR(Literal, Bounds::Unbounded());
-              }
-              CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-                CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-                  CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-                    CHECK_VAR(end, Bounds::Unbounded());
-                    CHECK_VAR(start, Bounds::Unbounded());
-                  }
-                  CHECK_EXPR(Literal, Bounds::Unbounded());
-                }
-                CHECK_EXPR(Literal, Bounds::Unbounded());
-              }
-            }
-          }
-          CHECK_EXPR(Literal, Bounds::Unbounded());
-        }
-      }
-      // "use asm";
-      CHECK_EXPR(Literal, Bounds::Unbounded());
-      // var exp = stdlib.Math.exp;
-      CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-        CHECK_VAR(exp, Bounds::Unbounded());
-        CHECK_EXPR(Property, Bounds::Unbounded()) {
-          CHECK_EXPR(Property, Bounds::Unbounded()) {
-            CHECK_VAR(stdlib, Bounds::Unbounded());
-            CHECK_EXPR(Literal, Bounds::Unbounded());
-          }
-          CHECK_EXPR(Literal, Bounds::Unbounded());
-        }
-      }
-      // var log = stdlib.Math.log;
-      CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-        CHECK_VAR(log, Bounds::Unbounded());
-        CHECK_EXPR(Property, Bounds::Unbounded()) {
-          CHECK_EXPR(Property, Bounds::Unbounded()) {
-            CHECK_VAR(stdlib, Bounds::Unbounded());
-            CHECK_EXPR(Literal, Bounds::Unbounded());
-          }
-          CHECK_EXPR(Literal, Bounds::Unbounded());
-        }
-      }
-      // var values = new stdlib.Float64Array(buffer);
-      CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-        CHECK_VAR(values, Bounds::Unbounded());
-        CHECK_EXPR(CallNew, Bounds::Unbounded()) {
-          CHECK_EXPR(Property, Bounds::Unbounded()) {
-            CHECK_VAR(stdlib, Bounds::Unbounded());
-            CHECK_EXPR(Literal, Bounds::Unbounded());
-          }
-          CHECK_VAR(buffer, Bounds::Unbounded());
-        }
-      }
-      // return { geometricMean: geometricMean };
-      CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) {
-        CHECK_VAR(geometricMean, Bounds::Unbounded());
-      }
-    }
-  }
-  CHECK_TYPES_END
-}
-
-
-TEST(VisitConditional) {
+  // Parse + compile test_function, and extract the AST node for it.
   v8::V8::Initialize();
   HandleAndZoneScope handles;
-  ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
-  // Check that traversing the ternary operator works.
-  const char test_function[] =
-      "function foo() {\n"
-      "  var a, b, c;\n"
-      "  var x = a ? b : c;\n"
-      "}\n";
-  CollectTypes(&handles, test_function, &types);
-  CHECK_TYPES_BEGIN {
-    CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
-      CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-        CHECK_VAR(x, Bounds::Unbounded());
-        CHECK_EXPR(Conditional, Bounds::Unbounded()) {
-          CHECK_VAR(a, Bounds::Unbounded());
-          CHECK_VAR(b, Bounds::Unbounded());
-          CHECK_VAR(c, Bounds::Unbounded());
-        }
-      }
-    }
-  }
-  CHECK_TYPES_END
-}
+  i::Isolate* isolate = CcTest::i_isolate();
+  i::Handle<i::String> source_code =
+      isolate->factory()
+          ->NewStringFromUtf8(i::CStrVector(test_function))
+          .ToHandleChecked();
+  i::Handle<i::Script> script = isolate->factory()->NewScript(source_code);
+  i::ParseInfo info(handles.main_zone(), script);
+  i::Parser parser(&info);
+  info.set_global();
+  info.set_lazy(false);
+  info.set_allow_lazy_parsing(false);
+  info.set_toplevel(true);
+  CHECK(i::Compiler::ParseAndAnalyze(&info));
+  Expression* test_function_expr =
+      info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun();
 
-
-TEST(VisitEmptyForStatment) {
-  v8::V8::Initialize();
-  HandleAndZoneScope handles;
-  ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
-  // Check that traversing an empty for statement works.
-  const char test_function[] =
-      "function foo() {\n"
-      "  for (;;) {}\n"
-      "}\n";
-  CollectTypes(&handles, test_function, &types);
-  CHECK_TYPES_BEGIN {
-    CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {}
-  }
-  CHECK_TYPES_END
-}
-
-
-TEST(VisitSwitchStatment) {
-  v8::V8::Initialize();
-  HandleAndZoneScope handles;
-  ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
-  // Check that traversing a switch with a default works.
-  const char test_function[] =
-      "function foo() {\n"
-      "  switch (0) { case 1: break; default: break; }\n"
-      "}\n";
-  CollectTypes(&handles, test_function, &types);
-  CHECK_TYPES_BEGIN {
-    CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
-      CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-        CHECK_VAR(.switch_tag, Bounds::Unbounded());
-        CHECK_EXPR(Literal, Bounds::Unbounded());
-      }
-      CHECK_EXPR(Literal, Bounds::Unbounded());
-      CHECK_VAR(.switch_tag, Bounds::Unbounded());
-      CHECK_EXPR(Literal, Bounds::Unbounded());
-    }
-  }
-  CHECK_TYPES_END
-}
-
-
-TEST(VisitThrow) {
-  v8::V8::Initialize();
-  HandleAndZoneScope handles;
-  ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
-  const char test_function[] =
-      "function foo() {\n"
-      "  throw 123;\n"
-      "}\n";
-  CollectTypes(&handles, test_function, &types);
-  CHECK_TYPES_BEGIN {
-    CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
-      CHECK_EXPR(Throw, Bounds::Unbounded()) {
-        CHECK_EXPR(Literal, Bounds::Unbounded());
-      }
-    }
-  }
-  CHECK_TYPES_END
-}
-
-
-TEST(VisitYield) {
-  v8::V8::Initialize();
-  HandleAndZoneScope handles;
-  ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
-  const char test_function[] =
-      "function* foo() {\n"
-      "  yield 123;\n"
-      "}\n";
-  CollectTypes(&handles, test_function, &types);
-  CHECK_TYPES_BEGIN {
-    CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
-      // Implicit initial yield
-      CHECK_EXPR(Yield, Bounds::Unbounded()) {
-        CHECK_VAR(.generator_object, Bounds::Unbounded());
-        CHECK_EXPR(Assignment, Bounds::Unbounded()) {
-          CHECK_VAR(.generator_object, Bounds::Unbounded());
-          CHECK_EXPR(CallRuntime, Bounds::Unbounded());
-        }
-      }
-      // Explicit yield (argument wrapped with CreateIterResultObject)
-      CHECK_EXPR(Yield, Bounds::Unbounded()) {
-        CHECK_VAR(.generator_object, Bounds::Unbounded());
-        CHECK_EXPR(CallRuntime, Bounds::Unbounded()) {
-          CHECK_EXPR(Literal, Bounds::Unbounded());
-          CHECK_EXPR(Literal, Bounds::Unbounded());
-        }
-      }
-      // Argument to implicit final return
-      CHECK_EXPR(CallRuntime, Bounds::Unbounded()) {  // CreateIterResultObject
-        CHECK_EXPR(Literal, Bounds::Unbounded());
-        CHECK_EXPR(Literal, Bounds::Unbounded());
-      }
-      // Implicit finally clause
-      CHECK_EXPR(CallRuntime, Bounds::Unbounded()) {
-        CHECK_VAR(.generator_object, Bounds::Unbounded());
-      }
-    }
-  }
-  CHECK_TYPES_END
-}
-
-
-TEST(VisitSkipping) {
-  v8::V8::Initialize();
-  HandleAndZoneScope handles;
-  ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
-  const char test_function[] =
-      "function foo(x) {\n"
-      "  return (x + x) + 1;\n"
-      "}\n";
-  CollectTypes(&handles, test_function, &types);
-  CHECK_TYPES_BEGIN {
-    CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
-      CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
-        // Skip x + x
-        CHECK_SKIP();
-        CHECK_EXPR(Literal, Bounds::Unbounded());
-      }
-    }
-  }
-  CHECK_TYPES_END
+  // Run NodeTypeCounter and sanity check counts for 3 expression types,
+  // and for overall # of types found.
+  NodeTypeCounter::Counters counts;
+  NodeTypeCounter(isolate, test_function_expr, &counts).Run();
+  CHECK_EQ(21, counts[AstNode::kBinaryOperation]);
+  CHECK_EQ(26, counts[AstNode::kLiteral]);
+  CHECK_EQ(3, counts[AstNode::kFunctionLiteral]);
+  CHECK_EQ(10, counts.size());
 }
diff --git a/test/cctest/test-code-cache.cc b/test/cctest/test-code-cache.cc
new file mode 100644
index 0000000..817fa15
--- /dev/null
+++ b/test/cctest/test-code-cache.cc
@@ -0,0 +1,77 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "src/list.h"
+#include "src/objects.h"
+#include "test/cctest/cctest.h"
+
+namespace v8 {
+namespace internal {
+
+namespace {
+
+static Handle<Code> GetDummyCode(Isolate* isolate) {
+  CodeDesc desc = {nullptr,   // buffer
+                   0,         // buffer_size
+                   0,         // instr_size
+                   0,         // reloc_size
+                   0,         // constant_pool_size
+                   nullptr,   // unwinding_info
+                   0,         // unwinding_info_size
+                   nullptr};  // origin
+  Code::Flags flags =
+      Code::ComputeFlags(Code::LOAD_IC, kNoExtraICState, kCacheOnReceiver);
+  Handle<Code> self_ref;
+  return isolate->factory()->NewCode(desc, flags, self_ref);
+}
+
+}  // namespace
+
+TEST(CodeCache) {
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  Factory* factory = isolate->factory();
+  HandleScope handle_scope(isolate);
+
+  Handle<Map> map =
+      factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize, FAST_ELEMENTS);
+
+  // This number should be large enough to cause the code cache to use its
+  // hash table storage format.
+  static const int kEntries = 150;
+
+  // Prepare name/code pairs.
+  List<Handle<Name>> names(kEntries);
+  List<Handle<Code>> codes(kEntries);
+  for (int i = 0; i < kEntries; i++) {
+    names.Add(isolate->factory()->NewSymbol());
+    codes.Add(GetDummyCode(isolate));
+  }
+  Handle<Name> bad_name = isolate->factory()->NewSymbol();
+  Code::Flags bad_flags =
+      Code::ComputeFlags(Code::LOAD_IC, kNoExtraICState, kCacheOnPrototype);
+  DCHECK(bad_flags != codes[0]->flags());
+
+  // Cache name/code pairs.
+  for (int i = 0; i < kEntries; i++) {
+    Handle<Name> name = names.at(i);
+    Handle<Code> code = codes.at(i);
+    Map::UpdateCodeCache(map, name, code);
+    CHECK_EQ(*code, map->LookupInCodeCache(*name, code->flags()));
+    CHECK_NULL(map->LookupInCodeCache(*name, bad_flags));
+  }
+  CHECK_NULL(map->LookupInCodeCache(*bad_name, bad_flags));
+
+  // Check that lookup works not only right after storing.
+  for (int i = 0; i < kEntries; i++) {
+    Handle<Name> name = names.at(i);
+    Handle<Code> code = codes.at(i);
+    CHECK_EQ(*code, map->LookupInCodeCache(*name, code->flags()));
+  }
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/test/cctest/test-code-layout.cc b/test/cctest/test-code-layout.cc
new file mode 100644
index 0000000..a88c878
--- /dev/null
+++ b/test/cctest/test-code-layout.cc
@@ -0,0 +1,84 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/objects.h"
+#include "test/cctest/cctest.h"
+
+using namespace v8::internal;
+
+TEST(CodeLayoutWithoutUnwindingInfo) {
+  CcTest::InitializeVM();
+  HandleScope handle_scope(CcTest::i_isolate());
+
+  // "Hello, World!" in ASCII.
+  byte buffer_array[13] = {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20,
+                           0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21};
+
+  byte* buffer = &buffer_array[0];
+  int buffer_size = sizeof(buffer_array);
+
+  CodeDesc code_desc;
+  code_desc.buffer = buffer;
+  code_desc.buffer_size = buffer_size;
+  code_desc.constant_pool_size = 0;
+  code_desc.instr_size = buffer_size;
+  code_desc.reloc_size = 0;
+  code_desc.origin = nullptr;
+  code_desc.unwinding_info = nullptr;
+  code_desc.unwinding_info_size = 0;
+
+  Handle<Code> code = CcTest::i_isolate()->factory()->NewCode(
+      code_desc, 0, Handle<Object>::null());
+
+  CHECK(!code->has_unwinding_info());
+  CHECK_EQ(code->instruction_size(), buffer_size);
+  CHECK_EQ(memcmp(code->instruction_start(), buffer, buffer_size), 0);
+  CHECK_EQ(code->instruction_end() - reinterpret_cast<byte*>(*code),
+           Code::kHeaderSize + buffer_size - kHeapObjectTag);
+}
+
+TEST(CodeLayoutWithUnwindingInfo) {
+  CcTest::InitializeVM();
+  HandleScope handle_scope(CcTest::i_isolate());
+
+  // "Hello, World!" in ASCII.
+  byte buffer_array[13] = {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20,
+                           0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21};
+
+  // "JavaScript" in ASCII.
+  byte unwinding_info_array[10] = {0x4a, 0x61, 0x76, 0x61, 0x53,
+                                   0x63, 0x72, 0x69, 0x70, 0x74};
+
+  byte* buffer = &buffer_array[0];
+  int buffer_size = sizeof(buffer_array);
+  byte* unwinding_info = &unwinding_info_array[0];
+  int unwinding_info_size = sizeof(unwinding_info_array);
+
+  CodeDesc code_desc;
+  code_desc.buffer = buffer;
+  code_desc.buffer_size = buffer_size;
+  code_desc.constant_pool_size = 0;
+  code_desc.instr_size = buffer_size;
+  code_desc.reloc_size = 0;
+  code_desc.origin = nullptr;
+  code_desc.unwinding_info = unwinding_info;
+  code_desc.unwinding_info_size = unwinding_info_size;
+
+  Handle<Code> code = CcTest::i_isolate()->factory()->NewCode(
+      code_desc, 0, Handle<Object>::null());
+
+  CHECK(code->has_unwinding_info());
+  CHECK_EQ(code->instruction_size(), buffer_size);
+  CHECK_EQ(memcmp(code->instruction_start(), buffer, buffer_size), 0);
+  CHECK(IsAligned(code->GetUnwindingInfoSizeOffset(), 8));
+  CHECK_EQ(code->unwinding_info_size(), unwinding_info_size);
+  CHECK(
+      IsAligned(reinterpret_cast<uintptr_t>(code->unwinding_info_start()), 8));
+  CHECK_EQ(
+      memcmp(code->unwinding_info_start(), unwinding_info, unwinding_info_size),
+      0);
+  CHECK_EQ(code->unwinding_info_end() - reinterpret_cast<byte*>(*code),
+           Code::kHeaderSize + RoundUp(buffer_size, kInt64Size) + kInt64Size +
+               unwinding_info_size - kHeapObjectTag);
+}
diff --git a/test/cctest/test-code-stub-assembler.cc b/test/cctest/test-code-stub-assembler.cc
new file mode 100644
index 0000000..2d9b666
--- /dev/null
+++ b/test/cctest/test-code-stub-assembler.cc
@@ -0,0 +1,1375 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/base/utils/random-number-generator.h"
+#include "src/ic/stub-cache.h"
+#include "src/isolate.h"
+#include "test/cctest/compiler/code-assembler-tester.h"
+#include "test/cctest/compiler/function-tester.h"
+
+namespace v8 {
+namespace internal {
+
+using compiler::FunctionTester;
+using compiler::Node;
+
+typedef compiler::CodeAssemblerTesterImpl<CodeStubAssembler>
+    CodeStubAssemblerTester;
+
+TEST(FixedArrayAccessSmiIndex) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeStubAssemblerTester m(isolate, descriptor);
+  Handle<FixedArray> array = isolate->factory()->NewFixedArray(5);
+  array->set(4, Smi::FromInt(733));
+  m.Return(m.LoadFixedArrayElement(m.HeapConstant(array),
+                                   m.SmiTag(m.Int32Constant(4)), 0,
+                                   CodeStubAssembler::SMI_PARAMETERS));
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(descriptor, code);
+  MaybeHandle<Object> result = ft.Call();
+  CHECK_EQ(733, Handle<Smi>::cast(result.ToHandleChecked())->value());
+}
+
+TEST(LoadHeapNumberValue) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeStubAssemblerTester m(isolate, descriptor);
+  Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(1234);
+  m.Return(m.SmiTag(
+      m.ChangeFloat64ToUint32(m.LoadHeapNumberValue(m.HeapConstant(number)))));
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(descriptor, code);
+  MaybeHandle<Object> result = ft.Call();
+  CHECK_EQ(1234, Handle<Smi>::cast(result.ToHandleChecked())->value());
+}
+
+TEST(LoadInstanceType) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeStubAssemblerTester m(isolate, descriptor);
+  Handle<HeapObject> undefined = isolate->factory()->undefined_value();
+  m.Return(m.SmiTag(m.LoadInstanceType(m.HeapConstant(undefined))));
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(descriptor, code);
+  MaybeHandle<Object> result = ft.Call();
+  CHECK_EQ(InstanceType::ODDBALL_TYPE,
+           Handle<Smi>::cast(result.ToHandleChecked())->value());
+}
+
+TEST(BitFieldDecode) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeStubAssemblerTester m(isolate, descriptor);
+
+  class TestBitField : public BitField<unsigned, 3, 3> {};
+  m.Return(m.SmiTag(m.BitFieldDecode<TestBitField>(m.Int32Constant(0x2f))));
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(descriptor, code);
+  MaybeHandle<Object> result = ft.Call();
+  // value  = 00101111
+  // mask   = 00111000
+  // result = 101
+  CHECK_EQ(5, Handle<Smi>::cast(result.ToHandleChecked())->value());
+}
+
+TEST(JSFunction) {
+  const int kNumParams = 3;  // Receiver, left, right.
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  CodeStubAssemblerTester m(isolate, kNumParams);
+  m.Return(m.SmiFromWord32(m.Int32Add(m.SmiToWord32(m.Parameter(1)),
+                                      m.SmiToWord32(m.Parameter(2)))));
+
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(code, kNumParams);
+
+  MaybeHandle<Object> result = ft.Call(isolate->factory()->undefined_value(),
+                                       handle(Smi::FromInt(23), isolate),
+                                       handle(Smi::FromInt(34), isolate));
+  CHECK_EQ(57, Handle<Smi>::cast(result.ToHandleChecked())->value());
+}
+
+TEST(ComputeIntegerHash) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  const int kNumParams = 2;
+  CodeStubAssemblerTester m(isolate, kNumParams);
+  m.Return(m.SmiFromWord32(m.ComputeIntegerHash(
+      m.SmiToWord32(m.Parameter(0)), m.SmiToWord32(m.Parameter(1)))));
+
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(code, kNumParams);
+
+  Handle<Smi> hash_seed = isolate->factory()->hash_seed();
+
+  base::RandomNumberGenerator rand_gen(FLAG_random_seed);
+
+  for (int i = 0; i < 1024; i++) {
+    int k = rand_gen.NextInt(Smi::kMaxValue);
+
+    Handle<Smi> key(Smi::FromInt(k), isolate);
+    Handle<Object> result = ft.Call(key, hash_seed).ToHandleChecked();
+
+    uint32_t hash = ComputeIntegerHash(k, hash_seed->value());
+    Smi* expected = Smi::FromInt(hash & Smi::kMaxValue);
+    CHECK_EQ(expected, Smi::cast(*result));
+  }
+}
+
+TEST(TryToName) {
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
+  Isolate* isolate(CcTest::InitIsolateOnce());
+
+  const int kNumParams = 3;
+  CodeStubAssemblerTester m(isolate, kNumParams);
+
+  enum Result { kKeyIsIndex, kKeyIsUnique, kBailout };
+  {
+    Node* key = m.Parameter(0);
+    Node* expected_result = m.Parameter(1);
+    Node* expected_arg = m.Parameter(2);
+
+    Label passed(&m), failed(&m);
+    Label if_keyisindex(&m), if_keyisunique(&m), if_bailout(&m);
+    Variable var_index(&m, MachineRepresentation::kWord32);
+
+    m.TryToName(key, &if_keyisindex, &var_index, &if_keyisunique, &if_bailout);
+
+    m.Bind(&if_keyisindex);
+    m.GotoUnless(
+        m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kKeyIsIndex))),
+        &failed);
+    m.Branch(m.Word32Equal(m.SmiToWord32(expected_arg), var_index.value()),
+             &passed, &failed);
+
+    m.Bind(&if_keyisunique);
+    m.GotoUnless(
+        m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kKeyIsUnique))),
+        &failed);
+    m.Branch(m.WordEqual(expected_arg, key), &passed, &failed);
+
+    m.Bind(&if_bailout);
+    m.Branch(
+        m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kBailout))),
+        &passed, &failed);
+
+    m.Bind(&passed);
+    m.Return(m.BooleanConstant(true));
+
+    m.Bind(&failed);
+    m.Return(m.BooleanConstant(false));
+  }
+
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(code, kNumParams);
+
+  Handle<Object> expect_index(Smi::FromInt(kKeyIsIndex), isolate);
+  Handle<Object> expect_unique(Smi::FromInt(kKeyIsUnique), isolate);
+  Handle<Object> expect_bailout(Smi::FromInt(kBailout), isolate);
+
+  {
+    // TryToName(<zero smi>) => if_keyisindex: smi value.
+    Handle<Object> key(Smi::FromInt(0), isolate);
+    ft.CheckTrue(key, expect_index, key);
+  }
+
+  {
+    // TryToName(<positive smi>) => if_keyisindex: smi value.
+    Handle<Object> key(Smi::FromInt(153), isolate);
+    ft.CheckTrue(key, expect_index, key);
+  }
+
+  {
+    // TryToName(<negative smi>) => bailout.
+    Handle<Object> key(Smi::FromInt(-1), isolate);
+    ft.CheckTrue(key, expect_bailout);
+  }
+
+  {
+    // TryToName(<symbol>) => if_keyisunique: <symbol>.
+    Handle<Object> key = isolate->factory()->NewSymbol();
+    ft.CheckTrue(key, expect_unique, key);
+  }
+
+  {
+    // TryToName(<internalized string>) => if_keyisunique: <internalized string>
+    Handle<Object> key = isolate->factory()->InternalizeUtf8String("test");
+    ft.CheckTrue(key, expect_unique, key);
+  }
+
+  {
+    // TryToName(<internalized number string>) => if_keyisindex: number.
+    Handle<Object> key = isolate->factory()->InternalizeUtf8String("153");
+    Handle<Object> index(Smi::FromInt(153), isolate);
+    ft.CheckTrue(key, expect_index, index);
+  }
+
+  {
+    // TryToName(<non-internalized string>) => bailout.
+    Handle<Object> key = isolate->factory()->NewStringFromAsciiChecked("test");
+    ft.CheckTrue(key, expect_bailout);
+  }
+}
+
+namespace {
+
+template <typename Dictionary>
+void TestNameDictionaryLookup() {
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
+  Isolate* isolate(CcTest::InitIsolateOnce());
+
+  const int kNumParams = 4;
+  CodeStubAssemblerTester m(isolate, kNumParams);
+
+  enum Result { kFound, kNotFound };
+  {
+    Node* dictionary = m.Parameter(0);
+    Node* unique_name = m.Parameter(1);
+    Node* expected_result = m.Parameter(2);
+    Node* expected_arg = m.Parameter(3);
+
+    Label passed(&m), failed(&m);
+    Label if_found(&m), if_not_found(&m);
+    Variable var_name_index(&m, MachineRepresentation::kWord32);
+
+    m.NameDictionaryLookup<Dictionary>(dictionary, unique_name, &if_found,
+                                       &var_name_index, &if_not_found);
+    m.Bind(&if_found);
+    m.GotoUnless(
+        m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))),
+        &failed);
+    m.Branch(m.Word32Equal(m.SmiToWord32(expected_arg), var_name_index.value()),
+             &passed, &failed);
+
+    m.Bind(&if_not_found);
+    m.Branch(
+        m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kNotFound))),
+        &passed, &failed);
+
+    m.Bind(&passed);
+    m.Return(m.BooleanConstant(true));
+
+    m.Bind(&failed);
+    m.Return(m.BooleanConstant(false));
+  }
+
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(code, kNumParams);
+
+  Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
+  Handle<Object> expect_not_found(Smi::FromInt(kNotFound), isolate);
+
+  Handle<Dictionary> dictionary = Dictionary::New(isolate, 40);
+  PropertyDetails fake_details = PropertyDetails::Empty();
+
+  Factory* factory = isolate->factory();
+  Handle<Name> keys[] = {
+      factory->InternalizeUtf8String("0"),
+      factory->InternalizeUtf8String("42"),
+      factory->InternalizeUtf8String("-153"),
+      factory->InternalizeUtf8String("0.0"),
+      factory->InternalizeUtf8String("4.2"),
+      factory->InternalizeUtf8String(""),
+      factory->InternalizeUtf8String("name"),
+      factory->NewSymbol(),
+      factory->NewPrivateSymbol(),
+  };
+
+  for (size_t i = 0; i < arraysize(keys); i++) {
+    Handle<Object> value = factory->NewPropertyCell();
+    dictionary = Dictionary::Add(dictionary, keys[i], value, fake_details);
+  }
+
+  for (size_t i = 0; i < arraysize(keys); i++) {
+    int entry = dictionary->FindEntry(keys[i]);
+    int name_index =
+        Dictionary::EntryToIndex(entry) + Dictionary::kEntryKeyIndex;
+    CHECK_NE(Dictionary::kNotFound, entry);
+
+    Handle<Object> expected_name_index(Smi::FromInt(name_index), isolate);
+    ft.CheckTrue(dictionary, keys[i], expect_found, expected_name_index);
+  }
+
+  Handle<Name> non_existing_keys[] = {
+      factory->InternalizeUtf8String("1"),
+      factory->InternalizeUtf8String("-42"),
+      factory->InternalizeUtf8String("153"),
+      factory->InternalizeUtf8String("-1.0"),
+      factory->InternalizeUtf8String("1.3"),
+      factory->InternalizeUtf8String("a"),
+      factory->InternalizeUtf8String("boom"),
+      factory->NewSymbol(),
+      factory->NewPrivateSymbol(),
+  };
+
+  for (size_t i = 0; i < arraysize(non_existing_keys); i++) {
+    int entry = dictionary->FindEntry(non_existing_keys[i]);
+    CHECK_EQ(Dictionary::kNotFound, entry);
+
+    ft.CheckTrue(dictionary, non_existing_keys[i], expect_not_found);
+  }
+}
+
+}  // namespace
+
+TEST(NameDictionaryLookup) { TestNameDictionaryLookup<NameDictionary>(); }
+
+TEST(GlobalDictionaryLookup) { TestNameDictionaryLookup<GlobalDictionary>(); }
+
+namespace {
+
+template <typename Dictionary>
+void TestNumberDictionaryLookup() {
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
+  Isolate* isolate(CcTest::InitIsolateOnce());
+
+  const int kNumParams = 4;
+  CodeStubAssemblerTester m(isolate, kNumParams);
+
+  enum Result { kFound, kNotFound };
+  {
+    Node* dictionary = m.Parameter(0);
+    Node* key = m.SmiToWord32(m.Parameter(1));
+    Node* expected_result = m.Parameter(2);
+    Node* expected_arg = m.Parameter(3);
+
+    Label passed(&m), failed(&m);
+    Label if_found(&m), if_not_found(&m);
+    Variable var_entry(&m, MachineRepresentation::kWord32);
+
+    m.NumberDictionaryLookup<Dictionary>(dictionary, key, &if_found, &var_entry,
+                                         &if_not_found);
+    m.Bind(&if_found);
+    m.GotoUnless(
+        m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))),
+        &failed);
+    m.Branch(m.Word32Equal(m.SmiToWord32(expected_arg), var_entry.value()),
+             &passed, &failed);
+
+    m.Bind(&if_not_found);
+    m.Branch(
+        m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kNotFound))),
+        &passed, &failed);
+
+    m.Bind(&passed);
+    m.Return(m.BooleanConstant(true));
+
+    m.Bind(&failed);
+    m.Return(m.BooleanConstant(false));
+  }
+
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(code, kNumParams);
+
+  Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
+  Handle<Object> expect_not_found(Smi::FromInt(kNotFound), isolate);
+
+  const int kKeysCount = 1000;
+  Handle<Dictionary> dictionary = Dictionary::New(isolate, kKeysCount);
+  uint32_t keys[kKeysCount];
+
+  Handle<Object> fake_value(Smi::FromInt(42), isolate);
+  PropertyDetails fake_details = PropertyDetails::Empty();
+
+  base::RandomNumberGenerator rand_gen(FLAG_random_seed);
+
+  for (int i = 0; i < kKeysCount; i++) {
+    int random_key = rand_gen.NextInt(Smi::kMaxValue);
+    keys[i] = static_cast<uint32_t>(random_key);
+    if (dictionary->FindEntry(keys[i]) != Dictionary::kNotFound) continue;
+
+    dictionary = Dictionary::Add(dictionary, keys[i], fake_value, fake_details);
+  }
+
+  // Now try querying existing keys.
+  for (int i = 0; i < kKeysCount; i++) {
+    int entry = dictionary->FindEntry(keys[i]);
+    CHECK_NE(Dictionary::kNotFound, entry);
+
+    Handle<Object> key(Smi::FromInt(keys[i]), isolate);
+    Handle<Object> expected_entry(Smi::FromInt(entry), isolate);
+    ft.CheckTrue(dictionary, key, expect_found, expected_entry);
+  }
+
+  // Now try querying random keys which do not exist in the dictionary.
+  for (int i = 0; i < kKeysCount;) {
+    int random_key = rand_gen.NextInt(Smi::kMaxValue);
+    int entry = dictionary->FindEntry(random_key);
+    if (entry != Dictionary::kNotFound) continue;
+    i++;
+
+    Handle<Object> key(Smi::FromInt(random_key), isolate);
+    ft.CheckTrue(dictionary, key, expect_not_found);
+  }
+}
+
+}  // namespace
+
+TEST(SeededNumberDictionaryLookup) {
+  TestNumberDictionaryLookup<SeededNumberDictionary>();
+}
+
+TEST(UnseededNumberDictionaryLookup) {
+  TestNumberDictionaryLookup<UnseededNumberDictionary>();
+}
+
+namespace {
+
+void AddProperties(Handle<JSObject> object, Handle<Name> names[],
+                   size_t count) {
+  Isolate* isolate = object->GetIsolate();
+  for (size_t i = 0; i < count; i++) {
+    Handle<Object> value(Smi::FromInt(static_cast<int>(42 + i)), isolate);
+    JSObject::AddProperty(object, names[i], value, NONE);
+  }
+}
+
+Handle<AccessorPair> CreateAccessorPair(FunctionTester* ft,
+                                        const char* getter_body,
+                                        const char* setter_body) {
+  Handle<AccessorPair> pair = ft->isolate->factory()->NewAccessorPair();
+  if (getter_body) {
+    pair->set_getter(*ft->NewFunction(getter_body));
+  }
+  if (setter_body) {
+    pair->set_setter(*ft->NewFunction(setter_body));
+  }
+  return pair;
+}
+
+void AddProperties(Handle<JSObject> object, Handle<Name> names[],
+                   size_t names_count, Handle<Object> values[],
+                   size_t values_count, int seed = 0) {
+  Isolate* isolate = object->GetIsolate();
+  for (size_t i = 0; i < names_count; i++) {
+    Handle<Object> value = values[(seed + i) % values_count];
+    if (value->IsAccessorPair()) {
+      Handle<AccessorPair> pair = Handle<AccessorPair>::cast(value);
+      Handle<Object> getter(pair->getter(), isolate);
+      Handle<Object> setter(pair->setter(), isolate);
+      JSObject::DefineAccessor(object, names[i], getter, setter, NONE).Check();
+    } else {
+      JSObject::AddProperty(object, names[i], value, NONE);
+    }
+  }
+}
+
+}  // namespace
+
+TEST(TryHasOwnProperty) {
+  typedef CodeStubAssembler::Label Label;
+  Isolate* isolate(CcTest::InitIsolateOnce());
+
+  const int kNumParams = 4;
+  CodeStubAssemblerTester m(isolate, kNumParams);
+
+  enum Result { kFound, kNotFound, kBailout };
+  {
+    Node* object = m.Parameter(0);
+    Node* unique_name = m.Parameter(1);
+    Node* expected_result = m.Parameter(2);
+
+    Label passed(&m), failed(&m);
+    Label if_found(&m), if_not_found(&m), if_bailout(&m);
+
+    Node* map = m.LoadMap(object);
+    Node* instance_type = m.LoadMapInstanceType(map);
+
+    m.TryHasOwnProperty(object, map, instance_type, unique_name, &if_found,
+                        &if_not_found, &if_bailout);
+
+    m.Bind(&if_found);
+    m.Branch(m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))),
+             &passed, &failed);
+
+    m.Bind(&if_not_found);
+    m.Branch(
+        m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kNotFound))),
+        &passed, &failed);
+
+    m.Bind(&if_bailout);
+    m.Branch(
+        m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kBailout))),
+        &passed, &failed);
+
+    m.Bind(&passed);
+    m.Return(m.BooleanConstant(true));
+
+    m.Bind(&failed);
+    m.Return(m.BooleanConstant(false));
+  }
+
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(code, kNumParams);
+
+  Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
+  Handle<Object> expect_not_found(Smi::FromInt(kNotFound), isolate);
+  Handle<Object> expect_bailout(Smi::FromInt(kBailout), isolate);
+
+  Factory* factory = isolate->factory();
+
+  Handle<Name> deleted_property_name =
+      factory->InternalizeUtf8String("deleted");
+
+  Handle<Name> names[] = {
+      factory->InternalizeUtf8String("a"),
+      factory->InternalizeUtf8String("bb"),
+      factory->InternalizeUtf8String("ccc"),
+      factory->InternalizeUtf8String("dddd"),
+      factory->InternalizeUtf8String("eeeee"),
+      factory->InternalizeUtf8String(""),
+      factory->InternalizeUtf8String("name"),
+      factory->NewSymbol(),
+      factory->NewPrivateSymbol(),
+  };
+
+  std::vector<Handle<JSObject>> objects;
+
+  {
+    // Fast object, no inobject properties.
+    int inobject_properties = 0;
+    Handle<Map> map = Map::Create(isolate, inobject_properties);
+    Handle<JSObject> object = factory->NewJSObjectFromMap(map);
+    AddProperties(object, names, arraysize(names));
+    CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
+    CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
+    CHECK(!object->map()->is_dictionary_map());
+    objects.push_back(object);
+  }
+
+  {
+    // Fast object, all inobject properties.
+    int inobject_properties = arraysize(names) * 2;
+    Handle<Map> map = Map::Create(isolate, inobject_properties);
+    Handle<JSObject> object = factory->NewJSObjectFromMap(map);
+    AddProperties(object, names, arraysize(names));
+    CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
+    CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
+    CHECK(!object->map()->is_dictionary_map());
+    objects.push_back(object);
+  }
+
+  {
+    // Fast object, half inobject properties.
+    int inobject_properties = arraysize(names) / 2;
+    Handle<Map> map = Map::Create(isolate, inobject_properties);
+    Handle<JSObject> object = factory->NewJSObjectFromMap(map);
+    AddProperties(object, names, arraysize(names));
+    CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
+    CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
+    CHECK(!object->map()->is_dictionary_map());
+    objects.push_back(object);
+  }
+
+  {
+    // Dictionary mode object.
+    Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
+    Handle<JSObject> object = factory->NewJSObject(function);
+    AddProperties(object, names, arraysize(names));
+    JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, "test");
+
+    JSObject::AddProperty(object, deleted_property_name, object, NONE);
+    CHECK(JSObject::DeleteProperty(object, deleted_property_name, SLOPPY)
+              .FromJust());
+
+    CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
+    CHECK(object->map()->is_dictionary_map());
+    objects.push_back(object);
+  }
+
+  {
+    // Global object.
+    Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
+    JSFunction::EnsureHasInitialMap(function);
+    function->initial_map()->set_instance_type(JS_GLOBAL_OBJECT_TYPE);
+    function->initial_map()->set_is_prototype_map(true);
+    function->initial_map()->set_dictionary_map(true);
+    Handle<JSObject> object = factory->NewJSGlobalObject(function);
+    AddProperties(object, names, arraysize(names));
+
+    JSObject::AddProperty(object, deleted_property_name, object, NONE);
+    CHECK(JSObject::DeleteProperty(object, deleted_property_name, SLOPPY)
+              .FromJust());
+
+    CHECK_EQ(JS_GLOBAL_OBJECT_TYPE, object->map()->instance_type());
+    CHECK(object->map()->is_dictionary_map());
+    objects.push_back(object);
+  }
+
+  {
+    for (Handle<JSObject> object : objects) {
+      for (size_t name_index = 0; name_index < arraysize(names); name_index++) {
+        Handle<Name> name = names[name_index];
+        CHECK(JSReceiver::HasProperty(object, name).FromJust());
+        ft.CheckTrue(object, name, expect_found);
+      }
+    }
+  }
+
+  {
+    Handle<Name> non_existing_names[] = {
+        factory->NewSymbol(),
+        factory->InternalizeUtf8String("ne_a"),
+        factory->InternalizeUtf8String("ne_bb"),
+        factory->NewPrivateSymbol(),
+        factory->InternalizeUtf8String("ne_ccc"),
+        factory->InternalizeUtf8String("ne_dddd"),
+        deleted_property_name,
+    };
+    for (Handle<JSObject> object : objects) {
+      for (size_t key_index = 0; key_index < arraysize(non_existing_names);
+           key_index++) {
+        Handle<Name> name = non_existing_names[key_index];
+        CHECK(!JSReceiver::HasProperty(object, name).FromJust());
+        ft.CheckTrue(object, name, expect_not_found);
+      }
+    }
+  }
+
+  {
+    Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
+    Handle<JSProxy> object = factory->NewJSProxy(function, objects[0]);
+    CHECK_EQ(JS_PROXY_TYPE, object->map()->instance_type());
+    ft.CheckTrue(object, names[0], expect_bailout);
+  }
+
+  {
+    Handle<JSObject> object = isolate->global_proxy();
+    CHECK_EQ(JS_GLOBAL_PROXY_TYPE, object->map()->instance_type());
+    ft.CheckTrue(object, names[0], expect_bailout);
+  }
+}
+
+TEST(TryGetOwnProperty) {
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  Factory* factory = isolate->factory();
+
+  const int kNumParams = 2;
+  CodeStubAssemblerTester m(isolate, kNumParams);
+
+  Handle<Symbol> not_found_symbol = factory->NewSymbol();
+  Handle<Symbol> bailout_symbol = factory->NewSymbol();
+  {
+    Node* object = m.Parameter(0);
+    Node* unique_name = m.Parameter(1);
+    Node* context = m.Parameter(kNumParams + 2);
+
+    Variable var_value(&m, MachineRepresentation::kTagged);
+    Label if_found(&m), if_not_found(&m), if_bailout(&m);
+
+    Node* map = m.LoadMap(object);
+    Node* instance_type = m.LoadMapInstanceType(map);
+
+    m.TryGetOwnProperty(context, object, object, map, instance_type,
+                        unique_name, &if_found, &var_value, &if_not_found,
+                        &if_bailout);
+
+    m.Bind(&if_found);
+    m.Return(var_value.value());
+
+    m.Bind(&if_not_found);
+    m.Return(m.HeapConstant(not_found_symbol));
+
+    m.Bind(&if_bailout);
+    m.Return(m.HeapConstant(bailout_symbol));
+  }
+
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(code, kNumParams);
+
+  Handle<Name> deleted_property_name =
+      factory->InternalizeUtf8String("deleted");
+
+  Handle<Name> names[] = {
+      factory->InternalizeUtf8String("bb"),
+      factory->NewSymbol(),
+      factory->InternalizeUtf8String("a"),
+      factory->InternalizeUtf8String("ccc"),
+      factory->InternalizeUtf8String("esajefe"),
+      factory->NewPrivateSymbol(),
+      factory->InternalizeUtf8String("eeeee"),
+      factory->InternalizeUtf8String("p1"),
+      factory->InternalizeUtf8String("acshw23e"),
+      factory->InternalizeUtf8String(""),
+      factory->InternalizeUtf8String("dddd"),
+      factory->NewPrivateSymbol(),
+      factory->InternalizeUtf8String("name"),
+      factory->InternalizeUtf8String("p2"),
+      factory->InternalizeUtf8String("p3"),
+      factory->InternalizeUtf8String("p4"),
+      factory->NewPrivateSymbol(),
+  };
+  Handle<Object> values[] = {
+      factory->NewFunction(factory->empty_string()),
+      factory->NewSymbol(),
+      factory->InternalizeUtf8String("a"),
+      CreateAccessorPair(&ft, "() => 188;", "() => 199;"),
+      factory->NewFunction(factory->InternalizeUtf8String("bb")),
+      factory->InternalizeUtf8String("ccc"),
+      CreateAccessorPair(&ft, "() => 88;", nullptr),
+      handle(Smi::FromInt(1), isolate),
+      factory->InternalizeUtf8String(""),
+      CreateAccessorPair(&ft, nullptr, "() => 99;"),
+      factory->NewHeapNumber(4.2),
+      handle(Smi::FromInt(153), isolate),
+      factory->NewJSObject(factory->NewFunction(factory->empty_string())),
+      factory->NewPrivateSymbol(),
+  };
+  STATIC_ASSERT(arraysize(values) < arraysize(names));
+
+  base::RandomNumberGenerator rand_gen(FLAG_random_seed);
+
+  std::vector<Handle<JSObject>> objects;
+
+  {
+    // Fast object, no inobject properties.
+    int inobject_properties = 0;
+    Handle<Map> map = Map::Create(isolate, inobject_properties);
+    Handle<JSObject> object = factory->NewJSObjectFromMap(map);
+    AddProperties(object, names, arraysize(names), values, arraysize(values),
+                  rand_gen.NextInt());
+    CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
+    CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
+    CHECK(!object->map()->is_dictionary_map());
+    objects.push_back(object);
+  }
+
+  {
+    // Fast object, all inobject properties.
+    int inobject_properties = arraysize(names) * 2;
+    Handle<Map> map = Map::Create(isolate, inobject_properties);
+    Handle<JSObject> object = factory->NewJSObjectFromMap(map);
+    AddProperties(object, names, arraysize(names), values, arraysize(values),
+                  rand_gen.NextInt());
+    CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
+    CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
+    CHECK(!object->map()->is_dictionary_map());
+    objects.push_back(object);
+  }
+
+  {
+    // Fast object, half inobject properties.
+    int inobject_properties = arraysize(names) / 2;
+    Handle<Map> map = Map::Create(isolate, inobject_properties);
+    Handle<JSObject> object = factory->NewJSObjectFromMap(map);
+    AddProperties(object, names, arraysize(names), values, arraysize(values),
+                  rand_gen.NextInt());
+    CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
+    CHECK_EQ(inobject_properties, object->map()->GetInObjectProperties());
+    CHECK(!object->map()->is_dictionary_map());
+    objects.push_back(object);
+  }
+
+  {
+    // Dictionary mode object.
+    Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
+    Handle<JSObject> object = factory->NewJSObject(function);
+    AddProperties(object, names, arraysize(names), values, arraysize(values),
+                  rand_gen.NextInt());
+    JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, "test");
+
+    JSObject::AddProperty(object, deleted_property_name, object, NONE);
+    CHECK(JSObject::DeleteProperty(object, deleted_property_name, SLOPPY)
+              .FromJust());
+
+    CHECK_EQ(JS_OBJECT_TYPE, object->map()->instance_type());
+    CHECK(object->map()->is_dictionary_map());
+    objects.push_back(object);
+  }
+
+  {
+    // Global object.
+    Handle<JSGlobalObject> object = isolate->global_object();
+    AddProperties(object, names, arraysize(names), values, arraysize(values),
+                  rand_gen.NextInt());
+
+    JSObject::AddProperty(object, deleted_property_name, object, NONE);
+    CHECK(JSObject::DeleteProperty(object, deleted_property_name, SLOPPY)
+              .FromJust());
+
+    CHECK_EQ(JS_GLOBAL_OBJECT_TYPE, object->map()->instance_type());
+    CHECK(object->map()->is_dictionary_map());
+    objects.push_back(object);
+  }
+
+  // TODO(ishell): test proxy and interceptors when they are supported.
+
+  {
+    for (Handle<JSObject> object : objects) {
+      for (size_t name_index = 0; name_index < arraysize(names); name_index++) {
+        Handle<Name> name = names[name_index];
+        Handle<Object> expected_value =
+            JSReceiver::GetProperty(object, name).ToHandleChecked();
+        Handle<Object> value = ft.Call(object, name).ToHandleChecked();
+        CHECK(expected_value->SameValue(*value));
+      }
+    }
+  }
+
+  {
+    Handle<Name> non_existing_names[] = {
+        factory->NewSymbol(),
+        factory->InternalizeUtf8String("ne_a"),
+        factory->InternalizeUtf8String("ne_bb"),
+        factory->NewPrivateSymbol(),
+        factory->InternalizeUtf8String("ne_ccc"),
+        factory->InternalizeUtf8String("ne_dddd"),
+        deleted_property_name,
+    };
+    for (Handle<JSObject> object : objects) {
+      for (size_t key_index = 0; key_index < arraysize(non_existing_names);
+           key_index++) {
+        Handle<Name> name = non_existing_names[key_index];
+        Handle<Object> expected_value =
+            JSReceiver::GetProperty(object, name).ToHandleChecked();
+        CHECK(expected_value->IsUndefined(isolate));
+        Handle<Object> value = ft.Call(object, name).ToHandleChecked();
+        CHECK_EQ(*not_found_symbol, *value);
+      }
+    }
+  }
+
+  {
+    Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
+    Handle<JSProxy> object = factory->NewJSProxy(function, objects[0]);
+    CHECK_EQ(JS_PROXY_TYPE, object->map()->instance_type());
+    Handle<Object> value = ft.Call(object, names[0]).ToHandleChecked();
+    // Proxies are not supported yet.
+    CHECK_EQ(*bailout_symbol, *value);
+  }
+
+  {
+    Handle<JSObject> object = isolate->global_proxy();
+    CHECK_EQ(JS_GLOBAL_PROXY_TYPE, object->map()->instance_type());
+    // Global proxies are not supported yet.
+    Handle<Object> value = ft.Call(object, names[0]).ToHandleChecked();
+    CHECK_EQ(*bailout_symbol, *value);
+  }
+}
+
+namespace {
+
+void AddElement(Handle<JSObject> object, uint32_t index, Handle<Object> value,
+                PropertyAttributes attributes = NONE) {
+  JSObject::AddDataElement(object, index, value, attributes).ToHandleChecked();
+}
+
+}  // namespace
+
+TEST(TryLookupElement) {
+  typedef CodeStubAssembler::Label Label;
+  Isolate* isolate(CcTest::InitIsolateOnce());
+
+  const int kNumParams = 3;
+  CodeStubAssemblerTester m(isolate, kNumParams);
+
+  enum Result { kFound, kNotFound, kBailout };
+  {
+    Node* object = m.Parameter(0);
+    Node* index = m.SmiToWord32(m.Parameter(1));
+    Node* expected_result = m.Parameter(2);
+
+    Label passed(&m), failed(&m);
+    Label if_found(&m), if_not_found(&m), if_bailout(&m);
+
+    Node* map = m.LoadMap(object);
+    Node* instance_type = m.LoadMapInstanceType(map);
+
+    m.TryLookupElement(object, map, instance_type, index, &if_found,
+                       &if_not_found, &if_bailout);
+
+    m.Bind(&if_found);
+    m.Branch(m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))),
+             &passed, &failed);
+
+    m.Bind(&if_not_found);
+    m.Branch(
+        m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kNotFound))),
+        &passed, &failed);
+
+    m.Bind(&if_bailout);
+    m.Branch(
+        m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kBailout))),
+        &passed, &failed);
+
+    m.Bind(&passed);
+    m.Return(m.BooleanConstant(true));
+
+    m.Bind(&failed);
+    m.Return(m.BooleanConstant(false));
+  }
+
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(code, kNumParams);
+
+  Factory* factory = isolate->factory();
+  Handle<Object> smi0(Smi::FromInt(0), isolate);
+  Handle<Object> smi1(Smi::FromInt(1), isolate);
+  Handle<Object> smi7(Smi::FromInt(7), isolate);
+  Handle<Object> smi13(Smi::FromInt(13), isolate);
+  Handle<Object> smi42(Smi::FromInt(42), isolate);
+
+  Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
+  Handle<Object> expect_not_found(Smi::FromInt(kNotFound), isolate);
+  Handle<Object> expect_bailout(Smi::FromInt(kBailout), isolate);
+
+#define CHECK_FOUND(object, index)                         \
+  CHECK(JSReceiver::HasElement(object, index).FromJust()); \
+  ft.CheckTrue(object, smi##index, expect_found);
+
+#define CHECK_NOT_FOUND(object, index)                      \
+  CHECK(!JSReceiver::HasElement(object, index).FromJust()); \
+  ft.CheckTrue(object, smi##index, expect_not_found);
+
+  {
+    Handle<JSArray> object = factory->NewJSArray(0, FAST_SMI_ELEMENTS);
+    AddElement(object, 0, smi0);
+    AddElement(object, 1, smi0);
+    CHECK_EQ(FAST_SMI_ELEMENTS, object->map()->elements_kind());
+
+    CHECK_FOUND(object, 0);
+    CHECK_FOUND(object, 1);
+    CHECK_NOT_FOUND(object, 7);
+    CHECK_NOT_FOUND(object, 13);
+    CHECK_NOT_FOUND(object, 42);
+  }
+
+  {
+    Handle<JSArray> object = factory->NewJSArray(0, FAST_HOLEY_SMI_ELEMENTS);
+    AddElement(object, 0, smi0);
+    AddElement(object, 13, smi0);
+    CHECK_EQ(FAST_HOLEY_SMI_ELEMENTS, object->map()->elements_kind());
+
+    CHECK_FOUND(object, 0);
+    CHECK_NOT_FOUND(object, 1);
+    CHECK_NOT_FOUND(object, 7);
+    CHECK_FOUND(object, 13);
+    CHECK_NOT_FOUND(object, 42);
+  }
+
+  {
+    Handle<JSArray> object = factory->NewJSArray(0, FAST_ELEMENTS);
+    AddElement(object, 0, smi0);
+    AddElement(object, 1, smi0);
+    CHECK_EQ(FAST_ELEMENTS, object->map()->elements_kind());
+
+    CHECK_FOUND(object, 0);
+    CHECK_FOUND(object, 1);
+    CHECK_NOT_FOUND(object, 7);
+    CHECK_NOT_FOUND(object, 13);
+    CHECK_NOT_FOUND(object, 42);
+  }
+
+  {
+    Handle<JSArray> object = factory->NewJSArray(0, FAST_HOLEY_ELEMENTS);
+    AddElement(object, 0, smi0);
+    AddElement(object, 13, smi0);
+    CHECK_EQ(FAST_HOLEY_ELEMENTS, object->map()->elements_kind());
+
+    CHECK_FOUND(object, 0);
+    CHECK_NOT_FOUND(object, 1);
+    CHECK_NOT_FOUND(object, 7);
+    CHECK_FOUND(object, 13);
+    CHECK_NOT_FOUND(object, 42);
+  }
+
+  {
+    Handle<JSFunction> constructor = isolate->string_function();
+    Handle<JSObject> object = factory->NewJSObject(constructor);
+    Handle<String> str = factory->InternalizeUtf8String("ab");
+    Handle<JSValue>::cast(object)->set_value(*str);
+    AddElement(object, 13, smi0);
+    CHECK_EQ(FAST_STRING_WRAPPER_ELEMENTS, object->map()->elements_kind());
+
+    CHECK_FOUND(object, 0);
+    CHECK_FOUND(object, 1);
+    CHECK_NOT_FOUND(object, 7);
+    CHECK_FOUND(object, 13);
+    CHECK_NOT_FOUND(object, 42);
+  }
+
+  {
+    Handle<JSFunction> constructor = isolate->string_function();
+    Handle<JSObject> object = factory->NewJSObject(constructor);
+    Handle<String> str = factory->InternalizeUtf8String("ab");
+    Handle<JSValue>::cast(object)->set_value(*str);
+    AddElement(object, 13, smi0);
+    JSObject::NormalizeElements(object);
+    CHECK_EQ(SLOW_STRING_WRAPPER_ELEMENTS, object->map()->elements_kind());
+
+    CHECK_FOUND(object, 0);
+    CHECK_FOUND(object, 1);
+    CHECK_NOT_FOUND(object, 7);
+    CHECK_FOUND(object, 13);
+    CHECK_NOT_FOUND(object, 42);
+  }
+
+// TODO(ishell): uncomment once NO_ELEMENTS kind is supported.
+//  {
+//    Handle<Map> map = Map::Create(isolate, 0);
+//    map->set_elements_kind(NO_ELEMENTS);
+//    Handle<JSObject> object = factory->NewJSObjectFromMap(map);
+//    CHECK_EQ(NO_ELEMENTS, object->map()->elements_kind());
+//
+//    CHECK_NOT_FOUND(object, 0);
+//    CHECK_NOT_FOUND(object, 1);
+//    CHECK_NOT_FOUND(object, 7);
+//    CHECK_NOT_FOUND(object, 13);
+//    CHECK_NOT_FOUND(object, 42);
+//  }
+
+#undef CHECK_FOUND
+#undef CHECK_NOT_FOUND
+
+  {
+    Handle<JSArray> handler = factory->NewJSArray(0);
+    Handle<JSFunction> function = factory->NewFunction(factory->empty_string());
+    Handle<JSProxy> object = factory->NewJSProxy(function, handler);
+    CHECK_EQ(JS_PROXY_TYPE, object->map()->instance_type());
+    ft.CheckTrue(object, smi0, expect_bailout);
+  }
+
+  {
+    Handle<JSObject> object = isolate->global_object();
+    CHECK_EQ(JS_GLOBAL_OBJECT_TYPE, object->map()->instance_type());
+    ft.CheckTrue(object, smi0, expect_bailout);
+  }
+
+  {
+    Handle<JSObject> object = isolate->global_proxy();
+    CHECK_EQ(JS_GLOBAL_PROXY_TYPE, object->map()->instance_type());
+    ft.CheckTrue(object, smi0, expect_bailout);
+  }
+}
+
+TEST(DeferredCodePhiHints) {
+  typedef compiler::Node Node;
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeStubAssemblerTester m(isolate, descriptor);
+  Label block1(&m, Label::kDeferred);
+  m.Goto(&block1);
+  m.Bind(&block1);
+  {
+    Variable var_object(&m, MachineRepresentation::kTagged);
+    Label loop(&m, &var_object);
+    var_object.Bind(m.IntPtrConstant(0));
+    m.Goto(&loop);
+    m.Bind(&loop);
+    {
+      Node* map = m.LoadMap(var_object.value());
+      var_object.Bind(map);
+      m.Goto(&loop);
+    }
+  }
+  CHECK(!m.GenerateCode().is_null());
+}
+
+TEST(TestOutOfScopeVariable) {
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  VoidDescriptor descriptor(isolate);
+  CodeStubAssemblerTester m(isolate, descriptor);
+  Label block1(&m);
+  Label block2(&m);
+  Label block3(&m);
+  Label block4(&m);
+  m.Branch(m.WordEqual(m.Parameter(0), m.IntPtrConstant(0)), &block1, &block4);
+  m.Bind(&block4);
+  {
+    Variable var_object(&m, MachineRepresentation::kTagged);
+    m.Branch(m.WordEqual(m.Parameter(0), m.IntPtrConstant(0)), &block2,
+             &block3);
+
+    m.Bind(&block2);
+    var_object.Bind(m.IntPtrConstant(55));
+    m.Goto(&block1);
+
+    m.Bind(&block3);
+    var_object.Bind(m.IntPtrConstant(66));
+    m.Goto(&block1);
+  }
+  m.Bind(&block1);
+  CHECK(!m.GenerateCode().is_null());
+}
+
+namespace {
+
+void TestStubCacheOffsetCalculation(StubCache::Table table,
+                                    Code::Kind handler_kind) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  const int kNumParams = 2;
+  CodeStubAssemblerTester m(isolate, kNumParams);
+
+  Code::Flags code_flags =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(handler_kind));
+  {
+    Node* name = m.Parameter(0);
+    Node* map = m.Parameter(1);
+    Node* primary_offset = m.StubCachePrimaryOffset(name, code_flags, map);
+    Node* result;
+    if (table == StubCache::kPrimary) {
+      result = primary_offset;
+    } else {
+      CHECK_EQ(StubCache::kSecondary, table);
+      result = m.StubCacheSecondaryOffset(name, code_flags, primary_offset);
+    }
+    m.Return(m.SmiFromWord32(result));
+  }
+
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(code, kNumParams);
+
+  Factory* factory = isolate->factory();
+  Handle<Name> names[] = {
+      factory->NewSymbol(),
+      factory->InternalizeUtf8String("a"),
+      factory->InternalizeUtf8String("bb"),
+      factory->InternalizeUtf8String("ccc"),
+      factory->NewPrivateSymbol(),
+      factory->InternalizeUtf8String("dddd"),
+      factory->InternalizeUtf8String("eeeee"),
+      factory->InternalizeUtf8String("name"),
+      factory->NewSymbol(),
+      factory->NewPrivateSymbol(),
+  };
+
+  Handle<Map> maps[] = {
+      Handle<Map>(nullptr, isolate),
+      factory->cell_map(),
+      Map::Create(isolate, 0),
+      factory->meta_map(),
+      factory->code_map(),
+      Map::Create(isolate, 0),
+      factory->hash_table_map(),
+      factory->symbol_map(),
+      factory->string_map(),
+      Map::Create(isolate, 0),
+      factory->sloppy_arguments_elements_map(),
+  };
+
+  for (int name_index = 0; name_index < arraysize(names); name_index++) {
+    Handle<Name> name = names[name_index];
+    for (int map_index = 0; map_index < arraysize(maps); map_index++) {
+      Handle<Map> map = maps[map_index];
+
+      int expected_result;
+      {
+        int primary_offset =
+            StubCache::PrimaryOffsetForTesting(*name, code_flags, *map);
+        if (table == StubCache::kPrimary) {
+          expected_result = primary_offset;
+        } else {
+          expected_result = StubCache::SecondaryOffsetForTesting(
+              *name, code_flags, primary_offset);
+        }
+      }
+      Handle<Object> result = ft.Call(name, map).ToHandleChecked();
+
+      Smi* expected = Smi::FromInt(expected_result & Smi::kMaxValue);
+      CHECK_EQ(expected, Smi::cast(*result));
+    }
+  }
+}
+
+}  // namespace
+
+TEST(StubCachePrimaryOffsetLoadIC) {
+  TestStubCacheOffsetCalculation(StubCache::kPrimary, Code::LOAD_IC);
+}
+
+TEST(StubCachePrimaryOffsetStoreIC) {
+  TestStubCacheOffsetCalculation(StubCache::kPrimary, Code::STORE_IC);
+}
+
+TEST(StubCacheSecondaryOffsetLoadIC) {
+  TestStubCacheOffsetCalculation(StubCache::kSecondary, Code::LOAD_IC);
+}
+
+TEST(StubCacheSecondaryOffsetStoreIC) {
+  TestStubCacheOffsetCalculation(StubCache::kSecondary, Code::STORE_IC);
+}
+
+namespace {
+
+Handle<Code> CreateCodeWithFlags(Code::Flags flags) {
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  CodeStubAssemblerTester m(isolate, flags);
+  m.Return(m.UndefinedConstant());
+  return m.GenerateCodeCloseAndEscape();
+}
+
+}  // namespace
+
+TEST(TryProbeStubCache) {
+  typedef CodeStubAssembler::Label Label;
+  typedef CodeStubAssembler::Variable Variable;
+  Isolate* isolate(CcTest::InitIsolateOnce());
+  const int kNumParams = 3;
+  CodeStubAssemblerTester m(isolate, kNumParams);
+
+  Code::Flags flags_to_query =
+      Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
+
+  StubCache stub_cache(isolate);
+  stub_cache.Clear();
+
+  {
+    Node* receiver = m.Parameter(0);
+    Node* name = m.Parameter(1);
+    Node* expected_handler = m.Parameter(2);
+
+    Label passed(&m), failed(&m);
+
+    Variable var_handler(&m, MachineRepresentation::kTagged);
+    Label if_handler(&m), if_miss(&m);
+
+    m.TryProbeStubCache(&stub_cache, flags_to_query, receiver, name,
+                        &if_handler, &var_handler, &if_miss);
+    m.Bind(&if_handler);
+    m.BranchIfWordEqual(expected_handler, var_handler.value(), &passed,
+                        &failed);
+
+    m.Bind(&if_miss);
+    m.BranchIfWordEqual(expected_handler, m.IntPtrConstant(0), &passed,
+                        &failed);
+
+    m.Bind(&passed);
+    m.Return(m.BooleanConstant(true));
+
+    m.Bind(&failed);
+    m.Return(m.BooleanConstant(false));
+  }
+
+  Handle<Code> code = m.GenerateCode();
+  FunctionTester ft(code, kNumParams);
+
+  std::vector<Handle<Name>> names;
+  std::vector<Handle<JSObject>> receivers;
+  std::vector<Handle<Code>> handlers;
+
+  base::RandomNumberGenerator rand_gen(FLAG_random_seed);
+
+  Factory* factory = isolate->factory();
+
+  // Generate some number of names.
+  for (int i = 0; i < StubCache::kPrimaryTableSize / 7; i++) {
+    Handle<Name> name;
+    switch (rand_gen.NextInt(3)) {
+      case 0: {
+        // Generate string.
+        std::stringstream ss;
+        ss << "s" << std::hex
+           << (rand_gen.NextInt(Smi::kMaxValue) % StubCache::kPrimaryTableSize);
+        name = factory->InternalizeUtf8String(ss.str().c_str());
+        break;
+      }
+      case 1: {
+        // Generate number string.
+        std::stringstream ss;
+        ss << (rand_gen.NextInt(Smi::kMaxValue) % StubCache::kPrimaryTableSize);
+        name = factory->InternalizeUtf8String(ss.str().c_str());
+        break;
+      }
+      case 2: {
+        // Generate symbol.
+        name = factory->NewSymbol();
+        break;
+      }
+      default:
+        UNREACHABLE();
+    }
+    names.push_back(name);
+  }
+
+  // Generate some number of receiver maps and receivers.
+  for (int i = 0; i < StubCache::kSecondaryTableSize / 2; i++) {
+    Handle<Map> map = Map::Create(isolate, 0);
+    receivers.push_back(factory->NewJSObjectFromMap(map));
+  }
+
+  // Generate some number of handlers.
+  for (int i = 0; i < 30; i++) {
+    Code::Kind code_kind;
+    switch (rand_gen.NextInt(4)) {
+      case 0:
+        code_kind = Code::LOAD_IC;
+        break;
+      case 1:
+        code_kind = Code::KEYED_LOAD_IC;
+        break;
+      case 2:
+        code_kind = Code::STORE_IC;
+        break;
+      case 3:
+        code_kind = Code::KEYED_STORE_IC;
+        break;
+      default:
+        UNREACHABLE();
+    }
+    Code::Flags flags =
+        Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(code_kind));
+    handlers.push_back(CreateCodeWithFlags(flags));
+  }
+
+  // Ensure that GC does happen because from now on we are going to fill our
+  // own stub cache instance with raw values.
+  DisallowHeapAllocation no_gc;
+
+  // Populate {stub_cache}.
+  const int N = StubCache::kPrimaryTableSize + StubCache::kSecondaryTableSize;
+  for (int i = 0; i < N; i++) {
+    int index = rand_gen.NextInt();
+    Handle<Name> name = names[index % names.size()];
+    Handle<JSObject> receiver = receivers[index % receivers.size()];
+    Handle<Code> handler = handlers[index % handlers.size()];
+    stub_cache.Set(*name, receiver->map(), *handler);
+  }
+
+  // Perform some queries.
+  bool queried_existing = false;
+  bool queried_non_existing = false;
+  for (int i = 0; i < N; i++) {
+    int index = rand_gen.NextInt();
+    Handle<Name> name = names[index % names.size()];
+    Handle<JSObject> receiver = receivers[index % receivers.size()];
+    Code* handler = stub_cache.Get(*name, receiver->map(), flags_to_query);
+    if (handler == nullptr) {
+      queried_non_existing = true;
+    } else {
+      queried_existing = true;
+    }
+
+    Handle<Code> expected_handler(handler, isolate);
+    ft.CheckTrue(receiver, name, expected_handler);
+  }
+
+  for (int i = 0; i < N; i++) {
+    int index1 = rand_gen.NextInt();
+    int index2 = rand_gen.NextInt();
+    Handle<Name> name = names[index1 % names.size()];
+    Handle<JSObject> receiver = receivers[index2 % receivers.size()];
+    Code* handler = stub_cache.Get(*name, receiver->map(), flags_to_query);
+    if (handler == nullptr) {
+      queried_non_existing = true;
+    } else {
+      queried_existing = true;
+    }
+
+    Handle<Code> expected_handler(handler, isolate);
+    ft.CheckTrue(receiver, name, expected_handler);
+  }
+  // Ensure we performed both kind of queries.
+  CHECK(queried_existing && queried_non_existing);
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/test/cctest/test-code-stubs-arm.cc b/test/cctest/test-code-stubs-arm.cc
index f59d854..0e0a132 100644
--- a/test/cctest/test-code-stubs-arm.cc
+++ b/test/cctest/test-code-stubs-arm.cc
@@ -78,8 +78,9 @@
   int source_reg_offset = kDoubleSize;
   int reg_num = 0;
   for (; reg_num < Register::kNumRegisters; ++reg_num) {
-    Register reg = Register::from_code(reg_num);
-    if (reg.IsAllocatable()) {
+    if (RegisterConfiguration::Crankshaft()->IsAllocatableGeneralCode(
+            reg_num)) {
+      Register reg = Register::from_code(reg_num);
       if (!reg.is(destination_reg)) {
         __ push(reg);
         source_reg_offset += kPointerSize;
@@ -107,8 +108,9 @@
 
   // Make sure no registers have been unexpectedly clobbered
   for (--reg_num; reg_num >= 0; --reg_num) {
-    Register reg = Register::from_code(reg_num);
-    if (reg.IsAllocatable()) {
+    if (RegisterConfiguration::Crankshaft()->IsAllocatableGeneralCode(
+            reg_num)) {
+      Register reg = Register::from_code(reg_num);
       if (!reg.is(destination_reg)) {
         __ ldr(ip, MemOperand(sp, 0));
         __ cmp(reg, ip);
diff --git a/test/cctest/test-code-stubs-arm64.cc b/test/cctest/test-code-stubs-arm64.cc
index f5a4078..2edb923 100644
--- a/test/cctest/test-code-stubs-arm64.cc
+++ b/test/cctest/test-code-stubs-arm64.cc
@@ -74,8 +74,9 @@
   int source_reg_offset = kDoubleSize;
   int reg_num = 0;
   for (; reg_num < Register::kNumRegisters; ++reg_num) {
-    Register reg = Register::from_code(reg_num);
-    if (reg.IsAllocatable()) {
+    if (RegisterConfiguration::Crankshaft()->IsAllocatableGeneralCode(
+            reg_num)) {
+      Register reg = Register::from_code(reg_num);
       if (!reg.is(destination_reg)) {
         queue.Queue(reg);
         source_reg_offset += kPointerSize;
@@ -103,8 +104,9 @@
 
   // // Make sure no registers have been unexpectedly clobbered
   for (--reg_num; reg_num >= 0; --reg_num) {
-    Register reg = Register::from_code(reg_num);
-    if (reg.IsAllocatable()) {
+    if (RegisterConfiguration::Crankshaft()->IsAllocatableGeneralCode(
+            reg_num)) {
+      Register reg = Register::from_code(reg_num);
       if (!reg.is(destination_reg)) {
         __ Pop(ip0);
         __ cmp(reg, ip0);
diff --git a/test/cctest/test-code-stubs-ia32.cc b/test/cctest/test-code-stubs-ia32.cc
index efc39e9..5a420b1 100644
--- a/test/cctest/test-code-stubs-ia32.cc
+++ b/test/cctest/test-code-stubs-ia32.cc
@@ -72,8 +72,9 @@
   // Save registers make sure they don't get clobbered.
   int reg_num = 0;
   for (; reg_num < Register::kNumRegisters; ++reg_num) {
-    Register reg = Register::from_code(reg_num);
-    if (reg.IsAllocatable()) {
+    if (RegisterConfiguration::Crankshaft()->IsAllocatableGeneralCode(
+            reg_num)) {
+      Register reg = Register::from_code(reg_num);
       if (!reg.is(esp) && !reg.is(ebp) && !reg.is(destination_reg)) {
         __ push(reg);
         param_offset += kPointerSize;
@@ -92,8 +93,9 @@
 
   // Make sure no registers have been unexpectedly clobbered
   for (--reg_num; reg_num >= 0; --reg_num) {
-    Register reg = Register::from_code(reg_num);
-    if (reg.IsAllocatable()) {
+    if (RegisterConfiguration::Crankshaft()->IsAllocatableGeneralCode(
+            reg_num)) {
+      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, kRegisterWasClobbered);
diff --git a/test/cctest/test-code-stubs-mips.cc b/test/cctest/test-code-stubs-mips.cc
index ce577da..149a174 100644
--- a/test/cctest/test-code-stubs-mips.cc
+++ b/test/cctest/test-code-stubs-mips.cc
@@ -82,8 +82,9 @@
   int source_reg_offset = kDoubleSize;
   int reg_num = 2;
   for (; reg_num < Register::kNumRegisters; ++reg_num) {
-    Register reg = Register::from_code(reg_num);
-    if (reg.IsAllocatable()) {
+    if (RegisterConfiguration::Crankshaft()->IsAllocatableGeneralCode(
+            reg_num)) {
+      Register reg = Register::from_code(reg_num);
       if (!reg.is(destination_reg)) {
         __ push(reg);
         source_reg_offset += kPointerSize;
@@ -111,8 +112,9 @@
 
   // Make sure no registers have been unexpectedly clobbered
   for (--reg_num; reg_num >= 2; --reg_num) {
-    Register reg = Register::from_code(reg_num);
-    if (reg.IsAllocatable()) {
+    if (RegisterConfiguration::Crankshaft()->IsAllocatableGeneralCode(
+            reg_num)) {
+      Register reg = Register::from_code(reg_num);
       if (!reg.is(destination_reg)) {
         __ lw(at, MemOperand(sp, 0));
         __ Assert(eq, kRegisterWasClobbered, reg, Operand(at));
diff --git a/test/cctest/test-code-stubs-mips64.cc b/test/cctest/test-code-stubs-mips64.cc
index 97f57b9..bef2171 100644
--- a/test/cctest/test-code-stubs-mips64.cc
+++ b/test/cctest/test-code-stubs-mips64.cc
@@ -81,8 +81,7 @@
   // Save registers make sure they don't get clobbered.
   int source_reg_offset = kDoubleSize;
   int reg_num = 2;
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   for (; reg_num < config->num_allocatable_general_registers(); ++reg_num) {
     Register reg = Register::from_code(reg_num);
     if (!reg.is(destination_reg)) {
diff --git a/test/cctest/test-code-stubs-x64.cc b/test/cctest/test-code-stubs-x64.cc
index 786da54..b9eddd6 100644
--- a/test/cctest/test-code-stubs-x64.cc
+++ b/test/cctest/test-code-stubs-x64.cc
@@ -64,9 +64,7 @@
   __ pushq(rsi);
   __ pushq(rdi);
 
-
-  const RegisterConfiguration* config =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
+  const RegisterConfiguration* config = RegisterConfiguration::Crankshaft();
   if (!source_reg.is(rsp)) {
     // The argument we pass to the stub is not a heap number, but instead
     // stack-allocated and offset-wise made to look like a heap number for
diff --git a/test/cctest/test-code-stubs-x87.cc b/test/cctest/test-code-stubs-x87.cc
index efc39e9..5a420b1 100644
--- a/test/cctest/test-code-stubs-x87.cc
+++ b/test/cctest/test-code-stubs-x87.cc
@@ -72,8 +72,9 @@
   // Save registers make sure they don't get clobbered.
   int reg_num = 0;
   for (; reg_num < Register::kNumRegisters; ++reg_num) {
-    Register reg = Register::from_code(reg_num);
-    if (reg.IsAllocatable()) {
+    if (RegisterConfiguration::Crankshaft()->IsAllocatableGeneralCode(
+            reg_num)) {
+      Register reg = Register::from_code(reg_num);
       if (!reg.is(esp) && !reg.is(ebp) && !reg.is(destination_reg)) {
         __ push(reg);
         param_offset += kPointerSize;
@@ -92,8 +93,9 @@
 
   // Make sure no registers have been unexpectedly clobbered
   for (--reg_num; reg_num >= 0; --reg_num) {
-    Register reg = Register::from_code(reg_num);
-    if (reg.IsAllocatable()) {
+    if (RegisterConfiguration::Crankshaft()->IsAllocatableGeneralCode(
+            reg_num)) {
+      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, kRegisterWasClobbered);
diff --git a/test/cctest/test-compiler.cc b/test/cctest/test-compiler.cc
index 32d720e..28cdda7 100644
--- a/test/cctest/test-compiler.cc
+++ b/test/cctest/test-compiler.cc
@@ -32,6 +32,7 @@
 
 #include "src/compiler.h"
 #include "src/disasm.h"
+#include "src/interpreter/interpreter.h"
 #include "src/parsing/parser.h"
 #include "test/cctest/cctest.h"
 
@@ -305,7 +306,7 @@
   // We shouldn't have deoptimization support. We want to recompile and
   // verify that our feedback vector preserves information.
   CHECK(!f->shared()->has_deoptimization_support());
-  Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector());
+  Handle<TypeFeedbackVector> feedback_vector(f->feedback_vector());
 
   // Verify that we gathered feedback.
   CHECK(!feedback_vector->is_empty());
@@ -320,7 +321,7 @@
   // of the full code.
   CHECK(f->IsOptimized());
   CHECK(f->shared()->has_deoptimization_support());
-  object = f->shared()->feedback_vector()->Get(slot_for_a);
+  object = f->feedback_vector()->Get(slot_for_a);
   CHECK(object->IsWeakCell() &&
         WeakCell::cast(object)->value()->IsJSFunction());
 }
@@ -355,18 +356,16 @@
   // If we are compiling lazily then it should not be compiled, and so no
   // feedback vector allocated yet.
   CHECK(!f->shared()->is_compiled());
-  CHECK(f->shared()->feedback_vector()->is_empty());
+  CHECK(f->feedback_vector()->is_empty());
 
   CompileRun("morphing_call();");
 
   // Now a feedback vector is allocated.
   CHECK(f->shared()->is_compiled());
-  CHECK(!f->shared()->feedback_vector()->is_empty());
+  CHECK(!f->feedback_vector()->is_empty());
 }
 
-
-// Test that optimized code for different closures is actually shared
-// immediately by the FastNewClosureStub when run in the same context.
+// Test that optimized code for different closures is actually shared.
 TEST(OptimizedCodeSharing1) {
   FLAG_stress_compaction = false;
   FLAG_allow_natives_syntax = true;
@@ -385,8 +384,8 @@
         "%DebugPrint(closure0());"
         "%OptimizeFunctionOnNextCall(closure0);"
         "%DebugPrint(closure0());"
-        "var closure1 = MakeClosure();"
-        "var closure2 = MakeClosure();");
+        "var closure1 = MakeClosure(); closure1();"
+        "var closure2 = MakeClosure(); closure2();");
     Handle<JSFunction> fun1 = Handle<JSFunction>::cast(
         v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
             env->Global()
@@ -403,9 +402,7 @@
   }
 }
 
-
-// Test that optimized code for different closures is actually shared
-// immediately by the FastNewClosureStub when run different contexts.
+// Test that optimized code for different closures is actually shared.
 TEST(OptimizedCodeSharing2) {
   if (FLAG_stress_compaction) return;
   FLAG_allow_natives_syntax = true;
@@ -456,8 +453,8 @@
         "%DebugPrint(closure0());"
         "%OptimizeFunctionOnNextCall(closure0);"
         "%DebugPrint(closure0());"
-        "var closure1 = MakeClosure();"
-        "var closure2 = MakeClosure();");
+        "var closure1 = MakeClosure(); closure1();"
+        "var closure2 = MakeClosure(); closure2();");
     Handle<JSFunction> fun1 = Handle<JSFunction>::cast(
         v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
             env->Global()
@@ -475,9 +472,7 @@
   }
 }
 
-
-// Test that optimized code for different closures is actually shared
-// immediately by the FastNewClosureStub without context-dependent entries.
+// Test that optimized code for different closures is actually shared.
 TEST(OptimizedCodeSharing3) {
   if (FLAG_stress_compaction) return;
   FLAG_allow_natives_syntax = true;
@@ -531,8 +526,8 @@
         "%DebugPrint(closure0());"
         "%OptimizeFunctionOnNextCall(closure0);"
         "%DebugPrint(closure0());"
-        "var closure1 = MakeClosure();"
-        "var closure2 = MakeClosure();");
+        "var closure1 = MakeClosure(); closure1();"
+        "var closure2 = MakeClosure(); closure2();");
     Handle<JSFunction> fun1 = Handle<JSFunction>::cast(
         v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
             env->Global()
@@ -763,3 +758,45 @@
   CheckCodeForUnsafeLiteral(GetJSFunction(context->Global(), "f"));
 }
 #endif
+
+static void IsBaselineCompiled(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  Handle<Object> object = v8::Utils::OpenHandle(*args[0]);
+  Handle<JSFunction> function = Handle<JSFunction>::cast(object);
+  bool is_baseline = function->shared()->code()->kind() == Code::FUNCTION;
+  return args.GetReturnValue().Set(is_baseline);
+}
+
+static void InstallIsBaselineCompiledHelper(v8::Isolate* isolate) {
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  v8::Local<v8::FunctionTemplate> t =
+      v8::FunctionTemplate::New(isolate, IsBaselineCompiled);
+  CHECK(context->Global()
+            ->Set(context, v8_str("IsBaselineCompiled"),
+                  t->GetFunction(context).ToLocalChecked())
+            .FromJust());
+}
+
+TEST(IgnitionBaselineOnReturn) {
+  FLAG_allow_natives_syntax = true;
+  FLAG_always_opt = false;
+  CcTest::InitializeVM();
+  FLAG_ignition = true;
+  reinterpret_cast<i::Isolate*>(CcTest::isolate())->interpreter()->Initialize();
+  v8::HandleScope scope(CcTest::isolate());
+  InstallIsBaselineCompiledHelper(CcTest::isolate());
+
+  CompileRun(
+      "var is_baseline_in_function, is_baseline_after_return;\n"
+      "var return_val;\n"
+      "function f() {\n"
+      "  %CompileBaseline(f);\n"
+      "  is_baseline_in_function = IsBaselineCompiled(f);\n"
+      "  return 1234;\n"
+      "};\n"
+      "return_val = f();\n"
+      "is_baseline_after_return = IsBaselineCompiled(f);\n");
+  CHECK_EQ(false, GetGlobalProperty("is_baseline_in_function")->BooleanValue());
+  CHECK_EQ(true, GetGlobalProperty("is_baseline_after_return")->BooleanValue());
+  CHECK_EQ(1234.0, GetGlobalProperty("return_val")->Number());
+}
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index 24c84c3..3bdf8ad 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -31,12 +31,13 @@
 
 #include "include/v8-profiler.h"
 #include "src/base/platform/platform.h"
-#include "src/base/smart-pointers.h"
 #include "src/deoptimizer.h"
 #include "src/profiler/cpu-profiler-inl.h"
+#include "src/profiler/profiler-listener.h"
 #include "src/utils.h"
 #include "test/cctest/cctest.h"
 #include "test/cctest/profiler-extension.h"
+
 using i::CodeEntry;
 using i::CpuProfile;
 using i::CpuProfiler;
@@ -45,10 +46,9 @@
 using i::ProfileGenerator;
 using i::ProfileNode;
 using i::ProfilerEventsProcessor;
+using i::ProfilerListener;
 using i::ScopedVector;
 using i::Vector;
-using v8::base::SmartPointer;
-
 
 // Helper methods
 static v8::Local<v8::Function> GetFunction(v8::Local<v8::Context> env,
@@ -57,30 +57,26 @@
       env->Global()->Get(env, v8_str(name)).ToLocalChecked());
 }
 
-
 static size_t offset(const char* src, const char* substring) {
   const char* it = strstr(src, substring);
   CHECK(it);
   return static_cast<size_t>(it - src);
 }
 
-
 static const char* reason(const i::Deoptimizer::DeoptReason reason) {
   return i::Deoptimizer::GetDeoptReason(reason);
 }
 
-
 TEST(StartStop) {
-  i::Isolate* isolate = CcTest::i_isolate();
-  CpuProfilesCollection profiles(isolate->heap());
+  CpuProfilesCollection profiles(CcTest::i_isolate());
   ProfileGenerator generator(&profiles);
-  SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor(
-      &generator, NULL, v8::base::TimeDelta::FromMicroseconds(100)));
+  std::unique_ptr<ProfilerEventsProcessor> processor(
+      new ProfilerEventsProcessor(&generator, nullptr,
+                                  v8::base::TimeDelta::FromMicroseconds(100)));
   processor->Start();
   processor->StopSynchronously();
 }
 
-
 static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc,
                                    i::Address frame1,
                                    i::Address frame2 = NULL,
@@ -157,46 +153,55 @@
   i::AbstractCode* args3_code = CreateCode(&env);
   i::AbstractCode* args4_code = CreateCode(&env);
 
-  CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate->heap());
+  CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
+  ProfileGenerator* generator = new ProfileGenerator(profiles);
+  ProfilerEventsProcessor* processor = new ProfilerEventsProcessor(
+      generator, nullptr, v8::base::TimeDelta::FromMicroseconds(100));
+  CpuProfiler profiler(isolate, profiles, generator, processor);
   profiles->StartProfiling("", false);
-  ProfileGenerator generator(profiles);
-  SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor(
-          &generator, NULL, v8::base::TimeDelta::FromMicroseconds(100)));
   processor->Start();
-  CpuProfiler profiler(isolate, profiles, &generator, processor.get());
+  ProfilerListener profiler_listener(isolate);
+  isolate->code_event_dispatcher()->AddListener(&profiler_listener);
+  profiler_listener.AddObserver(&profiler);
 
   // Enqueue code creation events.
   const char* aaa_str = "aaa";
   i::Handle<i::String> aaa_name = factory->NewStringFromAsciiChecked(aaa_str);
-  profiler.CodeCreateEvent(i::Logger::FUNCTION_TAG, aaa_code, *aaa_name);
-  profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment_code, "comment");
-  profiler.CodeCreateEvent(i::Logger::STUB_TAG, args5_code, 5);
-  profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment2_code, "comment2");
-  profiler.CodeMoveEvent(comment2_code, moved_code->address());
-  profiler.CodeCreateEvent(i::Logger::STUB_TAG, args3_code, 3);
-  profiler.CodeCreateEvent(i::Logger::STUB_TAG, args4_code, 4);
+  profiler_listener.CodeCreateEvent(i::Logger::FUNCTION_TAG, aaa_code,
+                                    *aaa_name);
+  profiler_listener.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment_code,
+                                    "comment");
+  profiler_listener.CodeCreateEvent(i::Logger::STUB_TAG, args5_code, 5);
+  profiler_listener.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment2_code,
+                                    "comment2");
+  profiler_listener.CodeMoveEvent(comment2_code, moved_code->address());
+  profiler_listener.CodeCreateEvent(i::Logger::STUB_TAG, args3_code, 3);
+  profiler_listener.CodeCreateEvent(i::Logger::STUB_TAG, args4_code, 4);
 
   // Enqueue a tick event to enable code events processing.
-  EnqueueTickSampleEvent(processor.get(), aaa_code->address());
+  EnqueueTickSampleEvent(processor, aaa_code->address());
 
+  profiler_listener.RemoveObserver(&profiler);
+  isolate->code_event_dispatcher()->RemoveListener(&profiler_listener);
   processor->StopSynchronously();
 
   // Check the state of profile generator.
-  CodeEntry* aaa = generator.code_map()->FindEntry(aaa_code->address());
+  CodeEntry* aaa = generator->code_map()->FindEntry(aaa_code->address());
   CHECK(aaa);
   CHECK_EQ(0, strcmp(aaa_str, aaa->name()));
 
-  CodeEntry* comment = generator.code_map()->FindEntry(comment_code->address());
+  CodeEntry* comment =
+      generator->code_map()->FindEntry(comment_code->address());
   CHECK(comment);
   CHECK_EQ(0, strcmp("comment", comment->name()));
 
-  CodeEntry* args5 = generator.code_map()->FindEntry(args5_code->address());
+  CodeEntry* args5 = generator->code_map()->FindEntry(args5_code->address());
   CHECK(args5);
   CHECK_EQ(0, strcmp("5", args5->name()));
 
-  CHECK(!generator.code_map()->FindEntry(comment2_code->address()));
+  CHECK(!generator->code_map()->FindEntry(comment2_code->address()));
 
-  CodeEntry* comment2 = generator.code_map()->FindEntry(moved_code->address());
+  CodeEntry* comment2 = generator->code_map()->FindEntry(moved_code->address());
   CHECK(comment2);
   CHECK_EQ(0, strcmp("comment2", comment2->name()));
 }
@@ -216,29 +221,32 @@
   i::AbstractCode* frame2_code = CreateCode(&env);
   i::AbstractCode* frame3_code = CreateCode(&env);
 
-  CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate->heap());
+  CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
+  ProfileGenerator* generator = new ProfileGenerator(profiles);
+  ProfilerEventsProcessor* processor = new ProfilerEventsProcessor(
+      generator, nullptr, v8::base::TimeDelta::FromMicroseconds(100));
+  CpuProfiler profiler(isolate, profiles, generator, processor);
   profiles->StartProfiling("", false);
-  ProfileGenerator generator(profiles);
-  SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor(
-          &generator, NULL, v8::base::TimeDelta::FromMicroseconds(100)));
   processor->Start();
-  CpuProfiler profiler(isolate, profiles, &generator, processor.get());
+  ProfilerListener profiler_listener(isolate);
+  isolate->code_event_dispatcher()->AddListener(&profiler_listener);
+  profiler_listener.AddObserver(&profiler);
 
-  profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame1_code, "bbb");
-  profiler.CodeCreateEvent(i::Logger::STUB_TAG, frame2_code, 5);
-  profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame3_code, "ddd");
+  profiler_listener.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame1_code, "bbb");
+  profiler_listener.CodeCreateEvent(i::Logger::STUB_TAG, frame2_code, 5);
+  profiler_listener.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame3_code, "ddd");
 
-  EnqueueTickSampleEvent(processor.get(), frame1_code->instruction_start());
+  EnqueueTickSampleEvent(processor, frame1_code->instruction_start());
   EnqueueTickSampleEvent(
-      processor.get(),
+      processor,
       frame2_code->instruction_start() + frame2_code->ExecutableSize() / 2,
       frame1_code->instruction_start() + frame2_code->ExecutableSize() / 2);
-  EnqueueTickSampleEvent(
-      processor.get(),
-      frame3_code->instruction_end() - 1,
-      frame2_code->instruction_end() - 1,
-      frame1_code->instruction_end() - 1);
+  EnqueueTickSampleEvent(processor, frame3_code->instruction_end() - 1,
+                         frame2_code->instruction_end() - 1,
+                         frame1_code->instruction_end() - 1);
 
+  profiler_listener.RemoveObserver(&profiler);
+  isolate->code_event_dispatcher()->RemoveListener(&profiler_listener);
   processor->StopSynchronously();
   CpuProfile* profile = profiles->StopProfiling("");
   CHECK(profile);
@@ -259,6 +267,8 @@
   const i::List<ProfileNode*>* top_down_ddd_children =
       top_down_stub_children->last()->children();
   CHECK_EQ(0, top_down_ddd_children->length());
+
+  isolate->code_event_dispatcher()->RemoveListener(&profiler_listener);
 }
 
 // http://crbug/51594
@@ -283,15 +293,18 @@
 
   i::AbstractCode* code = CreateCode(&env);
 
-  CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate->heap());
+  CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
+  ProfileGenerator* generator = new ProfileGenerator(profiles);
+  ProfilerEventsProcessor* processor = new ProfilerEventsProcessor(
+      generator, nullptr, v8::base::TimeDelta::FromMicroseconds(100));
+  CpuProfiler profiler(isolate, profiles, generator, processor);
   profiles->StartProfiling("", false);
-  ProfileGenerator generator(profiles);
-  SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor(
-          &generator, NULL, v8::base::TimeDelta::FromMicroseconds(100)));
   processor->Start();
-  CpuProfiler profiler(isolate, profiles, &generator, processor.get());
+  ProfilerListener profiler_listener(isolate);
+  isolate->code_event_dispatcher()->AddListener(&profiler_listener);
+  profiler_listener.AddObserver(&profiler);
 
-  profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, code, "bbb");
+  profiler_listener.CodeCreateEvent(i::Logger::BUILTIN_TAG, code, "bbb");
 
   i::TickSample* sample = processor->StartTickSample();
   sample->pc = code->address();
@@ -302,6 +315,8 @@
   }
   processor->FinishTickSample();
 
+  profiler_listener.RemoveObserver(&profiler);
+  isolate->code_event_dispatcher()->RemoveListener(&profiler_listener);
   processor->StopSynchronously();
   CpuProfile* profile = profiles->StopProfiling("");
   CHECK(profile);
@@ -422,7 +437,7 @@
   cpu_profiler->SetSamplingInterval(100);
   cpu_profiler->StartProfiling(profile_name, collect_samples);
 
-  i::Sampler* sampler =
+  v8::sampler::Sampler* sampler =
       reinterpret_cast<i::Isolate*>(env->GetIsolate())->logger()->sampler();
   sampler->StartCountingSamples();
   do {
@@ -461,8 +476,7 @@
   const v8::CpuProfileNode* result = FindChild(context, node, name);
   if (!result) {
     char buffer[100];
-    i::SNPrintF(Vector<char>(buffer, arraysize(buffer)),
-                "Failed to GetChild: %s", name);
+    i::SNPrintF(i::ArrayVector(buffer), "Failed to GetChild: %s", name);
     FATAL(buffer);
   }
   return result;
@@ -1022,31 +1036,36 @@
   i::Address code_address = code->instruction_start();
   CHECK(code_address);
 
-  CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate->heap());
+  CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
+  ProfileGenerator* generator = new ProfileGenerator(profiles);
+  ProfilerEventsProcessor* processor = new ProfilerEventsProcessor(
+      generator, nullptr, v8::base::TimeDelta::FromMicroseconds(100));
+  CpuProfiler profiler(isolate, profiles, generator, processor);
   profiles->StartProfiling("", false);
-  ProfileGenerator generator(profiles);
-  SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor(
-      &generator, NULL, v8::base::TimeDelta::FromMicroseconds(100)));
   processor->Start();
-  CpuProfiler profiler(isolate, profiles, &generator, processor.get());
+  ProfilerListener profiler_listener(isolate);
+  isolate->code_event_dispatcher()->AddListener(&profiler_listener);
+  profiler_listener.AddObserver(&profiler);
 
   // Enqueue code creation events.
   i::Handle<i::String> str = factory->NewStringFromAsciiChecked(func_name);
   int line = 1;
   int column = 1;
-  profiler.CodeCreateEvent(i::Logger::FUNCTION_TAG, code, func->shared(), NULL,
-                           *str, line, column);
+  profiler_listener.CodeCreateEvent(i::Logger::FUNCTION_TAG, code,
+                                    func->shared(), *str, line, column);
 
   // Enqueue a tick event to enable code events processing.
-  EnqueueTickSampleEvent(processor.get(), code_address);
+  EnqueueTickSampleEvent(processor, code_address);
 
+  profiler_listener.RemoveObserver(&profiler);
+  isolate->code_event_dispatcher()->RemoveListener(&profiler_listener);
   processor->StopSynchronously();
 
   CpuProfile* profile = profiles->StopProfiling("");
   CHECK(profile);
 
   // Check the state of profile generator.
-  CodeEntry* func_entry = generator.code_map()->FindEntry(code_address);
+  CodeEntry* func_entry = generator->code_map()->FindEntry(code_address);
   CHECK(func_entry);
   CHECK_EQ(0, strcmp(func_name, func_entry->name()));
   const i::JITLineInfoTable* line_info = func_entry->line_info();
@@ -1132,8 +1151,8 @@
   const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
   GetChild(env.local(), start_node, "bar");
 
-  const v8::CpuProfileNode* unresolved_node = FindChild(
-      env.local(), root, i::ProfileGenerator::kUnresolvedFunctionName);
+  const v8::CpuProfileNode* unresolved_node =
+      FindChild(env.local(), root, i::CodeEntry::kUnresolvedFunctionName);
   CHECK(!unresolved_node || GetChild(env.local(), unresolved_node, "call"));
 
   profile->Delete();
@@ -1188,8 +1207,8 @@
       GetChild(env.local(), start_node, "test");
   GetChild(env.local(), test_node, "bar");
 
-  const v8::CpuProfileNode* unresolved_node = FindChild(
-      env.local(), start_node, ProfileGenerator::kUnresolvedFunctionName);
+  const v8::CpuProfileNode* unresolved_node =
+      FindChild(env.local(), start_node, CodeEntry::kUnresolvedFunctionName);
   CHECK(!unresolved_node || GetChild(env.local(), unresolved_node, "apply"));
 
   profile->Delete();
@@ -1596,12 +1615,12 @@
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
   const v8::CpuProfileNode* program_node =
-      GetChild(env.local(), root, ProfileGenerator::kProgramEntryName);
+      GetChild(env.local(), root, CodeEntry::kProgramEntryName);
   CHECK_EQ(0, program_node->GetChildrenCount());
   CHECK_GE(program_node->GetHitCount(), 2u);
 
   const v8::CpuProfileNode* idle_node =
-      GetChild(env.local(), root, ProfileGenerator::kIdleEntryName);
+      GetChild(env.local(), root, CodeEntry::kIdleEntryName);
   CHECK_EQ(0, idle_node->GetChildrenCount());
   CHECK_GE(idle_node->GetHitCount(), 3u);
 
diff --git a/test/cctest/test-date.cc b/test/cctest/test-date.cc
index 67b9501..a745949 100644
--- a/test/cctest/test-date.cc
+++ b/test/cctest/test-date.cc
@@ -166,3 +166,52 @@
   CheckDST(august_20 + 2 * 3600 - 1000);
   CheckDST(august_20);
 }
+
+namespace {
+int legacy_parse_count = 0;
+void DateParseLegacyCounterCallback(v8::Isolate* isolate,
+                                    v8::Isolate::UseCounterFeature feature) {
+  if (feature == v8::Isolate::kLegacyDateParser) legacy_parse_count++;
+}
+}  // anonymous namespace
+
+TEST(DateParseLegacyUseCounter) {
+  CcTest::InitializeVM();
+  v8::HandleScope scope(CcTest::isolate());
+  LocalContext context;
+  CcTest::isolate()->SetUseCounterCallback(DateParseLegacyCounterCallback);
+  CHECK_EQ(0, legacy_parse_count);
+  CompileRun("Date.parse('2015-02-31')");
+  CHECK_EQ(0, legacy_parse_count);
+  CompileRun("Date.parse('2015-02-31T11:22:33.444Z01:23')");
+  CHECK_EQ(0, legacy_parse_count);
+  CompileRun("Date.parse('2015-02-31T11:22:33.444')");
+  CHECK_EQ(0, legacy_parse_count);
+  CompileRun("Date.parse('2000 01 01')");
+  CHECK_EQ(1, legacy_parse_count);
+  CompileRun("Date.parse('2015-02-31T11:22:33.444     ')");
+  CHECK_EQ(1, legacy_parse_count);
+}
+
+#ifdef V8_I18N_SUPPORT
+TEST(DateCacheVersion) {
+  FLAG_allow_natives_syntax = true;
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::Isolate::Scope isolate_scope(isolate);
+  v8::HandleScope scope(isolate);
+  v8::Local<v8::Context> context = v8::Context::New(isolate);
+  v8::Context::Scope context_scope(context);
+  v8::Local<v8::Number> date_cache_version =
+      v8::Local<v8::Number>::Cast(CompileRun("%DateCacheVersion()"));
+
+  CHECK(date_cache_version->IsNumber());
+  CHECK_EQ(0.0, date_cache_version->NumberValue(context).FromMaybe(-1.0));
+
+  v8::Date::DateTimeConfigurationChangeNotification(isolate);
+
+  date_cache_version =
+      v8::Local<v8::Number>::Cast(CompileRun("%DateCacheVersion()"));
+  CHECK(date_cache_version->IsNumber());
+  CHECK_EQ(1.0, date_cache_version->NumberValue(context).FromMaybe(-1.0));
+}
+#endif  // V8_I18N_SUPPORT
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index ab27f39..3ed6ec8 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -6081,53 +6081,48 @@
   ::v8::internal::EmbeddedVector<uint16_t, 1> empty_;
 };
 
-
-TEST(DebugGetLoadedScripts) {
+TEST(DebugScriptLineEndsAreAscending) {
   DebugLocalContext env;
-  v8::HandleScope scope(env->GetIsolate());
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
   env.ExposeDebug();
 
-  v8::Local<v8::Context> context = env.context();
-  EmptyExternalStringResource source_ext_str;
-  v8::Local<v8::String> source =
-      v8::String::NewExternalTwoByte(env->GetIsolate(), &source_ext_str)
-          .ToLocalChecked();
-  CHECK(v8::Script::Compile(context, source).IsEmpty());
-  Handle<i::ExternalTwoByteString> i_source(
-      i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source)));
-  // This situation can happen if source was an external string disposed
-  // by its owner.
-  i_source->set_resource(0);
+  // Compile a test script.
+  v8::Local<v8::String> script = v8_str(isolate,
+                                        "function f() {\n"
+                                        "  debugger;\n"
+                                        "}\n");
 
-  bool allow_natives_syntax = i::FLAG_allow_natives_syntax;
-  i::FLAG_allow_natives_syntax = true;
-  EnableDebugger(env->GetIsolate());
-  v8::MaybeLocal<v8::Value> result =
-      CompileRun(env.context(),
-                 "var scripts = %DebugGetLoadedScripts();"
-                 "var count = scripts.length;"
-                 "for (var i = 0; i < count; ++i) {"
-                 "  var lines = scripts[i].lineCount();"
-                 "  if (lines < 1) throw 'lineCount';"
-                 "  var last = -1;"
-                 "  for (var j = 0; j < lines; ++j) {"
-                 "    var end = scripts[i].lineEnd(j);"
-                 "    if (last >= end) throw 'lineEnd';"
-                 "    last = end;"
-                 "  }"
-                 "}");
-  CHECK(!result.IsEmpty());
-  DisableDebugger(env->GetIsolate());
-  // Must not crash while accessing line_ends.
-  i::FLAG_allow_natives_syntax = allow_natives_syntax;
+  v8::ScriptOrigin origin1 = v8::ScriptOrigin(v8_str(isolate, "name"));
+  v8::Local<v8::Script> script1 =
+      v8::Script::Compile(env.context(), script, &origin1).ToLocalChecked();
+  USE(script1);
 
-  // Some scripts are retrieved - at least the number of native scripts.
-  CHECK_GT(env->Global()
-               ->Get(context, v8_str(env->GetIsolate(), "count"))
-               .ToLocalChecked()
-               ->Int32Value(context)
-               .FromJust(),
-           8);
+  Handle<v8::internal::FixedArray> instances;
+  {
+    v8::internal::Debug* debug = CcTest::i_isolate()->debug();
+    v8::internal::DebugScope debug_scope(debug);
+    CHECK(!debug_scope.failed());
+    instances = debug->GetLoadedScripts();
+  }
+
+  CHECK_GT(instances->length(), 0);
+  for (int i = 0; i < instances->length(); i++) {
+    Handle<v8::internal::Script> script = Handle<v8::internal::Script>(
+        v8::internal::Script::cast(instances->get(i)));
+
+    v8::internal::Script::InitLineEnds(script);
+    v8::internal::FixedArray* ends =
+        v8::internal::FixedArray::cast(script->line_ends());
+    CHECK_GT(ends->length(), 0);
+
+    int prev_end = -1;
+    for (int j = 0; j < ends->length(); j++) {
+      const int curr_end = v8::internal::Smi::cast(ends->get(j))->value();
+      CHECK_GT(curr_end, prev_end);
+      prev_end = curr_end;
+    }
+  }
 }
 
 
@@ -7185,6 +7180,40 @@
   CHECK(context.IsEmpty());
 }
 
+static void DebugEventCheckContext(
+    const v8::Debug::EventDetails& event_details) {
+  if (event_details.GetEvent() == v8::Break) {
+    v8::Isolate* isolate = event_details.GetIsolate();
+    CHECK(v8::Debug::GetDebuggedContext(isolate)
+              .ToLocalChecked()
+              ->Global()
+              ->Equals(isolate->GetCurrentContext(),
+                       event_details.GetEventContext()->Global())
+              .FromJust());
+  }
+}
+
+static void CheckContext(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  CHECK(v8::Debug::GetDebuggedContext(args.GetIsolate()).IsEmpty());
+}
+
+TEST(DebuggedContext) {
+  DebugLocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+
+  v8::Debug::SetDebugEventListener(isolate, DebugEventCheckContext);
+
+  v8::Local<v8::Function> foo =
+      CompileFunction(&env, "function foo(){bar=0;}", "foo");
+
+  SetBreakPoint(foo, 0);
+  foo->Call(env.context(), env->Global(), 0, nullptr).ToLocalChecked();
+
+  v8::Local<v8::Function> fun = v8::FunctionTemplate::New(isolate, CheckContext)
+                                    ->GetFunction(env.context())
+                                    .ToLocalChecked();
+  fun->Call(env.context(), env->Global(), 0, nullptr).ToLocalChecked();
+}
 
 static v8::Local<v8::Value> expected_callback_data;
 static void DebugEventContextChecker(const v8::Debug::EventDetails& details) {
@@ -7834,8 +7863,8 @@
   CompileRun("var p = new Promise(function(res, rej) { fun(); res(); });");
   CompileRun(
       "var r;"
-      "p.chain(function() { r = 'resolved'; },"
-      "        function() { r = 'rejected'; });");
+      "p.then(function() { r = 'resolved'; },"
+      "       function() { r = 'rejected'; });");
   CHECK(CompileRun("r")->Equals(context, v8_str("resolved")).FromJust());
 }
 
@@ -7874,45 +7903,14 @@
   CompileRun("var p = new Promise(function(res, rej) { fun(); res(); });");
   CompileRun(
       "var r;"
-      "p.chain(function() { r = 'resolved'; },"
-      "        function(e) { r = 'rejected' + e; });");
+      "p.then(function() { r = 'resolved'; },"
+      "       function(e) { r = 'rejected' + e; });");
   CHECK(
       CompileRun("r")->Equals(context, v8_str("rejectedrejection")).FromJust());
   CHECK_EQ(1, exception_event_counter);
 }
 
 
-TEST(DebugBreakOnExceptionInObserveCallback) {
-  i::FLAG_harmony_object_observe = true;
-  DebugLocalContext env;
-  v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope scope(isolate);
-  v8::Debug::SetDebugEventListener(isolate, &DebugEventCountException);
-  v8::Local<v8::Context> context = env.context();
-  // Break on uncaught exception
-  ChangeBreakOnException(false, true);
-  exception_event_counter = 0;
-
-  v8::Local<v8::FunctionTemplate> fun =
-      v8::FunctionTemplate::New(isolate, ThrowCallback);
-  CHECK(env->Global()
-            ->Set(context, v8_str("fun"),
-                  fun->GetFunction(context).ToLocalChecked())
-            .FromJust());
-
-  CompileRun(
-      "var obj = {};"
-      "var callbackRan = false;"
-      "Object.observe(obj, function() {"
-      "   callbackRan = true;"
-      "   throw Error('foo');"
-      "});"
-      "obj.prop = 1");
-  CHECK(CompileRun("callbackRan")->BooleanValue(context).FromJust());
-  CHECK_EQ(1, exception_event_counter);
-}
-
-
 static void DebugHarmonyScopingListener(
     const v8::Debug::EventDetails& event_details) {
   v8::DebugEvent event = event_details.GetEvent();
@@ -8185,3 +8183,36 @@
   ExpectString("JSON.stringify(log)",
                "[\"a4\",\"b2\",\"c4\",\"e0\",\"e0\",\"e0\",\"e0\",\"f0\"]");
 }
+
+size_t current_action = 0;
+StepAction actions[] = {StepNext, StepNext};
+static void DebugStepOverFunctionWithCaughtExceptionListener(
+    const v8::Debug::EventDetails& event_details) {
+  v8::DebugEvent event = event_details.GetEvent();
+  if (event != v8::Break) return;
+  ++break_point_hit_count;
+  if (current_action >= 2) return;
+  PrepareStep(actions[current_action]);
+}
+
+TEST(DebugStepOverFunctionWithCaughtException) {
+  i::FLAG_allow_natives_syntax = true;
+
+  DebugLocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::HandleScope scope(isolate);
+  v8::Debug::SetDebugEventListener(
+      isolate, DebugStepOverFunctionWithCaughtExceptionListener);
+
+  break_point_hit_count = 0;
+  CompileRun(
+      "function foo() {\n"
+      "  try { throw new Error(); } catch (e) {}\n"
+      "}\n"
+      "debugger;\n"
+      "foo();\n"
+      "foo();\n");
+
+  v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
+  CHECK_EQ(break_point_hit_count, 4);
+}
diff --git a/test/cctest/test-dictionary.cc b/test/cctest/test-dictionary.cc
index cc4a753..28adc7b 100644
--- a/test/cctest/test-dictionary.cc
+++ b/test/cctest/test-dictionary.cc
@@ -35,7 +35,7 @@
 #include "src/global-handles.h"
 #include "src/macro-assembler.h"
 #include "src/objects.h"
-#include "test/cctest/heap/utils-inl.h"
+#include "test/cctest/heap/heap-utils.h"
 
 using namespace v8::internal;
 
@@ -89,7 +89,7 @@
   // code should not be found.
   for (int i = 0; i < 100; i++) {
     Handle<JSReceiver> key = factory->NewJSArray(7);
-    CHECK(JSReceiver::GetOrCreateIdentityHash(key)->IsSmi());
+    CHECK(JSReceiver::GetOrCreateIdentityHash(isolate, key)->IsSmi());
     CHECK_EQ(table->FindEntry(key), HashMap::kNotFound);
     CHECK_EQ(table->Lookup(key), CcTest::heap()->the_hole_value());
     CHECK(JSReceiver::GetIdentityHash(isolate, key)->IsSmi());
@@ -100,8 +100,8 @@
   for (int i = 0; i < 100; i++) {
     Handle<JSReceiver> key = factory->NewJSArray(7);
     CHECK_EQ(table->Lookup(key), CcTest::heap()->the_hole_value());
-    Handle<Object> identity_hash = JSReceiver::GetIdentityHash(isolate, key);
-    CHECK_EQ(CcTest::heap()->undefined_value(), *identity_hash);
+    Object* identity_hash = JSReceiver::GetIdentityHash(isolate, key);
+    CHECK_EQ(CcTest::heap()->undefined_value(), identity_hash);
   }
 }
 
@@ -175,8 +175,8 @@
 
   // Simulate a full heap so that generating an identity hash code
   // in subsequent calls will request GC.
-  SimulateFullSpace(CcTest::heap()->new_space());
-  SimulateFullSpace(CcTest::heap()->old_space());
+  heap::SimulateFullSpace(CcTest::heap()->new_space());
+  heap::SimulateFullSpace(CcTest::heap()->old_space());
 
   // Calling Contains() should not cause GC ever.
   int gc_count = isolate->heap()->gc_count();
@@ -206,11 +206,11 @@
 
   // Simulate a full heap so that generating an identity hash code
   // in subsequent calls will request GC.
-  SimulateFullSpace(CcTest::heap()->new_space());
-  SimulateFullSpace(CcTest::heap()->old_space());
+  heap::SimulateFullSpace(CcTest::heap()->new_space());
+  heap::SimulateFullSpace(CcTest::heap()->old_space());
 
   // Calling Lookup() should not cause GC ever.
-  CHECK(table->Lookup(key)->IsTheHole());
+  CHECK(table->Lookup(key)->IsTheHole(isolate));
 
   // Calling Put() should request GC by returning a failure.
   int gc_count = isolate->heap()->gc_count();
diff --git a/test/cctest/test-disasm-arm.cc b/test/cctest/test-disasm-arm.cc
index 7eea8a1..d5f5949 100644
--- a/test/cctest/test-disasm-arm.cc
+++ b/test/cctest/test-disasm-arm.cc
@@ -399,15 +399,6 @@
     COMPARE(bfi(r1, r0, 31, 1),
             "e7df1f90       bfi r1, r0, #31, #1");
 
-    COMPARE(usat(r0, 1, Operand(r1)),
-            "e6e10011       usat r0, #1, r1");
-    COMPARE(usat(r2, 7, Operand(lr)),
-            "e6e7201e       usat r2, #7, lr");
-    COMPARE(usat(r3, 31, Operand(r4, LSL, 31)),
-            "e6ff3f94       usat r3, #31, r4, lsl #31");
-    COMPARE(usat(r8, 0, Operand(r5, ASR, 17)),
-            "e6e088d5       usat r8, #0, r5, asr #17");
-
     COMPARE(pkhbt(r3, r4, Operand(r5, LSL, 17)),
             "e6843895       pkhbt r3, r4, r5, lsl #17");
     COMPARE(pkhtb(r3, r4, Operand(r5, ASR, 17)),
@@ -443,6 +434,15 @@
     COMPARE(rbit(r10, ip), "e6ffaf3c       rbit r10, ip");
   }
 
+  COMPARE(usat(r0, 1, Operand(r1)),
+          "e6e10011       usat r0, #1, r1");
+  COMPARE(usat(r2, 7, Operand(lr)),
+          "e6e7201e       usat r2, #7, lr");
+  COMPARE(usat(r3, 31, Operand(r4, LSL, 31)),
+          "e6ff3f94       usat r3, #31, r4, lsl #31");
+  COMPARE(usat(r8, 0, Operand(r5, ASR, 17)),
+          "e6e088d5       usat r8, #0, r5, asr #17");
+
   COMPARE(smmla(r0, r1, r2, r3), "e7503211       smmla r0, r1, r2, r3");
   COMPARE(smmla(r10, r9, r8, r7), "e75a7819       smmla r10, r9, r8, r7");
 
@@ -860,6 +860,51 @@
 }
 
 
+TEST(ARMv8_vselX_disasm) {
+  SET_UP();
+
+  if (CpuFeatures::IsSupported(ARMv8)) {
+    // Native instructions.
+    COMPARE(vsel(eq, d0, d1, d2),
+            "fe010b02       vseleq.f64 d0, d1, d2");
+    COMPARE(vsel(eq, s0, s1, s2),
+            "fe000a81       vseleq.f32 s0, s1, s2");
+    COMPARE(vsel(ge, d0, d1, d2),
+            "fe210b02       vselge.f64 d0, d1, d2");
+    COMPARE(vsel(ge, s0, s1, s2),
+            "fe200a81       vselge.f32 s0, s1, s2");
+    COMPARE(vsel(gt, d0, d1, d2),
+            "fe310b02       vselgt.f64 d0, d1, d2");
+    COMPARE(vsel(gt, s0, s1, s2),
+            "fe300a81       vselgt.f32 s0, s1, s2");
+    COMPARE(vsel(vs, d0, d1, d2),
+            "fe110b02       vselvs.f64 d0, d1, d2");
+    COMPARE(vsel(vs, s0, s1, s2),
+            "fe100a81       vselvs.f32 s0, s1, s2");
+
+    // Inverted conditions (and swapped inputs).
+    COMPARE(vsel(ne, d0, d1, d2),
+            "fe020b01       vseleq.f64 d0, d2, d1");
+    COMPARE(vsel(ne, s0, s1, s2),
+            "fe010a20       vseleq.f32 s0, s2, s1");
+    COMPARE(vsel(lt, d0, d1, d2),
+            "fe220b01       vselge.f64 d0, d2, d1");
+    COMPARE(vsel(lt, s0, s1, s2),
+            "fe210a20       vselge.f32 s0, s2, s1");
+    COMPARE(vsel(le, d0, d1, d2),
+            "fe320b01       vselgt.f64 d0, d2, d1");
+    COMPARE(vsel(le, s0, s1, s2),
+            "fe310a20       vselgt.f32 s0, s2, s1");
+    COMPARE(vsel(vc, d0, d1, d2),
+            "fe120b01       vselvs.f64 d0, d2, d1");
+    COMPARE(vsel(vc, s0, s1, s2),
+            "fe110a20       vselvs.f32 s0, s2, s1");
+  }
+
+  VERIFY_RUN();
+}
+
+
 TEST(Neon) {
   SET_UP();
 
@@ -1126,3 +1171,17 @@
 
   VERIFY_RUN();
 }
+
+
+TEST(LoadStoreExclusive) {
+  SET_UP();
+
+  COMPARE(ldrexb(r0, r1), "e1d10f9f       ldrexb r0, [r1]");
+  COMPARE(strexb(r0, r1, r2), "e1c20f91       strexb r0, r1, [r2]");
+  COMPARE(ldrexh(r0, r1), "e1f10f9f       ldrexh r0, [r1]");
+  COMPARE(strexh(r0, r1, r2), "e1e20f91       strexh r0, r1, [r2]");
+  COMPARE(ldrex(r0, r1), "e1910f9f       ldrex r0, [r1]");
+  COMPARE(strex(r0, r1, r2), "e1820f91       strex r0, r1, [r2]");
+
+  VERIFY_RUN();
+}
diff --git a/test/cctest/test-disasm-arm64.cc b/test/cctest/test-disasm-arm64.cc
index beca93e..c3653bd 100644
--- a/test/cctest/test-disasm-arm64.cc
+++ b/test/cctest/test-disasm-arm64.cc
@@ -1259,6 +1259,24 @@
   CLEANUP();
 }
 
+TEST_(load_store_acquire_release) {
+  SET_UP_MASM();
+
+  COMPARE(ldar(w0, x1), "ldar w0, [x1]");
+  COMPARE(ldarb(w2, x3), "ldarb w2, [x3]");
+  COMPARE(ldarh(w4, x5), "ldarh w4, [x5]");
+  COMPARE(ldaxr(w6, x7), "ldaxr w6, [x7]");
+  COMPARE(ldaxrb(w8, x9), "ldaxrb w8, [x9]");
+  COMPARE(ldaxrh(w10, x11), "ldaxrh w10, [x11]");
+  COMPARE(stlr(w12, x13), "stlr w12, [x13]");
+  COMPARE(stlrb(w14, x15), "stlrb w14, [x15]");
+  COMPARE(stlrh(w16, x17), "stlrh w16, [x17]");
+  COMPARE(stlxr(w18, w19, x20), "stlxr w18, w19, [x20]");
+  COMPARE(stlxrb(w21, w22, x23), "stlxrb w21, w22, [x23]");
+  COMPARE(stlxrh(w24, w25, x26), "stlxrh w24, w25, [x26]");
+
+  CLEANUP();
+}
 
 #if 0  // TODO(all): enable.
 TEST_(load_literal) {
diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc
index f96eb00..5bd11bc 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -29,11 +29,11 @@
 
 #include "src/v8.h"
 
+#include "src/code-factory.h"
 #include "src/debug/debug.h"
 #include "src/disasm.h"
 #include "src/disassembler.h"
 #include "src/ia32/frames-ia32.h"
-#include "src/ic/ic.h"
 #include "src/macro-assembler.h"
 #include "test/cctest/cctest.h"
 
@@ -290,7 +290,7 @@
   __ bind(&L2);
   __ call(Operand(ebx, ecx, times_4, 10000));
   __ nop();
-  Handle<Code> ic(LoadIC::initialize_stub(isolate, NOT_INSIDE_TYPEOF));
+  Handle<Code> ic(CodeFactory::LoadIC(isolate).code());
   __ call(ic, RelocInfo::CODE_TARGET);
   __ nop();
   __ call(FUNCTION_ADDR(DummyStaticFunction), RelocInfo::RUNTIME_ENTRY);
@@ -665,12 +665,30 @@
 
   // xchg.
   {
+    __ xchg_b(eax, Operand(eax, 8));
+    __ xchg_w(eax, Operand(ebx, 8));
     __ xchg(eax, eax);
     __ xchg(eax, ebx);
     __ xchg(ebx, ebx);
     __ xchg(ebx, Operand(esp, 12));
   }
 
+  // cmpxchg.
+  {
+    __ cmpxchg_b(Operand(esp, 12), eax);
+    __ cmpxchg_w(Operand(ebx, ecx, times_4, 10000), eax);
+    __ cmpxchg(Operand(ebx, ecx, times_4, 10000), eax);
+  }
+
+  // lock prefix.
+  {
+    __ lock();
+    __ cmpxchg(Operand(esp, 12), ebx);
+
+    __ lock();
+    __ xchg_w(eax, Operand(ecx, 8));
+  }
+
   // Nop instructions
   for (int i = 0; i < 16; i++) {
     __ Nop(i);
diff --git a/test/cctest/test-disasm-mips.cc b/test/cctest/test-disasm-mips.cc
index 9a7d8ae..b4f81ec 100644
--- a/test/cctest/test-disasm-mips.cc
+++ b/test/cctest/test-disasm-mips.cc
@@ -97,7 +97,6 @@
     V8_Fatal(__FILE__, __LINE__, "MIPS Disassembler tests failed.\n"); \
   }
 
-
 #define COMPARE_PC_REL_COMPACT(asm_, compare_string, offset)                   \
   {                                                                            \
     int pc_offset = assm.pc_offset();                                          \
@@ -106,28 +105,28 @@
     prev_instr_compact_branch = assm.IsPrevInstrCompactBranch();               \
     if (prev_instr_compact_branch) {                                           \
       snprintf(str_with_address, sizeof(str_with_address), "%s -> %p",         \
-               compare_string, progcounter + 8 + (offset * 4));                \
+               compare_string,                                                 \
+               static_cast<void *>(progcounter + 8 + (offset * 4)));           \
     } else {                                                                   \
       snprintf(str_with_address, sizeof(str_with_address), "%s -> %p",         \
-               compare_string, progcounter + 4 + (offset * 4));                \
+               compare_string,                                                 \
+               static_cast<void *>(progcounter + 4 + (offset * 4)));           \
     }                                                                          \
     assm.asm_;                                                                 \
     if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \
   }
 
-
 #define COMPARE_PC_REL(asm_, compare_string, offset)                           \
   {                                                                            \
     int pc_offset = assm.pc_offset();                                          \
     byte *progcounter = &buffer[pc_offset];                                    \
     char str_with_address[100];                                                \
     snprintf(str_with_address, sizeof(str_with_address), "%s -> %p",           \
-             compare_string, progcounter + (offset * 4));                      \
+             compare_string, static_cast<void *>(progcounter + (offset * 4))); \
     assm.asm_;                                                                 \
     if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \
   }
 
-
 #define COMPARE_PC_JUMP(asm_, compare_string, target)                          \
   {                                                                            \
     int pc_offset = assm.pc_offset();                                          \
@@ -136,14 +135,13 @@
     int instr_index = (target >> 2) & kImm26Mask;                              \
     snprintf(                                                                  \
         str_with_address, sizeof(str_with_address), "%s %p -> %p",             \
-        compare_string, reinterpret_cast<byte *>(target),                      \
-        reinterpret_cast<byte *>(((uint32_t)(progcounter + 4) & ~0xfffffff) |  \
+        compare_string, reinterpret_cast<void *>(target),                      \
+        reinterpret_cast<void *>(((uint32_t)(progcounter + 4) & ~0xfffffff) |  \
                                  (instr_index << 2)));                         \
     assm.asm_;                                                                 \
     if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \
   }
 
-
 #define GET_PC_REGION(pc_region)                                         \
   {                                                                      \
     int pc_offset = assm.pc_offset();                                    \
@@ -780,6 +778,20 @@
   }
 
   if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
+    COMPARE(seb(a0, a1), "7c052420       seb     a0, a1");
+    COMPARE(seb(s6, s7), "7c17b420       seb     s6, s7");
+    COMPARE(seb(v0, v1), "7c031420       seb     v0, v1");
+
+    COMPARE(seh(a0, a1), "7c052620       seh     a0, a1");
+    COMPARE(seh(s6, s7), "7c17b620       seh     s6, s7");
+    COMPARE(seh(v0, v1), "7c031620       seh     v0, v1");
+
+    COMPARE(wsbh(a0, a1), "7c0520a0       wsbh    a0, a1");
+    COMPARE(wsbh(s6, s7), "7c17b0a0       wsbh    s6, s7");
+    COMPARE(wsbh(v0, v1), "7c0310a0       wsbh    v0, v1");
+  }
+
+  if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
     COMPARE(ins_(a0, a1, 31, 1),
             "7ca4ffc4       ins     a0, a1, 31, 1");
     COMPARE(ins_(s6, s7, 30, 2),
diff --git a/test/cctest/test-disasm-mips64.cc b/test/cctest/test-disasm-mips64.cc
index 8a1e0e7..dc6f34e 100644
--- a/test/cctest/test-disasm-mips64.cc
+++ b/test/cctest/test-disasm-mips64.cc
@@ -97,7 +97,6 @@
     V8_Fatal(__FILE__, __LINE__, "MIPS Disassembler tests failed.\n"); \
   }
 
-
 #define COMPARE_PC_REL_COMPACT(asm_, compare_string, offset)                   \
   {                                                                            \
     int pc_offset = assm.pc_offset();                                          \
@@ -106,28 +105,28 @@
     prev_instr_compact_branch = assm.IsPrevInstrCompactBranch();               \
     if (prev_instr_compact_branch) {                                           \
       snprintf(str_with_address, sizeof(str_with_address), "%s -> %p",         \
-               compare_string, progcounter + 8 + (offset * 4));                \
+               compare_string,                                                 \
+               static_cast<void *>(progcounter + 8 + (offset * 4)));           \
     } else {                                                                   \
       snprintf(str_with_address, sizeof(str_with_address), "%s -> %p",         \
-               compare_string, progcounter + 4 + (offset * 4));                \
+               compare_string,                                                 \
+               static_cast<void *>(progcounter + 4 + (offset * 4)));           \
     }                                                                          \
     assm.asm_;                                                                 \
     if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \
   }
 
-
 #define COMPARE_PC_REL(asm_, compare_string, offset)                           \
   {                                                                            \
     int pc_offset = assm.pc_offset();                                          \
     byte *progcounter = &buffer[pc_offset];                                    \
     char str_with_address[100];                                                \
     snprintf(str_with_address, sizeof(str_with_address), "%s -> %p",           \
-             compare_string, progcounter + (offset * 4));                      \
+             compare_string, static_cast<void *>(progcounter + (offset * 4))); \
     assm.asm_;                                                                 \
     if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \
   }
 
-
 #define COMPARE_PC_JUMP(asm_, compare_string, target)                          \
   {                                                                            \
     int pc_offset = assm.pc_offset();                                          \
@@ -136,14 +135,13 @@
     int instr_index = (target >> 2) & kImm26Mask;                              \
     snprintf(                                                                  \
         str_with_address, sizeof(str_with_address), "%s %p -> %p",             \
-        compare_string, reinterpret_cast<byte *>(target),                      \
-        reinterpret_cast<byte *>(((uint64_t)(progcounter + 1) & ~0xfffffff) |  \
+        compare_string, reinterpret_cast<void *>(target),                      \
+        reinterpret_cast<void *>(((uint64_t)(progcounter + 1) & ~0xfffffff) |  \
                                  (instr_index << 2)));                         \
     assm.asm_;                                                                 \
     if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \
   }
 
-
 #define GET_PC_REGION(pc_region)                                         \
   {                                                                      \
     int pc_offset = assm.pc_offset();                                    \
@@ -530,41 +528,28 @@
   COMPARE(dsrav(v0, v1, fp),
           "03c31017       dsrav   v0, v1, fp");
 
-  if (kArchVariant == kMips64r2) {
-    COMPARE(rotr(a0, a1, 0),
-            "00252002       rotr    a0, a1, 0");
-    COMPARE(rotr(s0, s1, 8),
-            "00318202       rotr    s0, s1, 8");
-    COMPARE(rotr(a6, a7, 24),
-            "002b5602       rotr    a6, a7, 24");
-    COMPARE(rotr(v0, v1, 31),
-            "002317c2       rotr    v0, v1, 31");
-    COMPARE(drotr(a0, a1, 0),
-            "0025203a       drotr   a0, a1, 0");
-    COMPARE(drotr(s0, s1, 8),
-            "0031823a       drotr   s0, s1, 8");
-    COMPARE(drotr(a6, a7, 24),
-            "002b563a       drotr   a6, a7, 24");
-    COMPARE(drotr(v0, v1, 31),
-            "002317fa       drotr   v0, v1, 31");
+  COMPARE(rotr(a0, a1, 0), "00252002       rotr    a0, a1, 0");
+  COMPARE(rotr(s0, s1, 8), "00318202       rotr    s0, s1, 8");
+  COMPARE(rotr(a6, a7, 24), "002b5602       rotr    a6, a7, 24");
+  COMPARE(rotr(v0, v1, 31), "002317c2       rotr    v0, v1, 31");
+  COMPARE(drotr(a0, a1, 0), "0025203a       drotr   a0, a1, 0");
+  COMPARE(drotr(s0, s1, 8), "0031823a       drotr   s0, s1, 8");
+  COMPARE(drotr(a6, a7, 24), "002b563a       drotr   a6, a7, 24");
+  COMPARE(drotr(v0, v1, 31), "002317fa       drotr   v0, v1, 31");
 
-    COMPARE(rotrv(a0, a1, a2),
-            "00c52046       rotrv   a0, a1, a2");
-    COMPARE(rotrv(s0, s1, s2),
-            "02518046       rotrv   s0, s1, s2");
-    COMPARE(rotrv(a6, a7, t0),
-            "018b5046       rotrv   a6, a7, t0");
-    COMPARE(rotrv(v0, v1, fp),
-            "03c31046       rotrv   v0, v1, fp");
-    COMPARE(drotrv(a0, a1, a2),
-            "00c52056       drotrv  a0, a1, a2");
-    COMPARE(drotrv(s0, s1, s2),
-            "02518056       drotrv  s0, s1, s2");
-    COMPARE(drotrv(a6, a7, t0),
-            "018b5056       drotrv  a6, a7, t0");
-    COMPARE(drotrv(v0, v1, fp),
-            "03c31056       drotrv  v0, v1, fp");
-  }
+  COMPARE(drotr32(a0, a1, 0), "0025203e       drotr32 a0, a1, 0");
+  COMPARE(drotr32(s0, s1, 8), "0031823e       drotr32 s0, s1, 8");
+  COMPARE(drotr32(a6, a7, 24), "002b563e       drotr32 a6, a7, 24");
+  COMPARE(drotr32(v0, v1, 31), "002317fe       drotr32 v0, v1, 31");
+
+  COMPARE(rotrv(a0, a1, a2), "00c52046       rotrv   a0, a1, a2");
+  COMPARE(rotrv(s0, s1, s2), "02518046       rotrv   s0, s1, s2");
+  COMPARE(rotrv(a6, a7, t0), "018b5046       rotrv   a6, a7, t0");
+  COMPARE(rotrv(v0, v1, fp), "03c31046       rotrv   v0, v1, fp");
+  COMPARE(drotrv(a0, a1, a2), "00c52056       drotrv  a0, a1, a2");
+  COMPARE(drotrv(s0, s1, s2), "02518056       drotrv  s0, s1, s2");
+  COMPARE(drotrv(a6, a7, t0), "018b5056       drotrv  a6, a7, t0");
+  COMPARE(drotrv(v0, v1, fp), "03c31056       drotrv  v0, v1, fp");
 
   COMPARE(break_(0),
           "0000000d       break, code: 0x00000 (0)");
@@ -698,6 +683,26 @@
             "70621020       clz     v0, v1");
   }
 
+  COMPARE(seb(a0, a1), "7c052420       seb     a0, a1");
+  COMPARE(seb(s6, s7), "7c17b420       seb     s6, s7");
+  COMPARE(seb(v0, v1), "7c031420       seb     v0, v1");
+
+  COMPARE(seh(a0, a1), "7c052620       seh     a0, a1");
+  COMPARE(seh(s6, s7), "7c17b620       seh     s6, s7");
+  COMPARE(seh(v0, v1), "7c031620       seh     v0, v1");
+
+  COMPARE(wsbh(a0, a1), "7c0520a0       wsbh    a0, a1");
+  COMPARE(wsbh(s6, s7), "7c17b0a0       wsbh    s6, s7");
+  COMPARE(wsbh(v0, v1), "7c0310a0       wsbh    v0, v1");
+
+  COMPARE(dsbh(a0, a1), "7c0520a4       dsbh    a0, a1");
+  COMPARE(dsbh(s6, s7), "7c17b0a4       dsbh    s6, s7");
+  COMPARE(dsbh(v0, v1), "7c0310a4       dsbh    v0, v1");
+
+  COMPARE(dshd(a0, a1), "7c052164       dshd    a0, a1");
+  COMPARE(dshd(s6, s7), "7c17b164       dshd    s6, s7");
+  COMPARE(dshd(v0, v1), "7c031164       dshd    v0, v1");
+
   COMPARE(ins_(a0, a1, 31, 1),
           "7ca4ffc4       ins     a0, a1, 31, 1");
   COMPARE(ins_(s6, s7, 30, 2),
diff --git a/test/cctest/test-disasm-x64.cc b/test/cctest/test-disasm-x64.cc
index 3722c1f..64d97ea 100644
--- a/test/cctest/test-disasm-x64.cc
+++ b/test/cctest/test-disasm-x64.cc
@@ -29,10 +29,10 @@
 
 #include "src/v8.h"
 
+#include "src/code-factory.h"
 #include "src/debug/debug.h"
 #include "src/disasm.h"
 #include "src/disassembler.h"
-#include "src/ic/ic.h"
 #include "src/macro-assembler.h"
 #include "test/cctest/cctest.h"
 
@@ -282,7 +282,7 @@
   // TODO(mstarzinger): The following is protected.
   // __ call(Operand(rbx, rcx, times_4, 10000));
   __ nop();
-  Handle<Code> ic(LoadIC::initialize_stub(isolate, NOT_INSIDE_TYPEOF));
+  Handle<Code> ic(CodeFactory::LoadIC(isolate).code());
   __ call(ic, RelocInfo::CODE_TARGET);
   __ nop();
   __ nop();
@@ -458,6 +458,7 @@
     __ pcmpeqd(xmm1, xmm0);
 
     __ punpckldq(xmm1, xmm11);
+    __ punpckldq(xmm5, Operand(rdx, 4));
     __ punpckhdq(xmm8, xmm15);
   }
 
@@ -484,11 +485,46 @@
   {
     if (CpuFeatures::IsSupported(SSE4_1)) {
       CpuFeatureScope scope(&assm, SSE4_1);
+      __ insertps(xmm5, xmm1, 123);
       __ extractps(rax, xmm1, 0);
       __ pextrd(rbx, xmm15, 0);
       __ pextrd(r12, xmm0, 1);
       __ pinsrd(xmm9, r9, 0);
-      __ pinsrd(xmm5, rax, 1);
+      __ pinsrd(xmm5, Operand(rax, 4), 1);
+
+      __ cmpps(xmm5, xmm1, 1);
+      __ cmpeqps(xmm5, xmm1);
+      __ cmpltps(xmm5, xmm1);
+      __ cmpleps(xmm5, xmm1);
+      __ cmpneqps(xmm5, xmm1);
+      __ cmpnltps(xmm5, xmm1);
+      __ cmpnleps(xmm5, xmm1);
+
+      __ minps(xmm5, xmm1);
+      __ minps(xmm5, Operand(rdx, 4));
+      __ maxps(xmm5, xmm1);
+      __ maxps(xmm5, Operand(rdx, 4));
+      __ rcpps(xmm5, xmm1);
+      __ rcpps(xmm5, Operand(rdx, 4));
+      __ sqrtps(xmm5, xmm1);
+      __ sqrtps(xmm5, Operand(rdx, 4));
+      __ movups(xmm5, xmm1);
+      __ movups(xmm5, Operand(rdx, 4));
+      __ movups(Operand(rdx, 4), xmm5);
+      __ paddd(xmm5, xmm1);
+      __ paddd(xmm5, Operand(rdx, 4));
+      __ psubd(xmm5, xmm1);
+      __ psubd(xmm5, Operand(rdx, 4));
+      __ pmulld(xmm5, xmm1);
+      __ pmulld(xmm5, Operand(rdx, 4));
+      __ pmuludq(xmm5, xmm1);
+      __ pmuludq(xmm5, Operand(rdx, 4));
+      __ psrldq(xmm5, 123);
+      __ pshufd(xmm5, xmm1, 3);
+      __ cvtps2dq(xmm5, xmm1);
+      __ cvtps2dq(xmm5, Operand(rdx, 4));
+      __ cvtdq2ps(xmm5, xmm1);
+      __ cvtdq2ps(xmm5, Operand(rdx, 4));
     }
   }
 
@@ -745,12 +781,31 @@
 
   // xchg.
   {
+    __ xchgb(rax, Operand(rax, 8));
+    __ xchgw(rax, Operand(rbx, 8));
     __ xchgq(rax, rax);
     __ xchgq(rax, rbx);
     __ xchgq(rbx, rbx);
     __ xchgq(rbx, Operand(rsp, 12));
   }
 
+  // cmpxchg.
+  {
+    __ cmpxchgb(Operand(rsp, 12), rax);
+    __ cmpxchgw(Operand(rbx, rcx, times_4, 10000), rax);
+    __ cmpxchgl(Operand(rbx, rcx, times_4, 10000), rax);
+    __ cmpxchgq(Operand(rbx, rcx, times_4, 10000), rax);
+  }
+
+  // lock prefix.
+  {
+    __ lock();
+    __ cmpxchgl(Operand(rsp, 12), rbx);
+
+    __ lock();
+    __ xchgw(rax, Operand(rcx, 8));
+  }
+
   // Nop instructions
   for (int i = 0; i < 16; i++) {
     __ Nop(i);
diff --git a/test/cctest/test-disasm-x87.cc b/test/cctest/test-disasm-x87.cc
index 697a9d3..41f425d 100644
--- a/test/cctest/test-disasm-x87.cc
+++ b/test/cctest/test-disasm-x87.cc
@@ -29,10 +29,10 @@
 
 #include "src/v8.h"
 
+#include "src/code-factory.h"
 #include "src/debug/debug.h"
 #include "src/disasm.h"
 #include "src/disassembler.h"
-#include "src/ic/ic.h"
 #include "src/macro-assembler.h"
 #include "src/x87/frames-x87.h"
 #include "test/cctest/cctest.h"
@@ -290,7 +290,7 @@
   __ bind(&L2);
   __ call(Operand(ebx, ecx, times_4, 10000));
   __ nop();
-  Handle<Code> ic(LoadIC::initialize_stub(isolate, NOT_INSIDE_TYPEOF));
+  Handle<Code> ic(CodeFactory::LoadIC(isolate).code());
   __ call(ic, RelocInfo::CODE_TARGET);
   __ nop();
   __ call(FUNCTION_ADDR(DummyStaticFunction), RelocInfo::RUNTIME_ENTRY);
@@ -395,12 +395,30 @@
 
   // xchg.
   {
+    __ xchg_b(eax, Operand(eax, 8));
+    __ xchg_w(eax, Operand(ebx, 8));
     __ xchg(eax, eax);
     __ xchg(eax, ebx);
     __ xchg(ebx, ebx);
     __ xchg(ebx, Operand(esp, 12));
   }
 
+  // cmpxchg.
+  {
+    __ cmpxchg_b(Operand(esp, 12), eax);
+    __ cmpxchg_w(Operand(ebx, ecx, times_4, 10000), eax);
+    __ cmpxchg(Operand(ebx, ecx, times_4, 10000), eax);
+  }
+
+  // lock prefix.
+  {
+    __ lock();
+    __ cmpxchg(Operand(esp, 12), ebx);
+
+    __ lock();
+    __ xchg_w(eax, Operand(ecx, 8));
+  }
+
   // Nop instructions
   for (int i = 0; i < 16; i++) {
     __ Nop(i);
diff --git a/test/cctest/test-eh-frame-hdr.cc b/test/cctest/test-eh-frame-hdr.cc
new file mode 100644
index 0000000..d9539c7
--- /dev/null
+++ b/test/cctest/test-eh-frame-hdr.cc
@@ -0,0 +1,100 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/eh-frame.h"
+#include "src/objects.h"
+#include "test/cctest/cctest.h"
+
+using namespace v8::internal;
+
+TEST(EhFrameHdr) {
+  CcTest::InitializeVM();
+  HandleScope handle_scope(CcTest::i_isolate());
+
+  // The content is not relevant in this test
+  byte buffer[10] = {0};
+  byte unwinding_info[30 + EhFrameHdr::kRecordSize] = {0};
+
+  CodeDesc code_desc;
+  code_desc.buffer = &buffer[0];
+  code_desc.buffer_size = sizeof(buffer);
+  code_desc.constant_pool_size = 0;
+  code_desc.instr_size = sizeof(buffer);
+  code_desc.reloc_size = 0;
+  code_desc.origin = nullptr;
+  code_desc.unwinding_info = &unwinding_info[0];
+  code_desc.unwinding_info_size = sizeof(unwinding_info);
+
+  Handle<Code> code = CcTest::i_isolate()->factory()->NewCode(
+      code_desc, 0, Handle<Object>::null());
+
+  EhFrameHdr eh_frame_hdr(*code);
+  CHECK_EQ(eh_frame_hdr.lut_entries_number(), 1);
+
+  //
+  // Plugging some numbers in the DSO layout shown in eh-frame.cc:
+  //
+  //  |      ...      |
+  //  +---------------+ <-- (E) --------
+  //  |               |                ^
+  //  |  Instructions |  10 bytes      | .text
+  //  |               |                v
+  //  +---------------+ <---------------
+  //  |///////////////|
+  //  |////Padding////|   6 bytes
+  //  |///////////////|
+  //  +---------------+ <---(D)---------
+  //  |               |                ^
+  //  |      CIE      |   N bytes*     |
+  //  |               |                |
+  //  +---------------+ <-- (C)        | .eh_frame
+  //  |               |                |
+  //  |      FDE      |  30 - N bytes  |
+  //  |               |                v
+  //  +---------------+ <-- (B) --------
+  //  |    version    |                ^
+  //  +---------------+   4 bytes      |
+  //  |   encoding    |                |
+  //  |  specifiers   |                |
+  //  +---------------+ <---(A)        | .eh_frame_hdr
+  //  |   offset to   |                |
+  //  |   .eh_frame   |                |
+  //  +---------------+                |
+  //  |      ...      |               ...
+  //
+  //  (*) the size of the CIE is platform dependent.
+  //
+  CHECK_EQ(eh_frame_hdr.offset_to_eh_frame(), -(4 + 30));        // A -> D
+  CHECK_EQ(eh_frame_hdr.offset_to_procedure(), -(30 + 6 + 10));  // B -> E
+  CHECK_EQ(eh_frame_hdr.offset_to_fde(),
+           -(30 - EhFrameHdr::kCIESize));  // B -> C
+}
+
+TEST(DummyEhFrameHdr) {
+  CcTest::InitializeVM();
+  HandleScope handle_scope(CcTest::i_isolate());
+
+  byte buffer[10] = {0};  // The content is not relevant in this test
+
+  CodeDesc code_desc;
+  code_desc.buffer = &buffer[0];
+  code_desc.buffer_size = sizeof(buffer);
+  code_desc.constant_pool_size = 0;
+  code_desc.instr_size = sizeof(buffer);
+  code_desc.reloc_size = 0;
+  code_desc.origin = nullptr;
+  code_desc.unwinding_info = nullptr;
+  code_desc.unwinding_info_size = 0;
+
+  Handle<Code> code = CcTest::i_isolate()->factory()->NewCode(
+      code_desc, 0, Handle<Object>::null());
+
+  EhFrameHdr eh_frame_hdr(*code);
+  // A dummy header has an empty LUT
+  CHECK_EQ(eh_frame_hdr.lut_entries_number(), 0);
+  // These values should be irrelevant, but check that they have been zeroed.
+  CHECK_EQ(eh_frame_hdr.offset_to_eh_frame(), 0);
+  CHECK_EQ(eh_frame_hdr.offset_to_procedure(), 0);
+  CHECK_EQ(eh_frame_hdr.offset_to_fde(), 0);
+}
diff --git a/test/cctest/test-feedback-vector.cc b/test/cctest/test-feedback-vector.cc
index c06e5b9..69c60ca 100644
--- a/test/cctest/test-feedback-vector.cc
+++ b/test/cctest/test-feedback-vector.cc
@@ -208,7 +208,7 @@
   Handle<JSFunction> f = GetFunction("f");
   // There should be one IC.
   Handle<TypeFeedbackVector> feedback_vector =
-      Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
+      Handle<TypeFeedbackVector>(f->feedback_vector(), isolate);
   FeedbackVectorSlot slot(0);
   CallICNexus nexus(feedback_vector, slot);
   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
@@ -233,6 +233,41 @@
   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
 }
 
+TEST(VectorCallCounts) {
+  if (i::FLAG_always_opt) return;
+  CcTest::InitializeVM();
+  LocalContext context;
+  v8::HandleScope scope(context->GetIsolate());
+  Isolate* isolate = CcTest::i_isolate();
+
+  // Make sure function f has a call that uses a type feedback slot.
+  CompileRun(
+      "function foo() { return 17; }"
+      "function f(a) { a(); } f(foo);");
+  Handle<JSFunction> f = GetFunction("f");
+  // There should be one IC.
+  Handle<TypeFeedbackVector> feedback_vector =
+      Handle<TypeFeedbackVector>(f->feedback_vector(), isolate);
+  FeedbackVectorSlot slot(0);
+  CallICNexus nexus(feedback_vector, slot);
+  CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
+
+  CompileRun("f(foo); f(foo);");
+  CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
+  CHECK_EQ(3, nexus.ExtractCallCount());
+
+  CompileRun(
+      "function Foo() {}"
+      "function f(a) { new a(); } f(Foo);");
+  f = GetFunction("f");
+  // There should be one IC.
+  feedback_vector = Handle<TypeFeedbackVector>(f->feedback_vector(), isolate);
+  FeedbackVectorSlot cslot(1);
+
+  CompileRun("f(Foo); f(Foo);");
+  CHECK(feedback_vector->Get(cslot)->IsSmi());
+  CHECK_EQ(3, Smi::cast(feedback_vector->Get(cslot))->value());
+}
 
 TEST(VectorLoadICStates) {
   if (i::FLAG_always_opt) return;
@@ -249,7 +284,7 @@
   Handle<JSFunction> f = GetFunction("f");
   // There should be one IC.
   Handle<TypeFeedbackVector> feedback_vector =
-      Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
+      Handle<TypeFeedbackVector>(f->feedback_vector(), isolate);
   FeedbackVectorSlot slot(0);
   LoadICNexus nexus(feedback_vector, slot);
   CHECK_EQ(PREMONOMORPHIC, nexus.StateFromFeedback());
@@ -308,11 +343,11 @@
   Handle<JSFunction> f = GetFunction("f");
   // There should be one IC slot.
   Handle<TypeFeedbackVector> feedback_vector =
-      Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
+      Handle<TypeFeedbackVector>(f->feedback_vector(), isolate);
   FeedbackVectorHelper helper(feedback_vector);
   CHECK_EQ(1, helper.slot_count());
   FeedbackVectorSlot slot(0);
-  LoadICNexus nexus(feedback_vector, slot);
+  LoadGlobalICNexus nexus(feedback_vector, slot);
   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback());
 }
 
@@ -332,7 +367,7 @@
   Handle<JSFunction> f = GetFunction("f");
   // There should be one IC.
   Handle<TypeFeedbackVector> feedback_vector =
-      Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate);
+      Handle<TypeFeedbackVector>(f->feedback_vector(), isolate);
   FeedbackVectorSlot slot(0);
   LoadICNexus nexus(feedback_vector, slot);
   CHECK_EQ(PREMONOMORPHIC, nexus.StateFromFeedback());
@@ -397,13 +432,13 @@
 
     // There should be two LOAD_ICs, one for a and one for y at the end.
     Handle<TypeFeedbackVector> feedback_vector =
-        handle(f->shared()->feedback_vector(), isolate);
+        handle(f->feedback_vector(), isolate);
     FeedbackVectorHelper helper(feedback_vector);
     CHECK_EQ(4, helper.slot_count());
     CHECK_SLOT_KIND(helper, 0, FeedbackVectorSlotKind::STORE_IC);
-    CHECK_SLOT_KIND(helper, 1, FeedbackVectorSlotKind::LOAD_IC);
+    CHECK_SLOT_KIND(helper, 1, FeedbackVectorSlotKind::LOAD_GLOBAL_IC);
     CHECK_SLOT_KIND(helper, 2, FeedbackVectorSlotKind::STORE_IC);
-    CHECK_SLOT_KIND(helper, 3, FeedbackVectorSlotKind::LOAD_IC);
+    CHECK_SLOT_KIND(helper, 3, FeedbackVectorSlotKind::LOAD_GLOBAL_IC);
   }
 
   {
@@ -416,9 +451,11 @@
     Handle<JSFunction> f = GetFunction("testprop");
 
     // There should be one LOAD_IC, for the load of a.
-    Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector());
+    Handle<TypeFeedbackVector> feedback_vector(f->feedback_vector());
     FeedbackVectorHelper helper(feedback_vector);
     CHECK_EQ(2, helper.slot_count());
+    CHECK_SLOT_KIND(helper, 0, FeedbackVectorSlotKind::LOAD_GLOBAL_IC);
+    CHECK_SLOT_KIND(helper, 1, FeedbackVectorSlotKind::STORE_IC);
   }
 
   {
@@ -432,12 +469,13 @@
 
     Handle<JSFunction> f = GetFunction("testpropfunc");
 
-    // There should be 2 LOAD_ICs and 2 CALL_ICs.
-    Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector());
+    // There should be 1 LOAD_GLOBAL_IC to load x (in both cases), 2 CALL_ICs
+    // to call x and a LOAD_IC to load blue.
+    Handle<TypeFeedbackVector> feedback_vector(f->feedback_vector());
     FeedbackVectorHelper helper(feedback_vector);
     CHECK_EQ(5, helper.slot_count());
     CHECK_SLOT_KIND(helper, 0, FeedbackVectorSlotKind::CALL_IC);
-    CHECK_SLOT_KIND(helper, 1, FeedbackVectorSlotKind::LOAD_IC);
+    CHECK_SLOT_KIND(helper, 1, FeedbackVectorSlotKind::LOAD_GLOBAL_IC);
     CHECK_SLOT_KIND(helper, 2, FeedbackVectorSlotKind::STORE_IC);
     CHECK_SLOT_KIND(helper, 3, FeedbackVectorSlotKind::CALL_IC);
     CHECK_SLOT_KIND(helper, 4, FeedbackVectorSlotKind::LOAD_IC);
@@ -453,12 +491,12 @@
 
     Handle<JSFunction> f = GetFunction("testkeyedprop");
 
-    // There should be 1 LOAD_ICs for the load of a, and one KEYED_LOAD_IC for
-    // the load of x[0] in the return statement.
-    Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector());
+    // There should be 1 LOAD_GLOBAL_ICs for the load of a, and one
+    // KEYED_LOAD_IC for the load of x[0] in the return statement.
+    Handle<TypeFeedbackVector> feedback_vector(f->feedback_vector());
     FeedbackVectorHelper helper(feedback_vector);
     CHECK_EQ(3, helper.slot_count());
-    CHECK_SLOT_KIND(helper, 0, FeedbackVectorSlotKind::LOAD_IC);
+    CHECK_SLOT_KIND(helper, 0, FeedbackVectorSlotKind::LOAD_GLOBAL_IC);
     CHECK_SLOT_KIND(helper, 1, FeedbackVectorSlotKind::KEYED_STORE_IC);
     CHECK_SLOT_KIND(helper, 2, FeedbackVectorSlotKind::KEYED_LOAD_IC);
   }
@@ -473,11 +511,12 @@
 
     Handle<JSFunction> f = GetFunction("testcompound");
 
-    // There should be 3 LOAD_ICs, for load of a and load of x.old and x.young.
-    Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector());
+    // There should be 1 LOAD_GLOBAL_IC for load of a and 2 LOAD_ICs, for load
+    // of x.old and x.young.
+    Handle<TypeFeedbackVector> feedback_vector(f->feedback_vector());
     FeedbackVectorHelper helper(feedback_vector);
     CHECK_EQ(6, helper.slot_count());
-    CHECK_SLOT_KIND(helper, 0, FeedbackVectorSlotKind::LOAD_IC);
+    CHECK_SLOT_KIND(helper, 0, FeedbackVectorSlotKind::LOAD_GLOBAL_IC);
     CHECK_SLOT_KIND(helper, 1, FeedbackVectorSlotKind::STORE_IC);
     CHECK_SLOT_KIND(helper, 2, FeedbackVectorSlotKind::STORE_IC);
     CHECK_SLOT_KIND(helper, 3, FeedbackVectorSlotKind::STORE_IC);
@@ -504,7 +543,7 @@
       "f(a);");
   Handle<JSFunction> f = GetFunction("f");
   // There should be one IC slot.
-  Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector());
+  Handle<TypeFeedbackVector> feedback_vector(f->feedback_vector());
   FeedbackVectorHelper helper(feedback_vector);
   CHECK_EQ(1, helper.slot_count());
   FeedbackVectorSlot slot(0);
diff --git a/test/cctest/test-field-type-tracking.cc b/test/cctest/test-field-type-tracking.cc
index 7b262db..33a2dac 100644
--- a/test/cctest/test-field-type-tracking.cc
+++ b/test/cctest/test-field-type-tracking.cc
@@ -86,6 +86,7 @@
 class Expectations {
   static const int MAX_PROPERTIES = 10;
   Isolate* isolate_;
+  ElementsKind elements_kind_;
   PropertyType types_[MAX_PROPERTIES];
   PropertyAttributes attributes_[MAX_PROPERTIES];
   Representation representations_[MAX_PROPERTIES];
@@ -97,8 +98,15 @@
   int number_of_properties_;
 
  public:
+  explicit Expectations(Isolate* isolate, ElementsKind elements_kind)
+      : isolate_(isolate),
+        elements_kind_(elements_kind),
+        number_of_properties_(0) {}
+
   explicit Expectations(Isolate* isolate)
-      : isolate_(isolate), number_of_properties_(0) {}
+      : Expectations(
+            isolate,
+            isolate->object_function()->initial_map()->elements_kind()) {}
 
   void Init(int index, PropertyType type, PropertyAttributes attributes,
             Representation representation, Handle<Object> value) {
@@ -143,6 +151,10 @@
     os << "\n";
   }
 
+  void SetElementsKind(ElementsKind elements_kind) {
+    elements_kind_ = elements_kind;
+  }
+
   Handle<FieldType> GetFieldType(int index) {
     CHECK(index < MAX_PROPERTIES);
     CHECK(types_[index] == DATA || types_[index] == ACCESSOR);
@@ -252,6 +264,7 @@
   }
 
   bool Check(Map* map, int expected_nof) const {
+    CHECK_EQ(elements_kind_, map->elements_kind());
     CHECK(number_of_properties_ <= MAX_PROPERTIES);
     CHECK_EQ(expected_nof, map->NumberOfOwnDescriptors());
     CHECK(!map->is_dictionary_map());
@@ -279,6 +292,13 @@
   // given |map|.
   //
 
+  Handle<Map> AsElementsKind(Handle<Map> map, ElementsKind elements_kind) {
+    elements_kind_ = elements_kind;
+    map = Map::AsElementsKind(map, elements_kind);
+    CHECK_EQ(elements_kind_, map->elements_kind());
+    return map;
+  }
+
   Handle<Map> AddDataField(Handle<Map> map, PropertyAttributes attributes,
                            Representation representation,
                            Handle<FieldType> heap_type) {
@@ -368,16 +388,16 @@
 
     Handle<String> name = MakeName("prop", property_index);
 
-    CHECK(!getter->IsNull() || !setter->IsNull());
+    CHECK(!getter->IsNull(isolate_) || !setter->IsNull(isolate_));
     Factory* factory = isolate_->factory();
 
-    if (!getter->IsNull()) {
+    if (!getter->IsNull(isolate_)) {
       Handle<AccessorPair> pair = factory->NewAccessorPair();
       pair->SetComponents(*getter, *factory->null_value());
       AccessorConstantDescriptor new_desc(name, pair, attributes);
       map = Map::CopyInsertDescriptor(map, &new_desc, INSERT_TRANSITION);
     }
-    if (!setter->IsNull()) {
+    if (!setter->IsNull(isolate_)) {
       Handle<AccessorPair> pair = factory->NewAccessorPair();
       pair->SetComponents(*getter, *setter);
       AccessorConstantDescriptor new_desc(name, pair, attributes);
@@ -401,15 +421,8 @@
 
     int descriptor =
         map->instance_descriptors()->SearchWithCache(isolate, *name, *map);
-    map = Map::TransitionToAccessorProperty(
-        map, name, descriptor, ACCESSOR_GETTER, getter, attributes);
-    CHECK(!map->is_deprecated());
-    CHECK(!map->is_dictionary_map());
-
-    descriptor =
-        map->instance_descriptors()->SearchWithCache(isolate, *name, *map);
-    map = Map::TransitionToAccessorProperty(
-        map, name, descriptor, ACCESSOR_SETTER, setter, attributes);
+    map = Map::TransitionToAccessorProperty(isolate, map, name, descriptor,
+                                            getter, setter, attributes);
     CHECK(!map->is_deprecated());
     CHECK(!map->is_dictionary_map());
     return map;
@@ -473,7 +486,7 @@
   Handle<JSObject> obj = factory->NewJSObjectFromMap(map);
   JSObject::MigrateToMap(obj, prepared_map);
   FieldIndex index = FieldIndex::ForDescriptor(*prepared_map, 0);
-  CHECK(obj->RawFastPropertyAt(index)->IsUninitialized());
+  CHECK(obj->RawFastPropertyAt(index)->IsUninitialized(isolate));
 #ifdef VERIFY_HEAP
   obj->ObjectVerify();
 #endif
@@ -589,7 +602,7 @@
 
   // Create new maps by generalizing representation of propX field.
   Handle<Map> field_owner(map->FindFieldOwner(property_index), isolate);
-  CompilationInfo info("testing", isolate, &zone);
+  CompilationInfo info(ArrayVector("testing"), isolate, &zone);
   CHECK(!info.dependencies()->HasAborted());
 
   info.dependencies()->AssumeFieldType(field_owner);
@@ -631,7 +644,7 @@
     Map* tmp = *new_map;
     while (true) {
       Object* back = tmp->GetBackPointer();
-      if (back->IsUndefined()) break;
+      if (back->IsUndefined(isolate)) break;
       tmp = Map::cast(back);
       CHECK(!tmp->is_stable());
     }
@@ -968,7 +981,7 @@
 
   Zone zone(isolate->allocator());
   Handle<Map> field_owner(map->FindFieldOwner(kSplitProp), isolate);
-  CompilationInfo info("testing", isolate, &zone);
+  CompilationInfo info(ArrayVector("testing"), isolate, &zone);
   CHECK(!info.dependencies()->HasAborted());
   info.dependencies()->AssumeFieldType(field_owner);
 
@@ -1053,7 +1066,7 @@
 
   Zone zone(isolate->allocator());
   Handle<Map> field_owner(map->FindFieldOwner(kSplitProp), isolate);
-  CompilationInfo info("testing", isolate, &zone);
+  CompilationInfo info(ArrayVector("testing"), isolate, &zone);
   CHECK(!info.dependencies()->HasAborted());
   info.dependencies()->AssumeFieldType(field_owner);
 
@@ -1229,7 +1242,7 @@
     CHECK(!map->is_deprecated());
     CHECK_NE(*map, *new_map);
 
-    CHECK(new_map->GetBackPointer()->IsUndefined());
+    CHECK(new_map->GetBackPointer()->IsUndefined(map->GetIsolate()));
     for (int i = 0; i < kPropCount; i++) {
       expectations.GeneralizeRepresentation(i);
     }
@@ -1529,6 +1542,271 @@
 
 
 ////////////////////////////////////////////////////////////////////////////////
+// A set of tests for elements kind reconfiguration case.
+//
+
+// This test ensures that representation/field type generalization is correctly
+// propagated from one branch of transition tree (|map2) to another (|map|).
+//
+//   + - p0 - p1 - p2A - p3 - p4: |map|
+//   |
+//  ek
+//   |
+//  {} - p0 - p1 - p2B - p3 - p4: |map2|
+//
+// where "p2A" and "p2B" differ only in the representation/field type.
+//
+static void TestReconfigureElementsKind_GeneralizeRepresentation(
+    Representation from_representation, Handle<FieldType> from_type,
+    Representation to_representation, Handle<FieldType> to_type,
+    Representation expected_representation, Handle<FieldType> expected_type) {
+  Isolate* isolate = CcTest::i_isolate();
+
+  Expectations expectations(isolate, FAST_SMI_ELEMENTS);
+
+  // Create a map, add required properties to it and initialize expectations.
+  Handle<Map> initial_map = Map::Create(isolate, 0);
+  initial_map->set_elements_kind(FAST_SMI_ELEMENTS);
+
+  Handle<Map> map = initial_map;
+  map = expectations.AsElementsKind(map, FAST_ELEMENTS);
+  for (int i = 0; i < kPropCount; i++) {
+    map = expectations.AddDataField(map, NONE, from_representation, from_type);
+  }
+  CHECK(!map->is_deprecated());
+  CHECK(map->is_stable());
+  CHECK(expectations.Check(*map));
+
+  // Create another branch in transition tree (property at index |kDiffProp|
+  // has different representatio/field type), initialize expectations.
+  const int kDiffProp = kPropCount / 2;
+  Expectations expectations2(isolate, FAST_SMI_ELEMENTS);
+
+  Handle<Map> map2 = initial_map;
+  for (int i = 0; i < kPropCount; i++) {
+    if (i == kDiffProp) {
+      map2 = expectations2.AddDataField(map2, NONE, to_representation, to_type);
+    } else {
+      map2 = expectations2.AddDataField(map2, NONE, from_representation,
+                                        from_type);
+    }
+  }
+  CHECK(!map2->is_deprecated());
+  CHECK(map2->is_stable());
+  CHECK(expectations2.Check(*map2));
+
+  Zone zone(isolate->allocator());
+  Handle<Map> field_owner(map->FindFieldOwner(kDiffProp), isolate);
+  CompilationInfo info(ArrayVector("testing"), isolate, &zone);
+  CHECK(!info.dependencies()->HasAborted());
+  info.dependencies()->AssumeFieldType(field_owner);
+
+  // Reconfigure elements kinds of |map2|, which should generalize
+  // representations in |map|.
+  Handle<Map> new_map = Map::ReconfigureElementsKind(map2, FAST_ELEMENTS);
+
+  // |map2| should be left unchanged but marked unstable.
+  CHECK(!map2->is_stable());
+  CHECK(!map2->is_deprecated());
+  CHECK_NE(*map2, *new_map);
+  CHECK(expectations2.Check(*map2));
+
+  // |map| should be deprecated and |new_map| should match new expectations.
+  expectations.SetDataField(kDiffProp, expected_representation, expected_type);
+
+  CHECK(map->is_deprecated());
+  CHECK(!info.dependencies()->HasAborted());
+  info.dependencies()->Rollback();  // Properly cleanup compilation info.
+  CHECK_NE(*map, *new_map);
+
+  CHECK(!new_map->is_deprecated());
+  CHECK(expectations.Check(*new_map));
+
+  // Update deprecated |map|, it should become |new_map|.
+  Handle<Map> updated_map = Map::Update(map);
+  CHECK_EQ(*new_map, *updated_map);
+
+  // Ensure Map::FindElementsKindTransitionedMap() is able to find the
+  // transitioned map.
+  {
+    MapHandleList map_list;
+    map_list.Add(updated_map);
+    Map* transitioned_map = map2->FindElementsKindTransitionedMap(&map_list);
+    CHECK_EQ(*updated_map, transitioned_map);
+  }
+}
+
+// This test ensures that trivial representation/field type generalization
+// (from HeapObject to HeapObject) is correctly propagated from one branch of
+// transition tree (|map2|) to another (|map|).
+//
+//   + - p0 - p1 - p2A - p3 - p4: |map|
+//   |
+//  ek
+//   |
+//  {} - p0 - p1 - p2B - p3 - p4: |map2|
+//
+// where "p2A" and "p2B" differ only in the representation/field type.
+//
+static void TestReconfigureElementsKind_GeneralizeRepresentationTrivial(
+    Representation from_representation, Handle<FieldType> from_type,
+    Representation to_representation, Handle<FieldType> to_type,
+    Representation expected_representation, Handle<FieldType> expected_type,
+    bool expected_field_type_dependency = true) {
+  Isolate* isolate = CcTest::i_isolate();
+
+  Expectations expectations(isolate, FAST_SMI_ELEMENTS);
+
+  // Create a map, add required properties to it and initialize expectations.
+  Handle<Map> initial_map = Map::Create(isolate, 0);
+  initial_map->set_elements_kind(FAST_SMI_ELEMENTS);
+
+  Handle<Map> map = initial_map;
+  map = expectations.AsElementsKind(map, FAST_ELEMENTS);
+  for (int i = 0; i < kPropCount; i++) {
+    map = expectations.AddDataField(map, NONE, from_representation, from_type);
+  }
+  CHECK(!map->is_deprecated());
+  CHECK(map->is_stable());
+  CHECK(expectations.Check(*map));
+
+  // Create another branch in transition tree (property at index |kDiffProp|
+  // has different attributes), initialize expectations.
+  const int kDiffProp = kPropCount / 2;
+  Expectations expectations2(isolate, FAST_SMI_ELEMENTS);
+
+  Handle<Map> map2 = initial_map;
+  for (int i = 0; i < kPropCount; i++) {
+    if (i == kDiffProp) {
+      map2 = expectations2.AddDataField(map2, NONE, to_representation, to_type);
+    } else {
+      map2 = expectations2.AddDataField(map2, NONE, from_representation,
+                                        from_type);
+    }
+  }
+  CHECK(!map2->is_deprecated());
+  CHECK(map2->is_stable());
+  CHECK(expectations2.Check(*map2));
+
+  Zone zone(isolate->allocator());
+  Handle<Map> field_owner(map->FindFieldOwner(kDiffProp), isolate);
+  CompilationInfo info(ArrayVector("testing"), isolate, &zone);
+  CHECK(!info.dependencies()->HasAborted());
+  info.dependencies()->AssumeFieldType(field_owner);
+
+  // Reconfigure elements kinds of |map2|, which should generalize
+  // representations in |map|.
+  Handle<Map> new_map = Map::ReconfigureElementsKind(map2, FAST_ELEMENTS);
+
+  // |map2| should be left unchanged but marked unstable.
+  CHECK(!map2->is_stable());
+  CHECK(!map2->is_deprecated());
+  CHECK_NE(*map2, *new_map);
+  CHECK(expectations2.Check(*map2));
+
+  // In trivial case |map| should be returned as a result of the elements
+  // kind reconfiguration, respective field types should be generalized and
+  // respective code dependencies should be invalidated. |map| should be NOT
+  // deprecated and it should match new expectations.
+  expectations.SetDataField(kDiffProp, expected_representation, expected_type);
+  CHECK(!map->is_deprecated());
+  CHECK_EQ(*map, *new_map);
+  CHECK_EQ(expected_field_type_dependency, info.dependencies()->HasAborted());
+  info.dependencies()->Rollback();  // Properly cleanup compilation info.
+
+  CHECK(!new_map->is_deprecated());
+  CHECK(expectations.Check(*new_map));
+
+  Handle<Map> updated_map = Map::Update(map);
+  CHECK_EQ(*new_map, *updated_map);
+
+  // Ensure Map::FindElementsKindTransitionedMap() is able to find the
+  // transitioned map.
+  {
+    MapHandleList map_list;
+    map_list.Add(updated_map);
+    Map* transitioned_map = map2->FindElementsKindTransitionedMap(&map_list);
+    CHECK_EQ(*updated_map, transitioned_map);
+  }
+}
+
+TEST(ReconfigureElementsKind_GeneralizeRepresentationSmiToDouble) {
+  CcTest::InitializeVM();
+  v8::HandleScope scope(CcTest::isolate());
+  Isolate* isolate = CcTest::i_isolate();
+  Handle<FieldType> any_type = FieldType::Any(isolate);
+
+  TestReconfigureElementsKind_GeneralizeRepresentation(
+      Representation::Smi(), any_type, Representation::Double(), any_type,
+      Representation::Double(), any_type);
+}
+
+TEST(ReconfigureElementsKind_GeneralizeRepresentationSmiToTagged) {
+  CcTest::InitializeVM();
+  v8::HandleScope scope(CcTest::isolate());
+  Isolate* isolate = CcTest::i_isolate();
+  Handle<FieldType> any_type = FieldType::Any(isolate);
+  Handle<FieldType> value_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
+
+  TestReconfigureElementsKind_GeneralizeRepresentation(
+      Representation::Smi(), any_type, Representation::HeapObject(), value_type,
+      Representation::Tagged(), any_type);
+}
+
+TEST(ReconfigureElementsKind_GeneralizeRepresentationDoubleToTagged) {
+  CcTest::InitializeVM();
+  v8::HandleScope scope(CcTest::isolate());
+  Isolate* isolate = CcTest::i_isolate();
+  Handle<FieldType> any_type = FieldType::Any(isolate);
+  Handle<FieldType> value_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
+
+  TestReconfigureElementsKind_GeneralizeRepresentation(
+      Representation::Double(), any_type, Representation::HeapObject(),
+      value_type, Representation::Tagged(), any_type);
+}
+
+TEST(ReconfigureElementsKind_GeneralizeRepresentationHeapObjToHeapObj) {
+  CcTest::InitializeVM();
+  v8::HandleScope scope(CcTest::isolate());
+  Isolate* isolate = CcTest::i_isolate();
+  Handle<FieldType> any_type = FieldType::Any(isolate);
+
+  Handle<FieldType> current_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
+
+  Handle<FieldType> new_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
+
+  Handle<FieldType> expected_type = any_type;
+
+  TestReconfigureElementsKind_GeneralizeRepresentationTrivial(
+      Representation::HeapObject(), current_type, Representation::HeapObject(),
+      new_type, Representation::HeapObject(), expected_type);
+  current_type = expected_type;
+
+  new_type = FieldType::Class(Map::Create(isolate, 0), isolate);
+
+  TestReconfigureElementsKind_GeneralizeRepresentationTrivial(
+      Representation::HeapObject(), any_type, Representation::HeapObject(),
+      new_type, Representation::HeapObject(), any_type, false);
+}
+
+TEST(ReconfigureElementsKind_GeneralizeRepresentationHeapObjectToTagged) {
+  CcTest::InitializeVM();
+  v8::HandleScope scope(CcTest::isolate());
+  Isolate* isolate = CcTest::i_isolate();
+  Handle<FieldType> any_type = FieldType::Any(isolate);
+  Handle<FieldType> value_type =
+      FieldType::Class(Map::Create(isolate, 0), isolate);
+
+  TestReconfigureElementsKind_GeneralizeRepresentation(
+      Representation::HeapObject(), value_type, Representation::Smi(), any_type,
+      Representation::Tagged(), any_type);
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // A set of tests checking split map deprecation.
 //
 
@@ -1595,7 +1873,7 @@
   // Try to update |map|, since there is no place for propX transition at |map2|
   // |map| should become "copy-generalized".
   Handle<Map> updated_map = Map::Update(map);
-  CHECK(updated_map->GetBackPointer()->IsUndefined());
+  CHECK(updated_map->GetBackPointer()->IsUndefined(isolate));
 
   for (int i = 0; i < kPropCount; i++) {
     expectations.SetDataField(i, Representation::Tagged(), any_type);
@@ -1644,15 +1922,16 @@
   CHECK(map->is_stable());
   CHECK(expectations.Check(*map));
 
+  Expectations expectations2 = expectations;
+
   // Apply some special transition to |map|.
   CHECK(map->owns_descriptors());
-  Handle<Map> map2 = config.Transition(map);
+  Handle<Map> map2 = config.Transition(map, expectations2);
 
   // |map| should still match expectations.
   CHECK(!map->is_deprecated());
   CHECK(expectations.Check(*map));
 
-  Expectations expectations2 = expectations;
   if (config.generalizes_representations()) {
     for (int i = 0; i < kPropCount; i++) {
       expectations2.GeneralizeRepresentation(i);
@@ -1694,10 +1973,10 @@
       for (int i = 0; i < kPropCount; i++) {
         expectations2.GeneralizeRepresentation(i);
       }
-      CHECK(new_map2->GetBackPointer()->IsUndefined());
+      CHECK(new_map2->GetBackPointer()->IsUndefined(isolate));
       CHECK(expectations2.Check(*new_map2));
     } else {
-      CHECK(!new_map2->GetBackPointer()->IsUndefined());
+      CHECK(!new_map2->GetBackPointer()->IsUndefined(isolate));
       CHECK(expectations2.Check(*new_map2));
     }
   }
@@ -1724,13 +2003,15 @@
       FieldType::Class(Map::Create(isolate, 0), isolate);
 
   struct TestConfig {
-    Handle<Map> Transition(Handle<Map> map) {
-      return Map::CopyAsElementsKind(map, DICTIONARY_ELEMENTS,
-                                     INSERT_TRANSITION);
+    Handle<Map> Transition(Handle<Map> map, Expectations& expectations) {
+      Handle<Symbol> frozen_symbol(map->GetHeap()->frozen_symbol());
+      expectations.SetElementsKind(DICTIONARY_ELEMENTS);
+      return Map::CopyForPreventExtensions(map, NONE, frozen_symbol,
+                                           "CopyForPreventExtensions");
     }
     // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
     bool generalizes_representations() const { return false; }
-    bool is_non_equevalent_transition() const { return false; }
+    bool is_non_equevalent_transition() const { return true; }
   };
   TestConfig config;
   TestGeneralizeRepresentationWithSpecialTransition(
@@ -1748,7 +2029,7 @@
       FieldType::Class(Map::Create(isolate, 0), isolate);
 
   struct TestConfig {
-    Handle<Map> Transition(Handle<Map> map) {
+    Handle<Map> Transition(Handle<Map> map, Expectations& expectations) {
       Isolate* isolate = CcTest::i_isolate();
       Handle<FieldType> any_type = FieldType::Any(isolate);
 
@@ -1760,65 +2041,10 @@
           .ToHandleChecked();
       CHECK(!map->owns_descriptors());
 
-      return Map::CopyAsElementsKind(map, DICTIONARY_ELEMENTS,
-                                     INSERT_TRANSITION);
-    }
-    // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
-    bool generalizes_representations() const { return false; }
-    bool is_non_equevalent_transition() const { return false; }
-  };
-  TestConfig config;
-  TestGeneralizeRepresentationWithSpecialTransition(
-      config, Representation::Smi(), any_type, Representation::HeapObject(),
-      value_type, Representation::Tagged(), any_type);
-}
-
-
-TEST(ForObservedTransitionFromMapOwningDescriptor) {
-  CcTest::InitializeVM();
-  v8::HandleScope scope(CcTest::isolate());
-  Isolate* isolate = CcTest::i_isolate();
-  Handle<FieldType> any_type = FieldType::Any(isolate);
-  Handle<FieldType> value_type =
-      FieldType::Class(Map::Create(isolate, 0), isolate);
-
-  struct TestConfig {
-    Handle<Map> Transition(Handle<Map> map) {
-      return Map::CopyForObserved(map);
-    }
-    // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
-    bool generalizes_representations() const { return false; }
-    bool is_non_equevalent_transition() const { return true; }
-  };
-  TestConfig config;
-  TestGeneralizeRepresentationWithSpecialTransition(
-      config, Representation::Smi(), any_type, Representation::HeapObject(),
-      value_type, Representation::Tagged(), any_type);
-}
-
-
-TEST(ForObservedTransitionFromMapNotOwningDescriptor) {
-  CcTest::InitializeVM();
-  v8::HandleScope scope(CcTest::isolate());
-  Isolate* isolate = CcTest::i_isolate();
-  Handle<FieldType> any_type = FieldType::Any(isolate);
-  Handle<FieldType> value_type =
-      FieldType::Class(Map::Create(isolate, 0), isolate);
-
-  struct TestConfig {
-    Handle<Map> Transition(Handle<Map> map) {
-      Isolate* isolate = CcTest::i_isolate();
-      Handle<FieldType> any_type = FieldType::Any(isolate);
-
-      // Add one more transition to |map| in order to prevent descriptors
-      // ownership.
-      CHECK(map->owns_descriptors());
-      Map::CopyWithField(map, MakeString("foo"), any_type, NONE,
-                         Representation::Smi(), INSERT_TRANSITION)
-          .ToHandleChecked();
-      CHECK(!map->owns_descriptors());
-
-      return Map::CopyForObserved(map);
+      Handle<Symbol> frozen_symbol(map->GetHeap()->frozen_symbol());
+      expectations.SetElementsKind(DICTIONARY_ELEMENTS);
+      return Map::CopyForPreventExtensions(map, NONE, frozen_symbol,
+                                           "CopyForPreventExtensions");
     }
     // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
     bool generalizes_representations() const { return false; }
@@ -1849,7 +2075,7 @@
       prototype_ = factory->NewJSObjectFromMap(Map::Create(isolate, 0));
     }
 
-    Handle<Map> Transition(Handle<Map> map) {
+    Handle<Map> Transition(Handle<Map> map, Expectations& expectations) {
       return Map::TransitionToPrototype(map, prototype_, REGULAR_PROTOTYPE);
     }
     // TODO(ishell): remove once IS_PROTO_TRANS_ISSUE_FIXED is removed.
@@ -1883,7 +2109,7 @@
       prototype_ = factory->NewJSObjectFromMap(Map::Create(isolate, 0));
     }
 
-    Handle<Map> Transition(Handle<Map> map) {
+    Handle<Map> Transition(Handle<Map> map, Expectations& expectations) {
       Isolate* isolate = CcTest::i_isolate();
       Handle<FieldType> any_type = FieldType::Any(isolate);
 
diff --git a/test/cctest/test-global-handles.cc b/test/cctest/test-global-handles.cc
index 22fd785..06e7466 100644
--- a/test/cctest/test-global-handles.cc
+++ b/test/cctest/test-global-handles.cc
@@ -417,3 +417,55 @@
   // Should not crash.
   g.SetWeak<void>(nullptr, &WeakCallback, v8::WeakCallbackType::kParameter);
 }
+
+void finalizer(const v8::WeakCallbackInfo<v8::Global<v8::Object>>& data) {
+  data.GetParameter()->ClearWeak();
+  v8::Local<v8::Object> o =
+      v8::Local<v8::Object>::New(data.GetIsolate(), *data.GetParameter());
+  o->Set(data.GetIsolate()->GetCurrentContext(), v8_str("finalizer"),
+         v8_str("was here"))
+      .FromJust();
+}
+
+TEST(FinalizerWeakness) {
+  CcTest::InitializeVM();
+  v8::Isolate* isolate = CcTest::isolate();
+
+  v8::Global<v8::Object> g;
+  int identity;
+
+  {
+    v8::HandleScope scope(isolate);
+    v8::Local<v8::Object> o = v8::Object::New(isolate);
+    identity = o->GetIdentityHash();
+    g.Reset(isolate, o);
+    g.SetWeak(&g, finalizer, v8::WeakCallbackType::kFinalizer);
+  }
+
+  CcTest::i_isolate()->heap()->CollectAllAvailableGarbage();
+
+  CHECK(!g.IsEmpty());
+  v8::HandleScope scope(isolate);
+  v8::Local<v8::Object> o = v8::Local<v8::Object>::New(isolate, g);
+  CHECK_EQ(identity, o->GetIdentityHash());
+  CHECK(o->Has(isolate->GetCurrentContext(), v8_str("finalizer")).FromJust());
+}
+
+TEST(PhatomHandlesWithoutCallbacks) {
+  CcTest::InitializeVM();
+  v8::Isolate* isolate = CcTest::isolate();
+
+  v8::Global<v8::Object> g1, g2;
+  {
+    v8::HandleScope scope(isolate);
+    g1.Reset(isolate, v8::Object::New(isolate));
+    g1.SetWeak();
+    g2.Reset(isolate, v8::Object::New(isolate));
+    g2.SetWeak();
+  }
+
+  CHECK_EQ(0, isolate->NumberOfPhantomHandleResetsSinceLastCall());
+  CcTest::i_isolate()->heap()->CollectAllAvailableGarbage();
+  CHECK_EQ(2, isolate->NumberOfPhantomHandleResetsSinceLastCall());
+  CHECK_EQ(0, isolate->NumberOfPhantomHandleResetsSinceLastCall());
+}
diff --git a/test/cctest/test-hashmap.cc b/test/cctest/test-hashmap.cc
index b45d6c7..2d423b4 100644
--- a/test/cctest/test-hashmap.cc
+++ b/test/cctest/test-hashmap.cc
@@ -30,7 +30,7 @@
 #include "src/v8.h"
 #include "test/cctest/cctest.h"
 
-#include "src/hashmap.h"
+#include "src/base/hashmap.h"
 
 using namespace v8::internal;
 
@@ -48,7 +48,7 @@
 
   void Insert(int x) {
     CHECK_NE(0, x);  // 0 corresponds to (void*)NULL - illegal key value
-    HashMap::Entry* p =
+    v8::base::HashMap::Entry* p =
         map_.LookupOrInsert(reinterpret_cast<void*>(x), hash_(x));
     CHECK(p != NULL);  // insert is set!
     CHECK_EQ(reinterpret_cast<void*>(x), p->key);
@@ -61,7 +61,8 @@
   }
 
   bool Present(int x) {
-    HashMap::Entry* p = map_.Lookup(reinterpret_cast<void*>(x), hash_(x));
+    v8::base::HashMap::Entry* p =
+        map_.Lookup(reinterpret_cast<void*>(x), hash_(x));
     if (p != NULL) {
       CHECK_EQ(reinterpret_cast<void*>(x), p->key);
     }
@@ -74,7 +75,8 @@
 
   uint32_t occupancy() const {
     uint32_t count = 0;
-    for (HashMap::Entry* p = map_.Start(); p != NULL; p = map_.Next(p)) {
+    for (v8::base::HashMap::Entry* p = map_.Start(); p != NULL;
+         p = map_.Next(p)) {
       count++;
     }
     CHECK_EQ(map_.occupancy(), static_cast<double>(count));
@@ -83,7 +85,7 @@
 
  private:
   IntKeyHash hash_;
-  HashMap map_;
+  v8::base::HashMap map_;
 };
 
 
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index dfe5911..f8f1586 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -32,9 +32,9 @@
 #include "src/v8.h"
 
 #include "include/v8-profiler.h"
+#include "src/base/hashmap.h"
 #include "src/collector.h"
 #include "src/debug/debug.h"
-#include "src/hashmap.h"
 #include "src/profiler/allocation-tracker.h"
 #include "src/profiler/heap-profiler.h"
 #include "src/profiler/heap-snapshot-generator-inl.h"
@@ -43,7 +43,7 @@
 using i::AllocationTraceNode;
 using i::AllocationTraceTree;
 using i::AllocationTracker;
-using i::HashMap;
+using i::ArrayVector;
 using i::Vector;
 
 namespace {
@@ -65,7 +65,7 @@
   }
 
   void CheckAllReachables(i::HeapEntry* root) {
-    i::HashMap visited(AddressesMatch);
+    v8::base::HashMap visited(AddressesMatch);
     i::List<i::HeapEntry*> list(10);
     list.Add(root);
     CheckEntry(root);
@@ -75,7 +75,7 @@
       for (int i = 0; i < children.length(); ++i) {
         if (children[i]->type() == i::HeapGraphEdge::kShortcut) continue;
         i::HeapEntry* child = children[i]->to();
-        i::HashMap::Entry* entry = visited.LookupOrInsert(
+        v8::base::HashMap::Entry* entry = visited.LookupOrInsert(
             reinterpret_cast<void*>(child),
             static_cast<uint32_t>(reinterpret_cast<uintptr_t>(child)));
         if (entry->value)
@@ -143,10 +143,10 @@
   i::HeapSnapshot* heap_snapshot = const_cast<i::HeapSnapshot*>(
       reinterpret_cast<const i::HeapSnapshot*>(snapshot));
 
-  i::HashMap visited(AddressesMatch);
+  v8::base::HashMap visited(AddressesMatch);
   i::List<i::HeapGraphEdge>& edges = heap_snapshot->edges();
   for (int i = 0; i < edges.length(); ++i) {
-    i::HashMap::Entry* entry = visited.LookupOrInsert(
+    v8::base::HashMap::Entry* entry = visited.LookupOrInsert(
         reinterpret_cast<void*>(edges[i].to()),
         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(edges[i].to())));
     uint32_t ref_count = static_cast<uint32_t>(
@@ -156,7 +156,7 @@
   uint32_t unretained_entries_count = 0;
   i::List<i::HeapEntry>& entries = heap_snapshot->entries();
   for (int i = 0; i < entries.length(); ++i) {
-    i::HashMap::Entry* entry = visited.Lookup(
+    v8::base::HashMap::Entry* entry = visited.Lookup(
         reinterpret_cast<void*>(&entries[i]),
         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(&entries[i])));
     if (!entry && entries[i].id() != 1) {
@@ -2513,8 +2513,7 @@
   // Print for better diagnostics in case of failure.
   tracker->trace_tree()->Print(tracker);
 
-  AllocationTraceNode* node =
-      FindNode(tracker, Vector<const char*>(names, arraysize(names)));
+  AllocationTraceNode* node = FindNode(tracker, ArrayVector(names));
   CHECK(node);
   CHECK_GE(node->allocation_count(), 2u);
   CHECK_GE(node->allocation_size(), 4u * 5u);
@@ -2540,8 +2539,7 @@
   tracker->trace_tree()->Print(tracker);
 
   const char* names[] = {"", "start", "f_0_0", "f_0_1", "f_0_2"};
-  AllocationTraceNode* node =
-      FindNode(tracker, Vector<const char*>(names, arraysize(names)));
+  AllocationTraceNode* node = FindNode(tracker, ArrayVector(names));
   CHECK(node);
   CHECK_GE(node->allocation_count(), 100u);
   CHECK_GE(node->allocation_size(), 4 * node->allocation_count());
@@ -2590,8 +2588,7 @@
     // Print for better diagnostics in case of failure.
     tracker->trace_tree()->Print(tracker);
 
-    AllocationTraceNode* node =
-        FindNode(tracker, Vector<const char*>(names, arraysize(names)));
+    AllocationTraceNode* node = FindNode(tracker, ArrayVector(names));
     CHECK(node);
     CHECK_GE(node->allocation_count(), 100u);
     CHECK_GE(node->allocation_size(), 4 * node->allocation_count());
@@ -2616,8 +2613,7 @@
     // Print for better diagnostics in case of failure.
     tracker->trace_tree()->Print(tracker);
 
-    AllocationTraceNode* node =
-        FindNode(tracker, Vector<const char*>(names, arraysize(names)));
+    AllocationTraceNode* node = FindNode(tracker, ArrayVector(names));
     CHECK(node);
     CHECK_LT(node->allocation_count(), 100u);
 
@@ -2646,8 +2642,7 @@
   // Print for better diagnostics in case of failure.
   tracker->trace_tree()->Print(tracker);
 
-  AllocationTraceNode* node =
-      FindNode(tracker, Vector<const char*>(names, arraysize(names)));
+  AllocationTraceNode* node = FindNode(tracker, ArrayVector(names));
   CHECK(node);
   CHECK_GE(node->allocation_count(), 2u);
   CHECK_GE(node->allocation_size(), 4 * node->allocation_count());
@@ -2875,6 +2870,15 @@
   return node;
 }
 
+static void CheckNoZeroCountNodes(v8::AllocationProfile::Node* node) {
+  for (auto alloc : node->allocations) {
+    CHECK_GT(alloc.count, 0u);
+  }
+  for (auto child : node->children) {
+    CheckNoZeroCountNodes(child);
+  }
+}
+
 TEST(SamplingHeapProfiler) {
   v8::HandleScope scope(v8::Isolate::GetCurrent());
   LocalContext env;
@@ -2913,8 +2917,7 @@
     CHECK(!profile.is_empty());
 
     const char* names[] = {"", "foo", "bar"};
-    auto node_bar = FindAllocationProfileNode(
-        *profile, Vector<const char*>(names, arraysize(names)));
+    auto node_bar = FindAllocationProfileNode(*profile, ArrayVector(names));
     CHECK(node_bar);
 
     // Count the number of allocations we sampled from bar.
@@ -2941,8 +2944,7 @@
     CHECK(!profile.is_empty());
 
     const char* names[] = {"", "foo", "bar"};
-    auto node_bar = FindAllocationProfileNode(
-        *profile, Vector<const char*>(names, arraysize(names)));
+    auto node_bar = FindAllocationProfileNode(*profile, ArrayVector(names));
     CHECK(node_bar);
 
     // Count the number of allocations we sampled from bar.
@@ -2976,13 +2978,11 @@
     CHECK(!profile.is_empty());
 
     const char* names1[] = {"", "start", "f_0_0", "f_0_1", "f_0_2"};
-    auto node1 = FindAllocationProfileNode(
-        *profile, Vector<const char*>(names1, arraysize(names1)));
+    auto node1 = FindAllocationProfileNode(*profile, ArrayVector(names1));
     CHECK(node1);
 
     const char* names2[] = {"", "generateFunctions"};
-    auto node2 = FindAllocationProfileNode(
-        *profile, Vector<const char*>(names2, arraysize(names2)));
+    auto node2 = FindAllocationProfileNode(*profile, ArrayVector(names2));
     CHECK(node2);
 
     heap_profiler->StopSamplingHeapProfiler();
@@ -3002,6 +3002,8 @@
         heap_profiler->GetAllocationProfile());
     CHECK(!profile.is_empty());
 
+    CheckNoZeroCountNodes(profile->GetRootNode());
+
     heap_profiler->StopSamplingHeapProfiler();
   }
 }
@@ -3023,8 +3025,7 @@
       heap_profiler->GetAllocationProfile());
   CHECK(!profile.is_empty());
   const char* names[] = {"(V8 API)"};
-  auto node = FindAllocationProfileNode(
-      *profile, Vector<const char*>(names, arraysize(names)));
+  auto node = FindAllocationProfileNode(*profile, ArrayVector(names));
   CHECK(node);
 
   heap_profiler->StopSamplingHeapProfiler();
diff --git a/test/cctest/test-inobject-slack-tracking.cc b/test/cctest/test-inobject-slack-tracking.cc
index 004781a..9f33d55 100644
--- a/test/cctest/test-inobject-slack-tracking.cc
+++ b/test/cctest/test-inobject-slack-tracking.cc
@@ -925,15 +925,14 @@
   v8::HandleScope scope(CcTest::isolate());
 
   const int first_field = 2;
-  TestSubclassBuiltin("A1", JS_OBJECT_TYPE, "Error", "'err'", first_field);
-  TestSubclassBuiltin("A2", JS_OBJECT_TYPE, "EvalError", "'err'", first_field);
-  TestSubclassBuiltin("A3", JS_OBJECT_TYPE, "RangeError", "'err'", first_field);
-  TestSubclassBuiltin("A4", JS_OBJECT_TYPE, "ReferenceError", "'err'",
+  TestSubclassBuiltin("A1", JS_ERROR_TYPE, "Error", "'err'", first_field);
+  TestSubclassBuiltin("A2", JS_ERROR_TYPE, "EvalError", "'err'", first_field);
+  TestSubclassBuiltin("A3", JS_ERROR_TYPE, "RangeError", "'err'", first_field);
+  TestSubclassBuiltin("A4", JS_ERROR_TYPE, "ReferenceError", "'err'",
                       first_field);
-  TestSubclassBuiltin("A5", JS_OBJECT_TYPE, "SyntaxError", "'err'",
-                      first_field);
-  TestSubclassBuiltin("A6", JS_OBJECT_TYPE, "TypeError", "'err'", first_field);
-  TestSubclassBuiltin("A7", JS_OBJECT_TYPE, "URIError", "'err'", first_field);
+  TestSubclassBuiltin("A5", JS_ERROR_TYPE, "SyntaxError", "'err'", first_field);
+  TestSubclassBuiltin("A6", JS_ERROR_TYPE, "TypeError", "'err'", first_field);
+  TestSubclassBuiltin("A7", JS_ERROR_TYPE, "URIError", "'err'", first_field);
 }
 
 
@@ -1100,7 +1099,7 @@
   CcTest::InitializeVM();
   v8::HandleScope scope(CcTest::isolate());
 
-  const int first_field = 4;
+  const int first_field = 5;
   TestSubclassBuiltin("A1", JS_PROMISE_TYPE, "Promise",
                       "function(resolve, reject) { resolve('ok'); }",
                       first_field);
diff --git a/test/cctest/test-log-stack-tracer.cc b/test/cctest/test-log-stack-tracer.cc
index 05d7103..e38d74e 100644
--- a/test/cctest/test-log-stack-tracer.cc
+++ b/test/cctest/test-log-stack-tracer.cc
@@ -36,7 +36,7 @@
 #include "src/disassembler.h"
 #include "src/isolate.h"
 #include "src/log.h"
-#include "src/profiler/sampler.h"
+#include "src/profiler/tick-sample.h"
 #include "src/vm-state-inl.h"
 #include "test/cctest/cctest.h"
 #include "test/cctest/trace-extension.h"
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index 9c7e63b..b6bb256 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -375,9 +375,8 @@
     ObjMethod1_entry = *FUNCTION_ENTRYPOINT_ADDRESS(ObjMethod1_entry);
 #endif
     i::EmbeddedVector<char, 100> ref_data;
-    i::SNPrintF(ref_data,
-                "code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"method1\"",
-                reinterpret_cast<intptr_t>(ObjMethod1_entry));
+    i::SNPrintF(ref_data, "code-creation,Callback,-2,%p,1,\"method1\"",
+                static_cast<void*>(ObjMethod1_entry));
 
     CHECK(StrNStr(log.start(), ref_data.start(), log.length()));
     log.Dispose();
@@ -429,8 +428,8 @@
 #endif
     EmbeddedVector<char, 100> prop1_getter_record;
     i::SNPrintF(prop1_getter_record,
-                "code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"get prop1\"",
-                reinterpret_cast<intptr_t>(Prop1Getter_entry));
+                "code-creation,Callback,-2,%p,1,\"get prop1\"",
+                static_cast<void*>(Prop1Getter_entry));
     CHECK(StrNStr(log.start(), prop1_getter_record.start(), log.length()));
 
     Address Prop1Setter_entry = reinterpret_cast<Address>(Prop1Setter);
@@ -439,8 +438,8 @@
 #endif
     EmbeddedVector<char, 100> prop1_setter_record;
     i::SNPrintF(prop1_setter_record,
-                "code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"set prop1\"",
-                reinterpret_cast<intptr_t>(Prop1Setter_entry));
+                "code-creation,Callback,-2,%p,1,\"set prop1\"",
+                static_cast<void*>(Prop1Setter_entry));
     CHECK(StrNStr(log.start(), prop1_setter_record.start(), log.length()));
 
     Address Prop2Getter_entry = reinterpret_cast<Address>(Prop2Getter);
@@ -449,8 +448,8 @@
 #endif
     EmbeddedVector<char, 100> prop2_getter_record;
     i::SNPrintF(prop2_getter_record,
-                "code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"get prop2\"",
-                reinterpret_cast<intptr_t>(Prop2Getter_entry));
+                "code-creation,Callback,-2,%p,1,\"get prop2\"",
+                static_cast<void*>(Prop2Getter_entry));
     CHECK(StrNStr(log.start(), prop2_getter_record.start(), log.length()));
     log.Dispose();
   }
diff --git a/test/cctest/test-macro-assembler-mips.cc b/test/cctest/test-macro-assembler-mips.cc
index 91ee215..748198b 100644
--- a/test/cctest/test-macro-assembler-mips.cc
+++ b/test/cctest/test-macro-assembler-mips.cc
@@ -60,6 +60,71 @@
   return true;
 }
 
+TEST(BYTESWAP) {
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  HandleScope handles(isolate);
+
+  struct T {
+    int32_t r1;
+    int32_t r2;
+    int32_t r3;
+    int32_t r4;
+    int32_t r5;
+  };
+  T t;
+
+  MacroAssembler assembler(isolate, NULL, 0,
+                           v8::internal::CodeObjectRequired::kYes);
+  MacroAssembler* masm = &assembler;
+
+  __ lw(a2, MemOperand(a0, offsetof(T, r1)));
+  __ nop();
+  __ ByteSwapSigned(a2, 4);
+  __ sw(a2, MemOperand(a0, offsetof(T, r1)));
+
+  __ lw(a2, MemOperand(a0, offsetof(T, r2)));
+  __ nop();
+  __ ByteSwapSigned(a2, 2);
+  __ sw(a2, MemOperand(a0, offsetof(T, r2)));
+
+  __ lw(a2, MemOperand(a0, offsetof(T, r3)));
+  __ nop();
+  __ ByteSwapSigned(a2, 1);
+  __ sw(a2, MemOperand(a0, offsetof(T, r3)));
+
+  __ lw(a2, MemOperand(a0, offsetof(T, r4)));
+  __ nop();
+  __ ByteSwapUnsigned(a2, 1);
+  __ sw(a2, MemOperand(a0, offsetof(T, r4)));
+
+  __ lw(a2, MemOperand(a0, offsetof(T, r5)));
+  __ nop();
+  __ ByteSwapUnsigned(a2, 2);
+  __ sw(a2, MemOperand(a0, offsetof(T, r5)));
+
+  __ jr(ra);
+  __ nop();
+
+  CodeDesc desc;
+  masm->GetCode(&desc);
+  Handle<Code> code = isolate->factory()->NewCode(
+      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+  ::F3 f = FUNCTION_CAST<::F3>(code->entry());
+  t.r1 = 0x781A15C3;
+  t.r2 = 0x2CDE;
+  t.r3 = 0x9F;
+  t.r4 = 0x9F;
+  t.r5 = 0x2CDE;
+  Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
+  USE(dummy);
+
+  CHECK_EQ(static_cast<int32_t>(0xC3151A78), t.r1);
+  CHECK_EQ(static_cast<int32_t>(0xDE2C0000), t.r2);
+  CHECK_EQ(static_cast<int32_t>(0x9FFFFFFF), t.r3);
+  CHECK_EQ(static_cast<int32_t>(0x9F000000), t.r4);
+  CHECK_EQ(static_cast<int32_t>(0xDE2C0000), t.r5);
+}
 
 TEST(CopyBytes) {
   CcTest::InitializeVM();
@@ -390,14 +455,14 @@
   }
 }
 
-static const std::vector<uint32_t> uint32_test_values() {
+static const std::vector<uint32_t> cvt_trunc_uint32_test_values() {
   static const uint32_t kValues[] = {0x00000000, 0x00000001, 0x00ffff00,
                                      0x7fffffff, 0x80000000, 0x80000001,
                                      0x80ffff00, 0x8fffffff, 0xffffffff};
   return std::vector<uint32_t>(&kValues[0], &kValues[arraysize(kValues)]);
 }
 
-static const std::vector<int32_t> int32_test_values() {
+static const std::vector<int32_t> cvt_trunc_int32_test_values() {
   static const int32_t kValues[] = {
       static_cast<int32_t>(0x00000000), static_cast<int32_t>(0x00000001),
       static_cast<int32_t>(0x00ffff00), static_cast<int32_t>(0x7fffffff),
@@ -408,13 +473,31 @@
 }
 
 // Helper macros that can be used in FOR_INT32_INPUTS(i) { ... *i ... }
-#define FOR_INPUTS(ctype, itype, var)                        \
-  std::vector<ctype> var##_vec = itype##_test_values();      \
+#define FOR_INPUTS(ctype, itype, var, test_vector)           \
+  std::vector<ctype> var##_vec = test_vector();              \
   for (std::vector<ctype>::iterator var = var##_vec.begin(); \
        var != var##_vec.end(); ++var)
 
-#define FOR_UINT32_INPUTS(var) FOR_INPUTS(uint32_t, uint32, var)
-#define FOR_INT32_INPUTS(var) FOR_INPUTS(int32_t, int32, var)
+#define FOR_INPUTS2(ctype, itype, var, var2, test_vector)  \
+  std::vector<ctype> var##_vec = test_vector();            \
+  std::vector<ctype>::iterator var;                        \
+  std::vector<ctype>::reverse_iterator var2;               \
+  for (var = var##_vec.begin(), var2 = var##_vec.rbegin(); \
+       var != var##_vec.end(); ++var, ++var2)
+
+#define FOR_ENUM_INPUTS(var, type, test_vector) \
+  FOR_INPUTS(enum type, type, var, test_vector)
+#define FOR_STRUCT_INPUTS(var, type, test_vector) \
+  FOR_INPUTS(struct type, type, var, test_vector)
+#define FOR_UINT32_INPUTS(var, test_vector) \
+  FOR_INPUTS(uint32_t, uint32, var, test_vector)
+#define FOR_INT32_INPUTS(var, test_vector) \
+  FOR_INPUTS(int32_t, int32, var, test_vector)
+#define FOR_INT32_INPUTS2(var, var2, test_vector) \
+  FOR_INPUTS2(int32_t, int32, var, var2, test_vector)
+
+#define FOR_UINT64_INPUTS(var, test_vector) \
+  FOR_INPUTS(uint64_t, uint32, var, test_vector)
 
 template <typename RET_TYPE, typename IN_TYPE, typename Func>
 RET_TYPE run_Cvt(IN_TYPE x, Func GenerateConvertInstructionFunc) {
@@ -445,7 +528,7 @@
 
 TEST(cvt_s_w_Trunc_uw_s) {
   CcTest::InitializeVM();
-  FOR_UINT32_INPUTS(i) {
+  FOR_UINT32_INPUTS(i, cvt_trunc_uint32_test_values) {
     uint32_t input = *i;
     CHECK_EQ(static_cast<float>(input),
              run_Cvt<uint32_t>(input, [](MacroAssembler* masm) {
@@ -457,7 +540,7 @@
 
 TEST(cvt_d_w_Trunc_w_d) {
   CcTest::InitializeVM();
-  FOR_INT32_INPUTS(i) {
+  FOR_INT32_INPUTS(i, cvt_trunc_int32_test_values) {
     int32_t input = *i;
     CHECK_EQ(static_cast<double>(input),
              run_Cvt<int32_t>(input, [](MacroAssembler* masm) {
@@ -467,6 +550,342 @@
   }
 }
 
+static const std::vector<int32_t> overflow_int32_test_values() {
+  static const int32_t kValues[] = {
+      static_cast<int32_t>(0xf0000000), static_cast<int32_t>(0x00000001),
+      static_cast<int32_t>(0xff000000), static_cast<int32_t>(0x0000f000),
+      static_cast<int32_t>(0x0f000000), static_cast<int32_t>(0x991234ab),
+      static_cast<int32_t>(0xb0ffff01), static_cast<int32_t>(0x00006fff),
+      static_cast<int32_t>(0xffffffff)};
+  return std::vector<int32_t>(&kValues[0], &kValues[arraysize(kValues)]);
+}
+
+enum OverflowBranchType {
+  kAddBranchOverflow,
+  kSubBranchOverflow,
+};
+
+struct OverflowRegisterCombination {
+  Register dst;
+  Register left;
+  Register right;
+  Register scratch;
+};
+
+static const std::vector<enum OverflowBranchType> overflow_branch_type() {
+  static const enum OverflowBranchType kValues[] = {kAddBranchOverflow,
+                                                    kSubBranchOverflow};
+  return std::vector<enum OverflowBranchType>(&kValues[0],
+                                              &kValues[arraysize(kValues)]);
+}
+
+static const std::vector<struct OverflowRegisterCombination>
+overflow_register_combination() {
+  static const struct OverflowRegisterCombination kValues[] = {
+      {t0, t1, t2, t3}, {t0, t0, t2, t3}, {t0, t1, t0, t3}, {t0, t1, t1, t3}};
+  return std::vector<struct OverflowRegisterCombination>(
+      &kValues[0], &kValues[arraysize(kValues)]);
+}
+
+template <typename T>
+static bool IsAddOverflow(T x, T y) {
+  DCHECK(std::numeric_limits<T>::is_integer);
+  T max = std::numeric_limits<T>::max();
+  T min = std::numeric_limits<T>::min();
+
+  return (x > 0 && y > (max - x)) || (x < 0 && y < (min - x));
+}
+
+template <typename T>
+static bool IsSubOverflow(T x, T y) {
+  DCHECK(std::numeric_limits<T>::is_integer);
+  T max = std::numeric_limits<T>::max();
+  T min = std::numeric_limits<T>::min();
+
+  return (y > 0 && x < (min + y)) || (y < 0 && x > (max + y));
+}
+
+template <typename IN_TYPE, typename Func>
+static bool runOverflow(IN_TYPE valLeft, IN_TYPE valRight,
+                        Func GenerateOverflowInstructions) {
+  typedef int32_t (*F_CVT)(char* x0, int x1, int x2, int x3, int x4);
+
+  Isolate* isolate = CcTest::i_isolate();
+  HandleScope scope(isolate);
+  MacroAssembler assm(isolate, nullptr, 0,
+                      v8::internal::CodeObjectRequired::kYes);
+  MacroAssembler* masm = &assm;
+
+  GenerateOverflowInstructions(masm, valLeft, valRight);
+  __ jr(ra);
+  __ nop();
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Handle<Code> code = isolate->factory()->NewCode(
+      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+
+  F_CVT f = FUNCTION_CAST<F_CVT>(code->entry());
+
+  int32_t r =
+      reinterpret_cast<int32_t>(CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
+
+  DCHECK(r == 0 || r == 1);
+  return r;
+}
+
+TEST(BranchOverflowInt32BothLabels) {
+  FOR_INT32_INPUTS(i, overflow_int32_test_values) {
+    FOR_INT32_INPUTS(j, overflow_int32_test_values) {
+      FOR_ENUM_INPUTS(br, OverflowBranchType, overflow_branch_type) {
+        FOR_STRUCT_INPUTS(regComb, OverflowRegisterCombination,
+                          overflow_register_combination) {
+          int32_t ii = *i;
+          int32_t jj = *j;
+          enum OverflowBranchType branchType = *br;
+          struct OverflowRegisterCombination rc = *regComb;
+
+          // If left and right register are same then left and right
+          // test values must also be same, otherwise we skip the test
+          if (rc.left.code() == rc.right.code()) {
+            if (ii != jj) {
+              continue;
+            }
+          }
+
+          bool res1 = runOverflow<int32_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft,
+                                       int32_t valRight) {
+                Label overflow, no_overflow, end;
+                __ li(rc.left, valLeft);
+                __ li(rc.right, valRight);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ AddBranchOvf(rc.dst, rc.left, rc.right, &overflow,
+                                    &no_overflow, rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ SubBranchOvf(rc.dst, rc.left, rc.right, &overflow,
+                                    &no_overflow, rc.scratch);
+                    break;
+                }
+                __ li(v0, 2);
+                __ Branch(&end);
+                __ bind(&overflow);
+                __ li(v0, 1);
+                __ Branch(&end);
+                __ bind(&no_overflow);
+                __ li(v0, 0);
+                __ bind(&end);
+              });
+
+          bool res2 = runOverflow<int32_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft,
+                                       int32_t valRight) {
+                Label overflow, no_overflow, end;
+                __ li(rc.left, valLeft);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ AddBranchOvf(rc.dst, rc.left, Operand(valRight),
+                                    &overflow, &no_overflow, rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ SubBranchOvf(rc.dst, rc.left, Operand(valRight),
+                                    &overflow, &no_overflow, rc.scratch);
+                    break;
+                }
+                __ li(v0, 2);
+                __ Branch(&end);
+                __ bind(&overflow);
+                __ li(v0, 1);
+                __ Branch(&end);
+                __ bind(&no_overflow);
+                __ li(v0, 0);
+                __ bind(&end);
+              });
+
+          switch (branchType) {
+            case kAddBranchOverflow:
+              CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res1);
+              CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res2);
+              break;
+            case kSubBranchOverflow:
+              CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res1);
+              CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res2);
+              break;
+            default:
+              UNREACHABLE();
+          }
+        }
+      }
+    }
+  }
+}
+
+TEST(BranchOverflowInt32LeftLabel) {
+  FOR_INT32_INPUTS(i, overflow_int32_test_values) {
+    FOR_INT32_INPUTS(j, overflow_int32_test_values) {
+      FOR_ENUM_INPUTS(br, OverflowBranchType, overflow_branch_type) {
+        FOR_STRUCT_INPUTS(regComb, OverflowRegisterCombination,
+                          overflow_register_combination) {
+          int32_t ii = *i;
+          int32_t jj = *j;
+          enum OverflowBranchType branchType = *br;
+          struct OverflowRegisterCombination rc = *regComb;
+
+          // If left and right register are same then left and right
+          // test values must also be same, otherwise we skip the test
+          if (rc.left.code() == rc.right.code()) {
+            if (ii != jj) {
+              continue;
+            }
+          }
+
+          bool res1 = runOverflow<int32_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft,
+                                       int32_t valRight) {
+                Label overflow, end;
+                __ li(rc.left, valLeft);
+                __ li(rc.right, valRight);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ AddBranchOvf(rc.dst, rc.left, rc.right, &overflow, NULL,
+                                    rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ SubBranchOvf(rc.dst, rc.left, rc.right, &overflow, NULL,
+                                    rc.scratch);
+                    break;
+                }
+                __ li(v0, 0);
+                __ Branch(&end);
+                __ bind(&overflow);
+                __ li(v0, 1);
+                __ bind(&end);
+              });
+
+          bool res2 = runOverflow<int32_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft,
+                                       int32_t valRight) {
+                Label overflow, end;
+                __ li(rc.left, valLeft);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ AddBranchOvf(rc.dst, rc.left, Operand(valRight),
+                                    &overflow, NULL, rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ SubBranchOvf(rc.dst, rc.left, Operand(valRight),
+                                    &overflow, NULL, rc.scratch);
+                    break;
+                }
+                __ li(v0, 0);
+                __ Branch(&end);
+                __ bind(&overflow);
+                __ li(v0, 1);
+                __ bind(&end);
+              });
+
+          switch (branchType) {
+            case kAddBranchOverflow:
+              CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res1);
+              CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res2);
+              break;
+            case kSubBranchOverflow:
+              CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res1);
+              CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res2);
+              break;
+            default:
+              UNREACHABLE();
+          }
+        }
+      }
+    }
+  }
+}
+
+TEST(BranchOverflowInt32RightLabel) {
+  FOR_INT32_INPUTS(i, overflow_int32_test_values) {
+    FOR_INT32_INPUTS(j, overflow_int32_test_values) {
+      FOR_ENUM_INPUTS(br, OverflowBranchType, overflow_branch_type) {
+        FOR_STRUCT_INPUTS(regComb, OverflowRegisterCombination,
+                          overflow_register_combination) {
+          int32_t ii = *i;
+          int32_t jj = *j;
+          enum OverflowBranchType branchType = *br;
+          struct OverflowRegisterCombination rc = *regComb;
+
+          // If left and right register are same then left and right
+          // test values must also be same, otherwise we skip the test
+          if (rc.left.code() == rc.right.code()) {
+            if (ii != jj) {
+              continue;
+            }
+          }
+
+          bool res1 = runOverflow<int32_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft,
+                                       int32_t valRight) {
+                Label no_overflow, end;
+                __ li(rc.left, valLeft);
+                __ li(rc.right, valRight);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ AddBranchOvf(rc.dst, rc.left, rc.right, NULL,
+                                    &no_overflow, rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ SubBranchOvf(rc.dst, rc.left, rc.right, NULL,
+                                    &no_overflow, rc.scratch);
+                    break;
+                }
+                __ li(v0, 1);
+                __ Branch(&end);
+                __ bind(&no_overflow);
+                __ li(v0, 0);
+                __ bind(&end);
+              });
+
+          bool res2 = runOverflow<int32_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft,
+                                       int32_t valRight) {
+                Label no_overflow, end;
+                __ li(rc.left, valLeft);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ AddBranchOvf(rc.dst, rc.left, Operand(valRight), NULL,
+                                    &no_overflow, rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ SubBranchOvf(rc.dst, rc.left, Operand(valRight), NULL,
+                                    &no_overflow, rc.scratch);
+                    break;
+                }
+                __ li(v0, 1);
+                __ Branch(&end);
+                __ bind(&no_overflow);
+                __ li(v0, 0);
+                __ bind(&end);
+              });
+
+          switch (branchType) {
+            case kAddBranchOverflow:
+              CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res1);
+              CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res2);
+              break;
+            case kSubBranchOverflow:
+              CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res1);
+              CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res2);
+              break;
+            default:
+              UNREACHABLE();
+          }
+        }
+      }
+    }
+  }
+}
+
 TEST(min_max_nan) {
   CcTest::InitializeVM();
   Isolate* isolate = CcTest::i_isolate();
@@ -577,4 +996,241 @@
   }
 }
 
+template <typename IN_TYPE, typename Func>
+bool run_Unaligned(char* memory_buffer, int32_t in_offset, int32_t out_offset,
+                   IN_TYPE value, Func GenerateUnalignedInstructionFunc) {
+  typedef int32_t (*F_CVT)(char* x0, int x1, int x2, int x3, int x4);
+
+  Isolate* isolate = CcTest::i_isolate();
+  HandleScope scope(isolate);
+  MacroAssembler assm(isolate, nullptr, 0,
+                      v8::internal::CodeObjectRequired::kYes);
+  MacroAssembler* masm = &assm;
+  IN_TYPE res;
+
+  GenerateUnalignedInstructionFunc(masm, in_offset, out_offset);
+  __ jr(ra);
+  __ nop();
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Handle<Code> code = isolate->factory()->NewCode(
+      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+
+  F_CVT f = FUNCTION_CAST<F_CVT>(code->entry());
+
+  MemCopy(memory_buffer + in_offset, &value, sizeof(IN_TYPE));
+  CALL_GENERATED_CODE(isolate, f, memory_buffer, 0, 0, 0, 0);
+  MemCopy(&res, memory_buffer + out_offset, sizeof(IN_TYPE));
+
+  return res == value;
+}
+
+static const std::vector<uint64_t> unsigned_test_values() {
+  static const uint64_t kValues[] = {
+      0x2180f18a06384414, 0x000a714532102277, 0xbc1acccf180649f0,
+      0x8000000080008000, 0x0000000000000001, 0xffffffffffffffff,
+  };
+  return std::vector<uint64_t>(&kValues[0], &kValues[arraysize(kValues)]);
+}
+
+static const std::vector<int32_t> unsigned_test_offset() {
+  static const int32_t kValues[] = {// value, offset
+                                    -132 * KB, -21 * KB, 0, 19 * KB, 135 * KB};
+  return std::vector<int32_t>(&kValues[0], &kValues[arraysize(kValues)]);
+}
+
+static const std::vector<int32_t> unsigned_test_offset_increment() {
+  static const int32_t kValues[] = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5};
+  return std::vector<int32_t>(&kValues[0], &kValues[arraysize(kValues)]);
+}
+
+TEST(Ulh) {
+  CcTest::InitializeVM();
+
+  static const int kBufferSize = 300 * KB;
+  char memory_buffer[kBufferSize];
+  char* buffer_middle = memory_buffer + (kBufferSize / 2);
+
+  FOR_UINT64_INPUTS(i, unsigned_test_values) {
+    FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) {
+      FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) {
+        uint16_t value = static_cast<uint64_t>(*i & 0xFFFF);
+        int32_t in_offset = *j1 + *k1;
+        int32_t out_offset = *j2 + *k2;
+
+        CHECK_EQ(true, run_Unaligned<uint16_t>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             __ Ulh(v0, MemOperand(a0, in_offset));
+                             __ Ush(v0, MemOperand(a0, out_offset), v0);
+                           }));
+        CHECK_EQ(true, run_Unaligned<uint16_t>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             __ mov(t0, a0);
+                             __ Ulh(a0, MemOperand(a0, in_offset));
+                             __ Ush(a0, MemOperand(t0, out_offset), v0);
+                           }));
+        CHECK_EQ(true, run_Unaligned<uint16_t>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             __ mov(t0, a0);
+                             __ Ulhu(a0, MemOperand(a0, in_offset));
+                             __ Ush(a0, MemOperand(t0, out_offset), t1);
+                           }));
+        CHECK_EQ(true, run_Unaligned<uint16_t>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             __ Ulhu(v0, MemOperand(a0, in_offset));
+                             __ Ush(v0, MemOperand(a0, out_offset), t1);
+                           }));
+      }
+    }
+  }
+}
+
+TEST(Ulh_bitextension) {
+  CcTest::InitializeVM();
+
+  static const int kBufferSize = 300 * KB;
+  char memory_buffer[kBufferSize];
+  char* buffer_middle = memory_buffer + (kBufferSize / 2);
+
+  FOR_UINT64_INPUTS(i, unsigned_test_values) {
+    FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) {
+      FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) {
+        uint16_t value = static_cast<uint64_t>(*i & 0xFFFF);
+        int32_t in_offset = *j1 + *k1;
+        int32_t out_offset = *j2 + *k2;
+
+        CHECK_EQ(true, run_Unaligned<uint16_t>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             Label success, fail, end, different;
+                             __ Ulh(t0, MemOperand(a0, in_offset));
+                             __ Ulhu(t1, MemOperand(a0, in_offset));
+                             __ Branch(&different, ne, t0, Operand(t1));
+
+                             // If signed and unsigned values are same, check
+                             // the upper bits to see if they are zero
+                             __ sra(t0, t0, 15);
+                             __ Branch(&success, eq, t0, Operand(zero_reg));
+                             __ Branch(&fail);
+
+                             // If signed and unsigned values are different,
+                             // check that the upper bits are complementary
+                             __ bind(&different);
+                             __ sra(t1, t1, 15);
+                             __ Branch(&fail, ne, t1, Operand(1));
+                             __ sra(t0, t0, 15);
+                             __ addiu(t0, t0, 1);
+                             __ Branch(&fail, ne, t0, Operand(zero_reg));
+                             // Fall through to success
+
+                             __ bind(&success);
+                             __ Ulh(t0, MemOperand(a0, in_offset));
+                             __ Ush(t0, MemOperand(a0, out_offset), v0);
+                             __ Branch(&end);
+                             __ bind(&fail);
+                             __ Ush(zero_reg, MemOperand(a0, out_offset), v0);
+                             __ bind(&end);
+                           }));
+      }
+    }
+  }
+}
+
+TEST(Ulw) {
+  CcTest::InitializeVM();
+
+  static const int kBufferSize = 300 * KB;
+  char memory_buffer[kBufferSize];
+  char* buffer_middle = memory_buffer + (kBufferSize / 2);
+
+  FOR_UINT64_INPUTS(i, unsigned_test_values) {
+    FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) {
+      FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) {
+        uint32_t value = static_cast<uint32_t>(*i & 0xFFFFFFFF);
+        int32_t in_offset = *j1 + *k1;
+        int32_t out_offset = *j2 + *k2;
+
+        CHECK_EQ(true, run_Unaligned<uint32_t>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             __ Ulw(v0, MemOperand(a0, in_offset));
+                             __ Usw(v0, MemOperand(a0, out_offset));
+                           }));
+        CHECK_EQ(true,
+                 run_Unaligned<uint32_t>(
+                     buffer_middle, in_offset, out_offset, (uint32_t)value,
+                     [](MacroAssembler* masm, int32_t in_offset,
+                        int32_t out_offset) {
+                       __ mov(t0, a0);
+                       __ Ulw(a0, MemOperand(a0, in_offset));
+                       __ Usw(a0, MemOperand(t0, out_offset));
+                     }));
+      }
+    }
+  }
+}
+
+TEST(Ulwc1) {
+  CcTest::InitializeVM();
+
+  static const int kBufferSize = 300 * KB;
+  char memory_buffer[kBufferSize];
+  char* buffer_middle = memory_buffer + (kBufferSize / 2);
+
+  FOR_UINT64_INPUTS(i, unsigned_test_values) {
+    FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) {
+      FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) {
+        float value = static_cast<float>(*i & 0xFFFFFFFF);
+        int32_t in_offset = *j1 + *k1;
+        int32_t out_offset = *j2 + *k2;
+
+        CHECK_EQ(true, run_Unaligned<float>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             __ Ulwc1(f0, MemOperand(a0, in_offset), t0);
+                             __ Uswc1(f0, MemOperand(a0, out_offset), t0);
+                           }));
+      }
+    }
+  }
+}
+
+TEST(Uldc1) {
+  CcTest::InitializeVM();
+
+  static const int kBufferSize = 300 * KB;
+  char memory_buffer[kBufferSize];
+  char* buffer_middle = memory_buffer + (kBufferSize / 2);
+
+  FOR_UINT64_INPUTS(i, unsigned_test_values) {
+    FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) {
+      FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) {
+        double value = static_cast<double>(*i);
+        int32_t in_offset = *j1 + *k1;
+        int32_t out_offset = *j2 + *k2;
+
+        CHECK_EQ(true, run_Unaligned<double>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             __ Uldc1(f0, MemOperand(a0, in_offset), t0);
+                             __ Usdc1(f0, MemOperand(a0, out_offset), t0);
+                           }));
+      }
+    }
+  }
+}
+
 #undef __
diff --git a/test/cctest/test-macro-assembler-mips64.cc b/test/cctest/test-macro-assembler-mips64.cc
index e251242..258ac40 100644
--- a/test/cctest/test-macro-assembler-mips64.cc
+++ b/test/cctest/test-macro-assembler-mips64.cc
@@ -61,6 +61,89 @@
   return true;
 }
 
+TEST(BYTESWAP) {
+  DCHECK(kArchVariant == kMips64r6 || kArchVariant == kMips64r2);
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  HandleScope scope(isolate);
+
+  struct T {
+    int64_t r1;
+    int64_t r2;
+    int64_t r3;
+    int64_t r4;
+    int64_t r5;
+    int64_t r6;
+    int64_t r7;
+  };
+  T t;
+
+  MacroAssembler assembler(isolate, NULL, 0,
+                           v8::internal::CodeObjectRequired::kYes);
+
+  MacroAssembler* masm = &assembler;
+
+  __ ld(a4, MemOperand(a0, offsetof(T, r1)));
+  __ nop();
+  __ ByteSwapSigned(a4, 8);
+  __ sd(a4, MemOperand(a0, offsetof(T, r1)));
+
+  __ ld(a4, MemOperand(a0, offsetof(T, r2)));
+  __ nop();
+  __ ByteSwapSigned(a4, 4);
+  __ sd(a4, MemOperand(a0, offsetof(T, r2)));
+
+  __ ld(a4, MemOperand(a0, offsetof(T, r3)));
+  __ nop();
+  __ ByteSwapSigned(a4, 2);
+  __ sd(a4, MemOperand(a0, offsetof(T, r3)));
+
+  __ ld(a4, MemOperand(a0, offsetof(T, r4)));
+  __ nop();
+  __ ByteSwapSigned(a4, 1);
+  __ sd(a4, MemOperand(a0, offsetof(T, r4)));
+
+  __ ld(a4, MemOperand(a0, offsetof(T, r5)));
+  __ nop();
+  __ ByteSwapUnsigned(a4, 1);
+  __ sd(a4, MemOperand(a0, offsetof(T, r5)));
+
+  __ ld(a4, MemOperand(a0, offsetof(T, r6)));
+  __ nop();
+  __ ByteSwapUnsigned(a4, 2);
+  __ sd(a4, MemOperand(a0, offsetof(T, r6)));
+
+  __ ld(a4, MemOperand(a0, offsetof(T, r7)));
+  __ nop();
+  __ ByteSwapUnsigned(a4, 4);
+  __ sd(a4, MemOperand(a0, offsetof(T, r7)));
+
+  __ jr(ra);
+  __ nop();
+
+  CodeDesc desc;
+  masm->GetCode(&desc);
+  Handle<Code> code = isolate->factory()->NewCode(
+      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+  ::F3 f = FUNCTION_CAST<::F3>(code->entry());
+  t.r1 = 0x5612FFCD9D327ACC;
+  t.r2 = 0x781A15C3;
+  t.r3 = 0xFCDE;
+  t.r4 = 0x9F;
+  t.r5 = 0x9F;
+  t.r6 = 0xFCDE;
+  t.r7 = 0xC81A15C3;
+  Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
+  USE(dummy);
+
+  CHECK_EQ(static_cast<int64_t>(0xCC7A329DCDFF1256), t.r1);
+  CHECK_EQ(static_cast<int64_t>(0xC3151A7800000000), t.r2);
+  CHECK_EQ(static_cast<int64_t>(0xDEFCFFFFFFFFFFFF), t.r3);
+  CHECK_EQ(static_cast<int64_t>(0x9FFFFFFFFFFFFFFF), t.r4);
+  CHECK_EQ(static_cast<int64_t>(0x9F00000000000000), t.r5);
+  CHECK_EQ(static_cast<int64_t>(0xDEFC000000000000), t.r6);
+  CHECK_EQ(static_cast<int64_t>(0xC3151AC800000000), t.r7);
+}
 
 TEST(CopyBytes) {
   CcTest::InitializeVM();
@@ -523,14 +606,14 @@
   }
 }
 
-static const std::vector<uint32_t> uint32_test_values() {
+static const std::vector<uint32_t> cvt_trunc_uint32_test_values() {
   static const uint32_t kValues[] = {0x00000000, 0x00000001, 0x00ffff00,
                                      0x7fffffff, 0x80000000, 0x80000001,
                                      0x80ffff00, 0x8fffffff, 0xffffffff};
   return std::vector<uint32_t>(&kValues[0], &kValues[arraysize(kValues)]);
 }
 
-static const std::vector<int32_t> int32_test_values() {
+static const std::vector<int32_t> cvt_trunc_int32_test_values() {
   static const int32_t kValues[] = {
       static_cast<int32_t>(0x00000000), static_cast<int32_t>(0x00000001),
       static_cast<int32_t>(0x00ffff00), static_cast<int32_t>(0x7fffffff),
@@ -540,7 +623,7 @@
   return std::vector<int32_t>(&kValues[0], &kValues[arraysize(kValues)]);
 }
 
-static const std::vector<uint64_t> uint64_test_values() {
+static const std::vector<uint64_t> cvt_trunc_uint64_test_values() {
   static const uint64_t kValues[] = {
       0x0000000000000000, 0x0000000000000001, 0x0000ffffffff0000,
       0x7fffffffffffffff, 0x8000000000000000, 0x8000000000000001,
@@ -548,7 +631,7 @@
   return std::vector<uint64_t>(&kValues[0], &kValues[arraysize(kValues)]);
 }
 
-static const std::vector<int64_t> int64_test_values() {
+static const std::vector<int64_t> cvt_trunc_int64_test_values() {
   static const int64_t kValues[] = {static_cast<int64_t>(0x0000000000000000),
                                     static_cast<int64_t>(0x0000000000000001),
                                     static_cast<int64_t>(0x0000ffffffff0000),
@@ -562,15 +645,32 @@
 }
 
 // Helper macros that can be used in FOR_INT32_INPUTS(i) { ... *i ... }
-#define FOR_INPUTS(ctype, itype, var)                        \
-  std::vector<ctype> var##_vec = itype##_test_values();      \
+#define FOR_INPUTS(ctype, itype, var, test_vector)           \
+  std::vector<ctype> var##_vec = test_vector();              \
   for (std::vector<ctype>::iterator var = var##_vec.begin(); \
        var != var##_vec.end(); ++var)
 
-#define FOR_INT32_INPUTS(var) FOR_INPUTS(int32_t, int32, var)
-#define FOR_INT64_INPUTS(var) FOR_INPUTS(int64_t, int64, var)
-#define FOR_UINT32_INPUTS(var) FOR_INPUTS(uint32_t, uint32, var)
-#define FOR_UINT64_INPUTS(var) FOR_INPUTS(uint64_t, uint64, var)
+#define FOR_INPUTS2(ctype, itype, var, var2, test_vector)  \
+  std::vector<ctype> var##_vec = test_vector();            \
+  std::vector<ctype>::iterator var;                        \
+  std::vector<ctype>::reverse_iterator var2;               \
+  for (var = var##_vec.begin(), var2 = var##_vec.rbegin(); \
+       var != var##_vec.end(); ++var, ++var2)
+
+#define FOR_ENUM_INPUTS(var, type, test_vector) \
+  FOR_INPUTS(enum type, type, var, test_vector)
+#define FOR_STRUCT_INPUTS(var, type, test_vector) \
+  FOR_INPUTS(struct type, type, var, test_vector)
+#define FOR_INT32_INPUTS(var, test_vector) \
+  FOR_INPUTS(int32_t, int32, var, test_vector)
+#define FOR_INT32_INPUTS2(var, var2, test_vector) \
+  FOR_INPUTS2(int32_t, int32, var, var2, test_vector)
+#define FOR_INT64_INPUTS(var, test_vector) \
+  FOR_INPUTS(int64_t, int64, var, test_vector)
+#define FOR_UINT32_INPUTS(var, test_vector) \
+  FOR_INPUTS(uint32_t, uint32, var, test_vector)
+#define FOR_UINT64_INPUTS(var, test_vector) \
+  FOR_INPUTS(uint64_t, uint64, var, test_vector)
 
 template <typename RET_TYPE, typename IN_TYPE, typename Func>
 RET_TYPE run_Cvt(IN_TYPE x, Func GenerateConvertInstructionFunc) {
@@ -600,7 +700,7 @@
 
 TEST(Cvt_s_uw_Trunc_uw_s) {
   CcTest::InitializeVM();
-  FOR_UINT32_INPUTS(i) {
+  FOR_UINT32_INPUTS(i, cvt_trunc_uint32_test_values) {
     uint32_t input = *i;
     CHECK_EQ(static_cast<float>(input),
              run_Cvt<uint64_t>(input, [](MacroAssembler* masm) {
@@ -613,7 +713,7 @@
 
 TEST(Cvt_s_ul_Trunc_ul_s) {
   CcTest::InitializeVM();
-  FOR_UINT64_INPUTS(i) {
+  FOR_UINT64_INPUTS(i, cvt_trunc_uint64_test_values) {
     uint64_t input = *i;
     CHECK_EQ(static_cast<float>(input),
              run_Cvt<uint64_t>(input, [](MacroAssembler* masm) {
@@ -625,7 +725,7 @@
 
 TEST(Cvt_d_ul_Trunc_ul_d) {
   CcTest::InitializeVM();
-  FOR_UINT64_INPUTS(i) {
+  FOR_UINT64_INPUTS(i, cvt_trunc_uint64_test_values) {
     uint64_t input = *i;
     CHECK_EQ(static_cast<double>(input),
              run_Cvt<uint64_t>(input, [](MacroAssembler* masm) {
@@ -637,7 +737,7 @@
 
 TEST(cvt_d_l_Trunc_l_d) {
   CcTest::InitializeVM();
-  FOR_INT64_INPUTS(i) {
+  FOR_INT64_INPUTS(i, cvt_trunc_int64_test_values) {
     int64_t input = *i;
     CHECK_EQ(static_cast<double>(input),
              run_Cvt<int64_t>(input, [](MacroAssembler* masm) {
@@ -650,7 +750,7 @@
 
 TEST(cvt_d_l_Trunc_l_ud) {
   CcTest::InitializeVM();
-  FOR_INT64_INPUTS(i) {
+  FOR_INT64_INPUTS(i, cvt_trunc_int64_test_values) {
     int64_t input = *i;
     uint64_t abs_input = (input < 0) ? -input : input;
     CHECK_EQ(static_cast<double>(abs_input),
@@ -664,7 +764,7 @@
 
 TEST(cvt_d_w_Trunc_w_d) {
   CcTest::InitializeVM();
-  FOR_INT32_INPUTS(i) {
+  FOR_INT32_INPUTS(i, cvt_trunc_int32_test_values) {
     int32_t input = *i;
     CHECK_EQ(static_cast<double>(input),
              run_Cvt<int64_t>(input, [](MacroAssembler* masm) {
@@ -677,6 +777,607 @@
   }
 }
 
+static const std::vector<int32_t> overflow_int32_test_values() {
+  static const int32_t kValues[] = {
+      static_cast<int32_t>(0xf0000000), static_cast<int32_t>(0x00000001),
+      static_cast<int32_t>(0xff000000), static_cast<int32_t>(0x0000f000),
+      static_cast<int32_t>(0x0f000000), static_cast<int32_t>(0x991234ab),
+      static_cast<int32_t>(0xb0ffff01), static_cast<int32_t>(0x00006fff),
+      static_cast<int32_t>(0xffffffff)};
+  return std::vector<int32_t>(&kValues[0], &kValues[arraysize(kValues)]);
+}
+
+static const std::vector<int64_t> overflow_int64_test_values() {
+  static const int64_t kValues[] = {static_cast<int64_t>(0xf000000000000000),
+                                    static_cast<int64_t>(0x0000000000000001),
+                                    static_cast<int64_t>(0xff00000000000000),
+                                    static_cast<int64_t>(0x0000f00111111110),
+                                    static_cast<int64_t>(0x0f00001000000000),
+                                    static_cast<int64_t>(0x991234ab12a96731),
+                                    static_cast<int64_t>(0xb0ffff0f0f0f0f01),
+                                    static_cast<int64_t>(0x00006fffffffffff),
+                                    static_cast<int64_t>(0xffffffffffffffff)};
+  return std::vector<int64_t>(&kValues[0], &kValues[arraysize(kValues)]);
+}
+
+enum OverflowBranchType {
+  kAddBranchOverflow,
+  kSubBranchOverflow,
+};
+
+struct OverflowRegisterCombination {
+  Register dst;
+  Register left;
+  Register right;
+  Register scratch;
+};
+
+static const std::vector<enum OverflowBranchType> overflow_branch_type() {
+  static const enum OverflowBranchType kValues[] = {kAddBranchOverflow,
+                                                    kSubBranchOverflow};
+  return std::vector<enum OverflowBranchType>(&kValues[0],
+                                              &kValues[arraysize(kValues)]);
+}
+
+static const std::vector<struct OverflowRegisterCombination>
+overflow_register_combination() {
+  static const struct OverflowRegisterCombination kValues[] = {
+      {t0, t1, t2, t3}, {t0, t0, t2, t3}, {t0, t1, t0, t3}, {t0, t1, t1, t3}};
+  return std::vector<struct OverflowRegisterCombination>(
+      &kValues[0], &kValues[arraysize(kValues)]);
+}
+
+template <typename T>
+static bool IsAddOverflow(T x, T y) {
+  DCHECK(std::numeric_limits<T>::is_integer);
+  T max = std::numeric_limits<T>::max();
+  T min = std::numeric_limits<T>::min();
+
+  return (x > 0 && y > (max - x)) || (x < 0 && y < (min - x));
+}
+
+template <typename T>
+static bool IsSubOverflow(T x, T y) {
+  DCHECK(std::numeric_limits<T>::is_integer);
+  T max = std::numeric_limits<T>::max();
+  T min = std::numeric_limits<T>::min();
+
+  return (y > 0 && x < (min + y)) || (y < 0 && x > (max + y));
+}
+
+template <typename IN_TYPE, typename Func>
+static bool runOverflow(IN_TYPE valLeft, IN_TYPE valRight,
+                        Func GenerateOverflowInstructions) {
+  typedef int64_t (*F_CVT)(char* x0, int x1, int x2, int x3, int x4);
+
+  Isolate* isolate = CcTest::i_isolate();
+  HandleScope scope(isolate);
+  MacroAssembler assm(isolate, nullptr, 0,
+                      v8::internal::CodeObjectRequired::kYes);
+  MacroAssembler* masm = &assm;
+
+  GenerateOverflowInstructions(masm, valLeft, valRight);
+  __ jr(ra);
+  __ nop();
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Handle<Code> code = isolate->factory()->NewCode(
+      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+
+  F_CVT f = FUNCTION_CAST<F_CVT>(code->entry());
+
+  int64_t r =
+      reinterpret_cast<int64_t>(CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
+
+  DCHECK(r == 0 || r == 1);
+  return r;
+}
+
+TEST(BranchOverflowInt32BothLabels) {
+  FOR_INT32_INPUTS(i, overflow_int32_test_values) {
+    FOR_INT32_INPUTS(j, overflow_int32_test_values) {
+      FOR_ENUM_INPUTS(br, OverflowBranchType, overflow_branch_type) {
+        FOR_STRUCT_INPUTS(regComb, OverflowRegisterCombination,
+                          overflow_register_combination) {
+          int32_t ii = *i;
+          int32_t jj = *j;
+          enum OverflowBranchType branchType = *br;
+          struct OverflowRegisterCombination rc = *regComb;
+
+          // If left and right register are same then left and right
+          // test values must also be same, otherwise we skip the test
+          if (rc.left.code() == rc.right.code()) {
+            if (ii != jj) {
+              continue;
+            }
+          }
+
+          bool res1 = runOverflow<int32_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft,
+                                       int32_t valRight) {
+                Label overflow, no_overflow, end;
+                __ li(rc.left, valLeft);
+                __ li(rc.right, valRight);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ AddBranchOvf(rc.dst, rc.left, rc.right, &overflow,
+                                    &no_overflow, rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ SubBranchOvf(rc.dst, rc.left, rc.right, &overflow,
+                                    &no_overflow, rc.scratch);
+                    break;
+                }
+                __ li(v0, 2);
+                __ Branch(&end);
+                __ bind(&overflow);
+                __ li(v0, 1);
+                __ Branch(&end);
+                __ bind(&no_overflow);
+                __ li(v0, 0);
+                __ bind(&end);
+              });
+
+          bool res2 = runOverflow<int32_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft,
+                                       int32_t valRight) {
+                Label overflow, no_overflow, end;
+                __ li(rc.left, valLeft);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ AddBranchOvf(rc.dst, rc.left, Operand(valRight),
+                                    &overflow, &no_overflow, rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ SubBranchOvf(rc.dst, rc.left, Operand(valRight),
+                                    &overflow, &no_overflow, rc.scratch);
+                    break;
+                }
+                __ li(v0, 2);
+                __ Branch(&end);
+                __ bind(&overflow);
+                __ li(v0, 1);
+                __ Branch(&end);
+                __ bind(&no_overflow);
+                __ li(v0, 0);
+                __ bind(&end);
+              });
+
+          switch (branchType) {
+            case kAddBranchOverflow:
+              CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res1);
+              CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res2);
+              break;
+            case kSubBranchOverflow:
+              CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res1);
+              CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res2);
+              break;
+            default:
+              UNREACHABLE();
+          }
+        }
+      }
+    }
+  }
+}
+
+TEST(BranchOverflowInt32LeftLabel) {
+  FOR_INT32_INPUTS(i, overflow_int32_test_values) {
+    FOR_INT32_INPUTS(j, overflow_int32_test_values) {
+      FOR_ENUM_INPUTS(br, OverflowBranchType, overflow_branch_type) {
+        FOR_STRUCT_INPUTS(regComb, OverflowRegisterCombination,
+                          overflow_register_combination) {
+          int32_t ii = *i;
+          int32_t jj = *j;
+          enum OverflowBranchType branchType = *br;
+          struct OverflowRegisterCombination rc = *regComb;
+
+          // If left and right register are same then left and right
+          // test values must also be same, otherwise we skip the test
+          if (rc.left.code() == rc.right.code()) {
+            if (ii != jj) {
+              continue;
+            }
+          }
+
+          bool res1 = runOverflow<int32_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft,
+                                       int32_t valRight) {
+                Label overflow, end;
+                __ li(rc.left, valLeft);
+                __ li(rc.right, valRight);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ AddBranchOvf(rc.dst, rc.left, rc.right, &overflow, NULL,
+                                    rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ SubBranchOvf(rc.dst, rc.left, rc.right, &overflow, NULL,
+                                    rc.scratch);
+                    break;
+                }
+                __ li(v0, 0);
+                __ Branch(&end);
+                __ bind(&overflow);
+                __ li(v0, 1);
+                __ bind(&end);
+              });
+
+          bool res2 = runOverflow<int32_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft,
+                                       int32_t valRight) {
+                Label overflow, end;
+                __ li(rc.left, valLeft);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ AddBranchOvf(rc.dst, rc.left, Operand(valRight),
+                                    &overflow, NULL, rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ SubBranchOvf(rc.dst, rc.left, Operand(valRight),
+                                    &overflow, NULL, rc.scratch);
+                    break;
+                }
+                __ li(v0, 0);
+                __ Branch(&end);
+                __ bind(&overflow);
+                __ li(v0, 1);
+                __ bind(&end);
+              });
+
+          switch (branchType) {
+            case kAddBranchOverflow:
+              CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res1);
+              CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res2);
+              break;
+            case kSubBranchOverflow:
+              CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res1);
+              CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res2);
+              break;
+            default:
+              UNREACHABLE();
+          }
+        }
+      }
+    }
+  }
+}
+
+TEST(BranchOverflowInt32RightLabel) {
+  FOR_INT32_INPUTS(i, overflow_int32_test_values) {
+    FOR_INT32_INPUTS(j, overflow_int32_test_values) {
+      FOR_ENUM_INPUTS(br, OverflowBranchType, overflow_branch_type) {
+        FOR_STRUCT_INPUTS(regComb, OverflowRegisterCombination,
+                          overflow_register_combination) {
+          int32_t ii = *i;
+          int32_t jj = *j;
+          enum OverflowBranchType branchType = *br;
+          struct OverflowRegisterCombination rc = *regComb;
+
+          // If left and right register are same then left and right
+          // test values must also be same, otherwise we skip the test
+          if (rc.left.code() == rc.right.code()) {
+            if (ii != jj) {
+              continue;
+            }
+          }
+
+          bool res1 = runOverflow<int32_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft,
+                                       int32_t valRight) {
+                Label no_overflow, end;
+                __ li(rc.left, valLeft);
+                __ li(rc.right, valRight);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ AddBranchOvf(rc.dst, rc.left, rc.right, NULL,
+                                    &no_overflow, rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ SubBranchOvf(rc.dst, rc.left, rc.right, NULL,
+                                    &no_overflow, rc.scratch);
+                    break;
+                }
+                __ li(v0, 1);
+                __ Branch(&end);
+                __ bind(&no_overflow);
+                __ li(v0, 0);
+                __ bind(&end);
+              });
+
+          bool res2 = runOverflow<int32_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int32_t valLeft,
+                                       int32_t valRight) {
+                Label no_overflow, end;
+                __ li(rc.left, valLeft);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ AddBranchOvf(rc.dst, rc.left, Operand(valRight), NULL,
+                                    &no_overflow, rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ SubBranchOvf(rc.dst, rc.left, Operand(valRight), NULL,
+                                    &no_overflow, rc.scratch);
+                    break;
+                }
+                __ li(v0, 1);
+                __ Branch(&end);
+                __ bind(&no_overflow);
+                __ li(v0, 0);
+                __ bind(&end);
+              });
+
+          switch (branchType) {
+            case kAddBranchOverflow:
+              CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res1);
+              CHECK_EQ(IsAddOverflow<int32_t>(ii, jj), res2);
+              break;
+            case kSubBranchOverflow:
+              CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res1);
+              CHECK_EQ(IsSubOverflow<int32_t>(ii, jj), res2);
+              break;
+            default:
+              UNREACHABLE();
+          }
+        }
+      }
+    }
+  }
+}
+
+TEST(BranchOverflowInt64BothLabels) {
+  FOR_INT64_INPUTS(i, overflow_int64_test_values) {
+    FOR_INT64_INPUTS(j, overflow_int64_test_values) {
+      FOR_ENUM_INPUTS(br, OverflowBranchType, overflow_branch_type) {
+        FOR_STRUCT_INPUTS(regComb, OverflowRegisterCombination,
+                          overflow_register_combination) {
+          int64_t ii = *i;
+          int64_t jj = *j;
+          enum OverflowBranchType branchType = *br;
+          struct OverflowRegisterCombination rc = *regComb;
+
+          // If left and right register are same then left and right
+          // test values must also be same, otherwise we skip the test
+          if (rc.left.code() == rc.right.code()) {
+            if (ii != jj) {
+              continue;
+            }
+          }
+
+          bool res1 = runOverflow<int64_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int64_t valLeft,
+                                       int64_t valRight) {
+                Label overflow, no_overflow, end;
+                __ li(rc.left, valLeft);
+                __ li(rc.right, valRight);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ DaddBranchOvf(rc.dst, rc.left, rc.right, &overflow,
+                                     &no_overflow, rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ DsubBranchOvf(rc.dst, rc.left, rc.right, &overflow,
+                                     &no_overflow, rc.scratch);
+                    break;
+                }
+                __ li(v0, 2);
+                __ Branch(&end);
+                __ bind(&overflow);
+                __ li(v0, 1);
+                __ Branch(&end);
+                __ bind(&no_overflow);
+                __ li(v0, 0);
+                __ bind(&end);
+              });
+
+          bool res2 = runOverflow<int64_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int64_t valLeft,
+                                       int64_t valRight) {
+                Label overflow, no_overflow, end;
+                __ li(rc.left, valLeft);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ DaddBranchOvf(rc.dst, rc.left, Operand(valRight),
+                                     &overflow, &no_overflow, rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ DsubBranchOvf(rc.dst, rc.left, Operand(valRight),
+                                     &overflow, &no_overflow, rc.scratch);
+                    break;
+                }
+                __ li(v0, 2);
+                __ Branch(&end);
+                __ bind(&overflow);
+                __ li(v0, 1);
+                __ Branch(&end);
+                __ bind(&no_overflow);
+                __ li(v0, 0);
+                __ bind(&end);
+              });
+
+          switch (branchType) {
+            case kAddBranchOverflow:
+              CHECK_EQ(IsAddOverflow<int64_t>(ii, jj), res1);
+              CHECK_EQ(IsAddOverflow<int64_t>(ii, jj), res2);
+              break;
+            case kSubBranchOverflow:
+              CHECK_EQ(IsSubOverflow<int64_t>(ii, jj), res1);
+              CHECK_EQ(IsSubOverflow<int64_t>(ii, jj), res2);
+              break;
+            default:
+              UNREACHABLE();
+          }
+        }
+      }
+    }
+  }
+}
+
+TEST(BranchOverflowInt64LeftLabel) {
+  FOR_INT64_INPUTS(i, overflow_int64_test_values) {
+    FOR_INT64_INPUTS(j, overflow_int64_test_values) {
+      FOR_ENUM_INPUTS(br, OverflowBranchType, overflow_branch_type) {
+        FOR_STRUCT_INPUTS(regComb, OverflowRegisterCombination,
+                          overflow_register_combination) {
+          int64_t ii = *i;
+          int64_t jj = *j;
+          enum OverflowBranchType branchType = *br;
+          struct OverflowRegisterCombination rc = *regComb;
+
+          // If left and right register are same then left and right
+          // test values must also be same, otherwise we skip the test
+          if (rc.left.code() == rc.right.code()) {
+            if (ii != jj) {
+              continue;
+            }
+          }
+
+          bool res1 = runOverflow<int64_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int64_t valLeft,
+                                       int64_t valRight) {
+                Label overflow, end;
+                __ li(rc.left, valLeft);
+                __ li(rc.right, valRight);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ DaddBranchOvf(rc.dst, rc.left, rc.right, &overflow, NULL,
+                                     rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ DsubBranchOvf(rc.dst, rc.left, rc.right, &overflow, NULL,
+                                     rc.scratch);
+                    break;
+                }
+                __ li(v0, 0);
+                __ Branch(&end);
+                __ bind(&overflow);
+                __ li(v0, 1);
+                __ bind(&end);
+              });
+
+          bool res2 = runOverflow<int64_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int64_t valLeft,
+                                       int64_t valRight) {
+                Label overflow, end;
+                __ li(rc.left, valLeft);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ DaddBranchOvf(rc.dst, rc.left, Operand(valRight),
+                                     &overflow, NULL, rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ DsubBranchOvf(rc.dst, rc.left, Operand(valRight),
+                                     &overflow, NULL, rc.scratch);
+                    break;
+                }
+                __ li(v0, 0);
+                __ Branch(&end);
+                __ bind(&overflow);
+                __ li(v0, 1);
+                __ bind(&end);
+              });
+
+          switch (branchType) {
+            case kAddBranchOverflow:
+              CHECK_EQ(IsAddOverflow<int64_t>(ii, jj), res1);
+              CHECK_EQ(IsAddOverflow<int64_t>(ii, jj), res2);
+              break;
+            case kSubBranchOverflow:
+              CHECK_EQ(IsSubOverflow<int64_t>(ii, jj), res1);
+              CHECK_EQ(IsSubOverflow<int64_t>(ii, jj), res2);
+              break;
+            default:
+              UNREACHABLE();
+          }
+        }
+      }
+    }
+  }
+}
+
+TEST(BranchOverflowInt64RightLabel) {
+  FOR_INT64_INPUTS(i, overflow_int64_test_values) {
+    FOR_INT64_INPUTS(j, overflow_int64_test_values) {
+      FOR_ENUM_INPUTS(br, OverflowBranchType, overflow_branch_type) {
+        FOR_STRUCT_INPUTS(regComb, OverflowRegisterCombination,
+                          overflow_register_combination) {
+          int64_t ii = *i;
+          int64_t jj = *j;
+          enum OverflowBranchType branchType = *br;
+          struct OverflowRegisterCombination rc = *regComb;
+
+          // If left and right register are same then left and right
+          // test values must also be same, otherwise we skip the test
+          if (rc.left.code() == rc.right.code()) {
+            if (ii != jj) {
+              continue;
+            }
+          }
+
+          bool res1 = runOverflow<int64_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int64_t valLeft,
+                                       int64_t valRight) {
+                Label no_overflow, end;
+                __ li(rc.left, valLeft);
+                __ li(rc.right, valRight);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ DaddBranchOvf(rc.dst, rc.left, rc.right, NULL,
+                                     &no_overflow, rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ DsubBranchOvf(rc.dst, rc.left, rc.right, NULL,
+                                     &no_overflow, rc.scratch);
+                    break;
+                }
+                __ li(v0, 1);
+                __ Branch(&end);
+                __ bind(&no_overflow);
+                __ li(v0, 0);
+                __ bind(&end);
+              });
+
+          bool res2 = runOverflow<int64_t>(
+              ii, jj, [branchType, rc](MacroAssembler* masm, int64_t valLeft,
+                                       int64_t valRight) {
+                Label no_overflow, end;
+                __ li(rc.left, valLeft);
+                switch (branchType) {
+                  case kAddBranchOverflow:
+                    __ DaddBranchOvf(rc.dst, rc.left, Operand(valRight), NULL,
+                                     &no_overflow, rc.scratch);
+                    break;
+                  case kSubBranchOverflow:
+                    __ DsubBranchOvf(rc.dst, rc.left, Operand(valRight), NULL,
+                                     &no_overflow, rc.scratch);
+                    break;
+                }
+                __ li(v0, 1);
+                __ Branch(&end);
+                __ bind(&no_overflow);
+                __ li(v0, 0);
+                __ bind(&end);
+              });
+
+          switch (branchType) {
+            case kAddBranchOverflow:
+              CHECK_EQ(IsAddOverflow<int64_t>(ii, jj), res1);
+              CHECK_EQ(IsAddOverflow<int64_t>(ii, jj), res2);
+              break;
+            case kSubBranchOverflow:
+              CHECK_EQ(IsSubOverflow<int64_t>(ii, jj), res1);
+              CHECK_EQ(IsSubOverflow<int64_t>(ii, jj), res2);
+              break;
+            default:
+              UNREACHABLE();
+          }
+        }
+      }
+    }
+  }
+}
+
 TEST(min_max_nan) {
   CcTest::InitializeVM();
   Isolate* isolate = CcTest::i_isolate();
@@ -787,4 +1488,344 @@
   }
 }
 
+template <typename IN_TYPE, typename Func>
+bool run_Unaligned(char* memory_buffer, int32_t in_offset, int32_t out_offset,
+                   IN_TYPE value, Func GenerateUnalignedInstructionFunc) {
+  typedef int32_t (*F_CVT)(char* x0, int x1, int x2, int x3, int x4);
+
+  Isolate* isolate = CcTest::i_isolate();
+  HandleScope scope(isolate);
+  MacroAssembler assm(isolate, nullptr, 0,
+                      v8::internal::CodeObjectRequired::kYes);
+  MacroAssembler* masm = &assm;
+  IN_TYPE res;
+
+  GenerateUnalignedInstructionFunc(masm, in_offset, out_offset);
+  __ jr(ra);
+  __ nop();
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Handle<Code> code = isolate->factory()->NewCode(
+      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+
+  F_CVT f = FUNCTION_CAST<F_CVT>(code->entry());
+
+  MemCopy(memory_buffer + in_offset, &value, sizeof(IN_TYPE));
+  CALL_GENERATED_CODE(isolate, f, memory_buffer, 0, 0, 0, 0);
+  MemCopy(&res, memory_buffer + out_offset, sizeof(IN_TYPE));
+
+  return res == value;
+}
+
+static const std::vector<uint64_t> unsigned_test_values() {
+  static const uint64_t kValues[] = {
+      0x2180f18a06384414, 0x000a714532102277, 0xbc1acccf180649f0,
+      0x8000000080008000, 0x0000000000000001, 0xffffffffffffffff,
+  };
+  return std::vector<uint64_t>(&kValues[0], &kValues[arraysize(kValues)]);
+}
+
+static const std::vector<int32_t> unsigned_test_offset() {
+  static const int32_t kValues[] = {// value, offset
+                                    -132 * KB, -21 * KB, 0, 19 * KB, 135 * KB};
+  return std::vector<int32_t>(&kValues[0], &kValues[arraysize(kValues)]);
+}
+
+static const std::vector<int32_t> unsigned_test_offset_increment() {
+  static const int32_t kValues[] = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5};
+  return std::vector<int32_t>(&kValues[0], &kValues[arraysize(kValues)]);
+}
+
+TEST(Ulh) {
+  CcTest::InitializeVM();
+
+  static const int kBufferSize = 300 * KB;
+  char memory_buffer[kBufferSize];
+  char* buffer_middle = memory_buffer + (kBufferSize / 2);
+
+  FOR_UINT64_INPUTS(i, unsigned_test_values) {
+    FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) {
+      FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) {
+        uint16_t value = static_cast<uint64_t>(*i & 0xFFFF);
+        int32_t in_offset = *j1 + *k1;
+        int32_t out_offset = *j2 + *k2;
+
+        CHECK_EQ(true, run_Unaligned<uint16_t>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             __ Ulh(v0, MemOperand(a0, in_offset));
+                             __ Ush(v0, MemOperand(a0, out_offset), v0);
+                           }));
+        CHECK_EQ(true, run_Unaligned<uint16_t>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             __ mov(t0, a0);
+                             __ Ulh(a0, MemOperand(a0, in_offset));
+                             __ Ush(a0, MemOperand(t0, out_offset), v0);
+                           }));
+        CHECK_EQ(true, run_Unaligned<uint16_t>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             __ mov(t0, a0);
+                             __ Ulhu(a0, MemOperand(a0, in_offset));
+                             __ Ush(a0, MemOperand(t0, out_offset), t1);
+                           }));
+        CHECK_EQ(true, run_Unaligned<uint16_t>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             __ Ulhu(v0, MemOperand(a0, in_offset));
+                             __ Ush(v0, MemOperand(a0, out_offset), t1);
+                           }));
+      }
+    }
+  }
+}
+
+TEST(Ulh_bitextension) {
+  CcTest::InitializeVM();
+
+  static const int kBufferSize = 300 * KB;
+  char memory_buffer[kBufferSize];
+  char* buffer_middle = memory_buffer + (kBufferSize / 2);
+
+  FOR_UINT64_INPUTS(i, unsigned_test_values) {
+    FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) {
+      FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) {
+        uint16_t value = static_cast<uint64_t>(*i & 0xFFFF);
+        int32_t in_offset = *j1 + *k1;
+        int32_t out_offset = *j2 + *k2;
+
+        CHECK_EQ(true, run_Unaligned<uint16_t>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             Label success, fail, end, different;
+                             __ Ulh(t0, MemOperand(a0, in_offset));
+                             __ Ulhu(t1, MemOperand(a0, in_offset));
+                             __ Branch(&different, ne, t0, Operand(t1));
+
+                             // If signed and unsigned values are same, check
+                             // the upper bits to see if they are zero
+                             __ sra(t0, t0, 15);
+                             __ Branch(&success, eq, t0, Operand(zero_reg));
+                             __ Branch(&fail);
+
+                             // If signed and unsigned values are different,
+                             // check that the upper bits are complementary
+                             __ bind(&different);
+                             __ sra(t1, t1, 15);
+                             __ Branch(&fail, ne, t1, Operand(1));
+                             __ sra(t0, t0, 15);
+                             __ addiu(t0, t0, 1);
+                             __ Branch(&fail, ne, t0, Operand(zero_reg));
+                             // Fall through to success
+
+                             __ bind(&success);
+                             __ Ulh(t0, MemOperand(a0, in_offset));
+                             __ Ush(t0, MemOperand(a0, out_offset), v0);
+                             __ Branch(&end);
+                             __ bind(&fail);
+                             __ Ush(zero_reg, MemOperand(a0, out_offset), v0);
+                             __ bind(&end);
+                           }));
+      }
+    }
+  }
+}
+
+TEST(Ulw) {
+  CcTest::InitializeVM();
+
+  static const int kBufferSize = 300 * KB;
+  char memory_buffer[kBufferSize];
+  char* buffer_middle = memory_buffer + (kBufferSize / 2);
+
+  FOR_UINT64_INPUTS(i, unsigned_test_values) {
+    FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) {
+      FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) {
+        uint32_t value = static_cast<uint32_t>(*i & 0xFFFFFFFF);
+        int32_t in_offset = *j1 + *k1;
+        int32_t out_offset = *j2 + *k2;
+
+        CHECK_EQ(true, run_Unaligned<uint32_t>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             __ Ulw(v0, MemOperand(a0, in_offset));
+                             __ Usw(v0, MemOperand(a0, out_offset));
+                           }));
+        CHECK_EQ(true,
+                 run_Unaligned<uint32_t>(
+                     buffer_middle, in_offset, out_offset, (uint32_t)value,
+                     [](MacroAssembler* masm, int32_t in_offset,
+                        int32_t out_offset) {
+                       __ mov(t0, a0);
+                       __ Ulw(a0, MemOperand(a0, in_offset));
+                       __ Usw(a0, MemOperand(t0, out_offset));
+                     }));
+        CHECK_EQ(true, run_Unaligned<uint32_t>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             __ Ulwu(v0, MemOperand(a0, in_offset));
+                             __ Usw(v0, MemOperand(a0, out_offset));
+                           }));
+        CHECK_EQ(true,
+                 run_Unaligned<uint32_t>(
+                     buffer_middle, in_offset, out_offset, (uint32_t)value,
+                     [](MacroAssembler* masm, int32_t in_offset,
+                        int32_t out_offset) {
+                       __ mov(t0, a0);
+                       __ Ulwu(a0, MemOperand(a0, in_offset));
+                       __ Usw(a0, MemOperand(t0, out_offset));
+                     }));
+      }
+    }
+  }
+}
+
+TEST(Ulw_extension) {
+  CcTest::InitializeVM();
+
+  static const int kBufferSize = 300 * KB;
+  char memory_buffer[kBufferSize];
+  char* buffer_middle = memory_buffer + (kBufferSize / 2);
+
+  FOR_UINT64_INPUTS(i, unsigned_test_values) {
+    FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) {
+      FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) {
+        uint32_t value = static_cast<uint32_t>(*i & 0xFFFFFFFF);
+        int32_t in_offset = *j1 + *k1;
+        int32_t out_offset = *j2 + *k2;
+
+        CHECK_EQ(true, run_Unaligned<uint32_t>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             Label success, fail, end, different;
+                             __ Ulw(t0, MemOperand(a0, in_offset));
+                             __ Ulwu(t1, MemOperand(a0, in_offset));
+                             __ Branch(&different, ne, t0, Operand(t1));
+
+                             // If signed and unsigned values are same, check
+                             // the upper bits to see if they are zero
+                             __ dsra(t0, t0, 31);
+                             __ Branch(&success, eq, t0, Operand(zero_reg));
+                             __ Branch(&fail);
+
+                             // If signed and unsigned values are different,
+                             // check that the upper bits are complementary
+                             __ bind(&different);
+                             __ dsra(t1, t1, 31);
+                             __ Branch(&fail, ne, t1, Operand(1));
+                             __ dsra(t0, t0, 31);
+                             __ daddiu(t0, t0, 1);
+                             __ Branch(&fail, ne, t0, Operand(zero_reg));
+                             // Fall through to success
+
+                             __ bind(&success);
+                             __ Ulw(t0, MemOperand(a0, in_offset));
+                             __ Usw(t0, MemOperand(a0, out_offset));
+                             __ Branch(&end);
+                             __ bind(&fail);
+                             __ Usw(zero_reg, MemOperand(a0, out_offset));
+                             __ bind(&end);
+                           }));
+      }
+    }
+  }
+}
+
+TEST(Uld) {
+  CcTest::InitializeVM();
+
+  static const int kBufferSize = 300 * KB;
+  char memory_buffer[kBufferSize];
+  char* buffer_middle = memory_buffer + (kBufferSize / 2);
+
+  FOR_UINT64_INPUTS(i, unsigned_test_values) {
+    FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) {
+      FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) {
+        uint64_t value = *i;
+        int32_t in_offset = *j1 + *k1;
+        int32_t out_offset = *j2 + *k2;
+
+        CHECK_EQ(true, run_Unaligned<uint64_t>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             __ Uld(v0, MemOperand(a0, in_offset));
+                             __ Usd(v0, MemOperand(a0, out_offset));
+                           }));
+        CHECK_EQ(true,
+                 run_Unaligned<uint64_t>(
+                     buffer_middle, in_offset, out_offset, (uint32_t)value,
+                     [](MacroAssembler* masm, int32_t in_offset,
+                        int32_t out_offset) {
+                       __ mov(t0, a0);
+                       __ Uld(a0, MemOperand(a0, in_offset));
+                       __ Usd(a0, MemOperand(t0, out_offset));
+                     }));
+      }
+    }
+  }
+}
+
+TEST(Ulwc1) {
+  CcTest::InitializeVM();
+
+  static const int kBufferSize = 300 * KB;
+  char memory_buffer[kBufferSize];
+  char* buffer_middle = memory_buffer + (kBufferSize / 2);
+
+  FOR_UINT64_INPUTS(i, unsigned_test_values) {
+    FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) {
+      FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) {
+        float value = static_cast<float>(*i & 0xFFFFFFFF);
+        int32_t in_offset = *j1 + *k1;
+        int32_t out_offset = *j2 + *k2;
+
+        CHECK_EQ(true, run_Unaligned<float>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             __ Ulwc1(f0, MemOperand(a0, in_offset), t0);
+                             __ Uswc1(f0, MemOperand(a0, out_offset), t0);
+                           }));
+      }
+    }
+  }
+}
+
+TEST(Uldc1) {
+  CcTest::InitializeVM();
+
+  static const int kBufferSize = 300 * KB;
+  char memory_buffer[kBufferSize];
+  char* buffer_middle = memory_buffer + (kBufferSize / 2);
+
+  FOR_UINT64_INPUTS(i, unsigned_test_values) {
+    FOR_INT32_INPUTS2(j1, j2, unsigned_test_offset) {
+      FOR_INT32_INPUTS2(k1, k2, unsigned_test_offset_increment) {
+        double value = static_cast<double>(*i);
+        int32_t in_offset = *j1 + *k1;
+        int32_t out_offset = *j2 + *k2;
+
+        CHECK_EQ(true, run_Unaligned<double>(
+                           buffer_middle, in_offset, out_offset, value,
+                           [](MacroAssembler* masm, int32_t in_offset,
+                              int32_t out_offset) {
+                             __ Uldc1(f0, MemOperand(a0, in_offset), t0);
+                             __ Usdc1(f0, MemOperand(a0, out_offset), t0);
+                           }));
+      }
+    }
+  }
+}
+
 #undef __
diff --git a/test/cctest/test-microtask-delivery.cc b/test/cctest/test-microtask-delivery.cc
deleted file mode 100644
index 3150ab8..0000000
--- a/test/cctest/test-microtask-delivery.cc
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * 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.
-
-#include "src/v8.h"
-
-#include "test/cctest/cctest.h"
-
-namespace i = v8::internal;
-
-namespace {
-class HarmonyIsolate {
- public:
-  HarmonyIsolate() {
-    v8::Isolate::CreateParams create_params;
-    create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
-    isolate_ = v8::Isolate::New(create_params);
-    isolate_->Enter();
-  }
-
-  ~HarmonyIsolate() {
-    isolate_->Exit();
-    isolate_->Dispose();
-  }
-
-  v8::Isolate* GetIsolate() const { return isolate_; }
-
- private:
-  v8::Isolate* isolate_;
-};
-}  // namespace
-
-
-TEST(MicrotaskDeliverySimple) {
-  i::FLAG_harmony_object_observe = true;
-  HarmonyIsolate isolate;
-  v8::HandleScope scope(isolate.GetIsolate());
-  LocalContext context(isolate.GetIsolate());
-  CompileRun(
-      "var ordering = [];"
-      "var resolver = {};"
-      "function handler(resolve) { resolver.resolve = resolve; }"
-      "var obj = {};"
-      "var observeOrders = [1, 4];"
-      "function observer() {"
-        "ordering.push(observeOrders.shift());"
-        "resolver.resolve();"
-      "}"
-      "var p = new Promise(handler);"
-      "p.then(function() {"
-        "ordering.push(2);"
-      "}).then(function() {"
-        "ordering.push(3);"
-        "obj.id++;"
-        "return new Promise(handler);"
-      "}).then(function() {"
-        "ordering.push(5);"
-      "}).then(function() {"
-        "ordering.push(6);"
-      "});"
-      "Object.observe(obj, observer);"
-      "obj.id = 1;");
-  CHECK_EQ(
-      6, CompileRun("ordering.length")->Int32Value(context.local()).FromJust());
-  CHECK_EQ(1,
-           CompileRun("ordering[0]")->Int32Value(context.local()).FromJust());
-  CHECK_EQ(2,
-           CompileRun("ordering[1]")->Int32Value(context.local()).FromJust());
-  CHECK_EQ(3,
-           CompileRun("ordering[2]")->Int32Value(context.local()).FromJust());
-  CHECK_EQ(4,
-           CompileRun("ordering[3]")->Int32Value(context.local()).FromJust());
-  CHECK_EQ(5,
-           CompileRun("ordering[4]")->Int32Value(context.local()).FromJust());
-  CHECK_EQ(6,
-           CompileRun("ordering[5]")->Int32Value(context.local()).FromJust());
-}
-
-
-TEST(MicrotaskPerIsolateState) {
-  i::FLAG_harmony_object_observe = true;
-  HarmonyIsolate isolate;
-  v8::HandleScope scope(isolate.GetIsolate());
-  LocalContext context1(isolate.GetIsolate());
-  isolate.GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
-  CompileRun(
-      "var obj = { calls: 0 };");
-  v8::Local<v8::Value> obj = CompileRun("obj");
-  {
-    LocalContext context2(isolate.GetIsolate());
-    context2->Global()
-        ->Set(context2.local(),
-              v8::String::NewFromUtf8(isolate.GetIsolate(), "obj",
-                                      v8::NewStringType::kNormal)
-                  .ToLocalChecked(),
-              obj)
-        .FromJust();
-    CompileRun(
-        "var resolver = {};"
-        "new Promise(function(resolve) {"
-          "resolver.resolve = resolve;"
-        "}).then(function() {"
-          "obj.calls++;"
-        "});"
-        "(function() {"
-          "resolver.resolve();"
-        "})();");
-  }
-  {
-    LocalContext context3(isolate.GetIsolate());
-    context3->Global()
-        ->Set(context3.local(),
-              v8::String::NewFromUtf8(isolate.GetIsolate(), "obj",
-                                      v8::NewStringType::kNormal)
-                  .ToLocalChecked(),
-              obj)
-        .FromJust();
-    CompileRun(
-        "var foo = { id: 1 };"
-        "Object.observe(foo, function() {"
-          "obj.calls++;"
-        "});"
-        "foo.id++;");
-  }
-  {
-    LocalContext context4(isolate.GetIsolate());
-    context4->Global()
-        ->Set(context4.local(),
-              v8::String::NewFromUtf8(isolate.GetIsolate(), "obj",
-                                      v8::NewStringType::kNormal)
-                  .ToLocalChecked(),
-              obj)
-        .FromJust();
-    isolate.GetIsolate()->RunMicrotasks();
-    CHECK_EQ(2,
-             CompileRun("obj.calls")->Int32Value(context4.local()).FromJust());
-  }
-}
diff --git a/test/cctest/test-object-observe.cc b/test/cctest/test-object-observe.cc
deleted file mode 100644
index f17b8c0..0000000
--- a/test/cctest/test-object-observe.cc
+++ /dev/null
@@ -1,1078 +0,0 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * 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.
-
-#include "src/v8.h"
-
-#include "test/cctest/cctest.h"
-
-using namespace v8;
-namespace i = v8::internal;
-
-inline int32_t ToInt32(v8::Local<v8::Value> value) {
-  return value->Int32Value(v8::Isolate::GetCurrent()->GetCurrentContext())
-      .FromJust();
-}
-
-
-TEST(PerIsolateState) {
-  i::FLAG_harmony_object_observe = true;
-  HandleScope scope(CcTest::isolate());
-  LocalContext context1(CcTest::isolate());
-
-  Local<Value> foo = v8_str("foo");
-  context1->SetSecurityToken(foo);
-
-  CompileRun(
-      "var count = 0;"
-      "var calls = 0;"
-      "var observer = function(records) { count = records.length; calls++ };"
-      "var obj = {};"
-      "Object.observe(obj, observer);");
-  Local<Value> observer = CompileRun("observer");
-  Local<Value> obj = CompileRun("obj");
-  Local<Value> notify_fun1 = CompileRun("(function() { obj.foo = 'bar'; })");
-  Local<Value> notify_fun2;
-  {
-    LocalContext context2(CcTest::isolate());
-    context2->SetSecurityToken(foo);
-    context2->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"),
-              obj)
-        .FromJust();
-    notify_fun2 = CompileRun(
-        "(function() { obj.foo = 'baz'; })");
-  }
-  Local<Value> notify_fun3;
-  {
-    LocalContext context3(CcTest::isolate());
-    context3->SetSecurityToken(foo);
-    context3->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"),
-              obj)
-        .FromJust();
-    notify_fun3 = CompileRun("(function() { obj.foo = 'bat'; })");
-  }
-  {
-    LocalContext context4(CcTest::isolate());
-    context4->SetSecurityToken(foo);
-    context4->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(),
-              v8_str("observer"), observer)
-        .FromJust();
-    context4->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("fun1"),
-              notify_fun1)
-        .FromJust();
-    context4->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("fun2"),
-              notify_fun2)
-        .FromJust();
-    context4->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("fun3"),
-              notify_fun3)
-        .FromJust();
-    CompileRun("fun1(); fun2(); fun3(); Object.deliverChangeRecords(observer)");
-  }
-  CHECK_EQ(1, ToInt32(CompileRun("calls")));
-  CHECK_EQ(3, ToInt32(CompileRun("count")));
-}
-
-
-TEST(EndOfMicrotaskDelivery) {
-  i::FLAG_harmony_object_observe = true;
-  HandleScope scope(CcTest::isolate());
-  LocalContext context(CcTest::isolate());
-  CompileRun(
-      "var obj = {};"
-      "var count = 0;"
-      "var observer = function(records) { count = records.length };"
-      "Object.observe(obj, observer);"
-      "obj.foo = 'bar';");
-  CHECK_EQ(1, ToInt32(CompileRun("count")));
-}
-
-
-TEST(DeliveryOrdering) {
-  i::FLAG_harmony_object_observe = true;
-  HandleScope scope(CcTest::isolate());
-  LocalContext context(CcTest::isolate());
-  CompileRun(
-      "var obj1 = {};"
-      "var obj2 = {};"
-      "var ordering = [];"
-      "function observer2() { ordering.push(2); };"
-      "function observer1() { ordering.push(1); };"
-      "function observer3() { ordering.push(3); };"
-      "Object.observe(obj1, observer1);"
-      "Object.observe(obj1, observer2);"
-      "Object.observe(obj1, observer3);"
-      "obj1.foo = 'bar';");
-  CHECK_EQ(3, ToInt32(CompileRun("ordering.length")));
-  CHECK_EQ(1, ToInt32(CompileRun("ordering[0]")));
-  CHECK_EQ(2, ToInt32(CompileRun("ordering[1]")));
-  CHECK_EQ(3, ToInt32(CompileRun("ordering[2]")));
-  CompileRun(
-      "ordering = [];"
-      "Object.observe(obj2, observer3);"
-      "Object.observe(obj2, observer2);"
-      "Object.observe(obj2, observer1);"
-      "obj2.foo = 'baz'");
-  CHECK_EQ(3, ToInt32(CompileRun("ordering.length")));
-  CHECK_EQ(1, ToInt32(CompileRun("ordering[0]")));
-  CHECK_EQ(2, ToInt32(CompileRun("ordering[1]")));
-  CHECK_EQ(3, ToInt32(CompileRun("ordering[2]")));
-}
-
-
-TEST(DeliveryCallbackThrows) {
-  i::FLAG_harmony_object_observe = true;
-  HandleScope scope(CcTest::isolate());
-  LocalContext context(CcTest::isolate());
-  CompileRun(
-      "var obj = {};"
-      "var ordering = [];"
-      "function observer1() { ordering.push(1); };"
-      "function observer2() { ordering.push(2); };"
-      "function observer_throws() {"
-      "  ordering.push(0);"
-      "  throw new Error();"
-      "  ordering.push(-1);"
-      "};"
-      "Object.observe(obj, observer_throws.bind());"
-      "Object.observe(obj, observer1);"
-      "Object.observe(obj, observer_throws.bind());"
-      "Object.observe(obj, observer2);"
-      "Object.observe(obj, observer_throws.bind());"
-      "obj.foo = 'bar';");
-  CHECK_EQ(5, ToInt32(CompileRun("ordering.length")));
-  CHECK_EQ(0, ToInt32(CompileRun("ordering[0]")));
-  CHECK_EQ(1, ToInt32(CompileRun("ordering[1]")));
-  CHECK_EQ(0, ToInt32(CompileRun("ordering[2]")));
-  CHECK_EQ(2, ToInt32(CompileRun("ordering[3]")));
-  CHECK_EQ(0, ToInt32(CompileRun("ordering[4]")));
-}
-
-
-TEST(DeliveryChangesMutationInCallback) {
-  i::FLAG_harmony_object_observe = true;
-  HandleScope scope(CcTest::isolate());
-  LocalContext context(CcTest::isolate());
-  CompileRun(
-      "var obj = {};"
-      "var ordering = [];"
-      "function observer1(records) {"
-      "  ordering.push(100 + records.length);"
-      "  records.push(11);"
-      "  records.push(22);"
-      "};"
-      "function observer2(records) {"
-      "  ordering.push(200 + records.length);"
-      "  records.push(33);"
-      "  records.push(44);"
-      "};"
-      "Object.observe(obj, observer1);"
-      "Object.observe(obj, observer2);"
-      "obj.foo = 'bar';");
-  CHECK_EQ(2, ToInt32(CompileRun("ordering.length")));
-  CHECK_EQ(101, ToInt32(CompileRun("ordering[0]")));
-  CHECK_EQ(201, ToInt32(CompileRun("ordering[1]")));
-}
-
-
-TEST(DeliveryOrderingReentrant) {
-  i::FLAG_harmony_object_observe = true;
-  HandleScope scope(CcTest::isolate());
-  LocalContext context(CcTest::isolate());
-  CompileRun(
-      "var obj = {};"
-      "var reentered = false;"
-      "var ordering = [];"
-      "function observer1() { ordering.push(1); };"
-      "function observer2() {"
-      "  if (!reentered) {"
-      "    obj.foo = 'baz';"
-      "    reentered = true;"
-      "  }"
-      "  ordering.push(2);"
-      "};"
-      "function observer3() { ordering.push(3); };"
-      "Object.observe(obj, observer1);"
-      "Object.observe(obj, observer2);"
-      "Object.observe(obj, observer3);"
-      "obj.foo = 'bar';");
-  CHECK_EQ(5, ToInt32(CompileRun("ordering.length")));
-  CHECK_EQ(1, ToInt32(CompileRun("ordering[0]")));
-  CHECK_EQ(2, ToInt32(CompileRun("ordering[1]")));
-  CHECK_EQ(3, ToInt32(CompileRun("ordering[2]")));
-  // Note that we re-deliver to observers 1 and 2, while observer3
-  // already received the second record during the first round.
-  CHECK_EQ(1, ToInt32(CompileRun("ordering[3]")));
-  CHECK_EQ(2, ToInt32(CompileRun("ordering[1]")));
-}
-
-
-TEST(DeliveryOrderingDeliverChangeRecords) {
-  i::FLAG_harmony_object_observe = true;
-  HandleScope scope(CcTest::isolate());
-  LocalContext context(CcTest::isolate());
-  CompileRun(
-      "var obj = {};"
-      "var ordering = [];"
-      "function observer1() { ordering.push(1); if (!obj.b) obj.b = true };"
-      "function observer2() { ordering.push(2); };"
-      "Object.observe(obj, observer1);"
-      "Object.observe(obj, observer2);"
-      "obj.a = 1;"
-      "Object.deliverChangeRecords(observer2);");
-  CHECK_EQ(4, ToInt32(CompileRun("ordering.length")));
-  // First, observer2 is called due to deliverChangeRecords
-  CHECK_EQ(2, ToInt32(CompileRun("ordering[0]")));
-  // Then, observer1 is called when the stack unwinds
-  CHECK_EQ(1, ToInt32(CompileRun("ordering[1]")));
-  // observer1's mutation causes both 1 and 2 to be reactivated,
-  // with 1 having priority.
-  CHECK_EQ(1, ToInt32(CompileRun("ordering[2]")));
-  CHECK_EQ(2, ToInt32(CompileRun("ordering[3]")));
-}
-
-
-TEST(ObjectHashTableGrowth) {
-  i::FLAG_harmony_object_observe = true;
-  HandleScope scope(CcTest::isolate());
-  // Initializing this context sets up initial hash tables.
-  LocalContext context(CcTest::isolate());
-  Local<Value> obj = CompileRun("obj = {};");
-  Local<Value> observer = CompileRun(
-      "var ran = false;"
-      "(function() { ran = true })");
-  {
-    // As does initializing this context.
-    LocalContext context2(CcTest::isolate());
-    context2->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"),
-              obj)
-        .FromJust();
-    context2->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(),
-              v8_str("observer"), observer)
-        .FromJust();
-    CompileRun(
-        "var objArr = [];"
-        // 100 objects should be enough to make the hash table grow
-        // (and thus relocate).
-        "for (var i = 0; i < 100; ++i) {"
-        "  objArr.push({});"
-        "  Object.observe(objArr[objArr.length-1], function(){});"
-        "}"
-        "Object.observe(obj, observer);");
-  }
-  // obj is now marked "is_observed", but our map has moved.
-  CompileRun("obj.foo = 'bar'");
-  CHECK(CompileRun("ran")
-            ->BooleanValue(v8::Isolate::GetCurrent()->GetCurrentContext())
-            .FromJust());
-}
-
-
-struct RecordExpectation {
-  Local<Value> object;
-  const char* type;
-  const char* name;
-  Local<Value> old_value;
-};
-
-
-// TODO(adamk): Use this helper elsewhere in this file.
-static void ExpectRecords(v8::Isolate* isolate, Local<Value> records,
-                          const RecordExpectation expectations[], int num) {
-  CHECK(records->IsArray());
-  Local<Array> recordArray = records.As<Array>();
-  CHECK_EQ(num, static_cast<int>(recordArray->Length()));
-  for (int i = 0; i < num; ++i) {
-    Local<Value> record =
-        recordArray->Get(v8::Isolate::GetCurrent()->GetCurrentContext(), i)
-            .ToLocalChecked();
-    CHECK(record->IsObject());
-    Local<Object> recordObj = record.As<Object>();
-    Local<Value> value =
-        recordObj->Get(v8::Isolate::GetCurrent()->GetCurrentContext(),
-                       v8_str("object"))
-            .ToLocalChecked();
-    CHECK(expectations[i].object->StrictEquals(value));
-    value = recordObj->Get(v8::Isolate::GetCurrent()->GetCurrentContext(),
-                           v8_str("type"))
-                .ToLocalChecked();
-    CHECK(v8_str(expectations[i].type)
-              ->Equals(v8::Isolate::GetCurrent()->GetCurrentContext(), value)
-              .FromJust());
-    if (strcmp("splice", expectations[i].type) != 0) {
-      Local<Value> name =
-          recordObj->Get(v8::Isolate::GetCurrent()->GetCurrentContext(),
-                         v8_str("name"))
-              .ToLocalChecked();
-      CHECK(v8_str(expectations[i].name)
-                ->Equals(v8::Isolate::GetCurrent()->GetCurrentContext(), name)
-                .FromJust());
-      if (!expectations[i].old_value.IsEmpty()) {
-        Local<Value> old_value =
-            recordObj->Get(v8::Isolate::GetCurrent()->GetCurrentContext(),
-                           v8_str("oldValue"))
-                .ToLocalChecked();
-        CHECK(expectations[i]
-                  .old_value->Equals(
-                                v8::Isolate::GetCurrent()->GetCurrentContext(),
-                                old_value)
-                  .FromJust());
-      }
-    }
-  }
-}
-
-#define EXPECT_RECORDS(records, expectations)                \
-  ExpectRecords(CcTest::isolate(), records, expectations, \
-                arraysize(expectations))
-
-TEST(APITestBasicMutation) {
-  i::FLAG_harmony_object_observe = true;
-  v8::Isolate* v8_isolate = CcTest::isolate();
-  HandleScope scope(v8_isolate);
-  LocalContext context(v8_isolate);
-  Local<Object> obj = Local<Object>::Cast(
-      CompileRun("var records = [];"
-                 "var obj = {};"
-                 "function observer(r) { [].push.apply(records, r); };"
-                 "Object.observe(obj, observer);"
-                 "obj"));
-  obj->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("foo"),
-           Number::New(v8_isolate, 7))
-      .FromJust();
-  obj->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), 1,
-           Number::New(v8_isolate, 2))
-      .FromJust();
-  // CreateDataProperty should work just as well as Set
-  obj->CreateDataProperty(v8::Isolate::GetCurrent()->GetCurrentContext(),
-                          v8_str("foo"), Number::New(v8_isolate, 3))
-      .FromJust();
-  obj->CreateDataProperty(v8::Isolate::GetCurrent()->GetCurrentContext(), 1,
-                          Number::New(v8_isolate, 4))
-      .FromJust();
-  // Setting an indexed element via the property setting method
-  obj->Set(v8::Isolate::GetCurrent()->GetCurrentContext(),
-           Number::New(v8_isolate, 1), Number::New(v8_isolate, 5))
-      .FromJust();
-  // Setting with a non-String, non-uint32 key
-  obj->Set(v8::Isolate::GetCurrent()->GetCurrentContext(),
-           Number::New(v8_isolate, 1.1), Number::New(v8_isolate, 6))
-      .FromJust();
-  obj->Delete(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("foo"))
-      .FromJust();
-  obj->Delete(v8::Isolate::GetCurrent()->GetCurrentContext(), 1).FromJust();
-  obj->Delete(v8::Isolate::GetCurrent()->GetCurrentContext(),
-              Number::New(v8_isolate, 1.1))
-      .FromJust();
-
-  // Force delivery
-  // TODO(adamk): Should the above set methods trigger delivery themselves?
-  CompileRun("void 0");
-  CHECK_EQ(9, ToInt32(CompileRun("records.length")));
-  const RecordExpectation expected_records[] = {
-      {obj, "add", "foo", Local<Value>()},
-      {obj, "add", "1", Local<Value>()},
-      // Note: use 7 not 1 below, as the latter triggers a nifty VS10 compiler
-      // bug
-      // where instead of 1.0, a garbage value would be passed into Number::New.
-      {obj, "update", "foo", Number::New(v8_isolate, 7)},
-      {obj, "update", "1", Number::New(v8_isolate, 2)},
-      {obj, "update", "1", Number::New(v8_isolate, 4)},
-      {obj, "add", "1.1", Local<Value>()},
-      {obj, "delete", "foo", Number::New(v8_isolate, 3)},
-      {obj, "delete", "1", Number::New(v8_isolate, 5)},
-      {obj, "delete", "1.1", Number::New(v8_isolate, 6)}};
-  EXPECT_RECORDS(CompileRun("records"), expected_records);
-}
-
-
-TEST(HiddenPrototypeObservation) {
-  i::FLAG_harmony_object_observe = true;
-  v8::Isolate* v8_isolate = CcTest::isolate();
-  HandleScope scope(v8_isolate);
-  LocalContext context(v8_isolate);
-  Local<FunctionTemplate> tmpl = FunctionTemplate::New(v8_isolate);
-  tmpl->SetHiddenPrototype(true);
-  tmpl->InstanceTemplate()->Set(v8_str("foo"), Number::New(v8_isolate, 75));
-  Local<Function> function =
-      tmpl->GetFunction(v8::Isolate::GetCurrent()->GetCurrentContext())
-          .ToLocalChecked();
-  Local<Object> proto =
-      function->NewInstance(v8::Isolate::GetCurrent()->GetCurrentContext())
-          .ToLocalChecked();
-  Local<Object> obj = Object::New(v8_isolate);
-  obj->SetPrototype(v8::Isolate::GetCurrent()->GetCurrentContext(), proto)
-      .FromJust();
-  context->Global()
-      ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"), obj)
-      .FromJust();
-  context->Global()
-      ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("proto"),
-            proto)
-      .FromJust();
-  CompileRun(
-      "var records;"
-      "function observer(r) { records = r; };"
-      "Object.observe(obj, observer);"
-      "obj.foo = 41;"  // triggers a notification
-      "proto.foo = 42;");  // does not trigger a notification
-  const RecordExpectation expected_records[] = {
-    { obj, "update", "foo", Number::New(v8_isolate, 75) }
-  };
-  EXPECT_RECORDS(CompileRun("records"), expected_records);
-  obj->SetPrototype(v8::Isolate::GetCurrent()->GetCurrentContext(),
-                    Null(v8_isolate))
-      .FromJust();
-  CompileRun("obj.foo = 43");
-  const RecordExpectation expected_records2[] = {
-      {obj, "add", "foo", Local<Value>()}};
-  EXPECT_RECORDS(CompileRun("records"), expected_records2);
-  obj->SetPrototype(v8::Isolate::GetCurrent()->GetCurrentContext(), proto)
-      .FromJust();
-  CompileRun(
-      "Object.observe(proto, observer);"
-      "proto.bar = 1;"
-      "Object.unobserve(obj, observer);"
-      "obj.foo = 44;");
-  const RecordExpectation expected_records3[] = {
-      {proto, "add", "bar", Local<Value>()}
-      // TODO(adamk): The below record should be emitted since proto is observed
-      // and has been modified. Not clear if this happens in practice.
-      // { proto, "update", "foo", Number::New(43) }
-  };
-  EXPECT_RECORDS(CompileRun("records"), expected_records3);
-}
-
-
-static int NumberOfElements(i::Handle<i::JSWeakMap> map) {
-  return i::ObjectHashTable::cast(map->table())->NumberOfElements();
-}
-
-
-TEST(ObservationWeakMap) {
-  i::FLAG_harmony_object_observe = true;
-  HandleScope scope(CcTest::isolate());
-  LocalContext context(CcTest::isolate());
-  CompileRun(
-      "var obj = {};"
-      "Object.observe(obj, function(){});"
-      "Object.getNotifier(obj);"
-      "obj = null;");
-  i::Isolate* i_isolate = CcTest::i_isolate();
-  i::Handle<i::JSObject> observation_state =
-      i_isolate->factory()->observation_state();
-  i::Handle<i::JSWeakMap> callbackInfoMap = i::Handle<i::JSWeakMap>::cast(
-      i::JSReceiver::GetProperty(i_isolate, observation_state,
-                                 "callbackInfoMap")
-          .ToHandleChecked());
-  i::Handle<i::JSWeakMap> objectInfoMap = i::Handle<i::JSWeakMap>::cast(
-      i::JSReceiver::GetProperty(i_isolate, observation_state, "objectInfoMap")
-          .ToHandleChecked());
-  i::Handle<i::JSWeakMap> notifierObjectInfoMap = i::Handle<i::JSWeakMap>::cast(
-      i::JSReceiver::GetProperty(i_isolate, observation_state,
-                                 "notifierObjectInfoMap")
-          .ToHandleChecked());
-  CHECK_EQ(1, NumberOfElements(callbackInfoMap));
-  CHECK_EQ(1, NumberOfElements(objectInfoMap));
-  CHECK_EQ(1, NumberOfElements(notifierObjectInfoMap));
-  i_isolate->heap()->CollectAllGarbage();
-  CHECK_EQ(0, NumberOfElements(callbackInfoMap));
-  CHECK_EQ(0, NumberOfElements(objectInfoMap));
-  CHECK_EQ(0, NumberOfElements(notifierObjectInfoMap));
-}
-
-
-static int TestObserveSecurity(Local<Context> observer_context,
-                               Local<Context> object_context,
-                               Local<Context> mutation_context) {
-  Context::Scope observer_scope(observer_context);
-  CompileRun("var records = null;"
-             "var observer = function(r) { records = r };");
-  Local<Value> observer = CompileRun("observer");
-  {
-    Context::Scope object_scope(object_context);
-    object_context->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(),
-              v8_str("observer"), observer)
-        .FromJust();
-    CompileRun("var obj = {};"
-               "obj.length = 0;"
-               "Object.observe(obj, observer,"
-                   "['add', 'update', 'delete','reconfigure','splice']"
-               ");");
-    Local<Value> obj = CompileRun("obj");
-    {
-      Context::Scope mutation_scope(mutation_context);
-      mutation_context->Global()
-          ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"),
-                obj)
-          .FromJust();
-      CompileRun("obj.foo = 'bar';"
-                 "obj.foo = 'baz';"
-                 "delete obj.foo;"
-                 "Object.defineProperty(obj, 'bar', {value: 'bot'});"
-                 "Array.prototype.push.call(obj, 1, 2, 3);"
-                 "Array.prototype.splice.call(obj, 1, 2, 2, 4);"
-                 "Array.prototype.pop.call(obj);"
-                 "Array.prototype.shift.call(obj);");
-    }
-  }
-  return ToInt32(CompileRun("records ? records.length : 0"));
-}
-
-
-TEST(ObserverSecurityAAA) {
-  i::FLAG_harmony_object_observe = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Local<Context> contextA = Context::New(isolate);
-  CHECK_EQ(8, TestObserveSecurity(contextA, contextA, contextA));
-}
-
-
-TEST(ObserverSecurityA1A2A3) {
-  i::FLAG_harmony_object_observe = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-
-  v8::Local<Context> contextA1 = Context::New(isolate);
-  v8::Local<Context> contextA2 = Context::New(isolate);
-  v8::Local<Context> contextA3 = Context::New(isolate);
-
-  Local<Value> foo = v8_str("foo");
-  contextA1->SetSecurityToken(foo);
-  contextA2->SetSecurityToken(foo);
-  contextA3->SetSecurityToken(foo);
-
-  CHECK_EQ(8, TestObserveSecurity(contextA1, contextA2, contextA3));
-}
-
-
-TEST(ObserverSecurityAAB) {
-  i::FLAG_harmony_object_observe = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Local<Context> contextA = Context::New(isolate);
-  v8::Local<Context> contextB = Context::New(isolate);
-  CHECK_EQ(0, TestObserveSecurity(contextA, contextA, contextB));
-}
-
-
-TEST(ObserverSecurityA1A2B) {
-  i::FLAG_harmony_object_observe = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-
-  v8::Local<Context> contextA1 = Context::New(isolate);
-  v8::Local<Context> contextA2 = Context::New(isolate);
-  v8::Local<Context> contextB = Context::New(isolate);
-
-  Local<Value> foo = v8_str("foo");
-  contextA1->SetSecurityToken(foo);
-  contextA2->SetSecurityToken(foo);
-
-  CHECK_EQ(0, TestObserveSecurity(contextA1, contextA2, contextB));
-}
-
-
-TEST(ObserverSecurityABA) {
-  i::FLAG_harmony_object_observe = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Local<Context> contextA = Context::New(isolate);
-  v8::Local<Context> contextB = Context::New(isolate);
-  CHECK_EQ(0, TestObserveSecurity(contextA, contextB, contextA));
-}
-
-
-TEST(ObserverSecurityA1BA2) {
-  i::FLAG_harmony_object_observe = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Local<Context> contextA1 = Context::New(isolate);
-  v8::Local<Context> contextA2 = Context::New(isolate);
-  v8::Local<Context> contextB = Context::New(isolate);
-
-  Local<Value> foo = v8_str("foo");
-  contextA1->SetSecurityToken(foo);
-  contextA2->SetSecurityToken(foo);
-
-  CHECK_EQ(0, TestObserveSecurity(contextA1, contextB, contextA2));
-}
-
-
-TEST(ObserverSecurityBAA) {
-  i::FLAG_harmony_object_observe = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Local<Context> contextA = Context::New(isolate);
-  v8::Local<Context> contextB = Context::New(isolate);
-  CHECK_EQ(0, TestObserveSecurity(contextB, contextA, contextA));
-}
-
-
-TEST(ObserverSecurityBA1A2) {
-  i::FLAG_harmony_object_observe = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Local<Context> contextA1 = Context::New(isolate);
-  v8::Local<Context> contextA2 = Context::New(isolate);
-  v8::Local<Context> contextB = Context::New(isolate);
-
-  Local<Value> foo = v8_str("foo");
-  contextA1->SetSecurityToken(foo);
-  contextA2->SetSecurityToken(foo);
-
-  CHECK_EQ(0, TestObserveSecurity(contextB, contextA1, contextA2));
-}
-
-
-TEST(ObserverSecurityNotify) {
-  i::FLAG_harmony_object_observe = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  v8::Local<Context> contextA = Context::New(isolate);
-  v8::Local<Context> contextB = Context::New(isolate);
-
-  Context::Scope scopeA(contextA);
-  CompileRun("var obj = {};"
-             "var recordsA = null;"
-             "var observerA = function(r) { recordsA = r };"
-             "Object.observe(obj, observerA);");
-  Local<Value> obj = CompileRun("obj");
-
-  {
-    Context::Scope scopeB(contextB);
-    contextB->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"),
-              obj)
-        .FromJust();
-    CompileRun("var recordsB = null;"
-               "var observerB = function(r) { recordsB = r };"
-               "Object.observe(obj, observerB);");
-  }
-
-  CompileRun("var notifier = Object.getNotifier(obj);"
-             "notifier.notify({ type: 'update' });");
-  CHECK_EQ(1, ToInt32(CompileRun("recordsA ? recordsA.length : 0")));
-
-  {
-    Context::Scope scopeB(contextB);
-    CHECK_EQ(0, ToInt32(CompileRun("recordsB ? recordsB.length : 0")));
-  }
-}
-
-
-TEST(HiddenPropertiesLeakage) {
-  i::FLAG_harmony_object_observe = true;
-  HandleScope scope(CcTest::isolate());
-  LocalContext context(CcTest::isolate());
-  CompileRun("var obj = {};"
-             "var records = null;"
-             "var observer = function(r) { records = r };"
-             "Object.observe(obj, observer);");
-  Local<Value> obj =
-      context->Global()
-          ->Get(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"))
-          .ToLocalChecked();
-  Local<Object>::Cast(obj)
-      ->SetPrivate(v8::Isolate::GetCurrent()->GetCurrentContext(),
-                   v8::Private::New(CcTest::isolate(), v8_str("foo")),
-                   Null(CcTest::isolate()))
-      .FromJust();
-  CompileRun("");  // trigger delivery
-  CHECK(CompileRun("records")->IsNull());
-}
-
-
-TEST(GetNotifierFromOtherContext) {
-  i::FLAG_harmony_object_observe = true;
-  HandleScope scope(CcTest::isolate());
-  LocalContext context(CcTest::isolate());
-  CompileRun("var obj = {};");
-  Local<Value> instance = CompileRun("obj");
-  {
-    LocalContext context2(CcTest::isolate());
-    context2->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"),
-              instance)
-        .FromJust();
-    CHECK(CompileRun("Object.getNotifier(obj)")->IsNull());
-  }
-}
-
-
-TEST(GetNotifierFromOtherOrigin) {
-  i::FLAG_harmony_object_observe = true;
-  HandleScope scope(CcTest::isolate());
-  Local<Value> foo = v8_str("foo");
-  Local<Value> bar = v8_str("bar");
-  LocalContext context(CcTest::isolate());
-  context->SetSecurityToken(foo);
-  CompileRun("var obj = {};");
-  Local<Value> instance = CompileRun("obj");
-  {
-    LocalContext context2(CcTest::isolate());
-    context2->SetSecurityToken(bar);
-    context2->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"),
-              instance)
-        .FromJust();
-    CHECK(CompileRun("Object.getNotifier(obj)")->IsNull());
-  }
-}
-
-
-TEST(GetNotifierFromSameOrigin) {
-  i::FLAG_harmony_object_observe = true;
-  HandleScope scope(CcTest::isolate());
-  Local<Value> foo = v8_str("foo");
-  LocalContext context(CcTest::isolate());
-  context->SetSecurityToken(foo);
-  CompileRun("var obj = {};");
-  Local<Value> instance = CompileRun("obj");
-  {
-    LocalContext context2(CcTest::isolate());
-    context2->SetSecurityToken(foo);
-    context2->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"),
-              instance)
-        .FromJust();
-    CHECK(CompileRun("Object.getNotifier(obj)")->IsObject());
-  }
-}
-
-
-static int GetGlobalObjectsCount() {
-  int count = 0;
-  i::HeapIterator it(CcTest::heap());
-  for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
-    if (object->IsJSGlobalObject()) {
-      i::JSGlobalObject* g = i::JSGlobalObject::cast(object);
-      // Skip dummy global object.
-      if (i::GlobalDictionary::cast(g->properties())->NumberOfElements() != 0) {
-        count++;
-      }
-    }
-  // Subtract one to compensate for the code stub context that is always present
-  return count - 1;
-}
-
-
-static void CheckSurvivingGlobalObjectsCount(int expected) {
-  // We need to collect all garbage twice to be sure that everything
-  // has been collected.  This is because inline caches are cleared in
-  // the first garbage collection but some of the maps have already
-  // been marked at that point.  Therefore some of the maps are not
-  // collected until the second garbage collection.
-  CcTest::heap()->CollectAllGarbage();
-  CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
-  int count = GetGlobalObjectsCount();
-#ifdef DEBUG
-  if (count != expected) CcTest::heap()->TracePathToGlobal();
-#endif
-  CHECK_EQ(expected, count);
-}
-
-
-TEST(DontLeakContextOnObserve) {
-  i::FLAG_harmony_object_observe = true;
-  HandleScope scope(CcTest::isolate());
-  Local<Value> foo = v8_str("foo");
-  LocalContext context(CcTest::isolate());
-  context->SetSecurityToken(foo);
-  CompileRun("var obj = {};");
-  Local<Value> object = CompileRun("obj");
-  {
-    HandleScope scope(CcTest::isolate());
-    LocalContext context2(CcTest::isolate());
-    context2->SetSecurityToken(foo);
-    context2->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"),
-              object)
-        .FromJust();
-    CompileRun("function observer() {};"
-               "Object.observe(obj, observer, ['foo', 'bar', 'baz']);"
-               "Object.unobserve(obj, observer);");
-  }
-
-  CcTest::isolate()->ContextDisposedNotification();
-  CheckSurvivingGlobalObjectsCount(0);
-}
-
-
-TEST(DontLeakContextOnGetNotifier) {
-  i::FLAG_harmony_object_observe = true;
-  HandleScope scope(CcTest::isolate());
-  Local<Value> foo = v8_str("foo");
-  LocalContext context(CcTest::isolate());
-  context->SetSecurityToken(foo);
-  CompileRun("var obj = {};");
-  Local<Value> object = CompileRun("obj");
-  {
-    HandleScope scope(CcTest::isolate());
-    LocalContext context2(CcTest::isolate());
-    context2->SetSecurityToken(foo);
-    context2->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"),
-              object)
-        .FromJust();
-    CompileRun("Object.getNotifier(obj);");
-  }
-
-  CcTest::isolate()->ContextDisposedNotification();
-  CheckSurvivingGlobalObjectsCount(0);
-}
-
-
-TEST(DontLeakContextOnNotifierPerformChange) {
-  i::FLAG_harmony_object_observe = true;
-  HandleScope scope(CcTest::isolate());
-  Local<Value> foo = v8_str("foo");
-  LocalContext context(CcTest::isolate());
-  context->SetSecurityToken(foo);
-  CompileRun("var obj = {};");
-  Local<Value> object = CompileRun("obj");
-  Local<Value> notifier = CompileRun("Object.getNotifier(obj)");
-  {
-    HandleScope scope(CcTest::isolate());
-    LocalContext context2(CcTest::isolate());
-    context2->SetSecurityToken(foo);
-    context2->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"),
-              object)
-        .FromJust();
-    context2->Global()
-        ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(),
-              v8_str("notifier"), notifier)
-        .FromJust();
-    CompileRun("var obj2 = {};"
-               "var notifier2 = Object.getNotifier(obj2);"
-               "notifier2.performChange.call("
-                   "notifier, 'foo', function(){})");
-  }
-
-  CcTest::isolate()->ContextDisposedNotification();
-  CheckSurvivingGlobalObjectsCount(0);
-}
-
-
-static void ObserverCallback(const FunctionCallbackInfo<Value>& args) {
-  *static_cast<int*>(Local<External>::Cast(args.Data())->Value()) =
-      Local<Array>::Cast(args[0])->Length();
-}
-
-
-TEST(ObjectObserveCallsCppFunction) {
-  i::FLAG_harmony_object_observe = true;
-  Isolate* isolate = CcTest::isolate();
-  HandleScope scope(isolate);
-  LocalContext context(isolate);
-  int numRecordsSent = 0;
-  Local<Function> observer =
-      Function::New(CcTest::isolate()->GetCurrentContext(), ObserverCallback,
-                    External::New(isolate, &numRecordsSent))
-          .ToLocalChecked();
-  context->Global()
-      ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("observer"),
-            observer)
-      .FromJust();
-  CompileRun(
-      "var obj = {};"
-      "Object.observe(obj, observer);"
-      "obj.foo = 1;"
-      "obj.bar = 2;");
-  CHECK_EQ(2, numRecordsSent);
-}
-
-
-TEST(ObjectObserveCallsFunctionTemplateInstance) {
-  i::FLAG_harmony_object_observe = true;
-  Isolate* isolate = CcTest::isolate();
-  HandleScope scope(isolate);
-  LocalContext context(isolate);
-  int numRecordsSent = 0;
-  Local<FunctionTemplate> tmpl = FunctionTemplate::New(
-      isolate, ObserverCallback, External::New(isolate, &numRecordsSent));
-  Local<Function> function =
-      tmpl->GetFunction(v8::Isolate::GetCurrent()->GetCurrentContext())
-          .ToLocalChecked();
-  context->Global()
-      ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("observer"),
-            function)
-      .FromJust();
-  CompileRun(
-      "var obj = {};"
-      "Object.observe(obj, observer);"
-      "obj.foo = 1;"
-      "obj.bar = 2;");
-  CHECK_EQ(2, numRecordsSent);
-}
-
-
-static void AccessorGetter(Local<Name> property,
-                           const PropertyCallbackInfo<Value>& info) {
-  info.GetReturnValue().Set(Integer::New(info.GetIsolate(), 42));
-}
-
-
-static void AccessorSetter(Local<Name> property, Local<Value> value,
-                           const PropertyCallbackInfo<void>& info) {
-  info.GetReturnValue().SetUndefined();
-}
-
-
-TEST(APIAccessorsShouldNotNotify) {
-  i::FLAG_harmony_object_observe = true;
-  Isolate* isolate = CcTest::isolate();
-  HandleScope handle_scope(isolate);
-  LocalContext context(isolate);
-  Local<Object> object = Object::New(isolate);
-  object->SetAccessor(v8::Isolate::GetCurrent()->GetCurrentContext(),
-                      v8_str("accessor"), &AccessorGetter, &AccessorSetter)
-      .FromJust();
-  context->Global()
-      ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"),
-            object)
-      .FromJust();
-  CompileRun(
-      "var records = null;"
-      "Object.observe(obj, function(r) { records = r });"
-      "obj.accessor = 43;");
-  CHECK(CompileRun("records")->IsNull());
-  CompileRun("Object.defineProperty(obj, 'accessor', { value: 44 });");
-  CHECK(CompileRun("records")->IsNull());
-}
-
-
-namespace {
-
-int* global_use_counts = NULL;
-
-void MockUseCounterCallback(v8::Isolate* isolate,
-                            v8::Isolate::UseCounterFeature feature) {
-  ++global_use_counts[feature];
-}
-}
-
-
-TEST(UseCountObjectObserve) {
-  i::FLAG_harmony_object_observe = true;
-  i::Isolate* isolate = CcTest::i_isolate();
-  i::HandleScope scope(isolate);
-  LocalContext env;
-  int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
-  global_use_counts = use_counts;
-  CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
-  CompileRun(
-      "var obj = {};"
-      "Object.observe(obj, function(){})");
-  CHECK_EQ(1, use_counts[v8::Isolate::kObjectObserve]);
-  CompileRun(
-      "var obj2 = {};"
-      "Object.observe(obj2, function(){})");
-  // Only counts the first use of observe in a given context.
-  CHECK_EQ(1, use_counts[v8::Isolate::kObjectObserve]);
-  {
-    LocalContext env2;
-    CompileRun(
-        "var obj = {};"
-        "Object.observe(obj, function(){})");
-  }
-  // Counts different contexts separately.
-  CHECK_EQ(2, use_counts[v8::Isolate::kObjectObserve]);
-}
-
-
-TEST(UseCountObjectGetNotifier) {
-  i::FLAG_harmony_object_observe = true;
-  i::Isolate* isolate = CcTest::i_isolate();
-  i::HandleScope scope(isolate);
-  LocalContext env;
-  int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
-  global_use_counts = use_counts;
-  CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
-  CompileRun("var obj = {}");
-  CompileRun("Object.getNotifier(obj)");
-  CHECK_EQ(1, use_counts[v8::Isolate::kObjectObserve]);
-}
-
-static bool NamedAccessCheckAlwaysAllow(Local<v8::Context> accessing_context,
-                                        Local<v8::Object> accessed_object,
-                                        Local<v8::Value> data) {
-  return true;
-}
-
-
-TEST(DisallowObserveAccessCheckedObject) {
-  i::FLAG_harmony_object_observe = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  LocalContext env;
-  v8::Local<v8::ObjectTemplate> object_template =
-      v8::ObjectTemplate::New(isolate);
-  object_template->SetAccessCheckCallback(NamedAccessCheckAlwaysAllow);
-  Local<Object> new_instance =
-      object_template->NewInstance(
-                         v8::Isolate::GetCurrent()->GetCurrentContext())
-          .ToLocalChecked();
-  env->Global()
-      ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"),
-            new_instance)
-      .FromJust();
-  v8::TryCatch try_catch(isolate);
-  CompileRun("Object.observe(obj, function(){})");
-  CHECK(try_catch.HasCaught());
-}
-
-
-TEST(DisallowGetNotifierAccessCheckedObject) {
-  i::FLAG_harmony_object_observe = true;
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  LocalContext env;
-  v8::Local<v8::ObjectTemplate> object_template =
-      v8::ObjectTemplate::New(isolate);
-  object_template->SetAccessCheckCallback(NamedAccessCheckAlwaysAllow);
-  Local<Object> new_instance =
-      object_template->NewInstance(
-                         v8::Isolate::GetCurrent()->GetCurrentContext())
-          .ToLocalChecked();
-  env->Global()
-      ->Set(v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str("obj"),
-            new_instance)
-      .FromJust();
-  v8::TryCatch try_catch(isolate);
-  CompileRun("Object.getNotifier(obj)");
-  CHECK(try_catch.HasCaught());
-}
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index ae278d8..ab1fc76 100644
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -1070,7 +1070,6 @@
       i::Zone zone(CcTest::i_isolate()->allocator());
       i::ParseInfo info(&zone, script);
       i::Parser parser(&info);
-      parser.set_allow_harmony_sloppy(true);
       info.set_global();
       CHECK(parser.Parse(&info));
       CHECK(i::Rewriter::Rewrite(&info));
@@ -1122,13 +1121,11 @@
 
   i::ParseInfo info(handles.main_zone(), script);
   i::Parser parser(&info);
-  parser.set_allow_harmony_sloppy(true);
   info.set_global();
   info.set_lazy(false);
   info.set_allow_lazy_parsing(false);
   info.set_toplevel(true);
 
-  i::CompilationInfo compilation_info(&info);
   CHECK(i::Compiler::ParseAndAnalyze(&info));
 
   CHECK(info.scope()->declarations()->length() == 1);
@@ -1438,7 +1435,6 @@
     i::ParseInfo info(&zone, script);
     info.set_allow_lazy_parsing();
     i::Parser parser(&info);
-    parser.set_allow_harmony_sloppy(true);
     parser.Parse(&info);
     function = info.literal();
     CHECK_NOT_NULL(function);
@@ -1509,12 +1505,12 @@
 enum ParserFlag {
   kAllowLazy,
   kAllowNatives,
-  kAllowHarmonySloppy,
-  kAllowHarmonySloppyLet,
-  kAllowHarmonyNewTarget,
   kAllowHarmonyFunctionSent,
   kAllowHarmonyRestrictiveDeclarations,
-  kAllowHarmonyExponentiationOperator
+  kAllowHarmonyExponentiationOperator,
+  kAllowHarmonyForIn,
+  kAllowHarmonyAsyncAwait,
+  kAllowHarmonyRestrictiveGenerators,
 };
 
 enum ParserSyncTestResult {
@@ -1528,28 +1524,31 @@
                     i::EnumSet<ParserFlag> flags) {
   parser->set_allow_lazy(flags.Contains(kAllowLazy));
   parser->set_allow_natives(flags.Contains(kAllowNatives));
-  parser->set_allow_harmony_sloppy(flags.Contains(kAllowHarmonySloppy));
-  parser->set_allow_harmony_sloppy_let(flags.Contains(kAllowHarmonySloppyLet));
   parser->set_allow_harmony_function_sent(
       flags.Contains(kAllowHarmonyFunctionSent));
   parser->set_allow_harmony_restrictive_declarations(
       flags.Contains(kAllowHarmonyRestrictiveDeclarations));
   parser->set_allow_harmony_exponentiation_operator(
       flags.Contains(kAllowHarmonyExponentiationOperator));
+  parser->set_allow_harmony_for_in(flags.Contains(kAllowHarmonyForIn));
+  parser->set_allow_harmony_async_await(
+      flags.Contains(kAllowHarmonyAsyncAwait));
+  parser->set_allow_harmony_restrictive_generators(
+      flags.Contains(kAllowHarmonyRestrictiveGenerators));
 }
 
 
 void TestParserSyncWithFlags(i::Handle<i::String> source,
                              i::EnumSet<ParserFlag> flags,
                              ParserSyncTestResult result,
-                             bool is_module = false) {
+                             bool is_module = false,
+                             bool test_preparser = true) {
   i::Isolate* isolate = CcTest::i_isolate();
   i::Factory* factory = isolate->factory();
 
   uintptr_t stack_limit = isolate->stack_guard()->real_climit();
   int preparser_materialized_literals = -1;
   int parser_materialized_literals = -2;
-  bool test_preparser = !is_module;
 
   // Preparse the data.
   i::CompleteParserRecorder log;
@@ -1563,8 +1562,8 @@
                            stack_limit);
     SetParserFlags(&preparser, flags);
     scanner.Initialize(&stream);
-    i::PreParser::PreParseResult result = preparser.PreParseProgram(
-        &preparser_materialized_literals);
+    i::PreParser::PreParseResult result =
+        preparser.PreParseProgram(&preparser_materialized_literals, is_module);
     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
   }
   bool preparse_error = log.HasError();
@@ -1674,7 +1673,7 @@
                     size_t always_true_flags_length = 0,
                     const ParserFlag* always_false_flags = NULL,
                     size_t always_false_flags_length = 0,
-                    bool is_module = false) {
+                    bool is_module = false, bool test_preparser = true) {
   i::Handle<i::String> str =
       CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(source);
   for (int bits = 0; bits < (1 << varying_flags_length); bits++) {
@@ -1691,7 +1690,7 @@
          ++flag_index) {
       flags.Remove(always_false_flags[flag_index]);
     }
-    TestParserSyncWithFlags(str, flags, result, is_module);
+    TestParserSyncWithFlags(str, flags, result, is_module, test_preparser);
   }
 }
 
@@ -1839,7 +1838,8 @@
                        const ParserFlag* always_true_flags = NULL,
                        int always_true_len = 0,
                        const ParserFlag* always_false_flags = NULL,
-                       int always_false_len = 0, bool is_module = false) {
+                       int always_false_len = 0, bool is_module = false,
+                       bool test_preparser = true) {
   v8::HandleScope handles(CcTest::isolate());
   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
   v8::Context::Scope context_scope(context);
@@ -1894,7 +1894,7 @@
       CHECK(length == kProgramSize);
       TestParserSync(program.start(), flags, flags_len, result,
                      always_true_flags, always_true_len, always_false_flags,
-                     always_false_len, is_module);
+                     always_false_len, is_module, test_preparser);
     }
   }
   delete[] generated_flags;
@@ -1908,10 +1908,11 @@
                              const ParserFlag* always_true_flags = NULL,
                              int always_true_len = 0,
                              const ParserFlag* always_false_flags = NULL,
-                             int always_false_len = 0) {
+                             int always_false_len = 0,
+                             bool test_preparser = true) {
   RunParserSyncTest(context_data, statement_data, result, flags, flags_len,
                     always_true_flags, always_true_len, always_false_flags,
-                    always_false_len, true);
+                    always_false_len, true, test_preparser);
 }
 
 
@@ -2017,25 +2018,28 @@
   RunParserSyncTest(context_data, statement_data, kSuccess);
 }
 
+#define FUTURE_STRICT_RESERVED_WORDS_NO_LET(V) \
+  V(implements)                                \
+  V(interface)                                 \
+  V(package)                                   \
+  V(private)                                   \
+  V(protected)                                 \
+  V(public)                                    \
+  V(static)                                    \
+  V(yield)
 
 #define FUTURE_STRICT_RESERVED_WORDS(V) \
-  V(implements)                         \
-  V(interface)                          \
   V(let)                                \
-  V(package)                            \
-  V(private)                            \
-  V(protected)                          \
-  V(public)                             \
-  V(static)                             \
-  V(yield)
+  FUTURE_STRICT_RESERVED_WORDS_NO_LET(V)
 
+#define LIMITED_FUTURE_STRICT_RESERVED_WORDS_NO_LET(V) \
+  V(implements)                                        \
+  V(static)                                            \
+  V(yield)
 
 #define LIMITED_FUTURE_STRICT_RESERVED_WORDS(V) \
-  V(implements)                                 \
   V(let)                                        \
-  V(static)                                     \
-  V(yield)
-
+  LIMITED_FUTURE_STRICT_RESERVED_WORDS_NO_LET(V)
 
 #define FUTURE_STRICT_RESERVED_STATEMENTS(NAME) \
   "var " #NAME ";",                             \
@@ -2051,26 +2055,53 @@
   "++" #NAME ";",                               \
   #NAME " ++;",
 
+// clang-format off
+#define FUTURE_STRICT_RESERVED_LEX_BINDINGS(NAME) \
+  "let " #NAME ";",                               \
+  "for (let " #NAME "; false; ) {}",              \
+  "for (let " #NAME " in {}) {}",                 \
+  "for (let " #NAME " of []) {}",                 \
+  "const " #NAME " = null;",                      \
+  "for (const " #NAME " = null; false; ) {}",     \
+  "for (const " #NAME " in {}) {}",               \
+  "for (const " #NAME " of []) {}",
+// clang-format on
 
 TEST(ErrorsFutureStrictReservedWords) {
   // Tests that both preparsing and parsing produce the right kind of errors for
   // using future strict reserved words as identifiers. Without the strict mode,
   // it's ok to use future strict reserved words as identifiers. With the strict
   // mode, it isn't.
-  const char* context_data[][2] = {
+  const char* strict_contexts[][2] = {
       {"function test_func() {\"use strict\"; ", "}"},
       {"() => { \"use strict\"; ", "}"},
       {NULL, NULL}};
 
+  // clang-format off
   const char* statement_data[] {
     LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
+    LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_LEX_BINDINGS)
     NULL
   };
+  // clang-format on
 
-  RunParserSyncTest(context_data, statement_data, kError);
+  RunParserSyncTest(strict_contexts, statement_data, kError);
+
+  // From ES2015, 13.3.1.1 Static Semantics: Early Errors:
+  //
+  // > LexicalDeclaration : LetOrConst BindingList ;
+  // >
+  // > - It is a Syntax Error if the BoundNames of BindingList contains "let".
+  const char* non_strict_contexts[][2] = {{"", ""},
+                                          {"function test_func() {", "}"},
+                                          {"() => {", "}"},
+                                          {NULL, NULL}};
+  const char* invalid_statements[] = {FUTURE_STRICT_RESERVED_LEX_BINDINGS("let")
+                                          NULL};
+
+  RunParserSyncTest(non_strict_contexts, invalid_statements, kError);
 }
 
-
 #undef LIMITED_FUTURE_STRICT_RESERVED_WORDS
 
 
@@ -2082,10 +2113,13 @@
     { NULL, NULL }
   };
 
+  // clang-format off
   const char* statement_data[] = {
     FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
+    FUTURE_STRICT_RESERVED_WORDS_NO_LET(FUTURE_STRICT_RESERVED_LEX_BINDINGS)
     NULL
   };
+  // clang-format on
 
   RunParserSyncTest(context_data, statement_data, kSuccess);
 }
@@ -2349,9 +2383,7 @@
   };
   // clang-format on
 
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
-  RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, statement_data, kSuccess);
 }
 
 
@@ -2407,6 +2439,10 @@
     "var {foo: yield 24} = {a: 42};",
     "[yield 24] = [42];",
     "({a: yield 24} = {a: 42});",
+    "for (yield 'x' in {});",
+    "for (yield 'x' of {});",
+    "for (yield 'x' in {} in {});",
+    "for (yield 'x' in {} of {});",
     "class C extends yield { }",
     NULL
   };
@@ -3533,10 +3569,8 @@
   CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
   CompileRun("\"use asm\";\n"
              "var foo = 1;\n"
-             "\"use asm\";\n"  // Only the first one counts.
              "function bar() { \"use asm\"; var baz = 1; }");
-  // Optimizing will double-count because the source is parsed twice.
-  CHECK_EQ(i::FLAG_always_opt ? 4 : 2, use_counts[v8::Isolate::kUseAsm]);
+  CHECK_LT(0, use_counts[v8::Isolate::kUseAsm]);
 }
 
 
@@ -3949,11 +3983,7 @@
     NULL
   };
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonySloppy
-  };
-  RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, statement_data, kSuccess);
 }
 
 
@@ -3980,9 +4010,7 @@
     NULL
   };
 
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
-  RunParserSyncTest(context_data, expression_data, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, expression_data, kError);
 }
 
 
@@ -3996,9 +4024,7 @@
     NULL
   };
 
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
-  RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, success_data, kSuccess);
 
   const char* error_data[] = {
     "class C { constructor() { super(); } }",
@@ -4020,8 +4046,7 @@
     NULL
   };
 
-  RunParserSyncTest(context_data, error_data, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, error_data, kError);
 }
 
 
@@ -4046,9 +4071,7 @@
     NULL
   };
 
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
-  RunParserSyncTest(context_data, expression_data, kSuccess, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, expression_data, kSuccess);
 }
 
 
@@ -4079,9 +4102,7 @@
     NULL
   };
 
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
-  RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, statement_data, kError);
 }
 
 
@@ -4119,11 +4140,7 @@
     NULL
   };
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonySloppy
-  };
-  RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, statement_data, kError);
 }
 
 
@@ -4336,9 +4353,7 @@
     "class name extends class base {} {}",
     NULL};
 
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
-  RunParserSyncTest(context_data, class_data, kSuccess, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, class_data, kSuccess);
 }
 
 
@@ -4412,11 +4427,7 @@
     NULL};
   // clang-format on
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonySloppy
-  };
-  RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, class_body_data, kSuccess);
 }
 
 
@@ -4469,11 +4480,7 @@
     "finally",
     NULL};
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonySloppy
-  };
-  RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, name_data, kSuccess);
 }
 
 
@@ -4499,11 +4506,7 @@
     "class { m() {}, n() {} }",  // No commas allowed.
     NULL};
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonySloppy
-  };
-  RunParserSyncTest(context_data, class_data, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, class_data, kError);
 }
 
 
@@ -4535,11 +4538,7 @@
     "class name { *static m() {} }",
     NULL};
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonySloppy
-  };
-  RunParserSyncTest(context_data, class_data, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, class_data, kError);
 }
 
 
@@ -4564,11 +4563,7 @@
     "yield",
     NULL};
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonySloppy
-  };
-  RunParserSyncTest(context_data, class_name, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, class_name, kError);
 }
 
 
@@ -4596,11 +4591,7 @@
     "yield",
     NULL};
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonySloppy
-  };
-  RunParserSyncTest(context_data, class_name, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, class_name, kError);
 }
 
 
@@ -4623,11 +4614,7 @@
     "static *'prot\\u006ftype'() {}",
     NULL};
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonySloppy
-  };
-  RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, class_body_data, kError);
 }
 
 
@@ -4649,11 +4636,7 @@
     "*'c\\u006fnstructor'() {}",
     NULL};
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonySloppy
-  };
-  RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, class_body_data, kError);
 }
 
 
@@ -4670,11 +4653,7 @@
     "static *constructor() {}",
     NULL};
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonySloppy
-  };
-  RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, class_body_data, kSuccess);
 }
 
 
@@ -4687,11 +4666,7 @@
     "constructor() {}; constructor() {}",
     NULL};
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonySloppy
-  };
-  RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, class_body_data, kError);
 }
 
 
@@ -4708,11 +4683,7 @@
     "get m() {}; set m(_) {}; get m() {}; set m(_) {};",
     NULL};
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonySloppy
-  };
-  RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, class_body_data, kSuccess);
 }
 
 
@@ -4727,11 +4698,7 @@
     "class C { *method() { with ({}) {} } }",
     NULL};
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonySloppy
-  };
-  RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, class_body_data, kError);
 }
 
 
@@ -4869,10 +4836,7 @@
                         "for(let x in {}, {}) {}", "for(const x in {}, {}) {}",
                         NULL};
 
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
-                                            kAllowHarmonySloppyLet};
-  RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
-                    arraysize(always_flags));
+  RunParserSyncTest(context_data, data, kSuccess);
 }
 
 
@@ -4980,9 +4944,7 @@
       "for (const i, j = 1 in {}) {}",
       "for (const i, j = void 0 in [1, 2, 3]) {}",
       NULL};
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
-  RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
-                    arraysize(always_flags));
+  RunParserSyncTest(context_data, data, kError);
 }
 
 
@@ -5009,9 +4971,7 @@
       "for (const i, j = 1 of {}) {}",
       "for (const i, j = void 0 of [1, 2, 3]) {}",
       NULL};
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
-  RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
-                    arraysize(always_flags));
+  RunParserSyncTest(context_data, data, kError);
 }
 
 
@@ -5026,9 +4986,7 @@
       "for (var in {}) {}",
       "for (const in {}) {}",
       NULL};
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
-  RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
-                    arraysize(always_flags));
+  RunParserSyncTest(context_data, data, kError);
 }
 
 
@@ -5043,9 +5001,7 @@
       "for (var of [1, 2, 3]) {}",
       "for (const of [1, 2, 3]) {}",
       NULL};
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
-  RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
-                    arraysize(always_flags));
+  RunParserSyncTest(context_data, data, kError);
 }
 
 
@@ -5059,10 +5015,7 @@
       "for(x of 'foo' in {}) {}", "for(var x of 'foo' in {}) {}",
       "for(let x of 'foo' in {}) {}", "for(const x of 'foo' in {}) {}", NULL};
 
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
-                                            kAllowHarmonySloppyLet};
-  RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
-                    arraysize(always_flags));
+  RunParserSyncTest(context_data, data, kSuccess);
 }
 
 
@@ -5073,10 +5026,7 @@
                         "for(let x of yield) {}", "for(const x of yield) {}",
                         NULL};
 
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
-                                            kAllowHarmonySloppyLet};
-  RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
-                    arraysize(always_flags));
+  RunParserSyncTest(context_data, data, kSuccess);
 }
 
 
@@ -5091,10 +5041,7 @@
                         "function* g() { for(let x of yield) {} }",
                         "function* g() { for(const x of yield) {} }", NULL};
 
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
-                                            kAllowHarmonySloppyLet};
-  RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
-                    arraysize(always_flags));
+  RunParserSyncTest(context_data, data, kSuccess);
 }
 
 
@@ -5112,10 +5059,7 @@
       "for(x of { y = 23 }) {}", "for(var x of { y = 23 }) {}",
       "for(let x of { y = 23 }) {}", "for(const x of { y = 23 }) {}", NULL};
 
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
-                                            kAllowHarmonySloppyLet};
-  RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
-                    arraysize(always_flags));
+  RunParserSyncTest(context_data, data, kError);
 }
 
 
@@ -5205,7 +5149,7 @@
       "`foo${\r a}`",
       "`foo${'a' in a}`",
       NULL};
-  RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
+  RunParserSyncTest(context_data, data, kSuccess);
 }
 
 
@@ -5240,7 +5184,7 @@
       "tag`foo${\r a}`",
       "tag`foo${'a' in a}`",
       NULL};
-  RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
+  RunParserSyncTest(context_data, data, kSuccess);
 }
 
 
@@ -5267,7 +5211,7 @@
     NULL
   };
 
-  RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
+  RunParserSyncTest(context_data, data, kSuccess);
 }
 
 
@@ -5301,7 +5245,7 @@
       "`foo${fn(}`",
       "`foo${1 if}`",
       NULL};
-  RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
+  RunParserSyncTest(context_data, data, kError);
 }
 
 
@@ -5321,7 +5265,7 @@
       "`hello${1}\\x\n${2}`",
       NULL};
 
-  RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
+  RunParserSyncTest(context_data, data, kError);
 }
 
 
@@ -5396,13 +5340,12 @@
       {nullptr, nullptr}};
   const char* data[] = {"...a", "...arguments", "...eval", nullptr};
 
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
-  RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
-                    arraysize(always_flags));
+  RunParserSyncTest(context_data, data, kError);
 }
 
 
 TEST(RestParametersEvalArguments) {
+  // clang-format off
   const char* strict_context_data[][2] =
       {{"'use strict';(function(",
         "){ return;})(1, [], /regexp/, 'str',function(){});"},
@@ -5416,8 +5359,10 @@
       "...eval",
       "eval, ...args",
       "...arguments",
-      "arguments, ...args",
+      // See https://bugs.chromium.org/p/v8/issues/detail?id=4577
+      // "arguments, ...args",
       NULL};
+  // clang-format on
 
   // Fail in strict mode
   RunParserSyncTest(strict_context_data, data, kError);
@@ -5484,7 +5429,7 @@
                         "var [...x,] = [1,2,3];", "var [...x, y] = [1,2,3];",
                         "var {...x} = [1,2,3];",  "var { x } = {x: ...[1,2,3]}",
                         NULL};
-  RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
+  RunParserSyncTest(context_data, data, kError);
 }
 
 
@@ -5494,28 +5439,12 @@
       {"function f() {", "}"},
       {"{", "}"},
       {NULL, NULL}};
-  const char* bad_data[] = {
-    "let x = 1;",
-    "for(let x = 1;;){}",
-    "for(let x of []){}",
-    "for(let x in []){}",
-    "class C {}",
-    "class C extends D {}",
-    "(class {})",
-    "(class extends D {})",
-    "(class C {})",
-    "(class C extends D {})",
-    NULL};
-  static const ParserFlag always_false_flags[] = {kAllowHarmonySloppy};
-  RunParserSyncTest(context_data, bad_data, kError, NULL, 0, NULL, 0,
-                    always_false_flags, arraysize(always_false_flags));
 
   const char* good_data[] = {
     "let = 1;",
     "for(let = 1;;){}",
     NULL};
-  RunParserSyncTest(context_data, good_data, kSuccess, NULL, 0, NULL, 0,
-                    always_false_flags, arraysize(always_false_flags));
+  RunParserSyncTest(context_data, good_data, kSuccess);
 }
 
 
@@ -5535,11 +5464,7 @@
     "var name",
     NULL};
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonySloppy,
-  };
-  RunParserSyncTest(context_data, error_data, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, error_data, kError);
 
   const char* name_data[] = {
     "1",
@@ -5550,8 +5475,7 @@
     "{}",
     NULL};
 
-  RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, name_data, kSuccess);
 }
 
 
@@ -5563,11 +5487,7 @@
     "[1], a: 1",
     NULL};
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonySloppy,
-  };
-  RunParserSyncTest(context_data, error_data, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(context_data, error_data, kError);
 }
 
 
@@ -5600,6 +5520,8 @@
       "export { static } from 'm.js'",
       "export { let } from 'm.js'",
       "var a; export { a as b, a as c };",
+      "var a; export { a as await };",
+      "var a; export { a as enum };",
 
       "import 'somemodule.js';",
       "import { } from 'm.js';",
@@ -5725,6 +5647,8 @@
       "import { y as yield } from 'm.js'",
       "import { s as static } from 'm.js'",
       "import { l as let } from 'm.js'",
+      "import { a as await } from 'm.js';",
+      "import { a as enum } from 'm.js';",
       "import { x }, def from 'm.js';",
       "import def, def2 from 'm.js';",
       "import * as x, def from 'm.js';",
@@ -5757,6 +5681,179 @@
   }
 }
 
+TEST(ModuleTopLevelFunctionDecl) {
+  // clang-format off
+  const char* kErrorSources[] = {
+      "function f() {} function f() {}",
+      "var f; function f() {}",
+      "function f() {} var f;",
+      "function* f() {} function* f() {}",
+      "var f; function* f() {}",
+      "function* f() {} var f;",
+      "function f() {} function* f() {}",
+      "function* f() {} function f() {}",
+  };
+  // clang-format on
+
+  i::Isolate* isolate = CcTest::i_isolate();
+  i::Factory* factory = isolate->factory();
+
+  v8::HandleScope handles(CcTest::isolate());
+  v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
+  v8::Context::Scope context_scope(context);
+
+  isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
+                                        128 * 1024);
+
+  for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
+    i::Handle<i::String> source =
+        factory->NewStringFromAsciiChecked(kErrorSources[i]);
+
+    i::Handle<i::Script> script = factory->NewScript(source);
+    i::Zone zone(CcTest::i_isolate()->allocator());
+    i::ParseInfo info(&zone, script);
+    i::Parser parser(&info);
+    info.set_module();
+    CHECK(!parser.Parse(&info));
+  }
+}
+
+TEST(ModuleAwaitReserved) {
+  // clang-format off
+  const char* kErrorSources[] = {
+      "await;",
+      "await: ;",
+      "var await;",
+      "var [await] = [];",
+      "var { await } = {};",
+      "var { x: await } = {};",
+      "{ var await; }",
+      "let await;",
+      "let [await] = [];",
+      "let { await } = {};",
+      "let { x: await } = {};",
+      "{ let await; }",
+      "const await = null;",
+      "const [await] = [];",
+      "const { await } = {};",
+      "const { x: await } = {};",
+      "{ const await = null; }",
+      "function await() {}",
+      "function f(await) {}",
+      "function* await() {}",
+      "function* g(await) {}",
+      "(function await() {});",
+      "(function (await) {});",
+      "(function* await() {});",
+      "(function* (await) {});",
+      "(await) => {};",
+      "await => {};",
+      "class await {}",
+      "class C { constructor(await) {} }",
+      "class C { m(await) {} }",
+      "class C { static m(await) {} }",
+      "class C { *m(await) {} }",
+      "class C { static *m(await) {} }",
+      "(class await {})",
+      "(class { constructor(await) {} });",
+      "(class { m(await) {} });",
+      "(class { static m(await) {} });",
+      "(class { *m(await) {} });",
+      "(class { static *m(await) {} });",
+      "({ m(await) {} });",
+      "({ *m(await) {} });",
+      "({ set p(await) {} });",
+      "try {} catch (await) {}",
+      "try {} catch (await) {} finally {}",
+      NULL
+  };
+  // clang-format on
+  const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
+
+  RunModuleParserSyncTest(context_data, kErrorSources, kError);
+}
+
+TEST(ModuleAwaitReservedPreParse) {
+  const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
+  const char* error_data[] = {"function f() { var await = 0; }", NULL};
+
+  RunModuleParserSyncTest(context_data, error_data, kError);
+}
+
+TEST(ModuleAwaitPermitted) {
+  // clang-format off
+  const char* kValidSources[] = {
+    "({}).await;",
+    "({ await: null });",
+    "({ await() {} });",
+    "({ get await() {} });",
+    "({ set await(x) {} });",
+    "(class { await() {} });",
+    "(class { static await() {} });",
+    "(class { *await() {} });",
+    "(class { static *await() {} });",
+    NULL
+  };
+  // clang-format on
+  const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
+
+  RunModuleParserSyncTest(context_data, kValidSources, kSuccess);
+}
+
+TEST(EnumReserved) {
+  // clang-format off
+  const char* kErrorSources[] = {
+      "enum;",
+      "enum: ;",
+      "var enum;",
+      "var [enum] = [];",
+      "var { enum } = {};",
+      "var { x: enum } = {};",
+      "{ var enum; }",
+      "let enum;",
+      "let [enum] = [];",
+      "let { enum } = {};",
+      "let { x: enum } = {};",
+      "{ let enum; }",
+      "const enum = null;",
+      "const [enum] = [];",
+      "const { enum } = {};",
+      "const { x: enum } = {};",
+      "{ const enum = null; }",
+      "function enum() {}",
+      "function f(enum) {}",
+      "function* enum() {}",
+      "function* g(enum) {}",
+      "(function enum() {});",
+      "(function (enum) {});",
+      "(function* enum() {});",
+      "(function* (enum) {});",
+      "(enum) => {};",
+      "enum => {};",
+      "class enum {}",
+      "class C { constructor(enum) {} }",
+      "class C { m(enum) {} }",
+      "class C { static m(enum) {} }",
+      "class C { *m(enum) {} }",
+      "class C { static *m(enum) {} }",
+      "(class enum {})",
+      "(class { constructor(enum) {} });",
+      "(class { m(enum) {} });",
+      "(class { static m(enum) {} });",
+      "(class { *m(enum) {} });",
+      "(class { static *m(enum) {} });",
+      "({ m(enum) {} });",
+      "({ *m(enum) {} });",
+      "({ set p(enum) {} });",
+      "try {} catch (enum) {}",
+      "try {} catch (enum) {} finally {}",
+      NULL
+  };
+  // clang-format on
+  const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
+
+  RunModuleParserSyncTest(context_data, kErrorSources, kError);
+}
 
 TEST(ModuleParsingInternals) {
   i::Isolate* isolate = CcTest::i_isolate();
@@ -6213,9 +6310,7 @@
       "[ a ]",
       NULL};
     // clang-format on
-    static const ParserFlag always_flags[] = {kAllowHarmonySloppyLet};
-    RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
-                      arraysize(always_flags));
+    RunParserSyncTest(context_data, data, kError);
   }
 }
 
@@ -6684,6 +6779,9 @@
     // Arrow function within generator has the same rules.
     {"'use strict'; (function *g() { (", ") => {} });"},
     {"(function *g() { (", ") => {} });"},
+    // And similarly for arrow functions in the parameter list.
+    {"'use strict'; (function *g(z = (", ") => {}) { });"},
+    {"(function *g(z = (", ") => {}) { });"},
     {NULL, NULL}
   };
 
@@ -6819,16 +6917,10 @@
     NULL
   };
 
-  static const ParserFlag always_flags[] = {
-    kAllowHarmonyNewTarget,
-    kAllowHarmonySloppy,
-  };
   // clang-format on
 
-  RunParserSyncTest(good_context_data, data, kSuccess, NULL, 0, always_flags,
-                    arraysize(always_flags));
-  RunParserSyncTest(bad_context_data, data, kError, NULL, 0, always_flags,
-                    arraysize(always_flags));
+  RunParserSyncTest(good_context_data, data, kSuccess);
+  RunParserSyncTest(bad_context_data, data, kError);
 }
 
 
@@ -6848,9 +6940,7 @@
     NULL
   };
   // clang-format on
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
-  RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
-                    arraysize(always_flags));
+  RunParserSyncTest(context_data, data, kSuccess);
 }
 
 
@@ -6873,10 +6963,7 @@
   };
   // clang-format on
 
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
-                                            kAllowHarmonySloppyLet};
-  RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
-                    arraysize(always_flags));
+  RunParserSyncTest(context_data, data, kSuccess);
 }
 
 
@@ -6922,9 +7009,7 @@
       "{ initializedBindingPattern } = { initializedBindingPattern: true }",
       NULL};
 
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
-  RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
-                    arraysize(always_flags));
+  RunParserSyncTest(context_data, data, kError);
 }
 
 
@@ -6952,10 +7037,7 @@
   };
   // clang-format on
 
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
-                                            kAllowHarmonySloppyLet};
-  RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
-                    arraysize(always_flags));
+  RunParserSyncTest(context_data, data, kSuccess);
 
   // Some things should be rejected even in sloppy mode
   // This addresses BUG(v8:4403).
@@ -6989,10 +7071,7 @@
   };
   // clang-format on
 
-  static const ParserFlag fail_flags[] = {kAllowHarmonySloppy,
-                                          kAllowHarmonySloppyLet};
-  RunParserSyncTest(context_data, fail_data, kError, NULL, 0, fail_flags,
-                    arraysize(fail_flags));
+  RunParserSyncTest(context_data, fail_data, kError);
 }
 
 
@@ -7092,13 +7171,9 @@
   };
   // clang-format on
 
-  static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
-  RunParserSyncTest(sloppy_context_data, fail_data, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
-  RunParserSyncTest(strict_context_data, fail_data, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
-  RunModuleParserSyncTest(sloppy_context_data, fail_data, kError, NULL, 0,
-                          always_flags, arraysize(always_flags));
+  RunParserSyncTest(sloppy_context_data, fail_data, kError);
+  RunParserSyncTest(strict_context_data, fail_data, kError);
+  RunModuleParserSyncTest(sloppy_context_data, fail_data, kError);
 
   // clang-format off
   const char* let_data[] = {
@@ -7109,15 +7184,8 @@
   };
   // clang-format on
 
-  RunParserSyncTest(sloppy_context_data, let_data, kSuccess, NULL, 0,
-                    always_flags, arraysize(always_flags));
-  RunParserSyncTest(strict_context_data, let_data, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
-
-  static const ParserFlag sloppy_let_flags[] = {kAllowHarmonySloppy,
-                                                kAllowHarmonySloppyLet};
-  RunParserSyncTest(sloppy_context_data, let_data, kSuccess, NULL, 0,
-                    sloppy_let_flags, arraysize(sloppy_let_flags));
+  RunParserSyncTest(sloppy_context_data, let_data, kSuccess);
+  RunParserSyncTest(strict_context_data, let_data, kError);
 
   // Non-errors in sloppy mode
   const char* valid_data[] = {"(\\u0069mplements = 1);",
@@ -7142,12 +7210,9 @@
                               "var st\\u0061tic = 1;",
                               "var { st\\u0061tic } = {};",
                               NULL};
-  RunParserSyncTest(sloppy_context_data, valid_data, kSuccess, NULL, 0,
-                    always_flags, arraysize(always_flags));
-  RunParserSyncTest(strict_context_data, valid_data, kError, NULL, 0,
-                    always_flags, arraysize(always_flags));
-  RunModuleParserSyncTest(strict_context_data, valid_data, kError, NULL, 0,
-                          always_flags, arraysize(always_flags));
+  RunParserSyncTest(sloppy_context_data, valid_data, kSuccess);
+  RunParserSyncTest(strict_context_data, valid_data, kError);
+  RunModuleParserSyncTest(strict_context_data, valid_data, kError);
 }
 
 
@@ -7167,7 +7232,7 @@
   };
   // clang-format on
 
-  RunParserSyncTest(context_data, error_data, kError, NULL, 0, NULL, 0);
+  RunParserSyncTest(context_data, error_data, kError);
 }
 
 
@@ -7196,7 +7261,7 @@
   };
   // clang-format on
 
-  RunParserSyncTest(context_data, error_data, kError, NULL, 0, NULL, 0);
+  RunParserSyncTest(context_data, error_data, kError);
 }
 
 
@@ -7281,6 +7346,13 @@
     "with ({}) label: function f() { };",
     "if (true) label: function f() {}",
     "if (true) {} else label: function f() {}",
+    "if (true) function* f() { }",
+    "label: function* f() { }",
+    // TODO(littledan, v8:4806): Ban duplicate generator declarations in
+    // a block, maybe by tracking whether a Variable is a generator declaration
+    // "{ function* f() {} function* f() {} }",
+    // "{ function f() {} function* f() {} }",
+    // "{ function* f() {} function f() {} }",
     NULL
   };
   // Valid only in sloppy mode, with or without
@@ -7412,3 +7484,359 @@
   RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
                     arraysize(always_flags));
 }
+
+TEST(AsyncAwait) {
+  // clang-format off
+  const char* context_data[][2] = {
+    { "'use strict';", "" },
+    { "", "" },
+    { NULL, NULL }
+  };
+
+  const char* data[] = {
+    "var asyncFn = async function() { await 1; };",
+    "var asyncFn = async function withName() { await 1; };",
+    "var asyncFn = async () => await 'test';",
+    "var asyncFn = async x => await x + 'test';",
+    "async function asyncFn() { await 1; }",
+    "var O = { async method() { await 1; } }",
+    "var O = { async ['meth' + 'od']() { await 1; } }",
+    "var O = { async 'method'() { await 1; } }",
+    "var O = { async 0() { await 1; } }",
+    "async function await() {}",
+
+    "var asyncFn = async({ foo = 1 }) => foo;",
+    "var asyncFn = async({ foo = 1 } = {}) => foo;",
+    NULL
+  };
+  // clang-format on
+
+  static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
+  RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
+                    arraysize(always_flags));
+
+  // clang-format off
+  const char* async_body_context_data[][2] = {
+    { "async function f() {", "}" },
+    { "var f = async function() {", "}" },
+    { "var f = async() => {", "}" },
+    { "var O = { async method() {", "} }" },
+    { "'use strict'; async function f() {", "}" },
+    { "'use strict'; var f = async function() {", "}" },
+    { "'use strict'; var f = async() => {", "}" },
+    { "'use strict'; var O = { async method() {", "} }" },
+    { NULL, NULL }
+  };
+
+  const char* body_context_data[][2] = {
+    { "function f() {", "}" },
+    { "function* g() {", "}" },
+    { "var f = function() {", "}" },
+    { "var g = function*() {", "}" },
+    { "var O = { method() {", "} }" },
+    { "var O = { *method() {", "} }" },
+    { "var f = () => {", "}" },
+    { "'use strict'; function f() {", "}" },
+    { "'use strict'; function* g() {", "}" },
+    { "'use strict'; var f = function() {", "}" },
+    { "'use strict'; var g = function*() {", "}" },
+    { "'use strict'; var O = { method() {", "} }" },
+    { "'use strict'; var O = { *method() {", "} }" },
+    { "'use strict'; var f = () => {", "}" },
+    { NULL, NULL }
+  };
+
+  const char* body_data[] = {
+    "var async = 1; return async;",
+    "let async = 1; return async;",
+    "const async = 1; return async;",
+    "function async() {} return async();",
+    "var async = async => async; return async();",
+    "function foo() { var await = 1; return await; }",
+    "function foo(await) { return await; }",
+    "function* foo() { var await = 1; return await; }",
+    "function* foo(await) { return await; }",
+    "var f = (await) => await;",
+    "var f = () => { var await = 1; return await; }",
+    "var O = { method() { var await = 1; return await; } };",
+    "var O = { method(await) { return await; } };",
+    "var O = { *method() { var await = 1; return await; } };",
+    "var O = { *method(await) { return await; } };",
+
+    "(function await() {})",
+    NULL
+  };
+  // clang-format on
+
+  RunParserSyncTest(async_body_context_data, body_data, kSuccess, NULL, 0,
+                    always_flags, arraysize(always_flags));
+  RunParserSyncTest(body_context_data, body_data, kSuccess, NULL, 0,
+                    always_flags, arraysize(always_flags));
+}
+
+TEST(AsyncAwaitErrors) {
+  // clang-format off
+  const char* context_data[][2] = {
+    { "'use strict';", "" },
+    { "", "" },
+    { NULL, NULL }
+  };
+
+  const char* strict_context_data[][2] = {
+    { "'use strict';", "" },
+    { NULL, NULL }
+  };
+
+  const char* error_data[] = {
+    "var asyncFn = async function() { var await = 1; };",
+    "var asyncFn = async function() { var { await } = 1; };",
+    "var asyncFn = async function() { var [ await ] = 1; };",
+    "var asyncFn = async function await() {};",
+    "var asyncFn = async () => var await = 'test';",
+    "var asyncFn = async await => await + 'test';",
+    "var asyncFn = async function(await) {};",
+    "var asyncFn = async function() { return async (await) => {}; }",
+    "var asyncFn = async (await) => 'test';",
+    "var asyncFn = async x => { var await = 1; }",
+    "var asyncFn = async x => { var { await } = 1; }",
+    "var asyncFn = async x => { var [ await ] = 1; }",
+    "async function f(await) {}",
+    "async function f() { var await = 1; }",
+    "async function f() { var { await } = 1; }",
+    "async function f() { var [ await ] = 1; }",
+
+    "var O = { async method(a, a) {} }",
+    "var O = { async ['meth' + 'od'](a, a) {} }",
+    "var O = { async 'method'(a, a) {} }",
+    "var O = { async 0(a, a) {} }",
+
+    "async function f() { var O = { async [await](a, a) {} } }",
+
+    "var asyncFn = async function() { await; }",
+    "async function f() { await; }",
+    "var O = { async method() { await; } };",
+    "var f = async() => await;",
+    "var f = async() => { await; };",
+
+    "var asyncFn = async function*() {}",
+    "async function* f() {}",
+    "var O = { *async method() {} };",
+    "var O = { async *method() {} };",
+    "var O = { async method*() {} };",
+
+    "var asyncFn = async function(x = await 1) { return x; }",
+    "async function f(x = await 1) { return x; }",
+    "var f = async(x = await 1) => x;",
+    "var O = { async method(x = await 1) { return x; } };",
+
+    "var f = async(x = await) => 1;",
+
+    "class C { async constructor() {} }",
+    "class C {}; class C2 extends C { async constructor() {} }",
+    "class C { static async prototype() {} }",
+    "class C {}; class C2 extends C { static async prototype() {} }",
+
+    "var f = async() => ((async(x = await 1) => x)();",
+
+    "var asyncFn = async function() { function await() {} }",
+    "var asyncFn = async() => { function await() {} }",
+    "var O = { async method() { function await() {} } }",
+    "async function foo() { function await() {} }",
+
+    // Henrique Ferreiro's bug (tm)
+    "(async function foo() { } foo => 1)",
+    "(async function foo() { } () => 1)",
+    "(async function foo() { } => 1)",
+    "(async function() { } foo => 1)",
+    "(async function() { } () => 1)",
+    "(async function() { } => 1)",
+    "(async.foo => 1)",
+    "(async.foo foo => 1)",
+    "(async.foo () => 1)",
+    "(async().foo => 1)",
+    "(async().foo foo => 1)",
+    "(async().foo () => 1)",
+    "(async['foo'] => 1)",
+    "(async['foo'] foo => 1)",
+    "(async['foo'] () => 1)",
+    "(async()['foo'] => 1)",
+    "(async()['foo'] foo => 1)",
+    "(async()['foo'] () => 1)",
+    "(async`foo` => 1)",
+    "(async`foo` foo => 1)",
+    "(async`foo` () => 1)",
+    "(async`foo`.bar => 1)",
+    "(async`foo`.bar foo => 1)",
+    "(async`foo`.bar () => 1)",
+
+    // v8:5148 assert that errors are still thrown for calls that may have been
+    // async functions
+    "async({ foo = 1 })",
+    NULL
+  };
+
+  const char* strict_error_data[] = {
+    "var O = { async method(eval) {} }",
+    "var O = { async ['meth' + 'od'](eval) {} }",
+    "var O = { async 'method'(eval) {} }",
+    "var O = { async 0(eval) {} }",
+
+    "var O = { async method(arguments) {} }",
+    "var O = { async ['meth' + 'od'](arguments) {} }",
+    "var O = { async 'method'(arguments) {} }",
+    "var O = { async 0(arguments) {} }",
+
+    "var O = { async method(dupe, dupe) {} }",
+
+    // TODO(caitp): preparser needs to report duplicate parameter errors, too.
+    // "var f = async(dupe, dupe) => {}",
+
+    NULL
+  };
+
+  const char* formal_parameters_data[] = {
+    "var f = async({ await }) => 1;",
+    "var f = async({ await = 1 }) => 1;",
+    "var f = async({ await } = {}) => 1;",
+    "var f = async({ await = 1 } = {}) => 1;",
+    "var f = async([await]) => 1;",
+    "var f = async([await] = []) => 1;",
+    "var f = async([await = 1]) => 1;",
+    "var f = async([await = 1] = []) => 1;",
+    "var f = async(...await) => 1;",
+    "var f = async(await) => 1;",
+    "var f = async(await = 1) => 1;",
+    "var f = async(...[await]) => 1;",
+    NULL
+  };
+  // clang-format on
+
+  static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
+  RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
+                    arraysize(always_flags));
+  RunParserSyncTest(strict_context_data, strict_error_data, kError, NULL, 0,
+                    always_flags, arraysize(always_flags));
+
+  RunParserSyncTest(context_data, formal_parameters_data, kError, NULL, 0,
+                    always_flags, arraysize(always_flags));
+}
+
+TEST(AsyncAwaitModule) {
+  // clang-format off
+  const char* context_data[][2] = {
+    { "", "" },
+    { NULL, NULL }
+  };
+
+  const char* data[] = {
+    "export default async function() { await 1; }",
+    "export default async function async() { await 1; }",
+    "export async function async() { await 1; }",
+    NULL
+  };
+  // clang-format on
+
+  static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
+  RunModuleParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
+                          arraysize(always_flags), NULL, 0, false);
+}
+
+TEST(AsyncAwaitModuleErrors) {
+  // clang-format off
+  const char* context_data[][2] = {
+    { "", "" },
+    { NULL, NULL }
+  };
+
+  const char* error_data[] = {
+    "export default (async function await() {})",
+    "export default async function await() {}",
+    "export async function await() {}",
+    "export async function() {}",
+    "export async",
+    NULL
+  };
+  // clang-format on
+
+  static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
+  RunModuleParserSyncTest(context_data, error_data, kError, NULL, 0,
+                          always_flags, arraysize(always_flags), NULL, 0,
+                          false);
+}
+
+TEST(RestrictiveForInErrors) {
+  // clang-format off
+  const char* context_data[][2] = {
+    { "'use strict'", "" },
+    { "", "" },
+    { NULL, NULL }
+  };
+  const char* error_data[] = {
+    "for (var x = 0 in {});",
+    "for (const x = 0 in {});",
+    "for (let x = 0 in {});",
+    NULL
+  };
+  // clang-format on
+
+  static const ParserFlag always_flags[] = {kAllowHarmonyForIn};
+  RunParserSyncTest(context_data, error_data, kError, nullptr, 0, always_flags,
+                    arraysize(always_flags));
+}
+
+TEST(NoDuplicateGeneratorsInBlock) {
+  const char* block_context_data[][2] = {
+      {"'use strict'; {", "}"},
+      {"{", "}"},
+      {"(function() { {", "} })()"},
+      {"(function() {'use strict'; {", "} })()"},
+      {NULL, NULL}};
+  const char* top_level_context_data[][2] = {
+      {"'use strict';", ""},
+      {"", ""},
+      {"(function() {", "})()"},
+      {"(function() {'use strict';", "})()"},
+      {NULL, NULL}};
+  const char* error_data[] = {"function* x() {} function* x() {}",
+                              "function x() {} function* x() {}",
+                              "function* x() {} function x() {}", NULL};
+  static const ParserFlag always_flags[] = {kAllowHarmonyRestrictiveGenerators};
+  // The preparser doesn't enforce the restriction, so turn it off.
+  bool test_preparser = false;
+  RunParserSyncTest(block_context_data, error_data, kError, NULL, 0,
+                    always_flags, arraysize(always_flags), NULL, 0, false,
+                    test_preparser);
+  RunParserSyncTest(top_level_context_data, error_data, kSuccess, NULL, 0,
+                    always_flags, arraysize(always_flags));
+}
+
+TEST(NoDuplicateAsyncFunctionInBlock) {
+  const char* block_context_data[][2] = {
+      {"'use strict'; {", "}"},
+      {"{", "}"},
+      {"(function() { {", "} })()"},
+      {"(function() {'use strict'; {", "} })()"},
+      {NULL, NULL}};
+  const char* top_level_context_data[][2] = {
+      {"'use strict';", ""},
+      {"", ""},
+      {"(function() {", "})()"},
+      {"(function() {'use strict';", "})()"},
+      {NULL, NULL}};
+  const char* error_data[] = {"async function x() {} async function x() {}",
+                              "function x() {} async function x() {}",
+                              "async function x() {} function x() {}",
+                              "function* x() {} async function x() {}",
+                              "function* x() {} async function x() {}",
+                              "async function x() {} function* x() {}",
+                              "function* x() {} async function x() {}",
+                              NULL};
+  static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
+  // The preparser doesn't enforce the restriction, so turn it off.
+  bool test_preparser = false;
+  RunParserSyncTest(block_context_data, error_data, kError, NULL, 0,
+                    always_flags, arraysize(always_flags), NULL, 0, false,
+                    test_preparser);
+  RunParserSyncTest(top_level_context_data, error_data, kSuccess, NULL, 0,
+                    always_flags, arraysize(always_flags));
+}
diff --git a/test/cctest/test-platform.cc b/test/cctest/test-platform.cc
index 6012fd4..a0fbc21 100644
--- a/test/cctest/test-platform.cc
+++ b/test/cctest/test-platform.cc
@@ -17,7 +17,7 @@
 #elif V8_HOST_ARCH_IA32
   __asm__ __volatile__("mov %%esp, %0" : "=g"(sp_addr));
 #elif V8_HOST_ARCH_ARM
-  __asm__ __volatile__("str %%sp, %0" : "=g"(sp_addr));
+  __asm__ __volatile__("str sp, %0" : "=g"(sp_addr));
 #elif V8_HOST_ARCH_ARM64
   __asm__ __volatile__("mov x16, sp; str x16, %0" : "=g"(sp_addr));
 #elif V8_HOST_ARCH_MIPS
@@ -25,9 +25,9 @@
 #elif V8_HOST_ARCH_MIPS64
   __asm__ __volatile__("sd $sp, %0" : "=g"(sp_addr));
 #elif defined(__s390x__) || defined(_ARCH_S390X)
-  __asm__ __volatile__("stg 15, %0" : "=g"(sp_addr));
+  __asm__ __volatile__("stg 15, %0" : "=m"(sp_addr));
 #elif defined(__s390__) || defined(_ARCH_S390)
-  __asm__ __volatile__("st 15, %0" : "=g"(sp_addr));
+  __asm__ __volatile__("st 15, %0" : "=m"(sp_addr));
 #elif defined(__PPC64__) || defined(_ARCH_PPC64)
   __asm__ __volatile__("std 1, %0" : "=g"(sp_addr));
 #elif defined(__PPC__) || defined(_ARCH_PPC)
diff --git a/test/cctest/test-profile-generator.cc b/test/cctest/test-profile-generator.cc
index 48633f5..7e59839 100644
--- a/test/cctest/test-profile-generator.cc
+++ b/test/cctest/test-profile-generator.cc
@@ -51,17 +51,17 @@
   CcTest::InitializeVM();
   ProfileTree tree(CcTest::i_isolate());
   ProfileNode* node = tree.root();
-  CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
+  CodeEntry entry1(i::CodeEventListener::FUNCTION_TAG, "aaa");
   ProfileNode* childNode1 = node->FindOrAddChild(&entry1);
   CHECK(childNode1);
   CHECK_EQ(childNode1, node->FindOrAddChild(&entry1));
-  CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
+  CodeEntry entry2(i::CodeEventListener::FUNCTION_TAG, "bbb");
   ProfileNode* childNode2 = node->FindOrAddChild(&entry2);
   CHECK(childNode2);
   CHECK_NE(childNode1, childNode2);
   CHECK_EQ(childNode1, node->FindOrAddChild(&entry1));
   CHECK_EQ(childNode2, node->FindOrAddChild(&entry2));
-  CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
+  CodeEntry entry3(i::CodeEventListener::FUNCTION_TAG, "ccc");
   ProfileNode* childNode3 = node->FindOrAddChild(&entry3);
   CHECK(childNode3);
   CHECK_NE(childNode1, childNode3);
@@ -77,15 +77,15 @@
   const char* aaa = "aaa";
   ProfileTree tree(CcTest::i_isolate());
   ProfileNode* node = tree.root();
-  CodeEntry entry1(i::Logger::FUNCTION_TAG, aaa);
+  CodeEntry entry1(i::CodeEventListener::FUNCTION_TAG, aaa);
   ProfileNode* childNode1 = node->FindOrAddChild(&entry1);
   CHECK(childNode1);
   CHECK_EQ(childNode1, node->FindOrAddChild(&entry1));
   // The same function again.
-  CodeEntry entry2(i::Logger::FUNCTION_TAG, aaa);
+  CodeEntry entry2(i::CodeEventListener::FUNCTION_TAG, aaa);
   CHECK_EQ(childNode1, node->FindOrAddChild(&entry2));
   // Now with a different security token.
-  CodeEntry entry3(i::Logger::FUNCTION_TAG, aaa);
+  CodeEntry entry3(i::CodeEventListener::FUNCTION_TAG, aaa);
   CHECK_EQ(childNode1, node->FindOrAddChild(&entry3));
 }
 
@@ -122,9 +122,9 @@
 
 TEST(ProfileTreeAddPathFromEnd) {
   CcTest::InitializeVM();
-  CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
-  CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
-  CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
+  CodeEntry entry1(i::CodeEventListener::FUNCTION_TAG, "aaa");
+  CodeEntry entry2(i::CodeEventListener::FUNCTION_TAG, "bbb");
+  CodeEntry entry3(i::CodeEventListener::FUNCTION_TAG, "ccc");
   ProfileTree tree(CcTest::i_isolate());
   ProfileTreeTestHelper helper(&tree);
   CHECK(!helper.Walk(&entry1));
@@ -187,7 +187,7 @@
   empty_tree.root()->IncrementSelfTicks();
   CHECK_EQ(1u, empty_tree.root()->self_ticks());
 
-  CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
+  CodeEntry entry1(i::CodeEventListener::FUNCTION_TAG, "aaa");
   CodeEntry* e1_path[] = {&entry1};
   std::vector<CodeEntry*> e1_path_vec(e1_path, e1_path + arraysize(e1_path));
 
@@ -201,7 +201,7 @@
   CHECK_EQ(1u, single_child_tree.root()->self_ticks());
   CHECK_EQ(1u, node1->self_ticks());
 
-  CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
+  CodeEntry entry2(i::CodeEventListener::FUNCTION_TAG, "bbb");
   CodeEntry* e2_e1_path[] = {&entry2, &entry1};
   std::vector<CodeEntry*> e2_e1_path_vec(e2_e1_path,
                                          e2_e1_path + arraysize(e2_e1_path));
@@ -227,7 +227,7 @@
 
   CodeEntry* e2_path[] = {&entry2};
   std::vector<CodeEntry*> e2_path_vec(e2_path, e2_path + arraysize(e2_path));
-  CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
+  CodeEntry entry3(i::CodeEventListener::FUNCTION_TAG, "ccc");
   CodeEntry* e3_path[] = {&entry3};
   std::vector<CodeEntry*> e3_path_vec(e3_path, e3_path + arraysize(e3_path));
 
@@ -277,10 +277,10 @@
 
 TEST(CodeMapAddCode) {
   CodeMap code_map;
-  CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
-  CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
-  CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
-  CodeEntry entry4(i::Logger::FUNCTION_TAG, "ddd");
+  CodeEntry entry1(i::CodeEventListener::FUNCTION_TAG, "aaa");
+  CodeEntry entry2(i::CodeEventListener::FUNCTION_TAG, "bbb");
+  CodeEntry entry3(i::CodeEventListener::FUNCTION_TAG, "ccc");
+  CodeEntry entry4(i::CodeEventListener::FUNCTION_TAG, "ddd");
   code_map.AddCode(ToAddress(0x1500), &entry1, 0x200);
   code_map.AddCode(ToAddress(0x1700), &entry2, 0x100);
   code_map.AddCode(ToAddress(0x1900), &entry3, 0x50);
@@ -307,8 +307,8 @@
 
 TEST(CodeMapMoveAndDeleteCode) {
   CodeMap code_map;
-  CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
-  CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
+  CodeEntry entry1(i::CodeEventListener::FUNCTION_TAG, "aaa");
+  CodeEntry entry2(i::CodeEventListener::FUNCTION_TAG, "bbb");
   code_map.AddCode(ToAddress(0x1500), &entry1, 0x200);
   code_map.AddCode(ToAddress(0x1700), &entry2, 0x100);
   CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500)));
@@ -316,7 +316,7 @@
   code_map.MoveCode(ToAddress(0x1500), ToAddress(0x1700));  // Deprecate bbb.
   CHECK(!code_map.FindEntry(ToAddress(0x1500)));
   CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1700)));
-  CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
+  CodeEntry entry3(i::CodeEventListener::FUNCTION_TAG, "ccc");
   code_map.AddCode(ToAddress(0x1750), &entry3, 0x100);
   CHECK(!code_map.FindEntry(ToAddress(0x1700)));
   CHECK_EQ(&entry3, code_map.FindEntry(ToAddress(0x1750)));
@@ -344,12 +344,13 @@
 
 TEST(RecordTickSample) {
   TestSetup test_setup;
-  CpuProfilesCollection profiles(CcTest::heap());
+  CpuProfilesCollection profiles(CcTest::i_isolate());
+  profiles.set_cpu_profiler(CcTest::i_isolate()->cpu_profiler());
   profiles.StartProfiling("", false);
   ProfileGenerator generator(&profiles);
-  CodeEntry* entry1 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa");
-  CodeEntry* entry2 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "bbb");
-  CodeEntry* entry3 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "ccc");
+  CodeEntry* entry1 = new CodeEntry(i::Logger::FUNCTION_TAG, "aaa");
+  CodeEntry* entry2 = new CodeEntry(i::Logger::FUNCTION_TAG, "bbb");
+  CodeEntry* entry3 = new CodeEntry(i::Logger::FUNCTION_TAG, "ccc");
   generator.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200);
   generator.code_map()->AddCode(ToAddress(0x1700), entry2, 0x100);
   generator.code_map()->AddCode(ToAddress(0x1900), entry3, 0x50);
@@ -397,6 +398,10 @@
   ProfileNode* node4 = top_down_test_helper.Walk(entry1, entry3, entry1);
   CHECK(node4);
   CHECK_EQ(entry1, node4->entry());
+
+  delete entry1;
+  delete entry2;
+  delete entry3;
 }
 
 
@@ -410,12 +415,13 @@
 
 TEST(SampleIds) {
   TestSetup test_setup;
-  CpuProfilesCollection profiles(CcTest::heap());
+  CpuProfilesCollection profiles(CcTest::i_isolate());
+  profiles.set_cpu_profiler(CcTest::i_isolate()->cpu_profiler());
   profiles.StartProfiling("", true);
   ProfileGenerator generator(&profiles);
-  CodeEntry* entry1 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa");
-  CodeEntry* entry2 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "bbb");
-  CodeEntry* entry3 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "ccc");
+  CodeEntry* entry1 = new CodeEntry(i::Logger::FUNCTION_TAG, "aaa");
+  CodeEntry* entry2 = new CodeEntry(i::Logger::FUNCTION_TAG, "bbb");
+  CodeEntry* entry3 = new CodeEntry(i::Logger::FUNCTION_TAG, "ccc");
   generator.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200);
   generator.code_map()->AddCode(ToAddress(0x1700), entry2, 0x100);
   generator.code_map()->AddCode(ToAddress(0x1900), entry3, 0x50);
@@ -456,15 +462,20 @@
   for (int i = 0; i < 3; i++) {
     CHECK_EQ(expected_id[i], profile->sample(i)->id());
   }
+
+  delete entry1;
+  delete entry2;
+  delete entry3;
 }
 
 
 TEST(NoSamples) {
   TestSetup test_setup;
-  CpuProfilesCollection profiles(CcTest::heap());
+  CpuProfilesCollection profiles(CcTest::i_isolate());
+  profiles.set_cpu_profiler(CcTest::i_isolate()->cpu_profiler());
   profiles.StartProfiling("", false);
   ProfileGenerator generator(&profiles);
-  CodeEntry* entry1 = profiles.NewCodeEntry(i::Logger::FUNCTION_TAG, "aaa");
+  CodeEntry* entry1 = new CodeEntry(i::Logger::FUNCTION_TAG, "aaa");
   generator.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200);
 
   // We are building the following calls tree:
@@ -481,6 +492,8 @@
   CHECK_EQ(3u, nodeId - 1);
 
   CHECK_EQ(0, profile->samples_count());
+
+  delete entry1;
 }
 
 
@@ -544,7 +557,8 @@
 
 
 TEST(Issue51919) {
-  CpuProfilesCollection collection(CcTest::heap());
+  CpuProfilesCollection collection(CcTest::i_isolate());
+  collection.set_cpu_profiler(CcTest::i_isolate()->cpu_profiler());
   i::EmbeddedVector<char*,
       CpuProfilesCollection::kMaxSimultaneousProfiles> titles;
   for (int i = 0; i < CpuProfilesCollection::kMaxSimultaneousProfiles; ++i) {
@@ -618,16 +632,12 @@
   CHECK_EQ(script_a->GetUnboundScript()->GetId(), current->GetScriptId());
 }
 
-
-
-
 static const char* line_number_test_source_existing_functions =
 "function foo_at_the_first_line() {\n"
 "}\n"
 "foo_at_the_first_line();\n"
 "function lazy_func_at_forth_line() {}\n";
 
-
 static const char* line_number_test_source_profile_time_functions =
 "// Empty first line\n"
 "function bar_at_the_second_line() {\n"
@@ -652,7 +662,6 @@
   return func_entry->line_number();
 }
 
-
 TEST(LineNumber) {
   i::FLAG_use_inlining = false;
 
@@ -683,8 +692,6 @@
   profiler->StopProfiling("LineNumber");
 }
 
-
-
 TEST(BailoutReason) {
   v8::HandleScope scope(CcTest::isolate());
   v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
@@ -698,12 +705,7 @@
                         "  debugger;\n"
                         "  startProfiling();\n"
                         "}\n"
-                        "function TryFinally() {\n"
-                        "  try {\n"
-                        "    Debugger();\n"
-                        "  } finally { };\n"
-                        "}\n"
-                        "TryFinally();\n"
+                        "Debugger();\n"
                         "stopProfiling();"));
   script->Run(v8::Isolate::GetCurrent()->GetCurrentContext()).ToLocalChecked();
   CHECK_EQ(1, iprofiler->GetProfilesCount());
@@ -715,15 +717,10 @@
   // The tree should look like this:
   //  (root)
   //   ""
-  //     kTryFinallyStatement
-  //       kDebuggerStatement
+  //     kDebuggerStatement
   current = PickChild(current, "");
   CHECK(const_cast<v8::CpuProfileNode*>(current));
 
-  current = PickChild(current, "TryFinally");
-  CHECK(const_cast<v8::CpuProfileNode*>(current));
-  CHECK(!strcmp("TryFinallyStatement", current->GetBailoutReason()));
-
   current = PickChild(current, "Debugger");
   CHECK(const_cast<v8::CpuProfileNode*>(current));
   CHECK(!strcmp("DebuggerStatement", current->GetBailoutReason()));
diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc
index 0a153b7..071ab18 100644
--- a/test/cctest/test-regexp.cc
+++ b/test/cctest/test-regexp.cc
@@ -171,7 +171,6 @@
 
 void TestRegExpParser(bool lookbehind) {
   FLAG_harmony_regexp_lookbehind = lookbehind;
-  FLAG_harmony_unicode_regexps = true;
 
   CHECK_PARSE_ERROR("?");
 
@@ -438,6 +437,23 @@
   CHECK_MIN_MAX("a(?=b)c", 2, 2);
   CHECK_MIN_MAX("a(?=bbb|bb)c", 2, 2);
   CHECK_MIN_MAX("a(?!bbb|bb)c", 2, 2);
+
+  FLAG_harmony_regexp_named_captures = true;
+  CheckParseEq("(?<a>x)(?<b>x)(?<c>x)\\k<a>",
+               "(: (^ 'x') (^ 'x') (^ 'x') (<- 1))", true);
+  CheckParseEq("(?<a>x)(?<b>x)(?<c>x)\\k<b>",
+               "(: (^ 'x') (^ 'x') (^ 'x') (<- 2))", true);
+  CheckParseEq("(?<a>x)(?<b>x)(?<c>x)\\k<c>",
+               "(: (^ 'x') (^ 'x') (^ 'x') (<- 3))", true);
+  CheckParseEq("(?<a>a)\\k<a>", "(: (^ 'a') (<- 1))", true);
+  CheckParseEq("(?<a>a\\k<a>)", "(^ 'a')", true);
+  CheckParseEq("(?<a>\\k<a>a)", "(^ 'a')", true);
+  CheckParseEq("(?<a>\\k<b>)(?<b>\\k<a>)", "(: (^ (<- 2)) (^ (<- 1)))", true);
+  CheckParseEq("\\k<a>(?<a>a)", "(: (<- 1) (^ 'a'))", true);
+
+  CheckParseEq("(?<\\u{03C0}>a)", "(^ 'a')", true);
+  CheckParseEq("(?<\\u03C0>a)", "(^ 'a')", true);
+  FLAG_harmony_regexp_named_captures = false;
 }
 
 
@@ -450,7 +466,6 @@
   TestRegExpParser(true);  // Lookbehind enabled.
 }
 
-
 TEST(ParserRegression) {
   CheckParseEq("[A-Z$-][x]", "(! [A-Z $ -] [x])");
   CheckParseEq("a{3,4*}", "(: 'a{3,' (# 0 - g '4') '}')");
@@ -458,14 +473,16 @@
   CheckParseEq("a|", "(| 'a' %)");
 }
 
-static void ExpectError(const char* input,
-                        const char* expected) {
+static void ExpectError(const char* input, const char* expected,
+                        bool unicode = false) {
   v8::HandleScope scope(CcTest::isolate());
   Zone zone(CcTest::i_isolate()->allocator());
   FlatStringReader reader(CcTest::i_isolate(), CStrVector(input));
   RegExpCompileData result;
-  CHECK(!v8::internal::RegExpParser::ParseRegExp(
-      CcTest::i_isolate(), &zone, &reader, JSRegExp::kNone, &result));
+  JSRegExp::Flags flags = JSRegExp::kNone;
+  if (unicode) flags |= JSRegExp::kUnicode;
+  CHECK(!v8::internal::RegExpParser::ParseRegExp(CcTest::i_isolate(), &zone,
+                                                 &reader, flags, &result));
   CHECK(result.tree == NULL);
   CHECK(!result.error.is_null());
   v8::base::SmartArrayPointer<char> str = result.error->ToCString(ALLOW_NULLS);
@@ -499,6 +516,23 @@
     os << "()";
   }
   ExpectError(os.str().c_str(), kTooManyCaptures);
+
+  FLAG_harmony_regexp_named_captures = true;
+  const char* kInvalidCaptureName = "Invalid capture group name";
+  ExpectError("(?<>.)", kInvalidCaptureName, true);
+  ExpectError("(?<1>.)", kInvalidCaptureName, true);
+  ExpectError("(?<_%>.)", kInvalidCaptureName, true);
+  ExpectError("\\k<a", kInvalidCaptureName, true);
+  const char* kDuplicateCaptureName = "Duplicate capture group name";
+  ExpectError("(?<a>.)(?<a>.)", kDuplicateCaptureName, true);
+  const char* kInvalidUnicodeEscape = "Invalid Unicode escape sequence";
+  ExpectError("(?<\\u{FISK}", kInvalidUnicodeEscape, true);
+  const char* kInvalidCaptureReferenced = "Invalid named capture referenced";
+  ExpectError("\\k<a>", kInvalidCaptureReferenced, true);
+  ExpectError("(?<b>)\\k<a>", kInvalidCaptureReferenced, true);
+  const char* kInvalidNamedReference = "Invalid named reference";
+  ExpectError("\\ka", kInvalidNamedReference, true);
+  FLAG_harmony_regexp_named_captures = false;
 }
 
 
diff --git a/test/cctest/test-reloc-info.cc b/test/cctest/test-reloc-info.cc
index 4346f00..52b5ab8 100644
--- a/test/cctest/test-reloc-info.cc
+++ b/test/cctest/test-reloc-info.cc
@@ -57,9 +57,9 @@
     RelocInfo::Mode mode = (i % 2 == 0) ?
         RelocInfo::STATEMENT_POSITION : RelocInfo::POSITION;
     if (mode == RelocInfo::STATEMENT_POSITION) {
-      printf("TEST WRITING STATEMENT %p %d\n", pc, pos);
+      printf("TEST WRITING STATEMENT %p %d\n", static_cast<void*>(pc), pos);
     } else {
-      printf("TEST WRITING POSITION %p %d\n", pc, pos);
+      printf("TEST WRITING POSITION %p %d\n", static_cast<void*>(pc), pos);
     }
     WriteRinfo(&writer, pc, mode, pos);
     CHECK(writer.pos() - RelocInfoWriter::kMaxSize >= relocation_info_end);
@@ -68,8 +68,9 @@
   writer.Finish();
   relocation_info_size = static_cast<int>(buffer_end - writer.pos());
   MacroAssembler assm(CcTest::i_isolate(), nullptr, 0, CodeObjectRequired::kNo);
-  CodeDesc desc = {buffer.get(),         buffer_size, code_size,
-                   relocation_info_size, 0,           &assm};
+  CodeDesc desc = {
+      buffer.get(), buffer_size, code_size, relocation_info_size, 0,
+      nullptr,      0,           &assm};
 
   // Read only (non-statement) positions.
   {
diff --git a/test/cctest/test-run-wasm-relocation-arm.cc b/test/cctest/test-run-wasm-relocation-arm.cc
index adfeb28..b2e6ec3 100644
--- a/test/cctest/test-run-wasm-relocation-arm.cc
+++ b/test/cctest/test-run-wasm-relocation-arm.cc
@@ -23,8 +23,7 @@
 
 static int32_t DummyStaticFunction(Object* result) { return 1; }
 
-TEST(WasmRelocationArm) {
-  CcTest::InitializeVM();
+TEST(WasmRelocationArmMemoryReference) {
   Isolate* isolate = CcTest::i_isolate();
   HandleScope scope(isolate);
   v8::internal::byte buffer[4096];
@@ -77,4 +76,59 @@
 #endif
 }
 
+TEST(WasmRelocationArmMemorySizeReference) {
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  HandleScope scope(isolate);
+  v8::internal::byte buffer[4096];
+  DummyStaticFunction(NULL);
+  int32_t size = 512;
+  Label fail;
+
+  Assembler assm(isolate, buffer, sizeof buffer);
+
+  __ mov(r0, Operand(size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
+  __ cmp(r0, Operand(size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
+  __ b(ne, &fail);
+  __ mov(pc, Operand(lr));
+  __ bind(&fail);
+  __ mov(r0, Operand(0xdeadbeef));
+  __ mov(pc, Operand(lr));
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Handle<Code> code = isolate->factory()->NewCode(
+      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+
+  CSignature0<int32_t> csig;
+  CodeRunner<int32_t> runnable(isolate, code, &csig);
+  int32_t ret_value = runnable.Call();
+  CHECK_NE(ret_value, 0xdeadbeef);
+
+#ifdef DEBUG
+  OFStream os(stdout);
+  code->Print(os);
+  ::printf("f() = %d\n\n", ret_value);
+#endif
+  size_t diff = 512;
+
+  int mode_mask = (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
+  for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
+    RelocInfo::Mode mode = it.rinfo()->rmode();
+    if (RelocInfo::IsWasmMemorySizeReference(mode)) {
+      it.rinfo()->update_wasm_memory_reference(
+          reinterpret_cast<Address>(1234), reinterpret_cast<Address>(1234),
+          it.rinfo()->wasm_memory_size_reference(),
+          it.rinfo()->wasm_memory_size_reference() + diff, SKIP_ICACHE_FLUSH);
+    }
+  }
+
+  ret_value = runnable.Call();
+  CHECK_NE(ret_value, 0xdeadbeef);
+
+#ifdef DEBUG
+  code->Print(os);
+  ::printf("f() = %d\n\n", ret_value);
+#endif
+}
 #undef __
diff --git a/test/cctest/test-run-wasm-relocation-arm64.cc b/test/cctest/test-run-wasm-relocation-arm64.cc
index 48f9e85..3b49f00 100644
--- a/test/cctest/test-run-wasm-relocation-arm64.cc
+++ b/test/cctest/test-run-wasm-relocation-arm64.cc
@@ -24,8 +24,7 @@
 
 static int64_t DummyStaticFunction(Object* result) { return 1; }
 
-TEST(WasmRelocationArm64) {
-  CcTest::InitializeVM();
+TEST(WasmRelocationArm64MemoryReference) {
   Isolate* isolate = CcTest::i_isolate();
   HandleScope scope(isolate);
   v8::internal::byte buffer[4096];
@@ -51,7 +50,7 @@
 #ifdef DEBUG
   OFStream os(stdout);
   code->Print(os);
-  ::printf("f() = %ld\n\n", ret_value);
+  ::printf("f() = %" PRIx64 "\n\n", ret_value);
 #endif
   size_t offset = 1234;
 
@@ -75,7 +74,64 @@
 
 #ifdef DEBUG
   code->Print(os);
-  ::printf("f() = %ld\n\n", ret_value);
+  ::printf("f() = %" PRIx64 "\n\n", ret_value);
+#endif
+}
+
+TEST(WasmRelocationArm64MemorySizeReference) {
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  HandleScope scope(isolate);
+  v8::internal::byte buffer[4096];
+  DummyStaticFunction(NULL);
+  Immediate size = Immediate(512, RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
+  Label fail;
+
+  MacroAssembler masm(isolate, buffer, sizeof buffer,
+                      v8::internal::CodeObjectRequired::kYes);
+
+  __ Mov(x0, size);
+  __ Cmp(x0, size);
+  __ B(ne, &fail);
+  __ Ret();
+  __ Bind(&fail);
+  __ Mov(x0, Immediate(0xdeadbeef));
+  __ Ret();
+
+  CodeDesc desc;
+  masm.GetCode(&desc);
+  Handle<Code> code = isolate->factory()->NewCode(
+      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+
+  CSignature0<int64_t> csig;
+  CodeRunner<int64_t> runnable(isolate, code, &csig);
+  int64_t ret_value = runnable.Call();
+  CHECK_NE(ret_value, 0xdeadbeef);
+
+#ifdef DEBUG
+  OFStream os(stdout);
+  code->Print(os);
+  ::printf("f() = %" PRIx64 "\n\n", ret_value);
+#endif
+  int32_t diff = 512;
+
+  int mode_mask = (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
+  for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
+    RelocInfo::Mode mode = it.rinfo()->rmode();
+    if (RelocInfo::IsWasmMemorySizeReference(mode)) {
+      it.rinfo()->update_wasm_memory_reference(
+          reinterpret_cast<Address>(0x1234), reinterpret_cast<Address>(0x1234),
+          it.rinfo()->wasm_memory_size_reference(),
+          it.rinfo()->wasm_memory_size_reference() + diff, SKIP_ICACHE_FLUSH);
+    }
+  }
+
+  ret_value = runnable.Call();
+  CHECK_NE(ret_value, 0xdeadbeef);
+
+#ifdef DEBUG
+  code->Print(os);
+  ::printf("f() = %" PRIx64 "\n\n", ret_value);
 #endif
 }
 
diff --git a/test/cctest/test-run-wasm-relocation-ia32.cc b/test/cctest/test-run-wasm-relocation-ia32.cc
index 135b522..305d008 100644
--- a/test/cctest/test-run-wasm-relocation-ia32.cc
+++ b/test/cctest/test-run-wasm-relocation-ia32.cc
@@ -23,8 +23,7 @@
 
 static int32_t DummyStaticFunction(Object* result) { return 1; }
 
-TEST(WasmRelocationIa32) {
-  CcTest::InitializeVM();
+TEST(WasmRelocationIa32MemoryReference) {
   Isolate* isolate = CcTest::i_isolate();
   Zone zone(isolate->allocator());
   HandleScope scope(isolate);
@@ -78,7 +77,6 @@
   CHECK_EQ(ret_value, imm + offset);
 
 #ifdef OBJECT_PRINT
-  // OFStream os(stdout);
   code->Print(os);
   begin = code->instruction_start();
   end = begin + code->instruction_size();
@@ -86,4 +84,67 @@
 #endif
 }
 
+TEST(WasmRelocationIa32MemorySizeReference) {
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  Zone zone(isolate->allocator());
+  HandleScope scope(isolate);
+  v8::internal::byte buffer[4096];
+  Assembler assm(isolate, buffer, sizeof buffer);
+  DummyStaticFunction(NULL);
+  int32_t size = 80;
+  Label fail;
+
+  __ mov(eax, Immediate(reinterpret_cast<Address>(size),
+                        RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
+  __ cmp(eax, Immediate(reinterpret_cast<Address>(size),
+                        RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
+  __ j(not_equal, &fail);
+  __ ret(0);
+  __ bind(&fail);
+  __ mov(eax, 0xdeadbeef);
+  __ ret(0);
+
+  CSignature0<int32_t> csig;
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Handle<Code> code = isolate->factory()->NewCode(
+      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+  USE(code);
+
+  CodeRunner<int32_t> runnable(isolate, code, &csig);
+  int32_t ret_value = runnable.Call();
+  CHECK_NE(ret_value, 0xdeadbeef);
+
+#ifdef OBJECT_PRINT
+  OFStream os(stdout);
+  code->Print(os);
+  byte* begin = code->instruction_start();
+  byte* end = begin + code->instruction_size();
+  disasm::Disassembler::Disassemble(stdout, begin, end);
+#endif
+
+  size_t offset = 10;
+
+  int mode_mask = (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
+  for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
+    RelocInfo::Mode mode = it.rinfo()->rmode();
+    if (RelocInfo::IsWasmMemorySizeReference(mode)) {
+      it.rinfo()->update_wasm_memory_reference(
+          reinterpret_cast<Address>(1234), reinterpret_cast<Address>(1234),
+          it.rinfo()->wasm_memory_size_reference(),
+          it.rinfo()->wasm_memory_size_reference() + offset, SKIP_ICACHE_FLUSH);
+    }
+  }
+
+  ret_value = runnable.Call();
+  CHECK_NE(ret_value, 0xdeadbeef);
+
+#ifdef OBJECT_PRINT
+  code->Print(os);
+  begin = code->instruction_start();
+  end = begin + code->instruction_size();
+  disasm::Disassembler::Disassemble(stdout, begin, end);
+#endif
+}
 #undef __
diff --git a/test/cctest/test-run-wasm-relocation-x64.cc b/test/cctest/test-run-wasm-relocation-x64.cc
index f1b6d96..11fa451 100644
--- a/test/cctest/test-run-wasm-relocation-x64.cc
+++ b/test/cctest/test-run-wasm-relocation-x64.cc
@@ -21,8 +21,8 @@
 #define __ assm.
 
 static int32_t DummyStaticFunction(Object* result) { return 1; }
-TEST(WasmRelocationX64movq64) {
-  CcTest::InitializeVM();
+
+TEST(WasmRelocationX64MemoryReference) {
   Isolate* isolate = CcTest::i_isolate();
   HandleScope scope(isolate);
   v8::internal::byte buffer[4096];
@@ -80,4 +80,63 @@
 #endif
 }
 
+TEST(WasmRelocationX64WasmMemorySizeReference) {
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  HandleScope scope(isolate);
+  v8::internal::byte buffer[4096];
+  Assembler assm(isolate, buffer, sizeof buffer);
+  DummyStaticFunction(NULL);
+  int32_t size = 512;
+  Label fail;
+
+  __ movl(rax, Immediate(size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
+  __ cmpl(rax, Immediate(size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
+  __ j(not_equal, &fail);
+  __ ret(0);
+  __ bind(&fail);
+  __ movl(rax, Immediate(0xdeadbeef));
+  __ ret(0);
+
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Handle<Code> code = isolate->factory()->NewCode(
+      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+  USE(code);
+
+  CSignature0<int64_t> csig;
+  CodeRunner<int64_t> runnable(isolate, code, &csig);
+  int64_t ret_value = runnable.Call();
+  CHECK_NE(ret_value, 0xdeadbeef);
+
+#ifdef OBJECT_PRINT
+  OFStream os(stdout);
+  code->Print(os);
+  byte* begin = code->instruction_start();
+  byte* end = begin + code->instruction_size();
+  disasm::Disassembler::Disassemble(stdout, begin, end);
+#endif
+  int32_t diff = 512;
+
+  int mode_mask = (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
+  for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
+    RelocInfo::Mode mode = it.rinfo()->rmode();
+    if (RelocInfo::IsWasmMemorySizeReference(mode)) {
+      it.rinfo()->update_wasm_memory_reference(
+          reinterpret_cast<Address>(1234), reinterpret_cast<Address>(1234),
+          it.rinfo()->wasm_memory_size_reference(),
+          it.rinfo()->wasm_memory_size_reference() + diff, SKIP_ICACHE_FLUSH);
+    }
+  }
+
+  ret_value = runnable.Call();
+  CHECK_NE(ret_value, 0xdeadbeef);
+
+#ifdef OBJECT_PRINT
+  code->Print(os);
+  begin = code->instruction_start();
+  end = begin + code->instruction_size();
+  disasm::Disassembler::Disassemble(stdout, begin, end);
+#endif
+}
 #undef __
diff --git a/test/cctest/test-run-wasm-relocation-x87.cc b/test/cctest/test-run-wasm-relocation-x87.cc
index 6cbd065..2156e96 100644
--- a/test/cctest/test-run-wasm-relocation-x87.cc
+++ b/test/cctest/test-run-wasm-relocation-x87.cc
@@ -23,8 +23,7 @@
 
 static int32_t DummyStaticFunction(Object* result) { return 1; }
 
-TEST(WasmRelocationIa32) {
-  CcTest::InitializeVM();
+TEST(WasmRelocationX87MemoryReference) {
   Isolate* isolate = CcTest::i_isolate();
   Zone zone(isolate->allocator());
   HandleScope scope(isolate);
@@ -78,7 +77,6 @@
   CHECK_EQ(ret_value, imm + offset);
 
 #ifdef OBJECT_PRINT
-  // OFStream os(stdout);
   code->Print(os);
   begin = code->instruction_start();
   end = begin + code->instruction_size();
@@ -86,4 +84,67 @@
 #endif
 }
 
+TEST(WasmRelocationX87MemorySizeReference) {
+  CcTest::InitializeVM();
+  Isolate* isolate = CcTest::i_isolate();
+  Zone zone(isolate->allocator());
+  HandleScope scope(isolate);
+  v8::internal::byte buffer[4096];
+  Assembler assm(isolate, buffer, sizeof buffer);
+  DummyStaticFunction(NULL);
+  int32_t size = 80;
+  Label fail;
+
+  __ mov(eax, Immediate(reinterpret_cast<Address>(size),
+                        RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
+  __ cmp(eax, Immediate(reinterpret_cast<Address>(size),
+                        RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
+  __ j(not_equal, &fail);
+  __ ret(0);
+  __ bind(&fail);
+  __ mov(eax, 0xdeadbeef);
+  __ ret(0);
+
+  CSignature0<int32_t> csig;
+  CodeDesc desc;
+  assm.GetCode(&desc);
+  Handle<Code> code = isolate->factory()->NewCode(
+      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+  USE(code);
+
+  CodeRunner<int32_t> runnable(isolate, code, &csig);
+  int32_t ret_value = runnable.Call();
+  CHECK_NE(ret_value, 0xdeadbeef);
+
+#ifdef OBJECT_PRINT
+  OFStream os(stdout);
+  code->Print(os);
+  byte* begin = code->instruction_start();
+  byte* end = begin + code->instruction_size();
+  disasm::Disassembler::Disassemble(stdout, begin, end);
+#endif
+
+  size_t offset = 10;
+
+  int mode_mask = (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
+  for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
+    RelocInfo::Mode mode = it.rinfo()->rmode();
+    if (RelocInfo::IsWasmMemorySizeReference(mode)) {
+      it.rinfo()->update_wasm_memory_reference(
+          reinterpret_cast<Address>(1234), reinterpret_cast<Address>(1234),
+          it.rinfo()->wasm_memory_size_reference(),
+          it.rinfo()->wasm_memory_size_reference() + offset, SKIP_ICACHE_FLUSH);
+    }
+  }
+
+  ret_value = runnable.Call();
+  CHECK_NE(ret_value, 0xdeadbeef);
+
+#ifdef OBJECT_PRINT
+  code->Print(os);
+  begin = code->instruction_start();
+  end = begin + code->instruction_size();
+  disasm::Disassembler::Disassemble(stdout, begin, end);
+#endif
+}
 #undef __
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index cd349f9..de36877 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -36,6 +36,7 @@
 #include "src/compilation-cache.h"
 #include "src/debug/debug.h"
 #include "src/heap/spaces.h"
+#include "src/macro-assembler.h"
 #include "src/objects.h"
 #include "src/parsing/parser.h"
 #include "src/runtime/runtime.h"
@@ -46,7 +47,7 @@
 #include "src/snapshot/snapshot.h"
 #include "src/snapshot/startup-serializer.h"
 #include "test/cctest/cctest.h"
-#include "test/cctest/heap/utils-inl.h"
+#include "test/cctest/heap/heap-utils.h"
 
 using namespace v8::internal;
 
@@ -91,11 +92,11 @@
 
   Isolate* internal_isolate = reinterpret_cast<Isolate*>(isolate);
   internal_isolate->heap()->CollectAllAvailableGarbage("serialize");
-  SnapshotByteSink sink;
-  StartupSerializer ser(internal_isolate, &sink);
+  StartupSerializer ser(internal_isolate,
+                        v8::SnapshotCreator::FunctionCodeHandling::kClear);
   ser.SerializeStrongReferences();
   ser.SerializeWeakReferencesAndDeferred();
-  SnapshotData snapshot_data(ser);
+  SnapshotData snapshot_data(&ser);
   return WritePayload(snapshot_data.RawData());
 }
 
@@ -280,19 +281,17 @@
     }
     env.Reset();
 
-    SnapshotByteSink startup_sink;
-    StartupSerializer startup_serializer(isolate, &startup_sink);
+    StartupSerializer startup_serializer(
+        isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear);
     startup_serializer.SerializeStrongReferences();
 
-    SnapshotByteSink partial_sink;
-    PartialSerializer partial_serializer(isolate, &startup_serializer,
-                                         &partial_sink);
+    PartialSerializer partial_serializer(isolate, &startup_serializer);
     partial_serializer.Serialize(&raw_foo);
 
     startup_serializer.SerializeWeakReferencesAndDeferred();
 
-    SnapshotData startup_snapshot(startup_serializer);
-    SnapshotData partial_snapshot(partial_serializer);
+    SnapshotData startup_snapshot(&startup_serializer);
+    SnapshotData partial_snapshot(&partial_serializer);
 
     *partial_blob_out = WritePayload(partial_snapshot.RawData());
     *startup_blob_out = WritePayload(startup_snapshot.RawData());
@@ -380,17 +379,17 @@
     env.Reset();
 
     SnapshotByteSink startup_sink;
-    StartupSerializer startup_serializer(isolate, &startup_sink);
+    StartupSerializer startup_serializer(
+        isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear);
     startup_serializer.SerializeStrongReferences();
 
     SnapshotByteSink partial_sink;
-    PartialSerializer partial_serializer(isolate, &startup_serializer,
-                                         &partial_sink);
+    PartialSerializer partial_serializer(isolate, &startup_serializer);
     partial_serializer.Serialize(&raw_context);
     startup_serializer.SerializeWeakReferencesAndDeferred();
 
-    SnapshotData startup_snapshot(startup_serializer);
-    SnapshotData partial_snapshot(partial_serializer);
+    SnapshotData startup_snapshot(&startup_serializer);
+    SnapshotData partial_snapshot(&partial_serializer);
 
     *partial_blob_out = WritePayload(partial_snapshot.RawData());
     *startup_blob_out = WritePayload(startup_snapshot.RawData());
@@ -498,17 +497,17 @@
     env.Reset();
 
     SnapshotByteSink startup_sink;
-    StartupSerializer startup_serializer(isolate, &startup_sink);
+    StartupSerializer startup_serializer(
+        isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear);
     startup_serializer.SerializeStrongReferences();
 
     SnapshotByteSink partial_sink;
-    PartialSerializer partial_serializer(isolate, &startup_serializer,
-                                         &partial_sink);
+    PartialSerializer partial_serializer(isolate, &startup_serializer);
     partial_serializer.Serialize(&raw_context);
     startup_serializer.SerializeWeakReferencesAndDeferred();
 
-    SnapshotData startup_snapshot(startup_serializer);
-    SnapshotData partial_snapshot(partial_serializer);
+    SnapshotData startup_snapshot(&startup_serializer);
+    SnapshotData partial_snapshot(&partial_serializer);
 
     *partial_blob_out = WritePayload(partial_snapshot.RawData());
     *startup_blob_out = WritePayload(startup_snapshot.RawData());
@@ -792,7 +791,7 @@
 
 TEST(SnapshotDataBlobWithWarmup) {
   DisableTurbofan();
-  const char* warmup = "Math.tan(1); Math.sin = 1;";
+  const char* warmup = "Math.tanh(1); Math.sinh = 1;";
 
   v8::StartupData cold = v8::V8::CreateSnapshotDataBlob();
   v8::StartupData warm = v8::V8::WarmUpSnapshotDataBlob(cold, warmup);
@@ -811,9 +810,9 @@
     v8::Context::Scope c_scope(context);
     // Running the warmup script has effect on whether functions are
     // pre-compiled, but does not pollute the context.
-    CHECK(IsCompiled("Math.tan"));
-    CHECK(!IsCompiled("Math.cos"));
-    CHECK(CompileRun("Math.sin")->IsFunction());
+    CHECK(IsCompiled("Math.tanh"));
+    CHECK(!IsCompiled("Math.cosh"));
+    CHECK(CompileRun("Math.sinh")->IsFunction());
   }
   isolate->Dispose();
 }
@@ -821,9 +820,9 @@
 TEST(CustomSnapshotDataBlobWithWarmup) {
   DisableTurbofan();
   const char* source =
-      "function f() { return Math.sin(1); }\n"
-      "function g() { return Math.cos(1); }\n"
-      "Math.tan(1);"
+      "function f() { return Math.sinh(1); }\n"
+      "function g() { return Math.cosh(1); }\n"
+      "Math.tanh(1);"
       "var a = 5";
   const char* warmup = "a = f()";
 
@@ -845,10 +844,10 @@
     // Running the warmup script has effect on whether functions are
     // pre-compiled, but does not pollute the context.
     CHECK(IsCompiled("f"));
-    CHECK(IsCompiled("Math.sin"));
+    CHECK(IsCompiled("Math.sinh"));
     CHECK(!IsCompiled("g"));
-    CHECK(!IsCompiled("Math.cos"));
-    CHECK(!IsCompiled("Math.tan"));
+    CHECK(!IsCompiled("Math.cosh"));
+    CHECK(!IsCompiled("Math.tanh"));
     CHECK_EQ(5, CompileRun("a")->Int32Value(context).FromJust());
   }
   isolate->Dispose();
@@ -1827,12 +1826,302 @@
       false);
   delete script_data;
 
-  SimulateIncrementalMarking(isolate->heap());
+  heap::SimulateIncrementalMarking(isolate->heap());
 
   script_data = CodeSerializer::Serialize(isolate, shared, source);
   delete script_data;
 }
 
+#if V8_TARGET_ARCH_X64
+TEST(CodeSerializerCell) {
+  FLAG_serialize_toplevel = true;
+  LocalContext context;
+  Isolate* isolate = CcTest::i_isolate();
+  isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
+
+  v8::HandleScope scope(CcTest::isolate());
+
+  size_t actual_size;
+  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
+      Assembler::kMinimalBufferSize, &actual_size, true));
+  CHECK(buffer);
+  HandleScope handles(isolate);
+
+  MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
+                           v8::internal::CodeObjectRequired::kYes);
+  assembler.enable_serializer();
+  Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(0.3);
+  CHECK(isolate->heap()->InNewSpace(*number));
+  MacroAssembler* masm = &assembler;
+  masm->MoveHeapObject(rax, number);
+  masm->ret(0);
+  CodeDesc desc;
+  masm->GetCode(&desc);
+  Handle<Code> code = isolate->factory()->NewCode(
+      desc, Code::ComputeFlags(Code::FUNCTION), masm->CodeObject());
+  code->set_has_reloc_info_for_serialization(true);
+
+  RelocIterator rit1(*code, 1 << RelocInfo::CELL);
+  CHECK_EQ(*number, rit1.rinfo()->target_cell()->value());
+
+  Handle<String> source = isolate->factory()->empty_string();
+  Handle<SharedFunctionInfo> sfi =
+      isolate->factory()->NewSharedFunctionInfo(source, code, false);
+  ScriptData* script_data = CodeSerializer::Serialize(isolate, sfi, source);
+
+  Handle<SharedFunctionInfo> copy =
+      CodeSerializer::Deserialize(isolate, script_data, source)
+          .ToHandleChecked();
+  RelocIterator rit2(copy->code(), 1 << RelocInfo::CELL);
+  CHECK(rit2.rinfo()->target_cell()->IsCell());
+  Handle<Cell> cell(rit2.rinfo()->target_cell());
+  CHECK(cell->value()->IsHeapNumber());
+  CHECK_EQ(0.3, HeapNumber::cast(cell->value())->value());
+
+  delete script_data;
+}
+#endif  // V8_TARGET_ARCH_X64
+
+TEST(SnapshotCreatorMultipleContexts) {
+  DisableTurbofan();
+  v8::StartupData blob;
+  {
+    v8::SnapshotCreator creator;
+    v8::Isolate* isolate = creator.GetIsolate();
+    {
+      v8::HandleScope handle_scope(isolate);
+      v8::Local<v8::Context> context = v8::Context::New(isolate);
+      v8::Context::Scope context_scope(context);
+      CompileRun("var f = function() { return 1; }");
+      CHECK_EQ(0, creator.AddContext(context));
+    }
+    {
+      v8::HandleScope handle_scope(isolate);
+      v8::Local<v8::Context> context = v8::Context::New(isolate);
+      v8::Context::Scope context_scope(context);
+      CompileRun("var f = function() { return 2; }");
+      CHECK_EQ(1, creator.AddContext(context));
+    }
+    {
+      v8::HandleScope handle_scope(isolate);
+      v8::Local<v8::Context> context = v8::Context::New(isolate);
+      CHECK_EQ(2, creator.AddContext(context));
+    }
+    blob =
+        creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
+  }
+
+  v8::Isolate::CreateParams params;
+  params.snapshot_blob = &blob;
+  params.array_buffer_allocator = CcTest::array_buffer_allocator();
+  v8::Isolate* isolate = v8::Isolate::New(params);
+  {
+    v8::Isolate::Scope isolate_scope(isolate);
+    v8::ExtensionConfiguration* no_extension = nullptr;
+    v8::Local<v8::ObjectTemplate> no_template = v8::Local<v8::ObjectTemplate>();
+    v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
+    {
+      v8::HandleScope handle_scope(isolate);
+      v8::Local<v8::Context> context =
+          v8::Context::New(isolate, no_extension, no_template, no_object, 0);
+      v8::Context::Scope context_scope(context);
+      ExpectInt32("f()", 1);
+    }
+    {
+      v8::HandleScope handle_scope(isolate);
+      v8::Local<v8::Context> context =
+          v8::Context::New(isolate, no_extension, no_template, no_object, 1);
+      v8::Context::Scope context_scope(context);
+      ExpectInt32("f()", 2);
+    }
+    {
+      v8::HandleScope handle_scope(isolate);
+      v8::Local<v8::Context> context =
+          v8::Context::New(isolate, no_extension, no_template, no_object, 2);
+      v8::Context::Scope context_scope(context);
+      ExpectUndefined("this.f");
+    }
+  }
+
+  isolate->Dispose();
+  delete[] blob.data;
+}
+
+static void SerializedCallback(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  args.GetReturnValue().Set(v8_num(42));
+}
+
+static void SerializedCallbackReplacement(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  args.GetReturnValue().Set(v8_num(1337));
+}
+
+intptr_t original_external_references[] = {
+    reinterpret_cast<intptr_t>(SerializedCallback), 0};
+
+intptr_t replaced_external_references[] = {
+    reinterpret_cast<intptr_t>(SerializedCallbackReplacement), 0};
+
+TEST(SnapshotCreatorExternalReferences) {
+  DisableTurbofan();
+  v8::StartupData blob;
+  {
+    v8::SnapshotCreator creator(original_external_references);
+    v8::Isolate* isolate = creator.GetIsolate();
+    {
+      v8::HandleScope handle_scope(isolate);
+      v8::Local<v8::Context> context = v8::Context::New(isolate);
+      v8::Context::Scope context_scope(context);
+      v8::Local<v8::FunctionTemplate> callback =
+          v8::FunctionTemplate::New(isolate, SerializedCallback);
+      v8::Local<v8::Value> function =
+          callback->GetFunction(context).ToLocalChecked();
+      CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust());
+      ExpectInt32("f()", 42);
+      CHECK_EQ(0, creator.AddContext(context));
+    }
+    blob =
+        creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
+  }
+
+  // Deserialize with the original external reference.
+  {
+    v8::Isolate::CreateParams params;
+    params.snapshot_blob = &blob;
+    params.array_buffer_allocator = CcTest::array_buffer_allocator();
+    params.external_references = original_external_references;
+    v8::Isolate* isolate = v8::Isolate::New(params);
+    {
+      v8::Isolate::Scope isolate_scope(isolate);
+      v8::HandleScope handle_scope(isolate);
+      v8::ExtensionConfiguration* no_extension = nullptr;
+      v8::Local<v8::ObjectTemplate> no_template =
+          v8::Local<v8::ObjectTemplate>();
+      v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
+      v8::Local<v8::Context> context =
+          v8::Context::New(isolate, no_extension, no_template, no_object, 0);
+      v8::Context::Scope context_scope(context);
+      ExpectInt32("f()", 42);
+    }
+    isolate->Dispose();
+  }
+
+  // Deserialize with the some other external reference.
+  {
+    v8::Isolate::CreateParams params;
+    params.snapshot_blob = &blob;
+    params.array_buffer_allocator = CcTest::array_buffer_allocator();
+    params.external_references = replaced_external_references;
+    v8::Isolate* isolate = v8::Isolate::New(params);
+    {
+      v8::Isolate::Scope isolate_scope(isolate);
+      v8::HandleScope handle_scope(isolate);
+      v8::ExtensionConfiguration* no_extension = nullptr;
+      v8::Local<v8::ObjectTemplate> no_template =
+          v8::Local<v8::ObjectTemplate>();
+      v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
+      v8::Local<v8::Context> context =
+          v8::Context::New(isolate, no_extension, no_template, no_object, 0);
+      v8::Context::Scope context_scope(context);
+      ExpectInt32("f()", 1337);
+    }
+    isolate->Dispose();
+  }
+  delete[] blob.data;
+}
+
+TEST(SnapshotCreatorTemplates) {
+  DisableTurbofan();
+  v8::StartupData blob;
+  {
+    v8::SnapshotCreator creator(original_external_references);
+    v8::Isolate* isolate = creator.GetIsolate();
+    {
+      v8::HandleScope handle_scope(isolate);
+      v8::ExtensionConfiguration* no_extension = nullptr;
+      v8::Local<v8::ObjectTemplate> global_template =
+          v8::ObjectTemplate::New(isolate);
+      v8::Local<v8::FunctionTemplate> callback =
+          v8::FunctionTemplate::New(isolate, SerializedCallback);
+      global_template->Set(v8_str("f"), callback);
+      v8::Local<v8::Context> context =
+          v8::Context::New(isolate, no_extension, global_template);
+      v8::Context::Scope context_scope(context);
+      ExpectInt32("f()", 42);
+      CHECK_EQ(0, creator.AddContext(context));
+      CHECK_EQ(0, creator.AddTemplate(callback));
+      CHECK_EQ(1, creator.AddTemplate(global_template));
+    }
+    blob =
+        creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
+  }
+
+  {
+    v8::Isolate::CreateParams params;
+    params.snapshot_blob = &blob;
+    params.array_buffer_allocator = CcTest::array_buffer_allocator();
+    params.external_references = original_external_references;
+    v8::Isolate* isolate = v8::Isolate::New(params);
+    {
+      v8::Isolate::Scope isolate_scope(isolate);
+      {
+        // Create a new context without a new object template.
+        v8::HandleScope handle_scope(isolate);
+        v8::ExtensionConfiguration* no_extension = nullptr;
+        v8::Local<v8::ObjectTemplate> no_template =
+            v8::Local<v8::ObjectTemplate>();
+        v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
+        v8::Local<v8::Context> context =
+            v8::Context::New(isolate, no_extension, no_template, no_object, 0);
+        v8::Context::Scope context_scope(context);
+        ExpectInt32("f()", 42);
+
+        // Retrieve the snapshotted object template.
+        v8::Local<v8::ObjectTemplate> obj_template =
+            v8::ObjectTemplate::FromSnapshot(isolate, 1);
+        CHECK(!obj_template.IsEmpty());
+        v8::Local<v8::Object> object =
+            obj_template->NewInstance(context).ToLocalChecked();
+        CHECK(context->Global()->Set(context, v8_str("o"), object).FromJust());
+        ExpectInt32("o.f()", 42);
+        // Check that it instantiates to the same prototype.
+        ExpectTrue("o.f.prototype === f.prototype");
+
+        // Retrieve the snapshotted function template.
+        v8::Local<v8::FunctionTemplate> fun_template =
+            v8::FunctionTemplate::FromSnapshot(isolate, 0);
+        CHECK(!fun_template.IsEmpty());
+        v8::Local<v8::Function> fun =
+            fun_template->GetFunction(context).ToLocalChecked();
+        CHECK(context->Global()->Set(context, v8_str("g"), fun).FromJust());
+        ExpectInt32("g()", 42);
+        // Check that it instantiates to the same prototype.
+        ExpectTrue("g.prototype === f.prototype");
+      }
+
+      {
+        // Create a context with a new object template. It is merged into the
+        // deserialized global object.
+        v8::HandleScope handle_scope(isolate);
+        v8::ExtensionConfiguration* no_extension = nullptr;
+        v8::Local<v8::ObjectTemplate> global_template =
+            v8::ObjectTemplate::New(isolate);
+        global_template->Set(
+            v8_str("g"),
+            v8::FunctionTemplate::New(isolate, SerializedCallbackReplacement));
+        v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
+        v8::Local<v8::Context> context = v8::Context::New(
+            isolate, no_extension, global_template, no_object, 0);
+        v8::Context::Scope context_scope(context);
+        ExpectInt32("g()", 1337);
+        ExpectInt32("f()", 42);
+      }
+    }
+    isolate->Dispose();
+  }
+  delete[] blob.data;
+}
 
 TEST(SerializationMemoryStats) {
   FLAG_profile_deserialization = true;
diff --git a/test/cctest/test-slots-buffer.cc b/test/cctest/test-slots-buffer.cc
index 07b70f5..4b8aeb7 100644
--- a/test/cctest/test-slots-buffer.cc
+++ b/test/cctest/test-slots-buffer.cc
@@ -4,7 +4,7 @@
 
 #include "src/heap/slots-buffer.h"
 #include "test/cctest/cctest.h"
-#include "test/cctest/heap/utils-inl.h"
+#include "test/cctest/heap/heap-utils.h"
 
 namespace v8 {
 namespace internal {
@@ -101,7 +101,7 @@
 
   // Write an old space reference into field 4 which points to an object on an
   // evacuation candidate.
-  SimulateFullSpace(heap->old_space());
+  heap::SimulateFullSpace(heap->old_space());
   Handle<FixedArray> valid_object =
       isolate->factory()->NewFixedArray(23, TENURED);
   Page* page = Page::FromAddress(valid_object->address());
diff --git a/test/cctest/test-strings.cc b/test/cctest/test-strings.cc
index 770042d..afa8ecb 100644
--- a/test/cctest/test-strings.cc
+++ b/test/cctest/test-strings.cc
@@ -1110,7 +1110,8 @@
             .ToLocalChecked()
             ->Run(context)
             .ToLocalChecked();
-    CHECK_EQ(results[i]->IsUndefined(), result->IsUndefined());
+    CHECK_EQ(results[i]->IsUndefined(CcTest::i_isolate()),
+             result->IsUndefined());
     CHECK_EQ(results[i]->IsNumber(), result->IsNumber());
     if (result->IsNumber()) {
       int32_t value = 0;
diff --git a/test/cctest/test-thread-termination.cc b/test/cctest/test-thread-termination.cc
index 85dfd13..9d3cbf6 100644
--- a/test/cctest/test-thread-termination.cc
+++ b/test/cctest/test-thread-termination.cc
@@ -204,6 +204,31 @@
   semaphore = NULL;
 }
 
+// Test that execution can be terminated from within JSON.stringify.
+TEST(TerminateJsonStringify) {
+  semaphore = new v8::base::Semaphore(0);
+  TerminatorThread thread(CcTest::i_isolate());
+  thread.Start();
+
+  v8::HandleScope scope(CcTest::isolate());
+  v8::Local<v8::ObjectTemplate> global =
+      CreateGlobalTemplate(CcTest::isolate(), Signal, DoLoop);
+  v8::Local<v8::Context> context =
+      v8::Context::New(CcTest::isolate(), NULL, global);
+  v8::Context::Scope context_scope(context);
+  CHECK(!CcTest::isolate()->IsExecutionTerminating());
+  v8::MaybeLocal<v8::Value> result =
+      CompileRun(CcTest::isolate()->GetCurrentContext(),
+                 "var x = [];"
+                 "x[2**31]=1;"
+                 "terminate();"
+                 "JSON.stringify(x);"
+                 "fail();");
+  CHECK(result.IsEmpty());
+  thread.Join();
+  delete semaphore;
+  semaphore = NULL;
+}
 
 int call_count = 0;
 
diff --git a/test/cctest/test-typing-reset.cc b/test/cctest/test-typing-reset.cc
deleted file mode 100644
index 4e9413a..0000000
--- a/test/cctest/test-typing-reset.cc
+++ /dev/null
@@ -1,298 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdlib.h>
-
-#include "src/v8.h"
-
-#include "src/ast/ast.h"
-#include "src/ast/ast-expression-visitor.h"
-#include "src/ast/scopes.h"
-#include "src/parsing/parser.h"
-#include "src/parsing/rewriter.h"
-#include "src/typing-reset.h"
-#include "test/cctest/cctest.h"
-#include "test/cctest/compiler/function-tester.h"
-#include "test/cctest/expression-type-collector.h"
-#include "test/cctest/expression-type-collector-macros.h"
-
-#define INT32_TYPE Bounds(Type::Signed32(), Type::Signed32())
-
-using namespace v8::internal;
-
-namespace {
-
-class TypeSetter : public AstExpressionVisitor {
- public:
-  TypeSetter(Isolate* isolate, FunctionLiteral* root)
-      : AstExpressionVisitor(isolate, root) {}
-
- protected:
-  void VisitExpression(Expression* expression) {
-    expression->set_bounds(INT32_TYPE);
-  }
-};
-
-
-void CheckAllSame(ZoneVector<ExpressionTypeEntry>& types,
-                  Bounds expected_type) {
-  CHECK_TYPES_BEGIN {
-    // function logSum
-    CHECK_EXPR(FunctionLiteral, expected_type) {
-      CHECK_EXPR(FunctionLiteral, expected_type) {
-        CHECK_EXPR(Assignment, expected_type) {
-          CHECK_VAR(start, expected_type);
-          CHECK_EXPR(BinaryOperation, expected_type) {
-            CHECK_VAR(start, expected_type);
-            CHECK_EXPR(Literal, expected_type);
-          }
-        }
-        CHECK_EXPR(Assignment, expected_type) {
-          CHECK_VAR(end, expected_type);
-          CHECK_EXPR(BinaryOperation, expected_type) {
-            CHECK_VAR(end, expected_type);
-            CHECK_EXPR(Literal, expected_type);
-          }
-        }
-        CHECK_EXPR(Assignment, expected_type) {
-          CHECK_VAR(sum, expected_type);
-          CHECK_EXPR(Literal, expected_type);
-        }
-        CHECK_EXPR(Assignment, expected_type) {
-          CHECK_VAR(p, expected_type);
-          CHECK_EXPR(Literal, expected_type);
-        }
-        CHECK_EXPR(Assignment, expected_type) {
-          CHECK_VAR(q, expected_type);
-          CHECK_EXPR(Literal, expected_type);
-        }
-        // for (p = start << 3, q = end << 3;
-        CHECK_EXPR(BinaryOperation, expected_type) {
-          CHECK_EXPR(Assignment, expected_type) {
-            CHECK_VAR(p, expected_type);
-            CHECK_EXPR(BinaryOperation, expected_type) {
-              CHECK_VAR(start, expected_type);
-              CHECK_EXPR(Literal, expected_type);
-            }
-          }
-          CHECK_EXPR(Assignment, expected_type) {
-            CHECK_VAR(q, expected_type);
-            CHECK_EXPR(BinaryOperation, expected_type) {
-              CHECK_VAR(end, expected_type);
-              CHECK_EXPR(Literal, expected_type);
-            }
-          }
-        }
-        // (p|0) < (q|0);
-        CHECK_EXPR(CompareOperation, expected_type) {
-          CHECK_EXPR(BinaryOperation, expected_type) {
-            CHECK_VAR(p, expected_type);
-            CHECK_EXPR(Literal, expected_type);
-          }
-          CHECK_EXPR(BinaryOperation, expected_type) {
-            CHECK_VAR(q, expected_type);
-            CHECK_EXPR(Literal, expected_type);
-          }
-        }
-        // p = (p + 8)|0) {\n"
-        CHECK_EXPR(Assignment, expected_type) {
-          CHECK_VAR(p, expected_type);
-          CHECK_EXPR(BinaryOperation, expected_type) {
-            CHECK_EXPR(BinaryOperation, expected_type) {
-              CHECK_VAR(p, expected_type);
-              CHECK_EXPR(Literal, expected_type);
-            }
-            CHECK_EXPR(Literal, expected_type);
-          }
-        }
-        // sum = sum + +log(values[p>>3]);
-        CHECK_EXPR(Assignment, expected_type) {
-          CHECK_VAR(sum, expected_type);
-          CHECK_EXPR(BinaryOperation, expected_type) {
-            CHECK_VAR(sum, expected_type);
-            CHECK_EXPR(BinaryOperation, expected_type) {
-              CHECK_EXPR(Call, expected_type) {
-                CHECK_VAR(log, expected_type);
-                CHECK_EXPR(Property, expected_type) {
-                  CHECK_VAR(values, expected_type);
-                  CHECK_EXPR(BinaryOperation, expected_type) {
-                    CHECK_VAR(p, expected_type);
-                    CHECK_EXPR(Literal, expected_type);
-                  }
-                }
-              }
-              CHECK_EXPR(Literal, expected_type);
-            }
-          }
-        }
-        // return +sum;
-        CHECK_EXPR(BinaryOperation, expected_type) {
-          CHECK_VAR(sum, expected_type);
-          CHECK_EXPR(Literal, expected_type);
-        }
-      }
-      // function geometricMean
-      CHECK_EXPR(FunctionLiteral, expected_type) {
-        CHECK_EXPR(Assignment, expected_type) {
-          CHECK_VAR(start, expected_type);
-          CHECK_EXPR(BinaryOperation, expected_type) {
-            CHECK_VAR(start, expected_type);
-            CHECK_EXPR(Literal, expected_type);
-          }
-        }
-        CHECK_EXPR(Assignment, expected_type) {
-          CHECK_VAR(end, expected_type);
-          CHECK_EXPR(BinaryOperation, expected_type) {
-            CHECK_VAR(end, expected_type);
-            CHECK_EXPR(Literal, expected_type);
-          }
-        }
-        // return +exp(+logSum(start, end) / +((end - start)|0));
-        CHECK_EXPR(BinaryOperation, expected_type) {
-          CHECK_EXPR(Call, expected_type) {
-            CHECK_VAR(exp, expected_type);
-            CHECK_EXPR(BinaryOperation, expected_type) {
-              CHECK_EXPR(BinaryOperation, expected_type) {
-                CHECK_EXPR(Call, expected_type) {
-                  CHECK_VAR(logSum, expected_type);
-                  CHECK_VAR(start, expected_type);
-                  CHECK_VAR(end, expected_type);
-                }
-                CHECK_EXPR(Literal, expected_type);
-              }
-              CHECK_EXPR(BinaryOperation, expected_type) {
-                CHECK_EXPR(BinaryOperation, expected_type) {
-                  CHECK_EXPR(BinaryOperation, expected_type) {
-                    CHECK_VAR(end, expected_type);
-                    CHECK_VAR(start, expected_type);
-                  }
-                  CHECK_EXPR(Literal, expected_type);
-                }
-                CHECK_EXPR(Literal, expected_type);
-              }
-            }
-          }
-          CHECK_EXPR(Literal, expected_type);
-        }
-      }
-      // "use asm";
-      CHECK_EXPR(Literal, expected_type);
-      // var exp = stdlib.Math.exp;
-      CHECK_EXPR(Assignment, expected_type) {
-        CHECK_VAR(exp, expected_type);
-        CHECK_EXPR(Property, expected_type) {
-          CHECK_EXPR(Property, expected_type) {
-            CHECK_VAR(stdlib, expected_type);
-            CHECK_EXPR(Literal, expected_type);
-          }
-          CHECK_EXPR(Literal, expected_type);
-        }
-      }
-      // var log = stdlib.Math.log;
-      CHECK_EXPR(Assignment, expected_type) {
-        CHECK_VAR(log, expected_type);
-        CHECK_EXPR(Property, expected_type) {
-          CHECK_EXPR(Property, expected_type) {
-            CHECK_VAR(stdlib, expected_type);
-            CHECK_EXPR(Literal, expected_type);
-          }
-          CHECK_EXPR(Literal, expected_type);
-        }
-      }
-      // var values = new stdlib.Float64Array(buffer);
-      CHECK_EXPR(Assignment, expected_type) {
-        CHECK_VAR(values, expected_type);
-        CHECK_EXPR(CallNew, expected_type) {
-          CHECK_EXPR(Property, expected_type) {
-            CHECK_VAR(stdlib, expected_type);
-            CHECK_EXPR(Literal, expected_type);
-          }
-          CHECK_VAR(buffer, expected_type);
-        }
-      }
-      // return { geometricMean: geometricMean };
-      CHECK_EXPR(ObjectLiteral, expected_type) {
-        CHECK_VAR(geometricMean, expected_type);
-      }
-    }
-  }
-  CHECK_TYPES_END
-}
-
-}  // namespace
-
-
-TEST(ResetTypingInfo) {
-  const char test_function[] =
-      "function GeometricMean(stdlib, foreign, buffer) {\n"
-      "  \"use asm\";\n"
-      "\n"
-      "  var exp = stdlib.Math.exp;\n"
-      "  var log = stdlib.Math.log;\n"
-      "  var values = new stdlib.Float64Array(buffer);\n"
-      "\n"
-      "  function logSum(start, end) {\n"
-      "    start = start|0;\n"
-      "    end = end|0;\n"
-      "\n"
-      "    var sum = 0.0, p = 0, q = 0;\n"
-      "\n"
-      "    // asm.js forces byte addressing of the heap by requiring shifting "
-      "by 3\n"
-      "    for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {\n"
-      "      sum = sum + +log(values[p>>3]);\n"
-      "    }\n"
-      "\n"
-      "    return +sum;\n"
-      "  }\n"
-      "\n"
-      " function geometricMean(start, end) {\n"
-      "    start = start|0;\n"
-      "    end = end|0;\n"
-      "\n"
-      "    return +exp(+logSum(start, end) / +((end - start)|0));\n"
-      "  }\n"
-      "\n"
-      "  return { geometricMean: geometricMean };\n"
-      "}\n";
-
-  v8::V8::Initialize();
-  HandleAndZoneScope handles;
-
-  i::Isolate* isolate = CcTest::i_isolate();
-  i::Factory* factory = isolate->factory();
-
-  i::Handle<i::String> source_code =
-      factory->NewStringFromUtf8(i::CStrVector(test_function))
-          .ToHandleChecked();
-
-  i::Handle<i::Script> script = factory->NewScript(source_code);
-
-  i::ParseInfo info(handles.main_zone(), script);
-  i::Parser parser(&info);
-  parser.set_allow_harmony_sloppy(true);
-  info.set_global();
-  info.set_lazy(false);
-  info.set_allow_lazy_parsing(false);
-  info.set_toplevel(true);
-
-  CHECK(i::Compiler::ParseAndAnalyze(&info));
-  FunctionLiteral* root =
-      info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun();
-
-  // Core of the test.
-  ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
-  ExpressionTypeCollector(isolate, root, &types).Run();
-  CheckAllSame(types, Bounds::Unbounded());
-
-  TypeSetter(isolate, root).Run();
-
-  ExpressionTypeCollector(isolate, root, &types).Run();
-  CheckAllSame(types, INT32_TYPE);
-
-  TypingReseter(isolate, root).Run();
-
-  ExpressionTypeCollector(isolate, root, &types).Run();
-  CheckAllSame(types, Bounds::Unbounded());
-}
diff --git a/test/cctest/test-unboxed-doubles.cc b/test/cctest/test-unboxed-doubles.cc
index 7fc9b5b..c8a8bbb 100644
--- a/test/cctest/test-unboxed-doubles.cc
+++ b/test/cctest/test-unboxed-doubles.cc
@@ -15,7 +15,7 @@
 #include "src/ic/ic.h"
 #include "src/macro-assembler.h"
 #include "test/cctest/cctest.h"
-#include "test/cctest/heap/utils-inl.h"
+#include "test/cctest/heap/heap-utils.h"
 
 using namespace v8::base;
 using namespace v8::internal;
@@ -1112,7 +1112,7 @@
   {
     AlwaysAllocateScope always_allocate(isolate);
     // Make sure |obj_value| is placed on an old-space evacuation candidate.
-    SimulateFullSpace(old_space);
+    heap::SimulateFullSpace(old_space);
     obj_value = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, TENURED);
     ec_page = Page::FromAddress(obj_value->address());
   }
@@ -1142,7 +1142,7 @@
   FLAG_stress_compaction = true;
   FLAG_manual_evacuation_candidates_selection = true;
   ec_page->SetFlag(MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING);
-  SimulateIncrementalMarking(heap);
+  heap::SimulateIncrementalMarking(heap);
   // Disable stress compaction mode in order to let GC do scavenge.
   FLAG_stress_compaction = false;
 
@@ -1451,7 +1451,7 @@
     CHECK(old_space->Contains(*obj));
 
     // Make sure |obj_value| is placed on an old-space evacuation candidate.
-    SimulateFullSpace(old_space);
+    heap::SimulateFullSpace(old_space);
     obj_value = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, TENURED);
     ec_page = Page::FromAddress(obj_value->address());
     CHECK_NE(ec_page, Page::FromAddress(obj->address()));
@@ -1460,7 +1460,7 @@
   // Heap is ready, force |ec_page| to become an evacuation candidate and
   // simulate incremental marking.
   ec_page->SetFlag(MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING);
-  SimulateIncrementalMarking(heap);
+  heap::SimulateIncrementalMarking(heap);
 
   // Check that everything is ready for triggering incremental write barrier
   // (i.e. that both |obj| and |obj_value| are black and the marking phase is
@@ -1504,10 +1504,12 @@
   CHECK_EQ(boom_value, obj->RawFastDoublePropertyAt(double_field_index));
 }
 
-
-enum WriteBarrierKind { OLD_TO_OLD_WRITE_BARRIER, OLD_TO_NEW_WRITE_BARRIER };
+enum OldToWriteBarrierKind {
+  OLD_TO_OLD_WRITE_BARRIER,
+  OLD_TO_NEW_WRITE_BARRIER
+};
 static void TestWriteBarrierObjectShiftFieldsRight(
-    WriteBarrierKind write_barrier_kind) {
+    OldToWriteBarrierKind write_barrier_kind) {
   CcTest::InitializeVM();
   Isolate* isolate = CcTest::i_isolate();
   v8::HandleScope scope(CcTest::isolate());
diff --git a/test/cctest/test-usecounters.cc b/test/cctest/test-usecounters.cc
new file mode 100644
index 0000000..8d4628c
--- /dev/null
+++ b/test/cctest/test-usecounters.cc
@@ -0,0 +1,73 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "test/cctest/cctest.h"
+
+namespace {
+
+int* global_use_counts = NULL;
+
+void MockUseCounterCallback(v8::Isolate* isolate,
+                            v8::Isolate::UseCounterFeature feature) {
+  ++global_use_counts[feature];
+}
+}
+
+TEST(DefineGetterSetterThrowUseCount) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  LocalContext env;
+  int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
+  global_use_counts = use_counts;
+  CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
+
+  // __defineGetter__ and __defineSetter__ do not increment
+  // kDefineGetterOrSetterWouldThrow on success
+  CompileRun(
+      "var a = {};"
+      "Object.defineProperty(a, 'b', { value: 0, configurable: true });"
+      "a.__defineGetter__('b', ()=>{});");
+  CHECK_EQ(0, use_counts[v8::Isolate::kDefineGetterOrSetterWouldThrow]);
+  CompileRun(
+      "var a = {};"
+      "Object.defineProperty(a, 'b', { value: 0, configurable: true });"
+      "a.__defineSetter__('b', ()=>{});");
+  CHECK_EQ(0, use_counts[v8::Isolate::kDefineGetterOrSetterWouldThrow]);
+
+  // __defineGetter__ and __defineSetter__ do not increment
+  // kDefineGetterOrSetterWouldThrow on other errors
+  v8::Local<v8::Value> resultProxyThrow = CompileRun(
+      "var exception;"
+      "try {"
+      "var a = new Proxy({}, { defineProperty: ()=>{throw new Error;} });"
+      "a.__defineGetter__('b', ()=>{});"
+      "} catch (e) { exception = e; }"
+      "exception");
+  CHECK_EQ(0, use_counts[v8::Isolate::kDefineGetterOrSetterWouldThrow]);
+  CHECK(resultProxyThrow->IsObject());
+  resultProxyThrow = CompileRun(
+      "var exception;"
+      "try {"
+      "var a = new Proxy({}, { defineProperty: ()=>{throw new Error;} });"
+      "a.__defineSetter__('b', ()=>{});"
+      "} catch (e) { exception = e; }"
+      "exception");
+  CHECK_EQ(0, use_counts[v8::Isolate::kDefineGetterOrSetterWouldThrow]);
+  CHECK(resultProxyThrow->IsObject());
+
+  // __defineGetter__ and __defineSetter__ increment
+  // kDefineGetterOrSetterWouldThrow when they would throw per spec (B.2.2.2)
+  CompileRun(
+      "var a = {};"
+      "Object.defineProperty(a, 'b', { value: 0, configurable: false });"
+      "a.__defineGetter__('b', ()=>{});");
+  CHECK_EQ(1, use_counts[v8::Isolate::kDefineGetterOrSetterWouldThrow]);
+  CompileRun(
+      "var a = {};"
+      "Object.defineProperty(a, 'b', { value: 0, configurable: false });"
+      "a.__defineSetter__('b', ()=>{});");
+  CHECK_EQ(2, use_counts[v8::Isolate::kDefineGetterOrSetterWouldThrow]);
+}
diff --git a/test/cctest/test-weakmaps.cc b/test/cctest/test-weakmaps.cc
index 781ad1f..2d0e620 100644
--- a/test/cctest/test-weakmaps.cc
+++ b/test/cctest/test-weakmaps.cc
@@ -31,7 +31,7 @@
 
 #include "src/global-handles.h"
 #include "test/cctest/cctest.h"
-#include "test/cctest/heap/utils-inl.h"
+#include "test/cctest/heap/heap-utils.h"
 
 using namespace v8::internal;
 
@@ -52,8 +52,7 @@
 }
 
 static int NumberOfWeakCalls = 0;
-static void WeakPointerCallback(
-    const v8::WeakCallbackData<v8::Value, void>& data) {
+static void WeakPointerCallback(const v8::WeakCallbackInfo<void>& data) {
   std::pair<v8::Persistent<v8::Value>*, int>* p =
       reinterpret_cast<std::pair<v8::Persistent<v8::Value>*, int>*>(
           data.GetParameter());
@@ -107,20 +106,12 @@
   {
     HandleScope scope(isolate);
     std::pair<Handle<Object>*, int> handle_and_id(&key, 1234);
-    GlobalHandles::MakeWeak(key.location(),
-                            reinterpret_cast<void*>(&handle_and_id),
-                            &WeakPointerCallback);
+    GlobalHandles::MakeWeak(
+        key.location(), reinterpret_cast<void*>(&handle_and_id),
+        &WeakPointerCallback, v8::WeakCallbackType::kParameter);
   }
   CHECK(global_handles->IsWeak(key.location()));
 
-  // Force a full GC.
-  // Perform two consecutive GCs because the first one will only clear
-  // weak references whereas the second one will also clear weak maps.
-  heap->CollectAllGarbage(false);
-  CHECK_EQ(1, NumberOfWeakCalls);
-  CHECK_EQ(2, ObjectHashTable::cast(weakmap->table())->NumberOfElements());
-  CHECK_EQ(
-      0, ObjectHashTable::cast(weakmap->table())->NumberOfDeletedElements());
   heap->CollectAllGarbage(false);
   CHECK_EQ(1, NumberOfWeakCalls);
   CHECK_EQ(0, ObjectHashTable::cast(weakmap->table())->NumberOfElements());
@@ -186,7 +177,7 @@
 
   // Start second old-space page so that values land on evacuation candidate.
   Page* first_page = heap->old_space()->anchor()->next_page();
-  SimulateFullSpace(heap->old_space());
+  heap::SimulateFullSpace(heap->old_space());
 
   // Fill up weak map with values on an evacuation candidate.
   {
@@ -225,7 +216,7 @@
 
   // Start second old-space page so that keys land on evacuation candidate.
   Page* first_page = heap->old_space()->anchor()->next_page();
-  SimulateFullSpace(heap->old_space());
+  heap::SimulateFullSpace(heap->old_space());
 
   // Fill up weak map with keys on an evacuation candidate.
   Handle<JSObject> keys[32];
@@ -258,7 +249,7 @@
   {
     HandleScope scope(isolate);
     AllocateJSWeakMap(isolate);
-    SimulateIncrementalMarking(heap);
+    heap::SimulateIncrementalMarking(heap);
   }
   // The weak map is marked black here but leaving the handle scope will make
   // the object unreachable. Aborting incremental marking will clear all the
diff --git a/test/cctest/test-weaksets.cc b/test/cctest/test-weaksets.cc
index 643bb48..ec6945a 100644
--- a/test/cctest/test-weaksets.cc
+++ b/test/cctest/test-weaksets.cc
@@ -31,7 +31,7 @@
 
 #include "src/global-handles.h"
 #include "test/cctest/cctest.h"
-#include "test/cctest/heap/utils-inl.h"
+#include "test/cctest/heap/heap-utils.h"
 
 using namespace v8::internal;
 
@@ -55,8 +55,7 @@
 }
 
 static int NumberOfWeakCalls = 0;
-static void WeakPointerCallback(
-    const v8::WeakCallbackData<v8::Value, void>& data) {
+static void WeakPointerCallback(const v8::WeakCallbackInfo<void>& data) {
   std::pair<v8::Persistent<v8::Value>*, int>* p =
       reinterpret_cast<std::pair<v8::Persistent<v8::Value>*, int>*>(
           data.GetParameter());
@@ -106,20 +105,12 @@
   {
     HandleScope scope(isolate);
     std::pair<Handle<Object>*, int> handle_and_id(&key, 1234);
-    GlobalHandles::MakeWeak(key.location(),
-                            reinterpret_cast<void*>(&handle_and_id),
-                            &WeakPointerCallback);
+    GlobalHandles::MakeWeak(
+        key.location(), reinterpret_cast<void*>(&handle_and_id),
+        &WeakPointerCallback, v8::WeakCallbackType::kParameter);
   }
   CHECK(global_handles->IsWeak(key.location()));
 
-  // Force a full GC.
-  // Perform two consecutive GCs because the first one will only clear
-  // weak references whereas the second one will also clear weak sets.
-  heap->CollectAllGarbage(false);
-  CHECK_EQ(1, NumberOfWeakCalls);
-  CHECK_EQ(1, ObjectHashTable::cast(weakset->table())->NumberOfElements());
-  CHECK_EQ(
-      0, ObjectHashTable::cast(weakset->table())->NumberOfDeletedElements());
   heap->CollectAllGarbage(false);
   CHECK_EQ(1, NumberOfWeakCalls);
   CHECK_EQ(0, ObjectHashTable::cast(weakset->table())->NumberOfElements());
@@ -185,7 +176,7 @@
 
   // Start second old-space page so that values land on evacuation candidate.
   Page* first_page = heap->old_space()->anchor()->next_page();
-  SimulateFullSpace(heap->old_space());
+  heap::SimulateFullSpace(heap->old_space());
 
   // Fill up weak set with values on an evacuation candidate.
   {
@@ -224,7 +215,7 @@
 
   // Start second old-space page so that keys land on evacuation candidate.
   Page* first_page = heap->old_space()->anchor()->next_page();
-  SimulateFullSpace(heap->old_space());
+  heap::SimulateFullSpace(heap->old_space());
 
   // Fill up weak set with keys on an evacuation candidate.
   Handle<JSObject> keys[32];
diff --git a/test/cctest/trace-extension.cc b/test/cctest/trace-extension.cc
index 77a29e9..19f8cd8 100644
--- a/test/cctest/trace-extension.cc
+++ b/test/cctest/trace-extension.cc
@@ -27,7 +27,7 @@
 
 #include "test/cctest/trace-extension.h"
 
-#include "src/profiler/sampler.h"
+#include "src/profiler/tick-sample.h"
 #include "src/vm-state-inl.h"
 #include "test/cctest/cctest.h"
 
@@ -86,7 +86,7 @@
 #else
 #error Host architecture is neither 32-bit nor 64-bit.
 #endif
-  printf("Trace: %p\n", fp);
+  printf("Trace: %p\n", static_cast<void*>(fp));
   return fp;
 }
 
diff --git a/test/cctest/types-fuzz.h b/test/cctest/types-fuzz.h
index 79e4608..7bf9700 100644
--- a/test/cctest/types-fuzz.h
+++ b/test/cctest/types-fuzz.h
@@ -208,8 +208,6 @@
 
   Type* Representation(Type* t) { return Type::Representation(t, zone_); }
 
-  // Type* Semantic(Type* t) { return Intersect(t,
-  // MaskSemanticForTesting); }
   Type* Semantic(Type* t) { return Type::Semantic(t, zone_); }
 
   Type* Random() {
diff --git a/test/cctest/wasm/test-run-wasm-64.cc b/test/cctest/wasm/test-run-wasm-64.cc
index 784f21a..af87498 100644
--- a/test/cctest/wasm/test-run-wasm-64.cc
+++ b/test/cctest/wasm/test-run-wasm-64.cc
@@ -14,6 +14,13 @@
 #include "test/cctest/wasm/test-signatures.h"
 #include "test/cctest/wasm/wasm-run-utils.h"
 
+// If the target architecture is 64-bit, enable all tests.
+#if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64
+#define WASM_64 1
+#else
+#define WASM_64 0
+#endif
+
 #define CHECK_TRAP32(x) \
   CHECK_EQ(0xdeadbeef, (bit_cast<uint32_t>(x)) & 0xFFFFFFFF)
 #define CHECK_TRAP64(x) \
@@ -24,20 +31,14 @@
 
 #define asu64(x) static_cast<uint64_t>(x)
 
-#define B2(a, b) kExprBlock, 2, a, b
-#define B1(a) kExprBlock, 1, a
+#define B2(a, b) kExprBlock, a, b, kExprEnd
+#define B1(a) kExprBlock, a, kExprEnd
 
 // Can't bridge macro land with nested macros.
-#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_X87
-#define MIPS_OR_X87 true
+#if V8_TARGET_ARCH_MIPS
+#define MIPS true
 #else
-#define MIPS_OR_X87 false
-#endif
-
-#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_X87 || V8_TARGET_ARCH_ARM
-#define MIPS_OR_ARM_OR_X87 true
-#else
-#define MIPS_OR_ARM_OR_X87 false
+#define MIPS false
 #endif
 
 #define FOREACH_I64_OPERATOR(V) \
@@ -47,9 +48,9 @@
   V(I64Return, true)            \
   V(I64Param, true)             \
   V(I64LoadStore, true)         \
-  V(I64Add, !MIPS_OR_X87)       \
-  V(I64Sub, !MIPS_OR_X87)       \
-  V(I64Mul, !MIPS_OR_X87)       \
+  V(I64Add, true)               \
+  V(I64Sub, true)               \
+  V(I64Mul, !MIPS)              \
   V(I64DivS, true)              \
   V(I64DivU, true)              \
   V(I64RemS, true)              \
@@ -57,9 +58,9 @@
   V(I64And, true)               \
   V(I64Ior, true)               \
   V(I64Xor, true)               \
-  V(I64Shl, !MIPS_OR_X87)       \
-  V(I64ShrU, !MIPS_OR_X87)      \
-  V(I64ShrS, !MIPS_OR_X87)      \
+  V(I64Shl, true)               \
+  V(I64ShrU, true)              \
+  V(I64ShrS, true)              \
   V(I64Eq, true)                \
   V(I64Ne, true)                \
   V(I64LtS, true)               \
@@ -72,7 +73,7 @@
   V(I64GeU, true)               \
   V(I64Ctz, true)               \
   V(I64Clz, true)               \
-  V(I64Popcnt, !MIPS_OR_X87)    \
+  V(I64Popcnt, true)            \
   V(I32ConvertI64, true)        \
   V(I64SConvertF32, true)       \
   V(I64SConvertF64, true)       \
@@ -96,20 +97,20 @@
 #define REQUIRE(name) \
   if (!WASM_64 && !kSupported_##name) return
 
-TEST(Run_Wasm_I64Const) {
+WASM_EXEC_TEST(I64Const) {
   REQUIRE(I64Const);
-  WasmRunner<int64_t> r;
+  WasmRunner<int64_t> r(execution_mode);
   const int64_t kExpectedValue = 0x1122334455667788LL;
   // return(kExpectedValue)
   BUILD(r, WASM_I64V_9(kExpectedValue));
   CHECK_EQ(kExpectedValue, r.Call());
 }
 
-TEST(Run_Wasm_I64Const_many) {
+WASM_EXEC_TEST(I64Const_many) {
   REQUIRE(I64Const);
   int cntr = 0;
   FOR_INT32_INPUTS(i) {
-    WasmRunner<int64_t> r;
+    WasmRunner<int64_t> r(execution_mode);
     const int64_t kExpectedValue = (static_cast<int64_t>(*i) << 32) | cntr;
     // return(kExpectedValue)
     BUILD(r, WASM_I64V(kExpectedValue));
@@ -118,41 +119,39 @@
   }
 }
 
-TEST(Run_Wasm_Return_I64) {
+WASM_EXEC_TEST(Return_I64) {
   REQUIRE(I64Return);
-  WasmRunner<int64_t> r(MachineType::Int64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int64());
 
-  BUILD(r, WASM_RETURN(WASM_GET_LOCAL(0)));
+  BUILD(r, WASM_RETURN1(WASM_GET_LOCAL(0)));
 
   FOR_INT64_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
 }
 
-// todo(ahaas): I added a list of missing instructions here to make merging
-// easier when I do them one by one.
-// kExprI64Add:
-TEST(Run_WasmI64Add) {
+WASM_EXEC_TEST(I64Add) {
   REQUIRE(I64Add);
-  WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_INT64_INPUTS(i) {
     FOR_INT64_INPUTS(j) { CHECK_EQ(*i + *j, r.Call(*i, *j)); }
   }
 }
-// kExprI64Sub:
-TEST(Run_Wasm_I64Sub) {
+
+WASM_EXEC_TEST(I64Sub) {
   REQUIRE(I64Sub);
-  WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_INT64_INPUTS(i) {
     FOR_INT64_INPUTS(j) { CHECK_EQ(*i - *j, r.Call(*i, *j)); }
   }
 }
-// kExprI64Mul:
-// kExprI64DivS:
 
-TEST(Run_WasmI64DivS) {
+WASM_EXEC_TEST(I64DivS) {
   REQUIRE(I64DivS);
-  WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_INT64_INPUTS(i) {
     FOR_INT64_INPUTS(j) {
@@ -167,9 +166,10 @@
   }
 }
 
-TEST(Run_WasmI64DivS_Trap) {
+WASM_EXEC_TEST(I64DivS_Trap) {
   REQUIRE(I64DivS);
-  WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   CHECK_EQ(0, r.Call(asi64(0), asi64(100)));
   CHECK_TRAP64(r.Call(asi64(100), asi64(0)));
@@ -178,10 +178,10 @@
   CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), asi64(0)));
 }
 
-TEST(Run_WasmI64DivS_Byzero_Const) {
+WASM_EXEC_TEST(I64DivS_Byzero_Const) {
   REQUIRE(I64DivS);
   for (int8_t denom = -2; denom < 8; denom++) {
-    WasmRunner<int64_t> r(MachineType::Int64());
+    WasmRunner<int64_t> r(execution_mode, MachineType::Int64());
     BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_I64V_1(denom)));
     for (int64_t val = -7; val < 8; val++) {
       if (denom == 0) {
@@ -192,11 +192,11 @@
     }
   }
 }
-// kExprI64DivU:
 
-TEST(Run_WasmI64DivU) {
+WASM_EXEC_TEST(I64DivU) {
   REQUIRE(I64DivU);
-  WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64());
+  WasmRunner<uint64_t> r(execution_mode, MachineType::Uint64(),
+                         MachineType::Uint64());
   BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_UINT64_INPUTS(i) {
     FOR_UINT64_INPUTS(j) {
@@ -209,9 +209,10 @@
   }
 }
 
-TEST(Run_WasmI64DivU_Trap) {
+WASM_EXEC_TEST(I64DivU_Trap) {
   REQUIRE(I64DivU);
-  WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64());
+  WasmRunner<uint64_t> r(execution_mode, MachineType::Uint64(),
+                         MachineType::Uint64());
   BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   CHECK_EQ(0, r.Call(asu64(0), asu64(100)));
   CHECK_TRAP64(r.Call(asu64(100), asu64(0)));
@@ -219,10 +220,10 @@
   CHECK_TRAP64(r.Call(std::numeric_limits<uint64_t>::max(), asu64(0)));
 }
 
-TEST(Run_WasmI64DivU_Byzero_Const) {
+WASM_EXEC_TEST(I64DivU_Byzero_Const) {
   REQUIRE(I64DivU);
   for (uint64_t denom = 0xfffffffffffffffe; denom < 8; denom++) {
-    WasmRunner<uint64_t> r(MachineType::Uint64());
+    WasmRunner<uint64_t> r(execution_mode, MachineType::Uint64());
     BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_I64V_1(denom)));
 
     for (uint64_t val = 0xfffffffffffffff0; val < 8; val++) {
@@ -234,10 +235,11 @@
     }
   }
 }
-// kExprI64RemS:
-TEST(Run_WasmI64RemS) {
+
+WASM_EXEC_TEST(I64RemS) {
   REQUIRE(I64RemS);
-  WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_INT64_INPUTS(i) {
     FOR_INT64_INPUTS(j) {
@@ -250,9 +252,10 @@
   }
 }
 
-TEST(Run_WasmI64RemS_Trap) {
+WASM_EXEC_TEST(I64RemS_Trap) {
   REQUIRE(I64RemS);
-  WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   CHECK_EQ(33, r.Call(asi64(133), asi64(100)));
   CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), asi64(-1)));
@@ -261,10 +264,10 @@
   CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), asi64(0)));
 }
 
-// kExprI64RemU:
-TEST(Run_WasmI64RemU) {
+WASM_EXEC_TEST(I64RemU) {
   REQUIRE(I64RemU);
-  WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64());
+  WasmRunner<uint64_t> r(execution_mode, MachineType::Uint64(),
+                         MachineType::Uint64());
   BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_UINT64_INPUTS(i) {
     FOR_UINT64_INPUTS(j) {
@@ -277,9 +280,10 @@
   }
 }
 
-TEST(Run_Wasm_I64RemU_Trap) {
+WASM_EXEC_TEST(I64RemU_Trap) {
   REQUIRE(I64RemU);
-  WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64());
+  WasmRunner<uint64_t> r(execution_mode, MachineType::Uint64(),
+                         MachineType::Uint64());
   BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   CHECK_EQ(17, r.Call(asu64(217), asu64(100)));
   CHECK_TRAP64(r.Call(asu64(100), asu64(0)));
@@ -287,38 +291,41 @@
   CHECK_TRAP64(r.Call(std::numeric_limits<uint64_t>::max(), asu64(0)));
 }
 
-// kExprI64And:
-TEST(Run_Wasm_I64And) {
+WASM_EXEC_TEST(I64And) {
   REQUIRE(I64And);
-  WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_AND(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_INT64_INPUTS(i) {
     FOR_INT64_INPUTS(j) { CHECK_EQ((*i) & (*j), r.Call(*i, *j)); }
   }
 }
-// kExprI64Ior:
-TEST(Run_Wasm_I64Ior) {
+
+WASM_EXEC_TEST(I64Ior) {
   REQUIRE(I64Ior);
-  WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_IOR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_INT64_INPUTS(i) {
     FOR_INT64_INPUTS(j) { CHECK_EQ((*i) | (*j), r.Call(*i, *j)); }
   }
 }
-// kExprI64Xor:
-TEST(Run_Wasm_I64Xor) {
+
+WASM_EXEC_TEST(I64Xor) {
   REQUIRE(I64Xor);
-  WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_INT64_INPUTS(i) {
     FOR_INT64_INPUTS(j) { CHECK_EQ((*i) ^ (*j), r.Call(*i, *j)); }
   }
 }
-// kExprI64Shl:
-TEST(Run_Wasm_I64Shl) {
+
+WASM_EXEC_TEST(I64Shl) {
   REQUIRE(I64Shl);
   {
-    WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64());
+    WasmRunner<uint64_t> r(execution_mode, MachineType::Uint64(),
+                           MachineType::Uint64());
     BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
     FOR_UINT64_INPUTS(i) {
@@ -329,31 +336,32 @@
     }
   }
   {
-    WasmRunner<int64_t> r(MachineType::Int64());
+    WasmRunner<int64_t> r(execution_mode, MachineType::Int64());
     BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_I64V_1(0)));
     FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 0, r.Call(*i)); }
   }
   {
-    WasmRunner<int64_t> r(MachineType::Int64());
+    WasmRunner<int64_t> r(execution_mode, MachineType::Int64());
     BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_I64V_1(32)));
     FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 32, r.Call(*i)); }
   }
   {
-    WasmRunner<int64_t> r(MachineType::Int64());
+    WasmRunner<int64_t> r(execution_mode, MachineType::Int64());
     BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_I64V_1(20)));
     FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 20, r.Call(*i)); }
   }
   {
-    WasmRunner<int64_t> r(MachineType::Int64());
+    WasmRunner<int64_t> r(execution_mode, MachineType::Int64());
     BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_I64V_1(40)));
     FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 40, r.Call(*i)); }
   }
 }
-// kExprI64ShrU:
-TEST(Run_Wasm_I64ShrU) {
+
+WASM_EXEC_TEST(I64ShrU) {
   REQUIRE(I64ShrU);
   {
-    WasmRunner<uint64_t> r(MachineType::Uint64(), MachineType::Uint64());
+    WasmRunner<uint64_t> r(execution_mode, MachineType::Uint64(),
+                           MachineType::Uint64());
     BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
     FOR_UINT64_INPUTS(i) {
@@ -364,31 +372,32 @@
     }
   }
   {
-    WasmRunner<int64_t> r(MachineType::Int64());
+    WasmRunner<int64_t> r(execution_mode, MachineType::Int64());
     BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(0)));
     FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 0, r.Call(*i)); }
   }
   {
-    WasmRunner<int64_t> r(MachineType::Int64());
+    WasmRunner<int64_t> r(execution_mode, MachineType::Int64());
     BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(32)));
     FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 32, r.Call(*i)); }
   }
   {
-    WasmRunner<int64_t> r(MachineType::Int64());
+    WasmRunner<int64_t> r(execution_mode, MachineType::Int64());
     BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(20)));
     FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 20, r.Call(*i)); }
   }
   {
-    WasmRunner<int64_t> r(MachineType::Int64());
+    WasmRunner<int64_t> r(execution_mode, MachineType::Int64());
     BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(40)));
     FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 40, r.Call(*i)); }
   }
 }
-// kExprI64ShrS:
-TEST(Run_Wasm_I64ShrS) {
+
+WASM_EXEC_TEST(I64ShrS) {
   REQUIRE(I64ShrS);
   {
-    WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
+    WasmRunner<int64_t> r(execution_mode, MachineType::Int64(),
+                          MachineType::Int64());
     BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
     FOR_INT64_INPUTS(i) {
@@ -399,143 +408,151 @@
     }
   }
   {
-    WasmRunner<int64_t> r(MachineType::Int64());
+    WasmRunner<int64_t> r(execution_mode, MachineType::Int64());
     BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(0)));
     FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 0, r.Call(*i)); }
   }
   {
-    WasmRunner<int64_t> r(MachineType::Int64());
+    WasmRunner<int64_t> r(execution_mode, MachineType::Int64());
     BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(32)));
     FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 32, r.Call(*i)); }
   }
   {
-    WasmRunner<int64_t> r(MachineType::Int64());
+    WasmRunner<int64_t> r(execution_mode, MachineType::Int64());
     BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(20)));
     FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 20, r.Call(*i)); }
   }
   {
-    WasmRunner<int64_t> r(MachineType::Int64());
+    WasmRunner<int64_t> r(execution_mode, MachineType::Int64());
     BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(40)));
     FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 40, r.Call(*i)); }
   }
 }
-// kExprI64Eq:
-TEST(Run_Wasm_I64Eq) {
+
+WASM_EXEC_TEST(I64Eq) {
   REQUIRE(I64Eq);
-  WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_EQ(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_INT64_INPUTS(i) {
     FOR_INT64_INPUTS(j) { CHECK_EQ(*i == *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
-// kExprI64Ne:
-TEST(Run_Wasm_I64Ne) {
+
+WASM_EXEC_TEST(I64Ne) {
   REQUIRE(I64Ne);
-  WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_NE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_INT64_INPUTS(i) {
     FOR_INT64_INPUTS(j) { CHECK_EQ(*i != *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
-// kExprI64LtS:
-TEST(Run_Wasm_I64LtS) {
+
+WASM_EXEC_TEST(I64LtS) {
   REQUIRE(I64LtS);
-  WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_LTS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_INT64_INPUTS(i) {
     FOR_INT64_INPUTS(j) { CHECK_EQ(*i < *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
-TEST(Run_Wasm_I64LeS) {
+
+WASM_EXEC_TEST(I64LeS) {
   REQUIRE(I64LeS);
-  WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_LES(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_INT64_INPUTS(i) {
     FOR_INT64_INPUTS(j) { CHECK_EQ(*i <= *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
-TEST(Run_Wasm_I64LtU) {
+
+WASM_EXEC_TEST(I64LtU) {
   REQUIRE(I64LtU);
-  WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_LTU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_UINT64_INPUTS(i) {
     FOR_UINT64_INPUTS(j) { CHECK_EQ(*i < *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
-TEST(Run_Wasm_I64LeU) {
+
+WASM_EXEC_TEST(I64LeU) {
   REQUIRE(I64LeU);
-  WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_LEU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_UINT64_INPUTS(i) {
     FOR_UINT64_INPUTS(j) { CHECK_EQ(*i <= *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
-TEST(Run_Wasm_I64GtS) {
+
+WASM_EXEC_TEST(I64GtS) {
   REQUIRE(I64GtS);
-  WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_GTS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_INT64_INPUTS(i) {
     FOR_INT64_INPUTS(j) { CHECK_EQ(*i > *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
-TEST(Run_Wasm_I64GeS) {
+
+WASM_EXEC_TEST(I64GeS) {
   REQUIRE(I64GeS);
-  WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_GES(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_INT64_INPUTS(i) {
     FOR_INT64_INPUTS(j) { CHECK_EQ(*i >= *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
 
-TEST(Run_Wasm_I64GtU) {
+WASM_EXEC_TEST(I64GtU) {
   REQUIRE(I64GtU);
-  WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_GTU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_UINT64_INPUTS(i) {
     FOR_UINT64_INPUTS(j) { CHECK_EQ(*i > *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
 
-TEST(Run_Wasm_I64GeU) {
+WASM_EXEC_TEST(I64GeU) {
   REQUIRE(I64GeU);
-  WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_GEU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_UINT64_INPUTS(i) {
     FOR_UINT64_INPUTS(j) { CHECK_EQ(*i >= *j ? 1 : 0, r.Call(*i, *j)); }
   }
 }
-// kExprI32ConvertI64:
-TEST(Run_Wasm_I32ConvertI64) {
+
+WASM_EXEC_TEST(I32ConvertI64) {
   REQUIRE(I32ConvertI64);
   FOR_INT64_INPUTS(i) {
-    WasmRunner<int32_t> r;
+    WasmRunner<int32_t> r(execution_mode);
     BUILD(r, WASM_I32_CONVERT_I64(WASM_I64V(*i)));
     CHECK_EQ(static_cast<int32_t>(*i), r.Call());
   }
 }
-// kExprI64SConvertI32:
-TEST(Run_Wasm_I64SConvertI32) {
+
+WASM_EXEC_TEST(I64SConvertI32) {
   REQUIRE(I64SConvertI32);
-  WasmRunner<int64_t> r(MachineType::Int32());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int32());
   BUILD(r, WASM_I64_SCONVERT_I32(WASM_GET_LOCAL(0)));
   FOR_INT32_INPUTS(i) { CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i)); }
 }
 
-// kExprI64UConvertI32:
-TEST(Run_Wasm_I64UConvertI32) {
+WASM_EXEC_TEST(I64UConvertI32) {
   REQUIRE(I64UConvertI32);
-  WasmRunner<int64_t> r(MachineType::Uint32());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Uint32());
   BUILD(r, WASM_I64_UCONVERT_I32(WASM_GET_LOCAL(0)));
   FOR_UINT32_INPUTS(i) { CHECK_EQ(static_cast<uint64_t>(*i), r.Call(*i)); }
 }
 
-// kExprF64ReinterpretI64:
-// kExprI64ReinterpretF64:
-
-// kExprI64Clz:
-// kExprI64Ctz:
-// kExprI64Popcnt:
-TEST(Run_WasmI64Popcnt) {
+WASM_EXEC_TEST(I64Popcnt) {
   struct {
     int64_t expected;
     uint64_t input;
@@ -545,22 +562,21 @@
                 {26, 0x1123456782345678},
                 {38, 0xffedcba09edcba09}};
 
-  WasmRunner<int64_t> r(MachineType::Uint64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Uint64());
   BUILD(r, WASM_I64_POPCNT(WASM_GET_LOCAL(0)));
   for (size_t i = 0; i < arraysize(values); i++) {
     CHECK_EQ(values[i].expected, r.Call(values[i].input));
   }
 }
 
-// kExprF32SConvertI64:
-TEST(Run_WasmF32SConvertI64) {
+WASM_EXEC_TEST(F32SConvertI64) {
   REQUIRE(F32SConvertI64);
-  WasmRunner<float> r(MachineType::Int64());
+  WasmRunner<float> r(execution_mode, MachineType::Int64());
   BUILD(r, WASM_F32_SCONVERT_I64(WASM_GET_LOCAL(0)));
   FOR_INT64_INPUTS(i) { CHECK_FLOAT_EQ(static_cast<float>(*i), r.Call(*i)); }
 }
-// kExprF32UConvertI64:
-TEST(Run_WasmF32UConvertI64) {
+
+WASM_EXEC_TEST(F32UConvertI64) {
   REQUIRE(F32UConvertI64);
   struct {
     uint64_t input;
@@ -641,21 +657,21 @@
                 {0x8000008000000001, 0x5f000001},
                 {0x8000000000000400, 0x5f000000},
                 {0x8000000000000401, 0x5f000000}};
-  WasmRunner<float> r(MachineType::Uint64());
+  WasmRunner<float> r(execution_mode, MachineType::Uint64());
   BUILD(r, WASM_F32_UCONVERT_I64(WASM_GET_LOCAL(0)));
   for (size_t i = 0; i < arraysize(values); i++) {
     CHECK_EQ(bit_cast<float>(values[i].expected), r.Call(values[i].input));
   }
 }
-// kExprF64SConvertI64:
-TEST(Run_WasmF64SConvertI64) {
+
+WASM_EXEC_TEST(F64SConvertI64) {
   REQUIRE(F64SConvertI64);
-  WasmRunner<double> r(MachineType::Int64());
+  WasmRunner<double> r(execution_mode, MachineType::Int64());
   BUILD(r, WASM_F64_SCONVERT_I64(WASM_GET_LOCAL(0)));
   FOR_INT64_INPUTS(i) { CHECK_DOUBLE_EQ(static_cast<double>(*i), r.Call(*i)); }
 }
-// kExprF64UConvertI64:
-TEST(Run_Wasm_F64UConvertI64) {
+
+WASM_EXEC_TEST(F64UConvertI64) {
   REQUIRE(F64UConvertI64);
   struct {
     uint64_t input;
@@ -735,16 +751,15 @@
                 {0x8000008000000001, 0x43e0000010000000},
                 {0x8000000000000400, 0x43e0000000000000},
                 {0x8000000000000401, 0x43e0000000000001}};
-  WasmRunner<double> r(MachineType::Uint64());
+  WasmRunner<double> r(execution_mode, MachineType::Uint64());
   BUILD(r, WASM_F64_UCONVERT_I64(WASM_GET_LOCAL(0)));
   for (size_t i = 0; i < arraysize(values); i++) {
     CHECK_EQ(bit_cast<double>(values[i].expected), r.Call(values[i].input));
   }
 }
-// kExprI64SConvertF32:
 
-TEST(Run_Wasm_I64SConvertF32a) {
-  WasmRunner<int64_t> r(MachineType::Float32());
+WASM_EXEC_TEST(I64SConvertF32a) {
+  WasmRunner<int64_t> r(execution_mode, MachineType::Float32());
   BUILD(r, WASM_I64_SCONVERT_F32(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT32_INPUTS(i) {
@@ -756,9 +771,9 @@
     }
   }
 }
-// kExprI64SConvertF64:
-TEST(Run_Wasm_I64SConvertF64a) {
-  WasmRunner<int64_t> r(MachineType::Float64());
+
+WASM_EXEC_TEST(I64SConvertF64a) {
+  WasmRunner<int64_t> r(execution_mode, MachineType::Float64());
   BUILD(r, WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT64_INPUTS(i) {
@@ -771,9 +786,8 @@
   }
 }
 
-// kExprI64UConvertF32:
-TEST(Run_Wasm_I64UConvertF32a) {
-  WasmRunner<uint64_t> r(MachineType::Float32());
+WASM_EXEC_TEST(I64UConvertF32a) {
+  WasmRunner<uint64_t> r(execution_mode, MachineType::Float32());
   BUILD(r, WASM_I64_UCONVERT_F32(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT32_INPUTS(i) {
@@ -786,9 +800,8 @@
   }
 }
 
-// kExprI64UConvertF64:
-TEST(Run_Wasm_I64UConvertF64a) {
-  WasmRunner<uint64_t> r(MachineType::Float64());
+WASM_EXEC_TEST(I64UConvertF64a) {
+  WasmRunner<uint64_t> r(execution_mode, MachineType::Float64());
   BUILD(r, WASM_I64_UCONVERT_F64(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT64_INPUTS(i) {
@@ -801,7 +814,7 @@
   }
 }
 
-TEST(Run_WasmCallI64Parameter) {
+WASM_EXEC_TEST(CallI64Parameter) {
   // Build the target function.
   LocalType param_types[20];
   for (int i = 0; i < 20; i++) param_types[i] = kAstI64;
@@ -809,7 +822,7 @@
   param_types[4] = kAstI32;
   FunctionSig sig(1, 19, param_types);
   for (int i = 0; i < 19; i++) {
-    TestingModule module;
+    TestingModule module(execution_mode);
     WasmFunctionCompiler t(&sig, &module);
     if (i == 2 || i == 3) {
       continue;
@@ -822,8 +835,8 @@
     WasmRunner<int32_t> r(&module);
     BUILD(
         r,
-        WASM_I32_CONVERT_I64(WASM_CALL_FUNCTION(
-            index, WASM_I64V_9(0xbcd12340000000b),
+        WASM_I32_CONVERT_I64(WASM_CALL_FUNCTIONN(
+            19, index, WASM_I64V_9(0xbcd12340000000b),
             WASM_I64V_9(0xbcd12340000000c), WASM_I32V_1(0xd),
             WASM_I32_CONVERT_I64(WASM_I64V_9(0xbcd12340000000e)),
             WASM_I64V_9(0xbcd12340000000f), WASM_I64V_10(0xbcd1234000000010),
@@ -839,43 +852,47 @@
   }
 }
 
-void TestI64Binop(WasmOpcode opcode, int64_t expected, int64_t a, int64_t b) {
+void TestI64Binop(WasmExecutionMode execution_mode, WasmOpcode opcode,
+                  int64_t expected, int64_t a, int64_t b) {
   {
-    WasmRunner<int64_t> r;
+    WasmRunner<int64_t> r(execution_mode);
     // return K op K
     BUILD(r, WASM_BINOP(opcode, WASM_I64V(a), WASM_I64V(b)));
     CHECK_EQ(expected, r.Call());
   }
   {
-    WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
+    WasmRunner<int64_t> r(execution_mode, MachineType::Int64(),
+                          MachineType::Int64());
     // return a op b
     BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
     CHECK_EQ(expected, r.Call(a, b));
   }
 }
 
-void TestI64Cmp(WasmOpcode opcode, int64_t expected, int64_t a, int64_t b) {
+void TestI64Cmp(WasmExecutionMode execution_mode, WasmOpcode opcode,
+                int64_t expected, int64_t a, int64_t b) {
   {
-    WasmRunner<int32_t> r;
+    WasmRunner<int32_t> r(execution_mode);
     // return K op K
     BUILD(r, WASM_BINOP(opcode, WASM_I64V(a), WASM_I64V(b)));
     CHECK_EQ(expected, r.Call());
   }
   {
-    WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
+    WasmRunner<int32_t> r(execution_mode, MachineType::Int64(),
+                          MachineType::Int64());
     // return a op b
     BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
     CHECK_EQ(expected, r.Call(a, b));
   }
 }
 
-#define TEST_I64_BINOP(name, expected, a, b)     \
-  do {                                           \
-    if (WASM_64 || kSupported_##name)            \
-      TestI64Binop(kExpr##name, expected, a, b); \
+#define TEST_I64_BINOP(name, expected, a, b)                     \
+  do {                                                           \
+    if (WASM_64 || kSupported_##name)                            \
+      TestI64Binop(execution_mode, kExpr##name, expected, a, b); \
   } while (false)
 
-TEST(Run_Wasm_I64Binops) {
+WASM_EXEC_TEST(I64Binops) {
   TEST_I64_BINOP(I64Add, -5586332274295447011, 0x501b72ebabc26847,
                  0x625de9793d8f79d6);
   TEST_I64_BINOP(I64Sub, 9001903251710731490, 0xf24fe6474640002e,
@@ -907,12 +924,13 @@
   TEST_I64_BINOP(I64Rol, 8728493013947314237, 0xe07af243ac4d219d, 15);
 }
 
-#define TEST_I64_CMP(name, expected, a, b)                                     \
-  do {                                                                         \
-    if (WASM_64 || kSupported_##name) TestI64Cmp(kExpr##name, expected, a, b); \
+#define TEST_I64_CMP(name, expected, a, b)                     \
+  do {                                                         \
+    if (WASM_64 || kSupported_##name)                          \
+      TestI64Cmp(execution_mode, kExpr##name, expected, a, b); \
   } while (false)
 
-TEST(Run_Wasm_I64Compare) {
+WASM_EXEC_TEST(I64Compare) {
   TEST_I64_CMP(I64Eq, 0, 0xB915D8FA494064F0, 0x04D700B2536019A3);
   TEST_I64_CMP(I64Ne, 1, 0xC2FAFAAAB0446CDC, 0x52A3328F780C97A3);
   TEST_I64_CMP(I64LtS, 0, 0x673636E6306B0578, 0x028EC9ECA78F7227);
@@ -925,7 +943,7 @@
   TEST_I64_CMP(I64GeU, 0, 0x0886A0C58C7AA224, 0x5DDBE5A81FD7EE47);
 }
 
-TEST(Run_Wasm_I64Clz) {
+WASM_EXEC_TEST(I64Clz) {
   REQUIRE(I64Clz);
   struct {
     int64_t expected;
@@ -964,14 +982,14 @@
                 {62, 0x0000000000000002}, {63, 0x0000000000000001},
                 {64, 0x0000000000000000}};
 
-  WasmRunner<int64_t> r(MachineType::Uint64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Uint64());
   BUILD(r, WASM_I64_CLZ(WASM_GET_LOCAL(0)));
   for (size_t i = 0; i < arraysize(values); i++) {
     CHECK_EQ(values[i].expected, r.Call(values[i].input));
   }
 }
 
-TEST(Run_Wasm_I64Ctz) {
+WASM_EXEC_TEST(I64Ctz) {
   REQUIRE(I64Ctz);
   struct {
     int64_t expected;
@@ -1010,14 +1028,14 @@
                 {2, 0x000000009afdbc84},  {1, 0x000000009afdbc82},
                 {0, 0x000000009afdbc81}};
 
-  WasmRunner<int64_t> r(MachineType::Uint64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Uint64());
   BUILD(r, WASM_I64_CTZ(WASM_GET_LOCAL(0)));
   for (size_t i = 0; i < arraysize(values); i++) {
     CHECK_EQ(values[i].expected, r.Call(values[i].input));
   }
 }
 
-TEST(Run_Wasm_I64Popcnt) {
+WASM_EXEC_TEST(I64Popcnt2) {
   REQUIRE(I64Popcnt);
   struct {
     int64_t expected;
@@ -1028,7 +1046,7 @@
                 {26, 0x1123456782345678},
                 {38, 0xffedcba09edcba09}};
 
-  WasmRunner<int64_t> r(MachineType::Uint64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Uint64());
   BUILD(r, WASM_I64_POPCNT(WASM_GET_LOCAL(0)));
   for (size_t i = 0; i < arraysize(values); i++) {
     CHECK_EQ(values[i].expected, r.Call(values[i].input));
@@ -1037,29 +1055,30 @@
 
 // Test the WasmRunner with an Int64 return value and different numbers of
 // Int64 parameters.
-TEST(Run_TestI64WasmRunner) {
+WASM_EXEC_TEST(I64WasmRunner) {
   REQUIRE(I64Param);
   REQUIRE(I64Xor);
-  {FOR_INT64_INPUTS(i){WasmRunner<int64_t> r;
+  {FOR_INT64_INPUTS(i){WasmRunner<int64_t> r(execution_mode);
   BUILD(r, WASM_I64V(*i));
   CHECK_EQ(*i, r.Call());
 }
 }
 {
-  WasmRunner<int64_t> r(MachineType::Int64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int64());
   BUILD(r, WASM_GET_LOCAL(0));
   FOR_INT64_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
 }
 {
-  WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_INT64_INPUTS(i) {
     FOR_INT64_INPUTS(j) { CHECK_EQ(*i ^ *j, r.Call(*i, *j)); }
   }
 }
 {
-  WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64(),
-                        MachineType::Int64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64(), MachineType::Int64());
   BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0),
                         WASM_I64_XOR(WASM_GET_LOCAL(1), WASM_GET_LOCAL(2))));
   FOR_INT64_INPUTS(i) {
@@ -1071,8 +1090,9 @@
   }
 }
 {
-  WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64(),
-                        MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64(), MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0),
                         WASM_I64_XOR(WASM_GET_LOCAL(1),
                                      WASM_I64_XOR(WASM_GET_LOCAL(2),
@@ -1088,18 +1108,18 @@
 }
 }
 
-TEST(Run_WasmCall_Int64Sub) {
+WASM_EXEC_TEST(Call_Int64Sub) {
   REQUIRE(I64Sub);
   // Build the target function.
   TestSignatures sigs;
-  TestingModule module;
+  TestingModule module(execution_mode);
   WasmFunctionCompiler t(sigs.l_ll(), &module);
   BUILD(t, WASM_I64_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   uint32_t index = t.CompileAndAdd();
 
   // Build the caller function.
   WasmRunner<int64_t> r(&module, MachineType::Int64(), MachineType::Int64());
-  BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  BUILD(r, WASM_CALL_FUNCTION2(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_INT32_INPUTS(i) {
     FOR_INT32_INPUTS(j) {
@@ -1115,23 +1135,27 @@
   }
 }
 
-TEST(Run_Wasm_LoadStoreI64_sx) {
+WASM_EXEC_TEST(LoadStoreI64_sx) {
   REQUIRE(I64LoadStore);
   REQUIRE(DepthFirst);
   byte loads[] = {kExprI64LoadMem8S, kExprI64LoadMem16S, kExprI64LoadMem32S,
                   kExprI64LoadMem};
 
   for (size_t m = 0; m < arraysize(loads); m++) {
-    TestingModule module;
+    TestingModule module(execution_mode);
     byte* memory = module.AddMemoryElems<byte>(16);
     WasmRunner<int64_t> r(&module);
 
-    byte code[] = {kExprI64StoreMem, ZERO_ALIGNMENT,
-                   ZERO_OFFSET,          // --
-                   kExprI8Const,     8,  // --
-                   loads[m],         ZERO_ALIGNMENT,
-                   ZERO_OFFSET,           // --
-                   kExprI8Const,     0};  // --
+    byte code[] = {
+        kExprI8Const,     8,  // --
+        kExprI8Const,     0,  // --
+        loads[m],             // --
+        ZERO_ALIGNMENT,       // --
+        ZERO_OFFSET,          // --
+        kExprI64StoreMem,     // --
+        ZERO_ALIGNMENT,       // --
+        ZERO_OFFSET           // --
+    };
 
     r.Build(code, code + arraysize(code));
 
@@ -1152,9 +1176,9 @@
   }
 }
 
-TEST(Run_Wasm_I64SConvertF32b) {
+WASM_EXEC_TEST(I64SConvertF32b) {
   REQUIRE(I64SConvertF32);
-  WasmRunner<int64_t> r(MachineType::Float32());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Float32());
   BUILD(r, WASM_I64_SCONVERT_F32(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT32_INPUTS(i) {
@@ -1167,9 +1191,9 @@
   }
 }
 
-TEST(Run_Wasm_I64SConvertF64b) {
+WASM_EXEC_TEST(I64SConvertF64b) {
   REQUIRE(I64SConvertF64);
-  WasmRunner<int64_t> r(MachineType::Float64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Float64());
   BUILD(r, WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT64_INPUTS(i) {
@@ -1182,9 +1206,9 @@
   }
 }
 
-TEST(Run_Wasm_I64UConvertF32b) {
+WASM_EXEC_TEST(I64UConvertF32b) {
   REQUIRE(I64UConvertF32);
-  WasmRunner<uint64_t> r(MachineType::Float32());
+  WasmRunner<uint64_t> r(execution_mode, MachineType::Float32());
   BUILD(r, WASM_I64_UCONVERT_F32(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT32_INPUTS(i) {
@@ -1196,9 +1220,9 @@
   }
 }
 
-TEST(Run_Wasm_I64UConvertF64b) {
+WASM_EXEC_TEST(I64UConvertF64b) {
   REQUIRE(I64UConvertF64);
-  WasmRunner<uint64_t> r(MachineType::Float64());
+  WasmRunner<uint64_t> r(execution_mode, MachineType::Float64());
   BUILD(r, WASM_I64_UCONVERT_F64(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT64_INPUTS(i) {
@@ -1210,9 +1234,9 @@
   }
 }
 
-TEST(Run_Wasm_I64ReinterpretF64) {
+WASM_EXEC_TEST(I64ReinterpretF64) {
   REQUIRE(I64ReinterpretF64);
-  TestingModule module;
+  TestingModule module(execution_mode);
   int64_t* memory = module.AddMemoryElems<int64_t>(8);
   WasmRunner<int64_t> r(&module);
 
@@ -1226,9 +1250,9 @@
   }
 }
 
-TEST(Run_Wasm_F64ReinterpretI64) {
+WASM_EXEC_TEST(F64ReinterpretI64) {
   REQUIRE(F64ReinterpretI64);
-  TestingModule module;
+  TestingModule module(execution_mode);
   int64_t* memory = module.AddMemoryElems<int64_t>(8);
   WasmRunner<int64_t> r(&module, MachineType::Int64());
 
@@ -1244,9 +1268,9 @@
   }
 }
 
-TEST(Run_Wasm_LoadMemI64) {
+WASM_EXEC_TEST(LoadMemI64) {
   REQUIRE(I64LoadStore);
-  TestingModule module;
+  TestingModule module(execution_mode);
   int64_t* memory = module.AddMemoryElems<int64_t>(8);
   module.RandomizeMemory(1111);
   WasmRunner<int64_t> r(&module);
@@ -1263,13 +1287,35 @@
   CHECK_EQ(77777777, r.Call());
 }
 
-TEST(Run_Wasm_MemI64_Sum) {
+WASM_EXEC_TEST(LoadMemI64_alignment) {
+  REQUIRE(I64LoadStore);
+  TestingModule module(execution_mode);
+  int64_t* memory = module.AddMemoryElems<int64_t>(8);
+  for (byte alignment = 0; alignment <= 3; alignment++) {
+    module.RandomizeMemory(1111);
+    WasmRunner<int64_t> r(&module);
+
+    BUILD(r,
+          WASM_LOAD_MEM_ALIGNMENT(MachineType::Int64(), WASM_I8(0), alignment));
+
+    memory[0] = 0xaabbccdd00112233LL;
+    CHECK_EQ(0xaabbccdd00112233LL, r.Call());
+
+    memory[0] = 0x33aabbccdd001122LL;
+    CHECK_EQ(0x33aabbccdd001122LL, r.Call());
+
+    memory[0] = 77777777;
+    CHECK_EQ(77777777, r.Call());
+  }
+}
+
+WASM_EXEC_TEST(MemI64_Sum) {
   REQUIRE(I64LoadStore);
   REQUIRE(I64Add);
   REQUIRE(I64Sub);
   REQUIRE(I64Phi);
   const int kNumElems = 20;
-  TestingModule module;
+  TestingModule module(execution_mode);
   uint64_t* memory = module.AddMemoryElems<uint64_t>(kNumElems);
   WasmRunner<uint64_t> r(&module, MachineType::Int32());
   const byte kSum = r.AllocateLocal(kAstI64);
@@ -1299,12 +1345,29 @@
   }
 }
 
-TEST(Run_Wasm_I64Global) {
+WASM_EXEC_TEST(StoreMemI64_alignment) {
+  TestingModule module(execution_mode);
+  int64_t* memory = module.AddMemoryElems<int64_t>(4);
+  const int64_t kWritten = 0x12345678abcd0011ll;
+
+  for (byte i = 0; i <= 3; i++) {
+    WasmRunner<int64_t> r(&module, MachineType::Int64());
+    BUILD(r, WASM_STORE_MEM_ALIGNMENT(MachineType::Int64(), WASM_ZERO, i,
+                                      WASM_GET_LOCAL(0)));
+    module.RandomizeMemory(1111);
+    memory[0] = 0;
+
+    CHECK_EQ(kWritten, r.Call(kWritten));
+    CHECK_EQ(kWritten, memory[0]);
+  }
+}
+
+WASM_EXEC_TEST(I64Global) {
   REQUIRE(I64LoadStore);
   REQUIRE(I64SConvertI32);
   REQUIRE(I64And);
   REQUIRE(DepthFirst);
-  TestingModule module;
+  TestingModule module(execution_mode);
   int64_t* global = module.AddGlobal<int64_t>(MachineType::Int64());
   WasmRunner<int32_t> r(&module, MachineType::Int32());
   // global = global + p0
@@ -1321,10 +1384,10 @@
   }
 }
 
-TEST(Run_Wasm_I64Eqz) {
+WASM_EXEC_TEST(I64Eqz) {
   REQUIRE(I64Eq);
 
-  WasmRunner<int32_t> r(MachineType::Int64());
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int64());
   BUILD(r, WASM_I64_EQZ(WASM_GET_LOCAL(0)));
 
   FOR_INT64_INPUTS(i) {
@@ -1333,9 +1396,10 @@
   }
 }
 
-TEST(Run_Wasm_I64Ror) {
+WASM_EXEC_TEST(I64Ror) {
   REQUIRE(I64Ror);
-  WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_ROR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_UINT64_INPUTS(i) {
@@ -1346,9 +1410,10 @@
   }
 }
 
-TEST(Run_Wasm_I64Rol) {
+WASM_EXEC_TEST(I64Rol) {
   REQUIRE(I64Rol);
-  WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
+  WasmRunner<int64_t> r(execution_mode, MachineType::Int64(),
+                        MachineType::Int64());
   BUILD(r, WASM_I64_ROL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_UINT64_INPUTS(i) {
@@ -1358,3 +1423,153 @@
     }
   }
 }
+
+WASM_EXEC_TEST(StoreMem_offset_oob_i64) {
+  TestingModule module(execution_mode);
+  byte* memory = module.AddMemoryElems<byte>(32);
+
+  static const MachineType machineTypes[] = {
+      MachineType::Int8(),   MachineType::Uint8(),  MachineType::Int16(),
+      MachineType::Uint16(), MachineType::Int32(),  MachineType::Uint32(),
+      MachineType::Int64(),  MachineType::Uint64(), MachineType::Float32(),
+      MachineType::Float64()};
+
+  for (size_t m = 0; m < arraysize(machineTypes); m++) {
+    module.RandomizeMemory(1119 + static_cast<int>(m));
+    WasmRunner<int32_t> r(&module, MachineType::Uint32());
+
+    BUILD(r, WASM_STORE_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0),
+                                   WASM_LOAD_MEM(machineTypes[m], WASM_ZERO)),
+          WASM_ZERO);
+
+    byte memsize = WasmOpcodes::MemSize(machineTypes[m]);
+    uint32_t boundary = 24 - memsize;
+    CHECK_EQ(0, r.Call(boundary));  // in bounds.
+    CHECK_EQ(0, memcmp(&memory[0], &memory[8 + boundary], memsize));
+
+    for (uint32_t offset = boundary + 1; offset < boundary + 19; offset++) {
+      CHECK_TRAP(r.Call(offset));  // out of bounds.
+    }
+  }
+}
+
+#define ADD_CODE(vec, ...)                                              \
+  do {                                                                  \
+    byte __buf[] = {__VA_ARGS__};                                       \
+    for (size_t i = 0; i < sizeof(__buf); i++) vec.push_back(__buf[i]); \
+  } while (false)
+
+static void CompileCallIndirectMany(LocalType param) {
+  // Make sure we don't run out of registers when compiling indirect calls
+  // with many many parameters.
+  TestSignatures sigs;
+  for (byte num_params = 0; num_params < 40; num_params++) {
+    v8::base::AccountingAllocator allocator;
+    Zone zone(&allocator);
+    HandleScope scope(CcTest::InitIsolateOnce());
+    TestingModule module(kExecuteCompiled);
+    FunctionSig* sig = sigs.many(&zone, kAstStmt, param, num_params);
+
+    module.AddSignature(sig);
+    module.AddSignature(sig);
+    module.AddIndirectFunctionTable(nullptr, 0);
+
+    WasmFunctionCompiler t(sig, &module);
+
+    std::vector<byte> code;
+    ADD_CODE(code, kExprI8Const, 0);
+    for (byte p = 0; p < num_params; p++) {
+      ADD_CODE(code, kExprGetLocal, p);
+    }
+    ADD_CODE(code, kExprCallIndirect, static_cast<byte>(num_params), 1);
+
+    t.Build(&code[0], &code[0] + code.size());
+    t.Compile();
+  }
+}
+
+TEST(Compile_Wasm_CallIndirect_Many_i64) { CompileCallIndirectMany(kAstI64); }
+
+static void Run_WasmMixedCall_N(WasmExecutionMode execution_mode, int start) {
+  const int kExpected = 6333;
+  const int kElemSize = 8;
+  TestSignatures sigs;
+
+  static MachineType mixed[] = {
+      MachineType::Int32(),   MachineType::Float32(), MachineType::Int64(),
+      MachineType::Float64(), MachineType::Float32(), MachineType::Int64(),
+      MachineType::Int32(),   MachineType::Float64(), MachineType::Float32(),
+      MachineType::Float64(), MachineType::Int32(),   MachineType::Int64(),
+      MachineType::Int32(),   MachineType::Int32()};
+
+  int num_params = static_cast<int>(arraysize(mixed)) - start;
+  for (int which = 0; which < num_params; which++) {
+    v8::base::AccountingAllocator allocator;
+    Zone zone(&allocator);
+    TestingModule module(execution_mode);
+    module.AddMemory(1024);
+    MachineType* memtypes = &mixed[start];
+    MachineType result = memtypes[which];
+
+    // =========================================================================
+    // Build the selector function.
+    // =========================================================================
+    uint32_t index;
+    FunctionSig::Builder b(&zone, 1, num_params);
+    b.AddReturn(WasmOpcodes::LocalTypeFor(result));
+    for (int i = 0; i < num_params; i++) {
+      b.AddParam(WasmOpcodes::LocalTypeFor(memtypes[i]));
+    }
+    WasmFunctionCompiler t(b.Build(), &module);
+    BUILD(t, WASM_GET_LOCAL(which));
+    index = t.CompileAndAdd();
+
+    // =========================================================================
+    // Build the calling function.
+    // =========================================================================
+    WasmRunner<int32_t> r(&module);
+    std::vector<byte> code;
+
+    // Load the offset for the store.
+    ADD_CODE(code, WASM_ZERO);
+
+    // Load the arguments.
+    for (int i = 0; i < num_params; i++) {
+      int offset = (i + 1) * kElemSize;
+      ADD_CODE(code, WASM_LOAD_MEM(memtypes[i], WASM_I8(offset)));
+    }
+
+    // Call the selector function.
+    ADD_CODE(code, kExprCallFunction, static_cast<byte>(num_params),
+             static_cast<byte>(index));
+
+    // Store the result in memory.
+    ADD_CODE(code,
+             static_cast<byte>(WasmOpcodes::LoadStoreOpcodeOf(result, true)),
+             ZERO_ALIGNMENT, ZERO_OFFSET);
+
+    // Return the expected value.
+    ADD_CODE(code, WASM_I32V_2(kExpected));
+
+    r.Build(&code[0], &code[0] + code.size());
+
+    // Run the code.
+    for (int t = 0; t < 10; t++) {
+      module.RandomizeMemory();
+      CHECK_EQ(kExpected, r.Call());
+
+      int size = WasmOpcodes::MemSize(result);
+      for (int i = 0; i < size; i++) {
+        int base = (which + 1) * kElemSize;
+        byte expected = module.raw_mem_at<byte>(base + i);
+        byte result = module.raw_mem_at<byte>(i);
+        CHECK_EQ(expected, result);
+      }
+    }
+  }
+}
+
+WASM_EXEC_TEST(MixedCall_i64_0) { Run_WasmMixedCall_N(execution_mode, 0); }
+WASM_EXEC_TEST(MixedCall_i64_1) { Run_WasmMixedCall_N(execution_mode, 1); }
+WASM_EXEC_TEST(MixedCall_i64_2) { Run_WasmMixedCall_N(execution_mode, 2); }
+WASM_EXEC_TEST(MixedCall_i64_3) { Run_WasmMixedCall_N(execution_mode, 3); }
diff --git a/test/cctest/wasm/test-run-wasm-asmjs.cc b/test/cctest/wasm/test-run-wasm-asmjs.cc
new file mode 100644
index 0000000..4d39dd6
--- /dev/null
+++ b/test/cctest/wasm/test-run-wasm-asmjs.cc
@@ -0,0 +1,297 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "src/base/platform/elapsed-timer.h"
+
+#include "src/wasm/wasm-macro-gen.h"
+
+#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/value-helper.h"
+#include "test/cctest/wasm/test-signatures.h"
+#include "test/cctest/wasm/wasm-run-utils.h"
+
+using namespace v8::base;
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+using namespace v8::internal::wasm;
+
+// for even shorter tests.
+#define B2(a, b) kExprBlock, a, b, kExprEnd
+#define B1(a) kExprBlock, a, kExprEnd
+#define RET(x) x, kExprReturn, 1
+#define RET_I8(x) kExprI8Const, x, kExprReturn, 1
+
+namespace {
+uint32_t GetMatchingRelocInfoCount(Handle<Code> code, RelocInfo::Mode rmode) {
+  int filter = 1 << rmode;
+  uint32_t ret = 0;
+  for (RelocIterator it(*code, filter); !it.done(); it.next()) {
+    ++ret;
+  }
+  return ret;
+}
+}
+
+WASM_EXEC_TEST(Int32AsmjsDivS) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
+  BUILD(r, WASM_BINOP(kExprI32AsmjsDivS, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  const int32_t kMin = std::numeric_limits<int32_t>::min();
+  CHECK_EQ(0, r.Call(0, 100));
+  CHECK_EQ(0, r.Call(100, 0));
+  CHECK_EQ(0, r.Call(-1001, 0));
+  CHECK_EQ(kMin, r.Call(kMin, -1));
+  CHECK_EQ(0, r.Call(kMin, 0));
+}
+
+WASM_EXEC_TEST(Int32AsmjsRemS) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
+  BUILD(r, WASM_BINOP(kExprI32AsmjsRemS, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  const int32_t kMin = std::numeric_limits<int32_t>::min();
+  CHECK_EQ(33, r.Call(133, 100));
+  CHECK_EQ(0, r.Call(kMin, -1));
+  CHECK_EQ(0, r.Call(100, 0));
+  CHECK_EQ(0, r.Call(-1001, 0));
+  CHECK_EQ(0, r.Call(kMin, 0));
+}
+
+WASM_EXEC_TEST(Int32AsmjsDivU) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
+  BUILD(r, WASM_BINOP(kExprI32AsmjsDivU, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  const int32_t kMin = std::numeric_limits<int32_t>::min();
+  CHECK_EQ(0, r.Call(0, 100));
+  CHECK_EQ(0, r.Call(kMin, -1));
+  CHECK_EQ(0, r.Call(100, 0));
+  CHECK_EQ(0, r.Call(-1001, 0));
+  CHECK_EQ(0, r.Call(kMin, 0));
+}
+
+WASM_EXEC_TEST(Int32AsmjsRemU) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
+  BUILD(r, WASM_BINOP(kExprI32AsmjsRemU, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  const int32_t kMin = std::numeric_limits<int32_t>::min();
+  CHECK_EQ(17, r.Call(217, 100));
+  CHECK_EQ(0, r.Call(100, 0));
+  CHECK_EQ(0, r.Call(-1001, 0));
+  CHECK_EQ(0, r.Call(kMin, 0));
+  CHECK_EQ(kMin, r.Call(kMin, -1));
+}
+
+WASM_EXEC_TEST(I32AsmjsSConvertF32) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Float32());
+  BUILD(r, WASM_UNOP(kExprI32AsmjsSConvertF32, WASM_GET_LOCAL(0)));
+
+  FOR_FLOAT32_INPUTS(i) {
+    int32_t expected = DoubleToInt32(*i);
+    CHECK_EQ(expected, r.Call(*i));
+  }
+}
+
+WASM_EXEC_TEST(I32AsmjsSConvertF64) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Float64());
+  BUILD(r, WASM_UNOP(kExprI32AsmjsSConvertF64, WASM_GET_LOCAL(0)));
+
+  FOR_FLOAT64_INPUTS(i) {
+    int32_t expected = DoubleToInt32(*i);
+    CHECK_EQ(expected, r.Call(*i));
+  }
+}
+
+WASM_EXEC_TEST(I32AsmjsUConvertF32) {
+  WasmRunner<uint32_t> r(execution_mode, MachineType::Float32());
+  BUILD(r, WASM_UNOP(kExprI32AsmjsUConvertF32, WASM_GET_LOCAL(0)));
+
+  FOR_FLOAT32_INPUTS(i) {
+    uint32_t expected = DoubleToUint32(*i);
+    CHECK_EQ(expected, r.Call(*i));
+  }
+}
+
+WASM_EXEC_TEST(I32AsmjsUConvertF64) {
+  WasmRunner<uint32_t> r(execution_mode, MachineType::Float64());
+  BUILD(r, WASM_UNOP(kExprI32AsmjsUConvertF64, WASM_GET_LOCAL(0)));
+
+  FOR_FLOAT64_INPUTS(i) {
+    uint32_t expected = DoubleToUint32(*i);
+    CHECK_EQ(expected, r.Call(*i));
+  }
+}
+
+WASM_EXEC_TEST(LoadMemI32_oob_asm) {
+  TestingModule module(execution_mode);
+  int32_t* memory = module.AddMemoryElems<int32_t>(8);
+  WasmRunner<int32_t> r(&module, MachineType::Uint32());
+  module.RandomizeMemory(1112);
+
+  BUILD(r, WASM_UNOP(kExprI32AsmjsLoadMem, WASM_GET_LOCAL(0)));
+
+  memory[0] = 999999;
+  CHECK_EQ(999999, r.Call(0u));
+  // TODO(titzer): offset 29-31 should also be OOB.
+  for (uint32_t offset = 32; offset < 40; offset++) {
+    CHECK_EQ(0, r.Call(offset));
+  }
+
+  for (uint32_t offset = 0x80000000; offset < 0x80000010; offset++) {
+    CHECK_EQ(0, r.Call(offset));
+  }
+}
+
+WASM_EXEC_TEST(LoadMemF32_oob_asm) {
+  TestingModule module(execution_mode);
+  float* memory = module.AddMemoryElems<float>(8);
+  WasmRunner<float> r(&module, MachineType::Uint32());
+  module.RandomizeMemory(1112);
+
+  BUILD(r, WASM_UNOP(kExprF32AsmjsLoadMem, WASM_GET_LOCAL(0)));
+
+  memory[0] = 9999.5f;
+  CHECK_EQ(9999.5f, r.Call(0u));
+  // TODO(titzer): offset 29-31 should also be OOB.
+  for (uint32_t offset = 32; offset < 40; offset++) {
+    CHECK(std::isnan(r.Call(offset)));
+  }
+
+  for (uint32_t offset = 0x80000000; offset < 0x80000010; offset++) {
+    CHECK(std::isnan(r.Call(offset)));
+  }
+}
+
+WASM_EXEC_TEST(LoadMemF64_oob_asm) {
+  TestingModule module(execution_mode);
+  double* memory = module.AddMemoryElems<double>(8);
+  WasmRunner<double> r(&module, MachineType::Uint32());
+  module.RandomizeMemory(1112);
+
+  BUILD(r, WASM_UNOP(kExprF64AsmjsLoadMem, WASM_GET_LOCAL(0)));
+
+  memory[0] = 9799.5;
+  CHECK_EQ(9799.5, r.Call(0u));
+  memory[1] = 11799.25;
+  CHECK_EQ(11799.25, r.Call(8u));
+  // TODO(titzer): offset 57-63 should also be OOB.
+  for (uint32_t offset = 64; offset < 80; offset++) {
+    CHECK(std::isnan(r.Call(offset)));
+  }
+
+  for (uint32_t offset = 0x80000000; offset < 0x80000010; offset++) {
+    CHECK(std::isnan(r.Call(offset)));
+  }
+}
+
+WASM_EXEC_TEST(StoreMemI32_oob_asm) {
+  TestingModule module(execution_mode);
+  int32_t* memory = module.AddMemoryElems<int32_t>(8);
+  WasmRunner<int32_t> r(&module, MachineType::Uint32(), MachineType::Uint32());
+  module.RandomizeMemory(1112);
+
+  BUILD(r, WASM_BINOP(kExprI32AsmjsStoreMem, WASM_GET_LOCAL(0),
+                      WASM_GET_LOCAL(1)));
+
+  memory[0] = 7777;
+  CHECK_EQ(999999, r.Call(0u, 999999));
+  CHECK_EQ(999999, memory[0]);
+  // TODO(titzer): offset 29-31 should also be OOB.
+  for (uint32_t offset = 32; offset < 40; offset++) {
+    CHECK_EQ(8888, r.Call(offset, 8888));
+  }
+
+  for (uint32_t offset = 0x10000000; offset < 0xF0000000; offset += 0x1000000) {
+    CHECK_EQ(7777, r.Call(offset, 7777));
+  }
+}
+
+#define FOREACH_INT_CHECKED_LOAD_OP(TEST_BODY) \
+  TEST_BODY(kExprI32AsmjsLoadMem8S)            \
+  TEST_BODY(kExprI32AsmjsLoadMem8U)            \
+  TEST_BODY(kExprI32AsmjsLoadMem16S)           \
+  TEST_BODY(kExprI32AsmjsLoadMem16U)           \
+  TEST_BODY(kExprI32AsmjsLoadMem)
+
+#define FOREACH_INT_CHECKED_STORE_OP(TEST_BODY) \
+  TEST_BODY(kExprI32AsmjsStoreMem8)             \
+  TEST_BODY(kExprI32AsmjsStoreMem16)            \
+  TEST_BODY(kExprI32AsmjsStoreMem)
+
+#define INT_LOAD_TEST(OP_TYPE)                                                \
+  TEST(RunWasm_AsmCheckedRelocInfo##OP_TYPE) {                                \
+    TestingModule module(kExecuteCompiled);                                   \
+    WasmRunner<int32_t> r(&module, MachineType::Uint32());                    \
+    BUILD(r, WASM_UNOP(OP_TYPE, WASM_GET_LOCAL(0)));                          \
+    CHECK_EQ(1, GetMatchingRelocInfoCount(module.instance->function_code[0],  \
+                                          RelocInfo::WASM_MEMORY_REFERENCE)); \
+    CHECK_NE(                                                                 \
+        0, GetMatchingRelocInfoCount(module.instance->function_code[0],       \
+                                     RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); \
+  }
+
+FOREACH_INT_CHECKED_LOAD_OP(INT_LOAD_TEST)
+
+#define INT_STORE_TEST(OP_TYPE)                                               \
+  TEST(RunWasm_AsmCheckedRelocInfo##OP_TYPE) {                                \
+    TestingModule module(kExecuteCompiled);                                   \
+    WasmRunner<int32_t> r(&module, MachineType::Uint32(),                     \
+                          MachineType::Uint32());                             \
+    BUILD(r, WASM_BINOP(OP_TYPE, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));      \
+    CHECK_EQ(1, GetMatchingRelocInfoCount(module.instance->function_code[0],  \
+                                          RelocInfo::WASM_MEMORY_REFERENCE)); \
+    CHECK_NE(                                                                 \
+        0, GetMatchingRelocInfoCount(module.instance->function_code[0],       \
+                                     RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); \
+  }
+
+FOREACH_INT_CHECKED_STORE_OP(INT_STORE_TEST)
+
+TEST(RunWasm_AsmCheckedLoadFloat32RelocInfo) {
+  TestingModule module(kExecuteCompiled);
+  WasmRunner<float> r(&module, MachineType::Uint32());
+  BUILD(r, WASM_UNOP(kExprF32AsmjsLoadMem, WASM_GET_LOCAL(0)));
+
+  CHECK_EQ(1, GetMatchingRelocInfoCount(module.instance->function_code[0],
+                                        RelocInfo::WASM_MEMORY_REFERENCE));
+  CHECK_NE(0, GetMatchingRelocInfoCount(module.instance->function_code[0],
+                                        RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
+}
+
+TEST(RunWasm_AsmCheckedStoreFloat32RelocInfo) {
+  TestingModule module(kExecuteCompiled);
+  WasmRunner<float> r(&module, MachineType::Uint32(), MachineType::Float32());
+  BUILD(r, WASM_BINOP(kExprF32AsmjsStoreMem, WASM_GET_LOCAL(0),
+                      WASM_GET_LOCAL(1)));
+
+  CHECK_EQ(1, GetMatchingRelocInfoCount(module.instance->function_code[0],
+                                        RelocInfo::WASM_MEMORY_REFERENCE));
+  CHECK_NE(0, GetMatchingRelocInfoCount(module.instance->function_code[0],
+                                        RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
+}
+
+TEST(RunWasm_AsmCheckedLoadFloat64RelocInfo) {
+  TestingModule module(kExecuteCompiled);
+  WasmRunner<double> r(&module, MachineType::Uint32());
+  BUILD(r, WASM_UNOP(kExprF64AsmjsLoadMem, WASM_GET_LOCAL(0)));
+
+  CHECK_EQ(1, GetMatchingRelocInfoCount(module.instance->function_code[0],
+                                        RelocInfo::WASM_MEMORY_REFERENCE));
+  CHECK_NE(0, GetMatchingRelocInfoCount(module.instance->function_code[0],
+                                        RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
+}
+
+TEST(RunWasm_AsmCheckedStoreFloat64RelocInfo) {
+  TestingModule module(kExecuteCompiled);
+  WasmRunner<double> r(&module, MachineType::Uint32(), MachineType::Float64());
+  BUILD(r, WASM_BINOP(kExprF64AsmjsStoreMem, WASM_GET_LOCAL(0),
+                      WASM_GET_LOCAL(1)));
+
+  CHECK_EQ(1, GetMatchingRelocInfoCount(module.instance->function_code[0],
+                                        RelocInfo::WASM_MEMORY_REFERENCE));
+  CHECK_NE(0, GetMatchingRelocInfoCount(module.instance->function_code[0],
+                                        RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
+}
diff --git a/test/cctest/wasm/test-run-wasm-interpreter.cc b/test/cctest/wasm/test-run-wasm-interpreter.cc
new file mode 100644
index 0000000..42b0f88
--- /dev/null
+++ b/test/cctest/wasm/test-run-wasm-interpreter.cc
@@ -0,0 +1,289 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "src/wasm/wasm-macro-gen.h"
+
+#include "src/wasm/wasm-interpreter.h"
+
+#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/value-helper.h"
+#include "test/cctest/wasm/test-signatures.h"
+#include "test/cctest/wasm/wasm-run-utils.h"
+
+using namespace v8::base;
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+using namespace v8::internal::wasm;
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+TEST(Run_WasmInt8Const_i) {
+  WasmRunner<int32_t> r(kExecuteInterpreted);
+  const byte kExpectedValue = 109;
+  // return(kExpectedValue)
+  BUILD(r, WASM_I8(kExpectedValue));
+  CHECK_EQ(kExpectedValue, r.Call());
+}
+
+TEST(Run_WasmIfElse) {
+  WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Int32());
+  BUILD(r, WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_I8(9), WASM_I8(10)));
+  CHECK_EQ(10, r.Call(0));
+  CHECK_EQ(9, r.Call(1));
+}
+
+TEST(Run_WasmIfReturn) {
+  WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Int32());
+  BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_RETURN1(WASM_I8(77))), WASM_I8(65));
+  CHECK_EQ(65, r.Call(0));
+  CHECK_EQ(77, r.Call(1));
+}
+
+TEST(Run_WasmNopsN) {
+  const int kMaxNops = 10;
+  byte code[kMaxNops + 2];
+  for (int nops = 0; nops < kMaxNops; nops++) {
+    byte expected = static_cast<byte>(20 + nops);
+    memset(code, kExprNop, sizeof(code));
+    code[nops] = kExprI8Const;
+    code[nops + 1] = expected;
+
+    WasmRunner<int32_t> r(kExecuteInterpreted);
+    r.Build(code, code + nops + 2);
+    CHECK_EQ(expected, r.Call());
+  }
+}
+
+TEST(Run_WasmConstsN) {
+  const int kMaxConsts = 10;
+  byte code[kMaxConsts * 2];
+  for (int count = 1; count < kMaxConsts; count++) {
+    for (int i = 0; i < count; i++) {
+      code[i * 2] = kExprI8Const;
+      code[i * 2 + 1] = static_cast<byte>(count * 10 + i);
+    }
+    byte expected = static_cast<byte>(count * 11 - 1);
+
+    WasmRunner<int32_t> r(kExecuteInterpreted);
+    r.Build(code, code + (count * 2));
+    CHECK_EQ(expected, r.Call());
+  }
+}
+
+TEST(Run_WasmBlocksN) {
+  const int kMaxNops = 10;
+  const int kExtra = 4;
+  byte code[kMaxNops + kExtra];
+  for (int nops = 0; nops < kMaxNops; nops++) {
+    byte expected = static_cast<byte>(30 + nops);
+    memset(code, kExprNop, sizeof(code));
+    code[0] = kExprBlock;
+    code[1 + nops] = kExprI8Const;
+    code[1 + nops + 1] = expected;
+    code[1 + nops + 2] = kExprEnd;
+
+    WasmRunner<int32_t> r(kExecuteInterpreted);
+    r.Build(code, code + nops + kExtra);
+    CHECK_EQ(expected, r.Call());
+  }
+}
+
+TEST(Run_WasmBlockBreakN) {
+  const int kMaxNops = 10;
+  const int kExtra = 6;
+  byte code[kMaxNops + kExtra];
+  for (int nops = 0; nops < kMaxNops; nops++) {
+    // Place the break anywhere within the block.
+    for (int index = 0; index < nops; index++) {
+      memset(code, kExprNop, sizeof(code));
+      code[0] = kExprBlock;
+      code[sizeof(code) - 1] = kExprEnd;
+
+      int expected = nops * 11 + index;
+      code[1 + index + 0] = kExprI8Const;
+      code[1 + index + 1] = static_cast<byte>(expected);
+      code[1 + index + 2] = kExprBr;
+      code[1 + index + 3] = ARITY_1;
+      code[1 + index + 4] = 0;
+
+      WasmRunner<int32_t> r(kExecuteInterpreted);
+      r.Build(code, code + kMaxNops + kExtra);
+      CHECK_EQ(expected, r.Call());
+    }
+  }
+}
+
+TEST(Run_Wasm_nested_ifs_i) {
+  WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Int32(),
+                        MachineType::Int32());
+
+  BUILD(r, WASM_IF_ELSE(
+               WASM_GET_LOCAL(0),
+               WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_I8(11), WASM_I8(12)),
+               WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_I8(13), WASM_I8(14))));
+
+  CHECK_EQ(11, r.Call(1, 1));
+  CHECK_EQ(12, r.Call(1, 0));
+  CHECK_EQ(13, r.Call(0, 1));
+  CHECK_EQ(14, r.Call(0, 0));
+}
+
+// Make tests more robust by not hard-coding offsets of various operations.
+// The {Find} method finds the offsets for the given bytecodes, returning
+// the offsets in an array.
+SmartArrayPointer<int> Find(byte* code, size_t code_size, int n, ...) {
+  va_list vl;
+  va_start(vl, n);
+
+  SmartArrayPointer<int> offsets(new int[n]);
+
+  for (int i = 0; i < n; i++) {
+    offsets[i] = -1;
+  }
+
+  int pos = 0;
+  WasmOpcode current = static_cast<WasmOpcode>(va_arg(vl, int));
+  for (size_t i = 0; i < code_size; i++) {
+    if (code[i] == current) {
+      offsets[pos++] = static_cast<int>(i);
+      if (pos == n) break;
+      current = static_cast<WasmOpcode>(va_arg(vl, int));
+    }
+  }
+  va_end(vl);
+
+  return offsets;
+}
+
+TEST(Breakpoint_I32Add) {
+  static const int kLocalsDeclSize = 1;
+  static const int kNumBreakpoints = 3;
+  byte code[] = {WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))};
+  SmartArrayPointer<int> offsets =
+      Find(code, sizeof(code), kNumBreakpoints, kExprGetLocal, kExprGetLocal,
+           kExprI32Add);
+
+  WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Uint32(),
+                        MachineType::Uint32());
+
+  r.Build(code, code + arraysize(code));
+
+  WasmInterpreter* interpreter = r.interpreter();
+  WasmInterpreter::Thread* thread = interpreter->GetThread(0);
+  for (int i = 0; i < kNumBreakpoints; i++) {
+    interpreter->SetBreakpoint(r.function(), kLocalsDeclSize + offsets[i],
+                               true);
+  }
+
+  FOR_UINT32_INPUTS(a) {
+    for (uint32_t b = 11; b < 3000000000u; b += 1000000000u) {
+      thread->Reset();
+      WasmVal args[] = {WasmVal(*a), WasmVal(b)};
+      thread->PushFrame(r.function(), args);
+
+      for (int i = 0; i < kNumBreakpoints; i++) {
+        thread->Run();  // run to next breakpoint
+        // Check the thread stopped at the right pc.
+        CHECK_EQ(WasmInterpreter::PAUSED, thread->state());
+        CHECK_EQ(kLocalsDeclSize + offsets[i], thread->GetBreakpointPc());
+      }
+
+      thread->Run();  // run to completion
+
+      // Check the thread finished with the right value.
+      CHECK_EQ(WasmInterpreter::FINISHED, thread->state());
+      uint32_t expected = (*a) + (b);
+      CHECK_EQ(expected, thread->GetReturnValue().to<uint32_t>());
+    }
+  }
+}
+
+TEST(Step_I32Mul) {
+  static const int kTraceLength = 4;
+  byte code[] = {WASM_I32_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))};
+
+  WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Uint32(),
+                        MachineType::Uint32());
+
+  r.Build(code, code + arraysize(code));
+
+  WasmInterpreter* interpreter = r.interpreter();
+  WasmInterpreter::Thread* thread = interpreter->GetThread(0);
+
+  FOR_UINT32_INPUTS(a) {
+    for (uint32_t b = 33; b < 3000000000u; b += 1000000000u) {
+      thread->Reset();
+      WasmVal args[] = {WasmVal(*a), WasmVal(b)};
+      thread->PushFrame(r.function(), args);
+
+      // Run instructions one by one.
+      for (int i = 0; i < kTraceLength - 1; i++) {
+        thread->Step();
+        // Check the thread stopped.
+        CHECK_EQ(WasmInterpreter::PAUSED, thread->state());
+      }
+
+      // Run last instruction.
+      thread->Step();
+
+      // Check the thread finished with the right value.
+      CHECK_EQ(WasmInterpreter::FINISHED, thread->state());
+      uint32_t expected = (*a) * (b);
+      CHECK_EQ(expected, thread->GetReturnValue().to<uint32_t>());
+    }
+  }
+}
+
+TEST(Breakpoint_I32And_disable) {
+  static const int kLocalsDeclSize = 1;
+  static const int kNumBreakpoints = 1;
+  byte code[] = {WASM_I32_AND(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))};
+  SmartArrayPointer<int> offsets =
+      Find(code, sizeof(code), kNumBreakpoints, kExprI32And);
+
+  WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Uint32(),
+                        MachineType::Uint32());
+
+  r.Build(code, code + arraysize(code));
+
+  WasmInterpreter* interpreter = r.interpreter();
+  WasmInterpreter::Thread* thread = interpreter->GetThread(0);
+
+  FOR_UINT32_INPUTS(a) {
+    for (uint32_t b = 11; b < 3000000000u; b += 1000000000u) {
+      // Run with and without breakpoints.
+      for (int do_break = 0; do_break < 2; do_break++) {
+        interpreter->SetBreakpoint(r.function(), kLocalsDeclSize + offsets[0],
+                                   do_break);
+        thread->Reset();
+        WasmVal args[] = {WasmVal(*a), WasmVal(b)};
+        thread->PushFrame(r.function(), args);
+
+        if (do_break) {
+          thread->Run();  // run to next breakpoint
+          // Check the thread stopped at the right pc.
+          CHECK_EQ(WasmInterpreter::PAUSED, thread->state());
+          CHECK_EQ(kLocalsDeclSize + offsets[0], thread->GetBreakpointPc());
+        }
+
+        thread->Run();  // run to completion
+
+        // Check the thread finished with the right value.
+        CHECK_EQ(WasmInterpreter::FINISHED, thread->state());
+        uint32_t expected = (*a) & (b);
+        CHECK_EQ(expected, thread->GetReturnValue().to<uint32_t>());
+      }
+    }
+  }
+}
+
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
diff --git a/test/cctest/wasm/test-run-wasm-js.cc b/test/cctest/wasm/test-run-wasm-js.cc
index 6d95d6e..827cb3a 100644
--- a/test/cctest/wasm/test-run-wasm-js.cc
+++ b/test/cctest/wasm/test-run-wasm-js.cc
@@ -25,14 +25,12 @@
     r.Build(code, code + arraysize(code)); \
   } while (false)
 
-
 #define ADD_CODE(vec, ...)                                              \
   do {                                                                  \
     byte __buf[] = {__VA_ARGS__};                                       \
     for (size_t i = 0; i < sizeof(__buf); i++) vec.push_back(__buf[i]); \
   } while (false)
 
-
 namespace {
 // A helper for generating predictable but unique argument values that
 // are easy to debug (e.g. with misaligned stacks).
@@ -48,23 +46,6 @@
   }
 };
 
-
-uint32_t AddJsFunction(TestingModule* module, FunctionSig* sig,
-                       const char* source) {
-  Handle<JSFunction> jsfunc = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
-      *v8::Local<v8::Function>::Cast(CompileRun(source))));
-  module->AddFunction(sig, Handle<Code>::null());
-  uint32_t index = static_cast<uint32_t>(module->module->functions.size() - 1);
-  Isolate* isolate = CcTest::InitIsolateOnce();
-  WasmName module_name = {"test", 4};
-  WasmName function_name = {nullptr, 0};
-  Handle<Code> code = CompileWasmToJSWrapper(isolate, module, jsfunc, sig,
-                                             module_name, function_name);
-  module->instance->function_code[index] = code;
-  return index;
-}
-
-
 uint32_t AddJSSelector(TestingModule* module, FunctionSig* sig, int which) {
   const int kMaxParams = 11;
   static const char* formals[kMaxParams] = {"",
@@ -86,22 +67,9 @@
   SNPrintF(source, "(function(%s) { return %c; })",
            formals[sig->parameter_count()], param);
 
-  return AddJsFunction(module, sig, source.start());
+  return module->AddJsFunction(sig, source.start());
 }
 
-
-Handle<JSFunction> WrapCode(ModuleEnv* module, uint32_t index) {
-  Isolate* isolate = module->module->shared_isolate;
-  // Wrap the code so it can be called as a JS function.
-  Handle<String> name = isolate->factory()->NewStringFromStaticChars("main");
-  Handle<JSObject> module_object = Handle<JSObject>(0, isolate);
-  Handle<Code> code = module->instance->function_code[index];
-  WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
-  return compiler::CompileJSToWasmWrapper(isolate, module, name, code,
-                                          module_object, index);
-}
-
-
 void EXPECT_CALL(double expected, Handle<JSFunction> jsfunc,
                  Handle<Object>* buffer, int count) {
   Isolate* isolate = jsfunc->GetIsolate();
@@ -119,7 +87,6 @@
   }
 }
 
-
 void EXPECT_CALL(double expected, Handle<JSFunction> jsfunc, double a,
                  double b) {
   Isolate* isolate = jsfunc->GetIsolate();
@@ -134,68 +101,61 @@
   TestingModule module;
   WasmFunctionCompiler t(sigs.i_ii(), &module);
   BUILD(t, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+  Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
 
   EXPECT_CALL(33, jsfunc, 44, 11);
   EXPECT_CALL(-8723487, jsfunc, -8000000, 723487);
 }
 
-
 TEST(Run_Float32Div_jswrapped) {
   TestSignatures sigs;
   TestingModule module;
   WasmFunctionCompiler t(sigs.f_ff(), &module);
   BUILD(t, WASM_F32_DIV(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+  Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
 
   EXPECT_CALL(92, jsfunc, 46, 0.5);
   EXPECT_CALL(64, jsfunc, -16, -0.25);
 }
 
-
 TEST(Run_Float64Add_jswrapped) {
   TestSignatures sigs;
   TestingModule module;
   WasmFunctionCompiler t(sigs.d_dd(), &module);
   BUILD(t, WASM_F64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+  Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
 
   EXPECT_CALL(3, jsfunc, 2, 1);
   EXPECT_CALL(-5.5, jsfunc, -5.25, -0.25);
 }
 
-
 TEST(Run_I32Popcount_jswrapped) {
   TestSignatures sigs;
   TestingModule module;
   WasmFunctionCompiler t(sigs.i_i(), &module);
   BUILD(t, WASM_I32_POPCNT(WASM_GET_LOCAL(0)));
-  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+  Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
 
   EXPECT_CALL(2, jsfunc, 9, 0);
   EXPECT_CALL(3, jsfunc, 11, 0);
   EXPECT_CALL(6, jsfunc, 0x3F, 0);
-
-  USE(AddJsFunction);
 }
 
-
 TEST(Run_CallJS_Add_jswrapped) {
   TestSignatures sigs;
   TestingModule module;
   WasmFunctionCompiler t(sigs.i_i(), &module);
   uint32_t js_index =
-      AddJsFunction(&module, sigs.i_i(), "(function(a) { return a + 99; })");
-  BUILD(t, WASM_CALL_FUNCTION(js_index, WASM_GET_LOCAL(0)));
+      module.AddJsFunction(sigs.i_i(), "(function(a) { return a + 99; })");
+  BUILD(t, WASM_CALL_FUNCTION1(js_index, WASM_GET_LOCAL(0)));
 
-  Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+  Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
 
   EXPECT_CALL(101, jsfunc, 2, -8);
   EXPECT_CALL(199, jsfunc, 100, -1);
   EXPECT_CALL(-666666801, jsfunc, -666666900, -1);
 }
 
-
 void RunJSSelectTest(int which) {
   const int kMaxParams = 8;
   PredictableInputValues inputs(0x100);
@@ -212,24 +172,25 @@
 
     {
       std::vector<byte> code;
-      ADD_CODE(code, kExprCallFunction, static_cast<byte>(js_index));
 
       for (int i = 0; i < num_params; i++) {
         ADD_CODE(code, WASM_F64(inputs.arg_d(i)));
       }
 
+      ADD_CODE(code, kExprCallFunction, static_cast<byte>(num_params),
+               static_cast<byte>(js_index));
+
       size_t end = code.size();
       code.push_back(0);
       t.Build(&code[0], &code[end]);
     }
 
-    Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+    Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
     double expected = inputs.arg_d(which);
     EXPECT_CALL(expected, jsfunc, 0.0, 0.0);
   }
 }
 
-
 TEST(Run_JSSelect_0) { RunJSSelectTest(0); }
 
 TEST(Run_JSSelect_1) { RunJSSelectTest(1); }
@@ -246,7 +207,6 @@
 
 TEST(Run_JSSelect_7) { RunJSSelectTest(7); }
 
-
 void RunWASMSelectTest(int which) {
   PredictableInputValues inputs(0x200);
   Isolate* isolate = CcTest::InitIsolateOnce();
@@ -260,7 +220,7 @@
     TestingModule module;
     WasmFunctionCompiler t(&sig, &module);
     BUILD(t, WASM_GET_LOCAL(which));
-    Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+    Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
 
     Handle<Object> args[] = {
         isolate->factory()->NewNumber(inputs.arg_d(0)),
@@ -278,7 +238,6 @@
   }
 }
 
-
 TEST(Run_WASMSelect_0) { RunWASMSelectTest(0); }
 
 TEST(Run_WASMSelect_1) { RunWASMSelectTest(1); }
@@ -295,7 +254,6 @@
 
 TEST(Run_WASMSelect_7) { RunWASMSelectTest(7); }
 
-
 void RunWASMSelectAlignTest(int num_args, int num_params) {
   PredictableInputValues inputs(0x300);
   Isolate* isolate = CcTest::InitIsolateOnce();
@@ -310,7 +268,7 @@
     TestingModule module;
     WasmFunctionCompiler t(&sig, &module);
     BUILD(t, WASM_GET_LOCAL(which));
-    Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+    Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
 
     Handle<Object> args[] = {isolate->factory()->NewNumber(inputs.arg_d(0)),
                              isolate->factory()->NewNumber(inputs.arg_d(1)),
@@ -329,31 +287,26 @@
   }
 }
 
-
 TEST(Run_WASMSelectAlign_0) {
   RunWASMSelectAlignTest(0, 1);
   RunWASMSelectAlignTest(0, 2);
 }
 
-
 TEST(Run_WASMSelectAlign_1) {
   RunWASMSelectAlignTest(1, 2);
   RunWASMSelectAlignTest(1, 3);
 }
 
-
 TEST(Run_WASMSelectAlign_2) {
   RunWASMSelectAlignTest(2, 3);
   RunWASMSelectAlignTest(2, 4);
 }
 
-
 TEST(Run_WASMSelectAlign_3) {
   RunWASMSelectAlignTest(3, 3);
   RunWASMSelectAlignTest(3, 4);
 }
 
-
 TEST(Run_WASMSelectAlign_4) {
   RunWASMSelectAlignTest(4, 3);
   RunWASMSelectAlignTest(4, 4);
@@ -400,12 +353,13 @@
 
   // Build the calling code.
   std::vector<byte> code;
-  ADD_CODE(code, kExprCallFunction, 0);
 
   for (int i = 0; i < num_params; i++) {
     ADD_CODE(code, WASM_GET_LOCAL(i));
   }
 
+  ADD_CODE(code, kExprCallFunction, static_cast<byte>(num_params), 0);
+
   size_t end = code.size();
   code.push_back(0);
 
@@ -418,7 +372,7 @@
     WasmFunctionCompiler t(&sig, &module);
     t.Build(&code[0], &code[end]);
 
-    Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+    Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd());
 
     Handle<Object> args[] = {
         factory->NewNumber(inputs.arg_d(0)),
@@ -439,7 +393,6 @@
   }
 }
 
-
 TEST(Run_JSSelectAlign_0) {
   RunJSSelectAlignTest(0, 1);
   RunJSSelectAlignTest(0, 2);
diff --git a/test/cctest/wasm/test-run-wasm-module.cc b/test/cctest/wasm/test-run-wasm-module.cc
index 118a91f..7a79d67 100644
--- a/test/cctest/wasm/test-run-wasm-module.cc
+++ b/test/cctest/wasm/test-run-wasm-module.cc
@@ -12,129 +12,109 @@
 #include "src/wasm/wasm-opcodes.h"
 
 #include "test/cctest/cctest.h"
+#include "test/cctest/wasm/test-signatures.h"
 
 using namespace v8::base;
 using namespace v8::internal;
 using namespace v8::internal::compiler;
 using namespace v8::internal::wasm;
 
-
-// TODO(titzer): fix arm64 frame alignment.
 namespace {
-void TestModule(WasmModuleIndex* module, int32_t expected_result) {
+void TestModule(Zone* zone, WasmModuleBuilder* builder,
+                int32_t expected_result) {
+  ZoneBuffer buffer(zone);
+  builder->WriteTo(buffer);
+
   Isolate* isolate = CcTest::InitIsolateOnce();
   HandleScope scope(isolate);
   WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
   int32_t result =
-      CompileAndRunWasmModule(isolate, module->Begin(), module->End());
+      testing::CompileAndRunWasmModule(isolate, buffer.begin(), buffer.end());
   CHECK_EQ(expected_result, result);
 }
+
+void ExportAsMain(WasmFunctionBuilder* f) {
+  static const char kMainName[] = "main";
+  f->SetExported();
+  f->SetName(kMainName, arraysize(kMainName) - 1);
+}
 }  // namespace
 
-
-// A raw test that skips the WasmModuleBuilder.
-TEST(Run_WasmModule_CallAdd_rev) {
-  static const byte data[] = {
-      WASM_MODULE_HEADER,
-      // sig#0 ------------------------------------------
-      WASM_SECTION_SIGNATURES_SIZE + 7,          // Section size.
-      WASM_SECTION_SIGNATURES, 2, 0, kLocalI32,  // void -> int
-      2, kLocalI32, kLocalI32, kLocalI32,        // int,int -> int
-      // func#0 (main) ----------------------------------
-      WASM_SECTION_FUNCTIONS_SIZE + 24, WASM_SECTION_FUNCTIONS, 2,
-      kDeclFunctionExport, 0, 0,  // sig index
-      7, 0,                       // body size
-      0,                          // locals
-      kExprCallFunction, 1,       // --
-      kExprI8Const, 77,           // --
-      kExprI8Const, 22,           // --
-      // func#1 -----------------------------------------
-      0,                 // no name, not exported
-      1, 0,              // sig index
-      6, 0,              // body size
-      0,                 // locals
-      kExprI32Add,       // --
-      kExprGetLocal, 0,  // --
-      kExprGetLocal, 1,  // --
-  };
-
-  Isolate* isolate = CcTest::InitIsolateOnce();
-  HandleScope scope(isolate);
-  WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
-  int32_t result =
-      CompileAndRunWasmModule(isolate, data, data + arraysize(data));
-  CHECK_EQ(99, result);
-}
-
-
 TEST(Run_WasmModule_Return114) {
   static const int32_t kReturnValue = 114;
+  TestSignatures sigs;
   v8::base::AccountingAllocator allocator;
   Zone zone(&allocator);
+
   WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
   uint16_t f_index = builder->AddFunction();
   WasmFunctionBuilder* f = builder->FunctionAt(f_index);
-  f->ReturnType(kAstI32);
-  f->Exported(1);
+  f->SetSignature(sigs.i_v());
+  ExportAsMain(f);
   byte code[] = {WASM_I8(kReturnValue)};
   f->EmitCode(code, sizeof(code));
-  WasmModuleWriter* writer = builder->Build(&zone);
-  TestModule(writer->WriteTo(&zone), kReturnValue);
+  TestModule(&zone, builder, kReturnValue);
 }
 
-
 TEST(Run_WasmModule_CallAdd) {
   v8::base::AccountingAllocator allocator;
   Zone zone(&allocator);
+  TestSignatures sigs;
+
   WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
+
   uint16_t f1_index = builder->AddFunction();
   WasmFunctionBuilder* f = builder->FunctionAt(f1_index);
-  f->ReturnType(kAstI32);
-  uint16_t param1 = f->AddParam(kAstI32);
-  uint16_t param2 = f->AddParam(kAstI32);
+  f->SetSignature(sigs.i_ii());
+  uint16_t param1 = 0;
+  uint16_t param2 = 1;
   byte code1[] = {WASM_I32_ADD(WASM_GET_LOCAL(param1), WASM_GET_LOCAL(param2))};
-  uint32_t local_indices1[] = {2, 4};
-  f->EmitCode(code1, sizeof(code1), local_indices1, sizeof(local_indices1) / 4);
+  f->EmitCode(code1, sizeof(code1));
+
   uint16_t f2_index = builder->AddFunction();
   f = builder->FunctionAt(f2_index);
-  f->ReturnType(kAstI32);
-  f->Exported(1);
-  byte code2[] = {WASM_CALL_FUNCTION(f1_index, WASM_I8(77), WASM_I8(22))};
-  f->EmitCode(code2, sizeof(code2));
-  WasmModuleWriter* writer = builder->Build(&zone);
-  TestModule(writer->WriteTo(&zone), 99);
-}
+  f->SetSignature(sigs.i_v());
 
+  ExportAsMain(f);
+  byte code2[] = {WASM_CALL_FUNCTION2(f1_index, WASM_I8(77), WASM_I8(22))};
+  f->EmitCode(code2, sizeof(code2));
+  TestModule(&zone, builder, 99);
+}
 
 TEST(Run_WasmModule_ReadLoadedDataSegment) {
   static const byte kDataSegmentDest0 = 12;
   v8::base::AccountingAllocator allocator;
   Zone zone(&allocator);
+  TestSignatures sigs;
+
   WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
   uint16_t f_index = builder->AddFunction();
   WasmFunctionBuilder* f = builder->FunctionAt(f_index);
-  f->ReturnType(kAstI32);
-  f->Exported(1);
+  f->SetSignature(sigs.i_v());
+
+  ExportAsMain(f);
   byte code[] = {
       WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(kDataSegmentDest0))};
   f->EmitCode(code, sizeof(code));
   byte data[] = {0xaa, 0xbb, 0xcc, 0xdd};
   builder->AddDataSegment(new (&zone) WasmDataSegmentEncoder(
       &zone, data, sizeof(data), kDataSegmentDest0));
-  WasmModuleWriter* writer = builder->Build(&zone);
-  TestModule(writer->WriteTo(&zone), 0xddccbbaa);
+  TestModule(&zone, builder, 0xddccbbaa);
 }
 
 TEST(Run_WasmModule_CheckMemoryIsZero) {
   static const int kCheckSize = 16 * 1024;
   v8::base::AccountingAllocator allocator;
   Zone zone(&allocator);
+  TestSignatures sigs;
+
   WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
   uint16_t f_index = builder->AddFunction();
   WasmFunctionBuilder* f = builder->FunctionAt(f_index);
-  f->ReturnType(kAstI32);
+  f->SetSignature(sigs.i_v());
+
   uint16_t localIndex = f->AddLocal(kAstI32);
-  f->Exported(1);
+  ExportAsMain(f);
   byte code[] = {WASM_BLOCK(
       2,
       WASM_WHILE(
@@ -143,20 +123,22 @@
               WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(localIndex)),
               WASM_BRV(2, WASM_I8(-1)), WASM_INC_LOCAL_BY(localIndex, 4))),
       WASM_I8(11))};
-  f->EmitCode(code, sizeof(code), nullptr, 0);
-  WasmModuleWriter* writer = builder->Build(&zone);
-  TestModule(writer->WriteTo(&zone), 11);
+  f->EmitCode(code, sizeof(code));
+  TestModule(&zone, builder, 11);
 }
 
 TEST(Run_WasmModule_CallMain_recursive) {
   v8::base::AccountingAllocator allocator;
   Zone zone(&allocator);
+  TestSignatures sigs;
+
   WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
   uint16_t f_index = builder->AddFunction();
   WasmFunctionBuilder* f = builder->FunctionAt(f_index);
-  f->ReturnType(kAstI32);
+  f->SetSignature(sigs.i_v());
+
   uint16_t localIndex = f->AddLocal(kAstI32);
-  f->Exported(1);
+  ExportAsMain(f);
   byte code[] = {WASM_BLOCK(
       2, WASM_SET_LOCAL(localIndex,
                         WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)),
@@ -165,31 +147,31 @@
                                                 WASM_INC_LOCAL(localIndex)),
                               WASM_BRV(1, WASM_CALL_FUNCTION0(0))),
                    WASM_BRV(0, WASM_I8(55))))};
-  f->EmitCode(code, sizeof(code), nullptr, 0);
-  WasmModuleWriter* writer = builder->Build(&zone);
-  TestModule(writer->WriteTo(&zone), 55);
+  f->EmitCode(code, sizeof(code));
+  TestModule(&zone, builder, 55);
 }
 
 TEST(Run_WasmModule_Global) {
   v8::base::AccountingAllocator allocator;
   Zone zone(&allocator);
+  TestSignatures sigs;
+
   WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
   uint32_t global1 = builder->AddGlobal(MachineType::Int32(), 0);
   uint32_t global2 = builder->AddGlobal(MachineType::Int32(), 0);
   uint16_t f1_index = builder->AddFunction();
   WasmFunctionBuilder* f = builder->FunctionAt(f1_index);
-  f->ReturnType(kAstI32);
+  f->SetSignature(sigs.i_v());
   byte code1[] = {
       WASM_I32_ADD(WASM_LOAD_GLOBAL(global1), WASM_LOAD_GLOBAL(global2))};
   f->EmitCode(code1, sizeof(code1));
   uint16_t f2_index = builder->AddFunction();
   f = builder->FunctionAt(f2_index);
-  f->ReturnType(kAstI32);
-  f->Exported(1);
+  f->SetSignature(sigs.i_v());
+  ExportAsMain(f);
   byte code2[] = {WASM_STORE_GLOBAL(global1, WASM_I32V_1(56)),
                   WASM_STORE_GLOBAL(global2, WASM_I32V_1(41)),
-                  WASM_RETURN(WASM_CALL_FUNCTION0(f1_index))};
+                  WASM_RETURN1(WASM_CALL_FUNCTION0(f1_index))};
   f->EmitCode(code2, sizeof(code2));
-  WasmModuleWriter* writer = builder->Build(&zone);
-  TestModule(writer->WriteTo(&zone), 97);
+  TestModule(&zone, builder, 97);
 }
diff --git a/test/cctest/wasm/test-run-wasm-relocation.cc b/test/cctest/wasm/test-run-wasm-relocation.cc
new file mode 100644
index 0000000..6b1f643
--- /dev/null
+++ b/test/cctest/wasm/test-run-wasm-relocation.cc
@@ -0,0 +1,64 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdlib.h>
+
+#include "src/v8.h"
+
+#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/c-signature.h"
+#include "test/cctest/wasm/wasm-run-utils.h"
+
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+
+#define FOREACH_TYPE(TEST_BODY)             \
+  TEST_BODY(int8_t, Int8, WASM_I32_ADD)     \
+  TEST_BODY(uint8_t, Uint8, WASM_I32_ADD)   \
+  TEST_BODY(int16_t, Int16, WASM_I32_ADD)   \
+  TEST_BODY(uint16_t, Uint16, WASM_I32_ADD) \
+  TEST_BODY(int32_t, Int32, WASM_I32_ADD)   \
+  TEST_BODY(uint32_t, Uint32, WASM_I32_ADD) \
+  TEST_BODY(float, Float32, WASM_F32_ADD)   \
+  TEST_BODY(double, Float64, WASM_F64_ADD)
+
+#define LOAD_STORE_GLOBAL_TEST_BODY(C_TYPE, MACHINE_TYPE, ADD)                \
+  TEST(WasmRelocateGlobal##MACHINE_TYPE) {                                    \
+    TestingModule module(kExecuteCompiled);                                   \
+    module.AddGlobal<int32_t>(MachineType::MACHINE_TYPE());                   \
+    module.AddGlobal<int32_t>(MachineType::MACHINE_TYPE());                   \
+                                                                              \
+    WasmRunner<C_TYPE> r(&module, MachineType::MACHINE_TYPE());               \
+                                                                              \
+    /* global = global + p0 */                                                \
+    BUILD(r,                                                                  \
+          WASM_STORE_GLOBAL(1, ADD(WASM_LOAD_GLOBAL(0), WASM_GET_LOCAL(0)))); \
+    CHECK_EQ(1, module.instance->function_code.size());                       \
+                                                                              \
+    int filter = 1 << RelocInfo::WASM_GLOBAL_REFERENCE;                       \
+                                                                              \
+    Handle<Code> code = module.instance->function_code[0];                    \
+                                                                              \
+    Address old_start = module.instance->globals_start;                       \
+    Address new_start = old_start + 1;                                        \
+                                                                              \
+    Address old_addresses[2];                                                 \
+    uint32_t address_index = 0U;                                              \
+    for (RelocIterator it(*code, filter); !it.done(); it.next()) {            \
+      old_addresses[address_index] = it.rinfo()->wasm_global_reference();     \
+      it.rinfo()->update_wasm_global_reference(old_start, new_start);         \
+      ++address_index;                                                        \
+    }                                                                         \
+    CHECK_EQ(2U, address_index);                                              \
+                                                                              \
+    address_index = 0U;                                                       \
+    for (RelocIterator it(*code, filter); !it.done(); it.next()) {            \
+      CHECK_EQ(old_addresses[address_index] + 1,                              \
+               it.rinfo()->wasm_global_reference());                          \
+      ++address_index;                                                        \
+    }                                                                         \
+    CHECK_EQ(2U, address_index);                                              \
+  }
+
+FOREACH_TYPE(LOAD_STORE_GLOBAL_TEST_BODY)
diff --git a/test/cctest/wasm/test-run-wasm.cc b/test/cctest/wasm/test-run-wasm.cc
index 70d461b..ec7c5e7 100644
--- a/test/cctest/wasm/test-run-wasm.cc
+++ b/test/cctest/wasm/test-run-wasm.cc
@@ -6,6 +6,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "src/base/platform/elapsed-timer.h"
+
 #include "src/wasm/wasm-macro-gen.h"
 
 #include "test/cctest/cctest.h"
@@ -19,41 +21,38 @@
 using namespace v8::internal::wasm;
 
 // for even shorter tests.
-#define B2(a, b) kExprBlock, 2, a, b
-#define B1(a) kExprBlock, 1, a
-#define RET(x) kExprReturn, x
-#define RET_I8(x) kExprReturn, kExprI8Const, x
+#define B2(a, b) kExprBlock, a, b, kExprEnd
+#define B1(a) kExprBlock, a, kExprEnd
+#define RET(x) x, kExprReturn, 1
+#define RET_I8(x) kExprI8Const, x, kExprReturn, 1
 
-TEST(Run_WasmInt8Const) {
-  WasmRunner<int32_t> r;
+WASM_EXEC_TEST(Int8Const) {
+  WasmRunner<int32_t> r(execution_mode);
   const byte kExpectedValue = 121;
   // return(kExpectedValue)
   BUILD(r, WASM_I8(kExpectedValue));
   CHECK_EQ(kExpectedValue, r.Call());
 }
 
-
-TEST(Run_WasmInt8Const_fallthru1) {
-  WasmRunner<int32_t> r;
+WASM_EXEC_TEST(Int8Const_fallthru1) {
+  WasmRunner<int32_t> r(execution_mode);
   const byte kExpectedValue = 122;
   // kExpectedValue
   BUILD(r, WASM_I8(kExpectedValue));
   CHECK_EQ(kExpectedValue, r.Call());
 }
 
-
-TEST(Run_WasmInt8Const_fallthru2) {
-  WasmRunner<int32_t> r;
+WASM_EXEC_TEST(Int8Const_fallthru2) {
+  WasmRunner<int32_t> r(execution_mode);
   const byte kExpectedValue = 123;
   // -99 kExpectedValue
   BUILD(r, WASM_I8(-99), WASM_I8(kExpectedValue));
   CHECK_EQ(kExpectedValue, r.Call());
 }
 
-
-TEST(Run_WasmInt8Const_all) {
-  for (int value = -128; value <= 127; value++) {
-    WasmRunner<int32_t> r;
+WASM_EXEC_TEST(Int8Const_all) {
+  for (int value = -128; value <= 127; ++value) {
+    WasmRunner<int32_t> r(execution_mode);
     // return(value)
     BUILD(r, WASM_I8(value));
     int32_t result = r.Call();
@@ -61,19 +60,17 @@
   }
 }
 
-
-TEST(Run_WasmInt32Const) {
-  WasmRunner<int32_t> r;
+WASM_EXEC_TEST(Int32Const) {
+  WasmRunner<int32_t> r(execution_mode);
   const int32_t kExpectedValue = 0x11223344;
   // return(kExpectedValue)
   BUILD(r, WASM_I32V_5(kExpectedValue));
   CHECK_EQ(kExpectedValue, r.Call());
 }
 
-
-TEST(Run_WasmInt32Const_many) {
+WASM_EXEC_TEST(Int32Const_many) {
   FOR_INT32_INPUTS(i) {
-    WasmRunner<int32_t> r;
+    WasmRunner<int32_t> r(execution_mode);
     const int32_t kExpectedValue = *i;
     // return(kExpectedValue)
     BUILD(r, WASM_I32V(kExpectedValue));
@@ -81,66 +78,60 @@
   }
 }
 
-
-TEST(Run_WasmMemorySize) {
-  TestingModule module;
+WASM_EXEC_TEST(MemorySize) {
+  TestingModule module(execution_mode);
   WasmRunner<int32_t> r(&module);
   module.AddMemory(1024);
   BUILD(r, kExprMemorySize);
   CHECK_EQ(1024, r.Call());
 }
 
-
-TEST(Run_WasmInt32Param0) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Int32Param0) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   // return(local[0])
   BUILD(r, WASM_GET_LOCAL(0));
   FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
 }
 
-
-TEST(Run_WasmInt32Param0_fallthru) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Int32Param0_fallthru) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   // local[0]
   BUILD(r, WASM_GET_LOCAL(0));
   FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
 }
 
-
-TEST(Run_WasmInt32Param1) {
-  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+WASM_EXEC_TEST(Int32Param1) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
   // local[1]
   BUILD(r, WASM_GET_LOCAL(1));
   FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(-111, *i)); }
 }
 
-
-TEST(Run_WasmInt32Add) {
-  WasmRunner<int32_t> r;
+WASM_EXEC_TEST(Int32Add) {
+  WasmRunner<int32_t> r(execution_mode);
   // 11 + 44
   BUILD(r, WASM_I32_ADD(WASM_I8(11), WASM_I8(44)));
   CHECK_EQ(55, r.Call());
 }
 
-
-TEST(Run_WasmInt32Add_P) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Int32Add_P) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   // p0 + 13
   BUILD(r, WASM_I32_ADD(WASM_I8(13), WASM_GET_LOCAL(0)));
   FOR_INT32_INPUTS(i) { CHECK_EQ(*i + 13, r.Call(*i)); }
 }
 
-
-TEST(Run_WasmInt32Add_P_fallthru) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Int32Add_P_fallthru) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   // p0 + 13
   BUILD(r, WASM_I32_ADD(WASM_I8(13), WASM_GET_LOCAL(0)));
   FOR_INT32_INPUTS(i) { CHECK_EQ(*i + 13, r.Call(*i)); }
 }
 
-
-TEST(Run_WasmInt32Add_P2) {
-  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+WASM_EXEC_TEST(Int32Add_P2) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
   //  p0 + p1
   BUILD(r, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   FOR_INT32_INPUTS(i) {
@@ -152,180 +143,178 @@
   }
 }
 
-
-TEST(Run_WasmFloat32Add) {
-  WasmRunner<int32_t> r;
+WASM_EXEC_TEST(Float32Add) {
+  WasmRunner<int32_t> r(execution_mode);
   // int(11.5f + 44.5f)
   BUILD(r,
         WASM_I32_SCONVERT_F32(WASM_F32_ADD(WASM_F32(11.5f), WASM_F32(44.5f))));
   CHECK_EQ(56, r.Call());
 }
 
-
-TEST(Run_WasmFloat64Add) {
-  WasmRunner<int32_t> r;
+WASM_EXEC_TEST(Float64Add) {
+  WasmRunner<int32_t> r(execution_mode);
   // return int(13.5d + 43.5d)
   BUILD(r, WASM_I32_SCONVERT_F64(WASM_F64_ADD(WASM_F64(13.5), WASM_F64(43.5))));
   CHECK_EQ(57, r.Call());
 }
 
-
-void TestInt32Binop(WasmOpcode opcode, int32_t expected, int32_t a, int32_t b) {
+void TestInt32Binop(WasmExecutionMode execution_mode, WasmOpcode opcode,
+                    int32_t expected, int32_t a, int32_t b) {
   {
-    WasmRunner<int32_t> r;
+    WasmRunner<int32_t> r(execution_mode);
     // K op K
     BUILD(r, WASM_BINOP(opcode, WASM_I32V(a), WASM_I32V(b)));
     CHECK_EQ(expected, r.Call());
   }
   {
-    WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+    WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                          MachineType::Int32());
     // a op b
     BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
     CHECK_EQ(expected, r.Call(a, b));
   }
 }
 
-TEST(Run_WasmInt32Binops) {
-  TestInt32Binop(kExprI32Add, 88888888, 33333333, 55555555);
-  TestInt32Binop(kExprI32Sub, -1111111, 7777777, 8888888);
-  TestInt32Binop(kExprI32Mul, 65130756, 88734, 734);
-  TestInt32Binop(kExprI32DivS, -66, -4777344, 72384);
-  TestInt32Binop(kExprI32DivU, 805306368, 0xF0000000, 5);
-  TestInt32Binop(kExprI32RemS, -3, -3003, 1000);
-  TestInt32Binop(kExprI32RemU, 4, 4004, 1000);
-  TestInt32Binop(kExprI32And, 0xEE, 0xFFEE, 0xFF0000FF);
-  TestInt32Binop(kExprI32Ior, 0xF0FF00FF, 0xF0F000EE, 0x000F0011);
-  TestInt32Binop(kExprI32Xor, 0xABCDEF01, 0xABCDEFFF, 0xFE);
-  TestInt32Binop(kExprI32Shl, 0xA0000000, 0xA, 28);
-  TestInt32Binop(kExprI32ShrU, 0x07000010, 0x70000100, 4);
-  TestInt32Binop(kExprI32ShrS, 0xFF000000, 0x80000000, 7);
-  TestInt32Binop(kExprI32Ror, 0x01000000, 0x80000000, 7);
-  TestInt32Binop(kExprI32Ror, 0x01000000, 0x80000000, 39);
-  TestInt32Binop(kExprI32Rol, 0x00000040, 0x80000000, 7);
-  TestInt32Binop(kExprI32Rol, 0x00000040, 0x80000000, 39);
-  TestInt32Binop(kExprI32Eq, 1, -99, -99);
-  TestInt32Binop(kExprI32Ne, 0, -97, -97);
+WASM_EXEC_TEST(Int32Binops) {
+  TestInt32Binop(execution_mode, kExprI32Add, 88888888, 33333333, 55555555);
+  TestInt32Binop(execution_mode, kExprI32Sub, -1111111, 7777777, 8888888);
+  TestInt32Binop(execution_mode, kExprI32Mul, 65130756, 88734, 734);
+  TestInt32Binop(execution_mode, kExprI32DivS, -66, -4777344, 72384);
+  TestInt32Binop(execution_mode, kExprI32DivU, 805306368, 0xF0000000, 5);
+  TestInt32Binop(execution_mode, kExprI32RemS, -3, -3003, 1000);
+  TestInt32Binop(execution_mode, kExprI32RemU, 4, 4004, 1000);
+  TestInt32Binop(execution_mode, kExprI32And, 0xEE, 0xFFEE, 0xFF0000FF);
+  TestInt32Binop(execution_mode, kExprI32Ior, 0xF0FF00FF, 0xF0F000EE,
+                 0x000F0011);
+  TestInt32Binop(execution_mode, kExprI32Xor, 0xABCDEF01, 0xABCDEFFF, 0xFE);
+  TestInt32Binop(execution_mode, kExprI32Shl, 0xA0000000, 0xA, 28);
+  TestInt32Binop(execution_mode, kExprI32ShrU, 0x07000010, 0x70000100, 4);
+  TestInt32Binop(execution_mode, kExprI32ShrS, 0xFF000000, 0x80000000, 7);
+  TestInt32Binop(execution_mode, kExprI32Ror, 0x01000000, 0x80000000, 7);
+  TestInt32Binop(execution_mode, kExprI32Ror, 0x01000000, 0x80000000, 39);
+  TestInt32Binop(execution_mode, kExprI32Rol, 0x00000040, 0x80000000, 7);
+  TestInt32Binop(execution_mode, kExprI32Rol, 0x00000040, 0x80000000, 39);
+  TestInt32Binop(execution_mode, kExprI32Eq, 1, -99, -99);
+  TestInt32Binop(execution_mode, kExprI32Ne, 0, -97, -97);
 
-  TestInt32Binop(kExprI32LtS, 1, -4, 4);
-  TestInt32Binop(kExprI32LeS, 0, -2, -3);
-  TestInt32Binop(kExprI32LtU, 1, 0, -6);
-  TestInt32Binop(kExprI32LeU, 1, 98978, 0xF0000000);
+  TestInt32Binop(execution_mode, kExprI32LtS, 1, -4, 4);
+  TestInt32Binop(execution_mode, kExprI32LeS, 0, -2, -3);
+  TestInt32Binop(execution_mode, kExprI32LtU, 1, 0, -6);
+  TestInt32Binop(execution_mode, kExprI32LeU, 1, 98978, 0xF0000000);
 
-  TestInt32Binop(kExprI32GtS, 1, 4, -4);
-  TestInt32Binop(kExprI32GeS, 0, -3, -2);
-  TestInt32Binop(kExprI32GtU, 1, -6, 0);
-  TestInt32Binop(kExprI32GeU, 1, 0xF0000000, 98978);
+  TestInt32Binop(execution_mode, kExprI32GtS, 1, 4, -4);
+  TestInt32Binop(execution_mode, kExprI32GeS, 0, -3, -2);
+  TestInt32Binop(execution_mode, kExprI32GtU, 1, -6, 0);
+  TestInt32Binop(execution_mode, kExprI32GeU, 1, 0xF0000000, 98978);
 }
 
-
-void TestInt32Unop(WasmOpcode opcode, int32_t expected, int32_t a) {
+void TestInt32Unop(WasmExecutionMode execution_mode, WasmOpcode opcode,
+                   int32_t expected, int32_t a) {
   {
-    WasmRunner<int32_t> r;
+    WasmRunner<int32_t> r(execution_mode);
     // return op K
     BUILD(r, WASM_UNOP(opcode, WASM_I32V(a)));
     CHECK_EQ(expected, r.Call());
   }
   {
-    WasmRunner<int32_t> r(MachineType::Int32());
+    WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
     // return op a
     BUILD(r, WASM_UNOP(opcode, WASM_GET_LOCAL(0)));
     CHECK_EQ(expected, r.Call(a));
   }
 }
 
-
-TEST(Run_WasmInt32Clz) {
-  TestInt32Unop(kExprI32Clz, 0, 0x80001000);
-  TestInt32Unop(kExprI32Clz, 1, 0x40000500);
-  TestInt32Unop(kExprI32Clz, 2, 0x20000300);
-  TestInt32Unop(kExprI32Clz, 3, 0x10000003);
-  TestInt32Unop(kExprI32Clz, 4, 0x08050000);
-  TestInt32Unop(kExprI32Clz, 5, 0x04006000);
-  TestInt32Unop(kExprI32Clz, 6, 0x02000000);
-  TestInt32Unop(kExprI32Clz, 7, 0x010000a0);
-  TestInt32Unop(kExprI32Clz, 8, 0x00800c00);
-  TestInt32Unop(kExprI32Clz, 9, 0x00400000);
-  TestInt32Unop(kExprI32Clz, 10, 0x0020000d);
-  TestInt32Unop(kExprI32Clz, 11, 0x00100f00);
-  TestInt32Unop(kExprI32Clz, 12, 0x00080000);
-  TestInt32Unop(kExprI32Clz, 13, 0x00041000);
-  TestInt32Unop(kExprI32Clz, 14, 0x00020020);
-  TestInt32Unop(kExprI32Clz, 15, 0x00010300);
-  TestInt32Unop(kExprI32Clz, 16, 0x00008040);
-  TestInt32Unop(kExprI32Clz, 17, 0x00004005);
-  TestInt32Unop(kExprI32Clz, 18, 0x00002050);
-  TestInt32Unop(kExprI32Clz, 19, 0x00001700);
-  TestInt32Unop(kExprI32Clz, 20, 0x00000870);
-  TestInt32Unop(kExprI32Clz, 21, 0x00000405);
-  TestInt32Unop(kExprI32Clz, 22, 0x00000203);
-  TestInt32Unop(kExprI32Clz, 23, 0x00000101);
-  TestInt32Unop(kExprI32Clz, 24, 0x00000089);
-  TestInt32Unop(kExprI32Clz, 25, 0x00000041);
-  TestInt32Unop(kExprI32Clz, 26, 0x00000022);
-  TestInt32Unop(kExprI32Clz, 27, 0x00000013);
-  TestInt32Unop(kExprI32Clz, 28, 0x00000008);
-  TestInt32Unop(kExprI32Clz, 29, 0x00000004);
-  TestInt32Unop(kExprI32Clz, 30, 0x00000002);
-  TestInt32Unop(kExprI32Clz, 31, 0x00000001);
-  TestInt32Unop(kExprI32Clz, 32, 0x00000000);
+WASM_EXEC_TEST(Int32Clz) {
+  TestInt32Unop(execution_mode, kExprI32Clz, 0, 0x80001000);
+  TestInt32Unop(execution_mode, kExprI32Clz, 1, 0x40000500);
+  TestInt32Unop(execution_mode, kExprI32Clz, 2, 0x20000300);
+  TestInt32Unop(execution_mode, kExprI32Clz, 3, 0x10000003);
+  TestInt32Unop(execution_mode, kExprI32Clz, 4, 0x08050000);
+  TestInt32Unop(execution_mode, kExprI32Clz, 5, 0x04006000);
+  TestInt32Unop(execution_mode, kExprI32Clz, 6, 0x02000000);
+  TestInt32Unop(execution_mode, kExprI32Clz, 7, 0x010000a0);
+  TestInt32Unop(execution_mode, kExprI32Clz, 8, 0x00800c00);
+  TestInt32Unop(execution_mode, kExprI32Clz, 9, 0x00400000);
+  TestInt32Unop(execution_mode, kExprI32Clz, 10, 0x0020000d);
+  TestInt32Unop(execution_mode, kExprI32Clz, 11, 0x00100f00);
+  TestInt32Unop(execution_mode, kExprI32Clz, 12, 0x00080000);
+  TestInt32Unop(execution_mode, kExprI32Clz, 13, 0x00041000);
+  TestInt32Unop(execution_mode, kExprI32Clz, 14, 0x00020020);
+  TestInt32Unop(execution_mode, kExprI32Clz, 15, 0x00010300);
+  TestInt32Unop(execution_mode, kExprI32Clz, 16, 0x00008040);
+  TestInt32Unop(execution_mode, kExprI32Clz, 17, 0x00004005);
+  TestInt32Unop(execution_mode, kExprI32Clz, 18, 0x00002050);
+  TestInt32Unop(execution_mode, kExprI32Clz, 19, 0x00001700);
+  TestInt32Unop(execution_mode, kExprI32Clz, 20, 0x00000870);
+  TestInt32Unop(execution_mode, kExprI32Clz, 21, 0x00000405);
+  TestInt32Unop(execution_mode, kExprI32Clz, 22, 0x00000203);
+  TestInt32Unop(execution_mode, kExprI32Clz, 23, 0x00000101);
+  TestInt32Unop(execution_mode, kExprI32Clz, 24, 0x00000089);
+  TestInt32Unop(execution_mode, kExprI32Clz, 25, 0x00000041);
+  TestInt32Unop(execution_mode, kExprI32Clz, 26, 0x00000022);
+  TestInt32Unop(execution_mode, kExprI32Clz, 27, 0x00000013);
+  TestInt32Unop(execution_mode, kExprI32Clz, 28, 0x00000008);
+  TestInt32Unop(execution_mode, kExprI32Clz, 29, 0x00000004);
+  TestInt32Unop(execution_mode, kExprI32Clz, 30, 0x00000002);
+  TestInt32Unop(execution_mode, kExprI32Clz, 31, 0x00000001);
+  TestInt32Unop(execution_mode, kExprI32Clz, 32, 0x00000000);
 }
 
-
-TEST(Run_WasmInt32Ctz) {
-  TestInt32Unop(kExprI32Ctz, 32, 0x00000000);
-  TestInt32Unop(kExprI32Ctz, 31, 0x80000000);
-  TestInt32Unop(kExprI32Ctz, 30, 0x40000000);
-  TestInt32Unop(kExprI32Ctz, 29, 0x20000000);
-  TestInt32Unop(kExprI32Ctz, 28, 0x10000000);
-  TestInt32Unop(kExprI32Ctz, 27, 0xa8000000);
-  TestInt32Unop(kExprI32Ctz, 26, 0xf4000000);
-  TestInt32Unop(kExprI32Ctz, 25, 0x62000000);
-  TestInt32Unop(kExprI32Ctz, 24, 0x91000000);
-  TestInt32Unop(kExprI32Ctz, 23, 0xcd800000);
-  TestInt32Unop(kExprI32Ctz, 22, 0x09400000);
-  TestInt32Unop(kExprI32Ctz, 21, 0xaf200000);
-  TestInt32Unop(kExprI32Ctz, 20, 0xac100000);
-  TestInt32Unop(kExprI32Ctz, 19, 0xe0b80000);
-  TestInt32Unop(kExprI32Ctz, 18, 0x9ce40000);
-  TestInt32Unop(kExprI32Ctz, 17, 0xc7920000);
-  TestInt32Unop(kExprI32Ctz, 16, 0xb8f10000);
-  TestInt32Unop(kExprI32Ctz, 15, 0x3b9f8000);
-  TestInt32Unop(kExprI32Ctz, 14, 0xdb4c4000);
-  TestInt32Unop(kExprI32Ctz, 13, 0xe9a32000);
-  TestInt32Unop(kExprI32Ctz, 12, 0xfca61000);
-  TestInt32Unop(kExprI32Ctz, 11, 0x6c8a7800);
-  TestInt32Unop(kExprI32Ctz, 10, 0x8ce5a400);
-  TestInt32Unop(kExprI32Ctz, 9, 0xcb7d0200);
-  TestInt32Unop(kExprI32Ctz, 8, 0xcb4dc100);
-  TestInt32Unop(kExprI32Ctz, 7, 0xdfbec580);
-  TestInt32Unop(kExprI32Ctz, 6, 0x27a9db40);
-  TestInt32Unop(kExprI32Ctz, 5, 0xde3bcb20);
-  TestInt32Unop(kExprI32Ctz, 4, 0xd7e8a610);
-  TestInt32Unop(kExprI32Ctz, 3, 0x9afdbc88);
-  TestInt32Unop(kExprI32Ctz, 2, 0x9afdbc84);
-  TestInt32Unop(kExprI32Ctz, 1, 0x9afdbc82);
-  TestInt32Unop(kExprI32Ctz, 0, 0x9afdbc81);
+WASM_EXEC_TEST(Int32Ctz) {
+  TestInt32Unop(execution_mode, kExprI32Ctz, 32, 0x00000000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 31, 0x80000000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 30, 0x40000000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 29, 0x20000000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 28, 0x10000000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 27, 0xa8000000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 26, 0xf4000000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 25, 0x62000000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 24, 0x91000000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 23, 0xcd800000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 22, 0x09400000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 21, 0xaf200000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 20, 0xac100000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 19, 0xe0b80000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 18, 0x9ce40000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 17, 0xc7920000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 16, 0xb8f10000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 15, 0x3b9f8000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 14, 0xdb4c4000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 13, 0xe9a32000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 12, 0xfca61000);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 11, 0x6c8a7800);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 10, 0x8ce5a400);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 9, 0xcb7d0200);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 8, 0xcb4dc100);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 7, 0xdfbec580);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 6, 0x27a9db40);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 5, 0xde3bcb20);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 4, 0xd7e8a610);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 3, 0x9afdbc88);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 2, 0x9afdbc84);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 1, 0x9afdbc82);
+  TestInt32Unop(execution_mode, kExprI32Ctz, 0, 0x9afdbc81);
 }
 
-
-TEST(Run_WasmInt32Popcnt) {
-  TestInt32Unop(kExprI32Popcnt, 32, 0xffffffff);
-  TestInt32Unop(kExprI32Popcnt, 0, 0x00000000);
-  TestInt32Unop(kExprI32Popcnt, 1, 0x00008000);
-  TestInt32Unop(kExprI32Popcnt, 13, 0x12345678);
-  TestInt32Unop(kExprI32Popcnt, 19, 0xfedcba09);
+WASM_EXEC_TEST(Int32Popcnt) {
+  TestInt32Unop(execution_mode, kExprI32Popcnt, 32, 0xffffffff);
+  TestInt32Unop(execution_mode, kExprI32Popcnt, 0, 0x00000000);
+  TestInt32Unop(execution_mode, kExprI32Popcnt, 1, 0x00008000);
+  TestInt32Unop(execution_mode, kExprI32Popcnt, 13, 0x12345678);
+  TestInt32Unop(execution_mode, kExprI32Popcnt, 19, 0xfedcba09);
 }
 
-TEST(Run_WasmI32Eqz) {
-  TestInt32Unop(kExprI32Eqz, 0, 1);
-  TestInt32Unop(kExprI32Eqz, 0, -1);
-  TestInt32Unop(kExprI32Eqz, 0, -827343);
-  TestInt32Unop(kExprI32Eqz, 0, 8888888);
-  TestInt32Unop(kExprI32Eqz, 1, 0);
+WASM_EXEC_TEST(I32Eqz) {
+  TestInt32Unop(execution_mode, kExprI32Eqz, 0, 1);
+  TestInt32Unop(execution_mode, kExprI32Eqz, 0, -1);
+  TestInt32Unop(execution_mode, kExprI32Eqz, 0, -827343);
+  TestInt32Unop(execution_mode, kExprI32Eqz, 0, 8888888);
+  TestInt32Unop(execution_mode, kExprI32Eqz, 1, 0);
 }
 
-TEST(Run_WasmI32Shl) {
-  WasmRunner<uint32_t> r(MachineType::Uint32(), MachineType::Uint32());
+WASM_EXEC_TEST(I32Shl) {
+  WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(),
+                         MachineType::Uint32());
   BUILD(r, WASM_I32_SHL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_UINT32_INPUTS(i) {
@@ -336,8 +325,9 @@
   }
 }
 
-TEST(Run_WasmI32Shr) {
-  WasmRunner<uint32_t> r(MachineType::Uint32(), MachineType::Uint32());
+WASM_EXEC_TEST(I32Shr) {
+  WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(),
+                         MachineType::Uint32());
   BUILD(r, WASM_I32_SHR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_UINT32_INPUTS(i) {
@@ -348,8 +338,9 @@
   }
 }
 
-TEST(Run_WasmI32Sar) {
-  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+WASM_EXEC_TEST(I32Sar) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
   BUILD(r, WASM_I32_SAR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_INT32_INPUTS(i) {
@@ -360,8 +351,9 @@
   }
 }
 
-TEST(Run_WASM_Int32DivS_trap) {
-  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+WASM_EXEC_TEST(Int32DivS_trap) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
   BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   const int32_t kMin = std::numeric_limits<int32_t>::min();
   CHECK_EQ(0, r.Call(0, 100));
@@ -371,9 +363,9 @@
   CHECK_TRAP(r.Call(kMin, 0));
 }
 
-
-TEST(Run_WASM_Int32RemS_trap) {
-  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+WASM_EXEC_TEST(Int32RemS_trap) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
   BUILD(r, WASM_I32_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   const int32_t kMin = std::numeric_limits<int32_t>::min();
   CHECK_EQ(33, r.Call(133, 100));
@@ -383,9 +375,9 @@
   CHECK_TRAP(r.Call(kMin, 0));
 }
 
-
-TEST(Run_WASM_Int32DivU_trap) {
-  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+WASM_EXEC_TEST(Int32DivU_trap) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
   BUILD(r, WASM_I32_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   const int32_t kMin = std::numeric_limits<int32_t>::min();
   CHECK_EQ(0, r.Call(0, 100));
@@ -395,9 +387,9 @@
   CHECK_TRAP(r.Call(kMin, 0));
 }
 
-
-TEST(Run_WASM_Int32RemU_trap) {
-  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+WASM_EXEC_TEST(Int32RemU_trap) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
   BUILD(r, WASM_I32_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   CHECK_EQ(17, r.Call(217, 100));
   const int32_t kMin = std::numeric_limits<int32_t>::min();
@@ -407,64 +399,11 @@
   CHECK_EQ(kMin, r.Call(kMin, -1));
 }
 
-TEST(Run_WASM_Int32DivS_asmjs) {
-  TestingModule module;
-  module.origin = kAsmJsOrigin;
-  WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
-  BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  const int32_t kMin = std::numeric_limits<int32_t>::min();
-  CHECK_EQ(0, r.Call(0, 100));
-  CHECK_EQ(0, r.Call(100, 0));
-  CHECK_EQ(0, r.Call(-1001, 0));
-  CHECK_EQ(kMin, r.Call(kMin, -1));
-  CHECK_EQ(0, r.Call(kMin, 0));
-}
-
-TEST(Run_WASM_Int32RemS_asmjs) {
-  TestingModule module;
-  module.origin = kAsmJsOrigin;
-  WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
-  BUILD(r, WASM_I32_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  const int32_t kMin = std::numeric_limits<int32_t>::min();
-  CHECK_EQ(33, r.Call(133, 100));
-  CHECK_EQ(0, r.Call(kMin, -1));
-  CHECK_EQ(0, r.Call(100, 0));
-  CHECK_EQ(0, r.Call(-1001, 0));
-  CHECK_EQ(0, r.Call(kMin, 0));
-}
-
-TEST(Run_WASM_Int32DivU_asmjs) {
-  TestingModule module;
-  module.origin = kAsmJsOrigin;
-  WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
-  BUILD(r, WASM_I32_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  const int32_t kMin = std::numeric_limits<int32_t>::min();
-  CHECK_EQ(0, r.Call(0, 100));
-  CHECK_EQ(0, r.Call(kMin, -1));
-  CHECK_EQ(0, r.Call(100, 0));
-  CHECK_EQ(0, r.Call(-1001, 0));
-  CHECK_EQ(0, r.Call(kMin, 0));
-}
-
-TEST(Run_WASM_Int32RemU_asmjs) {
-  TestingModule module;
-  module.origin = kAsmJsOrigin;
-  WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
-  BUILD(r, WASM_I32_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
-  const int32_t kMin = std::numeric_limits<int32_t>::min();
-  CHECK_EQ(17, r.Call(217, 100));
-  CHECK_EQ(0, r.Call(100, 0));
-  CHECK_EQ(0, r.Call(-1001, 0));
-  CHECK_EQ(0, r.Call(kMin, 0));
-  CHECK_EQ(kMin, r.Call(kMin, -1));
-}
-
-
-TEST(Run_WASM_Int32DivS_byzero_const) {
-  for (int8_t denom = -2; denom < 8; denom++) {
-    WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Int32DivS_byzero_const) {
+  for (int8_t denom = -2; denom < 8; ++denom) {
+    WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
     BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_I8(denom)));
-    for (int32_t val = -7; val < 8; val++) {
+    for (int32_t val = -7; val < 8; ++val) {
       if (denom == 0) {
         CHECK_TRAP(r.Call(val));
       } else {
@@ -474,13 +413,12 @@
   }
 }
 
-
-TEST(Run_WASM_Int32DivU_byzero_const) {
-  for (uint32_t denom = 0xfffffffe; denom < 8; denom++) {
-    WasmRunner<uint32_t> r(MachineType::Uint32());
+WASM_EXEC_TEST(Int32DivU_byzero_const) {
+  for (uint32_t denom = 0xfffffffe; denom < 8; ++denom) {
+    WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32());
     BUILD(r, WASM_I32_DIVU(WASM_GET_LOCAL(0), WASM_I32V_1(denom)));
 
-    for (uint32_t val = 0xfffffff0; val < 8; val++) {
+    for (uint32_t val = 0xfffffff0; val < 8; ++val) {
       if (denom == 0) {
         CHECK_TRAP(r.Call(val));
       } else {
@@ -490,9 +428,8 @@
   }
 }
 
-
-TEST(Run_WASM_Int32DivS_trap_effect) {
-  TestingModule module;
+WASM_EXEC_TEST(Int32DivS_trap_effect) {
+  TestingModule module(execution_mode);
   module.AddMemoryElems<int32_t>(8);
   WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
 
@@ -510,33 +447,36 @@
   CHECK_TRAP(r.Call(0, 0));
 }
 
-void TestFloat32Binop(WasmOpcode opcode, int32_t expected, float a, float b) {
+void TestFloat32Binop(WasmExecutionMode execution_mode, WasmOpcode opcode,
+                      int32_t expected, float a, float b) {
   {
-    WasmRunner<int32_t> r;
+    WasmRunner<int32_t> r(execution_mode);
     // return K op K
     BUILD(r, WASM_BINOP(opcode, WASM_F32(a), WASM_F32(b)));
     CHECK_EQ(expected, r.Call());
   }
   {
-    WasmRunner<int32_t> r(MachineType::Float32(), MachineType::Float32());
+    WasmRunner<int32_t> r(execution_mode, MachineType::Float32(),
+                          MachineType::Float32());
     // return a op b
     BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
     CHECK_EQ(expected, r.Call(a, b));
   }
 }
 
-
-void TestFloat32BinopWithConvert(WasmOpcode opcode, int32_t expected, float a,
+void TestFloat32BinopWithConvert(WasmExecutionMode execution_mode,
+                                 WasmOpcode opcode, int32_t expected, float a,
                                  float b) {
   {
-    WasmRunner<int32_t> r;
+    WasmRunner<int32_t> r(execution_mode);
     // return int(K op K)
     BUILD(r,
           WASM_I32_SCONVERT_F32(WASM_BINOP(opcode, WASM_F32(a), WASM_F32(b))));
     CHECK_EQ(expected, r.Call());
   }
   {
-    WasmRunner<int32_t> r(MachineType::Float32(), MachineType::Float32());
+    WasmRunner<int32_t> r(execution_mode, MachineType::Float32(),
+                          MachineType::Float32());
     // return int(a op b)
     BUILD(r, WASM_I32_SCONVERT_F32(
                  WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))));
@@ -544,116 +484,119 @@
   }
 }
 
-
-void TestFloat32UnopWithConvert(WasmOpcode opcode, int32_t expected, float a) {
+void TestFloat32UnopWithConvert(WasmExecutionMode execution_mode,
+                                WasmOpcode opcode, int32_t expected, float a) {
   {
-    WasmRunner<int32_t> r;
+    WasmRunner<int32_t> r(execution_mode);
     // return int(op(K))
     BUILD(r, WASM_I32_SCONVERT_F32(WASM_UNOP(opcode, WASM_F32(a))));
     CHECK_EQ(expected, r.Call());
   }
   {
-    WasmRunner<int32_t> r(MachineType::Float32());
+    WasmRunner<int32_t> r(execution_mode, MachineType::Float32());
     // return int(op(a))
     BUILD(r, WASM_I32_SCONVERT_F32(WASM_UNOP(opcode, WASM_GET_LOCAL(0))));
     CHECK_EQ(expected, r.Call(a));
   }
 }
 
-
-void TestFloat64Binop(WasmOpcode opcode, int32_t expected, double a, double b) {
+void TestFloat64Binop(WasmExecutionMode execution_mode, WasmOpcode opcode,
+                      int32_t expected, double a, double b) {
   {
-    WasmRunner<int32_t> r;
+    WasmRunner<int32_t> r(execution_mode);
     // return K op K
     BUILD(r, WASM_BINOP(opcode, WASM_F64(a), WASM_F64(b)));
     CHECK_EQ(expected, r.Call());
   }
   {
-    WasmRunner<int32_t> r(MachineType::Float64(), MachineType::Float64());
+    WasmRunner<int32_t> r(execution_mode, MachineType::Float64(),
+                          MachineType::Float64());
     // return a op b
     BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
     CHECK_EQ(expected, r.Call(a, b));
   }
 }
 
-
-void TestFloat64BinopWithConvert(WasmOpcode opcode, int32_t expected, double a,
+void TestFloat64BinopWithConvert(WasmExecutionMode execution_mode,
+                                 WasmOpcode opcode, int32_t expected, double a,
                                  double b) {
   {
-    WasmRunner<int32_t> r;
+    WasmRunner<int32_t> r(execution_mode);
     // return int(K op K)
     BUILD(r,
           WASM_I32_SCONVERT_F64(WASM_BINOP(opcode, WASM_F64(a), WASM_F64(b))));
     CHECK_EQ(expected, r.Call());
   }
   {
-    WasmRunner<int32_t> r(MachineType::Float64(), MachineType::Float64());
+    WasmRunner<int32_t> r(execution_mode, MachineType::Float64(),
+                          MachineType::Float64());
     BUILD(r, WASM_I32_SCONVERT_F64(
                  WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))));
     CHECK_EQ(expected, r.Call(a, b));
   }
 }
 
-
-void TestFloat64UnopWithConvert(WasmOpcode opcode, int32_t expected, double a) {
+void TestFloat64UnopWithConvert(WasmExecutionMode execution_mode,
+                                WasmOpcode opcode, int32_t expected, double a) {
   {
-    WasmRunner<int32_t> r;
+    WasmRunner<int32_t> r(execution_mode);
     // return int(op(K))
     BUILD(r, WASM_I32_SCONVERT_F64(WASM_UNOP(opcode, WASM_F64(a))));
     CHECK_EQ(expected, r.Call());
   }
   {
-    WasmRunner<int32_t> r(MachineType::Float64());
+    WasmRunner<int32_t> r(execution_mode, MachineType::Float64());
     // return int(op(a))
     BUILD(r, WASM_I32_SCONVERT_F64(WASM_UNOP(opcode, WASM_GET_LOCAL(0))));
     CHECK_EQ(expected, r.Call(a));
   }
 }
 
-TEST(Run_WasmFloat32Binops) {
-  TestFloat32Binop(kExprF32Eq, 1, 8.125f, 8.125f);
-  TestFloat32Binop(kExprF32Ne, 1, 8.125f, 8.127f);
-  TestFloat32Binop(kExprF32Lt, 1, -9.5f, -9.0f);
-  TestFloat32Binop(kExprF32Le, 1, -1111.0f, -1111.0f);
-  TestFloat32Binop(kExprF32Gt, 1, -9.0f, -9.5f);
-  TestFloat32Binop(kExprF32Ge, 1, -1111.0f, -1111.0f);
+WASM_EXEC_TEST(Float32Binops) {
+  TestFloat32Binop(execution_mode, kExprF32Eq, 1, 8.125f, 8.125f);
+  TestFloat32Binop(execution_mode, kExprF32Ne, 1, 8.125f, 8.127f);
+  TestFloat32Binop(execution_mode, kExprF32Lt, 1, -9.5f, -9.0f);
+  TestFloat32Binop(execution_mode, kExprF32Le, 1, -1111.0f, -1111.0f);
+  TestFloat32Binop(execution_mode, kExprF32Gt, 1, -9.0f, -9.5f);
+  TestFloat32Binop(execution_mode, kExprF32Ge, 1, -1111.0f, -1111.0f);
 
-  TestFloat32BinopWithConvert(kExprF32Add, 10, 3.5f, 6.5f);
-  TestFloat32BinopWithConvert(kExprF32Sub, 2, 44.5f, 42.5f);
-  TestFloat32BinopWithConvert(kExprF32Mul, -66, -132.1f, 0.5f);
-  TestFloat32BinopWithConvert(kExprF32Div, 11, 22.1f, 2.0f);
+  TestFloat32BinopWithConvert(execution_mode, kExprF32Add, 10, 3.5f, 6.5f);
+  TestFloat32BinopWithConvert(execution_mode, kExprF32Sub, 2, 44.5f, 42.5f);
+  TestFloat32BinopWithConvert(execution_mode, kExprF32Mul, -66, -132.1f, 0.5f);
+  TestFloat32BinopWithConvert(execution_mode, kExprF32Div, 11, 22.1f, 2.0f);
 }
 
-TEST(Run_WasmFloat32Unops) {
-  TestFloat32UnopWithConvert(kExprF32Abs, 8, 8.125f);
-  TestFloat32UnopWithConvert(kExprF32Abs, 9, -9.125f);
-  TestFloat32UnopWithConvert(kExprF32Neg, -213, 213.125f);
-  TestFloat32UnopWithConvert(kExprF32Sqrt, 12, 144.4f);
+WASM_EXEC_TEST(Float32Unops) {
+  TestFloat32UnopWithConvert(execution_mode, kExprF32Abs, 8, 8.125f);
+  TestFloat32UnopWithConvert(execution_mode, kExprF32Abs, 9, -9.125f);
+  TestFloat32UnopWithConvert(execution_mode, kExprF32Neg, -213, 213.125f);
+  TestFloat32UnopWithConvert(execution_mode, kExprF32Sqrt, 12, 144.4f);
 }
 
-TEST(Run_WasmFloat64Binops) {
-  TestFloat64Binop(kExprF64Eq, 1, 16.25, 16.25);
-  TestFloat64Binop(kExprF64Ne, 1, 16.25, 16.15);
-  TestFloat64Binop(kExprF64Lt, 1, -32.4, 11.7);
-  TestFloat64Binop(kExprF64Le, 1, -88.9, -88.9);
-  TestFloat64Binop(kExprF64Gt, 1, 11.7, -32.4);
-  TestFloat64Binop(kExprF64Ge, 1, -88.9, -88.9);
+WASM_EXEC_TEST(Float64Binops) {
+  TestFloat64Binop(execution_mode, kExprF64Eq, 1, 16.25, 16.25);
+  TestFloat64Binop(execution_mode, kExprF64Ne, 1, 16.25, 16.15);
+  TestFloat64Binop(execution_mode, kExprF64Lt, 1, -32.4, 11.7);
+  TestFloat64Binop(execution_mode, kExprF64Le, 1, -88.9, -88.9);
+  TestFloat64Binop(execution_mode, kExprF64Gt, 1, 11.7, -32.4);
+  TestFloat64Binop(execution_mode, kExprF64Ge, 1, -88.9, -88.9);
 
-  TestFloat64BinopWithConvert(kExprF64Add, 100, 43.5, 56.5);
-  TestFloat64BinopWithConvert(kExprF64Sub, 200, 12200.1, 12000.1);
-  TestFloat64BinopWithConvert(kExprF64Mul, -33, 134, -0.25);
-  TestFloat64BinopWithConvert(kExprF64Div, -1111, -2222.3, 2);
+  TestFloat64BinopWithConvert(execution_mode, kExprF64Add, 100, 43.5, 56.5);
+  TestFloat64BinopWithConvert(execution_mode, kExprF64Sub, 200, 12200.1,
+                              12000.1);
+  TestFloat64BinopWithConvert(execution_mode, kExprF64Mul, -33, 134, -0.25);
+  TestFloat64BinopWithConvert(execution_mode, kExprF64Div, -1111, -2222.3, 2);
 }
 
-TEST(Run_WasmFloat64Unops) {
-  TestFloat64UnopWithConvert(kExprF64Abs, 108, 108.125);
-  TestFloat64UnopWithConvert(kExprF64Abs, 209, -209.125);
-  TestFloat64UnopWithConvert(kExprF64Neg, -209, 209.125);
-  TestFloat64UnopWithConvert(kExprF64Sqrt, 13, 169.4);
+WASM_EXEC_TEST(Float64Unops) {
+  TestFloat64UnopWithConvert(execution_mode, kExprF64Abs, 108, 108.125);
+  TestFloat64UnopWithConvert(execution_mode, kExprF64Abs, 209, -209.125);
+  TestFloat64UnopWithConvert(execution_mode, kExprF64Neg, -209, 209.125);
+  TestFloat64UnopWithConvert(execution_mode, kExprF64Sqrt, 13, 169.4);
 }
 
-TEST(Run_WasmFloat32Neg) {
-  WasmRunner<float> r(MachineType::Float32());
+WASM_EXEC_TEST(Float32Neg) {
+  WasmRunner<float> r(execution_mode, MachineType::Float32());
   BUILD(r, WASM_F32_NEG(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT32_INPUTS(i) {
@@ -662,9 +605,48 @@
   }
 }
 
+WASM_EXEC_TEST(Float32SubMinusZero) {
+  WasmRunner<float> r(execution_mode, MachineType::Float32());
+  BUILD(r, WASM_F32_SUB(WASM_F32(-0.0), WASM_GET_LOCAL(0)));
 
-TEST(Run_WasmFloat64Neg) {
-  WasmRunner<double> r(MachineType::Float64());
+  uint32_t sNanValue =
+      bit_cast<uint32_t>(std::numeric_limits<float>::signaling_NaN());
+  uint32_t qNanValue =
+      bit_cast<uint32_t>(std::numeric_limits<float>::quiet_NaN());
+  uint32_t payload = 0x00200000;
+
+  uint32_t expected = (qNanValue & 0xffc00000) | payload;
+  uint32_t operand = (sNanValue & 0xffc00000) | payload;
+  CHECK_EQ(expected, bit_cast<uint32_t>(r.Call(bit_cast<float>(operand))));
+
+  // Change the sign of the NaN.
+  expected |= 0x80000000;
+  operand |= 0x80000000;
+  CHECK_EQ(expected, bit_cast<uint32_t>(r.Call(bit_cast<float>(operand))));
+}
+
+WASM_EXEC_TEST(Float64SubMinusZero) {
+  WasmRunner<double> r(execution_mode, MachineType::Float64());
+  BUILD(r, WASM_F64_SUB(WASM_F64(-0.0), WASM_GET_LOCAL(0)));
+
+  uint64_t sNanValue =
+      bit_cast<uint64_t>(std::numeric_limits<double>::signaling_NaN());
+  uint64_t qNanValue =
+      bit_cast<uint64_t>(std::numeric_limits<double>::quiet_NaN());
+  uint64_t payload = 0x0000123456789abc;
+
+  uint64_t expected = (qNanValue & 0xfff8000000000000) | payload;
+  uint64_t operand = (sNanValue & 0xfff8000000000000) | payload;
+  CHECK_EQ(expected, bit_cast<uint64_t>(r.Call(bit_cast<double>(operand))));
+
+  // Change the sign of the NaN.
+  expected |= 0x8000000000000000;
+  operand |= 0x8000000000000000;
+  CHECK_EQ(expected, bit_cast<uint64_t>(r.Call(bit_cast<double>(operand))));
+}
+
+WASM_EXEC_TEST(Float64Neg) {
+  WasmRunner<double> r(execution_mode, MachineType::Float64());
   BUILD(r, WASM_F64_NEG(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT64_INPUTS(i) {
@@ -673,9 +655,8 @@
   }
 }
 
-
-TEST(Run_Wasm_IfElse_P) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(IfElse_P) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   // if (p0) return 11; else return 22;
   BUILD(r, WASM_IF_ELSE(WASM_GET_LOCAL(0),  // --
                         WASM_I8(11),        // --
@@ -686,9 +667,59 @@
   }
 }
 
+WASM_EXEC_TEST(If_empty1) {
+  WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(),
+                         MachineType::Uint32());
+  BUILD(r, WASM_GET_LOCAL(0), kExprIf, kExprEnd, WASM_GET_LOCAL(1));
+  FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i - 9, *i)); }
+}
 
-TEST(Run_Wasm_IfElse_Unreachable1) {
-  WasmRunner<int32_t> r;
+WASM_EXEC_TEST(IfElse_empty1) {
+  WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(),
+                         MachineType::Uint32());
+  BUILD(r, WASM_GET_LOCAL(0), kExprIf, kExprElse, kExprEnd, WASM_GET_LOCAL(1));
+  FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i - 8, *i)); }
+}
+
+WASM_EXEC_TEST(IfElse_empty2) {
+  WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(),
+                         MachineType::Uint32());
+  BUILD(r, WASM_GET_LOCAL(0), kExprIf, WASM_ZERO, kExprElse, kExprEnd,
+        WASM_GET_LOCAL(1));
+  FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i - 7, *i)); }
+}
+
+WASM_EXEC_TEST(IfElse_empty3) {
+  WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(),
+                         MachineType::Uint32());
+  BUILD(r, WASM_GET_LOCAL(0), kExprIf, kExprElse, WASM_ZERO, kExprEnd,
+        WASM_GET_LOCAL(1));
+  FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i - 6, *i)); }
+}
+
+WASM_EXEC_TEST(If_chain) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
+  // if (p0) 13; if (p0) 14; 15
+  BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_I8(13)),
+        WASM_IF(WASM_GET_LOCAL(0), WASM_I8(14)), WASM_I8(15));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(15, r.Call(*i)); }
+}
+
+WASM_EXEC_TEST(If_chain_set) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
+  // if (p0) p1 = 73; if (p0) p1 = 74; p1
+  BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(1, WASM_I8(73))),
+        WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(1, WASM_I8(74))),
+        WASM_GET_LOCAL(1));
+  FOR_INT32_INPUTS(i) {
+    int32_t expected = *i ? 74 : *i;
+    CHECK_EQ(expected, r.Call(*i, *i));
+  }
+}
+
+WASM_EXEC_TEST(IfElse_Unreachable1) {
+  WasmRunner<int32_t> r(execution_mode);
   // if (0) unreachable; else return 22;
   BUILD(r, WASM_IF_ELSE(WASM_ZERO,         // --
                         WASM_UNREACHABLE,  // --
@@ -696,34 +727,30 @@
   CHECK_EQ(27, r.Call());
 }
 
-
-TEST(Run_Wasm_Return12) {
-  WasmRunner<int32_t> r;
+WASM_EXEC_TEST(Return12) {
+  WasmRunner<int32_t> r(execution_mode);
 
   BUILD(r, RET_I8(12));
   CHECK_EQ(12, r.Call());
 }
 
-
-TEST(Run_Wasm_Return17) {
-  WasmRunner<int32_t> r;
+WASM_EXEC_TEST(Return17) {
+  WasmRunner<int32_t> r(execution_mode);
 
   BUILD(r, B1(RET_I8(17)));
   CHECK_EQ(17, r.Call());
 }
 
-
-TEST(Run_Wasm_Return_I32) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Return_I32) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
 
   BUILD(r, RET(WASM_GET_LOCAL(0)));
 
   FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
 }
 
-
-TEST(Run_Wasm_Return_F32) {
-  WasmRunner<float> r(MachineType::Float32());
+WASM_EXEC_TEST(Return_F32) {
+  WasmRunner<float> r(execution_mode, MachineType::Float32());
 
   BUILD(r, RET(WASM_GET_LOCAL(0)));
 
@@ -738,9 +765,8 @@
   }
 }
 
-
-TEST(Run_Wasm_Return_F64) {
-  WasmRunner<double> r(MachineType::Float64());
+WASM_EXEC_TEST(Return_F64) {
+  WasmRunner<double> r(execution_mode, MachineType::Float64());
 
   BUILD(r, RET(WASM_GET_LOCAL(0)));
 
@@ -755,9 +781,8 @@
   }
 }
 
-
-TEST(Run_Wasm_Select) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Select) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   // return select(11, 22, a);
   BUILD(r, WASM_SELECT(WASM_I8(11), WASM_I8(22), WASM_GET_LOCAL(0)));
   FOR_INT32_INPUTS(i) {
@@ -766,9 +791,8 @@
   }
 }
 
-
-TEST(Run_Wasm_Select_strict1) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Select_strict1) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   // select(a=0, a=1, a=2); return a
   BUILD(r, B2(WASM_SELECT(WASM_SET_LOCAL(0, WASM_I8(0)),
                           WASM_SET_LOCAL(0, WASM_I8(1)),
@@ -777,9 +801,8 @@
   FOR_INT32_INPUTS(i) { CHECK_EQ(2, r.Call(*i)); }
 }
 
-
-TEST(Run_Wasm_Select_strict2) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Select_strict2) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   r.AllocateLocal(kAstI32);
   r.AllocateLocal(kAstI32);
   // select(b=5, c=6, a)
@@ -791,8 +814,8 @@
   }
 }
 
-TEST(Run_Wasm_Select_strict3) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Select_strict3) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   r.AllocateLocal(kAstI32);
   r.AllocateLocal(kAstI32);
   // select(b=5, c=6, a=b)
@@ -805,9 +828,8 @@
   }
 }
 
-
-TEST(Run_Wasm_BrIf_strict) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(BrIf_strict) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(
       r,
       B2(B1(WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_I8(99)))),
@@ -816,23 +838,23 @@
   FOR_INT32_INPUTS(i) { CHECK_EQ(99, r.Call(*i)); }
 }
 
-TEST(Run_Wasm_BrTable0a) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(BrTable0a) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r,
         B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0))), WASM_I8(91)));
   FOR_INT32_INPUTS(i) { CHECK_EQ(91, r.Call(*i)); }
 }
 
-TEST(Run_Wasm_BrTable0b) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(BrTable0b) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r,
         B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(0), BR_TARGET(0))),
            WASM_I8(92)));
   FOR_INT32_INPUTS(i) { CHECK_EQ(92, r.Call(*i)); }
 }
 
-TEST(Run_Wasm_BrTable0c) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(BrTable0c) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(
       r,
       B2(B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(0), BR_TARGET(1))),
@@ -844,14 +866,14 @@
   }
 }
 
-TEST(Run_Wasm_BrTable1) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(BrTable1) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r, B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0))), RET_I8(93));
   FOR_INT32_INPUTS(i) { CHECK_EQ(93, r.Call(*i)); }
 }
 
-TEST(Run_Wasm_BrTable_loop) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(BrTable_loop) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r,
         B2(WASM_LOOP(1, WASM_BR_TABLE(WASM_INC_LOCAL_BY(0, 1), 2, BR_TARGET(2),
                                       BR_TARGET(1), BR_TARGET(0))),
@@ -864,8 +886,8 @@
   CHECK_EQ(98, r.Call(-100));
 }
 
-TEST(Run_Wasm_BrTable_br) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(BrTable_br) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r,
         B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(1), BR_TARGET(0))),
            RET_I8(91)),
@@ -876,8 +898,8 @@
   CHECK_EQ(91, r.Call(3));
 }
 
-TEST(Run_Wasm_BrTable_br2) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(BrTable_br2) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
 
   BUILD(r, B2(B2(B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 3, BR_TARGET(1),
                                      BR_TARGET(2), BR_TARGET(3), BR_TARGET(0))),
@@ -893,9 +915,9 @@
   CHECK_EQ(85, r.Call(5));
 }
 
-TEST(Run_Wasm_BrTable4) {
-  for (int i = 0; i < 4; i++) {
-    for (int t = 0; t < 4; t++) {
+WASM_EXEC_TEST(BrTable4) {
+  for (int i = 0; i < 4; ++i) {
+    for (int t = 0; t < 4; ++t) {
       uint32_t cases[] = {0, 1, 2, 3};
       cases[i] = t;
       byte code[] = {B2(B2(B2(B2(B1(WASM_BR_TABLE(
@@ -908,10 +930,10 @@
                         RET_I8(73)),
                      WASM_I8(75)};
 
-      WasmRunner<int32_t> r(MachineType::Int32());
+      WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
       r.Build(code, code + arraysize(code));
 
-      for (int x = -3; x < 50; x++) {
+      for (int x = -3; x < 50; ++x) {
         int index = (x > 3 || x < 0) ? 3 : x;
         int32_t expected = 70 + cases[index];
         CHECK_EQ(expected, r.Call(x));
@@ -920,12 +942,12 @@
   }
 }
 
-TEST(Run_Wasm_BrTable4x4) {
-  for (byte a = 0; a < 4; a++) {
-    for (byte b = 0; b < 4; b++) {
-      for (byte c = 0; c < 4; c++) {
-        for (byte d = 0; d < 4; d++) {
-          for (int i = 0; i < 4; i++) {
+WASM_EXEC_TEST(BrTable4x4) {
+  for (byte a = 0; a < 4; ++a) {
+    for (byte b = 0; b < 4; ++b) {
+      for (byte c = 0; c < 4; ++c) {
+        for (byte d = 0; d < 4; ++d) {
+          for (int i = 0; i < 4; ++i) {
             uint32_t cases[] = {a, b, c, d};
             byte code[] = {
                 B2(B2(B2(B2(B1(WASM_BR_TABLE(
@@ -938,10 +960,10 @@
                    RET_I8(53)),
                 WASM_I8(55)};
 
-            WasmRunner<int32_t> r(MachineType::Int32());
+            WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
             r.Build(code, code + arraysize(code));
 
-            for (int x = -6; x < 47; x++) {
+            for (int x = -6; x < 47; ++x) {
               int index = (x > 3 || x < 0) ? 3 : x;
               int32_t expected = 50 + cases[index];
               CHECK_EQ(expected, r.Call(x));
@@ -953,7 +975,7 @@
   }
 }
 
-TEST(Run_Wasm_BrTable4_fallthru) {
+WASM_EXEC_TEST(BrTable4_fallthru) {
   byte code[] = {
       B2(B2(B2(B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 3, BR_TARGET(0),
                                    BR_TARGET(1), BR_TARGET(2), BR_TARGET(3))),
@@ -963,7 +985,8 @@
          WASM_INC_LOCAL_BY(1, 8)),
       WASM_GET_LOCAL(1)};
 
-  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
   r.Build(code, code + arraysize(code));
 
   CHECK_EQ(15, r.Call(0, 0));
@@ -979,8 +1002,8 @@
   CHECK_EQ(108, r.Call(4, 100));
 }
 
-TEST(Run_Wasm_F32ReinterpretI32) {
-  TestingModule module;
+WASM_EXEC_TEST(F32ReinterpretI32) {
+  TestingModule module(execution_mode);
   int32_t* memory = module.AddMemoryElems<int32_t>(8);
   WasmRunner<int32_t> r(&module);
 
@@ -994,9 +1017,8 @@
   }
 }
 
-
-TEST(Run_Wasm_I32ReinterpretF32) {
-  TestingModule module;
+WASM_EXEC_TEST(I32ReinterpretF32) {
+  TestingModule module(execution_mode);
   int32_t* memory = module.AddMemoryElems<int32_t>(8);
   WasmRunner<int32_t> r(&module, MachineType::Int32());
 
@@ -1012,9 +1034,8 @@
   }
 }
 
-
-TEST(Run_Wasm_ReturnStore) {
-  TestingModule module;
+WASM_EXEC_TEST(ReturnStore) {
+  TestingModule module(execution_mode);
   int32_t* memory = module.AddMemoryElems<int32_t>(8);
   WasmRunner<int32_t> r(&module);
 
@@ -1028,13 +1049,12 @@
   }
 }
 
-
-TEST(Run_Wasm_VoidReturn1) {
+WASM_EXEC_TEST(VoidReturn1) {
   // We use a wrapper function because WasmRunner<void> does not exist.
 
   // Build the test function.
   TestSignatures sigs;
-  TestingModule module;
+  TestingModule module(execution_mode);
   WasmFunctionCompiler t(sigs.v_v(), &module);
   BUILD(t, kExprNop);
   uint32_t index = t.CompileAndAdd();
@@ -1048,12 +1068,11 @@
   CHECK_EQ(kExpected, result);
 }
 
-
-TEST(Run_Wasm_VoidReturn2) {
+WASM_EXEC_TEST(VoidReturn2) {
   // We use a wrapper function because WasmRunner<void> does not exist.
   // Build the test function.
   TestSignatures sigs;
-  TestingModule module;
+  TestingModule module(execution_mode);
   WasmFunctionCompiler t(sigs.v_v(), &module);
   BUILD(t, WASM_RETURN0);
   uint32_t index = t.CompileAndAdd();
@@ -1067,13 +1086,43 @@
   CHECK_EQ(kExpected, result);
 }
 
+WASM_EXEC_TEST(Block_empty) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
+  BUILD(r, kExprBlock, kExprEnd, WASM_GET_LOCAL(0));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
+}
 
-TEST(Run_Wasm_Block_If_P) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Block_empty_br1) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
+  BUILD(r, B1(WASM_BR(0)), WASM_GET_LOCAL(0));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
+}
+
+WASM_EXEC_TEST(Block_empty_brif1) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
+  BUILD(r, B1(WASM_BR_IF(0, WASM_ZERO)), WASM_GET_LOCAL(0));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
+}
+
+WASM_EXEC_TEST(Block_empty_brif2) {
+  WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(),
+                         MachineType::Uint32());
+  BUILD(r, B1(WASM_BR_IF(0, WASM_GET_LOCAL(1))), WASM_GET_LOCAL(0));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i, *i + 1)); }
+}
+
+WASM_EXEC_TEST(Block_br2) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
+  BUILD(r, B1(WASM_BRV(0, WASM_GET_LOCAL(0))));
+  FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
+}
+
+WASM_EXEC_TEST(Block_If_P) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   // { if (p0) return 51; return 52; }
   BUILD(r, B2(                                     // --
                WASM_IF(WASM_GET_LOCAL(0),          // --
-                       WASM_BRV(0, WASM_I8(51))),  // --
+                       WASM_BRV(1, WASM_I8(51))),  // --
                WASM_I8(52)));                      // --
   FOR_INT32_INPUTS(i) {
     int32_t expected = *i ? 51 : 52;
@@ -1081,9 +1130,33 @@
   }
 }
 
+WASM_EXEC_TEST(Loop_empty) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
+  BUILD(r, kExprLoop, kExprEnd, WASM_GET_LOCAL(0));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
+}
 
-TEST(Run_Wasm_Block_BrIf_P) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Loop_empty_br1) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
+  BUILD(r, WASM_LOOP(1, WASM_BR(1)), WASM_GET_LOCAL(0));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
+}
+
+WASM_EXEC_TEST(Loop_empty_brif1) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
+  BUILD(r, WASM_LOOP(1, WASM_BR_IF(1, WASM_ZERO)), WASM_GET_LOCAL(0));
+  FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); }
+}
+
+WASM_EXEC_TEST(Loop_empty_brif2) {
+  WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(),
+                         MachineType::Uint32());
+  BUILD(r, WASM_LOOP(1, WASM_BR_IF(1, WASM_GET_LOCAL(1))), WASM_GET_LOCAL(0));
+  FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i, *i + 1)); }
+}
+
+WASM_EXEC_TEST(Block_BrIf_P) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r, B2(WASM_BRV_IF(0, WASM_I8(51), WASM_GET_LOCAL(0)), WASM_I8(52)));
   FOR_INT32_INPUTS(i) {
     int32_t expected = *i ? 51 : 52;
@@ -1091,9 +1164,8 @@
   }
 }
 
-
-TEST(Run_Wasm_Block_IfElse_P_assign) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Block_IfElse_P_assign) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   // { if (p0) p0 = 71; else p0 = 72; return p0; }
   BUILD(r, B2(                                                // --
                WASM_IF_ELSE(WASM_GET_LOCAL(0),                // --
@@ -1106,9 +1178,8 @@
   }
 }
 
-
-TEST(Run_Wasm_Block_IfElse_P_return) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Block_IfElse_P_return) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   // if (p0) return 81; else return 82;
   BUILD(r,                               // --
         WASM_IF_ELSE(WASM_GET_LOCAL(0),  // --
@@ -1120,9 +1191,8 @@
   }
 }
 
-
-TEST(Run_Wasm_Block_If_P_assign) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Block_If_P_assign) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   // { if (p0) p0 = 61; p0; }
   BUILD(r, WASM_BLOCK(
                2, WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_I8(61))),
@@ -1133,17 +1203,15 @@
   }
 }
 
-
-TEST(Run_Wasm_DanglingAssign) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(DanglingAssign) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   // { return 0; p0 = 0; }
   BUILD(r, B2(RET_I8(99), WASM_SET_LOCAL(0, WASM_ZERO)));
   CHECK_EQ(99, r.Call(1));
 }
 
-
-TEST(Run_Wasm_ExprIf_P) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(ExprIf_P) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   // p0 ? 11 : 22;
   BUILD(r, WASM_IF_ELSE(WASM_GET_LOCAL(0),  // --
                         WASM_I8(11),        // --
@@ -1154,9 +1222,8 @@
   }
 }
 
-
-TEST(Run_Wasm_ExprIf_P_fallthru) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(ExprIf_P_fallthru) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   // p0 ? 11 : 22;
   BUILD(r, WASM_IF_ELSE(WASM_GET_LOCAL(0),  // --
                         WASM_I8(11),        // --
@@ -1167,14 +1234,13 @@
   }
 }
 
-
-TEST(Run_Wasm_CountDown) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(CountDown) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r,
         WASM_BLOCK(
             2, WASM_LOOP(
                    1, WASM_IF(WASM_GET_LOCAL(0),
-                              WASM_BRV(0, WASM_SET_LOCAL(
+                              WASM_BRV(1, WASM_SET_LOCAL(
                                               0, WASM_I32_SUB(WASM_GET_LOCAL(0),
                                                               WASM_I8(1)))))),
             WASM_GET_LOCAL(0)));
@@ -1183,12 +1249,11 @@
   CHECK_EQ(0, r.Call(100));
 }
 
-
-TEST(Run_Wasm_CountDown_fallthru) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(CountDown_fallthru) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r,
         WASM_BLOCK(
-            2, WASM_LOOP(3, WASM_IF(WASM_NOT(WASM_GET_LOCAL(0)), WASM_BREAK(0)),
+            2, WASM_LOOP(3, WASM_IF(WASM_NOT(WASM_GET_LOCAL(0)), WASM_BREAK(1)),
                          WASM_SET_LOCAL(
                              0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(1))),
                          WASM_CONTINUE(0)),
@@ -1198,9 +1263,8 @@
   CHECK_EQ(0, r.Call(100));
 }
 
-
-TEST(Run_Wasm_WhileCountDown) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(WhileCountDown) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r, WASM_BLOCK(
                2, WASM_WHILE(WASM_GET_LOCAL(0),
                              WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0),
@@ -1211,10 +1275,9 @@
   CHECK_EQ(0, r.Call(100));
 }
 
-
-TEST(Run_Wasm_Loop_if_break1) {
-  WasmRunner<int32_t> r(MachineType::Int32());
-  BUILD(r, B2(WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(0)),
+WASM_EXEC_TEST(Loop_if_break1) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
+  BUILD(r, B2(WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(1)),
                         WASM_SET_LOCAL(0, WASM_I8(99))),
               WASM_GET_LOCAL(0)));
   CHECK_EQ(99, r.Call(0));
@@ -1223,9 +1286,8 @@
   CHECK_EQ(-29, r.Call(-29));
 }
 
-
-TEST(Run_Wasm_Loop_if_break2) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Loop_if_break2) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r, B2(WASM_LOOP(2, WASM_BR_IF(1, WASM_GET_LOCAL(0)),
                         WASM_SET_LOCAL(0, WASM_I8(99))),
               WASM_GET_LOCAL(0)));
@@ -1235,9 +1297,8 @@
   CHECK_EQ(-29, r.Call(-29));
 }
 
-
-TEST(Run_Wasm_Loop_if_break_fallthru) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Loop_if_break_fallthru) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r, B1(WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BREAK(1)),
                         WASM_SET_LOCAL(0, WASM_I8(93)))),
         WASM_GET_LOCAL(0));
@@ -1247,9 +1308,26 @@
   CHECK_EQ(-22, r.Call(-22));
 }
 
+WASM_EXEC_TEST(IfBreak1) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
+  BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_SEQ(WASM_BR(0), WASM_UNREACHABLE)),
+        WASM_I8(91));
+  CHECK_EQ(91, r.Call(0));
+  CHECK_EQ(91, r.Call(1));
+  CHECK_EQ(91, r.Call(-8734));
+}
 
-TEST(Run_Wasm_LoadMemI32) {
-  TestingModule module;
+WASM_EXEC_TEST(IfBreak2) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
+  BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_SEQ(WASM_BR(0), RET_I8(77))),
+        WASM_I8(81));
+  CHECK_EQ(81, r.Call(0));
+  CHECK_EQ(81, r.Call(1));
+  CHECK_EQ(81, r.Call(-8734));
+}
+
+WASM_EXEC_TEST(LoadMemI32) {
+  TestingModule module(execution_mode);
   int32_t* memory = module.AddMemoryElems<int32_t>(8);
   WasmRunner<int32_t> r(&module, MachineType::Int32());
   module.RandomizeMemory(1111);
@@ -1266,9 +1344,29 @@
   CHECK_EQ(77777777, r.Call(0));
 }
 
+WASM_EXEC_TEST(LoadMemI32_alignment) {
+  TestingModule module(execution_mode);
+  int32_t* memory = module.AddMemoryElems<int32_t>(8);
+  for (byte alignment = 0; alignment <= 2; ++alignment) {
+    WasmRunner<int32_t> r(&module, MachineType::Int32());
+    module.RandomizeMemory(1111);
 
-TEST(Run_Wasm_LoadMemI32_oob) {
-  TestingModule module;
+    BUILD(r,
+          WASM_LOAD_MEM_ALIGNMENT(MachineType::Int32(), WASM_I8(0), alignment));
+
+    memory[0] = 0x1a2b3c4d;
+    CHECK_EQ(0x1a2b3c4d, r.Call(0));
+
+    memory[0] = 0x5e6f7a8b;
+    CHECK_EQ(0x5e6f7a8b, r.Call(0));
+
+    memory[0] = 0x9ca0b1c2;
+    CHECK_EQ(0x9ca0b1c2, r.Call(0));
+  }
+}
+
+WASM_EXEC_TEST(LoadMemI32_oob) {
+  TestingModule module(execution_mode);
   int32_t* memory = module.AddMemoryElems<int32_t>(8);
   WasmRunner<int32_t> r(&module, MachineType::Uint32());
   module.RandomizeMemory(1111);
@@ -1277,40 +1375,17 @@
 
   memory[0] = 88888888;
   CHECK_EQ(88888888, r.Call(0u));
-  for (uint32_t offset = 29; offset < 40; offset++) {
+  for (uint32_t offset = 29; offset < 40; ++offset) {
     CHECK_TRAP(r.Call(offset));
   }
 
-  for (uint32_t offset = 0x80000000; offset < 0x80000010; offset++) {
+  for (uint32_t offset = 0x80000000; offset < 0x80000010; ++offset) {
     CHECK_TRAP(r.Call(offset));
   }
 }
 
-
-TEST(Run_Wasm_LoadMemI32_oob_asm) {
-  TestingModule module;
-  module.origin = kAsmJsOrigin;
-  int32_t* memory = module.AddMemoryElems<int32_t>(8);
-  WasmRunner<int32_t> r(&module, MachineType::Uint32());
-  module.RandomizeMemory(1112);
-
-  BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0)));
-
-  memory[0] = 999999;
-  CHECK_EQ(999999, r.Call(0u));
-  // TODO(titzer): offset 29-31 should also be OOB.
-  for (uint32_t offset = 32; offset < 40; offset++) {
-    CHECK_EQ(0, r.Call(offset));
-  }
-
-  for (uint32_t offset = 0x80000000; offset < 0x80000010; offset++) {
-    CHECK_EQ(0, r.Call(offset));
-  }
-}
-
-
-TEST(Run_Wasm_LoadMem_offset_oob) {
-  TestingModule module;
+WASM_EXEC_TEST(LoadMem_offset_oob) {
+  TestingModule module(execution_mode);
   module.AddMemoryElems<int32_t>(8);
 
   static const MachineType machineTypes[] = {
@@ -1319,7 +1394,7 @@
       MachineType::Int64(),  MachineType::Uint64(), MachineType::Float32(),
       MachineType::Float64()};
 
-  for (size_t m = 0; m < arraysize(machineTypes); m++) {
+  for (size_t m = 0; m < arraysize(machineTypes); ++m) {
     module.RandomizeMemory(1116 + static_cast<int>(m));
     WasmRunner<int32_t> r(&module, MachineType::Uint32());
     uint32_t boundary = 24 - WasmOpcodes::MemSize(machineTypes[m]);
@@ -1329,15 +1404,14 @@
 
     CHECK_EQ(0, r.Call(boundary));  // in bounds.
 
-    for (uint32_t offset = boundary + 1; offset < boundary + 19; offset++) {
+    for (uint32_t offset = boundary + 1; offset < boundary + 19; ++offset) {
       CHECK_TRAP(r.Call(offset));  // out of bounds.
     }
   }
 }
 
-
-TEST(Run_Wasm_LoadMemI32_offset) {
-  TestingModule module;
+WASM_EXEC_TEST(LoadMemI32_offset) {
+  TestingModule module(execution_mode);
   int32_t* memory = module.AddMemoryElems<int32_t>(4);
   WasmRunner<int32_t> r(&module, MachineType::Int32());
   module.RandomizeMemory(1111);
@@ -1361,15 +1435,12 @@
   CHECK_EQ(44444444, r.Call(8));
 }
 
-
-#if !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_MIPS64
-
-TEST(Run_Wasm_LoadMemI32_const_oob_misaligned) {
+WASM_EXEC_TEST(LoadMemI32_const_oob_misaligned) {
   const int kMemSize = 12;
   // TODO(titzer): Fix misaligned accesses on MIPS and re-enable.
-  for (int offset = 0; offset < kMemSize + 5; offset++) {
-    for (int index = 0; index < kMemSize + 5; index++) {
-      TestingModule module;
+  for (int offset = 0; offset < kMemSize + 5; ++offset) {
+    for (int index = 0; index < kMemSize + 5; ++index) {
+      TestingModule module(execution_mode);
       module.AddMemoryElems<byte>(kMemSize);
 
       WasmRunner<int32_t> r(&module);
@@ -1387,14 +1458,11 @@
   }
 }
 
-#endif
-
-
-TEST(Run_Wasm_LoadMemI32_const_oob) {
+WASM_EXEC_TEST(LoadMemI32_const_oob) {
   const int kMemSize = 24;
   for (int offset = 0; offset < kMemSize + 5; offset += 4) {
     for (int index = 0; index < kMemSize + 5; index += 4) {
-      TestingModule module;
+      TestingModule module(execution_mode);
       module.AddMemoryElems<byte>(kMemSize);
 
       WasmRunner<int32_t> r(&module);
@@ -1412,9 +1480,25 @@
   }
 }
 
+WASM_EXEC_TEST(StoreMemI32_alignment) {
+  TestingModule module(execution_mode);
+  int32_t* memory = module.AddMemoryElems<int32_t>(4);
+  const int32_t kWritten = 0x12345678;
 
-TEST(Run_Wasm_StoreMemI32_offset) {
-  TestingModule module;
+  for (byte i = 0; i <= 2; ++i) {
+    WasmRunner<int32_t> r(&module, MachineType::Int32());
+    BUILD(r, WASM_STORE_MEM_ALIGNMENT(MachineType::Int32(), WASM_ZERO, i,
+                                      WASM_GET_LOCAL(0)));
+    module.RandomizeMemory(1111);
+    memory[0] = 0;
+
+    CHECK_EQ(kWritten, r.Call(kWritten));
+    CHECK_EQ(kWritten, memory[0]);
+  }
+}
+
+WASM_EXEC_TEST(StoreMemI32_offset) {
+  TestingModule module(execution_mode);
   int32_t* memory = module.AddMemoryElems<int32_t>(4);
   WasmRunner<int32_t> r(&module, MachineType::Int32());
   const int32_t kWritten = 0xaabbccdd;
@@ -1422,7 +1506,7 @@
   BUILD(r, WASM_STORE_MEM_OFFSET(MachineType::Int32(), 4, WASM_GET_LOCAL(0),
                                  WASM_I32V_5(kWritten)));
 
-  for (int i = 0; i < 2; i++) {
+  for (int i = 0; i < 2; ++i) {
     module.RandomizeMemory(1111);
     memory[0] = 66666666;
     memory[1] = 77777777;
@@ -1436,25 +1520,17 @@
   }
 }
 
-
-TEST(Run_Wasm_StoreMem_offset_oob) {
-  TestingModule module;
+WASM_EXEC_TEST(StoreMem_offset_oob) {
+  TestingModule module(execution_mode);
   byte* memory = module.AddMemoryElems<byte>(32);
 
-#if WASM_64
-  static const MachineType machineTypes[] = {
-      MachineType::Int8(),   MachineType::Uint8(),  MachineType::Int16(),
-      MachineType::Uint16(), MachineType::Int32(),  MachineType::Uint32(),
-      MachineType::Int64(),  MachineType::Uint64(), MachineType::Float32(),
-      MachineType::Float64()};
-#else
+  // 64-bit cases are handled in test-run-wasm-64.cc
   static const MachineType machineTypes[] = {
       MachineType::Int8(),    MachineType::Uint8(),  MachineType::Int16(),
       MachineType::Uint16(),  MachineType::Int32(),  MachineType::Uint32(),
       MachineType::Float32(), MachineType::Float64()};
-#endif
 
-  for (size_t m = 0; m < arraysize(machineTypes); m++) {
+  for (size_t m = 0; m < arraysize(machineTypes); ++m) {
     module.RandomizeMemory(1119 + static_cast<int>(m));
     WasmRunner<int32_t> r(&module, MachineType::Uint32());
 
@@ -1467,31 +1543,29 @@
     CHECK_EQ(0, r.Call(boundary));  // in bounds.
     CHECK_EQ(0, memcmp(&memory[0], &memory[8 + boundary], memsize));
 
-    for (uint32_t offset = boundary + 1; offset < boundary + 19; offset++) {
+    for (uint32_t offset = boundary + 1; offset < boundary + 19; ++offset) {
       CHECK_TRAP(r.Call(offset));  // out of bounds.
     }
   }
 }
 
-
-TEST(Run_Wasm_LoadMemI32_P) {
+WASM_EXEC_TEST(LoadMemI32_P) {
   const int kNumElems = 8;
-  TestingModule module;
+  TestingModule module(execution_mode);
   int32_t* memory = module.AddMemoryElems<int32_t>(kNumElems);
   WasmRunner<int32_t> r(&module, MachineType::Int32());
   module.RandomizeMemory(2222);
 
   BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0)));
 
-  for (int i = 0; i < kNumElems; i++) {
+  for (int i = 0; i < kNumElems; ++i) {
     CHECK_EQ(memory[i], r.Call(i * 4));
   }
 }
 
-
-TEST(Run_Wasm_MemI32_Sum) {
+WASM_EXEC_TEST(MemI32_Sum) {
   const int kNumElems = 20;
-  TestingModule module;
+  TestingModule module(execution_mode);
   uint32_t* memory = module.AddMemoryElems<uint32_t>(kNumElems);
   WasmRunner<uint32_t> r(&module, MachineType::Int32());
   const byte kSum = r.AllocateLocal(kAstI32);
@@ -1510,37 +1584,35 @@
                WASM_GET_LOCAL(1)));
 
   // Run 4 trials.
-  for (int i = 0; i < 3; i++) {
+  for (int i = 0; i < 3; ++i) {
     module.RandomizeMemory(i * 33);
     uint32_t expected = 0;
-    for (size_t j = kNumElems - 1; j > 0; j--) {
+    for (size_t j = kNumElems - 1; j > 0; --j) {
       expected += memory[j];
     }
-    uint32_t result = r.Call(static_cast<int>(4 * (kNumElems - 1)));
+    uint32_t result = r.Call(4 * (kNumElems - 1));
     CHECK_EQ(expected, result);
   }
 }
 
-
-TEST(Run_Wasm_CheckMachIntsZero) {
+WASM_EXEC_TEST(CheckMachIntsZero) {
   const int kNumElems = 55;
-  TestingModule module;
+  TestingModule module(execution_mode);
   module.AddMemoryElems<uint32_t>(kNumElems);
   WasmRunner<uint32_t> r(&module, MachineType::Int32());
 
-  BUILD(r, kExprBlock, 2, kExprLoop, 1, kExprIf, kExprGetLocal, 0, kExprBr, 0,
-        kExprIfElse, kExprI32LoadMem, ZERO_ALIGNMENT, ZERO_OFFSET,
-        kExprGetLocal, 0, kExprBr, 2, kExprI8Const, 255, kExprSetLocal, 0,
-        kExprI32Sub, kExprGetLocal, 0, kExprI8Const, 4, kExprI8Const, 0);
+  BUILD(r, kExprLoop, kExprGetLocal, 0, kExprIf, kExprGetLocal, 0,
+        kExprI32LoadMem, 0, 0, kExprIf, kExprI8Const, 255, kExprReturn, ARITY_1,
+        kExprEnd, kExprGetLocal, 0, kExprI8Const, 4, kExprI32Sub, kExprSetLocal,
+        0, kExprBr, ARITY_1, DEPTH_0, kExprEnd, kExprEnd, kExprI8Const, 0);
 
   module.BlankMemory();
   CHECK_EQ(0, r.Call((kNumElems - 1) * 4));
 }
 
-
-TEST(Run_Wasm_MemF32_Sum) {
+WASM_EXEC_TEST(MemF32_Sum) {
   const int kSize = 5;
-  TestingModule module;
+  TestingModule module(execution_mode);
   module.AddMemoryElems<float>(kSize);
   float* buffer = module.raw_mem_start<float>();
   buffer[0] = -99.25;
@@ -1571,13 +1643,13 @@
   CHECK_EQ(71256.0f, buffer[0]);
 }
 
-
 template <typename T>
-T GenerateAndRunFold(WasmOpcode binop, T* buffer, size_t size,
-                     LocalType astType, MachineType memType) {
-  TestingModule module;
+T GenerateAndRunFold(WasmExecutionMode execution_mode, WasmOpcode binop,
+                     T* buffer, uint32_t size, LocalType astType,
+                     MachineType memType) {
+  TestingModule module(execution_mode);
   module.AddMemoryElems<T>(size);
-  for (size_t i = 0; i < size; i++) {
+  for (uint32_t i = 0; i < size; ++i) {
     module.raw_mem_start<T>()[i] = buffer[i];
   }
   WasmRunner<int32_t> r(&module, MachineType::Int32());
@@ -1602,25 +1674,23 @@
   return module.raw_mem_at<double>(0);
 }
 
-
-TEST(Run_Wasm_MemF64_Mul) {
+WASM_EXEC_TEST(MemF64_Mul) {
   const size_t kSize = 6;
   double buffer[kSize] = {1, 2, 2, 2, 2, 2};
-  double result = GenerateAndRunFold<double>(kExprF64Mul, buffer, kSize,
-                                             kAstF64, MachineType::Float64());
+  double result =
+      GenerateAndRunFold<double>(execution_mode, kExprF64Mul, buffer, kSize,
+                                 kAstF64, MachineType::Float64());
   CHECK_EQ(32, result);
 }
 
-
-TEST(Build_Wasm_Infinite_Loop) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Build_Wasm_Infinite_Loop) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   // Only build the graph and compile, don't run.
   BUILD(r, WASM_INFINITE_LOOP);
 }
 
-
-TEST(Build_Wasm_Infinite_Loop_effect) {
-  TestingModule module;
+WASM_EXEC_TEST(Build_Wasm_Infinite_Loop_effect) {
+  TestingModule module(execution_mode);
   module.AddMemoryElems<int8_t>(16);
   WasmRunner<int32_t> r(&module, MachineType::Int32());
 
@@ -1628,92 +1698,78 @@
   BUILD(r, WASM_LOOP(1, WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)));
 }
 
-
-TEST(Run_Wasm_Unreachable0a) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Unreachable0a) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r, B2(WASM_BRV(0, WASM_I8(9)), RET(WASM_GET_LOCAL(0))));
   CHECK_EQ(9, r.Call(0));
   CHECK_EQ(9, r.Call(1));
 }
 
-
-TEST(Run_Wasm_Unreachable0b) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Unreachable0b) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r, B2(WASM_BRV(0, WASM_I8(7)), WASM_UNREACHABLE));
   CHECK_EQ(7, r.Call(0));
   CHECK_EQ(7, r.Call(1));
 }
 
-
 TEST(Build_Wasm_Unreachable1) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+  WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32());
   BUILD(r, WASM_UNREACHABLE);
 }
 
-
 TEST(Build_Wasm_Unreachable2) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+  WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32());
   BUILD(r, WASM_UNREACHABLE, WASM_UNREACHABLE);
 }
 
-
 TEST(Build_Wasm_Unreachable3) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+  WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32());
   BUILD(r, WASM_UNREACHABLE, WASM_UNREACHABLE, WASM_UNREACHABLE);
 }
 
-
 TEST(Build_Wasm_UnreachableIf1) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+  WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32());
   BUILD(r, WASM_UNREACHABLE, WASM_IF(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
 }
 
-
 TEST(Build_Wasm_UnreachableIf2) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+  WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32());
   BUILD(r, WASM_UNREACHABLE,
         WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_UNREACHABLE));
 }
 
-
-TEST(Run_Wasm_Unreachable_Load) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Unreachable_Load) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r, B2(WASM_BRV(0, WASM_GET_LOCAL(0)),
               WASM_LOAD_MEM(MachineType::Int8(), WASM_GET_LOCAL(0))));
   CHECK_EQ(11, r.Call(11));
   CHECK_EQ(21, r.Call(21));
 }
 
-
-TEST(Run_Wasm_Infinite_Loop_not_taken1) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Infinite_Loop_not_taken1) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_INFINITE_LOOP), WASM_I8(45)));
   // Run the code, but don't go into the infinite loop.
   CHECK_EQ(45, r.Call(0));
 }
 
-
-TEST(Run_Wasm_Infinite_Loop_not_taken2) {
-  WasmRunner<int32_t> r(MachineType::Int32());
-  BUILD(r, B1(WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(45)),
+WASM_EXEC_TEST(Infinite_Loop_not_taken2) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
+  BUILD(r, B1(WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_I8(45)),
                            WASM_INFINITE_LOOP)));
   // Run the code, but don't go into the infinite loop.
   CHECK_EQ(45, r.Call(1));
 }
 
-
-TEST(Run_Wasm_Infinite_Loop_not_taken2_brif) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(Infinite_Loop_not_taken2_brif) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r,
         B2(WASM_BRV_IF(0, WASM_I8(45), WASM_GET_LOCAL(0)), WASM_INFINITE_LOOP));
   // Run the code, but don't go into the infinite loop.
   CHECK_EQ(45, r.Call(1));
 }
 
-
 static void TestBuildGraphForSimpleExpression(WasmOpcode opcode) {
-  if (!WasmOpcodes::IsSupported(opcode)) return;
-
   Isolate* isolate = CcTest::InitIsolateOnce();
   Zone zone(isolate->allocator());
   HandleScope scope(isolate);
@@ -1726,20 +1782,18 @@
   FunctionSig* sig = WasmOpcodes::Signature(opcode);
 
   if (sig->parameter_count() == 1) {
-    byte code[] = {WASM_NO_LOCALS, static_cast<byte>(opcode), kExprGetLocal, 0};
-    TestBuildingGraph(&zone, &jsgraph, nullptr, sig, code,
+    byte code[] = {WASM_NO_LOCALS, kExprGetLocal, 0, static_cast<byte>(opcode)};
+    TestBuildingGraph(&zone, &jsgraph, nullptr, sig, nullptr, code,
                       code + arraysize(code));
   } else {
     CHECK_EQ(2, sig->parameter_count());
-    byte code[] = {WASM_NO_LOCALS, static_cast<byte>(opcode),
-                   kExprGetLocal,  0,
-                   kExprGetLocal,  1};
-    TestBuildingGraph(&zone, &jsgraph, nullptr, sig, code,
+    byte code[] = {WASM_NO_LOCALS,           kExprGetLocal, 0, kExprGetLocal, 1,
+                   static_cast<byte>(opcode)};
+    TestBuildingGraph(&zone, &jsgraph, nullptr, sig, nullptr, code,
                       code + arraysize(code));
   }
 }
 
-
 TEST(Build_Wasm_SimpleExprs) {
 // Test that the decoder can build a graph for all supported simple expressions.
 #define GRAPH_BUILD_TEST(name, opcode, sig) \
@@ -1750,9 +1804,8 @@
 #undef GRAPH_BUILD_TEST
 }
 
-
-TEST(Run_Wasm_Int32LoadInt8_signext) {
-  TestingModule module;
+WASM_EXEC_TEST(Int32LoadInt8_signext) {
+  TestingModule module(execution_mode);
   const int kNumElems = 16;
   int8_t* memory = module.AddMemoryElems<int8_t>(kNumElems);
   module.RandomizeMemory();
@@ -1760,14 +1813,13 @@
   WasmRunner<int32_t> r(&module, MachineType::Int32());
   BUILD(r, WASM_LOAD_MEM(MachineType::Int8(), WASM_GET_LOCAL(0)));
 
-  for (size_t i = 0; i < kNumElems; i++) {
-    CHECK_EQ(memory[i], r.Call(static_cast<int>(i)));
+  for (int i = 0; i < kNumElems; ++i) {
+    CHECK_EQ(memory[i], r.Call(i));
   }
 }
 
-
-TEST(Run_Wasm_Int32LoadInt8_zeroext) {
-  TestingModule module;
+WASM_EXEC_TEST(Int32LoadInt8_zeroext) {
+  TestingModule module(execution_mode);
   const int kNumElems = 16;
   byte* memory = module.AddMemory(kNumElems);
   module.RandomizeMemory(77);
@@ -1775,14 +1827,13 @@
   WasmRunner<int32_t> r(&module, MachineType::Int32());
   BUILD(r, WASM_LOAD_MEM(MachineType::Uint8(), WASM_GET_LOCAL(0)));
 
-  for (size_t i = 0; i < kNumElems; i++) {
-    CHECK_EQ(memory[i], r.Call(static_cast<int>(i)));
+  for (int i = 0; i < kNumElems; ++i) {
+    CHECK_EQ(memory[i], r.Call(i));
   }
 }
 
-
-TEST(Run_Wasm_Int32LoadInt16_signext) {
-  TestingModule module;
+WASM_EXEC_TEST(Int32LoadInt16_signext) {
+  TestingModule module(execution_mode);
   const int kNumBytes = 16;
   byte* memory = module.AddMemory(kNumBytes);
   module.RandomizeMemory(888);
@@ -1790,15 +1841,14 @@
   WasmRunner<int32_t> r(&module, MachineType::Int32());
   BUILD(r, WASM_LOAD_MEM(MachineType::Int16(), WASM_GET_LOCAL(0)));
 
-  for (size_t i = 0; i < kNumBytes; i += 2) {
+  for (int i = 0; i < kNumBytes; i += 2) {
     int32_t expected = memory[i] | (static_cast<int8_t>(memory[i + 1]) << 8);
-    CHECK_EQ(expected, r.Call(static_cast<int>(i)));
+    CHECK_EQ(expected, r.Call(i));
   }
 }
 
-
-TEST(Run_Wasm_Int32LoadInt16_zeroext) {
-  TestingModule module;
+WASM_EXEC_TEST(Int32LoadInt16_zeroext) {
+  TestingModule module(execution_mode);
   const int kNumBytes = 16;
   byte* memory = module.AddMemory(kNumBytes);
   module.RandomizeMemory(9999);
@@ -1806,15 +1856,14 @@
   WasmRunner<int32_t> r(&module, MachineType::Int32());
   BUILD(r, WASM_LOAD_MEM(MachineType::Uint16(), WASM_GET_LOCAL(0)));
 
-  for (size_t i = 0; i < kNumBytes; i += 2) {
+  for (int i = 0; i < kNumBytes; i += 2) {
     int32_t expected = memory[i] | (memory[i + 1] << 8);
-    CHECK_EQ(expected, r.Call(static_cast<int>(i)));
+    CHECK_EQ(expected, r.Call(i));
   }
 }
 
-
-TEST(Run_WasmInt32Global) {
-  TestingModule module;
+WASM_EXEC_TEST(Int32Global) {
+  TestingModule module(execution_mode);
   int32_t* global = module.AddGlobal<int32_t>(MachineType::Int32());
   WasmRunner<int32_t> r(&module, MachineType::Int32());
   // global = global + p0
@@ -1829,15 +1878,14 @@
   }
 }
 
-
-TEST(Run_WasmInt32Globals_DontAlias) {
+WASM_EXEC_TEST(Int32Globals_DontAlias) {
   const int kNumGlobals = 3;
-  TestingModule module;
+  TestingModule module(execution_mode);
   int32_t* globals[] = {module.AddGlobal<int32_t>(MachineType::Int32()),
                         module.AddGlobal<int32_t>(MachineType::Int32()),
                         module.AddGlobal<int32_t>(MachineType::Int32())};
 
-  for (int g = 0; g < kNumGlobals; g++) {
+  for (int g = 0; g < kNumGlobals; ++g) {
     // global = global + p0
     WasmRunner<int32_t> r(&module, MachineType::Int32());
     BUILD(r, WASM_STORE_GLOBAL(
@@ -1848,9 +1896,9 @@
     int32_t before[kNumGlobals];
     for (int i = 9; i < 444444; i += 111113) {
       int32_t sum = *globals[g] + i;
-      for (int j = 0; j < kNumGlobals; j++) before[j] = *globals[j];
+      for (int j = 0; j < kNumGlobals; ++j) before[j] = *globals[j];
       r.Call(i);
-      for (int j = 0; j < kNumGlobals; j++) {
+      for (int j = 0; j < kNumGlobals; ++j) {
         int32_t expected = j == g ? sum : before[j];
         CHECK_EQ(expected, *globals[j]);
       }
@@ -1858,9 +1906,8 @@
   }
 }
 
-
-TEST(Run_WasmFloat32Global) {
-  TestingModule module;
+WASM_EXEC_TEST(Float32Global) {
+  TestingModule module(execution_mode);
   float* global = module.AddGlobal<float>(MachineType::Float32());
   WasmRunner<int32_t> r(&module, MachineType::Int32());
   // global = global + p0
@@ -1877,9 +1924,8 @@
   }
 }
 
-
-TEST(Run_WasmFloat64Global) {
-  TestingModule module;
+WASM_EXEC_TEST(Float64Global) {
+  TestingModule module(execution_mode);
   double* global = module.AddGlobal<double>(MachineType::Float64());
   WasmRunner<int32_t> r(&module, MachineType::Int32());
   // global = global + p0
@@ -1896,9 +1942,8 @@
   }
 }
 
-
-TEST(Run_WasmMixedGlobals) {
-  TestingModule module;
+WASM_EXEC_TEST(MixedGlobals) {
+  TestingModule module(execution_mode);
   int32_t* unused = module.AddGlobal<int32_t>(MachineType::Int32());
   byte* memory = module.AddMemory(32);
 
@@ -1951,12 +1996,11 @@
   USE(unused);
 }
 
-
-TEST(Run_WasmCallEmpty) {
+WASM_EXEC_TEST(CallEmpty) {
   const int32_t kExpected = -414444;
   // Build the target function.
   TestSignatures sigs;
-  TestingModule module;
+  TestingModule module(execution_mode);
   WasmFunctionCompiler t(sigs.i_v(), &module);
   BUILD(t, WASM_I32V_3(kExpected));
   uint32_t index = t.CompileAndAdd();
@@ -1969,21 +2013,20 @@
   CHECK_EQ(kExpected, result);
 }
 
-
-TEST(Run_WasmCallF32StackParameter) {
+WASM_EXEC_TEST(CallF32StackParameter) {
   // Build the target function.
   LocalType param_types[20];
-  for (int i = 0; i < 20; i++) param_types[i] = kAstF32;
+  for (int i = 0; i < 20; ++i) param_types[i] = kAstF32;
   FunctionSig sig(1, 19, param_types);
-  TestingModule module;
+  TestingModule module(execution_mode);
   WasmFunctionCompiler t(&sig, &module);
   BUILD(t, WASM_GET_LOCAL(17));
   uint32_t index = t.CompileAndAdd();
 
   // Build the calling function.
   WasmRunner<float> r(&module);
-  BUILD(r, WASM_CALL_FUNCTION(
-               index, WASM_F32(1.0f), WASM_F32(2.0f), WASM_F32(4.0f),
+  BUILD(r, WASM_CALL_FUNCTIONN(
+               19, index, WASM_F32(1.0f), WASM_F32(2.0f), WASM_F32(4.0f),
                WASM_F32(8.0f), WASM_F32(16.0f), WASM_F32(32.0f),
                WASM_F32(64.0f), WASM_F32(128.0f), WASM_F32(256.0f),
                WASM_F32(1.5f), WASM_F32(2.5f), WASM_F32(4.5f), WASM_F32(8.5f),
@@ -1994,38 +2037,37 @@
   CHECK_EQ(256.5f, result);
 }
 
-
-TEST(Run_WasmCallF64StackParameter) {
+WASM_EXEC_TEST(CallF64StackParameter) {
   // Build the target function.
   LocalType param_types[20];
-  for (int i = 0; i < 20; i++) param_types[i] = kAstF64;
+  for (int i = 0; i < 20; ++i) param_types[i] = kAstF64;
   FunctionSig sig(1, 19, param_types);
-  TestingModule module;
+  TestingModule module(execution_mode);
   WasmFunctionCompiler t(&sig, &module);
   BUILD(t, WASM_GET_LOCAL(17));
   uint32_t index = t.CompileAndAdd();
 
   // Build the calling function.
   WasmRunner<double> r(&module);
-  BUILD(r, WASM_CALL_FUNCTION(index, WASM_F64(1.0), WASM_F64(2.0),
-                              WASM_F64(4.0), WASM_F64(8.0), WASM_F64(16.0),
-                              WASM_F64(32.0), WASM_F64(64.0), WASM_F64(128.0),
-                              WASM_F64(256.0), WASM_F64(1.5), WASM_F64(2.5),
-                              WASM_F64(4.5), WASM_F64(8.5), WASM_F64(16.5),
-                              WASM_F64(32.5), WASM_F64(64.5), WASM_F64(128.5),
-                              WASM_F64(256.5), WASM_F64(512.5)));
+  BUILD(r, WASM_CALL_FUNCTIONN(19, index, WASM_F64(1.0), WASM_F64(2.0),
+                               WASM_F64(4.0), WASM_F64(8.0), WASM_F64(16.0),
+                               WASM_F64(32.0), WASM_F64(64.0), WASM_F64(128.0),
+                               WASM_F64(256.0), WASM_F64(1.5), WASM_F64(2.5),
+                               WASM_F64(4.5), WASM_F64(8.5), WASM_F64(16.5),
+                               WASM_F64(32.5), WASM_F64(64.5), WASM_F64(128.5),
+                               WASM_F64(256.5), WASM_F64(512.5)));
 
   float result = r.Call();
   CHECK_EQ(256.5, result);
 }
 
-TEST(Run_WasmCallVoid) {
+WASM_EXEC_TEST(CallVoid) {
   const byte kMemOffset = 8;
   const int32_t kElemNum = kMemOffset / sizeof(int32_t);
   const int32_t kExpected = -414444;
   // Build the target function.
   TestSignatures sigs;
-  TestingModule module;
+  TestingModule module(execution_mode);
   module.AddMemory(16);
   module.RandomizeMemory();
   WasmFunctionCompiler t(sigs.v_v(), &module);
@@ -2043,18 +2085,17 @@
   CHECK_EQ(kExpected, module.raw_mem_start<int32_t>()[kElemNum]);
 }
 
-
-TEST(Run_WasmCall_Int32Add) {
+WASM_EXEC_TEST(Call_Int32Add) {
   // Build the target function.
   TestSignatures sigs;
-  TestingModule module;
+  TestingModule module(execution_mode);
   WasmFunctionCompiler t(sigs.i_ii(), &module);
   BUILD(t, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   uint32_t index = t.CompileAndAdd();
 
   // Build the caller function.
   WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
-  BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  BUILD(r, WASM_CALL_FUNCTION2(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_INT32_INPUTS(i) {
     FOR_INT32_INPUTS(j) {
@@ -2065,9 +2106,9 @@
   }
 }
 
-TEST(Run_WasmCall_Float32Sub) {
+WASM_EXEC_TEST(Call_Float32Sub) {
   TestSignatures sigs;
-  TestingModule module;
+  TestingModule module(execution_mode);
   WasmFunctionCompiler t(sigs.f_ff(), &module);
 
   // Build the target function.
@@ -2076,16 +2117,15 @@
 
   // Builder the caller function.
   WasmRunner<float> r(&module, MachineType::Float32(), MachineType::Float32());
-  BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+  BUILD(r, WASM_CALL_FUNCTION2(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_FLOAT32_INPUTS(i) {
     FOR_FLOAT32_INPUTS(j) { CHECK_FLOAT_EQ(*i - *j, r.Call(*i, *j)); }
   }
 }
 
-
-TEST(Run_WasmCall_Float64Sub) {
-  TestingModule module;
+WASM_EXEC_TEST(Call_Float64Sub) {
+  TestingModule module(execution_mode);
   double* memory = module.AddMemoryElems<double>(16);
   WasmRunner<int32_t> r(&module);
 
@@ -2115,35 +2155,26 @@
 #define ADD_CODE(vec, ...)                                              \
   do {                                                                  \
     byte __buf[] = {__VA_ARGS__};                                       \
-    for (size_t i = 0; i < sizeof(__buf); i++) vec.push_back(__buf[i]); \
+    for (size_t i = 0; i < sizeof(__buf); ++i) vec.push_back(__buf[i]); \
   } while (false)
 
-
-static void Run_WasmMixedCall_N(int start) {
+static void Run_WasmMixedCall_N(WasmExecutionMode execution_mode, int start) {
   const int kExpected = 6333;
   const int kElemSize = 8;
   TestSignatures sigs;
 
-#if WASM_64
-  static MachineType mixed[] = {
-      MachineType::Int32(),   MachineType::Float32(), MachineType::Int64(),
-      MachineType::Float64(), MachineType::Float32(), MachineType::Int64(),
-      MachineType::Int32(),   MachineType::Float64(), MachineType::Float32(),
-      MachineType::Float64(), MachineType::Int32(),   MachineType::Int64(),
-      MachineType::Int32(),   MachineType::Int32()};
-#else
+  // 64-bit cases handled in test-run-wasm-64.cc.
   static MachineType mixed[] = {
       MachineType::Int32(),   MachineType::Float32(), MachineType::Float64(),
       MachineType::Float32(), MachineType::Int32(),   MachineType::Float64(),
       MachineType::Float32(), MachineType::Float64(), MachineType::Int32(),
       MachineType::Int32(),   MachineType::Int32()};
-#endif
 
   int num_params = static_cast<int>(arraysize(mixed)) - start;
-  for (int which = 0; which < num_params; which++) {
+  for (int which = 0; which < num_params; ++which) {
     v8::base::AccountingAllocator allocator;
     Zone zone(&allocator);
-    TestingModule module;
+    TestingModule module(execution_mode);
     module.AddMemory(1024);
     MachineType* memtypes = &mixed[start];
     MachineType result = memtypes[which];
@@ -2154,7 +2185,7 @@
     uint32_t index;
     FunctionSig::Builder b(&zone, 1, num_params);
     b.AddReturn(WasmOpcodes::LocalTypeFor(result));
-    for (int i = 0; i < num_params; i++) {
+    for (int i = 0; i < num_params; ++i) {
       b.AddParam(WasmOpcodes::LocalTypeFor(memtypes[i]));
     }
     WasmFunctionCompiler t(b.Build(), &module);
@@ -2165,31 +2196,38 @@
     // Build the calling function.
     // =========================================================================
     WasmRunner<int32_t> r(&module);
-
     std::vector<byte> code;
-    ADD_CODE(code,
-             static_cast<byte>(WasmOpcodes::LoadStoreOpcodeOf(result, true)),
-             ZERO_ALIGNMENT, ZERO_OFFSET);
-    ADD_CODE(code, WASM_ZERO);
-    ADD_CODE(code, kExprCallFunction, static_cast<byte>(index));
 
-    for (int i = 0; i < num_params; i++) {
+    // Load the offset for the store.
+    ADD_CODE(code, WASM_ZERO);
+
+    // Load the arguments.
+    for (int i = 0; i < num_params; ++i) {
       int offset = (i + 1) * kElemSize;
       ADD_CODE(code, WASM_LOAD_MEM(memtypes[i], WASM_I8(offset)));
     }
 
+    // Call the selector function.
+    ADD_CODE(code, kExprCallFunction, static_cast<byte>(num_params),
+             static_cast<byte>(index));
+
+    // Store the result in memory.
+    ADD_CODE(code,
+             static_cast<byte>(WasmOpcodes::LoadStoreOpcodeOf(result, true)),
+             ZERO_ALIGNMENT, ZERO_OFFSET);
+
+    // Return the expected value.
     ADD_CODE(code, WASM_I32V_2(kExpected));
-    size_t end = code.size();
-    code.push_back(0);
-    r.Build(&code[0], &code[end]);
+
+    r.Build(&code[0], &code[0] + code.size());
 
     // Run the code.
-    for (int t = 0; t < 10; t++) {
+    for (int t = 0; t < 10; ++t) {
       module.RandomizeMemory();
       CHECK_EQ(kExpected, r.Call());
 
       int size = WasmOpcodes::MemSize(result);
-      for (int i = 0; i < size; i++) {
+      for (int i = 0; i < size; ++i) {
         int base = (which + 1) * kElemSize;
         byte expected = module.raw_mem_at<byte>(base + i);
         byte result = module.raw_mem_at<byte>(i);
@@ -2199,15 +2237,14 @@
   }
 }
 
+WASM_EXEC_TEST(MixedCall_0) { Run_WasmMixedCall_N(execution_mode, 0); }
+WASM_EXEC_TEST(MixedCall_1) { Run_WasmMixedCall_N(execution_mode, 1); }
+WASM_EXEC_TEST(MixedCall_2) { Run_WasmMixedCall_N(execution_mode, 2); }
+WASM_EXEC_TEST(MixedCall_3) { Run_WasmMixedCall_N(execution_mode, 3); }
 
-TEST(Run_WasmMixedCall_0) { Run_WasmMixedCall_N(0); }
-TEST(Run_WasmMixedCall_1) { Run_WasmMixedCall_N(1); }
-TEST(Run_WasmMixedCall_2) { Run_WasmMixedCall_N(2); }
-TEST(Run_WasmMixedCall_3) { Run_WasmMixedCall_N(3); }
-
-TEST(Run_Wasm_AddCall) {
+WASM_EXEC_TEST(AddCall) {
   TestSignatures sigs;
-  TestingModule module;
+  TestingModule module(execution_mode);
   WasmFunctionCompiler t1(sigs.i_ii(), &module);
   BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
   t1.CompileAndAdd();
@@ -2216,21 +2253,21 @@
   byte local = r.AllocateLocal(kAstI32);
   BUILD(r, B2(WASM_SET_LOCAL(local, WASM_I8(99)),
               WASM_I32_ADD(
-                  WASM_CALL_FUNCTION(t1.function_index_, WASM_GET_LOCAL(0),
-                                     WASM_GET_LOCAL(0)),
-                  WASM_CALL_FUNCTION(t1.function_index_, WASM_GET_LOCAL(1),
-                                     WASM_GET_LOCAL(local)))));
+                  WASM_CALL_FUNCTION2(t1.function_index(), WASM_GET_LOCAL(0),
+                                      WASM_GET_LOCAL(0)),
+                  WASM_CALL_FUNCTION2(t1.function_index(), WASM_GET_LOCAL(1),
+                                      WASM_GET_LOCAL(local)))));
 
   CHECK_EQ(198, r.Call(0));
   CHECK_EQ(200, r.Call(1));
   CHECK_EQ(100, r.Call(-49));
 }
 
-TEST(Run_Wasm_CountDown_expr) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(CountDown_expr) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r, WASM_LOOP(
                3, WASM_IF(WASM_NOT(WASM_GET_LOCAL(0)),
-                          WASM_BREAKV(0, WASM_GET_LOCAL(0))),
+                          WASM_BREAKV(1, WASM_GET_LOCAL(0))),
                WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(1))),
                WASM_CONTINUE(0)));
   CHECK_EQ(0, r.Call(1));
@@ -2238,51 +2275,46 @@
   CHECK_EQ(0, r.Call(100));
 }
 
-
-TEST(Run_Wasm_ExprBlock2a) {
-  WasmRunner<int32_t> r(MachineType::Int32());
-  BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(1))), WASM_I8(1)));
+WASM_EXEC_TEST(ExprBlock2a) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
+  BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_I8(1))), WASM_I8(1)));
   CHECK_EQ(1, r.Call(0));
   CHECK_EQ(1, r.Call(1));
 }
 
-
-TEST(Run_Wasm_ExprBlock2b) {
-  WasmRunner<int32_t> r(MachineType::Int32());
-  BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(1))), WASM_I8(2)));
+WASM_EXEC_TEST(ExprBlock2b) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
+  BUILD(r, B2(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_I8(1))), WASM_I8(2)));
   CHECK_EQ(2, r.Call(0));
   CHECK_EQ(1, r.Call(1));
 }
 
-
-TEST(Run_Wasm_ExprBlock2c) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(ExprBlock2c) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r, B2(WASM_BRV_IF(0, WASM_I8(1), WASM_GET_LOCAL(0)), WASM_I8(1)));
   CHECK_EQ(1, r.Call(0));
   CHECK_EQ(1, r.Call(1));
 }
 
-
-TEST(Run_Wasm_ExprBlock2d) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(ExprBlock2d) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r, B2(WASM_BRV_IF(0, WASM_I8(1), WASM_GET_LOCAL(0)), WASM_I8(2)));
   CHECK_EQ(2, r.Call(0));
   CHECK_EQ(1, r.Call(1));
 }
 
-
-TEST(Run_Wasm_ExprBlock_ManualSwitch) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(ExprBlock_ManualSwitch) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r, WASM_BLOCK(6, WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(1)),
-                                 WASM_BRV(0, WASM_I8(11))),
+                                 WASM_BRV(1, WASM_I8(11))),
                       WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(2)),
-                              WASM_BRV(0, WASM_I8(12))),
+                              WASM_BRV(1, WASM_I8(12))),
                       WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(3)),
-                              WASM_BRV(0, WASM_I8(13))),
+                              WASM_BRV(1, WASM_I8(13))),
                       WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(4)),
-                              WASM_BRV(0, WASM_I8(14))),
+                              WASM_BRV(1, WASM_I8(14))),
                       WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(5)),
-                              WASM_BRV(0, WASM_I8(15))),
+                              WASM_BRV(1, WASM_I8(15))),
                       WASM_I8(99)));
   CHECK_EQ(99, r.Call(0));
   CHECK_EQ(11, r.Call(1));
@@ -2293,9 +2325,8 @@
   CHECK_EQ(99, r.Call(6));
 }
 
-
-TEST(Run_Wasm_ExprBlock_ManualSwitch_brif) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(ExprBlock_ManualSwitch_brif) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
   BUILD(r,
         WASM_BLOCK(6, WASM_BRV_IF(0, WASM_I8(11),
                                   WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(1))),
@@ -2317,45 +2348,42 @@
   CHECK_EQ(99, r.Call(6));
 }
 
-
-TEST(Run_Wasm_nested_ifs) {
-  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+WASM_EXEC_TEST(nested_ifs) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
 
   BUILD(r, WASM_IF_ELSE(
                WASM_GET_LOCAL(0),
                WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_I8(11), WASM_I8(12)),
                WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_I8(13), WASM_I8(14))));
 
-
   CHECK_EQ(11, r.Call(1, 1));
   CHECK_EQ(12, r.Call(1, 0));
   CHECK_EQ(13, r.Call(0, 1));
   CHECK_EQ(14, r.Call(0, 0));
 }
 
-
-TEST(Run_Wasm_ExprBlock_if) {
-  WasmRunner<int32_t> r(MachineType::Int32());
+WASM_EXEC_TEST(ExprBlock_if) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32());
 
   BUILD(r, B1(WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(11)),
-                           WASM_BRV(0, WASM_I8(14)))));
+                           WASM_BRV(1, WASM_I8(14)))));
 
   CHECK_EQ(11, r.Call(1));
   CHECK_EQ(14, r.Call(0));
 }
 
-
-TEST(Run_Wasm_ExprBlock_nested_ifs) {
-  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+WASM_EXEC_TEST(ExprBlock_nested_ifs) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
 
   BUILD(r, WASM_BLOCK(
                1, WASM_IF_ELSE(
                       WASM_GET_LOCAL(0),
                       WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(0, WASM_I8(11)),
-                                   WASM_BRV(0, WASM_I8(12))),
+                                   WASM_BRV(1, WASM_I8(12))),
                       WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(0, WASM_I8(13)),
-                                   WASM_BRV(0, WASM_I8(14))))));
-
+                                   WASM_BRV(1, WASM_I8(14))))));
 
   CHECK_EQ(11, r.Call(1, 1));
   CHECK_EQ(12, r.Call(1, 0));
@@ -2363,18 +2391,17 @@
   CHECK_EQ(14, r.Call(0, 0));
 }
 
-
-TEST(Run_Wasm_ExprLoop_nested_ifs) {
-  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+WASM_EXEC_TEST(ExprLoop_nested_ifs) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
 
   BUILD(r, WASM_LOOP(
                1, WASM_IF_ELSE(
                       WASM_GET_LOCAL(0),
                       WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(1, WASM_I8(11)),
-                                   WASM_BRV(1, WASM_I8(12))),
+                                   WASM_BRV(3, WASM_I8(12))),
                       WASM_IF_ELSE(WASM_GET_LOCAL(1), WASM_BRV(1, WASM_I8(13)),
-                                   WASM_BRV(1, WASM_I8(14))))));
-
+                                   WASM_BRV(3, WASM_I8(14))))));
 
   CHECK_EQ(11, r.Call(1, 1));
   CHECK_EQ(12, r.Call(1, 0));
@@ -2382,10 +2409,9 @@
   CHECK_EQ(14, r.Call(0, 0));
 }
 
-
-TEST(Run_Wasm_SimpleCallIndirect) {
+WASM_EXEC_TEST(SimpleCallIndirect) {
   TestSignatures sigs;
-  TestingModule module;
+  TestingModule module(execution_mode);
 
   WasmFunctionCompiler t1(sigs.i_ii(), &module);
   BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -2407,17 +2433,16 @@
 
   // Builder the caller function.
   WasmRunner<int32_t> r(&module, MachineType::Int32());
-  BUILD(r, WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(0), WASM_I8(66), WASM_I8(22)));
+  BUILD(r, WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(0), WASM_I8(66), WASM_I8(22)));
 
   CHECK_EQ(88, r.Call(0));
   CHECK_EQ(44, r.Call(1));
   CHECK_TRAP(r.Call(2));
 }
 
-
-TEST(Run_Wasm_MultipleCallIndirect) {
+WASM_EXEC_TEST(MultipleCallIndirect) {
   TestSignatures sigs;
-  TestingModule module;
+  TestingModule module(execution_mode);
 
   WasmFunctionCompiler t1(sigs.i_ii(), &module);
   BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -2440,11 +2465,11 @@
   // Builder the caller function.
   WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32(),
                         MachineType::Int32());
-  BUILD(r,
-        WASM_I32_ADD(WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1),
-                                        WASM_GET_LOCAL(2)),
-                     WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(1), WASM_GET_LOCAL(2),
-                                        WASM_GET_LOCAL(0))));
+  BUILD(r, WASM_I32_ADD(
+               WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1),
+                                   WASM_GET_LOCAL(2)),
+               WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(1), WASM_GET_LOCAL(2),
+                                   WASM_GET_LOCAL(0))));
 
   CHECK_EQ(5, r.Call(0, 1, 2));
   CHECK_EQ(19, r.Call(0, 1, 9));
@@ -2457,9 +2482,9 @@
   CHECK_TRAP(r.Call(2, 1, 0));
 }
 
-TEST(Run_Wasm_CallIndirect_NoTable) {
+WASM_EXEC_TEST(CallIndirect_NoTable) {
   TestSignatures sigs;
-  TestingModule module;
+  TestingModule module(execution_mode);
 
   // One function.
   WasmFunctionCompiler t1(sigs.i_ii(), &module);
@@ -2472,71 +2497,72 @@
 
   // Builder the caller function.
   WasmRunner<int32_t> r(&module, MachineType::Int32());
-  BUILD(r, WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(0), WASM_I8(66), WASM_I8(22)));
+  BUILD(r, WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(0), WASM_I8(66), WASM_I8(22)));
 
   CHECK_TRAP(r.Call(0));
   CHECK_TRAP(r.Call(1));
   CHECK_TRAP(r.Call(2));
 }
 
-TEST(Run_Wasm_F32Floor) {
-  WasmRunner<float> r(MachineType::Float32());
+WASM_EXEC_TEST(F32Floor) {
+  WasmRunner<float> r(execution_mode, MachineType::Float32());
   BUILD(r, WASM_F32_FLOOR(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(floorf(*i), r.Call(*i)); }
 }
 
-TEST(Run_Wasm_F32Ceil) {
-  WasmRunner<float> r(MachineType::Float32());
+WASM_EXEC_TEST(F32Ceil) {
+  WasmRunner<float> r(execution_mode, MachineType::Float32());
   BUILD(r, WASM_F32_CEIL(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(ceilf(*i), r.Call(*i)); }
 }
 
-TEST(Run_Wasm_F32Trunc) {
-  WasmRunner<float> r(MachineType::Float32());
+WASM_EXEC_TEST(F32Trunc) {
+  WasmRunner<float> r(execution_mode, MachineType::Float32());
   BUILD(r, WASM_F32_TRUNC(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(truncf(*i), r.Call(*i)); }
 }
 
-TEST(Run_Wasm_F32NearestInt) {
-  WasmRunner<float> r(MachineType::Float32());
+WASM_EXEC_TEST(F32NearestInt) {
+  WasmRunner<float> r(execution_mode, MachineType::Float32());
   BUILD(r, WASM_F32_NEARESTINT(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(nearbyintf(*i), r.Call(*i)); }
 }
 
-TEST(Run_Wasm_F64Floor) {
-  WasmRunner<double> r(MachineType::Float64());
+WASM_EXEC_TEST(F64Floor) {
+  WasmRunner<double> r(execution_mode, MachineType::Float64());
   BUILD(r, WASM_F64_FLOOR(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(floor(*i), r.Call(*i)); }
 }
 
-TEST(Run_Wasm_F64Ceil) {
-  WasmRunner<double> r(MachineType::Float64());
+WASM_EXEC_TEST(F64Ceil) {
+  WasmRunner<double> r(execution_mode, MachineType::Float64());
   BUILD(r, WASM_F64_CEIL(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ceil(*i), r.Call(*i)); }
 }
 
-TEST(Run_Wasm_F64Trunc) {
-  WasmRunner<double> r(MachineType::Float64());
+WASM_EXEC_TEST(F64Trunc) {
+  WasmRunner<double> r(execution_mode, MachineType::Float64());
   BUILD(r, WASM_F64_TRUNC(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(trunc(*i), r.Call(*i)); }
 }
 
-TEST(Run_Wasm_F64NearestInt) {
-  WasmRunner<double> r(MachineType::Float64());
+WASM_EXEC_TEST(F64NearestInt) {
+  WasmRunner<double> r(execution_mode, MachineType::Float64());
   BUILD(r, WASM_F64_NEARESTINT(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(nearbyint(*i), r.Call(*i)); }
 }
 
-TEST(Run_Wasm_F32Min) {
-  WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());
+WASM_EXEC_TEST(F32Min) {
+  WasmRunner<float> r(execution_mode, MachineType::Float32(),
+                      MachineType::Float32());
   BUILD(r, WASM_F32_MIN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_FLOAT32_INPUTS(i) {
@@ -2558,9 +2584,9 @@
   }
 }
 
-
-TEST(Run_Wasm_F64Min) {
-  WasmRunner<double> r(MachineType::Float64(), MachineType::Float64());
+WASM_EXEC_TEST(F64Min) {
+  WasmRunner<double> r(execution_mode, MachineType::Float64(),
+                       MachineType::Float64());
   BUILD(r, WASM_F64_MIN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_FLOAT64_INPUTS(i) {
@@ -2582,9 +2608,9 @@
   }
 }
 
-
-TEST(Run_Wasm_F32Max) {
-  WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());
+WASM_EXEC_TEST(F32Max) {
+  WasmRunner<float> r(execution_mode, MachineType::Float32(),
+                      MachineType::Float32());
   BUILD(r, WASM_F32_MAX(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_FLOAT32_INPUTS(i) {
@@ -2606,9 +2632,9 @@
   }
 }
 
-
-TEST(Run_Wasm_F64Max) {
-  WasmRunner<double> r(MachineType::Float64(), MachineType::Float64());
+WASM_EXEC_TEST(F64Max) {
+  WasmRunner<double> r(execution_mode, MachineType::Float64(),
+                       MachineType::Float64());
   BUILD(r, WASM_F64_MAX(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_FLOAT64_INPUTS(i) {
@@ -2630,68 +2656,67 @@
   }
 }
 
-// TODO(ahaas): Fix on arm and mips and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS && \
-    !V8_TARGET_ARCH_MIPS64
+// TODO(ahaas): Fix on mips and reenable.
+#if !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_MIPS64
 
-TEST(Run_Wasm_F32Min_Snan) {
+WASM_EXEC_TEST(F32Min_Snan) {
   // Test that the instruction does not return a signalling NaN.
   {
-    WasmRunner<float> r;
+    WasmRunner<float> r(execution_mode);
     BUILD(r,
           WASM_F32_MIN(WASM_F32(bit_cast<float>(0xff80f1e2)), WASM_F32(57.67)));
     CHECK_EQ(0xffc0f1e2, bit_cast<uint32_t>(r.Call()));
   }
   {
-    WasmRunner<float> r;
+    WasmRunner<float> r(execution_mode);
     BUILD(r,
           WASM_F32_MIN(WASM_F32(45.73), WASM_F32(bit_cast<float>(0x7f80f1e2))));
     CHECK_EQ(0x7fc0f1e2, bit_cast<uint32_t>(r.Call()));
   }
 }
 
-TEST(Run_Wasm_F32Max_Snan) {
+WASM_EXEC_TEST(F32Max_Snan) {
   // Test that the instruction does not return a signalling NaN.
   {
-    WasmRunner<float> r;
+    WasmRunner<float> r(execution_mode);
     BUILD(r,
           WASM_F32_MAX(WASM_F32(bit_cast<float>(0xff80f1e2)), WASM_F32(57.67)));
     CHECK_EQ(0xffc0f1e2, bit_cast<uint32_t>(r.Call()));
   }
   {
-    WasmRunner<float> r;
+    WasmRunner<float> r(execution_mode);
     BUILD(r,
           WASM_F32_MAX(WASM_F32(45.73), WASM_F32(bit_cast<float>(0x7f80f1e2))));
     CHECK_EQ(0x7fc0f1e2, bit_cast<uint32_t>(r.Call()));
   }
 }
 
-TEST(Run_Wasm_F64Min_Snan) {
+WASM_EXEC_TEST(F64Min_Snan) {
   // Test that the instruction does not return a signalling NaN.
   {
-    WasmRunner<double> r;
+    WasmRunner<double> r(execution_mode);
     BUILD(r, WASM_F64_MIN(WASM_F64(bit_cast<double>(0xfff000000000f1e2)),
                           WASM_F64(57.67)));
     CHECK_EQ(0xfff800000000f1e2, bit_cast<uint64_t>(r.Call()));
   }
   {
-    WasmRunner<double> r;
+    WasmRunner<double> r(execution_mode);
     BUILD(r, WASM_F64_MIN(WASM_F64(45.73),
                           WASM_F64(bit_cast<double>(0x7ff000000000f1e2))));
     CHECK_EQ(0x7ff800000000f1e2, bit_cast<uint64_t>(r.Call()));
   }
 }
 
-TEST(Run_Wasm_F64Max_Snan) {
+WASM_EXEC_TEST(F64Max_Snan) {
   // Test that the instruction does not return a signalling NaN.
   {
-    WasmRunner<double> r;
+    WasmRunner<double> r(execution_mode);
     BUILD(r, WASM_F64_MAX(WASM_F64(bit_cast<double>(0xfff000000000f1e2)),
                           WASM_F64(57.67)));
     CHECK_EQ(0xfff800000000f1e2, bit_cast<uint64_t>(r.Call()));
   }
   {
-    WasmRunner<double> r;
+    WasmRunner<double> r(execution_mode);
     BUILD(r, WASM_F64_MAX(WASM_F64(45.73),
                           WASM_F64(bit_cast<double>(0x7ff000000000f1e2))));
     CHECK_EQ(0x7ff800000000f1e2, bit_cast<uint64_t>(r.Call()));
@@ -2700,8 +2725,8 @@
 
 #endif
 
-TEST(Run_Wasm_I32SConvertF32) {
-  WasmRunner<int32_t> r(MachineType::Float32());
+WASM_EXEC_TEST(I32SConvertF32) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Float32());
   BUILD(r, WASM_I32_SCONVERT_F32(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT32_INPUTS(i) {
@@ -2714,9 +2739,8 @@
   }
 }
 
-
-TEST(Run_Wasm_I32SConvertF64) {
-  WasmRunner<int32_t> r(MachineType::Float64());
+WASM_EXEC_TEST(I32SConvertF64) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Float64());
   BUILD(r, WASM_I32_SCONVERT_F64(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT64_INPUTS(i) {
@@ -2729,9 +2753,8 @@
   }
 }
 
-
-TEST(Run_Wasm_I32UConvertF32) {
-  WasmRunner<uint32_t> r(MachineType::Float32());
+WASM_EXEC_TEST(I32UConvertF32) {
+  WasmRunner<uint32_t> r(execution_mode, MachineType::Float32());
   BUILD(r, WASM_I32_UCONVERT_F32(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT32_INPUTS(i) {
@@ -2743,9 +2766,8 @@
   }
 }
 
-
-TEST(Run_Wasm_I32UConvertF64) {
-  WasmRunner<uint32_t> r(MachineType::Float64());
+WASM_EXEC_TEST(I32UConvertF64) {
+  WasmRunner<uint32_t> r(execution_mode, MachineType::Float64());
   BUILD(r, WASM_I32_UCONVERT_F64(WASM_GET_LOCAL(0)));
 
   FOR_FLOAT64_INPUTS(i) {
@@ -2757,8 +2779,9 @@
   }
 }
 
-TEST(Run_Wasm_F64CopySign) {
-  WasmRunner<double> r(MachineType::Float64(), MachineType::Float64());
+WASM_EXEC_TEST(F64CopySign) {
+  WasmRunner<double> r(execution_mode, MachineType::Float64(),
+                       MachineType::Float64());
   BUILD(r, WASM_F64_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_FLOAT64_INPUTS(i) {
@@ -2766,9 +2789,9 @@
   }
 }
 
-
-TEST(Run_Wasm_F32CopySign) {
-  WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());
+WASM_EXEC_TEST(F32CopySign) {
+  WasmRunner<float> r(execution_mode, MachineType::Float32(),
+                      MachineType::Float32());
   BUILD(r, WASM_F32_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
 
   FOR_FLOAT32_INPUTS(i) {
@@ -2776,15 +2799,15 @@
   }
 }
 
-void CompileCallIndirectMany(LocalType param) {
+static void CompileCallIndirectMany(LocalType param) {
   // Make sure we don't run out of registers when compiling indirect calls
   // with many many parameters.
   TestSignatures sigs;
-  for (byte num_params = 0; num_params < 40; num_params++) {
+  for (byte num_params = 0; num_params < 40; ++num_params) {
     v8::base::AccountingAllocator allocator;
     Zone zone(&allocator);
     HandleScope scope(CcTest::InitIsolateOnce());
-    TestingModule module;
+    TestingModule module(kExecuteCompiled);
     FunctionSig* sig = sigs.many(&zone, kAstStmt, param, num_params);
 
     module.AddSignature(sig);
@@ -2794,33 +2817,26 @@
     WasmFunctionCompiler t(sig, &module);
 
     std::vector<byte> code;
-    ADD_CODE(code, kExprCallIndirect, 1);
     ADD_CODE(code, kExprI8Const, 0);
-    for (byte p = 0; p < num_params; p++) {
+    for (byte p = 0; p < num_params; ++p) {
       ADD_CODE(code, kExprGetLocal, p);
     }
+    ADD_CODE(code, kExprCallIndirect, static_cast<byte>(num_params), 1);
 
     t.Build(&code[0], &code[0] + code.size());
     t.Compile();
   }
 }
 
-
 TEST(Compile_Wasm_CallIndirect_Many_i32) { CompileCallIndirectMany(kAstI32); }
 
-
-#if WASM_64
-TEST(Compile_Wasm_CallIndirect_Many_i64) { CompileCallIndirectMany(kAstI64); }
-#endif
-
-
 TEST(Compile_Wasm_CallIndirect_Many_f32) { CompileCallIndirectMany(kAstF32); }
 
-
 TEST(Compile_Wasm_CallIndirect_Many_f64) { CompileCallIndirectMany(kAstF64); }
 
-TEST(Run_WASM_Int32RemS_dead) {
-  WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
+WASM_EXEC_TEST(Int32RemS_dead) {
+  WasmRunner<int32_t> r(execution_mode, MachineType::Int32(),
+                        MachineType::Int32());
   BUILD(r, WASM_I32_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)), WASM_ZERO);
   const int32_t kMin = std::numeric_limits<int32_t>::min();
   CHECK_EQ(0, r.Call(133, 100));
diff --git a/test/cctest/wasm/test-wasm-function-name-table.cc b/test/cctest/wasm/test-wasm-function-name-table.cc
new file mode 100644
index 0000000..1ae78dc
--- /dev/null
+++ b/test/cctest/wasm/test-wasm-function-name-table.cc
@@ -0,0 +1,120 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/wasm/wasm-function-name-table.h"
+#include "src/wasm/wasm-module.h"
+
+#include "test/cctest/cctest.h"
+
+using namespace v8::internal;
+using namespace v8::internal::wasm;
+
+namespace {
+
+#define CHECK_STREQ(exp, found)                                                \
+  do {                                                                         \
+    Vector<const char> exp_ = (exp);                                           \
+    Vector<const char> found_ = (found);                                       \
+    if (V8_UNLIKELY(exp_.length() != found_.length() ||                        \
+                    memcmp(exp_.start(), found_.start(), exp_.length()))) {    \
+      V8_Fatal(__FILE__, __LINE__,                                             \
+               "Check failed: (%s) != (%s) ('%.*s' vs '%.*s').", #exp, #found, \
+               exp_.length(), exp_.start(), found_.length(), found_.start());  \
+    }                                                                          \
+  } while (0)
+
+void testFunctionNameTable(Vector<Vector<const char>> names) {
+  Isolate *isolate = CcTest::InitIsolateOnce();
+  HandleAndZoneScope scope;
+
+  WasmModule module;
+  std::vector<char> all_names;
+  // No name should have offset 0, because that encodes unnamed functions.
+  // In real wasm binary, offset 0 is impossible anyway.
+  all_names.push_back('\0');
+
+  uint32_t func_index = 0;
+  for (Vector<const char> name : names) {
+    size_t name_offset = name.start() ? all_names.size() : 0;
+    all_names.insert(all_names.end(), name.start(),
+                     name.start() + name.length());
+    // Make every second function name null-terminated.
+    if (func_index % 2) all_names.push_back('\0');
+    module.functions.push_back({nullptr, 0, 0,
+                                static_cast<uint32_t>(name_offset),
+                                static_cast<uint32_t>(name.length()), 0, 0});
+    ++func_index;
+  }
+
+  module.module_start = reinterpret_cast<byte *>(all_names.data());
+  module.module_end = module.module_start + all_names.size();
+
+  Handle<Object> wasm_function_name_table =
+      BuildFunctionNamesTable(isolate, &module);
+  CHECK(wasm_function_name_table->IsByteArray());
+
+  func_index = 0;
+  for (Vector<const char> name : names) {
+    MaybeHandle<String> string = GetWasmFunctionNameFromTable(
+        Handle<ByteArray>::cast(wasm_function_name_table), func_index);
+    if (name.start()) {
+      CHECK(string.ToHandleChecked()->IsUtf8EqualTo(name));
+    } else {
+      CHECK(string.is_null());
+    }
+    ++func_index;
+  }
+}
+
+void testFunctionNameTable(Vector<const char *> names) {
+  std::vector<Vector<const char>> names_vec;
+  for (const char *name : names)
+    names_vec.push_back(name ? CStrVector(name) : Vector<const char>());
+  testFunctionNameTable(Vector<Vector<const char>>(
+      names_vec.data(), static_cast<int>(names_vec.size())));
+}
+
+}  // namespace
+
+TEST(NoFunctions) { testFunctionNameTable(Vector<Vector<const char>>()); }
+
+TEST(OneFunctions) {
+  const char *names[] = {"foo"};
+  testFunctionNameTable(ArrayVector(names));
+}
+
+TEST(ThreeFunctions) {
+  const char *names[] = {"foo", "bar", "baz"};
+  testFunctionNameTable(ArrayVector(names));
+}
+
+TEST(OneUnnamedFunction) {
+  const char *names[] = {""};
+  testFunctionNameTable(ArrayVector(names));
+}
+
+TEST(UnnamedFirstFunction) {
+  const char *names[] = {"", "bar", "baz"};
+  testFunctionNameTable(ArrayVector(names));
+}
+
+TEST(UnnamedLastFunction) {
+  const char *names[] = {"bar", "baz", ""};
+  testFunctionNameTable(ArrayVector(names));
+}
+
+TEST(ThreeUnnamedFunctions) {
+  const char *names[] = {"", "", ""};
+  testFunctionNameTable(ArrayVector(names));
+}
+
+TEST(UTF8Names) {
+  const char *names[] = {"↱fun↰", "↺", "alpha:α beta:β"};
+  testFunctionNameTable(ArrayVector(names));
+}
+
+TEST(UnnamedVsEmptyNames) {
+  const char *names[] = {"", nullptr, nullptr, ""};
+  testFunctionNameTable(ArrayVector(names));
+}
diff --git a/test/cctest/wasm/test-wasm-stack.cc b/test/cctest/wasm/test-wasm-stack.cc
new file mode 100644
index 0000000..f2a8481
--- /dev/null
+++ b/test/cctest/wasm/test-wasm-stack.cc
@@ -0,0 +1,164 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/wasm/wasm-macro-gen.h"
+
+#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/value-helper.h"
+#include "test/cctest/wasm/test-signatures.h"
+#include "test/cctest/wasm/wasm-run-utils.h"
+
+using namespace v8::base;
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+using namespace v8::internal::wasm;
+
+using v8::Local;
+using v8::Utils;
+
+namespace {
+
+#define CHECK_CSTREQ(exp, found)                                           \
+  do {                                                                     \
+    const char* exp_ = (exp);                                              \
+    const char* found_ = (found);                                          \
+    DCHECK_NOT_NULL(exp);                                                  \
+    if (V8_UNLIKELY(found_ == nullptr || strcmp(exp_, found_) != 0)) {     \
+      V8_Fatal(__FILE__, __LINE__,                                         \
+               "Check failed: (%s) != (%s) ('%s' vs '%s').", #exp, #found, \
+               exp_, found_ ? found_ : "<null>");                          \
+    }                                                                      \
+  } while (0)
+
+void PrintStackTrace(v8::Local<v8::StackTrace> stack) {
+  printf("Stack Trace (length %d):\n", stack->GetFrameCount());
+  for (int i = 0, e = stack->GetFrameCount(); i != e; ++i) {
+    v8::Local<v8::StackFrame> frame = stack->GetFrame(i);
+    v8::Local<v8::String> script = frame->GetScriptName();
+    v8::Local<v8::String> func = frame->GetFunctionName();
+    printf("[%d] (%s) %s:%d:%d\n", i,
+           script.IsEmpty() ? "<null>" : *v8::String::Utf8Value(script),
+           func.IsEmpty() ? "<null>" : *v8::String::Utf8Value(func),
+           frame->GetLineNumber(), frame->GetColumn());
+  }
+}
+
+struct ExceptionInfo {
+  const char* func_name;
+  int line_nr;
+  int column;
+};
+
+template <int N>
+void CheckExceptionInfos(Handle<Object> exc,
+                         const ExceptionInfo (&excInfos)[N]) {
+  // Check that it's indeed an Error object.
+  CHECK(exc->IsJSError());
+
+  // Extract stack frame from the exception.
+  Local<v8::Value> localExc = Utils::ToLocal(exc);
+  v8::Local<v8::StackTrace> stack = v8::Exception::GetStackTrace(localExc);
+  PrintStackTrace(stack);
+  CHECK(!stack.IsEmpty());
+  CHECK_EQ(N, stack->GetFrameCount());
+
+  for (int frameNr = 0; frameNr < N; ++frameNr) {
+    v8::Local<v8::StackFrame> frame = stack->GetFrame(frameNr);
+    v8::String::Utf8Value funName(frame->GetFunctionName());
+    CHECK_CSTREQ(excInfos[frameNr].func_name, *funName);
+    CHECK_EQ(excInfos[frameNr].line_nr, frame->GetLineNumber());
+    CHECK_EQ(excInfos[frameNr].column, frame->GetColumn());
+  }
+}
+
+}  // namespace
+
+// Call from JS to WASM to JS and throw an Error from JS.
+TEST(CollectDetailedWasmStack_ExplicitThrowFromJs) {
+  TestSignatures sigs;
+  TestingModule module;
+
+  // Initialize WasmFunctionCompiler first, since it sets up the HandleScope.
+  WasmFunctionCompiler comp1(sigs.v_v(), &module);
+
+  uint32_t js_throwing_index = module.AddJsFunction(
+      sigs.v_v(),
+      "(function js() {\n function a() {\n throw new Error(); };\n a(); })");
+
+  // Add a nop such that we don't always get position 1.
+  BUILD(comp1, WASM_NOP, WASM_CALL_FUNCTION0(js_throwing_index));
+  uint32_t wasm_index = comp1.CompileAndAdd();
+
+  WasmFunctionCompiler comp2(sigs.v_v(), &module);
+  BUILD(comp2, WASM_CALL_FUNCTION0(wasm_index));
+  uint32_t wasm_index_2 = comp2.CompileAndAdd();
+
+  Handle<JSFunction> js_wasm_wrapper = module.WrapCode(wasm_index_2);
+
+  Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast(
+      v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
+          CompileRun("(function callFn(fn) { fn(); })"))));
+
+  Isolate* isolate = js_wasm_wrapper->GetIsolate();
+  isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
+                                                     v8::StackTrace::kOverview);
+  Handle<Object> global(isolate->context()->global_object(), isolate);
+  MaybeHandle<Object> maybe_exc;
+  Handle<Object> args[] = {js_wasm_wrapper};
+  MaybeHandle<Object> returnObjMaybe =
+      Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc);
+  CHECK(returnObjMaybe.is_null());
+
+  // The column is 1-based, so add 1 to the actual byte offset.
+  ExceptionInfo expected_exceptions[] = {
+      {"a", 3, 8},                                            // -
+      {"js", 4, 2},                                           // -
+      {"<WASM UNNAMED>", static_cast<int>(wasm_index), 3},    // -
+      {"<WASM UNNAMED>", static_cast<int>(wasm_index_2), 2},  // -
+      {"callFn", 1, 24}                                       // -
+  };
+  CheckExceptionInfos(maybe_exc.ToHandleChecked(), expected_exceptions);
+}
+
+// Trigger a trap in WASM, stack should be JS -> WASM -> WASM.
+TEST(CollectDetailedWasmStack_WasmError) {
+  TestSignatures sigs;
+  TestingModule module;
+
+  WasmFunctionCompiler comp1(sigs.i_v(), &module,
+                             ArrayVector("exec_unreachable"));
+  // Set the execution context, such that a runtime error can be thrown.
+  comp1.SetModuleContext();
+  BUILD(comp1, WASM_UNREACHABLE);
+  uint32_t wasm_index = comp1.CompileAndAdd();
+
+  WasmFunctionCompiler comp2(sigs.i_v(), &module,
+                             ArrayVector("call_exec_unreachable"));
+  BUILD(comp2, WASM_CALL_FUNCTION0(wasm_index));
+  uint32_t wasm_index_2 = comp2.CompileAndAdd();
+
+  Handle<JSFunction> js_wasm_wrapper = module.WrapCode(wasm_index_2);
+
+  Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast(
+      v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
+          CompileRun("(function callFn(fn) { fn(); })"))));
+
+  Isolate* isolate = js_wasm_wrapper->GetIsolate();
+  isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
+                                                     v8::StackTrace::kOverview);
+  Handle<Object> global(isolate->context()->global_object(), isolate);
+  MaybeHandle<Object> maybe_exc;
+  Handle<Object> args[] = {js_wasm_wrapper};
+  MaybeHandle<Object> maybe_return_obj =
+      Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc);
+  CHECK(maybe_return_obj.is_null());
+
+  // The column is 1-based, so add 1 to the actual byte offset.
+  ExceptionInfo expected_exceptions[] = {
+      {"<WASM UNNAMED>", static_cast<int>(wasm_index), 2},    // -
+      {"<WASM UNNAMED>", static_cast<int>(wasm_index_2), 2},  // -
+      {"callFn", 1, 24}                                       //-
+  };
+  CheckExceptionInfos(maybe_exc.ToHandleChecked(), expected_exceptions);
+}
diff --git a/test/cctest/wasm/test-wasm-trap-position.cc b/test/cctest/wasm/test-wasm-trap-position.cc
new file mode 100644
index 0000000..30f5d48
--- /dev/null
+++ b/test/cctest/wasm/test-wasm-trap-position.cc
@@ -0,0 +1,139 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/wasm/wasm-macro-gen.h"
+
+#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/value-helper.h"
+#include "test/cctest/wasm/test-signatures.h"
+#include "test/cctest/wasm/wasm-run-utils.h"
+
+using namespace v8::base;
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+using namespace v8::internal::wasm;
+
+using v8::Local;
+using v8::Utils;
+
+namespace {
+
+#define CHECK_CSTREQ(exp, found)                                           \
+  do {                                                                     \
+    const char* exp_ = (exp);                                              \
+    const char* found_ = (found);                                          \
+    DCHECK_NOT_NULL(exp);                                                  \
+    if (V8_UNLIKELY(found_ == nullptr || strcmp(exp_, found_) != 0)) {     \
+      V8_Fatal(__FILE__, __LINE__,                                         \
+               "Check failed: (%s) != (%s) ('%s' vs '%s').", #exp, #found, \
+               exp_, found_ ? found_ : "<null>");                          \
+    }                                                                      \
+  } while (0)
+
+struct ExceptionInfo {
+  const char* func_name;
+  int line_nr;
+  int column;
+};
+
+template <int N>
+void CheckExceptionInfos(Handle<Object> exc,
+                         const ExceptionInfo (&excInfos)[N]) {
+  // Check that it's indeed an Error object.
+  CHECK(exc->IsJSError());
+
+  // Extract stack frame from the exception.
+  Local<v8::Value> localExc = Utils::ToLocal(exc);
+  v8::Local<v8::StackTrace> stack = v8::Exception::GetStackTrace(localExc);
+  CHECK(!stack.IsEmpty());
+  CHECK_EQ(N, stack->GetFrameCount());
+
+  for (int frameNr = 0; frameNr < N; ++frameNr) {
+    v8::Local<v8::StackFrame> frame = stack->GetFrame(frameNr);
+    v8::String::Utf8Value funName(frame->GetFunctionName());
+    CHECK_CSTREQ(excInfos[frameNr].func_name, *funName);
+    CHECK_EQ(excInfos[frameNr].line_nr, frame->GetLineNumber());
+    CHECK_EQ(excInfos[frameNr].column, frame->GetColumn());
+  }
+}
+
+}  // namespace
+
+// Trigger a trap for executing unreachable.
+TEST(Unreachable) {
+  TestSignatures sigs;
+  TestingModule module;
+
+  WasmFunctionCompiler comp1(sigs.v_v(), &module,
+                             ArrayVector("exec_unreachable"));
+  // Set the execution context, such that a runtime error can be thrown.
+  comp1.SetModuleContext();
+  BUILD(comp1, WASM_UNREACHABLE);
+  uint32_t wasm_index = comp1.CompileAndAdd();
+
+  Handle<JSFunction> js_wasm_wrapper = module.WrapCode(wasm_index);
+
+  Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast(
+      v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
+          CompileRun("(function callFn(fn) { fn(); })"))));
+
+  Isolate* isolate = js_wasm_wrapper->GetIsolate();
+  isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
+                                                     v8::StackTrace::kOverview);
+  Handle<Object> global(isolate->context()->global_object(), isolate);
+  MaybeHandle<Object> maybe_exc;
+  Handle<Object> args[] = {js_wasm_wrapper};
+  MaybeHandle<Object> returnObjMaybe =
+      Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc);
+  CHECK(returnObjMaybe.is_null());
+
+  // The column is 1-based, so add 1 to the actual byte offset.
+  ExceptionInfo expected_exceptions[] = {
+      {"<WASM UNNAMED>", static_cast<int>(wasm_index), 2},  // --
+      {"callFn", 1, 24}                                     // --
+  };
+  CheckExceptionInfos(maybe_exc.ToHandleChecked(), expected_exceptions);
+}
+
+// Trigger a trap for loading from out-of-bounds.
+TEST(IllegalLoad) {
+  TestSignatures sigs;
+  TestingModule module;
+
+  WasmFunctionCompiler comp1(sigs.v_v(), &module, ArrayVector("mem_oob"));
+  // Set the execution context, such that a runtime error can be thrown.
+  comp1.SetModuleContext();
+  BUILD(comp1, WASM_IF(WASM_ONE,
+                       WASM_LOAD_MEM(MachineType::Int32(), WASM_I32V_1(-3))));
+  uint32_t wasm_index = comp1.CompileAndAdd();
+
+  WasmFunctionCompiler comp2(sigs.v_v(), &module, ArrayVector("call_mem_oob"));
+  // Insert a NOP such that the position of the call is not one.
+  BUILD(comp2, WASM_NOP, WASM_CALL_FUNCTION0(wasm_index));
+  uint32_t wasm_index_2 = comp2.CompileAndAdd();
+
+  Handle<JSFunction> js_wasm_wrapper = module.WrapCode(wasm_index_2);
+
+  Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast(
+      v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast(
+          CompileRun("(function callFn(fn) { fn(); })"))));
+
+  Isolate* isolate = js_wasm_wrapper->GetIsolate();
+  isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
+                                                     v8::StackTrace::kOverview);
+  Handle<Object> global(isolate->context()->global_object(), isolate);
+  MaybeHandle<Object> maybe_exc;
+  Handle<Object> args[] = {js_wasm_wrapper};
+  MaybeHandle<Object> returnObjMaybe =
+      Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc);
+  CHECK(returnObjMaybe.is_null());
+
+  // The column is 1-based, so add 1 to the actual byte offset.
+  ExceptionInfo expected_exceptions[] = {
+      {"<WASM UNNAMED>", static_cast<int>(wasm_index), 7},    // --
+      {"<WASM UNNAMED>", static_cast<int>(wasm_index_2), 3},  // --
+      {"callFn", 1, 24}                                       // --
+  };
+  CheckExceptionInfos(maybe_exc.ToHandleChecked(), expected_exceptions);
+}
diff --git a/test/cctest/wasm/wasm-run-utils.h b/test/cctest/wasm/wasm-run-utils.h
index 1e85f46..1f758bb 100644
--- a/test/cctest/wasm/wasm-run-utils.h
+++ b/test/cctest/wasm/wasm-run-utils.h
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "src/base/accounting-allocator.h"
 #include "src/base/utils/random-number-generator.h"
 
 #include "src/compiler/graph-visualizer.h"
@@ -17,9 +18,12 @@
 #include "src/compiler/node.h"
 #include "src/compiler/pipeline.h"
 #include "src/compiler/wasm-compiler.h"
+#include "src/compiler/zone-pool.h"
 
 #include "src/wasm/ast-decoder.h"
+#include "src/wasm/wasm-interpreter.h"
 #include "src/wasm/wasm-js.h"
+#include "src/wasm/wasm-macro-gen.h"
 #include "src/wasm/wasm-module.h"
 #include "src/wasm/wasm-opcodes.h"
 
@@ -29,15 +33,10 @@
 #include "test/cctest/compiler/call-tester.h"
 #include "test/cctest/compiler/graph-builder-tester.h"
 
-// TODO(titzer): pull WASM_64 up to a common header.
-#if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64
-#define WASM_64 1
-#else
-#define WASM_64 0
-#endif
-
 static const uint32_t kMaxFunctions = 10;
 
+enum WasmExecutionMode { kExecuteInterpreted, kExecuteCompiled };
+
 // TODO(titzer): check traps more robustly in tests.
 // Currently, in tests, we just return 0xdeadbeef from the function in which
 // the trap occurs if the runtime context is not available to throw a JavaScript
@@ -70,16 +69,21 @@
 // {WasmModuleInstance}.
 class TestingModule : public ModuleEnv {
  public:
-  TestingModule() : instance_(&module_), global_offset(0) {
-    module_.shared_isolate = CcTest::InitIsolateOnce();
+  explicit TestingModule(WasmExecutionMode mode = kExecuteCompiled)
+      : execution_mode_(mode),
+        instance_(&module_),
+        isolate_(CcTest::InitIsolateOnce()),
+        global_offset(0),
+        interpreter_(mode == kExecuteInterpreted
+                         ? new WasmInterpreter(&instance_, &allocator_)
+                         : nullptr) {
     module = &module_;
     instance = &instance_;
     instance->module = &module_;
     instance->globals_start = global_data;
-    instance->globals_size = kMaxGlobalsSize;
+    module_.globals_size = kMaxGlobalsSize;
     instance->mem_start = nullptr;
     instance->mem_size = 0;
-    linker = nullptr;
     origin = kWasmOrigin;
     memset(global_data, 0, sizeof(global_data));
   }
@@ -88,9 +92,10 @@
     if (instance->mem_start) {
       free(instance->mem_start);
     }
+    if (interpreter_) delete interpreter_;
   }
 
-  byte* AddMemory(size_t size) {
+  byte* AddMemory(uint32_t size) {
     CHECK_NULL(instance->mem_start);
     CHECK_EQ(0, instance->mem_size);
     instance->mem_start = reinterpret_cast<byte*>(malloc(size));
@@ -101,19 +106,19 @@
   }
 
   template <typename T>
-  T* AddMemoryElems(size_t count) {
+  T* AddMemoryElems(uint32_t count) {
     AddMemory(count * sizeof(T));
     return raw_mem_start<T>();
   }
 
   template <typename T>
   T* AddGlobal(MachineType mem_type) {
-    WasmGlobal* global = AddGlobal(mem_type);
+    const WasmGlobal* global = AddGlobal(mem_type);
     return reinterpret_cast<T*>(instance->globals_start + global->offset);
   }
 
   byte AddSignature(FunctionSig* sig) {
-    module->signatures.push_back(sig);
+    module_.signatures.push_back(sig);
     size_t size = module->signatures.size();
     CHECK(size < 127);
     return static_cast<byte>(size - 1);
@@ -159,32 +164,57 @@
     rng.NextBytes(raw, end - raw);
   }
 
-  int AddFunction(FunctionSig* sig, Handle<Code> code) {
+  uint32_t AddFunction(FunctionSig* sig, Handle<Code> code) {
     if (module->functions.size() == 0) {
       // TODO(titzer): Reserving space here to avoid the underlying WasmFunction
       // structs from moving.
-      module->functions.reserve(kMaxFunctions);
+      module_.functions.reserve(kMaxFunctions);
     }
     uint32_t index = static_cast<uint32_t>(module->functions.size());
-    module->functions.push_back(
-        {sig, index, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, false});
+    module_.functions.push_back({sig, index, 0, 0, 0, 0, 0});
     instance->function_code.push_back(code);
+    if (interpreter_) {
+      const WasmFunction* function = &module->functions.back();
+      int interpreter_index = interpreter_->AddFunctionForTesting(function);
+      CHECK_EQ(index, static_cast<uint32_t>(interpreter_index));
+    }
     DCHECK_LT(index, kMaxFunctions);  // limited for testing.
     return index;
   }
 
+  uint32_t AddJsFunction(FunctionSig* sig, const char* source) {
+    Handle<JSFunction> jsfunc = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
+        *v8::Local<v8::Function>::Cast(CompileRun(source))));
+    uint32_t index = AddFunction(sig, Handle<Code>::null());
+    WasmName module_name = ArrayVector("test");
+    WasmName function_name;
+    Handle<Code> code = CompileWasmToJSWrapper(isolate_, jsfunc, sig,
+                                               module_name, function_name);
+    instance->function_code[index] = code;
+    return index;
+  }
+
+  Handle<JSFunction> WrapCode(uint32_t index) {
+    // Wrap the code so it can be called as a JS function.
+    Handle<String> name = isolate_->factory()->NewStringFromStaticChars("main");
+    Handle<JSObject> module_object = Handle<JSObject>(0, isolate_);
+    Handle<Code> code = instance->function_code[index];
+    WasmJs::InstallWasmFunctionMap(isolate_, isolate_->native_context());
+    return compiler::CompileJSToWasmWrapper(isolate_, this, name, code,
+                                            module_object, index);
+  }
+
   void SetFunctionCode(uint32_t index, Handle<Code> code) {
     instance->function_code[index] = code;
   }
 
   void AddIndirectFunctionTable(int* functions, int table_size) {
-    Isolate* isolate = module->shared_isolate;
     Handle<FixedArray> fixed =
-        isolate->factory()->NewFixedArray(2 * table_size);
+        isolate_->factory()->NewFixedArray(2 * table_size);
     instance->function_table = fixed;
     DCHECK_EQ(0u, module->function_table.size());
     for (int i = 0; i < table_size; i++) {
-      module->function_table.push_back(functions[i]);
+      module_.function_table.push_back(functions[i]);
     }
   }
 
@@ -193,23 +223,31 @@
     int table_size = static_cast<int>(module->function_table.size());
     for (int i = 0; i < table_size; i++) {
       int function_index = module->function_table[i];
-      WasmFunction* function = &module->functions[function_index];
+      const WasmFunction* function = &module->functions[function_index];
       instance->function_table->set(i, Smi::FromInt(function->sig_index));
       instance->function_table->set(i + table_size,
                                     *instance->function_code[function_index]);
     }
   }
+  WasmFunction* GetFunctionAt(int index) { return &module_.functions[index]; }
+
+  WasmInterpreter* interpreter() { return interpreter_; }
+  WasmExecutionMode execution_mode() { return execution_mode_; }
 
  private:
+  WasmExecutionMode execution_mode_;
   WasmModule module_;
   WasmModuleInstance instance_;
+  Isolate* isolate_;
+  v8::base::AccountingAllocator allocator_;
   uint32_t global_offset;
   V8_ALIGNED(8) byte global_data[kMaxGlobalsSize];  // preallocated global data.
+  WasmInterpreter* interpreter_;
 
-  WasmGlobal* AddGlobal(MachineType mem_type) {
+  const WasmGlobal* AddGlobal(MachineType mem_type) {
     byte size = WasmOpcodes::MemSize(mem_type);
     global_offset = (global_offset + size - 1) & ~(size - 1);  // align
-    module->globals.push_back({0, 0, mem_type, global_offset, false});
+    module_.globals.push_back({0, 0, mem_type, global_offset, false});
     global_offset += size;
     // limit number of globals.
     CHECK_LT(global_offset, kMaxGlobalsSize);
@@ -218,9 +256,10 @@
 };
 
 inline void TestBuildingGraph(Zone* zone, JSGraph* jsgraph, ModuleEnv* module,
-                              FunctionSig* sig, const byte* start,
-                              const byte* end) {
-  compiler::WasmGraphBuilder builder(zone, jsgraph, sig);
+                              FunctionSig* sig,
+                              SourcePositionTable* source_position_table,
+                              const byte* start, const byte* end) {
+  compiler::WasmGraphBuilder builder(zone, jsgraph, sig, source_position_table);
   TreeResult result =
       BuildTFGraph(zone->allocator(), &builder, module, sig, start, end);
   if (result.failed()) {
@@ -356,7 +395,7 @@
         r.LowerGraph();
       }
 
-      CompilationInfo info("testing", isolate, graph()->zone());
+      CompilationInfo info(ArrayVector("testing"), isolate, graph()->zone());
       code_ =
           Pipeline::GenerateCodeForTesting(&info, descriptor, graph(), nullptr);
       CHECK(!code_.is_null());
@@ -382,41 +421,72 @@
 // A helper for compiling WASM functions for testing. This class can create a
 // standalone function if {module} is NULL or a function within a
 // {TestingModule}. It contains the internal state for compilation (i.e.
-// TurboFan graph) and, later, interpretation.
+// TurboFan graph) and interpretation (by adding to the interpreter manually).
 class WasmFunctionCompiler : public HandleAndZoneScope,
                              private GraphAndBuilders {
  public:
-  explicit WasmFunctionCompiler(FunctionSig* sig, TestingModule* module)
+  explicit WasmFunctionCompiler(
+      FunctionSig* sig, WasmExecutionMode mode,
+      Vector<const char> debug_name = ArrayVector("<WASM UNNAMED>"))
       : GraphAndBuilders(main_zone()),
+        execution_mode_(mode),
         jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
                 nullptr, this->machine()),
         sig(sig),
         descriptor_(nullptr),
-        testing_module_(module) {
-    if (module) {
-      // Get a new function from the testing module.
-      function_ = nullptr;
-      function_index_ = module->AddFunction(sig, Handle<Code>::null());
-    } else {
-      // Create our own function.
-      function_ = new WasmFunction();
-      function_->sig = sig;
-      function_index_ = 0;
+        testing_module_(nullptr),
+        debug_name_(debug_name),
+        local_decls(main_zone(), sig),
+        source_position_table_(this->graph()),
+        interpreter_(nullptr) {
+    // Create our own function.
+    function_ = new WasmFunction();
+    function_->sig = sig;
+    function_->func_index = 0;
+    function_->sig_index = 0;
+    if (mode == kExecuteInterpreted) {
+      interpreter_ = new WasmInterpreter(nullptr, zone()->allocator());
+      int index = interpreter_->AddFunctionForTesting(function_);
+      CHECK_EQ(0, index);
     }
   }
 
-  ~WasmFunctionCompiler() {
-    if (function_) delete function_;
+  explicit WasmFunctionCompiler(
+      FunctionSig* sig, TestingModule* module,
+      Vector<const char> debug_name = ArrayVector("<WASM UNNAMED>"))
+      : GraphAndBuilders(main_zone()),
+        execution_mode_(module->execution_mode()),
+        jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
+                nullptr, this->machine()),
+        sig(sig),
+        descriptor_(nullptr),
+        testing_module_(module),
+        debug_name_(debug_name),
+        local_decls(main_zone(), sig),
+        source_position_table_(this->graph()),
+        interpreter_(module->interpreter()) {
+    // Get a new function from the testing module.
+    int index = module->AddFunction(sig, Handle<Code>::null());
+    function_ = testing_module_->GetFunctionAt(index);
   }
 
+  ~WasmFunctionCompiler() {
+    if (testing_module_) return;  // testing module owns the below things.
+    delete function_;
+    if (interpreter_) delete interpreter_;
+  }
+
+  WasmExecutionMode execution_mode_;
   JSGraph jsgraph;
   FunctionSig* sig;
   // The call descriptor is initialized when the function is compiled.
   CallDescriptor* descriptor_;
   TestingModule* testing_module_;
+  Vector<const char> debug_name_;
   WasmFunction* function_;
-  int function_index_;
   LocalDeclEncoder local_decls;
+  SourcePositionTable source_position_table_;
+  WasmInterpreter* interpreter_;
 
   Isolate* isolate() { return main_isolate(); }
   Graph* graph() const { return main_graph_; }
@@ -429,16 +499,21 @@
     }
   }
   CallDescriptor* descriptor() { return descriptor_; }
+  uint32_t function_index() { return function_->func_index; }
 
   void Build(const byte* start, const byte* end) {
     // Build the TurboFan graph.
-    local_decls.Prepend(&start, &end);
-    TestBuildingGraph(main_zone(), &jsgraph, testing_module_, sig, start, end);
-    delete[] start;
+    local_decls.Prepend(main_zone(), &start, &end);
+    TestBuildingGraph(main_zone(), &jsgraph, testing_module_, sig,
+                      &source_position_table_, start, end);
+    if (interpreter_) {
+      // Add the code to the interpreter.
+      CHECK(interpreter_->SetFunctionCodeForTesting(function_, start, end));
+    }
   }
 
   byte AllocateLocal(LocalType type) {
-    uint32_t index = local_decls.AddLocals(1, type, sig);
+    uint32_t index = local_decls.AddLocals(1, type);
     byte result = static_cast<byte>(index);
     DCHECK_EQ(index, result);
     return result;
@@ -450,30 +525,52 @@
     if (kPointerSize == 4) {
       desc = testing_module_->GetI32WasmCallDescriptor(this->zone(), desc);
     }
-    CompilationInfo info("wasm compile", this->isolate(), this->zone());
-    Handle<Code> result =
-        Pipeline::GenerateCodeForTesting(&info, desc, this->graph());
+    CompilationInfo info(debug_name_, this->isolate(), this->zone(),
+                         Code::ComputeFlags(Code::WASM_FUNCTION));
+    v8::base::SmartPointer<CompilationJob> job(Pipeline::NewWasmCompilationJob(
+        &info, graph(), desc, &source_position_table_));
+    if (job->OptimizeGraph() != CompilationJob::SUCCEEDED ||
+        job->GenerateCode() != CompilationJob::SUCCEEDED)
+      return Handle<Code>::null();
+
+    Handle<Code> code = info.code();
+
+    // Length is always 2, since usually <wasm_obj, func_index> is stored in
+    // the deopt data. Here, we only store the function index.
+    DCHECK(code->deoptimization_data() == nullptr ||
+           code->deoptimization_data()->length() == 0);
+    Handle<FixedArray> deopt_data =
+        isolate()->factory()->NewFixedArray(2, TENURED);
+    deopt_data->set(1, Smi::FromInt(static_cast<int>(function_index())));
+    deopt_data->set_length(2);
+    code->set_deoptimization_data(*deopt_data);
+
 #ifdef ENABLE_DISASSEMBLER
-    if (!result.is_null() && FLAG_print_opt_code) {
+    if (FLAG_print_opt_code) {
       OFStream os(stdout);
-      result->Disassemble("wasm code", os);
+      code->Disassemble("wasm code", os);
     }
 #endif
 
-    return result;
+    return code;
   }
 
   uint32_t CompileAndAdd(uint16_t sig_index = 0) {
     CHECK(testing_module_);
-    function()->sig_index = sig_index;
+    function_->sig_index = sig_index;
     Handle<Code> code = Compile();
-    testing_module_->SetFunctionCode(function_index_, code);
-    return static_cast<uint32_t>(function_index_);
+    testing_module_->SetFunctionCode(function_index(), code);
+    return function_index();
   }
 
-  WasmFunction* function() {
-    if (function_) return function_;
-    return &testing_module_->module->functions[function_index_];
+  // Set the context, such that e.g. runtime functions can be called.
+  void SetModuleContext() {
+    if (!testing_module_->instance->context.is_null()) {
+      CHECK(testing_module_->instance->context.is_identical_to(
+          main_isolate()->native_context()));
+      return;
+    }
+    testing_module_->instance->context = main_isolate()->native_context();
   }
 };
 
@@ -482,7 +579,8 @@
 template <typename ReturnType>
 class WasmRunner {
  public:
-  WasmRunner(MachineType p0 = MachineType::None(),
+  WasmRunner(WasmExecutionMode execution_mode,
+             MachineType p0 = MachineType::None(),
              MachineType p1 = MachineType::None(),
              MachineType p2 = MachineType::None(),
              MachineType p3 = MachineType::None())
@@ -490,7 +588,7 @@
         compiled_(false),
         signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
                    GetParameterCount(p0, p1, p2, p3), storage_),
-        compiler_(&signature_, nullptr) {
+        compiler_(&signature_, execution_mode) {
     InitSigStorage(p0, p1, p2, p3);
   }
 
@@ -533,51 +631,102 @@
   void Build(const byte* start, const byte* end) {
     CHECK(!compiled_);
     compiled_ = true;
-
-    // Build the TF graph within the compiler.
     compiler_.Build(start, end);
-    // Generate code.
-    Handle<Code> code = compiler_.Compile();
 
-    if (compiler_.testing_module_) {
-      // Update the table of function code in the module.
-      compiler_.testing_module_->SetFunctionCode(compiler_.function_index_,
-                                                 code);
+    if (!interpret()) {
+      // Compile machine code and install it into the module.
+      Handle<Code> code = compiler_.Compile();
+
+      if (compiler_.testing_module_) {
+        // Update the table of function code in the module.
+        compiler_.testing_module_->SetFunctionCode(
+            compiler_.function_->func_index, code);
+      }
+
+      wrapper_.SetInnerCode(code);
     }
-
-    wrapper_.SetInnerCode(code);
   }
 
-  ReturnType Call() { return Call(0, 0, 0, 0); }
+  ReturnType Call() {
+    if (interpret()) {
+      return CallInterpreter(Vector<WasmVal>(nullptr, 0));
+    } else {
+      return Call(0, 0, 0, 0);
+    }
+  }
 
   template <typename P0>
   ReturnType Call(P0 p0) {
-    return Call(p0, 0, 0, 0);
+    if (interpret()) {
+      WasmVal args[] = {WasmVal(p0)};
+      return CallInterpreter(ArrayVector(args));
+    } else {
+      return Call(p0, 0, 0, 0);
+    }
   }
 
   template <typename P0, typename P1>
   ReturnType Call(P0 p0, P1 p1) {
-    return Call(p0, p1, 0, 0);
+    if (interpret()) {
+      WasmVal args[] = {WasmVal(p0), WasmVal(p1)};
+      return CallInterpreter(ArrayVector(args));
+    } else {
+      return Call(p0, p1, 0, 0);
+    }
   }
 
   template <typename P0, typename P1, typename P2>
   ReturnType Call(P0 p0, P1 p1, P2 p2) {
-    return Call(p0, p1, p2, 0);
+    if (interpret()) {
+      WasmVal args[] = {WasmVal(p0), WasmVal(p1), WasmVal(p2)};
+      return CallInterpreter(ArrayVector(args));
+    } else {
+      return Call(p0, p1, p2, 0);
+    }
   }
 
   template <typename P0, typename P1, typename P2, typename P3>
   ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) {
-    CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
-                               wrapper_.GetWrapperCode(), wrapper_.signature());
-    ReturnType return_value;
-    int32_t result = runner.Call<void*, void*, void*, void*, void*>(
-        &p0, &p1, &p2, &p3, &return_value);
-    CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result);
-    return return_value;
+    if (interpret()) {
+      WasmVal args[] = {WasmVal(p0), WasmVal(p1), WasmVal(p2), WasmVal(p3)};
+      return CallInterpreter(ArrayVector(args));
+    } else {
+      CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
+                                 wrapper_.GetWrapperCode(),
+                                 wrapper_.signature());
+      ReturnType return_value;
+      int32_t result = runner.Call<void*, void*, void*, void*, void*>(
+          &p0, &p1, &p2, &p3, &return_value);
+      CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result);
+      return return_value;
+    }
+  }
+
+  ReturnType CallInterpreter(Vector<WasmVal> args) {
+    CHECK_EQ(args.length(),
+             static_cast<int>(compiler_.function_->sig->parameter_count()));
+    WasmInterpreter::Thread* thread = interpreter()->GetThread(0);
+    thread->Reset();
+    thread->PushFrame(compiler_.function_, args.start());
+    if (thread->Run() == WasmInterpreter::FINISHED) {
+      WasmVal val = thread->GetReturnValue();
+      return val.to<ReturnType>();
+    } else if (thread->state() == WasmInterpreter::TRAPPED) {
+      // TODO(titzer): return the correct trap code
+      int64_t result = 0xdeadbeefdeadbeef;
+      return static_cast<ReturnType>(result);
+    } else {
+      // TODO(titzer): falling off end
+      ReturnType val = 0;
+      return val;
+    }
   }
 
   byte AllocateLocal(LocalType type) { return compiler_.AllocateLocal(type); }
 
+  WasmFunction* function() { return compiler_.function_; }
+  WasmInterpreter* interpreter() { return compiler_.interpreter_; }
+
  protected:
   v8::base::AccountingAllocator allocator_;
   Zone zone;
@@ -587,6 +736,8 @@
   WasmFunctionCompiler compiler_;
   WasmFunctionWrapper<ReturnType> wrapper_;
 
+  bool interpret() { return compiler_.execution_mode_ == kExecuteInterpreted; }
+
   static size_t GetParameterCount(MachineType p0, MachineType p1,
                                   MachineType p2, MachineType p3) {
     if (p0 == MachineType::None()) return 0;
@@ -597,6 +748,16 @@
   }
 };
 
+// A macro to define tests that run in different engine configurations.
+// Currently only supports compiled tests, but a future
+// RunWasmInterpreted_##name version will allow each test to also run in the
+// interpreter.
+#define WASM_EXEC_TEST(name)                                               \
+  void RunWasm_##name(WasmExecutionMode execution_mode);                   \
+  TEST(RunWasmCompiled_##name) { RunWasm_##name(kExecuteCompiled); }       \
+  TEST(RunWasmInterpreted_##name) { RunWasm_##name(kExecuteInterpreted); } \
+  void RunWasm_##name(WasmExecutionMode execution_mode)
+
 }  // namespace
 
 #endif
diff --git a/test/default.gyp b/test/default.gyp
index efc0406..dd1d9e2 100644
--- a/test/default.gyp
+++ b/test/default.gyp
@@ -19,8 +19,8 @@
             'unittests/unittests.gyp:unittests_run',
           ],
           'includes': [
-            '../build/features.gypi',
-            '../build/isolate.gypi',
+            '../gypfiles/features.gypi',
+            '../gypfiles/isolate.gypi',
           ],
           'sources': [
             'default.isolate',
diff --git a/test/fuzzer/fuzzer-support.cc b/test/fuzzer/fuzzer-support.cc
index cf3ee8c..ea9fb09 100644
--- a/test/fuzzer/fuzzer-support.cc
+++ b/test/fuzzer/fuzzer-support.cc
@@ -10,6 +10,8 @@
 
 #include "include/libplatform/libplatform.h"
 
+#include "src/flags.h"
+
 namespace v8_fuzzer {
 
 namespace {
@@ -36,8 +38,9 @@
 };
 
 FuzzerSupport::FuzzerSupport(int* argc, char*** argv) {
+  v8::internal::FLAG_expose_gc = true;
   v8::V8::SetFlagsFromCommandLine(argc, *argv, true);
-  v8::V8::InitializeICU();
+  v8::V8::InitializeICUDefaultLocation((*argv)[0]);
   v8::V8::InitializeExternalStartupData((*argv)[0]);
   platform_ = v8::platform::CreateDefaultPlatform();
   v8::V8::InitializePlatform(platform_);
@@ -65,6 +68,7 @@
     context_.Reset();
   }
 
+  isolate_->LowMemoryNotification();
   isolate_->Dispose();
   isolate_ = nullptr;
 
diff --git a/test/fuzzer/fuzzer.gyp b/test/fuzzer/fuzzer.gyp
index 6e15a90..c7c4cb4 100644
--- a/test/fuzzer/fuzzer.gyp
+++ b/test/fuzzer/fuzzer.gyp
@@ -6,10 +6,10 @@
   'variables': {
     'v8_code': 1,
   },
-  'includes': ['../../build/toolchain.gypi', '../../build/features.gypi'],
+  'includes': ['../../gypfiles/toolchain.gypi', '../../gypfiles/features.gypi'],
   'targets': [
     {
-      'target_name': 'json_fuzzer',
+      'target_name': 'v8_simple_json_fuzzer',
       'type': 'executable',
       'dependencies': [
         'json_fuzzer_lib',
@@ -35,7 +35,7 @@
       ],
     },
     {
-      'target_name': 'parser_fuzzer',
+      'target_name': 'v8_simple_parser_fuzzer',
       'type': 'executable',
       'dependencies': [
         'parser_fuzzer_lib',
@@ -61,7 +61,7 @@
       ],
     },
     {
-      'target_name': 'regexp_fuzzer',
+      'target_name': 'v8_simple_regexp_fuzzer',
       'type': 'executable',
       'dependencies': [
         'regexp_fuzzer_lib',
@@ -87,7 +87,7 @@
       ],
     },
     {
-      'target_name': 'wasm_fuzzer',
+      'target_name': 'v8_simple_wasm_fuzzer',
       'type': 'executable',
       'dependencies': [
         'wasm_fuzzer_lib',
@@ -113,7 +113,7 @@
       ],
     },
     {
-      'target_name': 'wasm_asmjs_fuzzer',
+      'target_name': 'v8_simple_wasm_asmjs_fuzzer',
       'type': 'executable',
       'dependencies': [
         'wasm_asmjs_fuzzer_lib',
@@ -142,7 +142,7 @@
       'target_name': 'fuzzer_support',
       'type': 'static_library',
       'dependencies': [
-        '../../tools/gyp/v8.gyp:v8_libplatform',
+        '../../src/v8.gyp:v8_libplatform',
       ],
       'include_dirs': [
         '../..',
@@ -155,9 +155,9 @@
         ['component=="shared_library"', {
           # fuzzers can't be built against a shared library, so we need to
           # depend on the underlying static target in that case.
-          'dependencies': ['../../tools/gyp/v8.gyp:v8_maybe_snapshot'],
+          'dependencies': ['../../src/v8.gyp:v8_maybe_snapshot'],
         }, {
-          'dependencies': ['../../tools/gyp/v8.gyp:v8'],
+          'dependencies': ['../../src/v8.gyp:v8'],
         }],
       ],
     },
@@ -169,12 +169,14 @@
           'target_name': 'fuzzer_run',
           'type': 'none',
           'dependencies': [
-            'json_fuzzer',
-            'parser_fuzzer',
-            'regexp_fuzzer',
+            'v8_simple_json_fuzzer',
+            'v8_simple_parser_fuzzer',
+            'v8_simple_regexp_fuzzer',
+            'v8_simple_wasm_fuzzer',
+            'v8_simple_wasm_asmjs_fuzzer',
           ],
           'includes': [
-            '../../build/isolate.gypi',
+            '../../gypfiles/isolate.gypi',
           ],
           'sources': [
             'fuzzer.isolate',
diff --git a/test/fuzzer/fuzzer.isolate b/test/fuzzer/fuzzer.isolate
index 4e98edd..2611c72 100644
--- a/test/fuzzer/fuzzer.isolate
+++ b/test/fuzzer/fuzzer.isolate
@@ -5,11 +5,11 @@
 {
   'variables': {
     'files': [
-      '<(PRODUCT_DIR)/json_fuzzer<(EXECUTABLE_SUFFIX)',
-      '<(PRODUCT_DIR)/parser_fuzzer<(EXECUTABLE_SUFFIX)',
-      '<(PRODUCT_DIR)/regexp_fuzzer<(EXECUTABLE_SUFFIX)',
-      '<(PRODUCT_DIR)/wasm_fuzzer<(EXECUTABLE_SUFFIX)',
-      '<(PRODUCT_DIR)/wasm_asmjs_fuzzer<(EXECUTABLE_SUFFIX)',
+      '<(PRODUCT_DIR)/v8_simple_json_fuzzer<(EXECUTABLE_SUFFIX)',
+      '<(PRODUCT_DIR)/v8_simple_parser_fuzzer<(EXECUTABLE_SUFFIX)',
+      '<(PRODUCT_DIR)/v8_simple_regexp_fuzzer<(EXECUTABLE_SUFFIX)',
+      '<(PRODUCT_DIR)/v8_simple_wasm_fuzzer<(EXECUTABLE_SUFFIX)',
+      '<(PRODUCT_DIR)/v8_simple_wasm_asmjs_fuzzer<(EXECUTABLE_SUFFIX)',
       './fuzzer.status',
       './testcfg.py',
       './json/',
diff --git a/test/fuzzer/json.cc b/test/fuzzer/json.cc
index f20e9b9..121939b 100644
--- a/test/fuzzer/json.cc
+++ b/test/fuzzer/json.cc
@@ -26,6 +26,8 @@
     return 0;
   }
 
-  v8::JSON::Parse(isolate, source).IsEmpty();
+  v8::JSON::Parse(support->GetContext(), source).IsEmpty();
+  isolate->RequestGarbageCollectionForTesting(
+      v8::Isolate::kFullGarbageCollection);
   return 0;
 }
diff --git a/test/fuzzer/parser.cc b/test/fuzzer/parser.cc
index be70b43..4035ade 100644
--- a/test/fuzzer/parser.cc
+++ b/test/fuzzer/parser.cc
@@ -38,5 +38,7 @@
   info.set_global();
   v8::internal::Parser parser(&info);
   parser.Parse(&info);
+  isolate->RequestGarbageCollectionForTesting(
+      v8::Isolate::kFullGarbageCollection);
   return 0;
 }
diff --git a/test/fuzzer/regexp.cc b/test/fuzzer/regexp.cc
index eb51da8..40e3470 100644
--- a/test/fuzzer/regexp.cc
+++ b/test/fuzzer/regexp.cc
@@ -30,7 +30,6 @@
   v8::Context::Scope context_scope(support->GetContext());
   v8::TryCatch try_catch(isolate);
 
-  i::FLAG_harmony_unicode_regexps = true;
   i::FLAG_harmony_regexp_lookbehind = true;
 
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
@@ -71,5 +70,7 @@
     Test(isolate, regexp, source, results_array);
   }
 
+  isolate->RequestGarbageCollectionForTesting(
+      v8::Isolate::kFullGarbageCollection);
   return 0;
 }
diff --git a/test/fuzzer/testcfg.py b/test/fuzzer/testcfg.py
index 35a5abb..85a38ed 100644
--- a/test/fuzzer/testcfg.py
+++ b/test/fuzzer/testcfg.py
@@ -26,7 +26,7 @@
   def ListTests(self, context):
     tests = []
     for subtest in FuzzerTestSuite.SUB_TESTS:
-      shell = '%s_fuzzer' % subtest
+      shell = 'v8_simple_%s_fuzzer' % subtest
       for fname in os.listdir(os.path.join(self.root, subtest)):
         if not os.path.isfile(os.path.join(self.root, subtest, fname)):
           continue
diff --git a/test/fuzzer/wasm-asmjs.cc b/test/fuzzer/wasm-asmjs.cc
index 3f7477b..cb8b86b 100644
--- a/test/fuzzer/wasm-asmjs.cc
+++ b/test/fuzzer/wasm-asmjs.cc
@@ -33,7 +33,7 @@
   v8::TryCatch try_catch(isolate);
   v8::internal::WasmJs::InstallWasmFunctionMap(i_isolate,
                                                i_isolate->native_context());
-  v8::internal::wasm::CompileAndRunWasmModule(i_isolate, data, data + size,
-                                              true);
+  v8::internal::wasm::testing::CompileAndRunWasmModule(i_isolate, data,
+                                                       data + size, true);
   return 0;
 }
diff --git a/test/fuzzer/wasm.cc b/test/fuzzer/wasm.cc
index 8750cbf..27259c6 100644
--- a/test/fuzzer/wasm.cc
+++ b/test/fuzzer/wasm.cc
@@ -33,7 +33,7 @@
   v8::TryCatch try_catch(isolate);
   v8::internal::WasmJs::InstallWasmFunctionMap(i_isolate,
                                                i_isolate->native_context());
-  v8::internal::wasm::CompileAndRunWasmModule(i_isolate, data, data + size,
-                                              false);
+  v8::internal::wasm::testing::CompileAndRunWasmModule(i_isolate, data,
+                                                       data + size, false);
   return 0;
 }
diff --git a/test/ignition.gyp b/test/ignition.gyp
index 6aebec9..55f94d5 100644
--- a/test/ignition.gyp
+++ b/test/ignition.gyp
@@ -14,8 +14,8 @@
             'mjsunit/mjsunit.gyp:mjsunit_run',
           ],
           'includes': [
-            '../build/features.gypi',
-            '../build/isolate.gypi',
+            '../gypfiles/features.gypi',
+            '../gypfiles/isolate.gypi',
           ],
           'sources': [
             'ignition.isolate',
diff --git a/test/intl/assert.js b/test/intl/assert.js
index 3180e6f..e176152 100644
--- a/test/intl/assert.js
+++ b/test/intl/assert.js
@@ -87,14 +87,13 @@
   return deepObjectEquals(a, b);
 }
 
-
 /**
- * Throws an exception, and prints the values in case of error.
+ * Throws an exception containing the user_message (if any) and the values.
  */
-function fail(expected, found) {
+function fail(expected, found, user_message = '') {
   // TODO(cira): Replace String with PrettyPrint for objects and arrays.
-  var message = 'Failure: expected <' + String(expected) + '>, found <' +
-      String(found) + '>.';
+  var message = 'Failure' + (user_message ? ' (' + user_message + ')' : '') +
+      ': expected <' + String(expected) + '>, found <' + String(found) + '>.';
   throw new Error(message);
 }
 
@@ -102,9 +101,9 @@
 /**
  * Throws if two variables have different types or values.
  */
-function assertEquals(expected, found) {
+function assertEquals(expected, found, user_message = '') {
   if (!deepEquals(expected, found)) {
-    fail(expected, found);
+    fail(expected, found, user_message);
   }
 }
 
@@ -112,49 +111,49 @@
 /**
  * Throws if value is false.
  */
-function assertTrue(value) {
-  assertEquals(true, value)
+function assertTrue(value, user_message = '') {
+  assertEquals(true, value, user_message);
 }
 
 
 /**
  * Throws if value is true.
  */
-function assertFalse(value) {
-  assertEquals(false, value);
+function assertFalse(value, user_message = '') {
+  assertEquals(false, value, user_message);
 }
 
 
 /**
- * Returns true if code throws specified exception.
+ * Runs code() and asserts that it throws the specified exception.
  */
 function assertThrows(code, type_opt, cause_opt) {
-  var threwException = true;
   try {
     if (typeof code == 'function') {
       code();
     } else {
       eval(code);
     }
-    threwException = false;
   } catch (e) {
     if (typeof type_opt == 'function') {
       assertInstanceof(e, type_opt);
     }
     if (arguments.length >= 3) {
-      assertEquals(e.type, cause_opt);
+      assertEquals(cause_opt, e.type, 'thrown exception type mismatch');
     }
     // Success.
     return;
   }
-  throw new Error("Did not throw exception");
+  var expected = arguments.length >= 3 ? cause_opt :
+      typeof type_opt == 'function' ? type_opt : 'any exception';
+  fail(expected, 'no exception', 'expected thrown exception');
 }
 
 
 /**
- * Throws an exception if code throws.
+ * Runs code() and asserts that it does now throw any exception.
  */
-function assertDoesNotThrow(code, name_opt) {
+function assertDoesNotThrow(code, user_message = '') {
   try {
     if (typeof code == 'function') {
       code();
@@ -162,7 +161,7 @@
       eval(code);
     }
   } catch (e) {
-    fail("threw an exception: ", e.message || e, name_opt);
+    fail("no expection", "exception: " + String(e), user_message);
   }
 }
 
diff --git a/test/intl/date-format/parse-MMMdy.js b/test/intl/date-format/parse-MMMdy.js
index b23a3cd..f8291f4 100644
--- a/test/intl/date-format/parse-MMMdy.js
+++ b/test/intl/date-format/parse-MMMdy.js
@@ -28,6 +28,8 @@
 // Testing v8Parse method for date and time pattern.
 // Month is represented as a short name.
 
+// Flags: --intl-extra
+
 var dtf = new Intl.DateTimeFormat(['en'],
                                   {year: 'numeric', month: 'short',
                                    day: 'numeric',
@@ -41,11 +43,17 @@
 assertEquals(1, date.getUTCMonth());
 assertEquals(4, date.getUTCDate());
 
-// Missing , in the pattern.
-assertEquals(undefined, dtf.v8Parse('Feb 4 1974'));
+// Can deal with a missing ','.
+date = dtf.v8Parse('Feb 4 1974');
+assertEquals(1974, date.getUTCFullYear());
+assertEquals(1, date.getUTCMonth());
+assertEquals(4, date.getUTCDate());
 
 // Extra "th" after 4 in the pattern.
 assertEquals(undefined, dtf.v8Parse('Feb 4th, 1974'));
 
-// Wrong pattern.
-assertEquals(undefined, dtf.v8Parse('2/4/1974'));
+// TODO(jshin): Make sure if this is what's supposed to be.
+date = dtf.v8Parse('2/4/1974');
+assertEquals(1974, date.getUTCFullYear());
+assertEquals(1, date.getUTCMonth());
+assertEquals(4, date.getUTCDate());
diff --git a/test/intl/date-format/parse-invalid-input.js b/test/intl/date-format/parse-invalid-input.js
index ab0b889..47a9547 100644
--- a/test/intl/date-format/parse-invalid-input.js
+++ b/test/intl/date-format/parse-invalid-input.js
@@ -25,6 +25,8 @@
 // (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: --intl-extra
+
 // Invalid input is handled properly.
 
 var dtf = new Intl.DateTimeFormat(['en']);
diff --git a/test/intl/date-format/parse-mdy.js b/test/intl/date-format/parse-mdy.js
index 7b1a79a..a248a08 100644
--- a/test/intl/date-format/parse-mdy.js
+++ b/test/intl/date-format/parse-mdy.js
@@ -25,6 +25,8 @@
 // (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: --intl-extra
+
 // Testing v8Parse method for date only.
 
 function checkDate(date) {
diff --git a/test/intl/date-format/parse-mdyhms.js b/test/intl/date-format/parse-mdyhms.js
index 73efb62..766f719 100644
--- a/test/intl/date-format/parse-mdyhms.js
+++ b/test/intl/date-format/parse-mdyhms.js
@@ -26,6 +26,8 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Testing v8Parse method for date and time pattern.
+//
+// Flags: --intl-extra
 
 var dtf = new Intl.DateTimeFormat(['en'],
                                   {year: 'numeric', month: 'numeric',
@@ -34,7 +36,7 @@
                                    timeZone: 'UTC'});
 
 // Make sure we have pattern we expect (may change in the future).
-assertEquals('M/d/y h:mm:ss a', dtf.resolved.pattern);
+assertEquals('M/d/y, h:mm:ss a', dtf.resolved.pattern);
 
 var date = dtf.v8Parse('2/4/74 12:30:42 pm');
 assertEquals(1974, date.getUTCFullYear());
@@ -44,14 +46,20 @@
 assertEquals(30, date.getUTCMinutes());
 assertEquals(42, date.getUTCSeconds());
 
+// Can deal with '-' vs '/'.
+date = dtf.v8Parse('2-4-74 12:30:42 am');
+assertEquals(1974, date.getUTCFullYear());
+assertEquals(1, date.getUTCMonth());
+assertEquals(4, date.getUTCDate());
+assertEquals(0, date.getUTCHours());
+assertEquals(30, date.getUTCMinutes());
+assertEquals(42, date.getUTCSeconds());
+
 // AM/PM were not specified.
-assertEquals(undefined, dtf.v8Parse('2/4/74 12:30:12'));
+assertEquals(undefined, dtf.v8Parse('2/4/74 12:30:42'));
 
 // Time was not specified.
 assertEquals(undefined, dtf.v8Parse('2/4/74'));
 
 // Month is numeric, so it fails on "Feb".
 assertEquals(undefined, dtf.v8Parse('Feb 4th 1974'));
-
-// Wrong date delimiter.
-assertEquals(undefined, dtf.v8Parse('2-4-74 12:30:12 am'));
diff --git a/test/intl/extra-flag.js b/test/intl/extra-flag.js
new file mode 100644
index 0000000..3d434a3
--- /dev/null
+++ b/test/intl/extra-flag.js
@@ -0,0 +1,23 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --intl-extra
+
+// Turning on the creates the non-standard properties
+
+var dtf = new Intl.DateTimeFormat(['en']);
+assertTrue('v8Parse' in dtf);
+assertTrue('resolved' in dtf);
+assertTrue(!!dtf.resolved && 'pattern' in dtf.resolved);
+
+var nf = new Intl.NumberFormat(['en']);
+assertTrue('v8Parse' in nf);
+assertTrue('resolved' in nf);
+assertTrue(!!nf.resolved && 'pattern' in nf.resolved);
+
+var col = new Intl.Collator(['en']);
+assertTrue('resolved' in col);
+
+var br = new Intl.v8BreakIterator(['en']);
+assertTrue('resolved' in br);
diff --git a/test/intl/general/case-mapping.js b/test/intl/general/case-mapping.js
new file mode 100644
index 0000000..a73622b
--- /dev/null
+++ b/test/intl/general/case-mapping.js
@@ -0,0 +1,138 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --icu_case_mapping
+
+// Some edge cases that unibrow got wrong
+
+assertEquals("𐐘", "𐑀".toUpperCase());
+assertEquals("𐑀", "𐐘".toLowerCase());
+assertEquals("σ", "Σ".toLowerCase());
+
+// Some different paths in the ICU case conversion fastpath
+
+assertEquals("σς", "\u03A3\u03A3".toLowerCase());
+// Expand sharp s in latin1 fastpath
+assertEquals("ASSB", "A\u00DFB".toUpperCase());
+assertEquals("AB", "Ab".toUpperCase());
+// Find first upper case in fastpath
+assertEquals("ab", "aB".toLowerCase());
+assertEquals("AÜ", "aü".toUpperCase());
+assertEquals("AÜ", "AÜ".toUpperCase());
+assertEquals("aü", "aü".toLowerCase());
+assertEquals("aü", "AÜ".toLowerCase());
+assertEquals("aü", "AÜ".toLowerCase());
+
+// Starts with fastpath, but switches to full Unicode path
+// U+00FF is uppercased to U+0178.
+assertEquals("AŸ", "aÿ".toUpperCase());
+// U+00B5 (µ) is uppercased to U+039C (Μ)
+assertEquals("AΜ", "aµ".toUpperCase());
+
+// Buffer size increase
+assertEquals("CSSBẶ", "cßbặ".toUpperCase());
+assertEquals("FIFLFFIFFL", "\uFB01\uFB02\uFB03\uFB04".toUpperCase());
+// OneByte input with buffer size increase: non-fast path
+assertEquals("ABCSS", "abCß".toLocaleUpperCase("tr"));
+
+// More comprehensive tests for "tr", "az" and "lt" are in
+// test262/intl402/Strings/*
+
+// Buffer size decrease with a single locale or locale list.
+// In Turkic (tr, az), U+0307 preceeded by Capital Letter I is dropped.
+assertEquals("abci", "aBcI\u0307".toLocaleLowerCase("tr"));
+assertEquals("abci", "aBcI\u0307".toLocaleLowerCase("az"));
+assertEquals("abci", "aBcI\u0307".toLocaleLowerCase(["tr", "en"]));
+
+// Cons string
+assertEquals("abcijkl", ("aBcI" + "\u0307jkl").toLocaleLowerCase("tr"));
+assertEquals("abcijkl",
+             ("aB" + "cI" + "\u0307j" + "kl").toLocaleLowerCase("tr"));
+assertEquals("abci\u0307jkl", ("aBcI" + "\u0307jkl").toLocaleLowerCase("en"));
+assertEquals("abci\u0307jkl",
+             ("aB" + "cI" + "\u0307j" + "kl").toLocaleLowerCase("en"));
+assertEquals("abci\u0307jkl", ("aBcI" + "\u0307jkl").toLowerCase());
+assertEquals("abci\u0307jkl",
+             ("aB" + "cI" + "\u0307j" + "kl").toLowerCase());
+
+// "tr" and "az" should behave identically.
+assertEquals("aBcI\u0307".toLocaleLowerCase("tr"),
+             "aBcI\u0307".toLocaleLowerCase("az"));
+// What matters is the first locale in the locale list.
+assertEquals("aBcI\u0307".toLocaleLowerCase(["tr", "en", "fr"]),
+             "aBcI\u0307".toLocaleLowerCase("tr"));
+assertEquals("aBcI\u0307".toLocaleLowerCase(["en", "tr", "az"]),
+             "aBcI\u0307".toLocaleLowerCase("en"));
+assertEquals("aBcI\u0307".toLocaleLowerCase(["en", "tr", "az"]),
+             "aBcI\u0307".toLowerCase());
+
+// An empty locale list is the same as the default locale. Try these tests
+// under Turkish and Greek locale.
+assertEquals("aBcI\u0307".toLocaleLowerCase([]),
+             "aBcI\u0307".toLocaleLowerCase());
+assertEquals("aBcI\u0307".toLocaleLowerCase([]),
+             "aBcI\u0307".toLocaleLowerCase(Intl.GetDefaultLocale));
+assertEquals("άόύώ".toLocaleUpperCase([]), "άόύώ".toLocaleUpperCase());
+assertEquals("άόύώ".toLocaleUpperCase([]),
+             "άόύώ".toLocaleUpperCase(Intl.GetDefaultLocale));
+
+
+// English/root locale keeps U+0307 (combining dot above).
+assertEquals("abci\u0307", "aBcI\u0307".toLocaleLowerCase("en"));
+assertEquals("abci\u0307", "aBcI\u0307".toLocaleLowerCase(["en", "tr"]));
+assertEquals("abci\u0307", "aBcI\u0307".toLowerCase());
+
+// Greek uppercasing: not covered by intl402/String/*, yet. Tonos (U+0301) and
+// other diacritic marks are dropped. This rule is based on the current CLDR's
+// el-Upper transformation, but Greek uppercasing rules are more sophisticated
+// than this. See http://bugs.icu-project.org/trac/ticket/10582 and
+// http://unicode.org/cldr/trac/ticket/7905 .
+assertEquals("Α", "α\u0301".toLocaleUpperCase("el"));
+assertEquals("Α", "α\u0301".toLocaleUpperCase("el-GR"));
+assertEquals("Α", "α\u0301".toLocaleUpperCase("el-Grek"));
+assertEquals("Α", "α\u0301".toLocaleUpperCase("el-Grek-GR"));
+assertEquals("Α", "ά".toLocaleUpperCase("el"));
+assertEquals("ΑΟΥΩ", "άόύώ".toLocaleUpperCase("el"));
+assertEquals("ΑΟΥΩ", "α\u0301ο\u0301υ\u0301ω\u0301".toLocaleUpperCase("el"));
+assertEquals("ΑΟΥΩ", "άόύώ".toLocaleUpperCase("el"));
+assertEquals("ΟΕ", "Ό\u1f15".toLocaleUpperCase("el"));
+assertEquals("ΟΕ", "Ο\u0301ε\u0314\u0301".toLocaleUpperCase("el"));
+
+// Input and output are identical.
+assertEquals("αβγδε", "αβγδε".toLocaleLowerCase("el"));
+assertEquals("ΑΒΓΔΕ", "ΑΒΓΔΕ".toLocaleUpperCase("el"));
+assertEquals("ΑΒΓΔΕАБ𝐀𝐁", "ΑΒΓΔΕАБ𝐀𝐁".toLocaleUpperCase("el"));
+assertEquals("ABCDEÂÓḴ123", "ABCDEÂÓḴ123".toLocaleUpperCase("el"));
+// ASCII-only or Latin-1 only: 1-byte
+assertEquals("ABCDE123", "ABCDE123".toLocaleUpperCase("el"));
+assertEquals("ABCDEÂÓ123", "ABCDEÂÓ123".toLocaleUpperCase("el"));
+
+// To make sure that the input string is not overwritten in place.
+var strings = ["abCdef", "αβγδε", "άόύώ", "аб"];
+for (var s  of strings) {
+  var backupAsArray = s.split("");
+  var uppered = s.toLocaleUpperCase("el");
+  assertEquals(s, backupAsArray.join(""));
+}
+
+// In other locales, U+0301 is preserved.
+assertEquals("Α\u0301Ο\u0301Υ\u0301Ω\u0301",
+             "α\u0301ο\u0301υ\u0301ω\u0301".toLocaleUpperCase("en"));
+assertEquals("Α\u0301Ο\u0301Υ\u0301Ω\u0301",
+             "α\u0301ο\u0301υ\u0301ω\u0301".toUpperCase());
+
+// Plane 1; Deseret and Warang Citi Script.
+assertEquals("\u{10400}\u{118A0}", "\u{10428}\u{118C0}".toUpperCase());
+assertEquals("\u{10428}\u{118C0}", "\u{10400}\u{118A0}".toLowerCase());
+// Mathematical Bold {Capital, Small} Letter A do not change.
+assertEquals("\u{1D400}\u{1D41A}", "\u{1D400}\u{1D41A}".toUpperCase());
+assertEquals("\u{1D400}\u{1D41A}", "\u{1D400}\u{1D41A}".toLowerCase());
+// Plane 1; New characters in Unicode 8.0
+assertEquals("\u{10C80}", "\u{10CC0}".toUpperCase());
+assertEquals("\u{10CC0}", "\u{10C80}".toLowerCase());
+assertEquals("\u{10C80}", "\u{10CC0}".toLocaleUpperCase());
+assertEquals("\u{10CC0}", "\u{10C80}".toLocaleLowerCase());
+assertEquals("\u{10C80}", "\u{10CC0}".toLocaleUpperCase(["tr"]));
+assertEquals("\u{10C80}", "\u{10CC0}".toLocaleUpperCase(["tr"]));
+assertEquals("\u{10CC0}", "\u{10C80}".toLocaleLowerCase());
diff --git a/test/intl/intl.gyp b/test/intl/intl.gyp
index 8fa7f06..f2e107f 100644
--- a/test/intl/intl.gyp
+++ b/test/intl/intl.gyp
@@ -13,8 +13,8 @@
             '../../src/d8.gyp:d8_run',
           ],
           'includes': [
-            '../../build/features.gypi',
-            '../../build/isolate.gypi',
+            '../../gypfiles/features.gypi',
+            '../../gypfiles/isolate.gypi',
           ],
           'sources': [
             'intl.isolate',
diff --git a/test/intl/intl.status b/test/intl/intl.status
index e890085..7ef6b0d 100644
--- a/test/intl/intl.status
+++ b/test/intl/intl.status
@@ -29,29 +29,11 @@
 [ALWAYS, {
   # TODO(jochen): The following test is flaky.
   'overrides/caching': [PASS, FAIL],
-
-  # BUG(v8:3454).
-  'date-format/parse-MMMdy': [FAIL],
-  'date-format/parse-mdyhms': [FAIL],
-  'number-format/parse-decimal': [FAIL],
-  'number-format/parse-percent': [FAIL],
 }],  # ALWAYS
 
-##############################################################################
-['system == linux', {
-  # BUG(v8:2899).
-  'collator/default-locale': [PASS, FAIL],
-}],  # 'system == linux'
-
-##############################################################################
-['system == macos', {
-  # BUG(v8:4459).
-  'collator/default-locale': [FAIL],
-}],  # 'system == macos'
-
-##############################################################################
-['arch == arm or arch == arm64', {
-  # BUG(v8:4459).
-  'collator/default-locale': [PASS, FAIL],
-}],  # 'arch == arm or arch == arm64'
+['arch == arm64 and mode == debug and simulator_run == True', {
+  # Ignition.
+  'date-format/timezone': [PASS, ['no_snap and mode == debug', NO_IGNITION]],
+  'number-format/check-digit-ranges': [PASS, ['no_snap and mode == debug', NO_IGNITION]],
+}],  # 'arch == arm64 and mode == debug and simulator_run == True'
 ]
diff --git a/test/intl/no-extra-flag.js b/test/intl/no-extra-flag.js
new file mode 100644
index 0000000..6735f84
--- /dev/null
+++ b/test/intl/no-extra-flag.js
@@ -0,0 +1,23 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --no-intl-extra
+
+// Turning off the flag removes the non-standard properties
+
+var dtf = new Intl.DateTimeFormat(['en']);
+assertFalse('v8Parse' in dtf);
+assertFalse('resolved' in dtf);
+assertFalse(!!dtf.resolved && 'pattern' in dtf.resolved);
+
+var nf = new Intl.NumberFormat(['en']);
+assertFalse('v8Parse' in nf);
+assertFalse('resolved' in nf);
+assertFalse(!!nf.resolved && 'pattern' in nf.resolved);
+
+var col = new Intl.Collator(['en']);
+assertFalse('resolved' in col);
+
+var br = new Intl.v8BreakIterator(['en']);
+assertFalse('resolved' in br);
diff --git a/test/intl/number-format/format-is-bound.js b/test/intl/number-format/format-is-bound.js
index d93ee00..edb6a4b 100644
--- a/test/intl/number-format/format-is-bound.js
+++ b/test/intl/number-format/format-is-bound.js
@@ -28,6 +28,8 @@
 // Create default NumberFormat.
 var nf = new Intl.NumberFormat();
 
+var beforeCount = Object.getOwnPropertyNames(nf).length;
+
 // Array we want to iterate, actual numbers are not important.
 var numberArray = [1, 2, 3];
 
@@ -39,4 +41,4 @@
 nf.format(12345);
 
 // Reading the format doesn't add any additional property keys
-assertEquals(1, Object.getOwnPropertyNames(nf).length);
+assertEquals(beforeCount, Object.getOwnPropertyNames(nf).length);
diff --git a/test/intl/number-format/parse-currency.js b/test/intl/number-format/parse-currency.js
index c87ffea..a57128e 100644
--- a/test/intl/number-format/parse-currency.js
+++ b/test/intl/number-format/parse-currency.js
@@ -28,6 +28,8 @@
 // Currency parsing is not yet supported. We need ICU49 or higher to get
 // it working.
 
+// Flags: --intl-extra
+
 var nf = new Intl.NumberFormat(['en'], {style: 'currency', currency: 'USD'});
 
 assertEquals(undefined, nf.v8Parse('USD 123.43'));
diff --git a/test/intl/number-format/parse-decimal.js b/test/intl/number-format/parse-decimal.js
index ea3f8dd..62f4728 100644
--- a/test/intl/number-format/parse-decimal.js
+++ b/test/intl/number-format/parse-decimal.js
@@ -24,16 +24,29 @@
 // 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: --intl-extra
 
 var nf = new Intl.NumberFormat(['en'], {style: 'decimal'});
 
 assertEquals(123.43, nf.v8Parse('123.43'));
 assertEquals(123, nf.v8Parse('123'));
 assertEquals(NaN, nf.v8Parse(NaN));
-assertEquals(12323, nf.v8Parse('123,23'));
-assertEquals(12323.456, nf.v8Parse('123,23.456'));
-assertEquals(12323.456, nf.v8Parse('0000000123,23.456'));
-assertEquals(-12323.456, nf.v8Parse('-123,23.456'));
+assertEquals(12323, nf.v8Parse('12,323'));
+assertEquals(12323, nf.v8Parse('12323'));
+assertEquals(12323.456, nf.v8Parse('12,323.456'));
+assertEquals(12323.456, nf.v8Parse('000000012323.456'));
+assertEquals(12323.456, nf.v8Parse('000,000,012,323.456'));
+assertEquals(-12323.456, nf.v8Parse('-12,323.456'));
 
-// Scientific notation gets ignored.
-assertEquals(123.456, nf.v8Parse('123.456e-3'));
+assertEquals(12323, nf.v8Parse('000000012323'));
+assertEquals(12323, nf.v8Parse('000,000,012,323'));
+assertEquals(undefined, nf.v8Parse('000000012,323.456'));
+
+// not tolerant of a misplaced thousand separator
+assertEquals(undefined, nf.v8Parse('123,23.456'));
+assertEquals(undefined, nf.v8Parse('0000000123,23.456'));
+assertEquals(undefined, nf.v8Parse('-123,23.456'));
+
+// Scientific notation is supported.
+assertEquals(0.123456, nf.v8Parse('123.456e-3'));
diff --git a/test/intl/number-format/parse-invalid-input.js b/test/intl/number-format/parse-invalid-input.js
index 8c84d0b..251b52a 100644
--- a/test/intl/number-format/parse-invalid-input.js
+++ b/test/intl/number-format/parse-invalid-input.js
@@ -25,6 +25,8 @@
 // (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: --intl-extra
+
 // Invalid input is handled properly.
 
 var nf = new Intl.NumberFormat(['en']);
diff --git a/test/intl/number-format/parse-percent.js b/test/intl/number-format/parse-percent.js
index 4964da4..0dc36d3 100644
--- a/test/intl/number-format/parse-percent.js
+++ b/test/intl/number-format/parse-percent.js
@@ -25,12 +25,22 @@
 // (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: --intl-extra
+
 var nf = new Intl.NumberFormat(['en'], {style: 'percent'});
 
 assertEquals(1.2343, nf.v8Parse('123.43%'));
 assertEquals(1.23, nf.v8Parse('123%'));
 assertEquals(NaN, nf.v8Parse(NaN));
-assertEquals(123.23, nf.v8Parse('123,23%'));
-assertEquals(123.23456, nf.v8Parse('123,23.456%'));
-assertEquals(123.23456, nf.v8Parse('0000000123,23.456%'));
-assertEquals(-123.23456, nf.v8Parse('-123,23.456%'));
+assertEquals(123.23, nf.v8Parse('12,323%'));
+assertEquals(123.23456, nf.v8Parse('12,323.456%'));
+assertEquals(123.23456, nf.v8Parse('000000012323.456%'));
+assertEquals(-123.23456, nf.v8Parse('-12,323.456%'));
+
+// Not tolerant of misplaced group separators.
+assertEquals(undefined, nf.v8Parse('123,23%'));
+assertEquals(undefined, nf.v8Parse('123,23.456%'));
+assertEquals(undefined, nf.v8Parse('0000000123,23.456%'));
+assertEquals(undefined, nf.v8Parse('-123,23.456%'));
+assertEquals(undefined, nf.v8Parse('0000000123,23.456%'));
+assertEquals(undefined, nf.v8Parse('-123,23.456%'));
diff --git a/test/intl/regress-4870.js b/test/intl/regress-4870.js
new file mode 100644
index 0000000..72c095e
--- /dev/null
+++ b/test/intl/regress-4870.js
@@ -0,0 +1,8 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+assertThrows(() =>
+    Object.getOwnPropertyDescriptor(Intl.Collator.prototype, 'compare')
+      .get.call(new Intl.DateTimeFormat())('a', 'b'),
+    TypeError);
diff --git a/test/intl/testcfg.py b/test/intl/testcfg.py
index 6e4b4f1..c7f17bb 100644
--- a/test/intl/testcfg.py
+++ b/test/intl/testcfg.py
@@ -26,10 +26,12 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import os
+import re
 
 from testrunner.local import testsuite
 from testrunner.objects import testcase
 
+FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
 
 class IntlTestSuite(testsuite.TestSuite):
 
@@ -55,7 +57,11 @@
     return tests
 
   def GetFlagsForTestCase(self, testcase, context):
+    source = self.GetSourceForTest(testcase)
     flags = ["--allow-natives-syntax"] + context.mode_flags
+    flags_match = re.findall(FLAGS_PATTERN, source)
+    for match in flags_match:
+      flags += match.strip().split()
 
     files = []
     files.append(os.path.join(self.root, "assert.js"))
@@ -71,6 +77,10 @@
 
     return testcase.flags + flags
 
+  def GetSourceForTest(self, testcase):
+    filename = os.path.join(self.root, testcase.path + self.suffix())
+    with open(filename) as f:
+      return f.read()
 
 def GetSuite(name, root):
   return IntlTestSuite(name, root)
diff --git a/test/js-perf-test/Generators/generators.js b/test/js-perf-test/Generators/generators.js
new file mode 100644
index 0000000..d49dee3
--- /dev/null
+++ b/test/js-perf-test/Generators/generators.js
@@ -0,0 +1,131 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+new BenchmarkSuite('Generators', [1000], [
+  new Benchmark('Basic', false, false, 0, Basic),
+  new Benchmark('Loop', false, false, 0, Loop),
+  new Benchmark('Input', false, false, 0, Input),
+  new Benchmark('YieldStar', false, false, 0, YieldStar),
+]);
+
+
+// ----------------------------------------------------------------------------
+// Benchmark: Basic
+// ----------------------------------------------------------------------------
+
+function* five() {
+  yield 1;
+  yield 2;
+  yield 3;
+  yield 4;
+  yield 5;
+}
+
+function Basic() {
+  let g = five();
+  let sum = 0;
+  sum += g.next().value;
+  sum += g.next().value;
+  sum += g.next().value;
+  sum += g.next().value;
+  sum += g.next().value;
+  if (sum != 15 || !g.next().done) throw "wrong";
+}
+
+
+// ----------------------------------------------------------------------------
+// Benchmark: Loop
+// ----------------------------------------------------------------------------
+
+function* fibonacci() {
+  let x = 0;
+  let y = 1;
+  yield x;
+  while (true) {
+    yield y;
+    let tmp = x;
+    x = y;
+    y += tmp;
+  }
+}
+
+function Loop() {
+  let n = 0;
+  let x;
+  for (x of fibonacci()) {
+    if (++n === 42) break;
+  }
+  if (x != 165580141) throw "wrong";
+}
+
+
+
+// ----------------------------------------------------------------------------
+// Benchmark: Input
+// ----------------------------------------------------------------------------
+
+function* multiples(x) {
+  let skip = function.sent || 0;
+  let next = 0;
+  while (true) {
+    if (skip === 0) {
+      skip = yield next;
+    } else {
+      skip--;
+    }
+    next += x;
+  }
+}
+
+function Input() {
+  let g = multiples(3);
+  results = [g.next(2), g.next(0), g.next(5), g.next(10)];
+  if (results.slice(-1)[0].value != 60) throw "wrong";
+}
+
+
+// ----------------------------------------------------------------------------
+// Benchmark: YieldStar
+// ----------------------------------------------------------------------------
+
+function* infix(node) {
+  if (node) {
+    yield* infix(node.left);
+    yield node.label;
+    yield* infix(node.right);
+  }
+}
+
+class Node {
+  constructor(label, left, right) {
+    this.label = label;
+    this.left = left;
+    this.right = right;
+  }
+}
+
+function YieldStar() {
+  let tree = new Node(1,
+      new Node(2,
+          new Node(3,
+              new Node(4,
+                  new Node(16,
+                      new Node(5,
+                          new Node(23,
+                              new Node(0),
+                              new Node(17)),
+                          new Node(44, new Node(20)))),
+                  new Node(7,
+                      undefined,
+                      new Node(23,
+                          new Node(0),
+                          new Node(41, undefined, new Node(11))))),
+              new Node(8)),
+          new Node(5)),
+      new Node(6, undefined, new Node(7)));
+  let labels = [...(infix(tree))];
+  // 0,23,17,5,20,44,16,4,7,0,23,41,11,3,8,2,5,1,6,7
+  if (labels[0] != 0) throw "wrong";
+}
diff --git a/test/js-perf-test/Generators/run.js b/test/js-perf-test/Generators/run.js
new file mode 100644
index 0000000..6feb6f7
--- /dev/null
+++ b/test/js-perf-test/Generators/run.js
@@ -0,0 +1,26 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+load('../base.js');
+load('generators.js');
+
+var success = true;
+
+function PrintResult(name, result) {
+  print(name + '-Generators(Score): ' + result);
+}
+
+
+function PrintError(name, error) {
+  PrintResult(name, error);
+  success = false;
+}
+
+
+BenchmarkSuite.config.doWarmup = undefined;
+BenchmarkSuite.config.doDeterministic = undefined;
+
+BenchmarkSuite.RunSuites({ NotifyResult: PrintResult,
+                           NotifyError: PrintError });
diff --git a/test/js-perf-test/JSTests.json b/test/js-perf-test/JSTests.json
index dc3cb75..ed471bb 100644
--- a/test/js-perf-test/JSTests.json
+++ b/test/js-perf-test/JSTests.json
@@ -9,6 +9,40 @@
   "resources": ["base.js"],
   "tests": [
     {
+      "name": "Generators",
+      "path": ["Generators"],
+      "main": "run.js",
+      "resources": ["generators.js"],
+      "flags": ["--harmony-function-sent"],
+      "results_regexp": "^Generators\\-Generators\\(Score\\): (.+)$"
+    },
+    {
+      "name": "GeneratorsIgnition",
+      "path": ["Generators"],
+      "main": "run.js",
+      "resources": ["generators.js"],
+      "flags": [
+        "--harmony-function-sent",
+        "--ignition",
+        "--ignition-generators"
+      ],
+      "results_regexp": "^Generators\\-Generators\\(Score\\): (.+)$"
+    },
+    {
+      "name": "GeneratorsIgnitionTurbofan",
+      "path": ["Generators"],
+      "main": "run.js",
+      "resources": ["generators.js"],
+      "flags": [
+        "--harmony-function-sent",
+        "--ignition",
+        "--ignition-generators",
+        "--turbo",
+        "--turbo-from-bytecode"
+      ],
+      "results_regexp": "^Generators\\-Generators\\(Score\\): (.+)$"
+    },
+    {
       "name": "RestParameters",
       "path": ["RestParameters"],
       "main": "run.js",
@@ -163,6 +197,29 @@
         {"name": "for (i < array.length)"},
         {"name": "for (i < length)"}
       ]
+    },
+    {
+      "name": "PropertyQueries",
+      "path": ["PropertyQueries"],
+      "main": "run.js",
+      "resources": ["property-queries.js"],
+      "results_regexp": "^%s\\-PropertyQueries\\(Score\\): (.+)$",
+      "tests": [
+        {"name": "in--INTERN-prop"},
+        {"name": "in--DEINTERN-prop"},
+        {"name": "in--NE-INTERN-prop"},
+        {"name": "in--NE-DEINTERN-prop"},
+        {"name": "in--el"},
+        {"name": "in--el-str"},
+        {"name": "in--NE-el"},
+        {"name": "Object.hasOwnProperty--INTERN-prop"},
+        {"name": "Object.hasOwnProperty--DEINTERN-prop"},
+        {"name": "Object.hasOwnProperty--NE-INTERN-prop"},
+        {"name": "Object.hasOwnProperty--NE-DEINTERN-prop"},
+        {"name": "Object.hasOwnProperty--el"},
+        {"name": "Object.hasOwnProperty--el-str"},
+        {"name": "Object.hasOwnProperty--NE-el"}
+      ]
     }
   ]
 }
diff --git a/test/js-perf-test/PropertyQueries/PropertyQueries.json b/test/js-perf-test/PropertyQueries/PropertyQueries.json
new file mode 100644
index 0000000..49b953d
--- /dev/null
+++ b/test/js-perf-test/PropertyQueries/PropertyQueries.json
@@ -0,0 +1,38 @@
+{
+  "name": "PropertyQueriesTests",
+  "run_count": 5,
+  "run_count_android_arm": 3,
+  "run_count_android_arm64": 3,
+  "timeout": 120,
+  "units": "score",
+  "total": true,
+  "resources": ["base.js"],
+  "tests": [
+    {
+      "name": "PropertyQueries",
+      "path": ["."],
+      "main": "run.js",
+      "flags": [""],
+      "resources": [
+        "property-queries.js"
+      ],
+      "results_regexp": "^%s\\-PropertyQueries\\(Score\\): (.+)$",
+      "tests": [
+        {"name": "in--INTERN-prop"},
+        {"name": "in--DEINTERN-prop"},
+        {"name": "in--NE-INTERN-prop"},
+        {"name": "in--NE-DEINTERN-prop"},
+        {"name": "in--el"},
+        {"name": "in--el-str"},
+        {"name": "in--NE-el"},
+        {"name": "Object.hasOwnProperty--INTERN-prop"},
+        {"name": "Object.hasOwnProperty--DEINTERN-prop"},
+        {"name": "Object.hasOwnProperty--NE-INTERN-prop"},
+        {"name": "Object.hasOwnProperty--NE-DEINTERN-prop"},
+        {"name": "Object.hasOwnProperty--el"},
+        {"name": "Object.hasOwnProperty--el-str"},
+        {"name": "Object.hasOwnProperty--NE-el"}
+      ]
+    }
+  ]
+}
diff --git a/test/js-perf-test/PropertyQueries/property-queries.js b/test/js-perf-test/PropertyQueries/property-queries.js
new file mode 100644
index 0000000..f763d26
--- /dev/null
+++ b/test/js-perf-test/PropertyQueries/property-queries.js
@@ -0,0 +1,274 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function ObjectWithKeys(count, keyOffset = 0, keyGen) {
+  var body = "";
+  for (var i = 0; i < count; i++) {
+    var key = keyGen(i + keyOffset);
+    if (typeof key === "string") {
+      body += `this.${key} = 0\n`;
+    } else {
+      body += `this[${key}] = 0\n`;
+    }
+  }
+  var f = new Function(body);
+  return new f();
+}
+
+function ObjectWithProperties(count, keyOffset) {
+  return ObjectWithKeys(count, keyOffset, (key) => "key" + key );
+}
+
+function ObjectWithElements(count, keyOffset) {
+  return ObjectWithKeys(count, keyOffset, (key) => key );
+}
+
+function ObjectWithMixedKeys(count, keyOffset) {
+  return ObjectWithKeys(count, keyOffset, (key) => {
+    if (key % 2 == 0) return (key / 2);
+    return "key" + ((key - 1)  / 2);
+  });
+}
+
+// Create an object with #depth prototypes each having #keys properties
+// generated by given keyGen.
+function ObjectWithProtoKeys(depth, keys, cacheable,
+                             keyGen = ObjectWithProperties) {
+  var o = keyGen(keys);
+  var current = o;
+  var keyOffset = 0;
+  for (var i = 0; i < depth; i++) {
+    keyOffset += keys;
+    current.__proto__ = keyGen(keys, keyOffset);
+    current = current.__proto__;
+  }
+  if (cacheable === false) {
+    // Add an empty proxy at the prototype chain to make caching properties
+    // impossible.
+    current.__proto__ = new Proxy({}, {});
+  }
+  return o;
+}
+
+
+function HoleyIntArray(size) {
+  var array = new Array(size);
+  for (var i = 0; i < size; i += 3) {
+    array[i] = i;
+  }
+  return array
+}
+
+function IntArray(size) {
+  var array = new Array(size);
+  for (var i = 0; i < size; i++) {
+    array[i] = i;
+  }
+  return array;
+}
+
+// Switch object's properties and elements to dictionary mode.
+function MakeDictionaryMode(obj) {
+  obj.foo = 0;
+  delete obj.foo;
+  obj[1e9] = 0;
+  return obj;
+}
+
+function Internalize(s) {
+  return Object.keys({[s]:0})[0];
+}
+
+function Deinternalize(s) {
+  return [...s].join("");
+}
+
+// ============================================================================
+
+const QUERY_INTERNALIZED_PROP = "INTERN-prop";
+const QUERY_DEINTERNALIZED_PROP = "DEINTERN-prop";
+const QUERY_NON_EXISTING_INTERNALIZED_PROP = "NE-INTERN-prop";
+const QUERY_NON_EXISTING_DEINTERNALIZED_PROP = "NE-DEINTERN-prop";
+const QUERY_ELEMENT = "el";
+const QUERY_ELEMENT_AS_STRING = "el-str";
+const QUERY_NON_EXISTING_ELEMENT = "NE-el";
+
+const OBJ_MODE_FAST = "fast";
+const OBJ_MODE_SLOW = "slow";
+
+var TestQueries = [
+  QUERY_INTERNALIZED_PROP,
+  QUERY_DEINTERNALIZED_PROP,
+  QUERY_NON_EXISTING_INTERNALIZED_PROP,
+  QUERY_NON_EXISTING_DEINTERNALIZED_PROP,
+  QUERY_ELEMENT,
+  QUERY_ELEMENT_AS_STRING,
+  QUERY_NON_EXISTING_ELEMENT,
+];
+
+const QUERIES_PER_OBJECT_NUMBER = 10;
+
+// Leave only every "count"th keys.
+function FilterKeys(keys, count) {
+  var len = keys.length;
+  if (len < count) throw new Error("Keys array is too short: " + len);
+  var step = len / count;
+  if (step == 0) throw new Error("Bad count specified: " + count);
+  return keys.filter((element, index) => index % step == 0);
+}
+
+
+function MakeKeyQueries(keys, query_kind) {
+  var properties = keys.filter((element) => isNaN(Number(element)));
+  var elements = keys.filter((element) => !isNaN(Number(element)));
+
+  properties = FilterKeys(properties, QUERIES_PER_OBJECT_NUMBER);
+  elements = FilterKeys(elements, QUERIES_PER_OBJECT_NUMBER);
+
+  switch (query_kind) {
+    case QUERY_INTERNALIZED_PROP:
+      return properties;
+
+    case QUERY_DEINTERNALIZED_PROP:
+      return properties.map(Deinternalize);
+
+    case QUERY_NON_EXISTING_INTERNALIZED_PROP:
+    case QUERY_NON_EXISTING_DEINTERNALIZED_PROP:
+      var non_existing = [];
+      for (var i = 0; i < QUERIES_PER_OBJECT_NUMBER; i++) {
+        non_existing.push("non-existing" + i);
+      }
+      if (query_kind == QUERY_NON_EXISTING_INTERNALIZED_PROP) {
+        return non_existing.map(Internalize);
+      } else {
+        return non_existing.map(Deinternalize);
+      }
+
+    case QUERY_ELEMENT:
+      return elements.map(Number);
+
+    case QUERY_ELEMENT_AS_STRING:
+      return elements.map(String);
+
+    case QUERY_NON_EXISTING_ELEMENT:
+      var non_existing = [];
+      for (var i = 0; i < QUERIES_PER_OBJECT_NUMBER; i++) {
+        non_existing.push(1200 + 100*i);
+      }
+      return non_existing;
+
+    default:
+      throw new Error("Bad query_kind: " + query_kind);
+  }
+}
+
+
+var TestData = [];
+
+[true, false].forEach((cachable) => {
+  [OBJ_MODE_FAST, OBJ_MODE_SLOW].forEach((obj_mode) => {
+    var proto_mode = cachable ? "" : "-with-slow-proto";
+    var name = `${obj_mode}-obj${proto_mode}`;
+    var objects = [];
+    [10, 50, 100, 200, 500].forEach((prop_count) => {
+      // Create object with prop_count properties and prop_count elements.
+      obj = ObjectWithProtoKeys(5, prop_count * 2, cachable,
+                                ObjectWithMixedKeys);
+      if (obj_mode == OBJ_MODE_SLOW) {
+        obj = MakeDictionaryMode(obj);
+      }
+      objects.push(obj);
+    });
+    TestData.push({name, objects});
+  });
+});
+
+
+// ============================================================================
+
+function CreateTestFunction(template, object, keys) {
+  // Force a new function for each test-object to avoid side-effects due to ICs.
+  var text = "// random comment " + Math.random() + "\n" +
+             template(object, keys);
+  var func = new Function("object", "keys", text);
+  return () => func(object, keys);
+}
+
+function CombineTestFunctions(tests) {
+  return () => {
+    for (var i = 0; i < tests.length; i++ ) {
+      tests[i]();
+    }
+  };
+}
+
+var TestFunctions = [
+  {
+    name: "in",
+    // Query all keys.
+    keys: (object) => Object.keys(object),
+    template: (object, keys) => {
+      var lines = [
+        `var result = true;`,
+        `for (var i = 0; i < keys.length; i++) {`,
+        `  var key = keys[i];`,
+        `  result = (key in object) && result;`,
+        `}`,
+        `return result;`,
+      ];
+      return lines.join("\n");
+    },
+  },
+  {
+    name: "Object.hasOwnProperty",
+    // Query only own keys.
+    keys: (object) => Object.getOwnPropertyNames(object),
+    template: (object, keys) => {
+      var lines = [
+        `var result = true;`,
+        `for (var i = 0; i < keys.length; i++) {`,
+        `  var key = keys[i];`,
+        `  result = object.hasOwnProperty(key) && result;`,
+        `}`,
+        `return result;`,
+      ];
+      return lines.join("\n");
+    },
+  },
+];
+
+
+// ============================================================================
+// Create the benchmark suites. We create a suite for each pair of the test
+// functions above and query kind. Each suite contains benchmarks for each
+// object type.
+var Benchmarks = [];
+
+for (var test_function_desc of TestFunctions) {
+  var test_function_name = test_function_desc.name;
+
+  for (var query_kind of TestQueries) {
+    var benchmarks = [];
+    var suit_name = test_function_name + "--" + query_kind;
+    for (var test_data of TestData) {
+      var name = suit_name + "--" + test_data.name;
+
+      var tests = [];
+      for (var object of test_data.objects) {
+        var keys = test_function_desc.keys(object);
+        keys = MakeKeyQueries(keys, query_kind);
+
+        var test = CreateTestFunction(test_function_desc.template, object,
+                                      keys);
+        tests.push(test);
+      }
+      var run_function = CombineTestFunctions(tests);
+      var benchmark = new Benchmark(name, false, false, 0, run_function);
+      benchmarks.push(benchmark);
+    }
+    Benchmarks.push(new BenchmarkSuite(suit_name, [100], benchmarks));
+  }
+}
+
+// ============================================================================
diff --git a/test/js-perf-test/PropertyQueries/run.js b/test/js-perf-test/PropertyQueries/run.js
new file mode 100644
index 0000000..d98c366
--- /dev/null
+++ b/test/js-perf-test/PropertyQueries/run.js
@@ -0,0 +1,23 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+load('../base.js');
+load('property-queries.js');
+
+var success = true;
+
+function PrintResult(name, result) {
+  print(name + '-PropertyQueries(Score): ' + result);
+}
+
+function PrintError(name, error) {
+  PrintResult(name, error);
+  success = false;
+}
+
+BenchmarkSuite.config.doWarmup = undefined;
+BenchmarkSuite.config.doDeterministic = undefined;
+
+BenchmarkSuite.RunSuites({ NotifyResult: PrintResult,
+                           NotifyError: PrintError });
diff --git a/test/memory/Memory.json b/test/memory/Memory.json
index 1cdc148..c6b8cd5 100644
--- a/test/memory/Memory.json
+++ b/test/memory/Memory.json
@@ -12,7 +12,7 @@
     },
     {
       "name": "ReservedMemoryContext",
-      "results_regexp": "(\\d+) bytes per context$"
+      "results_regexp": "(\\d+) bytes per context #0$"
     },
     {
       "name": "SnapshotSizeStartup",
@@ -20,7 +20,7 @@
     },
     {
       "name": "SnapshotSizeContext",
-      "results_regexp": "(\\d+) bytes for context$"
+      "results_regexp": "(\\d+) bytes for context #0$"
     }
   ]
 }
diff --git a/test/message/const-decl-no-init-sloppy.js b/test/message/const-decl-no-init-sloppy.js
deleted file mode 100644
index a122eae..0000000
--- a/test/message/const-decl-no-init-sloppy.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Flags: --harmony-sloppy
-
-function f() {
-  const a;
-}
diff --git a/test/message/generators-throw1.js b/test/message/generators-throw1.js
new file mode 100644
index 0000000..f544d33
--- /dev/null
+++ b/test/message/generators-throw1.js
@@ -0,0 +1,9 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --ignition-generators
+
+function* f() { yield }
+
+f().throw(42);
diff --git a/test/message/generators-throw1.out b/test/message/generators-throw1.out
new file mode 100644
index 0000000..aeb9645
--- /dev/null
+++ b/test/message/generators-throw1.out
@@ -0,0 +1,3 @@
+*%(basename)s:7: 42
+function* f() { yield }
+           ^
diff --git a/test/message/generators-throw2.js b/test/message/generators-throw2.js
new file mode 100644
index 0000000..b805bbc
--- /dev/null
+++ b/test/message/generators-throw2.js
@@ -0,0 +1,11 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --ignition-generators
+
+function* f() { yield }
+
+let g = f();
+g.next();
+g.throw(42);
diff --git a/test/message/generators-throw2.out b/test/message/generators-throw2.out
new file mode 100644
index 0000000..96353a5
--- /dev/null
+++ b/test/message/generators-throw2.out
@@ -0,0 +1,3 @@
+*%(basename)s:7: 42
+function* f() { yield }
+                ^
diff --git a/test/message/instanceof-noncallable.js b/test/message/instanceof-noncallable.js
index 571a2b0..d82b416 100644
--- a/test/message/instanceof-noncallable.js
+++ b/test/message/instanceof-noncallable.js
@@ -25,6 +25,6 @@
 // (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-instanceof
+
 
 1 instanceof {};
diff --git a/test/message/instanceof-nonobject.js b/test/message/instanceof-nonobject.js
index 4715257..ef8e0ae 100644
--- a/test/message/instanceof-nonobject.js
+++ b/test/message/instanceof-nonobject.js
@@ -25,6 +25,6 @@
 // (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-instanceof
+
 
 1 instanceof 2;
diff --git a/test/message/let-lexical-name-in-array-prohibited.js b/test/message/let-lexical-name-in-array-prohibited.js
index a6cba6f..e5e37e1 100644
--- a/test/message/let-lexical-name-in-array-prohibited.js
+++ b/test/message/let-lexical-name-in-array-prohibited.js
@@ -2,6 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Flags: --harmony-sloppy --harmony-sloppy-let
+//
 
 let [let];
diff --git a/test/message/let-lexical-name-in-object-prohibited.js b/test/message/let-lexical-name-in-object-prohibited.js
index 0a12762..4e26c62 100644
--- a/test/message/let-lexical-name-in-object-prohibited.js
+++ b/test/message/let-lexical-name-in-object-prohibited.js
@@ -2,6 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Flags: --harmony-sloppy --harmony-sloppy-let
+//
 
 let {let};
diff --git a/test/message/let-lexical-name-prohibited.js b/test/message/let-lexical-name-prohibited.js
index ed72fae..b001be8 100644
--- a/test/message/let-lexical-name-prohibited.js
+++ b/test/message/let-lexical-name-prohibited.js
@@ -2,6 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Flags: --harmony-sloppy --harmony-sloppy-let
+//
 
 let let;
diff --git a/test/message/message.gyp b/test/message/message.gyp
index dac6d9f..fc1ae32 100644
--- a/test/message/message.gyp
+++ b/test/message/message.gyp
@@ -13,8 +13,8 @@
             '../../src/d8.gyp:d8_run',
           ],
           'includes': [
-            '../../build/features.gypi',
-            '../../build/isolate.gypi',
+            '../../gypfiles/features.gypi',
+            '../../gypfiles/isolate.gypi',
           ],
           'sources': [
             'message.isolate',
diff --git a/test/message/message.status b/test/message/message.status
index 051911c..e4db83d 100644
--- a/test/message/message.status
+++ b/test/message/message.status
@@ -27,8 +27,6 @@
 
 [
 [ALWAYS, {
-  # All tests in the bug directory are expected to fail.
-  'bugs/*': [FAIL],
   # We don't parse RegExps at scanning time, so we can't fail on octal
   # escapes (we need to parse to distinguish octal escapes from valid
   # back-references).
diff --git a/test/message/no-legacy-const-2.js b/test/message/no-legacy-const-2.js
deleted file mode 100644
index 5dc63b3..0000000
--- a/test/message/no-legacy-const-2.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Flags: --no-harmony-sloppy --no-harmony-sloppy-let
-// Flags: --no-harmony-sloppy-function
-
-const = 42;
diff --git a/test/message/no-legacy-const-2.out b/test/message/no-legacy-const-2.out
deleted file mode 100644
index 5385250..0000000
--- a/test/message/no-legacy-const-2.out
+++ /dev/null
@@ -1,5 +0,0 @@
-*%(basename)s:8: SyntaxError: Unexpected token const
-const = 42;
-^^^^^
-
-SyntaxError: Unexpected token const
diff --git a/test/message/no-legacy-const-3.js b/test/message/no-legacy-const-3.js
deleted file mode 100644
index 43dd9c9..0000000
--- a/test/message/no-legacy-const-3.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Flags: --no-harmony-sloppy --no-harmony-sloppy-let
-// Flags: --no-harmony-sloppy-function
-
-const
diff --git a/test/message/no-legacy-const-3.out b/test/message/no-legacy-const-3.out
deleted file mode 100644
index 7539bbc..0000000
--- a/test/message/no-legacy-const-3.out
+++ /dev/null
@@ -1,5 +0,0 @@
-*%(basename)s:8: SyntaxError: Unexpected token const
-const
-^^^^^
-
-SyntaxError: Unexpected token const
diff --git a/test/message/no-legacy-const.js b/test/message/no-legacy-const.js
deleted file mode 100644
index 9eebee5..0000000
--- a/test/message/no-legacy-const.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Flags: --no-harmony-sloppy --no-harmony-sloppy-let
-// Flags: --no-harmony-sloppy-function
-
-const x = 42;
diff --git a/test/message/no-legacy-const.out b/test/message/no-legacy-const.out
deleted file mode 100644
index 33bb038..0000000
--- a/test/message/no-legacy-const.out
+++ /dev/null
@@ -1,5 +0,0 @@
-*%(basename)s:8: SyntaxError: Unexpected token const
-const x = 42;
-^^^^^
-
-SyntaxError: Unexpected token const
diff --git a/test/message/syntactic-tail-call-in-binop-lhs.js b/test/message/syntactic-tail-call-in-binop-lhs.js
new file mode 100644
index 0000000..58d4c95
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-binop-lhs.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+"use strict";
+
+function f() {
+  return 1;
+}
+
+function g() {
+  return   continue f()   - a ;
+}
diff --git a/test/message/syntactic-tail-call-in-binop-lhs.out b/test/message/syntactic-tail-call-in-binop-lhs.out
new file mode 100644
index 0000000..14670cd
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-binop-lhs.out
@@ -0,0 +1,4 @@
+*%(basename)s:13: SyntaxError: Tail call expression is not allowed here
+  return   continue f()   - a ;
+           ^^^^^^^^^^^^
+SyntaxError: Tail call expression is not allowed here
diff --git a/test/message/syntactic-tail-call-in-binop-rhs.js b/test/message/syntactic-tail-call-in-binop-rhs.js
new file mode 100644
index 0000000..a586cc8
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-binop-rhs.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+"use strict";
+
+function f() {
+  return 1;
+}
+
+function g() {
+  return b + continue f()  ;
+}
diff --git a/test/message/syntactic-tail-call-in-binop-rhs.out b/test/message/syntactic-tail-call-in-binop-rhs.out
new file mode 100644
index 0000000..207c526
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-binop-rhs.out
@@ -0,0 +1,4 @@
+*%(basename)s:13: SyntaxError: Tail call expression is not allowed here
+  return b + continue f()  ;
+             ^^^^^^^^^^^^
+SyntaxError: Tail call expression is not allowed here
diff --git a/test/message/syntactic-tail-call-in-comma.js b/test/message/syntactic-tail-call-in-comma.js
new file mode 100644
index 0000000..402a4a8
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-comma.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+"use strict";
+
+function f() {
+  return 1;
+}
+
+function g() {
+  return 1, 2, 3,   continue f() , 4  ;
+}
diff --git a/test/message/syntactic-tail-call-in-comma.out b/test/message/syntactic-tail-call-in-comma.out
new file mode 100644
index 0000000..c4ecc28
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-comma.out
@@ -0,0 +1,4 @@
+*%(basename)s:13: SyntaxError: Tail call expression is not allowed here
+  return 1, 2, 3,   continue f() , 4  ;
+                    ^^^^^^^^^^^^
+SyntaxError: Tail call expression is not allowed here
diff --git a/test/message/syntactic-tail-call-in-extends.js b/test/message/syntactic-tail-call-in-extends.js
new file mode 100644
index 0000000..86bf77e
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-extends.js
@@ -0,0 +1,10 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+"use strict";
+
+function g() {
+  return class A extends continue f() {};
+}
diff --git a/test/message/syntactic-tail-call-in-extends.out b/test/message/syntactic-tail-call-in-extends.out
new file mode 100644
index 0000000..f54155d
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-extends.out
@@ -0,0 +1,4 @@
+*%(basename)s:9: SyntaxError: Tail call expression is not allowed here
+  return class A extends continue f() {};
+                         ^^^^^^^^^^^^
+SyntaxError: Tail call expression is not allowed here
diff --git a/test/message/syntactic-tail-call-in-for-in.js b/test/message/syntactic-tail-call-in-for-in.js
new file mode 100644
index 0000000..8ad7aca
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-for-in.js
@@ -0,0 +1,16 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+"use strict";
+
+function f() {
+  return 1;
+}
+
+function g() {
+  for (var v in {a:0}) {
+    return continue f()  ;
+  }
+}
diff --git a/test/message/syntactic-tail-call-in-for-in.out b/test/message/syntactic-tail-call-in-for-in.out
new file mode 100644
index 0000000..1bf52c4
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-for-in.out
@@ -0,0 +1,4 @@
+*%(basename)s:14: SyntaxError: Tail call expression in for-in/of body
+    return continue f()  ;
+           ^^^^^^^^^^^^
+SyntaxError: Tail call expression in for-in/of body
diff --git a/test/message/syntactic-tail-call-in-for-of.js b/test/message/syntactic-tail-call-in-for-of.js
new file mode 100644
index 0000000..7cd761f
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-for-of.js
@@ -0,0 +1,16 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+"use strict";
+
+function f() {
+  return 1;
+}
+
+function g() {
+  for (var v of [1, 2, 3]) {
+    return continue f()  ;
+  }
+}
diff --git a/test/message/syntactic-tail-call-in-for-of.out b/test/message/syntactic-tail-call-in-for-of.out
new file mode 100644
index 0000000..1bf52c4
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-for-of.out
@@ -0,0 +1,4 @@
+*%(basename)s:14: SyntaxError: Tail call expression in for-in/of body
+    return continue f()  ;
+           ^^^^^^^^^^^^
+SyntaxError: Tail call expression in for-in/of body
diff --git a/test/message/syntactic-tail-call-in-logical-and.js b/test/message/syntactic-tail-call-in-logical-and.js
new file mode 100644
index 0000000..2c62ddc
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-logical-and.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+"use strict";
+
+function f() {
+  return 1;
+}
+
+function g() {
+  return   continue f()   && a ;
+}
diff --git a/test/message/syntactic-tail-call-in-logical-and.out b/test/message/syntactic-tail-call-in-logical-and.out
new file mode 100644
index 0000000..c400f74
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-logical-and.out
@@ -0,0 +1,4 @@
+*%(basename)s:13: SyntaxError: Tail call expression is not allowed here
+  return   continue f()   && a ;
+           ^^^^^^^^^^^^
+SyntaxError: Tail call expression is not allowed here
diff --git a/test/message/syntactic-tail-call-in-logical-or.js b/test/message/syntactic-tail-call-in-logical-or.js
new file mode 100644
index 0000000..6829bc6
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-logical-or.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+"use strict";
+
+function f() {
+  return 1;
+}
+
+function g() {
+  return   continue f()   || a ;
+}
diff --git a/test/message/syntactic-tail-call-in-logical-or.out b/test/message/syntactic-tail-call-in-logical-or.out
new file mode 100644
index 0000000..4ced761
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-logical-or.out
@@ -0,0 +1,4 @@
+*%(basename)s:13: SyntaxError: Tail call expression is not allowed here
+  return   continue f()   || a ;
+           ^^^^^^^^^^^^
+SyntaxError: Tail call expression is not allowed here
diff --git a/test/message/syntactic-tail-call-in-subclass.js b/test/message/syntactic-tail-call-in-subclass.js
new file mode 100644
index 0000000..ab78840
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-subclass.js
@@ -0,0 +1,15 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+"use strict";
+
+function g() {
+  class A {};
+  class B extends A {
+    constructor() {
+      return continue f() ;
+    }
+  }
+}
diff --git a/test/message/syntactic-tail-call-in-subclass.out b/test/message/syntactic-tail-call-in-subclass.out
new file mode 100644
index 0000000..fff26cc
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-subclass.out
@@ -0,0 +1,4 @@
+*%(basename)s:12: SyntaxError: Tail call expression is not allowed here
+      return continue f() ;
+             ^^^^^^^^^^^^
+SyntaxError: Tail call expression is not allowed here
diff --git a/test/message/syntactic-tail-call-in-try-catch-finally.js b/test/message/syntactic-tail-call-in-try-catch-finally.js
new file mode 100644
index 0000000..3aa35a1
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-try-catch-finally.js
@@ -0,0 +1,20 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+"use strict";
+
+function f() {
+  return 1;
+}
+
+function g() {
+  try {
+    f();
+  } catch(e) {
+    return continue f()  ;
+  } finally {
+    f();
+  }
+}
diff --git a/test/message/syntactic-tail-call-in-try-catch-finally.out b/test/message/syntactic-tail-call-in-try-catch-finally.out
new file mode 100644
index 0000000..b488c15
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-try-catch-finally.out
@@ -0,0 +1,4 @@
+*%(basename)s:16: SyntaxError: Tail call expression in catch block when finally block is also present
+    return continue f()  ;
+           ^^^^^^^^^^^^
+SyntaxError: Tail call expression in catch block when finally block is also present
diff --git a/test/message/syntactic-tail-call-in-try-try-catch-finally.js b/test/message/syntactic-tail-call-in-try-try-catch-finally.js
new file mode 100644
index 0000000..5b000f1
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-try-try-catch-finally.js
@@ -0,0 +1,22 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+"use strict";
+
+function f() {
+  return 1;
+}
+
+function g() {
+  try {
+    try {
+      f();
+    } catch(e) {
+      return continue f()  ;
+    }
+  } finally {
+    f();
+  }
+}
diff --git a/test/message/syntactic-tail-call-in-try-try-catch-finally.out b/test/message/syntactic-tail-call-in-try-try-catch-finally.out
new file mode 100644
index 0000000..bfc2692
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-try-try-catch-finally.out
@@ -0,0 +1,4 @@
+*%(basename)s:17: SyntaxError: Tail call expression in try block
+      return continue f()  ;
+             ^^^^^^^^^^^^
+SyntaxError: Tail call expression in try block
diff --git a/test/message/syntactic-tail-call-in-try.js b/test/message/syntactic-tail-call-in-try.js
new file mode 100644
index 0000000..71662db
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-try.js
@@ -0,0 +1,17 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+"use strict";
+
+function f() {
+  return 1;
+}
+
+function g() {
+  try {
+    return continue f()  ;
+  } catch(e) {
+  }
+}
diff --git a/test/message/syntactic-tail-call-in-try.out b/test/message/syntactic-tail-call-in-try.out
new file mode 100644
index 0000000..ed0b15c
--- /dev/null
+++ b/test/message/syntactic-tail-call-in-try.out
@@ -0,0 +1,4 @@
+*%(basename)s:14: SyntaxError: Tail call expression in try block
+    return continue f()  ;
+           ^^^^^^^^^^^^
+SyntaxError: Tail call expression in try block
diff --git a/test/message/syntactic-tail-call-inside-member-expr.js b/test/message/syntactic-tail-call-inside-member-expr.js
new file mode 100644
index 0000000..9b85dd4
--- /dev/null
+++ b/test/message/syntactic-tail-call-inside-member-expr.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+"use strict";
+
+function f() {
+  return 1;
+}
+
+function g() {
+  return (continue  f(1)) (2) ;
+}
diff --git a/test/message/syntactic-tail-call-inside-member-expr.out b/test/message/syntactic-tail-call-inside-member-expr.out
new file mode 100644
index 0000000..10fd54d
--- /dev/null
+++ b/test/message/syntactic-tail-call-inside-member-expr.out
@@ -0,0 +1,4 @@
+*%(basename)s:13: SyntaxError: Tail call expression is not allowed here
+  return (continue  f(1)) (2) ;
+          ^^^^^^^^^^^^^^
+SyntaxError: Tail call expression is not allowed here
diff --git a/test/message/syntactic-tail-call-of-eval.js b/test/message/syntactic-tail-call-of-eval.js
new file mode 100644
index 0000000..e69aa9c
--- /dev/null
+++ b/test/message/syntactic-tail-call-of-eval.js
@@ -0,0 +1,9 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+
+function g() {
+  return  continue  eval  ("f()")  ;
+}
diff --git a/test/message/syntactic-tail-call-of-eval.out b/test/message/syntactic-tail-call-of-eval.out
new file mode 100644
index 0000000..06eeb78
--- /dev/null
+++ b/test/message/syntactic-tail-call-of-eval.out
@@ -0,0 +1,4 @@
+*%(basename)s:8: SyntaxError: Tail call of a direct eval is not allowed
+  return  continue  eval  ("f()")  ;
+                    ^^^^^^^^^^^^^
+SyntaxError: Tail call of a direct eval is not allowed
diff --git a/test/message/syntactic-tail-call-of-identifier.js b/test/message/syntactic-tail-call-of-identifier.js
new file mode 100644
index 0000000..b3ca31d
--- /dev/null
+++ b/test/message/syntactic-tail-call-of-identifier.js
@@ -0,0 +1,10 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+"use strict";
+
+function g(x) {
+  return continue   x  ;
+}
diff --git a/test/message/syntactic-tail-call-of-identifier.out b/test/message/syntactic-tail-call-of-identifier.out
new file mode 100644
index 0000000..393bbc6
--- /dev/null
+++ b/test/message/syntactic-tail-call-of-identifier.out
@@ -0,0 +1,4 @@
+*%(basename)s:9: SyntaxError: Unexpected expression inside tail call
+  return continue   x  ;
+                    ^
+SyntaxError: Unexpected expression inside tail call
diff --git a/test/message/syntactic-tail-call-of-new.js b/test/message/syntactic-tail-call-of-new.js
new file mode 100644
index 0000000..60adec7
--- /dev/null
+++ b/test/message/syntactic-tail-call-of-new.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+
+function f() {
+  return 1;
+}
+
+function g() {
+  return continue new f()  ;
+}
diff --git a/test/message/syntactic-tail-call-of-new.out b/test/message/syntactic-tail-call-of-new.out
new file mode 100644
index 0000000..954e1ca
--- /dev/null
+++ b/test/message/syntactic-tail-call-of-new.out
@@ -0,0 +1,4 @@
+*%(basename)s:12: SyntaxError: Unexpected expression inside tail call
+  return continue new f()  ;
+                  ^^^^^^^
+SyntaxError: Unexpected expression inside tail call
diff --git a/test/message/syntactic-tail-call-sloppy.js b/test/message/syntactic-tail-call-sloppy.js
new file mode 100644
index 0000000..3973fc6
--- /dev/null
+++ b/test/message/syntactic-tail-call-sloppy.js
@@ -0,0 +1,9 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+
+function g() {
+  return  continue  f()  ;
+}
diff --git a/test/message/syntactic-tail-call-sloppy.out b/test/message/syntactic-tail-call-sloppy.out
new file mode 100644
index 0000000..74d9d53
--- /dev/null
+++ b/test/message/syntactic-tail-call-sloppy.out
@@ -0,0 +1,4 @@
+*%(basename)s:8: SyntaxError: Tail call expressions are not allowed in non-strict mode
+  return  continue  f()  ;
+          ^^^^^^^^^^^^^
+SyntaxError: Tail call expressions are not allowed in non-strict mode
diff --git a/test/message/syntactic-tail-call-without-return.js b/test/message/syntactic-tail-call-without-return.js
new file mode 100644
index 0000000..130f67d
--- /dev/null
+++ b/test/message/syntactic-tail-call-without-return.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-explicit-tailcalls
+"use strict";
+
+function f() {
+  return 1;
+}
+
+function g() {
+  var x =  continue  f()  ;
+}
diff --git a/test/message/syntactic-tail-call-without-return.out b/test/message/syntactic-tail-call-without-return.out
new file mode 100644
index 0000000..0508fc3
--- /dev/null
+++ b/test/message/syntactic-tail-call-without-return.out
@@ -0,0 +1,4 @@
+*%(basename)s:13: SyntaxError: Tail call expression is not allowed here
+  var x =  continue  f()  ;
+           ^^^^^^^^^^^^^
+SyntaxError: Tail call expression is not allowed here
diff --git a/test/mjsunit/arguments.js b/test/mjsunit/arguments.js
index 26eb389..97ec7cc 100644
--- a/test/mjsunit/arguments.js
+++ b/test/mjsunit/arguments.js
@@ -204,3 +204,70 @@
   }
   assertTrue(%HasSloppyArgumentsElements(a));
 })();
+
+(function testDeleteArguments() {
+  function f() { return arguments };
+  var args = f(1, 2);
+  assertEquals(1, args[0]);
+  assertEquals(2, args[1]);
+  assertEquals(2, args.length);
+
+  delete args[0];
+  assertEquals(undefined, args[0]);
+  assertEquals(2, args[1]);
+  assertEquals(2, args.length);
+
+  delete args[1];
+  assertEquals(undefined, args[0]);
+  assertEquals(undefined, args[1]);
+  assertEquals(2, args.length);
+})();
+
+(function testDeleteFastSloppyArguments() {
+  function f(a) { return arguments };
+  var args = f(1, 2);
+  assertEquals(1, args[0]);
+  assertEquals(2, args[1]);
+  assertEquals(2, args.length);
+
+  delete args[0];
+  assertEquals(undefined, args[0]);
+  assertEquals(2, args[1]);
+  assertEquals(2, args.length);
+
+  delete args[1];
+  assertEquals(undefined, args[0]);
+  assertEquals(undefined, args[1]);
+  assertEquals(2, args.length);
+})();
+
+(function testDeleteSlowSloppyArguments() {
+  var key = 10000;
+  function f(a) {
+    arguments[key] = key;
+    return arguments
+  };
+  var args = f(1, 2);
+  assertEquals(1, args[0]);
+  assertEquals(2, args[1]);
+  assertEquals(key, args[key]);
+  assertEquals(2, args.length);
+
+  delete args[0];
+  assertEquals(undefined, args[0]);
+  assertEquals(2, args[1]);
+  assertEquals(key, args[key]);
+  assertEquals(2, args.length);
+
+  delete args[1];
+  assertEquals(undefined, args[0]);
+  assertEquals(undefined, args[1]);
+  assertEquals(key, args[key]);
+  assertEquals(2, args.length);
+
+  delete args[key];
+  assertEquals(undefined, args[0]);
+  assertEquals(undefined, args[1]);
+  assertEquals(undefined, args[key]);
+  assertEquals(2, args.length);
+})();
diff --git a/test/mjsunit/array-push.js b/test/mjsunit/array-push.js
index c87fd12..ece3319 100644
--- a/test/mjsunit/array-push.js
+++ b/test/mjsunit/array-push.js
@@ -146,3 +146,16 @@
   f(a, {});
   assertEquals(10, a.f());
 })();
+
+
+(function testDoubleArrayPush() {
+  var a = [];
+  var max = 1000;
+  for (var i = 0; i < max; i++) {
+    a.push(i + 0.1);
+  }
+  assertEquals(max, a.length);
+  for (var i = 0; i < max; i++) {
+    assertEquals(i+0.1, a[i]);
+  }
+})();
diff --git a/test/mjsunit/array-push7.js b/test/mjsunit/array-push7.js
deleted file mode 100644
index 68c3a2a..0000000
--- a/test/mjsunit/array-push7.js
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-object-observe
-// Flags: --allow-natives-syntax
-
-var v = 0;
-
-function push_wrapper(array, value) {
-  array.push(value);
-}
-function pop_wrapper(array) {
-  return array.pop();
-}
-
-// Test that Object.observe() notification events are properly sent from
-// Array.push() and Array.pop() both from optimized and un-optimized code.
-var array = [];
-
-function somethingChanged(changes) {
-  v++;
-}
-
-Object.observe(array, somethingChanged);
-push_wrapper(array, 1);
-%RunMicrotasks();
-assertEquals(1, array.length);
-assertEquals(1, v);
-push_wrapper(array, 1);
-%RunMicrotasks();
-assertEquals(2, array.length);
-assertEquals(2, v);
-%OptimizeFunctionOnNextCall(push_wrapper);
-push_wrapper(array, 1);
-%RunMicrotasks();
-assertEquals(3, array.length);
-assertEquals(3, v);
-push_wrapper(array, 1);
-%RunMicrotasks();
-assertEquals(4, array.length);
-assertEquals(4, v);
-
-pop_wrapper(array);
-%RunMicrotasks();
-assertEquals(3, array.length);
-assertEquals(5, v);
-pop_wrapper(array);
-%RunMicrotasks();
-assertEquals(2, array.length);
-assertEquals(6, v);
-%OptimizeFunctionOnNextCall(pop_wrapper);
-pop_wrapper(array);
-%RunMicrotasks();
-assertEquals(1, array.length);
-assertEquals(7, v);
-pop_wrapper(array);
-%RunMicrotasks();
-assertEquals(0, array.length);
-assertEquals(8, v);
diff --git a/test/mjsunit/array-slice.js b/test/mjsunit/array-slice.js
index ae0e3bc..b017dd5 100644
--- a/test/mjsunit/array-slice.js
+++ b/test/mjsunit/array-slice.js
@@ -228,6 +228,7 @@
   func([]);
   func(['a'], 'a');
   func(['a', 1], 'a', 1);
+  func(['a', 1, 2, 3, 4, 5], 'a', 1, 2, 3, 4, 5);
   func(['a', 1, undefined], 'a', 1, undefined);
   func(['a', 1, undefined, void(0)], 'a', 1, undefined, void(0));
 })();
diff --git a/test/mjsunit/array-sort.js b/test/mjsunit/array-sort.js
index ae9f6ef..fdd2333 100644
--- a/test/mjsunit/array-sort.js
+++ b/test/mjsunit/array-sort.js
@@ -479,3 +479,68 @@
   }
 }
 TestSortOnProxy();
+
+
+// Test special prototypes
+(function testSortSpecialPrototypes() {
+  function test(proto, length, expected) {
+    var result = {
+       length: length,
+       __proto__: proto,
+     };
+    Array.prototype.sort.call(result);
+    assertEquals(expected.length, result.length, "result.length");
+    for (var i = 0; i<expected.length; i++) {
+      assertEquals(expected[i], result[i], "result["+i+"]");
+    }
+  }
+
+  (function fast() {
+    // Fast elements, non-empty
+    test(arguments, 0, []);
+    test(arguments, 1, [2]);
+    test(arguments, 2, [1, 2]);
+    test(arguments, 4, [1, 2, 3, 4]);
+    delete arguments[0]
+    // sort copies down the properties to the receiver, hence result[1]
+    // is read on the arguments through the hole on the receiver.
+    test(arguments, 2, [1, 1]);
+    arguments[0] = undefined;
+    test(arguments, 2, [1, undefined]);
+  })(2, 1, 4, 3);
+
+  (function fastSloppy(a) {
+    // Fast sloppy
+    test(arguments, 0, []);
+    test(arguments, 1, [2]);
+    test(arguments, 2, [1, 2]);
+    delete arguments[0]
+    test(arguments, 2, [1, 1]);
+    arguments[0] = undefined;
+    test(arguments, 2, [1, undefined]);
+  })(2, 1);
+
+  (function fastEmpty() {
+    test(arguments, 0, []);
+    test(arguments, 1, [undefined]);
+    test(arguments, 2, [undefined, undefined]);
+  })();
+
+  (function stringWrapper() {
+    // cannot redefine string wrapper properties
+    assertThrows(() => test(new String('cba'), 3, []), TypeError);
+  })();
+
+  (function typedArrys() {
+    test(new Int32Array(0), 0, []);
+    test(new Int32Array(1), 1, [0]);
+    var array = new Int32Array(3);
+    array[0] = 2;
+    array[1] = 1;
+    array[2] = 3;
+    test(array, 1, [2]);
+    test(array, 2, [1, 2]);
+    test(array, 3, [1, 2, 3]);
+  })()
+
+})();
diff --git a/test/mjsunit/array-splice.js b/test/mjsunit/array-splice.js
index 744e954..75ff2d1 100644
--- a/test/mjsunit/array-splice.js
+++ b/test/mjsunit/array-splice.js
@@ -300,6 +300,55 @@
   }
 })();
 
+// Check the behaviour when approaching maximal values for length.
+(function() {
+  for (var i = 0; i < 7; i++) {
+    try {
+      new Array(Math.pow(2, 32) - 3).splice(-1, 0, 1, 2, 3, 4, 5);
+      throw 'Should have thrown RangeError';
+    } catch (e) {
+      assertTrue(e instanceof RangeError);
+    }
+
+    // Check smi boundary
+    var bigNum = (1 << 30) - 3;
+    var array = new Array(bigNum);
+    array.splice(-1, 0, 1, 2, 3, 4, 5, 6, 7);
+    assertEquals(bigNum + 7, array.length);
+  }
+})();
+
+(function() {
+  for (var i = 0; i < 7; i++) {
+    var a = [7, 8, 9];
+    a.splice(0, 0, 1, 2, 3, 4, 5, 6);
+    assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a);
+    assertFalse(a.hasOwnProperty(10), "a.hasOwnProperty(10)");
+    assertEquals(undefined, a[10]);
+  }
+})();
+
+(function testSpliceDeleteDouble() {
+  var a = [1.1, 1.2, 1.3, 1.4];
+  a.splice(2, 1)
+  assertEquals([1.1, 1.2, 1.4], a);
+})();
+
+// Past this point the ArrayProtector is invalidated since we modify the
+// Array.prototype.
+
+// Check the case of JS builtin .splice()
+(function() {
+  for (var i = 0; i < 7; i++) {
+    var array = [1, 2, 3, 4];
+    Array.prototype[3] = 'foo';  // To force JS builtin.
+
+    var spliced = array.splice();
+
+    assertEquals([], spliced);
+    assertEquals([1, 2, 3, 4], array);
+  }
+})();
 
 // Now check the case with array of holes and some elements on prototype.
 (function() {
@@ -350,7 +399,6 @@
   }
 })();
 
-
 // Now check the case with array of holes and some elements on prototype.
 (function() {
   var len = 9;
@@ -397,46 +445,3 @@
                 "array.hasOwnProperty(Math.pow(2, 32) - 2)");
   }
 })();
-
-
-// Check the case of JS builtin .splice()
-(function() {
-  for (var i = 0; i < 7; i++) {
-    var array = [1, 2, 3, 4];
-    Array.prototype[3] = 'foo';  // To force JS builtin.
-
-    var spliced = array.splice();
-
-    assertEquals([], spliced);
-    assertEquals([1, 2, 3, 4], array);
-  }
-})();
-
-
-// Check the behaviour when approaching maximal values for length.
-(function() {
-  for (var i = 0; i < 7; i++) {
-    try {
-      new Array(Math.pow(2, 32) - 3).splice(-1, 0, 1, 2, 3, 4, 5);
-      throw 'Should have thrown RangeError';
-    } catch (e) {
-      assertTrue(e instanceof RangeError);
-    }
-
-    // Check smi boundary
-    var bigNum = (1 << 30) - 3;
-    var array = new Array(bigNum);
-    array.splice(-1, 0, 1, 2, 3, 4, 5, 6, 7);
-    assertEquals(bigNum + 7, array.length);
-  }
-})();
-
-(function() {
-  for (var i = 0; i < 7; i++) {
-    var a = [7, 8, 9];
-    a.splice(0, 0, 1, 2, 3, 4, 5, 6);
-    assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a);
-    assertFalse(a.hasOwnProperty(10), "a.hasOwnProperty(10)");
-    assertEquals(undefined, a[10]);
-  }
-})();
diff --git a/test/mjsunit/asm/construct-double.js b/test/mjsunit/asm/construct-double.js
deleted file mode 100644
index 8bb5000..0000000
--- a/test/mjsunit/asm/construct-double.js
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --allow-natives-syntax
-
-var stdlib = this;
-var foreign = {};
-var heap = new ArrayBuffer(64 * 1024);
-
-
-var m = (function(stdlib, foreign, heap) {
-  "use asm";
-  function cd1(i, j) {
-    i = i|0;
-    j = j|0;
-    return +%_ConstructDouble(i, j);
-  }
-  function cd2(i) {
-    i = i|0;
-    return +%_ConstructDouble(0, i);
-  }
-  return { cd1: cd1, cd2: cd2 };
-})(stdlib, foreign, heap);
-
-assertEquals(0.0, m.cd1(0, 0));
-assertEquals(%ConstructDouble(0, 1), m.cd2(1));
-for (var i = -2147483648; i < 2147483648; i += 3999773) {
-  assertEquals(%ConstructDouble(0, i), m.cd2(i));
-  for (var j = -2147483648; j < 2147483648; j += 3999773) {
-    assertEquals(%ConstructDouble(i, j), m.cd1(i, j));
-  }
-}
diff --git a/test/mjsunit/compiler/dont-constant-fold-deopting-checks.js b/test/mjsunit/compiler/dont-constant-fold-deopting-checks.js
new file mode 100644
index 0000000..02bd8d9
--- /dev/null
+++ b/test/mjsunit/compiler/dont-constant-fold-deopting-checks.js
@@ -0,0 +1,10 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function bar(a) { a[0](true); }
+function foo(a) { return bar(1); }
+%OptimizeFunctionOnNextCall(foo);
+assertThrows(function() {bar([foo])}, TypeError);
diff --git a/test/mjsunit/compiler/escape-analysis-1.js b/test/mjsunit/compiler/escape-analysis-1.js
index b8c6644..f05040b 100644
--- a/test/mjsunit/compiler/escape-analysis-1.js
+++ b/test/mjsunit/compiler/escape-analysis-1.js
@@ -26,7 +26,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --allow-natives-syntax --turbo-escape
-//
 
 function f(a) {
   "use strict";
diff --git a/test/mjsunit/compiler/escape-analysis-10.js b/test/mjsunit/compiler/escape-analysis-10.js
index c53cf4d..4f06d57 100644
--- a/test/mjsunit/compiler/escape-analysis-10.js
+++ b/test/mjsunit/compiler/escape-analysis-10.js
@@ -26,6 +26,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --allow-natives-syntax --turbo-escape
+
 (function() {
   "use strict";
   function f() {
diff --git a/test/mjsunit/compiler/escape-analysis-2.js b/test/mjsunit/compiler/escape-analysis-2.js
index d116e9a..49f440e 100644
--- a/test/mjsunit/compiler/escape-analysis-2.js
+++ b/test/mjsunit/compiler/escape-analysis-2.js
@@ -26,7 +26,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --allow-natives-syntax --turbo-escape
-//
 
 function f(a) {
   "use strict";
diff --git a/test/mjsunit/compiler/escape-analysis-3.js b/test/mjsunit/compiler/escape-analysis-3.js
index d1ebc9b..b92d1c3 100644
--- a/test/mjsunit/compiler/escape-analysis-3.js
+++ b/test/mjsunit/compiler/escape-analysis-3.js
@@ -26,7 +26,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --allow-natives-syntax --turbo-escape
-//
 
 function f(a) {
   "use strict";
diff --git a/test/mjsunit/compiler/escape-analysis-4.js b/test/mjsunit/compiler/escape-analysis-4.js
index d9fdccc..ef9f95f 100644
--- a/test/mjsunit/compiler/escape-analysis-4.js
+++ b/test/mjsunit/compiler/escape-analysis-4.js
@@ -26,7 +26,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --allow-natives-syntax --turbo-escape
-//
 
 function f(a) {
   "use strict";
diff --git a/test/mjsunit/compiler/escape-analysis-5.js b/test/mjsunit/compiler/escape-analysis-5.js
index cfaf81d..54b5e82 100644
--- a/test/mjsunit/compiler/escape-analysis-5.js
+++ b/test/mjsunit/compiler/escape-analysis-5.js
@@ -26,7 +26,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --allow-natives-syntax --turbo-escape
-//
 
 function f(h) {
   "use strict";
diff --git a/test/mjsunit/compiler/escape-analysis-6.js b/test/mjsunit/compiler/escape-analysis-6.js
index 6143cfb..c36e7d9 100644
--- a/test/mjsunit/compiler/escape-analysis-6.js
+++ b/test/mjsunit/compiler/escape-analysis-6.js
@@ -26,7 +26,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --allow-natives-syntax --turbo-escape
-//
 
 function f(a) {
   "use strict";
diff --git a/test/mjsunit/compiler/escape-analysis-7.js b/test/mjsunit/compiler/escape-analysis-7.js
index 16bc71c..cfa30cb 100644
--- a/test/mjsunit/compiler/escape-analysis-7.js
+++ b/test/mjsunit/compiler/escape-analysis-7.js
@@ -26,7 +26,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --allow-natives-syntax --turbo-escape
-//
 
 function f() {
   this.x=0;
diff --git a/test/mjsunit/compiler/escape-analysis-8.js b/test/mjsunit/compiler/escape-analysis-8.js
index bc5b1d9..d9c6d25 100644
--- a/test/mjsunit/compiler/escape-analysis-8.js
+++ b/test/mjsunit/compiler/escape-analysis-8.js
@@ -26,7 +26,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --allow-natives-syntax --turbo-escape
-//
 
 function f(a) {
   this.x=a;
diff --git a/test/mjsunit/compiler/escape-analysis-9.js b/test/mjsunit/compiler/escape-analysis-9.js
index a19786b..0b8f75c 100644
--- a/test/mjsunit/compiler/escape-analysis-9.js
+++ b/test/mjsunit/compiler/escape-analysis-9.js
@@ -26,7 +26,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Flags: --allow-natives-syntax --turbo-escape
-//
 
 function f() {
   return arguments;
diff --git a/test/mjsunit/compiler/inline-dead-jscreate.js b/test/mjsunit/compiler/inline-dead-jscreate.js
new file mode 100644
index 0000000..a977875
--- /dev/null
+++ b/test/mjsunit/compiler/inline-dead-jscreate.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var bar = 0;
+
+function baz() { return this; }
+
+function foo() {
+  bar += 1;
+  if (bar === 2) throw new baz();
+}
+
+foo();
diff --git a/test/mjsunit/compiler/optimized-float32array-length.js b/test/mjsunit/compiler/optimized-float32array-length.js
new file mode 100644
index 0000000..eed8922
--- /dev/null
+++ b/test/mjsunit/compiler/optimized-float32array-length.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+var a = new Float32Array(1);
+function len(a) { return a.length; }
+assertEquals(1, len(a));
+assertEquals(1, len(a));
+%OptimizeFunctionOnNextCall(len);
+assertEquals(1, len(a));
+assertOptimized(len);
diff --git a/test/mjsunit/compiler/optimized-float64array-length.js b/test/mjsunit/compiler/optimized-float64array-length.js
new file mode 100644
index 0000000..f6a3d77
--- /dev/null
+++ b/test/mjsunit/compiler/optimized-float64array-length.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+var a = new Float64Array(1);
+function len(a) { return a.length; }
+assertEquals(1, len(a));
+assertEquals(1, len(a));
+%OptimizeFunctionOnNextCall(len);
+assertEquals(1, len(a));
+assertOptimized(len);
diff --git a/test/mjsunit/compiler/optimized-instanceof-1.js b/test/mjsunit/compiler/optimized-instanceof-1.js
new file mode 100644
index 0000000..242b4be
--- /dev/null
+++ b/test/mjsunit/compiler/optimized-instanceof-1.js
@@ -0,0 +1,17 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function F() {}
+var f = new F
+
+var proto = Object.getPrototypeOf(F);
+Object.setPrototypeOf(F, null);
+F[Symbol.hasInstance] = function(v) { return true };
+Object.setPrototypeOf(F, proto);
+
+function foo(x) { return x instanceof F };
+%OptimizeFunctionOnNextCall(foo);
+assertTrue(foo(1));
diff --git a/test/mjsunit/compiler/optimized-instanceof-2.js b/test/mjsunit/compiler/optimized-instanceof-2.js
new file mode 100644
index 0000000..38a35b7
--- /dev/null
+++ b/test/mjsunit/compiler/optimized-instanceof-2.js
@@ -0,0 +1,19 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function F() {}
+var f = new F
+
+function foo(x) { return x instanceof F };
+%OptimizeFunctionOnNextCall(foo);
+assertFalse(foo(1));
+
+var proto = Object.getPrototypeOf(F);
+Object.setPrototypeOf(F, null);
+F[Symbol.hasInstance] = function(v) { return true };
+Object.setPrototypeOf(F, proto);
+
+assertTrue(foo(1));
diff --git a/test/mjsunit/compiler/optimized-int32array-length.js b/test/mjsunit/compiler/optimized-int32array-length.js
new file mode 100644
index 0000000..250d523
--- /dev/null
+++ b/test/mjsunit/compiler/optimized-int32array-length.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+var a = new Int32Array(1);
+function len(a) { return a.length; }
+assertEquals(1, len(a));
+assertEquals(1, len(a));
+%OptimizeFunctionOnNextCall(len);
+assertEquals(1, len(a));
+assertOptimized(len);
diff --git a/test/mjsunit/compiler/optimized-uint32array-length.js b/test/mjsunit/compiler/optimized-uint32array-length.js
new file mode 100644
index 0000000..d389370
--- /dev/null
+++ b/test/mjsunit/compiler/optimized-uint32array-length.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+var a = new Uint32Array(1);
+function len(a) { return a.length; }
+assertEquals(1, len(a));
+assertEquals(1, len(a));
+%OptimizeFunctionOnNextCall(len);
+assertEquals(1, len(a));
+assertOptimized(len);
diff --git a/test/mjsunit/compiler/osr-alignment.js b/test/mjsunit/compiler/osr-alignment.js
index 085d6c4..f815e71 100644
--- a/test/mjsunit/compiler/osr-alignment.js
+++ b/test/mjsunit/compiler/osr-alignment.js
@@ -25,7 +25,7 @@
 // (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 --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 function f1() {
   var sum = 0;
diff --git a/test/mjsunit/compiler/osr-backedges1.js b/test/mjsunit/compiler/osr-backedges1.js
index d415f4a..18a7e04 100644
--- a/test/mjsunit/compiler/osr-backedges1.js
+++ b/test/mjsunit/compiler/osr-backedges1.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 function foo(a) {
   var i = a | 0;
diff --git a/test/mjsunit/compiler/osr-block-scope-func.js b/test/mjsunit/compiler/osr-block-scope-func.js
index df4076c..7c41f54 100644
--- a/test/mjsunit/compiler/osr-block-scope-func.js
+++ b/test/mjsunit/compiler/osr-block-scope-func.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 "use strict";
 
diff --git a/test/mjsunit/compiler/osr-block-scope-id.js b/test/mjsunit/compiler/osr-block-scope-id.js
index 923c72f..bcc7cdd 100644
--- a/test/mjsunit/compiler/osr-block-scope-id.js
+++ b/test/mjsunit/compiler/osr-block-scope-id.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 "use strict";
 
diff --git a/test/mjsunit/compiler/osr-block-scope.js b/test/mjsunit/compiler/osr-block-scope.js
index 0d78cdc..c60f8af 100644
--- a/test/mjsunit/compiler/osr-block-scope.js
+++ b/test/mjsunit/compiler/osr-block-scope.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 "use strict";
 
diff --git a/test/mjsunit/compiler/osr-follow.js b/test/mjsunit/compiler/osr-follow.js
index b6a2e8e..46581a8 100644
--- a/test/mjsunit/compiler/osr-follow.js
+++ b/test/mjsunit/compiler/osr-follow.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --use-osr --turbo-osr
+// Flags: --use-osr
 
 function foo(a) {
   var sum = 0;
diff --git a/test/mjsunit/compiler/osr-for-let.js b/test/mjsunit/compiler/osr-for-let.js
index 4b2fa3e..b8cef78 100644
--- a/test/mjsunit/compiler/osr-for-let.js
+++ b/test/mjsunit/compiler/osr-for-let.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 "use strict";
 
diff --git a/test/mjsunit/compiler/osr-forin-nested.js b/test/mjsunit/compiler/osr-forin-nested.js
index ad55b30..dd81089 100644
--- a/test/mjsunit/compiler/osr-forin-nested.js
+++ b/test/mjsunit/compiler/osr-forin-nested.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --turbo-osr --allow-natives-syntax
+// Flags: --allow-natives-syntax
 
 function test(e, f, v) {
   assertEquals(e, f(v));
diff --git a/test/mjsunit/compiler/osr-forin.js b/test/mjsunit/compiler/osr-forin.js
index 8d16782..b45d200 100644
--- a/test/mjsunit/compiler/osr-forin.js
+++ b/test/mjsunit/compiler/osr-forin.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --use-osr --turbo-osr
+// Flags: --use-osr
 
 function f(a) {
   var sum = 0;
diff --git a/test/mjsunit/compiler/osr-forof.js b/test/mjsunit/compiler/osr-forof.js
index 36bff09..ce7b24d 100644
--- a/test/mjsunit/compiler/osr-forof.js
+++ b/test/mjsunit/compiler/osr-forof.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --use-osr --turbo-osr
+// Flags: --use-osr
 
 function f(a) {
   var sum = 0;
diff --git a/test/mjsunit/compiler/osr-function-id.js b/test/mjsunit/compiler/osr-function-id.js
index c506ae8..8761e85 100644
--- a/test/mjsunit/compiler/osr-function-id.js
+++ b/test/mjsunit/compiler/osr-function-id.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --use-osr --turbo-osr
+// Flags: --use-osr
 
 function id(f) { return f; }
 
diff --git a/test/mjsunit/compiler/osr-function-id2.js b/test/mjsunit/compiler/osr-function-id2.js
index 561c62e..e25ec31 100644
--- a/test/mjsunit/compiler/osr-function-id2.js
+++ b/test/mjsunit/compiler/osr-function-id2.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --use-osr --turbo-osr
+// Flags: --use-osr
 
 function id(f) { return f; }
 
diff --git a/test/mjsunit/compiler/osr-function.js b/test/mjsunit/compiler/osr-function.js
index 06d137b..cee7e9d 100644
--- a/test/mjsunit/compiler/osr-function.js
+++ b/test/mjsunit/compiler/osr-function.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --use-osr --turbo-osr
+// Flags: --use-osr
 
 function foo() {
   var sum = 0;
diff --git a/test/mjsunit/compiler/osr-infinite.js b/test/mjsunit/compiler/osr-infinite.js
index aa74c87..9d0bb47 100644
--- a/test/mjsunit/compiler/osr-infinite.js
+++ b/test/mjsunit/compiler/osr-infinite.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --use-osr --allow-natives-syntax --turbo-osr
+// Flags: --use-osr --allow-natives-syntax
 
 var global_counter = 0;
 
diff --git a/test/mjsunit/compiler/osr-labeled.js b/test/mjsunit/compiler/osr-labeled.js
index 1a97092..1384e9a 100644
--- a/test/mjsunit/compiler/osr-labeled.js
+++ b/test/mjsunit/compiler/osr-labeled.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 function foo() {
   var sum = 0;
diff --git a/test/mjsunit/compiler/osr-literals-adapted.js b/test/mjsunit/compiler/osr-literals-adapted.js
index 950d8b0..4d1798c 100644
--- a/test/mjsunit/compiler/osr-literals-adapted.js
+++ b/test/mjsunit/compiler/osr-literals-adapted.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 function mod() {
   function f0() {
diff --git a/test/mjsunit/compiler/osr-literals.js b/test/mjsunit/compiler/osr-literals.js
index d9f68a0..f2051dc 100644
--- a/test/mjsunit/compiler/osr-literals.js
+++ b/test/mjsunit/compiler/osr-literals.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 function mod() {
   function f0() {
diff --git a/test/mjsunit/compiler/osr-manual1.js b/test/mjsunit/compiler/osr-manual1.js
index 29a4948..c3db796 100644
--- a/test/mjsunit/compiler/osr-manual1.js
+++ b/test/mjsunit/compiler/osr-manual1.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 var counter = 111;
 
diff --git a/test/mjsunit/compiler/osr-manual2.js b/test/mjsunit/compiler/osr-manual2.js
index 8aa5d69..de7ec24 100644
--- a/test/mjsunit/compiler/osr-manual2.js
+++ b/test/mjsunit/compiler/osr-manual2.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 var counter = 188;
 
diff --git a/test/mjsunit/compiler/osr-multiple.js b/test/mjsunit/compiler/osr-multiple.js
index c318645..72fff85 100644
--- a/test/mjsunit/compiler/osr-multiple.js
+++ b/test/mjsunit/compiler/osr-multiple.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --use-osr --turbo-osr
+// Flags: --use-osr
 
 function f1(a,b,c) {
   var x = 0;
diff --git a/test/mjsunit/compiler/osr-multiple2.js b/test/mjsunit/compiler/osr-multiple2.js
index 9a81bfb..edb627a 100644
--- a/test/mjsunit/compiler/osr-multiple2.js
+++ b/test/mjsunit/compiler/osr-multiple2.js
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 // Flags: --use-osr
-// TODO(titzer): enable --turbo-osr when nested OSR works.
 
 function f1(a,b,c) {
   var x = 0;
diff --git a/test/mjsunit/compiler/osr-multiple3.js b/test/mjsunit/compiler/osr-multiple3.js
index 0fb1ac7..fa703ea 100644
--- a/test/mjsunit/compiler/osr-multiple3.js
+++ b/test/mjsunit/compiler/osr-multiple3.js
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 // Flags: --use-osr
-// TODO(titzer): enable --turbo-osr when nested OSR works.
 
 function f1(a,b,c) {
   var x = 0;
diff --git a/test/mjsunit/compiler/osr-nested2.js b/test/mjsunit/compiler/osr-nested2.js
index 41bd9b2..efe31f1 100644
--- a/test/mjsunit/compiler/osr-nested2.js
+++ b/test/mjsunit/compiler/osr-nested2.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 function f() {
   var sum = 0;
diff --git a/test/mjsunit/compiler/osr-nested2b.js b/test/mjsunit/compiler/osr-nested2b.js
index e64c10c..1808811 100644
--- a/test/mjsunit/compiler/osr-nested2b.js
+++ b/test/mjsunit/compiler/osr-nested2b.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 function f() {
   var sum = 0;
diff --git a/test/mjsunit/compiler/osr-nested3.js b/test/mjsunit/compiler/osr-nested3.js
index f5d09ba..d7c144b 100644
--- a/test/mjsunit/compiler/osr-nested3.js
+++ b/test/mjsunit/compiler/osr-nested3.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 function f() {
   var sum = 0;
diff --git a/test/mjsunit/compiler/osr-nested3b.js b/test/mjsunit/compiler/osr-nested3b.js
index 32ac2a7..a10d328 100644
--- a/test/mjsunit/compiler/osr-nested3b.js
+++ b/test/mjsunit/compiler/osr-nested3b.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 function f() {
   var sum = 0;
diff --git a/test/mjsunit/compiler/osr-regex-id.js b/test/mjsunit/compiler/osr-regex-id.js
index 7831b14..e0b4dad 100644
--- a/test/mjsunit/compiler/osr-regex-id.js
+++ b/test/mjsunit/compiler/osr-regex-id.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 function id(f) { return f; }
 
diff --git a/test/mjsunit/compiler/osr-sar.js b/test/mjsunit/compiler/osr-sar.js
index cc04adc..02684f0 100644
--- a/test/mjsunit/compiler/osr-sar.js
+++ b/test/mjsunit/compiler/osr-sar.js
@@ -25,7 +25,7 @@
 // (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 --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 function test() {
   // Loop to force OSR.
diff --git a/test/mjsunit/compiler/osr-warm.js b/test/mjsunit/compiler/osr-warm.js
index 7c30c07..73e1fd5 100644
--- a/test/mjsunit/compiler/osr-warm.js
+++ b/test/mjsunit/compiler/osr-warm.js
@@ -25,7 +25,7 @@
 // (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: --use-osr --turbo-osr
+// Flags: --use-osr
 
 function f1(x) {
   while (x > 0) {
diff --git a/test/mjsunit/compiler/osr-while-let.js b/test/mjsunit/compiler/osr-while-let.js
index c19cf6c..11ebc4b 100644
--- a/test/mjsunit/compiler/osr-while-let.js
+++ b/test/mjsunit/compiler/osr-while-let.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr
+// Flags: --allow-natives-syntax --use-osr
 
 "use strict";
 
diff --git a/test/mjsunit/compiler/regress-5074.js b/test/mjsunit/compiler/regress-5074.js
new file mode 100644
index 0000000..903b54a
--- /dev/null
+++ b/test/mjsunit/compiler/regress-5074.js
@@ -0,0 +1,18 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+var s = [,0.1];
+
+function foo(a, b) {
+  var x = s[a];
+  s[1] = 0.1;
+  return x + b;
+}
+
+assertEquals(2.1, foo(1, 2));
+assertEquals(2.1, foo(1, 2));
+%OptimizeFunctionOnNextCall(foo);
+assertEquals("undefined2", foo(0, "2"));
diff --git a/test/mjsunit/compiler/regress-5100.js b/test/mjsunit/compiler/regress-5100.js
new file mode 100644
index 0000000..694cd8a
--- /dev/null
+++ b/test/mjsunit/compiler/regress-5100.js
@@ -0,0 +1,51 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+var a = [0, 1];
+a["true"] = "true";
+a["false"] = "false";
+a["null"] = "null";
+a["undefined"] = "undefined";
+
+// Ensure we don't accidentially truncate true when used to index arrays.
+(function() {
+  function f(x) { return a[x]; }
+
+  assertEquals(0, f(0));
+  assertEquals(0, f(0));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals("true", f(true));
+})();
+
+// Ensure we don't accidentially truncate false when used to index arrays.
+(function() {
+  function f( x) { return a[x]; }
+
+  assertEquals(0, f(0));
+  assertEquals(0, f(0));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals("false", f(false));
+})();
+
+// Ensure we don't accidentially truncate null when used to index arrays.
+(function() {
+  function f( x) { return a[x]; }
+
+  assertEquals(0, f(0));
+  assertEquals(0, f(0));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals("null", f(null));
+})();
+
+// Ensure we don't accidentially truncate undefined when used to index arrays.
+(function() {
+  function f( x) { return a[x]; }
+
+  assertEquals(0, f(0));
+  assertEquals(0, f(0));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals("undefined", f(undefined));
+})();
diff --git a/test/mjsunit/compiler/regress-5129.js b/test/mjsunit/compiler/regress-5129.js
new file mode 100644
index 0000000..1d100ab
--- /dev/null
+++ b/test/mjsunit/compiler/regress-5129.js
@@ -0,0 +1,15 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function foo($a,$b) {
+ $a = $a|0;
+ $b = $b|0;
+ var $sub = $a - $b;
+ return ($sub|0) < 0;
+}
+
+%OptimizeFunctionOnNextCall(foo);
+assertTrue(foo(0x7fffffff,-1));
diff --git a/test/mjsunit/compiler/regress-607493.js b/test/mjsunit/compiler/regress-607493.js
new file mode 100644
index 0000000..540b47e
--- /dev/null
+++ b/test/mjsunit/compiler/regress-607493.js
@@ -0,0 +1,37 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+(function ForInTryCatchContrinueOsr() {
+  var a = [1];
+
+  function g() {
+    for (var x in a) {
+      try {
+        for (var i = 0; i < 10; i++) { %OptimizeOsr(); }
+        return;
+      } catch(e) {
+        continue;
+      }
+    }
+  }
+
+  g();
+})();
+
+(function ForInContinueNestedOsr() {
+  var a = [1];
+
+  function g() {
+    for (var x in a) {
+      if (x) {
+        for (var i = 0; i < 10; i++) { %OptimizeOsr(); }
+      }
+      continue;
+    }
+  }
+
+  g();
+})();
diff --git a/test/mjsunit/compiler/regress-621147.js b/test/mjsunit/compiler/regress-621147.js
new file mode 100644
index 0000000..0a5a221
--- /dev/null
+++ b/test/mjsunit/compiler/regress-621147.js
@@ -0,0 +1,29 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --turbo-filter=test2
+
+function test(n) {
+  return Array(n);
+}
+
+function test2() {
+  return test(2);
+}
+
+function test3(a) {
+  a[0] = 1;
+}
+
+test(0);
+
+var smi_array = [1,2];
+smi_array[2] = 3;
+test3(smi_array);
+
+%OptimizeFunctionOnNextCall(test2);
+
+var broken_array = test2();
+test3(broken_array);
+1+broken_array[0];
diff --git a/test/mjsunit/compiler/regress-621423.js b/test/mjsunit/compiler/regress-621423.js
new file mode 100644
index 0000000..962176f
--- /dev/null
+++ b/test/mjsunit/compiler/regress-621423.js
@@ -0,0 +1,21 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+var a = [0, ""];
+a[0] = 0;
+
+function g(array) {
+  array[1] = undefined;
+}
+
+function f() {
+  g(function() {});
+  g(a);
+}
+
+f();
+%OptimizeFunctionOnNextCall(f);
+f();
diff --git a/test/mjsunit/compiler/regress-number-is-hole-nan.js b/test/mjsunit/compiler/regress-number-is-hole-nan.js
new file mode 100644
index 0000000..368c837
--- /dev/null
+++ b/test/mjsunit/compiler/regress-number-is-hole-nan.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+var a = [, 2.121736758e-314];
+
+function foo() { return a[1]; }
+
+assertEquals(2.121736758e-314, foo());
+assertEquals(2.121736758e-314, foo());
+%OptimizeFunctionOnNextCall(foo);
+assertEquals(2.121736758e-314, foo());
diff --git a/test/mjsunit/compiler/regress-store-holey-double-array.js b/test/mjsunit/compiler/regress-store-holey-double-array.js
new file mode 100644
index 0000000..8123198
--- /dev/null
+++ b/test/mjsunit/compiler/regress-store-holey-double-array.js
@@ -0,0 +1,43 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+(function StoreHoleBitPattern() {
+  function g(src, dst, i) {
+    dst[i] = src[i];
+  }
+
+  var b = new ArrayBuffer(16);
+  var i32 = new Int32Array(b);
+  i32[0] = 0xFFF7FFFF;
+  i32[1] = 0xFFF7FFFF;
+  i32[3] = 0xFFF7FFFF;
+  i32[4] = 0xFFF7FFFF;
+  var f64 = new Float64Array(b);
+
+  var a = [,0.1];
+
+  g(f64, a, 1);
+  g(f64, a, 1);
+  %OptimizeFunctionOnNextCall(g);
+  g(f64, a, 0);
+
+  assertTrue(Number.isNaN(a[0]));
+})();
+
+
+(function ConvertHoleToNumberAndStore() {
+  function g(a, i) {
+    var x = a[i];
+    a[i] = +x;
+  }
+
+  var a=[,0.1];
+  g(a, 1);
+  g(a, 1);
+  %OptimizeFunctionOnNextCall(g);
+  g(a, 0);
+  assertTrue(Number.isNaN(a[0]));
+})();
diff --git a/test/mjsunit/compiler/regress-string-to-number-add.js b/test/mjsunit/compiler/regress-string-to-number-add.js
new file mode 100644
index 0000000..e872401
--- /dev/null
+++ b/test/mjsunit/compiler/regress-string-to-number-add.js
@@ -0,0 +1,15 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --turbo-type-feedback
+
+function f(x) {
+  var s = x ? "0" : "1";
+  return 1 + Number(s);
+}
+
+f(0);
+f(0);
+%OptimizeFunctionOnNextCall(f);
+assertEquals(2, f(0));
diff --git a/test/mjsunit/compiler/regress-truncate-number-or-undefined-to-float64.js b/test/mjsunit/compiler/regress-truncate-number-or-undefined-to-float64.js
new file mode 100644
index 0000000..1dc3042
--- /dev/null
+++ b/test/mjsunit/compiler/regress-truncate-number-or-undefined-to-float64.js
@@ -0,0 +1,19 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function g(a, b) {
+  a = +a;
+  if (b) {
+    a = undefined;
+  }
+  print(a);
+  return +a;
+}
+
+g(0);
+g(0);
+%OptimizeFunctionOnNextCall(g);
+assertTrue(Number.isNaN(g(0, true)));
diff --git a/test/mjsunit/compiler/try-osr.js b/test/mjsunit/compiler/try-osr.js
index e4eb8dd..c0ef27a 100644
--- a/test/mjsunit/compiler/try-osr.js
+++ b/test/mjsunit/compiler/try-osr.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --turbo-osr
+// Flags: --allow-natives-syntax
 
 function OSRInsideTry(x) {
   try {
diff --git a/test/mjsunit/compiler/turbo-number-feedback.js b/test/mjsunit/compiler/turbo-number-feedback.js
new file mode 100644
index 0000000..059a0ca
--- /dev/null
+++ b/test/mjsunit/compiler/turbo-number-feedback.js
@@ -0,0 +1,58 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --turbo-type-feedback
+
+(function AddSubtractSmis() {
+  function f0(a, b, c) {
+    return a + b - c;
+  }
+
+  assertEquals(4, f0(3, 2, 1));
+  assertEquals(4, f0(3, 2, 1));
+  %OptimizeFunctionOnNextCall(f0);
+  assertEquals(4, f0(3, 2, 1));
+})();
+
+(function AddSubtractDoubles() {
+  function f1(a, b, c) {
+    return a + b - c;
+  }
+
+  assertEquals(4.5, f1(3.5, 2.5, 1.5));
+  assertEquals(4.5, f1(3.5, 2.5, 1.5));
+  %OptimizeFunctionOnNextCall(f1);
+  assertEquals(4.5, f1(3.5, 2.5, 1.5));
+  assertEquals(4, f1(3, 2, 1));
+  assertTrue(isNaN(f1(3, 2, undefined)));
+  assertTrue(isNaN(f1(3, undefined, 1)));
+})();
+
+(function CheckUint32ToInt32Conv() {
+  function f2(a) {
+    return (a >>> 0) + 1;
+  }
+
+  assertEquals(1, f2(0));
+  assertEquals(1, f2(0));
+  %OptimizeFunctionOnNextCall(f2);
+  assertEquals(1, f2(0));
+  assertEquals(4294967295, f2(-2));
+})();
+
+(function CheckFloat64ToInt32Conv() {
+  function f3(a, b) {
+    var x = 0;
+    if (a) {
+      x = 0.5;
+    }
+    return x + b;
+  }
+
+  assertEquals(1, f3(0, 1));
+  assertEquals(1, f3(0, 1));
+  %OptimizeFunctionOnNextCall(f3);
+  assertEquals(1, f3(0, 1));
+  assertEquals(1.5, f3(1, 1));
+})();
diff --git a/test/mjsunit/debug-allscopes-on-debugger.js b/test/mjsunit/debug-allscopes-on-debugger.js
index b7a8dff..17668cf 100644
--- a/test/mjsunit/debug-allscopes-on-debugger.js
+++ b/test/mjsunit/debug-allscopes-on-debugger.js
@@ -49,10 +49,11 @@
   var i = 0; // Break 1.
   i++; // Break 2.
   i++; // Break 3.
-  return i; // Break 4.
-}()); // Break 5.
+  debugger;  // Break 4.
+  return i; // Break 5.
+}()); // Break 6.
 
-assertNull(exception); // Break 6.
+assertNull(exception); // Break 7.
 assertEquals(expected_breaks, break_count);
 
 Debug.setListener(null);
diff --git a/test/mjsunit/debug-backtrace-text.js b/test/mjsunit/debug-backtrace-text.js
index 61648fa..cfc89e6 100644
--- a/test/mjsunit/debug-backtrace-text.js
+++ b/test/mjsunit/debug-backtrace-text.js
@@ -35,7 +35,8 @@
 
 Point.prototype.distanceTo = function(p) {
   debugger;
-  return Math.sqrt(Math.pow(Math.abs(this.x - p.x), 2) + Math.pow(Math.abs(this.y - p.y), 2))
+  return Math.sqrt(Math.pow(Math.abs(this.x - p.x), 2) +
+         Math.pow(Math.abs(this.y - p.y), 2))
 }
 
 p1 = new Point(1,1);
@@ -58,7 +59,7 @@
 // Get the Debug object exposed from the debug context global object.
 Debug = debug.Debug
 
-testConstructor = false;  // Flag to control which part of the test is run.
+what = 'constructor';  // Flag to control which part of the test is run.
 listenerCalled = false;
 exception = false;
 
@@ -72,30 +73,47 @@
 
 function listener(event, exec_state, event_data, data) {
   try {
-  if (event == Debug.DebugEvent.Break)
-  {
-    if (!testConstructor) {
-      // The expected backtrace is
-      // 0: Call distance on Point where distance is a property on the prototype
-      // 1: Call distance on Point where distance is a direct property
-      // 2: Call on function an array element 2
-      // 3: [anonymous]
-      assertEquals("#<Point>.distanceTo(p=#<Point>)", exec_state.frame(0).invocationText());
-      assertEquals("#<Point>.distanceTo(p=#<Point>)", exec_state.frame(1).invocationText());
-      assertEquals("#<Array>[2](aka distance)(p=#<Point>, q=#<Point>)", exec_state.frame(2).invocationText());
-      assertEquals("[anonymous]()", exec_state.frame(3).invocationText());
-      listenerCalled = true;
-    } else {
-      // The expected backtrace is
-      // 0: Call Point constructor
-      // 1: Call on global function createPoint
-      // 2: [anonymous]
-      assertEquals("new Point(x=0, y=0)", exec_state.frame(0).invocationText());
-      assertEquals("createPoint(x=0, y=0)", exec_state.frame(1).invocationText());
-      assertEquals("[anonymous]()", exec_state.frame(2).invocationText());
-      listenerCalled = true;
+    if (event == Debug.DebugEvent.Break) {
+      if (what == 'constructor') {
+        // The expected backtrace is
+        // 0: Call distance on Point where distance is a prototype property
+        // 1: Call distance on Point where distance is a direct property
+        // 2: Call on function an array element 2
+        // 3: [anonymous]
+        assertEquals("#<Point>.distanceTo(p=#<Point>)",
+                     exec_state.frame(0).invocationText());
+        assertEquals("#<Point>.distanceTo(p=#<Point>)",
+                     exec_state.frame(1).invocationText());
+        assertEquals("#<Array>[2](aka distance)(p=#<Point>, q=#<Point>)",
+                     exec_state.frame(2).invocationText());
+        assertEquals("[anonymous]()", exec_state.frame(3).invocationText());
+        listenerCalled = true;
+      } else if (what == 'breakpoint') {
+        // The expected backtrace is
+        // 0: Call Point constructor
+        // 1: Call on global function createPoint
+        // 2: [anonymous]
+        assertEquals("new Point(x=0, y=0)",
+                     exec_state.frame(0).invocationText());
+        assertEquals("createPoint(x=0, y=0)",
+                     exec_state.frame(1).invocationText());
+        assertEquals("[anonymous]()", exec_state.frame(2).invocationText());
+        listenerCalled = true;
+      } else if (what == 'symbol') {
+        // The expected backtrace is
+        // 0: Call Point constructor
+        // 1: Call on symbol method
+        // 2: [anonymous]
+        assertEquals("new Point(x=0, y=0)",
+                     exec_state.frame(0).invocationText());
+        assertEquals("#<Object>[Symbol(Das Symbol)](x=0, y=0)",
+                     exec_state.frame(1).invocationText());
+        assertEquals("[anonymous]()", exec_state.frame(2).invocationText());
+        listenerCalled = true;
+      } else {
+        assertUnreachable();
+      }
     }
-  }
   } catch (e) {
     exception = e
   };
@@ -112,11 +130,21 @@
 assertFalse(exception, "exception in listener")
 
 // Set a break point and call to invoke the debug event listener.
+what = 'breakpoint';
 listenerCalled = false;
-testConstructor = true;
 Debug.setBreakPoint(Point, 0, 0);
 createPoint(0, 0);
 
 // Make sure that the debug event listener vas invoked (again).
 assertTrue(listenerCalled);
 assertFalse(exception, "exception in listener")
+
+what = 'symbol';
+listenerCalled = false;
+var S = Symbol('Das Symbol');
+var o = { [S](x, y) { return new Point(x, y); } };
+Debug.setBreakPoint(Point, 0, 0);
+o[S](0, 0);
+
+assertTrue(listenerCalled);
+assertFalse(exception, "exception in listener")
diff --git a/test/mjsunit/debug-eval-scope.js b/test/mjsunit/debug-eval-scope.js
new file mode 100644
index 0000000..2b97bf6
--- /dev/null
+++ b/test/mjsunit/debug-eval-scope.js
@@ -0,0 +1,144 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --no-always-opt
+
+// Test that the (strict) eval scope is visible to the debugger.
+
+var Debug = debug.Debug;
+var exception = null;
+var delegate = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    delegate(exec_state);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+// Current function is the top-level eval.
+// We can access stack- and context-allocated values in the eval-scope.
+delegate = function(exec_state) {
+  assertEquals([ debug.ScopeType.Eval,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(0).allScopes().map(s => s.scopeType()));
+  var scope = exec_state.frame(0).scope(0);
+  assertEquals(1, scope.scopeObject().property("a").value().value());
+  assertEquals(1, exec_state.frame(0).evaluate("a").value());
+  scope.setVariableValue("a", 2);
+  assertEquals(2, exec_state.frame(0).evaluate("a++").value());
+}
+
+eval("'use strict';      \n" +
+     "var a = 1;         \n" +
+     "debugger;          \n" +
+     "assertEquals(3, a);\n");
+
+eval("'use strict';      \n" +
+     "var a = 1;         \n" +
+     "(x=>a);            \n" +  // Force context-allocation.
+     "debugger;          \n" +
+     "assertEquals(3, a);\n");
+
+// Current function is an inner function.
+// We cannot access stack-allocated values in the eval-scope.
+delegate = function(exec_state) {
+  assertEquals([ debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(0).allScopes().map(s => s.scopeType()));
+  assertEquals([ debug.ScopeType.Eval,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(1).allScopes().map(s => s.scopeType()));
+  var scope = exec_state.frame(0).scope(0);
+  assertThrows(() => exec_state.frame(0).evaluate("a"), ReferenceError);
+  assertTrue(scope.scopeObject().property("a").isUndefined());
+}
+
+eval("'use strict';       \n" +
+     "var a = 1;          \n" +
+     "(() => {debugger})()\n");
+
+// Current function is an escaped inner function.
+delegate = function(exec_state) {
+  assertEquals([ debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(0).allScopes().map(s => s.scopeType()));
+  assertEquals([ debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(1).allScopes().map(s => s.scopeType()));
+  var scope = exec_state.frame(0).scope(0);
+  assertThrows(() => exec_state.frame(0).evaluate("a"), ReferenceError);
+  assertTrue(scope.scopeObject().property("a").isUndefined());
+}
+
+var f = eval("'use strict';   \n" +
+             "var a = 1;      \n" +
+             "() => {debugger}\n");
+f();
+
+// Current function is an inner function.
+// We can access context-allocated values in the eval-scope.
+delegate = function(exec_state) {
+  assertEquals([ debug.ScopeType.Local,
+                 debug.ScopeType.Closure,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(0).allScopes().map(s => s.scopeType()));
+  assertEquals([ debug.ScopeType.Eval,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(1).allScopes().map(s => s.scopeType()));
+  var scope = exec_state.frame(1).scope(0);
+  assertEquals(1, scope.scopeObject().property("a").value().value());
+  assertEquals(1, exec_state.frame(1).evaluate("a").value());
+  assertEquals(1, exec_state.frame(0).evaluate("a").value());
+  scope.setVariableValue("a", 2);
+  assertEquals(2, exec_state.frame(0).evaluate("a++").value());
+  assertEquals(3, exec_state.frame(1).evaluate("a++").value());
+}
+
+eval("'use strict';               \n" +
+     "var a = 1;                  \n" +
+     "(() => { a;                 \n" +  // Force context-allocation.
+     "         debugger;          \n" +
+     "         assertEquals(4, a);\n" +
+     "       })();                \n"
+     );
+
+// Current function is an escaped inner function.
+// We can access context-allocated values in the eval-scope.
+delegate = function(exec_state) {
+  assertEquals([ debug.ScopeType.Local,
+                 debug.ScopeType.Closure,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(0).allScopes().map(s => s.scopeType()));
+  assertEquals([ debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(1).allScopes().map(s => s.scopeType()));
+  var scope = exec_state.frame(0).scope(1);
+  assertEquals(1, scope.scopeObject().property("a").value().value());
+  assertEquals(1, exec_state.frame(0).evaluate("a").value());
+  scope.setVariableValue("a", 2);
+  assertEquals(2, exec_state.frame(0).evaluate("a++").value());
+}
+
+var g = eval("'use strict';              \n" +
+             "var a = 1;                 \n" +
+             "() => { a;                 \n" +
+             "        debugger;          \n" +
+             "        assertEquals(3, a);\n" +
+             "      }                    \n");
+g();
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/test/mjsunit/debug-evaluate-nested.js b/test/mjsunit/debug-evaluate-nested.js
index da11b90..965b5a7 100644
--- a/test/mjsunit/debug-evaluate-nested.js
+++ b/test/mjsunit/debug-evaluate-nested.js
@@ -34,7 +34,7 @@
       exec_state.frame(0).evaluate("debugger;");
     } else {
       checkScopes(exec_state.frame(0).allScopes(),
-                  [ ScopeType.With, ScopeType.Closure,
+                  [ ScopeType.Eval, ScopeType.With, ScopeType.Closure,
                     ScopeType.Script, ScopeType.Global ]);
     }
   } catch (e) {
diff --git a/test/mjsunit/debug-function-scopes.js b/test/mjsunit/debug-function-scopes.js
index f63d7b2..5509038 100644
--- a/test/mjsunit/debug-function-scopes.js
+++ b/test/mjsunit/debug-function-scopes.js
@@ -42,14 +42,7 @@
   }
 }
 
-// A copy of the scope types from debug/mirrors.js.
-var ScopeType = { Global: 0,
-                  Local: 1,
-                  With: 2,
-                  Closure: 3,
-                  Catch: 4,
-                  Block: 5,
-                  Script: 6};
+var ScopeType = debug.ScopeType;
 
 var f1 = (function F1(x) {
   function F2(y) {
diff --git a/test/mjsunit/debug-generator-break-on-stack.js b/test/mjsunit/debug-generator-break-on-stack.js
new file mode 100644
index 0000000..b743488
--- /dev/null
+++ b/test/mjsunit/debug-generator-break-on-stack.js
@@ -0,0 +1,46 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --ignition-generators
+
+var Debug = debug.Debug;
+
+var break_count = 0;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    break_count++;
+    var line = exec_state.frame(0).sourceLineText();
+    print(line);
+    assertTrue(line.indexOf(`B${break_count}`) > 0);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+
+function* g() {
+  setbreaks();
+  yield 1;  // B1
+}
+
+function* f() {
+  yield* g();
+  return 2;  // B2
+}
+
+function setbreaks() {
+  Debug.setListener(listener);
+  Debug.setBreakPoint(g, 2);
+  Debug.setBreakPoint(f, 2);
+}
+
+for (let _ of f()) { }
+
+assertEquals(2, break_count);
+assertNull(exception);
+
+Debug.setListener(null);
diff --git a/test/mjsunit/debug-generator-break.js b/test/mjsunit/debug-generator-break.js
new file mode 100644
index 0000000..4ab601b
--- /dev/null
+++ b/test/mjsunit/debug-generator-break.js
@@ -0,0 +1,44 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --ignition-generators
+
+var Debug = debug.Debug;
+
+var break_count = 0;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    break_count++;
+    var line = exec_state.frame(0).sourceLineText();
+    assertTrue(line.indexOf(`B${break_count}`) > 0);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+function* g() {
+  yield 1;
+}
+
+function* f() {
+  yield* g();                    // B1
+  assertEquals(2, break_count);  // B2
+  return 1;                      // B3
+}
+
+Debug.setBreakPoint(f, 1);
+Debug.setBreakPoint(f, 2);
+Debug.setBreakPoint(f, 3);
+
+for (let _ of f()) { }
+
+assertEquals(3, break_count);
+assertNull(exception);
+
+Debug.setListener(null);
diff --git a/test/mjsunit/debug-handle.js b/test/mjsunit/debug-handle.js
index 1582b9f..ca02592 100644
--- a/test/mjsunit/debug-handle.js
+++ b/test/mjsunit/debug-handle.js
@@ -108,7 +108,7 @@
     var handle_a = evaluateRequest(exec_state, '{"expression":"b","frame":1}');
     assertEquals(handle_o, handle_a);
     assertEquals(handle_a, handle_b);
-    assertFalse(handle_o == handle_p, "o and p have he same handle");
+    assertFalse(handle_o == handle_p, "o and p have the same handle");
 
     var response;
     var count;
@@ -140,7 +140,7 @@
     var handle_g = evaluateRequest(exec_state, '{"expression":"g"}');
     var handle_caller = evaluateRequest(exec_state, '{"expression":"f.caller"}');
 
-    assertFalse(handle_f == handle_g, "f and g have he same handle");
+    assertFalse(handle_f == handle_g, "f and g have the same handle");
     assertEquals(handle_g, handle_caller, "caller for f should be g");
 
     response = lookupRequest(exec_state, '{"handles":[' + handle_f + ']}', true);
diff --git a/test/mjsunit/debug-liveedit-exceptions.js b/test/mjsunit/debug-liveedit-exceptions.js
new file mode 100644
index 0000000..28ec01d
--- /dev/null
+++ b/test/mjsunit/debug-liveedit-exceptions.js
@@ -0,0 +1,67 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+Debug = debug.Debug
+
+function BestEditor() {
+  throw 'Emacs';
+}
+
+var exception = null;
+var results = [];
+var log = []
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Exception) return;
+  try {
+    var source_line = event_data.sourceLineText();
+    print(source_line);
+    log.push(source_line);
+    switch (results.length) {
+      case 0:
+        Replace(BestEditor, "Emacs", "Eclipse");
+        break;
+      case 1:
+        Replace(BestEditor, "Eclipse", "Vim");
+        break;
+      case 2:
+        break;
+      default:
+        assertUnreachable();
+    }
+  } catch (e) {
+    exception = e;
+  }
+};
+
+function Replace(fun, original, patch) {
+  var script = Debug.findScript(fun);
+  if (fun.toString().indexOf(original) < 0) return;
+  var patch_pos = script.source.indexOf(original);
+  var change_log = [];
+  Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, original.length, patch, change_log);
+}
+
+Debug.setListener(listener);
+Debug.setBreakOnException();
+
+for (var i = 0; i < 3; i++) {
+  try {
+    BestEditor();
+  } catch (e) {
+    results.push(e);
+  }
+}
+Debug.setListener(null);
+
+assertNull(exception);
+assertEquals(["Emacs", "Eclipse", "Vim"], results);
+print(JSON.stringify(log, 1));
+assertEquals([
+  "  throw 'Emacs';",
+  "  throw 'Eclipse';",
+  "  throw 'Vim';",
+], log);
diff --git a/test/mjsunit/debug-liveedit-stepin.js b/test/mjsunit/debug-liveedit-stepin.js
index 601a66f..c6070ce 100644
--- a/test/mjsunit/debug-liveedit-stepin.js
+++ b/test/mjsunit/debug-liveedit-stepin.js
@@ -7,8 +7,7 @@
 Debug = debug.Debug
 
 function BestEditor() {
-  var best_editor = "Emacs";
-  return best_editor;
+  return 'Emacs';
 }
 
 var exception = null;
@@ -62,20 +61,15 @@
 assertEquals([
   "debugger;",
   "results.push(BestEditor());",
-  "  var best_editor = \"Emacs\";",
-  "  return best_editor;","}",
+  "  return 'Emacs';","}",
   "results.push(BestEditor());",
   "results.push(BestEditor());",
-  "  var best_editor = \"Emacs\";",
-  "  return best_editor;",
-  "  var best_editor = \"Eclipse\";",
-  "  return best_editor;","}",
+  "  return 'Emacs';",
+  "  return 'Eclipse';","}",
   "results.push(BestEditor());",
   "results.push(BestEditor());",
-  "  var best_editor = \"Eclipse\";",
-  "  return best_editor;",
-  "  var best_editor = \"Vim\";",
-  "  return best_editor;",
+  "  return 'Eclipse';",
+  "  return 'Vim';",
   "}","results.push(BestEditor());",
   "Debug.setListener(null);"
 ], log);
diff --git a/test/mjsunit/debug-scopes.js b/test/mjsunit/debug-scopes.js
index 3659d4e..935de9c 100644
--- a/test/mjsunit/debug-scopes.js
+++ b/test/mjsunit/debug-scopes.js
@@ -183,10 +183,8 @@
   if (!scope.scopeObject().property('this').isUndefined()) {
     scope_size--;
   }
-  // Skip property with empty name.
-  if (!scope.scopeObject().property('').isUndefined()) {
-    scope_size--;
-  }
+  // Temporary variables introduced by the parser have not been materialized.
+  assertTrue(scope.scopeObject().property('').isUndefined());
 
   if (count != scope_size) {
     print('Names found in scope:');
@@ -1179,11 +1177,10 @@
 
 listener_delegate = function(exec_state) {
   CheckScopeChain([debug.ScopeType.Block,
-                   debug.ScopeType.Block,
                    debug.ScopeType.Local,
                    debug.ScopeType.Script,
                    debug.ScopeType.Global], exec_state);
-  CheckScopeChainPositions([{start: 52, end: 111}, {start: 42, end: 111}, {start: 22, end: 145}, {}, {}], exec_state);
+  CheckScopeChainPositions([{start: 52, end: 111}, {start: 22, end: 145}, {}, {}], exec_state);
 }
 eval(code3);
 EndTest();
diff --git a/test/mjsunit/debug-script.js b/test/mjsunit/debug-script.js
index 5396415..3bedb74 100644
--- a/test/mjsunit/debug-script.js
+++ b/test/mjsunit/debug-script.js
@@ -84,11 +84,6 @@
 assertEquals('native math.js', math_script.name);
 assertEquals(Debug.ScriptType.Native, math_script.type);
 
-// Test a builtins delay loaded script.
-var date_delay_script = Debug.findScript('native json.js');
-assertEquals('native json.js', date_delay_script.name);
-assertEquals(Debug.ScriptType.Native, date_delay_script.type);
-
 // Test a debugger script.
 var debug_delay_script = Debug.findScript('native debug.js');
 assertEquals('native debug.js', debug_delay_script.name);
diff --git a/test/mjsunit/debug-sourceinfo.js b/test/mjsunit/debug-sourceinfo.js
index cb41107..b79fb8e 100644
--- a/test/mjsunit/debug-sourceinfo.js
+++ b/test/mjsunit/debug-sourceinfo.js
@@ -63,12 +63,11 @@
 
 // This is the last position in the entire file (note: this equals
 // file size of <debug-sourceinfo.js> - 1, since starting at 0).
-var last_position = 11519;
+var last_position = 8126;
 // This is the last line of entire file (note: starting at 0).
-var last_line = 269;
-// This is the last column of last line (note: starting at 0 and +1, due
-// to trailing <LF>).
-var last_column = 1;
+var last_line = 200;
+// This is the last column of last line (note: starting at 0).
+var last_column = 71;
 
 // This magic number is the length or the first line comment (actually number
 // of characters before 'function a(...'.
@@ -168,66 +167,6 @@
 assertEquals(11, script.locationFromPosition(start_d).line - comment_lines);
 assertEquals(10, script.locationFromPosition(start_d).column);
 
-// Test first line.
-assertEquals(0, script.locationFromLine().position);
-assertEquals(0, script.locationFromLine().line);
-assertEquals(0, script.locationFromLine().column);
-assertEquals(0, script.locationFromLine(0).position);
-assertEquals(0, script.locationFromLine(0).line);
-assertEquals(0, script.locationFromLine(0).column);
-
-// Test first line column 1.
-assertEquals(1, script.locationFromLine(0, 1).position);
-assertEquals(0, script.locationFromLine(0, 1).line);
-assertEquals(1, script.locationFromLine(0, 1).column);
-
-// Test first line offset 1.
-assertEquals(1, script.locationFromLine(0, 0, 1).position);
-assertEquals(0, script.locationFromLine(0, 0, 1).line);
-assertEquals(1, script.locationFromLine(0, 0, 1).column);
-
-// Test offset function a().
-assertEquals(start_a, script.locationFromLine(void 0, void 0, start_a).position);
-assertEquals(0, script.locationFromLine(void 0, void 0, start_a).line - comment_lines);
-assertEquals(10, script.locationFromLine(void 0, void 0, start_a).column);
-assertEquals(start_a, script.locationFromLine(0, void 0, start_a).position);
-assertEquals(0, script.locationFromLine(0, void 0, start_a).line - comment_lines);
-assertEquals(10, script.locationFromLine(0, void 0, start_a).column);
-assertEquals(start_a, script.locationFromLine(0, 0, start_a).position);
-assertEquals(0, script.locationFromLine(0, 0, start_a).line - comment_lines);
-assertEquals(10, script.locationFromLine(0, 0, start_a).column);
-
-// Test second line offset function a().
-assertEquals(start_a + 13, script.locationFromLine(1, 0, start_a).position);
-assertEquals(1, script.locationFromLine(1, 0, start_a).line - comment_lines);
-assertEquals(0, script.locationFromLine(1, 0, start_a).column);
-
-// Test second line column 2 offset function a().
-assertEquals(start_a + 13 + 1, script.locationFromLine(1, 1, start_a).position);
-assertEquals(1, script.locationFromLine(1, 2, start_a).line - comment_lines);
-assertEquals(2, script.locationFromLine(1, 2, start_a).column);
-
-// Test offset function b().
-assertEquals(start_b, script.locationFromLine(0, 0, start_b).position);
-assertEquals(1, script.locationFromLine(0, 0, start_b).line - comment_lines);
-assertEquals(13, script.locationFromLine(0, 0, start_b).column);
-
-// Test second line offset function b().
-assertEquals(start_b + 5, script.locationFromLine(1, 0, start_b).position);
-assertEquals(2, script.locationFromLine(1, 0, start_b).line - comment_lines);
-assertEquals(0, script.locationFromLine(1, 0, start_b).column);
-
-// Test second line column 10 offset function b().
-assertEquals(start_b + 5 + 10, script.locationFromLine(1, 10, start_b).position);
-assertEquals(2, script.locationFromLine(1, 10, start_b).line - comment_lines);
-assertEquals(10, script.locationFromLine(1, 10, start_b).column);
-
-// Test second line column 11 offset function b. Second line in b is 10 long
-// using column 11 wraps to next line.
-assertEquals(start_b + 5 + 11, script.locationFromLine(1, 11, start_b).position);
-assertEquals(3, script.locationFromLine(1, 11, start_b).line - comment_lines);
-assertEquals(0, script.locationFromLine(1, 11, start_b).column);
-
 // Test the Debug.findSourcePosition which wraps SourceManager.
 assertEquals(0 + start_a, Debug.findFunctionSourceLocation(a, 0, 0).position);
 assertEquals(0 + start_b, Debug.findFunctionSourceLocation(b, 0, 0).position);
@@ -260,11 +199,3 @@
 assertEquals(last_line + 1,
              script.locationFromPosition(last_position + 1).line);
 assertEquals(0, script.locationFromPosition(last_position + 1).column);
-
-// Test that script.sourceLine(line) works.
-var location;
-
-for (line = 0; line < num_lines_d; line++) {
-  var line_content_regexp = new RegExp("  x = " + (line + 1));
-  assertTrue(line_content_regexp.test(script.sourceLine(start_line_d + line)));
-}
diff --git a/test/mjsunit/debug-sourceslice.js b/test/mjsunit/debug-sourceslice.js
deleted file mode 100644
index db9a3e7..0000000
--- a/test/mjsunit/debug-sourceslice.js
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --expose-debug-as debug
-// Source lines for test.
-var lines = [ 'function a() { b(); };\n',
-              'function    b() {\n',
-              '  c(true);\n',
-              '};\n',
-              '  function c(x) {\n',
-              '    if (x) {\n',
-              '      return 1;\n',
-              '    } else {\n',
-              '      return 1;\n',
-              '    }\n',
-              '  };\n' ];
-
-// Build source by putting all lines together
-var source = '';
-for (var i = 0; i < lines.length; i++) {
-  source += lines[i];
-}
-eval(source);
-
-// Flags: --expose-debug-as debug
-// Get the Debug object exposed from the debug context global object.
-Debug = debug.Debug
-
-// Get the script object from one of the functions in the source.
-var script = Debug.findScript(a);
-
-// Make sure that the source is as expected.
-assertEquals(source, script.source);
-assertEquals(source, script.sourceSlice().sourceText());
-
-// Try all possible line interval slices.
-for (var slice_size = 0; slice_size < lines.length; slice_size++) {
-  for (var n = 0; n < lines.length - slice_size; n++) {
-    var slice = script.sourceSlice(n, n + slice_size);
-    assertEquals(n, slice.from_line);
-    assertEquals(n + slice_size, slice.to_line);
-
-    var text = slice.sourceText();
-    var expected = '';
-    for (var i = 0; i < slice_size; i++) {
-      expected += lines[n + i];
-    }
-    assertEquals(expected, text);
-  }
-}
diff --git a/test/mjsunit/debug-stack-check-position.js b/test/mjsunit/debug-stack-check-position.js
new file mode 100644
index 0000000..a5570ce
--- /dev/null
+++ b/test/mjsunit/debug-stack-check-position.js
@@ -0,0 +1,30 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax
+
+var Debug = debug.Debug;
+var exception = null;
+var loop = true;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    assertTrue(exec_state.frame(0).sourceLineText().indexOf("BREAK") > 0);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+function f() {     // BREAK
+  return 1;
+}
+
+Debug.setListener(listener);
+
+%ScheduleBreak();  // Break on function entry.
+f();
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/test/mjsunit/delete.js b/test/mjsunit/delete.js
index 8d4636a..20fa6bf 100644
--- a/test/mjsunit/delete.js
+++ b/test/mjsunit/delete.js
@@ -178,3 +178,17 @@
 }
 
 load_deleted_property_using_IC();
+
+
+(function deleteLargeDoubleArrayAtEnd() {
+  var o = {};
+  var max = 100000;
+  for (var i = 0; i <= max; i++) {
+    o[i] = 1.1;
+  }
+  delete o[max];
+  for (var i = 0; i < max; i++) {
+    assertEquals(1.1, o[i]);
+  }
+  assertEquals(undefined, o[max]);
+})();
diff --git a/test/mjsunit/dictionary-properties.js b/test/mjsunit/dictionary-properties.js
index 0659268..33360d7 100644
--- a/test/mjsunit/dictionary-properties.js
+++ b/test/mjsunit/dictionary-properties.js
@@ -39,7 +39,13 @@
 SlowPrototype.prototype.bar = 2;
 SlowPrototype.prototype.baz = 3;
 delete SlowPrototype.prototype.baz;
-new SlowPrototype;
+assertFalse(%HasFastProperties(SlowPrototype.prototype));
+var slow_proto = new SlowPrototype;
+// ICs make prototypes fast.
+function ic() { return slow_proto.bar; }
+ic();
+ic();
+assertTrue(%HasFastProperties(slow_proto.__proto__));
 
 // Prototypes stay fast even after deleting properties.
 assertTrue(%HasFastProperties(SlowPrototype.prototype));
diff --git a/test/mjsunit/double-intrinsics.js b/test/mjsunit/double-intrinsics.js
index 16d6538..b50038e 100644
--- a/test/mjsunit/double-intrinsics.js
+++ b/test/mjsunit/double-intrinsics.js
@@ -7,10 +7,10 @@
 function assertDoubleBits(hi, lo, x) {
   hi = hi | 0;
   lo = lo | 0;
-  assertEquals(x, %_ConstructDouble(hi, lo));
+  assertEquals(x, %ConstructDouble(hi, lo));
   assertEquals(hi, %_DoubleHi(x));
   assertEquals(lo, %_DoubleLo(x));
-  assertEquals(x, %_ConstructDouble(%_DoubleHi(x), %_DoubleLo(x)));
+  assertEquals(x, %ConstructDouble(%_DoubleHi(x), %_DoubleLo(x)));
 }
 
 
diff --git a/test/mjsunit/es6/array-concat.js b/test/mjsunit/es6/array-concat.js
index fe320d6..00edfd6 100644
--- a/test/mjsunit/es6/array-concat.js
+++ b/test/mjsunit/es6/array-concat.js
@@ -1,7 +1,6 @@
 // Copyright 2014 the V8 project authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-
 (function testArrayConcatArity() {
   "use strict";
   assertEquals(1, Array.prototype.concat.length);
@@ -20,6 +19,15 @@
   assertEquals(false, desc.enumerable);
 })();
 
+(function testNonConcatSpreadableArray() {
+  "use strict"
+  var array = [1, 2, 3];
+  assertEquals(array, [].concat(array));
+  assertEquals(array, array.concat([]));
+  array[Symbol.isConcatSpreadable] = false;
+  assertEquals([[1,2,3]], [].concat(array));
+  assertEquals([[1,2,3]], array.concat([]));
+})();
 
 (function testConcatArrayLike() {
   "use strict";
diff --git a/test/mjsunit/es6/array-species-constructor-accessor.js b/test/mjsunit/es6/array-species-constructor-accessor.js
new file mode 100644
index 0000000..7ebf328
--- /dev/null
+++ b/test/mjsunit/es6/array-species-constructor-accessor.js
@@ -0,0 +1,28 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+// Overwriting the constructor of an instance updates the protector
+
+let x = [];
+
+assertEquals(Array, x.map(()=>{}).constructor);
+assertEquals(Array, x.filter(()=>{}).constructor);
+assertEquals(Array, x.slice().constructor);
+assertEquals(Array, x.splice().constructor);
+assertEquals(Array, x.concat([1]).constructor);
+assertEquals(1, x.concat([1])[0]);
+
+class MyArray extends Array { }
+
+Object.defineProperty(x, 'constructor', {get() { return MyArray; }});
+assertFalse(%SpeciesProtector());
+
+assertEquals(MyArray, x.map(()=>{}).constructor);
+assertEquals(MyArray, x.filter(()=>{}).constructor);
+assertEquals(MyArray, x.slice().constructor);
+assertEquals(MyArray, x.splice().constructor);
+assertEquals(MyArray, x.concat([1]).constructor);
+assertEquals(1, x.concat([1])[0]);
diff --git a/test/mjsunit/es6/array-species-constructor-delete.js b/test/mjsunit/es6/array-species-constructor-delete.js
new file mode 100644
index 0000000..fff22a2
--- /dev/null
+++ b/test/mjsunit/es6/array-species-constructor-delete.js
@@ -0,0 +1,29 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+// Overwriting the constructor of an instance updates the protector
+
+let x = [];
+
+assertEquals(Array, x.map(()=>{}).constructor);
+assertEquals(Array, x.filter(()=>{}).constructor);
+assertEquals(Array, x.slice().constructor);
+assertEquals(Array, x.splice().constructor);
+assertEquals(Array, x.concat([1]).constructor);
+assertEquals(1, x.concat([1])[0]);
+
+class MyArray extends Array { }
+
+Object.prototype.constructor = MyArray;
+delete Array.prototype.constructor;
+assertFalse(%SpeciesProtector());
+
+assertEquals(MyArray, x.map(()=>{}).constructor);
+assertEquals(MyArray, x.filter(()=>{}).constructor);
+assertEquals(MyArray, x.slice().constructor);
+assertEquals(MyArray, x.splice().constructor);
+assertEquals(MyArray, x.concat([1]).constructor);
+assertEquals(1, x.concat([1])[0]);
diff --git a/test/mjsunit/es6/array-species-constructor.js b/test/mjsunit/es6/array-species-constructor.js
new file mode 100644
index 0000000..0d888f4
--- /dev/null
+++ b/test/mjsunit/es6/array-species-constructor.js
@@ -0,0 +1,28 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+// Overwriting the constructor of an instance updates the protector
+
+let x = [];
+
+assertEquals(Array, x.map(()=>{}).constructor);
+assertEquals(Array, x.filter(()=>{}).constructor);
+assertEquals(Array, x.slice().constructor);
+assertEquals(Array, x.splice().constructor);
+assertEquals(Array, x.concat([1]).constructor);
+assertEquals(1, x.concat([1])[0]);
+
+class MyArray extends Array { }
+
+x.constructor = MyArray;
+assertFalse(%SpeciesProtector());
+
+assertEquals(MyArray, x.map(()=>{}).constructor);
+assertEquals(MyArray, x.filter(()=>{}).constructor);
+assertEquals(MyArray, x.slice().constructor);
+assertEquals(MyArray, x.splice().constructor);
+assertEquals(MyArray, x.concat([1]).constructor);
+assertEquals(1, x.concat([1])[0]);
diff --git a/test/mjsunit/es6/array-species-delete.js b/test/mjsunit/es6/array-species-delete.js
new file mode 100644
index 0000000..16a2fa2
--- /dev/null
+++ b/test/mjsunit/es6/array-species-delete.js
@@ -0,0 +1,29 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+// Overwriting the constructor of an instance updates the protector
+
+let x = [];
+
+assertEquals(Array, x.map(()=>{}).constructor);
+assertEquals(Array, x.filter(()=>{}).constructor);
+assertEquals(Array, x.slice().constructor);
+assertEquals(Array, x.splice().constructor);
+assertEquals(Array, x.concat([1]).constructor);
+assertEquals(1, x.concat([1])[0]);
+
+class MyArray extends Array { }
+
+Object.prototype[Symbol.species] = MyArray;
+delete Array[Symbol.species];
+assertFalse(%SpeciesProtector());
+
+assertEquals(MyArray, x.map(()=>{}).constructor);
+assertEquals(MyArray, x.filter(()=>{}).constructor);
+assertEquals(MyArray, x.slice().constructor);
+assertEquals(MyArray, x.splice().constructor);
+assertEquals(MyArray, x.concat([1]).constructor);
+assertEquals(1, x.concat([1])[0]);
diff --git a/test/mjsunit/es6/array-species-modified.js b/test/mjsunit/es6/array-species-modified.js
new file mode 100644
index 0000000..58feb31
--- /dev/null
+++ b/test/mjsunit/es6/array-species-modified.js
@@ -0,0 +1,28 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+// Overwriting Array[Symbol.species] updates the protector
+
+let x = [];
+
+assertEquals(Array, x.map(()=>{}).constructor);
+assertEquals(Array, x.filter(()=>{}).constructor);
+assertEquals(Array, x.slice().constructor);
+assertEquals(Array, x.splice().constructor);
+assertEquals(Array, x.concat([1]).constructor);
+assertEquals(1, x.concat([1])[0]);
+
+class MyArray extends Array { }
+
+Object.defineProperty(Array, Symbol.species, {value: MyArray});
+assertFalse(%SpeciesProtector());
+
+assertEquals(MyArray, x.map(()=>{}).constructor);
+assertEquals(MyArray, x.filter(()=>{}).constructor);
+assertEquals(MyArray, x.slice().constructor);
+assertEquals(MyArray, x.splice().constructor);
+assertEquals(MyArray, x.concat([1]).constructor);
+assertEquals(1, x.concat([1])[0]);
diff --git a/test/mjsunit/es6/array-species-neg-zero.js b/test/mjsunit/es6/array-species-neg-zero.js
new file mode 100644
index 0000000..d60b8ba
--- /dev/null
+++ b/test/mjsunit/es6/array-species-neg-zero.js
@@ -0,0 +1,23 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * 9.4.2.3 ArraySpeciesCreate(originalArray, length)
+ *
+ * 1. Assert: length is an integer Number ≥ 0.
+ * 2. If length is −0, let length be +0.
+ * [...]
+ */
+
+var x = [];
+var deleteCount;
+
+x.constructor = function() {};
+x.constructor[Symbol.species] = function(param) {
+  deleteCount = param;
+};
+
+x.splice(0, -0);
+
+assertEquals(0, deleteCount);
diff --git a/test/mjsunit/es6/array-species-parent-constructor.js b/test/mjsunit/es6/array-species-parent-constructor.js
new file mode 100644
index 0000000..b4fb1d5
--- /dev/null
+++ b/test/mjsunit/es6/array-species-parent-constructor.js
@@ -0,0 +1,28 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+// Overwriting Array.prototype.constructor updates the protector
+
+let x = [];
+
+assertEquals(Array, x.map(()=>{}).constructor);
+assertEquals(Array, x.filter(()=>{}).constructor);
+assertEquals(Array, x.slice().constructor);
+assertEquals(Array, x.splice().constructor);
+assertEquals(Array, x.concat([1]).constructor);
+assertEquals(1, x.concat([1])[0]);
+
+class MyArray extends Array { }
+
+Array.prototype.constructor = MyArray;
+assertFalse(%SpeciesProtector());
+
+assertEquals(MyArray, x.map(()=>{}).constructor);
+assertEquals(MyArray, x.filter(()=>{}).constructor);
+assertEquals(MyArray, x.slice().constructor);
+assertEquals(MyArray, x.splice().constructor);
+assertEquals(MyArray, x.concat([1]).constructor);
+assertEquals(1, x.concat([1])[0]);
diff --git a/test/mjsunit/es6/array-species-proto.js b/test/mjsunit/es6/array-species-proto.js
new file mode 100644
index 0000000..6b55881
--- /dev/null
+++ b/test/mjsunit/es6/array-species-proto.js
@@ -0,0 +1,28 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+// Overwriting an array instance's __proto__ updates the protector
+
+let x = [];
+
+assertEquals(Array, x.map(()=>{}).constructor);
+assertEquals(Array, x.filter(()=>{}).constructor);
+assertEquals(Array, x.slice().constructor);
+assertEquals(Array, x.splice().constructor);
+assertEquals(Array, x.concat([1]).constructor);
+assertEquals(1, x.concat([1])[0]);
+
+class MyArray extends Array { }
+
+x.__proto__ = MyArray.prototype;
+assertTrue(%SpeciesProtector());
+
+assertEquals(MyArray, x.map(()=>{}).constructor);
+assertEquals(MyArray, x.filter(()=>{}).constructor);
+assertEquals(MyArray, x.slice().constructor);
+assertEquals(MyArray, x.splice().constructor);
+assertEquals(MyArray, x.concat([1]).constructor);
+assertEquals(1, x.concat([1])[0]);
diff --git a/test/mjsunit/es6/array-species.js b/test/mjsunit/es6/array-species.js
new file mode 100644
index 0000000..25edf55
--- /dev/null
+++ b/test/mjsunit/es6/array-species.js
@@ -0,0 +1,171 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Test the ES2015 @@species feature
+
+'use strict';
+
+// Subclasses of Array construct themselves under map, etc
+
+class MyArray extends Array { }
+
+assertEquals(MyArray, new MyArray().map(()=>{}).constructor);
+assertEquals(MyArray, new MyArray().filter(()=>{}).constructor);
+assertEquals(MyArray, new MyArray().slice().constructor);
+assertEquals(MyArray, new MyArray().splice().constructor);
+assertEquals(MyArray, new MyArray().concat([1]).constructor);
+assertEquals(1, new MyArray().concat([1])[0]);
+
+// Subclasses can override @@species to return the another class
+
+class MyOtherArray extends Array {
+  static get [Symbol.species]() { return MyArray; }
+}
+
+assertEquals(MyArray, new MyOtherArray().map(()=>{}).constructor);
+assertEquals(MyArray, new MyOtherArray().filter(()=>{}).constructor);
+assertEquals(MyArray, new MyOtherArray().slice().constructor);
+assertEquals(MyArray, new MyOtherArray().splice().constructor);
+assertEquals(MyArray, new MyOtherArray().concat().constructor);
+
+// Array  methods on non-arrays return arrays
+
+class MyNonArray extends Array {
+  static get [Symbol.species]() { return MyObject; }
+}
+
+class MyObject { }
+
+assertEquals(MyObject,
+             Array.prototype.map.call(new MyNonArray(), ()=>{}).constructor);
+assertEquals(MyObject,
+             Array.prototype.filter.call(new MyNonArray(), ()=>{}).constructor);
+assertEquals(MyObject,
+             Array.prototype.slice.call(new MyNonArray()).constructor);
+assertEquals(MyObject,
+             Array.prototype.splice.call(new MyNonArray()).constructor);
+assertEquals(MyObject,
+             Array.prototype.concat.call(new MyNonArray()).constructor);
+
+assertEquals(undefined,
+             Array.prototype.map.call(new MyNonArray(), ()=>{}).length);
+assertEquals(undefined,
+             Array.prototype.filter.call(new MyNonArray(), ()=>{}).length);
+assertEquals(undefined,
+             Array.prototype.concat.call(new MyNonArray(), ()=>{}).length);
+// slice and splice actually do explicitly define the length for some reason
+assertEquals(0, Array.prototype.slice.call(new MyNonArray()).length);
+assertEquals(0, Array.prototype.splice.call(new MyNonArray()).length);
+
+// Cross-realm Arrays build same-realm arrays
+
+var realm = Realm.create();
+assertEquals(Array,
+             Array.prototype.map.call(
+                 Realm.eval(realm, "[]"), ()=>{}).constructor);
+assertFalse(Array === Realm.eval(realm, "[]").map(()=>{}).constructor);
+assertFalse(Array === Realm.eval(realm, "[].map(()=>{}).constructor"));
+assertEquals(Array,
+             Array.prototype.concat.call(
+                 Realm.eval(realm, "[]")).constructor);
+
+// Defaults when constructor or @@species is missing or non-constructor
+
+class MyDefaultArray extends Array {
+  static get [Symbol.species]() { return undefined; }
+}
+assertEquals(Array, new MyDefaultArray().map(()=>{}).constructor);
+
+class MyOtherDefaultArray extends Array { }
+assertEquals(MyOtherDefaultArray,
+             new MyOtherDefaultArray().map(()=>{}).constructor);
+MyOtherDefaultArray.prototype.constructor = undefined;
+assertEquals(Array, new MyOtherDefaultArray().map(()=>{}).constructor);
+assertEquals(Array, new MyOtherDefaultArray().concat().constructor);
+
+// Exceptions propagated when getting constructor @@species throws
+
+class SpeciesError extends Error { }
+class ConstructorError extends Error { }
+class MyThrowingArray extends Array {
+  static get [Symbol.species]() { throw new SpeciesError; }
+}
+assertThrows(() => new MyThrowingArray().map(()=>{}), SpeciesError);
+Object.defineProperty(MyThrowingArray.prototype, 'constructor', {
+    get() { throw new ConstructorError; }
+});
+assertThrows(() => new MyThrowingArray().map(()=>{}), ConstructorError);
+
+// Previously unexpected errors from setting properties in arrays throw
+
+class FrozenArray extends Array {
+  constructor(...args) {
+    super(...args);
+    Object.freeze(this);
+  }
+}
+assertThrows(() => new FrozenArray([1]).map(()=>0), TypeError);
+assertThrows(() => new FrozenArray([1]).filter(()=>true), TypeError);
+assertThrows(() => new FrozenArray([1]).slice(0, 1), TypeError);
+assertThrows(() => new FrozenArray([1]).splice(0, 1), TypeError);
+assertThrows(() => new FrozenArray([]).concat([1]), TypeError);
+
+// Verify call counts and constructor parameters
+
+var count;
+var params;
+class MyObservedArray extends Array {
+  constructor(...args) {
+    super(...args);
+    params = args;
+  }
+  static get [Symbol.species]() {
+    count++
+    return this;
+  }
+}
+
+count = 0;
+params = undefined;
+assertEquals(MyObservedArray,
+             new MyObservedArray().map(()=>{}).constructor);
+assertEquals(1, count);
+assertArrayEquals([0], params);
+
+count = 0;
+params = undefined;
+assertEquals(MyObservedArray,
+             new MyObservedArray().filter(()=>{}).constructor);
+assertEquals(1, count);
+assertArrayEquals([0], params);
+
+count = 0;
+params = undefined;
+assertEquals(MyObservedArray,
+             new MyObservedArray().concat().constructor);
+assertEquals(1, count);
+assertArrayEquals([0], params);
+
+count = 0;
+params = undefined;
+assertEquals(MyObservedArray,
+             new MyObservedArray().slice().constructor);
+assertEquals(1, count);
+assertArrayEquals([0], params);
+
+count = 0;
+params = undefined;
+assertEquals(MyObservedArray,
+             new MyObservedArray().splice().constructor);
+assertEquals(1, count);
+assertArrayEquals([0], params);
+
+// @@species constructor can be a Proxy, and the realm access doesn't
+// crash
+
+class MyProxyArray extends Array { }
+let ProxyArray = new Proxy(MyProxyArray, {});
+MyProxyArray.constructor = ProxyArray;
+
+assertEquals(MyProxyArray, new ProxyArray().map(()=>{}).constructor);
diff --git a/test/mjsunit/es6/arraybuffer-species.js b/test/mjsunit/es6/arraybuffer-species.js
new file mode 100644
index 0000000..1ac6efb
--- /dev/null
+++ b/test/mjsunit/es6/arraybuffer-species.js
@@ -0,0 +1,34 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// ArrayBuffer.prototype.slice makes subclass and checks length
+
+class MyArrayBuffer extends ArrayBuffer { }
+assertEquals(MyArrayBuffer, new MyArrayBuffer(0).slice().constructor);
+
+class MyShortArrayBuffer extends ArrayBuffer {
+  constructor(length) { super(length - 1); }
+}
+assertThrows(() => new MyShortArrayBuffer(5).slice(0, 4), TypeError);
+
+class SingletonArrayBuffer extends ArrayBuffer {
+  constructor(...args) {
+    if (SingletonArrayBuffer.cached) return SingletonArrayBuffer.cached;
+    super(...args);
+    SingletonArrayBuffer.cached = this;
+  }
+}
+assertThrows(() => new SingletonArrayBuffer(5).slice(0, 4), TypeError);
+
+class NonArrayBuffer extends ArrayBuffer {
+  constructor() {
+    return {};
+  }
+}
+assertThrows(() => new NonArrayBuffer(5).slice(0, 4), TypeError);
+
+// Species fallback is ArrayBuffer
+class UndefinedArrayBuffer extends ArrayBuffer { }
+UndefinedArrayBuffer.prototype.constructor = undefined;
+assertEquals(ArrayBuffer, new UndefinedArrayBuffer(0).slice().constructor);
diff --git a/test/mjsunit/es6/block-conflicts-sloppy.js b/test/mjsunit/es6/block-conflicts-sloppy.js
new file mode 100644
index 0000000..866abee
--- /dev/null
+++ b/test/mjsunit/es6/block-conflicts-sloppy.js
@@ -0,0 +1,177 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Test for conflicting variable bindings.
+
+function CheckException(e) {
+  var string = e.toString();
+  assertTrue(string.indexOf("has already been declared") >= 0 ||
+             string.indexOf("redeclaration") >= 0);
+  return 'Conflict';
+}
+
+
+function TestGlobal(s,e) {
+  try {
+    return eval(s + e);
+  } catch (x) {
+    return CheckException(x);
+  }
+}
+
+
+function TestFunction(s,e) {
+  try {
+    return eval("(function(){" + s + " return " + e + "})")();
+  } catch (x) {
+    return CheckException(x);
+  }
+}
+
+
+function TestBlock(s,e) {
+  try {
+    return eval("(function(){ {" + s + "} return " + e + "})")();
+  } catch (x) {
+    return CheckException(x);
+  }
+}
+
+function TestAll(expected,s,opt_e) {
+  var e = "";
+  var msg = s;
+  if (opt_e) { e = opt_e; msg += opt_e; }
+  // TODO(littledan): Add tests using Realm.eval to ensure that global eval
+  // works as expected.
+  assertEquals(expected === 'LocalConflict' ? 'NoConflict' : expected,
+      TestGlobal(s,e), "global:'" + msg + "'");
+  assertEquals(expected === 'LocalConflict' ? 'NoConflict' : expected,
+      TestFunction(s,e), "function:'" + msg + "'");
+  assertEquals(expected === 'LocalConflict' ? 'Conflict' : expected,
+      TestBlock(s,e), "block:'" + msg + "'");
+}
+
+
+function TestConflict(s) {
+  TestAll('Conflict', s);
+  TestAll('Conflict', 'eval("' + s + '");');
+}
+
+function TestNoConflict(s) {
+  TestAll('NoConflict', s, "'NoConflict'");
+  TestAll('NoConflict', 'eval("' + s + '");', "'NoConflict'");
+}
+
+function TestLocalConflict(s) {
+  TestAll('LocalConflict', s, "'NoConflict'");
+  TestAll('NoConflict', 'eval("' + s + '");', "'NoConflict'");
+}
+
+var letbinds = [ "let x;",
+                 "let x = 0;",
+                 "let x = undefined;",
+                 "let x = function() {};",
+                 "let x, y;",
+                 "let y, x;",
+                 "const x = 0;",
+                 "const x = undefined;",
+                 "const x = function() {};",
+                 "const x = 2, y = 3;",
+                 "const y = 4, x = 5;",
+                 "class x { }",
+                 ];
+function forCompatible(bind) {
+  return !bind.startsWith('class');
+}
+var varbinds = [ "var x;",
+                 "var x = 0;",
+                 "var x = undefined;",
+                 "var x = function() {};",
+                 "var x, y;",
+                 "var y, x;",
+                 ];
+var funbind = "function x() {}";
+
+for (var l = 0; l < letbinds.length; ++l) {
+  // Test conflicting let/var bindings.
+  for (var v = 0; v < varbinds.length; ++v) {
+    // Same level.
+    TestConflict(letbinds[l] + varbinds[v]);
+    TestConflict(varbinds[v] + letbinds[l]);
+    // Different level.
+    TestConflict(letbinds[l] + '{' + varbinds[v] + '}');
+    TestConflict('{' + varbinds[v] +'}' + letbinds[l]);
+    TestNoConflict(varbinds[v] + '{' + letbinds[l] + '}');
+    TestNoConflict('{' + letbinds[l] + '}' + varbinds[v]);
+    // For loop.
+    if (forCompatible(letbinds[l])) {
+      TestConflict('for (' + letbinds[l] + '0;) {' + varbinds[v] + '}');
+    }
+    TestNoConflict('for (' + varbinds[v] + '0;) {' + letbinds[l] + '}');
+  }
+
+  // Test conflicting let/let bindings.
+  for (var k = 0; k < letbinds.length; ++k) {
+    // Same level.
+    TestConflict(letbinds[l] + letbinds[k]);
+    TestConflict(letbinds[k] + letbinds[l]);
+    // Different level.
+    TestNoConflict(letbinds[l] + '{ ' + letbinds[k] + '}');
+    TestNoConflict('{' + letbinds[k] +'} ' + letbinds[l]);
+    // For loop.
+    if (forCompatible(letbinds[l])) {
+      TestNoConflict('for (' + letbinds[l] + '0;) {' + letbinds[k] + '}');
+    }
+    if (forCompatible(letbinds[k])) {
+      TestNoConflict('for (' + letbinds[k] + '0;) {' + letbinds[l] + '}');
+    }
+  }
+
+  // Test conflicting function/let bindings.
+  // Same level.
+  TestConflict(letbinds[l] + funbind);
+  TestConflict(funbind + letbinds[l]);
+  // Different level.
+  TestNoConflict(letbinds[l] + '{' + funbind + '}');
+  TestNoConflict('{' + funbind + '}' + letbinds[l]);
+  TestNoConflict(funbind + '{' + letbinds[l] + '}');
+  TestNoConflict('{' + letbinds[l] + '}' + funbind);
+  // For loop.
+  if (forCompatible(letbinds[l])) {
+    TestNoConflict('for (' + letbinds[l] + '0;) {' + funbind + '}');
+  }
+
+  // Test conflicting parameter/let bindings.
+  TestConflict('(function(x) {' + letbinds[l] + '})();');
+}
+
+// Test conflicting function/var bindings.
+for (var v = 0; v < varbinds.length; ++v) {
+  // Same level.
+  TestLocalConflict(varbinds[v] + funbind);
+  TestLocalConflict(funbind + varbinds[v]);
+  // Different level.
+  TestLocalConflict(funbind + '{' + varbinds[v] + '}');
+  TestLocalConflict('{' + varbinds[v] +'}' + funbind);
+  TestNoConflict(varbinds[v] + '{' + funbind + '}');
+  TestNoConflict('{' + funbind + '}' + varbinds[v]);
+  // For loop.
+  TestNoConflict('for (' + varbinds[v] + '0;) {' + funbind + '}');
+}
+
+// Test conflicting catch/var bindings.
+for (var v = 0; v < varbinds.length; ++v) {
+  TestNoConflict('try {} catch(x) {' + varbinds[v] + '}');
+}
+
+// Test conflicting parameter/var bindings.
+for (var v = 0; v < varbinds.length; ++v) {
+  TestNoConflict('(function (x) {' + varbinds[v] + '})();');
+}
+
+// Test conflicting catch/function bindings.
+TestNoConflict('try {} catch(x) {' + funbind + '}');
+
+// Test conflicting parameter/function bindings.
+TestNoConflict('(function (x) {' + funbind + '})();');
diff --git a/test/mjsunit/es6/block-const-assign-sloppy.js b/test/mjsunit/es6/block-const-assign-sloppy.js
new file mode 100644
index 0000000..99024ef
--- /dev/null
+++ b/test/mjsunit/es6/block-const-assign-sloppy.js
@@ -0,0 +1,156 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that we throw early syntax errors in harmony mode
+// when using an immutable binding in an assigment or with
+// prefix/postfix decrement/increment operators.
+
+const decls = [
+  // Const declaration.
+  function(use) { return "const c = 1; " + use + ";" }, TypeError,
+  function(use) { return "const x = 0, c = 1; " + use + ";" }, TypeError,
+  function(use) { return "const c = 1, x = (" + use + ");" }, TypeError,
+  function(use) { return use + "; const c = 1;" }, ReferenceError,
+  function(use) { return use + "; const x = 0, c = 1;" }, ReferenceError,
+  function(use) { return "const x = (" + use + "), c = 1;" }, ReferenceError,
+  function(use) { return "const c = (" + use + ");" }, ReferenceError,
+
+  // Function expression.
+  function(use) { return "(function c() { " + use + "; })();"; }, TypeError,
+  // TODO(rossberg): Once we have default parameters, test using 'c' there.
+
+  // Class expression.
+  function(use) {
+    return "new class c { constructor() { " + use + " } };";
+  }, TypeError,
+  function(use) {
+    return "(new class c { m() { " + use + " } }).m();";
+  }, TypeError,
+  function(use) {
+    return "(new class c { get a() { " + use + " } }).a;";
+  }, TypeError,
+  function(use) {
+    return "(new class c { set a(x) { " + use + " } }).a = 0;";
+  }, TypeError,
+  function(use) {
+    return "(class c { static m() { " + use + " } }).s();";
+  }, TypeError,
+  function(use) {
+    return "(class c extends (" + use + ") {});";
+  }, ReferenceError,
+  function(use) {
+    return "(class c { [" + use + "]() {} });";
+  }, ReferenceError,
+  function(use) {
+    return "(class c { get [" + use + "]() {} });";
+  }, ReferenceError,
+  function(use) {
+    return "(class c { set [" + use + "](x) {} });";
+  }, ReferenceError,
+  function(use) {
+    return "(class c { static [" + use + "]() {} });";
+  }, ReferenceError,
+
+  // For loop.
+  function(use) {
+    return "for (const c = 0; " + use + ";) {}"
+  }, TypeError,
+  function(use) {
+    return "for (const x = 0, c = 0; " + use + ";) {}"
+  }, TypeError,
+  function(use) {
+    return "for (const c = 0; ; " + use + ") {}"
+  }, TypeError,
+  function(use) {
+    return "for (const x = 0, c = 0; ; " + use + ") {}"
+  }, TypeError,
+  function(use) {
+    return "for (const c = 0; ;) { " + use + "; }"
+  }, TypeError,
+  function(use) {
+    return "for (const x = 0, c = 0; ;) { " + use + "; }"
+  }, TypeError,
+  function(use) {
+    return "for (const c in {a: 1}) { " + use + "; }"
+  }, TypeError,
+  function(use) {
+    return "for (const c of [1]) { " + use + "; }"
+  }, TypeError,
+  function(use) {
+    return "for (const x = (" + use + "), c = 0; ;) {}"
+  }, ReferenceError,
+  function(use) {
+    return "for (const c = (" + use + "); ;) {}"
+  }, ReferenceError,
+]
+
+let uses = [
+  'c = 1',
+  'c += 1',
+  '++c',
+  'c--',
+];
+
+let declcontexts = [
+  function(decl) { return decl; },
+  function(decl) { return "eval(\'" + decl + "\')"; },
+  function(decl) { return "{ " + decl + " }"; },
+  function(decl) { return "(function() { " + decl + " })()"; },
+];
+
+let usecontexts = [
+  function(use) { return use; },
+  function(use) { return "eval(\"" + use + "\")"; },
+  function(use) { return "(function() { " + use + " })()"; },
+  function(use) { return "(function() { eval(\"" + use + "\"); })()"; },
+  function(use) { return "eval(\"(function() { " + use + "; })\")()"; },
+];
+
+function Test(program, error) {
+  program = "'use strict'; " + program;
+  try {
+    print(program, "  // throw " + error.name);
+    eval(program);
+  } catch (e) {
+    assertInstanceof(e, error);
+    if (e === TypeError) {
+      assertTrue(e.toString().indexOf("Assignment to constant variable") >= 0);
+    }
+    return;
+  }
+  assertUnreachable();
+}
+
+for (var d = 0; d < decls.length; d += 2) {
+  for (var u = 0; u < uses.length; ++u) {
+    for (var o = 0; o < declcontexts.length; ++o) {
+      for (var i = 0; i < usecontexts.length; ++i) {
+        Test(declcontexts[o](decls[d](usecontexts[i](uses[u]))), decls[d + 1]);
+      }
+    }
+  }
+}
diff --git a/test/mjsunit/es6/block-early-errors.js b/test/mjsunit/es6/block-early-errors.js
deleted file mode 100644
index 4af6521..0000000
--- a/test/mjsunit/es6/block-early-errors.js
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --no-harmony-sloppy-let
-
-function CheckException(e) {
-  var string = e.toString();
-  assertInstanceof(e, SyntaxError);
-}
-
-function Check(str) {
-  try {
-    eval("(function () { " + str + " })");
-    assertUnreachable();
-  } catch (e) {
-    CheckException(e);
-  }
-  try {
-    eval("(function () { { " + str + " } })");
-    assertUnreachable();
-  } catch (e) {
-    CheckException(e);
-  }
-}
-
-// Check for early syntax errors when using let
-// declarations outside of strict mode.
-Check("let x;");
-Check("let x = 1;");
-Check("let x, y;");
diff --git a/test/mjsunit/es6/block-eval-var-over-let.js b/test/mjsunit/es6/block-eval-var-over-let.js
new file mode 100644
index 0000000..b68dbdd
--- /dev/null
+++ b/test/mjsunit/es6/block-eval-var-over-let.js
@@ -0,0 +1,141 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Var-let conflict in a function throws, even if the var is in an eval
+
+// Throws at the top level of a function
+assertThrows(function() {
+  let x = 1;
+  eval('var x');
+}, SyntaxError);
+
+// If the eval is in its own block scope, throws
+assertThrows(function() {
+  let y = 1;
+  { eval('var y'); }
+}, SyntaxError);
+
+// If the let is in its own block scope, with the eval, throws
+assertThrows(function() {
+  {
+    let x = 1;
+    eval('var x');
+  }
+}, SyntaxError);
+
+// Legal if the let is no longer visible
+assertDoesNotThrow(function() {
+  {
+    let x = 1;
+  }
+  eval('var x');
+});
+
+// All the same works for const:
+// Throws at the top level of a function
+assertThrows(function() {
+  const x = 1;
+  eval('var x');
+}, SyntaxError);
+
+// If the eval is in its own block scope, throws
+assertThrows(function() {
+  const y = 1;
+  { eval('var y'); }
+}, SyntaxError);
+
+// If the const is in its own block scope, with the eval, throws
+assertThrows(function() {
+  {
+    const x = 1;
+    eval('var x');
+  }
+}, SyntaxError);
+
+// Legal if the const is no longer visible
+assertDoesNotThrow(function() {
+  {
+    const x = 1;
+  }
+  eval('var x');
+});
+
+// In global scope
+let caught = false;
+try {
+  let z = 1;
+  eval('var z');
+} catch (e) {
+  caught = true;
+}
+assertTrue(caught);
+
+// Let declarations beyond a function boundary don't conflict
+caught = false;
+try {
+  let a = 1;
+  (function() {
+    eval('var a');
+  })();
+} catch (e) {
+  caught = true;
+}
+assertFalse(caught);
+
+// var across with doesn't conflict
+caught = false;
+try {
+  (function() {
+    with ({x: 1}) {
+      eval("var x");
+    }
+  })();
+} catch (e) {
+  caught = true;
+}
+assertFalse(caught);
+
+// var can still conflict with let across a with
+caught = false;
+try {
+  (function() {
+    let x;
+    with ({x: 1}) {
+      eval("var x");
+    }
+  })();
+} catch (e) {
+  caught = true;
+}
+assertTrue(caught);
+
+// Functions declared in eval also conflict
+caught = false
+try {
+  (function() {
+    {
+      let x = 1;
+      eval('function x() {}');
+    }
+  })();
+} catch (e) {
+  caught = true;
+}
+assertTrue(caught);
+
+// TODO(littledan): Hoisting x out of the block should be
+// prevented in this case BUG(v8:4479)
+caught = false
+try {
+  (function() {
+    {
+      let x = 1;
+      eval('{ function x() {} }');
+    }
+  })();
+} catch (e) {
+  caught = true;
+}
+// TODO(littledan): switch to assertTrue when bug is fixed
+assertTrue(caught);
diff --git a/test/mjsunit/es6/block-for-sloppy.js b/test/mjsunit/es6/block-for-sloppy.js
new file mode 100644
index 0000000..4f0f63f
--- /dev/null
+++ b/test/mjsunit/es6/block-for-sloppy.js
@@ -0,0 +1,199 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+function props(x) {
+  var array = [];
+  for (let p in x) array.push(p);
+  return array.sort();
+}
+
+assertEquals(0, props({}).length);
+assertEquals(1, props({x:1}).length);
+assertEquals(2, props({x:1, y:2}).length);
+
+assertArrayEquals(["x"], props({x:1}));
+assertArrayEquals(["x", "y"], props({x:1, y:2}));
+assertArrayEquals(["x", "y", "zoom"], props({x:1, y:2, zoom:3}));
+
+assertEquals(0, props([]).length);
+assertEquals(1, props([1]).length);
+assertEquals(2, props([1,2]).length);
+
+assertArrayEquals(["0"], props([1]));
+assertArrayEquals(["0", "1"], props([1,2]));
+assertArrayEquals(["0", "1", "2"], props([1,2,3]));
+
+var o = {};
+var a = [];
+let i = "outer_i";
+let s = "outer_s";
+for (let i = 0x0020; i < 0x01ff; i+=2) {
+  let s = 'char:' + String.fromCharCode(i);
+  a.push(s);
+  o[s] = i;
+}
+assertArrayEquals(a, props(o));
+assertEquals(i, "outer_i");
+assertEquals(s, "outer_s");
+
+var a = [];
+assertEquals(0, props(a).length);
+a[Math.pow(2,30)-1] = 0;
+assertEquals(1, props(a).length);
+a[Math.pow(2,31)-1] = 0;
+assertEquals(2, props(a).length);
+a[1] = 0;
+assertEquals(3, props(a).length);
+
+var result = '';
+for (let p in {a : [0], b : 1}) { result += p; }
+assertEquals('ab', result);
+
+var result = '';
+for (let p in {a : {v:1}, b : 1}) { result += p; }
+assertEquals('ab', result);
+
+var result = '';
+for (let p in { get a() {}, b : 1}) { result += p; }
+assertEquals('ab', result);
+
+var result = '';
+for (let p in { get a() {}, set a(x) {}, b : 1}) { result += p; }
+assertEquals('ab', result);
+
+
+// Check that there is exactly one variable without initializer
+// in a for-in statement with let variables.
+assertThrows("function foo() { 'use strict'; for (let in {}) { } }", SyntaxError);
+assertThrows("function foo() { 'use strict'; for (let x = 3 in {}) { } }", SyntaxError);
+assertThrows("function foo() { 'use strict'; for (let x, y in {}) { } }", SyntaxError);
+assertThrows("function foo() { 'use strict'; for (let x = 3, y in {}) { } }", SyntaxError);
+assertThrows("function foo() { 'use strict'; for (let x, y = 4 in {}) { } }", SyntaxError);
+assertThrows("function foo() { 'use strict'; for (let x = 3, y = 4 in {}) { } }", SyntaxError);
+
+
+// In a normal for statement the iteration variable is
+// freshly allocated for each iteration.
+function closures1() {
+  let a = [];
+  for (let i = 0; i < 5; ++i) {
+    a.push(function () { return i; });
+  }
+  for (let j = 0; j < 5; ++j) {
+    assertEquals(j, a[j]());
+  }
+}
+closures1();
+
+
+function closures2() {
+  let a = [], b = [];
+  for (let i = 0, j = 10; i < 5; ++i, ++j) {
+    a.push(function () { return i; });
+    b.push(function () { return j; });
+  }
+  for (let k = 0; k < 5; ++k) {
+    assertEquals(k, a[k]());
+    assertEquals(k + 10, b[k]());
+  }
+}
+closures2();
+
+
+function closure_in_for_init() {
+  let a = [];
+  for (let i = 0, f = function() { return i }; i < 5; ++i) {
+    a.push(f);
+  }
+  for (let k = 0; k < 5; ++k) {
+    assertEquals(0, a[k]());
+  }
+}
+closure_in_for_init();
+
+
+function closure_in_for_cond() {
+  let a = [];
+  for (let i = 0; a.push(function () { return i; }), i < 5; ++i) { }
+  for (let k = 0; k < 5; ++k) {
+    assertEquals(k, a[k]());
+  }
+}
+closure_in_for_cond();
+
+
+function closure_in_for_next() {
+  let a = [];
+  for (let i = 0; i < 5; a.push(function () { return i; }), ++i) { }
+  for (let k = 0; k < 5; ++k) {
+    assertEquals(k + 1, a[k]());
+  }
+}
+closure_in_for_next();
+
+
+// In a for-in statement the iteration variable is fresh
+// for each iteration.
+function closures3(x) {
+  let a = [];
+  for (let p in x) {
+    a.push(function () { return p; });
+  }
+  let k = 0;
+  for (let q in x) {
+    assertEquals(q, a[k]());
+    ++k;
+  }
+}
+closures3({a : [0], b : 1, c : {v : 1}, get d() {}, set e(x) {}});
+
+// Check normal for statement completion values.
+assertEquals(1, eval("for (let i = 0; i < 10; i++) { 1; }"));
+assertEquals(9, eval("for (let i = 0; i < 10; i++) { i; }"));
+assertEquals(undefined, eval("for (let i = 0; false;) { }"));
+assertEquals(undefined, eval("for (const i = 0; false;) { }"));
+assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { }"));
+assertEquals(undefined, eval("for (let i = 0; false;) { i; }"));
+assertEquals(undefined, eval("for (const i = 0; false;) { i; }"));
+assertEquals(undefined, eval("for (let i = 0; true;) { break; }"));
+assertEquals(undefined, eval("for (const i = 0; true;) { break; }"));
+assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { continue; }"));
+assertEquals(undefined, eval("for (let i = 0; true;) { break; i; }"));
+assertEquals(undefined, eval("for (const i = 0; true;) { break; i; }"));
+assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { continue; i; }"));
+assertEquals(0, eval("for (let i = 0; true;) { i; break; }"));
+assertEquals(0, eval("for (const i = 0; true;) { i; break; }"));
+assertEquals(9, eval("for (let i = 0; i < 10; i++) { i; continue; }"));
+assertEquals(
+  undefined, eval("for (let i = 0; true; i++) { i; if (i >= 3) break; }"));
+assertEquals(
+  undefined, eval("for (let i = 0; true; i++) { if (i >= 3) break; i; }"));
+assertEquals(
+  undefined, eval("for (let i = 0; i < 10; i++) { if (i >= 3) continue; i; }"));
+assertEquals(undefined, eval("foo: for (let i = 0; true;) { break foo; }"));
+assertEquals(undefined, eval("foo: for (const i = 0; true;) { break foo; }"));
+assertEquals(3, eval("foo: for (let i = 3; true;) { i; break foo; }"));
diff --git a/test/mjsunit/es6/block-leave-sloppy.js b/test/mjsunit/es6/block-leave-sloppy.js
new file mode 100644
index 0000000..1313026
--- /dev/null
+++ b/test/mjsunit/es6/block-leave-sloppy.js
@@ -0,0 +1,222 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// We want to test the context chain shape.  In each of the tests cases
+// below, the outer with is to force a runtime lookup of the identifier 'x'
+// to actually verify that the inner context has been discarded.  A static
+// lookup of 'x' might accidentally succeed.
+
+{
+  let x = 2;
+  L: {
+    let x = 3;
+    assertEquals(3, x);
+    break L;
+    assertTrue(false);
+  }
+  assertEquals(2, x);
+}
+
+do {
+  let x = 4;
+  assertEquals(4,x);
+  {
+    let x = 5;
+    assertEquals(5, x);
+    continue;
+    assertTrue(false);
+  }
+} while (false);
+
+var caught = false;
+try {
+  {
+    let xx = 18;
+    throw 25;
+    assertTrue(false);
+  }
+} catch (e) {
+  caught = true;
+  assertEquals(25, e);
+  (function () {
+    try {
+      // NOTE: This checks that the block scope containing xx has been
+      // removed from the context chain.
+      eval('xx');
+      assertTrue(false);  // should not reach here
+    } catch (e2) {
+      assertTrue(e2 instanceof ReferenceError);
+    }
+  })();
+}
+assertTrue(caught);
+
+
+(function(x) {
+  label: {
+    let x = 'inner';
+    break label;
+  }
+  assertEquals('outer', eval('x'));
+})('outer');
+
+
+(function(x) {
+  label: {
+    let x = 'middle';
+    {
+      let x = 'inner';
+      break label;
+    }
+  }
+  assertEquals('outer', eval('x'));
+})('outer');
+
+
+(function(x) {
+  for (var i = 0; i < 10; ++i) {
+    let x = 'inner' + i;
+    continue;
+  }
+  assertEquals('outer', eval('x'));
+})('outer');
+
+
+(function(x) {
+  label: for (var i = 0; i < 10; ++i) {
+    let x = 'middle' + i;
+    for (var j = 0; j < 10; ++j) {
+      let x = 'inner' + j;
+      continue label;
+    }
+  }
+  assertEquals('outer', eval('x'));
+})('outer');
+
+
+(function(x) {
+  try {
+    let x = 'inner';
+    throw 0;
+  } catch (e) {
+    assertEquals('outer', eval('x'));
+  }
+})('outer');
+
+
+(function(x) {
+  try {
+    let x = 'middle';
+    {
+      let x = 'inner';
+      throw 0;
+    }
+  } catch (e) {
+    assertEquals('outer', eval('x'));
+  }
+})('outer');
+
+
+try {
+  (function(x) {
+    try {
+      let x = 'inner';
+      throw 0;
+    } finally {
+      assertEquals('outer', eval('x'));
+    }
+  })('outer');
+} catch (e) {
+  if (e instanceof MjsUnitAssertionError) throw e;
+}
+
+
+try {
+  (function(x) {
+    try {
+      let x = 'middle';
+      {
+        let x = 'inner';
+        throw 0;
+      }
+    } finally {
+      assertEquals('outer', eval('x'));
+    }
+  })('outer');
+} catch (e) {
+  if (e instanceof MjsUnitAssertionError) throw e;
+}
+
+
+// Verify that the context is correctly set in the stack frame after exiting
+// from eval.
+function f() {}
+
+(function(x) {
+  label: {
+    let x = 'inner';
+    break label;
+  }
+  f();  // The context could be restored from the stack after the call.
+  assertEquals('outer', eval('x'));
+})('outer');
+
+
+(function(x) {
+  for (var i = 0; i < 10; ++i) {
+    let x = 'inner';
+    continue;
+  }
+  f();
+  assertEquals('outer', eval('x'));
+})('outer');
+
+
+(function(x) {
+  try {
+    let x = 'inner';
+    throw 0;
+  } catch (e) {
+    f();
+    assertEquals('outer', eval('x'));
+  }
+})('outer');
+
+
+try {
+  (function(x) {
+    try {
+      let x = 'inner';
+      throw 0;
+    } finally {
+      f();
+      assertEquals('outer', eval('x'));
+    }
+  })('outer');
+} catch (e) {
+  if (e instanceof MjsUnitAssertionError) throw e;
+}
diff --git a/test/mjsunit/es6/block-let-contextual-sloppy.js b/test/mjsunit/es6/block-let-contextual-sloppy.js
index ac7bca1..8282d77 100644
--- a/test/mjsunit/es6/block-let-contextual-sloppy.js
+++ b/test/mjsunit/es6/block-let-contextual-sloppy.js
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-sloppy --harmony-sloppy-let
-
 // let is usable as a variable with var, but not let or ES6 const
 
 (function (){
diff --git a/test/mjsunit/es6/block-let-crankshaft-sloppy.js b/test/mjsunit/es6/block-let-crankshaft-sloppy.js
new file mode 100644
index 0000000..b5e81f7
--- /dev/null
+++ b/test/mjsunit/es6/block-let-crankshaft-sloppy.js
@@ -0,0 +1,482 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+// Check that the following functions are optimizable.
+var functions = [ f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14,
+                  f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26,
+                  f27, f28, f29, f30, f31, f32, f33];
+
+for (var i = 0; i < functions.length; ++i) {
+  var func = functions[i];
+  print("Testing:");
+  print(func);
+  for (var j = 0; j < 10; ++j) {
+    func(12);
+  }
+  %OptimizeFunctionOnNextCall(func);
+  func(12);
+  assertOptimized(func);
+}
+
+function f1() { }
+
+function f2(x) { }
+
+function f3() {
+  let x;
+}
+
+function f4() {
+  function foo() {
+  }
+}
+
+function f5() {
+  let x = 1;
+}
+
+function f6() {
+  const x = 1;
+}
+
+function f7(x) {
+  return x;
+}
+
+function f8() {
+  let x;
+  return x;
+}
+
+function f9() {
+  function x() {
+  }
+  return x;
+}
+
+function f10(x) {
+  x = 1;
+}
+
+function f11() {
+  let x;
+  x = 1;
+}
+
+function f12() {
+  function x() {};
+  x = 1;
+}
+
+function f13(x) {
+  (function() { x; });
+}
+
+function f14() {
+  let x;
+  (function() { x; });
+}
+
+function f15() {
+  function x() {
+  }
+  (function() { x; });
+}
+
+function f16() {
+  let x = 1;
+  (function() { x; });
+}
+
+function f17() {
+  const x = 1;
+  (function() { x; });
+}
+
+function f18(x) {
+  return x;
+  (function() { x; });
+}
+
+function f19() {
+  let x;
+  return x;
+  (function() { x; });
+}
+
+function f20() {
+  function x() {
+  }
+  return x;
+  (function() { x; });
+}
+
+function f21(x) {
+  x = 1;
+  (function() { x; });
+}
+
+function f22() {
+  let x;
+  x = 1;
+  (function() { x; });
+}
+
+function f23() {
+  function x() { }
+  x = 1;
+  (function() { x; });
+}
+
+function f24() {
+  let x = 1;
+  {
+    let x = 2;
+    {
+      let x = 3;
+      assertEquals(3, x);
+    }
+    assertEquals(2, x);
+  }
+  assertEquals(1, x);
+}
+
+function f25() {
+  {
+    let x = 2;
+    L: {
+      let x = 3;
+      assertEquals(3, x);
+      break L;
+      assertTrue(false);
+    }
+    assertEquals(2, x);
+  }
+  assertTrue(true);
+}
+
+function f26() {
+  {
+    let x = 1;
+    L: {
+      let x = 2;
+      {
+        let x = 3;
+        assertEquals(3, x);
+        break L;
+        assertTrue(false);
+      }
+      assertTrue(false);
+    }
+    assertEquals(1, x);
+  }
+}
+
+
+function f27() {
+  do {
+    let x = 4;
+    assertEquals(4,x);
+    {
+      let x = 5;
+      assertEquals(5, x);
+      continue;
+      assertTrue(false);
+    }
+  } while (false);
+}
+
+function f28() {
+  label: for (var i = 0; i < 10; ++i) {
+    let x = 'middle' + i;
+    for (var j = 0; j < 10; ++j) {
+      let x = 'inner' + j;
+      continue label;
+    }
+  }
+}
+
+function f29() {
+  // Verify that the context is correctly set in the stack frame after exiting
+  // from with.
+
+  let x = 'outer';
+  label: {
+    let x = 'inner';
+    break label;
+  }
+  f();  // The context could be restored from the stack after the call.
+  assertEquals('outer', x);
+
+  function f() {
+    assertEquals('outer', x);
+  };
+}
+
+function f30() {
+  let x = 'outer';
+  for (var i = 0; i < 10; ++i) {
+    let x = 'inner';
+    continue;
+  }
+  f();
+  assertEquals('outer', x);
+
+  function f() {
+    assertEquals('outer', x);
+  };
+}
+
+function f31() {
+  {
+    let x = 'outer';
+    label: for (var i = 0; assertEquals('outer', x), i < 10; ++i) {
+      let x = 'middle' + i;
+      {
+        let x = 'inner' + j;
+        continue label;
+      }
+    }
+    assertEquals('outer', x);
+  }
+}
+
+var c = true;
+
+function f32() {
+  {
+    let x = 'outer';
+    L: {
+      {
+        let x = 'inner';
+        if (c) {
+          break L;
+        }
+      }
+      foo();
+    }
+  }
+
+  function foo() {
+    return 'bar';
+  }
+}
+
+function f33() {
+  {
+    let x = 'outer';
+    L: {
+      {
+        let x = 'inner';
+        if (c) {
+          break L;
+        }
+        foo();
+      }
+    }
+  }
+
+  function foo() {
+    return 'bar';
+  }
+}
+
+function TestThrow() {
+  function f() {
+    let x = 'outer';
+    {
+      let x = 'inner';
+      throw x;
+    }
+  }
+  for (var i = 0; i < 5; i++) {
+    try {
+      f();
+    } catch (e) {
+      assertEquals('inner', e);
+    }
+  }
+  %OptimizeFunctionOnNextCall(f);
+  try {
+    f();
+  } catch (e) {
+    assertEquals('inner', e);
+  }
+  assertOptimized(f);
+}
+
+TestThrow();
+
+// Test that temporal dead zone semantics for function and block scoped
+// let bindings are handled by the optimizing compiler.
+
+function TestFunctionLocal(s) {
+  'use strict';
+  var func = eval("(function baz(){" + s + "; })");
+  print("Testing:");
+  print(func);
+  for (var i = 0; i < 5; ++i) {
+    try {
+      func();
+      assertUnreachable();
+    } catch (e) {
+      assertInstanceof(e, ReferenceError);
+    }
+  }
+  %OptimizeFunctionOnNextCall(func);
+  try {
+    func();
+    assertUnreachable();
+  } catch (e) {
+    assertInstanceof(e, ReferenceError);
+  }
+}
+
+function TestFunctionContext(s) {
+  'use strict';
+  var func = eval("(function baz(){ " + s + "; (function() { x; }); })");
+  print("Testing:");
+  print(func);
+  for (var i = 0; i < 5; ++i) {
+    print(i);
+    try {
+      func();
+      assertUnreachable();
+    } catch (e) {
+      assertInstanceof(e, ReferenceError);
+    }
+  }
+  print("optimize");
+  %OptimizeFunctionOnNextCall(func);
+  try {
+    print("call");
+    func();
+    assertUnreachable();
+  } catch (e) {
+    print("catch");
+    assertInstanceof(e, ReferenceError);
+  }
+}
+
+function TestBlockLocal(s) {
+  'use strict';
+  var func = eval("(function baz(){ { " + s + "; } })");
+  print("Testing:");
+  print(func);
+  for (var i = 0; i < 5; ++i) {
+    try {
+      func();
+      assertUnreachable();
+    } catch (e) {
+      assertInstanceof(e, ReferenceError);
+    }
+  }
+  %OptimizeFunctionOnNextCall(func);
+  try {
+    func();
+    assertUnreachable();
+  } catch (e) {
+    assertInstanceof(e, ReferenceError);
+  }
+}
+
+function TestBlockContext(s) {
+  'use strict';
+  var func = eval("(function baz(){ { " + s + "; (function() { x; }); } })");
+  print("Testing:");
+  print(func);
+  for (var i = 0; i < 5; ++i) {
+    print(i);
+    try {
+      func();
+      assertUnreachable();
+    } catch (e) {
+      assertInstanceof(e, ReferenceError);
+    }
+  }
+  print("optimize");
+  %OptimizeFunctionOnNextCall(func);
+  try {
+    print("call");
+    func();
+    assertUnreachable();
+  } catch (e) {
+    print("catch");
+    assertInstanceof(e, ReferenceError);
+  }
+}
+
+function TestAll(s) {
+  TestFunctionLocal(s);
+  TestFunctionContext(s);
+  TestBlockLocal(s);
+  TestBlockContext(s);
+}
+
+// Use before initialization in declaration statement.
+TestAll('let x = x + 1');
+TestAll('let x = x += 1');
+TestAll('let x = x++');
+TestAll('let x = ++x');
+TestAll('const x = x + 1');
+
+// Use before initialization in prior statement.
+TestAll('x + 1; let x;');
+TestAll('x = 1; let x;');
+TestAll('x += 1; let x;');
+TestAll('++x; let x;');
+TestAll('x++; let x;');
+TestAll('let y = x; const x = 1;');
+
+
+function f(x) {
+  let y = x + 42;
+  return y;
+}
+
+function g(x) {
+  {
+    let y = x + 42;
+    return y;
+  }
+}
+
+for (var i=0; i<10; i++) {
+  f(i);
+  g(i);
+}
+
+%OptimizeFunctionOnNextCall(f);
+%OptimizeFunctionOnNextCall(g);
+
+f(12);
+g(12);
+
+assertTrue(%GetOptimizationStatus(f) != 2);
+assertTrue(%GetOptimizationStatus(g) != 2);
diff --git a/test/mjsunit/es6/block-let-declaration-sloppy.js b/test/mjsunit/es6/block-let-declaration-sloppy.js
new file mode 100644
index 0000000..ea0e39b
--- /dev/null
+++ b/test/mjsunit/es6/block-let-declaration-sloppy.js
@@ -0,0 +1,172 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test let declarations in various settings.
+
+// Global
+let x;
+let y = 2;
+const z = 4;
+class c { static foo() { return 1; } }
+
+// Block local
+{
+  let y;
+  let x = 3;
+  const z = 5;
+  class c { static foo() { return 2; } }
+}
+
+assertEquals(undefined, x);
+assertEquals(2,y);
+assertEquals(4,z);
+assertEquals(1, c.foo());
+
+if (true) {
+  let y;
+  assertEquals(undefined, y);
+}
+
+// Invalid declarations are early errors in harmony mode and thus should trigger
+// an exception in eval code during parsing, before even compiling or executing
+// the code. Thus the generated function is not called here.
+function TestLocalThrows(str, expect) {
+  assertThrows("(function(arg){ 'use strict'; " + str + "})", expect);
+}
+
+function TestLocalDoesNotThrow(str) {
+  assertDoesNotThrow("(function(arg){ 'use strict'; " + str + "})()");
+}
+
+// Test let declarations in statement positions.
+TestLocalThrows("if (true) let x;", SyntaxError);
+TestLocalThrows("if (true) {} else let x;", SyntaxError);
+TestLocalThrows("do let x; while (false)", SyntaxError);
+TestLocalThrows("while (false) let x;", SyntaxError);
+TestLocalThrows("label: let x;", SyntaxError);
+TestLocalThrows("for (;false;) let x;", SyntaxError);
+TestLocalDoesNotThrow("switch (true) { case true: let x; }");
+TestLocalDoesNotThrow("switch (true) { default: let x; }");
+
+// Test const declarations with initialisers in statement positions.
+TestLocalThrows("if (true) const x = 1;", SyntaxError);
+TestLocalThrows("if (true) {} else const x = 1;", SyntaxError);
+TestLocalThrows("do const x = 1; while (false)", SyntaxError);
+TestLocalThrows("while (false) const x = 1;", SyntaxError);
+TestLocalThrows("label: const x = 1;", SyntaxError);
+TestLocalThrows("for (;false;) const x = 1;", SyntaxError);
+TestLocalDoesNotThrow("switch (true) { case true: const x = 1; }");
+TestLocalDoesNotThrow("switch (true) { default: const x = 1; }");
+
+// Test const declarations without initialisers.
+TestLocalThrows("const x;", SyntaxError);
+TestLocalThrows("const x = 1, y;", SyntaxError);
+TestLocalThrows("const x, y = 1;", SyntaxError);
+
+// Test const declarations without initialisers in statement positions.
+TestLocalThrows("if (true) const x;", SyntaxError);
+TestLocalThrows("if (true) {} else const x;", SyntaxError);
+TestLocalThrows("do const x; while (false)", SyntaxError);
+TestLocalThrows("while (false) const x;", SyntaxError);
+TestLocalThrows("label: const x;", SyntaxError);
+TestLocalThrows("for (;false;) const x;", SyntaxError);
+TestLocalThrows("switch (true) { case true: const x; }", SyntaxError);
+TestLocalThrows("switch (true) { default: const x; }", SyntaxError);
+
+// Test var declarations in statement positions.
+TestLocalDoesNotThrow("if (true) var x;");
+TestLocalDoesNotThrow("if (true) {} else var x;");
+TestLocalDoesNotThrow("do var x; while (false)");
+TestLocalDoesNotThrow("while (false) var x;");
+TestLocalDoesNotThrow("label: var x;");
+TestLocalDoesNotThrow("for (;false;) var x;");
+TestLocalDoesNotThrow("switch (true) { case true: var x; }");
+TestLocalDoesNotThrow("switch (true) { default: var x; }");
+
+// Test class declarations with initialisers in statement positions.
+TestLocalThrows("if (true) class x { };", SyntaxError);
+TestLocalThrows("if (true) {} else class x { };", SyntaxError);
+TestLocalThrows("do class x { }; while (false)", SyntaxError);
+TestLocalThrows("while (false) class x { };", SyntaxError);
+TestLocalThrows("label: class x { };", SyntaxError);
+TestLocalThrows("for (;false;) class x { };", SyntaxError);
+TestLocalDoesNotThrow("switch (true) { case true: class x { }; }");
+TestLocalDoesNotThrow("switch (true) { default: class x { }; }");
+
+// Test that redeclarations of functions are only allowed in outermost scope.
+TestLocalThrows("{ let f; var f; }");
+TestLocalThrows("{ var f; let f; }");
+TestLocalThrows("{ function f() {} let f; }");
+TestLocalThrows("{ let f; function f() {} }");
+TestLocalThrows("{ function f() {} var f; }");
+TestLocalThrows("{ var f; function f() {} }");
+TestLocalThrows("{ function f() {} class f {} }");
+TestLocalThrows("{ class f {}; function f() {} }");
+TestLocalThrows("{ function f() {} function f() {} }");
+TestLocalThrows("function f() {} let f;");
+TestLocalThrows("let f; function f() {}");
+TestLocalThrows("function f() {} class f {}");
+TestLocalThrows("class f {}; function f() {}");
+TestLocalDoesNotThrow("function arg() {}");
+TestLocalDoesNotThrow("function f() {} var f;");
+TestLocalDoesNotThrow("var f; function f() {}");
+TestLocalDoesNotThrow("function f() {} function f() {}");
+
+function g(f) {
+  function f() { return 1 }
+  return f()
+}
+assertEquals(1, g(function() { return 2 }))
+
+
+// Test function declarations in source element and
+// sloppy statement positions.
+function f() {
+  // Sloppy source element positions.
+  function g0() {
+    "use strict";
+    // Strict source element positions.
+    function h() { }
+    {
+      function h1() { }
+    }
+  }
+  {
+    function g1() { }
+  }
+}
+f();
+
+// Test function declarations in statement position in strict mode.
+TestLocalThrows("function f() { if (true) function g() {} }", SyntaxError);
+TestLocalThrows("function f() { if (true) {} else function g() {} }", SyntaxError);
+TestLocalThrows("function f() { do function g() {} while (false) }", SyntaxError);
+TestLocalThrows("function f() { while (false) function g() {} }", SyntaxError);
+TestLocalThrows("function f() { label: function g() {} }", SyntaxError);
+TestLocalThrows("function f() { for (;false;) function g() {} }", SyntaxError);
+TestLocalDoesNotThrow("function f() { switch (true) { case true: function g() {} } }");
+TestLocalDoesNotThrow("function f() { switch (true) { default: function g() {} } }");
diff --git a/test/mjsunit/es6/block-let-semantics-sloppy.js b/test/mjsunit/es6/block-let-semantics-sloppy.js
new file mode 100644
index 0000000..4102ec8
--- /dev/null
+++ b/test/mjsunit/es6/block-let-semantics-sloppy.js
@@ -0,0 +1,191 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test temporal dead zone semantics of let bound variables in
+// function and block scopes.
+
+function TestFunctionLocal(s) {
+  try {
+    eval("(function(){" + s + "; })")();
+  } catch (e) {
+    assertInstanceof(e, ReferenceError);
+    return;
+  }
+  assertUnreachable();
+}
+
+function TestBlockLocal(s,e) {
+  try {
+    eval("(function(){ {" + s + ";} })")();
+  } catch (e) {
+    assertInstanceof(e, ReferenceError);
+    return;
+  }
+  assertUnreachable();
+}
+
+
+function TestAll(s) {
+  TestBlockLocal(s);
+  TestFunctionLocal(s);
+}
+
+// Use before initialization in declaration statement.
+TestAll('let x = x + 1');
+TestAll('let x = x += 1');
+TestAll('let x = x++');
+TestAll('let x = ++x');
+TestAll('const x = x + 1');
+
+// Use before initialization in prior statement.
+TestAll('x + 1; let x;');
+TestAll('x = 1; let x;');
+TestAll('x += 1; let x;');
+TestAll('++x; let x;');
+TestAll('x++; let x;');
+TestAll('let y = x; const x = 1;');
+TestAll('let y = x; class x {}');
+
+TestAll('f(); let x; function f() { return x + 1; }');
+TestAll('f(); let x; function f() { x = 1; }');
+TestAll('f(); let x; function f() { x += 1; }');
+TestAll('f(); let x; function f() { ++x; }');
+TestAll('f(); let x; function f() { x++; }');
+TestAll('f(); const x = 1; function f() { return x; }');
+TestAll('f(); class x { }; function f() { return x; }');
+
+TestAll('f()(); let x; function f() { return function() { return x + 1; } }');
+TestAll('f()(); let x; function f() { return function() { x = 1; } }');
+TestAll('f()(); let x; function f() { return function() { x += 1; } }');
+TestAll('f()(); let x; function f() { return function() { ++x; } }');
+TestAll('f()(); let x; function f() { return function() { x++; } }');
+TestAll('f()(); const x = 1; function f() { return function() { return x; } }');
+TestAll('f()(); class x { }; function f() { return function() { return x; } }');
+
+for (var kw of ['let x = 2', 'const x = 2', 'class x { }']) {
+  // Use before initialization with a dynamic lookup.
+  TestAll(`eval("x"); ${kw};`);
+  TestAll(`eval("x + 1;"); ${kw};`);
+  TestAll(`eval("x = 1;"); ${kw};`);
+  TestAll(`eval("x += 1;"); ${kw};`);
+  TestAll(`eval("++x;"); ${kw};`);
+  TestAll(`eval("x++;"); ${kw};`);
+
+  // Use before initialization with check for eval-shadowed bindings.
+  TestAll(`function f() { eval("var y = 2;"); x + 1; }; f(); ${kw};`);
+  TestAll(`function f() { eval("var y = 2;"); x = 1; }; f(); ${kw};`);
+  TestAll(`function f() { eval("var y = 2;"); x += 1; }; f(); ${kw};`);
+  TestAll(`function f() { eval("var y = 2;"); ++x; }; f(); ${kw};`);
+  TestAll(`function f() { eval("var y = 2;"); x++; }; f(); ${kw};`);
+}
+
+// Test that variables introduced by function declarations are created and
+// initialized upon entering a function / block scope.
+function f() {
+  {
+    assertEquals(2, g1());
+    assertEquals(2, eval("g1()"));
+
+    // block scoped function declaration
+    function g1() {
+      return 2;
+    }
+  }
+
+  assertEquals(3, g2());
+  assertEquals(3, eval("g2()"));
+  // function scoped function declaration
+  function g2() {
+    return 3;
+  }
+}
+f();
+
+// Test that a function declaration introduces a block scoped variable
+// and no function hoisting if there is a conflict.
+TestFunctionLocal('{ function k() { return 0; } }; k(); let k;');
+
+// Test that a function declaration sees the scope it resides in.
+function f2() {
+  let m, n, o, p;
+  {
+    m = g;
+    function g() {
+      return a;
+    }
+    let a = 1;
+  }
+  assertEquals(1, m());
+
+  try {
+    throw 2;
+  } catch(b) {
+    n = h;
+    function h() {
+      return b + c;
+    }
+    let c = 3;
+  }
+  assertEquals(5, n());
+
+  {
+    o = i;
+    function i() {
+      return d;
+    }
+    let d = 4;
+  }
+  assertEquals(4, o());
+
+  try {
+    throw 5;
+  } catch(e) {
+    p = j;
+    function j() {
+      return e + f;
+    }
+    let f = 6;
+  }
+  assertEquals(11, p());
+}
+f2();
+
+// Test that resolution of let bound variables works with scopes that call eval.
+function outer() {
+  function middle() {
+    function inner() {
+      return x;
+    }
+    eval("1 + 1");
+    return x + inner();
+  }
+
+  let x = 1;
+  return middle();
+}
+
+assertEquals(2, outer());
diff --git a/test/mjsunit/es6/block-non-strict-errors.js b/test/mjsunit/es6/block-non-strict-errors.js
deleted file mode 100644
index db7f558..0000000
--- a/test/mjsunit/es6/block-non-strict-errors.js
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --no-harmony-sloppy-let --no-harmony-sloppy-function
-// Flags: --no-harmony-sloppy
-
-function CheckError(source) {
-  var exception = null;
-  try {
-    eval(source);
-  } catch (e) {
-    exception = e;
-  }
-  assertNotNull(exception);
-  assertEquals(
-      "Block-scoped declarations (let, const, function, class) not yet supported outside strict mode",
-      exception.message);
-}
-
-
-function CheckOk(source) {
-  eval(source);
-}
-
-CheckError("let x = 1;");
-CheckError("{ let x = 1; }");
-CheckError("function f() { let x = 1; }");
-CheckError("for (let x = 1; x < 1; x++) {}");
-CheckError("for (let x of []) {}");
-CheckError("for (let x in []) {}");
-CheckError("class C {}");
-CheckError("class C extends Array {}");
-CheckError("(class {});");
-CheckError("(class extends Array {});");
-CheckError("(class C {});");
-CheckError("(class C exends Array {});");
-
-CheckOk("let = 1;");
-CheckOk("{ let = 1; }");
-CheckOk("function f() { let = 1; }");
-CheckOk("for (let = 1; let < 1; let++) {}");
diff --git a/test/mjsunit/es6/block-scope-class.js b/test/mjsunit/es6/block-scope-class.js
index 351feaa..7bbd49d 100644
--- a/test/mjsunit/es6/block-scope-class.js
+++ b/test/mjsunit/es6/block-scope-class.js
@@ -4,8 +4,6 @@
 
 // Test for conflicting variable bindings.
 
-// Flags: --harmony-sloppy --harmony-sloppy-function
-
 function AssertEqualsStrictAndSloppy(value, code) {
   assertEquals(value, eval("(function() {" + code + "})()"));
   assertEquals(value, eval("(function() { 'use strict'; " + code + "})()"));
diff --git a/test/mjsunit/es6/block-scoping-sloppy.js b/test/mjsunit/es6/block-scoping-sloppy.js
new file mode 100644
index 0000000..f5c5a63
--- /dev/null
+++ b/test/mjsunit/es6/block-scoping-sloppy.js
@@ -0,0 +1,309 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+// Test functionality of block scopes.
+
+// Hoisting of var declarations.
+function f1() {
+  {
+    var x = 1;
+    var y;
+  }
+  assertEquals(1, x)
+  assertEquals(undefined, y)
+}
+for (var j = 0; j < 5; ++j) f1();
+%OptimizeFunctionOnNextCall(f1);
+f1();
+assertTrue(%GetOptimizationStatus(f1) != 2);
+
+// Dynamic lookup in and through block contexts.
+function f2(one) {
+  var x = one + 1;
+  let y = one + 2;
+  const u = one + 4;
+  class a { static foo() { return one + 6; } }
+  {
+    let z = one + 3;
+    const v = one + 5;
+    class b { static foo() { return one + 7; } }
+    assertEquals(1, eval('one'));
+    assertEquals(2, eval('x'));
+    assertEquals(3, eval('y'));
+    assertEquals(4, eval('z'));
+    assertEquals(5, eval('u'));
+    assertEquals(6, eval('v'));
+    assertEquals(7, eval('a.foo()'));
+    assertEquals(8, eval('b.foo()'));
+  }
+}
+
+f2(1);
+
+// Lookup in and through block contexts.
+function f3(one) {
+  var x = one + 1;
+  let y = one + 2;
+  const u = one + 4;
+  class a { static foo() { return one + 6; } }
+  {
+    let z = one + 3;
+    const v = one + 5;
+    class b { static foo() { return one + 7; } }
+    assertEquals(1, one);
+    assertEquals(2, x);
+    assertEquals(3, y);
+    assertEquals(4, z);
+    assertEquals(5, u);
+    assertEquals(6, v);
+    assertEquals(7, a.foo());
+    assertEquals(8, b.foo());
+  }
+}
+for (var j = 0; j < 5; ++j) f3(1);
+%OptimizeFunctionOnNextCall(f3);
+f3(1);
+
+
+
+// Dynamic lookup from closure.
+function f4(one) {
+  var x = one + 1;
+  let y = one + 2;
+  const u = one + 4;
+  class a { static foo() { return one + 6; } }
+  {
+    let z = one + 3;
+    const v = one + 5;
+    class b { static foo() { return one + 7; } }
+    function f() {
+      assertEquals(1, eval('one'));
+      assertEquals(2, eval('x'));
+      assertEquals(3, eval('y'));
+      assertEquals(4, eval('z'));
+      assertEquals(5, eval('u'));
+      assertEquals(6, eval('v'));
+      assertEquals(7, eval('a.foo()'));
+      assertEquals(8, eval('b.foo()'));
+    }
+    f();
+  }
+}
+f4(1);
+
+
+// Lookup from closure.
+function f5(one) {
+  var x = one + 1;
+  let y = one + 2;
+  const u = one + 4;
+  class a { static foo() { return one + 6; } }
+  {
+    let z = one + 3;
+    const v = one + 5;
+    class b { static foo() { return one + 7; } }
+    function f() {
+      assertEquals(1, one);
+      assertEquals(2, x);
+      assertEquals(3, y);
+      assertEquals(4, z);
+      assertEquals(5, u);
+      assertEquals(6, v);
+      assertEquals(7, a.foo());
+      assertEquals(8, b.foo());
+    }
+    f();
+  }
+}
+f5(1);
+
+
+// Return from block.
+function f6() {
+  let x = 1;
+  const u = 3;
+  {
+    let y = 2;
+    const v = 4;
+    return x + y;
+  }
+}
+assertEquals(3, f6(6));
+
+
+// Variable shadowing and lookup.
+function f7(a) {
+  let b = 1;
+  var c = 1;
+  var d = 1;
+  const e = 1;
+  class f { static foo() { return 1; } }
+  { // let variables shadowing argument, let, const, class and var variables
+    let a = 2;
+    let b = 2;
+    let c = 2;
+    let e = 2;
+    let f = 2;
+    assertEquals(2,a);
+    assertEquals(2,b);
+    assertEquals(2,c);
+    assertEquals(2,e);
+    assertEquals(2,f);
+  }
+  { // const variables shadowing argument, let, const and var variables
+    const a = 2;
+    const b = 2;
+    const c = 2;
+    const e = 2;
+    const f = 2;
+    assertEquals(2,a);
+    assertEquals(2,b);
+    assertEquals(2,c);
+    assertEquals(2,e);
+    assertEquals(2,f);
+  }
+  { // class variables shadowing argument, let, const and var variables
+    class a { static foo() { return 2; } }
+    class b { static foo() { return 2; } }
+    class c { static foo() { return 2; } }
+    class d { static foo() { return 2; } }
+    class e { static foo() { return 2; } }
+    class f { static foo() { return 2; } }
+    assertEquals(2,a.foo());
+    assertEquals(2,b.foo());
+    assertEquals(2,c.foo());
+    assertEquals(2,e.foo());
+    assertEquals(2,f.foo());
+  }
+  try {
+    throw 'stuff1';
+  } catch (a) {
+    assertEquals('stuff1',a);
+    // catch variable shadowing argument
+    a = 2;
+    assertEquals(2,a);
+    {
+      // let variable shadowing catch variable
+      let a = 3;
+      assertEquals(3,a);
+      try {
+        throw 'stuff2';
+      } catch (a) {
+        assertEquals('stuff2',a);
+        // catch variable shadowing let variable
+        a = 4;
+        assertEquals(4,a);
+      }
+      assertEquals(3,a);
+    }
+    assertEquals(2,a);
+  }
+  try {
+    throw 'stuff3';
+  } catch (c) {
+    // catch variable shadowing var variable
+    assertEquals('stuff3',c);
+    {
+      // const variable shadowing catch variable
+      const c = 3;
+      assertEquals(3,c);
+    }
+    assertEquals('stuff3',c);
+    try {
+      throw 'stuff4';
+    } catch(c) {
+      assertEquals('stuff4',c);
+      // catch variable shadowing catch variable
+      c = 3;
+      assertEquals(3,c);
+    }
+    (function(c) {
+      // argument shadowing catch variable
+      c = 3;
+      assertEquals(3,c);
+    })();
+    assertEquals('stuff3', c);
+    (function() {
+      // var variable shadowing catch variable
+      var c = 3;
+    })();
+    assertEquals('stuff3', c);
+    c = 2;
+  }
+  assertEquals(1,c);
+  (function(a,b,c,e,f) {
+    // arguments shadowing argument, let, const, class and var variable
+    a = 2;
+    b = 2;
+    c = 2;
+    e = 2;
+    f = 2;
+    assertEquals(2,a);
+    assertEquals(2,b);
+    assertEquals(2,c);
+    assertEquals(2,e);
+    assertEquals(2,f);
+    // var variable shadowing var variable
+    var d = 2;
+  })(1,1);
+  assertEquals(1,a);
+  assertEquals(1,b);
+  assertEquals(1,c);
+  assertEquals(1,d);
+  assertEquals(1,e);
+  assertEquals(1,f.foo());
+}
+f7(1);
+
+
+// Ensure let and const variables are block local
+// and var variables function local.
+function f8() {
+  var let_accessors = [];
+  var var_accessors = [];
+  var const_accessors = [];
+  var class_accessors = [];
+  for (var i = 0; i < 10; i++) {
+    let x = i;
+    var y = i;
+    const z = i;
+    class a { static foo() { return x; } }
+    let_accessors[i] = function() { return x; }
+    var_accessors[i] = function() { return y; }
+    const_accessors[i] = function() { return z; }
+    class_accessors[i] = function() { return a; }
+  }
+  for (var j = 0; j < 10; j++) {
+    y = j + 10;
+    assertEquals(j, let_accessors[j]());
+    assertEquals(y, var_accessors[j]());
+    assertEquals(j, const_accessors[j]());
+    assertEquals(j, class_accessors[j]().foo());
+  }
+}
+f8();
diff --git a/test/mjsunit/es6/block-scoping-top-level-sloppy.js b/test/mjsunit/es6/block-scoping-top-level-sloppy.js
new file mode 100644
index 0000000..2a3b903
--- /dev/null
+++ b/test/mjsunit/es6/block-scoping-top-level-sloppy.js
@@ -0,0 +1,33 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --min-preparse-length=0
+
+let xxx = 1;
+let f = undefined;
+{
+  let inner_x = xxx;
+  f = function() { return inner_x; };
+}
+
+assertSame(1, f());
+
+xxx = 42;
+{
+  f = function() { return inner_x1; };
+  let inner_x1 = xxx;
+}
+
+assertSame(42, f());
+
+xxx = 31;
+{
+  let inner_x1 = xxx;
+  try {
+    throw new Error();
+  } catch (e) {
+    f = function() { return inner_x1; };
+  }
+}
+assertSame(31, f());
diff --git a/test/mjsunit/es6/block-sloppy-function.js b/test/mjsunit/es6/block-sloppy-function.js
new file mode 100644
index 0000000..41063b4
--- /dev/null
+++ b/test/mjsunit/es6/block-sloppy-function.js
@@ -0,0 +1,298 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Test Annex B 3.3 semantics for functions declared in blocks in sloppy mode.
+// http://www.ecma-international.org/ecma-262/6.0/#sec-block-level-function-declarations-web-legacy-compatibility-semantics
+
+(function overridingLocalFunction() {
+  var x = [];
+  assertEquals('function', typeof f);
+  function f() {
+    x.push(1);
+  }
+  f();
+  {
+    f();
+    function f() {
+      x.push(2);
+    }
+    f();
+  }
+  f();
+  {
+    f();
+    function f() {
+      x.push(3);
+    }
+    f();
+  }
+  f();
+  assertArrayEquals([1, 2, 2, 2, 3, 3, 3], x);
+})();
+
+(function newFunctionBinding() {
+  var x = [];
+  assertEquals('undefined', typeof f);
+  {
+    f();
+    function f() {
+      x.push(2);
+    }
+    f();
+  }
+  f();
+  {
+    f();
+    function f() {
+      x.push(3);
+    }
+    f();
+  }
+  f();
+  assertArrayEquals([2, 2, 2, 3, 3, 3], x);
+})();
+
+(function shadowingLetDoesntBind() {
+  let f = 1;
+  assertEquals(1, f);
+  {
+    let y = 3;
+    function f() {
+      y = 2;
+    }
+    f();
+    assertEquals(2, y);
+  }
+  assertEquals(1, f);
+})();
+
+(function shadowingClassDoesntBind() {
+  class f { }
+  assertEquals('class f { }', f.toString());
+  {
+    let y = 3;
+    function f() {
+      y = 2;
+    }
+    f();
+    assertEquals(2, y);
+  }
+  assertEquals('class f { }', f.toString());
+})();
+
+(function shadowingConstDoesntBind() {
+  const f = 1;
+  assertEquals(1, f);
+  {
+    let y = 3;
+    function f() {
+      y = 2;
+    }
+    f();
+    assertEquals(2, y);
+  }
+  assertEquals(1, f);
+})();
+
+(function shadowingVarBinds() {
+  var f = 1;
+  assertEquals(1, f);
+  {
+    let y = 3;
+    function f() {
+      y = 2;
+    }
+    f();
+    assertEquals(2, y);
+  }
+  assertEquals('function', typeof f);
+})();
+
+(function conditional() {
+  if (true) {
+    function f() { return 1; }
+  } else {
+    function f() { return 2; }
+  }
+  assertEquals(1, f());
+
+  if (false) {
+    function g() { return 1; }
+  } else {
+    function g() { return 2; }
+  }
+  assertEquals(2, g());
+})();
+
+(function skipExecution() {
+  {
+    function f() { return 1; }
+  }
+  assertEquals(1, f());
+  {
+    function f() { return 2; }
+  }
+  assertEquals(2, f());
+  L: {
+    assertEquals(3, f());
+    break L;
+    function f() { return 3; }
+  }
+  assertEquals(2, f());
+})();
+
+// Test that shadowing arguments is fine
+(function shadowArguments(x) {
+  assertArrayEquals([1], arguments);
+  {
+    assertEquals('function', typeof arguments);
+    function arguments() {}
+    assertEquals('function', typeof arguments);
+  }
+  assertEquals('function', typeof arguments);
+})(1);
+
+// Shadow function parameter
+(function shadowParameter(x) {
+  assertEquals(1, x);
+  {
+    function x() {}
+  }
+  assertEquals('function', typeof x);
+})(1);
+
+// Shadow function parameter
+(function shadowDefaultParameter(x = 0) {
+  assertEquals(1, x);
+  {
+    function x() {}
+  }
+  // TODO(littledan): Once destructured parameters are no longer
+  // let-bound, enable this assertion. This is the core of the test.
+  // assertEquals('function', typeof x);
+})(1);
+
+(function shadowRestParameter(...x) {
+  assertArrayEquals([1], x);
+  {
+    function x() {}
+  }
+  // TODO(littledan): Once destructured parameters are no longer
+  // let-bound, enable this assertion. This is the core of the test.
+  // assertEquals('function', typeof x);
+})(1);
+
+assertThrows(function notInDefaultScope(x = y) {
+  {
+    function y() {}
+  }
+  assertEquals('function', typeof y);
+  assertEquals(x, undefined);
+}, ReferenceError);
+
+// Test that hoisting from blocks does happen in global scope
+function globalHoisted() { return 0; }
+{
+  function globalHoisted() { return 1; }
+}
+assertEquals(1, globalHoisted());
+
+// Also happens when not previously defined
+assertEquals(undefined, globalUndefinedHoisted);
+{
+  function globalUndefinedHoisted() { return 1; }
+}
+assertEquals(1, globalUndefinedHoisted());
+var globalUndefinedHoistedDescriptor =
+    Object.getOwnPropertyDescriptor(this, "globalUndefinedHoisted");
+assertFalse(globalUndefinedHoistedDescriptor.configurable);
+assertTrue(globalUndefinedHoistedDescriptor.writable);
+assertTrue(globalUndefinedHoistedDescriptor.enumerable);
+assertEquals(1, globalUndefinedHoistedDescriptor.value());
+
+// When a function property is hoisted, it should be
+// made enumerable.
+// BUG(v8:4451)
+Object.defineProperty(this, "globalNonEnumerable", {
+  value: false,
+  configurable: true,
+  writable: true,
+  enumerable: false
+});
+eval("{function globalNonEnumerable() { return 1; }}");
+var globalNonEnumerableDescriptor
+    = Object.getOwnPropertyDescriptor(this, "globalNonEnumerable");
+// BUG(v8:4451): Should be made non-configurable
+assertTrue(globalNonEnumerableDescriptor.configurable);
+assertTrue(globalNonEnumerableDescriptor.writable);
+// BUG(v8:4451): Should be made enumerable
+assertFalse(globalNonEnumerableDescriptor.enumerable);
+assertEquals(1, globalNonEnumerableDescriptor.value());
+
+// When a function property is hoisted, it should be overwritten and
+// made writable and overwritten, even if the property was non-writable.
+Object.defineProperty(this, "globalNonWritable", {
+  value: false,
+  configurable: true,
+  writable: false,
+  enumerable: true
+});
+eval("{function globalNonWritable() { return 1; }}");
+var globalNonWritableDescriptor
+    = Object.getOwnPropertyDescriptor(this, "globalNonWritable");
+// BUG(v8:4451): Should be made non-configurable
+assertTrue(globalNonWritableDescriptor.configurable);
+// BUG(v8:4451): Should be made writable
+assertFalse(globalNonWritableDescriptor.writable);
+assertFalse(globalNonEnumerableDescriptor.enumerable);
+// BUG(v8:4451): Should be overwritten
+assertEquals(false, globalNonWritableDescriptor.value);
+
+// Test that hoisting from blocks does happen in an eval
+eval(`
+  function evalHoisted() { return 0; }
+  {
+    function evalHoisted() { return 1; }
+  }
+  assertEquals(1, evalHoisted());
+`);
+
+// Test that hoisting from blocks happens from eval in a function
+!function() {
+  eval(`
+    function evalInFunctionHoisted() { return 0; }
+    {
+      function evalInFunctionHoisted() { return 1; }
+    }
+    assertEquals(1, evalInFunctionHoisted());
+  `);
+}();
+
+let dontHoistGlobal;
+{ function dontHoistGlobal() {} }
+assertEquals(undefined, dontHoistGlobal);
+
+let dontHoistEval;
+// BUG(v8:) This shouldn't hoist and shouldn't throw
+var throws = false;
+try {
+  eval("{ function dontHoistEval() {} }");
+} catch (e) {
+  throws = true;
+}
+assertTrue(throws);
+
+// When the global object is frozen, silently don't hoist
+// Currently this actually throws BUG(v8:4452)
+Object.freeze(this);
+throws = false;
+try {
+  eval('{ function hoistWhenFrozen() {} }');
+} catch (e) {
+  throws = true;
+}
+assertFalse(this.hasOwnProperty("hoistWhenFrozen"));
+assertThrows(() => hoistWhenFrozen, ReferenceError);
+// Should be assertFalse BUG(v8:4452)
+assertTrue(throws);
diff --git a/test/mjsunit/es6/class-computed-property-names-super.js b/test/mjsunit/es6/class-computed-property-names-super.js
index cb9f251..b5a2ac9 100644
--- a/test/mjsunit/es6/class-computed-property-names-super.js
+++ b/test/mjsunit/es6/class-computed-property-names-super.js
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-sloppy
 // Flags: --allow-natives-syntax
 
 
diff --git a/test/mjsunit/es6/class-property-name-eval-arguments.js b/test/mjsunit/es6/class-property-name-eval-arguments.js
index 72ff60f..bbd05cc 100644
--- a/test/mjsunit/es6/class-property-name-eval-arguments.js
+++ b/test/mjsunit/es6/class-property-name-eval-arguments.js
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-sloppy
-
 
 (function Method() {
   class C {
diff --git a/test/mjsunit/es6/classes-derived-return-type.js b/test/mjsunit/es6/classes-derived-return-type.js
index 8283bcb..3f81a34 100644
--- a/test/mjsunit/es6/classes-derived-return-type.js
+++ b/test/mjsunit/es6/classes-derived-return-type.js
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-sloppy
-
 
 class Base {}
 
diff --git a/test/mjsunit/es6/classes-subclass-builtins.js b/test/mjsunit/es6/classes-subclass-builtins.js
index 7669ef3..dca514c 100644
--- a/test/mjsunit/es6/classes-subclass-builtins.js
+++ b/test/mjsunit/es6/classes-subclass-builtins.js
@@ -2,8 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --harmony-regexp-subclass
-// Flags: --expose-gc
+// Flags: --allow-natives-syntax --expose-gc
 
 "use strict";
 
diff --git a/test/mjsunit/es6/classes.js b/test/mjsunit/es6/classes.js
index 4dabda8..fb77dbb 100644
--- a/test/mjsunit/es6/classes.js
+++ b/test/mjsunit/es6/classes.js
@@ -2,8 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-sloppy --harmony-function-name --allow-natives-syntax
-// Flags: --harmony-do-expressions
+// Flags: --allow-natives-syntax --harmony-do-expressions
 
 (function TestBasics() {
   var C = class C {}
diff --git a/test/mjsunit/es6/completion.js b/test/mjsunit/es6/completion.js
index 7559514..988e970 100644
--- a/test/mjsunit/es6/completion.js
+++ b/test/mjsunit/es6/completion.js
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-sloppy-let
-
 
 function assertUndef(x) {
   assertEquals(undefined, x);
diff --git a/test/mjsunit/es6/debug-blockscopes.js b/test/mjsunit/es6/debug-blockscopes.js
index 193ad70..bf04a0a 100644
--- a/test/mjsunit/es6/debug-blockscopes.js
+++ b/test/mjsunit/es6/debug-blockscopes.js
@@ -52,6 +52,7 @@
       listener_delegate(exec_state);
     }
   } catch (e) {
+    print(e, e.stack);
     exception = e;
   }
 }
@@ -147,10 +148,8 @@
   if (!scope.scopeObject().property('arguments').isUndefined()) {
     scope_size--;
   }
-  // Skip property with empty name.
-  if (!scope.scopeObject().property('').isUndefined()) {
-    scope_size--;
-  }
+  // Temporary variables introduced by the parser have not been materialized.
+  assertTrue(scope.scopeObject().property('').isUndefined());
 
   if (count != scope_size) {
     print('Names found in scope:');
@@ -380,16 +379,12 @@
 
 listener_delegate = function(exec_state) {
   CheckScopeChain([debug.ScopeType.Block,
-                   debug.ScopeType.Block,
                    debug.ScopeType.Local,
                    debug.ScopeType.Script,
                    debug.ScopeType.Global], exec_state);
   CheckScopeContent({x:'y'}, 0, exec_state);
   // The function scope contains a temporary iteration variable, but it is
   // hidden to the debugger.
-  // TODO(adamk): This variable is only used to provide a TDZ for the enumerable
-  // expression and should not be visible to the debugger.
-  CheckScopeContent({x:undefined}, 1, exec_state);
 };
 for_loop_1();
 EndTest();
@@ -409,7 +404,6 @@
 listener_delegate = function(exec_state) {
   CheckScopeChain([debug.ScopeType.Block,
                    debug.ScopeType.Block,
-                   debug.ScopeType.Block,
                    debug.ScopeType.Local,
                    debug.ScopeType.Script,
                    debug.ScopeType.Global], exec_state);
@@ -417,9 +411,6 @@
   CheckScopeContent({x:'y'}, 1, exec_state);
   // The function scope contains a temporary iteration variable, hidden to the
   // debugger.
-  // TODO(adamk): This variable is only used to provide a TDZ for the enumerable
-  // expression and should not be visible to the debugger.
-  CheckScopeContent({x:undefined}, 2, exec_state);
 };
 for_loop_2();
 EndTest();
@@ -436,13 +427,11 @@
 
 listener_delegate = function(exec_state) {
   CheckScopeChain([debug.ScopeType.Block,
-                   debug.ScopeType.Block,
                    debug.ScopeType.Local,
                    debug.ScopeType.Script,
                    debug.ScopeType.Global], exec_state);
   CheckScopeContent({x:3}, 0, exec_state);
-  CheckScopeContent({x:3}, 1, exec_state);
-  CheckScopeContent({}, 2, exec_state);
+  CheckScopeContent({}, 1, exec_state);
 };
 for_loop_3();
 EndTest();
@@ -461,14 +450,12 @@
 listener_delegate = function(exec_state) {
   CheckScopeChain([debug.ScopeType.Block,
                    debug.ScopeType.Block,
-                   debug.ScopeType.Block,
                    debug.ScopeType.Local,
                    debug.ScopeType.Script,
                    debug.ScopeType.Global], exec_state);
   CheckScopeContent({x:5}, 0, exec_state);
   CheckScopeContent({x:3}, 1, exec_state);
-  CheckScopeContent({x:3}, 2, exec_state);
-  CheckScopeContent({}, 3, exec_state);
+  CheckScopeContent({}, 2, exec_state);
 };
 for_loop_4();
 EndTest();
@@ -485,13 +472,11 @@
 
 listener_delegate = function(exec_state) {
   CheckScopeChain([debug.ScopeType.Block,
-                   debug.ScopeType.Block,
                    debug.ScopeType.Local,
                    debug.ScopeType.Script,
                    debug.ScopeType.Global], exec_state);
   CheckScopeContent({x:3,y:5}, 0, exec_state);
-  CheckScopeContent({x:3,y:5}, 1, exec_state);
-  CheckScopeContent({}, 2, exec_state);
+  CheckScopeContent({}, 1, exec_state);
 };
 for_loop_5();
 EndTest();
diff --git a/test/mjsunit/es6/debug-evaluate-receiver-before-super.js b/test/mjsunit/es6/debug-evaluate-receiver-before-super.js
new file mode 100644
index 0000000..dc8ce2c
--- /dev/null
+++ b/test/mjsunit/es6/debug-evaluate-receiver-before-super.js
@@ -0,0 +1,39 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+// Test that debug-evaluate doesn't crash when this is used before super() call
+// in constructor.
+
+Debug = debug.Debug
+
+var result;
+
+function listener(event, exec_state, event_data, data)
+{
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      result = exec_state.frame(0).evaluate("this.a").value();
+    }
+  } catch (e) {
+    result = e.message;
+  }
+}
+
+Debug.setListener(listener);
+
+class A { constructor () { this.a = 239; } }
+class B extends A {
+  constructor () {
+    debugger;
+    assertEquals("Cannot read property 'a' of undefined", result);
+    super();
+    debugger;
+    assertEquals(239, result);
+  }
+}
+new B();
+
+Debug.setListener(null);
diff --git a/test/mjsunit/es6/debug-promises/async-task-event.js b/test/mjsunit/es6/debug-promises/async-task-event.js
index 88030a2..0b0fa1e 100644
--- a/test/mjsunit/es6/debug-promises/async-task-event.js
+++ b/test/mjsunit/es6/debug-promises/async-task-event.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --expose-debug-as debug
+// Flags: --expose-debug-as debug --allow-natives-syntax
 
 Debug = debug.Debug;
 
@@ -16,8 +16,8 @@
   "didHandle #1",
   "willHandle #2",
   "then #2",
-  "enqueue #3",
   "didHandle #2",
+  "enqueue #3",
   "willHandle #3",
   "didHandle #3"
 ];
@@ -58,4 +58,6 @@
 });
 resolver();
 
+%RunMicrotasks();
+
 assertNull(exception);
diff --git a/test/mjsunit/es6/debug-promises/evaluate-across-microtasks.js b/test/mjsunit/es6/debug-promises/evaluate-across-microtasks.js
new file mode 100644
index 0000000..73718ee
--- /dev/null
+++ b/test/mjsunit/es6/debug-promises/evaluate-across-microtasks.js
@@ -0,0 +1,66 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax
+
+var Debug = debug.Debug;
+var listenerComplete = false;
+var exception = null;
+var count = 0;
+var log = [];
+var done = false;
+
+function LogX(x) {
+  var stored_count = count;
+  return function() {
+    log.push(`[${stored_count}] ${x}`);
+  };
+}
+
+function DebuggerStatement() {
+  log.push(`[${count}] debugger`);
+  if (count++ < 3) {
+    debugger;
+  }
+}
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var p = Promise.resolve();
+    var q = p.then(LogX("then 1"));
+    p.then(LogX("then 2"));
+    q.then(LogX("then 3"));
+    q.then(DebuggerStatement);
+    var r = q.then(() => { throw 1; });
+    r.catch(LogX("catch"));
+    listenerComplete = true;
+  } catch (e) {
+    exception = e;
+    print(e, e.stack);
+    quit(1);
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+DebuggerStatement();
+LogX("start")();
+
+// Make sure that the debug event listener was invoked.
+assertTrue(listenerComplete);
+
+%RunMicrotasks();
+
+var expectation =
+  [ "[0] debugger", "[1] start", "[1] then 1",
+    "[1] then 2", "[1] then 3", "[1] debugger",
+    "[2] then 1", "[2] then 2", "[1] catch",
+    "[2] then 3", "[2] debugger", "[3] then 1",
+    "[3] then 2", "[2] catch", "[3] then 3",
+    "[3] debugger", "[3] catch",
+  ];
+
+assertEquals(expectation, log);
diff --git a/test/mjsunit/es6/debug-promises/stepin-constructor.js b/test/mjsunit/es6/debug-promises/stepin-constructor.js
index 906969e..6914ae0 100644
--- a/test/mjsunit/es6/debug-promises/stepin-constructor.js
+++ b/test/mjsunit/es6/debug-promises/stepin-constructor.js
@@ -21,9 +21,9 @@
 Debug.setListener(listener);
 
 function resolver(resolve, reject) {
-  1;
-  2;
-  3;
+  print(1);
+  print(2);
+  print(3);
   resolve();
 }
 
@@ -35,9 +35,9 @@
 var expected_breaks = [
   "debugger;",
   "var p = new Promise(resolver);",
-  "1;",
-  "2;",
-  "3;",
+  "print(1);",
+  "print(2);",
+  "print(3);",
   "resolve();",
   "}",
   "Debug.setListener(null);"
diff --git a/test/mjsunit/es6/debug-scope-default-param-with-eval.js b/test/mjsunit/es6/debug-scope-default-param-with-eval.js
new file mode 100644
index 0000000..d4dc93f
--- /dev/null
+++ b/test/mjsunit/es6/debug-scope-default-param-with-eval.js
@@ -0,0 +1,61 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+// Test that the parameter initialization block scope set up for
+// sloppy eval is visible to the debugger.
+
+var Debug = debug.Debug;
+var exception = null;
+var break_count = 0;
+
+function call_for_break() {
+  return 5;
+}
+
+function test(x = eval("var y = 7; debugger; y") + call_for_break()) {
+  return x;
+}
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var frame = exec_state.frame(0);
+    var block_scope;
+    if (break_count++ == 0) {
+      // Inside eval.
+      assertEquals([ debug.ScopeType.Eval,
+                     debug.ScopeType.Block,
+                     debug.ScopeType.Closure,
+                     debug.ScopeType.Script,
+                     debug.ScopeType.Global ],
+                   frame.allScopes().map(s => s.scopeType()));
+      exec_state.prepareStep(Debug.StepAction.StepOut);
+      block_scope = frame.scope(1);
+    } else {
+      // Outside of eval.
+      assertEquals([ debug.ScopeType.Block,
+                     debug.ScopeType.Local,
+                     debug.ScopeType.Script,
+                     debug.ScopeType.Global ],
+                   frame.allScopes().map(s => s.scopeType()));
+      block_scope = frame.scope(0);
+    }
+    assertTrue(block_scope.scopeObject().propertyNames().includes('y'));
+    assertEquals(7, block_scope.scopeObject().property('y').value().value());
+  } catch (e) {
+    print(e);
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+assertEquals(12, test());
+
+Debug.setListener(null);
+
+assertNull(exception);
+assertEquals(2, break_count);
diff --git a/test/mjsunit/es6/debug-step-into-regexp-subclass.js b/test/mjsunit/es6/debug-step-into-regexp-subclass.js
index 599fe05..5e5eb47 100644
--- a/test/mjsunit/es6/debug-step-into-regexp-subclass.js
+++ b/test/mjsunit/es6/debug-step-into-regexp-subclass.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --expose-debug-as debug --harmony-regexp-subclass
+// Flags: --expose-debug-as debug
 
 Debug = debug.Debug
 
diff --git a/test/mjsunit/es6/debug-stepin-generators.js b/test/mjsunit/es6/debug-stepin-generators.js
index 081dfb7..6e548b4 100644
--- a/test/mjsunit/es6/debug-stepin-generators.js
+++ b/test/mjsunit/es6/debug-stepin-generators.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --expose-debug-as debug
+// Flags: --expose-debug-as debug --ignition-generators
 
 Debug = debug.Debug
 var exception = null;
diff --git a/test/mjsunit/es6/debug-stepin-microtasks.js b/test/mjsunit/es6/debug-stepin-microtasks.js
index 6a7c553..e541f0f 100644
--- a/test/mjsunit/es6/debug-stepin-microtasks.js
+++ b/test/mjsunit/es6/debug-stepin-microtasks.js
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-object-observe
 // Flags: --allow-natives-syntax --expose-debug-as debug
 
 Debug = debug.Debug
@@ -46,6 +45,7 @@
   .then(Boolean) // Should skip stepping into native.
   .then(promise2)
   .catch(promise3)
+  .then(promise4)
   .catch(function(e) {
     %AbortJS("FAIL: uncaught exception " + e);
   });
@@ -60,36 +60,16 @@
 }
 
 function promise3() {
-  installObservers(); // Break 4. StepOver.
-  return break_count; // Break 5.
-} // Break 6.
-
-function installObservers() {
-  var dummy = {};
-  Object.observe(dummy, observer1);
-  Object.observe(dummy, Object); // Should skip stepping into native.
-  Object.observe(dummy, Boolean); // Should skip stepping into native.
-  Object.observe(dummy, observer2);
-  dummy.foo = 1;
-}
-
-function observer1() {
-  return exception || 3; // Break 7.
-} // Break 8.
-
-function observer2() {
-  Promise.resolve().then(promise4); // Break 9. StepOver.
-  return break_count + 1; // Break 10.
-} // Break 11.
+  return break_count; // Break 4.
+} // Break 5.
 
 function promise4() {
-  finalize(); // Break 12. StepOver.
-  return 0; // Break 13.
-} // Break 14. StepOver.
+  finalize(); // Break 6. StepOver.
+  return 0; // Break 7.
+} // Break 8. StepOver.
 
 function finalize() {
-  var dummy = {};
-  Object.observe(dummy, function() {
+  Promise.resolve().then(function() {
     if (expected_breaks !== break_count) {
       %AbortJS("FAIL: expected <" + expected_breaks + "> breaks instead of <" +
                break_count + ">");
@@ -98,5 +78,4 @@
       %AbortJS("FAIL: exception: " + exception);
     }
   });
-  dummy.foo = 1;
 }
diff --git a/test/mjsunit/es6/debug-stepin-proxies.js b/test/mjsunit/es6/debug-stepin-proxies.js
index 4e71c79..72c01f0 100644
--- a/test/mjsunit/es6/debug-stepin-proxies.js
+++ b/test/mjsunit/es6/debug-stepin-proxies.js
@@ -54,7 +54,7 @@
 
 assertEquals([
   "a0",
-  "b17", "h4b20", "i2b20",  // [[Has]]
+  "b17", "h4b17", "i2b17",  // [[Has]]
   "c15", "j4c15", "k2c15",  // [[Get]]
   "d0", "l4d11", "m2d11",   // [[Set]]
   "g0"
diff --git a/test/mjsunit/es6/debug-stepnext-for.js b/test/mjsunit/es6/debug-stepnext-for.js
index 9d5641a..d425a46 100644
--- a/test/mjsunit/es6/debug-stepnext-for.js
+++ b/test/mjsunit/es6/debug-stepnext-for.js
@@ -11,6 +11,8 @@
 
 var s = 0;
 var a = [1, 2, 3];
+var b = [1, 2, 3, 4];
+var null_value = null;
 var i = 0;
 
 function f() {
@@ -18,11 +20,11 @@
   debugger;                      // Break a
   var j;                         // Break b
 
-  for (var i in null) {          // Break c
+  for (var i in null_value) {    // Break c
     s += a[i];
   }
 
-  for (j in null) {              // Break d
+  for (j in null_value) {        // Break d
     s += a[j];
   }
 
@@ -46,7 +48,7 @@
     s += j;                      // Break I
   }
 
-  for (let i of a) {             // Break j
+  for (let i  of  a) {           // Break j
     s += i;                      // Break J
   }
 
@@ -61,6 +63,11 @@
   for (let i = 0; i < 3; i++) {  // Break m
     s += a[i];                   // Break M
   }
+
+  for (let i of a) {}            // Break n
+
+  [1, ...a]                      // Break o
+
 }                                // Break y
 
 function listener(event, exec_state, event_data, data) {
@@ -103,17 +110,21 @@
   // For-in-let: get enumerable, next, body, next,  ...
   "g16","g11","G4","g11","G4","g11","G4","g11",
   // For-of-var: [Symbol.iterator](), next(), body, next(), body, ...
-  "h16","h14","h15","H4","h15","H4","h15","H4","h15",
+  "h16","h13","H4","h13","H4","h13","H4","h13",
   // For-of: [Symbol.iterator](), next(), body, next(), body, ...
-  "i12","i10","i11","I4","i11","I4","i11","I4","i11",
+  "i12","i9","I4","i9","I4","i9","I4","i9",
   // For-of-let: [Symbol.iterator](), next(), body, next(), ...
-  "j16","j14","j15","J4","j15","J4","j15","J4","j15",
+  "j18","j14","J4","j14","J4","j14","J4","j14",
   // For-var: init, condition, body, next, condition, body, ...
   "k15","k20","K4","k26","k20","K4","k26","k20","K4","k26","k20",
   // For: init, condition, body, next, condition, body, ...
   "l7","l16","L4","l22","l16","L4","l22","l16","L4","l22","l16",
   // For-let: init, condition, body, next, condition, body, ...
   "m15","m20","M4","m26","m20","M4","m26","m20","M4","m26","m20",
+  // For-of, empty: [Symbol.iterator](), next() once
+  "n16", "n13",
+  // Spread: expression statement, spread
+  "o2", "o9",
   // Exit.
   "y0","z0",
 ]
diff --git a/test/mjsunit/es6/function-name.js b/test/mjsunit/es6/function-name.js
new file mode 100644
index 0000000..152a631
--- /dev/null
+++ b/test/mjsunit/es6/function-name.js
@@ -0,0 +1,370 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function testVariableDeclarationsFunction() {
+  'use strict';
+  var a = function(){};
+  assertEquals('a', a.name);
+  let b = () => {};
+  assertEquals('b', b.name);
+  const c = ((function(){}));
+  assertEquals('c', c.name);
+
+  var x = function(){}, y = () => {}, z = function withName() {};
+  assertEquals('x', x.name);
+  assertEquals('y', y.name);
+  assertEquals('withName', z.name);
+})();
+
+(function testVariableDeclarationsClass() {
+  'use strict';
+  var a = class {};
+  assertEquals('a', a.name);
+  let b = ((class {}));
+  assertEquals('b', b.name);
+  // Should not overwrite name property.
+  const c = class { static name() { } }
+  assertEquals('function', typeof c.name);
+
+  var x = class {}, y = class NamedClass {};
+  assertEquals('x', x.name);
+  assertEquals('NamedClass', y.name);
+})();
+
+(function testObjectProperties() {
+  'use strict';
+  var obj = {
+    a: function() {},
+    b: () => {},
+    c() { },
+    get d() { },
+    set d(val) { },
+    x: function withName() { },
+    y: class { },
+    z: class ClassName { },
+    42: function() {},
+    4.2: function() {},
+    __proto__: function() {},
+  };
+
+  assertEquals('a', obj.a.name);
+  assertEquals('b', obj.b.name);
+  assertEquals('c', obj.c.name);
+  var dDescriptor = Object.getOwnPropertyDescriptor(obj, 'd');
+  assertEquals('get d', dDescriptor.get.name);
+  assertEquals('set d', dDescriptor.set.name);
+  assertEquals('withName', obj.x.name);
+  assertEquals('y', obj.y.name);
+  assertEquals('ClassName', obj.z.name);
+  assertEquals('42', obj[42].name);
+  assertEquals('4.2', obj[4.2].name);
+  assertEquals('', obj.__proto__.name);
+})();
+
+(function testClassProperties() {
+  'use strict';
+  class C {
+    a() { }
+    static b() { }
+    get c() { }
+    set c(val) { }
+    42() { }
+    static 43() { }
+    get 44() { }
+    set 44(val) { }
+  };
+
+  assertEquals('a', C.prototype.a.name);
+  assertEquals('b', C.b.name);
+  var descriptor = Object.getOwnPropertyDescriptor(C.prototype, 'c');
+  assertEquals('get c', descriptor.get.name);
+  assertEquals('set c', descriptor.set.name);
+  assertEquals('42', C.prototype[42].name);
+  assertEquals('43', C[43].name);
+  var descriptor = Object.getOwnPropertyDescriptor(C.prototype, '44');
+  assertEquals('get 44', descriptor.get.name);
+  assertEquals('set 44', descriptor.set.name);
+})();
+
+(function testComputedProperties() {
+  'use strict';
+  var a = 'a';
+  var b = 'b';
+  var sym1 = Symbol('1');
+  var sym2 = Symbol('2');
+  var sym3 = Symbol('3');
+  var symNoDescription = Symbol();
+  var obj = {
+    [a]: function() {},
+    [sym1]: function() {},
+    [sym2]: function withName() {},
+    [symNoDescription]: function() {},
+
+    get [sym3]() {},
+    set [b](val) {},
+  };
+
+  assertEquals('a', obj[a].name);
+  assertEquals('[1]', obj[sym1].name);
+  assertEquals('withName', obj[sym2].name);
+  assertEquals('', obj[symNoDescription].name);
+
+  assertEquals('get [3]', Object.getOwnPropertyDescriptor(obj, sym3).get.name);
+  assertEquals('set b', Object.getOwnPropertyDescriptor(obj, 'b').set.name);
+
+  var objMethods = {
+    [a]() {},
+    [sym1]() {},
+    [symNoDescription]: function() {},
+  };
+
+  assertEquals('a', objMethods[a].name);
+  assertEquals('[1]', objMethods[sym1].name);
+  assertEquals('', objMethods[symNoDescription].name);
+
+  class C {
+    [a]() { }
+    [sym1]() { }
+    static [sym2]() { }
+    [symNoDescription]() { }
+
+    get [sym3]() { }
+    static set [b](val) { }
+  }
+
+  assertEquals('a', C.prototype[a].name);
+  assertEquals('[1]', C.prototype[sym1].name);
+  assertEquals('[2]', C[sym2].name);
+  assertEquals('', C.prototype[symNoDescription].name);
+
+  assertEquals('get [3]', Object.getOwnPropertyDescriptor(C.prototype, sym3).get.name);
+  assertEquals('set b', Object.getOwnPropertyDescriptor(C, 'b').set.name);
+})();
+
+
+(function testAssignment() {
+  var basicFn, arrowFn, generatorFn, classLit;
+
+  basicFn = function() { return true; };
+  assertEquals('basicFn', basicFn.name);
+  var basicFn2 = basicFn;
+  assertEquals('basicFn', basicFn2.name);
+  basicFn = function functionWithName() { };
+  assertEquals("functionWithName", basicFn.name);
+
+  arrowFn = x => x;
+  assertEquals('arrowFn', arrowFn.name);
+  var arrowFn2 = arrowFn;
+  assertEquals('arrowFn', arrowFn2.name);
+
+  generatorFn = function*() { yield true; };
+  assertEquals('generatorFn', generatorFn.name);
+  var generatorFn2 = generatorFn;
+  assertEquals('generatorFn', generatorFn2.name);
+  generatorFn = function* generatorWithName() { };
+  assertEquals("generatorWithName", generatorFn.name);
+
+  classLit = class { constructor() {} };
+  assertEquals('classLit', classLit.name);
+  var classLit2 = classLit;
+  assertEquals('classLit', classLit2.name);
+  classLit = class classWithName { constructor() {} };
+  assertEquals('classWithName', classLit.name);
+  classLit = class { constructor() {} static name() {} };
+  assertEquals('function', typeof classLit.name);
+  classLit = class { constructor() {} static get name() { return true; } };
+  assertTrue(classLit.name);
+  classLit = class { constructor() {} static ['name']() {} };
+  assertEquals('function', typeof classLit.name);
+  classLit = class { constructor() {} static get ['name']() { return true; } };
+  assertTrue(classLit.name);
+})();
+
+(function testObjectBindingPattern() {
+  var {
+    a = function() {},
+    b = () => {},
+    x = function withName() { },
+    y = class { },
+    z = class ClassName { },
+    q = class { static name() { return 42 } },
+    foo: bar = function() {},
+    inParens = (() => {}),
+    inManyParens = ((((() => {})))),
+  } = {};
+  assertEquals('a', a.name);
+  assertEquals('b', b.name);
+  assertEquals('withName', x.name);
+  assertEquals('y', y.name);
+  assertEquals('ClassName', z.name);
+  assertEquals('function', typeof q.name);
+  assertEquals('bar', bar.name);
+  assertEquals('inParens', inParens.name)
+  assertEquals('inManyParens', inManyParens.name)
+})();
+
+(function testArrayBindingPattern() {
+  var [
+    a = function() {},
+    b = () => {},
+    x = function withName() { },
+    y = class { },
+    z = class ClassName { },
+    q = class { static name() { return 42 } },
+    inParens = (() => {}),
+    inManyParens = ((((() => {})))),
+  ] = [];
+  assertEquals('a', a.name);
+  assertEquals('b', b.name);
+  assertEquals('withName', x.name);
+  assertEquals('y', y.name);
+  assertEquals('ClassName', z.name);
+  assertEquals('function', typeof q.name);
+  assertEquals('inParens', inParens.name)
+  assertEquals('inManyParens', inManyParens.name)
+})();
+
+(function testObjectAssignmentPattern() {
+  var a, b, x, y, z, q;
+  ({
+    a = function() {},
+    b = () => {},
+    x = function withName() { },
+    y = class { },
+    z = class ClassName { },
+    q = class { static name() { return 42 } },
+    foo: bar = function() {},
+    inParens = (() => {}),
+    inManyParens = ((((() => {})))),
+  } = {});
+  assertEquals('a', a.name);
+  assertEquals('b', b.name);
+  assertEquals('withName', x.name);
+  assertEquals('y', y.name);
+  assertEquals('ClassName', z.name);
+  assertEquals('function', typeof q.name);
+  assertEquals('bar', bar.name);
+  assertEquals('inParens', inParens.name)
+  assertEquals('inManyParens', inManyParens.name)
+})();
+
+(function testArrayAssignmentPattern() {
+  var a, b, x, y, z, q;
+  [
+    a = function() {},
+    b = () => {},
+    x = function withName() { },
+    y = class { },
+    z = class ClassName { },
+    q = class { static name() { return 42 } },
+    inParens = (() => {}),
+    inManyParens = ((((() => {})))),
+  ] = [];
+  assertEquals('a', a.name);
+  assertEquals('b', b.name);
+  assertEquals('withName', x.name);
+  assertEquals('y', y.name);
+  assertEquals('ClassName', z.name);
+  assertEquals('function', typeof q.name);
+  assertEquals('inParens', inParens.name)
+  assertEquals('inManyParens', inManyParens.name)
+})();
+
+(function testParameterDestructuring() {
+  (function({ a = function() {},
+              b = () => {},
+              x = function withName() { },
+              y = class { },
+              z = class ClassName { },
+              q = class { static name() { return 42 } },
+              foo: bar = function() {},
+              inParens = (() => {}),
+              inManyParens = ((((() => {})))) }) {
+    assertEquals('a', a.name);
+    assertEquals('b', b.name);
+    assertEquals('withName', x.name);
+    assertEquals('y', y.name);
+    assertEquals('ClassName', z.name);
+    assertEquals('function', typeof q.name);
+    assertEquals('bar', bar.name);
+    assertEquals('inParens', inParens.name)
+    assertEquals('inManyParens', inManyParens.name)
+  })({});
+
+  (function([ a = function() {},
+              b = () => {},
+              x = function withName() { },
+              y = class { },
+              z = class ClassName { },
+              q = class { static name() { return 42 } },
+              inParens = (() => {}),
+              inManyParens = ((((() => {})))) ]) {
+    assertEquals('a', a.name);
+    assertEquals('b', b.name);
+    assertEquals('withName', x.name);
+    assertEquals('y', y.name);
+    assertEquals('ClassName', z.name);
+    assertEquals('function', typeof q.name);
+    assertEquals('inParens', inParens.name)
+    assertEquals('inManyParens', inManyParens.name)
+  })([]);
+})();
+
+(function testDefaultParameters() {
+  (function(a = function() {},
+            b = () => {},
+            x = function withName() { },
+            y = class { },
+            z = class ClassName { },
+            q = class { static name() { return 42 } },
+            inParens = (() => {}),
+            inManyParens = ((((() => {}))))) {
+    assertEquals('a', a.name);
+    assertEquals('b', b.name);
+    assertEquals('withName', x.name);
+    assertEquals('y', y.name);
+    assertEquals('ClassName', z.name);
+    assertEquals('function', typeof q.name);
+    assertEquals('inParens', inParens.name)
+    assertEquals('inManyParens', inManyParens.name)
+  })();
+})();
+
+(function testComputedNameNotShared() {
+  function makeClass(propName) {
+    return class {
+      static [propName]() {}
+    }
+  }
+
+  var sym1 = Symbol('1');
+  var sym2 = Symbol('2');
+  var class1 = makeClass(sym1);
+  assertEquals('[1]', class1[sym1].name);
+  var class2 = makeClass(sym2);
+  assertEquals('[2]', class2[sym2].name);
+  assertEquals('[1]', class1[sym1].name);
+})();
+
+
+(function testComputedNamesOnlyAppliedSyntactically() {
+  function factory() { return () => {}; }
+
+  var obj = { ['foo']: factory() };
+  assertEquals('', obj.foo.name);
+})();
+
+
+(function testNameNotReflectedInToString() {
+  var f = function() {};
+  var g = function*() {};
+  var obj = {
+    ['h']: function() {},
+    i: () => {}
+  };
+  assertEquals('function () {}', f.toString());
+  assertEquals('function* () {}', g.toString());
+  assertEquals('function () {}', obj.h.toString());
+  assertEquals('() => {}', obj.i.toString());
+})();
diff --git a/test/mjsunit/es6/generators-debug-liveedit.js b/test/mjsunit/es6/generators-debug-liveedit.js
index 987a42c..2bbbfc2 100644
--- a/test/mjsunit/es6/generators-debug-liveedit.js
+++ b/test/mjsunit/es6/generators-debug-liveedit.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --expose-debug-as debug --allow-natives-syntax
+// Flags: --expose-debug-as debug --allow-natives-syntax --ignition-generators
 
 var Debug = debug.Debug;
 var LiveEdit = Debug.LiveEdit;
diff --git a/test/mjsunit/es6/generators-debug-scopes.js b/test/mjsunit/es6/generators-debug-scopes.js
index 126572d..b2a1ded 100644
--- a/test/mjsunit/es6/generators-debug-scopes.js
+++ b/test/mjsunit/es6/generators-debug-scopes.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --expose-debug-as debug
+// Flags: --expose-debug-as debug --ignition-generators
 
 var Debug = debug.Debug;
 
diff --git a/test/mjsunit/es6/generators-iteration.js b/test/mjsunit/es6/generators-iteration.js
index ae4c682..8f0a774 100644
--- a/test/mjsunit/es6/generators-iteration.js
+++ b/test/mjsunit/es6/generators-iteration.js
@@ -25,7 +25,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Flags: --expose-gc
+// Flags: --expose-gc --ignition-generators
 
 // Test generator iteration.
 
diff --git a/test/mjsunit/es6/generators-mirror.js b/test/mjsunit/es6/generators-mirror.js
index bf21f4d..62fbae0 100644
--- a/test/mjsunit/es6/generators-mirror.js
+++ b/test/mjsunit/es6/generators-mirror.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --expose-debug-as debug
+// Flags: --expose-debug-as debug --ignition-generators
 // Test the mirror object for functions.
 
 function *generator(f) {
diff --git a/test/mjsunit/es6/generators-objects.js b/test/mjsunit/es6/generators-objects.js
index a0c3b80..9a07518 100644
--- a/test/mjsunit/es6/generators-objects.js
+++ b/test/mjsunit/es6/generators-objects.js
@@ -25,7 +25,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Flags: --allow-natives-syntax
+// Flags: --allow-natives-syntax --ignition-generators
 
 // Test instantations of generators.
 
@@ -87,3 +87,43 @@
   TestNonGenerator(g.prototype);
 }
 TestGeneratorObjectMethods();
+
+
+function TestPrototype() {
+  function* g() { }
+
+  let g_prototype = g.prototype;
+  assertEquals([], Reflect.ownKeys(g_prototype));
+
+  let generator_prototype = Object.getPrototypeOf(g_prototype);
+  assertSame(generator_prototype, Object.getPrototypeOf(g).prototype);
+
+  // Unchanged .prototype
+  assertSame(g_prototype, Object.getPrototypeOf(g()));
+
+  // Custom object as .prototype
+  {
+    let proto = {};
+    g.prototype = proto;
+    assertSame(proto, Object.getPrototypeOf(g()));
+  }
+
+  // Custom non-object as .prototype
+  g.prototype = null;
+  assertSame(generator_prototype, Object.getPrototypeOf(g()));
+}
+TestPrototype();
+
+
+function TestComputedPropertyNames() {
+  function* f1() { return {[yield]: 42} }
+  var g1 = f1();
+  g1.next();
+  assertEquals(42, g1.next('a').value.a);
+
+  function* f2() { return {['a']: yield} }
+  var g2 = f2();
+  g2.next();
+  assertEquals(42, g2.next(42).value.a);
+}
+TestComputedPropertyNames();
diff --git a/test/mjsunit/es6/generators-parsing.js b/test/mjsunit/es6/generators-parsing.js
index f3f8cad..143c3d7 100644
--- a/test/mjsunit/es6/generators-parsing.js
+++ b/test/mjsunit/es6/generators-parsing.js
@@ -25,6 +25,8 @@
 // (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: --ignition-generators
+
 // Test basic generator syntax.
 
 // Yield statements.
diff --git a/test/mjsunit/es6/generators-poisoned-properties.js b/test/mjsunit/es6/generators-poisoned-properties.js
index e861022..5a0c652 100644
--- a/test/mjsunit/es6/generators-poisoned-properties.js
+++ b/test/mjsunit/es6/generators-poisoned-properties.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Flags: --ignition-generators
+
 (function testRestrictedPropertiesStrict() {
   function* generator() { "use strict"; }
   assertFalse(generator.hasOwnProperty("arguments"));
diff --git a/test/mjsunit/es6/generators-relocation.js b/test/mjsunit/es6/generators-relocation.js
index 2636f52..28311a8 100644
--- a/test/mjsunit/es6/generators-relocation.js
+++ b/test/mjsunit/es6/generators-relocation.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --expose-debug-as debug
+// Flags: --expose-debug-as debug --ignition-generators
 
 var Debug = debug.Debug;
 
diff --git a/test/mjsunit/es6/generators-runtime.js b/test/mjsunit/es6/generators-runtime.js
index 5c426b2..0cdbfca 100644
--- a/test/mjsunit/es6/generators-runtime.js
+++ b/test/mjsunit/es6/generators-runtime.js
@@ -25,6 +25,8 @@
 // (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: --ignition-generators
+
 // Test aspects of the generator runtime.
 
 // See:
diff --git a/test/mjsunit/es6/generators-states.js b/test/mjsunit/es6/generators-states.js
index 4e8c580..fb6b14a 100644
--- a/test/mjsunit/es6/generators-states.js
+++ b/test/mjsunit/es6/generators-states.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Flags: --ignition-generators
+
 // Test generator states.
 
 function Foo() {}
diff --git a/test/mjsunit/es6/instanceof.js b/test/mjsunit/es6/instanceof.js
new file mode 100644
index 0000000..6bf2259
--- /dev/null
+++ b/test/mjsunit/es6/instanceof.js
@@ -0,0 +1,67 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Make sure it's an error if @@hasInstance isn't a function.
+(function() {
+  var F = {};
+  F[Symbol.hasInstance] = null;
+  assertThrows(function() { 0 instanceof F; }, TypeError);
+})();
+
+// Make sure the result is coerced to boolean.
+(function() {
+  var F = {};
+  F[Symbol.hasInstance] = function() { return undefined; };
+  assertEquals(0 instanceof F, false);
+  F[Symbol.hasInstance] = function() { return null; };
+  assertEquals(0 instanceof F, false);
+  F[Symbol.hasInstance] = function() { return true; };
+  assertEquals(0 instanceof F, true);
+})();
+
+// Make sure if @@hasInstance throws, we catch it.
+(function() {
+  var F = {};
+  F[Symbol.hasInstance] = function() { throw new Error("always throws"); }
+  try {
+    0 instanceof F;
+  } catch (e) {
+    assertEquals(e.message, "always throws");
+  }
+})();
+
+// @@hasInstance works for bound functions.
+(function() {
+  var BC = function() {};
+  var bc = new BC();
+  var bound = BC.bind();
+  assertEquals(bound[Symbol.hasInstance](bc), true);
+  assertEquals(bound[Symbol.hasInstance]([]), false);
+})();
+
+// if OrdinaryHasInstance is passed a non-callable receiver, return false.
+assertEquals(Function.prototype[Symbol.hasInstance].call(Array, []), true);
+assertEquals(Function.prototype[Symbol.hasInstance].call({}, {}), false);
+
+// OrdinaryHasInstance passed a non-object argument returns false.
+assertEquals(Function.prototype[Symbol.hasInstance].call(Array, 0), false);
+
+// Cannot assign to @@hasInstance with %FunctionPrototype%.
+(function() {
+  "use strict";
+  function F() {}
+  assertThrows(function() { F[Symbol.hasInstance] = (v) => v }, TypeError);
+})();
+
+// Check correct invocation of @@hasInstance handler on function instance.
+(function() {
+  function F() {}
+  var counter = 0;
+  var proto = Object.getPrototypeOf(F);
+  Object.setPrototypeOf(F, null);
+  F[Symbol.hasInstance] = function(v) { ++counter; return true };
+  Object.setPrototypeOf(F, proto);
+  assertTrue(1 instanceof F);
+  assertEquals(1, counter);
+})();
diff --git a/test/mjsunit/es6/iterator-close.js b/test/mjsunit/es6/iterator-close.js
new file mode 100644
index 0000000..1a96bee
--- /dev/null
+++ b/test/mjsunit/es6/iterator-close.js
@@ -0,0 +1,1370 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+function* g() { yield 42; return 88 };
+
+
+// Return method is "undefined".
+{
+  g.prototype.return = null;
+
+
+  assertEquals(undefined, (() => {
+    for (var x of g()) { break; }
+  })());
+
+  assertEquals(undefined, (() => {
+    for (let x of g()) { break; }
+  })());
+
+  assertEquals(undefined, (() => {
+    for (const x of g()) { break; }
+  })());
+
+  assertEquals(undefined, (() => {
+    for (x of g()) { break; }
+  })());
+
+
+  assertThrowsEquals(() => {
+    for (var x of g()) { throw 42; }
+  }, 42);
+
+  assertThrowsEquals(() => {
+    for (let x of g()) { throw 42; }
+  }, 42);
+
+  assertThrowsEquals(() => {
+    for (const x of g()) { throw 42; }
+  }, 42);
+
+  assertThrowsEquals(() => {
+    for (x of g()) { throw 42; }
+  }, 42);
+
+
+  assertEquals(42, (() => {
+    for (var x of g()) { return 42; }
+  })());
+
+  assertEquals(42, (() => {
+    for (let x of g()) { return 42; }
+  })());
+
+  assertEquals(42, (() => {
+    for (const x of g()) { return 42; }
+  })());
+
+  assertEquals(42, (() => {
+    for (x of g()) { return 42; }
+  })());
+
+
+  assertEquals(42, eval('for (var x of g()) { x; }'));
+
+  assertEquals(42, eval('for (let x of g()) { x; }'));
+
+  assertEquals(42, eval('for (const x of g()) { x; }'));
+
+  assertEquals(42, eval('for (x of g()) { x; }'));
+
+
+  assertEquals(42, (() => {
+    var [x] = g(); return x;
+  })());
+
+  assertEquals(42, (() => {
+    let [x] = g(); return x;
+  })());
+
+  assertEquals(42, (() => {
+    const [x] = g(); return x;
+  })());
+
+  assertEquals(42, (() => {
+    [x] = g(); return x;
+  })());
+
+  assertEquals(42,
+    (([x]) => x)(g())
+  );
+}
+
+
+// Return method is not callable.
+{
+  g.prototype.return = 666;
+
+
+  assertThrows(() => {
+    for (var x of g()) { break; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (let x of g()) { break; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (const x of g()) { break; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (x of g()) { break; }
+  }, TypeError);
+
+
+  assertThrows(() => {
+    for (var x of g()) { throw 666; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (let x of g()) { throw 666; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (const x of g()) { throw 666; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (x of g()) { throw 666; }
+  }, TypeError);
+
+
+  assertThrows(() => {
+    for (var x of g()) { return 666; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (let x of g()) { return 666; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (const x of g()) { return 666; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (x of g()) { return 666; }
+  }, TypeError);
+
+
+  assertEquals(42, eval('for (var x of g()) { x; }'));
+
+  assertEquals(42, eval('for (let x of g()) { x; }'));
+
+  assertEquals(42, eval('for (const x of g()) { x; }'));
+
+  assertEquals(42, eval('for (x of g()) { x; }'));
+
+
+  assertThrows(() => {
+    var [x] = g(); return x;
+  }, TypeError);
+
+  assertThrows(() => {
+    let [x] = g(); return x;
+  }, TypeError);
+
+  assertThrows(() => {
+    const [x] = g(); return x;
+  }, TypeError);
+
+  assertThrows(() => {
+    [x] = g(); return x;
+  }, TypeError);
+
+  assertThrows(() => {
+    (([x]) => x)(g());
+  }, TypeError);
+}
+
+
+// Return method does not return an object.
+{
+  g.prototype.return = () => 666;
+
+
+  assertThrows(() => {
+    for (var x of g()) { break; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (let x of g()) { break; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (const x of g()) { break; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (x of g()) { break; }
+  }, TypeError);
+
+
+  // Throw from the body of a for loop 'wins' vs throw
+  // originating from a bad 'return' value.
+
+  assertThrowsEquals(() => {
+    for (var x of g()) { throw 666; }
+  }, 666);
+
+  assertThrowsEquals(() => {
+    for (let x of g()) { throw 666; }
+  }, 666);
+
+  assertThrowsEquals(() => {
+    for (const x of g()) { throw 666; }
+  }, 666);
+
+  assertThrowsEquals(() => {
+    for (x of g()) { throw 666; }
+  }, 666);
+
+
+  assertThrows(() => {
+    for (var x of g()) { return 666; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (let x of g()) { return 666; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (const x of g()) { return 666; }
+  }, TypeError);
+
+  assertThrows(() => {
+    for (x of g()) { return 666; }
+  }, TypeError);
+
+
+  assertEquals(42, eval('for (var x of g()) { x; }'));
+
+  assertEquals(42, eval('for (let x of g()) { x; }'));
+
+  assertEquals(42, eval('for (const x of g()) { x; }'));
+
+  assertEquals(42, eval('for (x of g()) { x; }'));
+
+
+  assertThrows(() => {
+    var [x] = g(); return x;
+  }, TypeError);
+
+  assertThrows(() => {
+    let [x] = g(); return x;
+  }, TypeError);
+
+  assertThrows(() => {
+    const [x] = g(); return x;
+  }, TypeError);
+
+  assertThrows(() => {
+    [x] = g(); return x;
+  }, TypeError);
+
+  assertThrows(() => {
+    (([x]) => x)(g());
+  }, TypeError);
+}
+
+
+// Return method returns an object.
+{
+  let log = [];
+  g.prototype.return = (...args) => { log.push(args); return {} };
+
+
+  log = [];
+  for (var x of g()) { break; }
+  assertEquals([[]], log);
+
+  log = [];
+  for (let x of g()) { break; }
+  assertEquals([[]], log);
+
+  log = [];
+  for (const x of g()) { break; }
+  assertEquals([[]], log);
+
+  log = [];
+  for (x of g()) { break; }
+  assertEquals([[]], log);
+
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (var x of g()) { throw 42; }
+  }, 42);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (let x of g()) { throw 42; }
+  }, 42);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (const x of g()) { throw 42; }
+  }, 42);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (x of g()) { throw 42; }
+  }, 42);
+  assertEquals([[]], log);
+
+
+  log = [];
+  assertEquals(42, (() => {
+    for (var x of g()) { return 42; }
+  })());
+  assertEquals([[]], log);
+
+  log = [];
+  assertEquals(42, (() => {
+    for (let x of g()) { return 42; }
+  })());
+  assertEquals([[]], log);
+
+  log = [];
+  assertEquals(42, (() => {
+    for (const x of g()) { return 42; }
+  })());
+  assertEquals([[]], log);
+
+  log = [];
+  assertEquals(42, (() => {
+    for (x of g()) { return 42; }
+  })());
+  assertEquals([[]], log);
+
+
+  log = [];
+  assertEquals(42, eval('for (var x of g()) { x; }'));
+  assertEquals([], log);
+
+  log = [];
+  assertEquals(42, eval('for (let x of g()) { x; }'));
+  assertEquals([], log);
+
+  log = [];
+  assertEquals(42, eval('for (const x of g()) { x; }'));
+  assertEquals([], log);
+
+  log = [];
+  assertEquals(42, eval('for (x of g()) { x; }'));
+  assertEquals([], log);
+
+
+  // Even if doing the assignment throws, still call return
+  log = [];
+  x = { set attr(_) { throw 1234; } };
+  assertThrowsEquals(() => {
+    for (x.attr of g()) { throw 456; }
+  }, 1234);
+  assertEquals([[]], log);
+
+
+  log = [];
+  assertEquals(42, (() => {
+    var [x] = g(); return x;
+  })());
+  assertEquals([[]], log);
+
+  log = [];
+  assertEquals(42, (() => {
+    let [x] = g(); return x;
+  })());
+  assertEquals([[]], log);
+
+  log = [];
+  assertEquals(42, (() => {
+    const [x] = g(); return x;
+  })());
+  assertEquals([[]], log);
+
+  log = [];
+  assertEquals(42, (() => {
+    [x] = g(); return x;
+  })());
+  assertEquals([[]], log);
+
+  log = []
+  assertEquals(42,
+    (([x]) => x)(g())
+  );
+  assertEquals([[]], log);
+
+
+  log = [];
+  assertEquals(42, (() => {
+    var [x,] = g(); return x;
+  })());
+  assertEquals([[]], log);
+
+  log = [];
+  assertEquals(42, (() => {
+    let [x,] = g(); return x;
+  })());
+  assertEquals([[]], log);
+
+  log = [];
+  assertEquals(42, (() => {
+    const [x,] = g(); return x;
+  })());
+  assertEquals([[]], log);
+
+  log = [];
+  assertEquals(42, (() => {
+    [x,] = g(); return x;
+  })());
+  assertEquals([[]], log);
+
+  log = []
+  assertEquals(42,
+    (([x,]) => x)(g())
+  );
+  assertEquals([[]], log);
+
+
+  log = [];
+  assertEquals(42, (() => {
+    var [x,,] = g(); return x;
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals(42, (() => {
+    let [x,,] = g(); return x;
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals(42, (() => {
+    const [x,,] = g(); return x;
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals(42, (() => {
+    [x,,] = g(); return x;
+  })());
+  assertEquals([], log);
+
+  log = []
+  assertEquals(42,
+    (([x,,]) => x)(g())
+  );
+  assertEquals([], log);
+
+
+  log = [];
+  assertEquals([42, undefined], (() => {
+    var [x, y] = g(); return [x, y];
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([42, undefined], (() => {
+    let [x, y] = g(); return [x, y];
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([42, undefined], (() => {
+    const [x, y] = g(); return [x, y];
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([42, undefined], (() => {
+    [x, y] = g(); return [x, y];
+  })());
+  assertEquals([], log);
+
+  log = []
+  assertEquals([42, undefined],
+    (([x, y]) => [x, y])(g())
+  );
+  assertEquals([], log);
+
+
+  log = [];
+  assertEquals([42], (() => {
+    var [...x] = g(); return x;
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([42], (() => {
+    let [...x] = g(); return x;
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([42], (() => {
+    const [...x] = g(); return x;
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([42], (() => {
+    [...x] = g(); return x;
+  })());
+  assertEquals([], log);
+
+  log = []
+  assertEquals([42],
+    (([...x]) => x)(g())
+  );
+  assertEquals([], log);
+
+
+  log = [];
+  assertEquals([42, []], (() => {
+    var [x, ...y] = g(); return [x, y];
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([42, []], (() => {
+    let [x, ...y] = g(); return [x, y];
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([42, []], (() => {
+    const [x, ...y] = g(); return [x, y];
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([42, []], (() => {
+    [x, ...y] = g(); return [x, y];
+  })());
+  assertEquals([], log);
+
+  log = []
+  assertEquals([42, []],
+    (([x, ...y]) => [x, y])(g())
+  );
+  assertEquals([], log);
+
+
+  log = [];
+  assertEquals([], (() => {
+    var [] = g(); return [];
+  })());
+  assertEquals([[]], log);
+
+  log = [];
+  assertEquals([], (() => {
+    let [] = g(); return [];
+  })());
+  assertEquals([[]], log);
+
+  log = [];
+  assertEquals([], (() => {
+    const [] = g(); return [];
+  })());
+  assertEquals([[]], log);
+
+  log = [];
+  assertEquals([], (() => {
+    [] = g(); return [];
+  })());
+  assertEquals([[]], log);
+
+  log = []
+  assertEquals([],
+    (([]) => [])(g())
+  );
+  assertEquals([[]], log);
+
+
+  log = [];
+  assertEquals([], (() => {
+    var [...[]] = g(); return [];
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([], (() => {
+    let [...[]] = g(); return [];
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([], (() => {
+    const [...[]] = g(); return [];
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([], (() => {
+    [...[]] = g(); return [];
+  })());
+  assertEquals([], log);
+
+  log = []
+  assertEquals([],
+    (([...[]]) => [])(g())
+  );
+  assertEquals([], log);
+
+
+  log = [];
+  assertEquals([42], (() => {
+    var [...[x]] = g(); return [x];
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([42], (() => {
+    let [...[x]] = g(); return [x];
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([42], (() => {
+    const [...[x]] = g(); return [x];
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([42], (() => {
+    [...[x]] = g(); return [x];
+  })());
+  assertEquals([], log);
+
+  log = []
+  assertEquals([42],
+    (([...[x]]) => [x])(g())
+  );
+  assertEquals([], log);
+
+
+  log = [];
+  assertEquals([42, undefined], (() => {
+    var [...[x, y]] = g(); return [x, y];
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([42, undefined], (() => {
+    let [...[x, y]] = g(); return [x, y];
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([42, undefined], (() => {
+    const [...[x, y]] = g(); return [x, y];
+  })());
+  assertEquals([], log);
+
+  log = [];
+  assertEquals([42, undefined], (() => {
+    [...[x, y]] = g(); return [x, y];
+  })());
+  assertEquals([], log);
+
+  log = []
+  assertEquals([42, undefined],
+    (([...[x, y]]) => [x, y])(g())
+  );
+  assertEquals([], log);
+
+
+  log = []
+  assertThrowsEquals(() => {
+    let x = { set foo(_) { throw 666; } };
+    [x.foo] = g();
+  }, 666);
+  assertEquals([[]], log);
+
+
+  log = []
+  assertThrows(() => {
+    var [[]] = g();
+  }, TypeError);
+  assertEquals([[]], log);
+
+  log = []
+  assertThrows(() => {
+    let [[]] = g();
+  }, TypeError);
+  assertEquals([[]], log);
+
+  log = []
+  assertThrows(() => {
+    const [[]] = g();
+  }, TypeError);
+  assertEquals([[]], log);
+
+  log = []
+  assertThrows(() => {
+    [[]] = g();
+  }, TypeError);
+  assertEquals([[]], log);
+
+  log = []
+  assertThrows(() => {
+    (([[]]) => 0)(g());
+  }, TypeError);
+  assertEquals([[]], log);
+
+
+  log = []
+  assertThrows(() => {
+    var [...[[]]] = g();
+  }, TypeError);
+  assertEquals([], log);
+
+  log = []
+  assertThrows(() => {
+    let [...[[]]] = g();
+  }, TypeError);
+  assertEquals([], log);
+
+  log = []
+  assertThrows(() => {
+    const [...[[]]] = g();
+  }, TypeError);
+  assertEquals([], log);
+
+  log = []
+  assertThrows(() => {
+    [...[[]]] = g();
+  }, TypeError);
+  assertEquals([], log);
+
+  log = []
+  assertThrows(() => {
+    (([...[[]]]) => 0)(g());
+  }, TypeError);
+  assertEquals([], log);
+
+
+  {
+    let backup = Array.prototype[Symbol.iterator];
+    Array.prototype[Symbol.iterator] = () => g();
+
+
+    log = [];
+    assertDoesNotThrow(() => {
+      var [x, ...[y]] = [1, 2, 3]
+    });
+    assertEquals(log, [[]]);
+
+    log = [];
+    assertDoesNotThrow(() => {
+      let [x, ...[y]] = [1, 2, 3];
+    });
+    assertEquals(log, [[]]);
+
+    log = [];
+    assertDoesNotThrow(() => {
+      const [x, ...[y]] = [1, 2, 3];
+    });
+    assertEquals(log, [[]]);
+
+    log = [];
+    assertDoesNotThrow(() => {
+      (([x, ...[y]]) => {})([1, 2, 3]);
+    });
+    assertEquals(log, [[]]);
+
+
+    log = [];
+    assertThrows(() => {
+      var [x, ...[[]]] = [1, 2, 3];
+    }, TypeError);
+    assertEquals(log, [[]]);
+
+    log = [];
+    assertThrows(() => {
+      let [x, ...[[]]] = [1, 2, 3];
+    }, TypeError);
+    assertEquals(log, [[]]);
+
+    log = [];
+    assertThrows(() => {
+      const [x, ...[[]]] = [1, 2, 3];
+    }, TypeError);
+    assertEquals(log, [[]]);
+
+    log = [];
+    assertThrows(() => {
+      (([x, ...[[]]]) => {})([1, 2, 3]);
+    }, TypeError);
+    assertEquals(log, [[]]);
+
+
+    log = [];
+    assertDoesNotThrow(() => {
+      var [x, ...[...y]] = [1, 2, 3];
+    });
+    assertEquals(log, []);
+
+    log = [];
+    assertDoesNotThrow(() => {
+      let [x, ...[...y]] = [1, 2, 3];
+    });
+    assertEquals(log, []);
+
+    log = [];
+    assertDoesNotThrow(() => {
+      const [x, ...[...y]] = [1, 2, 3];
+    });
+    assertEquals(log, []);
+
+    log = [];
+    assertDoesNotThrow(() => {
+      (([x, ...[...y]]) => {})([1, 2, 3]);
+    });
+    assertEquals(log, []);
+
+
+    Array.prototype[Symbol.iterator] = backup;
+  }
+}
+
+
+// Return method throws.
+{
+  let log = [];
+  g.prototype.return = (...args) => { log.push(args); throw 23 };
+
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (var x of g()) { break; }
+  }, 23);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (let x of g()) { break; }
+  }, 23);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (const x of g()) { break; }
+  }, 23);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (x of g()) { break; }
+  }, 23);
+  assertEquals([[]], log);
+
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (var x of g()) { throw 42; }
+  }, 42);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (let x of g()) { throw 42; }
+  }, 42);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (const x of g()) { throw 42; }
+  }, 42);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (x of g()) { throw 42; }
+  }, 42);
+  assertEquals([[]], log);
+
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (var x of g()) { return 42; }
+  }, 23);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (let x of g()) { return 42; }
+  }, 23);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (const x of g()) { return 42; }
+  }, 23);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (x of g()) { return 42; }
+  }, 23);
+  assertEquals([[]], log);
+
+
+  log = [];
+  assertEquals(42, eval('for (var x of g()) { x; }'));
+  assertEquals([], log);
+
+  log = [];
+  assertEquals(42, eval('for (let x of g()) { x; }'));
+  assertEquals([], log);
+
+  log = [];
+  assertEquals(42, eval('for (const x of g()) { x; }'));
+  assertEquals([], log);
+
+  log = [];
+  assertEquals(42, eval('for (x of g()) { x; }'));
+  assertEquals([], log);
+
+
+  log = [];
+  assertThrowsEquals(() => {
+    var [x] = g(); return x;
+  }, 23);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    let [x] = g(); return x;
+  }, 23);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    const [x] = g(); return x;
+  }, 23);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    [x] = g(); return x;
+  }, 23);
+  assertEquals([[]], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    (([x]) => x)(g())
+  }, 23);
+  assertEquals([[]], log);
+}
+
+
+// Next method throws.
+{
+  g.prototype.next = () => { throw 666; };
+  g.prototype.return = () => { assertUnreachable() };
+
+
+  assertThrowsEquals(() => {
+    for (var x of g()) {}
+  }, 666);
+
+  assertThrowsEquals(() => {
+    for (let x of g()) {}
+  }, 666);
+
+  assertThrowsEquals(() => {
+    for (const x of g()) {}
+  }, 666);
+
+  assertThrowsEquals(() => {
+    for (x of g()) {}
+  }, 666);
+
+  assertThrowsEquals(() => {
+    var [x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    let [x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    const [x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    [x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    (([x]) => x)(g());
+  }, 666);
+
+  assertThrowsEquals(() => {
+    var [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    let [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    const [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    (([...x]) => x)(g());
+  }, 666);
+}
+
+
+// Value throws.
+{
+  g.prototype.next = () => ({get value() {throw 666}});
+  g.prototype.return = () => { assertUnreachable() };
+
+
+  assertThrowsEquals(() => {
+    for (var x of g()) {}
+  }, 666);
+
+  assertThrowsEquals(() => {
+    for (let x of g()) {}
+  }, 666);
+
+  assertThrowsEquals(() => {
+    for (const x of g()) {}
+  }, 666);
+
+  assertThrowsEquals(() => {
+    for (x of g()) {}
+  }, 666);
+
+  assertThrowsEquals(() => {
+    var [x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    let [x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    const [x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    [x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    (([x]) => x)(g());
+  }, 666);
+
+  assertThrowsEquals(() => {
+    var [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    let [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    const [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    (([...x]) => x)(g());
+  }, 666);
+}
+
+
+// Done throws.
+{
+  g.prototype.next = () => ({get done() {throw 666}});
+  g.prototype.return = () => { assertUnreachable() };
+
+
+  assertThrowsEquals(() => {
+    for (var x of g()) {}
+  }, 666);
+
+  assertThrowsEquals(() => {
+    for (let x of g()) {}
+  }, 666);
+
+  assertThrowsEquals(() => {
+    for (const x of g()) {}
+  }, 666);
+
+  assertThrowsEquals(() => {
+    for (x of g()) {}
+  }, 666);
+
+  assertThrowsEquals(() => {
+    var [x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    let [x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    const [x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    [x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    (([x]) => x)(g());
+  }, 666);
+
+  assertThrowsEquals(() => {
+    var [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    let [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    const [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    [...x] = g();
+  }, 666);
+
+  assertThrowsEquals(() => {
+    (([...x]) => x)(g());
+  }, 666);
+}
+
+
+// Nested loops.
+{
+  function* g1() { yield 1; yield 2; throw 3; }
+  function* g2() { yield -1; yield -2; throw -3; }
+
+  assertDoesNotThrow(() => {
+    for (let x of g1()) {
+      for (let y of g2()) {
+        if (y == -2) break;
+      }
+      if (x == 2) break;
+    }
+  }, -3);
+
+  assertThrowsEquals(() => {
+    for (let x of g1()) {
+      for (let y of g2()) {
+      }
+    }
+  }, -3);
+
+  assertThrowsEquals(() => {
+    for (let x of g1()) {
+      for (let y of g2()) {
+        if (y == -2) break;
+      }
+    }
+  }, 3);
+
+  assertDoesNotThrow(() => {
+    l: for (let x of g1()) {
+      for (let y of g2()) {
+        if (y == -2) break l;
+      }
+    }
+  });
+
+  assertThrowsEquals(() => {
+    for (let x of g1()) {
+      for (let y of g2()) {
+        throw 4;
+      }
+    }
+  }, 4);
+
+  assertThrowsEquals(() => {
+    for (let x of g1()) {
+      for (let y of g2()) {
+        if (y == -2) throw 4;
+      }
+    }
+  }, 4);
+
+  let log = [];
+  g1.prototype.return = () => { log.push(1); throw 5 };
+  g2.prototype.return = () => { log.push(2); throw -5 };
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (let x of g1()) {
+      for (let y of g2()) {
+        if (y == -2) break;
+      }
+      if (x == 2) break;
+    }
+  }, -5);
+  assertEquals([2, 1], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (let x of g1()) {
+      for (let y of g2()) {
+      }
+    }
+  }, -3);
+  assertEquals([1], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (let x of g1()) {
+      for (let y of g2()) {
+        if (y == -2) break;
+      }
+    }
+  }, -5);
+  assertEquals([2, 1], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    l: for (let x of g1()) {
+      for (let y of g2()) {
+        if (y == -2) break l;
+      }
+    }
+  }, -5);
+  assertEquals([2, 1], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (let x of g1()) {
+      for (let y of g2()) {
+        throw 4;
+      }
+    }
+  }, 4);
+  assertEquals([2, 1], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (let x of g1()) {
+      for (let y of g2()) {
+        if (y == -2) throw 4;
+      }
+    }
+  }, 4);
+  assertEquals([2, 1], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (let x of g1()) {
+      try {
+        for (let y of g2()) {
+        }
+      } catch (_) {}
+    }
+  }, 3);
+  assertEquals([], log);
+
+  log = [];
+  assertThrowsEquals(() => {
+    for (let x of g1()) {
+      try {
+        for (let y of g2()) {
+        }
+      } catch (_) {}
+      if (x == 2) break;
+    }
+  }, 5);
+  assertEquals([1], log);
+}
+
+
+// yield*, argument's return method is "undefined".
+function TestYieldStarWithoutReturn(get_iterable) {
+  assertTrue(get_iterable().return == undefined);
+
+  function* g() { yield* get_iterable() }
+
+  {
+    let gen = g();
+    assertEquals({value: 1, done: false}, gen.next());
+    assertEquals({value: undefined, done: true}, gen.return());
+  }
+
+  assertEquals(42, (() => {
+    for (let x of g()) break;
+    return 42;
+  })());
+
+  assertEquals(42, (() => {
+    for (let x of g()) return 42;
+  })());
+
+  assertThrowsEquals(() => {
+    for (let x of g()) throw 42;
+  }, 42);
+}
+{
+  let get_iterable1 = () => [1, 2];
+  let get_iterable2 = function*() { yield 1; yield 2 };
+  get_iterable2.prototype.return = null;
+  TestYieldStarWithoutReturn(get_iterable1);
+  TestYieldStarWithoutReturn(get_iterable2);
+}
+
+
+// yield*, argument's return method is defined.
+{
+  let get_iterable = function*() { yield 1; yield 2 };
+  const obj = {};
+  get_iterable.prototype.return = (...args) => obj;
+
+  function* g() { yield* get_iterable() }
+
+  {
+    let gen = g();
+    assertEquals({value: 1, done: false}, gen.next());
+    assertSame(obj, gen.return());
+    assertSame(obj, gen.return());
+    assertSame(obj, gen.return());
+    assertEquals({value: 2, done: false}, gen.next());
+    assertSame(obj, gen.return());
+    assertSame(obj, gen.return());
+    assertSame(obj, gen.return());
+    assertEquals({value: undefined, done: true}, gen.next());
+    assertEquals({value: undefined, done: true}, gen.return());
+    assertEquals({value: undefined, done: true}, gen.return());
+  }
+
+  assertEquals(42, (() => {
+    for (let x of g()) break;
+    return 42;
+  })());
+
+  assertEquals(42, (() => {
+    for (let x of g()) return 42;
+  })());
+
+  assertThrowsEquals(() => {
+    for (let x of g()) throw 42;
+  }, 42);
+}
diff --git a/test/mjsunit/es6/json.js b/test/mjsunit/es6/json.js
index 4c1ada8..c049a25 100644
--- a/test/mjsunit/es6/json.js
+++ b/test/mjsunit/es6/json.js
@@ -9,5 +9,7 @@
   assertTrue(desc.configurable);
   assertFalse(desc.writable);
   assertEquals("JSON", desc.value);
+  delete JSON[Symbol.toStringTag];
+  assertEquals('[object Object]', "" + JSON);
 }
 testJSONToString();
diff --git a/test/mjsunit/es6/legacy-subclassing.js b/test/mjsunit/es6/legacy-subclassing.js
deleted file mode 100644
index dbf666d..0000000
--- a/test/mjsunit/es6/legacy-subclassing.js
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --noharmony-species
-
-// Before Symbol.species was added, ArrayBuffer subclasses constructed
-// ArrayBuffers, and Array subclasses constructed Arrays, but TypedArray and
-// Promise subclasses constructed an instance of the subclass.
-
-'use strict';
-
-assertEquals(undefined, Symbol.species);
-
-class MyArray extends Array { }
-let myArray = new MyArray();
-assertEquals(MyArray, myArray.constructor);
-assertEquals(Array, myArray.map(x => x + 1).constructor);
-assertEquals(Array, myArray.concat().constructor);
-
-class MyUint8Array extends Uint8Array { }
-Object.defineProperty(MyUint8Array.prototype, "BYTES_PER_ELEMENT", {value: 1});
-let myTypedArray = new MyUint8Array(3);
-assertEquals(MyUint8Array, myTypedArray.constructor);
-assertEquals(MyUint8Array, myTypedArray.map(x => x + 1).constructor);
-
-class MyArrayBuffer extends ArrayBuffer { }
-let myBuffer = new MyArrayBuffer(0);
-assertEquals(MyArrayBuffer, myBuffer.constructor);
-assertEquals(ArrayBuffer, myBuffer.slice().constructor);
-
-class MyPromise extends Promise { }
-let myPromise = new MyPromise(() => {});
-assertEquals(MyPromise, myPromise.constructor);
-assertEquals(MyPromise, myPromise.then().constructor);
-
-// However, subarray instantiates members of the parent class
-assertEquals(Uint8Array, myTypedArray.subarray(1).constructor);
diff --git a/test/mjsunit/es6/math-log2-log10.js b/test/mjsunit/es6/math-log2-log10.js
index b1a7736..ea17a79 100644
--- a/test/mjsunit/es6/math-log2-log10.js
+++ b/test/mjsunit/es6/math-log2-log10.js
@@ -57,13 +57,13 @@
 var n = -1074;
 // This loop covers n from -1074 to -1043
 for (var lowbits = 1; lowbits <= 0x80000000; lowbits *= 2) {
-  var x = %_ConstructDouble(0, lowbits);
+  var x = %ConstructDouble(0, lowbits);
   assertEquals(n, Math.log2(x));
   n++;
 }
 // This loop covers n from -1042 to -1023
 for (var hibits = 1; hibits <= 0x80000; hibits *= 2) {
-  var x = %_ConstructDouble(hibits, 0);
+  var x = %ConstructDouble(hibits, 0);
   assertEquals(n, Math.log2(x));
   n++;
 }
diff --git a/test/mjsunit/es6/math.js b/test/mjsunit/es6/math.js
index cb43bd5..dc761d6 100644
--- a/test/mjsunit/es6/math.js
+++ b/test/mjsunit/es6/math.js
@@ -9,5 +9,7 @@
   assertTrue(desc.configurable);
   assertFalse(desc.writable);
   assertEquals("Math", desc.value);
+  delete Math[Symbol.toStringTag];
+  assertEquals('[object Object]', "" + Math);
 }
 testMathToString();
diff --git a/test/mjsunit/es6/microtask-delivery.js b/test/mjsunit/es6/microtask-delivery.js
index 01b971d..6b239be 100644
--- a/test/mjsunit/es6/microtask-delivery.js
+++ b/test/mjsunit/es6/microtask-delivery.js
@@ -25,7 +25,6 @@
 // (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-object-observe
 // Flags: --allow-natives-syntax
 
 var ordering = [];
@@ -71,22 +70,6 @@
   };
 }
 
-function newObserver(id, fn, obj) {
-  var observer = {
-    value: 1,
-    recordCounts: []
-  };
-
-  Object.observe(observer, function(records) {
-    ordering.push('o' + id);
-    observer.recordCounts.push(records.length);
-    if (fn) fn();
-  });
-
-  return observer;
-}
-
-
 (function PromiseThens() {
   reset();
 
@@ -98,72 +81,3 @@
 
   assertOrdering(['p1', 'p2', 'p1:1', 'p2:1']);
 })();
-
-
-(function ObserversBatch() {
-  reset();
-
-  var p1 = newPromise(1);
-  var p2 = newPromise(2);
-  var p3 = newPromise(3);
-
-  var ob1 = newObserver(1);
-  var ob2 = newObserver(2, function() {
-    ob3.value++;
-    p3.resolve();
-    ob1.value++;
-  });
-  var ob3 = newObserver(3);
-
-  p1.resolve();
-  ob1.value++;
-  p2.resolve();
-  ob2.value++;
-
-  assertOrdering(['p1', 'o1', 'o2', 'p2', 'o1', 'o3', 'p3']);
-  assertArrayValues([1, 1], ob1.recordCounts);
-  assertArrayValues([1], ob2.recordCounts);
-  assertArrayValues([1], ob3.recordCounts);
-})();
-
-
-(function ObserversGetAllRecords() {
-  reset();
-
-  var p1 = newPromise(1);
-  var p2 = newPromise(2);
-  var ob1 = newObserver(1, function() {
-    ob2.value++;
-  });
-  var ob2 = newObserver(2);
-
-  p1.resolve();
-  ob1.value++;
-  p2.resolve();
-  ob2.value++;
-
-  assertOrdering(['p1', 'o1', 'o2', 'p2']);
-  assertArrayValues([1], ob1.recordCounts);
-  assertArrayValues([2], ob2.recordCounts);
-})();
-
-
-(function NewObserverDeliveryGetsNewMicrotask() {
-  reset();
-
-  var p1 = newPromise(1);
-  var p2 = newPromise(2);
-  var ob1 = newObserver(1);
-  var ob2 = newObserver(2, function() {
-    ob1.value++;
-  });
-
-  p1.resolve();
-  ob1.value++;
-  p2.resolve();
-  ob2.value++;
-
-  assertOrdering(['p1', 'o1', 'o2', 'p2', 'o1']);
-  assertArrayValues([1, 1], ob1.recordCounts);
-  assertArrayValues([1], ob2.recordCounts);
-})();
diff --git a/test/mjsunit/es6/mirror-collections.js b/test/mjsunit/es6/mirror-collections.js
index 81a98b8..4232ef9 100644
--- a/test/mjsunit/es6/mirror-collections.js
+++ b/test/mjsunit/es6/mirror-collections.js
@@ -88,16 +88,21 @@
 assertSame(o2, values[0]);
 assertEquals(undefined, values[1]);
 
+function initWeakMap(weakMap) {
+  weakMap.set(o1, 11);
+  weakMap.set(new Object(), 22);
+  weakMap.set(o3, 33);
+  weakMap.set(new Object(), 44);
+  var weakMapMirror = debug.MakeMirror(weakMap);
+  testMapMirror(weakMapMirror);
+  weakMap.set(new Object(), 55);
+  assertTrue(weakMapMirror.entries().length <= 5);
+  return weakMapMirror;
+}
+
 // Test the mirror object for WeakMaps
 var weakMap = new WeakMap();
-weakMap.set(o1, 11);
-weakMap.set(new Object(), 22);
-weakMap.set(o3, 33);
-weakMap.set(new Object(), 44);
-var weakMapMirror = debug.MakeMirror(weakMap);
-testMapMirror(weakMapMirror);
-weakMap.set(new Object(), 55);
-assertTrue(weakMapMirror.entries().length <= 5);
+var weakMapMirror = initWeakMap(weakMap);
 gc();
 
 function testWeakMapEntries(weakMapMirror) {
@@ -121,18 +126,23 @@
 
 testWeakMapEntries(weakMapMirror);
 
+function initWeakSet(weakSet) {
+  weakSet.add(o1);
+  weakSet.add(new Object());
+  weakSet.add(o2);
+  weakSet.add(new Object());
+  weakSet.add(new Object());
+  weakSet.add(o3);
+  weakSet.delete(o2);
+  var weakSetMirror =  debug.MakeMirror(weakSet);
+  testSetMirror(weakSetMirror);
+  assertTrue(weakSetMirror.values().length <= 5);
+  return weakSetMirror;
+}
+
 // Test the mirror object for WeakSets
 var weakSet = new WeakSet();
-weakSet.add(o1);
-weakSet.add(new Object());
-weakSet.add(o2);
-weakSet.add(new Object());
-weakSet.add(new Object());
-weakSet.add(o3);
-weakSet.delete(o2);
-var weakSetMirror = debug.MakeMirror(weakSet);
-testSetMirror(weakSetMirror);
-assertTrue(weakSetMirror.values().length <= 5);
+var weakSetMirror = initWeakSet(weakSet);
 gc();
 
 function testWeakSetValues(weakSetMirror) {
diff --git a/test/mjsunit/es6/no-unicode-regexp-flag.js b/test/mjsunit/es6/no-unicode-regexp-flag.js
deleted file mode 100644
index 82d070e..0000000
--- a/test/mjsunit/es6/no-unicode-regexp-flag.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Before Unicode RegExps are shipped, we shouldn't have the 'unicode'
-// property on RegExp.prototype, or read it from 'flags'.
-// mjsunit/es6/regexp-flags tests that the property is there when the
-// flag is on.
-
-// Flags: --no-harmony-unicode-regexps
-
-'use strict';
-
-assertFalse(RegExp.prototype.hasOwnProperty('unicode'));
-
-// If we were going to be really strict, we could have a test like this,
-// with the assertTrue replaced by assertFalse, since flags shouldn't
-// Get the 'unicode' property. However, it is probably OK to omit this
-// detailed fix.
-var x = /a/;
-var y = false;
-Object.defineProperty(x, 'unicode', { get() { y = true; } });
-assertEquals("", x.flags);
-assertTrue(y);
diff --git a/test/mjsunit/es6/object-tostring.js b/test/mjsunit/es6/object-tostring.js
index 29d07f2..bc7d968 100644
--- a/test/mjsunit/es6/object-tostring.js
+++ b/test/mjsunit/es6/object-tostring.js
@@ -15,15 +15,16 @@
   RegExp:   [ RegExp ],
   Error:    [ Error, TypeError, RangeError, SyntaxError, ReferenceError,
               EvalError, URIError ]
-}
-for (f in funs) {
-  for (i in funs[f]) {
+};
+for (var f in funs) {
+  for (var i in funs[f]) {
+
     assertEquals("[object " + f + "]",
-                 Object.prototype.toString.call(new funs[f][i]),
-                 funs[f][i]);
+      Object.prototype.toString.call(new funs[f][i]),
+      funs[f][i]);
     assertEquals("[object Function]",
-                 Object.prototype.toString.call(funs[f][i]),
-                 funs[f][i]);
+      Object.prototype.toString.call(funs[f][i]),
+      funs[f][i]);
   }
 }
 
@@ -130,11 +131,11 @@
 }
 testObjectToStringPropertyDesc();
 
-function testObjectToStringOwnNonStringValue() {
-  var obj = Object.defineProperty({}, Symbol.toStringTag, { value: 1 });
+function testObjectToStringOnNonStringValue(obj) {
+  Object.defineProperty(obj, Symbol.toStringTag, { value: 1 });
   assertEquals("[object Object]", ({}).toString.call(obj));
 }
-testObjectToStringOwnNonStringValue();
+testObjectToStringOnNonStringValue({});
 
 
 // Proxies
@@ -149,11 +150,77 @@
 assertTag("Foo", new Proxy(() => 42, {get() {return "Foo"}}));
 assertTag("Function", new Proxy(() => 42, {get() {return 666}}));
 
-revocable = Proxy.revocable([], {});
+var revocable = Proxy.revocable([], {});
 revocable.revoke();
 assertThrows(() => Object.prototype.toString.call(revocable.proxy), TypeError);
 
-handler = {};
+var handler = {};
 revocable = Proxy.revocable([], handler);
+// The first get() call, i.e., toString() revokes the proxy
 handler.get = () => revocable.revoke();
+assertEquals("[object Array]", Object.prototype.toString.call(revocable.proxy));
 assertThrows(() => Object.prototype.toString.call(revocable.proxy), TypeError);
+
+revocable = Proxy.revocable([], handler);
+handler.get = () => {revocable.revoke(); return "value";};
+assertEquals("[object value]", Object.prototype.toString.call(revocable.proxy));
+assertThrows(() => Object.prototype.toString.call(revocable.proxy), TypeError);
+
+
+revocable = Proxy.revocable(function() {}, handler);
+handler.get = () => revocable.revoke();
+assertEquals("[object Function]", Object.prototype.toString.call(revocable.proxy));
+assertThrows(() => Object.prototype.toString.call(revocable.proxy), TypeError);
+
+function* gen() { yield 1; }
+
+assertTag("GeneratorFunction", gen);
+Object.defineProperty(gen, Symbol.toStringTag, {writable: true});
+gen[Symbol.toStringTag] = "different string";
+assertTag("different string", gen);
+gen[Symbol.toStringTag] = 1;
+assertTag("Function", gen);
+
+function overwriteToStringTagWithNonStringValue(tag, obj) {
+  assertTag(tag, obj);
+
+  Object.defineProperty(obj, Symbol.toStringTag, {
+    configurable: true,
+    value: "different string"
+  });
+  assertTag("different string", obj);
+
+  testObjectToStringOnNonStringValue(obj);
+}
+
+overwriteToStringTagWithNonStringValue("global", global);
+overwriteToStringTagWithNonStringValue("Generator", gen());
+
+var arrayBuffer = new ArrayBuffer();
+overwriteToStringTagWithNonStringValue("ArrayBuffer", arrayBuffer);
+overwriteToStringTagWithNonStringValue("DataView", new DataView(arrayBuffer));
+
+overwriteToStringTagWithNonStringValue("Int8Array", new Int8Array());
+overwriteToStringTagWithNonStringValue("Uint8Array", new Uint8Array());
+overwriteToStringTagWithNonStringValue("Uint8ClampedArray",
+  new Uint8ClampedArray());
+overwriteToStringTagWithNonStringValue("Int16Array", new Int16Array());
+overwriteToStringTagWithNonStringValue("Uint16Array", new Uint16Array());
+overwriteToStringTagWithNonStringValue("Int32Array", new Int32Array());
+overwriteToStringTagWithNonStringValue("Uint32Array", new Uint32Array());
+overwriteToStringTagWithNonStringValue("Float32Array", new Float32Array());
+overwriteToStringTagWithNonStringValue("Float64Array", new Float64Array());
+
+var set = new Set();
+var map = new Map();
+
+overwriteToStringTagWithNonStringValue("Set", set);
+overwriteToStringTagWithNonStringValue("Map", map);
+
+overwriteToStringTagWithNonStringValue("Set Iterator", set[Symbol.iterator]());
+overwriteToStringTagWithNonStringValue("Map Iterator", map[Symbol.iterator]());
+
+overwriteToStringTagWithNonStringValue("WeakSet", new WeakSet());
+overwriteToStringTagWithNonStringValue("WeakMap", new WeakMap());
+
+overwriteToStringTagWithNonStringValue("Promise", new Promise(function() {}));
diff --git a/test/mjsunit/es6/pattern-brand-check.js b/test/mjsunit/es6/pattern-brand-check.js
index 9b0c011..2e32294 100644
--- a/test/mjsunit/es6/pattern-brand-check.js
+++ b/test/mjsunit/es6/pattern-brand-check.js
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-regexp-subclass
-
 function createNonRegExp(calls) {
   return {
     get [Symbol.match]() {
diff --git a/test/mjsunit/es6/promise-species.js b/test/mjsunit/es6/promise-species.js
new file mode 100644
index 0000000..f6f2e7a
--- /dev/null
+++ b/test/mjsunit/es6/promise-species.js
@@ -0,0 +1,42 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+// Test that Promises use @@species appropriately
+
+// Another constructor with no species will not be instantiated
+var test = new Promise(function(){});
+var bogoCount = 0;
+function bogusConstructor() { bogoCount++; }
+test.constructor = bogusConstructor;
+assertTrue(Promise.resolve(test) instanceof Promise);
+assertFalse(Promise.resolve(test) instanceof bogusConstructor);
+// Tests that chromium:575314 is fixed thoroughly
+Promise.resolve(test).catch(e => %AbortJS("Error " + e)).then(() => {
+  if (bogoCount != 0) %AbortJS("bogoCount was " + bogoCount + " should be 0");
+});
+
+// If there is a species, it will be instantiated
+// @@species will be read exactly once, and the constructor is called with a
+// function
+var count = 0;
+var params;
+class MyPromise extends Promise {
+  constructor(...args) {
+    super(...args);
+    params = args;
+  }
+  static get [Symbol.species]() {
+    count++
+    return this;
+  }
+}
+
+var myPromise = MyPromise.resolve().then();
+assertEquals(1, count);
+assertEquals(1, params.length);
+assertEquals('function', typeof(params[0]));
+assertTrue(myPromise instanceof MyPromise);
+assertTrue(myPromise instanceof Promise);
diff --git a/test/mjsunit/es6/proxies-for.js b/test/mjsunit/es6/proxies-for.js
index 5b81845..2b3060b 100644
--- a/test/mjsunit/es6/proxies-for.js
+++ b/test/mjsunit/es6/proxies-for.js
@@ -151,7 +151,7 @@
   object.__proto__ = proxy;
   assertEquals(["0"], keys(object));
 
-  // The Proxy doesn't set his ownKeys enumerable.
+  // The Proxy doesn't set its ownKeys enumerable.
   delete object[0];
   assertEquals([], keys(object));
 
@@ -209,10 +209,15 @@
   assertThrowsEquals(() => {keys(proxy)}, "error");
 })();
 
-
-(function () {
-  var symbol = Symbol();
-  var p = new Proxy({}, {ownKeys() { return ["1", symbol, "2"] }});
-  assertEquals(["1","2"], Object.getOwnPropertyNames(p));
-  assertEquals([symbol], Object.getOwnPropertySymbols(p));
+(function testNestedProxy() {
+  var handler = {
+    ownKeys() {
+      return ['c'];
+    },
+    getOwnPropertyDescriptor() { return {configurable: true, enumerable: true } }
+  }
+  var proxy = new Proxy({}, handler);
+  var proxy2 = new Proxy(proxy, {});
+  assertEquals(['c'], keys(proxy));
+  assertEquals(['c'], keys(proxy2));
 })();
diff --git a/test/mjsunit/es6/proxies-json.js b/test/mjsunit/es6/proxies-json.js
index d48d539..6b40e3e 100644
--- a/test/mjsunit/es6/proxies-json.js
+++ b/test/mjsunit/es6/proxies-json.js
@@ -35,7 +35,10 @@
   // Test fast case that bails out to slow case.
   assertEquals(expected, JSON.stringify(object));
   // Test slow case.
-  assertEquals(expected, JSON.stringify(object, undefined, 0));
+  assertEquals(expected, JSON.stringify(object, (key, value) => value));
+  // Test gap.
+  assertEquals(JSON.stringify(object, null, "="),
+               JSON.stringify(object, (key, value) => value, "="));
 }
 
 
@@ -67,6 +70,7 @@
 
 var parent1a = { b: proxy1 };
 testStringify('{"b":{"a":"A","b":"B","c":"C"}}', parent1a);
+testStringify('{"b":{"a":"A","b":"B","c":"C"}}', parent1a);
 
 var parent1b = { a: 123, b: proxy1, c: true };
 testStringify('{"a":123,"b":{"a":"A","b":"B","c":"C"},"c":true}', parent1b);
@@ -503,3 +507,56 @@
 assertEquals(["get", target, "length", proxy], log[0]);
 assertEquals(["get", target, "0", proxy], log[1]);
 assertEquals(["deleteProperty", target, "0"], log[2]);
+
+proxy = new Proxy([], {
+  get: function(target, property) {
+    if (property == "length") return 7;
+    return 0;
+  },
+});
+assertEquals('[[0,0,0,0,0,0,0]]', JSON.stringify([proxy]));
+
+proxy = new Proxy([], {
+  get: function(target, property) {
+    if (property == "length") return 1E40;
+    return 0;
+  },
+});
+assertThrows(() => JSON.stringify([proxy]), RangeError);
+
+log = [];
+proxy = new Proxy({}, {
+  ownKeys: function() {
+    log.push("ownKeys");
+    return ["0", "a", "b"];
+  },
+  get: function(target, property) {
+    log.push("get " + property);
+    return property.toUpperCase();
+  },
+  getOwnPropertyDescriptor: function(target, property) {
+    log.push("descriptor " + property);
+    return {enumerable: true, configurable: true};
+  },
+  isExtensible: assertUnreachable,
+  has: assertUnreachable,
+  getPrototypeOf: assertUnreachable,
+  setPrototypeOf: assertUnreachable,
+  preventExtensions: assertUnreachable,
+  setPrototypeOf: assertUnreachable,
+  defineProperty: assertUnreachable,
+  set: assertUnreachable,
+  deleteProperty: assertUnreachable,
+  apply: assertUnreachable,
+  construct: assertUnreachable,
+});
+
+assertEquals('[{"0":"0","a":"A","b":"B"}]', JSON.stringify([proxy]));
+assertEquals(['get toJSON',
+              'ownKeys',
+              'descriptor 0',
+              'descriptor a',
+              'descriptor b',
+              'get 0',
+              'get a',
+              'get b'], log);
diff --git a/test/mjsunit/es6/proxies-keys.js b/test/mjsunit/es6/proxies-keys.js
index 7344032..2635ac3 100644
--- a/test/mjsunit/es6/proxies-keys.js
+++ b/test/mjsunit/es6/proxies-keys.js
@@ -37,3 +37,42 @@
 handler.ownKeys = undefined;
 assertEquals(["target"], Object.keys(proxy));
 assertEquals(["target"], Object.keys(target));
+
+var proxy2 = new Proxy(proxy, {});
+assertEquals(["target"], Object.keys(proxy2));
+
+
+(function testForSymbols() {
+  var symbol = Symbol();
+  var p = new Proxy({}, {ownKeys() { return ["1", symbol, "2"] }});
+  assertEquals(["1","2"], Object.getOwnPropertyNames(p));
+  assertEquals([symbol], Object.getOwnPropertySymbols(p));
+})();
+
+(function testNoProxyTraps() {
+  var test_sym = Symbol("sym1");
+  var test_sym2 = Symbol("sym2");
+  var target = {
+    one: 1,
+    two: 2,
+    [test_sym]: 4,
+    0: 0,
+  };
+  Object.defineProperty(
+      target, "non-enum",
+      { enumerable: false, value: "nope", configurable: true, writable: true });
+  target.__proto__ = {
+    target_proto: 3,
+    1: 1,
+    [test_sym2]: 5
+  };
+  Object.defineProperty(
+      target.__proto__, "non-enum2",
+      { enumerable: false, value: "nope", configurable: true, writable: true });
+  var proxy = new Proxy(target, {});
+
+  assertEquals(["0", "one", "two"], Object.keys(proxy));
+  assertEquals(["0", "one", "two", "non-enum"],
+               Object.getOwnPropertyNames(proxy));
+  assertEquals([test_sym], Object.getOwnPropertySymbols(proxy));
+})();
diff --git a/test/mjsunit/es6/reflect-define-property.js b/test/mjsunit/es6/reflect-define-property.js
index b19c5aa..d62a934 100644
--- a/test/mjsunit/es6/reflect-define-property.js
+++ b/test/mjsunit/es6/reflect-define-property.js
@@ -441,8 +441,7 @@
 }
 
 
-// Test runtime calls to DefineDataPropertyUnchecked and
-// DefineAccessorPropertyUnchecked - make sure we don't
+// Test runtime calls to DefineAccessorPropertyUnchecked - make sure we don't
 // crash.
 try {
   %DefineAccessorPropertyUnchecked(0, 0, 0, 0, 0);
@@ -451,29 +450,11 @@
 }
 
 try {
-  %DefineDataPropertyUnchecked(0, 0, 0, 0);
-} catch (e) {
-  assertTrue(/illegal access/.test(e));
-}
-
-try {
-  %DefineDataPropertyUnchecked(null, null, null, null);
-} catch (e) {
-  assertTrue(/illegal access/.test(e));
-}
-
-try {
   %DefineAccessorPropertyUnchecked(null, null, null, null, null);
 } catch (e) {
   assertTrue(/illegal access/.test(e));
 }
 
-try {
-  %DefineDataPropertyUnchecked({}, null, null, null);
-} catch (e) {
-  assertTrue(/illegal access/.test(e));
-}
-
 // Defining properties null should fail even when we have
 // other allowed values
 try {
@@ -482,12 +463,6 @@
   assertTrue(/illegal access/.test(e));
 }
 
-try {
-  %DefineDataPropertyUnchecked(null, 'foo', 0, 0);
-} catch (e) {
-  assertTrue(/illegal access/.test(e));
-}
-
 // Test that all possible differences in step 6 in DefineOwnProperty are
 // exercised, i.e., any difference in the given property descriptor and the
 // existing properties should not return true, but throw an error if the
diff --git a/test/mjsunit/es6/reflect.js b/test/mjsunit/es6/reflect.js
index ee272b0..d597a78 100644
--- a/test/mjsunit/es6/reflect.js
+++ b/test/mjsunit/es6/reflect.js
@@ -541,6 +541,13 @@
       [s2]: 0, "-1": 0, "88": 0, "aaa": 0 };
   assertEquals(["0", "42", "88", "bla", "-1", "aaa", s1, s2],
       Reflect.ownKeys(obj));
+  // Force dict-mode elements.
+  delete obj[0];
+  assertEquals(["42", "88", "bla", "-1", "aaa", s1, s2],
+      Reflect.ownKeys(obj));
+  // Force dict-mode properties.
+  delete obj["bla"];
+  assertEquals(["42", "88", "-1", "aaa", s1, s2], Reflect.ownKeys(obj));
 })();
 
 
diff --git a/test/mjsunit/es6/regexp-constructor.js b/test/mjsunit/es6/regexp-constructor.js
index 559ac00..b685ff2 100644
--- a/test/mjsunit/es6/regexp-constructor.js
+++ b/test/mjsunit/es6/regexp-constructor.js
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-regexp-subclass
-
 "use strict";
 
 function should_not_be_called() {
diff --git a/test/mjsunit/es6/regexp-flags.js b/test/mjsunit/es6/regexp-flags.js
index 480222d..2bcccfa 100644
--- a/test/mjsunit/es6/regexp-flags.js
+++ b/test/mjsunit/es6/regexp-flags.js
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-unicode-regexps
-
 var r1 = /abc/gi;
 assertEquals("abc", r1.source);
 assertTrue(r1.global);
diff --git a/test/mjsunit/es6/regress/regress-3750.js b/test/mjsunit/es6/regress/regress-3750.js
deleted file mode 100644
index 10509bf..0000000
--- a/test/mjsunit/es6/regress/regress-3750.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Flags: --harmony-object-observe
-
-'use strict';
-class Example { }
-Object.observe(Example.prototype, function(){});
diff --git a/test/mjsunit/es6/regress/regress-4482.js b/test/mjsunit/es6/regress/regress-4482.js
new file mode 100644
index 0000000..d813d21
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-4482.js
@@ -0,0 +1,7 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+assertEquals("function", (function f() { f = 42; return typeof f })());
+assertEquals("function",
+             (function* g() { g = 42; yield typeof g })().next().value);
diff --git a/test/mjsunit/es6/regress/regress-468661.js b/test/mjsunit/es6/regress/regress-468661.js
index 4a42350..4a58a71 100644
--- a/test/mjsunit/es6/regress/regress-468661.js
+++ b/test/mjsunit/es6/regress/regress-468661.js
@@ -9,7 +9,8 @@
 var break_count = 0;
 
 var expected_values =
-  [ReferenceError, undefined, 0, 0, 0, 0, 1, ReferenceError, ReferenceError];
+  [ReferenceError, undefined, 0, 0, 0, 0, 1,
+   ReferenceError, ReferenceError];
 
 function listener(event, exec_state, event_data, data) {
   try {
@@ -39,7 +40,6 @@
         assertTrue(v instanceof ReferenceError);
       } else {
         assertSame(expected_values[break_count], v);
-
       }
       ++break_count;
 
diff --git a/test/mjsunit/es6/species.js b/test/mjsunit/es6/species.js
new file mode 100644
index 0000000..39156a4
--- /dev/null
+++ b/test/mjsunit/es6/species.js
@@ -0,0 +1,35 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Test the ES2015 @@species feature
+
+'use strict';
+
+let TypedArray = Uint8Array.__proto__;
+
+// The @@species property exists on the right objects and has the right values
+
+let classesWithSpecies = [RegExp, Array, TypedArray, ArrayBuffer, Map, Set, Promise];
+let classesWithoutSpecies = [Object, Function, String, Number, Symbol, WeakMap, WeakSet];
+
+for (let constructor of classesWithSpecies) {
+  assertEquals(constructor, constructor[Symbol.species]);
+  assertThrows(function() { constructor[Symbol.species] = undefined }, TypeError);
+  let descriptor = Object.getOwnPropertyDescriptor(constructor, Symbol.species);
+  assertTrue(descriptor.configurable);
+  assertFalse(descriptor.enumerable);
+  assertEquals(undefined, descriptor.writable);
+  assertEquals(undefined, descriptor.set);
+  assertEquals('function', typeof descriptor.get);
+}
+
+// @@species is defined with distinct getters
+assertEquals(classesWithSpecies.length,
+             new Set(classesWithSpecies.map(constructor =>
+                                            Object.getOwnPropertyDescriptor(
+                                              constructor, Symbol.species).get)
+                ).size);
+
+for (let constructor of classesWithoutSpecies)
+  assertEquals(undefined, constructor[Symbol.species]);
diff --git a/test/mjsunit/es6/spread-call-new-class.js b/test/mjsunit/es6/spread-call-new-class.js
index 1fdf25b..de88cff 100644
--- a/test/mjsunit/es6/spread-call-new-class.js
+++ b/test/mjsunit/es6/spread-call-new-class.js
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-sloppy
-
 
 (function testConstructClassStrict() {
   "use strict";
diff --git a/test/mjsunit/es6/spread-call-super-property.js b/test/mjsunit/es6/spread-call-super-property.js
index b298a69..a85ea41 100644
--- a/test/mjsunit/es6/spread-call-super-property.js
+++ b/test/mjsunit/es6/spread-call-super-property.js
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-sloppy
-
 (function testCallSuperPropertyStrict() {
   "use strict";
   class BaseClass {
diff --git a/test/mjsunit/es6/string-match.js b/test/mjsunit/es6/string-match.js
new file mode 100644
index 0000000..2c7affe
--- /dev/null
+++ b/test/mjsunit/es6/string-match.js
@@ -0,0 +1,18 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var pattern = {};
+pattern[Symbol.match] = function(string) {
+  return string.length;
+};
+// Check object coercible fails.
+assertThrows(() => String.prototype.match.call(null, pattern),
+             TypeError);
+// Override is called.
+assertEquals(5, "abcde".match(pattern));
+// Non-callable override.
+pattern[Symbol.match] = "dumdidum";
+assertThrows(() => "abcde".match(pattern), TypeError);
+
+assertEquals("[Symbol.match]", RegExp.prototype[Symbol.match].name);
diff --git a/test/mjsunit/es6/string-replace.js b/test/mjsunit/es6/string-replace.js
new file mode 100644
index 0000000..0beb57a
--- /dev/null
+++ b/test/mjsunit/es6/string-replace.js
@@ -0,0 +1,17 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var pattern = {
+  [Symbol.replace]: (string, newValue) => string + newValue
+};
+// Check object coercible fails.
+assertThrows(() => String.prototype.replace.call(null, pattern, "x"),
+             TypeError);
+// Override is called.
+assertEquals("abcdex", "abcde".replace(pattern, "x"));
+// Non-callable override.
+pattern[Symbol.replace] = "dumdidum";
+assertThrows(() => "abcde".replace(pattern, "x"), TypeError);
+
+assertEquals("[Symbol.replace]", RegExp.prototype[Symbol.replace].name);
diff --git a/test/mjsunit/es6/string-search.js b/test/mjsunit/es6/string-search.js
index dc02982..cbdf33d 100644
--- a/test/mjsunit/es6/string-search.js
+++ b/test/mjsunit/es6/string-search.js
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-regexp-subclass
-
 var pattern = {};
 pattern[Symbol.search] = function(string) {
   return string.length;
diff --git a/test/mjsunit/es6/string-split.js b/test/mjsunit/es6/string-split.js
new file mode 100644
index 0000000..8ca655c
--- /dev/null
+++ b/test/mjsunit/es6/string-split.js
@@ -0,0 +1,19 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var pattern = {};
+var limit = { value: 3 };
+pattern[Symbol.split] = function(string, limit) {
+  return string.length * limit.value;
+};
+// Check object coercible fails.
+assertThrows(() => String.prototype.split.call(null, pattern, limit),
+             TypeError);
+// Override is called.
+assertEquals(15, "abcde".split(pattern, limit));
+// Non-callable override.
+pattern[Symbol.split] = "dumdidum";
+assertThrows(() => "abcde".split(pattern, limit), TypeError);
+
+assertEquals("[Symbol.split]", RegExp.prototype[Symbol.split].name);
diff --git a/test/mjsunit/es6/super.js b/test/mjsunit/es6/super.js
index a2ba1e8..4c80ce7 100644
--- a/test/mjsunit/es6/super.js
+++ b/test/mjsunit/es6/super.js
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 // Flags: --allow-natives-syntax
-// Flags: --harmony-sloppy
 
 (function TestSuperNamedLoads() {
   function Base() { }
diff --git a/test/mjsunit/es6/symbols.js b/test/mjsunit/es6/symbols.js
index 9bac41f..a21afb3 100644
--- a/test/mjsunit/es6/symbols.js
+++ b/test/mjsunit/es6/symbols.js
@@ -555,7 +555,9 @@
 
 function TestStringify(expected, input) {
   assertEquals(expected, JSON.stringify(input));
-  assertEquals(expected, JSON.stringify(input, null, 0));
+  assertEquals(expected, JSON.stringify(input, (key, value) => value));
+  assertEquals(JSON.stringify(input, null, "="),
+               JSON.stringify(input, (key, value) => value, "="));
 }
 
 TestStringify(undefined, Symbol("a"));
diff --git a/test/mjsunit/es6/tail-call-megatest.js b/test/mjsunit/es6/tail-call-megatest.js
index 1de8ec6..3d2ecb8 100644
--- a/test/mjsunit/es6/tail-call-megatest.js
+++ b/test/mjsunit/es6/tail-call-megatest.js
@@ -10,6 +10,7 @@
   return error.message + "\n    at " + stack.join("\n    at ");
 }
 
+var verbose = typeof(arguments) !== "undefined" && arguments.indexOf("-v") >= 0;
 
 function checkStackTrace(expected) {
   var e = new Error();
@@ -340,32 +341,32 @@
     return source;
   }
 
-  var f_args_variants = ["", "1", "1, 2"];
-  var g_args_variants = ["", "10", "10, 20"];
+  var f_args_variants = [/*"", "1",*/ "1, 2"];
+  var g_args_variants = [/*"", "10",*/ "10, 20"];
   var f_inlinable_variants = [true, false];
   var g_inlinable_variants = [true, false];
   // This is to avoid bailing out because of referencing new.target.
-  var check_new_target_variants = [true, false];
+  var check_new_target_variants = [/*true,*/ false];
   var deopt_mode_variants = ["none", "f", "g", "test"];
   var f_variants = [
       f_cfg_sloppy,
       f_cfg_strict,
       f_cfg_bound,
       f_cfg_proxy,
-      f_cfg_possibly_eval,
+//      f_cfg_possibly_eval,
   ];
   var g_variants = [
       g_cfg_normal,
-      g_cfg_reflect_apply,
+//      g_cfg_reflect_apply,
       g_cfg_function_apply,
-      g_cfg_function_apply_arguments_object,
+//      g_cfg_function_apply_arguments_object,
       g_cfg_function_call,
   ];
   var test_warmup_counts = [0, 1, 2];
 
   var iter = 0;
   var tests_executed = 0;
-  if (shard !== undefined) {
+  if (verbose && shard !== undefined) {
     print("Running shard #" + shard);
   }
   f_variants.forEach((f_cfg) => {
@@ -378,7 +379,9 @@
                 g_inlinable_variants.forEach((g_inlinable) => {
                   test_warmup_counts.forEach((test_warmup_count) => {
                     if (shard !== undefined && (iter++) % SHARDS_COUNT != shard) {
-                      print("skipping...");
+                      if (verbose) {
+                        print("skipping...");
+                      }
                       return;
                     }
                     tests_executed++;
@@ -396,8 +399,10 @@
                       deopt_mode,
                     };
                     var source = test_template(cfg);
-                    print("====================");
-                    print(source);
+                    if (verbose) {
+                      // print("====================");
+                      // print(source);
+                    }
                     eval(source);
                   });
                 });
@@ -408,7 +413,9 @@
       });
     });
   });
-  print("Number of tests executed: " + tests_executed);
+  if (verbose) {
+    print("Number of tests executed: " + tests_executed);
+  }
 }
 
 // Uncomment to run all the tests at once or use shard runners.
diff --git a/test/mjsunit/es6/tail-call.js b/test/mjsunit/es6/tail-call.js
index d0d00f4..6ecf04f 100644
--- a/test/mjsunit/es6/tail-call.js
+++ b/test/mjsunit/es6/tail-call.js
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 // Flags: --allow-natives-syntax --harmony-tailcalls
+// Flags: --harmony-do-expressions
+
 "use strict";
 
 Error.prepareStackTrace = (error,stack) => {
@@ -259,9 +261,8 @@
   }
   %NeverOptimizeFunction(g);
 
-  var context = 10;
   function f(v) {
-    return g(context);
+    return g();
   }
   %SetForceInlineFlag(f);
 
@@ -319,10 +320,57 @@
     return f([f, g3, test], 13), f([f, test], 153);
   }
 
+  function g4(a) {
+    return f([f, g4, test], false) ||
+        (f([f, g4, test], true) && f([f, test], true));
+  }
+
+  function g5(a) {
+    return f([f, g5, test], true) &&
+        (f([f, g5, test], false) || f([f, test], true));
+  }
+
+  function g6(a) {
+    return f([f, g6, test], 13), f([f, g6, test], 42),
+        f([f, test], 153);
+  }
+
+  function g7(a) {
+    return f([f, g7, test], false) ||
+        (f([f, g7, test], false) ? f([f, test], true)
+             : f([f, test], true));
+  }
+
+  function g8(a) {
+    return f([f, g8, test], false) || f([f, g8, test], true) &&
+        f([f, test], true);
+  }
+
+  function g9(a) {
+    return f([f, g9, test], true) && f([f, g9, test], false) ||
+        f([f, test], true);
+  }
+
+  function g10(a) {
+    return f([f, g10, test], true) && f([f, g10, test], false) ||
+        f([f, g10, test], true) ?
+            f([f, g10, test], true) && f([f, g10, test], false) ||
+                f([f, test], true) :
+            f([f, g10, test], true) && f([f, g10, test], false) ||
+                f([f, test], true);
+  }
+
   function test() {
     assertEquals(true, g1());
     assertEquals(true, g2());
     assertEquals(153, g3());
+    assertEquals(true, g4());
+    assertEquals(true, g5());
+    assertEquals(153, g6());
+    assertEquals(true, g7());
+    assertEquals(true, g8());
+    assertEquals(true, g9());
+    assertEquals(true, g10());
   }
   test();
   test();
@@ -534,9 +582,34 @@
     return (() => f_153([f_153, test]))();
   }
 
+  function g3(a) {
+    var closure = () => f([f, closure, test], true)
+                              ? f_153([f_153, test])
+                              : f_153([f_153, test]);
+    return closure();
+  }
+
   function test() {
     assertEquals(153, g1());
     assertEquals(153, g2());
+    assertEquals(153, g3());
+  }
+  test();
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
+
+
+// Test tail calls from do expressions.
+(function () {
+  function g1(a) {
+    var a = do { return f_153([f_153, test]); 42; };
+    return a;
+  }
+
+  function test() {
+    assertEquals(153, g1());
   }
   test();
   test();
diff --git a/test/mjsunit/es6/typedarray-set-length-internal.js b/test/mjsunit/es6/typedarray-set-length-internal.js
new file mode 100644
index 0000000..22b8f67
--- /dev/null
+++ b/test/mjsunit/es6/typedarray-set-length-internal.js
@@ -0,0 +1,35 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var typedArrayConstructors = [
+  Uint8Array,
+  Int8Array,
+  Uint16Array,
+  Int16Array,
+  Uint32Array,
+  Int32Array,
+  Uint8ClampedArray,
+  Float32Array,
+  Float64Array
+];
+
+var descriptor = { get: function() { throw new Error("accessed length"); } };
+
+for (var constructor of typedArrayConstructors) {
+  var differentConstructor =
+    constructor === Uint8Array ? Int8Array : Uint8Array;
+  var target = new constructor(16);
+  Object.defineProperty(target, "length", descriptor);
+
+  var sameBuffer = new differentConstructor(target.buffer, 0, 2);
+  Object.defineProperty(sameBuffer, "length", descriptor);
+  target.set(sameBuffer);
+
+  var differentBuffer = new differentConstructor(16);
+  Object.defineProperty(differentBuffer, "length", descriptor);
+  target.set(differentBuffer);
+
+  var array = [0, 1, 2];
+  target.set(array);
+}
diff --git a/test/mjsunit/es6/typedarray-species.js b/test/mjsunit/es6/typedarray-species.js
new file mode 100644
index 0000000..020d65c
--- /dev/null
+++ b/test/mjsunit/es6/typedarray-species.js
@@ -0,0 +1,84 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Subclasses of %TypedArray% construct themselves under map, etc
+
+var typedArrayConstructors = [
+  Uint8Array,
+  Int8Array,
+  Uint16Array,
+  Int16Array,
+  Uint32Array,
+  Int32Array,
+  Uint8ClampedArray,
+  Float32Array,
+  Float64Array
+];
+
+for (let constructor of typedArrayConstructors) {
+  class MyTypedArray extends constructor { }
+  assertEquals(MyTypedArray, new MyTypedArray().map(()=>0).constructor);
+  assertEquals(MyTypedArray, new MyTypedArray().filter(()=>{}).constructor);
+  assertEquals(MyTypedArray, new MyTypedArray().slice().constructor);
+}
+
+// Subclasses can override @@species to return the another class
+
+for (let constructor of typedArrayConstructors) {
+  class MyTypedArray extends constructor { }
+  class MyOtherTypedArray extends constructor {
+    static get [Symbol.species]() { return MyTypedArray; }
+  }
+  assertEquals(MyTypedArray, new MyOtherTypedArray().map(()=>0).constructor);
+  assertEquals(MyTypedArray, new MyOtherTypedArray().filter(()=>{}).constructor);
+  assertEquals(MyTypedArray, new MyOtherTypedArray().slice().constructor);
+}
+
+// TypedArray too-short and non-TypedArray error checking
+
+for (let constructor of typedArrayConstructors) {
+  class MyShortTypedArray extends constructor {
+    constructor(length) { super(length - 1); }
+  }
+  assertThrows(() => new MyShortTypedArray(5).map(()=>0), TypeError);
+  assertThrows(() => new MyShortTypedArray(5).filter(()=>true), TypeError);
+  assertThrows(() => new MyShortTypedArray(5).slice(), TypeError);
+
+  class MyNonTypedArray extends constructor {
+    static get [Symbol.species]() { return Array; }
+  }
+  assertThrows(() => new MyNonTypedArray().map(()=>0), TypeError);
+  assertThrows(() => new MyNonTypedArray().filter(()=>{}), TypeError);
+  assertThrows(() => new MyNonTypedArray().slice(), TypeError);
+}
+
+// Defaults when constructor or @@species is missing or non-constructor
+
+for (let constructor of typedArrayConstructors) {
+  class MyDefaultTypedArray extends constructor {
+    static get [Symbol.species]() { return undefined; }
+  }
+  assertEquals(constructor, new MyDefaultTypedArray().map(()=>0).constructor);
+
+  class MyOtherDefaultTypedArray extends constructor { }
+  assertEquals(MyOtherDefaultTypedArray, new MyOtherDefaultTypedArray().map(()=>0).constructor);
+  MyOtherDefaultTypedArray.prototype.constructor = undefined;
+  assertEquals(constructor, new MyOtherDefaultTypedArray().map(()=>0).constructor);
+}
+
+// Exceptions propagated when getting constructor @@species throws
+
+class SpeciesError extends Error { }
+class ConstructorError extends Error { }
+
+for (let constructor of typedArrayConstructors) {
+  class MyThrowingArray extends constructor {
+    static get [Symbol.species]() { throw new SpeciesError; }
+  }
+  assertThrows(() => new MyThrowingArray().map(()=>{}), SpeciesError);
+  Object.defineProperty(MyThrowingArray.prototype, 'constructor', {
+      get() { throw new ConstructorError; }
+  });
+  assertThrows(() => new MyThrowingArray().map(()=>{}), ConstructorError);
+}
diff --git a/test/mjsunit/es6/unicode-character-ranges.js b/test/mjsunit/es6/unicode-character-ranges.js
new file mode 100644
index 0000000..f39004f
--- /dev/null
+++ b/test/mjsunit/es6/unicode-character-ranges.js
@@ -0,0 +1,158 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-regexp-lookbehind
+
+function execl(expectation, regexp, subject) {
+  if (regexp instanceof String) regexp = new RegExp(regexp, "u");
+  assertEquals(expectation, regexp.exec(subject));
+}
+
+function execs(expectation, regexp_source, subject) {
+  execl(expectation, new RegExp(regexp_source, "u"), subject);
+}
+
+// Character ranges.
+execl(["A"], /[A-D]/u, "A");
+execs(["A"], "[A-D]", "A");
+execl(["ABCD"], /[A-D]+/u, "ZABCDEF");
+execs(["ABCD"], "[A-D]+", "ZABCDEF");
+
+execl(["\u{12345}"], /[\u1234-\u{12345}]/u, "\u{12345}");
+execs(["\u{12345}"], "[\u1234-\u{12345}]", "\u{12345}");
+execl(null, /[^\u1234-\u{12345}]/u, "\u{12345}");
+execs(null, "[^\u1234-\u{12345}]", "\u{12345}");
+
+execl(["\u{1234}"], /[\u1234-\u{12345}]/u, "\u{1234}");
+execs(["\u{1234}"], "[\u1234-\u{12345}]", "\u{1234}");
+execl(null, /[^\u1234-\u{12345}]/u, "\u{1234}");
+execs(null, "[^\u1234-\u{12345}]", "\u{1234}");
+
+execl(null, /[\u1234-\u{12345}]/u, "\u{1233}");
+execs(null, "[\u1234-\u{12345}]", "\u{1233}");
+execl(["\u{1233}"], /[^\u1234-\u{12345}]/u, "\u{1233}");
+execs(["\u{1233}"], "[^\u1234-\u{12345}]", "\u{1233}");
+
+execl(["\u{12346}"], /[^\u1234-\u{12345}]/u, "\u{12346}");
+execs(["\u{12346}"], "[^\u1234-\u{12345}]", "\u{12346}");
+execl(null, /[\u1234-\u{12345}]/u, "\u{12346}");
+execs(null, "[\u1234-\u{12345}]", "\u{12346}");
+
+execl(["\u{12342}"], /[\u{12340}-\u{12345}]/u, "\u{12342}");
+execs(["\u{12342}"], "[\u{12340}-\u{12345}]", "\u{12342}");
+execl(["\u{12342}"], /[\ud808\udf40-\ud808\udf45]/u, "\u{12342}");
+execs(["\u{12342}"], "[\ud808\udf40-\ud808\udf45]", "\u{12342}");
+execl(null, /[^\u{12340}-\u{12345}]/u, "\u{12342}");
+execs(null, "[^\u{12340}-\u{12345}]", "\u{12342}");
+execl(null, /[^\ud808\udf40-\ud808\udf45]/u, "\u{12342}");
+execs(null, "[^\ud808\udf40-\ud808\udf45]", "\u{12342}");
+
+execl(["\u{ffff}"], /[\u{ff80}-\u{12345}]/u, "\u{ffff}");
+execs(["\u{ffff}"], "[\u{ff80}-\u{12345}]", "\u{ffff}");
+execl(["\u{ffff}"], /[\u{ff80}-\ud808\udf45]/u, "\u{ffff}");
+execs(["\u{ffff}"], "[\u{ff80}-\ud808\udf45]", "\u{ffff}");
+execl(null, /[^\u{ff80}-\u{12345}]/u, "\u{ffff}");
+execs(null, "[^\u{ff80}-\u{12345}]", "\u{ffff}");
+execl(null, /[^\u{ff80}-\ud808\udf45]/u, "\u{ffff}");
+execs(null, "[^\u{ff80}-\ud808\udf45]", "\u{ffff}");
+
+// Lone surrogate
+execl(["\ud800"], /[^\u{ff80}-\u{12345}]/u, "\uff99\u{d800}A");
+execs(["\udc00"], "[^\u{ff80}-\u{12345}]", "\uff99\u{dc00}A");
+execl(["\udc01"], /[\u0100-\u{10ffff}]/u, "A\udc01");
+execl(["\udc03"], /[\udc01-\udc03]/u, "\ud801\udc02\udc03");
+execl(["\ud801"], /[\ud801-\ud803]/u, "\ud802\udc01\ud801");
+
+// Paired sorrogate.
+execl(null, /[^\u{ff80}-\u{12345}]/u, "\u{d800}\u{dc00}");
+execs(null, "[^\u{ff80}-\u{12345}]", "\u{d800}\u{dc00}");
+execl(["\ud800\udc00"], /[\u{ff80}-\u{12345}]/u, "\u{d800}\u{dc00}");
+execs(["\ud800\udc00"], "[\u{ff80}-\u{12345}]", "\u{d800}\u{dc00}");
+execl(["foo\u{10e6d}bar"], /foo\ud803\ude6dbar/u, "foo\u{10e6d}bar");
+
+// Lone surrogates
+execl(["\ud801\ud801"], /\ud801+/u, "\ud801\udc01\ud801\ud801");
+execl(["\udc01\udc01"], /\udc01+/u, "\ud801\ud801\udc01\udc01\udc01");
+
+execl(["\udc02\udc03A"], /\W\WA/u, "\ud801\udc01A\udc02\udc03A");
+execl(["\ud801\ud802"], /\ud801./u, "\ud801\udc01\ud801\ud802");
+execl(["\udc02\udc03A"], /[\ud800-\udfff][\ud800-\udfff]A/u,
+      "\ud801\udc01A\udc02\udc03A");
+
+// Character classes
+execl(null, /\w/u, "\ud801\udc01");
+execl(["\ud801"], /[^\w]/, "\ud801\udc01");
+execl(["\ud801\udc01"], /[^\w]/u, "\ud801\udc01");
+execl(["\ud801"], /\W/, "\ud801\udc01");
+execl(["\ud801\udc01"], /\W/u, "\ud801\udc01");
+
+execl(["\ud800X"], /.X/u, "\ud800XaX");
+execl(["aX"], /.(?<!\ud800)X/u, "\ud800XaX");
+execl(["aX"], /.(?<![\ud800-\ud900])X/u, "\ud800XaX");
+
+execl(null, /[]/u, "\u1234");
+execl(["0abc"], /[^]abc/u, "0abc");
+execl(["\u1234abc"], /[^]abc/u, "\u1234abc");
+execl(["\u{12345}abc"], /[^]abc/u, "\u{12345}abc");
+
+execl(null, /[\u{0}-\u{1F444}]/u, "\ud83d\udfff");
+
+// Backward matches of lone surrogates.
+execl(["B", "\ud803A"], /(?<=([\ud800-\ud900]A))B/u,
+      "\ud801\udc00AB\udc00AB\ud802\ud803AB");
+execl(["B", "\udc00A"], /(?<=([\ud800-\u{10300}]A))B/u,
+       "\ud801\udc00AB\udc00AB\ud802\ud803AB");
+execl(["B", "\udc11A"], /(?<=([\udc00-\udd00]A))B/u,
+      "\ud801\udc00AB\udc11AB\ud802\ud803AB");
+execl(["X", "\ud800C"], /(?<=(\ud800\w))X/u,
+      "\ud800\udc00AX\udc11BX\ud800\ud800CX");
+execl(["C", "\ud800\ud800"], /(?<=(\ud800.))\w/u,
+      "\ud800\udc00AX\udc11BX\ud800\ud800CX");
+execl(["X", "\udc01C"], /(?<=(\udc01\w))X/u,
+      "\ud800\udc01AX\udc11BX\udc01\udc01CX");
+execl(["C", "\udc01\udc01"], /(?<=(\udc01.))./u,
+      "\ud800\udc01AX\udc11BX\udc01\udc01CX");
+
+var L = "\ud800";
+var T = "\udc00";
+var X = "X";
+
+// Test string contains only match.
+function testw(expect, src, subject) {
+  var re = new RegExp("^" + src + "$", "u");
+  assertEquals(expect, re.test(subject));
+}
+
+// Test string starts with match.
+function tests(expect, src, subject) {
+  var re = new RegExp("^" + src, "u");
+  assertEquals(expect, re.test(subject));
+}
+
+testw(true, X, X);
+testw(true, L, L);
+testw(true, T, T);
+testw(true, L + T, L + T);
+testw(true, T + L, T + L);
+testw(false, T, L + T);
+testw(false, L, L + T);
+testw(true, ".(?<=" + L + ")", L);
+testw(true, ".(?<=" + T + ")", T);
+testw(true, ".(?<=" + L + T + ")", L + T);
+testw(true, ".(?<=" + L + T + ")", L + T);
+tests(true, ".(?<=" + T + ")", T + L);
+tests(false, ".(?<=" + L + ")", L + T);
+tests(false, ".(?<=" + T + ")", L + T);
+tests(true, "..(?<=" + T + ")", T + T + L);
+tests(true, "..(?<=" + T + ")", X + T + L);
+tests(true, "...(?<=" + L + ")", X + T + L);
+tests(false, "...(?<=" + T + ")", X + L + T)
+tests(true, "..(?<=" + L + T + ")", X + L + T)
+tests(true, "..(?<=" + L + T + "(?<=" + L + T + "))", X + L + T);
+tests(false, "..(?<=" + L + "(" + T + "))", X + L + T);
+tests(false, ".*" + L, X + L + T);
+tests(true, ".*" + L, X + L + L + T);
+tests(false, ".*" + L, X + L + T + L + T);
+tests(false, ".*" + T, X + L + T + L + T);
+tests(true, ".*" + T, X + L + T + T + L + T);
diff --git a/test/mjsunit/es6/unicode-escapes-in-regexps.js b/test/mjsunit/es6/unicode-escapes-in-regexps.js
new file mode 100644
index 0000000..2d2d118
--- /dev/null
+++ b/test/mjsunit/es6/unicode-escapes-in-regexps.js
@@ -0,0 +1,285 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// ES6 extends the \uxxxx escape and also allows \u{xxxxx}.
+
+function testRegexpHelper(r) {
+  assertTrue(r.test("foo"));
+  assertTrue(r.test("boo"));
+  assertFalse(r.test("moo"));
+}
+
+
+(function TestUnicodeEscapes() {
+  testRegexpHelper(/(\u0066|\u0062)oo/);
+  testRegexpHelper(/(\u0066|\u0062)oo/u);
+  testRegexpHelper(/(\u{0066}|\u{0062})oo/u);
+  testRegexpHelper(/(\u{66}|\u{000062})oo/u);
+
+  // Note that we need \\ inside a string, otherwise it's interpreted as a
+  // unicode escape inside a string.
+  testRegexpHelper(new RegExp("(\\u0066|\\u0062)oo"));
+  testRegexpHelper(new RegExp("(\\u0066|\\u0062)oo", "u"));
+  testRegexpHelper(new RegExp("(\\u{0066}|\\u{0062})oo", "u"));
+  testRegexpHelper(new RegExp("(\\u{66}|\\u{000062})oo", "u"));
+
+  // Though, unicode escapes via strings should work too.
+  testRegexpHelper(new RegExp("(\u0066|\u0062)oo"));
+  testRegexpHelper(new RegExp("(\u0066|\u0062)oo", "u"));
+  testRegexpHelper(new RegExp("(\u{0066}|\u{0062})oo", "u"));
+  testRegexpHelper(new RegExp("(\u{66}|\u{000062})oo", "u"));
+})();
+
+
+(function TestUnicodeEscapesInCharacterClasses() {
+  testRegexpHelper(/[\u0062-\u0066]oo/);
+  testRegexpHelper(/[\u0062-\u0066]oo/u);
+  testRegexpHelper(/[\u{0062}-\u{0066}]oo/u);
+  testRegexpHelper(/[\u{62}-\u{00000066}]oo/u);
+
+  // Note that we need \\ inside a string, otherwise it's interpreted as a
+  // unicode escape inside a string.
+  testRegexpHelper(new RegExp("[\\u0062-\\u0066]oo"));
+  testRegexpHelper(new RegExp("[\\u0062-\\u0066]oo", "u"));
+  testRegexpHelper(new RegExp("[\\u{0062}-\\u{0066}]oo", "u"));
+  testRegexpHelper(new RegExp("[\\u{62}-\\u{00000066}]oo", "u"));
+
+  // Though, unicode escapes via strings should work too.
+  testRegexpHelper(new RegExp("[\u0062-\u0066]oo"));
+  testRegexpHelper(new RegExp("[\u0062-\u0066]oo", "u"));
+  testRegexpHelper(new RegExp("[\u{0062}-\u{0066}]oo", "u"));
+  testRegexpHelper(new RegExp("[\u{62}-\u{00000066}]oo", "u"));
+})();
+
+
+(function TestBraceEscapesWithoutUnicodeFlag() {
+  // \u followed by illegal escape will be parsed as u. {x} will be the
+  // character count.
+  function helper1(r) {
+    assertFalse(r.test("fbar"));
+    assertFalse(r.test("fubar"));
+    assertTrue(r.test("fuubar"));
+    assertFalse(r.test("fuuubar"));
+  }
+  helper1(/f\u{2}bar/);
+  helper1(new RegExp("f\\u{2}bar"));
+
+  function helper2(r) {
+    assertFalse(r.test("fbar"));
+    assertTrue(r.test("fubar"));
+    assertTrue(r.test("fuubar"));
+    assertFalse(r.test("fuuubar"));
+  }
+
+  helper2(/f\u{1,2}bar/);
+  helper2(new RegExp("f\\u{1,2}bar"));
+
+  function helper3(r) {
+    assertTrue(r.test("u"));
+    assertTrue(r.test("{"));
+    assertTrue(r.test("2"));
+    assertTrue(r.test("}"));
+    assertFalse(r.test("q"));
+    assertFalse(r.test("("));
+    assertFalse(r.test(")"));
+  }
+  helper3(/[\u{2}]/);
+  helper3(new RegExp("[\\u{2}]"));
+})();
+
+
+(function TestInvalidEscapes() {
+  // Without the u flag, invalid unicode escapes and other invalid escapes are
+  // treated as identity escapes.
+  function helper1(r) {
+    assertTrue(r.test("firstuxz89second"));
+  }
+  helper1(/first\u\x\z\8\9second/);
+  helper1(new RegExp("first\\u\\x\\z\\8\\9second"));
+
+  function helper2(r) {
+    assertTrue(r.test("u"));
+    assertTrue(r.test("x"));
+    assertTrue(r.test("z"));
+    assertTrue(r.test("8"));
+    assertTrue(r.test("9"));
+    assertFalse(r.test("q"));
+    assertFalse(r.test("7"));
+  }
+  helper2(/[\u\x\z\8\9]/);
+  helper2(new RegExp("[\\u\\x\\z\\8\\9]"));
+
+  // However, with the u flag, these are treated as invalid escapes.
+  assertThrows("/\\u/u", SyntaxError);
+  assertThrows("/\\u12/u", SyntaxError);
+  assertThrows("/\\ufoo/u", SyntaxError);
+  assertThrows("/\\x/u", SyntaxError);
+  assertThrows("/\\xfoo/u", SyntaxError);
+  assertThrows("/\\z/u", SyntaxError);
+  assertThrows("/\\8/u", SyntaxError);
+  assertThrows("/\\9/u", SyntaxError);
+
+  assertThrows("new RegExp('\\\\u', 'u')", SyntaxError);
+  assertThrows("new RegExp('\\\\u12', 'u')", SyntaxError);
+  assertThrows("new RegExp('\\\\ufoo', 'u')", SyntaxError);
+  assertThrows("new RegExp('\\\\x', 'u')", SyntaxError);
+  assertThrows("new RegExp('\\\\xfoo', 'u')", SyntaxError);
+  assertThrows("new RegExp('\\\\z', 'u')", SyntaxError);
+  assertThrows("new RegExp('\\\\8', 'u')", SyntaxError);
+  assertThrows("new RegExp('\\\\9', 'u')", SyntaxError);
+})();
+
+
+(function TestTooBigHexEscape() {
+  // The hex number inside \u{} has a maximum value.
+  /\u{10ffff}/u
+  new RegExp("\\u{10ffff}", "u")
+  assertThrows("/\\u{110000}/u", SyntaxError);
+  assertThrows("new RegExp('\\\\u{110000}', 'u')", SyntaxError);
+
+  // Without the u flag, they're of course fine ({x} is the count).
+  /\u{110000}/
+  new RegExp("\\u{110000}")
+})();
+
+
+(function TestSyntaxEscapes() {
+  // Syntax escapes work the same with or without the u flag.
+  function helper(r) {
+    assertTrue(r.test("foo[bar"));
+    assertFalse(r.test("foo]bar"));
+  }
+  helper(/foo\[bar/);
+  helper(new RegExp("foo\\[bar"));
+  helper(/foo\[bar/u);
+  helper(new RegExp("foo\\[bar", "u"));
+})();
+
+
+(function TestUnicodeSurrogates() {
+  // U+10E6D corresponds to the surrogate pair [U+D803, U+DE6D].
+  function helper(r) {
+    assertTrue(r.test("foo\u{10e6d}bar"));
+  }
+  helper(/foo\ud803\ude6dbar/u);
+  helper(new RegExp("foo\\ud803\\ude6dbar", "u"));
+})();
+
+
+(function AllFlags() {
+  // Test that we can pass all possible regexp flags and they work properly.
+  function helper1(r) {
+    assertTrue(r.global);
+    assertTrue(r.ignoreCase);
+    assertTrue(r.multiline);
+    assertTrue(r.sticky);
+    assertTrue(r.unicode);
+  }
+
+  helper1(/foo/gimyu);
+  helper1(new RegExp("foo", "gimyu"));
+
+  function helper2(r) {
+    assertFalse(r.global);
+    assertFalse(r.ignoreCase);
+    assertFalse(r.multiline);
+    assertFalse(r.sticky);
+    assertFalse(r.unicode);
+  }
+
+  helper2(/foo/);
+  helper2(new RegExp("foo"));
+})();
+
+
+(function DuplicatedFlags() {
+  // Test that duplicating the u flag is not allowed.
+  assertThrows("/foo/ugu");
+  assertThrows("new RegExp('foo', 'ugu')");
+})();
+
+
+(function ToString() {
+  // Test that the u flag is included in the string representation of regexps.
+  function helper(r) {
+    assertEquals(r.toString(), "/foo/u");
+  }
+  helper(/foo/u);
+  helper(new RegExp("foo", "u"));
+})();
+
+// Non-BMP patterns.
+// Single character atom.
+assertTrue(new RegExp("\u{12345}", "u").test("\u{12345}"));
+assertTrue(/\u{12345}/u.test("\u{12345}"));
+assertTrue(new RegExp("\u{12345}", "u").test("\ud808\udf45"));
+assertTrue(/\u{12345}/u.test("\ud808\udf45"));
+assertFalse(new RegExp("\u{12345}", "u").test("\udf45"));
+assertFalse(/\u{12345}/u.test("\udf45"));
+
+// Multi-character atom.
+assertTrue(new RegExp("\u{12345}\u{23456}", "u").test("a\u{12345}\u{23456}b"));
+assertTrue(/\u{12345}\u{23456}/u.test("b\u{12345}\u{23456}c"));
+assertFalse(new RegExp("\u{12345}\u{23456}", "u").test("a\udf45\u{23456}b"));
+assertFalse(/\u{12345}\u{23456}/u.test("b\udf45\u{23456}c"));
+
+// Disjunction.
+assertTrue(new RegExp("\u{12345}(?:\u{23456})", "u").test(
+    "a\u{12345}\u{23456}b"));
+assertTrue(/\u{12345}(?:\u{23456})/u.test("b\u{12345}\u{23456}c"));
+assertFalse(new RegExp("\u{12345}(?:\u{23456})", "u").test(
+    "a\udf45\u{23456}b"));
+assertFalse(/\u{12345}(?:\u{23456})/u.test("b\udf45\u{23456}c"));
+
+// Alternative.
+assertTrue(new RegExp("\u{12345}|\u{23456}", "u").test("a\u{12345}b"));
+assertTrue(/\u{12345}|\u{23456}/u.test("b\u{23456}c"));
+assertFalse(new RegExp("\u{12345}|\u{23456}", "u").test("a\udf45\ud84db"));
+assertFalse(/\u{12345}|\u{23456}/u.test("b\udf45\ud808c"));
+
+// Capture.
+assertTrue(new RegExp("(\u{12345}|\u{23456}).\\1", "u").test(
+    "\u{12345}b\u{12345}"));
+assertTrue(/(\u{12345}|\u{23456}).\1/u.test("\u{12345}b\u{12345}"));
+assertFalse(new RegExp("(\u{12345}|\u{23456}).\\1", "u").test(
+    "\u{12345}b\u{23456}"));
+assertFalse(/(\u{12345}|\u{23456}).\1/u.test("\u{12345}b\u{23456}"));
+
+// Quantifier.
+assertTrue(new RegExp("\u{12345}{3}", "u").test("\u{12345}\u{12345}\u{12345}"));
+assertTrue(/\u{12345}{3}/u.test("\u{12345}\u{12345}\u{12345}"));
+assertTrue(new RegExp("\u{12345}{3}").test("\u{12345}\udf45\udf45"));
+assertFalse(/\ud808\udf45{3}/u.test("\u{12345}\udf45\udf45"));
+assertTrue(/\ud808\udf45{3}/u.test("\u{12345}\u{12345}\u{12345}"));
+assertFalse(new RegExp("\u{12345}{3}", "u").test("\u{12345}\udf45\udf45"));
+assertFalse(/\u{12345}{3}/u.test("\u{12345}\udf45\udf45"));
+
+// Literal surrogates.
+assertEquals(["\u{10000}\u{10000}"],
+             new RegExp("\ud800\udc00+", "u").exec("\u{10000}\u{10000}"));
+assertEquals(["\u{10000}\u{10000}"],
+             new RegExp("\\ud800\\udc00+", "u").exec("\u{10000}\u{10000}"));
+
+assertEquals(["\u{10003}\u{50001}"],
+             new RegExp("[\\ud800\\udc03-\\ud900\\udc01\]+", "u").exec(
+                 "\u{10003}\u{50001}"));
+assertEquals(["\u{10003}\u{50001}"],
+             new RegExp("[\ud800\udc03-\u{50001}\]+", "u").exec(
+                 "\u{10003}\u{50001}"));
+
+// Unicode escape sequences to represent a non-BMP character cannot have
+// mixed notation, and must follow the rules for RegExpUnicodeEscapeSequence.
+assertThrows(() => new RegExp("[\\ud800\udc03-\ud900\\udc01\]+", "u"));
+assertThrows(() => new RegExp("[\\ud800\udc03-\ud900\\udc01\]+", "u"));
+assertNull(new RegExp("\\ud800\udc00+", "u").exec("\u{10000}\u{10000}"));
+assertNull(new RegExp("\ud800\\udc00+", "u").exec("\u{10000}\u{10000}"));
+
+assertNull(new RegExp("[\\ud800\udc00]", "u").exec("\u{10000}"));
+assertNull(new RegExp("[\\{ud800}\udc00]", "u").exec("\u{10000}"));
+assertNull(new RegExp("[\ud800\\udc00]", "u").exec("\u{10000}"));
+assertNull(new RegExp("[\ud800\\{udc00}]", "u").exec("\u{10000}"));
+
+assertNull(/\u{d800}\u{dc00}+/u.exec("\ud800\udc00\udc00"));
+assertNull(/\ud800\u{dc00}+/u.exec("\ud800\udc00\udc00"));
+assertNull(/\u{d800}\udc00+/u.exec("\ud800\udc00\udc00"));
diff --git a/test/mjsunit/es6/unicode-regexp-backrefs.js b/test/mjsunit/es6/unicode-regexp-backrefs.js
new file mode 100644
index 0000000..56b9c5e
--- /dev/null
+++ b/test/mjsunit/es6/unicode-regexp-backrefs.js
@@ -0,0 +1,53 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-regexp-lookbehind
+
+// Back reference does not end in the middle of a surrogate pair.
+function replace(string) {
+  return string.replace(/L/g, "\ud800")
+               .replace(/l/g, "\ud801")
+               .replace(/T/g, "\udc00")
+               .replace(/\./g, "[^]");
+}
+
+function test(expectation, regexp_source, subject) {
+  if (expectation !== null) expectation = expectation.map(replace);
+  subject = replace(subject);
+  regexp_source = replace(regexp_source);
+  assertEquals(expectation, new RegExp(regexp_source, "u").exec(subject));
+}
+
+// Back reference does not end in the middle of a surrogate pair.
+test(null, "(L)\\1", "LLT");
+test(["LLTLl", "L", "l"], "(L).*\\1(.)", "LLTLl");
+test(null, "(aL).*\\1", "aLaLT");
+test(["aLaLTaLl", "aL", "l"], "(aL).*\\1(.)", "aLaLTaLl");
+
+var s = "TabcLxLTabcLxTabcLTyTabcLz";
+test([s, "TabcL", "z"], "([^x]+).*\\1(.)", s);
+
+// Back reference does not start in the middle of a surrogate pair.
+test(["TLTabTc", "T", "c"], "(T).*\\1(.)", "TLTabTc");
+
+// Lookbehinds.
+test(null, "(?<=\\1(T)x)", "LTTx");
+test(["", "b", "T"], "(?<=(.)\\2.*(T)x)", "bTaLTTx");
+test(null, "(?<=\\1.*(L)x)", "LTLx");
+test(["", "b", "L"], "(?<=(.)\\2.*(L)x)", "bLaLTLx");
+
+
+test(null, "([^x]+)x*\\1", "LxLT");
+test(null, "([^x]+)x*\\1", "TxLT");
+test(null, "([^x]+)x*\\1", "LTxL");
+test(null, "([^x]+)x*\\1", "LTxT");
+test(null, "([^x]+)x*\\1", "xLxLT");
+test(null, "([^x]+)x*\\1", "xTxLT");
+test(null, "([^x]+)x*\\1", "xLTxL");
+test(null, "([^x]+)x*\\1", "xLTxT");
+test(null, "([^x]+)x*\\1", "xxxLxxLTxx");
+test(null, "([^x]+)x*\\1", "xxxTxxLTxx");
+test(null, "([^x]+)x*\\1", "xxxLTxxLxx");
+test(null, "([^x]+)x*\\1", "xxxLTxxTxx");
+test(["LTTxxLTT", "LTT"], "([^x]+)x*\\1", "xxxLTTxxLTTxx");
diff --git a/test/mjsunit/es6/unicode-regexp-ignore-case-noi18n.js b/test/mjsunit/es6/unicode-regexp-ignore-case-noi18n.js
new file mode 100644
index 0000000..a998942
--- /dev/null
+++ b/test/mjsunit/es6/unicode-regexp-ignore-case-noi18n.js
@@ -0,0 +1,57 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Non-unicode use toUpperCase mappings.
+assertFalse(/[\u00e5]/i.test("\u212b"));
+assertFalse(/[\u212b]/i.test("\u00e5\u1234"));
+assertFalse(/[\u212b]/i.test("\u00e5"));
+
+assertTrue("\u212b".toLowerCase() == "\u00e5");
+assertTrue("\u00c5".toLowerCase() == "\u00e5");
+assertTrue("\u00e5".toUpperCase() == "\u00c5");
+
+// Unicode uses case folding mappings.
+assertFalse(/\u00e5/ui.test("\u212b"));
+assertTrue(/\u00e5/ui.test("\u00c5"));
+assertTrue(/\u00e5/ui.test("\u00e5"));
+assertFalse(/\u00e5/ui.test("\u212b"));
+assertTrue(/\u00c5/ui.test("\u00e5"));
+assertFalse(/\u00c5/ui.test("\u212b"));
+assertTrue(/\u00c5/ui.test("\u00c5"));
+assertFalse(/\u212b/ui.test("\u00c5"));
+assertFalse(/\u212b/ui.test("\u00e5"));
+assertTrue(/\u212b/ui.test("\u212b"));
+
+// Non-BMP.
+assertFalse(/\u{10400}/i.test("\u{10428}"));
+assertFalse(/\u{10400}/ui.test("\u{10428}"));
+assertFalse(/\ud801\udc00/ui.test("\u{10428}"));
+assertFalse(/[\u{10428}]/ui.test("\u{10400}"));
+assertFalse(/[\ud801\udc28]/ui.test("\u{10400}"));
+assertEquals(["\uff21\u{10400}"],
+             /[\uff40-\u{10428}]+/ui.exec("\uff21\u{10400}abc"));
+assertEquals(["abc"], /[^\uff40-\u{10428}]+/ui.exec("\uff21\u{10400}abc\uff23"));
+assertEquals(["\uff53\u24bb"],
+             /[\u24d5-\uff33]+/ui.exec("\uff54\uff53\u24bb\u24ba"));
+
+// Full mappings are ignored.
+assertFalse(/\u00df/ui.test("SS"));
+assertFalse(/\u1f8d/ui.test("\u1f05\u03b9"));
+
+// Simple mappings.
+assertFalse(/\u1f8d/ui.test("\u1f85"));
+
+// Common mappings.
+assertTrue(/\u1f6b/ui.test("\u1f63"));
+
+// Back references.
+assertNull(/(.)\1\1/ui.exec("\u00e5\u212b\u00c5"));
+assertNull(/(.)\1/ui.exec("\u{118aa}\u{118ca}"));
+
+
+// Non-Latin1 maps to Latin1.
+assertNull(/^\u017F/ui.exec("s"));
+assertNull(/^\u017F/ui.exec("s\u1234"));
+assertNull(/^a[\u017F]/ui.exec("as"));
+assertNull(/^a[\u017F]/ui.exec("as\u1234"));
diff --git a/test/mjsunit/es6/unicode-regexp-ignore-case.js b/test/mjsunit/es6/unicode-regexp-ignore-case.js
new file mode 100644
index 0000000..dd02ca9
--- /dev/null
+++ b/test/mjsunit/es6/unicode-regexp-ignore-case.js
@@ -0,0 +1,62 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Non-unicode use toUpperCase mappings.
+assertFalse(/[\u00e5]/i.test("\u212b"));
+assertFalse(/[\u212b]/i.test("\u00e5\u1234"));
+assertFalse(/[\u212b]/i.test("\u00e5"));
+
+assertTrue("\u212b".toLowerCase() == "\u00e5");
+assertTrue("\u00c5".toLowerCase() == "\u00e5");
+assertTrue("\u00e5".toUpperCase() == "\u00c5");
+
+// Unicode uses case folding mappings.
+assertTrue(/\u00e5/ui.test("\u212b"));
+assertTrue(/\u00e5/ui.test("\u00c5"));
+assertTrue(/\u00e5/ui.test("\u00e5"));
+assertTrue(/\u00e5/ui.test("\u212b"));
+assertTrue(/\u00c5/ui.test("\u00e5"));
+assertTrue(/\u00c5/ui.test("\u212b"));
+assertTrue(/\u00c5/ui.test("\u00c5"));
+assertTrue(/\u212b/ui.test("\u00c5"));
+assertTrue(/\u212b/ui.test("\u00e5"));
+assertTrue(/\u212b/ui.test("\u212b"));
+
+// Non-BMP.
+assertFalse(/\u{10400}/i.test("\u{10428}"));
+assertTrue(/\u{10400}/ui.test("\u{10428}"));
+assertTrue(/\ud801\udc00/ui.test("\u{10428}"));
+assertTrue(/[\u{10428}]/ui.test("\u{10400}"));
+assertTrue(/[\ud801\udc28]/ui.test("\u{10400}"));
+assertEquals(["\uff21\u{10400}"],
+             /[\uff40-\u{10428}]+/ui.exec("\uff21\u{10400}abc"));
+assertEquals(["abc"], /[^\uff40-\u{10428}]+/ui.exec("\uff21\u{10400}abc\uff23"));
+assertEquals(["\uff53\u24bb"],
+             /[\u24d5-\uff33]+/ui.exec("\uff54\uff53\u24bb\u24ba"));
+
+// Full mappings are ignored.
+assertFalse(/\u00df/ui.test("SS"));
+assertFalse(/\u1f8d/ui.test("\u1f05\u03b9"));
+
+// Simple mappings work.
+assertTrue(/\u1f8d/ui.test("\u1f85"));
+
+// Common mappings work.
+assertTrue(/\u1f6b/ui.test("\u1f63"));
+
+// Back references.
+assertEquals(["\u00e5\u212b\u00c5", "\u00e5"],
+             /(.)\1\1/ui.exec("\u00e5\u212b\u00c5"));
+assertEquals(["\u{118aa}\u{118ca}", "\u{118aa}"],
+             /(.)\1/ui.exec("\u{118aa}\u{118ca}"));
+
+// Misc.
+assertTrue(/\u00e5\u00e5\u00e5/ui.test("\u212b\u00e5\u00c5"));
+assertTrue(/AB\u{10400}/ui.test("ab\u{10428}"));
+
+// Non-Latin1 maps to Latin1.
+assertEquals(["s"], /^\u017F/ui.exec("s"));
+assertEquals(["s"], /^\u017F/ui.exec("s\u1234"));
+assertEquals(["as"], /^a[\u017F]/ui.exec("as"));
+assertEquals(["as"], /^a[\u017F]/ui.exec("as\u1234"));
diff --git a/test/mjsunit/es6/unicode-regexp-last-index.js b/test/mjsunit/es6/unicode-regexp-last-index.js
new file mode 100644
index 0000000..67fbac7
--- /dev/null
+++ b/test/mjsunit/es6/unicode-regexp-last-index.js
@@ -0,0 +1,104 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-regexp-lookbehind
+
+var r = /./ug;
+assertEquals(["\ud800\udc00"], r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(2, r.lastIndex);
+r.lastIndex = 1;
+assertEquals(["\ud800\udc00"], r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(2, r.lastIndex);
+assertEquals(["\ud801\udc01"], r.exec("\ud800\udc00\ud801\udc01"));
+r.lastIndex = 3;
+assertEquals(["\ud801\udc01"], r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(4, r.lastIndex);
+r.lastIndex = 4;
+assertNull(r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(0, r.lastIndex);
+r.lastIndex = 5;
+assertNull(r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(0, r.lastIndex);
+
+r.lastIndex = 3;
+assertEquals(["\ud802"], r.exec("\ud800\udc00\ud801\ud802"));
+r.lastIndex = 4;
+assertNull(r.exec("\ud800\udc00\ud801\ud802"));
+
+r = /./g;
+assertEquals(["\ud800"], r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(1, r.lastIndex);
+assertEquals(["\udc00"], r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(2, r.lastIndex);
+assertEquals(["\ud801"], r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(3, r.lastIndex);
+assertEquals(["\udc01"], r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(4, r.lastIndex);
+assertNull(r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(0, r.lastIndex);
+r.lastIndex = 1;
+assertEquals(["\udc00"], r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(2, r.lastIndex);
+
+// ------------------------
+
+r = /^./ug;
+assertEquals(["\ud800\udc00"], r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(2, r.lastIndex);
+r.lastIndex = 1;
+assertEquals(["\ud800\udc00"], r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(2, r.lastIndex);
+assertNull(r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(0, r.lastIndex);
+r.lastIndex = 3;
+assertNull(r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(0, r.lastIndex);
+r.lastIndex = 4;
+assertNull(r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(0, r.lastIndex);
+r.lastIndex = 5;
+assertNull(r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(0, r.lastIndex);
+
+r = /^./g;
+assertEquals(["\ud800"], r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(1, r.lastIndex);
+assertNull(r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(0, r.lastIndex);
+r.lastIndex = 3;
+assertNull(r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(0, r.lastIndex);
+
+//------------------------
+
+r = /(?:(^.)|.)/ug;
+assertEquals(["\ud800\udc00", "\ud800\udc00"],
+             r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(2, r.lastIndex);
+r.lastIndex = 1;
+assertEquals(["\ud800\udc00", "\ud800\udc00"],
+             r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(2, r.lastIndex);
+assertEquals(["\ud801\udc01", undefined], r.exec("\ud800\udc00\ud801\udc01"));
+r.lastIndex = 3;
+assertEquals(["\ud801\udc01", undefined], r.exec("\ud800\udc00\ud801\udc01"));
+r.lastIndex = 4;
+assertNull(r.exec("\ud800\udc00\ud801\udc01"));
+r.lastIndex = 5;
+assertNull(r.exec("\ud800\udc00\ud801\udc01"));
+
+r.lastIndex = 3;
+assertEquals(["\ud802", undefined], r.exec("\ud800\udc00\ud801\ud802"));
+r.lastIndex = 4;
+assertNull(r.exec("\ud800\udc00\ud801\ud802"));
+
+r = /(?:(^.)|.)/g;
+assertEquals(["\ud800", "\ud800"],
+    r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(1, r.lastIndex);
+assertEquals(["\udc00", undefined], r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(2, r.lastIndex);
+r.lastIndex = 3;
+assertEquals(["\udc01", undefined], r.exec("\ud800\udc00\ud801\udc01"));
+assertEquals(4, r.lastIndex);
diff --git a/test/mjsunit/es6/unicode-regexp-restricted-syntax.js b/test/mjsunit/es6/unicode-regexp-restricted-syntax.js
new file mode 100644
index 0000000..dd4fa39
--- /dev/null
+++ b/test/mjsunit/es6/unicode-regexp-restricted-syntax.js
@@ -0,0 +1,42 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// test262/data/test/language/literals/regexp/u-dec-esc
+assertThrows("/\\1/u", SyntaxError);
+// test262/language/literals/regexp/u-invalid-char-range-a
+assertThrows("/[\\w-a]/u", SyntaxError);
+// test262/language/literals/regexp/u-invalid-char-range-b
+assertThrows("/[a-\\w]/u", SyntaxError);
+// test262/language/literals/regexp/u-invalid-char-esc
+assertThrows("/\\c/u", SyntaxError);
+assertThrows("/\\c0/u", SyntaxError);
+// test262/built-ins/RegExp/unicode_restricted_quantifiable_assertion
+assertThrows("/(?=.)*/u", SyntaxError);
+// test262/built-ins/RegExp/unicode_restricted_octal_escape
+assertThrows("/[\\1]/u", SyntaxError);
+assertThrows("/\\00/u", SyntaxError);
+assertThrows("/\\09/u", SyntaxError);
+// test262/built-ins/RegExp/unicode_restricted_identity_escape_alpha
+assertThrows("/[\\c]/u", SyntaxError);
+// test262/built-ins/RegExp/unicode_restricted_identity_escape_c
+assertThrows("/[\\c0]/u", SyntaxError);
+// test262/built-ins/RegExp/unicode_restricted_incomple_quantifier
+assertThrows("/a{/u", SyntaxError);
+assertThrows("/a{1,/u", SyntaxError);
+assertThrows("/{/u", SyntaxError);
+assertThrows("/}/u", SyntaxError);
+// test262/data/test/built-ins/RegExp/unicode_restricted_brackets
+assertThrows("/]/u", SyntaxError);
+// test262/built-ins/RegExp/unicode_identity_escape
+/\//u;
+
+// escaped \0 is allowed inside a character class.
+assertEquals(["\0"], /[\0]/u.exec("\0"));
+// unless it is followed by another digit.
+assertThrows("/[\\00]/u", SyntaxError);
+assertThrows("/[\\01]/u", SyntaxError);
+assertThrows("/[\\09]/u", SyntaxError);
+assertEquals(["\u{0}1\u{0}a\u{0}"], /[1\0a]+/u.exec("b\u{0}1\u{0}a\u{0}2"));
+// escaped \- is allowed inside a character class.
+assertEquals(["-"], /[a\-z]/u.exec("12-34"));
diff --git a/test/mjsunit/es6/unicode-regexp-unanchored-advance.js b/test/mjsunit/es6/unicode-regexp-unanchored-advance.js
new file mode 100644
index 0000000..c471122
--- /dev/null
+++ b/test/mjsunit/es6/unicode-regexp-unanchored-advance.js
@@ -0,0 +1,6 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var s = "a".repeat(1E7) + "\u1234";
+assertEquals(["\u1234", "\u1234"], /(\u1234)/u.exec(s));
diff --git a/test/mjsunit/es6/unicode-regexp-zero-length.js b/test/mjsunit/es6/unicode-regexp-zero-length.js
new file mode 100644
index 0000000..42bb2d7
--- /dev/null
+++ b/test/mjsunit/es6/unicode-regexp-zero-length.js
@@ -0,0 +1,56 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var L = "\ud800";
+var T = "\udc00";
+var x = "x";
+
+var r = /()/g;  // Global, but not unicode.
+// Zero-length matches do not advance lastIndex.
+assertEquals(["", ""], r.exec(L + T + L + T));
+assertEquals(0, r.lastIndex);
+r.lastIndex = 1;
+assertEquals(["", ""], r.exec(L + T + L + T));
+assertEquals(1, r.lastIndex);
+
+var u = /()/ug;  // Global and unicode.
+// Zero-length matches do not advance lastIndex.
+assertEquals(["", ""], u.exec(L + T + L + T));
+assertEquals(0, u.lastIndex);
+u.lastIndex = 1;
+assertEquals(["", ""], u.exec(L + T + L + T));
+assertEquals(0, u.lastIndex);
+
+// However, with repeating matches, lastIndex does not matter.
+// We do advance from match to match.
+r.lastIndex = 2;
+assertEquals(x + L + x + T + x + L + x + T + x,
+             (L + T + L + T).replace(r, "x"));
+
+// With unicode flag, we advance code point by code point.
+u.lastIndex = 3;
+assertEquals(x + L + T + x + L + T + x,
+             (L + T + L + T).replace(u, "x"));
+
+// Test that exhausting the global match cache is fine.
+assertEquals((x + L + T).repeat(1000) + x,
+             (L + T).repeat(1000).replace(u, "x"));
+
+// Same thing for RegExp.prototype.match.
+r.lastIndex = 1;
+assertEquals(["","","","",""], (L + T + L + T).match(r));
+r.lastIndex = 2;
+assertEquals(["","","","",""], (L + T + L + T).match(r));
+
+u.lastIndex = 1;
+assertEquals(["","",""], (L + T + L + T).match(u));
+u.lastIndex = 2;
+assertEquals(["","",""], (L + T + L + T).match(u));
+
+var expected = [];
+for (var i = 0; i <= 1000; i++) expected.push("");
+assertEquals(expected, (L + T).repeat(1000).match(u));
+
+// Also test RegExp.prototype.@@split.
+assertEquals(["\u{12345}"], "\u{12345}".split(/(?:)/u));
diff --git a/test/mjsunit/es7/array-includes.js b/test/mjsunit/es7/array-includes.js
index 303042a..3981797 100644
--- a/test/mjsunit/es7/array-includes.js
+++ b/test/mjsunit/es7/array-includes.js
@@ -673,3 +673,8 @@
   assertFalse(Array.prototype.includes.call(new Uint8Array([1, 2, 3]), 4));
   assertFalse(Array.prototype.includes.call(new Uint8Array([1, 2, 3]), 2, 2));
 })();
+
+
+(function testUnscopable() {
+  assertTrue(Array.prototype[Symbol.unscopables].includes);
+})();
diff --git a/test/mjsunit/es7/object-observe-debug-event.js b/test/mjsunit/es7/object-observe-debug-event.js
deleted file mode 100644
index 06123b8..0000000
--- a/test/mjsunit/es7/object-observe-debug-event.js
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-object-observe
-// Flags: --expose-debug-as debug
-
-Debug = debug.Debug;
-
-var base_id = -1;
-var exception = null;
-var expected = [
-  "enqueue #1",
-  "willHandle #1",
-  "didHandle #1",
-];
-
-function assertLog(msg) {
-  print(msg);
-  assertTrue(expected.length > 0);
-  assertEquals(expected.shift(), msg);
-  if (!expected.length) {
-    Debug.setListener(null);
-  }
-}
-
-function listener(event, exec_state, event_data, data) {
-  if (event != Debug.DebugEvent.AsyncTaskEvent) return;
-  try {
-    if (base_id < 0)
-      base_id = event_data.id();
-    var id = event_data.id() - base_id + 1;
-    assertEquals("Object.observe", event_data.name());
-    assertLog(event_data.type() + " #" + id);
-  } catch (e) {
-    print(e + e.stack)
-    exception = e;
-  }
-}
-
-Debug.setListener(listener);
-
-var obj = {};
-Object.observe(obj, function(changes) {
-  print(change.type + " " + change.name + " " + change.oldValue);
-});
-
-obj.foo = 1;
-obj.zoo = 2;
-obj.foo = 3;
-
-assertNull(exception);
diff --git a/test/mjsunit/es7/object-observe-runtime.js b/test/mjsunit/es7/object-observe-runtime.js
deleted file mode 100644
index 1a07141..0000000
--- a/test/mjsunit/es7/object-observe-runtime.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-object-observe
-// Flags: --allow-natives-syntax
-
-// These tests are meant to ensure that that the Object.observe runtime
-// functions are hardened.
-
-var obj = {};
-%SetIsObserved(obj);
-assertThrows(function() {
-  %SetIsObserved(obj);
-});
-
-assertThrows(function() {
-  %SetIsObserved(this);
-});
diff --git a/test/mjsunit/es7/object-observe.js b/test/mjsunit/es7/object-observe.js
deleted file mode 100644
index a558c51..0000000
--- a/test/mjsunit/es7/object-observe.js
+++ /dev/null
@@ -1,1865 +0,0 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * 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-object-observe
-// Flags: --allow-natives-syntax
-
-var allObservers = [];
-function reset() {
-  allObservers.forEach(function(observer) { observer.reset(); });
-}
-
-function stringifyNoThrow(arg) {
-  try {
-    return JSON.stringify(arg);
-  } catch (e) {
-    return '{<circular reference>}';
-  }
-}
-
-function createObserver() {
-  "use strict";  // So that |this| in callback can be undefined.
-
-  var observer = {
-    records: undefined,
-    callbackCount: 0,
-    reset: function() {
-      this.records = undefined;
-      this.callbackCount = 0;
-    },
-    assertNotCalled: function() {
-      assertEquals(undefined, this.records);
-      assertEquals(0, this.callbackCount);
-    },
-    assertCalled: function() {
-      assertEquals(1, this.callbackCount);
-    },
-    assertRecordCount: function(count) {
-      this.assertCalled();
-      assertEquals(count, this.records.length);
-    },
-    assertCallbackRecords: function(recs) {
-      this.assertRecordCount(recs.length);
-      for (var i = 0; i < recs.length; i++) {
-        if ('name' in recs[i]) recs[i].name = String(recs[i].name);
-        print(i, stringifyNoThrow(this.records[i]), stringifyNoThrow(recs[i]));
-        assertSame(this.records[i].object, recs[i].object);
-        assertEquals('string', typeof recs[i].type);
-        assertPropertiesEqual(this.records[i], recs[i]);
-      }
-    }
-  };
-
-  observer.callback = function(r) {
-    assertEquals(undefined, this);
-    assertEquals('object', typeof r);
-    assertTrue(r instanceof Array)
-    observer.records = r;
-    observer.callbackCount++;
-  };
-
-  observer.reset();
-  allObservers.push(observer);
-  return observer;
-}
-
-var observer = createObserver();
-var observer2 = createObserver();
-
-assertEquals("function", typeof observer.callback);
-assertEquals("function", typeof observer2.callback);
-
-var obj = {};
-
-function frozenFunction() {}
-Object.freeze(frozenFunction);
-var nonFunction = {};
-var changeRecordWithAccessor = { type: 'foo' };
-var recordCreated = false;
-Object.defineProperty(changeRecordWithAccessor, 'name', {
-  get: function() {
-    recordCreated = true;
-    return "bar";
-  },
-  enumerable: true
-})
-
-
-// Object.observe
-assertThrows(function() { Object.observe("non-object", observer.callback); },
-             TypeError);
-assertThrows(function() { Object.observe(this, observer.callback); },
-             TypeError);
-assertThrows(function() { Object.observe(obj, nonFunction); }, TypeError);
-assertThrows(function() { Object.observe(obj, frozenFunction); }, TypeError);
-assertEquals(obj, Object.observe(obj, observer.callback, [1]));
-assertEquals(obj, Object.observe(obj, observer.callback, [true]));
-assertEquals(obj, Object.observe(obj, observer.callback, ['foo', null]));
-assertEquals(obj, Object.observe(obj, observer.callback, [undefined]));
-assertEquals(obj, Object.observe(obj, observer.callback,
-             ['foo', 'bar', 'baz']));
-assertEquals(obj, Object.observe(obj, observer.callback, []));
-assertEquals(obj, Object.observe(obj, observer.callback, undefined));
-assertEquals(obj, Object.observe(obj, observer.callback));
-
-// Object.unobserve
-assertThrows(function() { Object.unobserve(4, observer.callback); }, TypeError);
-assertThrows(function() { Object.unobserve(this, observer.callback); },
-             TypeError);
-assertThrows(function() { Object.unobserve(obj, nonFunction); }, TypeError);
-assertEquals(obj, Object.unobserve(obj, observer.callback));
-
-
-// Object.getNotifier
-var notifier = Object.getNotifier(obj);
-assertSame(notifier, Object.getNotifier(obj));
-assertEquals(null, Object.getNotifier(Object.freeze({})));
-assertThrows(function() { Object.getNotifier(this) }, TypeError);
-assertFalse(notifier.hasOwnProperty('notify'));
-assertEquals([], Object.keys(notifier));
-var notifyDesc = Object.getOwnPropertyDescriptor(notifier.__proto__, 'notify');
-assertTrue(notifyDesc.configurable);
-assertTrue(notifyDesc.writable);
-assertFalse(notifyDesc.enumerable);
-assertThrows(function() { notifier.notify({}); }, TypeError);
-assertThrows(function() { notifier.notify({ type: 4 }); }, TypeError);
-
-assertThrows(function() { notifier.performChange(1, function(){}); }, TypeError);
-assertThrows(function() { notifier.performChange(undefined, function(){}); }, TypeError);
-assertThrows(function() { notifier.performChange('foo', undefined); }, TypeError);
-assertThrows(function() { notifier.performChange('foo', 'bar'); }, TypeError);
-var global = this;
-notifier.performChange('foo', function() {
-  assertEquals(global, this);
-});
-
-var notify = notifier.notify;
-assertThrows(function() { notify.call(undefined, { type: 'a' }); }, TypeError);
-assertThrows(function() { notify.call(null, { type: 'a' }); }, TypeError);
-assertThrows(function() { notify.call(5, { type: 'a' }); }, TypeError);
-assertThrows(function() { notify.call('hello', { type: 'a' }); }, TypeError);
-assertThrows(function() { notify.call(false, { type: 'a' }); }, TypeError);
-assertThrows(function() { notify.call({}, { type: 'a' }); }, TypeError);
-assertFalse(recordCreated);
-notifier.notify(changeRecordWithAccessor);
-assertFalse(recordCreated);  // not observed yet
-
-
-// Object.deliverChangeRecords
-assertThrows(function() { Object.deliverChangeRecords(nonFunction); }, TypeError);
-
-Object.observe(obj, observer.callback);
-
-
-// notify uses to [[CreateOwnProperty]] to create changeRecord;
-reset();
-var protoExpandoAccessed = false;
-Object.defineProperty(Object.prototype, 'protoExpando',
-  {
-    configurable: true,
-    set: function() { protoExpandoAccessed = true; }
-  }
-);
-notifier.notify({ type: 'foo', protoExpando: 'val'});
-assertFalse(protoExpandoAccessed);
-delete Object.prototype.protoExpando;
-Object.deliverChangeRecords(observer.callback);
-
-
-// Multiple records are delivered.
-reset();
-notifier.notify({
-  type: 'update',
-  name: 'foo',
-  expando: 1
-});
-
-notifier.notify({
-  object: notifier,  // object property is ignored
-  type: 'delete',
-  name: 'bar',
-  expando2: 'str'
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: obj, name: 'foo', type: 'update', expando: 1 },
-  { object: obj, name: 'bar', type: 'delete', expando2: 'str' }
-]);
-
-// Non-string accept values are coerced to strings
-reset();
-Object.observe(obj, observer.callback, [true, 1, null, undefined]);
-notifier = Object.getNotifier(obj);
-notifier.notify({ type: 'true' });
-notifier.notify({ type: 'false' });
-notifier.notify({ type: '1' });
-notifier.notify({ type: '-1' });
-notifier.notify({ type: 'null' });
-notifier.notify({ type: 'nill' });
-notifier.notify({ type: 'undefined' });
-notifier.notify({ type: 'defined' });
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: obj, type: 'true' },
-  { object: obj, type: '1' },
-  { object: obj, type: 'null' },
-  { object: obj, type: 'undefined' }
-]);
-
-// No delivery takes place if no records are pending
-reset();
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-
-// Multiple observation has no effect.
-reset();
-Object.observe(obj, observer.callback);
-Object.observe(obj, observer.callback);
-Object.getNotifier(obj).notify({
-  type: 'update',
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCalled();
-
-
-// Observation can be stopped.
-reset();
-Object.unobserve(obj, observer.callback);
-Object.getNotifier(obj).notify({
-  type: 'update',
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-
-// Multiple unobservation has no effect
-reset();
-Object.unobserve(obj, observer.callback);
-Object.unobserve(obj, observer.callback);
-Object.getNotifier(obj).notify({
-  type: 'update',
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-
-// Re-observation works and only includes changeRecords after of call.
-reset();
-Object.getNotifier(obj).notify({
-  type: 'update',
-});
-Object.observe(obj, observer.callback);
-Object.getNotifier(obj).notify({
-  type: 'update',
-});
-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: 'add', name: 'id' },
-]);
-
-// The empty-string property is observable
-reset();
-var obj = {};
-Object.observe(obj, observer.callback);
-obj[''] = '';
-obj[''] = ' ';
-delete obj[''];
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: obj, type: 'add', name: '' },
-  { object: obj, type: 'update', name: '', oldValue: '' },
-  { object: obj, type: 'delete', name: '', oldValue: ' ' },
-]);
-
-// Object.preventExtensions
-reset();
-var obj = { foo: 'bar'};
-Object.observe(obj, observer.callback);
-obj.baz = 'bat';
-Object.preventExtensions(obj);
-
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: obj, type: 'add', name: 'baz' },
-  { object: obj, type: 'preventExtensions' },
-]);
-
-reset();
-var obj = { foo: 'bar'};
-Object.preventExtensions(obj);
-Object.observe(obj, observer.callback);
-Object.preventExtensions(obj);
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-// Object.freeze
-reset();
-var obj = { a: 'a' };
-Object.defineProperty(obj, 'b', {
-  writable: false,
-  configurable: true,
-  value: 'b'
-});
-Object.defineProperty(obj, 'c', {
-  writable: true,
-  configurable: false,
-  value: 'c'
-});
-Object.defineProperty(obj, 'd', {
-  writable: false,
-  configurable: false,
-  value: 'd'
-});
-Object.observe(obj, observer.callback);
-Object.freeze(obj);
-
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: obj, type: 'preventExtensions' },
-  { object: obj, type: 'reconfigure', name: 'a' },
-  { object: obj, type: 'reconfigure', name: 'b' },
-  { object: obj, type: 'reconfigure', name: 'c' },
-]);
-
-reset();
-var obj = { foo: 'bar'};
-Object.freeze(obj);
-Object.observe(obj, observer.callback);
-Object.freeze(obj);
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-// Object.seal
-reset();
-var obj = { a: 'a' };
-Object.defineProperty(obj, 'b', {
-  writable: false,
-  configurable: true,
-  value: 'b'
-});
-Object.defineProperty(obj, 'c', {
-  writable: true,
-  configurable: false,
-  value: 'c'
-});
-Object.defineProperty(obj, 'd', {
-  writable: false,
-  configurable: false,
-  value: 'd'
-});
-Object.observe(obj, observer.callback);
-Object.seal(obj);
-
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: obj, type: 'preventExtensions' },
-  { object: obj, type: 'reconfigure', name: 'a' },
-  { object: obj, type: 'reconfigure', name: 'b' },
-]);
-
-reset();
-var obj = { foo: 'bar'};
-Object.seal(obj);
-Object.observe(obj, observer.callback);
-Object.seal(obj);
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-// Observing a continuous stream of changes, while itermittantly unobserving.
-reset();
-var obj = {};
-Object.observe(obj, observer.callback);
-Object.getNotifier(obj).notify({
-  type: 'update',
-  val: 1
-});
-
-Object.unobserve(obj, observer.callback);
-Object.getNotifier(obj).notify({
-  type: 'update',
-  val: 2
-});
-
-Object.observe(obj, observer.callback);
-Object.getNotifier(obj).notify({
-  type: 'update',
-  val: 3
-});
-
-Object.unobserve(obj, observer.callback);
-Object.getNotifier(obj).notify({
-  type: 'update',
-  val: 4
-});
-
-Object.observe(obj, observer.callback);
-Object.getNotifier(obj).notify({
-  type: 'update',
-  val: 5
-});
-
-Object.unobserve(obj, observer.callback);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: obj, type: 'update', val: 1 },
-  { object: obj, type: 'update', val: 3 },
-  { object: obj, type: 'update', val: 5 }
-]);
-
-// Accept
-reset();
-Object.observe(obj, observer.callback, ['somethingElse']);
-Object.getNotifier(obj).notify({
-  type: 'add'
-});
-Object.getNotifier(obj).notify({
-  type: 'update'
-});
-Object.getNotifier(obj).notify({
-  type: 'delete'
-});
-Object.getNotifier(obj).notify({
-  type: 'reconfigure'
-});
-Object.getNotifier(obj).notify({
-  type: 'setPrototype'
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-reset();
-Object.observe(obj, observer.callback, ['add', 'delete', 'setPrototype']);
-Object.getNotifier(obj).notify({
-  type: 'add'
-});
-Object.getNotifier(obj).notify({
-  type: 'update'
-});
-Object.getNotifier(obj).notify({
-  type: 'delete'
-});
-Object.getNotifier(obj).notify({
-  type: 'delete'
-});
-Object.getNotifier(obj).notify({
-  type: 'reconfigure'
-});
-Object.getNotifier(obj).notify({
-  type: 'setPrototype'
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: obj, type: 'add' },
-  { object: obj, type: 'delete' },
-  { object: obj, type: 'delete' },
-  { object: obj, type: 'setPrototype' }
-]);
-
-reset();
-Object.observe(obj, observer.callback, ['update', 'foo']);
-Object.getNotifier(obj).notify({
-  type: 'add'
-});
-Object.getNotifier(obj).notify({
-  type: 'update'
-});
-Object.getNotifier(obj).notify({
-  type: 'delete'
-});
-Object.getNotifier(obj).notify({
-  type: 'foo'
-});
-Object.getNotifier(obj).notify({
-  type: 'bar'
-});
-Object.getNotifier(obj).notify({
-  type: 'foo'
-});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: obj, type: 'update' },
-  { object: obj, type: 'foo' },
-  { object: obj, type: 'foo' }
-]);
-
-reset();
-function Thingy(a, b, c) {
-  this.a = a;
-  this.b = b;
-}
-
-Thingy.MULTIPLY = 'multiply';
-Thingy.INCREMENT = 'increment';
-Thingy.INCREMENT_AND_MULTIPLY = 'incrementAndMultiply';
-
-Thingy.prototype = {
-  increment: function(amount) {
-    var notifier = Object.getNotifier(this);
-
-    var self = this;
-    notifier.performChange(Thingy.INCREMENT, function() {
-      self.a += amount;
-      self.b += amount;
-
-      return {
-        incremented: amount
-      };  // implicit notify
-    });
-  },
-
-  multiply: function(amount) {
-    var notifier = Object.getNotifier(this);
-
-    var self = this;
-    notifier.performChange(Thingy.MULTIPLY, function() {
-      self.a *= amount;
-      self.b *= amount;
-
-      return {
-        multiplied: amount
-      };  // implicit notify
-    });
-  },
-
-  incrementAndMultiply: function(incAmount, multAmount) {
-    var notifier = Object.getNotifier(this);
-
-    var self = this;
-    notifier.performChange(Thingy.INCREMENT_AND_MULTIPLY, function() {
-      self.increment(incAmount);
-      self.multiply(multAmount);
-
-      return {
-        incremented: incAmount,
-        multiplied: multAmount
-      };  // implicit notify
-    });
-  }
-}
-
-Thingy.observe = function(thingy, callback) {
-  Object.observe(thingy, callback, [Thingy.INCREMENT,
-                                    Thingy.MULTIPLY,
-                                    Thingy.INCREMENT_AND_MULTIPLY,
-                                    'update']);
-}
-
-Thingy.unobserve = function(thingy, callback) {
-  Object.unobserve(thingy);
-}
-
-var thingy = new Thingy(2, 4);
-
-Object.observe(thingy, observer.callback);
-Thingy.observe(thingy, observer2.callback);
-thingy.increment(3);               // { a: 5, b: 7 }
-thingy.b++;                        // { a: 5, b: 8 }
-thingy.multiply(2);                // { a: 10, b: 16 }
-thingy.a++;                        // { a: 11, b: 16 }
-thingy.incrementAndMultiply(2, 2); // { a: 26, b: 36 }
-
-Object.deliverChangeRecords(observer.callback);
-Object.deliverChangeRecords(observer2.callback);
-observer.assertCallbackRecords([
-  { object: thingy, type: 'update', name: 'a', oldValue: 2 },
-  { object: thingy, type: 'update', name: 'b', oldValue: 4 },
-  { object: thingy, type: 'update', name: 'b', oldValue: 7 },
-  { object: thingy, type: 'update', name: 'a', oldValue: 5 },
-  { object: thingy, type: 'update', name: 'b', oldValue: 8 },
-  { object: thingy, type: 'update', name: 'a', oldValue: 10 },
-  { object: thingy, type: 'update', name: 'a', oldValue: 11 },
-  { object: thingy, type: 'update', name: 'b', oldValue: 16 },
-  { object: thingy, type: 'update', name: 'a', oldValue: 13 },
-  { object: thingy, type: 'update', name: 'b', oldValue: 18 },
-]);
-observer2.assertCallbackRecords([
-  { object: thingy, type: Thingy.INCREMENT, incremented: 3 },
-  { object: thingy, type: 'update', name: 'b', oldValue: 7 },
-  { object: thingy, type: Thingy.MULTIPLY, multiplied: 2 },
-  { object: thingy, type: 'update', name: 'a', oldValue: 10 },
-  {
-    object: thingy,
-    type: Thingy.INCREMENT_AND_MULTIPLY,
-    incremented: 2,
-    multiplied: 2
-  }
-]);
-
-// ArrayPush cached stub
-reset();
-
-function pushMultiple(arr) {
-  arr.push('a');
-  arr.push('b');
-  arr.push('c');
-}
-
-for (var i = 0; i < 5; i++) {
-  var arr = [];
-  pushMultiple(arr);
-}
-
-for (var i = 0; i < 5; i++) {
-  reset();
-  var arr = [];
-  Object.observe(arr, observer.callback);
-  pushMultiple(arr);
-  Object.unobserve(arr, observer.callback);
-  Object.deliverChangeRecords(observer.callback);
-  observer.assertCallbackRecords([
-    { object: arr, type: 'add', name: '0' },
-    { object: arr, type: 'update', name: 'length', oldValue: 0 },
-    { object: arr, type: 'add', name: '1' },
-    { object: arr, type: 'update', name: 'length', oldValue: 1 },
-    { object: arr, type: 'add', name: '2' },
-    { object: arr, type: 'update', name: 'length', oldValue: 2 },
-  ]);
-}
-
-
-// ArrayPop cached stub
-reset();
-
-function popMultiple(arr) {
-  arr.pop();
-  arr.pop();
-  arr.pop();
-}
-
-for (var i = 0; i < 5; i++) {
-  var arr = ['a', 'b', 'c'];
-  popMultiple(arr);
-}
-
-for (var i = 0; i < 5; i++) {
-  reset();
-  var arr = ['a', 'b', 'c'];
-  Object.observe(arr, observer.callback);
-  popMultiple(arr);
-  Object.unobserve(arr, observer.callback);
-  Object.deliverChangeRecords(observer.callback);
-  observer.assertCallbackRecords([
-    { object: arr, type: 'delete', name: '2', oldValue: 'c' },
-    { object: arr, type: 'update', name: 'length', oldValue: 3 },
-    { object: arr, type: 'delete', name: '1', oldValue: 'b' },
-    { object: arr, type: 'update', name: 'length', oldValue: 2 },
-    { object: arr, type: 'delete', name: '0', oldValue: 'a' },
-    { object: arr, type: 'update', name: 'length', oldValue: 1 },
-  ]);
-}
-
-
-reset();
-function RecursiveThingy() {}
-
-RecursiveThingy.MULTIPLY_FIRST_N = 'multiplyFirstN';
-
-RecursiveThingy.prototype = {
-  __proto__: Array.prototype,
-
-  multiplyFirstN: function(amount, n) {
-    if (!n)
-      return;
-    var notifier = Object.getNotifier(this);
-    var self = this;
-    notifier.performChange(RecursiveThingy.MULTIPLY_FIRST_N, function() {
-      self[n-1] = self[n-1]*amount;
-      self.multiplyFirstN(amount, n-1);
-    });
-
-    notifier.notify({
-      type: RecursiveThingy.MULTIPLY_FIRST_N,
-      multiplied: amount,
-      n: n
-    });
-  },
-}
-
-RecursiveThingy.observe = function(thingy, callback) {
-  Object.observe(thingy, callback, [RecursiveThingy.MULTIPLY_FIRST_N]);
-}
-
-RecursiveThingy.unobserve = function(thingy, callback) {
-  Object.unobserve(thingy);
-}
-
-var thingy = new RecursiveThingy;
-thingy.push(1, 2, 3, 4);
-
-Object.observe(thingy, observer.callback);
-RecursiveThingy.observe(thingy, observer2.callback);
-thingy.multiplyFirstN(2, 3);                // [2, 4, 6, 4]
-
-Object.deliverChangeRecords(observer.callback);
-Object.deliverChangeRecords(observer2.callback);
-observer.assertCallbackRecords([
-  { object: thingy, type: 'update', name: '2', oldValue: 3 },
-  { object: thingy, type: 'update', name: '1', oldValue: 2 },
-  { object: thingy, type: 'update', name: '0', oldValue: 1 }
-]);
-observer2.assertCallbackRecords([
-  { object: thingy, type: RecursiveThingy.MULTIPLY_FIRST_N, multiplied: 2, n: 3 }
-]);
-
-reset();
-function DeckSuit() {
-  this.push('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'A', 'Q', 'K');
-}
-
-DeckSuit.SHUFFLE = 'shuffle';
-
-DeckSuit.prototype = {
-  __proto__: Array.prototype,
-
-  shuffle: function() {
-    var notifier = Object.getNotifier(this);
-    var self = this;
-    notifier.performChange(DeckSuit.SHUFFLE, function() {
-      self.reverse();
-      self.sort(function() { return Math.random()* 2 - 1; });
-      var cut = self.splice(0, 6);
-      Array.prototype.push.apply(self, cut);
-      self.reverse();
-      self.sort(function() { return Math.random()* 2 - 1; });
-      var cut = self.splice(0, 6);
-      Array.prototype.push.apply(self, cut);
-      self.reverse();
-      self.sort(function() { return Math.random()* 2 - 1; });
-    });
-
-    notifier.notify({
-      type: DeckSuit.SHUFFLE
-    });
-  },
-}
-
-DeckSuit.observe = function(thingy, callback) {
-  Object.observe(thingy, callback, [DeckSuit.SHUFFLE]);
-}
-
-DeckSuit.unobserve = function(thingy, callback) {
-  Object.unobserve(thingy);
-}
-
-var deck = new DeckSuit;
-
-DeckSuit.observe(deck, observer2.callback);
-deck.shuffle();
-
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
-  { object: deck, type: DeckSuit.SHUFFLE }
-]);
-
-// Observing multiple objects; records appear in order.
-reset();
-var obj2 = {};
-var obj3 = {}
-Object.observe(obj, observer.callback);
-Object.observe(obj3, observer.callback);
-Object.observe(obj2, observer.callback);
-Object.getNotifier(obj).notify({
-  type: 'add',
-});
-Object.getNotifier(obj2).notify({
-  type: 'update',
-});
-Object.getNotifier(obj3).notify({
-  type: 'delete',
-});
-Object.observe(obj3, observer.callback);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: obj, type: 'add' },
-  { object: obj2, type: 'update' },
-  { object: obj3, type: 'delete' }
-]);
-
-
-// Recursive observation.
-var obj = {a: 1};
-var callbackCount = 0;
-function recursiveObserver(r) {
-  assertEquals(1, r.length);
-  ++callbackCount;
-  if (r[0].oldValue < 100) ++obj[r[0].name];
-}
-Object.observe(obj, recursiveObserver);
-++obj.a;
-Object.deliverChangeRecords(recursiveObserver);
-assertEquals(100, callbackCount);
-
-var obj1 = {a: 1};
-var obj2 = {a: 1};
-var recordCount = 0;
-function recursiveObserver2(r) {
-  recordCount += r.length;
-  if (r[0].oldValue < 100) {
-    ++obj1.a;
-    ++obj2.a;
-  }
-}
-Object.observe(obj1, recursiveObserver2);
-Object.observe(obj2, recursiveObserver2);
-++obj1.a;
-Object.deliverChangeRecords(recursiveObserver2);
-assertEquals(199, recordCount);
-
-
-// Observing named properties.
-reset();
-var obj = {a: 1}
-Object.observe(obj, observer.callback);
-obj.a = 2;
-obj["a"] = 3;
-delete obj.a;
-obj.a = 4;
-obj.a = 4;  // ignored
-obj.a = 5;
-Object.defineProperty(obj, "a", {value: 6});
-Object.defineProperty(obj, "a", {writable: false});
-obj.a = 7;  // ignored
-Object.defineProperty(obj, "a", {value: 8});
-Object.defineProperty(obj, "a", {value: 7, writable: true});
-Object.defineProperty(obj, "a", {get: function() {}});
-Object.defineProperty(obj, "a", {get: frozenFunction});
-Object.defineProperty(obj, "a", {get: frozenFunction});  // ignored
-Object.defineProperty(obj, "a", {get: frozenFunction, set: frozenFunction});
-Object.defineProperty(obj, "a", {set: frozenFunction});  // ignored
-Object.defineProperty(obj, "a", {get: undefined, set: frozenFunction});
-delete obj.a;
-delete obj.a;
-Object.defineProperty(obj, "a", {get: function() {}, configurable: true});
-Object.defineProperty(obj, "a", {value: 9, writable: true});
-obj.a = 10;
-++obj.a;
-obj.a++;
-obj.a *= 3;
-delete obj.a;
-Object.defineProperty(obj, "a", {value: 11, configurable: true});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: obj, name: "a", type: "update", oldValue: 1 },
-  { object: obj, name: "a", type: "update", oldValue: 2 },
-  { object: obj, name: "a", type: "delete", oldValue: 3 },
-  { object: obj, name: "a", type: "add" },
-  { object: obj, name: "a", type: "update", oldValue: 4 },
-  { object: obj, name: "a", type: "update", oldValue: 5 },
-  { object: obj, name: "a", type: "reconfigure" },
-  { object: obj, name: "a", type: "update", oldValue: 6 },
-  { object: obj, name: "a", type: "reconfigure", oldValue: 8 },
-  { object: obj, name: "a", type: "reconfigure", oldValue: 7 },
-  { object: obj, name: "a", type: "reconfigure" },
-  { object: obj, name: "a", type: "reconfigure" },
-  { object: obj, name: "a", type: "reconfigure" },
-  { object: obj, name: "a", type: "delete" },
-  { object: obj, name: "a", type: "add" },
-  { object: obj, name: "a", type: "reconfigure" },
-  { object: obj, name: "a", type: "update", oldValue: 9 },
-  { object: obj, name: "a", type: "update", oldValue: 10 },
-  { object: obj, name: "a", type: "update", oldValue: 11 },
-  { object: obj, name: "a", type: "update", oldValue: 12 },
-  { object: obj, name: "a", type: "delete", oldValue: 36 },
-  { object: obj, name: "a", type: "add" },
-]);
-
-
-// Observing indexed properties.
-reset();
-var obj = {'1': 1}
-Object.observe(obj, observer.callback);
-obj[1] = 2;
-obj[1] = 3;
-delete obj[1];
-obj[1] = 4;
-obj[1] = 4;  // ignored
-obj[1] = 5;
-Object.defineProperty(obj, "1", {value: 6});
-Object.defineProperty(obj, "1", {writable: false});
-obj[1] = 7;  // ignored
-Object.defineProperty(obj, "1", {value: 8});
-Object.defineProperty(obj, "1", {value: 7, writable: true});
-Object.defineProperty(obj, "1", {get: function() {}});
-Object.defineProperty(obj, "1", {get: frozenFunction});
-Object.defineProperty(obj, "1", {get: frozenFunction});  // ignored
-Object.defineProperty(obj, "1", {get: frozenFunction, set: frozenFunction});
-Object.defineProperty(obj, "1", {set: frozenFunction});  // ignored
-Object.defineProperty(obj, "1", {get: undefined, set: frozenFunction});
-delete obj[1];
-delete obj[1];
-Object.defineProperty(obj, "1", {get: function() {}, configurable: true});
-Object.defineProperty(obj, "1", {value: 9, writable: true});
-obj[1] = 10;
-++obj[1];
-obj[1]++;
-obj[1] *= 3;
-delete obj[1];
-Object.defineProperty(obj, "1", {value: 11, configurable: true});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: obj, name: "1", type: "update", oldValue: 1 },
-  { object: obj, name: "1", type: "update", oldValue: 2 },
-  { object: obj, name: "1", type: "delete", oldValue: 3 },
-  { object: obj, name: "1", type: "add" },
-  { object: obj, name: "1", type: "update", oldValue: 4 },
-  { object: obj, name: "1", type: "update", oldValue: 5 },
-  { object: obj, name: "1", type: "reconfigure" },
-  { object: obj, name: "1", type: "update", oldValue: 6 },
-  { object: obj, name: "1", type: "reconfigure", oldValue: 8 },
-  { object: obj, name: "1", type: "reconfigure", oldValue: 7 },
-  { object: obj, name: "1", type: "reconfigure" },
-  { object: obj, name: "1", type: "reconfigure" },
-  { object: obj, name: "1", type: "reconfigure" },
-  { object: obj, name: "1", type: "delete" },
-  { object: obj, name: "1", type: "add" },
-  { object: obj, name: "1", type: "reconfigure" },
-  { object: obj, name: "1", type: "update", oldValue: 9 },
-  { object: obj, name: "1", type: "update", oldValue: 10 },
-  { object: obj, name: "1", type: "update", oldValue: 11 },
-  { object: obj, name: "1", type: "update", oldValue: 12 },
-  { object: obj, name: "1", type: "delete", oldValue: 36 },
-  { object: obj, name: "1", type: "add" },
-]);
-
-
-// Observing symbol properties (not).
-print("*****")
-reset();
-var obj = {}
-var symbol = Symbol("secret");
-Object.observe(obj, observer.callback);
-obj[symbol] = 3;
-delete obj[symbol];
-Object.defineProperty(obj, symbol, {get: function() {}, configurable: true});
-Object.defineProperty(obj, symbol, {value: 6});
-Object.defineProperty(obj, symbol, {writable: false});
-delete obj[symbol];
-Object.defineProperty(obj, symbol, {value: 7});
-++obj[symbol];
-obj[symbol]++;
-obj[symbol] *= 3;
-delete obj[symbol];
-obj.__defineSetter__(symbol, function() {});
-obj.__defineGetter__(symbol, function() {});
-Object.deliverChangeRecords(observer.callback);
-observer.assertNotCalled();
-
-
-// Test all kinds of objects generically.
-function TestObserveConfigurable(obj, prop) {
-  reset();
-  Object.observe(obj, observer.callback);
-  Object.unobserve(obj, observer.callback);
-  obj[prop] = 1;
-  Object.observe(obj, observer.callback);
-  obj[prop] = 2;
-  obj[prop] = 3;
-  delete obj[prop];
-  obj[prop] = 4;
-  obj[prop] = 4;  // ignored
-  obj[prop] = 5;
-  Object.defineProperty(obj, prop, {value: 6});
-  Object.defineProperty(obj, prop, {writable: false});
-  obj[prop] = 7;  // ignored
-  Object.defineProperty(obj, prop, {value: 8});
-  Object.defineProperty(obj, prop, {value: 7, writable: true});
-  Object.defineProperty(obj, prop, {get: function() {}});
-  Object.defineProperty(obj, prop, {get: frozenFunction});
-  Object.defineProperty(obj, prop, {get: frozenFunction});  // ignored
-  Object.defineProperty(obj, prop, {get: frozenFunction, set: frozenFunction});
-  Object.defineProperty(obj, prop, {set: frozenFunction});  // ignored
-  Object.defineProperty(obj, prop, {get: undefined, set: frozenFunction});
-  obj.__defineSetter__(prop, frozenFunction);  // ignored
-  obj.__defineSetter__(prop, function() {});
-  obj.__defineGetter__(prop, function() {});
-  delete obj[prop];
-  delete obj[prop];  // ignored
-  obj.__defineGetter__(prop, function() {});
-  delete obj[prop];
-  Object.defineProperty(obj, prop, {get: function() {}, configurable: true});
-  Object.defineProperty(obj, prop, {value: 9, writable: true});
-  obj[prop] = 10;
-  ++obj[prop];
-  obj[prop]++;
-  obj[prop] *= 3;
-  delete obj[prop];
-  Object.defineProperty(obj, prop, {value: 11, configurable: true});
-  Object.deliverChangeRecords(observer.callback);
-  observer.assertCallbackRecords([
-    { object: obj, name: prop, type: "update", oldValue: 1 },
-    { object: obj, name: prop, type: "update", oldValue: 2 },
-    { object: obj, name: prop, type: "delete", oldValue: 3 },
-    { object: obj, name: prop, type: "add" },
-    { object: obj, name: prop, type: "update", oldValue: 4 },
-    { object: obj, name: prop, type: "update", oldValue: 5 },
-    { object: obj, name: prop, type: "reconfigure" },
-    { object: obj, name: prop, type: "update", oldValue: 6 },
-    { object: obj, name: prop, type: "reconfigure", oldValue: 8 },
-    { object: obj, name: prop, type: "reconfigure", oldValue: 7 },
-    { object: obj, name: prop, type: "reconfigure" },
-    { object: obj, name: prop, type: "reconfigure" },
-    { object: obj, name: prop, type: "reconfigure" },
-    { object: obj, name: prop, type: "reconfigure" },
-    { object: obj, name: prop, type: "reconfigure" },
-    { object: obj, name: prop, type: "delete" },
-    { object: obj, name: prop, type: "add" },
-    { object: obj, name: prop, type: "delete" },
-    { object: obj, name: prop, type: "add" },
-    { object: obj, name: prop, type: "reconfigure" },
-    { object: obj, name: prop, type: "update", oldValue: 9 },
-    { object: obj, name: prop, type: "update", oldValue: 10 },
-    { object: obj, name: prop, type: "update", oldValue: 11 },
-    { object: obj, name: prop, type: "update", oldValue: 12 },
-    { object: obj, name: prop, type: "delete", oldValue: 36 },
-    { object: obj, name: prop, type: "add" },
-  ]);
-  Object.unobserve(obj, observer.callback);
-  delete 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;
-  obj[prop] = 4;  // ignored
-  obj[prop] = 5;
-  Object.defineProperty(obj, prop, {value: 6});
-  Object.defineProperty(obj, prop, {value: 6});  // ignored
-  Object.defineProperty(obj, prop, {value: 7});
-  Object.defineProperty(obj, prop, {enumerable: desc.enumerable});  // ignored
-  Object.defineProperty(obj, prop, {writable: false});
-  obj[prop] = 7;  // ignored
-  Object.deliverChangeRecords(observer.callback);
-  observer.assertCallbackRecords([
-    { object: obj, name: prop, type: "update", oldValue: 1 },
-    { object: obj, name: prop, type: "update", oldValue: 4 },
-    { object: obj, name: prop, type: "update", oldValue: 5 },
-    { object: obj, name: prop, type: "update", oldValue: 6 },
-    { object: obj, name: prop, type: "reconfigure" },
-  ]);
-  Object.unobserve(obj, observer.callback);
-}
-
-// TODO(rafaelw) Enable when ES6 Proxies are implemented
-/*
-function createProxy(create, x) {
-  var handler = {
-    getPropertyDescriptor: function(k) {
-      for (var o = this.target; o; o = Object.getPrototypeOf(o)) {
-        var desc = Object.getOwnPropertyDescriptor(o, k);
-        if (desc) return desc;
-      }
-      return undefined;
-    },
-    getOwnPropertyDescriptor: function(k) {
-      return Object.getOwnPropertyDescriptor(this.target, k);
-    },
-    defineProperty: function(k, desc) {
-      var x = Object.defineProperty(this.target, k, desc);
-      Object.deliverChangeRecords(this.callback);
-      return x;
-    },
-    delete: function(k) {
-      var x = delete this.target[k];
-      Object.deliverChangeRecords(this.callback);
-      return x;
-    },
-    getPropertyNames: function() {
-      return Object.getOwnPropertyNames(this.target);
-    },
-    target: {isProxy: true},
-    callback: function(changeRecords) {
-      print("callback", stringifyNoThrow(handler.proxy), stringifyNoThrow(got));
-      for (var i in changeRecords) {
-        var got = changeRecords[i];
-        var change = {object: handler.proxy, name: got.name, type: got.type};
-        if ("oldValue" in got) change.oldValue = got.oldValue;
-        Object.getNotifier(handler.proxy).notify(change);
-      }
-    },
-  };
-  Object.observe(handler.target, handler.callback);
-  return handler.proxy = create(handler, x);
-}
-*/
-
-var objects = [
-  {},
-  [],
-  function(){},
-  (function(){ return arguments })(),
-  (function(){ "use strict"; return arguments })(),
-  Object(1), Object(true), Object("bla"),
-  new Date(),
-  Object, Function, Date, RegExp,
-  new Set, new Map, new WeakMap,
-  new ArrayBuffer(10), new Int32Array(5)
-// TODO(rafaelw) Enable when ES6 Proxies are implemented.
-//  createProxy(Proxy.create, null),
-//  createProxy(Proxy.createFunction, function(){}),
-];
-var properties = ["a", "1", 1, "length", "setPrototype", "name", "caller"];
-
-// Cases that yield non-standard results.
-function blacklisted(obj, prop) {
-  return (obj instanceof Int32Array && prop == 1) ||
-         (obj instanceof Int32Array && prop === "length") ||
-         (obj instanceof ArrayBuffer && prop == 1) ||
-         (obj instanceof Function && prop === "name") ||  // Has its own test.
-         (obj instanceof Function && prop === "length");  // Has its own test.
-}
-
-for (var i in objects) for (var j in properties) {
-  var obj = objects[i];
-  var prop = properties[j];
-  if (blacklisted(obj, prop)) continue;
-  var desc = Object.getOwnPropertyDescriptor(obj, prop);
-  print("***", typeof obj, stringifyNoThrow(obj), prop);
-  if (!desc || desc.configurable)
-    TestObserveConfigurable(obj, prop);
-  else if (desc.writable)
-    TestObserveNonConfigurable(obj, prop, desc);
-}
-
-
-// Observing array length (including truncation)
-reset();
-var arr = ['a', 'b', 'c', 'd'];
-var arr2 = ['alpha', 'beta'];
-var arr3 = ['hello'];
-arr3[2] = 'goodbye';
-arr3.length = 6;
-Object.defineProperty(arr, '0', {configurable: false});
-Object.defineProperty(arr, '2', {get: function(){}});
-Object.defineProperty(arr2, '0', {get: function(){}, configurable: false});
-Object.observe(arr, observer.callback);
-Array.observe(arr, observer2.callback);
-Object.observe(arr2, observer.callback);
-Array.observe(arr2, observer2.callback);
-Object.observe(arr3, observer.callback);
-Array.observe(arr3, observer2.callback);
-arr.length = 2;
-arr.length = 0;
-arr.length = 10;
-Object.defineProperty(arr, 'length', {writable: false});
-arr2.length = 0;
-arr2.length = 1; // no change expected
-Object.defineProperty(arr2, 'length', {value: 1, writable: false});
-arr3.length = 0;
-++arr3.length;
-arr3.length++;
-arr3.length /= 2;
-Object.defineProperty(arr3, 'length', {value: 5});
-arr3[4] = 5;
-Object.defineProperty(arr3, 'length', {value: 1, writable: false});
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: arr, name: '3', type: 'delete', oldValue: 'd' },
-  { object: arr, name: '2', type: 'delete' },
-  { object: arr, name: 'length', type: 'update', oldValue: 4 },
-  { object: arr, name: '1', type: 'delete', oldValue: 'b' },
-  { object: arr, name: 'length', type: 'update', oldValue: 2 },
-  { object: arr, name: 'length', type: 'update', oldValue: 1 },
-  { object: arr, name: 'length', type: 'reconfigure' },
-  { object: arr2, name: '1', type: 'delete', oldValue: 'beta' },
-  { object: arr2, name: 'length', type: 'update', oldValue: 2 },
-  { object: arr2, name: 'length', type: 'reconfigure' },
-  { object: arr3, name: '2', type: 'delete', oldValue: 'goodbye' },
-  { object: arr3, name: '0', type: 'delete', oldValue: 'hello' },
-  { object: arr3, name: 'length', type: 'update', oldValue: 6 },
-  { object: arr3, name: 'length', type: 'update', oldValue: 0 },
-  { object: arr3, name: 'length', type: 'update', oldValue: 1 },
-  { object: arr3, name: 'length', type: 'update', oldValue: 2 },
-  { object: arr3, name: 'length', type: 'update', oldValue: 1 },
-  { object: arr3, name: '4', type: 'add' },
-  { object: arr3, name: '4', type: 'delete', oldValue: 5 },
-  // TODO(rafaelw): It breaks spec compliance to get two records here.
-  // When the TODO in v8natives.js::DefineArrayProperty is addressed
-  // which prevents DefineProperty from over-writing the magic length
-  // property, these will collapse into a single record.
-  { object: arr3, name: 'length', type: 'update', oldValue: 5 },
-  { object: arr3, name: 'length', type: 'reconfigure' }
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
-  { object: arr, type: 'splice', index: 2, removed: [, 'd'], addedCount: 0 },
-  { object: arr, type: 'splice', index: 1, removed: ['b'], addedCount: 0 },
-  { object: arr, type: 'splice', index: 1, removed: [], addedCount: 9 },
-  { object: arr2, type: 'splice', index: 1, removed: ['beta'], addedCount: 0 },
-  { object: arr3, type: 'splice', index: 0, removed: ['hello',, 'goodbye',,,,], addedCount: 0 },
-  { object: arr3, type: 'splice', index: 0, removed: [], addedCount: 1 },
-  { object: arr3, type: 'splice', index: 1, removed: [], addedCount: 1 },
-  { object: arr3, type: 'splice', index: 1, removed: [,], addedCount: 0 },
-  { object: arr3, type: 'splice', index: 1, removed: [], addedCount: 4 },
-  { object: arr3, name: '4', type: 'add' },
-  { object: arr3, type: 'splice', index: 1, removed: [,,,5], addedCount: 0 }
-]);
-
-
-// Updating length on large (slow) array
-reset();
-var slow_arr = %NormalizeElements([]);
-slow_arr[500000000] = 'hello';
-slow_arr.length = 1000000000;
-Object.observe(slow_arr, observer.callback);
-var spliceRecords;
-function slowSpliceCallback(records) {
-  spliceRecords = records;
-}
-Array.observe(slow_arr, slowSpliceCallback);
-slow_arr.length = 100;
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: slow_arr, name: '500000000', type: 'delete', oldValue: 'hello' },
-  { object: slow_arr, name: 'length', type: 'update', oldValue: 1000000000 },
-]);
-Object.deliverChangeRecords(slowSpliceCallback);
-assertEquals(spliceRecords.length, 1);
-// Have to custom assert this splice record because the removed array is huge.
-var splice = spliceRecords[0];
-assertSame(splice.object, slow_arr);
-assertEquals(splice.type, 'splice');
-assertEquals(splice.index, 100);
-assertEquals(splice.addedCount, 0);
-var array_keys = %GetArrayKeys(splice.removed, splice.removed.length);
-assertEquals(array_keys.length, 1);
-assertEquals(array_keys[0], 499999900);
-assertEquals(splice.removed[499999900], 'hello');
-assertEquals(splice.removed.length, 999999900);
-
-
-// Assignments in loops (checking different IC states).
-reset();
-var obj = {};
-Object.observe(obj, observer.callback);
-for (var i = 0; i < 5; i++) {
-  obj["a" + i] = i;
-}
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: obj, name: "a0", type: "add" },
-  { object: obj, name: "a1", type: "add" },
-  { object: obj, name: "a2", type: "add" },
-  { object: obj, name: "a3", type: "add" },
-  { object: obj, name: "a4", type: "add" },
-]);
-
-reset();
-var obj = {};
-Object.observe(obj, observer.callback);
-for (var i = 0; i < 5; i++) {
-  obj[i] = i;
-}
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: obj, name: "0", type: "add" },
-  { object: obj, name: "1", type: "add" },
-  { object: obj, name: "2", type: "add" },
-  { object: obj, name: "3", type: "add" },
-  { object: obj, name: "4", type: "add" },
-]);
-
-
-// Adding elements past the end of an array should notify on length for
-// Object.observe and emit "splices" for Array.observe.
-reset();
-var arr = [1, 2, 3];
-Object.observe(arr, observer.callback);
-Array.observe(arr, observer2.callback);
-arr[3] = 10;
-arr[100] = 20;
-Object.defineProperty(arr, '200', {value: 7});
-Object.defineProperty(arr, '400', {get: function(){}});
-arr[50] = 30; // no length change expected
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: arr, name: '3', type: 'add' },
-  { object: arr, name: 'length', type: 'update', oldValue: 3 },
-  { object: arr, name: '100', type: 'add' },
-  { object: arr, name: 'length', type: 'update', oldValue: 4 },
-  { object: arr, name: '200', type: 'add' },
-  { object: arr, name: 'length', type: 'update', oldValue: 101 },
-  { object: arr, name: '400', type: 'add' },
-  { object: arr, name: 'length', type: 'update', oldValue: 201 },
-  { object: arr, name: '50', type: 'add' },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
-  { object: arr, type: 'splice', index: 3, removed: [], addedCount: 1 },
-  { object: arr, type: 'splice', index: 4, removed: [], addedCount: 97 },
-  { object: arr, type: 'splice', index: 101, removed: [], addedCount: 100 },
-  { object: arr, type: 'splice', index: 201, removed: [], addedCount: 200 },
-  { object: arr, type: 'add', name: '50' },
-]);
-
-
-// Tests for array methods, first on arrays and then on plain objects
-//
-// === ARRAYS ===
-//
-// Push
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.push(3, 4);
-array.push(5);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, name: '2', type: 'add' },
-  { object: array, name: 'length', type: 'update', oldValue: 2 },
-  { object: array, name: '3', type: 'add' },
-  { object: array, name: 'length', type: 'update', oldValue: 3 },
-  { object: array, name: '4', type: 'add' },
-  { object: array, name: 'length', type: 'update', oldValue: 4 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
-  { object: array, type: 'splice', index: 2, removed: [], addedCount: 2 },
-  { object: array, type: 'splice', index: 4, removed: [], addedCount: 1 }
-]);
-
-// Pop
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-array.pop();
-array.pop();
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, name: '1', type: 'delete', oldValue: 2 },
-  { object: array, name: 'length', type: 'update', oldValue: 2 },
-  { object: array, name: '0', type: 'delete', oldValue: 1 },
-  { object: array, name: 'length', type: 'update', oldValue: 1 },
-]);
-
-// Shift
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-array.shift();
-array.shift();
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, name: '0', type: 'update', oldValue: 1 },
-  { object: array, name: '1', type: 'delete', oldValue: 2 },
-  { object: array, name: 'length', type: 'update', oldValue: 2 },
-  { object: array, name: '0', type: 'delete', oldValue: 2 },
-  { object: array, name: 'length', type: 'update', oldValue: 1 },
-]);
-
-// Unshift
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-array.unshift(3, 4);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, name: '3', type: 'add' },
-  { object: array, name: 'length', type: 'update', oldValue: 2 },
-  { object: array, name: '2', type: 'add' },
-  { object: array, name: '0', type: 'update', oldValue: 1 },
-  { object: array, name: '1', type: 'update', oldValue: 2 },
-]);
-
-// Splice
-reset();
-var array = [1, 2, 3];
-Object.observe(array, observer.callback);
-array.splice(1, 1, 4, 5);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, name: '3', type: 'add' },
-  { object: array, name: 'length', type: 'update', oldValue: 3 },
-  { object: array, name: '1', type: 'update', oldValue: 2 },
-  { object: array, name: '2', type: 'update', oldValue: 3 },
-]);
-
-// Sort
-reset();
-var array = [3, 2, 1];
-Object.observe(array, observer.callback);
-array.sort();
-assertEquals(1, array[0]);
-assertEquals(2, array[1]);
-assertEquals(3, array[2]);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, name: '1', type: 'update', oldValue: 2 },
-  { object: array, name: '0', type: 'update', oldValue: 3 },
-  { object: array, name: '2', type: 'update', oldValue: 1 },
-  { object: array, name: '1', type: 'update', oldValue: 3 },
-  { object: array, name: '0', type: 'update', oldValue: 2 },
-]);
-
-// Splice emitted after Array mutation methods
-function MockArray(initial, observer) {
-  for (var i = 0; i < initial.length; i++)
-    this[i] = initial[i];
-
-  this.length_ = initial.length;
-  this.observer = observer;
-}
-MockArray.prototype = {
-  set length(length) {
-    Object.getNotifier(this).notify({ type: 'lengthChange' });
-    this.length_ = length;
-    Object.observe(this, this.observer.callback, ['splice']);
-  },
-  get length() {
-    return this.length_;
-  }
-}
-
-reset();
-var array = new MockArray([], observer);
-Object.observe(array, observer.callback, ['lengthChange']);
-Array.prototype.push.call(array, 1);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, type: 'lengthChange' },
-  { object: array, type: 'splice', index: 0, removed: [], addedCount: 1 },
-]);
-
-reset();
-var array = new MockArray([1], observer);
-Object.observe(array, observer.callback, ['lengthChange']);
-Array.prototype.pop.call(array);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, type: 'lengthChange' },
-  { object: array, type: 'splice', index: 0, removed: [1], addedCount: 0 },
-]);
-
-reset();
-var array = new MockArray([1], observer);
-Object.observe(array, observer.callback, ['lengthChange']);
-Array.prototype.shift.call(array);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, type: 'lengthChange' },
-  { object: array, type: 'splice', index: 0, removed: [1], addedCount: 0 },
-]);
-
-reset();
-var array = new MockArray([], observer);
-Object.observe(array, observer.callback, ['lengthChange']);
-Array.prototype.unshift.call(array, 1);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, type: 'lengthChange' },
-  { object: array, type: 'splice', index: 0, removed: [], addedCount: 1 },
-]);
-
-reset();
-var array = new MockArray([0, 1, 2], observer);
-Object.observe(array, observer.callback, ['lengthChange']);
-Array.prototype.splice.call(array, 1, 1);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, type: 'lengthChange' },
-  { object: array, type: 'splice', index: 1, removed: [1], addedCount: 0 },
-]);
-
-//
-// === PLAIN OBJECTS ===
-//
-// Push
-reset()
-var array = {0: 1, 1: 2, length: 2}
-Object.observe(array, observer.callback);
-Array.prototype.push.call(array, 3, 4);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, name: '2', type: 'add' },
-  { object: array, name: '3', type: 'add' },
-  { object: array, name: 'length', type: 'update', oldValue: 2 },
-]);
-
-// Pop
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.pop();
-array.pop();
-array.pop();
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, name: '1', type: 'delete', oldValue: 2 },
-  { object: array, name: 'length', type: 'update', oldValue: 2 },
-  { object: array, name: '0', type: 'delete', oldValue: 1 },
-  { object: array, name: 'length', type: 'update', oldValue: 1 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
-  { object: array, type: 'splice', index: 1, removed: [2], addedCount: 0 },
-  { object: array, type: 'splice', index: 0, removed: [1], addedCount: 0 }
-]);
-
-// Shift
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.shift();
-array.shift();
-array.shift();
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, name: '0', type: 'update', oldValue: 1 },
-  { object: array, name: '1', type: 'delete', oldValue: 2 },
-  { object: array, name: 'length', type: 'update', oldValue: 2 },
-  { object: array, name: '0', type: 'delete', oldValue: 2 },
-  { object: array, name: 'length', type: 'update', oldValue: 1 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
-  { object: array, type: 'splice', index: 0, removed: [1], addedCount: 0 },
-  { object: array, type: 'splice', index: 0, removed: [2], addedCount: 0 }
-]);
-
-// Unshift
-reset();
-var array = [1, 2];
-Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.unshift(3, 4);
-array.unshift(5);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, name: '3', type: 'add' },
-  { object: array, name: 'length', type: 'update', oldValue: 2 },
-  { object: array, name: '2', type: 'add' },
-  { object: array, name: '0', type: 'update', oldValue: 1 },
-  { object: array, name: '1', type: 'update', oldValue: 2 },
-  { object: array, name: '4', type: 'add' },
-  { object: array, name: 'length', type: 'update', oldValue: 4 },
-  { object: array, name: '3', type: 'update', oldValue: 2 },
-  { object: array, name: '2', type: 'update', oldValue: 1 },
-  { object: array, name: '1', type: 'update', oldValue: 4 },
-  { object: array, name: '0', type: 'update', oldValue: 3 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
-  { object: array, type: 'splice', index: 0, removed: [], addedCount: 2 },
-  { object: array, type: 'splice', index: 0, removed: [], addedCount: 1 }
-]);
-
-// Splice
-reset();
-var array = [1, 2, 3];
-Object.observe(array, observer.callback);
-Array.observe(array, observer2.callback);
-array.splice(1, 0, 4, 5); // 1 4 5 2 3
-array.splice(0, 2); // 5 2 3
-array.splice(1, 2, 6, 7); // 5 6 7
-array.splice(2, 0);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, name: '4', type: 'add' },
-  { object: array, name: 'length', type: 'update', oldValue: 3 },
-  { object: array, name: '3', type: 'add' },
-  { object: array, name: '1', type: 'update', oldValue: 2 },
-  { object: array, name: '2', type: 'update', oldValue: 3 },
-
-  { object: array, name: '0', type: 'update', oldValue: 1 },
-  { object: array, name: '1', type: 'update', oldValue: 4 },
-  { object: array, name: '2', type: 'update', oldValue: 5 },
-  { object: array, name: '4', type: 'delete', oldValue: 3 },
-  { object: array, name: '3', type: 'delete', oldValue: 2 },
-  { object: array, name: 'length', type: 'update', oldValue: 5 },
-
-  { object: array, name: '1', type: 'update', oldValue: 2 },
-  { object: array, name: '2', type: 'update', oldValue: 3 },
-]);
-Object.deliverChangeRecords(observer2.callback);
-observer2.assertCallbackRecords([
-  { object: array, type: 'splice', index: 1, removed: [], addedCount: 2 },
-  { object: array, type: 'splice', index: 0, removed: [1, 4], addedCount: 0 },
-  { object: array, type: 'splice', index: 1, removed: [2, 3], addedCount: 2 },
-]);
-
-// Exercise StoreIC_ArrayLength
-reset();
-var dummy = {};
-Object.observe(dummy, observer.callback);
-Object.unobserve(dummy, observer.callback);
-var array = [0];
-Object.observe(array, observer.callback);
-array.splice(0, 1);
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: array, name: '0', type: 'delete', oldValue: 0 },
-  { object: array, name: 'length', type: 'update', oldValue: 1},
-]);
-
-
-// __proto__
-reset();
-var obj = {};
-Object.observe(obj, observer.callback);
-var p = {foo: 'yes'};
-var q = {bar: 'no'};
-obj.__proto__ = p;
-obj.__proto__ = p;  // ignored
-obj.__proto__ = null;
-obj.__proto__ = q;  // the __proto__ accessor is gone
-// TODO(adamk): Add tests for objects with hidden prototypes
-// once we support observing the global object.
-Object.deliverChangeRecords(observer.callback);
-observer.assertCallbackRecords([
-  { object: obj, name: '__proto__', type: 'setPrototype',
-    oldValue: Object.prototype },
-  { object: obj, name: '__proto__', type: 'setPrototype', oldValue: p },
-  { object: obj, name: '__proto__', type: 'add' },
-]);
-
-
-// Function.prototype
-reset();
-var fun = function(){};
-Object.observe(fun, observer.callback);
-var myproto = {foo: 'bar'};
-fun.prototype = myproto;
-fun.prototype = 7;
-fun.prototype = 7;  // ignored
-Object.defineProperty(fun, 'prototype', {value: 8});
-Object.deliverChangeRecords(observer.callback);
-observer.assertRecordCount(3);
-// Manually examine the first record in order to test
-// lazy creation of oldValue
-assertSame(fun, observer.records[0].object);
-assertEquals('prototype', observer.records[0].name);
-assertEquals('update', observer.records[0].type);
-// The only existing reference to the oldValue object is in this
-// record, so to test that lazy creation happened correctly
-// we compare its constructor to our function (one of the invariants
-// ensured when creating an object via AllocateFunctionPrototype).
-assertSame(fun, observer.records[0].oldValue.constructor);
-observer.records.splice(0, 1);
-observer.assertCallbackRecords([
-  { object: fun, name: 'prototype', type: 'update', oldValue: myproto },
-  { object: fun, name: 'prototype', type: 'update', oldValue: 7 },
-]);
-
-// Function.prototype should not be observable except on the object itself
-reset();
-var fun = function(){};
-var obj = { __proto__: fun };
-Object.observe(obj, observer.callback);
-obj.prototype = 7;
-Object.deliverChangeRecords(observer.callback);
-observer.assertRecordCount(1);
-observer.assertCallbackRecords([
-  { object: obj, name: 'prototype', type: 'add' },
-]);
-
-// Check that changes in observation status are detected in all IC states and
-// in optimized code, especially in cases usually using fast elements.
-var mutation = [
-  "a[i] = v",
-  "a[i] ? ++a[i] : a[i] = v",
-  "a[i] ? a[i]++ : a[i] = v",
-  "a[i] ? a[i] += 1 : a[i] = v",
-  "a[i] ? a[i] -= -1 : a[i] = v",
-];
-
-var props = [1, "1", "a"];
-
-function TestFastElements(prop, mutation, prepopulate, polymorphic, optimize) {
-  var setElement = eval(
-    "(function setElement(a, i, v) { " + mutation + "; " +
-    "/* " + [].join.call(arguments, " ") + " */" +
-    "})"
-  );
-  print("TestFastElements:", setElement);
-
-  var arr = prepopulate ? [1, 2, 3, 4, 5] : [0];
-  if (prepopulate) arr[prop] = 2;  // for non-element case
-  setElement(arr, prop, 3);
-  setElement(arr, prop, 4);
-  if (polymorphic) setElement(["M", "i", "l", "n", "e", "r"], 0, "m");
-  if (optimize) %OptimizeFunctionOnNextCall(setElement);
-  setElement(arr, prop, 5);
-
-  reset();
-  Object.observe(arr, observer.callback);
-  setElement(arr, prop, 989898);
-  Object.deliverChangeRecords(observer.callback);
-  observer.assertCallbackRecords([
-    { object: arr, name: "" + prop, type: 'update', oldValue: 5 }
-  ]);
-}
-
-for (var b1 = 0; b1 < 2; ++b1)
-  for (var b2 = 0; b2 < 2; ++b2)
-    for (var b3 = 0; b3 < 2; ++b3)
-      for (var i in props)
-        for (var j in mutation)
-          TestFastElements(props[i], mutation[j], b1 != 0, b2 != 0, b3 != 0);
-
-
-var mutation = [
-  "a.length = v",
-  "a.length += newSize - oldSize",
-  "a.length -= oldSize - newSize",
-];
-
-var mutationByIncr = [
-  "++a.length",
-  "a.length++",
-];
-
-function TestFastElementsLength(
-  mutation, polymorphic, optimize, oldSize, newSize) {
-  var setLength = eval(
-    "(function setLength(a, v) { " + mutation + "; " +
-    "/* " + [].join.call(arguments, " ") + " */"
-    + "})"
-  );
-  print("TestFastElementsLength:", setLength);
-
-  function array(n) {
-    var arr = new Array(n);
-    for (var i = 0; i < n; ++i) arr[i] = i;
-    return arr;
-  }
-
-  setLength(array(oldSize), newSize);
-  setLength(array(oldSize), newSize);
-  if (polymorphic) setLength(array(oldSize).map(isNaN), newSize);
-  if (optimize) %OptimizeFunctionOnNextCall(setLength);
-  setLength(array(oldSize), newSize);
-
-  reset();
-  var arr = array(oldSize);
-  Object.observe(arr, observer.callback);
-  setLength(arr, newSize);
-  Object.deliverChangeRecords(observer.callback);
-  if (oldSize === newSize) {
-    observer.assertNotCalled();
-  } else {
-    var count = oldSize > newSize ? oldSize - newSize : 0;
-    observer.assertRecordCount(count + 1);
-    var lengthRecord = observer.records[count];
-    assertSame(arr, lengthRecord.object);
-    assertEquals('length', lengthRecord.name);
-    assertEquals('update', lengthRecord.type);
-    assertSame(oldSize, lengthRecord.oldValue);
-  }
-}
-
-for (var b1 = 0; b1 < 2; ++b1)
-  for (var b2 = 0; b2 < 2; ++b2)
-    for (var n1 = 0; n1 < 3; ++n1)
-      for (var n2 = 0; n2 < 3; ++n2)
-        for (var i in mutation)
-          TestFastElementsLength(mutation[i], b1 != 0, b2 != 0, 20*n1, 20*n2);
-
-for (var b1 = 0; b1 < 2; ++b1)
-  for (var b2 = 0; b2 < 2; ++b2)
-    for (var n = 0; n < 3; ++n)
-      for (var i in mutationByIncr)
-        TestFastElementsLength(mutationByIncr[i], b1 != 0, b2 != 0, 7*n, 7*n+1);
-
-
-(function TestFunctionName() {
-  reset();
-
-  function fun() {}
-  Object.observe(fun, observer.callback);
-  fun.name = 'x';  // No change. Not writable.
-  Object.defineProperty(fun, 'name', {value: 'a'});
-  Object.defineProperty(fun, 'name', {writable: true});
-  fun.name = 'b';
-  delete fun.name;
-  fun.name = 'x';  // No change. Function.prototype.name is non writable
-  Object.defineProperty(Function.prototype, 'name', {writable: true});
-  fun.name = 'c';
-  fun.name = 'c';  // Same, no update.
-  Object.deliverChangeRecords(observer.callback);
-  observer.assertCallbackRecords([
-    { object: fun, type: 'update', name: 'name', oldValue: 'fun' },
-    { object: fun, type: 'reconfigure', name: 'name'},
-    { object: fun, type: 'update', name: 'name', oldValue: 'a' },
-    { object: fun, type: 'delete', name: 'name', oldValue: 'b' },
-    { object: fun, type: 'add', name: 'name' },
-  ]);
-})();
-
-
-(function TestFunctionLength() {
-  reset();
-
-  function fun(x) {}
-  Object.observe(fun, observer.callback);
-  fun.length = 'x';  // No change. Not writable.
-  Object.defineProperty(fun, 'length', {value: 'a'});
-  Object.defineProperty(fun, 'length', {writable: true});
-  fun.length = 'b';
-  delete fun.length;
-  fun.length = 'x';  // No change. Function.prototype.length is non writable
-  Object.defineProperty(Function.prototype, 'length', {writable: true});
-  fun.length = 'c';
-  fun.length = 'c';  // Same, no update.
-  Object.deliverChangeRecords(observer.callback);
-  observer.assertCallbackRecords([
-    { object: fun, type: 'update', name: 'length', oldValue: 1 },
-    { object: fun, type: 'reconfigure', name: 'length'},
-    { object: fun, type: 'update', name: 'length', oldValue: 'a' },
-    { object: fun, type: 'delete', name: 'length', oldValue: 'b' },
-    { object: fun, type: 'add', name: 'length' },
-  ]);
-})();
-
-
-(function TestObserveInvalidAcceptMessage() {
-  var ex;
-  try {
-    Object.observe({}, function(){}, "not an object");
-  } catch (e) {
-    ex = e;
-  }
-  assertInstanceof(ex, TypeError);
-  assertEquals("Third argument to Object.observe must be an array of strings.",
-               ex.message);
-})()
diff --git a/test/mjsunit/es7/regress/regress-443982.js b/test/mjsunit/es7/regress/regress-443982.js
deleted file mode 100644
index e04f14c..0000000
--- a/test/mjsunit/es7/regress/regress-443982.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Flags: --harmony-object-observe
-
-var records;
-function observer(r) {
-  records = r;
-}
-
-Object.defineProperty(Array.prototype, '0', {
-  get: function() { return 0; },
-  set: function() { throw "boom!"; }
-});
-arr = [1, 2];
-Array.observe(arr, observer);
-arr.length = 0;
-assertEquals(0, arr.length);
-
-Object.deliverChangeRecords(observer);
-assertEquals(1, records.length);
-assertEquals('splice', records[0].type);
-assertArrayEquals([1, 2], records[0].removed);
diff --git a/test/mjsunit/es8/syntactic-tail-call-parsing-sloppy.js b/test/mjsunit/es8/syntactic-tail-call-parsing-sloppy.js
new file mode 100644
index 0000000..d026086
--- /dev/null
+++ b/test/mjsunit/es8/syntactic-tail-call-parsing-sloppy.js
@@ -0,0 +1,410 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-explicit-tailcalls
+// Flags: --harmony-do-expressions
+
+var SyntaxErrorTests = [
+  { msg: "Unexpected expression inside tail call",
+    tests: [
+      { src: `()=>{ return continue  foo ; }`,
+        err: `                       ^^^`,
+      },
+      { src: `()=>{ return  continue 42 ; }`,
+        err: `                       ^^`,
+      },
+      { src: `()=>{ return  continue   new foo ()  ; }`,
+        err: `                         ^^^^^^^^^^`,
+      },
+      { src: `()=>{ loop: return  continue  loop ; }`,
+        err: `                              ^^^^`,
+      },
+      { src: `class A { foo() { return  continue   super.x ; } }`,
+        err: `                                     ^^^^^^^`,
+      },
+      { src: `()=>{ return  continue  this  ; }`,
+        err: `                        ^^^^`,
+      },
+      { src: `()=>{ return  continue class A {} ; }`,
+        err: `                       ^^^^^^^^^^`,
+      },
+      { src: `()=>{ return  continue class A extends B {} ; }`,
+        err: `                       ^^^^^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return  continue function A() { } ; }`,
+        err: `                       ^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return  continue { a: b, c: d} ; }`,
+        err: `                       ^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return  continue function* Gen() { yield 1; } ; }`,
+        err: `                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^`,
+      },
+      { src: `function A() { return  continue new.target ; }`,
+        err: `                                ^^^^^^^^^^`,
+      },
+      { src: `()=>{ return  continue () ; }`,
+        err: `                       ^^`,
+      },
+      { src: `()=>{ return  continue ( 42 ) ; }`,
+        err: `                       ^^^^^^`,
+      },
+      { src: "()=>{ return continue `123 ${foo} 34lk` ;  }",
+        err: `                      ^^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue do { x ? foo() : bar() ; } }`,
+        err: `                      ^^^^^^^^^^^^^^^^^^^^^^^^^^`,
+      },
+    ],
+  },
+  { msg: "Tail call expression is not allowed here",
+    tests: [
+      { src: `class A {}; class B extends A { constructor() { return continue foo () ; } }`,
+        err: `                                                       ^^^^^^^^^^^^^^^`,
+      },
+      { src: `class A extends continue f () {}; }`,
+        err: `                ^^^^^^^^^^^^^`,
+      },
+    ],
+  },
+  { msg: "Tail call expressions are not allowed in non-strict mode",
+    tests: [
+      { src: `()=>{ return  continue continue continue b()  ; }`,
+        err: `                                ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return  continue ( continue b() ) ; }`,
+        err: `                         ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return   continue  f()   - a ; }`,
+        err: `               ^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return b + continue   f()  ; }`,
+        err: `                 ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return 1, 2, 3,   continue  f() , 4  ; }`,
+        err: `                        ^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ var x =  continue  f ( ) ; }`,
+        err: `               ^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return   continue f () ? 1 : 2 ; }`,
+        err: `               ^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return (1, 2, 3, continue f()), 4; }`,
+        err: `                       ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return [1, 2, continue f() ] ;  }`,
+        err: `                    ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return [1, 2, ... continue f() ] ;  }`,
+        err: `                        ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return [1, 2, continue f(), 3 ] ;  }`,
+        err: `                    ^^^^^^^^^^^^`,
+      },
+      { src: "()=>{ return `123 ${a} ${ continue foo ( ) } 34lk` ;  }",
+        err: `                          ^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return g( 1, 2, continue f() ); }`,
+        err: `                      ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue f() || a; }`,
+        err: `             ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a || b || c || continue f() || d; }`,
+        err: `                            ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a && b && c && continue f() && d; }`,
+        err: `                            ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a && b || c && continue f() ? d : e; }`,
+        err: `                            ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a ? b : c && continue f() && d || e; }`,
+        err: `                          ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue foo() instanceof bar ; }`,
+        err: `             ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return bar instanceof continue foo() ; }`,
+        err: `                            ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue foo() in bar ; }`,
+        err: `             ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return bar in continue foo() ; }`,
+        err: `                    ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ function* G() { yield continue foo(); } }`,
+        err: `                            ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ (1, 2, 3, continue f() ) => {} }`,
+        err: `                ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ (... continue f()) => {}  }`,
+        err: `           ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ (a, b, c, ... continue f() ) => {}  }`,
+        err: `                    ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a <= continue f(); }`,
+        err: `                  ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return b > continue f(); }`,
+        err: `                 ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a << continue f(); }`,
+        err: `                  ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return b >> continue f(); }`,
+        err: `                  ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return c >>> continue f(); }`,
+        err: `                   ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue f() = a ; }`,
+        err: `             ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a = continue f() ; }`,
+        err: `                 ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a += continue f(); }`,
+        err: `                  ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a ** continue f() ; }`,
+        err: `                  ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return delete continue foo() ; }`,
+        err: `                    ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ typeof continue foo()  ; }`,
+        err: `             ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return ~ continue foo() ; }`,
+        err: `               ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return void  continue foo() ; }`,
+        err: `                   ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return !continue foo() ; }`,
+        err: `              ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return -continue foo() ; }`,
+        err: `              ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return +continue foo() ; }`,
+        err: `              ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return ++ continue f( ) ; }`,
+        err: `                ^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue f()  ++; }`,
+        err: `             ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue f() --; }`,
+        err: `             ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return (continue foo()) () ;  }`,
+        err: `              ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ for (var i = continue foo(); i < 10; i++) bar(); }`,
+        err: `                   ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ for (var i = 0; i < continue foo(); i++) bar(); }`,
+        err: `                          ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ for (var i = 0; i < 10; continue foo()) bar(); }`,
+        err: `                              ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ if (continue foo()) bar(); }`,
+        err: `          ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ while (continue foo()) bar(); }`,
+        err: `             ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ do { smth; } while (continue foo()) ; }`,
+        err: `                          ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ throw continue foo() ; }`,
+        err: `            ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ switch (continue foo()) { case 1: break; } ; }`,
+        err: `              ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ with (continue foo()) { smth; } }`,
+        err: `            ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ let x = continue foo() }`,
+        err: `              ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ const c = continue  foo() }`,
+        err: `                ^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ try { return  continue   f ( ) ; } catch(e) {} }`,
+        err: `                    ^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ try { try { smth; } catch(e) { return  continue  f( ) ; } }`,
+        err: `                                             ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ try { try { smth; } catch(e) { return  continue  f( ) ; } } finally { bla; } }`,
+        err: `                                             ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ try { smth; } catch(e) { return  continue   f ( ) ; } finally { blah; } }`,
+        err: `                                       ^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ try { smth; } catch(e) { try { smth; } catch (e) { return  continue   f ( ) ; } } finally { blah; } }`,
+        err: `                                                                 ^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ for (var v in {a:0}) { return continue  foo () ; } }`,
+        err: `                                    ^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ for (var v of [1, 2, 3]) { return continue  foo () ; } }`,
+        err: `                                        ^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue  a.b.c.foo () ; }`,
+        err: `             ^^^^^^^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue  a().b.c().d.foo () ; }`,
+        err: `             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue  foo (1)(2)(3, 4) ; }`,
+        err: `             ^^^^^^^^^^^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return ( continue b() ) ; }`,
+        err: `               ^^^^^^^^^^^^`,
+      },
+      { src: "()=>{ return continue bar`ab cd ef` ; }",
+        err: `             ^^^^^^^^^^^^^^^^^^^^^^`,
+      },
+      { src: "()=>{ return continue bar`ab ${cd} ef` ; }",
+        err: `             ^^^^^^^^^^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a || continue f() ; }`,
+        err: `                  ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a && continue f() ; }`,
+        err: `                  ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a , continue f() ; }`,
+        err: `                 ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ function* G() { return continue foo(); } }`,
+        err: `                             ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ function B() { return continue new.target() ; } }`,
+        err: `                            ^^^^^^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue do { x ? foo() : bar() ; }() }`,
+        err: `             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue (do { x ? foo() : bar() ; })() }`,
+        err: `             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return do { 1, continue foo() } }`,
+        err: `                     ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return do { x ? continue foo() : y } }`,
+        err: `                      ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a || (b && continue c()); }`,
+        err: `                        ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a && (b || continue c()); }`,
+        err: `                        ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a || (b ? c : continue d()); }`,
+        err: `                           ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return 1, 2, 3, a || (b ? c : continue d()); }`,
+        err: `                                    ^^^^^^^^^^^^`,
+      },
+      { src: `()=> continue  (foo ()) ;`,
+        err: `     ^^^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=> a || continue  foo () ;`,
+        err: `          ^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=> a && continue  foo () ;`,
+        err: `          ^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=> a ? continue  foo () : b;`,
+        err: `         ^^^^^^^^^^^^^^^^`,
+      },
+    ],
+  },
+  { msg: "Undefined label 'foo'",
+    tests: [
+      { src: `()=>{ continue  foo () ; }`,
+        err: `                ^^^`,
+      },
+    ],
+  },
+];
+
+
+// Should parse successfully.
+var NoErrorTests = [
+  `()=>{ class A { foo() { return continue super.f() ; } } }`,
+  `()=>{ class A { foo() { return continue f() ; } } }`,
+  `()=>{ class A { foo() { return a || continue f() ; } } }`,
+  `()=>{ class A { foo() { return b && continue f() ; } } }`,
+];
+
+
+(function() {
+  for (var test_set of SyntaxErrorTests) {
+    var expected_message = "SyntaxError: " + test_set.msg;
+    for (var test of test_set.tests) {
+      var passed = true;
+      var e = null;
+      try {
+        Realm.eval(0, test.src);
+      } catch (ee) {
+        e = ee;
+      }
+      print("=======================================");
+      print("Expected | " + expected_message);
+      print("Source   | " + test.src);
+      print("         | " + test.err);
+
+      if (e === null) {
+        print("FAILED");
+        throw new Error("SyntaxError was not thrown");
+      }
+
+      var details = %GetExceptionDetails(e);
+      if (details.start_pos == undefined ||
+          details.end_pos == undefined) {
+        throw new Error("Bad message object returned");
+      }
+      var underline = " ".repeat(details.start_pos) +
+                      "^".repeat(details.end_pos - details.start_pos);
+      var passed = expected_message === e.toString() &&
+                   test.err === underline;
+
+      if (passed) {
+        print("PASSED");
+        print();
+      } else {
+        print("---------------------------------------");
+        print("Actual   | " + e);
+        print("Source   | " + test.src);
+        print("         | " + underline);
+        print("FAILED");
+        throw new Error("Test failed");
+      }
+    }
+  }
+})();
+
+
+(function() {
+  for (var src of NoErrorTests) {
+    print("=======================================");
+    print("Source   | " + src);
+    Realm.eval(0, src);
+    print("PASSED");
+    print();
+  }
+})();
diff --git a/test/mjsunit/es8/syntactic-tail-call-parsing.js b/test/mjsunit/es8/syntactic-tail-call-parsing.js
new file mode 100644
index 0000000..486c3e1
--- /dev/null
+++ b/test/mjsunit/es8/syntactic-tail-call-parsing.js
@@ -0,0 +1,393 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-explicit-tailcalls
+// Flags: --harmony-do-expressions --harmony-async-await
+"use strict";
+
+var SyntaxErrorTests = [
+  { msg: "Unexpected expression inside tail call",
+    tests: [
+      { src: `()=>{ return continue  foo ; }`,
+        err: `                       ^^^`,
+      },
+      { src: `()=>{ return  continue 42 ; }`,
+        err: `                       ^^`,
+      },
+      { src: `()=>{ return  continue   new foo ()  ; }`,
+        err: `                         ^^^^^^^^^^`,
+      },
+      { src: `()=>{ loop: return  continue  loop ; }`,
+        err: `                              ^^^^`,
+      },
+      { src: `class A { foo() { return  continue   super.x ; } }`,
+        err: `                                     ^^^^^^^`,
+      },
+      { src: `()=>{ return  continue  this  ; }`,
+        err: `                        ^^^^`,
+      },
+      { src: `()=>{ return  continue class A {} ; }`,
+        err: `                       ^^^^^^^^^^`,
+      },
+      { src: `()=>{ return  continue class A extends B {} ; }`,
+        err: `                       ^^^^^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return  continue function A() { } ; }`,
+        err: `                       ^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return  continue { a: b, c: d} ; }`,
+        err: `                       ^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return  continue function* Gen() { yield 1; } ; }`,
+        err: `                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^`,
+      },
+      { src: `function A() { return  continue new.target ; }`,
+        err: `                                ^^^^^^^^^^`,
+      },
+      { src: `()=>{ return  continue () ; }`,
+        err: `                       ^^`,
+      },
+      { src: `()=>{ return  continue ( 42 ) ; }`,
+        err: `                       ^^^^^^`,
+      },
+      { src: "()=>{ return continue `123 ${foo} 34lk` ;  }",
+        err: `                      ^^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue do { x ? foo() : bar() ; } }`,
+        err: `                      ^^^^^^^^^^^^^^^^^^^^^^^^^^`,
+      },
+    ],
+  },
+  { msg: "Tail call expression is not allowed here",
+    tests: [
+      { src: `()=>{ return  continue continue continue b()  ; }`,
+        err: `                                ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return  continue ( continue b() ) ; }`,
+        err: `                         ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return   continue  f()   - a ; }`,
+        err: `               ^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return b + continue   f()  ; }`,
+        err: `                 ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return 1, 2, 3,   continue  f() , 4  ; }`,
+        err: `                        ^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ var x =  continue  f ( ) ; }`,
+        err: `               ^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return   continue f () ? 1 : 2 ; }`,
+        err: `               ^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return (1, 2, 3, continue f()), 4; }`,
+        err: `                       ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return [1, 2, continue f() ] ;  }`,
+        err: `                    ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return [1, 2, ... continue f() ] ;  }`,
+        err: `                        ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return [1, 2, continue f(), 3 ] ;  }`,
+        err: `                    ^^^^^^^^^^^^`,
+      },
+      { src: "()=>{ return `123 ${a} ${ continue foo ( ) } 34lk` ;  }",
+        err: `                          ^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return g( 1, 2, continue f() ); }`,
+        err: `                      ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue f() || a; }`,
+        err: `             ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a || b || c || continue f() || d; }`,
+        err: `                            ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a && b && c && continue f() && d; }`,
+        err: `                            ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a && b || c && continue f() ? d : e; }`,
+        err: `                            ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a ? b : c && continue f() && d || e; }`,
+        err: `                          ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue foo() instanceof bar ; }`,
+        err: `             ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return bar instanceof continue foo() ; }`,
+        err: `                            ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue foo() in bar ; }`,
+        err: `             ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return bar in continue foo() ; }`,
+        err: `                    ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ function* G() { yield continue foo(); } }`,
+        err: `                                     ^^^^^`,
+      },
+      { src: `()=>{ function* G() { return continue foo(); } }`,
+        err: `                                      ^^^^^`,
+      },
+      { src: `()=>{ (1, 2, 3, continue f() ) => {} }`,
+        err: `                ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ (... continue f()) => {}  }`,
+        err: `           ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ (a, b, c, ... continue f() ) => {}  }`,
+        err: `                    ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a <= continue f(); }`,
+        err: `                  ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return b > continue f(); }`,
+        err: `                 ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a << continue f(); }`,
+        err: `                  ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return b >> continue f(); }`,
+        err: `                  ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return c >>> continue f(); }`,
+        err: `                   ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue f() = a ; }`,
+        err: `             ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a = continue f() ; }`,
+        err: `                 ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a += continue f(); }`,
+        err: `                  ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return a ** continue f() ; }`,
+        err: `                  ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return delete continue foo() ; }`,
+        err: `                    ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ typeof continue foo()  ; }`,
+        err: `             ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return ~ continue foo() ; }`,
+        err: `               ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return void  continue foo() ; }`,
+        err: `                   ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return !continue foo() ; }`,
+        err: `              ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return -continue foo() ; }`,
+        err: `              ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return +continue foo() ; }`,
+        err: `              ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return ++ continue f( ) ; }`,
+        err: `                ^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue f()  ++; }`,
+        err: `             ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return continue f() --; }`,
+        err: `             ^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return (continue foo()) () ;  }`,
+        err: `              ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ for (var i = continue foo(); i < 10; i++) bar(); }`,
+        err: `                   ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ for (var i = 0; i < continue foo(); i++) bar(); }`,
+        err: `                          ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ for (var i = 0; i < 10; continue foo()) bar(); }`,
+        err: `                              ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ if (continue foo()) bar(); }`,
+        err: `          ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ while (continue foo()) bar(); }`,
+        err: `             ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ do { smth; } while (continue foo()) ; }`,
+        err: `                          ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ throw continue foo() ; }`,
+        err: `            ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ switch (continue foo()) { case 1: break; } ; }`,
+        err: `              ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ let x = continue foo() }`,
+        err: `              ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ const c = continue  foo() }`,
+        err: `                ^^^^^^^^^^^^^^^`,
+      },
+      { src: `class A {}; class B extends A { constructor() { return continue foo () ; } }`,
+        err: `                                                       ^^^^^^^^^^^^^^^`,
+      },
+      { src: `class A extends continue f () {}; }`,
+        err: `                ^^^^^^^^^^^^^`,
+      },
+      { src: `async() => continue foo()`,
+        err: `                    ^^^^^`,
+      },
+    ],
+  },
+  { msg: "Tail call expression in try block",
+    tests: [
+      { src: `()=>{ try { return  continue   f ( ) ; } catch(e) {} }`,
+        err: `                    ^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ try { try { smth; } catch(e) { return  continue  f( ) ; } }`,
+        err: `                                             ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ try { try { smth; } catch(e) { return  continue  f( ) ; } } finally { bla; } }`,
+        err: `                                             ^^^^^^^^^^^^^^`,
+      },
+    ],
+  },
+  { msg: "Tail call expression in catch block when finally block is also present",
+    tests: [
+      { src: `()=>{ try { smth; } catch(e) { return  continue   f ( ) ; } finally { blah; } }`,
+        err: `                                       ^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ try { smth; } catch(e) { try { smth; } catch (e) { return  continue   f ( ) ; } } finally { blah; } }`,
+        err: `                                                                 ^^^^^^^^^^^^^^^^`,
+      },
+    ],
+  },
+  { msg: "Tail call expression in for-in/of body",
+    tests: [
+      { src: `()=>{ for (var v in {a:0}) { return continue  foo () ; } }`,
+        err: `                                    ^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ for (var v of [1, 2, 3]) { return continue  foo () ; } }`,
+        err: `                                        ^^^^^^^^^^^^^^^^`,
+      },
+    ],
+  },
+  { msg: "Tail call of a direct eval is not allowed",
+    tests: [
+      { src: `()=>{ return  continue  eval(" foo () " )  ; }`,
+        err: `                        ^^^^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return  a || continue  eval("", 1, 2)  ; }`,
+        err: `                             ^^^^^^^^^^^^^^`,
+      },
+      { src: `()=>{ return  a, continue  eval  ( )  ; }`,
+        err: `                           ^^^^^^^^^`,
+      },
+      { src: `()=> a, continue  eval  ( )  ; `,
+        err: `                  ^^^^^^^^^`,
+      },
+      { src: `()=> a || continue  eval  (' ' )  ; `,
+        err: `                    ^^^^^^^^^^^^`,
+      },
+    ],
+  },
+  { msg: "Undefined label 'foo'",
+    tests: [
+      { src: `()=>{ continue  foo () ; }`,
+        err: `                ^^^`,
+      },
+    ],
+  },
+];
+
+
+// Should parse successfully.
+var NoErrorTests = [
+  `()=>{ return continue  a.b.c.foo () ; }`,
+  `()=>{ return continue  a().b.c().d.foo () ; }`,
+  `()=>{ return continue  foo (1)(2)(3, 4) ; }`,
+  `()=>{ return continue (0, eval)(); }`,
+  `()=>{ return ( continue b() ) ; }`,
+  "()=>{ return continue bar`ab cd ef` ; }",
+  "()=>{ return continue bar`ab ${cd} ef` ; }",
+  `()=>{ return a || continue f() ; }`,
+  `()=>{ return a && continue f() ; }`,
+  `()=>{ return a , continue f() ; }`,
+  `()=>{ class A { foo() { return continue super.f() ; } } }`,
+  `()=>{ function B() { return continue new.target() ; } }`,
+  `()=>{ return continue do { x ? foo() : bar() ; }() }`,
+  `()=>{ return continue (do { x ? foo() : bar() ; })() }`,
+  `()=>{ return do { 1, continue foo() } }`,
+  `()=>{ return do { x ? continue foo() : y } }`,
+  `()=>{ return a || (b && continue c()); }`,
+  `()=>{ return a && (b || continue c()); }`,
+  `()=>{ return a || (b ? c : continue d()); }`,
+  `()=>{ return 1, 2, 3, a || (b ? c : continue d()); }`,
+  `()=> continue  (foo ()) ;`,
+  `()=> a || continue  foo () ;`,
+  `()=> a && continue  foo () ;`,
+  `()=> a ? continue  foo () : b;`,
+];
+
+
+(function() {
+  for (var test_set of SyntaxErrorTests) {
+    var expected_message = "SyntaxError: " + test_set.msg;
+    for (var test of test_set.tests) {
+      var passed = true;
+      var e = null;
+      try {
+        eval(test.src);
+      } catch (ee) {
+        e = ee;
+      }
+      print("=======================================");
+      print("Expected | " + expected_message);
+      print("Source   | " + test.src);
+      print("         | " + test.err);
+
+      if (e === null) {
+        print("FAILED");
+        throw new Error("SyntaxError was not thrown");
+      }
+
+      var details = %GetExceptionDetails(e);
+      if (details.start_pos == undefined ||
+          details.end_pos == undefined) {
+        throw new Error("Bad message object returned");
+      }
+      var underline = " ".repeat(details.start_pos) +
+                      "^".repeat(details.end_pos - details.start_pos);
+      var passed = expected_message === e.toString() &&
+                   test.err === underline;
+
+      if (passed) {
+        print("PASSED");
+        print();
+      } else {
+        print("---------------------------------------");
+        print("Actual   | " + e);
+        print("Source   | " + test.src);
+        print("         | " + underline);
+        print("FAILED");
+        throw new Error("Test failed");
+      }
+    }
+  }
+})();
+
+
+(function() {
+  for (var src of NoErrorTests) {
+    print("=======================================");
+    print("Source   | " + src);
+    src = `"use strict"; ` + src;
+    Realm.eval(0, src);
+    print("PASSED");
+    print();
+  }
+})();
diff --git a/test/mjsunit/es8/syntactic-tail-call-simple.js b/test/mjsunit/es8/syntactic-tail-call-simple.js
new file mode 100644
index 0000000..ec7ade6
--- /dev/null
+++ b/test/mjsunit/es8/syntactic-tail-call-simple.js
@@ -0,0 +1,143 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-explicit-tailcalls --stack-size=100
+
+//
+// Tail calls work only in strict mode.
+//
+(function() {
+  function f(n) {
+    if (n <= 0) {
+      return "foo";
+    }
+    return f(n - 1);
+  }
+  assertThrows(()=>{ f(1e5) });
+  %OptimizeFunctionOnNextCall(f);
+  assertThrows(()=>{ f(1e5) });
+})();
+
+
+//
+// Tail call normal functions.
+//
+(function() {
+  "use strict";
+  function f(n) {
+    if (n <= 0) {
+      return "foo";
+    }
+    return continue f(n - 1);
+  }
+  assertEquals("foo", f(1e5));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals("foo", f(1e5));
+})();
+
+
+(function() {
+  "use strict";
+  function f(n) {
+    if (n <= 0) {
+      return  "foo";
+    }
+    return continue f(n - 1, 42);  // Call with arguments adaptor.
+  }
+  assertEquals("foo", f(1e5));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals("foo", f(1e5));
+})();
+
+
+(function() {
+  "use strict";
+  function f(n){
+    if (n <= 0) {
+      return "foo";
+    }
+    return continue g(n - 1);
+  }
+  function g(n){
+    if (n <= 0) {
+      return "bar";
+    }
+    return continue f(n - 1);
+  }
+  assertEquals("foo", f(1e5));
+  assertEquals("bar", f(1e5 + 1));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals("foo", f(1e5));
+  assertEquals("bar", f(1e5 + 1));
+})();
+
+
+(function() {
+  "use strict";
+  function f(n){
+    if (n <= 0) {
+      return "foo";
+    }
+    return continue g(n - 1, 42);  // Call with arguments adaptor.
+  }
+  function g(n){
+    if (n <= 0) {
+      return "bar";
+    }
+    return continue f(n - 1, 42);  // Call with arguments adaptor.
+  }
+  assertEquals("foo", f(1e5));
+  assertEquals("bar", f(1e5 + 1));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals("foo", f(1e5));
+  assertEquals("bar", f(1e5 + 1));
+})();
+
+
+//
+// Tail call bound functions.
+//
+(function() {
+  "use strict";
+  function f0(n) {
+    if (n <= 0) {
+      return "foo";
+    }
+    return continue f_bound(n - 1);
+  }
+  var f_bound = f0.bind({});
+  function f(n) {
+    return continue f_bound(n);
+  }
+  assertEquals("foo", f(1e5));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals("foo", f(1e5));
+})();
+
+
+(function() {
+  "use strict";
+  function f0(n){
+    if (n <= 0) {
+      return "foo";
+    }
+    return continue g_bound(n - 1);
+  }
+  function g0(n){
+    if (n <= 0) {
+      return "bar";
+    }
+    return continue f_bound(n - 1);
+  }
+  var f_bound = f0.bind({});
+  var g_bound = g0.bind({});
+  function f(n) {
+    return continue f_bound(n);
+  }
+  assertEquals("foo", f(1e5));
+  assertEquals("bar", f(1e5 + 1));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals("foo", f(1e5));
+  assertEquals("bar", f(1e5 + 1));
+})();
diff --git a/test/mjsunit/es8/syntactic-tail-call.js b/test/mjsunit/es8/syntactic-tail-call.js
new file mode 100644
index 0000000..44936a4
--- /dev/null
+++ b/test/mjsunit/es8/syntactic-tail-call.js
@@ -0,0 +1,604 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-explicit-tailcalls
+// Flags: --harmony-do-expressions
+
+"use strict";
+
+Error.prepareStackTrace = (error,stack) => {
+  error.strace = stack;
+  return error.message + "\n    at " + stack.join("\n    at ");
+}
+
+
+function CheckStackTrace(expected) {
+  var e = new Error();
+  e.stack;  // prepare stack trace
+  var stack = e.strace;
+  assertEquals("CheckStackTrace", stack[0].getFunctionName());
+  for (var i = 0; i < expected.length; i++) {
+    assertEquals(expected[i].name, stack[i + 1].getFunctionName());
+  }
+}
+%NeverOptimizeFunction(CheckStackTrace);
+
+
+function f(expected_call_stack, a, b) {
+  CheckStackTrace(expected_call_stack);
+  return a;
+}
+
+function f_153(expected_call_stack, a) {
+  CheckStackTrace(expected_call_stack);
+  return 153;
+}
+
+
+// Tail call when caller does not have an arguments adaptor frame.
+(function() {
+  // Caller and callee have same number of arguments.
+  function f1(a) {
+    CheckStackTrace([f1, test]);
+    return 10 + a;
+  }
+  function g1(a) { return continue f1(2); }
+
+  // Caller has more arguments than callee.
+  function f2(a) {
+    CheckStackTrace([f2, test]);
+    return 10 + a;
+  }
+  function g2(a, b, c) { return continue f2(2); }
+
+  // Caller has less arguments than callee.
+  function f3(a, b, c) {
+    CheckStackTrace([f3, test]);
+    return 10 + a + b + c;
+  }
+  function g3(a) { return continue f3(2, 3, 4); }
+
+  // Callee has arguments adaptor frame.
+  function f4(a, b, c) {
+    CheckStackTrace([f4, test]);
+    return 10 + a;
+  }
+  function g4(a) { return continue f4(2); }
+
+  function test() {
+    assertEquals(12, g1(1));
+    assertEquals(12, g2(1, 2, 3));
+    assertEquals(19, g3(1));
+    assertEquals(12, g4(1));
+  }
+  test();
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
+
+
+// Tail call when caller has an arguments adaptor frame.
+(function() {
+  // Caller and callee have same number of arguments.
+  function f1(a) {
+    CheckStackTrace([f1, test]);
+    return 10 + a;
+  }
+  function g1(a) { return continue f1(2); }
+
+  // Caller has more arguments than callee.
+  function f2(a) {
+    CheckStackTrace([f2, test]);
+    return 10 + a;
+  }
+  function g2(a, b, c) { return continue f2(2); }
+
+  // Caller has less arguments than callee.
+  function f3(a, b, c) {
+    CheckStackTrace([f3, test]);
+    return 10 + a + b + c;
+  }
+  function g3(a) { return continue f3(2, 3, 4); }
+
+  // Callee has arguments adaptor frame.
+  function f4(a, b, c) {
+    CheckStackTrace([f4, test]);
+    return 10 + a;
+  }
+  function g4(a) { return continue f4(2); }
+
+  function test() {
+    assertEquals(12, g1());
+    assertEquals(12, g2());
+    assertEquals(19, g3());
+    assertEquals(12, g4());
+  }
+  test();
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
+
+
+// Tail call bound function when caller does not have an arguments
+// adaptor frame.
+(function() {
+  // Caller and callee have same number of arguments.
+  function f1(a) {
+    assertEquals(153, this.a);
+    CheckStackTrace([f1, test]);
+    return 10 + a;
+  }
+  var b1 = f1.bind({a: 153});
+  function g1(a) { return continue b1(2); }
+
+  // Caller has more arguments than callee.
+  function f2(a) {
+    assertEquals(153, this.a);
+    CheckStackTrace([f2, test]);
+    return 10 + a;
+  }
+  var b2 = f2.bind({a: 153});
+  function g2(a, b, c) { return continue b2(2); }
+
+  // Caller has less arguments than callee.
+  function f3(a, b, c) {
+    assertEquals(153, this.a);
+    CheckStackTrace([f3, test]);
+    return 10 + a + b + c;
+  }
+  var b3 = f3.bind({a: 153});
+  function g3(a) { return continue b3(2, 3, 4); }
+
+  // Callee has arguments adaptor frame.
+  function f4(a, b, c) {
+    assertEquals(153, this.a);
+    CheckStackTrace([f4, test]);
+    return 10 + a;
+  }
+  var b4 = f4.bind({a: 153});
+  function g4(a) { return continue b4(2); }
+
+  function test() {
+    assertEquals(12, g1(1));
+    assertEquals(12, g2(1, 2, 3));
+    assertEquals(19, g3(1));
+    assertEquals(12, g4(1));
+  }
+  test();
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
+
+
+// Tail call bound function when caller has an arguments adaptor frame.
+(function() {
+  // Caller and callee have same number of arguments.
+  function f1(a) {
+    assertEquals(153, this.a);
+    CheckStackTrace([f1, test]);
+    return 10 + a;
+  }
+  var b1 = f1.bind({a: 153});
+  function g1(a) { return continue b1(2); }
+
+  // Caller has more arguments than callee.
+  function f2(a) {
+    assertEquals(153, this.a);
+    CheckStackTrace([f2, test]);
+    return 10 + a;
+  }
+  var b2 = f2.bind({a: 153});
+  function g2(a, b, c) { return continue b2(2); }
+
+  // Caller has less arguments than callee.
+  function f3(a, b, c) {
+    assertEquals(153, this.a);
+    CheckStackTrace([f3, test]);
+    return 10 + a + b + c;
+  }
+  var b3 = f3.bind({a: 153});
+  function g3(a) { return continue b3(2, 3, 4); }
+
+  // Callee has arguments adaptor frame.
+  function f4(a, b, c) {
+    assertEquals(153, this.a);
+    CheckStackTrace([f4, test]);
+    return 10 + a;
+  }
+  var b4 = f4.bind({a: 153});
+  function g4(a) { return continue b4(2); }
+
+  function test() {
+    assertEquals(12, g1());
+    assertEquals(12, g2());
+    assertEquals(19, g3());
+    assertEquals(12, g4());
+  }
+  test();
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
+
+
+// Tail calling from getter.
+(function() {
+  function g(v) {
+    CheckStackTrace([g, test]);
+    %DeoptimizeFunction(test);
+    return 153;
+  }
+  %NeverOptimizeFunction(g);
+
+  function f(v) {
+    return continue g();
+  }
+  %SetForceInlineFlag(f);
+
+  function test() {
+    var o = {};
+    o.__defineGetter__('p', f);
+    assertEquals(153, o.p);
+  }
+
+  test();
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
+
+
+// Tail calling from setter.
+(function() {
+  function g() {
+    CheckStackTrace([g, test]);
+    %DeoptimizeFunction(test);
+    return 153;
+  }
+  %NeverOptimizeFunction(g);
+
+  function f(v) {
+    return continue g();
+  }
+  %SetForceInlineFlag(f);
+
+  function test() {
+    var o = {};
+    o.__defineSetter__('q', f);
+    assertEquals(1, o.q = 1);
+  }
+
+  test();
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
+
+
+// Tail calling from constructor.
+(function() {
+  function g(context) {
+    CheckStackTrace([g, test]);
+    %DeoptimizeFunction(test);
+    return {x: 153};
+  }
+  %NeverOptimizeFunction(g);
+
+  function A() {
+    this.x = 42;
+    return continue g();
+  }
+
+  function test() {
+    var o = new A();
+    %DebugPrint(o);
+    assertEquals(153, o.x);
+  }
+
+  test();
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
+
+
+// Tail calling via various expressions.
+(function() {
+  function g1(a) {
+    return f([f, g1, test], false) || continue f([f, test], true);
+  }
+
+  function g2(a) {
+    return f([f, g2, test], true) && continue f([f, test], true);
+  }
+
+  function g3(a) {
+    return f([f, g3, test], 13), continue f([f, test], 153);
+  }
+
+  function g4(a) {
+    return f([f, g4, test], false) ||
+        (f([f, g4, test], true) && continue f([f, test], true));
+  }
+
+  function g5(a) {
+    return f([f, g5, test], true) &&
+        (f([f, g5, test], false) || continue f([f, test], true));
+  }
+
+  function g6(a) {
+    return f([f, g6, test], 13), f([f, g6, test], 42),
+        continue f([f, test], 153);
+  }
+
+  function g7(a) {
+    return f([f, g7, test], false) ||
+        (f([f, g7, test], false) ? continue f([f, test], true)
+             : continue f([f, test], true));
+  }
+
+  function g8(a) {
+    return f([f, g8, test], false) || f([f, g8, test], true) &&
+        continue f([f, test], true);
+  }
+
+  function g9(a) {
+    return f([f, g9, test], true) && f([f, g9, test], false) ||
+        continue f([f, test], true);
+  }
+
+  function g10(a) {
+    return f([f, g10, test], true) && f([f, g10, test], false) ||
+        f([f, g10, test], true) ?
+            f([f, g10, test], true) && f([f, g10, test], false) ||
+                continue f([f, test], true) :
+            f([f, g10, test], true) && f([f, g10, test], false) ||
+                continue f([f, test], true);
+  }
+
+  function test() {
+    assertEquals(true, g1());
+    assertEquals(true, g2());
+    assertEquals(153, g3());
+    assertEquals(true, g4());
+    assertEquals(true, g5());
+    assertEquals(153, g6());
+    assertEquals(true, g7());
+    assertEquals(true, g8());
+    assertEquals(true, g9());
+    assertEquals(true, g10());
+  }
+  test();
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
+
+
+// Tail calling from various statements.
+(function() {
+  function g3() {
+    for (var i = 0; i < 10; i++) {
+      return continue f_153([f_153, test]);
+    }
+  }
+
+  function g4() {
+    while (true) {
+      return continue f_153([f_153, test]);
+    }
+  }
+
+  function g5() {
+    do {
+      return continue f_153([f_153, test]);
+    } while (true);
+  }
+
+  function test() {
+    assertEquals(153, g3());
+    assertEquals(153, g4());
+    assertEquals(153, g5());
+  }
+  test();
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
+
+
+// Test tail calls from try-catch constructs.
+(function() {
+  function tc1(a) {
+    try {
+      f_153([f_153, tc1, test]);
+      return f_153([f_153, tc1, test]);
+    } catch(e) {
+      f_153([f_153, tc1, test]);
+    }
+  }
+
+  function tc2(a) {
+    try {
+      f_153([f_153, tc2, test]);
+      throw new Error("boom");
+    } catch(e) {
+      f_153([f_153, tc2, test]);
+      return continue f_153([f_153, test]);
+    }
+  }
+
+  function tc3(a) {
+    try {
+      f_153([f_153, tc3, test]);
+      throw new Error("boom");
+    } catch(e) {
+      f_153([f_153, tc3, test]);
+    }
+    f_153([f_153, tc3, test]);
+    return continue f_153([f_153, test]);
+  }
+
+  function test() {
+    assertEquals(153, tc1());
+    assertEquals(153, tc2());
+    assertEquals(153, tc3());
+  }
+  test();
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
+
+
+// Test tail calls from try-finally constructs.
+(function() {
+  function tf1(a) {
+    try {
+      f_153([f_153, tf1, test]);
+      return f_153([f_153, tf1, test]);
+    } finally {
+      f_153([f_153, tf1, test]);
+    }
+  }
+
+  function tf2(a) {
+    try {
+      f_153([f_153, tf2, test]);
+      throw new Error("boom");
+    } finally {
+      f_153([f_153, tf2, test]);
+      return continue f_153([f_153, test]);
+    }
+  }
+
+  function tf3(a) {
+    try {
+      f_153([f_153, tf3, test]);
+    } finally {
+      f_153([f_153, tf3, test]);
+    }
+    return continue f_153([f_153, test]);
+  }
+
+  function test() {
+    assertEquals(153, tf1());
+    assertEquals(153, tf2());
+    assertEquals(153, tf3());
+  }
+  test();
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
+
+
+// Test tail calls from try-catch-finally constructs.
+(function() {
+  function tcf1(a) {
+    try {
+      f_153([f_153, tcf1, test]);
+      return f_153([f_153, tcf1, test]);
+    } catch(e) {
+    } finally {
+      f_153([f_153, tcf1, test]);
+    }
+  }
+
+  function tcf2(a) {
+    try {
+      f_153([f_153, tcf2, test]);
+      throw new Error("boom");
+    } catch(e) {
+      f_153([f_153, tcf2, test]);
+      return f_153([f_153, tcf2, test]);
+    } finally {
+      f_153([f_153, tcf2, test]);
+    }
+  }
+
+  function tcf3(a) {
+    try {
+      f_153([f_153, tcf3, test]);
+      throw new Error("boom");
+    } catch(e) {
+      f_153([f_153, tcf3, test]);
+    } finally {
+      f_153([f_153, tcf3, test]);
+      return continue f_153([f_153, test]);
+    }
+  }
+
+  function tcf4(a) {
+    try {
+      f_153([f_153, tcf4, test]);
+      throw new Error("boom");
+    } catch(e) {
+      f_153([f_153, tcf4, test]);
+    } finally {
+      f_153([f_153, tcf4, test]);
+    }
+    return continue f_153([f_153, test]);
+  }
+
+  function test() {
+    assertEquals(153, tcf1());
+    assertEquals(153, tcf2());
+    assertEquals(153, tcf3());
+    assertEquals(153, tcf4());
+  }
+  test();
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
+
+
+// Test tail calls from arrow functions.
+(function () {
+  function g1(a) {
+    return continue (() => { return continue f_153([f_153, test]); })();
+  }
+
+  function g2(a) {
+    return continue (() => continue f_153([f_153, test]))();
+  }
+
+  function g3(a) {
+    var closure = () => f([f, closure, test], true)
+                              ? continue f_153([f_153, test])
+                              : continue f_153([f_153, test]);
+    return continue closure();
+  }
+
+  function test() {
+    assertEquals(153, g1());
+    assertEquals(153, g2());
+    assertEquals(153, g3());
+  }
+  test();
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
+
+
+// Test tail calls from do expressions.
+(function () {
+  function g1(a) {
+    var a = do { return continue f_153([f_153, test]); 42; };
+    return a;
+  }
+
+  function test() {
+    assertEquals(153, g1());
+  }
+  test();
+  test();
+  %OptimizeFunctionOnNextCall(test);
+  test();
+})();
diff --git a/test/mjsunit/eval-origin.js b/test/mjsunit/eval-origin.js
new file mode 100644
index 0000000..bb86ef3
--- /dev/null
+++ b/test/mjsunit/eval-origin.js
@@ -0,0 +1,39 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --nostress-opt
+
+Error.prepareStackTrace = function(exception, frames) {
+  return frames[0].getEvalOrigin();
+}
+
+var source = "new Error()";
+var eval_origin;
+var geval = eval;
+var log = [];
+
+(function() {
+  log.push([geval(source).stack, "17:13"]);
+  log.push([geval(source).stack, "18:13"]);
+  // log.push([geval(source).stack, "19:13"]);  TODO(4921).
+})();
+
+(function() {
+  log.push([eval(source).stack, "23:13"]);
+  log.push([eval(source).stack, "24:13"]);
+  // log.push([eval(source).stack, "25:13"]);  TODO(4921).
+})();
+
+log.push([eval(source).stack, "28:11"]);
+log.push([eval(source).stack, "29:11"]);
+// log.push([eval(source).stack, "30:11"]);  TODO(4921).
+
+Error.prepareStackTrace = undefined;
+
+for (var item of log) {
+  var stacktraceline = item[0];
+  var expectation = item[1];
+  var re = new RegExp(`:${expectation}\\)$`);
+  assertTrue(re.test(stacktraceline));
+}
diff --git a/test/mjsunit/fast-prototype.js b/test/mjsunit/fast-prototype.js
index 7432ecc..aa0a62e 100644
--- a/test/mjsunit/fast-prototype.js
+++ b/test/mjsunit/fast-prototype.js
@@ -46,14 +46,20 @@
 
 
 function DoProtoMagic(proto, set__proto__) {
+  var receiver;
   if (set__proto__) {
-    (new Sub()).__proto__ = proto;
+    receiver = new Sub();
+    receiver.__proto__ = proto;
   } else {
     Sub.prototype = proto;
     // Need to instantiate Sub to mark .prototype as prototype. Make sure the
     // instantiated object is used so that the allocation is not optimized away.
-    %DebugPrint(new Sub());
+    receiver = new Sub();
   }
+  // Prototypes are made fast when ICs encounter them.
+  function ic() { return typeof receiver.foo; }
+  ic();
+  ic();
 }
 
 
diff --git a/test/mjsunit/for-in.js b/test/mjsunit/for-in.js
index bece37a..547c748 100644
--- a/test/mjsunit/for-in.js
+++ b/test/mjsunit/for-in.js
@@ -25,6 +25,8 @@
 // (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: --noharmony-for-in
+
 function props(x) {
   var array = [];
   for (var p in x) array.push(p);
diff --git a/test/mjsunit/harmony/array-concat-array-proto-getter.js b/test/mjsunit/harmony/array-concat-array-proto-getter.js
new file mode 100644
index 0000000..9368e7f
--- /dev/null
+++ b/test/mjsunit/harmony/array-concat-array-proto-getter.js
@@ -0,0 +1,53 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Check that @@isConcatSpreadable is checked when set on Object.prototype
+
+"use strict"
+
+var array = [1, 2, 3];
+var object = {length: 1, '0': 'a'};
+
+function testConcatDefaults() {
+  assertEquals(array, [].concat(array));
+  assertEquals(array, array.concat([]));
+  assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+  assertEquals([object], [].concat(object));
+  assertEquals([1, 2, 3, object], array.concat(object));
+  assertEquals([object], Array.prototype.concat.call(object,[]));
+  assertEquals([object, 1, 2, 3], Array.prototype.concat.call(object, array));
+  assertEquals([object, object], Array.prototype.concat.call(object, object));
+}
+
+testConcatDefaults();
+
+var concatSpreadable = false;
+Object.defineProperty(Array.prototype, Symbol.isConcatSpreadable, {
+    get() { return concatSpreadable },
+    configurable: true
+});
+
+assertEquals([[], array], [].concat(array));
+assertEquals([array, []], array.concat([]));
+assertEquals([array, array], array.concat(array));
+assertEquals([[], object], [].concat(object));
+assertEquals([array, object], array.concat(object));
+assertEquals([object, []], Array.prototype.concat.call(object,[]));
+assertEquals([object, array], Array.prototype.concat.call(object, array));
+assertEquals([object, object], Array.prototype.concat.call(object, object));
+
+concatSpreadable = true;
+
+assertEquals(array, [].concat(array));
+assertEquals(array, array.concat([]));
+assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+assertEquals([object], [].concat(object));
+assertEquals([1, 2, 3, object], array.concat(object));
+assertEquals([object], Array.prototype.concat.call(object,[]));
+assertEquals([object, 1, 2, 3], Array.prototype.concat.call(object, array));
+assertEquals([object, object], Array.prototype.concat.call(object, object));
+
+
+delete Array.prototype[Symbol.isConcatSpreadable];
+testConcatDefaults();
diff --git a/test/mjsunit/harmony/array-concat-array-proto.js b/test/mjsunit/harmony/array-concat-array-proto.js
new file mode 100644
index 0000000..520178f
--- /dev/null
+++ b/test/mjsunit/harmony/array-concat-array-proto.js
@@ -0,0 +1,48 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Check that @@isConcatSpreadable is checked when set on Object.prototype
+
+"use strict"
+
+var array = [1, 2, 3];
+var object = {length: 1, '0': 'a'};
+
+function testConcatDefaults() {
+  assertEquals(array, [].concat(array));
+  assertEquals(array, array.concat([]));
+  assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+  assertEquals([object], [].concat(object));
+  assertEquals([1, 2, 3, object], array.concat(object));
+  assertEquals([object], Array.prototype.concat.call(object,[]));
+  assertEquals([object, 1, 2, 3], Array.prototype.concat.call(object, array));
+  assertEquals([object, object], Array.prototype.concat.call(object, object));
+}
+
+testConcatDefaults();
+
+Array.prototype[Symbol.isConcatSpreadable] = false;
+
+assertEquals([[], array], [].concat(array));
+assertEquals([array, []], array.concat([]));
+assertEquals([array, array], array.concat(array));
+assertEquals([[], object], [].concat(object));
+assertEquals([array, object], array.concat(object));
+assertEquals([object, []], Array.prototype.concat.call(object,[]));
+assertEquals([object, array], Array.prototype.concat.call(object, array));
+assertEquals([object, object], Array.prototype.concat.call(object, object));
+
+Array.prototype[Symbol.isConcatSpreadable] = true;
+
+assertEquals(array, [].concat(array));
+assertEquals(array, array.concat([]));
+assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+assertEquals([object], [].concat(object));
+assertEquals([1, 2, 3, object], array.concat(object));
+assertEquals([object], Array.prototype.concat.call(object,[]));
+assertEquals([object, 1, 2, 3], Array.prototype.concat.call(object, array));
+assertEquals([object, object], Array.prototype.concat.call(object, object));
+
+delete Array.prototype[Symbol.isConcatSpreadable];
+testConcatDefaults();
diff --git a/test/mjsunit/harmony/array-concat-object-proto-dict-getter.js b/test/mjsunit/harmony/array-concat-object-proto-dict-getter.js
new file mode 100644
index 0000000..6e61588
--- /dev/null
+++ b/test/mjsunit/harmony/array-concat-object-proto-dict-getter.js
@@ -0,0 +1,57 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Check that @@isConcatSpreadable is checked when set on Object.prototype
+// with a dictionary backing store.
+
+// Force Object.prototype into dictionary backing store by adding many
+// properties.
+for (var i = 0; i < 10*1000; i++) {
+  Object.prototype['generatedProperty'+i] = true;
+}
+
+var array = [1, 2, 3];
+var object = {length: 1, '0': 'a'};
+
+function testConcatDefaults() {
+  assertEquals(array, [].concat(array));
+  assertEquals(array, array.concat([]));
+  assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+  assertEquals([object], [].concat(object));
+  assertEquals([1, 2, 3, object], array.concat(object));
+  assertEquals([object], Array.prototype.concat.call(object,[]));
+  assertEquals([object, 1, 2, 3], Array.prototype.concat.call(object, array));
+  assertEquals([object, object], Array.prototype.concat.call(object, object));
+}
+
+testConcatDefaults();
+
+var concatSpreadable = false;
+Object.defineProperty(Object.prototype, Symbol.isConcatSpreadable, {
+  get() { return concatSpreadable },
+  configurable: true
+});
+
+assertEquals([[], array], [].concat(array));
+assertEquals([array, []], array.concat([]));
+assertEquals([array, array], array.concat(array));
+assertEquals([[], object], [].concat(object));
+assertEquals([array, object], array.concat(object));
+assertEquals([object, []], Array.prototype.concat.call(object,[]));
+assertEquals([object, array], Array.prototype.concat.call(object, array));
+assertEquals([object, object], Array.prototype.concat.call(object, object));
+
+concatSpreadable = true;
+
+assertEquals(array, [].concat(array));
+assertEquals(array, array.concat([]));
+assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+assertEquals(['a'], [].concat(object));
+assertEquals([1, 2, 3, 'a'], array.concat(object));
+assertEquals(['a'], Array.prototype.concat.call(object,[]));
+assertEquals(['a', 1, 2, 3], Array.prototype.concat.call(object, array));
+assertEquals(['a', 'a'], Array.prototype.concat.call(object, object));
+
+delete Object.prototype[Symbol.isConcatSpreadable];
+testConcatDefaults();
diff --git a/test/mjsunit/harmony/array-concat-object-proto-dict.js b/test/mjsunit/harmony/array-concat-object-proto-dict.js
new file mode 100644
index 0000000..c817006
--- /dev/null
+++ b/test/mjsunit/harmony/array-concat-object-proto-dict.js
@@ -0,0 +1,53 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Check that @@isConcatSpreadable is checked when set on Object.prototype
+// with a dictionary backing store.
+
+// Force Object.prototype into dictionary backing store by adding many
+// properties.
+for (var i = 0; i < 10*1000; i++) {
+  Object.prototype['generatedProperty'+i] = true;
+}
+
+var array = [1, 2, 3];
+var object = {length: 1, '0': 'a'};
+
+function testConcatDefaults() {
+  assertEquals(array, [].concat(array));
+  assertEquals(array, array.concat([]));
+  assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+  assertEquals([object], [].concat(object));
+  assertEquals([1, 2, 3, object], array.concat(object));
+  assertEquals([object], Array.prototype.concat.call(object,[]));
+  assertEquals([object, 1, 2, 3], Array.prototype.concat.call(object, array));
+  assertEquals([object, object], Array.prototype.concat.call(object, object));
+}
+
+testConcatDefaults();
+
+Object.prototype[Symbol.isConcatSpreadable] = false;
+
+assertEquals([[], array], [].concat(array));
+assertEquals([array, []], array.concat([]));
+assertEquals([array, array], array.concat(array));
+assertEquals([[], object], [].concat(object));
+assertEquals([array, object], array.concat(object));
+assertEquals([object, []], Array.prototype.concat.call(object,[]));
+assertEquals([object, array], Array.prototype.concat.call(object, array));
+assertEquals([object, object], Array.prototype.concat.call(object, object));
+
+Object.prototype[Symbol.isConcatSpreadable] = true;
+
+assertEquals(array, [].concat(array));
+assertEquals(array, array.concat([]));
+assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+assertEquals(['a'], [].concat(object));
+assertEquals([1, 2, 3, 'a'], array.concat(object));
+assertEquals(['a'], Array.prototype.concat.call(object,[]));
+assertEquals(['a', 1, 2, 3], Array.prototype.concat.call(object, array));
+assertEquals(['a', 'a'], Array.prototype.concat.call(object, object));
+
+delete Object.prototype[Symbol.isConcatSpreadable];
+testConcatDefaults();
diff --git a/test/mjsunit/harmony/array-concat-object-proto-generic-dict.js b/test/mjsunit/harmony/array-concat-object-proto-generic-dict.js
new file mode 100644
index 0000000..7b61422
--- /dev/null
+++ b/test/mjsunit/harmony/array-concat-object-proto-generic-dict.js
@@ -0,0 +1,65 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Check that @@isConcatSpreadable is checked when set on Object.prototype
+// with a dictionary backing store.
+
+// Force Object.prototype into dictionary backing store by adding many
+// properties.
+for (var i = 0; i < 10*1000; i++) {
+  Object.prototype['generatedProperty'+i] = true;
+}
+
+var array = [1, 2, 3];
+var object = {length: 1, '0': 'a'};
+
+function SetProperty(receiver, key, value) {
+  receiver[key] = value;
+}
+
+// Force the Keyed Store IC in SetProperty to be generic.
+var receiver = {};
+for (var i = 0; i < 100; i++) {
+  SetProperty(receiver, 'prop'+i, 'value');
+}
+
+function testConcatDefaults() {
+  assertEquals(array, [].concat(array));
+  assertEquals(array, array.concat([]));
+  assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+  assertEquals([object], [].concat(object));
+  assertEquals([1, 2, 3, object], array.concat(object));
+  assertEquals([object], Array.prototype.concat.call(object,[]));
+  assertEquals([object, 1, 2, 3], Array.prototype.concat.call(object, array));
+  assertEquals([object, object], Array.prototype.concat.call(object, object));
+}
+
+testConcatDefaults();
+
+// Use a generic IC to set @@isConcatSpreadable
+SetProperty(Object.prototype, Symbol.isConcatSpreadable, false);
+
+assertEquals([[], array], [].concat(array));
+assertEquals([array, []], array.concat([]));
+assertEquals([array, array], array.concat(array));
+assertEquals([[], object], [].concat(object));
+assertEquals([array, object], array.concat(object));
+assertEquals([object, []], Array.prototype.concat.call(object,[]));
+assertEquals([object, array], Array.prototype.concat.call(object, array));
+assertEquals([object, object], Array.prototype.concat.call(object, object));
+
+// Use a generic IC to set @@isConcatSpreadable
+SetProperty(Object.prototype, Symbol.isConcatSpreadable, true);
+
+assertEquals(array, [].concat(array));
+assertEquals(array, array.concat([]));
+assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+assertEquals(['a'], [].concat(object));
+assertEquals([1, 2, 3, 'a'], array.concat(object));
+assertEquals(['a'], Array.prototype.concat.call(object,[]));
+assertEquals(['a', 1, 2, 3], Array.prototype.concat.call(object, array));
+assertEquals(['a', 'a'], Array.prototype.concat.call(object, object));
+
+delete Object.prototype[Symbol.isConcatSpreadable];
+testConcatDefaults();
diff --git a/test/mjsunit/harmony/array-concat-object-proto.js b/test/mjsunit/harmony/array-concat-object-proto.js
new file mode 100644
index 0000000..307326c
--- /dev/null
+++ b/test/mjsunit/harmony/array-concat-object-proto.js
@@ -0,0 +1,48 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Check that @@isConcatSpreadable is checked when set on Object.prototype
+
+"use strict"
+
+var array = [1, 2, 3];
+var object = {length: 1, '0': 'a'};
+
+function testConcatDefaults() {
+  assertEquals(array, [].concat(array));
+  assertEquals(array, array.concat([]));
+  assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+  assertEquals([object], [].concat(object));
+  assertEquals([1, 2, 3, object], array.concat(object));
+  assertEquals([object], Array.prototype.concat.call(object,[]));
+  assertEquals([object, 1, 2, 3], Array.prototype.concat.call(object, array));
+  assertEquals([object, object], Array.prototype.concat.call(object, object));
+}
+
+testConcatDefaults();
+
+Object.prototype[Symbol.isConcatSpreadable] = false;
+
+assertEquals([[], array], [].concat(array));
+assertEquals([array, []], array.concat([]));
+assertEquals([array, array], array.concat(array));
+assertEquals([[], object], [].concat(object));
+assertEquals([array, object], array.concat(object));
+assertEquals([object, []], Array.prototype.concat.call(object,[]));
+assertEquals([object, array], Array.prototype.concat.call(object, array));
+assertEquals([object, object], Array.prototype.concat.call(object, object));
+
+Object.prototype[Symbol.isConcatSpreadable] = true;
+
+assertEquals(array, [].concat(array));
+assertEquals(array, array.concat([]));
+assertEquals([1, 2, 3, 1, 2, 3], array.concat(array));
+assertEquals(['a'], [].concat(object));
+assertEquals([1, 2, 3, 'a'], array.concat(object));
+assertEquals(['a'], Array.prototype.concat.call(object,[]));
+assertEquals(['a', 1, 2, 3], Array.prototype.concat.call(object, array));
+assertEquals(['a', 'a'], Array.prototype.concat.call(object, object));
+
+delete Object.prototype[Symbol.isConcatSpreadable];
+testConcatDefaults();
diff --git a/test/mjsunit/harmony/array-species-constructor-accessor.js b/test/mjsunit/harmony/array-species-constructor-accessor.js
deleted file mode 100644
index 4c852f0..0000000
--- a/test/mjsunit/harmony/array-species-constructor-accessor.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-species --allow-natives-syntax
-
-// Overwriting the constructor of an instance updates the protector
-
-let x = [];
-
-assertEquals(Array, x.map(()=>{}).constructor);
-assertEquals(Array, x.filter(()=>{}).constructor);
-assertEquals(Array, x.slice().constructor);
-assertEquals(Array, x.splice().constructor);
-assertEquals(Array, x.concat([1]).constructor);
-assertEquals(1, x.concat([1])[0]);
-
-class MyArray extends Array { }
-
-Object.defineProperty(x, 'constructor', {get() { return MyArray; }});
-assertFalse(%SpeciesProtector());
-
-assertEquals(MyArray, x.map(()=>{}).constructor);
-assertEquals(MyArray, x.filter(()=>{}).constructor);
-assertEquals(MyArray, x.slice().constructor);
-assertEquals(MyArray, x.splice().constructor);
-assertEquals(MyArray, x.concat([1]).constructor);
-assertEquals(1, x.concat([1])[0]);
diff --git a/test/mjsunit/harmony/array-species-constructor-delete.js b/test/mjsunit/harmony/array-species-constructor-delete.js
deleted file mode 100644
index f341282..0000000
--- a/test/mjsunit/harmony/array-species-constructor-delete.js
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-species --allow-natives-syntax
-
-// Overwriting the constructor of an instance updates the protector
-
-let x = [];
-
-assertEquals(Array, x.map(()=>{}).constructor);
-assertEquals(Array, x.filter(()=>{}).constructor);
-assertEquals(Array, x.slice().constructor);
-assertEquals(Array, x.splice().constructor);
-assertEquals(Array, x.concat([1]).constructor);
-assertEquals(1, x.concat([1])[0]);
-
-class MyArray extends Array { }
-
-Object.prototype.constructor = MyArray;
-delete Array.prototype.constructor;
-assertFalse(%SpeciesProtector());
-
-assertEquals(MyArray, x.map(()=>{}).constructor);
-assertEquals(MyArray, x.filter(()=>{}).constructor);
-assertEquals(MyArray, x.slice().constructor);
-assertEquals(MyArray, x.splice().constructor);
-assertEquals(MyArray, x.concat([1]).constructor);
-assertEquals(1, x.concat([1])[0]);
diff --git a/test/mjsunit/harmony/array-species-constructor.js b/test/mjsunit/harmony/array-species-constructor.js
deleted file mode 100644
index d766e09..0000000
--- a/test/mjsunit/harmony/array-species-constructor.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-species --allow-natives-syntax
-
-// Overwriting the constructor of an instance updates the protector
-
-let x = [];
-
-assertEquals(Array, x.map(()=>{}).constructor);
-assertEquals(Array, x.filter(()=>{}).constructor);
-assertEquals(Array, x.slice().constructor);
-assertEquals(Array, x.splice().constructor);
-assertEquals(Array, x.concat([1]).constructor);
-assertEquals(1, x.concat([1])[0]);
-
-class MyArray extends Array { }
-
-x.constructor = MyArray;
-assertFalse(%SpeciesProtector());
-
-assertEquals(MyArray, x.map(()=>{}).constructor);
-assertEquals(MyArray, x.filter(()=>{}).constructor);
-assertEquals(MyArray, x.slice().constructor);
-assertEquals(MyArray, x.splice().constructor);
-assertEquals(MyArray, x.concat([1]).constructor);
-assertEquals(1, x.concat([1])[0]);
diff --git a/test/mjsunit/harmony/array-species-delete.js b/test/mjsunit/harmony/array-species-delete.js
deleted file mode 100644
index ba49414..0000000
--- a/test/mjsunit/harmony/array-species-delete.js
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-species --allow-natives-syntax
-
-// Overwriting the constructor of an instance updates the protector
-
-let x = [];
-
-assertEquals(Array, x.map(()=>{}).constructor);
-assertEquals(Array, x.filter(()=>{}).constructor);
-assertEquals(Array, x.slice().constructor);
-assertEquals(Array, x.splice().constructor);
-assertEquals(Array, x.concat([1]).constructor);
-assertEquals(1, x.concat([1])[0]);
-
-class MyArray extends Array { }
-
-Object.prototype[Symbol.species] = MyArray;
-delete Array[Symbol.species];
-assertFalse(%SpeciesProtector());
-
-assertEquals(MyArray, x.map(()=>{}).constructor);
-assertEquals(MyArray, x.filter(()=>{}).constructor);
-assertEquals(MyArray, x.slice().constructor);
-assertEquals(MyArray, x.splice().constructor);
-assertEquals(MyArray, x.concat([1]).constructor);
-assertEquals(1, x.concat([1])[0]);
diff --git a/test/mjsunit/harmony/array-species-modified.js b/test/mjsunit/harmony/array-species-modified.js
deleted file mode 100644
index 73c52b9..0000000
--- a/test/mjsunit/harmony/array-species-modified.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-species --allow-natives-syntax
-
-// Overwriting Array[Symbol.species] updates the protector
-
-let x = [];
-
-assertEquals(Array, x.map(()=>{}).constructor);
-assertEquals(Array, x.filter(()=>{}).constructor);
-assertEquals(Array, x.slice().constructor);
-assertEquals(Array, x.splice().constructor);
-assertEquals(Array, x.concat([1]).constructor);
-assertEquals(1, x.concat([1])[0]);
-
-class MyArray extends Array { }
-
-Object.defineProperty(Array, Symbol.species, {value: MyArray});
-assertFalse(%SpeciesProtector());
-
-assertEquals(MyArray, x.map(()=>{}).constructor);
-assertEquals(MyArray, x.filter(()=>{}).constructor);
-assertEquals(MyArray, x.slice().constructor);
-assertEquals(MyArray, x.splice().constructor);
-assertEquals(MyArray, x.concat([1]).constructor);
-assertEquals(1, x.concat([1])[0]);
diff --git a/test/mjsunit/harmony/array-species-parent-constructor.js b/test/mjsunit/harmony/array-species-parent-constructor.js
deleted file mode 100644
index 347732e..0000000
--- a/test/mjsunit/harmony/array-species-parent-constructor.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-species --allow-natives-syntax
-
-// Overwriting Array.prototype.constructor updates the protector
-
-let x = [];
-
-assertEquals(Array, x.map(()=>{}).constructor);
-assertEquals(Array, x.filter(()=>{}).constructor);
-assertEquals(Array, x.slice().constructor);
-assertEquals(Array, x.splice().constructor);
-assertEquals(Array, x.concat([1]).constructor);
-assertEquals(1, x.concat([1])[0]);
-
-class MyArray extends Array { }
-
-Array.prototype.constructor = MyArray;
-assertFalse(%SpeciesProtector());
-
-assertEquals(MyArray, x.map(()=>{}).constructor);
-assertEquals(MyArray, x.filter(()=>{}).constructor);
-assertEquals(MyArray, x.slice().constructor);
-assertEquals(MyArray, x.splice().constructor);
-assertEquals(MyArray, x.concat([1]).constructor);
-assertEquals(1, x.concat([1])[0]);
diff --git a/test/mjsunit/harmony/array-species-proto.js b/test/mjsunit/harmony/array-species-proto.js
deleted file mode 100644
index 70db751..0000000
--- a/test/mjsunit/harmony/array-species-proto.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-species --allow-natives-syntax
-
-// Overwriting an array instance's __proto__ updates the protector
-
-let x = [];
-
-assertEquals(Array, x.map(()=>{}).constructor);
-assertEquals(Array, x.filter(()=>{}).constructor);
-assertEquals(Array, x.slice().constructor);
-assertEquals(Array, x.splice().constructor);
-assertEquals(Array, x.concat([1]).constructor);
-assertEquals(1, x.concat([1])[0]);
-
-class MyArray extends Array { }
-
-x.__proto__ = MyArray.prototype;
-assertTrue(%SpeciesProtector());
-
-assertEquals(MyArray, x.map(()=>{}).constructor);
-assertEquals(MyArray, x.filter(()=>{}).constructor);
-assertEquals(MyArray, x.slice().constructor);
-assertEquals(MyArray, x.splice().constructor);
-assertEquals(MyArray, x.concat([1]).constructor);
-assertEquals(1, x.concat([1])[0]);
diff --git a/test/mjsunit/harmony/array-species.js b/test/mjsunit/harmony/array-species.js
deleted file mode 100644
index 19ed1d8..0000000
--- a/test/mjsunit/harmony/array-species.js
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-species
-
-// Test the ES2015 @@species feature
-
-'use strict';
-
-// Subclasses of Array construct themselves under map, etc
-
-class MyArray extends Array { }
-
-assertEquals(MyArray, new MyArray().map(()=>{}).constructor);
-assertEquals(MyArray, new MyArray().filter(()=>{}).constructor);
-assertEquals(MyArray, new MyArray().slice().constructor);
-assertEquals(MyArray, new MyArray().splice().constructor);
-assertEquals(MyArray, new MyArray().concat([1]).constructor);
-assertEquals(1, new MyArray().concat([1])[0]);
-
-// Subclasses can override @@species to return the another class
-
-class MyOtherArray extends Array {
-  static get [Symbol.species]() { return MyArray; }
-}
-
-assertEquals(MyArray, new MyOtherArray().map(()=>{}).constructor);
-assertEquals(MyArray, new MyOtherArray().filter(()=>{}).constructor);
-assertEquals(MyArray, new MyOtherArray().slice().constructor);
-assertEquals(MyArray, new MyOtherArray().splice().constructor);
-assertEquals(MyArray, new MyOtherArray().concat().constructor);
-
-// Array  methods on non-arrays return arrays
-
-class MyNonArray extends Array {
-  static get [Symbol.species]() { return MyObject; }
-}
-
-class MyObject { }
-
-assertEquals(MyObject,
-             Array.prototype.map.call(new MyNonArray(), ()=>{}).constructor);
-assertEquals(MyObject,
-             Array.prototype.filter.call(new MyNonArray(), ()=>{}).constructor);
-assertEquals(MyObject,
-             Array.prototype.slice.call(new MyNonArray()).constructor);
-assertEquals(MyObject,
-             Array.prototype.splice.call(new MyNonArray()).constructor);
-assertEquals(MyObject,
-             Array.prototype.concat.call(new MyNonArray()).constructor);
-
-assertEquals(undefined,
-             Array.prototype.map.call(new MyNonArray(), ()=>{}).length);
-assertEquals(undefined,
-             Array.prototype.filter.call(new MyNonArray(), ()=>{}).length);
-assertEquals(undefined,
-             Array.prototype.concat.call(new MyNonArray(), ()=>{}).length);
-// slice and splice actually do explicitly define the length for some reason
-assertEquals(0, Array.prototype.slice.call(new MyNonArray()).length);
-assertEquals(0, Array.prototype.splice.call(new MyNonArray()).length);
-
-// Cross-realm Arrays build same-realm arrays
-
-var realm = Realm.create();
-assertEquals(Array,
-             Array.prototype.map.call(
-                 Realm.eval(realm, "[]"), ()=>{}).constructor);
-assertFalse(Array === Realm.eval(realm, "[]").map(()=>{}).constructor);
-assertFalse(Array === Realm.eval(realm, "[].map(()=>{}).constructor"));
-assertEquals(Array,
-             Array.prototype.concat.call(
-                 Realm.eval(realm, "[]")).constructor);
-
-// Defaults when constructor or @@species is missing or non-constructor
-
-class MyDefaultArray extends Array {
-  static get [Symbol.species]() { return undefined; }
-}
-assertEquals(Array, new MyDefaultArray().map(()=>{}).constructor);
-
-class MyOtherDefaultArray extends Array { }
-assertEquals(MyOtherDefaultArray,
-             new MyOtherDefaultArray().map(()=>{}).constructor);
-MyOtherDefaultArray.prototype.constructor = undefined;
-assertEquals(Array, new MyOtherDefaultArray().map(()=>{}).constructor);
-assertEquals(Array, new MyOtherDefaultArray().concat().constructor);
-
-// Exceptions propagated when getting constructor @@species throws
-
-class SpeciesError extends Error { }
-class ConstructorError extends Error { }
-class MyThrowingArray extends Array {
-  static get [Symbol.species]() { throw new SpeciesError; }
-}
-assertThrows(() => new MyThrowingArray().map(()=>{}), SpeciesError);
-Object.defineProperty(MyThrowingArray.prototype, 'constructor', {
-    get() { throw new ConstructorError; }
-});
-assertThrows(() => new MyThrowingArray().map(()=>{}), ConstructorError);
-
-// Previously unexpected errors from setting properties in arrays throw
-
-class FrozenArray extends Array {
-  constructor(...args) {
-    super(...args);
-    Object.freeze(this);
-  }
-}
-assertThrows(() => new FrozenArray([1]).map(()=>0), TypeError);
-assertThrows(() => new FrozenArray([1]).filter(()=>true), TypeError);
-assertThrows(() => new FrozenArray([1]).slice(0, 1), TypeError);
-assertThrows(() => new FrozenArray([1]).splice(0, 1), TypeError);
-assertThrows(() => new FrozenArray([]).concat([1]), TypeError);
-
-// Verify call counts and constructor parameters
-
-var count;
-var params;
-class MyObservedArray extends Array {
-  constructor(...args) {
-    super(...args);
-    params = args;
-  }
-  static get [Symbol.species]() {
-    count++
-    return this;
-  }
-}
-
-count = 0;
-params = undefined;
-assertEquals(MyObservedArray,
-             new MyObservedArray().map(()=>{}).constructor);
-assertEquals(1, count);
-assertArrayEquals([0], params);
-
-count = 0;
-params = undefined;
-assertEquals(MyObservedArray,
-             new MyObservedArray().filter(()=>{}).constructor);
-assertEquals(1, count);
-assertArrayEquals([0], params);
-
-count = 0;
-params = undefined;
-assertEquals(MyObservedArray,
-             new MyObservedArray().concat().constructor);
-assertEquals(1, count);
-assertArrayEquals([0], params);
-
-count = 0;
-params = undefined;
-assertEquals(MyObservedArray,
-             new MyObservedArray().slice().constructor);
-assertEquals(1, count);
-assertArrayEquals([0], params);
-
-count = 0;
-params = undefined;
-assertEquals(MyObservedArray,
-             new MyObservedArray().splice().constructor);
-assertEquals(1, count);
-assertArrayEquals([0], params);
-
-// @@species constructor can be a Proxy, and the realm access doesn't
-// crash
-
-class MyProxyArray extends Array { }
-let ProxyArray = new Proxy(MyProxyArray, {});
-MyProxyArray.constructor = ProxyArray;
-
-assertEquals(MyProxyArray, new ProxyArray().map(()=>{}).constructor);
diff --git a/test/mjsunit/harmony/arraybuffer-species.js b/test/mjsunit/harmony/arraybuffer-species.js
deleted file mode 100644
index 0445a4b..0000000
--- a/test/mjsunit/harmony/arraybuffer-species.js
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-species
-
-// ArrayBuffer.prototype.slice makes subclass and checks length
-
-class MyArrayBuffer extends ArrayBuffer { }
-assertEquals(MyArrayBuffer, new MyArrayBuffer(0).slice().constructor);
-
-class MyShortArrayBuffer extends ArrayBuffer {
-  constructor(length) { super(length - 1); }
-}
-assertThrows(() => new MyShortArrayBuffer(5).slice(0, 4), TypeError);
-
-class SingletonArrayBuffer extends ArrayBuffer {
-  constructor(...args) {
-    if (SingletonArrayBuffer.cached) return SingletonArrayBuffer.cached;
-    super(...args);
-    SingletonArrayBuffer.cached = this;
-  }
-}
-assertThrows(() => new SingletonArrayBuffer(5).slice(0, 4), TypeError);
-
-class NonArrayBuffer extends ArrayBuffer {
-  constructor() {
-    return {};
-  }
-}
-assertThrows(() => new NonArrayBuffer(5).slice(0, 4), TypeError);
-
-// Species fallback is ArrayBuffer
-class UndefinedArrayBuffer extends ArrayBuffer { }
-UndefinedArrayBuffer.prototype.constructor = undefined;
-assertEquals(ArrayBuffer, new UndefinedArrayBuffer(0).slice().constructor);
diff --git a/test/mjsunit/harmony/async-arrow-lexical-arguments.js b/test/mjsunit/harmony/async-arrow-lexical-arguments.js
new file mode 100644
index 0000000..44d38a4
--- /dev/null
+++ b/test/mjsunit/harmony/async-arrow-lexical-arguments.js
@@ -0,0 +1,42 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await --allow-natives-syntax
+
+function assertEqualsAsync(expected, run, msg) {
+  var actual;
+  var hadValue = false;
+  var hadError = false;
+  var promise = run();
+
+  if (typeof promise !== "object" || typeof promise.then !== "function") {
+    throw new MjsUnitAssertionError(
+        "Expected " + run.toString() +
+        " to return a Promise, but it returned " + PrettyPrint(promise));
+  }
+
+  promise.then(function(value) { hadValue = true; actual = value; },
+               function(error) { hadError = true; actual = error; });
+
+  assertFalse(hadValue || hadError);
+
+  %RunMicrotasks();
+
+  if (hadError) throw actual;
+
+  assertTrue(
+      hadValue, "Expected '" + run.toString() + "' to produce a value");
+
+  assertEquals(expected, actual, msg);
+};
+
+assertEqualsAsync("[1,2,3]", () => (function() {
+  return (async () => JSON.stringify([...arguments]))();
+})(1, 2, 3));
+
+assertEqualsAsync("[4,5,6]",
+    () => (function() {
+      return (async () => {
+        return JSON.stringify([...await arguments]) })();
+      })(4, 5, 6));
diff --git a/test/mjsunit/harmony/async-arrow-lexical-new.target.js b/test/mjsunit/harmony/async-arrow-lexical-new.target.js
new file mode 100644
index 0000000..72b29e6
--- /dev/null
+++ b/test/mjsunit/harmony/async-arrow-lexical-new.target.js
@@ -0,0 +1,43 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await --allow-natives-syntax
+
+function assertEqualsAsync(expected, run, msg) {
+  var actual;
+  var hadValue = false;
+  var hadError = false;
+  var promise = run();
+
+  if (typeof promise !== "object" || typeof promise.then !== "function") {
+    throw new MjsUnitAssertionError(
+        "Expected " + run.toString() +
+        " to return a Promise, but it returned " + PrettyPrint(promise));
+  }
+
+  promise.then(function(value) { hadValue = true; actual = value; },
+               function(error) { hadError = true; actual = error; });
+
+  assertFalse(hadValue || hadError);
+
+  %RunMicrotasks();
+
+  if (hadError) throw actual;
+
+  assertTrue(
+      hadValue, "Expected '" + run.toString() + "' to produce a value");
+
+  assertEquals(expected, actual, msg);
+};
+
+class BaseClass {
+  constructor() {
+    return async () => new.target;
+  }
+}
+
+class ChildClass extends BaseClass {}
+
+assertEqualsAsync(BaseClass, () => new BaseClass()());
+assertEqualsAsync(ChildClass, () => new ChildClass()());
diff --git a/test/mjsunit/harmony/async-arrow-lexical-super.js b/test/mjsunit/harmony/async-arrow-lexical-super.js
new file mode 100644
index 0000000..78f5d55
--- /dev/null
+++ b/test/mjsunit/harmony/async-arrow-lexical-super.js
@@ -0,0 +1,58 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await --allow-natives-syntax
+
+function assertEqualsAsync(expected, run, msg) {
+  var actual;
+  var hadValue = false;
+  var hadError = false;
+  var promise = run();
+
+  if (typeof promise !== "object" || typeof promise.then !== "function") {
+    throw new MjsUnitAssertionError(
+        "Expected " + run.toString() +
+        " to return a Promise, but it returned " + PrettyPrint(promise));
+  }
+
+  promise.then(function(value) { hadValue = true; actual = value; },
+               function(error) { hadError = true; actual = error; });
+
+  assertFalse(hadValue || hadError);
+
+  %RunMicrotasks();
+
+  if (hadError) throw actual;
+
+  assertTrue(
+      hadValue, "Expected '" + run.toString() + "' to produce a value");
+
+  assertEquals(expected, actual, msg);
+};
+
+class BaseClass {
+  constructor(x) {
+    this.name_ = x;
+  }
+  get name() { return this.name_; }
+};
+
+class DeferredSuperCall extends BaseClass {
+  constructor(x) {
+    return async() => super(x);
+  }
+};
+
+assertEqualsAsync(
+  "LexicalSuperCall",
+  () => new DeferredSuperCall("LexicalSuperCall")().then(x => x.name));
+
+
+class DeferredSuperProperty extends BaseClass {
+  deferredName() { return async() => super.name; }
+};
+
+assertEqualsAsync(
+  "LexicalSuperProperty",
+  () => new DeferredSuperProperty("LexicalSuperProperty").deferredName()());
diff --git a/test/mjsunit/harmony/async-arrow-lexical-this.js b/test/mjsunit/harmony/async-arrow-lexical-this.js
new file mode 100644
index 0000000..182db47
--- /dev/null
+++ b/test/mjsunit/harmony/async-arrow-lexical-this.js
@@ -0,0 +1,48 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await --allow-natives-syntax
+
+function assertEqualsAsync(expected, run, msg) {
+  var actual;
+  var hadValue = false;
+  var hadError = false;
+  var promise = run();
+
+  if (typeof promise !== "object" || typeof promise.then !== "function") {
+    throw new MjsUnitAssertionError(
+        "Expected " + run.toString() +
+        " to return a Promise, but it returned " + PrettyPrint(promise));
+  }
+
+  promise.then(function(value) { hadValue = true; actual = value; },
+               function(error) { hadError = true; actual = error; });
+
+  assertFalse(hadValue || hadError);
+
+  %RunMicrotasks();
+
+  if (hadError) throw actual;
+
+  assertTrue(
+      hadValue, "Expected '" + run.toString() + "' to produce a value");
+
+  assertEquals(expected, actual, msg);
+};
+
+var O = {
+  [Symbol.toStringTag]: "LexicalThis",
+  run(n) {
+    return async passFail => `${n}. ${passFail}: ${this}`;
+  },
+};
+
+assertEqualsAsync("1. PASS: [object LexicalThis]", () => O.run(1)("PASS"));
+
+var O2 = {
+  [Symbol.toStringTag]: "LexicalThis",
+  run: O.run(2)
+};
+
+assertEqualsAsync("2. PASS: [object LexicalThis]", () => O2.run("PASS"));
diff --git a/test/mjsunit/harmony/async-await-basic.js b/test/mjsunit/harmony/async-await-basic.js
new file mode 100644
index 0000000..ba0350f
--- /dev/null
+++ b/test/mjsunit/harmony/async-await-basic.js
@@ -0,0 +1,369 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await --allow-natives-syntax
+
+// Do not install `AsyncFunction` constructor on global object
+
+function assertThrowsAsync(run, errorType, message) {
+  var actual;
+  var hadValue = false;
+  var hadError = false;
+  var promise = run();
+
+  if (typeof promise !== "object" || typeof promise.then !== "function") {
+    throw new MjsUnitAssertionError(
+        "Expected " + run.toString() +
+        " to return a Promise, but it returned " + PrettyPrint(promise));
+  }
+
+  promise.then(function(value) { hadValue = true; actual = value; },
+               function(error) { hadError = true; actual = error; });
+
+  assertFalse(hadValue || hadError);
+
+  %RunMicrotasks();
+
+  if (!hadError) {
+    throw new MjsUnitAssertionError(
+        "Expected " + run + "() to throw " + errorType.name +
+        ", but did not throw.");
+  }
+  if (!(actual instanceof errorType))
+    throw new MjsUnitAssertionError(
+        "Expected " + run + "() to throw " + errorType.name +
+        ", but threw '" + actual + "'");
+  if (message !== void 0 && actual.message !== message)
+    throw new MjsUnitAssertionError(
+        "Expected " + run + "() to throw '" + message + "', but threw '" +
+        actual.message + "'");
+};
+
+function assertEqualsAsync(expected, run, msg) {
+  var actual;
+  var hadValue = false;
+  var hadError = false;
+  var promise = run();
+
+  if (typeof promise !== "object" || typeof promise.then !== "function") {
+    throw new MjsUnitAssertionError(
+        "Expected " + run.toString() +
+        " to return a Promise, but it returned " + PrettyPrint(promise));
+  }
+
+  promise.then(function(value) { hadValue = true; actual = value; },
+               function(error) { hadError = true; actual = error; });
+
+  assertFalse(hadValue || hadError);
+
+  %RunMicrotasks();
+
+  if (hadError) throw actual;
+
+  assertTrue(
+      hadValue, "Expected '" + run.toString() + "' to produce a value");
+
+  assertEquals(expected, actual, msg);
+};
+
+assertEquals(undefined, this.AsyncFunction);
+let AsyncFunction = (async function() {}).constructor;
+
+// Let functionPrototype be the intrinsic object %AsyncFunctionPrototype%.
+async function asyncFunctionForProto() {}
+assertEquals(AsyncFunction.prototype,
+             Object.getPrototypeOf(asyncFunctionForProto));
+assertEquals(AsyncFunction.prototype,
+             Object.getPrototypeOf(async function() {}));
+assertEquals(AsyncFunction.prototype, Object.getPrototypeOf(async () => {}));
+assertEquals(AsyncFunction.prototype,
+             Object.getPrototypeOf({ async method() {} }.method));
+assertEquals(AsyncFunction.prototype, Object.getPrototypeOf(AsyncFunction()));
+assertEquals(AsyncFunction.prototype,
+             Object.getPrototypeOf(new AsyncFunction()));
+
+// AsyncFunctionCreate does not produce an object with a Prototype
+assertEquals(undefined, asyncFunctionForProto.prototype);
+assertEquals(false, asyncFunctionForProto.hasOwnProperty("prototype"));
+assertEquals(undefined, (async function() {}).prototype);
+assertEquals(false, (async function() {}).hasOwnProperty("prototype"));
+assertEquals(undefined, (async() => {}).prototype);
+assertEquals(false, (async() => {}).hasOwnProperty("prototype"));
+assertEquals(undefined, ({ async method() {} }).method.prototype);
+assertEquals(false, ({ async method() {} }).method.hasOwnProperty("prototype"));
+assertEquals(undefined, AsyncFunction().prototype);
+assertEquals(false, AsyncFunction().hasOwnProperty("prototype"));
+assertEquals(undefined, (new AsyncFunction()).prototype);
+assertEquals(false, (new AsyncFunction()).hasOwnProperty("prototype"));
+
+assertEquals(1, async function(a) { await 1; }.length);
+assertEquals(2, async function(a, b) { await 1; }.length);
+assertEquals(1, async function(a, b = 2) { await 1; }.length);
+assertEquals(2, async function(a, b, ...c) { await 1; }.length);
+
+assertEquals(1, (async(a) => await 1).length);
+assertEquals(2, (async(a, b) => await 1).length);
+assertEquals(1, (async(a, b = 2) => await 1).length);
+assertEquals(2, (async(a, b, ...c) => await 1).length);
+
+assertEquals(1, ({ async f(a) { await 1; } }).f.length);
+assertEquals(2, ({ async f(a, b) { await 1; } }).f.length);
+assertEquals(1, ({ async f(a, b = 2) { await 1; } }).f.length);
+assertEquals(2, ({ async f(a, b, ...c) { await 1; } }).f.length);
+
+assertEquals(1, AsyncFunction("a", "await 1").length);
+assertEquals(2, AsyncFunction("a", "b", "await 1").length);
+assertEquals(1, AsyncFunction("a", "b = 2", "await 1").length);
+assertEquals(2, AsyncFunction("a", "b", "...c", "await 1").length);
+
+assertEquals(1, (new AsyncFunction("a", "await 1")).length);
+assertEquals(2, (new AsyncFunction("a", "b", "await 1")).length);
+assertEquals(1, (new AsyncFunction("a", "b = 2", "await 1")).length);
+assertEquals(2, (new AsyncFunction("a", "b", "...c", "await 1")).length);
+
+// AsyncFunction.prototype[ @@toStringTag ]
+var descriptor =
+    Object.getOwnPropertyDescriptor(AsyncFunction.prototype,
+                                    Symbol.toStringTag);
+assertEquals("AsyncFunction", descriptor.value);
+assertEquals(false, descriptor.enumerable);
+assertEquals(false, descriptor.writable);
+assertEquals(true, descriptor.configurable);
+
+assertEquals(1, AsyncFunction.length);
+
+// Let F be ! FunctionAllocate(functionPrototype, Strict, "non-constructor")
+async function asyncNonConstructorDecl() {}
+assertThrows(
+    () => new asyncNonConstructorDecl(), TypeError);
+assertThrows(
+    () => new (async function() {}), TypeError);
+assertThrows(
+    () => new ({ async nonConstructor() {} }).nonConstructor(), TypeError);
+assertThrows(
+    () => new (() => "not a constructor!"), TypeError);
+assertThrows(
+    () => new (AsyncFunction()), TypeError);
+assertThrows(
+    () => new (new AsyncFunction()), TypeError);
+
+// Normal completion
+async function asyncDecl() { return "test"; }
+assertEqualsAsync("test", asyncDecl);
+assertEqualsAsync("test2", async function() { return "test2"; });
+assertEqualsAsync("test3", async () => "test3");
+assertEqualsAsync("test4", () => ({ async f() { return "test4"; } }).f());
+assertEqualsAsync("test5", () => AsyncFunction("no", "return 'test' + no;")(5));
+assertEqualsAsync("test6",
+                  () => (new AsyncFunction("no", "return 'test' + no;"))(6));
+
+class MyError extends Error {};
+
+// Throw completion
+async function asyncDeclThrower(e) { throw new MyError(e); }
+assertThrowsAsync(() => asyncDeclThrower("boom!"), MyError, "boom!");
+assertThrowsAsync(
+  () => (async function(e) { throw new MyError(e); })("boom!!!"),
+  MyError, "boom!!!");
+assertThrowsAsync(
+  () => (async e => { throw new MyError(e) })("boom!!"), MyError, "boom!!");
+assertThrowsAsync(
+  () => ({ async thrower(e) { throw new MyError(e); } }).thrower("boom!1!"),
+  MyError, "boom!1!");
+assertThrowsAsync(
+  () => AsyncFunction("msg", "throw new MyError(msg)")("boom!2!!"),
+  MyError, "boom!2!!");
+assertThrowsAsync(
+  () => (new AsyncFunction("msg", "throw new MyError(msg)"))("boom!2!!!"),
+  MyError, "boom!2!!!");
+
+function resolveLater(value) { return Promise.resolve(value); }
+function rejectLater(error) { return Promise.reject(error); }
+
+// Resume after Normal completion
+var log = [];
+async function resumeAfterNormal(value) {
+  log.push("start:" + value);
+  value = await resolveLater(value + 1);
+  log.push("resume:" + value);
+  value = await resolveLater(value + 1);
+  log.push("resume:" + value);
+  return value + 1;
+}
+
+assertEqualsAsync(4, () => resumeAfterNormal(1));
+assertEquals("start:1 resume:2 resume:3", log.join(" "));
+
+var O = {
+  async resumeAfterNormal(value) {
+    log.push("start:" + value);
+    value = await resolveLater(value + 1);
+    log.push("resume:" + value);
+    value = await resolveLater(value + 1);
+    log.push("resume:" + value);
+    return value + 1;
+  }
+};
+log = [];
+assertEqualsAsync(5, () => O.resumeAfterNormal(2));
+assertEquals("start:2 resume:3 resume:4", log.join(" "));
+
+var resumeAfterNormalArrow = async (value) => {
+  log.push("start:" + value);
+  value = await resolveLater(value + 1);
+  log.push("resume:" + value);
+  value = await resolveLater(value + 1);
+  log.push("resume:" + value);
+  return value + 1;
+};
+log = [];
+assertEqualsAsync(6, () => resumeAfterNormalArrow(3));
+assertEquals("start:3 resume:4 resume:5", log.join(" "));
+
+var resumeAfterNormalEval = AsyncFunction("value", `
+    log.push("start:" + value);
+    value = await resolveLater(value + 1);
+    log.push("resume:" + value);
+    value = await resolveLater(value + 1);
+    log.push("resume:" + value);
+    return value + 1;`);
+log = [];
+assertEqualsAsync(7, () => resumeAfterNormalEval(4));
+assertEquals("start:4 resume:5 resume:6", log.join(" "));
+
+var resumeAfterNormalNewEval = new AsyncFunction("value", `
+    log.push("start:" + value);
+    value = await resolveLater(value + 1);
+    log.push("resume:" + value);
+    value = await resolveLater(value + 1);
+    log.push("resume:" + value);
+    return value + 1;`);
+log = [];
+assertEqualsAsync(8, () => resumeAfterNormalNewEval(5));
+assertEquals("start:5 resume:6 resume:7", log.join(" "));
+
+// Resume after Throw completion
+async function resumeAfterThrow(value) {
+  log.push("start:" + value);
+  try {
+    value = await rejectLater("throw1");
+  } catch (e) {
+    log.push("resume:" + e);
+  }
+  try {
+    value = await rejectLater("throw2");
+  } catch (e) {
+    log.push("resume:" + e);
+  }
+  return value + 1;
+}
+
+log = [];
+assertEqualsAsync(2, () => resumeAfterThrow(1));
+assertEquals("start:1 resume:throw1 resume:throw2", log.join(" "));
+
+var O = {
+  async resumeAfterThrow(value) {
+    log.push("start:" + value);
+    try {
+      value = await rejectLater("throw1");
+    } catch (e) {
+      log.push("resume:" + e);
+    }
+    try {
+      value = await rejectLater("throw2");
+    } catch (e) {
+      log.push("resume:" + e);
+    }
+    return value + 1;
+  }
+}
+log = [];
+assertEqualsAsync(3, () => O.resumeAfterThrow(2));
+assertEquals("start:2 resume:throw1 resume:throw2", log.join(" "));
+
+var resumeAfterThrowArrow = async (value) => {
+  log.push("start:" + value);
+  try {
+    value = await rejectLater("throw1");
+  } catch (e) {
+    log.push("resume:" + e);
+  }
+  try {
+    value = await rejectLater("throw2");
+  } catch (e) {
+    log.push("resume:" + e);
+  }
+ return value + 1;
+};
+
+log = [];
+
+assertEqualsAsync(4, () => resumeAfterThrowArrow(3));
+assertEquals("start:3 resume:throw1 resume:throw2", log.join(" "));
+
+var resumeAfterThrowEval = AsyncFunction("value", `
+    log.push("start:" + value);
+    try {
+      value = await rejectLater("throw1");
+    } catch (e) {
+      log.push("resume:" + e);
+    }
+    try {
+      value = await rejectLater("throw2");
+    } catch (e) {
+      log.push("resume:" + e);
+    }
+    return value + 1;`);
+log = [];
+assertEqualsAsync(5, () => resumeAfterThrowEval(4));
+assertEquals("start:4 resume:throw1 resume:throw2", log.join(" "));
+
+var resumeAfterThrowNewEval = new AsyncFunction("value", `
+    log.push("start:" + value);
+    try {
+      value = await rejectLater("throw1");
+    } catch (e) {
+      log.push("resume:" + e);
+    }
+    try {
+      value = await rejectLater("throw2");
+    } catch (e) {
+      log.push("resume:" + e);
+    }
+    return value + 1;`);
+log = [];
+assertEqualsAsync(6, () => resumeAfterThrowNewEval(5));
+assertEquals("start:5 resume:throw1 resume:throw2", log.join(" "));
+
+async function foo() {}
+assertEquals("async function foo() {}", foo.toString());
+assertEquals("async function () {}", async function() {}.toString());
+assertEquals("async x => x", (async x => x).toString());
+assertEquals("async x => { return x }", (async x => { return x }).toString());
+class AsyncMethod { async foo() { } }
+assertEquals("async foo() { }",
+             Function.prototype.toString.call(AsyncMethod.prototype.foo));
+assertEquals("async foo() { }",
+             Function.prototype.toString.call({async foo() { }}.foo));
+
+// Async functions are not constructible
+assertThrows(() => class extends (async function() {}) {}, TypeError);
+
+// Regress v8:5148
+assertEqualsAsync("1", () => (async({ a = NaN }) => a)({ a: "1" }));
+assertEqualsAsync(
+    "10", () => (async(foo, { a = NaN }) => foo + a)("1", { a: "0" }));
+assertEqualsAsync("2", () => (async({ a = "2" }) => a)({ a: undefined }));
+assertEqualsAsync(
+    "20", () => (async(foo, { a = "0" }) => foo + a)("2", { a: undefined }));
+assertThrows(() => eval("async({ foo = 1 })"), SyntaxError);
+assertThrows(() => eval("async(a, { foo = 1 })"), SyntaxError);
+
+// https://bugs.chromium.org/p/chromium/issues/detail?id=638019
+async function gaga() {
+  let i = 1;
+  while (i-- > 0) { await 42 }
+}
+assertDoesNotThrow(gaga);
diff --git a/test/mjsunit/harmony/async-debug-basic.js b/test/mjsunit/harmony/async-debug-basic.js
new file mode 100644
index 0000000..a490972
--- /dev/null
+++ b/test/mjsunit/harmony/async-debug-basic.js
@@ -0,0 +1,40 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags:  --harmony-async-await --allow-natives-syntax --expose-debug-as debug
+
+// Get the Debug object exposed from the debug context global object.
+Debug = debug.Debug
+
+listenerComplete = false;
+breakPointCount = 0;
+
+async function f() {
+  await (async function() { var a = "a"; await 1; debugger; })();
+
+  var b = "b";
+
+  assertTrue(listenerDone);
+  assertFalse(exception);
+  assertEquals(1, breakpointCount);
+}
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event != Debug.DebugEvent.Break) return;
+
+    breakpointCount++;
+    listenerDone = true;
+    assertEquals("a", exec_state.frame(0).evaluate("a"));
+    assertEquals("b", exec_state.frame(1).evaluate("b"));
+    assertEquals("c", exec_state.frame(2).evaluate("c"));
+  } catch (e) {
+    exception = e;
+  };
+};
+
+Debug.setListener(listener);
+
+var c = "c";
+f();
diff --git a/test/mjsunit/harmony/async-debug-step-abort-at-break.js b/test/mjsunit/harmony/async-debug-step-abort-at-break.js
new file mode 100644
index 0000000..be1f805
--- /dev/null
+++ b/test/mjsunit/harmony/async-debug-step-abort-at-break.js
@@ -0,0 +1,55 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax --harmony-async-await
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var late_resolve;
+
+function g() {
+  return new Promise( // B3 StepOut
+    function(res, rej) {
+      late_resolve = res;
+    }
+  );
+}
+
+async function f() {
+  var a = 1;
+  debugger;          // B0 StepNext
+  a +=               // B1 StepNext
+       await         // B4 StepNext
+             g();    // B2 StepIn
+  return a;
+}
+
+f();
+
+// Starting a new step action at an intermediate break point
+// means that we will abort the current async step.
+debugger;            // B5 StepNext
+
+late_resolve(3);     // B6 Continue
+
+%RunMicrotasks();
+
+assertEquals(7, step_count);
diff --git a/test/mjsunit/harmony/async-debug-step-continue-at-break.js b/test/mjsunit/harmony/async-debug-step-continue-at-break.js
new file mode 100644
index 0000000..5099b2f
--- /dev/null
+++ b/test/mjsunit/harmony/async-debug-step-continue-at-break.js
@@ -0,0 +1,55 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax --harmony-async-await
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var late_resolve;
+
+function g() {
+  return new Promise( // B3 StepOut
+    function(res, rej) {
+      late_resolve = res;
+    }
+  );
+}
+
+async function f() {
+  var a = 1;
+  debugger;          // B0 StepNext
+  a +=               // B1 StepNext
+       await         // B4 StepNext
+             g();    // B2 StepIn
+  return a;          // B6 StepNext
+}                    // B7 Continue
+
+f();
+
+// Continuing at an intermediate break point means that we will
+// carry on with the current async step.
+debugger;            // B5 Continue
+
+late_resolve(3);
+
+%RunMicrotasks();
+
+assertEquals(8, step_count);
diff --git a/test/mjsunit/harmony/async-debug-step-in-and-out.js b/test/mjsunit/harmony/async-debug-step-in-and-out.js
new file mode 100644
index 0000000..30fe2d6
--- /dev/null
+++ b/test/mjsunit/harmony/async-debug-step-in-and-out.js
@@ -0,0 +1,51 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax --harmony-async-await
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var late_resolve;
+
+function g() {
+  return new Promise(  // B3 StepOut
+    function(res, rej) {
+      late_resolve = res;
+    }
+  );
+}
+
+async function f() {
+  var a = 1;
+  debugger;            // B0 StepNext
+  a +=                 // B1 StepNext
+       await           // B4 StepNext
+             g();      // B2 StepIn
+  return a;            // B5 StepNext
+}                      // B6 Continue
+
+f();
+
+late_resolve(3);
+
+%RunMicrotasks();
+
+assertEquals(7, step_count);
diff --git a/test/mjsunit/harmony/async-debug-step-in-out-out.js b/test/mjsunit/harmony/async-debug-step-in-out-out.js
new file mode 100644
index 0000000..c2f34bb
--- /dev/null
+++ b/test/mjsunit/harmony/async-debug-step-in-out-out.js
@@ -0,0 +1,51 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax --harmony-async-await
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var late_resolve;
+
+function g() {
+  return new Promise( // B3 StepOut
+    function(res, rej) {
+      late_resolve = res;
+    }
+  );
+}
+
+async function f() {
+  var a = 1;
+  debugger;        // B0 StepNext
+  a +=             // B1 StepNext
+       await       // B4 StepOut
+             g();  // B2 StepIn
+  return a;
+}
+
+f();
+
+late_resolve(3);   // B5 Continue
+
+%RunMicrotasks();
+
+assertEquals(6, step_count);
diff --git a/test/mjsunit/harmony/async-debug-step-in.js b/test/mjsunit/harmony/async-debug-step-in.js
new file mode 100644
index 0000000..0a7de1a
--- /dev/null
+++ b/test/mjsunit/harmony/async-debug-step-in.js
@@ -0,0 +1,51 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax --harmony-async-await
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var late_resolve;
+
+function g() {
+  return new Promise(  // B3 StepIn
+    function(res, rej) {
+      late_resolve = res;  // B4 StepIn
+    }                      // B5 StepIn
+  );
+}                      // B6 StepIn
+
+async function f() {
+  var a = 1;
+  debugger;            // B0 StepNext
+  a +=                 // B1 StepIn
+       await           // B7 StepIn
+             g();      // B2 StepIn
+  return a;            // B8 StepIn
+}                      // B9 Continue
+
+f().then(value => assertEquals(4, value));
+
+late_resolve(3);
+
+%RunMicrotasks();
+
+assertEquals(10, step_count);
diff --git a/test/mjsunit/harmony/async-debug-step-nested.js b/test/mjsunit/harmony/async-debug-step-nested.js
new file mode 100644
index 0000000..adf7a51
--- /dev/null
+++ b/test/mjsunit/harmony/async-debug-step-nested.js
@@ -0,0 +1,58 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax --harmony-async-await
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var late_resolve;
+
+function g() {
+  return new Promise( // B4 StepOut
+    function(res, rej) {
+      late_resolve = res;
+    }
+  );
+}
+
+async function f1() {
+  var a = 1;
+  debugger;          // B0 StepNext
+  a +=               // B1 StepNext
+       await         // B6 StepNext
+             f2();   // B2 StepIn
+  return a;          // B7 StepNext
+}                    // B8 Continue
+
+async function f2() {
+  var b =
+          await      // B5 StepOut
+                g(); // B3 StepIn
+  return b;
+}
+
+f1();
+
+late_resolve(3);
+
+%RunMicrotasks();
+
+assertEquals(9, step_count);
diff --git a/test/mjsunit/harmony/async-debug-step-next-constant.js b/test/mjsunit/harmony/async-debug-step-next-constant.js
new file mode 100644
index 0000000..cea86d7
--- /dev/null
+++ b/test/mjsunit/harmony/async-debug-step-next-constant.js
@@ -0,0 +1,39 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax --harmony-async-await
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+async function f() {
+  var a = 1;
+  debugger;          // B0 StepNext
+  a +=               // B1 StepNext
+       await         // B3 StepNext
+             5;      // B2 StepNext
+  return a;          // B4 StepNext
+}                    // B5 Continue
+
+f();
+
+%RunMicrotasks();
+
+assertEquals(6, step_count);
diff --git a/test/mjsunit/harmony/async-debug-step-next.js b/test/mjsunit/harmony/async-debug-step-next.js
new file mode 100644
index 0000000..952d88d
--- /dev/null
+++ b/test/mjsunit/harmony/async-debug-step-next.js
@@ -0,0 +1,51 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax --harmony-async-await
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var late_resolve;
+
+function g() {
+  return new Promise(
+    function(res, rej) {
+      late_resolve = res;
+    }
+  );
+}
+
+async function f() {
+  var a = 1;
+  debugger;        // B0 StepNext
+  a +=             // B1 StepNext
+       await       // B3 StepNext
+             g();  // B2 StepNext
+  return a;        // B4 StepNext
+}                  // B5 Continue
+
+f();
+
+late_resolve(3);
+
+%RunMicrotasks();
+
+assertEquals(6, step_count);
diff --git a/test/mjsunit/harmony/async-debug-step-out.js b/test/mjsunit/harmony/async-debug-step-out.js
new file mode 100644
index 0000000..41779ac
--- /dev/null
+++ b/test/mjsunit/harmony/async-debug-step-out.js
@@ -0,0 +1,49 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax --harmony-async-await
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var late_resolve;
+
+function g() {
+  return new Promise(
+    function(res, rej) {
+      late_resolve = res;
+    }
+  );
+}
+
+async function f() {
+  var a = 1;
+  debugger;        // B0 StepNext
+  a += await g();  // B1 StepOut
+  return a;
+}
+
+f();
+
+late_resolve(3);   // B2 Continue
+
+%RunMicrotasks();
+
+assertEquals(3, step_count);
diff --git a/test/mjsunit/harmony/async-function-debug-evaluate.js b/test/mjsunit/harmony/async-function-debug-evaluate.js
new file mode 100644
index 0000000..edf7bca
--- /dev/null
+++ b/test/mjsunit/harmony/async-function-debug-evaluate.js
@@ -0,0 +1,139 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await --expose-debug-as debug
+
+var Debug = debug.Debug;
+var breakPointCount = 0;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  ++breakPointCount;
+  try {
+    if (breakPointCount === 1) {
+      assertEquals(
+          "inner", exec_state.frame(0).evaluate("inner").value());
+      assertThrows(() => exec_state.frame(0).evaluate("letInner").value(),
+                   ReferenceError);
+      assertThrows(() => exec_state.frame(0).evaluate("constInner").value(),
+                   ReferenceError);
+
+      assertEquals("outer", exec_state.frame(0).evaluate("outer").value());
+      assertEquals(
+          "const outer", exec_state.frame(0).evaluate("constOuter").value());
+      assertEquals(
+          "let outer", exec_state.frame(0).evaluate("letOuter").value());
+
+      assertEquals("outer", exec_state.frame(1).evaluate("outer").value());
+      assertEquals(
+          "const outer", exec_state.frame(1).evaluate("constOuter").value());
+      assertEquals(
+          "let outer", exec_state.frame(1).evaluate("letOuter").value());
+
+      assertThrows(() => exec_state.frame(0).evaluate("withVar").value(),
+                   ReferenceError);
+
+    } else if (breakPointCount === 2) {
+      assertEquals(
+          "inner", exec_state.frame(0).evaluate("inner").value());
+      assertThrows(() => exec_state.frame(0).evaluate("letInner").value(),
+                   ReferenceError);
+      assertThrows(() => exec_state.frame(0).evaluate("constInner").value(),
+                   ReferenceError);
+
+      assertEquals(57, exec_state.frame(0).evaluate("x").value());
+      assertEquals(100, exec_state.frame(0).evaluate("y").value());
+
+      // From breakPointCount === 1 and later, it's not possible to access
+      // earlier framestates.
+      assertEquals("outer", exec_state.frame(0).evaluate("outer").value());
+      assertEquals(
+          "const outer", exec_state.frame(0).evaluate("constOuter").value());
+      assertEquals(
+          "let outer", exec_state.frame(0).evaluate("letOuter").value());
+
+      exec_state.frame(0).evaluate("x = `x later(${x})`");
+      exec_state.frame(0).evaluate("y = `y later(${y})`");
+      exec_state.frame(0).evaluate("z = `ZEE`");
+
+    } else if (breakPointCount === 3) {
+      assertEquals(
+          "inner", exec_state.frame(0).evaluate("inner").value());
+      assertEquals(
+          "let inner", exec_state.frame(0).evaluate("letInner").value());
+      assertEquals(
+          "const inner", exec_state.frame(0).evaluate("constInner").value());
+
+    } else if (breakPointCount === 4) {
+      assertEquals(
+          "oop", exec_state.frame(0).evaluate("error.message").value());
+      assertEquals(
+          "Error",
+          exec_state.frame(0).evaluate("error.constructor.name").value());
+      assertEquals("floof", exec_state.frame(0).evaluate("bun").value());
+      assertThrows(() => exec_state.frame(0).evaluate("cow").value(),
+                   ReferenceError);
+
+      assertEquals("outer", exec_state.frame(0).evaluate("outer").value());
+      assertEquals(
+          "const outer", exec_state.frame(0).evaluate("constOuter").value());
+      assertEquals(
+          "let outer", exec_state.frame(0).evaluate("letOuter").value());
+    }
+  } catch (e) {
+    print(e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var outer = "outer";
+const constOuter = "const outer";
+let letOuter = "let outer"
+
+async function thrower() {
+  return Promise.reject(new Error("oop"));
+}
+
+async function testLater() {
+  return { x: 57, y: 100 };
+}
+
+async function test() {
+  var inner = "inner";
+  debugger;
+
+  let withVar = await testLater();
+  with (withVar) {
+    debugger;
+  }
+
+  assertEquals("x later(57)", withVar.x);
+  assertEquals("y later(100)", withVar.y);
+  assertEquals(undefined, withVar.z);
+  assertEquals("ZEE", z);
+
+  let letInner = "let inner";
+  const constInner = "const inner";
+  debugger;
+
+  try {
+    await thrower();
+  } catch (error) {
+    const bun = "floof";
+    debugger;
+    let cow = "moo";
+  }
+}
+
+test().
+then(x => {
+  Debug.setListener(null);
+}).
+catch(error => {
+  print(error.stack);
+  quit(1);
+  Debug.setListener(null);
+});
diff --git a/test/mjsunit/harmony/async-function-debug-scopes.js b/test/mjsunit/harmony/async-function-debug-scopes.js
new file mode 100644
index 0000000..3d72549
--- /dev/null
+++ b/test/mjsunit/harmony/async-function-debug-scopes.js
@@ -0,0 +1,616 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await --expose-debug-as debug
+
+var Debug = debug.Debug;
+
+var AsyncFunction = (async function() {}).constructor;
+
+async function thrower() { throw 'Exception'; }
+
+async function test(name, func, args, handler, continuation) {
+  var handler_called = false;
+  var exception = null;
+
+  function listener(event, exec_state, event_data, data) {
+    try {
+      if (event == Debug.DebugEvent.Break) {
+        handler_called = true;
+        handler(exec_state);
+      }
+    } catch (e) {
+      exception = e;
+    }
+  }
+
+  Debug.setListener(listener);
+
+  var result;
+  if (typeof func === "object")
+    result = await func.method.apply(func, args);
+  else
+    result = await func.apply(null, args);
+
+  if (typeof continuation === "function") {
+    await continuation(result);
+  }
+
+  assertTrue(handler_called, `Expected ${name} handler to be called`);
+  if (exception) {
+    exception.message = `${name} / ${exception.message}`;
+    print(exception.stack);
+    quit(1);
+  }
+
+  Debug.setListener(null);
+}
+
+async function runTests() {
+
+// Simple
+await test(
+    "(AsyncFunctionExpression) Local 1",
+    async function() { debugger; }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 1 --- resume normal",
+    async function() { let z = await 2; debugger; }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({z: 2}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 1 --- resume throw",
+    async function() { let q = await 1;
+                       try { let z = await thrower(); }
+                       catch (e) { debugger; } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({e: 'Exception'}, 0, exec_state);
+      CheckScopeContent({q: 1}, 1, exec_state);
+
+    });
+
+// Simple With Parameter
+await test(
+    "(AsyncFunctionExpression) Local 2",
+    async function(a) { debugger; }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ a: 1 }, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 2 --- resume normal",
+    async function(a) { let z = await 2; debugger; }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ a: 1, z: 2 }, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 2 --- resume throw",
+    async function(a) { let z = await 2;
+                        try { await thrower(); } catch (e) { debugger; } }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ e: 'Exception' }, 0, exec_state);
+      CheckScopeContent({ a: 1, z: 2 }, 1, exec_state);
+    });
+
+// Simple With Parameter and Variable
+await test(
+    "(AsyncFunctionExpression) Local 3",
+    async function(a) { var b = 2; debugger; }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ a: 1, b: 2 }, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 3 --- resume normal",
+    async function(a) { let y = await 3; var b = 2; let z = await 4;
+                        debugger; }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ a: 1, b: 2, y: 3, z: 4 }, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 3 --- resume throw",
+    async function(a) { let y = await 3;
+                        try { var b = 2; let z = await thrower(); }
+                        catch (e) { debugger; } }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ e: 'Exception' }, 0, exec_state);
+      CheckScopeContent({ a: 1, b: 2, y: 3 }, 1, exec_state);
+    });
+
+// Local scope with parameters and local variables.
+await test(
+    "(AsyncFunctionExpression) Local 4",
+    async function(a, b) { var x = 3; var y = 4; debugger; }, [1, 2],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 4 --- resume normal",
+    async function(a, b) { let q = await 5; var x = 3; var y = 4;
+                           let r = await 6; debugger; }, [1, 2],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({a:1,b:2,x:3,y:4, q: 5, r: 6}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 4 --- resume throw",
+    async function(a, b) { let q = await 5; var x = 3; var y = 4;
+                           try { let r = await thrower(); }
+                           catch (e) { debugger; } }, [1, 2],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({e: 'Exception'}, 0, exec_state);
+      CheckScopeContent({a:1,b:2,x:3,y:4, q: 5}, 1, exec_state);
+    });
+
+// Empty local scope with use of eval.
+await test(
+    "(AsyncFunctionExpression) Local 5",
+    async function() { eval(""); debugger; }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 5 --- resume normal",
+    async function() { let x = await 1; eval(""); let y = await 2;
+                       debugger; }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ x: 1, y: 2 }, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 5 --- resume throw",
+    async function() { let x = await 1; eval("");
+                       try { let y = await thrower(); }
+                       catch (e) { debugger; } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ e: 'Exception' }, 0, exec_state);
+      CheckScopeContent({ x: 1 }, 1, exec_state);
+    });
+
+// Local introducing local variable using eval.
+await test(
+    "(AsyncFunctionExpression) Local 6",
+    async function() { eval("var i = 5"); debugger; }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({i:5}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 6 --- resume normal",
+    async function() { let x = await 1; eval("var i = 5"); let y = await 2;
+                       debugger; }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({i:5, x: 1, y: 2}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 6 --- resume throw",
+    async function() { let x = await 1; eval("var i = 5");
+                       try { let y = await thrower(); }
+                       catch (e) { debugger; } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({e: 'Exception' }, 0, exec_state);
+      CheckScopeContent({i:5, x: 1}, 1, exec_state);
+    });
+
+// Local scope with parameters, local variables and local variable introduced
+// using eval.
+await test(
+    "(AsyncFunctionExpression) Local 7",
+    async function(a, b) { var x = 3; var y = 4;
+                           eval("var i = 5;"); eval("var j = 6");
+                           debugger; }, [1, 2],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 7 --- resume normal",
+    async function(a, b) { let z = await 7; var x = 3; var y = 4;
+                           eval("var i = 5;"); eval("var j = 6");
+                           let q = await 8;
+                           debugger; }, [1, 2],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6, z:7, q:8}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 7 --- resume throw",
+    async function(a, b) { let z = await 7; var x = 3; var y = 4;
+                           eval("var i = 5;"); eval("var j = 6");
+                           try { let q = await thrower(); }
+                           catch (e) { debugger; } }, [1, 2],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({e: 'Exception'}, 0, exec_state);
+      //CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6, z:7}, 1, exec_state);
+    });
+
+// Nested empty with blocks.
+await test(
+    "(AsyncFunctionExpression) With",
+    async function() { with ({}) { with ({}) { debugger; } } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.With,
+                       debug.ScopeType.With,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({}, 0, exec_state);
+      CheckScopeContent({}, 1, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) With --- resume normal",
+    async function() { let x = await 1; with ({}) { with ({}) {
+                       let y = await 2; debugger; } } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Block,
+                       debug.ScopeType.With,
+                       debug.ScopeType.With,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({y:2}, 0, exec_state);
+      CheckScopeContent({}, 1, exec_state);
+      CheckScopeContent({}, 2, exec_state);
+      CheckScopeContent({x:1}, 3, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) With --- resume throw",
+    async function() { let x = await 1; with ({}) { with ({}) {
+                       try { let y = await thrower(); }
+                       catch (e) { debugger; } } } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.With,
+                       debug.ScopeType.With,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ e: 'Exception'}, 0, exec_state);
+      CheckScopeContent({}, 1, exec_state);
+      CheckScopeContent({}, 2, exec_state);
+      CheckScopeContent({x:1}, 3, exec_state);
+    });
+
+// Simple closure formed by returning an inner function referering the outer
+// functions arguments.
+await test(
+    "(AsyncFunctionExpression) Closure 1",
+    async function(a) { return function() { debugger; return a; } }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({a:1}, 1, exec_state);
+    },
+    result => result());
+
+await test(
+    "(AsyncFunctionExpression) Closure 1 --- resume normal",
+    async function(a) { let x = await 2;
+                        return function() { debugger; return a; } }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({a:1, x: 2}, 1, exec_state);
+    },
+    result => result());
+
+await test(
+    "(AsyncFunctionExpression) Closure 1 --- resume throw",
+    async function(a) { let x = await 2;
+                        return async function() {
+                            try { await thrower(); }
+                            catch (e) { debugger; } return a; }; }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({e: 'Exception'}, 0, exec_state);
+      CheckScopeContent({a:1, x: 2}, 2, exec_state);
+    },
+    result => result());
+
+await test(
+    "(AsyncFunctionExpression) Catch block 1",
+    async function() { try { throw 'Exception'; } catch (e) { debugger; } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({e:'Exception'}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Catch block 1 --- resume normal",
+    async function() {
+      let x = await 1;
+      try { throw 'Exception'; } catch (e) { let y = await 2; debugger; } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Block,
+                       debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({y: 2}, 0, exec_state);
+      CheckScopeContent({e:'Exception'}, 1, exec_state);
+      CheckScopeContent({x: 1}, 2, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Catch block 1 --- resume throw",
+    async function() {
+      let x = await 1;
+      try { throw 'Exception!'; } catch (e) {
+        try { let y = await thrower(); } catch (e) { debugger; } } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({e:'Exception'}, 0, exec_state);
+      CheckScopeContent({e:'Exception!'}, 1, exec_state);
+      CheckScopeContent({x: 1}, 2, exec_state);
+    });
+}
+
+runTests().catch(error => {
+  print(error.stack);
+  quit(1);
+})
+
+// Check that two scope are the same.
+function assertScopeMirrorEquals(scope1, scope2) {
+  assertEquals(scope1.scopeType(), scope2.scopeType());
+  assertEquals(scope1.frameIndex(), scope2.frameIndex());
+  assertEquals(scope1.scopeIndex(), scope2.scopeIndex());
+  assertPropertiesEqual(
+      scope1.scopeObject().value(), scope2.scopeObject().value());
+}
+
+function CheckFastAllScopes(scopes, exec_state) {
+  var fast_all_scopes = exec_state.frame().allScopes(true);
+  var length = fast_all_scopes.length;
+  assertTrue(scopes.length >= length);
+  for (var i = 0; i < scopes.length && i < length; i++) {
+    var scope = fast_all_scopes[length - i - 1];
+    assertTrue(scope.isScope());
+    assertEquals(scopes[scopes.length - i - 1], scope.scopeType());
+  }
+}
+
+// Check that the scope chain contains the expected types of scopes.
+function CheckScopeChain(scopes, exec_state) {
+  var all_scopes = exec_state.frame().allScopes();
+  assertEquals(
+      scopes.length, all_scopes.length, "FrameMirror.allScopes length");
+  for (var i = 0; i < scopes.length; i++) {
+    var scope = exec_state.frame().scope(i);
+    assertTrue(scope.isScope());
+    assertEquals(scopes[i], scope.scopeType());
+    assertScopeMirrorEquals(all_scopes[i], scope);
+
+    // Check the global object when hitting the global scope.
+    if (scopes[i] == debug.ScopeType.Global) {
+      // Objects don't have same class (one is "global", other is "Object",
+      // so just check the properties directly.
+      assertPropertiesEqual(this, scope.scopeObject().value());
+    }
+  }
+  CheckFastAllScopes(scopes, exec_state);
+
+  // Get the debug command processor.
+  var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
+
+  // Send a scopes request and check the result.
+  var json;
+  var request_json = '{"seq":0,"type":"request","command":"scopes"}';
+  var response_json = dcp.processDebugJSONRequest(request_json);
+  var response = JSON.parse(response_json);
+  assertEquals(scopes.length, response.body.scopes.length);
+  for (var i = 0; i < scopes.length; i++) {
+    var scopeRef = response.body.scopes[i].object.ref;
+    assertEquals(i, response.body.scopes[i].index);
+    assertEquals(scopes[i], response.body.scopes[i].type);
+    if (scopes[i] == debug.ScopeType.Local ||
+        scopes[i] == debug.ScopeType.Script ||
+        scopes[i] == debug.ScopeType.Closure) {
+      assertTrue(response.body.scopes[i].object.ref < 0);
+    } else {
+      assertTrue(response.body.scopes[i].object.ref >= 0);
+    }
+    var found = false;
+    for (var j = 0; j < response.refs.length && !found; j++) {
+      found = response.refs[j].handle == response.body.scopes[i].object.ref;
+    }
+    assertTrue(found, `Scope object ${scopeRef} not found`);
+  }
+}
+
+// Check that the content of the scope is as expected. For functions just check
+// that there is a function.
+function CheckScopeContent(content, number, exec_state) {
+  var scope = exec_state.frame().scope(number);
+  var count = 0;
+  for (var p in content) {
+    var property_mirror = scope.scopeObject().property(p);
+    assertFalse(property_mirror.isUndefined(),
+                `property ${p} not found in scope`);
+    if (typeof(content[p]) === 'function') {
+      assertTrue(property_mirror.value().isFunction());
+    } else {
+      assertEquals(content[p], property_mirror.value().value(),
+                   `property ${p} has unexpected value`);
+    }
+    count++;
+  }
+
+  // 'arguments' and might be exposed in the local and closure scope. Just
+  // ignore this.
+  var scope_size = scope.scopeObject().properties().length;
+  if (!scope.scopeObject().property('arguments').isUndefined()) {
+    scope_size--;
+  }
+  // Skip property with empty name.
+  if (!scope.scopeObject().property('').isUndefined()) {
+    scope_size--;
+  }
+
+  if (count != scope_size) {
+    print('Names found in scope:');
+    var names = scope.scopeObject().propertyNames();
+    for (var i = 0; i < names.length; i++) {
+      print(names[i]);
+    }
+  }
+  assertEquals(count, scope_size);
+
+  // Get the debug command processor.
+  var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
+
+  // Send a scope request for information on a single scope and check the
+  // result.
+  var request_json = `{
+    "seq": 0,
+    "type": "request",
+    "command": "scope",
+    "arguments": {
+      "number": `;
+  request_json += scope.scopeIndex();
+  request_json += '}}';
+  var response_json = dcp.processDebugJSONRequest(request_json);
+  var response = JSON.parse(response_json);
+  assertEquals(scope.scopeType(), response.body.type);
+  assertEquals(number, response.body.index);
+  if (scope.scopeType() == debug.ScopeType.Local ||
+      scope.scopeType() == debug.ScopeType.Script ||
+      scope.scopeType() == debug.ScopeType.Closure) {
+    assertTrue(response.body.object.ref < 0);
+  } else {
+    assertTrue(response.body.object.ref >= 0);
+  }
+  var found = false;
+  for (var i = 0; i < response.refs.length && !found; i++) {
+    found = response.refs[i].handle == response.body.object.ref;
+  }
+  assertTrue(found, "Scope object " + response.body.object.ref + " not found");
+}
diff --git a/test/mjsunit/harmony/async-function-stacktrace.js b/test/mjsunit/harmony/async-function-stacktrace.js
new file mode 100644
index 0000000..50df44d
--- /dev/null
+++ b/test/mjsunit/harmony/async-function-stacktrace.js
@@ -0,0 +1,115 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await
+
+async function test(func, funcs) {
+  try {
+    await func();
+    throw new Error("Expected " + func.toString() + " to throw");
+  } catch (e) {
+    var stack = e.stack.split('\n').
+        slice(1).
+        map(line => line.trim()).
+        map(line => line.match(/at (?:(.*) )?.*$/)[1]).
+        filter(x => typeof x === 'string' && x.length);
+
+    assertEquals(funcs, stack, `Unexpected stack trace ${e.stack}`);
+  }
+}
+
+function thrower() { throw new Error("NOPE"); }
+function reject() { return Promise.reject(new Error("NOPE")); }
+
+async function runTests() {
+  await test(async function a() {
+    throw new Error("FAIL");
+  },
+  ["a", "test", "runTests"]);
+
+  await test(async function a2() {
+    await 1;
+    throw new Error("FAIL");
+  }, ["a2"]);
+
+  await test(async function a3() {
+    await 1;
+    try { await thrower(); } catch (e) { throw new Error("FAIL"); }
+  }, ["a3"]);
+
+  await test(async function a4() {
+    await 1;
+    try { await reject(); } catch (e) { throw new Error("FAIL"); }
+  }, ["a4"]);
+
+  await test({ async b() {
+    throw new Error("FAIL");
+  }}.b,
+  ["b", "test", "runTests"]);
+
+  await test({ async b2() {
+    await 1;
+    throw new Error("FAIL");
+  }}.b2, ["b2"]);
+
+  await test({ async b3() {
+    await 1;
+    try { await thrower(); } catch (e) { throw new Error("FAIL"); }
+  } }.b3, ["b3"]);
+
+  await test({ async b4() {
+    await 1;
+    try { await reject(); } catch (e) { throw new Error("FAIL"); }
+  } }.b4, ["b4"]);
+
+  await test((new class { async c() {
+    throw new Error("FAIL");
+  } }).c,
+  ["c", "test", "runTests"]);
+
+  await test((new class { async c2() {
+    await 1;
+    throw new Error("FAIL");
+  } }).c2, ["c2"]);
+
+  await test((new class { async c3() {
+    await 1;
+    try { await thrower(); } catch (e) { throw new Error("FAIL"); }
+  } }).c3, ["c3"]);
+
+  await test((new class { async c4() {
+    await 1;
+    try { await reject(); } catch (e) { throw new Error("FAIL"); }
+  } }).c4, ["c4"]);
+
+  // TODO(caitp): `async` probably shouldn't be the inferred name for async
+  // arrow functions...
+  await test(async() => { throw new Error("FAIL") },
+  ["async", "test", "runTests"]);
+
+  await test(async() => { await 1; throw new Error("FAIL") }, ["async"]);
+
+  await test(async() => {
+    await 1;
+    try {
+      await thrower();
+    } catch (e) {
+      throw new Error("FAIL");
+    }
+  }, ["e"]); // TODO(caitp): FuncNameInferer is doing some weird stuff...
+
+  await test(async() => {
+    await 1;
+    try {
+      await reject();
+    } catch (e) {
+      throw new Error("FAIL");
+    }
+  }, ["e"]);
+}
+
+runTests().catch(e => {
+  print(e);
+  quit(1);
+});
diff --git a/test/mjsunit/harmony/atomics.js b/test/mjsunit/harmony/atomics.js
index bf27eb4..e608df3 100644
--- a/test/mjsunit/harmony/atomics.js
+++ b/test/mjsunit/harmony/atomics.js
@@ -16,26 +16,19 @@
   return value;
 }
 
-function toRangeClamped(value) {
-  if (value < this.min) return this.min;
-  if (value > this.max) return this.max;
-  return value;
-}
-
 function makeConstructorObject(constr, min, max, toRange) {
   var o = {constr: constr, min: min, max: max};
-  o.toRange = toRange.bind(o);
+  o.toRange = toRangeWrapped.bind(o);
   return o;
 }
 
 var IntegerTypedArrayConstructors = [
-  makeConstructorObject(Int8Array, -128, 127, toRangeWrapped),
-  makeConstructorObject(Int16Array, -32768, 32767, toRangeWrapped),
-  makeConstructorObject(Int32Array, -0x80000000, 0x7fffffff, toRangeWrapped),
-  makeConstructorObject(Uint8Array, 0, 255, toRangeWrapped),
-  makeConstructorObject(Uint8ClampedArray, 0, 255, toRangeClamped),
-  makeConstructorObject(Uint16Array, 0, 65535, toRangeWrapped),
-  makeConstructorObject(Uint32Array, 0, 0xffffffff, toRangeWrapped),
+  makeConstructorObject(Int8Array, -128, 127),
+  makeConstructorObject(Int16Array, -32768, 32767),
+  makeConstructorObject(Int32Array, -0x80000000, 0x7fffffff),
+  makeConstructorObject(Uint8Array, 0, 255),
+  makeConstructorObject(Uint16Array, 0, 65535),
+  makeConstructorObject(Uint32Array, 0, 0xffffffff),
 ];
 
 (function TestBadArray() {
@@ -44,9 +37,13 @@
   var sab = new SharedArrayBuffer(128);
   var sf32a = new Float32Array(sab);
   var sf64a = new Float64Array(sab);
+  var u8ca = new Uint8ClampedArray(sab);
 
   // Atomic ops required integer shared typed arrays
-  [undefined, 1, 'hi', 3.4, ab, u32a, sab, sf32a, sf64a].forEach(function(o) {
+  var badArrayTypes = [
+    undefined, 1, 'hi', 3.4, ab, u32a, sab, sf32a, sf64a, u8ca
+  ];
+  badArrayTypes.forEach(function(o) {
     assertThrows(function() { Atomics.compareExchange(o, 0, 0, 0); },
                  TypeError);
     assertThrows(function() { Atomics.load(o, 0); }, TypeError);
@@ -129,15 +126,16 @@
 
   var testOp = function(op, ia, index, expectedIndex, name) {
     for (var i = 0; i < ia.length; ++i)
-      ia[i] = 22;
+      ia[i] = i * 2;
 
     ia[expectedIndex] = 0;
-    assertEquals(0, op(ia, index, 0, 0), name);
+    var result = op(ia, index, 0, 0);
+    assertEquals(0, result, name);
     assertEquals(0, ia[expectedIndex], name);
 
     for (var i = 0; i < ia.length; ++i) {
       if (i == expectedIndex) continue;
-      assertEquals(22, ia[i], name);
+      assertEquals(i * 2, ia[i], name);
     }
   };
 
@@ -222,6 +220,24 @@
       }
     })
   });
+
+  // Test Smi range
+  (function () {
+    var sab = new SharedArrayBuffer(4);
+    var i32 = new Int32Array(sab);
+    var u32 = new Uint32Array(sab);
+
+    function testLoad(signedValue, unsignedValue) {
+      u32[0] = unsignedValue;
+      assertEquals(unsignedValue, Atomics.load(u32, 0));
+      assertEquals(signedValue, Atomics.load(i32, 0));
+    }
+
+    testLoad(0x3fffffff,  0x3fffffff); // 2**30-1 (always smi)
+    testLoad(0x40000000,  0x40000000); // 2**30 (smi if signed and 32-bits)
+    testLoad(0x80000000, -0x80000000); // 2**31 (smi if signed and 32-bits)
+    testLoad(0xffffffff, -1);          // 2**31 (smi if signed)
+  });
 })();
 
 (function TestStore() {
@@ -405,7 +421,7 @@
       assertEquals(50, Atomics.compareExchange(sta, 0, v, v), name);
 
       // Store
-      assertEquals(+v, Atomics.store(sta, 0, v), name);
+      assertEquals(v|0, Atomics.store(sta, 0, v), name);
       assertEquals(v|0, sta[0], name);
 
       // Add
diff --git a/test/mjsunit/harmony/block-conflicts-sloppy.js b/test/mjsunit/harmony/block-conflicts-sloppy.js
deleted file mode 100644
index 8908ce4..0000000
--- a/test/mjsunit/harmony/block-conflicts-sloppy.js
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Test for conflicting variable bindings.
-
-// Flags: --harmony-sloppy --harmony-sloppy-let --harmony-sloppy-function
-
-function CheckException(e) {
-  var string = e.toString();
-  assertTrue(string.indexOf("has already been declared") >= 0 ||
-             string.indexOf("redeclaration") >= 0);
-  return 'Conflict';
-}
-
-
-function TestGlobal(s,e) {
-  try {
-    return eval(s + e);
-  } catch (x) {
-    return CheckException(x);
-  }
-}
-
-
-function TestFunction(s,e) {
-  try {
-    return eval("(function(){" + s + " return " + e + "})")();
-  } catch (x) {
-    return CheckException(x);
-  }
-}
-
-
-function TestBlock(s,e) {
-  try {
-    return eval("(function(){ {" + s + "} return " + e + "})")();
-  } catch (x) {
-    return CheckException(x);
-  }
-}
-
-function TestAll(expected,s,opt_e) {
-  var e = "";
-  var msg = s;
-  if (opt_e) { e = opt_e; msg += opt_e; }
-  // TODO(littledan): Add tests using Realm.eval to ensure that global eval
-  // works as expected.
-  assertEquals(expected === 'LocalConflict' ? 'NoConflict' : expected,
-      TestGlobal(s,e), "global:'" + msg + "'");
-  assertEquals(expected === 'LocalConflict' ? 'NoConflict' : expected,
-      TestFunction(s,e), "function:'" + msg + "'");
-  assertEquals(expected === 'LocalConflict' ? 'Conflict' : expected,
-      TestBlock(s,e), "block:'" + msg + "'");
-}
-
-
-function TestConflict(s) {
-  TestAll('Conflict', s);
-  TestAll('Conflict', 'eval("' + s + '");');
-}
-
-function TestNoConflict(s) {
-  TestAll('NoConflict', s, "'NoConflict'");
-  TestAll('NoConflict', 'eval("' + s + '");', "'NoConflict'");
-}
-
-function TestLocalConflict(s) {
-  TestAll('LocalConflict', s, "'NoConflict'");
-  TestAll('NoConflict', 'eval("' + s + '");', "'NoConflict'");
-}
-
-var letbinds = [ "let x;",
-                 "let x = 0;",
-                 "let x = undefined;",
-                 "let x = function() {};",
-                 "let x, y;",
-                 "let y, x;",
-                 "const x = 0;",
-                 "const x = undefined;",
-                 "const x = function() {};",
-                 "const x = 2, y = 3;",
-                 "const y = 4, x = 5;",
-                 "class x { }",
-                 ];
-function forCompatible(bind) {
-  return !bind.startsWith('class');
-}
-var varbinds = [ "var x;",
-                 "var x = 0;",
-                 "var x = undefined;",
-                 "var x = function() {};",
-                 "var x, y;",
-                 "var y, x;",
-                 ];
-var funbind = "function x() {}";
-
-for (var l = 0; l < letbinds.length; ++l) {
-  // Test conflicting let/var bindings.
-  for (var v = 0; v < varbinds.length; ++v) {
-    // Same level.
-    TestConflict(letbinds[l] + varbinds[v]);
-    TestConflict(varbinds[v] + letbinds[l]);
-    // Different level.
-    TestConflict(letbinds[l] + '{' + varbinds[v] + '}');
-    TestConflict('{' + varbinds[v] +'}' + letbinds[l]);
-    TestNoConflict(varbinds[v] + '{' + letbinds[l] + '}');
-    TestNoConflict('{' + letbinds[l] + '}' + varbinds[v]);
-    // For loop.
-    if (forCompatible(letbinds[l])) {
-      TestConflict('for (' + letbinds[l] + '0;) {' + varbinds[v] + '}');
-    }
-    TestNoConflict('for (' + varbinds[v] + '0;) {' + letbinds[l] + '}');
-  }
-
-  // Test conflicting let/let bindings.
-  for (var k = 0; k < letbinds.length; ++k) {
-    // Same level.
-    TestConflict(letbinds[l] + letbinds[k]);
-    TestConflict(letbinds[k] + letbinds[l]);
-    // Different level.
-    TestNoConflict(letbinds[l] + '{ ' + letbinds[k] + '}');
-    TestNoConflict('{' + letbinds[k] +'} ' + letbinds[l]);
-    // For loop.
-    if (forCompatible(letbinds[l])) {
-      TestNoConflict('for (' + letbinds[l] + '0;) {' + letbinds[k] + '}');
-    }
-    if (forCompatible(letbinds[k])) {
-      TestNoConflict('for (' + letbinds[k] + '0;) {' + letbinds[l] + '}');
-    }
-  }
-
-  // Test conflicting function/let bindings.
-  // Same level.
-  TestConflict(letbinds[l] + funbind);
-  TestConflict(funbind + letbinds[l]);
-  // Different level.
-  TestNoConflict(letbinds[l] + '{' + funbind + '}');
-  TestNoConflict('{' + funbind + '}' + letbinds[l]);
-  TestNoConflict(funbind + '{' + letbinds[l] + '}');
-  TestNoConflict('{' + letbinds[l] + '}' + funbind);
-  // For loop.
-  if (forCompatible(letbinds[l])) {
-    TestNoConflict('for (' + letbinds[l] + '0;) {' + funbind + '}');
-  }
-
-  // Test conflicting parameter/let bindings.
-  TestConflict('(function(x) {' + letbinds[l] + '})();');
-}
-
-// Test conflicting function/var bindings.
-for (var v = 0; v < varbinds.length; ++v) {
-  // Same level.
-  TestLocalConflict(varbinds[v] + funbind);
-  TestLocalConflict(funbind + varbinds[v]);
-  // Different level.
-  TestLocalConflict(funbind + '{' + varbinds[v] + '}');
-  TestLocalConflict('{' + varbinds[v] +'}' + funbind);
-  TestNoConflict(varbinds[v] + '{' + funbind + '}');
-  TestNoConflict('{' + funbind + '}' + varbinds[v]);
-  // For loop.
-  TestNoConflict('for (' + varbinds[v] + '0;) {' + funbind + '}');
-}
-
-// Test conflicting catch/var bindings.
-for (var v = 0; v < varbinds.length; ++v) {
-  TestNoConflict('try {} catch(x) {' + varbinds[v] + '}');
-}
-
-// Test conflicting parameter/var bindings.
-for (var v = 0; v < varbinds.length; ++v) {
-  TestNoConflict('(function (x) {' + varbinds[v] + '})();');
-}
-
-// Test conflicting catch/function bindings.
-TestNoConflict('try {} catch(x) {' + funbind + '}');
-
-// Test conflicting parameter/function bindings.
-TestNoConflict('(function (x) {' + funbind + '})();');
diff --git a/test/mjsunit/harmony/block-const-assign-sloppy.js b/test/mjsunit/harmony/block-const-assign-sloppy.js
deleted file mode 100644
index 5dde82c..0000000
--- a/test/mjsunit/harmony/block-const-assign-sloppy.js
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --harmony-sloppy --harmony-sloppy-let
-
-// Test that we throw early syntax errors in harmony mode
-// when using an immutable binding in an assigment or with
-// prefix/postfix decrement/increment operators.
-
-const decls = [
-  // Const declaration.
-  function(use) { return "const c = 1; " + use + ";" }, TypeError,
-  function(use) { return "const x = 0, c = 1; " + use + ";" }, TypeError,
-  function(use) { return "const c = 1, x = (" + use + ");" }, TypeError,
-  function(use) { return use + "; const c = 1;" }, ReferenceError,
-  function(use) { return use + "; const x = 0, c = 1;" }, ReferenceError,
-  function(use) { return "const x = (" + use + "), c = 1;" }, ReferenceError,
-  function(use) { return "const c = (" + use + ");" }, ReferenceError,
-
-  // Function expression.
-  function(use) { return "(function c() { " + use + "; })();"; }, TypeError,
-  // TODO(rossberg): Once we have default parameters, test using 'c' there.
-
-  // Class expression.
-  function(use) {
-    return "new class c { constructor() { " + use + " } };";
-  }, TypeError,
-  function(use) {
-    return "(new class c { m() { " + use + " } }).m();";
-  }, TypeError,
-  function(use) {
-    return "(new class c { get a() { " + use + " } }).a;";
-  }, TypeError,
-  function(use) {
-    return "(new class c { set a(x) { " + use + " } }).a = 0;";
-  }, TypeError,
-  function(use) {
-    return "(class c { static m() { " + use + " } }).s();";
-  }, TypeError,
-  function(use) {
-    return "(class c extends (" + use + ") {});";
-  }, ReferenceError,
-  function(use) {
-    return "(class c { [" + use + "]() {} });";
-  }, ReferenceError,
-  function(use) {
-    return "(class c { get [" + use + "]() {} });";
-  }, ReferenceError,
-  function(use) {
-    return "(class c { set [" + use + "](x) {} });";
-  }, ReferenceError,
-  function(use) {
-    return "(class c { static [" + use + "]() {} });";
-  }, ReferenceError,
-
-  // For loop.
-  function(use) {
-    return "for (const c = 0; " + use + ";) {}"
-  }, TypeError,
-  function(use) {
-    return "for (const x = 0, c = 0; " + use + ";) {}"
-  }, TypeError,
-  function(use) {
-    return "for (const c = 0; ; " + use + ") {}"
-  }, TypeError,
-  function(use) {
-    return "for (const x = 0, c = 0; ; " + use + ") {}"
-  }, TypeError,
-  function(use) {
-    return "for (const c = 0; ;) { " + use + "; }"
-  }, TypeError,
-  function(use) {
-    return "for (const x = 0, c = 0; ;) { " + use + "; }"
-  }, TypeError,
-  function(use) {
-    return "for (const c in {a: 1}) { " + use + "; }"
-  }, TypeError,
-  function(use) {
-    return "for (const c of [1]) { " + use + "; }"
-  }, TypeError,
-  function(use) {
-    return "for (const x = (" + use + "), c = 0; ;) {}"
-  }, ReferenceError,
-  function(use) {
-    return "for (const c = (" + use + "); ;) {}"
-  }, ReferenceError,
-]
-
-let uses = [
-  'c = 1',
-  'c += 1',
-  '++c',
-  'c--',
-];
-
-let declcontexts = [
-  function(decl) { return decl; },
-  function(decl) { return "eval(\'" + decl + "\')"; },
-  function(decl) { return "{ " + decl + " }"; },
-  function(decl) { return "(function() { " + decl + " })()"; },
-];
-
-let usecontexts = [
-  function(use) { return use; },
-  function(use) { return "eval(\"" + use + "\")"; },
-  function(use) { return "(function() { " + use + " })()"; },
-  function(use) { return "(function() { eval(\"" + use + "\"); })()"; },
-  function(use) { return "eval(\"(function() { " + use + "; })\")()"; },
-];
-
-function Test(program, error) {
-  program = "'use strict'; " + program;
-  try {
-    print(program, "  // throw " + error.name);
-    eval(program);
-  } catch (e) {
-    assertInstanceof(e, error);
-    if (e === TypeError) {
-      assertTrue(e.toString().indexOf("Assignment to constant variable") >= 0);
-    }
-    return;
-  }
-  assertUnreachable();
-}
-
-for (var d = 0; d < decls.length; d += 2) {
-  for (var u = 0; u < uses.length; ++u) {
-    for (var o = 0; o < declcontexts.length; ++o) {
-      for (var i = 0; i < usecontexts.length; ++i) {
-        Test(declcontexts[o](decls[d](usecontexts[i](uses[u]))), decls[d + 1]);
-      }
-    }
-  }
-}
diff --git a/test/mjsunit/harmony/block-eval-var-over-let.js b/test/mjsunit/harmony/block-eval-var-over-let.js
deleted file mode 100644
index 98091b4..0000000
--- a/test/mjsunit/harmony/block-eval-var-over-let.js
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-sloppy --harmony-sloppy-let --harmony-sloppy-function
-
-// Var-let conflict in a function throws, even if the var is in an eval
-
-// Throws at the top level of a function
-assertThrows(function() {
-  let x = 1;
-  eval('var x');
-}, TypeError);
-
-// If the eval is in its own block scope, throws
-assertThrows(function() {
-  let y = 1;
-  { eval('var y'); }
-}, TypeError);
-
-// If the let is in its own block scope, with the eval, throws
-assertThrows(function() {
-  {
-    let x = 1;
-    eval('var x');
-  }
-}, TypeError);
-
-// Legal if the let is no longer visible
-assertDoesNotThrow(function() {
-  {
-    let x = 1;
-  }
-  eval('var x');
-});
-
-// All the same works for const:
-// Throws at the top level of a function
-assertThrows(function() {
-  const x = 1;
-  eval('var x');
-}, TypeError);
-
-// If the eval is in its own block scope, throws
-assertThrows(function() {
-  const y = 1;
-  { eval('var y'); }
-}, TypeError);
-
-// If the const is in its own block scope, with the eval, throws
-assertThrows(function() {
-  {
-    const x = 1;
-    eval('var x');
-  }
-}, TypeError);
-
-// Legal if the const is no longer visible
-assertDoesNotThrow(function() {
-  {
-    const x = 1;
-  }
-  eval('var x');
-});
-
-// In global scope
-let caught = false;
-try {
-  let z = 1;
-  eval('var z');
-} catch (e) {
-  caught = true;
-}
-assertTrue(caught);
-
-// Let declarations beyond a function boundary don't conflict
-caught = false;
-try {
-  let a = 1;
-  (function() {
-    eval('var a');
-  })();
-} catch (e) {
-  caught = true;
-}
-assertFalse(caught);
-
-// var across with doesn't conflict
-caught = false;
-try {
-  (function() {
-    with ({x: 1}) {
-      eval("var x");
-    }
-  })();
-} catch (e) {
-  caught = true;
-}
-assertFalse(caught);
-
-// var can still conflict with let across a with
-caught = false;
-try {
-  (function() {
-    let x;
-    with ({x: 1}) {
-      eval("var x");
-    }
-  })();
-} catch (e) {
-  caught = true;
-}
-assertTrue(caught);
-
-// Functions declared in eval also conflict
-caught = false
-try {
-  (function() {
-    {
-      let x = 1;
-      eval('function x() {}');
-    }
-  })();
-} catch (e) {
-  caught = true;
-}
-assertTrue(caught);
-
-// TODO(littledan): Hoisting x out of the block should be
-// prevented in this case BUG(v8:4479)
-caught = false
-try {
-  (function() {
-    {
-      let x = 1;
-      eval('{ function x() {} }');
-    }
-  })();
-} catch (e) {
-  caught = true;
-}
-// TODO(littledan): switch to assertTrue when bug is fixed
-assertTrue(caught);
diff --git a/test/mjsunit/harmony/block-for-sloppy.js b/test/mjsunit/harmony/block-for-sloppy.js
deleted file mode 100644
index 261c46a..0000000
--- a/test/mjsunit/harmony/block-for-sloppy.js
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --harmony-sloppy --harmony-sloppy-let
-
-function props(x) {
-  var array = [];
-  for (let p in x) array.push(p);
-  return array.sort();
-}
-
-assertEquals(0, props({}).length);
-assertEquals(1, props({x:1}).length);
-assertEquals(2, props({x:1, y:2}).length);
-
-assertArrayEquals(["x"], props({x:1}));
-assertArrayEquals(["x", "y"], props({x:1, y:2}));
-assertArrayEquals(["x", "y", "zoom"], props({x:1, y:2, zoom:3}));
-
-assertEquals(0, props([]).length);
-assertEquals(1, props([1]).length);
-assertEquals(2, props([1,2]).length);
-
-assertArrayEquals(["0"], props([1]));
-assertArrayEquals(["0", "1"], props([1,2]));
-assertArrayEquals(["0", "1", "2"], props([1,2,3]));
-
-var o = {};
-var a = [];
-let i = "outer_i";
-let s = "outer_s";
-for (let i = 0x0020; i < 0x01ff; i+=2) {
-  let s = 'char:' + String.fromCharCode(i);
-  a.push(s);
-  o[s] = i;
-}
-assertArrayEquals(a, props(o));
-assertEquals(i, "outer_i");
-assertEquals(s, "outer_s");
-
-var a = [];
-assertEquals(0, props(a).length);
-a[Math.pow(2,30)-1] = 0;
-assertEquals(1, props(a).length);
-a[Math.pow(2,31)-1] = 0;
-assertEquals(2, props(a).length);
-a[1] = 0;
-assertEquals(3, props(a).length);
-
-var result = '';
-for (let p in {a : [0], b : 1}) { result += p; }
-assertEquals('ab', result);
-
-var result = '';
-for (let p in {a : {v:1}, b : 1}) { result += p; }
-assertEquals('ab', result);
-
-var result = '';
-for (let p in { get a() {}, b : 1}) { result += p; }
-assertEquals('ab', result);
-
-var result = '';
-for (let p in { get a() {}, set a(x) {}, b : 1}) { result += p; }
-assertEquals('ab', result);
-
-
-// Check that there is exactly one variable without initializer
-// in a for-in statement with let variables.
-assertThrows("function foo() { 'use strict'; for (let in {}) { } }", SyntaxError);
-assertThrows("function foo() { 'use strict'; for (let x = 3 in {}) { } }", SyntaxError);
-assertThrows("function foo() { 'use strict'; for (let x, y in {}) { } }", SyntaxError);
-assertThrows("function foo() { 'use strict'; for (let x = 3, y in {}) { } }", SyntaxError);
-assertThrows("function foo() { 'use strict'; for (let x, y = 4 in {}) { } }", SyntaxError);
-assertThrows("function foo() { 'use strict'; for (let x = 3, y = 4 in {}) { } }", SyntaxError);
-
-
-// In a normal for statement the iteration variable is
-// freshly allocated for each iteration.
-function closures1() {
-  let a = [];
-  for (let i = 0; i < 5; ++i) {
-    a.push(function () { return i; });
-  }
-  for (let j = 0; j < 5; ++j) {
-    assertEquals(j, a[j]());
-  }
-}
-closures1();
-
-
-function closures2() {
-  let a = [], b = [];
-  for (let i = 0, j = 10; i < 5; ++i, ++j) {
-    a.push(function () { return i; });
-    b.push(function () { return j; });
-  }
-  for (let k = 0; k < 5; ++k) {
-    assertEquals(k, a[k]());
-    assertEquals(k + 10, b[k]());
-  }
-}
-closures2();
-
-
-function closure_in_for_init() {
-  let a = [];
-  for (let i = 0, f = function() { return i }; i < 5; ++i) {
-    a.push(f);
-  }
-  for (let k = 0; k < 5; ++k) {
-    assertEquals(0, a[k]());
-  }
-}
-closure_in_for_init();
-
-
-function closure_in_for_cond() {
-  let a = [];
-  for (let i = 0; a.push(function () { return i; }), i < 5; ++i) { }
-  for (let k = 0; k < 5; ++k) {
-    assertEquals(k, a[k]());
-  }
-}
-closure_in_for_cond();
-
-
-function closure_in_for_next() {
-  let a = [];
-  for (let i = 0; i < 5; a.push(function () { return i; }), ++i) { }
-  for (let k = 0; k < 5; ++k) {
-    assertEquals(k + 1, a[k]());
-  }
-}
-closure_in_for_next();
-
-
-// In a for-in statement the iteration variable is fresh
-// for each iteration.
-function closures3(x) {
-  let a = [];
-  for (let p in x) {
-    a.push(function () { return p; });
-  }
-  let k = 0;
-  for (let q in x) {
-    assertEquals(q, a[k]());
-    ++k;
-  }
-}
-closures3({a : [0], b : 1, c : {v : 1}, get d() {}, set e(x) {}});
-
-// Check normal for statement completion values.
-assertEquals(1, eval("for (let i = 0; i < 10; i++) { 1; }"));
-assertEquals(9, eval("for (let i = 0; i < 10; i++) { i; }"));
-assertEquals(undefined, eval("for (let i = 0; false;) { }"));
-assertEquals(undefined, eval("for (const i = 0; false;) { }"));
-assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { }"));
-assertEquals(undefined, eval("for (let i = 0; false;) { i; }"));
-assertEquals(undefined, eval("for (const i = 0; false;) { i; }"));
-assertEquals(undefined, eval("for (let i = 0; true;) { break; }"));
-assertEquals(undefined, eval("for (const i = 0; true;) { break; }"));
-assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { continue; }"));
-assertEquals(undefined, eval("for (let i = 0; true;) { break; i; }"));
-assertEquals(undefined, eval("for (const i = 0; true;) { break; i; }"));
-assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { continue; i; }"));
-assertEquals(0, eval("for (let i = 0; true;) { i; break; }"));
-assertEquals(0, eval("for (const i = 0; true;) { i; break; }"));
-assertEquals(9, eval("for (let i = 0; i < 10; i++) { i; continue; }"));
-assertEquals(
-  undefined, eval("for (let i = 0; true; i++) { i; if (i >= 3) break; }"));
-assertEquals(
-  undefined, eval("for (let i = 0; true; i++) { if (i >= 3) break; i; }"));
-assertEquals(
-  undefined, eval("for (let i = 0; i < 10; i++) { if (i >= 3) continue; i; }"));
-assertEquals(undefined, eval("foo: for (let i = 0; true;) { break foo; }"));
-assertEquals(undefined, eval("foo: for (const i = 0; true;) { break foo; }"));
-assertEquals(3, eval("foo: for (let i = 3; true;) { i; break foo; }"));
diff --git a/test/mjsunit/harmony/block-leave-sloppy.js b/test/mjsunit/harmony/block-leave-sloppy.js
deleted file mode 100644
index 0023fa0..0000000
--- a/test/mjsunit/harmony/block-leave-sloppy.js
+++ /dev/null
@@ -1,224 +0,0 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --harmony-sloppy --harmony-sloppy-let
-
-// We want to test the context chain shape.  In each of the tests cases
-// below, the outer with is to force a runtime lookup of the identifier 'x'
-// to actually verify that the inner context has been discarded.  A static
-// lookup of 'x' might accidentally succeed.
-
-{
-  let x = 2;
-  L: {
-    let x = 3;
-    assertEquals(3, x);
-    break L;
-    assertTrue(false);
-  }
-  assertEquals(2, x);
-}
-
-do {
-  let x = 4;
-  assertEquals(4,x);
-  {
-    let x = 5;
-    assertEquals(5, x);
-    continue;
-    assertTrue(false);
-  }
-} while (false);
-
-var caught = false;
-try {
-  {
-    let xx = 18;
-    throw 25;
-    assertTrue(false);
-  }
-} catch (e) {
-  caught = true;
-  assertEquals(25, e);
-  (function () {
-    try {
-      // NOTE: This checks that the block scope containing xx has been
-      // removed from the context chain.
-      eval('xx');
-      assertTrue(false);  // should not reach here
-    } catch (e2) {
-      assertTrue(e2 instanceof ReferenceError);
-    }
-  })();
-}
-assertTrue(caught);
-
-
-(function(x) {
-  label: {
-    let x = 'inner';
-    break label;
-  }
-  assertEquals('outer', eval('x'));
-})('outer');
-
-
-(function(x) {
-  label: {
-    let x = 'middle';
-    {
-      let x = 'inner';
-      break label;
-    }
-  }
-  assertEquals('outer', eval('x'));
-})('outer');
-
-
-(function(x) {
-  for (var i = 0; i < 10; ++i) {
-    let x = 'inner' + i;
-    continue;
-  }
-  assertEquals('outer', eval('x'));
-})('outer');
-
-
-(function(x) {
-  label: for (var i = 0; i < 10; ++i) {
-    let x = 'middle' + i;
-    for (var j = 0; j < 10; ++j) {
-      let x = 'inner' + j;
-      continue label;
-    }
-  }
-  assertEquals('outer', eval('x'));
-})('outer');
-
-
-(function(x) {
-  try {
-    let x = 'inner';
-    throw 0;
-  } catch (e) {
-    assertEquals('outer', eval('x'));
-  }
-})('outer');
-
-
-(function(x) {
-  try {
-    let x = 'middle';
-    {
-      let x = 'inner';
-      throw 0;
-    }
-  } catch (e) {
-    assertEquals('outer', eval('x'));
-  }
-})('outer');
-
-
-try {
-  (function(x) {
-    try {
-      let x = 'inner';
-      throw 0;
-    } finally {
-      assertEquals('outer', eval('x'));
-    }
-  })('outer');
-} catch (e) {
-  if (e instanceof MjsUnitAssertionError) throw e;
-}
-
-
-try {
-  (function(x) {
-    try {
-      let x = 'middle';
-      {
-        let x = 'inner';
-        throw 0;
-      }
-    } finally {
-      assertEquals('outer', eval('x'));
-    }
-  })('outer');
-} catch (e) {
-  if (e instanceof MjsUnitAssertionError) throw e;
-}
-
-
-// Verify that the context is correctly set in the stack frame after exiting
-// from eval.
-function f() {}
-
-(function(x) {
-  label: {
-    let x = 'inner';
-    break label;
-  }
-  f();  // The context could be restored from the stack after the call.
-  assertEquals('outer', eval('x'));
-})('outer');
-
-
-(function(x) {
-  for (var i = 0; i < 10; ++i) {
-    let x = 'inner';
-    continue;
-  }
-  f();
-  assertEquals('outer', eval('x'));
-})('outer');
-
-
-(function(x) {
-  try {
-    let x = 'inner';
-    throw 0;
-  } catch (e) {
-    f();
-    assertEquals('outer', eval('x'));
-  }
-})('outer');
-
-
-try {
-  (function(x) {
-    try {
-      let x = 'inner';
-      throw 0;
-    } finally {
-      f();
-      assertEquals('outer', eval('x'));
-    }
-  })('outer');
-} catch (e) {
-  if (e instanceof MjsUnitAssertionError) throw e;
-}
diff --git a/test/mjsunit/harmony/block-let-crankshaft-sloppy.js b/test/mjsunit/harmony/block-let-crankshaft-sloppy.js
deleted file mode 100644
index 4f29c05..0000000
--- a/test/mjsunit/harmony/block-let-crankshaft-sloppy.js
+++ /dev/null
@@ -1,483 +0,0 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --allow-natives-syntax
-// Flags: --harmony-sloppy --harmony-sloppy-let
-
-// Check that the following functions are optimizable.
-var functions = [ f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14,
-                  f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26,
-                  f27, f28, f29, f30, f31, f32, f33];
-
-for (var i = 0; i < functions.length; ++i) {
-  var func = functions[i];
-  print("Testing:");
-  print(func);
-  for (var j = 0; j < 10; ++j) {
-    func(12);
-  }
-  %OptimizeFunctionOnNextCall(func);
-  func(12);
-  assertOptimized(func);
-}
-
-function f1() { }
-
-function f2(x) { }
-
-function f3() {
-  let x;
-}
-
-function f4() {
-  function foo() {
-  }
-}
-
-function f5() {
-  let x = 1;
-}
-
-function f6() {
-  const x = 1;
-}
-
-function f7(x) {
-  return x;
-}
-
-function f8() {
-  let x;
-  return x;
-}
-
-function f9() {
-  function x() {
-  }
-  return x;
-}
-
-function f10(x) {
-  x = 1;
-}
-
-function f11() {
-  let x;
-  x = 1;
-}
-
-function f12() {
-  function x() {};
-  x = 1;
-}
-
-function f13(x) {
-  (function() { x; });
-}
-
-function f14() {
-  let x;
-  (function() { x; });
-}
-
-function f15() {
-  function x() {
-  }
-  (function() { x; });
-}
-
-function f16() {
-  let x = 1;
-  (function() { x; });
-}
-
-function f17() {
-  const x = 1;
-  (function() { x; });
-}
-
-function f18(x) {
-  return x;
-  (function() { x; });
-}
-
-function f19() {
-  let x;
-  return x;
-  (function() { x; });
-}
-
-function f20() {
-  function x() {
-  }
-  return x;
-  (function() { x; });
-}
-
-function f21(x) {
-  x = 1;
-  (function() { x; });
-}
-
-function f22() {
-  let x;
-  x = 1;
-  (function() { x; });
-}
-
-function f23() {
-  function x() { }
-  x = 1;
-  (function() { x; });
-}
-
-function f24() {
-  let x = 1;
-  {
-    let x = 2;
-    {
-      let x = 3;
-      assertEquals(3, x);
-    }
-    assertEquals(2, x);
-  }
-  assertEquals(1, x);
-}
-
-function f25() {
-  {
-    let x = 2;
-    L: {
-      let x = 3;
-      assertEquals(3, x);
-      break L;
-      assertTrue(false);
-    }
-    assertEquals(2, x);
-  }
-  assertTrue(true);
-}
-
-function f26() {
-  {
-    let x = 1;
-    L: {
-      let x = 2;
-      {
-        let x = 3;
-        assertEquals(3, x);
-        break L;
-        assertTrue(false);
-      }
-      assertTrue(false);
-    }
-    assertEquals(1, x);
-  }
-}
-
-
-function f27() {
-  do {
-    let x = 4;
-    assertEquals(4,x);
-    {
-      let x = 5;
-      assertEquals(5, x);
-      continue;
-      assertTrue(false);
-    }
-  } while (false);
-}
-
-function f28() {
-  label: for (var i = 0; i < 10; ++i) {
-    let x = 'middle' + i;
-    for (var j = 0; j < 10; ++j) {
-      let x = 'inner' + j;
-      continue label;
-    }
-  }
-}
-
-function f29() {
-  // Verify that the context is correctly set in the stack frame after exiting
-  // from with.
-
-  let x = 'outer';
-  label: {
-    let x = 'inner';
-    break label;
-  }
-  f();  // The context could be restored from the stack after the call.
-  assertEquals('outer', x);
-
-  function f() {
-    assertEquals('outer', x);
-  };
-}
-
-function f30() {
-  let x = 'outer';
-  for (var i = 0; i < 10; ++i) {
-    let x = 'inner';
-    continue;
-  }
-  f();
-  assertEquals('outer', x);
-
-  function f() {
-    assertEquals('outer', x);
-  };
-}
-
-function f31() {
-  {
-    let x = 'outer';
-    label: for (var i = 0; assertEquals('outer', x), i < 10; ++i) {
-      let x = 'middle' + i;
-      {
-        let x = 'inner' + j;
-        continue label;
-      }
-    }
-    assertEquals('outer', x);
-  }
-}
-
-var c = true;
-
-function f32() {
-  {
-    let x = 'outer';
-    L: {
-      {
-        let x = 'inner';
-        if (c) {
-          break L;
-        }
-      }
-      foo();
-    }
-  }
-
-  function foo() {
-    return 'bar';
-  }
-}
-
-function f33() {
-  {
-    let x = 'outer';
-    L: {
-      {
-        let x = 'inner';
-        if (c) {
-          break L;
-        }
-        foo();
-      }
-    }
-  }
-
-  function foo() {
-    return 'bar';
-  }
-}
-
-function TestThrow() {
-  function f() {
-    let x = 'outer';
-    {
-      let x = 'inner';
-      throw x;
-    }
-  }
-  for (var i = 0; i < 5; i++) {
-    try {
-      f();
-    } catch (e) {
-      assertEquals('inner', e);
-    }
-  }
-  %OptimizeFunctionOnNextCall(f);
-  try {
-    f();
-  } catch (e) {
-    assertEquals('inner', e);
-  }
-  assertOptimized(f);
-}
-
-TestThrow();
-
-// Test that temporal dead zone semantics for function and block scoped
-// let bindings are handled by the optimizing compiler.
-
-function TestFunctionLocal(s) {
-  'use strict';
-  var func = eval("(function baz(){" + s + "; })");
-  print("Testing:");
-  print(func);
-  for (var i = 0; i < 5; ++i) {
-    try {
-      func();
-      assertUnreachable();
-    } catch (e) {
-      assertInstanceof(e, ReferenceError);
-    }
-  }
-  %OptimizeFunctionOnNextCall(func);
-  try {
-    func();
-    assertUnreachable();
-  } catch (e) {
-    assertInstanceof(e, ReferenceError);
-  }
-}
-
-function TestFunctionContext(s) {
-  'use strict';
-  var func = eval("(function baz(){ " + s + "; (function() { x; }); })");
-  print("Testing:");
-  print(func);
-  for (var i = 0; i < 5; ++i) {
-    print(i);
-    try {
-      func();
-      assertUnreachable();
-    } catch (e) {
-      assertInstanceof(e, ReferenceError);
-    }
-  }
-  print("optimize");
-  %OptimizeFunctionOnNextCall(func);
-  try {
-    print("call");
-    func();
-    assertUnreachable();
-  } catch (e) {
-    print("catch");
-    assertInstanceof(e, ReferenceError);
-  }
-}
-
-function TestBlockLocal(s) {
-  'use strict';
-  var func = eval("(function baz(){ { " + s + "; } })");
-  print("Testing:");
-  print(func);
-  for (var i = 0; i < 5; ++i) {
-    try {
-      func();
-      assertUnreachable();
-    } catch (e) {
-      assertInstanceof(e, ReferenceError);
-    }
-  }
-  %OptimizeFunctionOnNextCall(func);
-  try {
-    func();
-    assertUnreachable();
-  } catch (e) {
-    assertInstanceof(e, ReferenceError);
-  }
-}
-
-function TestBlockContext(s) {
-  'use strict';
-  var func = eval("(function baz(){ { " + s + "; (function() { x; }); } })");
-  print("Testing:");
-  print(func);
-  for (var i = 0; i < 5; ++i) {
-    print(i);
-    try {
-      func();
-      assertUnreachable();
-    } catch (e) {
-      assertInstanceof(e, ReferenceError);
-    }
-  }
-  print("optimize");
-  %OptimizeFunctionOnNextCall(func);
-  try {
-    print("call");
-    func();
-    assertUnreachable();
-  } catch (e) {
-    print("catch");
-    assertInstanceof(e, ReferenceError);
-  }
-}
-
-function TestAll(s) {
-  TestFunctionLocal(s);
-  TestFunctionContext(s);
-  TestBlockLocal(s);
-  TestBlockContext(s);
-}
-
-// Use before initialization in declaration statement.
-TestAll('let x = x + 1');
-TestAll('let x = x += 1');
-TestAll('let x = x++');
-TestAll('let x = ++x');
-TestAll('const x = x + 1');
-
-// Use before initialization in prior statement.
-TestAll('x + 1; let x;');
-TestAll('x = 1; let x;');
-TestAll('x += 1; let x;');
-TestAll('++x; let x;');
-TestAll('x++; let x;');
-TestAll('let y = x; const x = 1;');
-
-
-function f(x) {
-  let y = x + 42;
-  return y;
-}
-
-function g(x) {
-  {
-    let y = x + 42;
-    return y;
-  }
-}
-
-for (var i=0; i<10; i++) {
-  f(i);
-  g(i);
-}
-
-%OptimizeFunctionOnNextCall(f);
-%OptimizeFunctionOnNextCall(g);
-
-f(12);
-g(12);
-
-assertTrue(%GetOptimizationStatus(f) != 2);
-assertTrue(%GetOptimizationStatus(g) != 2);
diff --git a/test/mjsunit/harmony/block-let-declaration-sloppy.js b/test/mjsunit/harmony/block-let-declaration-sloppy.js
deleted file mode 100644
index af95553..0000000
--- a/test/mjsunit/harmony/block-let-declaration-sloppy.js
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Test let declarations in various settings.
-
-// Flags: --harmony-sloppy --harmony-sloppy-let
-
-// Global
-let x;
-let y = 2;
-const z = 4;
-class c { static foo() { return 1; } }
-
-// Block local
-{
-  let y;
-  let x = 3;
-  const z = 5;
-  class c { static foo() { return 2; } }
-}
-
-assertEquals(undefined, x);
-assertEquals(2,y);
-assertEquals(4,z);
-assertEquals(1, c.foo());
-
-if (true) {
-  let y;
-  assertEquals(undefined, y);
-}
-
-// Invalid declarations are early errors in harmony mode and thus should trigger
-// an exception in eval code during parsing, before even compiling or executing
-// the code. Thus the generated function is not called here.
-function TestLocalThrows(str, expect) {
-  assertThrows("(function(arg){ 'use strict'; " + str + "})", expect);
-}
-
-function TestLocalDoesNotThrow(str) {
-  assertDoesNotThrow("(function(arg){ 'use strict'; " + str + "})()");
-}
-
-// Test let declarations in statement positions.
-TestLocalThrows("if (true) let x;", SyntaxError);
-TestLocalThrows("if (true) {} else let x;", SyntaxError);
-TestLocalThrows("do let x; while (false)", SyntaxError);
-TestLocalThrows("while (false) let x;", SyntaxError);
-TestLocalThrows("label: let x;", SyntaxError);
-TestLocalThrows("for (;false;) let x;", SyntaxError);
-TestLocalDoesNotThrow("switch (true) { case true: let x; }");
-TestLocalDoesNotThrow("switch (true) { default: let x; }");
-
-// Test const declarations with initialisers in statement positions.
-TestLocalThrows("if (true) const x = 1;", SyntaxError);
-TestLocalThrows("if (true) {} else const x = 1;", SyntaxError);
-TestLocalThrows("do const x = 1; while (false)", SyntaxError);
-TestLocalThrows("while (false) const x = 1;", SyntaxError);
-TestLocalThrows("label: const x = 1;", SyntaxError);
-TestLocalThrows("for (;false;) const x = 1;", SyntaxError);
-TestLocalDoesNotThrow("switch (true) { case true: const x = 1; }");
-TestLocalDoesNotThrow("switch (true) { default: const x = 1; }");
-
-// Test const declarations without initialisers.
-TestLocalThrows("const x;", SyntaxError);
-TestLocalThrows("const x = 1, y;", SyntaxError);
-TestLocalThrows("const x, y = 1;", SyntaxError);
-
-// Test const declarations without initialisers in statement positions.
-TestLocalThrows("if (true) const x;", SyntaxError);
-TestLocalThrows("if (true) {} else const x;", SyntaxError);
-TestLocalThrows("do const x; while (false)", SyntaxError);
-TestLocalThrows("while (false) const x;", SyntaxError);
-TestLocalThrows("label: const x;", SyntaxError);
-TestLocalThrows("for (;false;) const x;", SyntaxError);
-TestLocalThrows("switch (true) { case true: const x; }", SyntaxError);
-TestLocalThrows("switch (true) { default: const x; }", SyntaxError);
-
-// Test var declarations in statement positions.
-TestLocalDoesNotThrow("if (true) var x;");
-TestLocalDoesNotThrow("if (true) {} else var x;");
-TestLocalDoesNotThrow("do var x; while (false)");
-TestLocalDoesNotThrow("while (false) var x;");
-TestLocalDoesNotThrow("label: var x;");
-TestLocalDoesNotThrow("for (;false;) var x;");
-TestLocalDoesNotThrow("switch (true) { case true: var x; }");
-TestLocalDoesNotThrow("switch (true) { default: var x; }");
-
-// Test class declarations with initialisers in statement positions.
-TestLocalThrows("if (true) class x { };", SyntaxError);
-TestLocalThrows("if (true) {} else class x { };", SyntaxError);
-TestLocalThrows("do class x { }; while (false)", SyntaxError);
-TestLocalThrows("while (false) class x { };", SyntaxError);
-TestLocalThrows("label: class x { };", SyntaxError);
-TestLocalThrows("for (;false;) class x { };", SyntaxError);
-TestLocalDoesNotThrow("switch (true) { case true: class x { }; }");
-TestLocalDoesNotThrow("switch (true) { default: class x { }; }");
-
-// Test that redeclarations of functions are only allowed in outermost scope.
-TestLocalThrows("{ let f; var f; }");
-TestLocalThrows("{ var f; let f; }");
-TestLocalThrows("{ function f() {} let f; }");
-TestLocalThrows("{ let f; function f() {} }");
-TestLocalThrows("{ function f() {} var f; }");
-TestLocalThrows("{ var f; function f() {} }");
-TestLocalThrows("{ function f() {} class f {} }");
-TestLocalThrows("{ class f {}; function f() {} }");
-TestLocalThrows("{ function f() {} function f() {} }");
-TestLocalThrows("function f() {} let f;");
-TestLocalThrows("let f; function f() {}");
-TestLocalThrows("function f() {} class f {}");
-TestLocalThrows("class f {}; function f() {}");
-TestLocalDoesNotThrow("function arg() {}");
-TestLocalDoesNotThrow("function f() {} var f;");
-TestLocalDoesNotThrow("var f; function f() {}");
-TestLocalDoesNotThrow("function f() {} function f() {}");
-
-function g(f) {
-  function f() { return 1 }
-  return f()
-}
-assertEquals(1, g(function() { return 2 }))
-
-
-// Test function declarations in source element and
-// sloppy statement positions.
-function f() {
-  // Sloppy source element positions.
-  function g0() {
-    "use strict";
-    // Strict source element positions.
-    function h() { }
-    {
-      function h1() { }
-    }
-  }
-  {
-    function g1() { }
-  }
-}
-f();
-
-// Test function declarations in statement position in strict mode.
-TestLocalThrows("function f() { if (true) function g() {} }", SyntaxError);
-TestLocalThrows("function f() { if (true) {} else function g() {} }", SyntaxError);
-TestLocalThrows("function f() { do function g() {} while (false) }", SyntaxError);
-TestLocalThrows("function f() { while (false) function g() {} }", SyntaxError);
-TestLocalThrows("function f() { label: function g() {} }", SyntaxError);
-TestLocalThrows("function f() { for (;false;) function g() {} }", SyntaxError);
-TestLocalDoesNotThrow("function f() { switch (true) { case true: function g() {} } }");
-TestLocalDoesNotThrow("function f() { switch (true) { default: function g() {} } }");
diff --git a/test/mjsunit/harmony/block-let-semantics-sloppy.js b/test/mjsunit/harmony/block-let-semantics-sloppy.js
deleted file mode 100644
index a55ff8f..0000000
--- a/test/mjsunit/harmony/block-let-semantics-sloppy.js
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --harmony-sloppy --harmony-sloppy-let --harmony-sloppy-function
-
-// Test temporal dead zone semantics of let bound variables in
-// function and block scopes.
-
-function TestFunctionLocal(s) {
-  try {
-    eval("(function(){" + s + "; })")();
-  } catch (e) {
-    assertInstanceof(e, ReferenceError);
-    return;
-  }
-  assertUnreachable();
-}
-
-function TestBlockLocal(s,e) {
-  try {
-    eval("(function(){ {" + s + ";} })")();
-  } catch (e) {
-    assertInstanceof(e, ReferenceError);
-    return;
-  }
-  assertUnreachable();
-}
-
-
-function TestAll(s) {
-  TestBlockLocal(s);
-  TestFunctionLocal(s);
-}
-
-// Use before initialization in declaration statement.
-TestAll('let x = x + 1');
-TestAll('let x = x += 1');
-TestAll('let x = x++');
-TestAll('let x = ++x');
-TestAll('const x = x + 1');
-
-// Use before initialization in prior statement.
-TestAll('x + 1; let x;');
-TestAll('x = 1; let x;');
-TestAll('x += 1; let x;');
-TestAll('++x; let x;');
-TestAll('x++; let x;');
-TestAll('let y = x; const x = 1;');
-TestAll('let y = x; class x {}');
-
-TestAll('f(); let x; function f() { return x + 1; }');
-TestAll('f(); let x; function f() { x = 1; }');
-TestAll('f(); let x; function f() { x += 1; }');
-TestAll('f(); let x; function f() { ++x; }');
-TestAll('f(); let x; function f() { x++; }');
-TestAll('f(); const x = 1; function f() { return x; }');
-TestAll('f(); class x { }; function f() { return x; }');
-
-TestAll('f()(); let x; function f() { return function() { return x + 1; } }');
-TestAll('f()(); let x; function f() { return function() { x = 1; } }');
-TestAll('f()(); let x; function f() { return function() { x += 1; } }');
-TestAll('f()(); let x; function f() { return function() { ++x; } }');
-TestAll('f()(); let x; function f() { return function() { x++; } }');
-TestAll('f()(); const x = 1; function f() { return function() { return x; } }');
-TestAll('f()(); class x { }; function f() { return function() { return x; } }');
-
-for (var kw of ['let x = 2', 'const x = 2', 'class x { }']) {
-  // Use before initialization with a dynamic lookup.
-  TestAll(`eval("x"); ${kw};`);
-  TestAll(`eval("x + 1;"); ${kw};`);
-  TestAll(`eval("x = 1;"); ${kw};`);
-  TestAll(`eval("x += 1;"); ${kw};`);
-  TestAll(`eval("++x;"); ${kw};`);
-  TestAll(`eval("x++;"); ${kw};`);
-
-  // Use before initialization with check for eval-shadowed bindings.
-  TestAll(`function f() { eval("var y = 2;"); x + 1; }; f(); ${kw};`);
-  TestAll(`function f() { eval("var y = 2;"); x = 1; }; f(); ${kw};`);
-  TestAll(`function f() { eval("var y = 2;"); x += 1; }; f(); ${kw};`);
-  TestAll(`function f() { eval("var y = 2;"); ++x; }; f(); ${kw};`);
-  TestAll(`function f() { eval("var y = 2;"); x++; }; f(); ${kw};`);
-}
-
-// Test that variables introduced by function declarations are created and
-// initialized upon entering a function / block scope.
-function f() {
-  {
-    assertEquals(2, g1());
-    assertEquals(2, eval("g1()"));
-
-    // block scoped function declaration
-    function g1() {
-      return 2;
-    }
-  }
-
-  assertEquals(3, g2());
-  assertEquals(3, eval("g2()"));
-  // function scoped function declaration
-  function g2() {
-    return 3;
-  }
-}
-f();
-
-// Test that a function declaration introduces a block scoped variable
-// and no function hoisting if there is a conflict.
-TestFunctionLocal('{ function k() { return 0; } }; k(); let k;');
-
-// Test that a function declaration sees the scope it resides in.
-function f2() {
-  let m, n, o, p;
-  {
-    m = g;
-    function g() {
-      return a;
-    }
-    let a = 1;
-  }
-  assertEquals(1, m());
-
-  try {
-    throw 2;
-  } catch(b) {
-    n = h;
-    function h() {
-      return b + c;
-    }
-    let c = 3;
-  }
-  assertEquals(5, n());
-
-  {
-    o = i;
-    function i() {
-      return d;
-    }
-    let d = 4;
-  }
-  assertEquals(4, o());
-
-  try {
-    throw 5;
-  } catch(e) {
-    p = j;
-    function j() {
-      return e + f;
-    }
-    let f = 6;
-  }
-  assertEquals(11, p());
-}
-f2();
-
-// Test that resolution of let bound variables works with scopes that call eval.
-function outer() {
-  function middle() {
-    function inner() {
-      return x;
-    }
-    eval("1 + 1");
-    return x + inner();
-  }
-
-  let x = 1;
-  return middle();
-}
-
-assertEquals(2, outer());
diff --git a/test/mjsunit/harmony/block-scoping-sloppy.js b/test/mjsunit/harmony/block-scoping-sloppy.js
deleted file mode 100644
index 1785901..0000000
--- a/test/mjsunit/harmony/block-scoping-sloppy.js
+++ /dev/null
@@ -1,309 +0,0 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --allow-natives-syntax --harmony-sloppy --harmony-sloppy-let --harmony-sloppy-function
-// Test functionality of block scopes.
-
-// Hoisting of var declarations.
-function f1() {
-  {
-    var x = 1;
-    var y;
-  }
-  assertEquals(1, x)
-  assertEquals(undefined, y)
-}
-for (var j = 0; j < 5; ++j) f1();
-%OptimizeFunctionOnNextCall(f1);
-f1();
-assertTrue(%GetOptimizationStatus(f1) != 2);
-
-// Dynamic lookup in and through block contexts.
-function f2(one) {
-  var x = one + 1;
-  let y = one + 2;
-  const u = one + 4;
-  class a { static foo() { return one + 6; } }
-  {
-    let z = one + 3;
-    const v = one + 5;
-    class b { static foo() { return one + 7; } }
-    assertEquals(1, eval('one'));
-    assertEquals(2, eval('x'));
-    assertEquals(3, eval('y'));
-    assertEquals(4, eval('z'));
-    assertEquals(5, eval('u'));
-    assertEquals(6, eval('v'));
-    assertEquals(7, eval('a.foo()'));
-    assertEquals(8, eval('b.foo()'));
-  }
-}
-
-f2(1);
-
-// Lookup in and through block contexts.
-function f3(one) {
-  var x = one + 1;
-  let y = one + 2;
-  const u = one + 4;
-  class a { static foo() { return one + 6; } }
-  {
-    let z = one + 3;
-    const v = one + 5;
-    class b { static foo() { return one + 7; } }
-    assertEquals(1, one);
-    assertEquals(2, x);
-    assertEquals(3, y);
-    assertEquals(4, z);
-    assertEquals(5, u);
-    assertEquals(6, v);
-    assertEquals(7, a.foo());
-    assertEquals(8, b.foo());
-  }
-}
-for (var j = 0; j < 5; ++j) f3(1);
-%OptimizeFunctionOnNextCall(f3);
-f3(1);
-
-
-
-// Dynamic lookup from closure.
-function f4(one) {
-  var x = one + 1;
-  let y = one + 2;
-  const u = one + 4;
-  class a { static foo() { return one + 6; } }
-  {
-    let z = one + 3;
-    const v = one + 5;
-    class b { static foo() { return one + 7; } }
-    function f() {
-      assertEquals(1, eval('one'));
-      assertEquals(2, eval('x'));
-      assertEquals(3, eval('y'));
-      assertEquals(4, eval('z'));
-      assertEquals(5, eval('u'));
-      assertEquals(6, eval('v'));
-      assertEquals(7, eval('a.foo()'));
-      assertEquals(8, eval('b.foo()'));
-    }
-    f();
-  }
-}
-f4(1);
-
-
-// Lookup from closure.
-function f5(one) {
-  var x = one + 1;
-  let y = one + 2;
-  const u = one + 4;
-  class a { static foo() { return one + 6; } }
-  {
-    let z = one + 3;
-    const v = one + 5;
-    class b { static foo() { return one + 7; } }
-    function f() {
-      assertEquals(1, one);
-      assertEquals(2, x);
-      assertEquals(3, y);
-      assertEquals(4, z);
-      assertEquals(5, u);
-      assertEquals(6, v);
-      assertEquals(7, a.foo());
-      assertEquals(8, b.foo());
-    }
-    f();
-  }
-}
-f5(1);
-
-
-// Return from block.
-function f6() {
-  let x = 1;
-  const u = 3;
-  {
-    let y = 2;
-    const v = 4;
-    return x + y;
-  }
-}
-assertEquals(3, f6(6));
-
-
-// Variable shadowing and lookup.
-function f7(a) {
-  let b = 1;
-  var c = 1;
-  var d = 1;
-  const e = 1;
-  class f { static foo() { return 1; } }
-  { // let variables shadowing argument, let, const, class and var variables
-    let a = 2;
-    let b = 2;
-    let c = 2;
-    let e = 2;
-    let f = 2;
-    assertEquals(2,a);
-    assertEquals(2,b);
-    assertEquals(2,c);
-    assertEquals(2,e);
-    assertEquals(2,f);
-  }
-  { // const variables shadowing argument, let, const and var variables
-    const a = 2;
-    const b = 2;
-    const c = 2;
-    const e = 2;
-    const f = 2;
-    assertEquals(2,a);
-    assertEquals(2,b);
-    assertEquals(2,c);
-    assertEquals(2,e);
-    assertEquals(2,f);
-  }
-  { // class variables shadowing argument, let, const and var variables
-    class a { static foo() { return 2; } }
-    class b { static foo() { return 2; } }
-    class c { static foo() { return 2; } }
-    class d { static foo() { return 2; } }
-    class e { static foo() { return 2; } }
-    class f { static foo() { return 2; } }
-    assertEquals(2,a.foo());
-    assertEquals(2,b.foo());
-    assertEquals(2,c.foo());
-    assertEquals(2,e.foo());
-    assertEquals(2,f.foo());
-  }
-  try {
-    throw 'stuff1';
-  } catch (a) {
-    assertEquals('stuff1',a);
-    // catch variable shadowing argument
-    a = 2;
-    assertEquals(2,a);
-    {
-      // let variable shadowing catch variable
-      let a = 3;
-      assertEquals(3,a);
-      try {
-        throw 'stuff2';
-      } catch (a) {
-        assertEquals('stuff2',a);
-        // catch variable shadowing let variable
-        a = 4;
-        assertEquals(4,a);
-      }
-      assertEquals(3,a);
-    }
-    assertEquals(2,a);
-  }
-  try {
-    throw 'stuff3';
-  } catch (c) {
-    // catch variable shadowing var variable
-    assertEquals('stuff3',c);
-    {
-      // const variable shadowing catch variable
-      const c = 3;
-      assertEquals(3,c);
-    }
-    assertEquals('stuff3',c);
-    try {
-      throw 'stuff4';
-    } catch(c) {
-      assertEquals('stuff4',c);
-      // catch variable shadowing catch variable
-      c = 3;
-      assertEquals(3,c);
-    }
-    (function(c) {
-      // argument shadowing catch variable
-      c = 3;
-      assertEquals(3,c);
-    })();
-    assertEquals('stuff3', c);
-    (function() {
-      // var variable shadowing catch variable
-      var c = 3;
-    })();
-    assertEquals('stuff3', c);
-    c = 2;
-  }
-  assertEquals(1,c);
-  (function(a,b,c,e,f) {
-    // arguments shadowing argument, let, const, class and var variable
-    a = 2;
-    b = 2;
-    c = 2;
-    e = 2;
-    f = 2;
-    assertEquals(2,a);
-    assertEquals(2,b);
-    assertEquals(2,c);
-    assertEquals(2,e);
-    assertEquals(2,f);
-    // var variable shadowing var variable
-    var d = 2;
-  })(1,1);
-  assertEquals(1,a);
-  assertEquals(1,b);
-  assertEquals(1,c);
-  assertEquals(1,d);
-  assertEquals(1,e);
-  assertEquals(1,f.foo());
-}
-f7(1);
-
-
-// Ensure let and const variables are block local
-// and var variables function local.
-function f8() {
-  var let_accessors = [];
-  var var_accessors = [];
-  var const_accessors = [];
-  var class_accessors = [];
-  for (var i = 0; i < 10; i++) {
-    let x = i;
-    var y = i;
-    const z = i;
-    class a { static foo() { return x; } }
-    let_accessors[i] = function() { return x; }
-    var_accessors[i] = function() { return y; }
-    const_accessors[i] = function() { return z; }
-    class_accessors[i] = function() { return a; }
-  }
-  for (var j = 0; j < 10; j++) {
-    y = j + 10;
-    assertEquals(j, let_accessors[j]());
-    assertEquals(y, var_accessors[j]());
-    assertEquals(j, const_accessors[j]());
-    assertEquals(j, class_accessors[j]().foo());
-  }
-}
-f8();
diff --git a/test/mjsunit/harmony/block-scoping-top-level-sloppy.js b/test/mjsunit/harmony/block-scoping-top-level-sloppy.js
deleted file mode 100644
index 6f6a8fe..0000000
--- a/test/mjsunit/harmony/block-scoping-top-level-sloppy.js
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --min-preparse-length=0
-// Flags: --harmony-sloppy --harmony-sloppy-let
-
-let xxx = 1;
-let f = undefined;
-{
-  let inner_x = xxx;
-  f = function() { return inner_x; };
-}
-
-assertSame(1, f());
-
-xxx = 42;
-{
-  f = function() { return inner_x1; };
-  let inner_x1 = xxx;
-}
-
-assertSame(42, f());
-
-xxx = 31;
-{
-  let inner_x1 = xxx;
-  try {
-    throw new Error();
-  } catch (e) {
-    f = function() { return inner_x1; };
-  }
-}
-assertSame(31, f());
diff --git a/test/mjsunit/harmony/block-sloppy-function.js b/test/mjsunit/harmony/block-sloppy-function.js
deleted file mode 100644
index 2bea147..0000000
--- a/test/mjsunit/harmony/block-sloppy-function.js
+++ /dev/null
@@ -1,301 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-sloppy --harmony-sloppy-let
-// Flags: --harmony-sloppy-function
-
-// Test Annex B 3.3 semantics for functions declared in blocks in sloppy mode.
-// http://www.ecma-international.org/ecma-262/6.0/#sec-block-level-function-declarations-web-legacy-compatibility-semantics
-
-(function overridingLocalFunction() {
-  var x = [];
-  assertEquals('function', typeof f);
-  function f() {
-    x.push(1);
-  }
-  f();
-  {
-    f();
-    function f() {
-      x.push(2);
-    }
-    f();
-  }
-  f();
-  {
-    f();
-    function f() {
-      x.push(3);
-    }
-    f();
-  }
-  f();
-  assertArrayEquals([1, 2, 2, 2, 3, 3, 3], x);
-})();
-
-(function newFunctionBinding() {
-  var x = [];
-  assertEquals('undefined', typeof f);
-  {
-    f();
-    function f() {
-      x.push(2);
-    }
-    f();
-  }
-  f();
-  {
-    f();
-    function f() {
-      x.push(3);
-    }
-    f();
-  }
-  f();
-  assertArrayEquals([2, 2, 2, 3, 3, 3], x);
-})();
-
-(function shadowingLetDoesntBind() {
-  let f = 1;
-  assertEquals(1, f);
-  {
-    let y = 3;
-    function f() {
-      y = 2;
-    }
-    f();
-    assertEquals(2, y);
-  }
-  assertEquals(1, f);
-})();
-
-(function shadowingClassDoesntBind() {
-  class f { }
-  assertEquals('class f { }', f.toString());
-  {
-    let y = 3;
-    function f() {
-      y = 2;
-    }
-    f();
-    assertEquals(2, y);
-  }
-  assertEquals('class f { }', f.toString());
-})();
-
-(function shadowingConstDoesntBind() {
-  const f = 1;
-  assertEquals(1, f);
-  {
-    let y = 3;
-    function f() {
-      y = 2;
-    }
-    f();
-    assertEquals(2, y);
-  }
-  assertEquals(1, f);
-})();
-
-(function shadowingVarBinds() {
-  var f = 1;
-  assertEquals(1, f);
-  {
-    let y = 3;
-    function f() {
-      y = 2;
-    }
-    f();
-    assertEquals(2, y);
-  }
-  assertEquals('function', typeof f);
-})();
-
-(function conditional() {
-  if (true) {
-    function f() { return 1; }
-  } else {
-    function f() { return 2; }
-  }
-  assertEquals(1, f());
-
-  if (false) {
-    function g() { return 1; }
-  } else {
-    function g() { return 2; }
-  }
-  assertEquals(2, g());
-})();
-
-(function skipExecution() {
-  {
-    function f() { return 1; }
-  }
-  assertEquals(1, f());
-  {
-    function f() { return 2; }
-  }
-  assertEquals(2, f());
-  L: {
-    assertEquals(3, f());
-    break L;
-    function f() { return 3; }
-  }
-  assertEquals(2, f());
-})();
-
-// Test that shadowing arguments is fine
-(function shadowArguments(x) {
-  assertArrayEquals([1], arguments);
-  {
-    assertEquals('function', typeof arguments);
-    function arguments() {}
-    assertEquals('function', typeof arguments);
-  }
-  assertEquals('function', typeof arguments);
-})(1);
-
-// Shadow function parameter
-(function shadowParameter(x) {
-  assertEquals(1, x);
-  {
-    function x() {}
-  }
-  assertEquals('function', typeof x);
-})(1);
-
-// Shadow function parameter
-(function shadowDefaultParameter(x = 0) {
-  assertEquals(1, x);
-  {
-    function x() {}
-  }
-  // TODO(littledan): Once destructured parameters are no longer
-  // let-bound, enable this assertion. This is the core of the test.
-  // assertEquals('function', typeof x);
-})(1);
-
-(function shadowRestParameter(...x) {
-  assertArrayEquals([1], x);
-  {
-    function x() {}
-  }
-  // TODO(littledan): Once destructured parameters are no longer
-  // let-bound, enable this assertion. This is the core of the test.
-  // assertEquals('function', typeof x);
-})(1);
-
-assertThrows(function notInDefaultScope(x = y) {
-  {
-    function y() {}
-  }
-  assertEquals('function', typeof y);
-  assertEquals(x, undefined);
-}, ReferenceError);
-
-// Test that hoisting from blocks does happen in global scope
-function globalHoisted() { return 0; }
-{
-  function globalHoisted() { return 1; }
-}
-assertEquals(1, globalHoisted());
-
-// Also happens when not previously defined
-assertEquals(undefined, globalUndefinedHoisted);
-{
-  function globalUndefinedHoisted() { return 1; }
-}
-assertEquals(1, globalUndefinedHoisted());
-var globalUndefinedHoistedDescriptor =
-    Object.getOwnPropertyDescriptor(this, "globalUndefinedHoisted");
-assertFalse(globalUndefinedHoistedDescriptor.configurable);
-assertTrue(globalUndefinedHoistedDescriptor.writable);
-assertTrue(globalUndefinedHoistedDescriptor.enumerable);
-assertEquals(1, globalUndefinedHoistedDescriptor.value());
-
-// When a function property is hoisted, it should be
-// made enumerable.
-// BUG(v8:4451)
-Object.defineProperty(this, "globalNonEnumerable", {
-  value: false,
-  configurable: true,
-  writable: true,
-  enumerable: false
-});
-eval("{function globalNonEnumerable() { return 1; }}");
-var globalNonEnumerableDescriptor
-    = Object.getOwnPropertyDescriptor(this, "globalNonEnumerable");
-// BUG(v8:4451): Should be made non-configurable
-assertTrue(globalNonEnumerableDescriptor.configurable);
-assertTrue(globalNonEnumerableDescriptor.writable);
-// BUG(v8:4451): Should be made enumerable
-assertFalse(globalNonEnumerableDescriptor.enumerable);
-assertEquals(1, globalNonEnumerableDescriptor.value());
-
-// When a function property is hoisted, it should be overwritten and
-// made writable and overwritten, even if the property was non-writable.
-Object.defineProperty(this, "globalNonWritable", {
-  value: false,
-  configurable: true,
-  writable: false,
-  enumerable: true
-});
-eval("{function globalNonWritable() { return 1; }}");
-var globalNonWritableDescriptor
-    = Object.getOwnPropertyDescriptor(this, "globalNonWritable");
-// BUG(v8:4451): Should be made non-configurable
-assertTrue(globalNonWritableDescriptor.configurable);
-// BUG(v8:4451): Should be made writable
-assertFalse(globalNonWritableDescriptor.writable);
-assertFalse(globalNonEnumerableDescriptor.enumerable);
-// BUG(v8:4451): Should be overwritten
-assertEquals(false, globalNonWritableDescriptor.value);
-
-// Test that hoisting from blocks does happen in an eval
-eval(`
-  function evalHoisted() { return 0; }
-  {
-    function evalHoisted() { return 1; }
-  }
-  assertEquals(1, evalHoisted());
-`);
-
-// Test that hoisting from blocks happens from eval in a function
-!function() {
-  eval(`
-    function evalInFunctionHoisted() { return 0; }
-    {
-      function evalInFunctionHoisted() { return 1; }
-    }
-    assertEquals(1, evalInFunctionHoisted());
-  `);
-}();
-
-let dontHoistGlobal;
-{ function dontHoistGlobal() {} }
-assertEquals(undefined, dontHoistGlobal);
-
-let dontHoistEval;
-// BUG(v8:) This shouldn't hoist and shouldn't throw
-var throws = false;
-try {
-  eval("{ function dontHoistEval() {} }");
-} catch (e) {
-  throws = true;
-}
-assertTrue(throws);
-
-// When the global object is frozen, silently don't hoist
-// Currently this actually throws BUG(v8:4452)
-Object.freeze(this);
-throws = false;
-try {
-  eval('{ function hoistWhenFrozen() {} }');
-} catch (e) {
-  throws = true;
-}
-assertFalse(this.hasOwnProperty("hoistWhenFrozen"));
-assertThrows(() => hoistWhenFrozen, ReferenceError);
-// Should be assertFalse BUG(v8:4452)
-assertTrue(throws);
diff --git a/test/mjsunit/harmony/debug-async-break-on-stack.js b/test/mjsunit/harmony/debug-async-break-on-stack.js
new file mode 100644
index 0000000..d3d9d8b
--- /dev/null
+++ b/test/mjsunit/harmony/debug-async-break-on-stack.js
@@ -0,0 +1,78 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+// Flags: --harmony-async-await --allow-natives-syntax
+
+var Debug = debug.Debug;
+
+function assertEqualsAsync(expected, run, msg) {
+  var actual;
+  var hadValue = false;
+  var hadError = false;
+  var promise = run();
+
+  if (typeof promise !== "object" || typeof promise.then !== "function") {
+    throw new MjsUnitAssertionError(
+        "Expected " + run.toString() +
+        " to return a Promise, but it returned " + promise);
+  }
+
+  promise.then(function(value) { hadValue = true; actual = value; },
+               function(error) { hadError = true; actual = error; });
+
+  assertFalse(hadValue || hadError);
+
+  %RunMicrotasks();
+
+  if (hadError) throw actual;
+
+  assertTrue(
+      hadValue, "Expected '" + run.toString() + "' to produce a value");
+
+  assertEquals(expected, actual, msg);
+}
+
+var break_count = 0;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    break_count++;
+    var line = exec_state.frame(0).sourceLineText();
+    print(line);
+    assertTrue(line.indexOf(`B${break_count}`) > 0);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+
+async function g() {
+  setbreaks();
+  throw 1;  // B1
+}
+
+async function f() {
+  try {
+    await g();
+  } catch (e) {}
+  return 2;  // B2
+}
+
+function setbreaks() {
+  Debug.setListener(listener);
+  Debug.setBreakPoint(g, 2);
+  Debug.setBreakPoint(f, 4);
+}
+
+f();
+
+%RunMicrotasks();
+
+assertEqualsAsync(2, async () => break_count);
+assertEqualsAsync(null, async () => exception);
+
+Debug.setListener(null);
diff --git a/test/mjsunit/harmony/debug-async-break.js b/test/mjsunit/harmony/debug-async-break.js
new file mode 100644
index 0000000..3b6b71b
--- /dev/null
+++ b/test/mjsunit/harmony/debug-async-break.js
@@ -0,0 +1,76 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+// Flags: --harmony-async-await --allow-natives-syntax
+
+var Debug = debug.Debug;
+
+function assertEqualsAsync(expected, run, msg) {
+  var actual;
+  var hadValue = false;
+  var hadError = false;
+  var promise = run();
+
+  if (typeof promise !== "object" || typeof promise.then !== "function") {
+    throw new MjsUnitAssertionError(
+        "Expected " + run.toString() +
+        " to return a Promise, but it returned " + promise);
+  }
+
+  promise.then(function(value) { hadValue = true; actual = value; },
+               function(error) { hadError = true; actual = error; });
+
+  assertFalse(hadValue || hadError);
+
+  %RunMicrotasks();
+
+  if (hadError) throw actual;
+
+  assertTrue(
+      hadValue, "Expected '" + run.toString() + "' to produce a value");
+
+  assertEquals(expected, actual, msg);
+}
+
+var break_count = 0;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    break_count++;
+    var line = exec_state.frame(0).sourceLineText();
+    assertTrue(line.indexOf(`B${break_count}`) > 0);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+async function g() {
+  throw 1;
+}
+
+async function f() {
+  try {
+    await g();                   // B1
+  } catch (e) {}
+  assertEquals(2, break_count);  // B2
+  return 1;                      // B3
+}
+
+Debug.setBreakPoint(f, 2);
+Debug.setBreakPoint(f, 4);
+Debug.setBreakPoint(f, 5);
+
+f();
+
+%RunMicrotasks();
+
+assertEqualsAsync(3, async () => break_count);
+assertEqualsAsync(null, async () => exception);
+
+Debug.setListener(null);
diff --git a/test/mjsunit/harmony/debug-async-function-async-task-event.js b/test/mjsunit/harmony/debug-async-function-async-task-event.js
new file mode 100644
index 0000000..249f02f
--- /dev/null
+++ b/test/mjsunit/harmony/debug-async-function-async-task-event.js
@@ -0,0 +1,70 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await --expose-debug-as debug --allow-natives-syntax
+
+Debug = debug.Debug;
+
+var base_id = -1;
+var exception = null;
+var expected = [
+  "enqueue #1",
+  "willHandle #1",
+  "then #1",
+  "enqueue #2",
+  "enqueue #3",
+  "didHandle #1",
+  "willHandle #2",
+  "then #2",
+  "didHandle #2",
+  "willHandle #3",
+  "enqueue #4",
+  "didHandle #3",
+  "willHandle #4",
+  "didHandle #4",
+];
+
+function assertLog(msg) {
+  print(msg);
+  assertTrue(expected.length > 0);
+  assertEquals(expected.shift(), msg);
+  if (!expected.length) {
+    Debug.setListener(null);
+  }
+}
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.AsyncTaskEvent) return;
+  try {
+    if (base_id < 0)
+      base_id = event_data.id();
+    var id = event_data.id() - base_id + 1;
+    assertTrue("Promise.resolve" == event_data.name() ||
+               "PromiseResolveThenableJob" == event_data.name());
+    assertLog(event_data.type() + " #" + id);
+  } catch (e) {
+    print(e + e.stack)
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+var resolver;
+var p = new Promise(function(resolve, reject) {
+  resolver = resolve;
+});
+
+async function main() {
+  await p;
+  assertLog("then #1");
+  await undefined;
+  assertLog("then #2");
+}
+main();
+resolver();
+
+%RunMicrotasks();
+
+assertNull(exception);
diff --git a/test/mjsunit/harmony/debug-async-liveedit.js b/test/mjsunit/harmony/debug-async-liveedit.js
new file mode 100644
index 0000000..c651ddb
--- /dev/null
+++ b/test/mjsunit/harmony/debug-async-liveedit.js
@@ -0,0 +1,133 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await
+// Flags: --expose-debug-as debug --allow-natives-syntax --ignition-generators
+
+var Debug = debug.Debug;
+var LiveEdit = Debug.LiveEdit;
+
+unique_id = 0;
+
+var AsyncFunction = (async function(){}).constructor;
+
+function assertPromiseValue(value, promise) {
+  promise.then(resolve => {
+    went = true;
+    if (resolve !== value) {
+      print(`expected ${value} found ${resolve}`);
+      quit(1);
+    }
+  }, reject => {
+    print(`rejected ${reject}`);
+    quit(1);
+  });
+}
+
+function MakeAsyncFunction() {
+  // Prevents eval script caching.
+  unique_id++;
+  return AsyncFunction('callback',
+      "/* " + unique_id + "*/\n" +
+      "await callback();\n" +
+      "return 'Cat';\n");
+}
+
+function MakeFunction() {
+  // Prevents eval script caching.
+  unique_id++;
+  return Function('callback',
+      "/* " + unique_id + "*/\n" +
+      "callback();\n" +
+      "return 'Cat';\n");
+}
+
+// First, try MakeGenerator with no perturbations.
+(function(){
+  var asyncfn = MakeAsyncFunction();
+  function callback() {};
+  var promise = asyncfn(callback);
+  assertPromiseValue('Cat', promise);
+})();
+
+function patch(fun, from, to) {
+  function debug() {
+    var log = new Array();
+    var script = Debug.findScript(fun);
+    var pos = script.source.indexOf(from);
+    print(`pos ${pos}`);
+    try {
+      LiveEdit.TestApi.ApplySingleChunkPatch(script, pos, from.length, to,
+                                             log);
+    } finally {
+      print("Change log: " + JSON.stringify(log) + "\n");
+    }
+  }
+  %ExecuteInDebugContext(debug);
+}
+
+// Try to edit a MakeAsyncFunction while it's running, then again while it's
+// stopped.
+(function(){
+  var asyncfn = MakeAsyncFunction();
+
+  var patch_attempted = false;
+  function attempt_patch() {
+    assertFalse(patch_attempted);
+    patch_attempted = true;
+    assertThrows(function() { patch(asyncfn, "'Cat'", "'Capybara'") },
+                 LiveEdit.Failure);
+  };
+  var promise = asyncfn(attempt_patch);
+  // Patch should not succeed because there is a live async function activation
+  // on the stack.
+  assertPromiseValue("Cat", promise);
+  assertTrue(patch_attempted);
+
+  %RunMicrotasks();
+
+  // At this point one iterator is live, but closed, so the patch will succeed.
+  patch(asyncfn, "'Cat'", "'Capybara'");
+  promise = asyncfn(function(){});
+  // Patch successful.
+  assertPromiseValue("Capybara", promise);
+
+  // Patching will fail however when an async function is suspended.
+  var resolve;
+  promise = asyncfn(function(){return new Promise(function(r){resolve = r})});
+  assertThrows(function() { patch(asyncfn, "'Capybara'", "'Tapir'") },
+               LiveEdit.Failure);
+  resolve();
+  assertPromiseValue("Capybara", promise);
+
+  // Try to patch functions with activations inside and outside async
+  // function activations.  We should succeed in the former case, but not in the
+  // latter.
+  var fun_outside = MakeFunction();
+  var fun_inside = MakeFunction();
+  var fun_patch_attempted = false;
+  var fun_patch_restarted = false;
+  function attempt_fun_patches() {
+    if (fun_patch_attempted) {
+      assertFalse(fun_patch_restarted);
+      fun_patch_restarted = true;
+      return;
+    }
+    fun_patch_attempted = true;
+    // Patching outside an async function activation must fail.
+    assertThrows(function() { patch(fun_outside, "'Cat'", "'Cobra'") },
+                 LiveEdit.Failure);
+    // Patching inside an async function activation may succeed.
+    patch(fun_inside, "'Cat'", "'Koala'");
+  }
+  promise = asyncfn(function() { return fun_inside(attempt_fun_patches) });
+  assertEquals('Cat',
+               fun_outside(function () {
+                 assertPromiseValue('Capybara', promise);
+                 assertTrue(fun_patch_restarted);
+                 assertTrue(fun_inside.toString().includes("'Koala'"));
+               }));
+})();
+
+%RunMicrotasks();
diff --git a/test/mjsunit/harmony/do-expressions.js b/test/mjsunit/harmony/do-expressions.js
index b3be4ec..38b68b6 100644
--- a/test/mjsunit/harmony/do-expressions.js
+++ b/test/mjsunit/harmony/do-expressions.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-do-expressions --harmony-sloppy-let --allow-natives-syntax
+// Flags: --harmony-do-expressions --allow-natives-syntax
 
 function returnValue(v) { return v; }
 function MyError() {}
diff --git a/test/mjsunit/harmony/for-in.js b/test/mjsunit/harmony/for-in.js
new file mode 100644
index 0000000..58e343b
--- /dev/null
+++ b/test/mjsunit/harmony/for-in.js
@@ -0,0 +1,9 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-for-in
+
+assertThrows("for (var x = 0 in {});", SyntaxError);
+assertThrows("for (const x = 0 in {});", SyntaxError);
+assertThrows("for (let x = 0 in {});", SyntaxError);
diff --git a/test/mjsunit/harmony/function-name.js b/test/mjsunit/harmony/function-name.js
deleted file mode 100644
index 66a69e0..0000000
--- a/test/mjsunit/harmony/function-name.js
+++ /dev/null
@@ -1,372 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Flags: --harmony-function-name
-
-(function testVariableDeclarationsFunction() {
-  'use strict';
-  var a = function(){};
-  assertEquals('a', a.name);
-  let b = () => {};
-  assertEquals('b', b.name);
-  const c = ((function(){}));
-  assertEquals('c', c.name);
-
-  var x = function(){}, y = () => {}, z = function withName() {};
-  assertEquals('x', x.name);
-  assertEquals('y', y.name);
-  assertEquals('withName', z.name);
-})();
-
-(function testVariableDeclarationsClass() {
-  'use strict';
-  var a = class {};
-  assertEquals('a', a.name);
-  let b = ((class {}));
-  assertEquals('b', b.name);
-  // Should not overwrite name property.
-  const c = class { static name() { } }
-  assertEquals('function', typeof c.name);
-
-  var x = class {}, y = class NamedClass {};
-  assertEquals('x', x.name);
-  assertEquals('NamedClass', y.name);
-})();
-
-(function testObjectProperties() {
-  'use strict';
-  var obj = {
-    a: function() {},
-    b: () => {},
-    c() { },
-    get d() { },
-    set d(val) { },
-    x: function withName() { },
-    y: class { },
-    z: class ClassName { },
-    42: function() {},
-    4.2: function() {},
-    __proto__: function() {},
-  };
-
-  assertEquals('a', obj.a.name);
-  assertEquals('b', obj.b.name);
-  assertEquals('c', obj.c.name);
-  var dDescriptor = Object.getOwnPropertyDescriptor(obj, 'd');
-  assertEquals('get d', dDescriptor.get.name);
-  assertEquals('set d', dDescriptor.set.name);
-  assertEquals('withName', obj.x.name);
-  assertEquals('y', obj.y.name);
-  assertEquals('ClassName', obj.z.name);
-  assertEquals('42', obj[42].name);
-  assertEquals('4.2', obj[4.2].name);
-  assertEquals('', obj.__proto__.name);
-})();
-
-(function testClassProperties() {
-  'use strict';
-  class C {
-    a() { }
-    static b() { }
-    get c() { }
-    set c(val) { }
-    42() { }
-    static 43() { }
-    get 44() { }
-    set 44(val) { }
-  };
-
-  assertEquals('a', C.prototype.a.name);
-  assertEquals('b', C.b.name);
-  var descriptor = Object.getOwnPropertyDescriptor(C.prototype, 'c');
-  assertEquals('get c', descriptor.get.name);
-  assertEquals('set c', descriptor.set.name);
-  assertEquals('42', C.prototype[42].name);
-  assertEquals('43', C[43].name);
-  var descriptor = Object.getOwnPropertyDescriptor(C.prototype, '44');
-  assertEquals('get 44', descriptor.get.name);
-  assertEquals('set 44', descriptor.set.name);
-})();
-
-(function testComputedProperties() {
-  'use strict';
-  var a = 'a';
-  var b = 'b';
-  var sym1 = Symbol('1');
-  var sym2 = Symbol('2');
-  var sym3 = Symbol('3');
-  var symNoDescription = Symbol();
-  var obj = {
-    [a]: function() {},
-    [sym1]: function() {},
-    [sym2]: function withName() {},
-    [symNoDescription]: function() {},
-
-    get [sym3]() {},
-    set [b](val) {},
-  };
-
-  assertEquals('a', obj[a].name);
-  assertEquals('[1]', obj[sym1].name);
-  assertEquals('withName', obj[sym2].name);
-  assertEquals('', obj[symNoDescription].name);
-
-  assertEquals('get [3]', Object.getOwnPropertyDescriptor(obj, sym3).get.name);
-  assertEquals('set b', Object.getOwnPropertyDescriptor(obj, 'b').set.name);
-
-  var objMethods = {
-    [a]() {},
-    [sym1]() {},
-    [symNoDescription]: function() {},
-  };
-
-  assertEquals('a', objMethods[a].name);
-  assertEquals('[1]', objMethods[sym1].name);
-  assertEquals('', objMethods[symNoDescription].name);
-
-  class C {
-    [a]() { }
-    [sym1]() { }
-    static [sym2]() { }
-    [symNoDescription]() { }
-
-    get [sym3]() { }
-    static set [b](val) { }
-  }
-
-  assertEquals('a', C.prototype[a].name);
-  assertEquals('[1]', C.prototype[sym1].name);
-  assertEquals('[2]', C[sym2].name);
-  assertEquals('', C.prototype[symNoDescription].name);
-
-  assertEquals('get [3]', Object.getOwnPropertyDescriptor(C.prototype, sym3).get.name);
-  assertEquals('set b', Object.getOwnPropertyDescriptor(C, 'b').set.name);
-})();
-
-
-(function testAssignment() {
-  var basicFn, arrowFn, generatorFn, classLit;
-
-  basicFn = function() { return true; };
-  assertEquals('basicFn', basicFn.name);
-  var basicFn2 = basicFn;
-  assertEquals('basicFn', basicFn2.name);
-  basicFn = function functionWithName() { };
-  assertEquals("functionWithName", basicFn.name);
-
-  arrowFn = x => x;
-  assertEquals('arrowFn', arrowFn.name);
-  var arrowFn2 = arrowFn;
-  assertEquals('arrowFn', arrowFn2.name);
-
-  generatorFn = function*() { yield true; };
-  assertEquals('generatorFn', generatorFn.name);
-  var generatorFn2 = generatorFn;
-  assertEquals('generatorFn', generatorFn2.name);
-  generatorFn = function* generatorWithName() { };
-  assertEquals("generatorWithName", generatorFn.name);
-
-  classLit = class { constructor() {} };
-  assertEquals('classLit', classLit.name);
-  var classLit2 = classLit;
-  assertEquals('classLit', classLit2.name);
-  classLit = class classWithName { constructor() {} };
-  assertEquals('classWithName', classLit.name);
-  classLit = class { constructor() {} static name() {} };
-  assertEquals('function', typeof classLit.name);
-  classLit = class { constructor() {} static get name() { return true; } };
-  assertTrue(classLit.name);
-  classLit = class { constructor() {} static ['name']() {} };
-  assertEquals('function', typeof classLit.name);
-  classLit = class { constructor() {} static get ['name']() { return true; } };
-  assertTrue(classLit.name);
-})();
-
-(function testObjectBindingPattern() {
-  var {
-    a = function() {},
-    b = () => {},
-    x = function withName() { },
-    y = class { },
-    z = class ClassName { },
-    q = class { static name() { return 42 } },
-    foo: bar = function() {},
-    inParens = (() => {}),
-    inManyParens = ((((() => {})))),
-  } = {};
-  assertEquals('a', a.name);
-  assertEquals('b', b.name);
-  assertEquals('withName', x.name);
-  assertEquals('y', y.name);
-  assertEquals('ClassName', z.name);
-  assertEquals('function', typeof q.name);
-  assertEquals('bar', bar.name);
-  assertEquals('inParens', inParens.name)
-  assertEquals('inManyParens', inManyParens.name)
-})();
-
-(function testArrayBindingPattern() {
-  var [
-    a = function() {},
-    b = () => {},
-    x = function withName() { },
-    y = class { },
-    z = class ClassName { },
-    q = class { static name() { return 42 } },
-    inParens = (() => {}),
-    inManyParens = ((((() => {})))),
-  ] = [];
-  assertEquals('a', a.name);
-  assertEquals('b', b.name);
-  assertEquals('withName', x.name);
-  assertEquals('y', y.name);
-  assertEquals('ClassName', z.name);
-  assertEquals('function', typeof q.name);
-  assertEquals('inParens', inParens.name)
-  assertEquals('inManyParens', inManyParens.name)
-})();
-
-(function testObjectAssignmentPattern() {
-  var a, b, x, y, z, q;
-  ({
-    a = function() {},
-    b = () => {},
-    x = function withName() { },
-    y = class { },
-    z = class ClassName { },
-    q = class { static name() { return 42 } },
-    foo: bar = function() {},
-    inParens = (() => {}),
-    inManyParens = ((((() => {})))),
-  } = {});
-  assertEquals('a', a.name);
-  assertEquals('b', b.name);
-  assertEquals('withName', x.name);
-  assertEquals('y', y.name);
-  assertEquals('ClassName', z.name);
-  assertEquals('function', typeof q.name);
-  assertEquals('bar', bar.name);
-  assertEquals('inParens', inParens.name)
-  assertEquals('inManyParens', inManyParens.name)
-})();
-
-(function testArrayAssignmentPattern() {
-  var a, b, x, y, z, q;
-  [
-    a = function() {},
-    b = () => {},
-    x = function withName() { },
-    y = class { },
-    z = class ClassName { },
-    q = class { static name() { return 42 } },
-    inParens = (() => {}),
-    inManyParens = ((((() => {})))),
-  ] = [];
-  assertEquals('a', a.name);
-  assertEquals('b', b.name);
-  assertEquals('withName', x.name);
-  assertEquals('y', y.name);
-  assertEquals('ClassName', z.name);
-  assertEquals('function', typeof q.name);
-  assertEquals('inParens', inParens.name)
-  assertEquals('inManyParens', inManyParens.name)
-})();
-
-(function testParameterDestructuring() {
-  (function({ a = function() {},
-              b = () => {},
-              x = function withName() { },
-              y = class { },
-              z = class ClassName { },
-              q = class { static name() { return 42 } },
-              foo: bar = function() {},
-              inParens = (() => {}),
-              inManyParens = ((((() => {})))) }) {
-    assertEquals('a', a.name);
-    assertEquals('b', b.name);
-    assertEquals('withName', x.name);
-    assertEquals('y', y.name);
-    assertEquals('ClassName', z.name);
-    assertEquals('function', typeof q.name);
-    assertEquals('bar', bar.name);
-    assertEquals('inParens', inParens.name)
-    assertEquals('inManyParens', inManyParens.name)
-  })({});
-
-  (function([ a = function() {},
-              b = () => {},
-              x = function withName() { },
-              y = class { },
-              z = class ClassName { },
-              q = class { static name() { return 42 } },
-              inParens = (() => {}),
-              inManyParens = ((((() => {})))) ]) {
-    assertEquals('a', a.name);
-    assertEquals('b', b.name);
-    assertEquals('withName', x.name);
-    assertEquals('y', y.name);
-    assertEquals('ClassName', z.name);
-    assertEquals('function', typeof q.name);
-    assertEquals('inParens', inParens.name)
-    assertEquals('inManyParens', inManyParens.name)
-  })([]);
-})();
-
-(function testDefaultParameters() {
-  (function(a = function() {},
-            b = () => {},
-            x = function withName() { },
-            y = class { },
-            z = class ClassName { },
-            q = class { static name() { return 42 } },
-            inParens = (() => {}),
-            inManyParens = ((((() => {}))))) {
-    assertEquals('a', a.name);
-    assertEquals('b', b.name);
-    assertEquals('withName', x.name);
-    assertEquals('y', y.name);
-    assertEquals('ClassName', z.name);
-    assertEquals('function', typeof q.name);
-    assertEquals('inParens', inParens.name)
-    assertEquals('inManyParens', inManyParens.name)
-  })();
-})();
-
-(function testComputedNameNotShared() {
-  function makeClass(propName) {
-    return class {
-      static [propName]() {}
-    }
-  }
-
-  var sym1 = Symbol('1');
-  var sym2 = Symbol('2');
-  var class1 = makeClass(sym1);
-  assertEquals('[1]', class1[sym1].name);
-  var class2 = makeClass(sym2);
-  assertEquals('[2]', class2[sym2].name);
-  assertEquals('[1]', class1[sym1].name);
-})();
-
-
-(function testComputedNamesOnlyAppliedSyntactically() {
-  function factory() { return () => {}; }
-
-  var obj = { ['foo']: factory() };
-  assertEquals('', obj.foo.name);
-})();
-
-
-(function testNameNotReflectedInToString() {
-  var f = function() {};
-  var g = function*() {};
-  var obj = {
-    ['h']: function() {},
-    i: () => {}
-  };
-  assertEquals('function () {}', f.toString());
-  assertEquals('function* () {}', g.toString());
-  assertEquals('function () {}', obj.h.toString());
-  assertEquals('() => {}', obj.i.toString());
-})();
diff --git a/test/mjsunit/harmony/function-sent.js b/test/mjsunit/harmony/function-sent.js
index b3cd644..cd0ca95 100644
--- a/test/mjsunit/harmony/function-sent.js
+++ b/test/mjsunit/harmony/function-sent.js
@@ -49,7 +49,7 @@
     try {
       yield function.sent;
     } finally {
-      return 666;
+      return 23;
     }
   }
 
@@ -77,7 +77,7 @@
     let x = g();
     assertEquals({value: 1, done: false}, x.next(1));
     assertEquals({value: undefined, done: false}, x.next(2));
-    assertEquals({value: 42, done: true}, x.return(42));
+    assertEquals({value: 23, done: true}, x.return(42));
   }
 }
 
diff --git a/test/mjsunit/harmony/generators-turbo.js b/test/mjsunit/harmony/generators-turbo.js
new file mode 100644
index 0000000..23913e4
--- /dev/null
+++ b/test/mjsunit/harmony/generators-turbo.js
@@ -0,0 +1,655 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --ignition --ignition-generators --harmony-do-expressions
+// Flags: --allow-natives-syntax --turbo --turbo-from-bytecode
+
+
+// This file is identical to mjsunit/harmony/generators.js, except for its Flags
+// lines. The purpose is to explicitly mention --turbo-from-bytecode such that
+// Clusterfuzz can thoroughly test the new generators implementation.
+
+
+function MaybeOptimizeOrDeoptimize(f) {
+  let x = Math.random();  // --random-seed makes this deterministic
+  if (x <= 0.33) {
+    %OptimizeFunctionOnNextCall(f);
+  } else if (x <= 0.66) {
+    %DeoptimizeFunction(f);
+  }
+}
+
+function Next(generator, ...args) {
+  MaybeOptimizeOrDeoptimize(%GeneratorGetFunction(generator));
+  return generator.next(...args);
+}
+
+function Return(generator, ...args) {
+  MaybeOptimizeOrDeoptimize(%GeneratorGetFunction(generator));
+  return generator.return(...args);
+}
+
+function Throw(generator, ...args) {
+  MaybeOptimizeOrDeoptimize(%GeneratorGetFunction(generator));
+  return generator.throw(...args);
+}
+
+
+{ // yield in try-catch
+
+  let g = function*() {
+    try {yield 1} catch (error) {assertEquals("caught", error)}
+  };
+
+  assertThrowsEquals(() => Throw(g(), "not caught"), "not caught");
+
+  {
+    let x = g();
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: undefined, done: true}, Throw(x, "caught"));
+  }
+
+  {
+    let x = g();
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: undefined, done: true}, Next(x));
+    assertThrowsEquals(() => Throw(x, "not caught"), "not caught");
+  }
+}
+
+
+{ // return that doesn't close
+  let g = function*() { try {return 42} finally {yield 43} };
+
+  {
+    let x = g();
+    assertEquals({value: 43, done: false}, Next(x));
+    assertEquals({value: 42, done: true}, Next(x));
+  }
+}
+
+
+{ // return that doesn't close
+  let x;
+  let g = function*() { try {return 42} finally {Throw(x, 666)} };
+
+  {
+    x = g();
+    assertThrows(() => Next(x), TypeError);  // still executing
+  }
+}
+
+
+{ // yield in try-finally, finally clause performs return
+
+  let g = function*() { try {yield 42} finally {return 13} };
+
+  { // "return" closes at suspendedStart
+    let x = g();
+    assertEquals({value: 666, done: true}, Return(x, 666));
+    assertEquals({value: undefined, done: true}, Next(x, 42));
+    assertThrowsEquals(() => Throw(x, 43), 43);
+    assertEquals({value: 42, done: true}, Return(x, 42));
+  }
+
+  { // "throw" closes at suspendedStart
+    let x = g();
+    assertThrowsEquals(() => Throw(x, 666), 666);
+    assertEquals({value: undefined, done: true}, Next(x, 42));
+    assertEquals({value: 43, done: true}, Return(x, 43));
+    assertThrowsEquals(() => Throw(x, 44), 44);
+  }
+
+  { // "next" closes at suspendedYield
+    let x = g();
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 13, done: true}, Next(x, 666));
+    assertEquals({value: undefined, done: true}, Next(x, 666));
+    assertThrowsEquals(() => Throw(x, 666), 666);
+  }
+
+  { // "return" closes at suspendedYield
+    let x = g();
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 13, done: true}, Return(x, 666));
+    assertEquals({value: undefined, done: true}, Next(x, 666));
+    assertEquals({value: 666, done: true}, Return(x, 666));
+  }
+
+  { // "throw" closes at suspendedYield
+    let x = g();
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 13, done: true}, Throw(x, 666));
+    assertThrowsEquals(() => Throw(x, 666), 666);
+    assertEquals({value: undefined, done: true}, Next(x, 666));
+  }
+}
+
+
+{ // yield in try-finally, finally clause doesn't perform return
+
+  let g = function*() { try {yield 42} finally {13} };
+
+  { // "return" closes at suspendedStart
+    let x = g();
+    assertEquals({value: 666, done: true}, Return(x, 666));
+    assertEquals({value: undefined, done: true}, Next(x, 42));
+    assertThrowsEquals(() => Throw(x, 43), 43);
+    assertEquals({value: 42, done: true}, Return(x, 42));
+  }
+
+  { // "throw" closes at suspendedStart
+    let x = g();
+    assertThrowsEquals(() => Throw(x, 666), 666);
+    assertEquals({value: undefined, done: true}, Next(x, 42));
+    assertEquals({value: 43, done: true}, Return(x, 43));
+    assertThrowsEquals(() => Throw(x, 44), 44);
+  }
+
+  { // "next" closes at suspendedYield
+    let x = g();
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: undefined, done: true}, Next(x, 666));
+    assertEquals({value: undefined, done: true}, Next(x, 666));
+    assertThrowsEquals(() => Throw(x, 666), 666);
+    assertEquals({value: 42, done: true}, Return(x, 42));
+  }
+
+  { // "return" closes at suspendedYield
+    let x = g();
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 666, done: true}, Return(x, 666));
+    assertEquals({value: undefined, done: true}, Next(x, 666));
+    assertThrowsEquals(() => Throw(x, 44), 44);
+    assertEquals({value: 42, done: true}, Return(x, 42));
+  }
+
+  { // "throw" closes at suspendedYield
+    let x = g();
+    assertEquals({value: 42, done: false}, Next(x));
+    assertThrowsEquals(() => Throw(x, 666), 666);
+    assertEquals({value: undefined, done: true}, Next(x, 666));
+    assertThrowsEquals(() => Throw(x, 666), 666);
+    assertEquals({value: 42, done: true}, Return(x, 42));
+  }
+}
+
+
+{ // yield in try-finally, finally clause yields and performs return
+
+  let g = function*() { try {yield 42} finally {yield 43; return 13} };
+
+  {
+    let x = g();
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 43, done: false}, Return(x, 666));
+    assertEquals({value: 13, done: true}, Next(x));
+    assertEquals({value: 666, done: true}, Return(x, 666));
+  }
+
+  {
+    let x = g();
+    assertEquals({value: 666, done: true}, Return(x, 666));
+    assertEquals({value: undefined, done: true}, Next(x));
+    assertEquals({value: 666, done: true}, Return(x, 666));
+  }
+}
+
+
+{ // yield in try-finally, finally clause yields and doesn't perform return
+
+  let g = function*() { try {yield 42} finally {yield 43; 13} };
+
+  {
+    let x = g();
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 43, done: false}, Return(x, 666));
+    assertEquals({value: 666, done: true}, Next(x));
+    assertEquals({value: 5, done: true}, Return(x, 5));
+  }
+
+  {
+    let x = g();
+    assertEquals({value: 666, done: true}, Return(x, 666));
+    assertEquals({value: undefined, done: true}, Next(x));
+    assertEquals({value: 666, done: true}, Return(x, 666));
+  }
+}
+
+
+{ // yield*, finally clause performs return
+
+  let h = function*() { try {yield 42} finally {yield 43; return 13} };
+  let g = function*() { yield 1; yield yield* h(); };
+
+  {
+    let x = g();
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 43, done: false}, Next(x, 666));
+    assertEquals({value: 13, done: false}, Next(x));
+    assertEquals({value: undefined, done: true}, Next(x));
+  }
+
+  {
+    let x = g();
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 43, done: false}, Return(x, 666));
+    assertEquals({value: 13, done: false}, Next(x));
+    assertEquals({value: undefined, done: true}, Next(x));
+  }
+
+  {
+    let x = g();
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 43, done: false}, Throw(x, 666));
+    assertEquals({value: 13, done: false}, Next(x));
+    assertEquals({value: undefined, done: true}, Next(x));
+  }
+}
+
+
+{ // yield*, finally clause does not perform return
+
+  let h = function*() { try {yield 42} finally {yield 43; 13} };
+  let g = function*() { yield 1; yield yield* h(); };
+
+  {
+    let x = g();
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 43, done: false}, Next(x, 666));
+    assertEquals({value: undefined, done: false}, Next(x));
+    assertEquals({value: undefined, done: true}, Next(x));
+  }
+
+  {
+    let x = g();
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 43, done: false}, Return(x, 44));
+    assertEquals({value: 44, done: false}, Next(x));
+    assertEquals({value: undefined, done: true}, Next(x));
+  }
+
+  {
+    let x = g();
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 43, done: false}, Throw(x, 666));
+    assertThrowsEquals(() => Next(x), 666);
+  }
+}
+
+
+{ // yield*, .return argument is final result
+
+  function* inner() {
+    yield 2;
+  }
+
+  function* g() {
+    yield 1;
+    return yield* inner();
+  }
+
+  {
+    let x = g();
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: 2, done: false}, Next(x));
+    assertEquals({value: 42, done: true}, Return(x, 42));
+  }
+}
+
+
+// More or less random tests from here on.
+
+
+{
+  function* foo() { }
+  let g = foo();
+  assertEquals({value: undefined, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo() { return new.target }
+  let g = foo();
+  assertEquals({value: undefined, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo() { throw 666; return 42}
+  let g = foo();
+  assertThrowsEquals(() => Next(g), 666);
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo(a) { return a; }
+  let g = foo(42);
+  assertEquals({value: 42, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo(a) { a.iwashere = true; return a; }
+  let x = {};
+  let g = foo(x);
+  assertEquals({value: {iwashere: true}, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  let a = 42;
+  function* foo() { return a; }
+  let g = foo();
+  assertEquals({value: 42, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  let a = 40;
+  function* foo(b) { return a + b; }
+  let g = foo(2);
+  assertEquals({value: 42, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  let a = 40;
+  function* foo(b) { a--; b++; return a + b; }
+  let g = foo(2);
+  assertEquals({value: 42, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  let g;
+  function* foo() { Next(g) }
+  g = foo();
+  assertThrows(() => Next(g), TypeError);
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo() { yield 2; yield 3; yield 4 }
+  g = foo();
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 4, done: false}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+
+{
+  function* foo() { yield 2; if (true) { yield 3 }; yield 4 }
+  g = foo();
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 4, done: false}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo() { yield 2; if (true) { yield 3; yield 4 } }
+  g = foo();
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 4, done: false}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo() { yield 2; if (false) { yield 3 }; yield 4 }
+  g = foo();
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 4, done: false}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo() { yield 2; while (true) { yield 3 }; yield 4 }
+  g = foo();
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+}
+
+{
+  function* foo() { yield 2; (yield 3) + 42; yield 4 }
+  g = foo();
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 4, done: false}, Next(g));
+}
+
+{
+  function* foo() { yield 2; (do {yield 3}) + 42; yield 4 }
+  g = foo();
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 4, done: false}, Next(g));
+}
+
+{
+  function* foo() { yield 2; return (yield 3) + 42; yield 4 }
+  g = foo();
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 42, done: true}, Next(g, 0));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  let x = 42;
+  function* foo() {
+    yield x;
+    for (let x in {a: 1, b: 2}) {
+      let i = 2;
+      yield x;
+      yield i;
+      do {
+        yield i;
+      } while (i-- > 0);
+    }
+    yield x;
+    return 5;
+  }
+  g = foo();
+  assertEquals({value: 42, done: false}, Next(g));
+  assertEquals({value: 'a', done: false}, Next(g));
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 1, done: false}, Next(g));
+  assertEquals({value: 0, done: false}, Next(g));
+  assertEquals({value: 'b', done: false}, Next(g));
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 1, done: false}, Next(g));
+  assertEquals({value: 0, done: false}, Next(g));
+  assertEquals({value: 42, done: false}, Next(g));
+  assertEquals({value: 5, done: true}, Next(g));
+}
+
+{
+  let a = 3;
+  function* foo() {
+    let b = 4;
+    yield 1;
+    { let c = 5; yield 2; yield a; yield b; yield c; }
+  }
+  g = foo();
+  assertEquals({value: 1, done: false}, Next(g));
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 4, done: false}, Next(g));
+  assertEquals({value: 5, done: false}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo() {
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+  }
+  g = foo();
+  for (let i = 0; i < 100; ++i) {
+    assertEquals({value: 42, done: false}, i%25 === 0 ? Next(g) : g.next());
+  }
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo() {
+    for (let i = 0; i < 3; ++i) {
+      let j = 0
+      yield i;
+      do {
+        yield (i + 10);
+      } while (++j < 2);
+    }
+  }
+  g = foo();
+  assertEquals({value: 0, done: false}, Next(g));
+  assertEquals({value: 10, done: false}, Next(g));
+  assertEquals({value: 10, done: false}, Next(g));
+  assertEquals({value: 1, done: false}, Next(g));
+  assertEquals({value: 11, done: false}, Next(g));
+  assertEquals({value: 11, done: false}, Next(g));
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 12, done: false}, Next(g));
+  assertEquals({value: 12, done: false}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  let foo = function*() {
+    while (true) {
+      if (true || false) yield 42;
+      continue;
+    }
+  }
+  g = foo();
+  assertEquals({value: 42, done: false}, Next(g));
+  assertEquals({value: 42, done: false}, Next(g));
+  assertEquals({value: 42, done: false}, Next(g));
+}
+
+{
+  let foo = function*() {
+    yield* (function*() { yield 42; }());
+    assertUnreachable();
+  }
+  g = foo();
+  assertEquals({value: 42, done: false}, Next(g));
+  assertEquals({value: 23, done: true}, Return(g, 23));
+}
diff --git a/test/mjsunit/harmony/generators.js b/test/mjsunit/harmony/generators.js
index df6cec8..eb4e51e 100644
--- a/test/mjsunit/harmony/generators.js
+++ b/test/mjsunit/harmony/generators.js
@@ -2,6 +2,34 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Flags: --ignition-generators --harmony-do-expressions
+// Flags: --allow-natives-syntax
+
+
+function MaybeOptimizeOrDeoptimize(f) {
+  let x = Math.random();  // --random-seed makes this deterministic
+  if (x <= 0.33) {
+    %OptimizeFunctionOnNextCall(f);
+  } else if (x <= 0.66) {
+    %DeoptimizeFunction(f);
+  }
+}
+
+function Next(generator, ...args) {
+  MaybeOptimizeOrDeoptimize(%GeneratorGetFunction(generator));
+  return generator.next(...args);
+}
+
+function Return(generator, ...args) {
+  MaybeOptimizeOrDeoptimize(%GeneratorGetFunction(generator));
+  return generator.return(...args);
+}
+
+function Throw(generator, ...args) {
+  MaybeOptimizeOrDeoptimize(%GeneratorGetFunction(generator));
+  return generator.throw(...args);
+}
+
 
 { // yield in try-catch
 
@@ -9,19 +37,19 @@
     try {yield 1} catch (error) {assertEquals("caught", error)}
   };
 
-  assertThrowsEquals(() => g().throw("not caught"), "not caught");
+  assertThrowsEquals(() => Throw(g(), "not caught"), "not caught");
 
   {
     let x = g();
-    assertEquals({value: 1, done: false}, x.next());
-    assertEquals({value: undefined, done: true}, x.throw("caught"));
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: undefined, done: true}, Throw(x, "caught"));
   }
 
   {
     let x = g();
-    assertEquals({value: 1, done: false}, x.next());
-    assertEquals({value: undefined, done: true}, x.next());
-    assertThrowsEquals(() => x.throw("not caught"), "not caught");
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: undefined, done: true}, Next(x));
+    assertThrowsEquals(() => Throw(x, "not caught"), "not caught");
   }
 }
 
@@ -31,19 +59,19 @@
 
   {
     let x = g();
-    assertEquals({value: 43, done: false}, x.next());
-    assertEquals({value: 42, done: true}, x.next());
+    assertEquals({value: 43, done: false}, Next(x));
+    assertEquals({value: 42, done: true}, Next(x));
   }
 }
 
 
 { // return that doesn't close
   let x;
-  let g = function*() { try {return 42} finally {x.throw(666)} };
+  let g = function*() { try {return 42} finally {Throw(x, 666)} };
 
   {
     x = g();
-    assertThrows(() => x.next(), TypeError);  // still executing
+    assertThrows(() => Next(x), TypeError);  // still executing
   }
 }
 
@@ -54,42 +82,42 @@
 
   { // "return" closes at suspendedStart
     let x = g();
-    assertEquals({value: 666, done: true}, x.return(666));
-    assertEquals({value: undefined, done: true}, x.next(42));
-    assertThrowsEquals(() => x.throw(43), 43);
-    assertEquals({value: 42, done: true}, x.return(42));
+    assertEquals({value: 666, done: true}, Return(x, 666));
+    assertEquals({value: undefined, done: true}, Next(x, 42));
+    assertThrowsEquals(() => Throw(x, 43), 43);
+    assertEquals({value: 42, done: true}, Return(x, 42));
   }
 
   { // "throw" closes at suspendedStart
     let x = g();
-    assertThrowsEquals(() => x.throw(666), 666);
-    assertEquals({value: undefined, done: true}, x.next(42));
-    assertEquals({value: 43, done: true}, x.return(43));
-    assertThrowsEquals(() => x.throw(44), 44);
+    assertThrowsEquals(() => Throw(x, 666), 666);
+    assertEquals({value: undefined, done: true}, Next(x, 42));
+    assertEquals({value: 43, done: true}, Return(x, 43));
+    assertThrowsEquals(() => Throw(x, 44), 44);
   }
 
   { // "next" closes at suspendedYield
     let x = g();
-    assertEquals({value: 42, done: false}, x.next());
-    assertEquals({value: 13, done: true}, x.next(666));
-    assertEquals({value: undefined, done: true}, x.next(666));
-    assertThrowsEquals(() => x.throw(666), 666);
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 13, done: true}, Next(x, 666));
+    assertEquals({value: undefined, done: true}, Next(x, 666));
+    assertThrowsEquals(() => Throw(x, 666), 666);
   }
 
   { // "return" closes at suspendedYield
     let x = g();
-    assertEquals({value: 42, done: false}, x.next());
-    assertEquals({value: 13, done: true}, x.return(666));
-    assertEquals({value: undefined, done: true}, x.next(666));
-    assertEquals({value: 666, done: true}, x.return(666));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 13, done: true}, Return(x, 666));
+    assertEquals({value: undefined, done: true}, Next(x, 666));
+    assertEquals({value: 666, done: true}, Return(x, 666));
   }
 
   { // "throw" closes at suspendedYield
     let x = g();
-    assertEquals({value: 42, done: false}, x.next());
-    assertEquals({value: 13, done: true}, x.throw(666));
-    assertThrowsEquals(() => x.throw(666), 666);
-    assertEquals({value: undefined, done: true}, x.next(666));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 13, done: true}, Throw(x, 666));
+    assertThrowsEquals(() => Throw(x, 666), 666);
+    assertEquals({value: undefined, done: true}, Next(x, 666));
   }
 }
 
@@ -100,45 +128,45 @@
 
   { // "return" closes at suspendedStart
     let x = g();
-    assertEquals({value: 666, done: true}, x.return(666));
-    assertEquals({value: undefined, done: true}, x.next(42));
-    assertThrowsEquals(() => x.throw(43), 43);
-    assertEquals({value: 42, done: true}, x.return(42));
+    assertEquals({value: 666, done: true}, Return(x, 666));
+    assertEquals({value: undefined, done: true}, Next(x, 42));
+    assertThrowsEquals(() => Throw(x, 43), 43);
+    assertEquals({value: 42, done: true}, Return(x, 42));
   }
 
   { // "throw" closes at suspendedStart
     let x = g();
-    assertThrowsEquals(() => x.throw(666), 666);
-    assertEquals({value: undefined, done: true}, x.next(42));
-    assertEquals({value: 43, done: true}, x.return(43));
-    assertThrowsEquals(() => x.throw(44), 44);
+    assertThrowsEquals(() => Throw(x, 666), 666);
+    assertEquals({value: undefined, done: true}, Next(x, 42));
+    assertEquals({value: 43, done: true}, Return(x, 43));
+    assertThrowsEquals(() => Throw(x, 44), 44);
   }
 
   { // "next" closes at suspendedYield
     let x = g();
-    assertEquals({value: 42, done: false}, x.next());
-    assertEquals({value: undefined, done: true}, x.next(666));
-    assertEquals({value: undefined, done: true}, x.next(666));
-    assertThrowsEquals(() => x.throw(666), 666);
-    assertEquals({value: 42, done: true}, x.return(42));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: undefined, done: true}, Next(x, 666));
+    assertEquals({value: undefined, done: true}, Next(x, 666));
+    assertThrowsEquals(() => Throw(x, 666), 666);
+    assertEquals({value: 42, done: true}, Return(x, 42));
   }
 
   { // "return" closes at suspendedYield
     let x = g();
-    assertEquals({value: 42, done: false}, x.next());
-    assertEquals({value: 666, done: true}, x.return(666));
-    assertEquals({value: undefined, done: true}, x.next(666));
-    assertThrowsEquals(() => x.throw(44), 44);
-    assertEquals({value: 42, done: true}, x.return(42));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 666, done: true}, Return(x, 666));
+    assertEquals({value: undefined, done: true}, Next(x, 666));
+    assertThrowsEquals(() => Throw(x, 44), 44);
+    assertEquals({value: 42, done: true}, Return(x, 42));
   }
 
   { // "throw" closes at suspendedYield
     let x = g();
-    assertEquals({value: 42, done: false}, x.next());
-    assertThrowsEquals(() => x.throw(666), 666);
-    assertEquals({value: undefined, done: true}, x.next(666));
-    assertThrowsEquals(() => x.throw(666), 666);
-    assertEquals({value: 42, done: true}, x.return(42));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertThrowsEquals(() => Throw(x, 666), 666);
+    assertEquals({value: undefined, done: true}, Next(x, 666));
+    assertThrowsEquals(() => Throw(x, 666), 666);
+    assertEquals({value: 42, done: true}, Return(x, 42));
   }
 }
 
@@ -149,17 +177,17 @@
 
   {
     let x = g();
-    assertEquals({value: 42, done: false}, x.next());
-    assertEquals({value: 43, done: false}, x.return(666));
-    assertEquals({value: 13, done: true}, x.next());
-    assertEquals({value: 666, done: true}, x.return(666));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 43, done: false}, Return(x, 666));
+    assertEquals({value: 13, done: true}, Next(x));
+    assertEquals({value: 666, done: true}, Return(x, 666));
   }
 
   {
     let x = g();
-    assertEquals({value: 666, done: true}, x.return(666));
-    assertEquals({value: undefined, done: true}, x.next());
-    assertEquals({value: 666, done: true}, x.return(666));
+    assertEquals({value: 666, done: true}, Return(x, 666));
+    assertEquals({value: undefined, done: true}, Next(x));
+    assertEquals({value: 666, done: true}, Return(x, 666));
   }
 }
 
@@ -170,17 +198,17 @@
 
   {
     let x = g();
-    assertEquals({value: 42, done: false}, x.next());
-    assertEquals({value: 43, done: false}, x.return(666));
-    assertEquals({value: 666, done: true}, x.next());
-    assertEquals({value: 5, done: true}, x.return(5));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 43, done: false}, Return(x, 666));
+    assertEquals({value: 666, done: true}, Next(x));
+    assertEquals({value: 5, done: true}, Return(x, 5));
   }
 
   {
     let x = g();
-    assertEquals({value: 666, done: true}, x.return(666));
-    assertEquals({value: undefined, done: true}, x.next());
-    assertEquals({value: 666, done: true}, x.return(666));
+    assertEquals({value: 666, done: true}, Return(x, 666));
+    assertEquals({value: undefined, done: true}, Next(x));
+    assertEquals({value: 666, done: true}, Return(x, 666));
   }
 }
 
@@ -192,29 +220,29 @@
 
   {
     let x = g();
-    assertEquals({value: 1, done: false}, x.next());
-    assertEquals({value: 42, done: false}, x.next());
-    assertEquals({value: 43, done: false}, x.next(666));
-    assertEquals({value: 13, done: false}, x.next());
-    assertEquals({value: undefined, done: true}, x.next());
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 43, done: false}, Next(x, 666));
+    assertEquals({value: 13, done: false}, Next(x));
+    assertEquals({value: undefined, done: true}, Next(x));
   }
 
   {
     let x = g();
-    assertEquals({value: 1, done: false}, x.next());
-    assertEquals({value: 42, done: false}, x.next());
-    assertEquals({value: 43, done: false}, x.return(666));
-    assertEquals({value: 13, done: false}, x.next());
-    assertEquals({value: undefined, done: true}, x.next());
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 43, done: false}, Return(x, 666));
+    assertEquals({value: 13, done: false}, Next(x));
+    assertEquals({value: undefined, done: true}, Next(x));
   }
 
   {
     let x = g();
-    assertEquals({value: 1, done: false}, x.next());
-    assertEquals({value: 42, done: false}, x.next());
-    assertEquals({value: 43, done: false}, x.throw(666));
-    assertEquals({value: 13, done: false}, x.next());
-    assertEquals({value: undefined, done: true}, x.next());
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 43, done: false}, Throw(x, 666));
+    assertEquals({value: 13, done: false}, Next(x));
+    assertEquals({value: undefined, done: true}, Next(x));
   }
 }
 
@@ -226,28 +254,28 @@
 
   {
     let x = g();
-    assertEquals({value: 1, done: false}, x.next());
-    assertEquals({value: 42, done: false}, x.next());
-    assertEquals({value: 43, done: false}, x.next(666));
-    assertEquals({value: undefined, done: false}, x.next());
-    assertEquals({value: undefined, done: true}, x.next());
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 43, done: false}, Next(x, 666));
+    assertEquals({value: undefined, done: false}, Next(x));
+    assertEquals({value: undefined, done: true}, Next(x));
   }
 
   {
     let x = g();
-    assertEquals({value: 1, done: false}, x.next());
-    assertEquals({value: 42, done: false}, x.next());
-    assertEquals({value: 43, done: false}, x.return(44));
-    assertEquals({value: 44, done: false}, x.next());
-    assertEquals({value: undefined, done: true}, x.next());
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 43, done: false}, Return(x, 44));
+    assertEquals({value: 44, done: false}, Next(x));
+    assertEquals({value: undefined, done: true}, Next(x));
   }
 
   {
     let x = g();
-    assertEquals({value: 1, done: false}, x.next());
-    assertEquals({value: 42, done: false}, x.next());
-    assertEquals({value: 43, done: false}, x.throw(666));
-    assertThrowsEquals(() => x.next(), 666);
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: 42, done: false}, Next(x));
+    assertEquals({value: 43, done: false}, Throw(x, 666));
+    assertThrowsEquals(() => Next(x), 666);
   }
 }
 
@@ -265,8 +293,358 @@
 
   {
     let x = g();
-    assertEquals({value: 1, done: false}, x.next());
-    assertEquals({value: 2, done: false}, x.next());
-    assertEquals({value: 42, done: true}, x.return(42));
+    assertEquals({value: 1, done: false}, Next(x));
+    assertEquals({value: 2, done: false}, Next(x));
+    assertEquals({value: 42, done: true}, Return(x, 42));
   }
 }
+
+
+// More or less random tests from here on.
+
+
+{
+  function* foo() { }
+  let g = foo();
+  assertEquals({value: undefined, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo() { return new.target }
+  let g = foo();
+  assertEquals({value: undefined, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo() { throw 666; return 42}
+  let g = foo();
+  assertThrowsEquals(() => Next(g), 666);
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo(a) { return a; }
+  let g = foo(42);
+  assertEquals({value: 42, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo(a) { a.iwashere = true; return a; }
+  let x = {};
+  let g = foo(x);
+  assertEquals({value: {iwashere: true}, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  let a = 42;
+  function* foo() { return a; }
+  let g = foo();
+  assertEquals({value: 42, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  let a = 40;
+  function* foo(b) { return a + b; }
+  let g = foo(2);
+  assertEquals({value: 42, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  let a = 40;
+  function* foo(b) { a--; b++; return a + b; }
+  let g = foo(2);
+  assertEquals({value: 42, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  let g;
+  function* foo() { Next(g) }
+  g = foo();
+  assertThrows(() => Next(g), TypeError);
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo() { yield 2; yield 3; yield 4 }
+  g = foo();
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 4, done: false}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+
+{
+  function* foo() { yield 2; if (true) { yield 3 }; yield 4 }
+  g = foo();
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 4, done: false}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo() { yield 2; if (true) { yield 3; yield 4 } }
+  g = foo();
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 4, done: false}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo() { yield 2; if (false) { yield 3 }; yield 4 }
+  g = foo();
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 4, done: false}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo() { yield 2; while (true) { yield 3 }; yield 4 }
+  g = foo();
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+}
+
+{
+  function* foo() { yield 2; (yield 3) + 42; yield 4 }
+  g = foo();
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 4, done: false}, Next(g));
+}
+
+{
+  function* foo() { yield 2; (do {yield 3}) + 42; yield 4 }
+  g = foo();
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 4, done: false}, Next(g));
+}
+
+{
+  function* foo() { yield 2; return (yield 3) + 42; yield 4 }
+  g = foo();
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 42, done: true}, Next(g, 0));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  let x = 42;
+  function* foo() {
+    yield x;
+    for (let x in {a: 1, b: 2}) {
+      let i = 2;
+      yield x;
+      yield i;
+      do {
+        yield i;
+      } while (i-- > 0);
+    }
+    yield x;
+    return 5;
+  }
+  g = foo();
+  assertEquals({value: 42, done: false}, Next(g));
+  assertEquals({value: 'a', done: false}, Next(g));
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 1, done: false}, Next(g));
+  assertEquals({value: 0, done: false}, Next(g));
+  assertEquals({value: 'b', done: false}, Next(g));
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 1, done: false}, Next(g));
+  assertEquals({value: 0, done: false}, Next(g));
+  assertEquals({value: 42, done: false}, Next(g));
+  assertEquals({value: 5, done: true}, Next(g));
+}
+
+{
+  let a = 3;
+  function* foo() {
+    let b = 4;
+    yield 1;
+    { let c = 5; yield 2; yield a; yield b; yield c; }
+  }
+  g = foo();
+  assertEquals({value: 1, done: false}, Next(g));
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 3, done: false}, Next(g));
+  assertEquals({value: 4, done: false}, Next(g));
+  assertEquals({value: 5, done: false}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo() {
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+    yield 42;
+  }
+  g = foo();
+  for (let i = 0; i < 100; ++i) {
+    assertEquals({value: 42, done: false}, i%25 === 0 ? Next(g) : g.next());
+  }
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  function* foo() {
+    for (let i = 0; i < 3; ++i) {
+      let j = 0
+      yield i;
+      do {
+        yield (i + 10);
+      } while (++j < 2);
+    }
+  }
+  g = foo();
+  assertEquals({value: 0, done: false}, Next(g));
+  assertEquals({value: 10, done: false}, Next(g));
+  assertEquals({value: 10, done: false}, Next(g));
+  assertEquals({value: 1, done: false}, Next(g));
+  assertEquals({value: 11, done: false}, Next(g));
+  assertEquals({value: 11, done: false}, Next(g));
+  assertEquals({value: 2, done: false}, Next(g));
+  assertEquals({value: 12, done: false}, Next(g));
+  assertEquals({value: 12, done: false}, Next(g));
+  assertEquals({value: undefined, done: true}, Next(g));
+}
+
+{
+  let foo = function*() {
+    while (true) {
+      if (true || false) yield 42;
+      continue;
+    }
+  }
+  g = foo();
+  assertEquals({value: 42, done: false}, Next(g));
+  assertEquals({value: 42, done: false}, Next(g));
+  assertEquals({value: 42, done: false}, Next(g));
+}
+
+{
+  let foo = function*() {
+    yield* (function*() { yield 42; }());
+    assertUnreachable();
+  }
+  g = foo();
+  assertEquals({value: 42, done: false}, Next(g));
+  assertEquals({value: 23, done: true}, Return(g, 23));
+}
diff --git a/test/mjsunit/harmony/harmony-string-pad-end.js b/test/mjsunit/harmony/harmony-string-pad-end.js
index 3292e94..03e5aea 100644
--- a/test/mjsunit/harmony/harmony-string-pad-end.js
+++ b/test/mjsunit/harmony/harmony-string-pad-end.js
@@ -67,8 +67,19 @@
 (function TestFillerToString() {
   assertEquals(".         ", ".".padEnd(10));
   assertEquals(".         ", ".".padEnd(10, undefined));
-  assertEquals(".         ", ".".padEnd(10, { toString() { return ""; } }));
   assertEquals(".nullnulln", ".".padEnd(10, null));
+  assertEquals(".XXXXXXXXX", ".".padEnd(10, { toString() { return "X"; } }));
+  assertEquals(
+      ".111111111",
+      ".".padEnd(10, { toString: undefined, valueOf() { return 1; } }));
+})();
+
+
+(function TestFillerEmptyString() {
+  assertEquals(".", ".".padEnd(10, ""));
+  assertEquals(".", ".".padEnd(10, { toString() { return ""; } }));
+  assertEquals(
+      ".", ".".padEnd(10, { toString: undefined, valueOf() { return ""; } }));
 })();
 
 
diff --git a/test/mjsunit/harmony/harmony-string-pad-start.js b/test/mjsunit/harmony/harmony-string-pad-start.js
index 2b2d004..33bf8f3 100644
--- a/test/mjsunit/harmony/harmony-string-pad-start.js
+++ b/test/mjsunit/harmony/harmony-string-pad-start.js
@@ -67,8 +67,19 @@
 (function TestFillerToString() {
   assertEquals("         .", ".".padStart(10));
   assertEquals("         .", ".".padStart(10, undefined));
-  assertEquals("         .", ".".padStart(10, { toString() { return ""; } }));
   assertEquals("nullnulln.", ".".padStart(10, null));
+  assertEquals("XXXXXXXXX.", ".".padStart(10, { toString() { return "X"; } }));
+  assertEquals(
+      "111111111.",
+      ".".padStart(10, { toString: undefined, valueOf() { return 1; } }));
+})();
+
+
+(function TestFillerEmptyString() {
+  assertEquals(".", ".".padStart(10, ""));
+  assertEquals(".", ".".padStart(10, { toString() { return ""; } }));
+  assertEquals(
+      ".", ".".padStart(10, { toString: undefined, valueOf() { return ""; } }));
 })();
 
 
diff --git a/test/mjsunit/harmony/instanceof-es6.js b/test/mjsunit/harmony/instanceof-es6.js
deleted file mode 100644
index 60e7ee2..0000000
--- a/test/mjsunit/harmony/instanceof-es6.js
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-instanceof
-
-// Make sure it's an error if @@hasInstance isn't a function.
-(function() {
-  var F = {};
-  F[Symbol.hasInstance] = null;
-  assertThrows(function() { 0 instanceof F; }, TypeError);
-})();
-
-// Make sure the result is coerced to boolean.
-(function() {
-  var F = {};
-  F[Symbol.hasInstance] = function() { return undefined; };
-  assertEquals(0 instanceof F, false);
-  F[Symbol.hasInstance] = function() { return null; };
-  assertEquals(0 instanceof F, false);
-  F[Symbol.hasInstance] = function() { return true; };
-  assertEquals(0 instanceof F, true);
-})();
-
-// Make sure if @@hasInstance throws, we catch it.
-(function() {
-  var F = {};
-  F[Symbol.hasInstance] = function() { throw new Error("always throws"); }
-  try {
-    0 instanceof F;
-  } catch (e) {
-    assertEquals(e.message, "always throws");
-  }
-})();
-
-// @@hasInstance works for bound functions.
-(function() {
-  var BC = function() {};
-  var bc = new BC();
-  var bound = BC.bind();
-  assertEquals(bound[Symbol.hasInstance](bc), true);
-  assertEquals(bound[Symbol.hasInstance]([]), false);
-})();
-
-// if OrdinaryHasInstance is passed a non-callable receiver, return false.
-assertEquals(Function.prototype[Symbol.hasInstance].call(Array, []), true);
-assertEquals(Function.prototype[Symbol.hasInstance].call({}, {}), false);
-
-// OrdinaryHasInstance passed a non-object argument returns false.
-assertEquals(Function.prototype[Symbol.hasInstance].call(Array, 0), false);
diff --git a/test/mjsunit/harmony/iterator-close.js b/test/mjsunit/harmony/iterator-close.js
deleted file mode 100644
index 09e0153..0000000
--- a/test/mjsunit/harmony/iterator-close.js
+++ /dev/null
@@ -1,1240 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-iterator-close
-
-
-function* g() { yield 42; return 88 };
-
-
-// Return method is "undefined".
-{
-  g.prototype.return = null;
-
-
-  assertEquals(undefined, (() => {
-    for (var x of g()) { break; }
-  })());
-
-  assertEquals(undefined, (() => {
-    for (let x of g()) { break; }
-  })());
-
-  assertEquals(undefined, (() => {
-    for (const x of g()) { break; }
-  })());
-
-  assertEquals(undefined, (() => {
-    for (x of g()) { break; }
-  })());
-
-
-  assertThrowsEquals(() => {
-    for (var x of g()) { throw 42; }
-  }, 42);
-
-  assertThrowsEquals(() => {
-    for (let x of g()) { throw 42; }
-  }, 42);
-
-  assertThrowsEquals(() => {
-    for (const x of g()) { throw 42; }
-  }, 42);
-
-  assertThrowsEquals(() => {
-    for (x of g()) { throw 42; }
-  }, 42);
-
-
-  assertEquals(42, (() => {
-    for (var x of g()) { return 42; }
-  })());
-
-  assertEquals(42, (() => {
-    for (let x of g()) { return 42; }
-  })());
-
-  assertEquals(42, (() => {
-    for (const x of g()) { return 42; }
-  })());
-
-  assertEquals(42, (() => {
-    for (x of g()) { return 42; }
-  })());
-
-
-  assertEquals(42, eval('for (var x of g()) { x; }'));
-
-  assertEquals(42, eval('for (let x of g()) { x; }'));
-
-  assertEquals(42, eval('for (const x of g()) { x; }'));
-
-  assertEquals(42, eval('for (x of g()) { x; }'));
-
-
-  assertEquals(42, (() => {
-    var [x] = g(); return x;
-  })());
-
-  assertEquals(42, (() => {
-    let [x] = g(); return x;
-  })());
-
-  assertEquals(42, (() => {
-    const [x] = g(); return x;
-  })());
-
-  assertEquals(42, (() => {
-    [x] = g(); return x;
-  })());
-
-  assertEquals(42,
-    (([x]) => x)(g())
-  );
-}
-
-
-// Return method is not callable.
-{
-  g.prototype.return = 666;
-
-
-  assertThrows(() => {
-    for (var x of g()) { break; }
-  }, TypeError);
-
-  assertThrows(() => {
-    for (let x of g()) { break; }
-  }, TypeError);
-
-  assertThrows(() => {
-    for (const x of g()) { break; }
-  }, TypeError);
-
-  assertThrows(() => {
-    for (x of g()) { break; }
-  }, TypeError);
-
-
-  assertThrows(() => {
-    for (var x of g()) { throw 666; }
-  }, TypeError);
-
-  assertThrows(() => {
-    for (let x of g()) { throw 666; }
-  }, TypeError);
-
-  assertThrows(() => {
-    for (const x of g()) { throw 666; }
-  }, TypeError);
-
-  assertThrows(() => {
-    for (x of g()) { throw 666; }
-  }, TypeError);
-
-
-  assertThrows(() => {
-    for (var x of g()) { return 666; }
-  }, TypeError);
-
-  assertThrows(() => {
-    for (let x of g()) { return 666; }
-  }, TypeError);
-
-  assertThrows(() => {
-    for (const x of g()) { return 666; }
-  }, TypeError);
-
-  assertThrows(() => {
-    for (x of g()) { return 666; }
-  }, TypeError);
-
-
-  assertEquals(42, eval('for (var x of g()) { x; }'));
-
-  assertEquals(42, eval('for (let x of g()) { x; }'));
-
-  assertEquals(42, eval('for (const x of g()) { x; }'));
-
-  assertEquals(42, eval('for (x of g()) { x; }'));
-
-
-  assertThrows(() => {
-    var [x] = g(); return x;
-  }, TypeError);
-
-  assertThrows(() => {
-    let [x] = g(); return x;
-  }, TypeError);
-
-  assertThrows(() => {
-    const [x] = g(); return x;
-  }, TypeError);
-
-  assertThrows(() => {
-    [x] = g(); return x;
-  }, TypeError);
-
-  assertThrows(() => {
-    (([x]) => x)(g());
-  }, TypeError);
-}
-
-
-// Return method does not return an object.
-{
-  g.prototype.return = () => 666;
-
-
-  assertThrows(() => {
-    for (var x of g()) { break; }
-  }, TypeError);
-
-  assertThrows(() => {
-    for (let x of g()) { break; }
-  }, TypeError);
-
-  assertThrows(() => {
-    for (const x of g()) { break; }
-  }, TypeError);
-
-  assertThrows(() => {
-    for (x of g()) { break; }
-  }, TypeError);
-
-
-  // Throw from the body of a for loop 'wins' vs throw
-  // originating from a bad 'return' value.
-
-  assertThrowsEquals(() => {
-    for (var x of g()) { throw 666; }
-  }, 666);
-
-  assertThrowsEquals(() => {
-    for (let x of g()) { throw 666; }
-  }, 666);
-
-  assertThrowsEquals(() => {
-    for (const x of g()) { throw 666; }
-  }, 666);
-
-  assertThrowsEquals(() => {
-    for (x of g()) { throw 666; }
-  }, 666);
-
-
-  assertThrows(() => {
-    for (var x of g()) { return 666; }
-  }, TypeError);
-
-  assertThrows(() => {
-    for (let x of g()) { return 666; }
-  }, TypeError);
-
-  assertThrows(() => {
-    for (const x of g()) { return 666; }
-  }, TypeError);
-
-  assertThrows(() => {
-    for (x of g()) { return 666; }
-  }, TypeError);
-
-
-  assertEquals(42, eval('for (var x of g()) { x; }'));
-
-  assertEquals(42, eval('for (let x of g()) { x; }'));
-
-  assertEquals(42, eval('for (const x of g()) { x; }'));
-
-  assertEquals(42, eval('for (x of g()) { x; }'));
-
-
-  assertThrows(() => {
-    var [x] = g(); return x;
-  }, TypeError);
-
-  assertThrows(() => {
-    let [x] = g(); return x;
-  }, TypeError);
-
-  assertThrows(() => {
-    const [x] = g(); return x;
-  }, TypeError);
-
-  assertThrows(() => {
-    [x] = g(); return x;
-  }, TypeError);
-
-  assertThrows(() => {
-    (([x]) => x)(g());
-  }, TypeError);
-}
-
-
-// Return method returns an object.
-{
-  let log = [];
-  g.prototype.return = (...args) => { log.push(args); return {} };
-
-
-  log = [];
-  for (var x of g()) { break; }
-  assertEquals([[]], log);
-
-  log = [];
-  for (let x of g()) { break; }
-  assertEquals([[]], log);
-
-  log = [];
-  for (const x of g()) { break; }
-  assertEquals([[]], log);
-
-  log = [];
-  for (x of g()) { break; }
-  assertEquals([[]], log);
-
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (var x of g()) { throw 42; }
-  }, 42);
-  assertEquals([[]], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (let x of g()) { throw 42; }
-  }, 42);
-  assertEquals([[]], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (const x of g()) { throw 42; }
-  }, 42);
-  assertEquals([[]], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (x of g()) { throw 42; }
-  }, 42);
-  assertEquals([[]], log);
-
-
-  log = [];
-  assertEquals(42, (() => {
-    for (var x of g()) { return 42; }
-  })());
-  assertEquals([[]], log);
-
-  log = [];
-  assertEquals(42, (() => {
-    for (let x of g()) { return 42; }
-  })());
-  assertEquals([[]], log);
-
-  log = [];
-  assertEquals(42, (() => {
-    for (const x of g()) { return 42; }
-  })());
-  assertEquals([[]], log);
-
-  log = [];
-  assertEquals(42, (() => {
-    for (x of g()) { return 42; }
-  })());
-  assertEquals([[]], log);
-
-
-  log = [];
-  assertEquals(42, eval('for (var x of g()) { x; }'));
-  assertEquals([], log);
-
-  log = [];
-  assertEquals(42, eval('for (let x of g()) { x; }'));
-  assertEquals([], log);
-
-  log = [];
-  assertEquals(42, eval('for (const x of g()) { x; }'));
-  assertEquals([], log);
-
-  log = [];
-  assertEquals(42, eval('for (x of g()) { x; }'));
-  assertEquals([], log);
-
-
-  // Even if doing the assignment throws, still call return
-  log = [];
-  x = { set attr(_) { throw 1234; } };
-  assertThrowsEquals(() => {
-    for (x.attr of g()) { throw 456; }
-  }, 1234);
-  assertEquals([[]], log);
-
-
-  log = [];
-  assertEquals(42, (() => {
-    var [x] = g(); return x;
-  })());
-  assertEquals([[]], log);
-
-  log = [];
-  assertEquals(42, (() => {
-    let [x] = g(); return x;
-  })());
-  assertEquals([[]], log);
-
-  log = [];
-  assertEquals(42, (() => {
-    const [x] = g(); return x;
-  })());
-  assertEquals([[]], log);
-
-  log = [];
-  assertEquals(42, (() => {
-    [x] = g(); return x;
-  })());
-  assertEquals([[]], log);
-
-  log = []
-  assertEquals(42,
-    (([x]) => x)(g())
-  );
-  assertEquals([[]], log);
-
-
-  log = [];
-  assertEquals(42, (() => {
-    var [x,] = g(); return x;
-  })());
-  assertEquals([[]], log);
-
-  log = [];
-  assertEquals(42, (() => {
-    let [x,] = g(); return x;
-  })());
-  assertEquals([[]], log);
-
-  log = [];
-  assertEquals(42, (() => {
-    const [x,] = g(); return x;
-  })());
-  assertEquals([[]], log);
-
-  log = [];
-  assertEquals(42, (() => {
-    [x,] = g(); return x;
-  })());
-  assertEquals([[]], log);
-
-  log = []
-  assertEquals(42,
-    (([x,]) => x)(g())
-  );
-  assertEquals([[]], log);
-
-
-  log = [];
-  assertEquals(42, (() => {
-    var [x,,] = g(); return x;
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals(42, (() => {
-    let [x,,] = g(); return x;
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals(42, (() => {
-    const [x,,] = g(); return x;
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals(42, (() => {
-    [x,,] = g(); return x;
-  })());
-  assertEquals([], log);
-
-  log = []
-  assertEquals(42,
-    (([x,,]) => x)(g())
-  );
-  assertEquals([], log);
-
-
-  log = [];
-  assertEquals([42, undefined], (() => {
-    var [x, y] = g(); return [x, y];
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([42, undefined], (() => {
-    let [x, y] = g(); return [x, y];
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([42, undefined], (() => {
-    const [x, y] = g(); return [x, y];
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([42, undefined], (() => {
-    [x, y] = g(); return [x, y];
-  })());
-  assertEquals([], log);
-
-  log = []
-  assertEquals([42, undefined],
-    (([x, y]) => [x, y])(g())
-  );
-  assertEquals([], log);
-
-
-  log = [];
-  assertEquals([42], (() => {
-    var [...x] = g(); return x;
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([42], (() => {
-    let [...x] = g(); return x;
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([42], (() => {
-    const [...x] = g(); return x;
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([42], (() => {
-    [...x] = g(); return x;
-  })());
-  assertEquals([], log);
-
-  log = []
-  assertEquals([42],
-    (([...x]) => x)(g())
-  );
-  assertEquals([], log);
-
-
-  log = [];
-  assertEquals([42, []], (() => {
-    var [x, ...y] = g(); return [x, y];
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([42, []], (() => {
-    let [x, ...y] = g(); return [x, y];
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([42, []], (() => {
-    const [x, ...y] = g(); return [x, y];
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([42, []], (() => {
-    [x, ...y] = g(); return [x, y];
-  })());
-  assertEquals([], log);
-
-  log = []
-  assertEquals([42, []],
-    (([x, ...y]) => [x, y])(g())
-  );
-  assertEquals([], log);
-
-
-  log = [];
-  assertEquals([], (() => {
-    var [] = g(); return [];
-  })());
-  assertEquals([[]], log);
-
-  log = [];
-  assertEquals([], (() => {
-    let [] = g(); return [];
-  })());
-  assertEquals([[]], log);
-
-  log = [];
-  assertEquals([], (() => {
-    const [] = g(); return [];
-  })());
-  assertEquals([[]], log);
-
-  log = [];
-  assertEquals([], (() => {
-    [] = g(); return [];
-  })());
-  assertEquals([[]], log);
-
-  log = []
-  assertEquals([],
-    (([]) => [])(g())
-  );
-  assertEquals([[]], log);
-
-
-  log = [];
-  assertEquals([], (() => {
-    var [...[]] = g(); return [];
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([], (() => {
-    let [...[]] = g(); return [];
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([], (() => {
-    const [...[]] = g(); return [];
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([], (() => {
-    [...[]] = g(); return [];
-  })());
-  assertEquals([], log);
-
-  log = []
-  assertEquals([],
-    (([...[]]) => [])(g())
-  );
-  assertEquals([], log);
-
-
-  log = [];
-  assertEquals([42], (() => {
-    var [...[x]] = g(); return [x];
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([42], (() => {
-    let [...[x]] = g(); return [x];
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([42], (() => {
-    const [...[x]] = g(); return [x];
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([42], (() => {
-    [...[x]] = g(); return [x];
-  })());
-  assertEquals([], log);
-
-  log = []
-  assertEquals([42],
-    (([...[x]]) => [x])(g())
-  );
-  assertEquals([], log);
-
-
-  log = [];
-  assertEquals([42, undefined], (() => {
-    var [...[x, y]] = g(); return [x, y];
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([42, undefined], (() => {
-    let [...[x, y]] = g(); return [x, y];
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([42, undefined], (() => {
-    const [...[x, y]] = g(); return [x, y];
-  })());
-  assertEquals([], log);
-
-  log = [];
-  assertEquals([42, undefined], (() => {
-    [...[x, y]] = g(); return [x, y];
-  })());
-  assertEquals([], log);
-
-  log = []
-  assertEquals([42, undefined],
-    (([...[x, y]]) => [x, y])(g())
-  );
-  assertEquals([], log);
-
-
-  log = []
-  assertThrowsEquals(() => {
-    let x = { set foo(_) { throw 666; } };
-    [x.foo] = g();
-  }, 666);
-  assertEquals([[]], log);
-
-
-  log = []
-  assertThrows(() => {
-    var [[]] = g();
-  }, TypeError);
-  assertEquals([[]], log);
-
-  log = []
-  assertThrows(() => {
-    let [[]] = g();
-  }, TypeError);
-  assertEquals([[]], log);
-
-  log = []
-  assertThrows(() => {
-    const [[]] = g();
-  }, TypeError);
-  assertEquals([[]], log);
-
-  log = []
-  assertThrows(() => {
-    [[]] = g();
-  }, TypeError);
-  assertEquals([[]], log);
-
-  log = []
-  assertThrows(() => {
-    (([[]]) => 0)(g());
-  }, TypeError);
-  assertEquals([[]], log);
-
-
-  log = []
-  assertThrows(() => {
-    var [...[[]]] = g();
-  }, TypeError);
-  assertEquals([], log);
-
-  log = []
-  assertThrows(() => {
-    let [...[[]]] = g();
-  }, TypeError);
-  assertEquals([], log);
-
-  log = []
-  assertThrows(() => {
-    const [...[[]]] = g();
-  }, TypeError);
-  assertEquals([], log);
-
-  log = []
-  assertThrows(() => {
-    [...[[]]] = g();
-  }, TypeError);
-  assertEquals([], log);
-
-  log = []
-  assertThrows(() => {
-    (([...[[]]]) => 0)(g());
-  }, TypeError);
-  assertEquals([], log);
-
-
-  {
-    let backup = Array.prototype[Symbol.iterator];
-    Array.prototype[Symbol.iterator] = () => g();
-
-
-    log = [];
-    assertDoesNotThrow(() => {
-      var [x, ...[y]] = [1, 2, 3]
-    });
-    assertEquals(log, [[]]);
-
-    log = [];
-    assertDoesNotThrow(() => {
-      let [x, ...[y]] = [1, 2, 3];
-    });
-    assertEquals(log, [[]]);
-
-    log = [];
-    assertDoesNotThrow(() => {
-      const [x, ...[y]] = [1, 2, 3];
-    });
-    assertEquals(log, [[]]);
-
-    log = [];
-    assertDoesNotThrow(() => {
-      (([x, ...[y]]) => {})([1, 2, 3]);
-    });
-    assertEquals(log, [[]]);
-
-
-    log = [];
-    assertThrows(() => {
-      var [x, ...[[]]] = [1, 2, 3];
-    }, TypeError);
-    assertEquals(log, [[]]);
-
-    log = [];
-    assertThrows(() => {
-      let [x, ...[[]]] = [1, 2, 3];
-    }, TypeError);
-    assertEquals(log, [[]]);
-
-    log = [];
-    assertThrows(() => {
-      const [x, ...[[]]] = [1, 2, 3];
-    }, TypeError);
-    assertEquals(log, [[]]);
-
-    log = [];
-    assertThrows(() => {
-      (([x, ...[[]]]) => {})([1, 2, 3]);
-    }, TypeError);
-    assertEquals(log, [[]]);
-
-
-    log = [];
-    assertDoesNotThrow(() => {
-      var [x, ...[...y]] = [1, 2, 3];
-    });
-    assertEquals(log, []);
-
-    log = [];
-    assertDoesNotThrow(() => {
-      let [x, ...[...y]] = [1, 2, 3];
-    });
-    assertEquals(log, []);
-
-    log = [];
-    assertDoesNotThrow(() => {
-      const [x, ...[...y]] = [1, 2, 3];
-    });
-    assertEquals(log, []);
-
-    log = [];
-    assertDoesNotThrow(() => {
-      (([x, ...[...y]]) => {})([1, 2, 3]);
-    });
-    assertEquals(log, []);
-
-
-    Array.prototype[Symbol.iterator] = backup;
-  }
-}
-
-
-// Return method throws.
-{
-  let log = [];
-  g.prototype.return = (...args) => { log.push(args); throw 23 };
-
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (var x of g()) { break; }
-  }, 23);
-  assertEquals([[]], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (let x of g()) { break; }
-  }, 23);
-  assertEquals([[]], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (const x of g()) { break; }
-  }, 23);
-  assertEquals([[]], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (x of g()) { break; }
-  }, 23);
-  assertEquals([[]], log);
-
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (var x of g()) { throw 42; }
-  }, 42);
-  assertEquals([[]], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (let x of g()) { throw 42; }
-  }, 42);
-  assertEquals([[]], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (const x of g()) { throw 42; }
-  }, 42);
-  assertEquals([[]], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (x of g()) { throw 42; }
-  }, 42);
-  assertEquals([[]], log);
-
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (var x of g()) { return 42; }
-  }, 23);
-  assertEquals([[]], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (let x of g()) { return 42; }
-  }, 23);
-  assertEquals([[]], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (const x of g()) { return 42; }
-  }, 23);
-  assertEquals([[]], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (x of g()) { return 42; }
-  }, 23);
-  assertEquals([[]], log);
-
-
-  log = [];
-  assertEquals(42, eval('for (var x of g()) { x; }'));
-  assertEquals([], log);
-
-  log = [];
-  assertEquals(42, eval('for (let x of g()) { x; }'));
-  assertEquals([], log);
-
-  log = [];
-  assertEquals(42, eval('for (const x of g()) { x; }'));
-  assertEquals([], log);
-
-  log = [];
-  assertEquals(42, eval('for (x of g()) { x; }'));
-  assertEquals([], log);
-
-
-  log = [];
-  assertThrowsEquals(() => {
-    var [x] = g(); return x;
-  }, 23);
-  assertEquals([[]], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    let [x] = g(); return x;
-  }, 23);
-  assertEquals([[]], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    const [x] = g(); return x;
-  }, 23);
-  assertEquals([[]], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    [x] = g(); return x;
-  }, 23);
-  assertEquals([[]], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    (([x]) => x)(g())
-  }, 23);
-  assertEquals([[]], log);
-}
-
-
-// Next method throws.
-{
-  g.prototype.next = () => { throw 666; };
-  g.prototype.return = () => { assertUnreachable() };
-
-
-  assertThrowsEquals(() => {
-    for (var x of g()) {}
-  }, 666);
-
-  assertThrowsEquals(() => {
-    for (let x of g()) {}
-  }, 666);
-
-  assertThrowsEquals(() => {
-    for (const x of g()) {}
-  }, 666);
-
-  assertThrowsEquals(() => {
-    for (x of g()) {}
-  }, 666);
-
-  assertThrowsEquals(() => {
-    var [x] = g();
-  }, 666);
-
-  assertThrowsEquals(() => {
-    let [x] = g();
-  }, 666);
-
-  assertThrowsEquals(() => {
-    const [x] = g();
-  }, 666);
-
-  assertThrowsEquals(() => {
-    [x] = g();
-  }, 666);
-
-  assertThrowsEquals(() => {
-    (([x]) => x)(g());
-  }, 666);
-}
-
-
-// Value throws.
-{
-  g.prototype.next = () => ({get value() {throw 666}});
-  g.prototype.return = () => { assertUnreachable() };
-
-
-  assertThrowsEquals(() => {
-    for (var x of g()) {}
-  }, 666);
-
-  assertThrowsEquals(() => {
-    for (let x of g()) {}
-  }, 666);
-
-  assertThrowsEquals(() => {
-    for (const x of g()) {}
-  }, 666);
-
-  assertThrowsEquals(() => {
-    for (x of g()) {}
-  }, 666);
-
-  assertThrowsEquals(() => {
-    var [x] = g();
-  }, 666);
-
-  assertThrowsEquals(() => {
-    let [x] = g();
-  }, 666);
-
-  assertThrowsEquals(() => {
-    const [x] = g();
-  }, 666);
-
-  assertThrowsEquals(() => {
-    [x] = g();
-  }, 666);
-
-  assertThrowsEquals(() => {
-    (([x]) => x)(g());
-  }, 666);
-}
-
-
-// Done throws.
-{
-  g.prototype.next = () => ({get done() {throw 666}});
-  g.prototype.return = () => { assertUnreachable() };
-
-
-  assertThrowsEquals(() => {
-    for (var x of g()) {}
-  }, 666);
-
-  assertThrowsEquals(() => {
-    for (let x of g()) {}
-  }, 666);
-
-  assertThrowsEquals(() => {
-    for (const x of g()) {}
-  }, 666);
-
-  assertThrowsEquals(() => {
-    for (x of g()) {}
-  }, 666);
-
-  assertThrowsEquals(() => {
-    var [x] = g();
-  }, 666);
-
-  assertThrowsEquals(() => {
-    let [x] = g();
-  }, 666);
-
-  assertThrowsEquals(() => {
-    const [x] = g();
-  }, 666);
-
-  assertThrowsEquals(() => {
-    [x] = g();
-  }, 666);
-
-  assertThrowsEquals(() => {
-    (([x]) => x)(g());
-  }, 666);
-}
-
-
-// Nested loops.
-{
-  function* g1() { yield 1; yield 2; throw 3; }
-  function* g2() { yield -1; yield -2; throw -3; }
-
-  assertDoesNotThrow(() => {
-    for (let x of g1()) {
-      for (let y of g2()) {
-        if (y == -2) break;
-      }
-      if (x == 2) break;
-    }
-  }, -3);
-
-  assertThrowsEquals(() => {
-    for (let x of g1()) {
-      for (let y of g2()) {
-      }
-    }
-  }, -3);
-
-  assertThrowsEquals(() => {
-    for (let x of g1()) {
-      for (let y of g2()) {
-        if (y == -2) break;
-      }
-    }
-  }, 3);
-
-  assertDoesNotThrow(() => {
-    l: for (let x of g1()) {
-      for (let y of g2()) {
-        if (y == -2) break l;
-      }
-    }
-  });
-
-  assertThrowsEquals(() => {
-    for (let x of g1()) {
-      for (let y of g2()) {
-        throw 4;
-      }
-    }
-  }, 4);
-
-  assertThrowsEquals(() => {
-    for (let x of g1()) {
-      for (let y of g2()) {
-        if (y == -2) throw 4;
-      }
-    }
-  }, 4);
-
-  let log = [];
-  g1.prototype.return = () => { log.push(1); throw 5 };
-  g2.prototype.return = () => { log.push(2); throw -5 };
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (let x of g1()) {
-      for (let y of g2()) {
-        if (y == -2) break;
-      }
-      if (x == 2) break;
-    }
-  }, -5);
-  assertEquals([2, 1], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (let x of g1()) {
-      for (let y of g2()) {
-      }
-    }
-  }, -3);
-  assertEquals([1], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (let x of g1()) {
-      for (let y of g2()) {
-        if (y == -2) break;
-      }
-    }
-  }, -5);
-  assertEquals([2, 1], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    l: for (let x of g1()) {
-      for (let y of g2()) {
-        if (y == -2) break l;
-      }
-    }
-  }, -5);
-  assertEquals([2, 1], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (let x of g1()) {
-      for (let y of g2()) {
-        throw 4;
-      }
-    }
-  }, 4);
-  assertEquals([2, 1], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (let x of g1()) {
-      for (let y of g2()) {
-        if (y == -2) throw 4;
-      }
-    }
-  }, 4);
-  assertEquals([2, 1], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (let x of g1()) {
-      try {
-        for (let y of g2()) {
-        }
-      } catch (_) {}
-    }
-  }, 3);
-  assertEquals([], log);
-
-  log = [];
-  assertThrowsEquals(() => {
-    for (let x of g1()) {
-      try {
-        for (let y of g2()) {
-        }
-      } catch (_) {}
-      if (x == 2) break;
-    }
-  }, 5);
-  assertEquals([1], log);
-}
diff --git a/test/mjsunit/harmony/mirror-async-function-promise.js b/test/mjsunit/harmony/mirror-async-function-promise.js
new file mode 100644
index 0000000..966b0ce
--- /dev/null
+++ b/test/mjsunit/harmony/mirror-async-function-promise.js
@@ -0,0 +1,93 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --harmony-async-await --allow-natives-syntax
+// Test the mirror object for promises.
+
+var AsyncFunction = (async function() {}).constructor;
+
+function MirrorRefCache(json_refs) {
+  var tmp = eval('(' + json_refs + ')');
+  this.refs_ = [];
+  for (var i = 0; i < tmp.length; i++) {
+    this.refs_[tmp[i].handle] = tmp[i];
+  }
+}
+
+MirrorRefCache.prototype.lookup = function(handle) {
+  return this.refs_[handle];
+}
+
+function testPromiseMirror(promise, status, value) {
+  // Create mirror and JSON representation.
+  var mirror = debug.MakeMirror(promise);
+  var serializer = debug.MakeMirrorSerializer();
+  var json = JSON.stringify(serializer.serializeValue(mirror));
+  var refs = new MirrorRefCache(
+      JSON.stringify(serializer.serializeReferencedObjects()));
+
+  // Check the mirror hierachy.
+  assertTrue(mirror instanceof debug.Mirror);
+  assertTrue(mirror instanceof debug.ValueMirror);
+  assertTrue(mirror instanceof debug.ObjectMirror);
+  assertTrue(mirror instanceof debug.PromiseMirror);
+
+  // Check the mirror properties.
+  assertEquals(status, mirror.status());
+  assertTrue(mirror.isPromise());
+  assertEquals('promise', mirror.type());
+  assertFalse(mirror.isPrimitive());
+  assertEquals("Object", mirror.className());
+  assertEquals("#<Promise>", mirror.toText());
+  assertSame(promise, mirror.value());
+  assertTrue(mirror.promiseValue() instanceof debug.Mirror);
+  assertEquals(value, mirror.promiseValue().value());
+
+  // Parse JSON representation and check.
+  var fromJSON = eval('(' + json + ')');
+  assertEquals('promise', fromJSON.type);
+  assertEquals('Object', fromJSON.className);
+  assertEquals('function', refs.lookup(fromJSON.constructorFunction.ref).type);
+  assertEquals('Promise', refs.lookup(fromJSON.constructorFunction.ref).name);
+  assertEquals(status, fromJSON.status);
+  assertEquals(value, refs.lookup(fromJSON.promiseValue.ref).value);
+}
+
+// Test a number of different promises.
+var resolved = (async function() {})();
+var rejected = (async function() { throw undefined; })();
+var pending = (async function() { await 1; })();
+
+testPromiseMirror(resolved, "resolved", undefined);
+testPromiseMirror(rejected, "rejected", undefined);
+testPromiseMirror(pending, "pending", undefined);
+
+var resolvedv = (async function() { return "resolve"; })();
+var rejectedv = (async function() { return Promise.reject("reject"); })();
+var thrownv = (async function() { throw "throw"; })();
+
+testPromiseMirror(resolvedv, "resolved", 'resolve');
+testPromiseMirror(rejectedv, "rejected", 'reject');
+testPromiseMirror(thrownv, "rejected", 'throw');
+
+// Test internal properties of different promises.
+var m1 = debug.MakeMirror((async function() { return 1; })());
+var ip = m1.internalProperties();
+assertEquals(2, ip.length);
+assertEquals("[[PromiseStatus]]", ip[0].name());
+assertEquals("[[PromiseValue]]", ip[1].name());
+assertEquals("resolved", ip[0].value().value());
+assertEquals(1, ip[1].value().value());
+
+var m2 = debug.MakeMirror((async function() { throw 2; })());
+ip = m2.internalProperties();
+assertEquals("rejected", ip[0].value().value());
+assertEquals(2, ip[1].value().value());
+
+var m3 = debug.MakeMirror((async function() { await 1; })());
+ip = m3.internalProperties();
+assertEquals("pending", ip[0].value().value());
+assertEquals("undefined", typeof(ip[1].value().value()));
+
+%RunMicrotasks();
diff --git a/test/mjsunit/harmony/mirror-async-function.js b/test/mjsunit/harmony/mirror-async-function.js
new file mode 100644
index 0000000..b4ba831
--- /dev/null
+++ b/test/mjsunit/harmony/mirror-async-function.js
@@ -0,0 +1,76 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --harmony-async-await --allow-natives-syntax
+// Test the mirror object for functions.
+
+var AsyncFunction = (async function() {}).constructor;
+
+function MirrorRefCache(json_refs) {
+  var tmp = eval('(' + json_refs + ')');
+  this.refs_ = [];
+  for (var i = 0; i < tmp.length; i++) {
+    this.refs_[tmp[i].handle] = tmp[i];
+  }
+}
+
+MirrorRefCache.prototype.lookup = function(handle) {
+  return this.refs_[handle];
+}
+
+function testFunctionMirror(f) {
+  // Create mirror and JSON representation.
+  var mirror = debug.MakeMirror(f);
+  var serializer = debug.MakeMirrorSerializer();
+  var json = JSON.stringify(serializer.serializeValue(mirror));
+  var refs = new MirrorRefCache(
+      JSON.stringify(serializer.serializeReferencedObjects()));
+
+  // Check the mirror hierachy.
+  assertTrue(mirror instanceof debug.Mirror);
+  assertTrue(mirror instanceof debug.ValueMirror);
+  assertTrue(mirror instanceof debug.ObjectMirror);
+  assertTrue(mirror instanceof debug.FunctionMirror);
+
+  // Check the mirror properties.
+  assertTrue(mirror.isFunction());
+  assertEquals('function', mirror.type());
+  assertFalse(mirror.isPrimitive());
+  assertEquals("Function", mirror.className());
+  assertEquals(f.name, mirror.name());
+  assertTrue(mirror.resolved());
+  assertEquals(f.toString(), mirror.source());
+  assertTrue(mirror.constructorFunction() instanceof debug.ObjectMirror);
+  assertTrue(mirror.protoObject() instanceof debug.Mirror);
+  assertTrue(mirror.prototypeObject() instanceof debug.Mirror);
+
+  // Test text representation
+  assertEquals(f.toString(), mirror.toText());
+
+  // Parse JSON representation and check.
+  var fromJSON = eval('(' + json + ')');
+  assertEquals('function', fromJSON.type);
+  assertEquals('Function', fromJSON.className);
+  assertEquals('function', refs.lookup(fromJSON.constructorFunction.ref).type);
+  assertEquals('AsyncFunction',
+               refs.lookup(fromJSON.constructorFunction.ref).name);
+  assertTrue(fromJSON.resolved);
+  assertEquals(f.name, fromJSON.name);
+  assertEquals(f.toString(), fromJSON.source);
+
+  // Check the formatted text (regress 1142074).
+  assertEquals(f.toString(), fromJSON.text);
+}
+
+
+// Test a number of different functions.
+testFunctionMirror(async function(){});
+testFunctionMirror(AsyncFunction());
+testFunctionMirror(new AsyncFunction());
+testFunctionMirror(async() => {});
+testFunctionMirror(async function a(){return 1;});
+testFunctionMirror(({ async foo() {} }).foo);
+testFunctionMirror((async function(){}).bind({}), "Object");
+
+%RunMicrotasks();
diff --git a/test/mjsunit/harmony/promise-species.js b/test/mjsunit/harmony/promise-species.js
deleted file mode 100644
index 12244f2..0000000
--- a/test/mjsunit/harmony/promise-species.js
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-species --allow-natives-syntax
-
-// Test that Promises use @@species appropriately
-
-// Another constructor with no species will not be instantiated
-var test = new Promise(function(){});
-var bogoCount = 0;
-function bogusConstructor() { bogoCount++; }
-test.constructor = bogusConstructor;
-assertTrue(Promise.resolve(test) instanceof Promise);
-assertFalse(Promise.resolve(test) instanceof bogusConstructor);
-// Tests that chromium:575314 is fixed thoroughly
-Promise.resolve(test).catch(e => %AbortJS("Error " + e)).then(() => {
-  if (bogoCount != 0) %AbortJS("bogoCount was " + bogoCount + " should be 0");
-});
-
-// If there is a species, it will be instantiated
-// @@species will be read exactly once, and the constructor is called with a
-// function
-var count = 0;
-var params;
-class MyPromise extends Promise {
-  constructor(...args) {
-    super(...args);
-    params = args;
-  }
-  static get [Symbol.species]() {
-    count++
-    return this;
-  }
-}
-
-var myPromise = MyPromise.resolve().then();
-assertEquals(1, count);
-assertEquals(1, params.length);
-assertEquals('function', typeof(params[0]));
-assertTrue(myPromise instanceof MyPromise);
-assertTrue(myPromise instanceof Promise);
diff --git a/test/mjsunit/harmony/regexp-change-exec.js b/test/mjsunit/harmony/regexp-change-exec.js
index 4c9757e..ff84506 100644
--- a/test/mjsunit/harmony/regexp-change-exec.js
+++ b/test/mjsunit/harmony/regexp-change-exec.js
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-regexp-exec
-
 class MyError extends Error { }
 RegExp.prototype.exec = () => { throw new MyError() };
 assertThrows(() => "foo".match(/bar/), MyError);
diff --git a/test/mjsunit/harmony/regexp-named-captures.js b/test/mjsunit/harmony/regexp-named-captures.js
new file mode 100644
index 0000000..ced8e4b
--- /dev/null
+++ b/test/mjsunit/harmony/regexp-named-captures.js
@@ -0,0 +1,76 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-regexp-named-captures
+
+// Malformed named captures.
+assertThrows("/(?<>a)/u");  // Empty name.
+assertThrows("/(?<aa)/u");  // Unterminated name.
+assertThrows("/(?<42a>a)/u");  // Name starting with digits.
+assertThrows("/(?<:a>a)/u");  // Name starting with invalid char.
+assertThrows("/(?<a:>a)/u");  // Name containing with invalid char.
+assertThrows("/(?<a>a)(?<a>a)/u");  // Duplicate name.
+assertThrows("/(?<a>a)(?<b>b)(?<a>a)/u");  // Duplicate name.
+assertThrows("/\\k<a>/u");  // Invalid reference.
+assertThrows("/(?<a>a)\\k<ab>/u");  // Invalid reference.
+assertThrows("/(?<ab>a)\\k<a>/u");  // Invalid reference.
+assertThrows("/\\k<a>(?<ab>a)/u");  // Invalid reference.
+
+// Fallback behavior in non-unicode mode.
+assertThrows("/(?<>a)/");
+assertThrows("/(?<aa)/");
+assertThrows("/(?<42a>a)/");
+assertThrows("/(?<:a>a)/");
+assertThrows("/(?<a:>a)/");
+assertThrows("/(?<a>a)(?<a>a)/");
+assertThrows("/(?<a>a)(?<b>b)(?<a>a)/");
+assertThrows("/(?<a>a)\\k<ab>/");
+assertThrows("/(?<ab>a)\\k<a>/");
+
+assertEquals(["k<a>"], "xxxk<a>xxx".match(/\k<a>/));
+assertEquals(["k<a"], "xxxk<a>xxx".match(/\k<a/));
+
+// Basic named groups.
+assertEquals(["a", "a"], "bab".match(/(?<a>a)/u));
+assertEquals(["a", "a"], "bab".match(/(?<a42>a)/u));
+assertEquals(["a", "a"], "bab".match(/(?<_>a)/u));
+assertEquals(["a", "a"], "bab".match(/(?<$>a)/u));
+assertEquals(["bab", "a"], "bab".match(/.(?<$>a)./u));
+assertEquals(["bab", "a", "b"], "bab".match(/.(?<a>a)(.)/u));
+assertEquals(["bab", "a", "b"], "bab".match(/.(?<a>a)(?<b>.)/u));
+assertEquals(["bab", "ab"], "bab".match(/.(?<a>\w\w)/u));
+assertEquals(["bab", "bab"], "bab".match(/(?<a>\w\w\w)/u));
+assertEquals(["bab", "ba", "b"], "bab".match(/(?<a>\w\w)(?<b>\w)/u));
+
+assertEquals("bab".match(/(a)/u), "bab".match(/(?<a>a)/u));
+assertEquals("bab".match(/(a)/u), "bab".match(/(?<a42>a)/u));
+assertEquals("bab".match(/(a)/u), "bab".match(/(?<_>a)/u));
+assertEquals("bab".match(/(a)/u), "bab".match(/(?<$>a)/u));
+assertEquals("bab".match(/.(a)./u), "bab".match(/.(?<$>a)./u));
+assertEquals("bab".match(/.(a)(.)/u), "bab".match(/.(?<a>a)(.)/u));
+assertEquals("bab".match(/.(a)(.)/u), "bab".match(/.(?<a>a)(?<b>.)/u));
+assertEquals("bab".match(/.(\w\w)/u), "bab".match(/.(?<a>\w\w)/u));
+assertEquals("bab".match(/(\w\w\w)/u), "bab".match(/(?<a>\w\w\w)/u));
+assertEquals("bab".match(/(\w\w)(\w)/u), "bab".match(/(?<a>\w\w)(?<b>\w)/u));
+
+assertEquals(["bab", "b"], "bab".match(/(?<b>b).\1/u));
+assertEquals(["baba", "b", "a"], "baba".match(/(.)(?<a>a)\1\2/u));
+assertEquals(["baba", "b", "a", "b", "a"],
+    "baba".match(/(.)(?<a>a)(?<b>\1)(\2)/u));
+assertEquals(["<a", "<"], "<a".match(/(?<lt><)a/u));
+assertEquals([">a", ">"], ">a".match(/(?<gt>>)a/u));
+
+// Named references.
+assertEquals(["bab", "b"], "bab".match(/(?<b>.).\k<b>/u));
+assertNull("baa".match(/(?<b>.).\k<b>/u));
+
+// Nested groups.
+assertEquals(["bab", "bab", "ab", "b"], "bab".match(/(?<a>.(?<b>.(?<c>.)))/u));
+
+// Reference inside group.
+assertEquals(["bab", "b"], "bab".match(/(?<a>\k<a>\w)../u));
+
+// Reference before group.
+assertEquals(["bab", "b"], "bab".match(/\k<a>(?<a>b)\w\k<a>/u));
+assertEquals(["bab", "b", "a"], "bab".match(/(?<b>b)\k<a>(?<a>a)\k<b>/u));
diff --git a/test/mjsunit/harmony/regexp-no-change-exec.js b/test/mjsunit/harmony/regexp-no-change-exec.js
deleted file mode 100644
index 30b5050..0000000
--- a/test/mjsunit/harmony/regexp-no-change-exec.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --no-harmony-regexp-exec
-
-class MyError extends Error { }
-RegExp.prototype.exec = () => { throw new MyError() };
-assertEquals(null, "foo".match(/bar/));
diff --git a/test/mjsunit/harmony/regexp-property-binary.js b/test/mjsunit/harmony/regexp-property-binary.js
new file mode 100644
index 0000000..c0b4426
--- /dev/null
+++ b/test/mjsunit/harmony/regexp-property-binary.js
@@ -0,0 +1,25 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-regexp-property
+
+function t(re, s) { assertTrue(re.test(s)); }
+function f(re, s) { assertFalse(re.test(s)); }
+
+t(/\p{Bidi_Control}+/u, "\u200E");
+f(/\p{Bidi_C}+/u, "On a dark desert highway, cool wind in my hair");
+t(/\p{AHex}+/u, "DEADBEEF");
+t(/\p{Alphabetic}+/u, "abcdefg");
+t(/\P{Alphabetic}+/u, "1234");
+t(/\p{White_Space}+/u, "\u00A0");
+t(/\p{Uppercase}+/u, "V");
+f(/\p{Lower}+/u, "U");
+t(/\p{Ideo}+/u, "字");
+f(/\p{Ideo}+/u, "x");
+
+assertThrows("/\\p{Hiragana}/u");
+assertThrows("/\\p{Bidi_Class}/u");
+assertThrows("/\\p{Bidi_C=False}/u");
+assertThrows("/\\P{Bidi_Control=Y}/u");
+assertThrows("/\\p{AHex=Yes}/u");
diff --git a/test/mjsunit/harmony/regexp-property-blocks.js b/test/mjsunit/harmony/regexp-property-blocks.js
index d186e98..de3fd1e 100644
--- a/test/mjsunit/harmony/regexp-property-blocks.js
+++ b/test/mjsunit/harmony/regexp-property-blocks.js
@@ -2,33 +2,33 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-regexp-property --harmony-unicode-regexps
+// Flags: --harmony-regexp-property
 
 function t(re, s) { assertTrue(re.test(s)); }
 function f(re, s) { assertFalse(re.test(s)); }
 
-t(/\p{InASCII}+/u, ".");
-t(/\p{InASCII}+/u, "supercalifragilisticexpialidocious");
-t(/\p{InBasic_Latin}+/u, ".");
-t(/\p{InBasic_Latin}+/u, "supercalifragilisticexpialidocious");
+t(/\p{Block=ASCII}+/u, ".");
+t(/\p{Block=ASCII}+/u, "supercalifragilisticexpialidocious");
+t(/\p{Block=Basic_Latin}+/u, ".");
+t(/\p{Block=Basic_Latin}+/u, "supercalifragilisticexpialidocious");
 
-t(/\p{InCJK}+/u, "话说天下大势,分久必合,合久必分");
-t(/\p{InCJK_Unified_Ideographs}+/u, "吾庄后有一桃园,花开正盛");
-f(/\p{InCJK}+/u, "おはようございます");
-f(/\p{InCJK_Unified_Ideographs}+/u,
+t(/\p{blk=CJK}+/u, "话说天下大势,分久必合,合久必分");
+t(/\p{blk=CJK_Unified_Ideographs}+/u, "吾庄后有一桃园,花开正盛");
+f(/\p{blk=CJK}+/u, "おはようございます");
+f(/\p{blk=CJK_Unified_Ideographs}+/u,
   "Something is rotten in the state of Denmark");
 
-t(/\p{InLatin_1}+/u, "Wie froh bin ich, daß ich weg bin!");
-f(/\p{InLatin_1_Supplement}+/u, "奔腾千里荡尘埃,渡水登山紫雾开");
-f(/\p{InLatin_1_Sup}+/u, "いただきます");
+t(/\p{blk=Latin_1}+/u, "Wie froh bin ich, daß ich weg bin!");
+f(/\p{blk=Latin_1_Supplement}+/u, "奔腾千里荡尘埃,渡水登山紫雾开");
+f(/\p{blk=Latin_1_Sup}+/u, "いただきます");
 
-t(/\p{InHiragana}/u, "いただきます");
-t(/\p{Hiragana}/u, "\u{1b001}");    // This refers to the script "Hiragana".
-f(/\p{InHiragana}/u, "\u{1b001}");  // This refers to the block "Hiragana".
+t(/\p{blk=Hiragana}/u, "いただきます");
+t(/\p{sc=Hiragana}/u, "\u{1b001}");   // This refers to the script "Hiragana".
+f(/\p{blk=Hiragana}/u, "\u{1b001}");  // This refers to the block "Hiragana".
 
-t(/\p{InGreek_And_Coptic}/u,
+t(/\p{blk=Greek_And_Coptic}/u,
   "ἄνδρα μοι ἔννεπε, μοῦσα, πολύτροπον, ὃς μάλα πολλὰ");
-t(/\p{InGreek}/u, "μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος");
+t(/\p{blk=Greek}/u, "μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος");
 
 assertThrows("/\\p{In}/u");
 assertThrows("/\\pI/u");
diff --git a/test/mjsunit/harmony/regexp-property-char-class.js b/test/mjsunit/harmony/regexp-property-char-class.js
index 76774cb..c70e826 100644
--- a/test/mjsunit/harmony/regexp-property-char-class.js
+++ b/test/mjsunit/harmony/regexp-property-char-class.js
@@ -2,16 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-unicode-regexps --harmony-regexp-property
+// Flags: --harmony-regexp-property
 
 assertThrows("/[\\p]/u");
 assertThrows("/[\\p{garbage}]/u");
 assertThrows("/[\\p{}]/u");
 assertThrows("/[\\p{]/u");
 assertThrows("/[\\p}]/u");
-assertThrows("/[\\p{Math}]/u");
-assertThrows("/[\\p{Bidi_M}]/u");
-assertThrows("/[\\p{Hex}]/u");
 
 assertTrue(/^[\p{Lu}\p{Ll}]+$/u.test("ABCabc"));
 assertTrue(/^[\p{Lu}-\p{Ll}]+$/u.test("ABC-abc"));
@@ -19,6 +16,9 @@
 assertTrue(/^[\P{Lu}\p{Ll}]+$/u.test("abc"));
 assertTrue(/^[\P{Lu}]+$/u.test("abc123"));
 assertFalse(/^[\P{Lu}]+$/u.test("XYZ"));
+assertTrue(/[\p{Math}]/u.test("+"));
+assertTrue(/[\P{Bidi_M}]/u.test(" "));
+assertTrue(/[\p{Hex}]/u.test("A"));
 
 assertTrue(/^[^\P{Lu}]+$/u.test("XYZ"));
 assertFalse(/^[^\p{Lu}\p{Ll}]+$/u.test("abc"));
diff --git a/test/mjsunit/harmony/regexp-property-disabled.js b/test/mjsunit/harmony/regexp-property-disabled.js
index 7a3158c..f471ef4 100644
--- a/test/mjsunit/harmony/regexp-property-disabled.js
+++ b/test/mjsunit/harmony/regexp-property-disabled.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-unicode-regexps --no-harmony-regexp-property
+// Flags: --no-harmony-regexp-property
 
 function test(source, message) {
   try {
diff --git a/test/mjsunit/harmony/regexp-property-enumerated.js b/test/mjsunit/harmony/regexp-property-enumerated.js
new file mode 100644
index 0000000..dba8397
--- /dev/null
+++ b/test/mjsunit/harmony/regexp-property-enumerated.js
@@ -0,0 +1,28 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-regexp-property
+
+function t(re, s) { assertTrue(re.test(s)); }
+function f(re, s) { assertFalse(re.test(s)); }
+
+t(/\p{Bidi_Class=L}+/u, "Is this the real life?");
+t(/\p{bc=Left_To_Right}+/u, "Is this just fantasy?");
+t(/\p{bc=AL}+/u, "السلام عليكم‎");
+t(/\p{bc=Arabic_Letter}+/u, "متشرف بمعرفتك‎");
+
+t(/\p{Line_Break=Glue}/u, "\u00A0");
+t(/\p{lb=AL}/u, "~");
+
+assertThrows("/\\p{Block=}/u");
+assertThrows("/\\p{=}/u");
+assertThrows("/\\p{=L}/u");
+assertThrows("/\\p{=Hiragana}/u");
+assertThrows("/\\p{Block=CJK=}/u");
+
+assertThrows("/\\p{Age=V8_0}/u");
+assertThrows("/\\p{General_Category=Letter}/u");
+assertThrows("/\\p{gc=L}/u");
+assertThrows("/\\p{General_Category_Mask=Letter}/u");
+assertThrows("/\\p{gcm=L}/u");
diff --git a/test/mjsunit/harmony/regexp-property-exact-match.js b/test/mjsunit/harmony/regexp-property-exact-match.js
index 4dfcc5f..0d1f704 100644
--- a/test/mjsunit/harmony/regexp-property-exact-match.js
+++ b/test/mjsunit/harmony/regexp-property-exact-match.js
@@ -2,20 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-regexp-property --harmony-unicode-regexps
+// Flags: --harmony-regexp-property
 
 assertThrows("/\\p{In CJK}/u");
 assertThrows("/\\p{InCJKUnifiedIdeographs}/u");
-assertDoesNotThrow("/\\p{InCJK}/u");
-assertDoesNotThrow("/\\p{InCJK_Unified_Ideographs}/u");
+assertThrows("/\\p{InCJK}/u");
+assertThrows("/\\p{InCJK_Unified_Ideographs}/u");
 
-assertDoesNotThrow("/\\p{InCyrillic_Sup}/u");
-assertDoesNotThrow("/\\p{InCyrillic_Supplement}/u");
-assertDoesNotThrow("/\\p{InCyrillic_Supplementary}/u");
+assertThrows("/\\p{InCyrillic_Sup}/u");
+assertThrows("/\\p{InCyrillic_Supplement}/u");
+assertThrows("/\\p{InCyrillic_Supplementary}/u");
 assertThrows("/\\p{InCyrillicSupplementary}/u");
 assertThrows("/\\p{InCyrillic_supplementary}/u");
 
-assertDoesNotThrow("/\\pC/u");
+assertDoesNotThrow("/\\p{C}/u");
 assertDoesNotThrow("/\\p{Other}/u");
 assertDoesNotThrow("/\\p{Cc}/u");
 assertDoesNotThrow("/\\p{Control}/u");
@@ -25,9 +25,18 @@
 assertDoesNotThrow("/\\p{Combining_Mark}/u");
 assertThrows("/\\p{Combining Mark}/u");
 
-assertDoesNotThrow("/\\p{Copt}/u");
-assertDoesNotThrow("/\\p{Coptic}/u");
-assertDoesNotThrow("/\\p{Qaac}/u");
-assertDoesNotThrow("/\\p{Egyp}/u");
-assertDoesNotThrow("/\\p{Egyptian_Hieroglyphs}/u");
+assertDoesNotThrow("/\\p{Script=Copt}/u");
+assertThrows("/\\p{Coptic}/u");
+assertThrows("/\\p{Qaac}/u");
+assertThrows("/\\p{Egyp}/u");
+assertDoesNotThrow("/\\p{Script=Egyptian_Hieroglyphs}/u");
 assertThrows("/\\p{EgyptianHieroglyphs}/u");
+
+assertThrows("/\\p{BidiClass=LeftToRight}/u");
+assertThrows("/\\p{BidiC=LeftToRight}/u");
+assertThrows("/\\p{bidi_c=Left_To_Right}/u");
+
+assertDoesNotThrow("/\\p{Block=CJK}/u");
+assertThrows("/\\p{Block = CJK}/u");
+assertThrows("/\\p{Block=cjk}/u");
+assertThrows("/\\p{BLK=CJK}/u");
diff --git a/test/mjsunit/harmony/regexp-property-general-category.js b/test/mjsunit/harmony/regexp-property-general-category.js
index e2015ad..e4fb8b5 100644
--- a/test/mjsunit/harmony/regexp-property-general-category.js
+++ b/test/mjsunit/harmony/regexp-property-general-category.js
@@ -2,16 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-regexp-property --harmony-unicode-regexps
+// Flags: --harmony-regexp-property
 
 assertThrows("/\\p/u");
 assertThrows("/\\p{garbage}/u");
 assertThrows("/\\p{}/u");
 assertThrows("/\\p{/u");
 assertThrows("/\\p}/u");
-assertThrows("/\p{Math}/u");
-assertThrows("/\p{Bidi_M}/u");
-assertThrows("/\p{Hex}/u");
+assertThrows("/\\pL/u");
+assertThrows("/\\P/u");
+assertThrows("/\\P{garbage}/u");
+assertThrows("/\\P{}/u");
+assertThrows("/\\P{/u");
+assertThrows("/\\P}/u");
+assertThrows("/\\PL/u");
 
 assertTrue(/\p{Ll}/u.test("a"));
 assertFalse(/\P{Ll}/u.test("a"));
@@ -26,10 +30,10 @@
 assertTrue(/\p{Ll}/iu.test("\u{118D4}"));
 assertTrue(/\p{Ll}/iu.test("A"));
 assertTrue(/\p{Ll}/iu.test("\u{118B4}"));
-assertFalse(/\P{Ll}/iu.test("a"));
-assertFalse(/\P{Ll}/iu.test("\u{118D4}"));
-assertFalse(/\P{Ll}/iu.test("A"));
-assertFalse(/\P{Ll}/iu.test("\u{118B4}"));
+assertTrue(/\P{Ll}/iu.test("a"));
+assertTrue(/\P{Ll}/iu.test("\u{118D4}"));
+assertTrue(/\P{Ll}/iu.test("A"));
+assertTrue(/\P{Ll}/iu.test("\u{118B4}"));
 
 assertTrue(/\p{Lu}/u.test("A"));
 assertFalse(/\P{Lu}/u.test("A"));
@@ -44,22 +48,16 @@
 assertTrue(/\p{Lu}/iu.test("\u{118D4}"));
 assertTrue(/\p{Lu}/iu.test("A"));
 assertTrue(/\p{Lu}/iu.test("\u{118B4}"));
-assertFalse(/\P{Lu}/iu.test("a"));
-assertFalse(/\P{Lu}/iu.test("\u{118D4}"));
-assertFalse(/\P{Lu}/iu.test("A"));
-assertFalse(/\P{Lu}/iu.test("\u{118B4}"));
+assertTrue(/\P{Lu}/iu.test("a"));
+assertTrue(/\P{Lu}/iu.test("\u{118D4}"));
+assertTrue(/\P{Lu}/iu.test("A"));
+assertTrue(/\P{Lu}/iu.test("\u{118B4}"));
 
 assertTrue(/\p{Sm}/u.test("+"));
 assertFalse(/\P{Sm}/u.test("+"));
 assertTrue(/\p{Sm}/u.test("\u{1D6C1}"));
 assertFalse(/\P{Sm}/u.test("\u{1D6C1}"));
 
-assertTrue(/\pL/u.test("a"));
-assertFalse(/\PL/u.test("a"));
-assertFalse(/\pL/u.test("1"));
-assertTrue(/\PL/u.test("1"));
-assertTrue(/\pL/u.test("\u1FAB"));
-assertFalse(/\PL/u.test("\u1FAB"));
 assertFalse(/\p{L}/u.test("\uA6EE"));
 assertTrue(/\P{L}/u.test("\uA6EE"));
 
diff --git a/test/mjsunit/harmony/regexp-property-lu-ui.js b/test/mjsunit/harmony/regexp-property-lu-ui.js
new file mode 100644
index 0000000..115e064
--- /dev/null
+++ b/test/mjsunit/harmony/regexp-property-lu-ui.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-regexp-property
+
+const regexp = /\P{Lu}/ui;
+const regexpu = /[\0-@\[-\xBF\xD7\xDF-\xFF\u0101\u0103\u0105\u0107\u0109\u010B\u010D\u010F\u0111\u0113\u0115\u0117\u0119\u011B\u011D\u011F\u0121\u0123\u0125\u0127\u0129\u012B\u012D\u012F\u0131\u0133\u0135\u0137\u0138\u013A\u013C\u013E\u0140\u0142\u0144\u0146\u0148\u0149\u014B\u014D\u014F\u0151\u0153\u0155\u0157\u0159\u015B\u015D\u015F\u0161\u0163\u0165\u0167\u0169\u016B\u016D\u016F\u0171\u0173\u0175\u0177\u017A\u017C\u017E-\u0180\u0183\u0185\u0188\u018C\u018D\u0192\u0195\u0199-\u019B\u019E\u01A1\u01A3\u01A5\u01A8\u01AA\u01AB\u01AD\u01B0\u01B4\u01B6\u01B9-\u01BB\u01BD-\u01C3\u01C5\u01C6\u01C8\u01C9\u01CB\u01CC\u01CE\u01D0\u01D2\u01D4\u01D6\u01D8\u01DA\u01DC\u01DD\u01DF\u01E1\u01E3\u01E5\u01E7\u01E9\u01EB\u01ED\u01EF\u01F0\u01F2\u01F3\u01F5\u01F9\u01FB\u01FD\u01FF\u0201\u0203\u0205\u0207\u0209\u020B\u020D\u020F\u0211\u0213\u0215\u0217\u0219\u021B\u021D\u021F\u0221\u0223\u0225\u0227\u0229\u022B\u022D\u022F\u0231\u0233-\u0239\u023C\u023F\u0240\u0242\u0247\u0249\u024B\u024D\u024F-\u036F\u0371\u0373-\u0375\u0377-\u037E\u0380-\u0385\u0387\u038B\u038D\u0390\u03A2\u03AC-\u03CE\u03D0\u03D1\u03D5-\u03D7\u03D9\u03DB\u03DD\u03DF\u03E1\u03E3\u03E5\u03E7\u03E9\u03EB\u03ED\u03EF-\u03F3\u03F5\u03F6\u03F8\u03FB\u03FC\u0430-\u045F\u0461\u0463\u0465\u0467\u0469\u046B\u046D\u046F\u0471\u0473\u0475\u0477\u0479\u047B\u047D\u047F\u0481-\u0489\u048B\u048D\u048F\u0491\u0493\u0495\u0497\u0499\u049B\u049D\u049F\u04A1\u04A3\u04A5\u04A7\u04A9\u04AB\u04AD\u04AF\u04B1\u04B3\u04B5\u04B7\u04B9\u04BB\u04BD\u04BF\u04C2\u04C4\u04C6\u04C8\u04CA\u04CC\u04CE\u04CF\u04D1\u04D3\u04D5\u04D7\u04D9\u04DB\u04DD\u04DF\u04E1\u04E3\u04E5\u04E7\u04E9\u04EB\u04ED\u04EF\u04F1\u04F3\u04F5\u04F7\u04F9\u04FB\u04FD\u04FF\u0501\u0503\u0505\u0507\u0509\u050B\u050D\u050F\u0511\u0513\u0515\u0517\u0519\u051B\u051D\u051F\u0521\u0523\u0525\u0527\u0529\u052B\u052D\u052F\u0530\u0557-\u109F\u10C6\u10C8-\u10CC\u10CE-\u139F\u13F6-\u1DFF\u1E01\u1E03\u1E05\u1E07\u1E09\u1E0B\u1E0D\u1E0F\u1E11\u1E13\u1E15\u1E17\u1E19\u1E1B\u1E1D\u1E1F\u1E21\u1E23\u1E25\u1E27\u1E29\u1E2B\u1E2D\u1E2F\u1E31\u1E33\u1E35\u1E37\u1E39\u1E3B\u1E3D\u1E3F\u1E41\u1E43\u1E45\u1E47\u1E49\u1E4B\u1E4D\u1E4F\u1E51\u1E53\u1E55\u1E57\u1E59\u1E5B\u1E5D\u1E5F\u1E61\u1E63\u1E65\u1E67\u1E69\u1E6B\u1E6D\u1E6F\u1E71\u1E73\u1E75\u1E77\u1E79\u1E7B\u1E7D\u1E7F\u1E81\u1E83\u1E85\u1E87\u1E89\u1E8B\u1E8D\u1E8F\u1E91\u1E93\u1E95-\u1E9D\u1E9F\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7\u1EB9\u1EBB\u1EBD\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7\u1EC9\u1ECB\u1ECD\u1ECF\u1ED1\u1ED3\u1ED5\u1ED7\u1ED9\u1EDB\u1EDD\u1EDF\u1EE1\u1EE3\u1EE5\u1EE7\u1EE9\u1EEB\u1EED\u1EEF\u1EF1\u1EF3\u1EF5\u1EF7\u1EF9\u1EFB\u1EFD\u1EFF-\u1F07\u1F10-\u1F17\u1F1E-\u1F27\u1F30-\u1F37\u1F40-\u1F47\u1F4E-\u1F58\u1F5A\u1F5C\u1F5E\u1F60-\u1F67\u1F70-\u1FB7\u1FBC-\u1FC7\u1FCC-\u1FD7\u1FDC-\u1FE7\u1FED-\u1FF7\u1FFC-\u2101\u2103-\u2106\u2108-\u210A\u210E\u210F\u2113\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u212F\u2134-\u213D\u2140-\u2144\u2146-\u2182\u2184-\u2BFF\u2C2F-\u2C5F\u2C61\u2C65\u2C66\u2C68\u2C6A\u2C6C\u2C71\u2C73\u2C74\u2C76-\u2C7D\u2C81\u2C83\u2C85\u2C87\u2C89\u2C8B\u2C8D\u2C8F\u2C91\u2C93\u2C95\u2C97\u2C99\u2C9B\u2C9D\u2C9F\u2CA1\u2CA3\u2CA5\u2CA7\u2CA9\u2CAB\u2CAD\u2CAF\u2CB1\u2CB3\u2CB5\u2CB7\u2CB9\u2CBB\u2CBD\u2CBF\u2CC1\u2CC3\u2CC5\u2CC7\u2CC9\u2CCB\u2CCD\u2CCF\u2CD1\u2CD3\u2CD5\u2CD7\u2CD9\u2CDB\u2CDD\u2CDF\u2CE1\u2CE3-\u2CEA\u2CEC\u2CEE-\u2CF1\u2CF3-\uA63F\uA641\uA643\uA645\uA647\uA649\uA64B\uA64D\uA64F\uA651\uA653\uA655\uA657\uA659\uA65B\uA65D\uA65F\uA661\uA663\uA665\uA667\uA669\uA66B\uA66D-\uA67F\uA681\uA683\uA685\uA687\uA689\uA68B\uA68D\uA68F\uA691\uA693\uA695\uA697\uA699\uA69B-\uA721\uA723\uA725\uA727\uA729\uA72B\uA72D\uA72F-\uA731\uA733\uA735\uA737\uA739\uA73B\uA73D\uA73F\uA741\uA743\uA745\uA747\uA749\uA74B\uA74D\uA74F\uA751\uA753\uA755\uA757\uA759\uA75B\uA75D\uA75F\uA761\uA763\uA765\uA767\uA769\uA76B\uA76D\uA76F-\uA778\uA77A\uA77C\uA77F\uA781\uA783\uA785\uA787-\uA78A\uA78C\uA78E\uA78F\uA791\uA793-\uA795\uA797\uA799\uA79B\uA79D\uA79F\uA7A1\uA7A3\uA7A5\uA7A7\uA7A9\uA7AE\uA7AF\uA7B5\uA7B7-\uFF20\uFF3B-\u{103FF}\u{10428}-\u{10C7F}\u{10CB3}-\u{1189F}\u{118C0}-\u{1D3FF}\u{1D41A}-\u{1D433}\u{1D44E}-\u{1D467}\u{1D482}-\u{1D49B}\u{1D49D}\u{1D4A0}\u{1D4A1}\u{1D4A3}\u{1D4A4}\u{1D4A7}\u{1D4A8}\u{1D4AD}\u{1D4B6}-\u{1D4CF}\u{1D4EA}-\u{1D503}\u{1D506}\u{1D50B}\u{1D50C}\u{1D515}\u{1D51D}-\u{1D537}\u{1D53A}\u{1D53F}\u{1D545}\u{1D547}-\u{1D549}\u{1D551}-\u{1D56B}\u{1D586}-\u{1D59F}\u{1D5BA}-\u{1D5D3}\u{1D5EE}-\u{1D607}\u{1D622}-\u{1D63B}\u{1D656}-\u{1D66F}\u{1D68A}-\u{1D6A7}\u{1D6C1}-\u{1D6E1}\u{1D6FB}-\u{1D71B}\u{1D735}-\u{1D755}\u{1D76F}-\u{1D78F}\u{1D7A9}-\u{1D7C9}\u{1D7CB}-\u{10FFFF}]/ui;
+
+for (let codePoint = 0; codePoint <= 0x10FFFF; codePoint++) {
+  const string = String.fromCodePoint(codePoint);
+  assertEquals(regexp.test(string), regexpu.test(string));
+}
diff --git a/test/mjsunit/harmony/regexp-property-scripts.js b/test/mjsunit/harmony/regexp-property-scripts.js
index 19b50ee..565a59a 100644
--- a/test/mjsunit/harmony/regexp-property-scripts.js
+++ b/test/mjsunit/harmony/regexp-property-scripts.js
@@ -2,38 +2,38 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-regexp-property --harmony-unicode-regexps
+// Flags: --harmony-regexp-property
 
 function t(re, s) { assertTrue(re.test(s)); }
 function f(re, s) { assertFalse(re.test(s)); }
 
-t(/\p{Common}+/u, ".");
-f(/\p{Common}+/u, "supercalifragilisticexpialidocious");
+t(/\p{Script=Common}+/u, ".");
+f(/\p{Script=Common}+/u, "supercalifragilisticexpialidocious");
 
-t(/\p{Han}+/u, "话说天下大势,分久必合,合久必分");
-t(/\p{Hani}+/u, "吾庄后有一桃园,花开正盛");
-f(/\p{Han}+/u, "おはようございます");
-f(/\p{Hani}+/u, "Something is rotten in the state of Denmark");
+t(/\p{Script=Han}+/u, "话说天下大势,分久必合,合久必分");
+t(/\p{Script=Hani}+/u, "吾庄后有一桃园,花开正盛");
+f(/\p{Script=Han}+/u, "おはようございます");
+f(/\p{Script=Hani}+/u, "Something is rotten in the state of Denmark");
 
-t(/\p{Latin}+/u, "Wie froh bin ich, daß ich weg bin!");
-t(/\p{Latn}+/u,
+t(/\p{Script=Latin}+/u, "Wie froh bin ich, daß ich weg bin!");
+t(/\p{Script=Latn}+/u,
   "It was a bright day in April, and the clocks were striking thirteen");
-f(/\p{Latin}+/u, "奔腾千里荡尘埃,渡水登山紫雾开");
-f(/\p{Latn}+/u, "いただきます");
+f(/\p{Script=Latin}+/u, "奔腾千里荡尘埃,渡水登山紫雾开");
+f(/\p{Script=Latn}+/u, "いただきます");
 
-t(/\p{Hiragana}/u, "いただきます");
-t(/\p{Hira}/u, "ありがとうございました");
-f(/\p{Hiragana}/u,
+t(/\p{sc=Hiragana}/u, "いただきます");
+t(/\p{sc=Hira}/u, "ありがとうございました");
+f(/\p{sc=Hiragana}/u,
   "Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte");
-f(/\p{Hira}/u, "Call me Ishmael");
+f(/\p{sc=Hira}/u, "Call me Ishmael");
 
-t(/\p{Phoenician}/u, "\u{10900}\u{1091a}");
-t(/\p{Phnx}/u, "\u{1091f}\u{10916}");
-f(/\p{Phoenician}/u, "Arthur est un perroquet");
-f(/\p{Phnx}/u, "设心狠毒非良士,操卓原来一路人");
+t(/\p{sc=Phoenician}/u, "\u{10900}\u{1091a}");
+t(/\p{sc=Phnx}/u, "\u{1091f}\u{10916}");
+f(/\p{sc=Phoenician}/u, "Arthur est un perroquet");
+f(/\p{sc=Phnx}/u, "设心狠毒非良士,操卓原来一路人");
 
-t(/\p{Grek}/u, "ἄνδρα μοι ἔννεπε, μοῦσα, πολύτροπον, ὃς μάλα πολλὰ");
-t(/\p{Greek}/u, "μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος");
-f(/\p{Greek}/u, "高贤未服英雄志,屈节偏生杰士疑");
-f(/\p{Greek}/u,
+t(/\p{sc=Grek}/u, "ἄνδρα μοι ἔννεπε, μοῦσα, πολύτροπον, ὃς μάλα πολλὰ");
+t(/\p{sc=Greek}/u, "μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος");
+f(/\p{sc=Greek}/u, "高贤未服英雄志,屈节偏生杰士疑");
+f(/\p{sc=Greek}/u,
   "Mr. Jones, of the Manor Farm, had locked the hen-houses for the night");
diff --git a/test/mjsunit/harmony/regexp-property-special.js b/test/mjsunit/harmony/regexp-property-special.js
new file mode 100644
index 0000000..204b77f
--- /dev/null
+++ b/test/mjsunit/harmony/regexp-property-special.js
@@ -0,0 +1,51 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-regexp-property
+
+function t(re, s) { assertTrue(re.test(s)); }
+function f(re, s) { assertFalse(re.test(s)); }
+
+t(/\p{ASCII}+/u, "abc123");
+f(/\p{ASCII}+/u, "ⓐⓑⓒ①②③");
+f(/\p{ASCII}+/u, "🄰🄱🄲①②③");
+f(/\P{ASCII}+/u, "abcd123");
+t(/\P{ASCII}+/u, "ⓐⓑⓒ①②③");
+t(/\P{ASCII}+/u, "🄰🄱🄲①②③");
+
+f(/[^\p{ASCII}]+/u, "abc123");
+f(/[\p{ASCII}]+/u, "ⓐⓑⓒ①②③");
+f(/[\p{ASCII}]+/u, "🄰🄱🄲①②③");
+t(/[^\P{ASCII}]+/u, "abcd123");
+t(/[\P{ASCII}]+/u, "ⓐⓑⓒ①②③");
+f(/[^\P{ASCII}]+/u, "🄰🄱🄲①②③");
+
+t(/\p{Any}+/u, "🄰🄱🄲①②③");
+
+assertEquals(["\ud800"], /\p{Any}/u.exec("\ud800\ud801"));
+assertEquals(["\udc00"], /\p{Any}/u.exec("\udc00\udc01"));
+assertEquals(["\ud800\udc01"], /\p{Any}/u.exec("\ud800\udc01"));
+assertEquals(["\udc01"], /\p{Any}/u.exec("\udc01"));
+
+f(/\P{Any}+/u, "123");
+f(/[\P{Any}]+/u, "123");
+t(/[\P{Any}\d]+/u, "123");
+t(/[^\P{Any}]+/u, "123");
+
+t(/\p{Assigned}+/u, "123");
+t(/\p{Assigned}+/u, "🄰🄱🄲");
+f(/\p{Assigned}+/u, "\ufdd0");
+f(/\p{Assigned}+/u, "\u{fffff}");
+
+f(/\P{Assigned}+/u, "123");
+f(/\P{Assigned}+/u, "🄰🄱🄲");
+t(/\P{Assigned}+/u, "\ufdd0");
+t(/\P{Assigned}+/u, "\u{fffff}");
+f(/\P{Assigned}/u, "");
+
+t(/[^\P{Assigned}]+/u, "123");
+f(/[\P{Assigned}]+/u, "🄰🄱🄲");
+f(/[^\P{Assigned}]+/u, "\ufdd0");
+t(/[\P{Assigned}]+/u, "\u{fffff}");
+f(/[\P{Assigned}]/u, "");
diff --git a/test/mjsunit/harmony/regress/regress-4482.js b/test/mjsunit/harmony/regress/regress-4482.js
deleted file mode 100644
index 2472b46..0000000
--- a/test/mjsunit/harmony/regress/regress-4482.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Flags: --harmony-sloppy
-
-assertEquals("function", (function f() { f = 42; return typeof f })());
-assertEquals("function",
-             (function* g() { g = 42; yield typeof g })().next().value);
diff --git a/test/mjsunit/harmony/regress/regress-4904.js b/test/mjsunit/harmony/regress/regress-4904.js
new file mode 100644
index 0000000..a57d246
--- /dev/null
+++ b/test/mjsunit/harmony/regress/regress-4904.js
@@ -0,0 +1,24 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-do-expressions
+
+(function testCatchScopeInDoExpression() {
+  var f = (s = 17, y = do { try { throw 25; } catch(e) { s += e; }; }) => s;
+  var result = f();
+  assertEquals(result, 42);
+})();
+
+(function testCatchScopeInDoExpression() {
+  var f = (s = 17, y = do { let t; try { throw 25; } catch(e) { s += e; }; }) => s;
+  var result = f();
+  assertEquals(result, 42);
+})();
+
+(function testCatchScopeInDoExpression() {
+  let t1;
+  var f = (s = 17, y = do { let t2; try { throw 25; } catch(e) { s += e; }; }) => s;
+  var result = f();
+  assertEquals(result, 42);
+})();
diff --git a/test/mjsunit/harmony/regress/regress-618603.js b/test/mjsunit/harmony/regress/regress-618603.js
new file mode 100644
index 0000000..7b23ef4
--- /dev/null
+++ b/test/mjsunit/harmony/regress/regress-618603.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await --ignition-generators
+
+try {
+} catch(e) {; }
+function __f_7(expected, run) {
+  var __v_10 = run();
+};
+__f_7("[1,2,3]", () => (function() {
+      return (async () => {[...await arguments] })();
+      })());
diff --git a/test/mjsunit/harmony/regress/regress-crbug-621111.js b/test/mjsunit/harmony/regress/regress-crbug-621111.js
new file mode 100644
index 0000000..58a0d5c
--- /dev/null
+++ b/test/mjsunit/harmony/regress/regress-crbug-621111.js
@@ -0,0 +1,6 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(y = 1[1, [...[]]]) => 1;   // will core dump, if not fixed
+(y = 1[1, [...[]]]) => {};  // will core dump, if not fixed
diff --git a/test/mjsunit/harmony/regress/regress-crbug-621496.js b/test/mjsunit/harmony/regress/regress-crbug-621496.js
new file mode 100644
index 0000000..4db7a95
--- /dev/null
+++ b/test/mjsunit/harmony/regress/regress-crbug-621496.js
@@ -0,0 +1,7 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function testIllegalSpreadAsSingleArrowParameter() {
+  assertThrows("(...[42]) => 42)", SyntaxError)  // will core dump, if not fixed
+})();
diff --git a/test/mjsunit/harmony/regress/regress-observe-empty-double-array.js b/test/mjsunit/harmony/regress/regress-observe-empty-double-array.js
deleted file mode 100644
index 1460889..0000000
--- a/test/mjsunit/harmony/regress/regress-observe-empty-double-array.js
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * 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-object-observe
-// Flags: --allow-natives-syntax
-//
-// Test passes if it does not crash.
-
-arr = [1.1];
-Object.observe(arr, function(){});
-arr.length = 0;
-// TODO(observe): we currently disallow fast elements for observed object.
-// assertTrue(%HasFastDoubleElements(arr));
-// Should not crash
-arr.push(1.1);
diff --git a/test/mjsunit/harmony/simd.js b/test/mjsunit/harmony/simd.js
index 1868050..a3d4615 100644
--- a/test/mjsunit/harmony/simd.js
+++ b/test/mjsunit/harmony/simd.js
@@ -622,7 +622,9 @@
 
 function TestStringify(expected, input) {
   assertEquals(expected, JSON.stringify(input));
-  assertEquals(expected, JSON.stringify(input, null, 0));
+  assertEquals(expected, JSON.stringify(input, (key, value) => value));
+  assertEquals(JSON.stringify(input, null, "="),
+               JSON.stringify(input, (key, value) => value, "="));
 }
 
 TestStringify(undefined, SIMD.Float32x4(1, 2, 3, 4));
diff --git a/test/mjsunit/harmony/sloppy-legacy-duplicate-generators.js b/test/mjsunit/harmony/sloppy-legacy-duplicate-generators.js
new file mode 100644
index 0000000..1fde475
--- /dev/null
+++ b/test/mjsunit/harmony/sloppy-legacy-duplicate-generators.js
@@ -0,0 +1,60 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --no-harmony-restrictive-generators
+
+// In legacy mode, generators get sloppy-mode block-scoped function hoisting
+
+// Hoisting to the global scope
+
+{
+  function* foo() {}
+  assertEquals('function', typeof foo);
+}
+//assertEquals('function', typeof foo);
+
+// Hoisting within a function scope
+(function() {
+  { function* bar() {} }
+  assertEquals('function', typeof bar);
+})();
+
+// Lexical shadowing allowed; hoisting happens
+(function() {
+  function* x() { yield 1; }
+  { function* x() { yield 2 } }
+  assertEquals(2, x().next().value);
+})();
+
+// Duplicates allowed
+(function() {
+  function* y() { yield 1; }
+  function* y() { yield 2 }
+  assertEquals(2, y().next().value);
+})();
+
+// Functions and generators may duplicate each other
+(function() {
+  function* z() { yield 1; }
+  function z() { return 2 }
+  assertEquals(2, z());
+
+  function a() { return 1; }
+  function* a() { yield 2 }
+  assertEquals(2, a().next().value);
+})();
+
+// In strict mode, none of this happens
+
+(function() {
+  'use strict';
+
+  { function* bar() {} }
+  assertEquals('undefined', typeof bar);
+
+  // Lexical shadowing allowed; hoisting happens
+  function* x() { yield 1; }
+  { function* x() { yield 2 } }
+  assertEquals(1, x().next().value);
+})();
diff --git a/test/mjsunit/harmony/sloppy-no-duplicate-async.js b/test/mjsunit/harmony/sloppy-no-duplicate-async.js
new file mode 100644
index 0000000..97411c0
--- /dev/null
+++ b/test/mjsunit/harmony/sloppy-no-duplicate-async.js
@@ -0,0 +1,30 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-async-await
+
+// Async functions don't get sloppy-mode block-scoped function hoisting
+
+// No hoisting to the global scope
+
+{
+  async function foo() {}
+  assertEquals('function', typeof foo);
+}
+assertEquals('undefined', typeof foo);
+
+// No hoisting within a function scope
+(function() {
+  { async function bar() {} }
+  assertEquals('undefined', typeof bar);
+})();
+
+// Lexical shadowing allowed, no hoisting
+(function() {
+  var y;
+  async function x() { y = 1; }
+  { async function x() { y = 2; } }
+  x();
+  assertEquals(1, y);
+})();
diff --git a/test/mjsunit/harmony/sloppy-no-duplicate-generators.js b/test/mjsunit/harmony/sloppy-no-duplicate-generators.js
new file mode 100644
index 0000000..de2e461
--- /dev/null
+++ b/test/mjsunit/harmony/sloppy-no-duplicate-generators.js
@@ -0,0 +1,28 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-restrictive-generators
+
+// Generators don't get sloppy-mode block-scoped function hoisting
+
+// No hoisting to the global scope
+
+{
+  function* foo() {}
+  assertEquals('function', typeof foo);
+}
+assertEquals('undefined', typeof foo);
+
+// No hoisting within a function scope
+(function() {
+  { function* bar() {} }
+  assertEquals('undefined', typeof bar);
+})();
+
+// Lexical shadowing allowed, no hoisting
+(function() {
+  function* x() { yield 1; }
+  { function* x() { yield 2 } }
+  assertEquals(1, x().next().value);
+})();
diff --git a/test/mjsunit/harmony/species.js b/test/mjsunit/harmony/species.js
deleted file mode 100644
index da1df43..0000000
--- a/test/mjsunit/harmony/species.js
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-species
-
-// Test the ES2015 @@species feature
-
-'use strict';
-
-let TypedArray = Uint8Array.__proto__;
-
-// The @@species property exists on the right objects and has the right values
-
-let classesWithSpecies = [RegExp, Array, TypedArray, ArrayBuffer, Map, Set, Promise];
-let classesWithoutSpecies = [Object, Function, String, Number, Symbol, WeakMap, WeakSet];
-
-for (let constructor of classesWithSpecies) {
-  assertEquals(constructor, constructor[Symbol.species]);
-  assertThrows(function() { constructor[Symbol.species] = undefined }, TypeError);
-  let descriptor = Object.getOwnPropertyDescriptor(constructor, Symbol.species);
-  assertTrue(descriptor.configurable);
-  assertFalse(descriptor.enumerable);
-  assertEquals(undefined, descriptor.writable);
-  assertEquals(undefined, descriptor.set);
-  assertEquals('function', typeof descriptor.get);
-}
-
-// @@species is defined with distinct getters
-assertEquals(classesWithSpecies.length,
-             new Set(classesWithSpecies.map(constructor =>
-                                            Object.getOwnPropertyDescriptor(
-                                              constructor, Symbol.species).get)
-                ).size);
-
-for (let constructor of classesWithoutSpecies)
-  assertEquals(undefined, constructor[Symbol.species]);
diff --git a/test/mjsunit/harmony/string-match.js b/test/mjsunit/harmony/string-match.js
deleted file mode 100644
index 25a3ca2..0000000
--- a/test/mjsunit/harmony/string-match.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-regexp-subclass
-
-var pattern = {};
-pattern[Symbol.match] = function(string) {
-  return string.length;
-};
-// Check object coercible fails.
-assertThrows(() => String.prototype.match.call(null, pattern),
-             TypeError);
-// Override is called.
-assertEquals(5, "abcde".match(pattern));
-// Non-callable override.
-pattern[Symbol.match] = "dumdidum";
-assertThrows(() => "abcde".match(pattern), TypeError);
-
-assertEquals("[Symbol.match]", RegExp.prototype[Symbol.match].name);
diff --git a/test/mjsunit/harmony/string-replace.js b/test/mjsunit/harmony/string-replace.js
deleted file mode 100644
index 208c483..0000000
--- a/test/mjsunit/harmony/string-replace.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-regexp-subclass
-
-var pattern = {
-  [Symbol.replace]: (string, newValue) => string + newValue
-};
-// Check object coercible fails.
-assertThrows(() => String.prototype.replace.call(null, pattern, "x"),
-             TypeError);
-// Override is called.
-assertEquals("abcdex", "abcde".replace(pattern, "x"));
-// Non-callable override.
-pattern[Symbol.replace] = "dumdidum";
-assertThrows(() => "abcde".replace(pattern, "x"), TypeError);
-
-assertEquals("[Symbol.replace]", RegExp.prototype[Symbol.replace].name);
diff --git a/test/mjsunit/harmony/string-split.js b/test/mjsunit/harmony/string-split.js
deleted file mode 100644
index 1240d84..0000000
--- a/test/mjsunit/harmony/string-split.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-regexp-subclass
-
-var pattern = {};
-var limit = { value: 3 };
-pattern[Symbol.split] = function(string, limit) {
-  return string.length * limit.value;
-};
-// Check object coercible fails.
-assertThrows(() => String.prototype.split.call(null, pattern, limit),
-             TypeError);
-// Override is called.
-assertEquals(15, "abcde".split(pattern, limit));
-// Non-callable override.
-pattern[Symbol.split] = "dumdidum";
-assertThrows(() => "abcde".split(pattern, limit), TypeError);
-
-assertEquals("[Symbol.split]", RegExp.prototype[Symbol.split].name);
diff --git a/test/mjsunit/harmony/typedarray-species.js b/test/mjsunit/harmony/typedarray-species.js
deleted file mode 100644
index 35a9ea1..0000000
--- a/test/mjsunit/harmony/typedarray-species.js
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-species
-
-// Subclasses of %TypedArray% construct themselves under map, etc
-
-var typedArrayConstructors = [
-  Uint8Array,
-  Int8Array,
-  Uint16Array,
-  Int16Array,
-  Uint32Array,
-  Int32Array,
-  Uint8ClampedArray,
-  Float32Array,
-  Float64Array
-];
-
-for (let constructor of typedArrayConstructors) {
-  class MyTypedArray extends constructor { }
-  assertEquals(MyTypedArray, new MyTypedArray().map(()=>0).constructor);
-  assertEquals(MyTypedArray, new MyTypedArray().filter(()=>{}).constructor);
-  assertEquals(MyTypedArray, new MyTypedArray().slice().constructor);
-}
-
-// Subclasses can override @@species to return the another class
-
-for (let constructor of typedArrayConstructors) {
-  class MyTypedArray extends constructor { }
-  class MyOtherTypedArray extends constructor {
-    static get [Symbol.species]() { return MyTypedArray; }
-  }
-  assertEquals(MyTypedArray, new MyOtherTypedArray().map(()=>0).constructor);
-  assertEquals(MyTypedArray, new MyOtherTypedArray().filter(()=>{}).constructor);
-  assertEquals(MyTypedArray, new MyOtherTypedArray().slice().constructor);
-}
-
-// TypedArray too-short and non-TypedArray error checking
-
-for (let constructor of typedArrayConstructors) {
-  class MyShortTypedArray extends constructor {
-    constructor(length) { super(length - 1); }
-  }
-  assertThrows(() => new MyShortTypedArray(5).map(()=>0), TypeError);
-  assertThrows(() => new MyShortTypedArray(5).filter(()=>true), TypeError);
-  assertThrows(() => new MyShortTypedArray(5).slice(), TypeError);
-
-  class MyNonTypedArray extends constructor {
-    static get [Symbol.species]() { return Array; }
-  }
-  assertThrows(() => new MyNonTypedArray().map(()=>0), TypeError);
-  assertThrows(() => new MyNonTypedArray().filter(()=>{}), TypeError);
-  assertThrows(() => new MyNonTypedArray().slice(), TypeError);
-}
-
-// Defaults when constructor or @@species is missing or non-constructor
-
-for (let constructor of typedArrayConstructors) {
-  class MyDefaultTypedArray extends constructor {
-    static get [Symbol.species]() { return undefined; }
-  }
-  assertEquals(constructor, new MyDefaultTypedArray().map(()=>0).constructor);
-
-  class MyOtherDefaultTypedArray extends constructor { }
-  assertEquals(MyOtherDefaultTypedArray, new MyOtherDefaultTypedArray().map(()=>0).constructor);
-  MyOtherDefaultTypedArray.prototype.constructor = undefined;
-  assertEquals(constructor, new MyOtherDefaultTypedArray().map(()=>0).constructor);
-}
-
-// Exceptions propagated when getting constructor @@species throws
-
-class SpeciesError extends Error { }
-class ConstructorError extends Error { }
-
-for (let constructor of typedArrayConstructors) {
-  class MyThrowingArray extends constructor {
-    static get [Symbol.species]() { throw new SpeciesError; }
-  }
-  assertThrows(() => new MyThrowingArray().map(()=>{}), SpeciesError);
-  Object.defineProperty(MyThrowingArray.prototype, 'constructor', {
-      get() { throw new ConstructorError; }
-  });
-  assertThrows(() => new MyThrowingArray().map(()=>{}), ConstructorError);
-}
diff --git a/test/mjsunit/harmony/unicode-character-ranges.js b/test/mjsunit/harmony/unicode-character-ranges.js
deleted file mode 100644
index e4f5247..0000000
--- a/test/mjsunit/harmony/unicode-character-ranges.js
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-unicode-regexps --harmony-regexp-lookbehind
-
-function execl(expectation, regexp, subject) {
-  if (regexp instanceof String) regexp = new RegExp(regexp, "u");
-  assertEquals(expectation, regexp.exec(subject));
-}
-
-function execs(expectation, regexp_source, subject) {
-  execl(expectation, new RegExp(regexp_source, "u"), subject);
-}
-
-// Character ranges.
-execl(["A"], /[A-D]/u, "A");
-execs(["A"], "[A-D]", "A");
-execl(["ABCD"], /[A-D]+/u, "ZABCDEF");
-execs(["ABCD"], "[A-D]+", "ZABCDEF");
-
-execl(["\u{12345}"], /[\u1234-\u{12345}]/u, "\u{12345}");
-execs(["\u{12345}"], "[\u1234-\u{12345}]", "\u{12345}");
-execl(null, /[^\u1234-\u{12345}]/u, "\u{12345}");
-execs(null, "[^\u1234-\u{12345}]", "\u{12345}");
-
-execl(["\u{1234}"], /[\u1234-\u{12345}]/u, "\u{1234}");
-execs(["\u{1234}"], "[\u1234-\u{12345}]", "\u{1234}");
-execl(null, /[^\u1234-\u{12345}]/u, "\u{1234}");
-execs(null, "[^\u1234-\u{12345}]", "\u{1234}");
-
-execl(null, /[\u1234-\u{12345}]/u, "\u{1233}");
-execs(null, "[\u1234-\u{12345}]", "\u{1233}");
-execl(["\u{1233}"], /[^\u1234-\u{12345}]/u, "\u{1233}");
-execs(["\u{1233}"], "[^\u1234-\u{12345}]", "\u{1233}");
-
-execl(["\u{12346}"], /[^\u1234-\u{12345}]/u, "\u{12346}");
-execs(["\u{12346}"], "[^\u1234-\u{12345}]", "\u{12346}");
-execl(null, /[\u1234-\u{12345}]/u, "\u{12346}");
-execs(null, "[\u1234-\u{12345}]", "\u{12346}");
-
-execl(["\u{12342}"], /[\u{12340}-\u{12345}]/u, "\u{12342}");
-execs(["\u{12342}"], "[\u{12340}-\u{12345}]", "\u{12342}");
-execl(["\u{12342}"], /[\ud808\udf40-\ud808\udf45]/u, "\u{12342}");
-execs(["\u{12342}"], "[\ud808\udf40-\ud808\udf45]", "\u{12342}");
-execl(null, /[^\u{12340}-\u{12345}]/u, "\u{12342}");
-execs(null, "[^\u{12340}-\u{12345}]", "\u{12342}");
-execl(null, /[^\ud808\udf40-\ud808\udf45]/u, "\u{12342}");
-execs(null, "[^\ud808\udf40-\ud808\udf45]", "\u{12342}");
-
-execl(["\u{ffff}"], /[\u{ff80}-\u{12345}]/u, "\u{ffff}");
-execs(["\u{ffff}"], "[\u{ff80}-\u{12345}]", "\u{ffff}");
-execl(["\u{ffff}"], /[\u{ff80}-\ud808\udf45]/u, "\u{ffff}");
-execs(["\u{ffff}"], "[\u{ff80}-\ud808\udf45]", "\u{ffff}");
-execl(null, /[^\u{ff80}-\u{12345}]/u, "\u{ffff}");
-execs(null, "[^\u{ff80}-\u{12345}]", "\u{ffff}");
-execl(null, /[^\u{ff80}-\ud808\udf45]/u, "\u{ffff}");
-execs(null, "[^\u{ff80}-\ud808\udf45]", "\u{ffff}");
-
-// Lone surrogate
-execl(["\ud800"], /[^\u{ff80}-\u{12345}]/u, "\uff99\u{d800}A");
-execs(["\udc00"], "[^\u{ff80}-\u{12345}]", "\uff99\u{dc00}A");
-execl(["\udc01"], /[\u0100-\u{10ffff}]/u, "A\udc01");
-execl(["\udc03"], /[\udc01-\udc03]/u, "\ud801\udc02\udc03");
-execl(["\ud801"], /[\ud801-\ud803]/u, "\ud802\udc01\ud801");
-
-// Paired sorrogate.
-execl(null, /[^\u{ff80}-\u{12345}]/u, "\u{d800}\u{dc00}");
-execs(null, "[^\u{ff80}-\u{12345}]", "\u{d800}\u{dc00}");
-execl(["\ud800\udc00"], /[\u{ff80}-\u{12345}]/u, "\u{d800}\u{dc00}");
-execs(["\ud800\udc00"], "[\u{ff80}-\u{12345}]", "\u{d800}\u{dc00}");
-execl(["foo\u{10e6d}bar"], /foo\ud803\ude6dbar/u, "foo\u{10e6d}bar");
-
-// Lone surrogates
-execl(["\ud801\ud801"], /\ud801+/u, "\ud801\udc01\ud801\ud801");
-execl(["\udc01\udc01"], /\udc01+/u, "\ud801\ud801\udc01\udc01\udc01");
-
-execl(["\udc02\udc03A"], /\W\WA/u, "\ud801\udc01A\udc02\udc03A");
-execl(["\ud801\ud802"], /\ud801./u, "\ud801\udc01\ud801\ud802");
-execl(["\udc02\udc03A"], /[\ud800-\udfff][\ud800-\udfff]A/u,
-      "\ud801\udc01A\udc02\udc03A");
-
-// Character classes
-execl(null, /\w/u, "\ud801\udc01");
-execl(["\ud801"], /[^\w]/, "\ud801\udc01");
-execl(["\ud801\udc01"], /[^\w]/u, "\ud801\udc01");
-execl(["\ud801"], /\W/, "\ud801\udc01");
-execl(["\ud801\udc01"], /\W/u, "\ud801\udc01");
-
-execl(["\ud800X"], /.X/u, "\ud800XaX");
-execl(["aX"], /.(?<!\ud800)X/u, "\ud800XaX");
-execl(["aX"], /.(?<![\ud800-\ud900])X/u, "\ud800XaX");
-
-execl(null, /[]/u, "\u1234");
-execl(["0abc"], /[^]abc/u, "0abc");
-execl(["\u1234abc"], /[^]abc/u, "\u1234abc");
-execl(["\u{12345}abc"], /[^]abc/u, "\u{12345}abc");
-
-execl(null, /[\u{0}-\u{1F444}]/u, "\ud83d\udfff");
-
-// Backward matches of lone surrogates.
-execl(["B", "\ud803A"], /(?<=([\ud800-\ud900]A))B/u,
-      "\ud801\udc00AB\udc00AB\ud802\ud803AB");
-execl(["B", "\udc00A"], /(?<=([\ud800-\u{10300}]A))B/u,
-       "\ud801\udc00AB\udc00AB\ud802\ud803AB");
-execl(["B", "\udc11A"], /(?<=([\udc00-\udd00]A))B/u,
-      "\ud801\udc00AB\udc11AB\ud802\ud803AB");
-execl(["X", "\ud800C"], /(?<=(\ud800\w))X/u,
-      "\ud800\udc00AX\udc11BX\ud800\ud800CX");
-execl(["C", "\ud800\ud800"], /(?<=(\ud800.))\w/u,
-      "\ud800\udc00AX\udc11BX\ud800\ud800CX");
-execl(["X", "\udc01C"], /(?<=(\udc01\w))X/u,
-      "\ud800\udc01AX\udc11BX\udc01\udc01CX");
-execl(["C", "\udc01\udc01"], /(?<=(\udc01.))./u,
-      "\ud800\udc01AX\udc11BX\udc01\udc01CX");
-
-var L = "\ud800";
-var T = "\udc00";
-var X = "X";
-
-// Test string contains only match.
-function testw(expect, src, subject) {
-  var re = new RegExp("^" + src + "$", "u");
-  assertEquals(expect, re.test(subject));
-}
-
-// Test string starts with match.
-function tests(expect, src, subject) {
-  var re = new RegExp("^" + src, "u");
-  assertEquals(expect, re.test(subject));
-}
-
-testw(true, X, X);
-testw(true, L, L);
-testw(true, T, T);
-testw(true, L + T, L + T);
-testw(true, T + L, T + L);
-testw(false, T, L + T);
-testw(false, L, L + T);
-testw(true, ".(?<=" + L + ")", L);
-testw(true, ".(?<=" + T + ")", T);
-testw(true, ".(?<=" + L + T + ")", L + T);
-testw(true, ".(?<=" + L + T + ")", L + T);
-tests(true, ".(?<=" + T + ")", T + L);
-tests(false, ".(?<=" + L + ")", L + T);
-tests(false, ".(?<=" + T + ")", L + T);
-tests(true, "..(?<=" + T + ")", T + T + L);
-tests(true, "..(?<=" + T + ")", X + T + L);
-tests(true, "...(?<=" + L + ")", X + T + L);
-tests(false, "...(?<=" + T + ")", X + L + T)
-tests(true, "..(?<=" + L + T + ")", X + L + T)
-tests(true, "..(?<=" + L + T + "(?<=" + L + T + "))", X + L + T);
-tests(false, "..(?<=" + L + "(" + T + "))", X + L + T);
-tests(false, ".*" + L, X + L + T);
-tests(true, ".*" + L, X + L + L + T);
-tests(false, ".*" + L, X + L + T + L + T);
-tests(false, ".*" + T, X + L + T + L + T);
-tests(true, ".*" + T, X + L + T + T + L + T);
diff --git a/test/mjsunit/harmony/unicode-escapes-in-regexps.js b/test/mjsunit/harmony/unicode-escapes-in-regexps.js
deleted file mode 100644
index 7ea6f62..0000000
--- a/test/mjsunit/harmony/unicode-escapes-in-regexps.js
+++ /dev/null
@@ -1,287 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// ES6 extends the \uxxxx escape and also allows \u{xxxxx}.
-
-// Flags: --harmony-unicode-regexps
-
-function testRegexpHelper(r) {
-  assertTrue(r.test("foo"));
-  assertTrue(r.test("boo"));
-  assertFalse(r.test("moo"));
-}
-
-
-(function TestUnicodeEscapes() {
-  testRegexpHelper(/(\u0066|\u0062)oo/);
-  testRegexpHelper(/(\u0066|\u0062)oo/u);
-  testRegexpHelper(/(\u{0066}|\u{0062})oo/u);
-  testRegexpHelper(/(\u{66}|\u{000062})oo/u);
-
-  // Note that we need \\ inside a string, otherwise it's interpreted as a
-  // unicode escape inside a string.
-  testRegexpHelper(new RegExp("(\\u0066|\\u0062)oo"));
-  testRegexpHelper(new RegExp("(\\u0066|\\u0062)oo", "u"));
-  testRegexpHelper(new RegExp("(\\u{0066}|\\u{0062})oo", "u"));
-  testRegexpHelper(new RegExp("(\\u{66}|\\u{000062})oo", "u"));
-
-  // Though, unicode escapes via strings should work too.
-  testRegexpHelper(new RegExp("(\u0066|\u0062)oo"));
-  testRegexpHelper(new RegExp("(\u0066|\u0062)oo", "u"));
-  testRegexpHelper(new RegExp("(\u{0066}|\u{0062})oo", "u"));
-  testRegexpHelper(new RegExp("(\u{66}|\u{000062})oo", "u"));
-})();
-
-
-(function TestUnicodeEscapesInCharacterClasses() {
-  testRegexpHelper(/[\u0062-\u0066]oo/);
-  testRegexpHelper(/[\u0062-\u0066]oo/u);
-  testRegexpHelper(/[\u{0062}-\u{0066}]oo/u);
-  testRegexpHelper(/[\u{62}-\u{00000066}]oo/u);
-
-  // Note that we need \\ inside a string, otherwise it's interpreted as a
-  // unicode escape inside a string.
-  testRegexpHelper(new RegExp("[\\u0062-\\u0066]oo"));
-  testRegexpHelper(new RegExp("[\\u0062-\\u0066]oo", "u"));
-  testRegexpHelper(new RegExp("[\\u{0062}-\\u{0066}]oo", "u"));
-  testRegexpHelper(new RegExp("[\\u{62}-\\u{00000066}]oo", "u"));
-
-  // Though, unicode escapes via strings should work too.
-  testRegexpHelper(new RegExp("[\u0062-\u0066]oo"));
-  testRegexpHelper(new RegExp("[\u0062-\u0066]oo", "u"));
-  testRegexpHelper(new RegExp("[\u{0062}-\u{0066}]oo", "u"));
-  testRegexpHelper(new RegExp("[\u{62}-\u{00000066}]oo", "u"));
-})();
-
-
-(function TestBraceEscapesWithoutUnicodeFlag() {
-  // \u followed by illegal escape will be parsed as u. {x} will be the
-  // character count.
-  function helper1(r) {
-    assertFalse(r.test("fbar"));
-    assertFalse(r.test("fubar"));
-    assertTrue(r.test("fuubar"));
-    assertFalse(r.test("fuuubar"));
-  }
-  helper1(/f\u{2}bar/);
-  helper1(new RegExp("f\\u{2}bar"));
-
-  function helper2(r) {
-    assertFalse(r.test("fbar"));
-    assertTrue(r.test("fubar"));
-    assertTrue(r.test("fuubar"));
-    assertFalse(r.test("fuuubar"));
-  }
-
-  helper2(/f\u{1,2}bar/);
-  helper2(new RegExp("f\\u{1,2}bar"));
-
-  function helper3(r) {
-    assertTrue(r.test("u"));
-    assertTrue(r.test("{"));
-    assertTrue(r.test("2"));
-    assertTrue(r.test("}"));
-    assertFalse(r.test("q"));
-    assertFalse(r.test("("));
-    assertFalse(r.test(")"));
-  }
-  helper3(/[\u{2}]/);
-  helper3(new RegExp("[\\u{2}]"));
-})();
-
-
-(function TestInvalidEscapes() {
-  // Without the u flag, invalid unicode escapes and other invalid escapes are
-  // treated as identity escapes.
-  function helper1(r) {
-    assertTrue(r.test("firstuxz89second"));
-  }
-  helper1(/first\u\x\z\8\9second/);
-  helper1(new RegExp("first\\u\\x\\z\\8\\9second"));
-
-  function helper2(r) {
-    assertTrue(r.test("u"));
-    assertTrue(r.test("x"));
-    assertTrue(r.test("z"));
-    assertTrue(r.test("8"));
-    assertTrue(r.test("9"));
-    assertFalse(r.test("q"));
-    assertFalse(r.test("7"));
-  }
-  helper2(/[\u\x\z\8\9]/);
-  helper2(new RegExp("[\\u\\x\\z\\8\\9]"));
-
-  // However, with the u flag, these are treated as invalid escapes.
-  assertThrows("/\\u/u", SyntaxError);
-  assertThrows("/\\u12/u", SyntaxError);
-  assertThrows("/\\ufoo/u", SyntaxError);
-  assertThrows("/\\x/u", SyntaxError);
-  assertThrows("/\\xfoo/u", SyntaxError);
-  assertThrows("/\\z/u", SyntaxError);
-  assertThrows("/\\8/u", SyntaxError);
-  assertThrows("/\\9/u", SyntaxError);
-
-  assertThrows("new RegExp('\\\\u', 'u')", SyntaxError);
-  assertThrows("new RegExp('\\\\u12', 'u')", SyntaxError);
-  assertThrows("new RegExp('\\\\ufoo', 'u')", SyntaxError);
-  assertThrows("new RegExp('\\\\x', 'u')", SyntaxError);
-  assertThrows("new RegExp('\\\\xfoo', 'u')", SyntaxError);
-  assertThrows("new RegExp('\\\\z', 'u')", SyntaxError);
-  assertThrows("new RegExp('\\\\8', 'u')", SyntaxError);
-  assertThrows("new RegExp('\\\\9', 'u')", SyntaxError);
-})();
-
-
-(function TestTooBigHexEscape() {
-  // The hex number inside \u{} has a maximum value.
-  /\u{10ffff}/u
-  new RegExp("\\u{10ffff}", "u")
-  assertThrows("/\\u{110000}/u", SyntaxError);
-  assertThrows("new RegExp('\\\\u{110000}', 'u')", SyntaxError);
-
-  // Without the u flag, they're of course fine ({x} is the count).
-  /\u{110000}/
-  new RegExp("\\u{110000}")
-})();
-
-
-(function TestSyntaxEscapes() {
-  // Syntax escapes work the same with or without the u flag.
-  function helper(r) {
-    assertTrue(r.test("foo[bar"));
-    assertFalse(r.test("foo]bar"));
-  }
-  helper(/foo\[bar/);
-  helper(new RegExp("foo\\[bar"));
-  helper(/foo\[bar/u);
-  helper(new RegExp("foo\\[bar", "u"));
-})();
-
-
-(function TestUnicodeSurrogates() {
-  // U+10E6D corresponds to the surrogate pair [U+D803, U+DE6D].
-  function helper(r) {
-    assertTrue(r.test("foo\u{10e6d}bar"));
-  }
-  helper(/foo\ud803\ude6dbar/u);
-  helper(new RegExp("foo\\ud803\\ude6dbar", "u"));
-})();
-
-
-(function AllFlags() {
-  // Test that we can pass all possible regexp flags and they work properly.
-  function helper1(r) {
-    assertTrue(r.global);
-    assertTrue(r.ignoreCase);
-    assertTrue(r.multiline);
-    assertTrue(r.sticky);
-    assertTrue(r.unicode);
-  }
-
-  helper1(/foo/gimyu);
-  helper1(new RegExp("foo", "gimyu"));
-
-  function helper2(r) {
-    assertFalse(r.global);
-    assertFalse(r.ignoreCase);
-    assertFalse(r.multiline);
-    assertFalse(r.sticky);
-    assertFalse(r.unicode);
-  }
-
-  helper2(/foo/);
-  helper2(new RegExp("foo"));
-})();
-
-
-(function DuplicatedFlags() {
-  // Test that duplicating the u flag is not allowed.
-  assertThrows("/foo/ugu");
-  assertThrows("new RegExp('foo', 'ugu')");
-})();
-
-
-(function ToString() {
-  // Test that the u flag is included in the string representation of regexps.
-  function helper(r) {
-    assertEquals(r.toString(), "/foo/u");
-  }
-  helper(/foo/u);
-  helper(new RegExp("foo", "u"));
-})();
-
-// Non-BMP patterns.
-// Single character atom.
-assertTrue(new RegExp("\u{12345}", "u").test("\u{12345}"));
-assertTrue(/\u{12345}/u.test("\u{12345}"));
-assertTrue(new RegExp("\u{12345}", "u").test("\ud808\udf45"));
-assertTrue(/\u{12345}/u.test("\ud808\udf45"));
-assertFalse(new RegExp("\u{12345}", "u").test("\udf45"));
-assertFalse(/\u{12345}/u.test("\udf45"));
-
-// Multi-character atom.
-assertTrue(new RegExp("\u{12345}\u{23456}", "u").test("a\u{12345}\u{23456}b"));
-assertTrue(/\u{12345}\u{23456}/u.test("b\u{12345}\u{23456}c"));
-assertFalse(new RegExp("\u{12345}\u{23456}", "u").test("a\udf45\u{23456}b"));
-assertFalse(/\u{12345}\u{23456}/u.test("b\udf45\u{23456}c"));
-
-// Disjunction.
-assertTrue(new RegExp("\u{12345}(?:\u{23456})", "u").test(
-    "a\u{12345}\u{23456}b"));
-assertTrue(/\u{12345}(?:\u{23456})/u.test("b\u{12345}\u{23456}c"));
-assertFalse(new RegExp("\u{12345}(?:\u{23456})", "u").test(
-    "a\udf45\u{23456}b"));
-assertFalse(/\u{12345}(?:\u{23456})/u.test("b\udf45\u{23456}c"));
-
-// Alternative.
-assertTrue(new RegExp("\u{12345}|\u{23456}", "u").test("a\u{12345}b"));
-assertTrue(/\u{12345}|\u{23456}/u.test("b\u{23456}c"));
-assertFalse(new RegExp("\u{12345}|\u{23456}", "u").test("a\udf45\ud84db"));
-assertFalse(/\u{12345}|\u{23456}/u.test("b\udf45\ud808c"));
-
-// Capture.
-assertTrue(new RegExp("(\u{12345}|\u{23456}).\\1", "u").test(
-    "\u{12345}b\u{12345}"));
-assertTrue(/(\u{12345}|\u{23456}).\1/u.test("\u{12345}b\u{12345}"));
-assertFalse(new RegExp("(\u{12345}|\u{23456}).\\1", "u").test(
-    "\u{12345}b\u{23456}"));
-assertFalse(/(\u{12345}|\u{23456}).\1/u.test("\u{12345}b\u{23456}"));
-
-// Quantifier.
-assertTrue(new RegExp("\u{12345}{3}", "u").test("\u{12345}\u{12345}\u{12345}"));
-assertTrue(/\u{12345}{3}/u.test("\u{12345}\u{12345}\u{12345}"));
-assertTrue(new RegExp("\u{12345}{3}").test("\u{12345}\udf45\udf45"));
-assertFalse(/\ud808\udf45{3}/u.test("\u{12345}\udf45\udf45"));
-assertTrue(/\ud808\udf45{3}/u.test("\u{12345}\u{12345}\u{12345}"));
-assertFalse(new RegExp("\u{12345}{3}", "u").test("\u{12345}\udf45\udf45"));
-assertFalse(/\u{12345}{3}/u.test("\u{12345}\udf45\udf45"));
-
-// Literal surrogates.
-assertEquals(["\u{10000}\u{10000}"],
-             new RegExp("\ud800\udc00+", "u").exec("\u{10000}\u{10000}"));
-assertEquals(["\u{10000}\u{10000}"],
-             new RegExp("\\ud800\\udc00+", "u").exec("\u{10000}\u{10000}"));
-
-assertEquals(["\u{10003}\u{50001}"],
-             new RegExp("[\\ud800\\udc03-\\ud900\\udc01\]+", "u").exec(
-                 "\u{10003}\u{50001}"));
-assertEquals(["\u{10003}\u{50001}"],
-             new RegExp("[\ud800\udc03-\u{50001}\]+", "u").exec(
-                 "\u{10003}\u{50001}"));
-
-// Unicode escape sequences to represent a non-BMP character cannot have
-// mixed notation, and must follow the rules for RegExpUnicodeEscapeSequence.
-assertThrows(() => new RegExp("[\\ud800\udc03-\ud900\\udc01\]+", "u"));
-assertThrows(() => new RegExp("[\\ud800\udc03-\ud900\\udc01\]+", "u"));
-assertNull(new RegExp("\\ud800\udc00+", "u").exec("\u{10000}\u{10000}"));
-assertNull(new RegExp("\ud800\\udc00+", "u").exec("\u{10000}\u{10000}"));
-
-assertNull(new RegExp("[\\ud800\udc00]", "u").exec("\u{10000}"));
-assertNull(new RegExp("[\\{ud800}\udc00]", "u").exec("\u{10000}"));
-assertNull(new RegExp("[\ud800\\udc00]", "u").exec("\u{10000}"));
-assertNull(new RegExp("[\ud800\\{udc00}]", "u").exec("\u{10000}"));
-
-assertNull(/\u{d800}\u{dc00}+/u.exec("\ud800\udc00\udc00"));
-assertNull(/\ud800\u{dc00}+/u.exec("\ud800\udc00\udc00"));
-assertNull(/\u{d800}\udc00+/u.exec("\ud800\udc00\udc00"));
diff --git a/test/mjsunit/harmony/unicode-regexp-backrefs.js b/test/mjsunit/harmony/unicode-regexp-backrefs.js
deleted file mode 100644
index e02301b..0000000
--- a/test/mjsunit/harmony/unicode-regexp-backrefs.js
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-unicode-regexps --harmony-regexp-lookbehind
-
-// Back reference does not end in the middle of a surrogate pair.
-function replace(string) {
-  return string.replace(/L/g, "\ud800")
-               .replace(/l/g, "\ud801")
-               .replace(/T/g, "\udc00")
-               .replace(/\./g, "[^]");
-}
-
-function test(expectation, regexp_source, subject) {
-  if (expectation !== null) expectation = expectation.map(replace);
-  subject = replace(subject);
-  regexp_source = replace(regexp_source);
-  assertEquals(expectation, new RegExp(regexp_source, "u").exec(subject));
-}
-
-// Back reference does not end in the middle of a surrogate pair.
-test(null, "(L)\\1", "LLT");
-test(["LLTLl", "L", "l"], "(L).*\\1(.)", "LLTLl");
-test(null, "(aL).*\\1", "aLaLT");
-test(["aLaLTaLl", "aL", "l"], "(aL).*\\1(.)", "aLaLTaLl");
-
-var s = "TabcLxLTabcLxTabcLTyTabcLz";
-test([s, "TabcL", "z"], "([^x]+).*\\1(.)", s);
-
-// Back reference does not start in the middle of a surrogate pair.
-test(["TLTabTc", "T", "c"], "(T).*\\1(.)", "TLTabTc");
-
-// Lookbehinds.
-test(null, "(?<=\\1(T)x)", "LTTx");
-test(["", "b", "T"], "(?<=(.)\\2.*(T)x)", "bTaLTTx");
-test(null, "(?<=\\1.*(L)x)", "LTLx");
-test(["", "b", "L"], "(?<=(.)\\2.*(L)x)", "bLaLTLx");
-
-
-test(null, "([^x]+)x*\\1", "LxLT");
-test(null, "([^x]+)x*\\1", "TxLT");
-test(null, "([^x]+)x*\\1", "LTxL");
-test(null, "([^x]+)x*\\1", "LTxT");
-test(null, "([^x]+)x*\\1", "xLxLT");
-test(null, "([^x]+)x*\\1", "xTxLT");
-test(null, "([^x]+)x*\\1", "xLTxL");
-test(null, "([^x]+)x*\\1", "xLTxT");
-test(null, "([^x]+)x*\\1", "xxxLxxLTxx");
-test(null, "([^x]+)x*\\1", "xxxTxxLTxx");
-test(null, "([^x]+)x*\\1", "xxxLTxxLxx");
-test(null, "([^x]+)x*\\1", "xxxLTxxTxx");
-test(["LTTxxLTT", "LTT"], "([^x]+)x*\\1", "xxxLTTxxLTTxx");
diff --git a/test/mjsunit/harmony/unicode-regexp-ignore-case-noi18n.js b/test/mjsunit/harmony/unicode-regexp-ignore-case-noi18n.js
deleted file mode 100644
index a4cb9dc..0000000
--- a/test/mjsunit/harmony/unicode-regexp-ignore-case-noi18n.js
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-unicode-regexps
-
-// Non-unicode use toUpperCase mappings.
-assertFalse(/[\u00e5]/i.test("\u212b"));
-assertFalse(/[\u212b]/i.test("\u00e5\u1234"));
-assertFalse(/[\u212b]/i.test("\u00e5"));
-
-assertTrue("\u212b".toLowerCase() == "\u00e5");
-assertTrue("\u00c5".toLowerCase() == "\u00e5");
-assertTrue("\u00e5".toUpperCase() == "\u00c5");
-
-// Unicode uses case folding mappings.
-assertFalse(/\u00e5/ui.test("\u212b"));
-assertTrue(/\u00e5/ui.test("\u00c5"));
-assertTrue(/\u00e5/ui.test("\u00e5"));
-assertFalse(/\u00e5/ui.test("\u212b"));
-assertTrue(/\u00c5/ui.test("\u00e5"));
-assertFalse(/\u00c5/ui.test("\u212b"));
-assertTrue(/\u00c5/ui.test("\u00c5"));
-assertFalse(/\u212b/ui.test("\u00c5"));
-assertFalse(/\u212b/ui.test("\u00e5"));
-assertTrue(/\u212b/ui.test("\u212b"));
-
-// Non-BMP.
-assertFalse(/\u{10400}/i.test("\u{10428}"));
-assertFalse(/\u{10400}/ui.test("\u{10428}"));
-assertFalse(/\ud801\udc00/ui.test("\u{10428}"));
-assertFalse(/[\u{10428}]/ui.test("\u{10400}"));
-assertFalse(/[\ud801\udc28]/ui.test("\u{10400}"));
-assertEquals(["\uff21\u{10400}"],
-             /[\uff40-\u{10428}]+/ui.exec("\uff21\u{10400}abc"));
-assertEquals(["abc"], /[^\uff40-\u{10428}]+/ui.exec("\uff21\u{10400}abc\uff23"));
-assertEquals(["\uff53\u24bb"],
-             /[\u24d5-\uff33]+/ui.exec("\uff54\uff53\u24bb\u24ba"));
-
-// Full mappings are ignored.
-assertFalse(/\u00df/ui.test("SS"));
-assertFalse(/\u1f8d/ui.test("\u1f05\u03b9"));
-
-// Simple mappings.
-assertFalse(/\u1f8d/ui.test("\u1f85"));
-
-// Common mappings.
-assertTrue(/\u1f6b/ui.test("\u1f63"));
-
-// Back references.
-assertNull(/(.)\1\1/ui.exec("\u00e5\u212b\u00c5"));
-assertNull(/(.)\1/ui.exec("\u{118aa}\u{118ca}"));
-
-
-// Non-Latin1 maps to Latin1.
-assertNull(/^\u017F/ui.exec("s"));
-assertNull(/^\u017F/ui.exec("s\u1234"));
-assertNull(/^a[\u017F]/ui.exec("as"));
-assertNull(/^a[\u017F]/ui.exec("as\u1234"));
diff --git a/test/mjsunit/harmony/unicode-regexp-ignore-case.js b/test/mjsunit/harmony/unicode-regexp-ignore-case.js
deleted file mode 100644
index 291b866..0000000
--- a/test/mjsunit/harmony/unicode-regexp-ignore-case.js
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-unicode-regexps
-
-// Non-unicode use toUpperCase mappings.
-assertFalse(/[\u00e5]/i.test("\u212b"));
-assertFalse(/[\u212b]/i.test("\u00e5\u1234"));
-assertFalse(/[\u212b]/i.test("\u00e5"));
-
-assertTrue("\u212b".toLowerCase() == "\u00e5");
-assertTrue("\u00c5".toLowerCase() == "\u00e5");
-assertTrue("\u00e5".toUpperCase() == "\u00c5");
-
-// Unicode uses case folding mappings.
-assertTrue(/\u00e5/ui.test("\u212b"));
-assertTrue(/\u00e5/ui.test("\u00c5"));
-assertTrue(/\u00e5/ui.test("\u00e5"));
-assertTrue(/\u00e5/ui.test("\u212b"));
-assertTrue(/\u00c5/ui.test("\u00e5"));
-assertTrue(/\u00c5/ui.test("\u212b"));
-assertTrue(/\u00c5/ui.test("\u00c5"));
-assertTrue(/\u212b/ui.test("\u00c5"));
-assertTrue(/\u212b/ui.test("\u00e5"));
-assertTrue(/\u212b/ui.test("\u212b"));
-
-// Non-BMP.
-assertFalse(/\u{10400}/i.test("\u{10428}"));
-assertTrue(/\u{10400}/ui.test("\u{10428}"));
-assertTrue(/\ud801\udc00/ui.test("\u{10428}"));
-assertTrue(/[\u{10428}]/ui.test("\u{10400}"));
-assertTrue(/[\ud801\udc28]/ui.test("\u{10400}"));
-assertEquals(["\uff21\u{10400}"],
-             /[\uff40-\u{10428}]+/ui.exec("\uff21\u{10400}abc"));
-assertEquals(["abc"], /[^\uff40-\u{10428}]+/ui.exec("\uff21\u{10400}abc\uff23"));
-assertEquals(["\uff53\u24bb"],
-             /[\u24d5-\uff33]+/ui.exec("\uff54\uff53\u24bb\u24ba"));
-
-// Full mappings are ignored.
-assertFalse(/\u00df/ui.test("SS"));
-assertFalse(/\u1f8d/ui.test("\u1f05\u03b9"));
-
-// Simple mappings work.
-assertTrue(/\u1f8d/ui.test("\u1f85"));
-
-// Common mappings work.
-assertTrue(/\u1f6b/ui.test("\u1f63"));
-
-// Back references.
-assertEquals(["\u00e5\u212b\u00c5", "\u00e5"],
-             /(.)\1\1/ui.exec("\u00e5\u212b\u00c5"));
-assertEquals(["\u{118aa}\u{118ca}", "\u{118aa}"],
-             /(.)\1/ui.exec("\u{118aa}\u{118ca}"));
-
-// Misc.
-assertTrue(/\u00e5\u00e5\u00e5/ui.test("\u212b\u00e5\u00c5"));
-assertTrue(/AB\u{10400}/ui.test("ab\u{10428}"));
-
-// Non-Latin1 maps to Latin1.
-assertEquals(["s"], /^\u017F/ui.exec("s"));
-assertEquals(["s"], /^\u017F/ui.exec("s\u1234"));
-assertEquals(["as"], /^a[\u017F]/ui.exec("as"));
-assertEquals(["as"], /^a[\u017F]/ui.exec("as\u1234"));
diff --git a/test/mjsunit/harmony/unicode-regexp-last-index.js b/test/mjsunit/harmony/unicode-regexp-last-index.js
deleted file mode 100644
index 4a075d4..0000000
--- a/test/mjsunit/harmony/unicode-regexp-last-index.js
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-unicode-regexps --harmony-regexp-lookbehind
-
-var r = /./ug;
-assertEquals(["\ud800\udc00"], r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(2, r.lastIndex);
-r.lastIndex = 1;
-assertEquals(["\ud800\udc00"], r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(2, r.lastIndex);
-assertEquals(["\ud801\udc01"], r.exec("\ud800\udc00\ud801\udc01"));
-r.lastIndex = 3;
-assertEquals(["\ud801\udc01"], r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(4, r.lastIndex);
-r.lastIndex = 4;
-assertNull(r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(0, r.lastIndex);
-r.lastIndex = 5;
-assertNull(r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(0, r.lastIndex);
-
-r.lastIndex = 3;
-assertEquals(["\ud802"], r.exec("\ud800\udc00\ud801\ud802"));
-r.lastIndex = 4;
-assertNull(r.exec("\ud800\udc00\ud801\ud802"));
-
-r = /./g;
-assertEquals(["\ud800"], r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(1, r.lastIndex);
-assertEquals(["\udc00"], r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(2, r.lastIndex);
-assertEquals(["\ud801"], r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(3, r.lastIndex);
-assertEquals(["\udc01"], r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(4, r.lastIndex);
-assertNull(r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(0, r.lastIndex);
-r.lastIndex = 1;
-assertEquals(["\udc00"], r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(2, r.lastIndex);
-
-// ------------------------
-
-r = /^./ug;
-assertEquals(["\ud800\udc00"], r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(2, r.lastIndex);
-r.lastIndex = 1;
-assertEquals(["\ud800\udc00"], r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(2, r.lastIndex);
-assertNull(r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(0, r.lastIndex);
-r.lastIndex = 3;
-assertNull(r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(0, r.lastIndex);
-r.lastIndex = 4;
-assertNull(r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(0, r.lastIndex);
-r.lastIndex = 5;
-assertNull(r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(0, r.lastIndex);
-
-r = /^./g;
-assertEquals(["\ud800"], r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(1, r.lastIndex);
-assertNull(r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(0, r.lastIndex);
-r.lastIndex = 3;
-assertNull(r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(0, r.lastIndex);
-
-//------------------------
-
-r = /(?:(^.)|.)/ug;
-assertEquals(["\ud800\udc00", "\ud800\udc00"],
-             r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(2, r.lastIndex);
-r.lastIndex = 1;
-assertEquals(["\ud800\udc00", "\ud800\udc00"],
-             r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(2, r.lastIndex);
-assertEquals(["\ud801\udc01", undefined], r.exec("\ud800\udc00\ud801\udc01"));
-r.lastIndex = 3;
-assertEquals(["\ud801\udc01", undefined], r.exec("\ud800\udc00\ud801\udc01"));
-r.lastIndex = 4;
-assertNull(r.exec("\ud800\udc00\ud801\udc01"));
-r.lastIndex = 5;
-assertNull(r.exec("\ud800\udc00\ud801\udc01"));
-
-r.lastIndex = 3;
-assertEquals(["\ud802", undefined], r.exec("\ud800\udc00\ud801\ud802"));
-r.lastIndex = 4;
-assertNull(r.exec("\ud800\udc00\ud801\ud802"));
-
-r = /(?:(^.)|.)/g;
-assertEquals(["\ud800", "\ud800"],
-    r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(1, r.lastIndex);
-assertEquals(["\udc00", undefined], r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(2, r.lastIndex);
-r.lastIndex = 3;
-assertEquals(["\udc01", undefined], r.exec("\ud800\udc00\ud801\udc01"));
-assertEquals(4, r.lastIndex);
diff --git a/test/mjsunit/harmony/unicode-regexp-restricted-syntax.js b/test/mjsunit/harmony/unicode-regexp-restricted-syntax.js
deleted file mode 100644
index d129cc3..0000000
--- a/test/mjsunit/harmony/unicode-regexp-restricted-syntax.js
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-unicode-regexps
-
-// test262/data/test/language/literals/regexp/u-dec-esc
-assertThrows("/\\1/u", SyntaxError);
-// test262/language/literals/regexp/u-invalid-char-range-a
-assertThrows("/[\\w-a]/u", SyntaxError);
-// test262/language/literals/regexp/u-invalid-char-range-b
-assertThrows("/[a-\\w]/u", SyntaxError);
-// test262/language/literals/regexp/u-invalid-char-esc
-assertThrows("/\\c/u", SyntaxError);
-assertThrows("/\\c0/u", SyntaxError);
-// test262/built-ins/RegExp/unicode_restricted_quantifiable_assertion
-assertThrows("/(?=.)*/u", SyntaxError);
-// test262/built-ins/RegExp/unicode_restricted_octal_escape
-assertThrows("/[\\1]/u", SyntaxError);
-assertThrows("/\\00/u", SyntaxError);
-assertThrows("/\\09/u", SyntaxError);
-// test262/built-ins/RegExp/unicode_restricted_identity_escape_alpha
-assertThrows("/[\\c]/u", SyntaxError);
-// test262/built-ins/RegExp/unicode_restricted_identity_escape_c
-assertThrows("/[\\c0]/u", SyntaxError);
-// test262/built-ins/RegExp/unicode_restricted_incomple_quantifier
-assertThrows("/a{/u", SyntaxError);
-assertThrows("/a{1,/u", SyntaxError);
-assertThrows("/{/u", SyntaxError);
-assertThrows("/}/u", SyntaxError);
-// test262/data/test/built-ins/RegExp/unicode_restricted_brackets
-assertThrows("/]/u", SyntaxError);
-// test262/built-ins/RegExp/unicode_identity_escape
-/\//u;
-
-// escaped \0 is allowed inside a character class.
-assertEquals(["\0"], /[\0]/u.exec("\0"));
-// unless it is followed by another digit.
-assertThrows("/[\\00]/u", SyntaxError);
-assertThrows("/[\\01]/u", SyntaxError);
-assertThrows("/[\\09]/u", SyntaxError);
-assertEquals(["\u{0}1\u{0}a\u{0}"], /[1\0a]+/u.exec("b\u{0}1\u{0}a\u{0}2"));
-// escaped \- is allowed inside a character class.
-assertEquals(["-"], /[a\-z]/u.exec("12-34"));
diff --git a/test/mjsunit/harmony/unicode-regexp-unanchored-advance.js b/test/mjsunit/harmony/unicode-regexp-unanchored-advance.js
deleted file mode 100644
index 97960e1..0000000
--- a/test/mjsunit/harmony/unicode-regexp-unanchored-advance.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-unicode-regexps
-
-var s = "a".repeat(1E7) + "\u1234";
-assertEquals(["\u1234", "\u1234"], /(\u1234)/u.exec(s));
diff --git a/test/mjsunit/harmony/unicode-regexp-zero-length.js b/test/mjsunit/harmony/unicode-regexp-zero-length.js
deleted file mode 100644
index bbc17dc..0000000
--- a/test/mjsunit/harmony/unicode-regexp-zero-length.js
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-unicode-regexps
-
-var L = "\ud800";
-var T = "\udc00";
-var x = "x";
-
-var r = /()/g;  // Global, but not unicode.
-// Zero-length matches do not advance lastIndex.
-assertEquals(["", ""], r.exec(L + T + L + T));
-assertEquals(0, r.lastIndex);
-r.lastIndex = 1;
-assertEquals(["", ""], r.exec(L + T + L + T));
-assertEquals(1, r.lastIndex);
-
-var u = /()/ug;  // Global and unicode.
-// Zero-length matches do not advance lastIndex.
-assertEquals(["", ""], u.exec(L + T + L + T));
-assertEquals(0, u.lastIndex);
-u.lastIndex = 1;
-assertEquals(["", ""], u.exec(L + T + L + T));
-assertEquals(0, u.lastIndex);
-
-// However, with repeating matches, lastIndex does not matter.
-// We do advance from match to match.
-r.lastIndex = 2;
-assertEquals(x + L + x + T + x + L + x + T + x,
-             (L + T + L + T).replace(r, "x"));
-
-// With unicode flag, we advance code point by code point.
-u.lastIndex = 3;
-assertEquals(x + L + T + x + L + T + x,
-             (L + T + L + T).replace(u, "x"));
-
-// Test that exhausting the global match cache is fine.
-assertEquals((x + L + T).repeat(1000) + x,
-             (L + T).repeat(1000).replace(u, "x"));
-
-// Same thing for RegExp.prototype.match.
-r.lastIndex = 1;
-assertEquals(["","","","",""], (L + T + L + T).match(r));
-r.lastIndex = 2;
-assertEquals(["","","","",""], (L + T + L + T).match(r));
-
-u.lastIndex = 1;
-assertEquals(["","",""], (L + T + L + T).match(u));
-u.lastIndex = 2;
-assertEquals(["","",""], (L + T + L + T).match(u));
-
-var expected = [];
-for (var i = 0; i <= 1000; i++) expected.push("");
-assertEquals(expected, (L + T).repeat(1000).match(u));
-
-// Also test RegExp.prototype.@@split.
-assertEquals(["\u{12345}"], "\u{12345}".split(/(?:)/u));
diff --git a/test/mjsunit/holy-double-no-arg-array.js b/test/mjsunit/holy-double-no-arg-array.js
new file mode 100644
index 0000000..73e2ddc
--- /dev/null
+++ b/test/mjsunit/holy-double-no-arg-array.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function() {
+  function f() {
+    return new Array();
+  }
+  var a = f();
+  a[0] = 0.5;
+  var b = f();
+  b[2] = 0.5;
+  assertEquals(undefined, b[0]);
+})();
diff --git a/test/mjsunit/ignition/elided-instruction-no-ignition.js b/test/mjsunit/ignition/elided-instruction-no-ignition.js
deleted file mode 100644
index d31150b..0000000
--- a/test/mjsunit/ignition/elided-instruction-no-ignition.js
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --expose-debug-as debug
-
-Debug = debug.Debug
-
-var exception = null;
-var break_count = 0;
-
-function listener(event, exec_state, event_data, data) {
-  if (event != Debug.DebugEvent.Break) return;
-  try {
-    print(event_data.sourceLineText());
-    var column = event_data.sourceColumn();
-    assertTrue(event_data.sourceLineText().indexOf(
-        `Break ${break_count++}. ${column}.`) > 0);
-    exec_state.prepareStep(Debug.StepAction.StepIn);
-  } catch (e) {
-    print(e + e.stack);
-    exception = e;
-  }
-};
-
-function f() {
-  var a = 1;                     // Break 2. 10.
-  return a;                      // Break 3. 2.
-}                                // Break 4. 0.
-
-Debug.setListener(listener);
-debugger;                        // Break 0. 0.
-f();                             // Break 1. 0.
-Debug.setListener(null);         // Break 5. 0.
-
-assertNull(exception);
-assertEquals(6, break_count);
diff --git a/test/mjsunit/ignition/elided-instruction.js b/test/mjsunit/ignition/elided-instruction.js
index 807974b..d31150b 100644
--- a/test/mjsunit/ignition/elided-instruction.js
+++ b/test/mjsunit/ignition/elided-instruction.js
@@ -25,17 +25,13 @@
 
 function f() {
   var a = 1;                     // Break 2. 10.
-  // This return statement emits no bytecode instruction for the evaluation of
-  // the to-be-returned expression. Therefore we cannot set a break location
-  // before the statement and a second break location immediately before
-  // returning to the caller.
-  return a;
-}                                // Break 3. 0.
+  return a;                      // Break 3. 2.
+}                                // Break 4. 0.
 
 Debug.setListener(listener);
 debugger;                        // Break 0. 0.
 f();                             // Break 1. 0.
-Debug.setListener(null);         // Break 4. 0.
+Debug.setListener(null);         // Break 5. 0.
 
 assertNull(exception);
-assertEquals(5, break_count);
+assertEquals(6, break_count);
diff --git a/test/mjsunit/ignition/ignition-statistics-extension.js b/test/mjsunit/ignition/ignition-statistics-extension.js
new file mode 100644
index 0000000..43d05c9
--- /dev/null
+++ b/test/mjsunit/ignition/ignition-statistics-extension.js
@@ -0,0 +1,62 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --ignition --trace-ignition-dispatches
+
+assertEquals(typeof getIgnitionDispatchCounters, "function");
+
+var old_dispatch_counters = getIgnitionDispatchCounters();
+
+// Check that old_dispatch_counters is a non-empty object of objects, such that
+// the value of each property in the inner objects is a number.
+
+assertEquals(typeof old_dispatch_counters, "object");
+assertTrue(Object.getOwnPropertyNames(old_dispatch_counters).length > 0);
+for (var source_bytecode in old_dispatch_counters) {
+  var counters_row = old_dispatch_counters[source_bytecode];
+  assertEquals(typeof counters_row, "object");
+  for (var counter in counters_row) {
+    assertEquals(typeof counters_row[counter], "number");
+  }
+}
+
+// Do something
+function f(x) { return x*x; }
+f(42);
+
+var new_dispatch_counters = getIgnitionDispatchCounters();
+
+var old_source_bytecodes = Object.getOwnPropertyNames(old_dispatch_counters);
+var new_source_bytecodes = Object.getOwnPropertyNames(new_dispatch_counters);
+var common_source_bytecodes = new_source_bytecodes.filter(function (name) {
+  return old_source_bytecodes.indexOf(name) > -1;
+});
+
+// Check that the keys on the outer objects are the same
+assertEquals(common_source_bytecodes, old_source_bytecodes);
+assertEquals(common_source_bytecodes, new_source_bytecodes);
+
+common_source_bytecodes.forEach(function (source_bytecode) {
+  var new_counters_row = new_dispatch_counters[source_bytecode];
+  var old_counters_row = old_dispatch_counters[source_bytecode];
+
+  var old_destination_bytecodes = Object.getOwnPropertyNames(old_counters_row);
+  var new_destination_bytecodes = Object.getOwnPropertyNames(new_counters_row);
+
+  // Check that all the keys in old_ are in new_ too
+  old_destination_bytecodes.forEach(function (name) {
+    assertTrue(new_destination_bytecodes.indexOf(name) > -1);
+  });
+
+  // Check that for each source-destination pair, the counter has either
+  // appeared (was undefined before calling f()), is unchanged, or incremented.
+  new_destination_bytecodes.forEach(function (destination_bytecode) {
+    var new_counter = new_counters_row[destination_bytecode];
+    var old_counter = old_counters_row[destination_bytecode];
+    assertTrue(typeof new_counter === "number");
+    if (typeof old_counter === "number") {
+      assertTrue(new_counter >= old_counter);
+    }
+  });
+});
diff --git a/test/mjsunit/ignition/regress-599001-verifyheap.js b/test/mjsunit/ignition/regress-599001-verifyheap.js
index 5aa2efd..ce5b46d 100644
--- a/test/mjsunit/ignition/regress-599001-verifyheap.js
+++ b/test/mjsunit/ignition/regress-599001-verifyheap.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --verify-heap --expose-gc
+// Flags: --ignition --verify-heap --expose-gc
 
 // Tests that verify heap works for BytecodeArrays in the large object space.
 
diff --git a/test/mjsunit/ignition/regress-612386-smi-to-double-transition.js b/test/mjsunit/ignition/regress-612386-smi-to-double-transition.js
new file mode 100644
index 0000000..275f7d6
--- /dev/null
+++ b/test/mjsunit/ignition/regress-612386-smi-to-double-transition.js
@@ -0,0 +1,29 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --no-inline-new
+
+function keyed_store(obj, key, value) {
+  obj[key] = value;
+}
+
+function foo() {
+  obj = {};
+  obj.smi = 1;
+  obj.dbl = 1.5;
+  obj.obj = {a:1};
+
+  // Transition keyed store IC to polymorphic.
+  keyed_store(obj, "smi", 100);
+  keyed_store(obj, "dbl", 100);
+  keyed_store(obj, "obj", 100);
+
+  // Now call with a FAST_SMI_ELEMENTS object.
+  var smi_array = [5, 1, 1];
+  keyed_store(smi_array, 1, 6);
+  // Transition from FAST_SMI_ELEMENTS to FAST_DOUBLE_ELEMENTS.
+  keyed_store(smi_array, 2, 1.2);
+}
+
+foo();
diff --git a/test/mjsunit/ignition/regress-616064.js b/test/mjsunit/ignition/regress-616064.js
new file mode 100644
index 0000000..06de873
--- /dev/null
+++ b/test/mjsunit/ignition/regress-616064.js
@@ -0,0 +1,26 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --ignition
+
+function foo() {
+  if (this.Worker) {
+    function __f_0() { this.s = a; }
+    function __f_1() {
+      this.l = __f_0;
+    }
+
+    with ( 'source' , Object ) throw function __f_0(__f_0) {
+      return Worker.__f_0(-2147483648, __f_0);
+    };
+
+    var __v_9 = new Worker('');
+    __f_1 = {s: Math.s, __f_1: true};
+  }
+}
+
+try {
+  foo();
+} catch(e) {
+}
diff --git a/test/mjsunit/json-replacer-order.js b/test/mjsunit/json-replacer-order.js
index 8cb6441..19b69bf 100644
--- a/test/mjsunit/json-replacer-order.js
+++ b/test/mjsunit/json-replacer-order.js
@@ -20,7 +20,6 @@
 });
 
 JSON.stringify('', replacer, space);
-
 assertEquals(2, log.length);
 assertEquals('get 0', log[0]);
 assertEquals('toString', log[1]);
diff --git a/test/mjsunit/json-stringify-holder.js b/test/mjsunit/json-stringify-holder.js
new file mode 100644
index 0000000..2f06d77
--- /dev/null
+++ b/test/mjsunit/json-stringify-holder.js
@@ -0,0 +1,104 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function testBasic() {
+  var stack = [];
+  var object = {a: false};
+  var replaced = {a: false, replaced: true};
+
+  function replacer(key, value) {
+    stack.push({ holder: this, key, value });
+    if (stack.length === 1) return replaced;
+    if (key === "a") return true;
+    return value;
+  }
+
+  assertEquals(`{"a":true,"replaced":true}`, JSON.stringify(object, replacer));
+
+  assertEquals([
+    {
+      holder: { "": { a: false } },
+      key: "",
+      value: { a: false }
+    },
+    {
+      holder: { a: false, replaced: true },
+      key: "a",
+      value: false
+    },
+    {
+      holder: { a: false, replaced: true },
+      key: "replaced",
+      value: true
+    }
+  ], stack);
+
+  assertSame(stack[0].holder[""], object);
+  assertSame(stack[0].value, object);
+  assertSame(stack[1].holder, replaced);
+  assertSame(stack[2].holder, replaced);
+})();
+
+(function testToJSON() {
+  var stack = [];
+  var object = {a: false, toJSON };
+  var nested = { toJSON: nestedToJSON };
+  var replaced = {a: false, replaced: true, nested };
+  var toJSONd = {a: false, toJSONd: true }
+  var nestedToJSONd = { nestedToJSONd: true };
+
+  function toJSON(key, value) {
+    return toJSONd;
+  }
+
+  function nestedToJSON(key, value) {
+    return nestedToJSONd;
+  }
+
+  function replacer(key, value) {
+    stack.push({ holder: this, key, value });
+    if (stack.length === 1) return replaced;
+    if (key === "a") return true;
+    return value;
+  }
+
+  assertEquals(`{"a":true,"replaced":true,"nested":{"nestedToJSONd":true}}`,
+               JSON.stringify(object, replacer));
+
+  assertEquals([
+    {
+      holder: { "": { a: false, toJSON: toJSON } },
+      key: "",
+      value: { a: false, toJSONd: true }
+    },
+    {
+      holder: { a: false, replaced: true, nested: { toJSON: nestedToJSON } },
+      key: "a",
+      value: false
+    },
+    {
+      holder: { a: false, replaced: true, nested: { toJSON: nestedToJSON } },
+      key: "replaced",
+      value: true
+    },
+    {
+      holder: { a: false, replaced: true, nested: { toJSON: nestedToJSON } },
+      key: "nested",
+      value: { nestedToJSONd: true }
+    },
+    {
+      holder: { nestedToJSONd: true },
+      key: "nestedToJSONd",
+      value: true
+    }
+  ], stack);
+
+  assertSame(stack[0].holder[""], object);
+  assertSame(stack[0].value, toJSONd);
+  assertSame(stack[1].holder, replaced);
+  assertSame(stack[2].holder, replaced);
+  assertSame(stack[3].holder, replaced);
+  assertSame(stack[3].value, nestedToJSONd);
+  assertSame(stack[4].holder, nestedToJSONd);
+})();
diff --git a/test/mjsunit/json.js b/test/mjsunit/json.js
index 84f2056..3652feb 100644
--- a/test/mjsunit/json.js
+++ b/test/mjsunit/json.js
@@ -234,7 +234,9 @@
 
 function TestStringify(expected, input) {
   assertEquals(expected, JSON.stringify(input));
-  assertEquals(expected, JSON.stringify(input, null, 0));
+  assertEquals(expected, JSON.stringify(input, (key, value) => value));
+  assertEquals(JSON.stringify(input, null, "="),
+               JSON.stringify(input, (key, value) => value, "="));
 }
 
 TestStringify("true", true);
@@ -451,8 +453,8 @@
 // RegExps are not callable, so they are stringified as objects.
 TestStringify('{}', /regexp/);
 TestStringify('42', counter);
-assertEquals(2, getCount);
-assertEquals(2, callCount);
+assertEquals(4, getCount);
+assertEquals(4, callCount);
 
 var oddball2 = Object(42);
 var oddball3 = Object("foo");
@@ -518,3 +520,6 @@
   return p === "" ? v : 42;
 }
 assertEquals({a: 0, b: 1}, JSON.parse('{"a":0,"b":1}', reviver));
+
+reviver = (k, v) => (v === Infinity) ? "inf" : v;
+assertEquals('{"":"inf"}', JSON.stringify({"":Infinity}, reviver));
diff --git a/test/mjsunit/json2.js b/test/mjsunit/json2.js
index f68c76c..75e25f8 100644
--- a/test/mjsunit/json2.js
+++ b/test/mjsunit/json2.js
@@ -35,7 +35,9 @@
 // Test JSON.stringify of array in dictionary mode.
 function TestStringify(expected, input) {
   assertEquals(expected, JSON.stringify(input));
-  assertEquals(expected, JSON.stringify(input, null, 0));
+  assertEquals(expected, JSON.stringify(input, (key, value) => value));
+  assertEquals(JSON.stringify(input, null, "="),
+               JSON.stringify(input, (key, value) => value, "="));
 }
 
 var array_1 = [];
@@ -76,7 +78,7 @@
                          return 123;
                        } };
 TestStringify('{"getter":123}', getter_obj);
-assertEquals(2, counter);
+assertEquals(4, counter);
 
 // Test toJSON function.
 var tojson_obj = { toJSON: function() {
@@ -85,7 +87,7 @@
                            },
                    a: 1};
 TestStringify('[1,2]', tojson_obj);
-assertEquals(4, counter);
+assertEquals(8, counter);
 
 // Test that we don't recursively look for the toJSON function.
 var tojson_proto_obj = { a: 'fail' };
diff --git a/test/mjsunit/lithium/SeqStringSetChar.js b/test/mjsunit/lithium/SeqStringSetChar.js
deleted file mode 100644
index c5bd145..0000000
--- a/test/mjsunit/lithium/SeqStringSetChar.js
+++ /dev/null
@@ -1,46 +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.
-
-// Flags: --allow-natives-syntax
-
-function MyStringFromCharCode(code, i) {
-  var one_byte = %NewString(3, true);
-  %_OneByteSeqStringSetChar(0, code, one_byte);
-  %_OneByteSeqStringSetChar(1, code, one_byte);
-  %_OneByteSeqStringSetChar(i, code, one_byte);
-  var two_byte = %NewString(3, false);
-  %_TwoByteSeqStringSetChar(0, code, two_byte);
-  %_TwoByteSeqStringSetChar(1, code, two_byte);
-  %_TwoByteSeqStringSetChar(i, code, two_byte);
-  return one_byte + two_byte;
-}
-
-MyStringFromCharCode(65, 2);
-var r1 = MyStringFromCharCode(65, 2);
-%OptimizeFunctionOnNextCall(MyStringFromCharCode);
-var r2 = MyStringFromCharCode(65, 2);
-assertEquals(r1, r2);
diff --git a/test/mjsunit/messages.js b/test/mjsunit/messages.js
index 8796d05..30abc19 100644
--- a/test/mjsunit/messages.js
+++ b/test/mjsunit/messages.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 // Flags: --stack-size=100 --harmony
-// Flags: --harmony-simd --harmony-instanceof
+// Flags: --harmony-simd
 
 function test(f, expected, type) {
   try {
@@ -147,7 +147,12 @@
 }, "Method Set.prototype.add called on incompatible receiver [object Array]",
 TypeError);
 
-// kInstanceofFunctionExpected
+// kNonCallableInInstanceOfCheck
+test(function() {
+  1 instanceof {};
+}, "Right-hand side of 'instanceof' is not callable", TypeError);
+
+// kNonObjectInInstanceOfCheck
 test(function() {
   1 instanceof 1;
 }, "Right-hand side of 'instanceof' is not an object", TypeError);
diff --git a/test/mjsunit/migrations.js b/test/mjsunit/migrations.js
index a18d884..2bd70fb 100644
--- a/test/mjsunit/migrations.js
+++ b/test/mjsunit/migrations.js
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-ayle license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-object-observe
 // Flags: --allow-natives-syntax --track-fields --expose-gc
 
 var global = Function('return this')();
@@ -275,10 +274,6 @@
     },
   },
   {
-    name: "observe",
-    migr: function(o, i) { Object.observe(o, function(){}); },
-  },
-  {
     name: "seal",
     migr: function(o, i) { Object.seal(o); },
   },
diff --git a/test/mjsunit/mirror-object.js b/test/mjsunit/mirror-object.js
index 834d7a5..cae652a 100644
--- a/test/mjsunit/mirror-object.js
+++ b/test/mjsunit/mirror-object.js
@@ -265,3 +265,27 @@
 assertTrue("[[BoundArgs]]" in property_map);
 assertEquals("object", property_map["[[BoundArgs]]"].value().type());
 assertEquals(1, property_map["[[BoundArgs]]"].value().value().length);
+
+// Test JSProxy internal properties.
+var target = {};
+var handler = {
+  get: function (target, name, receiver) {
+    return target[name];
+  },
+  set: function(target, name, value, receiver) {
+    target[name] = value;
+    return value;
+  }
+}
+ip = debug.ObjectMirror.GetInternalProperties(new Proxy(target, handler));
+assertEquals(3, ip.length);
+var property_map = {};
+for (var i = 0; i < ip.length; i++) {
+  property_map[ip[i].name()] = ip[i];
+}
+assertTrue("[[Target]]" in property_map);
+assertEquals(target, property_map["[[Target]]"].value().value());
+assertTrue("[[Handler]]" in property_map);
+assertEquals(handler, property_map["[[Handler]]"].value().value());
+assertTrue("[[IsRevoked]]" in property_map);
+assertEquals(false, property_map["[[IsRevoked]]"].value().value());
diff --git a/test/mjsunit/mirror-regexp.js b/test/mjsunit/mirror-regexp.js
index 7aae1c6..0711ff9 100644
--- a/test/mjsunit/mirror-regexp.js
+++ b/test/mjsunit/mirror-regexp.js
@@ -25,7 +25,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Flags: --expose-debug-as debug --harmony-unicode-regexps
+// Flags: --expose-debug-as debug
 // Test the mirror object for regular expression values
 
 var dont_enum = debug.PropertyAttribute.DontEnum;
diff --git a/test/mjsunit/mirror-script.js b/test/mjsunit/mirror-script.js
index ed0dd12..7e3891a 100644
--- a/test/mjsunit/mirror-script.js
+++ b/test/mjsunit/mirror-script.js
@@ -83,16 +83,7 @@
 
 
 // Test the script mirror for different functions.
-testScriptMirror(function(){}, 'mirror-script.js', 99, 2, 0);
+testScriptMirror(function(){}, 'mirror-script.js', 90, 2, 0);
 testScriptMirror(Math.abs, 'native math.js', -1, 0, 0);
 testScriptMirror(eval('(function(){})'), null, 1, 2, 1, '(function(){})', 87);
 testScriptMirror(eval('(function(){\n  })'), null, 2, 2, 1, '(function(){\n  })', 88);
-
-// Test taking slices of source.
-var mirror = debug.MakeMirror(eval('(function(){\n  1;\n})')).script();
-assertEquals('(function(){\n', mirror.sourceSlice(0, 1).sourceText());
-assertEquals('  1;\n', mirror.sourceSlice(1, 2).sourceText());
-assertEquals('})', mirror.sourceSlice(2, 3).sourceText());
-assertEquals('(function(){\n  1;\n', mirror.sourceSlice(0, 2).sourceText());
-assertEquals('  1;\n})', mirror.sourceSlice(1, 3).sourceText());
-assertEquals('(function(){\n  1;\n})', mirror.sourceSlice(0, 3).sourceText());
diff --git a/test/mjsunit/mjsunit.gyp b/test/mjsunit/mjsunit.gyp
index 35ce2ff..e0a7469 100644
--- a/test/mjsunit/mjsunit.gyp
+++ b/test/mjsunit/mjsunit.gyp
@@ -13,8 +13,8 @@
             '../../src/d8.gyp:d8_run',
           ],
           'includes': [
-            '../../build/features.gypi',
-            '../../build/isolate.gypi',
+            '../../gypfiles/features.gypi',
+            '../../gypfiles/isolate.gypi',
           ],
           'sources': [
             'mjsunit.isolate',
diff --git a/test/mjsunit/mjsunit.isolate b/test/mjsunit/mjsunit.isolate
index 18b73c2..6ebd801 100644
--- a/test/mjsunit/mjsunit.isolate
+++ b/test/mjsunit/mjsunit.isolate
@@ -13,7 +13,8 @@
       '../../tools/profile_view.js',
       '../../tools/profviz/composer.js',
       '../../tools/splaytree.js',
-      '../../tools/tickprocessor.js'
+      '../../tools/tickprocessor.js',
+      '../../tools/dumpcpp.js'
     ],
   },
   'includes': [
diff --git a/test/mjsunit/mjsunit.js b/test/mjsunit/mjsunit.js
index 9b07953..6a7c2da 100644
--- a/test/mjsunit/mjsunit.js
+++ b/test/mjsunit/mjsunit.js
@@ -114,6 +114,9 @@
 var assertOptimized;
 var assertUnoptimized;
 
+// Assert that a string contains another expected substring.
+var assertContains;
+
 
 (function () {  // Scope for utility functions.
 
@@ -416,6 +419,12 @@
     throw new MjsUnitAssertionError(message);
   };
 
+  assertContains = function(sub, value, name_opt) {
+    if (value == null ? (sub != null) : value.indexOf(sub) == -1) {
+      fail("contains '" + String(sub) + "'", value, name_opt);
+    }
+  };
+
   var OptimizationStatusImpl = undefined;
 
   var OptimizationStatus = function(fun, sync_opt) {
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index 6d786f9..017fa4d 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -76,6 +76,7 @@
   'unicode-test': [PASS, NO_VARIANTS],
   'whitespaces': [PASS, NO_VARIANTS],
   'compiler/osr-assert': [PASS, NO_VARIANTS],
+  'ignition/regress-599001-verifyheap': [PASS, NO_VARIANTS],
   'es6/string-fromcodepoint': [PASS, NO_VARIANTS],
   'regress/regress-2185-2': [PASS, NO_VARIANTS],
   'regress/regress-2612': [PASS, NO_VARIANTS],
@@ -93,14 +94,12 @@
   'debug-evaluate-locals-optimized': [PASS, NO_VARIANTS],
   'debug-evaluate-locals-optimized-double': [PASS, NO_VARIANTS],
   'debug-evaluate-recursive': [PASS, NO_VARIANTS],  # only in no-snap debug.
-  'debug-ignore-breakpoints': [PASS, NO_VARIANTS],  # only in no-snap debug.
   'debug-setbreakpoint': [PASS, NO_VARIANTS],  # only in no-snap debug.
   'debug-step': [PASS, NO_VARIANTS],  # windows only.
   'debug-step-2': [PASS, NO_VARIANTS],  # flaky in no-snap mode.
   'debug-step-3': [PASS, NO_VARIANTS],  # flaky in no-snap mode.
   'debug-stepframe-clearing': [PASS, NO_VARIANTS],  # only in no-snap debug.
   'debug-stepin-call-function-stub': [PASS, NO_VARIANTS],  # only in no-snap debug.
-  'debug-stepin-positions': [PASS, NO_VARIANTS],  # only due to inlining.
   'regress/regress-3717': [PASS, NO_VARIANTS],  # only in no-snap mode.
   'regress/regress-2451': [PASS, NO_VARIANTS],  # with custom snapshot and gc-stress.
   'debug-multiple-breakpoints': [PASS, NO_VARIANTS],  # with custom snapshot and gc-stress.
@@ -123,7 +122,6 @@
   'mirror-script': [PASS, NO_VARIANTS],  # on ARM64 only.
 
   # TODO(jarin/mstarzinger): Investigate debugger issues with TurboFan.
-  'debug-evaluate-const': [PASS, NO_VARIANTS],
   'debug-evaluate-locals': [PASS, NO_VARIANTS],
   'debug-evaluate-locals-capturing': [PASS, NO_VARIANTS],
   'debug-liveedit-check-stack': [PASS, NO_VARIANTS],  # only in no-snap mode.
@@ -149,10 +147,6 @@
   # issue 4078:
   'allocation-site-info': [PASS, NO_VARIANTS],
 
-  # TODO(turbofan): The escape analysis needs some investigation.
-  'compiler/escape-analysis-deopt-5': [PASS, NO_VARIANTS],
-  'compiler/escape-analysis-9': [PASS, NO_VARIANTS],
-
   ##############################################################################
   # Too slow in debug mode with --stress-opt mode.
   'compiler/regress-stacktrace-methods': [PASS, ['mode == debug', SKIP]],
@@ -197,11 +191,6 @@
   'regress/regress-crbug-482998': [PASS, NO_VARIANTS, ['arch == arm or arch == arm64 or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips64el or arch == mips', SKIP]],
 
   ##############################################################################
-  # This test expects to reach a certain recursion depth, which may not work
-  # for debug mode.
-  'json-recursive': [PASS, ['mode == debug', PASS, FAIL]],
-
-  ##############################################################################
   # Skip long running tests that time out in debug mode.
   'generated-transition-stub': [PASS, ['mode == debug', SKIP]],
   'migrations': [SKIP],
@@ -217,6 +206,7 @@
   # that, it doesn't make sense to run several variants of d8-os anyways.
   'd8-os': [PASS, NO_VARIANTS, ['isolates or arch == android_arm or arch == android_arm64 or arch == android_ia32', SKIP]],
   'tools/tickprocessor': [PASS, NO_VARIANTS, ['arch == android_arm or arch == android_arm64 or arch == android_ia32', SKIP]],
+  'tools/dumpcpp': [PASS, NO_VARIANTS, ['arch == android_arm or arch == android_arm64 or arch == android_ia32', SKIP]],
 
   ##############################################################################
   # Long running test that reproduces memory leak and should be run manually.
@@ -231,7 +221,6 @@
   # Tests with different versions for release and debug.
   'compiler/alloc-number': [PASS, ['mode == debug', SKIP]],
   'compiler/alloc-number-debug': [PASS, ['mode == release', SKIP]],
-  'regress/regress-634': [PASS, ['mode == debug', SKIP]],
   'regress/regress-634-debug': [PASS, ['mode == release', SKIP]],
 
   # BUG(336820). TODO(bmeurer): Investigate.
@@ -260,12 +249,11 @@
   # Slow tests.
   'copy-on-write-assert': [PASS, SLOW],
   'debug-scopes': [PASS, SLOW],
-  'es7/object-observe': [PASS, ['mode == debug', SLOW]],
   'numops-fuzz-part*': [PASS, ['mode == debug', SLOW]],
   'readonly': [PASS, SLOW],
   'regress/regress-1200351': [PASS, ['mode == debug', SLOW]],
   'regress/regress-crbug-474297': [PASS, ['mode == debug', SLOW]],
-  'es6/tail-call-megatest*': [PASS, FAST_VARIANTS],
+  'es6/tail-call-megatest*': [PASS, SLOW, FAST_VARIANTS, ['tsan', SKIP]],
 
   # TODO(titzer): ASM->WASM tests on these platforms
   'wasm/asm-wasm': [PASS, ['arch in [arm, arm64, mips, mipsel, mips64, mips64el]', SKIP]],
@@ -274,21 +262,74 @@
   'wasm/asm-wasm-literals': [PASS, ['arch in [arm, arm64, mips, mipsel, mips64, mips64el] or ignition == True', SKIP]],
   'wasm/asm-wasm-copy': [PASS, ['arch in [arm, arm64, mips, mipsel, mips64, mips64el]', SKIP]],
   'wasm/asm-wasm-deopt': [PASS, ['arch in [arm, arm64, mips, mipsel, mips64, mips64el]', SKIP]],
+  'wasm/asm-wasm-switch': [PASS, ['arch in [arm, arm64, mips, mipsel, mips64, mips64el]', SKIP]],
 
   # TODO(branelson): Figure out why ignition + asm->wasm fails embenchen.
   'wasm/embenchen/*': [PASS, ['arch == arm64', SKIP], ['ignition == True', SKIP]],
 
-  # TODO(bradnelson) Fix and re-enable.
-  'wasm/embenchen/box2d': [SKIP],   # hang
-  'wasm/embenchen/lua_binarytrees': [SKIP],  # fails decode
-  #'wasm/embenchen/zlib': [SKIP],  # fails gc-stress
-
   # case-insensitive unicode regexp relies on case mapping provided by ICU.
-  'harmony/unicode-regexp-ignore-case': [PASS, ['no_i18n == True', FAIL]],
-  'harmony/unicode-regexp-ignore-case-noi18n': [FAIL, ['no_i18n == True', PASS]],
+  'es6/unicode-regexp-ignore-case': [PASS, ['no_i18n == True', FAIL]],
+  'es6/unicode-regexp-ignore-case-noi18n': [FAIL, ['no_i18n == True', PASS]],
   'regress/regress-5036': [PASS, ['no_i18n == True', FAIL]],
   # desugaring regexp property class relies on ICU.
   'harmony/regexp-property-*': [PASS, ['no_i18n == True', FAIL]],
+
+  # TODO(bmeurer): Flaky timeouts (sometimes <1s, sometimes >3m).
+  'unicodelctest': [PASS, NO_VARIANTS],
+  'unicodelctest-no-optimization': [PASS, NO_VARIANTS],
+
+  ############################################################################
+  # Ignition
+
+  # TODO(mythria, 4780): Related to type feedback for calls in interpreter.
+  'array-literal-feedback': [PASS, NO_IGNITION],
+  'regress/regress-4121': [PASS, NO_IGNITION],
+
+  # TODO(mythria, 4764): lack of osr support.
+  'regress/regress-2618': [PASS, NO_IGNITION],
+
+  # TODO(mythria, 4764): lack of osr support. The tests waits in a loop
+  # till it is optimized. So test timeouts.
+  'array-literal-transitions': [PASS, NO_IGNITION],
+
+  # TODO(4680): Test doesn't know about three tier compiler pipeline.
+  'assert-opt-and-deopt': [PASS, NO_IGNITION],
+
+  # BUG(rmcilroy,4989): Function is optimized without type feedback and so immediately deopts again, causing check failure in the test.
+  'compiler/deopt-inlined-from-call': [PASS, NO_IGNITION],
+  'compiler/increment-typefeedback': [PASS, NO_IGNITION],
+  'compiler/manual-concurrent-recompile': [PASS, NO_IGNITION],
+  'constant-folding-2': [PASS, NO_IGNITION],
+  'debug-is-active': [PASS, NO_IGNITION],
+  'deopt-with-fp-regs': [PASS, NO_IGNITION],
+  'deserialize-optimize-inner': [PASS, NO_IGNITION],
+  'div-mul-minus-one': [PASS, NO_IGNITION],
+  'double-intrinsics': [PASS, NO_IGNITION],
+  'elements-transition-hoisting': [PASS, NO_IGNITION],
+  'es6/block-let-crankshaft': [PASS, NO_IGNITION],
+  'es6/block-let-crankshaft-sloppy': [PASS, NO_IGNITION],
+  'getters-on-elements': [PASS, NO_IGNITION],
+  'harmony/do-expressions': [PASS, NO_IGNITION],
+  'math-floor-of-div-minus-zero': [PASS, NO_IGNITION],
+  'regress/regress-2132': [PASS, NO_IGNITION],
+  'regress/regress-2339': [PASS, NO_IGNITION],
+  'regress/regress-3176': [PASS, NO_IGNITION],
+  'regress/regress-3709': [PASS, NO_IGNITION],
+  'regress/regress-385565': [PASS, NO_IGNITION],
+  'regress/regress-crbug-594183': [PASS, NO_IGNITION],
+  'regress/regress-embedded-cons-string': [PASS, NO_IGNITION],
+  'regress/regress-map-invalidation-2': [PASS, NO_IGNITION],
+  'regress/regress-param-local-type': [PASS, NO_IGNITION],
+  'regress/regress-prepare-break-while-recompile': [PASS, NO_IGNITION],
+  'shift-for-integer-div': [PASS, NO_IGNITION],
+  'sin-cos': [PASS, NO_IGNITION],
+  'smi-mul-const': [PASS, NO_IGNITION],
+  'smi-mul': [PASS, NO_IGNITION],
+  'unary-minus-deopt': [PASS, NO_IGNITION],
+
+  # TODO(rmcilroy,5038): Crashes in Deoptimizer::PatchCodeForDeoptimization on
+  # nosnap builds when --stress-opt and --turbo-from-bytecode is enabled.
+  'harmony/generators-turbo': [PASS, FAST_VARIANTS],
 }],  # ALWAYS
 
 ['novfp3 == True', {
@@ -335,7 +376,6 @@
   # TODO(mstarzinger): Takes too long with TF.
   'array-sort': [PASS, NO_VARIANTS],
   'regress/regress-91008': [PASS, NO_VARIANTS],
-  'regress/regress-417709a': [PASS, ['arch == arm64', NO_VARIANTS]],
   'regress/regress-transcendental': [PASS, ['arch == arm64', NO_VARIANTS]],
   'compiler/osr-regress-max-locals': [PASS, NO_VARIANTS],
   'math-floor-of-div': [PASS, NO_VARIANTS],
@@ -368,6 +408,9 @@
 
   # BUG(v8:4779): Crashes flakily with stress mode on arm64.
   'array-splice': [PASS, SLOW, ['arch == arm64', FAST_VARIANTS]],
+
+  # BUG(v8:5053).
+  'wasm/embenchen/fasta': [PASS, FAST_VARIANTS],
 }],  # 'gc_stress == True'
 
 ##############################################################################
@@ -384,8 +427,6 @@
   'asm/sqlite3/*': [SKIP],
   # TODO(mips-team): Fix Wasm for big-endian.
   'wasm/*': [SKIP],
-  'regress/regress-599717': [SKIP],
-  'regress/regress-599719': [SKIP],
 }],  # 'byteorder == big'
 
 ##############################################################################
@@ -407,15 +448,12 @@
   'big-object-literal': [SKIP],
   'compiler/regress-arguments': [SKIP],
   'compiler/regress-gvn': [SKIP],
-  'compiler/regress-max-locals-for-osr': [SKIP],
   'compiler/regress-4': [SKIP],
   'compiler/regress-or': [SKIP],
   'compiler/regress-rep-change': [SKIP],
   'regress/regress-1117': [SKIP],
-  'regress/regress-1145': [SKIP],
   'regress/regress-1849': [SKIP],
   'regress/regress-3247124': [SKIP],
-  'regress/regress-634': [SKIP],
   'regress/regress-91008': [SKIP],
   'regress/regress-91010': [SKIP],
   'regress/regress-91013': [SKIP],
@@ -459,22 +497,31 @@
   'unicodelctest': [PASS, SLOW],
   'unicode-test': [PASS, SLOW],
   'whitespaces': [PASS, TIMEOUT, SLOW],
+
+  # TODO(rmcilroy,4680): Arm64 specific timeouts.
+  'asm/construct-double': [PASS, NO_IGNITION],
+  'compiler/osr-one': [PASS, NO_IGNITION],
+  'compiler/osr-two': [PASS, NO_IGNITION],
+  'wasm/asm-wasm-i32': [PASS, NO_IGNITION],
+  'wasm/asm-wasm-u32': [PASS, NO_IGNITION],
 }],  # 'arch == arm64'
 
 ['arch == arm64 and mode == debug and simulator_run == True', {
 
   # Pass but take too long with the simulator in debug mode.
-  'array-iterate-backwards': [PASS, TIMEOUT],
   'array-sort': [PASS, TIMEOUT],
   'packed-elements': [SKIP],
   'regexp-global': [SKIP],
-  'compiler/alloc-numbers': [SKIP],
   'math-floor-of-div': [PASS, TIMEOUT],
   'math-floor-of-div-nosudiv': [PASS, TIMEOUT],
   'unicodelctest': [PASS, TIMEOUT],
   'unicodelctest-no-optimization': [PASS, TIMEOUT],
   # Issue 3219:
   'getters-on-elements': [PASS, ['gc_stress == True', FAIL]],
+
+  # Ignition.
+  'es6/templates': [PASS, ['no_snap and mode == debug', NO_IGNITION]],
+  'regress/regress-crbug-364374': [PASS, ['no_snap and mode == debug', NO_IGNITION]],
 }],  # 'arch == arm64 and mode == debug and simulator_run == True'
 
 ##############################################################################
@@ -497,6 +544,20 @@
   'deep-recursion': [SKIP],
   'regress/regress-builtinbust-7': [SKIP],
   'string-localecompare': [SKIP],
+
+  # TODO(mythria,4680): All of these tests have large loops and hence slow
+  # and timeout.
+  'compiler/osr-big': [PASS, NO_IGNITION],
+  'compiler/osr-nested': [PASS, NO_IGNITION],
+  'regress/regress-298269': [PASS, NO_IGNITION],
+  'regress/regress-crbug-319860': [PASS, NO_IGNITION],
+  'regress/regress-deep-proto': [PASS, NO_IGNITION],
+  'try': [PASS, NO_IGNITION],
+  # Too slow for interpreter and msan.
+  'es6/tail-call-megatest*': [PASS, NO_IGNITION],
+
+  # Too slow.
+  'harmony/regexp-property-lu-ui': [SKIP],
 }],  # 'msan == True'
 
 ##############################################################################
@@ -520,7 +581,6 @@
   'big-object-literal': [SKIP],
   'compiler/alloc-number': [SKIP],
   'regress/regress-490': [SKIP],
-  'regress/regress-634': [SKIP],
   'regress/regress-create-exception': [SKIP],
   'regress/regress-3247124': [SKIP],
 
@@ -542,6 +602,11 @@
   'regress/regress-91008': [PASS, SLOW],
   'regress/regress-json-stringify-gc': [PASS, SLOW],
   'string-indexof-2': [PASS, TIMEOUT],
+
+  # TODO(rmcilroy,4680): Arm specific timeouts.
+  'compiler/osr-one': [PASS, NO_IGNITION],
+  'compiler/osr-two': [PASS, NO_IGNITION],
+  'regress/regress-1257': [PASS, NO_IGNITION],
 }],  # 'arch == arm or arch == android_arm'
 
 ##############################################################################
@@ -564,7 +629,6 @@
   # the buildbot.
   'compiler/alloc-number': [SKIP],
   'regress/regress-490': [SKIP],
-  'regress/regress-634': [SKIP],
   'regress/regress-create-exception': [SKIP],
   'regress/regress-3247124': [SKIP],
 
@@ -627,7 +691,6 @@
   'compiler/regress-3249650': [PASS, SLOW],
   'compiler/simple-deopt': [PASS, SLOW],
   'regress/regress-490': [PASS, SLOW],
-  'regress/regress-634': [PASS, SLOW],
   'regress/regress-create-exception': [PASS, SLOW],
   'regress/regress-3218915': [PASS, SLOW],
   'regress/regress-3247124': [PASS, SLOW],
@@ -647,7 +710,6 @@
   'big-object-literal': [PASS, ['mode == debug', SKIP]],
   'math-floor-of-div': [PASS, ['mode == debug', SKIP]],
   'math-floor-of-div-nosudiv': [PASS, ['mode == debug', SKIP]],
-  'osr-regress-max-locals': [PASS, ['mode == debug', SKIP]],
   'unicodelctest': [PASS, ['mode == debug', SKIP]],
 
   # BUG(v8:3435)
@@ -692,7 +754,6 @@
   'regress/regress-1257': [PASS, NO_VARIANTS],
   'regress/regress-2618': [PASS, NO_VARIANTS],
   'regress/regress-298269': [PASS, NO_VARIANTS],
-  'regress/regress-634': [PASS, NO_VARIANTS],
   'regress/regress-91008': [PASS, NO_VARIANTS],
   'compiler/osr-alignment': [PASS, NO_VARIANTS],
   'compiler/osr-one': [PASS, NO_VARIANTS],
@@ -759,35 +820,14 @@
 }],  # 'arch == ppc and simulator_run == True'
 
 ##############################################################################
-['ignition == True', {
-  # TODO(yangguo,4690): assertion failures in debugger tests.
-  'debug-allscopes-on-debugger': [FAIL],
-  'es6/debug-stepnext-for': [FAIL],
-  'es6/debug-promises/stepin-constructor': [FAIL],
-  'es6/debug-stepin-proxies': [FAIL],
-  'regress/regress-crbug-119800': [FAIL],
-  'regress/regress-opt-after-debug-deopt': [FAIL],
+['arch == ppc64', {
 
-  # TODO(yangguo,4690): flaky failures on the bots.
-  'debug-stepin-builtin-callback-opt': [SKIP],
+  # stack overflow
+  'big-array-literal': [SKIP],
+}],  # 'arch == ppc64'
 
-   # TODO(rmcilroy,4765): assertion failures in LiveEdit tests.
-  'debug-liveedit-restart-frame': [FAIL],
-  'debug-liveedit-literals': [FAIL],
-  'debug-liveedit-3': [FAIL],
-  'debug-liveedit-1': [FAIL],
-  'debug-liveedit-2': [FAIL],
-  'debug-liveedit-patch-positions-replace': [FAIL],
-  'debug-liveedit-patch-positions': [FAIL],
-  'debug-liveedit-stepin': [FAIL],
-  'debug-liveedit-newsource': [FAIL],
-  'debug-liveedit-stack-padding': [FAIL],
-  'debug-liveedit-breakpoints': [FAIL],
-  'es6/debug-liveedit-new-target-1': [FAIL],
-  'es6/debug-liveedit-new-target-2': [FAIL],
-  'es6/debug-liveedit-new-target-3': [FAIL],
-  'es6/generators-debug-liveedit': [FAIL],
-
+##############################################################################
+['ignition or ignition_turbofan', {
   # TODO(mythria, 4780): Related to type feedback for calls in interpreter.
   'array-literal-feedback': [FAIL],
   'regress/regress-4121': [FAIL],
@@ -798,56 +838,42 @@
   # till it is optimized. So test timeouts.
   'array-literal-transitions': [SKIP],
 
-  # TODO(mythria, 4680): Relate to GC and ignition holding references to
-  # objects.
-  'es6/mirror-collections': [FAIL],
-
-  # TODO(mythria, 4680): Fails with context_register_count_ > 0 (0 vs. 0) when
-  # trying to get a context register in BytecodeGenerator.
-  'harmony/regress/regress-4658': [FAIL, ['mode == release and dcheck_always_on == False', PASS],],
-
-  # TODO(rmcilroy, 4680): Script throws RangeError as expected, but does so during
-  # eager compile of the whole script instead of during lazy compile of the function
-  # f(), so we can't catch the exception in the try/catch. Skip because on some
-  # platforms the stack limit is different and the exception doesn't fire.
-  'regress/regress-crbug-589472': [SKIP],
-
-  # Debugger test cases that pass with ignition, but not full-codegen.
-  # These differences between full-codegen and ignition are deliberate.
-  'ignition/elided-instruction-no-ignition': [FAIL],
-
   'wasm/asm-wasm-f32': [PASS, ['arch in [arm64]', SKIP]],
   'wasm/asm-wasm-f64': [PASS, ['arch in [arm64]', SKIP]],
-}],  # ignition == True
 
-['ignition == True and system == windows', {
-  # TODO(rmcilroy,4680): Crash on windows nosnap shared.
-  'regress/regress-crbug-352058': [PASS, ['no_snap == True', SKIP]],
+  # TODO(rmcilroy,titzer): Times out after
+  # https://codereview.chromium.org/1951013002 .
+  'regress/regress-599717': [PASS, ['tsan', SKIP]],
 
-  # TODO(513471): Attempting to optimize generator hits unreachable path.
-  'regress/regress-crbug-513471': [PASS, ['no_snap == True', SKIP]],
+  # TODO(rmcilroy,5038): Crashes in Deoptimizer::PatchCodeForDeoptimization on
+  # nosnap builds when --stress-opt and --turbo-from-bytecode is enabled.
+  'harmony/generators-turbo': [PASS, FAST_VARIANTS],
+  'regress/regress-crbug-352058': [SKIP],
 
-  # TODO(rmcilroy,4680): Fails on win32 debug.
-  'div-mod': [PASS, ['arch == ia32', SKIP]],
-}],  # ignition == True and system == windows
+  # TODO(jarin): No truncations on CheckFloat64Hole.
+  'getters-on-elements': [SKIP],
 
-['ignition == True and arch == arm64', {
+  # TODO(rmcilroy): Flaky OOM.
+  'unicodelctest-no-optimization': [SKIP],
+}],  # ignition or ignition_turbofan
+
+['(ignition or ignition_turbofan) and arch == arm64', {
   # TODO(rmcilroy,4680): Arm64 specific timeouts.
   'asm/construct-double': [SKIP],
   'compiler/osr-one': [SKIP],
   'compiler/osr-two': [SKIP],
   'wasm/asm-wasm-i32': [SKIP],
   'wasm/asm-wasm-u32': [SKIP],
-}],  # ignition == True and arch == arm64
+}],  # (ignition or ignition_turbofan) and arch == arm64
 
-['ignition == True and arch == arm', {
+['(ignition or ignition_turbofan) and arch == arm', {
   # TODO(rmcilroy,4680): Arm specific timeouts.
   'compiler/osr-one': [SKIP],
   'compiler/osr-two': [SKIP],
   'regress/regress-1257': [SKIP],
-}],  # ignition == True and arch == arm
+}],  # (ignition or ignition_turbofan) and arch == arm
 
-['ignition == True and msan', {
+['(ignition or ignition_turbofan) and msan', {
   # TODO(mythria,4680): All of these tests have large loops and hence slow
   # and timeout.
   'compiler/osr-big': [SKIP],
@@ -858,55 +884,7 @@
   'try': [SKIP],
   # Too slow for interpreter and msan.
   'es6/tail-call-megatest*': [SKIP],
-}],  # ignition == True and msan
-
-['ignition == True and gc_stress == True', {
-  # TODO(oth,4680): failures from the bots.
-  'es6/debug-step-destructuring-bind': [SKIP],
-  'es6/debug-stepin-collections-foreach': [SKIP],
-  'ignition/elided-instruction': [SKIP],
-  'regress/regress-269': [SKIP],
-}],  # ignition == True and gc_stress == True
-
-['ignition == False', {
-  # Debugger test cases that pass with full-codegen, but not ignition.
-  # These differences between full-codegen and ignition are deliberate.
-  'ignition/elided-instruction': [FAIL],
-}],  # ignition == False
-
-['ignition == True and system == windows and no_snap', {
-  # TODO(rmcilroy): Fail with nosnap and shared libraries.
-  'es6/array-from': [FAIL],
-  'es6/classes-subclass-builtins': [FAIL],
-  'es6/computed-property-names-classes': [FAIL],
-  'es6/computed-property-names-object-literals-methods': [FAIL],
-  'es6/debug-stepin-generators': [FAIL],
-  'es6/destructuring': [FAIL],
-  'es6/destructuring-assignment': [FAIL],
-  'es6/generators-iteration': [FAIL],
-  'es6/generators-mirror': [FAIL],
-  'es6/generators-parsing': [FAIL],
-  'es6/generators-poisoned-properties': [FAIL],
-  'es6/generators-relocation': [FAIL],
-  'es6/generators-states': [FAIL],
-  'es6/iteration-semantics': [FAIL],
-  'es6/object-literals-method': [FAIL],
-  'es6/object-literals-super': [FAIL],
-  'es6/promises': [FAIL],
-  'es6/regress/regress-2681': [FAIL],
-  'es6/regress/regress-2691': [FAIL],
-  'es6/regress/regress-3280': [FAIL],
-  'es6/spread-array': [FAIL],
-  'es6/spread-call': [FAIL],
-  'es6/typedarray': [FAIL],
-  'es6/typedarray-from': [FAIL],
-  'harmony/function-sent': [FAIL],
-  'harmony/generators': [FAIL],
-  'harmony/iterator-close': [FAIL],
-  'harmony/regress/regress-4482': [FAIL],
-  'messages': [FAIL],
-  'regress-3225': [FAIL],
-}],  # ignition == True and system == windows and no_snap
+}],  # (ignition or ignition_turbofan) and msan
 
 ##############################################################################
 ['gcov_coverage', {
diff --git a/test/mjsunit/object-define-property.js b/test/mjsunit/object-define-property.js
index 4c495c6..380a71a 100644
--- a/test/mjsunit/object-define-property.js
+++ b/test/mjsunit/object-define-property.js
@@ -467,8 +467,7 @@
 }
 
 
-// Test runtime calls to DefineDataPropertyUnchecked and
-// DefineAccessorPropertyUnchecked - make sure we don't
+// Test runtime calls to DefineAccessorPropertyUnchecked - make sure we don't
 // crash.
 try {
   %DefineAccessorPropertyUnchecked(0, 0, 0, 0, 0);
@@ -477,29 +476,11 @@
 }
 
 try {
-  %DefineDataPropertyUnchecked(0, 0, 0, 0);
-} catch (e) {
-  assertTrue(/illegal access/.test(e));
-}
-
-try {
-  %DefineDataPropertyUnchecked(null, null, null, null);
-} catch (e) {
-  assertTrue(/illegal access/.test(e));
-}
-
-try {
   %DefineAccessorPropertyUnchecked(null, null, null, null, null);
 } catch (e) {
   assertTrue(/illegal access/.test(e));
 }
 
-try {
-  %DefineDataPropertyUnchecked({}, null, null, null);
-} catch (e) {
-  assertTrue(/illegal access/.test(e));
-}
-
 // Defining properties null should fail even when we have
 // other allowed values
 try {
@@ -508,12 +489,6 @@
   assertTrue(/illegal access/.test(e));
 }
 
-try {
-  %DefineDataPropertyUnchecked(null, 'foo', 0, 0);
-} catch (e) {
-  assertTrue(/illegal access/.test(e));
-}
-
 // Test that all possible differences in step 6 in DefineOwnProperty are
 // exercised, i.e., any difference in the given property descriptor and the
 // existing properties should not return true, but throw an error if the
diff --git a/test/mjsunit/object-literal.js b/test/mjsunit/object-literal.js
index 19860ff..b861d44 100644
--- a/test/mjsunit/object-literal.js
+++ b/test/mjsunit/object-literal.js
@@ -24,8 +24,6 @@
 // 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-function-name
 
 var obj = {
     a: 7,
diff --git a/test/mjsunit/osr-elements-kind.js b/test/mjsunit/osr-elements-kind.js
index bd15ef3..aee7017 100644
--- a/test/mjsunit/osr-elements-kind.js
+++ b/test/mjsunit/osr-elements-kind.js
@@ -30,7 +30,7 @@
 // Limit the number of stress runs to reduce polymorphism it defeats some of the
 // assumptions made about how elements transitions work because transition stubs
 // end up going generic.
-// Flags: --stress-runs=2
+// Flags: --stress-runs=1
 
 var elements_kind = {
   fast_smi_only             :  'fast smi only elements',
diff --git a/test/mjsunit/realm-property-access.js b/test/mjsunit/realm-property-access.js
new file mode 100644
index 0000000..679886d
--- /dev/null
+++ b/test/mjsunit/realm-property-access.js
@@ -0,0 +1,20 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var r = Realm.create();
+var f = Realm.eval(r, "function f() { return this }; f()");
+assertEquals(f, Realm.global(r));
+
+// Cross-origin property access throws
+assertThrows(() => f.a, TypeError);
+assertThrows(() => { 'use strict'; f.a = 1 }, TypeError);
+
+var r2 = Realm.createAllowCrossRealmAccess();
+var f2 = Realm.eval(r2, "function f() { return this }; f()");
+assertEquals(f2, Realm.global(r2));
+
+// Same-origin property access doesn't throw
+assertEquals(undefined, f2.a);
+f2.a = 1;
+assertEquals(1, f2.a);
diff --git a/test/mjsunit/regexp-compile.js b/test/mjsunit/regexp-compile.js
index 92c3f7b..f001780 100644
--- a/test/mjsunit/regexp-compile.js
+++ b/test/mjsunit/regexp-compile.js
@@ -42,3 +42,7 @@
 assertEquals(["y", "y"], re.exec("axyb"));
 
 assertEquals(2, re.compile.length);
+
+// If RegExp parsing fails, the RegExp is not modified
+var r = /./; try { r.compile('? invalid'); } catch(err){}
+assertEquals("/./", r.toString());
diff --git a/test/mjsunit/regexp-lastIndex.js b/test/mjsunit/regexp-lastIndex.js
deleted file mode 100644
index 1445b9b..0000000
--- a/test/mjsunit/regexp-lastIndex.js
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// lastIndex is set according to funny rules. It is typically set only
-// for global or sticky RegExps, but on a failure to find a match, it is
-// set unconditionally. If a set fails, then it acts as if in strict mode
-// and throws.
-
-var re = /x/;
-Object.defineProperty(re, 'lastIndex', {writable: false});
-assertThrows(() => re.exec(""), TypeError);
-assertEquals(["x"], re.exec("x"));
-
-var re = /x/y;
-Object.defineProperty(re, 'lastIndex', {writable: false});
-assertThrows(() => re.exec(""), TypeError);
-assertThrows(() => re.exec("x"), TypeError);
diff --git a/test/mjsunit/regexp-string-methods.js b/test/mjsunit/regexp-string-methods.js
index fa01a33..d5ad9c3 100644
--- a/test/mjsunit/regexp-string-methods.js
+++ b/test/mjsunit/regexp-string-methods.js
@@ -25,8 +25,6 @@
 // (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: --no-harmony-regexp-exec
-
 // Regexp shouldn't use String.prototype.slice()
 var s = new String("foo");
 assertEquals("f", s.slice(0,1));
@@ -43,11 +41,3 @@
 var f2 = new RegExp("[g]", "i");
 assertEquals(["G"], f2.exec("G"));
 assertTrue(f2.ignoreCase);
-
-// On the other hand test is defined in a semi-coherent way as a call to exec.
-// 15.10.6.3
-// We match other browsers in using the original value of RegExp.prototype.exec.
-// I.e., RegExp.prototype.test shouldn't use the current value of
-// RegExp.prototype.exec.
-RegExp.prototype.exec = function(string) { return 'x'; };
-assertFalse(/f/.test('x'));
diff --git a/test/mjsunit/regress-604044.js b/test/mjsunit/regress-604044.js
new file mode 100644
index 0000000..58ccfbe
--- /dev/null
+++ b/test/mjsunit/regress-604044.js
@@ -0,0 +1,7 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --min-preparse-length 1
+
+(function(_ = function() {}){})
diff --git a/test/mjsunit/regress-crbug-619476.js b/test/mjsunit/regress-crbug-619476.js
new file mode 100644
index 0000000..33204ae
--- /dev/null
+++ b/test/mjsunit/regress-crbug-619476.js
@@ -0,0 +1,7 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var x = {};
+// Crashes in debug mode if an erroneous DCHECK in dfb8d333 is not removed.
+eval, x[eval];
diff --git a/test/mjsunit/regress/redeclaration-error-types.js b/test/mjsunit/regress/redeclaration-error-types.js
new file mode 100644
index 0000000..72e097d
--- /dev/null
+++ b/test/mjsunit/regress/redeclaration-error-types.js
@@ -0,0 +1,145 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+function doTest(scripts, expectedError) {
+  var realm = Realm.create();
+
+  for (var i = 0; i < scripts.length - 1; i++) {
+    Realm.eval(realm, scripts[i]);
+  }
+  assertThrows(function() {
+    Realm.eval(realm, scripts[scripts.length - 1]);
+  }, Realm.eval(realm, expectedError));
+
+  Realm.dispose(realm);
+}
+
+var tests = [
+  {
+    // ES#sec-globaldeclarationinstantiation 5.a:
+    // If envRec.HasVarDeclaration(name) is true, throw a SyntaxError
+    // exception.
+    scripts: [
+      "var a;",
+      "let a;",
+    ],
+    expectedError: "SyntaxError",
+  },
+  {
+    // ES#sec-globaldeclarationinstantiation 6.a:
+    // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
+    // exception.
+    scripts: [
+      "let a;",
+      "var a;",
+    ],
+    expectedError: "SyntaxError",
+  },
+  {
+    // ES#sec-globaldeclarationinstantiation 5.b:
+    // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
+    // exception.
+    scripts: [
+      "let a;",
+      "let a;",
+    ],
+    expectedError: "SyntaxError",
+  },
+  {
+    // ES#sec-evaldeclarationinstantiation 5.a.i.1:
+    // If varEnvRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
+    // exception.
+    scripts: [
+      'let a; eval("var a;");',
+    ],
+    expectedError: "SyntaxError",
+  },
+  {
+    // ES#sec-evaldeclarationinstantiation 5.a.i.1:
+    // If varEnvRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
+    // exception.
+    scripts: [
+      'let a; eval("function a() {}");',
+    ],
+    expectedError: "SyntaxError",
+  },
+  {
+    // ES#sec-evaldeclarationinstantiation 5.d.ii.2.a.i:
+    // Throw a SyntaxError exception.
+    scripts: [
+      '(function() { let a; eval("var a;"); })();',
+    ],
+    expectedError: "SyntaxError",
+  },
+  {
+    // ES#sec-evaldeclarationinstantiation 5.d.ii.2.a.i:
+    // Throw a SyntaxError exception.
+    scripts: [
+      '(function() { let a; eval("function a() {}"); })();',
+    ],
+    expectedError: "SyntaxError",
+  },
+  {
+    // ES#sec-globaldeclarationinstantiation 5.d:
+    // If hasRestrictedGlobal is true, throw a SyntaxError exception.
+    scripts: [
+      'let NaN;',
+    ],
+    expectedError: "SyntaxError",
+  },
+  {
+    // ES#sec-globaldeclarationinstantiation 5.d:
+    // If hasRestrictedGlobal is true, throw a SyntaxError exception.
+    scripts: [
+      'function NaN() {}',
+    ],
+    expectedError: "SyntaxError",
+  },
+
+  {
+    // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b:
+    // If fnDefinable is false, throw a TypeError exception.
+    scripts: [
+      'eval("function NaN() {}");',
+    ],
+    expectedError: "TypeError",
+  },
+  {
+    // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b:
+    // If fnDefinable is false, throw a TypeError exception.
+    scripts: [
+      `
+        let a;
+        try {
+          eval("function a() {}");
+        } catch (e) {}
+        eval("function NaN() {}");
+      `,
+    ],
+    expectedError: "TypeError",
+  },
+  {
+    // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b:
+    // If fnDefinable is false, throw a TypeError exception.
+    scripts: [
+      `
+        eval("
+          function f() {
+            function b() {
+              (0, eval)('function NaN() {}');
+            }
+            b();
+          }
+          f();
+        ");
+      `.replace(/"/g, '`'),
+    ],
+    expectedError: "TypeError",
+  },
+];
+
+tests.forEach(function(test) {
+  doTest(test.scripts, test.expectedError);
+});
diff --git a/test/mjsunit/regress/regress-1132.js b/test/mjsunit/regress/regress-1132.js
index a5cb0a1..adb56b0 100644
--- a/test/mjsunit/regress/regress-1132.js
+++ b/test/mjsunit/regress/regress-1132.js
@@ -28,7 +28,7 @@
 // Test the case when exception is thrown from the parser when lazy
 // compiling a function.
 
-// Flags: --stack-size=46
+// Flags: --stack-size=100
 // NOTE: stack size constant above has been empirically chosen.
 // If the test starts to fail in Genesis, consider increasing this constant.
 
diff --git a/test/mjsunit/regress/regress-1246.js b/test/mjsunit/regress/regress-1246.js
deleted file mode 100644
index ca425ec..0000000
--- a/test/mjsunit/regress/regress-1246.js
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This regression tests the behaviour of the parseInt function when
-// the given radix is not a SMI.
-
-// Flags: --allow-natives-syntax
-
-var nonSmi10 = Math.log(Math.exp(10));
-var nonSmi16 = Math.log(Math.exp(16));
-
-assertTrue(!%_IsSmi(nonSmi10) && nonSmi10 == 10);
-assertTrue(!%_IsSmi(nonSmi16) && nonSmi16 == 16);
-
-// Giving these values as the radix argument triggers radix detection.
-var radix_detect = [0, -0, NaN, Infinity, -Infinity, undefined, null,
-                    "0", "-0", "a"];
-
-// These values will result in an integer radix outside of the valid range.
-var radix_invalid = [1, 37, -2, "-2", "37"];
-
-// These values will trigger decimal parsing.
-var radix10 = [10, 10.1, "10", "10.1", nonSmi10];
-
-// These values will trigger hexadecimal parsing.
-var radix16 = [16, 16.1, 0x10, "0X10", nonSmi16];
-
-for (var i = 0; i < radix_detect.length; i++) {
-  var radix = radix_detect[i];
-  assertEquals(NaN, parseInt("", radix));
-  assertEquals(23, parseInt("23", radix));
-  assertEquals(0xaf, parseInt("0xaf", radix));
-  assertEquals(NaN, parseInt("af", radix));
-}
-
-for (var i = 0; i < radix_invalid.length; i++) {
-  var radix = radix_invalid[i];
-  assertEquals(NaN, parseInt("", radix));
-  assertEquals(NaN, parseInt("23", radix));
-  assertEquals(NaN, parseInt("0xaf", radix));
-  assertEquals(NaN, parseInt("af", radix));
-}
-
-for (var i = 0; i < radix10.length; i++) {
-  var radix = radix10[i];
-  assertEquals(NaN, parseInt("", radix));
-  assertEquals(23, parseInt("23", radix));
-  assertEquals(0, parseInt("0xaf", radix));
-  assertEquals(NaN, parseInt("af", radix));
-}
-
-for (var i = 0; i < radix16.length; i++) {
-  var radix = radix16[i];
-  assertEquals(NaN, parseInt("", radix));
-  assertEquals(0x23, parseInt("23", radix));
-  assertEquals(0xaf, parseInt("0xaf", radix));
-  assertEquals(0xaf, parseInt("af", radix));
-}
diff --git a/test/mjsunit/regress/regress-3315.js b/test/mjsunit/regress/regress-3315.js
deleted file mode 100644
index bfd7df2..0000000
--- a/test/mjsunit/regress/regress-3315.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Flags: --harmony-object-observe
-
-var indexZeroCallCount = 0;
-var indexOneCallCount = 0;
-var lengthCallCount = 0;
-var acceptList = {
-  get 0() {
-    indexZeroCallCount++;
-    return 'foo';
-  },
-  get 1() {
-    indexOneCallCount++;
-    return 'bar';
-  },
-  get length() {
-    lengthCallCount++;
-    return 1;
-  }
-};
-
-Object.observe({}, function(){}, acceptList);
-assertEquals(1, lengthCallCount);
-assertEquals(1, indexZeroCallCount);
-assertEquals(0, indexOneCallCount);
diff --git a/test/mjsunit/regress/regress-353004.js b/test/mjsunit/regress/regress-353004.js
index 658fd6d..7e1fb7e 100644
--- a/test/mjsunit/regress/regress-353004.js
+++ b/test/mjsunit/regress/regress-353004.js
@@ -41,19 +41,21 @@
 
 
 var buffer5 = new ArrayBuffer(100 * 1024);
-var buffer6 = buffer5.slice({valueOf : function() {
-  %ArrayBufferNeuter(buffer5);
-  return 0;
-}}, 100 * 1024 * 1024);
-assertEquals(0, buffer6.byteLength);
+assertThrows(function() {
+  buffer5.slice({valueOf : function() {
+    %ArrayBufferNeuter(buffer5);
+    return 0;
+  }}, 100 * 1024 * 1024);
+}, TypeError);
 
 
 var buffer7 = new ArrayBuffer(100 * 1024 * 1024);
-var buffer8 = buffer7.slice(0, {valueOf : function() {
-  %ArrayBufferNeuter(buffer7);
-  return 100 * 1024 * 1024;
-}});
-assertEquals(0, buffer8.byteLength);
+assertThrows(function() {
+  buffer7.slice(0, {valueOf : function() {
+    %ArrayBufferNeuter(buffer7);
+    return 100 * 1024 * 1024;
+  }});
+}, TypeError);
 
 var buffer9 = new ArrayBuffer(1024);
 var array9 = new Uint8Array(buffer9);
diff --git a/test/mjsunit/regress/regress-356589.js b/test/mjsunit/regress/regress-356589.js
deleted file mode 100644
index a47f51b..0000000
--- a/test/mjsunit/regress/regress-356589.js
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 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-object-observe
-
-// This test passes if it does not crash in debug mode
-
-arr = ['a', 'b', 'c', 'd'];
-Object.defineProperty(arr.__proto__, '0', { get: function(){} });
-Object.defineProperty(arr, '2', {get: function(){} });
-Object.observe(arr, function() {});
-arr.length = 2;
diff --git a/test/mjsunit/regress/regress-3926.js b/test/mjsunit/regress/regress-3926.js
index 4720c1b..4d9b298 100644
--- a/test/mjsunit/regress/regress-3926.js
+++ b/test/mjsunit/regress/regress-3926.js
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-sloppy --harmony-sloppy-let
-
 // See: http://code.google.com/p/v8/issues/detail?id=3926
 
 // Switch statements should disable hole check elimination
diff --git a/test/mjsunit/regress/regress-403292.js b/test/mjsunit/regress/regress-403292.js
deleted file mode 100644
index 2e24d48..0000000
--- a/test/mjsunit/regress/regress-403292.js
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --allow-natives-syntax --expose-natives-as=builtins --expose-gc
-
-var SetIterator = builtins.ImportNow("SetIterator");
-var MapIterator = builtins.ImportNow("MapIterator");
-var __v_7 = [];
-var __v_8 = {};
-var __v_10 = {};
-var __v_11 = this;
-var __v_12 = {};
-var __v_13 = {};
-var __v_14 = "";
-var __v_15 = {};
-try {
-__v_1 = {x:0};
-%OptimizeFunctionOnNextCall(__f_1);
-assertEquals("good", __f_1());
-delete __v_1.x;
-assertEquals("good", __f_1());
-} catch(e) { print("Caught: " + e); }
-try {
-__v_3 = new Set();
-__v_5 = new SetIterator(__v_3, -12);
-__v_4 = new Map();
-__v_6 = new MapIterator(__v_4, 2);
-__f_3(Array);
-} catch(e) { print("Caught: " + e); }
-function __f_4(__v_8, filter) {
-  function __f_6(v) {
-    for (var __v_4 in v) {
-      for (var __v_4 in v) {}
-    }
-    %OptimizeFunctionOnNextCall(filter);
-    return filter(v);
-  }
-  var __v_7 = eval(__v_8);
-  gc();
-  return __f_6(__v_7);
-}
-function __f_5(__v_6) {
-  var __v_5 = new Array(__v_6);
-  for (var __v_4 = 0; __v_4 < __v_6; __v_4++) __v_5.push('{}');
-  return __v_5;
-}
-try {
-try {
-  __v_8.test("\x80");
-  assertUnreachable();
-} catch (e) {
-}
-gc();
-} catch(e) { print("Caught: " + e); }
diff --git a/test/mjsunit/regress/regress-417709a.js b/test/mjsunit/regress/regress-417709a.js
deleted file mode 100644
index 5500be2..0000000
--- a/test/mjsunit/regress/regress-417709a.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-object-observe
-// Flags: --stack-size=100
-
-var a = [];
-
-Object.observe(a, function() {});
-
-function f(a, x) {
-  a.length = x;
-  f(a, x + 1);
-}
-
-assertThrows(function() { f(a, 1); }, RangeError);
diff --git a/test/mjsunit/regress/regress-417709b.js b/test/mjsunit/regress/regress-417709b.js
deleted file mode 100644
index 4d9572e..0000000
--- a/test/mjsunit/regress/regress-417709b.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-object-observe --stack-size=100
-
-var a = [];
-
-Array.observe(a, function() {});
-
-function f(a, x) {
-  a.length = x;
-  f(a, x + 1);
-}
-
-assertThrows(function() { f(a, 1); }, RangeError);
diff --git a/test/mjsunit/regress/regress-449070.js b/test/mjsunit/regress/regress-449070.js
deleted file mode 100644
index 7a0f0a8..0000000
--- a/test/mjsunit/regress/regress-449070.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Flags: --allow-natives-syntax
-
-try {
-  %NormalizeElements(this);
-} catch(e) {
-}
diff --git a/test/mjsunit/regress/regress-4659.js b/test/mjsunit/regress/regress-4659.js
index ff436be..8992bb8 100644
--- a/test/mjsunit/regress/regress-4659.js
+++ b/test/mjsunit/regress/regress-4659.js
@@ -1,8 +1,6 @@
 // Copyright 2016 the V8 project authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-//
-// Flags: --harmony-function-name
 
 var obj = {
   get longerName(){
diff --git a/test/mjsunit/regress/regress-4665-2.js b/test/mjsunit/regress/regress-4665-2.js
deleted file mode 100644
index b94301e..0000000
--- a/test/mjsunit/regress/regress-4665-2.js
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-species
-
-// First test case
-
-function FirstBuffer () {}
-FirstBuffer.prototype.__proto__ = Uint8Array.prototype
-FirstBuffer.__proto__ = Uint8Array
-
-var buf = new Uint8Array(10)
-buf.__proto__ = FirstBuffer.prototype
-
-var buf2 = buf.subarray(2)
-assertEquals(8, buf2.length);
-
-// Second test case
-
-function SecondBuffer (arg) {
-  var arr = new Uint8Array(arg)
-  arr.__proto__ = SecondBuffer.prototype
-  return arr
-}
-SecondBuffer.prototype.__proto__ = Uint8Array.prototype
-SecondBuffer.__proto__ = Uint8Array
-
-var buf3 = new SecondBuffer(10)
-
-var buf4 = buf3.subarray(2)
-
-assertEquals(8, buf4.length);
diff --git a/test/mjsunit/regress/regress-4665.js b/test/mjsunit/regress/regress-4665.js
index 9d7307a..a75d68f 100644
--- a/test/mjsunit/regress/regress-4665.js
+++ b/test/mjsunit/regress/regress-4665.js
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --noharmony-species
-
 // First test case
 
 function FirstBuffer () {}
diff --git a/test/mjsunit/regress/regress-4693.js b/test/mjsunit/regress/regress-4693.js
index 13b4e2b..2c31cd9 100644
--- a/test/mjsunit/regress/regress-4693.js
+++ b/test/mjsunit/regress/regress-4693.js
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Flags: --harmony-sloppy-function
 
 // In sloppy mode we allow function redeclarations within blocks for webcompat.
 (function() {
diff --git a/test/mjsunit/regress/regress-4703.js b/test/mjsunit/regress/regress-4703.js
new file mode 100644
index 0000000..dad8a97
--- /dev/null
+++ b/test/mjsunit/regress/regress-4703.js
@@ -0,0 +1,30 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var all_scopes = exec_state.frame().allScopes();
+    assertEquals([ debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global ],
+                 all_scopes.map(scope => scope.scopeType()));
+  } catch (e) {
+    exception = e;
+  }
+}
+
+debug.Debug.setListener(listener);
+
+(function(arg, ...rest) {
+  var one = 1;
+  function inner() {
+    one;
+    arg;
+  }
+  debugger;
+})();
diff --git a/test/mjsunit/regress/regress-4815.js b/test/mjsunit/regress/regress-4815.js
new file mode 100644
index 0000000..00e61cb
--- /dev/null
+++ b/test/mjsunit/regress/regress-4815.js
@@ -0,0 +1,38 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var thrower = { [Symbol.toPrimitive]: () => FAIL };
+
+// Tests that a native conversion function is included in the
+// stack trace.
+function testTraceNativeConversion(nativeFunc) {
+  var nativeFuncName = nativeFunc.name;
+  try {
+    nativeFunc(thrower);
+    assertUnreachable(nativeFuncName);
+  } catch (e) {
+    assertTrue(e.stack.indexOf(nativeFuncName) >= 0, nativeFuncName);
+  }
+}
+
+testTraceNativeConversion(Math.max);
+testTraceNativeConversion(Math.min);
+
+function testBuiltinInStackTrace(script, nativeFuncName) {
+  try {
+    eval(script);
+    assertUnreachable(nativeFuncName);
+  } catch (e) {
+    assertTrue(e.stack.indexOf(nativeFuncName) >= 0, nativeFuncName);
+  }
+}
+
+// Use the full name ('String.getDate') in order to avoid false pass
+// results when the method name is mentioned in the error message itself.
+// This occurs, e.g., for Date.prototype.getYear, which uses a different code
+// path and never hits the Generate_DatePrototype_GetField builtin.
+testBuiltinInStackTrace("Date.prototype.getDate.call('')", "String.getDate");
+testBuiltinInStackTrace("Date.prototype.getUTCDate.call('')",
+                        "String.getUTCDate");
+testBuiltinInStackTrace("Date.prototype.getTime.call('')", "String.getTime");
diff --git a/test/mjsunit/regress/regress-4908.js b/test/mjsunit/regress/regress-4908.js
new file mode 100644
index 0000000..ec618b3
--- /dev/null
+++ b/test/mjsunit/regress/regress-4908.js
@@ -0,0 +1,7 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --always-opt --no-lazy
+
+(function() { ((s = 17, y = s) => s)() })();
diff --git a/test/mjsunit/regress/regress-4945.js b/test/mjsunit/regress/regress-4945.js
new file mode 100644
index 0000000..8e595e6
--- /dev/null
+++ b/test/mjsunit/regress/regress-4945.js
@@ -0,0 +1,10 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function* g(o) {
+  yield 'x' in o;
+}
+
+assertTrue(g({x: 1}).next().value);
+assertFalse(g({}).next().value);
diff --git a/test/mjsunit/regress/regress-4964.js b/test/mjsunit/regress/regress-4964.js
new file mode 100644
index 0000000..d834708
--- /dev/null
+++ b/test/mjsunit/regress/regress-4964.js
@@ -0,0 +1,22 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+// Neutered source
+var ab = new ArrayBuffer(10);
+ab.constructor = { get [Symbol.species]() { %ArrayBufferNeuter(ab); return ArrayBuffer; } };
+assertThrows(() => ab.slice(0), TypeError);
+
+// Neutered target
+class NeuteredArrayBuffer extends ArrayBuffer {
+  constructor(...args) {
+    super(...args);
+    %ArrayBufferNeuter(this);
+  }
+}
+
+var ab2 = new ArrayBuffer(10);
+ab2.constructor = NeuteredArrayBuffer;
+assertThrows(() => ab2.slice(0), TypeError);
diff --git a/test/mjsunit/regress/regress-4967.js b/test/mjsunit/regress/regress-4967.js
new file mode 100644
index 0000000..9b36405
--- /dev/null
+++ b/test/mjsunit/regress/regress-4967.js
@@ -0,0 +1,9 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+assertThrows(() => {
+  new class extends Object {
+    constructor() { (() => delete super[super()])(); }
+  }
+}, ReferenceError);
diff --git a/test/mjsunit/regress/regress-4971.js b/test/mjsunit/regress/regress-4971.js
new file mode 100644
index 0000000..041f6c2
--- /dev/null
+++ b/test/mjsunit/regress/regress-4971.js
@@ -0,0 +1,41 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+(function TestDeoptInNamedSuperGetter() {
+  class C { m() { return 23 } }
+  class D extends C { f() { return super.boom() } }
+
+  var should_deoptimize_caller = false;
+  Object.defineProperty(C.prototype, "boom", { get: function() {
+    if (should_deoptimize_caller) %DeoptimizeFunction(D.prototype.f);
+    return this.m
+  }})
+
+  assertEquals(23, new D().f());
+  assertEquals(23, new D().f());
+  %OptimizeFunctionOnNextCall(D.prototype.f);
+  assertEquals(23, new D().f());
+  should_deoptimize_caller = true;
+  assertEquals(23, new D().f());
+})();
+
+(function TestDeoptInKeyedSuperGetter() {
+  class C { m() { return 23 } }
+  class D extends C { f(name) { return super[name]() } }
+
+  var should_deoptimize_caller = false;
+  Object.defineProperty(C.prototype, "boom", { get: function() {
+    if (should_deoptimize_caller) %DeoptimizeFunction(D.prototype.f);
+    return this.m
+  }})
+
+  assertEquals(23, new D().f("boom"));
+  assertEquals(23, new D().f("boom"));
+  %OptimizeFunctionOnNextCall(D.prototype.f);
+  assertEquals(23, new D().f("boom"));
+  should_deoptimize_caller = true;
+  assertEquals(23, new D().f("boom"));
+})();
diff --git a/test/mjsunit/regress/regress-5004.js b/test/mjsunit/regress/regress-5004.js
new file mode 100644
index 0000000..234f5d4
--- /dev/null
+++ b/test/mjsunit/regress/regress-5004.js
@@ -0,0 +1,27 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function assertAsync(b, s) {
+  if (!b) {
+    %AbortJS(" FAILED!")
+  }
+}
+
+class P extends Promise {
+  constructor() {
+    super(...arguments)
+    return new Proxy(this, {
+      get: (_, key) => {
+        return key == 'then' ?
+            this.then.bind(this) :
+            this.constructor.resolve(20)
+      }
+    })
+  }
+}
+
+let p = P.resolve(10)
+p.key.then(v => assertAsync(v === 20));
diff --git a/test/mjsunit/regress/regress-5018.js b/test/mjsunit/regress/regress-5018.js
new file mode 100644
index 0000000..22025dc
--- /dev/null
+++ b/test/mjsunit/regress/regress-5018.js
@@ -0,0 +1,29 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var dv = new DataView(new ArrayBuffer(4), 2);
+
+function getByteLength(a) {
+  return a.byteLength;
+}
+
+assertEquals(2, getByteLength(dv));
+assertEquals(2, getByteLength(dv));
+
+Object.defineProperty(dv.__proto__, 'byteLength', {value: 42});
+
+assertEquals(42, dv.byteLength);
+assertEquals(42, getByteLength(dv));
+
+function getByteOffset(a) {
+  return a.byteOffset;
+}
+
+assertEquals(2, getByteOffset(dv));
+assertEquals(2, getByteOffset(dv));
+
+Object.defineProperty(dv.__proto__, 'byteOffset', {value: 42});
+
+assertEquals(42, dv.byteOffset);
+assertEquals(42, getByteOffset(dv));
diff --git a/test/mjsunit/regress/regress-5033.js b/test/mjsunit/regress/regress-5033.js
new file mode 100644
index 0000000..728094f
--- /dev/null
+++ b/test/mjsunit/regress/regress-5033.js
@@ -0,0 +1,21 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+var test = function() {
+  var t = Date.now();  // Just any non-constant double value.
+  var o = {
+    ['p']: 1,
+    t
+  };
+};
+
+function caller() {
+  test();
+}
+caller();
+caller();
+%OptimizeFunctionOnNextCall(caller);
+caller();
diff --git a/test/mjsunit/regress/regress-5036.js b/test/mjsunit/regress/regress-5036.js
index 036edd9..77bd242 100644
--- a/test/mjsunit/regress/regress-5036.js
+++ b/test/mjsunit/regress/regress-5036.js
@@ -2,6 +2,4 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-unicode-regexps
-
 assertEquals(["1\u212a"], /\d\w/ui.exec("1\u212a"));
diff --git a/test/mjsunit/regress/regress-5071.js b/test/mjsunit/regress/regress-5071.js
new file mode 100644
index 0000000..41c1250
--- /dev/null
+++ b/test/mjsunit/regress/regress-5071.js
@@ -0,0 +1,26 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+var Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  assertEquals(2, exec_state.frameCount());
+  assertEquals("a", exec_state.frame(0).localName(0));
+  assertEquals("1", exec_state.frame(0).localValue(0).value());
+  assertEquals(1, exec_state.frame(0).localCount());
+}
+
+Debug.setListener(listener);
+
+function f() {
+  var a = 1;
+  {
+    let b = 2;
+    debugger;
+  }
+}
+
+f();
diff --git a/test/mjsunit/regress/regress-5085.js b/test/mjsunit/regress/regress-5085.js
new file mode 100644
index 0000000..0ed034d
--- /dev/null
+++ b/test/mjsunit/regress/regress-5085.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function foo(x) {
+  return x instanceof Proxy;
+}
+
+assertFalse(foo({}));
+assertFalse(foo({}));
+%OptimizeFunctionOnNextCall(foo);
+assertFalse(foo({}));
diff --git a/test/mjsunit/regress/regress-5106.js b/test/mjsunit/regress/regress-5106.js
new file mode 100644
index 0000000..52d550a
--- /dev/null
+++ b/test/mjsunit/regress/regress-5106.js
@@ -0,0 +1,29 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function* g1() {
+  try {
+    throw {};
+  } catch ({a = class extends (yield) {}}) {
+  }
+}
+g1().next();  // crashes without fix
+
+function* g2() {
+  let x = function(){};
+  try {
+    throw {};
+  } catch ({b = class extends x {}}) {
+  }
+}
+g2().next();  // crashes without fix
+
+function* g3() {
+  let x = 42;
+  try {
+    throw {};
+  } catch ({c = (function() { return x })()}) {
+  }
+}
+g3().next();  // throws a ReferenceError without fix
diff --git a/test/mjsunit/regress/regress-5174.js b/test/mjsunit/regress/regress-5174.js
new file mode 100644
index 0000000..390d24e
--- /dev/null
+++ b/test/mjsunit/regress/regress-5174.js
@@ -0,0 +1,6 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// // Use of this source code is governed by a BSD-style license that can be
+// // found in the LICENSE file.
+
+assertEquals([], Object.keys(new Proxy([], {})));
+assertEquals([], Object.keys(new Proxy(/regex/, {})));
diff --git a/test/mjsunit/regress/regress-5178.js b/test/mjsunit/regress/regress-5178.js
new file mode 100644
index 0000000..bc0dd11
--- /dev/null
+++ b/test/mjsunit/regress/regress-5178.js
@@ -0,0 +1,7 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+assertThrows(() => {
+  try { throw {} } catch({a=b, b}) { a+b }
+}, ReferenceError);
diff --git a/test/mjsunit/regress/regress-5199.js b/test/mjsunit/regress/regress-5199.js
new file mode 100644
index 0000000..818e71a
--- /dev/null
+++ b/test/mjsunit/regress/regress-5199.js
@@ -0,0 +1,5 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+assertTrue(/(a[\u1000A])+/i.test('aa'));
diff --git a/test/mjsunit/regress/regress-520029.js b/test/mjsunit/regress/regress-520029.js
index 299dd75..9a1d200 100644
--- a/test/mjsunit/regress/regress-520029.js
+++ b/test/mjsunit/regress/regress-520029.js
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-sloppy-let --harmony-sloppy
-
 // Test that hoisting a function out of a lexical scope does not
 // lead to a parsing error
 
diff --git a/test/mjsunit/regress/regress-536751.js b/test/mjsunit/regress/regress-536751.js
index 0707e00..a63fae3 100644
--- a/test/mjsunit/regress/regress-536751.js
+++ b/test/mjsunit/regress/regress-536751.js
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-sloppy --harmony-sloppy-function --harmony-sloppy-let
 // Flags: --no-harmony-restrictive-declarations
 
 // At some point, this code led to DCHECK errors in debug mode
diff --git a/test/mjsunit/regress/regress-542099.js b/test/mjsunit/regress/regress-542099.js
index eef4953..6345fd4 100644
--- a/test/mjsunit/regress/regress-542099.js
+++ b/test/mjsunit/regress/regress-542099.js
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-sloppy --harmony-sloppy-function
 // Flags: --no-harmony-restrictive-declarations
 
 // Previously, this caused a CHECK fail in debug mode
diff --git a/test/mjsunit/regress/regress-542100.js b/test/mjsunit/regress/regress-542100.js
index 70fb5dc..c16e628 100644
--- a/test/mjsunit/regress/regress-542100.js
+++ b/test/mjsunit/regress/regress-542100.js
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-sloppy --harmony-sloppy-function
 // Flags: --no-harmony-restrictive-declarations
 
 (function() {
diff --git a/test/mjsunit/regress/regress-544991.js b/test/mjsunit/regress/regress-544991.js
index 911d8ac..a9fd809 100644
--- a/test/mjsunit/regress/regress-544991.js
+++ b/test/mjsunit/regress/regress-544991.js
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-species
-
 'use strict';
 
 var typedArray = new Int8Array(1);
diff --git a/test/mjsunit/regress/regress-585041.js b/test/mjsunit/regress/regress-585041.js
new file mode 100644
index 0000000..c072ed2
--- /dev/null
+++ b/test/mjsunit/regress/regress-585041.js
@@ -0,0 +1,21 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function f(arr, i) {
+  arr[i] = 50;
+}
+
+function boom(dummy) {
+  var arr = new Array(10);
+  f(arr, 10);
+  if (dummy) {
+    f(arr, -2147483648);
+  }
+}
+
+boom(false);
+%OptimizeFunctionOnNextCall(boom);
+boom(false);
diff --git a/test/mjsunit/regress/regress-592352.js b/test/mjsunit/regress/regress-592352.js
new file mode 100644
index 0000000..f3477c0
--- /dev/null
+++ b/test/mjsunit/regress/regress-592352.js
@@ -0,0 +1,20 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm --allow-natives-syntax
+
+function __f_76() {
+  "use asm";
+  function __f_72() {
+    %OptimizeFunctionOnNextCall();
+  }
+  return {__f_72:__f_72};
+}
+
+try {
+  Wasm.instantiateModuleFromAsm( __f_76.toString());
+  assertTrue(false);
+} catch (e) {
+  print("Caught: " + e);
+}
diff --git a/test/mjsunit/regress/regress-599068-func-bindings.js b/test/mjsunit/regress/regress-599068-func-bindings.js
new file mode 100644
index 0000000..887c000
--- /dev/null
+++ b/test/mjsunit/regress/regress-599068-func-bindings.js
@@ -0,0 +1,45 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+// Tests function bindings are correctly handled in ignition.
+(function f() {
+  function assignSloppy() {
+    f = 0;
+  }
+  assertDoesNotThrow(assignSloppy);
+
+  function assignStrict() {
+    'use strict';
+    f = 0;
+  }
+  assertThrows(assignStrict, TypeError);
+
+  function assignStrictLookup() {
+    eval("'use strict'; f = 1;");
+  }
+  assertThrows(assignStrictLookup, TypeError);
+})();
+
+// Tests for compound assignments which are handled differently
+// in crankshaft.
+(function f() {
+  function assignSloppy() {
+    f += "x";
+  }
+  assertDoesNotThrow(assignSloppy);
+  assertDoesNotThrow(assignSloppy);
+  %OptimizeFunctionOnNextCall(assignSloppy);
+  assertDoesNotThrow(assignSloppy);
+
+  function assignStrict() {
+    'use strict';
+    f += "x";
+  }
+  assertThrows(assignStrict, TypeError);
+  assertThrows(assignStrict, TypeError);
+  %OptimizeFunctionOnNextCall(assignStrict);
+  assertThrows(assignStrict, TypeError);
+})();
diff --git a/test/mjsunit/regress/regress-599717.js b/test/mjsunit/regress/regress-599717.js
new file mode 100644
index 0000000..2cfd7fc
--- /dev/null
+++ b/test/mjsunit/regress/regress-599717.js
@@ -0,0 +1,25 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm
+
+function __f_61(stdlib, buffer) {
+  "use asm";
+  var __v_14 = new stdlib.Float64Array(buffer);
+  function __f_74() {
+    var __v_35 = 6.0;
+    __v_14[2] = __v_35 + 1.0;
+  }
+  return {__f_74: __f_74};
+}
+var ok = false;
+try {
+  var __v_12 = new ArrayBuffer(2147483648);
+  ok = true;
+} catch (e) {
+  // Can happen on 32 bit systems.
+}
+if (ok) {
+  var module = Wasm.instantiateModuleFromAsm( __f_61.toString(), null, __v_12);
+}
diff --git a/test/mjsunit/regress/regress-599719.js b/test/mjsunit/regress/regress-599719.js
new file mode 100644
index 0000000..579fa1f
--- /dev/null
+++ b/test/mjsunit/regress/regress-599719.js
@@ -0,0 +1,24 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --expose-wasm
+
+function __f_7() {
+    %DeoptimizeFunction(__f_5);
+}
+function __f_8(global, env) {
+  "use asm";
+  var __f_7 = env.__f_7;
+  function __f_9(i4, i5) {
+    i4 = i4 | 0;
+    i5 = i5 | 0;
+    __f_7();
+  }
+  return {'__f_9': __f_9}
+}
+function __f_5() {
+  var __v_5 = Wasm.instantiateModuleFromAsm( __f_8.toString(), {'__f_7': __f_7});
+  __v_5.__f_9(0, 0, 0);
+}
+__f_5();
diff --git a/test/mjsunit/regress/regress-605470.js b/test/mjsunit/regress/regress-605470.js
new file mode 100644
index 0000000..722e8ae
--- /dev/null
+++ b/test/mjsunit/regress/regress-605470.js
@@ -0,0 +1,17 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --ignition
+
+function function_with_m_args(m) {
+  var source = '(function f() { return; })(';
+  for (var arg = 0; arg < m ; arg++) {
+    if (arg != 0) source += ',';
+    source += arg;
+  }
+  source += ')';
+  return eval(source);
+}
+
+function_with_m_args(0x7FFF);
diff --git a/test/mjsunit/regress/regress-605488.js b/test/mjsunit/regress/regress-605488.js
new file mode 100644
index 0000000..03e6a38
--- /dev/null
+++ b/test/mjsunit/regress/regress-605488.js
@@ -0,0 +1,12 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags:  --expose-wasm
+
+try {
+  Wasm.instantiateModuleFromAsm("");
+  assertTrue(false);
+} catch (e) {
+  print("Caught: " + e);
+}
diff --git a/test/mjsunit/regress/regress-606021.js b/test/mjsunit/regress/regress-606021.js
new file mode 100644
index 0000000..54b283e
--- /dev/null
+++ b/test/mjsunit/regress/regress-606021.js
@@ -0,0 +1,32 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function foo() {
+  return function(c) {
+    var double_var = [3.0, 3.5][0];
+    var literal = c ? [1, double_var] : [double_var, 3.5];
+    return literal[0];
+  };
+}
+
+var f1 = foo();
+var f2 = foo();
+
+// Both closures point to full code.
+f1(false);
+f2(false);
+
+// Optimize f1, but don't initialize the [1, double_var] literal.
+%OptimizeFunctionOnNextCall(f1);
+f1(false);
+
+// Initialize the [1, double_var] literal, and transition the boilerplate to
+// double.
+f2(true);
+
+// Trick crankshaft into writing double_var at the wrong position.
+var l = f1(true);
+assertEquals(1, l);
diff --git a/test/mjsunit/regress/regress-608630.js b/test/mjsunit/regress/regress-608630.js
new file mode 100644
index 0000000..a0f3c43
--- /dev/null
+++ b/test/mjsunit/regress/regress-608630.js
@@ -0,0 +1,69 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm
+
+var __v_5 = {};
+var __v_35 = {};
+var __v_44 = {};
+var __v_43 = {};
+
+try {
+__v_1 = 1;
+__v_2 = {
+  get: function() { return function() {} },
+  has() { return true },
+  getOwnPropertyDescriptor: function() {
+    if (__v_1-- == 0) throw "please die";
+    return {value: function() {}, configurable: true};
+  }
+};
+__v_3 = new Proxy({}, __v_2);
+__v_30 = Object.create(__v_35);
+with (__v_5) { f() }
+} catch(e) { print("Caught: " + e); }
+
+function __f_1(asmfunc, expect) {
+  var __v_1 = asmfunc.toString();
+  var __v_2 = __v_1.replace(new RegExp("use asm"), "");
+  var __v_39 = {Math: Math};
+  var __v_4 = eval("(" + __v_2 + ")")(__v_3);
+  print("Testing " + asmfunc.name + " (js)...");
+  __v_44.valueOf = __v_43;
+  expect(__v_4);
+  print("Testing " + asmfunc.name + " (asm.js)...");
+  var __v_5 = asmfunc(__v_3);
+  expect(__v_5);
+  print("Testing " + asmfunc.name + " (wasm)...");
+  var __v_6 = Wasm.instantiateModuleFromAsm(__v_1, __v_3);
+  expect(__v_6);
+}
+function __f_2() {
+  "use asm";
+  function __f_3() { return 0; }
+  function __f_4() { return 1; }
+  function __f_5() { return 4; }
+  function __f_6() { return 64; }
+  function __f_7() { return 137; }
+  function __f_8() { return 128; }
+  function __f_9() { return -1; }
+  function __f_10() { return 1000; }
+  function __f_11() { return 2000000; }
+  function __f_12() { return 2147483647; }
+  return {__f_3: __f_3, __f_4: __f_4, __f_5: __f_5, __f_6: __f_6, __f_7: __f_7, __f_8: __f_8,
+          __f_9: __f_9, __f_10: __f_10, __f_11, __f_12: __f_12};
+}
+try {
+__f_1(__f_2, function(module) {
+  assertEquals(0, module.__f_3());
+  assertEquals(1, module.__f_4());
+  assertEquals(4, module.__f_5());
+  assertEquals(64, module.__f_6());
+  assertEquals(128, module.__f_8());
+  assertEquals(-1, module.__f_9());
+  assertEquals(1000, module.__f_10());
+  assertEquals(2000000, module.__f_11());
+  assertEquals(2147483647, module.__f_12());
+});
+} catch(e) { print("Caught: " + e); }
diff --git a/test/mjsunit/regress/regress-610633.js b/test/mjsunit/regress/regress-610633.js
new file mode 100644
index 0000000..8ee0e7e
--- /dev/null
+++ b/test/mjsunit/regress/regress-610633.js
@@ -0,0 +1,40 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function getLength(a) {
+  return a.length;
+}
+
+function getByteLength(a) {
+  return a.byteLength;
+}
+
+function getByteOffset(a) {
+  return a.byteOffset;
+}
+
+var a = new Uint8Array([1, 2, 3]);
+getLength(a);
+getLength(a);
+
+Object.defineProperty(a.__proto__, 'length', {value: 42});
+
+assertEquals(42, getLength(a));
+assertEquals(42, a.length);
+
+getByteLength(a);
+getByteLength(a);
+
+Object.defineProperty(a.__proto__, 'byteLength', {value: 42});
+
+assertEquals(42, getByteLength(a));
+assertEquals(42, a.byteLength);
+
+getByteOffset(a);
+getByteOffset(a);
+
+Object.defineProperty(a.__proto__, 'byteOffset', {value: 42});
+
+assertEquals(42, getByteOffset(a));
+assertEquals(42, a.byteOffset);
diff --git a/test/mjsunit/regress/regress-612146.js b/test/mjsunit/regress/regress-612146.js
new file mode 100644
index 0000000..1bd3f0b
--- /dev/null
+++ b/test/mjsunit/regress/regress-612146.js
@@ -0,0 +1,33 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function f() {
+  var arguments_ = arguments;
+  if (undefined) {
+    while (true) {
+      arguments_[0];
+    }
+  } else {
+    %DeoptimizeNow();
+    return arguments_[0];
+  }
+};
+
+f(0);
+f(0);
+%OptimizeFunctionOnNextCall(f);
+assertEquals(1, f(1));
+
+function g() {
+    var a = arguments;
+    %DeoptimizeNow();
+    return a.length;
+}
+
+g(1);
+g(1);
+%OptimizeFunctionOnNextCall(g);
+assertEquals(1, g(1));
diff --git a/test/mjsunit/regress/regress-612412.js b/test/mjsunit/regress/regress-612412.js
new file mode 100644
index 0000000..3debe66
--- /dev/null
+++ b/test/mjsunit/regress/regress-612412.js
@@ -0,0 +1,20 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function counter() { return {x: 0} || this }
+
+var f = (function() {
+  "use asm";
+  return function g(c1, c2) {
+    for (var x = 0 ; x < 10; ++x) {
+      if (x == 5) %OptimizeOsr();
+      c1();
+    }
+  }
+})();
+
+g = (function() { f((Array), counter()); });
+g();
diff --git a/test/mjsunit/regress/regress-615776.js b/test/mjsunit/regress/regress-615776.js
new file mode 100644
index 0000000..7e89b56
--- /dev/null
+++ b/test/mjsunit/regress/regress-615776.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Object.defineProperty(Int32Array.prototype.__proto__, 'length', {
+  get: function() { throw new Error('Custom length property'); }
+});
+
+var a = Math.random();
+
+// This tests MathRandomRaw.
+var v0 = new Set();
+var v1 = new Object();
+v0.add(v1);
diff --git a/test/mjsunit/regress/regress-616386.js b/test/mjsunit/regress/regress-616386.js
new file mode 100644
index 0000000..d462ab7
--- /dev/null
+++ b/test/mjsunit/regress/regress-616386.js
@@ -0,0 +1,10 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --no-lazy
+
+assertEquals(0, ((y = (function(a2) { bbbb = a2 }), bbbb = eval('1')) => {y(0); return bbbb})())
+assertEquals(0, (({y = (function(a2) { bbbb = a2 }), bbbb = eval('1')} = {}) => {y(0); return bbbb})())
+assertEquals(0, (function (y = (function(a2) { bbbb = a2 }), bbbb = eval('1')) {y(0); return bbbb})())
+assertEquals(0, (function ({y = (function(a2) { bbbb = a2 }), bbbb = eval('1')} = {}) {y(0); return bbbb})())
diff --git a/test/mjsunit/regress/regress-617525.js b/test/mjsunit/regress/regress-617525.js
new file mode 100644
index 0000000..bb77e06
--- /dev/null
+++ b/test/mjsunit/regress/regress-617525.js
@@ -0,0 +1,11 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function __f_14() {
+  "use asm";
+  function __f_15() { return 0; }
+  function __f_15() { return 137; }  // redeclared function
+  return {};
+}
+assertThrows(function() { Wasm.instantiateModuleFromAsm(__f_14.toString()) });
diff --git a/test/mjsunit/regress/regress-617529.js b/test/mjsunit/regress/regress-617529.js
new file mode 100644
index 0000000..415e6c7
--- /dev/null
+++ b/test/mjsunit/regress/regress-617529.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function __f_71(stdlib, buffer) {
+  "use asm";
+  var __v_22 = new stdlib.Float64Array(buffer);
+  function __f_26() {
+    __v_22 = __v_22;
+  }
+  return {__f_26: __f_26};
+}
+
+assertThrows(function() { Wasm.instantiateModuleFromAsm( __f_71.toString()); });
diff --git a/test/mjsunit/regress/regress-618657.js b/test/mjsunit/regress/regress-618657.js
new file mode 100644
index 0000000..2882cff
--- /dev/null
+++ b/test/mjsunit/regress/regress-618657.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --ignition --ignition-generators --ignition-filter=-foo
+
+function* foo() { yield 42 }
+function* goo() { yield 42 }
+var f = foo();
+var g = goo();
+assertEquals(42, f.next().value);
+assertEquals(42, g.next().value);
+assertEquals(true, f.next().done);
+assertEquals(true, g.next().done);
diff --git a/test/mjsunit/regress/regress-619382.js b/test/mjsunit/regress/regress-619382.js
new file mode 100644
index 0000000..971318a
--- /dev/null
+++ b/test/mjsunit/regress/regress-619382.js
@@ -0,0 +1,35 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// // Use of this source code is governed by a BSD-style license that can be
+// // found in the LICENSE file.
+//
+// // Flags: --expose-gc --always-opt
+
+(function __f_9() {
+})();
+function __f_16(ctor_desc) {
+  var __v_22 = 5;
+  var __v_25 = [];
+  gc(); gc(); gc();
+  for (var __v_18 = 0; __v_18 < __v_22; __v_18++) {
+    __v_25[__v_18] = ctor_desc.ctor.apply();
+  }
+}
+var __v_28 = [
+  {
+    ctor: function(__v_27) { return {a: __v_27}; },
+    args: function() { return [1.5 + __v_18]; }  },
+  {
+    ctor: function(__v_27) { var __v_21 = []; __v_21[1] = __v_27; __v_21[200000] = __v_27; return __v_21; },
+    args: function() { return [1.5 + __v_18]; }  },
+  {
+    ctor: function() {
+    }  }
+];
+var __v_26 = [
+  {
+  }];
+  __v_26.forEach(function(__v_16) {
+    __v_28.forEach(function(ctor) {
+      __f_16(ctor);
+    });
+  });
diff --git a/test/mjsunit/regress/regress-620553.js b/test/mjsunit/regress/regress-620553.js
new file mode 100644
index 0000000..461b9bb
--- /dev/null
+++ b/test/mjsunit/regress/regress-620553.js
@@ -0,0 +1,17 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-gc
+
+var o0 = [];
+var o1 = [];
+var cnt = 0;
+o1.__defineGetter__(0, function() {
+  if (cnt++ > 2) return;
+  o0.shift();
+  gc();
+  o0.push(0);
+  o0.concat(o1);
+});
+o1[0];
diff --git a/test/mjsunit/regress/regress-620750.js b/test/mjsunit/regress/regress-620750.js
new file mode 100644
index 0000000..ab8fbd9
--- /dev/null
+++ b/test/mjsunit/regress/regress-620750.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --es-staging
+
+function push_a_lot(arr) {
+  for (var i = 0; i < 2e4; i++) {
+    arr.push(i);
+  }
+  return arr;
+}
+
+__v_13 = push_a_lot([]);
diff --git a/test/mjsunit/regress/regress-621869.js b/test/mjsunit/regress/regress-621869.js
new file mode 100644
index 0000000..db34064
--- /dev/null
+++ b/test/mjsunit/regress/regress-621869.js
@@ -0,0 +1,18 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-gc
+
+var o0 = [];
+var o1 = [];
+var cnt = 0;
+var only_scavenge = true;
+o1.__defineGetter__(0, function() {
+  if (cnt++ > 2) return;
+  o0.shift();
+  gc(only_scavenge);
+  o0.push((64));
+  o0.concat(o1);
+});
+o1[0];
diff --git a/test/mjsunit/regress/regress-622663.js b/test/mjsunit/regress/regress-622663.js
new file mode 100644
index 0000000..9606bd8
--- /dev/null
+++ b/test/mjsunit/regress/regress-622663.js
@@ -0,0 +1,14 @@
++// Copyright 2016 the V8 project authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++// Flags: --no-lazy
+
+(function() {
+  try { (y = [...[]]) => {} } catch(_) {}  // will core dump, if not fixed
+})();
+
+(function() {
+  try { ((y = [...[]]) => {})(); } catch(_) {}  // will core dump, if not fixed,
+                                                // even without --no-lazy
+})();
diff --git a/test/mjsunit/regress/regress-674753.js b/test/mjsunit/regress/regress-674753.js
index b3704ea..d8a504a 100644
--- a/test/mjsunit/regress/regress-674753.js
+++ b/test/mjsunit/regress/regress-674753.js
@@ -25,62 +25,138 @@
 // (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 undetectable = %GetUndetectable();
+
 // Number
 assertTrue(typeof 0 == 'number');
 assertTrue(typeof 0 === 'number');
+assertFalse(typeof 0 != 'number');
+assertFalse(typeof 0 !== 'number');
 assertTrue(typeof 1.2 == 'number');
 assertTrue(typeof 1.2 === 'number');
+assertFalse(typeof 1.2 != 'number');
+assertFalse(typeof 1.2 !== 'number');
+assertTrue(typeof 'x' != 'number');
+assertTrue(typeof 'x' !== 'number');
 assertFalse(typeof 'x' == 'number');
 assertFalse(typeof 'x' === 'number');
+assertTrue(typeof Object() != 'number');
+assertTrue(typeof Object() !== 'number');
+assertFalse(typeof Object() == 'number');
+assertFalse(typeof Object() === 'number');
 
 // String
 assertTrue(typeof 'x' == 'string');
 assertTrue(typeof 'x' === 'string');
+assertFalse(typeof 'x' != 'string');
+assertFalse(typeof 'x' !== 'string');
 assertTrue(typeof ('x' + 'x') == 'string');
 assertTrue(typeof ('x' + 'x') === 'string');
+assertFalse(typeof ('x' + 'x') != 'string');
+assertFalse(typeof ('x' + 'x') !== 'string');
+assertTrue(typeof 1 != 'string');
+assertTrue(typeof 1 !== 'string');
 assertFalse(typeof 1 == 'string');
 assertFalse(typeof 1 === 'string');
+assertTrue(typeof Object() != 'string');
+assertTrue(typeof Object() !== 'string');
 assertFalse(typeof Object() == 'string');
 assertFalse(typeof Object() === 'string');
 
 // Boolean
 assertTrue(typeof true == 'boolean');
 assertTrue(typeof true === 'boolean');
+assertFalse(typeof true != 'boolean');
+assertFalse(typeof true !== 'boolean');
 assertTrue(typeof false == 'boolean');
 assertTrue(typeof false === 'boolean');
+assertFalse(typeof false != 'boolean');
+assertFalse(typeof false !== 'boolean');
+assertTrue(typeof 1 != 'boolean');
+assertTrue(typeof 1 !== 'boolean');
 assertFalse(typeof 1 == 'boolean');
 assertFalse(typeof 1 === 'boolean');
+assertTrue(typeof 'x' != 'boolean');
+assertTrue(typeof 'x' !== 'boolean');
+assertFalse(typeof 'x' == 'boolean');
+assertFalse(typeof 'x' === 'boolean');
+assertTrue(typeof Object() != 'boolean');
+assertTrue(typeof Object() !== 'boolean');
 assertFalse(typeof Object() == 'boolean');
 assertFalse(typeof Object() === 'boolean');
 
 // Undefined
 assertTrue(typeof void 0 == 'undefined');
 assertTrue(typeof void 0 === 'undefined');
+assertFalse(typeof void 0 != 'undefined');
+assertFalse(typeof void 0 !== 'undefined');
+assertTrue(typeof 1 != 'undefined');
+assertTrue(typeof 1 !== 'undefined');
 assertFalse(typeof 1 == 'undefined');
 assertFalse(typeof 1 === 'undefined');
+assertTrue(typeof null != 'undefined');
+assertTrue(typeof null !== 'undefined');
+assertFalse(typeof null == 'undefined');
+assertFalse(typeof null === 'undefined');
+assertTrue(typeof Object() != 'undefined');
+assertTrue(typeof Object() !== 'undefined');
 assertFalse(typeof Object() == 'undefined');
 assertFalse(typeof Object() === 'undefined');
+assertTrue(typeof undetectable == 'undefined');
+assertTrue(typeof undetectable === 'undefined');
+assertFalse(typeof undetectable != 'undefined');
+assertFalse(typeof undetectable !== 'undefined');
 
 // Function
 assertTrue(typeof Object == 'function');
 assertTrue(typeof Object === 'function');
+assertFalse(typeof Object != 'function');
+assertFalse(typeof Object !== 'function');
+assertTrue(typeof 1 != 'function');
+assertTrue(typeof 1 !== 'function');
 assertFalse(typeof 1 == 'function');
 assertFalse(typeof 1 === 'function');
+assertTrue(typeof Object() != 'function');
+assertTrue(typeof Object() !== 'function');
 assertFalse(typeof Object() == 'function');
 assertFalse(typeof Object() === 'function');
+assertTrue(typeof undetectable != 'function');
+assertTrue(typeof undetectable !== 'function');
+assertFalse(typeof undetectable == 'function');
+assertFalse(typeof undetectable === 'function');
 
 // Object
 assertTrue(typeof Object() == 'object');
 assertTrue(typeof Object() === 'object');
+assertFalse(typeof Object() != 'object');
+assertFalse(typeof Object() !== 'object');
 assertTrue(typeof new String('x') == 'object');
 assertTrue(typeof new String('x') === 'object');
+assertFalse(typeof new String('x') != 'object');
+assertFalse(typeof new String('x') !== 'object');
 assertTrue(typeof ['x'] == 'object');
 assertTrue(typeof ['x'] === 'object');
+assertFalse(typeof ['x'] != 'object');
+assertFalse(typeof ['x'] !== 'object');
 assertTrue(typeof null == 'object');
 assertTrue(typeof null === 'object');
+assertFalse(typeof null != 'object');
+assertFalse(typeof null !== 'object');
+assertTrue(typeof 1 != 'object');
+assertTrue(typeof 1 !== 'object');
 assertFalse(typeof 1 == 'object');
 assertFalse(typeof 1 === 'object');
+assertTrue(typeof 'x' != 'object');
+assertTrue(typeof 'x' !== 'object');
 assertFalse(typeof 'x' == 'object');  // bug #674753
 assertFalse(typeof 'x' === 'object');
+assertTrue(typeof Object != 'object');
+assertTrue(typeof Object !== 'object');
 assertFalse(typeof Object == 'object');
 assertFalse(typeof Object === 'object');
+assertTrue(typeof undetectable != 'object');
+assertTrue(typeof undetectable !== 'object');
+assertFalse(typeof undetectable == 'object');
+assertFalse(typeof undetectable === 'object');
diff --git a/test/mjsunit/regress/regress-crbug-119800.js b/test/mjsunit/regress/regress-crbug-119800.js
index 3946fbb..85f28a7 100644
--- a/test/mjsunit/regress/regress-crbug-119800.js
+++ b/test/mjsunit/regress/regress-crbug-119800.js
@@ -5,9 +5,9 @@
 // Flags: --expose-debug-as debug
 
 function f() {
-  1;
-  2;
-  3;
+  print(1);
+  print(2);
+  print(3);
 }
 
 var Debug = debug.Debug;
@@ -34,4 +34,5 @@
 Debug.debuggerFlags().breakPointsActive.setValue(true);
 
 assertNull(exception);
-assertEquals(breaks, ["1;", "2;", "3;", "}", "Debug.setListener(null);"]);
+assertEquals(breaks, ["print(1);", "print(2);", "print(3);", "}",
+                      "Debug.setListener(null);"]);
diff --git a/test/mjsunit/regress/regress-crbug-320922.js b/test/mjsunit/regress/regress-crbug-320922.js
deleted file mode 100644
index f199628..0000000
--- a/test/mjsunit/regress/regress-crbug-320922.js
+++ /dev/null
@@ -1,50 +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.
-
-// Flags: --allow-natives-syntax
-
-var string = "internalized dummy";
-var expected = "internalized dummy";
-string = "hello world";
-expected = "Hello " + "world";
-function Capitalize() {
-  %_OneByteSeqStringSetChar(0, 0x48, string);
-}
-Capitalize();
-assertEquals(expected, string);
-Capitalize();
-assertEquals(expected, string);
-
-var twobyte = "\u20ACello world";
-
-function TwoByteCapitalize() {
-  %_TwoByteSeqStringSetChar(0, 0x48, twobyte);
-}
-TwoByteCapitalize();
-assertEquals(expected, twobyte);
-TwoByteCapitalize();
-assertEquals(expected, twobyte);
diff --git a/test/mjsunit/regress/regress-crbug-451770.js b/test/mjsunit/regress/regress-crbug-451770.js
index 770c807..b4f088d 100644
--- a/test/mjsunit/regress/regress-crbug-451770.js
+++ b/test/mjsunit/regress/regress-crbug-451770.js
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --harmony-sloppy
-
 assertThrows(function f() {
   var t = { toString: function() { throw new Error(); } };
   var o = { [t]: 23 };
diff --git a/test/mjsunit/regress/regress-crbug-480807.js b/test/mjsunit/regress/regress-crbug-480807.js
index c273f20..a1448d6 100644
--- a/test/mjsunit/regress/regress-crbug-480807.js
+++ b/test/mjsunit/regress/regress-crbug-480807.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Flags: --allow-natives-syntax --use-osr --turbo-osr --noalways-opt
+// Flags: --allow-natives-syntax --use-osr --noalways-opt
 
 function foo() {
   var c = 0;
diff --git a/test/mjsunit/regress/regress-crbug-495493.js b/test/mjsunit/regress/regress-crbug-495493.js
new file mode 100644
index 0000000..3dba236
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-495493.js
@@ -0,0 +1,12 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --nofold-constants --enable-slow-asserts --debug-code
+
+function foo(p) {
+  for (var i = 0; i < 100000; ++i) {
+    p = Math.min(-1, 0);
+  }
+}
+foo(0);
diff --git a/test/mjsunit/regress/regress-crbug-498142.js b/test/mjsunit/regress/regress-crbug-498142.js
deleted file mode 100644
index fcec5d1..0000000
--- a/test/mjsunit/regress/regress-crbug-498142.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --allow-natives-syntax --harmony-sharedarraybuffer
-
-var sab = new SharedArrayBuffer(16);
-assertThrows(function() { %ArrayBufferNeuter(sab); });
diff --git a/test/mjsunit/regress/regress-crbug-582048.js b/test/mjsunit/regress/regress-crbug-582048.js
new file mode 100644
index 0000000..6d98f48
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-582048.js
@@ -0,0 +1,31 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+var Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var frame_count = exec_state.frameCount();
+    for (var i = 0; i < frame_count; i++) {
+      var frame = exec_state.frame(i);
+      var scope_count = frame.scopeCount();
+      for (var j = 0; j < scope_count; j++) {
+        var scope = frame.scope(j);
+        assertTrue(scope.scopeObject().property('').isUndefined());
+      }
+    }
+  } catch (e) {
+    print(e, e.stack);
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+(function(a = 1) { debugger; })();
+
+Debug.setListener(null);
diff --git a/test/mjsunit/regress/regress-crbug-600257.js b/test/mjsunit/regress/regress-crbug-600257.js
new file mode 100644
index 0000000..87bd2e3
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-600257.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --stack-size=100
+
+(function rec() {
+  try {
+    rec();
+  } catch (e) {
+    /{/;
+  }
+})();
diff --git a/test/mjsunit/regress/regress-crbug-600995.js b/test/mjsunit/regress/regress-crbug-600995.js
deleted file mode 100644
index c532608..0000000
--- a/test/mjsunit/regress/regress-crbug-600995.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --noharmony-iterator-close
-
-// The {Set} function will produce a different type feedback vector layout
-// depending on whether Harmony iterator finalization is enabled or not.
-
-new Set();
diff --git a/test/mjsunit/regress/regress-crbug-602184.js b/test/mjsunit/regress/regress-crbug-602184.js
new file mode 100644
index 0000000..c7d793b
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-602184.js
@@ -0,0 +1,17 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function f(test, a) {
+  var v;
+  if (test) {
+    v = v|0;
+  }
+  a[v] = 1;
+}
+var v = new String();
+f(false, v);
+f(false, v);
+
+v = new Int32Array(10);
+f(true, v);
diff --git a/test/mjsunit/regress/regress-crbug-602595.js b/test/mjsunit/regress/regress-crbug-602595.js
new file mode 100644
index 0000000..7f6d478
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-602595.js
@@ -0,0 +1,12 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --turbo-escape
+
+function f(a) { return [a] }
+
+assertEquals([23], f(23));
+assertEquals([42], f(42));
+%OptimizeFunctionOnNextCall(f);
+assertEquals([65], f(65));
diff --git a/test/mjsunit/regress/regress-crbug-603463.js b/test/mjsunit/regress/regress-crbug-603463.js
new file mode 100644
index 0000000..20bfae6
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-603463.js
@@ -0,0 +1,16 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function load(a, i) {
+  return a[i];
+}
+
+function f() {
+  return load(new Proxy({}, {}), undefined);
+}
+
+f();
+f();
+load([11, 22, 33], 0);
+f();
diff --git a/test/mjsunit/regress/regress-crbug-604299.js b/test/mjsunit/regress/regress-crbug-604299.js
new file mode 100644
index 0000000..9908f2d
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-604299.js
@@ -0,0 +1,9 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Array.prototype.__defineSetter__(0,function(value){});
+
+if (this.Intl) {
+  var o = new Intl.DateTimeFormat('en-US', {'timeZone': 'Asia/Katmandu'})
+}
diff --git a/test/mjsunit/regress/regress-crbug-605060.js b/test/mjsunit/regress/regress-crbug-605060.js
new file mode 100644
index 0000000..d2dc79a
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-605060.js
@@ -0,0 +1,10 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+Array.prototype.__defineGetter__('map', function(){});
+Array.prototype.__defineGetter__('map', function(){});
+Array.prototype.__defineGetter__('map', function(){});
+assertTrue(%HasFastProperties(Array.prototype));
diff --git a/test/mjsunit/regress/regress-crbug-605581.js b/test/mjsunit/regress/regress-crbug-605581.js
new file mode 100644
index 0000000..0f1daab
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-605581.js
@@ -0,0 +1,28 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+var Debug = debug.Debug;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    assertThrows(() => exec_state.frame(0).evaluate("bar.baz"), ReferenceError);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+(function() {
+  debugger;    // bar is still in TDZ at this point.
+  let bar = 1;
+  (x => bar);  // force bar to be context-allocated.
+})();
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/test/mjsunit/regress/regress-crbug-605862.js b/test/mjsunit/regress/regress-crbug-605862.js
new file mode 100644
index 0000000..82a5d45
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-605862.js
@@ -0,0 +1,6 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/[]*1/u.exec("\u1234");
+/[^\u0000-\u{10ffff}]*1/u.exec("\u1234");
diff --git a/test/mjsunit/regress/regress-crbug-608279.js b/test/mjsunit/regress/regress-crbug-608279.js
new file mode 100644
index 0000000..22c69f2
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-608279.js
@@ -0,0 +1,18 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --always-opt --no-lazy
+
+function __f_38() {
+  try {
+    throw 0;
+  } catch (e) {
+    eval();
+    var __v_38 = { a: 'hest' };
+    __v_38.m = function () { return __v_38.a; };
+  }
+  return __v_38;
+}
+var __v_40 = __f_38();
+__v_40.m();
diff --git a/test/mjsunit/regress/regress-crbug-609029.js b/test/mjsunit/regress/regress-crbug-609029.js
new file mode 100644
index 0000000..bd77de2
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-609029.js
@@ -0,0 +1,7 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --always-opt --function-context-specialization --gc-interval=14
+// Flags: --turbo-filter=match --verify-heap
+"xxx".match();
diff --git a/test/mjsunit/regress/regress-crbug-609046.js b/test/mjsunit/regress/regress-crbug-609046.js
new file mode 100644
index 0000000..10b63af
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-609046.js
@@ -0,0 +1,36 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+// Test that hidden scopes are correctly walked in the scope chain.
+
+var Debug = debug.Debug;
+var exception = null;
+var delegate = null;
+var done = false;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    assertEquals([ debug.ScopeType.Block,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global ],
+                 exec_state.frame(0).allScopes().map(s => s.scopeType()));
+    done = true;
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+for(let a = 0; a < 3; a++) {
+  debugger;
+  eval();  // Force context-allocation of everything.
+}
+
+Debug.setListener(null);
+assertNull(exception);
+assertTrue(done);
diff --git a/test/mjsunit/regress/regress-crbug-610207.js b/test/mjsunit/regress/regress-crbug-610207.js
new file mode 100644
index 0000000..4396a56
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-610207.js
@@ -0,0 +1,13 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Error.prepareStackTrace = function(exception, frames) {
+  return frames[0].getEvalOrigin();
+}
+
+try {
+  Realm.eval(0, "throw new Error('boom');");
+} catch(e) {
+  print(e.stack);
+}
diff --git a/test/mjsunit/regress/regress-crbug-610228.js b/test/mjsunit/regress/regress-crbug-610228.js
deleted file mode 100644
index ca077d5..0000000
--- a/test/mjsunit/regress/regress-crbug-610228.js
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --allow-natives-syntax
-
-function foo() { return JSON.stringify({a: 0.1}); }
-assertEquals('{"a":0.1}', foo());
-assertEquals('{"a":0.1}', foo());
-%OptimizeFunctionOnNextCall(foo);
-assertEquals('{"a":0.1}', foo());
diff --git a/test/mjsunit/regress/regress-crbug-612109.js b/test/mjsunit/regress/regress-crbug-612109.js
new file mode 100644
index 0000000..202bd96
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-612109.js
@@ -0,0 +1,8 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+s = "string for triggering osr in __f_0";
+for (var i = 0; i < 16; i++) s = s + s;
+decodeURI(encodeURI(s));
diff --git a/test/mjsunit/regress/regress-crbug-612142.js b/test/mjsunit/regress/regress-crbug-612142.js
new file mode 100644
index 0000000..de2dc8d
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-612142.js
@@ -0,0 +1,10 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var thrower = {[Symbol.toPrimitive]: function(e) { throw e }};
+try {
+  for (var i = 0; i < 10; i++) { }
+  for (var i = 0.5; i < 100000; ++i) { }
+  for (var i = 16 | 0 || 0 || this || 1; i;) { String.fromCharCode(thrower); }
+} catch (e) { }
diff --git a/test/mjsunit/regress/regress-crbug-613494.js b/test/mjsunit/regress/regress-crbug-613494.js
new file mode 100644
index 0000000..6fcc1e9
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-613494.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --turbo-escape --noanalyze-environment-liveness
+
+function f() {
+  var bound = 0;
+  function g() { return bound }
+}
+f();
+f();
+%OptimizeFunctionOnNextCall(f);
+f();
diff --git a/test/mjsunit/regress/regress-crbug-613570.js b/test/mjsunit/regress/regress-crbug-613570.js
new file mode 100644
index 0000000..3cd9857
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-613570.js
@@ -0,0 +1,6 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+assertEquals("[\n\u26031,\n\u26032\n]",
+             JSON.stringify([1, 2], null, "\u2603"));
diff --git a/test/mjsunit/regress/regress-crbug-613905.js b/test/mjsunit/regress/regress-crbug-613905.js
new file mode 100644
index 0000000..8bb38c9
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-613905.js
@@ -0,0 +1,11 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Error.prepareStackTrace = (e,s) => s;
+var CallSiteConstructor = Error().stack[0].constructor;
+
+try {
+  (new CallSiteConstructor(3, 6)).toString();
+} catch (e) {
+}
diff --git a/test/mjsunit/regress/regress-crbug-613919.js b/test/mjsunit/regress/regress-crbug-613919.js
new file mode 100644
index 0000000..cbd3e43
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-613919.js
@@ -0,0 +1,18 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --turbo-escape
+
+function g(a) {
+  if (a) return arguments;
+  %DeoptimizeNow();
+  return 23;
+}
+function f() {
+  return g(false);
+}
+assertEquals(23, f());
+assertEquals(23, f());
+%OptimizeFunctionOnNextCall(f);
+assertEquals(23, f());
diff --git a/test/mjsunit/regress/regress-crbug-614292.js b/test/mjsunit/regress/regress-crbug-614292.js
new file mode 100644
index 0000000..3a67c17
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-614292.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function foo() {
+  return [] | 0 && values[0] || false;
+}
+
+%OptimizeFunctionOnNextCall(foo);
+try {
+  foo();
+} catch (e) {}
diff --git a/test/mjsunit/regress/regress-crbug-614727.js b/test/mjsunit/regress/regress-crbug-614727.js
new file mode 100644
index 0000000..0845afc
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-614727.js
@@ -0,0 +1,23 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+"use strict";
+
+function f(a, b, c) { return arguments }
+function g(...args) { return args }
+
+// On 64-bit machine this produces a 768K array which is sufficiently small to
+// not cause a stack overflow, but big enough to move the allocated arguments
+// object into large object space (kMaxRegularHeapObjectSize == 600K).
+var length = Math.pow(2, 15) * 3;
+var args = new Array(length);
+assertEquals(length, f.apply(null, args).length);
+assertEquals(length, g.apply(null, args).length);
+
+// On 32-bit machines this produces an equally sized array, however it might in
+// turn trigger a stack overflow on 64-bit machines, which we need to catch.
+var length = Math.pow(2, 16) * 3;
+var args = new Array(length);
+try { f.apply(null, args) } catch(e) {}
+try { g.apply(null, args) } catch(e) {}
diff --git a/test/mjsunit/regress/regress-crbug-615774.js b/test/mjsunit/regress/regress-crbug-615774.js
new file mode 100644
index 0000000..ea5e675
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-615774.js
@@ -0,0 +1,11 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Error.prepareStackTrace = (e,s) => s;
+var CallSiteConstructor = Error().stack[0].constructor;
+
+try {
+  (new CallSiteConstructor(CallSiteConstructor, 6)).toString();
+} catch (e) {
+}
diff --git a/test/mjsunit/regress/regress-crbug-617524.js b/test/mjsunit/regress/regress-crbug-617524.js
new file mode 100644
index 0000000..b32eeef
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-617524.js
@@ -0,0 +1,18 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-gc --always-opt
+
+function f(a,b,c) {
+  a.a = b;
+  a[1] = c;
+  return a;
+}
+
+f(new Array(5),.5,0);
+var o1 = f(new Array(5),0,.5);
+gc();
+var o2 = f(new Array(5),0,0);
+var o3 = f(new Array(5),0);
+assertEquals(0, o3.a);
diff --git a/test/mjsunit/regress/regress-crbug-617527.js b/test/mjsunit/regress/regress-crbug-617527.js
new file mode 100644
index 0000000..cf46628
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-617527.js
@@ -0,0 +1,8 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --enable-slow-asserts
+
+Object.defineProperty(Array.prototype, "1", { get: toLocaleString });
+assertThrows(_ => new RegExp(0, 0));
diff --git a/test/mjsunit/regress/regress-crbug-617567.js b/test/mjsunit/regress/regress-crbug-617567.js
new file mode 100644
index 0000000..f0c696e
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-617567.js
@@ -0,0 +1,24 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --turbo-filter=* --allow-natives-syntax
+
+var v1 = {};
+function g() {
+  v1 = [];
+  for (var i = 0; i < 1; i++) {
+    v1[i]();
+  }
+}
+
+var v2 = {};
+var v3 = {};
+function f() {
+  v3 = v2;
+  g();
+}
+
+assertThrows(g);
+%OptimizeFunctionOnNextCall(f);
+assertThrows(f);
diff --git a/test/mjsunit/regress/regress-crbug-618788.js b/test/mjsunit/regress/regress-crbug-618788.js
new file mode 100644
index 0000000..a104d8d
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-618788.js
@@ -0,0 +1,21 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Slice and splice both try to set the length property of their return
+// value. Add a bogus setter to allow that.
+Object.defineProperty(Int32Array.prototype, 'length', { set(v) { } });
+
+(function testSlice() {
+  var a = new Array();
+  a.constructor = Int32Array;
+  a.length = 1000; // Make the length >= 1000 so UseSparseVariant returns true.
+  assertTrue(a.slice() instanceof Int32Array);
+})();
+
+(function testSplice() {
+  var a = new Array();
+  a.constructor = Int32Array;
+  a.length = 1000; // Make the length >= 1000 so UseSparseVariant returns true.
+  assertTrue(a.splice(1) instanceof Int32Array);
+})();
diff --git a/test/mjsunit/regress/regress-crbug-618845.js b/test/mjsunit/regress/regress-crbug-618845.js
new file mode 100644
index 0000000..ea3baba
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-618845.js
@@ -0,0 +1,16 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function Foo() {}
+Object.defineProperty(Foo.prototype, "name",
+                      {get: function() { return "FooName"; }});
+
+function ic(f) {
+  return f.prototype.name;
+}
+
+assertEquals("FooName", ic(Foo));
+assertEquals("FooName", ic(Foo));  // Don't crash, don't time out.
diff --git a/test/mjsunit/regress/regress-crbug-620119.js b/test/mjsunit/regress/regress-crbug-620119.js
new file mode 100644
index 0000000..cbe5a78
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-620119.js
@@ -0,0 +1,8 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --no-lazy
+
+assertEquals(0, ((x, {[(x = function() { y = 0 }, "foo")]: y = eval(1)}) => { x(); return y })(42, {}));
+assertEquals(0, (function (x, {[(x = function() { y = 0 }, "foo")]: y = eval(1)}) { x(); return y })(42, {}));
diff --git a/test/mjsunit/regress/regress-crbug-620253.js b/test/mjsunit/regress/regress-crbug-620253.js
new file mode 100644
index 0000000..811a4e7
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-620253.js
@@ -0,0 +1,7 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --throws
+
+load("test/mjsunit/regress/regress-crbug-620253.js");
diff --git a/test/mjsunit/regress/regress-crbug-620650.js b/test/mjsunit/regress/regress-crbug-620650.js
new file mode 100644
index 0000000..25a92ca
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-620650.js
@@ -0,0 +1,16 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function() {
+  function f(src, dst, i) {
+    dst[i] = src[i];
+  }
+  var buf = new ArrayBuffer(16);
+  var view_int32 = new Int32Array(buf);
+  view_int32[1] = 0xFFF7FFFF;
+  var view_f64 = new Float64Array(buf);
+  var arr = [,0.1];
+  f(view_f64, arr, -1);
+  f(view_f64, arr, 0);
+})();
diff --git a/test/mjsunit/regress/regress-crbug-621361.js b/test/mjsunit/regress/regress-crbug-621361.js
new file mode 100644
index 0000000..f9496ae
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-621361.js
@@ -0,0 +1,40 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+var Debug = debug.Debug;
+var steps = 0;
+var exception = null;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    assertEquals([ debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global],
+                 execState.frame().allScopes().map(s => s.scopeType()));
+    var x_value = execState.frame().evaluate("x").value();
+    if (steps < 2) {
+      assertEquals(undefined, x_value);
+      execState.prepareStep(Debug.StepAction.StepIn);
+    } else {
+      assertEquals("l => l", x_value.toString());
+    }
+    steps++;
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+(function() {
+  debugger;
+  var x = l => l;
+})();
+
+Debug.setListener(null);
+assertNull(exception);
+assertEquals(3, steps);
diff --git a/test/mjsunit/regress/regress-crbug-621611.js b/test/mjsunit/regress/regress-crbug-621611.js
new file mode 100644
index 0000000..bf9a460
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-621611.js
@@ -0,0 +1,11 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+assertEquals(Math.E, Math.exp(1));
+assertEquals(Math.LN10, Math.log(10));
+assertEquals(Math.LN2, Math.log(2));
+assertEquals(Math.LOG10E, Math.log10(Math.E));
+assertEquals(Math.LOG2E, Math.log2(Math.E));
+assertEquals(Math.SQRT1_2, Math.sqrt(0.5));
+assertEquals(Math.SQRT2, Math.sqrt(2));
diff --git a/test/mjsunit/regress/regress-crbug-621816.js b/test/mjsunit/regress/regress-crbug-621816.js
new file mode 100644
index 0000000..ca7f5ac
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-621816.js
@@ -0,0 +1,18 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --turbo
+
+function f() {
+  var o = {};
+  o.a = 1;
+}
+function g() {
+  var o = { ['a']: function(){} };
+  f();
+}
+f();
+f();
+%OptimizeFunctionOnNextCall(g);
+g();
diff --git a/test/mjsunit/regress/regress-crbug-633585.js b/test/mjsunit/regress/regress-crbug-633585.js
new file mode 100644
index 0000000..c483e47
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-633585.js
@@ -0,0 +1,18 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-gc --turbo --always-opt
+
+function f() { this.x = this.x.x; }
+gc();
+f.prototype.x = { x:1 }
+new f();
+new f();
+
+function g() {
+  function h() {};
+  h.prototype = { set x(value) { } };
+  new f();
+}
+g();
diff --git a/test/mjsunit/regress/regress-crbug-642056.js b/test/mjsunit/regress/regress-crbug-642056.js
new file mode 100644
index 0000000..ca9fc78
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-642056.js
@@ -0,0 +1,17 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function f(o) {
+  return o.x instanceof Array;
+}
+
+var o = { x : 1.5 };
+o.x = 0;
+
+f(o);
+f(o);
+%OptimizeFunctionOnNextCall(f);
+f(o);
diff --git a/test/mjsunit/regress/regress-object-assign-deprecated-2.js b/test/mjsunit/regress/regress-object-assign-deprecated-2.js
new file mode 100644
index 0000000..89693de
--- /dev/null
+++ b/test/mjsunit/regress/regress-object-assign-deprecated-2.js
@@ -0,0 +1,8 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var x = {a:1, b:2};
+Object.defineProperty(x, "c", {set(v) {}})
+var y = {get c() { return {a:1, b:2.5} }};
+Object.assign(x, y, x);
diff --git a/test/mjsunit/regress/regress-object-assign-deprecated.js b/test/mjsunit/regress/regress-object-assign-deprecated.js
new file mode 100644
index 0000000..d2e60f9
--- /dev/null
+++ b/test/mjsunit/regress/regress-object-assign-deprecated.js
@@ -0,0 +1,7 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var x = {a:1, b:2};
+var y = {a:1, b:2.5};
+Object.assign(x, x);
diff --git a/test/mjsunit/regress/regress-observe-map-cache.js b/test/mjsunit/regress/regress-observe-map-cache.js
deleted file mode 100644
index c71759c..0000000
--- a/test/mjsunit/regress/regress-observe-map-cache.js
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --harmony-object-observe
-// Flags: --allow-natives-syntax --enable-slow-asserts
-
-function f() {
-  var x = new Array(0);
-  x[-1] = -1;
-  Object.observe(x, function() { });
-}
-
-f();
-f();
diff --git a/test/mjsunit/regress/regress-opt-typeof-null.js b/test/mjsunit/regress/regress-opt-typeof-null.js
new file mode 100644
index 0000000..e4721a1
--- /dev/null
+++ b/test/mjsunit/regress/regress-opt-typeof-null.js
@@ -0,0 +1,12 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function f() {
+  return typeof null === "object";
+};
+
+%OptimizeFunctionOnNextCall(f);
+assertTrue(f());
diff --git a/test/mjsunit/regress/regress-put-prototype-transition.js b/test/mjsunit/regress/regress-put-prototype-transition.js
index 70f0074..c5b4c5a 100644
--- a/test/mjsunit/regress/regress-put-prototype-transition.js
+++ b/test/mjsunit/regress/regress-put-prototype-transition.js
@@ -30,7 +30,7 @@
     __f_4(__v_1);
     assertFalse(%HasFastProperties(__v_1));
     __f_0(__v_1, __v_6);
-    assertTrue(%HasFastProperties(__v_1));
+    assertFalse(%HasFastProperties(__v_1));
   } else {
     __f_0(__v_1, __v_6);
     assertTrue(%HasFastProperties(__v_1));
diff --git a/test/mjsunit/regress/regress-recurse-patch-binary-op.js b/test/mjsunit/regress/regress-recurse-patch-binary-op.js
new file mode 100644
index 0000000..842cc79
--- /dev/null
+++ b/test/mjsunit/regress/regress-recurse-patch-binary-op.js
@@ -0,0 +1,10 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var i = 0
+function valueOf() {
+  while (true) return i++ < 4 ? 1 + this : 2
+}
+
+1 + ({valueOf})
diff --git a/test/mjsunit/regress/regress-seqstrsetchar-ex1.js b/test/mjsunit/regress/regress-seqstrsetchar-ex1.js
deleted file mode 100644
index 444fe4b..0000000
--- a/test/mjsunit/regress/regress-seqstrsetchar-ex1.js
+++ /dev/null
@@ -1,59 +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.
-
-// Flags: --allow-natives-syntax
-
-// stubbed version of ToNumber
-function ToNumber(x) {
-  return 311;
-}
-
-// Reduced version of String.fromCharCode;
-// does not actually do the same calculation but exhibits untagging bug.
-function StringFromCharCode(code) {
-  var n = arguments.length;
-  var one_byte = %NewString(n, true);
-  var i;
-  for (i = 0; i < n; i++) {
-    var code = arguments[i];
-    if (!%_IsSmi(code)) code = ToNumber(code) & 0xffff;
-    if (code > 0xff) break;
-  }
-
-  var two_byte = %NewString(n - i, false);
-  for (var j = 0; i < n; i++, j++) {
-    var code = arguments[i];
-    %_TwoByteSeqStringSetChar(j, code, two_byte);
-  }
-  return one_byte + two_byte;
-}
-
-StringFromCharCode(0xFFF, 0xFFF);
-StringFromCharCode(0x7C, 0x7C);
-%OptimizeFunctionOnNextCall(StringFromCharCode);
-StringFromCharCode(0x7C, 0x7C);
-StringFromCharCode(0xFFF, 0xFFF);
diff --git a/test/mjsunit/regress/regress-seqstrsetchar-ex3.js b/test/mjsunit/regress/regress-seqstrsetchar-ex3.js
deleted file mode 100644
index 0a6b211..0000000
--- a/test/mjsunit/regress/regress-seqstrsetchar-ex3.js
+++ /dev/null
@@ -1,44 +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.
-
-// Flags: --allow-natives-syntax
-
-function test() {
-  var string = %NewString(10, true);
-  for (var i = 0; i < 10; i++) {
-    %_OneByteSeqStringSetChar(i, 65, string);
-    %_OneByteSeqStringSetChar(i, 66, string);
-  }
-  for (var i = 0; i < 10; i++) {
-    assertEquals("B", string[i]);
-  }
-}
-
-test();
-test();
-%OptimizeFunctionOnNextCall(test);
-test();
diff --git a/test/mjsunit/regress/regress-string-from-char-code-tonumber.js b/test/mjsunit/regress/regress-string-from-char-code-tonumber.js
new file mode 100644
index 0000000..a02a277
--- /dev/null
+++ b/test/mjsunit/regress/regress-string-from-char-code-tonumber.js
@@ -0,0 +1,26 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+var thrower = { [Symbol.toPrimitive]: function() { FAIL } };
+
+function testTrace(func) {
+  try {
+    func(thrower);
+    assertUnreachable();
+  } catch (e) {
+    assertTrue(e.stack.indexOf("fromCharCode") >= 0);
+  }
+}
+
+testTrace(String.fromCharCode);
+
+function foo(x) { return String.fromCharCode(x); }
+
+foo(1);
+foo(2);
+testTrace(foo);
+%OptimizeFunctionOnNextCall(foo);
+testTrace(foo);
diff --git a/test/mjsunit/regress/regress-typedarray-length.js b/test/mjsunit/regress/regress-typedarray-length.js
index a0b9998..0dde61f 100644
--- a/test/mjsunit/regress/regress-typedarray-length.js
+++ b/test/mjsunit/regress/regress-typedarray-length.js
@@ -108,13 +108,13 @@
   assertEquals("blah", get(a));
 })();
 
-// Ensure we cannot delete length, byteOffset, byteLength.
+// Ensure we can delete length, byteOffset, byteLength.
 assertTrue(Int32Array.prototype.__proto__.hasOwnProperty("length"));
 assertTrue(Int32Array.prototype.__proto__.hasOwnProperty("byteOffset"));
 assertTrue(Int32Array.prototype.__proto__.hasOwnProperty("byteLength"));
-assertFalse(delete Int32Array.prototype.__proto__.length);
-assertFalse(delete Int32Array.prototype.__proto__.byteOffset);
-assertFalse(delete Int32Array.prototype.__proto__.byteLength);
+assertTrue(delete Int32Array.prototype.__proto__.length);
+assertTrue(delete Int32Array.prototype.__proto__.byteOffset);
+assertTrue(delete Int32Array.prototype.__proto__.byteLength);
 
 a = new Int32Array(100);
 
@@ -122,28 +122,28 @@
   return a.length;
 }
 
-assertEquals(100, get(a));
-assertEquals(100, get(a));
-assertEquals(100, get(a));
+assertEquals(undefined, get(a));
+assertEquals(undefined, get(a));
+assertEquals(undefined, get(a));
 %OptimizeFunctionOnNextCall(get);
-assertEquals(100, get(a));
+assertEquals(undefined, get(a));
 
 get = function(a) {
   return a.byteLength;
 }
 
-assertEquals(400, get(a));
-assertEquals(400, get(a));
-assertEquals(400, get(a));
+assertEquals(undefined, get(a));
+assertEquals(undefined, get(a));
+assertEquals(undefined, get(a));
 %OptimizeFunctionOnNextCall(get);
-assertEquals(400, get(a));
+assertEquals(undefined, get(a));
 
 get = function(a) {
   return a.byteOffset;
 }
 
-assertEquals(0, get(a));
-assertEquals(0, get(a));
-assertEquals(0, get(a));
+assertEquals(undefined, get(a));
+assertEquals(undefined, get(a));
+assertEquals(undefined, get(a));
 %OptimizeFunctionOnNextCall(get);
-assertEquals(0, get(a));
+assertEquals(undefined, get(a));
diff --git a/test/mjsunit/regress/regress-v8-5009.js b/test/mjsunit/regress/regress-v8-5009.js
new file mode 100644
index 0000000..f499548
--- /dev/null
+++ b/test/mjsunit/regress/regress-v8-5009.js
@@ -0,0 +1,61 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function fn1() {
+}
+
+function fn2() {
+}
+
+function fn3() {
+}
+
+function create(id) {
+  // Just some `FunctionTemplate` to hang on
+  var o = new version();
+
+  o.id = id;
+  o[0] = null;
+
+  return o;
+}
+
+function setM1(o) {
+  o.m1 = fn1;
+}
+
+function setM2(o) {
+  o.m2 = fn2;
+}
+
+function setAltM2(o) {
+  // Failing StoreIC happens here
+  o.m2 = fn3;
+}
+
+function setAltM1(o) {
+  o.m1 = null;
+}
+
+function test(o) {
+  o.m2();
+  o.m1();
+}
+
+var p0 = create(0);
+var p1 = create(1);
+var p2 = create(2);
+
+setM1(p0);
+setM1(p1);
+setM1(p2);
+
+setM2(p0);
+setAltM2(p0);
+setAltM1(p0);
+
+setAltM2(p1);
+
+setAltM2(p2);
+test(p2);
diff --git a/test/mjsunit/regress/string-set-char-deopt.js b/test/mjsunit/regress/string-set-char-deopt.js
deleted file mode 100644
index 8956e28..0000000
--- a/test/mjsunit/regress/string-set-char-deopt.js
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2014 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 OneByteSeqStringSetCharDeoptOsr() {
-  function deopt() {
-    %DeoptimizeFunction(f);
-  }
-
-  function f(string, osr) {
-    var world = " world";
-    %_OneByteSeqStringSetChar(0, (deopt(), 0x48), string);
-
-    for (var i = 0; osr && i < 2; i++) %OptimizeOsr();
-
-    return string + world;
-  }
-
-  assertEquals("Hello " + "world", f("hello", false));
-  %OptimizeFunctionOnNextCall(f);
-  assertEquals("Hello " + "world", f("hello", true));
-})();
-
-
-(function OneByteSeqStringSetCharDeopt() {
-  function deopt() {
-    %DeoptimizeFunction(f);
-  }
-
-  function g(x) {
-  }
-
-  function f(string) {
-    g(%_OneByteSeqStringSetChar(0, (deopt(), 0x48), string));
-    return string;
-  }
-
-  assertEquals("Hell" + "o", f("hello"));
-  %OptimizeFunctionOnNextCall(f);
-  assertEquals("Hell" + "o", f("hello"));
-})();
-
-
-(function TwoByteSeqStringSetCharDeopt() {
-  function deopt() {
-    %DeoptimizeFunction(f);
-  }
-
-  function g(x) {
-  }
-
-  function f(string) {
-    g(%_TwoByteSeqStringSetChar(0, (deopt(), 0x48), string));
-    return string;
-  }
-
-  assertEquals("Hell" + "o", f("\u20ACello"));
-  %OptimizeFunctionOnNextCall(f);
-  assertEquals("Hell" + "o", f("\u20ACello"));
-})();
diff --git a/test/mjsunit/stack-traces-overflow.js b/test/mjsunit/stack-traces-overflow.js
index e20c609..af81971 100644
--- a/test/mjsunit/stack-traces-overflow.js
+++ b/test/mjsunit/stack-traces-overflow.js
@@ -27,10 +27,22 @@
 
 // Flags: --stack-size=100
 
+function overflow() {
+  var a, b, c, d, e;  // Allocates some locals on the function's stack frame.
+  overflow();
+}
 function rec1(a) { rec1(a+1); }
 function rec2(a) { rec3(a+1); }
 function rec3(a) { rec2(a+1); }
 
+// Test stack trace has correct function location at top of the stack.
+try {
+  overflow();
+} catch (e) {
+  var first_frame = e.stack.split("\n")[1]
+  assertTrue(first_frame.indexOf("stack-traces-overflow.js:30:18") > 0);
+}
+
 // Test stack trace getter and setter.
 try {
   rec1(0);
diff --git a/test/mjsunit/string-natives.js b/test/mjsunit/string-natives.js
deleted file mode 100644
index 40fe9c6..0000000
--- a/test/mjsunit/string-natives.js
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Flags: --expose-gc --allow-natives-syntax
-
-function test() {
-  var s1 = %NewString(26, true);
-  for (i = 0; i < 26; i++) %_OneByteSeqStringSetChar(i, 65, s1);
-  assertEquals("AAAAAAAAAAAAAAAAAAAAAAAAAA", s1);
-  %_OneByteSeqStringSetChar(25, 66, s1);
-  assertEquals("AAAAAAAAAAAAAAAAAAAAAAAAAB", s1);
-  for (i = 0; i < 26; i++) %_OneByteSeqStringSetChar(i, i+65, s1);
-  assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZ", s1);
-  s1 = %TruncateString(s1, 13);
-  assertEquals("ABCDEFGHIJKLM", s1);
-
-  var s2 = %NewString(26, false);
-  for (i = 0; i < 26; i++) %_TwoByteSeqStringSetChar(i, 65, s2);
-  assertEquals("AAAAAAAAAAAAAAAAAAAAAAAAAA", s2);
-  %_TwoByteSeqStringSetChar(25, 66, s2);
-  assertEquals("AAAAAAAAAAAAAAAAAAAAAAAAAB", s2);
-  for (i = 0; i < 26; i++) %_TwoByteSeqStringSetChar(i, i+65, s2);
-  assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZ", s2);
-  s2 = %TruncateString(s2, 13);
-  assertEquals("ABCDEFGHIJKLM", s2);
-
-  var s3 = %NewString(26, false);
-  for (i = 0; i < 26; i++) %_TwoByteSeqStringSetChar(i, i+1000, s3);
-  for (i = 0; i < 26; i++) assertEquals(s3[i], String.fromCharCode(i+1000));
-
-  var a = [];
-  for (var i = 0; i < 1000; i++) {
-    var s = %NewString(10000, i % 2 == 1);
-    a.push(s);
-  }
-
-  gc();
-
-  for (var i = 0; i < 1000; i++) {
-    assertEquals(10000, a[i].length);
-    a[i] = %TruncateString(a[i], 5000);
-  }
-
-  gc();
-
-  for (var i = 0; i < 1000; i++) {
-    assertEquals(5000, a[i].length);
-  }
-}
-
-
-test();
-test();
-%OptimizeFunctionOnNextCall(test);
-test();
diff --git a/test/mjsunit/string-wrapper.js b/test/mjsunit/string-wrapper.js
new file mode 100644
index 0000000..d4b6500
--- /dev/null
+++ b/test/mjsunit/string-wrapper.js
@@ -0,0 +1,62 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var limit = 10000;
+
+function testStringWrapper(string) {
+  assertEquals('a', string[0]);
+  assertEquals('b', string[1]);
+  assertEquals('c', string[2]);
+}
+
+(function testFastStringWrapperGrow() {
+  var string = new String("abc");
+  for (var i = 0; i < limit; i += 2) {
+    string[i] = {};
+  }
+  testStringWrapper(string);
+
+  for (var i = limit; i > 0; i -= 2) {
+    delete string[i];
+  }
+  testStringWrapper(string);
+})();
+
+(function testSlowStringWrapperGrow() {
+  var string = new String("abc");
+  // Force Slow String Wrapper Elements Kind
+  string[limit] = limit;
+  for (var i = 0; i < limit; i += 2) {
+    string[i] = {};
+  }
+  testStringWrapper(string);
+  assertEquals(limit, string[limit]);
+
+  for (var i = limit; i > 0; i -= 2) {
+    delete string[i];
+  }
+  testStringWrapper(string);
+  assertEquals(undefined, string[limit]);
+})();
+
+
+(function testReconfigureStringWrapperElements() {
+  var s = new String('abc');
+  // Can't reconfigure string contents.
+  assertThrows(() => Object.defineProperty(s, '1', {value: "value"}), TypeError);
+
+  // Configure a property outside the string range
+  var value = 'v1';
+  Object.defineProperty(s, '3', {
+    get: () => {return value},
+    configurable:true
+  });
+  assertEquals('v1', s[3]);
+  value = 'v2';
+  assertEquals('v2', s[3]);
+
+  Object.defineProperty(s, '3', {value: 'v3', configurable: false});
+  assertEquals('v3', s[3]);
+  assertThrows(() => Object.defineProperty(s, '3', {value:2}), TypeError);
+})();
diff --git a/test/mjsunit/tools/dumpcpp.js b/test/mjsunit/tools/dumpcpp.js
new file mode 100644
index 0000000..49b4675
--- /dev/null
+++ b/test/mjsunit/tools/dumpcpp.js
@@ -0,0 +1,53 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Load implementations from <project root>/tools.
+// Files: tools/splaytree.js tools/codemap.js tools/csvparser.js
+// Files: tools/consarray.js tools/profile.js tools/profile_view.js
+// Files: tools/logreader.js tools/tickprocessor.js
+// Files: tools/dumpcpp.js
+// Env: TEST_FILE_NAME
+
+(function testProcessSharedLibrary() {
+  var oldLoadSymbols = UnixCppEntriesProvider.prototype.loadSymbols;
+
+  UnixCppEntriesProvider.prototype.loadSymbols = function(libName) {
+    this.symbols = [[
+      '00000100 00000001 t v8::internal::Runtime_StringReplaceRegExpWithString(v8::internal::Arguments)',
+      '00000110 00000001 T v8::internal::Runtime::GetElementOrCharAt(v8::internal::Handle<v8::internal::Object>, unsigned int)',
+      '00000120 00000001 t v8::internal::Runtime_DebugGetPropertyDetails(v8::internal::Arguments)',
+      '00000130 00000001 W v8::internal::RegExpMacroAssembler::CheckPosition(int, v8::internal::Label*)'
+    ].join('\n'), ''];
+  };
+
+  var testCppProcessor = new CppProcessor(new UnixCppEntriesProvider(),
+                                          false, false);
+  testCppProcessor.processSharedLibrary(
+    '/usr/local/google/home/lpy/v8/out/native/d8',
+    0x00000100, 0x00000400, 0);
+
+  var staticEntries = testCppProcessor.codeMap_.getAllStaticEntriesWithAddresses();
+  var total = staticEntries.length;
+  assertEquals(total, 3);
+  assertEquals(staticEntries[0],
+               [288,{size:1,
+                     name:'v8::internal::Runtime_DebugGetPropertyDetails(v8::internal::Arguments)',
+                     type:'CPP',
+                     nameUpdated_:false}
+               ]);
+  assertEquals(staticEntries[1],
+               [272,{size:1,
+                     name:'v8::internal::Runtime::GetElementOrCharAt(v8::internal::Handle<v8::internal::Object>, unsigned int)',
+                     type:'CPP',
+                     nameUpdated_:false}
+               ]);
+  assertEquals(staticEntries[2],
+              [256,{size:1,
+                    name:'v8::internal::Runtime_StringReplaceRegExpWithString(v8::internal::Arguments)',
+                    type:'CPP',
+                    nameUpdated_:false}
+              ]);
+
+  UnixCppEntriesProvider.prototype.loadSymbols = oldLoadSymbols;
+})();
diff --git a/test/mjsunit/tools/tickprocessor-test-func-info.log b/test/mjsunit/tools/tickprocessor-test-func-info.log
index 94aa56d..fcbf3b1 100644
--- a/test/mjsunit/tools/tickprocessor-test-func-info.log
+++ b/test/mjsunit/tools/tickprocessor-test-func-info.log
@@ -1,6 +1,6 @@
-shared-library,"shell",0x08048000,0x081ee000
-shared-library,"/lib32/libm-2.7.so",0xf7db6000,0xf7dd9000
-shared-library,"ffffe000-fffff000",0xffffe000,0xfffff000
+shared-library,"shell",0x08048000,0x081ee000,0
+shared-library,"/lib32/libm-2.7.so",0xf7db6000,0xf7dd9000,0
+shared-library,"ffffe000-fffff000",0xffffe000,0xfffff000,0
 profiler,"begin",1
 code-creation,Stub,0,0x424260,348,"CompareStub_GE"
 code-creation,LazyCompile,0,0x2a8100,18535,"DrawQube 3d-cube.js:188",0xf43abcac,
diff --git a/test/mjsunit/tools/tickprocessor-test.log b/test/mjsunit/tools/tickprocessor-test.log
index cf8b90d..fbc868e 100644
--- a/test/mjsunit/tools/tickprocessor-test.log
+++ b/test/mjsunit/tools/tickprocessor-test.log
@@ -1,6 +1,6 @@
-shared-library,"shell",0x08048000,0x081ee000
-shared-library,"/lib32/libm-2.7.so",0xf7db6000,0xf7dd9000
-shared-library,"ffffe000-fffff000",0xffffe000,0xfffff000
+shared-library,"shell",0x08048000,0x081ee000,0
+shared-library,"/lib32/libm-2.7.so",0xf7db6000,0xf7dd9000,0
+shared-library,"ffffe000-fffff000",0xffffe000,0xfffff000,0
 profiler,"begin",1
 code-creation,Stub,0,0xf540a100,474,"CEntryStub"
 code-creation,Script,0,0xf541cd80,736,"exp.js"
diff --git a/test/mjsunit/tools/tickprocessor.js b/test/mjsunit/tools/tickprocessor.js
index 73af098..804a85d 100644
--- a/test/mjsunit/tools/tickprocessor.js
+++ b/test/mjsunit/tools/tickprocessor.js
@@ -81,7 +81,7 @@
 
   var shell_prov = new UnixCppEntriesProvider();
   var shell_syms = [];
-  shell_prov.parseVmSymbols('shell', 0x08048000, 0x081ee000,
+  shell_prov.parseVmSymbols('shell', 0x08048000, 0x081ee000, 0,
       function (name, start, end) {
         shell_syms.push(Array.prototype.slice.apply(arguments, [0]));
       });
@@ -107,7 +107,7 @@
   };
   var libc_prov = new UnixCppEntriesProvider();
   var libc_syms = [];
-  libc_prov.parseVmSymbols('libc', 0xf7c5c000, 0xf7da5000,
+  libc_prov.parseVmSymbols('libc', 0xf7c5c000, 0xf7da5000, 0,
       function (name, start, end) {
         libc_syms.push(Array.prototype.slice.apply(arguments, [0]));
       });
@@ -145,17 +145,17 @@
 
   var shell_prov = new MacCppEntriesProvider();
   var shell_syms = [];
-  shell_prov.parseVmSymbols('shell', 0x00001b00, 0x00163156,
+  shell_prov.parseVmSymbols('shell', 0x00001c00, 0x00163256, 0x100,
       function (name, start, end) {
         shell_syms.push(Array.prototype.slice.apply(arguments, [0]));
       });
   assertEquals(
-      [['start', 0x00001b00, 0x00001b40],
-       ['dyld_stub_binding_helper', 0x00001b40, 0x0011b710],
-       ['v8::internal::RegExpMacroAssembler::CheckPosition', 0x0011b710, 0x00134250],
-       ['v8::internal::Runtime_StringReplaceRegExpWithString', 0x00134250, 0x00137220],
-       ['v8::internal::Runtime::GetElementOrCharAt', 0x00137220, 0x00137400],
-       ['v8::internal::Runtime_DebugGetPropertyDetails', 0x00137400, 0x00163156]],
+      [['start', 0x00001c00, 0x00001c40],
+       ['dyld_stub_binding_helper', 0x00001c40, 0x0011b810],
+       ['v8::internal::RegExpMacroAssembler::CheckPosition', 0x0011b810, 0x00134350],
+       ['v8::internal::Runtime_StringReplaceRegExpWithString', 0x00134350, 0x00137320],
+       ['v8::internal::Runtime::GetElementOrCharAt', 0x00137320, 0x00137500],
+       ['v8::internal::Runtime_DebugGetPropertyDetails', 0x00137500, 0x00163256]],
       shell_syms);
 
   // stdc++ library
@@ -168,7 +168,7 @@
   };
   var stdc_prov = new MacCppEntriesProvider();
   var stdc_syms = [];
-  stdc_prov.parseVmSymbols('stdc++', 0x95728fb4, 0x95770005,
+  stdc_prov.parseVmSymbols('stdc++', 0x95728fb4, 0x95770005, 0,
       function (name, start, end) {
         stdc_syms.push(Array.prototype.slice.apply(arguments, [0]));
       });
@@ -211,7 +211,7 @@
   };
   var shell_prov = new WindowsCppEntriesProvider();
   var shell_syms = [];
-  shell_prov.parseVmSymbols('shell.exe', 0x00400000, 0x0057c000,
+  shell_prov.parseVmSymbols('shell.exe', 0x00400000, 0x0057c000, 0,
       function (name, start, end) {
         shell_syms.push(Array.prototype.slice.apply(arguments, [0]));
       });
@@ -252,7 +252,7 @@
   read = exeSymbols;
   var exe_exe_syms = [];
   (new WindowsCppEntriesProvider()).parseVmSymbols(
-      'chrome.exe', 0x00400000, 0x00472000,
+      'chrome.exe', 0x00400000, 0x00472000, 0,
       function (name, start, end) {
         exe_exe_syms.push(Array.prototype.slice.apply(arguments, [0]));
       });
@@ -264,7 +264,7 @@
   read = dllSymbols;
   var exe_dll_syms = [];
   (new WindowsCppEntriesProvider()).parseVmSymbols(
-      'chrome.exe', 0x00400000, 0x00472000,
+      'chrome.exe', 0x00400000, 0x00472000, 0,
       function (name, start, end) {
         exe_dll_syms.push(Array.prototype.slice.apply(arguments, [0]));
       });
@@ -275,7 +275,7 @@
   read = dllSymbols;
   var dll_dll_syms = [];
   (new WindowsCppEntriesProvider()).parseVmSymbols(
-      'chrome.dll', 0x01c30000, 0x02b80000,
+      'chrome.dll', 0x01c30000, 0x02b80000, 0,
       function (name, start, end) {
         dll_dll_syms.push(Array.prototype.slice.apply(arguments, [0]));
       });
@@ -287,7 +287,7 @@
   read = exeSymbols;
   var dll_exe_syms = [];
   (new WindowsCppEntriesProvider()).parseVmSymbols(
-      'chrome.dll', 0x01c30000, 0x02b80000,
+      'chrome.dll', 0x01c30000, 0x02b80000, 0,
       function (name, start, end) {
         dll_exe_syms.push(Array.prototype.slice.apply(arguments, [0]));
       });
@@ -304,7 +304,7 @@
 
 
 CppEntriesProviderMock.prototype.parseVmSymbols = function(
-    name, startAddr, endAddr, symbolAdder) {
+    name, startAddr, endAddr, slideAddr, symbolAdder) {
   var symbols = {
     'shell':
         [['v8::internal::JSObject::LookupOwnRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)', 0x080f8800, 0x080f8d90],
diff --git a/test/mjsunit/wasm/adapter-frame.js b/test/mjsunit/wasm/adapter-frame.js
index 0e5d4b8..e595c3f 100644
--- a/test/mjsunit/wasm/adapter-frame.js
+++ b/test/mjsunit/wasm/adapter-frame.js
@@ -26,10 +26,9 @@
   }
 
   var builder = new WasmModuleBuilder();
-  var sig = new Array();
-  sig.push(type);
-  for (var i = 0; i < args; i++) sig.push(type);
-  builder.addFunction("select", sig)
+  var params = [];
+  for (var i = 0; i < args; i++) params.push(type);
+  builder.addFunction("select", makeSig(params, [type]))
     .addBody([kExprGetLocal, which])
     .exportFunc();
 
diff --git a/test/mjsunit/wasm/asm-wasm-switch.js b/test/mjsunit/wasm/asm-wasm-switch.js
new file mode 100644
index 0000000..bbdb1a2
--- /dev/null
+++ b/test/mjsunit/wasm/asm-wasm-switch.js
@@ -0,0 +1,468 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm
+
+(function TestSwitch0() {
+  function asmModule() {
+    "use asm"
+
+    function caller() {
+      var ret = 0;
+      var x = 7;
+      switch (x) {
+        case 1: {
+          return 0;
+        }
+        case 7: {
+          ret = 5;
+          break;
+        }
+        default: return 0;
+      }
+      return ret|0;
+    }
+
+    return {caller:caller};
+  }
+  var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+  assertEquals(5, wasm.caller());
+})();
+
+(function TestSwitch() {
+  function asmModule() {
+    "use asm"
+
+    function caller() {
+      var ret = 0;
+      var x = 7;
+      switch (x) {
+        case 1: return 0;
+        case 7: {
+          ret = 12;
+          break;
+        }
+        default: return 0;
+      }
+      switch (x) {
+        case 1: return 0;
+        case 8: return 0;
+        default: ret = (ret + 11)|0;
+      }
+      return ret|0;
+    }
+
+    return {caller:caller};
+  }
+  var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+  assertEquals(23, wasm.caller());
+})();
+
+(function TestSwitchFallthrough() {
+  function asmModule() {
+    "use asm"
+
+    function caller() {
+      var x = 17;
+      var ret = 0;
+      switch (x) {
+        case 17:
+        case 14: ret = 39;
+        case 1: ret = (ret + 3)|0;
+        case 4: break;
+        default: ret = (ret + 1)|0;
+      }
+      return ret|0;
+    }
+
+    return {caller:caller};
+  }
+  var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+  assertEquals(42, wasm.caller());
+})();
+
+(function TestNestedSwitch() {
+  function asmModule() {
+    "use asm"
+
+    function caller() {
+      var x = 3;
+      var y = -13;
+      switch (x) {
+        case 1: return 0;
+        case 3: {
+          switch (y) {
+            case 2: return 0;
+            case -13: return 43;
+            default: return 0;
+          }
+        }
+        default: return 0;
+      }
+      return 0;
+    }
+
+    return {caller:caller};
+  }
+  var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+  assertEquals(43, wasm.caller());
+})();
+
+(function TestSwitchWithDefaultOnly() {
+  function asmModule() {
+    "use asm";
+    function main(x) {
+      x = x|0;
+      switch(x|0) {
+        default: return -10;
+      }
+      return 0;
+    }
+    return {
+      main: main,
+    };
+  }
+  var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+  assertEquals(-10, wasm.main(2));
+  assertEquals(-10, wasm.main(54));
+})();
+
+(function TestEmptySwitch() {
+  function asmModule() {
+    "use asm";
+    function main(x) {
+      x = x|0;
+      switch(x|0) {
+      }
+      return 73;
+    }
+    return {
+      main: main,
+    };
+  }
+  var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+  assertEquals(73, wasm.main(7));
+})();
+
+(function TestSwitchWithBrTable() {
+  function asmModule() {
+    "use asm";
+    function main(x) {
+      x = x|0;
+      switch(x|0) {
+        case 14: return 23;
+        case 12: return 25;
+        case 15: return 29;
+        case 19: return 34;
+        case 18: return 17;
+        case 16: return 16;
+        default: return -1;
+      }
+      return 0;
+    }
+    return {
+      main: main,
+    };
+  }
+  var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+  assertEquals(25, wasm.main(12));
+  assertEquals(23, wasm.main(14));
+  assertEquals(29, wasm.main(15));
+  assertEquals(16, wasm.main(16));
+  assertEquals(17, wasm.main(18));
+  assertEquals(34, wasm.main(19));
+  assertEquals(-1, wasm.main(-1));
+})();
+
+(function TestSwitchWithBalancedTree() {
+  function asmModule() {
+    "use asm";
+    function main(x) {
+      x = x|0;
+      switch(x|0) {
+        case 5: return 52;
+        case 1: return 11;
+        case 6: return 63;
+        case 9: return 19;
+        case -4: return -4;
+      }
+      return 0;
+    }
+    return {
+      main: main,
+    };
+  }
+  var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+  assertEquals(-4, wasm.main(-4));
+  assertEquals(11, wasm.main(1));
+  assertEquals(52, wasm.main(5));
+  assertEquals(63, wasm.main(6));
+  assertEquals(19, wasm.main(9));
+  assertEquals(0, wasm.main(11));
+})();
+
+(function TestSwitchHybrid() {
+  function asmModule() {
+    "use asm";
+    function main(x) {
+      x = x|0;
+      switch(x|0) {
+        case 1: return -4;
+        case 2: return 23;
+        case 3: return 32;
+        case 4: return 14;
+        case 7: return 17;
+        case 10: return 10;
+        case 11: return 121;
+        case 12: return 112;
+        case 13: return 31;
+        case 16: return 16;
+        default: return -1;
+      }
+      return 0;
+    }
+    return {
+      main: main,
+    };
+  }
+  var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+  assertEquals(-4, wasm.main(1));
+  assertEquals(23, wasm.main(2));
+  assertEquals(32, wasm.main(3));
+  assertEquals(14, wasm.main(4));
+  assertEquals(17, wasm.main(7));
+  assertEquals(10, wasm.main(10));
+  assertEquals(121, wasm.main(11));
+  assertEquals(112, wasm.main(12));
+  assertEquals(31, wasm.main(13));
+  assertEquals(16, wasm.main(16));
+  assertEquals(-1, wasm.main(20));
+})();
+
+(function TestSwitchFallthroughWithBrTable() {
+  function asmModule() {
+    "use asm";
+    function main(x) {
+      x = x|0;
+      var ret = 0;
+      switch(x|0) {
+        case 1: {
+          ret = 21;
+          break;
+        }
+        case 2: {
+          ret = 12;
+          break;
+        }
+        case 3: {
+          ret = 43;
+        }
+        case 4: {
+          ret = 54;
+          break;
+        }
+        default: {
+          ret = 10;
+          break;
+        }
+      }
+      return ret|0;
+    }
+    return {
+      main: main,
+    };
+  }
+  var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+  assertEquals(12, wasm.main(2));
+  assertEquals(10, wasm.main(10));
+  assertEquals(54, wasm.main(3));
+})();
+
+(function TestSwitchFallthroughHybrid() {
+  function asmModule() {
+    "use asm";
+    function main(x) {
+      x = x|0;
+      var ret = 0;
+      switch(x|0) {
+        case 1: {
+          ret = 1;
+          break;
+        }
+        case 2: {
+          ret = 2;
+          break;
+        }
+        case 3: {
+          ret = 3;
+          break;
+        }
+        case 4: {
+          ret = 4;
+        }
+        case 7: {
+          ret = 7;
+          break;
+        }
+        case 10: {
+          ret = 10;
+        }
+        case 16: {
+          ret = 16;
+          break;
+        }
+        case 17: {
+          ret = 17;
+          break;
+        }
+        case 18: {
+          ret = 18;
+          break;
+        }
+        case 19: {
+          ret = 19;
+        }
+        default: {
+          ret = -1;
+          break;
+        }
+      }
+      return ret|0;
+    }
+    return {
+      main: main,
+    };
+  }
+  var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+  assertEquals(7, wasm.main(4));
+  assertEquals(16, wasm.main(10));
+  assertEquals(-1, wasm.main(19));
+  assertEquals(-1, wasm.main(23));
+})();
+
+(function TestSwitchHybridWithNoDefault() {
+  function asmModule() {
+    "use asm";
+    function main(x) {
+      x = x|0;
+      var ret = 19;
+      switch(x|0) {
+        case 1: {
+          ret = 1;
+          break;
+        }
+        case 2: {
+          ret = 2;
+          break;
+        }
+        case 3: {
+          ret = 3;
+          break;
+        }
+        case 4: {
+          ret = 4;
+          break;
+        }
+        case 7: {
+          ret = 7;
+          break;
+        }
+      }
+      return ret|0;
+    }
+    return {
+      main: main,
+    };
+  }
+  var wasm = Wasm.instantiateModuleFromAsm(asmModule.toString());
+  assertEquals(2, wasm.main(2));
+  assertEquals(7, wasm.main(7));
+  assertEquals(19, wasm.main(-1));
+})();
+
+(function TestLargeSwitch() {
+  function LargeSwitchGenerator(begin, end, gap, handle_case) {
+    var str = "function asmModule() {\
+      \"use asm\";\
+      function main(x) {\
+        x = x|0;\
+        switch(x|0) {";
+    for (var i = begin; i <= end; i = i + gap) {
+      str = str.concat("case ", i.toString(), ": ", handle_case(i));
+    }
+    str = str.concat("default: return -1;\
+        }\
+        return -2;\
+      }\
+      return {main: main}; }");
+
+    var wasm = Wasm.instantiateModuleFromAsm(str);
+    return wasm;
+  }
+
+  var handle_case = function(k) {
+    return "return ".concat(k, ";");
+  }
+  var wasm = LargeSwitchGenerator(0, 513, 1, handle_case);
+  for (var i = 0; i <= 513; i++) {
+    assertEquals(i, wasm.main(i));
+  }
+  assertEquals(-1, wasm.main(-1));
+
+  wasm = LargeSwitchGenerator(0, 1024, 3, handle_case);
+  for (var i = 0; i <= 1024; i = i + 3) {
+    assertEquals(i, wasm.main(i));
+  }
+  assertEquals(-1, wasm.main(-1));
+
+  wasm = LargeSwitchGenerator(-2147483648, -2147483000, 1, handle_case);
+  for (var i = -2147483648; i <= -2147483000; i++) {
+    assertEquals(i, wasm.main(i));
+  }
+  assertEquals(-1, wasm.main(-1));
+  assertEquals(-1, wasm.main(214748647));
+
+  wasm = LargeSwitchGenerator(-2147483648, -2147483000, 3, handle_case);
+  for (var i = -2147483648; i <= -2147483000; i = i + 3) {
+    assertEquals(i, wasm.main(i));
+  }
+  assertEquals(-1, wasm.main(-1));
+  assertEquals(-1, wasm.main(214748647));
+
+  wasm = LargeSwitchGenerator(2147483000, 2147483647, 1, handle_case);
+  for (var i = 2147483000; i <= 2147483647; i++) {
+    assertEquals(i, wasm.main(i));
+  }
+  assertEquals(-1, wasm.main(-1));
+  assertEquals(-1, wasm.main(-214748647));
+
+  wasm = LargeSwitchGenerator(2147483000, 2147483647, 4, handle_case);
+  for (var i = 2147483000; i <= 2147483647; i = i + 4) {
+    assertEquals(i, wasm.main(i));
+  }
+  assertEquals(-1, wasm.main(-1));
+  assertEquals(-1, wasm.main(-214748647));
+
+  handle_case = function(k) {
+    if (k != 7) return "return ".concat(k, ";");
+    else return "break;";
+  }
+  wasm = LargeSwitchGenerator(0, 1499, 7, handle_case);
+  for (var i = 0; i <= 1499; i = i + 7) {
+    if (i == 7) assertEquals(-2, wasm.main(i));
+    else assertEquals(i, wasm.main(i));
+  }
+  assertEquals(-1, wasm.main(-1));
+
+  handle_case = function(k) {
+    if (k != 56) return "break;";
+    else return "return 23;";
+  }
+  wasm = LargeSwitchGenerator(0, 638, 2, handle_case);
+  for (var i = 0; i <= 638; i = i + 2) {
+    if (i == 56) assertEquals(23, wasm.main(i));
+    else assertEquals(-2, wasm.main(i));
+  }
+  assertEquals(-1, wasm.main(-1));
+})();
diff --git a/test/mjsunit/wasm/asm-wasm.js b/test/mjsunit/wasm/asm-wasm.js
index 2efb006..4c28b61 100644
--- a/test/mjsunit/wasm/asm-wasm.js
+++ b/test/mjsunit/wasm/asm-wasm.js
@@ -23,6 +23,20 @@
 
 assertWasm(11, EmptyTest);
 
+function VoidReturnTest() {
+  "use asm";
+  function caller() {
+    empty();
+    return 19;
+  }
+  function empty() {
+    var x = 0;
+    if (x) return;
+  }
+  return {caller: caller};
+}
+
+assertWasm(19, VoidReturnTest);
 
 function IntTest() {
   "use asm";
@@ -193,6 +207,55 @@
 assertWasm(7, TestReturnInWhileWithoutBraces);
 
 
+function TestBreakInIf() {
+  "use asm";
+
+  function caller() {
+    label: {
+      if(1) break label;
+      return 11;
+    }
+    return 12;
+  }
+
+  return {caller: caller};
+}
+
+assertWasm(12, TestBreakInIf);
+
+function TestBreakInIfInDoWhileFalse() {
+  "use asm";
+
+  function caller() {
+    do {
+      if(1) break;
+      return 11;
+    } while(0);
+    return 12;
+  }
+
+  return {caller: caller};
+}
+
+assertWasm(12, TestBreakInIfInDoWhileFalse);
+
+function TestBreakInElse() {
+  "use asm";
+
+  function caller() {
+    do {
+      if(0) ;
+      else break;
+      return 14;
+    } while(0);
+    return 15;
+  }
+
+  return {caller: caller};
+}
+
+assertWasm(15, TestBreakInElse);
+
 function TestBreakInWhile() {
   "use asm";
 
@@ -209,6 +272,22 @@
 assertWasm(8, TestBreakInWhile);
 
 
+function TestBreakInIfInWhile() {
+  "use asm";
+
+  function caller() {
+    while(1) {
+      if (1) break;
+      else break;
+    }
+    return 8;
+  }
+
+  return {caller: caller};
+}
+
+assertWasm(8, TestBreakInIfInWhile);
+
 function TestBreakInNestedWhile() {
   "use asm";
 
@@ -603,6 +682,7 @@
 
 assertWasm(28, TestModDoubleNegative);
 
+
 (function () {
 function TestNamedFunctions() {
   "use asm";
@@ -628,6 +708,7 @@
 assertEquals(77.5, module.add());
 })();
 
+
 (function () {
 function TestGlobalsWithInit() {
   "use asm";
@@ -769,82 +850,6 @@
 assertWasm(41, TestConditional);
 
 
-function TestSwitch() {
-  "use asm"
-
-  function caller() {
-    var ret = 0;
-    var x = 7;
-    switch (x) {
-      case 1: return 0;
-      case 7: {
-        ret = 12;
-        break;
-      }
-      default: return 0;
-    }
-    switch (x) {
-      case 1: return 0;
-      case 8: return 0;
-      default: ret = (ret + 11)|0;
-    }
-    return ret|0;
-  }
-
-  return {caller:caller};
-}
-
-assertWasm(23, TestSwitch);
-
-
-function TestSwitchFallthrough() {
-  "use asm"
-
-  function caller() {
-    var x = 17;
-    var ret = 0;
-    switch (x) {
-      case 17:
-      case 14: ret = 39;
-      case 1: ret = (ret + 3)|0;
-      case 4: break;
-      default: ret = (ret + 1)|0;
-    }
-    return ret|0;
-  }
-
-  return {caller:caller};
-}
-
-assertWasm(42, TestSwitchFallthrough);
-
-
-function TestNestedSwitch() {
-  "use asm"
-
-  function caller() {
-    var x = 3;
-    var y = -13;
-    switch (x) {
-      case 1: return 0;
-      case 3: {
-        switch (y) {
-          case 2: return 0;
-          case -13: return 43;
-          default: return 0;
-        }
-      }
-      default: return 0;
-    }
-    return 0;
-  }
-
-  return {caller:caller};
-}
-
-assertWasm(43, TestNestedSwitch);
-
-
 (function () {
 function TestInitFunctionWithNoGlobals() {
   "use asm";
@@ -1355,6 +1360,38 @@
 })();
 
 
+(function TestBadAssignDoubleFromIntish() {
+  function Module(stdlib, foreign, heap) {
+    "use asm";
+    function func() {
+      var a = 1;
+      var b = 3.0;
+      b = a;
+    }
+    return {func: func};
+  }
+  assertThrows(function() {
+    Wasm.instantiateModuleFromAsm(Module.toString());
+  });
+})();
+
+
+(function TestBadAssignIntFromDouble() {
+  function Module(stdlib, foreign, heap) {
+    "use asm";
+    function func() {
+      var a = 1;
+      var b = 3.0;
+      a = b;
+    }
+    return {func: func};
+  }
+  assertThrows(function() {
+    Wasm.instantiateModuleFromAsm(Module.toString());
+  });
+})();
+
+
 (function TestBadMultiplyIntish() {
   function Module(stdlib, foreign, heap) {
     "use asm";
diff --git a/test/mjsunit/wasm/calls.js b/test/mjsunit/wasm/calls.js
index 11cc92a..94e97e6 100644
--- a/test/mjsunit/wasm/calls.js
+++ b/test/mjsunit/wasm/calls.js
@@ -37,20 +37,42 @@
   assertFalse(exp === null);
   assertFalse(exp === 0);
   assertEquals("function", typeof exp);
-
   return exp;
 }
 
+(function I64SubTest() {
+
+  var builder = new WasmModuleBuilder();
+
+  builder.addMemory(1, 1, true);
+  builder.addFunction("sub", kSig_l_ll)
+    .addBody([           // --
+      kExprGetLocal, 0,  // --
+      kExprGetLocal, 1,  // --
+      kExprI64Sub])      // --
+    .exportFunc()
+
+  var module = builder.instantiate();
+  assertModule(module, kPageSize);
+
+  // Check the properties of the sub function.
+  var sub = assertFunction(module, "sub");
+  assertEquals(-55, sub(33, 88));
+  assertEquals(-55555, sub(33333, 88888));
+  assertEquals(-5555555, sub(3333333, 8888888));
+})();
+
 (function SubTest() {
 
   var builder = new WasmModuleBuilder();
 
   builder.addMemory(1, 1, true);
-  builder.addFunction("sub", [kAstI32, kAstI32, kAstI32])
+  builder.addFunction("sub", kSig_i_ii)
     .addBody([
-      kExprI32Sub,                  // --
       kExprGetLocal, 0,             // --
-      kExprGetLocal, 1])            // --
+      kExprGetLocal, 1,             // --
+      kExprI32Sub,                  // --
+    ])
     .exportFunc()
 
   var module = builder.instantiate();
@@ -70,7 +92,7 @@
 
   var kPages = 2;
   builder.addMemory(kPages, kPages, true);
-  builder.addFunction("nop", [kAstStmt])
+  builder.addFunction("nop", kSig_v_v)
     .addBody([kExprNop])
     .exportFunc();
 
@@ -87,11 +109,12 @@
 
   var kPages = 3;
   builder.addMemory(kPages, kPages, true);
-  builder.addFunction("flt", [kAstI32, kAstF64, kAstF64])
+  builder.addFunction("flt", kSig_i_dd)
     .addBody([
-      kExprF64Lt,           // --
       kExprGetLocal, 0,     // --
-      kExprGetLocal, 1])    // --
+      kExprGetLocal, 1,     // --
+      kExprF64Lt            // --
+    ])                      // --
     .exportFunc();
 
   var module = builder.instantiate();
diff --git a/test/mjsunit/wasm/default-func-call.js b/test/mjsunit/wasm/default-func-call.js
new file mode 100644
index 0000000..14567d3
--- /dev/null
+++ b/test/mjsunit/wasm/default-func-call.js
@@ -0,0 +1,56 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm
+// Flags: --wasm-jit-prototype
+
+load("test/mjsunit/wasm/wasm-constants.js");
+load("test/mjsunit/wasm/wasm-module-builder.js");
+
+var module = (function () {
+  var builder = new WasmModuleBuilder();
+
+  var sig_index = builder.addType(kSig_i_ii);
+  builder.addPadFunctionTable(512);
+  builder.addImport("add", sig_index);
+  builder.addFunction("add", sig_index)
+    .addBody([
+      kExprGetLocal, 0, kExprGetLocal, 1, kExprCallImport, kArity2, 0
+    ]);
+  builder.addFunction("sub", sig_index)
+    .addBody([
+      kExprGetLocal, 0,             // --
+      kExprGetLocal, 1,             // --
+      kExprI32Sub,                  // --
+    ]);
+  builder.addFunction("main", kSig_i_iii)
+    .addBody([
+      kExprGetLocal, 0,
+      kExprGetLocal, 1,
+      kExprGetLocal, 2,
+      kExprCallIndirect, kArity2, sig_index
+    ])
+    .exportFunc()
+  builder.appendToTable([0, 1, 2]);
+
+  return builder.instantiate({add: function(a, b) { return a + b | 0; }});
+})();
+
+// Check the module exists.
+assertFalse(module === undefined);
+assertFalse(module === null);
+assertFalse(module === 0);
+assertEquals("object", typeof module.exports);
+assertEquals("function", typeof module.exports.main);
+
+assertEquals(5, module.exports.main(1, 12, 7));
+assertEquals(19, module.exports.main(0, 12, 7));
+
+assertTraps(kTrapFuncSigMismatch, "module.exports.main(2, 12, 33)");
+assertTraps(kTrapFuncSigMismatch, "module.exports.main(4, 12, 33)");
+assertTraps(kTrapFuncSigMismatch, "module.exports.main(511, 12, 33)");
+assertTraps(kTrapFuncInvalid, "module.exports.main(512, 12, 33)");
+assertTraps(kTrapFuncInvalid, "module.exports.main(1025, 12, 33)");
+assertTraps(kTrapFuncInvalid, "module.exports.main(-1, 12, 33)");
diff --git a/test/mjsunit/wasm/divrem-trap.js b/test/mjsunit/wasm/divrem-trap.js
index 976e473..6f3ff5d 100644
--- a/test/mjsunit/wasm/divrem-trap.js
+++ b/test/mjsunit/wasm/divrem-trap.js
@@ -33,8 +33,12 @@
 function makeBinop(opcode) {
   var builder = new WasmModuleBuilder();
 
-  builder.addFunction("main", [kAstI32, kAstI32, kAstI32])
-    .addBody([opcode, kExprGetLocal, 0, kExprGetLocal, 1])
+  builder.addFunction("main", kSig_i_ii)
+    .addBody([
+      kExprGetLocal, 0,           // --
+      kExprGetLocal, 1,           // --
+      opcode,                     // --
+    ])
     .exportFunc();
 
   return builder.instantiate().exports.main;
diff --git a/test/mjsunit/wasm/export-table.js b/test/mjsunit/wasm/export-table.js
index e85da9b..2084ddf 100644
--- a/test/mjsunit/wasm/export-table.js
+++ b/test/mjsunit/wasm/export-table.js
@@ -11,11 +11,12 @@
   var kReturnValue = 88;
   var builder = new WasmModuleBuilder();
 
-  builder.addFunction("main", [kAstI32])
+  builder.addFunction("main", kSig_i)
     .addBody([
-      kExprReturn,
       kExprI8Const,
-      kReturnValue])
+      kReturnValue,
+      kExprReturn, kArity1
+    ])
     .exportFunc();
 
   var module = builder.instantiate();
@@ -31,11 +32,12 @@
 
   var builder = new WasmModuleBuilder();
 
-  builder.addFunction("main", [kAstI32])
+  builder.addFunction("main", kSig_i)
     .addBody([
-      kExprReturn,
       kExprI8Const,
-      kReturnValue])
+      kReturnValue,
+      kExprReturn, kArity1
+    ])
     .exportAs("blah")
     .exportAs("foo");
 
@@ -48,3 +50,40 @@
   assertEquals(kReturnValue, module.exports.foo());
   assertEquals(kReturnValue, module.exports.blah());
 })();
+
+
+(function testNumericName() {
+  var kReturnValue = 93;
+
+  var builder = new WasmModuleBuilder();
+
+  builder.addFunction("main", kSig_i)
+    .addBody([
+      kExprI8Const,
+      kReturnValue,
+      kExprReturn, kArity1
+    ])
+    .exportAs("0");
+
+  var module = builder.instantiate();
+
+  assertEquals("object", typeof module.exports);
+  assertEquals("function", typeof module.exports["0"]);
+
+  assertEquals(kReturnValue, module.exports["0"]());
+})();
+
+(function testExportNameClash() {
+  var builder = new WasmModuleBuilder();
+
+  builder.addFunction("one",   kSig_v_v).addBody([kExprNop]).exportAs("main");
+  builder.addFunction("two",   kSig_v_v).addBody([kExprNop]).exportAs("other");
+  builder.addFunction("three", kSig_v_v).addBody([kExprNop]).exportAs("main");
+
+  try {
+    builder.instantiate();
+    assertUnreachable("should have thrown an exception");
+  } catch (e) {
+    assertContains("Duplicate export", e.toString());
+  }
+})();
diff --git a/test/mjsunit/wasm/ffi-error.js b/test/mjsunit/wasm/ffi-error.js
index 649ee27..b6474c6 100644
--- a/test/mjsunit/wasm/ffi-error.js
+++ b/test/mjsunit/wasm/ffi-error.js
@@ -10,13 +10,14 @@
 function testCallFFI(ffi) {
   var builder = new WasmModuleBuilder();
 
-  var sig_index = [kAstI32, kAstF64, kAstF64];
+  var sig_index = kSig_i_dd;
   builder.addImport("fun", sig_index);
   builder.addFunction("main", sig_index)
     .addBody([
-      kExprCallImport, 0,   // --
-      kExprGetLocal, 0,     // --
-      kExprGetLocal, 1])    // --
+      kExprGetLocal, 0,              // --
+      kExprGetLocal, 1,              // --
+      kExprCallFunction, kArity2, 0, // --
+    ])    // --
     .exportFunc();
 
   var module = builder.instantiate(ffi);
diff --git a/test/mjsunit/wasm/ffi.js b/test/mjsunit/wasm/ffi.js
index 61fcf02..9db8ea6 100644
--- a/test/mjsunit/wasm/ffi.js
+++ b/test/mjsunit/wasm/ffi.js
@@ -10,13 +10,14 @@
 function testCallFFI(func, check) {
   var builder = new WasmModuleBuilder();
 
-  var sig_index = builder.addSignature([kAstI32, kAstF64, kAstF64]);
+  var sig_index = builder.addType(kSig_i_dd);
   builder.addImport("func", sig_index);
   builder.addFunction("main", sig_index)
     .addBody([
-      kExprCallImport, 0,       // --
-      kExprGetLocal, 0,         // --
-      kExprGetLocal, 1])        // --
+      kExprGetLocal, 0,            // --
+      kExprGetLocal, 1,            // --
+      kExprCallImport, kArity2, 0  // --
+    ])        // --
     .exportFunc();
 
   var main = builder.instantiate({func: func}).exports.main;
@@ -184,14 +185,14 @@
 
   var builder = new WasmModuleBuilder();
 
-  builder.addImport("func", [kAstStmt, type, type]);
-  builder.addFunction("main", [kAstI32, type, type])
+  builder.addImport("func", makeSig_v_xx(type));
+  builder.addFunction("main", makeSig_r_xx(kAstI32, type))
     .addBody([
-      kExprBlock, 2,          // --
-      kExprCallImport, 0,     // --
-      kExprGetLocal, 0,       // --
-      kExprGetLocal, 1,       // --
-      kExprI8Const, 99])      // --
+      kExprGetLocal, 0,            // --
+      kExprGetLocal, 1,            // --
+      kExprCallImport, kArity2, 0, // --
+      kExprI8Const, 99             // --
+    ])                             // --
     .exportFunc()
 
   var main = builder.instantiate(ffi).exports.main;
@@ -240,15 +241,15 @@
 function testCallPrint() {
   var builder = new WasmModuleBuilder();
 
-  builder.addImport("print", [kAstStmt, kAstI32]);
-  builder.addImport("print", [kAstStmt, kAstF64]);
-  builder.addFunction("main", [kAstStmt, kAstF64])
+  builder.addImport("print", makeSig_v_x(kAstI32));
+  builder.addImport("print", makeSig_v_x(kAstF64));
+  builder.addFunction("main", makeSig_v_x(kAstF64))
     .addBody([
-      kExprBlock, 2,            // --
-      kExprCallImport, 0,       // --
-      kExprI8Const, 97,         // --
-      kExprCallImport, 1,       // --
-      kExprGetLocal, 0])        // --
+      kExprI8Const, 97,             // --
+      kExprCallImport, kArity1, 0,  // --
+      kExprGetLocal, 0,             // --
+      kExprCallImport, kArity1, 1   // --
+    ])        // --
     .exportFunc()
 
   var main = builder.instantiate({print: print}).exports.main;
diff --git a/test/mjsunit/wasm/function-names.js b/test/mjsunit/wasm/function-names.js
new file mode 100644
index 0000000..15771d8
--- /dev/null
+++ b/test/mjsunit/wasm/function-names.js
@@ -0,0 +1,69 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm
+
+load("test/mjsunit/wasm/wasm-constants.js");
+load("test/mjsunit/wasm/wasm-module-builder.js");
+
+var builder = new WasmModuleBuilder();
+
+var last_func_index = builder.addFunction("exec_unreachable", kSig_v_v)
+  .addBody([kExprUnreachable])
+
+var illegal_func_name = [0xff];
+var func_names = [ "☠", illegal_func_name, "some math: (½)² = ¼", "" ];
+var expected_names = ["exec_unreachable", "☠", null,
+                      "some math: (½)² = ¼", "", "main"];
+
+for (var func_name of func_names) {
+  last_func_index = builder.addFunction(func_name, kSig_v_v)
+    .addBody([kExprCallFunction, kArity0, last_func_index]).index;
+}
+
+builder.addFunction("main", kSig_v_v)
+  .addBody([kExprCallFunction, kArity0, last_func_index])
+  .exportFunc();
+
+var module = builder.instantiate();
+
+(function testFunctionNamesAsString() {
+  var names = expected_names.concat(["testFunctionNamesAsString", null]);
+  try {
+    module.exports.main();
+    assertFalse("should throw");
+  } catch (e) {
+    var lines = e.stack.split(/\r?\n/);
+    lines.shift();
+    assertEquals(names.length, lines.length);
+    for (var i = 0; i < names.length; ++i) {
+      var line = lines[i].trim();
+      if (names[i] === null) continue;
+      var printed_name = names[i] === undefined ? "<WASM UNNAMED>" : names[i]
+      var expected_start = "at " + printed_name + " (";
+      assertTrue(line.startsWith(expected_start),
+          "should start with '" + expected_start + "': '" + line + "'");
+    }
+  }
+})();
+
+// For the remaining tests, collect the Callsite objects instead of just a
+// string:
+Error.prepareStackTrace = function(error, frames) {
+  return frames;
+};
+
+
+(function testFunctionNamesAsCallSites() {
+  var names = expected_names.concat(["testFunctionNamesAsCallSites", null]);
+  try {
+    module.exports.main();
+    assertFalse("should throw");
+  } catch (e) {
+    assertEquals(names.length, e.stack.length);
+    for (var i = 0; i < names.length; ++i) {
+      assertEquals(names[i], e.stack[i].getFunctionName());
+    }
+  }
+})();
diff --git a/test/mjsunit/wasm/function-prototype.js b/test/mjsunit/wasm/function-prototype.js
index db04b95..25339ad 100644
--- a/test/mjsunit/wasm/function-prototype.js
+++ b/test/mjsunit/wasm/function-prototype.js
@@ -10,7 +10,7 @@
 (function TestFunctionPrototype() {
   var builder = new WasmModuleBuilder();
 
-  builder.addFunction("nine", [kAstI32])
+  builder.addFunction("nine", kSig_i)
     .addBody([kExprI8Const, 9])
     .exportFunc();
 
diff --git a/test/mjsunit/wasm/gc-frame.js b/test/mjsunit/wasm/gc-frame.js
index 8387d26..9c37fe4 100644
--- a/test/mjsunit/wasm/gc-frame.js
+++ b/test/mjsunit/wasm/gc-frame.js
@@ -10,14 +10,13 @@
 function makeFFI(func, t) {
   var builder = new WasmModuleBuilder();
 
-  var sig_index = builder.addSignature([t,t,t,t,t,t,t,t,t,t,t]);
+  var sig_index = builder.addType(makeSig([t,t,t,t,t,t,t,t,t,t], [t]));
   builder.addImport("func", sig_index);
   // Try to create a frame with lots of spilled values and parameters
   // on the stack to try to catch GC bugs in the reference maps for
   // the different parts of the stack.
   builder.addFunction("main", sig_index)
     .addBody([
-      kExprCallImport, 0,       // --
       kExprGetLocal, 0,         // --
       kExprGetLocal, 1,         // --
       kExprGetLocal, 2,         // --
@@ -28,7 +27,7 @@
       kExprGetLocal, 7,         // --
       kExprGetLocal, 8,         // --
       kExprGetLocal, 9,         // --
-      kExprCallImport, 0,       // --
+      kExprCallImport, 10, 0,   // --
       kExprGetLocal, 0,         // --
       kExprGetLocal, 1,         // --
       kExprGetLocal, 2,         // --
@@ -38,7 +37,8 @@
       kExprGetLocal, 6,         // --
       kExprGetLocal, 7,         // --
       kExprGetLocal, 8,         // --
-      kExprGetLocal, 9          // --
+      kExprGetLocal, 9,         // --
+      kExprCallImport, 10, 0    // --
     ])                          // --
     .exportFunc();
 
@@ -66,9 +66,32 @@
   }
 })();
 
-(function I32Test() {
+(function F64Test() {
   var main = makeFFI(print10, kAstF64);
   for (var i = 1; i < 2e+80; i *= -1137) {
     main(i - 1, i, i + 2, i + 3, i + 4, i + 5, i + 6, i + 7, i + 8);
   }
 })();
+
+(function GCInJSToWasmTest() {
+  var builder = new WasmModuleBuilder();
+
+  var sig_index = builder.addType(kSig_i_i);
+  builder.addFunction("main", sig_index)
+    .addBody([
+      kExprGetLocal, 0,         // --
+    ])                          // --
+    .exportFunc();
+
+  var main = builder.instantiate({}).exports.main;
+
+  var gc_object = {
+      valueOf: function() {
+        // Call the GC in valueOf, which is called within the JSToWasm wrapper.
+        gc();
+        return {};
+      }
+  };
+
+  main(gc_object);
+})();
diff --git a/test/mjsunit/wasm/import-table.js b/test/mjsunit/wasm/import-table.js
index 7579901..ebba040 100644
--- a/test/mjsunit/wasm/import-table.js
+++ b/test/mjsunit/wasm/import-table.js
@@ -10,13 +10,13 @@
 function testCallImport(func, check) {
   var builder = new WasmModuleBuilder();
 
-  var sig_index = builder.addSignature([kAstI32, kAstF64, kAstF64]);
+  var sig_index = builder.addType(kSig_i_dd);
   builder.addImport("func", sig_index);
   builder.addFunction("main", sig_index)
     .addBody([
-      kExprCallImport, 0,          // --
       kExprGetLocal, 0,            // --
-      kExprGetLocal, 1])           // --
+      kExprGetLocal, 1,            // --
+      kExprCallImport, 2, 0])      // --
     .exportAs("main");
 
   var main = builder.instantiate({func: func}).exports.main;
@@ -186,14 +186,14 @@
 
   var builder = new WasmModuleBuilder();
 
-  builder.addImport("func", [kAstStmt, type, type]);
-  builder.addFunction("main", [kAstI32, type, type])
+  builder.addImport("func", makeSig_v_xx(type));
+  builder.addFunction("main", makeSig_r_xx(kAstI32, type))
     .addBody([
-      kExprBlock, 2,              // --
-      kExprCallImport, 0,         // --
       kExprGetLocal, 0,           // --
       kExprGetLocal, 1,           // --
-      kExprI8Const, 99])
+      kExprCallImport, 2, 0,      // --
+      kExprI8Const, 99,           // --
+    ])
     .exportFunc("main");
 
   var main = builder.instantiate(ffi).exports.main;
@@ -241,15 +241,15 @@
 
 function testCallPrint() {
   var builder = new WasmModuleBuilder();
-  builder.addImport("print", [kAstStmt, kAstI32]);
-  builder.addImport("print", [kAstStmt, kAstF64]);
-  builder.addFunction("main", [kAstStmt, kAstF64])
+  builder.addImport("print", makeSig_v_x(kAstI32));
+  builder.addImport("print", makeSig_r_x(kAstF64, kAstF64));
+  builder.addFunction("main", makeSig_r_x(kAstF64, kAstF64))
     .addBody([
-      kExprBlock, 2,              // --
-      kExprCallImport, 0,         // --
-      kExprI8Const, 97,           // --
-      kExprCallImport, 1,         // --
-      kExprGetLocal, 0])          // --
+      kExprI8Const, 97,             // --
+      kExprCallImport, kArity1, 0,  // --
+      kExprGetLocal, 0,             // --
+      kExprCallImport, kArity1, 1   // --
+    ])
     .exportFunc();
 
   var main = builder.instantiate({print: print}).exports.main;
@@ -266,13 +266,14 @@
 function testCallImport2(foo, bar, expected) {
   var builder = new WasmModuleBuilder();
 
-  builder.addImport("foo", [kAstI32]);
-  builder.addImport("bar", [kAstI32]);
-  builder.addFunction("main", [kAstI32])
+  builder.addImport("foo", kSig_i);
+  builder.addImport("bar", kSig_i);
+  builder.addFunction("main", kSig_i)
     .addBody([
+      kExprCallImport, kArity0, 0, // --
+      kExprCallImport, kArity0, 1, // --
       kExprI32Add,                 // --
-      kExprCallImport, 0,          // --
-      kExprCallImport, 1])          // --
+    ])                             // --
     .exportFunc();
 
   var main = builder.instantiate({foo: foo, bar: bar}).exports.main;
diff --git a/test/mjsunit/wasm/indirect-calls.js b/test/mjsunit/wasm/indirect-calls.js
index 3258687..1e87c6f 100644
--- a/test/mjsunit/wasm/indirect-calls.js
+++ b/test/mjsunit/wasm/indirect-calls.js
@@ -10,24 +10,27 @@
 var module = (function () {
   var builder = new WasmModuleBuilder();
 
-  var sig_index = builder.addSignature([kAstI32, kAstI32, kAstI32]);
+  var sig_index = builder.addType(kSig_i_ii);
   builder.addImport("add", sig_index);
   builder.addFunction("add", sig_index)
     .addBody([
-      kExprCallImport, 0, kExprGetLocal, 0, kExprGetLocal, 1
+      kExprGetLocal, 0, kExprGetLocal, 1, kExprCallImport, kArity2, 0
     ]);
   builder.addFunction("sub", sig_index)
     .addBody([
-      kExprI32Sub, kExprGetLocal, 0, kExprGetLocal, 1
+      kExprGetLocal, 0,             // --
+      kExprGetLocal, 1,             // --
+      kExprI32Sub,                  // --
     ]);
-  builder.addFunction("main", [kAstI32, kAstI32, kAstI32, kAstI32])
+  builder.addFunction("main", kSig_i_iii)
     .addBody([
-      kExprCallIndirect, sig_index,
       kExprGetLocal, 0,
       kExprGetLocal, 1,
-      kExprGetLocal, 2])
+      kExprGetLocal, 2,
+      kExprCallIndirect, kArity2, sig_index
+    ])
     .exportFunc()
-  builder.appendToFunctionTable([0, 1, 2]);
+  builder.appendToTable([0, 1, 2]);
 
   return builder.instantiate({add: function(a, b) { return a + b | 0; }});
 })();
diff --git a/test/mjsunit/wasm/instantiate-module-basic.js b/test/mjsunit/wasm/instantiate-module-basic.js
index bc13122..72a3425 100644
--- a/test/mjsunit/wasm/instantiate-module-basic.js
+++ b/test/mjsunit/wasm/instantiate-module-basic.js
@@ -7,44 +7,54 @@
 load("test/mjsunit/wasm/wasm-constants.js");
 load("test/mjsunit/wasm/wasm-module-builder.js");
 
-var kReturnValue = 117;
+let kReturnValue = 117;
 
-var module = (function Build() {
-  var builder = new WasmModuleBuilder();
-
+let buffer = (() => {
+  let builder = new WasmModuleBuilder();
   builder.addMemory(1, 1, true);
-  builder.addFunction("main", [kAstI32])
+  builder.addFunction("main", kSig_i)
     .addBody([kExprI8Const, kReturnValue])
     .exportFunc();
 
-  return builder.instantiate();
-})();
+  return builder.toBuffer();
+})()
 
-// Check the module exists.
-assertFalse(module === undefined);
-assertFalse(module === null);
-assertFalse(module === 0);
-assertEquals("object", typeof module);
+function CheckInstance(instance) {
+  assertFalse(instance === undefined);
+  assertFalse(instance === null);
+  assertFalse(instance === 0);
+  assertEquals("object", typeof instance);
 
-// Check the memory is an ArrayBuffer.
-var mem = module.exports.memory;
-assertFalse(mem === undefined);
-assertFalse(mem === null);
-assertFalse(mem === 0);
-assertEquals("object", typeof mem);
-assertTrue(mem instanceof ArrayBuffer);
-for (var i = 0; i < 4; i++) {
-  module.exports.memory = 0;  // should be ignored
-  assertEquals(mem, module.exports.memory);
+  // Check the memory is an ArrayBuffer.
+  var mem = instance.exports.memory;
+  assertFalse(mem === undefined);
+  assertFalse(mem === null);
+  assertFalse(mem === 0);
+  assertEquals("object", typeof mem);
+  assertTrue(mem instanceof ArrayBuffer);
+  for (let i = 0; i < 4; i++) {
+    instance.exports.memory = 0;  // should be ignored
+    assertSame(mem, instance.exports.memory);
+  }
+
+  assertEquals(65536, instance.exports.memory.byteLength);
+
+  // Check the properties of the main function.
+  let main = instance.exports.main;
+  assertFalse(main === undefined);
+  assertFalse(main === null);
+  assertFalse(main === 0);
+  assertEquals("function", typeof main);
+
+  assertEquals(kReturnValue, main());
 }
 
-assertEquals(65536, module.exports.memory.byteLength);
+// Deprecated experimental API.
+CheckInstance(Wasm.instantiateModule(buffer));
 
-// Check the properties of the main function.
-var main = module.exports.main;
-assertFalse(main === undefined);
-assertFalse(main === null);
-assertFalse(main === 0);
-assertEquals("function", typeof main);
+// Official API
+let module = new WebAssembly.Module(buffer);
+CheckInstance(new WebAssembly.Instance(module));
 
-assertEquals(kReturnValue, main());
+let promise = WebAssembly.compile(buffer);
+promise.then(module => CheckInstance(new WebAssembly.Instance(module)));
diff --git a/test/mjsunit/wasm/instantiate-run-basic.js b/test/mjsunit/wasm/instantiate-run-basic.js
index 2e649a0..fe6fc14 100644
--- a/test/mjsunit/wasm/instantiate-run-basic.js
+++ b/test/mjsunit/wasm/instantiate-run-basic.js
@@ -11,7 +11,7 @@
   var kReturnValue = 107;
   var builder = new WasmModuleBuilder();
 
-  builder.addFunction("main", [kAstI32])
+  builder.addFunction("main", kSig_i_i)
     .addBody([kExprI8Const, kReturnValue])
     .exportFunc();
 
diff --git a/test/mjsunit/wasm/module-memory.js b/test/mjsunit/wasm/module-memory.js
index ef85eb2..a5e5f42 100644
--- a/test/mjsunit/wasm/module-memory.js
+++ b/test/mjsunit/wasm/module-memory.js
@@ -13,19 +13,27 @@
   var builder = new WasmModuleBuilder();
 
   builder.addMemory(1, 1, true);
-  builder.addFunction("main", [kAstI32, kAstI32])
+  builder.addFunction("main", kSig_i_i)
     .addBody([
-      kExprBlock,2,
-        kExprLoop,1,
-          kExprIf,
+    // main body: while(i) { if(mem[i]) return -1; i -= 4; } return 0;
+      kExprLoop,
+        kExprGetLocal,0,
+        kExprIf,
             kExprGetLocal,0,
-            kExprBr, 0,
-              kExprIfElse,
-                kExprI32LoadMem,0,0,kExprGetLocal,0,
-                kExprBr,2, kExprI8Const, 255,
-                kExprSetLocal,0,
-                  kExprI32Sub,kExprGetLocal,0,kExprI8Const,4,
-        kExprI8Const,0])
+          kExprI32LoadMem,0,0,
+          kExprIf,
+            kExprI8Const,255,
+            kExprReturn, kArity1,
+          kExprEnd,
+              kExprGetLocal,0,
+              kExprI8Const,4,
+            kExprI32Sub,
+          kExprSetLocal,0,
+        kExprBr, kArity1, 1,
+        kExprEnd,
+      kExprEnd,
+      kExprI8Const,0
+    ])
     .exportFunc();
 
   return builder.instantiate(null, memory);
@@ -120,14 +128,16 @@
   var builder = new WasmModuleBuilder();
 
   builder.addMemory(1, 1, true);
-  builder.addFunction("geti", [kAstI32, kAstI32, kAstI32])
+  builder.addFunction("geti", kSig_i_ii)
     .addBody([
-      kExprI32StoreMem, 0, 0, kExprGetLocal, 0, kExprI32LoadMem, 0, 0, kExprGetLocal, 1
+      kExprGetLocal, 0,
+      kExprGetLocal, 1,
+      kExprI32LoadMem, 0, 0,
+      kExprI32StoreMem, 0, 0
     ])
     .exportFunc();
 
   var module = builder.instantiate();
-
   var offset;
 
   function read() { return module.exports.geti(0, offset); }
diff --git a/test/mjsunit/wasm/parallel_compilation.js b/test/mjsunit/wasm/parallel_compilation.js
new file mode 100644
index 0000000..23c5658
--- /dev/null
+++ b/test/mjsunit/wasm/parallel_compilation.js
@@ -0,0 +1,100 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm --wasm-num-compilation-tasks=10
+
+load("test/mjsunit/wasm/wasm-constants.js");
+load("test/mjsunit/wasm/wasm-module-builder.js");
+
+function assertModule(module, memsize) {
+  // Check the module exists.
+  assertFalse(module === undefined);
+  assertFalse(module === null);
+  assertFalse(module === 0);
+  assertEquals("object", typeof module);
+
+  // Check the memory is an ArrayBuffer.
+  var mem = module.exports.memory;
+  assertFalse(mem === undefined);
+  assertFalse(mem === null);
+  assertFalse(mem === 0);
+  assertEquals("object", typeof mem);
+  assertTrue(mem instanceof ArrayBuffer);
+  for (var i = 0; i < 4; i++) {
+    module.exports.memory = 0;  // should be ignored
+    assertEquals(mem, module.exports.memory);
+  }
+
+  assertEquals(memsize, module.exports.memory.byteLength);
+}
+
+function assertFunction(module, func) {
+  assertEquals("object", typeof module.exports);
+
+  var exp = module.exports[func];
+  assertFalse(exp === undefined);
+  assertFalse(exp === null);
+  assertFalse(exp === 0);
+  assertEquals("function", typeof exp);
+  return exp;
+}
+
+(function CompileFunctionsTest() {
+
+  var builder = new WasmModuleBuilder();
+
+  builder.addMemory(1, 1, true);
+  for (i = 0; i < 1000; i++) {
+    builder.addFunction("sub" + i, kSig_i_i)
+      .addBody([                // --
+        kExprGetLocal, 0,       // --
+        kExprI32Const, i % 61,  // --
+        kExprI32Sub])           // --
+      .exportFunc()
+  }
+
+  var module = builder.instantiate();
+  assertModule(module, kPageSize);
+
+  // Check the properties of the functions.
+  for (i = 0; i < 1000; i++) {
+    var sub = assertFunction(module, "sub" + i);
+    assertEquals(33 - (i % 61), sub(33));
+  }
+})();
+
+(function CallFunctionsTest() {
+
+  var builder = new WasmModuleBuilder();
+
+  var f = []
+
+  f[0] = builder.addFunction("add0", kSig_i_ii)
+  .addBody([
+            kExprGetLocal, 0,             // --
+            kExprGetLocal, 1,             // --
+            kExprI32Add,                  // --
+          ])
+          .exportFunc()
+
+  builder.addMemory(1, 1, true);
+  for (i = 1; i < 256; i++) {
+    f[i] = builder.addFunction("add" + i, kSig_i_ii)
+      .addBody([                                            // --
+        kExprGetLocal, 0,                                   // --
+        kExprGetLocal, 1,                                   // --
+        kExprCallFunction, kArity2, f[i >>> 1].index])      // --
+      .exportFunc()
+  }
+  var module = builder.instantiate();
+  assertModule(module, kPageSize);
+
+  // Check the properties of the functions.
+  for (i = 0; i < 256; i++) {
+    var add = assertFunction(module, "add" + i);
+    assertEquals(88, add(33, 55));
+    assertEquals(88888, add(33333, 55555));
+    assertEquals(8888888, add(3333333, 5555555));
+  }
+})();
diff --git a/test/mjsunit/wasm/params.js b/test/mjsunit/wasm/params.js
index 7c2b3d1..fe1b7d4 100644
--- a/test/mjsunit/wasm/params.js
+++ b/test/mjsunit/wasm/params.js
@@ -17,7 +17,7 @@
 
     var builder = new WasmModuleBuilder();
 
-    builder.addFunction("select", [type, type, type])
+    builder.addFunction("select", makeSig_r_xx(type, type))
       .addBody([kExprGetLocal, which])
       .exportFunc()
 
@@ -79,7 +79,7 @@
     print("type = " + t + ", which = " + which);
 
     var builder = new WasmModuleBuilder();
-    builder.addFunction("select", [t,t,t,t,t,t,t,t,t,t,t])
+    builder.addFunction("select", makeSig([t,t,t,t,t,t,t,t,t,t], [t]))
       .addBody([kExprGetLocal, which])
       .exportFunc();
 
diff --git a/test/mjsunit/wasm/stack.js b/test/mjsunit/wasm/stack.js
index ed05517..4ff0d1d 100644
--- a/test/mjsunit/wasm/stack.js
+++ b/test/mjsunit/wasm/stack.js
@@ -2,39 +2,126 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// clang-format off
 // Flags: --expose-wasm
 
 load("test/mjsunit/wasm/wasm-constants.js");
 load("test/mjsunit/wasm/wasm-module-builder.js");
 
-var expected = "Error\n" +
-    // The line numbers below will change as this test gains / loses lines..
-    "    at STACK (stack.js:24:11)\n" +     // --
-    "    at <WASM> (<anonymous>)\n" +       // TODO(jfb): wasm stack here.
-    "    at testStack (stack.js:38:18)\n" + // --
-    "    at stack.js:40:3";                 // --
-
 // The stack trace contains file path, only keep "stack.js".
 function stripPath(s) {
   return s.replace(/[^ (]*stack\.js/g, "stack.js");
 }
 
+function verifyStack(frames, expected) {
+  assertEquals(expected.length, frames.length, "number of frames mismatch");
+  expected.forEach(function(exp, i) {
+    assertEquals(exp[1], frames[i].getFunctionName(),
+        "["+i+"].getFunctionName()");
+    assertEquals(exp[2], frames[i].getLineNumber(), "["+i+"].getLineNumber()");
+    if (exp[0])
+      assertEquals(exp[3], frames[i].getPosition(),
+          "["+i+"].getPosition()");
+    assertContains(exp[4], frames[i].getFileName(), "["+i+"].getFileName()");
+    var toString;
+    if (exp[0]) {
+      toString = exp[1] + " (<WASM>[" + exp[2] + "]+" + exp[3] + ")";
+    } else {
+      toString = exp[4] + ":" + exp[2] + ":";
+    }
+    assertContains(toString, frames[i].toString(), "["+i+"].toString()");
+  });
+}
+
+
 var stack;
 function STACK() {
   var e = new Error();
   stack = e.stack;
 }
 
-(function testStack() {
-  var builder = new WasmModuleBuilder();
+var builder = new WasmModuleBuilder();
 
-  builder.addImport("func", [kAstStmt]);
+builder.addImport("func", kSig_v_v);
 
-  builder.addFunction(undefined, [kAstStmt])
-    .addBody([kExprCallImport, 0])
-    .exportAs("main");
+builder.addFunction("main", kSig_v_v)
+  .addBody([kExprCallImport, kArity0, 0])
+  .exportAs("main");
 
-  var module = builder.instantiate({func: STACK});
+builder.addFunction("exec_unreachable", kSig_v_v)
+  .addBody([kExprUnreachable])
+  .exportAs("exec_unreachable");
+
+// Make this function unnamed, just to test also this case.
+var mem_oob_func = builder.addFunction(undefined, kSig_v_v)
+  // Access the memory at offset -1, to provoke a trap.
+  .addBody([kExprI32Const, 0x7f, kExprI32LoadMem8S, 0, 0])
+  .exportAs("mem_out_of_bounds");
+
+// Call the mem_out_of_bounds function, in order to have two WASM stack frames.
+builder.addFunction("call_mem_out_of_bounds", kSig_v_v)
+  .addBody([kExprCallFunction, kArity0, mem_oob_func.index])
+  .exportAs("call_mem_out_of_bounds");
+
+var module = builder.instantiate({func: STACK});
+
+(function testSimpleStack() {
+  var expected_string = "Error\n" +
+    // The line numbers below will change as this test gains / loses lines..
+    "    at STACK (stack.js:39:11)\n" +           // --
+    "    at main (<WASM>[0]+1)\n" +               // --
+    "    at testSimpleStack (stack.js:76:18)\n" + // --
+    "    at stack.js:78:3";                       // --
+
   module.exports.main();
-  assertEquals(expected, stripPath(stack));
+  assertEquals(expected_string, stripPath(stack));
+})();
+
+// For the remaining tests, collect the Callsite objects instead of just a
+// string:
+Error.prepareStackTrace = function(error, frames) {
+  return frames;
+};
+
+(function testStackFrames() {
+  module.exports.main();
+
+  verifyStack(stack, [
+      // isWasm           function   line  pos        file
+      [   false,           "STACK",    39,   0, "stack.js"],
+      [    true,            "main",     0,   1,       null],
+      [   false, "testStackFrames",    87,   0, "stack.js"],
+      [   false,              null,    96,   0, "stack.js"]
+  ]);
+})();
+
+(function testWasmUnreachable() {
+  try {
+    module.exports.exec_unreachable();
+    fail("expected wasm exception");
+  } catch (e) {
+    assertContains("unreachable", e.message);
+    verifyStack(e.stack, [
+        // isWasm               function   line  pos        file
+        [    true,    "exec_unreachable",    1,    1,       null],
+        [   false, "testWasmUnreachable",  100,    0, "stack.js"],
+        [   false,                  null,  111,    0, "stack.js"]
+    ]);
+  }
+})();
+
+(function testWasmMemOutOfBounds() {
+  try {
+    module.exports.call_mem_out_of_bounds();
+    fail("expected wasm exception");
+  } catch (e) {
+    assertContains("out of bounds", e.message);
+    verifyStack(e.stack, [
+        // isWasm                  function   line  pos        file
+        [    true,                       "",     2,   3,       null],
+        [    true, "call_mem_out_of_bounds",     3,   1,       null],
+        [   false, "testWasmMemOutOfBounds",   115,   0, "stack.js"],
+        [   false,                     null,   127,   0, "stack.js"]
+    ]);
+  }
 })();
diff --git a/test/mjsunit/wasm/stackwalk.js b/test/mjsunit/wasm/stackwalk.js
index 8b8fb7e..913269f 100644
--- a/test/mjsunit/wasm/stackwalk.js
+++ b/test/mjsunit/wasm/stackwalk.js
@@ -10,13 +10,14 @@
 function makeFFI(func) {
   var builder = new WasmModuleBuilder();
 
-  var sig_index = builder.addSignature([kAstI32, kAstF64, kAstF64]);
+  var sig_index = builder.addType(kSig_i_dd);
   builder.addImport("func", sig_index);
   builder.addFunction("main", sig_index)
     .addBody([
-      kExprCallImport, 0,       // --
-      kExprGetLocal, 0,         // --
-      kExprGetLocal, 1])        // --
+      kExprGetLocal, 0,            // --
+      kExprGetLocal, 1,            // --
+      kExprCallImport, kArity2, 0, // --
+    ])
     .exportFunc()
 
   return builder.instantiate({func: func}).exports.main;
diff --git a/test/mjsunit/wasm/start-function.js b/test/mjsunit/wasm/start-function.js
index bd4ccf2..c4d299e 100644
--- a/test/mjsunit/wasm/start-function.js
+++ b/test/mjsunit/wasm/start-function.js
@@ -37,19 +37,19 @@
   return module;
 }
 
-assertVerifies([kAstStmt], [kExprNop]);
-assertVerifies([kAstI32], [kExprI8Const, 0]);
+assertVerifies(kSig_v_v, [kExprNop]);
+assertVerifies(kSig_i, [kExprI8Const, 0]);
 
 // Arguments aren't allow to start functions.
-assertFails([kAstI32, kAstI32], [kExprGetLocal, 0]);
-assertFails([kAstI32, kAstI32, kAstF32], [kExprGetLocal, 0]);
-assertFails([kAstI32, kAstI32, kAstF32, kAstF64], [kExprGetLocal, 0]);
+assertFails(kSig_i_i, [kExprGetLocal, 0]);
+assertFails(kSig_i_ii, [kExprGetLocal, 0]);
+assertFails(kSig_i_dd, [kExprGetLocal, 0]);
 
 (function testInvalidIndex() {
   print("testInvalidIndex");
   var builder = new WasmModuleBuilder();
 
-  var func = builder.addFunction("", [kAstStmt])
+  var func = builder.addFunction("", kSig_v_v)
     .addBody([kExprNop]);
 
   builder.addStart(func.index + 1);
@@ -62,11 +62,11 @@
   print("testTwoStartFuncs");
   var builder = new WasmModuleBuilder();
 
-  var func = builder.addFunction("", [kAstStmt])
+  var func = builder.addFunction("", kSig_v_v)
     .addBody([kExprNop]);
 
-  builder.addExplicitSection([kDeclStartFunction, 0]);
-  builder.addExplicitSection([kDeclStartFunction, 0]);
+  builder.addExplicitSection([kDeclStart, 0]);
+  builder.addExplicitSection([kDeclStart, 0]);
 
   assertThrows(builder.instantiate);
 })();
@@ -78,8 +78,8 @@
 
   builder.addMemory(12, 12, true);
 
-  var func = builder.addFunction("", [kAstStmt])
-    .addBody([kExprI32StoreMem, 0, 0, kExprI8Const, 0, kExprI8Const, 77]);
+  var func = builder.addFunction("", kSig_v_v)
+    .addBody([kExprI8Const, 0, kExprI8Const, 77, kExprI32StoreMem, 0, 0]);
 
   builder.addStart(func.index);
 
@@ -98,11 +98,11 @@
   }};
 
   var builder = new WasmModuleBuilder();
-  var sig_index = builder.addSignature([kAstStmt]);
+  var sig_index = builder.addType(kSig_v_v);
 
   builder.addImport("foo", sig_index);
   var func = builder.addFunction("", sig_index)
-    .addBody([kExprCallImport, 0]);
+    .addBody([kExprCallImport, kArity0, 0]);
 
   builder.addStart(func.index);
 
diff --git a/test/mjsunit/wasm/test-wasm-module-builder.js b/test/mjsunit/wasm/test-wasm-module-builder.js
index 50797d0..72d5a7a 100644
--- a/test/mjsunit/wasm/test-wasm-module-builder.js
+++ b/test/mjsunit/wasm/test-wasm-module-builder.js
@@ -12,7 +12,7 @@
 (function BasicTest() {
     var module = new WasmModuleBuilder();
     module.addMemory(1, 2, false);
-    module.addFunction("foo", [kAstI32])
+    module.addFunction("foo", kSig_i)
         .addBody([kExprI8Const, 11])
         .exportAs("blarg");
 
@@ -23,9 +23,9 @@
 
 (function ImportTest() {
     var module = new WasmModuleBuilder();
-    var index = module.addImport("print", [kAstStmt, kAstI32]);
-    module.addFunction("foo", [kAstStmt])
-        .addBody([kExprCallImport, index, kExprI8Const, 13])
+    var index = module.addImport("print", makeSig_v_x(kAstI32));
+    module.addFunction("foo", kSig_v_v)
+        .addBody([kExprI8Const, 13, kExprCallImport, kArity1, index])
         .exportAs("main");
 
     var buffer = module.toBuffer(debug);
@@ -36,9 +36,9 @@
 
 (function LocalsTest() {
     var module = new WasmModuleBuilder();
-    module.addFunction(undefined, [kAstI32, kAstI32])
+    module.addFunction(undefined, kSig_i_i)
         .addLocals({i32_count: 1})
-        .addBody([kExprSetLocal, 1, kExprGetLocal, 0])
+        .addBody([kExprGetLocal, 0, kExprSetLocal, 1])
         .exportAs("main");
 
     var buffer = module.toBuffer(debug);
@@ -58,9 +58,9 @@
 
     for (p of types) {
       var module = new WasmModuleBuilder();
-      module.addFunction(undefined, [p.type, p.type])
+      module.addFunction(undefined, makeSig_r_x(p.type, p.type))
         .addLocals(p.locals)
-        .addBody([kExprSetLocal, 1, kExprGetLocal, 0])
+        .addBody([kExprGetLocal, 0, kExprSetLocal, 1])
         .exportAs("main");
 
       var buffer = module.toBuffer(debug);
@@ -72,10 +72,10 @@
 
 (function CallTest() {
     var module = new WasmModuleBuilder();
-    module.addFunction("add", [kAstI32, kAstI32, kAstI32])
-        .addBody([kExprI32Add, kExprGetLocal, 0, kExprGetLocal, 1]);
-    module.addFunction("main", [kAstI32, kAstI32, kAstI32])
-        .addBody([kExprCallFunction, 0, kExprGetLocal, 0, kExprGetLocal, 1])
+    module.addFunction("add", kSig_i_ii)
+        .addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]);
+    module.addFunction("main", kSig_i_ii)
+        .addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprCallFunction, kArity2, 0])
         .exportAs("main");
 
     var instance = module.instantiate();
@@ -85,13 +85,13 @@
 
 (function IndirectCallTest() {
     var module = new WasmModuleBuilder();
-    module.addFunction("add", [kAstI32, kAstI32, kAstI32])
-        .addBody([kExprI32Add, kExprGetLocal, 0, kExprGetLocal, 1]);
-    module.addFunction("main", [kAstI32, kAstI32, kAstI32, kAstI32])
-        .addBody([kExprCallIndirect, 0, kExprGetLocal,
-                  0, kExprGetLocal, 1, kExprGetLocal, 2])
+    module.addFunction("add", kSig_i_ii)
+        .addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]);
+    module.addFunction("main", kSig_i_iii)
+        .addBody([kExprGetLocal,
+                  0, kExprGetLocal, 1, kExprGetLocal, 2, kExprCallIndirect, kArity2, 0])
         .exportAs("main");
-    module.appendToFunctionTable([0]);
+    module.appendToTable([0]);
 
     var instance = module.instantiate();
     assertEquals(44, instance.exports.main(0, 11, 33));
@@ -102,8 +102,8 @@
 (function DataSegmentTest() {
     var module = new WasmModuleBuilder();
     module.addMemory(1, 1, false);
-    module.addFunction("load", [kAstI32, kAstI32])
-        .addBody([kExprI32LoadMem, 0, 0, kExprGetLocal, 0])
+    module.addFunction("load", kSig_i_i)
+        .addBody([kExprGetLocal, 0, kExprI32LoadMem, 0, 0])
         .exportAs("load");
     module.addDataSegment(0, [9, 9, 9, 9], true);
 
@@ -116,7 +116,7 @@
 (function BasicTestWithUint8Array() {
     var module = new WasmModuleBuilder();
     module.addMemory(1, 2, false);
-    module.addFunction("foo", [kAstI32])
+    module.addFunction("foo", kSig_i)
         .addBody([kExprI8Const, 17])
         .exportAs("blarg");
 
@@ -141,9 +141,9 @@
 
 (function ImportTestTwoLevel() {
     var module = new WasmModuleBuilder();
-    var index = module.addImportWithModule("mod", "print", [kAstStmt, kAstI32]);
-    module.addFunction("foo", [kAstStmt])
-        .addBody([kExprCallImport, index, kExprI8Const, 19])
+    var index = module.addImportWithModule("mod", "print", makeSig_v_x(kAstI32));
+    module.addFunction("foo", kSig_v_v)
+        .addBody([kExprI8Const, 19, kExprCallImport, kArity1, index])
         .exportAs("main");
 
     var buffer = module.toBuffer(debug);
diff --git a/test/mjsunit/wasm/trap-location.js b/test/mjsunit/wasm/trap-location.js
new file mode 100644
index 0000000..0440af9
--- /dev/null
+++ b/test/mjsunit/wasm/trap-location.js
@@ -0,0 +1,78 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm
+
+load("test/mjsunit/wasm/wasm-constants.js");
+load("test/mjsunit/wasm/wasm-module-builder.js");
+
+// Collect the Callsite objects instead of just a string:
+Error.prepareStackTrace = function(error, frames) {
+  return frames;
+};
+
+var builder = new WasmModuleBuilder();
+
+var sig_index = builder.addType(kSig_i_v)
+
+// Build a function to resemble this code:
+//   if (idx < 2) {
+//     return load(-2 / idx);
+//   } else if (idx == 2) {
+//     unreachable;
+//   } else {
+//     return call_indirect(idx);
+//   }
+// There are four different traps which are triggered by different input values:
+// (0) division by zero; (1) mem oob; (2) unreachable; (3) invalid call target
+// Each of them also has a different location where it traps.
+builder.addFunction("main", kSig_i_i)
+  .addBody([
+      // offset 1
+      kExprBlock,
+            kExprGetLocal, 0,
+            kExprI32Const, 2,
+          kExprI32LtU,
+        kExprIf,
+        // offset 8
+              kExprI32Const, 0x7e /* -2 */,
+              kExprGetLocal, 0,
+            kExprI32DivU,
+          // offset 13
+          kExprI32LoadMem, 0, 0,
+          kExprBr, 1, 1,
+        kExprEnd,
+        // offset 20
+            kExprGetLocal, 0,
+            kExprI32Const, 2,
+          kExprI32Eq,
+        kExprIf,
+          kExprUnreachable,
+        kExprEnd,
+        // offset 28
+          kExprGetLocal, 0,
+        kExprCallIndirect, kArity0, sig_index,
+      kExprEnd,
+  ])
+  .exportAs("main");
+
+var module = builder.instantiate();
+
+function testWasmTrap(value, reason, position) {
+  try {
+    module.exports.main(value);
+    fail("expected wasm exception");
+  } catch (e) {
+    assertEquals(kTrapMsgs[reason], e.message, "trap reason");
+    assertEquals(3, e.stack.length, "number of frames");
+    assertEquals(0, e.stack[0].getLineNumber(), "wasmFunctionIndex");
+    assertEquals(position, e.stack[0].getPosition(), "position");
+  }
+}
+
+// The actual tests:
+testWasmTrap(0, kTrapDivByZero,      12);
+testWasmTrap(1, kTrapMemOutOfBounds, 13);
+testWasmTrap(2, kTrapUnreachable,    26);
+testWasmTrap(3, kTrapFuncInvalid,    30);
diff --git a/test/mjsunit/wasm/unicode-validation.js b/test/mjsunit/wasm/unicode-validation.js
new file mode 100644
index 0000000..b2e4603
--- /dev/null
+++ b/test/mjsunit/wasm/unicode-validation.js
@@ -0,0 +1,121 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm
+
+load("test/mjsunit/wasm/wasm-constants.js");
+load("test/mjsunit/wasm/wasm-module-builder.js");
+
+function toByteArray(s) {
+  var arr = [];
+  for (var i = 0; i < s.length; ++i) {
+    arr.push(s.charCodeAt(i) & 0xff);
+  }
+  return arr;
+}
+
+function toString(arr) {
+  if (typeof arr === "string") return arr;
+  var s = "";
+  for (var b of arr) s += String.fromCharCode(b);
+  return s;
+}
+
+function toUTF8(arr) {
+  if (typeof arr === "string" || arr === undefined) return arr;
+  return decodeURIComponent(escape(toString(arr)));
+}
+
+function isValidUtf8(arr) {
+  if (typeof arr === "string" || arr === undefined) return true;
+  try {
+    var s = toUTF8(arr);
+    for (var i = 0; i < s.length; ++i)
+      if ((s.charCodeAt(i) & 0xfffe) == 0xfffe)
+        return false;
+    return true;
+  } catch (e) {
+    if (e instanceof URIError) return false;
+    throw e;
+  }
+}
+
+function checkImportsAndExports(imported_module_name, imported_function_name,
+    internal_function_name, exported_function_name, shouldThrow) {
+  var builder = new WasmModuleBuilder();
+
+  builder.addImportWithModule(imported_module_name, imported_function_name,
+      kSig_v_v);
+
+  builder.addFunction(internal_function_name, kSig_v_v)
+    .addBody([kExprCallImport, kArity0, 0])
+    .exportAs(exported_function_name);
+
+  // sanity check: does javascript agree with out shouldThrow annotation?
+  assertEquals(shouldThrow,
+      !isValidUtf8(imported_module_name) ||
+          !isValidUtf8(imported_function_name) ||
+          !isValidUtf8(exported_function_name),
+      "JavaScript does not agree with our shouldThrow expectation");
+
+  if (!shouldThrow) {
+    imported_module_name = toUTF8(imported_module_name);
+    imported_function_name = toUTF8(imported_function_name);
+  }
+
+  var ffi = new Object();
+  if (imported_function_name === undefined) {
+    ffi[imported_module_name] = function() { };
+  } else {
+    ffi[imported_module_name] = new Object();
+    ffi[imported_module_name][imported_function_name] = function() { };
+  }
+
+  var hasThrown = true;
+  try {
+    builder.instantiate(ffi);
+    hasThrown = false;
+  } catch (err) {
+    if (!shouldThrow) print(err);
+    assertTrue(shouldThrow, "Should not throw error on valid names");
+    assertContains("UTF-8", err.toString());
+  }
+  assertEquals(shouldThrow, hasThrown,
+      "Should throw validation error on invalid names");
+}
+
+function checkImportedModuleName(name, shouldThrow) {
+  checkImportsAndExports(name, "imp", "func", undefined, shouldThrow);
+}
+
+function checkImportedFunctionName(name, shouldThrow) {
+  checkImportsAndExports("module", name, "func", "func", shouldThrow);
+}
+
+function checkExportedFunctionName(name, shouldThrow) {
+  checkImportsAndExports("module", "func", "func", name, shouldThrow);
+}
+
+function checkInternalFunctionName(name) {
+  checkImportsAndExports("module", "func", name, "func", false);
+}
+
+function checkAll(name, shouldThrow) {
+  checkImportedModuleName(name, shouldThrow);
+  checkImportedFunctionName(name, shouldThrow);
+  checkExportedFunctionName(name, shouldThrow);
+  checkInternalFunctionName(name);
+}
+
+checkAll("ascii", false);
+checkAll("some math: (½)² = ¼", false);
+checkAll("中国历史系列条目\n北", false);
+checkAll(toByteArray("\xef\xb7\x8f"), false);
+checkAll(toByteArray("a\xc2\x81\xe1\x80\xbf\xf1\x80\xa0\xbf"), false);
+checkAll(toByteArray("\xff"), true);
+checkAll(toByteArray("\xed\xa0\x8f"), true);        // surrogate code points
+checkAll(toByteArray("\xe0\x82\x80"), true);        // overlong sequence
+checkAll(toByteArray("\xf4\x90\x80\x80"), true);    // beyond limit: U+110000
+checkAll(toByteArray("\xef\xbf\xbe"), true);        // non-character; U+FFFE
+checkAll(toByteArray("with\x00null"), false);
diff --git a/test/mjsunit/wasm/unreachable.js b/test/mjsunit/wasm/unreachable.js
index 3e2dffb..d77b53e 100644
--- a/test/mjsunit/wasm/unreachable.js
+++ b/test/mjsunit/wasm/unreachable.js
@@ -9,7 +9,7 @@
 
 var main = (function () {
   var builder = new WasmModuleBuilder();
-  builder.addFunction("main", [kAstStmt])
+  builder.addFunction("main", kSig_v_v)
     .addBody([kExprUnreachable])
     .exportAs("main");
 
@@ -23,4 +23,4 @@
     print("correctly caught: " + e);
     exception = e;
 }
-assertEquals("unreachable", exception);
+assertEquals("unreachable", exception.message);
diff --git a/test/mjsunit/wasm/verify-function-simple.js b/test/mjsunit/wasm/verify-function-simple.js
index aa5c676..31c23a6 100644
--- a/test/mjsunit/wasm/verify-function-simple.js
+++ b/test/mjsunit/wasm/verify-function-simple.js
@@ -8,9 +8,9 @@
 
 try {
   var data = bytes(
-      0,       kAstStmt,  // signature
-      kDeclNoLocals,      // --
-      kExprNop            // body
+      kWasmFunctionTypeForm, 0, kAstStmt,  // signature
+      kDeclNoLocals,                       // --
+      kExprNop                             // body
   );
 
   Wasm.verifyFunction(data);
@@ -23,9 +23,9 @@
 var threw = false;
 try {
   var data = bytes(
-      0,       kAstI32,   // signature
-      kDeclNoLocals,      // --
-      kExprBlock, 2, kExprNop, kExprNop  // body
+      kWasmFunctionTypeForm, 0, 1, kAstI32,     // signature
+      kDeclNoLocals,                            // --
+      kExprBlock, kExprNop, kExprNop, kExprEnd  // body
   );
 
   Wasm.verifyFunction(data);
diff --git a/test/mjsunit/wasm/wasm-constants.js b/test/mjsunit/wasm/wasm-constants.js
index cc620bb..319cadc 100644
--- a/test/mjsunit/wasm/wasm-constants.js
+++ b/test/mjsunit/wasm/wasm-constants.js
@@ -21,7 +21,7 @@
 var kWasmH2 = 0x73;
 var kWasmH3 = 0x6d;
 
-var kWasmV0 = 10;
+var kWasmV0 = 11;
 var kWasmV1 = 0;
 var kWasmV2 = 0;
 var kWasmV3 = 0;
@@ -52,23 +52,30 @@
 
 // Section declaration constants
 var kDeclMemory = 0x00;
-var kDeclSignatures = 0x01;
+var kDeclTypes = 0x01;
 var kDeclFunctions = 0x02;
 var kDeclGlobals = 0x03;
-var kDeclDataSegments = 0x04;
-var kDeclFunctionTable = 0x05;
+var kDeclData = 0x04;
+var kDeclTable = 0x05;
 var kDeclEnd = 0x06;
-var kDeclStartFunction = 0x07;
-var kDeclImportTable = 0x08;
-var kDeclExportTable = 0x09;
-var kDeclFunctionSignatures = 0x0a;
-var kDeclFunctionBodies = 0x0b;
+var kDeclStart = 0x07;
+var kDeclImports = 0x08;
+var kDeclExports = 0x09;
+var kDeclFunctions = 0x0a;
+var kDeclCode = 0x0b;
 var kDeclNames = 0x0c;
+var kDeclFunctionTablePad = 0x0d;
+
+var kArity0 = 0;
+var kArity1 = 1;
+var kArity2 = 2;
+var kArity3 = 3;
+var kWasmFunctionTypeForm = 0x40;
 
 var section_names = [
-  "memory", "signatures", "functions", "globals", "data_segments",
-  "function_table", "end", "start_function", "import_table", "export_table",
-  "function_signatures", "function_bodies", "names"];
+  "memory", "type", "old_function", "global", "data",
+  "table", "end", "start", "import", "export",
+  "function", "code", "name", "table_pad"];
 
 // Function declaration flags
 var kDeclFunctionName   = 0x01;
@@ -83,31 +90,68 @@
 var kAstF32 = 3;
 var kAstF64 = 4;
 
+// Useful signatures
+var kSig_i = makeSig([], [kAstI32]);
+var kSig_d = makeSig([], [kAstF64]);
+var kSig_i_i = makeSig([kAstI32], [kAstI32]);
+var kSig_i_ii = makeSig([kAstI32, kAstI32], [kAstI32]);
+var kSig_i_iii = makeSig([kAstI32, kAstI32, kAstI32], [kAstI32]);
+var kSig_d_dd = makeSig([kAstF64, kAstF64], [kAstF64]);
+var kSig_l_ll = makeSig([kAstI64, kAstI64], [kAstI64]);
+var kSig_i_dd = makeSig([kAstF64, kAstF64], [kAstI32]);
+var kSig_v_v = makeSig([], []);
+var kSig_i_v = makeSig([], [kAstI32]);
+
+function makeSig(params, results) {
+  return {params: params, results: results};
+}
+
+function makeSig_v_x(x) {
+  return makeSig([x], []);
+}
+
+function makeSig_v_xx(x) {
+  return makeSig([x, x], []);
+}
+
+function makeSig_r_v(r) {
+  return makeSig([], [r]);
+}
+
+function makeSig_r_x(r, x) {
+  return makeSig([x], [r]);
+}
+
+function makeSig_r_xx(r, x) {
+  return makeSig([x, x], [r]);
+}
+
 // Opcodes
 var kExprNop = 0x00;
 var kExprBlock = 0x01;
 var kExprLoop = 0x02;
 var kExprIf = 0x03;
-var kExprIfElse = 0x04;
+var kExprElse = 0x04;
 var kExprSelect = 0x05;
 var kExprBr = 0x06;
 var kExprBrIf = 0x07;
-var kExprTableSwitch = 0x08;
-var kExprReturn = 0x14;
-var kExprUnreachable = 0x15;
+var kExprBrTable = 0x08;
+var kExprReturn = 0x09;
+var kExprUnreachable = 0x0a;
+var kExprEnd = 0x0f;
 
-var kExprI8Const = 0x09;
-var kExprI32Const = 0x0a;
-var kExprI64Const = 0x0b;
-var kExprF64Const = 0x0c;
-var kExprF32Const = 0x0d;
-var kExprGetLocal = 0x0e;
-var kExprSetLocal = 0x0f;
-var kExprLoadGlobal = 0x10;
-var kExprStoreGlobal = 0x11;
-var kExprCallFunction = 0x12;
-var kExprCallIndirect = 0x13;
-var kExprCallImport = 0x1F;
+var kExprI32Const = 0x10;
+var kExprI64Const = 0x11;
+var kExprF64Const = 0x12;
+var kExprF32Const = 0x13;
+var kExprGetLocal = 0x14;
+var kExprSetLocal = 0x15;
+var kExprCallFunction = 0x16;
+var kExprCallIndirect = 0x17;
+var kExprCallImport = 0x18;
+var kExprI8Const = 0xcb;
+var kExprLoadGlobal = 0xcc;
+var kExprStoreGlobal = 0xcd;
 
 var kExprI32LoadMem8S = 0x20;
 var kExprI32LoadMem8U = 0x21;
@@ -290,8 +334,8 @@
       }
       threwException = false;
     } catch (e) {
-      assertEquals("string", typeof e);
-      assertEquals(kTrapMsgs[trap], e);
+      assertEquals("object", typeof e);
+      assertEquals(kTrapMsgs[trap], e.message);
       // Success.
       return;
     }
diff --git a/test/mjsunit/wasm/wasm-module-builder.js b/test/mjsunit/wasm/wasm-module-builder.js
index e1d9963..5c5df79 100644
--- a/test/mjsunit/wasm/wasm-module-builder.js
+++ b/test/mjsunit/wasm/wasm-module-builder.js
@@ -2,334 +2,373 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-function WasmFunctionBuilder(name, sig_index) {
-    this.name = name;
-    this.sig_index = sig_index;
-    this.exports = [];
-}
+class Binary extends Array {
+  emit_u8(val) {
+    this.push(val);
+  }
 
-WasmFunctionBuilder.prototype.exportAs = function(name) {
-    this.exports.push(name);
-    return this;
-}
+  emit_u16(val) {
+    this.push(val & 0xff);
+    this.push((val >> 8) & 0xff);
+  }
 
-WasmFunctionBuilder.prototype.exportFunc = function() {
-  this.exports.push(this.name);
-  return this;
-}
+  emit_u32(val) {
+    this.push(val & 0xff);
+    this.push((val >> 8) & 0xff);
+    this.push((val >> 16) & 0xff);
+    this.push((val >> 24) & 0xff);
+  }
 
-WasmFunctionBuilder.prototype.addBody = function(body) {
-    this.body = body;
-    return this;
-}
-
-WasmFunctionBuilder.prototype.addLocals = function(locals) {
-    this.locals = locals;
-    return this;
-}
-
-function WasmModuleBuilder() {
-    this.signatures = [];
-    this.imports = [];
-    this.functions = [];
-    this.exports = [];
-    this.function_table = [];
-    this.data_segments = [];
-    this.explicit = [];
-    return this;
-}
-
-WasmModuleBuilder.prototype.addStart = function(start_index) {
-    this.start_index = start_index;
-}
-
-WasmModuleBuilder.prototype.addMemory = function(min, max, exp) {
-    this.memory = {min: min, max: max, exp: exp};
-    return this;
-}
-
-WasmModuleBuilder.prototype.addExplicitSection = function(bytes) {
-  this.explicit.push(bytes);
-  return this;
-}
-
-// Add a signature; format is [rettype, param0, param1, ...]
-WasmModuleBuilder.prototype.addSignature = function(sig) {
-    // TODO: canonicalize signatures?
-    this.signatures.push(sig);
-    return this.signatures.length - 1;
-}
-
-WasmModuleBuilder.prototype.addFunction = function(name, sig) {
-    var sig_index = (typeof sig) == "number" ? sig : this.addSignature(sig);
-    var func = new WasmFunctionBuilder(name, sig_index);
-    func.index = this.functions.length;
-    this.functions.push(func);
-    return func;
-}
-
-WasmModuleBuilder.prototype.addImportWithModule = function(module, name, sig) {
-  var sig_index = (typeof sig) == "number" ? sig : this.addSignature(sig);
-  this.imports.push({module: module, name: name, sig_index: sig_index});
-  return this.imports.length - 1;
-}
-
-WasmModuleBuilder.prototype.addImport = function(name, sig) {
-  var sig_index = (typeof sig) == "number" ? sig : this.addSignature(sig);
-  this.imports.push({module: name, name: undefined, sig_index: sig_index});
-  return this.imports.length - 1;
-}
-
-WasmModuleBuilder.prototype.addDataSegment = function(addr, data, init) {
-    this.data_segments.push({addr: addr, data: data, init: init});
-    return this.data_segments.length - 1;
-}
-
-WasmModuleBuilder.prototype.appendToFunctionTable = function(array) {
-    this.function_table = this.function_table.concat(array);
-    return this;
-}
-
-function emit_u8(bytes, val) {
-    bytes.push(val & 0xff);
-}
-
-function emit_u16(bytes, val) {
-    bytes.push(val & 0xff);
-    bytes.push((val >> 8) & 0xff);
-}
-
-function emit_u32(bytes, val) {
-    bytes.push(val & 0xff);
-    bytes.push((val >> 8) & 0xff);
-    bytes.push((val >> 16) & 0xff);
-    bytes.push((val >> 24) & 0xff);
-}
-
-function emit_string(bytes, string) {
-    emit_varint(bytes, string.length);
-    for (var i = 0; i < string.length; i++) {
-      emit_u8(bytes, string.charCodeAt(i));
-    }
-}
-
-function emit_varint(bytes, val) {
+  emit_varint(val) {
     while (true) {
-        var v = val & 0xff;
-        val = val >>> 7;
-        if (val == 0) {
-            bytes.push(v);
-            break;
-        }
-        bytes.push(v | 0x80);
+      let v = val & 0xff;
+      val = val >>> 7;
+      if (val == 0) {
+        this.push(v);
+        break;
+      }
+      this.push(v | 0x80);
     }
-}
+  }
 
-function emit_bytes(bytes, data) {
-  for (var i = 0; i < data.length; i++) {
-    bytes.push(data[i] & 0xff);
+  emit_bytes(data) {
+    for (let i = 0; i < data.length; i++) {
+      this.push(data[i] & 0xff);
+    }
+  }
+
+  emit_string(string) {
+    // When testing illegal names, we pass a byte array directly.
+    if (string instanceof Array) {
+      this.emit_varint(string.length);
+      this.emit_bytes(string);
+      return;
+    }
+
+    // This is the hacky way to convert a JavaScript string to a UTF8 encoded
+    // string only containing single-byte characters.
+    let string_utf8 = unescape(encodeURIComponent(string));
+    this.emit_varint(string_utf8.length);
+    for (let i = 0; i < string_utf8.length; i++) {
+      this.emit_u8(string_utf8.charCodeAt(i));
+    }
+  }
+
+  emit_header() {
+    this.push(kWasmH0, kWasmH1, kWasmH2, kWasmH3,
+              kWasmV0, kWasmV1, kWasmV2, kWasmV3);
+  }
+
+  emit_section(section_code, content_generator) {
+    // Emit section name.
+    this.emit_string(section_names[section_code]);
+    // Emit the section to a temporary buffer: its full length isn't know yet.
+    let section = new Binary;
+    content_generator(section);
+    // Emit section length.
+    this.emit_varint(section.length);
+    // Copy the temporary buffer.
+    this.push(...section);
   }
 }
 
-function emit_section(bytes, section_code, content_generator) {
-    // Start the section in a temporary buffer: its full length isn't know yet.
-    var tmp_bytes = [];
-    emit_string(tmp_bytes, section_names[section_code]);
-    content_generator(tmp_bytes);
-    // Now that we know the section length, emit it and copy the section.
-    emit_varint(bytes, tmp_bytes.length);
-    Array.prototype.push.apply(bytes, tmp_bytes);
+class WasmFunctionBuilder {
+  constructor(name, type_index) {
+    this.name = name;
+    this.type_index = type_index;
+    this.exports = [];
+  }
+
+  exportAs(name) {
+    this.exports.push(name);
+    return this;
+  }
+
+  exportFunc() {
+    this.exports.push(this.name);
+    return this;
+  }
+
+  addBody(body) {
+    this.body = body;
+    return this;
+  }
+
+  addLocals(locals) {
+    this.locals = locals;
+    return this;
+  }
 }
 
-WasmModuleBuilder.prototype.toArray = function(debug) {
-    // Add header bytes
-    var bytes = [];
-    bytes = bytes.concat([kWasmH0, kWasmH1, kWasmH2, kWasmH3,
-                          kWasmV0, kWasmV1, kWasmV2, kWasmV3]);
+class WasmModuleBuilder {
+  constructor() {
+    this.types = [];
+    this.imports = [];
+    this.functions = [];
+    this.exports = [];
+    this.table = [];
+    this.segments = [];
+    this.explicit = [];
+    this.pad = null;
+    return this;
+  }
 
-    var wasm = this;
+  addStart(start_index) {
+    this.start_index = start_index;
+  }
 
-    // Add memory section
-    if (wasm.memory != undefined) {
-        if (debug) print("emitting memory @ " + bytes.length);
-        emit_section(bytes, kDeclMemory, function(bytes) {
-            emit_varint(bytes, wasm.memory.min);
-            emit_varint(bytes, wasm.memory.max);
-            emit_u8(bytes, wasm.memory.exp ? 1 : 0);
-        });
-    }
+  addMemory(min, max, exp) {
+    this.memory = {min: min, max: max, exp: exp};
+    return this;
+  }
 
-    // Add signatures section
-    if (wasm.signatures.length > 0) {
-        if (debug) print("emitting signatures @ " + bytes.length);
-        emit_section(bytes, kDeclSignatures, function(bytes) {
-            emit_varint(bytes, wasm.signatures.length);
-            for (sig of wasm.signatures) {
-                var params = sig.length - 1;
-                emit_varint(bytes, params);
-                for (var j = 0; j < sig.length; j++) {
-                    emit_u8(bytes, sig[j]);
-                }
-            }
-        });
+  addPadFunctionTable(size) {
+    this.pad = size;
+    return this;
+  }
+
+  addExplicitSection(bytes) {
+    this.explicit.push(bytes);
+    return this;
+  }
+
+  addType(type) {
+    // TODO: canonicalize types?
+    this.types.push(type);
+    return this.types.length - 1;
+  }
+
+  addFunction(name, type) {
+    let type_index = (typeof type) == "number" ? type : this.addType(type);
+    let func = new WasmFunctionBuilder(name, type_index);
+    func.index = this.functions.length;
+    this.functions.push(func);
+    return func;
+  }
+
+  addImportWithModule(module, name, type) {
+    let type_index = (typeof type) == "number" ? type : this.addType(type);
+    this.imports.push({module: module, name: name, type: type_index});
+    return this.imports.length - 1;
+  }
+
+  addImport(name, type) {
+    return this.addImportWithModule(name, undefined, type);
+  }
+
+  addDataSegment(addr, data, init) {
+    this.segments.push({addr: addr, data: data, init: init});
+    return this.segments.length - 1;
+  }
+
+  appendToTable(array) {
+    this.table.push(...array);
+    return this;
+  }
+
+  toArray(debug) {
+    let binary = new Binary;
+    let wasm = this;
+
+    // Add header
+    binary.emit_header();
+
+    // Add type section
+    if (wasm.types.length > 0) {
+      if (debug) print("emitting types @ " + binary.length);
+      binary.emit_section(kDeclTypes, section => {
+        section.emit_varint(wasm.types.length);
+        for (let type of wasm.types) {
+          section.emit_u8(kWasmFunctionTypeForm);
+          section.emit_varint(type.params.length);
+          for (let param of type.params) {
+            section.emit_u8(param);
+          }
+          section.emit_varint(type.results.length);
+          for (let result of type.results) {
+            section.emit_u8(result);
+          }
+        }
+      });
     }
 
     // Add imports section
     if (wasm.imports.length > 0) {
-        if (debug) print("emitting imports @ " + bytes.length);
-        emit_section(bytes, kDeclImportTable, function(bytes) {
-            emit_varint(bytes, wasm.imports.length);
-            for (imp of wasm.imports) {
-                emit_varint(bytes, imp.sig_index);
-                emit_string(bytes, imp.module);
-                emit_string(bytes, imp.name || '');
-            }
-        });
+      if (debug) print("emitting imports @ " + binary.length);
+      binary.emit_section(kDeclImports, section => {
+        section.emit_varint(wasm.imports.length);
+        for (let imp of wasm.imports) {
+          section.emit_varint(imp.type);
+          section.emit_string(imp.module);
+          section.emit_string(imp.name || '');
+        }
+      });
     }
 
-    // Add functions section
-    var names = false;
-    var exports = 0;
+    // Add functions declarations
+    let has_names = false;
+    let names = false;
+    let exports = 0;
     if (wasm.functions.length > 0) {
-        var has_names = false;
-
-        // emit function signatures
-        if (debug) print("emitting function sigs @ " + bytes.length);
-        emit_section(bytes, kDeclFunctionSignatures, function(bytes) {
-            emit_varint(bytes, wasm.functions.length);
-            for (func of wasm.functions) {
-              has_names = has_names || (func.name != undefined &&
-                                        func.name.length > 0);
-              exports += func.exports.length;
-
-              emit_varint(bytes, func.sig_index);
-            }
-        });
-
-        // emit function bodies
-        if (debug) print("emitting function bodies @ " + bytes.length);
-        emit_section(bytes, kDeclFunctionBodies, function(bytes) {
-            emit_varint(bytes, wasm.functions.length);
-            for (func of wasm.functions) {
-                // Function body length will be patched later.
-                var local_decls = [];
-                var l = func.locals;
-                if (l != undefined) {
-                  var local_decls_count = 0;
-                  if (l.i32_count > 0) {
-                    local_decls.push({count: l.i32_count, type: kAstI32});
-                  }
-                  if (l.i64_count > 0) {
-                    local_decls.push({count: l.i64_count, type: kAstI64});
-                  }
-                  if (l.f32_count > 0) {
-                    local_decls.push({count: l.f32_count, type: kAstF32});
-                  }
-                  if (l.f64_count > 0) {
-                    local_decls.push({count: l.f64_count, type: kAstF64});
-                  }
-                }
-                var header = new Array();
-
-                emit_varint(header, local_decls.length);
-                for (decl of local_decls) {
-                  emit_varint(header, decl.count);
-                  emit_u8(header, decl.type);
-                }
-
-                emit_varint(bytes, header.length + func.body.length);
-                emit_bytes(bytes, header);
-                emit_bytes(bytes, func.body);
-            }
-        });
+      if (debug) print("emitting function decls @ " + binary.length);
+      binary.emit_section(kDeclFunctions, section => {
+        section.emit_varint(wasm.functions.length);
+        for (let func of wasm.functions) {
+          has_names = has_names || (func.name != undefined &&
+                                   func.name.length > 0);
+          exports += func.exports.length;
+          section.emit_varint(func.type_index);
+        }
+      });
     }
 
-    // emit function names
-    if (has_names) {
-        if (debug) print("emitting names @ " + bytes.length);
-        emit_section(bytes, kDeclNames, function(bytes) {
-            emit_varint(bytes, wasm.functions.length);
-            for (func of wasm.functions) {
-                var name = func.name == undefined ? "" : func.name;
-               emit_string(bytes, name);
-               emit_u8(bytes, 0);  // local names count == 0
-            }
-        });
+    // Add table.
+    if (wasm.table.length > 0) {
+      if (debug) print("emitting table @ " + binary.length);
+      binary.emit_section(kDeclTable, section => {
+        section.emit_varint(wasm.table.length);
+        for (let index of wasm.table) {
+          section.emit_varint(index);
+        }
+      });
+    }
+
+    // Add memory section
+    if (wasm.memory != undefined) {
+      if (debug) print("emitting memory @ " + binary.length);
+      binary.emit_section(kDeclMemory, section => {
+        section.emit_varint(wasm.memory.min);
+        section.emit_varint(wasm.memory.max);
+        section.emit_u8(wasm.memory.exp ? 1 : 0);
+      });
+    }
+
+
+    // Add export table.
+    if (exports > 0) {
+      if (debug) print("emitting exports @ " + binary.length);
+      binary.emit_section(kDeclExports, section => {
+        section.emit_varint(exports);
+        for (let func of wasm.functions) {
+          for (let exp of func.exports) {
+            section.emit_varint(func.index);
+            section.emit_string(exp);
+          }
+        }
+      });
     }
 
     // Add start function section.
     if (wasm.start_index != undefined) {
-        if (debug) print("emitting start function @ " + bytes.length);
-        emit_section(bytes, kDeclStartFunction, function(bytes) {
-            emit_varint(bytes, wasm.start_index);
-        });
+      if (debug) print("emitting start function @ " + binary.length);
+      binary.emit_section(kDeclStart, section => {
+        section.emit_varint(wasm.start_index);
+      });
     }
 
-    if (wasm.function_table.length > 0) {
-        if (debug) print("emitting function table @ " + bytes.length);
-        emit_section(bytes, kDeclFunctionTable, function(bytes) {
-            emit_varint(bytes, wasm.function_table.length);
-            for (index of wasm.function_table) {
-                emit_varint(bytes, index);
+    // Add function bodies.
+    if (wasm.functions.length > 0) {
+      // emit function bodies
+      if (debug) print("emitting code @ " + binary.length);
+      binary.emit_section(kDeclCode, section => {
+        section.emit_varint(wasm.functions.length);
+        for (let func of wasm.functions) {
+          // Function body length will be patched later.
+          let local_decls = [];
+          let l = func.locals;
+          if (l != undefined) {
+            let local_decls_count = 0;
+            if (l.i32_count > 0) {
+              local_decls.push({count: l.i32_count, type: kAstI32});
             }
-        });
-    }
-
-    if (exports > 0) {
-        if (debug) print("emitting exports @ " + bytes.length);
-        emit_section(bytes, kDeclExportTable, function(bytes) {
-            emit_varint(bytes, exports);
-            for (func of wasm.functions) {
-                for (exp of func.exports) {
-                    emit_varint(bytes, func.index);
-                    emit_string(bytes, exp);
-                }
+            if (l.i64_count > 0) {
+              local_decls.push({count: l.i64_count, type: kAstI64});
             }
-        });
-    }
-
-    if (wasm.data_segments.length > 0) {
-        if (debug) print("emitting data segments @ " + bytes.length);
-        emit_section(bytes, kDeclDataSegments, function(bytes) {
-            emit_varint(bytes, wasm.data_segments.length);
-            for (seg of wasm.data_segments) {
-                emit_varint(bytes, seg.addr);
-                emit_varint(bytes, seg.data.length);
-                emit_bytes(bytes, seg.data);
+            if (l.f32_count > 0) {
+              local_decls.push({count: l.f32_count, type: kAstF32});
             }
-        });
+            if (l.f64_count > 0) {
+              local_decls.push({count: l.f64_count, type: kAstF64});
+            }
+          }
+
+          let header = new Binary;
+          header.emit_varint(local_decls.length);
+          for (let decl of local_decls) {
+            header.emit_varint(decl.count);
+            header.emit_u8(decl.type);
+          }
+
+          section.emit_varint(header.length + func.body.length);
+          section.emit_bytes(header);
+          section.emit_bytes(func.body);
+        }
+      });
     }
 
-    // Emit any explicitly added sections
-    for (exp of wasm.explicit) {
-        if (debug) print("emitting explicit @ " + bytes.length);
-        emit_bytes(bytes, exp);
+    // Add data segments.
+    if (wasm.segments.length > 0) {
+      if (debug) print("emitting data segments @ " + binary.length);
+      binary.emit_section(kDeclData, section => {
+        section.emit_varint(wasm.segments.length);
+        for (let seg of wasm.segments) {
+          section.emit_varint(seg.addr);
+          section.emit_varint(seg.data.length);
+          section.emit_bytes(seg.data);
+        }
+      });
+    }
+
+    // Add any explicitly added sections
+    for (let exp of wasm.explicit) {
+      if (debug) print("emitting explicit @ " + binary.length);
+      binary.emit_bytes(exp);
+    }
+
+    // Add function names.
+    if (has_names) {
+      if (debug) print("emitting names @ " + binary.length);
+      binary.emit_section(kDeclNames, section => {
+        section.emit_varint(wasm.functions.length);
+        for (let func of wasm.functions) {
+          var name = func.name == undefined ? "" : func.name;
+          section.emit_string(name);
+          section.emit_u8(0);  // local names count == 0
+        }
+      });
+    }
+
+    // Add an indirect function table pad section.
+    if (wasm.pad !== null) {
+      if (debug)
+        print("emitting indirect function table pad @ " + binary.length);
+      binary.emit_section(kDeclFunctionTablePad, section => {
+        section.emit_varint(wasm.pad);
+      });
     }
 
     // End the module.
-    if (debug) print("emitting end @ " + bytes.length);
-    emit_section(bytes, kDeclEnd, function(bytes) {});
+    if (debug) print("emitting end @ " + binary.length);
+    binary.emit_section(kDeclEnd, section => {});
 
-    return bytes;
-}
+    return binary;
+  }
 
-WasmModuleBuilder.prototype.toBuffer = function(debug) {
-    var bytes = this.toArray(debug);
-    var buffer = new ArrayBuffer(bytes.length);
-    var view = new Uint8Array(buffer);
-    for (var i = 0; i < bytes.length; i++) {
-        var val = bytes[i];
-        if ((typeof val) == "string") val = val.charCodeAt(0);
-        view[i] = val | 0;
+  toBuffer(debug) {
+    let bytes = this.toArray(debug);
+    let buffer = new ArrayBuffer(bytes.length);
+    let view = new Uint8Array(buffer);
+    for (let i = 0; i < bytes.length; i++) {
+      let val = bytes[i];
+      if ((typeof val) == "string") val = val.charCodeAt(0);
+      view[i] = val | 0;
     }
     return buffer;
-}
+  }
 
-WasmModuleBuilder.prototype.instantiate = function(ffi, memory) {
-    var buffer = this.toBuffer();
-    if (memory != undefined) {
-      return Wasm.instantiateModule(buffer, ffi, memory);
-    } else {
-      return Wasm.instantiateModule(buffer, ffi);
-    }
+  instantiate(...args) {
+    let module = new WebAssembly.Module(this.toBuffer());
+    let instance = new WebAssembly.Instance(module, ...args);
+    return instance;
+  }
 }
diff --git a/test/mjsunit/wasm/wasm-object-api.js b/test/mjsunit/wasm/wasm-object-api.js
index 2f25c66..510b571 100644
--- a/test/mjsunit/wasm/wasm-object-api.js
+++ b/test/mjsunit/wasm/wasm-object-api.js
@@ -10,3 +10,9 @@
 assertEquals("function", typeof Wasm.verifyFunction);
 assertEquals("function", typeof Wasm.instantiateModule);
 assertEquals("function", typeof Wasm.instantiateModuleFromAsm);
+assertFalse(undefined == Wasm.experimentalVersion);
+
+assertEquals('object', typeof WebAssembly);
+assertEquals('function', typeof WebAssembly.Module);
+assertEquals('function', typeof WebAssembly.Instance);
+assertEquals('function', typeof WebAssembly.compile);
diff --git a/test/mozilla/mozilla.gyp b/test/mozilla/mozilla.gyp
index 1202d28..0327dd8 100644
--- a/test/mozilla/mozilla.gyp
+++ b/test/mozilla/mozilla.gyp
@@ -13,8 +13,8 @@
             '../../src/d8.gyp:d8_run',
           ],
           'includes': [
-            '../../build/features.gypi',
-            '../../build/isolate.gypi',
+            '../../gypfiles/features.gypi',
+            '../../gypfiles/isolate.gypi',
           ],
           'sources': [
             'mozilla.isolate',
diff --git a/test/mozilla/mozilla.status b/test/mozilla/mozilla.status
index 0f7d4aa..d4eebee 100644
--- a/test/mozilla/mozilla.status
+++ b/test/mozilla/mozilla.status
@@ -59,11 +59,14 @@
 
   # TODO(turbofan): Causes timeouts since top-level code is optimized.
   'ecma_3/Statements/regress-324650': [PASS, NO_VARIANTS],
+  'ecma_3/Statements/regress-444979': [PASS, NO_VARIANTS],
   'ecma_3/Statements/regress-74474-002': [PASS, NO_VARIANTS],
   'ecma_3/Statements/regress-74474-003': [PASS, NO_VARIANTS],
   'js1_5/Regress/regress-111557': [PASS, NO_VARIANTS],
   'js1_5/Regress/regress-155081': [PASS, NO_VARIANTS],
   'js1_5/Regress/regress-155081-2': [PASS, NO_VARIANTS],
+  'js1_5/Regress/regress-159334': [PASS, NO_VARIANTS],
+  'js1_5/Regress/regress-321971': [PASS, NO_VARIANTS],
   'js1_5/Regress/regress-451322': [PASS, NO_VARIANTS],
 
   # TODO(turbofan): Large switch statements crash.
@@ -187,7 +190,7 @@
   'ecma_3/RegExp/regress-209067': [PASS, ['mode == debug', FAIL]],
   'js1_5/GC/regress-278725': [PASS, ['mode == debug', FAIL]],
   # http://b/issue?id=1206983
-  'js1_5/Regress/regress-367561-03': [PASS, ['mode == debug', FAIL]],
+  'js1_5/Regress/regress-367561-03': [PASS, ['mode == debug', FAIL], NO_VARIANTS],
   'ecma/Date/15.9.5.10-2': [PASS, FAIL, ['mode == debug', TIMEOUT, NO_VARIANTS]],
 
   # These tests create two Date objects just after each other and
@@ -239,7 +242,7 @@
   'js1_5/Array/regress-99120-01': [PASS, FAIL, NO_VARIANTS],
   'js1_5/Array/regress-99120-02': [PASS, FAIL],
   'js1_5/Regress/regress-347306-01': [PASS, FAIL],
-  'js1_5/Regress/regress-416628': [PASS, FAIL, ['mode == debug', TIMEOUT, NO_VARIANTS]],
+  'js1_5/Regress/regress-416628': [PASS, FAIL, ['mode == debug', TIMEOUT], NO_VARIANTS],
 
 
   # The following two tests assume that daylight savings time starts first
diff --git a/test/optimize_for_size.gyp b/test/optimize_for_size.gyp
index ac40ba8..047e3d8 100644
--- a/test/optimize_for_size.gyp
+++ b/test/optimize_for_size.gyp
@@ -16,8 +16,8 @@
             'webkit/webkit.gyp:webkit_run',
           ],
           'includes': [
-            '../build/features.gypi',
-            '../build/isolate.gypi',
+            '../gypfiles/features.gypi',
+            '../gypfiles/isolate.gypi',
           ],
           'sources': [
             'optimize_for_size.isolate',
diff --git a/test/perf.gyp b/test/perf.gyp
index ff84606..4f024f7 100644
--- a/test/perf.gyp
+++ b/test/perf.gyp
@@ -14,8 +14,8 @@
             '../src/d8.gyp:d8_run',
           ],
           'includes': [
-            '../build/features.gypi',
-            '../build/isolate.gypi',
+            '../gypfiles/features.gypi',
+            '../gypfiles/isolate.gypi',
           ],
           'sources': [
             'perf.isolate',
diff --git a/test/preparser/preparser.gyp b/test/preparser/preparser.gyp
index cb763d6..8e944ed 100644
--- a/test/preparser/preparser.gyp
+++ b/test/preparser/preparser.gyp
@@ -13,8 +13,8 @@
             '../../src/d8.gyp:d8_run',
           ],
           'includes': [
-            '../../build/features.gypi',
-            '../../build/isolate.gypi',
+            '../../gypfiles/features.gypi',
+            '../../gypfiles/isolate.gypi',
           ],
           'sources': [
             'preparser.isolate',
diff --git a/test/simdjs/simdjs.gyp b/test/simdjs/simdjs.gyp
index df0aa5e..c0c24dc 100644
--- a/test/simdjs/simdjs.gyp
+++ b/test/simdjs/simdjs.gyp
@@ -13,8 +13,8 @@
             '../../src/d8.gyp:d8_run',
           ],
           'includes': [
-            '../../build/features.gypi',
-            '../../build/isolate.gypi',
+            '../../gypfiles/features.gypi',
+            '../../gypfiles/isolate.gypi',
           ],
           'sources': [
             'simdjs.isolate',
diff --git a/test/test262/BUILD.gn b/test/test262/BUILD.gn
new file mode 100644
index 0000000..9aaa777
--- /dev/null
+++ b/test/test262/BUILD.gn
@@ -0,0 +1,34 @@
+# Copyright 2016 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("../../gni/isolate.gni")
+
+if (v8_test_isolation_mode != "noop") {
+  action("archive_test262") {
+    visibility = [ ":*" ]
+
+    script = "archive.py"
+
+    inputs = [
+      "list.py",
+    ]
+
+    sources = exec_script("list.py", [], "list lines")
+
+    outputs = [
+      "$target_gen_dir/test262_archiving.stamp",
+    ]
+
+    args = rebase_path(outputs, root_build_dir)
+  }
+}
+
+v8_isolate_run("test262") {
+  deps = [
+    ":archive_test262",
+    "../..:d8_run",
+  ]
+
+  isolate = "test262.isolate"
+}
diff --git a/test/test262/archive.py b/test/test262/archive.py
index c265b32..9a52d6c 100755
--- a/test/test262/archive.py
+++ b/test/test262/archive.py
@@ -4,7 +4,13 @@
 # found in the LICENSE file.
 
 import os
+import sys
 import tarfile
+import time
+
+# In GN we expect the path to a stamp file as an argument.
+if len(sys.argv) == 2:
+  STAMP_FILE = os.path.abspath(sys.argv[1])
 
 os.chdir(os.path.dirname(os.path.abspath(__file__)))
 
@@ -21,3 +27,10 @@
 
 with tarfile.open('data.tar', 'w') as tar:
   tar.add('data', filter=filter_git)
+
+# Workaround for GN. We can't specify the tarfile as output because it's
+# not in the product directory. Therefore we track running of this script
+# with an extra stamp file in the product directory.
+if len(sys.argv) == 2:
+  with open(STAMP_FILE, 'w') as f:
+    f.write(str(time.time()))
diff --git a/test/test262/detachArrayBuffer.js b/test/test262/detachArrayBuffer.js
new file mode 100644
index 0000000..adfece7
--- /dev/null
+++ b/test/test262/detachArrayBuffer.js
@@ -0,0 +1,7 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function $DETACHBUFFER(buffer) {
+  %ArrayBufferNeuter(buffer);
+}
diff --git a/test/test262/test262.gyp b/test/test262/test262.gyp
index 5d79add..2bdc6ce 100644
--- a/test/test262/test262.gyp
+++ b/test/test262/test262.gyp
@@ -13,8 +13,8 @@
             '../../src/d8.gyp:d8_run',
           ],
           'includes': [
-            '../../build/features.gypi',
-            '../../build/isolate.gypi',
+            '../../gypfiles/features.gypi',
+            '../../gypfiles/isolate.gypi',
           ],
           'sources': [
             'test262.isolate',
diff --git a/test/test262/test262.isolate b/test/test262/test262.isolate
index 0ac045a..4e14190 100644
--- a/test/test262/test262.isolate
+++ b/test/test262/test262.isolate
@@ -5,6 +5,7 @@
   'variables': {
     'files': [
       'data.tar',
+      'detachArrayBuffer.js',
       'harness-adapt.js',
       'test262.status',
       'testcfg.py',
diff --git a/test/test262/test262.status b/test/test262/test262.status
index 8cd4496..2933e15 100644
--- a/test/test262/test262.status
+++ b/test/test262/test262.status
@@ -71,6 +71,10 @@
   'language/expressions/assignment/S11.13.1_A6*': [FAIL],
 
   # https://bugs.chromium.org/p/v8/issues/detail?id=4709
+  'built-ins/Promise/reject-function-name': [FAIL],
+  'built-ins/Promise/resolve-function-name': [FAIL],
+  'built-ins/Promise/all/resolve-element-function-name': [FAIL],
+  'built-ins/Promise/executor-function-name': [FAIL],
   'built-ins/Proxy/revocable/revocation-function-name': [FAIL],
   'language/expressions/assignment/fn-name-lhs-cover': [FAIL],
   'language/expressions/assignment/fn-name-lhs-member': [FAIL],
@@ -100,41 +104,37 @@
   'language/asi/S7.9_A5.7_T1': [PASS, FAIL_OK],
 
   ###### BEGIN REGEXP SUBCLASSING SECTION ######
-  # Spec change in progress https://github.com/tc39/ecma262/pull/494
-  # RegExpBuiltinMatch reads flags from [[OriginalFlags]]
-  'built-ins/RegExp/prototype/Symbol.match/builtin-coerce-sticky': [FAIL],
-  'built-ins/RegExp/prototype/Symbol.match/builtin-get-global-err': [FAIL],
-  'built-ins/RegExp/prototype/Symbol.match/builtin-get-sticky-err': [FAIL],
-  'built-ins/RegExp/prototype/Symbol.match/builtin-success-g-set-lastindex': [FAIL],
-  'built-ins/RegExp/prototype/Symbol.match/builtin-success-g-set-lastindex-err': [FAIL],
-  'built-ins/RegExp/prototype/Symbol.match/coerce-sticky': [FAIL],
-  'built-ins/RegExp/prototype/Symbol.match/get-sticky-err': [FAIL],
-  'built-ins/RegExp/prototype/Symbol.replace/coerce-global': [FAIL],
-  'built-ins/RegExp/prototype/Symbol.replace/coerce-unicode': [FAIL],
-  'built-ins/RegExp/prototype/Symbol.replace/get-sticky-coerce': [FAIL],
-  'built-ins/RegExp/prototype/Symbol.replace/get-sticky-err': [SKIP],
-  'built-ins/RegExp/prototype/Symbol.search/get-sticky-coerce': [FAIL],
-  'built-ins/RegExp/prototype/Symbol.search/get-sticky-err': [FAIL],
-  'built-ins/RegExp/prototype/exec/get-sticky-coerce': [FAIL],
-  'built-ins/RegExp/prototype/exec/get-sticky-err': [FAIL],
-  'built-ins/RegExp/prototype/test/get-sticky-err': [FAIL],
-
-  # Missing lastIndex support
-  'built-ins/RegExp/prototype/Symbol.split/str-result-coerce-length-err': [FAIL],
-
   # Times out
-  'built-ins/RegExp/prototype/Symbol.split/str-coerce-lastindex': [SKIP],
   'built-ins/RegExp/prototype/Symbol.match/coerce-global': [SKIP],
-  'built-ins/RegExp/prototype/Symbol.match/builtin-coerce-global': [SKIP],
 
   # Sticky support busted
   'built-ins/RegExp/prototype/Symbol.replace/y-init-lastindex': [FAIL],
   'built-ins/RegExp/prototype/Symbol.replace/y-set-lastindex': [FAIL],
 
+  # https://code.google.com/p/v8/issues/detail?id=4504
+  # https://bugs.chromium.org/p/chromium/issues/detail?id=624318
+  'built-ins/RegExp/prototype/Symbol.match/builtin-failure-set-lastindex-err': [PASS, FAIL],
+  'built-ins/RegExp/prototype/Symbol.match/builtin-failure-y-set-lastindex-err': [PASS, FAIL],
+  'built-ins/RegExp/prototype/Symbol.match/builtin-success-g-set-lastindex-err': [SKIP],
+  'built-ins/RegExp/prototype/Symbol.match/builtin-success-y-set-lastindex-err': [PASS, FAIL],
+  'built-ins/RegExp/prototype/Symbol.match/g-init-lastindex-err': [PASS, FAIL],
+  'built-ins/RegExp/prototype/Symbol.match/g-match-empty-set-lastindex-err': [PASS, FAIL],
+  'built-ins/RegExp/prototype/Symbol.match/y-fail-lastindex-no-write': [PASS, FAIL],
+  'built-ins/RegExp/prototype/Symbol.replace/g-init-lastindex-err': [PASS, FAIL],
+  'built-ins/RegExp/prototype/Symbol.replace/y-fail-lastindex-no-write': [PASS, FAIL],
+  'built-ins/RegExp/prototype/Symbol.search/set-lastindex-init-err': [PASS, FAIL],
+  'built-ins/RegExp/prototype/Symbol.search/set-lastindex-restore-err': [PASS, FAIL],
+  'built-ins/RegExp/prototype/exec/y-fail-lastindex-no-write': [PASS, FAIL],
+  'built-ins/RegExp/prototype/test/y-fail-lastindex-no-write': [PASS, FAIL],
+
   # SKIP rather than FAIL, as the test checks for an exception which
   # happens to be thrown for some other reason.
   'built-ins/RegExp/prototype/Symbol.split/str-result-get-length-err': [SKIP],
 
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5123
+  'built-ins/RegExp/prototype/Symbol.replace/coerce-global': [FAIL],
+  'built-ins/RegExp/prototype/Symbol.replace/coerce-unicode': [FAIL],
+
   ###### END REGEXP SUBCLASSING SECTION ######
 
   # https://code.google.com/p/v8/issues/detail?id=4360
@@ -142,71 +142,353 @@
   'intl402/DateTimeFormat/12.1.1_1': [FAIL],
   'intl402/NumberFormat/11.1.1_1': [FAIL],
 
-  # https://code.google.com/p/v8/issues/detail?id=4476
-  'built-ins/String/prototype/toLocaleLowerCase/special_casing_conditional': [FAIL],
-  'built-ins/String/prototype/toLocaleLowerCase/supplementary_plane': [FAIL],
-  'built-ins/String/prototype/toLowerCase/special_casing_conditional': [FAIL],
-  'built-ins/String/prototype/toLowerCase/supplementary_plane': [FAIL],
-  'built-ins/String/prototype/toLocaleUpperCase/supplementary_plane': [FAIL],
-  'built-ins/String/prototype/toUpperCase/supplementary_plane': [FAIL],
-
-  # https://code.google.com/p/v8/issues/detail?id=4477
-  'intl402/String/prototype/toLocaleLowerCase/special_casing_Azeri': [FAIL],
-  'intl402/String/prototype/toLocaleLowerCase/special_casing_Lithuanian': [FAIL],
-  'intl402/String/prototype/toLocaleLowerCase/special_casing_Turkish': [FAIL],
-  'intl402/String/prototype/toLocaleUpperCase/special_casing_Azeri': [FAIL],
-  'intl402/String/prototype/toLocaleUpperCase/special_casing_Lithuanian': [FAIL],
-  'intl402/String/prototype/toLocaleUpperCase/special_casing_Turkish': [FAIL],
-
-  # https://bugs.chromium.org/p/v8/issues/detail?id=4628
-  'language/eval-code/non-definable-function-with-variable': [FAIL],
-  'language/eval-code/non-definable-function-with-function': [FAIL],
-
-  # https://bugs.chromium.org/p/v8/issues/detail?id=4592
-  'built-ins/ArrayBuffer/length-is-absent': [FAIL],
-  'built-ins/ArrayBuffer/length-is-not-number': [FAIL],
-  'built-ins/ArrayBuffer/positive-integer-length': [FAIL],
-  'language/statements/class/subclass/builtin-objects/ArrayBuffer/regular-subclassing': [FAIL],
-
-  # https://bugs.chromium.org/p/v8/issues/detail?id=4633
-  'built-ins/Promise/reject-function-name': [FAIL],
-  'built-ins/Promise/resolve-function-name': [FAIL],
-  'built-ins/Promise/all/resolve-element-function-name': [FAIL],
-  'built-ins/Promise/executor-function-name': [FAIL],
-
-  # https://bugs.chromium.org/p/v8/issues/detail?id=4634
-  'built-ins/DataView/prototype/setFloat64/index-check-before-value-conversion': [FAIL],
-  'built-ins/DataView/prototype/setFloat32/index-check-before-value-conversion': [FAIL],
-  'built-ins/DataView/prototype/setInt16/index-check-before-value-conversion': [FAIL],
-  'built-ins/DataView/prototype/setInt32/index-check-before-value-conversion': [FAIL],
-  'built-ins/DataView/prototype/setUint16/index-check-before-value-conversion': [FAIL],
-  'built-ins/DataView/prototype/setUint32/index-check-before-value-conversion': [FAIL],
-  'built-ins/DataView/prototype/setUint8/index-check-before-value-conversion': [FAIL],
-  'built-ins/DataView/prototype/setInt8/index-check-before-value-conversion': [FAIL],
-
-  # https://bugs.chromium.org/p/v8/issues/detail?id=4706
-  'language/statements/class/subclass/builtin-objects/NativeError/EvalError-message': [FAIL],
-  'language/statements/class/subclass/builtin-objects/NativeError/RangeError-message': [FAIL],
-  'language/statements/class/subclass/builtin-objects/NativeError/ReferenceError-message': [FAIL],
-  'language/statements/class/subclass/builtin-objects/NativeError/SyntaxError-message': [FAIL],
-  'language/statements/class/subclass/builtin-objects/NativeError/TypeError-message': [FAIL],
-  'language/statements/class/subclass/builtin-objects/NativeError/URIError-message': [FAIL],
-  'language/statements/class/subclass/builtin-objects/Error/message-property-assignment': [FAIL],
-
-  # https://code.google.com/p/chromium/issues/detail?id=581577
-  'built-ins/RegExp/prototype/source/15.10.7.1-1': [FAIL],
-  'built-ins/RegExp/prototype/global/15.10.7.2-1': [FAIL],
-  'built-ins/RegExp/prototype/ignoreCase/15.10.7.3-1': [FAIL],
-  'built-ins/RegExp/prototype/multiline/15.10.7.4-1': [FAIL],
-
   # https://bugs.chromium.org/p/v8/issues/detail?id=4727
-  'built-ins/TypedArrays/length-arg-is-undefined-throws': [FAIL],
   'built-ins/TypedArrays/length-arg-is-symbol-throws': [FAIL],
-  'built-ins/TypedArrays/length-arg-is-float-throws-rangeerror': [FAIL],
-  'built-ins/TypedArrays/length-arg-is-nan-throws-rangeerror': [FAIL],
 
   # https://bugs.chromium.org/p/v8/issues/detail?id=4784
-  'built-ins/TypedArrays/buffer-arg-defined-negative-length': [FAIL],
+  'built-ins/TypedArray/prototype/set/typedarray-arg-negative-integer-offset-throws': [FAIL],
+  'built-ins/TypedArray/prototype/set/array-arg-negative-integer-offset-throws': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=4901
+  'built-ins/TypedArrays/internals/DefineOwnProperty/key-is-greater-than-last-index': [FAIL],
+  'built-ins/TypedArrays/internals/DefineOwnProperty/key-is-lower-than-zero': [FAIL],
+  'built-ins/TypedArrays/internals/DefineOwnProperty/key-is-minus-zero': [FAIL],
+  'built-ins/TypedArrays/internals/DefineOwnProperty/key-is-not-integer': [FAIL],
+  'built-ins/TypedArrays/internals/DefineOwnProperty/key-is-numericindex-desc-not-writable': [FAIL],
+  'built-ins/TypedArrays/internals/Set/key-is-minus-zero': [FAIL],
+  'built-ins/TypedArrays/internals/Set/key-is-not-integer': [FAIL],
+  'built-ins/TypedArrays/internals/Set/key-is-out-of-bounds': [FAIL],
+  'built-ins/TypedArrays/internals/Set/tonumber-value-throws': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=4895
+  'built-ins/TypedArrays/internals/HasProperty/detached-buffer': [FAIL],
+  'built-ins/TypedArrays/internals/Set/detached-buffer': [FAIL],
+  'built-ins/TypedArrays/internals/GetOwnProperty/detached-buffer': [FAIL],
+  'built-ins/TypedArrays/internals/Get/detached-buffer': [FAIL],
+  'built-ins/TypedArrays/internals/DefineOwnProperty/detached-buffer': [FAIL],
+  # Some TypedArray methods throw due to the same bug, from Get
+  'built-ins/TypedArray/prototype/every/callbackfn-detachbuffer': [FAIL],
+  'built-ins/TypedArray/prototype/filter/callbackfn-detachbuffer': [FAIL],
+  'built-ins/TypedArray/prototype/find/predicate-may-detach-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/findIndex/predicate-may-detach-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/forEach/callbackfn-detachbuffer': [FAIL],
+  'built-ins/TypedArray/prototype/map/callbackfn-detachbuffer': [FAIL],
+  'built-ins/TypedArray/prototype/reduce/callbackfn-detachbuffer': [FAIL],
+  'built-ins/TypedArray/prototype/reduceRight/callbackfn-detachbuffer': [FAIL],
+  'built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-throws': [FAIL],
+  'built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-tointeger-offset-throws': [FAIL],
+  'built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-throws': [FAIL],
+  'built-ins/TypedArray/prototype/set/typedarray-arg-srcbuffer-detached-during-tointeger-offset-throws': [FAIL],
+  'built-ins/TypedArray/prototype/set/typedarray-arg-targetbuffer-detached-during-tointeger-offset-throws': [FAIL],
+  'built-ins/TypedArray/prototype/slice/detached-buffer-custom-ctor-other-targettype': [FAIL],
+  'built-ins/TypedArray/prototype/slice/detached-buffer-custom-ctor-same-targettype': [FAIL],
+  'built-ins/TypedArray/prototype/slice/detached-buffer-get-ctor': [FAIL],
+  'built-ins/TypedArray/prototype/slice/detached-buffer-speciesctor-get-species-custom-ctor-throws': [FAIL],
+  'built-ins/TypedArray/prototype/some/callbackfn-detachbuffer': [FAIL],
+  'built-ins/TypedArray/prototype/sort/detached-buffer-comparefn': [FAIL],
+  # DataView functions should also throw on detached buffers
+  'built-ins/DataView/prototype/getFloat32/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/getFloat32/detached-buffer-before-outofrange-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/getFloat64/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/getFloat64/detached-buffer-before-outofrange-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/getInt16/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/getInt16/detached-buffer-before-outofrange-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/getInt32/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/getInt32/detached-buffer-before-outofrange-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/getInt8/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/getInt8/detached-buffer-before-outofrange-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/getUint16/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/getUint16/detached-buffer-before-outofrange-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/getUint32/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/getUint32/detached-buffer-before-outofrange-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/getUint8/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/getUint8/detached-buffer-before-outofrange-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/setFloat32/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/setFloat32/detached-buffer-before-outofrange-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/setFloat64/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/setFloat64/detached-buffer-before-outofrange-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/setInt16/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/setInt16/detached-buffer-before-outofrange-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/setInt32/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/setInt32/detached-buffer-before-outofrange-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/setInt8/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/setInt8/detached-buffer-before-outofrange-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/setUint16/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/setUint16/detached-buffer-before-outofrange-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/setUint32/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/setUint32/detached-buffer-before-outofrange-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/setUint8/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/setUint8/detached-buffer-before-outofrange-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/byteLength/detached-buffer': [FAIL],
+  'built-ins/DataView/prototype/byteOffset/detached-buffer': [FAIL],
+  'built-ins/DataView/detached-buffer': [FAIL],
+  'built-ins/ArrayBuffer/prototype/byteLength/detached-buffer': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=4648
+  'built-ins/TypedArray/prototype/copyWithin/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/entries/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/every/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/fill/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/filter/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/find/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/findIndex/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/forEach/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/includes/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/indexOf/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/join/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/keys/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/lastIndexOf/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/map/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/reverse/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/slice/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/some/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/sort/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/subarray/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/toLocaleString/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/toString/detached-buffer': [FAIL],
+  'built-ins/TypedArray/prototype/values/detached-buffer': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=4034
+  'built-ins/ThrowTypeError/unique-per-realm-function-proto': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=4231
+  'language/eval-code/direct/var-env-lower-lex-catch-non-strict': [FAIL],
+  'language/statements/try/early-catch-lex': [FAIL],
+  'language/statements/try/early-catch-var': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=4951
+  'language/expressions/assignment/dstr-array-elem-iter-rtrn-close': [FAIL],
+  'language/expressions/assignment/dstr-array-elem-iter-rtrn-close-err': [FAIL],
+  'language/expressions/assignment/dstr-array-elem-iter-rtrn-close-null': [FAIL],
+  'language/expressions/assignment/dstr-array-elem-iter-thrw-close': [FAIL],
+  'language/expressions/assignment/dstr-array-elem-iter-thrw-close-err': [FAIL],
+  'language/expressions/assignment/dstr-array-elem-trlg-iter-list-rtrn-close': [FAIL],
+  'language/expressions/assignment/dstr-array-elem-trlg-iter-list-rtrn-close-err': [FAIL],
+  'language/expressions/assignment/dstr-array-elem-trlg-iter-list-rtrn-close-null': [FAIL],
+  'language/expressions/assignment/dstr-array-elem-trlg-iter-list-thrw-close': [FAIL],
+  'language/expressions/assignment/dstr-array-elem-trlg-iter-list-thrw-close-err': [FAIL],
+  'language/expressions/assignment/dstr-array-elem-trlg-iter-rest-rtrn-close': [FAIL],
+  'language/expressions/assignment/dstr-array-elem-trlg-iter-rest-rtrn-close-err': [FAIL],
+  'language/expressions/assignment/dstr-array-elem-trlg-iter-rest-rtrn-close-null': [FAIL],
+  'language/expressions/assignment/dstr-array-elem-trlg-iter-rest-thrw-close': [FAIL],
+  'language/expressions/assignment/dstr-array-elem-trlg-iter-rest-thrw-close-err': [FAIL],
+  'language/expressions/assignment/dstr-array-rest-iter-rtrn-close': [FAIL],
+  'language/expressions/assignment/dstr-array-rest-iter-rtrn-close-err': [FAIL],
+  'language/expressions/assignment/dstr-array-rest-iter-rtrn-close-null': [FAIL],
+  'language/expressions/assignment/dstr-array-rest-iter-thrw-close': [FAIL],
+  'language/expressions/assignment/dstr-array-rest-iter-thrw-close-err': [FAIL],
+  'language/expressions/assignment/dstr-array-rest-lref-err': [FAIL],
+  'language/statements/for-of/dstr-array-elem-iter-rtrn-close': [FAIL],
+  'language/statements/for-of/dstr-array-elem-iter-rtrn-close-err': [FAIL],
+  'language/statements/for-of/dstr-array-elem-iter-rtrn-close-null': [FAIL],
+  'language/statements/for-of/dstr-array-elem-iter-thrw-close': [FAIL],
+  'language/statements/for-of/dstr-array-elem-iter-thrw-close-err': [FAIL],
+  'language/statements/for-of/dstr-array-elem-trlg-iter-list-rtrn-close': [FAIL],
+  'language/statements/for-of/dstr-array-elem-trlg-iter-list-rtrn-close-err': [FAIL],
+  'language/statements/for-of/dstr-array-elem-trlg-iter-list-rtrn-close-null': [FAIL],
+  'language/statements/for-of/dstr-array-elem-trlg-iter-list-thrw-close': [FAIL],
+  'language/statements/for-of/dstr-array-elem-trlg-iter-list-thrw-close-err': [FAIL],
+  'language/statements/for-of/dstr-array-elem-trlg-iter-rest-rtrn-close': [FAIL],
+  'language/statements/for-of/dstr-array-elem-trlg-iter-rest-rtrn-close-err': [FAIL],
+  'language/statements/for-of/dstr-array-elem-trlg-iter-rest-rtrn-close-null': [FAIL],
+  'language/statements/for-of/dstr-array-elem-trlg-iter-rest-thrw-close': [FAIL],
+  'language/statements/for-of/dstr-array-elem-trlg-iter-rest-thrw-close-err': [FAIL],
+  'language/statements/for-of/dstr-array-rest-iter-rtrn-close': [FAIL],
+  'language/statements/for-of/dstr-array-rest-iter-rtrn-close-err': [FAIL],
+  'language/statements/for-of/dstr-array-rest-iter-rtrn-close-null': [FAIL],
+  'language/statements/for-of/dstr-array-rest-iter-thrw-close': [FAIL],
+  'language/statements/for-of/dstr-array-rest-iter-thrw-close-err': [FAIL],
+  'language/statements/for-of/dstr-array-rest-lref-err': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=896
+  'language/literals/regexp/early-err-pattern': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=4628
+  'language/eval-code/direct/non-definable-function-with-function': [FAIL],
+  'language/eval-code/direct/non-definable-function-with-variable': [FAIL],
+  'language/eval-code/indirect/non-definable-function-with-function': [FAIL],
+  'language/eval-code/indirect/non-definable-function-with-variable': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=4124
+  'built-ins/Simd/*': [SKIP],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=4958
+  'built-ins/Function/prototype/toString/Function': [FAIL],
+  'built-ins/Function/prototype/toString/GeneratorFunction': [FAIL],
+  'built-ins/Function/prototype/toString/function-declaration': [FAIL],
+  'built-ins/Function/prototype/toString/function-declaration-non-simple-parameter-list': [FAIL],
+  'built-ins/Function/prototype/toString/function-expression': [FAIL],
+  'built-ins/Function/prototype/toString/generator-function-declaration': [FAIL],
+  'built-ins/Function/prototype/toString/generator-function-expression': [FAIL],
+  'built-ins/Function/prototype/toString/generator-method': [FAIL],
+  'built-ins/Function/prototype/toString/getter-class': [FAIL],
+  'built-ins/Function/prototype/toString/getter-class-static': [FAIL],
+  'built-ins/Function/prototype/toString/getter-object': [FAIL],
+  'built-ins/Function/prototype/toString/line-terminator-normalisation-CR': [FAIL],
+  'built-ins/Function/prototype/toString/line-terminator-normalisation-CR-LF': [FAIL],
+  'built-ins/Function/prototype/toString/line-terminator-normalisation-LF': [FAIL],
+  'built-ins/Function/prototype/toString/method-class': [FAIL],
+  'built-ins/Function/prototype/toString/method-class-static': [FAIL],
+  'built-ins/Function/prototype/toString/method-computed-property-name': [FAIL],
+  'built-ins/Function/prototype/toString/method-object': [FAIL],
+  'built-ins/Function/prototype/toString/setter-class': [FAIL],
+  'built-ins/Function/prototype/toString/setter-class-static': [FAIL],
+  'built-ins/Function/prototype/toString/setter-object': [FAIL],
+  'built-ins/Function/prototype/toString/unicode': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=1569
+  'language/module-code/*': [SKIP],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5111
+  'annexB/language/function-code/block-decl-func-skip-param': [FAIL],
+  'annexB/language/function-code/if-decl-else-decl-a-func-skip-param': [FAIL],
+  'annexB/language/function-code/if-decl-else-decl-b-func-skip-param': [FAIL],
+  'annexB/language/function-code/if-decl-else-stmt-func-skip-param': [FAIL],
+  'annexB/language/function-code/if-decl-no-else-func-skip-param': [FAIL],
+  'annexB/language/function-code/if-stmt-else-decl-func-skip-param': [FAIL],
+  'annexB/language/function-code/switch-case-func-skip-param': [FAIL],
+  'annexB/language/function-code/switch-dflt-func-skip-param': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5112
+  'language/statements/try/scope-catch-block-lex-open': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5012
+  'intl402/Intl/getCanonicalLocales/*': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5113
+  'built-ins/TypedArray/prototype/toLocaleString/calls-tolocalestring-from-each-value': [FAIL],
+  'built-ins/TypedArray/prototype/toLocaleString/calls-tostring-from-each-value': [FAIL],
+  'built-ins/TypedArray/prototype/toLocaleString/calls-valueof-from-each-value': [FAIL],
+  'built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-firstelement-tolocalestring': [FAIL],
+  'built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-firstelement-tostring': [FAIL],
+  'built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-firstelement-valueof': [FAIL],
+  'built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-nextelement-tolocalestring': [FAIL],
+  'built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-nextelement-tostring': [FAIL],
+  'built-ins/TypedArray/prototype/toLocaleString/return-abrupt-from-nextelement-valueof': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5115
+  'language/statements/class/subclass/class-definition-null-proto-missing-return-override': [FAIL],
+  'language/statements/class/subclass/class-definition-null-proto-this': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5116
+  'built-ins/Object/internals/DefineOwnProperty/nan-equivalence': [PASS, FAIL],
+  'built-ins/TypedArray/prototype/fill/fill-values-conversion-operations-consistent-nan': [PASS, FAIL],
+  'built-ins/TypedArrays/internals/DefineOwnProperty/conversion-operation-consistent-nan': [PASS, FAIL],
+  'built-ins/TypedArrays/internals/Set/conversion-operation-consistent-nan': [PASS, FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5070
+  'annexB/built-ins/Object/prototype/__defineGetter__/define-non-configurable': [FAIL],
+  'annexB/built-ins/Object/prototype/__defineGetter__/define-non-extensible': [FAIL],
+  'annexB/built-ins/Object/prototype/__defineGetter__/this-non-obj': [FAIL],
+  'annexB/built-ins/Object/prototype/__defineSetter__/define-non-configurable': [FAIL],
+  'annexB/built-ins/Object/prototype/__defineSetter__/define-non-extensible': [FAIL],
+  'annexB/built-ins/Object/prototype/__defineSetter__/this-non-obj': [FAIL],
+  'annexB/built-ins/Object/prototype/__lookupGetter__/this-non-obj': [FAIL],
+  'annexB/built-ins/Object/prototype/__lookupSetter__/this-non-obj': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5120
+  'built-ins/DataView/negative-bytelength-throws': [FAIL],
+  'built-ins/DataView/prototype/getFloat32/toindex-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/getFloat64/toindex-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/getInt16/toindex-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/getInt32/toindex-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/getInt8/toindex-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/getUint16/toindex-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/getUint32/toindex-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/getUint8/toindex-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/setFloat32/no-value-arg': [FAIL],
+  'built-ins/DataView/prototype/setFloat32/toindex-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/setFloat64/no-value-arg': [FAIL],
+  'built-ins/DataView/prototype/setFloat64/toindex-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/setInt16/no-value-arg': [FAIL],
+  'built-ins/DataView/prototype/setInt16/toindex-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/setInt32/no-value-arg': [FAIL],
+  'built-ins/DataView/prototype/setInt32/toindex-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/setInt8/no-value-arg': [FAIL],
+  'built-ins/DataView/prototype/setInt8/toindex-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/setUint16/no-value-arg': [FAIL],
+  'built-ins/DataView/prototype/setUint16/toindex-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/setUint32/no-value-arg': [FAIL],
+  'built-ins/DataView/prototype/setUint32/toindex-byteoffset': [FAIL],
+  'built-ins/DataView/prototype/setUint8/no-value-arg': [FAIL],
+  'built-ins/DataView/prototype/setUint8/toindex-byteoffset': [FAIL],
+  'built-ins/DataView/toindex-byteoffset': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5121
+  'language/expressions/assignment/destructuring/obj-prop-__proto__dup': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5124
+  'built-ins/TypedArrays/length-arg-toindex-length': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=4973
+  'language/literals/numeric/non-octal-decimal-integer-strict': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5130
+  'annexB/built-ins/Object/prototype/__lookupGetter__/lookup-own-data': [FAIL],
+  'annexB/built-ins/Object/prototype/__lookupGetter__/lookup-own-get-err': [FAIL],
+  'annexB/built-ins/Object/prototype/__lookupGetter__/lookup-own-proto-err': [FAIL],
+  'annexB/built-ins/Object/prototype/__lookupGetter__/lookup-proto-data': [FAIL],
+  'annexB/built-ins/Object/prototype/__lookupGetter__/lookup-proto-get-err': [FAIL],
+  'annexB/built-ins/Object/prototype/__lookupGetter__/lookup-proto-proto-err': [FAIL],
+  'annexB/built-ins/Object/prototype/__lookupSetter__/lookup-own-data': [FAIL],
+  'annexB/built-ins/Object/prototype/__lookupSetter__/lookup-own-get-err': [FAIL],
+  'annexB/built-ins/Object/prototype/__lookupSetter__/lookup-own-proto-err': [FAIL],
+  'annexB/built-ins/Object/prototype/__lookupSetter__/lookup-proto-data': [FAIL],
+  'annexB/built-ins/Object/prototype/__lookupSetter__/lookup-proto-get-err': [FAIL],
+  'annexB/built-ins/Object/prototype/__lookupSetter__/lookup-proto-proto-err': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5134
+  'built-ins/Array/prototype/concat/is-concat-spreadable-is-array-proxy-revoked': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=4451
+  'annexB/language/eval-code/direct/global-block-decl-eval-global-exsting-global-init': [FAIL],
+  'annexB/language/eval-code/direct/global-if-decl-else-decl-a-eval-global-exsting-global-init': [FAIL],
+  'annexB/language/eval-code/direct/global-if-decl-else-decl-b-eval-global-exsting-global-init': [FAIL],
+  'annexB/language/eval-code/direct/global-if-decl-else-stmt-eval-global-exsting-global-init': [FAIL],
+  'annexB/language/eval-code/direct/global-if-decl-no-else-eval-global-exsting-global-init': [FAIL],
+  'annexB/language/eval-code/direct/global-if-stmt-else-decl-eval-global-exsting-global-init': [FAIL],
+  'annexB/language/eval-code/direct/global-switch-case-eval-global-exsting-global-init': [FAIL],
+  'annexB/language/eval-code/direct/global-switch-dflt-eval-global-exsting-global-init': [FAIL],
+  'annexB/language/eval-code/indirect/global-block-decl-eval-global-exsting-global-init': [FAIL],
+  'annexB/language/eval-code/indirect/global-if-decl-else-decl-a-eval-global-exsting-global-init': [FAIL],
+  'annexB/language/eval-code/indirect/global-if-decl-else-decl-b-eval-global-exsting-global-init': [FAIL],
+  'annexB/language/eval-code/indirect/global-if-decl-else-stmt-eval-global-exsting-global-init': [FAIL],
+  'annexB/language/eval-code/indirect/global-if-decl-no-else-eval-global-exsting-global-init': [FAIL],
+  'annexB/language/eval-code/indirect/global-if-stmt-else-decl-eval-global-exsting-global-init': [FAIL],
+  'annexB/language/eval-code/indirect/global-switch-case-eval-global-exsting-global-init': [FAIL],
+  'annexB/language/eval-code/indirect/global-switch-dflt-eval-global-exsting-global-init': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5135
+  'annexB/language/eval-code/direct/func-block-decl-eval-func-block-scoping': [FAIL],
+  'annexB/language/eval-code/direct/func-if-decl-else-decl-a-eval-func-block-scoping': [FAIL],
+  'annexB/language/eval-code/direct/func-if-decl-else-decl-b-eval-func-block-scoping': [FAIL],
+  'annexB/language/eval-code/direct/func-if-decl-else-stmt-eval-func-block-scoping': [FAIL],
+  'annexB/language/eval-code/direct/func-if-decl-no-else-eval-func-block-scoping': [FAIL],
+  'annexB/language/eval-code/direct/func-if-stmt-else-decl-eval-func-block-scoping': [FAIL],
+  'annexB/language/eval-code/direct/func-switch-case-eval-func-block-scoping': [FAIL],
+  'annexB/language/eval-code/direct/func-switch-dflt-eval-func-block-scoping': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5136
+  'annexB/language/comments/multi-line-html-close': [FAIL],
+  'annexB/language/comments/single-line-html-close': [FAIL],
+  'annexB/language/comments/single-line-html-close-asi': [FAIL],
+  'annexB/language/comments/single-line-html-open': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5137
+  'annexB/built-ins/RegExp/prototype/compile/flags-undefined': [FAIL],
+  'annexB/built-ins/RegExp/prototype/compile/pattern-regexp-distinct': [FAIL],
+  'annexB/built-ins/RegExp/prototype/compile/pattern-regexp-same': [FAIL],
+  'annexB/built-ins/RegExp/prototype/compile/pattern-undefined': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5138
+  'annexB/built-ins/RegExp/prototype/compile/pattern-regexp-immutable-lastindex': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5139
+  'annexB/built-ins/Date/prototype/setYear/time-clip': [FAIL],
+  'annexB/built-ins/Date/prototype/setYear/year-number-relative': [FAIL],
+
+  # https://bugs.chromium.org/p/v8/issues/detail?id=5140
+  'annexB/built-ins/String/prototype/substr/start-to-int-err': [FAIL],
 
   ######################## NEEDS INVESTIGATION ###########################
 
@@ -215,13 +497,10 @@
   # incompatibilities if the test cases turn out to be broken or ambiguous.
   # Some of these are related to v8:4361 in being visible side effects from Intl.
   'intl402/6.2.3': [FAIL],
-  'intl402/9.2.1_2': [FAIL],
-  'intl402/9.2.6_2': [FAIL],
   'intl402/Collator/10.1.2.1_4': [FAIL],
   'intl402/Collator/10.1.2_a': [PASS, FAIL],
   'intl402/Collator/10.2.3_b': [PASS, FAIL],
   'intl402/Collator/prototype/10.3_a': [FAIL],
-  'intl402/DateTimeFormat/12.1.1': [FAIL],
   'intl402/DateTimeFormat/12.1.2': [PASS, FAIL],
   'intl402/DateTimeFormat/12.1.2.1_4': [FAIL],
   'intl402/DateTimeFormat/12.2.3_b': [FAIL],
@@ -239,36 +518,46 @@
   # https://code.google.com/p/v8/issues/detail?id=4693
   'language/block-scope/syntax/redeclaration-in-block/attempt-to-redeclare-function-declaration-with-function-declaration': [PASS, FAIL_SLOPPY],
 
-  ############################ INVALID TESTS #############################
+  # https://bugs.chromium.org/p/v8/issues/detail?id=4953
+  'built-ins/TypedArray/prototype/subarray/speciesctor-get-ctor': [FAIL],
+  'built-ins/TypedArray/prototype/subarray/speciesctor-get-ctor-abrupt': [FAIL],
+  'built-ins/TypedArray/prototype/subarray/speciesctor-get-ctor-inherited': [FAIL],
+  'built-ins/TypedArray/prototype/subarray/speciesctor-get-ctor-returns-throws': [FAIL],
+  'built-ins/TypedArray/prototype/subarray/speciesctor-get-species': [FAIL],
+  'built-ins/TypedArray/prototype/subarray/speciesctor-get-species-abrupt': [FAIL],
+  'built-ins/TypedArray/prototype/subarray/speciesctor-get-species-custom-ctor': [FAIL],
+  'built-ins/TypedArray/prototype/subarray/speciesctor-get-species-custom-ctor-invocation': [FAIL],
+  'built-ins/TypedArray/prototype/subarray/speciesctor-get-species-custom-ctor-returns-another-instance': [FAIL],
+  'built-ins/TypedArray/prototype/subarray/speciesctor-get-species-custom-ctor-throws': [FAIL],
+  'built-ins/TypedArray/prototype/subarray/speciesctor-get-species-returns-throws': [FAIL],
 
-  # The reference value calculated by Test262 is incorrect if you run these
-  # tests in PST/PDT between first Sunday in March and first Sunday in April.
-  # The DST switch was moved in 2007 whereas Test262 bases the reference value
-  # on 2000. Test262 Bug: https://bugs.ecmascript.org/show_bug.cgi?id=293
-  'built-ins/Date/S15.9.3.1_A5_T1': [PASS, FAIL_OK],
-  'built-ins/Date/S15.9.3.1_A5_T2': [PASS, FAIL_OK],
-  'built-ins/Date/S15.9.3.1_A5_T3': [PASS, FAIL_OK],
-  'built-ins/Date/S15.9.3.1_A5_T4': [PASS, FAIL_OK],
-  'built-ins/Date/S15.9.3.1_A5_T5': [PASS, FAIL_OK],
-  'built-ins/Date/S15.9.3.1_A5_T6': [PASS, FAIL_OK],
+  # We do not expose Array.prototype.values due to webcompat issues.
+  # Most recent incompatability: https://crbug.com/615873
+  # https://code.google.com/p/v8/issues/detail?id=4247
+  'built-ins/Array/prototype/Symbol.iterator': [FAIL],
+  'built-ins/Array/prototype/values/returns-iterator': [FAIL],
+  'built-ins/Array/prototype/values/returns-iterator-from-object': [FAIL],
+  'built-ins/Array/prototype/values/prop-desc': [FAIL],
+  'built-ins/Array/prototype/values/name': [FAIL],
+  'built-ins/Array/prototype/values/length': [FAIL],
+  'built-ins/Array/prototype/values/iteration': [FAIL],
+  'built-ins/Array/prototype/values/iteration-mutable': [FAIL],
+  'built-ins/Array/prototype/Symbol.unscopables/value': [FAIL],
+
+  ############################ INVALID TESTS #############################
 
   # Test makes unjustified assumptions about the number of calls to SortCompare.
   # Test262 Bug: https://bugs.ecmascript.org/show_bug.cgi?id=596
   'built-ins/Array/prototype/sort/bug_596_1': [PASS, FAIL_OK],
 
-  # Test bug https://github.com/tc39/test262/issues/518
-  'built-ins/TypedArrays/object-arg-throws-setting-typedarray-property': [FAIL],
-  'built-ins/Object/getOwnPropertyDescriptors/duplicate-keys': [FAIL],
-  'built-ins/Object/getOwnPropertyDescriptors/symbols-included': [FAIL],
+  # https://github.com/tc39/test262/issues/677
+  'built-ins/RegExp/prototype/source/15.10.7.1-1': [FAIL],
+  'built-ins/RegExp/prototype/global/15.10.7.2-1': [FAIL],
+  'built-ins/RegExp/prototype/ignoreCase/15.10.7.3-1': [FAIL],
+  'built-ins/RegExp/prototype/multiline/15.10.7.4-1': [FAIL],
 
-  # Test bug https://github.com/tc39/test262/issues/521
-  'built-ins/TypedArray/from/mapfn-is-not-callable': [FAIL],
-
-  # Test bug https://github.com/tc39/test262/issues/529
-  'built-ins/Math/cos/S15.8.2.7_A7': [PASS, FAIL_OK],
-  'built-ins/Math/sin/S15.8.2.16_A7': [PASS, FAIL_OK],
-  'built-ins/Math/tan/S15.8.2.18_A7': [PASS, FAIL_OK],
-  'built-ins/Math/exp/S15.8.2.8_A6': [PASS, FAIL_OK],  # Math.exp (less precise with --fast-math)
+  # https://github.com/tc39/test262/issues/694
+  'language/statements/class/subclass/builtin-objects/ArrayBuffer/regular-subclassing': [FAIL],
 
   ############################ SKIPPED TESTS #############################
 
@@ -292,26 +581,6 @@
   'built-ins/Array/prototype/slice/S15.4.4.10_A3_T2': [SKIP],
 }],  # ALWAYS
 
-['system == linux', {
-  # BUG(v8:4437).
-  'intl402/Collator/10.1.1_19_c': [PASS, FAIL],
-  'intl402/Collator/9.2.5_11_g_ii_2': [PASS, FAIL],
-  'intl402/NumberFormat/11.1.1_17': [PASS, FAIL],
-  'intl402/NumberFormat/11.1.1_19': [PASS, FAIL],
-  'intl402/NumberFormat/prototype/format/11.3.2_TRF': [PASS, FAIL],
-  'intl402/NumberFormat/prototype/format/11.3.2_TRP': [PASS, FAIL],
-}],  # system == linux
-
-['system == macos', {
-  # BUG(v8:4437).
-  'intl402/Collator/10.1.1_19_c': [SKIP],
-  'intl402/Collator/9.2.5_11_g_ii_2': [SKIP],
-  'intl402/NumberFormat/11.1.1_17': [SKIP],
-  'intl402/NumberFormat/11.1.1_19': [SKIP],
-  'intl402/NumberFormat/prototype/format/11.3.2_TRF': [SKIP],
-  'intl402/NumberFormat/prototype/format/11.3.2_TRP': [SKIP],
-}],  # system == macos
-
 ['no_i18n == True', {
   # Unicode canonicalization is not available with i18n turned off.
   'built-ins/String/prototype/localeCompare/15.5.4.9_CE': [SKIP],
@@ -323,8 +592,23 @@
   'built-ins/String/prototype/normalize/return-normalized-string': [SKIP],
   'built-ins/String/prototype/normalize/return-normalized-string-from-coerced-form': [SKIP],
   'built-ins/String/prototype/normalize/return-normalized-string-using-default-parameter': [SKIP],
-}],  # no_i18n == True
 
+  # Case-conversion is not fully compliant to the Unicode spec with i18n off.
+  'built-ins/String/prototype/toLocaleLowerCase/special_casing_conditional': [FAIL],
+  'built-ins/String/prototype/toLocaleLowerCase/supplementary_plane': [FAIL],
+  'built-ins/String/prototype/toLowerCase/special_casing_conditional': [FAIL],
+  'built-ins/String/prototype/toLowerCase/supplementary_plane': [FAIL],
+  'built-ins/String/prototype/toLocaleUpperCase/supplementary_plane': [FAIL],
+  'built-ins/String/prototype/toUpperCase/supplementary_plane': [FAIL],
+
+  # Locale-sensitive case-conversion is not available with i18n off.
+  'intl402/String/prototype/toLocaleLowerCase/special_casing_Azeri': [FAIL],
+  'intl402/String/prototype/toLocaleLowerCase/special_casing_Lithuanian': [FAIL],
+  'intl402/String/prototype/toLocaleLowerCase/special_casing_Turkish': [FAIL],
+  'intl402/String/prototype/toLocaleUpperCase/special_casing_Azeri': [FAIL],
+  'intl402/String/prototype/toLocaleUpperCase/special_casing_Lithuanian': [FAIL],
+  'intl402/String/prototype/toLocaleUpperCase/special_casing_Turkish': [FAIL],
+}],  # no_i18n == True
 
 ['arch == arm or arch == mipsel or arch == mips or arch == arm64 or arch == mips64 or arch == mips64el', {
 
@@ -351,6 +635,7 @@
   # https://bugs.chromium.org/p/v8/issues/detail?id=4639
   # The failed allocation causes an asan/msan/tsan error
   'built-ins/ArrayBuffer/allocation-limit': [SKIP],
+  'built-ins/ArrayBuffer/length-is-too-large-throws': [SKIP],
 }],  # asan == True or msan == True or tsan == True
 
 ]
diff --git a/test/test262/testcfg.py b/test/test262/testcfg.py
index bf007bd..b62e9b0 100644
--- a/test/test262/testcfg.py
+++ b/test/test262/testcfg.py
@@ -43,6 +43,7 @@
 ARCHIVE = DATA + ".tar"
 
 TEST_262_HARNESS_FILES = ["sta.js", "assert.js"]
+TEST_262_NATIVE_FILES = ["detachArrayBuffer.js"]
 
 TEST_262_SUITE_PATH = ["data", "test"]
 TEST_262_HARNESS_PATH = ["data", "harness"]
@@ -129,8 +130,14 @@
   def GetFlagsForTestCase(self, testcase, context):
     return (testcase.flags + context.mode_flags + self.harness +
             self.GetIncludesForTest(testcase) + ["--harmony"] +
+            (["--module"] if "module" in self.GetTestRecord(testcase) else []) +
             [os.path.join(self.testroot, testcase.path + ".js")] +
-            (["--throws"] if "negative" in self.GetTestRecord(testcase) else []))
+            (["--throws"] if "negative" in self.GetTestRecord(testcase)
+                          else []) +
+            (["--allow-natives-syntax"]
+             if "detachArrayBuffer.js" in
+                self.GetTestRecord(testcase).get("includes", [])
+             else []))
 
   def _VariantGeneratorFactory(self):
     return Test262VariantGenerator
@@ -158,11 +165,14 @@
                                              testcase.path)
     return testcase.test_record
 
+  def BasePath(self, filename):
+    return self.root if filename in TEST_262_NATIVE_FILES else self.harnesspath
+
   def GetIncludesForTest(self, testcase):
     test_record = self.GetTestRecord(testcase)
     if "includes" in test_record:
-      includes = [os.path.join(self.harnesspath, f)
-                  for f in test_record["includes"]]
+      return [os.path.join(self.BasePath(filename), filename)
+              for filename in test_record.get("includes", [])]
     else:
       includes = []
     return includes
diff --git a/test/unittests/BUILD.gn b/test/unittests/BUILD.gn
new file mode 100644
index 0000000..b962673
--- /dev/null
+++ b/test/unittests/BUILD.gn
@@ -0,0 +1,182 @@
+# Copyright 2016 The V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Please keep this file in sync with unittests.gyp.
+
+import("../../gni/v8.gni")
+
+v8_executable("unittests") {
+  testonly = true
+
+  sources = [
+    "base/atomic-utils-unittest.cc",
+    "base/bits-unittest.cc",
+    "base/cpu-unittest.cc",
+    "base/division-by-constant-unittest.cc",
+    "base/flags-unittest.cc",
+    "base/functional-unittest.cc",
+    "base/ieee754-unittest.cc",
+    "base/iterator-unittest.cc",
+    "base/logging-unittest.cc",
+    "base/platform/condition-variable-unittest.cc",
+    "base/platform/mutex-unittest.cc",
+    "base/platform/platform-unittest.cc",
+    "base/platform/semaphore-unittest.cc",
+    "base/platform/time-unittest.cc",
+    "base/sys-info-unittest.cc",
+    "base/utils/random-number-generator-unittest.cc",
+    "cancelable-tasks-unittest.cc",
+    "char-predicates-unittest.cc",
+    "compiler/branch-elimination-unittest.cc",
+    "compiler/checkpoint-elimination-unittest.cc",
+    "compiler/common-operator-reducer-unittest.cc",
+    "compiler/common-operator-unittest.cc",
+    "compiler/compiler-test-utils.h",
+    "compiler/control-equivalence-unittest.cc",
+    "compiler/control-flow-optimizer-unittest.cc",
+    "compiler/dead-code-elimination-unittest.cc",
+    "compiler/diamond-unittest.cc",
+    "compiler/effect-control-linearizer-unittest.cc",
+    "compiler/escape-analysis-unittest.cc",
+    "compiler/graph-reducer-unittest.cc",
+    "compiler/graph-reducer-unittest.h",
+    "compiler/graph-trimmer-unittest.cc",
+    "compiler/graph-unittest.cc",
+    "compiler/graph-unittest.h",
+    "compiler/instruction-selector-unittest.cc",
+    "compiler/instruction-selector-unittest.h",
+    "compiler/instruction-sequence-unittest.cc",
+    "compiler/instruction-sequence-unittest.h",
+    "compiler/int64-lowering-unittest.cc",
+    "compiler/js-builtin-reducer-unittest.cc",
+    "compiler/js-create-lowering-unittest.cc",
+    "compiler/js-intrinsic-lowering-unittest.cc",
+    "compiler/js-operator-unittest.cc",
+    "compiler/js-typed-lowering-unittest.cc",
+    "compiler/linkage-tail-call-unittest.cc",
+    "compiler/live-range-unittest.cc",
+    "compiler/liveness-analyzer-unittest.cc",
+    "compiler/load-elimination-unittest.cc",
+    "compiler/loop-peeling-unittest.cc",
+    "compiler/machine-operator-reducer-unittest.cc",
+    "compiler/machine-operator-unittest.cc",
+    "compiler/move-optimizer-unittest.cc",
+    "compiler/node-cache-unittest.cc",
+    "compiler/node-matchers-unittest.cc",
+    "compiler/node-properties-unittest.cc",
+    "compiler/node-test-utils.cc",
+    "compiler/node-test-utils.h",
+    "compiler/node-unittest.cc",
+    "compiler/opcodes-unittest.cc",
+    "compiler/register-allocator-unittest.cc",
+    "compiler/schedule-unittest.cc",
+    "compiler/scheduler-rpo-unittest.cc",
+    "compiler/scheduler-unittest.cc",
+    "compiler/simplified-operator-reducer-unittest.cc",
+    "compiler/simplified-operator-unittest.cc",
+    "compiler/state-values-utils-unittest.cc",
+    "compiler/tail-call-optimization-unittest.cc",
+    "compiler/typer-unittest.cc",
+    "compiler/value-numbering-reducer-unittest.cc",
+    "compiler/zone-pool-unittest.cc",
+    "counters-unittest.cc",
+    "heap/bitmap-unittest.cc",
+    "heap/gc-idle-time-handler-unittest.cc",
+    "heap/gc-tracer-unittest.cc",
+    "heap/heap-unittest.cc",
+    "heap/memory-reducer-unittest.cc",
+    "heap/scavenge-job-unittest.cc",
+    "heap/slot-set-unittest.cc",
+    "interpreter/bytecode-array-builder-unittest.cc",
+    "interpreter/bytecode-array-iterator-unittest.cc",
+    "interpreter/bytecode-array-writer-unittest.cc",
+    "interpreter/bytecode-dead-code-optimizer-unittest.cc",
+    "interpreter/bytecode-peephole-optimizer-unittest.cc",
+    "interpreter/bytecode-pipeline-unittest.cc",
+    "interpreter/bytecode-register-allocator-unittest.cc",
+    "interpreter/bytecode-register-optimizer-unittest.cc",
+    "interpreter/bytecodes-unittest.cc",
+    "interpreter/constant-array-builder-unittest.cc",
+    "interpreter/interpreter-assembler-unittest.cc",
+    "interpreter/interpreter-assembler-unittest.h",
+    "interpreter/source-position-table-unittest.cc",
+    "libplatform/default-platform-unittest.cc",
+    "libplatform/task-queue-unittest.cc",
+    "libplatform/worker-thread-unittest.cc",
+    "locked-queue-unittest.cc",
+    "register-configuration-unittest.cc",
+    "run-all-unittests.cc",
+    "test-utils.cc",
+    "test-utils.h",
+    "wasm/asm-types-unittest.cc",
+    "wasm/ast-decoder-unittest.cc",
+    "wasm/control-transfer-unittest.cc",
+    "wasm/decoder-unittest.cc",
+    "wasm/encoder-unittest.cc",
+    "wasm/leb-helper-unittest.cc",
+    "wasm/loop-assignment-analysis-unittest.cc",
+    "wasm/module-decoder-unittest.cc",
+    "wasm/switch-logic-unittest.cc",
+    "wasm/wasm-macro-gen-unittest.cc",
+  ]
+
+  if (v8_target_cpu == "arm") {
+    sources += [ "compiler/arm/instruction-selector-arm-unittest.cc" ]
+  } else if (v8_target_cpu == "arm64") {
+    sources += [ "compiler/arm64/instruction-selector-arm64-unittest.cc" ]
+  } else if (v8_target_cpu == "x86") {
+    sources += [ "compiler/ia32/instruction-selector-ia32-unittest.cc" ]
+  } else if (v8_target_cpu == "mips" || v8_target_cpu == "mipsel") {
+    sources += [ "compiler/mips/instruction-selector-mips-unittest.cc" ]
+  } else if (v8_target_cpu == "mips64" || v8_target_cpu == "mips64el") {
+    sources += [ "compiler/mips64/instruction-selector-mips64-unittest.cc" ]
+  } else if (v8_target_cpu == "x64") {
+    sources += [ "compiler/x64/instruction-selector-x64-unittest.cc" ]
+  } else if (v8_target_cpu == "ppc" || v8_target_cpu == "ppc64") {
+    sources += [ "compiler/ppc/instruction-selector-ppc-unittest.cc" ]
+  } else if (v8_target_cpu == "s390" || v8_target_cpu == "s390x") {
+    sources += [ "compiler/s390/instruction-selector-s390-unittest.cc" ]
+  }
+
+  configs = [
+    "../..:external_config",
+    "../..:internal_config_base",
+  ]
+
+  # TODO(machenbach): Translate from gyp.
+  #['OS=="aix"', {
+  #  'ldflags': [ '-Wl,-bbigtoc' ],
+  #}],
+
+  deps = [
+    "../..:v8_libplatform",
+    "//build/config/sanitizers:deps",
+    "//build/win:default_exe_manifest",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+
+  if (is_component_build) {
+    # compiler-unittests can't be built against a shared library, so we
+    # need to depend on the underlying static target in that case.
+    deps += [ "../..:v8_maybe_snapshot" ]
+  } else {
+    deps += [ "../..:v8" ]
+  }
+
+  if (is_win) {
+    # This warning is benignly triggered by the U16 and U32 macros in
+    # bytecode-utils.h.
+    # C4309: 'static_cast': truncation of constant value
+    cflags = [ "/wd4309" ]
+
+    # Suppress warnings about importing locally defined symbols.
+    if (is_component_build) {
+      ldflags = [
+        "/ignore:4049",
+        "/ignore:4217",
+      ]
+    }
+  }
+}
diff --git a/test/unittests/atomic-utils-unittest.cc b/test/unittests/atomic-utils-unittest.cc
deleted file mode 100644
index ad33853..0000000
--- a/test/unittests/atomic-utils-unittest.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <limits.h>
-
-#include "src/atomic-utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace v8 {
-namespace internal {
-
-TEST(AtomicNumber, Constructor) {
-  // Test some common types.
-  AtomicNumber<int> zero_int;
-  AtomicNumber<size_t> zero_size_t;
-  AtomicNumber<intptr_t> zero_intptr_t;
-  EXPECT_EQ(0, zero_int.Value());
-  EXPECT_EQ(0U, zero_size_t.Value());
-  EXPECT_EQ(0, zero_intptr_t.Value());
-}
-
-
-TEST(AtomicNumber, Value) {
-  AtomicNumber<int> a(1);
-  EXPECT_EQ(1, a.Value());
-  AtomicNumber<int> b(-1);
-  EXPECT_EQ(-1, b.Value());
-  AtomicNumber<size_t> c(1);
-  EXPECT_EQ(1U, c.Value());
-  AtomicNumber<size_t> d(static_cast<size_t>(-1));
-  EXPECT_EQ(std::numeric_limits<size_t>::max(), d.Value());
-}
-
-
-TEST(AtomicNumber, SetValue) {
-  AtomicNumber<int> a(1);
-  a.SetValue(-1);
-  EXPECT_EQ(-1, a.Value());
-}
-
-
-TEST(AtomicNumber, Increment) {
-  AtomicNumber<int> a(std::numeric_limits<int>::max());
-  a.Increment(1);
-  EXPECT_EQ(std::numeric_limits<int>::min(), a.Value());
-  // Check that potential signed-ness of the underlying storage has no impact
-  // on unsigned types.
-  AtomicNumber<size_t> b(std::numeric_limits<intptr_t>::max());
-  b.Increment(1);
-  EXPECT_EQ(static_cast<size_t>(std::numeric_limits<intptr_t>::max()) + 1,
-            b.Value());
-  // Should work as decrement as well.
-  AtomicNumber<size_t> c(1);
-  c.Increment(-1);
-  EXPECT_EQ(0U, c.Value());
-  c.Increment(-1);
-  EXPECT_EQ(std::numeric_limits<size_t>::max(), c.Value());
-}
-
-
-namespace {
-
-enum TestFlag {
-  kA,
-  kB,
-  kC,
-};
-
-}  // namespace
-
-
-TEST(AtomicValue, Initial) {
-  AtomicValue<TestFlag> a(kA);
-  EXPECT_EQ(TestFlag::kA, a.Value());
-}
-
-
-TEST(AtomicValue, TrySetValue) {
-  AtomicValue<TestFlag> a(kA);
-  EXPECT_FALSE(a.TrySetValue(kB, kC));
-  EXPECT_TRUE(a.TrySetValue(kA, kC));
-  EXPECT_EQ(TestFlag::kC, a.Value());
-}
-
-
-TEST(AtomicValue, SetValue) {
-  AtomicValue<TestFlag> a(kB);
-  a.SetValue(kC);
-  EXPECT_EQ(TestFlag::kC, a.Value());
-}
-
-
-TEST(AtomicValue, WithVoidStar) {
-  AtomicValue<void*> a(nullptr);
-  AtomicValue<void*> dummy(nullptr);
-  EXPECT_EQ(nullptr, a.Value());
-  a.SetValue(&a);
-  EXPECT_EQ(&a, a.Value());
-  EXPECT_FALSE(a.TrySetValue(nullptr, &dummy));
-  EXPECT_TRUE(a.TrySetValue(&a, &dummy));
-  EXPECT_EQ(&dummy, a.Value());
-}
-
-
-namespace {
-
-enum TestSetValue { kAA, kBB, kCC, kLastValue = kCC };
-
-}  // namespace
-
-
-TEST(AtomicEnumSet, Constructor) {
-  AtomicEnumSet<TestSetValue> a;
-  EXPECT_TRUE(a.IsEmpty());
-  EXPECT_FALSE(a.Contains(kAA));
-}
-
-
-TEST(AtomicEnumSet, AddSingle) {
-  AtomicEnumSet<TestSetValue> a;
-  a.Add(kAA);
-  EXPECT_FALSE(a.IsEmpty());
-  EXPECT_TRUE(a.Contains(kAA));
-  EXPECT_FALSE(a.Contains(kBB));
-  EXPECT_FALSE(a.Contains(kCC));
-}
-
-
-TEST(AtomicEnumSet, AddOtherSet) {
-  AtomicEnumSet<TestSetValue> a;
-  AtomicEnumSet<TestSetValue> b;
-  a.Add(kAA);
-  EXPECT_FALSE(a.IsEmpty());
-  EXPECT_TRUE(b.IsEmpty());
-  b.Add(a);
-  EXPECT_FALSE(b.IsEmpty());
-  EXPECT_TRUE(a.Contains(kAA));
-  EXPECT_TRUE(b.Contains(kAA));
-}
-
-
-TEST(AtomicEnumSet, RemoveSingle) {
-  AtomicEnumSet<TestSetValue> a;
-  a.Add(kAA);
-  a.Add(kBB);
-  EXPECT_TRUE(a.Contains(kAA));
-  EXPECT_TRUE(a.Contains(kBB));
-  a.Remove(kAA);
-  EXPECT_FALSE(a.Contains(kAA));
-  EXPECT_TRUE(a.Contains(kBB));
-}
-
-
-TEST(AtomicEnumSet, RemoveOtherSet) {
-  AtomicEnumSet<TestSetValue> a;
-  AtomicEnumSet<TestSetValue> b;
-  a.Add(kAA);
-  a.Add(kBB);
-  b.Add(kBB);
-  a.Remove(b);
-  EXPECT_TRUE(a.Contains(kAA));
-  EXPECT_FALSE(a.Contains(kBB));
-  EXPECT_FALSE(a.Contains(kCC));
-}
-
-
-TEST(AtomicEnumSet, RemoveEmptySet) {
-  AtomicEnumSet<TestSetValue> a;
-  AtomicEnumSet<TestSetValue> b;
-  a.Add(kAA);
-  a.Add(kBB);
-  EXPECT_TRUE(a.Contains(kAA));
-  EXPECT_TRUE(a.Contains(kBB));
-  EXPECT_FALSE(a.Contains(kCC));
-  EXPECT_TRUE(b.IsEmpty());
-  a.Remove(b);
-  EXPECT_TRUE(a.Contains(kAA));
-  EXPECT_TRUE(a.Contains(kBB));
-  EXPECT_FALSE(a.Contains(kCC));
-}
-
-
-TEST(AtomicEnumSet, Intersect) {
-  AtomicEnumSet<TestSetValue> a;
-  AtomicEnumSet<TestSetValue> b;
-  a.Add(kAA);
-  b.Add(kCC);
-  a.Intersect(b);
-  EXPECT_TRUE(a.IsEmpty());
-}
-
-
-TEST(AtomicEnumSet, ContainsAnyOf) {
-  AtomicEnumSet<TestSetValue> a;
-  AtomicEnumSet<TestSetValue> b;
-  a.Add(kAA);
-  b.Add(kCC);
-  EXPECT_FALSE(a.ContainsAnyOf(b));
-  b.Add(kAA);
-  EXPECT_TRUE(a.ContainsAnyOf(b));
-}
-
-
-TEST(AtomicEnumSet, Equality) {
-  AtomicEnumSet<TestSetValue> a;
-  AtomicEnumSet<TestSetValue> b;
-  a.Add(kAA);
-  EXPECT_FALSE(a == b);
-  EXPECT_TRUE(a != b);
-  b.Add(kAA);
-  EXPECT_TRUE(a == b);
-  EXPECT_FALSE(a != b);
-}
-
-}  // namespace internal
-}  // namespace v8
diff --git a/test/unittests/base/atomic-utils-unittest.cc b/test/unittests/base/atomic-utils-unittest.cc
new file mode 100644
index 0000000..06079fe
--- /dev/null
+++ b/test/unittests/base/atomic-utils-unittest.cc
@@ -0,0 +1,217 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <limits.h>
+
+#include "src/base/atomic-utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace v8 {
+namespace base {
+
+TEST(AtomicNumber, Constructor) {
+  // Test some common types.
+  AtomicNumber<int> zero_int;
+  AtomicNumber<size_t> zero_size_t;
+  AtomicNumber<intptr_t> zero_intptr_t;
+  EXPECT_EQ(0, zero_int.Value());
+  EXPECT_EQ(0U, zero_size_t.Value());
+  EXPECT_EQ(0, zero_intptr_t.Value());
+}
+
+
+TEST(AtomicNumber, Value) {
+  AtomicNumber<int> a(1);
+  EXPECT_EQ(1, a.Value());
+  AtomicNumber<int> b(-1);
+  EXPECT_EQ(-1, b.Value());
+  AtomicNumber<size_t> c(1);
+  EXPECT_EQ(1U, c.Value());
+  AtomicNumber<size_t> d(static_cast<size_t>(-1));
+  EXPECT_EQ(std::numeric_limits<size_t>::max(), d.Value());
+}
+
+
+TEST(AtomicNumber, SetValue) {
+  AtomicNumber<int> a(1);
+  a.SetValue(-1);
+  EXPECT_EQ(-1, a.Value());
+}
+
+
+TEST(AtomicNumber, Increment) {
+  AtomicNumber<int> a(std::numeric_limits<int>::max());
+  a.Increment(1);
+  EXPECT_EQ(std::numeric_limits<int>::min(), a.Value());
+  // Check that potential signed-ness of the underlying storage has no impact
+  // on unsigned types.
+  AtomicNumber<size_t> b(std::numeric_limits<intptr_t>::max());
+  b.Increment(1);
+  EXPECT_EQ(static_cast<size_t>(std::numeric_limits<intptr_t>::max()) + 1,
+            b.Value());
+  // Should work as decrement as well.
+  AtomicNumber<size_t> c(1);
+  c.Increment(-1);
+  EXPECT_EQ(0U, c.Value());
+  c.Increment(-1);
+  EXPECT_EQ(std::numeric_limits<size_t>::max(), c.Value());
+}
+
+
+namespace {
+
+enum TestFlag {
+  kA,
+  kB,
+  kC,
+};
+
+}  // namespace
+
+
+TEST(AtomicValue, Initial) {
+  AtomicValue<TestFlag> a(kA);
+  EXPECT_EQ(TestFlag::kA, a.Value());
+}
+
+
+TEST(AtomicValue, TrySetValue) {
+  AtomicValue<TestFlag> a(kA);
+  EXPECT_FALSE(a.TrySetValue(kB, kC));
+  EXPECT_TRUE(a.TrySetValue(kA, kC));
+  EXPECT_EQ(TestFlag::kC, a.Value());
+}
+
+
+TEST(AtomicValue, SetValue) {
+  AtomicValue<TestFlag> a(kB);
+  a.SetValue(kC);
+  EXPECT_EQ(TestFlag::kC, a.Value());
+}
+
+
+TEST(AtomicValue, WithVoidStar) {
+  AtomicValue<void*> a(nullptr);
+  AtomicValue<void*> dummy(nullptr);
+  EXPECT_EQ(nullptr, a.Value());
+  a.SetValue(&a);
+  EXPECT_EQ(&a, a.Value());
+  EXPECT_FALSE(a.TrySetValue(nullptr, &dummy));
+  EXPECT_TRUE(a.TrySetValue(&a, &dummy));
+  EXPECT_EQ(&dummy, a.Value());
+}
+
+
+namespace {
+
+enum TestSetValue { kAA, kBB, kCC, kLastValue = kCC };
+
+}  // namespace
+
+
+TEST(AtomicEnumSet, Constructor) {
+  AtomicEnumSet<TestSetValue> a;
+  EXPECT_TRUE(a.IsEmpty());
+  EXPECT_FALSE(a.Contains(kAA));
+}
+
+
+TEST(AtomicEnumSet, AddSingle) {
+  AtomicEnumSet<TestSetValue> a;
+  a.Add(kAA);
+  EXPECT_FALSE(a.IsEmpty());
+  EXPECT_TRUE(a.Contains(kAA));
+  EXPECT_FALSE(a.Contains(kBB));
+  EXPECT_FALSE(a.Contains(kCC));
+}
+
+
+TEST(AtomicEnumSet, AddOtherSet) {
+  AtomicEnumSet<TestSetValue> a;
+  AtomicEnumSet<TestSetValue> b;
+  a.Add(kAA);
+  EXPECT_FALSE(a.IsEmpty());
+  EXPECT_TRUE(b.IsEmpty());
+  b.Add(a);
+  EXPECT_FALSE(b.IsEmpty());
+  EXPECT_TRUE(a.Contains(kAA));
+  EXPECT_TRUE(b.Contains(kAA));
+}
+
+
+TEST(AtomicEnumSet, RemoveSingle) {
+  AtomicEnumSet<TestSetValue> a;
+  a.Add(kAA);
+  a.Add(kBB);
+  EXPECT_TRUE(a.Contains(kAA));
+  EXPECT_TRUE(a.Contains(kBB));
+  a.Remove(kAA);
+  EXPECT_FALSE(a.Contains(kAA));
+  EXPECT_TRUE(a.Contains(kBB));
+}
+
+
+TEST(AtomicEnumSet, RemoveOtherSet) {
+  AtomicEnumSet<TestSetValue> a;
+  AtomicEnumSet<TestSetValue> b;
+  a.Add(kAA);
+  a.Add(kBB);
+  b.Add(kBB);
+  a.Remove(b);
+  EXPECT_TRUE(a.Contains(kAA));
+  EXPECT_FALSE(a.Contains(kBB));
+  EXPECT_FALSE(a.Contains(kCC));
+}
+
+
+TEST(AtomicEnumSet, RemoveEmptySet) {
+  AtomicEnumSet<TestSetValue> a;
+  AtomicEnumSet<TestSetValue> b;
+  a.Add(kAA);
+  a.Add(kBB);
+  EXPECT_TRUE(a.Contains(kAA));
+  EXPECT_TRUE(a.Contains(kBB));
+  EXPECT_FALSE(a.Contains(kCC));
+  EXPECT_TRUE(b.IsEmpty());
+  a.Remove(b);
+  EXPECT_TRUE(a.Contains(kAA));
+  EXPECT_TRUE(a.Contains(kBB));
+  EXPECT_FALSE(a.Contains(kCC));
+}
+
+
+TEST(AtomicEnumSet, Intersect) {
+  AtomicEnumSet<TestSetValue> a;
+  AtomicEnumSet<TestSetValue> b;
+  a.Add(kAA);
+  b.Add(kCC);
+  a.Intersect(b);
+  EXPECT_TRUE(a.IsEmpty());
+}
+
+
+TEST(AtomicEnumSet, ContainsAnyOf) {
+  AtomicEnumSet<TestSetValue> a;
+  AtomicEnumSet<TestSetValue> b;
+  a.Add(kAA);
+  b.Add(kCC);
+  EXPECT_FALSE(a.ContainsAnyOf(b));
+  b.Add(kAA);
+  EXPECT_TRUE(a.ContainsAnyOf(b));
+}
+
+
+TEST(AtomicEnumSet, Equality) {
+  AtomicEnumSet<TestSetValue> a;
+  AtomicEnumSet<TestSetValue> b;
+  a.Add(kAA);
+  EXPECT_FALSE(a == b);
+  EXPECT_TRUE(a != b);
+  b.Add(kAA);
+  EXPECT_TRUE(a == b);
+  EXPECT_FALSE(a != b);
+}
+
+}  // namespace base
+}  // namespace v8
diff --git a/test/unittests/base/ieee754-unittest.cc b/test/unittests/base/ieee754-unittest.cc
new file mode 100644
index 0000000..8c71b57
--- /dev/null
+++ b/test/unittests/base/ieee754-unittest.cc
@@ -0,0 +1,323 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <limits>
+
+#include "src/base/ieee754.h"
+#include "src/base/macros.h"
+#include "testing/gmock-support.h"
+#include "testing/gtest-support.h"
+
+using testing::BitEq;
+using testing::IsNaN;
+
+namespace v8 {
+namespace base {
+namespace ieee754 {
+
+namespace {
+
+double const kE = 2.718281828459045;
+double const kPI = 3.141592653589793;
+double const kTwo120 = 1.329227995784916e+36;
+
+}  // namespace
+
+TEST(Ieee754, Atan) {
+  EXPECT_THAT(atan(std::numeric_limits<double>::quiet_NaN()), IsNaN());
+  EXPECT_THAT(atan(std::numeric_limits<double>::signaling_NaN()), IsNaN());
+  EXPECT_THAT(atan(-0.0), BitEq(-0.0));
+  EXPECT_THAT(atan(0.0), BitEq(0.0));
+  EXPECT_DOUBLE_EQ(1.5707963267948966,
+                   atan(std::numeric_limits<double>::infinity()));
+  EXPECT_DOUBLE_EQ(-1.5707963267948966,
+                   atan(-std::numeric_limits<double>::infinity()));
+}
+
+TEST(Ieee754, Atan2) {
+  EXPECT_THAT(atan2(std::numeric_limits<double>::quiet_NaN(),
+                    std::numeric_limits<double>::quiet_NaN()),
+              IsNaN());
+  EXPECT_THAT(atan2(std::numeric_limits<double>::quiet_NaN(),
+                    std::numeric_limits<double>::signaling_NaN()),
+              IsNaN());
+  EXPECT_THAT(atan2(std::numeric_limits<double>::signaling_NaN(),
+                    std::numeric_limits<double>::quiet_NaN()),
+              IsNaN());
+  EXPECT_THAT(atan2(std::numeric_limits<double>::signaling_NaN(),
+                    std::numeric_limits<double>::signaling_NaN()),
+              IsNaN());
+  EXPECT_DOUBLE_EQ(0.7853981633974483,
+                   atan2(std::numeric_limits<double>::infinity(),
+                         std::numeric_limits<double>::infinity()));
+  EXPECT_DOUBLE_EQ(2.356194490192345,
+                   atan2(std::numeric_limits<double>::infinity(),
+                         -std::numeric_limits<double>::infinity()));
+  EXPECT_DOUBLE_EQ(-0.7853981633974483,
+                   atan2(-std::numeric_limits<double>::infinity(),
+                         std::numeric_limits<double>::infinity()));
+  EXPECT_DOUBLE_EQ(-2.356194490192345,
+                   atan2(-std::numeric_limits<double>::infinity(),
+                         -std::numeric_limits<double>::infinity()));
+}
+
+TEST(Ieee754, Atanh) {
+  EXPECT_THAT(atanh(std::numeric_limits<double>::quiet_NaN()), IsNaN());
+  EXPECT_THAT(atanh(std::numeric_limits<double>::signaling_NaN()), IsNaN());
+  EXPECT_THAT(atanh(std::numeric_limits<double>::infinity()), IsNaN());
+  EXPECT_EQ(std::numeric_limits<double>::infinity(), atanh(1));
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(), atanh(-1));
+  EXPECT_DOUBLE_EQ(0.54930614433405478, atanh(0.5));
+}
+
+TEST(Ieee754, Cos) {
+  // Test values mentioned in the EcmaScript spec.
+  EXPECT_THAT(cos(std::numeric_limits<double>::quiet_NaN()), IsNaN());
+  EXPECT_THAT(cos(std::numeric_limits<double>::signaling_NaN()), IsNaN());
+  EXPECT_THAT(cos(std::numeric_limits<double>::infinity()), IsNaN());
+  EXPECT_THAT(cos(-std::numeric_limits<double>::infinity()), IsNaN());
+
+  // Tests for cos for |x| < pi/4
+  EXPECT_EQ(1.0, 1 / cos(-0.0));
+  EXPECT_EQ(1.0, 1 / cos(0.0));
+  // cos(x) = 1 for |x| < 2^-27
+  EXPECT_EQ(1, cos(2.3283064365386963e-10));
+  EXPECT_EQ(1, cos(-2.3283064365386963e-10));
+  // Test KERNELCOS for |x| < 0.3.
+  // cos(pi/20) = sqrt(sqrt(2)*sqrt(sqrt(5)+5)+4)/2^(3/2)
+  EXPECT_EQ(0.9876883405951378, cos(0.15707963267948966));
+  // Test KERNELCOS for x ~= 0.78125
+  EXPECT_EQ(0.7100335477927638, cos(0.7812504768371582));
+  EXPECT_EQ(0.7100338835660797, cos(0.78125));
+  // Test KERNELCOS for |x| > 0.3.
+  // cos(pi/8) = sqrt(sqrt(2)+1)/2^(3/4)
+  EXPECT_EQ(0.9238795325112867, cos(0.39269908169872414));
+  // Test KERNELTAN for |x| < 0.67434.
+  EXPECT_EQ(0.9238795325112867, cos(-0.39269908169872414));
+
+  // Tests for cos.
+  EXPECT_EQ(1, cos(3.725290298461914e-9));
+  // Cover different code paths in KERNELCOS.
+  EXPECT_EQ(0.9689124217106447, cos(0.25));
+  EXPECT_EQ(0.8775825618903728, cos(0.5));
+  EXPECT_EQ(0.7073882691671998, cos(0.785));
+  // Test that cos(Math.PI/2) != 0 since Math.PI is not exact.
+  EXPECT_EQ(6.123233995736766e-17, cos(1.5707963267948966));
+  // Test cos for various phases.
+  EXPECT_EQ(0.7071067811865474, cos(7.0 / 4 * kPI));
+  EXPECT_EQ(0.7071067811865477, cos(9.0 / 4 * kPI));
+  EXPECT_EQ(-0.7071067811865467, cos(11.0 / 4 * kPI));
+  EXPECT_EQ(-0.7071067811865471, cos(13.0 / 4 * kPI));
+  EXPECT_EQ(0.9367521275331447, cos(1000000.0));
+  EXPECT_EQ(-3.435757038074824e-12, cos(1048575.0 / 2 * kPI));
+
+  // Test Hayne-Panek reduction.
+  EXPECT_EQ(-0.9258790228548379e0, cos(kTwo120));
+  EXPECT_EQ(-0.9258790228548379e0, cos(-kTwo120));
+}
+
+TEST(Ieee754, Exp) {
+  EXPECT_THAT(exp(std::numeric_limits<double>::quiet_NaN()), IsNaN());
+  EXPECT_THAT(exp(std::numeric_limits<double>::signaling_NaN()), IsNaN());
+  EXPECT_EQ(0.0, exp(-std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(0.0, exp(-1000));
+  EXPECT_EQ(0.0, exp(-745.1332191019412));
+  EXPECT_EQ(2.2250738585072626e-308, exp(-708.39641853226408));
+  EXPECT_EQ(3.307553003638408e-308, exp(-708.0));
+  EXPECT_EQ(4.9406564584124654e-324, exp(-7.45133219101941108420e+02));
+  EXPECT_EQ(0.36787944117144233, exp(-1.0));
+  EXPECT_EQ(1.0, exp(-0.0));
+  EXPECT_EQ(1.0, exp(0.0));
+  EXPECT_EQ(1.0, exp(2.2250738585072014e-308));
+
+  // Test that exp(x) is monotonic near 1.
+  EXPECT_GE(exp(1.0), exp(0.9999999999999999));
+  EXPECT_LE(exp(1.0), exp(1.0000000000000002));
+
+  // Test that we produce the correctly rounded result for 1.
+  EXPECT_EQ(kE, exp(1.0));
+
+  EXPECT_EQ(7.38905609893065e0, exp(2.0));
+  EXPECT_EQ(1.7976931348622732e308, exp(7.09782712893383973096e+02));
+  EXPECT_EQ(2.6881171418161356e+43, exp(100.0));
+  EXPECT_EQ(8.218407461554972e+307, exp(709.0));
+  EXPECT_EQ(1.7968190737295725e308, exp(709.7822265625e0));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(), exp(709.7827128933841e0));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(), exp(710.0));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(), exp(1000.0));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            exp(std::numeric_limits<double>::infinity()));
+}
+
+TEST(Ieee754, Expm1) {
+  EXPECT_THAT(expm1(std::numeric_limits<double>::quiet_NaN()), IsNaN());
+  EXPECT_THAT(expm1(std::numeric_limits<double>::signaling_NaN()), IsNaN());
+  EXPECT_EQ(-1.0, expm1(-std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            expm1(std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(0.0, expm1(-0.0));
+  EXPECT_EQ(0.0, expm1(0.0));
+  EXPECT_EQ(1.718281828459045, expm1(1.0));
+  EXPECT_EQ(2.6881171418161356e+43, expm1(100.0));
+  EXPECT_EQ(8.218407461554972e+307, expm1(709.0));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(), expm1(710.0));
+}
+
+TEST(Ieee754, Log) {
+  EXPECT_THAT(log(std::numeric_limits<double>::quiet_NaN()), IsNaN());
+  EXPECT_THAT(log(std::numeric_limits<double>::signaling_NaN()), IsNaN());
+  EXPECT_THAT(log(-std::numeric_limits<double>::infinity()), IsNaN());
+  EXPECT_THAT(log(-1.0), IsNaN());
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(), log(-0.0));
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(), log(0.0));
+  EXPECT_EQ(0.0, log(1.0));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            log(std::numeric_limits<double>::infinity()));
+
+  // Test that log(E) produces the correctly rounded result.
+  EXPECT_EQ(1.0, log(kE));
+}
+
+TEST(Ieee754, Log1p) {
+  EXPECT_THAT(log1p(std::numeric_limits<double>::quiet_NaN()), IsNaN());
+  EXPECT_THAT(log1p(std::numeric_limits<double>::signaling_NaN()), IsNaN());
+  EXPECT_THAT(log1p(-std::numeric_limits<double>::infinity()), IsNaN());
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(), log1p(-1.0));
+  EXPECT_EQ(0.0, log1p(0.0));
+  EXPECT_EQ(-0.0, log1p(-0.0));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            log1p(std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(6.9756137364252422e-03, log1p(0.007));
+  EXPECT_EQ(709.782712893384, log1p(1.7976931348623157e308));
+  EXPECT_EQ(2.7755575615628914e-17, log1p(2.7755575615628914e-17));
+  EXPECT_EQ(9.313225741817976e-10, log1p(9.313225746154785e-10));
+  EXPECT_EQ(-0.2876820724517809, log1p(-0.25));
+  EXPECT_EQ(0.22314355131420976, log1p(0.25));
+  EXPECT_EQ(2.3978952727983707, log1p(10));
+  EXPECT_EQ(36.841361487904734, log1p(10e15));
+  EXPECT_EQ(37.08337388996168, log1p(12738099905822720));
+  EXPECT_EQ(37.08336444902049, log1p(12737979646738432));
+  EXPECT_EQ(1.3862943611198906, log1p(3));
+  EXPECT_EQ(1.3862945995384413, log1p(3 + 9.5367431640625e-7));
+  EXPECT_EQ(0.5596157879354227, log1p(0.75));
+  EXPECT_EQ(0.8109302162163288, log1p(1.25));
+}
+
+TEST(Ieee754, Log2) {
+  EXPECT_THAT(log2(std::numeric_limits<double>::quiet_NaN()), IsNaN());
+  EXPECT_THAT(log2(std::numeric_limits<double>::signaling_NaN()), IsNaN());
+  EXPECT_THAT(log2(-std::numeric_limits<double>::infinity()), IsNaN());
+  EXPECT_THAT(log2(-1.0), IsNaN());
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(), log2(0.0));
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(), log2(-0.0));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            log2(std::numeric_limits<double>::infinity()));
+}
+
+TEST(Ieee754, Log10) {
+  EXPECT_THAT(log10(std::numeric_limits<double>::quiet_NaN()), IsNaN());
+  EXPECT_THAT(log10(std::numeric_limits<double>::signaling_NaN()), IsNaN());
+  EXPECT_THAT(log10(-std::numeric_limits<double>::infinity()), IsNaN());
+  EXPECT_THAT(log10(-1.0), IsNaN());
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(), log10(0.0));
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(), log10(-0.0));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            log10(std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(3.0, log10(1000.0));
+  EXPECT_EQ(14.0, log10(100000000000000));  // log10(10 ^ 14)
+  EXPECT_EQ(3.7389561269540406, log10(5482.2158));
+  EXPECT_EQ(14.661551142893833, log10(458723662312872.125782332587));
+  EXPECT_EQ(-0.9083828622192334, log10(0.12348583358871));
+  EXPECT_EQ(5.0, log10(100000.0));
+}
+
+TEST(Ieee754, Cbrt) {
+  EXPECT_THAT(cbrt(std::numeric_limits<double>::quiet_NaN()), IsNaN());
+  EXPECT_THAT(cbrt(std::numeric_limits<double>::signaling_NaN()), IsNaN());
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            cbrt(std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(),
+            cbrt(-std::numeric_limits<double>::infinity()));
+  EXPECT_EQ(1.4422495703074083, cbrt(3));
+  EXPECT_EQ(100, cbrt(100 * 100 * 100));
+  EXPECT_EQ(46.415888336127786, cbrt(100000));
+}
+
+TEST(Ieee754, Sin) {
+  // Test values mentioned in the EcmaScript spec.
+  EXPECT_THAT(sin(std::numeric_limits<double>::quiet_NaN()), IsNaN());
+  EXPECT_THAT(sin(std::numeric_limits<double>::signaling_NaN()), IsNaN());
+  EXPECT_THAT(sin(std::numeric_limits<double>::infinity()), IsNaN());
+  EXPECT_THAT(sin(-std::numeric_limits<double>::infinity()), IsNaN());
+
+  // Tests for sin for |x| < pi/4
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(), 1 / sin(-0.0));
+  EXPECT_EQ(std::numeric_limits<double>::infinity(), 1 / sin(0.0));
+  // sin(x) = x for x < 2^-27
+  EXPECT_EQ(2.3283064365386963e-10, sin(2.3283064365386963e-10));
+  EXPECT_EQ(-2.3283064365386963e-10, sin(-2.3283064365386963e-10));
+  // sin(pi/8) = sqrt(sqrt(2)-1)/2^(3/4)
+  EXPECT_EQ(0.3826834323650898, sin(0.39269908169872414));
+  EXPECT_EQ(-0.3826834323650898, sin(-0.39269908169872414));
+
+  // Tests for sin.
+  EXPECT_EQ(0.479425538604203, sin(0.5));
+  EXPECT_EQ(-0.479425538604203, sin(-0.5));
+  EXPECT_EQ(1, sin(kPI / 2.0));
+  EXPECT_EQ(-1, sin(-kPI / 2.0));
+  // Test that sin(Math.PI) != 0 since Math.PI is not exact.
+  EXPECT_EQ(1.2246467991473532e-16, sin(kPI));
+  EXPECT_EQ(-7.047032979958965e-14, sin(2200.0 * kPI));
+  // Test sin for various phases.
+  EXPECT_EQ(-0.7071067811865477, sin(7.0 / 4.0 * kPI));
+  EXPECT_EQ(0.7071067811865474, sin(9.0 / 4.0 * kPI));
+  EXPECT_EQ(0.7071067811865483, sin(11.0 / 4.0 * kPI));
+  EXPECT_EQ(-0.7071067811865479, sin(13.0 / 4.0 * kPI));
+  EXPECT_EQ(-3.2103381051568376e-11, sin(1048576.0 / 4 * kPI));
+
+  // Test Hayne-Panek reduction.
+  EXPECT_EQ(0.377820109360752e0, sin(kTwo120));
+  EXPECT_EQ(-0.377820109360752e0, sin(-kTwo120));
+}
+
+TEST(Ieee754, Tan) {
+  // Test values mentioned in the EcmaScript spec.
+  EXPECT_THAT(tan(std::numeric_limits<double>::quiet_NaN()), IsNaN());
+  EXPECT_THAT(tan(std::numeric_limits<double>::signaling_NaN()), IsNaN());
+  EXPECT_THAT(tan(std::numeric_limits<double>::infinity()), IsNaN());
+  EXPECT_THAT(tan(-std::numeric_limits<double>::infinity()), IsNaN());
+
+  // Tests for tan for |x| < pi/4
+  EXPECT_EQ(std::numeric_limits<double>::infinity(), 1 / tan(0.0));
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(), 1 / tan(-0.0));
+  // tan(x) = x for |x| < 2^-28
+  EXPECT_EQ(2.3283064365386963e-10, tan(2.3283064365386963e-10));
+  EXPECT_EQ(-2.3283064365386963e-10, tan(-2.3283064365386963e-10));
+  // Test KERNELTAN for |x| > 0.67434.
+  EXPECT_EQ(0.8211418015898941, tan(11.0 / 16.0));
+  EXPECT_EQ(-0.8211418015898941, tan(-11.0 / 16.0));
+  EXPECT_EQ(0.41421356237309503, tan(0.39269908169872414));
+  // crbug/427468
+  EXPECT_EQ(0.7993357819992383, tan(0.6743358));
+
+  // Tests for tan.
+  EXPECT_EQ(3.725290298461914e-9, tan(3.725290298461914e-9));
+  // Test that tan(PI/2) != Infinity since PI is not exact.
+  EXPECT_EQ(1.633123935319537e16, tan(kPI / 2));
+  // Cover different code paths in KERNELTAN (tangent and cotangent)
+  EXPECT_EQ(0.5463024898437905, tan(0.5));
+  EXPECT_EQ(2.0000000000000027, tan(1.107148717794091));
+  EXPECT_EQ(-1.0000000000000004, tan(7.0 / 4.0 * kPI));
+  EXPECT_EQ(0.9999999999999994, tan(9.0 / 4.0 * kPI));
+  EXPECT_EQ(-6.420676210313675e-11, tan(1048576.0 / 2.0 * kPI));
+  EXPECT_EQ(2.910566692924059e11, tan(1048575.0 / 2.0 * kPI));
+
+  // Test Hayne-Panek reduction.
+  EXPECT_EQ(-0.40806638884180424e0, tan(kTwo120));
+  EXPECT_EQ(0.40806638884180424e0, tan(-kTwo120));
+}
+
+}  // namespace ieee754
+}  // namespace base
+}  // namespace v8
diff --git a/test/unittests/base/platform/time-unittest.cc b/test/unittests/base/platform/time-unittest.cc
index b3bfbab..9aa609f 100644
--- a/test/unittests/base/platform/time-unittest.cc
+++ b/test/unittests/base/platform/time-unittest.cc
@@ -15,7 +15,10 @@
 #include "src/base/win32-headers.h"
 #endif
 
+#include <vector>
+
 #include "src/base/platform/elapsed-timer.h"
+#include "src/base/platform/platform.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace v8 {
@@ -182,5 +185,77 @@
   }
 }
 
+
+// Disable on windows until it is implemented.
+#if V8_OS_ANDROID
+#define MAYBE_ThreadNow DISABLED_ThreadNow
+#else
+#define MAYBE_ThreadNow ThreadNow
+#endif
+TEST(ThreadTicks, MAYBE_ThreadNow) {
+  if (ThreadTicks::IsSupported()) {
+    TimeTicks begin = TimeTicks::Now();
+    ThreadTicks begin_thread = ThreadTicks::Now();
+    // Make sure that ThreadNow value is non-zero.
+    EXPECT_GT(begin_thread, ThreadTicks());
+    // Sleep for 10 milliseconds to get the thread de-scheduled.
+    OS::Sleep(base::TimeDelta::FromMilliseconds(10));
+    ThreadTicks end_thread = ThreadTicks::Now();
+    TimeTicks end = TimeTicks::Now();
+    TimeDelta delta = end - begin;
+    TimeDelta delta_thread = end_thread - begin_thread;
+    // Make sure that some thread time have elapsed.
+    EXPECT_GT(delta_thread.InMicroseconds(), 0);
+    // But the thread time is at least 9ms less than clock time.
+    TimeDelta difference = delta - delta_thread;
+    EXPECT_GE(difference.InMicroseconds(), 9000);
+  }
+}
+
+
+#if V8_OS_WIN
+TEST(TimeTicks, TimerPerformance) {
+  // Verify that various timer mechanisms can always complete quickly.
+  // Note:  This is a somewhat arbitrary test.
+  const int kLoops = 10000;
+
+  typedef TimeTicks (*TestFunc)();
+  struct TestCase {
+    TestFunc func;
+    const char *description;
+  };
+  // Cheating a bit here:  assumes sizeof(TimeTicks) == sizeof(Time)
+  // in order to create a single test case list.
+  static_assert(sizeof(TimeTicks) == sizeof(Time),
+                "TimeTicks and Time must be the same size");
+  std::vector<TestCase> cases;
+  cases.push_back({reinterpret_cast<TestFunc>(&Time::Now), "Time::Now"});
+  cases.push_back({&TimeTicks::Now, "TimeTicks::Now"});
+
+  if (ThreadTicks::IsSupported()) {
+    ThreadTicks::WaitUntilInitialized();
+    cases.push_back(
+        {reinterpret_cast<TestFunc>(&ThreadTicks::Now), "ThreadTicks::Now"});
+  }
+
+  for (const auto& test_case : cases) {
+    TimeTicks start = TimeTicks::Now();
+    for (int index = 0; index < kLoops; index++)
+      test_case.func();
+    TimeTicks stop = TimeTicks::Now();
+    // Turning off the check for acceptible delays.  Without this check,
+    // the test really doesn't do much other than measure.  But the
+    // measurements are still useful for testing timers on various platforms.
+    // The reason to remove the check is because the tests run on many
+    // buildbots, some of which are VMs.  These machines can run horribly
+    // slow, and there is really no value for checking against a max timer.
+    // const int kMaxTime = 35;  // Maximum acceptible milliseconds for test.
+    // EXPECT_LT((stop - start).InMilliseconds(), kMaxTime);
+    printf("%s: %1.2fus per call\n", test_case.description,
+           (stop - start).InMillisecondsF() * 1000 / kLoops);
+  }
+}
+#endif  // V8_OS_WIN
+
 }  // namespace base
 }  // namespace v8
diff --git a/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc b/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
index 72cfc51..fa03039 100644
--- a/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
+++ b/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
@@ -1392,8 +1392,8 @@
     EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
     EXPECT_EQ(kMode_Offset_RI, s[0]->addressing_mode());
     ASSERT_EQ(3U, s[0]->InputCount());
-    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
-    EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
+    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(2)->kind());
+    EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(2)));
     EXPECT_EQ(0U, s[0]->OutputCount());
   }
 }
@@ -1403,6 +1403,39 @@
                         InstructionSelectorMemoryAccessTest,
                         ::testing::ValuesIn(kMemoryAccesses));
 
+TEST_F(InstructionSelectorMemoryAccessTest, LoadWithShiftedIndex) {
+  TRACED_FORRANGE(int, immediate_shift, 1, 31) {
+    StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
+                    MachineType::Int32());
+    Node* const index =
+        m.Word32Shl(m.Parameter(1), m.Int32Constant(immediate_shift));
+    m.Return(m.Load(MachineType::Int32(), m.Parameter(0), index));
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArmLdr, s[0]->arch_opcode());
+    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+    EXPECT_EQ(3U, s[0]->InputCount());
+    EXPECT_EQ(1U, s[0]->OutputCount());
+  }
+}
+
+TEST_F(InstructionSelectorMemoryAccessTest, StoreWithShiftedIndex) {
+  TRACED_FORRANGE(int, immediate_shift, 1, 31) {
+    StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
+                    MachineType::Int32(), MachineType::Int32());
+    Node* const index =
+        m.Word32Shl(m.Parameter(1), m.Int32Constant(immediate_shift));
+    m.Store(MachineRepresentation::kWord32, m.Parameter(0), index,
+            m.Parameter(2), kNoWriteBarrier);
+    m.Return(m.Int32Constant(0));
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArmStr, s[0]->arch_opcode());
+    EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+    EXPECT_EQ(4U, s[0]->InputCount());
+    EXPECT_EQ(0U, s[0]->OutputCount());
+  }
+}
 
 // -----------------------------------------------------------------------------
 // Conversions.
@@ -2228,7 +2261,7 @@
                   MachineType::Int32(), MachineType::Int32());
   m.Return(
       m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
-  Stream s = m.Build(MLS);
+  Stream s = m.Build(ARMv7);
   ASSERT_EQ(1U, s.size());
   EXPECT_EQ(kArmMls, s[0]->arch_opcode());
   EXPECT_EQ(1U, s[0]->OutputCount());
@@ -2324,7 +2357,7 @@
   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
                   MachineType::Int32());
   m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
-  Stream s = m.Build(MLS, SUDIV);
+  Stream s = m.Build(ARMv7, SUDIV);
   ASSERT_EQ(2U, s.size());
   EXPECT_EQ(kArmSdiv, s[0]->arch_opcode());
   ASSERT_EQ(1U, s[0]->OutputCount());
@@ -2530,7 +2563,7 @@
   StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
                   MachineType::Int32());
   m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1)));
-  Stream s = m.Build(MLS, SUDIV);
+  Stream s = m.Build(ARMv7, SUDIV);
   ASSERT_EQ(2U, s.size());
   EXPECT_EQ(kArmUdiv, s[0]->arch_opcode());
   ASSERT_EQ(1U, s[0]->OutputCount());
@@ -2954,6 +2987,108 @@
   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
 }
 
+TEST_F(InstructionSelectorTest, Float32Max) {
+  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
+                  MachineType::Float32());
+  Node* const p0 = m.Parameter(0);
+  Node* const p1 = m.Parameter(1);
+  Node* const n = m.Float32Max(p0, p1);
+  m.Return(n);
+  Stream s = m.Build(ARMv8);
+  // Float32Max is `(b < a) ? a : b`.
+  ASSERT_EQ(1U, s.size());
+  EXPECT_EQ(kArmFloat32Max, s[0]->arch_opcode());
+  ASSERT_EQ(2U, s[0]->InputCount());
+  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+  ASSERT_EQ(1U, s[0]->OutputCount());
+  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
+TEST_F(InstructionSelectorTest, Float32Min) {
+  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
+                  MachineType::Float32());
+  Node* const p0 = m.Parameter(0);
+  Node* const p1 = m.Parameter(1);
+  Node* const n = m.Float32Min(p0, p1);
+  m.Return(n);
+  Stream s = m.Build(ARMv8);
+  // Float32Min is `(a < b) ? a : b`.
+  ASSERT_EQ(1U, s.size());
+  EXPECT_EQ(kArmFloat32Min, s[0]->arch_opcode());
+  ASSERT_EQ(2U, s[0]->InputCount());
+  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+  ASSERT_EQ(1U, s[0]->OutputCount());
+  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
+TEST_F(InstructionSelectorTest, Float64Max) {
+  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
+                  MachineType::Float64());
+  Node* const p0 = m.Parameter(0);
+  Node* const p1 = m.Parameter(1);
+  Node* const n = m.Float64Max(p0, p1);
+  m.Return(n);
+  Stream s = m.Build(ARMv8);
+  // Float64Max is `(b < a) ? a : b`.
+  ASSERT_EQ(1U, s.size());
+  EXPECT_EQ(kArmFloat64Max, s[0]->arch_opcode());
+  ASSERT_EQ(2U, s[0]->InputCount());
+  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+  ASSERT_EQ(1U, s[0]->OutputCount());
+  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
+TEST_F(InstructionSelectorTest, Float64Min) {
+  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
+                  MachineType::Float64());
+  Node* const p0 = m.Parameter(0);
+  Node* const p1 = m.Parameter(1);
+  Node* const n = m.Float64Min(p0, p1);
+  m.Return(n);
+  Stream s = m.Build(ARMv8);
+  // Float64Min is `(a < b) ? a : b`.
+  ASSERT_EQ(1U, s.size());
+  EXPECT_EQ(kArmFloat64Min, s[0]->arch_opcode());
+  ASSERT_EQ(2U, s[0]->InputCount());
+  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+  EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+  ASSERT_EQ(1U, s[0]->OutputCount());
+  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
+TEST_F(InstructionSelectorTest, Float32Neg) {
+  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
+  Node* const p0 = m.Parameter(0);
+  // Don't use m.Float32Neg() as that generates an explicit sub.
+  Node* const n = m.AddNode(m.machine()->Float32Neg().op(), m.Parameter(0));
+  m.Return(n);
+  Stream s = m.Build();
+  ASSERT_EQ(1U, s.size());
+  EXPECT_EQ(kArmVnegF32, s[0]->arch_opcode());
+  ASSERT_EQ(1U, s[0]->InputCount());
+  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+  ASSERT_EQ(1U, s[0]->OutputCount());
+  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
+TEST_F(InstructionSelectorTest, Float64Neg) {
+  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
+  Node* const p0 = m.Parameter(0);
+  // Don't use m.Float64Neg() as that generates an explicit sub.
+  Node* const n = m.AddNode(m.machine()->Float64Neg().op(), m.Parameter(0));
+  m.Return(n);
+  Stream s = m.Build();
+  ASSERT_EQ(1U, s.size());
+  EXPECT_EQ(kArmVnegF64, s[0]->arch_opcode());
+  ASSERT_EQ(1U, s[0]->InputCount());
+  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+  ASSERT_EQ(1U, s[0]->OutputCount());
+  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc b/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
index 73532aa..5fc210b 100644
--- a/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
+++ b/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
@@ -184,8 +184,11 @@
     {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
      kArm64Add32, MachineType::Int32()},
     {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
-     kArm64Sub32, MachineType::Int32()}};
-
+     kArm64Sub32, MachineType::Int32()},
+    {&RawMachineAssembler::Int64AddWithOverflow, "Int64AddWithOverflow",
+     kArm64Add, MachineType::Int64()},
+    {&RawMachineAssembler::Int64SubWithOverflow, "Int64SubWithOverflow",
+     kArm64Sub, MachineType::Int64()}};
 
 // ARM64 shift instructions.
 const Shift kShiftInstructions[] = {
@@ -326,6 +329,52 @@
       kArm64Float64ToUint32, MachineType::Uint32()},
      MachineType::Float64()}};
 
+// ARM64 instructions that clear the top 32 bits of the destination.
+const MachInst2 kCanElideChangeUint32ToUint64[] = {
+    {&RawMachineAssembler::Word32And, "Word32And", kArm64And32,
+     MachineType::Uint32()},
+    {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Or32,
+     MachineType::Uint32()},
+    {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Eor32,
+     MachineType::Uint32()},
+    {&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Lsl32,
+     MachineType::Uint32()},
+    {&RawMachineAssembler::Word32Shr, "Word32Shr", kArm64Lsr32,
+     MachineType::Uint32()},
+    {&RawMachineAssembler::Word32Sar, "Word32Sar", kArm64Asr32,
+     MachineType::Uint32()},
+    {&RawMachineAssembler::Word32Ror, "Word32Ror", kArm64Ror32,
+     MachineType::Uint32()},
+    {&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32,
+     MachineType::Uint32()},
+    {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32,
+     MachineType::Int32()},
+    {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
+     kArm64Add32, MachineType::Int32()},
+    {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32,
+     MachineType::Int32()},
+    {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
+     kArm64Sub32, MachineType::Int32()},
+    {&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32,
+     MachineType::Int32()},
+    {&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32,
+     MachineType::Int32()},
+    {&RawMachineAssembler::Int32Mod, "Int32Mod", kArm64Imod32,
+     MachineType::Int32()},
+    {&RawMachineAssembler::Int32LessThan, "Int32LessThan", kArm64Cmp32,
+     MachineType::Int32()},
+    {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
+     kArm64Cmp32, MachineType::Int32()},
+    {&RawMachineAssembler::Uint32Div, "Uint32Div", kArm64Udiv32,
+     MachineType::Uint32()},
+    {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kArm64Cmp32,
+     MachineType::Uint32()},
+    {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
+     kArm64Cmp32, MachineType::Uint32()},
+    {&RawMachineAssembler::Uint32Mod, "Uint32Mod", kArm64Umod32,
+     MachineType::Uint32()},
+};
+
 }  // namespace
 
 
@@ -1132,7 +1181,6 @@
   }
 }
 
-
 TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnLeft) {
   TRACED_FORRANGE(int, bit, 0, 31) {
     uint32_t mask = 1 << bit;
@@ -1215,6 +1263,91 @@
   }
 }
 
+TEST_F(InstructionSelectorTest, Word32EqualZeroAndBranchWithOneBitMask) {
+  TRACED_FORRANGE(int, bit, 0, 31) {
+    uint32_t mask = 1 << bit;
+    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+    RawMachineLabel a, b;
+    m.Branch(m.Word32Equal(m.Word32And(m.Int32Constant(mask), m.Parameter(0)),
+                           m.Int32Constant(0)),
+             &a, &b);
+    m.Bind(&a);
+    m.Return(m.Int32Constant(1));
+    m.Bind(&b);
+    m.Return(m.Int32Constant(0));
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
+    EXPECT_EQ(kEqual, s[0]->flags_condition());
+    EXPECT_EQ(4U, s[0]->InputCount());
+    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
+    EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
+  }
+
+  TRACED_FORRANGE(int, bit, 0, 31) {
+    uint32_t mask = 1 << bit;
+    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+    RawMachineLabel a, b;
+    m.Branch(
+        m.Word32NotEqual(m.Word32And(m.Int32Constant(mask), m.Parameter(0)),
+                         m.Int32Constant(0)),
+        &a, &b);
+    m.Bind(&a);
+    m.Return(m.Int32Constant(1));
+    m.Bind(&b);
+    m.Return(m.Int32Constant(0));
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
+    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
+    EXPECT_EQ(4U, s[0]->InputCount());
+    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
+    EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
+  }
+}
+
+TEST_F(InstructionSelectorTest, Word64EqualZeroAndBranchWithOneBitMask) {
+  TRACED_FORRANGE(int, bit, 0, 63) {
+    uint64_t mask = V8_UINT64_C(1) << bit;
+    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
+    RawMachineLabel a, b;
+    m.Branch(m.Word64Equal(m.Word64And(m.Int64Constant(mask), m.Parameter(0)),
+                           m.Int64Constant(0)),
+             &a, &b);
+    m.Bind(&a);
+    m.Return(m.Int64Constant(1));
+    m.Bind(&b);
+    m.Return(m.Int64Constant(0));
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
+    EXPECT_EQ(kEqual, s[0]->flags_condition());
+    EXPECT_EQ(4U, s[0]->InputCount());
+    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
+    EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
+  }
+
+  TRACED_FORRANGE(int, bit, 0, 63) {
+    uint64_t mask = V8_UINT64_C(1) << bit;
+    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
+    RawMachineLabel a, b;
+    m.Branch(
+        m.Word64NotEqual(m.Word64And(m.Int64Constant(mask), m.Parameter(0)),
+                         m.Int64Constant(0)),
+        &a, &b);
+    m.Bind(&a);
+    m.Return(m.Int64Constant(1));
+    m.Bind(&b);
+    m.Return(m.Int64Constant(0));
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
+    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
+    EXPECT_EQ(4U, s[0]->InputCount());
+    EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
+    EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
+  }
+}
 
 TEST_F(InstructionSelectorTest, CompareAgainstZeroAndBranch) {
   {
@@ -1252,6 +1385,75 @@
   }
 }
 
+TEST_F(InstructionSelectorTest, EqualZeroAndBranch) {
+  {
+    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+    RawMachineLabel a, b;
+    Node* p0 = m.Parameter(0);
+    m.Branch(m.Word32Equal(p0, m.Int32Constant(0)), &a, &b);
+    m.Bind(&a);
+    m.Return(m.Int32Constant(1));
+    m.Bind(&b);
+    m.Return(m.Int32Constant(0));
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
+    EXPECT_EQ(kEqual, s[0]->flags_condition());
+    EXPECT_EQ(3U, s[0]->InputCount());
+    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+  }
+
+  {
+    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+    RawMachineLabel a, b;
+    Node* p0 = m.Parameter(0);
+    m.Branch(m.Word32NotEqual(p0, m.Int32Constant(0)), &a, &b);
+    m.Bind(&a);
+    m.Return(m.Int32Constant(1));
+    m.Bind(&b);
+    m.Return(m.Int32Constant(0));
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
+    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
+    EXPECT_EQ(3U, s[0]->InputCount());
+    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+  }
+
+  {
+    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
+    RawMachineLabel a, b;
+    Node* p0 = m.Parameter(0);
+    m.Branch(m.Word64Equal(p0, m.Int64Constant(0)), &a, &b);
+    m.Bind(&a);
+    m.Return(m.Int64Constant(1));
+    m.Bind(&b);
+    m.Return(m.Int64Constant(0));
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArm64CompareAndBranch, s[0]->arch_opcode());
+    EXPECT_EQ(kEqual, s[0]->flags_condition());
+    EXPECT_EQ(3U, s[0]->InputCount());
+    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+  }
+
+  {
+    StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
+    RawMachineLabel a, b;
+    Node* p0 = m.Parameter(0);
+    m.Branch(m.Word64NotEqual(p0, m.Int64Constant(0)), &a, &b);
+    m.Bind(&a);
+    m.Return(m.Int64Constant(1));
+    m.Bind(&b);
+    m.Return(m.Int64Constant(0));
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArm64CompareAndBranch, s[0]->arch_opcode());
+    EXPECT_EQ(kNotEqual, s[0]->flags_condition());
+    EXPECT_EQ(3U, s[0]->InputCount());
+    EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+  }
+}
 
 // -----------------------------------------------------------------------------
 // Add and subtract instructions with overflow.
@@ -1407,6 +1609,29 @@
   }
 }
 
+TEST_P(InstructionSelectorOvfAddSubTest, RORShift) {
+  // ADD and SUB do not support ROR shifts, make sure we do not try
+  // to merge them into the ADD/SUB instruction.
+  const MachInst2 dpi = GetParam();
+  const MachineType type = dpi.machine_type;
+  auto rotate = &RawMachineAssembler::Word64Ror;
+  ArchOpcode rotate_opcode = kArm64Ror;
+  if (type == MachineType::Int32()) {
+    rotate = &RawMachineAssembler::Word32Ror;
+    rotate_opcode = kArm64Ror32;
+  }
+  TRACED_FORRANGE(int32_t, imm, -32, 63) {
+    StreamBuilder m(this, type, type, type);
+    Node* const p0 = m.Parameter(0);
+    Node* const p1 = m.Parameter(1);
+    Node* r = (m.*rotate)(p1, m.Int32Constant(imm));
+    m.Return((m.*dpi.constructor)(p0, r));
+    Stream s = m.Build();
+    ASSERT_EQ(2U, s.size());
+    EXPECT_EQ(rotate_opcode, s[0]->arch_opcode());
+    EXPECT_EQ(dpi.arch_opcode, s[1]->arch_opcode());
+  }
+}
 
 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
                         InstructionSelectorOvfAddSubTest,
@@ -2105,6 +2330,71 @@
                         InstructionSelectorConversionTest,
                         ::testing::ValuesIn(kConversionInstructions));
 
+typedef InstructionSelectorTestWithParam<MachInst2>
+    InstructionSelectorElidedChangeUint32ToUint64Test;
+
+TEST_P(InstructionSelectorElidedChangeUint32ToUint64Test, Parameter) {
+  const MachInst2 binop = GetParam();
+  StreamBuilder m(this, MachineType::Uint64(), binop.machine_type,
+                  binop.machine_type);
+  m.Return(m.ChangeUint32ToUint64(
+      (m.*binop.constructor)(m.Parameter(0), m.Parameter(1))));
+  Stream s = m.Build();
+  // Make sure the `ChangeUint32ToUint64` node turned into a no-op.
+  ASSERT_EQ(1U, s.size());
+  EXPECT_EQ(binop.arch_opcode, s[0]->arch_opcode());
+  EXPECT_EQ(2U, s[0]->InputCount());
+  EXPECT_EQ(1U, s[0]->OutputCount());
+}
+
+INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
+                        InstructionSelectorElidedChangeUint32ToUint64Test,
+                        ::testing::ValuesIn(kCanElideChangeUint32ToUint64));
+
+TEST_F(InstructionSelectorTest, ChangeUint32ToUint64AfterLoad) {
+  // For each case, make sure the `ChangeUint32ToUint64` node turned into a
+  // no-op.
+
+  // Ldrb
+  {
+    StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
+                    MachineType::Int32());
+    m.Return(m.ChangeUint32ToUint64(
+        m.Load(MachineType::Uint8(), m.Parameter(0), m.Parameter(1))));
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArm64Ldrb, s[0]->arch_opcode());
+    EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
+    EXPECT_EQ(2U, s[0]->InputCount());
+    EXPECT_EQ(1U, s[0]->OutputCount());
+  }
+  // Ldrh
+  {
+    StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
+                    MachineType::Int32());
+    m.Return(m.ChangeUint32ToUint64(
+        m.Load(MachineType::Uint16(), m.Parameter(0), m.Parameter(1))));
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArm64Ldrh, s[0]->arch_opcode());
+    EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
+    EXPECT_EQ(2U, s[0]->InputCount());
+    EXPECT_EQ(1U, s[0]->OutputCount());
+  }
+  // LdrW
+  {
+    StreamBuilder m(this, MachineType::Uint64(), MachineType::Pointer(),
+                    MachineType::Int32());
+    m.Return(m.ChangeUint32ToUint64(
+        m.Load(MachineType::Uint32(), m.Parameter(0), m.Parameter(1))));
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArm64LdrW, s[0]->arch_opcode());
+    EXPECT_EQ(kMode_MRR, s[0]->addressing_mode());
+    EXPECT_EQ(2U, s[0]->InputCount());
+    EXPECT_EQ(1U, s[0]->OutputCount());
+  }
+}
 
 // -----------------------------------------------------------------------------
 // Memory access instructions.
@@ -2244,12 +2534,131 @@
     EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
     EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
     ASSERT_EQ(3U, s[0]->InputCount());
-    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
-    EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
+    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(2)->kind());
+    EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(2)));
     EXPECT_EQ(0U, s[0]->OutputCount());
   }
 }
 
+TEST_P(InstructionSelectorMemoryAccessTest, StoreZero) {
+  const MemoryAccess memacc = GetParam();
+  TRACED_FOREACH(int32_t, index, memacc.immediates) {
+    StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer());
+    m.Store(memacc.type.representation(), m.Parameter(0),
+            m.Int32Constant(index), m.Int32Constant(0), kNoWriteBarrier);
+    m.Return(m.Int32Constant(0));
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
+    EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
+    ASSERT_EQ(3U, s[0]->InputCount());
+    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(2)->kind());
+    EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(2)));
+    ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(0)->kind());
+    EXPECT_EQ(0, s.ToInt64(s[0]->InputAt(0)));
+    EXPECT_EQ(0U, s[0]->OutputCount());
+  }
+}
+
+TEST_P(InstructionSelectorMemoryAccessTest, LoadWithShiftedIndex) {
+  const MemoryAccess memacc = GetParam();
+  TRACED_FORRANGE(int, immediate_shift, 0, 4) {
+    // 32 bit shift
+    {
+      StreamBuilder m(this, memacc.type, MachineType::Pointer(),
+                      MachineType::Int32());
+      Node* const index =
+          m.Word32Shl(m.Parameter(1), m.Int32Constant(immediate_shift));
+      m.Return(m.Load(memacc.type, m.Parameter(0), index));
+      Stream s = m.Build();
+      if (immediate_shift == ElementSizeLog2Of(memacc.type.representation())) {
+        ASSERT_EQ(1U, s.size());
+        EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
+        EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+        EXPECT_EQ(3U, s[0]->InputCount());
+        EXPECT_EQ(1U, s[0]->OutputCount());
+      } else {
+        // Make sure we haven't merged the shift into the load instruction.
+        ASSERT_NE(1U, s.size());
+        EXPECT_NE(memacc.ldr_opcode, s[0]->arch_opcode());
+        EXPECT_NE(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+      }
+    }
+    // 64 bit shift
+    {
+      StreamBuilder m(this, memacc.type, MachineType::Pointer(),
+                      MachineType::Int64());
+      Node* const index =
+          m.Word64Shl(m.Parameter(1), m.Int64Constant(immediate_shift));
+      m.Return(m.Load(memacc.type, m.Parameter(0), index));
+      Stream s = m.Build();
+      if (immediate_shift == ElementSizeLog2Of(memacc.type.representation())) {
+        ASSERT_EQ(1U, s.size());
+        EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
+        EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+        EXPECT_EQ(3U, s[0]->InputCount());
+        EXPECT_EQ(1U, s[0]->OutputCount());
+      } else {
+        // Make sure we haven't merged the shift into the load instruction.
+        ASSERT_NE(1U, s.size());
+        EXPECT_NE(memacc.ldr_opcode, s[0]->arch_opcode());
+        EXPECT_NE(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+      }
+    }
+  }
+}
+
+TEST_P(InstructionSelectorMemoryAccessTest, StoreWithShiftedIndex) {
+  const MemoryAccess memacc = GetParam();
+  TRACED_FORRANGE(int, immediate_shift, 0, 4) {
+    // 32 bit shift
+    {
+      StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(),
+                      MachineType::Int32(), memacc.type);
+      Node* const index =
+          m.Word32Shl(m.Parameter(1), m.Int32Constant(immediate_shift));
+      m.Store(memacc.type.representation(), m.Parameter(0), index,
+              m.Parameter(2), kNoWriteBarrier);
+      m.Return(m.Int32Constant(0));
+      Stream s = m.Build();
+      if (immediate_shift == ElementSizeLog2Of(memacc.type.representation())) {
+        ASSERT_EQ(1U, s.size());
+        EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
+        EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+        EXPECT_EQ(4U, s[0]->InputCount());
+        EXPECT_EQ(0U, s[0]->OutputCount());
+      } else {
+        // Make sure we haven't merged the shift into the store instruction.
+        ASSERT_NE(1U, s.size());
+        EXPECT_NE(memacc.str_opcode, s[0]->arch_opcode());
+        EXPECT_NE(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+      }
+    }
+    // 64 bit shift
+    {
+      StreamBuilder m(this, MachineType::Int64(), MachineType::Pointer(),
+                      MachineType::Int64(), memacc.type);
+      Node* const index =
+          m.Word64Shl(m.Parameter(1), m.Int64Constant(immediate_shift));
+      m.Store(memacc.type.representation(), m.Parameter(0), index,
+              m.Parameter(2), kNoWriteBarrier);
+      m.Return(m.Int64Constant(0));
+      Stream s = m.Build();
+      if (immediate_shift == ElementSizeLog2Of(memacc.type.representation())) {
+        ASSERT_EQ(1U, s.size());
+        EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode());
+        EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+        EXPECT_EQ(4U, s[0]->InputCount());
+        EXPECT_EQ(0U, s[0]->OutputCount());
+      } else {
+        // Make sure we haven't merged the shift into the store instruction.
+        ASSERT_NE(1U, s.size());
+        EXPECT_NE(memacc.str_opcode, s[0]->arch_opcode());
+        EXPECT_NE(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
+      }
+    }
+  }
+}
 
 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
                         InstructionSelectorMemoryAccessTest,
@@ -2616,6 +3025,7 @@
 struct IntegerCmp {
   MachInst2 mi;
   FlagsCondition cond;
+  FlagsCondition commuted_cond;
 };
 
 
@@ -2628,19 +3038,24 @@
 const IntegerCmp kIntegerCmpInstructions[] = {
     {{&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32,
       MachineType::Int32()},
+     kEqual,
      kEqual},
     {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kArm64Cmp32,
       MachineType::Int32()},
-     kSignedLessThan},
+     kSignedLessThan,
+     kSignedGreaterThan},
     {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
       kArm64Cmp32, MachineType::Int32()},
-     kSignedLessThanOrEqual},
+     kSignedLessThanOrEqual,
+     kSignedGreaterThanOrEqual},
     {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kArm64Cmp32,
       MachineType::Uint32()},
-     kUnsignedLessThan},
+     kUnsignedLessThan,
+     kUnsignedGreaterThan},
     {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
       kArm64Cmp32, MachineType::Uint32()},
-     kUnsignedLessThanOrEqual}};
+     kUnsignedLessThanOrEqual,
+     kUnsignedGreaterThanOrEqual}};
 
 }  // namespace
 
@@ -2677,6 +3092,156 @@
   }
 }
 
+TEST_F(InstructionSelectorTest, CmpWithImmediateOnLeft) {
+  TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
+    TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
+      // kEqual and kNotEqual trigger the cbz/cbnz optimization, which
+      // is tested elsewhere.
+      if (cmp.cond == kEqual || cmp.cond == kNotEqual) continue;
+      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+      Node* const p0 = m.Parameter(0);
+      RawMachineLabel a, b;
+      m.Branch((m.*cmp.mi.constructor)(m.Int32Constant(imm), p0), &a, &b);
+      m.Bind(&a);
+      m.Return(m.Int32Constant(1));
+      m.Bind(&b);
+      m.Return(m.Int32Constant(0));
+      Stream s = m.Build();
+      ASSERT_EQ(1U, s.size());
+      EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
+      ASSERT_LE(2U, s[0]->InputCount());
+      EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+      EXPECT_EQ(cmp.commuted_cond, s[0]->flags_condition());
+      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
+    }
+  }
+}
+
+TEST_F(InstructionSelectorTest, CmnWithImmediateOnLeft) {
+  TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
+    TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
+      // kEqual and kNotEqual trigger the cbz/cbnz optimization, which
+      // is tested elsewhere.
+      if (cmp.cond == kEqual || cmp.cond == kNotEqual) continue;
+      StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+      Node* sub = m.Int32Sub(m.Int32Constant(0), m.Parameter(0));
+      RawMachineLabel a, b;
+      m.Branch((m.*cmp.mi.constructor)(m.Int32Constant(imm), sub), &a, &b);
+      m.Bind(&a);
+      m.Return(m.Int32Constant(1));
+      m.Bind(&b);
+      m.Return(m.Int32Constant(0));
+      Stream s = m.Build();
+      ASSERT_EQ(1U, s.size());
+      EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
+      ASSERT_LE(2U, s[0]->InputCount());
+      EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+      EXPECT_EQ(cmp.cond, s[0]->flags_condition());
+      EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
+    }
+  }
+}
+
+TEST_F(InstructionSelectorTest, CmpSignedExtendByteOnLeft) {
+  TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
+    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
+                    MachineType::Int32());
+    Node* extend = m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(24)),
+                               m.Int32Constant(24));
+    m.Return((m.*cmp.mi.constructor)(extend, m.Parameter(1)));
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
+    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
+    EXPECT_EQ(cmp.commuted_cond, s[0]->flags_condition());
+    EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
+  }
+}
+
+TEST_F(InstructionSelectorTest, CmnSignedExtendByteOnLeft) {
+  TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
+    StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
+                    MachineType::Int32());
+    Node* sub = m.Int32Sub(m.Int32Constant(0), m.Parameter(0));
+    Node* extend = m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(24)),
+                               m.Int32Constant(24));
+    m.Return((m.*cmp.mi.constructor)(extend, sub));
+    Stream s = m.Build();
+    ASSERT_EQ(1U, s.size());
+    EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
+    EXPECT_EQ(kFlags_set, s[0]->flags_mode());
+    EXPECT_EQ(cmp.cond, s[0]->flags_condition());
+    EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode());
+  }
+}
+
+TEST_F(InstructionSelectorTest, CmpShiftByImmediateOnLeft) {
+  TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
+    TRACED_FOREACH(Shift, shift, kShiftInstructions) {
+      // Only test relevant shifted operands.
+      if (shift.mi.machine_type != MachineType::Int32()) continue;
+
+      // The available shift operand range is `0 <= imm < 32`, but we also test
+      // that immediates outside this range are handled properly (modulo-32).
+      TRACED_FORRANGE(int, imm, -32, 63) {
+        StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
+                        MachineType::Int32());
+        m.Return((m.*cmp.mi.constructor)(
+            (m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm)),
+            m.Parameter(0)));
+        Stream s = m.Build();
+        // Cmp does not support ROR shifts.
+        if (shift.mi.arch_opcode == kArm64Ror32) {
+          ASSERT_EQ(2U, s.size());
+          continue;
+        }
+        ASSERT_EQ(1U, s.size());
+        EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
+        EXPECT_EQ(shift.mode, s[0]->addressing_mode());
+        EXPECT_EQ(3U, s[0]->InputCount());
+        EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
+        EXPECT_EQ(1U, s[0]->OutputCount());
+        EXPECT_EQ(kFlags_set, s[0]->flags_mode());
+        EXPECT_EQ(cmp.commuted_cond, s[0]->flags_condition());
+      }
+    }
+  }
+}
+
+TEST_F(InstructionSelectorTest, CmnShiftByImmediateOnLeft) {
+  TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
+    TRACED_FOREACH(Shift, shift, kShiftInstructions) {
+      // Only test relevant shifted operands.
+      if (shift.mi.machine_type != MachineType::Int32()) continue;
+
+      // The available shift operand range is `0 <= imm < 32`, but we also test
+      // that immediates outside this range are handled properly (modulo-32).
+      TRACED_FORRANGE(int, imm, -32, 63) {
+        StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
+                        MachineType::Int32());
+        Node* sub = m.Int32Sub(m.Int32Constant(0), m.Parameter(0));
+        m.Return((m.*cmp.mi.constructor)(
+            (m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm)),
+            sub));
+        Stream s = m.Build();
+        // Cmn does not support ROR shifts.
+        if (shift.mi.arch_opcode == kArm64Ror32) {
+          ASSERT_EQ(2U, s.size());
+          continue;
+        }
+        ASSERT_EQ(1U, s.size());
+        EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
+        EXPECT_EQ(shift.mode, s[0]->addressing_mode());
+        EXPECT_EQ(3U, s[0]->InputCount());
+        EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
+        EXPECT_EQ(1U, s[0]->OutputCount());
+        EXPECT_EQ(kFlags_set, s[0]->flags_mode());
+        EXPECT_EQ(cmp.cond, s[0]->flags_condition());
+      }
+    }
+  }
+}
+
 
 // -----------------------------------------------------------------------------
 // Miscellaneous
@@ -3344,6 +3909,36 @@
   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
 }
 
+TEST_F(InstructionSelectorTest, Float32Neg) {
+  StreamBuilder m(this, MachineType::Float32(), MachineType::Float32());
+  Node* const p0 = m.Parameter(0);
+  // Don't use m.Float32Neg() as that generates an explicit sub.
+  Node* const n = m.AddNode(m.machine()->Float32Neg().op(), m.Parameter(0));
+  m.Return(n);
+  Stream s = m.Build();
+  ASSERT_EQ(1U, s.size());
+  EXPECT_EQ(kArm64Float32Neg, s[0]->arch_opcode());
+  ASSERT_EQ(1U, s[0]->InputCount());
+  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+  ASSERT_EQ(1U, s[0]->OutputCount());
+  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
+TEST_F(InstructionSelectorTest, Float64Neg) {
+  StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
+  Node* const p0 = m.Parameter(0);
+  // Don't use m.Float64Neg() as that generates an explicit sub.
+  Node* const n = m.AddNode(m.machine()->Float64Neg().op(), m.Parameter(0));
+  m.Return(n);
+  Stream s = m.Build();
+  ASSERT_EQ(1U, s.size());
+  EXPECT_EQ(kArm64Float64Neg, s[0]->arch_opcode());
+  ASSERT_EQ(1U, s[0]->InputCount());
+  EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+  ASSERT_EQ(1U, s[0]->OutputCount());
+  EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/test/unittests/compiler/change-lowering-unittest.cc b/test/unittests/compiler/change-lowering-unittest.cc
deleted file mode 100644
index fd0766c..0000000
--- a/test/unittests/compiler/change-lowering-unittest.cc
+++ /dev/null
@@ -1,628 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/code-stubs.h"
-#include "src/compiler/change-lowering.h"
-#include "src/compiler/js-graph.h"
-#include "src/compiler/linkage.h"
-#include "src/compiler/node-properties.h"
-#include "src/compiler/simplified-operator.h"
-#include "test/unittests/compiler/compiler-test-utils.h"
-#include "test/unittests/compiler/graph-unittest.h"
-#include "test/unittests/compiler/node-test-utils.h"
-#include "testing/gmock-support.h"
-
-using testing::_;
-using testing::AllOf;
-using testing::BitEq;
-using testing::Capture;
-using testing::CaptureEq;
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-class ChangeLoweringTest : public TypedGraphTest {
- public:
-  ChangeLoweringTest() : simplified_(zone()) {}
-
-  virtual MachineRepresentation WordRepresentation() const = 0;
-
- protected:
-  bool Is32() const {
-    return WordRepresentation() == MachineRepresentation::kWord32;
-  }
-  bool Is64() const {
-    return WordRepresentation() == MachineRepresentation::kWord64;
-  }
-
-  Reduction Reduce(Node* node) {
-    MachineOperatorBuilder machine(zone(), WordRepresentation());
-    JSOperatorBuilder javascript(zone());
-    JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr,
-                    &machine);
-    ChangeLowering reducer(&jsgraph);
-    return reducer.Reduce(node);
-  }
-
-  SimplifiedOperatorBuilder* simplified() { return &simplified_; }
-
-  Matcher<Node*> IsAllocateHeapNumber(const Matcher<Node*>& effect_matcher,
-                                      const Matcher<Node*>& control_matcher) {
-    return IsCall(
-        _, IsHeapConstant(AllocateHeapNumberStub(isolate()).GetCode()),
-        IsNumberConstant(BitEq(0.0)), effect_matcher, control_matcher);
-  }
-  Matcher<Node*> IsChangeInt32ToSmi(const Matcher<Node*>& value_matcher) {
-    return Is64() ? IsWord64Shl(IsChangeInt32ToInt64(value_matcher),
-                                IsSmiShiftBitsConstant())
-                  : IsWord32Shl(value_matcher, IsSmiShiftBitsConstant());
-  }
-  Matcher<Node*> IsChangeSmiToInt32(const Matcher<Node*>& value_matcher) {
-    return Is64() ? IsTruncateInt64ToInt32(
-                        IsWord64Sar(value_matcher, IsSmiShiftBitsConstant()))
-                  : IsWord32Sar(value_matcher, IsSmiShiftBitsConstant());
-  }
-  Matcher<Node*> IsChangeUint32ToSmi(const Matcher<Node*>& value_matcher) {
-    return Is64() ? IsWord64Shl(IsChangeUint32ToUint64(value_matcher),
-                                IsSmiShiftBitsConstant())
-                  : IsWord32Shl(value_matcher, IsSmiShiftBitsConstant());
-  }
-  Matcher<Node*> IsLoadHeapNumber(const Matcher<Node*>& value_matcher,
-                                  const Matcher<Node*>& control_matcher) {
-    return IsLoad(MachineType::Float64(), value_matcher,
-                  IsIntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag),
-                  graph()->start(), control_matcher);
-  }
-  Matcher<Node*> IsIntPtrConstant(int value) {
-    return Is32() ? IsInt32Constant(value) : IsInt64Constant(value);
-  }
-  Matcher<Node*> IsSmiShiftBitsConstant() {
-    return IsIntPtrConstant(kSmiShiftSize + kSmiTagSize);
-  }
-  Matcher<Node*> IsWordEqual(const Matcher<Node*>& lhs_matcher,
-                             const Matcher<Node*>& rhs_matcher) {
-    return Is32() ? IsWord32Equal(lhs_matcher, rhs_matcher)
-                  : IsWord64Equal(lhs_matcher, rhs_matcher);
-  }
-
- private:
-  SimplifiedOperatorBuilder simplified_;
-};
-
-
-// -----------------------------------------------------------------------------
-// Common.
-
-
-class ChangeLoweringCommonTest
-    : public ChangeLoweringTest,
-      public ::testing::WithParamInterface<MachineRepresentation> {
- public:
-  ~ChangeLoweringCommonTest() override {}
-
-  MachineRepresentation WordRepresentation() const final { return GetParam(); }
-};
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBitToBool) {
-  Node* value = Parameter(Type::Boolean());
-  Reduction r =
-      Reduce(graph()->NewNode(simplified()->ChangeBitToBool(), value));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(), IsSelect(MachineRepresentation::kTagged, value,
-                                        IsTrueConstant(), IsFalseConstant()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBoolToBit) {
-  Node* value = Parameter(Type::Number());
-  Reduction r =
-      Reduce(graph()->NewNode(simplified()->ChangeBoolToBit(), value));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(), IsWordEqual(value, IsTrueConstant()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, ChangeInt32ToTaggedWithSignedSmall) {
-  Node* value = Parameter(Type::SignedSmall());
-  Reduction r =
-      Reduce(graph()->NewNode(simplified()->ChangeInt32ToTagged(), value));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(), IsChangeInt32ToSmi(value));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, ChangeUint32ToTaggedWithUnsignedSmall) {
-  Node* value = Parameter(Type::UnsignedSmall());
-  Reduction r =
-      Reduce(graph()->NewNode(simplified()->ChangeUint32ToTagged(), value));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(), IsChangeUint32ToSmi(value));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToInt32WithTaggedSigned) {
-  Node* value = Parameter(Type::TaggedSigned());
-  Reduction r =
-      Reduce(graph()->NewNode(simplified()->ChangeTaggedToInt32(), value));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(), IsChangeSmiToInt32(value));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToInt32WithTaggedPointer) {
-  Node* value = Parameter(Type::TaggedPointer());
-  Reduction r =
-      Reduce(graph()->NewNode(simplified()->ChangeTaggedToInt32(), value));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(), IsChangeFloat64ToInt32(
-                                   IsLoadHeapNumber(value, graph()->start())));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToUint32WithTaggedSigned) {
-  Node* value = Parameter(Type::TaggedSigned());
-  Reduction r =
-      Reduce(graph()->NewNode(simplified()->ChangeTaggedToUint32(), value));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(), IsChangeSmiToInt32(value));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToUint32WithTaggedPointer) {
-  Node* value = Parameter(Type::TaggedPointer());
-  Reduction r =
-      Reduce(graph()->NewNode(simplified()->ChangeTaggedToUint32(), value));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(), IsChangeFloat64ToUint32(
-                                   IsLoadHeapNumber(value, graph()->start())));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, StoreFieldSmi) {
-  FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
-                        Handle<Name>::null(), Type::Any(),
-                        MachineType::AnyTagged()};
-  Node* p0 = Parameter(Type::TaggedPointer());
-  Node* p1 = Parameter(Type::TaggedSigned());
-  Node* store = graph()->NewNode(simplified()->StoreField(access), p0, p1,
-                                 graph()->start(), graph()->start());
-  Reduction r = Reduce(store);
-
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(),
-              IsStore(StoreRepresentation(MachineRepresentation::kTagged,
-                                          kNoWriteBarrier),
-                      p0, IsIntPtrConstant(access.offset - access.tag()), p1,
-                      graph()->start(), graph()->start()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, StoreFieldTagged) {
-  FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
-                        Handle<Name>::null(), Type::Any(),
-                        MachineType::AnyTagged()};
-  Node* p0 = Parameter(Type::TaggedPointer());
-  Node* p1 = Parameter(Type::Tagged());
-  Node* store = graph()->NewNode(simplified()->StoreField(access), p0, p1,
-                                 graph()->start(), graph()->start());
-  Reduction r = Reduce(store);
-
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(),
-              IsStore(StoreRepresentation(MachineRepresentation::kTagged,
-                                          kFullWriteBarrier),
-                      p0, IsIntPtrConstant(access.offset - access.tag()), p1,
-                      graph()->start(), graph()->start()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, LoadField) {
-  FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
-                        Handle<Name>::null(), Type::Any(),
-                        MachineType::AnyTagged()};
-  Node* p0 = Parameter(Type::TaggedPointer());
-  Node* load = graph()->NewNode(simplified()->LoadField(access), p0,
-                                graph()->start(), graph()->start());
-  Reduction r = Reduce(load);
-
-  ASSERT_TRUE(r.Changed());
-  Matcher<Node*> index_match = IsIntPtrConstant(access.offset - access.tag());
-  EXPECT_THAT(r.replacement(),
-              IsLoad(MachineType::AnyTagged(), p0,
-                     IsIntPtrConstant(access.offset - access.tag()),
-                     graph()->start(), graph()->start()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, StoreElementTagged) {
-  ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
-                          MachineType::AnyTagged()};
-  Node* p0 = Parameter(Type::TaggedPointer());
-  Node* p1 = Parameter(Type::Signed32());
-  Node* p2 = Parameter(Type::Tagged());
-  Node* store = graph()->NewNode(simplified()->StoreElement(access), p0, p1, p2,
-                                 graph()->start(), graph()->start());
-  Reduction r = Reduce(store);
-
-  const int element_size_shift =
-      ElementSizeLog2Of(access.machine_type.representation());
-  ASSERT_TRUE(r.Changed());
-  Matcher<Node*> index_match =
-      IsInt32Add(IsWord32Shl(p1, IsInt32Constant(element_size_shift)),
-                 IsInt32Constant(access.header_size - access.tag()));
-  if (!Is32()) {
-    index_match = IsChangeUint32ToUint64(index_match);
-  }
-
-  EXPECT_THAT(r.replacement(),
-              IsStore(StoreRepresentation(MachineRepresentation::kTagged,
-                                          kFullWriteBarrier),
-                      p0, index_match, p2, graph()->start(), graph()->start()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, StoreElementUint8) {
-  ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
-                          Type::Signed32(), MachineType::Uint8()};
-  Node* p0 = Parameter(Type::TaggedPointer());
-  Node* p1 = Parameter(Type::Signed32());
-  Node* p2 = Parameter(Type::Signed32());
-  Node* store = graph()->NewNode(simplified()->StoreElement(access), p0, p1, p2,
-                                 graph()->start(), graph()->start());
-  Reduction r = Reduce(store);
-
-  ASSERT_TRUE(r.Changed());
-  Matcher<Node*> index_match =
-      IsInt32Add(p1, IsInt32Constant(access.header_size - access.tag()));
-  if (!Is32()) {
-    index_match = IsChangeUint32ToUint64(index_match);
-  }
-
-  EXPECT_THAT(r.replacement(),
-              IsStore(StoreRepresentation(MachineRepresentation::kWord8,
-                                          kNoWriteBarrier),
-                      p0, index_match, p2, graph()->start(), graph()->start()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, LoadElementTagged) {
-  ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
-                          MachineType::AnyTagged()};
-  Node* p0 = Parameter(Type::TaggedPointer());
-  Node* p1 = Parameter(Type::Signed32());
-  Node* load = graph()->NewNode(simplified()->LoadElement(access), p0, p1,
-                                graph()->start(), graph()->start());
-  Reduction r = Reduce(load);
-
-  const int element_size_shift =
-      ElementSizeLog2Of(access.machine_type.representation());
-  ASSERT_TRUE(r.Changed());
-  Matcher<Node*> index_match =
-      IsInt32Add(IsWord32Shl(p1, IsInt32Constant(element_size_shift)),
-                 IsInt32Constant(access.header_size - access.tag()));
-  if (!Is32()) {
-    index_match = IsChangeUint32ToUint64(index_match);
-  }
-
-  EXPECT_THAT(r.replacement(), IsLoad(MachineType::AnyTagged(), p0, index_match,
-                                      graph()->start(), graph()->start()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, LoadElementInt8) {
-  ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
-                          Type::Signed32(), MachineType::Int8()};
-  Node* p0 = Parameter(Type::TaggedPointer());
-  Node* p1 = Parameter(Type::Signed32());
-  Node* load = graph()->NewNode(simplified()->LoadElement(access), p0, p1,
-                                graph()->start(), graph()->start());
-  Reduction r = Reduce(load);
-
-  ASSERT_TRUE(r.Changed());
-  Matcher<Node*> index_match =
-      IsInt32Add(p1, IsInt32Constant(access.header_size - access.tag()));
-  if (!Is32()) {
-    index_match = IsChangeUint32ToUint64(index_match);
-  }
-
-  EXPECT_THAT(r.replacement(), IsLoad(MachineType::Int8(), p0, index_match,
-                                      graph()->start(), graph()->start()));
-}
-
-
-TARGET_TEST_P(ChangeLoweringCommonTest, Allocate) {
-  Node* p0 = Parameter(Type::Signed32());
-  Node* alloc = graph()->NewNode(simplified()->Allocate(TENURED), p0,
-                                 graph()->start(), graph()->start());
-  Reduction r = Reduce(alloc);
-
-  // Only check that we lowered, but do not specify the exact form since
-  // this is subject to change.
-  ASSERT_TRUE(r.Changed());
-}
-
-
-INSTANTIATE_TEST_CASE_P(ChangeLoweringTest, ChangeLoweringCommonTest,
-                        ::testing::Values(MachineRepresentation::kWord32,
-                                          MachineRepresentation::kWord64));
-
-
-// -----------------------------------------------------------------------------
-// 32-bit
-
-
-class ChangeLowering32Test : public ChangeLoweringTest {
- public:
-  ~ChangeLowering32Test() override {}
-  MachineRepresentation WordRepresentation() const final {
-    return MachineRepresentation::kWord32;
-  }
-};
-
-
-TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) {
-  Node* value = Parameter(Type::Integral32());
-  Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), value);
-  Reduction r = Reduce(node);
-  ASSERT_TRUE(r.Changed());
-  Capture<Node*> add, branch, heap_number, if_true;
-  EXPECT_THAT(
-      r.replacement(),
-      IsPhi(MachineRepresentation::kTagged,
-            IsFinishRegion(
-                AllOf(CaptureEq(&heap_number),
-                      IsAllocateHeapNumber(_, CaptureEq(&if_true))),
-                IsStore(
-                    StoreRepresentation(MachineRepresentation::kFloat64,
-                                        kNoWriteBarrier),
-                    CaptureEq(&heap_number),
-                    IsIntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag),
-                    IsChangeInt32ToFloat64(value), CaptureEq(&heap_number),
-                    CaptureEq(&if_true))),
-            IsProjection(0, AllOf(CaptureEq(&add),
-                                  IsInt32AddWithOverflow(value, value))),
-            IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
-                    IsIfFalse(AllOf(CaptureEq(&branch),
-                                    IsBranch(IsProjection(1, CaptureEq(&add)),
-                                             graph()->start()))))));
-}
-
-
-TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToFloat64) {
-  STATIC_ASSERT(kSmiTag == 0);
-  STATIC_ASSERT(kSmiTagSize == 1);
-
-  Node* value = Parameter(Type::Number());
-  Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), value);
-  Reduction r = Reduce(node);
-  ASSERT_TRUE(r.Changed());
-  Capture<Node*> branch, if_true;
-  EXPECT_THAT(
-      r.replacement(),
-      IsPhi(MachineRepresentation::kFloat64,
-            IsLoadHeapNumber(value, CaptureEq(&if_true)),
-            IsChangeInt32ToFloat64(IsWord32Sar(
-                value, IsInt32Constant(kSmiTagSize + kSmiShiftSize))),
-            IsMerge(AllOf(CaptureEq(&if_true),
-                          IsIfTrue(AllOf(
-                              CaptureEq(&branch),
-                              IsBranch(IsWord32And(
-                                           value, IsInt32Constant(kSmiTagMask)),
-                                       graph()->start())))),
-                    IsIfFalse(CaptureEq(&branch)))));
-}
-
-
-TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToInt32) {
-  STATIC_ASSERT(kSmiTag == 0);
-  STATIC_ASSERT(kSmiTagSize == 1);
-
-  Node* value = Parameter(Type::Signed32());
-  Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), value);
-  Reduction r = Reduce(node);
-  ASSERT_TRUE(r.Changed());
-  Capture<Node*> branch, if_true;
-  EXPECT_THAT(
-      r.replacement(),
-      IsPhi(
-          MachineRepresentation::kWord32,
-          IsChangeFloat64ToInt32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
-          IsWord32Sar(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
-          IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
-                  IsIfFalse(AllOf(
-                      CaptureEq(&branch),
-                      IsBranch(IsWord32And(value, IsInt32Constant(kSmiTagMask)),
-                               graph()->start()))))));
-}
-
-
-TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToUint32) {
-  STATIC_ASSERT(kSmiTag == 0);
-  STATIC_ASSERT(kSmiTagSize == 1);
-
-  Node* value = Parameter(Type::Unsigned32());
-  Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), value);
-  Reduction r = Reduce(node);
-  ASSERT_TRUE(r.Changed());
-  Capture<Node*> branch, if_true;
-  EXPECT_THAT(
-      r.replacement(),
-      IsPhi(
-          MachineRepresentation::kWord32,
-          IsChangeFloat64ToUint32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
-          IsWord32Sar(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
-          IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
-                  IsIfFalse(AllOf(
-                      CaptureEq(&branch),
-                      IsBranch(IsWord32And(value, IsInt32Constant(kSmiTagMask)),
-                               graph()->start()))))));
-}
-
-
-TARGET_TEST_F(ChangeLowering32Test, ChangeUint32ToTagged) {
-  STATIC_ASSERT(kSmiTag == 0);
-  STATIC_ASSERT(kSmiTagSize == 1);
-
-  Node* value = Parameter(Type::Number());
-  Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), value);
-  Reduction r = Reduce(node);
-  ASSERT_TRUE(r.Changed());
-  Capture<Node*> branch, heap_number, if_false;
-  EXPECT_THAT(
-      r.replacement(),
-      IsPhi(
-          MachineRepresentation::kTagged,
-          IsWord32Shl(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
-          IsFinishRegion(
-              AllOf(CaptureEq(&heap_number),
-                    IsAllocateHeapNumber(_, CaptureEq(&if_false))),
-              IsStore(
-                  StoreRepresentation(MachineRepresentation::kFloat64,
-                                      kNoWriteBarrier),
-                  CaptureEq(&heap_number),
-                  IsInt32Constant(HeapNumber::kValueOffset - kHeapObjectTag),
-                  IsChangeUint32ToFloat64(value), CaptureEq(&heap_number),
-                  CaptureEq(&if_false))),
-          IsMerge(IsIfTrue(AllOf(
-                      CaptureEq(&branch),
-                      IsBranch(IsUint32LessThanOrEqual(
-                                   value, IsInt32Constant(Smi::kMaxValue)),
-                               graph()->start()))),
-                  AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
-}
-
-
-// -----------------------------------------------------------------------------
-// 64-bit
-
-
-class ChangeLowering64Test : public ChangeLoweringTest {
- public:
-  ~ChangeLowering64Test() override {}
-  MachineRepresentation WordRepresentation() const final {
-    return MachineRepresentation::kWord64;
-  }
-};
-
-
-TARGET_TEST_F(ChangeLowering64Test, ChangeInt32ToTagged) {
-  Node* value = Parameter(Type::Signed32());
-  Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), value);
-  Reduction r = Reduce(node);
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(), IsChangeInt32ToSmi(value));
-}
-
-
-TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToFloat64) {
-  STATIC_ASSERT(kSmiTag == 0);
-  STATIC_ASSERT(kSmiTagSize == 1);
-
-  Node* value = Parameter(Type::Number());
-  Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), value);
-  Reduction r = Reduce(node);
-  ASSERT_TRUE(r.Changed());
-  Capture<Node*> branch, if_true;
-  EXPECT_THAT(
-      r.replacement(),
-      IsPhi(MachineRepresentation::kFloat64,
-            IsLoadHeapNumber(value, CaptureEq(&if_true)),
-            IsChangeInt32ToFloat64(IsTruncateInt64ToInt32(IsWord64Sar(
-                value, IsInt64Constant(kSmiTagSize + kSmiShiftSize)))),
-            IsMerge(AllOf(CaptureEq(&if_true),
-                          IsIfTrue(AllOf(
-                              CaptureEq(&branch),
-                              IsBranch(IsWord64And(
-                                           value, IsInt64Constant(kSmiTagMask)),
-                                       graph()->start())))),
-                    IsIfFalse(CaptureEq(&branch)))));
-}
-
-
-TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToInt32) {
-  STATIC_ASSERT(kSmiTag == 0);
-  STATIC_ASSERT(kSmiTagSize == 1);
-
-  Node* value = Parameter(Type::Signed32());
-  Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), value);
-  Reduction r = Reduce(node);
-  ASSERT_TRUE(r.Changed());
-  Capture<Node*> branch, if_true;
-  EXPECT_THAT(
-      r.replacement(),
-      IsPhi(
-          MachineRepresentation::kWord32,
-          IsChangeFloat64ToInt32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
-          IsTruncateInt64ToInt32(
-              IsWord64Sar(value, IsInt64Constant(kSmiTagSize + kSmiShiftSize))),
-          IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
-                  IsIfFalse(AllOf(
-                      CaptureEq(&branch),
-                      IsBranch(IsWord64And(value, IsInt64Constant(kSmiTagMask)),
-                               graph()->start()))))));
-}
-
-
-TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToUint32) {
-  STATIC_ASSERT(kSmiTag == 0);
-  STATIC_ASSERT(kSmiTagSize == 1);
-
-  Node* value = Parameter(Type::Unsigned32());
-  Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), value);
-  Reduction r = Reduce(node);
-  ASSERT_TRUE(r.Changed());
-  Capture<Node*> branch, if_true;
-  EXPECT_THAT(
-      r.replacement(),
-      IsPhi(
-          MachineRepresentation::kWord32,
-          IsChangeFloat64ToUint32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
-          IsTruncateInt64ToInt32(
-              IsWord64Sar(value, IsInt64Constant(kSmiTagSize + kSmiShiftSize))),
-          IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
-                  IsIfFalse(AllOf(
-                      CaptureEq(&branch),
-                      IsBranch(IsWord64And(value, IsInt64Constant(kSmiTagMask)),
-                               graph()->start()))))));
-}
-
-
-TARGET_TEST_F(ChangeLowering64Test, ChangeUint32ToTagged) {
-  STATIC_ASSERT(kSmiTag == 0);
-  STATIC_ASSERT(kSmiTagSize == 1);
-
-  Node* value = Parameter(Type::Number());
-  Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), value);
-  Reduction r = Reduce(node);
-  ASSERT_TRUE(r.Changed());
-  Capture<Node*> branch, heap_number, if_false;
-  EXPECT_THAT(
-      r.replacement(),
-      IsPhi(
-          MachineRepresentation::kTagged,
-          IsWord64Shl(IsChangeUint32ToUint64(value),
-                      IsInt64Constant(kSmiTagSize + kSmiShiftSize)),
-          IsFinishRegion(
-              AllOf(CaptureEq(&heap_number),
-                    IsAllocateHeapNumber(_, CaptureEq(&if_false))),
-              IsStore(
-                  StoreRepresentation(MachineRepresentation::kFloat64,
-                                      kNoWriteBarrier),
-                  CaptureEq(&heap_number),
-                  IsInt64Constant(HeapNumber::kValueOffset - kHeapObjectTag),
-                  IsChangeUint32ToFloat64(value), CaptureEq(&heap_number),
-                  CaptureEq(&if_false))),
-          IsMerge(IsIfTrue(AllOf(
-                      CaptureEq(&branch),
-                      IsBranch(IsUint32LessThanOrEqual(
-                                   value, IsInt32Constant(Smi::kMaxValue)),
-                               graph()->start()))),
-                  AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
-}
-
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
diff --git a/test/unittests/compiler/checkpoint-elimination-unittest.cc b/test/unittests/compiler/checkpoint-elimination-unittest.cc
new file mode 100644
index 0000000..a201fc9
--- /dev/null
+++ b/test/unittests/compiler/checkpoint-elimination-unittest.cc
@@ -0,0 +1,59 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/checkpoint-elimination.h"
+#include "src/compiler/common-operator.h"
+#include "src/compiler/operator.h"
+#include "test/unittests/compiler/graph-reducer-unittest.h"
+#include "test/unittests/compiler/graph-unittest.h"
+#include "test/unittests/compiler/node-test-utils.h"
+
+using testing::StrictMock;
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class CheckpointEliminationTest : public GraphTest {
+ public:
+  CheckpointEliminationTest() : GraphTest() {}
+  ~CheckpointEliminationTest() override {}
+
+ protected:
+  Reduction Reduce(AdvancedReducer::Editor* editor, Node* node) {
+    CheckpointElimination reducer(editor);
+    return reducer.Reduce(node);
+  }
+
+  Reduction Reduce(Node* node) {
+    StrictMock<MockAdvancedReducerEditor> editor;
+    return Reduce(&editor, node);
+  }
+};
+
+namespace {
+
+const Operator kOpNoWrite(0, Operator::kNoWrite, "OpNoWrite", 0, 1, 0, 0, 1, 0);
+
+}  // namespace
+
+// -----------------------------------------------------------------------------
+// Checkpoint
+
+TEST_F(CheckpointEliminationTest, CheckpointChain) {
+  Node* const control = graph()->start();
+  Node* frame_state = EmptyFrameState();
+  Node* checkpoint1 = graph()->NewNode(common()->Checkpoint(), frame_state,
+                                       graph()->start(), control);
+  Node* effect_link = graph()->NewNode(&kOpNoWrite, checkpoint1);
+  Node* checkpoint2 = graph()->NewNode(common()->Checkpoint(), frame_state,
+                                       effect_link, control);
+  Reduction r = Reduce(checkpoint2);
+  ASSERT_TRUE(r.Changed());
+  EXPECT_EQ(effect_link, r.replacement());
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/compiler/coalesced-live-ranges-unittest.cc b/test/unittests/compiler/coalesced-live-ranges-unittest.cc
deleted file mode 100644
index fe8fac4..0000000
--- a/test/unittests/compiler/coalesced-live-ranges-unittest.cc
+++ /dev/null
@@ -1,268 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/compiler/coalesced-live-ranges.h"
-#include "test/unittests/compiler/live-range-builder.h"
-#include "test/unittests/test-utils.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-
-class CoalescedLiveRangesTest : public TestWithZone {
- public:
-  CoalescedLiveRangesTest() : TestWithZone(), ranges_(zone()) {}
-  bool HasNoConflicts(const LiveRange* range);
-  bool ConflictsPreciselyWith(const LiveRange* range, int id);
-  bool ConflictsPreciselyWith(const LiveRange* range, int id1, int id2);
-
-  CoalescedLiveRanges& ranges() { return ranges_; }
-  const CoalescedLiveRanges& ranges() const { return ranges_; }
-  bool AllocationsAreValid() const;
-  void RemoveConflicts(LiveRange* range);
-
- private:
-  typedef ZoneSet<int> LiveRangeIDs;
-  bool IsRangeConflictingWith(const LiveRange* range, const LiveRangeIDs& ids);
-  CoalescedLiveRanges ranges_;
-};
-
-
-bool CoalescedLiveRangesTest::ConflictsPreciselyWith(const LiveRange* range,
-                                                     int id) {
-  LiveRangeIDs set(zone());
-  set.insert(id);
-  return IsRangeConflictingWith(range, set);
-}
-
-
-bool CoalescedLiveRangesTest::ConflictsPreciselyWith(const LiveRange* range,
-                                                     int id1, int id2) {
-  LiveRangeIDs set(zone());
-  set.insert(id1);
-  set.insert(id2);
-  return IsRangeConflictingWith(range, set);
-}
-
-
-bool CoalescedLiveRangesTest::HasNoConflicts(const LiveRange* range) {
-  LiveRangeIDs set(zone());
-  return IsRangeConflictingWith(range, set);
-}
-
-
-void CoalescedLiveRangesTest::RemoveConflicts(LiveRange* range) {
-  auto conflicts = ranges().GetConflicts(range);
-  LiveRangeIDs seen(zone());
-  for (auto c = conflicts.Current(); c != nullptr;
-       c = conflicts.RemoveCurrentAndGetNext()) {
-    int id = c->TopLevel()->vreg();
-    EXPECT_FALSE(seen.count(id) > 0);
-    seen.insert(c->TopLevel()->vreg());
-  }
-}
-
-
-bool CoalescedLiveRangesTest::AllocationsAreValid() const {
-  return ranges().VerifyAllocationsAreValidForTesting();
-}
-
-
-bool CoalescedLiveRangesTest::IsRangeConflictingWith(const LiveRange* range,
-                                                     const LiveRangeIDs& ids) {
-  LiveRangeIDs found_ids(zone());
-
-  auto conflicts = ranges().GetConflicts(range);
-  for (auto conflict = conflicts.Current(); conflict != nullptr;
-       conflict = conflicts.GetNext()) {
-    found_ids.insert(conflict->TopLevel()->vreg());
-  }
-  return found_ids == ids;
-}
-
-
-TEST_F(CoalescedLiveRangesTest, VisitEmptyAllocations) {
-  LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(1, 5);
-  ASSERT_TRUE(ranges().empty());
-  ASSERT_TRUE(AllocationsAreValid());
-  ASSERT_TRUE(HasNoConflicts(range));
-}
-
-
-TEST_F(CoalescedLiveRangesTest, CandidateBeforeAfterAllocations) {
-  LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(5, 6);
-  ranges().AllocateRange(range);
-  ASSERT_FALSE(ranges().empty());
-  ASSERT_TRUE(AllocationsAreValid());
-  LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(1, 2);
-  ASSERT_TRUE(HasNoConflicts(query));
-  query = TestRangeBuilder(zone()).Id(3).Build(1, 5);
-  ASSERT_TRUE(HasNoConflicts(query));
-}
-
-
-TEST_F(CoalescedLiveRangesTest, CandidateBeforeAfterManyAllocations) {
-  LiveRange* range =
-      TestRangeBuilder(zone()).Id(1).Add(5, 7).Add(10, 12).Build();
-  ranges().AllocateRange(range);
-  ASSERT_FALSE(ranges().empty());
-  ASSERT_TRUE(AllocationsAreValid());
-  LiveRange* query =
-      TestRangeBuilder(zone()).Id(2).Add(1, 2).Add(13, 15).Build();
-  ASSERT_TRUE(HasNoConflicts(query));
-  query = TestRangeBuilder(zone()).Id(3).Add(1, 5).Add(12, 15).Build();
-  ASSERT_TRUE(HasNoConflicts(query));
-}
-
-
-TEST_F(CoalescedLiveRangesTest, SelfConflictsPreciselyWithSelf) {
-  LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(1, 5);
-  ranges().AllocateRange(range);
-  ASSERT_FALSE(ranges().empty());
-  ASSERT_TRUE(AllocationsAreValid());
-  ASSERT_TRUE(ConflictsPreciselyWith(range, 1));
-  range = TestRangeBuilder(zone()).Id(2).Build(8, 10);
-  ranges().AllocateRange(range);
-  ASSERT_TRUE(ConflictsPreciselyWith(range, 2));
-}
-
-
-TEST_F(CoalescedLiveRangesTest, QueryStartsBeforeConflict) {
-  LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(2, 5);
-  ranges().AllocateRange(range);
-  LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(1, 3);
-  ASSERT_TRUE(ConflictsPreciselyWith(query, 1));
-  range = TestRangeBuilder(zone()).Id(3).Build(8, 10);
-  ranges().AllocateRange(range);
-  query = TestRangeBuilder(zone()).Id(4).Build(6, 9);
-  ASSERT_TRUE(ConflictsPreciselyWith(query, 3));
-}
-
-
-TEST_F(CoalescedLiveRangesTest, QueryStartsInConflict) {
-  LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(2, 5);
-  ranges().AllocateRange(range);
-  LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(3, 6);
-  ASSERT_TRUE(ConflictsPreciselyWith(query, 1));
-  range = TestRangeBuilder(zone()).Id(3).Build(8, 10);
-  ranges().AllocateRange(range);
-  query = TestRangeBuilder(zone()).Id(4).Build(9, 11);
-  ASSERT_TRUE(ConflictsPreciselyWith(query, 3));
-}
-
-
-TEST_F(CoalescedLiveRangesTest, QueryContainedInConflict) {
-  LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(1, 5);
-  ranges().AllocateRange(range);
-  LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(2, 3);
-  ASSERT_TRUE(ConflictsPreciselyWith(query, 1));
-}
-
-
-TEST_F(CoalescedLiveRangesTest, QueryContainsConflict) {
-  LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(2, 3);
-  ranges().AllocateRange(range);
-  LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(1, 5);
-  ASSERT_TRUE(ConflictsPreciselyWith(query, 1));
-}
-
-
-TEST_F(CoalescedLiveRangesTest, QueryCoversManyIntervalsSameRange) {
-  LiveRange* range =
-      TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(7, 9).Add(20, 25).Build();
-  ranges().AllocateRange(range);
-  LiveRange* query = TestRangeBuilder(zone()).Id(2).Build(2, 8);
-  ASSERT_TRUE(ConflictsPreciselyWith(query, 1));
-}
-
-
-TEST_F(CoalescedLiveRangesTest, QueryCoversManyIntervalsDifferentRanges) {
-  LiveRange* range =
-      TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(20, 25).Build();
-  ranges().AllocateRange(range);
-  range = TestRangeBuilder(zone()).Id(2).Build(7, 10);
-  ranges().AllocateRange(range);
-  LiveRange* query = TestRangeBuilder(zone()).Id(3).Build(2, 22);
-  ASSERT_TRUE(ConflictsPreciselyWith(query, 1, 2));
-}
-
-
-TEST_F(CoalescedLiveRangesTest, QueryFitsInGaps) {
-  LiveRange* range =
-      TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(10, 15).Add(20, 25).Build();
-  ranges().AllocateRange(range);
-  LiveRange* query =
-      TestRangeBuilder(zone()).Id(3).Add(5, 10).Add(16, 19).Add(27, 30).Build();
-  ASSERT_TRUE(HasNoConflicts(query));
-}
-
-
-TEST_F(CoalescedLiveRangesTest, DeleteConflictBefore) {
-  LiveRange* range = TestRangeBuilder(zone()).Id(1).Add(1, 4).Add(5, 6).Build();
-  ranges().AllocateRange(range);
-  range = TestRangeBuilder(zone()).Id(2).Build(40, 50);
-  ranges().AllocateRange(range);
-  LiveRange* query = TestRangeBuilder(zone()).Id(3).Build(3, 7);
-  RemoveConflicts(query);
-  query = TestRangeBuilder(zone()).Id(4).Build(0, 60);
-  ASSERT_TRUE(ConflictsPreciselyWith(query, 2));
-}
-
-
-TEST_F(CoalescedLiveRangesTest, DeleteConflictAfter) {
-  LiveRange* range = TestRangeBuilder(zone()).Id(1).Build(1, 5);
-  ranges().AllocateRange(range);
-  range = TestRangeBuilder(zone()).Id(2).Add(40, 50).Add(60, 70).Build();
-  ranges().AllocateRange(range);
-  LiveRange* query = TestRangeBuilder(zone()).Id(3).Build(45, 60);
-  RemoveConflicts(query);
-  query = TestRangeBuilder(zone()).Id(4).Build(0, 60);
-  ASSERT_TRUE(ConflictsPreciselyWith(query, 1));
-}
-
-
-TEST_F(CoalescedLiveRangesTest, DeleteConflictStraddle) {
-  LiveRange* range =
-      TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(10, 20).Build();
-  ranges().AllocateRange(range);
-  range = TestRangeBuilder(zone()).Id(2).Build(40, 50);
-  ranges().AllocateRange(range);
-  LiveRange* query = TestRangeBuilder(zone()).Id(3).Build(4, 15);
-  RemoveConflicts(query);
-  query = TestRangeBuilder(zone()).Id(4).Build(0, 60);
-  ASSERT_TRUE(ConflictsPreciselyWith(query, 2));
-}
-
-
-TEST_F(CoalescedLiveRangesTest, DeleteConflictManyOverlapsBefore) {
-  LiveRange* range =
-      TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(6, 10).Add(10, 20).Build();
-  ranges().AllocateRange(range);
-  range = TestRangeBuilder(zone()).Id(2).Build(40, 50);
-  ranges().AllocateRange(range);
-  LiveRange* query = TestRangeBuilder(zone()).Id(3).Build(4, 15);
-  RemoveConflicts(query);
-  query = TestRangeBuilder(zone()).Id(4).Build(0, 60);
-  ASSERT_TRUE(ConflictsPreciselyWith(query, 2));
-}
-
-
-TEST_F(CoalescedLiveRangesTest, DeleteWhenConflictRepeatsAfterNonConflict) {
-  LiveRange* range =
-      TestRangeBuilder(zone()).Id(1).Add(1, 5).Add(6, 10).Add(20, 30).Build();
-  ranges().AllocateRange(range);
-  range = TestRangeBuilder(zone()).Id(2).Build(12, 15);
-  ranges().AllocateRange(range);
-  LiveRange* query =
-      TestRangeBuilder(zone()).Id(3).Add(1, 8).Add(22, 25).Build();
-  RemoveConflicts(query);
-  query = TestRangeBuilder(zone()).Id(4).Build(0, 60);
-  ASSERT_TRUE(ConflictsPreciselyWith(query, 2));
-}
-
-
-}  // namespace compiler
-}  // namespace internal
-}  // namespace v8
diff --git a/test/unittests/compiler/common-operator-reducer-unittest.cc b/test/unittests/compiler/common-operator-reducer-unittest.cc
index 1c16370..510eaad 100644
--- a/test/unittests/compiler/common-operator-reducer-unittest.cc
+++ b/test/unittests/compiler/common-operator-reducer-unittest.cc
@@ -105,40 +105,6 @@
 }
 
 
-TEST_F(CommonOperatorReducerTest, BranchWithInt64ZeroConstant) {
-  TRACED_FOREACH(BranchHint, hint, kBranchHints) {
-    Node* const control = graph()->start();
-    Node* const branch =
-        graph()->NewNode(common()->Branch(hint), Int64Constant(0), control);
-    Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
-    Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
-    StrictMock<MockAdvancedReducerEditor> editor;
-    EXPECT_CALL(editor, Replace(if_true, IsDead()));
-    EXPECT_CALL(editor, Replace(if_false, control));
-    Reduction const r = Reduce(&editor, branch);
-    ASSERT_TRUE(r.Changed());
-    EXPECT_THAT(r.replacement(), IsDead());
-  }
-}
-
-
-TEST_F(CommonOperatorReducerTest, BranchWithInt64OneConstant) {
-  TRACED_FOREACH(BranchHint, hint, kBranchHints) {
-    Node* const control = graph()->start();
-    Node* const branch =
-        graph()->NewNode(common()->Branch(hint), Int64Constant(1), control);
-    Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
-    Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
-    StrictMock<MockAdvancedReducerEditor> editor;
-    EXPECT_CALL(editor, Replace(if_true, control));
-    EXPECT_CALL(editor, Replace(if_false, IsDead()));
-    Reduction const r = Reduce(&editor, branch);
-    ASSERT_TRUE(r.Changed());
-    EXPECT_THAT(r.replacement(), IsDead());
-  }
-}
-
-
 TEST_F(CommonOperatorReducerTest, BranchWithFalseConstant) {
   TRACED_FOREACH(BranchHint, hint, kBranchHints) {
     Node* const control = graph()->start();
@@ -500,30 +466,6 @@
 }
 
 
-TEST_F(CommonOperatorReducerTest, SelectWithInt64ZeroConstant) {
-  Node* p0 = Parameter(0);
-  Node* p1 = Parameter(1);
-  Node* select =
-      graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
-                       Int64Constant(0), p0, p1);
-  Reduction r = Reduce(select);
-  ASSERT_TRUE(r.Changed());
-  EXPECT_EQ(p1, r.replacement());
-}
-
-
-TEST_F(CommonOperatorReducerTest, SelectWithInt64OneConstant) {
-  Node* p0 = Parameter(0);
-  Node* p1 = Parameter(1);
-  Node* select =
-      graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
-                       Int64Constant(1), p0, p1);
-  Reduction r = Reduce(select);
-  ASSERT_TRUE(r.Changed());
-  EXPECT_EQ(p0, r.replacement());
-}
-
-
 TEST_F(CommonOperatorReducerTest, SelectWithFalseConstant) {
   Node* p0 = Parameter(0);
   Node* p1 = Parameter(1);
diff --git a/test/unittests/compiler/common-operator-unittest.cc b/test/unittests/compiler/common-operator-unittest.cc
index 0a55a2e..52f99a5 100644
--- a/test/unittests/compiler/common-operator-unittest.cc
+++ b/test/unittests/compiler/common-operator-unittest.cc
@@ -362,15 +362,26 @@
 
 
 TEST_F(CommonOperatorTest, BeginRegion) {
-  const Operator* op = common()->BeginRegion();
-  EXPECT_EQ(1, op->EffectInputCount());
-  EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
-  EXPECT_EQ(0, op->ControlOutputCount());
-  EXPECT_EQ(1, op->EffectOutputCount());
-  EXPECT_EQ(0, op->ValueOutputCount());
+  {
+    const Operator* op =
+        common()->BeginRegion(RegionObservability::kObservable);
+    EXPECT_EQ(1, op->EffectInputCount());
+    EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
+    EXPECT_EQ(0, op->ControlOutputCount());
+    EXPECT_EQ(1, op->EffectOutputCount());
+    EXPECT_EQ(0, op->ValueOutputCount());
+  }
+  {
+    const Operator* op =
+        common()->BeginRegion(RegionObservability::kNotObservable);
+    EXPECT_EQ(1, op->EffectInputCount());
+    EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
+    EXPECT_EQ(0, op->ControlOutputCount());
+    EXPECT_EQ(1, op->EffectOutputCount());
+    EXPECT_EQ(0, op->ValueOutputCount());
+  }
 }
 
-
 TEST_F(CommonOperatorTest, FinishRegion) {
   const Operator* op = common()->FinishRegion();
   EXPECT_EQ(1, op->ValueInputCount());
@@ -381,6 +392,19 @@
   EXPECT_EQ(1, op->ValueOutputCount());
 }
 
+TEST_F(CommonOperatorTest, Projection) {
+  TRACED_FORRANGE(size_t, index, 0, 3) {
+    const Operator* op = common()->Projection(index);
+    EXPECT_EQ(index, ProjectionIndexOf(op));
+    EXPECT_EQ(1, op->ValueInputCount());
+    EXPECT_EQ(1, op->ControlInputCount());
+    EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op));
+    EXPECT_EQ(0, op->ControlOutputCount());
+    EXPECT_EQ(0, op->EffectOutputCount());
+    EXPECT_EQ(1, op->ValueOutputCount());
+  }
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/test/unittests/compiler/effect-control-linearizer-unittest.cc b/test/unittests/compiler/effect-control-linearizer-unittest.cc
new file mode 100644
index 0000000..417444e
--- /dev/null
+++ b/test/unittests/compiler/effect-control-linearizer-unittest.cc
@@ -0,0 +1,330 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/effect-control-linearizer.h"
+#include "src/compiler/access-builder.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/linkage.h"
+#include "src/compiler/node-properties.h"
+#include "src/compiler/schedule.h"
+#include "src/compiler/simplified-operator.h"
+#include "test/unittests/compiler/graph-unittest.h"
+#include "test/unittests/compiler/node-test-utils.h"
+#include "test/unittests/test-utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class EffectControlLinearizerTest : public TypedGraphTest {
+ public:
+  EffectControlLinearizerTest()
+      : TypedGraphTest(3),
+        machine_(zone()),
+        javascript_(zone()),
+        simplified_(zone()),
+        jsgraph_(isolate(), graph(), common(), &javascript_, &simplified_,
+                 &machine_) {}
+
+  JSGraph* jsgraph() { return &jsgraph_; }
+  SimplifiedOperatorBuilder* simplified() { return &simplified_; }
+
+ private:
+  MachineOperatorBuilder machine_;
+  JSOperatorBuilder javascript_;
+  SimplifiedOperatorBuilder simplified_;
+  JSGraph jsgraph_;
+};
+
+namespace {
+
+BasicBlock* AddBlockToSchedule(Schedule* schedule) {
+  BasicBlock* block = schedule->NewBasicBlock();
+  block->set_rpo_number(static_cast<int32_t>(schedule->rpo_order()->size()));
+  schedule->rpo_order()->push_back(block);
+  return block;
+}
+
+}  // namespace
+
+TEST_F(EffectControlLinearizerTest, SimpleLoad) {
+  Schedule schedule(zone());
+
+  // Create the graph.
+  Node* heap_number = NumberConstant(0.5);
+  Node* load = graph()->NewNode(
+      simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), heap_number,
+      graph()->start(), graph()->start());
+  Node* ret = graph()->NewNode(common()->Return(), load, graph()->start(),
+                               graph()->start());
+
+  // Build the basic block structure.
+  BasicBlock* start = schedule.start();
+  schedule.rpo_order()->push_back(start);
+  start->set_rpo_number(0);
+
+  // Populate the basic blocks with nodes.
+  schedule.AddNode(start, graph()->start());
+  schedule.AddNode(start, heap_number);
+  schedule.AddNode(start, load);
+  schedule.AddReturn(start, ret);
+
+  // Run the state effect introducer.
+  EffectControlLinearizer introducer(jsgraph(), &schedule, zone());
+  introducer.Run();
+
+  EXPECT_THAT(load,
+              IsLoadField(AccessBuilder::ForHeapNumberValue(), heap_number,
+                          graph()->start(), graph()->start()));
+  // The return should have reconnected effect edge to the load.
+  EXPECT_THAT(ret, IsReturn(load, load, graph()->start()));
+}
+
+TEST_F(EffectControlLinearizerTest, DiamondLoad) {
+  Schedule schedule(zone());
+
+  // Create the graph.
+  Node* branch =
+      graph()->NewNode(common()->Branch(), Int32Constant(0), graph()->start());
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+  Node* heap_number = NumberConstant(0.5);
+  Node* vtrue = graph()->NewNode(
+      simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), heap_number,
+      graph()->start(), if_true);
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+  Node* vfalse = Float64Constant(2);
+
+  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+  Node* phi = graph()->NewNode(
+      common()->Phi(MachineRepresentation::kFloat64, 2), vtrue, vfalse, merge);
+
+  Node* ret =
+      graph()->NewNode(common()->Return(), phi, graph()->start(), merge);
+
+  // Build the basic block structure.
+  BasicBlock* start = schedule.start();
+  schedule.rpo_order()->push_back(start);
+  start->set_rpo_number(0);
+
+  BasicBlock* tblock = AddBlockToSchedule(&schedule);
+  BasicBlock* fblock = AddBlockToSchedule(&schedule);
+  BasicBlock* mblock = AddBlockToSchedule(&schedule);
+
+  // Populate the basic blocks with nodes.
+  schedule.AddNode(start, graph()->start());
+  schedule.AddBranch(start, branch, tblock, fblock);
+
+  schedule.AddNode(tblock, if_true);
+  schedule.AddNode(tblock, heap_number);
+  schedule.AddNode(tblock, vtrue);
+  schedule.AddGoto(tblock, mblock);
+
+  schedule.AddNode(fblock, if_false);
+  schedule.AddNode(fblock, vfalse);
+  schedule.AddGoto(fblock, mblock);
+
+  schedule.AddNode(mblock, merge);
+  schedule.AddNode(mblock, phi);
+  schedule.AddReturn(mblock, ret);
+
+  // Run the state effect introducer.
+  EffectControlLinearizer introducer(jsgraph(), &schedule, zone());
+  introducer.Run();
+
+  // The effect input to the return should be an effect phi with the
+  // newly introduced effectful change operators.
+  ASSERT_THAT(
+      ret, IsReturn(phi, IsEffectPhi(vtrue, graph()->start(), merge), merge));
+}
+
+TEST_F(EffectControlLinearizerTest, FloatingDiamondsControlWiring) {
+  Schedule schedule(zone());
+
+  // Create the graph and schedule. Roughly (omitting effects and unimportant
+  // nodes):
+  //
+  //            BLOCK 0:
+  //             r1: Start
+  //             c1: Call
+  //             b1: Branch(const0, s1)
+  //                |
+  //        +-------+------+
+  //        |              |
+  //   BLOCK 1:           BLOCK 2:
+  //    t1: IfTrue(b1)     f1: IfFalse(b1)
+  //        |              |
+  //        +-------+------+
+  //                |
+  //            BLOCK 3:
+  //             m1: Merge(t1, f1)
+  //             c2: IfSuccess(c1)
+  //             b2: Branch(const0 , s1)
+  //                |
+  //        +-------+------+
+  //        |              |
+  //   BLOCK 4:           BLOCK 5:
+  //    t2: IfTrue(b2)     f2:IfFalse(b2)
+  //        |              |
+  //        +-------+------+
+  //                |
+  //            BLOCK 6:
+  //             m2: Merge(t2, f2)
+  //             r1: Return(c1, c2)
+  MachineType kMachineSignature[] = {MachineType::AnyTagged(),
+                                     MachineType::AnyTagged()};
+  LinkageLocation kLocationSignature[] = {LinkageLocation::ForRegister(0),
+                                          LinkageLocation::ForRegister(1)};
+  const CallDescriptor* kCallDescriptor = new (zone()) CallDescriptor(
+      CallDescriptor::kCallCodeObject, MachineType::AnyTagged(),
+      LinkageLocation::ForRegister(0),
+      new (zone()) MachineSignature(1, 1, kMachineSignature),
+      new (zone()) LocationSignature(1, 1, kLocationSignature), 0,
+      Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags);
+  Node* p0 = Parameter(0);
+  Node* p1 = Parameter(1);
+  Node* const0 = Int32Constant(0);
+  Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1,
+                                graph()->start(), graph()->start());
+  Node* if_success = graph()->NewNode(common()->IfSuccess(), call);
+
+  // First Floating diamond.
+  Node* branch1 =
+      graph()->NewNode(common()->Branch(), const0, graph()->start());
+  Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+  Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+  Node* merge1 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+
+  // Second floating diamond.
+  Node* branch2 =
+      graph()->NewNode(common()->Branch(), const0, graph()->start());
+  Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
+  Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
+  Node* merge2 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
+
+  Node* ret =
+      graph()->NewNode(common()->Return(), call, graph()->start(), if_success);
+
+  // Build the basic block structure.
+  BasicBlock* start = schedule.start();
+  schedule.rpo_order()->push_back(start);
+  start->set_rpo_number(0);
+
+  BasicBlock* t1block = AddBlockToSchedule(&schedule);
+  BasicBlock* f1block = AddBlockToSchedule(&schedule);
+  BasicBlock* m1block = AddBlockToSchedule(&schedule);
+
+  BasicBlock* t2block = AddBlockToSchedule(&schedule);
+  BasicBlock* f2block = AddBlockToSchedule(&schedule);
+  BasicBlock* m2block = AddBlockToSchedule(&schedule);
+
+  // Populate the basic blocks with nodes.
+  schedule.AddNode(start, graph()->start());
+  schedule.AddNode(start, p0);
+  schedule.AddNode(start, p1);
+  schedule.AddNode(start, const0);
+  schedule.AddNode(start, call);
+  schedule.AddBranch(start, branch1, t1block, f1block);
+
+  schedule.AddNode(t1block, if_true1);
+  schedule.AddGoto(t1block, m1block);
+
+  schedule.AddNode(f1block, if_false1);
+  schedule.AddGoto(f1block, m1block);
+
+  schedule.AddNode(m1block, merge1);
+  // The scheduler does not always put the IfSuccess node to the corresponding
+  // call's block, simulate that here.
+  schedule.AddNode(m1block, if_success);
+  schedule.AddBranch(m1block, branch2, t2block, f2block);
+
+  schedule.AddNode(t2block, if_true2);
+  schedule.AddGoto(t2block, m2block);
+
+  schedule.AddNode(f2block, if_false2);
+  schedule.AddGoto(f2block, m2block);
+
+  schedule.AddNode(m2block, merge2);
+  schedule.AddReturn(m2block, ret);
+
+  // Run the state effect introducer.
+  EffectControlLinearizer introducer(jsgraph(), &schedule, zone());
+  introducer.Run();
+
+  // The effect input to the return should be an effect phi with the
+  // newly introduced effectful change operators.
+  ASSERT_THAT(ret, IsReturn(call, call, merge2));
+  ASSERT_THAT(branch2, IsBranch(const0, merge1));
+  ASSERT_THAT(branch1, IsBranch(const0, if_success));
+  ASSERT_THAT(if_success, IsIfSuccess(call));
+}
+
+TEST_F(EffectControlLinearizerTest, LoopLoad) {
+  Schedule schedule(zone());
+
+  // Create the graph.
+  Node* loop = graph()->NewNode(common()->Loop(1), graph()->start());
+  Node* effect_phi =
+      graph()->NewNode(common()->EffectPhi(1), graph()->start(), loop);
+
+  Node* cond = Int32Constant(0);
+  Node* branch = graph()->NewNode(common()->Branch(), cond, loop);
+
+  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+
+  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+
+  loop->AppendInput(zone(), if_false);
+  NodeProperties::ChangeOp(loop, common()->Loop(2));
+
+  effect_phi->InsertInput(zone(), 1, effect_phi);
+  NodeProperties::ChangeOp(effect_phi, common()->EffectPhi(2));
+
+  Node* heap_number = NumberConstant(0.5);
+  Node* load = graph()->NewNode(
+      simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), heap_number,
+      graph()->start(), loop);
+
+  Node* ret = graph()->NewNode(common()->Return(), load, effect_phi, if_true);
+
+  // Build the basic block structure.
+  BasicBlock* start = schedule.start();
+  schedule.rpo_order()->push_back(start);
+  start->set_rpo_number(0);
+
+  BasicBlock* lblock = AddBlockToSchedule(&schedule);
+  BasicBlock* fblock = AddBlockToSchedule(&schedule);
+  BasicBlock* rblock = AddBlockToSchedule(&schedule);
+
+  // Populate the basic blocks with nodes.
+  schedule.AddNode(start, graph()->start());
+  schedule.AddGoto(start, lblock);
+
+  schedule.AddNode(lblock, loop);
+  schedule.AddNode(lblock, effect_phi);
+  schedule.AddNode(lblock, heap_number);
+  schedule.AddNode(lblock, load);
+  schedule.AddNode(lblock, cond);
+  schedule.AddBranch(lblock, branch, rblock, fblock);
+
+  schedule.AddNode(fblock, if_false);
+  schedule.AddGoto(fblock, lblock);
+
+  schedule.AddNode(rblock, if_true);
+  schedule.AddReturn(rblock, ret);
+
+  // Run the state effect introducer.
+  EffectControlLinearizer introducer(jsgraph(), &schedule, zone());
+  introducer.Run();
+
+  ASSERT_THAT(ret, IsReturn(load, load, if_true));
+  EXPECT_THAT(load, IsLoadField(AccessBuilder::ForHeapNumberValue(),
+                                heap_number, effect_phi, loop));
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/compiler/escape-analysis-unittest.cc b/test/unittests/compiler/escape-analysis-unittest.cc
index d5e12ba..9b584a2 100644
--- a/test/unittests/compiler/escape-analysis-unittest.cc
+++ b/test/unittests/compiler/escape-analysis-unittest.cc
@@ -48,7 +48,8 @@
       effect = effect_;
     }
 
-    return effect_ = graph()->NewNode(common()->BeginRegion(), effect);
+    return effect_ = graph()->NewNode(
+               common()->BeginRegion(RegionObservability::kObservable), effect);
   }
 
   Node* FinishRegion(Node* value, Node* effect = nullptr) {
@@ -146,14 +147,18 @@
   }
 
   FieldAccess FieldAccessAtIndex(int offset) {
-    FieldAccess access = {kTaggedBase, offset, MaybeHandle<Name>(), Type::Any(),
-                          MachineType::AnyTagged()};
+    FieldAccess access = {kTaggedBase,
+                          offset,
+                          MaybeHandle<Name>(),
+                          Type::Any(),
+                          MachineType::AnyTagged(),
+                          kFullWriteBarrier};
     return access;
   }
 
   ElementAccess MakeElementAccess(int header_size) {
     ElementAccess access = {kTaggedBase, header_size, Type::Any(),
-                            MachineType::AnyTagged()};
+                            MachineType::AnyTagged(), kFullWriteBarrier};
     return access;
   }
 
diff --git a/test/unittests/compiler/graph-unittest.h b/test/unittests/compiler/graph-unittest.h
index 31bae6d..d4248e4 100644
--- a/test/unittests/compiler/graph-unittest.h
+++ b/test/unittests/compiler/graph-unittest.h
@@ -48,6 +48,9 @@
 
   Node* EmptyFrameState();
 
+  Matcher<Node*> IsBooleanConstant(bool value) {
+    return value ? IsTrueConstant() : IsFalseConstant();
+  }
   Matcher<Node*> IsFalseConstant();
   Matcher<Node*> IsTrueConstant();
   Matcher<Node*> IsUndefinedConstant();
diff --git a/test/unittests/compiler/instruction-selector-unittest.cc b/test/unittests/compiler/instruction-selector-unittest.cc
index 16030f8..936a94e 100644
--- a/test/unittests/compiler/instruction-selector-unittest.cc
+++ b/test/unittests/compiler/instruction-selector-unittest.cc
@@ -45,9 +45,8 @@
   selector.SelectInstructions();
   if (FLAG_trace_turbo) {
     OFStream out(stdout);
-    PrintableInstructionSequence printable = {
-        RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN),
-        &sequence};
+    PrintableInstructionSequence printable = {RegisterConfiguration::Turbofan(),
+                                              &sequence};
     out << "=== Code sequence after instruction selection ===" << std::endl
         << printable;
   }
@@ -94,12 +93,12 @@
   }
   for (auto i : s.virtual_registers_) {
     int const virtual_register = i.second;
-    if (sequence.IsFloat(virtual_register)) {
+    if (sequence.IsFP(virtual_register)) {
       EXPECT_FALSE(sequence.IsReference(virtual_register));
       s.doubles_.insert(virtual_register);
     }
     if (sequence.IsReference(virtual_register)) {
-      EXPECT_FALSE(sequence.IsFloat(virtual_register));
+      EXPECT_FALSE(sequence.IsFP(virtual_register));
       s.references_.insert(virtual_register);
     }
   }
@@ -199,11 +198,9 @@
 // -----------------------------------------------------------------------------
 // Conversions.
 
-
-TARGET_TEST_F(InstructionSelectorTest, TruncateFloat64ToInt32WithParameter) {
+TARGET_TEST_F(InstructionSelectorTest, TruncateFloat64ToWord32WithParameter) {
   StreamBuilder m(this, MachineType::Int32(), MachineType::Float64());
-  m.Return(
-      m.TruncateFloat64ToInt32(TruncationMode::kJavaScript, m.Parameter(0)));
+  m.Return(m.TruncateFloat64ToWord32(m.Parameter(0)));
   Stream s = m.Build(kAllInstructions);
   ASSERT_EQ(4U, s.size());
   EXPECT_EQ(kArchNop, s[0]->arch_opcode());
@@ -335,7 +332,8 @@
   Node* p2 = m2.Parameter(0);
   m2.Return(m2.AddNode(
       m2.machine()->Load(MachineType::Int32()), p2, m2.Int32Constant(0),
-      m2.AddNode(m2.common()->BeginRegion(), m2.graph()->start())));
+      m2.AddNode(m2.common()->BeginRegion(RegionObservability::kObservable),
+                 m2.graph()->start())));
   Stream s2 = m2.Build(kAllInstructions);
   EXPECT_LE(3U, s1.size());
   ASSERT_EQ(s1.size(), s2.size());
@@ -482,7 +480,7 @@
   EXPECT_EQ(0, s.ToInt32(call_instr->InputAt(4)));  // This should be a context.
                                                     // We inserted 0 here.
   EXPECT_EQ(0.5, s.ToFloat64(call_instr->InputAt(5)));
-  EXPECT_TRUE(s.ToHeapObject(call_instr->InputAt(6))->IsUndefined());
+  EXPECT_TRUE(s.ToHeapObject(call_instr->InputAt(6))->IsUndefined(isolate()));
   EXPECT_EQ(MachineType::AnyTagged(),
             desc_before->GetType(0));  // function is always
                                        // tagged/any.
diff --git a/test/unittests/compiler/instruction-sequence-unittest.cc b/test/unittests/compiler/instruction-sequence-unittest.cc
index 51112a6..619e0aa 100644
--- a/test/unittests/compiler/instruction-sequence-unittest.cc
+++ b/test/unittests/compiler/instruction-sequence-unittest.cc
@@ -15,10 +15,9 @@
 static const char*
     general_register_names_[RegisterConfiguration::kMaxGeneralRegisters];
 static const char*
-    double_register_names_[RegisterConfiguration::kMaxDoubleRegisters];
+    double_register_names_[RegisterConfiguration::kMaxFPRegisters];
 static char register_names_[10 * (RegisterConfiguration::kMaxGeneralRegisters +
-                                  RegisterConfiguration::kMaxDoubleRegisters)];
-
+                                  RegisterConfiguration::kMaxFPRegisters)];
 
 namespace {
 static int allocatable_codes[InstructionSequenceTest::kDefaultNRegs] = {
@@ -35,7 +34,7 @@
     loc += base::OS::SNPrintF(loc, 100, "gp_%d", i);
     *loc++ = 0;
   }
-  for (int i = 0; i < RegisterConfiguration::kMaxDoubleRegisters; ++i) {
+  for (int i = 0; i < RegisterConfiguration::kMaxFPRegisters; ++i) {
     double_register_names_[i] = loc;
     loc += base::OS::SNPrintF(loc, 100, "fp_%d", i) + 1;
     *loc++ = 0;
@@ -68,8 +67,11 @@
   if (config_.is_empty()) {
     config_.Reset(new RegisterConfiguration(
         num_general_registers_, num_double_registers_, num_general_registers_,
-        num_double_registers_, num_double_registers_, allocatable_codes,
-        allocatable_double_codes, general_register_names_,
+        num_double_registers_, allocatable_codes, allocatable_double_codes,
+        kSimpleFPAliasing ? RegisterConfiguration::OVERLAP
+                          : RegisterConfiguration::COMBINE,
+        general_register_names_,
+        double_register_names_,  // float register names
         double_register_names_));
   }
   return config_.get();
diff --git a/test/unittests/compiler/int64-lowering-unittest.cc b/test/unittests/compiler/int64-lowering-unittest.cc
index 08f3038..804c399 100644
--- a/test/unittests/compiler/int64-lowering-unittest.cc
+++ b/test/unittests/compiler/int64-lowering-unittest.cc
@@ -133,6 +133,7 @@
              MachineRepresentation::kWord64);
 
   Capture<Node*> high_word_load;
+#if defined(V8_TARGET_LITTLE_ENDIAN)
   Matcher<Node*> high_word_load_matcher =
       IsLoad(MachineType::Int32(), IsInt32Constant(base),
              IsInt32Add(IsInt32Constant(index), IsInt32Constant(0x4)), start(),
@@ -146,6 +147,21 @@
                        start()),
                 AllOf(CaptureEq(&high_word_load), high_word_load_matcher),
                 start(), start()));
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  Matcher<Node*> high_word_load_matcher =
+      IsLoad(MachineType::Int32(), IsInt32Constant(base),
+             IsInt32Constant(index), start(), start());
+
+  EXPECT_THAT(
+      graph()->end()->InputAt(1),
+      IsReturn2(
+          IsLoad(MachineType::Int32(), IsInt32Constant(base),
+                 IsInt32Add(IsInt32Constant(index), IsInt32Constant(0x4)),
+                 AllOf(CaptureEq(&high_word_load), high_word_load_matcher),
+                 start()),
+          AllOf(CaptureEq(&high_word_load), high_word_load_matcher), start(),
+          start()));
+#endif
 }
 
 TEST_F(Int64LoweringTest, Int64Store) {
@@ -177,6 +193,7 @@
   const StoreRepresentation rep(MachineRepresentation::kWord32,
                                 kNoWriteBarrier);
 
+#if defined(V8_TARGET_LITTLE_ENDIAN)
   EXPECT_THAT(
       graph()->end()->InputAt(1),
       IsReturn(
@@ -189,6 +206,20 @@
                       IsInt32Constant(high_word_value(0)), start(), start()),
               start()),
           start()));
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  EXPECT_THAT(
+      graph()->end()->InputAt(1),
+      IsReturn(
+          IsInt32Constant(return_value),
+          IsStore(
+              rep, IsInt32Constant(base),
+              IsInt32Add(IsInt32Constant(index), IsInt32Constant(4)),
+              IsInt32Constant(low_word_value(0)),
+              IsStore(rep, IsInt32Constant(base), IsInt32Constant(index),
+                      IsInt32Constant(high_word_value(0)), start(), start()),
+              start()),
+          start()));
+#endif
 }
 
 TEST_F(Int64LoweringTest, Int64And) {
@@ -301,9 +332,6 @@
       wasm::ModuleEnv::GetI32WasmCallDescriptor(zone(), desc));
 }
 
-// todo(ahaas): I added a list of missing instructions here to make merging
-// easier when I do them one by one.
-// kExprI64Add:
 TEST_F(Int64LoweringTest, Int64Add) {
   LowerGraph(graph()->NewNode(machine()->Int64Add(), Int64Constant(value(0)),
                               Int64Constant(value(1))),
@@ -319,7 +347,7 @@
                         IsProjection(1, AllOf(CaptureEq(&add), add_matcher)),
                         start(), start()));
 }
-// kExprI64Sub:
+
 TEST_F(Int64LoweringTest, Int64Sub) {
   LowerGraph(graph()->NewNode(machine()->Int64Sub(), Int64Constant(value(0)),
                               Int64Constant(value(1))),
@@ -336,7 +364,6 @@
                         start(), start()));
 }
 
-// kExprI64Mul:
 TEST_F(Int64LoweringTest, Int64Mul) {
   LowerGraph(graph()->NewNode(machine()->Int64Mul(), Int64Constant(value(0)),
                               Int64Constant(value(1))),
@@ -354,11 +381,6 @@
                 start(), start()));
 }
 
-// kExprI64DivS:
-// kExprI64DivU:
-// kExprI64RemS:
-// kExprI64RemU:
-// kExprI64Ior:
 TEST_F(Int64LoweringTest, Int64Ior) {
   LowerGraph(graph()->NewNode(machine()->Word64Or(), Int64Constant(value(0)),
                               Int64Constant(value(1))),
@@ -371,7 +393,6 @@
                         start(), start()));
 }
 
-// kExprI64Xor:
 TEST_F(Int64LoweringTest, Int64Xor) {
   LowerGraph(graph()->NewNode(machine()->Word64Xor(), Int64Constant(value(0)),
                               Int64Constant(value(1))),
@@ -383,7 +404,7 @@
                                     IsInt32Constant(high_word_value(1))),
                         start(), start()));
 }
-// kExprI64Shl:
+
 TEST_F(Int64LoweringTest, Int64Shl) {
   LowerGraph(graph()->NewNode(machine()->Word64Shl(), Int64Constant(value(0)),
                               Int64Constant(value(1))),
@@ -399,7 +420,7 @@
                         IsProjection(1, AllOf(CaptureEq(&shl), shl_matcher)),
                         start(), start()));
 }
-// kExprI64ShrU:
+
 TEST_F(Int64LoweringTest, Int64ShrU) {
   LowerGraph(graph()->NewNode(machine()->Word64Shr(), Int64Constant(value(0)),
                               Int64Constant(value(1))),
@@ -415,7 +436,7 @@
                         IsProjection(1, AllOf(CaptureEq(&shr), shr_matcher)),
                         start(), start()));
 }
-// kExprI64ShrS:
+
 TEST_F(Int64LoweringTest, Int64ShrS) {
   LowerGraph(graph()->NewNode(machine()->Word64Sar(), Int64Constant(value(0)),
                               Int64Constant(value(1))),
@@ -431,7 +452,7 @@
                         IsProjection(1, AllOf(CaptureEq(&sar), sar_matcher)),
                         start(), start()));
 }
-// kExprI64Eq:
+
 TEST_F(Int64LoweringTest, Int64Eq) {
   LowerGraph(graph()->NewNode(machine()->Word64Equal(), Int64Constant(value(0)),
                               Int64Constant(value(1))),
@@ -447,27 +468,25 @@
                start(), start()));
 }
 
-// kExprI64LtS:
 TEST_F(Int64LoweringTest, Int64LtS) {
   TestComparison(machine()->Int64LessThan(), IsInt32LessThan, IsUint32LessThan);
 }
-// kExprI64LeS:
+
 TEST_F(Int64LoweringTest, Int64LeS) {
   TestComparison(machine()->Int64LessThanOrEqual(), IsInt32LessThan,
                  IsUint32LessThanOrEqual);
 }
-// kExprI64LtU:
+
 TEST_F(Int64LoweringTest, Int64LtU) {
   TestComparison(machine()->Uint64LessThan(), IsUint32LessThan,
                  IsUint32LessThan);
 }
-// kExprI64LeU:
+
 TEST_F(Int64LoweringTest, Int64LeU) {
   TestComparison(machine()->Uint64LessThanOrEqual(), IsUint32LessThan,
                  IsUint32LessThanOrEqual);
 }
 
-// kExprI32ConvertI64:
 TEST_F(Int64LoweringTest, I32ConvertI64) {
   LowerGraph(graph()->NewNode(machine()->TruncateInt64ToInt32(),
                               Int64Constant(value(0))),
@@ -475,7 +494,7 @@
   EXPECT_THAT(graph()->end()->InputAt(1),
               IsReturn(IsInt32Constant(low_word_value(0)), start(), start()));
 }
-// kExprI64SConvertI32:
+
 TEST_F(Int64LoweringTest, I64SConvertI32) {
   LowerGraph(graph()->NewNode(machine()->ChangeInt32ToInt64(),
                               Int32Constant(low_word_value(0))),
@@ -501,7 +520,7 @@
                                     IsInt32Constant(31)),
                         start(), start()));
 }
-// kExprI64UConvertI32:
+
 TEST_F(Int64LoweringTest, I64UConvertI32) {
   LowerGraph(graph()->NewNode(machine()->ChangeUint32ToUint64(),
                               Int32Constant(low_word_value(0))),
@@ -523,7 +542,7 @@
               IsReturn2(IsInt32Constant(low_word_value(0)), IsInt32Constant(0),
                         start(), start()));
 }
-// kExprF64ReinterpretI64:
+
 TEST_F(Int64LoweringTest, F64ReinterpretI64) {
   LowerGraph(graph()->NewNode(machine()->BitcastInt64ToFloat64(),
                               Int64Constant(value(0))),
@@ -538,12 +557,13 @@
       IsStore(StoreRepresentation(MachineRepresentation::kWord32,
                                   WriteBarrierKind::kNoWriteBarrier),
               AllOf(CaptureEq(&stack_slot_capture), stack_slot_matcher),
-              IsInt32Constant(0), IsInt32Constant(low_word_value(0)),
+              IsInt32Constant(Int64Lowering::kLowerWordOffset),
+              IsInt32Constant(low_word_value(0)),
               IsStore(StoreRepresentation(MachineRepresentation::kWord32,
                                           WriteBarrierKind::kNoWriteBarrier),
                       AllOf(CaptureEq(&stack_slot_capture), stack_slot_matcher),
-                      IsInt32Constant(4), IsInt32Constant(high_word_value(0)),
-                      start(), start()),
+                      IsInt32Constant(Int64Lowering::kHigherWordOffset),
+                      IsInt32Constant(high_word_value(0)), start(), start()),
               start());
 
   EXPECT_THAT(
@@ -554,7 +574,7 @@
                       AllOf(CaptureEq(&store_capture), store_matcher), start()),
                start(), start()));
 }
-// kExprI64ReinterpretF64:
+
 TEST_F(Int64LoweringTest, I64ReinterpretF64) {
   LowerGraph(graph()->NewNode(machine()->BitcastFloat64ToInt64(),
                               Float64Constant(bit_cast<double>(value(0)))),
@@ -575,15 +595,15 @@
       graph()->end()->InputAt(1),
       IsReturn2(IsLoad(MachineType::Int32(),
                        AllOf(CaptureEq(&stack_slot), stack_slot_matcher),
-                       IsInt32Constant(0),
+                       IsInt32Constant(Int64Lowering::kLowerWordOffset),
                        AllOf(CaptureEq(&store), store_matcher), start()),
                 IsLoad(MachineType::Int32(),
                        AllOf(CaptureEq(&stack_slot), stack_slot_matcher),
-                       IsInt32Constant(0x4),
+                       IsInt32Constant(Int64Lowering::kHigherWordOffset),
                        AllOf(CaptureEq(&store), store_matcher), start()),
                 start(), start()));
 }
-// kExprI64Clz:
+
 TEST_F(Int64LoweringTest, I64Clz) {
   LowerGraph(graph()->NewNode(machine()->Word64Clz(), Int64Constant(value(0))),
              MachineRepresentation::kWord64);
@@ -606,7 +626,7 @@
                         AllOf(CaptureEq(&branch_capture), branch_matcher)))),
           IsInt32Constant(0), start(), start()));
 }
-// kExprI64Ctz:
+
 TEST_F(Int64LoweringTest, I64Ctz) {
   LowerGraph(graph()->NewNode(machine()->Word64CtzPlaceholder(),
                               Int64Constant(value(0))),
@@ -628,7 +648,6 @@
                         AllOf(CaptureEq(&branch_capture), branch_matcher)))),
           IsInt32Constant(0), start(), start()));
 }
-// kExprI64Popcnt:
 
 TEST_F(Int64LoweringTest, Dfs) {
   Node* common = Int64Constant(value(0));
diff --git a/test/unittests/compiler/js-builtin-reducer-unittest.cc b/test/unittests/compiler/js-builtin-reducer-unittest.cc
index 0f8eed7..9a1378a 100644
--- a/test/unittests/compiler/js-builtin-reducer-unittest.cc
+++ b/test/unittests/compiler/js-builtin-reducer-unittest.cc
@@ -49,6 +49,19 @@
     return HeapConstant(f);
   }
 
+  Node* StringFunction(const char* name) {
+    Handle<Object> m =
+        JSObject::GetProperty(
+            isolate()->global_object(),
+            isolate()->factory()->NewStringFromAsciiChecked("String"))
+            .ToHandleChecked();
+    Handle<JSFunction> f = Handle<JSFunction>::cast(
+        Object::GetProperty(
+            m, isolate()->factory()->NewStringFromAsciiChecked(name))
+            .ToHandleChecked());
+    return HeapConstant(f);
+  }
+
   JSOperatorBuilder* javascript() { return &javascript_; }
 
  private:
@@ -74,10 +87,519 @@
 
 
 // -----------------------------------------------------------------------------
+// Math.abs
+
+TEST_F(JSBuiltinReducerTest, MathAbsWithNumber) {
+  Node* function = MathFunction("abs");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  effect, control);
+    Reduction r = Reduce(call);
+
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsNumberAbs(p0));
+  }
+}
+
+TEST_F(JSBuiltinReducerTest, MathAbsWithPlainPrimitive) {
+  Node* function = MathFunction("abs");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberAbs(IsPlainPrimitiveToNumber(p0)));
+}
+
+// -----------------------------------------------------------------------------
+// Math.atan
+
+TEST_F(JSBuiltinReducerTest, MathAtanWithNumber) {
+  Node* function = MathFunction("atan");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  effect, control);
+    Reduction r = Reduce(call);
+
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsNumberAtan(p0));
+  }
+}
+
+TEST_F(JSBuiltinReducerTest, MathAtanWithPlainPrimitive) {
+  Node* function = MathFunction("atan");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberAtan(IsPlainPrimitiveToNumber(p0)));
+}
+
+// -----------------------------------------------------------------------------
+// Math.atan2
+
+TEST_F(JSBuiltinReducerTest, MathAtan2WithNumber) {
+  Node* function = MathFunction("atan2");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    TRACED_FOREACH(Type*, t1, kNumberTypes) {
+      Node* p1 = Parameter(t1, 0);
+      Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
+                                    UndefinedConstant(), p0, p1, context,
+                                    frame_state, effect, control);
+      Reduction r = Reduce(call);
+
+      ASSERT_TRUE(r.Changed());
+      EXPECT_THAT(r.replacement(), IsNumberAtan2(p0, p1));
+    }
+  }
+}
+
+TEST_F(JSBuiltinReducerTest, MathAtan2WithPlainPrimitive) {
+  Node* function = MathFunction("atan2");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* p1 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
+                                UndefinedConstant(), p0, p1, context,
+                                frame_state, effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberAtan2(IsPlainPrimitiveToNumber(p0),
+                                             IsPlainPrimitiveToNumber(p1)));
+}
+
+// -----------------------------------------------------------------------------
+// Math.ceil
+
+TEST_F(JSBuiltinReducerTest, MathCeilWithNumber) {
+  Node* function = MathFunction("ceil");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  effect, control);
+    Reduction r = Reduce(call);
+
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsNumberCeil(p0));
+  }
+}
+
+TEST_F(JSBuiltinReducerTest, MathCeilWithPlainPrimitive) {
+  Node* function = MathFunction("ceil");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberCeil(IsPlainPrimitiveToNumber(p0)));
+}
+
+// -----------------------------------------------------------------------------
+// Math.clz32
+
+TEST_F(JSBuiltinReducerTest, MathClz32WithUnsigned32) {
+  Node* function = MathFunction("clz32");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::Unsigned32(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberClz32(p0));
+}
+
+TEST_F(JSBuiltinReducerTest, MathClz32WithNumber) {
+  Node* function = MathFunction("clz32");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::Number(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberClz32(IsNumberToUint32(p0)));
+}
+
+TEST_F(JSBuiltinReducerTest, MathClz32WithPlainPrimitive) {
+  Node* function = MathFunction("clz32");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(),
+              IsNumberClz32(IsNumberToUint32(IsPlainPrimitiveToNumber(p0))));
+}
+
+// -----------------------------------------------------------------------------
+// Math.cos
+
+TEST_F(JSBuiltinReducerTest, MathCosWithNumber) {
+  Node* function = MathFunction("cos");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  effect, control);
+    Reduction r = Reduce(call);
+
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsNumberCos(p0));
+  }
+}
+
+TEST_F(JSBuiltinReducerTest, MathCosWithPlainPrimitive) {
+  Node* function = MathFunction("cos");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberCos(IsPlainPrimitiveToNumber(p0)));
+}
+
+// -----------------------------------------------------------------------------
+// Math.exp
+
+TEST_F(JSBuiltinReducerTest, MathExpWithNumber) {
+  Node* function = MathFunction("exp");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  effect, control);
+    Reduction r = Reduce(call);
+
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsNumberExp(p0));
+  }
+}
+
+TEST_F(JSBuiltinReducerTest, MathExpWithPlainPrimitive) {
+  Node* function = MathFunction("exp");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberExp(IsPlainPrimitiveToNumber(p0)));
+}
+
+// -----------------------------------------------------------------------------
+// Math.floor
+
+TEST_F(JSBuiltinReducerTest, MathFloorWithNumber) {
+  Node* function = MathFunction("floor");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  effect, control);
+    Reduction r = Reduce(call);
+
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsNumberFloor(p0));
+  }
+}
+
+TEST_F(JSBuiltinReducerTest, MathFloorWithPlainPrimitive) {
+  Node* function = MathFunction("floor");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberFloor(IsPlainPrimitiveToNumber(p0)));
+}
+
+// -----------------------------------------------------------------------------
+// Math.fround
+
+TEST_F(JSBuiltinReducerTest, MathFroundWithNumber) {
+  Node* function = MathFunction("fround");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  effect, control);
+    Reduction r = Reduce(call);
+
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsNumberFround(p0));
+  }
+}
+
+TEST_F(JSBuiltinReducerTest, MathFroundWithPlainPrimitive) {
+  Node* function = MathFunction("fround");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberFround(IsPlainPrimitiveToNumber(p0)));
+}
+
+// -----------------------------------------------------------------------------
+// Math.imul
+
+TEST_F(JSBuiltinReducerTest, MathImulWithUnsigned32) {
+  Node* function = MathFunction("imul");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::Unsigned32(), 0);
+  Node* p1 = Parameter(Type::Unsigned32(), 1);
+  Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
+                                UndefinedConstant(), p0, p1, context,
+                                frame_state, effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberImul(p0, p1));
+}
+
+TEST_F(JSBuiltinReducerTest, MathImulWithNumber) {
+  Node* function = MathFunction("imul");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::Number(), 0);
+  Node* p1 = Parameter(Type::Number(), 1);
+  Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
+                                UndefinedConstant(), p0, p1, context,
+                                frame_state, effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(),
+              IsNumberImul(IsNumberToUint32(p0), IsNumberToUint32(p1)));
+}
+
+TEST_F(JSBuiltinReducerTest, MathImulWithPlainPrimitive) {
+  Node* function = MathFunction("imul");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* p1 = Parameter(Type::PlainPrimitive(), 1);
+  Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
+                                UndefinedConstant(), p0, p1, context,
+                                frame_state, effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(),
+              IsNumberImul(IsNumberToUint32(IsPlainPrimitiveToNumber(p0)),
+                           IsNumberToUint32(IsPlainPrimitiveToNumber(p1))));
+}
+
+// -----------------------------------------------------------------------------
+// Math.log
+
+TEST_F(JSBuiltinReducerTest, MathLogWithNumber) {
+  Node* function = MathFunction("log");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  effect, control);
+    Reduction r = Reduce(call);
+
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsNumberLog(p0));
+  }
+}
+
+TEST_F(JSBuiltinReducerTest, MathLogWithPlainPrimitive) {
+  Node* function = MathFunction("log");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberLog(IsPlainPrimitiveToNumber(p0)));
+}
+
+// -----------------------------------------------------------------------------
+// Math.log1p
+
+TEST_F(JSBuiltinReducerTest, MathLog1pWithNumber) {
+  Node* function = MathFunction("log1p");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  effect, control);
+    Reduction r = Reduce(call);
+
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsNumberLog1p(p0));
+  }
+}
+
+TEST_F(JSBuiltinReducerTest, MathLog1pWithPlainPrimitive) {
+  Node* function = MathFunction("log1p");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberLog1p(IsPlainPrimitiveToNumber(p0)));
+}
+
+// -----------------------------------------------------------------------------
 // Math.max
 
-
-TEST_F(JSBuiltinReducerTest, MathMax0) {
+TEST_F(JSBuiltinReducerTest, MathMaxWithNoArguments) {
   Node* function = MathFunction("max");
 
   Node* effect = graph()->start();
@@ -86,15 +608,14 @@
   Node* frame_state = graph()->start();
   Node* call = graph()->NewNode(javascript()->CallFunction(2), function,
                                 UndefinedConstant(), context, frame_state,
-                                frame_state, effect, control);
+                                effect, control);
   Reduction r = Reduce(call);
 
   ASSERT_TRUE(r.Changed());
   EXPECT_THAT(r.replacement(), IsNumberConstant(-V8_INFINITY));
 }
 
-
-TEST_F(JSBuiltinReducerTest, MathMax1) {
+TEST_F(JSBuiltinReducerTest, MathMaxWithNumber) {
   Node* function = MathFunction("max");
 
   Node* effect = graph()->start();
@@ -105,7 +626,7 @@
     Node* p0 = Parameter(t0, 0);
     Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
                                   UndefinedConstant(), p0, context, frame_state,
-                                  frame_state, effect, control);
+                                  effect, control);
     Reduction r = Reduce(call);
 
     ASSERT_TRUE(r.Changed());
@@ -113,8 +634,24 @@
   }
 }
 
+TEST_F(JSBuiltinReducerTest, MathMaxWithPlainPrimitive) {
+  Node* function = MathFunction("max");
 
-TEST_F(JSBuiltinReducerTest, MathMax2) {
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsPlainPrimitiveToNumber(p0));
+}
+
+TEST_F(JSBuiltinReducerTest, MathMaxWithIntegral32) {
   Node* function = MathFunction("max");
 
   Node* effect = graph()->start();
@@ -127,7 +664,7 @@
       Node* p1 = Parameter(t1, 1);
       Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
                                     UndefinedConstant(), p0, p1, context,
-                                    frame_state, frame_state, effect, control);
+                                    frame_state, effect, control);
       Reduction r = Reduce(call);
 
       ASSERT_TRUE(r.Changed());
@@ -137,41 +674,27 @@
   }
 }
 
-
 // -----------------------------------------------------------------------------
-// Math.imul
+// Math.min
 
-
-TEST_F(JSBuiltinReducerTest, MathImul) {
-  Node* function = MathFunction("imul");
+TEST_F(JSBuiltinReducerTest, MathMinWithNoArguments) {
+  Node* function = MathFunction("min");
 
   Node* effect = graph()->start();
   Node* control = graph()->start();
   Node* context = UndefinedConstant();
   Node* frame_state = graph()->start();
-  TRACED_FOREACH(Type*, t0, kNumberTypes) {
-    TRACED_FOREACH(Type*, t1, kNumberTypes) {
-      Node* p0 = Parameter(t0, 0);
-      Node* p1 = Parameter(t1, 1);
-      Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
-                                    UndefinedConstant(), p0, p1, context,
-                                    frame_state, frame_state, effect, control);
-      Reduction r = Reduce(call);
+  Node* call = graph()->NewNode(javascript()->CallFunction(2), function,
+                                UndefinedConstant(), context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
 
-      ASSERT_TRUE(r.Changed());
-      EXPECT_THAT(r.replacement(),
-                  IsNumberImul(IsNumberToUint32(p0), IsNumberToUint32(p1)));
-    }
-  }
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberConstant(V8_INFINITY));
 }
 
-
-// -----------------------------------------------------------------------------
-// Math.fround
-
-
-TEST_F(JSBuiltinReducerTest, MathFround) {
-  Node* function = MathFunction("fround");
+TEST_F(JSBuiltinReducerTest, MathMinWithNumber) {
+  Node* function = MathFunction("min");
 
   Node* effect = graph()->start();
   Node* control = graph()->start();
@@ -181,14 +704,289 @@
     Node* p0 = Parameter(t0, 0);
     Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
                                   UndefinedConstant(), p0, context, frame_state,
-                                  frame_state, effect, control);
+                                  effect, control);
     Reduction r = Reduce(call);
 
     ASSERT_TRUE(r.Changed());
-    EXPECT_THAT(r.replacement(), IsTruncateFloat64ToFloat32(p0));
+    EXPECT_THAT(r.replacement(), p0);
   }
 }
 
+TEST_F(JSBuiltinReducerTest, MathMinWithPlainPrimitive) {
+  Node* function = MathFunction("min");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsPlainPrimitiveToNumber(p0));
+}
+
+TEST_F(JSBuiltinReducerTest, MathMinWithIntegral32) {
+  Node* function = MathFunction("min");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kIntegral32Types) {
+    TRACED_FOREACH(Type*, t1, kIntegral32Types) {
+      Node* p0 = Parameter(t0, 0);
+      Node* p1 = Parameter(t1, 1);
+      Node* call = graph()->NewNode(javascript()->CallFunction(4), function,
+                                    UndefinedConstant(), p0, p1, context,
+                                    frame_state, effect, control);
+      Reduction r = Reduce(call);
+
+      ASSERT_TRUE(r.Changed());
+      EXPECT_THAT(r.replacement(), IsSelect(MachineRepresentation::kNone,
+                                            IsNumberLessThan(p1, p0), p1, p0));
+    }
+  }
+}
+
+// -----------------------------------------------------------------------------
+// Math.round
+
+TEST_F(JSBuiltinReducerTest, MathRoundWithNumber) {
+  Node* function = MathFunction("round");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  effect, control);
+    Reduction r = Reduce(call);
+
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsNumberRound(p0));
+  }
+}
+
+TEST_F(JSBuiltinReducerTest, MathRoundWithPlainPrimitive) {
+  Node* function = MathFunction("round");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberRound(IsPlainPrimitiveToNumber(p0)));
+}
+
+// -----------------------------------------------------------------------------
+// Math.sin
+
+TEST_F(JSBuiltinReducerTest, MathSinWithNumber) {
+  Node* function = MathFunction("sin");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  effect, control);
+    Reduction r = Reduce(call);
+
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsNumberSin(p0));
+  }
+}
+
+TEST_F(JSBuiltinReducerTest, MathSinWithPlainPrimitive) {
+  Node* function = MathFunction("sin");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberSin(IsPlainPrimitiveToNumber(p0)));
+}
+
+// -----------------------------------------------------------------------------
+// Math.sqrt
+
+TEST_F(JSBuiltinReducerTest, MathSqrtWithNumber) {
+  Node* function = MathFunction("sqrt");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  effect, control);
+    Reduction r = Reduce(call);
+
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsNumberSqrt(p0));
+  }
+}
+
+TEST_F(JSBuiltinReducerTest, MathSqrtWithPlainPrimitive) {
+  Node* function = MathFunction("sqrt");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberSqrt(IsPlainPrimitiveToNumber(p0)));
+}
+
+// -----------------------------------------------------------------------------
+// Math.tan
+
+TEST_F(JSBuiltinReducerTest, MathTanWithNumber) {
+  Node* function = MathFunction("tan");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  effect, control);
+    Reduction r = Reduce(call);
+
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsNumberTan(p0));
+  }
+}
+
+TEST_F(JSBuiltinReducerTest, MathTanWithPlainPrimitive) {
+  Node* function = MathFunction("tan");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberTan(IsPlainPrimitiveToNumber(p0)));
+}
+
+// -----------------------------------------------------------------------------
+// Math.trunc
+
+TEST_F(JSBuiltinReducerTest, MathTruncWithNumber) {
+  Node* function = MathFunction("trunc");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  effect, control);
+    Reduction r = Reduce(call);
+
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsNumberTrunc(p0));
+  }
+}
+
+TEST_F(JSBuiltinReducerTest, MathTruncWithPlainPrimitive) {
+  Node* function = MathFunction("trunc");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberTrunc(IsPlainPrimitiveToNumber(p0)));
+}
+
+// -----------------------------------------------------------------------------
+// String.fromCharCode
+
+TEST_F(JSBuiltinReducerTest, StringFromCharCodeWithNumber) {
+  Node* function = StringFunction("fromCharCode");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  TRACED_FOREACH(Type*, t0, kNumberTypes) {
+    Node* p0 = Parameter(t0, 0);
+    Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                  UndefinedConstant(), p0, context, frame_state,
+                                  effect, control);
+    Reduction r = Reduce(call);
+
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsStringFromCharCode(p0));
+  }
+}
+
+TEST_F(JSBuiltinReducerTest, StringFromCharCodeWithPlainPrimitive) {
+  Node* function = StringFunction("fromCharCode");
+
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* context = UndefinedConstant();
+  Node* frame_state = graph()->start();
+  Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+  Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+                                UndefinedConstant(), p0, context, frame_state,
+                                effect, control);
+  Reduction r = Reduce(call);
+
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(),
+              IsStringFromCharCode(IsPlainPrimitiveToNumber(p0)));
+}
+
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/test/unittests/compiler/js-create-lowering-unittest.cc b/test/unittests/compiler/js-create-lowering-unittest.cc
index 837c574..6e6245d 100644
--- a/test/unittests/compiler/js-create-lowering-unittest.cc
+++ b/test/unittests/compiler/js-create-lowering-unittest.cc
@@ -80,95 +80,74 @@
 // -----------------------------------------------------------------------------
 // JSCreateArguments
 
-TEST_F(JSCreateLoweringTest, JSCreateArgumentsViaStub) {
-  Node* const closure = Parameter(Type::Any());
-  Node* const context = UndefinedConstant();
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
-  Node* const frame_state = FrameState(shared, graph()->start());
-  Reduction r = Reduce(graph()->NewNode(
-      javascript()->CreateArguments(CreateArgumentsType::kUnmappedArguments),
-      closure, context, frame_state, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(
-      r.replacement(),
-      IsCall(_, IsHeapConstant(
-                    CodeFactory::FastNewStrictArguments(isolate()).code()),
-             closure, context, frame_state, effect, control));
-}
-
-TEST_F(JSCreateLoweringTest, JSCreateArgumentsRestParameterViaStub) {
-  Node* const closure = Parameter(Type::Any());
-  Node* const context = UndefinedConstant();
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
-  Node* const frame_state = FrameState(shared, graph()->start());
-  Reduction r = Reduce(graph()->NewNode(
-      javascript()->CreateArguments(CreateArgumentsType::kRestParameter),
-      closure, context, frame_state, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(
-      r.replacement(),
-      IsCall(_, IsHeapConstant(
-                    CodeFactory::FastNewRestParameter(isolate()).code()),
-             closure, context, frame_state, effect, control));
-}
-
 TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedMapped) {
   Node* const closure = Parameter(Type::Any());
   Node* const context = UndefinedConstant();
   Node* const effect = graph()->start();
-  Node* const control = graph()->start();
   Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
   Node* const frame_state_outer = FrameState(shared, graph()->start());
   Node* const frame_state_inner = FrameState(shared, frame_state_outer);
   Reduction r = Reduce(graph()->NewNode(
       javascript()->CreateArguments(CreateArgumentsType::kMappedArguments),
-      closure, context, frame_state_inner, effect, control));
+      closure, context, frame_state_inner, effect));
   ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(),
-              IsFinishRegion(
-                  IsAllocate(IsNumberConstant(JSSloppyArgumentsObject::kSize),
-                             _, control),
-                  _));
+  EXPECT_THAT(
+      r.replacement(),
+      IsFinishRegion(
+          IsAllocate(IsNumberConstant(JSSloppyArgumentsObject::kSize), _, _),
+          _));
 }
 
 TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedUnmapped) {
   Node* const closure = Parameter(Type::Any());
   Node* const context = UndefinedConstant();
   Node* const effect = graph()->start();
-  Node* const control = graph()->start();
   Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
   Node* const frame_state_outer = FrameState(shared, graph()->start());
   Node* const frame_state_inner = FrameState(shared, frame_state_outer);
   Reduction r = Reduce(graph()->NewNode(
       javascript()->CreateArguments(CreateArgumentsType::kUnmappedArguments),
-      closure, context, frame_state_inner, effect, control));
+      closure, context, frame_state_inner, effect));
   ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(),
-              IsFinishRegion(
-                  IsAllocate(IsNumberConstant(JSStrictArgumentsObject::kSize),
-                             _, control),
-                  _));
+  EXPECT_THAT(
+      r.replacement(),
+      IsFinishRegion(
+          IsAllocate(IsNumberConstant(JSStrictArgumentsObject::kSize), _, _),
+          _));
 }
 
 TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedRestArray) {
   Node* const closure = Parameter(Type::Any());
   Node* const context = UndefinedConstant();
   Node* const effect = graph()->start();
-  Node* const control = graph()->start();
   Handle<SharedFunctionInfo> shared(isolate()->object_function()->shared());
   Node* const frame_state_outer = FrameState(shared, graph()->start());
   Node* const frame_state_inner = FrameState(shared, frame_state_outer);
   Reduction r = Reduce(graph()->NewNode(
       javascript()->CreateArguments(CreateArgumentsType::kRestParameter),
-      closure, context, frame_state_inner, effect, control));
+      closure, context, frame_state_inner, effect));
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(
+      r.replacement(),
+      IsFinishRegion(IsAllocate(IsNumberConstant(JSArray::kSize), _, _), _));
+}
+
+// -----------------------------------------------------------------------------
+// JSCreateClosure
+
+TEST_F(JSCreateLoweringTest, JSCreateClosureViaInlinedAllocation) {
+  Node* const context = UndefinedConstant();
+  Node* const effect = graph()->start();
+  Node* const control = graph()->start();
+  Handle<SharedFunctionInfo> shared(isolate()->number_function()->shared());
+  Reduction r =
+      Reduce(graph()->NewNode(javascript()->CreateClosure(shared, NOT_TENURED),
+                              context, effect, control));
   ASSERT_TRUE(r.Changed());
   EXPECT_THAT(r.replacement(),
-              IsFinishRegion(
-                  IsAllocate(IsNumberConstant(JSArray::kSize), _, control), _));
+              IsFinishRegion(IsAllocate(IsNumberConstant(JSFunction::kSize),
+                                        IsBeginRegion(_), control),
+                             _));
 }
 
 // -----------------------------------------------------------------------------
diff --git a/test/unittests/compiler/js-intrinsic-lowering-unittest.cc b/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
index de0eefc..7024559 100644
--- a/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
+++ b/test/unittests/compiler/js-intrinsic-lowering-unittest.cc
@@ -43,13 +43,6 @@
     return reducer.Reduce(node);
   }
 
-  Node* EmptyFrameState() {
-    MachineOperatorBuilder machine(zone());
-    JSGraph jsgraph(isolate(), graph(), common(), javascript(), nullptr,
-                    &machine);
-    return jsgraph.EmptyFrameState();
-  }
-
   JSOperatorBuilder* javascript() { return &javascript_; }
 
  private:
@@ -58,27 +51,6 @@
 
 
 // -----------------------------------------------------------------------------
-// %_ConstructDouble
-
-
-TEST_F(JSIntrinsicLoweringTest, InlineOptimizedConstructDouble) {
-  Node* const input0 = Parameter(0);
-  Node* const input1 = Parameter(1);
-  Node* const context = Parameter(2);
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Reduction const r = Reduce(graph()->NewNode(
-      javascript()->CallRuntime(Runtime::kInlineConstructDouble, 2), input0,
-      input1, context, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(), IsFloat64InsertHighWord32(
-                                   IsFloat64InsertLowWord32(
-                                       IsNumberConstant(BitEq(0.0)), input1),
-                                   input0));
-}
-
-
-// -----------------------------------------------------------------------------
 // %_DoubleLo
 
 
@@ -92,7 +64,7 @@
                        input, context, effect, control));
   ASSERT_TRUE(r.Changed());
   EXPECT_THAT(r.replacement(),
-              IsFloat64ExtractLowWord32(IsGuard(Type::Number(), input, _)));
+              IsFloat64ExtractLowWord32(IsTypeGuard(Type::Number(), input, _)));
 }
 
 
@@ -109,8 +81,8 @@
       graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineDoubleHi, 1),
                        input, context, effect, control));
   ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(),
-              IsFloat64ExtractHighWord32(IsGuard(Type::Number(), input, _)));
+  EXPECT_THAT(r.replacement(), IsFloat64ExtractHighWord32(
+                                   IsTypeGuard(Type::Number(), input, _)));
 }
 
 
@@ -284,23 +256,6 @@
               AllOf(CaptureEq(&if_false0), IsIfFalse(CaptureEq(&branch0))))));
 }
 
-// -----------------------------------------------------------------------------
-// %_GetOrdinaryHasInstance
-
-TEST_F(JSIntrinsicLoweringTest, InlineGetOrdinaryHasInstance) {
-  Node* const context = Parameter(0);
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Reduction const r = Reduce(graph()->NewNode(
-      javascript()->CallRuntime(Runtime::kInlineGetOrdinaryHasInstance, 0),
-      context, effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(
-      r.replacement(),
-      IsLoadContext(
-          ContextAccess(0, Context::ORDINARY_HAS_INSTANCE_INDEX, true), _));
-}
-
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
diff --git a/test/unittests/compiler/js-operator-unittest.cc b/test/unittests/compiler/js-operator-unittest.cc
index 15b1427..d5f30ef 100644
--- a/test/unittests/compiler/js-operator-unittest.cc
+++ b/test/unittests/compiler/js-operator-unittest.cc
@@ -40,23 +40,12 @@
         control_input_count, value_output_count, effect_output_count,        \
         control_output_count                                                 \
   }
-    SHARED(Equal, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
-    SHARED(NotEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
-    SHARED(StrictEqual, Operator::kNoThrow, 2, 0, 1, 1, 1, 1, 0),
-    SHARED(StrictNotEqual, Operator::kNoThrow, 2, 0, 1, 1, 1, 1, 0),
-    SHARED(LessThan, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
-    SHARED(GreaterThan, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
-    SHARED(LessThanOrEqual, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
-    SHARED(GreaterThanOrEqual, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
     SHARED(ToNumber, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
     SHARED(ToString, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
     SHARED(ToName, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
-    SHARED(ToObject, Operator::kNoProperties, 1, 1, 1, 1, 1, 1, 2),
-    SHARED(Yield, Operator::kNoProperties, 1, 0, 1, 1, 1, 1, 2),
+    SHARED(ToObject, Operator::kFoldable, 1, 1, 1, 1, 1, 1, 2),
     SHARED(Create, Operator::kEliminatable, 2, 1, 1, 0, 1, 1, 0),
-    SHARED(HasProperty, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
-    SHARED(TypeOf, Operator::kEliminatable, 1, 0, 1, 0, 1, 1, 0),
-    SHARED(InstanceOf, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2),
+    SHARED(TypeOf, Operator::kPure, 1, 0, 0, 0, 1, 0, 0),
     SHARED(CreateWithContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1, 2),
     SHARED(CreateModuleContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1, 2),
 #undef SHARED
diff --git a/test/unittests/compiler/js-typed-lowering-unittest.cc b/test/unittests/compiler/js-typed-lowering-unittest.cc
index 1adb5da..3a8e778 100644
--- a/test/unittests/compiler/js-typed-lowering-unittest.cc
+++ b/test/unittests/compiler/js-typed-lowering-unittest.cc
@@ -87,8 +87,9 @@
     // TODO(titzer): mock the GraphReducer here for better unit testing.
     GraphReducer graph_reducer(zone(), graph());
     JSTypedLowering reducer(&graph_reducer, &deps_,
-                            JSTypedLowering::kDeoptimizationEnabled, &jsgraph,
-                            zone());
+                            JSTypedLowering::kDeoptimizationEnabled |
+                                JSTypedLowering::kTypeFeedbackEnabled,
+                            &jsgraph, zone());
     return reducer.Reduce(node);
   }
 
@@ -212,9 +213,8 @@
 TEST_F(JSTypedLoweringTest, JSToBooleanWithBoolean) {
   Node* input = Parameter(Type::Boolean(), 0);
   Node* context = Parameter(Type::Any(), 1);
-  Reduction r =
-      Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
-                              input, context, graph()->start()));
+  Reduction r = Reduce(graph()->NewNode(
+      javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
   ASSERT_TRUE(r.Changed());
   EXPECT_EQ(input, r.replacement());
 }
@@ -242,9 +242,8 @@
           zone()),
       0);
   Node* context = Parameter(Type::Any(), 1);
-  Reduction r =
-      Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
-                              input, context, graph()->start()));
+  Reduction r = Reduce(graph()->NewNode(
+      javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
   ASSERT_TRUE(r.Changed());
   EXPECT_THAT(r.replacement(), IsFalseConstant());
 }
@@ -258,9 +257,8 @@
           zone()),
       0);
   Node* context = Parameter(Type::Any(), 1);
-  Reduction r =
-      Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
-                              input, context, graph()->start()));
+  Reduction r = Reduce(graph()->NewNode(
+      javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
   ASSERT_TRUE(r.Changed());
   EXPECT_THAT(r.replacement(), IsTrueConstant());
 }
@@ -269,9 +267,8 @@
 TEST_F(JSTypedLoweringTest, JSToBooleanWithNonZeroPlainNumber) {
   Node* input = Parameter(Type::Range(1, V8_INFINITY, zone()), 0);
   Node* context = Parameter(Type::Any(), 1);
-  Reduction r =
-      Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
-                              input, context, graph()->start()));
+  Reduction r = Reduce(graph()->NewNode(
+      javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
   ASSERT_TRUE(r.Changed());
   EXPECT_THAT(r.replacement(), IsTrueConstant());
 }
@@ -280,9 +277,8 @@
 TEST_F(JSTypedLoweringTest, JSToBooleanWithOrderedNumber) {
   Node* input = Parameter(Type::OrderedNumber(), 0);
   Node* context = Parameter(Type::Any(), 1);
-  Reduction r =
-      Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
-                              input, context, graph()->start()));
+  Reduction r = Reduce(graph()->NewNode(
+      javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
   ASSERT_TRUE(r.Changed());
   EXPECT_THAT(r.replacement(),
               IsBooleanNot(IsNumberEqual(input, IsNumberConstant(0.0))));
@@ -292,9 +288,8 @@
 TEST_F(JSTypedLoweringTest, JSToBooleanWithString) {
   Node* input = Parameter(Type::String(), 0);
   Node* context = Parameter(Type::Any(), 1);
-  Reduction r =
-      Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
-                              input, context, graph()->start()));
+  Reduction r = Reduce(graph()->NewNode(
+      javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
   ASSERT_TRUE(r.Changed());
   EXPECT_THAT(
       r.replacement(),
@@ -307,9 +302,8 @@
 TEST_F(JSTypedLoweringTest, JSToBooleanWithAny) {
   Node* input = Parameter(Type::Any(), 0);
   Node* context = Parameter(Type::Any(), 1);
-  Reduction r =
-      Reduce(graph()->NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
-                              input, context, graph()->start()));
+  Reduction r = Reduce(graph()->NewNode(
+      javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
   ASSERT_FALSE(r.Changed());
 }
 
@@ -327,8 +321,7 @@
       Reduce(graph()->NewNode(javascript()->ToNumber(), input, context,
                               EmptyFrameState(), effect, control));
   ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(), IsToNumber(input, IsNumberConstant(BitEq(0.0)),
-                                          graph()->start(), control));
+  EXPECT_THAT(r.replacement(), IsPlainPrimitiveToNumber(input));
 }
 
 
@@ -391,9 +384,9 @@
   Node* const context = UndefinedConstant();
   TRACED_FOREACH(Type*, type, kJSTypes) {
     Node* const lhs = Parameter(type);
-    Reduction r =
-        Reduce(graph()->NewNode(javascript()->StrictEqual(), lhs, the_hole,
-                                context, graph()->start(), graph()->start()));
+    Reduction r = Reduce(graph()->NewNode(
+        javascript()->StrictEqual(CompareOperationHints::Any()), lhs, the_hole,
+        context));
     ASSERT_TRUE(r.Changed());
     EXPECT_THAT(r.replacement(), IsFalseConstant());
   }
@@ -404,9 +397,9 @@
   Node* const lhs = Parameter(Type::Unique(), 0);
   Node* const rhs = Parameter(Type::Unique(), 1);
   Node* const context = Parameter(Type::Any(), 2);
-  Reduction r =
-      Reduce(graph()->NewNode(javascript()->StrictEqual(), lhs, rhs, context,
-                              graph()->start(), graph()->start()));
+  Reduction r = Reduce(
+      graph()->NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
+                       lhs, rhs, context));
   ASSERT_TRUE(r.Changed());
   EXPECT_THAT(r.replacement(), IsReferenceEqual(Type::Unique(), lhs, rhs));
 }
@@ -611,9 +604,9 @@
     Node* context = UndefinedConstant();
     Node* effect = graph()->start();
     Node* control = graph()->start();
-    Reduction r = Reduce(graph()->NewNode(
-        javascript()->LoadProperty(feedback), base, key, vector, context,
-        EmptyFrameState(), EmptyFrameState(), effect, control));
+    Reduction r = Reduce(graph()->NewNode(javascript()->LoadProperty(feedback),
+                                          base, key, vector, context,
+                                          EmptyFrameState(), effect, control));
 
     Matcher<Node*> offset_matcher =
         element_size == 1
@@ -652,9 +645,9 @@
     Node* context = UndefinedConstant();
     Node* effect = graph()->start();
     Node* control = graph()->start();
-    Reduction r = Reduce(graph()->NewNode(
-        javascript()->LoadProperty(feedback), base, key, vector, context,
-        EmptyFrameState(), EmptyFrameState(), effect, control));
+    Reduction r = Reduce(graph()->NewNode(javascript()->LoadProperty(feedback),
+                                          base, key, vector, context,
+                                          EmptyFrameState(), effect, control));
 
     ASSERT_TRUE(r.Changed());
     EXPECT_THAT(
@@ -693,8 +686,7 @@
       VectorSlotPair feedback;
       const Operator* op = javascript()->StoreProperty(language_mode, feedback);
       Node* node = graph()->NewNode(op, base, key, value, vector, context,
-                                    EmptyFrameState(), EmptyFrameState(),
-                                    effect, control);
+                                    EmptyFrameState(), effect, control);
       Reduction r = Reduce(node);
 
       Matcher<Node*> offset_matcher =
@@ -734,11 +726,14 @@
       Node* context = UndefinedConstant();
       Node* effect = graph()->start();
       Node* control = graph()->start();
+      // TODO(mstarzinger): Once the effect-control-linearizer provides a frame
+      // state we can get rid of this checkpoint again. The reducer won't care.
+      Node* checkpoint = graph()->NewNode(common()->Checkpoint(),
+                                          EmptyFrameState(), effect, control);
       VectorSlotPair feedback;
       const Operator* op = javascript()->StoreProperty(language_mode, feedback);
       Node* node = graph()->NewNode(op, base, key, value, vector, context,
-                                    EmptyFrameState(), EmptyFrameState(),
-                                    effect, control);
+                                    EmptyFrameState(), checkpoint, control);
       Reduction r = Reduce(node);
 
       Matcher<Node*> offset_matcher =
@@ -747,7 +742,7 @@
               : IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size)));
 
       Matcher<Node*> value_matcher =
-          IsToNumber(value, context, effect, control);
+          IsToNumber(value, context, checkpoint, control);
       Matcher<Node*> effect_matcher = value_matcher;
 
       ASSERT_TRUE(r.Changed());
@@ -787,8 +782,7 @@
       VectorSlotPair feedback;
       const Operator* op = javascript()->StoreProperty(language_mode, feedback);
       Node* node = graph()->NewNode(op, base, key, value, vector, context,
-                                    EmptyFrameState(), EmptyFrameState(),
-                                    effect, control);
+                                    EmptyFrameState(), effect, control);
       Reduction r = Reduce(node);
 
       ASSERT_TRUE(r.Changed());
@@ -814,33 +808,15 @@
   Node* const context = UndefinedConstant();
   Node* const effect = graph()->start();
   Node* const control = graph()->start();
-  Reduction const r = Reduce(graph()->NewNode(
-      javascript()->LoadNamed(name, feedback), receiver, vector, context,
-      EmptyFrameState(), EmptyFrameState(), effect, control));
+  Reduction const r = Reduce(
+      graph()->NewNode(javascript()->LoadNamed(name, feedback), receiver,
+                       vector, context, EmptyFrameState(), effect, control));
   ASSERT_TRUE(r.Changed());
   EXPECT_THAT(r.replacement(), IsLoadField(AccessBuilder::ForStringLength(),
                                            receiver, effect, control));
 }
 
 
-TEST_F(JSTypedLoweringTest, JSLoadNamedFunctionPrototype) {
-  VectorSlotPair feedback;
-  Handle<Name> name = factory()->prototype_string();
-  Handle<JSFunction> function = isolate()->object_function();
-  Handle<JSObject> function_prototype(JSObject::cast(function->prototype()));
-  Node* const receiver = Parameter(Type::Constant(function, zone()), 0);
-  Node* const vector = Parameter(Type::Internal(), 1);
-  Node* const context = Parameter(Type::Internal(), 2);
-  Node* const effect = graph()->start();
-  Node* const control = graph()->start();
-  Reduction const r = Reduce(graph()->NewNode(
-      javascript()->LoadNamed(name, feedback), receiver, vector, context,
-      EmptyFrameState(), EmptyFrameState(), effect, control));
-  ASSERT_TRUE(r.Changed());
-  EXPECT_THAT(r.replacement(), IsHeapConstant(function_prototype));
-}
-
-
 // -----------------------------------------------------------------------------
 // JSAdd
 
@@ -865,6 +841,52 @@
                        lhs, rhs, context, frame_state0, effect, control));
 }
 
+TEST_F(JSTypedLoweringTest, JSAddSmis) {
+  BinaryOperationHints const hints(BinaryOperationHints::kSignedSmall,
+                                   BinaryOperationHints::kSignedSmall,
+                                   BinaryOperationHints::kSignedSmall);
+  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
+    Node* lhs = Parameter(Type::Number(), 0);
+    Node* rhs = Parameter(Type::Number(), 1);
+    Node* context = Parameter(Type::Any(), 2);
+    Node* frame_state0 = EmptyFrameState();
+    Node* frame_state1 = EmptyFrameState();
+    Node* effect = graph()->start();
+    Node* control = graph()->start();
+    Reduction r =
+        Reduce(graph()->NewNode(javascript()->Add(hints), lhs, rhs, context,
+                                frame_state0, frame_state1, effect, control));
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(),
+                IsSpeculativeNumberAdd(BinaryOperationHints::kSignedSmall, lhs,
+                                       rhs, effect, control));
+  }
+}
+
+// -----------------------------------------------------------------------------
+// JSSubtract
+
+TEST_F(JSTypedLoweringTest, JSSubtractSmis) {
+  BinaryOperationHints const hints(BinaryOperationHints::kSignedSmall,
+                                   BinaryOperationHints::kSignedSmall,
+                                   BinaryOperationHints::kSignedSmall);
+  TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) {
+    Node* lhs = Parameter(Type::Number(), 0);
+    Node* rhs = Parameter(Type::Number(), 1);
+    Node* context = Parameter(Type::Any(), 2);
+    Node* frame_state0 = EmptyFrameState();
+    Node* frame_state1 = EmptyFrameState();
+    Node* effect = graph()->start();
+    Node* control = graph()->start();
+    Reduction r = Reduce(graph()->NewNode(javascript()->Subtract(hints), lhs,
+                                          rhs, context, frame_state0,
+                                          frame_state1, effect, control));
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(),
+                IsSpeculativeNumberSubtract(BinaryOperationHints::kSignedSmall,
+                                            lhs, rhs, effect, control));
+  }
+}
 
 // -----------------------------------------------------------------------------
 // JSInstanceOf
diff --git a/test/unittests/compiler/load-elimination-unittest.cc b/test/unittests/compiler/load-elimination-unittest.cc
index 38bb151..721d6df 100644
--- a/test/unittests/compiler/load-elimination-unittest.cc
+++ b/test/unittests/compiler/load-elimination-unittest.cc
@@ -14,23 +14,20 @@
 
 class LoadEliminationTest : public TypedGraphTest {
  public:
-  LoadEliminationTest()
-      : TypedGraphTest(3), common_(zone()), simplified_(zone()) {}
+  LoadEliminationTest() : TypedGraphTest(3), simplified_(zone()) {}
   ~LoadEliminationTest() override {}
 
  protected:
   Reduction Reduce(Node* node) {
     // TODO(titzer): mock the GraphReducer here for better unit testing.
     GraphReducer graph_reducer(zone(), graph());
-    LoadElimination reducer(&graph_reducer, graph(), common());
+    LoadElimination reducer(&graph_reducer, graph(), simplified());
     return reducer.Reduce(node);
   }
 
   SimplifiedOperatorBuilder* simplified() { return &simplified_; }
-  CommonOperatorBuilder* common() { return &common_; }
 
  private:
-  CommonOperatorBuilder common_;
   SimplifiedOperatorBuilder simplified_;
 };
 
diff --git a/test/unittests/compiler/machine-operator-reducer-unittest.cc b/test/unittests/compiler/machine-operator-reducer-unittest.cc
index 2feba2e..05156ed 100644
--- a/test/unittests/compiler/machine-operator-reducer-unittest.cc
+++ b/test/unittests/compiler/machine-operator-reducer-unittest.cc
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "src/compiler/machine-operator-reducer.h"
 #include "src/base/bits.h"
 #include "src/base/division-by-constant.h"
+#include "src/base/ieee754.h"
 #include "src/compiler/js-graph.h"
-#include "src/compiler/machine-operator-reducer.h"
 #include "src/compiler/typer.h"
 #include "src/conversions-inl.h"
 #include "test/unittests/compiler/graph-unittest.h"
@@ -16,6 +17,7 @@
 using testing::BitEq;
 using testing::Capture;
 using testing::CaptureEq;
+using testing::NanSensitiveDoubleEq;
 
 namespace v8 {
 namespace internal {
@@ -236,10 +238,6 @@
     0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff};
 
 
-const TruncationMode kTruncationModes[] = {TruncationMode::kJavaScript,
-                                           TruncationMode::kRoundToZero};
-
-
 struct ComparisonBinaryOperator {
   const Operator* (MachineOperatorBuilder::*constructor)();
   const char* constructor_name;
@@ -413,51 +411,28 @@
 
 
 // -----------------------------------------------------------------------------
-// TruncateFloat64ToInt32
-
+// TruncateFloat64ToWord32
 
 TEST_F(MachineOperatorReducerTest,
-       TruncateFloat64ToInt32WithChangeInt32ToFloat64) {
-  TRACED_FOREACH(TruncationMode, mode, kTruncationModes) {
-    Node* value = Parameter(0);
-    Reduction reduction = Reduce(graph()->NewNode(
-        machine()->TruncateFloat64ToInt32(mode),
-        graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
-    ASSERT_TRUE(reduction.Changed());
-    EXPECT_EQ(value, reduction.replacement());
-  }
+       TruncateFloat64ToWord32WithChangeInt32ToFloat64) {
+  Node* value = Parameter(0);
+  Reduction reduction = Reduce(graph()->NewNode(
+      machine()->TruncateFloat64ToWord32(),
+      graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
+  ASSERT_TRUE(reduction.Changed());
+  EXPECT_EQ(value, reduction.replacement());
 }
 
-
-TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithConstant) {
+TEST_F(MachineOperatorReducerTest, TruncateFloat64ToWord32WithConstant) {
   TRACED_FOREACH(double, x, kFloat64Values) {
     Reduction reduction = Reduce(graph()->NewNode(
-        machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript),
-        Float64Constant(x)));
+        machine()->TruncateFloat64ToWord32(), Float64Constant(x)));
     ASSERT_TRUE(reduction.Changed());
     EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(x)));
   }
 }
 
 
-TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithPhi) {
-  Node* const p0 = Parameter(0);
-  Node* const p1 = Parameter(1);
-  Node* const merge = graph()->start();
-  TRACED_FOREACH(TruncationMode, mode, kTruncationModes) {
-    Reduction reduction = Reduce(graph()->NewNode(
-        machine()->TruncateFloat64ToInt32(mode),
-        graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), p0,
-                         p1, merge)));
-    ASSERT_TRUE(reduction.Changed());
-    EXPECT_THAT(
-        reduction.replacement(),
-        IsPhi(MachineRepresentation::kWord32, IsTruncateFloat64ToInt32(p0),
-              IsTruncateFloat64ToInt32(p1), merge));
-  }
-}
-
-
 // -----------------------------------------------------------------------------
 // TruncateInt64ToInt32
 
@@ -485,8 +460,30 @@
 
 
 // -----------------------------------------------------------------------------
-// Word32And
+// RoundFloat64ToInt32
 
+TEST_F(MachineOperatorReducerTest,
+       RoundFloat64ToInt32WithChangeInt32ToFloat64) {
+  Node* value = Parameter(0);
+  Reduction reduction = Reduce(graph()->NewNode(
+      machine()->RoundFloat64ToInt32(),
+      graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
+  ASSERT_TRUE(reduction.Changed());
+  EXPECT_EQ(value, reduction.replacement());
+}
+
+TEST_F(MachineOperatorReducerTest, RoundFloat64ToInt32WithConstant) {
+  TRACED_FOREACH(double, x, kFloat64Values) {
+    Reduction reduction = Reduce(
+        graph()->NewNode(machine()->RoundFloat64ToInt32(), Float64Constant(x)));
+    ASSERT_TRUE(reduction.Changed());
+    EXPECT_THAT(reduction.replacement(),
+                IsInt32Constant(static_cast<int32_t>(x)));
+  }
+}
+
+// -----------------------------------------------------------------------------
+// Word32And
 
 TEST_F(MachineOperatorReducerTest, Word32AndWithWord32ShlWithConstant) {
   Node* const p0 = Parameter(0);
@@ -853,8 +850,24 @@
 
 
 // -----------------------------------------------------------------------------
-// Word32Shl
+// Word32Shr
 
+TEST_F(MachineOperatorReducerTest, Word32ShrWithWord32And) {
+  Node* const p0 = Parameter(0);
+  TRACED_FORRANGE(int32_t, shift, 1, 31) {
+    uint32_t mask = (1 << shift) - 1;
+    Node* node = graph()->NewNode(
+        machine()->Word32Shr(),
+        graph()->NewNode(machine()->Word32And(), p0, Int32Constant(mask)),
+        Int32Constant(shift));
+    Reduction r = Reduce(node);
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(), IsInt32Constant(0));
+  }
+}
+
+// -----------------------------------------------------------------------------
+// Word32Shl
 
 TEST_F(MachineOperatorReducerTest, Word32ShlWithZeroShift) {
   Node* p0 = Parameter(0);
@@ -1271,28 +1284,31 @@
 
 
 TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithZero) {
+  Node* control = graph()->start();
   Node* p0 = Parameter(0);
   {
     Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
-                                 Int32Constant(0), p0);
+                                 Int32Constant(0), p0, control);
 
-    Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
+    Reduction r =
+        Reduce(graph()->NewNode(common()->Projection(1), add, control));
     ASSERT_TRUE(r.Changed());
     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
 
-    r = Reduce(graph()->NewNode(common()->Projection(0), add));
+    r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
     ASSERT_TRUE(r.Changed());
     EXPECT_EQ(p0, r.replacement());
   }
   {
     Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), p0,
-                                 Int32Constant(0));
+                                 Int32Constant(0), control);
 
-    Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
+    Reduction r =
+        Reduce(graph()->NewNode(common()->Projection(1), add, control));
     ASSERT_TRUE(r.Changed());
     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
 
-    r = Reduce(graph()->NewNode(common()->Projection(0), add));
+    r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
     ASSERT_TRUE(r.Changed());
     EXPECT_EQ(p0, r.replacement());
   }
@@ -1300,18 +1316,20 @@
 
 
 TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithConstant) {
+  Node* control = graph()->start();
   TRACED_FOREACH(int32_t, x, kInt32Values) {
     TRACED_FOREACH(int32_t, y, kInt32Values) {
       int32_t z;
       Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
-                                   Int32Constant(x), Int32Constant(y));
+                                   Int32Constant(x), Int32Constant(y), control);
 
-      Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
+      Reduction r =
+          Reduce(graph()->NewNode(common()->Projection(1), add, control));
       ASSERT_TRUE(r.Changed());
       EXPECT_THAT(r.replacement(),
                   IsInt32Constant(base::bits::SignedAddOverflow32(x, y, &z)));
 
-      r = Reduce(graph()->NewNode(common()->Projection(0), add));
+      r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
       ASSERT_TRUE(r.Changed());
       EXPECT_THAT(r.replacement(), IsInt32Constant(z));
     }
@@ -1324,33 +1342,36 @@
 
 
 TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithZero) {
+  Node* control = graph()->start();
   Node* p0 = Parameter(0);
-  Node* add =
-      graph()->NewNode(machine()->Int32SubWithOverflow(), p0, Int32Constant(0));
+  Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(), p0,
+                               Int32Constant(0), control);
 
-  Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
+  Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add, control));
   ASSERT_TRUE(r.Changed());
   EXPECT_THAT(r.replacement(), IsInt32Constant(0));
 
-  r = Reduce(graph()->NewNode(common()->Projection(0), add));
+  r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
   ASSERT_TRUE(r.Changed());
   EXPECT_EQ(p0, r.replacement());
 }
 
 
 TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithConstant) {
+  Node* control = graph()->start();
   TRACED_FOREACH(int32_t, x, kInt32Values) {
     TRACED_FOREACH(int32_t, y, kInt32Values) {
       int32_t z;
       Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(),
-                                   Int32Constant(x), Int32Constant(y));
+                                   Int32Constant(x), Int32Constant(y), control);
 
-      Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
+      Reduction r =
+          Reduce(graph()->NewNode(common()->Projection(1), add, control));
       ASSERT_TRUE(r.Changed());
       EXPECT_THAT(r.replacement(),
                   IsInt32Constant(base::bits::SignedSubOverflow32(x, y, &z)));
 
-      r = Reduce(graph()->NewNode(common()->Projection(0), add));
+      r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
       ASSERT_TRUE(r.Changed());
       EXPECT_THAT(r.replacement(), IsInt32Constant(z));
     }
@@ -1404,8 +1425,133 @@
 
 
 // -----------------------------------------------------------------------------
-// Float64InsertLowWord32
+// Float64Atan
 
+TEST_F(MachineOperatorReducerTest, Float64AtanWithConstant) {
+  TRACED_FOREACH(double, x, kFloat64Values) {
+    Reduction const r =
+        Reduce(graph()->NewNode(machine()->Float64Atan(), Float64Constant(x)));
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(
+        r.replacement(),
+        IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::atan(x))));
+  }
+}
+
+// -----------------------------------------------------------------------------
+// Float64Atan2
+
+TEST_F(MachineOperatorReducerTest, Float64Atan2WithConstant) {
+  TRACED_FOREACH(double, y, kFloat64Values) {
+    TRACED_FOREACH(double, x, kFloat64Values) {
+      Reduction const r = Reduce(graph()->NewNode(
+          machine()->Float64Atan2(), Float64Constant(y), Float64Constant(x)));
+      ASSERT_TRUE(r.Changed());
+      EXPECT_THAT(
+          r.replacement(),
+          IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::atan2(y, x))));
+    }
+  }
+}
+
+TEST_F(MachineOperatorReducerTest, Float64Atan2WithNaN) {
+  Node* const p0 = Parameter(0);
+  Node* const nan = Float64Constant(std::numeric_limits<double>::quiet_NaN());
+  {
+    Reduction const r =
+        Reduce(graph()->NewNode(machine()->Float64Atan2(), p0, nan));
+    ASSERT_TRUE(r.Changed());
+    EXPECT_EQ(nan, r.replacement());
+  }
+  {
+    Reduction const r =
+        Reduce(graph()->NewNode(machine()->Float64Atan2(), nan, p0));
+    ASSERT_TRUE(r.Changed());
+    EXPECT_EQ(nan, r.replacement());
+  }
+}
+
+// -----------------------------------------------------------------------------
+// Float64Cos
+
+TEST_F(MachineOperatorReducerTest, Float64CosWithConstant) {
+  TRACED_FOREACH(double, x, kFloat64Values) {
+    Reduction const r =
+        Reduce(graph()->NewNode(machine()->Float64Cos(), Float64Constant(x)));
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(),
+                IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::cos(x))));
+  }
+}
+
+// -----------------------------------------------------------------------------
+// Float64Exp
+
+TEST_F(MachineOperatorReducerTest, Float64ExpWithConstant) {
+  TRACED_FOREACH(double, x, kFloat64Values) {
+    Reduction const r =
+        Reduce(graph()->NewNode(machine()->Float64Exp(), Float64Constant(x)));
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(),
+                IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::exp(x))));
+  }
+}
+
+// -----------------------------------------------------------------------------
+// Float64Log
+
+TEST_F(MachineOperatorReducerTest, Float64LogWithConstant) {
+  TRACED_FOREACH(double, x, kFloat64Values) {
+    Reduction const r =
+        Reduce(graph()->NewNode(machine()->Float64Log(), Float64Constant(x)));
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(),
+                IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::log(x))));
+  }
+}
+
+// -----------------------------------------------------------------------------
+// Float64Log1p
+
+TEST_F(MachineOperatorReducerTest, Float64Log1pWithConstant) {
+  TRACED_FOREACH(double, x, kFloat64Values) {
+    Reduction const r =
+        Reduce(graph()->NewNode(machine()->Float64Log1p(), Float64Constant(x)));
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(
+        r.replacement(),
+        IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::log1p(x))));
+  }
+}
+
+// -----------------------------------------------------------------------------
+// Float64Sin
+
+TEST_F(MachineOperatorReducerTest, Float64SinWithConstant) {
+  TRACED_FOREACH(double, x, kFloat64Values) {
+    Reduction const r =
+        Reduce(graph()->NewNode(machine()->Float64Sin(), Float64Constant(x)));
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(),
+                IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::sin(x))));
+  }
+}
+
+// -----------------------------------------------------------------------------
+// Float64Tan
+
+TEST_F(MachineOperatorReducerTest, Float64TanWithConstant) {
+  TRACED_FOREACH(double, x, kFloat64Values) {
+    Reduction const r =
+        Reduce(graph()->NewNode(machine()->Float64Tan(), Float64Constant(x)));
+    ASSERT_TRUE(r.Changed());
+    EXPECT_THAT(r.replacement(),
+                IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::tan(x))));
+  }
+}
+
+// -----------------------------------------------------------------------------
+// Float64InsertLowWord32
 
 TEST_F(MachineOperatorReducerTest, Float64InsertLowWord32WithConstant) {
   TRACED_FOREACH(double, x, kFloat64Values) {
diff --git a/test/unittests/compiler/machine-operator-unittest.cc b/test/unittests/compiler/machine-operator-unittest.cc
index 59eb484..4367705 100644
--- a/test/unittests/compiler/machine-operator-unittest.cc
+++ b/test/unittests/compiler/machine-operator-unittest.cc
@@ -208,9 +208,7 @@
     PURE(Word64Ror, 2, 0, 1),                 // --
     PURE(Word64Equal, 2, 0, 1),               // --
     PURE(Int32Add, 2, 0, 1),                  // --
-    PURE(Int32AddWithOverflow, 2, 0, 2),      // --
     PURE(Int32Sub, 2, 0, 1),                  // --
-    PURE(Int32SubWithOverflow, 2, 0, 2),      // --
     PURE(Int32Mul, 2, 0, 1),                  // --
     PURE(Int32MulHigh, 2, 0, 1),              // --
     PURE(Int32Div, 2, 1, 1),                  // --
@@ -327,6 +325,8 @@
     OPTIONAL_ENTRY(Float64RoundDown, 1, 0, 1),      // --
     OPTIONAL_ENTRY(Float64RoundTruncate, 1, 0, 1),  // --
     OPTIONAL_ENTRY(Float64RoundTiesAway, 1, 0, 1),  // --
+    OPTIONAL_ENTRY(Float32Neg, 1, 0, 1),            // --
+    OPTIONAL_ENTRY(Float64Neg, 1, 0, 1),            // --
 #undef OPTIONAL_ENTRY
 };
 }  // namespace
diff --git a/test/unittests/compiler/move-optimizer-unittest.cc b/test/unittests/compiler/move-optimizer-unittest.cc
index 5ccd0c6..4c69384 100644
--- a/test/unittests/compiler/move-optimizer-unittest.cc
+++ b/test/unittests/compiler/move-optimizer-unittest.cc
@@ -106,11 +106,9 @@
 
 TEST_F(MoveOptimizerTest, RemovesRedundantExplicit) {
   int first_reg_index =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableGeneralCode(0);
+      RegisterConfiguration::Turbofan()->GetAllocatableGeneralCode(0);
   int second_reg_index =
-      RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
-          ->GetAllocatableGeneralCode(1);
+      RegisterConfiguration::Turbofan()->GetAllocatableGeneralCode(1);
 
   StartBlock();
   auto first_instr = EmitNop();
diff --git a/test/unittests/compiler/node-test-utils.cc b/test/unittests/compiler/node-test-utils.cc
index 6e5d39f..e700080 100644
--- a/test/unittests/compiler/node-test-utils.cc
+++ b/test/unittests/compiler/node-test-utils.cc
@@ -612,49 +612,6 @@
 };
 
 
-class IsEffectSetMatcher final : public NodeMatcher {
- public:
-  IsEffectSetMatcher(const Matcher<Node*>& effect0_matcher,
-                     const Matcher<Node*>& effect1_matcher)
-      : NodeMatcher(IrOpcode::kEffectSet),
-        effect0_matcher_(effect0_matcher),
-        effect1_matcher_(effect1_matcher) {}
-
-  void DescribeTo(std::ostream* os) const final {
-    NodeMatcher::DescribeTo(os);
-    *os << "), effect0 (";
-    effect0_matcher_.DescribeTo(os);
-    *os << ") and effect1 (";
-    effect1_matcher_.DescribeTo(os);
-    *os << ")";
-  }
-
-  bool MatchAndExplain(Node* node, MatchResultListener* listener) const final {
-    if (!NodeMatcher::MatchAndExplain(node, listener)) return false;
-
-    Node* effect0 = NodeProperties::GetEffectInput(node, 0);
-    Node* effect1 = NodeProperties::GetEffectInput(node, 1);
-
-    {
-      // Try matching in the reverse order first.
-      StringMatchResultListener value_listener;
-      if (effect0_matcher_.MatchAndExplain(effect1, &value_listener) &&
-          effect1_matcher_.MatchAndExplain(effect0, &value_listener)) {
-        return true;
-      }
-    }
-
-    return PrintMatchAndExplain(effect0, "effect0", effect0_matcher_,
-                                listener) &&
-           PrintMatchAndExplain(effect1, "effect1", effect1_matcher_, listener);
-  }
-
- private:
-  const Matcher<Node*> effect0_matcher_;
-  const Matcher<Node*> effect1_matcher_;
-};
-
-
 class IsProjectionMatcher final : public NodeMatcher {
  public:
   IsProjectionMatcher(const Matcher<size_t>& index_matcher,
@@ -843,6 +800,40 @@
   const Matcher<Node*> rhs_matcher_;
 };
 
+class IsSpeculativeBinopMatcher final : public NodeMatcher {
+ public:
+  IsSpeculativeBinopMatcher(
+      IrOpcode::Value opcode,
+      const Matcher<BinaryOperationHints::Hint>& hint_matcher,
+      const Matcher<Node*>& lhs_matcher, const Matcher<Node*>& rhs_matcher,
+      const Matcher<Node*>& effect_matcher,
+      const Matcher<Node*>& control_matcher)
+      : NodeMatcher(opcode),
+        lhs_matcher_(lhs_matcher),
+        rhs_matcher_(rhs_matcher),
+        effect_matcher_(effect_matcher),
+        control_matcher_(control_matcher) {}
+
+  bool MatchAndExplain(Node* node, MatchResultListener* listener) const final {
+    return (NodeMatcher::MatchAndExplain(node, listener) &&
+            // TODO(bmeurer): The type parameter is currently ignored.
+            PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "lhs",
+                                 lhs_matcher_, listener) &&
+            PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), "rhs",
+                                 rhs_matcher_, listener) &&
+            PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
+                                 effect_matcher_, listener) &&
+            PrintMatchAndExplain(NodeProperties::GetControlInput(node),
+                                 "control", control_matcher_, listener));
+  }
+
+ private:
+  const Matcher<Type*> type_matcher_;
+  const Matcher<Node*> lhs_matcher_;
+  const Matcher<Node*> rhs_matcher_;
+  const Matcher<Node*> effect_matcher_;
+  const Matcher<Node*> control_matcher_;
+};
 
 class IsAllocateMatcher final : public NodeMatcher {
  public:
@@ -1352,12 +1343,12 @@
   const Matcher<MachineRepresentation> rep_matcher_;
 };
 
-class IsGuardMatcher final : public NodeMatcher {
+class IsTypeGuardMatcher final : public NodeMatcher {
  public:
-  IsGuardMatcher(const Matcher<Type*>& type_matcher,
-                 const Matcher<Node*>& value_matcher,
-                 const Matcher<Node*>& control_matcher)
-      : NodeMatcher(IrOpcode::kGuard),
+  IsTypeGuardMatcher(const Matcher<Type*>& type_matcher,
+                     const Matcher<Node*>& value_matcher,
+                     const Matcher<Node*>& control_matcher)
+      : NodeMatcher(IrOpcode::kTypeGuard),
         type_matcher_(type_matcher),
         value_matcher_(value_matcher),
         control_matcher_(control_matcher) {}
@@ -1818,12 +1809,6 @@
 }
 
 
-Matcher<Node*> IsEffectSet(const Matcher<Node*>& effect0_matcher,
-                           const Matcher<Node*>& effect1_matcher) {
-  return MakeMatcher(new IsEffectSetMatcher(effect0_matcher, effect1_matcher));
-}
-
-
 Matcher<Node*> IsProjection(const Matcher<size_t>& index_matcher,
                             const Matcher<Node*>& base_matcher) {
   return MakeMatcher(new IsProjectionMatcher(index_matcher, base_matcher));
@@ -2064,11 +2049,11 @@
                                            effect_matcher, control_matcher));
 }
 
-Matcher<Node*> IsGuard(const Matcher<Type*>& type_matcher,
-                       const Matcher<Node*>& value_matcher,
-                       const Matcher<Node*>& control_matcher) {
+Matcher<Node*> IsTypeGuard(const Matcher<Type*>& type_matcher,
+                           const Matcher<Node*>& value_matcher,
+                           const Matcher<Node*>& control_matcher) {
   return MakeMatcher(
-      new IsGuardMatcher(type_matcher, value_matcher, control_matcher));
+      new IsTypeGuardMatcher(type_matcher, value_matcher, control_matcher));
 }
 
 Matcher<Node*> IsReferenceEqual(const Matcher<Type*>& type_matcher,
@@ -2078,6 +2063,25 @@
       new IsReferenceEqualMatcher(type_matcher, lhs_matcher, rhs_matcher));
 }
 
+Matcher<Node*> IsSpeculativeNumberAdd(
+    const Matcher<BinaryOperationHints::Hint>& hint_matcher,
+    const Matcher<Node*>& lhs_matcher, const Matcher<Node*>& rhs_matcher,
+    const Matcher<Node*>& effect_matcher,
+    const Matcher<Node*>& control_matcher) {
+  return MakeMatcher(new IsSpeculativeBinopMatcher(
+      IrOpcode::kSpeculativeNumberAdd, hint_matcher, lhs_matcher, rhs_matcher,
+      effect_matcher, control_matcher));
+}
+
+Matcher<Node*> IsSpeculativeNumberSubtract(
+    const Matcher<BinaryOperationHints::Hint>& hint_matcher,
+    const Matcher<Node*>& lhs_matcher, const Matcher<Node*>& rhs_matcher,
+    const Matcher<Node*>& effect_matcher,
+    const Matcher<Node*>& control_matcher) {
+  return MakeMatcher(new IsSpeculativeBinopMatcher(
+      IrOpcode::kSpeculativeNumberSubtract, hint_matcher, lhs_matcher,
+      rhs_matcher, effect_matcher, control_matcher));
+}
 
 Matcher<Node*> IsAllocate(const Matcher<Node*>& size_matcher,
                           const Matcher<Node*>& effect_matcher,
@@ -2204,6 +2208,10 @@
   return MakeMatcher(new NodeMatcher(IrOpcode::kLoadFramePointer));
 }
 
+Matcher<Node*> IsLoadParentFramePointer() {
+  return MakeMatcher(new NodeMatcher(IrOpcode::kLoadParentFramePointer));
+}
+
 #define IS_QUADOP_MATCHER(Name)                                               \
   Matcher<Node*> Is##Name(                                                    \
       const Matcher<Node*>& a_matcher, const Matcher<Node*>& b_matcher,       \
@@ -2242,6 +2250,7 @@
 IS_BINOP_MATCHER(NumberShiftRight)
 IS_BINOP_MATCHER(NumberShiftRightLogical)
 IS_BINOP_MATCHER(NumberImul)
+IS_BINOP_MATCHER(NumberAtan2)
 IS_BINOP_MATCHER(Word32And)
 IS_BINOP_MATCHER(Word32Or)
 IS_BINOP_MATCHER(Word32Xor)
@@ -2284,6 +2293,7 @@
     return MakeMatcher(new IsUnopMatcher(IrOpcode::k##Name, input_matcher)); \
   }
 IS_UNOP_MATCHER(BooleanNot)
+IS_UNOP_MATCHER(TruncateFloat64ToWord32)
 IS_UNOP_MATCHER(ChangeFloat64ToInt32)
 IS_UNOP_MATCHER(ChangeFloat64ToUint32)
 IS_UNOP_MATCHER(ChangeInt32ToFloat64)
@@ -2291,7 +2301,6 @@
 IS_UNOP_MATCHER(ChangeUint32ToFloat64)
 IS_UNOP_MATCHER(ChangeUint32ToUint64)
 IS_UNOP_MATCHER(TruncateFloat64ToFloat32)
-IS_UNOP_MATCHER(TruncateFloat64ToInt32)
 IS_UNOP_MATCHER(TruncateInt64ToInt32)
 IS_UNOP_MATCHER(Float32Abs)
 IS_UNOP_MATCHER(Float64Abs)
@@ -2301,10 +2310,32 @@
 IS_UNOP_MATCHER(Float64RoundTiesAway)
 IS_UNOP_MATCHER(Float64ExtractLowWord32)
 IS_UNOP_MATCHER(Float64ExtractHighWord32)
+IS_UNOP_MATCHER(NumberAbs)
+IS_UNOP_MATCHER(NumberAtan)
+IS_UNOP_MATCHER(NumberAtanh)
+IS_UNOP_MATCHER(NumberCeil)
+IS_UNOP_MATCHER(NumberClz32)
+IS_UNOP_MATCHER(NumberCbrt)
+IS_UNOP_MATCHER(NumberCos)
+IS_UNOP_MATCHER(NumberExp)
+IS_UNOP_MATCHER(NumberExpm1)
+IS_UNOP_MATCHER(NumberFloor)
+IS_UNOP_MATCHER(NumberFround)
+IS_UNOP_MATCHER(NumberLog)
+IS_UNOP_MATCHER(NumberLog1p)
+IS_UNOP_MATCHER(NumberLog10)
+IS_UNOP_MATCHER(NumberLog2)
+IS_UNOP_MATCHER(NumberRound)
+IS_UNOP_MATCHER(NumberSin)
+IS_UNOP_MATCHER(NumberSqrt)
+IS_UNOP_MATCHER(NumberTan)
+IS_UNOP_MATCHER(NumberTrunc)
 IS_UNOP_MATCHER(NumberToInt32)
 IS_UNOP_MATCHER(NumberToUint32)
+IS_UNOP_MATCHER(PlainPrimitiveToNumber)
 IS_UNOP_MATCHER(ObjectIsReceiver)
 IS_UNOP_MATCHER(ObjectIsSmi)
+IS_UNOP_MATCHER(StringFromCharCode)
 IS_UNOP_MATCHER(Word32Clz)
 IS_UNOP_MATCHER(Word32Ctz)
 IS_UNOP_MATCHER(Word32Popcnt)
diff --git a/test/unittests/compiler/node-test-utils.h b/test/unittests/compiler/node-test-utils.h
index dd036c9..60a0895 100644
--- a/test/unittests/compiler/node-test-utils.h
+++ b/test/unittests/compiler/node-test-utils.h
@@ -6,6 +6,7 @@
 #define V8_UNITTESTS_COMPILER_NODE_TEST_UTILS_H_
 
 #include "src/compiler/machine-operator.h"
+#include "src/compiler/type-hints.h"
 #include "src/machine-type.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
@@ -97,8 +98,6 @@
 Matcher<Node*> IsEffectPhi(const Matcher<Node*>& effect0_matcher,
                            const Matcher<Node*>& effect1_matcher,
                            const Matcher<Node*>& merge_matcher);
-Matcher<Node*> IsEffectSet(const Matcher<Node*>& effect0_matcher,
-                           const Matcher<Node*>& effect1_matcher);
 Matcher<Node*> IsProjection(const Matcher<size_t>& index_matcher,
                             const Matcher<Node*>& base_matcher);
 Matcher<Node*> IsCall(const Matcher<const CallDescriptor*>& descriptor_matcher,
@@ -201,6 +200,18 @@
                              const Matcher<Node*>& rhs_matcher);
 Matcher<Node*> IsNumberLessThan(const Matcher<Node*>& lhs_matcher,
                                 const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsNumberAdd(const Matcher<Node*>& lhs_matcher,
+                           const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsSpeculativeNumberAdd(
+    const Matcher<BinaryOperationHints::Hint>& hint_matcher,
+    const Matcher<Node*>& lhs_matcher, const Matcher<Node*>& rhs_matcher,
+    const Matcher<Node*>& effect_matcher,
+    const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsSpeculativeNumberSubtract(
+    const Matcher<BinaryOperationHints::Hint>& hint_matcher,
+    const Matcher<Node*>& lhs_matcher, const Matcher<Node*>& rhs_matcher,
+    const Matcher<Node*>& effect_matcher,
+    const Matcher<Node*>& control_matcher);
 Matcher<Node*> IsNumberSubtract(const Matcher<Node*>& lhs_matcher,
                                 const Matcher<Node*>& rhs_matcher);
 Matcher<Node*> IsNumberMultiply(const Matcher<Node*>& lhs_matcher,
@@ -213,6 +224,29 @@
                                          const Matcher<Node*>& rhs_matcher);
 Matcher<Node*> IsNumberImul(const Matcher<Node*>& lhs_matcher,
                             const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsNumberAbs(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberAtan(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberAtan2(const Matcher<Node*>& lhs_matcher,
+                             const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsNumberAtanh(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberCeil(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberClz32(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberCos(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberExp(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberExpm1(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberFloor(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberFround(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberLog(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberLog1p(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberLog2(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberLog10(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberRound(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberCbrt(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberSin(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberSqrt(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberTan(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsNumberTrunc(const Matcher<Node*>& value_matcher);
+Matcher<Node*> IsStringFromCharCode(const Matcher<Node*>& value_matcher);
 Matcher<Node*> IsAllocate(const Matcher<Node*>& size_matcher,
                           const Matcher<Node*>& effect_matcher,
                           const Matcher<Node*>& control_matcher);
@@ -315,6 +349,7 @@
                           const Matcher<Node*>& rhs_matcher);
 Matcher<Node*> IsJSAdd(const Matcher<Node*>& lhs_matcher,
                        const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsTruncateFloat64ToWord32(const Matcher<Node*>& input_matcher);
 Matcher<Node*> IsChangeFloat64ToInt32(const Matcher<Node*>& input_matcher);
 Matcher<Node*> IsChangeFloat64ToUint32(const Matcher<Node*>& input_matcher);
 Matcher<Node*> IsChangeInt32ToFloat64(const Matcher<Node*>& input_matcher);
@@ -322,7 +357,6 @@
 Matcher<Node*> IsChangeUint32ToFloat64(const Matcher<Node*>& input_matcher);
 Matcher<Node*> IsChangeUint32ToUint64(const Matcher<Node*>& input_matcher);
 Matcher<Node*> IsTruncateFloat64ToFloat32(const Matcher<Node*>& input_matcher);
-Matcher<Node*> IsTruncateFloat64ToInt32(const Matcher<Node*>& input_matcher);
 Matcher<Node*> IsTruncateInt64ToInt32(const Matcher<Node*>& input_matcher);
 Matcher<Node*> IsFloat32Max(const Matcher<Node*>& lhs_matcher,
                             const Matcher<Node*>& rhs_matcher);
@@ -362,6 +396,8 @@
 Matcher<Node*> IsNumberToUint32(const Matcher<Node*>& input_matcher);
 Matcher<Node*> IsParameter(const Matcher<int> index_matcher);
 Matcher<Node*> IsLoadFramePointer();
+Matcher<Node*> IsLoadParentFramePointer();
+Matcher<Node*> IsPlainPrimitiveToNumber(const Matcher<Node*>& input_matcher);
 
 Matcher<Node*> IsInt32PairAdd(const Matcher<Node*>& a_matcher,
                               const Matcher<Node*>& b_matcher,
@@ -388,9 +424,9 @@
                                const Matcher<Node*>& rhs_matcher);
 
 Matcher<Node*> IsStackSlot();
-Matcher<Node*> IsGuard(const Matcher<Type*>& type_matcher,
-                       const Matcher<Node*>& value_matcher,
-                       const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsTypeGuard(const Matcher<Type*>& type_matcher,
+                           const Matcher<Node*>& value_matcher,
+                           const Matcher<Node*>& control_matcher);
 
 }  // namespace compiler
 }  // namespace internal
diff --git a/test/unittests/compiler/register-allocator-unittest.cc b/test/unittests/compiler/register-allocator-unittest.cc
index c5ff90f..71a726f 100644
--- a/test/unittests/compiler/register-allocator-unittest.cc
+++ b/test/unittests/compiler/register-allocator-unittest.cc
@@ -678,8 +678,7 @@
 
   Allocate();
   // TODO(mtrofin): at the moment, the linear allocator spills var1 and var2,
-  // so only var3 is spilled in deferred blocks. Greedy avoids spilling 1&2.
-  // Expand the test once greedy is back online with this facility.
+  // so only var3 is spilled in deferred blocks.
   const int var3_reg = 2;
   const int var3_slot = 2;
 
diff --git a/test/unittests/compiler/simplified-operator-reducer-unittest.cc b/test/unittests/compiler/simplified-operator-reducer-unittest.cc
index f571898..f84b9bf 100644
--- a/test/unittests/compiler/simplified-operator-reducer-unittest.cc
+++ b/test/unittests/compiler/simplified-operator-reducer-unittest.cc
@@ -32,7 +32,8 @@
     JSOperatorBuilder javascript(zone());
     JSGraph jsgraph(isolate(), graph(), common(), &javascript, simplified(),
                     &machine);
-    SimplifiedOperatorReducer reducer(&jsgraph);
+    GraphReducer graph_reducer(zone(), graph());
+    SimplifiedOperatorReducer reducer(&graph_reducer, &jsgraph);
     return reducer.Reduce(node);
   }
 
@@ -91,26 +92,6 @@
     1866841746, 2032089723, 2147483647};
 
 
-const uint32_t kUint32Values[] = {
-    0x0,        0x5,        0x8,        0xc,        0xd,        0x26,
-    0x28,       0x29,       0x30,       0x34,       0x3e,       0x42,
-    0x50,       0x5b,       0x63,       0x71,       0x77,       0x7c,
-    0x83,       0x88,       0x96,       0x9c,       0xa3,       0xfa,
-    0x7a7,      0x165d,     0x234d,     0x3acb,     0x43a5,     0x4573,
-    0x5b4f,     0x5f14,     0x6996,     0x6c6e,     0x7289,     0x7b9a,
-    0x7bc9,     0x86bb,     0xa839,     0xaa41,     0xb03b,     0xc942,
-    0xce68,     0xcf4c,     0xd3ad,     0xdea3,     0xe90c,     0xed86,
-    0xfba5,     0x172dcc6,  0x114d8fc1, 0x182d6c9d, 0x1b1e3fad, 0x1db033bf,
-    0x1e1de755, 0x1f625c80, 0x28f6cf00, 0x2acb6a94, 0x2c20240e, 0x2f0fe54e,
-    0x31863a7c, 0x33325474, 0x3532fae3, 0x3bab82ea, 0x4c4b83a2, 0x4cd93d1e,
-    0x4f7331d4, 0x5491b09b, 0x57cc6ff9, 0x60d3b4dc, 0x653f5904, 0x690ae256,
-    0x69fe3276, 0x6bebf0ba, 0x6e2c69a3, 0x73b84ff7, 0x7b3a1924, 0x7ed032d9,
-    0x84dd734b, 0x8552ea53, 0x8680754f, 0x8e9660eb, 0x94fe2b9c, 0x972d30cf,
-    0x9b98c482, 0xb158667e, 0xb432932c, 0xb5b70989, 0xb669971a, 0xb7c359d1,
-    0xbeb15c0d, 0xc171c53d, 0xc743dd38, 0xc8e2af50, 0xc98e2df0, 0xd9d1cdf9,
-    0xdcc91049, 0xe46f396d, 0xee991950, 0xef64e521, 0xf7aeefc9, 0xffffffff};
-
-
 const double kNaNs[] = {-std::numeric_limits<double>::quiet_NaN(),
                         std::numeric_limits<double>::quiet_NaN(),
                         bit_cast<double>(V8_UINT64_C(0x7FFFFFFFFFFFFFFF)),
@@ -150,60 +131,54 @@
 
 
 // -----------------------------------------------------------------------------
-// ChangeBoolToBit
+// ChangeTaggedToBit
 
-
-TEST_F(SimplifiedOperatorReducerTest, ChangeBitToBoolWithChangeBoolToBit) {
+TEST_F(SimplifiedOperatorReducerTest, ChangeBitToTaggedWithChangeTaggedToBit) {
   Node* param0 = Parameter(0);
   Reduction reduction = Reduce(graph()->NewNode(
-      simplified()->ChangeBitToBool(),
-      graph()->NewNode(simplified()->ChangeBoolToBit(), param0)));
+      simplified()->ChangeBitToTagged(),
+      graph()->NewNode(simplified()->ChangeTaggedToBit(), param0)));
   ASSERT_TRUE(reduction.Changed());
   EXPECT_EQ(param0, reduction.replacement());
 }
 
-
-TEST_F(SimplifiedOperatorReducerTest, ChangeBitToBoolWithZeroConstant) {
+TEST_F(SimplifiedOperatorReducerTest, ChangeBitToTaggedWithZeroConstant) {
   Reduction reduction = Reduce(
-      graph()->NewNode(simplified()->ChangeBitToBool(), Int32Constant(0)));
+      graph()->NewNode(simplified()->ChangeBitToTagged(), Int32Constant(0)));
   ASSERT_TRUE(reduction.Changed());
   EXPECT_THAT(reduction.replacement(), IsFalseConstant());
 }
 
-
-TEST_F(SimplifiedOperatorReducerTest, ChangeBitToBoolWithOneConstant) {
+TEST_F(SimplifiedOperatorReducerTest, ChangeBitToTaggedWithOneConstant) {
   Reduction reduction = Reduce(
-      graph()->NewNode(simplified()->ChangeBitToBool(), Int32Constant(1)));
+      graph()->NewNode(simplified()->ChangeBitToTagged(), Int32Constant(1)));
   ASSERT_TRUE(reduction.Changed());
   EXPECT_THAT(reduction.replacement(), IsTrueConstant());
 }
 
 
 // -----------------------------------------------------------------------------
-// ChangeBoolToBit
+// ChangeTaggedToBit
 
-
-TEST_F(SimplifiedOperatorReducerTest, ChangeBoolToBitWithFalseConstant) {
+TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToBitWithFalseConstant) {
   Reduction reduction = Reduce(
-      graph()->NewNode(simplified()->ChangeBoolToBit(), FalseConstant()));
+      graph()->NewNode(simplified()->ChangeTaggedToBit(), FalseConstant()));
   ASSERT_TRUE(reduction.Changed());
   EXPECT_THAT(reduction.replacement(), IsInt32Constant(0));
 }
 
-
-TEST_F(SimplifiedOperatorReducerTest, ChangeBoolToBitWithTrueConstant) {
-  Reduction reduction =
-      Reduce(graph()->NewNode(simplified()->ChangeBoolToBit(), TrueConstant()));
+TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToBitWithTrueConstant) {
+  Reduction reduction = Reduce(
+      graph()->NewNode(simplified()->ChangeTaggedToBit(), TrueConstant()));
   ASSERT_TRUE(reduction.Changed());
   EXPECT_THAT(reduction.replacement(), IsInt32Constant(1));
 }
 
-
-TEST_F(SimplifiedOperatorReducerTest, ChangeBoolToBitWithChangeBitToBool) {
+TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToBitWithChangeBitToTagged) {
   Node* param0 = Parameter(0);
   Reduction reduction = Reduce(graph()->NewNode(
-      simplified()->ChangeBoolToBit(),
-      graph()->NewNode(simplified()->ChangeBitToBool(), param0)));
+      simplified()->ChangeTaggedToBit(),
+      graph()->NewNode(simplified()->ChangeBitToTagged(), param0)));
   ASSERT_TRUE(reduction.Changed());
   EXPECT_EQ(param0, reduction.replacement());
 }
@@ -320,26 +295,6 @@
 }
 
 
-TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToInt32WithConstant) {
-  TRACED_FOREACH(double, n, kFloat64Values) {
-    Reduction reduction = Reduce(graph()->NewNode(
-        simplified()->ChangeTaggedToInt32(), NumberConstant(n)));
-    ASSERT_TRUE(reduction.Changed());
-    EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(n)));
-  }
-}
-
-
-TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToInt32WithNaNConstant) {
-  TRACED_FOREACH(double, nan, kNaNs) {
-    Reduction reduction = Reduce(graph()->NewNode(
-        simplified()->ChangeTaggedToInt32(), NumberConstant(nan)));
-    ASSERT_TRUE(reduction.Changed());
-    EXPECT_THAT(reduction.replacement(), IsInt32Constant(0));
-  }
-}
-
-
 // -----------------------------------------------------------------------------
 // ChangeTaggedToUint32
 
@@ -366,38 +321,135 @@
 }
 
 
-TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToUint32WithConstant) {
+// -----------------------------------------------------------------------------
+// TruncateTaggedToWord32
+
+TEST_F(SimplifiedOperatorReducerTest,
+       TruncateTaggedToWord3WithChangeFloat64ToTagged) {
+  Node* param0 = Parameter(0);
+  Reduction reduction = Reduce(graph()->NewNode(
+      simplified()->TruncateTaggedToWord32(),
+      graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0)));
+  ASSERT_TRUE(reduction.Changed());
+  EXPECT_THAT(reduction.replacement(), IsTruncateFloat64ToWord32(param0));
+}
+
+TEST_F(SimplifiedOperatorReducerTest, TruncateTaggedToWord32WithConstant) {
   TRACED_FOREACH(double, n, kFloat64Values) {
     Reduction reduction = Reduce(graph()->NewNode(
-        simplified()->ChangeTaggedToUint32(), NumberConstant(n)));
+        simplified()->TruncateTaggedToWord32(), NumberConstant(n)));
     ASSERT_TRUE(reduction.Changed());
-    EXPECT_THAT(reduction.replacement(),
-                IsInt32Constant(bit_cast<int32_t>(DoubleToUint32(n))));
+    EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(n)));
   }
 }
 
-
-TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToUint32WithNaNConstant) {
-  TRACED_FOREACH(double, nan, kNaNs) {
-    Reduction reduction = Reduce(graph()->NewNode(
-        simplified()->ChangeTaggedToUint32(), NumberConstant(nan)));
-    ASSERT_TRUE(reduction.Changed());
-    EXPECT_THAT(reduction.replacement(), IsInt32Constant(0));
-  }
-}
-
-
 // -----------------------------------------------------------------------------
-// ChangeUint32ToTagged
+// CheckTaggedPointer
 
+TEST_F(SimplifiedOperatorReducerTest, CheckTaggedPointerWithChangeBitToTagged) {
+  Node* param0 = Parameter(0);
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* value = graph()->NewNode(simplified()->ChangeBitToTagged(), param0);
+  Reduction reduction = Reduce(graph()->NewNode(
+      simplified()->CheckTaggedPointer(), value, effect, control));
+  ASSERT_TRUE(reduction.Changed());
+  EXPECT_EQ(value, reduction.replacement());
+}
 
-TEST_F(SimplifiedOperatorReducerTest, ChangeUint32ToTagged) {
-  TRACED_FOREACH(uint32_t, n, kUint32Values) {
-    Reduction reduction =
-        Reduce(graph()->NewNode(simplified()->ChangeUint32ToTagged(),
-                                Int32Constant(bit_cast<int32_t>(n))));
+TEST_F(SimplifiedOperatorReducerTest, CheckTaggedPointerWithHeapConstant) {
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Handle<HeapObject> kHeapObjects[] = {
+      factory()->empty_string(), factory()->null_value(),
+      factory()->species_symbol(), factory()->undefined_value()};
+  TRACED_FOREACH(Handle<HeapObject>, object, kHeapObjects) {
+    Node* value = HeapConstant(object);
+    Reduction reduction = Reduce(graph()->NewNode(
+        simplified()->CheckTaggedPointer(), value, effect, control));
     ASSERT_TRUE(reduction.Changed());
-    EXPECT_THAT(reduction.replacement(), IsNumberConstant(BitEq(FastUI2D(n))));
+    EXPECT_EQ(value, reduction.replacement());
+  }
+}
+
+// -----------------------------------------------------------------------------
+// CheckTaggedSigned
+
+TEST_F(SimplifiedOperatorReducerTest,
+       CheckTaggedSignedWithChangeInt31ToTaggedSigned) {
+  Node* param0 = Parameter(0);
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* value =
+      graph()->NewNode(simplified()->ChangeInt31ToTaggedSigned(), param0);
+  Reduction reduction = Reduce(graph()->NewNode(
+      simplified()->CheckTaggedSigned(), value, effect, control));
+  ASSERT_TRUE(reduction.Changed());
+  EXPECT_EQ(value, reduction.replacement());
+}
+
+TEST_F(SimplifiedOperatorReducerTest, CheckTaggedSignedWithNumberConstant) {
+  Node* effect = graph()->start();
+  Node* control = graph()->start();
+  Node* value = NumberConstant(1.0);
+  Reduction reduction = Reduce(graph()->NewNode(
+      simplified()->CheckTaggedSigned(), value, effect, control));
+  ASSERT_TRUE(reduction.Changed());
+  EXPECT_EQ(value, reduction.replacement());
+}
+
+// -----------------------------------------------------------------------------
+// NumberAbs
+
+TEST_F(SimplifiedOperatorReducerTest, NumberAbsWithNumberConstant) {
+  TRACED_FOREACH(double, n, kFloat64Values) {
+    Reduction reduction =
+        Reduce(graph()->NewNode(simplified()->NumberAbs(), NumberConstant(n)));
+    ASSERT_TRUE(reduction.Changed());
+    EXPECT_THAT(reduction.replacement(), IsNumberConstant(std::fabs(n)));
+  }
+}
+
+// -----------------------------------------------------------------------------
+// ObjectIsSmi
+
+TEST_F(SimplifiedOperatorReducerTest, ObjectIsSmiWithChangeBitToTagged) {
+  Node* param0 = Parameter(0);
+  Reduction reduction = Reduce(graph()->NewNode(
+      simplified()->ObjectIsSmi(),
+      graph()->NewNode(simplified()->ChangeBitToTagged(), param0)));
+  ASSERT_TRUE(reduction.Changed());
+  EXPECT_THAT(reduction.replacement(), IsFalseConstant());
+}
+
+TEST_F(SimplifiedOperatorReducerTest,
+       ObjectIsSmiWithChangeInt31ToTaggedSigned) {
+  Node* param0 = Parameter(0);
+  Reduction reduction = Reduce(graph()->NewNode(
+      simplified()->ObjectIsSmi(),
+      graph()->NewNode(simplified()->ChangeInt31ToTaggedSigned(), param0)));
+  ASSERT_TRUE(reduction.Changed());
+  EXPECT_THAT(reduction.replacement(), IsTrueConstant());
+}
+
+TEST_F(SimplifiedOperatorReducerTest, ObjectIsSmiWithHeapConstant) {
+  Handle<HeapObject> kHeapObjects[] = {
+      factory()->empty_string(), factory()->null_value(),
+      factory()->species_symbol(), factory()->undefined_value()};
+  TRACED_FOREACH(Handle<HeapObject>, o, kHeapObjects) {
+    Reduction reduction =
+        Reduce(graph()->NewNode(simplified()->ObjectIsSmi(), HeapConstant(o)));
+    ASSERT_TRUE(reduction.Changed());
+    EXPECT_THAT(reduction.replacement(), IsFalseConstant());
+  }
+}
+
+TEST_F(SimplifiedOperatorReducerTest, ObjectIsSmiWithNumberConstant) {
+  TRACED_FOREACH(double, n, kFloat64Values) {
+    Reduction reduction = Reduce(
+        graph()->NewNode(simplified()->ObjectIsSmi(), NumberConstant(n)));
+    ASSERT_TRUE(reduction.Changed());
+    EXPECT_THAT(reduction.replacement(), IsBooleanConstant(IsSmiDouble(n)));
   }
 }
 
diff --git a/test/unittests/compiler/simplified-operator-unittest.cc b/test/unittests/compiler/simplified-operator-unittest.cc
index bd8509f..3343c8f 100644
--- a/test/unittests/compiler/simplified-operator-unittest.cc
+++ b/test/unittests/compiler/simplified-operator-unittest.cc
@@ -31,7 +31,6 @@
   return os << IrOpcode::Mnemonic(pop.opcode);
 }
 
-
 const PureOperator kPureOperators[] = {
 #define PURE(Name, properties, input_count)              \
   {                                                      \
@@ -56,15 +55,16 @@
     PURE(NumberShiftRightLogical, Operator::kNoProperties, 2),
     PURE(NumberToInt32, Operator::kNoProperties, 1),
     PURE(NumberToUint32, Operator::kNoProperties, 1),
-    PURE(PlainPrimitiveToNumber, Operator::kNoProperties, 1),
+    PURE(ChangeTaggedSignedToInt32, Operator::kNoProperties, 1),
     PURE(ChangeTaggedToInt32, Operator::kNoProperties, 1),
     PURE(ChangeTaggedToUint32, Operator::kNoProperties, 1),
     PURE(ChangeTaggedToFloat64, Operator::kNoProperties, 1),
     PURE(ChangeInt32ToTagged, Operator::kNoProperties, 1),
     PURE(ChangeUint32ToTagged, Operator::kNoProperties, 1),
     PURE(ChangeFloat64ToTagged, Operator::kNoProperties, 1),
-    PURE(ChangeBoolToBit, Operator::kNoProperties, 1),
-    PURE(ChangeBitToBool, Operator::kNoProperties, 1),
+    PURE(ChangeTaggedToBit, Operator::kNoProperties, 1),
+    PURE(ChangeBitToTagged, Operator::kNoProperties, 1),
+    PURE(TruncateTaggedToWord32, Operator::kNoProperties, 1),
     PURE(ObjectIsNumber, Operator::kNoProperties, 1),
     PURE(ObjectIsReceiver, Operator::kNoProperties, 1),
     PURE(ObjectIsSmi, Operator::kNoProperties, 1)
@@ -156,7 +156,8 @@
   const Operator* op = simplified.LoadBuffer(access);
 
   EXPECT_EQ(IrOpcode::kLoadBuffer, op->opcode());
-  EXPECT_EQ(Operator::kNoThrow | Operator::kNoWrite, op->properties());
+  EXPECT_EQ(Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite,
+            op->properties());
   EXPECT_EQ(access, BufferAccessOf(op));
 
   EXPECT_EQ(3, op->ValueInputCount());
@@ -176,7 +177,8 @@
   const Operator* op = simplified.StoreBuffer(access);
 
   EXPECT_EQ(IrOpcode::kStoreBuffer, op->opcode());
-  EXPECT_EQ(Operator::kNoRead | Operator::kNoThrow, op->properties());
+  EXPECT_EQ(Operator::kNoDeopt | Operator::kNoRead | Operator::kNoThrow,
+            op->properties());
   EXPECT_EQ(access, BufferAccessOf(op));
 
   EXPECT_EQ(4, op->ValueInputCount());
@@ -203,39 +205,46 @@
 
 const ElementAccess kElementAccesses[] = {
     {kTaggedBase, FixedArray::kHeaderSize, Type::Any(),
-     MachineType::AnyTagged()},
-    {kUntaggedBase, 0, Type::Any(), MachineType::Int8()},
-    {kUntaggedBase, 0, Type::Any(), MachineType::Int16()},
-    {kUntaggedBase, 0, Type::Any(), MachineType::Int32()},
-    {kUntaggedBase, 0, Type::Any(), MachineType::Uint8()},
-    {kUntaggedBase, 0, Type::Any(), MachineType::Uint16()},
-    {kUntaggedBase, 0, Type::Any(), MachineType::Uint32()},
-    {kUntaggedBase, 0, Type::Signed32(), MachineType::Int8()},
-    {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint8()},
-    {kUntaggedBase, 0, Type::Signed32(), MachineType::Int16()},
-    {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint16()},
-    {kUntaggedBase, 0, Type::Signed32(), MachineType::Int32()},
-    {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint32()},
+     MachineType::AnyTagged(), kFullWriteBarrier},
+    {kUntaggedBase, 0, Type::Any(), MachineType::Int8(), kNoWriteBarrier},
+    {kUntaggedBase, 0, Type::Any(), MachineType::Int16(), kNoWriteBarrier},
+    {kUntaggedBase, 0, Type::Any(), MachineType::Int32(), kNoWriteBarrier},
+    {kUntaggedBase, 0, Type::Any(), MachineType::Uint8(), kNoWriteBarrier},
+    {kUntaggedBase, 0, Type::Any(), MachineType::Uint16(), kNoWriteBarrier},
+    {kUntaggedBase, 0, Type::Any(), MachineType::Uint32(), kNoWriteBarrier},
+    {kUntaggedBase, 0, Type::Signed32(), MachineType::Int8(), kNoWriteBarrier},
+    {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint8(),
+     kNoWriteBarrier},
+    {kUntaggedBase, 0, Type::Signed32(), MachineType::Int16(), kNoWriteBarrier},
+    {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint16(),
+     kNoWriteBarrier},
+    {kUntaggedBase, 0, Type::Signed32(), MachineType::Int32(), kNoWriteBarrier},
+    {kUntaggedBase, 0, Type::Unsigned32(), MachineType::Uint32(),
+     kNoWriteBarrier},
     {kUntaggedBase, 0, Type::Number(),
-     MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone)},
+     MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone),
+     kNoWriteBarrier},
     {kUntaggedBase, 0, Type::Number(),
-     MachineType(MachineRepresentation::kFloat64, MachineSemantic::kNone)},
+     MachineType(MachineRepresentation::kFloat64, MachineSemantic::kNone),
+     kNoWriteBarrier},
     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
-     MachineType::Int8()},
+     MachineType::Int8(), kNoWriteBarrier},
     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
-     MachineType::Uint8()},
+     MachineType::Uint8(), kNoWriteBarrier},
     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
-     MachineType::Int16()},
+     MachineType::Int16(), kNoWriteBarrier},
     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
-     MachineType::Uint16()},
+     MachineType::Uint16(), kNoWriteBarrier},
     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Signed32(),
-     MachineType::Int32()},
+     MachineType::Int32(), kNoWriteBarrier},
     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Unsigned32(),
-     MachineType::Uint32()},
+     MachineType::Uint32(), kNoWriteBarrier},
     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
-     MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone)},
+     MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone),
+     kNoWriteBarrier},
     {kTaggedBase, FixedTypedArrayBase::kDataOffset, Type::Number(),
-     MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone)}};
+     MachineType(MachineRepresentation::kFloat32, MachineSemantic::kNone),
+     kNoWriteBarrier}};
 
 }  // namespace
 
@@ -251,7 +260,8 @@
   const Operator* op = simplified.LoadElement(access);
 
   EXPECT_EQ(IrOpcode::kLoadElement, op->opcode());
-  EXPECT_EQ(Operator::kNoThrow | Operator::kNoWrite, op->properties());
+  EXPECT_EQ(Operator::kNoDeopt | Operator::kNoThrow | Operator::kNoWrite,
+            op->properties());
   EXPECT_EQ(access, ElementAccessOf(op));
 
   EXPECT_EQ(2, op->ValueInputCount());
@@ -271,7 +281,8 @@
   const Operator* op = simplified.StoreElement(access);
 
   EXPECT_EQ(IrOpcode::kStoreElement, op->opcode());
-  EXPECT_EQ(Operator::kNoRead | Operator::kNoThrow, op->properties());
+  EXPECT_EQ(Operator::kNoDeopt | Operator::kNoRead | Operator::kNoThrow,
+            op->properties());
   EXPECT_EQ(access, ElementAccessOf(op));
 
   EXPECT_EQ(3, op->ValueInputCount());
diff --git a/test/unittests/compiler/typer-unittest.cc b/test/unittests/compiler/typer-unittest.cc
index 9d664a6..61e00a5 100644
--- a/test/unittests/compiler/typer-unittest.cc
+++ b/test/unittests/compiler/typer-unittest.cc
@@ -290,44 +290,51 @@
 
 
 TEST_F(TyperTest, TypeJSLessThan) {
-  TestBinaryCompareOp(javascript_.LessThan(), std::less<double>());
+  TestBinaryCompareOp(javascript_.LessThan(CompareOperationHints::Any()),
+                      std::less<double>());
 }
 
 
 TEST_F(TyperTest, TypeJSLessThanOrEqual) {
-  TestBinaryCompareOp(javascript_.LessThanOrEqual(), std::less_equal<double>());
+  TestBinaryCompareOp(javascript_.LessThanOrEqual(CompareOperationHints::Any()),
+                      std::less_equal<double>());
 }
 
 
 TEST_F(TyperTest, TypeJSGreaterThan) {
-  TestBinaryCompareOp(javascript_.GreaterThan(), std::greater<double>());
+  TestBinaryCompareOp(javascript_.GreaterThan(CompareOperationHints::Any()),
+                      std::greater<double>());
 }
 
 
 TEST_F(TyperTest, TypeJSGreaterThanOrEqual) {
-  TestBinaryCompareOp(javascript_.GreaterThanOrEqual(),
-                      std::greater_equal<double>());
+  TestBinaryCompareOp(
+      javascript_.GreaterThanOrEqual(CompareOperationHints::Any()),
+      std::greater_equal<double>());
 }
 
 
 TEST_F(TyperTest, TypeJSEqual) {
-  TestBinaryCompareOp(javascript_.Equal(), std::equal_to<double>());
+  TestBinaryCompareOp(javascript_.Equal(CompareOperationHints::Any()),
+                      std::equal_to<double>());
 }
 
 
 TEST_F(TyperTest, TypeJSNotEqual) {
-  TestBinaryCompareOp(javascript_.NotEqual(), std::not_equal_to<double>());
+  TestBinaryCompareOp(javascript_.NotEqual(CompareOperationHints::Any()),
+                      std::not_equal_to<double>());
 }
 
 
 // For numbers there's no difference between strict and non-strict equality.
 TEST_F(TyperTest, TypeJSStrictEqual) {
-  TestBinaryCompareOp(javascript_.StrictEqual(), std::equal_to<double>());
+  TestBinaryCompareOp(javascript_.StrictEqual(CompareOperationHints::Any()),
+                      std::equal_to<double>());
 }
 
 
 TEST_F(TyperTest, TypeJSStrictNotEqual) {
-  TestBinaryCompareOp(javascript_.StrictNotEqual(),
+  TestBinaryCompareOp(javascript_.StrictNotEqual(CompareOperationHints::Any()),
                       std::not_equal_to<double>());
 }
 
@@ -335,10 +342,9 @@
 //------------------------------------------------------------------------------
 // Monotonicity
 
-
-#define TEST_BINARY_MONOTONICITY(name)          \
-  TEST_F(TyperTest, Monotonicity_##name) {      \
-    TestBinaryMonotonicity(javascript_.name()); \
+#define TEST_BINARY_MONOTONICITY(name)                                      \
+  TEST_F(TyperTest, Monotonicity_##name) {                                  \
+    TestBinaryMonotonicity(javascript_.name(CompareOperationHints::Any())); \
   }
 TEST_BINARY_MONOTONICITY(Equal)
 TEST_BINARY_MONOTONICITY(NotEqual)
diff --git a/test/unittests/heap/slot-set-unittest.cc b/test/unittests/heap/slot-set-unittest.cc
index 26a26f0..cfb1f1f 100644
--- a/test/unittests/heap/slot-set-unittest.cc
+++ b/test/unittests/heap/slot-set-unittest.cc
@@ -142,23 +142,29 @@
 TEST(TypedSlotSet, Iterate) {
   TypedSlotSet set(0);
   const int kDelta = 10000001;
+  const int kHostDelta = 50001;
   int added = 0;
-  for (uint32_t i = 0; i < TypedSlotSet::kMaxOffset; i += kDelta) {
+  uint32_t j = 0;
+  for (uint32_t i = 0; i < TypedSlotSet::kMaxOffset;
+       i += kDelta, j += kHostDelta) {
     SlotType type = static_cast<SlotType>(i % NUMBER_OF_SLOT_TYPES);
-    set.Insert(type, i);
+    set.Insert(type, j, i);
     ++added;
   }
   int iterated = 0;
-  set.Iterate([&iterated, kDelta](SlotType type, Address addr) {
+  set.Iterate([&iterated, kDelta, kHostDelta](SlotType type, Address host_addr,
+                                              Address addr) {
     uint32_t i = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(addr));
+    uint32_t j = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(host_addr));
     EXPECT_EQ(i % NUMBER_OF_SLOT_TYPES, static_cast<uint32_t>(type));
     EXPECT_EQ(0, i % kDelta);
+    EXPECT_EQ(0, j % kHostDelta);
     ++iterated;
     return i % 2 == 0 ? KEEP_SLOT : REMOVE_SLOT;
   });
   EXPECT_EQ(added, iterated);
   iterated = 0;
-  set.Iterate([&iterated](SlotType type, Address addr) {
+  set.Iterate([&iterated](SlotType type, Address host_addr, Address addr) {
     uint32_t i = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(addr));
     EXPECT_EQ(0, i % 2);
     ++iterated;
diff --git a/test/unittests/interpreter/bytecode-array-builder-unittest.cc b/test/unittests/interpreter/bytecode-array-builder-unittest.cc
index 255d836..7bbef45 100644
--- a/test/unittests/interpreter/bytecode-array-builder-unittest.cc
+++ b/test/unittests/interpreter/bytecode-array-builder-unittest.cc
@@ -6,6 +6,7 @@
 
 #include "src/interpreter/bytecode-array-builder.h"
 #include "src/interpreter/bytecode-array-iterator.h"
+#include "src/interpreter/bytecode-label.h"
 #include "src/interpreter/bytecode-register-allocator.h"
 #include "test/unittests/test-utils.h"
 
@@ -22,11 +23,16 @@
 
 TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
   BytecodeArrayBuilder builder(isolate(), zone(), 0, 1, 131);
+  Factory* factory = isolate()->factory();
 
   CHECK_EQ(builder.locals_count(), 131);
   CHECK_EQ(builder.context_count(), 1);
   CHECK_EQ(builder.fixed_register_count(), 132);
 
+  Register reg(0);
+  Register other(reg.index() + 1);
+  Register wide(128);
+
   // Emit argument creation operations.
   builder.CreateArguments(CreateArgumentsType::kMappedArguments)
       .CreateArguments(CreateArgumentsType::kUnmappedArguments)
@@ -34,31 +40,39 @@
 
   // Emit constant loads.
   builder.LoadLiteral(Smi::FromInt(0))
+      .StoreAccumulatorInRegister(reg)
       .LoadLiteral(Smi::FromInt(8))
+      .StoreAccumulatorInRegister(reg)
       .LoadLiteral(Smi::FromInt(10000000))
+      .StoreAccumulatorInRegister(reg)
+      .LoadLiteral(factory->NewStringFromStaticChars("A constant"))
+      .StoreAccumulatorInRegister(reg)
       .LoadUndefined()
+      .Debugger()  // Prevent peephole optimization LdaNull, Star -> LdrNull.
       .LoadNull()
+      .StoreAccumulatorInRegister(reg)
       .LoadTheHole()
+      .StoreAccumulatorInRegister(reg)
       .LoadTrue()
-      .LoadFalse();
+      .StoreAccumulatorInRegister(reg)
+      .LoadFalse()
+      .StoreAccumulatorInRegister(wide);
 
-  Register reg(0);
-  Register other(reg.index() + 1);
-  Register wide(128);
-
-  builder.LoadAccumulatorWithRegister(reg)
-      .LoadNull()
-      .StoreAccumulatorInRegister(reg);
+  // Emit Ldar and Star taking care to foil the register optimizer.
+  builder.StackCheck(0)
+      .LoadAccumulatorWithRegister(other)
+      .BinaryOperation(Token::ADD, reg)
+      .StoreAccumulatorInRegister(reg)
+      .LoadNull();
 
   // Emit register-register transfer.
   builder.MoveRegister(reg, other);
   builder.MoveRegister(reg, wide);
 
   // Emit global load / store operations.
-  Factory* factory = isolate()->factory();
   Handle<String> name = factory->NewStringFromStaticChars("var_name");
-  builder.LoadGlobal(name, 1, TypeofMode::NOT_INSIDE_TYPEOF)
-      .LoadGlobal(name, 1, TypeofMode::INSIDE_TYPEOF)
+  builder.LoadGlobal(1, TypeofMode::NOT_INSIDE_TYPEOF)
+      .LoadGlobal(1, TypeofMode::INSIDE_TYPEOF)
       .StoreGlobal(name, 1, LanguageMode::SLOPPY)
       .StoreGlobal(name, 1, LanguageMode::STRICT);
 
@@ -126,7 +140,10 @@
   builder.CountOperation(Token::Value::ADD).CountOperation(Token::Value::SUB);
 
   // Emit unary operator invocations.
-  builder.LogicalNot().TypeOf();
+  builder
+      .LogicalNot()  // ToBooleanLogicalNot
+      .LogicalNot()  // non-ToBoolean LogicalNot
+      .TypeOf();
 
   // Emit delete
   builder.Delete(reg, LanguageMode::SLOPPY).Delete(reg, LanguageMode::STRICT);
@@ -154,26 +171,34 @@
   // Emit control flow. Return must be the last instruction.
   BytecodeLabel start;
   builder.Bind(&start);
-  // Short jumps with Imm8 operands
-  builder.Jump(&start)
-      .JumpIfNull(&start)
-      .JumpIfUndefined(&start)
-      .JumpIfNotHole(&start);
+  {
+    // Short jumps with Imm8 operands
+    BytecodeLabel after_jump;
+    builder.Jump(&start)
+        .Bind(&after_jump)
+        .JumpIfNull(&start)
+        .JumpIfUndefined(&start)
+        .JumpIfNotHole(&start);
+  }
 
   // Longer jumps with constant operands
   BytecodeLabel end[8];
-  builder.Jump(&end[0])
-      .LoadTrue()
-      .JumpIfTrue(&end[1])
-      .LoadTrue()
-      .JumpIfFalse(&end[2])
-      .LoadLiteral(Smi::FromInt(0))
-      .JumpIfTrue(&end[3])
-      .LoadLiteral(Smi::FromInt(0))
-      .JumpIfFalse(&end[4])
-      .JumpIfNull(&end[5])
-      .JumpIfUndefined(&end[6])
-      .JumpIfNotHole(&end[7]);
+  {
+    BytecodeLabel after_jump;
+    builder.Jump(&end[0])
+        .Bind(&after_jump)
+        .LoadTrue()
+        .JumpIfTrue(&end[1])
+        .LoadTrue()
+        .JumpIfFalse(&end[2])
+        .LoadLiteral(Smi::FromInt(0))
+        .JumpIfTrue(&end[3])
+        .LoadLiteral(Smi::FromInt(0))
+        .JumpIfFalse(&end[4])
+        .JumpIfNull(&end[5])
+        .JumpIfUndefined(&end[6])
+        .JumpIfNotHole(&end[7]);
+  }
 
   // Perform an operation that returns boolean value to
   // generate JumpIfTrue/False
@@ -192,30 +217,36 @@
     builder.LoadTrue();
   }
   // Longer jumps requiring Constant operand
-  builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start).JumpIfNotHole(
-      &start);
-  // Perform an operation that returns boolean value to
-  // generate JumpIfTrue/False
-  builder.CompareOperation(Token::Value::EQ, reg)
-      .JumpIfTrue(&start)
-      .CompareOperation(Token::Value::EQ, reg)
-      .JumpIfFalse(&start);
-  // Perform an operation that returns a non-boolean operation to
-  // generate JumpIfToBooleanTrue/False.
-  builder.BinaryOperation(Token::Value::ADD, reg)
-      .JumpIfTrue(&start)
-      .BinaryOperation(Token::Value::ADD, reg)
-      .JumpIfFalse(&start);
+  {
+    BytecodeLabel after_jump;
+    builder.Jump(&start)
+        .Bind(&after_jump)
+        .JumpIfNull(&start)
+        .JumpIfUndefined(&start)
+        .JumpIfNotHole(&start);
+    // Perform an operation that returns boolean value to
+    // generate JumpIfTrue/False
+    builder.CompareOperation(Token::Value::EQ, reg)
+        .JumpIfTrue(&start)
+        .CompareOperation(Token::Value::EQ, reg)
+        .JumpIfFalse(&start);
+    // Perform an operation that returns a non-boolean operation to
+    // generate JumpIfToBooleanTrue/False.
+    builder.BinaryOperation(Token::Value::ADD, reg)
+        .JumpIfTrue(&start)
+        .BinaryOperation(Token::Value::ADD, reg)
+        .JumpIfFalse(&start);
+  }
 
   // Emit stack check bytecode.
-  builder.StackCheck();
+  builder.StackCheck(0);
 
   // Emit throw and re-throw in it's own basic block so that the rest of the
   // code isn't omitted due to being dead.
   BytecodeLabel after_throw;
-  builder.Jump(&after_throw).Throw().Bind(&after_throw);
+  builder.Throw().Bind(&after_throw);
   BytecodeLabel after_rethrow;
-  builder.Jump(&after_rethrow).ReThrow().Bind(&after_rethrow);
+  builder.ReThrow().Bind(&after_rethrow);
 
   builder.ForInPrepare(reg)
       .ForInDone(reg, reg)
@@ -235,14 +266,14 @@
   Handle<String> wide_name = factory->NewStringFromStaticChars("var_wide_name");
 
   // Emit wide global load / store operations.
-  builder.LoadGlobal(name, 1024, TypeofMode::NOT_INSIDE_TYPEOF)
-      .LoadGlobal(name, 1024, TypeofMode::INSIDE_TYPEOF)
-      .LoadGlobal(name, 1024, TypeofMode::INSIDE_TYPEOF)
+  builder.LoadGlobal(1024, TypeofMode::NOT_INSIDE_TYPEOF)
+      .LoadGlobal(1024, TypeofMode::INSIDE_TYPEOF)
+      .LoadGlobal(1024, TypeofMode::INSIDE_TYPEOF)
       .StoreGlobal(name, 1024, LanguageMode::SLOPPY)
       .StoreGlobal(wide_name, 1, LanguageMode::STRICT);
 
   // Emit extra wide global load.
-  builder.LoadGlobal(name, 1024 * 1024, TypeofMode::NOT_INSIDE_TYPEOF);
+  builder.LoadGlobal(1024 * 1024, TypeofMode::NOT_INSIDE_TYPEOF);
 
   // Emit wide load / store property operations.
   builder.LoadNamedProperty(reg, wide_name, 0)
@@ -261,6 +292,19 @@
       .StoreLookupSlot(wide_name, LanguageMode::SLOPPY)
       .StoreLookupSlot(wide_name, LanguageMode::STRICT);
 
+  // Emit loads which will be transformed to Ldr equivalents by the peephole
+  // optimizer.
+  builder.LoadNamedProperty(reg, name, 0)
+      .StoreAccumulatorInRegister(reg)
+      .LoadKeyedProperty(reg, 0)
+      .StoreAccumulatorInRegister(reg)
+      .LoadContextSlot(reg, 1)
+      .StoreAccumulatorInRegister(reg)
+      .LoadGlobal(0, TypeofMode::NOT_INSIDE_TYPEOF)
+      .StoreAccumulatorInRegister(reg)
+      .LoadUndefined()
+      .StoreAccumulatorInRegister(reg);
+
   // CreateClosureWide
   Handle<SharedFunctionInfo> shared_info2 = factory->NewSharedFunctionInfo(
       factory->NewStringFromStaticChars("function_b"), MaybeHandle<Code>(),
@@ -274,14 +318,22 @@
       .CreateObjectLiteral(factory->NewFixedArray(2), 0, 0);
 
   // Longer jumps requiring ConstantWide operand
-  builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start).JumpIfNotHole(
-      &start);
+  {
+    BytecodeLabel after_jump;
+    builder.Jump(&start)
+        .Bind(&after_jump)
+        .JumpIfNull(&start)
+        .JumpIfUndefined(&start)
+        .JumpIfNotHole(&start);
+  }
+
   // Perform an operation that returns boolean value to
   // generate JumpIfTrue/False
   builder.CompareOperation(Token::Value::EQ, reg)
       .JumpIfTrue(&start)
       .CompareOperation(Token::Value::EQ, reg)
       .JumpIfFalse(&start);
+
   // Perform an operation that returns a non-boolean operation to
   // generate JumpIfToBooleanTrue/False.
   builder.BinaryOperation(Token::Value::ADD, reg)
@@ -289,6 +341,10 @@
       .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfFalse(&start);
 
+  // Emit generator operations
+  builder.SuspendGenerator(reg)
+      .ResumeGenerator(reg);
+
   // Intrinsics handled by the interpreter.
   builder.CallRuntime(Runtime::kInlineIsArray, reg, 1)
       .CallRuntime(Runtime::kInlineIsArray, wide, 1);
@@ -327,6 +383,24 @@
   // Insert entry for illegal bytecode as this is never willingly emitted.
   scorecard[Bytecodes::ToByte(Bytecode::kIllegal)] = 1;
 
+  // Insert entry for nop bytecode as this often gets optimized out.
+  scorecard[Bytecodes::ToByte(Bytecode::kNop)] = 1;
+
+  if (!FLAG_ignition_peephole) {
+    // Insert entries for bytecodes only emitted by peephole optimizer.
+    scorecard[Bytecodes::ToByte(Bytecode::kLdrNamedProperty)] = 1;
+    scorecard[Bytecodes::ToByte(Bytecode::kLdrKeyedProperty)] = 1;
+    scorecard[Bytecodes::ToByte(Bytecode::kLdrGlobal)] = 1;
+    scorecard[Bytecodes::ToByte(Bytecode::kLdrContextSlot)] = 1;
+    scorecard[Bytecodes::ToByte(Bytecode::kLdrUndefined)] = 1;
+    scorecard[Bytecodes::ToByte(Bytecode::kLogicalNot)] = 1;
+    scorecard[Bytecodes::ToByte(Bytecode::kJump)] = 1;
+    scorecard[Bytecodes::ToByte(Bytecode::kJumpIfTrue)] = 1;
+    scorecard[Bytecodes::ToByte(Bytecode::kJumpIfFalse)] = 1;
+    scorecard[Bytecodes::ToByte(Bytecode::kJumpIfTrueConstant)] = 1;
+    scorecard[Bytecodes::ToByte(Bytecode::kJumpIfFalseConstant)] = 1;
+  }
+
   // Check return occurs at the end and only once in the BytecodeArray.
   CHECK_EQ(final_bytecode, Bytecode::kReturn);
   CHECK_EQ(scorecard[Bytecodes::ToByte(final_bytecode)], 1);
@@ -348,9 +422,20 @@
         BytecodeArrayBuilder builder(isolate(), zone(), 0, contexts, locals);
         BytecodeRegisterAllocator temporaries(
             zone(), builder.temporary_register_allocator());
+        for (int i = 0; i < locals + contexts; i++) {
+          builder.LoadLiteral(Smi::FromInt(0));
+          builder.StoreAccumulatorInRegister(Register(i));
+        }
         for (int i = 0; i < temps; i++) {
+          builder.LoadLiteral(Smi::FromInt(0));
           builder.StoreAccumulatorInRegister(temporaries.NewRegister());
         }
+        if (temps > 0) {
+          // Ensure temporaries are used so not optimized away by the
+          // register optimizer.
+          builder.New(Register(locals + contexts), Register(locals + contexts),
+                      static_cast<size_t>(temps));
+        }
         builder.Return();
 
         Handle<BytecodeArray> the_array = builder.ToBytecodeArray();
@@ -364,14 +449,11 @@
 
 TEST_F(BytecodeArrayBuilderTest, RegisterValues) {
   int index = 1;
-  int32_t operand = -index;
 
   Register the_register(index);
   CHECK_EQ(the_register.index(), index);
 
   int actual_operand = the_register.ToOperand();
-  CHECK_EQ(actual_operand, operand);
-
   int actual_index = Register::FromOperand(actual_operand).index();
   CHECK_EQ(actual_index, index);
 }
@@ -379,6 +461,7 @@
 
 TEST_F(BytecodeArrayBuilderTest, Parameters) {
   BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 0);
+
   Register param0(builder.Parameter(0));
   Register param9(builder.Parameter(9));
   CHECK_EQ(param9.index() - param0.index(), 9);
@@ -410,6 +493,7 @@
 
 TEST_F(BytecodeArrayBuilderTest, Constants) {
   BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
+
   Factory* factory = isolate()->factory();
   Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(3.14);
   Handle<HeapObject> heap_num_2 = factory->NewHeapNumber(5.2);
@@ -428,16 +512,24 @@
   CHECK_EQ(array->constant_pool()->length(), 3);
 }
 
+static Bytecode PeepholeToBoolean(Bytecode jump_bytecode) {
+  return FLAG_ignition_peephole
+             ? Bytecodes::GetJumpWithoutToBoolean(jump_bytecode)
+             : jump_bytecode;
+}
 
 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
   static const int kFarJumpDistance = 256;
 
   BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1);
+
   Register reg(0);
   BytecodeLabel far0, far1, far2, far3, far4;
   BytecodeLabel near0, near1, near2, near3, near4;
+  BytecodeLabel after_jump0, after_jump1;
 
   builder.Jump(&near0)
+      .Bind(&after_jump0)
       .CompareOperation(Token::Value::EQ, reg)
       .JumpIfTrue(&near1)
       .CompareOperation(Token::Value::EQ, reg)
@@ -452,6 +544,7 @@
       .Bind(&near3)
       .Bind(&near4)
       .Jump(&far0)
+      .Bind(&after_jump1)
       .CompareOperation(Token::Value::EQ, reg)
       .JumpIfTrue(&far1)
       .CompareOperation(Token::Value::EQ, reg)
@@ -461,7 +554,7 @@
       .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfFalse(&far4);
   for (int i = 0; i < kFarJumpDistance - 18; i++) {
-    builder.LoadUndefined();
+    builder.Debugger();
   }
   builder.Bind(&far0).Bind(&far1).Bind(&far2).Bind(&far3).Bind(&far4);
   builder.Return();
@@ -477,14 +570,16 @@
   // Ignore compare operation.
   iterator.Advance();
 
-  CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue);
+  CHECK_EQ(iterator.current_bytecode(),
+           PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrue));
   CHECK_EQ(iterator.GetImmediateOperand(0), 14);
   iterator.Advance();
 
   // Ignore compare operation.
   iterator.Advance();
 
-  CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse);
+  CHECK_EQ(iterator.current_bytecode(),
+           PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalse));
   CHECK_EQ(iterator.GetImmediateOperand(0), 10);
   iterator.Advance();
 
@@ -502,7 +597,6 @@
   CHECK_EQ(iterator.GetImmediateOperand(0), 2);
   iterator.Advance();
 
-
   CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant);
   CHECK_EQ(*iterator.GetConstantForIndexOperand(0),
            Smi::FromInt(kFarJumpDistance));
@@ -511,7 +605,8 @@
   // Ignore compare operation.
   iterator.Advance();
 
-  CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant);
+  CHECK_EQ(iterator.current_bytecode(),
+           PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrueConstant));
   CHECK_EQ(*iterator.GetConstantForIndexOperand(0),
            Smi::FromInt(kFarJumpDistance - 4));
   iterator.Advance();
@@ -519,7 +614,8 @@
   // Ignore compare operation.
   iterator.Advance();
 
-  CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant);
+  CHECK_EQ(iterator.current_bytecode(),
+           PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalseConstant));
   CHECK_EQ(*iterator.GetConstantForIndexOperand(0),
            Smi::FromInt(kFarJumpDistance - 8));
   iterator.Advance();
@@ -545,6 +641,7 @@
 
 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
   BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1);
+
   Register reg(0);
 
   BytecodeLabel label0, label1, label2, label3, label4;
@@ -563,12 +660,13 @@
       .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfFalse(&label4);
   for (int i = 0; i < 63; i++) {
-    builder.Jump(&label4);
+    BytecodeLabel after_jump;
+    builder.Jump(&label4).Bind(&after_jump);
   }
 
   // Add padding to force wide backwards jumps.
   for (int i = 0; i < 256; i++) {
-    builder.LoadTrue();
+    builder.Debugger();
   }
 
   builder.BinaryOperation(Token::Value::ADD, reg).JumpIfFalse(&label4);
@@ -576,6 +674,8 @@
   builder.CompareOperation(Token::Value::EQ, reg).JumpIfFalse(&label2);
   builder.CompareOperation(Token::Value::EQ, reg).JumpIfTrue(&label1);
   builder.Jump(&label0);
+  BytecodeLabel end;
+  builder.Bind(&end);
   builder.Return();
 
   Handle<BytecodeArray> array = builder.ToBytecodeArray();
@@ -585,13 +685,15 @@
   iterator.Advance();
   // Ignore compare operation.
   iterator.Advance();
-  CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue);
+  CHECK_EQ(iterator.current_bytecode(),
+           PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrue));
   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
   CHECK_EQ(iterator.GetImmediateOperand(0), -2);
   iterator.Advance();
   // Ignore compare operation.
   iterator.Advance();
-  CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse);
+  CHECK_EQ(iterator.current_bytecode(),
+           PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalse));
   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
   CHECK_EQ(iterator.GetImmediateOperand(0), -2);
   iterator.Advance();
@@ -615,7 +717,7 @@
   }
   // Check padding to force wide backwards jumps.
   for (int i = 0; i < 256; i++) {
-    CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaTrue);
+    CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
     iterator.Advance();
   }
   // Ignore binary operation.
@@ -632,13 +734,15 @@
   iterator.Advance();
   // Ignore compare operation.
   iterator.Advance();
-  CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse);
+  CHECK_EQ(iterator.current_bytecode(),
+           PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalse));
   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble);
   CHECK_EQ(iterator.GetImmediateOperand(0), -409);
   iterator.Advance();
   // Ignore compare operation.
   iterator.Advance();
-  CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue);
+  CHECK_EQ(iterator.current_bytecode(),
+           PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrue));
   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble);
   CHECK_EQ(iterator.GetImmediateOperand(0), -419);
   iterator.Advance();
@@ -657,9 +761,15 @@
 
   // Labels can only have 1 forward reference, but
   // can be referred to mulitple times once bound.
-  BytecodeLabel label;
+  BytecodeLabel label, after_jump0, after_jump1;
 
-  builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label).Return();
+  builder.Jump(&label)
+      .Bind(&label)
+      .Jump(&label)
+      .Bind(&after_jump0)
+      .Jump(&label)
+      .Bind(&after_jump1)
+      .Return();
 
   Handle<BytecodeArray> array = builder.ToBytecodeArray();
   BytecodeArrayIterator iterator(array);
@@ -683,8 +793,13 @@
 
   BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
   for (int i = 0; i < kRepeats; i++) {
-    BytecodeLabel label;
-    builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label);
+    BytecodeLabel label, after_jump0, after_jump1;
+    builder.Jump(&label)
+        .Bind(&label)
+        .Jump(&label)
+        .Bind(&after_jump0)
+        .Jump(&label)
+        .Bind(&after_jump1);
   }
   builder.Return();
 
@@ -706,85 +821,6 @@
   CHECK(iterator.done());
 }
 
-TEST_F(BytecodeArrayBuilderTest, OperandScales) {
-  CHECK_EQ(BytecodeArrayBuilder::OperandSizesToScale(OperandSize::kByte),
-           OperandScale::kSingle);
-  CHECK_EQ(BytecodeArrayBuilder::OperandSizesToScale(OperandSize::kShort),
-           OperandScale::kDouble);
-  CHECK_EQ(BytecodeArrayBuilder::OperandSizesToScale(OperandSize::kQuad),
-           OperandScale::kQuadruple);
-  CHECK_EQ(BytecodeArrayBuilder::OperandSizesToScale(
-               OperandSize::kShort, OperandSize::kShort, OperandSize::kShort,
-               OperandSize::kShort),
-           OperandScale::kDouble);
-  CHECK_EQ(BytecodeArrayBuilder::OperandSizesToScale(
-               OperandSize::kQuad, OperandSize::kShort, OperandSize::kShort,
-               OperandSize::kShort),
-           OperandScale::kQuadruple);
-  CHECK_EQ(BytecodeArrayBuilder::OperandSizesToScale(
-               OperandSize::kShort, OperandSize::kQuad, OperandSize::kShort,
-               OperandSize::kShort),
-           OperandScale::kQuadruple);
-  CHECK_EQ(BytecodeArrayBuilder::OperandSizesToScale(
-               OperandSize::kShort, OperandSize::kShort, OperandSize::kQuad,
-               OperandSize::kShort),
-           OperandScale::kQuadruple);
-  CHECK_EQ(BytecodeArrayBuilder::OperandSizesToScale(
-               OperandSize::kShort, OperandSize::kShort, OperandSize::kShort,
-               OperandSize::kQuad),
-           OperandScale::kQuadruple);
-}
-
-TEST_F(BytecodeArrayBuilderTest, SizesForSignOperands) {
-  CHECK(BytecodeArrayBuilder::SizeForSignedOperand(0) == OperandSize::kByte);
-  CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMaxInt8) ==
-        OperandSize::kByte);
-  CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMinInt8) ==
-        OperandSize::kByte);
-  CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMaxInt8 + 1) ==
-        OperandSize::kShort);
-  CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMinInt8 - 1) ==
-        OperandSize::kShort);
-  CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMaxInt16) ==
-        OperandSize::kShort);
-  CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMinInt16) ==
-        OperandSize::kShort);
-  CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMaxInt16 + 1) ==
-        OperandSize::kQuad);
-  CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMinInt16 - 1) ==
-        OperandSize::kQuad);
-  CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMaxInt) ==
-        OperandSize::kQuad);
-  CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMinInt) ==
-        OperandSize::kQuad);
-}
-
-TEST_F(BytecodeArrayBuilderTest, SizesForUnsignOperands) {
-  // int overloads
-  CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(0) == OperandSize::kByte);
-  CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(kMaxUInt8) ==
-        OperandSize::kByte);
-  CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(kMaxUInt8 + 1) ==
-        OperandSize::kShort);
-  CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(kMaxUInt16) ==
-        OperandSize::kShort);
-  CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(kMaxUInt16 + 1) ==
-        OperandSize::kQuad);
-  // size_t overloads
-  CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(static_cast<size_t>(0)) ==
-        OperandSize::kByte);
-  CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(
-            static_cast<size_t>(kMaxUInt8)) == OperandSize::kByte);
-  CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(
-            static_cast<size_t>(kMaxUInt8 + 1)) == OperandSize::kShort);
-  CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(
-            static_cast<size_t>(kMaxUInt16)) == OperandSize::kShort);
-  CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(
-            static_cast<size_t>(kMaxUInt16 + 1)) == OperandSize::kQuad);
-  CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(
-            static_cast<size_t>(kMaxUInt32)) == OperandSize::kQuad);
-}
-
 }  // namespace interpreter
 }  // namespace internal
 }  // namespace v8
diff --git a/test/unittests/interpreter/bytecode-array-iterator-unittest.cc b/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
index 43c6caa..6b7374e 100644
--- a/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
+++ b/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
@@ -37,18 +37,26 @@
   int feedback_slot = 97;
 
   builder.LoadLiteral(heap_num_0)
+      .StoreAccumulatorInRegister(reg_0)
       .LoadLiteral(heap_num_1)
+      .StoreAccumulatorInRegister(reg_0)
       .LoadLiteral(zero)
+      .StoreAccumulatorInRegister(reg_0)
       .LoadLiteral(smi_0)
+      .StoreAccumulatorInRegister(reg_0)
       .LoadLiteral(smi_1)
+      .StoreAccumulatorInRegister(reg_1)
       .LoadAccumulatorWithRegister(reg_0)
+      .BinaryOperation(Token::Value::ADD, reg_0)
+      .StoreAccumulatorInRegister(reg_1)
       .LoadNamedProperty(reg_1, name, feedback_slot)
+      .BinaryOperation(Token::Value::ADD, reg_0)
       .StoreAccumulatorInRegister(param)
       .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, param, 1, reg_0)
       .ForInPrepare(reg_0)
       .CallRuntime(Runtime::kLoadIC_Miss, reg_0, 1)
       .Debugger()
-      .LoadGlobal(name, 0x10000000, TypeofMode::NOT_INSIDE_TYPEOF)
+      .LoadGlobal(0x10000000, TypeofMode::NOT_INSIDE_TYPEOF)
       .Return();
 
   // Test iterator sees the expected output from the builder.
@@ -64,6 +72,15 @@
   offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle);
   iterator.Advance();
 
+  CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
+  CHECK_EQ(iterator.current_offset(), offset);
+  CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
+  CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
+  CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
+  CHECK(!iterator.done());
+  offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
+  iterator.Advance();
+
   CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaConstant);
   CHECK_EQ(iterator.current_offset(), offset);
   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
@@ -72,6 +89,15 @@
   offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle);
   iterator.Advance();
 
+  CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
+  CHECK_EQ(iterator.current_offset(), offset);
+  CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
+  CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
+  CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
+  CHECK(!iterator.done());
+  offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
+  iterator.Advance();
+
   CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaZero);
   CHECK_EQ(iterator.current_offset(), offset);
   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
@@ -79,6 +105,15 @@
   offset += Bytecodes::Size(Bytecode::kLdaZero, OperandScale::kSingle);
   iterator.Advance();
 
+  CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
+  CHECK_EQ(iterator.current_offset(), offset);
+  CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
+  CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
+  CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
+  CHECK(!iterator.done());
+  offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
+  iterator.Advance();
+
   CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
   CHECK_EQ(iterator.current_offset(), offset);
   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
@@ -87,6 +122,15 @@
   offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kSingle);
   iterator.Advance();
 
+  CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
+  CHECK_EQ(iterator.current_offset(), offset);
+  CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
+  CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
+  CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
+  CHECK(!iterator.done());
+  offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
+  iterator.Advance();
+
   CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
   CHECK_EQ(iterator.current_offset(), offset);
   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kQuadruple);
@@ -96,6 +140,15 @@
             kPrefixByteSize;
   iterator.Advance();
 
+  CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
+  CHECK_EQ(iterator.current_offset(), offset);
+  CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
+  CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
+  CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
+  CHECK(!iterator.done());
+  offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
+  iterator.Advance();
+
   CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdar);
   CHECK_EQ(iterator.current_offset(), offset);
   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
@@ -104,14 +157,41 @@
   offset += Bytecodes::Size(Bytecode::kLdar, OperandScale::kSingle);
   iterator.Advance();
 
-  CHECK_EQ(iterator.current_bytecode(), Bytecode::kLoadIC);
+  CHECK_EQ(iterator.current_bytecode(), Bytecode::kAdd);
+  CHECK_EQ(iterator.current_offset(), offset);
+  CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
+  CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
+  CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
+  CHECK(!iterator.done());
+  offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
+  iterator.Advance();
+
+  CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
+  CHECK_EQ(iterator.current_offset(), offset);
+  CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
+  CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
+  CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
+  CHECK(!iterator.done());
+  offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
+  iterator.Advance();
+
+  CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaNamedProperty);
   CHECK_EQ(iterator.current_offset(), offset);
   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
   CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
   CHECK_EQ(iterator.GetIndexOperand(1), name_index);
   CHECK_EQ(iterator.GetIndexOperand(2), feedback_slot);
   CHECK(!iterator.done());
-  offset += Bytecodes::Size(Bytecode::kLoadIC, OperandScale::kSingle);
+  offset += Bytecodes::Size(Bytecode::kLdaNamedProperty, OperandScale::kSingle);
+  iterator.Advance();
+
+  CHECK_EQ(iterator.current_bytecode(), Bytecode::kAdd);
+  CHECK_EQ(iterator.current_offset(), offset);
+  CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
+  CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
+  CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
+  CHECK(!iterator.done());
+  offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
   iterator.Advance();
 
   CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
@@ -149,8 +229,7 @@
   CHECK_EQ(iterator.current_bytecode(), Bytecode::kCallRuntime);
   CHECK_EQ(iterator.current_offset(), offset);
   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
-  CHECK_EQ(static_cast<Runtime::FunctionId>(iterator.GetRuntimeIdOperand(0)),
-           Runtime::kLoadIC_Miss);
+  CHECK_EQ(iterator.GetRuntimeIdOperand(0), Runtime::kLoadIC_Miss);
   CHECK_EQ(iterator.GetRegisterOperand(1).index(), reg_0.index());
   CHECK_EQ(iterator.GetRegisterCountOperand(2), 1);
   CHECK(!iterator.done());
@@ -167,8 +246,8 @@
   CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaGlobal);
   CHECK_EQ(iterator.current_offset(), offset);
   CHECK_EQ(iterator.current_operand_scale(), OperandScale::kQuadruple);
-  CHECK_EQ(iterator.current_bytecode_size(), 10);
-  CHECK_EQ(iterator.GetIndexOperand(1), 0x10000000);
+  CHECK_EQ(iterator.current_bytecode_size(), 6);
+  CHECK_EQ(iterator.GetIndexOperand(0), 0x10000000);
   offset += Bytecodes::Size(Bytecode::kLdaGlobal, OperandScale::kQuadruple) +
             kPrefixByteSize;
   iterator.Advance();
diff --git a/test/unittests/interpreter/bytecode-array-writer-unittest.cc b/test/unittests/interpreter/bytecode-array-writer-unittest.cc
new file mode 100644
index 0000000..90a91ce
--- /dev/null
+++ b/test/unittests/interpreter/bytecode-array-writer-unittest.cc
@@ -0,0 +1,254 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "src/api.h"
+#include "src/factory.h"
+#include "src/interpreter/bytecode-array-writer.h"
+#include "src/interpreter/bytecode-label.h"
+#include "src/interpreter/constant-array-builder.h"
+#include "src/interpreter/source-position-table.h"
+#include "src/isolate.h"
+#include "src/utils.h"
+#include "test/unittests/interpreter/bytecode-utils.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+class BytecodeArrayWriterUnittest : public TestWithIsolateAndZone {
+ public:
+  BytecodeArrayWriterUnittest()
+      : constant_array_builder_(isolate(), zone()),
+        bytecode_array_writer_(isolate(), zone(), &constant_array_builder_) {}
+  ~BytecodeArrayWriterUnittest() override {}
+
+  void Write(BytecodeNode* node, const BytecodeSourceInfo& info);
+  void Write(Bytecode bytecode,
+             const BytecodeSourceInfo& info = BytecodeSourceInfo());
+  void Write(Bytecode bytecode, uint32_t operand0,
+             const BytecodeSourceInfo& info = BytecodeSourceInfo());
+  void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
+
+             const BytecodeSourceInfo& info = BytecodeSourceInfo());
+  void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
+             uint32_t operand2,
+             const BytecodeSourceInfo& info = BytecodeSourceInfo());
+  void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
+             uint32_t operand2, uint32_t operand3,
+             const BytecodeSourceInfo& info = BytecodeSourceInfo());
+
+  void WriteJump(Bytecode bytecode, BytecodeLabel* label,
+
+                 const BytecodeSourceInfo& info = BytecodeSourceInfo());
+
+  BytecodeArrayWriter* writer() { return &bytecode_array_writer_; }
+  ZoneVector<unsigned char>* bytecodes() { return writer()->bytecodes(); }
+  SourcePositionTableBuilder* source_position_table_builder() {
+    return writer()->source_position_table_builder();
+  }
+  int max_register_count() { return writer()->max_register_count(); }
+
+ private:
+  ConstantArrayBuilder constant_array_builder_;
+  BytecodeArrayWriter bytecode_array_writer_;
+};
+
+void BytecodeArrayWriterUnittest::Write(BytecodeNode* node,
+                                        const BytecodeSourceInfo& info) {
+  if (info.is_valid()) {
+    node->source_info().Clone(info);
+  }
+  writer()->Write(node);
+}
+
+void BytecodeArrayWriterUnittest::Write(Bytecode bytecode,
+                                        const BytecodeSourceInfo& info) {
+  BytecodeNode node(bytecode);
+  Write(&node, info);
+}
+
+void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
+                                        const BytecodeSourceInfo& info) {
+  BytecodeNode node(bytecode, operand0);
+  Write(&node, info);
+}
+
+void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
+                                        uint32_t operand1,
+                                        const BytecodeSourceInfo& info) {
+  BytecodeNode node(bytecode, operand0, operand1);
+  Write(&node, info);
+}
+
+void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
+                                        uint32_t operand1, uint32_t operand2,
+                                        const BytecodeSourceInfo& info) {
+  BytecodeNode node(bytecode, operand0, operand1, operand2);
+  Write(&node, info);
+}
+
+void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
+                                        uint32_t operand1, uint32_t operand2,
+                                        uint32_t operand3,
+                                        const BytecodeSourceInfo& info) {
+  BytecodeNode node(bytecode, operand0, operand1, operand2, operand3);
+  Write(&node, info);
+}
+
+void BytecodeArrayWriterUnittest::WriteJump(Bytecode bytecode,
+                                            BytecodeLabel* label,
+                                            const BytecodeSourceInfo& info) {
+  BytecodeNode node(bytecode, 0);
+  if (info.is_valid()) {
+    node.source_info().Clone(info);
+  }
+  writer()->WriteJump(&node, label);
+}
+
+TEST_F(BytecodeArrayWriterUnittest, SimpleExample) {
+  CHECK_EQ(bytecodes()->size(), 0);
+
+  Write(Bytecode::kStackCheck, {10, false});
+  CHECK_EQ(bytecodes()->size(), 1);
+  CHECK_EQ(max_register_count(), 0);
+
+  Write(Bytecode::kLdaSmi, 127, {55, true});
+  CHECK_EQ(bytecodes()->size(), 3);
+  CHECK_EQ(max_register_count(), 0);
+
+  Write(Bytecode::kLdar, Register(200).ToOperand());
+  CHECK_EQ(bytecodes()->size(), 7);
+  CHECK_EQ(max_register_count(), 201);
+
+  Write(Bytecode::kReturn, {70, true});
+  CHECK_EQ(bytecodes()->size(), 8);
+  CHECK_EQ(max_register_count(), 201);
+
+  static const uint8_t bytes[] = {B(StackCheck), B(LdaSmi), U8(127),  B(Wide),
+                                  B(Ldar),       R16(200),  B(Return)};
+  CHECK_EQ(bytecodes()->size(), arraysize(bytes));
+  for (size_t i = 0; i < arraysize(bytes); ++i) {
+    CHECK_EQ(bytecodes()->at(i), bytes[i]);
+  }
+
+  writer()->ToBytecodeArray(0, 0, factory()->empty_fixed_array());
+  CHECK_EQ(bytecodes()->size(), arraysize(bytes));
+
+  PositionTableEntry expected_positions[] = {
+      {0, 10, false}, {1, 55, true}, {7, 70, true}};
+  Handle<ByteArray> source_positions =
+      source_position_table_builder()->ToSourcePositionTable();
+  SourcePositionTableIterator source_iterator(*source_positions);
+  for (size_t i = 0; i < arraysize(expected_positions); ++i) {
+    const PositionTableEntry& expected = expected_positions[i];
+    CHECK_EQ(source_iterator.bytecode_offset(), expected.bytecode_offset);
+    CHECK_EQ(source_iterator.source_position(), expected.source_position);
+    CHECK_EQ(source_iterator.is_statement(), expected.is_statement);
+    source_iterator.Advance();
+  }
+  CHECK(source_iterator.done());
+}
+
+TEST_F(BytecodeArrayWriterUnittest, ComplexExample) {
+  static const uint8_t expected_bytes[] = {
+      // clang-format off
+      /*  0 30 E> */ B(StackCheck),
+      /*  1 42 S> */ B(LdaConstant), U8(0),
+      /*  3 42 E> */ B(Star), R8(1),
+      /*  5 68 S> */ B(JumpIfUndefined), U8(38),
+      /*  7       */ B(JumpIfNull), U8(36),
+      /*  9       */ B(ToObject),
+      /* 10       */ B(Star), R8(3),
+      /* 12       */ B(ForInPrepare), R8(4),
+      /* 14       */ B(LdaZero),
+      /* 15       */ B(Star), R8(7),
+      /* 17 63 S> */ B(ForInDone), R8(7), R8(6),
+      /* 20       */ B(JumpIfTrue), U8(23),
+      /* 22       */ B(ForInNext), R8(3), R8(7), R8(4), U8(1),
+      /* 27       */ B(JumpIfUndefined), U8(10),
+      /* 29       */ B(Star), R8(0),
+      /* 31 54 E> */ B(StackCheck),
+      /* 32       */ B(Ldar), R8(0),
+      /* 34       */ B(Star), R8(2),
+      /* 36 85 S> */ B(Return),
+      /* 37       */ B(ForInStep), R8(7),
+      /* 39       */ B(Star), R8(7),
+      /* 41       */ B(Jump), U8(-24),
+      /* 43       */ B(LdaUndefined),
+      /* 44 85 S> */ B(Return),
+      // clang-format on
+  };
+
+  static const PositionTableEntry expected_positions[] = {
+      {0, 30, false}, {1, 42, true},   {3, 42, false}, {5, 68, true},
+      {17, 63, true}, {31, 54, false}, {36, 85, true}, {44, 85, true}};
+
+  BytecodeLabel back_jump, jump_for_in, jump_end_1, jump_end_2, jump_end_3;
+
+#define R(i) static_cast<uint32_t>(Register(i).ToOperand())
+  Write(Bytecode::kStackCheck, {30, false});
+  Write(Bytecode::kLdaConstant, U8(0), {42, true});
+  CHECK_EQ(max_register_count(), 0);
+  Write(Bytecode::kStar, R(1), {42, false});
+  CHECK_EQ(max_register_count(), 2);
+  WriteJump(Bytecode::kJumpIfUndefined, &jump_end_1, {68, true});
+  WriteJump(Bytecode::kJumpIfNull, &jump_end_2);
+  Write(Bytecode::kToObject);
+  CHECK_EQ(max_register_count(), 2);
+  Write(Bytecode::kStar, R(3));
+  CHECK_EQ(max_register_count(), 4);
+  Write(Bytecode::kForInPrepare, R(4));
+  CHECK_EQ(max_register_count(), 7);
+  Write(Bytecode::kLdaZero);
+  CHECK_EQ(max_register_count(), 7);
+  Write(Bytecode::kStar, R(7));
+  CHECK_EQ(max_register_count(), 8);
+  writer()->BindLabel(&back_jump);
+  Write(Bytecode::kForInDone, R(7), R(6), {63, true});
+  CHECK_EQ(max_register_count(), 8);
+  WriteJump(Bytecode::kJumpIfTrue, &jump_end_3);
+  Write(Bytecode::kForInNext, R(3), R(7), R(4), U8(1));
+  WriteJump(Bytecode::kJumpIfUndefined, &jump_for_in);
+  Write(Bytecode::kStar, R(0));
+  Write(Bytecode::kStackCheck, {54, false});
+  Write(Bytecode::kLdar, R(0));
+  Write(Bytecode::kStar, R(2));
+  Write(Bytecode::kReturn, {85, true});
+  writer()->BindLabel(&jump_for_in);
+  Write(Bytecode::kForInStep, R(7));
+  Write(Bytecode::kStar, R(7));
+  WriteJump(Bytecode::kJump, &back_jump);
+  writer()->BindLabel(&jump_end_1);
+  writer()->BindLabel(&jump_end_2);
+  writer()->BindLabel(&jump_end_3);
+  Write(Bytecode::kLdaUndefined);
+  Write(Bytecode::kReturn, {85, true});
+  CHECK_EQ(max_register_count(), 8);
+#undef R
+
+  CHECK_EQ(bytecodes()->size(), arraysize(expected_bytes));
+  for (size_t i = 0; i < arraysize(expected_bytes); ++i) {
+    CHECK_EQ(static_cast<int>(bytecodes()->at(i)),
+             static_cast<int>(expected_bytes[i]));
+  }
+
+  Handle<ByteArray> source_positions =
+      source_position_table_builder()->ToSourcePositionTable();
+  SourcePositionTableIterator source_iterator(*source_positions);
+  for (size_t i = 0; i < arraysize(expected_positions); ++i) {
+    const PositionTableEntry& expected = expected_positions[i];
+    CHECK_EQ(source_iterator.bytecode_offset(), expected.bytecode_offset);
+    CHECK_EQ(source_iterator.source_position(), expected.source_position);
+    CHECK_EQ(source_iterator.is_statement(), expected.is_statement);
+    source_iterator.Advance();
+  }
+  CHECK(source_iterator.done());
+}
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/interpreter/bytecode-dead-code-optimizer-unittest.cc b/test/unittests/interpreter/bytecode-dead-code-optimizer-unittest.cc
new file mode 100644
index 0000000..915c23d
--- /dev/null
+++ b/test/unittests/interpreter/bytecode-dead-code-optimizer-unittest.cc
@@ -0,0 +1,149 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "src/interpreter/bytecode-dead-code-optimizer.h"
+#include "src/interpreter/bytecode-label.h"
+#include "src/objects.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+class BytecodeDeadCodeOptimizerTest : public BytecodePipelineStage,
+                                      public TestWithIsolateAndZone {
+ public:
+  BytecodeDeadCodeOptimizerTest() : dead_code_optimizer_(this) {}
+  ~BytecodeDeadCodeOptimizerTest() override {}
+
+  void Write(BytecodeNode* node) override {
+    write_count_++;
+    last_written_.Clone(node);
+  }
+
+  void WriteJump(BytecodeNode* node, BytecodeLabel* label) override {
+    write_count_++;
+    last_written_.Clone(node);
+  }
+
+  void BindLabel(BytecodeLabel* label) override {}
+  void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override {}
+  Handle<BytecodeArray> ToBytecodeArray(
+      int fixed_register_count, int parameter_count,
+      Handle<FixedArray> handle_table) override {
+    return Handle<BytecodeArray>();
+  }
+
+  BytecodeDeadCodeOptimizer* optimizer() { return &dead_code_optimizer_; }
+
+  int write_count() const { return write_count_; }
+  const BytecodeNode& last_written() const { return last_written_; }
+
+ private:
+  BytecodeDeadCodeOptimizer dead_code_optimizer_;
+
+  int write_count_ = 0;
+  BytecodeNode last_written_;
+};
+
+TEST_F(BytecodeDeadCodeOptimizerTest, LiveCodeKept) {
+  BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
+  optimizer()->Write(&add);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(add, last_written());
+
+  BytecodeLabel target;
+  BytecodeNode jump(Bytecode::kJump, 0);
+  optimizer()->WriteJump(&jump, &target);
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(jump, last_written());
+}
+
+TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeAfterReturnEliminated) {
+  BytecodeNode ret(Bytecode::kReturn);
+  optimizer()->Write(&ret);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(ret, last_written());
+
+  BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
+  optimizer()->Write(&add);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(ret, last_written());
+}
+
+TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeAfterThrowEliminated) {
+  BytecodeNode thrw(Bytecode::kThrow);
+  optimizer()->Write(&thrw);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(thrw, last_written());
+
+  BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
+  optimizer()->Write(&add);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(thrw, last_written());
+}
+
+TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeAfterReThrowEliminated) {
+  BytecodeNode rethrow(Bytecode::kReThrow);
+  optimizer()->Write(&rethrow);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(rethrow, last_written());
+
+  BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
+  optimizer()->Write(&add);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(rethrow, last_written());
+}
+
+TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeAfterJumpEliminated) {
+  BytecodeLabel target;
+  BytecodeNode jump(Bytecode::kJump, 0);
+  optimizer()->WriteJump(&jump, &target);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(jump, last_written());
+
+  BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
+  optimizer()->Write(&add);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(jump, last_written());
+}
+
+TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeStillDeadAfterConditinalJump) {
+  BytecodeNode ret(Bytecode::kReturn);
+  optimizer()->Write(&ret);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(ret, last_written());
+
+  BytecodeLabel target;
+  BytecodeNode jump(Bytecode::kJumpIfTrue, 0);
+  optimizer()->WriteJump(&jump, &target);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(ret, last_written());
+
+  BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
+  optimizer()->Write(&add);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(ret, last_written());
+}
+
+TEST_F(BytecodeDeadCodeOptimizerTest, CodeLiveAfterLabelBind) {
+  BytecodeNode ret(Bytecode::kReturn);
+  optimizer()->Write(&ret);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(ret, last_written());
+
+  BytecodeLabel target;
+  optimizer()->BindLabel(&target);
+
+  BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
+  optimizer()->Write(&add);
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(add, last_written());
+}
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/interpreter/bytecode-peephole-optimizer-unittest.cc b/test/unittests/interpreter/bytecode-peephole-optimizer-unittest.cc
new file mode 100644
index 0000000..671bdf8
--- /dev/null
+++ b/test/unittests/interpreter/bytecode-peephole-optimizer-unittest.cc
@@ -0,0 +1,494 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "src/factory.h"
+#include "src/interpreter/bytecode-label.h"
+#include "src/interpreter/bytecode-peephole-optimizer.h"
+#include "src/interpreter/constant-array-builder.h"
+#include "src/objects-inl.h"
+#include "src/objects.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+class BytecodePeepholeOptimizerTest : public BytecodePipelineStage,
+                                      public TestWithIsolateAndZone {
+ public:
+  BytecodePeepholeOptimizerTest()
+      : constant_array_builder_(isolate(), zone()),
+        peephole_optimizer_(&constant_array_builder_, this) {}
+  ~BytecodePeepholeOptimizerTest() override {}
+
+  void Write(BytecodeNode* node) override {
+    write_count_++;
+    last_written_.Clone(node);
+  }
+
+  void WriteJump(BytecodeNode* node, BytecodeLabel* label) override {
+    write_count_++;
+    last_written_.Clone(node);
+  }
+
+  void BindLabel(BytecodeLabel* label) override {}
+  void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override {}
+  Handle<BytecodeArray> ToBytecodeArray(
+      int fixed_register_count, int parameter_count,
+      Handle<FixedArray> handle_table) override {
+    return Handle<BytecodeArray>();
+  }
+
+  void Flush() {
+    optimizer()->ToBytecodeArray(0, 0, factory()->empty_fixed_array());
+  }
+
+  BytecodePeepholeOptimizer* optimizer() { return &peephole_optimizer_; }
+  ConstantArrayBuilder* constant_array() { return &constant_array_builder_; }
+
+  int write_count() const { return write_count_; }
+  const BytecodeNode& last_written() const { return last_written_; }
+
+ private:
+  ConstantArrayBuilder constant_array_builder_;
+  BytecodePeepholeOptimizer peephole_optimizer_;
+
+  int write_count_ = 0;
+  BytecodeNode last_written_;
+};
+
+// Sanity tests.
+
+TEST_F(BytecodePeepholeOptimizerTest, FlushOnJump) {
+  CHECK_EQ(write_count(), 0);
+
+  BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
+  optimizer()->Write(&add);
+  CHECK_EQ(write_count(), 0);
+
+  BytecodeLabel target;
+  BytecodeNode jump(Bytecode::kJump, 0);
+  optimizer()->WriteJump(&jump, &target);
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(jump, last_written());
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, FlushOnBind) {
+  CHECK_EQ(write_count(), 0);
+
+  BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
+  optimizer()->Write(&add);
+  CHECK_EQ(write_count(), 0);
+
+  BytecodeLabel target;
+  optimizer()->BindLabel(&target);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(add, last_written());
+}
+
+// Nop elimination tests.
+
+TEST_F(BytecodePeepholeOptimizerTest, ElideEmptyNop) {
+  BytecodeNode nop(Bytecode::kNop);
+  optimizer()->Write(&nop);
+  BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
+  optimizer()->Write(&add);
+  Flush();
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(add, last_written());
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, ElideExpressionNop) {
+  BytecodeNode nop(Bytecode::kNop);
+  nop.source_info().MakeExpressionPosition(3);
+  optimizer()->Write(&nop);
+  BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
+  optimizer()->Write(&add);
+  Flush();
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(add, last_written());
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, KeepStatementNop) {
+  BytecodeNode nop(Bytecode::kNop);
+  nop.source_info().MakeStatementPosition(3);
+  optimizer()->Write(&nop);
+  BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand());
+  add.source_info().MakeExpressionPosition(3);
+  optimizer()->Write(&add);
+  Flush();
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(add, last_written());
+}
+
+// Tests covering BytecodePeepholeOptimizer::UpdateCurrentBytecode().
+
+TEST_F(BytecodePeepholeOptimizerTest, KeepJumpIfToBooleanTrue) {
+  BytecodeNode first(Bytecode::kLdaNull);
+  BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3);
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written(), first);
+  Flush();
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(last_written(), second);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, ElideJumpIfToBooleanTrue) {
+  BytecodeNode first(Bytecode::kLdaTrue);
+  BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3);
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written(), first);
+  Flush();
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(last_written().bytecode(), Bytecode::kJumpIfTrue);
+  CHECK_EQ(last_written().operand(0), second.operand(0));
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, KeepToBooleanLogicalNot) {
+  BytecodeNode first(Bytecode::kLdaNull);
+  BytecodeNode second(Bytecode::kToBooleanLogicalNot);
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written(), first);
+  Flush();
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(last_written(), second);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, ElideToBooleanLogicalNot) {
+  BytecodeNode first(Bytecode::kLdaTrue);
+  BytecodeNode second(Bytecode::kToBooleanLogicalNot);
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written(), first);
+  Flush();
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(last_written().bytecode(), Bytecode::kLogicalNot);
+}
+
+// Tests covering BytecodePeepholeOptimizer::CanElideCurrent().
+
+TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRy) {
+  BytecodeNode first(Bytecode::kStar, Register(0).ToOperand());
+  BytecodeNode second(Bytecode::kLdar, Register(1).ToOperand());
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written(), first);
+  Flush();
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(last_written(), second);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRx) {
+  BytecodeLabel label;
+  BytecodeNode first(Bytecode::kStar, Register(0).ToOperand());
+  BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand());
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written(), first);
+  Flush();
+  CHECK_EQ(write_count(), 1);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatement) {
+  BytecodeNode first(Bytecode::kStar, Register(0).ToOperand());
+  BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand());
+  second.source_info().MakeStatementPosition(0);
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written(), first);
+  Flush();
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(last_written().bytecode(), Bytecode::kNop);
+  CHECK_EQ(last_written().source_info(), second.source_info());
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatementStarRy) {
+  BytecodeLabel label;
+  BytecodeNode first(Bytecode::kStar, Register(0).ToOperand());
+  BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand());
+  BytecodeNode third(Bytecode::kStar, Register(3).ToOperand());
+  second.source_info().MakeStatementPosition(0);
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written(), first);
+  optimizer()->Write(&third);
+  CHECK_EQ(write_count(), 1);
+  Flush();
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(last_written(), third);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, LdarToName) {
+  BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand());
+  BytecodeNode second(Bytecode::kToName);
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written(), first);
+  Flush();
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(last_written(), second);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, ToNameToName) {
+  BytecodeNode first(Bytecode::kToName);
+  BytecodeNode second(Bytecode::kToName);
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written(), first);
+  Flush();
+  CHECK_EQ(write_count(), 1);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, TypeOfToName) {
+  BytecodeNode first(Bytecode::kTypeOf);
+  BytecodeNode second(Bytecode::kToName);
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written(), first);
+  Flush();
+  CHECK_EQ(write_count(), 1);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, LdaConstantStringToName) {
+  Handle<Object> word =
+      isolate()->factory()->NewStringFromStaticChars("optimizing");
+  size_t index = constant_array()->Insert(word);
+  BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index));
+  BytecodeNode second(Bytecode::kToName);
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written(), first);
+  Flush();
+  CHECK_EQ(write_count(), 1);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, LdaConstantNumberToName) {
+  Handle<Object> word = isolate()->factory()->NewNumber(0.380);
+  size_t index = constant_array()->Insert(word);
+  BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index));
+  BytecodeNode second(Bytecode::kToName);
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written(), first);
+  Flush();
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(last_written(), second);
+}
+
+// Tests covering BytecodePeepholeOptimizer::CanElideLast().
+
+TEST_F(BytecodePeepholeOptimizerTest, LdaTrueLdaFalse) {
+  BytecodeNode first(Bytecode::kLdaTrue);
+  BytecodeNode second(Bytecode::kLdaFalse);
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 0);
+  Flush();
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written(), second);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, LdaTrueStatementLdaFalse) {
+  BytecodeNode first(Bytecode::kLdaTrue);
+  first.source_info().MakeExpressionPosition(3);
+  BytecodeNode second(Bytecode::kLdaFalse);
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 0);
+  Flush();
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written(), second);
+  CHECK(second.source_info().is_expression());
+  CHECK_EQ(second.source_info().source_position(), 3);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, NopStackCheck) {
+  BytecodeNode first(Bytecode::kNop);
+  BytecodeNode second(Bytecode::kStackCheck);
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 0);
+  Flush();
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written(), second);
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, NopStatementStackCheck) {
+  BytecodeNode first(Bytecode::kNop);
+  first.source_info().MakeExpressionPosition(3);
+  BytecodeNode second(Bytecode::kStackCheck);
+  optimizer()->Write(&first);
+  CHECK_EQ(write_count(), 0);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 0);
+  Flush();
+  CHECK_EQ(write_count(), 1);
+  second.source_info().MakeExpressionPosition(
+      first.source_info().source_position());
+  CHECK_EQ(last_written(), second);
+}
+
+// Tests covering BytecodePeepholeOptimizer::UpdateLastAndCurrentBytecodes().
+
+TEST_F(BytecodePeepholeOptimizerTest, MergeLoadICStar) {
+  const uint32_t operands[] = {
+      static_cast<uint32_t>(Register(31).ToOperand()), 32, 33,
+      static_cast<uint32_t>(Register(256).ToOperand())};
+  const int expected_operand_count = static_cast<int>(arraysize(operands));
+
+  BytecodeNode first(Bytecode::kLdaNamedProperty, operands[0], operands[1],
+                     operands[2]);
+  BytecodeNode second(Bytecode::kStar, operands[3]);
+  BytecodeNode third(Bytecode::kReturn);
+  optimizer()->Write(&first);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written().bytecode(), Bytecode::kLdrNamedProperty);
+  CHECK_EQ(last_written().operand_count(), expected_operand_count);
+  for (int i = 0; i < expected_operand_count; ++i) {
+    CHECK_EQ(last_written().operand(i), operands[i]);
+  }
+  optimizer()->Write(&third);
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
+  CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
+  Flush();
+  CHECK_EQ(last_written().bytecode(), third.bytecode());
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, MergeLdaKeyedPropertyStar) {
+  const uint32_t operands[] = {static_cast<uint32_t>(Register(31).ToOperand()),
+                               9999997,
+                               static_cast<uint32_t>(Register(1).ToOperand())};
+  const int expected_operand_count = static_cast<int>(arraysize(operands));
+
+  BytecodeNode first(Bytecode::kLdaKeyedProperty, operands[0], operands[1]);
+  BytecodeNode second(Bytecode::kStar, operands[2]);
+  BytecodeNode third(Bytecode::kReturn);
+  optimizer()->Write(&first);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written().bytecode(), Bytecode::kLdrKeyedProperty);
+  CHECK_EQ(last_written().operand_count(), expected_operand_count);
+  for (int i = 0; i < expected_operand_count; ++i) {
+    CHECK_EQ(last_written().operand(i), operands[i]);
+  }
+  optimizer()->Write(&third);
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
+  CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
+  Flush();
+  CHECK_EQ(last_written().bytecode(), third.bytecode());
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, MergeLdaGlobalStar) {
+  const uint32_t operands[] = {19191,
+                               static_cast<uint32_t>(Register(1).ToOperand())};
+  const int expected_operand_count = static_cast<int>(arraysize(operands));
+
+  BytecodeNode first(Bytecode::kLdaGlobal, operands[0]);
+  BytecodeNode second(Bytecode::kStar, operands[1]);
+  BytecodeNode third(Bytecode::kReturn);
+  optimizer()->Write(&first);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written().bytecode(), Bytecode::kLdrGlobal);
+  CHECK_EQ(last_written().operand_count(), expected_operand_count);
+  for (int i = 0; i < expected_operand_count; ++i) {
+    CHECK_EQ(last_written().operand(i), operands[i]);
+  }
+  optimizer()->Write(&third);
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
+  CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
+  Flush();
+  CHECK_EQ(last_written().bytecode(), third.bytecode());
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, MergeLdaContextSlotStar) {
+  const uint32_t operands[] = {
+      static_cast<uint32_t>(Register(200000).ToOperand()), 55005500,
+      static_cast<uint32_t>(Register(1).ToOperand())};
+  const int expected_operand_count = static_cast<int>(arraysize(operands));
+
+  BytecodeNode first(Bytecode::kLdaContextSlot, operands[0], operands[1]);
+  BytecodeNode second(Bytecode::kStar, operands[2]);
+  BytecodeNode third(Bytecode::kReturn);
+  optimizer()->Write(&first);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written().bytecode(), Bytecode::kLdrContextSlot);
+  CHECK_EQ(last_written().operand_count(), expected_operand_count);
+  for (int i = 0; i < expected_operand_count; ++i) {
+    CHECK_EQ(last_written().operand(i), operands[i]);
+  }
+  optimizer()->Write(&third);
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
+  CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
+  Flush();
+  CHECK_EQ(last_written().bytecode(), third.bytecode());
+}
+
+TEST_F(BytecodePeepholeOptimizerTest, MergeLdaUndefinedStar) {
+  const uint32_t operands[] = {
+      static_cast<uint32_t>(Register(100000).ToOperand())};
+  const int expected_operand_count = static_cast<int>(arraysize(operands));
+
+  BytecodeNode first(Bytecode::kLdaUndefined);
+  BytecodeNode second(Bytecode::kStar, operands[0]);
+  BytecodeNode third(Bytecode::kReturn);
+  optimizer()->Write(&first);
+  optimizer()->Write(&second);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(last_written().bytecode(), Bytecode::kLdrUndefined);
+  CHECK_EQ(last_written().operand_count(), expected_operand_count);
+  for (int i = 0; i < expected_operand_count; ++i) {
+    CHECK_EQ(last_written().operand(i), operands[i]);
+  }
+  optimizer()->Write(&third);
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
+  CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
+  Flush();
+  CHECK_EQ(last_written().bytecode(), third.bytecode());
+}
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/interpreter/bytecode-pipeline-unittest.cc b/test/unittests/interpreter/bytecode-pipeline-unittest.cc
new file mode 100644
index 0000000..663b7e5
--- /dev/null
+++ b/test/unittests/interpreter/bytecode-pipeline-unittest.cc
@@ -0,0 +1,185 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "src/interpreter/bytecode-pipeline.h"
+#include "src/interpreter/bytecode-register-allocator.h"
+#include "src/isolate.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+using BytecodeNodeTest = TestWithIsolateAndZone;
+
+TEST(BytecodeSourceInfo, Operations) {
+  BytecodeSourceInfo x(0, true);
+  CHECK_EQ(x.source_position(), 0);
+  CHECK_EQ(x.is_statement(), true);
+  CHECK_EQ(x.is_valid(), true);
+  x.set_invalid();
+  CHECK_EQ(x.is_statement(), false);
+  CHECK_EQ(x.is_valid(), false);
+
+  x.MakeStatementPosition(1);
+  BytecodeSourceInfo y(1, true);
+  CHECK(x == y);
+  CHECK(!(x != y));
+
+  x.set_invalid();
+  CHECK(!(x == y));
+  CHECK(x != y);
+
+  y.MakeStatementPosition(1);
+  CHECK_EQ(y.source_position(), 1);
+  CHECK_EQ(y.is_statement(), true);
+
+  y.MakeStatementPosition(2);
+  CHECK_EQ(y.source_position(), 2);
+  CHECK_EQ(y.is_statement(), true);
+
+  y.set_invalid();
+  y.MakeExpressionPosition(3);
+  CHECK_EQ(y.source_position(), 3);
+  CHECK_EQ(y.is_statement(), false);
+
+  y.MakeStatementPosition(3);
+  CHECK_EQ(y.source_position(), 3);
+  CHECK_EQ(y.is_statement(), true);
+}
+
+TEST_F(BytecodeNodeTest, Constructor0) {
+  BytecodeNode node;
+  CHECK_EQ(node.bytecode(), Bytecode::kIllegal);
+  CHECK(!node.source_info().is_valid());
+}
+
+TEST_F(BytecodeNodeTest, Constructor1) {
+  BytecodeNode node(Bytecode::kLdaZero);
+  CHECK_EQ(node.bytecode(), Bytecode::kLdaZero);
+  CHECK_EQ(node.operand_count(), 0);
+  CHECK(!node.source_info().is_valid());
+}
+
+TEST_F(BytecodeNodeTest, Constructor2) {
+  uint32_t operands[] = {0x11};
+  BytecodeNode node(Bytecode::kJumpIfTrue, operands[0]);
+  CHECK_EQ(node.bytecode(), Bytecode::kJumpIfTrue);
+  CHECK_EQ(node.operand_count(), 1);
+  CHECK_EQ(node.operand(0), operands[0]);
+  CHECK(!node.source_info().is_valid());
+}
+
+TEST_F(BytecodeNodeTest, Constructor3) {
+  uint32_t operands[] = {0x11};
+  BytecodeNode node(Bytecode::kLdaGlobal, operands[0]);
+  CHECK_EQ(node.bytecode(), Bytecode::kLdaGlobal);
+  CHECK_EQ(node.operand_count(), 1);
+  CHECK_EQ(node.operand(0), operands[0]);
+  CHECK(!node.source_info().is_valid());
+}
+
+TEST_F(BytecodeNodeTest, Constructor4) {
+  uint32_t operands[] = {0x11, 0x22, 0x33};
+  BytecodeNode node(Bytecode::kLdaNamedProperty, operands[0], operands[1],
+                    operands[2]);
+  CHECK_EQ(node.operand_count(), 3);
+  CHECK_EQ(node.bytecode(), Bytecode::kLdaNamedProperty);
+  CHECK_EQ(node.operand(0), operands[0]);
+  CHECK_EQ(node.operand(1), operands[1]);
+  CHECK_EQ(node.operand(2), operands[2]);
+  CHECK(!node.source_info().is_valid());
+}
+
+TEST_F(BytecodeNodeTest, Constructor5) {
+  uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
+  BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
+                    operands[3]);
+  CHECK_EQ(node.operand_count(), 4);
+  CHECK_EQ(node.bytecode(), Bytecode::kForInNext);
+  CHECK_EQ(node.operand(0), operands[0]);
+  CHECK_EQ(node.operand(1), operands[1]);
+  CHECK_EQ(node.operand(2), operands[2]);
+  CHECK_EQ(node.operand(3), operands[3]);
+  CHECK(!node.source_info().is_valid());
+}
+
+TEST_F(BytecodeNodeTest, Equality) {
+  uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
+  BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
+                    operands[3]);
+  CHECK_EQ(node, node);
+  BytecodeNode other(Bytecode::kForInNext, operands[0], operands[1],
+                     operands[2], operands[3]);
+  CHECK_EQ(node, other);
+}
+
+TEST_F(BytecodeNodeTest, EqualityWithSourceInfo) {
+  uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
+  BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
+                    operands[3]);
+  node.source_info().MakeStatementPosition(3);
+  CHECK_EQ(node, node);
+  BytecodeNode other(Bytecode::kForInNext, operands[0], operands[1],
+                     operands[2], operands[3]);
+  other.source_info().MakeStatementPosition(3);
+  CHECK_EQ(node, other);
+}
+
+TEST_F(BytecodeNodeTest, NoEqualityWithDifferentSourceInfo) {
+  uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
+  BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
+                    operands[3]);
+  node.source_info().MakeStatementPosition(3);
+  BytecodeNode other(Bytecode::kForInNext, operands[0], operands[1],
+                     operands[2], operands[3]);
+  CHECK_NE(node, other);
+}
+
+TEST_F(BytecodeNodeTest, Clone) {
+  uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
+  BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
+                    operands[3]);
+  BytecodeNode clone;
+  clone.Clone(&node);
+  CHECK_EQ(clone, node);
+}
+
+TEST_F(BytecodeNodeTest, SetBytecode0) {
+  uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
+  BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
+                    operands[3]);
+  BytecodeSourceInfo source_info(77, false);
+  node.source_info().Clone(source_info);
+  CHECK_EQ(node.source_info(), source_info);
+
+  BytecodeNode clone;
+  clone.Clone(&node);
+  clone.set_bytecode(Bytecode::kNop);
+  CHECK_EQ(clone.bytecode(), Bytecode::kNop);
+  CHECK_EQ(clone.operand_count(), 0);
+  CHECK_EQ(clone.source_info(), source_info);
+}
+
+TEST_F(BytecodeNodeTest, SetBytecode1) {
+  uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
+  BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
+                    operands[3]);
+  BytecodeSourceInfo source_info(77, false);
+  node.source_info().Clone(source_info);
+
+  BytecodeNode clone;
+  clone.Clone(&node);
+  clone.set_bytecode(Bytecode::kJump, 0x01aabbcc);
+  CHECK_EQ(clone.bytecode(), Bytecode::kJump);
+  CHECK_EQ(clone.operand_count(), 1);
+  CHECK_EQ(clone.operand(0), 0x01aabbcc);
+  CHECK_EQ(clone.source_info(), source_info);
+}
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/interpreter/bytecode-register-optimizer-unittest.cc b/test/unittests/interpreter/bytecode-register-optimizer-unittest.cc
new file mode 100644
index 0000000..795bee8
--- /dev/null
+++ b/test/unittests/interpreter/bytecode-register-optimizer-unittest.cc
@@ -0,0 +1,219 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "src/factory.h"
+#include "src/interpreter/bytecode-label.h"
+#include "src/interpreter/bytecode-register-optimizer.h"
+#include "src/objects-inl.h"
+#include "src/objects.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+class BytecodeRegisterOptimizerTest : public BytecodePipelineStage,
+                                      public TestWithIsolateAndZone {
+ public:
+  BytecodeRegisterOptimizerTest() {}
+  ~BytecodeRegisterOptimizerTest() override { delete register_allocator_; }
+
+  void Initialize(int number_of_parameters, int number_of_locals) {
+    register_allocator_ =
+        new TemporaryRegisterAllocator(zone(), number_of_locals);
+    register_optimizer_ = new (zone()) BytecodeRegisterOptimizer(
+        zone(), register_allocator_, number_of_parameters, this);
+  }
+
+  void Write(BytecodeNode* node) override { output_.push_back(*node); }
+  void WriteJump(BytecodeNode* node, BytecodeLabel* label) override {
+    output_.push_back(*node);
+  }
+  void BindLabel(BytecodeLabel* label) override {}
+  void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override {}
+  Handle<BytecodeArray> ToBytecodeArray(
+      int fixed_register_count, int parameter_count,
+      Handle<FixedArray> handle_table) override {
+    return Handle<BytecodeArray>();
+  }
+
+  TemporaryRegisterAllocator* allocator() { return register_allocator_; }
+  BytecodeRegisterOptimizer* optimizer() { return register_optimizer_; }
+
+  Register NewTemporary() {
+    return Register(allocator()->BorrowTemporaryRegister());
+  }
+
+  void KillTemporary(Register reg) {
+    allocator()->ReturnTemporaryRegister(reg.index());
+  }
+
+  size_t write_count() const { return output_.size(); }
+  const BytecodeNode& last_written() const { return output_.back(); }
+  const std::vector<BytecodeNode>* output() { return &output_; }
+
+ private:
+  TemporaryRegisterAllocator* register_allocator_;
+  BytecodeRegisterOptimizer* register_optimizer_;
+
+  std::vector<BytecodeNode> output_;
+};
+
+// Sanity tests.
+
+TEST_F(BytecodeRegisterOptimizerTest, WriteNop) {
+  Initialize(1, 1);
+  BytecodeNode node(Bytecode::kNop);
+  optimizer()->Write(&node);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(node, last_written());
+}
+
+TEST_F(BytecodeRegisterOptimizerTest, WriteNopExpression) {
+  Initialize(1, 1);
+  BytecodeNode node(Bytecode::kNop);
+  node.source_info().MakeExpressionPosition(3);
+  optimizer()->Write(&node);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(node, last_written());
+}
+
+TEST_F(BytecodeRegisterOptimizerTest, WriteNopStatement) {
+  Initialize(1, 1);
+  BytecodeNode node(Bytecode::kNop);
+  node.source_info().MakeStatementPosition(3);
+  optimizer()->Write(&node);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(node, last_written());
+}
+
+TEST_F(BytecodeRegisterOptimizerTest, TemporaryMaterializedForJump) {
+  Initialize(1, 1);
+  Register temp = NewTemporary();
+  BytecodeNode node(Bytecode::kStar, temp.ToOperand());
+  optimizer()->Write(&node);
+  CHECK_EQ(write_count(), 0);
+  BytecodeLabel label;
+  BytecodeNode jump(Bytecode::kJump, 0);
+  optimizer()->WriteJump(&jump, &label);
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(output()->at(0).bytecode(), Bytecode::kStar);
+  CHECK_EQ(output()->at(0).operand(0), temp.ToOperand());
+  CHECK_EQ(output()->at(1).bytecode(), Bytecode::kJump);
+}
+
+TEST_F(BytecodeRegisterOptimizerTest, TemporaryMaterializedForBind) {
+  Initialize(1, 1);
+  Register temp = NewTemporary();
+  BytecodeNode node(Bytecode::kStar, temp.ToOperand());
+  optimizer()->Write(&node);
+  CHECK_EQ(write_count(), 0);
+  BytecodeLabel label;
+  optimizer()->BindLabel(&label);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(output()->at(0).bytecode(), Bytecode::kStar);
+  CHECK_EQ(output()->at(0).operand(0), temp.ToOperand());
+}
+
+// Basic Register Optimizations
+
+TEST_F(BytecodeRegisterOptimizerTest, TemporaryNotEmitted) {
+  Initialize(3, 1);
+  Register parameter = Register::FromParameterIndex(1, 3);
+  BytecodeNode node0(Bytecode::kLdar, parameter.ToOperand());
+  optimizer()->Write(&node0);
+  CHECK_EQ(write_count(), 0);
+  Register temp = NewTemporary();
+  BytecodeNode node1(Bytecode::kStar, NewTemporary().ToOperand());
+  optimizer()->Write(&node1);
+  CHECK_EQ(write_count(), 0);
+  KillTemporary(temp);
+  CHECK_EQ(write_count(), 0);
+  BytecodeNode node2(Bytecode::kReturn);
+  optimizer()->Write(&node2);
+  CHECK_EQ(write_count(), 2);
+  CHECK_EQ(output()->at(0).bytecode(), Bytecode::kLdar);
+  CHECK_EQ(output()->at(0).operand(0), parameter.ToOperand());
+  CHECK_EQ(output()->at(1).bytecode(), Bytecode::kReturn);
+}
+
+TEST_F(BytecodeRegisterOptimizerTest, StoresToLocalsImmediate) {
+  Initialize(3, 1);
+  Register parameter = Register::FromParameterIndex(1, 3);
+  BytecodeNode node0(Bytecode::kLdar, parameter.ToOperand());
+  optimizer()->Write(&node0);
+  CHECK_EQ(write_count(), 0);
+  Register local = Register(0);
+  BytecodeNode node1(Bytecode::kStar, local.ToOperand());
+  optimizer()->Write(&node1);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(output()->at(0).bytecode(), Bytecode::kMov);
+  CHECK_EQ(output()->at(0).operand(0), parameter.ToOperand());
+  CHECK_EQ(output()->at(0).operand(1), local.ToOperand());
+
+  BytecodeNode node2(Bytecode::kReturn);
+  optimizer()->Write(&node2);
+  CHECK_EQ(write_count(), 3);
+  CHECK_EQ(output()->at(1).bytecode(), Bytecode::kLdar);
+  CHECK_EQ(output()->at(1).operand(0), local.ToOperand());
+  CHECK_EQ(output()->at(2).bytecode(), Bytecode::kReturn);
+}
+
+TEST_F(BytecodeRegisterOptimizerTest, TemporaryNotMaterializedForInput) {
+  Initialize(3, 1);
+  Register parameter = Register::FromParameterIndex(1, 3);
+  Register temp0 = NewTemporary();
+  Register temp1 = NewTemporary();
+  BytecodeNode node0(Bytecode::kMov, parameter.ToOperand(), temp0.ToOperand());
+  optimizer()->Write(&node0);
+  BytecodeNode node1(Bytecode::kMov, parameter.ToOperand(), temp1.ToOperand());
+  optimizer()->Write(&node1);
+  CHECK_EQ(write_count(), 0);
+  BytecodeNode node2(Bytecode::kCallJSRuntime, 0, temp0.ToOperand(), 1);
+  optimizer()->Write(&node2);
+  CHECK_EQ(write_count(), 1);
+  CHECK_EQ(output()->at(0).bytecode(), Bytecode::kCallJSRuntime);
+  CHECK_EQ(output()->at(0).operand(0), 0);
+  CHECK_EQ(output()->at(0).operand(1), parameter.ToOperand());
+  CHECK_EQ(output()->at(0).operand(2), 1);
+}
+
+TEST_F(BytecodeRegisterOptimizerTest, RangeOfTemporariesMaterializedForInput) {
+  Initialize(3, 1);
+  Register parameter = Register::FromParameterIndex(1, 3);
+  Register temp0 = NewTemporary();
+  Register temp1 = NewTemporary();
+  BytecodeNode node0(Bytecode::kLdaSmi, 3);
+  optimizer()->Write(&node0);
+  CHECK_EQ(write_count(), 1);
+  BytecodeNode node1(Bytecode::kStar, temp0.ToOperand());
+  optimizer()->Write(&node1);
+  BytecodeNode node2(Bytecode::kMov, parameter.ToOperand(), temp1.ToOperand());
+  optimizer()->Write(&node2);
+  CHECK_EQ(write_count(), 1);
+  BytecodeNode node3(Bytecode::kCallJSRuntime, 0, temp0.ToOperand(), 2);
+  optimizer()->Write(&node3);
+  CHECK_EQ(write_count(), 4);
+
+  CHECK_EQ(output()->at(0).bytecode(), Bytecode::kLdaSmi);
+  CHECK_EQ(output()->at(0).operand(0), 3);
+
+  CHECK_EQ(output()->at(1).bytecode(), Bytecode::kStar);
+  CHECK_EQ(output()->at(1).operand(0), temp0.ToOperand());
+
+  CHECK_EQ(output()->at(2).bytecode(), Bytecode::kMov);
+  CHECK_EQ(output()->at(2).operand(0), parameter.ToOperand());
+  CHECK_EQ(output()->at(2).operand(1), temp1.ToOperand());
+
+  CHECK_EQ(output()->at(3).bytecode(), Bytecode::kCallJSRuntime);
+  CHECK_EQ(output()->at(3).operand(0), 0);
+  CHECK_EQ(output()->at(3).operand(1), temp0.ToOperand());
+  CHECK_EQ(output()->at(3).operand(2), 2);
+}
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/interpreter/bytecode-utils.h b/test/unittests/interpreter/bytecode-utils.h
new file mode 100644
index 0000000..fffb719
--- /dev/null
+++ b/test/unittests/interpreter/bytecode-utils.h
@@ -0,0 +1,37 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_UNITTESTS_INTERPRETER_BYTECODE_UTILS_H_
+#define V8_UNITTESTS_INTERPRETER_BYTECODE_UTILS_H_
+
+#include "src/frames.h"
+
+#if V8_TARGET_LITTLE_ENDIAN
+
+#define EXTRACT(x, n) static_cast<uint8_t>((x) >> (8 * n))
+#define U16(i) EXTRACT(i, 0), EXTRACT(i, 1)
+#define U32(i) EXTRACT(i, 0), EXTRACT(i, 1), EXTRACT(i, 2), EXTRACT(i, 3)
+
+#elif V8_TARGET_BIG_ENDIAN
+
+#define EXTRACT(x, n) static_cast<uint8_t>((x) >> (8 * n))
+
+#define U16(i) EXTRACT(i, 1), EXTRACT(i, 0)
+#define U32(i) EXTRACT(i, 3), EXTRACT(i, 2), EXTRACT(i, 1), EXTRACT(i, 0)
+
+#else
+
+#error "Unknown Architecture"
+
+#endif
+
+#define U8(i) static_cast<uint8_t>(i)
+#define B(Name) static_cast<uint8_t>(Bytecode::k##Name)
+#define REG_OPERAND(i) \
+  (InterpreterFrameConstants::kRegisterFileFromFp / kPointerSize - (i))
+#define R8(i) static_cast<uint8_t>(REG_OPERAND(i))
+#define R16(i) U16(REG_OPERAND(i))
+#define R32(i) U32(REG_OPERAND(i))
+
+#endif  // V8_UNITTESTS_INTERPRETER_BYTECODE_UTILS_H_
diff --git a/test/unittests/interpreter/bytecodes-unittest.cc b/test/unittests/interpreter/bytecodes-unittest.cc
index b3554c3..74a2bb3 100644
--- a/test/unittests/interpreter/bytecodes-unittest.cc
+++ b/test/unittests/interpreter/bytecodes-unittest.cc
@@ -7,6 +7,7 @@
 #include "src/v8.h"
 
 #include "src/interpreter/bytecodes.h"
+#include "test/unittests/interpreter/bytecode-utils.h"
 #include "test/unittests/test-utils.h"
 
 namespace v8 {
@@ -31,15 +32,6 @@
     Register reg2 = Register::FromOperand(operand2);
     CHECK_EQ(i, reg2.index());
   }
-
-  for (int i = 0; i <= kMaxUInt8; i++) {
-    Register reg = Register::FromOperand(i);
-    if (i > 0) {
-      CHECK(reg.is_parameter());
-    } else {
-      CHECK(!reg.is_parameter());
-    }
-  }
 }
 
 TEST(OperandConversion, Parameters) {
@@ -85,9 +77,13 @@
 }
 
 TEST(OperandScaling, ScalableAndNonScalable) {
-  for (OperandScale operand_scale = OperandScale::kSingle;
-       operand_scale <= OperandScale::kMaxValid;
-       operand_scale = Bytecodes::NextOperandScale(operand_scale)) {
+  const OperandScale kOperandScales[] = {
+#define VALUE(Name, _) OperandScale::k##Name,
+      OPERAND_SCALE_LIST(VALUE)
+#undef VALUE
+  };
+
+  for (OperandScale operand_scale : kOperandScales) {
     int scale = static_cast<int>(operand_scale);
     CHECK_EQ(Bytecodes::Size(Bytecode::kCallRuntime, operand_scale),
              1 + 2 + 2 * scale);
@@ -185,23 +181,22 @@
     const char* output;
   };
 
-#define B(Name) static_cast<uint8_t>(Bytecode::k##Name)
   const BytecodesAndResult cases[] = {
-      {{B(LdaSmi), 0x01}, 2, 0, "            LdaSmi [1]"},
-      {{B(Wide), B(LdaSmi), 0xe8, 0x03}, 4, 0, "      LdaSmi.Wide [1000]"},
-      {{B(ExtraWide), B(LdaSmi), 0xa0, 0x86, 0x01, 0x00},
+      {{B(LdaSmi), U8(1)}, 2, 0, "            LdaSmi [1]"},
+      {{B(Wide), B(LdaSmi), U16(1000)}, 4, 0, "      LdaSmi.Wide [1000]"},
+      {{B(ExtraWide), B(LdaSmi), U32(100000)},
        6,
        0,
        "LdaSmi.ExtraWide [100000]"},
-      {{B(LdaSmi), 0xff}, 2, 0, "            LdaSmi [-1]"},
-      {{B(Wide), B(LdaSmi), 0x18, 0xfc}, 4, 0, "      LdaSmi.Wide [-1000]"},
-      {{B(ExtraWide), B(LdaSmi), 0x60, 0x79, 0xfe, 0xff},
+      {{B(LdaSmi), U8(-1)}, 2, 0, "            LdaSmi [-1]"},
+      {{B(Wide), B(LdaSmi), U16(-1000)}, 4, 0, "      LdaSmi.Wide [-1000]"},
+      {{B(ExtraWide), B(LdaSmi), U32(-100000)},
        6,
        0,
        "LdaSmi.ExtraWide [-100000]"},
-      {{B(Star), 0xfb}, 2, 0, "            Star r5"},
-      {{B(Wide), B(Star), 0x78, 0xff}, 4, 0, "      Star.Wide r136"},
-      {{B(Wide), B(Call), 0x7a, 0xff, 0x79, 0xff, 0x02, 0x00, 0xb1, 0x00},
+      {{B(Star), R8(5)}, 2, 0, "            Star r5"},
+      {{B(Wide), B(Star), R16(136)}, 4, 0, "      Star.Wide r136"},
+      {{B(Wide), B(Call), R16(134), R16(135), U16(2), U16(177)},
        10,
        0,
        "Call.Wide r134, r135, #2, [177]"},
@@ -210,16 +205,15 @@
        2,
        3,
        "            Ldar a1"},
-      {{B(Wide), B(CreateObjectLiteral), 0x01, 0x02, 0x03, 0x04, 0xa5},
+      {{B(Wide), B(CreateObjectLiteral), U16(513), U16(1027), U8(165)},
        7,
        0,
        "CreateObjectLiteral.Wide [513], [1027], #165"},
-      {{B(ExtraWide), B(JumpIfNull), 0x15, 0xcd, 0x5b, 0x07},
+      {{B(ExtraWide), B(JumpIfNull), U32(123456789)},
        6,
        0,
        "JumpIfNull.ExtraWide [123456789]"},
   };
-#undef B
 
   for (size_t i = 0; i < arraysize(cases); ++i) {
     // Generate reference string by prepending formatted bytes.
@@ -260,13 +254,42 @@
   }
 }
 
-TEST(OperandScale, PrefixesScale) {
-  CHECK(Bytecodes::NextOperandScale(OperandScale::kSingle) ==
-        OperandScale::kDouble);
-  CHECK(Bytecodes::NextOperandScale(OperandScale::kDouble) ==
-        OperandScale::kQuadruple);
-  CHECK(Bytecodes::NextOperandScale(OperandScale::kQuadruple) ==
-        OperandScale::kInvalid);
+TEST(Bytecodes, SizesForSignedOperands) {
+  CHECK(Bytecodes::SizeForSignedOperand(0) == OperandSize::kByte);
+  CHECK(Bytecodes::SizeForSignedOperand(kMaxInt8) == OperandSize::kByte);
+  CHECK(Bytecodes::SizeForSignedOperand(kMinInt8) == OperandSize::kByte);
+  CHECK(Bytecodes::SizeForSignedOperand(kMaxInt8 + 1) == OperandSize::kShort);
+  CHECK(Bytecodes::SizeForSignedOperand(kMinInt8 - 1) == OperandSize::kShort);
+  CHECK(Bytecodes::SizeForSignedOperand(kMaxInt16) == OperandSize::kShort);
+  CHECK(Bytecodes::SizeForSignedOperand(kMinInt16) == OperandSize::kShort);
+  CHECK(Bytecodes::SizeForSignedOperand(kMaxInt16 + 1) == OperandSize::kQuad);
+  CHECK(Bytecodes::SizeForSignedOperand(kMinInt16 - 1) == OperandSize::kQuad);
+  CHECK(Bytecodes::SizeForSignedOperand(kMaxInt) == OperandSize::kQuad);
+  CHECK(Bytecodes::SizeForSignedOperand(kMinInt) == OperandSize::kQuad);
+}
+
+TEST(Bytecodes, SizesForUnsignedOperands) {
+  // int overloads
+  CHECK(Bytecodes::SizeForUnsignedOperand(0) == OperandSize::kByte);
+  CHECK(Bytecodes::SizeForUnsignedOperand(kMaxUInt8) == OperandSize::kByte);
+  CHECK(Bytecodes::SizeForUnsignedOperand(kMaxUInt8 + 1) ==
+        OperandSize::kShort);
+  CHECK(Bytecodes::SizeForUnsignedOperand(kMaxUInt16) == OperandSize::kShort);
+  CHECK(Bytecodes::SizeForUnsignedOperand(kMaxUInt16 + 1) ==
+        OperandSize::kQuad);
+  // size_t overloads
+  CHECK(Bytecodes::SizeForUnsignedOperand(static_cast<size_t>(0)) ==
+        OperandSize::kByte);
+  CHECK(Bytecodes::SizeForUnsignedOperand(static_cast<size_t>(kMaxUInt8)) ==
+        OperandSize::kByte);
+  CHECK(Bytecodes::SizeForUnsignedOperand(static_cast<size_t>(kMaxUInt8 + 1)) ==
+        OperandSize::kShort);
+  CHECK(Bytecodes::SizeForUnsignedOperand(static_cast<size_t>(kMaxUInt16)) ==
+        OperandSize::kShort);
+  CHECK(Bytecodes::SizeForUnsignedOperand(
+            static_cast<size_t>(kMaxUInt16 + 1)) == OperandSize::kQuad);
+  CHECK(Bytecodes::SizeForUnsignedOperand(static_cast<size_t>(kMaxUInt32)) ==
+        OperandSize::kQuad);
 }
 
 TEST(OperandScale, PrefixesRequired) {
@@ -314,7 +337,6 @@
   names.insert(Bytecodes::AccumulatorUseToString(AccumulatorUse::kReadWrite));
   CHECK_EQ(names.size(), 4);
 }
-
 }  // namespace interpreter
 }  // namespace internal
 }  // namespace v8
diff --git a/test/unittests/interpreter/constant-array-builder-unittest.cc b/test/unittests/interpreter/constant-array-builder-unittest.cc
index 7122437..c48ac58 100644
--- a/test/unittests/interpreter/constant-array-builder-unittest.cc
+++ b/test/unittests/interpreter/constant-array-builder-unittest.cc
@@ -89,7 +89,7 @@
     }
     for (size_t i = 0; i < reserved; i++) {
       size_t index = k8BitCapacity - reserved + i;
-      CHECK(builder.At(index)->IsTheHole());
+      CHECK(builder.At(index)->IsTheHole(isolate()));
     }
 
     // Now make reservations, and commit them with unique entries.
diff --git a/test/unittests/interpreter/interpreter-assembler-unittest.cc b/test/unittests/interpreter/interpreter-assembler-unittest.cc
index 0106c57..1bc80c0 100644
--- a/test/unittests/interpreter/interpreter-assembler-unittest.cc
+++ b/test/unittests/interpreter/interpreter-assembler-unittest.cc
@@ -313,12 +313,7 @@
 TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
-    m.Dispatch();
-    Graph* graph = m.graph();
-
-    Node* end = graph->end();
-    EXPECT_EQ(1, end->InputCount());
-    Node* tail_call_node = end->InputAt(0);
+    Node* tail_call_node = m.Dispatch();
 
     OperandScale operand_scale = OperandScale::kSingle;
     Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
@@ -342,12 +337,10 @@
         IsTailCall(
             _, code_target_matcher,
             IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
-            IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
             next_bytecode_offset_matcher,
             IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
             IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
-            IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
-            _));
+            _, _));
   }
 }
 
@@ -359,11 +352,7 @@
   TRACED_FOREACH(int, jump_offset, jump_offsets) {
     TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
       InterpreterAssemblerForTest m(this, bytecode);
-      m.Jump(m.IntPtrConstant(jump_offset));
-      Graph* graph = m.graph();
-      Node* end = graph->end();
-      EXPECT_EQ(1, end->InputCount());
-      Node* tail_call_node = end->InputAt(0);
+      Node* tail_call_node = m.Jump(m.IntPtrConstant(jump_offset));
 
       Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
           IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
@@ -385,100 +374,14 @@
           IsTailCall(
               _, code_target_matcher,
               IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
-              IsParameter(
-                  InterpreterDispatchDescriptor::kRegisterFileParameter),
               next_bytecode_offset_matcher, _,
               IsParameter(
                   InterpreterDispatchDescriptor::kDispatchTableParameter),
-              IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
-              _));
+              _, _));
     }
   }
 }
 
-TARGET_TEST_F(InterpreterAssemblerTest, JumpIfWordEqual) {
-  static const int kJumpIfTrueOffset = 73;
-
-  // If debug code is enabled we emit extra code in Jump.
-  if (FLAG_debug_code) return;
-
-  MachineOperatorBuilder machine(zone());
-
-  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
-    InterpreterAssemblerForTest m(this, bytecode);
-    Node* lhs = m.IntPtrConstant(0);
-    Node* rhs = m.IntPtrConstant(1);
-    m.JumpIfWordEqual(lhs, rhs, m.IntPtrConstant(kJumpIfTrueOffset));
-    Graph* graph = m.graph();
-    Node* end = graph->end();
-    EXPECT_EQ(2, end->InputCount());
-
-    OperandScale operand_scale = OperandScale::kSingle;
-    int jump_offsets[] = {kJumpIfTrueOffset, interpreter::Bytecodes::Size(
-                                                 bytecode, operand_scale)};
-    for (int i = 0; i < static_cast<int>(arraysize(jump_offsets)); i++) {
-      Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
-          IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
-          IsIntPtrConstant(jump_offsets[i]));
-      Matcher<Node*> target_bytecode_matcher =
-          m.IsLoad(MachineType::Uint8(), _, next_bytecode_offset_matcher);
-      if (kPointerSize == 8) {
-        target_bytecode_matcher =
-            IsChangeUint32ToUint64(target_bytecode_matcher);
-      }
-      Matcher<Node*> code_target_matcher = m.IsLoad(
-          MachineType::Pointer(),
-          IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
-          IsWordShl(target_bytecode_matcher,
-                    IsIntPtrConstant(kPointerSizeLog2)));
-      EXPECT_THAT(
-          end->InputAt(i),
-          IsTailCall(
-              _, code_target_matcher,
-              IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
-              IsParameter(
-                  InterpreterDispatchDescriptor::kRegisterFileParameter),
-              next_bytecode_offset_matcher, _,
-              IsParameter(
-                  InterpreterDispatchDescriptor::kDispatchTableParameter),
-              IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
-              _));
-    }
-
-    // TODO(oth): test control flow paths.
-  }
-}
-
-TARGET_TEST_F(InterpreterAssemblerTest, InterpreterReturn) {
-  // If debug code is enabled we emit extra code in InterpreterReturn.
-  if (FLAG_debug_code) return;
-
-  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
-    InterpreterAssemblerForTest m(this, bytecode);
-    m.InterpreterReturn();
-    Graph* graph = m.graph();
-
-    Node* end = graph->end();
-    EXPECT_EQ(1, end->InputCount());
-    Node* tail_call_node = end->InputAt(0);
-
-    Handle<HeapObject> exit_trampoline =
-        isolate()->builtins()->InterpreterExitTrampoline();
-    EXPECT_THAT(
-        tail_call_node,
-        IsTailCall(
-            _, IsHeapConstant(exit_trampoline),
-            IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
-            IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
-            IsParameter(
-                InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
-            _,
-            IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
-            IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
-            _));
-  }
-}
-
 TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
   static const OperandScale kOperandScales[] = {
       OperandScale::kSingle, OperandScale::kDouble, OperandScale::kQuadruple};
@@ -525,6 +428,10 @@
             EXPECT_THAT(m.BytecodeOperandRuntimeId(i),
                         m.IsUnsignedOperand(offset, operand_size));
             break;
+          case interpreter::OperandType::kIntrinsicId:
+            EXPECT_THAT(m.BytecodeOperandIntrinsicId(i),
+                        m.IsUnsignedOperand(offset, operand_size));
+            break;
           case interpreter::OperandType::kNone:
             UNREACHABLE();
             break;
@@ -555,24 +462,21 @@
     EXPECT_THAT(m.GetAccumulator(), accumulator_value_2);
 
     // Should be passed to next bytecode handler on dispatch.
-    m.Dispatch();
-    Graph* graph = m.graph();
-
-    Node* end = graph->end();
-    EXPECT_EQ(1, end->InputCount());
-    Node* tail_call_node = end->InputAt(0);
+    Node* tail_call_node = m.Dispatch();
 
     EXPECT_THAT(tail_call_node,
-                IsTailCall(_, _, accumulator_value_2, _, _, _, _, _, _));
+                IsTailCall(_, _, accumulator_value_2, _, _, _, _));
   }
 }
 
-TARGET_TEST_F(InterpreterAssemblerTest, GetSetContext) {
+TARGET_TEST_F(InterpreterAssemblerTest, GetContext) {
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
-    Node* context_node = m.Int32Constant(100);
-    m.SetContext(context_node);
-    EXPECT_THAT(m.GetContext(), context_node);
+    EXPECT_THAT(
+        m.GetContext(),
+        m.IsLoad(MachineType::AnyTagged(), IsLoadParentFramePointer(),
+                 IsIntPtrConstant(Register::current_context().ToOperand()
+                                  << kPointerSizeLog2)));
   }
 }
 
@@ -581,11 +485,10 @@
     InterpreterAssemblerForTest m(this, bytecode);
     Node* reg_index_node = m.IntPtrConstant(44);
     Node* reg_location_node = m.RegisterLocation(reg_index_node);
-    EXPECT_THAT(
-        reg_location_node,
-        IsIntPtrAdd(
-            IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
-            IsWordShl(reg_index_node, IsIntPtrConstant(kPointerSizeLog2))));
+    EXPECT_THAT(reg_location_node,
+                IsIntPtrAdd(IsLoadParentFramePointer(),
+                            IsWordShl(reg_index_node,
+                                      IsIntPtrConstant(kPointerSizeLog2))));
   }
 }
 
@@ -594,12 +497,10 @@
     InterpreterAssemblerForTest m(this, bytecode);
     Node* reg_index_node = m.IntPtrConstant(44);
     Node* load_reg_node = m.LoadRegister(reg_index_node);
-    EXPECT_THAT(
-        load_reg_node,
-        m.IsLoad(
-            MachineType::AnyTagged(),
-            IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
-            IsWordShl(reg_index_node, IsIntPtrConstant(kPointerSizeLog2))));
+    EXPECT_THAT(load_reg_node,
+                m.IsLoad(MachineType::AnyTagged(), IsLoadParentFramePointer(),
+                         IsWordShl(reg_index_node,
+                                   IsIntPtrConstant(kPointerSizeLog2))));
   }
 }
 
@@ -611,12 +512,11 @@
     Node* store_reg_node = m.StoreRegister(store_value, reg_index_node);
     EXPECT_THAT(
         store_reg_node,
-        m.IsStore(
-            StoreRepresentation(MachineRepresentation::kTagged,
-                                kNoWriteBarrier),
-            IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
-            IsWordShl(reg_index_node, IsIntPtrConstant(kPointerSizeLog2)),
-            store_value));
+        m.IsStore(StoreRepresentation(MachineRepresentation::kTagged,
+                                      kNoWriteBarrier),
+                  IsLoadParentFramePointer(),
+                  IsWordShl(reg_index_node, IsIntPtrConstant(kPointerSizeLog2)),
+                  store_value));
   }
 }
 
@@ -624,9 +524,9 @@
   TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
     InterpreterAssemblerForTest m(this, bytecode);
     Node* value = m.Int32Constant(44);
-    EXPECT_THAT(
-        m.SmiTag(value),
-        IsWordShl(value, IsIntPtrConstant(kSmiShiftSize + kSmiTagSize)));
+    EXPECT_THAT(m.SmiTag(value),
+                IsIntPtrConstant(static_cast<intptr_t>(44)
+                                 << (kSmiShiftSize + kSmiTagSize)));
     EXPECT_THAT(
         m.SmiUntag(value),
         IsWordSar(value, IsIntPtrConstant(kSmiShiftSize + kSmiTagSize)));
@@ -730,14 +630,10 @@
     InterpreterAssemblerForTest m(this, bytecode);
     Node* arg1 = m.Int32Constant(2);
     Node* arg2 = m.Int32Constant(3);
-    Node* context =
-        m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
+    Node* context = m.Int32Constant(4);
     Node* call_runtime = m.CallRuntime(Runtime::kAdd, context, arg1, arg2);
-    EXPECT_THAT(
-        call_runtime,
-        IsCall(_, _, arg1, arg2, _, IsInt32Constant(2),
-               IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
-               _));
+    EXPECT_THAT(call_runtime,
+                IsCall(_, _, arg1, arg2, _, IsInt32Constant(2), context, _, _));
   }
 }
 
@@ -751,8 +647,7 @@
       Node* function_id = m.Int32Constant(0);
       Node* first_arg = m.Int32Constant(1);
       Node* arg_count = m.Int32Constant(2);
-      Node* context =
-          m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
+      Node* context = m.Int32Constant(4);
 
       Matcher<Node*> function_table = IsExternalConstant(
           ExternalReference::runtime_function_table_address(isolate()));
@@ -765,12 +660,9 @@
 
       Node* call_runtime = m.CallRuntimeN(function_id, context, first_arg,
                                           arg_count, result_size);
-      EXPECT_THAT(
-          call_runtime,
-          IsCall(_, IsHeapConstant(builtin.code()), arg_count, first_arg,
-                 function_entry,
-                 IsParameter(InterpreterDispatchDescriptor::kContextParameter),
-                 _, _));
+      EXPECT_THAT(call_runtime,
+                  IsCall(_, IsHeapConstant(builtin.code()), arg_count,
+                         first_arg, function_entry, context, _, _));
     }
   }
 }
@@ -786,16 +678,11 @@
       Node* function = m.Int32Constant(0);
       Node* first_arg = m.Int32Constant(1);
       Node* arg_count = m.Int32Constant(2);
-      Node* context =
-          m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
+      Node* context = m.Int32Constant(3);
       Node* call_js =
           m.CallJS(function, context, first_arg, arg_count, tail_call_mode);
-      EXPECT_THAT(
-          call_js,
-          IsCall(_, IsHeapConstant(builtin.code()), arg_count, first_arg,
-                 function,
-                 IsParameter(InterpreterDispatchDescriptor::kContextParameter),
-                 _, _));
+      EXPECT_THAT(call_js, IsCall(_, IsHeapConstant(builtin.code()), arg_count,
+                                  first_arg, function, context, _, _));
     }
   }
 }
@@ -805,21 +692,18 @@
     InterpreterAssemblerForTest m(this, bytecode);
     Node* feedback_vector = m.LoadTypeFeedbackVector();
 
-    Matcher<Node*> load_function_matcher = m.IsLoad(
-        MachineType::AnyTagged(),
-        IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
-        IsIntPtrConstant(
-            InterpreterFrameConstants::kFunctionFromRegisterPointer));
-    Matcher<Node*> load_shared_function_info_matcher =
-        m.IsLoad(MachineType::AnyTagged(), load_function_matcher,
-                 IsIntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
-                                  kHeapObjectTag));
+    Matcher<Node*> load_function_matcher =
+        m.IsLoad(MachineType::AnyTagged(), IsLoadParentFramePointer(),
+                 IsIntPtrConstant(Register::function_closure().ToOperand()
+                                  << kPointerSizeLog2));
+    Matcher<Node*> load_literals_matcher = m.IsLoad(
+        MachineType::AnyTagged(), load_function_matcher,
+        IsIntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag));
 
-    EXPECT_THAT(
-        feedback_vector,
-        m.IsLoad(MachineType::AnyTagged(), load_shared_function_info_matcher,
-                 IsIntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
-                                  kHeapObjectTag)));
+    EXPECT_THAT(feedback_vector,
+                m.IsLoad(MachineType::AnyTagged(), load_literals_matcher,
+                         IsIntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
+                                          kHeapObjectTag)));
   }
 }
 
diff --git a/test/unittests/interpreter/source-position-table-unittest.cc b/test/unittests/interpreter/source-position-table-unittest.cc
index d62302a..87d58fd 100644
--- a/test/unittests/interpreter/source-position-table-unittest.cc
+++ b/test/unittests/interpreter/source-position-table-unittest.cc
@@ -25,7 +25,7 @@
 TEST_F(SourcePositionTableTest, EncodeStatement) {
   SourcePositionTableBuilder builder(isolate(), zone());
   for (int i = 0; i < arraysize(offsets); i++) {
-    builder.AddStatementPosition(offsets[i], offsets[i]);
+    builder.AddPosition(offsets[i], offsets[i], true);
   }
 
   // To test correctness, we rely on the assertions in ToSourcePositionTable().
@@ -36,8 +36,8 @@
 TEST_F(SourcePositionTableTest, EncodeStatementDuplicates) {
   SourcePositionTableBuilder builder(isolate(), zone());
   for (int i = 0; i < arraysize(offsets); i++) {
-    builder.AddStatementPosition(offsets[i], offsets[i]);
-    builder.AddStatementPosition(offsets[i], offsets[i] + 1);
+    builder.AddPosition(offsets[i], offsets[i], true);
+    builder.AddPosition(offsets[i], offsets[i] + 1, true);
   }
 
   // To test correctness, we rely on the assertions in ToSourcePositionTable().
@@ -48,7 +48,7 @@
 TEST_F(SourcePositionTableTest, EncodeExpression) {
   SourcePositionTableBuilder builder(isolate(), zone());
   for (int i = 0; i < arraysize(offsets); i++) {
-    builder.AddExpressionPosition(offsets[i], offsets[i]);
+    builder.AddPosition(offsets[i], offsets[i], false);
   }
   CHECK(!builder.ToSourcePositionTable().is_null());
 }
@@ -56,23 +56,26 @@
 TEST_F(SourcePositionTableTest, EncodeAscending) {
   SourcePositionTableBuilder builder(isolate(), zone());
 
-  int accumulator = 0;
+  int code_offset = 0;
+  int source_position = 0;
   for (int i = 0; i < arraysize(offsets); i++) {
-    accumulator += offsets[i];
+    code_offset += offsets[i];
+    source_position += offsets[i];
     if (i % 2) {
-      builder.AddStatementPosition(accumulator, accumulator);
+      builder.AddPosition(code_offset, source_position, true);
     } else {
-      builder.AddExpressionPosition(accumulator, accumulator);
+      builder.AddPosition(code_offset, source_position, false);
     }
   }
 
-  // Also test negative offsets:
+  // Also test negative offsets for source positions:
   for (int i = 0; i < arraysize(offsets); i++) {
-    accumulator -= offsets[i];
+    code_offset += offsets[i];
+    source_position -= offsets[i];
     if (i % 2) {
-      builder.AddStatementPosition(accumulator, accumulator);
+      builder.AddPosition(code_offset, source_position, true);
     } else {
-      builder.AddExpressionPosition(accumulator, accumulator);
+      builder.AddPosition(code_offset, source_position, false);
     }
   }
 
diff --git a/test/unittests/register-configuration-unittest.cc b/test/unittests/register-configuration-unittest.cc
new file mode 100644
index 0000000..31333ee
--- /dev/null
+++ b/test/unittests/register-configuration-unittest.cc
@@ -0,0 +1,130 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/register-configuration.h"
+#include "testing/gtest-support.h"
+
+namespace v8 {
+namespace internal {
+
+const MachineRepresentation kFloat32 = MachineRepresentation::kFloat32;
+const MachineRepresentation kFloat64 = MachineRepresentation::kFloat64;
+
+class RegisterConfigurationUnitTest : public ::testing::Test {
+ public:
+  RegisterConfigurationUnitTest() {}
+  virtual ~RegisterConfigurationUnitTest() {}
+
+ private:
+};
+
+TEST_F(RegisterConfigurationUnitTest, BasicProperties) {
+  const int kNumGeneralRegs = 3;
+  const int kNumDoubleRegs = 4;
+  const int kNumAllocatableGeneralRegs = 2;
+  const int kNumAllocatableDoubleRegs = 2;
+  int general_codes[kNumAllocatableGeneralRegs] = {1, 2};
+  int double_codes[kNumAllocatableDoubleRegs] = {2, 3};
+
+  RegisterConfiguration test(
+      kNumGeneralRegs, kNumDoubleRegs, kNumAllocatableGeneralRegs,
+      kNumAllocatableDoubleRegs, general_codes, double_codes,
+      RegisterConfiguration::OVERLAP, nullptr, nullptr, nullptr);
+
+  EXPECT_EQ(test.num_general_registers(), kNumGeneralRegs);
+  EXPECT_EQ(test.num_double_registers(), kNumDoubleRegs);
+  EXPECT_EQ(test.num_allocatable_general_registers(),
+            kNumAllocatableGeneralRegs);
+  EXPECT_EQ(test.num_allocatable_double_registers(), kNumAllocatableDoubleRegs);
+  EXPECT_EQ(test.num_allocatable_float_registers(), kNumAllocatableDoubleRegs);
+
+  EXPECT_EQ(test.allocatable_general_codes_mask(),
+            (1 << general_codes[0]) | (1 << general_codes[1]));
+  EXPECT_EQ(test.GetAllocatableGeneralCode(0), general_codes[0]);
+  EXPECT_EQ(test.GetAllocatableGeneralCode(1), general_codes[1]);
+  EXPECT_EQ(test.allocatable_double_codes_mask(),
+            (1 << double_codes[0]) | (1 << double_codes[1]));
+  EXPECT_EQ(test.GetAllocatableDoubleCode(0), double_codes[0]);
+  EXPECT_EQ(test.GetAllocatableDoubleCode(1), double_codes[1]);
+}
+
+TEST_F(RegisterConfigurationUnitTest, Aliasing) {
+  const int kNumGeneralRegs = 3;
+  const int kNumDoubleRegs = 4;
+  const int kNumAllocatableGeneralRegs = 2;
+  const int kNumAllocatableDoubleRegs = 3;
+  int general_codes[] = {1, 2};
+  int double_codes[] = {2, 3, 16};  // reg 16 should not alias registers 32, 33.
+
+  RegisterConfiguration test(
+      kNumGeneralRegs, kNumDoubleRegs, kNumAllocatableGeneralRegs,
+      kNumAllocatableDoubleRegs, general_codes, double_codes,
+      RegisterConfiguration::COMBINE, nullptr, nullptr, nullptr);
+
+  // There are 3 allocatable double regs, but only 2 can alias float regs.
+  EXPECT_EQ(test.num_allocatable_float_registers(), 4);
+
+  // Test that float registers combine in pairs to form double registers.
+  EXPECT_EQ(test.GetAllocatableFloatCode(0), double_codes[0] * 2);
+  EXPECT_EQ(test.GetAllocatableFloatCode(1), double_codes[0] * 2 + 1);
+  EXPECT_EQ(test.GetAllocatableFloatCode(2), double_codes[1] * 2);
+  EXPECT_EQ(test.GetAllocatableFloatCode(3), double_codes[1] * 2 + 1);
+
+  // Registers alias themselves.
+  EXPECT_TRUE(test.AreAliases(kFloat32, 0, kFloat32, 0));
+  EXPECT_TRUE(test.AreAliases(kFloat64, 0, kFloat64, 0));
+  // Registers don't alias other registers of the same size.
+  EXPECT_FALSE(test.AreAliases(kFloat32, 1, kFloat32, 0));
+  EXPECT_FALSE(test.AreAliases(kFloat64, 1, kFloat64, 0));
+  // Float registers combine in pairs and alias double registers.
+  EXPECT_TRUE(test.AreAliases(kFloat32, 0, kFloat64, 0));
+  EXPECT_TRUE(test.AreAliases(kFloat32, 1, kFloat64, 0));
+  EXPECT_TRUE(test.AreAliases(kFloat64, 0, kFloat32, 0));
+  EXPECT_TRUE(test.AreAliases(kFloat64, 0, kFloat32, 1));
+
+  EXPECT_FALSE(test.AreAliases(kFloat32, 0, kFloat64, 1));
+  EXPECT_FALSE(test.AreAliases(kFloat32, 1, kFloat64, 1));
+
+  EXPECT_TRUE(test.AreAliases(kFloat64, 0, kFloat32, 1));
+  EXPECT_TRUE(test.AreAliases(kFloat64, 1, kFloat32, 2));
+  EXPECT_TRUE(test.AreAliases(kFloat64, 1, kFloat32, 3));
+  EXPECT_TRUE(test.AreAliases(kFloat64, 2, kFloat32, 4));
+  EXPECT_TRUE(test.AreAliases(kFloat64, 2, kFloat32, 5));
+
+  int alias_base_index = -1;
+  EXPECT_EQ(test.GetAliases(kFloat32, 0, kFloat32, &alias_base_index), 1);
+  EXPECT_EQ(alias_base_index, 0);
+  EXPECT_EQ(test.GetAliases(kFloat64, 1, kFloat64, &alias_base_index), 1);
+  EXPECT_EQ(alias_base_index, 1);
+  EXPECT_EQ(test.GetAliases(kFloat32, 0, kFloat64, &alias_base_index), 1);
+  EXPECT_EQ(alias_base_index, 0);
+  EXPECT_EQ(test.GetAliases(kFloat32, 1, kFloat64, &alias_base_index), 1);
+  EXPECT_EQ(test.GetAliases(kFloat32, 2, kFloat64, &alias_base_index), 1);
+  EXPECT_EQ(alias_base_index, 1);
+  EXPECT_EQ(test.GetAliases(kFloat32, 3, kFloat64, &alias_base_index), 1);
+  EXPECT_EQ(alias_base_index, 1);
+  EXPECT_EQ(test.GetAliases(kFloat64, 0, kFloat32, &alias_base_index), 2);
+  EXPECT_EQ(alias_base_index, 0);
+  EXPECT_EQ(test.GetAliases(kFloat64, 1, kFloat32, &alias_base_index), 2);
+  EXPECT_EQ(alias_base_index, 2);
+
+  // Non-allocatable codes still alias.
+  EXPECT_EQ(test.GetAliases(kFloat64, 2, kFloat32, &alias_base_index), 2);
+  EXPECT_EQ(alias_base_index, 4);
+  // High numbered double registers don't alias nonexistent single registers.
+  EXPECT_EQ(
+      test.GetAliases(kFloat64, RegisterConfiguration::kMaxFPRegisters / 2,
+                      kFloat32, &alias_base_index),
+      0);
+  EXPECT_EQ(
+      test.GetAliases(kFloat64, RegisterConfiguration::kMaxFPRegisters / 2 + 1,
+                      kFloat32, &alias_base_index),
+      0);
+  EXPECT_EQ(test.GetAliases(kFloat64, RegisterConfiguration::kMaxFPRegisters,
+                            kFloat32, &alias_base_index),
+            0);
+}
+
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/unittests.gyp b/test/unittests/unittests.gyp
index 003281b..d5ba353 100644
--- a/test/unittests/unittests.gyp
+++ b/test/unittests/unittests.gyp
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+# Please keep this file in sync with BUILD.gn.
+
 {
   'variables': {
     'v8_code': 1,
   },
-  'includes': ['../../build/toolchain.gypi', '../../build/features.gypi'],
+  'includes': ['../../gypfiles/toolchain.gypi', '../../gypfiles/features.gypi'],
   'targets': [
     {
       'target_name': 'unittests',
@@ -17,18 +19,19 @@
       'dependencies': [
         '../../testing/gmock.gyp:gmock',
         '../../testing/gtest.gyp:gtest',
-        '../../tools/gyp/v8.gyp:v8_libplatform',
+        '../../src/v8.gyp:v8_libplatform',
       ],
       'include_dirs': [
         '../..',
       ],
       'sources': [  ### gcmole(all) ###
-        'atomic-utils-unittest.cc',
+        'base/atomic-utils-unittest.cc',
         'base/bits-unittest.cc',
         'base/cpu-unittest.cc',
         'base/division-by-constant-unittest.cc',
         'base/flags-unittest.cc',
         'base/functional-unittest.cc',
+        'base/ieee754-unittest.cc',
         'base/logging-unittest.cc',
         'base/iterator-unittest.cc',
         'base/platform/condition-variable-unittest.cc',
@@ -41,8 +44,7 @@
         'cancelable-tasks-unittest.cc',
         'char-predicates-unittest.cc',
         'compiler/branch-elimination-unittest.cc',
-        'compiler/change-lowering-unittest.cc',
-        'compiler/coalesced-live-ranges-unittest.cc',
+        'compiler/checkpoint-elimination-unittest.cc',
         'compiler/common-operator-reducer-unittest.cc',
         'compiler/common-operator-unittest.cc',
         'compiler/compiler-test-utils.h',
@@ -50,6 +52,7 @@
         'compiler/control-flow-optimizer-unittest.cc',
         'compiler/dead-code-elimination-unittest.cc',
         'compiler/diamond-unittest.cc',
+        'compiler/effect-control-linearizer-unittest.cc',
         'compiler/escape-analysis-unittest.cc',
         'compiler/graph-reducer-unittest.cc',
         'compiler/graph-reducer-unittest.h',
@@ -96,7 +99,12 @@
         'interpreter/bytecodes-unittest.cc',
         'interpreter/bytecode-array-builder-unittest.cc',
         'interpreter/bytecode-array-iterator-unittest.cc',
+        'interpreter/bytecode-array-writer-unittest.cc',
+        'interpreter/bytecode-dead-code-optimizer-unittest.cc',
+        'interpreter/bytecode-peephole-optimizer-unittest.cc',
+        'interpreter/bytecode-pipeline-unittest.cc',
         'interpreter/bytecode-register-allocator-unittest.cc',
+        'interpreter/bytecode-register-optimizer-unittest.cc',
         'interpreter/constant-array-builder-unittest.cc',
         'interpreter/interpreter-assembler-unittest.cc',
         'interpreter/interpreter-assembler-unittest.h',
@@ -112,14 +120,19 @@
         'heap/scavenge-job-unittest.cc',
         'heap/slot-set-unittest.cc',
         'locked-queue-unittest.cc',
+        'register-configuration-unittest.cc',
         'run-all-unittests.cc',
         'test-utils.h',
         'test-utils.cc',
+        'wasm/asm-types-unittest.cc',
         'wasm/ast-decoder-unittest.cc',
+        'wasm/control-transfer-unittest.cc',
         'wasm/decoder-unittest.cc',
         'wasm/encoder-unittest.cc',
+        'wasm/leb-helper-unittest.cc',
         'wasm/loop-assignment-analysis-unittest.cc',
         'wasm/module-decoder-unittest.cc',
+        'wasm/switch-logic-unittest.cc',
         'wasm/wasm-macro-gen-unittest.cc',
       ],
       'conditions': [
@@ -138,11 +151,21 @@
             'compiler/ia32/instruction-selector-ia32-unittest.cc',
           ],
         }],
+        ['v8_target_arch=="mips"', {
+          'sources': [  ### gcmole(arch:mips) ###
+            'compiler/mips/instruction-selector-mips-unittest.cc',
+          ],
+        }],
         ['v8_target_arch=="mipsel"', {
           'sources': [  ### gcmole(arch:mipsel) ###
             'compiler/mips/instruction-selector-mips-unittest.cc',
           ],
         }],
+        ['v8_target_arch=="mips64"', {
+          'sources': [  ### gcmole(arch:mips64) ###
+            'compiler/mips64/instruction-selector-mips64-unittest.cc',
+          ],
+        }],
         ['v8_target_arch=="mips64el"', {
           'sources': [  ### gcmole(arch:mips64el) ###
             'compiler/mips64/instruction-selector-mips64-unittest.cc',
@@ -169,9 +192,9 @@
         ['component=="shared_library"', {
           # compiler-unittests can't be built against a shared library, so we
           # need to depend on the underlying static target in that case.
-          'dependencies': ['../../tools/gyp/v8.gyp:v8_maybe_snapshot'],
+          'dependencies': ['../../src/v8.gyp:v8_maybe_snapshot'],
         }, {
-          'dependencies': ['../../tools/gyp/v8.gyp:v8'],
+          'dependencies': ['../../src/v8.gyp:v8'],
         }],
         ['os_posix == 1', {
           # TODO(svenpanne): This is a temporary work-around to fix the warnings
@@ -198,7 +221,7 @@
             'unittests',
           ],
           'includes': [
-            '../../build/isolate.gypi',
+            '../../gypfiles/isolate.gypi',
           ],
           'sources': [
             'unittests.isolate',
diff --git a/test/unittests/unittests.status b/test/unittests/unittests.status
index 40b5754..6d67439 100644
--- a/test/unittests/unittests.status
+++ b/test/unittests/unittests.status
@@ -11,6 +11,10 @@
   'WasmDecoderTest.AllLoadMemCombinations': [SKIP],
   'AstDecoderTest.AllLoadMemCombinations': [SKIP],
   'AstDecoderTest.AllStoreMemCombinations': [SKIP],
-  'Bytecodes.DecodeBytecodeAndOperands': [SKIP],
 }],  # 'byteorder == big'
+['arch == x87', {
+  'Ieee754.Expm1': [SKIP],
+  'Ieee754.Cos': [SKIP],
+  'Ieee754.Tan': [SKIP],
+}],  # 'arch == x87'
 ]
diff --git a/test/unittests/wasm/asm-types-unittest.cc b/test/unittests/wasm/asm-types-unittest.cc
new file mode 100644
index 0000000..9b29362
--- /dev/null
+++ b/test/unittests/wasm/asm-types-unittest.cc
@@ -0,0 +1,729 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/wasm/asm-types.h"
+
+#include <unordered_map>
+#include <unordered_set>
+
+#include "src/base/macros.h"
+#include "test/unittests/test-utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+namespace {
+
+using ::testing::StrEq;
+
+class AsmTypeTest : public TestWithZone {
+ public:
+  using Type = AsmType;
+
+  AsmTypeTest()
+      : parents_({
+            {Type::Uint8Array(), {Type::Heap()}},
+            {Type::Int8Array(), {Type::Heap()}},
+            {Type::Uint16Array(), {Type::Heap()}},
+            {Type::Int16Array(), {Type::Heap()}},
+            {Type::Uint32Array(), {Type::Heap()}},
+            {Type::Int32Array(), {Type::Heap()}},
+            {Type::Float32Array(), {Type::Heap()}},
+            {Type::Float64Array(), {Type::Heap()}},
+            {Type::FloatishDoubleQ(), {Type::Floatish(), Type::DoubleQ()}},
+            {Type::FloatQDoubleQ(),
+             {Type::FloatQ(), Type::Floatish(), Type::DoubleQ()}},
+            {Type::Float(), {Type::FloatQ(), Type::Floatish()}},
+            {Type::FloatQ(), {Type::Floatish()}},
+            {Type::FixNum(),
+             {Type::Signed(), Type::Extern(), Type::Unsigned(), Type::Int(),
+              Type::Intish()}},
+            {Type::Unsigned(), {Type::Int(), Type::Intish()}},
+            {Type::Signed(), {Type::Extern(), Type::Int(), Type::Intish()}},
+            {Type::Int(), {Type::Intish()}},
+            {Type::Double(), {Type::DoubleQ(), Type::Extern()}},
+        }) {}
+
+ protected:
+  std::unordered_set<Type*> ParentsOf(Type* derived) const {
+    const auto parents_iter = parents_.find(derived);
+    if (parents_iter == parents_.end()) {
+      return std::unordered_set<Type*>();
+    }
+    return parents_iter->second;
+  }
+
+  class FunctionTypeBuilder {
+   public:
+    FunctionTypeBuilder(FunctionTypeBuilder&& b)
+        : function_type_(b.function_type_) {
+      b.function_type_ = nullptr;
+    }
+
+    FunctionTypeBuilder& operator=(FunctionTypeBuilder&& b) {
+      if (this != &b) {
+        function_type_ = b.function_type_;
+        b.function_type_ = nullptr;
+      }
+      return *this;
+    }
+
+    FunctionTypeBuilder(Zone* zone, Type* return_type)
+        : function_type_(Type::Function(zone, return_type)) {}
+
+   private:
+    static void AddAllArguments(AsmFunctionType*) {}
+
+    template <typename Arg, typename... Others>
+    static void AddAllArguments(AsmFunctionType* function_type, Arg* arg,
+                                Others... others) {
+      CHECK(function_type != nullptr);
+      function_type->AddArgument((*arg)());
+      AddAllArguments(function_type, others...);
+    }
+
+   public:
+    template <typename... Args>
+    Type* operator()(Args... args) {
+      Type* ret = function_type_;
+      function_type_ = nullptr;
+      AddAllArguments(ret->AsFunctionType(), args...);
+      return ret;
+    }
+
+   private:
+    Type* function_type_;
+  };
+
+  FunctionTypeBuilder Function(Type* (*return_type)()) {
+    return FunctionTypeBuilder(zone(), (*return_type)());
+  }
+
+  template <typename... Overloads>
+  Type* Overload(Overloads... overloads) {
+    auto* ret = Type::OverloadedFunction(zone());
+    AddAllOverloads(ret->AsOverloadedFunctionType(), overloads...);
+    return ret;
+  }
+
+ private:
+  static void AddAllOverloads(AsmOverloadedFunctionType*) {}
+
+  template <typename Overload, typename... Others>
+  static void AddAllOverloads(AsmOverloadedFunctionType* function,
+                              Overload* overload, Others... others) {
+    CHECK(function != nullptr);
+    function->AddOverload(overload);
+    AddAllOverloads(function, others...);
+  }
+
+  const std::unordered_map<Type*, std::unordered_set<Type*>> parents_;
+};
+
+// AsmValueTypeParents expose the bitmasks for the parents for each value type
+// in asm's type system. It inherits from AsmValueType so that the kAsm<Foo>
+// members are available when expanding the FOR_EACH_ASM_VALUE_TYPE_LIST macro.
+class AsmValueTypeParents : private AsmValueType {
+ public:
+  enum : uint32_t {
+#define V(CamelName, string_name, number, parent_types) \
+  CamelName = parent_types,
+    FOR_EACH_ASM_VALUE_TYPE_LIST(V)
+#undef V
+  };
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(AsmValueTypeParents);
+};
+
+TEST_F(AsmTypeTest, ValidateBits) {
+  // Generic validation tests for the bits in the type system's type
+  // definitions.
+
+  std::unordered_set<Type*> seen_types;
+  std::unordered_set<uint32_t> seen_numbers;
+  uint32_t total_types = 0;
+#define V(CamelName, string_name, number, parent_types)                      \
+  do {                                                                       \
+    ++total_types;                                                           \
+    if (AsmValueTypeParents::CamelName != 0) {                               \
+      EXPECT_NE(0, ParentsOf(AsmType::CamelName()).size()) << #CamelName;    \
+    }                                                                        \
+    seen_types.insert(Type::CamelName());                                    \
+    seen_numbers.insert(number);                                             \
+    /* Every ASM type must have a valid number. */                           \
+    EXPECT_NE(0, number) << Type::CamelName()->Name();                       \
+    /* Inheritance cycles - unlikely, but we're paranoid and check for it */ \
+    /* anyways.*/                                                            \
+    EXPECT_EQ(0, (1 << (number)) & AsmValueTypeParents::CamelName);          \
+  } while (0);
+  FOR_EACH_ASM_VALUE_TYPE_LIST(V)
+#undef V
+
+  // At least one type was expanded.
+  EXPECT_GT(total_types, 0u);
+
+  // Each value type is unique.
+  EXPECT_EQ(total_types, seen_types.size());
+
+  // Each number is unique.
+  EXPECT_EQ(total_types, seen_numbers.size());
+}
+
+TEST_F(AsmTypeTest, SaneParentsMap) {
+  // This test ensures our parents map contains all the parents types that are
+  // specified in the types' declaration. It does not report bogus inheritance.
+
+  // Handy-dandy lambda for counting bits. Code borrowed from stack overflow.
+  auto NumberOfSetBits = [](uintptr_t parent_mask) -> uint32_t {
+    uint32_t parent_mask32 = static_cast<uint32_t>(parent_mask);
+    CHECK_EQ(parent_mask, parent_mask32);
+    parent_mask32 = parent_mask32 - ((parent_mask32 >> 1) & 0x55555555);
+    parent_mask32 =
+        (parent_mask32 & 0x33333333) + ((parent_mask32 >> 2) & 0x33333333);
+    return (((parent_mask32 + (parent_mask32 >> 4)) & 0x0F0F0F0F) *
+            0x01010101) >>
+           24;
+  };
+
+#define V(CamelName, string_name, number, parent_types)                    \
+  do {                                                                     \
+    const uintptr_t parents =                                              \
+        reinterpret_cast<uintptr_t>(Type::CamelName()) & ~(1 << (number)); \
+    EXPECT_EQ(NumberOfSetBits(parents),                                    \
+              1 + ParentsOf(Type::CamelName()).size())                     \
+        << Type::CamelName()->Name() << ", parents "                       \
+        << reinterpret_cast<void*>(parents) << ", type "                   \
+        << static_cast<void*>(Type::CamelName());                          \
+  } while (0);
+  FOR_EACH_ASM_VALUE_TYPE_LIST(V)
+#undef V
+}
+
+TEST_F(AsmTypeTest, Names) {
+#define V(CamelName, string_name, number, parent_types)         \
+  do {                                                          \
+    EXPECT_THAT(Type::CamelName()->Name(), StrEq(string_name)); \
+  } while (0);
+  FOR_EACH_ASM_VALUE_TYPE_LIST(V)
+#undef V
+
+  EXPECT_THAT(Function(Type::Int)(Type::Double, Type::Float)->Name(),
+              StrEq("(double, float) -> int"));
+
+  EXPECT_THAT(Overload(Function(Type::Int)(Type::Double, Type::Float),
+                       Function(Type::Int)(Type::Int))
+                  ->Name(),
+              StrEq("(double, float) -> int /\\ (int) -> int"));
+
+  EXPECT_THAT(Type::FroundType(zone())->Name(), StrEq("fround"));
+
+  EXPECT_THAT(Type::MinMaxType(zone(), Type::Signed(), Type::Int())->Name(),
+              StrEq("(int, int...) -> signed"));
+  EXPECT_THAT(Type::MinMaxType(zone(), Type::Float(), Type::Floatish())->Name(),
+              StrEq("(floatish, floatish...) -> float"));
+  EXPECT_THAT(Type::MinMaxType(zone(), Type::Double(), Type::DoubleQ())->Name(),
+              StrEq("(double?, double?...) -> double"));
+
+  EXPECT_THAT(Type::FFIType(zone())->Name(), StrEq("Function"));
+
+  auto* ft =
+      Type::FunctionTableType(zone(), 15, Function(Type::Double)(Type::Int));
+  EXPECT_THAT(ft->Name(), StrEq("(int) -> double[15]"));
+}
+
+TEST_F(AsmTypeTest, IsExactly) {
+  Type* test_types[] = {
+#define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(),
+      FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE)
+#undef CREATE
+          Function(Type::Int)(Type::Double),
+      Function(Type::Int)(Type::DoubleQ),
+      Overload(Function(Type::Int)(Type::Double)),
+      Function(Type::Int)(Type::Int, Type::Int),
+      Type::MinMaxType(zone(), Type::Signed(), Type::Int()),
+      Function(Type::Int)(Type::Float), Type::FroundType(zone()),
+      Type::FFIType(zone()),
+      Type::FunctionTableType(zone(), 10, Function(Type::Void)()),
+  };
+
+  for (size_t ii = 0; ii < arraysize(test_types); ++ii) {
+    for (size_t jj = 0; jj < arraysize(test_types); ++jj) {
+      EXPECT_EQ(ii == jj, test_types[ii]->IsExactly(test_types[jj]))
+          << test_types[ii]->Name()
+          << ((ii == jj) ? " is not exactly " : " is exactly ")
+          << test_types[jj]->Name();
+    }
+  }
+}
+
+TEST_F(AsmTypeTest, IsA) {
+  Type* test_types[] = {
+#define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(),
+      FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE)
+#undef CREATE
+          Function(Type::Int)(Type::Double),
+      Function(Type::Int)(Type::DoubleQ),
+      Overload(Function(Type::Int)(Type::Double)),
+      Function(Type::Int)(Type::Int, Type::Int),
+      Type::MinMaxType(zone(), Type::Signed(), Type::Int()),
+      Function(Type::Int)(Type::Float), Type::FroundType(zone()),
+      Type::FFIType(zone()),
+      Type::FunctionTableType(zone(), 10, Function(Type::Void)()),
+  };
+
+  for (size_t ii = 0; ii < arraysize(test_types); ++ii) {
+    for (size_t jj = 0; jj < arraysize(test_types); ++jj) {
+      const bool Expected =
+          (ii == jj) || ParentsOf(test_types[ii]).count(test_types[jj]) != 0;
+      EXPECT_EQ(Expected, test_types[ii]->IsA(test_types[jj]))
+          << test_types[ii]->Name() << (Expected ? " is not a " : " is a ")
+          << test_types[jj]->Name();
+    }
+  }
+}
+
+TEST_F(AsmTypeTest, ValidateCall) {
+  auto* min_max_int = Type::MinMaxType(zone(), Type::Signed(), Type::Int());
+  auto* i2s = Function(Type::Signed)(Type::Int);
+  auto* ii2s = Function(Type::Signed)(Type::Int, Type::Int);
+  auto* iii2s = Function(Type::Signed)(Type::Int, Type::Int, Type::Int);
+  auto* iiii2s =
+      Function(Type::Signed)(Type::Int, Type::Int, Type::Int, Type::Int);
+
+  EXPECT_EQ(Type::Signed(), min_max_int->AsCallableType()->ValidateCall(
+                                min_max_int->AsFunctionType()->ReturnType(),
+                                min_max_int->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Signed(), min_max_int->AsCallableType()->ValidateCall(
+                                ii2s->AsFunctionType()->ReturnType(),
+                                ii2s->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Signed(), min_max_int->AsCallableType()->ValidateCall(
+                                iii2s->AsFunctionType()->ReturnType(),
+                                iii2s->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Signed(), min_max_int->AsCallableType()->ValidateCall(
+                                iiii2s->AsFunctionType()->ReturnType(),
+                                iiii2s->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::None(), min_max_int->AsCallableType()->ValidateCall(
+                              i2s->AsFunctionType()->ReturnType(),
+                              i2s->AsFunctionType()->Arguments()));
+
+  auto* min_max_double =
+      Type::MinMaxType(zone(), Type::Double(), Type::Double());
+  auto* d2d = Function(Type::Double)(Type::Double);
+  auto* dd2d = Function(Type::Double)(Type::Double, Type::Double);
+  auto* ddd2d =
+      Function(Type::Double)(Type::Double, Type::Double, Type::Double);
+  auto* dddd2d = Function(Type::Double)(Type::Double, Type::Double,
+                                        Type::Double, Type::Double);
+  EXPECT_EQ(Type::Double(), min_max_double->AsCallableType()->ValidateCall(
+                                min_max_double->AsFunctionType()->ReturnType(),
+                                min_max_double->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Double(), min_max_double->AsCallableType()->ValidateCall(
+                                dd2d->AsFunctionType()->ReturnType(),
+                                dd2d->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Double(), min_max_double->AsCallableType()->ValidateCall(
+                                ddd2d->AsFunctionType()->ReturnType(),
+                                ddd2d->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Double(), min_max_double->AsCallableType()->ValidateCall(
+                                dddd2d->AsFunctionType()->ReturnType(),
+                                dddd2d->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::None(), min_max_double->AsCallableType()->ValidateCall(
+                              d2d->AsFunctionType()->ReturnType(),
+                              d2d->AsFunctionType()->Arguments()));
+
+  auto* min_max = Overload(min_max_int, min_max_double);
+  EXPECT_EQ(Type::None(), min_max->AsCallableType()->ValidateCall(
+                              i2s->AsFunctionType()->ReturnType(),
+                              i2s->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::None(), min_max->AsCallableType()->ValidateCall(
+                              d2d->AsFunctionType()->ReturnType(),
+                              d2d->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Signed(), min_max->AsCallableType()->ValidateCall(
+                                min_max_int->AsFunctionType()->ReturnType(),
+                                min_max_int->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Signed(), min_max->AsCallableType()->ValidateCall(
+                                ii2s->AsFunctionType()->ReturnType(),
+                                ii2s->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Signed(), min_max->AsCallableType()->ValidateCall(
+                                iii2s->AsFunctionType()->ReturnType(),
+                                iii2s->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Signed(), min_max->AsCallableType()->ValidateCall(
+                                iiii2s->AsFunctionType()->ReturnType(),
+                                iiii2s->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Double(), min_max->AsCallableType()->ValidateCall(
+                                min_max_double->AsFunctionType()->ReturnType(),
+                                min_max_double->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Double(), min_max->AsCallableType()->ValidateCall(
+                                dd2d->AsFunctionType()->ReturnType(),
+                                dd2d->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Double(), min_max->AsCallableType()->ValidateCall(
+                                ddd2d->AsFunctionType()->ReturnType(),
+                                ddd2d->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Double(), min_max->AsCallableType()->ValidateCall(
+                                dddd2d->AsFunctionType()->ReturnType(),
+                                dddd2d->AsFunctionType()->Arguments()));
+
+  auto* fround = Type::FroundType(zone());
+
+  ZoneVector<AsmType*> arg(zone());
+  arg.push_back(Type::Floatish());
+  EXPECT_EQ(Type::Float(),
+            fround->AsCallableType()->ValidateCall(Type::Float(), arg));
+  arg.clear();
+  arg.push_back(Type::FloatQ());
+  EXPECT_EQ(Type::Float(),
+            fround->AsCallableType()->ValidateCall(Type::Float(), arg));
+  arg.clear();
+  arg.push_back(Type::Float());
+  EXPECT_EQ(Type::Float(),
+            fround->AsCallableType()->ValidateCall(Type::Float(), arg));
+  arg.clear();
+  arg.push_back(Type::DoubleQ());
+  EXPECT_EQ(Type::Float(),
+            fround->AsCallableType()->ValidateCall(Type::Float(), arg));
+  arg.clear();
+  arg.push_back(Type::Double());
+  EXPECT_EQ(Type::Float(),
+            fround->AsCallableType()->ValidateCall(Type::Float(), arg));
+  arg.clear();
+  arg.push_back(Type::Signed());
+  EXPECT_EQ(Type::Float(),
+            fround->AsCallableType()->ValidateCall(Type::Float(), arg));
+  arg.clear();
+  arg.push_back(Type::Unsigned());
+  EXPECT_EQ(Type::Float(),
+            fround->AsCallableType()->ValidateCall(Type::Float(), arg));
+  arg.clear();
+  arg.push_back(Type::FixNum());
+  EXPECT_EQ(Type::Float(),
+            fround->AsCallableType()->ValidateCall(Type::Float(), arg));
+
+  auto* idf2v = Function(Type::Void)(Type::Int, Type::Double, Type::Float);
+  auto* i2d = Function(Type::Double)(Type::Int);
+  auto* i2f = Function(Type::Float)(Type::Int);
+  auto* fi2d = Function(Type::Double)(Type::Float, Type::Int);
+  auto* idif2i =
+      Function(Type::Int)(Type::Int, Type::Double, Type::Int, Type::Float);
+  auto* overload = Overload(idf2v, i2f, /*i2d missing, */ fi2d, idif2i);
+  EXPECT_EQ(Type::Void(), overload->AsCallableType()->ValidateCall(
+                              idf2v->AsFunctionType()->ReturnType(),
+                              idf2v->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Float(), overload->AsCallableType()->ValidateCall(
+                               i2f->AsFunctionType()->ReturnType(),
+                               i2f->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Double(), overload->AsCallableType()->ValidateCall(
+                                fi2d->AsFunctionType()->ReturnType(),
+                                fi2d->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::Int(), overload->AsCallableType()->ValidateCall(
+                             idif2i->AsFunctionType()->ReturnType(),
+                             idif2i->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::None(), overload->AsCallableType()->ValidateCall(
+                              i2d->AsFunctionType()->ReturnType(),
+                              i2d->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::None(), i2f->AsCallableType()->ValidateCall(
+                              i2d->AsFunctionType()->ReturnType(),
+                              i2d->AsFunctionType()->Arguments()));
+
+  auto* ffi = Type::FFIType(zone());
+  AsmType* (*kReturnTypes[])() = {
+      Type::Void, Type::Double, Type::Signed,
+  };
+  AsmType* (*kParameterTypes[])() = {
+      Type::Double, Type::Signed, Type::FixNum,
+  };
+  for (size_t ii = 0; ii < arraysize(kReturnTypes); ++ii) {
+    for (size_t jj = 0; jj < arraysize(kParameterTypes); ++jj) {
+      auto* f = Function(kReturnTypes[ii])(kParameterTypes[jj]);
+      EXPECT_EQ(kReturnTypes[ii](), ffi->AsCallableType()->ValidateCall(
+                                        f->AsFunctionType()->ReturnType(),
+                                        f->AsFunctionType()->Arguments()))
+          << kReturnTypes[ii]()->Name();
+
+      // Call with non-parameter type type should fail.
+      f = Function(kReturnTypes[ii])(kParameterTypes[jj], Type::Int);
+      EXPECT_EQ(Type::None(), ffi->AsCallableType()->ValidateCall(
+                                  f->AsFunctionType()->ReturnType(),
+                                  f->AsFunctionType()->Arguments()))
+          << kReturnTypes[ii]()->Name();
+    }
+  }
+
+  auto* ft0 = Type::FunctionTableType(zone(), 10, fi2d);
+  EXPECT_EQ(Type::Double(), ft0->AsCallableType()->ValidateCall(
+                                fi2d->AsFunctionType()->ReturnType(),
+                                fi2d->AsFunctionType()->Arguments()));
+  EXPECT_EQ(Type::None(), ft0->AsCallableType()->ValidateCall(
+                              i2d->AsFunctionType()->ReturnType(),
+                              i2d->AsFunctionType()->Arguments()));
+}
+
+TEST_F(AsmTypeTest, ToReturnType) {
+  std::unordered_map<AsmType*, AsmType*> kToReturnType = {
+      {Type::Signed(), Type::Signed()}, {Type::FixNum(), Type::Signed()},
+      {Type::Double(), Type::Double()}, {Type::Float(), Type::Float()},
+      {Type::Void(), Type::Void()},
+  };
+
+  Type* test_types[] = {
+#define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(),
+      FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE)
+#undef CREATE
+          Function(Type::Int)(Type::Double),
+      Function(Type::Int)(Type::DoubleQ),
+      Overload(Function(Type::Int)(Type::Double)),
+      Function(Type::Int)(Type::Int, Type::Int),
+      Type::MinMaxType(zone(), Type::Signed(), Type::Int()),
+      Function(Type::Int)(Type::Float), Type::FroundType(zone()),
+      Type::FFIType(zone()),
+      Type::FunctionTableType(zone(), 10, Function(Type::Void)()),
+  };
+
+  for (size_t ii = 0; ii < arraysize(test_types); ++ii) {
+    auto* return_type = Type::None();
+    auto to_return_type_iter = kToReturnType.find(test_types[ii]);
+    if (to_return_type_iter != kToReturnType.end()) {
+      return_type = to_return_type_iter->second;
+    }
+    EXPECT_EQ(return_type, test_types[ii]->ToReturnType())
+        << return_type->Name() << " != " << test_types[ii]->ToReturnType();
+  }
+}
+
+TEST_F(AsmTypeTest, IsReturnType) {
+  Type* test_types[] = {
+#define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(),
+      FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE)
+#undef CREATE
+          Function(Type::Int)(Type::Double),
+      Function(Type::Int)(Type::DoubleQ),
+      Overload(Function(Type::Int)(Type::Double)),
+      Function(Type::Int)(Type::Int, Type::Int),
+      Type::MinMaxType(zone(), Type::Signed(), Type::Int()),
+      Function(Type::Int)(Type::Float), Type::FroundType(zone()),
+      Type::FFIType(zone()),
+      Type::FunctionTableType(zone(), 10, Function(Type::Void)()),
+  };
+
+  std::unordered_set<Type*> return_types{
+      Type::Double(), Type::Signed(), Type::Float(), Type::Void(),
+  };
+
+  for (size_t ii = 0; ii < arraysize(test_types); ++ii) {
+    const bool IsReturnType = return_types.count(test_types[ii]);
+    EXPECT_EQ(IsReturnType, test_types[ii]->IsReturnType())
+        << test_types[ii]->Name()
+        << (IsReturnType ? " is not a return type" : " is a return type");
+  }
+}
+
+TEST_F(AsmTypeTest, ToParameterType) {
+  std::unordered_map<AsmType*, AsmType*> kToParameterType = {
+      {Type::Int(), Type::Int()},       {Type::Signed(), Type::Int()},
+      {Type::Unsigned(), Type::Int()},  {Type::FixNum(), Type::Int()},
+      {Type::Double(), Type::Double()}, {Type::Float(), Type::Float()},
+  };
+
+  Type* test_types[] = {
+#define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(),
+      FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE)
+#undef CREATE
+          Function(Type::Int)(Type::Double),
+      Function(Type::Int)(Type::DoubleQ),
+      Overload(Function(Type::Int)(Type::Double)),
+      Function(Type::Int)(Type::Int, Type::Int),
+      Type::MinMaxType(zone(), Type::Signed(), Type::Int()),
+      Function(Type::Int)(Type::Float), Type::FroundType(zone()),
+      Type::FFIType(zone()),
+      Type::FunctionTableType(zone(), 10, Function(Type::Void)()),
+  };
+
+  for (size_t ii = 0; ii < arraysize(test_types); ++ii) {
+    auto* parameter_type = Type::None();
+    auto to_parameter_type_iter = kToParameterType.find(test_types[ii]);
+    if (to_parameter_type_iter != kToParameterType.end()) {
+      parameter_type = to_parameter_type_iter->second;
+    }
+    EXPECT_EQ(parameter_type, test_types[ii]->ToParameterType())
+        << parameter_type->Name()
+        << " != " << test_types[ii]->ToParameterType();
+  }
+}
+
+TEST_F(AsmTypeTest, IsParameterType) {
+  Type* test_types[] = {
+#define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(),
+      FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE)
+#undef CREATE
+          Function(Type::Int)(Type::Double),
+      Function(Type::Int)(Type::DoubleQ),
+      Overload(Function(Type::Int)(Type::Double)),
+      Function(Type::Int)(Type::Int, Type::Int),
+      Type::MinMaxType(zone(), Type::Signed(), Type::Int()),
+      Function(Type::Int)(Type::Float), Type::FroundType(zone()),
+      Type::FFIType(zone()),
+      Type::FunctionTableType(zone(), 10, Function(Type::Void)()),
+  };
+
+  std::unordered_set<Type*> parameter_types{
+      Type::Double(), Type::Int(), Type::Float(),
+  };
+
+  for (size_t ii = 0; ii < arraysize(test_types); ++ii) {
+    const bool IsParameterType = parameter_types.count(test_types[ii]);
+    EXPECT_EQ(IsParameterType, test_types[ii]->IsParameterType())
+        << test_types[ii]->Name()
+        << (IsParameterType ? " is not a parameter type"
+                            : " is a parameter type");
+  }
+}
+
+TEST_F(AsmTypeTest, IsComparableType) {
+  Type* test_types[] = {
+#define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(),
+      FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE)
+#undef CREATE
+          Function(Type::Int)(Type::Double),
+      Function(Type::Int)(Type::DoubleQ),
+      Overload(Function(Type::Int)(Type::Double)),
+      Function(Type::Int)(Type::Int, Type::Int),
+      Type::MinMaxType(zone(), Type::Signed(), Type::Int()),
+      Function(Type::Int)(Type::Float), Type::FroundType(zone()),
+      Type::FFIType(zone()),
+      Type::FunctionTableType(zone(), 10, Function(Type::Void)()),
+  };
+
+  std::unordered_set<Type*> comparable_types{
+      Type::Double(), Type::Signed(), Type::Unsigned(), Type::Float(),
+  };
+
+  for (size_t ii = 0; ii < arraysize(test_types); ++ii) {
+    const bool IsComparableType = comparable_types.count(test_types[ii]);
+    EXPECT_EQ(IsComparableType, test_types[ii]->IsComparableType())
+        << test_types[ii]->Name()
+        << (IsComparableType ? " is not a comparable type"
+                             : " is a comparable type");
+  }
+}
+
+TEST_F(AsmTypeTest, ElementSizeInBytes) {
+  Type* test_types[] = {
+#define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(),
+      FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE)
+#undef CREATE
+          Function(Type::Int)(Type::Double),
+      Function(Type::Int)(Type::DoubleQ),
+      Overload(Function(Type::Int)(Type::Double)),
+      Function(Type::Int)(Type::Int, Type::Int),
+      Type::MinMaxType(zone(), Type::Signed(), Type::Int()),
+      Function(Type::Int)(Type::Float), Type::FroundType(zone()),
+      Type::FFIType(zone()),
+      Type::FunctionTableType(zone(), 10, Function(Type::Void)()),
+  };
+
+  auto ElementSizeInBytesForType = [](Type* type) -> int32_t {
+    if (type == Type::Int8Array() || type == Type::Uint8Array()) {
+      return 1;
+    }
+    if (type == Type::Int16Array() || type == Type::Uint16Array()) {
+      return 2;
+    }
+    if (type == Type::Int32Array() || type == Type::Uint32Array() ||
+        type == Type::Float32Array()) {
+      return 4;
+    }
+    if (type == Type::Float64Array()) {
+      return 8;
+    }
+    return -1;
+  };
+
+  for (size_t ii = 0; ii < arraysize(test_types); ++ii) {
+    EXPECT_EQ(ElementSizeInBytesForType(test_types[ii]),
+              test_types[ii]->ElementSizeInBytes());
+  }
+}
+
+TEST_F(AsmTypeTest, LoadType) {
+  Type* test_types[] = {
+#define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(),
+      FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE)
+#undef CREATE
+          Function(Type::Int)(Type::Double),
+      Function(Type::Int)(Type::DoubleQ),
+      Overload(Function(Type::Int)(Type::Double)),
+      Function(Type::Int)(Type::Int, Type::Int),
+      Type::MinMaxType(zone(), Type::Signed(), Type::Int()),
+      Function(Type::Int)(Type::Float), Type::FroundType(zone()),
+      Type::FFIType(zone()),
+      Type::FunctionTableType(zone(), 10, Function(Type::Void)()),
+  };
+
+  auto LoadTypeForType = [](Type* type) -> Type* {
+    if (type == Type::Int8Array() || type == Type::Uint8Array() ||
+        type == Type::Int16Array() || type == Type::Uint16Array() ||
+        type == Type::Int32Array() || type == Type::Uint32Array()) {
+      return Type::Intish();
+    }
+
+    if (type == Type::Float32Array()) {
+      return Type::FloatQ();
+    }
+
+    if (type == Type::Float64Array()) {
+      return Type::DoubleQ();
+    }
+
+    return Type::None();
+  };
+
+  for (size_t ii = 0; ii < arraysize(test_types); ++ii) {
+    EXPECT_EQ(LoadTypeForType(test_types[ii]), test_types[ii]->LoadType());
+  }
+}
+
+TEST_F(AsmTypeTest, StoreType) {
+  Type* test_types[] = {
+#define CREATE(CamelName, string_name, number, parent_types) Type::CamelName(),
+      FOR_EACH_ASM_VALUE_TYPE_LIST(CREATE)
+#undef CREATE
+          Function(Type::Int)(Type::Double),
+      Function(Type::Int)(Type::DoubleQ),
+      Overload(Function(Type::Int)(Type::Double)),
+      Function(Type::Int)(Type::Int, Type::Int),
+      Type::MinMaxType(zone(), Type::Signed(), Type::Int()),
+      Function(Type::Int)(Type::Float), Type::FroundType(zone()),
+      Type::FFIType(zone()),
+      Type::FunctionTableType(zone(), 10, Function(Type::Void)()),
+  };
+
+  auto StoreTypeForType = [](Type* type) -> Type* {
+    if (type == Type::Int8Array() || type == Type::Uint8Array() ||
+        type == Type::Int16Array() || type == Type::Uint16Array() ||
+        type == Type::Int32Array() || type == Type::Uint32Array()) {
+      return Type::Intish();
+    }
+
+    if (type == Type::Float32Array()) {
+      return Type::FloatishDoubleQ();
+    }
+
+    if (type == Type::Float64Array()) {
+      return Type::FloatQDoubleQ();
+    }
+
+    return Type::None();
+  };
+
+  for (size_t ii = 0; ii < arraysize(test_types); ++ii) {
+    EXPECT_EQ(StoreTypeForType(test_types[ii]), test_types[ii]->StoreType())
+        << test_types[ii]->Name();
+  }
+}
+
+}  // namespace
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/wasm/ast-decoder-unittest.cc b/test/unittests/wasm/ast-decoder-unittest.cc
index 0b1b79e..8be0e41 100644
--- a/test/unittests/wasm/ast-decoder-unittest.cc
+++ b/test/unittests/wasm/ast-decoder-unittest.cc
@@ -18,9 +18,13 @@
 namespace internal {
 namespace wasm {
 
+#define B1(a) kExprBlock, a, kExprEnd
+#define B2(a, b) kExprBlock, a, b, kExprEnd
+#define B3(a, b, c) kExprBlock, a, b, c, kExprEnd
+
 static const byte kCodeGetLocal0[] = {kExprGetLocal, 0};
 static const byte kCodeGetLocal1[] = {kExprGetLocal, 1};
-static const byte kCodeSetLocal0[] = {kExprSetLocal, 0, kExprI8Const, 0};
+static const byte kCodeSetLocal0[] = {WASM_SET_LOCAL(0, WASM_ZERO)};
 
 static const LocalType kLocalTypes[] = {kAstI32, kAstI64, kAstF32, kAstF64};
 static const MachineType machineTypes[] = {
@@ -36,7 +40,7 @@
     kExprI32LeS,  kExprI32LtU,  kExprI32LeU};
 
 #define WASM_BRV_IF_ZERO(depth, val) \
-  kExprBrIf, static_cast<byte>(depth), val, WASM_ZERO
+  val, WASM_ZERO, kExprBrIf, ARITY_1, static_cast<byte>(depth)
 
 #define EXPECT_VERIFIES(env, x) Verify(kSuccess, env, x, x + arraysize(x))
 
@@ -48,7 +52,6 @@
     Verify(kSuccess, env, code, code + arraysize(code)); \
   } while (false)
 
-
 #define EXPECT_FAILURE_INLINE(env, ...)                \
   do {                                                 \
     static byte code[] = {__VA_ARGS__};                \
@@ -65,7 +68,8 @@
  public:
   typedef std::pair<uint32_t, LocalType> LocalsDecl;
 
-  AstDecoderTest() : module(nullptr) {}
+  AstDecoderTest() : module(nullptr), local_decls(zone()) {}
+
   TestSignatures sigs;
   ModuleEnv* module;
   LocalDeclEncoder local_decls;
@@ -74,11 +78,11 @@
     local_decls.AddLocals(count, type);
   }
 
-  // Preprends local variable declarations and renders nice error messages for
+  // Prepends local variable declarations and renders nice error messages for
   // verification failures.
   void Verify(ErrorCode expected, FunctionSig* sig, const byte* start,
               const byte* end) {
-    local_decls.Prepend(&start, &end);
+    local_decls.Prepend(zone(), &start, &end);
     // Verify the code.
     TreeResult result =
         VerifyWasmCode(zone()->allocator(), module, sig, start, end);
@@ -101,14 +105,11 @@
       }
       FATAL(str.str().c_str());
     }
-
-    delete[] start;  // local_decls.Prepend() allocated a new buffer.
   }
 
   void TestBinop(WasmOpcode opcode, FunctionSig* success) {
     // op(local[0], local[1])
-    byte code[] = {static_cast<byte>(opcode), kExprGetLocal, 0, kExprGetLocal,
-                   1};
+    byte code[] = {WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))};
     EXPECT_VERIFIES(success, code);
 
     // Try all combinations of return and parameter types.
@@ -134,7 +135,7 @@
 
   void TestUnop(WasmOpcode opcode, LocalType ret_type, LocalType param_type) {
     // Return(op(local[0]))
-    byte code[] = {static_cast<byte>(opcode), kExprGetLocal, 0};
+    byte code[] = {WASM_UNOP(opcode, WASM_GET_LOCAL(0))};
     {
       LocalType types[] = {ret_type, param_type};
       FunctionSig sig(1, 1, types);
@@ -155,7 +156,6 @@
   }
 };
 
-
 TEST_F(AstDecoderTest, Int8Const) {
   byte code[] = {kExprI8Const, 0};
   for (int i = -128; i < 128; i++) {
@@ -176,12 +176,6 @@
   EXPECT_FAILURE(sigs.i_i(), code);
 }
 
-TEST_F(AstDecoderTest, IncompleteIf2) {
-  byte code[] = {kExprIf, kExprI8Const, 0};
-  EXPECT_FAILURE(sigs.v_v(), code);
-  EXPECT_FAILURE(sigs.i_i(), code);
-}
-
 TEST_F(AstDecoderTest, Int8Const_fallthru) {
   byte code[] = {kExprI8Const, 0, kExprI8Const, 1};
   EXPECT_VERIFIES(sigs.i_i(), code);
@@ -303,199 +297,294 @@
     EXPECT_FAILURE(sigs.i_i(), code1);
   }
 
-  byte code3[] = {0, kExprGetLocal, 0};  // [opcode] [expr]
+  byte code3[] = {kExprGetLocal, 0, 0};  // [expr] [opcode]
   for (size_t i = 0; i < arraysize(kInt32BinopOpcodes); i++) {
-    code3[0] = kInt32BinopOpcodes[i];
+    code3[2] = kInt32BinopOpcodes[i];
     EXPECT_FAILURE(sigs.i_i(), code3);
   }
 
-  byte code4[] = {0, kExprGetLocal, 0, 0};  // [opcode] [expr] [opcode]
+  byte code4[] = {kExprGetLocal, 0, 0, 0};  // [expr] [opcode] [opcode]
   for (size_t i = 0; i < arraysize(kInt32BinopOpcodes); i++) {
-    code4[0] = kInt32BinopOpcodes[i];
+    code4[2] = kInt32BinopOpcodes[i];
     code4[3] = kInt32BinopOpcodes[i];
     EXPECT_FAILURE(sigs.i_i(), code4);
   }
 }
 
+TEST_F(AstDecoderTest, BinopsAcrossBlock1) {
+  static const byte code[] = {WASM_ZERO, kExprBlock, WASM_ZERO, kExprI32Add,
+                              kExprEnd};
+  EXPECT_FAILURE(sigs.i_i(), code);
+}
 
-//===================================================================
-//== Statements
-//===================================================================
+TEST_F(AstDecoderTest, BinopsAcrossBlock2) {
+  static const byte code[] = {WASM_ZERO, WASM_ZERO, kExprBlock, kExprI32Add,
+                              kExprEnd};
+  EXPECT_FAILURE(sigs.i_i(), code);
+}
+
+TEST_F(AstDecoderTest, BinopsAcrossBlock3) {
+  static const byte code[] = {WASM_ZERO, WASM_ZERO,   kExprIf, kExprI32Add,
+                              kExprElse, kExprI32Add, kExprEnd};
+  EXPECT_FAILURE(sigs.i_i(), code);
+}
+
 TEST_F(AstDecoderTest, Nop) {
   static const byte code[] = {kExprNop};
   EXPECT_VERIFIES(sigs.v_v(), code);
 }
 
 TEST_F(AstDecoderTest, SetLocal0_param) {
-  static const byte code[] = {kExprSetLocal, 0, kExprI8Const, 0};
-  EXPECT_VERIFIES(sigs.i_i(), code);
+  EXPECT_VERIFIES(sigs.i_i(), kCodeSetLocal0);
+  EXPECT_FAILURE(sigs.f_ff(), kCodeSetLocal0);
+  EXPECT_FAILURE(sigs.d_dd(), kCodeSetLocal0);
 }
 
 TEST_F(AstDecoderTest, SetLocal0_local) {
-  byte code[] = {kExprSetLocal, 0, kExprI8Const, 0};
+  EXPECT_FAILURE(sigs.i_v(), kCodeSetLocal0);
   AddLocals(kAstI32, 1);
-  EXPECT_VERIFIES(sigs.i_v(), code);
+  EXPECT_VERIFIES(sigs.i_v(), kCodeSetLocal0);
 }
 
 TEST_F(AstDecoderTest, SetLocalN_local) {
   for (byte i = 1; i < 8; i++) {
     AddLocals(kAstI32, 1);
     for (byte j = 0; j < i; j++) {
-      byte code[] = {kExprSetLocal, j, kExprI8Const, i};
-      EXPECT_VERIFIES(sigs.v_v(), code);
+      EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_SET_LOCAL(j, WASM_I8(i)));
     }
   }
 }
 
+TEST_F(AstDecoderTest, BlockN) {
+  const int kMaxSize = 200;
+  byte buffer[kMaxSize + 2];
+
+  for (int i = 0; i <= kMaxSize; i++) {
+    memset(buffer, kExprNop, sizeof(buffer));
+    buffer[0] = kExprBlock;
+    buffer[i + 1] = kExprEnd;
+    Verify(kSuccess, sigs.v_i(), buffer, buffer + i + 2);
+  }
+}
+
 TEST_F(AstDecoderTest, Block0) {
-  static const byte code[] = {kExprBlock, 0};
+  static const byte code[] = {kExprBlock, kExprEnd};
   EXPECT_VERIFIES(sigs.v_v(), code);
+  EXPECT_FAILURE(sigs.i_i(), code);
 }
 
 TEST_F(AstDecoderTest, Block0_fallthru1) {
-  static const byte code[] = {kExprBlock, 0, kExprBlock, 0};
+  static const byte code[] = {kExprBlock, kExprBlock, kExprEnd, kExprEnd};
   EXPECT_VERIFIES(sigs.v_v(), code);
+  EXPECT_FAILURE(sigs.i_i(), code);
+}
+
+TEST_F(AstDecoderTest, Block0Block0) {
+  static const byte code[] = {kExprBlock, kExprEnd, kExprBlock, kExprEnd};
+  EXPECT_VERIFIES(sigs.v_v(), code);
+  EXPECT_FAILURE(sigs.i_i(), code);
+}
+
+TEST_F(AstDecoderTest, Block0_end_end) {
+  static const byte code[] = {kExprBlock, kExprEnd, kExprEnd};
+  EXPECT_FAILURE(sigs.v_v(), code);
 }
 
 TEST_F(AstDecoderTest, Block1) {
-  static const byte code[] = {kExprBlock, 1, kExprSetLocal, 0, kExprI8Const, 0};
+  byte code[] = {B1(WASM_SET_LOCAL(0, WASM_ZERO))};
   EXPECT_VERIFIES(sigs.i_i(), code);
+  EXPECT_VERIFIES(sigs.v_i(), code);
+  EXPECT_FAILURE(sigs.d_dd(), code);
 }
 
-TEST_F(AstDecoderTest, Block0_fallthru2) {
-  static const byte code[] = {kExprBlock, 0, kExprSetLocal, 0, kExprI8Const, 0};
+TEST_F(AstDecoderTest, Block1_i) {
+  byte code[] = {B1(WASM_ZERO)};
   EXPECT_VERIFIES(sigs.i_i(), code);
+  EXPECT_FAILURE(sigs.f_ff(), code);
+  EXPECT_FAILURE(sigs.d_dd(), code);
+  EXPECT_FAILURE(sigs.l_ll(), code);
 }
 
-TEST_F(AstDecoderTest, Block2) {
-  static const byte code[] = {kExprBlock,    2,                    // --
-                              kExprSetLocal, 0, kExprI8Const, 0,   // --
-                              kExprSetLocal, 0, kExprI8Const, 0};  // --
-  EXPECT_VERIFIES(sigs.i_i(), code);
-}
-
-TEST_F(AstDecoderTest, Block2_fallthru) {
-  static const byte code[] = {kExprBlock,    2,                   // --
-                              kExprSetLocal, 0, kExprI8Const, 0,  // --
-                              kExprSetLocal, 0, kExprI8Const, 0,  // --
-                              kExprI8Const,  11};                 // --
-  EXPECT_VERIFIES(sigs.i_i(), code);
-}
-
-TEST_F(AstDecoderTest, BlockN) {
-  byte block[] = {kExprBlock, 2};
-
-  for (size_t i = 0; i < 10; i++) {
-    size_t total = sizeof(block) + sizeof(kCodeSetLocal0) * i;
-    byte* code = reinterpret_cast<byte*>(malloc(total));
-    memcpy(code, block, sizeof(block));
-    code[1] = static_cast<byte>(i);
-    for (size_t j = 0; j < i; j++) {
-      memcpy(code + sizeof(block) + j * sizeof(kCodeSetLocal0), kCodeSetLocal0,
-             sizeof(kCodeSetLocal0));
-    }
-    Verify(kSuccess, sigs.v_i(), code, code + total);
-    free(code);
-  }
-}
-
-TEST_F(AstDecoderTest, BlockN_off_end) {
-  for (byte i = 2; i < 10; i++) {
-    byte code[] = {kExprBlock, i, kExprNop};
-    EXPECT_FAILURE(sigs.v_v(), code);
-  }
-}
-
-TEST_F(AstDecoderTest, Block1_break) {
-  static const byte code[] = {kExprBlock, 1, kExprBr, 0, kExprNop};
-  EXPECT_VERIFIES(sigs.v_v(), code);
-}
-
-TEST_F(AstDecoderTest, Block2_break) {
-  static const byte code[] = {kExprBlock, 2, kExprNop, kExprBr, 0, kExprNop};
-  EXPECT_VERIFIES(sigs.v_v(), code);
+TEST_F(AstDecoderTest, Block1_f) {
+  byte code[] = {B1(WASM_F32(0))};
+  EXPECT_FAILURE(sigs.i_i(), code);
+  EXPECT_VERIFIES(sigs.f_ff(), code);
+  EXPECT_FAILURE(sigs.d_dd(), code);
+  EXPECT_FAILURE(sigs.l_ll(), code);
 }
 
 TEST_F(AstDecoderTest, Block1_continue) {
-  static const byte code[] = {kExprBlock, 1, kExprBr, 1, kExprNop};
-  EXPECT_FAILURE(sigs.v_v(), code);
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), B1(WASM_BR(0)));
+  EXPECT_FAILURE_INLINE(sigs.v_v(), B1(WASM_BR(1)));
+  EXPECT_FAILURE_INLINE(sigs.v_v(), B1(WASM_BR(2)));
+  EXPECT_FAILURE_INLINE(sigs.v_v(), B1(WASM_BR(3)));
 }
 
-TEST_F(AstDecoderTest, Block2_continue) {
-  static const byte code[] = {kExprBlock, 2, kExprNop, kExprBr, 1, kExprNop};
-  EXPECT_FAILURE(sigs.v_v(), code);
+TEST_F(AstDecoderTest, Block1_br) {
+  EXPECT_FAILURE_INLINE(sigs.v_v(), kExprBlock, kExprBr, ARITY_1, DEPTH_0,
+                        kExprEnd);
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), kExprBlock, kExprBr, ARITY_0, DEPTH_0,
+                         kExprEnd);
 }
 
-TEST_F(AstDecoderTest, ExprBlock0) {
-  static const byte code[] = {kExprBlock, 0};
-  EXPECT_VERIFIES(sigs.v_v(), code);
+TEST_F(AstDecoderTest, Block2_br) {
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), B2(WASM_NOP, WASM_BR(0)));
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), B2(WASM_BR(0), WASM_NOP));
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), B2(WASM_BR(0), WASM_BR(0)));
 }
 
-TEST_F(AstDecoderTest, ExprBlock1a) {
-  static const byte code[] = {kExprBlock, 1, kExprI8Const, 0};
+TEST_F(AstDecoderTest, Block2) {
+  EXPECT_VERIFIES_INLINE(sigs.i_i(),
+                         B2(WASM_NOP, WASM_SET_LOCAL(0, WASM_ZERO)));
+  EXPECT_FAILURE_INLINE(sigs.i_i(), B2(WASM_SET_LOCAL(0, WASM_ZERO), WASM_NOP));
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), B2(WASM_SET_LOCAL(0, WASM_ZERO),
+                                        WASM_SET_LOCAL(0, WASM_ZERO)));
+}
+
+TEST_F(AstDecoderTest, Block2b) {
+  byte code[] = {B2(WASM_SET_LOCAL(0, WASM_ZERO), WASM_ZERO)};
   EXPECT_VERIFIES(sigs.i_i(), code);
-}
-
-TEST_F(AstDecoderTest, ExprBlock1b) {
-  static const byte code[] = {kExprBlock, 1, kExprI8Const, 0};
+  EXPECT_FAILURE(sigs.v_v(), code);
   EXPECT_FAILURE(sigs.f_ff(), code);
 }
 
-TEST_F(AstDecoderTest, ExprBlock1c) {
-  static const byte code[] = {kExprBlock, 1, kExprF32Const, 0, 0, 0, 0};
+TEST_F(AstDecoderTest, Block2_fallthru) {
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), B2(WASM_SET_LOCAL(0, WASM_ZERO),
+                                        WASM_SET_LOCAL(0, WASM_ZERO)),
+                         WASM_I8(23));
+}
+
+TEST_F(AstDecoderTest, Block3) {
+  EXPECT_VERIFIES_INLINE(
+      sigs.i_i(), B3(WASM_SET_LOCAL(0, WASM_ZERO), WASM_SET_LOCAL(0, WASM_ZERO),
+                     WASM_I8(11)));
+}
+
+TEST_F(AstDecoderTest, Block5) {
+  EXPECT_VERIFIES_INLINE(sigs.v_i(), B1(WASM_GET_LOCAL(0)));
+
+  EXPECT_VERIFIES_INLINE(sigs.v_i(), B2(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
+
+  EXPECT_VERIFIES_INLINE(
+      sigs.v_i(), B3(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
+
+  EXPECT_VERIFIES_INLINE(sigs.v_i(),
+                         WASM_BLOCK(4, WASM_GET_LOCAL(0), WASM_GET_LOCAL(0),
+                                    WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
+
+  EXPECT_VERIFIES_INLINE(
+      sigs.v_i(),
+      WASM_BLOCK(5, WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_GET_LOCAL(0),
+                 WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)));
+}
+
+TEST_F(AstDecoderTest, BlockF32) {
+  static const byte code[] = {kExprBlock, kExprF32Const, 0, 0, 0, 0, kExprEnd};
   EXPECT_VERIFIES(sigs.f_ff(), code);
+  EXPECT_FAILURE(sigs.i_i(), code);
+  EXPECT_FAILURE(sigs.d_dd(), code);
+}
+
+TEST_F(AstDecoderTest, BlockN_off_end) {
+  byte code[] = {kExprBlock, kExprNop, kExprNop, kExprNop, kExprNop, kExprEnd};
+  EXPECT_VERIFIES(sigs.v_v(), code);
+  for (size_t i = 1; i < arraysize(code); i++) {
+    Verify(kError, sigs.v_v(), code, code + i);
+  }
+}
+
+TEST_F(AstDecoderTest, Block2_continue) {
+  static const byte code[] = {kExprBlock, kExprBr,  ARITY_0,
+                              DEPTH_1,    kExprNop, kExprEnd};
+  EXPECT_FAILURE(sigs.v_v(), code);
+}
+
+TEST_F(AstDecoderTest, NestedBlock_return) {
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), B1(B1(WASM_RETURN1(WASM_ZERO))));
+}
+
+TEST_F(AstDecoderTest, BlockBinop) {
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_I32_AND(B1(WASM_I8(1)), WASM_I8(2)));
+}
+
+TEST_F(AstDecoderTest, BlockBrBinop) {
+  EXPECT_VERIFIES_INLINE(sigs.i_i(),
+                         WASM_I32_AND(B1(WASM_BRV(0, WASM_I8(1))), WASM_I8(2)));
+}
+
+TEST_F(AstDecoderTest, If_empty1) {
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_ZERO, kExprIf, kExprEnd);
+}
+
+TEST_F(AstDecoderTest, If_empty2) {
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_ZERO, kExprIf, kExprElse, kExprEnd);
+}
+
+TEST_F(AstDecoderTest, If_empty3) {
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_ZERO, kExprIf, WASM_ZERO, kExprElse,
+                         kExprEnd);
+}
+
+TEST_F(AstDecoderTest, If_empty4) {
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_ZERO, kExprIf, kExprElse, WASM_ZERO,
+                         kExprEnd);
+}
+
+TEST_F(AstDecoderTest, If_empty_stack) {
+  byte code[] = {kExprIf};
+  EXPECT_FAILURE(sigs.v_v(), code);
+  EXPECT_FAILURE(sigs.i_i(), code);
+}
+
+TEST_F(AstDecoderTest, If_incomplete1) {
+  byte code[] = {kExprI8Const, 0, kExprIf};
+  EXPECT_FAILURE(sigs.v_v(), code);
+  EXPECT_FAILURE(sigs.i_i(), code);
+}
+
+TEST_F(AstDecoderTest, If_incomplete2) {
+  byte code[] = {kExprI8Const, 0, kExprIf, kExprNop};
+  EXPECT_FAILURE(sigs.v_v(), code);
+  EXPECT_FAILURE(sigs.i_i(), code);
+}
+
+TEST_F(AstDecoderTest, If_else_else) {
+  byte code[] = {kExprI8Const, 0, kExprIf, kExprElse, kExprElse, kExprEnd};
+  EXPECT_FAILURE(sigs.v_v(), code);
+  EXPECT_FAILURE(sigs.i_i(), code);
 }
 
 TEST_F(AstDecoderTest, IfEmpty) {
-  static const byte code[] = {kExprIf, kExprGetLocal, 0, kExprNop};
-  EXPECT_VERIFIES(sigs.v_i(), code);
+  EXPECT_VERIFIES_INLINE(sigs.v_i(), kExprGetLocal, 0, kExprIf, kExprEnd);
 }
 
 TEST_F(AstDecoderTest, IfSet) {
-  static const byte code[] = {kExprIfElse, kExprGetLocal, 0, kExprSetLocal,
-                              0,           kExprI8Const,  0, kExprNop};
-  EXPECT_VERIFIES(sigs.v_i(), code);
-}
-
-TEST_F(AstDecoderTest, IfBlock1) {
-  static const byte code[] = {kExprIfElse, kExprGetLocal, 0, kExprBlock,
-                              1,           kExprSetLocal, 0, kExprI8Const,
-                              0,           kExprNop};
-  EXPECT_VERIFIES(sigs.v_i(), code);
-}
-
-TEST_F(AstDecoderTest, IfBlock2) {
-  static const byte code[] = {kExprIf, kExprGetLocal, 0, kExprBlock,
-                              2,       kExprSetLocal, 0, kExprI8Const,
-                              0,       kExprSetLocal, 0, kExprI8Const,
-                              0};
-  EXPECT_VERIFIES(sigs.v_i(), code);
+  EXPECT_VERIFIES_INLINE(
+      sigs.v_i(), WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_ZERO)));
+  EXPECT_VERIFIES_INLINE(
+      sigs.v_i(),
+      WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_ZERO), WASM_NOP));
 }
 
 TEST_F(AstDecoderTest, IfElseEmpty) {
-  static const byte code[] = {kExprIfElse, kExprGetLocal, 0, kExprNop,
-                              kExprNop};
-  EXPECT_VERIFIES(sigs.v_i(), code);
+  EXPECT_VERIFIES_INLINE(sigs.v_i(), WASM_GET_LOCAL(0), kExprIf, kExprElse,
+                         kExprEnd);
+  EXPECT_VERIFIES_INLINE(sigs.v_i(),
+                         WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_NOP, WASM_NOP));
 }
 
-TEST_F(AstDecoderTest, IfElseSet) {
-  static const byte code[] = {kExprIfElse,
-                              kExprGetLocal,
-                              0,  // --
-                              kExprSetLocal,
-                              0,
-                              kExprI8Const,
-                              0,  // --
-                              kExprSetLocal,
-                              0,
-                              kExprI8Const,
-                              1};  // --
-  EXPECT_VERIFIES(sigs.v_i(), code);
+TEST_F(AstDecoderTest, IfElseUnreachable1) {
+  EXPECT_VERIFIES_INLINE(
+      sigs.i_i(),
+      WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_UNREACHABLE, WASM_GET_LOCAL(0)));
+  EXPECT_VERIFIES_INLINE(
+      sigs.i_i(),
+      WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_UNREACHABLE));
 }
 
-TEST_F(AstDecoderTest, IfElseUnreachable) {
-  static const byte code[] = {kExprIfElse,      kExprI8Const,  0,
-                              kExprUnreachable, kExprGetLocal, 0};
+TEST_F(AstDecoderTest, IfElseUnreachable2) {
+  static const byte code[] = {
+      WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_UNREACHABLE, WASM_GET_LOCAL(0))};
 
   for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
     LocalType types[] = {kAstI32, kLocalTypes[i]};
@@ -509,66 +598,136 @@
   }
 }
 
+TEST_F(AstDecoderTest, IfBreak) {
+  EXPECT_VERIFIES_INLINE(sigs.v_i(), WASM_IF(WASM_GET_LOCAL(0), WASM_BR(0)));
+  EXPECT_FAILURE_INLINE(sigs.v_i(), WASM_IF(WASM_GET_LOCAL(0), WASM_BR(1)));
+}
+
+TEST_F(AstDecoderTest, IfElseBreak) {
+  EXPECT_VERIFIES_INLINE(sigs.v_i(),
+                         WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_NOP, WASM_BR(0)));
+  EXPECT_FAILURE_INLINE(sigs.v_i(),
+                        WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_NOP, WASM_BR(1)));
+}
+
+TEST_F(AstDecoderTest, Block_else) {
+  byte code[] = {kExprI8Const, 0, kExprBlock, kExprElse, kExprEnd};
+  EXPECT_FAILURE(sigs.v_v(), code);
+  EXPECT_FAILURE(sigs.i_i(), code);
+}
+
+TEST_F(AstDecoderTest, IfNop) {
+  EXPECT_VERIFIES_INLINE(sigs.v_i(), WASM_IF(WASM_GET_LOCAL(0), WASM_NOP));
+}
+
+TEST_F(AstDecoderTest, IfNopElseNop) {
+  EXPECT_VERIFIES_INLINE(sigs.v_i(),
+                         WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_NOP, WASM_NOP));
+}
+
+TEST_F(AstDecoderTest, If_end_end) {
+  static const byte code[] = {kExprGetLocal, 0, kExprIf, kExprEnd, kExprEnd};
+  EXPECT_FAILURE(sigs.v_i(), code);
+}
+
+TEST_F(AstDecoderTest, If_falloff) {
+  static const byte code[] = {kExprGetLocal, 0, kExprIf};
+  EXPECT_FAILURE(sigs.v_i(), code);
+}
+
+TEST_F(AstDecoderTest, IfElse_falloff) {
+  static const byte code[] = {kExprGetLocal, 0, kExprIf, kExprNop, kExprElse};
+  EXPECT_FAILURE(sigs.v_i(), code);
+}
+
+TEST_F(AstDecoderTest, IfElseNop) {
+  EXPECT_VERIFIES_INLINE(
+      sigs.v_i(),
+      WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_ZERO), WASM_NOP));
+}
+
+TEST_F(AstDecoderTest, IfBlock1) {
+  EXPECT_VERIFIES_INLINE(
+      sigs.v_i(), WASM_IF_ELSE(WASM_GET_LOCAL(0),
+                               B1(WASM_SET_LOCAL(0, WASM_ZERO)), WASM_NOP));
+}
+
+TEST_F(AstDecoderTest, IfBlock1b) {
+  EXPECT_VERIFIES_INLINE(
+      sigs.v_i(), WASM_IF(WASM_GET_LOCAL(0), B1(WASM_SET_LOCAL(0, WASM_ZERO))));
+}
+
+TEST_F(AstDecoderTest, IfBlock2a) {
+  EXPECT_VERIFIES_INLINE(
+      sigs.v_i(), WASM_IF(WASM_GET_LOCAL(0), B2(WASM_SET_LOCAL(0, WASM_ZERO),
+                                                WASM_SET_LOCAL(0, WASM_ZERO))));
+}
+
+TEST_F(AstDecoderTest, IfBlock2b) {
+  EXPECT_VERIFIES_INLINE(
+      sigs.v_i(),
+      WASM_IF_ELSE(WASM_GET_LOCAL(0), B2(WASM_SET_LOCAL(0, WASM_ZERO),
+                                         WASM_SET_LOCAL(0, WASM_ZERO)),
+                   WASM_NOP));
+}
+
+TEST_F(AstDecoderTest, IfElseSet) {
+  EXPECT_VERIFIES_INLINE(
+      sigs.v_i(), WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_ZERO),
+                               WASM_SET_LOCAL(0, WASM_I8(1))));
+}
+
 TEST_F(AstDecoderTest, Loop0) {
-  static const byte code[] = {kExprLoop, 0};
+  static const byte code[] = {kExprLoop, kExprEnd};
   EXPECT_VERIFIES(sigs.v_v(), code);
 }
 
 TEST_F(AstDecoderTest, Loop1) {
-  static const byte code[] = {kExprLoop, 1, kExprSetLocal, 0, kExprI8Const, 0};
+  static const byte code[] = {WASM_LOOP(1, WASM_SET_LOCAL(0, WASM_ZERO))};
   EXPECT_VERIFIES(sigs.v_i(), code);
+  EXPECT_FAILURE(sigs.v_v(), code);
+  EXPECT_FAILURE(sigs.f_ff(), code);
 }
 
 TEST_F(AstDecoderTest, Loop2) {
-  static const byte code[] = {kExprLoop,     2,                    // --
-                              kExprSetLocal, 0, kExprI8Const, 0,   // --
-                              kExprSetLocal, 0, kExprI8Const, 0};  // --
-  EXPECT_VERIFIES(sigs.v_i(), code);
+  EXPECT_VERIFIES_INLINE(sigs.v_i(), WASM_LOOP(2, WASM_SET_LOCAL(0, WASM_ZERO),
+                                               WASM_SET_LOCAL(0, WASM_ZERO)));
 }
 
 TEST_F(AstDecoderTest, Loop1_continue) {
-  static const byte code[] = {kExprLoop, 1, kExprBr, 0, kExprNop};
-  EXPECT_VERIFIES(sigs.v_v(), code);
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_LOOP(1, WASM_BR(0)));
 }
 
 TEST_F(AstDecoderTest, Loop1_break) {
-  static const byte code[] = {kExprLoop, 1, kExprBr, 1, kExprNop};
-  EXPECT_VERIFIES(sigs.v_v(), code);
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_LOOP(1, WASM_BR(1)));
 }
 
 TEST_F(AstDecoderTest, Loop2_continue) {
-  static const byte code[] = {kExprLoop,     2,                   // --
-                              kExprSetLocal, 0, kExprI8Const, 0,  // --
-                              kExprBr,       0, kExprNop};        // --
-  EXPECT_VERIFIES(sigs.v_i(), code);
+  EXPECT_VERIFIES_INLINE(
+      sigs.v_i(), WASM_LOOP(2, WASM_SET_LOCAL(0, WASM_ZERO), WASM_BR(0)));
 }
 
 TEST_F(AstDecoderTest, Loop2_break) {
-  static const byte code[] = {kExprLoop,     2,                   // --
-                              kExprSetLocal, 0, kExprI8Const, 0,  // --
-                              kExprBr,       1, kExprNop};        // --
-  EXPECT_VERIFIES(sigs.v_i(), code);
+  EXPECT_VERIFIES_INLINE(
+      sigs.v_i(), WASM_LOOP(2, WASM_SET_LOCAL(0, WASM_ZERO), WASM_BR(1)));
 }
 
 TEST_F(AstDecoderTest, ExprLoop0) {
-  static const byte code[] = {kExprLoop, 0};
+  static const byte code[] = {kExprLoop, kExprEnd};
   EXPECT_VERIFIES(sigs.v_v(), code);
 }
 
 TEST_F(AstDecoderTest, ExprLoop1a) {
-  static const byte code[] = {kExprLoop, 1, kExprBr, 0, kExprI8Const, 0};
-  EXPECT_VERIFIES(sigs.i_i(), code);
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_LOOP(1, WASM_BRV(0, WASM_ZERO)));
 }
 
 TEST_F(AstDecoderTest, ExprLoop1b) {
-  static const byte code[] = {kExprLoop, 1, kExprBr, 0, kExprI8Const, 0};
-  EXPECT_VERIFIES(sigs.i_i(), code);
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_LOOP(1, WASM_BRV(1, WASM_ZERO)));
+  EXPECT_FAILURE_INLINE(sigs.f_ff(), WASM_LOOP(1, WASM_BRV(1, WASM_ZERO)));
 }
 
 TEST_F(AstDecoderTest, ExprLoop2_unreachable) {
-  static const byte code[] = {kExprLoop,    2, kExprBr, 0,
-                              kExprI8Const, 0, kExprNop};
-  EXPECT_VERIFIES(sigs.i_i(), code);
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_LOOP(2, WASM_BR(0), WASM_NOP));
 }
 
 TEST_F(AstDecoderTest, ReturnVoid1) {
@@ -579,7 +738,7 @@
 }
 
 TEST_F(AstDecoderTest, ReturnVoid2) {
-  static const byte code[] = {kExprBlock, 1, kExprBr, 0, kExprNop};
+  static const byte code[] = {kExprBlock, kExprBr, ARITY_0, DEPTH_0, kExprEnd};
   EXPECT_VERIFIES(sigs.v_v(), code);
   EXPECT_FAILURE(sigs.i_i(), code);
   EXPECT_FAILURE(sigs.i_f(), code);
@@ -598,67 +757,85 @@
 TEST_F(AstDecoderTest, Unreachable1) {
   EXPECT_VERIFIES_INLINE(sigs.v_v(), kExprUnreachable);
   EXPECT_VERIFIES_INLINE(sigs.v_v(), kExprUnreachable, kExprUnreachable);
-  EXPECT_VERIFIES_INLINE(sigs.v_v(),
-                         WASM_BLOCK(2, WASM_UNREACHABLE, WASM_ZERO));
-  EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_BLOCK(2, WASM_BR(0), WASM_ZERO));
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), B2(WASM_UNREACHABLE, WASM_ZERO));
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), B2(WASM_BR(0), WASM_ZERO));
   EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_LOOP(2, WASM_UNREACHABLE, WASM_ZERO));
   EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_LOOP(2, WASM_BR(0), WASM_ZERO));
 }
 
-TEST_F(AstDecoderTest, Codeiness) {
-  VERIFY(kExprLoop, 2,                       // --
-         kExprSetLocal, 0, kExprI8Const, 0,  // --
-         kExprBr, 0, kExprNop);              // --
+TEST_F(AstDecoderTest, Unreachable_binop) {
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_I32_AND(WASM_ZERO, WASM_UNREACHABLE));
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_I32_AND(WASM_UNREACHABLE, WASM_ZERO));
 }
 
-TEST_F(AstDecoderTest, ExprIf1) {
-  VERIFY(kExprIf, kExprGetLocal, 0, kExprI8Const, 0, kExprI8Const, 1);
-  VERIFY(kExprIf, kExprGetLocal, 0, kExprGetLocal, 0, kExprGetLocal, 0);
-  VERIFY(kExprIf, kExprGetLocal, 0, kExprI32Add, kExprGetLocal, 0,
-         kExprGetLocal, 0, kExprI8Const, 1);
+TEST_F(AstDecoderTest, Unreachable_select) {
+  EXPECT_VERIFIES_INLINE(sigs.i_i(),
+                         WASM_SELECT(WASM_UNREACHABLE, WASM_ZERO, WASM_ZERO));
+  EXPECT_VERIFIES_INLINE(sigs.i_i(),
+                         WASM_SELECT(WASM_ZERO, WASM_UNREACHABLE, WASM_ZERO));
+  EXPECT_VERIFIES_INLINE(sigs.i_i(),
+                         WASM_SELECT(WASM_ZERO, WASM_ZERO, WASM_UNREACHABLE));
 }
 
-TEST_F(AstDecoderTest, ExprIf_off_end) {
-  static const byte kCode[] = {kExprIf, kExprGetLocal, 0, kExprGetLocal,
-                               0,       kExprGetLocal, 0};
-  for (size_t len = 1; len < arraysize(kCode); len++) {
+TEST_F(AstDecoderTest, If1) {
+  EXPECT_VERIFIES_INLINE(
+      sigs.i_i(), WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_I8(9), WASM_I8(8)));
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_I8(9),
+                                                  WASM_GET_LOCAL(0)));
+  EXPECT_VERIFIES_INLINE(
+      sigs.i_i(),
+      WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_I8(8)));
+}
+
+TEST_F(AstDecoderTest, If_off_end) {
+  static const byte kCode[] = {
+      WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_GET_LOCAL(0))};
+  for (size_t len = 3; len < arraysize(kCode); len++) {
     Verify(kError, sigs.i_i(), kCode, kCode + len);
   }
 }
 
-TEST_F(AstDecoderTest, ExprIf_type) {
-  {
-    // float|double ? 1 : 2
-    static const byte kCode[] = {kExprIfElse, kExprGetLocal, 0, kExprI8Const,
-                                 1,           kExprI8Const,  2};
-    EXPECT_FAILURE(sigs.i_f(), kCode);
-    EXPECT_FAILURE(sigs.i_d(), kCode);
-  }
-  {
-    // 1 ? float|double : 2
-    static const byte kCode[] = {kExprIfElse, kExprI8Const, 1, kExprGetLocal,
-                                 0,           kExprI8Const, 2};
-    EXPECT_FAILURE(sigs.i_f(), kCode);
-    EXPECT_FAILURE(sigs.i_d(), kCode);
-  }
-  {
-    // stmt ? 0 : 1
-    static const byte kCode[] = {kExprIfElse, kExprNop,     kExprI8Const,
-                                 0,           kExprI8Const, 1};
-    EXPECT_FAILURE(sigs.i_i(), kCode);
-  }
-  {
-    // 0 ? stmt : 1
-    static const byte kCode[] = {kExprIfElse, kExprI8Const, 0,
-                                 kExprNop,    kExprI8Const, 1};
-    EXPECT_FAILURE(sigs.i_i(), kCode);
-  }
-  {
-    // 0 ? 1 : stmt
-    static const byte kCode[] = {kExprIfElse, kExprI8Const, 0, kExprI8Const, 1,
-                                 0,           kExprBlock};
-    EXPECT_FAILURE(sigs.i_i(), kCode);
-  }
+TEST_F(AstDecoderTest, If_type1) {
+  // float|double ? 1 : 2
+  static const byte kCode[] = {
+      WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_I8(0), WASM_I8(2))};
+  EXPECT_VERIFIES(sigs.i_i(), kCode);
+  EXPECT_FAILURE(sigs.i_f(), kCode);
+  EXPECT_FAILURE(sigs.i_d(), kCode);
+}
+
+TEST_F(AstDecoderTest, If_type2) {
+  // 1 ? float|double : 2
+  static const byte kCode[] = {
+      WASM_IF_ELSE(WASM_I8(1), WASM_GET_LOCAL(0), WASM_I8(1))};
+  EXPECT_VERIFIES(sigs.i_i(), kCode);
+  EXPECT_FAILURE(sigs.i_f(), kCode);
+  EXPECT_FAILURE(sigs.i_d(), kCode);
+}
+
+TEST_F(AstDecoderTest, If_type3) {
+  // stmt ? 0 : 1
+  static const byte kCode[] = {WASM_IF_ELSE(WASM_NOP, WASM_I8(0), WASM_I8(1))};
+  EXPECT_FAILURE(sigs.i_i(), kCode);
+  EXPECT_FAILURE(sigs.i_f(), kCode);
+  EXPECT_FAILURE(sigs.i_d(), kCode);
+}
+
+TEST_F(AstDecoderTest, If_type4) {
+  // 0 ? stmt : 1
+  static const byte kCode[] = {
+      WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_NOP, WASM_I8(1))};
+  EXPECT_FAILURE(sigs.i_i(), kCode);
+  EXPECT_FAILURE(sigs.i_f(), kCode);
+  EXPECT_FAILURE(sigs.i_d(), kCode);
+}
+
+TEST_F(AstDecoderTest, If_type5) {
+  // 0 ? 1 : stmt
+  static const byte kCode[] = {WASM_IF_ELSE(WASM_ZERO, WASM_I8(1), WASM_NOP)};
+  EXPECT_FAILURE(sigs.i_i(), kCode);
+  EXPECT_FAILURE(sigs.i_f(), kCode);
+  EXPECT_FAILURE(sigs.i_d(), kCode);
 }
 
 TEST_F(AstDecoderTest, Int64Local_param) {
@@ -669,8 +846,7 @@
   for (byte i = 1; i < 8; i++) {
     AddLocals(kAstI64, 1);
     for (byte j = 0; j < i; j++) {
-      byte code[] = {kExprGetLocal, j};
-      EXPECT_VERIFIES(sigs.l_v(), code);
+      EXPECT_VERIFIES_INLINE(sigs.l_v(), WASM_GET_LOCAL(j));
     }
   }
 }
@@ -737,7 +913,7 @@
   VERIFY(WASM_IF(WASM_GET_LOCAL(0), WASM_NOP));
   VERIFY(WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_NOP, WASM_NOP));
   VERIFY(WASM_NOP);
-  VERIFY(WASM_BLOCK(1, WASM_NOP));
+  VERIFY(B1(WASM_NOP));
   VERIFY(WASM_LOOP(1, WASM_NOP));
   VERIFY(WASM_LOOP(1, WASM_BREAK(0)));
   VERIFY(WASM_LOOP(1, WASM_CONTINUE(0)));
@@ -760,30 +936,30 @@
 }
 
 TEST_F(AstDecoderTest, MacrosVariadic) {
-  VERIFY(WASM_BLOCK(2, WASM_NOP, WASM_NOP));
-  VERIFY(WASM_BLOCK(3, WASM_NOP, WASM_NOP, WASM_NOP));
+  VERIFY(B2(WASM_NOP, WASM_NOP));
+  VERIFY(B3(WASM_NOP, WASM_NOP, WASM_NOP));
   VERIFY(WASM_LOOP(2, WASM_NOP, WASM_NOP));
   VERIFY(WASM_LOOP(3, WASM_NOP, WASM_NOP, WASM_NOP));
 }
 
 TEST_F(AstDecoderTest, MacrosNestedBlocks) {
-  VERIFY(WASM_BLOCK(2, WASM_NOP, WASM_BLOCK(2, WASM_NOP, WASM_NOP)));
-  VERIFY(WASM_BLOCK(3, WASM_NOP,                          // --
-                    WASM_BLOCK(2, WASM_NOP, WASM_NOP),    // --
-                    WASM_BLOCK(2, WASM_NOP, WASM_NOP)));  // --
-  VERIFY(WASM_BLOCK(1, WASM_BLOCK(1, WASM_BLOCK(2, WASM_NOP, WASM_NOP))));
+  VERIFY(B2(WASM_NOP, B2(WASM_NOP, WASM_NOP)));
+  VERIFY(B3(WASM_NOP,                  // --
+            B2(WASM_NOP, WASM_NOP),    // --
+            B2(WASM_NOP, WASM_NOP)));  // --
+  VERIFY(B1(B1(B2(WASM_NOP, WASM_NOP))));
 }
 
 TEST_F(AstDecoderTest, MultipleReturn) {
   static LocalType kIntTypes5[] = {kAstI32, kAstI32, kAstI32, kAstI32, kAstI32};
   FunctionSig sig_ii_v(2, 0, kIntTypes5);
-  EXPECT_VERIFIES_INLINE(&sig_ii_v, WASM_RETURN(WASM_ZERO, WASM_ONE));
-  EXPECT_FAILURE_INLINE(&sig_ii_v, WASM_RETURN(WASM_ZERO));
+  EXPECT_VERIFIES_INLINE(&sig_ii_v, WASM_RETURNN(2, WASM_ZERO, WASM_ONE));
+  EXPECT_FAILURE_INLINE(&sig_ii_v, WASM_RETURNN(1, WASM_ZERO));
 
   FunctionSig sig_iii_v(3, 0, kIntTypes5);
   EXPECT_VERIFIES_INLINE(&sig_iii_v,
-                         WASM_RETURN(WASM_ZERO, WASM_ONE, WASM_I8(44)));
-  EXPECT_FAILURE_INLINE(&sig_iii_v, WASM_RETURN(WASM_ZERO, WASM_ONE));
+                         WASM_RETURNN(3, WASM_ZERO, WASM_ONE, WASM_I8(44)));
+  EXPECT_FAILURE_INLINE(&sig_iii_v, WASM_RETURNN(2, WASM_ZERO, WASM_ONE));
 }
 
 TEST_F(AstDecoderTest, MultipleReturn_fallthru) {
@@ -887,78 +1063,57 @@
 }
 
 TEST_F(AstDecoderTest, GrowMemory) {
-  byte code[] = {kExprGrowMemory, kExprGetLocal, 0};
+  byte code[] = {WASM_UNOP(kExprGrowMemory, WASM_GET_LOCAL(0))};
   EXPECT_VERIFIES(sigs.i_i(), code);
   EXPECT_FAILURE(sigs.i_d(), code);
 }
 
 TEST_F(AstDecoderTest, LoadMemOffset) {
   for (int offset = 0; offset < 128; offset += 7) {
-    byte code[] = {kExprI32LoadMem, ZERO_ALIGNMENT, static_cast<byte>(offset),
-                   kExprI8Const, 0};
+    byte code[] = {kExprI8Const, 0, kExprI32LoadMem, ZERO_ALIGNMENT,
+                   static_cast<byte>(offset)};
     EXPECT_VERIFIES(sigs.i_i(), code);
   }
 }
 
 TEST_F(AstDecoderTest, StoreMemOffset) {
   for (int offset = 0; offset < 128; offset += 7) {
-    byte code[] = {
-        kExprI32StoreMem, 0, static_cast<byte>(offset), kExprI8Const, 0,
-        kExprI8Const,     0};
+    byte code[] = {WASM_STORE_MEM_OFFSET(MachineType::Int32(), offset,
+                                         WASM_ZERO, WASM_ZERO)};
     EXPECT_VERIFIES(sigs.i_i(), code);
   }
 }
 
-TEST_F(AstDecoderTest, LoadMemOffset_varint) {
-  byte code1[] = {kExprI32LoadMem, ZERO_ALIGNMENT, ZERO_OFFSET, kExprI8Const,
-                  0};
-  byte code2[] = {kExprI32LoadMem, ZERO_ALIGNMENT, 0x80, 1, kExprI8Const, 0};
-  byte code3[] = {
-      kExprI32LoadMem, ZERO_ALIGNMENT, 0x81, 0x82, 5, kExprI8Const, 0};
-  byte code4[] = {
-      kExprI32LoadMem, ZERO_ALIGNMENT, 0x83, 0x84, 0x85, 7, kExprI8Const, 0};
+#define BYTE0(x) ((x)&0x7F)
+#define BYTE1(x) ((x >> 7) & 0x7F)
+#define BYTE2(x) ((x >> 14) & 0x7F)
+#define BYTE3(x) ((x >> 21) & 0x7F)
 
-  EXPECT_VERIFIES(sigs.i_i(), code1);
-  EXPECT_VERIFIES(sigs.i_i(), code2);
-  EXPECT_VERIFIES(sigs.i_i(), code3);
-  EXPECT_VERIFIES(sigs.i_i(), code4);
+#define VARINT1(x) BYTE0(x)
+#define VARINT2(x) BYTE0(x) | 0x80, BYTE1(x)
+#define VARINT3(x) BYTE0(x) | 0x80, BYTE1(x) | 0x80, BYTE2(x)
+#define VARINT4(x) BYTE0(x) | 0x80, BYTE1(x) | 0x80, BYTE2(x) | 0x80, BYTE3(x)
+
+TEST_F(AstDecoderTest, LoadMemOffset_varint) {
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_ZERO, kExprI32LoadMem, ZERO_ALIGNMENT,
+                         VARINT1(0x45));
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_ZERO, kExprI32LoadMem, ZERO_ALIGNMENT,
+                         VARINT2(0x3999));
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_ZERO, kExprI32LoadMem, ZERO_ALIGNMENT,
+                         VARINT3(0x344445));
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_ZERO, kExprI32LoadMem, ZERO_ALIGNMENT,
+                         VARINT4(0x36666667));
 }
 
 TEST_F(AstDecoderTest, StoreMemOffset_varint) {
-  byte code1[] = {
-      kExprI32StoreMem, ZERO_ALIGNMENT, 0, kExprI8Const, 0, kExprI8Const, 0};
-  byte code2[] = {kExprI32StoreMem,
-                  ZERO_ALIGNMENT,
-                  0x80,
-                  1,
-                  kExprI8Const,
-                  0,
-                  kExprI8Const,
-                  0};
-  byte code3[] = {kExprI32StoreMem,
-                  ZERO_ALIGNMENT,
-                  0x81,
-                  0x82,
-                  5,
-                  kExprI8Const,
-                  0,
-                  kExprI8Const,
-                  0};
-  byte code4[] = {kExprI32StoreMem,
-                  ZERO_ALIGNMENT,
-                  0x83,
-                  0x84,
-                  0x85,
-                  7,
-                  kExprI8Const,
-                  0,
-                  kExprI8Const,
-                  0};
-
-  EXPECT_VERIFIES(sigs.i_i(), code1);
-  EXPECT_VERIFIES(sigs.i_i(), code2);
-  EXPECT_VERIFIES(sigs.i_i(), code3);
-  EXPECT_VERIFIES(sigs.i_i(), code4);
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_ZERO, WASM_ZERO, kExprI32StoreMem,
+                         ZERO_ALIGNMENT, VARINT1(0x33));
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_ZERO, WASM_ZERO, kExprI32StoreMem,
+                         ZERO_ALIGNMENT, VARINT2(0x1111));
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_ZERO, WASM_ZERO, kExprI32StoreMem,
+                         ZERO_ALIGNMENT, VARINT3(0x222222));
+  EXPECT_VERIFIES_INLINE(sigs.i_i(), WASM_ZERO, WASM_ZERO, kExprI32StoreMem,
+                         ZERO_ALIGNMENT, VARINT4(0x44444444));
 }
 
 TEST_F(AstDecoderTest, AllLoadMemCombinations) {
@@ -966,9 +1121,7 @@
     LocalType local_type = kLocalTypes[i];
     for (size_t j = 0; j < arraysize(machineTypes); j++) {
       MachineType mem_type = machineTypes[j];
-      byte code[] = {
-          static_cast<byte>(WasmOpcodes::LoadStoreOpcodeOf(mem_type, false)),
-          ZERO_ALIGNMENT, ZERO_OFFSET, kExprI8Const, 0};
+      byte code[] = {WASM_LOAD_MEM(mem_type, WASM_ZERO)};
       FunctionSig sig(1, 0, &local_type);
       if (local_type == WasmOpcodes::LocalTypeFor(mem_type)) {
         EXPECT_VERIFIES(&sig, code);
@@ -984,14 +1137,7 @@
     LocalType local_type = kLocalTypes[i];
     for (size_t j = 0; j < arraysize(machineTypes); j++) {
       MachineType mem_type = machineTypes[j];
-      byte code[] = {
-          static_cast<byte>(WasmOpcodes::LoadStoreOpcodeOf(mem_type, true)),
-          ZERO_ALIGNMENT,
-          ZERO_OFFSET,
-          kExprI8Const,
-          0,
-          kExprGetLocal,
-          0};
+      byte code[] = {WASM_STORE_MEM(mem_type, WASM_ZERO, WASM_GET_LOCAL(0))};
       FunctionSig sig(0, 1, &local_type);
       if (local_type == WasmOpcodes::LocalTypeFor(mem_type)) {
         EXPECT_VERIFIES(&sig, code);
@@ -1002,7 +1148,6 @@
   }
 }
 
-
 namespace {
 // A helper for tests that require a module environment for functions and
 // globals.
@@ -1011,7 +1156,6 @@
   TestModuleEnv() {
     instance = nullptr;
     module = &mod;
-    linker = nullptr;
   }
   byte AddGlobal(MachineType mem_type) {
     mod.globals.push_back({0, 0, mem_type, 0, false});
@@ -1024,12 +1168,23 @@
     return static_cast<byte>(mod.signatures.size() - 1);
   }
   byte AddFunction(FunctionSig* sig) {
-    mod.functions.push_back({sig, 0, 0, 0, 0, 0, 0, 0, false, false});
+    mod.functions.push_back({sig,  // sig
+                             0,    // func_index
+                             0,    // sig_index
+                             0,    // name_offset
+                             0,    // name_length
+                             0,    // code_start_offset
+                             0});  // code_end_offset
     CHECK(mod.functions.size() <= 127);
     return static_cast<byte>(mod.functions.size() - 1);
   }
   byte AddImport(FunctionSig* sig) {
-    mod.import_table.push_back({sig, 0, 0});
+    mod.import_table.push_back({sig,  // sig
+                                0,    // sig_index
+                                0,    // module_name_offset
+                                0,    // module_name_length
+                                0,    // function_name_offset
+                                0});  // function_name_length
     CHECK(mod.import_table.size() <= 127);
     return static_cast<byte>(mod.import_table.size() - 1);
   }
@@ -1048,9 +1203,9 @@
   module_env.AddFunction(sigs.i_i());
   module_env.AddFunction(sigs.i_ii());
 
-  EXPECT_VERIFIES_INLINE(sig, WASM_CALL_FUNCTION(0));
-  EXPECT_VERIFIES_INLINE(sig, WASM_CALL_FUNCTION(1, WASM_I8(27)));
-  EXPECT_VERIFIES_INLINE(sig, WASM_CALL_FUNCTION(2, WASM_I8(37), WASM_I8(77)));
+  EXPECT_VERIFIES_INLINE(sig, WASM_CALL_FUNCTION0(0));
+  EXPECT_VERIFIES_INLINE(sig, WASM_CALL_FUNCTION1(1, WASM_I8(27)));
+  EXPECT_VERIFIES_INLINE(sig, WASM_CALL_FUNCTION2(2, WASM_I8(37), WASM_I8(77)));
 }
 
 TEST_F(AstDecoderTest, CallsWithTooFewArguments) {
@@ -1063,35 +1218,8 @@
   module_env.AddFunction(sigs.f_ff());
 
   EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION0(0));
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(1, WASM_ZERO));
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(2, WASM_GET_LOCAL(0)));
-}
-
-TEST_F(AstDecoderTest, CallsWithSpilloverArgs) {
-  static LocalType a_i_ff[] = {kAstI32, kAstF32, kAstF32};
-  FunctionSig sig_i_ff(1, 2, a_i_ff);
-
-  TestModuleEnv module_env;
-  module = &module_env;
-
-  module_env.AddFunction(&sig_i_ff);
-
-  EXPECT_VERIFIES_INLINE(sigs.i_i(),
-                         WASM_CALL_FUNCTION(0, WASM_F32(0.1), WASM_F32(0.1)));
-
-  EXPECT_VERIFIES_INLINE(sigs.i_ff(),
-                         WASM_CALL_FUNCTION(0, WASM_F32(0.1), WASM_F32(0.1)));
-
-  EXPECT_FAILURE_INLINE(sigs.f_ff(),
-                        WASM_CALL_FUNCTION(0, WASM_F32(0.1), WASM_F32(0.1)));
-
-  EXPECT_FAILURE_INLINE(
-      sigs.i_i(),
-      WASM_CALL_FUNCTION(0, WASM_F32(0.1), WASM_F32(0.1), WASM_F32(0.2)));
-
-  EXPECT_VERIFIES_INLINE(
-      sigs.f_ff(),
-      WASM_CALL_FUNCTION(0, WASM_F32(0.1), WASM_F32(0.1), WASM_F32(11)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(1, WASM_ZERO));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(2, WASM_GET_LOCAL(0)));
 }
 
 TEST_F(AstDecoderTest, CallsWithMismatchedSigs2) {
@@ -1101,9 +1229,9 @@
 
   module_env.AddFunction(sigs.i_i());
 
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(0, WASM_I64V_1(17)));
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(0, WASM_F32(17.1)));
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(0, WASM_F64(17.1)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(0, WASM_I64V_1(17)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(0, WASM_F32(17.1)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(0, WASM_F64(17.1)));
 }
 
 TEST_F(AstDecoderTest, CallsWithMismatchedSigs3) {
@@ -1113,15 +1241,15 @@
 
   module_env.AddFunction(sigs.i_f());
 
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(0, WASM_I8(17)));
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(0, WASM_I64V_1(27)));
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(0, WASM_F64(37.2)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(0, WASM_I8(17)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(0, WASM_I64V_1(27)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(0, WASM_F64(37.2)));
 
   module_env.AddFunction(sigs.i_d());
 
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(1, WASM_I8(16)));
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(1, WASM_I64V_1(16)));
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION(1, WASM_F32(17.6)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(1, WASM_I8(16)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(1, WASM_I64V_1(16)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_FUNCTION1(1, WASM_F32(17.6)));
 }
 
 TEST_F(AstDecoderTest, SimpleIndirectCalls) {
@@ -1134,9 +1262,9 @@
   byte f2 = module_env.AddSignature(sigs.i_ii());
 
   EXPECT_VERIFIES_INLINE(sig, WASM_CALL_INDIRECT0(f0, WASM_ZERO));
-  EXPECT_VERIFIES_INLINE(sig, WASM_CALL_INDIRECT(f1, WASM_ZERO, WASM_I8(22)));
+  EXPECT_VERIFIES_INLINE(sig, WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_I8(22)));
   EXPECT_VERIFIES_INLINE(
-      sig, WASM_CALL_INDIRECT(f2, WASM_ZERO, WASM_I8(32), WASM_I8(72)));
+      sig, WASM_CALL_INDIRECT2(f2, WASM_ZERO, WASM_I8(32), WASM_I8(72)));
 }
 
 TEST_F(AstDecoderTest, IndirectCallsOutOfBounds) {
@@ -1148,11 +1276,11 @@
   module_env.AddSignature(sigs.i_v());
   EXPECT_VERIFIES_INLINE(sig, WASM_CALL_INDIRECT0(0, WASM_ZERO));
 
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT(1, WASM_ZERO, WASM_I8(22)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT1(1, WASM_ZERO, WASM_I8(22)));
   module_env.AddSignature(sigs.i_i());
-  EXPECT_VERIFIES_INLINE(sig, WASM_CALL_INDIRECT(1, WASM_ZERO, WASM_I8(27)));
+  EXPECT_VERIFIES_INLINE(sig, WASM_CALL_INDIRECT1(1, WASM_ZERO, WASM_I8(27)));
 
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT(2, WASM_ZERO, WASM_I8(27)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT1(2, WASM_ZERO, WASM_I8(27)));
 }
 
 TEST_F(AstDecoderTest, IndirectCallsWithMismatchedSigs3) {
@@ -1162,10 +1290,11 @@
 
   byte f0 = module_env.AddFunction(sigs.i_f());
 
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT(f0, WASM_ZERO, WASM_I8(17)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT1(f0, WASM_ZERO, WASM_I8(17)));
   EXPECT_FAILURE_INLINE(sig,
-                        WASM_CALL_INDIRECT(f0, WASM_ZERO, WASM_I64V_1(27)));
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT(f0, WASM_ZERO, WASM_F64(37.2)));
+                        WASM_CALL_INDIRECT1(f0, WASM_ZERO, WASM_I64V_1(27)));
+  EXPECT_FAILURE_INLINE(sig,
+                        WASM_CALL_INDIRECT1(f0, WASM_ZERO, WASM_F64(37.2)));
 
   EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT0(f0, WASM_I8(17)));
   EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT0(f0, WASM_I64V_1(27)));
@@ -1173,10 +1302,11 @@
 
   byte f1 = module_env.AddFunction(sigs.i_d());
 
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT(f1, WASM_ZERO, WASM_I8(16)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_I8(16)));
   EXPECT_FAILURE_INLINE(sig,
-                        WASM_CALL_INDIRECT(f1, WASM_ZERO, WASM_I64V_1(16)));
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_INDIRECT(f1, WASM_ZERO, WASM_F32(17.6)));
+                        WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_I64V_1(16)));
+  EXPECT_FAILURE_INLINE(sig,
+                        WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_F32(17.6)));
 }
 
 TEST_F(AstDecoderTest, SimpleImportCalls) {
@@ -1189,8 +1319,8 @@
   byte f2 = module_env.AddImport(sigs.i_ii());
 
   EXPECT_VERIFIES_INLINE(sig, WASM_CALL_IMPORT0(f0));
-  EXPECT_VERIFIES_INLINE(sig, WASM_CALL_IMPORT(f1, WASM_I8(22)));
-  EXPECT_VERIFIES_INLINE(sig, WASM_CALL_IMPORT(f2, WASM_I8(32), WASM_I8(72)));
+  EXPECT_VERIFIES_INLINE(sig, WASM_CALL_IMPORT1(f1, WASM_I8(22)));
+  EXPECT_VERIFIES_INLINE(sig, WASM_CALL_IMPORT2(f2, WASM_I8(32), WASM_I8(72)));
 }
 
 TEST_F(AstDecoderTest, ImportCallsWithMismatchedSigs3) {
@@ -1201,16 +1331,16 @@
   byte f0 = module_env.AddImport(sigs.i_f());
 
   EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT0(f0));
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT(f0, WASM_I8(17)));
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT(f0, WASM_I64V_1(27)));
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT(f0, WASM_F64(37.2)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT1(f0, WASM_I8(17)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT1(f0, WASM_I64V_1(27)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT1(f0, WASM_F64(37.2)));
 
   byte f1 = module_env.AddImport(sigs.i_d());
 
   EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT0(f1));
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT(f1, WASM_I8(16)));
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT(f1, WASM_I64V_1(16)));
-  EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT(f1, WASM_F32(17.6)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT1(f1, WASM_I8(16)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT1(f1, WASM_I64V_1(16)));
+  EXPECT_FAILURE_INLINE(sig, WASM_CALL_IMPORT1(f1, WASM_F32(17.6)));
 }
 
 TEST_F(AstDecoderTest, Int32Globals) {
@@ -1334,11 +1464,29 @@
   }
 }
 
+TEST_F(AstDecoderTest, BreakEnd) {
+  EXPECT_VERIFIES_INLINE(sigs.i_i(),
+                         B1(WASM_I32_ADD(WASM_BRV(0, WASM_ZERO), WASM_ZERO)));
+  EXPECT_VERIFIES_INLINE(sigs.i_i(),
+                         B1(WASM_I32_ADD(WASM_ZERO, WASM_BRV(0, WASM_ZERO))));
+}
+
+TEST_F(AstDecoderTest, BreakIfBinop) {
+  EXPECT_FAILURE_INLINE(
+      sigs.i_i(),
+      WASM_BLOCK(
+          1, WASM_I32_ADD(WASM_BRV_IF(0, WASM_ZERO, WASM_ZERO), WASM_ZERO)));
+  EXPECT_FAILURE_INLINE(
+      sigs.i_i(),
+      WASM_BLOCK(
+          1, WASM_I32_ADD(WASM_ZERO, WASM_BRV_IF(0, WASM_ZERO, WASM_ZERO))));
+}
+
 TEST_F(AstDecoderTest, BreakNesting1) {
   for (int i = 0; i < 5; i++) {
     // (block[2] (loop[2] (if (get p) break[N]) (set p 1)) p)
     byte code[] = {WASM_BLOCK(
-        2, WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(i, WASM_ZERO)),
+        2, WASM_LOOP(2, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(i + 1, WASM_ZERO)),
                      WASM_SET_LOCAL(0, WASM_I8(1))),
         WASM_GET_LOCAL(0))};
     if (i < 3) {
@@ -1353,8 +1501,8 @@
   AddLocals(kAstI32, 1);
   for (int i = 0; i < 5; i++) {
     // (block[2] (loop[2] (if 0 break[N]) (set p 1)) (return p)) (11)
-    byte code[] = {WASM_BLOCK(1, WASM_LOOP(2, WASM_IF(WASM_ZERO, WASM_BREAK(i)),
-                                           WASM_SET_LOCAL(0, WASM_I8(1)))),
+    byte code[] = {B1(WASM_LOOP(2, WASM_IF(WASM_ZERO, WASM_BREAK(i + 1)),
+                                WASM_SET_LOCAL(0, WASM_I8(1)))),
                    WASM_I8(11)};
     if (i < 2) {
       EXPECT_VERIFIES(sigs.v_v(), code);
@@ -1367,8 +1515,8 @@
 TEST_F(AstDecoderTest, BreakNesting3) {
   for (int i = 0; i < 5; i++) {
     // (block[1] (loop[1] (block[1] (if 0 break[N])
-    byte code[] = {WASM_BLOCK(
-        1, WASM_LOOP(1, WASM_BLOCK(1, WASM_IF(WASM_ZERO, WASM_BREAK(i)))))};
+    byte code[] = {
+        WASM_BLOCK(1, WASM_LOOP(1, B1(WASM_IF(WASM_ZERO, WASM_BREAK(i + 1)))))};
     if (i < 3) {
       EXPECT_VERIFIES(sigs.v_v(), code);
     } else {
@@ -1378,41 +1526,42 @@
 }
 
 TEST_F(AstDecoderTest, BreaksWithMultipleTypes) {
-  EXPECT_FAILURE_INLINE(
-      sigs.i_i(),
-      WASM_BLOCK(2, WASM_BRV_IF_ZERO(0, WASM_I8(7)), WASM_F32(7.7)));
+  EXPECT_FAILURE_INLINE(sigs.i_i(),
+                        B2(WASM_BRV_IF_ZERO(0, WASM_I8(7)), WASM_F32(7.7)));
 
-  EXPECT_FAILURE_INLINE(sigs.i_i(),
-                        WASM_BLOCK(2, WASM_BRV_IF_ZERO(0, WASM_I8(7)),
-                                   WASM_BRV_IF_ZERO(0, WASM_F32(7.7))));
-  EXPECT_FAILURE_INLINE(sigs.i_i(),
-                        WASM_BLOCK(3, WASM_BRV_IF_ZERO(0, WASM_I8(8)),
-                                   WASM_BRV_IF_ZERO(0, WASM_I8(0)),
-                                   WASM_BRV_IF_ZERO(0, WASM_F32(7.7))));
-  EXPECT_FAILURE_INLINE(sigs.i_i(),
-                        WASM_BLOCK(3, WASM_BRV_IF_ZERO(0, WASM_I8(9)),
-                                   WASM_BRV_IF_ZERO(0, WASM_F32(7.7)),
-                                   WASM_BRV_IF_ZERO(0, WASM_I8(11))));
+  EXPECT_FAILURE_INLINE(sigs.i_i(), B2(WASM_BRV_IF_ZERO(0, WASM_I8(7)),
+                                       WASM_BRV_IF_ZERO(0, WASM_F32(7.7))));
+  EXPECT_FAILURE_INLINE(sigs.i_i(), B3(WASM_BRV_IF_ZERO(0, WASM_I8(8)),
+                                       WASM_BRV_IF_ZERO(0, WASM_I8(0)),
+                                       WASM_BRV_IF_ZERO(0, WASM_F32(7.7))));
+  EXPECT_FAILURE_INLINE(sigs.i_i(), B3(WASM_BRV_IF_ZERO(0, WASM_I8(9)),
+                                       WASM_BRV_IF_ZERO(0, WASM_F32(7.7)),
+                                       WASM_BRV_IF_ZERO(0, WASM_I8(11))));
 }
 
 TEST_F(AstDecoderTest, BreakNesting_6_levels) {
   for (int mask = 0; mask < 64; mask++) {
     for (int i = 0; i < 14; i++) {
       byte code[] = {
-          kExprBlock, 1,  // --
-          kExprBlock, 1,  // --
-          kExprBlock, 1,  // --
-          kExprBlock, 1,  // --
-          kExprBlock, 1,  // --
-          kExprBlock, 1,  // --
-          kExprBr,    static_cast<byte>(i),
-          kExprNop  // --
+          kExprBlock,                                 // --
+          kExprBlock,                                 // --
+          kExprBlock,                                 // --
+          kExprBlock,                                 // --
+          kExprBlock,                                 // --
+          kExprBlock,                                 // --
+          kExprBr,    ARITY_0, static_cast<byte>(i),  // --
+          kExprEnd,                                   // --
+          kExprEnd,                                   // --
+          kExprEnd,                                   // --
+          kExprEnd,                                   // --
+          kExprEnd,                                   // --
+          kExprEnd                                    // --
       };
 
       int depth = 6;
       for (int l = 0; l < 6; l++) {
         if (mask & (1 << l)) {
-          code[l * 2] = kExprLoop;
+          code[l] = kExprLoop;
           depth++;
         }
       }
@@ -1432,29 +1581,27 @@
     FunctionSig* sig = sigarray[i];
     // unify X and X => OK
     EXPECT_VERIFIES_INLINE(
-        sig, WASM_BLOCK(2, WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_GET_LOCAL(0))),
-                        WASM_GET_LOCAL(0)));
+        sig, B2(WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_GET_LOCAL(0))),
+                WASM_GET_LOCAL(0)));
   }
 
   // unify i32 and f32 => fail
   EXPECT_FAILURE_INLINE(
       sigs.i_i(),
-      WASM_BLOCK(2, WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_ZERO)), WASM_F32(1.2)));
+      B2(WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_ZERO)), WASM_F32(1.2)));
 
   // unify f64 and f64 => OK
   EXPECT_VERIFIES_INLINE(
       sigs.d_dd(),
-      WASM_BLOCK(2, WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_GET_LOCAL(0))),
-                 WASM_F64(1.2)));
+      B2(WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_GET_LOCAL(0))), WASM_F64(1.2)));
 }
 
 TEST_F(AstDecoderTest, ExprBreak_TypeCheckAll) {
   byte code1[] = {WASM_BLOCK(2,
                              WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_GET_LOCAL(0))),
                              WASM_GET_LOCAL(1))};
-  byte code2[] = {
-      WASM_BLOCK(2, WASM_IF(WASM_ZERO, WASM_BRV_IF_ZERO(0, WASM_GET_LOCAL(0))),
-                 WASM_GET_LOCAL(1))};
+  byte code2[] = {B2(WASM_IF(WASM_ZERO, WASM_BRV_IF_ZERO(0, WASM_GET_LOCAL(0))),
+                     WASM_GET_LOCAL(1))};
 
   for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
     for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
@@ -1479,14 +1626,12 @@
       LocalType storage[] = {kAstI32, kAstI32, type};
       FunctionSig sig(1, 2, storage);
 
-      byte code1[] = {
-          WASM_BLOCK(2, WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_GET_LOCAL(which))),
-                     WASM_GET_LOCAL(which ^ 1))};
+      byte code1[] = {B2(WASM_IF(WASM_ZERO, WASM_BRV(1, WASM_GET_LOCAL(which))),
+                         WASM_GET_LOCAL(which ^ 1))};
       byte code2[] = {
-          WASM_LOOP(2, WASM_IF(WASM_ZERO, WASM_BRV(1, WASM_GET_LOCAL(which))),
+          WASM_LOOP(2, WASM_IF(WASM_ZERO, WASM_BRV(2, WASM_GET_LOCAL(which))),
                     WASM_GET_LOCAL(which ^ 1))};
 
-
       if (type == kAstI32) {
         EXPECT_VERIFIES(&sig, code1);
         EXPECT_VERIFIES(&sig, code2);
@@ -1499,8 +1644,7 @@
 }
 
 TEST_F(AstDecoderTest, ExprBrIf_cond_type) {
-  byte code[] = {
-      WASM_BLOCK(1, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))};
+  byte code[] = {B1(WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))};
   for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
     for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
       LocalType types[] = {kLocalTypes[i], kLocalTypes[j]};
@@ -1516,9 +1660,8 @@
 }
 
 TEST_F(AstDecoderTest, ExprBrIf_val_type) {
-  byte code[] = {
-      WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(1), WASM_GET_LOCAL(2)),
-                 WASM_GET_LOCAL(0))};
+  byte code[] = {B2(WASM_BRV_IF(0, WASM_GET_LOCAL(1), WASM_GET_LOCAL(2)),
+                    WASM_GET_LOCAL(0))};
   for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
     for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
       LocalType types[] = {kLocalTypes[i], kLocalTypes[i], kLocalTypes[j],
@@ -1541,8 +1684,8 @@
       LocalType storage[] = {kAstI32, kAstI32, type};
       FunctionSig sig(1, 2, storage);
 
-      byte code1[] = {WASM_BLOCK(2, WASM_BRV_IF_ZERO(0, WASM_GET_LOCAL(which)),
-                                 WASM_GET_LOCAL(which ^ 1))};
+      byte code1[] = {B2(WASM_BRV_IF_ZERO(0, WASM_GET_LOCAL(which)),
+                         WASM_GET_LOCAL(which ^ 1))};
       byte code2[] = {WASM_LOOP(2, WASM_BRV_IF_ZERO(1, WASM_GET_LOCAL(which)),
                                 WASM_GET_LOCAL(which ^ 1))};
 
@@ -1558,31 +1701,29 @@
 }
 
 TEST_F(AstDecoderTest, BrTable0) {
-  static byte code[] = {kExprBrTable, 0, 0};
+  static byte code[] = {kExprNop, kExprBrTable, 0, 0};
   EXPECT_FAILURE(sigs.v_v(), code);
 }
 
 TEST_F(AstDecoderTest, BrTable0b) {
-  static byte code[] = {kExprBrTable, 0, 0, kExprI32Const, 11};
+  static byte code[] = {kExprNop, kExprI32Const, 11, kExprBrTable, 0, 0};
   EXPECT_FAILURE(sigs.v_v(), code);
   EXPECT_FAILURE(sigs.i_i(), code);
 }
 
 TEST_F(AstDecoderTest, BrTable0c) {
-  static byte code[] = {kExprBrTable, 0, 1, 0, 0, kExprI32Const, 11};
+  static byte code[] = {kExprNop, kExprI32Const, 11, kExprBrTable, 0, 1, 0, 0};
   EXPECT_FAILURE(sigs.v_v(), code);
   EXPECT_FAILURE(sigs.i_i(), code);
 }
 
 TEST_F(AstDecoderTest, BrTable1a) {
-  static byte code[] = {
-      WASM_BLOCK(1, WASM_BR_TABLE(WASM_I8(67), 0, BR_TARGET(0)))};
+  static byte code[] = {B1(WASM_BR_TABLE(WASM_I8(67), 0, BR_TARGET(0)))};
   EXPECT_VERIFIES(sigs.v_v(), code);
 }
 
 TEST_F(AstDecoderTest, BrTable1b) {
-  static byte code[] = {
-      WASM_BLOCK(1, WASM_BR_TABLE(WASM_ZERO, 0, BR_TARGET(0)))};
+  static byte code[] = {B1(WASM_BR_TABLE(WASM_ZERO, 0, BR_TARGET(0)))};
   EXPECT_VERIFIES(sigs.v_v(), code);
   EXPECT_FAILURE(sigs.i_i(), code);
   EXPECT_FAILURE(sigs.f_ff(), code);
@@ -1591,7 +1732,7 @@
 
 TEST_F(AstDecoderTest, BrTable2a) {
   static byte code[] = {
-      WASM_BLOCK(1, WASM_BR_TABLE(WASM_I8(67), 1, BR_TARGET(0), BR_TARGET(0)))};
+      B1(WASM_BR_TABLE(WASM_I8(67), 1, BR_TARGET(0), BR_TARGET(0)))};
   EXPECT_VERIFIES(sigs.v_v(), code);
 }
 
@@ -1603,8 +1744,7 @@
 }
 
 TEST_F(AstDecoderTest, BrTable_off_end) {
-  static byte code[] = {
-      WASM_BLOCK(1, WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0)))};
+  static byte code[] = {B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0)))};
   for (size_t len = 1; len < sizeof(code); len++) {
     Verify(kError, sigs.i_i(), code, code + len);
   }
@@ -1612,8 +1752,7 @@
 
 TEST_F(AstDecoderTest, BrTable_invalid_br1) {
   for (int depth = 0; depth < 4; depth++) {
-    byte code[] = {
-        WASM_BLOCK(1, WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(depth)))};
+    byte code[] = {B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(depth)))};
     if (depth == 0) {
       EXPECT_VERIFIES(sigs.v_i(), code);
     } else {
@@ -1635,11 +1774,10 @@
 }
 
 TEST_F(AstDecoderTest, ExprBreakNesting1) {
-  EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_BLOCK(1, WASM_BRV(0, WASM_ZERO)));
-  EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_BLOCK(1, WASM_BR(0)));
-  EXPECT_VERIFIES_INLINE(sigs.v_v(),
-                         WASM_BLOCK(1, WASM_BRV_IF(0, WASM_ZERO, WASM_ZERO)));
-  EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_BLOCK(1, WASM_BR_IF(0, WASM_ZERO)));
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), B1(WASM_BRV(0, WASM_ZERO)));
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), B1(WASM_BR(0)));
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), B1(WASM_BRV_IF(0, WASM_ZERO, WASM_ZERO)));
+  EXPECT_VERIFIES_INLINE(sigs.v_v(), B1(WASM_BR_IF(0, WASM_ZERO)));
 
   EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_LOOP(1, WASM_BRV(0, WASM_ZERO)));
   EXPECT_VERIFIES_INLINE(sigs.v_v(), WASM_LOOP(1, WASM_BR(0)));
@@ -1714,7 +1852,6 @@
       WASM_SELECT(WASM_F32(9.9), WASM_GET_LOCAL(0), WASM_I64V_1(0)));
 }
 
-
 class WasmOpcodeLengthTest : public TestWithZone {
  public:
   WasmOpcodeLengthTest() : TestWithZone() {}
@@ -1734,16 +1871,16 @@
 
 TEST_F(WasmOpcodeLengthTest, Statements) {
   EXPECT_LENGTH(1, kExprNop);
-  EXPECT_LENGTH(2, kExprBlock);
-  EXPECT_LENGTH(2, kExprLoop);
+  EXPECT_LENGTH(1, kExprBlock);
+  EXPECT_LENGTH(1, kExprLoop);
   EXPECT_LENGTH(1, kExprIf);
-  EXPECT_LENGTH(1, kExprIfElse);
+  EXPECT_LENGTH(1, kExprElse);
+  EXPECT_LENGTH(1, kExprEnd);
   EXPECT_LENGTH(1, kExprSelect);
-  EXPECT_LENGTH(2, kExprBr);
-  EXPECT_LENGTH(2, kExprBrIf);
+  EXPECT_LENGTH(3, kExprBr);
+  EXPECT_LENGTH(3, kExprBrIf);
 }
 
-
 TEST_F(WasmOpcodeLengthTest, MiscExpressions) {
   EXPECT_LENGTH(2, kExprI8Const);
   EXPECT_LENGTH(5, kExprF32Const);
@@ -1752,15 +1889,14 @@
   EXPECT_LENGTH(2, kExprSetLocal);
   EXPECT_LENGTH(2, kExprLoadGlobal);
   EXPECT_LENGTH(2, kExprStoreGlobal);
-  EXPECT_LENGTH(2, kExprCallFunction);
-  EXPECT_LENGTH(2, kExprCallImport);
-  EXPECT_LENGTH(2, kExprCallIndirect);
+  EXPECT_LENGTH(3, kExprCallFunction);
+  EXPECT_LENGTH(3, kExprCallImport);
+  EXPECT_LENGTH(3, kExprCallIndirect);
   EXPECT_LENGTH(1, kExprIf);
-  EXPECT_LENGTH(1, kExprIfElse);
-  EXPECT_LENGTH(2, kExprBlock);
-  EXPECT_LENGTH(2, kExprLoop);
-  EXPECT_LENGTH(2, kExprBr);
-  EXPECT_LENGTH(2, kExprBrIf);
+  EXPECT_LENGTH(1, kExprBlock);
+  EXPECT_LENGTH(1, kExprLoop);
+  EXPECT_LENGTH(3, kExprBr);
+  EXPECT_LENGTH(3, kExprBrIf);
 }
 
 TEST_F(WasmOpcodeLengthTest, I32Const) {
@@ -1818,13 +1954,11 @@
   EXPECT_LENGTH(3, kExprF64StoreMem);
 }
 
-
 TEST_F(WasmOpcodeLengthTest, MiscMemExpressions) {
   EXPECT_LENGTH(1, kExprMemorySize);
   EXPECT_LENGTH(1, kExprGrowMemory);
 }
 
-
 TEST_F(WasmOpcodeLengthTest, SimpleExpressions) {
   EXPECT_LENGTH(1, kExprI32Add);
   EXPECT_LENGTH(1, kExprI32Sub);
@@ -1946,54 +2080,49 @@
   EXPECT_LENGTH(1, kExprI64ReinterpretF64);
 }
 
-
 class WasmOpcodeArityTest : public TestWithZone {
  public:
   WasmOpcodeArityTest() : TestWithZone() {}
-  TestModuleEnv module;
-  TestSignatures sigs;
 };
 
-#define EXPECT_ARITY(expected, ...)                                            \
-  {                                                                            \
-    static const byte code[] = {__VA_ARGS__};                                  \
-    EXPECT_EQ(expected, OpcodeArity(&module, sig, code, code + sizeof(code))); \
+#define EXPECT_ARITY(expected, ...)                              \
+  {                                                              \
+    static const byte code[] = {__VA_ARGS__};                    \
+    EXPECT_EQ(expected, OpcodeArity(code, code + sizeof(code))); \
   }
 
 TEST_F(WasmOpcodeArityTest, Control) {
-  FunctionSig* sig = sigs.v_v();
   EXPECT_ARITY(0, kExprNop);
 
   EXPECT_ARITY(0, kExprBlock, 0);
-  EXPECT_ARITY(1, kExprBlock, 1);
-  EXPECT_ARITY(2, kExprBlock, 2);
-  EXPECT_ARITY(5, kExprBlock, 5);
-  EXPECT_ARITY(10, kExprBlock, 10);
+  EXPECT_ARITY(0, kExprBlock, 1);
+  EXPECT_ARITY(0, kExprBlock, 2);
+  EXPECT_ARITY(0, kExprBlock, 5);
+  EXPECT_ARITY(0, kExprBlock, 10);
 
   EXPECT_ARITY(0, kExprLoop, 0);
-  EXPECT_ARITY(1, kExprLoop, 1);
-  EXPECT_ARITY(2, kExprLoop, 2);
-  EXPECT_ARITY(7, kExprLoop, 7);
-  EXPECT_ARITY(11, kExprLoop, 11);
+  EXPECT_ARITY(0, kExprLoop, 1);
+  EXPECT_ARITY(0, kExprLoop, 2);
+  EXPECT_ARITY(0, kExprLoop, 7);
+  EXPECT_ARITY(0, kExprLoop, 11);
 
-  EXPECT_ARITY(2, kExprIf);
-  EXPECT_ARITY(3, kExprIfElse);
   EXPECT_ARITY(3, kExprSelect);
 
-  EXPECT_ARITY(1, kExprBr);
-  EXPECT_ARITY(2, kExprBrIf);
+  EXPECT_ARITY(0, kExprBr);
+  EXPECT_ARITY(1, kExprBrIf);
+  EXPECT_ARITY(1, kExprBrTable);
+
+  EXPECT_ARITY(1, kExprBr, ARITY_1);
+  EXPECT_ARITY(2, kExprBrIf, ARITY_1);
+  EXPECT_ARITY(2, kExprBrTable, ARITY_1);
 
   {
-    sig = sigs.v_v();
-    EXPECT_ARITY(0, kExprReturn);
-    sig = sigs.i_i();
-    EXPECT_ARITY(1, kExprReturn);
+    EXPECT_ARITY(0, kExprReturn, ARITY_0);
+    EXPECT_ARITY(1, kExprReturn, ARITY_1);
   }
 }
 
-
 TEST_F(WasmOpcodeArityTest, Misc) {
-  FunctionSig* sig = sigs.v_v();
   EXPECT_ARITY(0, kExprI8Const);
   EXPECT_ARITY(0, kExprI32Const);
   EXPECT_ARITY(0, kExprF32Const);
@@ -2005,41 +2134,37 @@
   EXPECT_ARITY(1, kExprStoreGlobal);
 }
 
-
 TEST_F(WasmOpcodeArityTest, Calls) {
-  module.AddFunction(sigs.i_ii());
-  module.AddFunction(sigs.i_i());
-
-  module.AddSignature(sigs.f_ff());
-  module.AddSignature(sigs.i_d());
-
-  module.AddImport(sigs.f_ff());
-  module.AddImport(sigs.i_d());
-
   {
-    FunctionSig* sig = sigs.i_ii();
+    EXPECT_ARITY(2, kExprCallFunction, 2, 0);
+    EXPECT_ARITY(2, kExprCallImport, 2, 0);
+    EXPECT_ARITY(3, kExprCallIndirect, 2, 0);
 
-    EXPECT_ARITY(2, kExprCallFunction, 0);
-    EXPECT_ARITY(2, kExprCallImport, 0);
-    EXPECT_ARITY(3, kExprCallIndirect, 0);
-    EXPECT_ARITY(1, kExprBr);
-    EXPECT_ARITY(2, kExprBrIf);
+    EXPECT_ARITY(1, kExprBr, ARITY_1);
+    EXPECT_ARITY(2, kExprBrIf, ARITY_1);
+    EXPECT_ARITY(2, kExprBrTable, ARITY_1);
+
+    EXPECT_ARITY(0, kExprBr, ARITY_0);
+    EXPECT_ARITY(1, kExprBrIf, ARITY_0);
+    EXPECT_ARITY(1, kExprBrTable, ARITY_0);
   }
 
   {
-    FunctionSig* sig = sigs.v_v();
+    EXPECT_ARITY(1, kExprCallFunction, ARITY_1, 1);
+    EXPECT_ARITY(1, kExprCallImport, ARITY_1, 1);
+    EXPECT_ARITY(2, kExprCallIndirect, ARITY_1, 1);
 
-    EXPECT_ARITY(1, kExprCallFunction, 1);
-    EXPECT_ARITY(1, kExprCallImport, 1);
-    EXPECT_ARITY(2, kExprCallIndirect, 1);
-    EXPECT_ARITY(1, kExprBr);
-    EXPECT_ARITY(2, kExprBrIf);
+    EXPECT_ARITY(1, kExprBr, ARITY_1);
+    EXPECT_ARITY(2, kExprBrIf, ARITY_1);
+    EXPECT_ARITY(2, kExprBrTable, ARITY_1);
+
+    EXPECT_ARITY(0, kExprBr, ARITY_0);
+    EXPECT_ARITY(1, kExprBrIf, ARITY_0);
+    EXPECT_ARITY(1, kExprBrTable, ARITY_0);
   }
 }
 
-
 TEST_F(WasmOpcodeArityTest, LoadsAndStores) {
-  FunctionSig* sig = sigs.v_v();
   EXPECT_ARITY(1, kExprI32LoadMem8S);
   EXPECT_ARITY(1, kExprI32LoadMem8U);
   EXPECT_ARITY(1, kExprI32LoadMem16S);
@@ -2067,16 +2192,12 @@
   EXPECT_ARITY(2, kExprF64StoreMem);
 }
 
-
 TEST_F(WasmOpcodeArityTest, MiscMemExpressions) {
-  FunctionSig* sig = sigs.v_v();
   EXPECT_ARITY(0, kExprMemorySize);
   EXPECT_ARITY(1, kExprGrowMemory);
 }
 
-
 TEST_F(WasmOpcodeArityTest, SimpleExpressions) {
-  FunctionSig* sig = sigs.v_v();
   EXPECT_ARITY(2, kExprI32Add);
   EXPECT_ARITY(2, kExprI32Sub);
   EXPECT_ARITY(2, kExprI32Mul);
@@ -2246,7 +2367,7 @@
 
     LocalTypeMap map = Expand(decls);
     EXPECT_EQ(1, map.size());
-    EXPECT_EQ(type, map.at(0));
+    EXPECT_EQ(type, map[0]);
   }
 }
 
@@ -2297,12 +2418,12 @@
 TEST_F(LocalDeclDecoderTest, UseEncoder) {
   const byte* data = nullptr;
   const byte* end = nullptr;
-  LocalDeclEncoder local_decls;
+  LocalDeclEncoder local_decls(zone());
 
   local_decls.AddLocals(5, kAstF32);
   local_decls.AddLocals(1337, kAstI32);
   local_decls.AddLocals(212, kAstI64);
-  local_decls.Prepend(&data, &end);
+  local_decls.Prepend(zone(), &data, &end);
 
   AstLocalDecls decls(zone());
   bool result = DecodeLocalDecls(decls, data, end);
@@ -2314,7 +2435,6 @@
   pos = ExpectRun(map, pos, kAstF32, 5);
   pos = ExpectRun(map, pos, kAstI32, 1337);
   pos = ExpectRun(map, pos, kAstI64, 212);
-  delete[] data;
 }
 
 }  // namespace wasm
diff --git a/test/unittests/wasm/control-transfer-unittest.cc b/test/unittests/wasm/control-transfer-unittest.cc
new file mode 100644
index 0000000..2b67f12
--- /dev/null
+++ b/test/unittests/wasm/control-transfer-unittest.cc
@@ -0,0 +1,402 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "test/unittests/test-utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+#include "src/v8.h"
+
+#include "src/wasm/wasm-interpreter.h"
+#include "src/wasm/wasm-macro-gen.h"
+
+using testing::MakeMatcher;
+using testing::Matcher;
+using testing::MatcherInterface;
+using testing::MatchResultListener;
+using testing::StringMatchResultListener;
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+#define B1(a) kExprBlock, a, kExprEnd
+#define B2(a, b) kExprBlock, a, b, kExprEnd
+#define B3(a, b, c) kExprBlock, a, b, c, kExprEnd
+
+struct ExpectedTarget {
+  pc_t pc;
+  ControlTransfer expected;
+};
+
+// For nicer error messages.
+class ControlTransferMatcher : public MatcherInterface<const ControlTransfer&> {
+ public:
+  explicit ControlTransferMatcher(pc_t pc, const ControlTransfer& expected)
+      : pc_(pc), expected_(expected) {}
+
+  void DescribeTo(std::ostream* os) const override {
+    *os << "@" << pc_ << " {pcdiff = " << expected_.pcdiff
+        << ", spdiff = " << expected_.spdiff
+        << ", action = " << expected_.action << "}";
+  }
+
+  bool MatchAndExplain(const ControlTransfer& input,
+                       MatchResultListener* listener) const override {
+    if (input.pcdiff != expected_.pcdiff || input.spdiff != expected_.spdiff ||
+        input.action != expected_.action) {
+      *listener << "@" << pc_ << " {pcdiff = " << input.pcdiff
+                << ", spdiff = " << input.spdiff
+                << ", action = " << input.action << "}";
+      return false;
+    }
+    return true;
+  }
+
+ private:
+  pc_t pc_;
+  const ControlTransfer& expected_;
+};
+
+class ControlTransferTest : public TestWithZone {
+ public:
+  void CheckControlTransfers(const byte* start, const byte* end,
+                             ExpectedTarget* expected_targets,
+                             size_t num_targets) {
+    ControlTransferMap map =
+        WasmInterpreter::ComputeControlTransfersForTesting(zone(), start, end);
+    // Check all control targets in the map.
+    for (size_t i = 0; i < num_targets; i++) {
+      pc_t pc = expected_targets[i].pc;
+      auto it = map.find(pc);
+      if (it == map.end()) {
+        printf("expected control target @ +%zu\n", pc);
+        EXPECT_TRUE(false);
+      } else {
+        ControlTransfer& expected = expected_targets[i].expected;
+        ControlTransfer& target = it->second;
+        EXPECT_THAT(target,
+                    MakeMatcher(new ControlTransferMatcher(pc, expected)));
+      }
+    }
+
+    // Check there are no other control targets.
+    for (pc_t pc = 0; start + pc < end; pc++) {
+      bool found = false;
+      for (size_t i = 0; i < num_targets; i++) {
+        if (expected_targets[i].pc == pc) {
+          found = true;
+          break;
+        }
+      }
+      if (found) continue;
+      if (map.find(pc) != map.end()) {
+        printf("expected no control @ +%zu\n", pc);
+        EXPECT_TRUE(false);
+      }
+    }
+  }
+};
+
+// Macro for simplifying tests below.
+#define EXPECT_TARGETS(...)                                                    \
+  do {                                                                         \
+    ExpectedTarget pairs[] = {__VA_ARGS__};                                    \
+    CheckControlTransfers(code, code + sizeof(code), pairs, arraysize(pairs)); \
+  } while (false)
+
+TEST_F(ControlTransferTest, SimpleIf) {
+  byte code[] = {
+      kExprI32Const,  // @0
+      0,              //   +1
+      kExprIf,        // @2
+      kExprEnd        // @3
+  };
+  EXPECT_TARGETS({2, {2, 0, ControlTransfer::kPushVoid}},  // --
+                 {3, {1, 0, ControlTransfer::kPushVoid}});
+}
+
+TEST_F(ControlTransferTest, SimpleIf1) {
+  byte code[] = {
+      kExprI32Const,  // @0
+      0,              //   +1
+      kExprIf,        // @2
+      kExprNop,       // @3
+      kExprEnd        // @4
+  };
+  EXPECT_TARGETS({2, {3, 0, ControlTransfer::kPushVoid}},  // --
+                 {4, {1, 1, ControlTransfer::kPopAndRepush}});
+}
+
+TEST_F(ControlTransferTest, SimpleIf2) {
+  byte code[] = {
+      kExprI32Const,  // @0
+      0,              //   +1
+      kExprIf,        // @2
+      kExprNop,       // @3
+      kExprNop,       // @4
+      kExprEnd        // @5
+  };
+  EXPECT_TARGETS({2, {4, 0, ControlTransfer::kPushVoid}},  // --
+                 {5, {1, 2, ControlTransfer::kPopAndRepush}});
+}
+
+TEST_F(ControlTransferTest, SimpleIfElse) {
+  byte code[] = {
+      kExprI32Const,  // @0
+      0,              //   +1
+      kExprIf,        // @2
+      kExprElse,      // @3
+      kExprEnd        // @4
+  };
+  EXPECT_TARGETS({2, {2, 0, ControlTransfer::kNoAction}},  // --
+                 {3, {2, 0, ControlTransfer::kPushVoid}},  // --
+                 {4, {1, 0, ControlTransfer::kPushVoid}});
+}
+
+TEST_F(ControlTransferTest, SimpleIfElse1) {
+  byte code[] = {
+      kExprI32Const,  // @0
+      0,              //   +1
+      kExprIf,        // @2
+      kExprNop,       // @3
+      kExprElse,      // @4
+      kExprNop,       // @5
+      kExprEnd        // @6
+  };
+  EXPECT_TARGETS({2, {3, 0, ControlTransfer::kNoAction}},      // --
+                 {4, {3, 1, ControlTransfer::kPopAndRepush}},  // --
+                 {6, {1, 1, ControlTransfer::kPopAndRepush}});
+}
+
+TEST_F(ControlTransferTest, IfBr) {
+  byte code[] = {
+      kExprI32Const,  // @0
+      0,              //   +1
+      kExprIf,        // @2
+      kExprBr,        // @3
+      ARITY_0,        //   +1
+      0,              //   +1
+      kExprEnd        // @6
+  };
+  EXPECT_TARGETS({2, {5, 0, ControlTransfer::kPushVoid}},  // --
+                 {3, {4, 0, ControlTransfer::kPushVoid}},  // --
+                 {6, {1, 1, ControlTransfer::kPopAndRepush}});
+}
+
+TEST_F(ControlTransferTest, IfBrElse) {
+  byte code[] = {
+      kExprI32Const,  // @0
+      0,              //   +1
+      kExprIf,        // @2
+      kExprBr,        // @3
+      ARITY_0,        //   +1
+      0,              //   +1
+      kExprElse,      // @6
+      kExprEnd        // @7
+  };
+  EXPECT_TARGETS({2, {5, 0, ControlTransfer::kNoAction}},      // --
+                 {3, {5, 0, ControlTransfer::kPushVoid}},      // --
+                 {6, {2, 1, ControlTransfer::kPopAndRepush}},  // --
+                 {7, {1, 0, ControlTransfer::kPushVoid}});
+}
+
+TEST_F(ControlTransferTest, IfElseBr) {
+  byte code[] = {
+      kExprI32Const,  // @0
+      0,              //   +1
+      kExprIf,        // @2
+      kExprNop,       // @3
+      kExprElse,      // @4
+      kExprBr,        // @5
+      ARITY_0,        //   +1
+      0,              //   +1
+      kExprEnd        // @8
+  };
+  EXPECT_TARGETS({2, {3, 0, ControlTransfer::kNoAction}},      // --
+                 {4, {5, 1, ControlTransfer::kPopAndRepush}},  // --
+                 {5, {4, 0, ControlTransfer::kPushVoid}},      // --
+                 {8, {1, 1, ControlTransfer::kPopAndRepush}});
+}
+
+TEST_F(ControlTransferTest, BlockEmpty) {
+  byte code[] = {
+      kExprBlock,  // @0
+      kExprEnd     // @1
+  };
+  EXPECT_TARGETS({1, {1, 0, ControlTransfer::kPushVoid}});
+}
+
+TEST_F(ControlTransferTest, Br0) {
+  byte code[] = {
+      kExprBlock,  // @0
+      kExprBr,     // @1
+      ARITY_0,     //   +1
+      0,           //   +1
+      kExprEnd     // @4
+  };
+  EXPECT_TARGETS({1, {4, 0, ControlTransfer::kPushVoid}},
+                 {4, {1, 1, ControlTransfer::kPopAndRepush}});
+}
+
+TEST_F(ControlTransferTest, Br1) {
+  byte code[] = {
+      kExprBlock,  // @0
+      kExprNop,    // @1
+      kExprBr,     // @2
+      ARITY_0,     //   +1
+      0,           //   +1
+      kExprEnd     // @5
+  };
+  EXPECT_TARGETS({2, {4, 1, ControlTransfer::kPopAndRepush}},  // --
+                 {5, {1, 2, ControlTransfer::kPopAndRepush}});
+}
+
+TEST_F(ControlTransferTest, Br2) {
+  byte code[] = {
+      kExprBlock,  // @0
+      kExprNop,    // @1
+      kExprNop,    // @2
+      kExprBr,     // @3
+      ARITY_0,     //   +1
+      0,           //   +1
+      kExprEnd     // @6
+  };
+  EXPECT_TARGETS({3, {4, 2, ControlTransfer::kPopAndRepush}},  // --
+                 {6, {1, 3, ControlTransfer::kPopAndRepush}});
+}
+
+TEST_F(ControlTransferTest, Br0b) {
+  byte code[] = {
+      kExprBlock,  // @0
+      kExprBr,     // @1
+      ARITY_0,     //   +1
+      0,           //   +1
+      kExprNop,    // @4
+      kExprEnd     // @5
+  };
+  EXPECT_TARGETS({1, {5, 0, ControlTransfer::kPushVoid}},  // --
+                 {5, {1, 2, ControlTransfer::kPopAndRepush}});
+}
+
+TEST_F(ControlTransferTest, Br0c) {
+  byte code[] = {
+      kExprBlock,  // @0
+      kExprBr,     // @1
+      ARITY_0,     //   +1
+      0,           //   +1
+      kExprNop,    // @4
+      kExprNop,    // @5
+      kExprEnd     // @6
+  };
+  EXPECT_TARGETS({1, {6, 0, ControlTransfer::kPushVoid}},  // --
+                 {6, {1, 3, ControlTransfer::kPopAndRepush}});
+}
+
+TEST_F(ControlTransferTest, SimpleLoop1) {
+  byte code[] = {
+      kExprLoop,  // @0
+      kExprBr,    // @1
+      ARITY_0,    //   +1
+      0,          //   +1
+      kExprEnd    // @4
+  };
+  EXPECT_TARGETS({1, {-1, 0, ControlTransfer::kNoAction}},  // --
+                 {4, {1, 1, ControlTransfer::kPopAndRepush}});
+}
+
+TEST_F(ControlTransferTest, SimpleLoop2) {
+  byte code[] = {
+      kExprLoop,  // @0
+      kExprNop,   // @1
+      kExprBr,    // @2
+      ARITY_0,    //   +1
+      0,          //   +1
+      kExprEnd    // @5
+  };
+  EXPECT_TARGETS({2, {-2, 1, ControlTransfer::kNoAction}},  // --
+                 {5, {1, 2, ControlTransfer::kPopAndRepush}});
+}
+
+TEST_F(ControlTransferTest, SimpleLoopExit1) {
+  byte code[] = {
+      kExprLoop,  // @0
+      kExprBr,    // @1
+      ARITY_0,    //   +1
+      1,          //   +1
+      kExprEnd    // @4
+  };
+  EXPECT_TARGETS({1, {4, 0, ControlTransfer::kPushVoid}},  // --
+                 {4, {1, 1, ControlTransfer::kPopAndRepush}});
+}
+
+TEST_F(ControlTransferTest, SimpleLoopExit2) {
+  byte code[] = {
+      kExprLoop,  // @0
+      kExprNop,   // @1
+      kExprBr,    // @2
+      ARITY_0,    //   +1
+      1,          //   +1
+      kExprEnd    // @5
+  };
+  EXPECT_TARGETS({2, {4, 1, ControlTransfer::kPopAndRepush}},  // --
+                 {5, {1, 2, ControlTransfer::kPopAndRepush}});
+}
+
+TEST_F(ControlTransferTest, BrTable0) {
+  byte code[] = {
+      kExprBlock,    // @0
+      kExprI8Const,  // @1
+      0,             //   +1
+      kExprBrTable,  // @3
+      ARITY_0,       //   +1
+      0,             //   +1
+      U32_LE(0),     //   +4
+      kExprEnd       // @10
+  };
+  EXPECT_TARGETS({3, {8, 0, ControlTransfer::kPushVoid}},  // --
+                 {10, {1, 1, ControlTransfer::kPopAndRepush}});
+}
+
+TEST_F(ControlTransferTest, BrTable1) {
+  byte code[] = {
+      kExprBlock,    // @0
+      kExprI8Const,  // @1
+      0,             //   +1
+      kExprBrTable,  // @3
+      ARITY_0,       //   +1
+      1,             //   +1
+      U32_LE(0),     //   +4
+      U32_LE(0),     //   +4
+      kExprEnd       // @14
+  };
+  EXPECT_TARGETS({3, {12, 0, ControlTransfer::kPushVoid}},  // --
+                 {4, {11, 0, ControlTransfer::kPushVoid}},  // --
+                 {14, {1, 1, ControlTransfer::kPopAndRepush}});
+}
+
+TEST_F(ControlTransferTest, BrTable2) {
+  byte code[] = {
+      kExprBlock,    // @0
+      kExprBlock,    // @1
+      kExprI8Const,  // @2
+      0,             //   +1
+      kExprBrTable,  // @4
+      ARITY_0,       //   +1
+      2,             //   +1
+      U32_LE(0),     //   +4
+      U32_LE(0),     //   +4
+      U32_LE(1),     //   +4
+      kExprEnd,      // @19
+      kExprEnd       // @19
+  };
+  EXPECT_TARGETS({4, {16, 0, ControlTransfer::kPushVoid}},      // --
+                 {5, {15, 0, ControlTransfer::kPushVoid}},      // --
+                 {6, {15, 0, ControlTransfer::kPushVoid}},      // --
+                 {19, {1, 1, ControlTransfer::kPopAndRepush}},  // --
+                 {20, {1, 1, ControlTransfer::kPopAndRepush}});
+}
+
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/wasm/decoder-unittest.cc b/test/unittests/wasm/decoder-unittest.cc
index 11d68f1..e298f0b 100644
--- a/test/unittests/wasm/decoder-unittest.cc
+++ b/test/unittests/wasm/decoder-unittest.cc
@@ -4,6 +4,7 @@
 
 #include "test/unittests/test-utils.h"
 
+#include "src/objects-inl.h"
 #include "src/wasm/decoder.h"
 #include "src/wasm/wasm-macro-gen.h"
 
@@ -22,7 +23,7 @@
   do {                                                                 \
     const byte data[] = {__VA_ARGS__};                                 \
     decoder.Reset(data, data + sizeof(data));                          \
-    int length;                                                        \
+    unsigned length;                                                   \
     EXPECT_EQ(expected,                                                \
               decoder.checked_read_u32v(decoder.start(), 0, &length)); \
     EXPECT_EQ(expected_length, length);                                \
@@ -32,7 +33,7 @@
   do {                                                                 \
     const byte data[] = {__VA_ARGS__};                                 \
     decoder.Reset(data, data + sizeof(data));                          \
-    int length;                                                        \
+    unsigned length;                                                   \
     EXPECT_EQ(expected,                                                \
               decoder.checked_read_i32v(decoder.start(), 0, &length)); \
     EXPECT_EQ(expected_length, length);                                \
@@ -42,7 +43,7 @@
   do {                                                                 \
     const byte data[] = {__VA_ARGS__};                                 \
     decoder.Reset(data, data + sizeof(data));                          \
-    int length;                                                        \
+    unsigned length;                                                   \
     EXPECT_EQ(expected,                                                \
               decoder.checked_read_u64v(decoder.start(), 0, &length)); \
     EXPECT_EQ(expected_length, length);                                \
@@ -52,7 +53,7 @@
   do {                                                                 \
     const byte data[] = {__VA_ARGS__};                                 \
     decoder.Reset(data, data + sizeof(data));                          \
-    int length;                                                        \
+    unsigned length;                                                   \
     EXPECT_EQ(expected,                                                \
               decoder.checked_read_i64v(decoder.start(), 0, &length)); \
     EXPECT_EQ(expected_length, length);                                \
@@ -365,7 +366,7 @@
 
 TEST_F(DecoderTest, ReadU32v_off_end1) {
   static const byte data[] = {U32V_1(11)};
-  int length = 0;
+  unsigned length = 0;
   decoder.Reset(data, data);
   decoder.checked_read_u32v(decoder.start(), 0, &length);
   EXPECT_EQ(0, length);
@@ -375,7 +376,7 @@
 TEST_F(DecoderTest, ReadU32v_off_end2) {
   static const byte data[] = {U32V_2(1111)};
   for (size_t i = 0; i < sizeof(data); i++) {
-    int length = 0;
+    unsigned length = 0;
     decoder.Reset(data, data + i);
     decoder.checked_read_u32v(decoder.start(), 0, &length);
     EXPECT_EQ(i, length);
@@ -386,7 +387,7 @@
 TEST_F(DecoderTest, ReadU32v_off_end3) {
   static const byte data[] = {U32V_3(111111)};
   for (size_t i = 0; i < sizeof(data); i++) {
-    int length = 0;
+    unsigned length = 0;
     decoder.Reset(data, data + i);
     decoder.checked_read_u32v(decoder.start(), 0, &length);
     EXPECT_EQ(i, length);
@@ -397,7 +398,7 @@
 TEST_F(DecoderTest, ReadU32v_off_end4) {
   static const byte data[] = {U32V_4(11111111)};
   for (size_t i = 0; i < sizeof(data); i++) {
-    int length = 0;
+    unsigned length = 0;
     decoder.Reset(data, data + i);
     decoder.checked_read_u32v(decoder.start(), 0, &length);
     EXPECT_EQ(i, length);
@@ -408,7 +409,7 @@
 TEST_F(DecoderTest, ReadU32v_off_end5) {
   static const byte data[] = {U32V_5(111111111)};
   for (size_t i = 0; i < sizeof(data); i++) {
-    int length = 0;
+    unsigned length = 0;
     decoder.Reset(data, data + i);
     decoder.checked_read_u32v(decoder.start(), 0, &length);
     EXPECT_EQ(i, length);
@@ -420,7 +421,7 @@
   byte data[] = {0x80, 0x80, 0x80, 0x80, 0x00};
   for (int i = 1; i < 16; i++) {
     data[4] = static_cast<byte>(i << 4);
-    int length = 0;
+    unsigned length = 0;
     decoder.Reset(data, data + sizeof(data));
     decoder.checked_read_u32v(decoder.start(), 0, &length);
     EXPECT_EQ(5, length);
@@ -430,7 +431,7 @@
 
 TEST_F(DecoderTest, ReadI32v_extra_bits_negative) {
   // OK for negative signed values to have extra ones.
-  int length = 0;
+  unsigned length = 0;
   byte data[] = {0xff, 0xff, 0xff, 0xff, 0x7f};
   decoder.Reset(data, data + sizeof(data));
   decoder.checked_read_i32v(decoder.start(), 0, &length);
@@ -440,7 +441,7 @@
 
 TEST_F(DecoderTest, ReadI32v_extra_bits_positive) {
   // Not OK for positive signed values to have extra ones.
-  int length = 0;
+  unsigned length = 0;
   byte data[] = {0x80, 0x80, 0x80, 0x80, 0x77};
   decoder.Reset(data, data + sizeof(data));
   decoder.checked_read_i32v(decoder.start(), 0, &length);
@@ -477,7 +478,7 @@
       // foreach buffer size 0...5
       for (int limit = 0; limit <= kMaxSize; limit++) {
         decoder.Reset(data, data + limit);
-        int rlen;
+        unsigned rlen;
         uint32_t result = decoder.checked_read_u32v(data, 0, &rlen);
         if (limit < length) {
           EXPECT_FALSE(decoder.ok());
@@ -533,7 +534,7 @@
 
     for (int limit = 0; limit <= kMaxSize; limit++) {
       decoder.Reset(data, data + limit);
-      int length;
+      unsigned length;
       uint64_t result = decoder.checked_read_u64v(data, 0, &length);
       if (limit <= index) {
         EXPECT_FALSE(decoder.ok());
@@ -574,7 +575,7 @@
       // foreach buffer size 0...10
       for (int limit = 0; limit <= kMaxSize; limit++) {
         decoder.Reset(data, data + limit);
-        int rlen;
+        unsigned rlen;
         uint64_t result = decoder.checked_read_u64v(data, 0, &rlen);
         if (limit < length) {
           EXPECT_FALSE(decoder.ok());
@@ -616,7 +617,7 @@
       // foreach buffer size 0...10
       for (int limit = 0; limit <= kMaxSize; limit++) {
         decoder.Reset(data, data + limit);
-        int rlen;
+        unsigned rlen;
         int64_t result = decoder.checked_read_i64v(data, 0, &rlen);
         if (limit < length) {
           EXPECT_FALSE(decoder.ok());
@@ -634,7 +635,7 @@
   byte data[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00};
   for (int i = 1; i < 128; i++) {
     data[9] = static_cast<byte>(i << 1);
-    int length = 0;
+    unsigned length = 0;
     decoder.Reset(data, data + sizeof(data));
     decoder.checked_read_u64v(decoder.start(), 0, &length);
     EXPECT_EQ(10, length);
@@ -644,7 +645,7 @@
 
 TEST_F(DecoderTest, ReadI64v_extra_bits_negative) {
   // OK for negative signed values to have extra ones.
-  int length = 0;
+  unsigned length = 0;
   byte data[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f};
   decoder.Reset(data, data + sizeof(data));
   decoder.checked_read_i64v(decoder.start(), 0, &length);
@@ -654,7 +655,7 @@
 
 TEST_F(DecoderTest, ReadI64v_extra_bits_positive) {
   // Not OK for positive signed values to have extra ones.
-  int length = 0;
+  unsigned length = 0;
   byte data[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x77};
   decoder.Reset(data, data + sizeof(data));
   decoder.checked_read_i64v(decoder.start(), 0, &length);
diff --git a/test/unittests/wasm/encoder-unittest.cc b/test/unittests/wasm/encoder-unittest.cc
index 740c054..47885e6 100644
--- a/test/unittests/wasm/encoder-unittest.cc
+++ b/test/unittests/wasm/encoder-unittest.cc
@@ -9,6 +9,8 @@
 #include "src/wasm/ast-decoder.h"
 #include "src/wasm/encoder.h"
 
+#include "test/cctest/wasm/test-signatures.h"
+
 namespace v8 {
 namespace internal {
 namespace wasm {
@@ -17,202 +19,10 @@
  protected:
   void AddLocal(WasmFunctionBuilder* f, LocalType type) {
     uint16_t index = f->AddLocal(type);
-    const std::vector<uint8_t>& out_index = UnsignedLEB128From(index);
-    std::vector<uint8_t> code;
-    code.push_back(kExprGetLocal);
-    for (size_t i = 0; i < out_index.size(); i++) {
-      code.push_back(out_index.at(i));
-    }
-    uint32_t local_indices[] = {1};
-    f->EmitCode(&code[0], static_cast<uint32_t>(code.size()), local_indices, 1);
-  }
-
-  void CheckReadValue(uint8_t* leb_value, uint32_t expected_result,
-                      int expected_length,
-                      ReadUnsignedLEB128ErrorCode expected_error_code) {
-    int length;
-    uint32_t result;
-    ReadUnsignedLEB128ErrorCode error_code =
-        ReadUnsignedLEB128Operand(leb_value, leb_value + 5, &length, &result);
-    CHECK_EQ(error_code, expected_error_code);
-    if (error_code == 0) {
-      CHECK_EQ(result, expected_result);
-      CHECK_EQ(length, expected_length);
-    }
-  }
-
-  void CheckWriteValue(uint32_t input, int length, uint8_t* vals) {
-    const std::vector<uint8_t> result = UnsignedLEB128From(input);
-    CHECK_EQ(result.size(), length);
-    for (int i = 0; i < length; i++) {
-      CHECK_EQ(result.at(i), vals[i]);
-    }
+    f->EmitGetLocal(index);
   }
 };
 
-
-TEST_F(EncoderTest, Function_Builder_Variable_Indexing) {
-  base::AccountingAllocator allocator;
-  Zone zone(&allocator);
-  WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
-  uint16_t f_index = builder->AddFunction();
-  WasmFunctionBuilder* function = builder->FunctionAt(f_index);
-  uint16_t local_f32 = function->AddLocal(kAstF32);
-  uint16_t param_float32 = function->AddParam(kAstF32);
-  uint16_t local_i32 = function->AddLocal(kAstI32);
-  uint16_t local_f64 = function->AddLocal(kAstF64);
-  uint16_t local_i64 = function->AddLocal(kAstI64);
-  uint16_t param_int32 = function->AddParam(kAstI32);
-  uint16_t local_i32_2 = function->AddLocal(kAstI32);
-
-  byte code[] = {kExprGetLocal, static_cast<uint8_t>(param_float32)};
-  uint32_t local_indices[] = {1};
-  function->EmitCode(code, sizeof(code), local_indices, 1);
-  code[1] = static_cast<uint8_t>(param_int32);
-  function->EmitCode(code, sizeof(code), local_indices, 1);
-  code[1] = static_cast<uint8_t>(local_i32);
-  function->EmitCode(code, sizeof(code), local_indices, 1);
-  code[1] = static_cast<uint8_t>(local_i32_2);
-  function->EmitCode(code, sizeof(code), local_indices, 1);
-  code[1] = static_cast<uint8_t>(local_i64);
-  function->EmitCode(code, sizeof(code), local_indices, 1);
-  code[1] = static_cast<uint8_t>(local_f32);
-  function->EmitCode(code, sizeof(code), local_indices, 1);
-  code[1] = static_cast<uint8_t>(local_f64);
-  function->EmitCode(code, sizeof(code), local_indices, 1);
-
-  WasmFunctionEncoder* f = function->Build(&zone, builder);
-  ZoneVector<uint8_t> buffer_vector(f->HeaderSize() + f->BodySize(), &zone);
-  byte* buffer = &buffer_vector[0];
-  byte* header = buffer;
-  byte* body = buffer + f->HeaderSize();
-  f->Serialize(buffer, &header, &body);
-}
-
-
-TEST_F(EncoderTest, Function_Builder_Indexing_Variable_Width) {
-  base::AccountingAllocator allocator;
-  Zone zone(&allocator);
-  WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
-  uint16_t f_index = builder->AddFunction();
-  WasmFunctionBuilder* function = builder->FunctionAt(f_index);
-  for (size_t i = 0; i < 128; i++) {
-    AddLocal(function, kAstF32);
-  }
-  AddLocal(function, kAstI32);
-
-  WasmFunctionEncoder* f = function->Build(&zone, builder);
-  ZoneVector<uint8_t> buffer_vector(f->HeaderSize() + f->BodySize(), &zone);
-  byte* buffer = &buffer_vector[0];
-  byte* header = buffer;
-  byte* body = buffer + f->HeaderSize();
-  f->Serialize(buffer, &header, &body);
-  body = buffer + f->HeaderSize();
-}
-
-TEST_F(EncoderTest, Function_Builder_Block_Variable_Width) {
-  base::AccountingAllocator allocator;
-  Zone zone(&allocator);
-  WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
-  uint16_t f_index = builder->AddFunction();
-  WasmFunctionBuilder* function = builder->FunctionAt(f_index);
-  function->EmitWithVarInt(kExprBlock, 200);
-  for (int i = 0; i < 200; ++i) {
-    function->Emit(kExprNop);
-  }
-
-  WasmFunctionEncoder* f = function->Build(&zone, builder);
-  CHECK_EQ(f->BodySize(), 204);
-}
-
-TEST_F(EncoderTest, Function_Builder_EmitEditableVarIntImmediate) {
-  base::AccountingAllocator allocator;
-  Zone zone(&allocator);
-  WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
-  uint16_t f_index = builder->AddFunction();
-  WasmFunctionBuilder* function = builder->FunctionAt(f_index);
-  function->Emit(kExprLoop);
-  uint32_t offset = function->EmitEditableVarIntImmediate();
-  for (int i = 0; i < 200; ++i) {
-    function->Emit(kExprNop);
-  }
-  function->EditVarIntImmediate(offset, 200);
-
-  WasmFunctionEncoder* f = function->Build(&zone, builder);
-  CHECK_EQ(f->BodySize(), 204);
-}
-
-TEST_F(EncoderTest, Function_Builder_EmitEditableVarIntImmediate_Locals) {
-  base::AccountingAllocator allocator;
-  Zone zone(&allocator);
-  WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
-  uint16_t f_index = builder->AddFunction();
-  WasmFunctionBuilder* function = builder->FunctionAt(f_index);
-  function->Emit(kExprBlock);
-  uint32_t offset = function->EmitEditableVarIntImmediate();
-  for (int i = 0; i < 200; ++i) {
-    AddLocal(function, kAstI32);
-  }
-  function->EditVarIntImmediate(offset, 200);
-
-  WasmFunctionEncoder* f = function->Build(&zone, builder);
-  ZoneVector<uint8_t> buffer_vector(f->HeaderSize() + f->BodySize(), &zone);
-  byte* buffer = &buffer_vector[0];
-  byte* header = buffer;
-  byte* body = buffer + f->HeaderSize();
-  f->Serialize(buffer, &header, &body);
-  body = buffer + f->HeaderSize();
-
-  CHECK_EQ(f->BodySize(), 479);
-  const uint8_t varint200_low = (200 & 0x7f) | 0x80;
-  const uint8_t varint200_high = (200 >> 7) & 0x7f;
-  offset = 0;
-  CHECK_EQ(body[offset++], 1);  // Local decl count.
-  CHECK_EQ(body[offset++], varint200_low);
-  CHECK_EQ(body[offset++], varint200_high);
-  CHECK_EQ(body[offset++], kLocalI32);
-  CHECK_EQ(body[offset++], kExprBlock);
-  CHECK_EQ(body[offset++], varint200_low);
-  CHECK_EQ(body[offset++], varint200_high);
-  // GetLocal with one-byte indices.
-  for (int i = 0; i <= 127; ++i) {
-    CHECK_EQ(body[offset++], kExprGetLocal);
-    CHECK_EQ(body[offset++], i);
-  }
-  // GetLocal with two-byte indices.
-  for (int i = 128; i < 200; ++i) {
-    CHECK_EQ(body[offset++], kExprGetLocal);
-    CHECK_EQ(body[offset++], (i & 0x7f) | 0x80);
-    CHECK_EQ(body[offset++], (i >> 7) & 0x7f);
-  }
-  CHECK_EQ(offset, 479);
-}
-
-TEST_F(EncoderTest, LEB_Functions) {
-  byte leb_value[5] = {0, 0, 0, 0, 0};
-  CheckReadValue(leb_value, 0, 1, kNoError);
-  CheckWriteValue(0, 1, leb_value);
-  leb_value[0] = 23;
-  CheckReadValue(leb_value, 23, 1, kNoError);
-  CheckWriteValue(23, 1, leb_value);
-  leb_value[0] = 0x80;
-  leb_value[1] = 0x01;
-  CheckReadValue(leb_value, 128, 2, kNoError);
-  CheckWriteValue(128, 2, leb_value);
-  leb_value[0] = 0x80;
-  leb_value[1] = 0x80;
-  leb_value[2] = 0x80;
-  leb_value[3] = 0x80;
-  leb_value[4] = 0x01;
-  CheckReadValue(leb_value, 0x10000000, 5, kNoError);
-  CheckWriteValue(0x10000000, 5, leb_value);
-  leb_value[0] = 0x80;
-  leb_value[1] = 0x80;
-  leb_value[2] = 0x80;
-  leb_value[3] = 0x80;
-  leb_value[4] = 0x80;
-  CheckReadValue(leb_value, -1, -1, kInvalidLEB128);
-}
 }  // namespace wasm
 }  // namespace internal
 }  // namespace v8
diff --git a/test/unittests/wasm/leb-helper-unittest.cc b/test/unittests/wasm/leb-helper-unittest.cc
new file mode 100644
index 0000000..b975933
--- /dev/null
+++ b/test/unittests/wasm/leb-helper-unittest.cc
@@ -0,0 +1,191 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "test/unittests/test-utils.h"
+
+#include "src/objects-inl.h"
+#include "src/wasm/decoder.h"
+#include "src/wasm/leb-helper.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+class LEBHelperTest : public TestWithZone {};
+
+TEST_F(LEBHelperTest, sizeof_u32v) {
+  EXPECT_EQ(1, LEBHelper::sizeof_u32v(0));
+  EXPECT_EQ(1, LEBHelper::sizeof_u32v(1));
+  EXPECT_EQ(1, LEBHelper::sizeof_u32v(3));
+
+  for (uint32_t i = 4; i < 128; i++) {
+    EXPECT_EQ(1, LEBHelper::sizeof_u32v(i));
+  }
+
+  for (uint32_t i = (1 << 7); i < (1 << 9); i++) {
+    EXPECT_EQ(2, LEBHelper::sizeof_u32v(i));
+  }
+
+  for (uint32_t i = (1 << 14); i < (1 << 16); i += 33) {
+    EXPECT_EQ(3, LEBHelper::sizeof_u32v(i));
+  }
+
+  for (uint32_t i = (1 << 21); i < (1 << 24); i += 33999) {
+    EXPECT_EQ(4, LEBHelper::sizeof_u32v(i));
+  }
+
+  for (uint32_t i = (1 << 28); i < (1 << 31); i += 33997779) {
+    EXPECT_EQ(5, LEBHelper::sizeof_u32v(i));
+  }
+
+  EXPECT_EQ(5, LEBHelper::sizeof_u32v(0xFFFFFFFF));
+}
+
+TEST_F(LEBHelperTest, sizeof_i32v) {
+  EXPECT_EQ(1, LEBHelper::sizeof_i32v(0));
+  EXPECT_EQ(1, LEBHelper::sizeof_i32v(1));
+  EXPECT_EQ(1, LEBHelper::sizeof_i32v(3));
+
+  for (int32_t i = 0; i < (1 << 6); i++) {
+    EXPECT_EQ(1, LEBHelper::sizeof_i32v(i));
+  }
+
+  for (int32_t i = (1 << 6); i < (1 << 8); i++) {
+    EXPECT_EQ(2, LEBHelper::sizeof_i32v(i));
+  }
+
+  for (int32_t i = (1 << 13); i < (1 << 15); i += 31) {
+    EXPECT_EQ(3, LEBHelper::sizeof_i32v(i));
+  }
+
+  for (int32_t i = (1 << 20); i < (1 << 22); i += 31991) {
+    EXPECT_EQ(4, LEBHelper::sizeof_i32v(i));
+  }
+
+  for (int32_t i = (1 << 27); i < (1 << 29); i += 3199893) {
+    EXPECT_EQ(5, LEBHelper::sizeof_i32v(i));
+  }
+
+  for (int32_t i = -(1 << 6); i <= 0; i++) {
+    EXPECT_EQ(1, LEBHelper::sizeof_i32v(i));
+  }
+
+  for (int32_t i = -(1 << 13); i < -(1 << 6); i++) {
+    EXPECT_EQ(2, LEBHelper::sizeof_i32v(i));
+  }
+
+  for (int32_t i = -(1 << 20); i < -(1 << 18); i += 11) {
+    EXPECT_EQ(3, LEBHelper::sizeof_i32v(i));
+  }
+
+  for (int32_t i = -(1 << 27); i < -(1 << 25); i += 11999) {
+    EXPECT_EQ(4, LEBHelper::sizeof_i32v(i));
+  }
+
+  for (int32_t i = -(1 << 30); i < -(1 << 28); i += 1199999) {
+    EXPECT_EQ(5, LEBHelper::sizeof_i32v(i));
+  }
+}
+
+#define DECLARE_ENCODE_DECODE_CHECKER(ctype, name)                         \
+  static void CheckEncodeDecode_##name(ctype val) {                        \
+    static const int kSize = 16;                                           \
+    static byte buffer[kSize];                                             \
+    byte *ptr = buffer;                                                    \
+    LEBHelper::write_##name(&ptr, val);                                    \
+    EXPECT_EQ(LEBHelper::sizeof_##name(val),                               \
+              static_cast<size_t>(ptr - buffer));                          \
+    Decoder decoder(buffer, buffer + kSize);                               \
+    unsigned length = 0;                                                   \
+    ctype result = decoder.checked_read_##name(buffer, 0, &length);        \
+    EXPECT_EQ(val, result);                                                \
+    EXPECT_EQ(LEBHelper::sizeof_##name(val), static_cast<size_t>(length)); \
+  }
+
+DECLARE_ENCODE_DECODE_CHECKER(int32_t, i32v)
+DECLARE_ENCODE_DECODE_CHECKER(uint32_t, u32v)
+DECLARE_ENCODE_DECODE_CHECKER(int64_t, i64v)
+DECLARE_ENCODE_DECODE_CHECKER(uint64_t, u64v)
+
+TEST_F(LEBHelperTest, WriteAndDecode_u32v) {
+  CheckEncodeDecode_u32v(0);
+  CheckEncodeDecode_u32v(1);
+  CheckEncodeDecode_u32v(5);
+  CheckEncodeDecode_u32v(99);
+  CheckEncodeDecode_u32v(298);
+  CheckEncodeDecode_u32v(87348723);
+  CheckEncodeDecode_u32v(77777);
+
+  for (uint32_t val = 0x3a; val != 0; val = val << 1) {
+    CheckEncodeDecode_u32v(val);
+  }
+}
+
+TEST_F(LEBHelperTest, WriteAndDecode_i32v) {
+  CheckEncodeDecode_i32v(0);
+  CheckEncodeDecode_i32v(1);
+  CheckEncodeDecode_i32v(5);
+  CheckEncodeDecode_i32v(99);
+  CheckEncodeDecode_i32v(298);
+  CheckEncodeDecode_i32v(87348723);
+  CheckEncodeDecode_i32v(77777);
+
+  CheckEncodeDecode_i32v(-2);
+  CheckEncodeDecode_i32v(-4);
+  CheckEncodeDecode_i32v(-59);
+  CheckEncodeDecode_i32v(-288);
+  CheckEncodeDecode_i32v(-12608);
+  CheckEncodeDecode_i32v(-87328723);
+  CheckEncodeDecode_i32v(-77377);
+
+  for (uint32_t val = 0x3a; val != 0; val = val << 1) {
+    CheckEncodeDecode_i32v(bit_cast<int32_t>(val));
+  }
+
+  for (uint32_t val = 0xFFFFFF3B; val != 0; val = val << 1) {
+    CheckEncodeDecode_i32v(bit_cast<int32_t>(val));
+  }
+}
+
+TEST_F(LEBHelperTest, WriteAndDecode_u64v) {
+  CheckEncodeDecode_u64v(0);
+  CheckEncodeDecode_u64v(1);
+  CheckEncodeDecode_u64v(5);
+  CheckEncodeDecode_u64v(99);
+  CheckEncodeDecode_u64v(298);
+  CheckEncodeDecode_u64v(87348723);
+  CheckEncodeDecode_u64v(77777);
+
+  for (uint64_t val = 0x3a; val != 0; val = val << 1) {
+    CheckEncodeDecode_u64v(val);
+  }
+}
+
+TEST_F(LEBHelperTest, WriteAndDecode_i64v) {
+  CheckEncodeDecode_i64v(0);
+  CheckEncodeDecode_i64v(1);
+  CheckEncodeDecode_i64v(5);
+  CheckEncodeDecode_i64v(99);
+  CheckEncodeDecode_i64v(298);
+  CheckEncodeDecode_i64v(87348723);
+  CheckEncodeDecode_i64v(77777);
+
+  CheckEncodeDecode_i64v(-2);
+  CheckEncodeDecode_i64v(-4);
+  CheckEncodeDecode_i64v(-59);
+  CheckEncodeDecode_i64v(-288);
+  CheckEncodeDecode_i64v(-87648723);
+  CheckEncodeDecode_i64v(-77377);
+
+  for (uint64_t val = 0x3a; val != 0; val = val << 1) {
+    CheckEncodeDecode_i64v(bit_cast<int64_t>(val));
+  }
+
+  for (uint64_t val = 0xFFFFFFFFFFFFFF3B; val != 0; val = val << 1) {
+    CheckEncodeDecode_i64v(bit_cast<int64_t>(val));
+  }
+}
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/wasm/loop-assignment-analysis-unittest.cc b/test/unittests/wasm/loop-assignment-analysis-unittest.cc
index e77c1cf..c134de8 100644
--- a/test/unittests/wasm/loop-assignment-analysis-unittest.cc
+++ b/test/unittests/wasm/loop-assignment-analysis-unittest.cc
@@ -32,14 +32,12 @@
   }
 };
 
-
 TEST_F(WasmLoopAssignmentAnalyzerTest, Empty0) {
   byte code[] = { 0 };
   BitVector* assigned = Analyze(code, code);
   CHECK_NULL(assigned);
 }
 
-
 TEST_F(WasmLoopAssignmentAnalyzerTest, Empty1) {
   byte code[] = {kExprLoop, 0};
   for (int i = 0; i < 5; i++) {
@@ -51,7 +49,6 @@
   }
 }
 
-
 TEST_F(WasmLoopAssignmentAnalyzerTest, One) {
   num_locals = 5;
   for (int i = 0; i < 5; i++) {
@@ -63,7 +60,6 @@
   }
 }
 
-
 TEST_F(WasmLoopAssignmentAnalyzerTest, OneBeyond) {
   num_locals = 5;
   for (int i = 0; i < 5; i++) {
@@ -75,7 +71,6 @@
   }
 }
 
-
 TEST_F(WasmLoopAssignmentAnalyzerTest, Two) {
   num_locals = 5;
   for (int i = 0; i < 5; i++) {
@@ -90,7 +85,6 @@
   }
 }
 
-
 TEST_F(WasmLoopAssignmentAnalyzerTest, NestedIf) {
   num_locals = 5;
   for (int i = 0; i < 5; i++) {
@@ -104,14 +98,12 @@
   }
 }
 
-
 static byte LEBByte(uint32_t val, byte which) {
   byte b = (val >> (which * 7)) & 0x7F;
   if (val >> ((which + 1) * 7)) b |= 0x80;
   return b;
 }
 
-
 TEST_F(WasmLoopAssignmentAnalyzerTest, BigLocal) {
   num_locals = 65000;
   for (int i = 13; i < 65000; i = static_cast<int>(i * 1.5)) {
@@ -133,7 +125,6 @@
   }
 }
 
-
 TEST_F(WasmLoopAssignmentAnalyzerTest, Break) {
   num_locals = 3;
   byte code[] = {
@@ -147,7 +138,6 @@
   }
 }
 
-
 TEST_F(WasmLoopAssignmentAnalyzerTest, Loop1) {
   num_locals = 5;
   byte code[] = {
@@ -164,7 +154,6 @@
   }
 }
 
-
 TEST_F(WasmLoopAssignmentAnalyzerTest, Loop2) {
   num_locals = 6;
   const byte kIter = 0;
@@ -184,13 +173,20 @@
       WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO, WASM_GET_LOCAL(kSum)),
       WASM_GET_LOCAL(kIter))};
 
-  BitVector* assigned = Analyze(code + 2, code + arraysize(code));
+  BitVector* assigned = Analyze(code + 1, code + arraysize(code));
   for (int j = 0; j < assigned->length(); j++) {
     bool expected = j == kIter || j == kSum;
     CHECK_EQ(expected, assigned->Contains(j));
   }
 }
 
+TEST_F(WasmLoopAssignmentAnalyzerTest, Malformed) {
+  byte code[] = {kExprLoop, kExprF32Neg, kExprBrTable, 0x0e, 'h', 'e',
+                 'l',       'l',         'o',          ',',  ' ', 'w',
+                 'o',       'r',         'l',          'd',  '!'};
+  BitVector* assigned = Analyze(code, code + arraysize(code));
+  CHECK_NULL(assigned);
+}
 
 }  // namespace wasm
 }  // namespace internal
diff --git a/test/unittests/wasm/module-decoder-unittest.cc b/test/unittests/wasm/module-decoder-unittest.cc
index 44e7865..789112a 100644
--- a/test/unittests/wasm/module-decoder-unittest.cc
+++ b/test/unittests/wasm/module-decoder-unittest.cc
@@ -4,6 +4,8 @@
 
 #include "test/unittests/test-utils.h"
 
+#include "src/handles.h"
+#include "src/objects-inl.h"
 #include "src/wasm/module-decoder.h"
 #include "src/wasm/wasm-macro-gen.h"
 #include "src/wasm/wasm-opcodes.h"
@@ -13,18 +15,66 @@
 namespace wasm {
 
 #define EMPTY_FUNCTION(sig_index) 0, SIG_INDEX(sig_index), U16_LE(0)
-#define EMPTY_FUNCTION_SIZE ((size_t)5)
+#define SIZEOF_EMPTY_FUNCTION ((size_t)5)
 #define EMPTY_BODY 0
-#define EMPTY_BODY_SIZE ((size_t)1)
+#define SIZEOF_EMPTY_BODY ((size_t)1)
 #define NOP_BODY 2, 0, kExprNop
-#define NOP_BODY_SIZE ((size_t)3)
-#define VOID_VOID_SIG 0, kLocalVoid
-#define VOID_VOID_SIG_SIZE ((size_t)2)
-#define INT_INT_SIG 1, kLocalI32, kLocalI32
-#define INT_INT_SIG_SIZE ((size_t)3)
+#define SIZEOF_NOP_BODY ((size_t)3)
 
-#define SECTION(NAME, EXTRA_SIZE) \
-  U32V_1(WASM_SECTION_##NAME##_SIZE + (EXTRA_SIZE)), WASM_SECTION_##NAME
+#define SIG_ENTRY_i_i SIG_ENTRY_x_x(kLocalI32, kLocalI32)
+
+#define UNKNOWN_EMPTY_SECTION_NAME 1, '\0'
+#define UNKNOWN_SECTION_NAME 4, 'l', 'u', 'l', 'z'
+
+#define SECTION(NAME, EXTRA_SIZE) WASM_SECTION_##NAME, U32V_1(EXTRA_SIZE)
+
+#define SIGNATURES_SECTION(count, ...) \
+  SECTION(SIGNATURES, 1 + 3 * (count)), U32V_1(count), __VA_ARGS__
+#define FUNCTION_SIGNATURES_SECTION(count, ...) \
+  SECTION(FUNCTION_SIGNATURES, 1 + (count)), U32V_1(count), __VA_ARGS__
+
+#define FOO_STRING 3, 'f', 'o', 'o'
+#define NO_LOCAL_NAMES 0
+
+#define EMPTY_SIGNATURES_SECTION SECTION(SIGNATURES, 1), 0
+#define EMPTY_FUNCTION_SIGNATURES_SECTION SECTION(FUNCTION_SIGNATURES, 1), 0
+#define EMPTY_FUNCTION_BODIES_SECTION SECTION(FUNCTION_BODIES, 1), 0
+#define EMPTY_NAMES_SECTION SECTION(NAMES, 1), 0
+
+#define X1(...) __VA_ARGS__
+#define X2(...) __VA_ARGS__, __VA_ARGS__
+#define X3(...) __VA_ARGS__, __VA_ARGS__, __VA_ARGS__
+#define X4(...) __VA_ARGS__, __VA_ARGS__, __VA_ARGS__, __VA_ARGS__
+
+#define ONE_EMPTY_FUNCTION WASM_SECTION_FUNCTION_SIGNATURES, 1 + 1 * 1, 1, X1(0)
+
+#define TWO_EMPTY_FUNCTIONS \
+  WASM_SECTION_FUNCTION_SIGNATURES, 1 + 2 * 1, 2, X2(0)
+
+#define THREE_EMPTY_FUNCTIONS \
+  WASM_SECTION_FUNCTION_SIGNATURES, 1 + 3 * 1, 3, X3(0)
+
+#define FOUR_EMPTY_FUNCTIONS \
+  WASM_SECTION_FUNCTION_SIGNATURES, 1 + 4 * 1, 4, X4(0)
+
+#define ONE_EMPTY_BODY                                              \
+  WASM_SECTION_FUNCTION_BODIES, 1 + 1 * (1 + SIZEOF_EMPTY_BODY), 1, \
+      X1(SIZEOF_EMPTY_BODY, EMPTY_BODY)
+
+#define TWO_EMPTY_BODIES                                            \
+  WASM_SECTION_FUNCTION_BODIES, 1 + 2 * (1 + SIZEOF_EMPTY_BODY), 2, \
+      X2(SIZEOF_EMPTY_BODY, EMPTY_BODY)
+
+#define THREE_EMPTY_BODIES                                          \
+  WASM_SECTION_FUNCTION_BODIES, 1 + 3 * (1 + SIZEOF_EMPTY_BODY), 3, \
+      X3(SIZEOF_EMPTY_BODY, EMPTY_BODY)
+
+#define FOUR_EMPTY_BODIES                                           \
+  WASM_SECTION_FUNCTION_BODIES, 1 + 4 * (1 + SIZEOF_EMPTY_BODY), 4, \
+      X4(SIZEOF_EMPTY_BODY, EMPTY_BODY)
+
+#define SIGNATURES_SECTION_VOID_VOID \
+  SECTION(SIGNATURES, 1 + SIZEOF_SIG_ENTRY_v_v), 1, SIG_ENTRY_v_v
 
 #define EXPECT_VERIFIES(data)                                         \
   do {                                                                \
@@ -49,6 +99,15 @@
     }                                                   \
   } while (false)
 
+#define EXPECT_OK(result)                \
+  do {                                   \
+    EXPECT_TRUE(result.ok());            \
+    if (!result.ok()) {                  \
+      if (result.val) delete result.val; \
+      return;                            \
+    }                                    \
+  } while (false)
+
 static size_t SizeOfVarInt(size_t value) {
   size_t size = 0;
   do {
@@ -66,7 +125,7 @@
                    {kLocalF32, kAstF32},
                    {kLocalF64, kAstF64}};
 
-class WasmModuleVerifyTest : public TestWithZone {
+class WasmModuleVerifyTest : public TestWithIsolateAndZone {
  public:
   ModuleResult DecodeModule(const byte* module_start, const byte* module_end) {
     // Add the WASM magic and version number automatically.
@@ -76,14 +135,14 @@
     auto temp = new byte[total];
     memcpy(temp, header, sizeof(header));
     memcpy(temp + sizeof(header), module_start, size);
-    ModuleResult result = DecodeWasmModule(nullptr, zone(), temp, temp + total,
-                                           false, kWasmOrigin);
+    ModuleResult result = DecodeWasmModule(isolate(), zone(), temp,
+                                           temp + total, false, kWasmOrigin);
     delete[] temp;
     return result;
   }
   ModuleResult DecodeModuleNoHeader(const byte* module_start,
                                     const byte* module_end) {
-    return DecodeWasmModule(nullptr, zone(), module_start, module_end, false,
+    return DecodeWasmModule(isolate(), zone(), module_start, module_end, false,
                             kWasmOrigin);
   }
 };
@@ -115,7 +174,7 @@
 
 TEST_F(WasmModuleVerifyTest, OneGlobal) {
   static const byte data[] = {
-      SECTION(GLOBALS, 7),  // --
+      SECTION(GLOBALS, 5),  // --
       1,
       NAME_LENGTH(1),
       'g',      // name
@@ -126,12 +185,12 @@
   {
     // Should decode to exactly one global.
     ModuleResult result = DecodeModule(data, data + arraysize(data));
-    EXPECT_TRUE(result.ok());
+    EXPECT_OK(result);
     EXPECT_EQ(1, result.val->globals.size());
     EXPECT_EQ(0, result.val->functions.size());
     EXPECT_EQ(0, result.val->data_segments.size());
 
-    WasmGlobal* global = &result.val->globals.back();
+    const WasmGlobal* global = &result.val->globals.back();
 
     EXPECT_EQ(1, global->name_length);
     EXPECT_EQ(MachineType::Int32(), global->type);
@@ -144,6 +203,20 @@
   EXPECT_OFF_END_FAILURE(data, 1, sizeof(data));
 }
 
+TEST_F(WasmModuleVerifyTest, Global_invalid_type) {
+  static const byte data[] = {
+      SECTION(GLOBALS, 5),  // --
+      1,
+      NAME_LENGTH(1),
+      'g',  // name
+      64,   // invalid memory type
+      0,    // exported
+  };
+
+  ModuleResult result = DecodeModuleNoHeader(data, data + sizeof(data));
+  EXPECT_FALSE(result.ok());
+  if (result.val) delete result.val;
+}
 
 TEST_F(WasmModuleVerifyTest, ZeroGlobals) {
   static const byte data[] = {
@@ -151,11 +224,10 @@
       0,                    // declare 0 globals
   };
   ModuleResult result = DecodeModule(data, data + arraysize(data));
-  EXPECT_TRUE(result.ok());
+  EXPECT_OK(result);
   if (result.val) delete result.val;
 }
 
-
 static void AppendUint32v(std::vector<byte>& buffer, uint32_t val) {
   while (true) {
     uint32_t next = val >> 7;
@@ -170,7 +242,6 @@
   }
 }
 
-
 TEST_F(WasmModuleVerifyTest, NGlobals) {
   static const byte data[] = {
       NO_NAME,  // name length
@@ -180,9 +251,8 @@
 
   for (uint32_t i = 0; i < 1000000; i = i * 13 + 1) {
     std::vector<byte> buffer;
-    size_t size =
-        WASM_SECTION_GLOBALS_SIZE + SizeOfVarInt(i) + i * sizeof(data);
-    const byte globals[] = {U32V_5(size), WASM_SECTION_GLOBALS};
+    size_t size = SizeOfVarInt(i) + i * sizeof(data);
+    const byte globals[] = {WASM_SECTION_GLOBALS, U32V_5(size)};
     for (size_t g = 0; g != sizeof(globals); ++g) {
       buffer.push_back(globals[g]);
     }
@@ -192,7 +262,7 @@
     }
 
     ModuleResult result = DecodeModule(&buffer[0], &buffer[0] + buffer.size());
-    EXPECT_TRUE(result.ok());
+    EXPECT_OK(result);
     if (result.val) delete result.val;
   }
 }
@@ -221,10 +291,9 @@
   EXPECT_FAILURE(data);
 }
 
-
 TEST_F(WasmModuleVerifyTest, TwoGlobals) {
   static const byte data[] = {
-      SECTION(GLOBALS, 13),
+      SECTION(GLOBALS, 7),
       2,
       NO_NAME,  // #0: name length
       kMemF32,  // memory type
@@ -237,13 +306,13 @@
   {
     // Should decode to exactly two globals.
     ModuleResult result = DecodeModule(data, data + arraysize(data));
-    EXPECT_TRUE(result.ok());
+    EXPECT_OK(result);
     EXPECT_EQ(2, result.val->globals.size());
     EXPECT_EQ(0, result.val->functions.size());
     EXPECT_EQ(0, result.val->data_segments.size());
 
-    WasmGlobal* g0 = &result.val->globals[0];
-    WasmGlobal* g1 = &result.val->globals[1];
+    const WasmGlobal* g0 = &result.val->globals[0];
+    const WasmGlobal* g1 = &result.val->globals[1];
 
     EXPECT_EQ(0, g0->name_length);
     EXPECT_EQ(MachineType::Float32(), g0->type);
@@ -252,7 +321,7 @@
 
     EXPECT_EQ(0, g1->name_length);
     EXPECT_EQ(MachineType::Float64(), g1->type);
-    EXPECT_EQ(0, g1->offset);
+    EXPECT_EQ(8, g1->offset);
     EXPECT_TRUE(g1->exported);
 
     if (result.val) delete result.val;
@@ -261,39 +330,31 @@
   EXPECT_OFF_END_FAILURE(data, 1, sizeof(data));
 }
 
-
 TEST_F(WasmModuleVerifyTest, OneSignature) {
   {
-    static const byte data[] = {SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), 1,
-                                VOID_VOID_SIG};
+    static const byte data[] = {SIGNATURES_SECTION_VOID_VOID};
     EXPECT_VERIFIES(data);
   }
 
   {
-    static const byte data[] = {SECTION(SIGNATURES, 1 + INT_INT_SIG_SIZE), 1,
-                                INT_INT_SIG};
+    static const byte data[] = {SECTION(SIGNATURES, 1 + SIZEOF_SIG_ENTRY_x_x),
+                                1, SIG_ENTRY_i_i};
     EXPECT_VERIFIES(data);
   }
 }
 
-
 TEST_F(WasmModuleVerifyTest, MultipleSignatures) {
   static const byte data[] = {
-      SECTION(SIGNATURES, 10),
-      3,
-      0,
-      kLocalVoid,  // void -> void
-      1,
-      kLocalI32,
-      kLocalF32,  // f32 -> i32
-      2,
-      kLocalI32,
-      kLocalF64,
-      kLocalF64,  // (f64,f64) -> i32
+      SECTION(SIGNATURES, 1 + SIZEOF_SIG_ENTRY_v_v + SIZEOF_SIG_ENTRY_x_x +
+                              SIZEOF_SIG_ENTRY_x_xx),   // --
+      3,                                                // --
+      SIG_ENTRY_v_v,                                    // void -> void
+      SIG_ENTRY_x_x(kLocalI32, kLocalF32),              // f32 -> i32
+      SIG_ENTRY_x_xx(kLocalI32, kLocalF64, kLocalF64),  // f64,f64 -> i32
   };
 
   ModuleResult result = DecodeModule(data, data + arraysize(data));
-  EXPECT_TRUE(result.ok());
+  EXPECT_OK(result);
   EXPECT_EQ(3, result.val->signatures.size());
   if (result.val->signatures.size() == 3) {
     EXPECT_EQ(0, result.val->signatures[0]->return_count());
@@ -309,262 +370,8 @@
   EXPECT_OFF_END_FAILURE(data, 1, sizeof(data));
 }
 
-
-TEST_F(WasmModuleVerifyTest, FunctionWithoutSig) {
-  static const byte data[] = {
-      SECTION(FUNCTIONS, 25), 1,
-      // func#0 ------------------------------------------------------
-      SIG_INDEX(0),  // signature index
-      NO_NAME,       // name length
-      U32_LE(0),     // code start offset
-      U32_LE(0),     // code end offset
-      U16_LE(899),   // local int32 count
-      U16_LE(799),   // local int64 count
-      U16_LE(699),   // local float32 count
-      U16_LE(599),   // local float64 count
-      0,             // exported
-      1              // external
-  };
-
-  ModuleResult result = DecodeModule(data, data + arraysize(data));
-  EXPECT_FALSE(result.ok());
-  if (result.val) delete result.val;
-}
-
-
-TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) {
-  const int kCodeStartOffset = 51;
-  const int kCodeEndOffset = kCodeStartOffset + 1;
-
-  static const byte data[] = {
-      SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), 1,
-      // sig#0 -------------------------------------------------------
-      VOID_VOID_SIG,
-      // func#0 ------------------------------------------------------
-      SECTION(FUNCTIONS, 19), 1,
-      kDeclFunctionLocals | kDeclFunctionExport | kDeclFunctionName,
-      SIG_INDEX(0),              // signature index
-      NAME_LENGTH(2), 'h', 'i',  // name
-      U16_LE(1466),              // local int32 count
-      U16_LE(1355),              // local int64 count
-      U16_LE(1244),              // local float32 count
-      U16_LE(1133),              // local float64 count
-      1, 0,                      // size
-      kExprNop,
-  };
-
-  {
-    // Should decode to exactly one function.
-    ModuleResult result = DecodeModule(data, data + arraysize(data));
-    EXPECT_TRUE(result.ok());
-    EXPECT_EQ(0, result.val->globals.size());
-    EXPECT_EQ(1, result.val->signatures.size());
-    EXPECT_EQ(1, result.val->functions.size());
-    EXPECT_EQ(0, result.val->data_segments.size());
-    EXPECT_EQ(0, result.val->function_table.size());
-
-    WasmFunction* function = &result.val->functions.back();
-
-    EXPECT_EQ(39, function->name_offset);
-    EXPECT_EQ(2, function->name_length);
-    EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
-    EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
-
-    EXPECT_EQ(1466, function->local_i32_count);
-    EXPECT_EQ(1355, function->local_i64_count);
-    EXPECT_EQ(1244, function->local_f32_count);
-    EXPECT_EQ(1133, function->local_f64_count);
-
-    EXPECT_TRUE(function->exported);
-    EXPECT_FALSE(function->external);
-
-    if (result.val) delete result.val;
-  }
-
-  EXPECT_OFF_END_FAILURE(data, 16, sizeof(data));
-}
-
-
-TEST_F(WasmModuleVerifyTest, OneFunctionImported) {
-  static const byte data[] = {
-      SECTION(SIGNATURES, VOID_VOID_SIG_SIZE), 1,
-      // sig#0 -------------------------------------------------------
-      VOID_VOID_SIG, SECTION(FUNCTIONS, 6), 1,
-      // func#0 ------------------------------------------------------
-      kDeclFunctionImport,  // no name, no locals, imported
-      SIG_INDEX(0),
-  };
-
-  ModuleResult result = DecodeModule(data, data + arraysize(data));
-  EXPECT_TRUE(result.ok());
-  EXPECT_EQ(1, result.val->functions.size());
-  WasmFunction* function = &result.val->functions.back();
-
-  EXPECT_EQ(0, function->name_length);
-  EXPECT_EQ(0, function->code_start_offset);
-  EXPECT_EQ(0, function->code_end_offset);
-
-  EXPECT_EQ(0, function->local_i32_count);
-  EXPECT_EQ(0, function->local_i64_count);
-  EXPECT_EQ(0, function->local_f32_count);
-  EXPECT_EQ(0, function->local_f64_count);
-
-  EXPECT_FALSE(function->exported);
-  EXPECT_TRUE(function->external);
-
-  if (result.val) delete result.val;
-}
-
-TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody) {
-  static const byte kCodeStartOffset = 40;
-  static const byte kCodeEndOffset = kCodeStartOffset + 1;
-
-  static const byte data[] = {
-      SECTION(SIGNATURES, 3), 1,
-      // sig#0 -------------------------------------------------------
-      0, 0,  // void -> void
-      SECTION(FUNCTIONS, 7), 1,
-      // func#0 ------------------------------------------------------
-      0,        // no name, no locals
-      0, 0,     // signature index
-      1, 0,     // body size
-      kExprNop  // body
-  };
-
-  ModuleResult result = DecodeModule(data, data + arraysize(data));
-  EXPECT_TRUE(result.ok());
-  EXPECT_EQ(1, result.val->functions.size());
-  WasmFunction* function = &result.val->functions.back();
-
-  EXPECT_EQ(0, function->name_length);
-  EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
-  EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
-
-  EXPECT_EQ(0, function->local_i32_count);
-  EXPECT_EQ(0, function->local_i64_count);
-  EXPECT_EQ(0, function->local_f32_count);
-  EXPECT_EQ(0, function->local_f64_count);
-
-  EXPECT_FALSE(function->exported);
-  EXPECT_FALSE(function->external);
-
-  if (result.val) delete result.val;
-}
-
-
-TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody_WithLocals) {
-  static const byte kCodeStartOffset = 48;
-  static const byte kCodeEndOffset = kCodeStartOffset + 1;
-
-  static const byte data[] = {
-      SECTION(SIGNATURES, 3), 1,
-      // sig#0 -------------------------------------------------------
-      0, 0,  // void -> void
-      SECTION(FUNCTIONS, 15), 1,
-      // func#0 ------------------------------------------------------
-      kDeclFunctionLocals, 0, 0,  // signature index
-      1, 2,                       // local int32 count
-      3, 4,                       // local int64 count
-      5, 6,                       // local float32 count
-      7, 8,                       // local float64 count
-      1, 0,                       // body size
-      kExprNop                    // body
-  };
-
-  ModuleResult result = DecodeModule(data, data + arraysize(data));
-  EXPECT_TRUE(result.ok());
-  EXPECT_EQ(1, result.val->functions.size());
-  WasmFunction* function = &result.val->functions.back();
-
-  EXPECT_EQ(0, function->name_length);
-  EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
-  EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
-
-  EXPECT_EQ(513, function->local_i32_count);
-  EXPECT_EQ(1027, function->local_i64_count);
-  EXPECT_EQ(1541, function->local_f32_count);
-  EXPECT_EQ(2055, function->local_f64_count);
-
-  EXPECT_FALSE(function->exported);
-  EXPECT_FALSE(function->external);
-
-  if (result.val) delete result.val;
-}
-
-
-TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) {
-  static const byte kCodeStartOffset = 75;
-  static const byte kCodeEndOffset = kCodeStartOffset + 3;
-  static const byte kDataSegmentSourceOffset = kCodeEndOffset + 20;
-
-  static const byte data[] = {
-      SECTION(MEMORY, 3), 28, 28, 1,
-      // global#0 --------------------------------------------------
-      SECTION(GLOBALS, 7), 1,
-      0,       // name length
-      kMemU8,  // memory type
-      0,       // exported
-      // sig#0 -----------------------------------------------------
-      SECTION(SIGNATURES, 3), 1, 0, 0,  // void -> void
-      // func#0 ----------------------------------------------------
-      SECTION(FUNCTIONS, 20), 1, kDeclFunctionLocals | kDeclFunctionName, 0,
-      0,            // signature index
-      2, 'h', 'i',  // name
-      1, 2,         // local int32 count
-      3, 4,         // local int64 count
-      5, 6,         // local float32 count
-      7, 8,         // local float64 count
-      3, 0,         // body size
-      kExprNop,     // func#0 body
-      kExprNop,     // func#0 body
-      kExprNop,     // func#0 body
-      // segment#0 -------------------------------------------------
-      SECTION(DATA_SEGMENTS, 14), 1,
-      U32V_3(0x8b3ae),  // dest addr
-      U32V_1(5),        // source size
-      0, 1, 2, 3, 4,    // data bytes
-      // rest ------------------------------------------------------
-      SECTION(END, 0),
-  };
-
-  {
-    ModuleResult result = DecodeModule(data, data + arraysize(data));
-    EXPECT_TRUE(result.ok());
-    EXPECT_EQ(1, result.val->globals.size());
-    EXPECT_EQ(1, result.val->functions.size());
-    EXPECT_EQ(1, result.val->data_segments.size());
-
-    WasmGlobal* global = &result.val->globals.back();
-
-    EXPECT_EQ(0, global->name_length);
-    EXPECT_EQ(MachineType::Uint8(), global->type);
-    EXPECT_EQ(0, global->offset);
-    EXPECT_FALSE(global->exported);
-
-    WasmFunction* function = &result.val->functions.back();
-
-    EXPECT_EQ(63, function->name_offset);
-    EXPECT_EQ(2, function->name_length);
-    EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
-    EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
-
-    EXPECT_FALSE(function->exported);
-    EXPECT_FALSE(function->external);
-
-    WasmDataSegment* segment = &result.val->data_segments.back();
-
-    EXPECT_EQ(0x8b3ae, segment->dest_addr);
-    EXPECT_EQ(kDataSegmentSourceOffset, segment->source_offset);
-    EXPECT_EQ(5, segment->source_size);
-    EXPECT_TRUE(segment->init);
-
-    if (result.val) delete result.val;
-  }
-}
-
-
 TEST_F(WasmModuleVerifyTest, OneDataSegment) {
-  const byte kDataSegmentSourceOffset = 39;
+  const byte kDataSegmentSourceOffset = 30;
   const byte data[] = {
       SECTION(MEMORY, 3),
       28,
@@ -582,12 +389,12 @@
   {
     EXPECT_VERIFIES(data);
     ModuleResult result = DecodeModule(data, data + arraysize(data));
-    EXPECT_TRUE(result.ok());
+    EXPECT_OK(result);
     EXPECT_EQ(0, result.val->globals.size());
     EXPECT_EQ(0, result.val->functions.size());
     EXPECT_EQ(1, result.val->data_segments.size());
 
-    WasmDataSegment* segment = &result.val->data_segments.back();
+    const WasmDataSegment* segment = &result.val->data_segments.back();
 
     EXPECT_EQ(0x9bbaa, segment->dest_addr);
     EXPECT_EQ(kDataSegmentSourceOffset, segment->source_offset);
@@ -600,17 +407,16 @@
   EXPECT_OFF_END_FAILURE(data, 13, sizeof(data));
 }
 
-
 TEST_F(WasmModuleVerifyTest, TwoDataSegments) {
-  const byte kDataSegment0SourceOffset = 39;
-  const byte kDataSegment1SourceOffset = 39 + 8;
+  const byte kDataSegment0SourceOffset = 30;
+  const byte kDataSegment1SourceOffset = 30 + 8;
 
   const byte data[] = {
       SECTION(MEMORY, 3),
       28,
       28,
       1,
-      SECTION(DATA_SEGMENTS, 31),
+      SECTION(DATA_SEGMENTS, 23),
       2,                // segment count
       U32V_3(0x7ffee),  // #0: dest addr
       U32V_1(4),        // source size
@@ -634,13 +440,13 @@
 
   {
     ModuleResult result = DecodeModule(data, data + arraysize(data));
-    EXPECT_TRUE(result.ok());
+    EXPECT_OK(result);
     EXPECT_EQ(0, result.val->globals.size());
     EXPECT_EQ(0, result.val->functions.size());
     EXPECT_EQ(2, result.val->data_segments.size());
 
-    WasmDataSegment* s0 = &result.val->data_segments[0];
-    WasmDataSegment* s1 = &result.val->data_segments[1];
+    const WasmDataSegment* s0 = &result.val->data_segments[0];
+    const WasmDataSegment* s1 = &result.val->data_segments[1];
 
     EXPECT_EQ(0x7ffee, s0->dest_addr);
     EXPECT_EQ(kDataSegment0SourceOffset, s0->source_offset);
@@ -670,7 +476,7 @@
                      mem_pages,
                      mem_pages,
                      1,
-                     SECTION(DATA_SEGMENTS, 14),
+                     SECTION(DATA_SEGMENTS, 8),
                      1,
                      U32V_3(dest_addr),
                      U32V_1(source_size),
@@ -687,21 +493,17 @@
   }
 }
 
-
-// To make below tests for indirect calls much shorter.
-#define FUNCTION(sig_index, external) kDeclFunctionImport, SIG_INDEX(sig_index)
-
 TEST_F(WasmModuleVerifyTest, OneIndirectFunction) {
   static const byte data[] = {
       // sig#0 -------------------------------------------------------
-      SECTION(SIGNATURES, 3), 1, 0, 0,  // void -> void
-      // func#0 ------------------------------------------------------
-      SECTION(FUNCTIONS, 4), 1, FUNCTION(0, 0),
+      SIGNATURES_SECTION_VOID_VOID,
+      // funcs ------------------------------------------------------
+      ONE_EMPTY_FUNCTION,
       // indirect table ----------------------------------------------
       SECTION(FUNCTION_TABLE, 2), 1, U32V_1(0)};
 
   ModuleResult result = DecodeModule(data, data + arraysize(data));
-  EXPECT_TRUE(result.ok());
+  EXPECT_OK(result);
   if (result.ok()) {
     EXPECT_EQ(1, result.val->signatures.size());
     EXPECT_EQ(1, result.val->functions.size());
@@ -711,17 +513,15 @@
   if (result.val) delete result.val;
 }
 
-
 TEST_F(WasmModuleVerifyTest, MultipleIndirectFunctions) {
   static const byte data[] = {
       // sig#0 -------------------------------------------------------
-      SECTION(SIGNATURES, 5), 2, 0, 0,  // void -> void
-      0, kLocalI32,                     // void -> i32
-      // func#0 ------------------------------------------------------
-      SECTION(FUNCTIONS, 13), 4, FUNCTION(0, 1),  // --
-      FUNCTION(1, 1),                             // --
-      FUNCTION(0, 1),                             // --
-      FUNCTION(1, 1),                             // --
+      SECTION(SIGNATURES, 1 + SIZEOF_SIG_ENTRY_v_v + SIZEOF_SIG_ENTRY_v_x),
+      2,                         // --
+      SIG_ENTRY_v_v,             // void -> void
+      SIG_ENTRY_v_x(kLocalI32),  // void -> i32
+      // funcs ------------------------------------------------------
+      FOUR_EMPTY_FUNCTIONS,
       // indirect table ----------------------------------------------
       SECTION(FUNCTION_TABLE, 9), 8,
       U32V_1(0),  // --
@@ -732,10 +532,10 @@
       U32V_1(1),  // --
       U32V_1(2),  // --
       U32V_1(3),  // --
-  };
+      FOUR_EMPTY_BODIES};
 
   ModuleResult result = DecodeModule(data, data + arraysize(data));
-  EXPECT_TRUE(result.ok());
+  EXPECT_OK(result);
   if (result.ok()) {
     EXPECT_EQ(2, result.val->signatures.size());
     EXPECT_EQ(4, result.val->functions.size());
@@ -747,11 +547,10 @@
   if (result.val) delete result.val;
 }
 
-
 TEST_F(WasmModuleVerifyTest, IndirectFunctionNoFunctions) {
   static const byte data[] = {
       // sig#0 -------------------------------------------------------
-      SECTION(SIGNATURES, 3), 1, 0, 0,  // void -> void
+      SIGNATURES_SECTION_VOID_VOID,
       // indirect table ----------------------------------------------
       SECTION(FUNCTION_TABLE, 3), 1, 0, 0,
   };
@@ -759,13 +558,12 @@
   EXPECT_FAILURE(data);
 }
 
-
 TEST_F(WasmModuleVerifyTest, IndirectFunctionInvalidIndex) {
   static const byte data[] = {
       // sig#0 -------------------------------------------------------
-      SECTION(SIGNATURES, 3), 1, 0, 0,  // void -> void
+      SIGNATURES_SECTION_VOID_VOID,
       // functions ---------------------------------------------------
-      SECTION(FUNCTIONS, 4), 1, FUNCTION(0, 1),
+      ONE_EMPTY_FUNCTION,
       // indirect table ----------------------------------------------
       SECTION(FUNCTION_TABLE, 3), 1, 1, 0,
   };
@@ -773,12 +571,10 @@
   EXPECT_FAILURE(data);
 }
 
-
 class WasmSignatureDecodeTest : public TestWithZone {};
 
-
 TEST_F(WasmSignatureDecodeTest, Ok_v_v) {
-  static const byte data[] = {0, 0};
+  static const byte data[] = {SIG_ENTRY_v_v};
   base::AccountingAllocator allocator;
   Zone zone(&allocator);
   FunctionSig* sig =
@@ -789,11 +585,10 @@
   EXPECT_EQ(0, sig->return_count());
 }
 
-
 TEST_F(WasmSignatureDecodeTest, Ok_t_v) {
   for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
     LocalTypePair ret_type = kLocalTypes[i];
-    const byte data[] = {0, ret_type.code};
+    const byte data[] = {SIG_ENTRY_x(ret_type.code)};
     FunctionSig* sig =
         DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
 
@@ -804,11 +599,10 @@
   }
 }
 
-
 TEST_F(WasmSignatureDecodeTest, Ok_v_t) {
   for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
     LocalTypePair param_type = kLocalTypes[i];
-    const byte data[] = {1, 0, param_type.code};
+    const byte data[] = {SIG_ENTRY_v_x(param_type.code)};
     FunctionSig* sig =
         DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
 
@@ -819,15 +613,12 @@
   }
 }
 
-
 TEST_F(WasmSignatureDecodeTest, Ok_t_t) {
   for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
     LocalTypePair ret_type = kLocalTypes[i];
     for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
       LocalTypePair param_type = kLocalTypes[j];
-      const byte data[] = {1,                 // param count
-                           ret_type.code,     // ret
-                           param_type.code};  // param
+      const byte data[] = {SIG_ENTRY_x_x(ret_type.code, param_type.code)};
       FunctionSig* sig =
           DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
 
@@ -840,16 +631,13 @@
   }
 }
 
-
 TEST_F(WasmSignatureDecodeTest, Ok_i_tt) {
   for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
     LocalTypePair p0_type = kLocalTypes[i];
     for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
       LocalTypePair p1_type = kLocalTypes[j];
-      const byte data[] = {2,              // param count
-                           kLocalI32,      // ret
-                           p0_type.code,   // p0
-                           p1_type.code};  // p1
+      const byte data[] = {
+          SIG_ENTRY_x_xx(kLocalI32, p0_type.code, p1_type.code)};
       FunctionSig* sig =
           DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
 
@@ -862,7 +650,6 @@
   }
 }
 
-
 TEST_F(WasmSignatureDecodeTest, Fail_off_end) {
   byte data[256];
   for (int p = 0; p <= 255; p = p + 1 + p * 3) {
@@ -877,11 +664,10 @@
   }
 }
 
-
 TEST_F(WasmSignatureDecodeTest, Fail_invalid_type) {
   byte kInvalidType = 76;
-  for (int i = 1; i < 3; i++) {
-    byte data[] = {2, kLocalI32, kLocalI32, kLocalI32};
+  for (size_t i = 0; i < SIZEOF_SIG_ENTRY_x_xx; i++) {
+    byte data[] = {SIG_ENTRY_x_xx(kLocalI32, kLocalI32, kLocalI32)};
     data[i] = kInvalidType;
     FunctionSig* sig =
         DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
@@ -889,47 +675,56 @@
   }
 }
 
-
-TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type) {
-  static const int kParamCount = 3;
-  for (int i = 0; i < kParamCount; i++) {
-    byte data[] = {kParamCount, kLocalI32, kLocalI32, kLocalI32, kLocalI32};
-    data[i + 2] = kLocalVoid;
-    FunctionSig* sig =
-        DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
-    EXPECT_EQ(nullptr, sig);
-  }
+TEST_F(WasmSignatureDecodeTest, Fail_invalid_ret_type1) {
+  static const byte data[] = {SIG_ENTRY_x_x(kLocalVoid, kLocalI32)};
+  FunctionSig* sig =
+      DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
+  EXPECT_EQ(nullptr, sig);
 }
 
+TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type1) {
+  static const byte data[] = {SIG_ENTRY_x_x(kLocalI32, kLocalVoid)};
+  FunctionSig* sig =
+      DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
+  EXPECT_EQ(nullptr, sig);
+}
 
-class WasmFunctionVerifyTest : public TestWithZone {};
+TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type2) {
+  static const byte data[] = {SIG_ENTRY_x_xx(kLocalI32, kLocalI32, kLocalVoid)};
+  FunctionSig* sig =
+      DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
+  EXPECT_EQ(nullptr, sig);
+}
 
+class WasmFunctionVerifyTest : public TestWithIsolateAndZone {};
 
 TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
   static const byte data[] = {
-      0,       kLocalVoid,  // signature
-      4,                    // locals
-      3,       kLocalI32,   // --
-      4,       kLocalI64,   // --
-      5,       kLocalF32,   // --
-      6,       kLocalF64,   // --
-      kExprNop              // body
+      SIG_ENTRY_v_v,  // signature entry
+      4,              // locals
+      3,
+      kLocalI32,  // --
+      4,
+      kLocalI64,  // --
+      5,
+      kLocalF32,  // --
+      6,
+      kLocalF64,  // --
+      kExprNop    // body
   };
 
-  FunctionResult result = DecodeWasmFunction(nullptr, zone(), nullptr, data,
+  FunctionResult result = DecodeWasmFunction(isolate(), zone(), nullptr, data,
                                              data + arraysize(data));
-  EXPECT_TRUE(result.ok());
+  EXPECT_OK(result);
 
   if (result.val && result.ok()) {
     WasmFunction* function = result.val;
     EXPECT_EQ(0, function->sig->parameter_count());
     EXPECT_EQ(0, function->sig->return_count());
     EXPECT_EQ(0, function->name_offset);
-    EXPECT_EQ(2, function->code_start_offset);
+    EXPECT_EQ(SIZEOF_SIG_ENTRY_v_v, function->code_start_offset);
     EXPECT_EQ(arraysize(data), function->code_end_offset);
     // TODO(titzer): verify encoding of local declarations
-    EXPECT_FALSE(function->external);
-    EXPECT_FALSE(function->exported);
   }
 
   if (result.val) delete result.val;
@@ -942,47 +737,51 @@
 
 TEST_F(WasmModuleVerifyTest, TheLoneliestOfValidModulesTheTrulyEmptyOne) {
   const byte data[] = {
-      1,  // Section size.
       0,  // Empty section name.
           // No section name, no content, nothing but sadness.
+      0,  // No section content.
   };
   EXPECT_VERIFIES(data);
 }
 
 TEST_F(WasmModuleVerifyTest, OnlyUnknownSectionEmpty) {
   const byte data[] = {
-      5,                      // Section size.
-      4, 'l', 'u', 'l', 'z',  // unknown section.
+      UNKNOWN_SECTION_NAME, 0,
   };
   EXPECT_VERIFIES(data);
 }
 
 TEST_F(WasmModuleVerifyTest, OnlyUnknownSectionNonEmpty) {
   const byte data[] = {
-      10,                     // Section size.
-      4, 'l', 'u', 'l', 'z',  // unknown section.
-      // Section content:
-      0xff, 0xff, 0xff, 0xff, 0xff,
+      UNKNOWN_SECTION_NAME,
+      5,  // section size
+      0xff,
+      0xff,
+      0xff,
+      0xff,
+      0xff,  // section data
   };
   EXPECT_VERIFIES(data);
 }
 
 TEST_F(WasmModuleVerifyTest, SignatureFollowedByEmptyUnknownSection) {
   const byte data[] = {
-      SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), 1, VOID_VOID_SIG,
+      // signatures
+      SIGNATURES_SECTION_VOID_VOID,
       // -----------------------------------------------------------
-      5,                      // Section size.
-      4, 'l', 'u', 'l', 'z',  // unknown section.
+      UNKNOWN_SECTION_NAME,
+      0  // empty section
   };
   EXPECT_VERIFIES(data);
 }
 
 TEST_F(WasmModuleVerifyTest, SignatureFollowedByUnknownSection) {
   const byte data[] = {
-      SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), 1, VOID_VOID_SIG,
+      // signatures
+      SIGNATURES_SECTION_VOID_VOID,
       // -----------------------------------------------------------
-      10,                     // Section size.
-      4, 'l', 'u', 'l', 'z',  // unknown section.
+      UNKNOWN_SECTION_NAME,
+      5,  // section size
       0xff, 0xff, 0xff, 0xff, 0xff,
   };
   EXPECT_VERIFIES(data);
@@ -990,29 +789,46 @@
 
 TEST_F(WasmModuleVerifyTest, SignatureFollowedByUnknownSectionWithLongLEB) {
   const byte data[] = {
-      SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE), 1, VOID_VOID_SIG,
+      // signatures
+      SIGNATURES_SECTION_VOID_VOID,
       // -----------------------------------------------------------
-      0x85, 0x80, 0x80, 0x80, 0x00,  // Section size: 1 but in a 5-byte LEB.
-      4, 'l', 'u', 'l', 'z',         // unknown section.
+      UNKNOWN_SECTION_NAME, 0x81, 0x80, 0x80, 0x80,
+      0x00,  // section size: 1 but in a 5-byte LEB
+      0,
   };
   EXPECT_VERIFIES(data);
 }
 
 TEST_F(WasmModuleVerifyTest, UnknownSectionOverflow) {
   static const byte data[] = {
-      13,                                // Section size.
-      1,                                 // Section name length.
-      '\0',                              // Section name.
-      1,    2, 3, 4, 5, 6, 7, 8, 9, 10,  // 10 byte section
+      UNKNOWN_EMPTY_SECTION_NAME,
+      9,  // section size
+      1,
+      2,
+      3,
+      4,
+      5,
+      6,
+      7,
+      8,
+      9,
+      10,  // 10 byte section
   };
   EXPECT_FAILURE(data);
 }
 
 TEST_F(WasmModuleVerifyTest, UnknownSectionUnderflow) {
   static const byte data[] = {
-      0xff, 0xff, 0xff, 0xff, 0x0f,  // Section size LEB128 0xffffffff
-      1,    '\0',                    // Section name and name length.
-      1,    2,    3,    4,           // 4 byte section
+      UNKNOWN_EMPTY_SECTION_NAME,
+      0xff,
+      0xff,
+      0xff,
+      0xff,
+      0x0f,  // Section size LEB128 0xffffffff
+      1,
+      2,
+      3,
+      4,  // 4 byte section
   };
   EXPECT_FAILURE(data);
 }
@@ -1020,33 +836,39 @@
 TEST_F(WasmModuleVerifyTest, UnknownSectionLoop) {
   // Would infinite loop decoding if wrapping and allowed.
   static const byte data[] = {
-      0xfa, 0xff, 0xff, 0xff, 0x0f,  // Section size LEB128 0xfffffffa
-      1,    '\0',                    // Section name and name length.
-      1,    2,    3,    4,           // 4 byte section
+      UNKNOWN_EMPTY_SECTION_NAME,
+      1,
+      2,
+      3,
+      4,  // 4 byte section
+      0xfa,
+      0xff,
+      0xff,
+      0xff,
+      0x0f,  // Section size LEB128 0xfffffffa
   };
   EXPECT_FAILURE(data);
 }
 
 TEST_F(WasmModuleVerifyTest, UnknownSectionSkipped) {
   static const byte data[] = {
-      3,  // Section size.
-      1,
-      '\0',  // Section name: LEB128 1, string '\0'
-      0,     // one byte section
-      SECTION(GLOBALS, 7),
+      UNKNOWN_EMPTY_SECTION_NAME,
+      1,  // section size
+      0,  // one byte section
+      SECTION(GLOBALS, 4),
       1,
       0,        // name length
       kMemI32,  // memory type
       0,        // exported
   };
   ModuleResult result = DecodeModule(data, data + arraysize(data));
-  EXPECT_TRUE(result.ok());
+  EXPECT_OK(result);
 
   EXPECT_EQ(1, result.val->globals.size());
   EXPECT_EQ(0, result.val->functions.size());
   EXPECT_EQ(0, result.val->data_segments.size());
 
-  WasmGlobal* global = &result.val->globals.back();
+  const WasmGlobal* global = &result.val->globals.back();
 
   EXPECT_EQ(0, global->name_length);
   EXPECT_EQ(MachineType::Int32(), global->type);
@@ -1062,26 +884,36 @@
   EXPECT_VERIFIES(data);
 }
 
-TEST_F(WasmModuleVerifyTest, ImportTable_nosigs) {
+TEST_F(WasmModuleVerifyTest, ImportTable_nosigs1) {
   static const byte data[] = {SECTION(IMPORT_TABLE, 1), 0};
+  EXPECT_VERIFIES(data);
+}
+
+TEST_F(WasmModuleVerifyTest, ImportTable_nosigs2) {
+  static const byte data[] = {
+      SECTION(IMPORT_TABLE, 6), 1,    // sig table
+      IMPORT_SIG_INDEX(0),            // sig index
+      NAME_LENGTH(1),           'm',  // module name
+      NAME_LENGTH(1),           'f',  // function name
+  };
   EXPECT_FAILURE(data);
 }
 
 TEST_F(WasmModuleVerifyTest, ImportTable_invalid_sig) {
   static const byte data[] = {
-      SECTION(SIGNATURES, 1), 0,   SECTION(IMPORT_TABLE, 6), 1,
-      IMPORT_SIG_INDEX(0),          // sig index
-      NAME_LENGTH(1),         'm',  // module name
-      NAME_LENGTH(1),         'f',  // function name
+      SECTION(SIGNATURES, 1),   0,    // --
+      SECTION(IMPORT_TABLE, 6), 1,    // --
+      IMPORT_SIG_INDEX(0),            // sig index
+      NAME_LENGTH(1),           'm',  // module name
+      NAME_LENGTH(1),           'f',  // function name
   };
   EXPECT_FAILURE(data);
 }
 
 TEST_F(WasmModuleVerifyTest, ImportTable_one_sig) {
   static const byte data[] = {
-      SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
-      1,
-      VOID_VOID_SIG,
+      // signatures
+      SIGNATURES_SECTION_VOID_VOID,
       SECTION(IMPORT_TABLE, 6),
       1,                    // --
       IMPORT_SIG_INDEX(0),  // sig index
@@ -1095,9 +927,8 @@
 
 TEST_F(WasmModuleVerifyTest, ImportTable_invalid_module) {
   static const byte data[] = {
-      SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
-      1,
-      VOID_VOID_SIG,
+      // signatures
+      SIGNATURES_SECTION_VOID_VOID,
       SECTION(IMPORT_TABLE, 6),
       1,                    // --
       IMPORT_SIG_INDEX(0),  // sig index
@@ -1110,9 +941,8 @@
 
 TEST_F(WasmModuleVerifyTest, ImportTable_off_end) {
   static const byte data[] = {
-      SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
-      1,
-      VOID_VOID_SIG,
+      // signatures
+      SIGNATURES_SECTION_VOID_VOID,
       SECTION(IMPORT_TABLE, 6),
       1,
       IMPORT_SIG_INDEX(0),  // sig index
@@ -1126,28 +956,33 @@
 }
 
 TEST_F(WasmModuleVerifyTest, ExportTable_empty1) {
-  static const byte data[] = {SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
-                              1,
-                              VOID_VOID_SIG,
-                              SECTION(FUNCTIONS, 1 + EMPTY_FUNCTION_SIZE),
-                              1,
-                              EMPTY_FUNCTION(0),
+  static const byte data[] = {// signatures
+                              SIGNATURES_SECTION_VOID_VOID, ONE_EMPTY_FUNCTION,
                               SECTION(EXPORT_TABLE, 1),
-                              0};
-  EXPECT_VERIFIES(data);
+                              0,  // --
+                              ONE_EMPTY_BODY};
+
+  ModuleResult result = DecodeModule(data, data + arraysize(data));
+  EXPECT_OK(result);
+
+  EXPECT_EQ(1, result.val->functions.size());
+  EXPECT_EQ(0, result.val->export_table.size());
+
+  if (result.val) delete result.val;
 }
 
 TEST_F(WasmModuleVerifyTest, ExportTable_empty2) {
-  static const byte data[] = {SECTION(SIGNATURES, 1),   0,
-                              SECTION(FUNCTIONS, 1),    0,
-                              SECTION(EXPORT_TABLE, 1), 0};
+  static const byte data[] = {
+      SECTION(SIGNATURES, 1), 0, SECTION(EXPORT_TABLE, 1), 0  // --
+  };
   // TODO(titzer): current behavior treats empty functions section as missing.
   EXPECT_FAILURE(data);
 }
 
 TEST_F(WasmModuleVerifyTest, ExportTable_NoFunctions1) {
-  static const byte data[] = {SECTION(SIGNATURES, 1), 0,
-                              SECTION(EXPORT_TABLE, 1), 0};
+  static const byte data[] = {
+      SECTION(SIGNATURES, 1), 0, SECTION(EXPORT_TABLE, 1), 0  // --
+  };
   EXPECT_FAILURE(data);
 }
 
@@ -1157,89 +992,88 @@
 }
 
 TEST_F(WasmModuleVerifyTest, ExportTableOne) {
-  static const byte data[] = {
-      SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
-      1,              // sigs
-      VOID_VOID_SIG,  // --
-      SECTION(FUNCTIONS, 1 + EMPTY_FUNCTION_SIZE),
-      1,                  // functions
-      EMPTY_FUNCTION(0),  // --
-      SECTION(EXPORT_TABLE, 7),
-      1,              // exports
-      FUNC_INDEX(0),  // --
-      NO_NAME         // --
-  };
-  EXPECT_VERIFIES(data);
+  static const byte data[] = {// signatures
+                              SIGNATURES_SECTION_VOID_VOID,
+                              ONE_EMPTY_FUNCTION,
+                              SECTION(EXPORT_TABLE, 3),
+                              1,              // exports
+                              FUNC_INDEX(0),  // --
+                              NO_NAME,        // --
+                              ONE_EMPTY_BODY};
+  ModuleResult result = DecodeModule(data, data + arraysize(data));
+  EXPECT_OK(result);
+
+  EXPECT_EQ(1, result.val->functions.size());
+  EXPECT_EQ(1, result.val->export_table.size());
+
+  if (result.val) delete result.val;
 }
 
 TEST_F(WasmModuleVerifyTest, ExportTableTwo) {
-  static const byte data[] = {
-      SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
-      1,              // sigs
-      VOID_VOID_SIG,  // --
-      SECTION(FUNCTIONS, 1 + EMPTY_FUNCTION_SIZE),
-      1,                  // functions
-      EMPTY_FUNCTION(0),  // --
-      SECTION(EXPORT_TABLE, 12),
-      2,              // exports
-      FUNC_INDEX(0),  // --
-      NAME_LENGTH(4),
-      'n',
-      'a',
-      'm',
-      'e',            // --
-      FUNC_INDEX(0),  // --
-      NAME_LENGTH(3),
-      'n',
-      'o',
-      'm'  // --
-  };
-  EXPECT_VERIFIES(data);
+  static const byte data[] = {// signatures
+                              SIGNATURES_SECTION_VOID_VOID,
+                              ONE_EMPTY_FUNCTION,
+                              SECTION(EXPORT_TABLE, 12),
+                              2,              // exports
+                              FUNC_INDEX(0),  // --
+                              NAME_LENGTH(4),
+                              'n',
+                              'a',
+                              'm',
+                              'e',            // --
+                              FUNC_INDEX(0),  // --
+                              NAME_LENGTH(3),
+                              'n',
+                              'o',
+                              'm',  // --
+                              ONE_EMPTY_BODY};
+
+  ModuleResult result = DecodeModule(data, data + arraysize(data));
+  EXPECT_OK(result);
+
+  EXPECT_EQ(1, result.val->functions.size());
+  EXPECT_EQ(2, result.val->export_table.size());
+
+  if (result.val) delete result.val;
 }
 
 TEST_F(WasmModuleVerifyTest, ExportTableThree) {
-  static const byte data[] = {
-      SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
-      1,              // sigs
-      VOID_VOID_SIG,  // --
-      SECTION(FUNCTIONS, 1 + 3 * EMPTY_FUNCTION_SIZE),
-      3,                  // functions
-      EMPTY_FUNCTION(0),  // --
-      EMPTY_FUNCTION(0),  // --
-      EMPTY_FUNCTION(0),  // --
-      SECTION(EXPORT_TABLE, 10),
-      3,              // exports
-      FUNC_INDEX(0),  // --
-      NAME_LENGTH(1),
-      'a',            // --
-      FUNC_INDEX(1),  // --
-      NAME_LENGTH(1),
-      'b',            // --
-      FUNC_INDEX(2),  // --
-      NAME_LENGTH(1),
-      'c'  // --
-  };
-  EXPECT_VERIFIES(data);
+  static const byte data[] = {// signatures
+                              SIGNATURES_SECTION_VOID_VOID,
+                              THREE_EMPTY_FUNCTIONS,
+                              SECTION(EXPORT_TABLE, 10),
+                              3,              // exports
+                              FUNC_INDEX(0),  // --
+                              NAME_LENGTH(1),
+                              'a',            // --
+                              FUNC_INDEX(1),  // --
+                              NAME_LENGTH(1),
+                              'b',            // --
+                              FUNC_INDEX(2),  // --
+                              NAME_LENGTH(1),
+                              'c',  // --
+                              THREE_EMPTY_BODIES};
+  ModuleResult result = DecodeModule(data, data + arraysize(data));
+  EXPECT_OK(result);
+
+  EXPECT_EQ(3, result.val->functions.size());
+  EXPECT_EQ(3, result.val->export_table.size());
+
+  if (result.val) delete result.val;
 }
 
 TEST_F(WasmModuleVerifyTest, ExportTableThreeOne) {
   for (int i = 0; i < 6; i++) {
-    const byte data[] = {
-        SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
-        1,              // sigs
-        VOID_VOID_SIG,  // --
-        SECTION(FUNCTIONS, 1 + 3 * EMPTY_FUNCTION_SIZE),
-        3,                  // functions
-        EMPTY_FUNCTION(0),  // --
-        EMPTY_FUNCTION(0),  // --
-        EMPTY_FUNCTION(0),  // --
-        SECTION(EXPORT_TABLE, 5),
-        1,              // exports
-        FUNC_INDEX(i),  // --
-        NAME_LENGTH(2),
-        'e',
-        'x',  // --
-    };
+    const byte data[] = {// signatures
+                         SIGNATURES_SECTION_VOID_VOID,
+                         THREE_EMPTY_FUNCTIONS,
+                         SECTION(EXPORT_TABLE, 5),
+                         1,              // exports
+                         FUNC_INDEX(i),  // --
+                         NAME_LENGTH(2),
+                         'e',
+                         'x',  // --
+                         THREE_EMPTY_BODIES};
 
     if (i < 3) {
       EXPECT_VERIFIES(data);
@@ -1251,12 +1085,9 @@
 
 TEST_F(WasmModuleVerifyTest, ExportTableOne_off_end) {
   static const byte data[] = {
-      SECTION(SIGNATURES, 1 + VOID_VOID_SIG_SIZE),
-      1,              // sigs
-      VOID_VOID_SIG,  // --
-      SECTION(FUNCTIONS, 1 + EMPTY_FUNCTION_SIZE),
-      1,                  // functions
-      EMPTY_FUNCTION(0),  // --
+      // signatures
+      SIGNATURES_SECTION_VOID_VOID,
+      ONE_EMPTY_FUNCTION,
       SECTION(EXPORT_TABLE, 1 + 6),
       1,              // exports
       FUNC_INDEX(0),  // --
@@ -1270,67 +1101,68 @@
   }
 }
 
-#define SIGNATURES_SECTION(count, ...) \
-  SECTION(SIGNATURES, 1 + 3 * (count)), U32V_1(count), __VA_ARGS__
-#define FUNCTION_SIGNATURES_SECTION(count, ...) \
-  SECTION(FUNCTION_SIGNATURES, 1 + (count)), U32V_1(count), __VA_ARGS__
-
-#define FOO_STRING 3, 'f', 'o', 'o'
-#define NO_LOCAL_NAMES 0
-
-#define EMPTY_SIGNATURES_SECTION SECTION(SIGNATURES, 1), 0
-#define EMPTY_FUNCTION_SIGNATURES_SECTION SECTION(FUNCTION_SIGNATURES, 1), 0
-#define EMPTY_FUNCTION_BODIES_SECTION SECTION(FUNCTION_BODIES, 1), 0
-#define EMPTY_NAMES_SECTION SECTION(NAMES, 1), 0
-
 TEST_F(WasmModuleVerifyTest, FunctionSignatures_empty) {
-  static const byte data[] = {SECTION(SIGNATURES, 1), 0,
-                              SECTION(FUNCTION_SIGNATURES, 1), 0};
+  static const byte data[] = {
+      SECTION(SIGNATURES, 1), 0,          // --
+      SECTION(FUNCTION_SIGNATURES, 1), 0  // --
+  };                                      // --
   EXPECT_VERIFIES(data);
 }
 
 TEST_F(WasmModuleVerifyTest, FunctionSignatures_one) {
-  static const byte data[] = {SIGNATURES_SECTION(1, VOID_VOID_SIG),
-                              FUNCTION_SIGNATURES_SECTION(1, 0)};
+  static const byte data[] = {
+      SIGNATURES_SECTION(1, SIG_ENTRY_v_v),  // --
+      FUNCTION_SIGNATURES_SECTION(1, 0)      // --
+  };
   EXPECT_VERIFIES(data);
 }
 
 TEST_F(WasmModuleVerifyTest, FunctionBodies_empty) {
-  static const byte data[] = {EMPTY_SIGNATURES_SECTION,
-                              EMPTY_FUNCTION_SIGNATURES_SECTION,
-                              EMPTY_FUNCTION_BODIES_SECTION};
+  static const byte data[] = {
+      EMPTY_SIGNATURES_SECTION,           // --
+      EMPTY_FUNCTION_SIGNATURES_SECTION,  // --
+      EMPTY_FUNCTION_BODIES_SECTION       // --
+  };
   EXPECT_VERIFIES(data);
 }
 
 TEST_F(WasmModuleVerifyTest, FunctionBodies_one_empty) {
   static const byte data[] = {
-      SIGNATURES_SECTION(1, VOID_VOID_SIG), FUNCTION_SIGNATURES_SECTION(1, 0),
-      SECTION(FUNCTION_BODIES, 1 + EMPTY_BODY_SIZE), 1, EMPTY_BODY};
+      SIGNATURES_SECTION(1, SIG_ENTRY_v_v),                           // --
+      FUNCTION_SIGNATURES_SECTION(1, 0),                              // --
+      SECTION(FUNCTION_BODIES, 1 + SIZEOF_EMPTY_BODY), 1, EMPTY_BODY  // --
+  };
   EXPECT_VERIFIES(data);
 }
 
 TEST_F(WasmModuleVerifyTest, FunctionBodies_one_nop) {
   static const byte data[] = {
-      SIGNATURES_SECTION(1, VOID_VOID_SIG), FUNCTION_SIGNATURES_SECTION(1, 0),
-      SECTION(FUNCTION_BODIES, 1 + NOP_BODY_SIZE), 1, NOP_BODY};
+      SIGNATURES_SECTION(1, SIG_ENTRY_v_v),                       // --
+      FUNCTION_SIGNATURES_SECTION(1, 0),                          // --
+      SECTION(FUNCTION_BODIES, 1 + SIZEOF_NOP_BODY), 1, NOP_BODY  // --
+  };
   EXPECT_VERIFIES(data);
 }
 
 TEST_F(WasmModuleVerifyTest, FunctionBodies_count_mismatch1) {
-  static const byte data[] = {SIGNATURES_SECTION(1, VOID_VOID_SIG),
-                              FUNCTION_SIGNATURES_SECTION(2, 0, 0),
-                              SECTION(FUNCTION_BODIES, 1 + EMPTY_BODY_SIZE), 1,
-                              EMPTY_BODY};
+  static const byte data[] = {
+      SIGNATURES_SECTION(1, SIG_ENTRY_v_v),                // --
+      FUNCTION_SIGNATURES_SECTION(2, 0, 0),                // --
+      SECTION(FUNCTION_BODIES, 1 + SIZEOF_EMPTY_BODY), 1,  // --
+      EMPTY_BODY                                           // --
+  };
   EXPECT_FAILURE(data);
 }
 
 TEST_F(WasmModuleVerifyTest, FunctionBodies_count_mismatch2) {
-  static const byte data[] = {SIGNATURES_SECTION(1, VOID_VOID_SIG),
-                              FUNCTION_SIGNATURES_SECTION(1, 0),
-                              SECTION(FUNCTION_BODIES, 1 + 2 * NOP_BODY_SIZE),
-                              2,
-                              NOP_BODY,
-                              NOP_BODY};
+  static const byte data[] = {
+      SIGNATURES_SECTION(1, SIG_ENTRY_v_v),               // --
+      FUNCTION_SIGNATURES_SECTION(1, 0),                  // --
+      SECTION(FUNCTION_BODIES, 1 + 2 * SIZEOF_NOP_BODY),  // --
+      2,                                                  // --
+      NOP_BODY,                                           // --
+      NOP_BODY                                            // --
+  };
   EXPECT_FAILURE(data);
 }
 
@@ -1343,9 +1175,9 @@
 
 TEST_F(WasmModuleVerifyTest, Names_one_empty) {
   static const byte data[] = {
-      SIGNATURES_SECTION(1, VOID_VOID_SIG),  // --
+      SIGNATURES_SECTION(1, SIG_ENTRY_v_v),  // --
       FUNCTION_SIGNATURES_SECTION(1, 0),     // --
-      SECTION(FUNCTION_BODIES, 1 + EMPTY_BODY_SIZE),
+      SECTION(FUNCTION_BODIES, 1 + SIZEOF_EMPTY_BODY),
       1,
       EMPTY_BODY,  // --
       SECTION(NAMES, 1 + 5),
@@ -1358,9 +1190,9 @@
 
 TEST_F(WasmModuleVerifyTest, Names_two_empty) {
   static const byte data[] = {
-      SIGNATURES_SECTION(1, VOID_VOID_SIG),               // --
-      FUNCTION_SIGNATURES_SECTION(2, 0, 0),               // --
-      SECTION(FUNCTION_BODIES, 1 + 2 * EMPTY_BODY_SIZE),  // --
+      SIGNATURES_SECTION(1, SIG_ENTRY_v_v),                 // --
+      FUNCTION_SIGNATURES_SECTION(2, 0, 0),                 // --
+      SECTION(FUNCTION_BODIES, 1 + 2 * SIZEOF_EMPTY_BODY),  // --
       2,
       EMPTY_BODY,
       EMPTY_BODY,  // --
diff --git a/test/unittests/wasm/switch-logic-unittest.cc b/test/unittests/wasm/switch-logic-unittest.cc
new file mode 100644
index 0000000..be587c2
--- /dev/null
+++ b/test/unittests/wasm/switch-logic-unittest.cc
@@ -0,0 +1,89 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/wasm/switch-logic.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+class SwitchLogicTest : public TestWithZone {};
+
+void CheckNodeValues(CaseNode* node, int begin, int end) {
+  CHECK_EQ(node->begin, begin);
+  CHECK_EQ(node->end, end);
+}
+
+TEST_F(SwitchLogicTest, Single_Table_Test) {
+  ZoneVector<int> values(zone());
+  values.push_back(14);
+  values.push_back(12);
+  values.push_back(15);
+  values.push_back(19);
+  values.push_back(18);
+  values.push_back(16);
+  CaseNode* root = OrderCases(&values, zone());
+  CHECK_NULL(root->left);
+  CHECK_NULL(root->right);
+  CheckNodeValues(root, 12, 19);
+}
+
+TEST_F(SwitchLogicTest, Balanced_Tree_Test) {
+  ZoneVector<int> values(zone());
+  values.push_back(5);
+  values.push_back(1);
+  values.push_back(6);
+  values.push_back(9);
+  values.push_back(-4);
+  CaseNode* root = OrderCases(&values, zone());
+  CheckNodeValues(root, 5, 5);
+  CheckNodeValues(root->left, -4, -4);
+  CHECK_NULL(root->left->left);
+  CheckNodeValues(root->left->right, 1, 1);
+  CHECK_NULL(root->left->right->left);
+  CHECK_NULL(root->left->right->right);
+  CheckNodeValues(root->right, 6, 6);
+  CHECK_NULL(root->right->left);
+  CheckNodeValues(root->right->right, 9, 9);
+  CHECK_NULL(root->right->right->left);
+  CHECK_NULL(root->right->right->right);
+}
+
+TEST_F(SwitchLogicTest, Hybrid_Test) {
+  ZoneVector<int> values(zone());
+  values.push_back(1);
+  values.push_back(2);
+  values.push_back(3);
+  values.push_back(4);
+  values.push_back(7);
+  values.push_back(10);
+  values.push_back(11);
+  values.push_back(12);
+  values.push_back(13);
+  values.push_back(16);
+  CaseNode* root = OrderCases(&values, zone());
+  CheckNodeValues(root, 7, 7);
+  CheckNodeValues(root->left, 1, 4);
+  CheckNodeValues(root->right, 10, 13);
+  CheckNodeValues(root->right->right, 16, 16);
+}
+
+TEST_F(SwitchLogicTest, Single_Case) {
+  ZoneVector<int> values(zone());
+  values.push_back(3);
+  CaseNode* root = OrderCases(&values, zone());
+  CheckNodeValues(root, 3, 3);
+  CHECK_NULL(root->left);
+  CHECK_NULL(root->right);
+}
+
+TEST_F(SwitchLogicTest, Empty_Case) {
+  ZoneVector<int> values(zone());
+  CaseNode* root = OrderCases(&values, zone());
+  CHECK_NULL(root);
+}
+
+}  // namespace wasm
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/wasm/wasm-macro-gen-unittest.cc b/test/unittests/wasm/wasm-macro-gen-unittest.cc
index ec188c0..1058993 100644
--- a/test/unittests/wasm/wasm-macro-gen-unittest.cc
+++ b/test/unittests/wasm/wasm-macro-gen-unittest.cc
@@ -18,7 +18,6 @@
     EXPECT_EQ(size, sizeof(code)); \
   } while (false)
 
-
 TEST_F(WasmMacroGenTest, Constants) {
   EXPECT_SIZE(2, WASM_ONE);
   EXPECT_SIZE(2, WASM_ZERO);
@@ -48,7 +47,6 @@
   EXPECT_SIZE(9, WASM_F64(-9818934.0));
 }
 
-
 TEST_F(WasmMacroGenTest, Statements) {
   EXPECT_SIZE(1, WASM_NOP);
 
@@ -58,9 +56,9 @@
 
   EXPECT_SIZE(7, WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO, WASM_ZERO));
 
-  EXPECT_SIZE(4, WASM_IF(WASM_ZERO, WASM_NOP));
+  EXPECT_SIZE(5, WASM_IF(WASM_ZERO, WASM_NOP));
 
-  EXPECT_SIZE(5, WASM_IF_ELSE(WASM_ZERO, WASM_NOP, WASM_NOP));
+  EXPECT_SIZE(7, WASM_IF_ELSE(WASM_ZERO, WASM_NOP, WASM_NOP));
 
   EXPECT_SIZE(5, WASM_SELECT(WASM_ZERO, WASM_NOP, WASM_NOP));
 
@@ -79,16 +77,14 @@
   EXPECT_SIZE(5, WASM_LOOP(1, WASM_BR(0)));
   EXPECT_SIZE(7, WASM_LOOP(1, WASM_BR_IF(0, WASM_ZERO)));
 
-  EXPECT_SIZE(1, WASM_RETURN0);
-  EXPECT_SIZE(3, WASM_RETURN(WASM_ZERO));
-  EXPECT_SIZE(5, WASM_RETURN(WASM_ZERO, WASM_ZERO));
+  EXPECT_SIZE(2, WASM_RETURN0);
+  EXPECT_SIZE(4, WASM_RETURN1(WASM_ZERO));
 
   EXPECT_SIZE(1, WASM_UNREACHABLE);
 }
 
-
 TEST_F(WasmMacroGenTest, MacroStatements) {
-  EXPECT_SIZE(8, WASM_WHILE(WASM_I8(0), WASM_NOP));
+  EXPECT_SIZE(10, WASM_WHILE(WASM_I8(0), WASM_NOP));
   EXPECT_SIZE(7, WASM_INC_LOCAL(0));
   EXPECT_SIZE(7, WASM_INC_LOCAL_BY(0, 3));
 
@@ -97,10 +93,10 @@
 }
 
 TEST_F(WasmMacroGenTest, BrTable) {
-  EXPECT_SIZE(8, WASM_BR_TABLE(WASM_ZERO, 1, BR_TARGET(1)));
+  EXPECT_SIZE(9, WASM_BR_TABLE(WASM_ZERO, 1, BR_TARGET(1)));
+  EXPECT_SIZE(11, WASM_BR_TABLEV(WASM_ZERO, WASM_ZERO, 1, BR_TARGET(1)));
 }
 
-
 TEST_F(WasmMacroGenTest, Expressions) {
   EXPECT_SIZE(2, WASM_GET_LOCAL(0));
   EXPECT_SIZE(2, WASM_GET_LOCAL(1));
@@ -114,8 +110,8 @@
 
   EXPECT_SIZE(3, WASM_NOT(WASM_ZERO));
 
-  EXPECT_SIZE(4, WASM_BRV(1, WASM_ZERO));
-  EXPECT_SIZE(6, WASM_BRV_IF(1, WASM_ZERO, WASM_ZERO));
+  EXPECT_SIZE(5, WASM_BRV(1, WASM_ZERO));
+  EXPECT_SIZE(7, WASM_BRV_IF(1, WASM_ZERO, WASM_ZERO));
 
   EXPECT_SIZE(4, WASM_BLOCK(1, WASM_ZERO));
   EXPECT_SIZE(5, WASM_BLOCK(2, WASM_NOP, WASM_ZERO));
@@ -127,33 +123,32 @@
 }
 
 TEST_F(WasmMacroGenTest, CallFunction) {
-  EXPECT_SIZE(2, WASM_CALL_FUNCTION0(0));
-  EXPECT_SIZE(2, WASM_CALL_FUNCTION0(1));
-  EXPECT_SIZE(2, WASM_CALL_FUNCTION0(11));
+  EXPECT_SIZE(3, WASM_CALL_FUNCTION0(0));
+  EXPECT_SIZE(3, WASM_CALL_FUNCTION0(1));
+  EXPECT_SIZE(3, WASM_CALL_FUNCTION0(11));
 
-  EXPECT_SIZE(4, WASM_CALL_FUNCTION(0, WASM_ZERO));
-  EXPECT_SIZE(6, WASM_CALL_FUNCTION(1, WASM_ZERO, WASM_ZERO));
+  EXPECT_SIZE(5, WASM_CALL_FUNCTION1(0, WASM_ZERO));
+  EXPECT_SIZE(7, WASM_CALL_FUNCTION2(1, WASM_ZERO, WASM_ZERO));
 }
 
 TEST_F(WasmMacroGenTest, CallImport) {
-  EXPECT_SIZE(2, WASM_CALL_IMPORT0(0));
-  EXPECT_SIZE(2, WASM_CALL_IMPORT0(1));
-  EXPECT_SIZE(2, WASM_CALL_IMPORT0(11));
+  EXPECT_SIZE(3, WASM_CALL_IMPORT0(0));
+  EXPECT_SIZE(3, WASM_CALL_IMPORT0(1));
+  EXPECT_SIZE(3, WASM_CALL_IMPORT0(11));
 
-  EXPECT_SIZE(4, WASM_CALL_IMPORT(0, WASM_ZERO));
-  EXPECT_SIZE(6, WASM_CALL_IMPORT(1, WASM_ZERO, WASM_ZERO));
+  EXPECT_SIZE(5, WASM_CALL_IMPORT1(0, WASM_ZERO));
+  EXPECT_SIZE(7, WASM_CALL_IMPORT2(1, WASM_ZERO, WASM_ZERO));
 }
 
 TEST_F(WasmMacroGenTest, CallIndirect) {
-  EXPECT_SIZE(4, WASM_CALL_INDIRECT0(0, WASM_ZERO));
-  EXPECT_SIZE(4, WASM_CALL_INDIRECT0(1, WASM_ZERO));
-  EXPECT_SIZE(4, WASM_CALL_INDIRECT0(11, WASM_ZERO));
+  EXPECT_SIZE(5, WASM_CALL_INDIRECT0(0, WASM_ZERO));
+  EXPECT_SIZE(5, WASM_CALL_INDIRECT0(1, WASM_ZERO));
+  EXPECT_SIZE(5, WASM_CALL_INDIRECT0(11, WASM_ZERO));
 
-  EXPECT_SIZE(6, WASM_CALL_INDIRECT(0, WASM_ZERO, WASM_ZERO));
-  EXPECT_SIZE(8, WASM_CALL_INDIRECT(1, WASM_ZERO, WASM_ZERO, WASM_ZERO));
+  EXPECT_SIZE(7, WASM_CALL_INDIRECT1(0, WASM_ZERO, WASM_ZERO));
+  EXPECT_SIZE(9, WASM_CALL_INDIRECT2(1, WASM_ZERO, WASM_ZERO, WASM_ZERO));
 }
 
-
 TEST_F(WasmMacroGenTest, Int32Ops) {
   EXPECT_SIZE(5, WASM_I32_ADD(WASM_ZERO, WASM_ZERO));
   EXPECT_SIZE(5, WASM_I32_SUB(WASM_ZERO, WASM_ZERO));
@@ -189,7 +184,6 @@
   EXPECT_SIZE(3, WASM_I32_EQZ(WASM_ZERO));
 }
 
-
 TEST_F(WasmMacroGenTest, Int64Ops) {
   EXPECT_SIZE(5, WASM_I64_ADD(WASM_ZERO, WASM_ZERO));
   EXPECT_SIZE(5, WASM_I64_SUB(WASM_ZERO, WASM_ZERO));
@@ -225,7 +219,6 @@
   EXPECT_SIZE(3, WASM_I64_EQZ(WASM_ZERO));
 }
 
-
 TEST_F(WasmMacroGenTest, Float32Ops) {
   EXPECT_SIZE(5, WASM_F32_ADD(WASM_ZERO, WASM_ZERO));
   EXPECT_SIZE(5, WASM_F32_SUB(WASM_ZERO, WASM_ZERO));
@@ -250,7 +243,6 @@
   EXPECT_SIZE(5, WASM_F32_GE(WASM_ZERO, WASM_ZERO));
 }
 
-
 TEST_F(WasmMacroGenTest, Float64Ops) {
   EXPECT_SIZE(5, WASM_F64_ADD(WASM_ZERO, WASM_ZERO));
   EXPECT_SIZE(5, WASM_F64_SUB(WASM_ZERO, WASM_ZERO));
@@ -275,7 +267,6 @@
   EXPECT_SIZE(5, WASM_F64_GE(WASM_ZERO, WASM_ZERO));
 }
 
-
 TEST_F(WasmMacroGenTest, Conversions) {
   EXPECT_SIZE(3, WASM_I32_SCONVERT_F32(WASM_ZERO));
   EXPECT_SIZE(3, WASM_I32_SCONVERT_F64(WASM_ZERO));
@@ -317,7 +308,6 @@
   }
 }
 
-
 TEST_F(WasmMacroGenTest, LoadsAndStoresWithOffset) {
   for (size_t i = 0; i < arraysize(kMemTypes); i++) {
     EXPECT_SIZE(5, WASM_LOAD_MEM_OFFSET(kMemTypes[i], 11, WASM_ZERO));
diff --git a/test/webkit/class-constructor-return.js b/test/webkit/class-constructor-return.js
index 6eb72ad..3691928 100644
--- a/test/webkit/class-constructor-return.js
+++ b/test/webkit/class-constructor-return.js
@@ -21,8 +21,6 @@
 // (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-sloppy
-
 description('Tests for ES6 class constructor return values');
 
 // ES6
diff --git a/test/webkit/class-syntax-call.js b/test/webkit/class-syntax-call.js
index fa32a8c..747b0eb 100644
--- a/test/webkit/class-syntax-call.js
+++ b/test/webkit/class-syntax-call.js
@@ -21,8 +21,6 @@
 // (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-sloppy
-
 description('Tests for calling the constructors of ES6 classes');
 
 class A { constructor() {} };
diff --git a/test/webkit/class-syntax-declaration.js b/test/webkit/class-syntax-declaration.js
index 3c9aed7..775a335 100644
--- a/test/webkit/class-syntax-declaration.js
+++ b/test/webkit/class-syntax-declaration.js
@@ -21,8 +21,6 @@
 // (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-sloppy
-
 description('Tests for ES6 class syntax declarations');
 
 var constructorCallCount = 0;
diff --git a/test/webkit/class-syntax-default-constructor.js b/test/webkit/class-syntax-default-constructor.js
index 1695f6a..2772108 100644
--- a/test/webkit/class-syntax-default-constructor.js
+++ b/test/webkit/class-syntax-default-constructor.js
@@ -21,8 +21,6 @@
 // (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-sloppy
-
 description('Tests for ES6 class syntax default constructor');
 
 class A { };
diff --git a/test/webkit/class-syntax-expression.js b/test/webkit/class-syntax-expression.js
index 3272b81..ab6dc0e 100644
--- a/test/webkit/class-syntax-expression.js
+++ b/test/webkit/class-syntax-expression.js
@@ -21,8 +21,6 @@
 // (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-sloppy
-
 description('Tests for ES6 class syntax expressions');
 
 var constructorCallCount = 0;
diff --git a/test/webkit/class-syntax-extends-expected.txt b/test/webkit/class-syntax-extends-expected.txt
index 45e999d..5d0dca7 100644
--- a/test/webkit/class-syntax-extends-expected.txt
+++ b/test/webkit/class-syntax-extends-expected.txt
@@ -23,8 +23,8 @@
 PASS Object.getPrototypeOf(x.prototype) is Base.prototype
 PASS x = class extends null { constructor() { } }; x.__proto__ is Function.prototype
 PASS x.__proto__ is Function.prototype
-PASS x = class extends 3 { constructor() { } }; x.__proto__ threw exception TypeError: Class extends value 3 is not a function or null.
-PASS x = class extends "abc" { constructor() { } }; x.__proto__ threw exception TypeError: Class extends value abc is not a function or null.
+PASS x = class extends 3 { constructor() { } }; x.__proto__ threw exception TypeError: Class extends value 3 is not a constructor or null.
+PASS x = class extends "abc" { constructor() { } }; x.__proto__ threw exception TypeError: Class extends value abc is not a constructor or null.
 PASS baseWithBadPrototype = function () {}; baseWithBadPrototype.prototype = 3; new baseWithBadPrototype did not throw exception.
 PASS x = class extends baseWithBadPrototype { constructor() { } } threw exception TypeError: Class extends value does not have valid prototype property 3.
 PASS baseWithBadPrototype.prototype = "abc" did not throw exception.
@@ -32,8 +32,8 @@
 PASS baseWithBadPrototype.prototype = null; x = class extends baseWithBadPrototype { constructor() { } } did not throw exception.
 PASS x = 1; c = class extends ++x { constructor() { } }; threw exception SyntaxError: Unexpected token ++.
 PASS x = 1; c = class extends x++ { constructor() { } }; threw exception SyntaxError: Unexpected token ++.
-PASS x = 1; c = class extends (++x) { constructor() { } }; threw exception TypeError: Class extends value 2 is not a function or null.
-PASS x = 1; c = class extends (x++) { constructor() { } }; threw exception TypeError: Class extends value 1 is not a function or null.
+PASS x = 1; c = class extends (++x) { constructor() { } }; threw exception TypeError: Class extends value 2 is not a constructor or null.
+PASS x = 1; c = class extends (x++) { constructor() { } }; threw exception TypeError: Class extends value 1 is not a constructor or null.
 PASS x = 1; try { c = class extends (++x) { constructor() { } } } catch (e) { }; x is 2
 PASS x = 1; try { c = class extends (x++) { constructor() { } } } catch (e) { }; x is 2
 PASS namespace = {}; namespace.A = class { }; namespace.B = class extends namespace.A { } did not throw exception.
@@ -47,17 +47,17 @@
 PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (false||null||namespace.A) { constructor() { } } did not throw exception.
 PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends false||null||namespace.A { constructor() { } } threw exception SyntaxError: Unexpected token ||.
 PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (x++, namespace.A) { constructor() { } }; did not throw exception.
-PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (namespace.A, x++) { constructor() { } }; threw exception TypeError: Class extends value 1 is not a function or null.
-PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A { constructor() { } } threw exception TypeError: Class extends value [object Object] is not a function or null.
-PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A() { constructor() { } } threw exception TypeError: Class extends value [object Object] is not a function or null.
+PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends (namespace.A, x++) { constructor() { } }; threw exception TypeError: Class extends value 1 is not a constructor or null.
+PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A { constructor() { } } threw exception TypeError: Class extends value [object Object] is not a constructor or null.
+PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A() { constructor() { } } threw exception TypeError: Class extends value [object Object] is not a constructor or null.
 PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; try { namespace.B = class extends (x++, namespace.A) { constructor() { } } } catch (e) { } x is 2
 PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; try { namespace.B = class extends (namespace.A, x++) { constructor() { } } } catch (e) { } x is 2
 PASS Object.getPrototypeOf((class { constructor () { } }).prototype) is Object.prototype
 PASS Object.getPrototypeOf((class extends null { constructor () { super(); } }).prototype) is null
-PASS new (class extends undefined { constructor () { this } }) threw exception TypeError: Class extends value undefined is not a function or null.
-PASS new (class extends undefined { constructor () { super(); } }) threw exception TypeError: Class extends value undefined is not a function or null.
-PASS x = {}; new (class extends undefined { constructor () { return x; } }) threw exception TypeError: Class extends value undefined is not a function or null.
-PASS y = 12; new (class extends undefined { constructor () { return y; } }) threw exception TypeError: Class extends value undefined is not a function or null.
+PASS new (class extends undefined { constructor () { this } }) threw exception TypeError: Class extends value undefined is not a constructor or null.
+PASS new (class extends undefined { constructor () { super(); } }) threw exception TypeError: Class extends value undefined is not a constructor or null.
+PASS x = {}; new (class extends undefined { constructor () { return x; } }) threw exception TypeError: Class extends value undefined is not a constructor or null.
+PASS y = 12; new (class extends undefined { constructor () { return y; } }) threw exception TypeError: Class extends value undefined is not a constructor or null.
 PASS class x {}; new (class extends null { constructor () { return new x; } }) instanceof x is true
 PASS new (class extends null { constructor () { this; } }) threw exception ReferenceError: this is not defined.
 PASS new (class extends null { constructor () { super(); } }) threw exception TypeError: super is not a constructor.
diff --git a/test/webkit/class-syntax-extends.js b/test/webkit/class-syntax-extends.js
index a1b8f12..d505bf8 100644
--- a/test/webkit/class-syntax-extends.js
+++ b/test/webkit/class-syntax-extends.js
@@ -21,8 +21,6 @@
 // (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-sloppy
-
 description('Tests for ES6 class syntax "extends"');
 
 class Base {
@@ -60,8 +58,8 @@
 shouldBe('Object.getPrototypeOf(x.prototype)', 'Base.prototype');
 shouldBe('x = class extends null { constructor() { } }; x.__proto__', 'Function.prototype');
 shouldBe('x.__proto__', 'Function.prototype');
-shouldThrow('x = class extends 3 { constructor() { } }; x.__proto__', '"TypeError: Class extends value 3 is not a function or null"');
-shouldThrow('x = class extends "abc" { constructor() { } }; x.__proto__', '"TypeError: Class extends value abc is not a function or null"');
+shouldThrow('x = class extends 3 { constructor() { } }; x.__proto__', '"TypeError: Class extends value 3 is not a constructor or null"');
+shouldThrow('x = class extends "abc" { constructor() { } }; x.__proto__', '"TypeError: Class extends value abc is not a constructor or null"');
 shouldNotThrow('baseWithBadPrototype = function () {}; baseWithBadPrototype.prototype = 3; new baseWithBadPrototype');
 shouldThrow('x = class extends baseWithBadPrototype { constructor() { } }', '"TypeError: Class extends value does not have valid prototype property 3"');
 shouldNotThrow('baseWithBadPrototype.prototype = "abc"');
@@ -94,10 +92,10 @@
 
 shouldBe('Object.getPrototypeOf((class { constructor () { } }).prototype)', 'Object.prototype');
 shouldBe('Object.getPrototypeOf((class extends null { constructor () { super(); } }).prototype)', 'null');
-shouldThrow('new (class extends undefined { constructor () { this } })', '"TypeError: Class extends value undefined is not a function or null"');
-shouldThrow('new (class extends undefined { constructor () { super(); } })', '"TypeError: Class extends value undefined is not a function or null"');
-shouldThrow('x = {}; new (class extends undefined { constructor () { return x; } })', '"TypeError: Class extends value undefined is not a function or null"');
-shouldThrow('y = 12; new (class extends undefined { constructor () { return y; } })', '"TypeError: Class extends value undefined is not a function or null"');
+shouldThrow('new (class extends undefined { constructor () { this } })', '"TypeError: Class extends value undefined is not a constructor or null"');
+shouldThrow('new (class extends undefined { constructor () { super(); } })', '"TypeError: Class extends value undefined is not a constructor or null"');
+shouldThrow('x = {}; new (class extends undefined { constructor () { return x; } })', '"TypeError: Class extends value undefined is not a constructor or null"');
+shouldThrow('y = 12; new (class extends undefined { constructor () { return y; } })', '"TypeError: Class extends value undefined is not a constructor or null"');
 shouldBeTrue ('class x {}; new (class extends null { constructor () { return new x; } }) instanceof x');
 shouldThrow('new (class extends null { constructor () { this; } })', '"ReferenceError: this is not defined"');
 shouldThrow('new (class extends null { constructor () { super(); } })', '"TypeError: super is not a constructor"');
diff --git a/test/webkit/class-syntax-name.js b/test/webkit/class-syntax-name.js
index 1604565..7686f6c 100644
--- a/test/webkit/class-syntax-name.js
+++ b/test/webkit/class-syntax-name.js
@@ -21,8 +21,6 @@
 // (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-sloppy
-
 description('Tests for ES6 class name semantics in class statements and expressions');
 
 function runTestShouldBe(statement, result) {
diff --git a/test/webkit/class-syntax-prototype.js b/test/webkit/class-syntax-prototype.js
index 02ec578..6f0b40c 100644
--- a/test/webkit/class-syntax-prototype.js
+++ b/test/webkit/class-syntax-prototype.js
@@ -21,8 +21,6 @@
 // (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-sloppy
-
 description('Tests for the descriptors of the properties implicitly defined by ES6 class syntax');
 
 function descriptor(object, propertyName) {
diff --git a/test/webkit/class-syntax-scoping.js b/test/webkit/class-syntax-scoping.js
index 02f5a1e..7c23634 100644
--- a/test/webkit/class-syntax-scoping.js
+++ b/test/webkit/class-syntax-scoping.js
@@ -21,8 +21,6 @@
 // (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-sloppy
-
 description('Tests for scoping of variables in ES6 class syntax');
 
 var local = "FAIL";
diff --git a/test/webkit/class-syntax-semicolon.js b/test/webkit/class-syntax-semicolon.js
index 33504f9..d4a0d9b 100644
--- a/test/webkit/class-syntax-semicolon.js
+++ b/test/webkit/class-syntax-semicolon.js
@@ -21,8 +21,6 @@
 // (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-sloppy
-
 description('Tests for ES6 class syntax containing semicolon in the class body');
 
 shouldThrow("class A { foo;() { } }", "'SyntaxError: Unexpected token ;'");
diff --git a/test/webkit/class-syntax-super.js b/test/webkit/class-syntax-super.js
index e355b4b..d70f2a1 100644
--- a/test/webkit/class-syntax-super.js
+++ b/test/webkit/class-syntax-super.js
@@ -21,8 +21,6 @@
 // (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-sloppy
-
 description('Tests for ES6 class syntax "super"');
 
 var baseMethodValue = {};
diff --git a/test/webkit/exception-for-nonobject.js b/test/webkit/exception-for-nonobject.js
index f54915e..d39c3e0 100644
--- a/test/webkit/exception-for-nonobject.js
+++ b/test/webkit/exception-for-nonobject.js
@@ -21,8 +21,6 @@
 // (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-instanceof
-
 description("Test for correct handling of exceptions from instanceof and 'new' expressions");
 
 shouldThrow("new {}.undefined");
diff --git a/test/webkit/fast/js/excessive-comma-usage.js b/test/webkit/fast/js/excessive-comma-usage.js
index 414b29b..a67a3ff 100644
--- a/test/webkit/fast/js/excessive-comma-usage.js
+++ b/test/webkit/fast/js/excessive-comma-usage.js
@@ -34,7 +34,7 @@
 declarationTestString += ";return true;";
 
 var commaExpressionTestString = "1";
-for (var i = 0; i < 5000; i++)
+for (var i = 0; i < 2500; i++)
     commaExpressionTestString += ",1";
 commaExpressionTestString += ";return true;";
 
diff --git a/test/webkit/fast/regex/lastIndex-expected.txt b/test/webkit/fast/regex/lastIndex-expected.txt
index 71292c7..1e0959c 100644
--- a/test/webkit/fast/regex/lastIndex-expected.txt
+++ b/test/webkit/fast/regex/lastIndex-expected.txt
@@ -42,10 +42,10 @@
 PASS Object.defineProperty(Object.defineProperty(/x/, 'lastIndex', {writable:false}), 'lastIndex', {writable:true}); true threw exception TypeError: Cannot redefine property: lastIndex.
 PASS Object.defineProperty(Object.defineProperty(/x/, 'lastIndex', {writable:false}), 'lastIndex', {value:42}); true threw exception TypeError: Cannot redefine property: lastIndex.
 PASS Object.defineProperty(Object.defineProperty(/x/, 'lastIndex', {writable:false}), 'lastIndex', {value:0}); true is true
-FAIL Object.defineProperty(/x/, 'lastIndex', {writable:false}).exec('') should be null. Threw exception TypeError: Cannot assign to read only property 'lastIndex' of object '[object RegExp]'
+PASS Object.defineProperty(/x/, 'lastIndex', {writable:false}).exec('') is null
 PASS Object.defineProperty(/x/, 'lastIndex', {writable:false}).exec('x') is ["x"]
-PASS Object.defineProperty(/x/g, 'lastIndex', {writable:false}).exec('') threw exception TypeError: Cannot assign to read only property 'lastIndex' of object '[object RegExp]'.
-PASS Object.defineProperty(/x/g, 'lastIndex', {writable:false}).exec('x') threw exception TypeError: Cannot assign to read only property 'lastIndex' of object '[object RegExp]'.
+FAIL Object.defineProperty(/x/g, 'lastIndex', {writable:false}).exec('') should throw an exception. Was null.
+FAIL Object.defineProperty(/x/g, 'lastIndex', {writable:false}).exec('x') should throw an exception. Was x.
 PASS var re = /x/; Object.freeze(re); Object.isFrozen(re); is true
 PASS successfullyParsed is true
 
diff --git a/test/webkit/function-declaration-statement.js b/test/webkit/function-declaration-statement.js
index 34e3fdd..2c866d5 100644
--- a/test/webkit/function-declaration-statement.js
+++ b/test/webkit/function-declaration-statement.js
@@ -147,7 +147,7 @@
 function forInVarInitTest()
 {
     var a;
-    for (var a = false in { field: false })
+    for (var a in { field: false })
         function f()
         {
             return true;
diff --git a/test/webkit/instance-of-immediates.js b/test/webkit/instance-of-immediates.js
index be63e4b..649a29f 100644
--- a/test/webkit/instance-of-immediates.js
+++ b/test/webkit/instance-of-immediates.js
@@ -21,8 +21,6 @@
 // (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-instanceof
-
 description('This test makes sure that instance of behaves correctly when the value, constructor, or its prototype are immediates.');
 
 // A Constructor to use check for instances of, and an instance called obj.
diff --git a/test/webkit/run-json-stringify-expected.txt b/test/webkit/run-json-stringify-expected.txt
index 2cd7852..bbd9f28 100644
--- a/test/webkit/run-json-stringify-expected.txt
+++ b/test/webkit/run-json-stringify-expected.txt
@@ -83,7 +83,7 @@
 function (jsonObject){
         return jsonObject.stringify({toJSON: Date.prototype.toJSON});
     }
-PASS tests[i](nativeJSON) threw exception TypeError: (var).toISOString is not a function.
+PASS tests[i](nativeJSON) threw exception TypeError: toISOString is not a function.
 function (jsonObject){
         return jsonObject.stringify({toJSON: Date.prototype.toJSON, toISOString: function(){ return "custom toISOString"; }});
     }
@@ -101,7 +101,7 @@
         d.toISOString = null;
         return jsonObject.stringify(d);
     }
-PASS tests[i](nativeJSON) threw exception TypeError: (var).toISOString is not a function.
+PASS tests[i](nativeJSON) threw exception TypeError: toISOString is not a function.
 function (jsonObject){
         var d = new Date(0);
         d.toJSON = undefined;
diff --git a/test/webkit/toString-for-var-decl.js b/test/webkit/toString-for-var-decl.js
index 2b4db73..ba30883 100644
--- a/test/webkit/toString-for-var-decl.js
+++ b/test/webkit/toString-for-var-decl.js
@@ -25,7 +25,7 @@
 "This test checks for a couple of specific ways that bugs in toString() round trips have changed the meanings of functions with var declarations inside for loops."
 );
 
-function f1() { for (var j = 1 in []) {}  }
+function f1() { for (var j in []) {}  }
 var f2 = function () { for (var j = 1; j < 10; ++j) {}  }
 var f3 = function () { for (j = 1;j < 10; ++j) {}  }
 var f4 = function () { for (var j;;) {}  }
diff --git a/test/webkit/webkit.gyp b/test/webkit/webkit.gyp
index 8d655fe..cd4c4b9 100644
--- a/test/webkit/webkit.gyp
+++ b/test/webkit/webkit.gyp
@@ -13,8 +13,8 @@
             '../../src/d8.gyp:d8_run',
           ],
           'includes': [
-            '../../build/features.gypi',
-            '../../build/isolate.gypi',
+            '../../gypfiles/features.gypi',
+            '../../gypfiles/isolate.gypi',
           ],
           'sources': [
             'webkit.isolate',
diff --git a/test/webkit/webkit.status b/test/webkit/webkit.status
index e23b9cf..b2b0b01 100644
--- a/test/webkit/webkit.status
+++ b/test/webkit/webkit.status
@@ -70,6 +70,14 @@
   # Too slow.
   'dfg-int-overflow-in-loop': [SKIP],
 }], # 'arch == ppc or arch == ppc64'
+['arch == s390 or arch == s390x', {
+  # Too slow.
+  'dfg-int-overflow-in-loop': [SKIP],
+}],  # 'arch == s390 or arch == s390x'
+['arch == x87', {
+  # Too slow.
+  'dfg-negative-array-index': [SKIP],
+}], # 'arch == x87'
 
 ##############################################################################
 ['asan == True', {
@@ -97,17 +105,18 @@
 }],  # 'gc_stress == True and mode == debug'
 
 ##############################################################################
-['ignition == True', {
-  # TODO(4680): Throws a RangeError due to stack overflow. Need investigation.
-  'fast/js/excessive-comma-usage': [SKIP],  # Stack is brittle, SKIP not FAIL.
-}],  # ignition == True
+['msan', {
+  # TODO(mythria,4680): Too slow and timeout on ignition.
+  'dfg-double-vote-fuzz': [PASS, NO_IGNITION],
+  'dfg-int-overflow-in-loop': [PASS, NO_IGNITION],
+}],  # msan
 
 ##############################################################################
-['ignition == True and msan', {
+['(ignition or ignition_turbofan) and msan', {
   # TODO(mythria,4680): Too slow and timeout on ignition.
   'dfg-double-vote-fuzz': [SKIP],
   'dfg-int-overflow-in-loop': [SKIP],
-}],  # ignition == True and msan
+}],  # (ignition or ignition_turbofan) and msan
 
 ##############################################################################
 ['gcov_coverage', {
diff --git a/third_party/binutils/download.py b/third_party/binutils/download.py
index 44b6c65..a8ad814 100755
--- a/third_party/binutils/download.py
+++ b/third_party/binutils/download.py
@@ -23,7 +23,7 @@
 BINUTILS_OUT = 'Release'
 
 DETECT_HOST_ARCH = os.path.abspath(os.path.join(
-    BINUTILS_DIR, '../../build/detect_v8_host_arch.py'))
+    BINUTILS_DIR, '../../gypfiles/detect_v8_host_arch.py'))
 
 
 def ReadFile(filename):
diff --git a/tools/BUILD.gn b/tools/BUILD.gn
new file mode 100644
index 0000000..4f97777
--- /dev/null
+++ b/tools/BUILD.gn
@@ -0,0 +1,59 @@
+# Copyright 2016 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("../gni/isolate.gni")
+
+group("gn_all") {
+  testonly = true
+
+  if (v8_test_isolation_mode != "noop") {
+    deps = [
+      ":check-static-initializers_run",
+      ":jsfunfuzz_run",
+      ":run-deopt-fuzzer_run",
+      ":run-gcmole_run",
+      ":run-valgrind_run",
+    ]
+  }
+}
+
+v8_isolate_run("check-static-initializers") {
+  deps = [
+    "..:d8_run",
+  ]
+
+  isolate = "check-static-initializers.isolate"
+}
+
+v8_isolate_run("jsfunfuzz") {
+  deps = [
+    "..:d8_run",
+  ]
+
+  isolate = "jsfunfuzz/jsfunfuzz.isolate"
+}
+
+v8_isolate_run("run-deopt-fuzzer") {
+  deps = [
+    "..:d8_run",
+  ]
+
+  isolate = "run-deopt-fuzzer.isolate"
+}
+
+v8_isolate_run("run-gcmole") {
+  deps = [
+    "..:d8_run",
+  ]
+
+  isolate = "gcmole/run-gcmole.isolate"
+}
+
+v8_isolate_run("run-valgrind") {
+  deps = [
+    "..:d8_run",
+  ]
+
+  isolate = "run-valgrind.isolate"
+}
diff --git a/tools/callstats.html b/tools/callstats.html
new file mode 100644
index 0000000..afce194
--- /dev/null
+++ b/tools/callstats.html
@@ -0,0 +1,1806 @@
+<html>
+<!--
+Copyright 2016 the V8 project authors. All rights reserved.  Use of this source
+code is governed by a BSD-style license that can be found in the LICENSE file.
+-->
+
+<head>
+  <meta charset="UTF-8">
+  <style>
+    body {
+      font-family: arial;
+    }
+    
+    table {
+      display: table;
+      border-spacing: 0px;
+    }
+    
+    tr {
+      border-spacing: 0px;
+      padding: 10px;
+    }
+    
+    td,
+    th {
+      padding: 3px 10px 3px 5px;
+    }
+    
+    .inline {
+      display: inline-block;
+      vertical-align: top;
+    }
+    
+    h2,
+    h3 {
+      margin-bottom: 0px;
+    }
+    
+    .hidden {
+      display: none;
+    }
+    
+    .view {
+      display: table;
+    }
+    
+    .column {
+      display: table-cell;
+      border-right: 1px black dotted;
+      min-width: 200px;
+    }
+    
+    .column .header {
+      padding: 0 10px 0 10px
+    }
+    
+    #column {
+      display: none;
+    }
+   
+    .list {
+      width: 100%;
+    }
+    
+    select {
+      width: 100%
+    }
+    
+    .list tbody {
+      cursor: pointer;
+    }
+    
+    .list tr:nth-child(even) {
+      background-color: #EFEFEF;
+    }
+    
+    .list tr:nth-child(even).selected {
+      background-color: #DDD;
+    }
+    
+    .list tr.child {
+      display: none;
+    }
+    
+    .list tr.child.visible {
+      display: table-row;
+    }
+    
+    .list .child .name {
+      padding-left: 20px;
+    }
+    
+    .list .parent td {
+      border-top: 1px solid #AAA;
+    }
+    
+    .list .total {
+      font-weight: bold
+    }
+    
+    .list tr.parent {
+      background-color: #FFF;
+    }
+    
+    .list tr.parent.selected {
+      background-color: #DDD;
+    }
+    
+    tr.selected {
+      background-color: #DDD;
+    }
+    
+    .codeSearch {
+      display: block-inline;
+      float: right;
+      border-radius: 5px;
+      background-color: #EEE;
+      width: 1em;
+      text-align: center;
+    }
+    
+    .list .position {
+      text-align: right;
+      display: none;
+    }
+    
+    .list div.toggle {
+      cursor: pointer;
+    }
+    
+    #column_0 .position {
+      display: table-cell;
+    }
+    
+    #column_0 .name {
+      display: table-cell;
+    }
+    
+    .list .name {
+      display: none;
+      white-space: nowrap;
+    }
+    
+    .value {
+      text-align: right;
+    }
+    
+    .selectedVersion {
+      font-weight: bold;
+    }
+    
+    #baseline {
+      width: auto;
+    }
+    
+    .compareSelector {
+      padding-bottom: 20px;
+    }
+    
+    .pageDetailTable tbody {
+      cursor: pointer
+    }
+    
+    .pageDetailTable tfoot td {
+      border-top: 1px grey solid;
+    }
+    
+    #popover {
+      position: absolute;
+      transform: translateY(-50%) translateX(40px);
+      box-shadow: -2px 10px 44px -10px #000;
+      border-radius: 5px;
+      z-index: 1;
+      background-color: #FFF;
+      display: none;
+      white-space: nowrap;
+    }
+    
+    #popover table {
+      position: relative;
+      z-index: 1;
+      text-align: right;
+      margin: 10px;
+    }
+    #popover td {
+      padding: 3px 0px 3px 5px;
+      white-space: nowrap;
+    }
+    
+    .popoverArrow {
+      background-color: #FFF;
+      position: absolute;
+      width: 30px;
+      height: 30px;
+      transform: translateY(-50%)rotate(45deg);
+      top: 50%;
+      left: -10px;
+      z-index: 0;
+    }
+    
+    #popover .name {
+      padding: 5px;
+      font-weight: bold;
+      text-align: center;
+    }
+    
+    #popover table .compare {
+      display: none
+    }
+    
+    #popover table.compare .compare {
+      display: table-cell;
+    }
+
+    #popover .compare .time,
+    #popover .compare .version {
+      padding-left: 10px;
+    }
+    .graph,
+    .graph .content {
+      width: 100%;
+    }
+
+    .diff .hideDiff {
+      display: none;
+    }
+    .noDiff .hideNoDiff {
+      display: none;
+    }
+  </style>
+  <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
+  <script type="text/javascript">
+    "use strict"
+    google.charts.load('current', {packages: ['corechart']});
+
+    // Did anybody say monkeypatching?
+    if (!NodeList.prototype.forEach) {
+      NodeList.prototype.forEach = function(func) {
+        for (var i = 0; i < this.length; i++) {
+          func(this[i]);
+        }
+      }
+    }
+
+    var versions;
+    var pages;
+    var selectedPage;
+    var baselineVersion;
+    var selectedEntry;
+
+    function initialize() {
+      var original = $("column");
+      var view = document.createElement('div');
+      view.id = 'view';
+      var i = 0;
+      versions.forEach((version) =>  {
+        if (!version.enabled) return;
+        // add column
+        var column = original.cloneNode(true);
+        column.id = "column_" + i;
+        // Fill in all versions
+        var select = column.querySelector(".version");
+        select.id = "selectVersion_" + i;
+        // add all select options
+        versions.forEach((version) => {
+          if (!version.enabled) return;
+          var option = document.createElement("option");
+          option.textContent = version.name;
+          option.version = version;
+          select.appendChild(option);
+        });
+        // Fill in all page versions
+        select = column.querySelector(".pageVersion");
+        select.id = "select_" + i;
+        // add all pages
+        versions.forEach((version) => {
+          if (!version.enabled) return;
+          var optgroup = document.createElement("optgroup");
+          optgroup.label = version.name;
+          optgroup.version = version;
+          version.forEachPage((page) => {
+            var option = document.createElement("option");
+            option.textContent = page.name;
+            option.page = page;
+            optgroup.appendChild(option);
+          });
+          select.appendChild(optgroup);
+        });
+        view.appendChild(column);
+        i++;
+      });
+      var oldView = $('view');
+      oldView.parentNode.replaceChild(view, oldView);
+      
+      var select = $('baseline');
+      removeAllChildren(select);
+      select.appendChild(document.createElement('option'));
+      versions.forEach((version) => {
+        var option = document.createElement("option");
+        option.textContent = version.name;
+        option.version = version;
+        select.appendChild(option);
+      });
+      initializeToggleList(versions.versions, $('versionSelector'));
+      initializeToggleList(pages.values(), $('pageSelector'));
+      initializeToggleContentVisibility();
+    }
+
+    function initializeToggleList(items, node) {
+      var list = node.querySelector('ul');
+      removeAllChildren(list);
+      items = Array.from(items);
+      items.sort(NameComparator);
+      items.forEach((item) => {
+        var li = document.createElement('li');
+        var checkbox = document.createElement('input');
+        checkbox.type = 'checkbox';
+        checkbox.checked = item.enabled;
+        checkbox.item = item;
+        checkbox.addEventListener('click', handleToggleVersionEnable);
+        li.appendChild(checkbox);
+        li.appendChild(document.createTextNode(item.name));
+        list.appendChild(li);
+      });
+      $('results').querySelectorAll('#results > .hidden').forEach((node) => {
+        toggleCssClass(node, 'hidden', false);
+      })
+    }
+
+    function initializeToggleContentVisibility() {
+      var nodes = document.querySelectorAll('.toggleContentVisibility');
+      nodes.forEach((node) => {
+        var content = node.querySelector('.content');
+        var header = node.querySelector('h1,h2,h3');
+        if (content === undefined || header === undefined) return;
+        if (header.querySelector('input') != undefined) return;
+        var checkbox = document.createElement('input');
+        checkbox.type = 'checkbox';
+        checkbox.checked = content.className.indexOf('hidden') == -1;
+        checkbox.contentNode = content;
+        checkbox.addEventListener('click', handleToggleContentVisibility);
+        header.insertBefore(checkbox, header.childNodes[0]);
+      });
+    }
+
+    function showPage(firstPage) {
+      var changeSelectedEntry = selectedEntry !== undefined 
+          && selectedEntry.page === selectedPage;
+      selectedPage = firstPage;
+      selectedPage.sort();
+      showPageInColumn(firstPage, 0);
+      // Show the other versions of this page in the following columns.
+      var pageVersions = versions.getPageVersions(firstPage);
+      var index = 1;
+      pageVersions.forEach((page) => {
+        if (page !== firstPage) {
+          showPageInColumn(page, index);
+          index++;
+        }
+      });
+      if (changeSelectedEntry) {
+        showEntryDetail(selectedPage.getEntry(selectedEntry));
+      } else {
+        showImpactList(selectedPage);
+      }
+    }
+
+    function showPageInColumn(page, columnIndex) {
+      page.sort();
+      var showDiff = (baselineVersion === undefined && columnIndex !== 0) ||
+        (baselineVersion !== undefined && page.version !== baselineVersion);
+      var diffStatus = (td, a, b) => {};
+      if (showDiff) {
+        if (baselineVersion !== undefined) {
+          diffStatus = (td, a, b) => {
+            if (a == 0) return;
+            td.style.color = a < 0 ? '#FF0000' : '#00BB00';
+          };
+        } else {
+          diffStatus = (td, a, b) => {
+            if (a == b) return;
+            var color;
+            var ratio = a / b;
+            if (ratio > 1) {
+              ratio = Math.min(Math.round((ratio - 1) * 255 * 10), 200);
+              color = '#' + ratio.toString(16) + "0000";
+            } else {
+              ratio = Math.min(Math.round((1 - ratio) * 255 * 10), 200);
+              color = '#00' + ratio.toString(16) + "00";
+            }
+            td.style.color = color;
+          }
+        }
+      }
+
+      var column = $('column_' + columnIndex);
+      var select = $('select_' + columnIndex);
+      // Find the matching option
+      selectOption(select, (i, option) => {
+        return option.page == page
+      });
+      var table = column.querySelector("table");
+      var oldTbody = table.querySelector('tbody');
+      var tbody = document.createElement('tbody');
+      var referencePage = selectedPage;
+      page.forEachSorted(selectedPage, (parentEntry, entry, referenceEntry) => {
+        // Filter out entries that do not exist in the first column for the default
+        // view.
+        if (baselineVersion === undefined && referenceEntry &&
+          referenceEntry.time == 0) {
+          return;
+        }
+        var tr = document.createElement('tr');
+        tbody.appendChild(tr);
+        tr.entry = entry;
+        tr.parentEntry = parentEntry;
+        tr.className = parentEntry === undefined ? 'parent' : 'child';
+        // Don't show entries that do not exist on the current page or if we
+        // compare against the current page
+        if (entry !== undefined && page.version !== baselineVersion) {
+          // If we show a diff, use the baselineVersion as the referenceEntry
+          if (baselineVersion !== undefined) {
+            var baselineEntry = baselineVersion.getEntry(entry);
+            if (baselineEntry !== undefined) referenceEntry = baselineEntry
+          }
+          if (!parentEntry) {
+            var node = td(tr, '<div class="toggle">►</div>', 'position');
+            node.firstChild.addEventListener('click', handleToggleGroup);
+          } else {
+            td(tr, entry.position == 0 ? '' : entry.position, 'position');
+          }
+          addCodeSearchButton(entry,
+              td(tr, entry.name, 'name ' + entry.cssClass()));
+          
+          diffStatus(
+            td(tr, ms(entry.time), 'value time'),
+            entry.time, referenceEntry.time);
+          diffStatus(
+            td(tr, percent(entry.timePercent), 'value time'),
+            entry.time, referenceEntry.time);
+          diffStatus(
+            td(tr, count(entry.count), 'value count'),
+            entry.count, referenceEntry.count);
+        } else if (baselineVersion !== undefined && referenceEntry 
+            && page.version !== baselineVersion) {
+          // Show comparison of entry that does not exist on the current page.
+          tr.entry = new Entry(0, referenceEntry.name);
+          tr.entry.page = page;
+          td(tr, '-', 'position');
+          td(tr, referenceEntry.name, 'name');
+          diffStatus(
+            td(tr, ms(-referenceEntry.time), 'value time'),
+            -referenceEntry.time, 0);
+          diffStatus(
+            td(tr, percent(-referenceEntry.timePercent), 'value time'),
+            -referenceEntry.timePercent, 0);
+          diffStatus(
+            td(tr, count(-referenceEntry.count), 'value count'),
+            -referenceEntry.count, 0);
+        } else {
+          // Display empty entry / baseline entry
+          var showBaselineEntry = entry !== undefined;
+          if (showBaselineEntry) {
+            if (!parentEntry) {
+              var node = td(tr, '<div class="toggle">►</div>', 'position');
+              node.firstChild.addEventListener('click', handleToggleGroup);
+            } else {
+              td(tr, entry.position == 0 ? '' : entry.position, 'position');
+            }
+            td(tr, entry.name, 'name');
+            td(tr, ms(entry.time, false), 'value time');
+            td(tr, percent(entry.timePercent, false), 'value time');
+            td(tr, count(entry.count, false), 'value count');
+          } else {
+            td(tr, '-', 'position');
+            td(tr, '-', 'name');
+            td(tr, '-', 'value time');
+            td(tr, '-', 'value time');
+            td(tr, '-', 'value count');
+          }
+        }
+      });
+      table.replaceChild(tbody, oldTbody);
+      var versionSelect = column.querySelector('select.version');
+      selectOption(versionSelect, (index, option) => {
+        return option.version == page.version
+      });
+    }
+
+    function selectEntry(entry, updateSelectedPage) {
+      if (updateSelectedPage) {
+        entry = selectedPage.version.getEntry(entry);
+      }
+      var rowIndex = 0;
+      var needsPageSwitch = updateSelectedPage && entry.page != selectedPage;
+      // If clicked in the detail row change the first column to that page.
+      if (needsPageSwitch) showPage(entry.page);
+      var childNodes = $('column_0').querySelector('.list tbody').childNodes;
+      for (var i = 0; i < childNodes.length; i++) {
+        if (childNodes[i].entry.name == entry.name) {
+          rowIndex = i;
+          break;
+        }
+      }
+      var firstEntry = childNodes[rowIndex].entry;
+      if (rowIndex) {
+        if (firstEntry.parent) showGroup(firstEntry.parent);
+      }
+      // Deselect all
+      $('view').querySelectorAll('.list tbody tr').forEach((tr) => {
+        toggleCssClass(tr, 'selected', false);
+      });
+      // Select the entry row
+      $('view').querySelectorAll("tbody").forEach((body) => {
+        var row = body.childNodes[rowIndex];
+        if (!row) return;
+        toggleCssClass(row, 'selected', row.entry && row.entry.name ==
+          firstEntry.name);
+      });
+      if (updateSelectedPage) {
+        entry = selectedEntry.page.version.getEntry(entry);
+      }
+      selectedEntry = entry;
+      showEntryDetail(entry);
+    }
+
+    function showEntryDetail(entry) {
+      showVersionDetails(entry);
+      showPageDetails(entry);
+      showImpactList(entry.page);
+      showGraphs(entry.page);
+    }
+    
+    function showVersionDetails(entry) {
+      var table, tbody, entries;
+      table = $('detailView').querySelector('.versionDetailTable');
+      tbody = document.createElement('tbody');
+      if (entry !== undefined) {
+        $('detailView').querySelector('.versionDetail h3 span').innerHTML =
+          entry.name + ' in ' + entry.page.name;
+        entries = versions.getPageVersions(entry.page).map(
+          (page) => {
+            return page.get(entry.name)
+          });
+        entries.sort((a, b) => {
+          return a.time - b.time
+        });
+        entries.forEach((pageEntry) => {
+          if (pageEntry === undefined) return;
+          var tr = document.createElement('tr');
+          if (pageEntry == entry) tr.className += 'selected';
+          tr.entry = pageEntry;
+          var isBaselineEntry = pageEntry.page.version == baselineVersion;
+          td(tr, pageEntry.page.version.name, 'version');
+          td(tr, ms(pageEntry.time, !isBaselineEntry), 'value time');
+          td(tr, percent(pageEntry.timePercent, !isBaselineEntry), 'value time');
+          td(tr, count(pageEntry.count, !isBaselineEntry), 'value count');
+          tbody.appendChild(tr);
+        });
+      }
+      table.replaceChild(tbody, table.querySelector('tbody'));
+    }
+
+    function showPageDetails(entry) {
+      var table, tbody, entries;
+      table = $('detailView').querySelector('.pageDetailTable');
+      tbody = document.createElement('tbody');
+      if (entry === undefined) {
+        table.replaceChild(tbody, table.querySelector('tbody'));
+        return;
+      }
+      var version = entry.page.version;
+      var showDiff = version !== baselineVersion;
+      $('detailView').querySelector('.pageDetail h3 span').innerHTML =
+        version.name;
+      entries = version.pages.map((page) => {
+          if (!page.enabled) return;
+          return page.get(entry.name)
+        });
+      entries.sort((a, b) => {
+        var cmp = b.timePercent - a.timePercent;
+        if (cmp.toFixed(1) == 0) return b.time - a.time;
+        return cmp
+      });
+      entries.forEach((pageEntry) => {
+        if (pageEntry === undefined) return;
+        var tr = document.createElement('tr');
+        if (pageEntry === entry) tr.className += 'selected';
+        tr.entry = pageEntry;
+        td(tr, pageEntry.page.name, 'name');
+        td(tr, ms(pageEntry.time, showDiff), 'value time');
+        td(tr, percent(pageEntry.timePercent, showDiff), 'value time');
+        td(tr, percent(pageEntry.timePercentPerEntry, showDiff),
+            'value time hideNoDiff');
+        td(tr, count(pageEntry.count, showDiff), 'value count');
+        tbody.appendChild(tr);
+      });
+      // show the total for all pages
+      var tds = table.querySelectorAll('tfoot td');
+      tds[1].innerHTML = ms(entry.getTimeImpact(), showDiff);
+      // Only show the percentage total if we are in diff mode:
+      tds[2].innerHTML = percent(entry.getTimePercentImpact(), showDiff);
+      tds[3].innerHTML = '';
+      tds[4].innerHTML = count(entry.getCountImpact(), showDiff);
+      table.replaceChild(tbody, table.querySelector('tbody'));
+    }
+
+    function showImpactList(page) {
+      var impactView = $('detailView').querySelector('.impactView');
+      impactView.querySelector('h3 span').innerHTML = page.version.name;
+
+      var table = impactView.querySelector('table');
+      var tbody = document.createElement('tbody');
+      var version = page.version;
+      var entries = version.allEntries();
+      if (selectedEntry !== undefined && selectedEntry.isGroup) {
+        impactView.querySelector('h3 span').innerHTML += " " + selectedEntry.name;
+        entries = entries.filter((entry) => {
+          return entry.name == selectedEntry.name ||
+            (entry.parent && entry.parent.name == selectedEntry.name)
+        });
+      }
+      var isCompareView = baselineVersion !== undefined;
+      entries = entries.filter((entry) => {
+        if (isCompareView) {
+          var impact = entry.getTimeImpact();
+          return impact < -1 || 1 < impact
+        }
+        return entry.getTimePercentImpact() > 0.1;
+      });
+      entries.sort((a, b) => {
+        var cmp = b.getTimePercentImpact() - a.getTimePercentImpact(); 
+        if (isCompareView || cmp.toFixed(1) == 0) {
+          return b.getTimeImpact() - a.getTimeImpact();
+        }
+        return cmp
+      });
+      entries.forEach((entry) => {
+        var tr = document.createElement('tr');
+        tr.entry = entry;
+        td(tr, entry.name, 'name');
+        td(tr, ms(entry.getTimeImpact()), 'value time');
+        var percentImpact = entry.getTimePercentImpact();
+        td(tr, percentImpact > 1000 ? '-' : percent(percentImpact), 'value time');
+        var topPages = entry.getPagesByPercentImpact().slice(0, 3)
+          .map((each) => {
+            return each.name + ' (' + percent(each.getEntry(entry).timePercent) +
+              ')'
+          });
+        td(tr, topPages.join(', '), 'name');
+        tbody.appendChild(tr);
+      });
+      table.replaceChild(tbody, table.querySelector('tbody'));
+    }
+    
+    function showGraphs(page) {
+      var groups = page.groups.slice(); 
+      // Sort groups by the biggest impact
+      groups.sort((a, b) => {
+        return b.getTimeImpact() - a.getTimeImpact();
+      });
+      if (selectedGroup == undefined) {
+        selectedGroup = groups[0];
+      } else {
+        groups = groups.filter(each => each.name != selectedGroup.name);
+        groups.unshift(selectedGroup);
+      }
+      showPageGraph(groups, page);
+      showVersionGraph(groups, page);
+      showPageVersionGraph(groups, page);
+    }
+    
+    function getGraphDataTable(groups) {
+      var dataTable = new google.visualization.DataTable();
+      dataTable.addColumn('string', 'Name');
+      groups.forEach(group => {
+        var column = dataTable.addColumn('number', group.name.substring(6));
+        dataTable.setColumnProperty(column, 'group', group);
+      });
+      return dataTable;
+    }
+
+    var selectedGroup;
+    function showPageGraph(groups, page) {
+      var isDiffView = baselineVersion !== undefined;
+      var dataTable = getGraphDataTable(groups);
+      // Calculate the average row
+      var row = ['Average'];
+      groups.forEach((group) => {
+        if (isDiffView) {
+          row.push(group.isTotal ? 0 : group.getAverageTimeImpact());
+        } else {
+          row.push(group.isTotal ? 0 : group.getTimeImpact());
+        }
+      });
+      dataTable.addRow(row);
+      // Sort the pages by the selected group.
+      var pages = page.version.pages.filter(page => page.enabled);
+      function sumDiff(page) {
+        var sum = 0;
+        groups.forEach(group => {
+          var value = group.getTimePercentImpact() -
+            page.getEntry(group).timePercent;
+          sum += value * value;
+        });
+        return sum;
+      }
+      if (isDiffView) {
+        pages.sort((a, b) => {
+          return b.getEntry(selectedGroup).time-
+            a.getEntry(selectedGroup).time; 
+        });
+      } else {
+        pages.sort((a, b) => {
+          return b.getEntry(selectedGroup).timePercent -
+            a.getEntry(selectedGroup).timePercent; 
+        });
+      }
+      // Sort by sum of squared distance to the average.
+      // pages.sort((a, b) => {
+      //   return a.distanceFromTotalPercent() - b.distanceFromTotalPercent(); 
+      // });
+      // Calculate the entries for the pages
+      pages.forEach((page) => { 
+        row = [page.name];
+        groups.forEach((group) => {
+          row.push(group.isTotal ? 0 : page.getEntry(group).time);
+        });
+        var rowIndex = dataTable.addRow(row);
+        dataTable.setRowProperty(rowIndex, 'page', page);
+      });
+      renderGraph('Pages for ' + page.version.name, groups, dataTable,
+          'pageGraph', isDiffView ? true : 'percent');
+    }
+
+    function showVersionGraph(groups, page) {
+      var dataTable = getGraphDataTable(groups);
+      var row;
+      var vs = versions.versions.filter(version => version.enabled);
+      vs.sort((a, b) => {
+        return b.getEntry(selectedGroup).getTimeImpact() -
+          a.getEntry(selectedGroup).getTimeImpact(); 
+      });
+      // Calculate the entries for the versions 
+      vs.forEach((version) => { 
+        row = [version.name];
+        groups.forEach((group) => {
+          row.push(group.isTotal ? 0 : version.getEntry(group).getTimeImpact());
+        });
+        var rowIndex = dataTable.addRow(row);
+        dataTable.setRowProperty(rowIndex, 'page', page);
+      });
+      renderGraph('Versions Total Time over all Pages', groups, dataTable,
+          'versionGraph', true);
+    }
+
+    function showPageVersionGraph(groups, page) {
+      var dataTable = getGraphDataTable(groups);
+      var row;
+      var vs = versions.getPageVersions(page);
+      vs.sort((a, b) => {
+        return b.getEntry(selectedGroup).time - a.getEntry(selectedGroup).time; 
+      });
+      // Calculate the entries for the versions 
+      vs.forEach((page) => { 
+        row = [page.version.name];
+        groups.forEach((group) => {
+          row.push(group.isTotal ? 0 : page.getEntry(group).time);
+        });
+        var rowIndex = dataTable.addRow(row);
+        dataTable.setRowProperty(rowIndex, 'page', page);
+      });
+      renderGraph('Versions for ' + page.name, groups, dataTable,
+          'pageVersionGraph', true);
+    }
+
+    function renderGraph(title, groups, dataTable, id, isStacked) {
+      var isDiffView = baselineVersion !== undefined;
+      var formatter = new google.visualization.NumberFormat({
+        suffix: (isDiffView ? 'msΔ' : 'ms'), 
+        negativeColor: 'red', 
+        groupingSymbol: "'"
+      });
+      for (var i = 1; i < dataTable.getNumberOfColumns(); i++) {
+        formatter.format(dataTable, i);
+      }
+      var height = 85 + 28 * dataTable.getNumberOfRows();
+      var options = {
+        isStacked: isStacked,
+        height: height,
+        hAxis: {
+          minValue: 0,
+        },
+        animation:{
+          duration: 500,
+          easing: 'out',
+        },
+        vAxis: {
+        },
+        explorer: {
+          actions: ['dragToZoom', 'rightClickToReset'],
+          maxZoomIn: 0.01
+        },
+        legend: {position:'top', textStyle:{fontSize: '16px'}},
+        chartArea: {left:200, top:50, width:'98%', height:'80%'},
+        colors: groups.map(each => each.color)
+      };
+      var parentNode = $(id);
+      parentNode.querySelector('h2>span, h3>span').innerHTML = title;
+      var graphNode = parentNode.querySelector('.content');
+
+      var chart = graphNode.chart;
+      if (chart === undefined) {
+        chart = graphNode.chart = new google.visualization.BarChart(graphNode);
+      } else {
+        google.visualization.events.removeAllListeners(chart);
+      }
+      google.visualization.events.addListener(chart, 'select', selectHandler);
+      function getChartEntry(selection) {
+        if (!selection) return undefined;
+        var column = selection.column;
+        if (column == undefined) return undefined;
+        var selectedGroup = dataTable.getColumnProperty(column, 'group');
+        var row = selection.row;
+        if (row == null) return selectedGroup;
+        var page = dataTable.getRowProperty(row, 'page');
+        if (!page) return selectedGroup;
+        return page.getEntry(selectedGroup);
+      }
+      function selectHandler() {
+        selectedGroup = getChartEntry(chart.getSelection()[0])
+        if (!selectedGroup) return;
+        selectEntry(selectedGroup, true);
+      }
+
+      // Make our global tooltips work
+      google.visualization.events.addListener(chart, 'onmouseover', mouseOverHandler);
+      function mouseOverHandler(selection) {
+        graphNode.entry = getChartEntry(selection);
+      }
+      chart.draw(dataTable, options);
+    }
+
+    function showGroup(entry) {
+      toggleGroup(entry, true);
+    }
+
+    function toggleGroup(group, show) {
+      $('view').querySelectorAll(".child").forEach((tr) => {
+        var entry = tr.parentEntry;
+        if (!entry) return;
+        if (entry.name !== group.name) return;
+        toggleCssClass(tr, 'visible', show);
+      });
+    }
+
+    function showPopover(entry) {
+      var popover = $('popover');
+      popover.querySelector('td.name').innerHTML = entry.name;
+      popover.querySelector('td.page').innerHTML = entry.page.name;
+      setPopoverDetail(popover, entry, '');
+      popover.querySelector('table').className = "";
+      if (baselineVersion !== undefined) {
+        entry = baselineVersion.getEntry(entry);
+        setPopoverDetail(popover, entry, '.compare');
+        popover.querySelector('table').className = "compare";
+      }
+    }
+
+    function setPopoverDetail(popover, entry, prefix) {
+      var node = (name) => popover.querySelector(prefix + name);
+      if (entry == undefined) {
+        node('.version').innerHTML = baselineVersion.name;
+        node('.time').innerHTML = '-';
+        node('.timeVariance').innerHTML = '-';
+        node('.percent').innerHTML = '-';
+        node('.percentPerEntry').innerHTML = '-';
+        node('.percentVariance').innerHTML  = '-';
+        node('.count').innerHTML =  '-';
+        node('.countVariance').innerHTML = '-';
+        node('.timeImpact').innerHTML = '-';
+        node('.timePercentImpact').innerHTML = '-';
+      } else {
+        node('.version').innerHTML = entry.page.version.name;
+        node('.time').innerHTML = ms(entry._time, false);
+        node('.timeVariance').innerHTML
+            = percent(entry.timeVariancePercent, false);
+        node('.percent').innerHTML = percent(entry.timePercent, false);
+        node('.percentPerEntry').innerHTML
+            = percent(entry.timePercentPerEntry, false);
+        node('.percentVariance').innerHTML 
+            = percent(entry.timePercentVariancePercent, false);
+        node('.count').innerHTML = count(entry._count, false);
+        node('.countVariance').innerHTML
+            = percent(entry.timeVariancePercent, false);
+        node('.timeImpact').innerHTML
+            = ms(entry.getTimeImpact(false), false);
+        node('.timePercentImpact').innerHTML
+            = percent(entry.getTimeImpactVariancePercent(false), false);
+      }
+    }
+  </script>
+  <script type="text/javascript">
+  "use strict"
+    // =========================================================================
+    // Helpers
+    function $(id) {
+      return document.getElementById(id)
+    }
+
+    function removeAllChildren(node) {
+      while (node.firstChild) {
+        node.removeChild(node.firstChild);
+      }
+    }
+
+    function selectOption(select, match) {
+      var options = select.options;
+      for (var i = 0; i < options.length; i++) {
+        if (match(i, options[i])) {
+          select.selectedIndex = i;
+          return;
+        }
+      }
+    }
+
+    function addCodeSearchButton(entry, node) {
+      if (entry.isGroup) return;
+      var button = document.createElement("div");
+      button.innerHTML = '?'
+      button.className = "codeSearch"
+      button.addEventListener('click', handleCodeSearch);
+      node.appendChild(button);
+      return node;
+    }
+
+    function td(tr, content, className) {
+      var td = document.createElement("td");
+      td.innerHTML = content;
+      td.className = className
+      tr.appendChild(td);
+      return td
+    }
+
+    function nodeIndex(node) {
+      var children = node.parentNode.childNodes,
+        i = 0;
+      for (; i < children.length; i++) {
+        if (children[i] == node) {
+          return i;
+        }
+      }
+      return -1;
+    }
+
+    function toggleCssClass(node, cssClass, toggleState) {
+      var index = -1;
+      var classes;
+      if (node.className != undefined) {
+        classes = node.className.split(' ');
+        index = classes.indexOf(cssClass);
+      }
+      if (index == -1) {
+        if (toggleState === false) return;
+        node.className += ' ' + cssClass;
+        return;
+      }
+      if (toggleState === true) return;
+      classes.splice(index, 1);
+      node.className = classes.join(' ');
+    }
+
+    function NameComparator(a, b) {
+      if (a.name > b.name) return 1;
+      if (a.name < b.name) return -1;
+      return 0
+    }
+
+    function diffSign(value, digits, unit, showDiff) {
+      if (showDiff === false || baselineVersion == undefined) {
+        if (value === undefined) return '';
+        return value.toFixed(digits) + unit;
+      }
+      return (value >= 0 ? '+' : '') + value.toFixed(digits) + unit + 'Δ';
+    }
+
+    function ms(value, showDiff) {
+      return diffSign(value, 1, 'ms', showDiff);
+    }
+
+    function count(value, showDiff) {
+      return diffSign(value, 0, '#', showDiff);
+    }
+
+    function percent(value, showDiff) {
+      return diffSign(value, 1, '%', showDiff);
+    }
+
+  </script>
+  <script type="text/javascript">
+  "use strict"
+    // =========================================================================
+    // EventHandlers
+    function handleBodyLoad() {
+      $('uploadInput').focus(); 
+    }
+
+    function handleLoadFile() {
+      var files = document.getElementById("uploadInput").files;
+      var file = files[0];
+      var reader = new FileReader();
+
+      reader.onload = function(evt) {
+        pages = new Pages();
+        versions = Versions.fromJSON(JSON.parse(this.result));
+        initialize()
+        showPage(versions.versions[0].pages[0]);
+      }
+      reader.readAsText(file);
+    }
+
+    function handleToggleGroup(event) {
+      var group = event.target.parentNode.parentNode.entry;
+      toggleGroup(selectedPage.get(group.name));
+    }
+
+    function handleSelectPage(select, event) {
+      var option = select.options[select.selectedIndex];
+      if (select.id == "select_0") {
+        showPage(option.page);
+      } else {
+        var columnIndex = select.id.split('_')[1];
+        showPageInColumn(option.page, columnIndex);
+      }
+    }
+
+    function handleSelectVersion(select, event) {
+      var option = select.options[select.selectedIndex];
+      var version = option.version;
+      if (select.id == "selectVersion_0") {
+        var page = version.get(selectedPage.name);
+        showPage(page);
+      } else {
+        var columnIndex = select.id.split('_')[1];
+        var pageSelect = $('select_' + columnIndex);
+        var page = pageSelect.options[pageSelect.selectedIndex].page;
+        page = version.get(page.name);
+        showPageInColumn(page, columnIndex);
+      }
+    }
+
+    function handleSelectDetailRow(table, event) {
+      if (event.target.tagName != 'TD') return;
+      var tr = event.target.parentNode;
+      if (tr.tagName != 'TR') return;
+      if (tr.entry === undefined) return;
+      selectEntry(tr.entry, true);
+    }
+
+    function handleSelectRow(table, event, fromDetail) {
+      if (event.target.tagName != 'TD') return;
+      var tr = event.target.parentNode;
+      if (tr.tagName != 'TR') return;
+      if (tr.entry === undefined) return;
+      selectEntry(tr.entry, false);
+    }
+
+    function handleSelectBaseline(select, event) {
+      var option = select.options[select.selectedIndex];
+      baselineVersion = option.version;
+      var showingDiff = baselineVersion !== undefined;
+      var body = $('body');
+      toggleCssClass(body, 'diff', showingDiff);
+      toggleCssClass(body, 'noDiff', !showingDiff);
+      showPage(selectedPage);
+      if (selectedEntry === undefined) return;
+      selectEntry(selectedEntry, true);
+    }
+
+    function findEntry(event) {
+      var target = event.target;
+      while (target.entry === undefined) {
+        target = target.parentNode;
+        if (!target) return undefined;
+      }
+      return target.entry;
+    }
+
+    function handleUpdatePopover(event) {
+      var popover = $('popover');
+      popover.style.left = event.pageX + 'px';
+      popover.style.top = event.pageY + 'px';
+      popover.style.display = 'none';
+      popover.style.display = event.shiftKey ? 'block' : 'none';
+      var entry = findEntry(event);
+      if (entry === undefined) return;
+      showPopover(entry);
+    }
+
+    function handleToggleVersionEnable(event) {
+      var item = this.item ;
+      if (item  === undefined) return;
+      item .enabled = this.checked;
+      initialize();
+      var page = selectedPage;
+      if (page === undefined || !page.version.enabled) {
+        page = versions.getEnabledPage(page.name);
+      }
+      showPage(page);
+    }
+
+    function handleToggleContentVisibility(event) {
+      var content = event.target.contentNode;
+      toggleCssClass(content, 'hidden');
+    }
+
+    function handleCodeSearch(event) {
+      var entry = findEntry(event);
+      if (entry === undefined) return;
+      var url = "https://cs.chromium.org/search/?sq=package:chromium&type=cs&q=";
+      name = entry.name;
+      if (name.startsWith("API_")) {
+        name = name.substring(4);
+      }
+      url += encodeURIComponent(name) + "+file:src/v8/src";
+      window.open(url,'_blank');
+    }
+  </script>
+  <script type="text/javascript">
+  "use strict"
+    // =========================================================================
+    class Versions {
+      constructor() {
+        this.versions = [];
+      }
+      add(version) {
+        this.versions.push(version)
+      }
+      getPageVersions(page) {
+        var result = [];
+        this.versions.forEach((version) => {
+          if (!version.enabled) return;
+          var versionPage = version.get(page.name);
+          if (versionPage  !== undefined) result.push(versionPage);
+        });
+        return result;
+      }
+      get length() {
+        return this.versions.length
+      }
+      get(index) {
+        return this.versions[index]
+      };
+      forEach(f) {
+        this.versions.forEach(f);
+      }
+      sort() {
+        this.versions.sort(NameComparator);
+      }
+      getEnabledPage(name) {
+        for (var i = 0; i < this.versions.length; i++) {
+          var version = this.versions[i];
+          if (!version.enabled) continue;
+          var page = version.get(name);
+          if (page !== undefined) return page;
+        }
+      }
+    }
+    Versions.fromJSON = function(json) {
+      var versions = new Versions();
+      for (var version in json) {
+        versions.add(Version.fromJSON(version, json[version]));
+      }
+      versions.sort();
+      return versions;
+    }
+
+    class Version {
+      constructor(name) {
+        this.name = name;
+        this.enabled = true;
+        this.pages = [];
+      }
+      add(page) {
+        this.pages.push(page);
+      }
+      indexOf(name) {
+        for (var i = 0; i < this.pages.length; i++) {
+          if (this.pages[i].name == name) return i;
+        }
+        return -1;
+      }
+      get(name) {
+        var index = this.indexOf(name);
+        if (0 <= index) return this.pages[index];
+        return undefined
+      }
+      get length() {
+        return this.versions.length
+      }
+      getEntry(entry) {
+        if (entry === undefined) return undefined;
+        var page = this.get(entry.page.name);
+        if (page === undefined) return undefined;
+        return page.get(entry.name);
+      }
+      forEachEntry(fun) {
+        this.forEachPage((page) => {
+          page.forEach(fun);
+        });
+      }
+      forEachPage(fun) {
+        this.pages.forEach((page) => {
+          if (!page.enabled) return;
+          fun(page);
+        })
+      }
+      allEntries() {
+        var map = new Map();
+        this.forEachEntry((group, entry) => {
+          if (!map.has(entry.name)) map.set(entry.name, entry);
+        });
+        return Array.from(map.values());
+      }
+      getTotalValue(name, property) {
+        if (name === undefined) name = this.pages[0].total.name;
+        var sum = 0;
+        this.forEachPage((page) => {
+          var entry = page.get(name);
+          if (entry !== undefined) sum += entry[property];
+        });
+        return sum;
+      }
+      getTotalTime(name, showDiff) {
+        return this.getTotalValue(name, showDiff === false ? '_time' : 'time');
+      }
+      getTotalTimePercent(name, showDiff) {
+        if (baselineVersion === undefined || showDiff === false) {
+          // Return the overall average percent of the given entry name.
+          return this.getTotalValue(name, 'time') /
+            this.getTotalTime('Group-Total') * 100;
+        }
+        // Otherwise return the difference to the sum of the baseline version.
+        var baselineValue = baselineVersion.getTotalTime(name, false);
+        var total = this.getTotalValue(name, '_time');
+        return (total / baselineValue - 1)  * 100;
+      }
+      getTotalTimeVariance(name, showDiff) {
+        // Calculate the overall error for a given entry name
+        var sum = 0;
+        this.forEachPage((page) => {
+          var entry = page.get(name);
+          if (entry === undefined) return;
+          sum += entry.timeVariance * entry.timeVariance;
+        });
+        return Math.sqrt(sum);
+      }
+      getTotalTimeVariancePercent(name, showDiff) {
+        return this.getTotalTimeVariance(name, showDiff) / 
+          this.getTotalTime(name, showDiff) * 100;
+      }
+      getTotalCount(name, showDiff) {
+        return this.getTotalValue(name, showDiff === false ? '_count' : 'count');
+      }
+      getAverageTimeImpact(name, showDiff) {
+        return this.getTotalTime(name, showDiff) / this.pages.length;
+      }
+      getPagesByPercentImpact(name) {
+        var sortedPages =
+          this.pages.filter((each) => {
+            return each.get(name) !== undefined
+          });
+        sortedPages.sort((a, b) => {
+          return b.get(name).timePercent - a.get(name).timePercent;
+        });
+        return sortedPages;
+      }
+      sort() {
+        this.pages.sort(NameComparator)
+      }
+    }
+    Version.fromJSON = function(name, data) {
+      var version = new Version(name);
+      for (var pageName in data) {
+        version.add(PageVersion.fromJSON(version, pageName, data[pageName]));
+      }
+      version.sort();
+      return version;
+    }
+    
+    class Pages extends Map {
+      get(name) {
+        if (name.indexOf('www.') == 0) {
+          name = name.substring(4);
+        }
+        if (!this.has(name)) {
+          this.set(name, new Page(name));
+        }
+        return super.get(name);
+      }
+    }
+
+    class Page {
+      constructor(name) {
+        this.name = name;
+        this.enabled = true;
+        this.versions = [];
+      }
+      add(page) {
+        this.versions.push(page);
+      }
+    }
+
+    class PageVersion {
+      constructor(version, page) {
+        this.page = page;
+        this.page.add(this);
+        this.total = new GroupedEntry('Total', /.*Total.*/, '#BBB');
+        this.total.isTotal = true;
+        this.unclassified = new UnclassifiedEntry(this, "#000")
+        this.groups = [
+          this.total,
+          new GroupedEntry('IC', /.*IC.*/, "#3366CC"),
+          new GroupedEntry('Optimize',
+            /StackGuard|.*Optimize.*|.*Deoptimize.*|Recompile.*/, "#DC3912"),
+          new GroupedEntry('Compile', /.*Compile.*/, "#FFAA00"),
+          new GroupedEntry('Parse', /.*Parse.*/, "#FF6600"),
+          new GroupedEntry('Callback', /.*Callback$/, "#109618"),
+          new GroupedEntry('API', /.*API.*/, "#990099"),
+          new GroupedEntry('GC', /GC|AllocateInTargetSpace/, "#0099C6"),
+          new GroupedEntry('JavaScript', /JS_Execution/, "#DD4477"),
+          new GroupedEntry('Runtime', /.*/, "#88BB00"),
+          this.unclassified
+        ];
+        this.entryDict = new Map();
+        this.groups.forEach((entry) => {
+          entry.page = this;
+          this.entryDict.set(entry.name, entry);
+        });
+        this.version = version;
+      }
+      add(entry) {
+        entry.page = this;
+        this.entryDict.set(entry.name, entry);
+        var added = false;
+        this.groups.forEach((group) => {
+          if (!added) added = group.add(entry);
+        });
+        if (added) return;
+        this.unclassified.push(entry);
+      }
+      get(name) {
+        return this.entryDict.get(name)
+      }
+      getEntry(entry) {
+        if (entry === undefined) return undefined;
+        return this.get(entry.name);
+      }
+      get length() {
+        return this.versions.length
+      }
+      get name() { return this.page.name }
+      get enabled() { return this.page.enabled }
+      forEachSorted(referencePage, func) {
+        // Iterate over all the entries in the order they appear on the
+        // reference page.
+        referencePage.forEach((parent, referenceEntry) => {
+          var entry;
+          if (parent) parent = this.entryDict.get(parent.name);
+          if (referenceEntry) entry = this.entryDict.get(referenceEntry.name);
+          func(parent, entry, referenceEntry);
+        });
+      }
+      forEach(fun) {
+        this.forEachGroup((group) => {
+          fun(undefined, group);
+          group.forEach((entry) => {
+            fun(group, entry)
+          });
+        });
+      }
+      forEachGroup(fun) {
+        this.groups.forEach(fun)
+      }
+      sort() {
+        this.groups.sort((a, b) => {
+          return b.time - a.time;
+        });
+        this.groups.forEach((group) => {
+          group.sort()
+        });
+      }
+      distanceFromTotalPercent() {
+        var sum = 0;
+        this.groups.forEach(group => {
+          if (group == this.total) return;
+          var value = group.getTimePercentImpact() - 
+              this.getEntry(group).timePercent;
+          sum += value * value;
+        });
+        return sum;
+      }
+    }
+    PageVersion.fromJSON = function(version, name, data) {
+      var page = new PageVersion(version, pages.get(name));
+      for (var i = 0; i < data.length; i++) {
+        page.add(Entry.fromJSON(i, data[data.length - i - 1]));
+      }
+      page.sort();
+      return page
+    }
+
+
+    class Entry {
+      constructor(position, name, time, timeVariance, timeVariancePercent,
+        count,
+        countVariance, countVariancePercent) {
+        this.position = position;
+        this.name = name;
+        this._time = time;
+        this._timeVariance = timeVariance;
+        this._timeVariancePercent = timeVariancePercent;
+        this._count = count;
+        this.countVariance = countVariance;
+        this.countVariancePercent = countVariancePercent;
+        this.page = undefined;
+        this.parent = undefined;
+        this.isTotal = false;
+      }
+      getCompareWithBaseline(value, property) {
+        if (baselineVersion == undefined) return value;
+        var baselineEntry = baselineVersion.getEntry(this);
+        if (!baselineEntry) return value;
+        if (baselineVersion === this.page.version) return value;
+        return value - baselineEntry[property];
+      }
+      cssClass() {
+        return ''
+      }
+      get time() {
+        return this.getCompareWithBaseline(this._time, '_time');
+      }
+      get count() {
+        return this.getCompareWithBaseline(this._count, '_count');
+      }
+      get timePercent() {
+        var value = this._time / this.page.total._time * 100;
+        if (baselineVersion == undefined) return value;
+        var baselineEntry = baselineVersion.getEntry(this);
+        if (!baselineEntry) return value;
+        if (baselineVersion === this.page.version) return value;
+        return (this._time - baselineEntry._time) / this.page.total._time *
+          100;
+      }
+      get timePercentPerEntry() {
+        var value = this._time / this.page.total._time * 100;
+        if (baselineVersion == undefined) return value;
+        var baselineEntry = baselineVersion.getEntry(this);
+        if (!baselineEntry) return value;
+        if (baselineVersion === this.page.version) return value;
+        return (this._time / baselineEntry._time - 1) * 100;
+      }
+      get timePercentVariancePercent() {
+        // Get the absolute values for the percentages
+        return this.timeVariance / this.page.total._time * 100;
+      }
+      getTimeImpact(showDiff) {
+        return this.page.version.getTotalTime(this.name, showDiff);
+      }
+      getTimeImpactVariancePercent(showDiff) {
+        return this.page.version.getTotalTimeVariancePercent(this.name, showDiff);
+      }
+      getTimePercentImpact(showDiff) {
+        return this.page.version.getTotalTimePercent(this.name, showDiff);
+      }
+      getCountImpact(showDiff) {
+        return this.page.version.getTotalCount(this.name, showDiff);
+      }
+      getAverageTimeImpact(showDiff) {
+        return this.page.version.getAverageTimeImpact(this.name, showDiff);
+      }
+      getPagesByPercentImpact() {
+        return this.page.version.getPagesByPercentImpact(this.name);
+      }
+      get isGroup() {
+        return false
+      }
+      get timeVariance() {
+        return this._timeVariance
+      }
+      get timeVariancePercent() {
+        return this._timeVariancePercent
+      }
+    }
+    Entry.fromJSON = function(position, data) {
+      return new Entry(position, ...data);
+    }
+
+
+    class GroupedEntry extends Entry {
+      constructor(name, regexp, color) {
+        super(0, 'Group-' + name, 0, 0, 0, 0, 0, 0);
+        this.regexp = regexp;
+        this.color = color;
+        this.entries = [];
+      }
+      add(entry) {
+        if (!entry.name.match(this.regexp)) return false;
+        this._time += entry.time;
+        this._count += entry.count;
+        // TODO: sum up variance
+        this.entries.push(entry);
+        entry.parent = this;
+        return true;
+      }
+      forEach(fun) {
+        if (baselineVersion === undefined) {
+          this.entries.forEach(fun);
+          return;
+        }
+        // If we have a baslineVersion to compare against show also all entries
+        // from the other group.
+        var tmpEntries = baselineVersion.getEntry(this)
+          .entries.filter((entry) => {
+            return this.page.get(entry.name) == undefined
+          });
+
+        // The compared entries are sorted by absolute impact.
+        tmpEntries = tmpEntries.map((entry) => {
+          var tmpEntry = new Entry(0, entry.name, 0, 0, 0, 0, 0, 0);
+          tmpEntry.page = this.page;
+          return tmpEntry;
+        });
+        tmpEntries = tmpEntries.concat(this.entries);
+        tmpEntries.sort((a, b) => {
+          return a.time - b.time
+        });
+        tmpEntries.forEach(fun);
+      }
+      sort() {
+        this.entries.sort((a, b) => {
+          return b.time - a.time;
+        });
+      }
+      cssClass() {
+        if (this.page.total == this) return 'total';
+        return '';
+      }
+      get isGroup() {
+        return true
+      }
+      getVarianceForProperty(property) {
+        var sum = 0;
+        this.entries.forEach((entry) => {
+          sum += entry[property + 'Variance'] * entry[property +
+            'Variance'];
+        });
+        return Math.sqrt(sum);
+      }
+      get timeVariancePercent() {
+        if (this._time == 0) return 0;
+        return this.getVarianceForProperty('time')  / this._time * 100
+      }
+      get timeVariance() {
+        return this.getVarianceForProperty('time')
+      }
+    }
+
+    class UnclassifiedEntry extends GroupedEntry {
+      constructor(page, color) {
+        super('Unclassified', undefined, color);
+        this.page = page;
+        this._time = undefined;
+        this._count = undefined;
+      }
+      add(entry) {
+        this.entries.push(entry);
+        entry.parent = this;
+        return true;
+      }
+      forEachPageGroup(fun) {
+        this.page.forEachGroup((group) => {
+          if (group == this) return;
+          if (group == this.page.total) return;
+          fun(group);
+        });
+      }
+      get time() {
+        if (this._time === undefined) {
+          this._time = this.page.total._time;
+          this.forEachPageGroup((group) => {
+            this._time -= group._time;
+          });
+        }
+        return this.getCompareWithBaseline(this._time, '_time');
+      }
+      get count() {
+        if (this._count === undefined) {
+          this._count = this.page.total._count;
+          this.forEachPageGroup((group) => {
+            this._count -= group._count;
+          });
+        }
+        return this.getCompareWithBaseline(this._count, '_count');
+      }
+    }
+  </script>
+</head>
+
+<body id="body" onmousemove="handleUpdatePopover(event)" onload="handleBodyLoad()" class="noDiff">
+  <h1>Runtime Stats Komparator</h1>
+
+  <div id="results">
+    <div class="inline">
+      <h2>Data</h2>
+      <form name="fileForm">
+        <p>
+          <input id="uploadInput" type="file" name="files" onchange="handleLoadFile();" accept=".json">
+        </p>
+      </form>
+    </div>
+
+    <div class="inline hidden">
+      <h2>Result</h2>
+      <div class="compareSelector inline">
+        Compare against:&nbsp;<select id="baseline" onchange="handleSelectBaseline(this, event)"></select><br/>
+        <span style="color: #060">Green</span> the selected version above performs
+        better on this measurement.
+      </div>
+    </div>
+    
+    <div id="versionSelector" class="inline toggleContentVisibility">
+      <h2>Version Selector</h2>
+      <div class="content hidden">
+        <ul></ul>
+      </div>
+    </div>
+    
+    <div id="pageSelector" class="inline toggleContentVisibility">
+      <h2>Page Selector</h2>
+      <div class="content hidden">
+        <ul></ul>
+      </div>
+    </div>
+
+    <div id="view">
+    </div>
+
+    <div id="detailView" class="hidden">
+      <div class="versionDetail inline toggleContentVisibility">
+        <h3><span></span></h3>
+        <div class="content">
+          <table class="versionDetailTable" onclick="handleSelectDetailRow(this, event);">
+            <thead>
+              <tr>
+                <th class="version">Version&nbsp;</th>
+                <th class="position">Pos.&nbsp;</th>
+                <th class="value time">Time▴&nbsp;</th>
+                <th class="value time">Percent&nbsp;</th>
+                <th class="value count">Count&nbsp;</th>
+              </tr>
+            </thead>
+            <tbody></tbody>
+          </table>
+        </div>
+      </div>
+      <div class="pageDetail inline toggleContentVisibility">
+        <h3>Page Comparison for <span></span></h3>
+        <div class="content">
+          <table class="pageDetailTable" onclick="handleSelectDetailRow(this, event);">
+            <thead>
+              <tr>
+                <th class="page">Page&nbsp;</th>
+                <th class="value time">Time&nbsp;</th>
+                <th class="value time">Percent▾&nbsp;</th>
+                <th class="value time hideNoDiff">%/Entry&nbsp;</th>
+                <th class="value count">Count&nbsp;</th>
+              </tr>
+            </thead>
+            <tfoot>
+              <tr>
+                <td class="page">Total:</td>
+                <td class="value time"></td>
+                <td class="value time"></td>
+                <td class="value time hideNoDiff"></td>
+                <td class="value count"></td>
+              </tr>
+            </tfoot>
+            <tbody></tbody>
+          </table>
+        </div>
+      </div>
+      <div class="impactView inline toggleContentVisibility">
+        <h3>Impact list for <span></span></h3>
+        <div class="content">
+          <table class="pageDetailTable" onclick="handleSelectDetailRow(this, event);">
+            <thead>
+              <tr>
+                <th class="page">Name&nbsp;</th>
+                <th class="value time">Time&nbsp;</th>
+                <th class="value time">Percent▾&nbsp;</th>
+                <th class="">Top Pages</th>
+              </tr>
+            </thead>
+            <tbody></tbody>
+          </table>
+        </div>
+      </div>
+    </div>
+    <div id="pageVersionGraph" class="graph hidden toggleContentVisibility">
+      <h3><span></span></h3>
+      <div class="content"></div>
+    </div>
+    <div id="pageGraph" class="graph hidden toggleContentVisibility">
+      <h3><span></span></h3>
+      <div class="content"></div>
+    </div>
+    <div id="versionGraph" class="graph hidden toggleContentVisibility">
+      <h3><span></span></h3>
+      <div class="content"></div>
+    </div>
+
+    <div id="column" class="column">
+      <div class="header">
+        <select class="version" onchange="handleSelectVersion(this, event);"></select>
+        <select class="pageVersion" onchange="handleSelectPage(this, event);"></select>
+      </div>
+      <table class="list" onclick="handleSelectRow(this, event);">
+        <thead>
+          <tr>
+            <th class="position">Pos.&nbsp;</th>
+            <th class="name">Name&nbsp;</th>
+            <th class="value time">Time&nbsp;</th>
+            <th class="value time">Percent&nbsp;</th>
+            <th class="value count">Count&nbsp;</th>
+          </tr>
+        </thead>
+        <tbody></tbody>
+      </table>
+    </div>
+  </div>
+
+  <div class="inline">
+    <h2>Usage</h2>
+    <ol>
+      <li>Install scipy, e.g. <code>sudo aptitude install python-scipy</code>
+      <li>Build chrome with the <a href="https://codereview.chromium.org/1923893002">extended runtime callstats</a>.</li>
+      <li>Run <code>callstats.py</code> with a web-page-replay archive:
+        <pre>$V8_DIR/tools/callstats.py run \
+        --replay-bin=$CHROME_SRC/third_party/webpagereplay/replay.py \
+        --replay-wpr=$INPUT_DIR/top25.wpr \
+        --js-flags="" \
+        --with-chrome=$CHROME_SRC/out/Release/chrome \
+        --sites-file=$INPUT_DIR/top25.json</pre>
+      </li>
+      <li>Move results file to a subdirectory: <code>mkdir $VERSION_DIR; mv *.txt $VERSION_DIR</code></li>
+      <li>Repeat from step 1 with a different configuration (e.g. <code>--js-flags="--nolazy"</code>).</li>
+      <li>Create the final results file: <code>./callstats.py json $VERSION_DIR1 $VERSION_DIR2 > result.json</code></li>
+      <li>Use <code>results.json</code> on this site.</code>
+    </ol>
+  </div>
+
+  <div id="popover">
+    <div class="popoverArrow"></div>
+    <table>
+      <tr>
+        <td class="name" colspan="6"></td>
+      </tr>
+      <tr>
+        <td>Page:</td>
+        <td class="page name" colspan="6"></td>
+      </tr>
+      <tr>
+        <td>Version:</td>
+        <td class="version name" colspan="3"></td>
+        <td class="compare version name" colspan="3"></td>
+      </tr>
+      <tr>
+        <td>Time:</td>
+        <td class="time"></td><td>±</td><td class="timeVariance"></td>
+        <td class="compare time"></td><td class="compare"> ± </td><td class="compare timeVariance"></td>
+      </tr>
+      <tr>
+        <td>Percent:</td>
+        <td class="percent"></td><td>±</td><td class="percentVariance"></td>
+        <td class="compare percent"></td><td class="compare"> ± </td><td class="compare percentVariance"></td>
+      </tr>
+      <tr>
+        <td>Percent per Entry:</td>
+        <td class="percentPerEntry"></td><td colspan=2></td>
+        <td class="compare percentPerEntry"></td><td colspan=2></td>
+      </tr>
+      <tr>
+        <td>Count:</td>
+        <td class="count"></td><td>±</td><td class="countVariance"></td>
+        <td class="compare count"></td><td class="compare"> ± </td><td class="compare countVariance"></td>
+      </tr>
+      <tr>
+        <td>Overall Impact:</td>
+        <td class="timeImpact"></td><td>±</td><td class="timePercentImpact"></td>
+        <td class="compare timeImpact"></td><td class="compare"> ± </td><td class="compare timePercentImpact"></td>
+      </tr>
+    </table>
+  </div>
+</body>
+</html>
diff --git a/tools/callstats.py b/tools/callstats.py
new file mode 100755
index 0000000..28408bf
--- /dev/null
+++ b/tools/callstats.py
@@ -0,0 +1,638 @@
+#!/usr/bin/env python
+# Copyright 2016 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+'''
+Usage: runtime-call-stats.py [-h] <command> ...
+
+Optional arguments:
+  -h, --help  show this help message and exit
+
+Commands:
+  run         run chrome with --runtime-call-stats and generate logs
+  stats       process logs and print statistics
+  json        process logs from several versions and generate JSON
+  help        help information
+
+For each command, you can try ./runtime-call-stats.py help command.
+'''
+
+import argparse
+import json
+import os
+import re
+import shutil
+import subprocess
+import sys
+import tempfile
+import operator
+
+import numpy
+import scipy
+import scipy.stats
+from math import sqrt
+
+
+# Run benchmarks.
+
+def print_command(cmd_args):
+  def fix_for_printing(arg):
+    m = re.match(r'^--([^=]+)=(.*)$', arg)
+    if m and (' ' in m.group(2) or m.group(2).startswith('-')):
+      arg = "--{}='{}'".format(m.group(1), m.group(2))
+    elif ' ' in arg:
+      arg = "'{}'".format(arg)
+    return arg
+  print " ".join(map(fix_for_printing, cmd_args))
+
+
+def start_replay_server(args, sites):
+  with tempfile.NamedTemporaryFile(prefix='callstats-inject-', suffix='.js',
+                                   mode='wt', delete=False) as f:
+    injection = f.name
+    generate_injection(f, sites, args.refresh)
+  http_port = 4080 + args.port_offset
+  https_port = 4443 + args.port_offset
+  cmd_args = [
+      args.replay_bin,
+      "--port=%s" % http_port,
+      "--ssl_port=%s" % https_port,
+      "--no-dns_forwarding",
+      "--use_closest_match",
+      "--no-diff_unknown_requests",
+      "--inject_scripts=deterministic.js,{}".format(injection),
+      args.replay_wpr,
+  ]
+  print "=" * 80
+  print_command(cmd_args)
+  with open(os.devnull, 'w') as null:
+    server = subprocess.Popen(cmd_args, stdout=null, stderr=null)
+  print "RUNNING REPLAY SERVER: %s with PID=%s" % (args.replay_bin, server.pid)
+  print "=" * 80
+  return {'process': server, 'injection': injection}
+
+
+def stop_replay_server(server):
+  print("SHUTTING DOWN REPLAY SERVER %s" % server['process'].pid)
+  server['process'].terminate()
+  os.remove(server['injection'])
+
+
+def generate_injection(f, sites, refreshes=0):
+  print >> f, """\
+(function() {
+  var s = window.sessionStorage.getItem("refreshCounter");
+  var refreshTotal = """, refreshes, """;
+  var refreshCounter = s ? parseInt(s) : refreshTotal;
+  var refreshId = refreshTotal - refreshCounter;
+  if (refreshCounter > 0) {
+    window.sessionStorage.setItem("refreshCounter", refreshCounter-1);
+  }
+  function match(url, item) {
+    if ('regexp' in item) { return url.match(item.regexp) !== null };
+    var url_wanted = item.url;
+    /* Allow automatic redirections from http to https. */
+    if (url_wanted.startsWith("http://") && url.startsWith("https://")) {
+      url_wanted = "https://" + url_wanted.substr(7);
+    }
+    return url.startsWith(url_wanted);
+  };
+  function onLoad(url) {
+    for (var item of sites) {
+      if (!match(url, item)) continue;
+      var timeout = 'timeline' in item ? 2000 * item.timeline
+                  : 'timeout'  in item ? 1000 * (item.timeout - 3)
+                  : 10000;
+      console.log("Setting time out of " + timeout + " for: " + url);
+      window.setTimeout(function() {
+        console.log("Time is out for: " + url);
+        var msg = "STATS: (" + refreshId + ") " + url;
+        %GetAndResetRuntimeCallStats(1, msg);
+        if (refreshCounter > 0) {
+          console.log(
+              "Refresh counter is " + refreshCounter + ", refreshing: " + url);
+          window.location.reload();
+        }
+      }, timeout);
+      return;
+    }
+    console.log("Ignoring: " + url);
+  };
+  var sites =
+    """, json.dumps(sites), """;
+  onLoad(window.location.href);
+})();"""
+
+
+def run_site(site, domain, args, timeout=None):
+  print "="*80
+  print "RUNNING DOMAIN %s" % domain
+  print "="*80
+  result_template = "{domain}#{count}.txt" if args.repeat else "{domain}.txt"
+  count = 0
+  if timeout is None: timeout = args.timeout
+  if args.replay_wpr:
+    timeout *= 1 + args.refresh
+    timeout += 1
+  retries_since_good_run = 0
+  while count == 0 or args.repeat is not None and count < args.repeat:
+    count += 1
+    result = result_template.format(domain=domain, count=count)
+    retries = 0
+    while args.retries is None or retries < args.retries:
+      retries += 1
+      try:
+        if args.user_data_dir:
+          user_data_dir = args.user_data_dir
+        else:
+          user_data_dir = tempfile.mkdtemp(prefix="chr_")
+        js_flags = "--runtime-call-stats"
+        if args.replay_wpr: js_flags += " --allow-natives-syntax"
+        if args.js_flags: js_flags += " " + args.js_flags
+        chrome_flags = [
+            "--no-default-browser-check",
+            "--no-sandbox",
+            "--disable-translate",
+            "--js-flags={}".format(js_flags),
+            "--no-first-run",
+            "--user-data-dir={}".format(user_data_dir),
+        ]
+        if args.replay_wpr:
+          http_port = 4080 + args.port_offset
+          https_port = 4443 + args.port_offset
+          chrome_flags += [
+              "--host-resolver-rules=MAP *:80 localhost:%s, "  \
+                                    "MAP *:443 localhost:%s, " \
+                                    "EXCLUDE localhost" % (
+                                        http_port, https_port),
+              "--ignore-certificate-errors",
+              "--disable-seccomp-sandbox",
+              "--disable-web-security",
+              "--reduce-security-for-testing",
+              "--allow-insecure-localhost",
+          ]
+        else:
+          chrome_flags += [
+              "--single-process",
+          ]
+        if args.chrome_flags:
+          chrome_flags += args.chrome_flags.split()
+        cmd_args = [
+            "timeout", str(timeout),
+            args.with_chrome
+        ] + chrome_flags + [ site ]
+        print "- " * 40
+        print_command(cmd_args)
+        print "- " * 40
+        with open(result, "wt") as f:
+          with open(args.log_stderr or os.devnull, 'at') as err:
+            status = subprocess.call(cmd_args, stdout=f, stderr=err)
+        # 124 means timeout killed chrome, 0 means the user was bored first!
+        # If none of these two happened, then chrome apparently crashed, so
+        # it must be called again.
+        if status != 124 and status != 0:
+          print("CHROME CRASHED, REPEATING RUN");
+          continue
+        # If the stats file is empty, chrome must be called again.
+        if os.path.isfile(result) and os.path.getsize(result) > 0:
+          if args.print_url:
+            with open(result, "at") as f:
+              print >> f
+              print >> f, "URL: {}".format(site)
+          retries_since_good_run = 0
+          break
+        if retries_since_good_run < 6:
+          timeout += 2 ** retries_since_good_run
+          retries_since_good_run += 1
+        print("EMPTY RESULT, REPEATING RUN ({})".format(
+            retries_since_good_run));
+      finally:
+        if not args.user_data_dir:
+          shutil.rmtree(user_data_dir)
+
+
+def read_sites_file(args):
+  try:
+    sites = []
+    try:
+      with open(args.sites_file, "rt") as f:
+        for item in json.load(f):
+          if 'timeout' not in item:
+            # This is more-or-less arbitrary.
+            item['timeout'] = int(1.5 * item['timeline'] + 7)
+          if item['timeout'] > args.timeout: item['timeout'] = args.timeout
+          sites.append(item)
+    except ValueError:
+      with open(args.sites_file, "rt") as f:
+        for line in f:
+          line = line.strip()
+          if not line or line.startswith('#'): continue
+          sites.append({'url': line, 'timeout': args.timeout})
+    return sites
+  except IOError as e:
+    args.error("Cannot read from {}. {}.".format(args.sites_file, e.strerror))
+    sys.exit(1)
+
+
+def do_run(args):
+  # Determine the websites to benchmark.
+  if args.sites_file:
+    sites = read_sites_file(args)
+  else:
+    sites = [{'url': site, 'timeout': args.timeout} for site in args.sites]
+  # Disambiguate domains, if needed.
+  L = []
+  domains = {}
+  for item in sites:
+    site = item['url']
+    domain = None
+    if args.domain:
+      domain = args.domain
+    elif 'domain' in item:
+      domain = item['domain']
+    else:
+      m = re.match(r'^(https?://)?([^/]+)(/.*)?$', site)
+      if not m:
+        args.error("Invalid URL {}.".format(site))
+        continue
+      domain = m.group(2)
+    entry = [site, domain, None, item['timeout']]
+    if domain not in domains:
+      domains[domain] = entry
+    else:
+      if not isinstance(domains[domain], int):
+        domains[domain][2] = 1
+        domains[domain] = 1
+      domains[domain] += 1
+      entry[2] = domains[domain]
+    L.append(entry)
+  replay_server = start_replay_server(args, sites) if args.replay_wpr else None
+  try:
+    # Run them.
+    for site, domain, count, timeout in L:
+      if count is not None: domain = "{}%{}".format(domain, count)
+      print site, domain, timeout
+      run_site(site, domain, args, timeout)
+  finally:
+    if replay_server:
+      stop_replay_server(replay_server)
+
+
+# Calculate statistics.
+
+def statistics(data):
+  N = len(data)
+  average = numpy.average(data)
+  median = numpy.median(data)
+  low = numpy.min(data)
+  high= numpy.max(data)
+  if N > 1:
+    # evaluate sample variance by setting delta degrees of freedom (ddof) to
+    # 1. The degree used in calculations is N - ddof
+    stddev = numpy.std(data, ddof=1)
+    # Get the endpoints of the range that contains 95% of the distribution
+    t_bounds = scipy.stats.t.interval(0.95, N-1)
+    #assert abs(t_bounds[0] + t_bounds[1]) < 1e-6
+    # sum mean to the confidence interval
+    ci = {
+        'abs': t_bounds[1] * stddev / sqrt(N),
+        'low': average + t_bounds[0] * stddev / sqrt(N),
+        'high': average + t_bounds[1] * stddev / sqrt(N)
+    }
+  else:
+    stddev = 0
+    ci = { 'abs': 0, 'low': average, 'high': average }
+  if abs(stddev) > 0.0001 and abs(average) > 0.0001:
+    ci['perc'] = t_bounds[1] * stddev / sqrt(N) / average * 100
+  else:
+    ci['perc'] = 0
+  return { 'samples': N, 'average': average, 'median': median,
+           'stddev': stddev, 'min': low, 'max': high, 'ci': ci }
+
+
+def read_stats(path, domain, args):
+  groups = [];
+  if args.aggregate:
+    groups = [
+        ('Group-IC', re.compile(".*IC.*")),
+        ('Group-Optimize',
+         re.compile("StackGuard|.*Optimize.*|.*Deoptimize.*|Recompile.*")),
+        ('Group-Compile', re.compile(".*Compile.*")),
+        ('Group-Parse', re.compile(".*Parse.*")),
+        ('Group-Callback', re.compile(".*Callback.*")),
+        ('Group-API', re.compile(".*API.*")),
+        ('Group-GC', re.compile("GC|AllocateInTargetSpace")),
+        ('Group-JavaScript', re.compile("JS_Execution")),
+        ('Group-Runtime', re.compile(".*"))]
+  with open(path, "rt") as f:
+    # Process the whole file and sum repeating entries.
+    entries = { 'Sum': {'time': 0, 'count': 0} }
+    for group_name, regexp in groups:
+      entries[group_name] = { 'time': 0, 'count': 0 }
+    for line in f:
+      line = line.strip()
+      # Discard headers and footers.
+      if not line: continue
+      if line.startswith("Runtime Function"): continue
+      if line.startswith("===="): continue
+      if line.startswith("----"): continue
+      if line.startswith("URL:"): continue
+      if line.startswith("STATS:"): continue
+      # We have a regular line.
+      fields = line.split()
+      key = fields[0]
+      time = float(fields[1].replace("ms", ""))
+      count = int(fields[3])
+      if key not in entries: entries[key] = { 'time': 0, 'count': 0 }
+      entries[key]['time'] += time
+      entries[key]['count'] += count
+      # We calculate the sum, if it's not the "total" line.
+      if key != "Total":
+        entries['Sum']['time'] += time
+        entries['Sum']['count'] += count
+        for group_name, regexp in groups:
+          if not regexp.match(key): continue
+          entries[group_name]['time'] += time
+          entries[group_name]['count'] += count
+          break
+    # Append the sums as single entries to domain.
+    for key in entries :
+      if key not in domain: domain[key] = { 'time_list': [], 'count_list': [] }
+      domain[key]['time_list'].append(entries[key]['time'])
+      domain[key]['count_list'].append(entries[key]['count'])
+
+
+def print_stats(S, args):
+  # Sort by ascending/descending time average, then by ascending/descending
+  # count average, then by ascending name.
+  def sort_asc_func(item):
+    return (item[1]['time_stat']['average'],
+            item[1]['count_stat']['average'],
+            item[0])
+  def sort_desc_func(item):
+    return (-item[1]['time_stat']['average'],
+            -item[1]['count_stat']['average'],
+            item[0])
+  # Sorting order is in the commend-line arguments.
+  sort_func = sort_asc_func if args.sort == "asc" else sort_desc_func
+  # Possibly limit how many elements to print.
+  L = [item for item in sorted(S.items(), key=sort_func)
+       if item[0] not in ["Total", "Sum"]]
+  N = len(L)
+  if args.limit == 0:
+    low, high = 0, N
+  elif args.sort == "desc":
+    low, high = 0, args.limit
+  else:
+    low, high = N-args.limit, N
+  # How to print entries.
+  def print_entry(key, value):
+    def stats(s, units=""):
+      conf = "{:0.1f}({:0.2f}%)".format(s['ci']['abs'], s['ci']['perc'])
+      return "{:8.1f}{} +/- {:15s}".format(s['average'], units, conf)
+    print "{:>50s}  {}  {}".format(
+      key,
+      stats(value['time_stat'], units="ms"),
+      stats(value['count_stat'])
+    )
+  # Print and calculate partial sums, if necessary.
+  for i in range(low, high):
+    print_entry(*L[i])
+    if args.totals and args.limit != 0 and not args.aggregate:
+      if i == low:
+        partial = { 'time_list': [0] * len(L[i][1]['time_list']),
+                    'count_list': [0] * len(L[i][1]['count_list']) }
+      assert len(partial['time_list']) == len(L[i][1]['time_list'])
+      assert len(partial['count_list']) == len(L[i][1]['count_list'])
+      for j, v in enumerate(L[i][1]['time_list']):
+        partial['time_list'][j] += v
+      for j, v in enumerate(L[i][1]['count_list']):
+        partial['count_list'][j] += v
+  # Print totals, if necessary.
+  if args.totals:
+    print '-' * 80
+    if args.limit != 0 and not args.aggregate:
+      partial['time_stat'] = statistics(partial['time_list'])
+      partial['count_stat'] = statistics(partial['count_list'])
+      print_entry("Partial", partial)
+    print_entry("Sum", S["Sum"])
+    print_entry("Total", S["Total"])
+
+
+def do_stats(args):
+  domains = {}
+  for path in args.logfiles:
+    filename = os.path.basename(path)
+    m = re.match(r'^([^#]+)(#.*)?$', filename)
+    domain = m.group(1)
+    if domain not in domains: domains[domain] = {}
+    read_stats(path, domains[domain], args)
+  if args.aggregate:
+    create_total_page_stats(domains, args)
+  for i, domain in enumerate(sorted(domains)):
+    if len(domains) > 1:
+      if i > 0: print
+      print "{}:".format(domain)
+      print '=' * 80
+    domain_stats = domains[domain]
+    for key in domain_stats:
+      domain_stats[key]['time_stat'] = \
+          statistics(domain_stats[key]['time_list'])
+      domain_stats[key]['count_stat'] = \
+          statistics(domain_stats[key]['count_list'])
+    print_stats(domain_stats, args)
+
+
+# Create a Total page with all entries summed up.
+def create_total_page_stats(domains, args):
+  total = {}
+  def sum_up(parent, key, other):
+    sums = parent[key]
+    for i, item in enumerate(other[key]):
+      if i >= len(sums):
+        sums.extend([0] * (i - len(sums) + 1))
+      if item is not None:
+        sums[i] += item
+  # Sum up all the entries/metrics from all domains
+  for domain, entries in domains.items():
+    for key, domain_stats in entries.items():
+      if key not in total:
+        total[key] = {}
+        total[key]['time_list'] = list(domain_stats['time_list'])
+        total[key]['count_list'] = list(domain_stats['count_list'])
+      else:
+        sum_up(total[key], 'time_list', domain_stats)
+        sum_up(total[key], 'count_list', domain_stats)
+  # Add a new "Total" page containing the summed up metrics.
+  domains['Total'] = total
+
+
+# Generate JSON file.
+
+def do_json(args):
+  versions = {}
+  for path in args.logdirs:
+    if os.path.isdir(path):
+      for root, dirs, files in os.walk(path):
+        version = os.path.basename(root)
+        if version not in versions: versions[version] = {}
+        for filename in files:
+          if filename.endswith(".txt"):
+            m = re.match(r'^([^#]+)(#.*)?\.txt$', filename)
+            domain = m.group(1)
+            if domain not in versions[version]: versions[version][domain] = {}
+            read_stats(os.path.join(root, filename),
+                       versions[version][domain], args)
+  for version, domains in versions.items():
+    if args.aggregate:
+      create_total_page_stats(domains, args)
+    for domain, entries in domains.items():
+      stats = []
+      for name, value in entries.items():
+        # We don't want the calculated sum in the JSON file.
+        if name == "Sum": continue
+        entry = [name]
+        for x in ['time_list', 'count_list']:
+          s = statistics(entries[name][x])
+          entry.append(round(s['average'], 1))
+          entry.append(round(s['ci']['abs'], 1))
+          entry.append(round(s['ci']['perc'], 2))
+        stats.append(entry)
+      domains[domain] = stats
+  print json.dumps(versions, separators=(',', ':'))
+
+
+# Help.
+
+def do_help(parser, subparsers, args):
+  if args.help_cmd:
+    if args.help_cmd in subparsers:
+      subparsers[args.help_cmd].print_help()
+    else:
+      args.error("Unknown command '{}'".format(args.help_cmd))
+  else:
+    parser.print_help()
+
+
+# Main program, parse command line and execute.
+
+def coexist(*l):
+  given = sum(1 for x in l if x)
+  return given == 0 or given == len(l)
+
+def main():
+  parser = argparse.ArgumentParser()
+  subparser_adder = parser.add_subparsers(title="commands", dest="command",
+                                          metavar="<command>")
+  subparsers = {}
+  # Command: run.
+  subparsers["run"] = subparser_adder.add_parser(
+      "run", help="run --help")
+  subparsers["run"].set_defaults(
+      func=do_run, error=subparsers["run"].error)
+  subparsers["run"].add_argument(
+      "--chrome-flags", type=str, default="",
+      help="specify additional chrome flags")
+  subparsers["run"].add_argument(
+      "--js-flags", type=str, default="",
+      help="specify additional V8 flags")
+  subparsers["run"].add_argument(
+      "--domain", type=str, default="",
+      help="specify the output file domain name")
+  subparsers["run"].add_argument(
+      "--no-url", dest="print_url", action="store_false", default=True,
+      help="do not include url in statistics file")
+  subparsers["run"].add_argument(
+      "-n", "--repeat", type=int, metavar="<num>",
+      help="specify iterations for each website (default: once)")
+  subparsers["run"].add_argument(
+      "-k", "--refresh", type=int, metavar="<num>", default=0,
+      help="specify refreshes for each iteration (default: 0)")
+  subparsers["run"].add_argument(
+      "--replay-wpr", type=str, metavar="<path>",
+      help="use the specified web page replay (.wpr) archive")
+  subparsers["run"].add_argument(
+      "--replay-bin", type=str, metavar="<path>",
+      help="specify the replay.py script typically located in " \
+           "$CHROMIUM/src/third_party/webpagereplay/replay.py")
+  subparsers["run"].add_argument(
+      "-r", "--retries", type=int, metavar="<num>",
+      help="specify retries if website is down (default: forever)")
+  subparsers["run"].add_argument(
+      "-f", "--sites-file", type=str, metavar="<path>",
+      help="specify file containing benchmark websites")
+  subparsers["run"].add_argument(
+      "-t", "--timeout", type=int, metavar="<seconds>", default=60,
+      help="specify seconds before chrome is killed")
+  subparsers["run"].add_argument(
+      "-p", "--port-offset", type=int, metavar="<offset>", default=0,
+      help="specify the offset for the replay server's default ports")
+  subparsers["run"].add_argument(
+      "-u", "--user-data-dir", type=str, metavar="<path>",
+      help="specify user data dir (default is temporary)")
+  subparsers["run"].add_argument(
+      "-c", "--with-chrome", type=str, metavar="<path>",
+      default="/usr/bin/google-chrome",
+      help="specify chrome executable to use")
+  subparsers["run"].add_argument(
+      "-l", "--log-stderr", type=str, metavar="<path>",
+      help="specify where chrome's stderr should go (default: /dev/null)")
+  subparsers["run"].add_argument(
+      "sites", type=str, metavar="<URL>", nargs="*",
+      help="specify benchmark website")
+  # Command: stats.
+  subparsers["stats"] = subparser_adder.add_parser(
+      "stats", help="stats --help")
+  subparsers["stats"].set_defaults(
+      func=do_stats, error=subparsers["stats"].error)
+  subparsers["stats"].add_argument(
+      "-l", "--limit", type=int, metavar="<num>", default=0,
+      help="limit how many items to print (default: none)")
+  subparsers["stats"].add_argument(
+      "-s", "--sort", choices=["asc", "desc"], default="asc",
+      help="specify sorting order (default: ascending)")
+  subparsers["stats"].add_argument(
+      "-n", "--no-total", dest="totals", action="store_false", default=True,
+      help="do not print totals")
+  subparsers["stats"].add_argument(
+      "logfiles", type=str, metavar="<logfile>", nargs="*",
+      help="specify log files to parse")
+  subparsers["stats"].add_argument(
+      "--aggregate", dest="aggregate", action="store_true", default=False,
+      help="Create aggregated entries. Adds Group-* entries at the toplevel. " +
+      "Additionally creates a Total page with all entries.")
+  # Command: json.
+  subparsers["json"] = subparser_adder.add_parser(
+      "json", help="json --help")
+  subparsers["json"].set_defaults(
+      func=do_json, error=subparsers["json"].error)
+  subparsers["json"].add_argument(
+      "logdirs", type=str, metavar="<logdir>", nargs="*",
+      help="specify directories with log files to parse")
+  subparsers["json"].add_argument(
+      "--aggregate", dest="aggregate", action="store_true", default=False,
+      help="Create aggregated entries. Adds Group-* entries at the toplevel. " +
+      "Additionally creates a Total page with all entries.")
+  # Command: help.
+  subparsers["help"] = subparser_adder.add_parser(
+      "help", help="help information")
+  subparsers["help"].set_defaults(
+      func=lambda args: do_help(parser, subparsers, args),
+      error=subparsers["help"].error)
+  subparsers["help"].add_argument(
+      "help_cmd", type=str, metavar="<command>", nargs="?",
+      help="command for which to display help")
+  # Execute the command.
+  args = parser.parse_args()
+  setattr(args, 'script_path', os.path.dirname(sys.argv[0]))
+  if args.command == "run" and coexist(args.sites_file, args.sites):
+    args.error("use either option --sites-file or site URLs")
+    sys.exit(1)
+  elif args.command == "run" and not coexist(args.replay_wpr, args.replay_bin):
+    args.error("options --replay-wpr and --replay-bin must be used together")
+    sys.exit(1)
+  else:
+    args.func(args)
+
+if __name__ == "__main__":
+  sys.exit(main())
diff --git a/tools/check-static-initializers.gyp b/tools/check-static-initializers.gyp
index 547a6c8..cfeacfc 100644
--- a/tools/check-static-initializers.gyp
+++ b/tools/check-static-initializers.gyp
@@ -13,8 +13,8 @@
             '../src/d8.gyp:d8_run',
           ],
           'includes': [
-            '../build/features.gypi',
-            '../build/isolate.gypi',
+            '../gypfiles/features.gypi',
+            '../gypfiles/isolate.gypi',
           ],
           'sources': [
             'check-static-initializers.isolate',
diff --git a/tools/codemap.js b/tools/codemap.js
index fa6c36b..30cdc21 100644
--- a/tools/codemap.js
+++ b/tools/codemap.js
@@ -246,6 +246,14 @@
 
 
 /**
+ * Returns an array of pairs of all static code entries and their addresses.
+ */
+CodeMap.prototype.getAllStaticEntriesWithAddresses = function() {
+  return this.statics_.exportKeysAndValues();
+};
+
+
+/**
  * Returns an array of all libraries entries.
  */
 CodeMap.prototype.getAllLibrariesEntries = function() {
diff --git a/tools/detect-builtins.js b/tools/detect-builtins.js
index 2a476ba..90bdc08 100644
--- a/tools/detect-builtins.js
+++ b/tools/detect-builtins.js
@@ -24,6 +24,8 @@
       }
       // Avoid endless recursion.
       if (this_name === "prototype" && name === "constructor") continue;
+      // Avoid needless duplication.
+      if (this_name === "__PROTO__" && name === "constructor") continue;
       // Could get this from the parent, but having it locally is easier.
       var property = { "name": name };
       try {
@@ -39,9 +41,18 @@
         property.length = value.length;
         property.prototype = GetProperties("prototype", value.prototype);
       }
-      property.properties = GetProperties(name, value);
+      if (type === "string" || type === "number") {
+        property.value = value;
+      } else {
+        property.properties = GetProperties(name, value);
+      }
       result[name] = property;
     }
+    // Print the __proto__ if it's not the default Object prototype.
+    if (typeof object === "object" && object.__proto__ !== null &&
+        !object.__proto__.hasOwnProperty("__proto__")) {
+      result.__PROTO__ = GetProperties("__PROTO__", object.__proto__);
+    }
     return result;
   };
 
diff --git a/tools/dump-cpp.py b/tools/dump-cpp.py
new file mode 100644
index 0000000..5198eca
--- /dev/null
+++ b/tools/dump-cpp.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+# Copyright 2016 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This script executes dumpcpp.js, collects all dumped C++ symbols,
+# and merges them back into v8 log.
+
+import os
+import platform
+import re
+import subprocess
+import sys
+
+def is_file_executable(fPath):
+  return os.path.isfile(fPath) and os.access(fPath, os.X_OK)
+
+if __name__ == '__main__':
+  JS_FILES = ['splaytree.js', 'codemap.js', 'csvparser.js', 'consarray.js',
+              'profile.js', 'logreader.js', 'tickprocessor.js', 'SourceMap.js',
+              'dumpcpp.js', 'dumpcpp-driver.js']
+  tools_path = os.path.dirname(os.path.realpath(__file__))
+  on_windows = platform.system() == 'Windows'
+  JS_FILES = [os.path.join(tools_path, f) for f in JS_FILES]
+
+  args = []
+  log_file = 'v8.log'
+  debug = False
+  for arg in sys.argv[1:]:
+    if arg == '--debug':
+      debug = True
+      continue
+    args.append(arg)
+    if not arg.startswith('-'):
+      log_file = arg
+
+  if on_windows:
+    args.append('--windows')
+
+  with open(log_file, 'r') as f:
+    lines = f.readlines()
+
+  d8_line = re.search(',\"(.*d8)', ''.join(lines))
+  if d8_line:
+    d8_exec = d8_line.group(1)
+    if not is_file_executable(d8_exec):
+      print 'd8 binary path found in {} is not executable.'.format(log_file)
+      sys.exit(-1)
+  else:
+    print 'No d8 binary path found in {}.'.format(log_file)
+    sys.exit(-1)
+
+  args = [d8_exec] + JS_FILES + ['--'] + args
+
+  with open(log_file) as f:
+    sp = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+                          stdin=f)
+    out, err = sp.communicate()
+  if debug:
+    print err
+  if sp.returncode != 0:
+    print out
+    exit(-1)
+
+  if on_windows and out:
+    out = re.sub('\r+\n', '\n', out)
+
+  is_written = not bool(out)
+  with open(log_file, 'w') as f:
+    for line in lines:
+      if not is_written and line.startswith('tick'):
+        f.write(out)
+        is_written = True
+      f.write(line)
diff --git a/tools/dumpcpp-driver.js b/tools/dumpcpp-driver.js
new file mode 100644
index 0000000..4452777
--- /dev/null
+++ b/tools/dumpcpp-driver.js
@@ -0,0 +1,45 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Dump C++ symbols of shared library if possible
+
+function processArguments(args) {
+  var processor = new ArgumentsProcessor(args);
+  if (processor.parse()) {
+    return processor.result();
+  } else {
+    processor.printUsageAndExit();
+  }
+}
+
+function initSourceMapSupport() {
+  // Pull dev tools source maps into our name space.
+  SourceMap = WebInspector.SourceMap;
+
+  // Overwrite the load function to load scripts synchronously.
+  SourceMap.load = function(sourceMapURL) {
+    var content = readFile(sourceMapURL);
+    var sourceMapObject = (JSON.parse(content));
+    return new SourceMap(sourceMapURL, sourceMapObject);
+  };
+}
+
+var entriesProviders = {
+  'unix': UnixCppEntriesProvider,
+  'windows': WindowsCppEntriesProvider,
+  'mac': MacCppEntriesProvider
+};
+
+var params = processArguments(arguments);
+var sourceMap = null;
+if (params.sourceMap) {
+  initSourceMapSupport();
+  sourceMap = SourceMap.load(params.sourceMap);
+}
+
+var cppProcessor = new CppProcessor(
+  new (entriesProviders[params.platform])(params.nm, params.targetRootFS),
+  params.timedRange, params.pairwiseTimedRange);
+cppProcessor.processLogFile(params.logFileName);
+cppProcessor.dumpCppSymbols();
diff --git a/tools/dumpcpp.js b/tools/dumpcpp.js
new file mode 100644
index 0000000..ca5ff67
--- /dev/null
+++ b/tools/dumpcpp.js
@@ -0,0 +1,58 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function CppProcessor(cppEntriesProvider, timedRange, pairwiseTimedRange) {
+  LogReader.call(this, {
+      'shared-library': { parsers: [null, parseInt, parseInt, parseInt],
+          processor: this.processSharedLibrary }
+  }, timedRange, pairwiseTimedRange);
+
+  this.cppEntriesProvider_ = cppEntriesProvider;
+  this.codeMap_ = new CodeMap();
+  this.lastLogFileName_ = null;
+}
+inherits(CppProcessor, LogReader);
+
+/**
+ * @override
+ */
+CppProcessor.prototype.printError = function(str) {
+  print(str);
+};
+
+CppProcessor.prototype.processLogFile = function(fileName) {
+  this.lastLogFileName_ = fileName;
+  var line;
+  while (line = readline()) {
+    this.processLogLine(line);
+  }
+};
+
+CppProcessor.prototype.processLogFileInTest = function(fileName) {
+   // Hack file name to avoid dealing with platform specifics.
+  this.lastLogFileName_ = 'v8.log';
+  var contents = readFile(fileName);
+  this.processLogChunk(contents);
+};
+
+CppProcessor.prototype.processSharedLibrary = function(
+    name, startAddr, endAddr, aslrSlide) {
+  var self = this;
+  var libFuncs = this.cppEntriesProvider_.parseVmSymbols(
+      name, startAddr, endAddr, aslrSlide, function(fName, fStart, fEnd) {
+    var entry = new CodeMap.CodeEntry(fEnd - fStart, fName, 'CPP');
+    self.codeMap_.addStaticCode(fStart, entry);
+  });
+};
+
+CppProcessor.prototype.dumpCppSymbols = function() {
+  var staticEntries = this.codeMap_.getAllStaticEntriesWithAddresses();
+  var total = staticEntries.length;
+  for (var i = 0; i < total; ++i) {
+    var entry = staticEntries[i];
+    var printValues = ['cpp', '0x' + entry[0].toString(16), entry[1].size,
+                       '"' + entry[1].name + '"'];
+    print(printValues.join(','));
+  }
+};
diff --git a/tools/eval_gc_nvp.py b/tools/eval_gc_nvp.py
index fcb6d8b..25afe8e 100755
--- a/tools/eval_gc_nvp.py
+++ b/tools/eval_gc_nvp.py
@@ -10,7 +10,7 @@
 from argparse import ArgumentParser
 from copy import deepcopy
 from gc_nvp_common import split_nvp
-from math import log
+from math import ceil,log
 from sys import stdin
 
 
@@ -74,11 +74,12 @@
 
 
 class Category:
-  def __init__(self, key, histogram, csv):
+  def __init__(self, key, histogram, csv, percentiles):
     self.key = key
     self.values = []
     self.histogram = histogram
     self.csv = csv
+    self.percentiles = percentiles
 
   def process_entry(self, entry):
     if self.key in entry:
@@ -100,6 +101,16 @@
   def empty(self):
     return len(self.values) == 0
 
+  def _compute_percentiles(self):
+    ret = []
+    if len(self.values) == 0:
+      return ret
+    sorted_values = sorted(self.values)
+    for percentile in self.percentiles:
+      index = int(ceil((len(self.values) - 1) * percentile / 100))
+      ret.append("  {0}%: {1}".format(percentile, sorted_values[index]))
+    return ret
+
   def __str__(self):
     if self.csv:
       ret = [self.key]
@@ -118,6 +129,8 @@
         ret.append("  avg: {0}".format(self.avg()))
         if self.histogram:
           ret.append(str(self.histogram))
+        if self.percentiles:
+          ret.append("\n".join(self._compute_percentiles()))
       return "\n".join(ret)
 
   def __repr__(self):
@@ -160,6 +173,9 @@
                       help="rank keys by metric (default: no)")
   parser.add_argument('--csv', dest='csv',
                       action='store_true', help='provide output as csv')
+  parser.add_argument('--percentiles', dest='percentiles',
+                      type=str, default="",
+                      help='comma separated list of percentiles')
   args = parser.parse_args()
 
   histogram = None
@@ -171,7 +187,14 @@
       bucket_trait = LinearBucket(args.linear_histogram_granularity)
     histogram = Histogram(bucket_trait, not args.histogram_omit_empty)
 
-  categories = [ Category(key, deepcopy(histogram), args.csv)
+  percentiles = []
+  for percentile in args.percentiles.split(','):
+    try:
+      percentiles.append(float(percentile))
+    except ValueError:
+      pass
+
+  categories = [ Category(key, deepcopy(histogram), args.csv, percentiles)
                  for key in args.keys ]
 
   while True:
diff --git a/tools/eval_gc_time.sh b/tools/eval_gc_time.sh
index ceb4db5..140165d 100755
--- a/tools/eval_gc_time.sh
+++ b/tools/eval_gc_time.sh
@@ -17,6 +17,7 @@
   echo  "  -c|--csv                               provide csv output"
   echo  "  -f|--file FILE                         profile input in a file"
   echo  "                                         (default: stdin)"
+  echo  "  -p|--percentiles                       comma separated percentiles"
   exit 1
 }
 
@@ -25,6 +26,7 @@
 TOP_LEVEL=no
 CSV=""
 LOGFILE=/dev/stdin
+PERCENTILES=""
 
 while [[ $# -ge 1 ]]
 do
@@ -60,6 +62,10 @@
       LOGFILE=$2
       shift
       ;;
+    -p|--percentiles)
+      PERCENTILES="--percentiles=$2"
+      shift
+      ;;
     *)
       break
       ;;
@@ -98,7 +104,6 @@
   evacuate.clean_up \
   evacuate.copy \
   evacuate.update_pointers \
-  evacuate.update_pointers.between_evacuated \
   evacuate.update_pointers.to_evacuated \
   evacuate.update_pointers.to_new \
   evacuate.update_pointers.weak \
@@ -145,6 +150,7 @@
       --no-histogram \
       --rank $RANK_MODE \
       $CSV \
+      $PERCENTILES \
       ${INTERESTING_NEW_GEN_KEYS}
     ;;
   old-gen-rank)
@@ -153,6 +159,7 @@
       --no-histogram \
       --rank $RANK_MODE \
       $CSV \
+      $PERCENTILES \
       ${INTERESTING_OLD_GEN_KEYS}
     ;;
   *)
diff --git a/tools/gcmole/gcmole.lua b/tools/gcmole/gcmole.lua
index 82ea4e0..5c5e502 100644
--- a/tools/gcmole/gcmole.lua
+++ b/tools/gcmole/gcmole.lua
@@ -184,26 +184,26 @@
 -- GYP file parsing
 
 local function ParseGYPFile()
-   local gyp = ""
-   local gyp_files = { "tools/gyp/v8.gyp", "test/cctest/cctest.gyp" }
-   for i = 1, #gyp_files do
-      local f = assert(io.open(gyp_files[i]), "failed to open GYP file")
-      local t = f:read('*a')
-      gyp = gyp .. t
-      f:close()
-   end
-
    local result = {}
+   local gyp_files = {
+       { "src/v8.gyp",             "'([^']-%.cc)'",      "src/"         },
+       { "test/cctest/cctest.gyp", "'(test-[^']-%.cc)'", "test/cctest/" }
+   }
 
-   for condition, sources in
-      gyp:gmatch "'sources': %[.-### gcmole%((.-)%) ###(.-)%]" do
-      if result[condition] == nil then result[condition] = {} end
-      for file in sources:gmatch "'%.%./%.%./src/([^']-%.cc)'" do
-         table.insert(result[condition], "src/" .. file)
+   for i = 1, #gyp_files do
+      local filename = gyp_files[i][1]
+      local pattern = gyp_files[i][2]
+      local prefix = gyp_files[i][3]
+      local gyp_file = assert(io.open(filename), "failed to open GYP file")
+      local gyp = gyp_file:read('*a')
+      for condition, sources in
+         gyp:gmatch "'sources': %[.-### gcmole%((.-)%) ###(.-)%]" do
+         if result[condition] == nil then result[condition] = {} end
+         for file in sources:gmatch(pattern) do
+            table.insert(result[condition], prefix .. file)
+         end
       end
-      for file in sources:gmatch "'(test-[^']-%.cc)'" do
-         table.insert(result[condition], "test/cctest/" .. file)
-      end
+      gyp_file:close()
    end
 
    return result
diff --git a/tools/gcmole/run-gcmole.isolate b/tools/gcmole/run-gcmole.isolate
index df6e9a2..39990de 100644
--- a/tools/gcmole/run-gcmole.isolate
+++ b/tools/gcmole/run-gcmole.isolate
@@ -12,7 +12,6 @@
       'parallel.py',
       'run-gcmole.py',
       # The following contains all relevant source and gyp files.
-      '../gyp/v8.gyp',
       '../../base/',
       '../../include/',
       '../../src/',
diff --git a/tools/gcmole/run_gcmole.gyp b/tools/gcmole/run_gcmole.gyp
index 9d13f76..7d206bf 100644
--- a/tools/gcmole/run_gcmole.gyp
+++ b/tools/gcmole/run_gcmole.gyp
@@ -10,8 +10,8 @@
           'target_name': 'run_gcmole_run',
           'type': 'none',
           'includes': [
-            '../../build/features.gypi',
-            '../../build/isolate.gypi',
+            '../../gypfiles/features.gypi',
+            '../../gypfiles/isolate.gypi',
           ],
           'sources': [
             'run-gcmole.isolate',
diff --git a/tools/gen-postmortem-metadata.py b/tools/gen-postmortem-metadata.py
index a0afc06..a9e5b56 100644
--- a/tools/gen-postmortem-metadata.py
+++ b/tools/gen-postmortem-metadata.py
@@ -50,7 +50,8 @@
 import sys
 
 #
-# Miscellaneous constants, tags, and masks used for object identification.
+# Miscellaneous constants such as tags and masks used for object identification,
+# enumeration values used as indexes in internal tables, etc..
 #
 consts_misc = [
     { 'name': 'FirstNonstringType',     'value': 'FIRST_NONSTRING_TYPE' },
@@ -92,6 +93,8 @@
         'value': 'DescriptorArray::kFirstIndex' },
     { 'name': 'prop_type_field',
         'value': 'DATA' },
+    { 'name': 'prop_type_const_field',
+        'value': 'DATA_CONSTANT' },
     { 'name': 'prop_type_mask',
         'value': 'PropertyDetails::TypeField::kMask' },
     { 'name': 'prop_index_mask',
@@ -179,17 +182,46 @@
         'value': 'JSArrayBuffer::WasNeutered::kMask' },
     { 'name': 'jsarray_buffer_was_neutered_shift',
         'value': 'JSArrayBuffer::WasNeutered::kShift' },
+
+    { 'name': 'context_idx_closure',
+        'value': 'Context::CLOSURE_INDEX' },
+    { 'name': 'context_idx_native',
+        'value': 'Context::NATIVE_CONTEXT_INDEX' },
+    { 'name': 'context_idx_prev',
+        'value': 'Context::PREVIOUS_INDEX' },
+    { 'name': 'context_idx_ext',
+        'value': 'Context::EXTENSION_INDEX' },
+    { 'name': 'context_min_slots',
+        'value': 'Context::MIN_CONTEXT_SLOTS' },
+
+    { 'name': 'namedictionaryshape_prefix_size',
+        'value': 'NameDictionaryShape::kPrefixSize' },
+    { 'name': 'namedictionaryshape_entry_size',
+        'value': 'NameDictionaryShape::kEntrySize' },
+
+    { 'name': 'namedictionary_prefix_start_index',
+        'value': 'NameDictionary::kPrefixStartIndex' },
+
+    { 'name': 'seedednumberdictionaryshape_prefix_size',
+        'value': 'SeededNumberDictionaryShape::kPrefixSize' },
+
+    { 'name': 'unseedednumberdictionaryshape_prefix_size',
+        'value': 'UnseededNumberDictionaryShape::kPrefixSize' },
+
+    { 'name': 'numberdictionaryshape_entry_size',
+        'value': 'NumberDictionaryShape::kEntrySize' }
 ];
 
 #
 # The following useful fields are missing accessors, so we define fake ones.
+# Please note that extra accessors should _only_ be added to expose offsets that
+# can be used to access actual V8 objects' properties. They should not be added
+# for exposing other values. For instance, enumeration values or class'
+# constants should be exposed by adding an entry in the "consts_misc" table, not
+# in this "extras_accessors" table.
 #
 extras_accessors = [
     'JSFunction, context, Context, kContextOffset',
-    'Context, closure_index, int, CLOSURE_INDEX',
-    'Context, native_context_index, int, NATIVE_CONTEXT_INDEX',
-    'Context, previous_index, int, PREVIOUS_INDEX',
-    'Context, min_context_slots, int, MIN_CONTEXT_SLOTS',
     'HeapObject, map, Map, kMapOffset',
     'JSObject, elements, Object, kElementsOffset',
     'FixedArray, data, uintptr_t, kHeaderSize',
@@ -203,12 +235,6 @@
     'Map, bit_field2, char, kBitField2Offset',
     'Map, bit_field3, int, kBitField3Offset',
     'Map, prototype, Object, kPrototypeOffset',
-    'NameDictionaryShape, prefix_size, int, kPrefixSize',
-    'NameDictionaryShape, entry_size, int, kEntrySize',
-    'NameDictionary, prefix_start_index, int, kPrefixStartIndex',
-    'SeededNumberDictionaryShape, prefix_size, int, kPrefixSize',
-    'UnseededNumberDictionaryShape, prefix_size, int, kPrefixSize',
-    'NumberDictionaryShape, entry_size, int, kEntrySize',
     'Oddball, kind_offset, int, kKindOffset',
     'HeapNumber, value, double, kValueOffset',
     'ConsString, first, String, kFirstOffset',
@@ -252,6 +278,7 @@
 #include "src/v8.h"
 #include "src/frames.h"
 #include "src/frames-inl.h" /* for architecture-specific frame constants */
+#include "src/contexts.h"
 
 using namespace v8::internal;
 
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
deleted file mode 100644
index b09fd1f..0000000
--- a/tools/gyp/v8.gyp
+++ /dev/null
@@ -1,2281 +0,0 @@
-# Copyright 2012 the V8 project authors. All rights reserved.
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * 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.
-
-{
-  'variables': {
-    'icu_use_data_file_flag%': 0,
-    'v8_code': 1,
-    'v8_random_seed%': 314159265,
-    'v8_vector_stores%': 0,
-    'embed_script%': "",
-    'warmup_script%': "",
-    'v8_extra_library_files%': [],
-    'v8_experimental_extra_library_files%': [],
-    'mksnapshot_exec': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)mksnapshot<(EXECUTABLE_SUFFIX)',
-  },
-  'includes': ['../../build/toolchain.gypi', '../../build/features.gypi'],
-  'targets': [
-    {
-      'target_name': 'v8',
-      'dependencies_traverse': 1,
-      'dependencies': ['v8_maybe_snapshot'],
-      'conditions': [
-        ['want_separate_host_toolset==1', {
-          'toolsets': ['host', 'target'],
-        }, {
-          'toolsets': ['target'],
-        }],
-        ['component=="shared_library"', {
-          'type': '<(component)',
-          'sources': [
-            # Note: on non-Windows we still build this file so that gyp
-            # has some sources to link into the component.
-            '../../src/v8dll-main.cc',
-          ],
-          'include_dirs': [
-            '../..',
-          ],
-          'defines': [
-            'V8_SHARED',
-            'BUILDING_V8_SHARED',
-          ],
-          'direct_dependent_settings': {
-            'defines': [
-              'V8_SHARED',
-              'USING_V8_SHARED',
-            ],
-          },
-          'target_conditions': [
-            ['OS=="android" and _toolset=="target"', {
-              'libraries': [
-                '-llog',
-              ],
-              'include_dirs': [
-                'src/common/android/include',
-              ],
-            }],
-          ],
-          'conditions': [
-            ['OS=="mac"', {
-              'xcode_settings': {
-                'OTHER_LDFLAGS': ['-dynamiclib', '-all_load']
-              },
-            }],
-            ['soname_version!=""', {
-              'product_extension': 'so.<(soname_version)',
-            }],
-          ],
-        },
-        {
-          'type': 'none',
-        }],
-      ],
-      'direct_dependent_settings': {
-        'include_dirs': [
-          '../../include',
-        ],
-      },
-    },
-    {
-      # This rule delegates to either v8_snapshot, v8_nosnapshot, or
-      # v8_external_snapshot, depending on the current variables.
-      # The intention is to make the 'calling' rules a bit simpler.
-      'target_name': 'v8_maybe_snapshot',
-      'type': 'none',
-      'conditions': [
-        ['v8_use_snapshot!="true"', {
-          # The dependency on v8_base should come from a transitive
-          # dependency however the Android toolchain requires libv8_base.a
-          # to appear before libv8_snapshot.a so it's listed explicitly.
-          'dependencies': ['v8_base', 'v8_nosnapshot'],
-        }],
-        ['v8_use_snapshot=="true" and v8_use_external_startup_data==0', {
-          # The dependency on v8_base should come from a transitive
-          # dependency however the Android toolchain requires libv8_base.a
-          # to appear before libv8_snapshot.a so it's listed explicitly.
-          'dependencies': ['v8_base', 'v8_snapshot'],
-        }],
-        ['v8_use_snapshot=="true" and v8_use_external_startup_data==1 and want_separate_host_toolset==0', {
-          'dependencies': ['v8_base', 'v8_external_snapshot'],
-          'inputs': ['<(PRODUCT_DIR)/snapshot_blob.bin'],
-          'conditions': [
-            ['v8_separate_ignition_snapshot==1', {
-              'inputs': ['<(PRODUCT_DIR)/snapshot_blob_ignition.bin'],
-            }],
-          ]
-        }],
-        ['v8_use_snapshot=="true" and v8_use_external_startup_data==1 and want_separate_host_toolset==1', {
-          'dependencies': ['v8_base', 'v8_external_snapshot'],
-          'target_conditions': [
-            ['_toolset=="host"', {
-              'inputs': ['<(PRODUCT_DIR)/snapshot_blob_host.bin'],
-            }, {
-              'inputs': ['<(PRODUCT_DIR)/snapshot_blob.bin'],
-            }],
-          ],
-          'conditions': [
-            ['v8_separate_ignition_snapshot==1', {
-              'target_conditions': [
-                ['_toolset=="host"', {
-                  'inputs': ['<(PRODUCT_DIR)/snapshot_blob_ignition_host.bin'],
-                }, {
-                  'inputs': ['<(PRODUCT_DIR)/snapshot_blob_ignition.bin'],
-                }],
-              ],
-            }],
-          ],
-        }],
-        ['want_separate_host_toolset==1', {
-          'toolsets': ['host', 'target'],
-        }, {
-          'toolsets': ['target'],
-        }],
-      ]
-    },
-    {
-      'target_name': 'v8_snapshot',
-      'type': 'static_library',
-      'conditions': [
-        ['want_separate_host_toolset==1', {
-          'toolsets': ['host', 'target'],
-          'dependencies': [
-            'mksnapshot#host',
-            'js2c#host',
-          ],
-        }, {
-          'toolsets': ['target'],
-          'dependencies': [
-            'mksnapshot',
-            'js2c',
-          ],
-        }],
-        ['component=="shared_library"', {
-          'defines': [
-            'V8_SHARED',
-            'BUILDING_V8_SHARED',
-          ],
-          'direct_dependent_settings': {
-            'defines': [
-              'V8_SHARED',
-              'USING_V8_SHARED',
-            ],
-          },
-        }],
-      ],
-      'dependencies': [
-        'v8_base',
-      ],
-      'include_dirs+': [
-        '../..',
-      ],
-      'sources': [
-        '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
-        '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc',
-        '<(SHARED_INTERMEDIATE_DIR)/extras-libraries.cc',
-        '<(SHARED_INTERMEDIATE_DIR)/experimental-extras-libraries.cc',
-        '<(INTERMEDIATE_DIR)/snapshot.cc',
-      ],
-      'actions': [
-        {
-          'action_name': 'run_mksnapshot',
-          'inputs': [
-            '<(mksnapshot_exec)',
-            '<(embed_script)',
-            '<(warmup_script)',
-          ],
-          'outputs': [
-            '<(INTERMEDIATE_DIR)/snapshot.cc',
-          ],
-          'variables': {
-            'mksnapshot_flags': [],
-            'conditions': [
-              ['v8_random_seed!=0', {
-                'mksnapshot_flags': ['--random-seed', '<(v8_random_seed)'],
-              }],
-              ['v8_vector_stores!=0', {
-                'mksnapshot_flags': ['--vector-stores'],
-              }],
-            ],
-          },
-          'action': [
-            '<(mksnapshot_exec)',
-            '<@(mksnapshot_flags)',
-            '--startup_src', '<@(INTERMEDIATE_DIR)/snapshot.cc',
-            '<(embed_script)',
-            '<(warmup_script)',
-          ],
-        },
-      ],
-    },
-    {
-      'target_name': 'v8_nosnapshot',
-      'type': 'static_library',
-      'dependencies': [
-        'v8_base',
-      ],
-      'include_dirs+': [
-        '../..',
-      ],
-      'sources': [
-        '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
-        '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc',
-        '<(SHARED_INTERMEDIATE_DIR)/extras-libraries.cc',
-        '<(SHARED_INTERMEDIATE_DIR)/experimental-extras-libraries.cc',
-        '../../src/snapshot/snapshot-empty.cc',
-      ],
-      'conditions': [
-        ['want_separate_host_toolset==1', {
-          'toolsets': ['host', 'target'],
-          'dependencies': ['js2c#host'],
-        }, {
-          'toolsets': ['target'],
-          'dependencies': ['js2c'],
-        }],
-        ['component=="shared_library"', {
-          'defines': [
-            'BUILDING_V8_SHARED',
-            'V8_SHARED',
-          ],
-        }],
-      ]
-    },
-    {
-      'target_name': 'v8_external_snapshot',
-      'type': 'static_library',
-      'conditions': [
-        [ 'v8_use_external_startup_data==1', {
-          'conditions': [
-            ['want_separate_host_toolset==1', {
-              'toolsets': ['host', 'target'],
-              'dependencies': [
-                'mksnapshot#host',
-                'js2c#host',
-                'natives_blob',
-            ]}, {
-              'toolsets': ['target'],
-              'dependencies': [
-                'mksnapshot',
-                'js2c',
-                'natives_blob',
-              ],
-            }],
-            ['component=="shared_library"', {
-              'defines': [
-                'V8_SHARED',
-                'BUILDING_V8_SHARED',
-              ],
-              'direct_dependent_settings': {
-                'defines': [
-                  'V8_SHARED',
-                  'USING_V8_SHARED',
-                ],
-              },
-            }],
-            # Extra snapshot blob for ignition.
-            ['v8_separate_ignition_snapshot==1', {
-              # This is concatenated to the other actions list of
-              # v8_external_snapshot.
-              'actions': [
-                {
-                  'action_name': 'run_mksnapshot (ignition)',
-                  'inputs': ['<(mksnapshot_exec)'],
-                  'variables': {
-                    # TODO: Extract common mksnapshot_flags to a separate
-                    # variable.
-                    'mksnapshot_flags_ignition': [
-                      '--ignition',
-                    ],
-                    'conditions': [
-                      ['v8_random_seed!=0', {
-                        'mksnapshot_flags_ignition': ['--random-seed', '<(v8_random_seed)'],
-                      }],
-                      ['v8_vector_stores!=0', {
-                        'mksnapshot_flags_ignition': ['--vector-stores'],
-                      }],
-                    ],
-                  },
-                  'conditions': [
-                    ['want_separate_host_toolset==1', {
-                      'target_conditions': [
-                        ['_toolset=="host"', {
-                          'outputs': ['<(PRODUCT_DIR)/snapshot_blob_ignition_host.bin'],
-                          'action': [
-                            '<(mksnapshot_exec)',
-                            '<@(mksnapshot_flags_ignition)',
-                            '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob_ignition_host.bin',
-                            '<(embed_script)',
-                            '<(warmup_script)',
-                          ],
-                        }, {
-                          'outputs': ['<(PRODUCT_DIR)/snapshot_blob_ignition.bin'],
-                          'action': [
-                            '<(mksnapshot_exec)',
-                            '<@(mksnapshot_flags_ignition)',
-                            '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob_ignition.bin',
-                            '<(embed_script)',
-                            '<(warmup_script)',
-                          ],
-                        }],
-                      ],
-                    }, {
-                      'outputs': ['<(PRODUCT_DIR)/snapshot_blob_ignition.bin'],
-                      'action': [
-                        '<(mksnapshot_exec)',
-                        '<@(mksnapshot_flags_ignition)',
-                        '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob_ignition.bin',
-                        '<(embed_script)',
-                        '<(warmup_script)',
-                      ],
-                    }],
-                  ],
-                },
-              ],
-            }],
-          ],
-          'dependencies': [
-            'v8_base',
-          ],
-          'include_dirs+': [
-            '../..',
-          ],
-          'sources': [
-            '../../src/snapshot/natives-external.cc',
-            '../../src/snapshot/snapshot-external.cc',
-          ],
-          'actions': [
-            {
-              'action_name': 'run_mksnapshot (external)',
-              'inputs': ['<(mksnapshot_exec)'],
-              'variables': {
-                'mksnapshot_flags': [],
-                'conditions': [
-                  ['v8_random_seed!=0', {
-                    'mksnapshot_flags': ['--random-seed', '<(v8_random_seed)'],
-                  }],
-                  ['v8_vector_stores!=0', {
-                    'mksnapshot_flags': ['--vector-stores'],
-                  }],
-                ],
-              },
-              'conditions': [
-                ['want_separate_host_toolset==1', {
-                  'target_conditions': [
-                    ['_toolset=="host"', {
-                      'outputs': ['<(PRODUCT_DIR)/snapshot_blob_host.bin'],
-                      'action': [
-                        '<(mksnapshot_exec)',
-                        '<@(mksnapshot_flags)',
-                        '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob_host.bin',
-                        '<(embed_script)',
-                        '<(warmup_script)',
-                      ],
-                    }, {
-                      'outputs': ['<(PRODUCT_DIR)/snapshot_blob.bin'],
-                      'action': [
-                        '<(mksnapshot_exec)',
-                        '<@(mksnapshot_flags)',
-                        '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob.bin',
-                        '<(embed_script)',
-                        '<(warmup_script)',
-                      ],
-                    }],
-                  ],
-                }, {
-                  'outputs': ['<(PRODUCT_DIR)/snapshot_blob.bin'],
-                  'action': [
-                    '<(mksnapshot_exec)',
-                    '<@(mksnapshot_flags)',
-                    '--startup_blob', '<(PRODUCT_DIR)/snapshot_blob.bin',
-                    '<(embed_script)',
-                    '<(warmup_script)',
-                  ],
-                }],
-              ],
-            },
-          ],
-        }],
-      ],
-    },
-    {
-      'target_name': 'v8_base',
-      'type': 'static_library',
-      'dependencies': [
-        'v8_libbase',
-      ],
-      'variables': {
-        'optimize': 'max',
-      },
-      'include_dirs+': [
-        '../..',
-        # To be able to find base/trace_event/common/trace_event_common.h
-        '../../..',
-      ],
-      'defines': [
-        # TODO(jochen): Remove again after this is globally turned on.
-        'V8_IMMINENT_DEPRECATION_WARNINGS',
-      ],
-      'sources': [  ### gcmole(all) ###
-        '../../include/v8-debug.h',
-        '../../include/v8-experimental.h',
-        '../../include/v8-platform.h',
-        '../../include/v8-profiler.h',
-        '../../include/v8-testing.h',
-        '../../include/v8-util.h',
-        '../../include/v8-version.h',
-        '../../include/v8.h',
-        '../../include/v8config.h',
-        '../../src/accessors.cc',
-        '../../src/accessors.h',
-        '../../src/address-map.cc',
-        '../../src/address-map.h',
-        '../../src/allocation.cc',
-        '../../src/allocation.h',
-        '../../src/allocation-site-scopes.cc',
-        '../../src/allocation-site-scopes.h',
-        '../../src/api-experimental.cc',
-        '../../src/api-experimental.h',
-        '../../src/api.cc',
-        '../../src/api.h',
-        '../../src/api-arguments.cc',
-        '../../src/api-arguments.h',
-        '../../src/api-natives.cc',
-        '../../src/api-natives.h',
-        '../../src/arguments.cc',
-        '../../src/arguments.h',
-        '../../src/assembler.cc',
-        '../../src/assembler.h',
-        '../../src/assert-scope.h',
-        '../../src/assert-scope.cc',
-        '../../src/ast/ast-expression-rewriter.cc',
-        '../../src/ast/ast-expression-rewriter.h',
-        '../../src/ast/ast-expression-visitor.cc',
-        '../../src/ast/ast-expression-visitor.h',
-        '../../src/ast/ast-literal-reindexer.cc',
-        '../../src/ast/ast-literal-reindexer.h',
-        '../../src/ast/ast-numbering.cc',
-        '../../src/ast/ast-numbering.h',
-        '../../src/ast/ast-value-factory.cc',
-        '../../src/ast/ast-value-factory.h',
-        '../../src/ast/ast.cc',
-        '../../src/ast/ast.h',
-        '../../src/ast/modules.cc',
-        '../../src/ast/modules.h',
-        '../../src/ast/prettyprinter.cc',
-        '../../src/ast/prettyprinter.h',
-        '../../src/ast/scopeinfo.cc',
-        '../../src/ast/scopeinfo.h',
-        '../../src/ast/scopes.cc',
-        '../../src/ast/scopes.h',
-        '../../src/ast/variables.cc',
-        '../../src/ast/variables.h',
-        '../../src/atomic-utils.h',
-        '../../src/background-parsing-task.cc',
-        '../../src/background-parsing-task.h',
-        '../../src/bailout-reason.cc',
-        '../../src/bailout-reason.h',
-        '../../src/basic-block-profiler.cc',
-        '../../src/basic-block-profiler.h',
-        '../../src/bignum-dtoa.cc',
-        '../../src/bignum-dtoa.h',
-        '../../src/bignum.cc',
-        '../../src/bignum.h',
-        '../../src/bit-vector.cc',
-        '../../src/bit-vector.h',
-        '../../src/bootstrapper.cc',
-        '../../src/bootstrapper.h',
-        '../../src/builtins.cc',
-        '../../src/builtins.h',
-        '../../src/cached-powers.cc',
-        '../../src/cached-powers.h',
-        '../../src/cancelable-task.cc',
-        '../../src/cancelable-task.h',
-        '../../src/char-predicates.cc',
-        '../../src/char-predicates-inl.h',
-        '../../src/char-predicates.h',
-        '../../src/checks.h',
-        '../../src/code-factory.cc',
-        '../../src/code-factory.h',
-        '../../src/code-stubs.cc',
-        '../../src/code-stubs.h',
-        '../../src/code-stubs-hydrogen.cc',
-        '../../src/codegen.cc',
-        '../../src/codegen.h',
-        '../../src/collector.h',
-        '../../src/compilation-cache.cc',
-        '../../src/compilation-cache.h',
-        '../../src/compilation-dependencies.cc',
-        '../../src/compilation-dependencies.h',
-        '../../src/compilation-statistics.cc',
-        '../../src/compilation-statistics.h',
-        '../../src/compiler/access-builder.cc',
-        '../../src/compiler/access-builder.h',
-        '../../src/compiler/access-info.cc',
-        '../../src/compiler/access-info.h',
-        '../../src/compiler/all-nodes.cc',
-        '../../src/compiler/all-nodes.h',
-        '../../src/compiler/ast-graph-builder.cc',
-        '../../src/compiler/ast-graph-builder.h',
-        '../../src/compiler/ast-loop-assignment-analyzer.cc',
-        '../../src/compiler/ast-loop-assignment-analyzer.h',
-        '../../src/compiler/basic-block-instrumentor.cc',
-        '../../src/compiler/basic-block-instrumentor.h',
-        '../../src/compiler/branch-elimination.cc',
-        '../../src/compiler/branch-elimination.h',
-        '../../src/compiler/bytecode-branch-analysis.cc',
-        '../../src/compiler/bytecode-branch-analysis.h',
-        '../../src/compiler/bytecode-graph-builder.cc',
-        '../../src/compiler/bytecode-graph-builder.h',
-        '../../src/compiler/change-lowering.cc',
-        '../../src/compiler/change-lowering.h',
-        '../../src/compiler/c-linkage.cc',
-        '../../src/compiler/coalesced-live-ranges.cc',
-        '../../src/compiler/coalesced-live-ranges.h',
-        '../../src/compiler/code-generator-impl.h',
-        '../../src/compiler/code-generator.cc',
-        '../../src/compiler/code-generator.h',
-        '../../src/compiler/code-stub-assembler.cc',
-        '../../src/compiler/code-stub-assembler.h',
-        '../../src/compiler/common-node-cache.cc',
-        '../../src/compiler/common-node-cache.h',
-        '../../src/compiler/common-operator-reducer.cc',
-        '../../src/compiler/common-operator-reducer.h',
-        '../../src/compiler/common-operator.cc',
-        '../../src/compiler/common-operator.h',
-        '../../src/compiler/control-builders.cc',
-        '../../src/compiler/control-builders.h',
-        '../../src/compiler/control-equivalence.cc',
-        '../../src/compiler/control-equivalence.h',
-        '../../src/compiler/control-flow-optimizer.cc',
-        '../../src/compiler/control-flow-optimizer.h',
-        '../../src/compiler/dead-code-elimination.cc',
-        '../../src/compiler/dead-code-elimination.h',
-        '../../src/compiler/diamond.h',
-        '../../src/compiler/escape-analysis.cc',
-        '../../src/compiler/escape-analysis.h',
-        "../../src/compiler/escape-analysis-reducer.cc",
-        "../../src/compiler/escape-analysis-reducer.h",
-        '../../src/compiler/frame.cc',
-        '../../src/compiler/frame.h',
-        '../../src/compiler/frame-elider.cc',
-        '../../src/compiler/frame-elider.h',
-        "../../src/compiler/frame-states.cc",
-        "../../src/compiler/frame-states.h",
-        '../../src/compiler/gap-resolver.cc',
-        '../../src/compiler/gap-resolver.h',
-        '../../src/compiler/graph-reducer.cc',
-        '../../src/compiler/graph-reducer.h',
-        '../../src/compiler/graph-replay.cc',
-        '../../src/compiler/graph-replay.h',
-        '../../src/compiler/graph-trimmer.cc',
-        '../../src/compiler/graph-trimmer.h',
-        '../../src/compiler/graph-visualizer.cc',
-        '../../src/compiler/graph-visualizer.h',
-        '../../src/compiler/graph.cc',
-        '../../src/compiler/graph.h',
-        '../../src/compiler/greedy-allocator.cc',
-        '../../src/compiler/greedy-allocator.h',
-        '../../src/compiler/instruction-codes.h',
-        '../../src/compiler/instruction-selector-impl.h',
-        '../../src/compiler/instruction-selector.cc',
-        '../../src/compiler/instruction-selector.h',
-        '../../src/compiler/instruction-scheduler.cc',
-        '../../src/compiler/instruction-scheduler.h',
-        '../../src/compiler/instruction.cc',
-        '../../src/compiler/instruction.h',
-        '../../src/compiler/int64-lowering.cc',
-        '../../src/compiler/int64-lowering.h',
-        '../../src/compiler/js-builtin-reducer.cc',
-        '../../src/compiler/js-builtin-reducer.h',
-        '../../src/compiler/js-call-reducer.cc',
-        '../../src/compiler/js-call-reducer.h',
-        '../../src/compiler/js-context-specialization.cc',
-        '../../src/compiler/js-context-specialization.h',
-        '../../src/compiler/js-create-lowering.cc',
-        '../../src/compiler/js-create-lowering.h',
-        '../../src/compiler/js-frame-specialization.cc',
-        '../../src/compiler/js-frame-specialization.h',
-        '../../src/compiler/js-generic-lowering.cc',
-        '../../src/compiler/js-generic-lowering.h',
-        '../../src/compiler/js-global-object-specialization.cc',
-        '../../src/compiler/js-global-object-specialization.h',
-        '../../src/compiler/js-graph.cc',
-        '../../src/compiler/js-graph.h',
-        '../../src/compiler/js-inlining.cc',
-        '../../src/compiler/js-inlining.h',
-        '../../src/compiler/js-inlining-heuristic.cc',
-        '../../src/compiler/js-inlining-heuristic.h',
-        '../../src/compiler/js-intrinsic-lowering.cc',
-        '../../src/compiler/js-intrinsic-lowering.h',
-        '../../src/compiler/js-native-context-specialization.cc',
-        '../../src/compiler/js-native-context-specialization.h',
-        '../../src/compiler/js-operator.cc',
-        '../../src/compiler/js-operator.h',
-        '../../src/compiler/js-typed-lowering.cc',
-        '../../src/compiler/js-typed-lowering.h',
-        '../../src/compiler/jump-threading.cc',
-        '../../src/compiler/jump-threading.h',
-        '../../src/compiler/linkage.cc',
-        '../../src/compiler/linkage.h',
-        '../../src/compiler/liveness-analyzer.cc',
-        '../../src/compiler/liveness-analyzer.h',
-        '../../src/compiler/live-range-separator.cc',
-        '../../src/compiler/live-range-separator.h',
-        '../../src/compiler/load-elimination.cc',
-        '../../src/compiler/load-elimination.h',
-        '../../src/compiler/loop-analysis.cc',
-        '../../src/compiler/loop-analysis.h',
-        '../../src/compiler/loop-peeling.cc',
-        '../../src/compiler/loop-peeling.h',
-        '../../src/compiler/machine-operator-reducer.cc',
-        '../../src/compiler/machine-operator-reducer.h',
-        '../../src/compiler/machine-operator.cc',
-        '../../src/compiler/machine-operator.h',
-        '../../src/compiler/move-optimizer.cc',
-        '../../src/compiler/move-optimizer.h',
-        '../../src/compiler/node-aux-data.h',
-        '../../src/compiler/node-cache.cc',
-        '../../src/compiler/node-cache.h',
-        '../../src/compiler/node-marker.cc',
-        '../../src/compiler/node-marker.h',
-        '../../src/compiler/node-matchers.cc',
-        '../../src/compiler/node-matchers.h',
-        '../../src/compiler/node-properties.cc',
-        '../../src/compiler/node-properties.h',
-        '../../src/compiler/node.cc',
-        '../../src/compiler/node.h',
-        '../../src/compiler/opcodes.cc',
-        '../../src/compiler/opcodes.h',
-        '../../src/compiler/operator-properties.cc',
-        '../../src/compiler/operator-properties.h',
-        '../../src/compiler/operator.cc',
-        '../../src/compiler/operator.h',
-        '../../src/compiler/osr.cc',
-        '../../src/compiler/osr.h',
-        '../../src/compiler/pipeline.cc',
-        '../../src/compiler/pipeline.h',
-        '../../src/compiler/pipeline-statistics.cc',
-        '../../src/compiler/pipeline-statistics.h',
-        '../../src/compiler/raw-machine-assembler.cc',
-        '../../src/compiler/raw-machine-assembler.h',
-        '../../src/compiler/register-allocator.cc',
-        '../../src/compiler/register-allocator.h',
-        '../../src/compiler/register-allocator-verifier.cc',
-        '../../src/compiler/register-allocator-verifier.h',
-        '../../src/compiler/representation-change.cc',
-        '../../src/compiler/representation-change.h',
-        '../../src/compiler/schedule.cc',
-        '../../src/compiler/schedule.h',
-        '../../src/compiler/scheduler.cc',
-        '../../src/compiler/scheduler.h',
-        '../../src/compiler/select-lowering.cc',
-        '../../src/compiler/select-lowering.h',
-        '../../src/compiler/simplified-lowering.cc',
-        '../../src/compiler/simplified-lowering.h',
-        '../../src/compiler/simplified-operator-reducer.cc',
-        '../../src/compiler/simplified-operator-reducer.h',
-        '../../src/compiler/simplified-operator.cc',
-        '../../src/compiler/simplified-operator.h',
-        '../../src/compiler/source-position.cc',
-        '../../src/compiler/source-position.h',
-        '../../src/compiler/state-values-utils.cc',
-        '../../src/compiler/state-values-utils.h',
-        '../../src/compiler/tail-call-optimization.cc',
-        '../../src/compiler/tail-call-optimization.h',
-        '../../src/compiler/type-hint-analyzer.cc',
-        '../../src/compiler/type-hint-analyzer.h',
-        '../../src/compiler/type-hints.cc',
-        '../../src/compiler/type-hints.h',
-        '../../src/compiler/typer.cc',
-        '../../src/compiler/typer.h',
-        '../../src/compiler/value-numbering-reducer.cc',
-        '../../src/compiler/value-numbering-reducer.h',
-        '../../src/compiler/verifier.cc',
-        '../../src/compiler/verifier.h',
-        '../../src/compiler/wasm-compiler.cc',
-        '../../src/compiler/wasm-compiler.h',
-        '../../src/compiler/wasm-linkage.cc',
-        '../../src/compiler/zone-pool.cc',
-        '../../src/compiler/zone-pool.h',
-        '../../src/compiler.cc',
-        '../../src/compiler.h',
-        '../../src/context-measure.cc',
-        '../../src/context-measure.h',
-        '../../src/contexts-inl.h',
-        '../../src/contexts.cc',
-        '../../src/contexts.h',
-        '../../src/conversions-inl.h',
-        '../../src/conversions.cc',
-        '../../src/conversions.h',
-        '../../src/counters.cc',
-        '../../src/counters.h',
-        '../../src/crankshaft/compilation-phase.cc',
-        '../../src/crankshaft/compilation-phase.h',
-        '../../src/crankshaft/hydrogen-alias-analysis.h',
-        '../../src/crankshaft/hydrogen-bce.cc',
-        '../../src/crankshaft/hydrogen-bce.h',
-        '../../src/crankshaft/hydrogen-canonicalize.cc',
-        '../../src/crankshaft/hydrogen-canonicalize.h',
-        '../../src/crankshaft/hydrogen-check-elimination.cc',
-        '../../src/crankshaft/hydrogen-check-elimination.h',
-        '../../src/crankshaft/hydrogen-dce.cc',
-        '../../src/crankshaft/hydrogen-dce.h',
-        '../../src/crankshaft/hydrogen-dehoist.cc',
-        '../../src/crankshaft/hydrogen-dehoist.h',
-        '../../src/crankshaft/hydrogen-environment-liveness.cc',
-        '../../src/crankshaft/hydrogen-environment-liveness.h',
-        '../../src/crankshaft/hydrogen-escape-analysis.cc',
-        '../../src/crankshaft/hydrogen-escape-analysis.h',
-        '../../src/crankshaft/hydrogen-flow-engine.h',
-        '../../src/crankshaft/hydrogen-gvn.cc',
-        '../../src/crankshaft/hydrogen-gvn.h',
-        '../../src/crankshaft/hydrogen-infer-representation.cc',
-        '../../src/crankshaft/hydrogen-infer-representation.h',
-        '../../src/crankshaft/hydrogen-infer-types.cc',
-        '../../src/crankshaft/hydrogen-infer-types.h',
-        '../../src/crankshaft/hydrogen-instructions.cc',
-        '../../src/crankshaft/hydrogen-instructions.h',
-        '../../src/crankshaft/hydrogen-load-elimination.cc',
-        '../../src/crankshaft/hydrogen-load-elimination.h',
-        '../../src/crankshaft/hydrogen-mark-deoptimize.cc',
-        '../../src/crankshaft/hydrogen-mark-deoptimize.h',
-        '../../src/crankshaft/hydrogen-mark-unreachable.cc',
-        '../../src/crankshaft/hydrogen-mark-unreachable.h',
-        '../../src/crankshaft/hydrogen-osr.cc',
-        '../../src/crankshaft/hydrogen-osr.h',
-        '../../src/crankshaft/hydrogen-range-analysis.cc',
-        '../../src/crankshaft/hydrogen-range-analysis.h',
-        '../../src/crankshaft/hydrogen-redundant-phi.cc',
-        '../../src/crankshaft/hydrogen-redundant-phi.h',
-        '../../src/crankshaft/hydrogen-removable-simulates.cc',
-        '../../src/crankshaft/hydrogen-removable-simulates.h',
-        '../../src/crankshaft/hydrogen-representation-changes.cc',
-        '../../src/crankshaft/hydrogen-representation-changes.h',
-        '../../src/crankshaft/hydrogen-sce.cc',
-        '../../src/crankshaft/hydrogen-sce.h',
-        '../../src/crankshaft/hydrogen-store-elimination.cc',
-        '../../src/crankshaft/hydrogen-store-elimination.h',
-        '../../src/crankshaft/hydrogen-types.cc',
-        '../../src/crankshaft/hydrogen-types.h',
-        '../../src/crankshaft/hydrogen-uint32-analysis.cc',
-        '../../src/crankshaft/hydrogen-uint32-analysis.h',
-        '../../src/crankshaft/hydrogen.cc',
-        '../../src/crankshaft/hydrogen.h',
-        '../../src/crankshaft/lithium-allocator-inl.h',
-        '../../src/crankshaft/lithium-allocator.cc',
-        '../../src/crankshaft/lithium-allocator.h',
-        '../../src/crankshaft/lithium-codegen.cc',
-        '../../src/crankshaft/lithium-codegen.h',
-        '../../src/crankshaft/lithium.cc',
-        '../../src/crankshaft/lithium.h',
-        '../../src/crankshaft/lithium-inl.h',
-        '../../src/crankshaft/typing.cc',
-        '../../src/crankshaft/typing.h',
-        '../../src/crankshaft/unique.h',
-        '../../src/date.cc',
-        '../../src/date.h',
-        '../../src/dateparser-inl.h',
-        '../../src/dateparser.cc',
-        '../../src/dateparser.h',
-        '../../src/debug/debug-evaluate.cc',
-        '../../src/debug/debug-evaluate.h',
-        '../../src/debug/debug-frames.cc',
-        '../../src/debug/debug-frames.h',
-        '../../src/debug/debug-scopes.cc',
-        '../../src/debug/debug-scopes.h',
-        '../../src/debug/debug.cc',
-        '../../src/debug/debug.h',
-        '../../src/debug/liveedit.cc',
-        '../../src/debug/liveedit.h',
-        '../../src/deoptimizer.cc',
-        '../../src/deoptimizer.h',
-        '../../src/disasm.h',
-        '../../src/disassembler.cc',
-        '../../src/disassembler.h',
-        '../../src/diy-fp.cc',
-        '../../src/diy-fp.h',
-        '../../src/double.h',
-        '../../src/dtoa.cc',
-        '../../src/dtoa.h',
-        '../../src/effects.h',
-        '../../src/elements-kind.cc',
-        '../../src/elements-kind.h',
-        '../../src/elements.cc',
-        '../../src/elements.h',
-        '../../src/execution.cc',
-        '../../src/execution.h',
-        '../../src/extensions/externalize-string-extension.cc',
-        '../../src/extensions/externalize-string-extension.h',
-        '../../src/extensions/free-buffer-extension.cc',
-        '../../src/extensions/free-buffer-extension.h',
-        '../../src/extensions/gc-extension.cc',
-        '../../src/extensions/gc-extension.h',
-        '../../src/extensions/statistics-extension.cc',
-        '../../src/extensions/statistics-extension.h',
-        '../../src/extensions/trigger-failure-extension.cc',
-        '../../src/extensions/trigger-failure-extension.h',
-        '../../src/external-reference-table.cc',
-        '../../src/external-reference-table.h',
-        '../../src/factory.cc',
-        '../../src/factory.h',
-        '../../src/fast-accessor-assembler.cc',
-        '../../src/fast-accessor-assembler.h',
-        '../../src/fast-dtoa.cc',
-        '../../src/fast-dtoa.h',
-        '../../src/field-index.h',
-        '../../src/field-index-inl.h',
-        '../../src/field-type.cc',
-        '../../src/field-type.h',
-        '../../src/fixed-dtoa.cc',
-        '../../src/fixed-dtoa.h',
-        '../../src/flag-definitions.h',
-        '../../src/flags.cc',
-        '../../src/flags.h',
-        '../../src/frames-inl.h',
-        '../../src/frames.cc',
-        '../../src/frames.h',
-        '../../src/full-codegen/full-codegen.cc',
-        '../../src/full-codegen/full-codegen.h',
-        '../../src/futex-emulation.cc',
-        '../../src/futex-emulation.h',
-        '../../src/gdb-jit.cc',
-        '../../src/gdb-jit.h',
-        '../../src/global-handles.cc',
-        '../../src/global-handles.h',
-        '../../src/globals.h',
-        '../../src/handles-inl.h',
-        '../../src/handles.cc',
-        '../../src/handles.h',
-        '../../src/hashmap.h',
-        '../../src/heap-symbols.h',
-        '../../src/heap/array-buffer-tracker.cc',
-        '../../src/heap/array-buffer-tracker.h',
-        '../../src/heap/memory-reducer.cc',
-        '../../src/heap/memory-reducer.h',
-        '../../src/heap/gc-idle-time-handler.cc',
-        '../../src/heap/gc-idle-time-handler.h',
-        '../../src/heap/gc-tracer.cc',
-        '../../src/heap/gc-tracer.h',
-        '../../src/heap/heap-inl.h',
-        '../../src/heap/heap.cc',
-        '../../src/heap/heap.h',
-        '../../src/heap/incremental-marking-inl.h',
-        '../../src/heap/incremental-marking-job.cc',
-        '../../src/heap/incremental-marking-job.h',
-        '../../src/heap/incremental-marking.cc',
-        '../../src/heap/incremental-marking.h',
-        '../../src/heap/mark-compact-inl.h',
-        '../../src/heap/mark-compact.cc',
-        '../../src/heap/mark-compact.h',
-        '../../src/heap/object-stats.cc',
-        '../../src/heap/object-stats.h',
-        '../../src/heap/objects-visiting-inl.h',
-        '../../src/heap/objects-visiting.cc',
-        '../../src/heap/objects-visiting.h',
-        '../../src/heap/page-parallel-job.h',
-        '../../src/heap/remembered-set.cc',
-        '../../src/heap/remembered-set.h',
-        '../../src/heap/scavenge-job.h',
-        '../../src/heap/scavenge-job.cc',
-        '../../src/heap/scavenger-inl.h',
-        '../../src/heap/scavenger.cc',
-        '../../src/heap/scavenger.h',
-        '../../src/heap/slot-set.h',
-        '../../src/heap/spaces-inl.h',
-        '../../src/heap/spaces.cc',
-        '../../src/heap/spaces.h',
-        '../../src/heap/store-buffer.cc',
-        '../../src/heap/store-buffer.h',
-        '../../src/i18n.cc',
-        '../../src/i18n.h',
-        '../../src/icu_util.cc',
-        '../../src/icu_util.h',
-        '../../src/ic/access-compiler.cc',
-        '../../src/ic/access-compiler.h',
-        '../../src/ic/call-optimization.cc',
-        '../../src/ic/call-optimization.h',
-        '../../src/ic/handler-compiler.cc',
-        '../../src/ic/handler-compiler.h',
-        '../../src/ic/ic-inl.h',
-        '../../src/ic/ic-state.cc',
-        '../../src/ic/ic-state.h',
-        '../../src/ic/ic.cc',
-        '../../src/ic/ic.h',
-        '../../src/ic/ic-compiler.cc',
-        '../../src/ic/ic-compiler.h',
-        '../../src/identity-map.cc',
-        '../../src/identity-map.h',
-        '../../src/interface-descriptors.cc',
-        '../../src/interface-descriptors.h',
-        '../../src/interpreter/bytecodes.cc',
-        '../../src/interpreter/bytecodes.h',
-        '../../src/interpreter/bytecode-array-builder.cc',
-        '../../src/interpreter/bytecode-array-builder.h',
-        '../../src/interpreter/bytecode-array-iterator.cc',
-        '../../src/interpreter/bytecode-array-iterator.h',
-        '../../src/interpreter/bytecode-register-allocator.cc',
-        '../../src/interpreter/bytecode-register-allocator.h',
-        '../../src/interpreter/bytecode-generator.cc',
-        '../../src/interpreter/bytecode-generator.h',
-        '../../src/interpreter/bytecode-traits.h',
-        '../../src/interpreter/constant-array-builder.cc',
-        '../../src/interpreter/constant-array-builder.h',
-        '../../src/interpreter/control-flow-builders.cc',
-        '../../src/interpreter/control-flow-builders.h',
-        '../../src/interpreter/handler-table-builder.cc',
-        '../../src/interpreter/handler-table-builder.h',
-        '../../src/interpreter/interpreter.cc',
-        '../../src/interpreter/interpreter.h',
-        '../../src/interpreter/interpreter-assembler.cc',
-        '../../src/interpreter/interpreter-assembler.h',
-        '../../src/interpreter/interpreter-intrinsics.cc',
-        '../../src/interpreter/interpreter-intrinsics.h',
-        '../../src/interpreter/source-position-table.cc',
-        '../../src/interpreter/source-position-table.h',
-        '../../src/isolate-inl.h',
-        '../../src/isolate.cc',
-        '../../src/isolate.h',
-        '../../src/json-parser.h',
-        '../../src/json-stringifier.h',
-        '../../src/keys.h',
-        '../../src/keys.cc',
-        '../../src/layout-descriptor-inl.h',
-        '../../src/layout-descriptor.cc',
-        '../../src/layout-descriptor.h',
-        '../../src/list-inl.h',
-        '../../src/list.h',
-        '../../src/locked-queue-inl.h',
-        '../../src/locked-queue.h',
-        '../../src/log-inl.h',
-        '../../src/log-utils.cc',
-        '../../src/log-utils.h',
-        '../../src/log.cc',
-        '../../src/log.h',
-        '../../src/lookup.cc',
-        '../../src/lookup.h',
-        '../../src/macro-assembler.h',
-        '../../src/machine-type.cc',
-        '../../src/machine-type.h',
-        '../../src/messages.cc',
-        '../../src/messages.h',
-        '../../src/msan.h',
-        '../../src/objects-body-descriptors-inl.h',
-        '../../src/objects-body-descriptors.h',
-        '../../src/objects-debug.cc',
-        '../../src/objects-inl.h',
-        '../../src/objects-printer.cc',
-        '../../src/objects.cc',
-        '../../src/objects.h',
-        '../../src/optimizing-compile-dispatcher.cc',
-        '../../src/optimizing-compile-dispatcher.h',
-        '../../src/ostreams.cc',
-        '../../src/ostreams.h',
-        '../../src/parsing/expression-classifier.h',
-        '../../src/parsing/func-name-inferrer.cc',
-        '../../src/parsing/func-name-inferrer.h',
-        '../../src/parsing/parameter-initializer-rewriter.cc',
-        '../../src/parsing/parameter-initializer-rewriter.h',
-        '../../src/parsing/parser-base.h',
-        '../../src/parsing/parser.cc',
-        '../../src/parsing/parser.h',
-        '../../src/parsing/pattern-rewriter.cc',
-        '../../src/parsing/preparse-data-format.h',
-        '../../src/parsing/preparse-data.cc',
-        '../../src/parsing/preparse-data.h',
-        '../../src/parsing/preparser.cc',
-        '../../src/parsing/preparser.h',
-        '../../src/parsing/rewriter.cc',
-        '../../src/parsing/rewriter.h',
-        '../../src/parsing/scanner-character-streams.cc',
-        '../../src/parsing/scanner-character-streams.h',
-        '../../src/parsing/scanner.cc',
-        '../../src/parsing/scanner.h',
-        '../../src/parsing/token.cc',
-        '../../src/parsing/token.h',
-        '../../src/pending-compilation-error-handler.cc',
-        '../../src/pending-compilation-error-handler.h',
-        '../../src/perf-jit.cc',
-        '../../src/perf-jit.h',
-        '../../src/profiler/allocation-tracker.cc',
-        '../../src/profiler/allocation-tracker.h',
-        '../../src/profiler/circular-queue-inl.h',
-        '../../src/profiler/circular-queue.h',
-        '../../src/profiler/cpu-profiler-inl.h',
-        '../../src/profiler/cpu-profiler.cc',
-        '../../src/profiler/cpu-profiler.h',
-        '../../src/profiler/heap-profiler.cc',
-        '../../src/profiler/heap-profiler.h',
-        '../../src/profiler/heap-snapshot-generator-inl.h',
-        '../../src/profiler/heap-snapshot-generator.cc',
-        '../../src/profiler/heap-snapshot-generator.h',
-        '../../src/profiler/profile-generator-inl.h',
-        '../../src/profiler/profile-generator.cc',
-        '../../src/profiler/profile-generator.h',
-        '../../src/profiler/sampler.cc',
-        '../../src/profiler/sampler.h',
-        '../../src/profiler/sampling-heap-profiler.cc',
-        '../../src/profiler/sampling-heap-profiler.h',
-        '../../src/profiler/strings-storage.cc',
-        '../../src/profiler/strings-storage.h',
-        '../../src/profiler/unbound-queue-inl.h',
-        '../../src/profiler/unbound-queue.h',
-        '../../src/property-descriptor.cc',
-        '../../src/property-descriptor.h',
-        '../../src/property-details.h',
-        '../../src/property.cc',
-        '../../src/property.h',
-        '../../src/prototype.h',
-        '../../src/regexp/bytecodes-irregexp.h',
-        '../../src/regexp/interpreter-irregexp.cc',
-        '../../src/regexp/interpreter-irregexp.h',
-        '../../src/regexp/jsregexp-inl.h',
-        '../../src/regexp/jsregexp.cc',
-        '../../src/regexp/jsregexp.h',
-        '../../src/regexp/regexp-ast.cc',
-        '../../src/regexp/regexp-ast.h',
-        '../../src/regexp/regexp-macro-assembler-irregexp-inl.h',
-        '../../src/regexp/regexp-macro-assembler-irregexp.cc',
-        '../../src/regexp/regexp-macro-assembler-irregexp.h',
-        '../../src/regexp/regexp-macro-assembler-tracer.cc',
-        '../../src/regexp/regexp-macro-assembler-tracer.h',
-        '../../src/regexp/regexp-macro-assembler.cc',
-        '../../src/regexp/regexp-macro-assembler.h',
-        '../../src/regexp/regexp-parser.cc',
-        '../../src/regexp/regexp-parser.h',
-        '../../src/regexp/regexp-stack.cc',
-        '../../src/regexp/regexp-stack.h',
-        '../../src/register-configuration.cc',
-        '../../src/register-configuration.h',
-        '../../src/runtime-profiler.cc',
-        '../../src/runtime-profiler.h',
-        '../../src/runtime/runtime-array.cc',
-        '../../src/runtime/runtime-atomics.cc',
-        '../../src/runtime/runtime-classes.cc',
-        '../../src/runtime/runtime-collections.cc',
-        '../../src/runtime/runtime-compiler.cc',
-        '../../src/runtime/runtime-date.cc',
-        '../../src/runtime/runtime-debug.cc',
-        '../../src/runtime/runtime-forin.cc',
-        '../../src/runtime/runtime-function.cc',
-        '../../src/runtime/runtime-futex.cc',
-        '../../src/runtime/runtime-generator.cc',
-        '../../src/runtime/runtime-i18n.cc',
-        '../../src/runtime/runtime-internal.cc',
-        '../../src/runtime/runtime-interpreter.cc',
-        '../../src/runtime/runtime-json.cc',
-        '../../src/runtime/runtime-literals.cc',
-        '../../src/runtime/runtime-liveedit.cc',
-        '../../src/runtime/runtime-maths.cc',
-        '../../src/runtime/runtime-numbers.cc',
-        '../../src/runtime/runtime-object.cc',
-        '../../src/runtime/runtime-observe.cc',
-        '../../src/runtime/runtime-operators.cc',
-        '../../src/runtime/runtime-proxy.cc',
-        '../../src/runtime/runtime-regexp.cc',
-        '../../src/runtime/runtime-scopes.cc',
-        '../../src/runtime/runtime-simd.cc',
-        '../../src/runtime/runtime-strings.cc',
-        '../../src/runtime/runtime-symbol.cc',
-        '../../src/runtime/runtime-test.cc',
-        '../../src/runtime/runtime-typedarray.cc',
-        '../../src/runtime/runtime-uri.cc',
-        '../../src/runtime/runtime-utils.h',
-        '../../src/runtime/runtime.cc',
-        '../../src/runtime/runtime.h',
-        '../../src/safepoint-table.cc',
-        '../../src/safepoint-table.h',
-        '../../src/signature.h',
-        '../../src/simulator.h',
-        '../../src/small-pointer-list.h',
-        '../../src/snapshot/code-serializer.cc',
-        '../../src/snapshot/code-serializer.h',
-        '../../src/snapshot/deserializer.cc',
-        '../../src/snapshot/deserializer.h',
-        '../../src/snapshot/natives.h',
-        '../../src/snapshot/natives-common.cc',
-        '../../src/snapshot/partial-serializer.cc',
-        '../../src/snapshot/partial-serializer.h',
-        '../../src/snapshot/serializer.cc',
-        '../../src/snapshot/serializer.h',
-        '../../src/snapshot/serializer-common.cc',
-        '../../src/snapshot/serializer-common.h',
-        '../../src/snapshot/snapshot.h',
-        '../../src/snapshot/snapshot-common.cc',
-        '../../src/snapshot/snapshot-source-sink.cc',
-        '../../src/snapshot/snapshot-source-sink.h',
-        '../../src/snapshot/startup-serializer.cc',
-        '../../src/snapshot/startup-serializer.h',
-        '../../src/source-position.h',
-        '../../src/splay-tree.h',
-        '../../src/splay-tree-inl.h',
-        '../../src/startup-data-util.cc',
-        '../../src/startup-data-util.h',
-        '../../src/string-builder.cc',
-        '../../src/string-builder.h',
-        '../../src/string-search.h',
-        '../../src/string-stream.cc',
-        '../../src/string-stream.h',
-        '../../src/strtod.cc',
-        '../../src/strtod.h',
-        '../../src/ic/stub-cache.cc',
-        '../../src/ic/stub-cache.h',
-        '../../src/tracing/trace-event.cc',
-        '../../src/tracing/trace-event.h',
-        '../../src/transitions-inl.h',
-        '../../src/transitions.cc',
-        '../../src/transitions.h',
-        '../../src/type-cache.cc',
-        '../../src/type-cache.h',
-        '../../src/type-feedback-vector-inl.h',
-        '../../src/type-feedback-vector.cc',
-        '../../src/type-feedback-vector.h',
-        '../../src/type-info.cc',
-        '../../src/type-info.h',
-        '../../src/types.cc',
-        '../../src/types.h',
-        '../../src/typing-asm.cc',
-        '../../src/typing-asm.h',
-        '../../src/typing-reset.cc',
-        '../../src/typing-reset.h',
-        '../../src/unicode-inl.h',
-        '../../src/unicode.cc',
-        '../../src/unicode.h',
-        '../../src/unicode-cache-inl.h',
-        '../../src/unicode-cache.h',
-        '../../src/unicode-decoder.cc',
-        '../../src/unicode-decoder.h',
-        '../../src/utils-inl.h',
-        '../../src/utils.cc',
-        '../../src/utils.h',
-        '../../src/v8.cc',
-        '../../src/v8.h',
-        '../../src/v8memory.h',
-        '../../src/v8threads.cc',
-        '../../src/v8threads.h',
-        '../../src/vector.h',
-        '../../src/version.cc',
-        '../../src/version.h',
-        '../../src/vm-state-inl.h',
-        '../../src/vm-state.h',
-        '../../src/wasm/asm-wasm-builder.cc',
-        '../../src/wasm/asm-wasm-builder.h',
-        '../../src/wasm/ast-decoder.cc',
-        '../../src/wasm/ast-decoder.h',
-        '../../src/wasm/decoder.h',
-        '../../src/wasm/encoder.cc',
-        '../../src/wasm/encoder.h',
-        '../../src/wasm/module-decoder.cc',
-        '../../src/wasm/module-decoder.h',
-        '../../src/wasm/wasm-js.cc',
-        '../../src/wasm/wasm-js.h',
-        '../../src/wasm/wasm-macro-gen.h',
-        '../../src/wasm/wasm-module.cc',
-        '../../src/wasm/wasm-module.h',
-        '../../src/wasm/wasm-opcodes.cc',
-        '../../src/wasm/wasm-opcodes.h',
-        '../../src/wasm/wasm-result.cc',
-        '../../src/wasm/wasm-result.h',
-        '../../src/zone.cc',
-        '../../src/zone.h',
-        '../../src/zone-allocator.h',
-        '../../src/zone-containers.h',
-        '../../src/third_party/fdlibm/fdlibm.cc',
-        '../../src/third_party/fdlibm/fdlibm.h',
-      ],
-      'conditions': [
-        ['want_separate_host_toolset==1', {
-          'toolsets': ['host', 'target'],
-        }, {
-          'toolsets': ['target'],
-        }],
-        ['v8_target_arch=="arm"', {
-          'sources': [  ### gcmole(arch:arm) ###
-            '../../src/arm/assembler-arm-inl.h',
-            '../../src/arm/assembler-arm.cc',
-            '../../src/arm/assembler-arm.h',
-            '../../src/arm/builtins-arm.cc',
-            '../../src/arm/code-stubs-arm.cc',
-            '../../src/arm/code-stubs-arm.h',
-            '../../src/arm/codegen-arm.cc',
-            '../../src/arm/codegen-arm.h',
-            '../../src/arm/constants-arm.h',
-            '../../src/arm/constants-arm.cc',
-            '../../src/arm/cpu-arm.cc',
-            '../../src/arm/deoptimizer-arm.cc',
-            '../../src/arm/disasm-arm.cc',
-            '../../src/arm/frames-arm.cc',
-            '../../src/arm/frames-arm.h',
-            '../../src/arm/interface-descriptors-arm.cc',
-            '../../src/arm/interface-descriptors-arm.h',
-            '../../src/arm/macro-assembler-arm.cc',
-            '../../src/arm/macro-assembler-arm.h',
-            '../../src/arm/simulator-arm.cc',
-            '../../src/arm/simulator-arm.h',
-            '../../src/compiler/arm/code-generator-arm.cc',
-            '../../src/compiler/arm/instruction-codes-arm.h',
-            '../../src/compiler/arm/instruction-scheduler-arm.cc',
-            '../../src/compiler/arm/instruction-selector-arm.cc',
-            '../../src/crankshaft/arm/lithium-arm.cc',
-            '../../src/crankshaft/arm/lithium-arm.h',
-            '../../src/crankshaft/arm/lithium-codegen-arm.cc',
-            '../../src/crankshaft/arm/lithium-codegen-arm.h',
-            '../../src/crankshaft/arm/lithium-gap-resolver-arm.cc',
-            '../../src/crankshaft/arm/lithium-gap-resolver-arm.h',
-            '../../src/debug/arm/debug-arm.cc',
-            '../../src/full-codegen/arm/full-codegen-arm.cc',
-            '../../src/ic/arm/access-compiler-arm.cc',
-            '../../src/ic/arm/handler-compiler-arm.cc',
-            '../../src/ic/arm/ic-arm.cc',
-            '../../src/ic/arm/ic-compiler-arm.cc',
-            '../../src/ic/arm/stub-cache-arm.cc',
-            '../../src/regexp/arm/regexp-macro-assembler-arm.cc',
-            '../../src/regexp/arm/regexp-macro-assembler-arm.h',
-          ],
-        }],
-        ['v8_target_arch=="arm64"', {
-          'sources': [  ### gcmole(arch:arm64) ###
-            '../../src/arm64/assembler-arm64.cc',
-            '../../src/arm64/assembler-arm64.h',
-            '../../src/arm64/assembler-arm64-inl.h',
-            '../../src/arm64/builtins-arm64.cc',
-            '../../src/arm64/codegen-arm64.cc',
-            '../../src/arm64/codegen-arm64.h',
-            '../../src/arm64/code-stubs-arm64.cc',
-            '../../src/arm64/code-stubs-arm64.h',
-            '../../src/arm64/constants-arm64.h',
-            '../../src/arm64/cpu-arm64.cc',
-            '../../src/arm64/decoder-arm64.cc',
-            '../../src/arm64/decoder-arm64.h',
-            '../../src/arm64/decoder-arm64-inl.h',
-            '../../src/arm64/deoptimizer-arm64.cc',
-            '../../src/arm64/disasm-arm64.cc',
-            '../../src/arm64/disasm-arm64.h',
-            '../../src/arm64/frames-arm64.cc',
-            '../../src/arm64/frames-arm64.h',
-            '../../src/arm64/instructions-arm64.cc',
-            '../../src/arm64/instructions-arm64.h',
-            '../../src/arm64/instrument-arm64.cc',
-            '../../src/arm64/instrument-arm64.h',
-            '../../src/arm64/interface-descriptors-arm64.cc',
-            '../../src/arm64/interface-descriptors-arm64.h',
-            '../../src/arm64/macro-assembler-arm64.cc',
-            '../../src/arm64/macro-assembler-arm64.h',
-            '../../src/arm64/macro-assembler-arm64-inl.h',
-            '../../src/arm64/simulator-arm64.cc',
-            '../../src/arm64/simulator-arm64.h',
-            '../../src/arm64/utils-arm64.cc',
-            '../../src/arm64/utils-arm64.h',
-            '../../src/compiler/arm64/code-generator-arm64.cc',
-            '../../src/compiler/arm64/instruction-codes-arm64.h',
-            '../../src/compiler/arm64/instruction-scheduler-arm64.cc',
-            '../../src/compiler/arm64/instruction-selector-arm64.cc',
-            '../../src/crankshaft/arm64/delayed-masm-arm64.cc',
-            '../../src/crankshaft/arm64/delayed-masm-arm64.h',
-            '../../src/crankshaft/arm64/delayed-masm-arm64-inl.h',
-            '../../src/crankshaft/arm64/lithium-arm64.cc',
-            '../../src/crankshaft/arm64/lithium-arm64.h',
-            '../../src/crankshaft/arm64/lithium-codegen-arm64.cc',
-            '../../src/crankshaft/arm64/lithium-codegen-arm64.h',
-            '../../src/crankshaft/arm64/lithium-gap-resolver-arm64.cc',
-            '../../src/crankshaft/arm64/lithium-gap-resolver-arm64.h',
-            '../../src/debug/arm64/debug-arm64.cc',
-            '../../src/full-codegen/arm64/full-codegen-arm64.cc',
-            '../../src/ic/arm64/access-compiler-arm64.cc',
-            '../../src/ic/arm64/handler-compiler-arm64.cc',
-            '../../src/ic/arm64/ic-arm64.cc',
-            '../../src/ic/arm64/ic-compiler-arm64.cc',
-            '../../src/ic/arm64/stub-cache-arm64.cc',
-            '../../src/regexp/arm64/regexp-macro-assembler-arm64.cc',
-            '../../src/regexp/arm64/regexp-macro-assembler-arm64.h',
-          ],
-        }],
-        ['v8_target_arch=="ia32"', {
-          'sources': [  ### gcmole(arch:ia32) ###
-            '../../src/ia32/assembler-ia32-inl.h',
-            '../../src/ia32/assembler-ia32.cc',
-            '../../src/ia32/assembler-ia32.h',
-            '../../src/ia32/builtins-ia32.cc',
-            '../../src/ia32/code-stubs-ia32.cc',
-            '../../src/ia32/code-stubs-ia32.h',
-            '../../src/ia32/codegen-ia32.cc',
-            '../../src/ia32/codegen-ia32.h',
-            '../../src/ia32/cpu-ia32.cc',
-            '../../src/ia32/deoptimizer-ia32.cc',
-            '../../src/ia32/disasm-ia32.cc',
-            '../../src/ia32/frames-ia32.cc',
-            '../../src/ia32/frames-ia32.h',
-            '../../src/ia32/interface-descriptors-ia32.cc',
-            '../../src/ia32/macro-assembler-ia32.cc',
-            '../../src/ia32/macro-assembler-ia32.h',
-            '../../src/compiler/ia32/code-generator-ia32.cc',
-            '../../src/compiler/ia32/instruction-codes-ia32.h',
-            '../../src/compiler/ia32/instruction-scheduler-ia32.cc',
-            '../../src/compiler/ia32/instruction-selector-ia32.cc',
-            '../../src/crankshaft/ia32/lithium-codegen-ia32.cc',
-            '../../src/crankshaft/ia32/lithium-codegen-ia32.h',
-            '../../src/crankshaft/ia32/lithium-gap-resolver-ia32.cc',
-            '../../src/crankshaft/ia32/lithium-gap-resolver-ia32.h',
-            '../../src/crankshaft/ia32/lithium-ia32.cc',
-            '../../src/crankshaft/ia32/lithium-ia32.h',
-            '../../src/debug/ia32/debug-ia32.cc',
-            '../../src/full-codegen/ia32/full-codegen-ia32.cc',
-            '../../src/ic/ia32/access-compiler-ia32.cc',
-            '../../src/ic/ia32/handler-compiler-ia32.cc',
-            '../../src/ic/ia32/ic-ia32.cc',
-            '../../src/ic/ia32/ic-compiler-ia32.cc',
-            '../../src/ic/ia32/stub-cache-ia32.cc',
-            '../../src/regexp/ia32/regexp-macro-assembler-ia32.cc',
-            '../../src/regexp/ia32/regexp-macro-assembler-ia32.h',
-          ],
-        }],
-        ['v8_target_arch=="x87"', {
-          'sources': [  ### gcmole(arch:x87) ###
-            '../../src/x87/assembler-x87-inl.h',
-            '../../src/x87/assembler-x87.cc',
-            '../../src/x87/assembler-x87.h',
-            '../../src/x87/builtins-x87.cc',
-            '../../src/x87/code-stubs-x87.cc',
-            '../../src/x87/code-stubs-x87.h',
-            '../../src/x87/codegen-x87.cc',
-            '../../src/x87/codegen-x87.h',
-            '../../src/x87/cpu-x87.cc',
-            '../../src/x87/deoptimizer-x87.cc',
-            '../../src/x87/disasm-x87.cc',
-            '../../src/x87/frames-x87.cc',
-            '../../src/x87/frames-x87.h',
-            '../../src/x87/interface-descriptors-x87.cc',
-            '../../src/x87/macro-assembler-x87.cc',
-            '../../src/x87/macro-assembler-x87.h',
-            '../../src/compiler/x87/code-generator-x87.cc',
-            '../../src/compiler/x87/instruction-codes-x87.h',
-            '../../src/compiler/x87/instruction-scheduler-x87.cc',
-            '../../src/compiler/x87/instruction-selector-x87.cc',
-            '../../src/crankshaft/x87/lithium-codegen-x87.cc',
-            '../../src/crankshaft/x87/lithium-codegen-x87.h',
-            '../../src/crankshaft/x87/lithium-gap-resolver-x87.cc',
-            '../../src/crankshaft/x87/lithium-gap-resolver-x87.h',
-            '../../src/crankshaft/x87/lithium-x87.cc',
-            '../../src/crankshaft/x87/lithium-x87.h',
-            '../../src/debug/x87/debug-x87.cc',
-            '../../src/full-codegen/x87/full-codegen-x87.cc',
-            '../../src/ic/x87/access-compiler-x87.cc',
-            '../../src/ic/x87/handler-compiler-x87.cc',
-            '../../src/ic/x87/ic-x87.cc',
-            '../../src/ic/x87/ic-compiler-x87.cc',
-            '../../src/ic/x87/stub-cache-x87.cc',
-            '../../src/regexp/x87/regexp-macro-assembler-x87.cc',
-            '../../src/regexp/x87/regexp-macro-assembler-x87.h',
-          ],
-        }],
-        ['v8_target_arch=="mips" or v8_target_arch=="mipsel"', {
-          'sources': [  ### gcmole(arch:mipsel) ###
-            '../../src/mips/assembler-mips.cc',
-            '../../src/mips/assembler-mips.h',
-            '../../src/mips/assembler-mips-inl.h',
-            '../../src/mips/builtins-mips.cc',
-            '../../src/mips/codegen-mips.cc',
-            '../../src/mips/codegen-mips.h',
-            '../../src/mips/code-stubs-mips.cc',
-            '../../src/mips/code-stubs-mips.h',
-            '../../src/mips/constants-mips.cc',
-            '../../src/mips/constants-mips.h',
-            '../../src/mips/cpu-mips.cc',
-            '../../src/mips/deoptimizer-mips.cc',
-            '../../src/mips/disasm-mips.cc',
-            '../../src/mips/frames-mips.cc',
-            '../../src/mips/frames-mips.h',
-            '../../src/mips/interface-descriptors-mips.cc',
-            '../../src/mips/macro-assembler-mips.cc',
-            '../../src/mips/macro-assembler-mips.h',
-            '../../src/mips/simulator-mips.cc',
-            '../../src/mips/simulator-mips.h',
-            '../../src/compiler/mips/code-generator-mips.cc',
-            '../../src/compiler/mips/instruction-codes-mips.h',
-            '../../src/compiler/mips/instruction-scheduler-mips.cc',
-            '../../src/compiler/mips/instruction-selector-mips.cc',
-            '../../src/crankshaft/mips/lithium-codegen-mips.cc',
-            '../../src/crankshaft/mips/lithium-codegen-mips.h',
-            '../../src/crankshaft/mips/lithium-gap-resolver-mips.cc',
-            '../../src/crankshaft/mips/lithium-gap-resolver-mips.h',
-            '../../src/crankshaft/mips/lithium-mips.cc',
-            '../../src/crankshaft/mips/lithium-mips.h',
-            '../../src/full-codegen/mips/full-codegen-mips.cc',
-            '../../src/debug/mips/debug-mips.cc',
-            '../../src/ic/mips/access-compiler-mips.cc',
-            '../../src/ic/mips/handler-compiler-mips.cc',
-            '../../src/ic/mips/ic-mips.cc',
-            '../../src/ic/mips/ic-compiler-mips.cc',
-            '../../src/ic/mips/stub-cache-mips.cc',
-            '../../src/regexp/mips/regexp-macro-assembler-mips.cc',
-            '../../src/regexp/mips/regexp-macro-assembler-mips.h',
-          ],
-        }],
-        ['v8_target_arch=="mips64" or v8_target_arch=="mips64el"', {
-          'sources': [  ### gcmole(arch:mips64el) ###
-            '../../src/mips64/assembler-mips64.cc',
-            '../../src/mips64/assembler-mips64.h',
-            '../../src/mips64/assembler-mips64-inl.h',
-            '../../src/mips64/builtins-mips64.cc',
-            '../../src/mips64/codegen-mips64.cc',
-            '../../src/mips64/codegen-mips64.h',
-            '../../src/mips64/code-stubs-mips64.cc',
-            '../../src/mips64/code-stubs-mips64.h',
-            '../../src/mips64/constants-mips64.cc',
-            '../../src/mips64/constants-mips64.h',
-            '../../src/mips64/cpu-mips64.cc',
-            '../../src/mips64/deoptimizer-mips64.cc',
-            '../../src/mips64/disasm-mips64.cc',
-            '../../src/mips64/frames-mips64.cc',
-            '../../src/mips64/frames-mips64.h',
-            '../../src/mips64/interface-descriptors-mips64.cc',
-            '../../src/mips64/macro-assembler-mips64.cc',
-            '../../src/mips64/macro-assembler-mips64.h',
-            '../../src/mips64/simulator-mips64.cc',
-            '../../src/mips64/simulator-mips64.h',
-            '../../src/compiler/mips64/code-generator-mips64.cc',
-            '../../src/compiler/mips64/instruction-codes-mips64.h',
-            '../../src/compiler/mips64/instruction-scheduler-mips64.cc',
-            '../../src/compiler/mips64/instruction-selector-mips64.cc',
-            '../../src/crankshaft/mips64/lithium-codegen-mips64.cc',
-            '../../src/crankshaft/mips64/lithium-codegen-mips64.h',
-            '../../src/crankshaft/mips64/lithium-gap-resolver-mips64.cc',
-            '../../src/crankshaft/mips64/lithium-gap-resolver-mips64.h',
-            '../../src/crankshaft/mips64/lithium-mips64.cc',
-            '../../src/crankshaft/mips64/lithium-mips64.h',
-            '../../src/debug/mips64/debug-mips64.cc',
-            '../../src/full-codegen/mips64/full-codegen-mips64.cc',
-            '../../src/ic/mips64/access-compiler-mips64.cc',
-            '../../src/ic/mips64/handler-compiler-mips64.cc',
-            '../../src/ic/mips64/ic-mips64.cc',
-            '../../src/ic/mips64/ic-compiler-mips64.cc',
-            '../../src/ic/mips64/stub-cache-mips64.cc',
-            '../../src/regexp/mips64/regexp-macro-assembler-mips64.cc',
-            '../../src/regexp/mips64/regexp-macro-assembler-mips64.h',
-          ],
-        }],
-        ['v8_target_arch=="x64" or v8_target_arch=="x32"', {
-          'sources': [  ### gcmole(arch:x64) ###
-            '../../src/crankshaft/x64/lithium-codegen-x64.cc',
-            '../../src/crankshaft/x64/lithium-codegen-x64.h',
-            '../../src/crankshaft/x64/lithium-gap-resolver-x64.cc',
-            '../../src/crankshaft/x64/lithium-gap-resolver-x64.h',
-            '../../src/crankshaft/x64/lithium-x64.cc',
-            '../../src/crankshaft/x64/lithium-x64.h',
-            '../../src/x64/assembler-x64-inl.h',
-            '../../src/x64/assembler-x64.cc',
-            '../../src/x64/assembler-x64.h',
-            '../../src/x64/builtins-x64.cc',
-            '../../src/x64/code-stubs-x64.cc',
-            '../../src/x64/code-stubs-x64.h',
-            '../../src/x64/codegen-x64.cc',
-            '../../src/x64/codegen-x64.h',
-            '../../src/x64/cpu-x64.cc',
-            '../../src/x64/deoptimizer-x64.cc',
-            '../../src/x64/disasm-x64.cc',
-            '../../src/x64/frames-x64.cc',
-            '../../src/x64/frames-x64.h',
-            '../../src/x64/interface-descriptors-x64.cc',
-            '../../src/x64/macro-assembler-x64.cc',
-            '../../src/x64/macro-assembler-x64.h',
-            '../../src/debug/x64/debug-x64.cc',
-            '../../src/full-codegen/x64/full-codegen-x64.cc',
-            '../../src/ic/x64/access-compiler-x64.cc',
-            '../../src/ic/x64/handler-compiler-x64.cc',
-            '../../src/ic/x64/ic-x64.cc',
-            '../../src/ic/x64/ic-compiler-x64.cc',
-            '../../src/ic/x64/stub-cache-x64.cc',
-            '../../src/regexp/x64/regexp-macro-assembler-x64.cc',
-            '../../src/regexp/x64/regexp-macro-assembler-x64.h',
-          ],
-        }],
-        ['v8_target_arch=="x64"', {
-          'sources': [
-            '../../src/compiler/x64/code-generator-x64.cc',
-            '../../src/compiler/x64/instruction-codes-x64.h',
-            '../../src/compiler/x64/instruction-scheduler-x64.cc',
-            '../../src/compiler/x64/instruction-selector-x64.cc',
-          ],
-        }],
-        ['v8_target_arch=="ppc" or v8_target_arch=="ppc64"', {
-          'sources': [  ### gcmole(arch:ppc) ###
-            '../../src/compiler/ppc/code-generator-ppc.cc',
-            '../../src/compiler/ppc/instruction-codes-ppc.h',
-            '../../src/compiler/ppc/instruction-scheduler-ppc.cc',
-            '../../src/compiler/ppc/instruction-selector-ppc.cc',
-            '../../src/crankshaft/ppc/lithium-ppc.cc',
-            '../../src/crankshaft/ppc/lithium-ppc.h',
-            '../../src/crankshaft/ppc/lithium-codegen-ppc.cc',
-            '../../src/crankshaft/ppc/lithium-codegen-ppc.h',
-            '../../src/crankshaft/ppc/lithium-gap-resolver-ppc.cc',
-            '../../src/crankshaft/ppc/lithium-gap-resolver-ppc.h',
-            '../../src/debug/ppc/debug-ppc.cc',
-            '../../src/full-codegen/ppc/full-codegen-ppc.cc',
-            '../../src/ic/ppc/access-compiler-ppc.cc',
-            '../../src/ic/ppc/handler-compiler-ppc.cc',
-            '../../src/ic/ppc/ic-ppc.cc',
-            '../../src/ic/ppc/ic-compiler-ppc.cc',
-            '../../src/ic/ppc/stub-cache-ppc.cc',
-            '../../src/ppc/assembler-ppc-inl.h',
-            '../../src/ppc/assembler-ppc.cc',
-            '../../src/ppc/assembler-ppc.h',
-            '../../src/ppc/builtins-ppc.cc',
-            '../../src/ppc/code-stubs-ppc.cc',
-            '../../src/ppc/code-stubs-ppc.h',
-            '../../src/ppc/codegen-ppc.cc',
-            '../../src/ppc/codegen-ppc.h',
-            '../../src/ppc/constants-ppc.h',
-            '../../src/ppc/constants-ppc.cc',
-            '../../src/ppc/cpu-ppc.cc',
-            '../../src/ppc/deoptimizer-ppc.cc',
-            '../../src/ppc/disasm-ppc.cc',
-            '../../src/ppc/frames-ppc.cc',
-            '../../src/ppc/frames-ppc.h',
-            '../../src/ppc/interface-descriptors-ppc.cc',
-            '../../src/ppc/macro-assembler-ppc.cc',
-            '../../src/ppc/macro-assembler-ppc.h',
-            '../../src/ppc/simulator-ppc.cc',
-            '../../src/ppc/simulator-ppc.h',
-            '../../src/regexp/ppc/regexp-macro-assembler-ppc.cc',
-            '../../src/regexp/ppc/regexp-macro-assembler-ppc.h',
-          ],
-        }],
-        ['v8_target_arch=="s390" or v8_target_arch=="s390x"', {
-          'sources': [  ### gcmole(arch:s390) ###
-            '../../src/compiler/s390/code-generator-s390.cc',
-            '../../src/compiler/s390/instruction-codes-s390.h',
-            '../../src/compiler/s390/instruction-scheduler-s390.cc',
-            '../../src/compiler/s390/instruction-selector-s390.cc',
-            '../../src/crankshaft/s390/lithium-codegen-s390.cc',
-            '../../src/crankshaft/s390/lithium-codegen-s390.h',
-            '../../src/crankshaft/s390/lithium-gap-resolver-s390.cc',
-            '../../src/crankshaft/s390/lithium-gap-resolver-s390.h',
-            '../../src/crankshaft/s390/lithium-s390.cc',
-            '../../src/crankshaft/s390/lithium-s390.h',
-            '../../src/debug/s390/debug-s390.cc',
-            '../../src/full-codegen/s390/full-codegen-s390.cc',
-            '../../src/ic/s390/access-compiler-s390.cc',
-            '../../src/ic/s390/handler-compiler-s390.cc',
-            '../../src/ic/s390/ic-compiler-s390.cc',
-            '../../src/ic/s390/ic-s390.cc',
-            '../../src/ic/s390/stub-cache-s390.cc',
-            '../../src/regexp/s390/regexp-macro-assembler-s390.cc',
-            '../../src/regexp/s390/regexp-macro-assembler-s390.h',
-            '../../src/s390/assembler-s390.cc',
-            '../../src/s390/assembler-s390.h',
-            '../../src/s390/assembler-s390-inl.h',
-            '../../src/s390/builtins-s390.cc',
-            '../../src/s390/codegen-s390.cc',
-            '../../src/s390/codegen-s390.h',
-            '../../src/s390/code-stubs-s390.cc',
-            '../../src/s390/code-stubs-s390.h',
-            '../../src/s390/constants-s390.cc',
-            '../../src/s390/constants-s390.h',
-            '../../src/s390/cpu-s390.cc',
-            '../../src/s390/deoptimizer-s390.cc',
-            '../../src/s390/disasm-s390.cc',
-            '../../src/s390/frames-s390.cc',
-            '../../src/s390/frames-s390.h',
-            '../../src/s390/interface-descriptors-s390.cc',
-            '../../src/s390/macro-assembler-s390.cc',
-            '../../src/s390/macro-assembler-s390.h',
-            '../../src/s390/simulator-s390.cc',
-            '../../src/s390/simulator-s390.h',
-          ],
-        }],
-        ['OS=="win"', {
-          'variables': {
-            'gyp_generators': '<!(echo $GYP_GENERATORS)',
-          },
-          'msvs_disabled_warnings': [4351, 4355, 4800],
-          # When building Official, the .lib is too large and exceeds the 2G
-          # limit. This breaks it into multiple pieces to avoid the limit.
-          # See http://crbug.com/485155.
-          'msvs_shard': 4,
-        }],
-        ['component=="shared_library"', {
-          'defines': [
-            'BUILDING_V8_SHARED',
-            'V8_SHARED',
-          ],
-        }],
-        ['v8_postmortem_support=="true"', {
-          'sources': [
-            '<(SHARED_INTERMEDIATE_DIR)/debug-support.cc',
-          ]
-        }],
-        ['v8_enable_i18n_support==1', {
-          'dependencies': [
-            '<(icu_gyp_path):icui18n',
-            '<(icu_gyp_path):icuuc',
-          ]
-        }, {  # v8_enable_i18n_support==0
-          'sources!': [
-            '../../src/i18n.cc',
-            '../../src/i18n.h',
-          ],
-        }],
-        ['OS=="win" and v8_enable_i18n_support==1', {
-          'dependencies': [
-            '<(icu_gyp_path):icudata',
-          ],
-        }],
-        ['icu_use_data_file_flag==1', {
-          'defines': ['ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE'],
-        }, { # else icu_use_data_file_flag !=1
-          'conditions': [
-            ['OS=="win"', {
-              'defines': ['ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_SHARED'],
-            }, {
-              'defines': ['ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC'],
-            }],
-          ],
-        }],
-      ],
-    },
-    {
-      'target_name': 'v8_libbase',
-      'type': 'static_library',
-      'variables': {
-        'optimize': 'max',
-      },
-      'include_dirs+': [
-        '../..',
-      ],
-      'sources': [
-        '../../src/base/accounting-allocator.cc',
-        '../../src/base/accounting-allocator.h',
-        '../../src/base/adapters.h',
-        '../../src/base/atomicops.h',
-        '../../src/base/atomicops_internals_arm64_gcc.h',
-        '../../src/base/atomicops_internals_arm_gcc.h',
-        '../../src/base/atomicops_internals_atomicword_compat.h',
-        '../../src/base/atomicops_internals_mac.h',
-        '../../src/base/atomicops_internals_mips_gcc.h',
-        '../../src/base/atomicops_internals_mips64_gcc.h',
-        '../../src/base/atomicops_internals_portable.h',
-        '../../src/base/atomicops_internals_ppc_gcc.h',
-        '../../src/base/atomicops_internals_s390_gcc.h',
-        '../../src/base/atomicops_internals_tsan.h',
-        '../../src/base/atomicops_internals_x86_gcc.cc',
-        '../../src/base/atomicops_internals_x86_gcc.h',
-        '../../src/base/atomicops_internals_x86_msvc.h',
-        '../../src/base/bits.cc',
-        '../../src/base/bits.h',
-        '../../src/base/build_config.h',
-        '../../src/base/compiler-specific.h',
-        '../../src/base/cpu.cc',
-        '../../src/base/cpu.h',
-        '../../src/base/division-by-constant.cc',
-        '../../src/base/division-by-constant.h',
-        '../../src/base/flags.h',
-        '../../src/base/functional.cc',
-        '../../src/base/functional.h',
-        '../../src/base/iterator.h',
-        '../../src/base/lazy-instance.h',
-        '../../src/base/logging.cc',
-        '../../src/base/logging.h',
-        '../../src/base/macros.h',
-        '../../src/base/once.cc',
-        '../../src/base/once.h',
-        '../../src/base/platform/elapsed-timer.h',
-        '../../src/base/platform/time.cc',
-        '../../src/base/platform/time.h',
-        '../../src/base/platform/condition-variable.cc',
-        '../../src/base/platform/condition-variable.h',
-        '../../src/base/platform/mutex.cc',
-        '../../src/base/platform/mutex.h',
-        '../../src/base/platform/platform.h',
-        '../../src/base/platform/semaphore.cc',
-        '../../src/base/platform/semaphore.h',
-        '../../src/base/safe_conversions.h',
-        '../../src/base/safe_conversions_impl.h',
-        '../../src/base/safe_math.h',
-        '../../src/base/safe_math_impl.h',
-        '../../src/base/smart-pointers.h',
-        '../../src/base/sys-info.cc',
-        '../../src/base/sys-info.h',
-        '../../src/base/utils/random-number-generator.cc',
-        '../../src/base/utils/random-number-generator.h',
-      ],
-      'conditions': [
-        ['want_separate_host_toolset==1', {
-          'toolsets': ['host', 'target'],
-        }, {
-          'toolsets': ['target'],
-        }],
-        ['OS=="linux"', {
-            'conditions': [
-              ['nacl_target_arch=="none"', {
-                'link_settings': {
-                  'libraries': [
-                    '-ldl',
-                    '-lrt'
-                  ],
-                },
-              }, {
-                'defines': [
-                  'V8_LIBRT_NOT_AVAILABLE=1',
-                ],
-              }],
-            ],
-            'sources': [
-              '../../src/base/platform/platform-linux.cc',
-              '../../src/base/platform/platform-posix.cc'
-            ],
-          }
-        ],
-        ['OS=="android"', {
-            'sources': [
-              '../../src/base/platform/platform-posix.cc'
-            ],
-            'link_settings': {
-              'target_conditions': [
-                ['_toolset=="host"', {
-                  # Only include libdl and librt on host builds because they
-                  # are included by default on Android target builds, and we
-                  # don't want to re-include them here since this will change
-                  # library order and break (see crbug.com/469973).
-                  'libraries': [
-                    '-ldl',
-                    '-lrt'
-                  ]
-                }]
-              ]
-            },
-            'conditions': [
-              ['host_os=="mac"', {
-                'target_conditions': [
-                  ['_toolset=="host"', {
-                    'sources': [
-                      '../../src/base/platform/platform-macos.cc'
-                    ]
-                  }, {
-                    'sources': [
-                      '../../src/base/platform/platform-linux.cc'
-                    ]
-                  }],
-                ],
-              }, {
-                'sources': [
-                  '../../src/base/platform/platform-linux.cc'
-                ]
-              }],
-            ],
-          },
-        ],
-        ['OS=="qnx"', {
-            'link_settings': {
-              'target_conditions': [
-                ['_toolset=="host" and host_os=="linux"', {
-                  'libraries': [
-                    '-lrt'
-                  ],
-                }],
-                ['_toolset=="target"', {
-                  'libraries': [
-                    '-lbacktrace'
-                  ],
-                }],
-              ],
-            },
-            'sources': [
-              '../../src/base/platform/platform-posix.cc',
-              '../../src/base/qnx-math.h',
-            ],
-            'target_conditions': [
-              ['_toolset=="host" and host_os=="linux"', {
-                'sources': [
-                  '../../src/base/platform/platform-linux.cc'
-                ],
-              }],
-              ['_toolset=="host" and host_os=="mac"', {
-                'sources': [
-                  '../../src/base/platform/platform-macos.cc'
-                ],
-              }],
-              ['_toolset=="target"', {
-                'sources': [
-                  '../../src/base/platform/platform-qnx.cc'
-                ],
-              }],
-            ],
-          },
-        ],
-        ['OS=="freebsd"', {
-            'link_settings': {
-              'libraries': [
-                '-L/usr/local/lib -lexecinfo',
-            ]},
-            'sources': [
-              '../../src/base/platform/platform-freebsd.cc',
-              '../../src/base/platform/platform-posix.cc'
-            ],
-          }
-        ],
-        ['OS=="openbsd"', {
-            'link_settings': {
-              'libraries': [
-                '-L/usr/local/lib -lexecinfo',
-            ]},
-            'sources': [
-              '../../src/base/platform/platform-openbsd.cc',
-              '../../src/base/platform/platform-posix.cc'
-            ],
-          }
-        ],
-        ['OS=="netbsd"', {
-            'link_settings': {
-              'libraries': [
-                '-L/usr/pkg/lib -Wl,-R/usr/pkg/lib -lexecinfo',
-            ]},
-            'sources': [
-              '../../src/base/platform/platform-openbsd.cc',
-              '../../src/base/platform/platform-posix.cc'
-            ],
-          }
-        ],
-        ['OS=="aix"', {
-          'sources': [
-            '../../src/base/platform/platform-aix.cc',
-            '../../src/base/platform/platform-posix.cc'
-          ]},
-        ],
-        ['OS=="solaris"', {
-            'link_settings': {
-              'libraries': [
-                '-lnsl -lrt',
-            ]},
-            'sources': [
-              '../../src/base/platform/platform-solaris.cc',
-              '../../src/base/platform/platform-posix.cc'
-            ],
-          }
-        ],
-        ['OS=="mac"', {
-          'sources': [
-            '../../src/base/platform/platform-macos.cc',
-            '../../src/base/platform/platform-posix.cc'
-          ]},
-        ],
-        ['OS=="win"', {
-          'defines': [
-            '_CRT_RAND_S'  # for rand_s()
-          ],
-          'variables': {
-            'gyp_generators': '<!(echo $GYP_GENERATORS)',
-          },
-          'conditions': [
-            ['gyp_generators=="make"', {
-              'variables': {
-                'build_env': '<!(uname -o)',
-              },
-              'conditions': [
-                ['build_env=="Cygwin"', {
-                  'sources': [
-                    '../../src/base/platform/platform-cygwin.cc',
-                    '../../src/base/platform/platform-posix.cc'
-                  ],
-                }, {
-                  'sources': [
-                    '../../src/base/platform/platform-win32.cc',
-                    '../../src/base/win32-headers.h',
-                  ],
-                }],
-              ],
-              'link_settings':  {
-                'libraries': [ '-lwinmm', '-lws2_32' ],
-              },
-            }, {
-              'sources': [
-                '../../src/base/platform/platform-win32.cc',
-                '../../src/base/win32-headers.h',
-              ],
-              'msvs_disabled_warnings': [4351, 4355, 4800],
-              'link_settings':  {
-                'libraries': [ '-lwinmm.lib', '-lws2_32.lib' ],
-              },
-            }],
-          ],
-        }],
-      ],
-    },
-    {
-      'target_name': 'v8_libplatform',
-      'type': 'static_library',
-      'variables': {
-        'optimize': 'max',
-      },
-      'dependencies': [
-        'v8_libbase',
-      ],
-      'include_dirs+': [
-        '../..',
-      ],
-      'sources': [
-        '../../include/libplatform/libplatform.h',
-        '../../src/libplatform/default-platform.cc',
-        '../../src/libplatform/default-platform.h',
-        '../../src/libplatform/task-queue.cc',
-        '../../src/libplatform/task-queue.h',
-        '../../src/libplatform/worker-thread.cc',
-        '../../src/libplatform/worker-thread.h',
-      ],
-      'conditions': [
-        ['want_separate_host_toolset==1', {
-          'toolsets': ['host', 'target'],
-        }, {
-          'toolsets': ['target'],
-        }],
-      ],
-      'direct_dependent_settings': {
-        'include_dirs': [
-          '../../include',
-        ],
-      },
-    },
-    {
-      'target_name': 'natives_blob',
-      'type': 'none',
-      'conditions': [
-        [ 'v8_use_external_startup_data==1', {
-          'conditions': [
-            ['want_separate_host_toolset==1', {
-              'dependencies': ['js2c#host'],
-            }, {
-              'dependencies': ['js2c'],
-            }],
-          ],
-          'actions': [{
-            'action_name': 'concatenate_natives_blob',
-            'inputs': [
-              '../../tools/concatenate-files.py',
-              '<(SHARED_INTERMEDIATE_DIR)/libraries.bin',
-              '<(SHARED_INTERMEDIATE_DIR)/libraries-experimental.bin',
-              '<(SHARED_INTERMEDIATE_DIR)/libraries-extras.bin',
-              '<(SHARED_INTERMEDIATE_DIR)/libraries-experimental-extras.bin',
-            ],
-            'conditions': [
-              ['want_separate_host_toolset==1', {
-                'target_conditions': [
-                  ['_toolset=="host"', {
-                    'outputs': [
-                      '<(PRODUCT_DIR)/natives_blob_host.bin',
-                    ],
-                    'action': [
-                      'python', '<@(_inputs)', '<(PRODUCT_DIR)/natives_blob_host.bin'
-                    ],
-                  }, {
-                    'outputs': [
-                      '<(PRODUCT_DIR)/natives_blob.bin',
-                    ],
-                    'action': [
-                      'python', '<@(_inputs)', '<(PRODUCT_DIR)/natives_blob.bin'
-                    ],
-                  }],
-                ],
-              }, {
-                'outputs': [
-                  '<(PRODUCT_DIR)/natives_blob.bin',
-                ],
-                'action': [
-                  'python', '<@(_inputs)', '<(PRODUCT_DIR)/natives_blob.bin'
-                ],
-              }],
-            ],
-          }],
-        }],
-        ['want_separate_host_toolset==1', {
-          'toolsets': ['host', 'target'],
-        }, {
-          'toolsets': ['target'],
-        }],
-      ]
-    },
-    {
-      'target_name': 'js2c',
-      'type': 'none',
-      'conditions': [
-        ['want_separate_host_toolset==1', {
-          'toolsets': ['host'],
-        }, {
-          'toolsets': ['target'],
-        }],
-        ['v8_enable_i18n_support==1', {
-          'variables': {
-            'i18n_library_files': [
-              '../../src/js/i18n.js',
-            ],
-          },
-        }, {
-          'variables': {
-            'i18n_library_files': [],
-          },
-        }],
-      ],
-      'variables': {
-        'library_files': [
-          '../../src/js/macros.py',
-          '../../src/messages.h',
-          '../../src/js/prologue.js',
-          '../../src/js/runtime.js',
-          '../../src/js/v8natives.js',
-          '../../src/js/symbol.js',
-          '../../src/js/array.js',
-          '../../src/js/string.js',
-          '../../src/js/uri.js',
-          '../../src/js/math.js',
-          '../../src/third_party/fdlibm/fdlibm.js',
-          '../../src/js/regexp.js',
-          '../../src/js/arraybuffer.js',
-          '../../src/js/typedarray.js',
-          '../../src/js/iterator-prototype.js',
-          '../../src/js/generator.js',
-          '../../src/js/object-observe.js',
-          '../../src/js/collection.js',
-          '../../src/js/weak-collection.js',
-          '../../src/js/collection-iterator.js',
-          '../../src/js/promise.js',
-          '../../src/js/messages.js',
-          '../../src/js/json.js',
-          '../../src/js/array-iterator.js',
-          '../../src/js/string-iterator.js',
-          '../../src/js/templates.js',
-          '../../src/js/spread.js',
-          '../../src/js/proxy.js',
-          '../../src/debug/mirrors.js',
-          '../../src/debug/debug.js',
-          '../../src/debug/liveedit.js',
-        ],
-        'experimental_library_files': [
-          '../../src/js/macros.py',
-          '../../src/messages.h',
-          '../../src/js/generator.js',
-          '../../src/js/harmony-atomics.js',
-          '../../src/js/harmony-regexp-exec.js',
-          '../../src/js/harmony-object-observe.js',
-          '../../src/js/harmony-sharedarraybuffer.js',
-          '../../src/js/harmony-simd.js',
-          '../../src/js/harmony-species.js',
-          '../../src/js/harmony-unicode-regexps.js',
-          '../../src/js/harmony-string-padding.js',
-          '../../src/js/promise-extra.js',
-        ],
-        'libraries_bin_file': '<(SHARED_INTERMEDIATE_DIR)/libraries.bin',
-        'libraries_experimental_bin_file': '<(SHARED_INTERMEDIATE_DIR)/libraries-experimental.bin',
-        'libraries_extras_bin_file': '<(SHARED_INTERMEDIATE_DIR)/libraries-extras.bin',
-        'libraries_experimental_extras_bin_file': '<(SHARED_INTERMEDIATE_DIR)/libraries-experimental-extras.bin',
-      },
-      'actions': [
-        {
-          'action_name': 'js2c',
-          'inputs': [
-            '../../tools/js2c.py',
-            '<@(library_files)',
-            '<@(i18n_library_files)'
-          ],
-          'outputs': ['<(SHARED_INTERMEDIATE_DIR)/libraries.cc'],
-          'action': [
-            'python',
-            '../../tools/js2c.py',
-            '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
-            'CORE',
-            '<@(library_files)',
-            '<@(i18n_library_files)'
-          ],
-        },
-        {
-          'action_name': 'js2c_bin',
-          'inputs': [
-            '../../tools/js2c.py',
-            '<@(library_files)',
-            '<@(i18n_library_files)'
-          ],
-          'outputs': ['<@(libraries_bin_file)'],
-          'action': [
-            'python',
-            '../../tools/js2c.py',
-            '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
-            'CORE',
-            '<@(library_files)',
-            '<@(i18n_library_files)',
-            '--startup_blob', '<@(libraries_bin_file)',
-            '--nojs',
-          ],
-        },
-        {
-          'action_name': 'js2c_experimental',
-          'inputs': [
-            '../../tools/js2c.py',
-            '<@(experimental_library_files)',
-          ],
-          'outputs': ['<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc'],
-          'action': [
-            'python',
-            '../../tools/js2c.py',
-            '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc',
-            'EXPERIMENTAL',
-            '<@(experimental_library_files)'
-          ],
-        },
-        {
-          'action_name': 'js2c_experimental_bin',
-          'inputs': [
-            '../../tools/js2c.py',
-            '<@(experimental_library_files)',
-          ],
-          'outputs': ['<@(libraries_experimental_bin_file)'],
-          'action': [
-            'python',
-            '../../tools/js2c.py',
-            '<(SHARED_INTERMEDIATE_DIR)/experimental-libraries.cc',
-            'EXPERIMENTAL',
-            '<@(experimental_library_files)',
-            '--startup_blob', '<@(libraries_experimental_bin_file)',
-            '--nojs',
-          ],
-        },
-        {
-          'action_name': 'js2c_extras',
-          'inputs': [
-            '../../tools/js2c.py',
-            '<@(v8_extra_library_files)',
-          ],
-          'outputs': ['<(SHARED_INTERMEDIATE_DIR)/extras-libraries.cc'],
-          'action': [
-            'python',
-            '../../tools/js2c.py',
-            '<(SHARED_INTERMEDIATE_DIR)/extras-libraries.cc',
-            'EXTRAS',
-            '<@(v8_extra_library_files)',
-          ],
-        },
-        {
-          'action_name': 'js2c_extras_bin',
-          'inputs': [
-            '../../tools/js2c.py',
-            '<@(v8_extra_library_files)',
-          ],
-          'outputs': ['<@(libraries_extras_bin_file)'],
-          'action': [
-            'python',
-            '../../tools/js2c.py',
-            '<(SHARED_INTERMEDIATE_DIR)/extras-libraries.cc',
-            'EXTRAS',
-            '<@(v8_extra_library_files)',
-            '--startup_blob', '<@(libraries_extras_bin_file)',
-            '--nojs',
-          ],
-        },
-        {
-          'action_name': 'js2c_experimental_extras',
-          'inputs': [
-            '../../tools/js2c.py',
-            '<@(v8_experimental_extra_library_files)',
-          ],
-          'outputs': [
-            '<(SHARED_INTERMEDIATE_DIR)/experimental-extras-libraries.cc',
-          ],
-          'action': [
-            'python',
-            '../../tools/js2c.py',
-            '<(SHARED_INTERMEDIATE_DIR)/experimental-extras-libraries.cc',
-            'EXPERIMENTAL_EXTRAS',
-            '<@(v8_experimental_extra_library_files)',
-          ],
-        },
-        {
-          'action_name': 'js2c_experimental_extras_bin',
-          'inputs': [
-            '../../tools/js2c.py',
-            '<@(v8_experimental_extra_library_files)',
-          ],
-          'outputs': ['<@(libraries_experimental_extras_bin_file)'],
-          'action': [
-            'python',
-            '../../tools/js2c.py',
-            '<(SHARED_INTERMEDIATE_DIR)/experimental-extras-libraries.cc',
-            'EXPERIMENTAL_EXTRAS',
-            '<@(v8_experimental_extra_library_files)',
-            '--startup_blob', '<@(libraries_experimental_extras_bin_file)',
-            '--nojs',
-          ],
-        },
-      ],
-    },
-    {
-      'target_name': 'postmortem-metadata',
-      'type': 'none',
-      'variables': {
-        'heapobject_files': [
-            '../../src/objects.h',
-            '../../src/objects-inl.h',
-        ],
-      },
-      'actions': [
-          {
-            'action_name': 'gen-postmortem-metadata',
-            'inputs': [
-              '../../tools/gen-postmortem-metadata.py',
-              '<@(heapobject_files)',
-            ],
-            'outputs': [
-              '<(SHARED_INTERMEDIATE_DIR)/debug-support.cc',
-            ],
-            'action': [
-              'python',
-              '../../tools/gen-postmortem-metadata.py',
-              '<@(_outputs)',
-              '<@(heapobject_files)'
-            ]
-          }
-        ]
-    },
-    {
-      'target_name': 'mksnapshot',
-      'type': 'executable',
-      'dependencies': ['v8_base', 'v8_nosnapshot', 'v8_libplatform'],
-      'include_dirs+': [
-        '../..',
-      ],
-      'sources': [
-        '../../src/snapshot/mksnapshot.cc',
-      ],
-      'conditions': [
-        ['v8_enable_i18n_support==1', {
-          'dependencies': [
-            '<(icu_gyp_path):icui18n',
-            '<(icu_gyp_path):icuuc',
-          ]
-        }],
-        ['want_separate_host_toolset==1', {
-          'toolsets': ['host'],
-        }, {
-          'toolsets': ['target'],
-        }],
-      ],
-    },
-  ],
-}
diff --git a/tools/gyp_flag_compare.py b/tools/gyp_flag_compare.py
new file mode 100755
index 0000000..6e356cf
--- /dev/null
+++ b/tools/gyp_flag_compare.py
@@ -0,0 +1,273 @@
+#!/usr/bin/env python
+
+# Copyright 2016 the V8 project authors. All rights reserved.
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Given the output of -t commands from a ninja build for a gyp and GN generated
+build, report on differences between the command lines."""
+
+
+import os
+import shlex
+import subprocess
+import sys
+
+
+# Must be in v8/.
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+os.chdir(BASE_DIR)
+
+
+g_total_differences = 0
+
+
+def FindAndRemoveArgWithValue(command_line, argname):
+  """Given a command line as a list, remove and return the value of an option
+  that takes a value as a separate entry.
+
+  Modifies |command_line| in place.
+  """
+  if argname not in command_line:
+    return ''
+  location = command_line.index(argname)
+  value = command_line[location + 1]
+  command_line[location:location + 2] = []
+  return value
+
+
+def MergeSpacedArgs(command_line, argname):
+  """Combine all arguments |argname| with their values, separated by a space."""
+  i = 0
+  result = []
+  while i < len(command_line):
+    arg = command_line[i]
+    if arg == argname:
+      result.append(arg + ' ' + command_line[i + 1])
+      i += 1
+    else:
+      result.append(arg)
+    i += 1
+  return result
+
+
+def NormalizeSymbolArguments(command_line):
+  """Normalize -g arguments.
+
+  If there's no -g args, it's equivalent to -g0. -g2 is equivalent to -g.
+  Modifies |command_line| in place.
+  """
+  # Strip -g0 if there's no symbols.
+  have_some_symbols = False
+  for x in command_line:
+    if x.startswith('-g') and x != '-g0':
+      have_some_symbols = True
+  if not have_some_symbols and '-g0' in command_line:
+    command_line.remove('-g0')
+
+  # Rename -g2 to -g.
+  if '-g2' in command_line:
+    command_line[command_line.index('-g2')] = '-g'
+
+
+def GetFlags(lines, build_dir):
+  """Turn a list of command lines into a semi-structured dict."""
+  is_win = sys.platform == 'win32'
+  flags_by_output = {}
+  for line in lines:
+    command_line = shlex.split(line.strip(), posix=not is_win)[1:]
+
+    output_name = FindAndRemoveArgWithValue(command_line, '-o')
+    dep_name = FindAndRemoveArgWithValue(command_line, '-MF')
+
+    NormalizeSymbolArguments(command_line)
+
+    command_line = MergeSpacedArgs(command_line, '-Xclang')
+
+    cc_file = [x for x in command_line if x.endswith('.cc') or
+                                          x.endswith('.c') or
+                                          x.endswith('.cpp')]
+    if len(cc_file) != 1:
+      print 'Skipping %s' % command_line
+      continue
+    assert len(cc_file) == 1
+
+    if is_win:
+      rsp_file = [x for x in command_line if x.endswith('.rsp')]
+      assert len(rsp_file) <= 1
+      if rsp_file:
+        rsp_file = os.path.join(build_dir, rsp_file[0][1:])
+        with open(rsp_file, "r") as open_rsp_file:
+          command_line = shlex.split(open_rsp_file, posix=False)
+
+    defines = [x for x in command_line if x.startswith('-D')]
+    include_dirs = [x for x in command_line if x.startswith('-I')]
+    dash_f = [x for x in command_line if x.startswith('-f')]
+    warnings = \
+        [x for x in command_line if x.startswith('/wd' if is_win else '-W')]
+    others = [x for x in command_line if x not in defines and \
+                                         x not in include_dirs and \
+                                         x not in dash_f and \
+                                         x not in warnings and \
+                                         x not in cc_file]
+
+    for index, value in enumerate(include_dirs):
+      if value == '-Igen':
+        continue
+      path = value[2:]
+      if not os.path.isabs(path):
+        path = os.path.join(build_dir, path)
+      include_dirs[index] = '-I' + os.path.normpath(path)
+
+    # GYP supports paths above the source root like <(DEPTH)/../foo while such
+    # paths are unsupported by gn. But gn allows to use system-absolute paths
+    # instead (paths that start with single '/'). Normalize all paths.
+    cc_file = [os.path.normpath(os.path.join(build_dir, cc_file[0]))]
+
+    # Filter for libFindBadConstructs.so having a relative path in one and
+    # absolute path in the other.
+    others_filtered = []
+    for x in others:
+      if x.startswith('-Xclang ') and x.endswith('libFindBadConstructs.so'):
+        others_filtered.append(
+            '-Xclang ' +
+            os.path.join(os.getcwd(),
+                         os.path.normpath(
+                             os.path.join('out/gn_flags', x.split(' ', 1)[1]))))
+      elif x.startswith('-B'):
+        others_filtered.append(
+            '-B' +
+            os.path.join(os.getcwd(),
+                         os.path.normpath(os.path.join('out/gn_flags', x[2:]))))
+      else:
+        others_filtered.append(x)
+    others = others_filtered
+
+    flags_by_output[cc_file[0]] = {
+      'output': output_name,
+      'depname': dep_name,
+      'defines': sorted(defines),
+      'include_dirs': sorted(include_dirs),  # TODO(scottmg): This is wrong.
+      'dash_f': sorted(dash_f),
+      'warnings': sorted(warnings),
+      'other': sorted(others),
+    }
+  return flags_by_output
+
+
+def CompareLists(gyp, gn, name, dont_care_gyp=None, dont_care_gn=None):
+  """Return a report of any differences between gyp and gn lists, ignoring
+  anything in |dont_care_{gyp|gn}| respectively."""
+  global g_total_differences
+  if not dont_care_gyp:
+    dont_care_gyp = []
+  if not dont_care_gn:
+    dont_care_gn = []
+  output = ''
+  if gyp[name] != gn[name]:
+    gyp_set = set(gyp[name])
+    gn_set = set(gn[name])
+    missing_in_gyp = gyp_set - gn_set
+    missing_in_gn = gn_set - gyp_set
+    missing_in_gyp -= set(dont_care_gyp)
+    missing_in_gn -= set(dont_care_gn)
+    if missing_in_gyp or missing_in_gn:
+      output += '  %s differ:\n' % name
+    if missing_in_gyp:
+      output += '    In gyp, but not in GN:\n      %s' % '\n      '.join(
+          sorted(missing_in_gyp)) + '\n'
+      g_total_differences += len(missing_in_gyp)
+    if missing_in_gn:
+      output += '    In GN, but not in gyp:\n      %s' % '\n      '.join(
+          sorted(missing_in_gn)) + '\n\n'
+      g_total_differences += len(missing_in_gn)
+  return output
+
+
+def Run(command_line):
+  """Run |command_line| as a subprocess and return stdout. Raises on error."""
+  return subprocess.check_output(command_line, shell=True)
+
+
+def main():
+  if len(sys.argv) < 4:
+    print ('usage: %s gn_outdir gyp_outdir gn_target '
+           '[gyp_target1, gyp_target2, ...]' % __file__)
+    return 1
+
+  if len(sys.argv) == 4:
+    sys.argv.append(sys.argv[3])
+  gn_out_dir = sys.argv[1]
+  print >> sys.stderr, 'Expecting gn outdir in %s...' % gn_out_dir
+  gn = Run('ninja -C %s -t commands %s' % (gn_out_dir, sys.argv[3]))
+  if sys.platform == 'win32':
+    # On Windows flags are stored in .rsp files which are created during build.
+    print >> sys.stderr, 'Building in %s...' % gn_out_dir
+    Run('ninja -C %s -d keeprsp %s' % (gn_out_dir, sys.argv[3]))
+
+  gyp_out_dir = sys.argv[2]
+  print >> sys.stderr, 'Expecting gyp outdir in %s...' % gyp_out_dir
+  gyp = Run('ninja -C %s -t commands %s' % (gyp_out_dir, " ".join(sys.argv[4:])))
+  if sys.platform == 'win32':
+    # On Windows flags are stored in .rsp files which are created during build.
+    print >> sys.stderr, 'Building in %s...' % gyp_out_dir
+    Run('ninja -C %s -d keeprsp %s' % (gyp_out_dir, " ".join(sys.argv[4:])))
+
+  all_gyp_flags = GetFlags(gyp.splitlines(),
+                           os.path.join(os.getcwd(), gyp_out_dir))
+  all_gn_flags = GetFlags(gn.splitlines(),
+                          os.path.join(os.getcwd(), gn_out_dir))
+  gyp_files = set(all_gyp_flags.keys())
+  gn_files = set(all_gn_flags.keys())
+  different_source_list = gyp_files != gn_files
+  if different_source_list:
+    print 'Different set of sources files:'
+    print '  In gyp, not in GN:\n    %s' % '\n    '.join(
+        sorted(gyp_files - gn_files))
+    print '  In GN, not in gyp:\n    %s' % '\n    '.join(
+        sorted(gn_files - gyp_files))
+    print '\nNote that flags will only be compared for files in both sets.\n'
+  file_list = gyp_files & gn_files
+  files_with_given_differences = {}
+  for filename in sorted(file_list):
+    gyp_flags = all_gyp_flags[filename]
+    gn_flags = all_gn_flags[filename]
+    differences = CompareLists(gyp_flags, gn_flags, 'dash_f')
+    differences += CompareLists(gyp_flags, gn_flags, 'defines')
+    differences += CompareLists(gyp_flags, gn_flags, 'include_dirs',
+                                ['-I%s' % os.path.dirname(BASE_DIR)])
+    differences += CompareLists(gyp_flags, gn_flags, 'warnings',
+        # More conservative warnings in GN we consider to be OK.
+        dont_care_gyp=[
+          '/wd4091',  # 'keyword' : ignored on left of 'type' when no variable
+                      # is declared.
+          '/wd4456',  # Declaration hides previous local declaration.
+          '/wd4457',  # Declaration hides function parameter.
+          '/wd4458',  # Declaration hides class member.
+          '/wd4459',  # Declaration hides global declaration.
+          '/wd4702',  # Unreachable code.
+          '/wd4800',  # Forcing value to bool 'true' or 'false'.
+          '/wd4838',  # Conversion from 'type' to 'type' requires a narrowing
+                      # conversion.
+        ] if sys.platform == 'win32' else None,
+        dont_care_gn=[
+          '-Wendif-labels',
+          '-Wextra',
+          '-Wsign-compare',
+        ] if not sys.platform == 'win32' else None)
+    differences += CompareLists(gyp_flags, gn_flags, 'other')
+    if differences:
+      files_with_given_differences.setdefault(differences, []).append(filename)
+
+  for diff, files in files_with_given_differences.iteritems():
+    print '\n'.join(sorted(files))
+    print diff
+
+  print 'Total differences:', g_total_differences
+  # TODO(scottmg): Return failure on difference once we're closer to identical.
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/tools/ic-explorer.html b/tools/ic-explorer.html
index 43b486a..42bbc20 100644
--- a/tools/ic-explorer.html
+++ b/tools/ic-explorer.html
@@ -1,338 +1,366 @@
 <html>
-  <head>
-<style>
-  .entry-details { 
-  }
-  .entry-details TD { 
-  }
-  .details {
-    width: 2em;
-    border: 1px black dotted;
-  }
-  .count {
-    text-align: right;
-    width: 5em;
-    font-family: monospace;
-  }
-  .percentage { 
-    text-align: right;
-    width: 5em;
-    font-family: monospace;
-  }
-  .key {
-    padding-left: 1em;
-  }
-  .drilldown-group-title {
-    font-weight: bold;
-    padding: 0.5em 0 0.2em 0;
-  }
-</style>
-  <script>
-"use strict"
-var entries = [];
+<!--
+Copyright 2016 the V8 project authors. All rights reserved.  Use of this source
+code is governed by a BSD-style license that can be found in the LICENSE file.
+-->
 
-class Entry {
-  constructor(id, line) {
-    this.id = id;
-    this.line = line;
-    var parts = line.split(" ");
-    if (parts.length < 6) return
-    this.isValid = false;
-    if (parts[0][0] !== "[") return;
-    if (parts[1] === "patching") return;
-    this.type = parts[0].substr(1);
-    this.category = "Other";
-    if (this.type.indexOf("Store") !== -1) {
-      this.category = "Store";
-    } else if (this.type.indexOf("Load") !== -1) {
-      this.category = "Load";
+<head>
+  <style>
+    .entry-details {}
+    
+    .entry-details TD {}
+    
+    .details {
+      width: 2em;
+      border: 1px black dotted;
     }
-    if (this.type.length == 0) return;
-    if (this.type.indexOf('BinaryOpIC(') === 0) {
-      this.type = "BinaryOpIC";
-      var split = parts[0].split('(');
-      this.state = "(" + split[1] + " => " + parts[2];
-      var offset = this.parsePositionAndFile(parts, 6);
-      if (offset == -1) return
-      if (this.file === undefined) return
-      this.file = this.file.slice(0,-1);
-    } else {
-      var offset = this.parsePositionAndFile(parts, 2);
-      if (offset == -1) return
-      this.state = parts[++offset];
-      if (this.type !== "CompareIC") {
-        // if there is no address we have a smi key
-        var address = parts[++offset];
-        if (address !== undefined && address.indexOf("0x") === 0) {
-          this.key = parts.slice(++offset).join(" ");
+    
+    .count {
+      text-align: right;
+      width: 5em;
+      font-family: monospace;
+    }
+    
+    .percentage {
+      text-align: right;
+      width: 5em;
+      font-family: monospace;
+    }
+    
+    .key {
+      padding-left: 1em;
+    }
+    
+    .drilldown-group-title {
+      font-weight: bold;
+      padding: 0.5em 0 0.2em 0;
+    }
+  </style>
+  <script>
+    "use strict"
+    var entries = [];
+
+    class Entry {
+      constructor(id, line) {
+        this.id = id;
+        this.line = line;
+        var parts = line.split(" ");
+        if (parts.length < 6) return
+        this.isValid = false;
+        if (parts[0][0] !== "[") return;
+        if (parts[1] === "patching") return;
+        this.type = parts[0].substr(1);
+        this.category = "Other";
+        this.map = undefined;
+        if (this.type.indexOf("Store") !== -1) {
+          this.category = "Store";
+        } else if (this.type.indexOf("Load") !== -1) {
+          this.category = "Load";
+        }
+        if (this.type.length == 0) return;
+        if (this.type.indexOf('BinaryOpIC(') === 0) {
+          this.type = "BinaryOpIC";
+          var split = parts[0].split('(');
+          this.state = "(" + split[1] + " => " + parts[2];
+          var offset = this.parsePositionAndFile(parts, 6);
+          if (offset == -1) return
+          if (this.file === undefined) return
+          this.file = this.file.slice(0, -1);
         } else {
-          this.key = address;
+          var offset = this.parsePositionAndFile(parts, 2);
+          if (offset == -1) return
+          this.state = parts[++offset];
+          this.map = parts[offset + 1];
+          if (this.map !== undefined && this.map.startsWith("map=")) {
+            this.map = this.map.substring(4);
+            offset++;
+          } else {
+            this.map = undefined;
+          }
+          if (this.type !== "CompareIC") {
+            // if there is no address we have a smi key
+            var address = parts[++offset];
+            if (address !== undefined && address.indexOf("0x") === 0) {
+              this.key = parts.slice(++offset).join(" ");
+            } else {
+              this.key = address;
+            }
+          }
+        }
+        this.filePosition = this.file + " " + this.position;
+        if (this.key) {
+          var isStringKey = false
+          if (this.key.indexOf("<String[") === 0) {
+            isStringKey = true;
+            this.key = "\"" + this.key.slice(this.key.indexOf(']') + 3);
+          } else if (this.key.indexOf("<") === 0) {
+            this.key = this.key.slice(1);
+          }
+          if (this.key.endsWith(">]")) {
+            this.key = this.key.slice(0, -2);
+          } else if (this.key.endsWith("]")) {
+            this.key = this.key.slice(0, -1);
+          }
+          if (isStringKey) {
+            this.key = this.key + "\"";
+          }
+        }
+        this.isValid = true;
+      }
+
+      parsePositionAndFile(parts, start) {
+        // find the position of 'at' in the parts array.
+        var offset = start;
+        for (var i = start + 1; i < parts.length; i++) {
+          offset++;
+          if (parts[i] == 'at') break;
+        }
+        if (parts[offset] !== 'at') return -1;
+        this.position = parts.slice(start, offset).join(' ');
+        offset += 1;
+        this.isNative = parts[offset] == "native"
+        offset += this.isNative ? 1 : 0;
+        this.file = parts[offset];
+        return offset;
+      }
+    }
+
+    function loadFile() {
+      var files = document.getElementById("uploadInput").files;
+
+      var file = files[0];
+      var reader = new FileReader();
+
+      reader.onload = function(evt) {
+        entries = [];
+        var end = this.result.length;
+        var current = 0;
+        var next = 0;
+        var line;
+        var i = 0;
+        var entry;
+        while (current < end) {
+          next = this.result.indexOf("\n", current);
+          if (next === -1) break;
+          i++;
+          line = this.result.substring(current, next);
+          current = next + 1;
+          entry = new Entry(i, line);
+          if (entry.isValid) entries.push(entry);
+        }
+
+        document.getElementById("count").innerHTML = i;
+        updateTable();
+      }
+      reader.readAsText(file);
+      initGroupKeySelect();
+    }
+
+
+
+    var properties = ['type', 'category', 'file', 'filePosition', 'state',
+      'key', 'isNative', 'map'
+    ]
+
+    class Group {
+      constructor(property, key, entry) {
+        this.property = property;
+        this.key = key;
+        this.count = 1;
+        this.entries = [entry];
+        this.percentage = undefined;
+        this.groups = undefined;
+      }
+
+      add(entry) {
+        this.count++;
+        this.entries.push(entry)
+      }
+
+      createSubGroups() {
+        this.groups = {};
+        for (var i = 0; i < properties.length; i++) {
+          var subProperty = properties[i];
+          if (this.property == subProperty) continue;
+          this.groups[subProperty] = groupBy(this.entries, subProperty);
         }
       }
     }
-    this.filePosition = this.file + " " + this.position;
-    if (this.key) {
-      var isStringKey = false
-      if (this.key.indexOf("<String[") === 0) {
-       isStringKey = true;
-        this.key = "\"" + this.key.slice(this.key.indexOf(']')+3);
-      } else if (this.key.indexOf("<") === 0) {
-        this.key = this.key.slice(1);
+
+    function groupBy(entries, property) {
+      var accumulator = {};
+      accumulator.__proto__ = null;
+      var length = entries.length;
+      for (var i = 0; i < length; i++) {
+        var entry = entries[i];
+        var key = entry[property];
+        if (accumulator[key] == undefined) {
+          accumulator[key] = new Group(property, key, entry)
+        } else {
+          var group = accumulator[key];
+          if (group.entries == undefined) console.log([group, entry]);
+          group.add(entry)
+        }
       }
-      if (this.key.endsWith(">]")) {
-        this.key = this.key.slice(0, -2);
-      } else if (this.key.endsWith("]")) {
-        this.key = this.key.slice(0, -1);
+      var result = []
+      for (var key in accumulator) {
+        var group = accumulator[key];
+        group.percentage = Math.round(group.count / length * 100 * 100) / 100;
+        result.push(group);
       }
-      if (isStringKey) {
-        this.key = this.key + "\"";
+      result.sort((a, b) => {
+        return b.count - a.count
+      });
+      return result;
+    }
+
+
+
+    function escapeHtml(unsafe) {
+      if (!unsafe) return "";
+      return unsafe.toString()
+           .replace(/&/g, "&amp;")
+           .replace(/</g, "&lt;")
+           .replace(/>/g, "&gt;")
+           .replace(/"/g, "&quot;")
+           .replace(/'/g, "&#039;");
+    }
+
+    function updateTable() {
+      var select = document.getElementById("group-key");
+      var key = select.options[select.selectedIndex].text;
+      console.log(key);
+      var tableBody = document.getElementById("table-body");
+      removeAllChildren(tableBody);
+      var groups = groupBy(entries, key, true);
+      display(groups, tableBody);
+    }
+
+    function selecedOption(node) {
+      return node.options[node.selectedIndex]
+    }
+
+    function removeAllChildren(node) {
+      while (node.firstChild) {
+        node.removeChild(node.firstChild);
       }
     }
-    this.isValid = true;
-  }
-  
-  parsePositionAndFile(parts, start) {
-    // find the position of 'at' in the parts array.
-    var offset = start;
-    for (var i = start+1; i<parts.length; i++) {
-      offset++;
-      if (parts[i] == 'at') break;
+
+    function display(entries, parent) {
+      var fragment = document.createDocumentFragment();
+
+      function td(tr, content, className) {
+        var td = document.createElement("td");
+        td.innerHTML = content;
+        td.className = className
+        tr.appendChild(td);
+        return td
+      }
+      var max = Math.min(1000, entries.length)
+      for (var i = 0; i < max; i++) {
+        var entry = entries[i];
+        var tr = document.createElement("tr");
+        tr.entry = entry;
+        td(tr, '<span onclick="toggleDetails(this)">details</a>', 'details');
+        td(tr, entry.percentage + "%", 'percentage');
+        td(tr, entry.count, 'count');
+        td(tr, escapeHtml(entry.key), 'key');
+        fragment.appendChild(tr);
+      }
+      var omitted = entries.length - max;
+      if (omitted > 0) {
+        var tr = document.createElement("tr");
+        var td = td(tr, 'Omitted ' + omitted + " entries.");
+        td.colSpan = 4;
+        fragment.appendChild(tr);
+      }
+      parent.appendChild(fragment);
     }
-    if (parts[offset] !== 'at') return -1;
-    this.position = parts.slice(start, offset).join(' ');
-    offset += 1;
-    this.isNative = parts[offset] == "native"
-    offset += this.isNative ? 1 : 0;
-    this.file = parts[offset];
-    return offset;
-  }
-}
 
-function loadFile() {
-  var files = document.getElementById("uploadInput").files;
-
-  var file = files[0];
-  var reader = new FileReader();
-
-  reader.onload = function(evt) {
-    entries = [];
-    var end = this.result.length;
-    var current = 0;
-    var next = 0;
-    var line;
-    var i = 0;
-    var entry;
-    while (current < end) {
-      next = this.result.indexOf("\n", current);
-      if (next === -1) break;
-      i++;
-                            
-      line = this.result.substring(current, next);
-      current = next+1;
-      entry = new Entry(i, line);
-      if (entry.isValid) entries.push(entry);
+    function displayDrilldown(entry, previousSibling) {
+      var tr = document.createElement('tr');
+      tr.className = "entry-details";
+      tr.style.display = "none";
+      // indent by one td.
+      tr.appendChild(document.createElement("td"));
+      var td = document.createElement("td");
+      td.colSpan = 3;
+      for (var key in entry.groups) {
+        td.appendChild(displayDrilldownGroup(entry, key));
+      }
+      tr.appendChild(td);
+      // Append the new TR after previousSibling.
+      previousSibling.parentNode.insertBefore(tr, previousSibling.nextSibling)
     }
-                          
-    document.getElementById("count").innerHTML = i;
-    updateTable();
-  }
-  reader.readAsText(file);
-  initGroupKeySelect(); 
-}
 
-
-
-var properties = ['type', 'category', 'file', 'filePosition', 'state' , 'key', 'isNative']
-
-class Group {
-  constructor(property, key, entry) {
-    this.property = property;
-    this.key = key;
-    this.count = 1;
-    this.entries = [entry];
-    this.percentage = undefined;
-    this.groups = undefined;
-  }
-  
-  add(entry) {
-    this.count ++;
-    this.entries.push(entry)
-  }
-  
-  createSubGroups() {
-    this.groups = {};
-    for (var i=0; i<properties.length; i++) {
-      var subProperty = properties[i];
-      if (this.property == subProperty) continue;
-      this.groups[subProperty] = groupBy(this.entries, subProperty);
+    function displayDrilldownGroup(entry, key) {
+      var max = 20;
+      var group = entry.groups[key];
+      var div = document.createElement("div")
+      div.className = 'drilldown-group-title'
+      div.innerHTML = key + ' [top ' + max + ' out of ' + group.length + ']';
+      var table = document.createElement("table");
+      display(group.slice(0, max), table, false)
+      div.appendChild(table);
+      return div;
     }
-  }
-}
 
-function groupBy(entries, property) {
-  var accumulator = {};
-  accumulator.__proto__ = null;
-  var length = entries.length;
-  for (var i = 0; i < length; i++) {
-    var entry = entries[i];
-    var key = entry[property];
-    if (accumulator[key] == undefined) {
-      accumulator[key] = new Group(property, key, entry)
-    } else {
-      var group = accumulator[key];
-      if (group.entries == undefined) console.log([group, entry]);
-      group.add(entry)
+    function toggleDetails(node) {
+      var tr = node.parentNode.parentNode;
+      var entry = tr.entry;
+
+      // Create subgroup in-place if the don't exist yet.
+      if (entry.groups === undefined) {
+        entry.createSubGroups();
+        displayDrilldown(entry, tr);
+      }
+      var details = tr.nextSibling;
+      var display = details.style.display;
+      if (display != "none") {
+        display = "none";
+      } else {
+        display = "table-row"
+      };
+      details.style.display = display;
     }
-  }
-  var result = []
-  for (var key in accumulator) {
-    var group = accumulator[key];
-    group.percentage = Math.round(group.count / length * 100 * 100) / 100;
-    result.push(group);
-  }
-  result.sort((a,b) => { return b.count - a.count });
-  return result;
-}
 
-
-
-
-function updateTable() {
-  var select = document.getElementById("group-key");
-  var key = select.options[select.selectedIndex].text;
-  console.log(key);
-  var tableBody = document.getElementById("table-body");
-  removeAllChildren(tableBody);
-  var groups = groupBy(entries, key, true);
-  display(groups, tableBody);
-}
-
-function selecedOption(node) {
- return node.options[node.selectedIndex]
-}
-
-function removeAllChildren(node) {
-  while (node.firstChild) {
-    node.removeChild(node.firstChild);
-  }
-}
-
-function display(entries, parent) {
-  var fragment = document.createDocumentFragment();
-
-  function td(tr, content, className) { 
-    var td = document.createElement("td");
-    td.innerHTML = content;
-    td.className = className
-    tr.appendChild(td);
-    return td
-  }
-  var max = Math.min(1000, entries.length)
-  for (var i = 0; i<max; i++) {
-    var entry = entries[i];
-    var tr = document.createElement("tr");
-    tr.entry = entry;
-    td(tr, '<span onclick="toggleDetails(this)">details</a>', 'details');
-    td(tr, entry.percentage +"%", 'percentage');
-    td(tr, entry.count, 'count');
-    td(tr, entry.key, 'key');
-    fragment.appendChild(tr);
-  }
-  var omitted = entries.length - max;
-  if (omitted > 0) {
-    var tr = document.createElement("tr");
-    var td = td(tr, 'Omitted ' + omitted + " entries.");
-    td.colSpan = 4;
-    fragment.appendChild(tr);
-  }
-  parent.appendChild(fragment);
-}
-
-function displayDrilldown(entry, previousSibling) {
-  var tr = document.createElement('tr');
-  tr.className = "entry-details";
-  tr.style.display = "none";
-  // indent by one td.
-  tr.appendChild(document.createElement("td"));
-  var td = document.createElement("td");
-  td.colSpan = 3;
-  for (var key in entry.groups) {
-    td.appendChild(displayDrilldownGroup(entry, key));
-  }
-  tr.appendChild(td);
-  // Append the new TR after previousSibling.
-  previousSibling.parentNode.insertBefore(tr, previousSibling.nextSibling)
-}
-
-function displayDrilldownGroup(entry, key) {
-  var max = 20;
-  var group = entry.groups[key];
-  var div = document.createElement("div")
-  div.className = 'drilldown-group-title'
-  div.innerHTML = key + ' [top ' + max + ']';
-  var table = document.createElement("table");
-  display(group.slice(0, max), table, false)
-  div.appendChild(table);
-  return div;
-}
-
-function toggleDetails(node) {
-  var tr = node.parentNode.parentNode;
-  var entry = tr.entry;
-
-  // Create subgroup in-place if the don't exist yet.
-  if (entry.groups === undefined) {
-    entry.createSubGroups();
-    displayDrilldown(entry, tr);
-  }
-  var details = tr.nextSibling;
-  var display = details.style.display;
-  if (display != "none") {
-    display = "none";
-  }else {
-    display = "table-row"
-  };
-  details.style.display = display;
-}
-
-function initGroupKeySelect() {
-  var select = document.getElementById("group-key");
-  for (var i in properties) {
-    var option = document.createElement("option");
-    option.text = properties[i];
-    select.add(option);
-  }
-}
-
+    function initGroupKeySelect() {
+      var select = document.getElementById("group-key");
+      for (var i in properties) {
+        var option = document.createElement("option");
+        option.text = properties[i];
+        select.add(option);
+      }
+    }
   </script>
-  </head>
-  <body>
-    <h1>
+</head>
+
+<body>
+  <h1>
       <span style="color: #00FF00">I</span>
       <span style="color: #FF00FF">C</span>
       <span style="color: #00FFFF">E</span>
-    </h1>
-    Your IC-Explorer.
-    <h2>Usage</h2>
-    Run your script with <code>--trace_ic</code> and upload on this page:<br/>
-    <code>/path/to/d8 --trace_ic your_script.js > trace.txt</code>
-    <h2>Data</h2>
-    <form name="fileForm">
-      <p>
-        <input id="uploadInput" type="file" name="files" onchange="loadFile();" >
-        trace entries: <span id="count">0</span>
-      </p>
-    </form>
-    <h2>Result</h2>
+    </h1> Your IC-Explorer.
+  <h2>Usage</h2> Run your script with <code>--trace_ic</code> and upload on this page:<br/>
+  <code>/path/to/d8 --trace_ic your_script.js > trace.txt</code>
+  <h2>Data</h2>
+  <form name="fileForm">
     <p>
+      <input id="uploadInput" type="file" name="files" onchange="loadFile();"> trace
+      entries: <span id="count">0</span>
+    </p>
+  </form>
+  <h2>Result</h2>
+  <p>
     Group-Key:
     <select id="group-key" onchange="updateTable()"></select>
-    </p>
-    <p>
-      <table id="table" width="100%">
-        <tbody id="table-body"> 
-        </tbody>
-      </table>
-    </p>
-  </body>
+  </p>
+  <p>
+    <table id="table" width="100%">
+      <tbody id="table-body">
+      </tbody>
+    </table>
+  </p>
+</body>
+
 </html>
diff --git a/tools/ignition/bytecode_dispatches_report.py b/tools/ignition/bytecode_dispatches_report.py
new file mode 100755
index 0000000..1c14014
--- /dev/null
+++ b/tools/ignition/bytecode_dispatches_report.py
@@ -0,0 +1,258 @@
+#! /usr/bin/python
+#
+# Copyright 2016 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+
+import argparse
+import heapq
+import json
+from matplotlib import colors
+from matplotlib import pyplot
+import numpy
+import struct
+
+
+__DESCRIPTION = """
+Process v8.ignition_dispatches_counters.json and list top counters,
+or plot a dispatch heatmap.
+
+Please note that those handlers that may not or will never dispatch
+(e.g. Return or Throw) do not show up in the results.
+"""
+
+
+__HELP_EPILOGUE = """
+examples:
+  # Print the hottest bytecodes in descending order, reading from
+  # default filename v8.ignition_dispatches_counters.json (default mode)
+  $ tools/ignition/bytecode_dispatches_report.py
+
+  # Print the hottest 15 bytecode dispatch pairs reading from data.json
+  $ tools/ignition/bytecode_dispatches_report.py -t -n 15 data.json
+
+  # Save heatmap to default filename v8.ignition_dispatches_counters.svg
+  $ tools/ignition/bytecode_dispatches_report.py -p
+
+  # Save heatmap to filename data.svg
+  $ tools/ignition/bytecode_dispatches_report.py -p -o data.svg
+
+  # Open the heatmap in an interactive viewer
+  $ tools/ignition/bytecode_dispatches_report.py -p -i
+
+  # Display the top 5 sources and destinations of dispatches to/from LdaZero
+  $ tools/ignition/bytecode_dispatches_report.py -f LdaZero -n 5
+"""
+
+__COUNTER_BITS = struct.calcsize("P") * 8  # Size in bits of a pointer
+__COUNTER_MAX = 2**__COUNTER_BITS - 1
+
+
+def warn_if_counter_may_have_saturated(dispatches_table):
+  for source, counters_from_source in dispatches_table.items():
+    for destination, counter in counters_from_source.items():
+      if counter == __COUNTER_MAX:
+        print "WARNING: {} -> {} may have saturated.".format(source,
+                                                             destination)
+
+
+def find_top_bytecode_dispatch_pairs(dispatches_table, top_count):
+  def flattened_counters_generator():
+    for source, counters_from_source in dispatches_table.items():
+      for destination, counter in counters_from_source.items():
+        yield source, destination, counter
+
+  return heapq.nlargest(top_count, flattened_counters_generator(),
+                        key=lambda x: x[2])
+
+
+def print_top_bytecode_dispatch_pairs(dispatches_table, top_count):
+  top_bytecode_dispatch_pairs = (
+    find_top_bytecode_dispatch_pairs(dispatches_table, top_count))
+  print "Top {} bytecode dispatch pairs:".format(top_count)
+  for source, destination, counter in top_bytecode_dispatch_pairs:
+    print "{:>12d}\t{} -> {}".format(counter, source, destination)
+
+
+def find_top_bytecodes(dispatches_table):
+  top_bytecodes = []
+  for bytecode, counters_from_bytecode in dispatches_table.items():
+    top_bytecodes.append((bytecode, sum(counters_from_bytecode.values())))
+  top_bytecodes.sort(key=lambda x: x[1], reverse=True)
+  return top_bytecodes
+
+
+def print_top_bytecodes(dispatches_table):
+  top_bytecodes = find_top_bytecodes(dispatches_table)
+  print "Top bytecodes:"
+  for bytecode, counter in top_bytecodes:
+    print "{:>12d}\t{}".format(counter, bytecode)
+
+
+def find_top_dispatch_sources(dispatches_table, destination, top_count):
+  def source_counters_generator():
+    for source, table_row in dispatches_table.items():
+      if destination in table_row:
+        yield source, table_row[destination]
+
+  return heapq.nlargest(top_count, source_counters_generator(),
+                        key=lambda x: x[1])
+
+
+def print_top_dispatch_sources_and_destinations(dispatches_table, bytecode,
+                                                top_count):
+  top_sources = find_top_dispatch_sources(dispatches_table, bytecode, top_count)
+  top_destinations = heapq.nlargest(top_count,
+                                    dispatches_table[bytecode].items(),
+                                    key=lambda x: x[1])
+
+  print "Top sources of dispatches to {}:".format(bytecode)
+  for source_name, counter in top_sources:
+    print "{:>12d}\t{}".format(counter, source_name)
+
+  print "\nTop destinations of dispatches from {}:".format(bytecode)
+  for destination_name, counter in top_destinations:
+    print "{:>12d}\t{}".format(counter, destination_name)
+
+
+def build_counters_matrix(dispatches_table):
+  labels = sorted(dispatches_table.keys())
+
+  counters_matrix = numpy.empty([len(labels), len(labels)], dtype=int)
+  for from_index, from_name in enumerate(labels):
+    current_row = dispatches_table[from_name];
+    for to_index, to_name in enumerate(labels):
+      counters_matrix[from_index, to_index] = current_row.get(to_name, 0)
+
+  # Reverse y axis for a nicer appearance
+  xlabels = labels
+  ylabels = list(reversed(xlabels))
+  counters_matrix = numpy.flipud(counters_matrix)
+
+  return counters_matrix, xlabels, ylabels
+
+
+def plot_dispatches_table(dispatches_table, figure, axis):
+  counters_matrix, xlabels, ylabels = build_counters_matrix(dispatches_table)
+
+  image = axis.pcolor(
+    counters_matrix,
+    cmap="jet",
+    norm=colors.LogNorm(),
+    edgecolor="grey",
+    linestyle="dotted",
+    linewidth=0.5
+  )
+
+  axis.xaxis.set(
+    ticks=numpy.arange(0.5, len(xlabels)),
+    label="From bytecode handler"
+  )
+  axis.xaxis.tick_top()
+  axis.set_xlim(0, len(xlabels))
+  axis.set_xticklabels(xlabels, rotation="vertical")
+
+  axis.yaxis.set(
+    ticks=numpy.arange(0.5, len(ylabels)),
+    label="To bytecode handler",
+    ticklabels=ylabels
+  )
+  axis.set_ylim(0, len(ylabels))
+
+  figure.colorbar(
+    image,
+    ax=axis,
+    fraction=0.01,
+    pad=0.01
+  )
+
+
+def parse_command_line():
+  command_line_parser = argparse.ArgumentParser(
+    formatter_class=argparse.RawDescriptionHelpFormatter,
+    description=__DESCRIPTION,
+    epilog=__HELP_EPILOGUE
+  )
+  command_line_parser.add_argument(
+    "--plot-size", "-s",
+    metavar="N",
+    default=30,
+    help="shorter side in inches of the output plot (default 30)"
+  )
+  command_line_parser.add_argument(
+    "--plot", "-p",
+    action="store_true",
+    help="plot dispatch pairs heatmap"
+  )
+  command_line_parser.add_argument(
+    "--interactive", "-i",
+    action="store_true",
+    help="open the heatmap in an interactive viewer, instead of writing to file"
+  )
+  command_line_parser.add_argument(
+    "--top-bytecode-dispatch-pairs", "-t",
+    action="store_true",
+    help="print the top bytecode dispatch pairs"
+  )
+  command_line_parser.add_argument(
+    "--top-entries-count", "-n",
+    metavar="N",
+    type=int,
+    default=10,
+    help="print N top entries when running with -t or -f (default 10)"
+  )
+  command_line_parser.add_argument(
+    "--top-dispatches-for-bytecode", "-f",
+    metavar="<bytecode name>",
+    help="print top dispatch sources and destinations to the specified bytecode"
+  )
+  command_line_parser.add_argument(
+    "--output-filename", "-o",
+    metavar="<output filename>",
+    default="v8.ignition_dispatches_table.svg",
+    help=("file to save the plot file to. File type is deduced from the "
+          "extension. PDF, SVG, PNG supported")
+  )
+  command_line_parser.add_argument(
+    "input_filename",
+    metavar="<input filename>",
+    default="v8.ignition_dispatches_table.json",
+    nargs='?',
+    help="Ignition counters JSON file"
+  )
+
+  return command_line_parser.parse_args()
+
+
+def main():
+  program_options = parse_command_line()
+
+  with open(program_options.input_filename) as stream:
+    dispatches_table = json.load(stream)
+
+  warn_if_counter_may_have_saturated(dispatches_table)
+
+  if program_options.plot:
+    figure, axis = pyplot.subplots()
+    plot_dispatches_table(dispatches_table, figure, axis)
+
+    if program_options.interactive:
+      pyplot.show()
+    else:
+      figure.set_size_inches(program_options.plot_size,
+                             program_options.plot_size)
+      pyplot.savefig(program_options.output_filename)
+  elif program_options.top_bytecode_dispatch_pairs:
+    print_top_bytecode_dispatch_pairs(
+      dispatches_table, program_options.top_entries_count)
+  elif program_options.top_dispatches_for_bytecode:
+    print_top_dispatch_sources_and_destinations(
+      dispatches_table, program_options.top_dispatches_for_bytecode,
+      program_options.top_entries_count)
+  else:
+    print_top_bytecodes(dispatches_table)
+
+
+if __name__ == "__main__":
+  main()
diff --git a/tools/ignition/bytecode_dispatches_report_test.py b/tools/ignition/bytecode_dispatches_report_test.py
new file mode 100644
index 0000000..523dac2
--- /dev/null
+++ b/tools/ignition/bytecode_dispatches_report_test.py
@@ -0,0 +1,54 @@
+# Copyright 2016 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import bytecode_dispatches_report as bdr
+import unittest
+
+
+class BytecodeDispatchesReportTest(unittest.TestCase):
+  def test_find_top_counters(self):
+    top_counters = bdr.find_top_bytecode_dispatch_pairs({
+      "a": {"a": 10, "b": 8, "c": 99},
+      "b": {"a":  1, "b": 4, "c":  1},
+      "c": {"a": 42, "b": 3, "c":  7}}, 5)
+    self.assertListEqual(top_counters, [
+      ('a', 'c', 99),
+      ('c', 'a', 42),
+      ('a', 'a', 10),
+      ('a', 'b',  8),
+      ('c', 'c',  7)])
+
+  def test_build_counters_matrix(self):
+    counters_matrix, xlabels, ylabels = bdr.build_counters_matrix({
+      "a": {"a": 10, "b":  8, "c":  7},
+      "b": {"a":  1, "c":  4},
+      "c": {"a": 42, "b": 12, "c": 99}})
+    self.assertTrue((counters_matrix == [[42, 12, 99],
+                                         [ 1,  0,  4],
+                                         [10,  8,  7]]).all())
+    self.assertListEqual(xlabels, ['a', 'b', 'c'])
+    self.assertListEqual(ylabels, ['c', 'b', 'a'])
+
+  def test_find_top_bytecodes(self):
+    top_dispatch_sources = bdr.find_top_bytecodes({
+      "a": {"a": 10, "b":  8, "c":  7},
+      "b": {"a":  1, "c":  4},
+      "c": {"a": 42, "b": 12, "c": 99}
+    })
+    self.assertListEqual(top_dispatch_sources, [
+      ('c', 153),
+      ('a',  25),
+      ('b',   5)
+    ])
+
+  def test_find_top_dispatch_sources(self):
+    top_dispatch_sources = bdr.find_top_dispatch_sources({
+      "a": {"a": 10, "b":  8, "c":  7},
+      "b": {"a":  1, "c":  4},
+      "c": {"a": 42, "b": 12, "c": 99}
+    }, "b", 10)
+    self.assertListEqual(top_dispatch_sources, [
+      ("c", 12),
+      ("a",  8)
+    ])
diff --git a/tools/ignition/linux_perf_bytecode_annotate.py b/tools/ignition/linux_perf_bytecode_annotate.py
new file mode 100755
index 0000000..6681190
--- /dev/null
+++ b/tools/ignition/linux_perf_bytecode_annotate.py
@@ -0,0 +1,174 @@
+#! /usr/bin/python2
+#
+# Copyright 2016 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+
+import argparse
+import collections
+import os
+import subprocess
+import sys
+
+
+__DESCRIPTION = """
+Processes a perf.data sample file and annotates the hottest instructions in a
+given bytecode handler.
+"""
+
+
+__HELP_EPILOGUE = """
+Note:
+  This tool uses the disassembly of interpreter's bytecode handler codegen
+  from out/<arch>.debug/d8. you should ensure that this binary is in-sync with
+  the version used to generate the perf profile.
+
+  Also, the tool depends on the symbol offsets from perf samples being accurate.
+  As such, you should use the ":pp" suffix for events.
+
+Examples:
+  EVENT_TYPE=cycles:pp tools/run-perf.sh out/x64.release/d8
+  tools/ignition/linux_perf_bytecode_annotate.py Add
+"""
+
+
+def bytecode_offset_generator(perf_stream, bytecode_name):
+  skip_until_end_of_chain = False
+  bytecode_symbol = "BytecodeHandler:" + bytecode_name;
+
+  for line in perf_stream:
+    # Lines starting with a "#" are comments, skip them.
+    if line[0] == "#":
+      continue
+    line = line.strip()
+
+    # Empty line signals the end of the callchain.
+    if not line:
+      skip_until_end_of_chain = False
+      continue
+
+    if skip_until_end_of_chain:
+      continue
+
+    symbol_and_offset = line.split(" ", 1)[1]
+
+    if symbol_and_offset.startswith("BytecodeHandler:"):
+      skip_until_end_of_chain = True
+
+      if symbol_and_offset.startswith(bytecode_symbol):
+        yield int(symbol_and_offset.split("+", 1)[1], 16)
+
+
+def bytecode_offset_counts(bytecode_offsets):
+  offset_counts = collections.defaultdict(int)
+  for offset in bytecode_offsets:
+    offset_counts[offset] += 1
+  return offset_counts
+
+
+def bytecode_disassembly_generator(ignition_codegen, bytecode_name):
+  name_string = "name = " + bytecode_name
+  for line in ignition_codegen:
+    if line.startswith(name_string):
+      break
+
+  # Found the bytecode disassembly.
+  for line in ignition_codegen:
+    line = line.strip()
+    # Blank line marks the end of the bytecode's disassembly.
+    if not line:
+      return
+
+    # Only yield disassembly output.
+    if not line.startswith("0x"):
+      continue
+
+    yield line
+
+
+def print_disassembly_annotation(offset_counts, bytecode_disassembly):
+  total = sum(offset_counts.values())
+  offsets = sorted(offset_counts, reverse=True)
+  def next_offset():
+    return offsets.pop() if offsets else -1
+
+  current_offset = next_offset()
+  print current_offset;
+
+  for line in bytecode_disassembly:
+    disassembly_offset = int(line.split()[1])
+    if disassembly_offset == current_offset:
+      count = offset_counts[current_offset]
+      percentage = 100.0 * count / total
+      print "{:>8d} ({:>5.1f}%) ".format(count, percentage),
+      current_offset = next_offset()
+    else:
+      print "                ",
+    print line
+
+  if offsets:
+    print ("WARNING: Offsets not empty. Output is most likely invalid due to "
+           "a mismatch between perf output and debug d8 binary.")
+
+
+def parse_command_line():
+  command_line_parser = argparse.ArgumentParser(
+      formatter_class=argparse.RawDescriptionHelpFormatter,
+      description=__DESCRIPTION,
+      epilog=__HELP_EPILOGUE)
+
+  command_line_parser.add_argument(
+      "--arch", "-a",
+      help="The architecture (default: x64)",
+      default="x64",
+  )
+  command_line_parser.add_argument(
+      "--input", "-i",
+      help="perf sample file to process (default: perf.data)",
+      default="perf.data",
+      metavar="<perf filename>",
+      dest="perf_filename"
+  )
+  command_line_parser.add_argument(
+      "--output", "-o",
+      help="output file name (stdout if omitted)",
+      type=argparse.FileType("wt"),
+      default=sys.stdout,
+      metavar="<output filename>",
+      dest="output_stream"
+  )
+  command_line_parser.add_argument(
+      "bytecode_name",
+      metavar="<bytecode name>",
+      nargs="?",
+      help="The bytecode handler to annotate"
+  )
+
+  return command_line_parser.parse_args()
+
+
+def main():
+  program_options = parse_command_line()
+  perf = subprocess.Popen(["perf", "script", "-f", "ip,sym,symoff",
+                           "-i", program_options.perf_filename],
+                          stdout=subprocess.PIPE)
+
+  v8_root_path = os.path.dirname(__file__) + "/../../"
+  d8_path = "{}/out/{}.debug/d8".format(v8_root_path, program_options.arch)
+  d8_codegen = subprocess.Popen([d8_path, "--ignition",
+                                 "--trace-ignition-codegen", "-e", "1"],
+                                stdout=subprocess.PIPE)
+
+  bytecode_offsets = bytecode_offset_generator(
+      perf.stdout, program_options.bytecode_name)
+  offset_counts = bytecode_offset_counts(bytecode_offsets)
+
+  bytecode_disassembly = bytecode_disassembly_generator(
+      d8_codegen.stdout, program_options.bytecode_name)
+
+  print_disassembly_annotation(offset_counts, bytecode_disassembly)
+
+
+if __name__ == "__main__":
+  main()
diff --git a/tools/ignition/linux_perf_bytecode_annotate_test.py b/tools/ignition/linux_perf_bytecode_annotate_test.py
new file mode 100644
index 0000000..15abbed
--- /dev/null
+++ b/tools/ignition/linux_perf_bytecode_annotate_test.py
@@ -0,0 +1,85 @@
+# Copyright 2016 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import StringIO
+import unittest
+import linux_perf_bytecode_annotate as bytecode_annotate
+
+
+PERF_SCRIPT_OUTPUT = """
+# This line is a comment
+# This should be ignored too
+#
+#    cdefab01  aRandomSymbol::Name(to, be, ignored)
+
+   00000000 firstSymbol
+   00000123 secondSymbol
+
+   01234567 foo
+   abcdef76 BytecodeHandler:bar+0x12
+   76543210 baz
+   abcdef76 BytecodeHandler:bar+0x16
+   76543210 baz
+
+   01234567 foo
+   abcdef76 BytecodeHandler:foo+0x1
+   76543210 baz
+   abcdef76 BytecodeHandler:bar+0x2
+   76543210 bar
+
+   abcdef76 BytecodeHandler:bar+0x19
+
+   abcdef76 BytecodeHandler:bar+0x12
+
+   abcdef76 BytecodeHandler:bar+0x12
+"""
+
+
+D8_CODEGEN_OUTPUT = """
+kind = BYTECODE_HANDLER
+name = foo
+compiler = turbofan
+Instructions (size = 3)
+0x3101394a3c0     0  55             push rbp
+0x3101394a3c1     1  ffe3           jmp rbx
+
+kind = BYTECODE_HANDLER
+name = bar
+compiler = turbofan
+Instructions (size = 5)
+0x3101394b3c0     0  55             push rbp
+0x3101394b3c1     1  4883c428       REX.W addq rsp,0x28
+# Unexpected comment
+0x3101394b3c5     5  ffe3           jmp rbx
+
+kind = BYTECODE_HANDLER
+name = baz
+compiler = turbofan
+Instructions (size = 5)
+0x3101394c3c0     0  55             push rbp
+0x3101394c3c1     1  4883c428       REX.W addq rsp,0x28
+0x3101394c3c5     5  ffe3           jmp rbx
+"""
+
+
+class LinuxPerfBytecodeAnnotateTest(unittest.TestCase):
+
+  def test_bytecode_offset_generator(self):
+    perf_stream = StringIO.StringIO(PERF_SCRIPT_OUTPUT)
+    offsets = list(
+        bytecode_annotate.bytecode_offset_generator(perf_stream, "bar"))
+    self.assertListEqual(offsets, [18, 25, 18, 18])
+
+  def test_bytecode_disassembly_generator(self):
+    codegen_stream = StringIO.StringIO(D8_CODEGEN_OUTPUT)
+    disassembly = list(
+        bytecode_annotate.bytecode_disassembly_generator(codegen_stream, "bar"))
+    self.assertListEqual(disassembly, [
+        "0x3101394b3c0     0  55             push rbp",
+        "0x3101394b3c1     1  4883c428       REX.W addq rsp,0x28",
+        "0x3101394b3c5     5  ffe3           jmp rbx"])
+
+
+if __name__ == "__main__":
+  unittest.main()
diff --git a/tools/ignition/linux_perf_report.py b/tools/ignition/linux_perf_report.py
new file mode 100755
index 0000000..fbf562c
--- /dev/null
+++ b/tools/ignition/linux_perf_report.py
@@ -0,0 +1,222 @@
+#! /usr/bin/python2
+#
+# Copyright 2016 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+
+import argparse
+import collections
+import re
+import subprocess
+import sys
+
+
+__DESCRIPTION = """
+Processes a perf.data sample file and reports the hottest Ignition bytecodes,
+or write an input file for flamegraph.pl.
+"""
+
+
+__HELP_EPILOGUE = """
+examples:
+  # Get a flamegraph for Ignition bytecode handlers on Octane benchmark,
+  # without considering the time spent compiling JS code, entry trampoline
+  # samples and other non-Ignition samples.
+  #
+  $ tools/run-perf.sh out/x64.release/d8 \\
+        --ignition --noturbo --nocrankshaft run.js
+  $ tools/ignition/linux_perf_report.py --flamegraph -o out.collapsed
+  $ flamegraph.pl --colors js out.collapsed > out.svg
+
+  # Same as above, but show all samples, including time spent compiling JS code,
+  # entry trampoline samples and other samples.
+  $ # ...
+  $ tools/ignition/linux_perf_report.py \\
+      --flamegraph --show-all -o out.collapsed
+  $ # ...
+
+  # Same as above, but show full function signatures in the flamegraph.
+  $ # ...
+  $ tools/ignition/linux_perf_report.py \\
+      --flamegraph --show-full-signatures -o out.collapsed
+  $ # ...
+
+  # See the hottest bytecodes on Octane benchmark, by number of samples.
+  #
+  $ tools/run-perf.sh out/x64.release/d8 \\
+        --ignition --noturbo --nocrankshaft octane/run.js
+  $ tools/ignition/linux_perf_report.py
+"""
+
+
+COMPILER_SYMBOLS_RE = re.compile(
+  r"v8::internal::(?:\(anonymous namespace\)::)?Compile|v8::internal::Parser")
+
+
+def strip_function_parameters(symbol):
+  if symbol[-1] != ')': return symbol
+  pos = 1
+  parenthesis_count = 0
+  for c in reversed(symbol):
+    if c == ')':
+      parenthesis_count += 1
+    elif c == '(':
+      parenthesis_count -= 1
+    if parenthesis_count == 0:
+      break
+    else:
+      pos += 1
+  return symbol[:-pos]
+
+
+def collapsed_callchains_generator(perf_stream, show_all=False,
+                                   show_full_signatures=False):
+  current_chain = []
+  skip_until_end_of_chain = False
+  compiler_symbol_in_chain = False
+
+  for line in perf_stream:
+    # Lines starting with a "#" are comments, skip them.
+    if line[0] == "#":
+      continue
+
+    line = line.strip()
+
+    # Empty line signals the end of the callchain.
+    if not line:
+      if not skip_until_end_of_chain and current_chain and show_all:
+        current_chain.append("[other]")
+        yield current_chain
+      # Reset parser status.
+      current_chain = []
+      skip_until_end_of_chain = False
+      compiler_symbol_in_chain = False
+      continue
+
+    if skip_until_end_of_chain:
+      continue
+
+    symbol = line.split(" ", 1)[1]
+    if not show_full_signatures:
+      symbol = strip_function_parameters(symbol)
+    current_chain.append(symbol)
+
+    if symbol.startswith("BytecodeHandler:"):
+      yield current_chain
+      skip_until_end_of_chain = True
+    elif symbol == "Stub:CEntryStub" and compiler_symbol_in_chain:
+      if show_all:
+        current_chain[-1] = "[compiler]"
+        yield current_chain
+      skip_until_end_of_chain = True
+    elif COMPILER_SYMBOLS_RE.match(symbol):
+      compiler_symbol_in_chain = True
+    elif symbol == "Builtin:InterpreterEntryTrampoline":
+      if len(current_chain) == 1:
+        yield ["[entry trampoline]"]
+      else:
+        # If we see an InterpreterEntryTrampoline which is not at the top of the
+        # chain and doesn't have a BytecodeHandler above it, then we have
+        # skipped the top BytecodeHandler due to the top-level stub not building
+        # a frame. File the chain in the [misattributed] bucket.
+        current_chain[-1] = "[misattributed]"
+        yield current_chain
+      skip_until_end_of_chain = True
+
+
+def calculate_samples_count_per_callchain(callchains):
+  chain_counters = collections.defaultdict(int)
+  for callchain in callchains:
+    key = ";".join(reversed(callchain))
+    chain_counters[key] += 1
+  return chain_counters.items()
+
+
+def calculate_samples_count_per_handler(callchains):
+  def strip_handler_prefix_if_any(handler):
+    return handler if handler[0] == "[" else handler.split(":", 1)[1]
+
+  handler_counters = collections.defaultdict(int)
+  for callchain in callchains:
+    handler = strip_handler_prefix_if_any(callchain[-1])
+    handler_counters[handler] += 1
+  return handler_counters.items()
+
+
+def write_flamegraph_input_file(output_stream, callchains):
+  for callchain, count in calculate_samples_count_per_callchain(callchains):
+    output_stream.write("{}; {}\n".format(callchain, count))
+
+
+def write_handlers_report(output_stream, callchains):
+  handler_counters = calculate_samples_count_per_handler(callchains)
+  samples_num = sum(counter for _, counter in handler_counters)
+  # Sort by decreasing number of samples
+  handler_counters.sort(key=lambda entry: entry[1], reverse=True)
+  for bytecode_name, count in handler_counters:
+    output_stream.write(
+      "{}\t{}\t{:.3f}%\n".format(bytecode_name, count,
+                                 100. * count / samples_num))
+
+
+def parse_command_line():
+  command_line_parser = argparse.ArgumentParser(
+    formatter_class=argparse.RawDescriptionHelpFormatter,
+    description=__DESCRIPTION,
+    epilog=__HELP_EPILOGUE)
+
+  command_line_parser.add_argument(
+    "perf_filename",
+    help="perf sample file to process (default: perf.data)",
+    nargs="?",
+    default="perf.data",
+    metavar="<perf filename>"
+  )
+  command_line_parser.add_argument(
+    "--flamegraph", "-f",
+    help="output an input file for flamegraph.pl, not a report",
+    action="store_true",
+    dest="output_flamegraph"
+  )
+  command_line_parser.add_argument(
+    "--show-all", "-a",
+    help="show samples outside Ignition bytecode handlers",
+    action="store_true"
+  )
+  command_line_parser.add_argument(
+    "--show-full-signatures", "-s",
+    help="show full signatures instead of function names",
+    action="store_true"
+  )
+  command_line_parser.add_argument(
+    "--output", "-o",
+    help="output file name (stdout if omitted)",
+    type=argparse.FileType('wt'),
+    default=sys.stdout,
+    metavar="<output filename>",
+    dest="output_stream"
+  )
+
+  return command_line_parser.parse_args()
+
+
+def main():
+  program_options = parse_command_line()
+
+  perf = subprocess.Popen(["perf", "script", "-f", "ip,sym",
+                           "-i", program_options.perf_filename],
+                          stdout=subprocess.PIPE)
+
+  callchains = collapsed_callchains_generator(
+    perf.stdout, program_options.show_all,
+    program_options.show_full_signatures)
+
+  if program_options.output_flamegraph:
+    write_flamegraph_input_file(program_options.output_stream, callchains)
+  else:
+    write_handlers_report(program_options.output_stream, callchains)
+
+
+if __name__ == "__main__":
+  main()
diff --git a/tools/ignition/linux_perf_report_test.py b/tools/ignition/linux_perf_report_test.py
new file mode 100644
index 0000000..d9cef75
--- /dev/null
+++ b/tools/ignition/linux_perf_report_test.py
@@ -0,0 +1,147 @@
+# Copyright 2016 the V8 project authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import linux_perf_report as ipr
+import StringIO
+import unittest
+
+
+PERF_SCRIPT_OUTPUT = """
+# This line is a comment
+# This should be ignored too
+#
+#    cdefab01  aRandomSymbol::Name(to, be, ignored)
+
+   00000000 firstSymbol
+   00000123 secondSymbol
+
+   01234567 foo
+   abcdef76 BytecodeHandler:bar
+   76543210 baz
+
+# Indentation shouldn't matter (neither should this line)
+
+    01234567 foo
+      abcdef76 BytecodeHandler:bar
+        76543210 baz
+
+      01234567 beep
+   abcdef76 BytecodeHandler:bar
+    76543210 baz
+
+   01234567 hello
+   abcdef76 v8::internal::Compiler
+   00000000 Stub:CEntryStub
+   76543210 world
+   11111111 BytecodeHandler:nope
+
+   00000000 Lost
+   11111111 Builtin:InterpreterEntryTrampoline
+   22222222 bar
+
+   11111111 Builtin:InterpreterEntryTrampoline
+   22222222 bar
+"""
+
+
+class LinuxPerfReportTest(unittest.TestCase):
+  def test_collapsed_callchains_generator(self):
+    perf_stream = StringIO.StringIO(PERF_SCRIPT_OUTPUT)
+    callchains = list(ipr.collapsed_callchains_generator(perf_stream))
+    self.assertListEqual(callchains, [
+      ["foo", "BytecodeHandler:bar"],
+      ["foo", "BytecodeHandler:bar"],
+      ["beep", "BytecodeHandler:bar"],
+      ["[entry trampoline]"],
+    ])
+
+  def test_collapsed_callchains_generator_show_other(self):
+    perf_stream = StringIO.StringIO(PERF_SCRIPT_OUTPUT)
+    callchains = list(ipr.collapsed_callchains_generator(perf_stream,
+                                                         show_all=True))
+    self.assertListEqual(callchains, [
+      ['firstSymbol', 'secondSymbol', '[other]'],
+      ["foo", "BytecodeHandler:bar"],
+      ["foo", "BytecodeHandler:bar"],
+      ["beep", "BytecodeHandler:bar"],
+      ["hello", "v8::internal::Compiler", "[compiler]"],
+      ["Lost", "[misattributed]"],
+      ["[entry trampoline]"],
+    ])
+
+  def test_calculate_samples_count_per_callchain(self):
+    counters = ipr.calculate_samples_count_per_callchain([
+      ["foo", "BytecodeHandler:bar"],
+      ["foo", "BytecodeHandler:bar"],
+      ["beep", "BytecodeHandler:bar"],
+      ["hello", "v8::internal::Compiler", "[compiler]"],
+    ])
+    self.assertItemsEqual(counters, [
+      ('BytecodeHandler:bar;foo', 2),
+      ('BytecodeHandler:bar;beep', 1),
+      ('[compiler];v8::internal::Compiler;hello', 1),
+    ])
+
+  def test_calculate_samples_count_per_callchain(self):
+    counters = ipr.calculate_samples_count_per_callchain([
+      ["foo", "BytecodeHandler:bar"],
+      ["foo", "BytecodeHandler:bar"],
+      ["beep", "BytecodeHandler:bar"],
+    ])
+    self.assertItemsEqual(counters, [
+      ('BytecodeHandler:bar;foo', 2),
+      ('BytecodeHandler:bar;beep', 1),
+    ])
+
+  def test_calculate_samples_count_per_handler_show_compile(self):
+    counters = ipr.calculate_samples_count_per_handler([
+      ["foo", "BytecodeHandler:bar"],
+      ["foo", "BytecodeHandler:bar"],
+      ["beep", "BytecodeHandler:bar"],
+      ["hello", "v8::internal::Compiler", "[compiler]"],
+    ])
+    self.assertItemsEqual(counters, [
+      ("bar", 3),
+      ("[compiler]", 1)
+    ])
+
+  def test_calculate_samples_count_per_handler_(self):
+    counters = ipr.calculate_samples_count_per_handler([
+      ["foo", "BytecodeHandler:bar"],
+      ["foo", "BytecodeHandler:bar"],
+      ["beep", "BytecodeHandler:bar"],
+    ])
+    self.assertItemsEqual(counters, [("bar", 3)])
+
+  def test_multiple_handlers(self):
+    perf_stream = StringIO.StringIO("""
+        0000 foo(bar)
+        1234 BytecodeHandler:first
+        5678 a::random::call<to>(something, else)
+        9abc BytecodeHandler:second
+        def0 otherIrrelevant(stuff)
+        1111 entrypoint
+    """)
+    callchains = list(ipr.collapsed_callchains_generator(perf_stream, False))
+    self.assertListEqual(callchains, [
+      ["foo", "BytecodeHandler:first"],
+    ])
+
+  def test_compiler_symbols_regex(self):
+    compiler_symbols = [
+      "v8::internal::Parser",
+      "v8::internal::(anonymous namespace)::Compile",
+      "v8::internal::Compiler::foo",
+    ]
+    for compiler_symbol in compiler_symbols:
+      self.assertTrue(ipr.COMPILER_SYMBOLS_RE.match(compiler_symbol))
+
+  def test_strip_function_parameters(self):
+    def should_match(signature, name):
+      self.assertEqual(ipr.strip_function_parameters(signature), name)
+
+    should_match("foo(bar)", "foo"),
+    should_match("Foo(foomatic::(anonymous)::bar(baz))", "Foo"),
+    should_match("v8::(anonymous ns)::bar<thing(with, parentheses)>(baz, poe)",
+       "v8::(anonymous ns)::bar<thing(with, parentheses)>")
diff --git a/tools/isolate_driver.py b/tools/isolate_driver.py
index d1b39b0..1542353 100644
--- a/tools/isolate_driver.py
+++ b/tools/isolate_driver.py
@@ -30,6 +30,16 @@
       'version': 1,
     }, f, indent=2, sort_keys=True)
 
+def rebase_directories(args, abs_base):
+  """Rebases all paths to be relative to abs_base."""
+  def replace(index):
+    args[index] = os.path.relpath(os.path.abspath(args[index]), abs_base)
+  for i, arg in enumerate(args):
+    if arg in ['--isolate', '--isolated']:
+      replace(i + 1)
+    if arg == '--path-variable':
+      # Path variables have a triple form: --path-variable NAME <path>.
+      replace(i + 2)
 
 def main():
   logging.basicConfig(level=logging.ERROR, format='%(levelname)7s %(message)s')
@@ -49,6 +59,14 @@
     print >> sys.stderr, 'Internal failure'
     return 1
 
+  # Make sure all paths are relative to the isolate file. This is an
+  # expectation of the go binaries. In gn, this script is not called
+  # relative to the isolate file, but relative to the product dir.
+  new_base = os.path.abspath(os.path.dirname(args[isolate]))
+  rebase_directories(args, new_base)
+  assert args[isolate] == os.path.basename(args[isolate])
+  os.chdir(new_base)
+
   # In 'prepare' mode just collect all required information for postponed
   # isolated.py invocation later, store it in *.isolated.gen.json file.
   if mode == 'prepare':
diff --git a/tools/jsfunfuzz/jsfunfuzz.gyp b/tools/jsfunfuzz/jsfunfuzz.gyp
index fb0e5f4..8938e44 100644
--- a/tools/jsfunfuzz/jsfunfuzz.gyp
+++ b/tools/jsfunfuzz/jsfunfuzz.gyp
@@ -13,8 +13,8 @@
             '../../src/d8.gyp:d8_run',
           ],
           'includes': [
-            '../../build/features.gypi',
-            '../../build/isolate.gypi',
+            '../../gypfiles/features.gypi',
+            '../../gypfiles/isolate.gypi',
           ],
           'sources': [
             'jsfunfuzz.isolate',
diff --git a/tools/mingw-generate-makefiles.sh b/tools/mingw-generate-makefiles.sh
index 32af52d..67715fc 100755
--- a/tools/mingw-generate-makefiles.sh
+++ b/tools/mingw-generate-makefiles.sh
@@ -27,7 +27,7 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 # Monkey-patch GYP.
-cat > build/gyp/gyp.mingw << EOF
+cat > tools/gyp/gyp.mingw << EOF
 #!/usr/bin/env python
 
 # Copyright (c) 2009 Google Inc. All rights reserved.
@@ -74,11 +74,11 @@
 find out -name '*.mk' -or -name 'Makefile*' -exec rm {} \;
 
 # Generate fresh Makefiles.
-mv build/gyp/gyp build/gyp/gyp.original
-mv build/gyp/gyp.mingw build/gyp/gyp
+mv tools/gyp/gyp tools/gyp/gyp.original
+mv tools/gyp/gyp.mingw tools/gyp/gyp
 make out/Makefile.ia32
-mv build/gyp/gyp build/gyp/gyp.mingw
-mv build/gyp/gyp.original build/gyp/gyp
+mv tools/gyp/gyp tools/gyp/gyp.mingw
+mv tools/gyp/gyp.original tools/gyp/gyp
 
 # Patch generated Makefiles: replace most backslashes with forward slashes,
 # fix library names in linker flags.
diff --git a/tools/parser-shell.cc b/tools/parser-shell.cc
index ad687c9..810c5b9 100644
--- a/tools/parser-shell.cc
+++ b/tools/parser-shell.cc
@@ -142,7 +142,7 @@
 
 int main(int argc, char* argv[]) {
   v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
-  v8::V8::InitializeICU();
+  v8::V8::InitializeICUDefaultLocation(argv[0]);
   v8::Platform* platform = v8::platform::CreateDefaultPlatform();
   v8::V8::InitializePlatform(platform);
   v8::V8::Initialize();
diff --git a/tools/parser-shell.gyp b/tools/parser-shell.gyp
index 77ed1eb..4ef1a82 100644
--- a/tools/parser-shell.gyp
+++ b/tools/parser-shell.gyp
@@ -30,14 +30,14 @@
     'v8_code': 1,
     'v8_enable_i18n_support%': 1,
   },
-  'includes': ['../build/toolchain.gypi', '../build/features.gypi'],
+  'includes': ['../gypfiles/toolchain.gypi', '../gypfiles/features.gypi'],
   'targets': [
     {
       'target_name': 'parser-shell',
       'type': 'executable',
       'dependencies': [
-        '../tools/gyp/v8.gyp:v8',
-        '../tools/gyp/v8.gyp:v8_libplatform',
+        '../src/v8.gyp:v8',
+        '../src/v8.gyp:v8_libplatform',
       ],
       'conditions': [
         ['v8_enable_i18n_support==1', {
@@ -50,10 +50,6 @@
       'include_dirs+': [
         '..',
       ],
-      'defines': [
-        # TODO(jochen): Remove again after this is globally turned on.
-        'V8_IMMINENT_DEPRECATION_WARNINGS',
-      ],
       'sources': [
         'parser-shell.cc',
         'shell-utils.h',
diff --git a/tools/perf-to-html.py b/tools/perf-to-html.py
index 63faeb1..7ec9c50 100755
--- a/tools/perf-to-html.py
+++ b/tools/perf-to-html.py
@@ -115,8 +115,8 @@
     self.name_ = name
     self.tests_ = {}
     for test in data:
-      # strip off "<name>/" prefix
-      test_name = test.split("/")[1]
+      # strip off "<name>/" prefix, allowing for subsequent "/"s
+      test_name = test.split("/", 1)[1]
       self.appendResult(test_name, data[test])
 
   # tests is a dictionary of Results
diff --git a/tools/plot-timer-events b/tools/plot-timer-events
index 15f28ac..da2e823 100755
--- a/tools/plot-timer-events
+++ b/tools/plot-timer-events
@@ -70,10 +70,9 @@
   rm $calibration_log
 
   # Overhead in picoseconds.
-  options=--distortion=
-  options+=`echo "1000*(($t_1_end - $t_1_start) - ($t_2_end - $t_2_start)) \
+  distortion=`echo "1000*(($t_1_end - $t_1_start) - ($t_2_end - $t_2_start)) \
               / ($n_1 - $n_2)" | bc`
-  echo $options
+  options="--distortion=$distortion"
 fi
 
 cat $log_file |
diff --git a/tools/release/auto_roll.py b/tools/release/auto_roll.py
index b71cac5..243b029 100755
--- a/tools/release/auto_roll.py
+++ b/tools/release/auto_roll.py
@@ -18,7 +18,9 @@
 
 Please close rolling in case of a roll revert:
 https://v8-roll.appspot.com/
-This only works with a Google account.""")
+This only works with a Google account.
+
+CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel""")
 
 class Preparation(Step):
   MESSAGE = "Preparation."
diff --git a/tools/release/check_clusterfuzz.py b/tools/release/check_clusterfuzz.py
index cd73051..0fdffd9 100755
--- a/tools/release/check_clusterfuzz.py
+++ b/tools/release/check_clusterfuzz.py
@@ -89,6 +89,15 @@
   },
   {
     "args": {
+      "job_type": "linux_asan_d8_ignition_v8_arm_dbg",
+      "reproducible": "True",
+      "open": "True",
+      "bug_information": "",
+    },
+    "crash_state": ANY_RE,
+  },
+  {
+    "args": {
       "job_type": "linux_asan_d8_v8_arm64_dbg",
       "reproducible": "True",
       "open": "True",
diff --git a/tools/release/create_release.py b/tools/release/create_release.py
index 7477ea1..14d44b4 100755
--- a/tools/release/create_release.py
+++ b/tools/release/create_release.py
@@ -223,6 +223,27 @@
     os.remove(self.Config("CHANGELOG_ENTRY_FILE"))
 
 
+class FixBrokenTag(Step):
+  MESSAGE = "Check for a missing tag and fix that instead."
+
+  def RunStep(self):
+    commit = None
+    try:
+      commit = self.GitLog(
+          n=1, format="%H",
+          grep=self["commit_title"],
+          branch="origin/%s" % self["version"],
+      )
+    except GitFailedException:
+      # In the normal case, the remote doesn't exist yet and git will fail.
+      pass
+    if commit:
+      print "Found %s. Trying to repair tag and bail out." % self["version"]
+      self.Git("tag %s %s" % (self["version"], commit))
+      self.Git("push origin refs/tags/%s" % self["version"])
+      return True
+
+
 class PushBranch(Step):
   MESSAGE = "Push changes."
 
@@ -303,6 +324,7 @@
       SetVersion,
       EnableMergeWatchlist,
       CommitBranch,
+      FixBrokenTag,
       PushBranch,
       TagRevision,
       CleanUp,
diff --git a/tools/release/test_scripts.py b/tools/release/test_scripts.py
index 05457c9..417f739 100644
--- a/tools/release/test_scripts.py
+++ b/tools/release/test_scripts.py
@@ -970,6 +970,8 @@
           cb=self.WriteFakeWatchlistsFile),
       Cmd("git commit -aF \"%s\"" % TEST_CONFIG["COMMITMSG_FILE"], "",
           cb=CheckVersionCommit),
+      Cmd("git log -1 --format=%H --grep=\"Version 3.22.5\" origin/3.22.5",
+          ""),
       Cmd("git push origin "
           "refs/heads/work-branch:refs/pending/heads/3.22.5 "
           "push_hash:refs/pending-tags/heads/3.22.5 "
@@ -1041,6 +1043,8 @@
 https://v8-roll.appspot.com/
 This only works with a Google account.
 
+CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel
+
 TBR=reviewer@chromium.org"""
 
   # Snippet from the original DEPS file.
diff --git a/tools/run-deopt-fuzzer.gyp b/tools/run-deopt-fuzzer.gyp
index 73f0aaf..9eb6b53 100644
--- a/tools/run-deopt-fuzzer.gyp
+++ b/tools/run-deopt-fuzzer.gyp
@@ -13,8 +13,8 @@
             '../src/d8.gyp:d8_run',
           ],
           'includes': [
-            '../build/features.gypi',
-            '../build/isolate.gypi',
+            '../gypfiles/features.gypi',
+            '../gypfiles/isolate.gypi',
           ],
           'sources': [
             'run-deopt-fuzzer.isolate',
diff --git a/tools/run-deopt-fuzzer.py b/tools/run-deopt-fuzzer.py
index 970aa8e..928c71b 100755
--- a/tools/run-deopt-fuzzer.py
+++ b/tools/run-deopt-fuzzer.py
@@ -399,6 +399,7 @@
     "gc_stress": False,
     "gcov_coverage": False,
     "ignition": False,
+    "ignition_turbofan": False,
     "isolates": options.isolates,
     "mode": mode,
     "no_i18n": False,
diff --git a/tools/run-perf.sh b/tools/run-perf.sh
index 24053b4..03123fd 100755
--- a/tools/run-perf.sh
+++ b/tools/run-perf.sh
@@ -13,6 +13,7 @@
 SAMPLE_RATE_CONFIG_FILE="/proc/sys/kernel/perf_event_max_sample_rate"
 KERNEL_MAP_CONFIG_FILE="/proc/sys/kernel/kptr_restrict"
 CALL_GRAPH_METHOD="fp"  # dwarf does not play nice with JITted objects.
+EVENT_TYPE=${EVENT_TYPE:=cycles:u}
 
 ########## Usage
 
@@ -46,7 +47,7 @@
 
 echo "Running..."
 perf record -R \
-  -e cycles:u \
+  -e $EVENT_TYPE \
   -c $SAMPLE_EVERY_N_CYCLES \
   --call-graph $CALL_GRAPH_METHOD \
   -i $@ --perf_basic_prof
diff --git a/tools/run-tests.py b/tools/run-tests.py
index a380c97..b1c71dd 100755
--- a/tools/run-tests.py
+++ b/tools/run-tests.py
@@ -105,6 +105,7 @@
 VARIANTS = ["default", "stress", "turbofan"]
 
 EXHAUSTIVE_VARIANTS = VARIANTS + [
+  "ignition",
   "nocrankshaft",
   "turbofan_opt",
 ]
@@ -194,6 +195,8 @@
               "mips64el",
               "nacl_ia32",
               "nacl_x64",
+              "s390",
+              "s390x",
               "x87",
               "arm64"]
 
@@ -253,6 +256,9 @@
                     default="")
   result.add_option("--ignition", help="Skip tests which don't run in ignition",
                     default=False, action="store_true")
+  result.add_option("--ignition-turbofan",
+                    help="Skip tests which don't run in ignition_turbofan",
+                    default=False, action="store_true")
   result.add_option("--isolates", help="Whether to test isolates",
                     default=False, action="store_true")
   result.add_option("-j", help="The number of parallel tasks to run",
@@ -335,7 +341,7 @@
   result.add_option("--time", help="Print timing information after running",
                     default=False, action="store_true")
   result.add_option("-t", "--timeout", help="Timeout in seconds",
-                    default= -1, type="int")
+                    default=TIMEOUT_DEFAULT, type="int")
   result.add_option("--tsan",
                     help="Regard test expectations for TSAN",
                     default=False, action="store_true")
@@ -378,6 +384,10 @@
 
 def SetupEnvironment(options):
   """Setup additional environment variables."""
+
+  # Many tests assume an English interface.
+  os.environ['LANG'] = 'en_US.UTF-8'
+
   symbolizer = 'external_symbolizer_path=%s' % (
       os.path.join(
           BASE_DIR, 'third_party', 'llvm-build', 'Release+Asserts', 'bin',
@@ -591,6 +601,11 @@
     return 1
   SetupEnvironment(options)
 
+  if options.swarming:
+    # Swarming doesn't print how isolated commands are called. Lets make this
+    # less cryptic by printing it ourselves.
+    print ' '.join(sys.argv)
+
   exit_code = 0
   if not options.no_presubmit:
     print ">>> running presubmit tests"
@@ -663,19 +678,16 @@
 
   # Populate context object.
   mode_flags = MODES[mode]["flags"]
-  timeout = options.timeout
-  if timeout == -1:
-    # Simulators are slow, therefore allow a longer default timeout.
-    if arch in SLOW_ARCHS:
-      timeout = 2 * TIMEOUT_DEFAULT;
-    else:
-      timeout = TIMEOUT_DEFAULT;
 
-  timeout *= MODES[mode]["timeout_scalefactor"]
+  # Simulators are slow, therefore allow a longer timeout.
+  if arch in SLOW_ARCHS:
+    options.timeout *= 2
+
+  options.timeout *= MODES[mode]["timeout_scalefactor"]
 
   if options.predictable:
     # Predictable mode is slower.
-    timeout *= 2
+    options.timeout *= 2
 
   # TODO(machenbach): Remove temporary verbose output on windows after
   # debugging driver-hung-up on XP.
@@ -685,7 +697,8 @@
   )
   ctx = context.Context(arch, MODES[mode]["execution_mode"], shell_dir,
                         mode_flags, verbose_output,
-                        timeout, options.isolates,
+                        options.timeout,
+                        options.isolates,
                         options.command_prefix,
                         options.extra_flags,
                         options.no_i18n,
@@ -711,6 +724,7 @@
     "gc_stress": options.gc_stress,
     "gcov_coverage": options.gcov_coverage,
     "ignition": options.ignition,
+    "ignition_turbofan": options.ignition_turbofan,
     "isolates": options.isolates,
     "mode": MODES[mode]["status_mode"],
     "no_i18n": options.no_i18n,
diff --git a/tools/run-valgrind.gyp b/tools/run-valgrind.gyp
index d06be93..02dd26d 100644
--- a/tools/run-valgrind.gyp
+++ b/tools/run-valgrind.gyp
@@ -13,8 +13,8 @@
             '../src/d8.gyp:d8_run',
           ],
           'includes': [
-            '../build/features.gypi',
-            '../build/isolate.gypi',
+            '../gypfiles/features.gypi',
+            '../gypfiles/isolate.gypi',
           ],
           'sources': [
             'run-valgrind.isolate',
diff --git a/tools/run_perf.py b/tools/run_perf.py
index db4245f..2db71d4 100755
--- a/tools/run_perf.py
+++ b/tools/run_perf.py
@@ -612,6 +612,21 @@
 class DesktopPlatform(Platform):
   def __init__(self, options):
     super(DesktopPlatform, self).__init__(options)
+    self.command_prefix = []
+
+    if options.prioritize or options.affinitize != None:
+      self.command_prefix = ["schedtool"]
+      if options.prioritize:
+        self.command_prefix += ["-n", "-20"]
+      if options.affinitize != None:
+      # schedtool expects a bit pattern when setting affinity, where each
+      # bit set to '1' corresponds to a core where the process may run on.
+      # First bit corresponds to CPU 0. Since the 'affinitize' parameter is
+      # a core number, we need to map to said bit pattern.
+        cpu = int(options.affinitize)
+        core = 1 << cpu
+        self.command_prefix += ["-a", ("0x%x" % core)]
+      self.command_prefix += ["-e"]
 
   def PreExecution(self):
     pass
@@ -627,15 +642,18 @@
     suffix = ' - without patch' if no_patch else ''
     shell_dir = self.shell_dir_no_patch if no_patch else self.shell_dir
     title = ">>> %%s (#%d)%s:" % ((count + 1), suffix)
+    command = self.command_prefix + runnable.GetCommand(shell_dir,
+                                                        self.extra_flags)
     try:
       output = commands.Execute(
-          runnable.GetCommand(shell_dir, self.extra_flags),
-          timeout=runnable.timeout,
+        command,
+        timeout=runnable.timeout,
       )
     except OSError as e:  # pragma: no cover
       print title % "OSError"
       print e
       return ""
+
     print title % "Stdout"
     print output.stdout
     if output.stderr:  # pragma: no cover
@@ -788,6 +806,109 @@
       stdout = ""
     return stdout
 
+class CustomMachineConfiguration:
+  def __init__(self, disable_aslr = False, governor = None):
+    self.aslr_backup = None
+    self.governor_backup = None
+    self.disable_aslr = disable_aslr
+    self.governor = governor
+
+  def __enter__(self):
+    if self.disable_aslr:
+      self.aslr_backup = CustomMachineConfiguration.GetASLR()
+      CustomMachineConfiguration.SetASLR(0)
+    if self.governor != None:
+      self.governor_backup = CustomMachineConfiguration.GetCPUGovernor()
+      CustomMachineConfiguration.SetCPUGovernor(self.governor)
+    return self
+
+  def __exit__(self, type, value, traceback):
+    if self.aslr_backup != None:
+      CustomMachineConfiguration.SetASLR(self.aslr_backup)
+    if self.governor_backup != None:
+      CustomMachineConfiguration.SetCPUGovernor(self.governor_backup)
+
+  @staticmethod
+  def GetASLR():
+    try:
+      with open("/proc/sys/kernel/randomize_va_space", "r") as f:
+        return int(f.readline().strip())
+    except Exception as e:
+      print "Failed to get current ASLR settings."
+      raise e
+
+  @staticmethod
+  def SetASLR(value):
+    try:
+      with open("/proc/sys/kernel/randomize_va_space", "w") as f:
+        f.write(str(value))
+    except Exception as e:
+      print "Failed to update ASLR to %s." % value
+      print "Are we running under sudo?"
+      raise e
+
+    new_value = CustomMachineConfiguration.GetASLR()
+    if value != new_value:
+      raise Exception("Present value is %s" % new_value)
+
+  @staticmethod
+  def GetCPUCoresRange():
+    try:
+      with open("/sys/devices/system/cpu/present", "r") as f:
+        indexes = f.readline()
+        r = map(int, indexes.split("-"))
+        if len(r) == 1:
+          return range(r[0], r[0] + 1)
+        return range(r[0], r[1] + 1)
+    except Exception as e:
+      print "Failed to retrieve number of CPUs."
+      raise e
+
+  @staticmethod
+  def GetCPUPathForId(cpu_index):
+    ret = "/sys/devices/system/cpu/cpu"
+    ret += str(cpu_index)
+    ret += "/cpufreq/scaling_governor"
+    return ret
+
+  @staticmethod
+  def GetCPUGovernor():
+    try:
+      cpu_indices = CustomMachineConfiguration.GetCPUCoresRange()
+      ret = None
+      for cpu_index in cpu_indices:
+        cpu_device = CustomMachineConfiguration.GetCPUPathForId(cpu_index)
+        with open(cpu_device, "r") as f:
+          # We assume the governors of all CPUs are set to the same value
+          val = f.readline().strip()
+          if ret == None:
+            ret = val
+          elif ret != val:
+            raise Exception("CPU cores have differing governor settings")
+      return ret
+    except Exception as e:
+      print "Failed to get the current CPU governor."
+      print "Is the CPU governor disabled? Check BIOS."
+      raise e
+
+  @staticmethod
+  def SetCPUGovernor(value):
+    try:
+      cpu_indices = CustomMachineConfiguration.GetCPUCoresRange()
+      for cpu_index in cpu_indices:
+        cpu_device = CustomMachineConfiguration.GetCPUPathForId(cpu_index)
+        with open(cpu_device, "w") as f:
+          f.write(value)
+
+    except Exception as e:
+      print "Failed to change CPU governor to %s." % value
+      print "Are we running under sudo?"
+      raise e
+
+    cur_value = CustomMachineConfiguration.GetCPUGovernor()
+    if cur_value != value:
+      raise Exception("Could not set CPU governor. Present value is %s"
+                      % cur_value )
 
 # TODO: Implement results_processor.
 def Main(args):
@@ -822,6 +943,27 @@
                     help="JavaScript engine binary. By default, d8 under "
                     "architecture-specific build dir. "
                     "Not supported in conjunction with outdir-no-patch.")
+  parser.add_option("--prioritize",
+                    help="Raise the priority to nice -20 for the benchmarking "
+                    "process.Requires Linux, schedtool, and sudo privileges.",
+                    default=False, action="store_true")
+  parser.add_option("--affinitize",
+                    help="Run benchmarking process on the specified core. "
+                    "For example: "
+                    "--affinitize=0 will run the benchmark process on core 0. "
+                    "--affinitize=3 will run the benchmark process on core 3. "
+                    "Requires Linux, schedtool, and sudo privileges.",
+                    default=None)
+  parser.add_option("--noaslr",
+                    help="Disable ASLR for the duration of the benchmarked "
+                    "process. Requires Linux and sudo privileges.",
+                    default=False, action="store_true")
+  parser.add_option("--cpu-governor",
+                    help="Set cpu governor to specified policy for the "
+                    "duration of the benchmarked process. Typical options: "
+                    "'powersave' for more stable results, or 'performance' "
+                    "for shorter completion time of suite, with potentially "
+                    "more noise in results.")
 
   (options, args) = parser.parse_args(args)
 
@@ -872,56 +1014,60 @@
   else:
     options.shell_dir_no_patch = None
 
+  prev_aslr = None
+  prev_cpu_gov = None
   platform = Platform.GetPlatform(options)
 
   results = Results()
   results_no_patch = Results()
-  for path in args:
-    path = os.path.abspath(path)
+  with CustomMachineConfiguration(governor = options.cpu_governor,
+                                  disable_aslr = options.noaslr) as conf:
+    for path in args:
+      path = os.path.abspath(path)
 
-    if not os.path.exists(path):  # pragma: no cover
-      results.errors.append("Configuration file %s does not exist." % path)
-      continue
+      if not os.path.exists(path):  # pragma: no cover
+        results.errors.append("Configuration file %s does not exist." % path)
+        continue
 
-    with open(path) as f:
-      suite = json.loads(f.read())
+      with open(path) as f:
+        suite = json.loads(f.read())
 
-    # If no name is given, default to the file name without .json.
-    suite.setdefault("name", os.path.splitext(os.path.basename(path))[0])
+      # If no name is given, default to the file name without .json.
+      suite.setdefault("name", os.path.splitext(os.path.basename(path))[0])
 
-    # Setup things common to one test suite.
-    platform.PreExecution()
+      # Setup things common to one test suite.
+      platform.PreExecution()
 
-    # Build the graph/trace tree structure.
-    default_parent = DefaultSentinel(default_binary_name)
-    root = BuildGraphConfigs(suite, options.arch, default_parent)
+      # Build the graph/trace tree structure.
+      default_parent = DefaultSentinel(default_binary_name)
+      root = BuildGraphConfigs(suite, options.arch, default_parent)
 
-    # Callback to be called on each node on traversal.
-    def NodeCB(node):
-      platform.PreTests(node, path)
+      # Callback to be called on each node on traversal.
+      def NodeCB(node):
+        platform.PreTests(node, path)
 
-    # Traverse graph/trace tree and interate over all runnables.
-    for runnable in FlattenRunnables(root, NodeCB):
-      print ">>> Running suite: %s" % "/".join(runnable.graphs)
+      # Traverse graph/trace tree and interate over all runnables.
+      for runnable in FlattenRunnables(root, NodeCB):
+        print ">>> Running suite: %s" % "/".join(runnable.graphs)
 
-      def Runner():
-        """Output generator that reruns several times."""
-        for i in xrange(0, max(1, runnable.run_count)):
-          # TODO(machenbach): Allow timeout per arch like with run_count per
-          # arch.
-          yield platform.Run(runnable, i)
+        def Runner():
+          """Output generator that reruns several times."""
+          for i in xrange(0, max(1, runnable.run_count)):
+            # TODO(machenbach): Allow timeout per arch like with run_count per
+            # arch.
+            yield platform.Run(runnable, i)
 
-      # Let runnable iterate over all runs and handle output.
-      result, result_no_patch = runnable.Run(
+        # Let runnable iterate over all runs and handle output.
+        result, result_no_patch = runnable.Run(
           Runner, trybot=options.shell_dir_no_patch)
-      results += result
-      results_no_patch += result_no_patch
-    platform.PostExecution()
+        results += result
+        results_no_patch += result_no_patch
+      platform.PostExecution()
 
-  if options.json_test_results:
-    results.WriteToFile(options.json_test_results)
-  else:  # pragma: no cover
-    print results
+    if options.json_test_results:
+      results.WriteToFile(options.json_test_results)
+    else:  # pragma: no cover
+      print results
 
   if options.json_test_results_no_patch:
     results_no_patch.WriteToFile(options.json_test_results_no_patch)
diff --git a/tools/testrunner/local/execution.py b/tools/testrunner/local/execution.py
index e0aec0b..f3d11a8 100644
--- a/tools/testrunner/local/execution.py
+++ b/tools/testrunner/local/execution.py
@@ -248,7 +248,6 @@
       self.total += 1
 
   def _ProcessTestNormal(self, test, result, pool):
-    self.indicator.AboutToRun(test)
     test.output = result[1]
     test.duration = result[2]
     has_unexpected_output = test.suite.HasUnexpectedOutput(test)
@@ -285,7 +284,6 @@
     if test.run == 1 and result[1].HasTimedOut():
       # If we get a timeout in the first run, we are already in an
       # unpredictable state. Just report it as a failure and don't rerun.
-      self.indicator.AboutToRun(test)
       test.output = result[1]
       self.remaining -= 1
       self.failed.append(test)
@@ -294,16 +292,13 @@
       # From the second run on, check for different allocations. If a
       # difference is found, call the indicator twice to report both tests.
       # All runs of each test are counted as one for the statistic.
-      self.indicator.AboutToRun(test)
       self.remaining -= 1
       self.failed.append(test)
       self.indicator.HasRun(test, True)
-      self.indicator.AboutToRun(test)
       test.output = result[1]
       self.indicator.HasRun(test, True)
     elif test.run >= 3:
       # No difference on the third run -> report a success.
-      self.indicator.AboutToRun(test)
       self.remaining -= 1
       self.succeeded += 1
       test.output = result[1]
diff --git a/tools/testrunner/local/progress.py b/tools/testrunner/local/progress.py
index 4e1be3e..33e27e1 100644
--- a/tools/testrunner/local/progress.py
+++ b/tools/testrunner/local/progress.py
@@ -34,6 +34,7 @@
 
 from . import execution
 from . import junit_output
+from . import statusfile
 
 
 ABS_PATH_PREFIX = os.getcwd() + os.sep
@@ -53,9 +54,6 @@
   def Done(self):
     pass
 
-  def AboutToRun(self, test):
-    pass
-
   def HasRun(self, test, has_unexpected_output):
     pass
 
@@ -146,10 +144,6 @@
 
 class VerboseProgressIndicator(SimpleProgressIndicator):
 
-  def AboutToRun(self, test):
-    print 'Starting %s...' % test.GetLabel()
-    sys.stdout.flush()
-
   def HasRun(self, test, has_unexpected_output):
     if has_unexpected_output:
       if test.output.HasCrashed():
@@ -200,10 +194,8 @@
     self.PrintProgress('Done')
     print ""  # Line break.
 
-  def AboutToRun(self, test):
-    self.PrintProgress(test.GetLabel())
-
   def HasRun(self, test, has_unexpected_output):
+    self.PrintProgress(test.GetLabel())
     if has_unexpected_output:
       self.ClearLine(self.last_status_length)
       self.PrintFailureHeader(test)
@@ -329,6 +321,12 @@
         # Buildbot might start out with an empty file.
         complete_results = json.loads(f.read() or "[]")
 
+    duration_mean = None
+    if self.tests:
+      # Get duration mean.
+      duration_mean = (
+          sum(t.duration for t in self.tests) / float(len(self.tests)))
+
     # Sort tests by duration.
     timed_tests = [t for t in self.tests if t.duration is not None]
     timed_tests.sort(lambda a, b: cmp(b.duration, a.duration))
@@ -338,6 +336,7 @@
         "flags": test.flags,
         "command": self._EscapeCommand(test).replace(ABS_PATH_PREFIX, ""),
         "duration": test.duration,
+        "marked_slow": statusfile.IsSlow(test.outcomes),
       } for test in timed_tests[:20]
     ]
 
@@ -346,6 +345,8 @@
       "mode": self.mode,
       "results": self.results,
       "slowest_tests": slowest_tests,
+      "duration_mean": duration_mean,
+      "test_total": len(self.tests),
     })
 
     with open(self.json_test_results, "w") as f:
diff --git a/tools/testrunner/local/statusfile.py b/tools/testrunner/local/statusfile.py
index 7e96cc3..fde6237 100644
--- a/tools/testrunner/local/statusfile.py
+++ b/tools/testrunner/local/statusfile.py
@@ -36,6 +36,7 @@
 CRASH = "CRASH"
 SLOW = "SLOW"
 FAST_VARIANTS = "FAST_VARIANTS"
+NO_IGNITION = "NO_IGNITION"
 NO_VARIANTS = "NO_VARIANTS"
 # These are just for the status files and are mapped below in DEFS:
 FAIL_OK = "FAIL_OK"
@@ -46,7 +47,8 @@
 
 KEYWORDS = {}
 for key in [SKIP, FAIL, PASS, OKAY, TIMEOUT, CRASH, SLOW, FAIL_OK,
-            FAST_VARIANTS, NO_VARIANTS, PASS_OR_FAIL, FAIL_SLOPPY, ALWAYS]:
+            FAST_VARIANTS, NO_IGNITION, NO_VARIANTS, PASS_OR_FAIL, FAIL_SLOPPY,
+            ALWAYS]:
   KEYWORDS[key] = key
 
 DEFS = {FAIL_OK: [FAIL, OKAY],
@@ -70,6 +72,10 @@
   return SLOW in outcomes
 
 
+def NoIgnitionVariant(outcomes):
+  return NO_IGNITION in outcomes
+
+
 def OnlyStandardVariant(outcomes):
   return NO_VARIANTS in outcomes
 
diff --git a/tools/testrunner/local/testsuite.py b/tools/testrunner/local/testsuite.py
index f43d008..8e8b476 100644
--- a/tools/testrunner/local/testsuite.py
+++ b/tools/testrunner/local/testsuite.py
@@ -41,7 +41,8 @@
   "turbofan": [["--turbo"]],
   "turbofan_opt": [["--turbo", "--always-opt"]],
   "nocrankshaft": [["--nocrankshaft"]],
-  "ignition": [["--ignition", "--turbo"]],
+  "ignition": [["--ignition"]],
+  "ignition_turbofan": [["--ignition", "--turbo", "--turbo-from-bytecode"]],
   "preparser": [["--min-preparse-length=0"]],
 }
 
@@ -51,14 +52,17 @@
   "stress": [["--stress-opt"]],
   "turbofan": [["--turbo"]],
   "nocrankshaft": [["--nocrankshaft"]],
-  "ignition": [["--ignition", "--turbo"]],
+  "ignition": [["--ignition"]],
+  "ignition_turbofan": [["--ignition", "--turbo", "--turbo-from-bytecode"]],
   "preparser": [["--min-preparse-length=0"]],
 }
 
 ALL_VARIANTS = set(["default", "stress", "turbofan", "turbofan_opt",
-                    "nocrankshaft", "ignition", "preparser"])
+                    "nocrankshaft", "ignition", "ignition_turbofan",
+                    "preparser"])
 FAST_VARIANTS = set(["default", "turbofan"])
 STANDARD_VARIANT = set(["default"])
+IGNITION_VARIANT = set(["ignition"])
 
 
 class VariantGenerator(object):
@@ -69,12 +73,15 @@
     self.standard_variant = STANDARD_VARIANT & variants
 
   def FilterVariantsByTest(self, testcase):
-    if testcase.outcomes and statusfile.OnlyStandardVariant(
-        testcase.outcomes):
-      return self.standard_variant
-    if testcase.outcomes and statusfile.OnlyFastVariants(testcase.outcomes):
-      return self.fast_variants
-    return self.all_variants
+    result = self.all_variants
+    if testcase.outcomes:
+      if statusfile.OnlyStandardVariant(testcase.outcomes):
+        return self.standard_variant
+      if statusfile.OnlyFastVariants(testcase.outcomes):
+        result = self.fast_variants
+      if statusfile.NoIgnitionVariant(testcase.outcomes):
+        result = result - IGNITION_VARIANT
+    return result
 
   def GetFlagSets(self, testcase, variant):
     if testcase.outcomes and statusfile.OnlyFastVariants(testcase.outcomes):
diff --git a/tools/testrunner/network/network_execution.py b/tools/testrunner/network/network_execution.py
index c842aba..a954401 100644
--- a/tools/testrunner/network/network_execution.py
+++ b/tools/testrunner/network/network_execution.py
@@ -203,7 +203,6 @@
                   [constants.INFORM_DURATION, perf_key, test.duration,
                    self.context.arch, self.context.mode],
                   self.local_socket)
-              self.indicator.AboutToRun(test)
               has_unexpected_output = test.suite.HasUnexpectedOutput(test)
               if has_unexpected_output:
                 self.failed.append(test)
diff --git a/tools/testrunner/server/main.py b/tools/testrunner/server/main.py
index 1000713..c237e1a 100644
--- a/tools/testrunner/server/main.py
+++ b/tools/testrunner/server/main.py
@@ -221,7 +221,7 @@
     if not self.IsTrusted(signer):
       return
     if self.IsTrusted(fingerprint):
-      return  # Already trust this guy.
+      return  # Already trusted.
     filename = self._PubkeyFilename(fingerprint)
     signer_pubkeyfile = self._PubkeyFilename(signer)
     if not signatures.VerifySignature(filename, pubkey, signature,
diff --git a/tools/tickprocessor-driver.js b/tools/tickprocessor-driver.js
index 3f2321f..be374c9 100644
--- a/tools/tickprocessor-driver.js
+++ b/tools/tickprocessor-driver.js
@@ -72,6 +72,7 @@
   sourceMap,
   params.timedRange,
   params.pairwiseTimedRange,
-  params.onlySummary);
+  params.onlySummary,
+  params.runtimeTimerFilter);
 tickProcessor.processLogFile(params.logFileName);
 tickProcessor.printStatistics();
diff --git a/tools/tickprocessor.js b/tools/tickprocessor.js
index ba7401a..ec56d49 100644
--- a/tools/tickprocessor.js
+++ b/tools/tickprocessor.js
@@ -81,9 +81,10 @@
     sourceMap,
     timedRange,
     pairwiseTimedRange,
-    onlySummary) {
+    onlySummary,
+    runtimeTimerFilter) {
   LogReader.call(this, {
-      'shared-library': { parsers: [null, parseInt, parseInt],
+      'shared-library': { parsers: [null, parseInt, parseInt, parseInt],
           processor: this.processSharedLibrary },
       'code-creation': {
           parsers: [null, parseInt, parseInt, parseInt, null, 'var-args'],
@@ -94,6 +95,9 @@
           processor: this.processCodeDelete },
       'sfi-move': { parsers: [parseInt, parseInt],
           processor: this.processFunctionMove },
+      'active-runtime-timer': {
+        parsers: [null],
+        processor: this.processRuntimeTimerEvent },
       'tick': {
           parsers: [parseInt, parseInt, parseInt,
                     parseInt, parseInt, 'var-args'],
@@ -124,6 +128,7 @@
   this.callGraphSize_ = callGraphSize;
   this.ignoreUnknown_ = ignoreUnknown;
   this.stateFilter_ = stateFilter;
+  this.runtimeTimerFilter_ = runtimeTimerFilter;
   this.sourceMap = sourceMap;
   this.deserializedEntriesNames_ = [];
   var ticks = this.ticks_ =
@@ -242,13 +247,13 @@
 
 
 TickProcessor.prototype.processSharedLibrary = function(
-    name, startAddr, endAddr) {
-  var entry = this.profile_.addLibrary(name, startAddr, endAddr);
+    name, startAddr, endAddr, aslrSlide) {
+  var entry = this.profile_.addLibrary(name, startAddr, endAddr, aslrSlide);
   this.setCodeType(entry.getName(), 'SHARED_LIB');
 
   var self = this;
   var libFuncs = this.cppEntriesProvider_.parseVmSymbols(
-      name, startAddr, endAddr, function(fName, fStart, fEnd) {
+      name, startAddr, endAddr, aslrSlide, function(fName, fStart, fEnd) {
     self.profile_.addStaticCode(fName, fStart, fEnd);
     self.setCodeType(fName, 'CPP');
   });
@@ -284,9 +289,18 @@
 
 
 TickProcessor.prototype.includeTick = function(vmState) {
-  return this.stateFilter_ == null || this.stateFilter_ == vmState;
+  if (this.stateFilter_ !== null) {
+    return this.stateFilter_ == vmState;
+  } else if (this.runtimeTimerFilter_ !== null) {
+    return this.currentRuntimeTimer == this.runtimeTimerFilter_;
+  }
+  return true;
 };
 
+TickProcessor.prototype.processRuntimeTimerEvent = function(name) {
+  this.currentRuntimeTimer = name;
+}
+
 TickProcessor.prototype.processTick = function(pc,
                                                ns_since_start,
                                                is_external_callback,
@@ -559,7 +573,7 @@
 
 
 CppEntriesProvider.prototype.parseVmSymbols = function(
-    libName, libStart, libEnd, processorFunc) {
+    libName, libStart, libEnd, libASLRSlide, processorFunc) {
   this.loadSymbols(libName);
 
   var prevEntry;
@@ -588,6 +602,7 @@
     } else if (funcInfo === false) {
       break;
     }
+    funcInfo.start += libASLRSlide;
     if (funcInfo.start < libStart && funcInfo.start < libEnd - libStart) {
       funcInfo.start += libStart;
     }
@@ -780,6 +795,8 @@
         'Show only ticks from OTHER VM state'],
     '-e': ['stateFilter', TickProcessor.VmStates.EXTERNAL,
         'Show only ticks from EXTERNAL VM state'],
+    '--filter-runtime-timer': ['runtimeTimerFilter', null,
+            'Show only ticks matching the given runtime timer scope'],
     '--call-graph-size': ['callGraphSize', TickProcessor.CALL_GRAPH_SIZE,
         'Set the call graph size'],
     '--ignore-unknown': ['ignoreUnknown', true,
@@ -831,7 +848,8 @@
   distortion: 0,
   timedRange: false,
   pairwiseTimedRange: false,
-  onlySummary: false
+  onlySummary: false,
+  runtimeTimerFilter: null,
 };
 
 
diff --git a/tools/try_perf.py b/tools/try_perf.py
index fbd4036..e022ab4 100755
--- a/tools/try_perf.py
+++ b/tools/try_perf.py
@@ -33,17 +33,23 @@
   'emscripten',
   'compile',
   'jetstream',
+  'jetstream-ignition',
   'jsbench',
   'jstests',
   'kraken_orig',
+  'kraken_orig-ignition',
   'massive',
   'memory',
   'octane',
+  'octane-noopt',
+  'octane-ignition',
   'octane-pr',
   'octane-tf',
   'octane-tf-pr',
   'simdjs',
   'sunspider',
+  'sunspider-ignition',
+  'wasm',
 ]
 
 V8_BASE = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
diff --git a/tools/turbolizer/OWNERS b/tools/turbolizer/OWNERS
new file mode 100644
index 0000000..fc52961
--- /dev/null
+++ b/tools/turbolizer/OWNERS
@@ -0,0 +1 @@
+danno@chromium.org
diff --git a/tools/turbolizer/README b/tools/turbolizer/README
new file mode 100644
index 0000000..99548b0
--- /dev/null
+++ b/tools/turbolizer/README
@@ -0,0 +1,20 @@
+Turbolizer is a HTML-based tool that visualizes optimized code along the various
+phases of Turbofan's optimization pipeline, allowing easy navigation between
+source code, Turbofan IR graphs, scheduled IR nodes and generated assembly code.
+
+Turbolizer consumes .json files that are generated per-function by d8 by passing
+the '--trace-turbo' command-line flag.
+
+Host the turbolizer locally by starting a web server that serves the contents of
+the turbolizer directory, e.g.:
+
+cd src/tools/turbolizer
+python -m SimpleHTTPServer 8000
+
+Graph visualization and manipulation based on Mike Bostock's sample code for an
+interactive tool for creating directed graphs. Original source is at
+https://github.com/metacademy/directed-graph-creator and released under the
+MIT/X license.
+
+Icons dervied from the "White Olive Collection" created by Breezi released under
+the Creative Commons BY license.
diff --git a/tools/turbolizer/code-view.js b/tools/turbolizer/code-view.js
new file mode 100644
index 0000000..aa106d3
--- /dev/null
+++ b/tools/turbolizer/code-view.js
@@ -0,0 +1,177 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var CodeView = function(divID, PR, sourceText, sourcePosition, broker) {
+  "use strict";
+  var view = this;
+
+  view.divElement = document.getElementById(divID);
+  view.broker = broker;
+  view.codeSelection = null;
+  view.allSpans = [];
+
+  var selectionHandler = {
+    clear: function() {
+      broker.clear(selectionHandler);
+    },
+    select: function(items, selected) {
+      var handler = this;
+      var divElement = view.divElement;
+      var broker = view.broker;
+      for (let span of items) {
+        if (selected) {
+          span.classList.add("selected");
+        } else {
+          span.classList.remove("selected");
+        }
+      }
+      var ranges = [];
+      for (var span of items) {
+        ranges.push([span.start, span.end, null]);
+      }
+      broker.select(selectionHandler, ranges, selected);
+    },
+    selectionDifference: function(span1, inclusive1, span2, inclusive2) {
+      var pos1 = span1.start;
+      var pos2 = span2.start;
+      var result = [];
+      var lineListDiv = view.divElement.firstChild.firstChild.childNodes;
+      for (var i=0; i < lineListDiv.length; i++) {
+        var currentLineElement = lineListDiv[i];
+        var spans = currentLineElement.childNodes;
+        for (var j=0; j < spans.length; ++j) {
+          var currentSpan = spans[j];
+          if (currentSpan.start > pos1 || (inclusive1 && currentSpan.start == pos1)) {
+            if (currentSpan.start < pos2 || (inclusive2 && currentSpan.start == pos2)) {
+              result.push(currentSpan);
+            }
+          }
+        }
+      }
+      return result;
+    },
+    brokeredSelect: function(ranges, selected) {
+      var firstSelect = view.codeSelection.isEmpty();
+      for (var range of ranges) {
+        var start = range[0];
+        var end = range[1];
+        var lower = 0;
+        var upper = view.allSpans.length;
+        if (upper > 0) {
+          while ((upper - lower) > 1) {
+            var middle = Math.floor((upper + lower) / 2);
+            var lineStart = view.allSpans[middle].start;
+            if (lineStart < start) {
+              lower = middle;
+            } else if (lineStart > start) {
+              upper = middle;
+            } else {
+              lower = middle;
+              break;
+            }
+          }
+          var currentSpan = view.allSpans[lower];
+          var currentLineElement = currentSpan.parentNode;
+          if ((currentSpan.start <= start && start < currentSpan.end) ||
+              (currentSpan.start <= end && end < currentSpan.end)) {
+            if (firstSelect) {
+              makeContainerPosVisible(view.divElement, currentLineElement.offsetTop);
+              firstSelect = false;
+            }
+            view.codeSelection.select(currentSpan, selected);
+          }
+        }
+      }
+    },
+    brokeredClear: function() {
+      view.codeSelection.clear();
+    },
+  };
+
+  view.codeSelection = new Selection(selectionHandler);
+  broker.addSelectionHandler(selectionHandler);
+
+  var mouseDown = false;
+
+  this.handleSpanMouseDown = function(e) {
+    e.stopPropagation();
+    if (!e.shiftKey) {
+      view.codeSelection.clear();
+    }
+    view.codeSelection.select(this, true);
+    mouseDown = true;
+  }
+
+  this.handleSpanMouseMove = function(e) {
+    if (mouseDown) {
+      view.codeSelection.extendTo(this);
+    }
+  }
+
+  this.handleCodeMouseDown = function(e) {
+    view.codeSelection.clear();
+  }
+
+  document.addEventListener('mouseup', function(e){
+    mouseDown = false;
+  }, false);
+
+  this.initializeCode(sourceText, sourcePosition);
+}
+
+CodeView.prototype.initializeCode = function(sourceText, sourcePosition) {
+  var view = this;
+  if (sourceText == "") {
+    var newHtml = "<pre class=\"prettyprint\"</pre>";
+    view.divElement.innerHTML = newHtml;
+  } else {
+    var newHtml = "<pre class=\"prettyprint linenums\">"
+      + sourceText + "</pre>";
+    view.divElement.innerHTML = newHtml;
+    try {
+      // Wrap in try to work when offline.
+      PR.prettyPrint();
+    } catch (e) {
+    }
+
+    view.divElement.onmousedown = this.handleCodeMouseDown;
+
+    var base = sourcePosition;
+    var current = 0;
+    var lineListDiv = view.divElement.firstChild.firstChild.childNodes;
+    for (i=0; i < lineListDiv.length; i++) {
+      var currentLineElement = lineListDiv[i];
+      currentLineElement.id = "li" + i;
+      var pos = base + current;
+      currentLineElement.pos = pos;
+      var spans = currentLineElement.childNodes;
+      for (j=0; j < spans.length; ++j) {
+        var currentSpan = spans[j];
+        if (currentSpan.nodeType == 1) {
+          currentSpan.start = pos;
+          currentSpan.end = pos + currentSpan.textContent.length;
+          currentSpan.onmousedown = this.handleSpanMouseDown;
+          currentSpan.onmousemove = this.handleSpanMouseMove;
+          view.allSpans.push(currentSpan);
+        }
+        current += currentSpan.textContent.length;
+        pos = base + current;
+      }
+      while ((current < sourceText.length) && (
+        sourceText[current] == '\n' ||
+          sourceText[current] == '\r')) {
+        ++current;
+      }
+    }
+  }
+
+  this.resizeToParent();
+}
+
+CodeView.prototype.resizeToParent = function() {
+  var view = this;
+  var documentElement = document.documentElement;
+  var y = view.divElement.parentNode.clientHeight || documentElement.clientHeight;
+  view.divElement.style.height = y + "px";
+}
diff --git a/tools/turbolizer/constants.js b/tools/turbolizer/constants.js
new file mode 100644
index 0000000..f380431
--- /dev/null
+++ b/tools/turbolizer/constants.js
@@ -0,0 +1,22 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var MAX_RANK_SENTINEL = 0;
+var GRAPH_MARGIN = 250;
+var WIDTH = 'width';
+var HEIGHT = 'height';
+var VISIBILITY = 'visibility';
+var SOURCE_PANE_ID = 'left';
+var SOURCE_COLLAPSE_ID = 'source-shrink';
+var SOURCE_EXPAND_ID = 'source-expand';
+var INTERMEDIATE_PANE_ID = 'middle';
+var EMPTY_PANE_ID = 'empty';
+var GRAPH_PANE_ID = 'graph';
+var SCHEDULE_PANE_ID = 'schedule';
+var GENERATED_PANE_ID = 'right';
+var DISASSEMBLY_PANE_ID = 'disassembly';
+var DISASSEMBLY_COLLAPSE_ID = 'disassembly-shrink';
+var DISASSEMBLY_EXPAND_ID = 'disassembly-expand';
+var COLLAPSE_PANE_BUTTON_VISIBLE = 'button-input';
+var COLLAPSE_PANE_BUTTON_INVISIBLE = 'button-input-invisible';
diff --git a/tools/turbolizer/disassembly-view.js b/tools/turbolizer/disassembly-view.js
new file mode 100644
index 0000000..94150ec
--- /dev/null
+++ b/tools/turbolizer/disassembly-view.js
@@ -0,0 +1,106 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+"use strict";
+
+class DisassemblyView extends TextView {
+  constructor(id, broker, sortedPositionList) {
+    super(id, broker, null, false);
+    this.pos_start = -1;
+    let view = this;
+    let ADDRESS_STYLE = {
+      css: 'tag',
+      location: function(text) {
+        ADDRESS_STYLE.last_address = text;
+        return undefined;
+      }
+    };
+    let ADDRESS_LINK_STYLE = {
+      css: 'tag',
+      link: function(text) {
+        view.select(function(location) { return location.address == text; }, true, true);
+      }
+    };
+    let UNCLASSIFIED_STYLE = {
+      css: 'com'
+    };
+    let NUMBER_STYLE = {
+      css: 'lit'
+    };
+    let COMMENT_STYLE = {
+      css: 'com'
+    };
+    let POSITION_STYLE = {
+      css: 'com',
+      location: function(text) {
+        view.pos_start = Number(text);
+      }
+    };
+    let OPCODE_STYLE = {
+      css: 'kwd',
+      location: function(text) {
+        return {
+          address: ADDRESS_STYLE.last_address
+        };
+      }
+    };
+    let patterns = [
+      [
+        [/^0x[0-9a-f]{8,16}/, ADDRESS_STYLE, 1],
+        [/^.*/, UNCLASSIFIED_STYLE, -1]
+      ],
+      [
+        [/^\s+\d+\s+[0-9a-f]+\s+/, NUMBER_STYLE, 2],
+        [/^.*/, null, -1]
+      ],
+      [
+        [/^\S+\s+/, OPCODE_STYLE, 3],
+        [/^\S+$/, OPCODE_STYLE, -1],
+        [/^.*/, null, -1]
+      ],
+      [
+        [/^\s+/, null],
+        [/^[^\(;]+$/, null, -1],
+        [/^[^\(;]+/, null],
+        [/^\(/, null, 4],
+        [/^;/, COMMENT_STYLE, 5]
+      ],
+      [
+        [/^0x[0-9a-f]{8,16}/, ADDRESS_LINK_STYLE],
+        [/^[^\)]/, null],
+        [/^\)$/, null, -1],
+        [/^\)/, null, 3]
+      ],
+      [
+        [/^; debug\: position /, COMMENT_STYLE, 6],
+        [/^.+$/, COMMENT_STYLE, -1]
+      ],
+      [
+        [/^\d+$/, POSITION_STYLE, -1],
+      ]
+    ];
+    view.setPatterns(patterns);
+  }
+
+  lineLocation(li) {
+    let view = this;
+    let result = undefined;
+    for (let i = 0; i < li.children.length; ++i) {
+      let fragment = li.children[i];
+      let location = fragment.location;
+      if (location != null) {
+        if (location.address != undefined) {
+          if (result === undefined) result = {};
+          result.address = location.address;
+        }
+        if (view.pos_start != -1) {
+          if (result === undefined) result = {};
+          result.pos_start = view.pos_start;
+          result.pos_end = result.pos_start + 1;
+        }
+      }
+    }
+    return result;
+  }
+}
diff --git a/tools/turbolizer/edge.js b/tools/turbolizer/edge.js
new file mode 100644
index 0000000..7e46391
--- /dev/null
+++ b/tools/turbolizer/edge.js
@@ -0,0 +1,77 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var MINIMUM_EDGE_SEPARATION = 20;
+
+function isEdgeInitiallyVisible(target, index, source, type) {
+  return type == "control" && (target.cfg || source.cfg);
+}
+
+var Edge = function(target, index, source, type) {
+  this.target = target;
+  this.source = source;
+  this.index = index;
+  this.type = type;
+  this.backEdgeNumber = 0;
+  this.visible = isEdgeInitiallyVisible(target, index, source, type);
+};
+
+Edge.prototype.stringID = function() {
+  return this.source.id + "," + this.index +  "," + this.target.id;
+};
+
+Edge.prototype.isVisible = function() {
+  return this.visible && this.source.visible && this.target.visible;
+};
+
+Edge.prototype.getInputHorizontalPosition = function(graph) {
+  if (this.backEdgeNumber > 0) {
+    return graph.maxGraphNodeX + this.backEdgeNumber * MINIMUM_EDGE_SEPARATION;
+  }
+  var source = this.source;
+  var target = this.target;
+  var index = this.index;
+  var input_x = target.x + target.getInputX(index);
+  var inputApproach = target.getInputApproach(this.index);
+  var outputApproach = source.getOutputApproach(graph);
+  if (inputApproach > outputApproach) {
+    return input_x;
+  } else {
+    var inputOffset = MINIMUM_EDGE_SEPARATION * (index + 1);
+    return (target.x < source.x)
+      ? (target.x + target.getTotalNodeWidth() + inputOffset)
+      : (target.x - inputOffset)
+  }
+}
+
+Edge.prototype.generatePath = function(graph) {
+  var target = this.target;
+  var source = this.source;
+  var input_x = target.x + target.getInputX(this.index);
+  var output_x = source.x + source.getOutputX();
+  var output_y = source.y + DEFAULT_NODE_HEIGHT + DEFAULT_NODE_BUBBLE_RADIUS;
+  var inputApproach = target.getInputApproach(this.index);
+  var outputApproach = source.getOutputApproach(graph);
+  var horizontalPos = this.getInputHorizontalPosition(graph);
+
+  var result = "M" + output_x + "," + output_y +
+    "L" + output_x + "," + outputApproach +
+    "L" + horizontalPos + "," + outputApproach;
+
+  if (horizontalPos != input_x) {
+    result += "L" + horizontalPos + "," + inputApproach;
+  } else {
+    if (inputApproach < outputApproach) {
+      inputApproach = outputApproach;
+    }
+  }
+
+  result += "L" + input_x + "," + inputApproach +
+    "L" + input_x + "," + (target.y - DEFAULT_NODE_BUBBLE_RADIUS - 12);
+  return result;
+}
+
+Edge.prototype.isBackEdge = function() {
+  return this.target.hasBackEdges() && (this.target.rank < this.source.rank);
+}
diff --git a/tools/turbolizer/empty-view.js b/tools/turbolizer/empty-view.js
new file mode 100644
index 0000000..66caf59
--- /dev/null
+++ b/tools/turbolizer/empty-view.js
@@ -0,0 +1,19 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+"use strict";
+
+class EmptyView extends View {
+  constructor(id, broker) {
+    super(id, broker);
+    this.svg = this.divElement.append("svg").attr('version','1.1').attr("width", "100%");
+  }
+
+  initializeContent(data, rememberedSelection) {
+    this.svg.attr("height", document.documentElement.clientHeight + "px");
+  }
+
+  deleteContent() {
+  }
+}
diff --git a/tools/turbolizer/expand-all.jpg b/tools/turbolizer/expand-all.jpg
new file mode 100644
index 0000000..df64a2c
--- /dev/null
+++ b/tools/turbolizer/expand-all.jpg
Binary files differ
diff --git a/tools/turbolizer/graph-layout.js b/tools/turbolizer/graph-layout.js
new file mode 100644
index 0000000..8e411b7
--- /dev/null
+++ b/tools/turbolizer/graph-layout.js
@@ -0,0 +1,474 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var DEFAULT_NODE_ROW_SEPARATION = 130
+
+var traceLayout = false;
+
+function newGraphOccupation(graph){
+  var isSlotFilled = [];
+  var maxSlot = 0;
+  var minSlot = 0;
+  var nodeOccupation = [];
+
+  function slotToIndex(slot) {
+    if (slot >= 0) {
+      return slot * 2;
+    } else {
+      return slot * 2 + 1;
+    }
+  }
+
+  function indexToSlot(index) {
+    if ((index % 0) == 0) {
+      return index / 2;
+    } else {
+      return -((index - 1) / 2);
+    }
+  }
+
+  function positionToSlot(pos) {
+    return Math.floor(pos / NODE_INPUT_WIDTH);
+  }
+
+  function slotToLeftPosition(slot) {
+    return slot * NODE_INPUT_WIDTH
+  }
+
+  function slotToRightPosition(slot) {
+    return (slot + 1) * NODE_INPUT_WIDTH
+  }
+
+  function findSpace(pos, width, direction) {
+    var widthSlots = Math.floor((width + NODE_INPUT_WIDTH - 1) /
+                                NODE_INPUT_WIDTH);
+    var currentSlot = positionToSlot(pos + width / 2);
+    var currentScanSlot = currentSlot;
+    var widthSlotsRemainingLeft = widthSlots;
+    var widthSlotsRemainingRight = widthSlots;
+    var slotsChecked = 0;
+    while (true) {
+      var mod = slotsChecked++ % 2;
+      currentScanSlot = currentSlot + (mod ? -1 : 1) * (slotsChecked >> 1);
+      if (!isSlotFilled[slotToIndex(currentScanSlot)]) {
+        if (mod) {
+          if (direction <= 0) --widthSlotsRemainingLeft
+        } else {
+          if (direction >= 0) --widthSlotsRemainingRight
+        }
+        if (widthSlotsRemainingLeft == 0 ||
+            widthSlotsRemainingRight == 0 ||
+            (widthSlotsRemainingLeft + widthSlotsRemainingRight) == widthSlots &&
+            (widthSlots == slotsChecked)) {
+          if (mod) {
+            return [currentScanSlot, widthSlots];
+          } else {
+            return [currentScanSlot - widthSlots + 1, widthSlots];
+          }
+        }
+      } else {
+        if (mod) {
+          widthSlotsRemainingLeft = widthSlots;
+        } else {
+          widthSlotsRemainingRight = widthSlots;
+        }
+      }
+    }
+  }
+
+  function setIndexRange(from, to, value) {
+    if (to < from) {
+      throw("illegal slot range");
+    }
+    while (from <= to) {
+      if (from > maxSlot) {
+        maxSlot = from;
+      }
+      if (from < minSlot) {
+        minSlot = from;
+      }
+      isSlotFilled[slotToIndex(from++)] = value;
+    }
+  }
+
+  function occupySlotRange(from, to) {
+    if (traceLayout) {
+      console.log("Occupied [" + slotToLeftPosition(from) + "  " + slotToLeftPosition(to + 1) + ")");
+    }
+    setIndexRange(from, to, true);
+  }
+
+  function clearSlotRange(from, to) {
+    if (traceLayout) {
+      console.log("Cleared [" + slotToLeftPosition(from) + "  " + slotToLeftPosition(to + 1) + ")");
+    }
+    setIndexRange(from, to, false);
+  }
+
+  function occupyPositionRange(from, to) {
+    occupySlotRange(positionToSlot(from), positionToSlot(to - 1));
+  }
+
+  function clearPositionRange(from, to) {
+    clearSlotRange(positionToSlot(from), positionToSlot(to - 1));
+  }
+
+  function occupyPositionRangeWithMargin(from, to, margin) {
+    var fromMargin = from - Math.floor(margin);
+    var toMargin = to + Math.floor(margin);
+    occupyPositionRange(fromMargin, toMargin);
+  }
+
+  function clearPositionRangeWithMargin(from, to, margin) {
+    var fromMargin = from - Math.floor(margin);
+    var toMargin = to + Math.floor(margin);
+    clearPositionRange(fromMargin, toMargin);
+  }
+
+  var occupation = {
+    occupyNodeInputs: function(node) {
+      for (var i = 0; i < node.inputs.length; ++i) {
+        if (node.inputs[i].isVisible()) {
+          var edge = node.inputs[i];
+          if (!edge.isBackEdge()) {
+            var source = edge.source;
+            var horizontalPos = edge.getInputHorizontalPosition(graph);
+            if (traceLayout) {
+              console.log("Occupying input " + i + " of " + node.id + " at " + horizontalPos);
+            }
+            occupyPositionRangeWithMargin(horizontalPos,
+                                          horizontalPos,
+                                          NODE_INPUT_WIDTH / 2);
+          }
+        }
+      }
+    },
+    occupyNode: function(node) {
+      var getPlacementHint = function(n) {
+        var pos = 0;
+        var direction = -1;
+        var outputEdges = 0;
+        var inputEdges = 0;
+        for (var k = 0; k < n.outputs.length; ++k) {
+          var outputEdge = n.outputs[k];
+          if (outputEdge.isVisible()) {
+            var output = n.outputs[k].target;
+            for (var l = 0; l < output.inputs.length; ++l) {
+              if (output.rank > n.rank) {
+                var inputEdge = output.inputs[l];
+                if (inputEdge.isVisible()) {
+                  ++inputEdges;
+                }
+                if (output.inputs[l].source == n) {
+                  pos += output.x + output.getInputX(l) + NODE_INPUT_WIDTH / 2;
+                  outputEdges++;
+                  if (l >= (output.inputs.length / 2)) {
+                    direction = 1;
+                  }
+                }
+              }
+            }
+          }
+        }
+        if (outputEdges != 0) {
+          pos = pos / outputEdges;
+        }
+        if (outputEdges > 1 || inputEdges == 1) {
+          direction = 0;
+        }
+        return [direction, pos];
+      }
+      var width = node.getTotalNodeWidth();
+      var margin = MINIMUM_EDGE_SEPARATION;
+      var paddedWidth = width + 2 * margin;
+      var placementHint = getPlacementHint(node);
+      var x = placementHint[1] - paddedWidth + margin;
+      if (traceLayout) {
+        console.log("Node " + node.id + " placement hint [" + x + ", " + (x + paddedWidth) + ")");
+      }
+      var placement = findSpace(x, paddedWidth, placementHint[0]);
+      var firstSlot = placement[0];
+      var slotWidth = placement[1];
+      var endSlotExclusive = firstSlot + slotWidth - 1;
+      occupySlotRange(firstSlot, endSlotExclusive);
+      nodeOccupation.push([firstSlot, endSlotExclusive]);
+      if (placementHint[0] < 0) {
+        return slotToLeftPosition(firstSlot + slotWidth) - width - margin;
+      } else if (placementHint[0] > 0) {
+        return slotToLeftPosition(firstSlot) + margin;
+      } else {
+        return slotToLeftPosition(firstSlot + slotWidth / 2) - (width / 2);
+      }
+    },
+    clearOccupiedNodes: function() {
+      nodeOccupation.forEach(function(o) {
+        clearSlotRange(o[0], o[1]);
+      });
+      nodeOccupation = [];
+    },
+    clearNodeOutputs: function(source) {
+      source.outputs.forEach(function(edge) {
+        if (edge.isVisible()) {
+          var target = edge.target;
+          for (var i = 0; i < target.inputs.length; ++i) {
+            if (target.inputs[i].source === source) {
+              var horizontalPos = edge.getInputHorizontalPosition(graph);
+              clearPositionRangeWithMargin(horizontalPos,
+                                           horizontalPos,
+                                           NODE_INPUT_WIDTH / 2);
+            }
+          }
+        }
+      });
+    },
+    print: function() {
+      var s = "";
+      for (var currentSlot = -40; currentSlot < 40; ++currentSlot) {
+        if (currentSlot != 0) {
+          s += " ";
+        } else {
+          s += "|";
+        }
+      }
+      console.log(s);
+      s = "";
+      for (var currentSlot2 = -40; currentSlot2 < 40; ++currentSlot2) {
+        if (isSlotFilled[slotToIndex(currentSlot2)]) {
+          s += "*";
+        } else {
+          s += " ";
+        }
+      }
+      console.log(s);
+    }
+  }
+  return occupation;
+}
+
+function layoutNodeGraph(graph) {
+  graph.minGraphX = 0;
+  graph.maxGraphNodeX = 1;
+  graph.maxGraphX = 1;
+  graph.minGraphY = 0;
+  graph.maxGraphY = 1;
+
+  // First determine the set of nodes that have no outputs. Those are the
+  // basis for bottom-up DFS to determine rank and node placement.
+  var endNodesHasNoOutputs = [];
+  var startNodesHasNoInputs = [];
+  graph.nodes.forEach(function(n, i){
+    endNodesHasNoOutputs[n.id] = true;
+    startNodesHasNoInputs[n.id] = true;
+  });
+  graph.edges.forEach(function(e, i){
+    endNodesHasNoOutputs[e.source.id] = false;
+    startNodesHasNoInputs[e.target.id] = false;
+  });
+
+  // Finialize the list of start and end nodes.
+  var endNodes = [];
+  var startNodes = [];
+  var visited = [];
+  var rank = [];
+  graph.nodes.forEach(function(n, i){
+    if (endNodesHasNoOutputs[n.id]) {
+      endNodes.push(n);
+    }
+    if (startNodesHasNoInputs[n.id]) {
+      startNodes.push(n);
+    }
+    visited[n.id] = false;
+    rank[n.id] = -1;
+    n.rank = 0;
+    n.visitOrderWithinRank = 0;
+    n.outputApproach = MINIMUM_NODE_OUTPUT_APPROACH;
+  });
+
+
+  var maxRank = 0;
+  var visited = [];
+  var dfsStack = [];
+  var visitOrderWithinRank = 0;
+
+  var worklist = startNodes.slice();
+  while (worklist.length != 0) {
+    var n = worklist.pop();
+    var changed = false;
+    if (n.rank == MAX_RANK_SENTINEL) {
+      n.rank = 1;
+      changed = true;
+    }
+    var begin = 0;
+    var end = n.inputs.length;
+    if (n.opcode == 'Phi' || n.opcode == 'EffectPhi') {
+      // Keep with merge or loop node
+      begin = n.inputs.length - 1;
+    } else if (n.hasBackEdges()) {
+      end = 1;
+    }
+    for (var l = begin; l < end; ++l) {
+      var input = n.inputs[l].source;
+      if (input.visible && input.rank >= n.rank) {
+        n.rank = input.rank + 1;
+        changed = true;
+      }
+    }
+    if (changed) {
+      var hasBackEdges = n.hasBackEdges();
+      for (var l = n.outputs.length - 1; l >= 0; --l) {
+        if (hasBackEdges && (l != 0)) {
+          worklist.unshift(n.outputs[l].target);
+        } else {
+          worklist.push(n.outputs[l].target);
+        }
+      }
+    }
+    if (n.rank > maxRank) {
+      maxRank = n.rank;
+    }
+  }
+
+   visited = [];
+  function dfsFindRankLate(n) {
+    if (visited[n.id]) return;
+    visited[n.id] = true;
+    var originalRank = n.rank;
+    var newRank = n.rank;
+    var firstInput = true;
+    for (var l = 0; l < n.outputs.length; ++l) {
+      var output = n.outputs[l].target;
+      dfsFindRankLate(output);
+      var outputRank = output.rank;
+      if (output.visible && (firstInput || outputRank <= newRank) &&
+          (outputRank > originalRank)) {
+        newRank = outputRank - 1;
+      }
+      firstInput = false;
+    }
+    if (n.opcode != "Start" && n.opcode != "Phi" && n.opcode != "EffectPhi") {
+      n.rank = newRank;
+    }
+  }
+
+  startNodes.forEach(dfsFindRankLate);
+
+  visited = [];
+  function dfsRankOrder(n) {
+    if (visited[n.id]) return;
+    visited[n.id] = true;
+    for (var l = 0; l < n.outputs.length; ++l) {
+      var edge = n.outputs[l];
+      if (edge.isVisible()) {
+        var output = edge.target;
+        dfsRankOrder(output);
+      }
+    }
+    if (n.visitOrderWithinRank == 0) {
+      n.visitOrderWithinRank = ++visitOrderWithinRank;
+    }
+  }
+  startNodes.forEach(dfsRankOrder);
+
+  endNodes.forEach(function(n) {
+    n.rank = maxRank + 1;
+  });
+
+  var rankSets = [];
+  // Collect sets for each rank.
+  graph.nodes.forEach(function(n, i){
+    n.y = n.rank * (DEFAULT_NODE_ROW_SEPARATION + graph.getNodeHeight() +
+                    2 * DEFAULT_NODE_BUBBLE_RADIUS);
+    if (n.visible) {
+      if (rankSets[n.rank] === undefined) {
+        rankSets[n.rank] = [n];
+      } else {
+        rankSets[n.rank].push(n);
+      }
+    }
+  });
+
+  // Iterate backwards from highest to lowest rank, placing nodes so that they
+  // spread out from the "center" as much as possible while still being
+  // compact and not overlapping live input lines.
+  var occupation = newGraphOccupation(graph);
+  var rankCount = 0;
+
+  rankSets.reverse().forEach(function(rankSet) {
+
+    for (var i = 0; i < rankSet.length; ++i) {
+      occupation.clearNodeOutputs(rankSet[i]);
+    }
+
+    if (traceLayout) {
+      console.log("After clearing outputs");
+      occupation.print();
+    }
+
+    var placedCount = 0;
+    rankSet = rankSet.sort(function(a,b) {
+      return a.visitOrderWithinRank < b.visitOrderWithinRank;
+    });
+    for (var i = 0; i < rankSet.length; ++i) {
+      var nodeToPlace = rankSet[i];
+      if (nodeToPlace.visible) {
+        nodeToPlace.x = occupation.occupyNode(nodeToPlace);
+        if (traceLayout) {
+          console.log("Node " + nodeToPlace.id + " is placed between [" + nodeToPlace.x + ", " + (nodeToPlace.x + nodeToPlace.getTotalNodeWidth()) + ")");
+        }
+        var staggeredFlooredI = Math.floor(placedCount++ % 3);
+        var delta = MINIMUM_EDGE_SEPARATION * staggeredFlooredI
+        nodeToPlace.outputApproach += delta;
+      } else {
+        nodeToPlace.x = 0;
+      }
+
+      if (nodeToPlace.x < graph.minGraphX) {
+        graph.minGraphX = nodeToPlace.x;
+      }
+      if ((nodeToPlace.y - 50) < graph.minGraphY) {
+        graph.minGraphY = nodeToPlace.y - 50;
+      }
+      if ((nodeToPlace.x + nodeToPlace.getTotalNodeWidth()) > graph.maxGraphNodeX) {
+        graph.maxGraphNodeX = nodeToPlace.x + nodeToPlace.getTotalNodeWidth();
+      }
+      if ((nodeToPlace.y + graph.getNodeHeight() + 50) > graph.maxGraphY) {
+        graph.maxGraphY = nodeToPlace.y + graph.getNodeHeight() + 50;
+      }
+    }
+
+    if (traceLayout) {
+      console.log("Before clearing nodes");
+      occupation.print();
+    }
+
+    occupation.clearOccupiedNodes();
+
+    if (traceLayout) {
+      console.log("After clearing nodes");
+      occupation.print();
+    }
+
+    for (var i = 0; i < rankSet.length; ++i) {
+      var node = rankSet[i];
+      occupation.occupyNodeInputs(node);
+    }
+
+    if (traceLayout) {
+      console.log("After occupying inputs");
+      occupation.print();
+    }
+  });
+
+  var backEdgeNumber = 0;
+  graph.visibleEdges.each(function (e) {
+    if (e.isBackEdge()) {
+      e.backEdgeNumber = ++backEdgeNumber;
+    } else {
+      e.backEdgeNumber = 0;
+    }
+  });
+
+  graph.maxGraphX = graph.maxGraphNodeX +
+    backEdgeNumber * MINIMUM_EDGE_SEPARATION;
+}
diff --git a/tools/turbolizer/graph-view.js b/tools/turbolizer/graph-view.js
new file mode 100644
index 0000000..41d35d8
--- /dev/null
+++ b/tools/turbolizer/graph-view.js
@@ -0,0 +1,987 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+"use strict";
+
+class GraphView extends View {
+  constructor (d3, id, nodes, edges, broker) {
+    super(id, broker);
+    var graph = this;
+
+    var svg = this.divElement.append("svg").attr('version','1.1').attr("width", "100%");
+    graph.svg = svg;
+
+    graph.nodes = nodes || [];
+    graph.edges = edges || [];
+
+    graph.minGraphX = 0;
+    graph.maxGraphX = 1;
+    graph.minGraphY = 0;
+    graph.maxGraphY = 1;
+
+    graph.state = {
+      selection: null,
+      mouseDownNode: null,
+      justDragged: false,
+      justScaleTransGraph: false,
+      lastKeyDown: -1,
+      showTypes: false
+    };
+
+    var selectionHandler = {
+      clear: function() {
+        broker.clear(selectionHandler);
+      },
+      select: function(items, selected) {
+        var ranges = [];
+        for (var d of items) {
+          if (selected) {
+            d.classList.add("selected");
+          } else {
+            d.classList.remove("selected");
+          }
+          var data = d.__data__;
+          ranges.push([data.pos, data.pos + 1, data.id]);
+        }
+        broker.select(selectionHandler, ranges, selected);
+      },
+      selectionDifference: function(span1, inclusive1, span2, inclusive2) {
+        // Should not be called
+      },
+      brokeredSelect: function(ranges, selected) {
+        var test = [].entries().next();
+        var selection = graph.nodes
+          .filter(function(n) {
+            var pos = n.pos;
+            for (var range of ranges) {
+              var start = range[0];
+              var end = range[1];
+              var id = range[2];
+              if (end != undefined) {
+                if (pos >= start && pos < end) {
+                  return true;
+                }
+              } else if (start != undefined) {
+                if (pos === start) {
+                  return true;
+                }
+              } else {
+                if (n.id === id) {
+                  return true;
+                }
+              }
+            }
+            return false;
+          });
+        var newlySelected = new Set();
+        selection.forEach(function(n) {
+          newlySelected.add(n);
+          if (!n.visible) {
+            n.visible = true;
+          }
+        });
+        graph.updateGraphVisibility();
+        graph.visibleNodes.each(function(n) {
+          if (newlySelected.has(n)) {
+            graph.state.selection.select(this, selected);
+          }
+        });
+        graph.updateGraphVisibility();
+        graph.viewSelection();
+      },
+      brokeredClear: function() {
+        graph.state.selection.clear();
+      }
+    };
+    broker.addSelectionHandler(selectionHandler);
+
+    graph.state.selection = new Selection(selectionHandler);
+
+    var defs = svg.append('svg:defs');
+    defs.append('svg:marker')
+      .attr('id', 'end-arrow')
+      .attr('viewBox', '0 -4 8 8')
+      .attr('refX', 2)
+      .attr('markerWidth', 2.5)
+      .attr('markerHeight', 2.5)
+      .attr('orient', 'auto')
+      .append('svg:path')
+      .attr('d', 'M0,-4L8,0L0,4');
+
+    this.graphElement = svg.append("g");
+    graph.visibleEdges = this.graphElement.append("g").selectAll("g");
+    graph.visibleNodes = this.graphElement.append("g").selectAll("g");
+
+    graph.drag = d3.behavior.drag()
+      .origin(function(d){
+        return {x: d.x, y: d.y};
+      })
+      .on("drag", function(args){
+        graph.state.justDragged = true;
+        graph.dragmove.call(graph, args);
+      })
+
+    d3.select("#upload").on("click", function(){
+      document.getElementById("hidden-file-upload").click();
+    });
+
+    d3.select("#layout").on("click", function(){
+      graph.updateGraphVisibility();
+      graph.layoutGraph();
+      graph.updateGraphVisibility();
+      graph.viewWholeGraph();
+    });
+
+    d3.select("#show-all").on("click", function(){
+      graph.nodes.filter(function(n) { n.visible = true; })
+      graph.edges.filter(function(e) { e.visible = true; })
+      graph.updateGraphVisibility();
+      graph.viewWholeGraph();
+    });
+
+    d3.select("#hide-unselected").on("click", function() {
+      var unselected = graph.visibleNodes.filter(function(n) {
+        return !this.classList.contains("selected");
+      });
+      unselected.each(function(n) {
+        n.visible = false;
+      });
+      graph.updateGraphVisibility();
+    });
+
+    d3.select("#hide-selected").on("click", function() {
+      var selected = graph.visibleNodes.filter(function(n) {
+        return this.classList.contains("selected");
+      });
+      selected.each(function(n) {
+        n.visible = false;
+      });
+      graph.state.selection.clear();
+      graph.updateGraphVisibility();
+    });
+
+    d3.select("#zoom-selection").on("click", function() {
+      graph.viewSelection();
+    });
+
+    d3.select("#toggle-types").on("click", function() {
+      graph.toggleTypes();
+    });
+
+    d3.select("#search-input").on("keydown", function() {
+      if (d3.event.keyCode == 13) {
+        graph.state.selection.clear();
+        var reg = new RegExp(this.value);
+        var filterFunction = function(n) {
+          return (reg.exec(n.getDisplayLabel()) != null ||
+                  (graph.state.showTypes && reg.exec(n.getDisplayType())) ||
+                  reg.exec(n.opcode) != null);
+        };
+        if (d3.event.ctrlKey) {
+          graph.nodes.forEach(function(n, i) {
+            if (filterFunction(n)) {
+              n.visible = true;
+            }
+          });
+          graph.updateGraphVisibility();
+        }
+        var selected = graph.visibleNodes.each(function(n) {
+          if (filterFunction(n)) {
+            graph.state.selection.select(this, true);
+          }
+        });
+        graph.connectVisibleSelectedNodes();
+        graph.updateGraphVisibility();
+        this.blur();
+        graph.viewSelection();
+      }
+      d3.event.stopPropagation();
+    });
+
+    // listen for key events
+    d3.select(window).on("keydown", function(e){
+      graph.svgKeyDown.call(graph);
+    })
+      .on("keyup", function(){
+        graph.svgKeyUp.call(graph);
+      });
+    svg.on("mousedown", function(d){graph.svgMouseDown.call(graph, d);});
+    svg.on("mouseup", function(d){graph.svgMouseUp.call(graph, d);});
+
+    graph.dragSvg = d3.behavior.zoom()
+      .on("zoom", function(){
+        if (d3.event.sourceEvent.shiftKey){
+          return false;
+        } else{
+          graph.zoomed.call(graph);
+        }
+        return true;
+      })
+      .on("zoomstart", function(){
+        if (!d3.event.sourceEvent.shiftKey) d3.select('body').style("cursor", "move");
+      })
+      .on("zoomend", function(){
+        d3.select('body').style("cursor", "auto");
+      });
+
+    svg.call(graph.dragSvg).on("dblclick.zoom", null);
+  }
+
+  static get selectedClass() {
+    return "selected";
+  }
+  static get rectClass() {
+    return "nodeStyle";
+  }
+  static get activeEditId() {
+    return "active-editing";
+  }
+  static get nodeRadius() {
+    return 50;
+  }
+
+  getNodeHeight(graph) {
+    if (this.state.showTypes) {
+      return DEFAULT_NODE_HEIGHT + TYPE_HEIGHT;
+    } else {
+      return DEFAULT_NODE_HEIGHT;
+    }
+  }
+
+  getEdgeFrontier(nodes, inEdges, edgeFilter) {
+    let frontier = new Set();
+    nodes.forEach(function(element) {
+      var edges = inEdges ? element.__data__.inputs : element.__data__.outputs;
+      var edgeNumber = 0;
+      edges.forEach(function(edge) {
+        if (edgeFilter == undefined || edgeFilter(edge, edgeNumber)) {
+          frontier.add(edge);
+        }
+        ++edgeNumber;
+      });
+    });
+    return frontier;
+  }
+
+  getNodeFrontier(nodes, inEdges, edgeFilter) {
+    let graph = this;
+    var frontier = new Set();
+    var newState = true;
+    var edgeFrontier = graph.getEdgeFrontier(nodes, inEdges, edgeFilter);
+    // Control key toggles edges rather than just turning them on
+    if (d3.event.ctrlKey) {
+      edgeFrontier.forEach(function(edge) {
+        if (edge.visible) {
+          newState = false;
+        }
+      });
+    }
+    edgeFrontier.forEach(function(edge) {
+      edge.visible = newState;
+      if (newState) {
+        var node = inEdges ? edge.source : edge.target;
+        node.visible = true;
+        frontier.add(node);
+      }
+    });
+    graph.updateGraphVisibility();
+    if (newState) {
+      return graph.visibleNodes.filter(function(n) {
+        return frontier.has(n);
+      });
+    } else {
+      return undefined;
+    }
+  }
+
+  dragmove(d) {
+    var graph = this;
+    d.x += d3.event.dx;
+    d.y += d3.event.dy;
+    graph.updateGraphVisibility();
+  }
+
+  initializeContent(data, rememberedSelection) {
+    this.createGraph(data, rememberedSelection);
+    if (rememberedSelection != null) {
+      this.attachSelection(rememberedSelection);
+      this.connectVisibleSelectedNodes();
+    }
+    this.updateGraphVisibility();
+  }
+
+  deleteContent() {
+    if (this.visibleNodes) {
+      this.nodes = [];
+      this.edges = [];
+      this.nodeMap = [];
+      this.updateGraphVisibility();
+    }
+  };
+
+  createGraph(data, initiallyVisibileIds) {
+    var g = this;
+    g.nodes = data.nodes;
+    g.nodeMap = [];
+    var textMeasure = document.getElementById('text-measure');
+    g.nodes.forEach(function(n, i){
+      n.__proto__ = Node;
+      n.visible = false;
+      n.x = 0;
+      n.y = 0;
+      n.rank = MAX_RANK_SENTINEL;
+      n.inputs = [];
+      n.outputs = [];
+      n.rpo = -1;
+      n.outputApproach = MINIMUM_NODE_OUTPUT_APPROACH;
+      n.cfg = n.control;
+      g.nodeMap[n.id] = n;
+      n.displayLabel = n.getDisplayLabel();
+      textMeasure.textContent = n.getDisplayLabel();
+      var width = textMeasure.getComputedTextLength();
+      textMeasure.textContent = n.getDisplayType();
+      width = Math.max(width, textMeasure.getComputedTextLength());
+      n.width = Math.alignUp(width + NODE_INPUT_WIDTH * 2,
+                             NODE_INPUT_WIDTH);
+    });
+    g.edges = [];
+    data.edges.forEach(function(e, i){
+      var t = g.nodeMap[e.target];
+      var s = g.nodeMap[e.source];
+      var newEdge = new Edge(t, e.index, s, e.type);
+      t.inputs.push(newEdge);
+      s.outputs.push(newEdge);
+      g.edges.push(newEdge);
+      if (e.type == 'control') {
+        s.cfg = true;
+      }
+    });
+    g.nodes.forEach(function(n, i) {
+      n.visible = isNodeInitiallyVisible(n);
+      if (initiallyVisibileIds != undefined) {
+        if (initiallyVisibileIds.has(n.id)) {
+          n.visible = true;
+        }
+      }
+    });
+    g.fitGraphViewToWindow();
+    g.updateGraphVisibility();
+    g.layoutGraph();
+    g.updateGraphVisibility();
+    g.viewWholeGraph();
+  }
+
+  connectVisibleSelectedNodes() {
+    var graph = this;
+    graph.state.selection.selection.forEach(function(element) {
+      var edgeNumber = 0;
+      element.__data__.inputs.forEach(function(edge) {
+        if (edge.source.visible && edge.target.visible) {
+          edge.visible = true;
+        }
+      });
+      element.__data__.outputs.forEach(function(edge) {
+        if (edge.source.visible && edge.target.visible) {
+          edge.visible = true;
+        }
+      });
+    });
+  }
+
+  updateInputAndOutputBubbles() {
+    var g = this;
+    var s = g.visibleBubbles;
+    s.classed("filledBubbleStyle", function(c) {
+      var components = this.id.split(',');
+      if (components[0] == "ib") {
+        var edge = g.nodeMap[components[3]].inputs[components[2]];
+        return edge.isVisible();
+      } else {
+        return g.nodeMap[components[1]].areAnyOutputsVisible() == 2;
+      }
+    }).classed("halfFilledBubbleStyle", function(c) {
+      var components = this.id.split(',');
+      if (components[0] == "ib") {
+        var edge = g.nodeMap[components[3]].inputs[components[2]];
+        return false;
+      } else {
+        return g.nodeMap[components[1]].areAnyOutputsVisible() == 1;
+      }
+    }).classed("bubbleStyle", function(c) {
+      var components = this.id.split(',');
+      if (components[0] == "ib") {
+        var edge = g.nodeMap[components[3]].inputs[components[2]];
+        return !edge.isVisible();
+      } else {
+        return g.nodeMap[components[1]].areAnyOutputsVisible() == 0;
+      }
+    });
+    s.each(function(c) {
+      var components = this.id.split(',');
+      if (components[0] == "ob") {
+        var from = g.nodeMap[components[1]];
+        var x = from.getOutputX();
+        var y = g.getNodeHeight() + DEFAULT_NODE_BUBBLE_RADIUS / 2 + 4;
+        var transform = "translate(" + x + "," + y + ")";
+        this.setAttribute('transform', transform);
+      }
+    });
+  }
+
+  attachSelection(s) {
+    var graph = this;
+    if (s.size != 0) {
+      this.visibleNodes.each(function(n) {
+        if (s.has(this.__data__.id)) {
+          graph.state.selection.select(this, true);
+        }
+      });
+    }
+  }
+
+  detachSelection() {
+    var selection = this.state.selection.detachSelection();
+    var s = new Set();
+    for (var i of selection) {
+      s.add(i.__data__.id);
+    };
+    return s;
+  }
+
+  pathMouseDown(path, d) {
+    d3.event.stopPropagation();
+    this.state.selection.clear();
+    this.state.selection.add(path);
+  };
+
+  nodeMouseDown(node, d) {
+    d3.event.stopPropagation();
+    this.state.mouseDownNode = d;
+  }
+
+  nodeMouseUp(d3node, d) {
+    var graph = this,
+    state = graph.state,
+    consts = graph.consts;
+
+    var mouseDownNode = state.mouseDownNode;
+
+    if (!mouseDownNode) return;
+
+    if (mouseDownNode !== d){
+      // we're in a different node: create new edge for mousedown edge and add to graph
+      var newEdge = {source: mouseDownNode, target: d};
+      var filtRes = graph.visibleEdges.filter(function(d){
+        if (d.source === newEdge.target && d.target === newEdge.source){
+          graph.edges.splice(graph.edges.indexOf(d), 1);
+        }
+        return d.source === newEdge.source && d.target === newEdge.target;
+      });
+      if (!filtRes[0].length){
+        graph.edges.push(newEdge);
+        graph.updateGraphVisibility();
+      }
+    } else{
+      // we're in the same node
+      if (state.justDragged) {
+        // dragged, not clicked
+        state.justDragged = false;
+      } else{
+        // clicked, not dragged
+        var extend = d3.event.shiftKey;
+        var selection = graph.state.selection;
+        if (!extend) {
+          selection.clear();
+        }
+        selection.select(d3node[0][0], true);
+      }
+    }
+  }
+
+  selectSourcePositions(start, end, selected) {
+    var graph = this;
+    var map = [];
+    var sel = graph.nodes.filter(function(n) {
+      var pos = (n.pos === undefined)
+        ? -1
+        : n.getFunctionRelativeSourcePosition(graph);
+      if (pos >= start && pos < end) {
+        map[n.id] = true;
+        n.visible = true;
+      }
+    });
+    graph.updateGraphVisibility();
+    graph.visibleNodes.filter(function(n) { return map[n.id]; })
+      .each(function(n) {
+        var selection = graph.state.selection;
+        selection.select(d3.select(this), selected);
+      });
+  }
+
+  selectAllNodes(inEdges, filter) {
+    var graph = this;
+    if (!d3.event.shiftKey) {
+      graph.state.selection.clear();
+    }
+    graph.state.selection.select(graph.visibleNodes[0], true);
+    graph.updateGraphVisibility();
+  }
+
+  svgMouseDown() {
+    this.state.graphMouseDown = true;
+  }
+
+  svgMouseUp() {
+    var graph = this,
+    state = graph.state;
+    if (state.justScaleTransGraph) {
+      // Dragged
+      state.justScaleTransGraph = false;
+    } else {
+      // Clicked
+      if (state.mouseDownNode == null) {
+        graph.state.selection.clear();
+      }
+    }
+    state.mouseDownNode = null;
+    state.graphMouseDown = false;
+  }
+
+  svgKeyDown() {
+    var state = this.state;
+    var graph = this;
+
+    // Don't handle key press repetition
+    if(state.lastKeyDown !== -1) return;
+
+    var showSelectionFrontierNodes = function(inEdges, filter, select) {
+      var frontier = graph.getNodeFrontier(state.selection.selection, inEdges, filter);
+      if (frontier != undefined) {
+        if (select) {
+          if (!d3.event.shiftKey) {
+            state.selection.clear();
+          }
+          state.selection.select(frontier[0], true);
+        }
+        graph.updateGraphVisibility();
+      }
+      allowRepetition = false;
+    }
+
+    var allowRepetition = true;
+    var eventHandled = true; // unless the below switch defaults
+    switch(d3.event.keyCode) {
+    case 49:
+    case 50:
+    case 51:
+    case 52:
+    case 53:
+    case 54:
+    case 55:
+    case 56:
+    case 57:
+      // '1'-'9'
+      showSelectionFrontierNodes(true,
+          (edge, index) => { return index == (d3.event.keyCode - 49); },
+          false);
+      break;
+    case 67:
+      // 'c'
+      showSelectionFrontierNodes(true,
+          (edge, index) => { return edge.type == 'control'; },
+          false);
+      break;
+    case 69:
+      // 'e'
+      showSelectionFrontierNodes(true,
+          (edge, index) => { return edge.type == 'effect'; },
+          false);
+      break;
+    case 79:
+      // 'o'
+      showSelectionFrontierNodes(false, undefined, false);
+      break;
+    case 73:
+      // 'i'
+      showSelectionFrontierNodes(true, undefined, false);
+      break;
+    case 65:
+      // 'a'
+      graph.selectAllNodes();
+      allowRepetition = false;
+      break;
+    case 38:
+    case 40: {
+      showSelectionFrontierNodes(d3.event.keyCode == 38, undefined, true);
+      break;
+    }
+    default:
+      eventHandled = false;
+      break;
+    }
+    if (eventHandled) {
+      d3.event.preventDefault();
+    }
+    if (!allowRepetition) {
+      state.lastKeyDown = d3.event.keyCode;
+    }
+  }
+
+  svgKeyUp() {
+    this.state.lastKeyDown = -1
+  };
+
+  layoutEdges() {
+    var graph = this;
+    graph.maxGraphX = graph.maxGraphNodeX;
+    this.visibleEdges.attr("d", function(edge){
+      return edge.generatePath(graph);
+    });
+  }
+
+  layoutGraph() {
+    layoutNodeGraph(this);
+  }
+
+  // call to propagate changes to graph
+  updateGraphVisibility() {
+
+    var graph = this,
+    state = graph.state;
+
+    var filteredEdges = graph.edges.filter(function(e) { return e.isVisible(); });
+    var visibleEdges = graph.visibleEdges.data(filteredEdges, function(edge) {
+      return edge.stringID();
+    });
+
+    // add new paths
+    visibleEdges.enter()
+      .append('path')
+      .style('marker-end','url(#end-arrow)')
+      .classed('hidden', function(e) {
+        return !e.isVisible();
+      })
+      .attr("id", function(edge){ return "e," + edge.stringID(); })
+      .on("mousedown", function(d){
+        graph.pathMouseDown.call(graph, d3.select(this), d);
+      })
+
+    // Set the correct styles on all of the paths
+    visibleEdges.classed('value', function(e) {
+      return e.type == 'value' || e.type == 'context';
+    }).classed('control', function(e) {
+      return e.type == 'control';
+    }).classed('effect', function(e) {
+      return e.type == 'effect';
+    }).classed('frame-state', function(e) {
+      return e.type == 'frame-state';
+    }).attr('stroke-dasharray', function(e) {
+      if (e.type == 'frame-state') return "10,10";
+      return (e.type == 'effect') ? "5,5" : "";
+    });
+
+    // remove old links
+    visibleEdges.exit().remove();
+
+    graph.visibleEdges = visibleEdges;
+
+    // update existing nodes
+    var filteredNodes = graph.nodes.filter(function(n) { return n.visible; });
+    graph.visibleNodes = graph.visibleNodes.data(filteredNodes, function(d) {
+      return d.id;
+    });
+    graph.visibleNodes.attr("transform", function(n){
+      return "translate(" + n.x + "," + n.y + ")";
+    }).select('rect').
+      attr(HEIGHT, function(d) { return graph.getNodeHeight(); });
+
+    // add new nodes
+    var newGs = graph.visibleNodes.enter()
+      .append("g");
+
+    newGs.classed("control", function(n) { return n.isControl(); })
+      .classed("javascript", function(n) { return n.isJavaScript(); })
+      .classed("input", function(n) { return n.isInput(); })
+      .classed("simplified", function(n) { return n.isSimplified(); })
+      .classed("machine", function(n) { return n.isMachine(); })
+      .attr("transform", function(d){ return "translate(" + d.x + "," + d.y + ")";})
+      .on("mousedown", function(d){
+        graph.nodeMouseDown.call(graph, d3.select(this), d);
+      })
+      .on("mouseup", function(d){
+        graph.nodeMouseUp.call(graph, d3.select(this), d);
+      })
+      .call(graph.drag);
+
+    newGs.append("rect")
+      .attr("rx", 10)
+      .attr("ry", 10)
+      .attr(WIDTH, function(d) { return d.getTotalNodeWidth(); })
+      .attr(HEIGHT, function(d) { return graph.getNodeHeight(); })
+
+    function appendInputAndOutputBubbles(g, d) {
+      for (var i = 0; i < d.inputs.length; ++i) {
+        var x = d.getInputX(i);
+        var y = -DEFAULT_NODE_BUBBLE_RADIUS / 2 - 4;
+        var s = g.append('circle')
+          .classed("filledBubbleStyle", function(c) {
+            return d.inputs[i].isVisible();
+          } )
+          .classed("bubbleStyle", function(c) {
+            return !d.inputs[i].isVisible();
+          } )
+          .attr("id", "ib," + d.inputs[i].stringID())
+          .attr("r", DEFAULT_NODE_BUBBLE_RADIUS)
+          .attr("transform", function(d) {
+            return "translate(" + x + "," + y + ")";
+          })
+          .on("mousedown", function(d){
+            var components = this.id.split(',');
+            var node = graph.nodeMap[components[3]];
+            var edge = node.inputs[components[2]];
+            var visible = !edge.isVisible();
+            node.setInputVisibility(components[2], visible);
+            d3.event.stopPropagation();
+            graph.updateGraphVisibility();
+          });
+      }
+      if (d.outputs.length != 0) {
+        var x = d.getOutputX();
+        var y = graph.getNodeHeight() + DEFAULT_NODE_BUBBLE_RADIUS / 2 + 4;
+        var s = g.append('circle')
+          .classed("filledBubbleStyle", function(c) {
+            return d.areAnyOutputsVisible() == 2;
+          } )
+          .classed("halFilledBubbleStyle", function(c) {
+            return d.areAnyOutputsVisible() == 1;
+          } )
+          .classed("bubbleStyle", function(c) {
+            return d.areAnyOutputsVisible() == 0;
+          } )
+          .attr("id", "ob," + d.id)
+          .attr("r", DEFAULT_NODE_BUBBLE_RADIUS)
+          .attr("transform", function(d) {
+            return "translate(" + x + "," + y + ")";
+          })
+          .on("mousedown", function(d) {
+            d.setOutputVisibility(d.areAnyOutputsVisible() == 0);
+            d3.event.stopPropagation();
+            graph.updateGraphVisibility();
+          });
+      }
+    }
+
+    newGs.each(function(d){
+      appendInputAndOutputBubbles(d3.select(this), d);
+    });
+
+    newGs.each(function(d){
+      d3.select(this).append("text")
+        .classed("label", true)
+        .attr("text-anchor","right")
+        .attr("dx", "5")
+        .attr("dy", DEFAULT_NODE_HEIGHT / 2 + 5)
+        .append('tspan')
+        .text(function(l) {
+          return d.getDisplayLabel();
+        })
+        .append("title")
+        .text(function(l) {
+          return d.getLabel();
+        })
+      if (d.type != undefined) {
+        d3.select(this).append("text")
+          .classed("label", true)
+          .classed("type", true)
+          .attr("text-anchor","right")
+          .attr("dx", "5")
+          .attr("dy", DEFAULT_NODE_HEIGHT / 2 + TYPE_HEIGHT + 5)
+          .append('tspan')
+          .text(function(l) {
+            return d.getDisplayType();
+          })
+          .append("title")
+          .text(function(l) {
+            return d.getType();
+          })
+      }
+    });
+
+    graph.visibleNodes.select('.type').each(function (d) {
+      this.setAttribute('visibility', graph.state.showTypes ? 'visible' : 'hidden');
+    });
+
+    // remove old nodes
+    graph.visibleNodes.exit().remove();
+
+    graph.visibleBubbles = d3.selectAll('circle');
+
+    graph.updateInputAndOutputBubbles();
+
+    graph.layoutEdges();
+
+    graph.svg.style.height = '100%';
+  }
+
+  getVisibleTranslation(translate, scale) {
+    var graph = this;
+    var height = (graph.maxGraphY - graph.minGraphY + 2 * GRAPH_MARGIN) * scale;
+    var width = (graph.maxGraphX - graph.minGraphX + 2 * GRAPH_MARGIN) * scale;
+
+    var dimensions = this.getSvgViewDimensions();
+
+    var baseY = translate[1];
+    var minY = (graph.minGraphY - GRAPH_MARGIN) * scale;
+    var maxY = (graph.maxGraphY + GRAPH_MARGIN) * scale;
+
+    var adjustY = 0;
+    var adjustYCandidate = 0;
+    if ((maxY + baseY) < dimensions[1]) {
+      adjustYCandidate = dimensions[1] - (maxY + baseY);
+      if ((minY + baseY + adjustYCandidate) > 0) {
+        adjustY = (dimensions[1] / 2) - (maxY - (height / 2)) - baseY;
+      } else {
+        adjustY = adjustYCandidate;
+      }
+    } else if (-baseY < minY) {
+      adjustYCandidate = -(baseY + minY);
+      if ((maxY + baseY + adjustYCandidate) < dimensions[1]) {
+        adjustY = (dimensions[1] / 2) - (maxY - (height / 2)) - baseY;
+      } else {
+        adjustY = adjustYCandidate;
+      }
+    }
+    translate[1] += adjustY;
+
+    var baseX = translate[0];
+    var minX = (graph.minGraphX - GRAPH_MARGIN) * scale;
+    var maxX = (graph.maxGraphX + GRAPH_MARGIN) * scale;
+
+    var adjustX = 0;
+    var adjustXCandidate = 0;
+    if ((maxX + baseX) < dimensions[0]) {
+      adjustXCandidate = dimensions[0] - (maxX + baseX);
+      if ((minX + baseX + adjustXCandidate) > 0) {
+        adjustX = (dimensions[0] / 2) - (maxX - (width / 2)) - baseX;
+      } else {
+        adjustX = adjustXCandidate;
+      }
+    } else if (-baseX < minX) {
+      adjustXCandidate = -(baseX + minX);
+      if ((maxX + baseX + adjustXCandidate) < dimensions[0]) {
+        adjustX = (dimensions[0] / 2) - (maxX - (width / 2)) - baseX;
+      } else {
+        adjustX = adjustXCandidate;
+      }
+    }
+    translate[0] += adjustX;
+    return translate;
+  }
+
+  translateClipped(translate, scale, transition) {
+    var graph = this;
+    var graphNode = this.graphElement[0][0];
+    var translate = this.getVisibleTranslation(translate, scale);
+    if (transition) {
+      graphNode.classList.add('visible-transition');
+      clearTimeout(graph.transitionTimout);
+      graph.transitionTimout = setTimeout(function(){
+        graphNode.classList.remove('visible-transition');
+      }, 1000);
+    }
+    var translateString = "translate(" + translate[0] + "px," + translate[1] + "px) scale(" + scale + ")";
+    graphNode.style.transform = translateString;
+    graph.dragSvg.translate(translate);
+    graph.dragSvg.scale(scale);
+  }
+
+  zoomed(){
+    this.state.justScaleTransGraph = true;
+    var scale =  this.dragSvg.scale();
+    this.translateClipped(d3.event.translate, scale);
+  }
+
+
+  getSvgViewDimensions() {
+    var canvasWidth = this.parentNode.clientWidth;
+    var documentElement = document.documentElement;
+    var canvasHeight = documentElement.clientHeight;
+    return [canvasWidth, canvasHeight];
+  }
+
+
+  minScale() {
+    var graph = this;
+    var dimensions = this.getSvgViewDimensions();
+    var width = graph.maxGraphX - graph.minGraphX;
+    var height = graph.maxGraphY - graph.minGraphY;
+    var minScale = dimensions[0] / (width + GRAPH_MARGIN * 2);
+    var minScaleYCandidate = dimensions[1] / (height + GRAPH_MARGIN * 2);
+    if (minScaleYCandidate < minScale) {
+      minScale = minScaleYCandidate;
+    }
+    this.dragSvg.scaleExtent([minScale, 1.5]);
+    return minScale;
+  }
+
+  fitGraphViewToWindow() {
+    this.svg.attr("height", document.documentElement.clientHeight + "px");
+    this.translateClipped(this.dragSvg.translate(), this.dragSvg.scale());
+  }
+
+  toggleTypes() {
+    var graph = this;
+    graph.state.showTypes = !graph.state.showTypes;
+    var element = document.getElementById('toggle-types');
+    if (graph.state.showTypes) {
+      element.classList.add('button-input-toggled');
+    } else {
+      element.classList.remove('button-input-toggled');
+    }
+    graph.updateGraphVisibility();
+  }
+
+  viewSelection() {
+    var graph = this;
+    var minX, maxX, minY, maxY;
+    var hasSelection = false;
+    graph.visibleNodes.each(function(n) {
+      if (this.classList.contains("selected")) {
+        hasSelection = true;
+        minX = minX ? Math.min(minX, n.x) : n.x;
+        maxX = maxX ? Math.max(maxX, n.x + n.getTotalNodeWidth()) :
+          n.x + n.getTotalNodeWidth();
+        minY = minY ? Math.min(minY, n.y) : n.y;
+        maxY = maxY ? Math.max(maxY, n.y + DEFAULT_NODE_HEIGHT) :
+          n.y + DEFAULT_NODE_HEIGHT;
+      }
+    });
+    if (hasSelection) {
+      graph.viewGraphRegion(minX - NODE_INPUT_WIDTH, minY - 60,
+                            maxX + NODE_INPUT_WIDTH, maxY + 60,
+                            true);
+    }
+  }
+
+  viewGraphRegion(minX, minY, maxX, maxY, transition) {
+    var graph = this;
+    var dimensions = this.getSvgViewDimensions();
+    var width = maxX - minX;
+    var height = maxY - minY;
+    var scale = Math.min(dimensions[0] / width, dimensions[1] / height);
+    scale = Math.min(1.5, scale);
+    scale = Math.max(graph.minScale(), scale);
+    var translation = [-minX*scale, -minY*scale];
+    translation = graph.getVisibleTranslation(translation, scale);
+    graph.translateClipped(translation, scale, transition);
+  }
+
+  viewWholeGraph() {
+    var graph = this;
+    var minScale = graph.minScale();
+    var translation = [0, 0];
+    translation = graph.getVisibleTranslation(translation, minScale);
+    graph.translateClipped(translation, minScale);
+  }
+}
diff --git a/tools/turbolizer/hide-selected.png b/tools/turbolizer/hide-selected.png
new file mode 100644
index 0000000..207cdbb
--- /dev/null
+++ b/tools/turbolizer/hide-selected.png
Binary files differ
diff --git a/tools/turbolizer/hide-unselected.png b/tools/turbolizer/hide-unselected.png
new file mode 100644
index 0000000..15617b0
--- /dev/null
+++ b/tools/turbolizer/hide-unselected.png
Binary files differ
diff --git a/tools/turbolizer/index.html b/tools/turbolizer/index.html
new file mode 100644
index 0000000..6991d92
--- /dev/null
+++ b/tools/turbolizer/index.html
@@ -0,0 +1,89 @@
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <link rel="stylesheet" href="turbo-visualizer.css" />
+  </head>
+  <body width="100%">
+    <div id="left">
+      <div id='source-text'>
+        <pre id='source-text-pre'\>
+      </div>
+    </div>
+    <div id="middle">
+      <span id="graph-toolbox">
+        <input id="layout" type="image" title="layout graph" src="layout-icon.png"
+               alt="layout graph" class="button-input">
+        <input id="show-all" type="image" title="show all nodes" src="expand-all.jpg"
+               alt="show all nodes" class="button-input">
+        <input id="hide-unselected" type="image" title="hide unselected nodes"
+               src="hide-unselected.png" alt="hide unselected nodes" class="button-input">
+        <input id="hide-selected" type="image" title="hide selected nodes"
+               src="hide-selected.png" alt="hide selected nodes" class="button-input">
+        <input id="zoom-selection" type="image" title="zoom to selection"
+               src="search.png" alt="zoom to selection" class="button-input">
+        <input id="toggle-types" type="image" title="show/hide types"
+               src="types.png" alt="show/hide types" class="button-input">
+        <input id="search-input" type="text" title="search nodes for regex"
+               alt="search node for regex" class="search-input"
+               placeholder="find with regexp&hellip;">
+        <select id="display-selector"></select>
+      </span>
+      <div id="load-file">
+        <input type="file" id="hidden-file-upload">
+        <input id="upload" type="image" title="load graph" class="button-input"
+               src="upload-icon.png" alt="upload graph">
+      </div>
+      <div id="empty" width="100%" height="100%"></div>
+      <div id="graph" width="100%" height="100%"></div>
+      <div id="schedule" width="100%">
+        <pre id="schedule-text-pre" class='prettyprint prettyprinted'>
+          <ul id="schedule-list" class='nolinenums noindent'>
+          </ul>
+        </pre>        
+      </div>
+      <div id='text-placeholder' width="0px" height="0px" style="position: absolute; top:100000px;" ><svg><text text-anchor="right">
+          <tspan white-space="inherit" id="text-measure"/>
+      </text></svg></div>
+    </div>
+    <div id="right">
+      <div id='disassembly'>
+        <pre id='disassembly-text-pre' class='prettyprint prettyprinted'>
+          <ul id='disassembly-list' class='nolinenums noindent'>            
+          </ul>
+        </pre>
+      </div>
+    </div>
+    <div id="source-collapse" class="collapse-pane">
+      <input id="source-expand" type="image" title="show source"
+             src="right-arrow.png" class="button-input-invisible">
+      <input id="source-shrink" type="image" title="hide source"
+             src="left-arrow.png" class="button-input">
+    </div>
+    <div id="disassembly-collapse" class="collapse-pane">
+      <input id="disassembly-expand" type="image" title="show disassembly"
+             src="left-arrow.png" class="button-input">
+      <input id="disassembly-shrink" type="image" title="hide disassembly" 
+             src="right-arrow.png" class="button-input-invisible">
+    </div>
+    <script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
+    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+    <script src="https://cdn.jsdelivr.net/filesaver.js/0.1/FileSaver.min.js"></script>
+    <script src="monkey.js"></script>
+    <script src="util.js"></script>
+    <script src="lang-disassembly.js"></script>
+    <script src="node.js"></script>
+    <script src="edge.js"></script>
+    <script src="selection.js"></script>
+    <script src="selection-broker.js"></script>
+    <script src="constants.js"></script>
+    <script src="view.js"></script>
+    <script src="text-view.js"></script>
+    <script src="empty-view.js"></script>
+    <script src="code-view.js"></script>
+    <script src="graph-layout.js"></script>
+    <script src="graph-view.js"></script>
+    <script src="schedule-view.js"></script>
+    <script src="disassembly-view.js"></script>
+    <script src="turbo-visualizer.js"></script>
+  </body>
+</html>
diff --git a/tools/turbolizer/lang-disassembly.js b/tools/turbolizer/lang-disassembly.js
new file mode 100644
index 0000000..590f9fd
--- /dev/null
+++ b/tools/turbolizer/lang-disassembly.js
@@ -0,0 +1,14 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+PR.registerLangHandler(
+    PR.createSimpleLexer(
+      [
+        [PR.PR_STRING,        /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$))/, null, '\''],
+        [PR.PR_PLAIN,         /^\s+/, null, ' \r\n\t\xA0']
+      ],
+      [ // fallthroughStylePatterns
+        [PR.PR_COMMENT,       /;; debug: position \d+/, null],
+      ]),
+    ['disassembly']);
diff --git a/tools/turbolizer/layout-icon.png b/tools/turbolizer/layout-icon.png
new file mode 100644
index 0000000..95a517a
--- /dev/null
+++ b/tools/turbolizer/layout-icon.png
Binary files differ
diff --git a/tools/turbolizer/left-arrow.png b/tools/turbolizer/left-arrow.png
new file mode 100644
index 0000000..fc0603e
--- /dev/null
+++ b/tools/turbolizer/left-arrow.png
Binary files differ
diff --git a/tools/turbolizer/monkey.js b/tools/turbolizer/monkey.js
new file mode 100644
index 0000000..129f8b3
--- /dev/null
+++ b/tools/turbolizer/monkey.js
@@ -0,0 +1,26 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Array.prototype.getStaggeredFromMiddle = function(i) {
+  if (i >= this.length) {
+    throw("getStaggeredFromMiddle: OOB");
+  }
+  var middle = Math.floor(this.length / 2);
+  var index = middle + (((i % 2) == 0) ? (i / 2) : (((1 - i) / 2) - 1));
+  return this[index];
+}
+
+Array.prototype.contains = function(obj) {
+  var i = this.length;
+  while (i--) {
+    if (this[i] === obj) {
+      return true;
+    }
+  }
+  return false;
+}
+
+Math.alignUp = function(raw, multiple) {
+  return Math.floor((raw + multiple - 1) / multiple) * multiple;
+}
diff --git a/tools/turbolizer/node.js b/tools/turbolizer/node.js
new file mode 100644
index 0000000..18ce0e7
--- /dev/null
+++ b/tools/turbolizer/node.js
@@ -0,0 +1,138 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var DEFAULT_NODE_WIDTH = 240;
+var DEFAULT_NODE_HEIGHT = 40;
+var TYPE_HEIGHT = 25;
+var DEFAULT_NODE_BUBBLE_RADIUS = 4;
+var NODE_INPUT_WIDTH = 20;
+var MINIMUM_NODE_INPUT_APPROACH = 20;
+var MINIMUM_NODE_OUTPUT_APPROACH = 15;
+
+function isNodeInitiallyVisible(node) {
+  return node.cfg;
+}
+
+var Node = {
+  isControl: function() {
+    return this.control;
+  },
+  isInput: function() {
+    return this.opcode == 'Parameter' || this.opcode.endsWith('Constant');
+  },
+  isJavaScript: function() {
+    return this.opcode.startsWith('JS');
+  },
+  isSimplified: function() {
+    if (this.isJavaScript) return false;
+    return this.opcode.endsWith('Phi') ||
+      this.opcode.startsWith('Boolean') ||
+      this.opcode.startsWith('Number') ||
+      this.opcode.startsWith('String') ||
+      this.opcode.startsWith('Change') ||
+      this.opcode.startsWith('Object') ||
+      this.opcode.startsWith('Reference') ||
+      this.opcode.startsWith('Any') ||
+      this.opcode.endsWith('ToNumber') ||
+      (this.opcode == 'AnyToBoolean') ||
+      (this.opcode.startsWith('Load') && this.opcode.length > 4) ||
+      (this.opcode.startsWith('Store') && this.opcode.length > 5);
+  },
+  isMachine: function() {
+    return !(this.isControl() || this.isInput() ||
+             this.isJavaScript() || this.isSimplified());
+  },
+  getTotalNodeWidth: function() {
+    var inputWidth = this.inputs.length * NODE_INPUT_WIDTH;
+    return Math.max(inputWidth, this.width);
+  },
+  getLabel: function() {
+    return this.label;
+  },
+  getDisplayLabel: function() {
+    var result = this.id + ":" + this.label;
+    if (result.length > 30) {
+      return this.id + ":" + this.opcode;
+    } else  {
+      return result;
+    }
+  },
+  getType: function() {
+    return this.type;
+  },
+  getDisplayType: function() {
+    var type_string = this.type;
+    if (type_string == undefined) return "";
+    if (type_string.length > 24) {
+      type_string = type_string.substr(0, 25) + "...";
+    }
+    return type_string;
+  },
+  deepestInputRank: function() {
+    var deepestRank = 0;
+    this.inputs.forEach(function(e) {
+      if (e.isVisible() && !e.isBackEdge()) {
+        if (e.source.rank > deepestRank) {
+          deepestRank = e.source.rank;
+        }
+      }
+    });
+    return deepestRank;
+  },
+  areAnyOutputsVisible: function() {
+    var visibleCount = 0;
+    this.outputs.forEach(function(e) { if (e.isVisible()) ++visibleCount; });
+    if (this.outputs.length == visibleCount) return 2;
+    if (visibleCount != 0) return 1;
+    return 0;
+  },
+  setOutputVisibility: function(v) {
+    var result = false;
+    this.outputs.forEach(function(e) {
+      e.visible = v;
+      if (v) {
+        if (!e.target.visible) {
+          e.target.visible = true;
+          result = true;
+        }
+      }
+    });
+    return result;
+  },
+  setInputVisibility: function(i, v) {
+    var edge = this.inputs[i];
+    edge.visible = v;
+    if (v) {
+      if (!edge.source.visible) {
+        edge.source.visible = true;
+        return true;
+      }
+    }
+    return false;
+  },
+  getInputApproach: function(index) {
+    return this.y - MINIMUM_NODE_INPUT_APPROACH -
+      (index % 4) * MINIMUM_EDGE_SEPARATION - DEFAULT_NODE_BUBBLE_RADIUS
+  },
+  getOutputApproach: function(graph, index) {
+    return this.y + this.outputApproach + graph.getNodeHeight() +
+      + DEFAULT_NODE_BUBBLE_RADIUS;
+  },
+  getInputX: function(index) {
+    var result = this.getTotalNodeWidth() - (NODE_INPUT_WIDTH / 2) +
+        (index - this.inputs.length + 1) * NODE_INPUT_WIDTH;
+    return result;
+  },
+  getOutputX: function() {
+    return this.getTotalNodeWidth() - (NODE_INPUT_WIDTH / 2);
+  },
+  getFunctionRelativeSourcePosition: function(graph) {
+    return this.pos - graph.sourcePosition;
+  },
+  hasBackEdges: function() {
+    return (this.opcode == "Loop") ||
+      ((this.opcode == "Phi" || this.opcode == "EffectPhi") &&
+       this.inputs[this.inputs.length - 1].source.opcode == "Loop");
+  }
+};
diff --git a/tools/turbolizer/right-arrow.png b/tools/turbolizer/right-arrow.png
new file mode 100644
index 0000000..ef39643
--- /dev/null
+++ b/tools/turbolizer/right-arrow.png
Binary files differ
diff --git a/tools/turbolizer/schedule-view.js b/tools/turbolizer/schedule-view.js
new file mode 100644
index 0000000..00ce205
--- /dev/null
+++ b/tools/turbolizer/schedule-view.js
@@ -0,0 +1,127 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+"use strict";
+
+class ScheduleView extends TextView {
+  constructor(id, broker, nodePositionMap) {
+    super(id, broker, null, false);
+    let view = this;
+    let BLOCK_STYLE = {
+      css: 'tag'
+    };
+    const BLOCK_HEADER_STYLE = {
+      css: 'com',
+      block_id: -1,
+      location: function(text) {
+        let matches = /\d+/.exec(text);
+        if (!matches) return undefined;
+        BLOCK_HEADER_STYLE.block_id = Number(matches[0]);
+        return {
+          block_id: BLOCK_HEADER_STYLE.block_id
+        };
+      },
+    };
+    const BLOCK_LINK_STYLE = {
+      css: 'tag',
+      link: function(text) {
+        let id = Number(text.substr(1));
+        view.select(function(location) { return location.block_id == id; }, true, true);
+      }
+    };
+    const ID_STYLE = {
+      css: 'tag',
+      location: function(text) {
+        let matches = /\d+/.exec(text);
+        return {
+          node_id: Number(matches[0]),
+          block_id: BLOCK_HEADER_STYLE.block_id
+        };
+      },
+    };
+    const ID_LINK_STYLE = {
+      css: 'tag',
+      link: function(text) {
+        let id = Number(text);
+        view.select(function(location) { return location.node_id == id; }, true, true);
+      }
+    };
+    const NODE_STYLE = { css: 'kwd' };
+    const GOTO_STYLE = { css: 'kwd',
+      goto_id: -2,
+      location: function(text) {
+        return {
+          node_id: GOTO_STYLE.goto_id--,
+          block_id: BLOCK_HEADER_STYLE.block_id
+        };
+      }
+    }
+    const ARROW_STYLE = { css: 'kwd' };
+    let patterns = [
+      [
+        [/^--- BLOCK B\d+/, BLOCK_HEADER_STYLE, 1],
+        [/^\s+\d+: /, ID_STYLE, 2],
+        [/^\s+Goto/, GOTO_STYLE, 6],
+        [/^.*/, null, -1]
+      ],
+      [
+        [/^ +/, null],
+        [/^\(deferred\)/, BLOCK_HEADER_STYLE],
+        [/^B\d+/, BLOCK_LINK_STYLE],
+        [/^<-/, ARROW_STYLE],
+        [/^->/, ARROW_STYLE],
+        [/^,/, null],
+        [/^---/, BLOCK_HEADER_STYLE, -1]
+      ],
+      // Parse opcode including []
+      [
+        [/^[A-Za-z0-9_]+(\[.*\])?$/, NODE_STYLE, -1],
+        [/^[A-Za-z0-9_]+(\[.*\])?/, NODE_STYLE, 3]
+      ],
+      // Parse optional parameters
+      [
+        [/^ /, null, 4],
+        [/^\(/, null],
+        [/^\d+/, ID_LINK_STYLE],
+        [/^, /, null],
+        [/^\)$/, null, -1],
+        [/^\)/, null, 4],
+      ],
+      [
+        [/^ -> /, ARROW_STYLE, 5],
+        [/^.*/, null, -1]
+      ],
+      [
+        [/^B\d+$/, BLOCK_LINK_STYLE, -1],
+        [/^B\d+/, BLOCK_LINK_STYLE],
+        [/^, /, null]
+      ],
+      [
+        [/^ -> /, ARROW_STYLE],
+        [/^B\d+$/, BLOCK_LINK_STYLE, -1]
+      ]
+    ];
+    this.setPatterns(patterns);
+    this.setNodePositionMap(nodePositionMap);
+  }
+
+  initializeContent(data, rememberedSelection) {
+    super.initializeContent(data, rememberedSelection);
+    var graph = this;
+    var locations = [];
+    for (var id of rememberedSelection) {
+      locations.push({ node_id : id });
+    }
+    this.selectLocations(locations, true, false);
+  }
+
+  detachSelection() {
+    var selection = this.selection.detachSelection();
+    var s = new Set();
+    for (var i of selection) {
+      s.add(i.location.node_id);
+    };
+    return s;
+  }
+}
diff --git a/tools/turbolizer/search.png b/tools/turbolizer/search.png
new file mode 100644
index 0000000..12dc3e3
--- /dev/null
+++ b/tools/turbolizer/search.png
Binary files differ
diff --git a/tools/turbolizer/search2.png b/tools/turbolizer/search2.png
new file mode 100644
index 0000000..88dd193
--- /dev/null
+++ b/tools/turbolizer/search2.png
Binary files differ
diff --git a/tools/turbolizer/selection-broker.js b/tools/turbolizer/selection-broker.js
new file mode 100644
index 0000000..3a223d8
--- /dev/null
+++ b/tools/turbolizer/selection-broker.js
@@ -0,0 +1,46 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var SelectionBroker = function() {
+  this.brokers = [];
+  this.dispatching = false;
+  this.lastDispatchingHandler = null;
+};
+
+SelectionBroker.prototype.addSelectionHandler = function(handler) {
+  this.brokers.push(handler);
+}
+
+SelectionBroker.prototype.select = function(from, ranges, selected) {
+  if (!this.dispatching) {
+    this.lastDispatchingHandler = from;
+    try {
+      this.dispatching = true;
+      for (var b of this.brokers) {
+        if (b != from) {
+          b.brokeredSelect(ranges, selected);
+        }
+      }
+    }
+    finally {
+      this.dispatching = false;
+    }
+  }
+}
+
+SelectionBroker.prototype.clear = function(from) {
+  this.lastDispatchingHandler = null;
+  if (!this.dispatching) {
+    try {
+      this.dispatching = true;
+      this.brokers.forEach(function(b) {
+        if (b != from) {
+          b.brokeredClear();
+        }
+      });
+    } finally {
+      this.dispatching = false;
+    }
+  }
+}
diff --git a/tools/turbolizer/selection.js b/tools/turbolizer/selection.js
new file mode 100644
index 0000000..e9c02dd
--- /dev/null
+++ b/tools/turbolizer/selection.js
@@ -0,0 +1,107 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var Selection = function(handler) {
+  this.handler = handler;
+  this.selectionBase = null;
+  this.lastSelection = null;
+  this.selection = new Set();
+}
+
+
+Selection.prototype.isEmpty = function() {
+  return this.selection.size == 0;
+}
+
+
+Selection.prototype.clear = function() {
+  var handler = this.handler;
+  this.selectionBase = null;
+  this.lastSelection = null;
+  handler.select(this.selection, false);
+  handler.clear();
+  this.selection = new Set();
+}
+
+
+count = 0;
+
+Selection.prototype.select = function(s, isSelected) {
+  var handler = this.handler;
+  if (!(Symbol.iterator in Object(s))) { s = [s]; }
+  if (isSelected) {
+    let first = true;
+    for (let i of s) {
+      if (first) {
+        this.selectionBase = i;
+        this.lastSelection = i;
+        first = false;
+      }
+      this.selection.add(i);
+    }
+  } else {
+    let unselectSet = new Set();
+    for (let i of s) {
+      if (this.selection.has(i)) {
+        unselectSet.add(i);
+        this.selection.delete(i);
+      }
+    }
+  }
+  handler.select(this.selection, isSelected);
+}
+
+
+Selection.prototype.extendTo = function(pos) {
+  if (pos == this.lastSelection || this.lastSelection === null) return;
+
+  var handler = this.handler;
+  var pos_diff = handler.selectionDifference(pos, true, this.lastSelection, false);
+  var unselect_diff = [];
+  if (pos_diff.length == 0) {
+    pos_diff = handler.selectionDifference(this.selectionBase, false, pos, true);
+    if (pos_diff.length != 0) {
+      unselect_diff = handler.selectionDifference(this.lastSelection, true, this.selectionBase, false);
+      this.selection = new Set();
+      this.selection.add(this.selectionBase);
+      for (var d of pos_diff) {
+        this.selection.add(d);
+      }
+    } else {
+      unselect_diff = handler.selectionDifference(this.lastSelection, true, pos, false);
+      for (var d of unselect_diff) {
+        this.selection.delete(d);
+      }
+    }
+  } else {
+    unselect_diff = handler.selectionDifference(this.selectionBase, false, this.lastSelection, true);
+    if (unselect_diff != 0) {
+      pos_diff = handler.selectionDifference(pos, true, this.selectionBase, false);
+      if (pos_diff.length == 0) {
+        unselect_diff = handler.selectionDifference(pos, false, this.lastSelection, true);
+      }
+      for (var d of unselect_diff) {
+        this.selection.delete(d);
+      }
+    }
+    if (pos_diff.length != 0) {
+      for (var d of pos_diff) {
+        this.selection.add(d);
+      }
+    }
+  }
+  handler.select(unselect_diff, false);
+  handler.select(pos_diff, true);
+  this.lastSelection = pos;
+}
+
+
+Selection.prototype.detachSelection = function() {
+  var result = new Set();
+  for (var i of this.selection) {
+    result.add(i);
+  }
+  this.clear();
+  return result;
+}
diff --git a/tools/turbolizer/text-view.js b/tools/turbolizer/text-view.js
new file mode 100644
index 0000000..c41c25b
--- /dev/null
+++ b/tools/turbolizer/text-view.js
@@ -0,0 +1,394 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+"use strict";
+
+class TextView extends View {
+  constructor(id, broker, patterns, allowSpanSelection) {
+    super(id, broker);
+    let view = this;
+    view.sortedPositionList = [];
+    view.nodePositionMap = [];
+    view.positionNodeMap = [];
+    view.textListNode = view.divNode.getElementsByTagName('ul')[0];
+    view.fillerSvgElement = view.divElement.append("svg").attr('version','1.1').attr("width", "0");
+    view.patterns = patterns;
+    view.allowSpanSelection = allowSpanSelection;
+    view.nodeToLineMap = [];
+    var selectionHandler = {
+      clear: function() {
+        broker.clear(selectionHandler);
+      },
+      select: function(items, selected) {
+        for (let i of items) {
+          if (selected) {
+            i.classList.add("selected");
+          } else {
+            i.classList.remove("selected");
+          }
+        }
+        broker.select(selectionHandler, view.getRanges(items), selected);
+      },
+      selectionDifference: function(span1, inclusive1, span2, inclusive2) {
+        return null;
+      },
+      brokeredSelect: function(ranges, selected) {
+        let locations = view.rangesToLocations(ranges);
+        view.selectLocations(locations, selected, true);
+      },
+      brokeredClear: function() {
+        view.selection.clear();
+      }
+    };
+    view.selection = new Selection(selectionHandler);
+    broker.addSelectionHandler(selectionHandler);
+  }
+
+  setPatterns(patterns) {
+    let view = this;
+    view.patterns = patterns;
+  }
+
+  clearText() {
+    let view = this;
+    while (view.textListNode.firstChild) {
+      view.textListNode.removeChild(view.textListNode.firstChild);
+    }
+  }
+
+  rangeToLocation(range) {
+    return range;
+  }
+
+  rangesToLocations(ranges) {
+    let view = this;
+    let nodes = new Set();
+    let result = [];
+    for (let range of ranges) {
+      let start = range[0];
+      let end = range[1];
+      let location = { pos_start: start, pos_end: end };
+      if (range[2] !== null && range[2] != -1) {
+        location.node_id = range[2];
+        if (range[0] == -1 && range[1] == -1) {
+          location.pos_start = view.nodePositionMap[location.node_id];
+          location.pos_end = location.pos_start + 1;
+        }
+      } else {
+        if (range[0] != undefined) {
+          location.pos_start = range[0];
+          location.pos_end = range[1];
+        }
+      }
+      result.push(location);
+    }
+    return result;
+  }
+
+  sameLocation(l1, l2) {
+    let view = this;
+    if (l1.block_id != undefined && l2.block_id != undefined &&
+      l1.block_id == l2.block_id && l1.node_id === undefined) {
+      return true;
+    }
+
+    if (l1.address != undefined && l1.address == l2.address) {
+      return true;
+    }
+
+    let node1 = l1.node_id;
+    let node2 = l2.node_id;
+
+    if (node1 === undefined && node2 == undefined) {
+      if (l1.pos_start === undefined || l2.pos_start == undefined) {
+        return false;
+      }
+      if (l1.pos_start == -1 || l2.pos_start == -1) {
+        return false;
+      }
+      if (l1.pos_start < l2.pos_start) {
+        return l1.pos_end > l2.pos_start;
+      } {
+        return l1.pos_start < l2.pos_end;
+      }
+    }
+
+    if (node1 === undefined) {
+      let lower = lowerBound(view.positionNodeMap, l1.pos_start, undefined, function(a, b) {
+        var node = a[b];
+        return view.nodePositionMap[node];
+      } );
+      while (++lower < view.positionNodeMap.length &&
+             view.nodePositionMap[view.positionNodeMap[lower]] < l1.pos_end) {
+        if (view.positionNodeMap[lower] == node2) {
+          return true;
+        }
+      }
+      return false;
+    }
+
+    if (node2 === undefined) {
+      let lower = lowerBound(view.positionNodeMap, l2.pos_start, undefined, function(a, b) {
+        var node = a[b];
+        return view.nodePositionMap[node];
+      } );
+      while (++lower < view.positionNodeMap.length &&
+             view.nodePositionMap[view.positionNodeMap[lower]] < l2.pos_end) {
+        if (view.positionNodeMap[lower] == node1) {
+          return true;
+        }
+      }
+      return false;
+    }
+
+    return l1.node_id == l2.node_id;
+  }
+
+  setNodePositionMap(map) {
+    let view = this;
+    view.nodePositionMap = map;
+    view.positionNodeMap = [];
+    view.sortedPositionList = [];
+    let next = 0;
+    for (let i in view.nodePositionMap) {
+      view.sortedPositionList[next] = Number(view.nodePositionMap[i]);
+      view.positionNodeMap[next++] = i;
+    }
+    view.sortedPositionList = sortUnique(view.sortedPositionList,
+                                         function(a,b) { return a - b; });
+    this.positionNodeMap.sort(function(a,b) {
+      let result = view.nodePositionMap[a] - view.nodePositionMap[b];
+      if (result != 0) return result;
+      return a - b;
+    });
+  }
+
+  selectLocations(locations, selected, makeVisible) {
+    let view = this;
+    for (let l of locations) {
+      for (let i = 0; i < view.textListNode.children.length; ++i) {
+        let child = view.textListNode.children[i];
+        if (child.location != undefined && view.sameLocation(l, child.location)) {
+          view.selectCommon(child, selected, makeVisible);
+        }
+      }
+    }
+  }
+
+  getRanges(items) {
+    let result = [];
+    let lastObject = null;
+    for (let i of items) {
+      if (i.location) {
+        let location = i.location;
+        let start = -1;
+        let end = -1;
+        let node_id = -1;
+        if (location.node_id !== undefined) {
+          node_id = location.node_id;
+        }
+        if (location.pos_start !== undefined) {
+          start = location.pos_start;
+          end = location.pos_end;
+        } else {
+          if (this.nodePositionMap && this.nodePositionMap[node_id]) {
+            start = this.nodePositionMap[node_id];
+            end = start + 1;
+          }
+        }
+        if (lastObject == null ||
+            (lastObject[2] != node_id ||
+             lastObject[0] != start ||
+             lastObject[1] != end)) {
+          lastObject = [start, end, node_id];
+          result.push(lastObject);
+        }
+      }
+    }
+    return result;
+  }
+
+  createFragment(text, style) {
+    let view = this;
+    let span = document.createElement("SPAN");
+    span.onmousedown = function(e) {
+      view.mouseDownSpan(span, e);
+    }
+    if (style != undefined) {
+      span.classList.add(style);
+    }
+    span.innerText = text;
+    return span;
+  }
+
+  appendFragment(li, fragment) {
+    li.appendChild(fragment);
+  }
+
+  processLine(line) {
+    let view = this;
+    let result = [];
+    let patternSet = 0;
+    while (true) {
+      let beforeLine = line;
+      for (let pattern of view.patterns[patternSet]) {
+        let matches = line.match(pattern[0]);
+        if (matches != null) {
+          if (matches[0] != '') {
+            let style = pattern[1] != null ? pattern[1] : {};
+            let text = matches[0];
+            if (text != '') {
+              let fragment = view.createFragment(matches[0], style.css);
+              if (style.link) {
+                fragment.classList.add('linkable-text');
+                fragment.link = style.link;
+              }
+              result.push(fragment);
+              if (style.location != undefined) {
+                let location = style.location(text);
+                if (location != undefined) {
+                  fragment.location = location;
+                }
+              }
+            }
+            line = line.substr(matches[0].length);
+          }
+          let nextPatternSet = patternSet;
+          if (pattern.length > 2) {
+            nextPatternSet = pattern[2];
+          }
+          if (line == "") {
+            if (nextPatternSet != -1) {
+              throw("illegal parsing state in text-view in patternSet" + patternSet);
+            }
+            return result;
+          }
+          patternSet = nextPatternSet;
+          break;
+        }
+      }
+      if (beforeLine == line) {
+        throw("input not consumed in text-view in patternSet" + patternSet);
+      }
+    }
+  }
+
+  select(s, selected, makeVisible) {
+    let view = this;
+    view.selection.clear();
+    view.selectCommon(s, selected, makeVisible);
+  }
+
+  selectCommon(s, selected, makeVisible) {
+    let view = this;
+    let firstSelect = makeVisible && view.selection.isEmpty();
+    if ((typeof s) === 'function') {
+      for (let i = 0; i < view.textListNode.children.length; ++i) {
+        let child = view.textListNode.children[i];
+        if (child.location && s(child.location)) {
+          if (firstSelect) {
+            makeContainerPosVisible(view.parentNode, child.offsetTop);
+            firstSelect = false;
+          }
+          view.selection.select(child, selected);
+        }
+      }
+    } else if (s.length) {
+      for (let i of s) {
+        if (firstSelect) {
+          makeContainerPosVisible(view.parentNode, i.offsetTop);
+          firstSelect = false;
+        }
+        view.selection.select(i, selected);
+      }
+    } else {
+      if (firstSelect) {
+        makeContainerPosVisible(view.parentNode, s.offsetTop);
+        firstSelect = false;
+      }
+      view.selection.select(s, selected);
+    }
+  }
+
+  mouseDownLine(li, e) {
+    let view = this;
+    e.stopPropagation();
+    if (!e.shiftKey) {
+      view.selection.clear();
+    }
+    if (li.location != undefined) {
+      view.selectLocations([li.location], true, false);
+    }
+  }
+
+  mouseDownSpan(span, e) {
+    let view = this;
+    if (view.allowSpanSelection) {
+      e.stopPropagation();
+      if (!e.shiftKey) {
+        view.selection.clear();
+      }
+      select(li, true);
+    } else if (span.link) {
+      span.link(span.textContent);
+      e.stopPropagation();
+    }
+  }
+
+  processText(text) {
+    let view = this;
+    let textLines = text.split(/[\n]/);
+    let lineNo = 0;
+    for (let line of textLines) {
+      let li = document.createElement("LI");
+      li.onmousedown = function(e) {
+        view.mouseDownLine(li, e);
+      }
+      li.className = "nolinenums";
+      li.lineNo = lineNo++;
+      let fragments = view.processLine(line);
+      for (let fragment of fragments) {
+        view.appendFragment(li, fragment);
+      }
+      let lineLocation = view.lineLocation(li);
+      if (lineLocation != undefined) {
+        li.location = lineLocation;
+      }
+      view.textListNode.appendChild(li);
+    }
+  }
+
+  initializeContent(data, rememberedSelection) {
+    let view = this;
+    view.clearText();
+    view.processText(data);
+    var fillerSize = document.documentElement.clientHeight -
+        view.textListNode.clientHeight;
+    if (fillerSize < 0) {
+      fillerSize = 0;
+    }
+    view.fillerSvgElement.attr("height", fillerSize);
+  }
+
+  deleteContent() {
+  }
+
+  isScrollable() {
+    return true;
+  }
+
+  detachSelection() {
+    return null;
+  }
+
+  lineLocation(li) {
+    let view = this;
+    for (let i = 0; i < li.children.length; ++i) {
+      let fragment = li.children[i];
+      if (fragment.location != undefined && !view.allowSpanSelection) {
+        return fragment.location;
+      }
+    }
+  }
+}
diff --git a/tools/turbolizer/turbo-visualizer.css b/tools/turbolizer/turbo-visualizer.css
new file mode 100644
index 0000000..3c5c9d6
--- /dev/null
+++ b/tools/turbolizer/turbo-visualizer.css
@@ -0,0 +1,327 @@
+.visible-transition {
+    transition-delay: 0s;
+    transition-duration: 1s;
+    transition-property: all;
+    transition-timing-function: ease;
+}
+
+.collapse-pane {
+    background: #A0A0A0;
+    bottom: 0;
+    position: absolute;
+    margin-bottom: 0.5em;
+    margin-right: 0.5em;
+    margin-left: 0.5em;
+    border-radius: 5px;
+    padding: 0.5em;
+    z-index: 5;
+    opacity: 0.7;
+    cursor: pointer;
+}
+
+.search-input {
+    vertical-align: middle;
+    width: 145px;
+    opacity: 1;
+}
+
+.button-input {
+    vertical-align: middle;
+    width: 24px;
+    opacity: 0.4;
+    cursor: pointer;
+}
+
+.button-input-toggled {
+    border-radius: 5px;
+    background-color: #505050;
+}
+
+.button-input:focus {
+    outline: none;
+}
+
+.button-input-invisible {
+    vertical-align: middle;
+    width: 0px;
+    visibility: hidden;
+}
+
+
+.selected {
+    background-color: #FFFF33;
+}
+
+.prettyprint ol.linenums > li {
+    list-style-type: decimal;
+    !important
+}
+
+body {
+    margin: 0;
+    padding: 0;
+    overflow:hidden;
+    -webkit-touch-callout: none;
+    -webkit-user-select: none;
+    -khtml-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+}
+
+p { 
+    text-align: center; 
+    overflow: overlay;
+    position: relative;
+}
+
+marker {
+    fill: #080808;
+}
+
+g rect {
+    fill: #F0F0F0;
+    stroke: #080808;
+    stroke-width: 2px;
+}
+
+g.unsorted rect {
+    opacity: 0.5;
+}
+
+div.scrollable {
+    overflow-y: _croll; overflow-x: hidden;
+}
+
+g.control rect { 
+    fill: #EFCC00;
+    stroke: #080808;
+    stroke-width: 5px;
+}
+
+g.javascript rect { 
+    fill: #DD7E6B;
+}
+
+g.simplified rect { 
+    fill: #3C78D8;
+}
+
+g.machine rect { 
+    fill: #6AA84F;
+}
+
+g.input rect {
+    fill: #CFE2F3;
+}
+
+g.selected rect {
+    fill: #FFFF33;
+}
+
+circle.bubbleStyle {
+    fill: #080808;
+    fill-opacity: 0.0;
+    stroke: #080808;
+    stroke-width: 2px;
+}
+
+circle.bubbleStyle:hover {
+    stroke-width: 3px;
+}
+
+circle.filledBubbleStyle {
+    fill: #080808;
+    stroke: #080808;
+    stroke-width: 2px;
+}
+
+circle.filledBubbleStyle:hover {
+    fill: #080808;
+    stroke-width: 3px;
+}
+
+circle.halfFilledBubbleStyle {
+    fill: #808080;
+    stroke: #101010;
+    stroke-width: 2px;
+}
+
+circle.halfFilledBubbleStyle:hover {
+    fill: #808080;
+    stroke-width: 3px;
+}
+
+path.effect {
+    fill: none;
+    stroke: #080808;
+    stroke-width: 4px;
+    cursor: default;
+}
+
+path.effect:hover {
+    stroke-width: 6px;
+}
+
+path.control {
+    fill: none;
+    stroke: #080808;
+    stroke-width: 4px;
+    cursor: default;
+}
+
+path.control:hover {
+    stroke-width: 6px;
+}
+
+path.value {
+    fill: none;
+    stroke: #888888;
+    stroke-width: 4px;
+    cursor: default;
+}
+
+path.value:hover {
+    stroke-width: 6px;
+}
+
+path.frame-state {
+    fill: none;
+    stroke: #080808;
+    stroke-width: 4px;
+    cursor: default;
+}
+
+path.frame-state:hover{
+    stroke-width: 6px;
+}
+
+path.hidden {
+    fill: none;
+    stroke-width: 0;
+}
+
+path.link.selected {
+    stroke: #FFFF33;
+}
+
+pre.prettyprint {
+  border: none !important;
+  padding: 0px;
+}
+
+li.L1,
+li.L3,
+li.L5,
+li.L7,
+li.L9 {
+    background: none !important
+}
+
+li.nolinenums {
+  list-style-type:none;
+}
+
+ul.noindent {
+  -webkit-padding-start: 0px;
+  -webkit-margin-before: 0px;
+  -webkit-margin-after: 0px;
+}
+
+input:hover, .collapse-pane:hover input {
+    opacity: 1;
+    cursor: pointer;
+}
+
+span.linkable-text {
+    text-decoration: underline;
+}
+
+span.linkable-text:hover {
+    cursor: pointer;
+    font-weight: bold;
+}
+
+#left {
+    float: left; height: 100%; background-color: #FFFFFF;
+    -webkit-transition: all 1s ease-in-out;
+    -moz-transition: all 1s ease-in-out;
+    -o-transition: all 1s ease-in-out;
+    transition: all 1s ease-in-out;
+    transition-property: width;
+    transition-duration: 1s, 1s;
+}
+
+#middle {
+    float:left; height: 100%; background-color: #F8F8F8; 
+    -webkit-transition: all 1s ease-in-out;
+    -moz-transition: all 1s ease-in-out;
+    -o-transition: all 1s ease-in-out;
+    transition: all 1s ease-in-out;
+    transition-property: width;
+    transition-duration: 1s, 1s;
+}
+
+#right {
+    float: right; background-color: #FFFFFF; 
+    -webkit-transition: all 1s ease-in-out;
+    -moz-transition: all 1s ease-in-out;
+    -o-transition: all 1s ease-in-out;
+    transition: all 1s ease-in-out;
+    transition-property: width;
+    transition-duration: 1s, 1s;
+}
+
+#disassembly-collapse {
+    right: 0;
+}
+
+#source-collapse {
+    left: 0;
+}
+
+#graph-toolbox {
+    position: relative;
+    top: 1em;
+    left: 0.7em;
+    border: 2px solid #eee8d5;
+    border-radius: 5px;
+    padding: 0.7em;
+    z-index: 5;
+}
+
+#disassembly-collapse {
+    right: 0;
+}
+
+#source-collapse {
+    left: 0;
+}
+
+#graph-toolbox {
+    position: relative;
+    top: 1em;
+    left: 0.7em;
+    border: 2px solid #eee8d5;
+    border-radius: 5px;
+    padding: 0.7em;
+    z-index: 5;
+}
+
+#load-file {
+    background: #A0A0A0;
+    position: absolute;
+    top: 0;
+    right: 0;
+    margin-top: 0.5em;
+    margin-right: 0.5em;
+    border-radius: 5px;
+    padding: 0.5em;
+    z-index: 5;
+    opacity: 0.7;
+}
+
+#hidden-file-upload{
+    display: none;
+}
+
diff --git a/tools/turbolizer/turbo-visualizer.js b/tools/turbolizer/turbo-visualizer.js
new file mode 100644
index 0000000..d85be6b
--- /dev/null
+++ b/tools/turbolizer/turbo-visualizer.js
@@ -0,0 +1,211 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+document.onload = (function(d3){
+  "use strict";
+  var jsonObj;
+  var sourceExpandClassList = document.getElementById(SOURCE_EXPAND_ID).classList;
+  var sourceCollapseClassList = document.getElementById(SOURCE_COLLAPSE_ID).classList;
+  var sourceExpanded = sourceCollapseClassList.contains(COLLAPSE_PANE_BUTTON_VISIBLE);
+  var disassemblyExpandClassList = document.getElementById(DISASSEMBLY_EXPAND_ID).classList;
+  var disassemblyCollapseClassList = document.getElementById(DISASSEMBLY_COLLAPSE_ID).classList;
+  var disassemblyExpanded = disassemblyCollapseClassList.contains(COLLAPSE_PANE_BUTTON_VISIBLE);
+  var svg  = null;
+  var graph = null;
+  var schedule = null;
+  var empty = null;
+  var currentPhaseView = null;
+  var disassemblyView = null;
+  var sourceView = null;
+  var selectionBroker = null;
+
+  function updatePanes() {
+    if (sourceExpanded) {
+      if (disassemblyExpanded) {
+        d3.select("#" + SOURCE_PANE_ID).style(WIDTH, "30%");
+        d3.select("#" + INTERMEDIATE_PANE_ID).style(WIDTH, "40%");
+        d3.select("#" + GENERATED_PANE_ID).style(WIDTH, "30%");
+      } else {
+        d3.select("#" + SOURCE_PANE_ID).style(WIDTH, "50%");
+        d3.select("#" + INTERMEDIATE_PANE_ID).style(WIDTH, "50%");
+        d3.select("#" + GENERATED_PANE_ID).style(WIDTH, "0%");
+      }
+    } else {
+      if (disassemblyExpanded) {
+        d3.select("#" + SOURCE_PANE_ID).style(WIDTH, "0%");
+        d3.select("#" + INTERMEDIATE_PANE_ID).style(WIDTH, "50%");
+        d3.select("#" + GENERATED_PANE_ID).style(WIDTH, "50%");
+      } else {
+        d3.select("#" + SOURCE_PANE_ID).style(WIDTH, "0%");
+        d3.select("#" + INTERMEDIATE_PANE_ID).style(WIDTH, "100%");
+        d3.select("#" + GENERATED_PANE_ID).style(WIDTH, "0%");
+      }
+    }
+  }
+
+  function toggleSourceExpanded() {
+    setSourceExpanded(!sourceExpanded);
+  }
+
+  function setSourceExpanded(newState) {
+    sourceExpanded = newState;
+    updatePanes();
+    if (newState) {
+      sourceCollapseClassList.add(COLLAPSE_PANE_BUTTON_VISIBLE);
+      sourceCollapseClassList.remove(COLLAPSE_PANE_BUTTON_INVISIBLE);
+      sourceExpandClassList.add(COLLAPSE_PANE_BUTTON_INVISIBLE);
+      sourceExpandClassList.remove(COLLAPSE_PANE_BUTTON_VISIBLE);
+    } else {
+      sourceCollapseClassList.add(COLLAPSE_PANE_BUTTON_INVISIBLE);
+      sourceCollapseClassList.remove(COLLAPSE_PANE_BUTTON_VISIBLE);
+      sourceExpandClassList.add(COLLAPSE_PANE_BUTTON_VISIBLE);
+      sourceExpandClassList.remove(COLLAPSE_PANE_BUTTON_INVISIBLE);
+    }
+  }
+
+  function toggleDisassemblyExpanded() {
+    setDisassemblyExpanded(!disassemblyExpanded);
+  }
+
+  function setDisassemblyExpanded(newState) {
+    disassemblyExpanded = newState;
+    updatePanes();
+    if (newState) {
+      disassemblyCollapseClassList.add(COLLAPSE_PANE_BUTTON_VISIBLE);
+      disassemblyCollapseClassList.remove(COLLAPSE_PANE_BUTTON_INVISIBLE);
+      disassemblyExpandClassList.add(COLLAPSE_PANE_BUTTON_INVISIBLE);
+      disassemblyExpandClassList.remove(COLLAPSE_PANE_BUTTON_VISIBLE);
+    } else {
+      disassemblyCollapseClassList.add(COLLAPSE_PANE_BUTTON_INVISIBLE);
+      disassemblyCollapseClassList.remove(COLLAPSE_PANE_BUTTON_VISIBLE);
+      disassemblyExpandClassList.add(COLLAPSE_PANE_BUTTON_VISIBLE);
+      disassemblyExpandClassList.remove(COLLAPSE_PANE_BUTTON_INVISIBLE);
+    }
+  }
+
+  function hideCurrentPhase() {
+    var rememberedSelection = null;
+    if (currentPhaseView != null) {
+      rememberedSelection = currentPhaseView.detachSelection();
+      currentPhaseView.hide();
+      currentPhaseView = null;
+    }
+    return rememberedSelection;
+  }
+
+  function displayPhaseView(view, data) {
+    var rememberedSelection = hideCurrentPhase();
+    view.show(data, rememberedSelection);
+    d3.select("#middle").classed("scrollable", view.isScrollable());
+    currentPhaseView = view;
+  }
+
+  function displayPhase(phase) {
+    if (phase.type == 'graph') {
+      displayPhaseView(graph, phase.data);
+    } else if (phase.type == 'schedule') {
+      displayPhaseView(schedule, phase.data);
+    } else {
+      displayPhaseView(empty, null);
+    }
+  }
+
+  function fitPanesToParents() {
+    d3.select("#left").classed("scrollable", false)
+    d3.select("#right").classed("scrollable", false);
+
+    graph.fitGraphViewToWindow();
+    disassemblyView.resizeToParent();
+    sourceView.resizeToParent();
+
+    d3.select("#left").classed("scrollable", true);
+    d3.select("#right").classed("scrollable", true);
+  }
+
+  selectionBroker = new SelectionBroker();
+
+  function initializeHandlers(g) {
+    d3.select("#source-collapse").on("click", function(){
+      toggleSourceExpanded(true);
+      setTimeout(function(){
+        g.fitGraphViewToWindow();
+      }, 1000);
+    });
+    d3.select("#disassembly-collapse").on("click", function(){
+      toggleDisassemblyExpanded();
+      setTimeout(function(){
+        g.fitGraphViewToWindow();
+      }, 1000);
+    });
+    window.onresize = function(){
+      fitPanesToParents();
+    };
+    d3.select("#hidden-file-upload").on("change", function() {
+      if (window.File && window.FileReader && window.FileList) {
+        var uploadFile = this.files[0];
+        var filereader = new window.FileReader();
+        var consts = Node.consts;
+        filereader.onload = function(){
+          var txtRes = filereader.result;
+          // If the JSON isn't properly terminated, assume compiler crashed and
+          // add best-guess empty termination
+          if (txtRes[txtRes.length-2] == ',') {
+            txtRes += '{"name":"disassembly","type":"disassembly","data":""}]}';
+          }
+          try{
+            jsonObj = JSON.parse(txtRes);
+
+            sourceView.initializeCode(jsonObj.source, jsonObj.sourcePosition);
+            schedule.setNodePositionMap(jsonObj.nodePositions);
+
+            var selectMenu = document.getElementById('display-selector');
+            var disassemblyPhase = null;
+            selectMenu.innerHTML = '';
+            for (var i = 0; i < jsonObj.phases.length; ++i) {
+              var optionElement = document.createElement("option");
+              optionElement.text = jsonObj.phases[i].name;
+              if (optionElement.text == 'disassembly') {
+                disassemblyPhase = jsonObj.phases[i];
+              } else {
+                selectMenu.add(optionElement, null);
+              }
+            }
+            disassemblyView.setNodePositionMap(jsonObj.nodePositions);
+            disassemblyView.show(disassemblyPhase.data, null);
+
+            displayPhase(jsonObj.phases[0]);
+
+            selectMenu.onchange = function(item) {
+              displayPhase(jsonObj.phases[selectMenu.selectedIndex]);
+            }
+
+            fitPanesToParents();
+          }
+          catch(err) {
+            window.alert("Invalid TurboFan JSON file\n" +
+                         "error: " + err.message);
+            return;
+          }
+        };
+        filereader.readAsText(uploadFile);
+      } else {
+        alert("Can't load graph");
+      }
+    });
+  }
+
+  sourceView = new CodeView(SOURCE_PANE_ID, PR, "", 0, selectionBroker);
+  disassemblyView = new DisassemblyView(DISASSEMBLY_PANE_ID, selectionBroker);
+  graph = new GraphView(d3, GRAPH_PANE_ID, [], [], selectionBroker);
+  schedule = new ScheduleView(SCHEDULE_PANE_ID, selectionBroker);
+  empty = new EmptyView(EMPTY_PANE_ID, selectionBroker);
+
+  initializeHandlers(graph);
+
+  setSourceExpanded(true);
+  setDisassemblyExpanded(false);
+
+  displayPhaseView(empty, null);
+  fitPanesToParents();
+})(window.d3);
diff --git a/tools/turbolizer/types.png b/tools/turbolizer/types.png
new file mode 100644
index 0000000..8fead8f
--- /dev/null
+++ b/tools/turbolizer/types.png
Binary files differ
diff --git a/tools/turbolizer/upload-icon.png b/tools/turbolizer/upload-icon.png
new file mode 100644
index 0000000..c1a289b
--- /dev/null
+++ b/tools/turbolizer/upload-icon.png
Binary files differ
diff --git a/tools/turbolizer/util.js b/tools/turbolizer/util.js
new file mode 100644
index 0000000..09a7473
--- /dev/null
+++ b/tools/turbolizer/util.js
@@ -0,0 +1,71 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+"use strict";
+
+function makeContainerPosVisible(container, pos) {
+  var height = container.offsetHeight;
+  var margin = Math.floor(height / 4);
+  if (pos < container.scrollTop + margin) {
+    pos -= margin;
+    if (pos < 0) pos = 0;
+    container.scrollTop = pos;
+    return;
+  }
+  if (pos > (container.scrollTop + 3 * margin)) {
+    pos = pos - 3 * margin;
+    if (pos < 0) pos = 0;
+    container.scrollTop = pos;
+  }
+}
+
+
+function lowerBound(a, value, compare, lookup) {
+  let first = 0;
+  let count = a.length;
+  while (count > 0) {
+    let step = Math.floor(count / 2);
+    let middle = first + step;
+    let middle_value = (lookup === undefined) ? a[middle] : lookup(a, middle);
+    let result = (compare === undefined) ? (middle_value < value) : compare(middle_value, value);
+    if (result) {
+      first = middle + 1;
+      count -= step + 1;
+    } else {
+      count = step;
+    }
+  }
+  return first;
+}
+
+
+function upperBound(a, value, compare, lookup) {
+  let first = 0;
+  let count = a.length;
+  while (count > 0) {
+    let step = Math.floor(count / 2);
+    let middle = first + step;
+    let middle_value = (lookup === undefined) ? a[middle] : lookup(a, middle);
+    let result = (compare === undefined) ? (value < middle_value) : compare(value, middle_value);
+    if (!result) {
+      first = middle + 1;
+      count -= step + 1;
+    } else {
+      count = step;
+    }
+  }
+  return first;
+}
+
+
+function sortUnique(arr, f) {
+  arr = arr.sort(f);
+  let ret = [arr[0]];
+  for (var i = 1; i < arr.length; i++) {
+    if (arr[i-1] !== arr[i]) {
+      ret.push(arr[i]);
+    }
+  }
+  return ret;
+}
diff --git a/tools/turbolizer/view.js b/tools/turbolizer/view.js
new file mode 100644
index 0000000..2c90c6d
--- /dev/null
+++ b/tools/turbolizer/view.js
@@ -0,0 +1,42 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+"use strict";
+
+class View {
+  constructor(id, broker) {
+    this.divElement = d3.select("#" + id);
+    this.divNode = this.divElement[0][0];
+    this.parentNode = this.divNode.parentNode;
+    this.hide();
+  }
+
+  isScrollable() {
+    return false;
+  }
+
+  show(data, rememberedSelection) {
+    this.parentNode.appendChild(this.divElement[0][0]);
+    this.initializeContent(data, rememberedSelection);
+    this.resizeToParent();
+    this.divElement.attr(VISIBILITY, 'visible');
+  }
+
+  resizeToParent() {
+    var view = this;
+    var documentElement = document.documentElement;
+    var y = this.parentNode.clientHeight || documentElement.clientHeight;
+    this.parentNode.style.height = y + 'px';
+  }
+
+  hide() {
+    this.divElement.attr(VISIBILITY, 'hidden');
+    this.deleteContent();
+    this.parentNode.removeChild(this.divNode);
+  }
+
+  detachSelection() {
+    return null;
+  }
+}
diff --git a/tools/verify_source_deps.py b/tools/verify_source_deps.py
index 50caace..56e3156 100755
--- a/tools/verify_source_deps.py
+++ b/tools/verify_source_deps.py
@@ -24,10 +24,10 @@
 
 GYP_FILES = [
   os.path.join(V8_BASE, 'src', 'd8.gyp'),
+  os.path.join(V8_BASE, 'src', 'v8.gyp'),
   os.path.join(V8_BASE, 'src', 'third_party', 'vtune', 'v8vtune.gyp'),
   os.path.join(V8_BASE, 'test', 'cctest', 'cctest.gyp'),
   os.path.join(V8_BASE, 'test', 'unittests', 'unittests.gyp'),
-  os.path.join(V8_BASE, 'tools', 'gyp', 'v8.gyp'),
   os.path.join(V8_BASE, 'tools', 'parser-shell.gyp'),
 ]
 
diff --git a/tools/whitespace.txt b/tools/whitespace.txt
index d1395f5..687be11 100644
--- a/tools/whitespace.txt
+++ b/tools/whitespace.txt
@@ -5,4 +5,4 @@
 A Smi balks into a war and says:
 "I'm so deoptimized today!"
 The doubles heard this and started to unbox.
-The Smi looked at them when a crazy v8-autoroll account showed up..
+The Smi looked at them when a crazy v8-autoroll account showed up.....